From 3c0e092ef82e17e1077c9a372b7034d9f3239eeb Mon Sep 17 00:00:00 2001 From: Ximin Luo Date: Tue, 8 Mar 2022 11:28:32 +0000 Subject: [PATCH] New upstream version 1.58.1+dfsg1 --- CONTRIBUTING.md | 11 +- Cargo.lock | 216 +- Cargo.toml | 7 + README.md | 5 +- RELEASES.md | 191 + compiler/rustc_apfloat/src/ieee.rs | 2 - compiler/rustc_arena/src/lib.rs | 166 +- compiler/rustc_ast/README.md | 3 +- compiler/rustc_ast/src/ast.rs | 87 +- compiler/rustc_ast/src/attr/mod.rs | 6 +- compiler/rustc_ast/src/lib.rs | 4 +- compiler/rustc_ast/src/mut_visit.rs | 116 +- compiler/rustc_ast/src/tokenstream.rs | 6 - compiler/rustc_ast/src/util/comments.rs | 4 +- compiler/rustc_ast/src/util/parser.rs | 12 +- compiler/rustc_ast/src/util/unicode.rs | 35 + compiler/rustc_ast/src/visit.rs | 28 +- compiler/rustc_ast_lowering/Cargo.toml | 1 + compiler/rustc_ast_lowering/src/asm.rs | 105 +- compiler/rustc_ast_lowering/src/expr.rs | 163 +- .../src/index.rs} | 207 +- compiler/rustc_ast_lowering/src/item.rs | 72 +- compiler/rustc_ast_lowering/src/lib.rs | 218 +- .../rustc_ast_passes/src/ast_validation.rs | 50 +- compiler/rustc_ast_passes/src/feature_gate.rs | 46 +- compiler/rustc_ast_pretty/src/pprust/state.rs | 86 +- compiler/rustc_borrowck/src/borrow_set.rs | 30 +- .../src/diagnostics/bound_region_errors.rs | 2 +- .../src/diagnostics/conflict_errors.rs | 62 +- .../src/diagnostics/explain_borrow.rs | 18 +- .../rustc_borrowck/src/diagnostics/mod.rs | 12 +- .../src/diagnostics/move_errors.rs | 21 +- .../src/diagnostics/mutability_errors.rs | 44 +- .../src/diagnostics/outlives_suggestion.rs | 4 +- compiler/rustc_borrowck/src/lib.rs | 6 +- compiler/rustc_borrowck/src/nll.rs | 2 +- .../rustc_borrowck/src/region_infer/mod.rs | 28 +- .../rustc_borrowck/src/region_infer/values.rs | 28 +- .../src/type_check/canonical.rs | 1 + .../src/type_check/free_region_relations.rs | 22 +- .../src/type_check/input_output.rs | 60 +- .../src/type_check/liveness/trace.rs | 40 +- compiler/rustc_borrowck/src/type_check/mod.rs | 134 +- .../rustc_borrowck/src/universal_regions.rs | 95 +- compiler/rustc_builtin_macros/src/asm.rs | 96 +- compiler/rustc_builtin_macros/src/derive.rs | 2 +- .../src/deriving/generic/mod.rs | 28 +- .../rustc_builtin_macros/src/deriving/mod.rs | 6 +- compiler/rustc_builtin_macros/src/format.rs | 67 +- .../src/global_allocator.rs | 14 +- .../src/standard_library_imports.rs | 2 +- compiler/rustc_builtin_macros/src/test.rs | 4 +- .../rustc_builtin_macros/src/test_harness.rs | 12 +- .../rustc_codegen_cranelift/src/driver/aot.rs | 2 +- compiler/rustc_codegen_gcc/src/abi.rs | 2 +- compiler/rustc_codegen_gcc/src/asm.rs | 2 +- compiler/rustc_codegen_gcc/src/base.rs | 8 +- compiler/rustc_codegen_gcc/src/builder.rs | 10 + .../rustc_codegen_gcc/src/intrinsic/mod.rs | 7 +- compiler/rustc_codegen_llvm/Cargo.toml | 2 +- compiler/rustc_codegen_llvm/src/abi.rs | 16 +- compiler/rustc_codegen_llvm/src/asm.rs | 10 +- compiler/rustc_codegen_llvm/src/attributes.rs | 14 +- compiler/rustc_codegen_llvm/src/back/write.rs | 50 +- compiler/rustc_codegen_llvm/src/base.rs | 9 +- compiler/rustc_codegen_llvm/src/builder.rs | 34 +- compiler/rustc_codegen_llvm/src/consts.rs | 2 +- compiler/rustc_codegen_llvm/src/context.rs | 15 +- .../rustc_codegen_llvm/src/debuginfo/mod.rs | 2 +- compiler/rustc_codegen_llvm/src/intrinsic.rs | 114 +- compiler/rustc_codegen_llvm/src/lib.rs | 74 + compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 11 +- compiler/rustc_codegen_llvm/src/llvm_util.rs | 41 +- compiler/rustc_codegen_ssa/src/back/link.rs | 36 +- compiler/rustc_codegen_ssa/src/back/linker.rs | 92 +- .../src/back/symbol_export.rs | 4 +- compiler/rustc_codegen_ssa/src/back/write.rs | 104 +- .../src/debuginfo/type_names.rs | 5 +- compiler/rustc_codegen_ssa/src/lib.rs | 5 +- compiler/rustc_codegen_ssa/src/mir/block.rs | 53 +- compiler/rustc_codegen_ssa/src/mir/mod.rs | 8 + compiler/rustc_codegen_ssa/src/mir/operand.rs | 4 +- .../rustc_codegen_ssa/src/mir/statement.rs | 2 +- .../rustc_codegen_ssa/src/target_features.rs | 29 +- compiler/rustc_codegen_ssa/src/traits/abi.rs | 2 +- compiler/rustc_codegen_ssa/src/traits/asm.rs | 1 + .../rustc_codegen_ssa/src/traits/backend.rs | 26 +- .../rustc_codegen_ssa/src/traits/builder.rs | 2 + .../rustc_codegen_ssa/src/traits/intrinsic.rs | 6 +- .../rustc_const_eval/src/const_eval/error.rs | 5 +- .../src/const_eval/eval_queries.rs | 1 + .../src/const_eval/fn_queries.rs | 9 +- .../src/const_eval/machine.rs | 60 +- .../src/interpret/intrinsics.rs | 47 +- .../interpret/intrinsics/caller_location.rs | 15 +- .../src/interpret/intrinsics/type_name.rs | 6 +- .../rustc_const_eval/src/interpret/machine.rs | 9 + .../rustc_const_eval/src/interpret/memory.rs | 13 +- .../rustc_const_eval/src/interpret/operand.rs | 12 + .../src/interpret/operator.rs | 7 +- .../rustc_const_eval/src/interpret/place.rs | 28 +- .../src/interpret/terminator.rs | 6 +- .../src/interpret/validity.rs | 8 +- compiler/rustc_const_eval/src/lib.rs | 1 + .../src/transform/check_consts/check.rs | 137 +- .../src/transform/check_consts/mod.rs | 19 - .../src/transform/check_consts/ops.rs | 10 +- .../check_consts/post_drop_elaboration.rs | 2 +- .../src/transform/check_consts/qualifs.rs | 63 +- .../src/transform/check_consts/resolver.rs | 220 +- .../src/transform/promote_consts.rs | 205 +- compiler/rustc_data_structures/Cargo.toml | 2 +- compiler/rustc_data_structures/src/base_n.rs | 2 +- .../src/graph/implementation/mod.rs | 10 +- .../src/graph/iterate/mod.rs | 4 +- compiler/rustc_data_structures/src/lib.rs | 1 - .../src/obligation_forest/mod.rs | 12 +- .../rustc_data_structures/src/profiling.rs | 43 +- .../rustc_data_structures/src/sorted_map.rs | 35 +- .../src/sorted_map/index_map.rs | 14 +- compiler/rustc_data_structures/src/sso/map.rs | 16 +- compiler/rustc_data_structures/src/sso/set.rs | 2 +- .../src/stable_hasher.rs | 11 +- compiler/rustc_data_structures/src/stack.rs | 1 - .../rustc_data_structures/src/tiny_list.rs | 2 +- .../src/vec_linked_list.rs | 4 +- compiler/rustc_driver/src/lib.rs | 12 +- compiler/rustc_driver/src/pretty.rs | 30 +- compiler/rustc_error_codes/src/error_codes.rs | 40 +- .../src/error_codes/E0206.md | 9 +- .../src/error_codes/E0482.md | 6 +- .../src/error_codes/E0637.md | 36 +- .../src/error_codes/E0786.md | 14 + .../src/annotate_snippet_emitter_writer.rs | 2 +- compiler/rustc_errors/src/diagnostic.rs | 12 +- compiler/rustc_errors/src/emitter.rs | 55 +- compiler/rustc_errors/src/lib.rs | 51 +- compiler/rustc_expand/src/expand.rs | 10 +- compiler/rustc_expand/src/lib.rs | 3 +- compiler/rustc_expand/src/mbe/quoted.rs | 2 +- compiler/rustc_expand/src/mbe/transcribe.rs | 14 +- compiler/rustc_expand/src/mut_visit/tests.rs | 5 +- compiler/rustc_expand/src/placeholders.rs | 2 +- compiler/rustc_expand/src/proc_macro.rs | 28 +- .../rustc_expand/src/proc_macro_server.rs | 164 +- compiler/rustc_feature/src/accepted.rs | 440 +- compiler/rustc_feature/src/active.rs | 817 +- compiler/rustc_feature/src/builtin_attrs.rs | 490 +- compiler/rustc_feature/src/lib.rs | 2 + compiler/rustc_feature/src/removed.rs | 196 +- compiler/rustc_graphviz/src/lib.rs | 2 +- compiler/rustc_hir/src/arena.rs | 81 +- compiler/rustc_hir/src/def.rs | 7 +- compiler/rustc_hir/src/hir.rs | 169 +- compiler/rustc_hir/src/hir_id.rs | 72 +- compiler/rustc_hir/src/intravisit.rs | 30 + compiler/rustc_hir/src/lang_items.rs | 6 +- compiler/rustc_hir/src/lib.rs | 2 + compiler/rustc_hir/src/pat_util.rs | 11 + compiler/rustc_hir/src/stable_hash_impls.rs | 37 +- compiler/rustc_hir_pretty/src/lib.rs | 19 +- .../rustc_incremental/src/assert_dep_graph.rs | 40 +- compiler/rustc_incremental/src/lib.rs | 1 + .../src/persist/dirty_clean.rs | 21 +- .../src/persist/file_format.rs | 6 + compiler/rustc_incremental/src/persist/fs.rs | 16 +- .../rustc_incremental/src/persist/load.rs | 26 +- compiler/rustc_index/src/bit_set.rs | 149 +- compiler/rustc_index/src/bit_set/tests.rs | 95 + compiler/rustc_index/src/lib.rs | 2 + compiler/rustc_index/src/vec.rs | 41 +- .../src/infer/canonical/query_response.rs | 4 +- compiler/rustc_infer/src/infer/combine.rs | 29 +- .../src/infer/error_reporting/mod.rs | 149 +- .../infer/error_reporting/need_type_info.rs | 24 +- .../nice_region_error/different_lifetimes.rs | 94 +- .../nice_region_error/named_anon_conflict.rs | 65 +- .../nice_region_error/static_impl_trait.rs | 10 +- .../trait_impl_difference.rs | 67 +- .../error_reporting/nice_region_error/util.rs | 5 +- .../src/infer/error_reporting/note.rs | 59 +- .../rustc_infer/src/infer/free_regions.rs | 23 - .../src/infer/lexical_region_resolve/mod.rs | 156 +- compiler/rustc_infer/src/infer/mod.rs | 56 +- .../rustc_infer/src/infer/opaque_types.rs | 592 +- .../rustc_infer/src/infer/outlives/env.rs | 8 +- compiler/rustc_infer/src/lib.rs | 2 + compiler/rustc_infer/src/traits/engine.rs | 15 +- .../src/traits/error_reporting/mod.rs | 5 +- compiler/rustc_infer/src/traits/mod.rs | 20 +- .../src/traits/structural_impls.rs | 3 +- compiler/rustc_infer/src/traits/util.rs | 17 + compiler/rustc_interface/src/interface.rs | 25 +- compiler/rustc_interface/src/passes.rs | 37 +- compiler/rustc_interface/src/tests.rs | 25 +- compiler/rustc_interface/src/util.rs | 7 +- compiler/rustc_lexer/Cargo.toml | 1 + compiler/rustc_lexer/src/lib.rs | 24 + compiler/rustc_lexer/src/unescape.rs | 2 +- compiler/rustc_lint/src/array_into_iter.rs | 3 +- compiler/rustc_lint/src/builtin.rs | 56 +- compiler/rustc_lint/src/context.rs | 4 +- .../src/hidden_unicode_codepoints.rs | 12 +- compiler/rustc_lint/src/internal.rs | 102 +- compiler/rustc_lint/src/lib.rs | 2 +- compiler/rustc_lint/src/unused.rs | 2 +- compiler/rustc_lint_defs/src/builtin.rs | 4 +- compiler/rustc_llvm/build.rs | 4 +- .../llvm-wrapper/CoverageMappingWrapper.cpp | 7 - .../rustc_llvm/llvm-wrapper/LLVMWrapper.h | 4 +- .../rustc_llvm/llvm-wrapper/PassWrapper.cpp | 196 +- .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 56 +- compiler/rustc_llvm/src/lib.rs | 2 +- compiler/rustc_macros/src/query.rs | 83 +- compiler/rustc_macros/src/serialize.rs | 25 +- .../rustc_macros/src/session_diagnostic.rs | 8 +- compiler/rustc_metadata/src/creader.rs | 1 + compiler/rustc_metadata/src/lib.rs | 1 + compiler/rustc_metadata/src/locator.rs | 94 +- compiler/rustc_metadata/src/native_libs.rs | 2 +- compiler/rustc_metadata/src/rmeta/decoder.rs | 19 +- .../src/rmeta/decoder/cstore_impl.rs | 8 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 21 +- compiler/rustc_metadata/src/rmeta/mod.rs | 8 +- compiler/rustc_middle/Cargo.toml | 1 + compiler/rustc_middle/src/arena.rs | 53 +- .../rustc_middle/src/dep_graph/dep_node.rs | 224 +- compiler/rustc_middle/src/dep_graph/mod.rs | 72 +- compiler/rustc_middle/src/hir/map/blocks.rs | 239 - compiler/rustc_middle/src/hir/map/mod.rs | 145 +- compiler/rustc_middle/src/hir/mod.rs | 124 +- compiler/rustc_middle/src/lib.rs | 2 + compiler/rustc_middle/src/lint.rs | 10 +- compiler/rustc_middle/src/middle/stability.rs | 61 +- .../rustc_middle/src/mir/interpret/error.rs | 10 +- compiler/rustc_middle/src/mir/mod.rs | 10 +- compiler/rustc_middle/src/mir/pretty.rs | 3 +- compiler/rustc_middle/src/mir/query.rs | 1 + compiler/rustc_middle/src/mir/spanview.rs | 4 +- compiler/rustc_middle/src/query/mod.rs | 143 +- compiler/rustc_middle/src/traits/mod.rs | 26 +- compiler/rustc_middle/src/traits/select.rs | 10 +- compiler/rustc_middle/src/traits/util.rs | 49 + compiler/rustc_middle/src/ty/codec.rs | 18 +- compiler/rustc_middle/src/ty/consts.rs | 79 +- compiler/rustc_middle/src/ty/context.rs | 45 +- compiler/rustc_middle/src/ty/diagnostics.rs | 4 +- compiler/rustc_middle/src/ty/error.rs | 29 +- compiler/rustc_middle/src/ty/generics.rs | 21 +- compiler/rustc_middle/src/ty/layout.rs | 20 +- compiler/rustc_middle/src/ty/mod.rs | 79 +- compiler/rustc_middle/src/ty/print/pretty.rs | 290 +- compiler/rustc_middle/src/ty/query.rs | 60 +- compiler/rustc_middle/src/ty/relate.rs | 23 +- .../rustc_middle/src/ty/structural_impls.rs | 11 +- compiler/rustc_middle/src/ty/sty.rs | 89 +- compiler/rustc_middle/src/ty/subst.rs | 10 +- compiler/rustc_middle/src/ty/util.rs | 30 +- compiler/rustc_middle/src/util/common.rs | 2 +- .../src/build/expr/as_place.rs | 6 +- .../rustc_mir_build/src/build/matches/mod.rs | 13 +- compiler/rustc_mir_build/src/build/mod.rs | 101 +- compiler/rustc_mir_build/src/build/scope.rs | 6 +- .../rustc_mir_build/src/check_unsafety.rs | 23 +- compiler/rustc_mir_build/src/lib.rs | 1 + compiler/rustc_mir_build/src/lints.rs | 5 +- compiler/rustc_mir_build/src/thir/cx/expr.rs | 2 +- .../src/thir/pattern/check_match.rs | 21 +- .../src/thir/pattern/const_to_pat.rs | 3 + .../rustc_mir_build/src/thir/pattern/mod.rs | 2 +- .../src/thir/pattern/usefulness.rs | 17 +- .../rustc_mir_dataflow/src/elaborate_drops.rs | 9 +- .../src/framework/cursor.rs | 7 + .../rustc_mir_dataflow/src/framework/tests.rs | 2 + .../src/impls/borrowed_locals.rs | 132 +- compiler/rustc_mir_dataflow/src/impls/mod.rs | 75 +- compiler/rustc_mir_dataflow/src/lib.rs | 2 +- compiler/rustc_mir_dataflow/src/rustc_peek.rs | 37 +- .../rustc_mir_transform/src/const_prop.rs | 3 +- .../rustc_mir_transform/src/coverage/mod.rs | 23 +- .../rustc_mir_transform/src/coverage/spans.rs | 7 +- compiler/rustc_mir_transform/src/dump_mir.rs | 26 +- compiler/rustc_mir_transform/src/inline.rs | 4 +- compiler/rustc_mir_transform/src/lib.rs | 17 +- .../src/lower_slice_len.rs | 4 +- .../src/normalize_array_len.rs | 6 +- .../src/remove_unneeded_drops.rs | 2 +- .../rustc_mir_transform/src/reveal_all.rs | 58 + compiler/rustc_mir_transform/src/shim.rs | 149 - .../src/uninhabited_enum_branching.rs | 9 +- .../src/unreachable_prop.rs | 5 +- compiler/rustc_monomorphize/src/collector.rs | 13 +- compiler/rustc_monomorphize/src/lib.rs | 1 + .../src/partitioning/default.rs | 4 +- .../src/partitioning/mod.rs | 11 + .../rustc_monomorphize/src/polymorphize.rs | 5 +- compiler/rustc_monomorphize/src/util.rs | 2 +- compiler/rustc_parse/src/lexer/mod.rs | 30 +- .../src/lexer/unescape_error_reporting.rs | 27 + .../rustc_parse/src/lexer/unicode_chars.rs | 2 +- .../rustc_parse/src/parser/diagnostics.rs | 85 +- compiler/rustc_parse/src/parser/expr.rs | 6 +- compiler/rustc_parse/src/parser/generics.rs | 5 +- compiler/rustc_parse/src/parser/item.rs | 89 +- compiler/rustc_parse/src/parser/mod.rs | 10 +- compiler/rustc_parse/src/parser/pat.rs | 6 +- compiler/rustc_parse/src/parser/path.rs | 88 +- compiler/rustc_parse/src/parser/stmt.rs | 25 +- compiler/rustc_parse/src/parser/ty.rs | 40 +- compiler/rustc_parse/src/validate_attr.rs | 11 +- compiler/rustc_passes/src/check_attr.rs | 165 +- compiler/rustc_passes/src/check_const.rs | 12 +- compiler/rustc_passes/src/lib.rs | 2 +- compiler/rustc_passes/src/region.rs | 11 +- compiler/rustc_privacy/src/lib.rs | 27 +- compiler/rustc_query_impl/Cargo.toml | 3 +- compiler/rustc_query_impl/src/lib.rs | 23 +- .../rustc_query_impl/src/on_disk_cache.rs | 25 +- compiler/rustc_query_impl/src/plumbing.rs | 290 +- .../src/dep_graph/dep_node.rs | 14 +- .../rustc_query_system/src/dep_graph/graph.rs | 78 +- .../rustc_query_system/src/dep_graph/mod.rs | 21 +- .../src/dep_graph/serialized.rs | 10 +- compiler/rustc_query_system/src/ich/hcx.rs | 64 +- .../rustc_query_system/src/ich/impls_hir.rs | 46 +- compiler/rustc_query_system/src/lib.rs | 2 + .../rustc_query_system/src/query/config.rs | 74 +- compiler/rustc_query_system/src/query/job.rs | 4 +- compiler/rustc_query_system/src/query/mod.rs | 10 +- .../rustc_query_system/src/query/plumbing.rs | 243 +- compiler/rustc_resolve/Cargo.toml | 1 + .../rustc_resolve/src/build_reduced_graph.rs | 29 +- compiler/rustc_resolve/src/check_unused.rs | 3 +- compiler/rustc_resolve/src/diagnostics.rs | 108 +- compiler/rustc_resolve/src/imports.rs | 54 +- compiler/rustc_resolve/src/late.rs | 41 +- .../rustc_resolve/src/late/diagnostics.rs | 43 +- compiler/rustc_resolve/src/late/lifetimes.rs | 54 +- compiler/rustc_resolve/src/lib.rs | 104 +- compiler/rustc_resolve/src/macros.rs | 10 +- .../rustc_save_analysis/src/dump_visitor.rs | 4 +- compiler/rustc_save_analysis/src/lib.rs | 1 + compiler/rustc_serialize/src/json.rs | 14 + compiler/rustc_serialize/src/serialize.rs | 18 +- compiler/rustc_session/src/config.rs | 95 +- compiler/rustc_session/src/lib.rs | 1 + compiler/rustc_session/src/options.rs | 79 +- compiler/rustc_session/src/parse.rs | 17 +- compiler/rustc_session/src/session.rs | 42 +- compiler/rustc_span/src/hygiene.rs | 13 +- compiler/rustc_span/src/lev_distance.rs | 36 +- compiler/rustc_span/src/lev_distance/tests.rs | 10 +- compiler/rustc_span/src/lib.rs | 18 +- compiler/rustc_span/src/source_map.rs | 19 +- compiler/rustc_span/src/symbol.rs | 17 +- compiler/rustc_symbol_mangling/src/lib.rs | 8 +- compiler/rustc_symbol_mangling/src/v0.rs | 36 + compiler/rustc_target/src/abi/call/mod.rs | 6 +- compiler/rustc_target/src/asm/mod.rs | 10 +- .../src/spec/aarch64_apple_darwin.rs | 9 +- .../src/spec/aarch64_be_unknown_linux_gnu.rs | 1 + .../aarch64_be_unknown_linux_gnu_ilp32.rs | 1 + .../rustc_target/src/spec/aarch64_fuchsia.rs | 2 +- .../src/spec/aarch64_linux_android.rs | 2 +- .../src/spec/aarch64_unknown_freebsd.rs | 1 + .../src/spec/aarch64_unknown_linux_gnu.rs | 2 + .../spec/aarch64_unknown_linux_gnu_ilp32.rs | 1 + compiler/rustc_target/src/spec/apple_base.rs | 19 +- .../src/spec/armv6k_nintendo_3ds.rs | 3 +- .../src/spec/hermit_kernel_base.rs | 5 +- compiler/rustc_target/src/spec/mod.rs | 83 +- .../src/spec/nvptx64_nvidia_cuda.rs | 4 + .../src/spec/wasm32_unknown_emscripten.rs | 2 +- .../src/spec/wasm64_unknown_unknown.rs | 14 +- compiler/rustc_target/src/spec/wasm_base.rs | 6 + .../src/spec/x86_64_apple_darwin.rs | 3 +- .../rustc_target/src/spec/x86_64_fuchsia.rs | 2 +- .../src/spec/x86_64_pc_solaris.rs | 2 +- .../src/spec/x86_64_unknown_freebsd.rs | 3 +- .../src/spec/x86_64_unknown_illumos.rs | 2 +- .../src/spec/x86_64_unknown_linux_gnu.rs | 7 +- .../src/spec/x86_64_unknown_linux_musl.rs | 7 +- .../src/spec/x86_64_unknown_netbsd.rs | 7 +- .../src/spec/x86_64_unknown_none.rs | 41 + .../rustc_trait_selection/src/autoderef.rs | 5 +- compiler/rustc_trait_selection/src/lib.rs | 2 + .../rustc_trait_selection/src/opaque_types.rs | 775 +- .../src/traits/auto_trait.rs | 10 +- .../src/traits/chalk_fulfill.rs | 44 +- .../src/traits/codegen.rs | 3 +- .../src/traits/coherence.rs | 53 +- .../src/traits/const_evaluatable.rs | 34 +- .../src/traits/error_reporting/mod.rs | 203 +- .../src/traits/error_reporting/suggestions.rs | 284 +- .../src/traits/fulfill.rs | 52 +- .../rustc_trait_selection/src/traits/misc.rs | 3 +- .../rustc_trait_selection/src/traits/mod.rs | 48 +- .../src/traits/object_safety.rs | 19 +- .../src/traits/on_unimplemented.rs | 4 +- .../src/traits/project.rs | 22 +- .../src/traits/query/type_op/custom.rs | 5 +- .../src/traits/relationships.rs | 1 + .../src/traits/select/candidate_assembly.rs | 184 +- .../src/traits/select/confirmation.rs | 90 +- .../src/traits/select/mod.rs | 265 +- .../src/traits/specialize/mod.rs | 40 +- .../src/traits/structural_match.rs | 8 +- .../rustc_trait_selection/src/traits/util.rs | 19 +- .../rustc_trait_selection/src/traits/wf.rs | 7 +- .../src/implied_outlives_bounds.rs | 6 +- compiler/rustc_ty_utils/src/instance.rs | 2 +- compiler/rustc_ty_utils/src/needs_drop.rs | 84 +- compiler/rustc_ty_utils/src/ty.rs | 5 +- compiler/rustc_type_ir/src/lib.rs | 1 + compiler/rustc_typeck/src/astconv/generics.rs | 24 +- compiler/rustc_typeck/src/astconv/mod.rs | 4 +- compiler/rustc_typeck/src/check/_match.rs | 2 +- compiler/rustc_typeck/src/check/callee.rs | 14 +- compiler/rustc_typeck/src/check/cast.rs | 7 +- compiler/rustc_typeck/src/check/check.rs | 22 +- compiler/rustc_typeck/src/check/closure.rs | 8 +- compiler/rustc_typeck/src/check/coercion.rs | 31 +- .../rustc_typeck/src/check/compare_method.rs | 76 +- compiler/rustc_typeck/src/check/demand.rs | 214 +- compiler/rustc_typeck/src/check/dropck.rs | 5 +- compiler/rustc_typeck/src/check/expr.rs | 251 +- compiler/rustc_typeck/src/check/fallback.rs | 2 +- .../rustc_typeck/src/check/fn_ctxt/_impl.rs | 73 +- .../rustc_typeck/src/check/fn_ctxt/checks.rs | 223 +- .../src/check/fn_ctxt/suggestions.rs | 97 +- compiler/rustc_typeck/src/check/intrinsic.rs | 7 +- .../rustc_typeck/src/check/method/confirm.rs | 26 +- compiler/rustc_typeck/src/check/method/mod.rs | 10 +- .../rustc_typeck/src/check/method/probe.rs | 164 +- .../rustc_typeck/src/check/method/suggest.rs | 241 +- compiler/rustc_typeck/src/check/mod.rs | 16 +- compiler/rustc_typeck/src/check/op.rs | 22 +- compiler/rustc_typeck/src/check/pat.rs | 9 +- compiler/rustc_typeck/src/check/place_op.rs | 4 +- compiler/rustc_typeck/src/check/regionck.rs | 35 +- compiler/rustc_typeck/src/check/upvar.rs | 35 +- compiler/rustc_typeck/src/check/wfcheck.rs | 395 +- compiler/rustc_typeck/src/check/writeback.rs | 6 + .../rustc_typeck/src/coherence/builtin.rs | 14 +- compiler/rustc_typeck/src/coherence/mod.rs | 8 +- compiler/rustc_typeck/src/coherence/orphan.rs | 464 +- compiler/rustc_typeck/src/collect.rs | 76 +- compiler/rustc_typeck/src/collect/type_of.rs | 10 +- compiler/rustc_typeck/src/hir_wf_check.rs | 3 +- .../src/impl_wf_check/min_specialization.rs | 2 + compiler/rustc_typeck/src/lib.rs | 17 +- .../src/outlives/outlives_bounds.rs | 3 +- .../wrong_number_of_generic_args.rs | 2 +- .../rustc_typeck/src/variance/constraints.rs | 30 +- config.toml.example | 12 +- git-commit-hash | 2 +- library/alloc/benches/btree/map.rs | 4 +- library/alloc/src/alloc.rs | 3 + library/alloc/src/boxed.rs | 3 + library/alloc/src/collections/binary_heap.rs | 22 +- library/alloc/src/collections/btree/map.rs | 21 +- .../alloc/src/collections/btree/map/entry.rs | 2 + .../alloc/src/collections/btree/map/tests.rs | 26 +- library/alloc/src/collections/btree/set.rs | 20 +- .../alloc/src/collections/btree/set/tests.rs | 8 +- library/alloc/src/collections/linked_list.rs | 23 + library/alloc/src/collections/mod.rs | 1 + .../alloc/src/collections/vec_deque/mod.rs | 2 +- library/alloc/src/fmt.rs | 18 + library/alloc/src/lib.rs | 97 +- library/alloc/src/raw_vec.rs | 61 +- library/alloc/src/raw_vec/tests.rs | 84 + library/alloc/src/rc.rs | 66 +- library/alloc/src/slice.rs | 4 + library/alloc/src/str.rs | 7 +- library/alloc/src/string.rs | 15 +- library/alloc/src/sync.rs | 37 +- library/alloc/src/vec/drain.rs | 1 + library/alloc/src/vec/mod.rs | 42 +- library/alloc/tests/lib.rs | 1 + library/alloc/tests/str.rs | 66 +- library/backtrace/.github/workflows/main.yml | 5 + library/backtrace/Cargo.toml | 6 +- library/backtrace/crates/as-if-std/Cargo.toml | 2 +- library/backtrace/src/backtrace/libunwind.rs | 235 +- .../backtrace/src/symbolize/gimli/macho.rs | 10 +- library/backtrace/src/symbolize/mod.rs | 2 +- library/core/src/alloc/layout.rs | 22 +- library/core/src/any.rs | 3 + library/core/src/array/mod.rs | 128 +- library/core/src/ascii.rs | 1 + library/core/src/cell.rs | 15 +- library/core/src/char/convert.rs | 44 +- library/core/src/char/decode.rs | 1 + library/core/src/char/methods.rs | 35 +- library/core/src/clone.rs | 3 +- library/core/src/convert/mod.rs | 9 +- library/core/src/convert/num.rs | 5 +- library/core/src/default.rs | 1 + library/core/src/ffi.rs | 12 +- library/core/src/fmt/float.rs | 53 +- library/core/src/fmt/mod.rs | 25 +- library/core/src/future/mod.rs | 1 + library/core/src/internal_macros.rs | 71 + library/core/src/intrinsics.rs | 62 +- library/core/src/iter/adapters/zip.rs | 8 +- library/core/src/iter/sources/empty.rs | 1 + library/core/src/iter/traits/iterator.rs | 6 +- library/core/src/lazy.rs | 2 +- library/core/src/lib.rs | 24 +- library/core/src/macros/mod.rs | 7 +- library/core/src/marker.rs | 4 +- library/core/src/mem/mod.rs | 13 + library/core/src/num/error.rs | 6 +- library/core/src/num/f32.rs | 71 +- library/core/src/num/f64.rs | 71 +- library/core/src/num/fmt.rs | 4 +- library/core/src/num/int_macros.rs | 67 +- library/core/src/num/mod.rs | 78 +- library/core/src/num/nonzero.rs | 24 +- library/core/src/num/saturating.rs | 4 +- library/core/src/num/uint_macros.rs | 26 +- library/core/src/num/wrapping.rs | 128 +- library/core/src/ops/arith.rs | 65 +- library/core/src/ops/bit.rs | 55 +- library/core/src/ops/control_flow.rs | 40 +- library/core/src/ops/generator.rs | 1 + library/core/src/ops/range.rs | 1 + library/core/src/option.rs | 16 +- library/core/src/panic/location.rs | 4 + library/core/src/panic/panic_info.rs | 5 +- library/core/src/panicking.rs | 31 +- library/core/src/pin.rs | 1 + library/core/src/primitive_docs.rs | 8 +- library/core/src/ptr/const_ptr.rs | 21 +- library/core/src/ptr/mod.rs | 2 + library/core/src/ptr/mut_ptr.rs | 24 +- library/core/src/ptr/non_null.rs | 12 +- library/core/src/ptr/unique.rs | 3 +- library/core/src/result.rs | 11 +- library/core/src/slice/ascii.rs | 2 + library/core/src/slice/iter.rs | 15 +- library/core/src/slice/memchr.rs | 2 + library/core/src/slice/mod.rs | 217 +- library/core/src/slice/raw.rs | 62 +- library/core/src/str/converts.rs | 31 +- library/core/src/str/error.rs | 14 +- library/core/src/str/iter.rs | 20 +- library/core/src/str/lossy.rs | 1 + library/core/src/str/mod.rs | 11 +- library/core/src/str/pattern.rs | 73 + library/core/src/str/traits.rs | 9 +- library/core/src/str/validations.rs | 97 +- library/core/src/sync/atomic.rs | 9 +- library/core/src/task/poll.rs | 3 +- library/core/src/task/wake.rs | 2 + library/core/src/time.rs | 67 +- library/core/tests/array.rs | 38 + library/core/tests/ascii.rs | 2 +- library/core/tests/atomic.rs | 7 + library/core/tests/cell.rs | 9 + library/core/tests/char.rs | 12 + library/core/tests/fmt/float.rs | 24 + library/core/tests/lazy.rs | 6 + library/core/tests/lib.rs | 12 +- library/core/tests/nonzero.rs | 10 +- library/core/tests/num/mod.rs | 61 + library/core/tests/option.rs | 15 + library/core/tests/result.rs | 23 + library/core/tests/slice.rs | 41 + library/panic_abort/src/lib.rs | 2 +- library/panic_unwind/src/dummy.rs | 4 +- library/panic_unwind/src/lib.rs | 2 +- .../.github/ISSUE_TEMPLATE/blank_issue.md | 4 + .../.github/ISSUE_TEMPLATE/bug_report.md | 50 + .../.github/ISSUE_TEMPLATE/config.yml | 10 + .../.github/ISSUE_TEMPLATE/feature_request.md | 14 + .../.github/PULL_REQUEST_TEMPLATE.md | 18 + .../portable-simd/.github/workflows/ci.yml | 260 + .../portable-simd/.github/workflows/doc.yml | 30 + library/portable-simd/CONTRIBUTING.md | 32 + library/portable-simd/Cargo.toml | 6 + library/portable-simd/LICENSE-APACHE | 202 + library/portable-simd/LICENSE-MIT | 19 + library/portable-simd/README.md | 69 + library/portable-simd/beginners-guide.md | 86 + .../portable-simd/crates/core_simd/Cargo.toml | 28 + .../crates/core_simd/LICENSE-APACHE | 202 + .../crates/core_simd/LICENSE-MIT | 19 + .../core_simd/examples/matrix_inversion.rs | 316 + .../crates/core_simd/examples/nbody.rs | 193 + .../crates/core_simd/src/comparisons.rs | 50 + .../crates/core_simd/src/core_simd_docs.md | 4 + .../portable-simd/crates/core_simd/src/fmt.rs | 39 + .../crates/core_simd/src/intrinsics.rs | 115 + .../crates/core_simd/src/iter.rs | 58 + .../crates/core_simd/src/lane_count.rs | 48 + .../portable-simd/crates/core_simd/src/lib.rs | 21 + .../crates/core_simd/src/masks.rs | 545 + .../crates/core_simd/src/masks/bitmask.rs | 220 + .../crates/core_simd/src/masks/full_masks.rs | 228 + .../crates/core_simd/src/math.rs | 159 + .../portable-simd/crates/core_simd/src/mod.rs | 33 + .../portable-simd/crates/core_simd/src/ops.rs | 644 + .../crates/core_simd/src/reduction.rs | 123 + .../crates/core_simd/src/round.rs | 78 + .../crates/core_simd/src/select.rs | 86 + .../crates/core_simd/src/swizzle.rs | 374 + .../crates/core_simd/src/to_bytes.rs | 39 + .../crates/core_simd/src/vector.rs | 528 + .../crates/core_simd/src/vector/float.rs | 210 + .../crates/core_simd/src/vector/int.rs | 103 + .../crates/core_simd/src/vector/ptr.rs | 55 + .../crates/core_simd/src/vector/uint.rs | 63 + .../crates/core_simd/src/vendor.rs | 29 + .../crates/core_simd/src/vendor/arm.rs | 76 + .../crates/core_simd/src/vendor/powerpc.rs | 11 + .../crates/core_simd/src/vendor/wasm32.rs | 30 + .../crates/core_simd/src/vendor/x86.rs | 63 + .../crates/core_simd/tests/f32_ops.rs | 5 + .../crates/core_simd/tests/f64_ops.rs | 5 + .../crates/core_simd/tests/i16_ops.rs | 5 + .../crates/core_simd/tests/i32_ops.rs | 5 + .../crates/core_simd/tests/i64_ops.rs | 5 + .../crates/core_simd/tests/i8_ops.rs | 5 + .../crates/core_simd/tests/isize_ops.rs | 5 + .../crates/core_simd/tests/mask_ops.rs | 3 + .../core_simd/tests/mask_ops_impl/mask16.rs | 4 + .../core_simd/tests/mask_ops_impl/mask32.rs | 4 + .../core_simd/tests/mask_ops_impl/mask64.rs | 3 + .../core_simd/tests/mask_ops_impl/mask8.rs | 3 + .../tests/mask_ops_impl/mask_macros.rs | 225 + .../core_simd/tests/mask_ops_impl/masksize.rs | 3 + .../core_simd/tests/mask_ops_impl/mod.rs | 9 + .../crates/core_simd/tests/masks.rs | 102 + .../crates/core_simd/tests/ops_macros.rs | 618 + .../crates/core_simd/tests/round.rs | 92 + .../crates/core_simd/tests/swizzle.rs | 62 + .../crates/core_simd/tests/to_bytes.rs | 14 + .../crates/core_simd/tests/u16_ops.rs | 5 + .../crates/core_simd/tests/u32_ops.rs | 5 + .../crates/core_simd/tests/u64_ops.rs | 5 + .../crates/core_simd/tests/u8_ops.rs | 5 + .../crates/core_simd/tests/usize_ops.rs | 5 + .../crates/core_simd/webdriver.json | 7 + .../crates/test_helpers/Cargo.toml | 10 + .../crates/test_helpers/src/array.rs | 97 + .../crates/test_helpers/src/biteq.rs | 106 + .../crates/test_helpers/src/lib.rs | 437 + .../crates/test_helpers/src/wasm.rs | 51 + library/proc_macro/src/bridge/mod.rs | 1 + library/proc_macro/src/lib.rs | 60 +- library/std/Cargo.toml | 8 +- library/std/build.rs | 1 + library/std/src/backtrace.rs | 3 + library/std/src/collections/hash/map.rs | 5 + library/std/src/collections/hash/set.rs | 12 +- library/std/src/collections/mod.rs | 2 +- library/std/src/env.rs | 8 + library/std/src/f32.rs | 36 - library/std/src/f32/tests.rs | 75 +- library/std/src/f64.rs | 36 - library/std/src/f64/tests.rs | 55 - library/std/src/ffi/c_str.rs | 26 +- library/std/src/ffi/mod.rs | 2 +- library/std/src/ffi/os_str.rs | 5 + library/std/src/fs.rs | 31 +- library/std/src/fs/tests.rs | 118 +- library/std/src/io/error.rs | 11 + library/std/src/io/mod.rs | 7 +- library/std/src/io/stdio.rs | 4 + library/std/src/io/util.rs | 3 + library/std/src/keyword_docs.rs | 7 +- library/std/src/lib.rs | 16 +- library/std/src/net/addr.rs | 8 + library/std/src/net/ip.rs | 17 +- library/std/src/net/ip/tests.rs | 8 + library/std/src/net/parser.rs | 28 +- library/std/src/net/tcp.rs | 1 + library/std/src/os/raw/mod.rs | 9 +- library/std/src/os/unix/net/addr.rs | 2 +- library/std/src/os/unix/net/ancillary.rs | 8 + library/std/src/os/unix/net/listener.rs | 1 + library/std/src/os/unix/process.rs | 13 +- library/std/src/os/wasi/fs.rs | 8 +- library/std/src/panic.rs | 2 +- library/std/src/panicking.rs | 32 +- library/std/src/path.rs | 96 +- library/std/src/path/tests.rs | 80 +- library/std/src/primitive_docs.rs | 8 +- library/std/src/process.rs | 27 + library/std/src/process/tests.rs | 93 +- library/std/src/rt.rs | 7 +- library/std/src/sync/barrier.rs | 2 +- library/std/src/sync/condvar.rs | 1 + library/std/src/sync/mpsc/cache_aligned.rs | 7 +- library/std/src/sync/mpsc/mod.rs | 2 + library/std/src/sys/common/alloc.rs | 3 +- library/std/src/sys/hermit/condvar.rs | 16 +- library/std/src/sys/hermit/mutex.rs | 11 +- library/std/src/sys/hermit/net.rs | 2 +- library/std/src/sys/itron/thread.rs | 2 +- library/std/src/sys/mod.rs | 2 +- library/std/src/sys/solid/abi/mod.rs | 13 +- library/std/src/sys/unix/fs.rs | 285 +- library/std/src/sys/unix/kernel_copy.rs | 6 +- library/std/src/sys/unix/path.rs | 1 + .../std/src/sys/unix/process/process_unix.rs | 3 + library/std/src/sys/unix/stack_overflow.rs | 20 +- library/std/src/sys/unix/thread.rs | 8 + library/std/src/sys/unix/weak.rs | 5 +- library/std/src/sys/wasi/fs.rs | 71 +- library/std/src/sys/wasm/alloc.rs | 4 +- library/std/src/sys/windows/c.rs | 132 +- library/std/src/sys/windows/fs.rs | 349 +- library/std/src/sys/windows/os.rs | 4 + library/std/src/sys/windows/path.rs | 123 +- library/std/src/sys/windows/path/tests.rs | 52 + library/std/src/sys/windows/process.rs | 183 +- library/std/src/sys/windows/process/tests.rs | 56 + .../std/src/sys/windows/thread_local_dtor.rs | 26 +- .../std/src/sys/windows/thread_local_key.rs | 2 + library/std/src/sys_common/mod.rs | 2 +- library/std/src/sys_common/process.rs | 1 + library/std/src/sys_common/wtf8.rs | 5 +- library/std/src/thread/local.rs | 28 +- library/std/src/thread/mod.rs | 21 +- library/std/src/thread/tests.rs | 36 +- library/std/src/time.rs | 7 + library/std/src/time/tests.rs | 4 +- library/stdarch/.github/workflows/main.yml | 3 +- library/stdarch/ci/run.sh | 2 +- library/stdarch/crates/core_arch/MISSING.md | 116 + .../core_arch/src/aarch64/neon/generated.rs | 17564 +++++++--- .../crates/core_arch/src/aarch64/neon/mod.rs | 266 +- .../stdarch/crates/core_arch/src/arm/neon.rs | 69 +- .../crates/core_arch/src/arm_shared/crypto.rs | 2 - .../src/arm_shared/neon/generated.rs | 29105 +++++++++++----- .../core_arch/src/arm_shared/neon/mod.rs | 273 +- .../arm_shared/neon/shift_and_insert_tests.rs | 4 + .../src/arm_shared/neon/store_tests.rs | 23 + library/stdarch/crates/core_arch/src/lib.rs | 4 +- .../stdarch/crates/core_arch/src/mips/msa.rs | 2 +- library/stdarch/crates/core_arch/src/mod.rs | 26 +- .../crates/core_arch/src/wasm32/memory.rs | 12 +- .../stdarch/crates/core_arch/src/x86/avx.rs | 3 +- .../stdarch/crates/core_arch/src/x86/sse41.rs | 27 +- .../stdarch/crates/intrinsic-test/Cargo.toml | 3 +- .../stdarch/crates/intrinsic-test/missing.txt | 115 + .../crates/intrinsic-test/neon-intrinsics.csv | 4356 --- .../intrinsic-test/src/acle_csv_parser.rs | 313 + .../crates/intrinsic-test/src/argument.rs | 108 +- .../crates/intrinsic-test/src/intrinsic.rs | 72 +- .../stdarch/crates/intrinsic-test/src/main.rs | 153 +- .../crates/intrinsic-test/src/types.rs | 166 +- .../crates/std_detect/src/detect/arch/arm.rs | 2 + .../crates/std_detect/src/detect/macros.rs | 2 +- .../crates/std_detect/src/detect/os/x86.rs | 20 + library/stdarch/crates/stdarch-gen/neon.spec | 2301 +- .../stdarch/crates/stdarch-gen/src/main.rs | 570 +- .../stdarch/crates/stdarch-test/src/lib.rs | 13 + .../crates/stdarch-verify/tests/arm.rs | 108 + library/test/src/console.rs | 2 +- library/test/src/formatters/junit.rs | 4 +- library/test/src/lib.rs | 4 +- library/unwind/src/lib.rs | 1 - src/bootstrap/CHANGELOG.md | 1 + src/bootstrap/bin/rustc.rs | 2 +- src/bootstrap/bootstrap.py | 60 +- src/bootstrap/builder.rs | 23 +- src/bootstrap/compile.rs | 6 +- src/bootstrap/config.rs | 33 +- src/bootstrap/dist.rs | 24 +- src/bootstrap/doc.rs | 16 +- src/bootstrap/lib.rs | 3 +- src/bootstrap/metadata.rs | 3 +- src/bootstrap/native.rs | 7 +- src/bootstrap/test.rs | 55 +- src/bootstrap/tool.rs | 8 +- src/bootstrap/util.rs | 32 + .../host-x86_64/disabled/asmjs/Dockerfile | 1 + .../host-x86_64/dist-arm-linux/Dockerfile | 1 + .../host-x86_64/dist-x86_64-linux/Dockerfile | 2 +- .../dist-x86_64-linux/build-clang.sh | 2 +- .../host-x86_64/dist-x86_64-musl/Dockerfile | 1 + .../host-x86_64/test-various/Dockerfile | 2 + .../Dockerfile | 9 +- .../host-x86_64/x86_64-gnu-tools/Dockerfile | 2 +- src/ci/docker/run.sh | 9 +- src/ci/docker/scripts/freebsd-toolchain.sh | 2 +- .../docker/scripts/musl-patch-configure.diff | 13 + src/ci/docker/scripts/musl-toolchain.sh | 9 +- src/ci/github-actions/ci.yml | 16 +- src/ci/pgo.sh | 38 +- src/ci/run.sh | 9 +- src/doc/book/2018-edition/src/SUMMARY.md | 2 +- .../listing-09-10/Cargo.lock | 79 +- .../listing-09-10/Cargo.toml | 3 +- .../output.txt | 0 .../listing-09-10/src/main.rs | 54 +- .../Cargo.lock | 3 +- .../Cargo.toml | 0 .../listing-09-11/src/main.rs | 15 + .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 0 .../listing-09-13/Cargo.lock | 83 + .../listing-09-13/Cargo.toml | 7 + .../listing-09-13/src/main.rs | 55 + .../src/main.rs | 5 - .../listing-10-11/src/main.rs | 10 +- .../listing-10-12/Cargo.toml | 2 +- .../listing-10-13/Cargo.toml | 2 +- .../listing-10-14/Cargo.toml | 2 +- .../Cargo.lock | 5 +- .../Cargo.toml | 2 +- .../src/main.rs | 4 +- .../Cargo.toml | 2 +- .../Cargo.toml | 2 +- .../Cargo.toml | 2 +- .../Cargo.toml | 2 +- .../Cargo.toml | 2 +- src/doc/book/nostarch/chapter02.md | 488 +- src/doc/book/nostarch/chapter03.md | 446 +- src/doc/book/nostarch/chapter04.md | 484 +- src/doc/book/nostarch/chapter08.md | 1063 + src/doc/book/nostarch/chapter09.md | 1042 + src/doc/book/nostarch/chapter10.md | 2042 ++ src/doc/book/redirects/const-and-static.md | 2 +- src/doc/book/second-edition/src/SUMMARY.md | 2 +- src/doc/book/src/SUMMARY.md | 2 +- src/doc/book/src/appendix-06-translation.md | 1 - src/doc/book/src/ch01-01-installation.md | 8 +- src/doc/book/src/ch01-02-hello-world.md | 2 +- .../src/ch02-00-guessing-game-tutorial.md | 462 +- .../src/ch03-01-variables-and-mutability.md | 123 +- src/doc/book/src/ch03-02-data-types.md | 118 +- .../book/src/ch03-03-how-functions-work.md | 69 +- src/doc/book/src/ch03-04-comments.md | 6 +- src/doc/book/src/ch03-05-control-flow.md | 129 +- .../src/ch04-00-understanding-ownership.md | 10 +- src/doc/book/src/ch04-01-what-is-ownership.md | 189 +- .../src/ch04-02-references-and-borrowing.md | 78 +- src/doc/book/src/ch04-03-slices.md | 59 +- ...referring-to-an-item-in-the-module-tree.md | 2 +- src/doc/book/src/ch08-01-vectors.md | 12 +- src/doc/book/src/ch08-02-strings.md | 5 +- src/doc/book/src/ch08-03-hash-maps.md | 39 +- .../ch09-02-recoverable-errors-with-result.md | 173 +- .../src/ch09-03-to-panic-or-not-to-panic.md | 19 +- src/doc/book/src/ch10-00-generics.md | 6 +- src/doc/book/src/ch10-01-syntax.md | 37 +- src/doc/book/src/ch10-02-traits.md | 75 +- src/doc/book/src/ch10-03-lifetime-syntax.md | 45 +- src/doc/book/src/ch11-01-writing-tests.md | 2 +- ...improving-error-handling-and-modularity.md | 2 +- ...2-05-working-with-environment-variables.md | 8 +- src/doc/book/src/ch15-06-reference-cycles.md | 2 +- .../book/src/ch17-03-oo-design-patterns.md | 2 +- src/doc/book/src/ch19-01-unsafe-rust.md | 2 +- src/doc/book/src/ch19-06-macros.md | 2 +- src/doc/book/src/ch20-01-single-threaded.md | 2 +- src/doc/book/tools/convert-quotes.sh | 2 +- .../src/rust-2021/default-cargo-resolver.md | 2 +- .../rust-2021/disjoint-capture-in-closures.md | 4 +- .../edition-guide/src/rust-2021/prelude.md | 2 +- src/doc/embedded-book/src/SUMMARY.md | 1 + .../embedded-book/src/peripherals/borrowck.md | 2 +- src/doc/embedded-book/src/unsorted/math.md | 75 + src/doc/nomicon/src/arc-mutex/arc-layout.md | 2 +- src/doc/nomicon/src/ffi.md | 86 +- src/doc/nomicon/src/phantom-data.md | 2 +- src/doc/nomicon/src/safe-unsafe-meaning.md | 2 +- src/doc/nomicon/src/subtyping.md | 2 +- src/doc/nomicon/src/what-unsafe-does.md | 2 +- src/doc/reference/src/const_eval.md | 2 - .../reference/src/crates-and-source-files.md | 2 +- .../reference/src/special-types-and-traits.md | 17 +- src/doc/reference/src/tokens.md | 2 +- src/doc/reference/style-check/Cargo.toml | 2 +- .../custom_types/enum/testcase_linked_list.md | 2 +- .../src/custom_types/structs.md | 2 +- .../src/testing/dev_dependencies.md | 10 +- .../rust-by-example/src/trait/impl_trait.md | 51 + .../.github/workflows/date-check.yml | 4 + .../rustc-dev-guide/ci/date-check/Cargo.toml | 4 +- src/doc/rustc-dev-guide/src/SUMMARY.md | 1 + .../rustc-dev-guide/src/about-this-guide.md | 60 +- .../rustc-dev-guide/src/appendix/glossary.md | 2 +- .../src/backend/implicit-caller-location.md | 12 +- .../rustc-dev-guide/src/backend/monomorph.md | 12 +- .../src/backend/updating-llvm.md | 2 +- src/doc/rustc-dev-guide/src/borrow_check.md | 8 +- .../moves_and_initialization/move_paths.md | 28 +- .../src/borrow_check/region_inference.md | 32 +- .../constraint_propagation.md | 16 +- .../region_inference/lifetime_parameters.md | 12 +- .../src/borrow_check/type_check.md | 2 +- .../src/building/bootstrapping.md | 154 +- .../build-install-distribution-artifacts.md | 2 +- .../src/building/compiler-documenting.md | 2 +- .../src/building/how-to-build-and-run.md | 2 +- .../src/building/new-target.md | 2 +- .../rustc-dev-guide/src/building/suggested.md | 15 +- src/doc/rustc-dev-guide/src/closure.md | 2 +- src/doc/rustc-dev-guide/src/compiletest.md | 6 +- src/doc/rustc-dev-guide/src/const-eval.md | 4 +- src/doc/rustc-dev-guide/src/contributing.md | 44 +- src/doc/rustc-dev-guide/src/diagnostics.md | 12 +- .../src/diagnostics/diagnostic-items.md | 2 +- .../src/diagnostics/lintstore.md | 2 +- .../rustc-dev-guide/src/early-late-bound.md | 2 +- .../rustc-dev-guide/src/getting-started.md | 32 +- src/doc/rustc-dev-guide/src/git.md | 4 +- .../src/llvm-coverage-instrumentation.md | 42 +- .../rustc-dev-guide/src/macro-expansion.md | 2 +- src/doc/rustc-dev-guide/src/mir/dataflow.md | 22 +- src/doc/rustc-dev-guide/src/mir/debugging.md | 4 +- .../src/mir/drop-elaboration.md | 195 + src/doc/rustc-dev-guide/src/mir/index.md | 10 +- .../rustc-dev-guide/src/mir/optimizations.md | 21 +- src/doc/rustc-dev-guide/src/mir/passes.md | 7 +- src/doc/rustc-dev-guide/src/mir/visitor.md | 3 +- src/doc/rustc-dev-guide/src/miri.md | 16 +- src/doc/rustc-dev-guide/src/overview.md | 12 +- src/doc/rustc-dev-guide/src/profiling.md | 9 +- .../src/profiling/with_perf.md | 20 +- .../rustc-dev-guide/src/rustdoc-internals.md | 2 +- src/doc/rustc-dev-guide/src/sanitizers.md | 15 +- src/doc/rustc-dev-guide/src/tests/adding.md | 1 - src/doc/rustc-dev-guide/src/tests/intro.md | 5 +- src/doc/rustc-dev-guide/src/tests/running.md | 15 +- src/doc/rustc-dev-guide/src/tracing.md | 4 +- src/doc/rustc-dev-guide/src/ty.md | 2 +- src/doc/rustc/src/SUMMARY.md | 2 + src/doc/rustc/src/codegen-options/index.md | 16 + src/doc/rustc/src/exploit-mitigations.md | 40 +- src/doc/rustc/src/platform-support.md | 3 +- .../wasm64-unknown-unknown.md | 101 + .../platform-support/x86_64-unknown-none.md | 76 + src/doc/rustdoc/src/SUMMARY.md | 1 + src/doc/rustdoc/src/documentation-tests.md | 10 + src/doc/rustdoc/src/how-to-read-rustdoc.md | 107 + src/doc/rustdoc/src/the-doc-attribute.md | 55 +- src/doc/rustdoc/src/unstable-features.md | 123 +- .../src/compiler-flags/location-detail.md | 43 + .../compiler-flags/no-unique-section-names.md | 9 + .../src/compiler-flags/sanitizer.md | 181 +- .../unstable-book/src/compiler-flags/strip.md | 17 - .../src/compiler-flags/temps-dir.md | 10 + .../src/language-features/inline-const-pat.md | 24 + .../src/language-features/inline-const.md | 17 +- .../type-changing-struct-update.md | 33 + .../unstable-book/src/library-features/asm.md | 23 +- .../library-features/format-args-capture.md | 47 - .../src/library-features/global-asm.md | 4 +- src/librustdoc/Cargo.toml | 2 +- src/librustdoc/clean/auto_trait.rs | 38 +- src/librustdoc/clean/blanket_impl.rs | 10 +- src/librustdoc/clean/inline.rs | 50 +- src/librustdoc/clean/mod.rs | 567 +- src/librustdoc/clean/types.rs | 271 +- src/librustdoc/clean/utils.rs | 69 +- src/librustdoc/config.rs | 39 +- src/librustdoc/core.rs | 54 +- src/librustdoc/docfs.rs | 11 +- src/librustdoc/doctest.rs | 49 +- src/librustdoc/doctest/tests.rs | 17 +- src/librustdoc/doctree.rs | 27 - src/librustdoc/externalfiles.rs | 6 +- src/librustdoc/fold.rs | 78 +- src/librustdoc/formats/cache.rs | 71 +- src/librustdoc/formats/item_type.rs | 3 + src/librustdoc/html/format.rs | 37 +- src/librustdoc/html/highlight.rs | 112 +- .../html/highlight/fixtures/decorations.html | 2 + .../html/highlight/fixtures/sample.html | 4 +- src/librustdoc/html/highlight/tests.rs | 25 +- src/librustdoc/html/layout.rs | 8 +- src/librustdoc/html/markdown.rs | 64 +- src/librustdoc/html/render/cache.rs | 290 +- src/librustdoc/html/render/context.rs | 63 +- src/librustdoc/html/render/mod.rs | 466 +- src/librustdoc/html/render/print_item.rs | 333 +- src/librustdoc/html/render/span_map.rs | 59 +- src/librustdoc/html/render/write_shared.rs | 33 +- src/librustdoc/html/sources.rs | 96 +- src/librustdoc/html/static/css/noscript.css | 9 + src/librustdoc/html/static/css/rustdoc.css | 329 +- src/librustdoc/html/static/css/themes/ayu.css | 46 +- .../html/static/css/themes/dark.css | 50 +- .../html/static/css/themes/light.css | 29 +- .../static/fonts/NanumBarunGothic-LICENSE.txt | 99 + .../static/fonts/NanumBarunGothic.ttf.woff | Bin 0 -> 677868 bytes .../static/fonts/NanumBarunGothic.ttf.woff2 | Bin 0 -> 399468 bytes src/librustdoc/html/static/js/main.js | 21 +- .../html/static/js/scrape-examples.js | 86 + src/librustdoc/html/static/js/search.js | 37 +- src/librustdoc/html/static_files.rs | 42 +- src/librustdoc/html/templates/page.html | 18 +- src/librustdoc/json/conversions.rs | 53 +- src/librustdoc/lib.rs | 44 +- src/librustdoc/markdown.rs | 8 +- src/librustdoc/passes/bare_urls.rs | 15 +- .../passes/calculate_doc_coverage.rs | 23 +- .../passes/check_code_block_syntax.rs | 21 +- .../passes/check_doc_test_visibility.rs | 16 +- .../passes/collect_intra_doc_links.rs | 46 +- .../passes/collect_intra_doc_links/early.rs | 4 +- src/librustdoc/passes/collect_trait_impls.rs | 95 +- src/librustdoc/passes/html_tags.rs | 22 +- src/librustdoc/passes/stripper.rs | 6 +- src/librustdoc/passes/unindent_comments.rs | 4 +- .../passes/unindent_comments/tests.rs | 1 - src/librustdoc/scrape_examples.rs | 305 + src/librustdoc/visit.rs | 71 + src/librustdoc/visit_ast.rs | 41 +- src/librustdoc/visit_lib.rs | 6 +- src/stage0.json | 564 +- src/test/assembly/asm/aarch64-modifiers.rs | 1 - .../assembly/asm/aarch64-outline-atomics.rs | 1 - src/test/assembly/asm/aarch64-types.rs | 3 +- src/test/assembly/asm/arm-modifiers.rs | 1 - src/test/assembly/asm/arm-types.rs | 3 +- src/test/assembly/asm/bpf-types.rs | 2 +- src/test/assembly/asm/global_asm.rs | 3 +- src/test/assembly/asm/hexagon-types.rs | 3 +- src/test/assembly/asm/mips-types.rs | 3 +- src/test/assembly/asm/nvptx-types.rs | 3 +- src/test/assembly/asm/powerpc-types.rs | 4 +- src/test/assembly/asm/riscv-types.rs | 4 +- src/test/assembly/asm/s390x-types.rs | 3 +- src/test/assembly/asm/wasm-types.rs | 3 +- src/test/assembly/asm/x86-modifiers.rs | 1 - src/test/assembly/asm/x86-types.rs | 3 +- .../stack-protector-heuristics-effect.rs | 396 + .../stack-protector-target-support.rs | 286 + src/test/assembly/static-relocation-model.rs | 1 - .../item-collection/implicit-panic-call.rs | 58 + src/test/codegen/alloc-optimisation.rs | 1 - src/test/codegen/array-clone.rs | 15 + src/test/codegen/asm-powerpc-clobbers.rs | 3 +- .../binary-search-index-no-bound-check.rs | 1 - .../codegen/enum-bounds-check-derived-idx.rs | 1 - .../codegen/enum-bounds-check-issue-13926.rs | 1 - .../codegen/enum-bounds-check-issue-82871.rs | 1 - src/test/codegen/function-arguments.rs | 2 - src/test/codegen/issue-27130.rs | 1 - src/test/codegen/issue-73031.rs | 1 - ...issue-73396-bounds-check-after-position.rs | 1 - ...sue-73827-bounds-check-index-in-subexpr.rs | 1 - src/test/codegen/issue-75525-bounds-checks.rs | 1 - src/test/codegen/issue-75546.rs | 1 - src/test/codegen/issue-77812.rs | 1 - .../codegen/non-terminate/infinite-loop-1.rs | 1 - .../codegen/non-terminate/infinite-loop-2.rs | 1 - .../non-terminate/infinite-recursion.rs | 1 - .../non-terminate/nonempty-infinite-loop.rs | 1 - .../codegen/repr-transparent-aggregates-1.rs | 1 - .../codegen/repr-transparent-aggregates-2.rs | 1 - .../codegen/repr-transparent-aggregates-3.rs | 1 - ...izer_cfi_add_canonical_jump_tables_flag.rs | 14 + .../codegen/sanitizer_cfi_emit_type_checks.rs | 24 + .../sanitizer_cfi_emit_type_metadata.rs | 31 + src/test/codegen/slice-reverse.rs | 27 + .../src-hash-algorithm-sha256.rs | 1 - src/test/codegen/stack-protector.rs | 34 + src/test/codegen/vec-in-place.rs | 1 - src/test/codegen/wasm_casts_trapping.rs | 1 - .../auxiliary/rustc-rust-log-aux.rs | 8 + src/test/incremental/hashes/for_loops.rs | 6 +- src/test/incremental/hashes/trait_defs.rs | 6 +- .../issue-85360-eval-obligation-ice.rs | 118 + .../link_order/auxiliary/my_lib.rs | 4 +- src/test/incremental/rustc-rust-log.rs | 16 + .../incremental/struct_change_field_name.rs | 1 + .../inline/inline_generator.main.Inline.diff | 8 +- src/test/mir-opt/inline/issue-78442.rs | 20 + .../inline/issue_78442.bar.Inline.diff | 67 + .../inline/issue_78442.bar.RevealAll.diff | 55 + src/test/mir-opt/issue-78192.rs | 4 +- ...age_markers.main.RemoveStorageMarkers.diff | 115 +- src/test/pretty/dollar-crate.pp | 2 +- src/test/pretty/issue-4264.pp | 2 +- .../coverage-llvmir/Makefile | 1 - .../coverage-reports/Makefile | 1 - .../expected_show_coverage.continue.txt | 5 - .../expected_show_coverage.inline.txt | 3 +- .../expected_show_coverage.loops_branches.txt | 6 +- .../expected_show_coverage.simple_match.txt | 2 +- ...xpected_show_coverage.try_error_result.txt | 4 +- .../foreign-exceptions/foo.rs | 2 - .../invalid-library/Makefile | 2 +- .../obtain-borrowck/driver.rs | 5 +- src/test/run-make-fulldeps/print-cfg/Makefile | 2 + .../rustdoc-scrape-examples-macros/Makefile | 18 + .../examples/ex.rs | 27 + .../rustdoc-scrape-examples-macros/src/lib.rs | 12 + .../src/proc.rs | 39 + .../split-debuginfo/Makefile | 2 - .../run-make-fulldeps/split-dwarf/Makefile | 1 - src/test/run-make-fulldeps/tools.mk | 4 +- src/test/run-make/invalid-so/Makefile | 7 + src/test/run-make/invalid-so/bar.rs | 1 + .../run-make/issue-10971-temps-dir/Makefile | 10 + src/test/run-make/issue-36710/foo.rs | 3 - .../Makefile | 5 + .../examples/ex.rs | 2 + .../src/lib.rs | 1 + .../rustdoc-scrape-examples-multiple/Makefile | 5 + .../examples/ex.rs | 4 + .../examples/ex2.rs | 3 + .../scrape.mk | 20 + .../src/lib.rs | 6 + .../rustdoc-scrape-examples-ordering/Makefile | 5 + .../examples/ex1.rs | 11 + .../examples/ex2.rs | 8 + .../src/lib.rs | 7 + .../rustdoc-scrape-examples-remap/Makefile | 5 + .../examples/ex.rs | 4 + .../rustdoc-scrape-examples-remap/src/a.rs | 1 + .../rustdoc-scrape-examples-remap/src/lib.rs | 8 + src/test/rustdoc-gui/anchor-navigable.goml | 11 + src/test/rustdoc-gui/anchors.goml | 74 + src/test/rustdoc-gui/basic.goml | 2 +- .../rustdoc-gui/check-code-blocks-margin.goml | 6 + .../docblock-code-block-line-number.goml | 22 + src/test/rustdoc-gui/font-weight.goml | 8 +- src/test/rustdoc-gui/header-size.goml | 99 - src/test/rustdoc-gui/headers-color.goml | 18 + src/test/rustdoc-gui/headings.goml | 156 + src/test/rustdoc-gui/item-info-width.goml | 2 +- src/test/rustdoc-gui/javascript-disabled.goml | 6 + src/test/rustdoc-gui/module-items-font.goml | 28 +- .../overflow-tooltip-information.goml | 8 + src/test/rustdoc-gui/search-filter.goml | 4 +- .../rustdoc-gui/sidebar-macro-reexport.goml | 5 + src/test/rustdoc-gui/sidebar.goml | 28 +- src/test/rustdoc-gui/src/lib2/lib.rs | 19 + src/test/rustdoc-gui/src/test_docs/lib.rs | 12 +- .../rustdoc-gui/toggle-click-deadspace.goml | 12 + .../rustdoc-gui/type-declation-overflow.goml | 21 +- src/test/rustdoc-js/generics.js | 22 +- src/test/rustdoc-js/generics.rs | 5 + src/test/rustdoc-json/primitive.rs | 2 +- src/test/rustdoc-ui/auxiliary/empty-fn.rs | 3 + src/test/rustdoc-ui/coverage/exotic.rs | 3 +- src/test/rustdoc-ui/display-output.rs | 8 +- src/test/rustdoc-ui/display-output.stdout | 46 +- src/test/rustdoc-ui/doc-without-codeblock.rs | 9 + .../rustdoc-ui/doc-without-codeblock.stderr | 2 +- .../failed-doctest-extra-semicolon-on-item.rs | 18 + ...led-doctest-extra-semicolon-on-item.stdout | 24 + src/test/rustdoc-ui/invalid-doc-attr.stderr | 4 +- src/test/rustdoc-ui/invalid-keyword.rs | 2 +- src/test/rustdoc-ui/issue-91134.rs | 14 + src/test/rustdoc-ui/issue-91134.stdout | 6 + src/test/rustdoc-ui/recursive-deref-ice.rs | 19 + src/test/rustdoc-ui/scrape-examples-ice.rs | 4 + .../scrape-examples-wrong-options-1.rs | 1 + .../scrape-examples-wrong-options-1.stderr | 2 + .../scrape-examples-wrong-options-2.rs | 1 + .../scrape-examples-wrong-options-2.stderr | 2 + src/test/rustdoc/attributes.rs | 2 +- src/test/rustdoc/auxiliary/reexports.rs | 36 +- src/test/rustdoc/deref-recursive-pathbuf.rs | 25 + src/test/rustdoc/deref-recursive.rs | 41 + src/test/rustdoc/deref-typedef.rs | 4 +- src/test/rustdoc/enum-headings.rs | 40 + src/test/rustdoc/include_str_cut.rs | 7 + src/test/rustdoc/issue-32374.rs | 9 +- src/test/rustdoc/keyword.rs | 2 +- .../rustdoc/mixing-doc-comments-and-attrs.rs | 26 + src/test/rustdoc/recursive-deref-sidebar.rs | 2 +- src/test/rustdoc/recursive-deref.rs | 100 +- src/test/rustdoc/reexports-priv.rs | 120 +- src/test/rustdoc/reexports.rs | 90 +- src/test/rustdoc/short-line.md | 2 + src/test/rustdoc/tab_title.rs | 2 +- src/test/rustdoc/toggle-item-contents.rs | 2 +- src/test/rustdoc/trait_alias.rs | 9 +- src/test/rustdoc/tuple-struct-fields-doc.rs | 4 +- .../internal-lints/existing_doc_keyword.rs | 2 +- src/test/ui-fulldeps/lint-tool-test.rs | 3 + src/test/ui-fulldeps/lint-tool-test.stderr | 42 +- .../ui/{ => abi}/c-stack-returning-int64.rs | 0 src/test/ui/abi/stack-protector.rs | 99 + src/test/ui/abi/unsupported.aarch64.stderr | 19 +- src/test/ui/abi/unsupported.arm.stderr | 19 +- src/test/ui/abi/unsupported.rs | 11 +- src/test/ui/abi/unsupported.x64.stderr | 19 +- src/test/ui/{ => abi}/x86stdcall.rs | 5 +- src/test/ui/{ => abi}/x86stdcall2.rs | 0 .../default-alloc-error-hook.rs | 0 src/test/ui/alloca-from-derived-tydesc.rs | 15 - src/test/ui/allocator/not-an-allocator.stderr | 20 - src/test/ui/argument-passing.rs | 25 - .../ui/{ => array-slice-vec}/byte-literals.rs | 0 .../{ => array-slice-vec}/mut-vstore-expr.rs | 0 src/test/ui/asm/aarch64/bad-reg.rs | 2 +- src/test/ui/asm/aarch64/const.rs | 3 +- src/test/ui/asm/aarch64/parse-error.rs | 14 +- src/test/ui/asm/aarch64/parse-error.stderr | 118 +- src/test/ui/asm/aarch64/srcloc.rs | 1 - src/test/ui/asm/aarch64/srcloc.stderr | 46 +- src/test/ui/asm/aarch64/sym.rs | 7 +- src/test/ui/asm/aarch64/type-check-2.rs | 2 +- src/test/ui/asm/aarch64/type-check-3.rs | 5 +- src/test/ui/asm/aarch64/type-check-3.stderr | 38 +- src/test/ui/asm/bad-template.rs | 2 +- src/test/ui/asm/issue-89305.rs | 1 + src/test/ui/asm/issue-89305.stderr | 4 +- src/test/ui/asm/naked-functions.rs | 22 +- src/test/ui/asm/naked-functions.stderr | 70 +- src/test/ui/asm/named-asm-labels.rs | 2 +- src/test/ui/asm/type-check-1.rs | 2 +- src/test/ui/asm/x86_64/bad-clobber-abi.rs | 32 + src/test/ui/asm/x86_64/bad-clobber-abi.stderr | 88 + src/test/ui/asm/x86_64/bad-options.rs | 3 + src/test/ui/asm/x86_64/bad-options.stderr | 31 +- src/test/ui/asm/x86_64/bad-reg.rs | 2 +- src/test/ui/asm/x86_64/const.rs | 3 +- src/test/ui/asm/x86_64/issue-89875.rs | 14 + .../ui/asm/x86_64/multiple-clobber-abi.rs | 33 + src/test/ui/asm/x86_64/parse-error.rs | 16 +- src/test/ui/asm/x86_64/parse-error.stderr | 54 +- src/test/ui/asm/x86_64/srcloc.rs | 1 - src/test/ui/asm/x86_64/srcloc.stderr | 48 +- src/test/ui/asm/x86_64/sym.rs | 8 +- src/test/ui/asm/x86_64/type-check-2.rs | 2 +- src/test/ui/asm/x86_64/type-check-3.rs | 2 +- .../associated-const-array-len.stderr | 6 - .../ui/associated-consts/issue-63496.stderr | 10 - .../ui/associated-item/issue-48027.stderr | 5 - .../bad-bounds-on-assoc-in-trait.stderr | 29 - .../bounds-on-assoc-in-trait.stderr | 22 - .../associated-item-long-paths.rs | 0 .../associated-types-bound-failure.stderr | 5 - .../associated-types-for-unimpl-trait.stderr | 5 - .../associated-types-no-suitable-bound.stderr | 5 - ...ated-types-no-suitable-supertrait-2.stderr | 5 - ...ciated-types-no-suitable-supertrait.stderr | 11 - .../associated-types-path-2.rs | 2 + .../associated-types-path-2.stderr | 26 +- ...ted-trait-in-method-without-default.stderr | 5 - .../associated-types-unconstrained.stderr | 5 - .../default-associated-types.rs | 0 .../issue-22066.rs | 0 .../issue-22828.rs | 0 .../issue-28871.rs | 0 .../ui/associated-types/issue-44153.stderr | 5 - .../issue-47139-1.rs | 0 .../issue-54467.rs | 0 src/test/ui/associated-types/issue-87261.rs | 8 +- .../ui/associated-types/issue-87261.stderr | 24 +- .../substs-ppaux.normal.stderr | 5 - .../ui/{ => associated-types}/substs-ppaux.rs | 0 .../substs-ppaux.verbose.stderr | 5 - ...ync-block-control-flow-static-semantics.rs | 6 +- ...block-control-flow-static-semantics.stderr | 4 +- .../ui/async-await/async-fn-nonsend.stderr | 16 +- .../dont-suggest-missing-await.stderr | 2 +- src/test/ui/async-await/generator-desc.stderr | 8 +- ...correct-move-async-order-issue-79694.fixed | 0 .../incorrect-move-async-order-issue-79694.rs | 0 ...orrect-move-async-order-issue-79694.stderr | 0 src/test/ui/async-await/issue-61076.rs | 12 +- src/test/ui/async-await/issue-61076.stderr | 36 +- .../ui/async-await/issue-64130-1-sync.stderr | 6 +- .../ui/async-await/issue-64130-2-send.stderr | 6 +- .../ui/async-await/issue-64130-3-other.rs | 8 +- .../ui/async-await/issue-64130-3-other.stderr | 10 +- .../issue-64130-non-send-future-diags.stderr | 6 +- .../issue-67252-unnamed-future.stderr | 2 +- src/test/ui/async-await/issue-68112.stderr | 14 +- src/test/ui/async-await/issue-70594.stderr | 5 - src/test/ui/async-await/issue-71137.stderr | 6 +- .../{issues => async-await}/issue-73541-1.rs | 0 .../issue-73541-1.stderr | 0 .../issue-74497-lifetime-in-opaque.stderr | 2 +- src/test/ui/async-await/issue-84841.stderr | 14 +- .../async-await/issues/issue-62009-1.stderr | 5 - .../issue-65436-raw-ptr-not-send.stderr | 2 +- src/test/ui/async-await/issues/issue-67893.rs | 2 +- .../ui/async-await/issues/issue-67893.stderr | 19 +- .../ret-impl-trait-one.nll.stderr | 32 +- .../multiple-lifetimes/ret-impl-trait-one.rs | 8 +- .../ret-impl-trait-one.stderr | 28 +- .../async-await/pin-needed-to-poll-2.stderr | 12 +- .../suggest-missing-await-closure.stderr | 2 +- .../ui/async-await/suggest-missing-await.rs | 45 + .../async-await/suggest-missing-await.stderr | 110 +- .../async-await/try-on-option-in-async.stderr | 15 - .../ui/{ => attributes}/attr-eq-token-tree.rs | 0 .../attr-eq-token-tree.stderr | 0 .../ui/attributes/invalid-doc-attr.stderr | 4 +- .../ui/{issues => attributes}/issue-40962.rs | 0 src/test/ui/attributes/issue-90873.rs | 9 + src/test/ui/attributes/issue-90873.stderr | 50 + .../ui/attributes/key-value-expansion.stderr | 18 +- .../{ => attributes}/suffixed-literal-meta.rs | 0 .../suffixed-literal-meta.stderr | 0 .../ui/{ => attributes}/tool_attributes.rs | 0 .../unrestricted-attribute-tokens.rs | 0 .../ui/augmented-assignments-feature-gate.rs | 15 - src/test/ui/binding/ambiguity-item.stderr | 6 +- .../ui/{ => binop}/operator-multidispatch.rs | 0 .../ui/{ => binop}/operator-overloading.rs | 0 src/test/ui/{ => binop}/placement-syntax.rs | 0 .../ui/{ => binop}/placement-syntax.stderr | 0 .../ui/{ => binop}/shift-various-bad-types.rs | 0 .../shift-various-bad-types.stderr | 0 src/test/ui/{ => binop}/structured-compare.rs | 0 .../{ => borrowck}/access-mode-in-closures.rs | 0 .../access-mode-in-closures.stderr | 0 .../immut-function-arguments.rs | 0 .../immut-function-arguments.stderr | 0 .../ui/{issues => borrowck}/issue-46095.rs | 0 src/test/ui/borrowck/issue-80772.rs | 21 + src/test/ui/borrowck/issue-91206.rs | 15 + src/test/ui/borrowck/issue-91206.stderr | 12 + .../kindck-implicit-close-over-mut-var.rs | 0 src/test/ui/{ => borrowck}/lazy-init.rs | 0 ...regions-bound-missing-bound-in-impl.stderr | 4 +- .../return-local-binding-from-desugaring.rs | 2 +- ...eturn-local-binding-from-desugaring.stderr | 4 +- src/test/ui/box/into-boxed-slice-fail.stderr | 12 +- src/test/ui/{ => box}/new-box-syntax.rs | 0 src/test/ui/{ => box}/new-box.rs | 0 src/test/ui/builtin-clone-unwind.rs | 2 +- .../ui/{issues => c-variadic}/issue-32201.rs | 0 .../{issues => c-variadic}/issue-32201.stderr | 0 src/test/ui/cast/casts-differing-anon.stderr | 2 +- src/test/ui/{ => cast}/codegen-object-shim.rs | 0 src/test/ui/{ => cast}/supported-cast.rs | 0 src/test/ui/cfg/cfg-target-family.rs | 11 +- src/test/ui/{ => cfg}/crt-static-off-works.rs | 0 src/test/ui/{ => cfg}/crt-static-on-works.rs | 0 src/test/ui/{ => cfg}/expanded-cfg.rs | 0 src/test/ui/chalkify/builtin-copy-clone.rs | 5 +- src/test/ui/chalkify/type_wf.stderr | 6 +- ...ds-static-cant-capture-borrowed.nll.stderr | 13 +- ...ure-bounds-static-cant-capture-borrowed.rs | 2 +- ...bounds-static-cant-capture-borrowed.stderr | 18 +- .../ui/{ => closures}/closure-expected.rs | 0 .../ui/{ => closures}/closure-expected.stderr | 5 + .../ui/{ => closures}/closure_promotion.rs | 0 .../closures/coerce-unsafe-to-closure.stderr | 5 + .../ui/{issues => closures}/issue-10398.rs | 0 .../{issues => closures}/issue-10398.stderr | 0 .../ui/{issues => closures}/issue-42463.rs | 0 .../{ => closures}/once-move-out-on-heap.rs | 0 ...re-print-generic-trim-off-verbose-2.stderr | 2 +- .../closure-print-generic-verbose-2.stderr | 2 +- .../print/closure-print-verbose.stderr | 2 +- .../{ => closures}/semistatement-in-lambda.rs | 0 .../thir-unsafeck-issue-85871.rs | 0 .../cmse-nonsecure-call/params-on-stack.rs | 1 - .../params-on-stack.stderr | 1 - .../cmse-nonsecure-entry/params-on-stack.rs | 1 - .../params-on-stack.stderr | 1 - .../{ => codegen}/auxiliary/llvm_pr32379.rs | 0 src/test/ui/{ => codegen}/init-large-type.rs | 0 src/test/ui/{ => codegen}/llvm-pr32379.rs | 0 .../auxiliary/issue-39823.rs | 0 .../ui/{issues => coercion}/issue-14589.rs | 0 .../ui/{issues => coercion}/issue-39823.rs | 0 .../ui/{issues => coercion}/issue-73886.rs | 0 .../{issues => coercion}/issue-73886.stderr | 0 src/test/ui/{ => coercion}/retslot-cast.rs | 0 .../ui/{ => coercion}/retslot-cast.stderr | 0 src/test/ui/{ => coercion}/unsafe-coercion.rs | 0 src/test/ui/coherence/auxiliary/error_lib.rs | 5 + .../coherence-cross-crate-conflict.rs | 4 +- .../coherence-cross-crate-conflict.stderr | 14 +- ...mpl-trait-for-marker-trait-negative.stderr | 24 +- ...mpl-trait-for-marker-trait-positive.stderr | 24 +- src/test/ui/coherence/coherence-impls-copy.rs | 6 +- .../ui/coherence/coherence-impls-copy.stderr | 83 +- src/test/ui/coherence/coherence-impls-send.rs | 3 +- .../ui/coherence/coherence-impls-send.stderr | 15 +- .../ui/coherence/coherence-impls-sized.stderr | 66 +- src/test/ui/coherence/coherence-orphan.stderr | 22 +- .../coherence-overlap-negate-alias-strict.rs | 19 + ...herence-overlap-negate-alias-strict.stderr | 12 + ...nce-overlap-negate-not-use-feature-gate.rs | 8 + ...overlap-negate-not-use-feature-gate.stderr | 11 + .../coherence-overlap-negate-strict.rs | 18 + ...herence-overlap-negate-use-feature-gate.rs | 11 + .../coherence-overlap-negative-trait.rs | 16 + .../coherence-overlap-trait-alias.rs | 20 + .../coherence-overlap-trait-alias.stderr | 18 + src/test/ui/compare-method/issue-90444.rs | 17 + src/test/ui/compare-method/issue-90444.stderr | 27 + .../proj-outlives-region.stderr | 4 +- .../ui/compare-method/region-extra-2.stderr | 4 +- .../ui/compare-method/region-extra.stderr | 4 +- .../ui/compare-method/region-unrelated.stderr | 4 +- .../trait-bound-on-type-parameter.stderr | 4 +- .../traits-misc-mismatch-1.stderr | 28 +- .../traits-misc-mismatch-2.stderr | 4 +- .../cfg-arg-invalid-7.rs | 5 + .../cfg-arg-invalid-7.stderr | 4 + .../issue-34028.rs | 0 .../auxiliary/legacy-const-generics.rs | 0 .../defaults/default-annotation.rs | 2 +- .../const-generics/defaults/doesnt_infer.rs | 15 + .../defaults/doesnt_infer.stderr | 11 + .../const-generics/defaults/rp_impl_trait.rs | 31 + .../defaults/rp_impl_trait_fail.rs | 33 + .../defaults/rp_impl_trait_fail.stderr | 30 + .../const-generics/defaults/trait_objects.rs | 45 + .../defaults/trait_objects_fail.rs | 32 + .../defaults/trait_objects_fail.stderr | 27 + src/test/ui/const-generics/defaults/wfness.rs | 21 + .../ui/const-generics/defaults/wfness.stderr | 33 + .../ui/const-generics/defaults/wrong-order.rs | 3 + .../defaults/wrong-order.stderr | 8 +- .../dont-evaluate-array-len-on-err-1.stderr | 6 - .../ui/const-generics/exhaustive-value.stderr | 5 - .../issue-72787.min.stderr | 10 - .../generic_const_exprs/issue-83765.stderr | 5 + .../generic_const_exprs/issue-85848.stderr | 12 +- .../impl-trait-with-const-arguments.stderr | 3 + .../ui/const-generics/invariant.nll.stderr | 26 + src/test/ui/const-generics/invariant.rs | 33 + src/test/ui/const-generics/invariant.stderr | 26 + .../ui/const-generics/issues/issue-67185-2.rs | 9 +- .../issues/issue-67185-2.stderr | 60 +- .../issues/issue-67375.full.stderr | 12 +- .../ui/const-generics/issues/issue-67375.rs | 2 +- .../issues/issue-67945-1.full.stderr | 14 +- .../ui/const-generics/issues/issue-67945-1.rs | 2 +- .../ui/const-generics/issues/issue-88997.rs | 14 + .../const-generics/issues/issue-88997.stderr | 15 + .../ui/const-generics/issues/issue-89304.rs | 20 + .../ui/const-generics/issues/issue-90364.rs | 9 + .../const-generics/issues/issue-90364.stderr | 9 + .../legacy-const-generics-bad.rs | 0 .../legacy-const-generics-bad.stderr | 0 .../legacy-const-generics.rs | 0 .../occurs-check/unused-substs-1.stderr | 10 +- .../closure-structural-match-issue-90013.rs | 7 + .../consts/const-blocks/fn-call-in-const.rs | 2 +- src/test/ui/consts/const-deref-ptr.rs | 4 +- src/test/ui/consts/const-deref-ptr.stderr | 9 +- src/test/ui/consts/const-err.rs | 2 +- .../assign-to-static-within-other-static-2.rs | 19 - ...ign-to-static-within-other-static-2.stderr | 9 - .../assign-to-static-within-other-static.rs | 2 - ...ssign-to-static-within-other-static.stderr | 2 +- .../const_panic_stability.e2018.stderr | 16 + .../const_panic_stability.e2021.stderr | 13 + .../const-eval/const_panic_stability.rs | 17 + .../consts/const-eval/const_raw_ptr_ops2.rs | 2 - .../const-eval/const_raw_ptr_ops2.stderr | 4 +- src/test/ui/consts/const-eval/dangling.rs | 2 - src/test/ui/consts/const-eval/dangling.stderr | 2 +- .../const-eval/heap/alloc_intrinsic_errors.rs | 1 - .../heap/alloc_intrinsic_errors.stderr | 6 +- .../heap/alloc_intrinsic_nontransient.rs | 1 - .../heap/alloc_intrinsic_nontransient_fail.rs | 1 - .../alloc_intrinsic_nontransient_fail.stderr | 2 +- .../heap/alloc_intrinsic_transient.rs | 1 - .../heap/alloc_intrinsic_uninit.32bit.stderr | 2 +- .../heap/alloc_intrinsic_uninit.64bit.stderr | 2 +- .../const-eval/heap/alloc_intrinsic_uninit.rs | 1 - .../heap/alloc_intrinsic_untyped.rs | 1 - .../heap/alloc_intrinsic_untyped.stderr | 2 +- .../issue-84957-const-str-as-bytes.rs | 28 + .../const-eval/mod-static-with-const-fn.rs | 4 +- .../mod-static-with-const-fn.stderr | 9 +- .../const-eval/partial_ptr_overwrite.rs | 2 +- .../consts/const-eval/promoted_raw_ptr_ops.rs | 2 - .../const-eval/promoted_raw_ptr_ops.stderr | 8 +- .../consts/const-eval/simd/insert_extract.rs | 22 +- .../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 +- src/test/ui/consts/const-suggest-feature.rs | 4 +- .../ui/consts/const-suggest-feature.stderr | 6 +- src/test/ui/consts/const_discriminant.rs | 7 + src/test/ui/{ => consts}/eval-enum.rs | 0 src/test/ui/{ => consts}/eval-enum.stderr | 0 src/test/ui/consts/inline_asm.rs | 2 + src/test/ui/consts/inline_asm.stderr | 2 +- src/test/ui/consts/int_ptr_for_zst_slices.rs | 4 +- src/test/ui/{issues => consts}/issue-13902.rs | 0 src/test/ui/{issues => consts}/issue-17074.rs | 0 src/test/ui/{issues => consts}/issue-18294.rs | 0 .../ui/{issues => consts}/issue-18294.stderr | 0 .../issue-23968-const-not-overflow.rs | 0 .../issue-37550-1.rs} | 0 .../issue-37550-1.stderr} | 2 +- src/test/ui/{issues => consts}/issue-37991.rs | 0 src/test/ui/consts/issue-90878-2.rs | 10 + src/test/ui/consts/issue-90878-2.stderr | 14 + src/test/ui/consts/issue-90878-3.rs | 6 + src/test/ui/consts/issue-90878-3.stderr | 11 + src/test/ui/consts/issue-90878.rs | 4 + src/test/ui/consts/issue-90878.stderr | 11 + src/test/ui/consts/issue-miri-1910.rs | 12 + src/test/ui/consts/issue-miri-1910.stderr | 26 + .../allow_raw_ptr_dereference_const_fn.rs | 1 - .../min_const_fn/min_const_fn_unsafe_bad.rs | 6 +- .../min_const_fn_unsafe_bad.stderr | 18 +- .../const_refers_to_static.stderr | 5 - .../const_refers_to_static2.32bit.stderr | 5 - .../const_refers_to_static2.64bit.stderr | 5 - .../ui/consts/non-const-value-in-const.rs | 7 + .../ui/consts/non-const-value-in-const.stderr | 20 + src/test/ui/consts/offset_from.rs | 1 - src/test/ui/consts/offset_from_ub.rs | 1 - src/test/ui/consts/offset_from_ub.stderr | 12 +- .../ui/consts/precise-drop-with-promoted.rs | 9 + src/test/ui/consts/promote-not.rs | 15 + src/test/ui/consts/promote-not.stderr | 94 +- src/test/ui/consts/promoted-const-drop.rs | 15 + src/test/ui/consts/promoted-const-drop.stderr | 24 + src/test/ui/consts/promoted-storage.rs | 20 + src/test/ui/consts/ptr_comparisons.rs | 1 - src/test/ui/consts/ptr_comparisons.stderr | 10 +- .../consts/qualif-indirect-mutation-fail.rs | 64 + .../qualif-indirect-mutation-fail.stderr | 57 + .../consts/qualif-indirect-mutation-pass.rs | 24 + src/test/ui/consts/qualif-union.rs | 32 + src/test/ui/consts/qualif-union.stderr | 57 + src/test/ui/consts/validate_never_arrays.rs | 2 +- .../write_to_mut_ref_dest.mut_refs.stderr | 12 - src/test/ui/consts/write_to_mut_ref_dest.rs | 3 +- .../consts/write_to_mut_ref_dest.stock.stderr | 10 +- .../ui/crate-loading/auxiliary/libfoo.rlib | 0 src/test/ui/crate-loading/invalid-rlib.rs | 8 + src/test/ui/crate-loading/invalid-rlib.stderr | 11 + src/test/ui/cross/cross-fn-cache-hole.rs | 4 +- src/test/ui/cross/cross-fn-cache-hole.stderr | 12 +- src/test/ui/deprecation/deprecation-lint.rs | 1 + .../ui/deprecation/deprecation-lint.stderr | 81 +- .../ui/deprecation/invalid-literal.stderr | 8 +- .../{ => deprecation}/try-macro-suggestion.rs | 0 .../try-macro-suggestion.stderr | 0 .../derives/derive-assoc-type-not-impl.stderr | 10 +- ...ives-span-Clone-enum-struct-variant.stderr | 5 - .../ui/derives/derives-span-Clone-enum.stderr | 5 - .../derives/derives-span-Clone-struct.stderr | 5 - .../derives-span-Clone-tuple-struct.stderr | 5 - .../derives-span-Default-struct.stderr | 5 - .../derives-span-Default-tuple-struct.stderr | 5 - ...rives-span-Hash-enum-struct-variant.stderr | 5 - .../ui/derives/derives-span-Hash-enum.stderr | 5 - .../derives/derives-span-Hash-struct.stderr | 5 - .../derives-span-Hash-tuple-struct.stderr | 5 - ...erives-span-Ord-enum-struct-variant.stderr | 5 - .../ui/derives/derives-span-Ord-enum.stderr | 5 - .../ui/derives/derives-span-Ord-struct.stderr | 5 - .../derives-span-Ord-tuple-struct.stderr | 5 - ...span-PartialOrd-enum-struct-variant.stderr | 5 - .../derives-span-PartialOrd-enum.stderr | 5 - .../derives-span-PartialOrd-struct.stderr | 5 - ...erives-span-PartialOrd-tuple-struct.stderr | 5 - src/test/ui/derives/deriving-copyclone.stderr | 6 +- ...eriving-no-inner-impl-error-message.stderr | 5 - .../ui/{issues => deriving}/issue-19358.rs | 0 .../ui/{issues => deriving}/issue-58319.rs | 0 .../ui/did_you_mean/compatible-variants.rs | 43 + .../did_you_mean/compatible-variants.stderr | 137 + .../issue-39802-show-5-trait-impls.stderr | 15 - src/test/ui/did_you_mean/issue-42764.rs | 2 +- src/test/ui/did_you_mean/issue-42764.stderr | 6 +- .../ui/{ => drop}/auxiliary/inline_dtor.rs | 0 src/test/ui/{issues => drop}/issue-35546.rs | 0 .../drop/issue-90752-raw-ptr-shenanigans.rs | 41 + src/test/ui/drop/issue-90752.rs | 32 + .../ui/{ => drop}/terminate-in-initializer.rs | 0 src/test/ui/{ => drop}/use_inline_dtor.rs | 0 .../{ => dropck}/cleanup-arm-conditional.rs | 0 src/test/ui/dropck/drop-on-non-struct.stderr | 12 +- .../issue-28498-ugeh-with-passed-to-fn.rs | 0 src/test/ui/dst/dst-bad-assign-3.stderr | 4 +- src/test/ui/dst/dst-bad-assign.stderr | 4 +- .../ui/editions/dyn-trait-sugg-2021.stderr | 4 +- .../edition-keywords-2015-2015.rs | 0 .../edition-keywords-2015-2018.rs | 0 .../edition-keywords-2018-2015.rs | 0 .../edition-keywords-2018-2018.rs | 0 .../ui/{ => editions}/epoch-gate-feature.rs | 0 src/test/ui/empty/empty-attributes.rs | 14 + src/test/ui/empty/empty-attributes.stderr | 63 + .../ui/empty/empty-struct-unit-expr.stderr | 14 +- .../ui/entry-point/imported_main_conflict.rs | 2 +- .../entry-point/imported_main_conflict.stderr | 3 +- ...d_main_const_fn_item_type_forbidden.stderr | 2 +- .../arbitrary_enum_discriminant.rs | 2 +- .../issue-51582.rs | 0 src/test/ui/{issues => enum}/issue-42747.rs | 0 src/test/ui/error-codes/E0070.rs | 1 - src/test/ui/error-codes/E0070.stderr | 11 +- src/test/ui/error-codes/E0117.stderr | 12 +- src/test/ui/error-codes/E0206.rs | 6 - src/test/ui/error-codes/E0206.stderr | 24 +- src/test/ui/error-codes/E0275.stderr | 5 - src/test/ui/error-codes/E0276.stderr | 4 +- src/test/ui/error-codes/E0283.stderr | 14 +- src/test/ui/error-codes/E0365.rs | 2 +- src/test/ui/error-codes/E0365.stderr | 4 +- src/test/ui/error-codes/E0396-fixed.rs | 4 +- src/test/ui/error-codes/E0396.rs | 12 +- src/test/ui/error-codes/E0396.stderr | 24 +- src/test/ui/error-codes/E0618.stderr | 7 +- src/test/ui/error-codes/E0637.rs | 18 +- src/test/ui/error-codes/E0637.stderr | 31 +- src/test/ui/error-codes/E0659.stderr | 3 +- src/test/ui/error-codes/e0119/complex-impl.rs | 1 - .../ui/error-codes/e0119/complex-impl.stderr | 15 +- src/test/ui/error-codes/e0119/issue-28981.rs | 1 - .../ui/error-codes/e0119/issue-28981.stderr | 15 +- src/test/ui/estr-uniq.rs | 15 - src/test/ui/export-import.rs | 11 - src/test/ui/export-import.stderr | 15 - src/test/ui/export-non-interference2.rs | 11 - src/test/ui/export-non-interference3.rs | 11 - src/test/ui/export.rs | 10 - src/test/ui/export.stderr | 40 - src/test/ui/export2.rs | 11 - src/test/ui/export2.stderr | 9 - src/test/ui/expr-block-slot.rs | 13 - src/test/ui/expr-block-unique.rs | 4 - src/test/ui/{ => expr/if}/expr-if.rs | 0 .../ruby_style_closure.stderr | 5 + .../auxiliary/no-mangle-associated-fn.rs | 0 .../auxiliary/reexport-should-still-link.rs | 0 src/test/ui/extern/extern-methods.rs | 2 +- src/test/ui/extern/extern-thiscall.rs | 2 +- src/test/ui/extern/extern-vectorcall.rs | 2 +- .../{issues => extern}/issue-28324.mir.stderr | 0 src/test/ui/{issues => extern}/issue-28324.rs | 0 .../issue-28324.thir.stderr | 0 .../{ => extern}/no-mangle-associated-fn.rs | 0 .../feature-gates/feature-gate-asm_const.rs | 10 + .../feature-gate-asm_const.stderr | 12 + .../feature-gate-asm_experimental_arch.rs | 21 + .../feature-gate-asm_experimental_arch.stderr | 12 + .../ui/feature-gates/feature-gate-asm_sym.rs | 10 + .../feature-gates/feature-gate-asm_sym.stderr | 12 + ...feature-gate-associated_type_bounds.stderr | 7 - .../feature-gates/feature-gate-doc_keyword.rs | 5 - .../feature-gate-doc_keyword.stderr | 12 - .../feature-gate-inline_const_pat.rs | 4 + .../feature-gate-inline_const_pat.stderr | 12 + .../feature-gate-relaxed_struct_unsize.rs | 10 - .../feature-gate-relaxed_struct_unsize.stderr | 14 - .../feature-gate-rustdoc_internals.rs | 5 + .../feature-gate-rustdoc_internals.stderr | 12 + .../feature-gate-trivial_bounds.stderr | 76 +- .../feature-gate-untagged_unions.stderr | 14 +- .../{ => feature-gates}/gated-bad-feature.rs | 0 .../gated-bad-feature.stderr | 0 ...sue-43106-gating-of-builtin-attrs-error.rs | 23 + ...43106-gating-of-builtin-attrs-error.stderr | 45 +- .../issue-43106-gating-of-builtin-attrs.rs | 13 - ...issue-43106-gating-of-builtin-attrs.stderr | 204 +- .../issue-43106-gating-of-macro_use.stderr | 4 +- .../ui/{ => feature-gates}/stable-features.rs | 0 .../stable-features.stderr | 0 .../fmt/feature-gate-format-args-capture.rs | 6 - .../feature-gate-format-args-capture.stderr | 18 - .../fmt/format-args-capture-macro-hygiene.rs | 2 - .../format-args-capture-macro-hygiene.stderr | 4 +- .../format-args-capture-missing-variables.rs | 2 - ...rmat-args-capture-missing-variables.stderr | 14 +- src/test/ui/fmt/format-args-capture.rs | 1 - src/test/ui/fmt/ifmt-bad-arg.rs | 10 +- src/test/ui/fmt/ifmt-bad-arg.stderr | 73 +- src/test/ui/fmt/ifmt-unimpl.stderr | 5 - src/test/ui/{ => fn}/expr-fn.rs | 0 src/test/ui/{ => fn}/fun-call-variants.rs | 0 .../nested-function-names-issue-8587.rs | 0 .../break-outside-loop.rs | 0 .../break-outside-loop.stderr | 0 .../break-while-condition.rs | 0 .../break-while-condition.stderr | 0 .../{issues => for-loop-while}/issue-51345.rs | 0 .../ui/{ => for-loop-while}/long-while.rs | 0 .../while-let-2.rs} | 0 .../while-let-2.stderr} | 6 +- src/test/ui/for/for-c-in-str.rs | 2 - src/test/ui/for/for-c-in-str.stderr | 5 - src/test/ui/for/for-loop-bogosity.stderr | 5 - ...for-loop-unconstrained-element-type.stderr | 6 +- .../ui/{ => foreign}/nil-decl-in-foreign.rs | 0 .../fully-qualified-type-name1.rs | 8 +- .../fully-qualified-type-name1.stderr | 15 +- .../fully-qualified-type-name4.stderr | 9 +- ...function-pointer-comparison-issue-54685.rs | 1 - .../generator-region-requirements.nll.stderr | 11 + .../generator-region-requirements.rs | 2 +- .../generator-region-requirements.stderr | 14 +- src/test/ui/generator/issue-68112.stderr | 8 +- ...yield-outside-generator-issue-78653.stderr | 5 - .../collections-project-default.rs | 2 +- .../generic-associated-types/collections.rs | 2 +- .../generic-associated-type-bounds.rs | 2 +- .../impl_bounds.stderr | 4 +- .../generic-associated-types/issue-70303.rs | 2 +- .../generic-associated-types/issue-76535.rs | 2 +- .../issue-76535.stderr | 6 +- .../generic-associated-types/issue-79422.rs | 4 +- .../issue-79422.stderr | 6 +- .../generic-associated-types/issue-85921.rs | 19 + .../issue-86483.stderr | 3 +- .../generic-associated-types/issue-86787.rs | 5 +- .../issue-86787.stderr | 36 +- .../generic-associated-types/issue-87258_a.rs | 24 + .../issue-87258_a.stderr | 11 + .../generic-associated-types/issue-87258_b.rs | 26 + .../issue-87258_b.stderr | 11 + .../generic-associated-types/issue-88287.rs | 4 +- .../generic-associated-types/issue-88360.rs | 3 +- .../issue-88360.stderr | 2 +- .../generic-associated-types/issue-88459.rs | 19 + .../generic-associated-types/issue-88595.rs | 24 + .../issue-88595.stderr | 40 + .../generic-associated-types/issue-90014.rs | 22 + .../issue-90014.stderr | 15 + .../method-unsatified-assoc-type-predicate.rs | 2 +- ...hod-unsatified-assoc-type-predicate.stderr | 11 +- ...ojection-type-lifetime-mismatch.nll.stderr | 26 + .../projection-type-lifetime-mismatch.rs | 8 +- .../projection-type-lifetime-mismatch.stderr | 26 +- .../self-outlives-lint.rs | 173 + .../self-outlives-lint.stderr | 98 + .../streaming_iterator.rs | 8 +- .../variance_constraints.rs | 2 +- src/test/ui/{ => generics}/autobind.rs | 0 .../ui/{issues => generics}/issue-1112.rs | 0 src/test/ui/{issues => generics}/issue-333.rs | 0 .../ui/{issues => generics}/issue-59508-1.rs | 0 .../{issues => generics}/issue-59508-1.stderr | 0 .../ui/{issues => generics}/issue-59508.fixed | 0 .../ui/{issues => generics}/issue-59508.rs | 0 .../{issues => generics}/issue-59508.stderr | 0 .../lifetime-before-type-params.rs | 0 .../lifetime-before-type-params.stderr | 0 .../{ => generics}/type-params-in-for-each.rs | 0 .../range_pat_interactions0.rs | 2 +- .../range_pat_interactions3.rs | 2 +- .../range_pat_interactions3.stderr | 4 +- src/test/ui/hello2021.rs | 1 - .../issue-60283.rs | 0 .../issue-60283.stderr | 0 .../normalize-under-binder}/issue-44005.rs | 3 +- .../normalize-under-binder/issue-56556.rs | 13 + .../normalize-under-binder/issue-62529-1.rs | 2 +- .../issue-62529-1.stderr | 31 +- .../normalize-under-binder/issue-70120.rs | 4 +- .../normalize-under-binder/issue-70120.stderr | 20 - .../issue-71955.migrate.stderr | 92 + .../issue-71955.nll.stderr | 8 + .../normalize-under-binder/issue-71955.rs | 64 + .../normalize-under-binder/issue-74261.rs | 30 + .../normalize-under-binder/issue-76956.rs | 15 + .../normalize-under-binder/issue-90612.rs | 43 + .../normalize-under-binder/issue-90638.rs | 37 + src/test/ui/hrtb/issue-30786.migrate.stderr | 30 +- src/test/ui/hrtb/issue-30786.nll.stderr | 30 +- src/test/ui/hrtb/issue-62203-hrtb-ice.rs | 2 +- src/test/ui/hrtb/issue-62203-hrtb-ice.stderr | 36 +- src/test/ui/hrtb/issue-90177.rs | 32 + src/test/ui/hygiene/auxiliary/fields.rs | 73 + src/test/ui/hygiene/auxiliary/methods.rs | 160 + src/test/ui/hygiene/auxiliary/pub_hygiene.rs | 7 + src/test/ui/hygiene/auxiliary/use_by_macro.rs | 15 + src/test/ui/hygiene/auxiliary/variants.rs | 36 + .../ui/hygiene/cross-crate-define-and-use.rs | 19 + src/test/ui/hygiene/cross-crate-fields.rs | 24 + .../ui/hygiene/cross-crate-glob-hygiene.rs | 23 + .../hygiene/cross-crate-glob-hygiene.stderr | 11 + src/test/ui/hygiene/cross-crate-methods.rs | 33 + .../ui/hygiene/cross-crate-name-collision.rs | 12 + .../ui/hygiene/cross-crate-name-hiding-2.rs | 15 + .../hygiene/cross-crate-name-hiding-2.stderr | 9 + .../ui/hygiene/cross-crate-name-hiding.rs | 13 + .../ui/hygiene/cross-crate-name-hiding.stderr | 9 + src/test/ui/hygiene/cross-crate-redefine.rs | 14 + .../ui/hygiene/cross-crate-redefine.stderr | 15 + src/test/ui/hygiene/cross-crate-variants.rs | 18 + src/test/ui/hygiene/cross_crate_hygiene.rs | 8 - .../ui/{ => hygiene}/lambda-var-hygiene.rs | 0 .../hygiene/rustc-macro-transparency.stderr | 16 +- .../thread-local-not-in-prelude.rs | 0 .../ui/impl-trait/auto-trait-leak2.stderr | 24 +- src/test/ui/impl-trait/equality.rs | 2 +- src/test/ui/impl-trait/equality.stderr | 19 +- .../feature-gate.stderr | 3 + .../ui/impl-trait/impl-trait-in-macro.stderr | 2 + .../ui/{issues => impl-trait}/issue-49579.rs | 0 .../ui/{issues => impl-trait}/issue-49685.rs | 0 .../ui/{issues => impl-trait}/issue-51185.rs | 0 src/test/ui/impl-trait/issue-55872-1.stderr | 4 +- src/test/ui/impl-trait/issue-55872-2.rs | 2 +- src/test/ui/impl-trait/issue-55872-2.stderr | 4 +- src/test/ui/impl-trait/issue-72911.stderr | 8 +- src/test/ui/impl-trait/issue-87450.stderr | 4 +- .../ui/impl-trait/issues/issue-78722.stderr | 4 +- .../issues/universal-issue-48703.stderr | 3 + ...sal-turbofish-in-method-issue-50950.stderr | 3 + .../ordinary-bounds-unrelated.nll.stderr | 16 - .../ordinary-bounds-unrelated.stderr | 11 +- .../ordinary-bounds-unsuited.nll.stderr | 16 - .../ordinary-bounds-unsuited.stderr | 11 +- ...t_outlive_least_region_or_bound.nll.stderr | 49 +- .../must_outlive_least_region_or_bound.rs | 9 +- .../must_outlive_least_region_or_bound.stderr | 98 +- .../no-method-suggested-traits.stderr | 8 +- .../static-return-lifetime-infered.nll.stderr | 28 - .../static-return-lifetime-infered.rs | 8 +- .../static-return-lifetime-infered.stderr | 58 +- .../universal-two-impl-traits.stderr | 1 + src/test/ui/impl-trait/where-allowed.rs | 1 + src/test/ui/impl-trait/where-allowed.stderr | 22 +- .../absolute-paths-in-nested-use-groups.rs | 0 ...absolute-paths-in-nested-use-groups.stderr | 0 src/test/ui/imports/duplicate.stderr | 9 +- src/test/ui/{ => imports}/export-multi.rs | 0 ...e-extern-crate-restricted-shadowing.stderr | 3 +- src/test/ui/{ => imports}/glob-cycles.rs | 0 src/test/ui/imports/glob-shadowing.stderr | 9 +- src/test/ui/imports/issue-53269.stderr | 3 +- src/test/ui/imports/issue-55884-1.stderr | 3 +- src/test/ui/imports/issue-56125.stderr | 9 +- src/test/ui/imports/issue-57539.stderr | 3 +- .../local-modularized-tricky-fail-1.stderr | 12 +- src/test/ui/imports/macro-paths.stderr | 6 +- src/test/ui/imports/macros.stderr | 9 +- src/test/ui/{ => imports}/no-std-inject.rs | 0 .../ui/{ => imports}/no-std-inject.stderr | 0 src/test/ui/{ => imports}/reexport-star.rs | 0 .../ui/imports/rfc-1560-warning-cycle.stderr | 3 +- .../ui/imports/shadow_builtin_macros.stderr | 12 +- src/test/ui/{ => imports}/use-mod.rs | 0 .../in-band-lifetimes.rs | 0 .../mismatched_trait_impl-2.stderr | 8 +- .../mismatched_trait_impl.nll.stderr | 8 +- .../mismatched_trait_impl.stderr | 8 +- .../auxiliary/inference_unstable_iterator.rs | 17 + .../auxiliary/inference_unstable_itertools.rs | 14 + src/test/ui/inference/inference_unstable.rs | 9 + .../ui/inference/inference_unstable.stderr | 37 +- src/test/ui/inference/issue-71732.stderr | 14 +- src/test/ui/inference/issue-72616.stderr | 6 +- .../lub-glb-with-unbound-infer-var.rs | 0 .../{ => inference}/newlambdas-ret-infer.rs | 0 .../{ => inference}/newlambdas-ret-infer2.rs | 0 .../question-mark-type-infer.rs | 0 .../question-mark-type-infer.stderr | 0 .../ui/{ => inference}/range-type-infer.rs | 0 src/test/ui/{ => inference}/simple-infer.rs | 0 .../tutorial-suffix-inference-test.rs | 0 .../tutorial-suffix-inference-test.stderr | 0 .../type-infer-generalize-ty-var.rs | 0 .../ui/inline-const/const-expr-array-init.rs | 1 - src/test/ui/inline-const/const-expr-basic.rs | 2 +- .../ui/inline-const/const-expr-inference.rs | 11 + .../inline-const/const-expr-lifetime-err.rs | 29 + .../const-expr-lifetime-err.stderr | 18 + .../ui/inline-const/const-expr-lifetime.rs | 35 + src/test/ui/inline-const/const-expr-macro.rs | 2 +- .../ui/inline-const/const-expr-reference.rs | 1 - .../inline-const/const-match-pat-generic.rs | 2 +- .../inline-const/const-match-pat-inference.rs | 12 + .../const-match-pat-lifetime-err.rs | 34 + .../inline-const/const-match-pat-lifetime.rs | 37 + .../ui/inline-const/const-match-pat-range.rs | 2 +- src/test/ui/inline-const/const-match-pat.rs | 2 +- .../ui/integral-variable-unification-error.rs | 6 +- ...integral-variable-unification-error.stderr | 7 +- .../ui/intrinsics/const-eval-select-bad.rs | 1 + .../intrinsics/const-eval-select-bad.stderr | 32 +- src/test/ui/intrinsics/intrinsic-alignment.rs | 1 + src/test/ui/issues/issue-13407.rs | 1 - src/test/ui/issues/issue-13407.stderr | 10 +- src/test/ui/issues/issue-14853.stderr | 4 +- src/test/ui/issues/issue-17651.stderr | 6 +- src/test/ui/issues/issue-18611.stderr | 6 - src/test/ui/issues/issue-18937.rs | 4 +- src/test/ui/issues/issue-18937.stderr | 10 +- src/test/ui/issues/issue-20162.stderr | 6 + src/test/ui/issues/issue-20261.stderr | 4 +- src/test/ui/issues/issue-20413.stderr | 30 - src/test/ui/issues/issue-20605.stderr | 5 - src/test/ui/issues/issue-21160.stderr | 5 - src/test/ui/issues/issue-21974.stderr | 5 - src/test/ui/issues/issue-22933-2.stderr | 5 +- src/test/ui/issues/issue-23966.stderr | 5 + src/test/ui/issues/issue-24424.stderr | 5 - src/test/ui/issues/issue-2444.rs | 17 - src/test/ui/issues/issue-2748-b.rs | 11 - src/test/ui/issues/issue-28098.stderr | 30 - src/test/ui/issues/issue-29147.stderr | 11 +- src/test/ui/issues/issue-2951.stderr | 1 + src/test/ui/issues/issue-31173.rs | 2 - src/test/ui/issues/issue-31173.stderr | 13 +- src/test/ui/issues/issue-31299.rs | 1 + src/test/ui/issues/issue-3211.rs | 7 - src/test/ui/issues/issue-32709.stderr | 5 - src/test/ui/issues/issue-33941.rs | 1 - src/test/ui/issues/issue-33941.stderr | 29 +- src/test/ui/issues/issue-34229.stderr | 5 - src/test/ui/issues/issue-34334.stderr | 5 + src/test/ui/issues/issue-39970.stderr | 5 - src/test/ui/issues/issue-40827.stderr | 12 +- src/test/ui/issues/issue-41974.rs | 6 +- src/test/ui/issues/issue-41974.stderr | 27 +- src/test/ui/issues/issue-44005.stderr | 20 - src/test/ui/issues/issue-4401.rs | 7 - src/test/ui/issues/issue-46983.nll.stderr | 10 + src/test/ui/issues/issue-46983.rs | 2 +- src/test/ui/issues/issue-46983.stderr | 8 +- src/test/ui/issues/issue-47706-trait.stderr | 6 + src/test/ui/issues/issue-47706.stderr | 6 + src/test/ui/issues/issue-50993.rs | 9 - src/test/ui/issues/issue-50993.stderr | 4 - ...1632-try-desugar-incompatible-types.stderr | 4 +- src/test/ui/issues/issue-53348.rs | 2 +- src/test/ui/issues/issue-53348.stderr | 3 + src/test/ui/issues/issue-5358-1.stderr | 4 + src/test/ui/issues/issue-54954.stderr | 5 - src/test/ui/issues/issue-58022.stderr | 5 - src/test/ui/issues/issue-59494.rs | 2 +- src/test/ui/issues/issue-59494.stderr | 6 +- src/test/ui/issues/issue-66353.stderr | 6 - ...e-66923-show-error-for-correct-call.stderr | 10 + .../issue-69225-SCEVAddExpr-wrap-flag.rs | 1 - src/test/ui/issues/issue-69455.rs | 1 + src/test/ui/issues/issue-69455.stderr | 24 +- src/test/ui/issues/issue-69683.rs | 1 + src/test/ui/issues/issue-69683.stderr | 28 +- src/test/ui/issues/issue-7246.rs | 1 + src/test/ui/issues/issue-7246.stderr | 10 +- src/test/ui/issues/issue-72690.rs | 9 + src/test/ui/issues/issue-72690.stderr | 203 +- src/test/ui/issues/issue-73427.stderr | 8 +- src/test/ui/issues/issue-77218.rs | 11 - src/test/ui/issues/issue-77218.stderr | 40 - .../ui/issues/issue-77218/issue-77218-2.fixed | 7 + .../ui/issues/issue-77218/issue-77218-2.rs | 7 + .../issues/issue-77218/issue-77218-2.stderr | 16 + .../ui/issues/issue-77218/issue-77218.fixed | 6 + src/test/ui/issues/issue-77218/issue-77218.rs | 6 + .../ui/issues/issue-77218/issue-77218.stderr | 18 + src/test/ui/issues/issue-811.rs | 26 - src/test/ui/iterators/integral.stderr | 60 - .../ui/iterators/into-iter-on-arrays-2021.rs | 1 - src/test/ui/iterators/ranges.stderr | 10 - src/test/ui/iterators/rsplit-clone.rs | 11 + src/test/ui/iterators/string.stderr | 10 - src/test/ui/keyword-changes-2012-07-31.rs | 20 - .../ui/{issues => lang-items}/issue-19660.rs | 0 .../{issues => lang-items}/issue-19660.stderr | 0 .../ui/{issues => lang-items}/issue-31076.rs | 0 .../{issues => lang-items}/issue-31076.stderr | 0 src/test/ui/lang-items/issue-87573.rs | 28 + src/test/ui/lang-items/issue-87573.stderr | 21 + .../no_owned_box_lang_item.rs | 0 .../no_owned_box_lang_item.stderr | 0 .../ui/{ => lang-items}/required-lang-item.rs | 0 .../required-lang-item.stderr | 0 src/test/ui/layout/debug.stderr | 634 +- src/test/ui/layout/hexagon-enum.stderr | 820 +- src/test/ui/layout/thumb-enum.stderr | 820 +- src/test/ui/leak-unique-as-tydesc.rs | 9 - src/test/ui/let-else/issue-89960.rs | 7 + src/test/ui/let-else/issue-89960.stderr | 12 + .../let-else/let-else-bool-binop-init.stderr | 4 +- .../let-else-brace-before-else.stderr | 8 +- src/test/ui/let-else/let-else-if.rs | 10 + src/test/ui/let-else/let-else-if.stderr | 18 + .../lex-bad-binary-literal.rs | 0 .../lex-bad-binary-literal.stderr | 0 .../lex-bad-char-literals-1.rs | 0 .../lex-bad-char-literals-1.stderr | 0 .../lex-bad-char-literals-2.rs | 0 .../lex-bad-char-literals-2.stderr | 0 .../lex-bad-char-literals-3.rs | 0 .../lex-bad-char-literals-3.stderr | 0 .../lex-bad-char-literals-4.rs | 0 .../lex-bad-char-literals-4.stderr | 0 .../lex-bad-char-literals-5.rs | 0 .../lex-bad-char-literals-5.stderr | 0 .../lex-bad-char-literals-6.rs | 0 .../lex-bad-char-literals-6.stderr | 0 .../lex-bad-char-literals-7.rs | 0 .../lex-bad-char-literals-7.stderr | 0 .../lex-bad-numeric-literals.rs | 0 .../lex-bad-numeric-literals.stderr | 0 .../lex-bad-octal-literal.rs | 0 .../lex-bad-octal-literal.stderr | 0 .../ui/{parser => lexer}/lex-bad-token.rs | 0 .../ui/{parser => lexer}/lex-bad-token.stderr | 0 .../lex-bare-cr-nondoc-comment.rs | 0 .../lex-bare-cr-string-literal-doc-comment.rs | 0 ...-bare-cr-string-literal-doc-comment.stderr | 0 .../{parser => lexer}/lex-stray-backslash.rs | 0 .../lex-stray-backslash.stderr | 0 ...line-endings-string-literal-doc-comment.rs | 0 .../ui/{issues => lifetimes}/issue-26638.rs | 0 .../{issues => lifetimes}/issue-26638.stderr | 0 src/test/ui/lifetimes/issue-34979.stderr | 5 - .../issue-90170-elision-mismatch.fixed | 9 + .../issue-90170-elision-mismatch.nll.stderr | 29 + .../lifetimes/issue-90170-elision-mismatch.rs | 9 + .../issue-90170-elision-mismatch.stderr | 45 + ...expected-return-static-indirect.nll.stderr | 24 + ...e-90600-expected-return-static-indirect.rs | 14 + ...600-expected-return-static-indirect.stderr | 14 + .../ex3-both-anon-regions-2.stderr | 6 + .../ex3-both-anon-regions-3.stderr | 12 + ...x3-both-anon-regions-using-fn-items.stderr | 6 + ...th-anon-regions-using-trait-objects.stderr | 6 + .../ex3-both-anon-regions.stderr | 6 + ...ime-mismatch-between-trait-and-impl.stderr | 8 +- .../link-cfg-works-transitive-dylib.rs | 0 .../link-cfg-works-transitive-rlib.rs | 0 .../{ => linkage-attr}/auxiliary/linkage1.rs | 0 .../ui/{ => linkage-attr}/link-cfg-works.rs | 0 src/test/ui/{ => linkage-attr}/linkage1.rs | 0 src/test/ui/lint/crate_level_only_lint.rs | 3 + src/test/ui/lint/crate_level_only_lint.stderr | 28 +- .../ui/lint/dead-code/anon-const-in-pat.rs | 2 +- src/test/ui/lint/forbid-group-group-2.rs | 6 + src/test/ui/lint/forbid-group-group-2.stderr | 38 +- .../allowed-cli-deny-by-default-lint.rs | 2 +- ...-group-allowed-cli-warn-by-default-lint.rs | 2 +- .../warn-by-default-lint-two-modules.rs | 2 +- .../ui/lint/force-warn/warnings-lint-group.rs | 2 +- .../force-warn/warnings-lint-group.stderr | 4 +- src/test/ui/{issues => lint}/issue-14837.rs | 0 src/test/ui/{issues => lint}/issue-57410-1.rs | 0 src/test/ui/{issues => lint}/issue-63364.rs | 0 .../ui/{issues => lint}/issue-63364.stderr | 0 src/test/ui/{ => lint}/lint-cap.rs | 0 src/test/ui/lint/lint-ctypes-73251-2.rs | 2 +- src/test/ui/lint/lint-ctypes-73251-2.stderr | 2 +- .../ui/lint/lint-forbid-internal-unsafe.rs | 1 + .../lint/lint-forbid-internal-unsafe.stderr | 10 +- src/test/ui/lint/opaque-ty-ffi-unsafe.rs | 2 +- src/test/ui/lint/opaque-ty-ffi-unsafe.stderr | 2 +- .../lint-uncommon-codepoints.rs | 1 + .../lint-uncommon-codepoints.stderr | 14 +- ...est-allow-dead-extern-static-no-warning.rs | 0 .../ui/{ => lint}/unnecessary-extern-crate.rs | 0 .../unnecessary-extern-crate.stderr | 0 src/test/ui/lint/unused/issue-70041.stderr | 11 +- src/test/ui/lint/unused/unused-async.rs | 43 + src/test/ui/lint/unused/unused-async.stderr | 26 + .../ui/lint/unused/unused-attr-duplicate.rs | 108 + .../lint/unused/unused-attr-duplicate.stderr | 306 + .../ui/lint/unused/unused-macro-rules.stderr | 35 +- src/test/ui/lint/unused/unused-macro.stderr | 30 +- .../lint/unused_parens_json_suggestion.fixed | 2 +- .../ui/lint/unused_parens_json_suggestion.rs | 2 +- .../lint/unused_parens_json_suggestion.stderr | 2 +- ...unused_parens_remove_json_suggestion.fixed | 2 +- .../unused_parens_remove_json_suggestion.rs | 2 +- ...nused_parens_remove_json_suggestion.stderr | 18 +- src/test/ui/{ => lint}/warn-ctypes-inhibit.rs | 0 src/test/ui/{ => lint}/warn-path-statement.rs | 0 .../ui/{ => lint}/warn-path-statement.stderr | 0 .../liveness-assign-imm-local-after-ret.rs | 0 .../ui/{issues => llvm-asm}/issue-23458.rs | 0 .../{issues => llvm-asm}/issue-23458.stderr | 0 .../ui/{issues => llvm-asm}/issue-37366.rs | 0 .../issue-53787-inline-assembler-macro.rs | 0 .../issue-53787-inline-assembler-macro.stderr | 0 src/test/ui/{thinlto => lto}/all-crates.rs | 0 .../{ => lto}/auxiliary/debuginfo-lto-aux.rs | 0 .../ui/{thinlto => lto}/auxiliary/dylib.rs | 0 .../auxiliary/lto-duplicate-symbols1.rs | 0 .../auxiliary/lto-duplicate-symbols2.rs | 0 .../lto-rustc-loads-linker-plugin.rs | 0 .../auxiliary/msvc-imp-present.rs | 0 .../auxiliary/thin-lto-inlines-aux.rs | 0 src/test/ui/{ => lto}/debuginfo-lto.rs | 0 src/test/ui/{thinlto => lto}/dylib-works.rs | 0 src/test/ui/{ => lto}/fat-lto.rs | 0 .../{ => lto}/lto-and-no-bitcode-in-rlib.rs | 0 .../lto-and-no-bitcode-in-rlib.stderr | 0 .../ui/{ => lto}/lto-duplicate-symbols.rs | 0 .../ui/{ => lto}/lto-duplicate-symbols.stderr | 0 .../ui/{ => lto}/lto-many-codegen-units.rs | 0 src/test/ui/{ => lto}/lto-opt-level-s.rs | 0 src/test/ui/{ => lto}/lto-opt-level-z.rs | 0 .../lto-rustc-loads-linker-plugin.rs | 0 .../{ => lto}/lto-still-runs-thread-dtors.rs | 0 .../lto-thin-rustc-loads-linker-plugin.rs | 0 .../ui/{thinlto => lto}/msvc-imp-present.rs | 0 .../ui/{ => lto}/thin-lto-global-allocator.rs | 0 .../ui/{thinlto => lto}/thin-lto-inlines.rs | 0 .../ui/{thinlto => lto}/thin-lto-inlines2.rs | 0 src/test/ui/{thinlto => lto}/weak-works.rs | 0 .../macros/ambiguity-legacy-vs-modern.stderr | 6 +- .../auxiliary/issue-19163.rs | 0 .../{ => macros}/auxiliary/proc_macro_def.rs | 0 src/test/ui/{ => macros}/concat.rs | 0 src/test/ui/{ => macros}/concat.stderr | 0 .../include-single-expr-helper-1.rs | 0 .../include-single-expr-helper.rs | 0 .../ui/{ => macros}/include-single-expr.rs | 0 .../{ => macros}/include-single-expr.stderr | 0 src/test/ui/{issues => macros}/issue-16098.rs | 0 .../ui/{issues => macros}/issue-16098.stderr | 0 src/test/ui/{issues => macros}/issue-19163.rs | 0 .../ui/{issues => macros}/issue-19163.stderr | 0 src/test/ui/{issues => macros}/issue-21356.rs | 0 .../ui/{issues => macros}/issue-21356.stderr | 0 src/test/ui/{issues => macros}/issue-22463.rs | 0 src/test/ui/{issues => macros}/issue-29084.rs | 0 .../ui/{issues => macros}/issue-29084.stderr | 0 src/test/ui/{issues => macros}/issue-34171.rs | 0 src/test/ui/{issues => macros}/issue-37175.rs | 0 src/test/ui/{issues => macros}/issue-39388.rs | 0 .../ui/{issues => macros}/issue-39388.stderr | 0 src/test/ui/{issues => macros}/issue-40770.rs | 0 src/test/ui/{issues => macros}/issue-57597.rs | 0 .../ui/{issues => macros}/issue-57597.stderr | 0 .../ui/{issues => macros}/issue-6596-1.rs | 0 .../ui/{issues => macros}/issue-6596-1.stderr | 0 src/test/ui/{issues => macros}/issue-86865.rs | 0 .../ui/{issues => macros}/issue-86865.stderr | 0 .../macro-path-prelude-shadowing.stderr | 3 +- src/test/ui/macros/macro-shadowing.stderr | 3 +- .../ui/macros/macro-use-all-and-none.stderr | 3 +- .../ui/{ => macros}/malformed_macro_lhs.rs | 0 .../{ => macros}/malformed_macro_lhs.stderr | 0 src/test/ui/macros/missing-bang-in-decl.fixed | 16 + src/test/ui/macros/missing-bang-in-decl.rs | 16 + .../ui/macros/missing-bang-in-decl.stderr | 20 + src/test/ui/{ => macros}/no-std-macros.rs | 0 .../ui/macros/out-of-order-shadowing.stderr | 3 +- src/test/ui/{ => macros}/proc_macro.rs | 0 .../macros/restricted-shadowing-legacy.stderr | 24 +- .../macros/restricted-shadowing-modern.stderr | 18 +- .../ui/{ => macros}/trace_macros-format.rs | 0 .../{ => macros}/trace_macros-format.stderr | 0 ...lap-doesnt-conflict-with-specialization.rs | 0 ...doesnt-conflict-with-specialization.stderr | 0 ...p-permitted-for-annotated-marker-traits.rs | 0 .../marker_trait_attr/region-overlap.stderr | 22 +- src/test/ui/{issues => match}/issue-11940.rs | 0 src/test/ui/{issues => match}/issue-18060.rs | 0 src/test/ui/{issues => match}/issue-26251.rs | 0 src/test/ui/{issues => match}/issue-26996.rs | 0 src/test/ui/{issues => match}/issue-42679.rs | 0 src/test/ui/match/issue-91058.rs | 11 + src/test/ui/match/issue-91058.stderr | 11 + .../match-on-negative-integer-ranges.rs | 0 ...method-ambig-one-trait-unknown-int-type.rs | 2 +- ...od-ambig-one-trait-unknown-int-type.stderr | 19 +- .../mir-dataflow/indirect-mutation-offset.rs | 48 - .../indirect-mutation-offset.stderr | 10 - src/test/ui/{ => mir}/issue-73914.rs | 0 src/test/ui/{issues => mir}/issue-74739.rs | 0 src/test/ui/mir/mir_overflow_off.rs | 2 +- src/test/ui/mismatched_types/abridged.stderr | 18 +- .../assignment-operator-unimplemented.rs | 0 .../assignment-operator-unimplemented.stderr | 0 .../mismatched_types/closure-arg-count.stderr | 24 + .../closure-arg-type-mismatch.nll.stderr | 18 + .../closure-arg-type-mismatch.stderr | 18 + .../float-literal-inference-restrictions.rs | 0 ...loat-literal-inference-restrictions.stderr | 0 .../ui/mismatched_types/issue-36053-2.stderr | 6 + .../issue-75361-mismatched-impl.stderr | 8 +- .../ui/mismatched_types/issue-84976.stderr | 6 + .../auxiliary/issue-69725.rs | 0 .../ui/missing-trait-bounds/issue-35677.fixed | 11 + .../issue-35677.rs | 3 + .../issue-35677.stderr | 6 +- .../ui/missing-trait-bounds/issue-69725.fixed | 13 + .../issue-69725.rs | 2 + .../issue-69725.stderr | 6 +- .../missing-trait-bound-for-op.fixed | 0 .../missing-trait-bound-for-op.rs | 0 .../missing-trait-bound-for-op.stderr | 0 .../missing-trait-bounds-for-method-call.rs | 0 ...issing-trait-bounds-for-method-call.stderr | 0 src/test/ui/modules/issue-56411.rs | 2 +- src/test/ui/modules/issue-56411.stderr | 4 +- src/test/ui/moves/move-of-addr-of-mut.rs | 12 + src/test/ui/moves/move-of-addr-of-mut.stderr | 11 + src/test/ui/mut/mutable-enum-indirect.stderr | 6 +- src/test/ui/negative.rs | 8 - .../diverging-tuple-parts-39485.rs | 0 .../diverging-tuple-parts-39485.stderr | 0 ...lue-fallback-issue-66757.nofallback.stderr | 5 - src/test/ui/newtype-temporary.rs | 12 - ...region-lbr-anon-does-not-outlive-static.rs | 2 +- ...on-lbr-anon-does-not-outlive-static.stderr | 7 +- src/test/ui/nll/dont-print-desugared.stderr | 2 +- src/test/ui/nll/guarantor-issue-46974.rs | 2 +- src/test/ui/nll/guarantor-issue-46974.stderr | 10 +- src/test/ui/nll/issue-53773.stderr | 4 +- src/test/ui/nll/issue-73159-rpit-static.rs | 3 +- .../ui/nll/issue-73159-rpit-static.stderr | 7 +- src/test/ui/nll/issue-78561.rs | 23 + src/test/ui/{ => nll}/lub-if.nll.stderr | 0 src/test/ui/{ => nll}/lub-if.rs | 0 src/test/ui/{ => nll}/lub-if.stderr | 0 src/test/ui/{ => nll}/lub-match.nll.stderr | 0 src/test/ui/{ => nll}/lub-match.rs | 0 src/test/ui/{ => nll}/lub-match.stderr | 0 src/test/ui/{ => nll}/ref-suggestion.rs | 0 src/test/ui/{ => nll}/ref-suggestion.stderr | 0 .../ui/nll/ty-outlives/impl-trait-captures.rs | 2 +- .../ty-outlives/impl-trait-captures.stderr | 14 +- src/test/ui/no_send-enum.stderr | 6 +- src/test/ui/no_share-enum.stderr | 6 +- src/test/ui/non-legacy-modes.rs | 22 - .../ui/numbers-arithmetic/int-abs-overflow.rs | 2 +- .../unary-minus-suffix-inference.rs | 0 .../integer-literal-suffix-inference.rs | 0 .../integer-literal-suffix-inference.stderr | 0 ...ject-lifetime-default-default-to-static.rs | 0 ...object-lifetime-default-from-ref-struct.rs | 0 .../object-lifetime-default-from-rptr-box.rs | 0 .../object-lifetime-default-from-rptr-mut.rs | 0 ...bject-lifetime-default-from-rptr-struct.rs | 0 .../object-lifetime-default-from-rptr.rs | 0 .../object-lifetime-default-inferred.rs | 0 .../ui/on-unimplemented/bad-annotation.stderr | 4 +- .../ui/on-unimplemented/multiple-impls.stderr | 15 - src/test/ui/on-unimplemented/on-impl.stderr | 5 - src/test/ui/output-type-mismatch.stderr | 4 +- .../ui/{ => overloaded}/fixup-deref-mut.rs | 0 .../overloaded-calls-nontuple.rs | 0 .../overloaded-calls-nontuple.stderr | 0 .../issue-45152.rs => packed/issue-46152.rs} | 0 .../panics/location-detail-panic-no-column.rs | 7 + ...location-detail-panic-no-column.run.stderr | 2 + .../panics/location-detail-panic-no-file.rs | 7 + .../location-detail-panic-no-file.run.stderr | 2 + .../panics/location-detail-panic-no-line.rs | 7 + .../location-detail-panic-no-line.run.stderr | 2 + .../panics/location-detail-unwrap-no-file.rs | 8 + .../location-detail-unwrap-no-file.run.stderr | 2 + src/test/ui/paren-free.rs | 7 - ...bute-with-no-generics-in-parameter-list.rs | 0 ...-with-no-generics-in-parameter-list.stderr | 0 .../{ => parser}/bastion-of-the-turbofish.rs | 0 .../char/whitespace-character-literal.rs | 10 + .../char/whitespace-character-literal.stderr | 16 + ...onst-param-decl-on-type-instead-of-impl.rs | 15 + ...-param-decl-on-type-instead-of-impl.stderr | 47 + .../{ => parser}/dyn-trait-compatibility.rs | 0 .../dyn-trait-compatibility.stderr | 0 src/test/ui/parser/emoji-identifiers.rs | 16 + src/test/ui/parser/emoji-identifiers.stderr | 83 + .../ui/parser/fn-header-semantic-fail.stderr | 4 +- src/test/ui/parser/issue-90728.rs | 6 + src/test/ui/parser/issue-90728.stderr | 20 + .../{ => issues}/auxiliary/issue-21146-inc.rs | 0 ...971-outer-attr-following-inner-attr-ice.rs | 13 + .../parser/{ => issues}/issue-10392-2.fixed | 0 .../ui/parser/{ => issues}/issue-10392-2.rs | 0 .../parser/{ => issues}/issue-10392-2.stderr | 0 .../ui/parser/{ => issues}/issue-10392.rs | 0 .../ui/parser/{ => issues}/issue-10392.stderr | 0 .../ui/parser/{ => issues}/issue-10636-1.rs | 0 .../parser/{ => issues}/issue-10636-1.stderr | 0 .../ui/parser/{ => issues}/issue-10636-2.rs | 0 .../parser/{ => issues}/issue-10636-2.stderr | 0 .../ui/{ => parser}/issues/issue-13483.rs | 0 .../ui/{ => parser}/issues/issue-13483.stderr | 0 .../parser/{ => issues}/issue-14303-enum.rs | 0 .../{ => issues}/issue-14303-enum.stderr | 0 .../parser/{ => issues}/issue-14303-fn-def.rs | 0 .../{ => issues}/issue-14303-fn-def.stderr | 0 .../issue-14303-fncall.full.stderr | 0 .../issue-14303-fncall.generic_arg.stderr | 0 .../parser/{ => issues}/issue-14303-fncall.rs | 0 .../parser/{ => issues}/issue-14303-impl.rs | 0 .../{ => issues}/issue-14303-impl.stderr | 0 .../parser/{ => issues}/issue-14303-path.rs | 0 .../{ => issues}/issue-14303-path.stderr | 0 .../parser/{ => issues}/issue-14303-struct.rs | 0 .../{ => issues}/issue-14303-struct.stderr | 0 .../parser/{ => issues}/issue-14303-trait.rs | 0 .../{ => issues}/issue-14303-trait.stderr | 0 .../ui/parser/{ => issues}/issue-15914.rs | 0 .../ui/parser/{ => issues}/issue-15914.stderr | 0 .../ui/parser/{ => issues}/issue-15980.rs | 0 .../ui/parser/{ => issues}/issue-15980.stderr | 0 src/test/ui/parser/{ => issues}/issue-1655.rs | 0 .../ui/parser/{ => issues}/issue-1655.stderr | 0 .../ui/parser/{ => issues}/issue-17383.rs | 0 .../ui/parser/{ => issues}/issue-17383.stderr | 0 .../{ => issues}/issue-17718-const-mut.rs | 0 .../{ => issues}/issue-17718-const-mut.stderr | 0 .../ui/parser/{ => issues}/issue-17904-2.rs | 0 .../parser/{ => issues}/issue-17904-2.stderr | 0 .../ui/parser/{ => issues}/issue-17904.rs | 0 .../ui/parser/{ => issues}/issue-17904.stderr | 0 .../ui/parser/{ => issues}/issue-1802-1.rs | 0 .../parser/{ => issues}/issue-1802-1.stderr | 0 .../ui/parser/{ => issues}/issue-1802-2.rs | 0 .../parser/{ => issues}/issue-1802-2.stderr | 0 .../ui/parser/{ => issues}/issue-19096.rs | 0 .../ui/parser/{ => issues}/issue-19096.stderr | 0 .../ui/parser/{ => issues}/issue-19398.rs | 0 .../ui/parser/{ => issues}/issue-19398.stderr | 0 .../ui/parser/{ => issues}/issue-20616-1.rs | 0 .../parser/{ => issues}/issue-20616-1.stderr | 0 .../ui/parser/{ => issues}/issue-20616-2.rs | 0 .../parser/{ => issues}/issue-20616-2.stderr | 0 .../ui/parser/{ => issues}/issue-20616-3.rs | 0 .../parser/{ => issues}/issue-20616-3.stderr | 0 .../ui/{ => parser}/issues/issue-20616-4.rs | 0 .../{ => parser}/issues/issue-20616-4.stderr | 0 .../ui/{ => parser}/issues/issue-20616-5.rs | 0 .../{ => parser}/issues/issue-20616-5.stderr | 0 .../ui/{ => parser}/issues/issue-20616-6.rs | 0 .../{ => parser}/issues/issue-20616-6.stderr | 0 .../ui/{ => parser}/issues/issue-20616-7.rs | 0 .../{ => parser}/issues/issue-20616-7.stderr | 0 .../ui/parser/{ => issues}/issue-20616-8.rs | 0 .../parser/{ => issues}/issue-20616-8.stderr | 0 .../ui/parser/{ => issues}/issue-20616-9.rs | 0 .../parser/{ => issues}/issue-20616-9.stderr | 0 .../ui/parser/{ => issues}/issue-20711-2.rs | 0 .../parser/{ => issues}/issue-20711-2.stderr | 0 .../ui/parser/{ => issues}/issue-20711.rs | 0 .../ui/parser/{ => issues}/issue-20711.stderr | 0 .../ui/parser/{ => issues}/issue-21146.rs | 0 .../ui/parser/{ => issues}/issue-21146.stderr | 0 .../ui/parser/{ => issues}/issue-21153.rs | 0 .../ui/parser/{ => issues}/issue-21153.stderr | 0 .../ui/{ => parser}/issues/issue-21475.rs | 0 .../ui/parser/{ => issues}/issue-22647.rs | 0 .../ui/parser/{ => issues}/issue-22647.stderr | 0 .../ui/parser/{ => issues}/issue-22712.rs | 0 .../ui/parser/{ => issues}/issue-22712.stderr | 0 .../ui/parser/{ => issues}/issue-2354-1.rs | 0 .../parser/{ => issues}/issue-2354-1.stderr | 0 src/test/ui/parser/{ => issues}/issue-2354.rs | 0 .../ui/parser/{ => issues}/issue-2354.stderr | 0 .../issue-23620-invalid-escapes.rs | 0 .../issue-23620-invalid-escapes.stderr | 0 .../ui/parser/{ => issues}/issue-24197.rs | 0 .../ui/parser/{ => issues}/issue-24197.stderr | 0 .../ui/parser/{ => issues}/issue-24375.rs | 0 .../ui/parser/{ => issues}/issue-24375.stderr | 0 .../ui/parser/{ => issues}/issue-24780.rs | 0 .../ui/parser/{ => issues}/issue-24780.stderr | 0 .../ui/parser/{ => issues}/issue-27255.rs | 0 .../ui/parser/{ => issues}/issue-27255.stderr | 0 .../ui/parser/{ => issues}/issue-30318.fixed | 0 .../ui/parser/{ => issues}/issue-30318.rs | 0 .../ui/parser/{ => issues}/issue-30318.stderr | 0 .../ui/parser/{ => issues}/issue-3036.fixed | 0 src/test/ui/parser/{ => issues}/issue-3036.rs | 0 .../ui/parser/{ => issues}/issue-3036.stderr | 0 .../ui/{ => parser}/issues/issue-31804.rs | 0 .../ui/{ => parser}/issues/issue-31804.stderr | 0 .../ui/parser/{ => issues}/issue-32214.rs | 0 .../ui/parser/{ => issues}/issue-32214.stderr | 0 .../ui/parser/{ => issues}/issue-32446.rs | 0 .../ui/parser/{ => issues}/issue-32446.stderr | 0 .../ui/parser/{ => issues}/issue-32501.rs | 0 .../ui/parser/{ => issues}/issue-32501.stderr | 0 .../ui/parser/{ => issues}/issue-32505.rs | 0 .../ui/parser/{ => issues}/issue-32505.stderr | 0 .../ui/parser/{ => issues}/issue-33262.rs | 0 .../ui/parser/{ => issues}/issue-33262.stderr | 0 .../ui/parser/{ => issues}/issue-33413.rs | 0 .../ui/parser/{ => issues}/issue-33413.stderr | 0 .../ui/parser/{ => issues}/issue-33418.fixed | 0 .../ui/parser/{ => issues}/issue-33418.rs | 0 .../ui/parser/{ => issues}/issue-33418.stderr | 0 .../ui/parser/{ => issues}/issue-33455.rs | 0 .../ui/parser/{ => issues}/issue-33455.stderr | 0 .../ui/parser/{ => issues}/issue-34222-1.rs | 0 .../parser/{ => issues}/issue-34222-1.stderr | 0 .../ui/{ => parser}/issues/issue-34255-1.rs | 0 .../{ => parser}/issues/issue-34255-1.stderr | 0 .../issue-35813-postfix-after-cast.rs | 0 .../issue-35813-postfix-after-cast.stderr | 0 .../ui/parser/{ => issues}/issue-41155.rs | 0 .../ui/parser/{ => issues}/issue-41155.stderr | 0 .../ui/parser/{ => issues}/issue-43196.rs | 0 .../ui/parser/{ => issues}/issue-43196.stderr | 0 .../ui/parser/{ => issues}/issue-43692.rs | 0 .../ui/parser/{ => issues}/issue-43692.stderr | 0 .../ui/parser/{ => issues}/issue-44021.rs | 0 .../ui/parser/{ => issues}/issue-44021.stderr | 0 .../ui/parser/{ => issues}/issue-44406.rs | 0 .../ui/parser/{ => issues}/issue-44406.stderr | 0 .../ui/parser/{ => issues}/issue-45296.rs | 0 .../ui/parser/{ => issues}/issue-45296.stderr | 0 .../ui/parser/{ => issues}/issue-46186.fixed | 0 .../ui/parser/{ => issues}/issue-46186.rs | 0 .../ui/parser/{ => issues}/issue-46186.stderr | 0 ...not-interpolate-impl-items-bad-variants.rs | 0 ...interpolate-impl-items-bad-variants.stderr | 0 ...37-macros-cannot-interpolate-impl-items.rs | 0 .../ui/parser/{ => issues}/issue-48508-aux.rs | 0 .../ui/parser/{ => issues}/issue-48508.rs | 0 .../ui/parser/{ => issues}/issue-48636.fixed | 0 .../ui/parser/{ => issues}/issue-48636.rs | 0 .../ui/parser/{ => issues}/issue-48636.stderr | 0 .../ui/{ => parser}/issues/issue-49040.rs | 0 .../ui/{ => parser}/issues/issue-49040.stderr | 0 .../ui/parser/{ => issues}/issue-51602.rs | 0 .../ui/parser/{ => issues}/issue-51602.stderr | 0 .../ui/parser/{ => issues}/issue-52496.rs | 0 .../ui/parser/{ => issues}/issue-52496.stderr | 0 .../ui/parser/{ => issues}/issue-54521-1.rs | 0 .../parser/{ => issues}/issue-54521-2.fixed | 0 .../ui/parser/{ => issues}/issue-54521-2.rs | 0 .../parser/{ => issues}/issue-54521-2.stderr | 0 .../parser/{ => issues}/issue-54521-3.fixed | 0 .../ui/parser/{ => issues}/issue-54521-3.rs | 0 .../parser/{ => issues}/issue-54521-3.stderr | 0 .../ui/parser/{ => issues}/issue-5544-a.rs | 0 .../parser/{ => issues}/issue-5544-a.stderr | 0 .../ui/parser/{ => issues}/issue-5544-b.rs | 0 .../parser/{ => issues}/issue-5544-b.stderr | 0 .../ui/{ => parser}/issues/issue-56031.rs | 0 .../ui/{ => parser}/issues/issue-56031.stderr | 0 .../ui/parser/{ => issues}/issue-57198.rs | 0 .../ui/parser/{ => issues}/issue-57198.stderr | 0 .../ui/parser/{ => issues}/issue-57684.fixed | 0 .../ui/parser/{ => issues}/issue-57684.rs | 0 .../ui/parser/{ => issues}/issue-57684.stderr | 0 .../ui/parser/{ => issues}/issue-57819.fixed | 0 .../ui/parser/{ => issues}/issue-57819.rs | 0 .../ui/parser/{ => issues}/issue-57819.stderr | 0 src/test/ui/parser/{ => issues}/issue-5806.rs | 0 .../ui/parser/{ => issues}/issue-5806.stderr | 0 ...ssue-58094-missing-right-square-bracket.rs | 0 ...-58094-missing-right-square-bracket.stderr | 0 .../ui/parser/{ => issues}/issue-58856-1.rs | 0 .../parser/{ => issues}/issue-58856-1.stderr | 0 .../ui/parser/{ => issues}/issue-58856-2.rs | 0 .../parser/{ => issues}/issue-58856-2.stderr | 0 .../ui/parser/{ => issues}/issue-59418.rs | 0 .../ui/parser/{ => issues}/issue-59418.stderr | 0 .../ui/parser/{ => issues}/issue-60075.rs | 0 .../ui/parser/{ => issues}/issue-60075.stderr | 0 .../ui/parser/{ => issues}/issue-62524.rs | 0 .../ui/parser/{ => issues}/issue-62524.stderr | 0 .../ui/parser/{ => issues}/issue-62546.rs | 0 .../ui/parser/{ => issues}/issue-62546.stderr | 0 .../ui/parser/{ => issues}/issue-62554.rs | 0 .../ui/parser/{ => issues}/issue-62554.stderr | 0 .../ui/parser/{ => issues}/issue-62660.rs | 0 .../ui/parser/{ => issues}/issue-62660.stderr | 0 .../ui/parser/{ => issues}/issue-62881.rs | 0 .../ui/parser/{ => issues}/issue-62881.stderr | 0 .../ui/parser/{ => issues}/issue-62894.rs | 0 .../ui/parser/{ => issues}/issue-62894.stderr | 0 .../ui/parser/{ => issues}/issue-62895.rs | 0 .../ui/parser/{ => issues}/issue-62895.stderr | 0 .../ui/parser/{ => issues}/issue-62913.rs | 0 .../ui/parser/{ => issues}/issue-62913.stderr | 0 .../ui/parser/{ => issues}/issue-62973.rs | 0 .../ui/parser/{ => issues}/issue-62973.stderr | 0 .../issue-63115-range-pat-interpolated.rs | 0 .../ui/parser/{ => issues}/issue-63116.rs | 0 .../ui/parser/{ => issues}/issue-63116.stderr | 0 .../ui/parser/{ => issues}/issue-63135.rs | 0 .../ui/parser/{ => issues}/issue-63135.stderr | 0 .../ui/parser/{ => issues}/issue-64732.rs | 0 .../ui/parser/{ => issues}/issue-64732.stderr | 0 .../issue-65041-empty-vis-matcher-in-enum.rs | 0 .../issue-65041-empty-vis-matcher-in-trait.rs | 0 .../issue-65122-mac-invoc-in-mut-patterns.rs | 0 ...sue-65122-mac-invoc-in-mut-patterns.stderr | 0 .../issue-65257-invalid-var-decl-recovery.rs | 0 ...sue-65257-invalid-var-decl-recovery.stderr | 0 ...e-65846-rollback-gating-failing-matcher.rs | 0 src/test/ui/parser/{ => issues}/issue-6610.rs | 0 .../ui/parser/{ => issues}/issue-6610.stderr | 0 .../issue-66357-unexpected-unreachable.rs | 0 .../issue-66357-unexpected-unreachable.stderr | 0 .../ui/parser/{ => issues}/issue-66473.rs | Bin .../ui/parser/{ => issues}/issue-66473.stderr | Bin ...gative-outlives-bound-syntactic-fail.fixed | 0 ...-negative-outlives-bound-syntactic-fail.rs | 0 ...ative-outlives-bound-syntactic-fail.stderr | 0 ...377-invalid-syntax-in-enum-discriminant.rs | 0 ...invalid-syntax-in-enum-discriminant.stderr | 0 ...68000-unicode-ident-after-missing-comma.rs | 0 ...0-unicode-ident-after-missing-comma.stderr | 0 .../ui/parser/{ => issues}/issue-68629.rs | Bin .../ui/parser/{ => issues}/issue-68629.stderr | Bin .../ui/parser/{ => issues}/issue-68730.rs | Bin .../ui/parser/{ => issues}/issue-68730.stderr | Bin .../issue-68788-in-trait-item-propagation.rs | 0 .../ui/parser/{ => issues}/issue-68890-2.rs | 0 .../parser/{ => issues}/issue-68890-2.stderr | 0 .../ui/parser/{ => issues}/issue-68890.rs | 0 .../ui/parser/{ => issues}/issue-68890.stderr | 0 ...sue-70050-ntliteral-accepts-negated-lit.rs | 0 .../issue-70388-recover-dotdotdot-rest-pat.rs | 0 ...ue-70388-recover-dotdotdot-rest-pat.stderr | 0 .../issue-70388-without-witness.fixed | 0 .../issue-70388-without-witness.rs | 0 .../issue-70388-without-witness.stderr | 0 ...70549-resolve-after-recovered-self-ctor.rs | 0 ...9-resolve-after-recovered-self-ctor.stderr | 0 ...e-70552-ascription-in-parens-after-call.rs | 0 ...552-ascription-in-parens-after-call.stderr | 0 .../issue-70583-block-is-empty-1.rs | 0 .../issue-70583-block-is-empty-1.stderr | 0 .../issue-70583-block-is-empty-2.rs | 0 .../issue-70583-block-is-empty-2.stderr | 0 src/test/ui/parser/{ => issues}/issue-7222.rs | 0 .../ui/parser/{ => issues}/issue-72253.rs | 0 .../ui/parser/{ => issues}/issue-72253.stderr | 0 .../ui/parser/{ => issues}/issue-72373.rs | 0 .../ui/parser/{ => issues}/issue-72373.stderr | 0 .../issue-73568-lifetime-after-mut.rs | 0 .../issue-73568-lifetime-after-mut.stderr | 0 .../ui/parser/{ => issues}/issue-75599.rs | 0 .../parser/{ => issues}/issue-76437-async.rs | 0 .../{ => issues}/issue-76437-async.stderr | 0 .../issue-76437-const-async-unsafe.rs | 0 .../issue-76437-const-async-unsafe.stderr | 0 .../{ => issues}/issue-76437-const-async.rs | 0 .../issue-76437-const-async.stderr | 0 .../parser/{ => issues}/issue-76437-const.rs | 0 .../{ => issues}/issue-76437-const.stderr | 0 .../issue-76437-pub-crate-unsafe.rs | 0 .../issue-76437-pub-crate-unsafe.stderr | 0 .../parser/{ => issues}/issue-76437-unsafe.rs | 0 .../{ => issues}/issue-76437-unsafe.stderr | 0 .../ui/parser/{ => issues}/issue-76597.fixed | 0 .../ui/parser/{ => issues}/issue-76597.rs | 0 .../ui/parser/{ => issues}/issue-76597.stderr | 0 .../ui/parser/{ => issues}/issue-7970b.rs | 0 .../ui/parser/{ => issues}/issue-7970b.stderr | 0 .../ui/parser/{ => issues}/issue-81806.rs | 0 .../ui/parser/{ => issues}/issue-81806.stderr | 0 .../ui/{ => parser/issues}/issue-83639.rs | 0 .../ui/{ => parser/issues}/issue-83639.stderr | 0 .../ui/parser/{ => issues}/issue-84104.rs | 0 .../ui/parser/{ => issues}/issue-84104.stderr | 0 .../ui/parser/{ => issues}/issue-84117.rs | 0 .../ui/parser/{ => issues}/issue-84117.stderr | 0 .../ui/parser/{ => issues}/issue-84148-1.rs | 0 .../parser/{ => issues}/issue-84148-1.stderr | 0 .../ui/parser/{ => issues}/issue-84148-2.rs | 0 .../parser/{ => issues}/issue-84148-2.stderr | 0 src/test/ui/parser/{ => issues}/issue-8537.rs | 0 .../ui/parser/{ => issues}/issue-8537.stderr | 0 .../ui/parser/{ => issues}/issue-86895.rs | 0 .../ui/parser/{ => issues}/issue-86895.stderr | 0 .../issue-87086-colon-path-sep.rs | 0 .../issue-87086-colon-path-sep.stderr | 0 .../issue-87197-missing-semicolon.fixed | 0 .../issue-87197-missing-semicolon.rs | 0 .../issue-87197-missing-semicolon.stderr | 0 .../const-async-const.rs | 0 .../const-async-const.stderr | 0 .../several-kw-jump.rs | 0 .../several-kw-jump.stderr | 0 .../issue-87217-keyword-order/wrong-async.rs | 0 .../wrong-async.stderr | 0 .../issue-87217-keyword-order/wrong-const.rs | 0 .../wrong-const.stderr | 0 .../issue-87217-keyword-order/wrong-unsafe.rs | 0 .../wrong-unsafe.stderr | 0 .../ui/parser/{ => issues}/issue-87635.rs | 0 .../ui/parser/{ => issues}/issue-87635.stderr | 0 .../parser/{ => issues}/issue-87812-path.rs | 0 .../{ => issues}/issue-87812-path.stderr | 0 .../ui/parser/{ => issues}/issue-87812.rs | 0 .../ui/parser/{ => issues}/issue-87812.stderr | 0 .../{ => issues}/issue-88276-unary-plus.fixed | 0 .../{ => issues}/issue-88276-unary-plus.rs | 0 .../issue-88276-unary-plus.stderr | 0 .../issue-88583-union-as-ident.rs | 0 .../ui/parser/{ => issues}/issue-88770.rs | 0 .../ui/parser/{ => issues}/issue-88770.stderr | 0 .../ui/parser/{ => issues}/issue-88818.rs | 0 .../ui/parser/{ => issues}/issue-88818.stderr | 0 .../ui/parser/{ => issues}/issue-89388.rs | 0 .../ui/parser/{ => issues}/issue-89388.stderr | 0 .../ui/parser/{ => issues}/issue-89396.fixed | 0 .../ui/parser/{ => issues}/issue-89396.rs | 0 .../ui/parser/{ => issues}/issue-89396.stderr | 0 .../ui/parser/{ => issues}/issue-89574.rs | 0 .../ui/parser/{ => issues}/issue-89574.stderr | 0 ...971-outer-attr-following-inner-attr-ice.rs | 15 + ...outer-attr-following-inner-attr-ice.stderr | 18 + src/test/ui/parser/issues/issue-90993.rs | 6 + src/test/ui/parser/issues/issue-90993.stderr | 31 + .../obsolete-syntax-impl-for-dotdot.rs | 0 .../obsolete-syntax-impl-for-dotdot.stderr | 0 .../ui/{ => parser}/operator-associativity.rs | 0 src/test/ui/{ => parser}/ranges-precedence.rs | 0 .../recover-for-loop-parens-around-head.rs | 2 +- ...recover-for-loop-parens-around-head.stderr | 4 +- src/test/ui/{ => parser}/similar-tokens.rs | 0 .../ui/{ => parser}/similar-tokens.stderr | 0 .../ui/parser/struct-literal-in-for.stderr | 5 - src/test/ui/{ => parser}/utf8_idents-rpass.rs | 0 .../ui/{ => pattern}/ignore-all-the-things.rs | 0 .../ui/{issues => pattern}/issue-11577.rs | 0 .../ui/{issues => pattern}/issue-15080.rs | 0 ...67037-pat-tup-scrut-ty-diff-less-fields.rs | 2 +- .../ui/{issues => pattern}/issue-72574-2.rs | 0 .../{issues => pattern}/issue-72574-2.stderr | 0 .../ui/{issues => pattern}/issue-8351-1.rs | 0 .../ui/{issues => pattern}/issue-8351-2.rs | 0 .../ui/pattern/non-structural-match-types.rs | 14 + .../pattern/non-structural-match-types.stderr | 14 + .../ui/pattern/pat-type-err-let-stmt.stderr | 10 +- src/test/ui/pattern/usefulness/issue-88747.rs | 14 + .../auxiliary/impl_privacy_xc_2.rs | 0 .../auxiliary/reachable-unnameable-items.rs | 0 src/test/ui/privacy/crate-private-reexport.rs | 66 + .../ui/privacy/crate-private-reexport.stderr | 220 + .../ui/{ => privacy}/export-tag-variant.rs | 0 .../{ => privacy}/export-tag-variant.stderr | 0 .../ui/{ => privacy}/impl-privacy-xc-2.rs | 0 src/test/ui/privacy/privacy2.stderr | 8 +- src/test/ui/privacy/privacy3.stderr | 8 +- .../ui/privacy/private-variant-reexport.rs | 6 +- .../privacy/private-variant-reexport.stderr | 8 +- src/test/ui/privacy/pub-priv-dep/pub-priv1.rs | 1 + .../ui/privacy/pub-priv-dep/pub-priv1.stderr | 8 +- .../reachable-unnameable-items.rs | 0 src/test/ui/{ => privacy}/useless-pub.rs | 0 src/test/ui/{ => privacy}/useless-pub.stderr | 0 .../ui/proc-macro/ambiguous-builtin-attrs.rs | 2 +- .../proc-macro/ambiguous-builtin-attrs.stderr | 18 +- src/test/ui/proc-macro/auxiliary/api/parse.rs | 10 + .../{ => proc-macro}/auxiliary/cond_plugin.rs | 0 .../ui/proc-macro/auxiliary/expand-expr.rs | 80 + .../ui/proc-macro/auxiliary/included-file.txt | 1 + .../proc-macro/derive-helper-shadowing.stderr | 6 +- src/test/ui/proc-macro/expand-expr.rs | 121 + src/test/ui/proc-macro/expand-expr.stderr | 55 + src/test/ui/proc-macro/generate-mod.rs | 8 +- src/test/ui/proc-macro/generate-mod.stderr | 38 +- .../group-compat-hack/group-compat-hack.rs | 11 +- .../group-compat-hack.stderr | 66 +- .../group-compat-hack.stdout | 22 +- ...helper-attr-blocked-by-import-ambig.stderr | 3 +- src/test/ui/proc-macro/issue-39889.rs | 2 +- src/test/ui/proc-macro/issue-41211.stderr | 3 +- .../issue-73933-procedural-masquerade.rs | 3 +- .../issue-73933-procedural-masquerade.stderr | 14 +- .../issue-73933-procedural-masquerade.stdout | 8 +- .../ui/{ => proc-macro}/macro-quote-cond.rs | 0 .../ui/proc-macro/meta-macro-hygiene.stdout | 2 + .../nonterminal-token-hygiene.stdout | 2 + .../proc-macro/proc-macro-attributes.stderr | 12 +- src/test/ui/{ => process}/core-run-destroy.rs | 0 src/test/ui/{ => process}/fds-are-cloexec.rs | 0 .../ui/{issues => process}/issue-14456.rs | 0 .../ui/{issues => process}/issue-16272.rs | 0 .../ui/{issues => process}/issue-20091.rs | 0 src/test/ui/{ => process}/multi-panic.rs | 0 src/test/ui/{ => process}/no-stdio.rs | 0 .../ui/{ => process}/signal-exit-status.rs | 0 .../sigpipe-should-be-ignored.rs | 0 src/test/ui/{ => process}/try-wait.rs | 0 src/test/ui/pure-sum.rs | 51 - src/test/ui/purity-infer.rs | 6 - src/test/ui/query-system/issue-83479.rs | 16 + src/test/ui/query-system/issue-83479.stderr | 44 + src/test/ui/range/range-1.stderr | 5 - src/test/ui/range/range_traits-1.stderr | 60 - src/test/ui/reachable/expr_cast.rs | 1 + src/test/ui/reachable/expr_cast.stderr | 9 +- .../ui/reachable/unreachable-loop-patterns.rs | 1 - .../unreachable-loop-patterns.stderr | 8 +- src/test/ui/readalias.rs | 12 - src/test/ui/{ => recursion}/instantiable.rs | 0 src/test/ui/reexport-should-still-link.rs | 10 - .../ui/{ => regions}/init-res-into-things.rs | 0 .../ui/{issues => regions}/issue-21520.rs | 0 .../ui/{issues => regions}/issue-26448-1.rs | 0 .../ui/{issues => regions}/issue-26448-2.rs | 0 .../ui/{issues => regions}/issue-26448-3.rs | 0 .../ui/{ => regions}/owned-implies-static.rs | 0 .../{ => regions}/rcvr-borrowed-to-region.rs | 0 ...ions-bounded-method-type-parameters.stderr | 6 +- .../regions-close-object-into-object-5.stderr | 8 +- .../regions-static-bound.ll.nll.stderr | 28 - .../regions-static-bound.migrate.nll.stderr | 23 - .../regions-static-bound.migrate.stderr | 29 - .../regions/regions-static-bound.nll.stderr | 31 +- src/test/ui/regions/regions-static-bound.rs | 12 +- .../ui/regions/regions-static-bound.stderr | 46 + .../wf-bound-region-in-object-type.rs | 0 src/test/ui/{ => repr}/attr-usage-repr.rs | 0 src/test/ui/{ => repr}/attr-usage-repr.stderr | 0 src/test/ui/{ => repr}/repr.rs | 0 src/test/ui/{ => repr}/repr.stderr | 0 .../blind-item-mixed-crate-use-item-foo.rs | 0 .../blind-item-mixed-crate-use-item-foo2.rs | 0 .../blind-item-mixed-crate-use-item.rs | 0 .../blind-item-mixed-use-item.rs | 0 src/test/ui/{ => resolve}/crate-in-paths.rs | 0 .../ui/{ => resolve}/crate-in-paths.stderr | 0 .../{ => resolve}/editions-crate-root-2015.rs | 0 .../editions-crate-root-2015.stderr | 0 .../{ => resolve}/editions-crate-root-2018.rs | 0 .../editions-crate-root-2018.stderr | 0 .../ui/{ => resolve}/enums-pats-not-idents.rs | 0 .../enums-pats-not-idents.stderr | 0 .../{ => resolve}/export-fully-qualified.rs | 0 .../export-fully-qualified.stderr | 0 .../ui/{issues => resolve}/issue-12796.rs | 0 .../ui/{issues => resolve}/issue-12796.stderr | 0 .../ui/{issues => resolve}/issue-23716.rs | 0 .../ui/{issues => resolve}/issue-23716.stderr | 0 .../ui/{issues => resolve}/issue-3021-c.rs | 0 .../{issues => resolve}/issue-3021-c.stderr | 0 src/test/ui/{issues => resolve}/issue-3021.rs | 0 .../ui/{issues => resolve}/issue-3021.stderr | 0 .../ui/{issues => resolve}/issue-31845.rs | 0 .../ui/{issues => resolve}/issue-31845.stderr | 0 src/test/ui/{issues => resolve}/issue-5099.rs | 0 .../ui/{issues => resolve}/issue-5099.stderr | 0 ...0736-async-fn-no-body-def-collector.stderr | 2 +- src/test/ui/resolve/issue-90113.rs | 21 + src/test/ui/resolve/issue-90113.stderr | 14 + .../no-implicit-prelude-nested.rs | 0 .../no-implicit-prelude-nested.stderr | 0 src/test/ui/{ => resolve}/no-std-1.rs | 0 src/test/ui/{ => resolve}/no-std-2.rs | 0 src/test/ui/{ => resolve}/no-std-3.rs | 0 .../ui/{ => resolve}/pathless-extern-ok.rs | 0 src/test/ui/resolve/privacy-enum-ctor.stderr | 21 +- .../ui/{ => resolve}/resolve-issue-2428.rs | 0 src/test/ui/ret-none.rs | 13 - .../issue-6804.rs | 0 .../issue-6804.stderr | 0 .../disallowed-positions.stderr | 155 +- .../link-ordinal-multiple.rs | 3 +- .../link-ordinal-multiple.stderr | 8 +- .../const-and-non-const-impl.rs | 9 +- .../const-and-non-const-impl.stderr | 62 +- .../const-drop-bound.rs | 20 + .../const-drop-fail.precise.stderr | 9 +- .../const-drop-fail.stock.stderr | 9 +- .../trait-default-body-stability.rs | 51 + .../trait-where-clause.stderr | 24 +- .../feature-gate.rs | 29 + .../feature-gate.stderr | 22 + .../lifetime-update.rs | 43 + .../lifetime-update.stderr | 15 + .../type-generic-update.rs | 57 + .../type-generic-update.stderr | 30 + src/test/ui/{ => runtime}/atomic-print.rs | 0 .../{ => runtime}/backtrace-debuginfo-aux.rs | 0 .../ui/{ => runtime}/backtrace-debuginfo.rs | 0 .../{ => runtime}/native-print-no-runtime.rs | 0 src/test/ui/{ => runtime}/out-of-stack.rs | 0 .../rt-explody-panic-payloads.rs | 2 +- .../{ => runtime}/running-with-no-runtime.rs | 0 .../signal-alternate-stack-cleanup.rs | 0 .../{ => runtime}/stdout-during-shutdown.rs | 0 .../stdout-during-shutdown.run.stdout | 0 .../ambiguity-macros-nested.stderr | 3 +- .../uniform-paths/ambiguity-macros.stderr | 3 +- .../uniform-paths/ambiguity-nested.stderr | 3 +- .../rust-2018/uniform-paths/ambiguity.stderr | 3 +- .../auxiliary/issue-55779-extern-trait.rs | 1 + .../uniform-paths/auxiliary/issue-87932-a.rs | 3 + .../block-scoped-shadow-nested.stderr | 3 +- .../uniform-paths/block-scoped-shadow.stderr | 9 +- .../ui/rust-2018/uniform-paths/issue-55779.rs | 29 + .../uniform-paths/issue-56596.stderr | 3 +- .../ui/rust-2018/uniform-paths/issue-87932.rs | 15 + .../uniform-paths/issue-87932.stderr | 18 + .../ui/rust-2018/uniform-paths/macro-rules.rs | 2 +- .../uniform-paths/macro-rules.stderr | 5 +- .../ui/rust-2018/uniform-paths/redundant.rs | 8 +- .../future-prelude-collision-shadow.stderr | 1 + src/test/ui/rust-2021/prelude2021.rs | 1 - .../reserved-prefixes-migration.fixed | 2 +- .../rust-2021/reserved-prefixes-migration.rs | 2 +- src/test/ui/rustc-rust-log.rs | 5 +- src/test/ui/rustdoc/doc_keyword.rs | 2 +- .../ui/{ => rustdoc}/duplicate_doc_alias.rs | 0 .../{ => rustdoc}/duplicate_doc_alias.stderr | 0 .../ui/rustdoc/hidden-doc-associated-item.rs | 15 + .../renamed-features-rustdoc_internals.rs | 5 + .../renamed-features-rustdoc_internals.stderr | 19 + ...s_pin_lifetime_impl_trait-async.nll.stderr | 15 - ...elf_types_pin_lifetime_impl_trait-async.rs | 2 +- ...types_pin_lifetime_impl_trait-async.stderr | 15 +- ...f_types_pin_lifetime_impl_trait.nll.stderr | 15 - ...rary_self_types_pin_lifetime_impl_trait.rs | 3 +- ..._self_types_pin_lifetime_impl_trait.stderr | 19 +- src/test/ui/{ => self}/class-missing-self.rs | 0 .../ui/{ => self}/class-missing-self.stderr | 0 src/test/ui/{issues => self}/issue-61882-2.rs | 0 .../ui/{issues => self}/issue-61882-2.stderr | 0 src/test/ui/{issues => self}/issue-61882.rs | 0 .../ui/{issues => self}/issue-61882.stderr | 0 .../objects-owned-object-owned-method.rs | 0 src/test/ui/simd/intrinsic/generic-bitmask.rs | 10 +- .../ui/simd/intrinsic/generic-bitmask.stderr | 10 +- .../simd/intrinsic/generic-elements-pass.rs | 1 - src/test/ui/simd/intrinsic/generic-select.rs | 11 +- .../ui/simd/intrinsic/generic-select.stderr | 22 +- src/test/ui/simd/simd-bitmask.rs | 52 + src/test/ui/span/issue-29595.stderr | 6 - ...pecialization-trait-not-implemented.stderr | 8 +- .../transmute-specialization.rs | 0 .../transmute-specialization.stderr | 0 .../stability-attribute-trait-impl.rs | 17 +- .../stability-attribute-trait-impl.stderr | 18 +- .../stability-in-private-module.rs | 0 .../stability-in-private-module.stderr | 0 .../suggest-vec-allocator-api.rs | 9 + .../suggest-vec-allocator-api.stderr | 49 + ...arn-stack-protector-unsupported.all.stderr | 4 + ...n-stack-protector-unsupported.basic.stderr | 4 + .../warn-stack-protector-unsupported.rs | 19 + ...-stack-protector-unsupported.strong.stderr | 4 + .../{ => static}/auxiliary/extern-statics.rs | 0 .../ui/{ => static}/auxiliary/nested_item.rs | 0 src/test/ui/{ => static}/nested_item_main.rs | 0 .../refer-to-other-statics-by-value.rs | 0 .../safe-extern-statics-mut.mir.stderr | 0 .../{ => static}/safe-extern-statics-mut.rs | 0 .../safe-extern-statics-mut.thir.stderr | 0 .../safe-extern-statics.mir.stderr | 0 .../ui/{ => static}/safe-extern-statics.rs | 0 .../safe-extern-statics.thir.stderr | 0 .../ui/static/static-mut-bad-types.stderr | 3 + .../{ => static}/static_sized_requirement.rs | 0 .../ui/{ => static}/thread-local-in-ctfe.rs | 0 .../{ => static}/thread-local-in-ctfe.stderr | 0 .../issue-14227.mir.stderr | 0 .../ui/{issues => statics}/issue-14227.rs | 0 .../issue-14227.thir.stderr | 0 src/test/ui/statics/issue-91050-1.rs | 34 + src/test/ui/statics/issue-91050-2.rs | 24 + src/test/ui/statics/uninhabited-static.rs | 4 + src/test/ui/statics/uninhabited-static.stderr | 46 +- .../{ => stdlib-unit-tests}/builtin-clone.rs | 0 .../eq-multidispatch.rs | 0 src/test/ui/{ => stdlib-unit-tests}/istr.rs | 0 .../log-knows-the-names-of-variants-in-std.rs | 0 .../ui/{ => stdlib-unit-tests}/matches2021.rs | 1 - .../minmax-stability-issue-23687.rs | 0 .../ui/{ => stdlib-unit-tests}/not-sync.rs | 0 .../{ => stdlib-unit-tests}/not-sync.stderr | 0 .../ui/{ => stdlib-unit-tests}/raw-fat-ptr.rs | 0 .../ui/{ => stdlib-unit-tests}/seq-compare.rs | 0 .../volatile-fat-ptr.rs | 0 src/test/ui/str/str-idx.stderr | 10 + src/test/ui/str/str-mut-idx.stderr | 10 + .../{issues => structs-enums}/issue-50731.rs | 0 src/test/ui/structs-enums/rec-align-u64.rs | 1 + src/test/ui/{ => structs}/large-records.rs | 0 .../structs/struct-path-alias-bounds.stderr | 6 +- src/test/ui/suggest-using-chars.rs | 7 + src/test/ui/suggest-using-chars.stderr | 48 + ...rg-where-it-should-have-been-called.stderr | 6 +- .../{ => suggestions}/bound-suggestions.fixed | 0 .../ui/{ => suggestions}/bound-suggestions.rs | 0 .../bound-suggestions.stderr | 0 .../ui/suggestions/boxed-variant-field.rs | 16 + .../ui/suggestions/boxed-variant-field.stderr | 20 + .../core-std-import-order-issue-83564.stderr | 4 +- .../expected-boxed-future-isnt-pinned.stderr | 14 +- ...rg-where-it-should-have-been-called.stderr | 4 +- src/test/ui/suggestions/if-let-typo.stderr | 5 - ...-bound-needing-more-suggestions.nll.stderr | 16 +- ...t-static-bound-needing-more-suggestions.rs | 2 +- ...atic-bound-needing-more-suggestions.stderr | 16 +- src/test/ui/suggestions/into-str.stderr | 6 +- src/test/ui/suggestions/issue-62843.stderr | 5 + src/test/ui/suggestions/issue-72766.stderr | 9 +- src/test/ui/suggestions/issue-81839.stderr | 2 +- src/test/ui/suggestions/issue-84973.stderr | 9 +- ...-where-clause-before-suggesting-unsized.rs | 8 + ...re-clause-before-suggesting-unsized.stderr | 18 + src/test/ui/suggestions/issue-90974.rs | 3 + src/test/ui/suggestions/issue-90974.stderr | 14 + .../missing-lifetimes-in-signature-2.stderr | 7 +- ...ait-object-nested-in-impl-trait.nll.stderr | 26 +- .../match-prev-arm-needing-semi.rs | 2 +- .../match-prev-arm-needing-semi.stderr | 10 +- .../mut-borrow-needed-by-trait.stderr | 6 +- .../suggestions/mut-ref-reassignment.stderr | 8 + .../ui/suggestions/opaque-type-error.stderr | 4 +- .../ui/suggestions/slice-issue-87994.stderr | 20 - .../ui/suggestions/suggest-change-mut.stderr | 6 +- ...-full-enum-variant-for-local-module.stderr | 10 +- .../suggest-on-bare-closure-call.stderr | 2 +- .../suggestions/suggest-remove-refs-1.stderr | 5 - .../suggestions/suggest-remove-refs-2.stderr | 5 - .../suggestions/suggest-remove-refs-3.stderr | 5 - .../suggest-tryinto-edition-change.rs | 31 + .../suggest-tryinto-edition-change.stderr | 76 + .../ui/suggestions/undeclared-module-alloc.rs | 5 + .../undeclared-module-alloc.stderr | 11 + .../{ => svh}/auxiliary/changing-crates-a1.rs | 0 .../{ => svh}/auxiliary/changing-crates-a2.rs | 0 .../{ => svh}/auxiliary/changing-crates-b.rs | 0 src/test/ui/{ => svh}/changing-crates.rs | 0 src/test/ui/{ => svh}/changing-crates.stderr | 0 .../ui/syntax-trait-polarity-feature-gate.rs | 10 - .../syntax-trait-polarity-feature-gate.stderr | 12 - src/test/ui/synthetic-param.rs | 28 - src/test/ui/synthetic-param.stderr | 21 - src/test/ui/tail-direct.rs | 7 - src/test/ui/terr-sorts.stderr | 4 + .../ui/{issues => test-attrs}/issue-20823.rs | 0 .../child-outlives-parent.rs | 0 .../clone-with-exterior.rs | 0 .../issue-24313.rs | 0 .../issue-4448.rs | 0 .../issue-8827.rs | 0 .../issue-9396.rs | 0 .../ui/{ => threads-sendsync}/mpsc_stress.rs | 0 .../ui/{ => threads-sendsync}/tcp-stress.rs | 0 .../{ => threads-sendsync}/trivial-message.rs | 0 .../{ => threads-sendsync}/unwind-resource.rs | 0 src/test/ui/{ => threads-sendsync}/yield.rs | 0 src/test/ui/{ => threads-sendsync}/yield1.rs | 0 src/test/ui/{ => threads-sendsync}/yield2.rs | 0 src/test/ui/trait-bounds/issue-75961.rs | 7 + src/test/ui/traits/alias/issue-83613.stderr | 16 +- .../{ => traits}/alignment-gep-tup-like-1.rs | 0 .../ui/traits/bad-method-typaram-kind.stderr | 5 + src/test/ui/traits/bad-sized.stderr | 6 +- .../bound/on-structs-and-enums-locals.stderr | 6 +- .../bound/on-structs-and-enums-xc1.stderr | 6 +- src/test/ui/{ => traits}/bug-7295.rs | 0 src/test/ui/traits/cache-reached-depth-ice.rs | 2 +- .../ui/traits/cache-reached-depth-ice.stderr | 2 +- .../ui/{ => traits}/cycle-generic-bound.rs | 0 .../ui/{ => traits}/early-vtbl-resolution.rs | 0 .../repeated-supertrait-ambig.stderr | 11 - src/test/ui/{issues => traits}/issue-24010.rs | 0 src/test/ui/{issues => traits}/issue-38604.rs | 0 .../ui/{issues => traits}/issue-38604.stderr | 0 src/test/ui/{issues => traits}/issue-3973.rs | 0 .../ui/{issues => traits}/issue-3973.stderr | 0 .../ui/{issues => traits}/issue-59029-1.rs | 0 .../{issues => traits}/issue-59029-1.stderr | 0 src/test/ui/traits/issue-71136.stderr | 7 +- src/test/ui/{issues => traits}/issue-72455.rs | 0 src/test/ui/traits/issue-77982.rs | 1 + src/test/ui/traits/issue-77982.stderr | 75 +- src/test/ui/traits/issue-78372.stderr | 12 +- src/test/ui/traits/issue-79458.stderr | 5 - .../issue-83538-tainted-cache-after-cycle.rs | 8 +- ...sue-83538-tainted-cache-after-cycle.stderr | 8 +- .../traits/issue-85360-eval-obligation-ice.rs | 130 + .../issue-85360-eval-obligation-ice.stderr | 20 + src/test/ui/traits/issue-85735.stderr | 9 - src/test/ui/traits/issue-90195-2.rs | 20 + src/test/ui/traits/issue-90195.rs | 21 + src/test/ui/{ => traits}/map-types.rs | 0 src/test/ui/{ => traits}/map-types.stderr | 0 src/test/ui/{ => traits}/monad.rs | 0 ...nomorphized-callees-with-ty-params-3314.rs | 0 ...ispatch-conditional-impl-not-considered.rs | 0 .../multidispatch-convert-ambig-dest.rs | 3 +- .../multidispatch-convert-ambig-dest.stderr | 31 +- src/test/ui/{ => traits}/multidispatch1.rs | 0 src/test/ui/{ => traits}/multidispatch2.rs | 0 .../negated-auto-traits-error.stderr | 22 +- .../rely-on-negative-impl-in-coherence.rs | 4 +- .../rely-on-negative-impl-in-coherence.stderr | 11 - src/test/ui/{ => traits}/no_send-struct.rs | 0 .../ui/{ => traits}/no_send-struct.stderr | 0 .../object-does-not-impl-trait.rs | 0 .../object-does-not-impl-trait.stderr | 0 ...owned-object-borrowed-method-headerless.rs | 0 .../param-without-lifetime-constraint.stderr | 8 +- .../ui/traits/reservation-impl/no-use.stderr | 5 - .../self-without-lifetime-constraint.stderr | 8 +- .../static-method-generic-inference.stderr | 5 - .../ui/{ => traits}/staticness-mismatch.rs | 0 .../{ => traits}/staticness-mismatch.stderr | 0 .../ui/traits/suggest-where-clause.stderr | 16 - .../ui/{ => traits}/syntax-trait-polarity.rs | 0 .../{ => traits}/syntax-trait-polarity.stderr | 0 src/test/ui/traits/test-2.rs | 4 +- src/test/ui/traits/test-2.stderr | 32 +- .../typeclasses-eq-example-static.rs | 0 .../ui/{ => traits}/typeclasses-eq-example.rs | 0 .../ui/{ => traits}/vtable-res-trait-param.rs | 0 .../vtable-res-trait-param.stderr | 6 + src/test/ui/traits/vtable/issue-91807.rs | 17 + .../ui/traits/vtable/vtable-diamond.stderr | 30 +- .../traits/vtable/vtable-multi-level.stderr | 208 +- .../ui/traits/vtable/vtable-multiple.stderr | 26 +- .../vtable/vtable-non-object-safe.stderr | 16 +- .../ui/traits/vtable/vtable-vacant.stderr | 16 +- .../trivial-bounds/trivial-bounds-leak.stderr | 6 - .../ui/{issues => try-block}/issue-45124.rs | 0 .../ui/try-block/try-block-bad-type.stderr | 15 - .../ui/try-block/try-block-in-while.stderr | 5 - .../try-is-identifier-edition2015.rs | 0 .../ui/try-trait/bad-interconversion.stderr | 40 - src/test/ui/try-trait/option-to-result.stderr | 10 - .../try-on-option-diagnostics.stderr | 20 - src/test/ui/try-trait/try-on-option.stderr | 10 - .../ui/try-trait/try-operator-on-main.stderr | 20 - .../ui/{ => tuple}/tuple-index-fat-types.rs | 0 ...riority-lint-ambiguous_associated_items.rs | 3 + ...ity-lint-ambiguous_associated_items.stderr | 21 +- ...t-variant-form-through-alias-caught.stderr | 7 +- .../argument-types.stderr | 2 + .../auto-trait-leakage2.stderr | 6 +- .../incoherent-assoc-imp-trait.rs | 3 +- .../incoherent-assoc-imp-trait.stderr | 15 +- .../issue-60662.rs | 0 .../issue-60662.stdout | 0 .../ui/type-alias-impl-trait/issue-89686.rs | 24 + .../type-alias-impl-trait/issue-89686.stderr | 34 + src/test/ui/type-in-nested-module.rs | 17 - .../{issues => type-inference}/issue-30225.rs | 0 .../issue-30225.stderr | 0 src/test/ui/{ => type}/type-ascription.rs | 0 src/test/ui/type/type-check-defaults.stderr | 23 - .../assignment-expected-bool.stderr | 4 - .../type/type-check/assignment-in-if.stderr | 4 - .../ui/type/type-check/issue-40294.stderr | 5 - .../type-params-in-different-spaces-2.stderr | 10 - .../auxiliary/xcrate-issue-43189-a.rs | 0 .../auxiliary/xcrate-issue-43189-b.rs | 0 .../xcrate-issue-46112-rexport-core.rs | 0 .../auxiliary/xcrate-issue-61711-b.rs | 0 src/test/ui/{issues => typeck}/issue-43189.rs | 0 .../ui/{issues => typeck}/issue-43189.stderr | 0 src/test/ui/{issues => typeck}/issue-46112.rs | 0 .../ui/{issues => typeck}/issue-46112.stderr | 9 +- .../issue-61711-once-caused-rustc-inf-loop.rs | 0 src/test/ui/typeck/issue-81293.stderr | 3 + ...sue-87771-ice-assign-assign-to-bool.stderr | 2 + src/test/ui/typeck/issue-89806.rs | 3 + src/test/ui/typeck/issue-89806.stderr | 9 + src/test/ui/typeck/issue-89856.rs | 8 + src/test/ui/typeck/issue-89856.stderr | 16 + src/test/ui/typeck/issue-90101.rs | 8 + src/test/ui/typeck/issue-90101.stderr | 24 + src/test/ui/typeck/issue-90164.rs | 9 + src/test/ui/typeck/issue-90164.stderr | 22 + ...ue-90804-incorrect-reference-suggestion.rs | 11 + ...0804-incorrect-reference-suggestion.stderr | 17 + .../ui/{ => typeck}/no-type-for-node-ice.rs | 0 .../{ => typeck}/no-type-for-node-ice.stderr | 0 src/test/ui/{ => typeck}/prim-with-args.rs | 0 .../ui/{ => typeck}/prim-with-args.stderr | 0 .../{ => typeck}/project-cache-issue-37154.rs | 0 .../typeck/typeck-unsafe-always-share.stderr | 6 +- src/test/ui/{ => typeck}/ufcs-type-params.rs | 0 src/test/ui/{ => typeck}/unify-return-ty.rs | 0 .../ui/ufcs/ufcs-qpath-self-mismatch.stderr | 5 - .../issue-18652.rs | 0 ...underscore-lifetime-elison-mismatch.stderr | 6 + .../unevaluated_fixed_size_array_len.stderr | 5 - src/test/ui/uniform-paths/basic-nested.rs | 8 +- src/test/ui/uniform-paths/basic.rs | 4 +- src/test/ui/uniform-paths/macros-nested.rs | 6 +- src/test/ui/uniform-paths/macros.rs | 2 +- src/test/ui/union/issue-41073.stderr | 7 +- src/test/ui/union/union-custom-drop.stderr | 7 +- .../ui/union/union-generic.mirunsafeck.stderr | 12 +- .../union/union-generic.thirunsafeck.stderr | 12 +- .../union-with-drop-fields.mirunsafeck.stderr | 21 +- ...union-with-drop-fields.thirunsafeck.stderr | 21 +- .../unsafe-unstable-const-fn.mir.stderr | 2 +- .../ui/unsafe/unsafe-unstable-const-fn.rs | 1 - .../unsafe-unstable-const-fn.thir.stderr | 2 +- .../ui/unsized-locals/unsized-exprs.stderr | 2 +- .../ui/{issues => unsized}/issue-30355.rs | 0 .../ui/{issues => unsized}/issue-30355.stderr | 0 src/test/ui/unsized/issue-71659.stderr | 9 + .../{ => unsized}/maybe-bounds-where-cpass.rs | 2 +- .../ui/{ => unsized}/maybe-bounds-where.rs | 0 .../{ => unsized}/maybe-bounds-where.stderr | 0 src/test/ui/unsized/unchanged-param.rs | 1 - .../extern-loc-missing-loc.rs | 2 +- src/test/ui/use-crate-name-alias.rs | 7 - .../use/use-nested-groups-unused-imports.rs | 1 - .../use-nested-groups-unused-imports.stderr | 8 +- .../ui/variance/variance-associated-consts.rs | 17 + .../variance-associated-consts.stderr | 10 + src/test/ui/{ => wasm}/wasm-import-module.rs | 0 .../ui/{ => wasm}/wasm-import-module.stderr | 0 src/test/ui/wf/wf-foreign-fn-decl-ret.stderr | 6 - .../where-clause-method-substituion.stderr | 6 + .../where-clauses-method-unsatisfied.stderr | 6 + src/test/ui/writealias.rs | 19 - src/tools/bump-stage0/src/main.rs | 1 - .../clippy/.cargo/{config => config.toml} | 0 src/tools/clippy/.github/deploy.sh | 3 +- src/tools/clippy/CHANGELOG.md | 173 +- src/tools/clippy/CONTRIBUTING.md | 4 +- src/tools/clippy/Cargo.toml | 8 +- src/tools/clippy/clippy_dev/Cargo.toml | 1 + src/tools/clippy/clippy_dev/src/main.rs | 6 + src/tools/clippy/clippy_dev/src/new_lint.rs | 240 +- .../clippy/clippy_dev/src/update_lints.rs | 4 +- src/tools/clippy/clippy_lints/Cargo.toml | 6 +- .../src/casts/cast_possible_truncation.rs | 79 +- .../src/casts/fn_to_numeric_cast_any.rs | 34 + .../clippy/clippy_lints/src/casts/mod.rs | 41 +- src/tools/clippy/clippy_lints/src/copies.rs | 10 +- src/tools/clippy/clippy_lints/src/default.rs | 8 + .../clippy_lints/src/deprecated_lints.rs | 3 + .../clippy_lints/src/disallowed_type.rs | 69 +- src/tools/clippy/clippy_lints/src/doc.rs | 64 +- .../clippy/clippy_lints/src/enum_variants.rs | 58 +- src/tools/clippy/clippy_lints/src/eq_op.rs | 11 +- .../clippy_lints/src/equatable_if_let.rs | 8 +- .../clippy_lints/src/excessive_bools.rs | 12 +- src/tools/clippy/clippy_lints/src/format.rs | 104 +- .../clippy/clippy_lints/src/format_args.rs | 223 + .../clippy/clippy_lints/src/functions/mod.rs | 12 +- .../clippy_lints/src/future_not_send.rs | 4 +- .../clippy/clippy_lints/src/identity_op.rs | 1 - .../clippy/clippy_lints/src/if_not_else.rs | 23 +- .../src/implicit_saturating_sub.rs | 2 +- .../clippy_lints/src/inherent_to_string.rs | 8 +- .../src/invalid_upcast_comparisons.rs | 68 +- .../clippy/clippy_lints/src/let_underscore.rs | 7 +- .../clippy_lints/src/lib.register_all.rs | 6 + .../src/lib.register_complexity.rs | 1 + .../src/lib.register_correctness.rs | 3 + .../clippy_lints/src/lib.register_lints.rs | 12 + .../clippy_lints/src/lib.register_nursery.rs | 1 + .../clippy_lints/src/lib.register_pedantic.rs | 3 +- .../clippy_lints/src/lib.register_perf.rs | 2 + .../src/lib.register_restriction.rs | 6 + src/tools/clippy/clippy_lints/src/lib.rs | 20 +- .../clippy/clippy_lints/src/lifetimes.rs | 6 +- .../src/loops/explicit_counter_loop.rs | 8 +- .../clippy_lints/src/loops/manual_memcpy.rs | 4 +- .../clippy/clippy_lints/src/loops/mod.rs | 19 +- .../clippy_lints/src/loops/never_loop.rs | 58 +- .../src/loops/single_element_loop.rs | 5 +- .../clippy/clippy_lints/src/loops/utils.rs | 12 - .../clippy/clippy_lints/src/manual_assert.rs | 29 +- .../clippy_lints/src/manual_unwrap_or.rs | 2 +- .../clippy_lints/src/match_result_ok.rs | 2 +- .../src/match_str_case_mismatch.rs | 171 + src/tools/clippy/clippy_lints/src/matches.rs | 90 +- .../clippy/clippy_lints/src/methods/mod.rs | 11 +- .../src/methods/uninit_assumed_init.rs | 14 +- src/tools/clippy/clippy_lints/src/misc.rs | 5 +- .../clippy_lints/src/misc_early/double_neg.rs | 23 +- .../src/misc_early/literal_suffix.rs | 38 + .../clippy/clippy_lints/src/misc_early/mod.rs | 41 +- .../misc_early/unseparated_literal_suffix.rs | 26 - .../clippy/clippy_lints/src/missing_inline.rs | 2 +- src/tools/clippy/clippy_lints/src/mut_mut.rs | 4 + .../clippy/clippy_lints/src/no_effect.rs | 179 +- .../clippy_lints/src/non_expressive_names.rs | 6 +- .../clippy_lints/src/option_if_let_else.rs | 2 +- .../clippy_lints/src/pattern_type_mismatch.rs | 207 +- src/tools/clippy/clippy_lints/src/ptr.rs | 54 +- .../clippy/clippy_lints/src/question_mark.rs | 68 +- .../src/semicolon_if_nothing_returned.rs | 4 +- src/tools/clippy/clippy_lints/src/shadow.rs | 6 +- src/tools/clippy/clippy_lints/src/strings.rs | 106 +- .../src/suspicious_operation_groupings.rs | 2 +- .../clippy_lints/src/trailing_empty_array.rs | 77 + .../clippy/clippy_lints/src/transmute/mod.rs | 25 + .../src/transmute/transmute_int_to_char.rs | 2 +- .../src/transmute/transmute_int_to_float.rs | 2 +- .../src/transmute/transmute_num_to_bytes.rs | 49 + .../clippy_lints/src/types/borrowed_box.rs | 8 +- .../src/undocumented_unsafe_blocks.rs | 226 + src/tools/clippy/clippy_lints/src/unicode.rs | 2 +- .../clippy/clippy_lints/src/uninit_vec.rs | 223 + .../clippy/clippy_lints/src/unit_hash.rs | 77 + .../src/unit_types/let_unit_value.rs | 4 - .../clippy_lints/src/unnecessary_sort_by.rs | 11 +- .../clippy_lints/src/unwrap_in_result.rs | 2 +- .../clippy/clippy_lints/src/utils/conf.rs | 14 +- .../clippy_lints/src/utils/internal_lints.rs | 3 +- .../internal_lints/metadata_collector.rs | 13 +- src/tools/clippy/clippy_lints/src/vec.rs | 8 +- .../clippy_lints/src/vec_init_then_push.rs | 52 +- src/tools/clippy/clippy_lints/src/write.rs | 4 +- src/tools/clippy/clippy_utils/Cargo.toml | 2 +- .../clippy/clippy_utils/src/ast_utils.rs | 25 +- .../clippy/clippy_utils/src/camel_case.rs | 117 - src/tools/clippy/clippy_utils/src/consts.rs | 59 + .../clippy/clippy_utils/src/diagnostics.rs | 2 +- src/tools/clippy/clippy_utils/src/higher.rs | 218 +- src/tools/clippy/clippy_utils/src/lib.rs | 123 +- src/tools/clippy/clippy_utils/src/paths.rs | 21 +- .../clippy/clippy_utils/src/str_utils.rs | 230 + src/tools/clippy/clippy_utils/src/sugg.rs | 6 +- src/tools/clippy/clippy_utils/src/ty.rs | 10 + src/tools/clippy/doc/adding_lints.md | 48 +- src/tools/clippy/doc/basics.md | 1 + src/tools/clippy/rust-toolchain | 2 +- src/tools/clippy/tests/compile-test.rs | 19 +- src/tools/clippy/tests/missing-test-files.rs | 35 +- .../ui-internal/unnecessary_symbol_str.fixed | 4 +- .../ui-internal/unnecessary_symbol_str.rs | 4 +- .../ui-internal/unnecessary_symbol_str.stderr | 8 +- .../tests/ui-toml/functions_maxlines/test.rs | 2 - .../ui-toml/functions_maxlines/test.stderr | 8 +- .../ui-toml/lint_decimal_readability/test.rs | 1 + .../lint_decimal_readability/test.stderr | 2 +- .../ui-toml/toml_disallowed_type/clippy.toml | 6 +- .../conf_disallowed_type.rs | 4 + .../conf_disallowed_type.stderr | 34 +- .../tests/ui/assertions_on_constants.rs | 4 +- .../tests/ui/assertions_on_constants.stderr | 19 +- .../clippy/tests/ui/async_yields_async.fixed | 1 - .../clippy/tests/ui/async_yields_async.rs | 1 - .../clippy/tests/ui/async_yields_async.stderr | 12 +- .../clippy/tests/ui/author/for_loop.stdout | 53 +- .../clippy/tests/ui/auxiliary/macro_rules.rs | 7 + .../clippy/tests/ui/await_holding_lock.rs | 1 - .../clippy/tests/ui/await_holding_lock.stderr | 16 +- .../tests/ui/await_holding_refcell_ref.rs | 1 - .../tests/ui/await_holding_refcell_ref.stderr | 24 +- src/tools/clippy/tests/ui/cast.rs | 23 + src/tools/clippy/tests/ui/cast.stderr | 14 +- .../clippy/tests/ui/cfg_attr_rustfmt.fixed | 2 +- src/tools/clippy/tests/ui/cfg_attr_rustfmt.rs | 2 +- .../ui/crashes/auxiliary/ice-7868-aux.rs | 3 + src/tools/clippy/tests/ui/crashes/ice-3969.rs | 5 +- .../clippy/tests/ui/crashes/ice-3969.stderr | 44 +- src/tools/clippy/tests/ui/crashes/ice-5207.rs | 2 - .../clippy/tests/ui/crashes/ice-6250.stderr | 3 + src/tools/clippy/tests/ui/crashes/ice-6252.rs | 1 - .../clippy/tests/ui/crashes/ice-6252.stderr | 12 +- src/tools/clippy/tests/ui/crashes/ice-7231.rs | 1 - src/tools/clippy/tests/ui/crashes/ice-7868.rs | 7 + .../clippy/tests/ui/crashes/ice-7868.stderr | 15 + src/tools/clippy/tests/ui/crashes/ice-7869.rs | 7 + .../clippy/tests/ui/crashes/ice-7869.stderr | 15 + .../crashes/used_underscore_binding_macro.rs | 2 - .../tests/ui/debug_assert_with_mut_call.rs | 2 +- src/tools/clippy/tests/ui/deprecated.rs | 33 +- src/tools/clippy/tests/ui/deprecated.stderr | 128 +- src/tools/clippy/tests/ui/deref_addrof.fixed | 4 +- src/tools/clippy/tests/ui/deref_addrof.rs | 4 +- .../tests/ui/diverging_sub_expression.rs | 1 - .../tests/ui/diverging_sub_expression.stderr | 22 +- .../clippy/tests/ui/doc/doc-fixable.fixed | 215 + .../tests/ui/doc/{doc.rs => doc-fixable.rs} | 19 +- .../clippy/tests/ui/doc/doc-fixable.stderr | 184 + src/tools/clippy/tests/ui/doc/doc.stderr | 190 - src/tools/clippy/tests/ui/doc/issue_1832.rs | 9 + src/tools/clippy/tests/ui/doc/issue_902.rs | 7 + .../tests/ui/doc/unbalanced_ticks.stderr | 12 +- src/tools/clippy/tests/ui/doc_errors.rs | 1 - src/tools/clippy/tests/ui/doc_errors.stderr | 14 +- src/tools/clippy/tests/ui/doc_unsafe.rs | 15 + src/tools/clippy/tests/ui/double_neg.rs | 1 + src/tools/clippy/tests/ui/double_neg.stderr | 2 +- .../clippy/tests/ui/enum_variants.stderr | 2 +- .../clippy/tests/ui/equatable_if_let.fixed | 9 + src/tools/clippy/tests/ui/equatable_if_let.rs | 9 + .../clippy/tests/ui/equatable_if_let.stderr | 8 +- .../clippy/tests/ui/eval_order_dependence.rs | 2 - .../tests/ui/eval_order_dependence.stderr | 16 +- .../clippy/tests/ui/expect_fun_call.fixed | 1 + src/tools/clippy/tests/ui/expect_fun_call.rs | 1 + .../clippy/tests/ui/expect_fun_call.stderr | 24 +- .../clippy/tests/ui/fallible_impl_from.stderr | 6 +- .../tests/ui/field_reassign_with_default.rs | 64 + .../ui/field_reassign_with_default.stderr | 26 +- .../tests/ui/fn_params_excessive_bools.rs | 1 + .../tests/ui/fn_params_excessive_bools.stderr | 12 +- .../clippy/tests/ui/fn_to_numeric_cast_any.rs | 76 + .../tests/ui/fn_to_numeric_cast_any.stderr | 106 + src/tools/clippy/tests/ui/format.fixed | 10 +- src/tools/clippy/tests/ui/format.rs | 10 +- src/tools/clippy/tests/ui/format.stderr | 40 +- src/tools/clippy/tests/ui/format_args.fixed | 117 + src/tools/clippy/tests/ui/format_args.rs | 117 + src/tools/clippy/tests/ui/format_args.stderr | 130 + .../clippy/tests/ui/format_args_unfixable.rs | 61 + .../tests/ui/format_args_unfixable.stderr | 175 + src/tools/clippy/tests/ui/formatting.rs | 1 + src/tools/clippy/tests/ui/formatting.stderr | 12 +- src/tools/clippy/tests/ui/future_not_send.rs | 1 - .../clippy/tests/ui/future_not_send.stderr | 36 +- src/tools/clippy/tests/ui/if_not_else.rs | 10 + src/tools/clippy/tests/ui/if_not_else.stderr | 4 +- src/tools/clippy/tests/ui/implicit_hasher.rs | 1 - .../clippy/tests/ui/implicit_hasher.stderr | 24 +- .../clippy/tests/ui/implicit_return.fixed | 1 - src/tools/clippy/tests/ui/implicit_return.rs | 1 - .../clippy/tests/ui/implicit_return.stderr | 32 +- .../tests/ui/implicit_saturating_sub.fixed | 8 + .../tests/ui/implicit_saturating_sub.rs | 8 + .../ui/inconsistent_struct_constructor.fixed | 1 - .../ui/inconsistent_struct_constructor.rs | 1 - .../ui/inconsistent_struct_constructor.stderr | 4 +- src/tools/clippy/tests/ui/issue-7447.stderr | 19 + src/tools/clippy/tests/ui/issue_4266.rs | 1 - src/tools/clippy/tests/ui/issue_4266.stderr | 4 +- src/tools/clippy/tests/ui/iter_count.fixed | 7 +- src/tools/clippy/tests/ui/iter_count.rs | 7 +- src/tools/clippy/tests/ui/iter_count.stderr | 62 +- .../clippy/tests/ui/len_without_is_empty.rs | 2 - .../tests/ui/len_without_is_empty.stderr | 34 +- src/tools/clippy/tests/ui/literals.rs | 5 +- src/tools/clippy/tests/ui/literals.stderr | 74 +- .../clippy/tests/ui/macro_use_imports.fixed | 1 - .../clippy/tests/ui/macro_use_imports.rs | 1 - .../clippy/tests/ui/macro_use_imports.stderr | 14 +- .../tests/ui/manual_assert.edition2018.fixed | 43 + ...tderr => manual_assert.edition2018.stderr} | 14 +- .../tests/ui/manual_assert.edition2021.fixed | 43 + .../tests/ui/manual_assert.edition2021.stderr | 60 + src/tools/clippy/tests/ui/manual_assert.fixed | 3 + src/tools/clippy/tests/ui/manual_assert.rs | 3 + .../clippy/tests/ui/manual_async_fn.fixed | 1 - src/tools/clippy/tests/ui/manual_async_fn.rs | 1 - .../clippy/tests/ui/manual_async_fn.stderr | 20 +- .../clippy/tests/ui/manual_map_option.fixed | 1 - .../clippy/tests/ui/manual_map_option.rs | 1 - .../clippy/tests/ui/manual_map_option.stderr | 42 +- .../clippy/tests/ui/manual_unwrap_or.fixed | 4 +- src/tools/clippy/tests/ui/manual_unwrap_or.rs | 4 +- .../clippy/tests/ui/many_single_char_names.rs | 1 + .../tests/ui/many_single_char_names.stderr | 10 +- .../ui/match_expr_like_matches_macro.stderr | 35 +- .../clippy/tests/ui/match_overlapping_arm.rs | 66 +- .../tests/ui/match_overlapping_arm.stderr | 34 +- src/tools/clippy/tests/ui/match_ref_pats.rs | 44 +- .../clippy/tests/ui/match_ref_pats.stderr | 57 +- .../tests/ui/match_str_case_mismatch.rs | 184 + .../tests/ui/match_str_case_mismatch.stderr | 80 + ... => match_wild_err_arm.edition2018.stderr} | 8 +- .../ui/match_wild_err_arm.edition2021.stderr | 35 + .../clippy/tests/ui/match_wild_err_arm.rs | 3 + src/tools/clippy/tests/ui/methods.rs | 1 - src/tools/clippy/tests/ui/methods.stderr | 4 +- src/tools/clippy/tests/ui/missing-doc.rs | 9 +- src/tools/clippy/tests/ui/missing-doc.stderr | 48 +- .../clippy/tests/ui/missing_panics_doc.rs | 1 - .../clippy/tests/ui/missing_panics_doc.stderr | 34 +- .../tests/ui/mistyped_literal_suffix.fixed | 2 +- .../tests/ui/mistyped_literal_suffix.rs | 2 +- .../tests/ui/mistyped_literal_suffix.stderr | 18 +- src/tools/clippy/tests/ui/mut_mut.rs | 10 + src/tools/clippy/tests/ui/mut_mut.stderr | 18 +- .../needless_arbitrary_self_type_unfixable.rs | 1 + ...dless_arbitrary_self_type_unfixable.stderr | 2 +- .../clippy/tests/ui/needless_borrow_pat.rs | 1 - .../tests/ui/needless_borrow_pat.stderr | 24 +- .../clippy/tests/ui/needless_continue.rs | 1 + .../clippy/tests/ui/needless_continue.stderr | 16 +- .../clippy/tests/ui/needless_lifetimes.rs | 5 + .../clippy/tests/ui/needless_lifetimes.stderr | 44 +- .../clippy/tests/ui/needless_return.fixed | 1 - src/tools/clippy/tests/ui/needless_return.rs | 1 - .../clippy/tests/ui/needless_return.stderr | 64 +- src/tools/clippy/tests/ui/no_effect.rs | 8 +- src/tools/clippy/tests/ui/no_effect.stderr | 28 +- .../clippy/tests/ui/non_expressive_names.rs | 8 +- .../tests/ui/non_expressive_names.stderr | 12 +- .../clippy/tests/ui/nonminimal_bool.stderr | 20 +- .../clippy/tests/ui/option_if_let_else.fixed | 4 +- .../clippy/tests/ui/option_if_let_else.rs | 4 +- .../clippy/tests/ui/option_if_let_else.stderr | 28 +- .../clippy/tests/ui/panic_in_result_fn.rs | 1 - .../clippy/tests/ui/panic_in_result_fn.stderr | 28 +- src/tools/clippy/tests/ui/ptr_arg.rs | 4 + src/tools/clippy/tests/ui/question_mark.fixed | 34 + src/tools/clippy/tests/ui/question_mark.rs | 36 + .../clippy/tests/ui/question_mark.stderr | 16 +- .../clippy/tests/ui/redundant_clone.fixed | 2 +- .../clippy/tests/ui/redundant_clone.stderr | 14 +- .../tests/ui/redundant_closure_call_early.rs | 1 + src/tools/clippy/tests/ui/redundant_else.rs | 4 +- .../tests/ui/ref_binding_to_reference.rs | 1 - .../tests/ui/ref_binding_to_reference.stderr | 14 +- src/tools/clippy/tests/ui/rename.fixed | 57 +- src/tools/clippy/tests/ui/rename.rs | 57 +- src/tools/clippy/tests/ui/rename.stderr | 188 +- .../tests/ui/semicolon_if_nothing_returned.rs | 12 + src/tools/clippy/tests/ui/shadow.rs | 5 + src/tools/clippy/tests/ui/shadow.stderr | 60 +- .../ui/should_impl_trait/corner_cases.rs | 2 - .../ui/should_impl_trait/method_list_1.rs | 2 - .../ui/should_impl_trait/method_list_1.stderr | 28 +- .../ui/should_impl_trait/method_list_2.rs | 2 - .../ui/should_impl_trait/method_list_2.stderr | 30 +- src/tools/clippy/tests/ui/similar_names.rs | 7 +- .../clippy/tests/ui/similar_names.stderr | 28 +- .../ui/single_component_path_imports.fixed | 1 - .../tests/ui/single_component_path_imports.rs | 1 - .../ui/single_component_path_imports.stderr | 4 +- .../single_component_path_imports_macro.fixed | 1 - .../ui/single_component_path_imports_macro.rs | 1 - ...single_component_path_imports_macro.stderr | 2 +- ...gle_component_path_imports_nested_first.rs | 1 - ...component_path_imports_nested_first.stderr | 6 +- ...ingle_component_path_imports_self_after.rs | 1 - ...ngle_component_path_imports_self_before.rs | 1 - src/tools/clippy/tests/ui/string_slice.rs | 10 + src/tools/clippy/tests/ui/string_slice.stderr | 22 + .../tests/ui/suspicious_else_formatting.rs | 1 + .../ui/suspicious_else_formatting.stderr | 18 +- .../ui/suspicious_operation_groupings.rs | 3 +- .../ui/suspicious_operation_groupings.stderr | 52 +- .../clippy/tests/ui/to_string_in_display.rs | 2 +- .../clippy/tests/ui/trailing_empty_array.rs | 186 + .../tests/ui/trailing_empty_array.stderr | 120 + src/tools/clippy/tests/ui/transmute.rs | 27 + src/tools/clippy/tests/ui/transmute.stderr | 92 +- .../tests/ui/undocumented_unsafe_blocks.rs | 287 + .../ui/undocumented_unsafe_blocks.stderr | 159 + src/tools/clippy/tests/ui/uninit_vec.rs | 94 + src/tools/clippy/tests/ui/uninit_vec.stderr | 105 + src/tools/clippy/tests/ui/unit_hash.rs | 27 + src/tools/clippy/tests/ui/unit_hash.stderr | 27 + .../clippy/tests/ui/unnecessary_sort_by.fixed | 5 + .../clippy/tests/ui/unnecessary_sort_by.rs | 5 + .../tests/ui/unnecessary_sort_by.stderr | 24 +- src/tools/clippy/tests/ui/unused_async.rs | 1 - src/tools/clippy/tests/ui/unused_async.stderr | 2 +- src/tools/clippy/tests/ui/use_self.fixed | 1 - src/tools/clippy/tests/ui/use_self.rs | 1 - src/tools/clippy/tests/ui/use_self.stderr | 56 +- .../tests/ui/used_underscore_binding.rs | 1 - .../tests/ui/used_underscore_binding.stderr | 12 +- .../clippy/tests/ui/useless_conversion.fixed | 2 +- .../clippy/tests/ui/useless_conversion.rs | 2 +- .../clippy/tests/ui/wildcard_imports.fixed | 15 +- src/tools/clippy/tests/ui/wildcard_imports.rs | 15 +- .../clippy/tests/ui/wildcard_imports.stderr | 48 +- .../clippy/tests/ui/wrong_self_convention.rs | 1 - .../tests/ui/wrong_self_convention.stderr | 48 +- .../clippy/tests/ui/wrong_self_convention2.rs | 1 - .../tests/ui/wrong_self_convention2.stderr | 4 +- .../tests/ui/wrong_self_conventions_mut.rs | 1 - .../ui/wrong_self_conventions_mut.stderr | 4 +- src/tools/clippy/tests/ui_test/eq_op.rs | 15 + src/tools/compiletest/src/common.rs | 3 + src/tools/compiletest/src/header.rs | 9 +- src/tools/compiletest/src/header/tests.rs | 2 +- src/tools/compiletest/src/json.rs | 2 - src/tools/compiletest/src/main.rs | 4 +- src/tools/compiletest/src/runtest.rs | 3 - src/tools/compiletest/src/util.rs | 6 +- src/tools/html-checker/main.rs | 23 + src/tools/linkchecker/main.rs | 2 + src/tools/rustdoc-gui/tester.js | 8 +- src/tools/rustdoc-js/tester.js | 26 +- .../.github/workflows/rustdoc_check.yml | 25 + .../.github/workflows/upload-assets.yml | 29 +- .../rustfmt/.github/workflows/windows.yml | 3 - src/tools/rustfmt/CHANGELOG.md | 67 + src/tools/rustfmt/Cargo.lock | 372 +- src/tools/rustfmt/Cargo.toml | 10 +- src/tools/rustfmt/Configurations.md | 89 +- src/tools/rustfmt/Contributing.md | 2 +- src/tools/rustfmt/README.md | 23 +- src/tools/rustfmt/appveyor.yml | 55 - src/tools/rustfmt/intellij.md | 23 +- src/tools/rustfmt/legacy-rustfmt.toml | 2 - src/tools/rustfmt/rust-toolchain | 2 +- src/tools/rustfmt/src/attr.rs | 9 +- src/tools/rustfmt/src/attr/doc_comment.rs | 2 +- src/tools/rustfmt/src/bin/main.rs | 4 +- src/tools/rustfmt/src/cargo-fmt/main.rs | 301 +- .../src/cargo-fmt/test/message_format.rs | 80 + src/tools/rustfmt/src/cargo-fmt/test/mod.rs | 137 + .../rustfmt/src/cargo-fmt/test/targets.rs | 134 + src/tools/rustfmt/src/chains.rs | 4 +- src/tools/rustfmt/src/comment.rs | 84 +- src/tools/rustfmt/src/config/mod.rs | 9 +- src/tools/rustfmt/src/config/options.rs | 17 +- src/tools/rustfmt/src/emitter/checkstyle.rs | 4 +- src/tools/rustfmt/src/emitter/diff.rs | 2 +- src/tools/rustfmt/src/expr.rs | 61 +- src/tools/rustfmt/src/format-diff/main.rs | 2 +- src/tools/rustfmt/src/formatting.rs | 13 +- src/tools/rustfmt/src/formatting/generated.rs | 7 + src/tools/rustfmt/src/git-rustfmt/main.rs | 2 +- src/tools/rustfmt/src/imports.rs | 150 +- src/tools/rustfmt/src/items.rs | 358 +- src/tools/rustfmt/src/lib.rs | 4 +- src/tools/rustfmt/src/lists.rs | 12 +- src/tools/rustfmt/src/macros.rs | 16 +- src/tools/rustfmt/src/matches.rs | 11 +- src/tools/rustfmt/src/missed_spans.rs | 20 +- src/tools/rustfmt/src/modules.rs | 16 +- src/tools/rustfmt/src/overflow.rs | 6 +- src/tools/rustfmt/src/pairs.rs | 16 +- src/tools/rustfmt/src/patterns.rs | 32 +- src/tools/rustfmt/src/reorder.rs | 5 +- src/tools/rustfmt/src/spanned.rs | 2 +- src/tools/rustfmt/src/syntux/parser.rs | 18 +- src/tools/rustfmt/src/syntux/session.rs | 8 +- src/tools/rustfmt/src/test/mod.rs | 29 +- src/tools/rustfmt/src/test/mod_resolver.rs | 42 +- src/tools/rustfmt/src/types.rs | 139 +- src/tools/rustfmt/src/utils.rs | 6 +- src/tools/rustfmt/src/visitor.rs | 238 +- .../divergent-crate-dir-names/Cargo.toml | 13 + .../dependency-dir-name/Cargo.toml | 10 + .../dependency-dir-name/src/lib.rs | 7 + .../subdep-dir-name/Cargo.toml | 7 + .../subdep-dir-name/src/lib.rs | 7 + .../divergent-crate-dir-names/src/main.rs | 3 + .../workspaces/path-dep-above/e/Cargo.toml | 8 + .../workspaces/path-dep-above/e/src/main.rs | 1 + .../workspaces/path-dep-above/ws/Cargo.toml | 5 + .../workspaces/path-dep-above/ws/a/Cargo.toml | 6 + .../path-dep-above/ws/a/d/Cargo.toml | 7 + .../path-dep-above/ws/a/d/f/Cargo.toml | 4 + .../path-dep-above/ws/a/d/f/src/lib.rs | 1 + .../path-dep-above/ws/a/d/src/lib.rs | 1 + .../path-dep-above/ws/a/src/main.rs | 1 + .../workspaces/path-dep-above/ws/b/Cargo.toml | 6 + .../path-dep-above/ws/b/src/main.rs | 1 + .../workspaces/path-dep-above/ws/c/Cargo.toml | 4 + .../workspaces/path-dep-above/ws/c/src/lib.rs | 1 + .../tests/mod-resolver/issue-5063/foo.rs | 2 + .../mod-resolver/issue-5063/foo/bar/baz.rs | 1 + .../tests/mod-resolver/issue-5063/main.rs | 5 + .../source/binop-separator-back/bitwise.rs | 14 + .../tests/source/binop-separator-back/comp.rs | 23 + .../source/binop-separator-back/logic.rs | 7 + .../tests/source/binop-separator-back/math.rs | 7 + .../source/binop-separator-back/patterns.rs | 9 + .../source/binop-separator-back/range.rs | 7 + .../configs/format_generated_files/false.rs | 8 + .../configs/format_generated_files/true.rs | 8 + .../group_imports/One-merge_imports.rs | 17 + .../configs/group_imports/One-nested.rs | 7 + .../configs/group_imports/One-no_reorder.rs | 16 + .../tests/source/configs/group_imports/One.rs | 15 + .../source/empty-item-single-line-false.rs | 46 + .../rustfmt/tests/source/hex_literal_lower.rs | 5 + .../rustfmt/tests/source/hex_literal_upper.rs | 5 + src/tools/rustfmt/tests/source/impls.rs | 8 + .../tests/source/imports_granularity_one.rs | 60 + src/tools/rustfmt/tests/source/issue-3158.rs | 74 + src/tools/rustfmt/tests/source/issue-4530.rs | 4 + .../source/issue-4615/minimum_example.rs | 4 + .../rustfmt/tests/source/issue-4816/lib.rs | 10 + .../source/issue-4926/deeply_nested_struct.rs | 35 + ...ply_nested_struct_with_long_field_names.rs | 43 + .../deeply_nested_struct_with_many_fields.rs | 44 + .../source/issue-4926/enum_struct_field.rs | 35 + .../source/issue-4926/minimum_example.rs | 10 + .../struct_with_long_field_names.rs | 21 + .../issue-4926/struct_with_many_fields.rs | 21 + .../source/issue-4984/minimum_example.rs | 2 + .../source/issue-4984/multi_line_derive.rs | 20 + .../issue-4984/multiple_comments_within.rs | 8 + src/tools/rustfmt/tests/source/issue-5011.rs | 12 + src/tools/rustfmt/tests/source/issue_4032.rs | 4 + src/tools/rustfmt/tests/source/issue_4257.rs | 13 + src/tools/rustfmt/tests/source/issue_4322.rs | 3 + src/tools/rustfmt/tests/source/issue_4579.rs | 15 + src/tools/rustfmt/tests/source/issue_4911.rs | 6 + src/tools/rustfmt/tests/source/issue_4943.rs | 9 + src/tools/rustfmt/tests/source/issue_4954.rs | 5 + src/tools/rustfmt/tests/source/issue_4963.rs | 5 + .../item-brace-style-always-next-line.rs | 35 + .../source/match-block-trailing-comma.rs | 8 + src/tools/rustfmt/tests/source/trait.rs | 7 + .../target/binop-separator-back/bitwise.rs | 18 + .../tests/target/binop-separator-back/comp.rs | 33 + .../target/binop-separator-back/logic.rs | 10 + .../tests/target/binop-separator-back/math.rs | 23 + .../target/binop-separator-back/patterns.rs | 11 + .../target/binop-separator-back/range.rs | 9 + .../configs/format_generated_files/false.rs | 8 + .../configs/format_generated_files/true.rs | 6 + .../group_imports/One-merge_imports.rs | 14 + .../configs/group_imports/One-nested.rs | 6 + .../configs/group_imports/One-no_reorder.rs | 12 + .../tests/target/configs/group_imports/One.rs | 11 + .../target/empty-item-single-line-false.rs | 41 + .../rustfmt/tests/target/hex_literal_lower.rs | 5 + .../tests/target/hex_literal_preserve.rs | 5 + .../rustfmt/tests/target/hex_literal_upper.rs | 5 + src/tools/rustfmt/tests/target/impls.rs | 8 + .../tests/target/imports_granularity_one.rs | 79 + src/tools/rustfmt/tests/target/issue-3158.rs | 74 + src/tools/rustfmt/tests/target/issue-4530.rs | 9 + .../target/issue-4615/minimum_example.rs | 5 + .../rustfmt/tests/target/issue-4816/lib.rs | 35 + .../rustfmt/tests/target/issue-4908-2.rs | 20 + src/tools/rustfmt/tests/target/issue-4908.rs | 34 + .../target/issue-4926/deeply_nested_struct.rs | 38 + ...ply_nested_struct_with_long_field_names.rs | 44 + .../deeply_nested_struct_with_many_fields.rs | 54 + .../target/issue-4926/enum_struct_field.rs | 41 + .../target/issue-4926/minimum_example.rs | 10 + .../struct_with_long_field_names.rs | 24 + .../issue-4926/struct_with_many_fields.rs | 34 + .../target/issue-4984/minimum_example.rs | 2 + .../target/issue-4984/multi_line_derive.rs | 26 + .../issue-4984/multiple_comments_within.rs | 11 + .../target/issue-4984/should_not_change.rs | 5 + .../target/issue-5005/minimum_example.rs | 9 + .../target/issue-5009/1_minimum_example.rs | 4 + .../2_many_in_connectors_in_pattern.rs | 3 + ...sted_for_loop_with_connector_in_pattern.rs | 5 + .../4_nested_for_loop_with_if_elseif_else.rs | 13 + ...r_loop_with_connector_in_if_elseif_else.rs | 15 + ...sted_for_loop_with_connector_in_pattern.rs | 32 + src/tools/rustfmt/tests/target/issue-5011.rs | 8 + .../issue-5012/trailing_comma_always.rs | 8 + .../target/issue-5012/trailing_comma_never.rs | 8 + .../target/issue-5033/minimum_example.rs | 8 + .../tests/target/issue-5033/nested_modules.rs | 11 + src/tools/rustfmt/tests/target/issue_4031.rs | 21 + src/tools/rustfmt/tests/target/issue_4032.rs | 18 + src/tools/rustfmt/tests/target/issue_4110.rs | 55 + src/tools/rustfmt/tests/target/issue_4257.rs | 18 + src/tools/rustfmt/tests/target/issue_4322.rs | 5 + src/tools/rustfmt/tests/target/issue_4579.rs | 16 + src/tools/rustfmt/tests/target/issue_4850.rs | 4 + src/tools/rustfmt/tests/target/issue_4911.rs | 9 + src/tools/rustfmt/tests/target/issue_4936.rs | 10 + src/tools/rustfmt/tests/target/issue_4943.rs | 10 + src/tools/rustfmt/tests/target/issue_4954.rs | 7 + src/tools/rustfmt/tests/target/issue_4963.rs | 9 + .../item-brace-style-always-next-line.rs | 29 + .../target/match-block-trailing-comma.rs | 10 + src/tools/rustfmt/tests/target/trait.rs | 7 + src/tools/rustfmt/triagebot.toml | 1 + src/tools/tidy/src/deps.rs | 11 +- src/tools/tidy/src/edition.rs | 10 +- src/tools/tidy/src/features.rs | 47 +- src/tools/tidy/src/lib.rs | 1 + src/tools/tidy/src/style.rs | 10 +- src/tools/tidy/src/ui_tests.rs | 4 +- src/version | 2 +- .../.cargo-checksum.json | 0 .../CHANGELOG.md | 0 .../Cargo.lock | 0 .../Cargo.toml | 0 .../LICENSE-APACHE | 0 .../LICENSE-MIT | 0 .../{addr2line => addr2line-0.16.0}/README.md | 0 .../bench.plot.r | 0 .../benchmark.sh | 0 .../{addr2line => addr2line-0.16.0}/coverage | 0 .../examples/addr2line.rs | 0 .../rustfmt.toml | 0 .../src/function.rs | 0 .../src/lazy.rs | 0 .../src/lib.rs | 0 .../tests/correctness.rs | 0 .../tests/output_equivalence.rs | 0 .../tests/parse.rs | 0 vendor/anyhow/.cargo-checksum.json | 2 +- vendor/anyhow/Cargo.toml | 5 +- vendor/anyhow/README.md | 6 +- vendor/anyhow/rust-toolchain.toml | 2 + vendor/anyhow/src/lib.rs | 33 +- vendor/anyhow/src/macros.rs | 13 +- vendor/anyhow/tests/test_context.rs | 1 + vendor/anyhow/tests/ui/no-impl.stderr | 59 +- vendor/anyhow/tests/ui/temporary-value.stderr | 2 +- vendor/arrayvec/.cargo-checksum.json | 2 +- vendor/arrayvec/CHANGELOG.md | 14 + vendor/arrayvec/Cargo.toml | 11 +- vendor/arrayvec/src/array_string.rs | 48 +- vendor/arrayvec/src/arrayvec.rs | 33 +- vendor/arrayvec/src/errors.rs | 2 +- vendor/arrayvec/tests/tests.rs | 7 +- vendor/camino/.cargo-checksum.json | 1 + vendor/camino/CHANGELOG.md | 57 + vendor/camino/CODE_OF_CONDUCT.md | 133 + vendor/camino/Cargo.lock | 277 + vendor/camino/Cargo.toml | 46 + vendor/{gimli => camino}/LICENSE-APACHE | 0 .../{itertools-0.8.2 => camino}/LICENSE-MIT | 2 - vendor/camino/README.md | 125 + vendor/camino/build.rs | 40 + vendor/camino/clippy.toml | 1 + vendor/camino/examples/serde.rs | 64 + vendor/camino/examples/structopt.rs | 33 + vendor/camino/rustfmt.toml | 2 + vendor/camino/src/lib.rs | 2458 ++ vendor/camino/src/serde_impls.rs | 55 + vendor/camino/src/tests.rs | 46 + vendor/camino/tests/integration_tests.rs | 115 + vendor/cargo-platform/.cargo-checksum.json | 1 + vendor/cargo-platform/Cargo.lock | 65 + vendor/cargo-platform/Cargo.toml | 24 + vendor/cargo-platform/LICENSE-APACHE | 201 + vendor/cargo-platform/LICENSE-MIT | 23 + vendor/cargo-platform/examples/matches.rs | 55 + vendor/cargo-platform/src/cfg.rs | 319 + vendor/cargo-platform/src/error.rs | 67 + vendor/cargo-platform/src/lib.rs | 146 + vendor/cargo-platform/tests/test_cfg.rs | 251 + vendor/cargo_metadata/.cargo-checksum.json | 1 + vendor/cargo_metadata/Cargo.toml | 49 + vendor/cargo_metadata/LICENSE-MIT | 23 + vendor/cargo_metadata/README.md | 12 + vendor/cargo_metadata/src/dependency.rs | 90 + vendor/cargo_metadata/src/diagnostic.rs | 160 + vendor/cargo_metadata/src/errors.rs | 110 + vendor/cargo_metadata/src/lib.rs | 641 + vendor/cargo_metadata/src/messages.rs | 165 + vendor/cargo_metadata/tests/selftest.rs | 159 + vendor/cargo_metadata/tests/test_samples.rs | 621 + vendor/cc/.cargo-checksum.json | 2 +- vendor/cc/Cargo.lock | 56 +- vendor/cc/Cargo.toml | 11 +- vendor/cc/src/lib.rs | 34 +- vendor/compiler_builtins/.cargo-checksum.json | 2 +- vendor/compiler_builtins/Cargo.lock | 2 +- vendor/compiler_builtins/Cargo.toml | 2 +- vendor/compiler_builtins/build.rs | 17 +- vendor/compiler_builtins/src/lib.rs | 3 +- vendor/compiler_builtins/src/math.rs | 50 +- vendor/compiler_builtins/src/mem/impls.rs | 262 +- vendor/compiletest_rs/.cargo-checksum.json | 2 +- vendor/compiletest_rs/Cargo.toml | 11 +- vendor/compiletest_rs/src/common.rs | 4 + vendor/compiletest_rs/src/header.rs | 8 +- vendor/compiletest_rs/src/lib.rs | 4 + vendor/compiletest_rs/src/runtest.rs | 5 + vendor/dlmalloc/.cargo-checksum.json | 2 +- vendor/dlmalloc/Cargo.toml | 11 +- vendor/dlmalloc/src/dlmalloc.rs | 14 +- vendor/dlmalloc/src/global.rs | 2 + vendor/dlmalloc/src/lib.rs | 15 +- vendor/dlmalloc/src/macos.rs | 72 - vendor/dlmalloc/src/{linux.rs => unix.rs} | 51 +- vendor/dlmalloc/src/wasm.rs | 12 +- vendor/env_logger-0.8.4/.cargo-checksum.json | 1 + vendor/env_logger-0.8.4/CHANGELOG.md | 3 + vendor/env_logger-0.8.4/Cargo.toml | 65 + .../LICENSE-APACHE | 0 vendor/env_logger-0.8.4/LICENSE-MIT | 25 + vendor/env_logger-0.8.4/README.md | 185 + vendor/env_logger-0.8.4/src/filter/mod.rs | 868 + vendor/env_logger-0.8.4/src/filter/regex.rs | 29 + vendor/env_logger-0.8.4/src/filter/string.rs | 24 + .../src/fmt/humantime/extern_impl.rs | 118 + .../env_logger-0.8.4/src/fmt/humantime/mod.rs | 11 + .../src/fmt/humantime/shim_impl.rs | 5 + vendor/env_logger-0.8.4/src/fmt/mod.rs | 547 + .../env_logger-0.8.4/src/fmt/writer/atty.rs | 32 + vendor/env_logger-0.8.4/src/fmt/writer/mod.rs | 252 + .../src/fmt/writer/termcolor/extern_impl.rs | 510 + .../src/fmt/writer/termcolor/mod.rs | 12 + .../src/fmt/writer/termcolor/shim_impl.rs | 73 + vendor/env_logger-0.8.4/src/lib.rs | 1299 + .../tests/init-twice-retains-filter.rs | 40 + vendor/env_logger-0.8.4/tests/log-in-log.rs | 39 + .../env_logger-0.8.4/tests/log_tls_dtors.rs | 66 + .../env_logger-0.8.4/tests/regexp_filter.rs | 57 + .../.cargo-checksum.json | 0 vendor/{gimli => gimli-0.25.0}/CHANGELOG.md | 0 .../{gimli => gimli-0.25.0}/CONTRIBUTING.md | 0 vendor/{gimli => gimli-0.25.0}/Cargo.lock | 0 vendor/{gimli => gimli-0.25.0}/Cargo.toml | 0 .../{object => gimli-0.25.0}/LICENSE-APACHE | 0 vendor/{gimli => gimli-0.25.0}/LICENSE-MIT | 0 vendor/{gimli => gimli-0.25.0}/README.md | 0 .../{gimli => gimli-0.25.0}/benches/bench.rs | 0 .../examples/dwarf-validate.rs | 0 .../examples/dwarfdump.rs | 0 .../examples/simple.rs | 0 .../examples/simple_line.rs | 0 .../fixtures/self/README.md | 0 .../fixtures/self/debug_abbrev | Bin .../fixtures/self/debug_aranges | Bin .../fixtures/self/debug_info | Bin .../fixtures/self/debug_inlined | Bin .../fixtures/self/debug_line | Bin .../fixtures/self/debug_loc | Bin .../fixtures/self/debug_pubnames | Bin .../fixtures/self/debug_pubtypes | Bin .../fixtures/self/debug_ranges | Bin .../fixtures/self/debug_str | Bin .../fixtures/self/eh_frame | Bin .../fixtures/self/eh_frame_hdr | Bin vendor/gimli-0.25.0/rustfmt.toml | 0 vendor/{gimli => gimli-0.25.0}/src/arch.rs | 0 vendor/{gimli => gimli-0.25.0}/src/common.rs | 0 .../{gimli => gimli-0.25.0}/src/constants.rs | 0 .../{gimli => gimli-0.25.0}/src/endianity.rs | 0 vendor/{gimli => gimli-0.25.0}/src/leb128.rs | 0 vendor/{gimli => gimli-0.25.0}/src/lib.rs | 0 .../src/read/abbrev.rs | 0 .../{gimli => gimli-0.25.0}/src/read/addr.rs | 0 .../src/read/aranges.rs | 0 .../{gimli => gimli-0.25.0}/src/read/cfi.rs | 0 .../{gimli => gimli-0.25.0}/src/read/dwarf.rs | 0 .../src/read/endian_reader.rs | 0 .../src/read/endian_slice.rs | 0 .../{gimli => gimli-0.25.0}/src/read/line.rs | 0 .../{gimli => gimli-0.25.0}/src/read/lists.rs | 0 .../src/read/loclists.rs | 0 .../src/read/lookup.rs | 0 .../{gimli => gimli-0.25.0}/src/read/mod.rs | 0 vendor/{gimli => gimli-0.25.0}/src/read/op.rs | 0 .../src/read/pubnames.rs | 0 .../src/read/pubtypes.rs | 0 .../src/read/reader.rs | 0 .../src/read/rnglists.rs | 0 .../{gimli => gimli-0.25.0}/src/read/str.rs | 0 .../{gimli => gimli-0.25.0}/src/read/unit.rs | 0 .../{gimli => gimli-0.25.0}/src/read/value.rs | 0 .../{gimli => gimli-0.25.0}/src/test_util.rs | 0 .../src/write/abbrev.rs | 0 .../{gimli => gimli-0.25.0}/src/write/cfi.rs | 0 .../src/write/dwarf.rs | 0 .../src/write/endian_vec.rs | 0 .../{gimli => gimli-0.25.0}/src/write/line.rs | 0 .../{gimli => gimli-0.25.0}/src/write/loc.rs | 0 .../{gimli => gimli-0.25.0}/src/write/mod.rs | 0 .../{gimli => gimli-0.25.0}/src/write/op.rs | 0 .../src/write/range.rs | 0 .../src/write/section.rs | 0 .../{gimli => gimli-0.25.0}/src/write/str.rs | 0 .../{gimli => gimli-0.25.0}/src/write/unit.rs | 0 .../src/write/writer.rs | 0 .../tests/convert_self.rs | 0 .../tests/parse_self.rs | 0 vendor/humantime/.cargo-checksum.json | 1 + vendor/humantime/Cargo.toml | 37 + vendor/humantime/LICENSE-APACHE | 202 + vendor/humantime/LICENSE-MIT | 26 + vendor/humantime/README.md | 68 + vendor/humantime/benches/datetime_format.rs | 56 + vendor/humantime/benches/datetime_parse.rs | 47 + vendor/humantime/bulk.yaml | 8 + vendor/humantime/src/date.rs | 616 + vendor/humantime/src/duration.rs | 449 + vendor/humantime/src/lib.rs | 34 + vendor/humantime/src/wrapper.rs | 107 + vendor/humantime/vagga.yaml | 92 + vendor/indoc/.cargo-checksum.json | 1 + vendor/indoc/Cargo.toml | 36 + vendor/indoc/LICENSE-APACHE | 201 + vendor/indoc/LICENSE-MIT | 23 + vendor/indoc/README.md | 150 + vendor/indoc/src/error.rs | 47 + vendor/indoc/src/expr.rs | 56 + vendor/indoc/src/lib.rs | 385 + vendor/indoc/tests/compiletest.rs | 6 + vendor/indoc/tests/test_formatdoc.rs | 117 + vendor/indoc/tests/test_indoc.rs | 166 + vendor/indoc/tests/test_unindent.rs | 51 + vendor/indoc/tests/test_writedoc.rs | 55 + vendor/indoc/tests/ui/no-arguments.rs | 5 + vendor/indoc/tests/ui/no-arguments.stderr | 7 + vendor/indoc/tests/ui/non-lit.rs | 5 + vendor/indoc/tests/ui/non-lit.stderr | 5 + vendor/indoc/tests/ui/non-string.rs | 5 + vendor/indoc/tests/ui/non-string.stderr | 5 + vendor/indoc/tests/ui/printdoc-binary.rs | 5 + vendor/indoc/tests/ui/printdoc-binary.stderr | 5 + vendor/indoc/tests/ui/printdoc-extra-arg.rs | 5 + .../indoc/tests/ui/printdoc-extra-arg.stderr | 7 + vendor/indoc/tests/ui/printdoc-no-arg.rs | 5 + vendor/indoc/tests/ui/printdoc-no-arg.stderr | 5 + vendor/indoc/tests/ui/printdoc-no-display.rs | 7 + .../indoc/tests/ui/printdoc-no-display.stderr | 10 + .../indoc/tests/ui/printdoc-no-named-arg.rs | 5 + .../tests/ui/printdoc-no-named-arg.stderr | 7 + vendor/indoc/tests/ui/three-arguments.rs | 9 + vendor/indoc/tests/ui/three-arguments.stderr | 5 + vendor/indoc/tests/ui/two-arguments.rs | 9 + vendor/indoc/tests/ui/two-arguments.stderr | 5 + vendor/instant/.cargo-checksum.json | 2 +- vendor/instant/CHANGELOGS.md | 7 + vendor/instant/Cargo.toml | 7 +- vendor/instant/README.md | 25 +- vendor/instant/src/lib.rs | 4 +- vendor/instant/src/native.rs | 8 +- vendor/instant/src/wasm.rs | 78 + vendor/instant/tests/wasm.rs | 10 +- vendor/itertools-0.8.2/.cargo-checksum.json | 1 - vendor/itertools-0.8.2/Cargo.lock | 227 - vendor/itertools-0.8.2/Cargo.toml | 47 - vendor/itertools-0.8.2/README.rst | 620 - vendor/itertools-0.8.2/benches/bench1.rs | 806 - .../benches/combinations_with_replacement.rs | 34 - vendor/itertools-0.8.2/benches/extra/mod.rs | 4 - .../benches/extra/zipslices.rs | 189 - .../benches/fold_specialization.rs | 66 - vendor/itertools-0.8.2/benches/tree_fold1.rs | 126 - .../benches/tuple_combinations.rs | 97 - vendor/itertools-0.8.2/benches/tuples.rs | 190 - vendor/itertools-0.8.2/examples/iris.data | 150 - vendor/itertools-0.8.2/examples/iris.rs | 141 - vendor/itertools-0.8.2/src/adaptors/mod.rs | 1251 - .../src/adaptors/multi_product.rs | 220 - vendor/itertools-0.8.2/src/combinations.rs | 100 - .../src/combinations_with_replacement.rs | 108 - vendor/itertools-0.8.2/src/concat_impl.rs | 22 - .../itertools-0.8.2/src/cons_tuples_impl.rs | 68 - vendor/itertools-0.8.2/src/diff.rs | 61 - vendor/itertools-0.8.2/src/either_or_both.rs | 190 - vendor/itertools-0.8.2/src/exactly_one_err.rs | 58 - vendor/itertools-0.8.2/src/format.rs | 113 - vendor/itertools-0.8.2/src/free.rs | 236 - vendor/itertools-0.8.2/src/group_map.rs | 22 - vendor/itertools-0.8.2/src/groupbylazy.rs | 571 - vendor/itertools-0.8.2/src/impl_macros.rs | 14 - vendor/itertools-0.8.2/src/intersperse.rs | 79 - vendor/itertools-0.8.2/src/kmerge_impl.rs | 231 - vendor/itertools-0.8.2/src/lazy_buffer.rs | 68 - vendor/itertools-0.8.2/src/lib.rs | 2391 -- vendor/itertools-0.8.2/src/merge_join.rs | 87 - vendor/itertools-0.8.2/src/minmax.rs | 114 - vendor/itertools-0.8.2/src/multipeek_impl.rs | 104 - vendor/itertools-0.8.2/src/pad_tail.rs | 83 - .../itertools-0.8.2/src/peeking_take_while.rs | 149 - vendor/itertools-0.8.2/src/permutations.rs | 272 - .../src/process_results_impl.rs | 81 - vendor/itertools-0.8.2/src/put_back_n_impl.rs | 63 - vendor/itertools-0.8.2/src/rciter_impl.rs | 98 - vendor/itertools-0.8.2/src/repeatn.rs | 54 - vendor/itertools-0.8.2/src/size_hint.rs | 104 - vendor/itertools-0.8.2/src/sources.rs | 190 - vendor/itertools-0.8.2/src/tee.rs | 78 - vendor/itertools-0.8.2/src/tuple_impl.rs | 266 - vendor/itertools-0.8.2/src/unique_impl.rs | 134 - vendor/itertools-0.8.2/src/with_position.rs | 90 - vendor/itertools-0.8.2/src/zip_eq_impl.rs | 60 - vendor/itertools-0.8.2/src/zip_longest.rs | 78 - vendor/itertools-0.8.2/src/ziptuple.rs | 111 - .../tests/adaptors_no_collect.rs | 49 - .../tests/fold_specialization.rs | 15 - vendor/itertools-0.8.2/tests/merge_join.rs | 110 - .../tests/peeking_take_while.rs | 53 - vendor/itertools-0.8.2/tests/quick.rs | 1161 - vendor/itertools-0.8.2/tests/test_core.rs | 272 - vendor/itertools-0.8.2/tests/test_std.rs | 781 - vendor/itertools-0.8.2/tests/tuples.rs | 88 - vendor/itertools-0.8.2/tests/zip.rs | 65 - vendor/libc/.cargo-checksum.json | 2 +- vendor/libc/Cargo.toml | 2 +- vendor/libc/build.rs | 4 + vendor/libc/src/lib.rs | 8 +- vendor/libc/src/macros.rs | 16 + vendor/libc/src/solid/aarch64.rs | 4 + vendor/libc/src/solid/arm.rs | 4 + vendor/libc/src/solid/mod.rs | 904 + vendor/libc/src/unix/bsd/apple/b32/mod.rs | 4 + .../src/unix/bsd/apple/b64/aarch64/mod.rs | 6 + .../libc/src/unix/bsd/apple/b64/x86_64/mod.rs | 68 + vendor/libc/src/unix/bsd/apple/mod.rs | 96 +- .../src/unix/bsd/freebsdlike/dragonfly/mod.rs | 29 + .../bsd/freebsdlike/freebsd/freebsd11/mod.rs | 1 + .../bsd/freebsdlike/freebsd/freebsd12/mod.rs | 33 +- .../bsd/freebsdlike/freebsd/freebsd13/mod.rs | 83 +- .../src/unix/bsd/freebsdlike/freebsd/mod.rs | 615 +- vendor/libc/src/unix/bsd/freebsdlike/mod.rs | 24 +- .../src/unix/bsd/netbsdlike/netbsd/mod.rs | 254 + .../src/unix/bsd/netbsdlike/openbsd/mod.rs | 11 + vendor/libc/src/unix/haiku/mod.rs | 87 + .../libc/src/unix/linux_like/android/mod.rs | 70 +- .../src/unix/linux_like/emscripten/mod.rs | 6 - .../unix/linux_like/linux/arch/generic/mod.rs | 18 + .../unix/linux_like/linux/arch/mips/mod.rs | 18 + .../unix/linux_like/linux/arch/sparc/mod.rs | 18 + .../unix/linux_like/linux/gnu/b32/arm/mod.rs | 11 - .../unix/linux_like/linux/gnu/b32/mips/mod.rs | 11 - .../linux_like/linux/gnu/b32/sparc/mod.rs | 11 - .../unix/linux_like/linux/gnu/b32/x86/mod.rs | 11 - .../linux_like/linux/gnu/b64/aarch64/mod.rs | 11 - .../linux_like/linux/gnu/b64/mips64/mod.rs | 11 - .../unix/linux_like/linux/gnu/b64/s390x.rs | 11 - .../linux_like/linux/gnu/b64/sparc64/mod.rs | 11 - .../linux_like/linux/gnu/b64/x86_64/mod.rs | 11 - .../libc/src/unix/linux_like/linux/gnu/mod.rs | 19 + vendor/libc/src/unix/linux_like/linux/mod.rs | 66 +- .../unix/linux_like/linux/musl/b32/hexagon.rs | 11 - .../linux_like/linux/uclibc/x86_64/mod.rs | 8 + vendor/libc/src/unix/linux_like/mod.rs | 12 +- vendor/libc/src/unix/mod.rs | 24 +- vendor/libc/src/unix/redox/mod.rs | 2 + vendor/libc/src/unix/solarish/mod.rs | 30 + vendor/libc/src/vxworks/mod.rs | 0 vendor/libc/src/wasi.rs | 39 +- vendor/libc/src/windows/msvc/mod.rs | 9 - vendor/libc/src/windows/msvc/x86_64.rs | 140 - vendor/measureme/.cargo-checksum.json | 2 +- vendor/measureme/Cargo.toml | 11 +- vendor/measureme/src/counters.rs | 133 +- vendor/measureme/src/event_id.rs | 194 +- vendor/measureme/src/file_header.rs | 290 +- vendor/measureme/src/lib.rs | 10 +- vendor/measureme/src/profiler.rs | 20 +- vendor/measureme/src/raw_event.rs | 754 +- vendor/measureme/src/rustc.rs | 26 +- vendor/measureme/src/serialization.rs | 996 +- vendor/measureme/src/stringtable.rs | 656 +- .../.cargo-checksum.json | 0 vendor/{object => object-0.26.2}/CHANGELOG.md | 0 vendor/{object => object-0.26.2}/Cargo.lock | 0 vendor/{object => object-0.26.2}/Cargo.toml | 0 vendor/object-0.26.2/LICENSE-APACHE | 201 + vendor/{object => object-0.26.2}/LICENSE-MIT | 0 vendor/{object => object-0.26.2}/README.md | 0 vendor/{object => object-0.26.2}/clippy.toml | 0 .../{object => object-0.26.2}/examples/ar.rs | 0 .../examples/dyldcachedump.rs | 0 .../{object => object-0.26.2}/examples/nm.rs | 0 .../examples/objcopy.rs | 0 .../examples/objdump.rs | 0 .../examples/objectmap.rs | 0 .../examples/readobj.rs | 0 .../{object => object-0.26.2}/src/archive.rs | 0 .../{object => object-0.26.2}/src/common.rs | 0 vendor/{object => object-0.26.2}/src/elf.rs | 0 .../{object => object-0.26.2}/src/endian.rs | 0 vendor/{object => object-0.26.2}/src/lib.rs | 0 vendor/{object => object-0.26.2}/src/macho.rs | 0 vendor/{object => object-0.26.2}/src/pe.rs | 0 vendor/{object => object-0.26.2}/src/pod.rs | 0 .../{object => object-0.26.2}/src/read/any.rs | 0 .../src/read/archive.rs | 0 .../src/read/coff/comdat.rs | 0 .../src/read/coff/file.rs | 0 .../src/read/coff/mod.rs | 0 .../src/read/coff/relocation.rs | 0 .../src/read/coff/section.rs | 0 .../src/read/coff/symbol.rs | 0 .../src/read/elf/comdat.rs | 0 .../src/read/elf/compression.rs | 0 .../src/read/elf/dynamic.rs | 0 .../src/read/elf/file.rs | 0 .../src/read/elf/hash.rs | 0 .../src/read/elf/mod.rs | 0 .../src/read/elf/note.rs | 0 .../src/read/elf/relocation.rs | 0 .../src/read/elf/section.rs | 0 .../src/read/elf/segment.rs | 0 .../src/read/elf/symbol.rs | 0 .../src/read/elf/version.rs | 0 .../src/read/macho/dyld_cache.rs | 0 .../src/read/macho/fat.rs | 0 .../src/read/macho/file.rs | 0 .../src/read/macho/load_command.rs | 0 .../src/read/macho/mod.rs | 0 .../src/read/macho/relocation.rs | 0 .../src/read/macho/section.rs | 0 .../src/read/macho/segment.rs | 0 .../src/read/macho/symbol.rs | 0 .../{object => object-0.26.2}/src/read/mod.rs | 0 .../src/read/pe/file.rs | 0 .../src/read/pe/mod.rs | 0 .../src/read/pe/section.rs | 0 .../src/read/read_cache.rs | 0 .../src/read/read_ref.rs | 0 .../src/read/traits.rs | 0 .../src/read/util.rs | 0 .../src/read/wasm.rs | 0 .../src/write/coff.rs | 0 .../src/write/elf.rs | 0 .../src/write/macho.rs | 0 .../src/write/mod.rs | 0 .../src/write/string.rs | 0 .../src/write/util.rs | 0 .../tests/integration.rs | 0 .../tests/parse_self.rs | 0 .../tests/round_trip/bss.rs | 0 .../tests/round_trip/comdat.rs | 0 .../tests/round_trip/common.rs | 0 .../tests/round_trip/elf.rs | 0 .../tests/round_trip/macho.rs | 0 .../tests/round_trip/mod.rs | 0 .../tests/round_trip/tls.rs | 0 vendor/proc-macro2/.cargo-checksum.json | 2 +- vendor/proc-macro2/Cargo.toml | 7 +- vendor/proc-macro2/README.md | 7 +- vendor/proc-macro2/build.rs | 12 +- vendor/proc-macro2/src/detection.rs | 9 +- vendor/proc-macro2/src/fallback.rs | 20 +- vendor/proc-macro2/src/lib.rs | 36 +- vendor/proc-macro2/src/parse.rs | 7 +- vendor/proc-macro2/tests/comments.rs | 18 +- vendor/proc-macro2/tests/marker.rs | 12 +- vendor/proc-macro2/tests/test.rs | 13 +- vendor/proc-macro2/tests/test_fmt.rs | 4 +- vendor/quote/.cargo-checksum.json | 2 +- vendor/quote/Cargo.toml | 13 +- vendor/quote/benches/bench.rs | 192 + vendor/quote/src/ident_fragment.rs | 2 +- vendor/quote/src/lib.rs | 32 +- vendor/quote/src/runtime.rs | 19 - vendor/quote/src/to_tokens.rs | 14 +- vendor/quote/tests/test.rs | 29 +- ...does-not-have-iter-interpolated-dup.stderr | 10 + .../ui/does-not-have-iter-interpolated.stderr | 10 + .../ui/does-not-have-iter-separated.stderr | 10 + .../quote/tests/ui/does-not-have-iter.stderr | 10 + vendor/quote/tests/ui/not-quotable.stderr | 15 + vendor/quote/tests/ui/not-repeatable.stderr | 25 + vendor/quote/tests/ui/wrong-type-span.stderr | 8 + vendor/semver/.cargo-checksum.json | 1 + vendor/semver/Cargo.toml | 32 + vendor/semver/LICENSE-APACHE | 201 + vendor/semver/LICENSE-MIT | 23 + vendor/semver/README.md | 84 + vendor/semver/benches/parse.rs | 24 + vendor/semver/build.rs | 79 + vendor/semver/src/backport.rs | 63 + vendor/semver/src/display.rs | 165 + vendor/semver/src/error.rs | 90 + vendor/semver/src/eval.rs | 181 + vendor/semver/src/identifier.rs | 356 + vendor/semver/src/impls.rs | 156 + vendor/semver/src/lib.rs | 523 + vendor/semver/src/parse.rs | 391 + vendor/semver/src/serde.rs | 74 + vendor/semver/tests/node/mod.rs | 43 + vendor/semver/tests/test_identifier.rs | 38 + vendor/semver/tests/test_version.rs | 235 + vendor/semver/tests/test_version_req.rs | 408 + vendor/semver/tests/util/mod.rs | 39 + vendor/serde_json/.cargo-checksum.json | 2 +- vendor/serde_json/Cargo.toml | 5 +- vendor/serde_json/src/lexical/algorithm.rs | 2 +- vendor/serde_json/src/lexical/float.rs | 2 +- vendor/serde_json/src/lexical/math.rs | 6 +- vendor/serde_json/src/lib.rs | 5 +- vendor/serde_json/src/number.rs | 38 +- vendor/serde_json/src/read.rs | 4 +- vendor/serde_json/src/ser.rs | 4 +- vendor/sharded-slab/.cargo-checksum.json | 2 +- vendor/sharded-slab/CHANGELOG.md | 14 +- vendor/sharded-slab/Cargo.toml | 7 +- vendor/sharded-slab/IMPLEMENTATION.md | 135 + vendor/sharded-slab/README.md | 14 +- vendor/sharded-slab/benches/bench.rs | 2 +- vendor/sharded-slab/src/implementation.rs | 19 +- vendor/sharded-slab/src/lib.rs | 80 +- vendor/sharded-slab/src/pool.rs | 16 +- vendor/sharded-slab/src/shard.rs | 7 + vendor/syn/.cargo-checksum.json | 2 +- vendor/syn/Cargo.toml | 5 +- vendor/syn/build.rs | 4 + vendor/syn/src/export.rs | 1 - vendor/syn/src/generics.rs | 45 +- vendor/syn/src/lib.rs | 4 +- vendor/syn/src/lit.rs | 57 +- vendor/syn/src/parse_quote.rs | 6 +- vendor/syn/src/punctuated.rs | 12 +- vendor/syn/src/ty.rs | 102 +- vendor/syn/tests/common/eq.rs | 2 +- vendor/syn/tests/common/mod.rs | 1 + vendor/syn/tests/debug/mod.rs | 6 + vendor/syn/tests/repo/mod.rs | 11 +- vendor/syn/tests/test_derive_input.rs | 2 + vendor/syn/tests/test_generics.rs | 2 + vendor/syn/tests/test_item.rs | 35 + vendor/syn/tests/test_lit.rs | 9 +- vendor/syn/tests/test_meta.rs | 2 + vendor/syn/tests/test_parse_buffer.rs | 4 +- vendor/syn/tests/test_precedence.rs | 14 +- vendor/syn/tests/test_round_trip.rs | 1 + vendor/syn/tests/test_size.rs | 2 +- vendor/syn/tests/test_stmt.rs | 2 + vendor/syn/tests/test_ty.rs | 64 + vendor/synstructure/.cargo-checksum.json | 2 +- vendor/synstructure/Cargo.toml | 11 +- vendor/synstructure/src/lib.rs | 68 +- .../tracing-attributes/.cargo-checksum.json | 2 +- vendor/tracing-attributes/CHANGELOG.md | 19 +- vendor/tracing-attributes/Cargo.toml | 2 +- vendor/tracing-attributes/README.md | 4 +- vendor/tracing-attributes/src/lib.rs | 34 +- vendor/tracing-attributes/tests/async_fn.rs | 40 + vendor/tracing-attributes/tests/err.rs | 6 + .../tracing-subscriber/.cargo-checksum.json | 2 +- vendor/tracing-subscriber/CHANGELOG.md | 20 + vendor/tracing-subscriber/Cargo.toml | 11 +- vendor/tracing-subscriber/README.md | 2 +- .../src/filter/layer_filters.rs | 2 +- .../tracing-subscriber/src/filter/targets.rs | 2 +- vendor/tracing-subscriber/src/layer/mod.rs | 81 +- vendor/tracing-subscriber/src/lib.rs | 2 +- .../tests/layer_filters/downcast_raw.rs | 68 + .../tests/layer_filters/main.rs | 1 + vendor/tracing/.cargo-checksum.json | 2 +- vendor/tracing/CHANGELOG.md | 38 + vendor/tracing/Cargo.toml | 15 +- vendor/tracing/README.md | 8 +- vendor/tracing/src/instrument.rs | 203 +- vendor/tracing/src/lib.rs | 6 +- vendor/tracing/tests/event.rs | 108 + .../unic-char-property/.cargo-checksum.json | 1 + vendor/unic-char-property/Cargo.toml | 42 + vendor/unic-char-property/src/lib.rs | 59 + vendor/unic-char-property/src/macros.rs | 293 + vendor/unic-char-property/src/pkg_info.rs | 20 + vendor/unic-char-property/src/property.rs | 48 + vendor/unic-char-property/src/range_types.rs | 104 + vendor/unic-char-property/src/tables.rs | 117 + .../tests/bool_property_macro.rs | 73 + .../tests/enum_property_macro.rs | 87 + .../tests/tables/property_table.rsv | 3 + .../unic-char-property/tests/tables_tests.rs | 43 + vendor/unic-char-range/.cargo-checksum.json | 1 + vendor/unic-char-range/Cargo.toml | 51 + vendor/unic-char-range/benches/benchmarks.rs | 41 + .../examples/macro_use_std_tests.rs | 18 + vendor/unic-char-range/src/iter.rs | 151 + vendor/unic-char-range/src/iter_fused.rs | 15 + .../unic-char-range/src/iter_trusted_len.rs | 16 + vendor/unic-char-range/src/lib.rs | 75 + vendor/unic-char-range/src/macros.rs | 44 + vendor/unic-char-range/src/par_iter.rs | 110 + vendor/unic-char-range/src/pkg_info.rs | 20 + vendor/unic-char-range/src/range.rs | 231 + vendor/unic-char-range/src/step.rs | 45 + vendor/unic-char-range/tests/iter_tests.rs | 78 + vendor/unic-common/.cargo-checksum.json | 1 + vendor/unic-common/Cargo.toml | 44 + vendor/unic-common/README.md | 7 + vendor/unic-common/src/lib.rs | 31 + vendor/unic-common/src/pkg_info.rs | 20 + vendor/unic-common/src/version.rs | 72 + vendor/unic-emoji-char/.cargo-checksum.json | 1 + vendor/unic-emoji-char/Cargo.toml | 48 + vendor/unic-emoji-char/src/emoji.rs | 106 + vendor/unic-emoji-char/src/emoji_component.rs | 108 + vendor/unic-emoji-char/src/emoji_modifier.rs | 106 + .../src/emoji_modifier_base.rs | 106 + .../unic-emoji-char/src/emoji_presentation.rs | 106 + vendor/unic-emoji-char/src/emoji_version.rs | 17 + vendor/unic-emoji-char/src/lib.rs | 47 + vendor/unic-emoji-char/src/pkg_info.rs | 20 + vendor/unic-emoji-char/tables/emoji.rsv | 149 + .../tables/emoji_component.rsv | 9 + .../unic-emoji-char/tables/emoji_modifier.rsv | 5 + .../tables/emoji_modifier_base.rsv | 36 + .../tables/emoji_presentation.rsv | 79 + .../unic-emoji-char/tables/emoji_version.rsv | 3 + .../tests/emoji_version_tests.rs | 19 + vendor/unic-ucd-version/.cargo-checksum.json | 1 + vendor/unic-ucd-version/Cargo.toml | 42 + vendor/unic-ucd-version/src/lib.rs | 32 + vendor/unic-ucd-version/src/pkg_info.rs | 20 + .../unic-ucd-version/src/unicode_version.rs | 29 + .../tables/unicode_version.rsv | 3 + vendor/unic-ucd-version/tests/basic_tests.rs | 26 + vendor/unicode-bidi/.cargo-checksum.json | 2 +- vendor/unicode-bidi/Cargo.toml | 11 +- vendor/unicode-bidi/src/lib.rs | 2 +- vendor/unindent/.cargo-checksum.json | 1 + vendor/unindent/Cargo.toml | 25 + vendor/unindent/LICENSE-APACHE | 201 + vendor/unindent/LICENSE-MIT | 23 + vendor/unindent/README.md | 65 + vendor/unindent/src/lib.rs | 181 + version | 2 +- 4268 files changed, 124230 insertions(+), 59580 deletions(-) create mode 100644 compiler/rustc_ast/src/util/unicode.rs rename compiler/{rustc_middle/src/hir/map/collector.rs => rustc_ast_lowering/src/index.rs} (62%) create mode 100644 compiler/rustc_error_codes/src/error_codes/E0786.md delete mode 100644 compiler/rustc_middle/src/hir/map/blocks.rs create mode 100644 compiler/rustc_middle/src/traits/util.rs create mode 100644 compiler/rustc_mir_transform/src/reveal_all.rs create mode 100644 compiler/rustc_target/src/spec/x86_64_unknown_none.rs create mode 100644 library/portable-simd/.github/ISSUE_TEMPLATE/blank_issue.md create mode 100644 library/portable-simd/.github/ISSUE_TEMPLATE/bug_report.md create mode 100644 library/portable-simd/.github/ISSUE_TEMPLATE/config.yml create mode 100644 library/portable-simd/.github/ISSUE_TEMPLATE/feature_request.md create mode 100644 library/portable-simd/.github/PULL_REQUEST_TEMPLATE.md create mode 100644 library/portable-simd/.github/workflows/ci.yml create mode 100644 library/portable-simd/.github/workflows/doc.yml create mode 100644 library/portable-simd/CONTRIBUTING.md create mode 100644 library/portable-simd/Cargo.toml create mode 100644 library/portable-simd/LICENSE-APACHE create mode 100644 library/portable-simd/LICENSE-MIT create mode 100644 library/portable-simd/README.md create mode 100644 library/portable-simd/beginners-guide.md create mode 100644 library/portable-simd/crates/core_simd/Cargo.toml create mode 100644 library/portable-simd/crates/core_simd/LICENSE-APACHE create mode 100644 library/portable-simd/crates/core_simd/LICENSE-MIT create mode 100644 library/portable-simd/crates/core_simd/examples/matrix_inversion.rs create mode 100644 library/portable-simd/crates/core_simd/examples/nbody.rs create mode 100644 library/portable-simd/crates/core_simd/src/comparisons.rs create mode 100644 library/portable-simd/crates/core_simd/src/core_simd_docs.md create mode 100644 library/portable-simd/crates/core_simd/src/fmt.rs create mode 100644 library/portable-simd/crates/core_simd/src/intrinsics.rs create mode 100644 library/portable-simd/crates/core_simd/src/iter.rs create mode 100644 library/portable-simd/crates/core_simd/src/lane_count.rs create mode 100644 library/portable-simd/crates/core_simd/src/lib.rs create mode 100644 library/portable-simd/crates/core_simd/src/masks.rs create mode 100644 library/portable-simd/crates/core_simd/src/masks/bitmask.rs create mode 100644 library/portable-simd/crates/core_simd/src/masks/full_masks.rs create mode 100644 library/portable-simd/crates/core_simd/src/math.rs create mode 100644 library/portable-simd/crates/core_simd/src/mod.rs create mode 100644 library/portable-simd/crates/core_simd/src/ops.rs create mode 100644 library/portable-simd/crates/core_simd/src/reduction.rs create mode 100644 library/portable-simd/crates/core_simd/src/round.rs create mode 100644 library/portable-simd/crates/core_simd/src/select.rs create mode 100644 library/portable-simd/crates/core_simd/src/swizzle.rs create mode 100644 library/portable-simd/crates/core_simd/src/to_bytes.rs create mode 100644 library/portable-simd/crates/core_simd/src/vector.rs create mode 100644 library/portable-simd/crates/core_simd/src/vector/float.rs create mode 100644 library/portable-simd/crates/core_simd/src/vector/int.rs create mode 100644 library/portable-simd/crates/core_simd/src/vector/ptr.rs create mode 100644 library/portable-simd/crates/core_simd/src/vector/uint.rs create mode 100644 library/portable-simd/crates/core_simd/src/vendor.rs create mode 100644 library/portable-simd/crates/core_simd/src/vendor/arm.rs create mode 100644 library/portable-simd/crates/core_simd/src/vendor/powerpc.rs create mode 100644 library/portable-simd/crates/core_simd/src/vendor/wasm32.rs create mode 100644 library/portable-simd/crates/core_simd/src/vendor/x86.rs create mode 100644 library/portable-simd/crates/core_simd/tests/f32_ops.rs create mode 100644 library/portable-simd/crates/core_simd/tests/f64_ops.rs create mode 100644 library/portable-simd/crates/core_simd/tests/i16_ops.rs create mode 100644 library/portable-simd/crates/core_simd/tests/i32_ops.rs create mode 100644 library/portable-simd/crates/core_simd/tests/i64_ops.rs create mode 100644 library/portable-simd/crates/core_simd/tests/i8_ops.rs create mode 100644 library/portable-simd/crates/core_simd/tests/isize_ops.rs create mode 100644 library/portable-simd/crates/core_simd/tests/mask_ops.rs create mode 100644 library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask16.rs create mode 100644 library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask32.rs create mode 100644 library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask64.rs create mode 100644 library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask8.rs create mode 100644 library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask_macros.rs create mode 100644 library/portable-simd/crates/core_simd/tests/mask_ops_impl/masksize.rs create mode 100644 library/portable-simd/crates/core_simd/tests/mask_ops_impl/mod.rs create mode 100644 library/portable-simd/crates/core_simd/tests/masks.rs create mode 100644 library/portable-simd/crates/core_simd/tests/ops_macros.rs create mode 100644 library/portable-simd/crates/core_simd/tests/round.rs create mode 100644 library/portable-simd/crates/core_simd/tests/swizzle.rs create mode 100644 library/portable-simd/crates/core_simd/tests/to_bytes.rs create mode 100644 library/portable-simd/crates/core_simd/tests/u16_ops.rs create mode 100644 library/portable-simd/crates/core_simd/tests/u32_ops.rs create mode 100644 library/portable-simd/crates/core_simd/tests/u64_ops.rs create mode 100644 library/portable-simd/crates/core_simd/tests/u8_ops.rs create mode 100644 library/portable-simd/crates/core_simd/tests/usize_ops.rs create mode 100644 library/portable-simd/crates/core_simd/webdriver.json create mode 100644 library/portable-simd/crates/test_helpers/Cargo.toml create mode 100644 library/portable-simd/crates/test_helpers/src/array.rs create mode 100644 library/portable-simd/crates/test_helpers/src/biteq.rs create mode 100644 library/portable-simd/crates/test_helpers/src/lib.rs create mode 100644 library/portable-simd/crates/test_helpers/src/wasm.rs create mode 100644 library/stdarch/crates/core_arch/MISSING.md create mode 100644 library/stdarch/crates/intrinsic-test/missing.txt delete mode 100644 library/stdarch/crates/intrinsic-test/neon-intrinsics.csv create mode 100644 library/stdarch/crates/intrinsic-test/src/acle_csv_parser.rs rename src/ci/docker/host-x86_64/{x86_64-gnu-llvm-10 => x86_64-gnu-llvm-12}/Dockerfile (93%) create mode 100644 src/ci/docker/scripts/musl-patch-configure.diff rename src/doc/book/listings/ch09-error-handling/{no-listing-06-question-mark-in-main => listing-09-10}/output.txt (100%) rename src/doc/book/listings/ch09-error-handling/{no-listing-07-main-returning-result => listing-09-11}/Cargo.lock (92%) rename src/doc/book/listings/ch09-error-handling/{no-listing-06-question-mark-in-main => listing-09-11}/Cargo.toml (100%) create mode 100644 src/doc/book/listings/ch09-error-handling/listing-09-11/src/main.rs rename src/doc/book/listings/ch09-error-handling/{no-listing-06-question-mark-in-main => listing-09-12}/Cargo.lock (100%) rename src/doc/book/listings/ch09-error-handling/{no-listing-07-main-returning-result => listing-09-12}/Cargo.toml (100%) rename src/doc/book/listings/ch09-error-handling/{no-listing-07-main-returning-result => listing-09-12}/src/main.rs (100%) create mode 100644 src/doc/book/listings/ch09-error-handling/listing-09-13/Cargo.lock create mode 100644 src/doc/book/listings/ch09-error-handling/listing-09-13/Cargo.toml create mode 100644 src/doc/book/listings/ch09-error-handling/listing-09-13/src/main.rs delete mode 100644 src/doc/book/listings/ch09-error-handling/no-listing-06-question-mark-in-main/src/main.rs create mode 100644 src/doc/book/nostarch/chapter08.md create mode 100644 src/doc/book/nostarch/chapter09.md create mode 100644 src/doc/book/nostarch/chapter10.md create mode 100644 src/doc/embedded-book/src/unsorted/math.md create mode 100644 src/doc/rustc-dev-guide/src/mir/drop-elaboration.md create mode 100644 src/doc/rustc/src/platform-support/wasm64-unknown-unknown.md create mode 100644 src/doc/rustc/src/platform-support/x86_64-unknown-none.md create mode 100644 src/doc/rustdoc/src/how-to-read-rustdoc.md create mode 100644 src/doc/unstable-book/src/compiler-flags/location-detail.md create mode 100644 src/doc/unstable-book/src/compiler-flags/no-unique-section-names.md delete mode 100644 src/doc/unstable-book/src/compiler-flags/strip.md create mode 100644 src/doc/unstable-book/src/compiler-flags/temps-dir.md create mode 100644 src/doc/unstable-book/src/language-features/inline-const-pat.md create mode 100644 src/doc/unstable-book/src/language-features/type-changing-struct-update.md delete mode 100644 src/doc/unstable-book/src/library-features/format-args-capture.md delete mode 100644 src/librustdoc/doctree.rs create mode 100644 src/librustdoc/html/highlight/fixtures/decorations.html create mode 100644 src/librustdoc/html/static/fonts/NanumBarunGothic-LICENSE.txt create mode 100644 src/librustdoc/html/static/fonts/NanumBarunGothic.ttf.woff create mode 100644 src/librustdoc/html/static/fonts/NanumBarunGothic.ttf.woff2 create mode 100644 src/librustdoc/html/static/js/scrape-examples.js create mode 100644 src/librustdoc/scrape_examples.rs create mode 100644 src/librustdoc/visit.rs create mode 100644 src/test/assembly/stack-protector/stack-protector-heuristics-effect.rs create mode 100644 src/test/assembly/stack-protector/stack-protector-target-support.rs create mode 100644 src/test/codegen-units/item-collection/implicit-panic-call.rs create mode 100644 src/test/codegen/array-clone.rs create mode 100644 src/test/codegen/sanitizer_cfi_add_canonical_jump_tables_flag.rs create mode 100644 src/test/codegen/sanitizer_cfi_emit_type_checks.rs create mode 100644 src/test/codegen/sanitizer_cfi_emit_type_metadata.rs create mode 100644 src/test/codegen/slice-reverse.rs create mode 100644 src/test/codegen/stack-protector.rs create mode 100644 src/test/incremental/auxiliary/rustc-rust-log-aux.rs create mode 100644 src/test/incremental/issue-85360-eval-obligation-ice.rs create mode 100644 src/test/incremental/rustc-rust-log.rs create mode 100644 src/test/mir-opt/inline/issue-78442.rs create mode 100644 src/test/mir-opt/inline/issue_78442.bar.Inline.diff create mode 100644 src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff create mode 100644 src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/Makefile create mode 100644 src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/examples/ex.rs create mode 100644 src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/lib.rs create mode 100644 src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/proc.rs create mode 100644 src/test/run-make/invalid-so/Makefile create mode 100644 src/test/run-make/invalid-so/bar.rs create mode 100644 src/test/run-make/issue-10971-temps-dir/Makefile create mode 100644 src/test/run-make/rustdoc-scrape-examples-invalid-expr/Makefile create mode 100644 src/test/run-make/rustdoc-scrape-examples-invalid-expr/examples/ex.rs create mode 100644 src/test/run-make/rustdoc-scrape-examples-invalid-expr/src/lib.rs create mode 100644 src/test/run-make/rustdoc-scrape-examples-multiple/Makefile create mode 100644 src/test/run-make/rustdoc-scrape-examples-multiple/examples/ex.rs create mode 100644 src/test/run-make/rustdoc-scrape-examples-multiple/examples/ex2.rs create mode 100644 src/test/run-make/rustdoc-scrape-examples-multiple/scrape.mk create mode 100644 src/test/run-make/rustdoc-scrape-examples-multiple/src/lib.rs create mode 100644 src/test/run-make/rustdoc-scrape-examples-ordering/Makefile create mode 100644 src/test/run-make/rustdoc-scrape-examples-ordering/examples/ex1.rs create mode 100644 src/test/run-make/rustdoc-scrape-examples-ordering/examples/ex2.rs create mode 100644 src/test/run-make/rustdoc-scrape-examples-ordering/src/lib.rs create mode 100644 src/test/run-make/rustdoc-scrape-examples-remap/Makefile create mode 100644 src/test/run-make/rustdoc-scrape-examples-remap/examples/ex.rs create mode 100644 src/test/run-make/rustdoc-scrape-examples-remap/src/a.rs create mode 100644 src/test/run-make/rustdoc-scrape-examples-remap/src/lib.rs create mode 100644 src/test/rustdoc-gui/anchor-navigable.goml create mode 100644 src/test/rustdoc-gui/anchors.goml create mode 100644 src/test/rustdoc-gui/check-code-blocks-margin.goml create mode 100644 src/test/rustdoc-gui/docblock-code-block-line-number.goml delete mode 100644 src/test/rustdoc-gui/header-size.goml create mode 100644 src/test/rustdoc-gui/headings.goml create mode 100644 src/test/rustdoc-gui/javascript-disabled.goml create mode 100644 src/test/rustdoc-gui/overflow-tooltip-information.goml create mode 100644 src/test/rustdoc-gui/sidebar-macro-reexport.goml create mode 100644 src/test/rustdoc-gui/toggle-click-deadspace.goml create mode 100644 src/test/rustdoc-ui/auxiliary/empty-fn.rs create mode 100644 src/test/rustdoc-ui/failed-doctest-extra-semicolon-on-item.rs create mode 100644 src/test/rustdoc-ui/failed-doctest-extra-semicolon-on-item.stdout create mode 100644 src/test/rustdoc-ui/issue-91134.rs create mode 100644 src/test/rustdoc-ui/issue-91134.stdout create mode 100644 src/test/rustdoc-ui/recursive-deref-ice.rs create mode 100644 src/test/rustdoc-ui/scrape-examples-ice.rs create mode 100644 src/test/rustdoc-ui/scrape-examples-wrong-options-1.rs create mode 100644 src/test/rustdoc-ui/scrape-examples-wrong-options-1.stderr create mode 100644 src/test/rustdoc-ui/scrape-examples-wrong-options-2.rs create mode 100644 src/test/rustdoc-ui/scrape-examples-wrong-options-2.stderr create mode 100644 src/test/rustdoc/deref-recursive-pathbuf.rs create mode 100644 src/test/rustdoc/deref-recursive.rs create mode 100644 src/test/rustdoc/enum-headings.rs create mode 100644 src/test/rustdoc/include_str_cut.rs create mode 100644 src/test/rustdoc/mixing-doc-comments-and-attrs.rs create mode 100644 src/test/rustdoc/short-line.md rename src/test/ui/{ => abi}/c-stack-returning-int64.rs (100%) create mode 100644 src/test/ui/abi/stack-protector.rs rename src/test/ui/{ => abi}/x86stdcall.rs (89%) rename src/test/ui/{ => abi}/x86stdcall2.rs (100%) rename src/test/ui/{ => alloc-error}/default-alloc-error-hook.rs (100%) delete mode 100644 src/test/ui/alloca-from-derived-tydesc.rs delete mode 100644 src/test/ui/argument-passing.rs rename src/test/ui/{ => array-slice-vec}/byte-literals.rs (100%) rename src/test/ui/{ => array-slice-vec}/mut-vstore-expr.rs (100%) create mode 100644 src/test/ui/asm/x86_64/bad-clobber-abi.rs create mode 100644 src/test/ui/asm/x86_64/bad-clobber-abi.stderr create mode 100644 src/test/ui/asm/x86_64/issue-89875.rs create mode 100644 src/test/ui/asm/x86_64/multiple-clobber-abi.rs rename src/test/ui/{ => associated-types}/associated-item-long-paths.rs (100%) rename src/test/ui/{ => associated-types}/default-associated-types.rs (100%) rename src/test/ui/{issues => associated-types}/issue-22066.rs (100%) rename src/test/ui/{issues => associated-types}/issue-22828.rs (100%) rename src/test/ui/{issues => associated-types}/issue-28871.rs (100%) rename src/test/ui/{issues => associated-types}/issue-47139-1.rs (100%) rename src/test/ui/{issues => associated-types}/issue-54467.rs (100%) rename src/test/ui/{ => associated-types}/substs-ppaux.normal.stderr (94%) rename src/test/ui/{ => associated-types}/substs-ppaux.rs (100%) rename src/test/ui/{ => associated-types}/substs-ppaux.verbose.stderr (94%) rename src/test/ui/{parser => async-await}/incorrect-move-async-order-issue-79694.fixed (100%) rename src/test/ui/{parser => async-await}/incorrect-move-async-order-issue-79694.rs (100%) rename src/test/ui/{parser => async-await}/incorrect-move-async-order-issue-79694.stderr (100%) rename src/test/ui/{issues => async-await}/issue-73541-1.rs (100%) rename src/test/ui/{issues => async-await}/issue-73541-1.stderr (100%) rename src/test/ui/{ => attributes}/attr-eq-token-tree.rs (100%) rename src/test/ui/{ => attributes}/attr-eq-token-tree.stderr (100%) rename src/test/ui/{issues => attributes}/issue-40962.rs (100%) create mode 100644 src/test/ui/attributes/issue-90873.rs create mode 100644 src/test/ui/attributes/issue-90873.stderr rename src/test/ui/{ => attributes}/suffixed-literal-meta.rs (100%) rename src/test/ui/{ => attributes}/suffixed-literal-meta.stderr (100%) rename src/test/ui/{ => attributes}/tool_attributes.rs (100%) rename src/test/ui/{ => attributes}/unrestricted-attribute-tokens.rs (100%) delete mode 100644 src/test/ui/augmented-assignments-feature-gate.rs rename src/test/ui/{ => binop}/operator-multidispatch.rs (100%) rename src/test/ui/{ => binop}/operator-overloading.rs (100%) rename src/test/ui/{ => binop}/placement-syntax.rs (100%) rename src/test/ui/{ => binop}/placement-syntax.stderr (100%) rename src/test/ui/{ => binop}/shift-various-bad-types.rs (100%) rename src/test/ui/{ => binop}/shift-various-bad-types.stderr (100%) rename src/test/ui/{ => binop}/structured-compare.rs (100%) rename src/test/ui/{ => borrowck}/access-mode-in-closures.rs (100%) rename src/test/ui/{ => borrowck}/access-mode-in-closures.stderr (100%) rename src/test/ui/{ => borrowck}/immut-function-arguments.rs (100%) rename src/test/ui/{ => borrowck}/immut-function-arguments.stderr (100%) rename src/test/ui/{issues => borrowck}/issue-46095.rs (100%) create mode 100644 src/test/ui/borrowck/issue-80772.rs create mode 100644 src/test/ui/borrowck/issue-91206.rs create mode 100644 src/test/ui/borrowck/issue-91206.stderr rename src/test/ui/{ => borrowck}/kindck-implicit-close-over-mut-var.rs (100%) rename src/test/ui/{ => borrowck}/lazy-init.rs (100%) rename src/test/ui/{ => box}/new-box-syntax.rs (100%) rename src/test/ui/{ => box}/new-box.rs (100%) rename src/test/ui/{issues => c-variadic}/issue-32201.rs (100%) rename src/test/ui/{issues => c-variadic}/issue-32201.stderr (100%) rename src/test/ui/{ => cast}/codegen-object-shim.rs (100%) rename src/test/ui/{ => cast}/supported-cast.rs (100%) rename src/test/ui/{ => cfg}/crt-static-off-works.rs (100%) rename src/test/ui/{ => cfg}/crt-static-on-works.rs (100%) rename src/test/ui/{ => cfg}/expanded-cfg.rs (100%) rename src/test/ui/{ => closures}/closure-expected.rs (100%) rename src/test/ui/{ => closures}/closure-expected.stderr (67%) rename src/test/ui/{ => closures}/closure_promotion.rs (100%) rename src/test/ui/{issues => closures}/issue-10398.rs (100%) rename src/test/ui/{issues => closures}/issue-10398.stderr (100%) rename src/test/ui/{issues => closures}/issue-42463.rs (100%) rename src/test/ui/{ => closures}/once-move-out-on-heap.rs (100%) rename src/test/ui/{ => closures}/semistatement-in-lambda.rs (100%) rename src/test/ui/{ => closures}/thir-unsafeck-issue-85871.rs (100%) rename src/test/ui/{ => codegen}/auxiliary/llvm_pr32379.rs (100%) rename src/test/ui/{ => codegen}/init-large-type.rs (100%) rename src/test/ui/{ => codegen}/llvm-pr32379.rs (100%) rename src/test/ui/{issues => coercion}/auxiliary/issue-39823.rs (100%) rename src/test/ui/{issues => coercion}/issue-14589.rs (100%) rename src/test/ui/{issues => coercion}/issue-39823.rs (100%) rename src/test/ui/{issues => coercion}/issue-73886.rs (100%) rename src/test/ui/{issues => coercion}/issue-73886.stderr (100%) rename src/test/ui/{ => coercion}/retslot-cast.rs (100%) rename src/test/ui/{ => coercion}/retslot-cast.stderr (100%) rename src/test/ui/{ => coercion}/unsafe-coercion.rs (100%) create mode 100644 src/test/ui/coherence/auxiliary/error_lib.rs create mode 100644 src/test/ui/coherence/coherence-overlap-negate-alias-strict.rs create mode 100644 src/test/ui/coherence/coherence-overlap-negate-alias-strict.stderr create mode 100644 src/test/ui/coherence/coherence-overlap-negate-not-use-feature-gate.rs create mode 100644 src/test/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr create mode 100644 src/test/ui/coherence/coherence-overlap-negate-strict.rs create mode 100644 src/test/ui/coherence/coherence-overlap-negate-use-feature-gate.rs create mode 100644 src/test/ui/coherence/coherence-overlap-negative-trait.rs create mode 100644 src/test/ui/coherence/coherence-overlap-trait-alias.rs create mode 100644 src/test/ui/coherence/coherence-overlap-trait-alias.stderr create mode 100644 src/test/ui/compare-method/issue-90444.rs create mode 100644 src/test/ui/compare-method/issue-90444.stderr create mode 100644 src/test/ui/conditional-compilation/cfg-arg-invalid-7.rs create mode 100644 src/test/ui/conditional-compilation/cfg-arg-invalid-7.stderr rename src/test/ui/{issues => conditional-compilation}/issue-34028.rs (100%) rename src/test/ui/{ => const-generics}/auxiliary/legacy-const-generics.rs (100%) create mode 100644 src/test/ui/const-generics/defaults/doesnt_infer.rs create mode 100644 src/test/ui/const-generics/defaults/doesnt_infer.stderr create mode 100644 src/test/ui/const-generics/defaults/rp_impl_trait.rs create mode 100644 src/test/ui/const-generics/defaults/rp_impl_trait_fail.rs create mode 100644 src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr create mode 100644 src/test/ui/const-generics/defaults/trait_objects.rs create mode 100644 src/test/ui/const-generics/defaults/trait_objects_fail.rs create mode 100644 src/test/ui/const-generics/defaults/trait_objects_fail.stderr create mode 100644 src/test/ui/const-generics/defaults/wfness.rs create mode 100644 src/test/ui/const-generics/defaults/wfness.stderr create mode 100644 src/test/ui/const-generics/invariant.nll.stderr create mode 100644 src/test/ui/const-generics/invariant.rs create mode 100644 src/test/ui/const-generics/invariant.stderr create mode 100644 src/test/ui/const-generics/issues/issue-88997.rs create mode 100644 src/test/ui/const-generics/issues/issue-88997.stderr create mode 100644 src/test/ui/const-generics/issues/issue-89304.rs create mode 100644 src/test/ui/const-generics/issues/issue-90364.rs create mode 100644 src/test/ui/const-generics/issues/issue-90364.stderr rename src/test/ui/{ => const-generics}/legacy-const-generics-bad.rs (100%) rename src/test/ui/{ => const-generics}/legacy-const-generics-bad.stderr (100%) rename src/test/ui/{ => const-generics}/legacy-const-generics.rs (100%) create mode 100644 src/test/ui/consts/closure-structural-match-issue-90013.rs delete mode 100644 src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs delete mode 100644 src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr create mode 100644 src/test/ui/consts/const-eval/const_panic_stability.e2018.stderr create mode 100644 src/test/ui/consts/const-eval/const_panic_stability.e2021.stderr create mode 100644 src/test/ui/consts/const-eval/const_panic_stability.rs create mode 100644 src/test/ui/consts/const-eval/issue-84957-const-str-as-bytes.rs rename src/test/ui/{ => consts}/eval-enum.rs (100%) rename src/test/ui/{ => consts}/eval-enum.stderr (100%) rename src/test/ui/{issues => consts}/issue-13902.rs (100%) rename src/test/ui/{issues => consts}/issue-17074.rs (100%) rename src/test/ui/{issues => consts}/issue-18294.rs (100%) rename src/test/ui/{issues => consts}/issue-18294.stderr (100%) rename src/test/ui/{issues => consts}/issue-23968-const-not-overflow.rs (100%) rename src/test/ui/{issues/issue-37550.rs => consts/issue-37550-1.rs} (100%) rename src/test/ui/{issues/issue-37550.stderr => consts/issue-37550-1.stderr} (92%) rename src/test/ui/{issues => consts}/issue-37991.rs (100%) create mode 100644 src/test/ui/consts/issue-90878-2.rs create mode 100644 src/test/ui/consts/issue-90878-2.stderr create mode 100644 src/test/ui/consts/issue-90878-3.rs create mode 100644 src/test/ui/consts/issue-90878-3.stderr create mode 100644 src/test/ui/consts/issue-90878.rs create mode 100644 src/test/ui/consts/issue-90878.stderr create mode 100644 src/test/ui/consts/issue-miri-1910.rs create mode 100644 src/test/ui/consts/issue-miri-1910.stderr create mode 100644 src/test/ui/consts/non-const-value-in-const.rs create mode 100644 src/test/ui/consts/non-const-value-in-const.stderr create mode 100644 src/test/ui/consts/precise-drop-with-promoted.rs create mode 100644 src/test/ui/consts/promoted-const-drop.rs create mode 100644 src/test/ui/consts/promoted-const-drop.stderr create mode 100644 src/test/ui/consts/promoted-storage.rs create mode 100644 src/test/ui/consts/qualif-indirect-mutation-fail.rs create mode 100644 src/test/ui/consts/qualif-indirect-mutation-fail.stderr create mode 100644 src/test/ui/consts/qualif-indirect-mutation-pass.rs create mode 100644 src/test/ui/consts/qualif-union.rs create mode 100644 src/test/ui/consts/qualif-union.stderr delete mode 100644 src/test/ui/consts/write_to_mut_ref_dest.mut_refs.stderr rename vendor/gimli/rustfmt.toml => src/test/ui/crate-loading/auxiliary/libfoo.rlib (100%) create mode 100644 src/test/ui/crate-loading/invalid-rlib.rs create mode 100644 src/test/ui/crate-loading/invalid-rlib.stderr rename src/test/ui/{ => deprecation}/try-macro-suggestion.rs (100%) rename src/test/ui/{ => deprecation}/try-macro-suggestion.stderr (100%) rename src/test/ui/{issues => deriving}/issue-19358.rs (100%) rename src/test/ui/{issues => deriving}/issue-58319.rs (100%) create mode 100644 src/test/ui/did_you_mean/compatible-variants.rs create mode 100644 src/test/ui/did_you_mean/compatible-variants.stderr rename src/test/ui/{ => drop}/auxiliary/inline_dtor.rs (100%) rename src/test/ui/{issues => drop}/issue-35546.rs (100%) create mode 100644 src/test/ui/drop/issue-90752-raw-ptr-shenanigans.rs create mode 100644 src/test/ui/drop/issue-90752.rs rename src/test/ui/{ => drop}/terminate-in-initializer.rs (100%) rename src/test/ui/{ => drop}/use_inline_dtor.rs (100%) rename src/test/ui/{ => dropck}/cleanup-arm-conditional.rs (100%) rename src/test/ui/{issues => dropck}/issue-28498-ugeh-with-passed-to-fn.rs (100%) rename src/test/ui/{ => editions}/edition-keywords-2015-2015.rs (100%) rename src/test/ui/{ => editions}/edition-keywords-2015-2018.rs (100%) rename src/test/ui/{ => editions}/edition-keywords-2018-2015.rs (100%) rename src/test/ui/{ => editions}/edition-keywords-2018-2018.rs (100%) rename src/test/ui/{ => editions}/epoch-gate-feature.rs (100%) create mode 100644 src/test/ui/empty/empty-attributes.rs create mode 100644 src/test/ui/empty/empty-attributes.stderr rename src/test/ui/{issues => enum-discriminant}/issue-51582.rs (100%) rename src/test/ui/{issues => enum}/issue-42747.rs (100%) delete mode 100644 src/test/ui/estr-uniq.rs delete mode 100644 src/test/ui/export-import.rs delete mode 100644 src/test/ui/export-import.stderr delete mode 100644 src/test/ui/export-non-interference2.rs delete mode 100644 src/test/ui/export-non-interference3.rs delete mode 100644 src/test/ui/export.rs delete mode 100644 src/test/ui/export.stderr delete mode 100644 src/test/ui/export2.rs delete mode 100644 src/test/ui/export2.stderr delete mode 100644 src/test/ui/expr-block-slot.rs delete mode 100644 src/test/ui/expr-block-unique.rs rename src/test/ui/{ => expr/if}/expr-if.rs (100%) rename src/test/ui/{ => extern}/auxiliary/no-mangle-associated-fn.rs (100%) rename src/test/ui/{ => extern}/auxiliary/reexport-should-still-link.rs (100%) rename src/test/ui/{issues => extern}/issue-28324.mir.stderr (100%) rename src/test/ui/{issues => extern}/issue-28324.rs (100%) rename src/test/ui/{issues => extern}/issue-28324.thir.stderr (100%) rename src/test/ui/{ => extern}/no-mangle-associated-fn.rs (100%) create mode 100644 src/test/ui/feature-gates/feature-gate-asm_const.rs create mode 100644 src/test/ui/feature-gates/feature-gate-asm_const.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-asm_experimental_arch.rs create mode 100644 src/test/ui/feature-gates/feature-gate-asm_experimental_arch.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-asm_sym.rs create mode 100644 src/test/ui/feature-gates/feature-gate-asm_sym.stderr delete mode 100644 src/test/ui/feature-gates/feature-gate-doc_keyword.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-doc_keyword.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-inline_const_pat.rs create mode 100644 src/test/ui/feature-gates/feature-gate-inline_const_pat.stderr delete mode 100644 src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-rustdoc_internals.rs create mode 100644 src/test/ui/feature-gates/feature-gate-rustdoc_internals.stderr rename src/test/ui/{ => feature-gates}/gated-bad-feature.rs (100%) rename src/test/ui/{ => feature-gates}/gated-bad-feature.stderr (100%) rename src/test/ui/{ => feature-gates}/stable-features.rs (100%) rename src/test/ui/{ => feature-gates}/stable-features.stderr (100%) delete mode 100644 src/test/ui/fmt/feature-gate-format-args-capture.rs delete mode 100644 src/test/ui/fmt/feature-gate-format-args-capture.stderr rename src/test/ui/{ => fn}/expr-fn.rs (100%) rename src/test/ui/{ => fn}/fun-call-variants.rs (100%) rename src/test/ui/{ => fn}/nested-function-names-issue-8587.rs (100%) rename src/test/ui/{ => for-loop-while}/break-outside-loop.rs (100%) rename src/test/ui/{ => for-loop-while}/break-outside-loop.stderr (100%) rename src/test/ui/{ => for-loop-while}/break-while-condition.rs (100%) rename src/test/ui/{ => for-loop-while}/break-while-condition.stderr (100%) rename src/test/ui/{issues => for-loop-while}/issue-51345.rs (100%) rename src/test/ui/{ => for-loop-while}/long-while.rs (100%) rename src/test/ui/{while-let.rs => for-loop-while/while-let-2.rs} (100%) rename src/test/ui/{while-let.stderr => for-loop-while/while-let-2.stderr} (93%) rename src/test/ui/{ => foreign}/nil-decl-in-foreign.rs (100%) create mode 100644 src/test/ui/generator/generator-region-requirements.nll.stderr create mode 100644 src/test/ui/generic-associated-types/issue-85921.rs create mode 100644 src/test/ui/generic-associated-types/issue-87258_a.rs create mode 100644 src/test/ui/generic-associated-types/issue-87258_a.stderr create mode 100644 src/test/ui/generic-associated-types/issue-87258_b.rs create mode 100644 src/test/ui/generic-associated-types/issue-87258_b.stderr create mode 100644 src/test/ui/generic-associated-types/issue-88459.rs create mode 100644 src/test/ui/generic-associated-types/issue-88595.rs create mode 100644 src/test/ui/generic-associated-types/issue-88595.stderr create mode 100644 src/test/ui/generic-associated-types/issue-90014.rs create mode 100644 src/test/ui/generic-associated-types/issue-90014.stderr create mode 100644 src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.nll.stderr create mode 100644 src/test/ui/generic-associated-types/self-outlives-lint.rs create mode 100644 src/test/ui/generic-associated-types/self-outlives-lint.stderr rename src/test/ui/{ => generics}/autobind.rs (100%) rename src/test/ui/{issues => generics}/issue-1112.rs (100%) rename src/test/ui/{issues => generics}/issue-333.rs (100%) rename src/test/ui/{issues => generics}/issue-59508-1.rs (100%) rename src/test/ui/{issues => generics}/issue-59508-1.stderr (100%) rename src/test/ui/{issues => generics}/issue-59508.fixed (100%) rename src/test/ui/{issues => generics}/issue-59508.rs (100%) rename src/test/ui/{issues => generics}/issue-59508.stderr (100%) rename src/test/ui/{ => generics}/lifetime-before-type-params.rs (100%) rename src/test/ui/{ => generics}/lifetime-before-type-params.stderr (100%) rename src/test/ui/{ => generics}/type-params-in-for-each.rs (100%) rename src/test/ui/{issues => higher-rank-trait-bounds}/issue-60283.rs (100%) rename src/test/ui/{issues => higher-rank-trait-bounds}/issue-60283.stderr (100%) rename src/test/ui/{issues => higher-rank-trait-bounds/normalize-under-binder}/issue-44005.rs (95%) create mode 100644 src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-56556.rs delete mode 100644 src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.stderr create mode 100644 src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.migrate.stderr create mode 100644 src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.nll.stderr create mode 100644 src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs create mode 100644 src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-74261.rs create mode 100644 src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-76956.rs create mode 100644 src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90612.rs create mode 100644 src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90638.rs create mode 100644 src/test/ui/hrtb/issue-90177.rs create mode 100644 src/test/ui/hygiene/auxiliary/fields.rs create mode 100644 src/test/ui/hygiene/auxiliary/methods.rs create mode 100644 src/test/ui/hygiene/auxiliary/pub_hygiene.rs create mode 100644 src/test/ui/hygiene/auxiliary/use_by_macro.rs create mode 100644 src/test/ui/hygiene/auxiliary/variants.rs create mode 100644 src/test/ui/hygiene/cross-crate-define-and-use.rs create mode 100644 src/test/ui/hygiene/cross-crate-fields.rs create mode 100644 src/test/ui/hygiene/cross-crate-glob-hygiene.rs create mode 100644 src/test/ui/hygiene/cross-crate-glob-hygiene.stderr create mode 100644 src/test/ui/hygiene/cross-crate-methods.rs create mode 100644 src/test/ui/hygiene/cross-crate-name-collision.rs create mode 100644 src/test/ui/hygiene/cross-crate-name-hiding-2.rs create mode 100644 src/test/ui/hygiene/cross-crate-name-hiding-2.stderr create mode 100644 src/test/ui/hygiene/cross-crate-name-hiding.rs create mode 100644 src/test/ui/hygiene/cross-crate-name-hiding.stderr create mode 100644 src/test/ui/hygiene/cross-crate-redefine.rs create mode 100644 src/test/ui/hygiene/cross-crate-redefine.stderr create mode 100644 src/test/ui/hygiene/cross-crate-variants.rs delete mode 100644 src/test/ui/hygiene/cross_crate_hygiene.rs rename src/test/ui/{ => hygiene}/lambda-var-hygiene.rs (100%) rename src/test/ui/{ => hygiene}/thread-local-not-in-prelude.rs (100%) rename src/test/ui/{issues => impl-trait}/issue-49579.rs (100%) rename src/test/ui/{issues => impl-trait}/issue-49685.rs (100%) rename src/test/ui/{issues => impl-trait}/issue-51185.rs (100%) delete mode 100644 src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.nll.stderr delete mode 100644 src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.nll.stderr delete mode 100644 src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr rename src/test/ui/{ => imports}/absolute-paths-in-nested-use-groups.rs (100%) rename src/test/ui/{ => imports}/absolute-paths-in-nested-use-groups.stderr (100%) rename src/test/ui/{ => imports}/export-multi.rs (100%) rename src/test/ui/{ => imports}/glob-cycles.rs (100%) rename src/test/ui/{ => imports}/no-std-inject.rs (100%) rename src/test/ui/{ => imports}/no-std-inject.stderr (100%) rename src/test/ui/{ => imports}/reexport-star.rs (100%) rename src/test/ui/{ => imports}/use-mod.rs (100%) rename src/test/ui/{ => in-band-lifetimes}/in-band-lifetimes.rs (100%) rename src/test/ui/{ => inference}/lub-glb-with-unbound-infer-var.rs (100%) rename src/test/ui/{ => inference}/newlambdas-ret-infer.rs (100%) rename src/test/ui/{ => inference}/newlambdas-ret-infer2.rs (100%) rename src/test/ui/{ => inference}/question-mark-type-infer.rs (100%) rename src/test/ui/{ => inference}/question-mark-type-infer.stderr (100%) rename src/test/ui/{ => inference}/range-type-infer.rs (100%) rename src/test/ui/{ => inference}/simple-infer.rs (100%) rename src/test/ui/{ => inference}/tutorial-suffix-inference-test.rs (100%) rename src/test/ui/{ => inference}/tutorial-suffix-inference-test.stderr (100%) rename src/test/ui/{ => inference}/type-infer-generalize-ty-var.rs (100%) create mode 100644 src/test/ui/inline-const/const-expr-inference.rs create mode 100644 src/test/ui/inline-const/const-expr-lifetime-err.rs create mode 100644 src/test/ui/inline-const/const-expr-lifetime-err.stderr create mode 100644 src/test/ui/inline-const/const-expr-lifetime.rs create mode 100644 src/test/ui/inline-const/const-match-pat-inference.rs create mode 100644 src/test/ui/inline-const/const-match-pat-lifetime-err.rs create mode 100644 src/test/ui/inline-const/const-match-pat-lifetime.rs delete mode 100644 src/test/ui/issues/issue-2444.rs delete mode 100644 src/test/ui/issues/issue-2748-b.rs delete mode 100644 src/test/ui/issues/issue-3211.rs delete mode 100644 src/test/ui/issues/issue-44005.stderr delete mode 100644 src/test/ui/issues/issue-4401.rs create mode 100644 src/test/ui/issues/issue-46983.nll.stderr delete mode 100644 src/test/ui/issues/issue-50993.rs delete mode 100644 src/test/ui/issues/issue-50993.stderr delete mode 100644 src/test/ui/issues/issue-77218.rs delete mode 100644 src/test/ui/issues/issue-77218.stderr create mode 100644 src/test/ui/issues/issue-77218/issue-77218-2.fixed create mode 100644 src/test/ui/issues/issue-77218/issue-77218-2.rs create mode 100644 src/test/ui/issues/issue-77218/issue-77218-2.stderr create mode 100644 src/test/ui/issues/issue-77218/issue-77218.fixed create mode 100644 src/test/ui/issues/issue-77218/issue-77218.rs create mode 100644 src/test/ui/issues/issue-77218/issue-77218.stderr delete mode 100644 src/test/ui/issues/issue-811.rs create mode 100644 src/test/ui/iterators/rsplit-clone.rs delete mode 100644 src/test/ui/keyword-changes-2012-07-31.rs rename src/test/ui/{issues => lang-items}/issue-19660.rs (100%) rename src/test/ui/{issues => lang-items}/issue-19660.stderr (100%) rename src/test/ui/{issues => lang-items}/issue-31076.rs (100%) rename src/test/ui/{issues => lang-items}/issue-31076.stderr (100%) create mode 100644 src/test/ui/lang-items/issue-87573.rs create mode 100644 src/test/ui/lang-items/issue-87573.stderr rename src/test/ui/{ => lang-items}/no_owned_box_lang_item.rs (100%) rename src/test/ui/{ => lang-items}/no_owned_box_lang_item.stderr (100%) rename src/test/ui/{ => lang-items}/required-lang-item.rs (100%) rename src/test/ui/{ => lang-items}/required-lang-item.stderr (100%) delete mode 100644 src/test/ui/leak-unique-as-tydesc.rs create mode 100644 src/test/ui/let-else/issue-89960.rs create mode 100644 src/test/ui/let-else/issue-89960.stderr create mode 100644 src/test/ui/let-else/let-else-if.rs create mode 100644 src/test/ui/let-else/let-else-if.stderr rename src/test/ui/{parser => lexer}/lex-bad-binary-literal.rs (100%) rename src/test/ui/{parser => lexer}/lex-bad-binary-literal.stderr (100%) rename src/test/ui/{parser => lexer}/lex-bad-char-literals-1.rs (100%) rename src/test/ui/{parser => lexer}/lex-bad-char-literals-1.stderr (100%) rename src/test/ui/{parser => lexer}/lex-bad-char-literals-2.rs (100%) rename src/test/ui/{parser => lexer}/lex-bad-char-literals-2.stderr (100%) rename src/test/ui/{parser => lexer}/lex-bad-char-literals-3.rs (100%) rename src/test/ui/{parser => lexer}/lex-bad-char-literals-3.stderr (100%) rename src/test/ui/{parser => lexer}/lex-bad-char-literals-4.rs (100%) rename src/test/ui/{parser => lexer}/lex-bad-char-literals-4.stderr (100%) rename src/test/ui/{parser => lexer}/lex-bad-char-literals-5.rs (100%) rename src/test/ui/{parser => lexer}/lex-bad-char-literals-5.stderr (100%) rename src/test/ui/{parser => lexer}/lex-bad-char-literals-6.rs (100%) rename src/test/ui/{parser => lexer}/lex-bad-char-literals-6.stderr (100%) rename src/test/ui/{parser => lexer}/lex-bad-char-literals-7.rs (100%) rename src/test/ui/{parser => lexer}/lex-bad-char-literals-7.stderr (100%) rename src/test/ui/{parser => lexer}/lex-bad-numeric-literals.rs (100%) rename src/test/ui/{parser => lexer}/lex-bad-numeric-literals.stderr (100%) rename src/test/ui/{parser => lexer}/lex-bad-octal-literal.rs (100%) rename src/test/ui/{parser => lexer}/lex-bad-octal-literal.stderr (100%) rename src/test/ui/{parser => lexer}/lex-bad-token.rs (100%) rename src/test/ui/{parser => lexer}/lex-bad-token.stderr (100%) rename src/test/ui/{parser => lexer}/lex-bare-cr-nondoc-comment.rs (100%) rename src/test/ui/{parser => lexer}/lex-bare-cr-string-literal-doc-comment.rs (100%) rename src/test/ui/{parser => lexer}/lex-bare-cr-string-literal-doc-comment.stderr (100%) rename src/test/ui/{parser => lexer}/lex-stray-backslash.rs (100%) rename src/test/ui/{parser => lexer}/lex-stray-backslash.stderr (100%) rename src/test/ui/{parser => lexer}/lexer-crlf-line-endings-string-literal-doc-comment.rs (100%) rename src/test/ui/{issues => lifetimes}/issue-26638.rs (100%) rename src/test/ui/{issues => lifetimes}/issue-26638.stderr (100%) create mode 100644 src/test/ui/lifetimes/issue-90170-elision-mismatch.fixed create mode 100644 src/test/ui/lifetimes/issue-90170-elision-mismatch.nll.stderr create mode 100644 src/test/ui/lifetimes/issue-90170-elision-mismatch.rs create mode 100644 src/test/ui/lifetimes/issue-90170-elision-mismatch.stderr create mode 100644 src/test/ui/lifetimes/issue-90600-expected-return-static-indirect.nll.stderr create mode 100644 src/test/ui/lifetimes/issue-90600-expected-return-static-indirect.rs create mode 100644 src/test/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr rename src/test/ui/{ => linkage-attr}/auxiliary/link-cfg-works-transitive-dylib.rs (100%) rename src/test/ui/{ => linkage-attr}/auxiliary/link-cfg-works-transitive-rlib.rs (100%) rename src/test/ui/{ => linkage-attr}/auxiliary/linkage1.rs (100%) rename src/test/ui/{ => linkage-attr}/link-cfg-works.rs (100%) rename src/test/ui/{ => linkage-attr}/linkage1.rs (100%) rename src/test/ui/{issues => lint}/issue-14837.rs (100%) rename src/test/ui/{issues => lint}/issue-57410-1.rs (100%) rename src/test/ui/{issues => lint}/issue-63364.rs (100%) rename src/test/ui/{issues => lint}/issue-63364.stderr (100%) rename src/test/ui/{ => lint}/lint-cap.rs (100%) rename src/test/ui/{ => lint}/test-allow-dead-extern-static-no-warning.rs (100%) rename src/test/ui/{ => lint}/unnecessary-extern-crate.rs (100%) rename src/test/ui/{ => lint}/unnecessary-extern-crate.stderr (100%) create mode 100644 src/test/ui/lint/unused/unused-async.rs create mode 100644 src/test/ui/lint/unused/unused-async.stderr create mode 100644 src/test/ui/lint/unused/unused-attr-duplicate.rs create mode 100644 src/test/ui/lint/unused/unused-attr-duplicate.stderr rename src/test/ui/{ => lint}/warn-ctypes-inhibit.rs (100%) rename src/test/ui/{ => lint}/warn-path-statement.rs (100%) rename src/test/ui/{ => lint}/warn-path-statement.stderr (100%) rename src/test/ui/{ => liveness}/liveness-assign-imm-local-after-ret.rs (100%) rename src/test/ui/{issues => llvm-asm}/issue-23458.rs (100%) rename src/test/ui/{issues => llvm-asm}/issue-23458.stderr (100%) rename src/test/ui/{issues => llvm-asm}/issue-37366.rs (100%) rename src/test/ui/{issues => llvm-asm}/issue-53787-inline-assembler-macro.rs (100%) rename src/test/ui/{issues => llvm-asm}/issue-53787-inline-assembler-macro.stderr (100%) rename src/test/ui/{thinlto => lto}/all-crates.rs (100%) rename src/test/ui/{ => lto}/auxiliary/debuginfo-lto-aux.rs (100%) rename src/test/ui/{thinlto => lto}/auxiliary/dylib.rs (100%) rename src/test/ui/{ => lto}/auxiliary/lto-duplicate-symbols1.rs (100%) rename src/test/ui/{ => lto}/auxiliary/lto-duplicate-symbols2.rs (100%) rename src/test/ui/{ => lto}/auxiliary/lto-rustc-loads-linker-plugin.rs (100%) rename src/test/ui/{thinlto => lto}/auxiliary/msvc-imp-present.rs (100%) rename src/test/ui/{thinlto => lto}/auxiliary/thin-lto-inlines-aux.rs (100%) rename src/test/ui/{ => lto}/debuginfo-lto.rs (100%) rename src/test/ui/{thinlto => lto}/dylib-works.rs (100%) rename src/test/ui/{ => lto}/fat-lto.rs (100%) rename src/test/ui/{ => lto}/lto-and-no-bitcode-in-rlib.rs (100%) rename src/test/ui/{ => lto}/lto-and-no-bitcode-in-rlib.stderr (100%) rename src/test/ui/{ => lto}/lto-duplicate-symbols.rs (100%) rename src/test/ui/{ => lto}/lto-duplicate-symbols.stderr (100%) rename src/test/ui/{ => lto}/lto-many-codegen-units.rs (100%) rename src/test/ui/{ => lto}/lto-opt-level-s.rs (100%) rename src/test/ui/{ => lto}/lto-opt-level-z.rs (100%) rename src/test/ui/{ => lto}/lto-rustc-loads-linker-plugin.rs (100%) rename src/test/ui/{ => lto}/lto-still-runs-thread-dtors.rs (100%) rename src/test/ui/{ => lto}/lto-thin-rustc-loads-linker-plugin.rs (100%) rename src/test/ui/{thinlto => lto}/msvc-imp-present.rs (100%) rename src/test/ui/{ => lto}/thin-lto-global-allocator.rs (100%) rename src/test/ui/{thinlto => lto}/thin-lto-inlines.rs (100%) rename src/test/ui/{thinlto => lto}/thin-lto-inlines2.rs (100%) rename src/test/ui/{thinlto => lto}/weak-works.rs (100%) rename src/test/ui/{issues => macros}/auxiliary/issue-19163.rs (100%) rename src/test/ui/{ => macros}/auxiliary/proc_macro_def.rs (100%) rename src/test/ui/{ => macros}/concat.rs (100%) rename src/test/ui/{ => macros}/concat.stderr (100%) rename src/test/ui/{ => macros}/include-single-expr-helper-1.rs (100%) rename src/test/ui/{ => macros}/include-single-expr-helper.rs (100%) rename src/test/ui/{ => macros}/include-single-expr.rs (100%) rename src/test/ui/{ => macros}/include-single-expr.stderr (100%) rename src/test/ui/{issues => macros}/issue-16098.rs (100%) rename src/test/ui/{issues => macros}/issue-16098.stderr (100%) rename src/test/ui/{issues => macros}/issue-19163.rs (100%) rename src/test/ui/{issues => macros}/issue-19163.stderr (100%) rename src/test/ui/{issues => macros}/issue-21356.rs (100%) rename src/test/ui/{issues => macros}/issue-21356.stderr (100%) rename src/test/ui/{issues => macros}/issue-22463.rs (100%) rename src/test/ui/{issues => macros}/issue-29084.rs (100%) rename src/test/ui/{issues => macros}/issue-29084.stderr (100%) rename src/test/ui/{issues => macros}/issue-34171.rs (100%) rename src/test/ui/{issues => macros}/issue-37175.rs (100%) rename src/test/ui/{issues => macros}/issue-39388.rs (100%) rename src/test/ui/{issues => macros}/issue-39388.stderr (100%) rename src/test/ui/{issues => macros}/issue-40770.rs (100%) rename src/test/ui/{issues => macros}/issue-57597.rs (100%) rename src/test/ui/{issues => macros}/issue-57597.stderr (100%) rename src/test/ui/{issues => macros}/issue-6596-1.rs (100%) rename src/test/ui/{issues => macros}/issue-6596-1.stderr (100%) rename src/test/ui/{issues => macros}/issue-86865.rs (100%) rename src/test/ui/{issues => macros}/issue-86865.stderr (100%) rename src/test/ui/{ => macros}/malformed_macro_lhs.rs (100%) rename src/test/ui/{ => macros}/malformed_macro_lhs.stderr (100%) create mode 100644 src/test/ui/macros/missing-bang-in-decl.fixed create mode 100644 src/test/ui/macros/missing-bang-in-decl.rs create mode 100644 src/test/ui/macros/missing-bang-in-decl.stderr rename src/test/ui/{ => macros}/no-std-macros.rs (100%) rename src/test/ui/{ => macros}/proc_macro.rs (100%) rename src/test/ui/{ => macros}/trace_macros-format.rs (100%) rename src/test/ui/{ => macros}/trace_macros-format.stderr (100%) rename src/test/ui/{ => marker_trait_attr}/overlap-doesnt-conflict-with-specialization.rs (100%) rename src/test/ui/{ => marker_trait_attr}/overlap-doesnt-conflict-with-specialization.stderr (100%) rename src/test/ui/{ => marker_trait_attr}/overlap-permitted-for-annotated-marker-traits.rs (100%) rename src/test/ui/{issues => match}/issue-11940.rs (100%) rename src/test/ui/{issues => match}/issue-18060.rs (100%) rename src/test/ui/{issues => match}/issue-26251.rs (100%) rename src/test/ui/{issues => match}/issue-26996.rs (100%) rename src/test/ui/{issues => match}/issue-42679.rs (100%) create mode 100644 src/test/ui/match/issue-91058.rs create mode 100644 src/test/ui/match/issue-91058.stderr rename src/test/ui/{ => match}/match-on-negative-integer-ranges.rs (100%) delete mode 100644 src/test/ui/mir-dataflow/indirect-mutation-offset.rs delete mode 100644 src/test/ui/mir-dataflow/indirect-mutation-offset.stderr rename src/test/ui/{ => mir}/issue-73914.rs (100%) rename src/test/ui/{issues => mir}/issue-74739.rs (100%) rename src/test/ui/{ => mismatched_types}/assignment-operator-unimplemented.rs (100%) rename src/test/ui/{ => mismatched_types}/assignment-operator-unimplemented.stderr (100%) rename src/test/ui/{ => mismatched_types}/float-literal-inference-restrictions.rs (100%) rename src/test/ui/{ => mismatched_types}/float-literal-inference-restrictions.stderr (100%) rename src/test/ui/{issues => missing-trait-bounds}/auxiliary/issue-69725.rs (100%) create mode 100644 src/test/ui/missing-trait-bounds/issue-35677.fixed rename src/test/ui/{issues => missing-trait-bounds}/issue-35677.rs (74%) rename src/test/ui/{issues => missing-trait-bounds}/issue-35677.stderr (61%) create mode 100644 src/test/ui/missing-trait-bounds/issue-69725.fixed rename src/test/ui/{issues => missing-trait-bounds}/issue-69725.rs (83%) rename src/test/ui/{issues => missing-trait-bounds}/issue-69725.stderr (78%) rename src/test/ui/{suggestions => missing-trait-bounds}/missing-trait-bound-for-op.fixed (100%) rename src/test/ui/{suggestions => missing-trait-bounds}/missing-trait-bound-for-op.rs (100%) rename src/test/ui/{suggestions => missing-trait-bounds}/missing-trait-bound-for-op.stderr (100%) rename src/test/ui/{suggestions => missing-trait-bounds}/missing-trait-bounds-for-method-call.rs (100%) rename src/test/ui/{suggestions => missing-trait-bounds}/missing-trait-bounds-for-method-call.stderr (100%) create mode 100644 src/test/ui/moves/move-of-addr-of-mut.rs create mode 100644 src/test/ui/moves/move-of-addr-of-mut.stderr delete mode 100644 src/test/ui/negative.rs rename src/test/ui/{ => never_type}/diverging-tuple-parts-39485.rs (100%) rename src/test/ui/{ => never_type}/diverging-tuple-parts-39485.stderr (100%) delete mode 100644 src/test/ui/newtype-temporary.rs create mode 100644 src/test/ui/nll/issue-78561.rs rename src/test/ui/{ => nll}/lub-if.nll.stderr (100%) rename src/test/ui/{ => nll}/lub-if.rs (100%) rename src/test/ui/{ => nll}/lub-if.stderr (100%) rename src/test/ui/{ => nll}/lub-match.nll.stderr (100%) rename src/test/ui/{ => nll}/lub-match.rs (100%) rename src/test/ui/{ => nll}/lub-match.stderr (100%) rename src/test/ui/{ => nll}/ref-suggestion.rs (100%) rename src/test/ui/{ => nll}/ref-suggestion.stderr (100%) delete mode 100644 src/test/ui/non-legacy-modes.rs rename src/test/ui/{ => numbers-arithmetic}/unary-minus-suffix-inference.rs (100%) rename src/test/ui/{ => numeric}/integer-literal-suffix-inference.rs (100%) rename src/test/ui/{ => numeric}/integer-literal-suffix-inference.stderr (100%) rename src/test/ui/{ => object-lifetime}/object-lifetime-default-default-to-static.rs (100%) rename src/test/ui/{structs-enums => object-lifetime}/object-lifetime-default-from-ref-struct.rs (100%) rename src/test/ui/{ => object-lifetime}/object-lifetime-default-from-rptr-box.rs (100%) rename src/test/ui/{ => object-lifetime}/object-lifetime-default-from-rptr-mut.rs (100%) rename src/test/ui/{structs-enums => object-lifetime}/object-lifetime-default-from-rptr-struct.rs (100%) rename src/test/ui/{ => object-lifetime}/object-lifetime-default-from-rptr.rs (100%) rename src/test/ui/{ => object-lifetime}/object-lifetime-default-inferred.rs (100%) rename src/test/ui/{ => overloaded}/fixup-deref-mut.rs (100%) rename src/test/ui/{ => overloaded}/overloaded-calls-nontuple.rs (100%) rename src/test/ui/{ => overloaded}/overloaded-calls-nontuple.stderr (100%) rename src/test/ui/{issues/issue-45152.rs => packed/issue-46152.rs} (100%) create mode 100644 src/test/ui/panics/location-detail-panic-no-column.rs create mode 100644 src/test/ui/panics/location-detail-panic-no-column.run.stderr create mode 100644 src/test/ui/panics/location-detail-panic-no-file.rs create mode 100644 src/test/ui/panics/location-detail-panic-no-file.run.stderr create mode 100644 src/test/ui/panics/location-detail-panic-no-line.rs create mode 100644 src/test/ui/panics/location-detail-panic-no-line.run.stderr create mode 100644 src/test/ui/panics/location-detail-unwrap-no-file.rs create mode 100644 src/test/ui/panics/location-detail-unwrap-no-file.run.stderr delete mode 100644 src/test/ui/paren-free.rs rename src/test/ui/{ => parser}/attribute-with-no-generics-in-parameter-list.rs (100%) rename src/test/ui/{ => parser}/attribute-with-no-generics-in-parameter-list.stderr (100%) rename src/test/ui/{ => parser}/bastion-of-the-turbofish.rs (100%) create mode 100644 src/test/ui/parser/char/whitespace-character-literal.rs create mode 100644 src/test/ui/parser/char/whitespace-character-literal.stderr create mode 100644 src/test/ui/parser/const-param-decl-on-type-instead-of-impl.rs create mode 100644 src/test/ui/parser/const-param-decl-on-type-instead-of-impl.stderr rename src/test/ui/{ => parser}/dyn-trait-compatibility.rs (100%) rename src/test/ui/{ => parser}/dyn-trait-compatibility.stderr (100%) create mode 100644 src/test/ui/parser/emoji-identifiers.rs create mode 100644 src/test/ui/parser/emoji-identifiers.stderr create mode 100644 src/test/ui/parser/issue-90728.rs create mode 100644 src/test/ui/parser/issue-90728.stderr rename src/test/ui/parser/{ => issues}/auxiliary/issue-21146-inc.rs (100%) create mode 100644 src/test/ui/parser/issues/auxiliary/issue-89971-outer-attr-following-inner-attr-ice.rs rename src/test/ui/parser/{ => issues}/issue-10392-2.fixed (100%) rename src/test/ui/parser/{ => issues}/issue-10392-2.rs (100%) rename src/test/ui/parser/{ => issues}/issue-10392-2.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-10392.rs (100%) rename src/test/ui/parser/{ => issues}/issue-10392.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-10636-1.rs (100%) rename src/test/ui/parser/{ => issues}/issue-10636-1.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-10636-2.rs (100%) rename src/test/ui/parser/{ => issues}/issue-10636-2.stderr (100%) rename src/test/ui/{ => parser}/issues/issue-13483.rs (100%) rename src/test/ui/{ => parser}/issues/issue-13483.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-14303-enum.rs (100%) rename src/test/ui/parser/{ => issues}/issue-14303-enum.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-14303-fn-def.rs (100%) rename src/test/ui/parser/{ => issues}/issue-14303-fn-def.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-14303-fncall.full.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-14303-fncall.generic_arg.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-14303-fncall.rs (100%) rename src/test/ui/parser/{ => issues}/issue-14303-impl.rs (100%) rename src/test/ui/parser/{ => issues}/issue-14303-impl.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-14303-path.rs (100%) rename src/test/ui/parser/{ => issues}/issue-14303-path.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-14303-struct.rs (100%) rename src/test/ui/parser/{ => issues}/issue-14303-struct.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-14303-trait.rs (100%) rename src/test/ui/parser/{ => issues}/issue-14303-trait.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-15914.rs (100%) rename src/test/ui/parser/{ => issues}/issue-15914.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-15980.rs (100%) rename src/test/ui/parser/{ => issues}/issue-15980.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-1655.rs (100%) rename src/test/ui/parser/{ => issues}/issue-1655.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-17383.rs (100%) rename src/test/ui/parser/{ => issues}/issue-17383.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-17718-const-mut.rs (100%) rename src/test/ui/parser/{ => issues}/issue-17718-const-mut.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-17904-2.rs (100%) rename src/test/ui/parser/{ => issues}/issue-17904-2.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-17904.rs (100%) rename src/test/ui/parser/{ => issues}/issue-17904.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-1802-1.rs (100%) rename src/test/ui/parser/{ => issues}/issue-1802-1.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-1802-2.rs (100%) rename src/test/ui/parser/{ => issues}/issue-1802-2.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-19096.rs (100%) rename src/test/ui/parser/{ => issues}/issue-19096.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-19398.rs (100%) rename src/test/ui/parser/{ => issues}/issue-19398.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-20616-1.rs (100%) rename src/test/ui/parser/{ => issues}/issue-20616-1.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-20616-2.rs (100%) rename src/test/ui/parser/{ => issues}/issue-20616-2.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-20616-3.rs (100%) rename src/test/ui/parser/{ => issues}/issue-20616-3.stderr (100%) rename src/test/ui/{ => parser}/issues/issue-20616-4.rs (100%) rename src/test/ui/{ => parser}/issues/issue-20616-4.stderr (100%) rename src/test/ui/{ => parser}/issues/issue-20616-5.rs (100%) rename src/test/ui/{ => parser}/issues/issue-20616-5.stderr (100%) rename src/test/ui/{ => parser}/issues/issue-20616-6.rs (100%) rename src/test/ui/{ => parser}/issues/issue-20616-6.stderr (100%) rename src/test/ui/{ => parser}/issues/issue-20616-7.rs (100%) rename src/test/ui/{ => parser}/issues/issue-20616-7.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-20616-8.rs (100%) rename src/test/ui/parser/{ => issues}/issue-20616-8.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-20616-9.rs (100%) rename src/test/ui/parser/{ => issues}/issue-20616-9.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-20711-2.rs (100%) rename src/test/ui/parser/{ => issues}/issue-20711-2.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-20711.rs (100%) rename src/test/ui/parser/{ => issues}/issue-20711.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-21146.rs (100%) rename src/test/ui/parser/{ => issues}/issue-21146.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-21153.rs (100%) rename src/test/ui/parser/{ => issues}/issue-21153.stderr (100%) rename src/test/ui/{ => parser}/issues/issue-21475.rs (100%) rename src/test/ui/parser/{ => issues}/issue-22647.rs (100%) rename src/test/ui/parser/{ => issues}/issue-22647.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-22712.rs (100%) rename src/test/ui/parser/{ => issues}/issue-22712.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-2354-1.rs (100%) rename src/test/ui/parser/{ => issues}/issue-2354-1.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-2354.rs (100%) rename src/test/ui/parser/{ => issues}/issue-2354.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-23620-invalid-escapes.rs (100%) rename src/test/ui/parser/{ => issues}/issue-23620-invalid-escapes.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-24197.rs (100%) rename src/test/ui/parser/{ => issues}/issue-24197.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-24375.rs (100%) rename src/test/ui/parser/{ => issues}/issue-24375.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-24780.rs (100%) rename src/test/ui/parser/{ => issues}/issue-24780.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-27255.rs (100%) rename src/test/ui/parser/{ => issues}/issue-27255.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-30318.fixed (100%) rename src/test/ui/parser/{ => issues}/issue-30318.rs (100%) rename src/test/ui/parser/{ => issues}/issue-30318.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-3036.fixed (100%) rename src/test/ui/parser/{ => issues}/issue-3036.rs (100%) rename src/test/ui/parser/{ => issues}/issue-3036.stderr (100%) rename src/test/ui/{ => parser}/issues/issue-31804.rs (100%) rename src/test/ui/{ => parser}/issues/issue-31804.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-32214.rs (100%) rename src/test/ui/parser/{ => issues}/issue-32214.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-32446.rs (100%) rename src/test/ui/parser/{ => issues}/issue-32446.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-32501.rs (100%) rename src/test/ui/parser/{ => issues}/issue-32501.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-32505.rs (100%) rename src/test/ui/parser/{ => issues}/issue-32505.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-33262.rs (100%) rename src/test/ui/parser/{ => issues}/issue-33262.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-33413.rs (100%) rename src/test/ui/parser/{ => issues}/issue-33413.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-33418.fixed (100%) rename src/test/ui/parser/{ => issues}/issue-33418.rs (100%) rename src/test/ui/parser/{ => issues}/issue-33418.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-33455.rs (100%) rename src/test/ui/parser/{ => issues}/issue-33455.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-34222-1.rs (100%) rename src/test/ui/parser/{ => issues}/issue-34222-1.stderr (100%) rename src/test/ui/{ => parser}/issues/issue-34255-1.rs (100%) rename src/test/ui/{ => parser}/issues/issue-34255-1.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-35813-postfix-after-cast.rs (100%) rename src/test/ui/parser/{ => issues}/issue-35813-postfix-after-cast.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-41155.rs (100%) rename src/test/ui/parser/{ => issues}/issue-41155.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-43196.rs (100%) rename src/test/ui/parser/{ => issues}/issue-43196.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-43692.rs (100%) rename src/test/ui/parser/{ => issues}/issue-43692.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-44021.rs (100%) rename src/test/ui/parser/{ => issues}/issue-44021.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-44406.rs (100%) rename src/test/ui/parser/{ => issues}/issue-44406.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-45296.rs (100%) rename src/test/ui/parser/{ => issues}/issue-45296.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-46186.fixed (100%) rename src/test/ui/parser/{ => issues}/issue-46186.rs (100%) rename src/test/ui/parser/{ => issues}/issue-46186.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs (100%) rename src/test/ui/parser/{ => issues}/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-48137-macros-cannot-interpolate-impl-items.rs (100%) rename src/test/ui/parser/{ => issues}/issue-48508-aux.rs (100%) rename src/test/ui/parser/{ => issues}/issue-48508.rs (100%) rename src/test/ui/parser/{ => issues}/issue-48636.fixed (100%) rename src/test/ui/parser/{ => issues}/issue-48636.rs (100%) rename src/test/ui/parser/{ => issues}/issue-48636.stderr (100%) rename src/test/ui/{ => parser}/issues/issue-49040.rs (100%) rename src/test/ui/{ => parser}/issues/issue-49040.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-51602.rs (100%) rename src/test/ui/parser/{ => issues}/issue-51602.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-52496.rs (100%) rename src/test/ui/parser/{ => issues}/issue-52496.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-54521-1.rs (100%) rename src/test/ui/parser/{ => issues}/issue-54521-2.fixed (100%) rename src/test/ui/parser/{ => issues}/issue-54521-2.rs (100%) rename src/test/ui/parser/{ => issues}/issue-54521-2.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-54521-3.fixed (100%) rename src/test/ui/parser/{ => issues}/issue-54521-3.rs (100%) rename src/test/ui/parser/{ => issues}/issue-54521-3.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-5544-a.rs (100%) rename src/test/ui/parser/{ => issues}/issue-5544-a.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-5544-b.rs (100%) rename src/test/ui/parser/{ => issues}/issue-5544-b.stderr (100%) rename src/test/ui/{ => parser}/issues/issue-56031.rs (100%) rename src/test/ui/{ => parser}/issues/issue-56031.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-57198.rs (100%) rename src/test/ui/parser/{ => issues}/issue-57198.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-57684.fixed (100%) rename src/test/ui/parser/{ => issues}/issue-57684.rs (100%) rename src/test/ui/parser/{ => issues}/issue-57684.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-57819.fixed (100%) rename src/test/ui/parser/{ => issues}/issue-57819.rs (100%) rename src/test/ui/parser/{ => issues}/issue-57819.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-5806.rs (100%) rename src/test/ui/parser/{ => issues}/issue-5806.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-58094-missing-right-square-bracket.rs (100%) rename src/test/ui/parser/{ => issues}/issue-58094-missing-right-square-bracket.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-58856-1.rs (100%) rename src/test/ui/parser/{ => issues}/issue-58856-1.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-58856-2.rs (100%) rename src/test/ui/parser/{ => issues}/issue-58856-2.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-59418.rs (100%) rename src/test/ui/parser/{ => issues}/issue-59418.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-60075.rs (100%) rename src/test/ui/parser/{ => issues}/issue-60075.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-62524.rs (100%) rename src/test/ui/parser/{ => issues}/issue-62524.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-62546.rs (100%) rename src/test/ui/parser/{ => issues}/issue-62546.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-62554.rs (100%) rename src/test/ui/parser/{ => issues}/issue-62554.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-62660.rs (100%) rename src/test/ui/parser/{ => issues}/issue-62660.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-62881.rs (100%) rename src/test/ui/parser/{ => issues}/issue-62881.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-62894.rs (100%) rename src/test/ui/parser/{ => issues}/issue-62894.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-62895.rs (100%) rename src/test/ui/parser/{ => issues}/issue-62895.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-62913.rs (100%) rename src/test/ui/parser/{ => issues}/issue-62913.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-62973.rs (100%) rename src/test/ui/parser/{ => issues}/issue-62973.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-63115-range-pat-interpolated.rs (100%) rename src/test/ui/parser/{ => issues}/issue-63116.rs (100%) rename src/test/ui/parser/{ => issues}/issue-63116.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-63135.rs (100%) rename src/test/ui/parser/{ => issues}/issue-63135.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-64732.rs (100%) rename src/test/ui/parser/{ => issues}/issue-64732.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-65041-empty-vis-matcher-in-enum.rs (100%) rename src/test/ui/parser/{ => issues}/issue-65041-empty-vis-matcher-in-trait.rs (100%) rename src/test/ui/parser/{ => issues}/issue-65122-mac-invoc-in-mut-patterns.rs (100%) rename src/test/ui/parser/{ => issues}/issue-65122-mac-invoc-in-mut-patterns.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-65257-invalid-var-decl-recovery.rs (100%) rename src/test/ui/parser/{ => issues}/issue-65257-invalid-var-decl-recovery.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-65846-rollback-gating-failing-matcher.rs (100%) rename src/test/ui/parser/{ => issues}/issue-6610.rs (100%) rename src/test/ui/parser/{ => issues}/issue-6610.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-66357-unexpected-unreachable.rs (100%) rename src/test/ui/parser/{ => issues}/issue-66357-unexpected-unreachable.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-66473.rs (100%) rename src/test/ui/parser/{ => issues}/issue-66473.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-67146-negative-outlives-bound-syntactic-fail.fixed (100%) rename src/test/ui/parser/{ => issues}/issue-67146-negative-outlives-bound-syntactic-fail.rs (100%) rename src/test/ui/parser/{ => issues}/issue-67146-negative-outlives-bound-syntactic-fail.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-67377-invalid-syntax-in-enum-discriminant.rs (100%) rename src/test/ui/parser/{ => issues}/issue-67377-invalid-syntax-in-enum-discriminant.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-68000-unicode-ident-after-missing-comma.rs (100%) rename src/test/ui/parser/{ => issues}/issue-68000-unicode-ident-after-missing-comma.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-68629.rs (100%) rename src/test/ui/parser/{ => issues}/issue-68629.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-68730.rs (100%) rename src/test/ui/parser/{ => issues}/issue-68730.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-68788-in-trait-item-propagation.rs (100%) rename src/test/ui/parser/{ => issues}/issue-68890-2.rs (100%) rename src/test/ui/parser/{ => issues}/issue-68890-2.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-68890.rs (100%) rename src/test/ui/parser/{ => issues}/issue-68890.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-70050-ntliteral-accepts-negated-lit.rs (100%) rename src/test/ui/parser/{ => issues}/issue-70388-recover-dotdotdot-rest-pat.rs (100%) rename src/test/ui/parser/{ => issues}/issue-70388-recover-dotdotdot-rest-pat.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-70388-without-witness.fixed (100%) rename src/test/ui/parser/{ => issues}/issue-70388-without-witness.rs (100%) rename src/test/ui/parser/{ => issues}/issue-70388-without-witness.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-70549-resolve-after-recovered-self-ctor.rs (100%) rename src/test/ui/parser/{ => issues}/issue-70549-resolve-after-recovered-self-ctor.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-70552-ascription-in-parens-after-call.rs (100%) rename src/test/ui/parser/{ => issues}/issue-70552-ascription-in-parens-after-call.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-70583-block-is-empty-1.rs (100%) rename src/test/ui/parser/{ => issues}/issue-70583-block-is-empty-1.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-70583-block-is-empty-2.rs (100%) rename src/test/ui/parser/{ => issues}/issue-70583-block-is-empty-2.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-7222.rs (100%) rename src/test/ui/parser/{ => issues}/issue-72253.rs (100%) rename src/test/ui/parser/{ => issues}/issue-72253.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-72373.rs (100%) rename src/test/ui/parser/{ => issues}/issue-72373.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-73568-lifetime-after-mut.rs (100%) rename src/test/ui/parser/{ => issues}/issue-73568-lifetime-after-mut.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-75599.rs (100%) rename src/test/ui/parser/{ => issues}/issue-76437-async.rs (100%) rename src/test/ui/parser/{ => issues}/issue-76437-async.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-76437-const-async-unsafe.rs (100%) rename src/test/ui/parser/{ => issues}/issue-76437-const-async-unsafe.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-76437-const-async.rs (100%) rename src/test/ui/parser/{ => issues}/issue-76437-const-async.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-76437-const.rs (100%) rename src/test/ui/parser/{ => issues}/issue-76437-const.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-76437-pub-crate-unsafe.rs (100%) rename src/test/ui/parser/{ => issues}/issue-76437-pub-crate-unsafe.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-76437-unsafe.rs (100%) rename src/test/ui/parser/{ => issues}/issue-76437-unsafe.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-76597.fixed (100%) rename src/test/ui/parser/{ => issues}/issue-76597.rs (100%) rename src/test/ui/parser/{ => issues}/issue-76597.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-7970b.rs (100%) rename src/test/ui/parser/{ => issues}/issue-7970b.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-81806.rs (100%) rename src/test/ui/parser/{ => issues}/issue-81806.stderr (100%) rename src/test/ui/{ => parser/issues}/issue-83639.rs (100%) rename src/test/ui/{ => parser/issues}/issue-83639.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-84104.rs (100%) rename src/test/ui/parser/{ => issues}/issue-84104.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-84117.rs (100%) rename src/test/ui/parser/{ => issues}/issue-84117.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-84148-1.rs (100%) rename src/test/ui/parser/{ => issues}/issue-84148-1.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-84148-2.rs (100%) rename src/test/ui/parser/{ => issues}/issue-84148-2.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-8537.rs (100%) rename src/test/ui/parser/{ => issues}/issue-8537.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-86895.rs (100%) rename src/test/ui/parser/{ => issues}/issue-86895.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-87086-colon-path-sep.rs (100%) rename src/test/ui/parser/{ => issues}/issue-87086-colon-path-sep.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-87197-missing-semicolon.fixed (100%) rename src/test/ui/parser/{ => issues}/issue-87197-missing-semicolon.rs (100%) rename src/test/ui/parser/{ => issues}/issue-87197-missing-semicolon.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-87217-keyword-order/const-async-const.rs (100%) rename src/test/ui/parser/{ => issues}/issue-87217-keyword-order/const-async-const.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-87217-keyword-order/several-kw-jump.rs (100%) rename src/test/ui/parser/{ => issues}/issue-87217-keyword-order/several-kw-jump.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-87217-keyword-order/wrong-async.rs (100%) rename src/test/ui/parser/{ => issues}/issue-87217-keyword-order/wrong-async.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-87217-keyword-order/wrong-const.rs (100%) rename src/test/ui/parser/{ => issues}/issue-87217-keyword-order/wrong-const.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-87217-keyword-order/wrong-unsafe.rs (100%) rename src/test/ui/parser/{ => issues}/issue-87217-keyword-order/wrong-unsafe.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-87635.rs (100%) rename src/test/ui/parser/{ => issues}/issue-87635.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-87812-path.rs (100%) rename src/test/ui/parser/{ => issues}/issue-87812-path.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-87812.rs (100%) rename src/test/ui/parser/{ => issues}/issue-87812.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-88276-unary-plus.fixed (100%) rename src/test/ui/parser/{ => issues}/issue-88276-unary-plus.rs (100%) rename src/test/ui/parser/{ => issues}/issue-88276-unary-plus.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-88583-union-as-ident.rs (100%) rename src/test/ui/parser/{ => issues}/issue-88770.rs (100%) rename src/test/ui/parser/{ => issues}/issue-88770.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-88818.rs (100%) rename src/test/ui/parser/{ => issues}/issue-88818.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-89388.rs (100%) rename src/test/ui/parser/{ => issues}/issue-89388.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-89396.fixed (100%) rename src/test/ui/parser/{ => issues}/issue-89396.rs (100%) rename src/test/ui/parser/{ => issues}/issue-89396.stderr (100%) rename src/test/ui/parser/{ => issues}/issue-89574.rs (100%) rename src/test/ui/parser/{ => issues}/issue-89574.stderr (100%) create mode 100644 src/test/ui/parser/issues/issue-89971-outer-attr-following-inner-attr-ice.rs create mode 100644 src/test/ui/parser/issues/issue-89971-outer-attr-following-inner-attr-ice.stderr create mode 100644 src/test/ui/parser/issues/issue-90993.rs create mode 100644 src/test/ui/parser/issues/issue-90993.stderr rename src/test/ui/{ => parser}/obsolete-syntax-impl-for-dotdot.rs (100%) rename src/test/ui/{ => parser}/obsolete-syntax-impl-for-dotdot.stderr (100%) rename src/test/ui/{ => parser}/operator-associativity.rs (100%) rename src/test/ui/{ => parser}/ranges-precedence.rs (100%) rename src/test/ui/{ => parser}/similar-tokens.rs (100%) rename src/test/ui/{ => parser}/similar-tokens.stderr (100%) rename src/test/ui/{ => parser}/utf8_idents-rpass.rs (100%) rename src/test/ui/{ => pattern}/ignore-all-the-things.rs (100%) rename src/test/ui/{issues => pattern}/issue-11577.rs (100%) rename src/test/ui/{issues => pattern}/issue-15080.rs (100%) rename src/test/ui/{issues => pattern}/issue-72574-2.rs (100%) rename src/test/ui/{issues => pattern}/issue-72574-2.stderr (100%) rename src/test/ui/{issues => pattern}/issue-8351-1.rs (100%) rename src/test/ui/{issues => pattern}/issue-8351-2.rs (100%) create mode 100644 src/test/ui/pattern/non-structural-match-types.rs create mode 100644 src/test/ui/pattern/non-structural-match-types.stderr create mode 100644 src/test/ui/pattern/usefulness/issue-88747.rs rename src/test/ui/{ => privacy}/auxiliary/impl_privacy_xc_2.rs (100%) rename src/test/ui/{ => privacy}/auxiliary/reachable-unnameable-items.rs (100%) create mode 100644 src/test/ui/privacy/crate-private-reexport.rs create mode 100644 src/test/ui/privacy/crate-private-reexport.stderr rename src/test/ui/{ => privacy}/export-tag-variant.rs (100%) rename src/test/ui/{ => privacy}/export-tag-variant.stderr (100%) rename src/test/ui/{ => privacy}/impl-privacy-xc-2.rs (100%) rename src/test/ui/{ => privacy}/reachable-unnameable-items.rs (100%) rename src/test/ui/{ => privacy}/useless-pub.rs (100%) rename src/test/ui/{ => privacy}/useless-pub.stderr (100%) rename src/test/ui/{ => proc-macro}/auxiliary/cond_plugin.rs (100%) create mode 100644 src/test/ui/proc-macro/auxiliary/expand-expr.rs create mode 100644 src/test/ui/proc-macro/auxiliary/included-file.txt create mode 100644 src/test/ui/proc-macro/expand-expr.rs create mode 100644 src/test/ui/proc-macro/expand-expr.stderr rename src/test/ui/{ => proc-macro}/macro-quote-cond.rs (100%) rename src/test/ui/{ => process}/core-run-destroy.rs (100%) rename src/test/ui/{ => process}/fds-are-cloexec.rs (100%) rename src/test/ui/{issues => process}/issue-14456.rs (100%) rename src/test/ui/{issues => process}/issue-16272.rs (100%) rename src/test/ui/{issues => process}/issue-20091.rs (100%) rename src/test/ui/{ => process}/multi-panic.rs (100%) rename src/test/ui/{ => process}/no-stdio.rs (100%) rename src/test/ui/{ => process}/signal-exit-status.rs (100%) rename src/test/ui/{ => process}/sigpipe-should-be-ignored.rs (100%) rename src/test/ui/{ => process}/try-wait.rs (100%) delete mode 100644 src/test/ui/pure-sum.rs delete mode 100644 src/test/ui/purity-infer.rs create mode 100644 src/test/ui/query-system/issue-83479.rs create mode 100644 src/test/ui/query-system/issue-83479.stderr delete mode 100644 src/test/ui/readalias.rs rename src/test/ui/{ => recursion}/instantiable.rs (100%) delete mode 100644 src/test/ui/reexport-should-still-link.rs rename src/test/ui/{ => regions}/init-res-into-things.rs (100%) rename src/test/ui/{issues => regions}/issue-21520.rs (100%) rename src/test/ui/{issues => regions}/issue-26448-1.rs (100%) rename src/test/ui/{issues => regions}/issue-26448-2.rs (100%) rename src/test/ui/{issues => regions}/issue-26448-3.rs (100%) rename src/test/ui/{ => regions}/owned-implies-static.rs (100%) rename src/test/ui/{ => regions}/rcvr-borrowed-to-region.rs (100%) delete mode 100644 src/test/ui/regions/regions-static-bound.ll.nll.stderr delete mode 100644 src/test/ui/regions/regions-static-bound.migrate.nll.stderr delete mode 100644 src/test/ui/regions/regions-static-bound.migrate.stderr create mode 100644 src/test/ui/regions/regions-static-bound.stderr rename src/test/ui/{ => regions}/wf-bound-region-in-object-type.rs (100%) rename src/test/ui/{ => repr}/attr-usage-repr.rs (100%) rename src/test/ui/{ => repr}/attr-usage-repr.stderr (100%) rename src/test/ui/{ => repr}/repr.rs (100%) rename src/test/ui/{ => repr}/repr.stderr (100%) rename src/test/ui/{ => resolve}/auxiliary/blind-item-mixed-crate-use-item-foo.rs (100%) rename src/test/ui/{ => resolve}/auxiliary/blind-item-mixed-crate-use-item-foo2.rs (100%) rename src/test/ui/{ => resolve}/blind-item-mixed-crate-use-item.rs (100%) rename src/test/ui/{ => resolve}/blind-item-mixed-use-item.rs (100%) rename src/test/ui/{ => resolve}/crate-in-paths.rs (100%) rename src/test/ui/{ => resolve}/crate-in-paths.stderr (100%) rename src/test/ui/{ => resolve}/editions-crate-root-2015.rs (100%) rename src/test/ui/{ => resolve}/editions-crate-root-2015.stderr (100%) rename src/test/ui/{ => resolve}/editions-crate-root-2018.rs (100%) rename src/test/ui/{ => resolve}/editions-crate-root-2018.stderr (100%) rename src/test/ui/{ => resolve}/enums-pats-not-idents.rs (100%) rename src/test/ui/{ => resolve}/enums-pats-not-idents.stderr (100%) rename src/test/ui/{ => resolve}/export-fully-qualified.rs (100%) rename src/test/ui/{ => resolve}/export-fully-qualified.stderr (100%) rename src/test/ui/{issues => resolve}/issue-12796.rs (100%) rename src/test/ui/{issues => resolve}/issue-12796.stderr (100%) rename src/test/ui/{issues => resolve}/issue-23716.rs (100%) rename src/test/ui/{issues => resolve}/issue-23716.stderr (100%) rename src/test/ui/{issues => resolve}/issue-3021-c.rs (100%) rename src/test/ui/{issues => resolve}/issue-3021-c.stderr (100%) rename src/test/ui/{issues => resolve}/issue-3021.rs (100%) rename src/test/ui/{issues => resolve}/issue-3021.stderr (100%) rename src/test/ui/{issues => resolve}/issue-31845.rs (100%) rename src/test/ui/{issues => resolve}/issue-31845.stderr (100%) rename src/test/ui/{issues => resolve}/issue-5099.rs (100%) rename src/test/ui/{issues => resolve}/issue-5099.stderr (100%) create mode 100644 src/test/ui/resolve/issue-90113.rs create mode 100644 src/test/ui/resolve/issue-90113.stderr rename src/test/ui/{ => resolve}/no-implicit-prelude-nested.rs (100%) rename src/test/ui/{ => resolve}/no-implicit-prelude-nested.stderr (100%) rename src/test/ui/{ => resolve}/no-std-1.rs (100%) rename src/test/ui/{ => resolve}/no-std-2.rs (100%) rename src/test/ui/{ => resolve}/no-std-3.rs (100%) rename src/test/ui/{ => resolve}/pathless-extern-ok.rs (100%) rename src/test/ui/{ => resolve}/resolve-issue-2428.rs (100%) delete mode 100644 src/test/ui/ret-none.rs rename src/test/ui/{issues => rfc-1445-restrict-constants-in-patterns}/issue-6804.rs (100%) rename src/test/ui/{issues => rfc-1445-restrict-constants-in-patterns}/issue-6804.stderr (100%) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/const-drop-bound.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/trait-default-body-stability.rs create mode 100644 src/test/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.rs create mode 100644 src/test/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.stderr create mode 100644 src/test/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.rs create mode 100644 src/test/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr create mode 100644 src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs create mode 100644 src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr rename src/test/ui/{ => runtime}/atomic-print.rs (100%) rename src/test/ui/{ => runtime}/backtrace-debuginfo-aux.rs (100%) rename src/test/ui/{ => runtime}/backtrace-debuginfo.rs (100%) rename src/test/ui/{ => runtime}/native-print-no-runtime.rs (100%) rename src/test/ui/{ => runtime}/out-of-stack.rs (100%) rename src/test/ui/{ => runtime}/rt-explody-panic-payloads.rs (90%) rename src/test/ui/{ => runtime}/running-with-no-runtime.rs (100%) rename src/test/ui/{ => runtime}/signal-alternate-stack-cleanup.rs (100%) rename src/test/ui/{ => runtime}/stdout-during-shutdown.rs (100%) rename src/test/ui/{ => runtime}/stdout-during-shutdown.run.stdout (100%) create mode 100644 src/test/ui/rust-2018/uniform-paths/auxiliary/issue-55779-extern-trait.rs create mode 100644 src/test/ui/rust-2018/uniform-paths/auxiliary/issue-87932-a.rs create mode 100644 src/test/ui/rust-2018/uniform-paths/issue-55779.rs create mode 100644 src/test/ui/rust-2018/uniform-paths/issue-87932.rs create mode 100644 src/test/ui/rust-2018/uniform-paths/issue-87932.stderr rename src/test/ui/{ => rustdoc}/duplicate_doc_alias.rs (100%) rename src/test/ui/{ => rustdoc}/duplicate_doc_alias.stderr (100%) create mode 100644 src/test/ui/rustdoc/hidden-doc-associated-item.rs create mode 100644 src/test/ui/rustdoc/renamed-features-rustdoc_internals.rs create mode 100644 src/test/ui/rustdoc/renamed-features-rustdoc_internals.stderr delete mode 100644 src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.nll.stderr delete mode 100644 src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.nll.stderr rename src/test/ui/{ => self}/class-missing-self.rs (100%) rename src/test/ui/{ => self}/class-missing-self.stderr (100%) rename src/test/ui/{issues => self}/issue-61882-2.rs (100%) rename src/test/ui/{issues => self}/issue-61882-2.stderr (100%) rename src/test/ui/{issues => self}/issue-61882.rs (100%) rename src/test/ui/{issues => self}/issue-61882.stderr (100%) rename src/test/ui/{ => self}/objects-owned-object-owned-method.rs (100%) create mode 100644 src/test/ui/simd/simd-bitmask.rs rename src/test/ui/{ => specialization}/transmute-specialization.rs (100%) rename src/test/ui/{ => specialization}/transmute-specialization.stderr (100%) rename src/test/ui/{ => stability-attribute}/stability-in-private-module.rs (100%) rename src/test/ui/{ => stability-attribute}/stability-in-private-module.stderr (100%) create mode 100644 src/test/ui/stability-attribute/suggest-vec-allocator-api.rs create mode 100644 src/test/ui/stability-attribute/suggest-vec-allocator-api.stderr create mode 100644 src/test/ui/stack-protector/warn-stack-protector-unsupported.all.stderr create mode 100644 src/test/ui/stack-protector/warn-stack-protector-unsupported.basic.stderr create mode 100644 src/test/ui/stack-protector/warn-stack-protector-unsupported.rs create mode 100644 src/test/ui/stack-protector/warn-stack-protector-unsupported.strong.stderr rename src/test/ui/{ => static}/auxiliary/extern-statics.rs (100%) rename src/test/ui/{ => static}/auxiliary/nested_item.rs (100%) rename src/test/ui/{ => static}/nested_item_main.rs (100%) rename src/test/ui/{ => static}/refer-to-other-statics-by-value.rs (100%) rename src/test/ui/{ => static}/safe-extern-statics-mut.mir.stderr (100%) rename src/test/ui/{ => static}/safe-extern-statics-mut.rs (100%) rename src/test/ui/{ => static}/safe-extern-statics-mut.thir.stderr (100%) rename src/test/ui/{ => static}/safe-extern-statics.mir.stderr (100%) rename src/test/ui/{ => static}/safe-extern-statics.rs (100%) rename src/test/ui/{ => static}/safe-extern-statics.thir.stderr (100%) rename src/test/ui/{ => static}/static_sized_requirement.rs (100%) rename src/test/ui/{ => static}/thread-local-in-ctfe.rs (100%) rename src/test/ui/{ => static}/thread-local-in-ctfe.stderr (100%) rename src/test/ui/{issues => statics}/issue-14227.mir.stderr (100%) rename src/test/ui/{issues => statics}/issue-14227.rs (100%) rename src/test/ui/{issues => statics}/issue-14227.thir.stderr (100%) create mode 100644 src/test/ui/statics/issue-91050-1.rs create mode 100644 src/test/ui/statics/issue-91050-2.rs rename src/test/ui/{ => stdlib-unit-tests}/builtin-clone.rs (100%) rename src/test/ui/{ => stdlib-unit-tests}/eq-multidispatch.rs (100%) rename src/test/ui/{ => stdlib-unit-tests}/istr.rs (100%) rename src/test/ui/{ => stdlib-unit-tests}/log-knows-the-names-of-variants-in-std.rs (100%) rename src/test/ui/{ => stdlib-unit-tests}/matches2021.rs (86%) rename src/test/ui/{ => stdlib-unit-tests}/minmax-stability-issue-23687.rs (100%) rename src/test/ui/{ => stdlib-unit-tests}/not-sync.rs (100%) rename src/test/ui/{ => stdlib-unit-tests}/not-sync.stderr (100%) rename src/test/ui/{ => stdlib-unit-tests}/raw-fat-ptr.rs (100%) rename src/test/ui/{ => stdlib-unit-tests}/seq-compare.rs (100%) rename src/test/ui/{ => stdlib-unit-tests}/volatile-fat-ptr.rs (100%) rename src/test/ui/{issues => structs-enums}/issue-50731.rs (100%) rename src/test/ui/{ => structs}/large-records.rs (100%) create mode 100644 src/test/ui/suggest-using-chars.rs create mode 100644 src/test/ui/suggest-using-chars.stderr rename src/test/ui/{ => suggestions}/bound-suggestions.fixed (100%) rename src/test/ui/{ => suggestions}/bound-suggestions.rs (100%) rename src/test/ui/{ => suggestions}/bound-suggestions.stderr (100%) create mode 100644 src/test/ui/suggestions/boxed-variant-field.rs create mode 100644 src/test/ui/suggestions/boxed-variant-field.stderr create mode 100644 src/test/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.rs create mode 100644 src/test/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr create mode 100644 src/test/ui/suggestions/issue-90974.rs create mode 100644 src/test/ui/suggestions/issue-90974.stderr create mode 100644 src/test/ui/suggestions/suggest-tryinto-edition-change.rs create mode 100644 src/test/ui/suggestions/suggest-tryinto-edition-change.stderr create mode 100644 src/test/ui/suggestions/undeclared-module-alloc.rs create mode 100644 src/test/ui/suggestions/undeclared-module-alloc.stderr rename src/test/ui/{ => svh}/auxiliary/changing-crates-a1.rs (100%) rename src/test/ui/{ => svh}/auxiliary/changing-crates-a2.rs (100%) rename src/test/ui/{ => svh}/auxiliary/changing-crates-b.rs (100%) rename src/test/ui/{ => svh}/changing-crates.rs (100%) rename src/test/ui/{ => svh}/changing-crates.stderr (100%) delete mode 100644 src/test/ui/syntax-trait-polarity-feature-gate.rs delete mode 100644 src/test/ui/syntax-trait-polarity-feature-gate.stderr delete mode 100644 src/test/ui/synthetic-param.rs delete mode 100644 src/test/ui/synthetic-param.stderr delete mode 100644 src/test/ui/tail-direct.rs rename src/test/ui/{issues => test-attrs}/issue-20823.rs (100%) rename src/test/ui/{ => threads-sendsync}/child-outlives-parent.rs (100%) rename src/test/ui/{ => threads-sendsync}/clone-with-exterior.rs (100%) rename src/test/ui/{issues => threads-sendsync}/issue-24313.rs (100%) rename src/test/ui/{issues => threads-sendsync}/issue-4448.rs (100%) rename src/test/ui/{issues => threads-sendsync}/issue-8827.rs (100%) rename src/test/ui/{issues => threads-sendsync}/issue-9396.rs (100%) rename src/test/ui/{ => threads-sendsync}/mpsc_stress.rs (100%) rename src/test/ui/{ => threads-sendsync}/tcp-stress.rs (100%) rename src/test/ui/{ => threads-sendsync}/trivial-message.rs (100%) rename src/test/ui/{ => threads-sendsync}/unwind-resource.rs (100%) rename src/test/ui/{ => threads-sendsync}/yield.rs (100%) rename src/test/ui/{ => threads-sendsync}/yield1.rs (100%) rename src/test/ui/{ => threads-sendsync}/yield2.rs (100%) create mode 100644 src/test/ui/trait-bounds/issue-75961.rs rename src/test/ui/{ => traits}/alignment-gep-tup-like-1.rs (100%) rename src/test/ui/{ => traits}/bug-7295.rs (100%) rename src/test/ui/{ => traits}/cycle-generic-bound.rs (100%) rename src/test/ui/{ => traits}/early-vtbl-resolution.rs (100%) rename src/test/ui/{issues => traits}/issue-24010.rs (100%) rename src/test/ui/{issues => traits}/issue-38604.rs (100%) rename src/test/ui/{issues => traits}/issue-38604.stderr (100%) rename src/test/ui/{issues => traits}/issue-3973.rs (100%) rename src/test/ui/{issues => traits}/issue-3973.stderr (100%) rename src/test/ui/{issues => traits}/issue-59029-1.rs (100%) rename src/test/ui/{issues => traits}/issue-59029-1.stderr (100%) rename src/test/ui/{issues => traits}/issue-72455.rs (100%) create mode 100644 src/test/ui/traits/issue-85360-eval-obligation-ice.rs create mode 100644 src/test/ui/traits/issue-85360-eval-obligation-ice.stderr create mode 100644 src/test/ui/traits/issue-90195-2.rs create mode 100644 src/test/ui/traits/issue-90195.rs rename src/test/ui/{ => traits}/map-types.rs (100%) rename src/test/ui/{ => traits}/map-types.stderr (100%) rename src/test/ui/{ => traits}/monad.rs (100%) rename src/test/ui/{ => traits}/monomorphized-callees-with-ty-params-3314.rs (100%) rename src/test/ui/{ => traits}/multidispatch-conditional-impl-not-considered.rs (100%) rename src/test/ui/{ => traits}/multidispatch1.rs (100%) rename src/test/ui/{ => traits}/multidispatch2.rs (100%) delete mode 100644 src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.stderr rename src/test/ui/{ => traits}/no_send-struct.rs (100%) rename src/test/ui/{ => traits}/no_send-struct.stderr (100%) rename src/test/ui/{ => traits}/object-does-not-impl-trait.rs (100%) rename src/test/ui/{ => traits}/object-does-not-impl-trait.stderr (100%) rename src/test/ui/{ => traits}/objects-owned-object-borrowed-method-headerless.rs (100%) rename src/test/ui/{ => traits}/staticness-mismatch.rs (100%) rename src/test/ui/{ => traits}/staticness-mismatch.stderr (100%) rename src/test/ui/{ => traits}/syntax-trait-polarity.rs (100%) rename src/test/ui/{ => traits}/syntax-trait-polarity.stderr (100%) rename src/test/ui/{ => traits}/typeclasses-eq-example-static.rs (100%) rename src/test/ui/{ => traits}/typeclasses-eq-example.rs (100%) rename src/test/ui/{ => traits}/vtable-res-trait-param.rs (100%) rename src/test/ui/{ => traits}/vtable-res-trait-param.stderr (62%) create mode 100644 src/test/ui/traits/vtable/issue-91807.rs rename src/test/ui/{issues => try-block}/issue-45124.rs (100%) rename src/test/ui/{ => try-block}/try-is-identifier-edition2015.rs (100%) rename src/test/ui/{ => tuple}/tuple-index-fat-types.rs (100%) rename src/test/ui/{issues => type-alias-impl-trait}/issue-60662.rs (100%) rename src/test/ui/{issues => type-alias-impl-trait}/issue-60662.stdout (100%) create mode 100644 src/test/ui/type-alias-impl-trait/issue-89686.rs create mode 100644 src/test/ui/type-alias-impl-trait/issue-89686.stderr delete mode 100644 src/test/ui/type-in-nested-module.rs rename src/test/ui/{issues => type-inference}/issue-30225.rs (100%) rename src/test/ui/{issues => type-inference}/issue-30225.stderr (100%) rename src/test/ui/{ => type}/type-ascription.rs (100%) rename src/test/ui/{issues => typeck}/auxiliary/xcrate-issue-43189-a.rs (100%) rename src/test/ui/{issues => typeck}/auxiliary/xcrate-issue-43189-b.rs (100%) rename src/test/ui/{issues => typeck}/auxiliary/xcrate-issue-46112-rexport-core.rs (100%) rename src/test/ui/{issues => typeck}/auxiliary/xcrate-issue-61711-b.rs (100%) rename src/test/ui/{issues => typeck}/issue-43189.rs (100%) rename src/test/ui/{issues => typeck}/issue-43189.stderr (100%) rename src/test/ui/{issues => typeck}/issue-46112.rs (100%) rename src/test/ui/{issues => typeck}/issue-46112.stderr (58%) rename src/test/ui/{issues => typeck}/issue-61711-once-caused-rustc-inf-loop.rs (100%) create mode 100644 src/test/ui/typeck/issue-89806.rs create mode 100644 src/test/ui/typeck/issue-89806.stderr create mode 100644 src/test/ui/typeck/issue-89856.rs create mode 100644 src/test/ui/typeck/issue-89856.stderr create mode 100644 src/test/ui/typeck/issue-90101.rs create mode 100644 src/test/ui/typeck/issue-90101.stderr create mode 100644 src/test/ui/typeck/issue-90164.rs create mode 100644 src/test/ui/typeck/issue-90164.stderr create mode 100644 src/test/ui/typeck/issue-90804-incorrect-reference-suggestion.rs create mode 100644 src/test/ui/typeck/issue-90804-incorrect-reference-suggestion.stderr rename src/test/ui/{ => typeck}/no-type-for-node-ice.rs (100%) rename src/test/ui/{ => typeck}/no-type-for-node-ice.stderr (100%) rename src/test/ui/{ => typeck}/prim-with-args.rs (100%) rename src/test/ui/{ => typeck}/prim-with-args.stderr (100%) rename src/test/ui/{ => typeck}/project-cache-issue-37154.rs (100%) rename src/test/ui/{ => typeck}/ufcs-type-params.rs (100%) rename src/test/ui/{ => typeck}/unify-return-ty.rs (100%) rename src/test/ui/{issues => unboxed-closures}/issue-18652.rs (100%) rename src/test/ui/{issues => unsized}/issue-30355.rs (100%) rename src/test/ui/{issues => unsized}/issue-30355.stderr (100%) rename src/test/ui/{ => unsized}/maybe-bounds-where-cpass.rs (69%) rename src/test/ui/{ => unsized}/maybe-bounds-where.rs (100%) rename src/test/ui/{ => unsized}/maybe-bounds-where.stderr (100%) delete mode 100644 src/test/ui/use-crate-name-alias.rs create mode 100644 src/test/ui/variance/variance-associated-consts.rs create mode 100644 src/test/ui/variance/variance-associated-consts.stderr rename src/test/ui/{ => wasm}/wasm-import-module.rs (100%) rename src/test/ui/{ => wasm}/wasm-import-module.stderr (100%) delete mode 100644 src/test/ui/writealias.rs rename src/tools/clippy/.cargo/{config => config.toml} (100%) create mode 100644 src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_any.rs create mode 100644 src/tools/clippy/clippy_lints/src/format_args.rs create mode 100644 src/tools/clippy/clippy_lints/src/match_str_case_mismatch.rs create mode 100644 src/tools/clippy/clippy_lints/src/misc_early/literal_suffix.rs delete mode 100644 src/tools/clippy/clippy_lints/src/misc_early/unseparated_literal_suffix.rs create mode 100644 src/tools/clippy/clippy_lints/src/trailing_empty_array.rs create mode 100644 src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs create mode 100644 src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs create mode 100644 src/tools/clippy/clippy_lints/src/uninit_vec.rs create mode 100644 src/tools/clippy/clippy_lints/src/unit_hash.rs delete mode 100644 src/tools/clippy/clippy_utils/src/camel_case.rs create mode 100644 src/tools/clippy/clippy_utils/src/str_utils.rs create mode 100644 src/tools/clippy/tests/ui/crashes/auxiliary/ice-7868-aux.rs create mode 100644 src/tools/clippy/tests/ui/crashes/ice-7868.rs create mode 100644 src/tools/clippy/tests/ui/crashes/ice-7868.stderr create mode 100644 src/tools/clippy/tests/ui/crashes/ice-7869.rs create mode 100644 src/tools/clippy/tests/ui/crashes/ice-7869.stderr create mode 100644 src/tools/clippy/tests/ui/doc/doc-fixable.fixed rename src/tools/clippy/tests/ui/doc/{doc.rs => doc-fixable.rs} (91%) create mode 100644 src/tools/clippy/tests/ui/doc/doc-fixable.stderr delete mode 100644 src/tools/clippy/tests/ui/doc/doc.stderr create mode 100644 src/tools/clippy/tests/ui/doc/issue_1832.rs create mode 100644 src/tools/clippy/tests/ui/doc/issue_902.rs create mode 100644 src/tools/clippy/tests/ui/fn_to_numeric_cast_any.rs create mode 100644 src/tools/clippy/tests/ui/fn_to_numeric_cast_any.stderr create mode 100644 src/tools/clippy/tests/ui/format_args.fixed create mode 100644 src/tools/clippy/tests/ui/format_args.rs create mode 100644 src/tools/clippy/tests/ui/format_args.stderr create mode 100644 src/tools/clippy/tests/ui/format_args_unfixable.rs create mode 100644 src/tools/clippy/tests/ui/format_args_unfixable.stderr create mode 100644 src/tools/clippy/tests/ui/issue-7447.stderr create mode 100644 src/tools/clippy/tests/ui/manual_assert.edition2018.fixed rename src/tools/clippy/tests/ui/{manual_assert.stderr => manual_assert.edition2018.stderr} (96%) create mode 100644 src/tools/clippy/tests/ui/manual_assert.edition2021.fixed create mode 100644 src/tools/clippy/tests/ui/manual_assert.edition2021.stderr create mode 100644 src/tools/clippy/tests/ui/match_str_case_mismatch.rs create mode 100644 src/tools/clippy/tests/ui/match_str_case_mismatch.stderr rename src/tools/clippy/tests/ui/{match_wild_err_arm.stderr => match_wild_err_arm.edition2018.stderr} (86%) create mode 100644 src/tools/clippy/tests/ui/match_wild_err_arm.edition2021.stderr create mode 100644 src/tools/clippy/tests/ui/string_slice.rs create mode 100644 src/tools/clippy/tests/ui/string_slice.stderr create mode 100644 src/tools/clippy/tests/ui/trailing_empty_array.rs create mode 100644 src/tools/clippy/tests/ui/trailing_empty_array.stderr create mode 100644 src/tools/clippy/tests/ui/undocumented_unsafe_blocks.rs create mode 100644 src/tools/clippy/tests/ui/undocumented_unsafe_blocks.stderr create mode 100644 src/tools/clippy/tests/ui/uninit_vec.rs create mode 100644 src/tools/clippy/tests/ui/uninit_vec.stderr create mode 100644 src/tools/clippy/tests/ui/unit_hash.rs create mode 100644 src/tools/clippy/tests/ui/unit_hash.stderr create mode 100644 src/tools/clippy/tests/ui_test/eq_op.rs create mode 100644 src/tools/rustfmt/.github/workflows/rustdoc_check.yml delete mode 100644 src/tools/rustfmt/appveyor.yml delete mode 100644 src/tools/rustfmt/legacy-rustfmt.toml create mode 100644 src/tools/rustfmt/src/cargo-fmt/test/message_format.rs create mode 100644 src/tools/rustfmt/src/cargo-fmt/test/mod.rs create mode 100644 src/tools/rustfmt/src/cargo-fmt/test/targets.rs create mode 100644 src/tools/rustfmt/src/formatting/generated.rs create mode 100644 src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/Cargo.toml create mode 100644 src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/Cargo.toml create mode 100644 src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/src/lib.rs create mode 100644 src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/Cargo.toml create mode 100644 src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/src/lib.rs create mode 100644 src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/src/main.rs create mode 100644 src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/e/Cargo.toml create mode 100644 src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/e/src/main.rs create mode 100644 src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/Cargo.toml create mode 100644 src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/Cargo.toml create mode 100644 src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/Cargo.toml create mode 100644 src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/Cargo.toml create mode 100644 src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/src/lib.rs create mode 100644 src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/src/lib.rs create mode 100644 src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/src/main.rs create mode 100644 src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/b/Cargo.toml create mode 100644 src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/b/src/main.rs create mode 100644 src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/c/Cargo.toml create mode 100644 src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/c/src/lib.rs create mode 100644 src/tools/rustfmt/tests/mod-resolver/issue-5063/foo.rs create mode 100644 src/tools/rustfmt/tests/mod-resolver/issue-5063/foo/bar/baz.rs create mode 100644 src/tools/rustfmt/tests/mod-resolver/issue-5063/main.rs create mode 100644 src/tools/rustfmt/tests/source/binop-separator-back/bitwise.rs create mode 100644 src/tools/rustfmt/tests/source/binop-separator-back/comp.rs create mode 100644 src/tools/rustfmt/tests/source/binop-separator-back/logic.rs create mode 100644 src/tools/rustfmt/tests/source/binop-separator-back/math.rs create mode 100644 src/tools/rustfmt/tests/source/binop-separator-back/patterns.rs create mode 100644 src/tools/rustfmt/tests/source/binop-separator-back/range.rs create mode 100644 src/tools/rustfmt/tests/source/configs/format_generated_files/false.rs create mode 100644 src/tools/rustfmt/tests/source/configs/format_generated_files/true.rs create mode 100644 src/tools/rustfmt/tests/source/configs/group_imports/One-merge_imports.rs create mode 100644 src/tools/rustfmt/tests/source/configs/group_imports/One-nested.rs create mode 100644 src/tools/rustfmt/tests/source/configs/group_imports/One-no_reorder.rs create mode 100644 src/tools/rustfmt/tests/source/configs/group_imports/One.rs create mode 100644 src/tools/rustfmt/tests/source/empty-item-single-line-false.rs create mode 100644 src/tools/rustfmt/tests/source/hex_literal_lower.rs create mode 100644 src/tools/rustfmt/tests/source/hex_literal_upper.rs create mode 100644 src/tools/rustfmt/tests/source/imports_granularity_one.rs create mode 100644 src/tools/rustfmt/tests/source/issue-3158.rs create mode 100644 src/tools/rustfmt/tests/source/issue-4530.rs create mode 100644 src/tools/rustfmt/tests/source/issue-4615/minimum_example.rs create mode 100644 src/tools/rustfmt/tests/source/issue-4816/lib.rs create mode 100644 src/tools/rustfmt/tests/source/issue-4926/deeply_nested_struct.rs create mode 100644 src/tools/rustfmt/tests/source/issue-4926/deeply_nested_struct_with_long_field_names.rs create mode 100644 src/tools/rustfmt/tests/source/issue-4926/deeply_nested_struct_with_many_fields.rs create mode 100644 src/tools/rustfmt/tests/source/issue-4926/enum_struct_field.rs create mode 100644 src/tools/rustfmt/tests/source/issue-4926/minimum_example.rs create mode 100644 src/tools/rustfmt/tests/source/issue-4926/struct_with_long_field_names.rs create mode 100644 src/tools/rustfmt/tests/source/issue-4926/struct_with_many_fields.rs create mode 100644 src/tools/rustfmt/tests/source/issue-4984/minimum_example.rs create mode 100644 src/tools/rustfmt/tests/source/issue-4984/multi_line_derive.rs create mode 100644 src/tools/rustfmt/tests/source/issue-4984/multiple_comments_within.rs create mode 100644 src/tools/rustfmt/tests/source/issue-5011.rs create mode 100644 src/tools/rustfmt/tests/source/issue_4032.rs create mode 100644 src/tools/rustfmt/tests/source/issue_4257.rs create mode 100644 src/tools/rustfmt/tests/source/issue_4322.rs create mode 100644 src/tools/rustfmt/tests/source/issue_4579.rs create mode 100644 src/tools/rustfmt/tests/source/issue_4911.rs create mode 100644 src/tools/rustfmt/tests/source/issue_4943.rs create mode 100644 src/tools/rustfmt/tests/source/issue_4954.rs create mode 100644 src/tools/rustfmt/tests/source/issue_4963.rs create mode 100644 src/tools/rustfmt/tests/target/binop-separator-back/bitwise.rs create mode 100644 src/tools/rustfmt/tests/target/binop-separator-back/comp.rs create mode 100644 src/tools/rustfmt/tests/target/binop-separator-back/logic.rs create mode 100644 src/tools/rustfmt/tests/target/binop-separator-back/math.rs create mode 100644 src/tools/rustfmt/tests/target/binop-separator-back/patterns.rs create mode 100644 src/tools/rustfmt/tests/target/binop-separator-back/range.rs create mode 100644 src/tools/rustfmt/tests/target/configs/format_generated_files/false.rs create mode 100644 src/tools/rustfmt/tests/target/configs/format_generated_files/true.rs create mode 100644 src/tools/rustfmt/tests/target/configs/group_imports/One-merge_imports.rs create mode 100644 src/tools/rustfmt/tests/target/configs/group_imports/One-nested.rs create mode 100644 src/tools/rustfmt/tests/target/configs/group_imports/One-no_reorder.rs create mode 100644 src/tools/rustfmt/tests/target/configs/group_imports/One.rs create mode 100644 src/tools/rustfmt/tests/target/empty-item-single-line-false.rs create mode 100644 src/tools/rustfmt/tests/target/hex_literal_lower.rs create mode 100644 src/tools/rustfmt/tests/target/hex_literal_preserve.rs create mode 100644 src/tools/rustfmt/tests/target/hex_literal_upper.rs create mode 100644 src/tools/rustfmt/tests/target/imports_granularity_one.rs create mode 100644 src/tools/rustfmt/tests/target/issue-3158.rs create mode 100644 src/tools/rustfmt/tests/target/issue-4530.rs create mode 100644 src/tools/rustfmt/tests/target/issue-4615/minimum_example.rs create mode 100644 src/tools/rustfmt/tests/target/issue-4816/lib.rs create mode 100644 src/tools/rustfmt/tests/target/issue-4908-2.rs create mode 100644 src/tools/rustfmt/tests/target/issue-4908.rs create mode 100644 src/tools/rustfmt/tests/target/issue-4926/deeply_nested_struct.rs create mode 100644 src/tools/rustfmt/tests/target/issue-4926/deeply_nested_struct_with_long_field_names.rs create mode 100644 src/tools/rustfmt/tests/target/issue-4926/deeply_nested_struct_with_many_fields.rs create mode 100644 src/tools/rustfmt/tests/target/issue-4926/enum_struct_field.rs create mode 100644 src/tools/rustfmt/tests/target/issue-4926/minimum_example.rs create mode 100644 src/tools/rustfmt/tests/target/issue-4926/struct_with_long_field_names.rs create mode 100644 src/tools/rustfmt/tests/target/issue-4926/struct_with_many_fields.rs create mode 100644 src/tools/rustfmt/tests/target/issue-4984/minimum_example.rs create mode 100644 src/tools/rustfmt/tests/target/issue-4984/multi_line_derive.rs create mode 100644 src/tools/rustfmt/tests/target/issue-4984/multiple_comments_within.rs create mode 100644 src/tools/rustfmt/tests/target/issue-4984/should_not_change.rs create mode 100644 src/tools/rustfmt/tests/target/issue-5005/minimum_example.rs create mode 100644 src/tools/rustfmt/tests/target/issue-5009/1_minimum_example.rs create mode 100644 src/tools/rustfmt/tests/target/issue-5009/2_many_in_connectors_in_pattern.rs create mode 100644 src/tools/rustfmt/tests/target/issue-5009/3_nested_for_loop_with_connector_in_pattern.rs create mode 100644 src/tools/rustfmt/tests/target/issue-5009/4_nested_for_loop_with_if_elseif_else.rs create mode 100644 src/tools/rustfmt/tests/target/issue-5009/5_nested_for_loop_with_connector_in_if_elseif_else.rs create mode 100644 src/tools/rustfmt/tests/target/issue-5009/6_deeply_nested_for_loop_with_connector_in_pattern.rs create mode 100644 src/tools/rustfmt/tests/target/issue-5011.rs create mode 100644 src/tools/rustfmt/tests/target/issue-5012/trailing_comma_always.rs create mode 100644 src/tools/rustfmt/tests/target/issue-5012/trailing_comma_never.rs create mode 100644 src/tools/rustfmt/tests/target/issue-5033/minimum_example.rs create mode 100644 src/tools/rustfmt/tests/target/issue-5033/nested_modules.rs create mode 100644 src/tools/rustfmt/tests/target/issue_4031.rs create mode 100644 src/tools/rustfmt/tests/target/issue_4032.rs create mode 100644 src/tools/rustfmt/tests/target/issue_4110.rs create mode 100644 src/tools/rustfmt/tests/target/issue_4257.rs create mode 100644 src/tools/rustfmt/tests/target/issue_4322.rs create mode 100644 src/tools/rustfmt/tests/target/issue_4579.rs create mode 100644 src/tools/rustfmt/tests/target/issue_4850.rs create mode 100644 src/tools/rustfmt/tests/target/issue_4911.rs create mode 100644 src/tools/rustfmt/tests/target/issue_4936.rs create mode 100644 src/tools/rustfmt/tests/target/issue_4943.rs create mode 100644 src/tools/rustfmt/tests/target/issue_4954.rs create mode 100644 src/tools/rustfmt/tests/target/issue_4963.rs create mode 100644 src/tools/rustfmt/triagebot.toml rename vendor/{addr2line => addr2line-0.16.0}/.cargo-checksum.json (100%) rename vendor/{addr2line => addr2line-0.16.0}/CHANGELOG.md (100%) rename vendor/{addr2line => addr2line-0.16.0}/Cargo.lock (100%) rename vendor/{addr2line => addr2line-0.16.0}/Cargo.toml (100%) rename vendor/{addr2line => addr2line-0.16.0}/LICENSE-APACHE (100%) rename vendor/{addr2line => addr2line-0.16.0}/LICENSE-MIT (100%) rename vendor/{addr2line => addr2line-0.16.0}/README.md (100%) rename vendor/{addr2line => addr2line-0.16.0}/bench.plot.r (100%) rename vendor/{addr2line => addr2line-0.16.0}/benchmark.sh (100%) rename vendor/{addr2line => addr2line-0.16.0}/coverage (100%) rename vendor/{addr2line => addr2line-0.16.0}/examples/addr2line.rs (100%) rename vendor/{addr2line => addr2line-0.16.0}/rustfmt.toml (100%) rename vendor/{addr2line => addr2line-0.16.0}/src/function.rs (100%) rename vendor/{addr2line => addr2line-0.16.0}/src/lazy.rs (100%) rename vendor/{addr2line => addr2line-0.16.0}/src/lib.rs (100%) rename vendor/{addr2line => addr2line-0.16.0}/tests/correctness.rs (100%) rename vendor/{addr2line => addr2line-0.16.0}/tests/output_equivalence.rs (100%) rename vendor/{addr2line => addr2line-0.16.0}/tests/parse.rs (100%) create mode 100644 vendor/anyhow/rust-toolchain.toml create mode 100644 vendor/camino/.cargo-checksum.json create mode 100644 vendor/camino/CHANGELOG.md create mode 100644 vendor/camino/CODE_OF_CONDUCT.md create mode 100644 vendor/camino/Cargo.lock create mode 100644 vendor/camino/Cargo.toml rename vendor/{gimli => camino}/LICENSE-APACHE (100%) rename vendor/{itertools-0.8.2 => camino}/LICENSE-MIT (98%) create mode 100644 vendor/camino/README.md create mode 100644 vendor/camino/build.rs create mode 100644 vendor/camino/clippy.toml create mode 100644 vendor/camino/examples/serde.rs create mode 100644 vendor/camino/examples/structopt.rs create mode 100644 vendor/camino/rustfmt.toml create mode 100644 vendor/camino/src/lib.rs create mode 100644 vendor/camino/src/serde_impls.rs create mode 100644 vendor/camino/src/tests.rs create mode 100644 vendor/camino/tests/integration_tests.rs create mode 100644 vendor/cargo-platform/.cargo-checksum.json create mode 100644 vendor/cargo-platform/Cargo.lock create mode 100644 vendor/cargo-platform/Cargo.toml create mode 100644 vendor/cargo-platform/LICENSE-APACHE create mode 100644 vendor/cargo-platform/LICENSE-MIT create mode 100644 vendor/cargo-platform/examples/matches.rs create mode 100644 vendor/cargo-platform/src/cfg.rs create mode 100644 vendor/cargo-platform/src/error.rs create mode 100644 vendor/cargo-platform/src/lib.rs create mode 100644 vendor/cargo-platform/tests/test_cfg.rs create mode 100644 vendor/cargo_metadata/.cargo-checksum.json create mode 100644 vendor/cargo_metadata/Cargo.toml create mode 100644 vendor/cargo_metadata/LICENSE-MIT create mode 100644 vendor/cargo_metadata/README.md create mode 100644 vendor/cargo_metadata/src/dependency.rs create mode 100644 vendor/cargo_metadata/src/diagnostic.rs create mode 100644 vendor/cargo_metadata/src/errors.rs create mode 100644 vendor/cargo_metadata/src/lib.rs create mode 100644 vendor/cargo_metadata/src/messages.rs create mode 100644 vendor/cargo_metadata/tests/selftest.rs create mode 100644 vendor/cargo_metadata/tests/test_samples.rs delete mode 100644 vendor/dlmalloc/src/macos.rs rename vendor/dlmalloc/src/{linux.rs => unix.rs} (56%) create mode 100644 vendor/env_logger-0.8.4/.cargo-checksum.json create mode 100644 vendor/env_logger-0.8.4/CHANGELOG.md create mode 100644 vendor/env_logger-0.8.4/Cargo.toml rename vendor/{itertools-0.8.2 => env_logger-0.8.4}/LICENSE-APACHE (100%) create mode 100644 vendor/env_logger-0.8.4/LICENSE-MIT create mode 100644 vendor/env_logger-0.8.4/README.md create mode 100644 vendor/env_logger-0.8.4/src/filter/mod.rs create mode 100644 vendor/env_logger-0.8.4/src/filter/regex.rs create mode 100644 vendor/env_logger-0.8.4/src/filter/string.rs create mode 100644 vendor/env_logger-0.8.4/src/fmt/humantime/extern_impl.rs create mode 100644 vendor/env_logger-0.8.4/src/fmt/humantime/mod.rs create mode 100644 vendor/env_logger-0.8.4/src/fmt/humantime/shim_impl.rs create mode 100644 vendor/env_logger-0.8.4/src/fmt/mod.rs create mode 100644 vendor/env_logger-0.8.4/src/fmt/writer/atty.rs create mode 100644 vendor/env_logger-0.8.4/src/fmt/writer/mod.rs create mode 100644 vendor/env_logger-0.8.4/src/fmt/writer/termcolor/extern_impl.rs create mode 100644 vendor/env_logger-0.8.4/src/fmt/writer/termcolor/mod.rs create mode 100644 vendor/env_logger-0.8.4/src/fmt/writer/termcolor/shim_impl.rs create mode 100644 vendor/env_logger-0.8.4/src/lib.rs create mode 100644 vendor/env_logger-0.8.4/tests/init-twice-retains-filter.rs create mode 100644 vendor/env_logger-0.8.4/tests/log-in-log.rs create mode 100644 vendor/env_logger-0.8.4/tests/log_tls_dtors.rs create mode 100644 vendor/env_logger-0.8.4/tests/regexp_filter.rs rename vendor/{gimli => gimli-0.25.0}/.cargo-checksum.json (100%) rename vendor/{gimli => gimli-0.25.0}/CHANGELOG.md (100%) rename vendor/{gimli => gimli-0.25.0}/CONTRIBUTING.md (100%) rename vendor/{gimli => gimli-0.25.0}/Cargo.lock (100%) rename vendor/{gimli => gimli-0.25.0}/Cargo.toml (100%) rename vendor/{object => gimli-0.25.0}/LICENSE-APACHE (100%) rename vendor/{gimli => gimli-0.25.0}/LICENSE-MIT (100%) rename vendor/{gimli => gimli-0.25.0}/README.md (100%) rename vendor/{gimli => gimli-0.25.0}/benches/bench.rs (100%) rename vendor/{gimli => gimli-0.25.0}/examples/dwarf-validate.rs (100%) rename vendor/{gimli => gimli-0.25.0}/examples/dwarfdump.rs (100%) rename vendor/{gimli => gimli-0.25.0}/examples/simple.rs (100%) rename vendor/{gimli => gimli-0.25.0}/examples/simple_line.rs (100%) rename vendor/{gimli => gimli-0.25.0}/fixtures/self/README.md (100%) rename vendor/{gimli => gimli-0.25.0}/fixtures/self/debug_abbrev (100%) rename vendor/{gimli => gimli-0.25.0}/fixtures/self/debug_aranges (100%) rename vendor/{gimli => gimli-0.25.0}/fixtures/self/debug_info (100%) rename vendor/{gimli => gimli-0.25.0}/fixtures/self/debug_inlined (100%) rename vendor/{gimli => gimli-0.25.0}/fixtures/self/debug_line (100%) rename vendor/{gimli => gimli-0.25.0}/fixtures/self/debug_loc (100%) rename vendor/{gimli => gimli-0.25.0}/fixtures/self/debug_pubnames (100%) rename vendor/{gimli => gimli-0.25.0}/fixtures/self/debug_pubtypes (100%) rename vendor/{gimli => gimli-0.25.0}/fixtures/self/debug_ranges (100%) rename vendor/{gimli => gimli-0.25.0}/fixtures/self/debug_str (100%) rename vendor/{gimli => gimli-0.25.0}/fixtures/self/eh_frame (100%) rename vendor/{gimli => gimli-0.25.0}/fixtures/self/eh_frame_hdr (100%) create mode 100644 vendor/gimli-0.25.0/rustfmt.toml rename vendor/{gimli => gimli-0.25.0}/src/arch.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/common.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/constants.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/endianity.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/leb128.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/lib.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/read/abbrev.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/read/addr.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/read/aranges.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/read/cfi.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/read/dwarf.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/read/endian_reader.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/read/endian_slice.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/read/line.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/read/lists.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/read/loclists.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/read/lookup.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/read/mod.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/read/op.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/read/pubnames.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/read/pubtypes.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/read/reader.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/read/rnglists.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/read/str.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/read/unit.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/read/value.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/test_util.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/write/abbrev.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/write/cfi.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/write/dwarf.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/write/endian_vec.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/write/line.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/write/loc.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/write/mod.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/write/op.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/write/range.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/write/section.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/write/str.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/write/unit.rs (100%) rename vendor/{gimli => gimli-0.25.0}/src/write/writer.rs (100%) rename vendor/{gimli => gimli-0.25.0}/tests/convert_self.rs (100%) rename vendor/{gimli => gimli-0.25.0}/tests/parse_self.rs (100%) create mode 100644 vendor/humantime/.cargo-checksum.json create mode 100644 vendor/humantime/Cargo.toml create mode 100644 vendor/humantime/LICENSE-APACHE create mode 100644 vendor/humantime/LICENSE-MIT create mode 100644 vendor/humantime/README.md create mode 100644 vendor/humantime/benches/datetime_format.rs create mode 100644 vendor/humantime/benches/datetime_parse.rs create mode 100644 vendor/humantime/bulk.yaml create mode 100644 vendor/humantime/src/date.rs create mode 100644 vendor/humantime/src/duration.rs create mode 100644 vendor/humantime/src/lib.rs create mode 100644 vendor/humantime/src/wrapper.rs create mode 100644 vendor/humantime/vagga.yaml create mode 100644 vendor/indoc/.cargo-checksum.json create mode 100644 vendor/indoc/Cargo.toml create mode 100644 vendor/indoc/LICENSE-APACHE create mode 100644 vendor/indoc/LICENSE-MIT create mode 100644 vendor/indoc/README.md create mode 100644 vendor/indoc/src/error.rs create mode 100644 vendor/indoc/src/expr.rs create mode 100644 vendor/indoc/src/lib.rs create mode 100644 vendor/indoc/tests/compiletest.rs create mode 100644 vendor/indoc/tests/test_formatdoc.rs create mode 100644 vendor/indoc/tests/test_indoc.rs create mode 100644 vendor/indoc/tests/test_unindent.rs create mode 100644 vendor/indoc/tests/test_writedoc.rs create mode 100644 vendor/indoc/tests/ui/no-arguments.rs create mode 100644 vendor/indoc/tests/ui/no-arguments.stderr create mode 100644 vendor/indoc/tests/ui/non-lit.rs create mode 100644 vendor/indoc/tests/ui/non-lit.stderr create mode 100644 vendor/indoc/tests/ui/non-string.rs create mode 100644 vendor/indoc/tests/ui/non-string.stderr create mode 100644 vendor/indoc/tests/ui/printdoc-binary.rs create mode 100644 vendor/indoc/tests/ui/printdoc-binary.stderr create mode 100644 vendor/indoc/tests/ui/printdoc-extra-arg.rs create mode 100644 vendor/indoc/tests/ui/printdoc-extra-arg.stderr create mode 100644 vendor/indoc/tests/ui/printdoc-no-arg.rs create mode 100644 vendor/indoc/tests/ui/printdoc-no-arg.stderr create mode 100644 vendor/indoc/tests/ui/printdoc-no-display.rs create mode 100644 vendor/indoc/tests/ui/printdoc-no-display.stderr create mode 100644 vendor/indoc/tests/ui/printdoc-no-named-arg.rs create mode 100644 vendor/indoc/tests/ui/printdoc-no-named-arg.stderr create mode 100644 vendor/indoc/tests/ui/three-arguments.rs create mode 100644 vendor/indoc/tests/ui/three-arguments.stderr create mode 100644 vendor/indoc/tests/ui/two-arguments.rs create mode 100644 vendor/indoc/tests/ui/two-arguments.stderr create mode 100644 vendor/instant/CHANGELOGS.md delete mode 100644 vendor/itertools-0.8.2/.cargo-checksum.json delete mode 100644 vendor/itertools-0.8.2/Cargo.lock delete mode 100644 vendor/itertools-0.8.2/Cargo.toml delete mode 100644 vendor/itertools-0.8.2/README.rst delete mode 100644 vendor/itertools-0.8.2/benches/bench1.rs delete mode 100644 vendor/itertools-0.8.2/benches/combinations_with_replacement.rs delete mode 100644 vendor/itertools-0.8.2/benches/extra/mod.rs delete mode 100644 vendor/itertools-0.8.2/benches/extra/zipslices.rs delete mode 100644 vendor/itertools-0.8.2/benches/fold_specialization.rs delete mode 100644 vendor/itertools-0.8.2/benches/tree_fold1.rs delete mode 100644 vendor/itertools-0.8.2/benches/tuple_combinations.rs delete mode 100644 vendor/itertools-0.8.2/benches/tuples.rs delete mode 100644 vendor/itertools-0.8.2/examples/iris.data delete mode 100644 vendor/itertools-0.8.2/examples/iris.rs delete mode 100644 vendor/itertools-0.8.2/src/adaptors/mod.rs delete mode 100644 vendor/itertools-0.8.2/src/adaptors/multi_product.rs delete mode 100644 vendor/itertools-0.8.2/src/combinations.rs delete mode 100644 vendor/itertools-0.8.2/src/combinations_with_replacement.rs delete mode 100644 vendor/itertools-0.8.2/src/concat_impl.rs delete mode 100644 vendor/itertools-0.8.2/src/cons_tuples_impl.rs delete mode 100644 vendor/itertools-0.8.2/src/diff.rs delete mode 100644 vendor/itertools-0.8.2/src/either_or_both.rs delete mode 100644 vendor/itertools-0.8.2/src/exactly_one_err.rs delete mode 100644 vendor/itertools-0.8.2/src/format.rs delete mode 100644 vendor/itertools-0.8.2/src/free.rs delete mode 100644 vendor/itertools-0.8.2/src/group_map.rs delete mode 100644 vendor/itertools-0.8.2/src/groupbylazy.rs delete mode 100644 vendor/itertools-0.8.2/src/impl_macros.rs delete mode 100644 vendor/itertools-0.8.2/src/intersperse.rs delete mode 100644 vendor/itertools-0.8.2/src/kmerge_impl.rs delete mode 100644 vendor/itertools-0.8.2/src/lazy_buffer.rs delete mode 100644 vendor/itertools-0.8.2/src/lib.rs delete mode 100644 vendor/itertools-0.8.2/src/merge_join.rs delete mode 100644 vendor/itertools-0.8.2/src/minmax.rs delete mode 100644 vendor/itertools-0.8.2/src/multipeek_impl.rs delete mode 100644 vendor/itertools-0.8.2/src/pad_tail.rs delete mode 100644 vendor/itertools-0.8.2/src/peeking_take_while.rs delete mode 100644 vendor/itertools-0.8.2/src/permutations.rs delete mode 100644 vendor/itertools-0.8.2/src/process_results_impl.rs delete mode 100644 vendor/itertools-0.8.2/src/put_back_n_impl.rs delete mode 100644 vendor/itertools-0.8.2/src/rciter_impl.rs delete mode 100644 vendor/itertools-0.8.2/src/repeatn.rs delete mode 100644 vendor/itertools-0.8.2/src/size_hint.rs delete mode 100644 vendor/itertools-0.8.2/src/sources.rs delete mode 100644 vendor/itertools-0.8.2/src/tee.rs delete mode 100644 vendor/itertools-0.8.2/src/tuple_impl.rs delete mode 100644 vendor/itertools-0.8.2/src/unique_impl.rs delete mode 100644 vendor/itertools-0.8.2/src/with_position.rs delete mode 100644 vendor/itertools-0.8.2/src/zip_eq_impl.rs delete mode 100644 vendor/itertools-0.8.2/src/zip_longest.rs delete mode 100644 vendor/itertools-0.8.2/src/ziptuple.rs delete mode 100644 vendor/itertools-0.8.2/tests/adaptors_no_collect.rs delete mode 100644 vendor/itertools-0.8.2/tests/fold_specialization.rs delete mode 100644 vendor/itertools-0.8.2/tests/merge_join.rs delete mode 100644 vendor/itertools-0.8.2/tests/peeking_take_while.rs delete mode 100644 vendor/itertools-0.8.2/tests/quick.rs delete mode 100644 vendor/itertools-0.8.2/tests/test_core.rs delete mode 100644 vendor/itertools-0.8.2/tests/test_std.rs delete mode 100644 vendor/itertools-0.8.2/tests/tuples.rs delete mode 100644 vendor/itertools-0.8.2/tests/zip.rs create mode 100644 vendor/libc/src/solid/aarch64.rs create mode 100644 vendor/libc/src/solid/arm.rs create mode 100644 vendor/libc/src/solid/mod.rs mode change 100755 => 100644 vendor/libc/src/vxworks/mod.rs delete mode 100644 vendor/libc/src/windows/msvc/x86_64.rs rename vendor/{object => object-0.26.2}/.cargo-checksum.json (100%) rename vendor/{object => object-0.26.2}/CHANGELOG.md (100%) rename vendor/{object => object-0.26.2}/Cargo.lock (100%) rename vendor/{object => object-0.26.2}/Cargo.toml (100%) create mode 100644 vendor/object-0.26.2/LICENSE-APACHE rename vendor/{object => object-0.26.2}/LICENSE-MIT (100%) rename vendor/{object => object-0.26.2}/README.md (100%) rename vendor/{object => object-0.26.2}/clippy.toml (100%) rename vendor/{object => object-0.26.2}/examples/ar.rs (100%) rename vendor/{object => object-0.26.2}/examples/dyldcachedump.rs (100%) rename vendor/{object => object-0.26.2}/examples/nm.rs (100%) rename vendor/{object => object-0.26.2}/examples/objcopy.rs (100%) rename vendor/{object => object-0.26.2}/examples/objdump.rs (100%) rename vendor/{object => object-0.26.2}/examples/objectmap.rs (100%) rename vendor/{object => object-0.26.2}/examples/readobj.rs (100%) rename vendor/{object => object-0.26.2}/src/archive.rs (100%) rename vendor/{object => object-0.26.2}/src/common.rs (100%) rename vendor/{object => object-0.26.2}/src/elf.rs (100%) rename vendor/{object => object-0.26.2}/src/endian.rs (100%) rename vendor/{object => object-0.26.2}/src/lib.rs (100%) rename vendor/{object => object-0.26.2}/src/macho.rs (100%) rename vendor/{object => object-0.26.2}/src/pe.rs (100%) rename vendor/{object => object-0.26.2}/src/pod.rs (100%) rename vendor/{object => object-0.26.2}/src/read/any.rs (100%) rename vendor/{object => object-0.26.2}/src/read/archive.rs (100%) rename vendor/{object => object-0.26.2}/src/read/coff/comdat.rs (100%) rename vendor/{object => object-0.26.2}/src/read/coff/file.rs (100%) rename vendor/{object => object-0.26.2}/src/read/coff/mod.rs (100%) rename vendor/{object => object-0.26.2}/src/read/coff/relocation.rs (100%) rename vendor/{object => object-0.26.2}/src/read/coff/section.rs (100%) rename vendor/{object => object-0.26.2}/src/read/coff/symbol.rs (100%) rename vendor/{object => object-0.26.2}/src/read/elf/comdat.rs (100%) rename vendor/{object => object-0.26.2}/src/read/elf/compression.rs (100%) rename vendor/{object => object-0.26.2}/src/read/elf/dynamic.rs (100%) rename vendor/{object => object-0.26.2}/src/read/elf/file.rs (100%) rename vendor/{object => object-0.26.2}/src/read/elf/hash.rs (100%) rename vendor/{object => object-0.26.2}/src/read/elf/mod.rs (100%) rename vendor/{object => object-0.26.2}/src/read/elf/note.rs (100%) rename vendor/{object => object-0.26.2}/src/read/elf/relocation.rs (100%) rename vendor/{object => object-0.26.2}/src/read/elf/section.rs (100%) rename vendor/{object => object-0.26.2}/src/read/elf/segment.rs (100%) rename vendor/{object => object-0.26.2}/src/read/elf/symbol.rs (100%) rename vendor/{object => object-0.26.2}/src/read/elf/version.rs (100%) rename vendor/{object => object-0.26.2}/src/read/macho/dyld_cache.rs (100%) rename vendor/{object => object-0.26.2}/src/read/macho/fat.rs (100%) rename vendor/{object => object-0.26.2}/src/read/macho/file.rs (100%) rename vendor/{object => object-0.26.2}/src/read/macho/load_command.rs (100%) rename vendor/{object => object-0.26.2}/src/read/macho/mod.rs (100%) rename vendor/{object => object-0.26.2}/src/read/macho/relocation.rs (100%) rename vendor/{object => object-0.26.2}/src/read/macho/section.rs (100%) rename vendor/{object => object-0.26.2}/src/read/macho/segment.rs (100%) rename vendor/{object => object-0.26.2}/src/read/macho/symbol.rs (100%) rename vendor/{object => object-0.26.2}/src/read/mod.rs (100%) rename vendor/{object => object-0.26.2}/src/read/pe/file.rs (100%) rename vendor/{object => object-0.26.2}/src/read/pe/mod.rs (100%) rename vendor/{object => object-0.26.2}/src/read/pe/section.rs (100%) rename vendor/{object => object-0.26.2}/src/read/read_cache.rs (100%) rename vendor/{object => object-0.26.2}/src/read/read_ref.rs (100%) rename vendor/{object => object-0.26.2}/src/read/traits.rs (100%) rename vendor/{object => object-0.26.2}/src/read/util.rs (100%) rename vendor/{object => object-0.26.2}/src/read/wasm.rs (100%) rename vendor/{object => object-0.26.2}/src/write/coff.rs (100%) rename vendor/{object => object-0.26.2}/src/write/elf.rs (100%) rename vendor/{object => object-0.26.2}/src/write/macho.rs (100%) rename vendor/{object => object-0.26.2}/src/write/mod.rs (100%) rename vendor/{object => object-0.26.2}/src/write/string.rs (100%) rename vendor/{object => object-0.26.2}/src/write/util.rs (100%) rename vendor/{object => object-0.26.2}/tests/integration.rs (100%) rename vendor/{object => object-0.26.2}/tests/parse_self.rs (100%) rename vendor/{object => object-0.26.2}/tests/round_trip/bss.rs (100%) rename vendor/{object => object-0.26.2}/tests/round_trip/comdat.rs (100%) rename vendor/{object => object-0.26.2}/tests/round_trip/common.rs (100%) rename vendor/{object => object-0.26.2}/tests/round_trip/elf.rs (100%) rename vendor/{object => object-0.26.2}/tests/round_trip/macho.rs (100%) rename vendor/{object => object-0.26.2}/tests/round_trip/mod.rs (100%) rename vendor/{object => object-0.26.2}/tests/round_trip/tls.rs (100%) create mode 100644 vendor/quote/benches/bench.rs create mode 100644 vendor/quote/tests/ui/does-not-have-iter-interpolated-dup.stderr create mode 100644 vendor/quote/tests/ui/does-not-have-iter-interpolated.stderr create mode 100644 vendor/quote/tests/ui/does-not-have-iter-separated.stderr create mode 100644 vendor/quote/tests/ui/does-not-have-iter.stderr create mode 100644 vendor/quote/tests/ui/not-quotable.stderr create mode 100644 vendor/quote/tests/ui/not-repeatable.stderr create mode 100644 vendor/quote/tests/ui/wrong-type-span.stderr create mode 100644 vendor/semver/.cargo-checksum.json create mode 100644 vendor/semver/Cargo.toml create mode 100644 vendor/semver/LICENSE-APACHE create mode 100644 vendor/semver/LICENSE-MIT create mode 100644 vendor/semver/README.md create mode 100644 vendor/semver/benches/parse.rs create mode 100644 vendor/semver/build.rs create mode 100644 vendor/semver/src/backport.rs create mode 100644 vendor/semver/src/display.rs create mode 100644 vendor/semver/src/error.rs create mode 100644 vendor/semver/src/eval.rs create mode 100644 vendor/semver/src/identifier.rs create mode 100644 vendor/semver/src/impls.rs create mode 100644 vendor/semver/src/lib.rs create mode 100644 vendor/semver/src/parse.rs create mode 100644 vendor/semver/src/serde.rs create mode 100644 vendor/semver/tests/node/mod.rs create mode 100644 vendor/semver/tests/test_identifier.rs create mode 100644 vendor/semver/tests/test_version.rs create mode 100644 vendor/semver/tests/test_version_req.rs create mode 100644 vendor/semver/tests/util/mod.rs create mode 100644 vendor/sharded-slab/IMPLEMENTATION.md create mode 100644 vendor/tracing-subscriber/tests/layer_filters/downcast_raw.rs create mode 100644 vendor/unic-char-property/.cargo-checksum.json create mode 100644 vendor/unic-char-property/Cargo.toml create mode 100644 vendor/unic-char-property/src/lib.rs create mode 100644 vendor/unic-char-property/src/macros.rs create mode 100644 vendor/unic-char-property/src/pkg_info.rs create mode 100644 vendor/unic-char-property/src/property.rs create mode 100644 vendor/unic-char-property/src/range_types.rs create mode 100644 vendor/unic-char-property/src/tables.rs create mode 100644 vendor/unic-char-property/tests/bool_property_macro.rs create mode 100644 vendor/unic-char-property/tests/enum_property_macro.rs create mode 100644 vendor/unic-char-property/tests/tables/property_table.rsv create mode 100644 vendor/unic-char-property/tests/tables_tests.rs create mode 100644 vendor/unic-char-range/.cargo-checksum.json create mode 100644 vendor/unic-char-range/Cargo.toml create mode 100644 vendor/unic-char-range/benches/benchmarks.rs create mode 100644 vendor/unic-char-range/examples/macro_use_std_tests.rs create mode 100644 vendor/unic-char-range/src/iter.rs create mode 100644 vendor/unic-char-range/src/iter_fused.rs create mode 100644 vendor/unic-char-range/src/iter_trusted_len.rs create mode 100644 vendor/unic-char-range/src/lib.rs create mode 100644 vendor/unic-char-range/src/macros.rs create mode 100644 vendor/unic-char-range/src/par_iter.rs create mode 100644 vendor/unic-char-range/src/pkg_info.rs create mode 100644 vendor/unic-char-range/src/range.rs create mode 100644 vendor/unic-char-range/src/step.rs create mode 100644 vendor/unic-char-range/tests/iter_tests.rs create mode 100644 vendor/unic-common/.cargo-checksum.json create mode 100644 vendor/unic-common/Cargo.toml create mode 100644 vendor/unic-common/README.md create mode 100644 vendor/unic-common/src/lib.rs create mode 100644 vendor/unic-common/src/pkg_info.rs create mode 100644 vendor/unic-common/src/version.rs create mode 100644 vendor/unic-emoji-char/.cargo-checksum.json create mode 100644 vendor/unic-emoji-char/Cargo.toml create mode 100644 vendor/unic-emoji-char/src/emoji.rs create mode 100644 vendor/unic-emoji-char/src/emoji_component.rs create mode 100644 vendor/unic-emoji-char/src/emoji_modifier.rs create mode 100644 vendor/unic-emoji-char/src/emoji_modifier_base.rs create mode 100644 vendor/unic-emoji-char/src/emoji_presentation.rs create mode 100644 vendor/unic-emoji-char/src/emoji_version.rs create mode 100644 vendor/unic-emoji-char/src/lib.rs create mode 100644 vendor/unic-emoji-char/src/pkg_info.rs create mode 100644 vendor/unic-emoji-char/tables/emoji.rsv create mode 100644 vendor/unic-emoji-char/tables/emoji_component.rsv create mode 100644 vendor/unic-emoji-char/tables/emoji_modifier.rsv create mode 100644 vendor/unic-emoji-char/tables/emoji_modifier_base.rsv create mode 100644 vendor/unic-emoji-char/tables/emoji_presentation.rsv create mode 100644 vendor/unic-emoji-char/tables/emoji_version.rsv create mode 100644 vendor/unic-emoji-char/tests/emoji_version_tests.rs create mode 100644 vendor/unic-ucd-version/.cargo-checksum.json create mode 100644 vendor/unic-ucd-version/Cargo.toml create mode 100644 vendor/unic-ucd-version/src/lib.rs create mode 100644 vendor/unic-ucd-version/src/pkg_info.rs create mode 100644 vendor/unic-ucd-version/src/unicode_version.rs create mode 100644 vendor/unic-ucd-version/tables/unicode_version.rsv create mode 100644 vendor/unic-ucd-version/tests/basic_tests.rs create mode 100644 vendor/unindent/.cargo-checksum.json create mode 100644 vendor/unindent/Cargo.toml create mode 100644 vendor/unindent/LICENSE-APACHE create mode 100644 vendor/unindent/LICENSE-MIT create mode 100644 vendor/unindent/README.md create mode 100644 vendor/unindent/src/lib.rs diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2827a46ae6..223fd0065b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,13 +3,14 @@ Thank you for your interest in contributing to Rust! There are many ways to contribute and we appreciate all of them. +The best way to get started is by asking for help in the [#new +members](https://rust-lang.zulipchat.com/#narrow/stream/122652-new-members) +Zulip stream. We have lots of docs below of how to get started on your own, but +the Zulip stream is the best place to *ask* for help. + Documentation for contributing to Rust is located in the [Guide to Rustc Development](https://rustc-dev-guide.rust-lang.org/), commonly known as the [rustc-dev-guide]. Despite the name, this guide documents -not just how to develop rustc (the Rust compiler), but also how to contribute to any part -of the Rust project. - -To get started with contributing, please read the [Contributing to Rust] chapter of the guide. -That chapter explains how to get your development environment set up and how to get help. +not just how to develop rustc (the Rust compiler), but also how to contribute to the standard library and rustdoc. ## About the [rustc-dev-guide] diff --git a/Cargo.lock b/Cargo.lock index dce7745076..48d9fdb3d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -265,14 +265,23 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81a18687293a1546b67c246452202bbbf143d239cb43494cc163da14979082da" +[[package]] +name = "camino" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52d74260d9bf6944e2208aa46841b4b8f0d7ffc0849a06837b2f510337f86b2b" +dependencies = [ + "serde", +] + [[package]] name = "cargo" -version = "0.58.0" +version = "0.59.0" dependencies = [ "anyhow", "atty", "bytesize", - "cargo-platform", + "cargo-platform 0.1.2", "cargo-test-macro", "cargo-test-support", "cargo-util", @@ -374,6 +383,15 @@ dependencies = [ "serde", ] +[[package]] +name = "cargo-platform" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" +dependencies = [ + "serde", +] + [[package]] name = "cargo-test-macro" version = "0.1.0" @@ -421,23 +439,24 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.8.2" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "700b3731fd7d357223d0000f4dbf1808401b694609035c3c411fbc0cd375c426" +checksum = "d5a5f7b42f606b7f23674f6f4d877628350682bc40687d3fae65679a58d55345" dependencies = [ - "semver 0.9.0", + "semver 0.11.0", "serde", - "serde_derive", "serde_json", ] [[package]] name = "cargo_metadata" -version = "0.12.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5a5f7b42f606b7f23674f6f4d877628350682bc40687d3fae65679a58d55345" +checksum = "c297bd3135f558552f99a0daa180876984ea2c4ffa7470314540dff8c654109a" dependencies = [ - "semver 0.11.0", + "camino", + "cargo-platform 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 1.0.3", "serde", "serde_json", ] @@ -555,9 +574,9 @@ dependencies = [ [[package]] name = "clippy" -version = "0.1.57" +version = "0.1.58" dependencies = [ - "cargo_metadata 0.12.0", + "cargo_metadata 0.14.0", "clippy_lints", "clippy_utils", "compiletest_rs", @@ -569,7 +588,7 @@ dependencies = [ "regex", "rustc-workspace-hack", "rustc_tools_util 0.2.0", - "semver 0.11.0", + "semver 1.0.3", "serde", "syn", "tempfile", @@ -582,6 +601,7 @@ version = "0.0.1" dependencies = [ "bytecount", "clap", + "indoc", "itertools 0.10.1", "opener", "regex", @@ -591,9 +611,9 @@ dependencies = [ [[package]] name = "clippy_lints" -version = "0.1.57" +version = "0.1.58" dependencies = [ - "cargo_metadata 0.12.0", + "cargo_metadata 0.14.0", "clippy_utils", "if_chain", "itertools 0.10.1", @@ -601,7 +621,7 @@ dependencies = [ "quine-mc_cluskey", "regex-syntax", "rustc-semver", - "semver 0.11.0", + "semver 1.0.3", "serde", "serde_json", "toml", @@ -612,7 +632,7 @@ dependencies = [ [[package]] name = "clippy_utils" -version = "0.1.57" +version = "0.1.58" dependencies = [ "if_chain", "rustc-semver", @@ -658,9 +678,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.49" +version = "0.1.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20b1438ef42c655665a8ab2c1c6d605a305f031d38d9be689ddfef41a20f3aa2" +checksum = "2467ff455350a4df7d02f1ed1449d0279605a763de5d586dcf6aa7d732508bcb" dependencies = [ "cc", "rustc-std-workspace-core", @@ -690,9 +710,9 @@ dependencies = [ [[package]] name = "compiletest_rs" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64698e5e2435db061a85e6320af12c30c5fd88eb84b35d2c1e03ce4f143255ca" +checksum = "29843cb8d351febf86557681d049d1e1652b81a086a190fa1173c07fd17fbf83" dependencies = [ "diff", "filetime", @@ -868,9 +888,9 @@ dependencies = [ [[package]] name = "curl" -version = "0.4.39" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaa3b8db7f3341ddef15786d250106334d4a6c4b0ae4a46cd77082777d9849b9" +checksum = "1bc6d233563261f8db6ffb83bbaad5a73837a6e6b28868e926337ebbdece0be3" dependencies = [ "curl-sys", "libc", @@ -883,9 +903,9 @@ dependencies = [ [[package]] name = "curl-sys" -version = "0.4.49+curl-7.79.1" +version = "0.4.51+curl-7.80.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0f44960aea24a786a46907b8824ebc0e66ca06bf4e4978408c7499620343483" +checksum = "d130987e6a6a34fe0889e1083022fa48cd90e6709a84be3fb8dd95801de5af20" dependencies = [ "cc", "libc", @@ -1008,9 +1028,9 @@ dependencies = [ [[package]] name = "dlmalloc" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "332570860c2edf2d57914987bf9e24835425f75825086b6ba7d1e6a3e4f1f254" +checksum = "a6fe28e0bf9357092740362502f5cc7955d8dc125ebda71dec72336c2e15c62e" dependencies = [ "compiler_builtins", "libc", @@ -1069,9 +1089,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.6.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" +checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" dependencies = [ "atty", "humantime 1.3.0", @@ -1082,12 +1102,12 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.7.1" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" +checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" dependencies = [ "atty", - "humantime 1.3.0", + "humantime 2.0.1", "log", "regex", "termcolor", @@ -1665,6 +1685,15 @@ dependencies = [ "serde", ] +[[package]] +name = "indoc" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a75aeaaef0ce18b58056d306c27b07436fbb34b8816c53094b76dd81803136" +dependencies = [ + "unindent", +] + [[package]] name = "installer" version = "0.0.0" @@ -1688,15 +1717,6 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b141fdc7836c525d4d594027d318c84161ca17aaf8113ab1f81ab93ae897485" -[[package]] -name = "itertools" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.9.0" @@ -1880,9 +1900,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.103" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" +checksum = "a60553f9a9e039a333b4e9b20573b9e9b9c0bb3a11e201ccc48ef4283456d673" dependencies = [ "rustc-std-workspace-core", ] @@ -2143,6 +2163,20 @@ dependencies = [ "smallvec", ] +[[package]] +name = "measureme" +version = "10.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd460fad6e55ca82fa0cd9dab0d315294188fd9ec6efbf4105e5635d4872ef9c" +dependencies = [ + "log", + "memmap2", + "parking_lot", + "perf-event-open-sys", + "rustc-hash", + "smallvec", +] + [[package]] name = "memchr" version = "2.4.1" @@ -2247,7 +2281,7 @@ dependencies = [ "hex 0.4.2", "libc", "log", - "measureme", + "measureme 9.1.2", "rand 0.8.4", "rustc-workspace-hack", "rustc_version 0.4.0", @@ -2728,9 +2762,9 @@ checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" [[package]] name = "proc-macro2" -version = "1.0.24" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +checksum = "edc3358ebc67bc8b7fa0c007f945b0b18226f78437d61bec735a9eb96b61ee70" dependencies = [ "unicode-xid", ] @@ -3235,7 +3269,7 @@ dependencies = [ "indexmap", "jobserver", "libc", - "measureme", + "measureme 9.1.2", "memmap2", "parking_lot", "rustc-ap-rustc_graphviz", @@ -3568,6 +3602,7 @@ dependencies = [ "rustc_errors", "rustc_hir", "rustc_index", + "rustc_query_system", "rustc_session", "rustc_span", "rustc_target", @@ -3673,7 +3708,7 @@ dependencies = [ "bitflags", "cstr", "libc", - "measureme", + "measureme 10.0.0", "rustc-demangle", "rustc_arena", "rustc_ast", @@ -3766,7 +3801,7 @@ dependencies = [ "indexmap", "jobserver", "libc", - "measureme", + "measureme 10.0.0", "memmap2", "parking_lot", "rustc-hash", @@ -4005,6 +4040,7 @@ name = "rustc_lexer" version = "0.1.0" dependencies = [ "expect-test", + "unic-emoji-char", "unicode-xid", ] @@ -4102,6 +4138,7 @@ dependencies = [ "polonius-engine", "rand 0.8.4", "rand_xoshiro 0.6.0", + "rustc-rayon", "rustc-rayon-core", "rustc_apfloat", "rustc_arena", @@ -4291,7 +4328,7 @@ dependencies = [ name = "rustc_query_impl" version = "0.0.0" dependencies = [ - "measureme", + "measureme 10.0.0", "rustc-rayon-core", "rustc_ast", "rustc_data_structures", @@ -4304,7 +4341,6 @@ dependencies = [ "rustc_serialize", "rustc_session", "rustc_span", - "tracing", ] [[package]] @@ -4347,6 +4383,7 @@ dependencies = [ "rustc_index", "rustc_metadata", "rustc_middle", + "rustc_query_system", "rustc_session", "rustc_span", "smallvec", @@ -4580,8 +4617,8 @@ dependencies = [ "itertools 0.9.0", "minifier", "pulldown-cmark 0.8.0", + "rayon", "regex", - "rustc-rayon", "rustdoc-json-types", "serde", "serde_json", @@ -4648,19 +4685,19 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.4.37" +version = "1.4.38" dependencies = [ "annotate-snippets", "anyhow", "bytecount", - "cargo_metadata 0.8.2", + "cargo_metadata 0.14.0", "derive-new", "diff", "dirs", - "env_logger 0.6.2", + "env_logger 0.8.4", "getopts", "ignore", - "itertools 0.8.2", + "itertools 0.9.0", "lazy_static", "log", "regex", @@ -4743,23 +4780,13 @@ dependencies = [ "libc", ] -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser 0.7.0", - "serde", -] - [[package]] name = "semver" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" dependencies = [ - "semver-parser 0.10.2", + "semver-parser", "serde", ] @@ -4772,12 +4799,6 @@ dependencies = [ "serde", ] -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - [[package]] name = "semver-parser" version = "0.10.2" @@ -5091,9 +5112,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.65" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3a1d708c221c5a612956ef9f75b37e454e88d1f7b899fbd3a18d4252012d663" +checksum = "d010a1623fbd906d51d650a9916aaefc05ffa0e4053ff7fe601167f3e715d194" dependencies = [ "proc-macro2", "quote", @@ -5490,6 +5511,47 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" +[[package]] +name = "unic-char-property" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221" +dependencies = [ + "unic-char-range", +] + +[[package]] +name = "unic-char-range" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc" + +[[package]] +name = "unic-common" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" + +[[package]] +name = "unic-emoji-char" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b07221e68897210270a38bde4babb655869637af0f69407f96053a34f76494d" +dependencies = [ + "unic-char-property", + "unic-char-range", + "unic-ucd-version", +] + +[[package]] +name = "unic-ucd-version" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4" +dependencies = [ + "unic-common", +] + [[package]] name = "unicase" version = "2.6.0" @@ -5578,6 +5640,12 @@ dependencies = [ "diff", ] +[[package]] +name = "unindent" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f14ee04d9415b52b3aeab06258a3f07093182b88ba0f9b8d203f211a7a7d41c7" + [[package]] name = "unstable-book-gen" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 8d6afd2b44..cae48d7951 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -77,6 +77,13 @@ overflow-checks = false # per-crate configuration isn't specifiable in the environment. codegen-units = 10000 +[profile.release.package.rustc-rayon-core] +# The rustc fork of Rayon has deadlock detection code which intermittently +# causes overflows in the CI (see https://github.com/rust-lang/rust/issues/90227) +# so we turn overflow checks off for now. +# FIXME: This workaround should be removed once #90227 is fixed. +overflow-checks = false + # These dependencies of the standard library implement symbolication for # backtraces on most platforms. Their debuginfo causes both linking to be slower # (more data to chew through) and binaries to be larger without really all that diff --git a/README.md b/README.md index 32fab9fc25..78edac9d12 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,10 @@ standard library, and documentation. **Note: this README is for _users_ rather than _contributors_. If you wish to _contribute_ to the compiler, you should read the -[Getting Started][gettingstarted] section of the rustc-dev-guide instead.** +[Getting Started][gettingstarted] section of the rustc-dev-guide instead. +You can ask for help in the [#new members Zulip stream][new-members].** + +[new-members]: https://rust-lang.zulipchat.com/#narrow/stream/122652-new-members ## Quick Start diff --git a/RELEASES.md b/RELEASES.md index 4b9b20f4cb..bee6da2e67 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,190 @@ +Version 1.58.1 (2022-01-19) +=========================== + +* Fix race condition in `std::fs::remove_dir_all` ([CVE-2022-21658]) +* [Handle captured arguments in the `useless_format` Clippy lint][clippy/8295] +* [Move `non_send_fields_in_send_ty` Clippy lint to nursery][clippy/8075] +* [Fix wrong error message displayed when some imports are missing][91254] +* [Fix rustfmt not formatting generated files from stdin][92912] + +[CVE-2022-21658]: https://www.cve.org/CVERecord?id=CVE-2022-21658] +[91254]: https://github.com/rust-lang/rust/pull/91254 +[92912]: https://github.com/rust-lang/rust/pull/92912 +[clippy/8075]: https://github.com/rust-lang/rust-clippy/pull/8075 +[clippy/8295]: https://github.com/rust-lang/rust-clippy/pull/8295 + +Version 1.58.0 (2022-01-13) +========================== + +Language +-------- + +- [Format strings can now capture arguments simply by writing `{ident}` in the string.][90473] This works in all macros accepting format strings. Support for this in `panic!` (`panic!("{ident}")`) requires the 2021 edition; panic invocations in previous editions that appear to be trying to use this will result in a warning lint about not having the intended effect. +- [`*const T` pointers can now be dereferenced in const contexts.][89551] +- [The rules for when a generic struct implements `Unsize` have been relaxed.][90417] + +Compiler +-------- + +- [Add LLVM CFI support to the Rust compiler][89652] +- [Stabilize -Z strip as -C strip][90058]. Note that while release builds already don't add debug symbols for the code you compile, the compiled standard library that ships with Rust includes debug symbols, so you may want to use the `strip` option to remove these symbols to produce smaller release binaries. Note that this release only includes support in rustc, not directly in cargo. +- [Add support for LLVM coverage mapping format versions 5 and 6][91207] +- [Emit LLVM optimization remarks when enabled with `-Cremark`][90833] +- [Update the minimum external LLVM to 12][90175] +- [Add `x86_64-unknown-none` at Tier 3*][89062] +- [Build musl dist artifacts with debuginfo enabled][90733]. When building release binaries using musl, you may want to use the newly stabilized strip option to remove these debug symbols, reducing the size of your binaries. +- [Don't abort compilation after giving a lint error][87337] +- [Error messages point at the source of trait bound obligations in more places][89580] + +\* Refer to Rust's [platform support page][platform-support-doc] for more + information on Rust's tiered platform support. + +Libraries +--------- + +- [All remaining functions in the standard library have `#[must_use]` annotations where appropriate][89692], producing a warning when ignoring their return value. This helps catch mistakes such as expecting a function to mutate a value in place rather than return a new value. +- [Paths are automatically canonicalized on Windows for operations that support it][89174] +- [Re-enable debug checks for `copy` and `copy_nonoverlapping`][90041] +- [Implement `RefUnwindSafe` for `Rc`][87467] +- [Make RSplit: Clone not require T: Clone][90117] +- [Implement `Termination` for `Result`][88601]. This allows writing `fn main() -> Result`, for a program whose successful exits never involve returning from `main` (for instance, a program that calls `exit`, or that uses `exec` to run another program). + +Stabilized APIs +--------------- + +- [`Metadata::is_symlink`] +- [`Path::is_symlink`] +- [`{integer}::saturating_div`] +- [`Option::unwrap_unchecked`] +- [`Result::unwrap_unchecked`] +- [`Result::unwrap_err_unchecked`] +- [`NonZero{unsigned}::is_power_of_two`] +- [`File::options`] + +These APIs are now usable in const contexts: + +- [`Duration::new`] +- [`Duration::checked_add`] +- [`Duration::saturating_add`] +- [`Duration::checked_sub`] +- [`Duration::saturating_sub`] +- [`Duration::checked_mul`] +- [`Duration::saturating_mul`] +- [`Duration::checked_div`] +- [`MaybeUninit::as_ptr`] +- [`MaybeUninit::as_mut_ptr`] +- [`MaybeUninit::assume_init`] +- [`MaybeUninit::assume_init_ref`] + +Cargo +----- + +- [Add --message-format for install command][cargo/10107] +- [Warn when alias shadows external subcommand][cargo/10082] + +Rustdoc +------- + +- [Show all Deref implementations recursively in rustdoc][90183] +- [Use computed visibility in rustdoc][88447] + +Compatibility Notes +------------------- + +- [Try all stable method candidates first before trying unstable ones][90329]. This change ensures that adding new nightly-only methods to the Rust standard library will not break code invoking methods of the same name from traits outside the standard library. +- Windows: [`std::process::Command` will no longer search the current directory for executables.][87704] +- [All proc-macro backward-compatibility lints are now deny-by-default.][88041] +- [proc_macro: Append .0 to unsuffixed float if it would otherwise become int token][90297] +- [Refactor weak symbols in std::sys::unix][90846]. This optimizes accesses to glibc functions, by avoiding the use of dlopen. This does not increase the [minimum expected version of glibc](https://doc.rust-lang.org/nightly/rustc/platform-support.html). However, software distributions that use symbol versions to detect library dependencies, and which take weak symbols into account in that analysis, may detect rust binaries as requiring newer versions of glibc. +- [rustdoc now rejects some unexpected semicolons in doctests][91026] + +Internal Changes +---------------- + +These changes provide no direct user facing benefits, but represent significant +improvements to the internals and overall performance of rustc +and related tools. + +- [Implement coherence checks for negative trait impls][90104] +- [Add rustc lint, warning when iterating over hashmaps][89558] +- [Optimize live point computation][90491] +- [Enable verification for 1/32nd of queries loaded from disk][90361] +- [Implement version of normalize_erasing_regions that allows for normalization failure][91255] + +[87337]: https://github.com/rust-lang/rust/pull/87337/ +[87467]: https://github.com/rust-lang/rust/pull/87467/ +[87704]: https://github.com/rust-lang/rust/pull/87704/ +[88041]: https://github.com/rust-lang/rust/pull/88041/ +[88300]: https://github.com/rust-lang/rust/pull/88300/ +[88447]: https://github.com/rust-lang/rust/pull/88447/ +[88601]: https://github.com/rust-lang/rust/pull/88601/ +[88624]: https://github.com/rust-lang/rust/pull/88624/ +[89062]: https://github.com/rust-lang/rust/pull/89062/ +[89174]: https://github.com/rust-lang/rust/pull/89174/ +[89542]: https://github.com/rust-lang/rust/pull/89542/ +[89551]: https://github.com/rust-lang/rust/pull/89551/ +[89558]: https://github.com/rust-lang/rust/pull/89558/ +[89580]: https://github.com/rust-lang/rust/pull/89580/ +[89652]: https://github.com/rust-lang/rust/pull/89652/ +[89677]: https://github.com/rust-lang/rust/pull/89677/ +[89951]: https://github.com/rust-lang/rust/pull/89951/ +[90041]: https://github.com/rust-lang/rust/pull/90041/ +[90058]: https://github.com/rust-lang/rust/pull/90058/ +[90104]: https://github.com/rust-lang/rust/pull/90104/ +[90117]: https://github.com/rust-lang/rust/pull/90117/ +[90175]: https://github.com/rust-lang/rust/pull/90175/ +[90183]: https://github.com/rust-lang/rust/pull/90183/ +[90297]: https://github.com/rust-lang/rust/pull/90297/ +[90329]: https://github.com/rust-lang/rust/pull/90329/ +[90361]: https://github.com/rust-lang/rust/pull/90361/ +[90417]: https://github.com/rust-lang/rust/pull/90417/ +[90473]: https://github.com/rust-lang/rust/pull/90473/ +[90491]: https://github.com/rust-lang/rust/pull/90491/ +[90733]: https://github.com/rust-lang/rust/pull/90733/ +[90833]: https://github.com/rust-lang/rust/pull/90833/ +[90846]: https://github.com/rust-lang/rust/pull/90846/ +[90896]: https://github.com/rust-lang/rust/pull/90896/ +[91026]: https://github.com/rust-lang/rust/pull/91026/ +[91207]: https://github.com/rust-lang/rust/pull/91207/ +[91255]: https://github.com/rust-lang/rust/pull/91255/ +[91301]: https://github.com/rust-lang/rust/pull/91301/ +[cargo/10082]: https://github.com/rust-lang/cargo/pull/10082/ +[cargo/10107]: https://github.com/rust-lang/cargo/pull/10107/ +[`Metadata::is_symlink`]: https://doc.rust-lang.org/stable/std/fs/struct.Metadata.html#method.is_symlink +[`Path::is_symlink`]: https://doc.rust-lang.org/stable/std/path/struct.Path.html#method.is_symlink +[`{integer}::saturating_div`]: https://doc.rust-lang.org/stable/std/primitive.i8.html#method.saturating_div +[`Option::unwrap_unchecked`]: https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.unwrap_unchecked +[`Result::unwrap_unchecked`]: https://doc.rust-lang.org/stable/std/result/enum.Result.html#method.unwrap_unchecked +[`Result::unwrap_err_unchecked`]: https://doc.rust-lang.org/stable/std/result/enum.Result.html#method.unwrap_err_unchecked +[`NonZero{unsigned}::is_power_of_two`]: https://doc.rust-lang.org/stable/std/num/struct.NonZeroU8.html#method.is_power_of_two +[`File::options`]: https://doc.rust-lang.org/stable/std/fs/struct.File.html#method.options +[`unix::process::ExitStatusExt::core_dumped`]: https://doc.rust-lang.org/stable/std/os/unix/process/trait.ExitStatusExt.html#tymethod.core_dumped +[`unix::process::ExitStatusExt::stopped_signal`]: https://doc.rust-lang.org/stable/std/os/unix/process/trait.ExitStatusExt.html#tymethod.stopped_signal +[`unix::process::ExitStatusExt::continued`]: https://doc.rust-lang.org/stable/std/os/unix/process/trait.ExitStatusExt.html#tymethod.continued +[`unix::process::ExitStatusExt::into_raw`]: https://doc.rust-lang.org/stable/std/os/unix/process/trait.ExitStatusExt.html#tymethod.into_raw +[`Duration::new`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.new +[`Duration::checked_add`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.checked_add +[`Duration::saturating_add`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.saturating_add +[`Duration::checked_sub`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.checked_sub +[`Duration::saturating_sub`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.saturating_sub +[`Duration::checked_mul`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.checked_mul +[`Duration::saturating_mul`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.saturating_mul +[`Duration::checked_div`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.checked_div +[`Duration::as_secs_f64`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.as_secs_f64 +[`Duration::as_secs_f32`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.as_secs_f32 +[`Duration::from_secs_f64`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.from_secs_f64 +[`Duration::from_secs_f32`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.from_secs_f32 +[`Duration::mul_f64`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.mul_f64 +[`Duration::mul_f32`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.mul_f32 +[`Duration::div_f64`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.div_f64 +[`Duration::div_f32`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.div_f32 +[`Duration::div_duration_f64`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.div_duration_f64 +[`Duration::div_duration_f32`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.div_duration_f32 +[`MaybeUninit::as_ptr`]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.as_ptr +[`MaybeUninit::as_mut_ptr`]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.as_mut_ptr +[`MaybeUninit::assume_init`]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.assume_init +[`MaybeUninit::assume_init_ref`]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.assume_init_ref + Version 1.57.0 (2021-12-02) ========================== @@ -388,6 +575,10 @@ Compatibility Notes `Command` would cause them to be ASCII-uppercased. - [Rustdoc will now warn on using rustdoc lints that aren't prefixed with `rustdoc::`][86849] +- `RUSTFLAGS` is no longer set for build scripts. Build scripts + should use `CARGO_ENCODED_RUSTFLAGS` instead. See the + [documentation](https://doc.rust-lang.org/nightly/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts) + for more details. [86849]: https://github.com/rust-lang/rust/pull/86849 [86513]: https://github.com/rust-lang/rust/pull/86513 diff --git a/compiler/rustc_apfloat/src/ieee.rs b/compiler/rustc_apfloat/src/ieee.rs index 739c6fd0a4..96277950cf 100644 --- a/compiler/rustc_apfloat/src/ieee.rs +++ b/compiler/rustc_apfloat/src/ieee.rs @@ -389,7 +389,6 @@ impl fmt::Display for IeeeFloat { let _: Loss = sig::shift_right(&mut sig, &mut exp, trailing_zeros as usize); // Change the exponent from 2^e to 10^e. - #[allow(clippy::comparison_chain)] if exp == 0 { // Nothing to do. } else if exp > 0 { @@ -2527,7 +2526,6 @@ mod sig { if *a_sign ^ b_sign { let (reverse, loss); - #[allow(clippy::comparison_chain)] if bits == 0 { reverse = cmp(a_sig, b_sig) == Ordering::Less; loss = Loss::ExactlyZero; diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index 6d5f47acee..6f9ecb9cd2 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -19,7 +19,6 @@ #![feature(rustc_attrs)] #![cfg_attr(test, feature(test))] -use rustc_data_structures::sync; use smallvec::SmallVec; use std::alloc::Layout; @@ -112,7 +111,7 @@ impl Default for TypedArena { // alloc() will trigger a grow(). ptr: Cell::new(ptr::null_mut()), end: Cell::new(ptr::null_mut()), - chunks: RefCell::new(vec![]), + chunks: Default::default(), _own: PhantomData, } } @@ -326,13 +325,17 @@ unsafe impl<#[may_dangle] T> Drop for TypedArena { unsafe impl Send for TypedArena {} +/// An arena that can hold objects of multiple different types that impl `Copy` +/// and/or satisfy `!mem::needs_drop`. 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. + /// The allocation proceeds downwards from the end of the chunk towards the + /// start. (This is slightly simpler and faster than allocating upwards, + /// see .) /// When this pointer crosses the start pointer, a new chunk is allocated. end: Cell<*mut u8>, @@ -517,130 +520,16 @@ impl DroplessArena { } } -/// Calls the destructor for an object when dropped. -struct DropType { - drop_fn: unsafe fn(*mut u8), - obj: *mut u8, -} - -// SAFETY: we require `T: Send` before type-erasing into `DropType`. -#[cfg(parallel_compiler)] -unsafe impl sync::Send for DropType {} - -impl DropType { - #[inline] - unsafe fn new(obj: *mut T) -> Self { - unsafe fn drop_for_type(to_drop: *mut u8) { - std::ptr::drop_in_place(to_drop as *mut T) - } - - DropType { drop_fn: drop_for_type::, obj: obj as *mut u8 } - } -} - -impl Drop for DropType { - fn drop(&mut self) { - unsafe { (self.drop_fn)(self.obj) } - } -} - -/// An arena which can be used to allocate any type. -/// -/// # Safety -/// -/// 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 - where - T: sync::Send, - { - 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::new(result)); - result - } - - #[inline] - pub unsafe fn alloc_from_iter(&self, iter: I) -> &mut [T] - where - T: sync::Send, - I: IntoIterator, - { - 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::new(start_ptr.add(i))); - } - - slice::from_raw_parts_mut(start_ptr, len) - } -} - -pub macro 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) - }, -} - -pub macro 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) - }, -} - +// Declare an `Arena` containing one dropless arena and many typed arenas (the +// types of the typed arenas are specified by the arguments). The dropless +// arena will be used for any types that impl `Copy`, and also for any of the +// specified types that satisfy `!mem::needs_drop`. #[rustc_macro_transparency = "semitransparent"] -pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) { +pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) { #[derive(Default)] - pub struct Arena<$tcx> { + pub struct Arena<'tcx> { pub dropless: $crate::DroplessArena, - drop: $crate::DropArena, - $($name: $crate::arena_for_type!($a[$ty]),)* + $($name: $crate::TypedArena<$ty>,)* } pub trait ArenaAllocatable<'tcx, T = Self>: Sized { @@ -651,6 +540,7 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) { ) -> &'a mut [Self]; } + // Any type that impls `Copy` can be arena-allocated in the `DroplessArena`. impl<'tcx, T: Copy> ArenaAllocatable<'tcx, ()> for T { #[inline] fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self { @@ -663,36 +553,27 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) { ) -> &'a mut [Self] { arena.dropless.alloc_from_iter(iter) } - } $( - impl<$tcx> ArenaAllocatable<$tcx, $ty> for $ty { + impl<'tcx> ArenaAllocatable<'tcx, $ty> for $ty { #[inline] - fn allocate_on<'a>(self, arena: &'a Arena<$tcx>) -> &'a mut Self { + 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) }, + arena.dropless.alloc(self) + } else { + arena.$name.alloc(self) } } #[inline] fn allocate_from_iter<'a>( - arena: &'a Arena<$tcx>, + 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) }, + arena.dropless.alloc_from_iter(iter) + } else { + arena.$name.alloc_from_iter(iter) } } } @@ -704,6 +585,7 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) { value.allocate_on(self) } + // Any type that impls `Copy` can have slices be arena-allocated in the `DroplessArena`. #[inline] pub fn alloc_slice(&self, value: &[T]) -> &mut [T] { if value.is_empty() { diff --git a/compiler/rustc_ast/README.md b/compiler/rustc_ast/README.md index dd407dba1f..b2b90fed03 100644 --- a/compiler/rustc_ast/README.md +++ b/compiler/rustc_ast/README.md @@ -1,6 +1,5 @@ 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. +– that is, the AST ("abstract syntax tree"), along with some definitions for tokens and token streams, data structures/traits for mutating ASTs, and shared definitions for other AST-related parts of the compiler (like the lexer and macro-expansion). For more information about how these things work in rustc, see the rustc dev guide: diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index e2424e7d7a..55b243a84a 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -405,6 +405,21 @@ pub struct GenericParam { pub kind: GenericParamKind, } +impl GenericParam { + pub fn span(&self) -> Span { + match &self.kind { + GenericParamKind::Lifetime | GenericParamKind::Type { default: None } => { + self.ident.span + } + GenericParamKind::Type { default: Some(ty) } => self.ident.span.to(ty.span), + GenericParamKind::Const { kw_span, default: Some(default), .. } => { + kw_span.to(default.value.span) + } + GenericParamKind::Const { kw_span, default: None, ty } => kw_span.to(ty.span), + } + } +} + /// Represents lifetime, type and const parameters attached to a declaration of /// a function, enum, trait, etc. #[derive(Clone, Encodable, Decodable, Debug)] @@ -2058,7 +2073,7 @@ pub struct InlineAsm { pub template: Vec, pub template_strs: Box<[(Symbol, Option, Span)]>, pub operands: Vec<(InlineAsmOperand, Span)>, - pub clobber_abi: Option<(Symbol, Span)>, + pub clobber_abis: Vec<(Symbol, Span)>, pub options: InlineAsmOptions, pub line_spans: Vec, } @@ -2645,34 +2660,42 @@ impl Default for FnHeader { } #[derive(Clone, Encodable, Decodable, Debug)] -pub struct TraitKind( - pub IsAuto, - pub Unsafe, - pub Generics, - pub GenericBounds, - pub Vec>, -); +pub struct Trait { + pub unsafety: Unsafe, + pub is_auto: IsAuto, + pub generics: Generics, + pub bounds: GenericBounds, + pub items: Vec>, +} #[derive(Clone, Encodable, Decodable, Debug)] -pub struct TyAliasKind(pub Defaultness, pub Generics, pub GenericBounds, pub Option>); +pub struct TyAlias { + pub defaultness: Defaultness, + pub generics: Generics, + pub bounds: GenericBounds, + pub ty: Option>, +} #[derive(Clone, Encodable, Decodable, Debug)] -pub struct ImplKind { - pub unsafety: Unsafe, - pub polarity: ImplPolarity, +pub struct Impl { pub defaultness: Defaultness, - pub constness: Const, + pub unsafety: Unsafe, pub generics: Generics, - + pub constness: Const, + pub polarity: ImplPolarity, /// 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>); +pub struct Fn { + pub defaultness: Defaultness, + pub generics: Generics, + pub sig: FnSig, + pub body: Option>, +} #[derive(Clone, Encodable, Decodable, Debug)] pub enum ItemKind { @@ -2695,7 +2718,7 @@ pub enum ItemKind { /// A function declaration (`fn`). /// /// E.g., `fn foo(bar: usize) -> usize { .. }`. - Fn(Box), + Fn(Box), /// A module declaration (`mod`). /// /// E.g., `mod foo;` or `mod foo { .. }`. @@ -2707,11 +2730,11 @@ pub enum ItemKind { /// E.g., `extern {}` or `extern "C" {}`. ForeignMod(ForeignMod), /// Module-level inline assembly (from `global_asm!()`). - GlobalAsm(InlineAsm), + GlobalAsm(Box), /// A type alias (`type`). /// /// E.g., `type Foo = Bar;`. - TyAlias(Box), + TyAlias(Box), /// An enum definition (`enum`). /// /// E.g., `enum Foo { C, D }`. @@ -2727,7 +2750,7 @@ pub enum ItemKind { /// A trait declaration (`trait`). /// /// E.g., `trait Foo { .. }`, `trait Foo { .. }` or `auto trait Foo {}`. - Trait(Box), + Trait(Box), /// Trait alias /// /// E.g., `trait Foo = Bar + Quux;`. @@ -2735,7 +2758,7 @@ pub enum ItemKind { /// An implementation. /// /// E.g., `impl Foo { .. }` or `impl Trait for Foo { .. }`. - Impl(Box), + Impl(Box), /// A macro invocation. /// /// E.g., `foo!(..)`. @@ -2782,14 +2805,14 @@ impl ItemKind { pub fn generics(&self) -> Option<&Generics> { match self { - Self::Fn(box FnKind(_, _, generics, _)) - | Self::TyAlias(box TyAliasKind(_, generics, ..)) + Self::Fn(box Fn { generics, .. }) + | Self::TyAlias(box TyAlias { generics, .. }) | Self::Enum(_, generics) | Self::Struct(_, generics) | Self::Union(_, generics) - | Self::Trait(box TraitKind(_, _, generics, ..)) + | Self::Trait(box Trait { generics, .. }) | Self::TraitAlias(generics, _) - | Self::Impl(box ImplKind { generics, .. }) => Some(generics), + | Self::Impl(box Impl { generics, .. }) => Some(generics), _ => None, } } @@ -2812,9 +2835,9 @@ pub enum AssocItemKind { /// If `def` is parsed, then the constant is provided, and otherwise required. Const(Defaultness, P, Option>), /// An associated function. - Fn(Box), + Fn(Box), /// An associated type. - TyAlias(Box), + TyAlias(Box), /// A macro expanding to associated items. MacCall(MacCall), } @@ -2825,9 +2848,9 @@ 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::Const(defaultness, ..) + | Self::Fn(box Fn { defaultness, .. }) + | Self::TyAlias(box TyAlias { defaultness, .. }) => defaultness, Self::MacCall(..) => Defaultness::Final, } } @@ -2864,9 +2887,9 @@ pub enum ForeignItemKind { /// A foreign static item (`static FOO: u8`). Static(P, Mutability, Option>), /// An foreign function. - Fn(Box), + Fn(Box), /// An foreign type. - TyAlias(Box), + TyAlias(Box), /// A macro expanding to foreign items. MacCall(MacCall), } diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 5f17008bdc..927d7c6aaf 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -62,7 +62,7 @@ impl NestedMetaItem { 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 + self.ident().unwrap_or_else(Ident::empty).name } /// Gets the string value if `self` is a `MetaItem` and the `MetaItem` is a @@ -131,7 +131,7 @@ impl Attribute { } } pub fn name_or_empty(&self) -> Symbol { - self.ident().unwrap_or_else(Ident::invalid).name + self.ident().unwrap_or_else(Ident::empty).name } pub fn value_str(&self) -> Option { @@ -166,7 +166,7 @@ impl MetaItem { 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 + self.ident().unwrap_or_else(Ident::empty).name } // Example: diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index e3c610585d..b9db2a7e08 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -1,4 +1,4 @@ -//! The Rust parser and macro expander. +//! The Rust Abstract Syntax Tree (AST). //! //! # Note //! @@ -16,6 +16,7 @@ #![feature(nll)] #![feature(min_specialization)] #![recursion_limit = "256"] +#![feature(slice_internals)] #[macro_use] extern crate rustc_macros; @@ -25,6 +26,7 @@ pub mod util { pub mod comments; pub mod literal; pub mod parser; + pub mod unicode; } pub mod ast; diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index ba86036577..fc5cc96399 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -37,9 +37,7 @@ 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 - } + const VISIT_TOKENS: bool = false; // Methods in this trait have one of three forms: // @@ -363,7 +361,7 @@ pub fn visit_mac_args(args: &mut MacArgs, vis: &mut T) { } MacArgs::Eq(eq_span, token) => { vis.visit_span(eq_span); - if vis.token_visiting_enabled() { + if T::VISIT_TOKENS { visit_token(token, vis); } else { // The value in `#[key = VALUE]` must be visited as an expression for backward @@ -461,7 +459,8 @@ pub fn noop_visit_ty(ty: &mut P, vis: &mut T) { vis.visit_mt(mt); } TyKind::BareFn(bft) => { - let BareFnTy { unsafety: _, ext: _, generic_params, decl } = bft.deref_mut(); + let BareFnTy { unsafety, ext: _, generic_params, decl } = bft.deref_mut(); + visit_unsafety(unsafety, vis); generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param)); vis.visit_fn_decl(decl); } @@ -490,7 +489,8 @@ pub fn noop_visit_ty(ty: &mut P, vis: &mut T) { } pub fn noop_visit_foreign_mod(foreign_mod: &mut ForeignMod, vis: &mut T) { - let ForeignMod { unsafety: _, abi: _, items } = foreign_mod; + let ForeignMod { unsafety, abi: _, items } = foreign_mod; + visit_unsafety(unsafety, vis); items.flat_map_in_place(|item| vis.flat_map_foreign_item(item)); } @@ -682,7 +682,7 @@ pub fn visit_tt(tt: &mut TokenTree, vis: &mut T) { // 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() { + if T::VISIT_TOKENS && !tts.is_empty() { let tts = Lrc::make_mut(tts); visit_vec(tts, |(tree, _is_joint)| visit_tt(tree, vis)); } @@ -692,14 +692,14 @@ pub fn visit_attr_annotated_tts( AttrAnnotatedTokenStream(tts): &mut AttrAnnotatedTokenStream, vis: &mut T, ) { - if vis.token_visiting_enabled() && !tts.is_empty() { + if T::VISIT_TOKENS && !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() { + if T::VISIT_TOKENS { if let Some(lazy_tts) = lazy_tts { let mut tts = lazy_tts.create_token_stream(); visit_attr_annotated_tts(&mut tts, vis); @@ -790,6 +790,38 @@ pub fn visit_interpolated(nt: &mut token::Nonterminal, vis: &mut } } +// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. +pub fn visit_defaultness(defaultness: &mut Defaultness, vis: &mut T) { + match defaultness { + Defaultness::Default(span) => vis.visit_span(span), + Defaultness::Final => {} + } +} + +// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. +pub fn visit_unsafety(unsafety: &mut Unsafe, vis: &mut T) { + match unsafety { + Unsafe::Yes(span) => vis.visit_span(span), + Unsafe::No => {} + } +} + +// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. +pub fn visit_polarity(polarity: &mut ImplPolarity, vis: &mut T) { + match polarity { + ImplPolarity::Positive => {} + ImplPolarity::Negative(span) => vis.visit_span(span), + } +} + +// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. +pub fn visit_constness(constness: &mut Const, vis: &mut T) { + match constness { + Const::Yes(span) => vis.visit_span(span), + Const::No => {} + } +} + pub fn noop_visit_asyncness(asyncness: &mut Async, vis: &mut T) { match asyncness { Async::Yes { span: _, closure_id, return_impl_trait_id } => { @@ -957,25 +989,35 @@ 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) => { + ItemKind::Static(ty, _, expr) => { vis.visit_ty(ty); visit_opt(expr, |expr| vis.visit_expr(expr)); } - ItemKind::Fn(box FnKind(_, sig, generics, body)) => { + ItemKind::Const(defaultness, ty, expr) => { + visit_defaultness(defaultness, vis); + vis.visit_ty(ty); + visit_opt(expr, |expr| vis.visit_expr(expr)); + } + ItemKind::Fn(box Fn { defaultness, generics, sig, body }) => { + visit_defaultness(defaultness, vis); visit_fn_sig(sig, vis); vis.visit_generics(generics); visit_opt(body, |body| vis.visit_block(body)); } - ItemKind::Mod(_unsafety, mod_kind) => match mod_kind { - ModKind::Loaded(items, _inline, inner_span) => { - vis.visit_span(inner_span); - items.flat_map_in_place(|item| vis.flat_map_item(item)); + ItemKind::Mod(unsafety, mod_kind) => { + visit_unsafety(unsafety, vis); + match mod_kind { + ModKind::Loaded(items, _inline, inner_span) => { + vis.visit_span(inner_span); + items.flat_map_in_place(|item| vis.flat_map_item(item)); + } + ModKind::Unloaded => {} } - ModKind::Unloaded => {} - }, + } ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm), ItemKind::GlobalAsm(asm) => noop_visit_inline_asm(asm, vis), - ItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => { + ItemKind::TyAlias(box TyAlias { defaultness, generics, bounds, ty }) => { + visit_defaultness(defaultness, vis); vis.visit_generics(generics); visit_bounds(bounds, vis); visit_opt(ty, |ty| vis.visit_ty(ty)); @@ -988,22 +1030,27 @@ pub fn noop_visit_item_kind(kind: &mut ItemKind, vis: &mut T) { vis.visit_variant_data(variant_data); vis.visit_generics(generics); } - ItemKind::Impl(box ImplKind { - unsafety: _, - polarity: _, - defaultness: _, - constness: _, + ItemKind::Impl(box Impl { + defaultness, + unsafety, generics, + constness, + polarity, of_trait, self_ty, items, }) => { + visit_defaultness(defaultness, vis); + visit_unsafety(unsafety, vis); vis.visit_generics(generics); + visit_constness(constness, vis); + visit_polarity(polarity, vis); 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)) => { + ItemKind::Trait(box Trait { unsafety, is_auto: _, generics, bounds, items }) => { + visit_unsafety(unsafety, vis); vis.visit_generics(generics); visit_bounds(bounds, vis); items.flat_map_in_place(|item| vis.flat_map_trait_item(item)); @@ -1027,16 +1074,19 @@ pub fn noop_flat_map_assoc_item( visitor.visit_vis(vis); visit_attrs(attrs, visitor); match kind { - AssocItemKind::Const(_, ty, expr) => { + AssocItemKind::Const(defaultness, ty, expr) => { + visit_defaultness(defaultness, visitor); visitor.visit_ty(ty); visit_opt(expr, |expr| visitor.visit_expr(expr)); } - AssocItemKind::Fn(box FnKind(_, sig, generics, body)) => { + AssocItemKind::Fn(box Fn { defaultness, generics, sig, body }) => { + visit_defaultness(defaultness, visitor); visitor.visit_generics(generics); visit_fn_sig(sig, visitor); visit_opt(body, |body| visitor.visit_block(body)); } - AssocItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => { + AssocItemKind::TyAlias(box TyAlias { defaultness, generics, bounds, ty }) => { + visit_defaultness(defaultness, visitor); visitor.visit_generics(generics); visit_bounds(bounds, visitor); visit_opt(ty, |ty| visitor.visit_ty(ty)); @@ -1049,8 +1099,10 @@ pub fn noop_flat_map_assoc_item( } pub fn noop_visit_fn_header(header: &mut FnHeader, vis: &mut T) { - let FnHeader { unsafety: _, asyncness, constness: _, ext: _ } = header; + let FnHeader { unsafety, asyncness, constness, ext: _ } = header; + visit_constness(constness, vis); vis.visit_asyncness(asyncness); + visit_unsafety(unsafety, vis); } // FIXME: Avoid visiting the crate as a `Mod` item, flat map only the inner items if possible, @@ -1060,7 +1112,7 @@ pub fn noop_visit_crate(krate: &mut Crate, vis: &mut T) { let item_vis = Visibility { kind: VisibilityKind::Public, span: span.shrink_to_lo(), tokens: None }; let item = P(Item { - ident: Ident::invalid(), + ident: Ident::empty(), attrs, id: DUMMY_NODE_ID, vis: item_vis, @@ -1116,12 +1168,14 @@ pub fn noop_flat_map_foreign_item( visitor.visit_ty(ty); visit_opt(expr, |expr| visitor.visit_expr(expr)); } - ForeignItemKind::Fn(box FnKind(_, sig, generics, body)) => { + ForeignItemKind::Fn(box Fn { defaultness, generics, sig, body }) => { + visit_defaultness(defaultness, visitor); visitor.visit_generics(generics); visit_fn_sig(sig, visitor); visit_opt(body, |body| visitor.visit_block(body)); } - ForeignItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => { + ForeignItemKind::TyAlias(box TyAlias { defaultness, generics, bounds, ty }) => { + visit_defaultness(defaultness, visitor); visitor.visit_generics(generics); visit_bounds(bounds, visitor); visit_opt(ty, |ty| visitor.visit_ty(ty)); diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 5d994dbad4..51cabb50cd 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -221,12 +221,6 @@ impl AttrAnnotatedTokenStream { for attr in &data.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 => { diff --git a/compiler/rustc_ast/src/util/comments.rs b/compiler/rustc_ast/src/util/comments.rs index 542a330a03..80a06fa594 100644 --- a/compiler/rustc_ast/src/util/comments.rs +++ b/compiler/rustc_ast/src/util/comments.rs @@ -38,7 +38,7 @@ pub fn beautify_doc_string(data: Symbol) -> Symbol { 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 == '*') { + if j > i && !lines[j - 1].is_empty() && lines[j - 1].chars().all(|c| c == '*') { j -= 1; } @@ -169,7 +169,7 @@ pub fn gather_comments(sm: &SourceMap, path: FileName, src: String) -> Vec bool { use AssocOp::*; - match self { + matches!( + self, BitXor | // `{ 42 } ^ 3` Assign | // `{ 42 } = { 42 }` Divide | // `{ 42 } / 42` @@ -225,9 +226,8 @@ impl AssocOp { 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, - } + Colon, // `{ 42 }: usize` + ) } } @@ -357,13 +357,13 @@ impl ExprPrecedence { } } -/// In `let p = e`, operators with precedence `<=` this one requires parenthesis in `e`. +/// In `let p = e`, operators with precedence `<=` this one requires parentheses 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? +/// Is the `order` such that `e` in `let _ = e` needs parentheses 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`? diff --git a/compiler/rustc_ast/src/util/unicode.rs b/compiler/rustc_ast/src/util/unicode.rs new file mode 100644 index 0000000000..f009f7b300 --- /dev/null +++ b/compiler/rustc_ast/src/util/unicode.rs @@ -0,0 +1,35 @@ +pub const TEXT_FLOW_CONTROL_CHARS: &[char] = &[ + '\u{202A}', '\u{202B}', '\u{202D}', '\u{202E}', '\u{2066}', '\u{2067}', '\u{2068}', '\u{202C}', + '\u{2069}', +]; + +#[inline] +pub fn contains_text_flow_control_chars(s: &str) -> bool { + // Char - UTF-8 + // U+202A - E2 80 AA + // U+202B - E2 80 AB + // U+202C - E2 80 AC + // U+202D - E2 80 AD + // U+202E - E2 80 AE + // U+2066 - E2 81 A6 + // U+2067 - E2 81 A7 + // U+2068 - E2 81 A8 + // U+2069 - E2 81 A9 + let mut bytes = s.as_bytes(); + loop { + match core::slice::memchr::memchr(0xE2, &bytes) { + Some(idx) => { + // bytes are valid UTF-8 -> E2 must be followed by two bytes + let ch = &bytes[idx..idx + 3]; + match ch { + [_, 0x80, 0xAA..=0xAE] | [_, 0x81, 0xA6..=0xA9] => break true, + _ => {} + } + bytes = &bytes[idx + 3..]; + } + None => { + break false; + } + } + } +} diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index b38031042e..be794ed221 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -285,7 +285,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { visitor.visit_ty(typ); walk_list!(visitor, visit_expr, expr); } - ItemKind::Fn(box FnKind(_, ref sig, ref generics, ref body)) => { + ItemKind::Fn(box Fn { defaultness: _, ref generics, ref sig, 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) @@ -300,7 +300,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { walk_list!(visitor, visit_foreign_item, &foreign_module.items); } ItemKind::GlobalAsm(ref asm) => walk_inline_asm(visitor, asm), - ItemKind::TyAlias(box TyAliasKind(_, ref generics, ref bounds, ref ty)) => { + ItemKind::TyAlias(box TyAlias { defaultness: _, ref generics, ref bounds, ref ty }) => { visitor.visit_generics(generics); walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_ty, ty); @@ -309,12 +309,12 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { visitor.visit_generics(generics); visitor.visit_enum_def(enum_definition, generics, item.id, item.span) } - ItemKind::Impl(box ImplKind { - unsafety: _, - polarity: _, + ItemKind::Impl(box Impl { defaultness: _, - constness: _, + unsafety: _, ref generics, + constness: _, + polarity: _, ref of_trait, ref self_ty, ref items, @@ -329,7 +329,13 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { visitor.visit_generics(generics); visitor.visit_variant_data(struct_definition); } - ItemKind::Trait(box TraitKind(.., ref generics, ref bounds, ref items)) => { + ItemKind::Trait(box Trait { + unsafety: _, + is_auto: _, + 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); @@ -547,12 +553,12 @@ pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignI visitor.visit_ty(ty); walk_list!(visitor, visit_expr, expr); } - ForeignItemKind::Fn(box FnKind(_, sig, generics, body)) => { + ForeignItemKind::Fn(box Fn { defaultness: _, ref generics, ref sig, ref 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)) => { + ForeignItemKind::TyAlias(box TyAlias { defaultness: _, generics, bounds, ty }) => { visitor.visit_generics(generics); walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_ty, ty); @@ -653,12 +659,12 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem, visitor.visit_ty(ty); walk_list!(visitor, visit_expr, expr); } - AssocItemKind::Fn(box FnKind(_, sig, generics, body)) => { + AssocItemKind::Fn(box Fn { defaultness: _, ref generics, ref sig, ref 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)) => { + AssocItemKind::TyAlias(box TyAlias { defaultness: _, generics, bounds, ty }) => { visitor.visit_generics(generics); walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_ty, ty); diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml index f4859ee4ae..7989af24d9 100644 --- a/compiler/rustc_ast_lowering/Cargo.toml +++ b/compiler/rustc_ast_lowering/Cargo.toml @@ -14,6 +14,7 @@ rustc_hir = { path = "../rustc_hir" } rustc_target = { path = "../rustc_target" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_index = { path = "../rustc_index" } +rustc_query_system = { path = "../rustc_query_system" } rustc_span = { path = "../rustc_span" } rustc_errors = { path = "../rustc_errors" } rustc_session = { path = "../rustc_session" } diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 957b14f348..cfa97ff84e 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -2,22 +2,45 @@ use super::LoweringContext; use rustc_ast::*; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::stable_set::FxHashSet; use rustc_errors::struct_span_err; use rustc_hir as hir; -use rustc_span::{Span, Symbol}; +use rustc_session::parse::feature_err; +use rustc_span::{sym, Span, Symbol}; use rustc_target::asm; use std::collections::hash_map::Entry; use std::fmt::Write; impl<'a, 'hir> LoweringContext<'a, 'hir> { crate fn lower_inline_asm(&mut self, sp: Span, asm: &InlineAsm) -> &'hir hir::InlineAsm<'hir> { - // Rustdoc needs to support asm! from foriegn architectures: don't try - // lowering the register contraints in this case. + // Rustdoc needs to support asm! from foreign architectures: don't try + // lowering the register constraints in this case. let asm_arch = if self.sess.opts.actually_rustdoc { None } else { self.sess.asm_arch }; if asm_arch.is_none() && !self.sess.opts.actually_rustdoc { struct_span_err!(self.sess, sp, E0472, "inline assembly is unsupported on this target") .emit(); } + if let Some(asm_arch) = asm_arch { + // Inline assembly is currently only stable for these architectures. + let is_stable = matches!( + asm_arch, + asm::InlineAsmArch::X86 + | asm::InlineAsmArch::X86_64 + | asm::InlineAsmArch::Arm + | asm::InlineAsmArch::AArch64 + | asm::InlineAsmArch::RiscV32 + | asm::InlineAsmArch::RiscV64 + ); + if !is_stable && !self.sess.features_untracked().asm_experimental_arch { + feature_err( + &self.sess.parse_sess, + sym::asm_experimental_arch, + sp, + "inline assembly is not stable yet on this architecture", + ) + .emit(); + } + } if asm.options.contains(InlineAsmOptions::ATT_SYNTAX) && !matches!(asm_arch, Some(asm::InlineAsmArch::X86 | asm::InlineAsmArch::X86_64)) && !self.sess.opts.actually_rustdoc @@ -27,22 +50,47 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .emit(); } - let mut clobber_abi = None; + let mut clobber_abis = FxHashMap::default(); if let Some(asm_arch) = asm_arch { - if let Some((abi_name, abi_span)) = asm.clobber_abi { - match asm::InlineAsmClobberAbi::parse(asm_arch, &self.sess.target, abi_name) { - Ok(abi) => clobber_abi = Some((abi, abi_span)), + for (abi_name, abi_span) in &asm.clobber_abis { + match asm::InlineAsmClobberAbi::parse(asm_arch, &self.sess.target, *abi_name) { + Ok(abi) => { + // If the abi was already in the list, emit an error + match clobber_abis.get(&abi) { + Some((prev_name, prev_sp)) => { + let mut err = self.sess.struct_span_err( + *abi_span, + &format!("`{}` ABI specified multiple times", prev_name), + ); + err.span_label(*prev_sp, "previously specified here"); + + // Multiple different abi names may actually be the same ABI + // If the specified ABIs are not the same name, alert the user that they resolve to the same ABI + let source_map = self.sess.source_map(); + if source_map.span_to_snippet(*prev_sp) + != source_map.span_to_snippet(*abi_span) + { + err.note("these ABIs are equivalent on the current target"); + } + + err.emit(); + } + None => { + clobber_abis.insert(abi, (abi_name, *abi_span)); + } + } + } Err(&[]) => { self.sess .struct_span_err( - abi_span, + *abi_span, "`clobber_abi` is not supported on this target", ) .emit(); } Err(supported_abis) => { let mut err = - self.sess.struct_span_err(abi_span, "invalid ABI for `clobber_abi`"); + self.sess.struct_span_err(*abi_span, "invalid ABI for `clobber_abi`"); let mut abis = format!("`{}`", supported_abis[0]); for m in &supported_abis[1..] { let _ = write!(abis, ", `{}`", m); @@ -121,10 +169,30 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { out_expr: out_expr.as_ref().map(|expr| self.lower_expr_mut(expr)), } } - InlineAsmOperand::Const { ref anon_const } => hir::InlineAsmOperand::Const { - anon_const: self.lower_anon_const(anon_const), - }, + InlineAsmOperand::Const { ref anon_const } => { + if !self.sess.features_untracked().asm_const { + feature_err( + &self.sess.parse_sess, + sym::asm_const, + *op_sp, + "const operands for inline assembly are unstable", + ) + .emit(); + } + hir::InlineAsmOperand::Const { + anon_const: self.lower_anon_const(anon_const), + } + } InlineAsmOperand::Sym { ref expr } => { + if !self.sess.features_untracked().asm_sym { + feature_err( + &self.sess.parse_sess, + sym::asm_sym, + *op_sp, + "sym operands for inline assembly are unstable", + ) + .emit(); + } hir::InlineAsmOperand::Sym { expr: self.lower_expr_mut(expr) } } }; @@ -214,9 +282,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // means that we disallow passing a value in/out of the asm and // require that the operand name an explicit register, not a // register class. - if reg_class.is_clobber_only(asm_arch.unwrap()) - && !(op.is_clobber() && matches!(reg, asm::InlineAsmRegOrRegClass::Reg(_))) - { + if reg_class.is_clobber_only(asm_arch.unwrap()) && !op.is_clobber() { let msg = format!( "register class `{}` can only be used as a clobber, \ not as an input or output", @@ -308,8 +374,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // If a clobber_abi is specified, add the necessary clobbers to the // operands list. - if let Some((abi, abi_span)) = clobber_abi { + let mut clobbered = FxHashSet::default(); + for (abi, (_, abi_span)) in clobber_abis { for &clobber in abi.clobbered_regs() { + // Don't emit a clobber for a register already clobbered + if clobbered.contains(&clobber) { + continue; + } + let mut output_used = false; clobber.overlapping_regs(|reg| { if used_output_regs.contains_key(®) { @@ -326,6 +398,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }, self.lower_span(abi_span), )); + clobbered.insert(clobber); } } } diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 6027027428..9c579209fe 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -13,7 +13,7 @@ use rustc_session::parse::feature_err; use rustc_span::hygiene::ExpnId; use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned}; use rustc_span::symbol::{sym, Ident, Symbol}; -use rustc_span::{hygiene::ForLoopLoc, DUMMY_SP}; +use rustc_span::DUMMY_SP; impl<'hir> LoweringContext<'_, 'hir> { fn lower_exprs(&mut self, exprs: &[AstP]) -> &'hir [hir::Expr<'hir>] { @@ -252,9 +252,10 @@ impl<'hir> LoweringContext<'_, 'hir> { } // Merge attributes into the inner expression. if !e.attrs.is_empty() { - let old_attrs = self.attrs.get(&ex.hir_id).map(|la| *la).unwrap_or(&[]); + let old_attrs = + self.attrs.get(&ex.hir_id.local_id).map(|la| *la).unwrap_or(&[]); self.attrs.insert( - ex.hir_id, + ex.hir_id.local_id, &*self.arena.alloc_from_iter( e.attrs .iter() @@ -914,14 +915,22 @@ impl<'hir> LoweringContext<'_, 'hir> { ); } if !self.sess.features_untracked().destructuring_assignment { - feature_err( + let mut err = feature_err( &self.sess.parse_sess, sym::destructuring_assignment, eq_sign_span, "destructuring assignments are unstable", - ) - .span_label(lhs.span, "cannot assign to this expression") - .emit(); + ); + err.span_label(lhs.span, "cannot assign to this expression"); + if self.is_in_loop_condition { + err.span_suggestion_verbose( + lhs.span.shrink_to_lo(), + "you might have meant to use pattern destructuring", + "let ".to_string(), + rustc_errors::Applicability::MachineApplicable, + ); + } + err.emit(); } let mut assignments = vec![]; @@ -1307,16 +1316,13 @@ impl<'hir> LoweringContext<'_, 'hir> { /// Desugar `ExprForLoop` from: `[opt_ident]: for in ` into: /// ```rust /// { - /// let result = match ::std::iter::IntoIterator::into_iter() { + /// let result = match IntoIterator::into_iter() { /// mut iter => { /// [opt_ident]: loop { - /// let mut __next; - /// match ::std::iter::Iterator::next(&mut iter) { - /// ::std::option::Option::Some(val) => __next = val, - /// ::std::option::Option::None => break + /// match Iterator::next(&mut iter) { + /// None => break, + /// Some() => , /// }; - /// let = __next; - /// StmtKind::Expr(); /// } /// } /// }; @@ -1331,136 +1337,75 @@ impl<'hir> LoweringContext<'_, 'hir> { body: &Block, opt_label: Option(&self, artifact_kind: &str, artifact_name: A, size: u64) + where + A: Borrow + Into, + { + drop(self.exec(EventFilter::ARTIFACT_SIZES, |profiler| { + let builder = EventIdBuilder::new(&profiler.profiler); + let event_label = profiler.get_or_alloc_cached_string(artifact_kind); + let event_arg = profiler.get_or_alloc_cached_string(artifact_name); + let event_id = builder.from_label_and_arg(event_label, event_arg); + let thread_id = get_thread_id(); + + profiler.profiler.record_integer_event( + profiler.artifact_size_event_kind, + event_id, + thread_id, + size, + ); + + TimingGuard::none() + })) + } + #[inline(always)] pub fn generic_activity_with_args( &self, @@ -372,7 +402,7 @@ impl SelfProfilerRef { ) { 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; + let thread_id = get_thread_id(); profiler.profiler.record_instant_event( event_kind(profiler), @@ -425,6 +455,7 @@ pub struct SelfProfiler { incremental_result_hashing_event_kind: StringId, query_blocked_event_kind: StringId, query_cache_hit_event_kind: StringId, + artifact_size_event_kind: StringId, } impl SelfProfiler { @@ -447,6 +478,7 @@ impl SelfProfiler { profiler.alloc_string("IncrementalResultHashing"); let query_blocked_event_kind = profiler.alloc_string("QueryBlocked"); let query_cache_hit_event_kind = profiler.alloc_string("QueryCacheHit"); + let artifact_size_event_kind = profiler.alloc_string("ArtifactSize"); let mut event_filter_mask = EventFilter::empty(); @@ -491,6 +523,7 @@ impl SelfProfiler { incremental_result_hashing_event_kind, query_blocked_event_kind, query_cache_hit_event_kind, + artifact_size_event_kind, }) } @@ -561,7 +594,7 @@ impl<'a> TimingGuard<'a> { event_kind: StringId, event_id: EventId, ) -> TimingGuard<'a> { - let thread_id = std::thread::current().id().as_u64().get() as u32; + let thread_id = get_thread_id(); let raw_profiler = &profiler.profiler; let timing_guard = raw_profiler.start_recording_interval_event(event_kind, event_id, thread_id); @@ -655,6 +688,10 @@ pub fn duration_to_secs_str(dur: std::time::Duration) -> String { format!("{:.3}", dur.as_secs_f64()) } +fn get_thread_id() -> u32 { + std::thread::current().id().as_u64().get() as u32 +} + // Memory reporting cfg_if! { if #[cfg(windows)] { diff --git a/compiler/rustc_data_structures/src/sorted_map.rs b/compiler/rustc_data_structures/src/sorted_map.rs index e80db0845a..9efea1228a 100644 --- a/compiler/rustc_data_structures/src/sorted_map.rs +++ b/compiler/rustc_data_structures/src/sorted_map.rs @@ -1,3 +1,4 @@ +use crate::stable_hasher::{HashStable, StableHasher}; use std::borrow::Borrow; use std::cmp::Ordering; use std::iter::FromIterator; @@ -16,17 +17,26 @@ pub use index_map::SortedIndexMultiMap; /// 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 { +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)] +pub struct SortedMap { data: Vec<(K, V)>, } -impl SortedMap { +impl Default for SortedMap { + #[inline] + fn default() -> SortedMap { + SortedMap { data: Vec::new() } + } +} + +impl SortedMap { #[inline] - pub fn new() -> SortedMap { - SortedMap { data: vec![] } + pub const fn new() -> SortedMap { + SortedMap { data: Vec::new() } } +} +impl SortedMap { /// Construct a `SortedMap` from a presorted set of elements. This is faster /// than creating an empty map and then inserting the elements individually. /// @@ -205,10 +215,10 @@ impl SortedMap { R: RangeBounds, { let start = match range.start_bound() { - Bound::Included(k) => match self.lookup_index_for(k) { + Bound::Included(ref k) => match self.lookup_index_for(k) { Ok(index) | Err(index) => index, }, - Bound::Excluded(k) => match self.lookup_index_for(k) { + Bound::Excluded(ref k) => match self.lookup_index_for(k) { Ok(index) => index + 1, Err(index) => index, }, @@ -216,11 +226,11 @@ impl SortedMap { }; let end = match range.end_bound() { - Bound::Included(k) => match self.lookup_index_for(k) { + Bound::Included(ref k) => match self.lookup_index_for(k) { Ok(index) => index + 1, Err(index) => index, }, - Bound::Excluded(k) => match self.lookup_index_for(k) { + Bound::Excluded(ref k) => match self.lookup_index_for(k) { Ok(index) | Err(index) => index, }, Bound::Unbounded => self.data.len(), @@ -281,5 +291,12 @@ impl FromIterator<(K, V)> for SortedMap { } } +impl, V: HashStable, CTX> HashStable for SortedMap { + #[inline] + fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + self.data.hash_stable(ctx, hasher); + } +} + #[cfg(test)] mod tests; diff --git a/compiler/rustc_data_structures/src/sorted_map/index_map.rs b/compiler/rustc_data_structures/src/sorted_map/index_map.rs index 1395bb16e8..61c7239c55 100644 --- a/compiler/rustc_data_structures/src/sorted_map/index_map.rs +++ b/compiler/rustc_data_structures/src/sorted_map/index_map.rs @@ -34,39 +34,47 @@ pub struct SortedIndexMultiMap { } impl SortedIndexMultiMap { + #[inline] pub fn new() -> Self { SortedIndexMultiMap { items: IndexVec::new(), idx_sorted_by_item_key: Vec::new() } } + #[inline] pub fn len(&self) -> usize { self.items.len() } + #[inline] pub fn is_empty(&self) -> bool { self.items.is_empty() } /// Returns an iterator over the items in the map in insertion order. + #[inline] 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. + #[inline] 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. + #[inline] 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. + #[inline] 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. + #[inline] pub fn get(&self, idx: I) -> Option<&(K, V)> { self.items.get(idx) } @@ -75,7 +83,8 @@ impl SortedIndexMultiMap { /// /// If there are multiple items that are equivalent to `key`, they will be yielded in /// insertion order. - pub fn get_by_key(&self, key: K) -> impl Iterator { + #[inline] + pub fn get_by_key(&'a self, key: K) -> impl 'a + Iterator { self.get_by_key_enumerated(key).map(|(_, v)| v) } @@ -84,7 +93,8 @@ impl SortedIndexMultiMap { /// /// 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: K) -> impl Iterator { + #[inline] + pub fn get_by_key_enumerated(&'a self, key: K) -> impl '_ + Iterator { let lower_bound = self.idx_sorted_by_item_key.partition_point(|&i| self.items[i].0 < key); self.idx_sorted_by_item_key[lower_bound..].iter().map_while(move |&i| { let (k, v) = &self.items[i]; diff --git a/compiler/rustc_data_structures/src/sso/map.rs b/compiler/rustc_data_structures/src/sso/map.rs index d4274e99f1..2de05cd4e5 100644 --- a/compiler/rustc_data_structures/src/sso/map.rs +++ b/compiler/rustc_data_structures/src/sso/map.rs @@ -257,7 +257,11 @@ impl SsoHashMap { pub fn remove(&mut self, key: &K) -> Option { match self { SsoHashMap::Array(array) => { - array.iter().position(|(k, _v)| k == key).map(|index| array.swap_remove(index).1) + 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), } @@ -268,7 +272,11 @@ impl SsoHashMap { pub fn remove_entry(&mut self, key: &K) -> Option<(K, V)> { match self { SsoHashMap::Array(array) => { - array.iter().position(|(k, _v)| k == key).map(|index| array.swap_remove(index)) + 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), } @@ -415,14 +423,14 @@ impl IntoIterator for SsoHashMap { /// adapts Item of array reference iterator to Item of hashmap reference iterator. #[inline(always)] -fn adapt_array_ref_it(pair: &(K, V)) -> (&K, &V) { +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: &mut (K, V)) -> (&K, &mut V) { +fn adapt_array_mut_it(pair: &'a mut (K, V)) -> (&'a K, &'a mut V) { let (a, b) = pair; (a, b) } diff --git a/compiler/rustc_data_structures/src/sso/set.rs b/compiler/rustc_data_structures/src/sso/set.rs index f71522d371..29baf4e1dd 100644 --- a/compiler/rustc_data_structures/src/sso/set.rs +++ b/compiler/rustc_data_structures/src/sso/set.rs @@ -75,7 +75,7 @@ impl SsoHashSet { /// An iterator visiting all elements in arbitrary order. /// The iterator element type is `&'a T`. #[inline] - pub fn iter(&self) -> impl Iterator { + pub fn iter(&'a self) -> impl Iterator { self.into_iter() } diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs index 2e992e7622..f800ec6a6a 100644 --- a/compiler/rustc_data_structures/src/stable_hasher.rs +++ b/compiler/rustc_data_structures/src/stable_hasher.rs @@ -229,14 +229,14 @@ impl HashStable for ::std::num::NonZeroUsize { impl HashStable for f32 { fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - let val: u32 = self.to_bits(); + 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 = self.to_bits(); + let val: u64 = unsafe { ::std::mem::transmute(*self) }; val.hash_stable(ctx, hasher); } } @@ -301,6 +301,13 @@ impl, CTX> HashStable for [T] { } } +impl HashStable for [u8] { + fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + self.len().hash_stable(ctx, hasher); + hasher.write(self); + } +} + impl, CTX> HashStable for Vec { #[inline] fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { diff --git a/compiler/rustc_data_structures/src/stack.rs b/compiler/rustc_data_structures/src/stack.rs index ba22c7f9b9..a4964b7aa0 100644 --- a/compiler/rustc_data_structures/src/stack.rs +++ b/compiler/rustc_data_structures/src/stack.rs @@ -5,7 +5,6 @@ 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. -#[allow(clippy::identity_op)] const STACK_PER_RECURSION: usize = 1 * 1024 * 1024; // 1MB /// Grows the stack on demand to prevent stack overflow. Call this in strategic locations diff --git a/compiler/rustc_data_structures/src/tiny_list.rs b/compiler/rustc_data_structures/src/tiny_list.rs index 9e605ea2d9..9b07f86846 100644 --- a/compiler/rustc_data_structures/src/tiny_list.rs +++ b/compiler/rustc_data_structures/src/tiny_list.rs @@ -48,7 +48,7 @@ impl TinyList { #[inline] pub fn contains(&self, data: &T) -> bool { let mut elem = self.head.as_ref(); - while let Some(e) = elem { + while let Some(ref e) = elem { if &e.data == data { return true; } diff --git a/compiler/rustc_data_structures/src/vec_linked_list.rs b/compiler/rustc_data_structures/src/vec_linked_list.rs index ce60d40b24..1cf030d852 100644 --- a/compiler/rustc_data_structures/src/vec_linked_list.rs +++ b/compiler/rustc_data_structures/src/vec_linked_list.rs @@ -2,8 +2,8 @@ use rustc_index::vec::{Idx, IndexVec}; pub fn iter( first: Option, - links: &Ls, -) -> impl Iterator + '_ + links: &'a Ls, +) -> impl Iterator + 'a where Ls: Links, { diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 9a57ec9914..6ff9434114 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -267,6 +267,7 @@ fn run_compiler( None, compiler.output_dir(), compiler.output_file(), + compiler.temps_dir(), ); if should_stop == Compilation::Stop { @@ -295,6 +296,7 @@ fn run_compiler( Some(compiler.input()), compiler.output_dir(), compiler.output_file(), + compiler.temps_dir(), ) .and_then(|| { RustcDefaultCalls::list_metadata( @@ -647,6 +649,7 @@ impl RustcDefaultCalls { input: Option<&Input>, odir: &Option, ofile: &Option, + temps_dir: &Option, ) -> Compilation { use rustc_session::config::PrintRequest::*; // PrintRequest::NativeStaticLibs is special - printed during linking @@ -685,7 +688,7 @@ impl RustcDefaultCalls { }); let attrs = attrs.as_ref().unwrap(); let t_outputs = rustc_interface::util::build_output_filenames( - input, odir, ofile, attrs, sess, + input, odir, ofile, temps_dir, attrs, sess, ); let id = rustc_session::output::find_crate_name(sess, attrs, input); if *req == PrintRequest::CrateName { @@ -733,7 +736,12 @@ impl RustcDefaultCalls { println!("{}", cfg); } } - RelocationModels | CodeModels | TlsModels | TargetCPUs | TargetFeatures => { + RelocationModels + | CodeModels + | TlsModels + | TargetCPUs + | StackProtectorStrategies + | TargetFeatures => { codegen_backend.print(*req, sess); } // Any output here interferes with Cargo's parsing of other printed output diff --git a/compiler/rustc_driver/src/pretty.rs b/compiler/rustc_driver/src/pretty.rs index 8e8bea9525..2e9050dd67 100644 --- a/compiler/rustc_driver/src/pretty.rs +++ b/compiler/rustc_driver/src/pretty.rs @@ -59,23 +59,23 @@ where } fn call_with_pp_support_hir(ppmode: &PpHirMode, tcx: TyCtxt<'_>, f: F) -> A where - F: FnOnce(&dyn HirPrinterSupport<'_>, &hir::Crate<'_>) -> A, + F: FnOnce(&dyn HirPrinterSupport<'_>, hir_map::Map<'_>) -> A, { match *ppmode { PpHirMode::Normal => { let annotation = NoAnn { sess: tcx.sess, tcx: Some(tcx) }; - f(&annotation, tcx.hir().krate()) + f(&annotation, tcx.hir()) } PpHirMode::Identified => { let annotation = IdentifiedAnnotation { sess: tcx.sess, tcx: Some(tcx) }; - f(&annotation, tcx.hir().krate()) + f(&annotation, tcx.hir()) } PpHirMode::Typed => { abort_on_err(tcx.analysis(()), tcx.sess); let annotation = TypedAnnotation { tcx, maybe_typeck_results: Cell::new(None) }; - tcx.dep_graph.with_ignore(|| f(&annotation, tcx.hir().krate())) + tcx.dep_graph.with_ignore(|| f(&annotation, tcx.hir())) } } } @@ -443,17 +443,27 @@ pub fn print_after_hir_lowering<'tcx>( format!("{:#?}", krate) } - Hir(s) => call_with_pp_support_hir(&s, tcx, move |annotation, krate| { + Hir(s) => call_with_pp_support_hir(&s, tcx, move |annotation, hir_map| { debug!("pretty printing HIR {:?}", s); let sess = annotation.sess(); let sm = sess.source_map(); - pprust_hir::print_crate(sm, krate, src_name, src, annotation.pp_ann()) + let attrs = |id| hir_map.attrs(id); + pprust_hir::print_crate( + sm, + hir_map.root_module(), + src_name, + src, + &attrs, + annotation.pp_ann(), + ) }), - HirTree => call_with_pp_support_hir(&PpHirMode::Normal, tcx, move |_annotation, krate| { - debug!("pretty printing HIR tree"); - format!("{:#?}", krate) - }), + HirTree => { + call_with_pp_support_hir(&PpHirMode::Normal, tcx, move |_annotation, hir_map| { + debug!("pretty printing HIR tree"); + format!("{:#?}", hir_map.krate()) + }) + } _ => unreachable!(), }; diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index 724e3f7fed..ce26ff6223 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -484,12 +484,13 @@ E0782: include_str!("./error_codes/E0782.md"), E0783: include_str!("./error_codes/E0783.md"), E0784: include_str!("./error_codes/E0784.md"), E0785: include_str!("./error_codes/E0785.md"), +E0786: include_str!("./error_codes/E0786.md"), ; // E0006, // merged with E0005 // E0008, // cannot bind by-move into a pattern guard -// E0019, merged into E0015 -// E0035, merged into E0087/E0089 -// E0036, merged into E0087/E0089 +// E0019, // merged into E0015 +// E0035, // merged into E0087/E0089 +// E0036, // merged into E0087/E0089 // E0068, // E0085, // E0086, @@ -504,8 +505,8 @@ E0785: include_str!("./error_codes/E0785.md"), // E0134, // E0135, // E0141, -// E0153, unused error code -// E0157, unused error code +// E0153, // unused error code +// E0157, // unused error code // E0159, // use of trait `{}` as struct constructor // E0163, // merged into E0071 // E0167, @@ -573,24 +574,24 @@ E0785: include_str!("./error_codes/E0785.md"), // between structures with the same definition // E0385, // {} in an aliasable location // E0402, // cannot use an outer type parameter in this context -// E0406, merged into 420 -// E0410, merged into 408 -// E0413, merged into 530 -// E0414, merged into 530 -// E0417, merged into 532 -// E0418, merged into 532 -// E0419, merged into 531 -// E0420, merged into 532 -// E0421, merged into 531 -// E0427, merged into 530 +// E0406, // merged into 420 +// E0410, // merged into 408 +// E0413, // merged into 530 +// E0414, // merged into 530 +// E0417, // merged into 532 +// E0418, // merged into 532 +// E0419, // merged into 531 +// E0420, // merged into 532 +// E0421, // merged into 531 +// E0427, // merged into 530 // E0456, // plugin `..` is not available for triple `..` E0457, // plugin `..` only found in rlib format, but must be available... E0460, // found possibly newer version of crate `..` E0461, // couldn't find crate `..` with expected target triple .. E0462, // found staticlib `..` instead of rlib or dylib E0465, // multiple .. candidates for `..` found -// E0467, removed -// E0470, removed +// E0467, // removed +// E0470, // removed // E0471, // constant evaluation error (in pattern) E0472, // llvm_asm! is unsupported on this target // E0473, // dereference of reference outside its lifetime @@ -610,8 +611,7 @@ E0785: include_str!("./error_codes/E0785.md"), E0490, // a value of type `..` is borrowed for too long E0514, // metadata version mismatch E0519, // local crate and dependency have same (crate-name, disambiguator) - // two dependencies have same (crate-name, disambiguator) but different SVH - E0523, + E0523, // two dependencies have same (crate-name, disambiguator) but different SVH // E0526, // shuffle indices are not constant // E0540, // multiple rustc_deprecated attributes // E0548, // replaced with a generic attribute input check @@ -638,7 +638,7 @@ E0785: include_str!("./error_codes/E0785.md"), E0711, // a feature has been declared with conflicting stability attributes E0717, // rustc_promotable without stability attribute // E0721, // `await` keyword -// E0723, unstable feature in `const` context +// 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" { ... }`. E0772, // `'static' obligation coming from `impl dyn Trait {}` or `impl Foo for dyn Bar {}`. diff --git a/compiler/rustc_error_codes/src/error_codes/E0206.md b/compiler/rustc_error_codes/src/error_codes/E0206.md index da53b671ad..4405a2149c 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0206.md +++ b/compiler/rustc_error_codes/src/error_codes/E0206.md @@ -4,15 +4,12 @@ enum. Erroneous code example: ```compile_fail,E0206 -type Foo = [u8; 256]; -impl Copy for Foo { } // error! - #[derive(Copy, Clone)] struct Bar; impl Copy for &'static mut Bar { } // error! ``` -You can only implement `Copy` for a struct or an enum. Both of the previous -examples will fail, because neither `[u8; 256]` nor `&'static mut Bar` -(mutable reference to `Bar`) is a struct or enum. +You can only implement `Copy` for a struct or an enum. +The previous example will fail because `&'static mut Bar` +is not a struct or enum. diff --git a/compiler/rustc_error_codes/src/error_codes/E0482.md b/compiler/rustc_error_codes/src/error_codes/E0482.md index 58ebf43cc9..ad363816e1 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0482.md +++ b/compiler/rustc_error_codes/src/error_codes/E0482.md @@ -1,8 +1,10 @@ +#### Note: this error code is no longer emitted by the compiler. + A lifetime of a returned value does not outlive the function call. Erroneous code example: -```compile_fail,E0482 +```compile_fail,E0700 fn prefix<'a>( words: impl Iterator ) -> impl Iterator { // error! @@ -41,7 +43,7 @@ fn prefix( A similar lifetime problem might arise when returning closures: -```compile_fail,E0482 +```compile_fail,E0700 fn foo( x: &mut Vec ) -> impl FnMut(&mut Vec) -> &[i32] { // error! diff --git a/compiler/rustc_error_codes/src/error_codes/E0637.md b/compiler/rustc_error_codes/src/error_codes/E0637.md index d9068950bd..62d5565df2 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0637.md +++ b/compiler/rustc_error_codes/src/error_codes/E0637.md @@ -1,35 +1,51 @@ -An underscore `_` character has been used as the identifier for a lifetime. +`'_` lifetime name or `&T` without an explicit lifetime name has been used +on illegal place. Erroneous code example: ```compile_fail,E0106,E0637 -fn longest<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str { - //^^ `'_` is a reserved lifetime name +fn underscore_lifetime<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str { + //^^ `'_` is a reserved lifetime name if str1.len() > str2.len() { str1 } else { str2 } } + +fn and_without_explicit_lifetime() +where + T: Into<&u32>, + //^ `&` without an explicit lifetime name +{ +} ``` -`'_`, cannot be used as a lifetime identifier because it is a reserved for the -anonymous lifetime. To fix this, use a lowercase letter such as 'a, or a series -of lowercase letters such as `'foo`. For more information, see [the -book][bk-no]. For more information on using the anonymous lifetime in rust -nightly, see [the nightly book][bk-al]. +First, `'_` cannot be used as a lifetime identifier in some places +because it is a reserved for the anonymous lifetime. Second, `&T` +without an explicit lifetime name cannot also be used in some places. +To fix them, use a lowercase letter such as `'a`, or a series +of lowercase letters such as `'foo`. For more information about lifetime +identifier, see [the book][bk-no]. For more information on using +the anonymous lifetime in Rust 2018, see [the Rust 2018 blog post][blog-al]. Corrected example: ``` -fn longest<'a>(str1: &'a str, str2: &'a str) -> &'a str { +fn underscore_lifetime<'a>(str1: &'a str, str2: &'a str) -> &'a str { if str1.len() > str2.len() { str1 } else { str2 } } + +fn and_without_explicit_lifetime<'foo, T>() +where + T: Into<&'foo u32>, +{ +} ``` [bk-no]: https://doc.rust-lang.org/book/appendix-02-operators.html#non-operator-symbols -[bk-al]: https://doc.rust-lang.org/nightly/edition-guide/rust-2018/ownership-and-lifetimes/the-anonymous-lifetime.html +[blog-al]: https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html#more-lifetime-elision-rules diff --git a/compiler/rustc_error_codes/src/error_codes/E0786.md b/compiler/rustc_error_codes/src/error_codes/E0786.md new file mode 100644 index 0000000000..4a9635bf51 --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0786.md @@ -0,0 +1,14 @@ +A metadata file was invalid. + +Erroneous code example: + +```ignore (needs extern files) +use ::foo; // error: found invalid metadata files for crate `foo` +``` + +When loading crates, each crate must have a valid metadata file. +Invalid files could be caused by filesystem corruption, +an IO error while reading the file, or (rarely) a bug in the compiler itself. + +Consider deleting the file and recreating it, +or reporting a bug against the compiler. diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index 1eb497460e..9db8f75139 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -66,7 +66,7 @@ fn source_string(file: Lrc, line: &Line) -> String { /// 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::Bug | Level::Fatal | Level::Error { .. } => AnnotationType::Error, Level::Warning => AnnotationType::Warning, Level::Note => AnnotationType::Note, Level::Help => AnnotationType::Help, diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 41a73268f4..e5116cd8df 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -114,7 +114,7 @@ impl Diagnostic { pub fn is_error(&self) -> bool { match self.level { - Level::Bug | Level::Fatal | Level::Error | Level::FailureNote => true, + Level::Bug | Level::Fatal | Level::Error { .. } | Level::FailureNote => true, Level::Warning | Level::Note | Level::Help | Level::Cancelled | Level::Allow => false, } @@ -465,10 +465,14 @@ impl Diagnostic { suggestions: impl Iterator, applicability: Applicability, ) -> &mut Self { + let mut suggestions: Vec<_> = suggestions.collect(); + suggestions.sort(); + let substitutions = suggestions + .into_iter() + .map(|snippet| Substitution { parts: vec![SubstitutionPart { snippet, span: sp }] }) + .collect(); self.suggestions.push(CodeSuggestion { - substitutions: suggestions - .map(|snippet| Substitution { parts: vec![SubstitutionPart { snippet, span: sp }] }) - .collect(), + substitutions, msg: msg.to_owned(), style: SuggestionStyle::ShowCode, applicability, diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 7fa29bd33c..d64a589bd9 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -15,7 +15,7 @@ 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, SubstitutionHighlight, + CodeSuggestion, Diagnostic, DiagnosticId, Handler, Level, SubDiagnostic, SubstitutionHighlight, SuggestionStyle, }; @@ -449,11 +449,7 @@ pub trait Emitter { span: &mut MultiSpan, children: &mut Vec, ) { - let source_map = if let Some(ref sm) = source_map { - sm - } else { - return; - }; + let Some(source_map) = source_map else { return }; debug!("fix_multispans_in_extern_macros: before: span={:?} children={:?}", span, children); self.fix_multispan_in_extern_macros(source_map, span); for child in children.iter_mut() { @@ -527,14 +523,27 @@ impl Emitter for EmitterWriter { } } -/// An emitter that does nothing when emitting a diagnostic. -pub struct SilentEmitter; +/// An emitter that does nothing when emitting a non-fatal diagnostic. +/// Fatal diagnostics are forwarded to `fatal_handler` to avoid silent +/// failures of rustc, as witnessed e.g. in issue #89358. +pub struct SilentEmitter { + pub fatal_handler: Handler, + pub fatal_note: Option, +} impl Emitter for SilentEmitter { fn source_map(&self) -> Option<&Lrc> { None } - fn emit_diagnostic(&mut self, _: &Diagnostic) {} + fn emit_diagnostic(&mut self, d: &Diagnostic) { + if d.level == Level::Fatal { + let mut d = d.clone(); + if let Some(ref note) = self.fatal_note { + d.note(note); + } + self.fatal_handler.emit_diagnostic(&d); + } + } } /// Maximum number of lines we will print for a multiline suggestion; arbitrary. @@ -721,7 +730,7 @@ impl EmitterWriter { } let source_string = match file.get_line(line.line_index - 1) { - Some(s) => replace_tabs(&*s), + Some(s) => normalize_whitespace(&*s), None => return Vec::new(), }; @@ -1257,22 +1266,37 @@ impl EmitterWriter { } self.msg_to_buffer(&mut buffer, msg, max_line_num_len, "note", None); } else { + let mut label_width = 0; // The failure note level itself does not provide any useful diagnostic information if *level != Level::FailureNote { buffer.append(0, level.to_str(), Style::Level(*level)); + label_width += level.to_str().len(); } // only render error codes, not lint codes if let Some(DiagnosticId::Error(ref code)) = *code { buffer.append(0, "[", Style::Level(*level)); buffer.append(0, &code, Style::Level(*level)); buffer.append(0, "]", Style::Level(*level)); + label_width += 2 + code.len(); } let header_style = if is_secondary { Style::HeaderMsg } else { Style::MainHeaderMsg }; if *level != Level::FailureNote { buffer.append(0, ": ", header_style); + label_width += 2; } for &(ref text, _) in msg.iter() { - buffer.append(0, &replace_tabs(text), header_style); + // Account for newlines to align output to its label. + for (line, text) in normalize_whitespace(text).lines().enumerate() { + buffer.append( + 0 + line, + &format!( + "{}{}", + if line == 0 { String::new() } else { " ".repeat(label_width) }, + text + ), + header_style, + ); + } } } @@ -1526,7 +1550,7 @@ impl EmitterWriter { self.draw_line( &mut buffer, - &replace_tabs(&unannotated_line), + &normalize_whitespace(&unannotated_line), annotated_file.lines[line_idx + 1].line_index - 1, last_buffer_line_num, width_offset, @@ -1648,7 +1672,7 @@ impl EmitterWriter { buffer.puts( row_num - 1, max_line_num_len + 3, - &replace_tabs( + &normalize_whitespace( &*file_lines .file .get_line(file_lines.lines[line_pos].line_index) @@ -1674,7 +1698,7 @@ impl EmitterWriter { } // print the suggestion - buffer.append(row_num, &replace_tabs(line), Style::NoStyle); + buffer.append(row_num, &normalize_whitespace(line), Style::NoStyle); // Colorize addition/replacements with green. for &SubstitutionHighlight { start, end } in highlight_parts { @@ -2057,6 +2081,7 @@ fn num_decimal_digits(num: usize) -> usize { // We replace some characters so the CLI output is always consistent and underlines aligned. const OUTPUT_REPLACEMENTS: &[(char, &str)] = &[ ('\t', " "), // We do our own tab replacement + ('\u{200D}', ""), // Replace ZWJ with nothing for consistent terminal output of grapheme clusters. ('\u{202A}', ""), // The following unicode text flow control characters are inconsistently ('\u{202B}', ""), // supported accross CLIs and can cause confusion due to the bytes on disk ('\u{202D}', ""), // not corresponding to the visible source code, so we replace them always. @@ -2068,7 +2093,7 @@ const OUTPUT_REPLACEMENTS: &[(char, &str)] = &[ ('\u{2069}', ""), ]; -fn replace_tabs(str: &str) -> String { +fn normalize_whitespace(str: &str) -> String { let mut s = str.to_string(); for (c, replacement) in OUTPUT_REPLACEMENTS { s = s.replace(*c, replacement); diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 9b2094adb1..bb3d3a415e 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -6,8 +6,9 @@ #![feature(crate_visibility_modifier)] #![feature(backtrace)] #![feature(if_let_guard)] -#![feature(format_args_capture)] +#![cfg_attr(bootstrap, feature(format_args_capture))] #![feature(iter_zip)] +#![feature(let_else)] #![feature(nll)] #[macro_use] @@ -410,6 +411,8 @@ pub struct Handler { /// as well as inconsistent state observation. struct HandlerInner { flags: HandlerFlags, + /// The number of lint errors that have been emitted. + lint_err_count: usize, /// The number of errors that have been emitted, including duplicates. /// /// This is not necessarily the count that's reported to the user once @@ -549,6 +552,7 @@ impl Handler { flags, inner: Lock::new(HandlerInner { flags, + lint_err_count: 0, err_count: 0, warn_count: 0, deduplicated_err_count: 0, @@ -725,7 +729,13 @@ impl Handler { /// Construct a builder at the `Error` level with the `msg`. // FIXME: This method should be removed (every error should have an associated error code). pub fn struct_err(&self, msg: &str) -> DiagnosticBuilder<'_> { - DiagnosticBuilder::new(self, Level::Error, msg) + DiagnosticBuilder::new(self, Level::Error { lint: false }, msg) + } + + /// This should only be used by `rustc_middle::lint::struct_lint_level`. Do not use it for hard errors. + #[doc(hidden)] + pub fn struct_err_lint(&self, msg: &str) -> DiagnosticBuilder<'_> { + DiagnosticBuilder::new(self, Level::Error { lint: true }, msg) } /// Construct a builder at the `Error` level with the `msg` and the `code`. @@ -789,11 +799,14 @@ impl Handler { } pub fn span_err(&self, span: impl Into, msg: &str) { - self.emit_diag_at_span(Diagnostic::new(Error, msg), span); + self.emit_diag_at_span(Diagnostic::new(Error { lint: false }, msg), span); } pub fn span_err_with_code(&self, span: impl Into, msg: &str, code: DiagnosticId) { - self.emit_diag_at_span(Diagnostic::new_with_code(Error, Some(code), msg), span); + self.emit_diag_at_span( + Diagnostic::new_with_code(Error { lint: false }, Some(code), msg), + span, + ); } pub fn span_warn(&self, span: impl Into, msg: &str) { @@ -861,6 +874,9 @@ impl Handler { pub fn has_errors(&self) -> bool { self.inner.borrow().has_errors() } + pub fn has_errors_or_lint_errors(&self) -> bool { + self.inner.borrow().has_errors_or_lint_errors() + } pub fn has_errors_or_delayed_span_bugs(&self) -> bool { self.inner.borrow().has_errors_or_delayed_span_bugs() } @@ -978,7 +994,11 @@ impl HandlerInner { } } if diagnostic.is_error() { - self.bump_err_count(); + if matches!(diagnostic.level, Level::Error { lint: true }) { + self.bump_lint_err_count(); + } else { + self.bump_err_count(); + } } else { self.bump_warn_count(); } @@ -1072,11 +1092,14 @@ impl HandlerInner { fn has_errors(&self) -> bool { self.err_count() > 0 } + fn has_errors_or_lint_errors(&self) -> bool { + self.has_errors() || self.lint_err_count > 0 + } fn has_errors_or_delayed_span_bugs(&self) -> bool { self.has_errors() || !self.delayed_span_bugs.is_empty() } fn has_any_message(&self) -> bool { - self.err_count() > 0 || self.warn_count > 0 + self.err_count() > 0 || self.lint_err_count > 0 || self.warn_count > 0 } fn abort_if_errors(&mut self) { @@ -1130,7 +1153,7 @@ impl HandlerInner { } fn err(&mut self, msg: &str) { - self.emit_error(Error, msg); + self.emit_error(Error { lint: false }, msg); } /// Emit an error; level should be `Error` or `Fatal`. @@ -1166,6 +1189,11 @@ impl HandlerInner { } } + fn bump_lint_err_count(&mut self) { + self.lint_err_count += 1; + self.panic_if_treat_err_as_bug(); + } + fn bump_err_count(&mut self) { self.err_count += 1; self.panic_if_treat_err_as_bug(); @@ -1209,7 +1237,10 @@ impl DelayedDiagnostic { pub enum Level { Bug, Fatal, - Error, + Error { + /// If this error comes from a lint, don't abort compilation even when abort_if_errors() is called. + lint: bool, + }, Warning, Note, Help, @@ -1228,7 +1259,7 @@ impl Level { fn color(self) -> ColorSpec { let mut spec = ColorSpec::new(); match self { - Bug | Fatal | Error => { + Bug | Fatal | Error { .. } => { spec.set_fg(Some(Color::Red)).set_intense(true); } Warning => { @@ -1249,7 +1280,7 @@ impl Level { pub fn to_str(self) -> &'static str { match self { Bug => "error: internal compiler error", - Fatal | Error => "error", + Fatal | Error { .. } => "error", Warning => "warning", Note => "note", Help => "help", diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index f548e2848a..89dbd64ed8 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -383,7 +383,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { Unsafe::No, ModKind::Loaded(krate.items, Inline::Yes, krate.span) ), - ident: Ident::invalid(), + ident: Ident::empty(), id: ast::DUMMY_NODE_ID, vis: ast::Visibility { span: krate.span.shrink_to_lo(), @@ -447,9 +447,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let mut undetermined_invocations = Vec::new(); let (mut progress, mut force) = (false, !self.monotonic); loop { - let (invoc, ext) = if let Some(invoc) = invocations.pop() { - invoc - } else { + let Some((invoc, ext)) = invocations.pop() else { self.resolve_imports(); if undetermined_invocations.is_empty() { break; @@ -1426,7 +1424,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { _ => unreachable!(), }) } - ast::ItemKind::Mod(_, ref mut mod_kind) if ident != Ident::invalid() => { + ast::ItemKind::Mod(_, ref mut mod_kind) if ident != Ident::empty() => { let (file_path, dir_path, dir_ownership) = match mod_kind { ModKind::Loaded(_, inline, _) => { // Inline `mod foo { ... }`, but we still need to push directories. @@ -1508,7 +1506,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { _ => { item.attrs = attrs; // The crate root is special - don't assign an ID to it. - if !(matches!(item.kind, ast::ItemKind::Mod(..)) && ident == Ident::invalid()) { + if !(matches!(item.kind, ast::ItemKind::Mod(..)) && ident == Ident::empty()) { assign_id!(self, &mut item.id, || noop_flat_map_item(item, self)) } else { noop_flat_map_item(item, self) diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index 6dfeb047ec..4e84a9df6c 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -1,9 +1,10 @@ #![feature(crate_visibility_modifier)] #![feature(decl_macro)] #![feature(destructuring_assignment)] -#![feature(format_args_capture)] +#![cfg_attr(bootstrap, feature(format_args_capture))] #![feature(if_let_guard)] #![feature(iter_zip)] +#![feature(let_else)] #![feature(proc_macro_diagnostic)] #![feature(proc_macro_internals)] #![feature(proc_macro_span)] diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index 363cc72b52..dedc6c618b 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -204,7 +204,7 @@ fn parse_tree( pprust::token_to_string(&token), ); sess.span_diagnostic.span_err(token.span, &msg); - TokenTree::MetaVar(token.span, Ident::invalid()) + TokenTree::MetaVar(token.span, Ident::empty()) } // There are no more tokens. Just return the `$` we already have. diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 9ed5c8b8ff..88e1623012 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -19,9 +19,7 @@ use std::mem; struct Marker(LocalExpnId, Transparency); impl MutVisitor for Marker { - fn token_visiting_enabled(&self) -> bool { - true - } + const VISIT_TOKENS: bool = true; fn visit_span(&mut self, span: &mut Span) { *span = span.apply_mark(self.0.to_expn_id(), self.1) @@ -116,10 +114,8 @@ pub(super) fn transcribe<'a>( loop { // Look at the last frame on the stack. - let tree = if let Some(tree) = stack.last_mut().unwrap().next() { - // If it still has a TokenTree we have not looked at yet, use that tree. - tree - } else { + // If it still has a TokenTree we have not looked at yet, use that tree. + let Some(tree) = stack.last_mut().unwrap().next() else { // This else-case never produces a value for `tree` (it `continue`s or `return`s). // Otherwise, if we have just reached the end of a sequence and we can keep repeating, @@ -190,9 +186,7 @@ pub(super) fn transcribe<'a>( LockstepIterSize::Constraint(len, _) => { // We do this to avoid an extra clone above. We know that this is a // sequence already. - let (sp, seq) = if let mbe::TokenTree::Sequence(sp, seq) = seq { - (sp, seq) - } else { + let mbe::TokenTree::Sequence(sp, seq) = seq else { unreachable!() }; diff --git a/compiler/rustc_expand/src/mut_visit/tests.rs b/compiler/rustc_expand/src/mut_visit/tests.rs index 0068539fb3..8974d45b4d 100644 --- a/compiler/rustc_expand/src/mut_visit/tests.rs +++ b/compiler/rustc_expand/src/mut_visit/tests.rs @@ -15,9 +15,8 @@ fn print_crate_items(krate: &ast::Crate) -> String { struct ToZzIdentMutVisitor; impl MutVisitor for ToZzIdentMutVisitor { - fn token_visiting_enabled(&self) -> bool { - true - } + const VISIT_TOKENS: bool = true; + fn visit_ident(&mut self, ident: &mut Ident) { *ident = Ident::from_str("zz"); } diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs index 8e78fcbb8d..12b6bc7bbe 100644 --- a/compiler/rustc_expand/src/placeholders.rs +++ b/compiler/rustc_expand/src/placeholders.rs @@ -23,7 +23,7 @@ pub fn placeholder( } } - let ident = Ident::invalid(); + let ident = Ident::empty(); let attrs = Vec::new(); let vis = vis.unwrap_or(ast::Visibility { span: DUMMY_SP, diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs index 3f84979ac0..42c17a60a5 100644 --- a/compiler/rustc_expand/src/proc_macro.rs +++ b/compiler/rustc_expand/src/proc_macro.rs @@ -24,8 +24,9 @@ impl base::ProcMacro for BangProcMacro { span: Span, input: TokenStream, ) -> Result { + let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace; let server = proc_macro_server::Rustc::new(ecx); - self.client.run(&EXEC_STRATEGY, server, input, ecx.ecfg.proc_macro_backtrace).map_err(|e| { + self.client.run(&EXEC_STRATEGY, server, input, proc_macro_backtrace).map_err(|e| { let mut err = ecx.struct_span_err(span, "proc macro panicked"); if let Some(s) = e.as_str() { err.help(&format!("message: {}", s)); @@ -48,9 +49,10 @@ impl base::AttrProcMacro for AttrProcMacro { annotation: TokenStream, annotated: TokenStream, ) -> Result { + let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace; let server = proc_macro_server::Rustc::new(ecx); self.client - .run(&EXEC_STRATEGY, server, annotation, annotated, ecx.ecfg.proc_macro_backtrace) + .run(&EXEC_STRATEGY, server, annotation, annotated, proc_macro_backtrace) .map_err(|e| { let mut err = ecx.struct_span_err(span, "custom attribute panicked"); if let Some(s) = e.as_str() { @@ -97,19 +99,19 @@ impl MultiItemModifier for ProcMacroDerive { nt_to_tokenstream(&item, &ecx.sess.parse_sess, CanSynthesizeMissingTokens::No) }; + let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace; let server = proc_macro_server::Rustc::new(ecx); - let stream = - match self.client.run(&EXEC_STRATEGY, server, input, ecx.ecfg.proc_macro_backtrace) { - Ok(stream) => stream, - Err(e) => { - let mut err = ecx.struct_span_err(span, "proc-macro derive panicked"); - if let Some(s) = e.as_str() { - err.help(&format!("message: {}", s)); - } - err.emit(); - return ExpandResult::Ready(vec![]); + let stream = match self.client.run(&EXEC_STRATEGY, server, input, proc_macro_backtrace) { + Ok(stream) => stream, + Err(e) => { + let mut err = ecx.struct_span_err(span, "proc-macro derive panicked"); + if let Some(s) = e.as_str() { + err.help(&format!("message: {}", s)); } - }; + err.emit(); + return ExpandResult::Ready(vec![]); + } + }; let error_count_before = ecx.sess.parse_sess.span_diagnostic.err_count(); let mut parser = diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 5cb9719876..fa9e98be9e 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -1,4 +1,4 @@ -use crate::base::{ExtCtxt, ResolverExpand}; +use crate::base::ExtCtxt; use rustc_ast as ast; use rustc_ast::token::{self, Nonterminal, NtIdent}; @@ -7,7 +7,7 @@ use rustc_ast::tokenstream::{DelimSpan, Spacing::*, TokenStream, TreeAndSpacing} use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; -use rustc_errors::Diagnostic; +use rustc_errors::{Diagnostic, PResult}; use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT; use rustc_lint_defs::BuiltinLintDiagnostics; use rustc_parse::lexer::nfc_normalize; @@ -53,11 +53,11 @@ impl ToInternal for Delimiter { } } -impl FromInternal<(TreeAndSpacing, &'_ mut Vec, &mut Rustc<'_>)> +impl FromInternal<(TreeAndSpacing, &'_ mut Vec, &mut Rustc<'_, '_>)> for TokenTree { fn from_internal( - ((tree, spacing), stack, rustc): (TreeAndSpacing, &mut Vec, &mut Rustc<'_>), + ((tree, spacing), stack, rustc): (TreeAndSpacing, &mut Vec, &mut Rustc<'_, '_>), ) -> Self { use rustc_ast::token::*; @@ -146,10 +146,10 @@ impl FromInternal<(TreeAndSpacing, &'_ mut Vec, &mut Rustc<'_>)> SingleQuote => op!('\''), Ident(name, false) if name == kw::DollarCrate => tt!(Ident::dollar_crate()), - Ident(name, is_raw) => tt!(Ident::new(rustc.sess, name, is_raw)), + Ident(name, is_raw) => tt!(Ident::new(rustc.sess(), name, is_raw)), Lifetime(name) => { let ident = symbol::Ident::new(name, span).without_first_quote(); - stack.push(tt!(Ident::new(rustc.sess, ident.name, false))); + stack.push(tt!(Ident::new(rustc.sess(), ident.name, false))); tt!(Punct::new('\'', true)) } Literal(lit) => tt!(Literal { lit }), @@ -181,15 +181,15 @@ impl FromInternal<(TreeAndSpacing, &'_ mut Vec, &mut Rustc<'_>)> Interpolated(nt) if let Some((name, is_raw)) = ident_name_compatibility_hack(&nt, span, rustc) => { - TokenTree::Ident(Ident::new(rustc.sess, name.name, is_raw, name.span)) + TokenTree::Ident(Ident::new(rustc.sess(), name.name, is_raw, name.span)) } Interpolated(nt) => { - let stream = nt_to_tokenstream(&nt, rustc.sess, CanSynthesizeMissingTokens::No); + let stream = nt_to_tokenstream(&nt, rustc.sess(), CanSynthesizeMissingTokens::No); TokenTree::Group(Group { delimiter: Delimiter::None, stream, span: DelimSpan::from_single(span), - flatten: crate::base::pretty_printing_compatibility_hack(&nt, rustc.sess), + flatten: crate::base::pretty_printing_compatibility_hack(&nt, rustc.sess()), }) } @@ -273,7 +273,7 @@ impl ToInternal for TokenTree { impl ToInternal for Level { fn to_internal(self) -> rustc_errors::Level { match self { - Level::Error => rustc_errors::Level::Error, + Level::Error => rustc_errors::Level::Error { lint: false }, Level::Warning => rustc_errors::Level::Warning, Level::Note => rustc_errors::Level::Note, Level::Help => rustc_errors::Level::Help, @@ -355,38 +355,38 @@ pub struct Literal { span: Span, } -pub(crate) struct Rustc<'a> { - resolver: &'a dyn ResolverExpand, - sess: &'a ParseSess, +pub(crate) struct Rustc<'a, 'b> { + ecx: &'a mut ExtCtxt<'b>, def_site: Span, call_site: Span, mixed_site: Span, - span_debug: bool, krate: CrateNum, rebased_spans: FxHashMap, } -impl<'a> Rustc<'a> { - pub fn new(cx: &'a ExtCtxt<'_>) -> Self { - let expn_data = cx.current_expansion.id.expn_data(); +impl<'a, 'b> Rustc<'a, 'b> { + pub fn new(ecx: &'a mut ExtCtxt<'b>) -> Self { + let expn_data = ecx.current_expansion.id.expn_data(); Rustc { - resolver: cx.resolver, - sess: cx.parse_sess(), - def_site: cx.with_def_site_ctxt(expn_data.def_site), - call_site: cx.with_call_site_ctxt(expn_data.call_site), - mixed_site: cx.with_mixed_site_ctxt(expn_data.call_site), - span_debug: cx.ecfg.span_debug, + def_site: ecx.with_def_site_ctxt(expn_data.def_site), + call_site: ecx.with_call_site_ctxt(expn_data.call_site), + mixed_site: ecx.with_mixed_site_ctxt(expn_data.call_site), krate: expn_data.macro_def_id.unwrap().krate, rebased_spans: FxHashMap::default(), + ecx, } } + fn sess(&self) -> &ParseSess { + self.ecx.parse_sess() + } + fn lit(&mut self, kind: token::LitKind, symbol: Symbol, suffix: Option) -> Literal { Literal { lit: token::Lit::new(kind, symbol, suffix), span: server::Span::call_site(self) } } } -impl server::Types for Rustc<'_> { +impl server::Types for Rustc<'_, '_> { type FreeFunctions = FreeFunctions; type TokenStream = TokenStream; type TokenStreamBuilder = tokenstream::TokenStreamBuilder; @@ -401,17 +401,20 @@ impl server::Types for Rustc<'_> { type Span = Span; } -impl server::FreeFunctions for Rustc<'_> { +impl server::FreeFunctions for Rustc<'_, '_> { fn track_env_var(&mut self, var: &str, value: Option<&str>) { - self.sess.env_depinfo.borrow_mut().insert((Symbol::intern(var), value.map(Symbol::intern))); + self.sess() + .env_depinfo + .borrow_mut() + .insert((Symbol::intern(var), value.map(Symbol::intern))); } fn track_path(&mut self, path: &str) { - self.sess.file_depinfo.borrow_mut().insert(Symbol::intern(path)); + self.sess().file_depinfo.borrow_mut().insert(Symbol::intern(path)); } } -impl server::TokenStream for Rustc<'_> { +impl server::TokenStream for Rustc<'_, '_> { fn new(&mut self) -> Self::TokenStream { TokenStream::default() } @@ -422,13 +425,62 @@ impl server::TokenStream for Rustc<'_> { parse_stream_from_source_str( FileName::proc_macro_source_code(src), src.to_string(), - self.sess, + self.sess(), Some(self.call_site), ) } fn to_string(&mut self, stream: &Self::TokenStream) -> String { pprust::tts_to_string(stream) } + fn expand_expr(&mut self, stream: &Self::TokenStream) -> Result { + // Parse the expression from our tokenstream. + let expr: PResult<'_, _> = try { + let mut p = rustc_parse::stream_to_parser( + self.sess(), + stream.clone(), + Some("proc_macro expand expr"), + ); + let expr = p.parse_expr()?; + if p.token != token::Eof { + p.unexpected()?; + } + expr + }; + let expr = expr.map_err(|mut err| err.emit())?; + + // Perform eager expansion on the expression. + let expr = self + .ecx + .expander() + .fully_expand_fragment(crate::expand::AstFragment::Expr(expr)) + .make_expr(); + + // NOTE: For now, limit `expand_expr` to exclusively expand to literals. + // This may be relaxed in the future. + // We don't use `nt_to_tokenstream` as the tokenstream currently cannot + // be recovered in the general case. + match &expr.kind { + ast::ExprKind::Lit(l) => { + Ok(tokenstream::TokenTree::token(token::Literal(l.token), l.span).into()) + } + ast::ExprKind::Unary(ast::UnOp::Neg, e) => match &e.kind { + ast::ExprKind::Lit(l) => match l.token { + token::Lit { kind: token::Integer | token::Float, .. } => { + Ok(std::array::IntoIter::new([ + // FIXME: The span of the `-` token is lost when + // parsing, so we cannot faithfully recover it here. + tokenstream::TokenTree::token(token::BinOp(token::Minus), e.span), + tokenstream::TokenTree::token(token::Literal(l.token), l.span), + ]) + .collect()) + } + _ => Err(()), + }, + _ => Err(()), + }, + _ => Err(()), + } + } fn from_token_tree( &mut self, tree: TokenTree, @@ -440,7 +492,7 @@ impl server::TokenStream for Rustc<'_> { } } -impl server::TokenStreamBuilder for Rustc<'_> { +impl server::TokenStreamBuilder for Rustc<'_, '_> { fn new(&mut self) -> Self::TokenStreamBuilder { tokenstream::TokenStreamBuilder::new() } @@ -452,7 +504,7 @@ impl server::TokenStreamBuilder for Rustc<'_> { } } -impl server::TokenStreamIter for Rustc<'_> { +impl server::TokenStreamIter for Rustc<'_, '_> { fn next( &mut self, iter: &mut Self::TokenStreamIter, @@ -477,7 +529,7 @@ impl server::TokenStreamIter for Rustc<'_> { } } -impl server::Group for Rustc<'_> { +impl server::Group for Rustc<'_, '_> { fn new(&mut self, delimiter: Delimiter, stream: Self::TokenStream) -> Self::Group { Group { delimiter, @@ -506,7 +558,7 @@ impl server::Group for Rustc<'_> { } } -impl server::Punct for Rustc<'_> { +impl server::Punct for Rustc<'_, '_> { fn new(&mut self, ch: char, spacing: Spacing) -> Self::Punct { Punct::new(ch, spacing == Spacing::Joint, server::Span::call_site(self)) } @@ -524,9 +576,9 @@ impl server::Punct for Rustc<'_> { } } -impl server::Ident for Rustc<'_> { +impl server::Ident for Rustc<'_, '_> { fn new(&mut self, string: &str, span: Self::Span, is_raw: bool) -> Self::Ident { - Ident::new(self.sess, Symbol::intern(string), is_raw, span) + Ident::new(self.sess(), Symbol::intern(string), is_raw, span) } fn span(&mut self, ident: Self::Ident) -> Self::Span { ident.span @@ -536,10 +588,10 @@ impl server::Ident for Rustc<'_> { } } -impl server::Literal for Rustc<'_> { +impl server::Literal for Rustc<'_, '_> { fn from_str(&mut self, s: &str) -> Result { let name = FileName::proc_macro_source_code(s); - let mut parser = rustc_parse::new_parser_from_source_str(self.sess, name, s.to_owned()); + let mut parser = rustc_parse::new_parser_from_source_str(self.sess(), name, s.to_owned()); let first_span = parser.token.span.data(); let minus_present = parser.eat(&token::BinOp(token::Minus)); @@ -675,7 +727,7 @@ impl server::Literal for Rustc<'_> { } } -impl server::SourceFile for Rustc<'_> { +impl server::SourceFile for Rustc<'_, '_> { fn eq(&mut self, file1: &Self::SourceFile, file2: &Self::SourceFile) -> bool { Lrc::ptr_eq(file1, file2) } @@ -695,7 +747,7 @@ impl server::SourceFile for Rustc<'_> { } } -impl server::MultiSpan for Rustc<'_> { +impl server::MultiSpan for Rustc<'_, '_> { fn new(&mut self) -> Self::MultiSpan { vec![] } @@ -704,7 +756,7 @@ impl server::MultiSpan for Rustc<'_> { } } -impl server::Diagnostic for Rustc<'_> { +impl server::Diagnostic for Rustc<'_, '_> { fn new(&mut self, level: Level, msg: &str, spans: Self::MultiSpan) -> Self::Diagnostic { let mut diag = Diagnostic::new(level.to_internal(), msg); diag.set_span(MultiSpan::from_spans(spans)); @@ -720,13 +772,13 @@ impl server::Diagnostic for Rustc<'_> { diag.sub(level.to_internal(), msg, MultiSpan::from_spans(spans), None); } fn emit(&mut self, diag: Self::Diagnostic) { - self.sess.span_diagnostic.emit_diagnostic(&diag); + self.sess().span_diagnostic.emit_diagnostic(&diag); } } -impl server::Span for Rustc<'_> { +impl server::Span for Rustc<'_, '_> { fn debug(&mut self, span: Self::Span) -> String { - if self.span_debug { + if self.ecx.ecfg.span_debug { format!("{:?}", span) } else { format!("{:?} bytes({}..{})", span.ctxt(), span.lo().0, span.hi().0) @@ -742,7 +794,7 @@ impl server::Span for Rustc<'_> { self.mixed_site } fn source_file(&mut self, span: Self::Span) -> Self::SourceFile { - self.sess.source_map().lookup_char_pos(span.lo()).file + self.sess().source_map().lookup_char_pos(span.lo()).file } fn parent(&mut self, span: Self::Span) -> Option { span.parent_callsite() @@ -751,11 +803,11 @@ impl server::Span for Rustc<'_> { span.source_callsite() } fn start(&mut self, span: Self::Span) -> LineColumn { - let loc = self.sess.source_map().lookup_char_pos(span.lo()); + let loc = self.sess().source_map().lookup_char_pos(span.lo()); LineColumn { line: loc.line, column: loc.col.to_usize() } } fn end(&mut self, span: Self::Span) -> LineColumn { - let loc = self.sess.source_map().lookup_char_pos(span.hi()); + let loc = self.sess().source_map().lookup_char_pos(span.hi()); LineColumn { line: loc.line, column: loc.col.to_usize() } } fn before(&mut self, span: Self::Span) -> Self::Span { @@ -765,8 +817,8 @@ impl server::Span for Rustc<'_> { span.shrink_to_hi() } fn join(&mut self, first: Self::Span, second: Self::Span) -> Option { - let self_loc = self.sess.source_map().lookup_char_pos(first.lo()); - let other_loc = self.sess.source_map().lookup_char_pos(second.lo()); + let self_loc = self.sess().source_map().lookup_char_pos(first.lo()); + let other_loc = self.sess().source_map().lookup_char_pos(second.lo()); if self_loc.file.name != other_loc.file.name { return None; @@ -778,7 +830,7 @@ impl server::Span for Rustc<'_> { span.with_ctxt(at.ctxt()) } fn source_text(&mut self, span: Self::Span) -> Option { - self.sess.source_map().span_to_snippet(span).ok() + self.sess().source_map().span_to_snippet(span).ok() } /// Saves the provided span into the metadata of /// *the crate we are currently compiling*, which must @@ -805,10 +857,10 @@ impl server::Span for Rustc<'_> { /// since we've loaded `my_proc_macro` from disk in order to execute it). /// In this way, we have obtained a span pointing into `my_proc_macro` fn save_span(&mut self, span: Self::Span) -> usize { - self.sess.save_proc_macro_span(span) + self.sess().save_proc_macro_span(span) } fn recover_proc_macro_span(&mut self, id: usize) -> Self::Span { - let (resolver, krate, def_site) = (self.resolver, self.krate, self.def_site); + let (resolver, krate, def_site) = (&*self.ecx.resolver, self.krate, self.def_site); *self.rebased_spans.entry(id).or_insert_with(|| { // FIXME: `SyntaxContext` for spans from proc macro crates is lost during encoding, // replace it with a def-site context until we are encoding it properly. @@ -821,11 +873,11 @@ impl server::Span for Rustc<'_> { fn ident_name_compatibility_hack( nt: &Nonterminal, orig_span: Span, - rustc: &mut Rustc<'_>, + rustc: &mut Rustc<'_, '_>, ) -> Option<(rustc_span::symbol::Ident, bool)> { if let NtIdent(ident, is_raw) = nt { if let ExpnKind::Macro(_, macro_name) = orig_span.ctxt().outer_expn_data().kind { - let source_map = rustc.sess.source_map(); + let source_map = rustc.sess().source_map(); let filename = source_map.span_to_filename(orig_span); if let FileName::Real(RealFileName::LocalPath(path)) = filename { let matches_prefix = |prefix, filename| { @@ -846,7 +898,7 @@ fn ident_name_compatibility_hack( let snippet = source_map.span_to_snippet(orig_span); if snippet.as_deref() == Ok("$name") { if time_macros_impl { - rustc.sess.buffer_lint_with_diagnostic( + rustc.sess().buffer_lint_with_diagnostic( &PROC_MACRO_BACK_COMPAT, orig_span, ast::CRATE_NODE_ID, @@ -871,7 +923,7 @@ fn ident_name_compatibility_hack( .and_then(|c| c.parse::().ok()) .map_or(false, |v| v < 40) { - rustc.sess.buffer_lint_with_diagnostic( + rustc.sess().buffer_lint_with_diagnostic( &PROC_MACRO_BACK_COMPAT, orig_span, ast::CRATE_NODE_ID, @@ -894,7 +946,7 @@ fn ident_name_compatibility_hack( source_map.span_to_filename(rustc.def_site) { if macro_path.to_string_lossy().contains("pin-project-internal-0.") { - rustc.sess.buffer_lint_with_diagnostic( + rustc.sess().buffer_lint_with_diagnostic( &PROC_MACRO_BACK_COMPAT, orig_span, ast::CRATE_NODE_ID, diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 0d7a2afb63..6950fae898 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -34,6 +34,9 @@ declare_features! ( /// These are used to test this portion of the compiler, /// they don't actually mean anything. (accepted, test_accepted_feature, "1.0.0", None, None), + // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! + // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way. + // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! // ------------------------------------------------------------------------- // feature-group-end: for testing purposes @@ -43,260 +46,269 @@ declare_features! ( // feature-group-start: accepted features // ------------------------------------------------------------------------- + /// Allows the sysV64 ABI to be specified on all platforms + /// instead of just the platforms on which it is the C ABI. + (accepted, abi_sysv64, "1.24.0", Some(36167), None), + /// Allows the definition of associated constants in `trait` or `impl` blocks. + (accepted, associated_consts, "1.20.0", Some(29646), None), /// Allows using associated `type`s in `trait`s. (accepted, associated_types, "1.0.0", None, None), - /// Allows using assigning a default type to type parameters in algebraic data type definitions. - (accepted, default_type_params, "1.0.0", None, None), - // FIXME: explain `globs`. - (accepted, globs, "1.0.0", None, None), - /// Allows `macro_rules!` items. - (accepted, macro_rules, "1.0.0", None, None), - /// Allows use of `&foo[a..b]` as a slicing syntax. - (accepted, slicing_syntax, "1.0.0", None, None), - /// Allows struct variants `Foo { baz: u8, .. }` in enums (RFC 418). - (accepted, struct_variant, "1.0.0", None, None), - /// Allows indexing tuples. - (accepted, tuple_indexing, "1.0.0", None, None), - /// Allows the use of `if let` expressions. - (accepted, if_let, "1.0.0", None, None), - /// Allows the use of `while let` expressions. - (accepted, while_let, "1.0.0", None, None), - /// Allows using `#![no_std]`. - (accepted, no_std, "1.6.0", None, None), + /// Allows free and inherent `async fn`s, `async` blocks, and `.await` expressions. + (accepted, async_await, "1.39.0", Some(50547), None), + /// Allows all literals in attribute lists and values of key-value pairs. + (accepted, attr_literals, "1.30.0", Some(34981), None), /// Allows overloading augmented assignment operations like `a += b`. (accepted, augmented_assignments, "1.8.0", Some(28235), None), + /// Allows mixing bind-by-move in patterns and references to those identifiers in guards. + (accepted, bind_by_move_pattern_guards, "1.39.0", Some(15287), None), + /// Allows bindings in the subpattern of a binding pattern. + /// For example, you can write `x @ Some(y)`. + (accepted, bindings_after_at, "1.56.0", Some(65490), None), /// Allows empty structs and enum variants with braces. (accepted, braced_empty_structs, "1.8.0", Some(29720), None), - /// Allows `#[deprecated]` attribute. - (accepted, deprecated, "1.9.0", Some(29935), None), - /// Allows macros to appear in the type position. - (accepted, type_macros, "1.13.0", Some(27245), None), - /// Allows use of the postfix `?` operator in expressions. - (accepted, question_mark, "1.13.0", Some(31436), None), - /// Allows `..` in tuple (struct) patterns. - (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627), None), - /// Allows some increased flexibility in the name resolution rules, - /// especially around globs and shadowing (RFC 1560). - (accepted, item_like_imports, "1.15.0", Some(35120), None), - /// Allows using `Self` and associated types in struct expressions and patterns. - (accepted, more_struct_aliases, "1.16.0", Some(37544), None), - /// Allows elision of `'static` lifetimes in `static`s and `const`s. - (accepted, static_in_const, "1.17.0", Some(35897), None), - /// Allows field shorthands (`x` meaning `x: x`) in struct literal expressions. - (accepted, field_init_shorthand, "1.17.0", Some(37340), None), - /// Allows the definition recursive static items. - (accepted, static_recursion, "1.17.0", Some(29719), None), - /// Allows `pub(restricted)` visibilities (RFC 1422). - (accepted, pub_restricted, "1.18.0", Some(32409), None), - /// Allows `#![windows_subsystem]`. - (accepted, windows_subsystem, "1.18.0", Some(37499), None), - /// Allows `break {expr}` with a value inside `loop`s. - (accepted, loop_break_value, "1.19.0", Some(37339), None), - /// Allows numeric fields in struct expressions and patterns. - (accepted, relaxed_adts, "1.19.0", Some(35626), None), + /// Allows `#[cfg_attr(predicate, multiple, attributes, here)]`. + (accepted, cfg_attr_multi, "1.33.0", Some(54881), None), + /// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests. + (accepted, cfg_doctest, "1.40.0", Some(62210), None), + /// Allows `cfg(target_feature = "...")`. + (accepted, cfg_target_feature, "1.27.0", Some(29717), None), + /// Allows `cfg(target_vendor = "...")`. + (accepted, cfg_target_vendor, "1.33.0", Some(29718), None), + /// Allows implementing `Clone` for closures where possible (RFC 2132). + (accepted, clone_closures, "1.26.0", Some(44490), None), /// Allows coercing non capturing closures to function pointers. (accepted, closure_to_fn_coercion, "1.19.0", Some(39817), None), - /// Allows attributes on struct literal fields. - (accepted, struct_field_attributes, "1.20.0", Some(38814), None), - /// Allows the definition of associated constants in `trait` or `impl` blocks. - (accepted, associated_consts, "1.20.0", Some(29646), None), /// Allows usage of the `compile_error!` macro. (accepted, compile_error, "1.20.0", Some(40872), None), - /// Allows code like `let x: &'static u32 = &42` to work (RFC 1414). - (accepted, rvalue_static_promotion, "1.21.0", Some(38865), None), - /// Allows `Drop` types in constants (RFC 1440). - (accepted, drop_types_in_const, "1.22.0", Some(33156), None), - /// Allows the sysV64 ABI to be specified on all platforms - /// instead of just the platforms on which it is the C ABI. - (accepted, abi_sysv64, "1.24.0", Some(36167), None), - /// Allows `repr(align(16))` struct attribute (RFC 1358). - (accepted, repr_align, "1.25.0", Some(33626), None), - /// Allows '|' at beginning of match arms (RFC 1925). - (accepted, match_beginning_vert, "1.25.0", Some(44101), None), - /// Allows nested groups in `use` items (RFC 2128). - (accepted, use_nested_groups, "1.25.0", Some(44494), None), + /// Allows `impl Trait` in function return types. + (accepted, conservative_impl_trait, "1.26.0", Some(34511), None), + /// Allows calling constructor functions in `const fn`. + (accepted, const_constructor, "1.40.0", Some(61456), None), + /// Allows calling `transmute` in const fn + (accepted, const_fn_transmute, "1.56.0", Some(53605), None), + /// Allows accessing fields of unions inside `const` functions. + (accepted, const_fn_union, "1.56.0", Some(51909), None), + /// Allows unsizing coercions in `const fn`. + (accepted, const_fn_unsize, "1.54.0", Some(64992), None), + /// Allows the use of `if` and `match` in constants. + (accepted, const_if_match, "1.46.0", Some(49146), None), /// Allows indexing into constant arrays. (accepted, const_indexing, "1.26.0", Some(29947), None), - /// Allows using `a..=b` and `..=b` as inclusive range syntaxes. - (accepted, inclusive_range_syntax, "1.26.0", Some(28237), None), - /// Allows `..=` in patterns (RFC 1192). - (accepted, dotdoteq_in_patterns, "1.26.0", Some(28237), None), - /// Allows `fn main()` with return types which implements `Termination` (RFC 1937). - (accepted, termination_trait, "1.26.0", Some(43301), None), - /// Allows implementing `Clone` for closures where possible (RFC 2132). - (accepted, clone_closures, "1.26.0", Some(44490), None), + /// Allows let bindings, assignments and destructuring in `const` functions and constants. + /// As long as control flow is not implemented in const eval, `&&` and `||` may not be used + /// at the same time as let bindings. + (accepted, const_let, "1.33.0", Some(48821), None), + /// Allows the use of `loop` and `while` in constants. + (accepted, const_loop, "1.46.0", Some(52000), None), + /// Allows panicking during const eval (producing compile-time errors). + (accepted, const_panic, "1.57.0", Some(51999), None), + /// Allows dereferencing raw pointers during const eval. + (accepted, const_raw_ptr_deref, "1.58.0", Some(51911), None), /// Allows implementing `Copy` for closures where possible (RFC 2132). (accepted, copy_closures, "1.26.0", Some(44490), None), - /// Allows `impl Trait` in function arguments. - (accepted, universal_impl_trait, "1.26.0", Some(34511), None), - /// Allows `impl Trait` in function return types. - (accepted, conservative_impl_trait, "1.26.0", Some(34511), None), - /// Allows using the `u128` and `i128` types. - (accepted, i128_type, "1.26.0", Some(35118), None), - /// Allows default match binding modes (RFC 2005). - (accepted, match_default_bindings, "1.26.0", Some(42640), None), - /// Allows `'_` placeholder lifetimes. - (accepted, underscore_lifetimes, "1.26.0", Some(44524), None), - /// Allows attributes on lifetime/type formal parameters in generics (RFC 1327). - (accepted, generic_param_attrs, "1.27.0", Some(48848), None), - /// Allows `cfg(target_feature = "...")`. - (accepted, cfg_target_feature, "1.27.0", Some(29717), None), - /// Allows `#[target_feature(...)]`. - (accepted, target_feature, "1.27.0", None, None), - /// Allows using `dyn Trait` as a syntax for trait objects. - (accepted, dyn_trait, "1.27.0", Some(44662), None), - /// Allows `#[must_use]` on functions, and introduces must-use operators (RFC 1940). - (accepted, fn_must_use, "1.27.0", Some(43302), None), - /// Allows use of the `:lifetime` macro fragment specifier. - (accepted, macro_lifetime_matcher, "1.27.0", Some(34303), None), - /// Allows `#[test]` functions where the return type implements `Termination` (RFC 1937). - (accepted, termination_trait_test, "1.27.0", Some(48854), None), - /// Allows the `#[global_allocator]` attribute. - (accepted, global_allocator, "1.28.0", Some(27389), None), - /// Allows `#[repr(transparent)]` attribute on newtype structs. - (accepted, repr_transparent, "1.28.0", Some(43036), None), - /// Allows procedural macros in `proc-macro` crates. - (accepted, proc_macro, "1.29.0", Some(38356), None), - /// Allows `foo.rs` as an alternative to `foo/mod.rs`. - (accepted, non_modrs_mods, "1.30.0", Some(44660), None), - /// Allows use of the `:vis` macro fragment specifier - (accepted, macro_vis_matcher, "1.30.0", Some(41022), None), - /// Allows importing and reexporting macros with `use`, - /// enables macro modularization in general. - (accepted, use_extern_macros, "1.30.0", Some(35896), None), - /// Allows keywords to be escaped for use as identifiers. - (accepted, raw_identifiers, "1.30.0", Some(48589), None), - /// Allows attributes scoped to tools. - (accepted, tool_attributes, "1.30.0", Some(44690), None), - /// Allows multi-segment paths in attributes and derives. - (accepted, proc_macro_path_invoc, "1.30.0", Some(38356), None), - /// Allows all literals in attribute lists and values of key-value pairs. - (accepted, attr_literals, "1.30.0", Some(34981), None), - /// Allows inferring outlives requirements (RFC 2093). - (accepted, infer_outlives_requirements, "1.30.0", Some(44493), None), - /// Allows annotating functions conforming to `fn(&PanicInfo) -> !` with `#[panic_handler]`. - /// This defines the behavior of panics. - (accepted, panic_handler, "1.30.0", Some(44489), None), - /// Allows `#[used]` to preserve symbols (see llvm.compiler.used). - (accepted, used, "1.30.0", Some(40289), None), /// Allows `crate` in paths. (accepted, crate_in_paths, "1.30.0", Some(45477), None), + /// Allows using assigning a default type to type parameters in algebraic data type definitions. + (accepted, default_type_params, "1.0.0", None, None), + /// Allows `#[deprecated]` attribute. + (accepted, deprecated, "1.9.0", Some(29935), None), + /// Allows `#[doc(alias = "...")]`. + (accepted, doc_alias, "1.48.0", Some(50146), None), + /// Allows `..` in tuple (struct) patterns. + (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627), None), + /// Allows `..=` in patterns (RFC 1192). + (accepted, dotdoteq_in_patterns, "1.26.0", Some(28237), None), + /// Allows `Drop` types in constants (RFC 1440). + (accepted, drop_types_in_const, "1.22.0", Some(33156), None), + /// Allows using `dyn Trait` as a syntax for trait objects. + (accepted, dyn_trait, "1.27.0", Some(44662), None), + /// Allows integer match exhaustiveness checking (RFC 2591). + (accepted, exhaustive_integer_patterns, "1.33.0", Some(50907), None), + /// Allows arbitrary expressions in key-value attributes at parse time. + (accepted, extended_key_value_attributes, "1.54.0", Some(78835), None), /// Allows resolving absolute paths as paths from other crates. (accepted, extern_absolute_paths, "1.30.0", Some(44660), None), + /// Allows `extern crate foo as bar;`. This puts `bar` into extern prelude. + (accepted, extern_crate_item_prelude, "1.31.0", Some(55599), None), + /// Allows `extern crate self as foo;`. + /// This puts local crate root into extern prelude under name `foo`. + (accepted, extern_crate_self, "1.34.0", Some(56409), None), /// Allows access to crate names passed via `--extern` through prelude. (accepted, extern_prelude, "1.30.0", Some(44660), None), - /// Allows parentheses in patterns. - (accepted, pattern_parentheses, "1.31.0", Some(51087), None), - /// Allows the definition of `const fn` functions. - (accepted, min_const_fn, "1.31.0", Some(53555), None), - /// Allows scoped lints. - (accepted, tool_lints, "1.31.0", Some(44690), None), + /// Allows field shorthands (`x` meaning `x: x`) in struct literal expressions. + (accepted, field_init_shorthand, "1.17.0", Some(37340), None), + /// Allows `#[must_use]` on functions, and introduces must-use operators (RFC 1940). + (accepted, fn_must_use, "1.27.0", Some(43302), None), + /// Allows capturing variables in scope using format_args! + (accepted, format_args_capture, "1.58.0", Some(67984), None), + /// Allows attributes on lifetime/type formal parameters in generics (RFC 1327). + (accepted, generic_param_attrs, "1.27.0", Some(48848), None), + /// Allows the `#[global_allocator]` attribute. + (accepted, global_allocator, "1.28.0", Some(27389), None), + // FIXME: explain `globs`. + (accepted, globs, "1.0.0", None, None), + /// Allows using the `u128` and `i128` types. + (accepted, i128_type, "1.26.0", Some(35118), None), + /// Allows the use of `if let` expressions. + (accepted, if_let, "1.0.0", None, None), + /// Allows top level or-patterns (`p | q`) in `if let` and `while let`. + (accepted, if_while_or_patterns, "1.33.0", Some(48215), None), /// Allows lifetime elision in `impl` headers. For example: /// + `impl Iterator for &mut Iterator` /// + `impl Debug for Foo<'_>` (accepted, impl_header_lifetime_elision, "1.31.0", Some(15872), None), - /// Allows `extern crate foo as bar;`. This puts `bar` into extern prelude. - (accepted, extern_crate_item_prelude, "1.31.0", Some(55599), None), - /// Allows use of the `:literal` macro fragment specifier (RFC 1576). - (accepted, macro_literal_matcher, "1.32.0", Some(35625), None), - /// Allows use of `?` as the Kleene "at most one" operator in macros. - (accepted, macro_at_most_once_rep, "1.32.0", Some(48075), None), - /// Allows `Self` struct constructor (RFC 2302). - (accepted, self_struct_ctor, "1.32.0", Some(51994), None), - /// Allows `Self` in type definitions (RFC 2300). - (accepted, self_in_typedefs, "1.32.0", Some(49303), None), - /// Allows `use x::y;` to search `x` in the current scope. - (accepted, uniform_paths, "1.32.0", Some(53130), None), - /// Allows integer match exhaustiveness checking (RFC 2591). - (accepted, exhaustive_integer_patterns, "1.33.0", Some(50907), None), - /// Allows `use path as _;` and `extern crate c as _;`. - (accepted, underscore_imports, "1.33.0", Some(48216), None), - /// Allows `#[repr(packed(N))]` attribute on structs. - (accepted, repr_packed, "1.33.0", Some(33158), None), + /// Allows using `a..=b` and `..=b` as inclusive range syntaxes. + (accepted, inclusive_range_syntax, "1.26.0", Some(28237), None), + /// Allows inferring outlives requirements (RFC 2093). + (accepted, infer_outlives_requirements, "1.30.0", Some(44493), None), /// Allows irrefutable patterns in `if let` and `while let` statements (RFC 2086). (accepted, irrefutable_let_patterns, "1.33.0", Some(44495), None), - /// Allows calling `const unsafe fn` inside `unsafe` blocks in `const fn` functions. - (accepted, min_const_unsafe_fn, "1.33.0", Some(55607), None), - /// Allows let bindings, assignments and destructuring in `const` functions and constants. - /// As long as control flow is not implemented in const eval, `&&` and `||` may not be used - /// at the same time as let bindings. - (accepted, const_let, "1.33.0", Some(48821), None), - /// Allows `#[cfg_attr(predicate, multiple, attributes, here)]`. - (accepted, cfg_attr_multi, "1.33.0", Some(54881), None), - /// Allows top level or-patterns (`p | q`) in `if let` and `while let`. - (accepted, if_while_or_patterns, "1.33.0", Some(48215), None), - /// Allows `cfg(target_vendor = "...")`. - (accepted, cfg_target_vendor, "1.33.0", Some(29718), None), - /// Allows `extern crate self as foo;`. - /// This puts local crate root into extern prelude under name `foo`. - (accepted, extern_crate_self, "1.34.0", Some(56409), None), - /// Allows arbitrary delimited token streams in non-macro attributes. - (accepted, unrestricted_attribute_tokens, "1.34.0", Some(55208), None), - /// Allows paths to enum variants on type aliases including `Self`. - (accepted, type_alias_enum_variants, "1.37.0", Some(49683), None), - /// Allows using `#[repr(align(X))]` on enums with equivalent semantics - /// to wrapping an enum in a wrapper struct with `#[repr(align(X))]`. - (accepted, repr_align_enum, "1.37.0", Some(57996), None), - /// Allows `const _: TYPE = VALUE`. - (accepted, underscore_const_names, "1.37.0", Some(54912), None), - /// Allows free and inherent `async fn`s, `async` blocks, and `.await` expressions. - (accepted, async_await, "1.39.0", Some(50547), None), - /// Allows mixing bind-by-move in patterns and references to those identifiers in guards. - (accepted, bind_by_move_pattern_guards, "1.39.0", Some(15287), None), - /// Allows attributes in formal function parameters. - (accepted, param_attrs, "1.39.0", Some(60406), None), + /// Allows some increased flexibility in the name resolution rules, + /// especially around globs and shadowing (RFC 1560). + (accepted, item_like_imports, "1.15.0", Some(35120), None), + /// Allows `break {expr}` with a value inside `loop`s. + (accepted, loop_break_value, "1.19.0", Some(37339), None), + /// Allows use of `?` as the Kleene "at most one" operator in macros. + (accepted, macro_at_most_once_rep, "1.32.0", Some(48075), None), + /// Allows macro attributes to observe output of `#[derive]`. + (accepted, macro_attributes_in_derive_output, "1.57.0", Some(81119), None), + /// Allows use of the `:lifetime` macro fragment specifier. + (accepted, macro_lifetime_matcher, "1.27.0", Some(34303), None), + /// Allows use of the `:literal` macro fragment specifier (RFC 1576). + (accepted, macro_literal_matcher, "1.32.0", Some(35625), None), + /// Allows `macro_rules!` items. + (accepted, macro_rules, "1.0.0", None, None), + /// Allows use of the `:vis` macro fragment specifier + (accepted, macro_vis_matcher, "1.30.0", Some(41022), None), /// Allows macro invocations in `extern {}` blocks. (accepted, macros_in_extern, "1.40.0", Some(49476), None), + /// Allows '|' at beginning of match arms (RFC 1925). + (accepted, match_beginning_vert, "1.25.0", Some(44101), None), + /// Allows default match binding modes (RFC 2005). + (accepted, match_default_bindings, "1.26.0", Some(42640), None), + /// Allows `impl Trait` with multiple unrelated lifetimes. + (accepted, member_constraints, "1.54.0", Some(61997), None), + /// Allows the definition of `const fn` functions. + (accepted, min_const_fn, "1.31.0", Some(53555), None), + /// The smallest useful subset of const generics. + (accepted, min_const_generics, "1.51.0", Some(74878), None), + /// Allows calling `const unsafe fn` inside `unsafe` blocks in `const fn` functions. + (accepted, min_const_unsafe_fn, "1.33.0", Some(55607), None), + /// Allows using `Self` and associated types in struct expressions and patterns. + (accepted, more_struct_aliases, "1.16.0", Some(37544), None), + /// Allows patterns with concurrent by-move and by-ref bindings. + /// For example, you can write `Foo(a, ref b)` where `a` is by-move and `b` is by-ref. + (accepted, move_ref_pattern, "1.49.0", Some(68354), None), + /// Allows using `#![no_std]`. + (accepted, no_std, "1.6.0", None, None), + /// Allows defining identifiers beyond ASCII. + (accepted, non_ascii_idents, "1.53.0", Some(55467), None), /// Allows future-proofing enums/structs with the `#[non_exhaustive]` attribute (RFC 2008). (accepted, non_exhaustive, "1.40.0", Some(44109), None), - /// Allows calling constructor functions in `const fn`. - (accepted, const_constructor, "1.40.0", Some(61456), None), - /// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests. - (accepted, cfg_doctest, "1.40.0", Some(62210), None), + /// Allows `foo.rs` as an alternative to `foo/mod.rs`. + (accepted, non_modrs_mods, "1.30.0", Some(44660), None), + /// Allows the use of or-patterns (e.g., `0 | 1`). + (accepted, or_patterns, "1.53.0", Some(54883), None), + /// Allows annotating functions conforming to `fn(&PanicInfo) -> !` with `#[panic_handler]`. + /// This defines the behavior of panics. + (accepted, panic_handler, "1.30.0", Some(44489), None), + /// Allows attributes in formal function parameters. + (accepted, param_attrs, "1.39.0", Some(60406), None), + /// Allows parentheses in patterns. + (accepted, pattern_parentheses, "1.31.0", Some(51087), None), + /// Allows procedural macros in `proc-macro` crates. + (accepted, proc_macro, "1.29.0", Some(38356), None), + /// Allows multi-segment paths in attributes and derives. + (accepted, proc_macro_path_invoc, "1.30.0", Some(38356), None), + /// Allows `pub(restricted)` visibilities (RFC 1422). + (accepted, pub_restricted, "1.18.0", Some(32409), None), + /// Allows use of the postfix `?` operator in expressions. + (accepted, question_mark, "1.13.0", Some(31436), None), + /// Allows keywords to be escaped for use as identifiers. + (accepted, raw_identifiers, "1.30.0", Some(48589), None), /// Allows relaxing the coherence rules such that /// `impl ForeignTrait for ForeignType` is permitted. (accepted, re_rebalance_coherence, "1.41.0", Some(55437), None), - /// Allows #[repr(transparent)] on univariant enums (RFC 2645). - (accepted, transparent_enums, "1.42.0", Some(60405), None), + /// Allows numeric fields in struct expressions and patterns. + (accepted, relaxed_adts, "1.19.0", Some(35626), None), + /// Lessens the requirements for structs to implement `Unsize`. + (accepted, relaxed_struct_unsize, "1.58.0", Some(81793), None), + /// Allows `repr(align(16))` struct attribute (RFC 1358). + (accepted, repr_align, "1.25.0", Some(33626), None), + /// Allows using `#[repr(align(X))]` on enums with equivalent semantics + /// to wrapping an enum in a wrapper struct with `#[repr(align(X))]`. + (accepted, repr_align_enum, "1.37.0", Some(57996), None), + /// Allows `#[repr(packed(N))]` attribute on structs. + (accepted, repr_packed, "1.33.0", Some(33158), None), + /// Allows `#[repr(transparent)]` attribute on newtype structs. + (accepted, repr_transparent, "1.28.0", Some(43036), None), + /// Allows code like `let x: &'static u32 = &42` to work (RFC 1414). + (accepted, rvalue_static_promotion, "1.21.0", Some(38865), None), + /// Allows `Self` in type definitions (RFC 2300). + (accepted, self_in_typedefs, "1.32.0", Some(49303), None), + /// Allows `Self` struct constructor (RFC 2302). + (accepted, self_struct_ctor, "1.32.0", Some(51994), None), /// Allows using subslice patterns, `[a, .., b]` and `[a, xs @ .., b]`. (accepted, slice_patterns, "1.42.0", Some(62254), None), - /// Allows the use of `if` and `match` in constants. - (accepted, const_if_match, "1.46.0", Some(49146), None), - /// Allows the use of `loop` and `while` in constants. - (accepted, const_loop, "1.46.0", Some(52000), None), + /// Allows use of `&foo[a..b]` as a slicing syntax. + (accepted, slicing_syntax, "1.0.0", None, None), + /// Allows elision of `'static` lifetimes in `static`s and `const`s. + (accepted, static_in_const, "1.17.0", Some(35897), None), + /// Allows the definition recursive static items. + (accepted, static_recursion, "1.17.0", Some(29719), None), + /// Allows attributes on struct literal fields. + (accepted, struct_field_attributes, "1.20.0", Some(38814), None), + /// Allows struct variants `Foo { baz: u8, .. }` in enums (RFC 418). + (accepted, struct_variant, "1.0.0", None, None), + /// Allows `#[target_feature(...)]`. + (accepted, target_feature, "1.27.0", None, None), + /// Allows `fn main()` with return types which implements `Termination` (RFC 1937). + (accepted, termination_trait, "1.26.0", Some(43301), None), + /// Allows `#[test]` functions where the return type implements `Termination` (RFC 1937). + (accepted, termination_trait_test, "1.27.0", Some(48854), None), + /// Allows attributes scoped to tools. + (accepted, tool_attributes, "1.30.0", Some(44690), None), + /// Allows scoped lints. + (accepted, tool_lints, "1.31.0", Some(44690), None), /// Allows `#[track_caller]` to be used which provides /// accurate caller location reporting during panic (RFC 2091). (accepted, track_caller, "1.46.0", Some(47809), None), - /// Allows `#[doc(alias = "...")]`. - (accepted, doc_alias, "1.48.0", Some(50146), None), - /// Allows patterns with concurrent by-move and by-ref bindings. - /// For example, you can write `Foo(a, ref b)` where `a` is by-move and `b` is by-ref. - (accepted, move_ref_pattern, "1.49.0", Some(68354), None), - /// The smallest useful subset of const generics. - (accepted, min_const_generics, "1.51.0", Some(74878), None), + /// Allows #[repr(transparent)] on univariant enums (RFC 2645). + (accepted, transparent_enums, "1.42.0", Some(60405), None), + /// Allows indexing tuples. + (accepted, tuple_indexing, "1.0.0", None, None), + /// Allows paths to enum variants on type aliases including `Self`. + (accepted, type_alias_enum_variants, "1.37.0", Some(49683), None), + /// Allows macros to appear in the type position. + (accepted, type_macros, "1.13.0", Some(27245), None), + /// Allows `const _: TYPE = VALUE`. + (accepted, underscore_const_names, "1.37.0", Some(54912), None), + /// Allows `use path as _;` and `extern crate c as _;`. + (accepted, underscore_imports, "1.33.0", Some(48216), None), + /// Allows `'_` placeholder lifetimes. + (accepted, underscore_lifetimes, "1.26.0", Some(44524), None), + /// Allows `use x::y;` to search `x` in the current scope. + (accepted, uniform_paths, "1.32.0", Some(53130), None), + /// Allows `impl Trait` in function arguments. + (accepted, universal_impl_trait, "1.26.0", Some(34511), None), + /// Allows arbitrary delimited token streams in non-macro attributes. + (accepted, unrestricted_attribute_tokens, "1.34.0", Some(55208), 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.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), - /// Allows arbitrary expressions in key-value attributes at parse time. - (accepted, extended_key_value_attributes, "1.54.0", Some(78835), None), - /// Allows unsizing coercions in `const fn`. - (accepted, const_fn_unsize, "1.54.0", Some(64992), None), - /// Allows `impl Trait` with multiple unrelated lifetimes. - (accepted, member_constraints, "1.54.0", Some(61997), None), - /// Allows bindings in the subpattern of a binding pattern. - /// For example, you can write `x @ Some(y)`. - (accepted, bindings_after_at, "1.56.0", Some(65490), None), - /// Allows calling `transmute` in const fn - (accepted, const_fn_transmute, "1.56.0", Some(53605), None), - /// Allows accessing fields of unions inside `const` functions. - (accepted, const_fn_union, "1.56.0", Some(51909), None), - /// Allows macro attributes to observe output of `#[derive]`. - (accepted, macro_attributes_in_derive_output, "1.57.0", Some(81119), None), - /// Allows panicking during const eval (producing compile-time errors). - (accepted, const_panic, "1.57.0", Some(51999), None), + /// Allows importing and reexporting macros with `use`, + /// enables macro modularization in general. + (accepted, use_extern_macros, "1.30.0", Some(35896), None), + /// Allows nested groups in `use` items (RFC 2128). + (accepted, use_nested_groups, "1.25.0", Some(44494), None), + /// Allows `#[used]` to preserve symbols (see llvm.compiler.used). + (accepted, used, "1.30.0", Some(40289), None), + /// Allows the use of `while let` expressions. + (accepted, while_let, "1.0.0", None, None), + /// Allows `#![windows_subsystem]`. + (accepted, windows_subsystem, "1.18.0", Some(37499), None), + // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! + // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way. + // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! // ------------------------------------------------------------------------- // feature-group-end: accepted features diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 0ba764021e..7860f92f96 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -101,9 +101,13 @@ impl Feature { } } +// See https://rustc-dev-guide.rust-lang.org/feature-gates.html#feature-gates for more +// documentation about handling feature gates. +// // If you change this, please modify `src/doc/unstable-book` as well. // -// Don't ever remove anything from this list; move them to `removed.rs`. +// Don't ever remove anything from this list; move them to `accepted.rs` if +// accepted or `removed.rs` if removed. // // The version numbers here correspond to the version in which the current status // was set. This is most important for knowing when a particular feature became @@ -118,130 +122,103 @@ impl Feature { #[rustfmt::skip] declare_features! ( // ------------------------------------------------------------------------- - // feature-group-start: internal feature gates + // feature-group-start: internal feature gates (no tracking issue) // ------------------------------------------------------------------------- - // no-tracking-issue-start - /// Allows using `rustc_*` attributes (RFC 572). - (active, rustc_attrs, "1.0.0", None, None), - - /// Allows using compiler's own crates. - (active, rustc_private, "1.0.0", Some(27812), None), - - /// Allows using the `rust-intrinsic`'s "ABI". - (active, intrinsics, "1.0.0", None, None), - - /// Allows using `#[lang = ".."]` attribute for linking items to special compiler logic. - (active, lang_items, "1.0.0", None, None), - - /// Allows using the `#[stable]` and `#[unstable]` attributes. - (active, staged_api, "1.0.0", None, None), - - /// Allows using `#[allow_internal_unstable]`. This is an + /// Allows using the `thiscall` ABI. + (active, abi_thiscall, "1.19.0", None, None), + /// Allows using the `unadjusted` ABI; perma-unstable. + (active, abi_unadjusted, "1.16.0", None, None), + /// Allows using the `vectorcall` ABI. + (active, abi_vectorcall, "1.7.0", None, None), + /// Allows using `#![needs_allocator]`, an implementation detail of `#[global_allocator]`. + (active, allocator_internals, "1.20.0", None, None), + /// Allows using `#[allow_internal_unsafe]`. This is an /// attribute on `macro_rules!` and can't use the attribute handling /// below (it has to be checked before expansion possibly makes /// macros disappear). - (active, allow_internal_unstable, "1.0.0", None, None), - - /// Allows using `#[allow_internal_unsafe]`. This is an + (active, allow_internal_unsafe, "1.0.0", None, None), + /// Allows using `#[allow_internal_unstable]`. This is an /// attribute on `macro_rules!` and can't use the attribute handling /// below (it has to be checked before expansion possibly makes /// macros disappear). - (active, allow_internal_unsafe, "1.0.0", None, None), - - /// no-tracking-issue-end - - /// Allows using `#[link_name="llvm.*"]`. - (active, link_llvm_intrinsics, "1.0.0", Some(29602), None), - - /// Allows using the `box $expr` syntax. - (active, box_syntax, "1.0.0", Some(49733), None), - - /// Allows using `#[start]` on a function indicating that it is the program entrypoint. - (active, start, "1.0.0", Some(29633), None), - - /// Allows using the `#[fundamental]` attribute. - (active, fundamental, "1.0.0", Some(29635), None), - - /// Allows using the `rust-call` ABI. - (active, unboxed_closures, "1.0.0", Some(29625), None), - - /// Allows using the `#[linkage = ".."]` attribute. - (active, linkage, "1.0.0", Some(29603), None), - - /// Allows using `box` in patterns (RFC 469). - (active, box_patterns, "1.0.0", Some(29641), None), - - // no-tracking-issue-start - - /// Allows using `#[prelude_import]` on glob `use` items. - (active, prelude_import, "1.2.0", None, None), - - // no-tracking-issue-end - - // no-tracking-issue-start - - /// Allows using `#[omit_gdb_pretty_printer_section]`. - (active, omit_gdb_pretty_printer_section, "1.5.0", None, None), - - /// Allows using the `vectorcall` ABI. - (active, abi_vectorcall, "1.7.0", None, None), - - // no-tracking-issue-end - - /// Allows using `#[structural_match]` which indicates that a type is structurally matchable. - /// FIXME: Subsumed by trait `StructuralPartialEq`, cannot move to removed until a library - /// feature with the same name exists. - (active, structural_match, "1.8.0", Some(31434), None), - - /// Allows using the `may_dangle` attribute (RFC 1327). - (active, dropck_eyepatch, "1.10.0", Some(34761), None), - - /// Allows using the `#![panic_runtime]` attribute. - (active, panic_runtime, "1.10.0", Some(32837), None), - - /// Allows declaring with `#![needs_panic_runtime]` that a panic runtime is needed. - (active, needs_panic_runtime, "1.10.0", Some(32837), None), - - // no-tracking-issue-start - + (active, allow_internal_unstable, "1.0.0", None, None), /// Allows identifying the `compiler_builtins` crate. (active, compiler_builtins, "1.13.0", None, None), - - /// Allows using the `unadjusted` ABI; perma-unstable. - (active, abi_unadjusted, "1.16.0", None, None), - + /// Allows using the `rust-intrinsic`'s "ABI". + (active, intrinsics, "1.0.0", None, None), + /// Allows using `#[lang = ".."]` attribute for linking items to special compiler logic. + (active, lang_items, "1.0.0", None, None), + /// Allows `#[repr(no_niche)]` (an implementation detail of `rustc`, + /// it is not on path for eventual stabilization). + (active, no_niche, "1.42.0", None, None), + /// Allows using `#[omit_gdb_pretty_printer_section]`. + (active, omit_gdb_pretty_printer_section, "1.5.0", None, None), + /// Allows using `#[prelude_import]` on glob `use` items. + (active, prelude_import, "1.2.0", None, None), /// Used to identify crates that contain the profiler runtime. (active, profiler_runtime, "1.18.0", None, None), - - /// Allows using the `thiscall` ABI. - (active, abi_thiscall, "1.19.0", None, None), - - /// Allows using `#![needs_allocator]`, an implementation detail of `#[global_allocator]`. - (active, allocator_internals, "1.20.0", None, None), - + /// Allows using `rustc_*` attributes (RFC 572). + (active, rustc_attrs, "1.0.0", None, None), + /// Allows using the `#[stable]` and `#[unstable]` attributes. + (active, staged_api, "1.0.0", None, None), /// Added for testing E0705; perma-unstable. (active, test_2018_feature, "1.31.0", None, Some(Edition::Edition2018)), + // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! + // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way. + // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! - /// Allows `#[repr(no_niche)]` (an implementation detail of `rustc`, - /// it is not on path for eventual stabilization). - (active, no_niche, "1.42.0", None, None), + // no-tracking-issue-end + // ------------------------------------------------------------------------- + // feature-group-end: internal feature gates (no tracking issue) + // ------------------------------------------------------------------------- - /// Allows using `#[rustc_allow_const_fn_unstable]`. - /// This is an attribute on `const fn` for the same - /// purpose as `#[allow_internal_unstable]`. - (active, rustc_allow_const_fn_unstable, "1.49.0", Some(69399), None), + // ------------------------------------------------------------------------- + // feature-group-start: internal feature gates + // ------------------------------------------------------------------------- /// Allows features specific to auto traits. /// Renamed from `optin_builtin_traits`. (active, auto_traits, "1.50.0", Some(13231), None), - + /// Allows using `box` in patterns (RFC 469). + (active, box_patterns, "1.0.0", Some(29641), None), + /// Allows using the `box $expr` syntax. + (active, box_syntax, "1.0.0", Some(49733), None), /// Allows `#[doc(notable_trait)]`. /// Renamed from `doc_spotlight`. (active, doc_notable_trait, "1.52.0", Some(45040), None), - - // no-tracking-issue-end + /// Allows using the `may_dangle` attribute (RFC 1327). + (active, dropck_eyepatch, "1.10.0", Some(34761), None), + /// Allows using the `#[fundamental]` attribute. + (active, fundamental, "1.0.0", Some(29635), None), + /// Allows using `#[link_name="llvm.*"]`. + (active, link_llvm_intrinsics, "1.0.0", Some(29602), None), + /// Allows using the `#[linkage = ".."]` attribute. + (active, linkage, "1.0.0", Some(29603), None), + /// Allows declaring with `#![needs_panic_runtime]` that a panic runtime is needed. + (active, needs_panic_runtime, "1.10.0", Some(32837), None), + /// Allows using the `#![panic_runtime]` attribute. + (active, panic_runtime, "1.10.0", Some(32837), None), + /// Allows using `#[rustc_allow_const_fn_unstable]`. + /// This is an attribute on `const fn` for the same + /// purpose as `#[allow_internal_unstable]`. + (active, rustc_allow_const_fn_unstable, "1.49.0", Some(69399), None), + /// Allows using compiler's own crates. + (active, rustc_private, "1.0.0", Some(27812), None), + /// Allows using internal rustdoc features like `doc(primitive)` or `doc(keyword)`. + (active, rustdoc_internals, "1.58.0", Some(90418), None), + /// Allows using `#[start]` on a function indicating that it is the program entrypoint. + (active, start, "1.0.0", Some(29633), None), + /// Allows using `#[structural_match]` which indicates that a type is structurally matchable. + /// FIXME: Subsumed by trait `StructuralPartialEq`, cannot move to removed until a library + /// feature with the same name exists. + (active, structural_match, "1.8.0", Some(31434), None), + /// Allows using the `rust-call` ABI. + (active, unboxed_closures, "1.0.0", Some(29625), None), + // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! + // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way. + // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! // ------------------------------------------------------------------------- // feature-group-end: internal feature gates @@ -254,23 +231,26 @@ declare_features! ( // FIXME: Document these and merge with the list below. // Unstable `#[target_feature]` directives. - (active, arm_target_feature, "1.27.0", Some(44839), None), (active, aarch64_target_feature, "1.27.0", Some(44839), None), + (active, adx_target_feature, "1.32.0", Some(44839), None), + (active, arm_target_feature, "1.27.0", Some(44839), None), + (active, avx512_target_feature, "1.27.0", Some(44839), None), + (active, bpf_target_feature, "1.54.0", Some(44839), None), + (active, cmpxchg16b_target_feature, "1.32.0", Some(44839), None), + (active, ermsb_target_feature, "1.49.0", Some(44839), None), + (active, f16c_target_feature, "1.36.0", Some(44839), None), (active, hexagon_target_feature, "1.27.0", Some(44839), None), - (active, powerpc_target_feature, "1.27.0", Some(44839), None), (active, mips_target_feature, "1.27.0", Some(44839), None), - (active, avx512_target_feature, "1.27.0", Some(44839), None), + (active, movbe_target_feature, "1.34.0", Some(44839), None), + (active, powerpc_target_feature, "1.27.0", Some(44839), None), + (active, riscv_target_feature, "1.45.0", Some(44839), None), + (active, rtm_target_feature, "1.35.0", Some(44839), None), (active, sse4a_target_feature, "1.27.0", Some(44839), None), (active, tbm_target_feature, "1.27.0", Some(44839), None), (active, wasm_target_feature, "1.30.0", Some(44839), None), - (active, adx_target_feature, "1.32.0", Some(44839), None), - (active, cmpxchg16b_target_feature, "1.32.0", Some(44839), None), - (active, movbe_target_feature, "1.34.0", Some(44839), None), - (active, rtm_target_feature, "1.35.0", Some(44839), None), - (active, f16c_target_feature, "1.36.0", Some(44839), None), - (active, riscv_target_feature, "1.45.0", Some(44839), None), - (active, ermsb_target_feature, "1.49.0", Some(44839), None), - (active, bpf_target_feature, "1.54.0", Some(44839), None), + // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! + // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way. + // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! // ------------------------------------------------------------------------- // feature-group-end: actual feature gates (target features) @@ -280,412 +260,285 @@ declare_features! ( // feature-group-start: actual feature gates // ------------------------------------------------------------------------- - /// Allows using `#![plugin(myplugin)]`. - (active, plugin, "1.0.0", Some(29597), None), - - /// Allows using `#[thread_local]` on `static` items. - (active, thread_local, "1.0.0", Some(29594), None), - - /// Allows the use of SIMD types in functions declared in `extern` blocks. - (active, simd_ffi, "1.0.0", Some(27731), None), - - /// Allows using non lexical lifetimes (RFC 2094). - (active, nll, "1.0.0", Some(43234), None), - + /// Allows using the `amdgpu-kernel` ABI. + (active, abi_amdgpu_kernel, "1.29.0", Some(51575), None), + /// Allows `extern "avr-interrupt" fn()` and `extern "avr-non-blocking-interrupt" fn()`. + (active, abi_avr_interrupt, "1.45.0", Some(69664), None), + /// Allows `extern "C-cmse-nonsecure-call" fn()`. + (active, abi_c_cmse_nonsecure_call, "1.51.0", Some(81391), None), + /// Allows using the `efiapi` ABI. + (active, abi_efiapi, "1.40.0", Some(65815), None), + /// Allows `extern "msp430-interrupt" fn()`. + (active, abi_msp430_interrupt, "1.16.0", Some(38487), None), + /// Allows `extern "ptx-*" fn()`. + (active, abi_ptx, "1.15.0", Some(38788), None), + /// Allows `extern "x86-interrupt" fn()`. + (active, abi_x86_interrupt, "1.17.0", Some(40180), None), + /// Allows additional const parameter types, such as `&'static str` or user defined types + (incomplete, adt_const_params, "1.56.0", Some(44580), None), + /// Allows defining an `#[alloc_error_handler]`. + (active, alloc_error_handler, "1.29.0", Some(51540), None), + /// Allows a test to fail without failing the whole suite. + (active, allow_fail, "1.19.0", Some(46488), None), + /// Allows explicit discriminants on non-unit enum variants. + (active, arbitrary_enum_discriminant, "1.37.0", Some(60553), None), + /// Allows trait methods with arbitrary self types. + (active, arbitrary_self_types, "1.23.0", Some(44874), None), + /// Allows using `const` operands in inline assembly. + (active, asm_const, "1.58.0", Some(72016), None), + /// Enables experimental inline assembly support for additional architectures. + (active, asm_experimental_arch, "1.58.0", Some(72016), None), + /// Allows using `sym` operands in inline assembly. + (active, asm_sym, "1.58.0", Some(72016), None), + /// Allows the user of associated type bounds. + (active, associated_type_bounds, "1.34.0", Some(52662), None), /// Allows associated type defaults. (active, associated_type_defaults, "1.2.0", Some(29661), None), - - /// Allows `#![no_core]`. - (active, no_core, "1.3.0", Some(29639), None), - - /// Allows default type parameters to influence type inference. - (active, default_type_parameter_fallback, "1.3.0", Some(27336), None), - - /// Allows `repr(simd)` and importing the various simd intrinsics. - (active, repr_simd, "1.4.0", Some(27731), None), - - /// Allows `extern "platform-intrinsic" { ... }`. - (active, platform_intrinsics, "1.4.0", Some(27731), None), - - /// Allows attributes on expressions and non-item statements. - (active, stmt_expr_attributes, "1.6.0", Some(15701), None), - - /// Allows the use of type ascription in expressions. - (active, type_ascription, "1.6.0", Some(23416), None), - - /// Allows `cfg(target_thread_local)`. - (active, cfg_target_thread_local, "1.7.0", Some(29594), None), - - /// Allows specialization of implementations (RFC 1210). - (incomplete, specialization, "1.7.0", Some(31844), None), - - /// A minimal, sound subset of specialization intended to be used by the - /// standard library until the soundness issues with specialization - /// are fixed. - (active, min_specialization, "1.7.0", Some(31844), None), - - /// Allows using `#[naked]` on functions. - (active, naked_functions, "1.9.0", Some(32408), None), - + /// Allows `async || body` closures. + (active, async_closure, "1.37.0", Some(62290), None), + /// Allows `extern "C-unwind" fn` to enable unwinding across ABI boundaries. + (active, c_unwind, "1.52.0", Some(74990), None), + /// Allows using C-variadics. + (active, c_variadic, "1.34.0", Some(44930), None), + /// Allows capturing disjoint fields in a closure/generator (RFC 2229). + (incomplete, capture_disjoint_fields, "1.49.0", Some(53488), None), + /// Enables `#[cfg(panic = "...")]` config key. + (active, cfg_panic, "1.49.0", Some(77443), None), + /// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used. + (active, cfg_sanitize, "1.41.0", Some(39699), None), + /// Allows `cfg(target_abi = "...")`. + (active, cfg_target_abi, "1.55.0", Some(80970), None), /// Allows `cfg(target_has_atomic = "...")`. (active, cfg_target_has_atomic, "1.9.0", Some(32976), None), - - /// Allows `X..Y` patterns. - (active, exclusive_range_pattern, "1.11.0", Some(37854), None), - - /// Allows the `!` type. Does not imply 'exhaustive_patterns' (below) any more. - (active, never_type, "1.13.0", Some(35121), None), - - /// Allows exhaustive pattern matching on types that contain uninhabited types. - (active, exhaustive_patterns, "1.13.0", Some(51085), None), - - /// Allows `union`s to implement `Drop`. Moreover, `union`s may now include fields - /// that don't implement `Copy` as long as they don't have any drop glue. - /// This is checked recursively. On encountering type variable where no progress can be made, - /// `T: Copy` is used as a substitute for "no drop glue". - /// - /// NOTE: A limited form of `union U { ... }` was accepted in 1.19.0. - (active, untagged_unions, "1.13.0", Some(55149), None), - - /// Allows `#[link(..., cfg(..))]`. - (active, link_cfg, "1.14.0", Some(37406), None), - - /// Allows `extern "ptx-*" fn()`. - (active, abi_ptx, "1.15.0", Some(38788), None), - - /// Allows the `#[repr(i128)]` attribute for enums. - (incomplete, repr128, "1.16.0", Some(56071), None), - - /// Allows `#[link(kind="static-nobundle"...)]`. - (active, static_nobundle, "1.16.0", Some(37403), None), - - /// Allows `extern "msp430-interrupt" fn()`. - (active, abi_msp430_interrupt, "1.16.0", Some(38487), None), - + /// Allows `cfg(target_thread_local)`. + (active, cfg_target_thread_local, "1.7.0", Some(29594), None), + /// Allow conditional compilation depending on rust version + (active, cfg_version, "1.45.0", Some(64796), None), + /// Allows `#[track_caller]` on closures and generators. + (active, closure_track_caller, "1.57.0", Some(87417), None), + /// Allows to use the `#[cmse_nonsecure_entry]` attribute. + (active, cmse_nonsecure_entry, "1.48.0", Some(75835), None), + /// Allows `async {}` expressions in const contexts. + (active, const_async_blocks, "1.53.0", Some(85368), None), + // Allows limiting the evaluation steps of const expressions + (active, const_eval_limit, "1.43.0", Some(67217), None), + /// Allows the definition of `const extern fn` and `const unsafe extern fn`. + (active, const_extern_fn, "1.40.0", Some(64926), None), + /// Allows basic arithmetic on floating point types in a `const fn`. + (active, const_fn_floating_point_arithmetic, "1.48.0", Some(57241), None), + /// Allows using and casting function pointers in a `const fn`. + (active, const_fn_fn_ptr_basics, "1.48.0", Some(57563), None), + /// Allows trait bounds in `const fn`. + (active, const_fn_trait_bound, "1.53.0", Some(57563), None), + /// Allows `for _ in _` loops in const contexts. + (active, const_for, "1.56.0", Some(87575), None), + /// Allows const generics to have default values (e.g. `struct Foo(...);`). + (active, const_generics_defaults, "1.51.0", Some(44580), None), + /// Allows argument and return position `impl Trait` in a `const fn`. + (active, const_impl_trait, "1.48.0", Some(77463), None), + /// Allows using `&mut` in constant functions. + (active, const_mut_refs, "1.41.0", Some(57349), None), + /// Be more precise when looking for live drops in a const context. + (active, const_precise_live_drops, "1.46.0", Some(73255), None), + /// Allows references to types with interior mutability within constants + (active, const_refs_to_cell, "1.51.0", Some(80384), None), + /// Allows `impl const Trait for T` syntax. + (active, const_trait_impl, "1.42.0", Some(67792), None), + /// Allows the `?` operator in const contexts. + (active, const_try, "1.56.0", Some(74935), None), + /// Allows using `crate` as visibility modifier, synonymous with `pub(crate)`. + (active, crate_visibility_modifier, "1.23.0", Some(53120), None), + /// Allows non-builtin attributes in inner attribute position. + (active, custom_inner_attributes, "1.30.0", Some(54726), None), + /// Allows custom test frameworks with `#![test_runner]` and `#[test_case]`. + (active, custom_test_frameworks, "1.30.0", Some(50297), None), /// Allows declarative macros 2.0 (`macro`). (active, decl_macro, "1.17.0", Some(39412), None), - - /// Allows `extern "x86-interrupt" fn()`. - (active, abi_x86_interrupt, "1.17.0", Some(40180), None), - - /// Allows a test to fail without failing the whole suite. - (active, allow_fail, "1.19.0", Some(46488), None), - - /// Allows unsized tuple coercion. - (active, unsized_tuple_coercion, "1.20.0", Some(42877), None), - - /// Allows defining generators. - (active, generators, "1.21.0", Some(43122), None), - + /// Allows rustc to inject a default alloc_error_handler + (active, default_alloc_error_handler, "1.48.0", Some(66741), None), + /// Allows default type parameters to influence type inference. + (active, default_type_parameter_fallback, "1.3.0", Some(27336), None), + /// Allows `#[derive(Default)]` and `#[default]` on enums. + (active, derive_default_enum, "1.56.0", Some(86985), None), + /// Allows the use of destructuring assignments. + (active, destructuring_assignment, "1.49.0", Some(71126), None), + /// Tells rustdoc to automatically generate `#[doc(cfg(...))]`. + (active, doc_auto_cfg, "1.58.0", Some(43781), None), /// Allows `#[doc(cfg(...))]`. (active, doc_cfg, "1.21.0", Some(43781), None), - + /// Allows `#[doc(cfg_hide(...))]`. + (active, doc_cfg_hide, "1.57.0", Some(43781), None), /// Allows `#[doc(masked)]`. (active, doc_masked, "1.21.0", Some(44027), None), - - /// Allows using `crate` as visibility modifier, synonymous with `pub(crate)`. - (active, crate_visibility_modifier, "1.23.0", Some(53120), None), - + /// Allows `X..Y` patterns. + (active, exclusive_range_pattern, "1.11.0", Some(37854), None), + /// Allows exhaustive pattern matching on types that contain uninhabited types. + (active, exhaustive_patterns, "1.13.0", Some(51085), None), + /// Allows explicit generic arguments specification with `impl Trait` present. + (active, explicit_generic_args_with_impl_trait, "1.56.0", Some(83701), None), /// Allows defining `extern type`s. (active, extern_types, "1.23.0", Some(43467), None), - - /// Allows trait methods with arbitrary self types. - (active, arbitrary_self_types, "1.23.0", Some(44874), None), - - /// Allows in-band quantification of lifetime bindings (e.g., `fn foo(x: &'a u8) -> &'a u8`). - (active, in_band_lifetimes, "1.23.0", Some(44524), None), - + /// Allows the use of `#[ffi_const]` on foreign functions. + (active, ffi_const, "1.45.0", Some(58328), None), + /// Allows the use of `#[ffi_pure]` on foreign functions. + (active, ffi_pure, "1.45.0", Some(58329), None), + /// Allows using `#[ffi_returns_twice]` on foreign functions. + (active, ffi_returns_twice, "1.34.0", Some(58314), None), + /// Allows using `#[repr(align(...))]` on function items + (active, fn_align, "1.53.0", Some(82232), None), + /// Allows defining generators. + (active, generators, "1.21.0", Some(43122), None), + /// Infer generic args for both consts and types. + (active, generic_arg_infer, "1.55.0", Some(85077), None), /// Allows associated types to be generic, e.g., `type Foo;` (RFC 1598). (active, generic_associated_types, "1.23.0", Some(44265), None), - - /// Allows defining `trait X = A + B;` alias items. - (active, trait_alias, "1.24.0", Some(41517), None), - + /// Allows non-trivial generic constants which have to have wfness manually propagated to callers + (incomplete, generic_const_exprs, "1.56.0", Some(76560), None), + /// Allows using `..X`, `..=X`, `...X`, and `X..` as a pattern. + (active, half_open_range_patterns, "1.41.0", Some(67264), None), + /// Allows `if let` guard in match arms. + (active, if_let_guard, "1.47.0", Some(51114), None), + /// Allows using imported `main` function + (active, imported_main, "1.53.0", Some(28937), None), + /// Allows in-band quantification of lifetime bindings (e.g., `fn foo(x: &'a u8) -> &'a u8`). + (active, in_band_lifetimes, "1.23.0", Some(44524), None), /// Allows inferring `'static` outlives requirements (RFC 2093). (active, infer_static_outlives_requirements, "1.26.0", Some(54185), None), - - /// Allows dereferencing raw pointers during const eval. - (active, const_raw_ptr_deref, "1.27.0", Some(51911), None), - - /// Allows inconsistent bounds in where clauses. - (active, trivial_bounds, "1.28.0", Some(48214), None), - + /// Allows associated types in inherent impls. + (incomplete, inherent_associated_types, "1.52.0", Some(8995), None), + /// Allow anonymous constants from an inline `const` block + (active, inline_const, "1.49.0", Some(76001), None), + /// Allow anonymous constants from an inline `const` block in pattern position + (incomplete, inline_const_pat, "1.58.0", Some(76001), None), + /// Allows using `pointer` and `reference` in intra-doc links + (active, intra_doc_pointers, "1.51.0", Some(80896), None), + /// Allows `#[instruction_set(_)]` attribute + (active, isa_attribute, "1.48.0", Some(74727), None), /// Allows `'a: { break 'a; }`. (active, label_break_value, "1.28.0", Some(48594), None), - - /// Allows using `#[doc(keyword = "...")]`. - (active, doc_keyword, "1.28.0", Some(51315), None), - - /// Allows using `try {...}` expressions. - (active, try_blocks, "1.29.0", Some(31436), None), - - /// Allows defining an `#[alloc_error_handler]`. - (active, alloc_error_handler, "1.29.0", Some(51540), None), - - /// Allows using the `amdgpu-kernel` ABI. - (active, abi_amdgpu_kernel, "1.29.0", Some(51575), None), - - /// Allows `#[marker]` on certain traits allowing overlapping implementations. - (active, marker_trait_attr, "1.30.0", Some(29864), None), - - /// Allows macro attributes on expressions, statements and non-inline modules. - (active, proc_macro_hygiene, "1.30.0", Some(54727), None), - - /// Allows unsized rvalues at arguments and parameters. - (incomplete, unsized_locals, "1.30.0", Some(48055), None), - - /// Allows custom test frameworks with `#![test_runner]` and `#[test_case]`. - (active, custom_test_frameworks, "1.30.0", Some(50297), None), - - /// Allows non-builtin attributes in inner attribute position. - (active, custom_inner_attributes, "1.30.0", Some(54726), None), - + // Allows setting the threshold for the `large_assignments` lint. + (active, large_assignments, "1.52.0", Some(83518), None), + /// Allows `if/while p && let q = r && ...` chains. + (incomplete, let_chains, "1.37.0", Some(53667), None), + /// Allows `let...else` statements. + (active, let_else, "1.56.0", Some(87335), None), + /// Allows `#[link(..., cfg(..))]`. + (active, link_cfg, "1.14.0", Some(37406), None), /// Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check. (active, lint_reasons, "1.31.0", Some(54503), None), - - /// Allows exhaustive integer pattern matching on `usize` and `isize`. - (active, precise_pointer_size_matching, "1.32.0", Some(56354), None), - - /// Allows using `#[ffi_returns_twice]` on foreign functions. - (active, ffi_returns_twice, "1.34.0", Some(58314), None), - + /// Allows `#[marker]` on certain traits allowing overlapping implementations. + (active, marker_trait_attr, "1.30.0", Some(29864), None), + /// A minimal, sound subset of specialization intended to be used by the + /// standard library until the soundness issues with specialization + /// are fixed. + (active, min_specialization, "1.7.0", Some(31844), None), + /// Allows qualified paths in struct expressions, struct patterns and tuple struct patterns. + (active, more_qualified_paths, "1.54.0", Some(86935), None), + /// Allows the `#[must_not_suspend]` attribute. + (active, must_not_suspend, "1.57.0", Some(83310), None), + /// Allows using `#[naked]` on functions. + (active, naked_functions, "1.9.0", Some(32408), None), + /// Allows specifying modifiers in the link attribute: `#[link(modifiers = "...")]` + (active, native_link_modifiers, "1.53.0", Some(81490), None), + /// Allows specifying the as-needed link modifier + (active, native_link_modifiers_as_needed, "1.53.0", Some(81490), None), + /// Allows specifying the bundle link modifier + (active, native_link_modifiers_bundle, "1.53.0", Some(81490), None), + /// Allows specifying the verbatim link modifier + (active, native_link_modifiers_verbatim, "1.53.0", Some(81490), None), + /// Allows specifying the whole-archive link modifier + (active, native_link_modifiers_whole_archive, "1.53.0", Some(81490), None), + /// Allow negative trait implementations. + (active, negative_impls, "1.44.0", Some(68318), None), + /// Allows the `!` type. Does not imply 'exhaustive_patterns' (below) any more. + (active, never_type, "1.13.0", Some(35121), None), + /// Allows diverging expressions to fall back to `!` rather than `()`. + (active, never_type_fallback, "1.41.0", Some(65992), None), + /// Allows using non lexical lifetimes (RFC 2094). + (active, nll, "1.0.0", Some(43234), None), + /// Allows `#![no_core]`. + (active, no_core, "1.3.0", Some(29639), None), + /// Allows function attribute `#[no_coverage]`, to bypass coverage + /// instrumentation of that function. + (active, no_coverage, "1.53.0", Some(84605), None), + /// Allows the use of `no_sanitize` attribute. + (active, no_sanitize, "1.42.0", Some(39699), None), + /// Allows using the `non_exhaustive_omitted_patterns` lint. + (active, non_exhaustive_omitted_patterns_lint, "1.57.0", Some(89554), None), + /// Allows making `dyn Trait` well-formed even if `Trait` is not object safe. + /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and + /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden. + (active, object_safe_for_dispatch, "1.40.0", Some(43561), None), /// Allows using `#[optimize(X)]`. (active, optimize_attribute, "1.34.0", Some(54882), None), - - /// Allows using C-variadics. - (active, c_variadic, "1.34.0", Some(44930), None), - - /// Allows the user of associated type bounds. - (active, associated_type_bounds, "1.34.0", Some(52662), None), - - /// Allows `if/while p && let q = r && ...` chains. - (incomplete, let_chains, "1.37.0", Some(53667), None), - - /// Allows #[repr(transparent)] on unions (RFC 2645). - (active, transparent_unions, "1.37.0", Some(60405), None), - - /// Allows explicit discriminants on non-unit enum variants. - (active, arbitrary_enum_discriminant, "1.37.0", Some(60553), None), - - /// Allows `async || body` closures. - (active, async_closure, "1.37.0", Some(62290), None), - - /// Allows `impl Trait` to be used inside type aliases (RFC 2515). - (active, type_alias_impl_trait, "1.38.0", Some(63063), None), - - /// Allows the definition of `const extern fn` and `const unsafe extern fn`. - (active, const_extern_fn, "1.40.0", Some(64926), None), - + /// Allows `extern "platform-intrinsic" { ... }`. + (active, platform_intrinsics, "1.4.0", Some(27731), None), + /// Allows using `#![plugin(myplugin)]`. + (active, plugin, "1.0.0", Some(29597), None), + /// Allows exhaustive integer pattern matching on `usize` and `isize`. + (active, precise_pointer_size_matching, "1.32.0", Some(56354), None), + /// Allows macro attributes on expressions, statements and non-inline modules. + (active, proc_macro_hygiene, "1.30.0", Some(54727), None), /// Allows the use of raw-dylibs (RFC 2627). (incomplete, raw_dylib, "1.40.0", Some(58713), None), - - /// Allows making `dyn Trait` well-formed even if `Trait` is not object safe. - /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and - /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden. - (active, object_safe_for_dispatch, "1.40.0", Some(43561), None), - - /// Allows using the `efiapi` ABI. - (active, abi_efiapi, "1.40.0", Some(65815), None), - /// Allows `&raw const $place_expr` and `&raw mut $place_expr` expressions. (active, raw_ref_op, "1.41.0", Some(64490), None), - - /// Allows diverging expressions to fall back to `!` rather than `()`. - (active, never_type_fallback, "1.41.0", Some(65992), None), - /// Allows using the `#[register_attr]` attribute. (active, register_attr, "1.41.0", Some(66080), None), - /// Allows using the `#[register_tool]` attribute. (active, register_tool, "1.41.0", Some(66079), None), - - /// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used. - (active, cfg_sanitize, "1.41.0", Some(39699), None), - - /// Allows using `..X`, `..=X`, `...X`, and `X..` as a pattern. - (active, half_open_range_patterns, "1.41.0", Some(67264), None), - - /// Allows using `&mut` in constant functions. - (active, const_mut_refs, "1.41.0", Some(57349), None), - - /// Allows `impl const Trait for T` syntax. - (active, const_trait_impl, "1.42.0", Some(67792), None), - - /// Allows the use of `no_sanitize` attribute. - (active, no_sanitize, "1.42.0", Some(39699), None), - - // Allows limiting the evaluation steps of const expressions - (active, const_eval_limit, "1.43.0", Some(67217), None), - - /// Allow negative trait implementations. - (active, negative_impls, "1.44.0", Some(68318), None), - + /// Allows the `#[repr(i128)]` attribute for enums. + (incomplete, repr128, "1.16.0", Some(56071), None), + /// Allows `repr(simd)` and importing the various simd intrinsics. + (active, repr_simd, "1.4.0", Some(27731), None), + /// Allows the use of SIMD types in functions declared in `extern` blocks. + (active, simd_ffi, "1.0.0", Some(27731), None), + /// Allows specialization of implementations (RFC 1210). + (incomplete, specialization, "1.7.0", Some(31844), None), + /// Allows `#[link(kind="static-nobundle"...)]`. + (active, static_nobundle, "1.16.0", Some(37403), None), + /// Allows attributes on expressions and non-item statements. + (active, stmt_expr_attributes, "1.6.0", Some(15701), None), /// Allows the use of `#[target_feature]` on safe functions. (active, target_feature_11, "1.45.0", Some(69098), None), - - /// Allow conditional compilation depending on rust version - (active, cfg_version, "1.45.0", Some(64796), None), - - /// Allows the use of `#[ffi_pure]` on foreign functions. - (active, ffi_pure, "1.45.0", Some(58329), None), - - /// Allows the use of `#[ffi_const]` on foreign functions. - (active, ffi_const, "1.45.0", Some(58328), None), - - /// Allows `extern "avr-interrupt" fn()` and `extern "avr-non-blocking-interrupt" fn()`. - (active, abi_avr_interrupt, "1.45.0", Some(69664), None), - - /// Be more precise when looking for live drops in a const context. - (active, const_precise_live_drops, "1.46.0", Some(73255), None), - - /// Allows capturing variables in scope using format_args! - (active, format_args_capture, "1.46.0", Some(67984), None), - - /// Allows `if let` guard in match arms. - (active, if_let_guard, "1.47.0", Some(51114), None), - - /// Allows basic arithmetic on floating point types in a `const fn`. - (active, const_fn_floating_point_arithmetic, "1.48.0", Some(57241), None), - - /// Allows using and casting function pointers in a `const fn`. - (active, const_fn_fn_ptr_basics, "1.48.0", Some(57563), None), - - /// Allows to use the `#[cmse_nonsecure_entry]` attribute. - (active, cmse_nonsecure_entry, "1.48.0", Some(75835), None), - - /// Allows rustc to inject a default alloc_error_handler - (active, default_alloc_error_handler, "1.48.0", Some(66741), None), - - /// Allows argument and return position `impl Trait` in a `const fn`. - (active, const_impl_trait, "1.48.0", Some(77463), None), - - /// Allows `#[instruction_set(_)]` attribute - (active, isa_attribute, "1.48.0", Some(74727), None), - - /// Allow anonymous constants from an inline `const` block - (incomplete, inline_const, "1.49.0", Some(76001), None), - + /// Allows using `#[thread_local]` on `static` items. + (active, thread_local, "1.0.0", Some(29594), None), + /// Allows defining `trait X = A + B;` alias items. + (active, trait_alias, "1.24.0", Some(41517), None), + /// Allows upcasting trait objects via supertraits. + /// Trait upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`. + (incomplete, trait_upcasting, "1.56.0", Some(65991), None), + /// Allows #[repr(transparent)] on unions (RFC 2645). + (active, transparent_unions, "1.37.0", Some(60405), None), + /// Allows inconsistent bounds in where clauses. + (active, trivial_bounds, "1.28.0", Some(48214), None), + /// Allows using `try {...}` expressions. + (active, try_blocks, "1.29.0", Some(31436), None), + /// 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 type ascription in expressions. + (active, type_ascription, "1.6.0", Some(23416), None), + /// Allows creation of instances of a struct by moving fields that have + /// not changed from prior instances of the same struct (RFC #2528) + (incomplete, type_changing_struct_update, "1.58.0", Some(86555), None), /// Allows unsized fn parameters. (active, unsized_fn_params, "1.49.0", Some(48055), None), - - /// Allows the use of destructuring assignments. - (active, destructuring_assignment, "1.49.0", Some(71126), None), - - /// Enables `#[cfg(panic = "...")]` config key. - (active, cfg_panic, "1.49.0", Some(77443), None), - - /// Allows capturing disjoint fields in a closure/generator (RFC 2229). - (incomplete, capture_disjoint_fields, "1.49.0", Some(53488), None), - - /// Allows const generics to have default values (e.g. `struct Foo(...);`). - (active, const_generics_defaults, "1.51.0", Some(44580), None), - - /// Allows references to types with interior mutability within constants - (active, const_refs_to_cell, "1.51.0", Some(80384), None), - - /// Allows using `pointer` and `reference` in intra-doc links - (active, intra_doc_pointers, "1.51.0", Some(80896), None), - - /// Allows `extern "C-cmse-nonsecure-call" fn()`. - (active, abi_c_cmse_nonsecure_call, "1.51.0", Some(81391), None), - - /// Lessens the requirements for structs to implement `Unsize`. - (active, relaxed_struct_unsize, "1.51.0", Some(81793), None), - - /// Allows associated types in inherent impls. - (incomplete, inherent_associated_types, "1.52.0", Some(8995), None), - - // Allows setting the threshold for the `large_assignments` lint. - (active, large_assignments, "1.52.0", Some(83518), None), - - /// Allows `extern "C-unwind" fn` to enable unwinding across ABI boundaries. - (active, c_unwind, "1.52.0", Some(74990), None), - - /// Allows using `#[repr(align(...))]` on function items - (active, fn_align, "1.53.0", Some(82232), None), - + /// Allows unsized rvalues at arguments and parameters. + (incomplete, unsized_locals, "1.30.0", Some(48055), None), + /// Allows unsized tuple coercion. + (active, unsized_tuple_coercion, "1.20.0", Some(42877), None), + /// Allows `union`s to implement `Drop`. Moreover, `union`s may now include fields + /// that don't implement `Copy` as long as they don't have any drop glue. + /// This is checked recursively. On encountering type variable where no progress can be made, + /// `T: Copy` is used as a substitute for "no drop glue". + /// + /// NOTE: A limited form of `union U { ... }` was accepted in 1.19.0. + (active, untagged_unions, "1.13.0", Some(55149), 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 `async {}` expressions in const contexts. - (active, const_async_blocks, "1.53.0", Some(85368), None), - - /// Allows using imported `main` function - (active, imported_main, "1.53.0", Some(28937), None), - - /// Allows specifying modifiers in the link attribute: `#[link(modifiers = "...")]` - (active, native_link_modifiers, "1.53.0", Some(81490), None), - - /// Allows specifying the bundle link modifier - (active, native_link_modifiers_bundle, "1.53.0", Some(81490), None), - - /// Allows specifying the verbatim link modifier - (active, native_link_modifiers_verbatim, "1.53.0", Some(81490), None), - - /// Allows specifying the whole-archive link modifier - (active, native_link_modifiers_whole_archive, "1.53.0", Some(81490), None), - - /// Allows specifying the as-needed link modifier - (active, native_link_modifiers_as_needed, "1.53.0", Some(81490), None), - - /// Allows qualified paths in struct expressions, struct patterns and tuple struct patterns. - (active, more_qualified_paths, "1.54.0", Some(86935), None), - - /// Allows `cfg(target_abi = "...")`. - (active, cfg_target_abi, "1.55.0", Some(80970), None), - - /// Infer generic args for both consts and types. - (active, generic_arg_infer, "1.55.0", Some(85077), None), - - /// Allows `#[derive(Default)]` and `#[default]` on enums. - (active, derive_default_enum, "1.56.0", Some(86985), None), - - /// Allows `for _ in _` loops in const contexts. - (active, const_for, "1.56.0", Some(87575), None), - - /// Allows the `?` operator in const contexts. - (active, const_try, "1.56.0", Some(74935), None), - - /// Allows upcasting trait objects via supertraits. - /// Trait upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`. - (incomplete, trait_upcasting, "1.56.0", Some(65991), None), - - /// Allows explicit generic arguments specification with `impl Trait` present. - (active, explicit_generic_args_with_impl_trait, "1.56.0", Some(83701), None), - - /// Allows using doc(primitive) without a future-incompat warning - (active, doc_primitive, "1.56.0", Some(88070), None), - - /// Allows non-trivial generic constants which have to have wfness manually propagated to callers - (incomplete, generic_const_exprs, "1.56.0", Some(76560), None), - - /// Allows additional const parameter types, such as `&'static str` or user defined types - (incomplete, adt_const_params, "1.56.0", Some(44580), None), - - /// Allows `let...else` statements. - (active, let_else, "1.56.0", Some(87335), None), - - /// Allows the `#[must_not_suspend]` attribute. - (active, must_not_suspend, "1.57.0", Some(83310), None), - - /// Allows `#[track_caller]` on closures and generators. - (active, closure_track_caller, "1.57.0", Some(87417), None), - - /// Allows `#[doc(cfg_hide(...))]`. - (active, doc_cfg_hide, "1.57.0", Some(43781), None), - - /// Allows using the `non_exhaustive_omitted_patterns` lint. - (active, non_exhaustive_omitted_patterns_lint, "1.57.0", Some(89554), None), - - /// Tells rustdoc to automatically generate `#[doc(cfg(...))]`. - (active, doc_auto_cfg, "1.57.0", Some(43781), None), + // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! + // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way. + // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! // ------------------------------------------------------------------------- // 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 85b0db468d..f25b2d8f56 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -1,5 +1,6 @@ //! Built-in attributes and `cfg` flag gating. +use AttributeDuplicates::*; use AttributeGate::*; use AttributeType::*; @@ -88,11 +89,66 @@ impl AttributeGate { /// Only top-level shape (`#[attr]` vs `#[attr(...)]` vs `#[attr = ...]`) is considered now. #[derive(Clone, Copy, Default)] pub struct AttributeTemplate { + /// If `true`, the attribute is allowed to be a bare word like `#[test]`. pub word: bool, + /// If `Some`, the attribute is allowed to take a list of items like `#[allow(..)]`. pub list: Option<&'static str>, + /// If `Some`, the attribute is allowed to be a name/value pair where the + /// value is a string, like `#[must_use = "reason"]`. pub name_value_str: Option<&'static str>, } +/// How to handle multiple duplicate attributes on the same item. +#[derive(Clone, Copy, Default)] +pub enum AttributeDuplicates { + /// Duplicates of this attribute are allowed. + /// + /// This should only be used with attributes where duplicates have semantic + /// meaning, or some kind of "additive" behavior. For example, `#[warn(..)]` + /// can be specified multiple times, and it combines all the entries. Or use + /// this if there is validation done elsewhere. + #[default] + DuplicatesOk, + /// Duplicates after the first attribute will be an unused_attribute warning. + /// + /// This is usually used for "word" attributes, where they are used as a + /// boolean marker, like `#[used]`. It is not necessarily wrong that there + /// are duplicates, but the others should probably be removed. + WarnFollowing, + /// Same as `WarnFollowing`, but only issues warnings for word-style attributes. + /// + /// This is only for special cases, for example multiple `#[macro_use]` can + /// be warned, but multiple `#[macro_use(...)]` should not because the list + /// form has different meaning from the word form. + WarnFollowingWordOnly, + /// Duplicates after the first attribute will be an error. + /// + /// This should be used where duplicates would be ignored, but carry extra + /// meaning that could cause confusion. For example, `#[stable(since="1.0")] + /// #[stable(since="2.0")]`, which version should be used for `stable`? + ErrorFollowing, + /// Duplicates preceding the last instance of the attribute will be an error. + /// + /// This is the same as `ErrorFollowing`, except the last attribute is the + /// one that is "used". This is typically used in cases like codegen + /// attributes which usually only honor the last attribute. + ErrorPreceding, + /// Duplicates after the first attribute will be an unused_attribute warning + /// with a note that this will be an error in the future. + /// + /// This should be used for attributes that should be `ErrorFollowing`, but + /// because older versions of rustc silently accepted (and ignored) the + /// attributes, this is used to transition. + FutureWarnFollowing, + /// Duplicates preceding the last instance of the attribute will be a + /// warning, with a note that this will be an error in the future. + /// + /// This is the same as `FutureWarnFollowing`, except the last attribute is + /// the one that is "used". Ideally these can eventually migrate to + /// `ErrorPreceding`. + FutureWarnPreceding, +} + /// A convenience macro for constructing attribute templates. /// E.g., `template!(Word, List: "description")` means that the attribute /// supports forms `#[attr]` and `#[attr(description)]`. @@ -114,26 +170,45 @@ macro_rules! template { } macro_rules! ungated { - ($attr:ident, $typ:expr, $tpl:expr $(,)?) => { - (sym::$attr, $typ, $tpl, Ungated) + ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr $(,)?) => { + BuiltinAttribute { + name: sym::$attr, + type_: $typ, + template: $tpl, + gate: Ungated, + duplicates: $duplicates, + } }; } macro_rules! gated { - ($attr:ident, $typ:expr, $tpl:expr, $gate:ident, $msg:expr $(,)?) => { - (sym::$attr, $typ, $tpl, Gated(Stability::Unstable, sym::$gate, $msg, cfg_fn!($gate))) + ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $gate:ident, $msg:expr $(,)?) => { + BuiltinAttribute { + name: sym::$attr, + type_: $typ, + template: $tpl, + duplicates: $duplicates, + gate: Gated(Stability::Unstable, sym::$gate, $msg, cfg_fn!($gate)), + } }; - ($attr:ident, $typ:expr, $tpl:expr, $msg:expr $(,)?) => { - (sym::$attr, $typ, $tpl, Gated(Stability::Unstable, sym::$attr, $msg, cfg_fn!($attr))) + ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $msg:expr $(,)?) => { + BuiltinAttribute { + name: sym::$attr, + type_: $typ, + template: $tpl, + duplicates: $duplicates, + gate: Gated(Stability::Unstable, sym::$attr, $msg, cfg_fn!($attr)), + } }; } macro_rules! rustc_attr { - (TEST, $attr:ident, $typ:expr, $tpl:expr $(,)?) => { + (TEST, $attr:ident, $typ:expr, $tpl:expr, $duplicate:expr $(,)?) => { rustc_attr!( $attr, $typ, $tpl, + $duplicate, concat!( "the `#[", stringify!($attr), @@ -142,13 +217,14 @@ macro_rules! rustc_attr { ), ) }; - ($attr:ident, $typ:expr, $tpl:expr, $msg:expr $(,)?) => { - ( - sym::$attr, - $typ, - $tpl, - Gated(Stability::Unstable, sym::rustc_attrs, $msg, cfg_fn!(rustc_attrs)), - ) + ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $msg:expr $(,)?) => { + BuiltinAttribute { + name: sym::$attr, + type_: $typ, + template: $tpl, + duplicates: $duplicates, + gate: Gated(Stability::Unstable, sym::rustc_attrs, $msg, cfg_fn!(rustc_attrs)), + } }; } @@ -161,7 +237,13 @@ macro_rules! experimental { const IMPL_DETAIL: &str = "internal implementation detail"; const INTERNAL_UNSTABLE: &str = "this is an internal attribute that will never be stable"; -pub type BuiltinAttribute = (Symbol, AttributeType, AttributeTemplate, AttributeGate); +pub struct BuiltinAttribute { + pub name: Symbol, + pub type_: AttributeType, + pub template: AttributeTemplate, + pub duplicates: AttributeDuplicates, + pub gate: AttributeGate, +} /// Attributes that have a special meaning to rustc or rustdoc. #[rustfmt::skip] @@ -171,42 +253,48 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // ========================================================================== // Conditional compilation: - ungated!(cfg, Normal, template!(List: "predicate")), - ungated!(cfg_attr, Normal, template!(List: "predicate, attr1, attr2, ...")), + ungated!(cfg, Normal, template!(List: "predicate"), DuplicatesOk), + ungated!(cfg_attr, Normal, template!(List: "predicate, attr1, attr2, ..."), DuplicatesOk), // Testing: - ungated!(ignore, Normal, template!(Word, NameValueStr: "reason")), + ungated!(ignore, Normal, template!(Word, NameValueStr: "reason"), WarnFollowing), ungated!( should_panic, Normal, - template!(Word, List: r#"expected = "reason"#, NameValueStr: "reason"), + template!(Word, List: r#"expected = "reason"#, NameValueStr: "reason"), FutureWarnFollowing, ), // FIXME(Centril): This can be used on stable but shouldn't. - ungated!(reexport_test_harness_main, CrateLevel, template!(NameValueStr: "name")), + ungated!(reexport_test_harness_main, CrateLevel, template!(NameValueStr: "name"), ErrorFollowing), // Macros: - ungated!(automatically_derived, Normal, template!(Word)), - // FIXME(#14407) - ungated!(macro_use, Normal, template!(Word, List: "name1, name2, ...")), - ungated!(macro_escape, Normal, template!(Word)), // Deprecated synonym for `macro_use`. - ungated!(macro_export, Normal, template!(Word, List: "local_inner_macros")), - ungated!(proc_macro, Normal, template!(Word)), + ungated!(automatically_derived, Normal, template!(Word), WarnFollowing), + ungated!(macro_use, Normal, template!(Word, List: "name1, name2, ..."), WarnFollowingWordOnly), + ungated!(macro_escape, Normal, template!(Word), WarnFollowing), // Deprecated synonym for `macro_use`. + ungated!(macro_export, Normal, template!(Word, List: "local_inner_macros"), WarnFollowing), + ungated!(proc_macro, Normal, template!(Word), ErrorFollowing), ungated!( proc_macro_derive, Normal, - template!(List: "TraitName, /*opt*/ attributes(name1, name2, ...)"), + template!(List: "TraitName, /*opt*/ attributes(name1, name2, ...)"), ErrorFollowing, ), - ungated!(proc_macro_attribute, Normal, template!(Word)), + ungated!(proc_macro_attribute, Normal, template!(Word), ErrorFollowing), // Lints: - ungated!(warn, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), - ungated!(allow, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), - ungated!(forbid, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), - ungated!(deny, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), - ungated!(must_use, Normal, template!(Word, NameValueStr: "reason")), + ungated!( + warn, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk + ), + ungated!( + allow, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk + ), + ungated!( + forbid, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk + ), + ungated!( + deny, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk + ), + ungated!(must_use, Normal, template!(Word, NameValueStr: "reason"), FutureWarnFollowing), gated!( - must_not_suspend, Normal, template!(Word, NameValueStr: "reason"), must_not_suspend, - experimental!(must_not_suspend) + must_not_suspend, Normal, template!(Word, NameValueStr: "reason"), WarnFollowing, + must_not_suspend, experimental!(must_not_suspend) ), - // FIXME(#14407) ungated!( deprecated, Normal, template!( @@ -214,85 +302,96 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ List: r#"/*opt*/ since = "version", /*opt*/ note = "reason""#, NameValueStr: "reason" ), + // This has special duplicate handling in E0550 to handle duplicates with rustc_deprecated + DuplicatesOk ), // Crate properties: - ungated!(crate_name, CrateLevel, template!(NameValueStr: "name")), - ungated!(crate_type, CrateLevel, template!(NameValueStr: "bin|lib|...")), - ungated!(crate_id, CrateLevel, template!(NameValueStr: "ignored")), + ungated!(crate_name, CrateLevel, template!(NameValueStr: "name"), FutureWarnFollowing), + ungated!(crate_type, CrateLevel, template!(NameValueStr: "bin|lib|..."), FutureWarnFollowing), + // crate_id is deprecated + ungated!(crate_id, CrateLevel, template!(NameValueStr: "ignored"), FutureWarnFollowing), // ABI, linking, symbols, and FFI ungated!( link, Normal, template!(List: r#"name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...""#), + DuplicatesOk, ), - ungated!(link_name, Normal, template!(NameValueStr: "name")), - ungated!(no_link, Normal, template!(Word)), - ungated!(repr, Normal, template!(List: "C")), - ungated!(export_name, Normal, template!(NameValueStr: "name")), - ungated!(link_section, Normal, template!(NameValueStr: "name")), - ungated!(no_mangle, Normal, template!(Word)), - ungated!(used, Normal, template!(Word)), + ungated!(link_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding), + ungated!(no_link, Normal, template!(Word), WarnFollowing), + ungated!(repr, Normal, template!(List: "C"), DuplicatesOk), + ungated!(export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding), + ungated!(link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding), + ungated!(no_mangle, Normal, template!(Word), WarnFollowing), + ungated!(used, Normal, template!(Word), WarnFollowing), // Limits: - ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N")), - ungated!(type_length_limit, CrateLevel, template!(NameValueStr: "N")), + ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing), + ungated!(type_length_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing), gated!( - const_eval_limit, CrateLevel, template!(NameValueStr: "N"), const_eval_limit, - experimental!(const_eval_limit) + const_eval_limit, CrateLevel, template!(NameValueStr: "N"), ErrorFollowing, + const_eval_limit, experimental!(const_eval_limit) ), gated!( - move_size_limit, CrateLevel, template!(NameValueStr: "N"), large_assignments, - experimental!(move_size_limit) + move_size_limit, CrateLevel, template!(NameValueStr: "N"), ErrorFollowing, + large_assignments, experimental!(move_size_limit) ), // Entry point: - ungated!(main, Normal, template!(Word)), - ungated!(start, Normal, template!(Word)), - ungated!(no_start, CrateLevel, template!(Word)), - ungated!(no_main, CrateLevel, template!(Word)), + ungated!(main, Normal, template!(Word), WarnFollowing), + ungated!(start, Normal, template!(Word), WarnFollowing), + ungated!(no_start, CrateLevel, template!(Word), WarnFollowing), + ungated!(no_main, CrateLevel, template!(Word), WarnFollowing), // Modules, prelude, and resolution: - ungated!(path, Normal, template!(NameValueStr: "file")), - ungated!(no_std, CrateLevel, template!(Word)), - ungated!(no_implicit_prelude, Normal, template!(Word)), - ungated!(non_exhaustive, Normal, template!(Word)), + ungated!(path, Normal, template!(NameValueStr: "file"), FutureWarnFollowing), + ungated!(no_std, CrateLevel, template!(Word), WarnFollowing), + ungated!(no_implicit_prelude, Normal, template!(Word), WarnFollowing), + ungated!(non_exhaustive, Normal, template!(Word), WarnFollowing), // Runtime - ungated!(windows_subsystem, Normal, template!(NameValueStr: "windows|console")), - ungated!(panic_handler, Normal, template!(Word)), // RFC 2070 + ungated!( + windows_subsystem, Normal, + template!(NameValueStr: "windows|console"), FutureWarnFollowing + ), + ungated!(panic_handler, Normal, template!(Word), WarnFollowing), // RFC 2070 // Code generation: - ungated!(inline, Normal, template!(Word, List: "always|never")), - ungated!(cold, Normal, template!(Word)), - ungated!(no_builtins, Normal, template!(Word)), - ungated!(target_feature, Normal, template!(List: r#"enable = "name""#)), - ungated!(track_caller, Normal, template!(Word)), + ungated!(inline, Normal, template!(Word, List: "always|never"), FutureWarnFollowing), + ungated!(cold, Normal, template!(Word), WarnFollowing), + ungated!(no_builtins, Normal, template!(Word), WarnFollowing), + ungated!(target_feature, Normal, template!(List: r#"enable = "name""#), DuplicatesOk), + ungated!(track_caller, Normal, template!(Word), WarnFollowing), gated!( no_sanitize, Normal, - template!(List: "address, memory, thread"), + template!(List: "address, memory, thread"), DuplicatesOk, experimental!(no_sanitize) ), - gated!(no_coverage, Normal, template!(Word), experimental!(no_coverage)), + gated!(no_coverage, Normal, template!(Word), WarnFollowing, experimental!(no_coverage)), - // FIXME: #14408 assume docs are used since rustdoc looks at them. - ungated!(doc, Normal, template!(List: "hidden|inline|...", NameValueStr: "string")), + ungated!( + doc, Normal, template!(List: "hidden|inline|...", NameValueStr: "string"), DuplicatesOk + ), // ========================================================================== // Unstable attributes: // ========================================================================== // Linking: - gated!(naked, Normal, template!(Word), naked_functions, experimental!(naked)), + gated!(naked, Normal, template!(Word), WarnFollowing, naked_functions, experimental!(naked)), gated!( - link_ordinal, Normal, template!(List: "ordinal"), raw_dylib, + link_ordinal, Normal, template!(List: "ordinal"), ErrorPreceding, raw_dylib, experimental!(link_ordinal) ), // Plugins: - ( - sym::plugin, CrateLevel, template!(List: "name"), - Gated( + BuiltinAttribute { + name: sym::plugin, + type_: CrateLevel, + template: template!(List: "name"), + duplicates: DuplicatesOk, + gate: Gated( Stability::Deprecated( "https://github.com/rust-lang/rust/pull/64675", Some("may be removed in a future compiler version"), @@ -300,46 +399,56 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ sym::plugin, "compiler plugins are deprecated", cfg_fn!(plugin) - ) - ), + ), + }, // Testing: - gated!(allow_fail, Normal, template!(Word), experimental!(allow_fail)), + gated!(allow_fail, Normal, template!(Word), WarnFollowing, experimental!(allow_fail)), gated!( - test_runner, CrateLevel, template!(List: "path"), custom_test_frameworks, + test_runner, CrateLevel, template!(List: "path"), ErrorFollowing, custom_test_frameworks, "custom test frameworks are an unstable feature", ), // RFC #1268 - gated!(marker, Normal, template!(Word), marker_trait_attr, experimental!(marker)), gated!( - thread_local, Normal, template!(Word), + marker, Normal, template!(Word), WarnFollowing, marker_trait_attr, experimental!(marker) + ), + gated!( + thread_local, Normal, template!(Word), WarnFollowing, "`#[thread_local]` is an experimental feature, and does not currently handle destructors", ), - gated!(no_core, CrateLevel, template!(Word), experimental!(no_core)), + gated!(no_core, CrateLevel, template!(Word), WarnFollowing, experimental!(no_core)), // RFC 2412 gated!( - optimize, Normal, template!(List: "size|speed"), optimize_attribute, + optimize, Normal, template!(List: "size|speed"), ErrorPreceding, optimize_attribute, experimental!(optimize), ), // RFC 2867 - gated!(instruction_set, Normal, template!(List: "set"), isa_attribute, experimental!(instruction_set)), + gated!( + instruction_set, Normal, template!(List: "set"), ErrorPreceding, + isa_attribute, experimental!(instruction_set) + ), - gated!(ffi_returns_twice, Normal, template!(Word), experimental!(ffi_returns_twice)), - gated!(ffi_pure, Normal, template!(Word), experimental!(ffi_pure)), - gated!(ffi_const, Normal, template!(Word), experimental!(ffi_const)), gated!( - register_attr, CrateLevel, template!(List: "attr1, attr2, ..."), + ffi_returns_twice, Normal, template!(Word), WarnFollowing, experimental!(ffi_returns_twice) + ), + gated!(ffi_pure, Normal, template!(Word), WarnFollowing, experimental!(ffi_pure)), + gated!(ffi_const, Normal, template!(Word), WarnFollowing, experimental!(ffi_const)), + gated!( + register_attr, CrateLevel, template!(List: "attr1, attr2, ..."), DuplicatesOk, experimental!(register_attr), ), gated!( - register_tool, CrateLevel, template!(List: "tool1, tool2, ..."), + register_tool, CrateLevel, template!(List: "tool1, tool2, ..."), DuplicatesOk, experimental!(register_tool), ), - gated!(cmse_nonsecure_entry, Normal, template!(Word), experimental!(cmse_nonsecure_entry)), + gated!( + cmse_nonsecure_entry, Normal, template!(Word), WarnFollowing, + experimental!(cmse_nonsecure_entry) + ), // RFC 2632 gated!( - default_method_body_is_const, Normal, template!(Word), const_trait_impl, + default_method_body_is_const, Normal, template!(Word), WarnFollowing, const_trait_impl, "`default_method_body_is_const` is a temporary placeholder for declaring default bodies \ as `const`, which may be removed or renamed in the future." ), @@ -348,34 +457,33 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Internal attributes: Stability, deprecation, and unsafe: // ========================================================================== - ungated!(feature, CrateLevel, template!(List: "name1, name1, ...")), - // FIXME(#14407) -- only looked at on-demand so we can't - // guarantee they'll have already been checked. + ungated!(feature, CrateLevel, template!(List: "name1, name1, ..."), DuplicatesOk), + // DuplicatesOk since it has its own validation ungated!( rustc_deprecated, Normal, - template!(List: r#"since = "version", reason = "...""#) + template!(List: r#"since = "version", reason = "...""#), DuplicatesOk // See E0550 + ), + // DuplicatesOk since it has its own validation + ungated!( + stable, Normal, template!(List: r#"feature = "name", since = "version""#), DuplicatesOk ), - // FIXME(#14407) - ungated!(stable, Normal, template!(List: r#"feature = "name", since = "version""#)), - // FIXME(#14407) ungated!( unstable, Normal, - template!(List: r#"feature = "name", reason = "...", issue = "N""#), + template!(List: r#"feature = "name", reason = "...", issue = "N""#), DuplicatesOk, ), - // FIXME(#14407) - ungated!(rustc_const_unstable, Normal, template!(List: r#"feature = "name""#)), - // FIXME(#14407) - ungated!(rustc_const_stable, Normal, template!(List: r#"feature = "name""#)), + ungated!(rustc_const_unstable, Normal, template!(List: r#"feature = "name""#), DuplicatesOk), + ungated!(rustc_const_stable, Normal, template!(List: r#"feature = "name""#), DuplicatesOk), gated!( - allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), + allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), DuplicatesOk, "allow_internal_unstable side-steps feature gating and stability checks", ), gated!( - rustc_allow_const_fn_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), + rustc_allow_const_fn_unstable, Normal, + template!(Word, List: "feat1, feat2, ..."), DuplicatesOk, "rustc_allow_const_fn_unstable side-steps feature gating and stability checks" ), gated!( - allow_internal_unsafe, Normal, template!(Word), + allow_internal_unsafe, Normal, template!(Word), WarnFollowing, "allow_internal_unsafe side-steps the unsafe_code lint", ), @@ -383,9 +491,9 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Internal attributes: Type system related: // ========================================================================== - gated!(fundamental, Normal, template!(Word), experimental!(fundamental)), + gated!(fundamental, Normal, template!(Word), WarnFollowing, experimental!(fundamental)), gated!( - may_dangle, Normal, template!(Word), dropck_eyepatch, + may_dangle, Normal, template!(Word), WarnFollowing, dropck_eyepatch, "`may_dangle` has unstable semantics and may be removed in the future", ), @@ -393,26 +501,32 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Internal attributes: Runtime related: // ========================================================================== - rustc_attr!(rustc_allocator, Normal, template!(Word), IMPL_DETAIL), - rustc_attr!(rustc_allocator_nounwind, Normal, template!(Word), IMPL_DETAIL), - gated!(alloc_error_handler, Normal, template!(Word), experimental!(alloc_error_handler)), + rustc_attr!(rustc_allocator, Normal, template!(Word), WarnFollowing, IMPL_DETAIL), + rustc_attr!(rustc_allocator_nounwind, Normal, template!(Word), WarnFollowing, IMPL_DETAIL), gated!( - default_lib_allocator, Normal, template!(Word), allocator_internals, + alloc_error_handler, Normal, template!(Word), WarnFollowing, + experimental!(alloc_error_handler) + ), + gated!( + default_lib_allocator, Normal, template!(Word), WarnFollowing, allocator_internals, experimental!(default_lib_allocator), ), gated!( - needs_allocator, Normal, template!(Word), allocator_internals, + needs_allocator, Normal, template!(Word), WarnFollowing, allocator_internals, experimental!(needs_allocator), ), - gated!(panic_runtime, Normal, template!(Word), experimental!(panic_runtime)), - gated!(needs_panic_runtime, Normal, template!(Word), experimental!(needs_panic_runtime)), + gated!(panic_runtime, Normal, template!(Word), WarnFollowing, experimental!(panic_runtime)), + gated!( + needs_panic_runtime, Normal, template!(Word), WarnFollowing, + experimental!(needs_panic_runtime) + ), gated!( - compiler_builtins, Normal, template!(Word), + compiler_builtins, Normal, template!(Word), WarnFollowing, "the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate \ which contains compiler-rt intrinsics and will never be stable", ), gated!( - profiler_runtime, Normal, template!(Word), + profiler_runtime, Normal, template!(Word), WarnFollowing, "the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate \ which contains the profiler runtime and will never be stable", ), @@ -422,10 +536,12 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // ========================================================================== gated!( - linkage, Normal, template!(NameValueStr: "external|internal|..."), + linkage, Normal, template!(NameValueStr: "external|internal|..."), ErrorPreceding, "the `linkage` attribute is experimental and not portable across platforms", ), - rustc_attr!(rustc_std_internal_symbol, Normal, template!(Word), INTERNAL_UNSTABLE), + rustc_attr!( + rustc_std_internal_symbol, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE + ), // ========================================================================== // Internal attributes, Macro related: @@ -433,13 +549,13 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_attr!( rustc_builtin_macro, Normal, - template!(Word, List: "name, /*opt*/ attributes(name1, name2, ...)"), + template!(Word, List: "name, /*opt*/ attributes(name1, name2, ...)"), ErrorFollowing, IMPL_DETAIL, ), - rustc_attr!(rustc_proc_macro_decls, Normal, template!(Word), INTERNAL_UNSTABLE), + rustc_attr!(rustc_proc_macro_decls, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE), rustc_attr!( rustc_macro_transparency, Normal, - template!(NameValueStr: "transparent|semitransparent|opaque"), + template!(NameValueStr: "transparent|semitransparent|opaque"), ErrorFollowing, "used internally for testing macro hygiene", ), @@ -453,39 +569,49 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ List: r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#, NameValueStr: "message" ), + ErrorFollowing, INTERNAL_UNSTABLE ), // Enumerates "identity-like" conversion methods to suggest on type mismatch. - rustc_attr!(rustc_conversion_suggestion, Normal, template!(Word), INTERNAL_UNSTABLE), + rustc_attr!( + rustc_conversion_suggestion, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE + ), // Prevents field reads in the marked trait or method to be considered // during dead code analysis. - rustc_attr!(rustc_trivial_field_reads, Normal, template!(Word), INTERNAL_UNSTABLE), + rustc_attr!( + rustc_trivial_field_reads, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE + ), // ========================================================================== // Internal attributes, Const related: // ========================================================================== - rustc_attr!(rustc_promotable, Normal, template!(Word), IMPL_DETAIL), - rustc_attr!(rustc_legacy_const_generics, Normal, template!(List: "N"), INTERNAL_UNSTABLE), + rustc_attr!(rustc_promotable, Normal, template!(Word), WarnFollowing, IMPL_DETAIL), + rustc_attr!( + rustc_legacy_const_generics, Normal, template!(List: "N"), ErrorFollowing, + INTERNAL_UNSTABLE + ), // Do not const-check this function's body. It will always get replaced during CTFE. - rustc_attr!(rustc_do_not_const_check, Normal, template!(Word), INTERNAL_UNSTABLE), + rustc_attr!( + rustc_do_not_const_check, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE + ), // ========================================================================== // Internal attributes, Layout related: // ========================================================================== rustc_attr!( - rustc_layout_scalar_valid_range_start, Normal, template!(List: "value"), + rustc_layout_scalar_valid_range_start, Normal, template!(List: "value"), ErrorFollowing, "the `#[rustc_layout_scalar_valid_range_start]` attribute is just used to enable \ niche optimizations in libcore and will never be stable", ), rustc_attr!( - rustc_layout_scalar_valid_range_end, Normal, template!(List: "value"), + rustc_layout_scalar_valid_range_end, Normal, template!(List: "value"), ErrorFollowing, "the `#[rustc_layout_scalar_valid_range_end]` attribute is just used to enable \ niche optimizations in libcore and will never be stable", ), rustc_attr!( - rustc_nonnull_optimization_guaranteed, Normal, template!(Word), + rustc_nonnull_optimization_guaranteed, Normal, template!(Word), WarnFollowing, "the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable \ niche optimizations in libcore and will never be stable", ), @@ -494,57 +620,60 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Internal attributes, Misc: // ========================================================================== gated!( - lang, Normal, template!(NameValueStr: "name"), lang_items, + lang, Normal, template!(NameValueStr: "name"), DuplicatesOk, lang_items, "language items are subject to change", ), - ( - sym::rustc_diagnostic_item, - Normal, - template!(NameValueStr: "name"), - Gated( + BuiltinAttribute { + name: sym::rustc_diagnostic_item, + type_: Normal, + template: template!(NameValueStr: "name"), + duplicates: ErrorFollowing, + gate: Gated( Stability::Unstable, sym::rustc_attrs, "diagnostic items compiler internal support for linting", cfg_fn!(rustc_attrs), ), - ), + }, gated!( // Used in resolve: - prelude_import, Normal, template!(Word), + prelude_import, Normal, template!(Word), WarnFollowing, "`#[prelude_import]` is for use by rustc only", ), gated!( - rustc_paren_sugar, Normal, template!(Word), unboxed_closures, + rustc_paren_sugar, Normal, template!(Word), WarnFollowing, unboxed_closures, "unboxed_closures are still evolving", ), rustc_attr!( - rustc_inherit_overflow_checks, Normal, template!(Word), + rustc_inherit_overflow_checks, Normal, template!(Word), WarnFollowing, "the `#[rustc_inherit_overflow_checks]` attribute is just used to control \ overflow checking behavior of several libcore functions that are inlined \ across crates and will never be stable", ), - rustc_attr!(rustc_reservation_impl, Normal, template!(NameValueStr: "reservation message"), - "the `#[rustc_reservation_impl]` attribute is internally used \ - for reserving for `for From for T` impl" + rustc_attr!( + rustc_reservation_impl, Normal, + template!(NameValueStr: "reservation message"), ErrorFollowing, + "the `#[rustc_reservation_impl]` attribute is internally used \ + for reserving for `for From for T` impl" ), rustc_attr!( - rustc_test_marker, Normal, template!(Word), + rustc_test_marker, Normal, template!(Word), WarnFollowing, "the `#[rustc_test_marker]` attribute is used internally to track tests", ), rustc_attr!( - rustc_unsafe_specialization_marker, Normal, template!(Word), + rustc_unsafe_specialization_marker, Normal, template!(Word), WarnFollowing, "the `#[rustc_unsafe_specialization_marker]` attribute is used to check specializations" ), rustc_attr!( - rustc_specialization_trait, Normal, template!(Word), + rustc_specialization_trait, Normal, template!(Word), WarnFollowing, "the `#[rustc_specialization_trait]` attribute is used to check specializations" ), rustc_attr!( - rustc_main, Normal, template!(Word), + rustc_main, Normal, template!(Word), WarnFollowing, "the `#[rustc_main]` attribute is used internally to specify test entry point function", ), rustc_attr!( - rustc_skip_array_during_method_dispatch, Normal, template!(Word), + rustc_skip_array_during_method_dispatch, Normal, template!(Word), WarnFollowing, "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." ), @@ -553,54 +682,59 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Internal attributes, Testing: // ========================================================================== - rustc_attr!(TEST, rustc_outlives, Normal, template!(Word)), - rustc_attr!(TEST, rustc_capture_analysis, Normal, template!(Word)), - rustc_attr!(TEST, rustc_insignificant_dtor, Normal, template!(Word)), - rustc_attr!(TEST, rustc_variance, Normal, template!(Word)), - rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ...")), - rustc_attr!(TEST, rustc_regions, Normal, template!(Word)), + rustc_attr!(TEST, rustc_outlives, Normal, template!(Word), WarnFollowing), + rustc_attr!(TEST, rustc_capture_analysis, Normal, template!(Word), WarnFollowing), + rustc_attr!(TEST, rustc_insignificant_dtor, Normal, template!(Word), WarnFollowing), + rustc_attr!(TEST, rustc_strict_coherence, Normal, template!(Word), WarnFollowing), + rustc_attr!(TEST, rustc_variance, Normal, template!(Word), WarnFollowing), + rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ..."), WarnFollowing), + rustc_attr!(TEST, rustc_regions, Normal, template!(Word), WarnFollowing), rustc_attr!( TEST, rustc_error, Normal, - template!(Word, List: "delay_span_bug_from_inside_query") + template!(Word, List: "delay_span_bug_from_inside_query"), WarnFollowingWordOnly + ), + rustc_attr!(TEST, rustc_dump_user_substs, Normal, template!(Word), WarnFollowing), + rustc_attr!(TEST, rustc_evaluate_where_clauses, Normal, template!(Word), WarnFollowing), + rustc_attr!( + TEST, rustc_if_this_changed, Normal, template!(Word, List: "DepNode"), DuplicatesOk + ), + rustc_attr!( + TEST, rustc_then_this_would_need, Normal, template!(List: "DepNode"), DuplicatesOk ), - rustc_attr!(TEST, rustc_dump_user_substs, Normal, template!(Word)), - rustc_attr!(TEST, rustc_evaluate_where_clauses, Normal, template!(Word)), - rustc_attr!(TEST, rustc_if_this_changed, Normal, template!(Word, List: "DepNode")), - rustc_attr!(TEST, rustc_then_this_would_need, Normal, template!(List: "DepNode")), rustc_attr!( TEST, rustc_clean, Normal, template!(List: r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#), + DuplicatesOk, ), rustc_attr!( TEST, rustc_partition_reused, Normal, - template!(List: r#"cfg = "...", module = "...""#), + template!(List: r#"cfg = "...", module = "...""#), DuplicatesOk, ), rustc_attr!( TEST, rustc_partition_codegened, Normal, - template!(List: r#"cfg = "...", module = "...""#), + template!(List: r#"cfg = "...", module = "...""#), DuplicatesOk, ), rustc_attr!( TEST, rustc_expected_cgu_reuse, Normal, - template!(List: r#"cfg = "...", module = "...", kind = "...""#), - ), - rustc_attr!(TEST, rustc_synthetic, Normal, template!(Word)), - rustc_attr!(TEST, rustc_symbol_name, Normal, template!(Word)), - rustc_attr!(TEST, rustc_polymorphize_error, Normal, template!(Word)), - rustc_attr!(TEST, rustc_def_path, Normal, template!(Word)), - rustc_attr!(TEST, rustc_mir, Normal, template!(List: "arg1, arg2, ...")), - rustc_attr!(TEST, rustc_dump_program_clauses, Normal, template!(Word)), - rustc_attr!(TEST, rustc_dump_env_program_clauses, Normal, template!(Word)), - rustc_attr!(TEST, rustc_object_lifetime_default, Normal, template!(Word)), - rustc_attr!(TEST, rustc_dump_vtable, Normal, template!(Word)), - rustc_attr!(TEST, rustc_dummy, Normal, template!(Word /* doesn't matter*/)), + template!(List: r#"cfg = "...", module = "...", kind = "...""#), DuplicatesOk, + ), + rustc_attr!(TEST, rustc_symbol_name, Normal, template!(Word), WarnFollowing), + rustc_attr!(TEST, rustc_polymorphize_error, Normal, template!(Word), WarnFollowing), + rustc_attr!(TEST, rustc_def_path, Normal, template!(Word), WarnFollowing), + rustc_attr!(TEST, rustc_mir, Normal, template!(List: "arg1, arg2, ..."), DuplicatesOk), + rustc_attr!(TEST, rustc_dump_program_clauses, Normal, template!(Word), WarnFollowing), + rustc_attr!(TEST, rustc_dump_env_program_clauses, Normal, template!(Word), WarnFollowing), + rustc_attr!(TEST, rustc_object_lifetime_default, Normal, template!(Word), WarnFollowing), + rustc_attr!(TEST, rustc_dump_vtable, Normal, template!(Word), WarnFollowing), + rustc_attr!(TEST, rustc_dummy, Normal, template!(Word /* doesn't matter*/), DuplicatesOk), gated!( - omit_gdb_pretty_printer_section, Normal, template!(Word), + omit_gdb_pretty_printer_section, Normal, template!(Word), WarnFollowing, "the `#[omit_gdb_pretty_printer_section]` attribute is just used for the Rust test suite", ), ]; pub fn deprecated_attributes() -> Vec<&'static BuiltinAttribute> { - BUILTIN_ATTRIBUTES.iter().filter(|(.., gate)| gate.is_deprecated()).collect() + BUILTIN_ATTRIBUTES.iter().filter(|attr| attr.gate.is_deprecated()).collect() } pub fn is_builtin_attr_name(name: Symbol) -> bool { @@ -611,8 +745,8 @@ pub static BUILTIN_ATTRIBUTE_MAP: SyncLazy> SyncLazy::new(|| { let mut map = FxHashMap::default(); for attr in BUILTIN_ATTRIBUTES.iter() { - if map.insert(attr.0, attr).is_some() { - panic!("duplicate builtin attribute `{}`", attr.0); + if map.insert(attr.name, attr).is_some() { + panic!("duplicate builtin attribute `{}`", attr.name); } } map diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index b25aab21e4..bfc537cfae 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -11,6 +11,7 @@ //! even if it is stabilized or removed, *do not remove it*. Instead, move the //! symbol to the `accepted` or `removed` modules respectively. +#![feature(derive_default_enum)] #![feature(once_cell)] mod accepted; @@ -146,6 +147,7 @@ pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option(...);`). + (removed, const_generics, "1.34.0", Some(44580), None, + Some("removed in favor of `#![feature(adt_const_params)]` and `#![feature(generic_const_exprs)]`")), + /// Allows `[x; N]` where `x` is a constant (RFC 2203). + (removed, const_in_array_repeat_expressions, "1.37.0", Some(49147), None, + Some("removed due to causing promotable bugs")), + /// Allows casting raw pointers to `usize` during const eval. + (removed, const_raw_ptr_to_usize_cast, "1.55.0", Some(51910), None, + Some("at compile-time, pointers do not have an integer value, so these casts cannot be properly supported")), + /// Allows `T: ?const Trait` syntax in bounds. + (removed, const_trait_bound_opt_out, "1.42.0", Some(67794), None, + Some("Removed in favor of `~const` bound in #![feature(const_trait_impl)]")), /// Allows using custom attributes (RFC 572). (removed, custom_attribute, "1.0.0", Some(29642), None, Some("removed in favor of `#![register_tool]` and `#![register_attr]`")), - /// Allows features specific to OIBIT (now called auto traits). - /// Renamed to `auto_traits`. - (removed, optin_builtin_traits, "1.0.0", Some(13231), None, - Some("renamed to `auto_traits`")), - (removed, pushpop_unsafe, "1.2.0", None, None, None), - (removed, needs_allocator, "1.4.0", Some(27389), None, - Some("subsumed by `#![feature(allocator_internals)]`")), - /// Allows identifying crates that contain sanitizer runtimes. - (removed, sanitizer_runtime, "1.17.0", None, None, None), + /// Allows the use of `#[derive(Anything)]` as sugar for `#[derive_Anything]`. + (removed, custom_derive, "1.32.0", Some(29644), None, + Some("subsumed by `#[proc_macro_derive]`")), + /// Allows using `#[doc(keyword = "...")]`. + (removed, doc_keyword, "1.28.0", Some(51315), None, + Some("merged into `#![feature(rustdoc_internals)]`")), + /// Allows using `doc(primitive)` without a future-incompat warning. + (removed, doc_primitive, "1.56.0", Some(88070), None, + Some("merged into `#![feature(rustdoc_internals)]`")), /// 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, - Some("subsumed by `#![feature(proc_macro_hygiene)]`")), - (removed, proc_macro_non_items, "1.27.0", Some(54727), None, - Some("subsumed by `#![feature(proc_macro_hygiene)]`")), - (removed, proc_macro_gen, "1.27.0", Some(54727), None, - Some("subsumed by `#![feature(proc_macro_hygiene)]`")), - (removed, panic_implementation, "1.28.0", Some(44489), None, - Some("subsumed by `#[panic_handler]`")), - /// Allows the use of `#[derive(Anything)]` as sugar for `#[derive_Anything]`. - (removed, custom_derive, "1.32.0", Some(29644), None, - Some("subsumed by `#[proc_macro_derive]`")), - /// Paths of the form: `extern::foo::bar` - (removed, extern_in_paths, "1.33.0", Some(55600), None, - Some("subsumed by `::foo::bar` paths")), - (removed, quote, "1.33.0", Some(29601), None, None), - /// Allows const generic types (e.g. `struct Foo(...);`). - (removed, const_generics, "1.34.0", Some(44580), None, - Some("removed in favor of `#![feature(adt_const_params)]` and `#![feature(generic_const_exprs)]`")), - /// Allows `[x; N]` where `x` is a constant (RFC 2203). - (removed, const_in_array_repeat_expressions, "1.37.0", Some(49147), None, - Some("removed due to causing promotable bugs")), /// Allows using `#[unsafe_destructor_blind_to_params]` (RFC 1238). (removed, dropck_parametricity, "1.38.0", Some(28498), None, None), - (removed, await_macro, "1.38.0", Some(50547), None, - Some("subsumed by `.await` syntax")), /// Allows defining `existential type`s. (removed, existential_type, "1.38.0", Some(63063), None, Some("removed in favor of `#![feature(type_alias_impl_trait)]`")), - /// Allows using the macros: - /// + `__diagnostic_used` - /// + `__register_diagnostic` - /// +`__build_diagnostic_array` - (removed, rustc_diagnostic_macros, "1.38.0", None, None, None), - /// Allows using `#[on_unimplemented(..)]` on traits. - /// (Moved to `rustc_attrs`.) - (removed, on_unimplemented, "1.40.0", None, None, None), - /// Allows overlapping impls of marker traits. - (removed, overlapping_marker_traits, "1.42.0", Some(29864), None, - Some("removed in favor of `#![feature(marker_trait_attr)]`")), - /// Allows `T: ?const Trait` syntax in bounds. - (removed, const_trait_bound_opt_out, "1.42.0", Some(67794), None, - Some("Removed in favor of `~const` bound in #![feature(const_trait_impl)]")), - /// Allows `#[no_debug]`. - (removed, no_debug, "1.43.0", Some(29721), None, Some("removed due to lack of demand")), + /// Paths of the form: `extern::foo::bar` + (removed, extern_in_paths, "1.33.0", Some(55600), None, + Some("subsumed by `::foo::bar` paths")), + /// Allows `#[doc(include = "some-file")]`. + (removed, external_doc, "1.54.0", Some(44732), None, + Some("use #[doc = include_str!(\"filename\")] instead, which handles macro invocations")), + /// Allows `impl Trait` in bindings (`let`, `const`, `static`). + (removed, impl_trait_in_bindings, "1.55.0", Some(63065), None, + Some("the implementation was not maintainable, the feature may get reintroduced once the current refactorings are done")), + (removed, import_shadowing, "1.0.0", None, None, None), /// Lazily evaluate constants. This allows constants to depend on type parameters. (removed, lazy_normalization_consts, "1.46.0", Some(72219), None, Some("superseded by `generic_const_exprs`")), - /// 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 non-trivial generic constants which have to be manually propagated upwards. - (removed, const_evaluatable_checked, "1.48.0", Some(76560), None, Some("renamed to `generic_const_exprs`")), /// 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")), + (removed, macro_reexport, "1.0.0", Some(29638), None, + Some("subsumed by `pub use`")), /// 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")), - /// Allows the definition of `const` functions with some advanced features. - (removed, const_fn, "1.54.0", Some(57563), None, - Some("split into finer-grained feature gates")), - /// Allows using `#[plugin_registrar]` on functions. - (removed, plugin_registrar, "1.54.0", Some(29597), None, - Some("a __rustc_plugin_registrar symbol must now be defined instead")), - - /// Allows `#[doc(include = "some-file")]`. - (removed, external_doc, "1.54.0", Some(44732), None, - Some("use #[doc = include_str!(\"filename\")] instead, which handles macro invocations")), - - /// Allows casting raw pointers to `usize` during const eval. - (removed, const_raw_ptr_to_usize_cast, "1.55.0", Some(51910), None, - Some("at compile-time, pointers do not have an integer value, so these casts cannot be properly supported")), - - /// Allows `impl Trait` in bindings (`let`, `const`, `static`). - (removed, impl_trait_in_bindings, "1.55.0", Some(63065), None, - Some("the implementation was not maintainable, the feature may get reintroduced once the current refactorings are done")), - + (removed, managed_boxes, "1.0.0", None, None, None), /// Allows the use of type alias impl trait in function return positions (removed, min_type_alias_impl_trait, "1.56.0", Some(63063), None, Some("removed in favor of full type_alias_impl_trait")), - + (removed, needs_allocator, "1.4.0", Some(27389), None, + Some("subsumed by `#![feature(allocator_internals)]`")), + /// Allows use of unary negate on unsigned integers, e.g., -e for e: u8 + (removed, negate_unsigned, "1.0.0", Some(29645), None, None), + /// Allows `#[no_debug]`. + (removed, no_debug, "1.43.0", Some(29721), None, Some("removed due to lack of demand")), + /// Allows using `#[on_unimplemented(..)]` on traits. + /// (Moved to `rustc_attrs`.) + (removed, on_unimplemented, "1.40.0", None, None, None), + /// A way to temporarily opt out of opt in copy. This will *never* be accepted. + (removed, opt_out_copy, "1.0.0", None, None, None), + /// Allows features specific to OIBIT (now called auto traits). + /// Renamed to `auto_traits`. + (removed, optin_builtin_traits, "1.0.0", Some(13231), None, + Some("renamed to `auto_traits`")), + /// Allows overlapping impls of marker traits. + (removed, overlapping_marker_traits, "1.42.0", Some(29864), None, + Some("removed in favor of `#![feature(marker_trait_attr)]`")), + (removed, panic_implementation, "1.28.0", Some(44489), None, + Some("subsumed by `#[panic_handler]`")), + /// Allows using `#[plugin_registrar]` on functions. + (removed, plugin_registrar, "1.54.0", Some(29597), None, + Some("a __rustc_plugin_registrar symbol must now be defined instead")), + (removed, proc_macro_expr, "1.27.0", Some(54727), None, + Some("subsumed by `#![feature(proc_macro_hygiene)]`")), + (removed, proc_macro_gen, "1.27.0", Some(54727), None, + Some("subsumed by `#![feature(proc_macro_hygiene)]`")), + (removed, proc_macro_mod, "1.27.0", Some(54727), None, + Some("subsumed by `#![feature(proc_macro_hygiene)]`")), + (removed, proc_macro_non_items, "1.27.0", Some(54727), None, + Some("subsumed by `#![feature(proc_macro_hygiene)]`")), + (removed, pub_macro_rules, "1.53.0", Some(78855), None, + Some("removed due to being incomplete, in particular it does not work across crates")), + (removed, pushpop_unsafe, "1.2.0", None, None, None), + (removed, quad_precision_float, "1.0.0", None, None, None), + (removed, quote, "1.33.0", Some(29601), None, None), + (removed, reflect, "1.0.0", Some(27749), None, None), + /// Allows using the macros: + /// + `__diagnostic_used` + /// + `__register_diagnostic` + /// +`__build_diagnostic_array` + (removed, rustc_diagnostic_macros, "1.38.0", None, None, None), + /// Allows identifying crates that contain sanitizer runtimes. + (removed, sanitizer_runtime, "1.17.0", None, None, None), + (removed, simd, "1.0.0", Some(27731), None, + Some("removed in favor of `#[repr(simd)]`")), + (removed, struct_inherit, "1.0.0", None, None, None), + (removed, test_removed_feature, "1.0.0", None, None, None), + /// Allows using items which are missing stability attributes + (removed, unmarked_api, "1.0.0", None, None, None), + (removed, unsafe_no_drop_flag, "1.0.0", None, None, None), /// Allows `#[unwind(..)]`. /// /// Permits specifying whether a function should permit unwinding or abort on unwind. (removed, unwind_attributes, "1.56.0", Some(58760), None, Some("use the C-unwind ABI instead")), + (removed, visible_private_types, "1.0.0", None, None, None), + // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! + // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way. + // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! // ------------------------------------------------------------------------- // feature-group-end: removed features diff --git a/compiler/rustc_graphviz/src/lib.rs b/compiler/rustc_graphviz/src/lib.rs index e69289b71f..27390fd2e4 100644 --- a/compiler/rustc_graphviz/src/lib.rs +++ b/compiler/rustc_graphviz/src/lib.rs @@ -512,7 +512,7 @@ impl<'a> LabelText<'a> { pub fn to_dot_string(&self) -> String { match *self { LabelStr(ref s) => format!("\"{}\"", s.escape_default()), - EscStr(ref s) => format!("\"{}\"", LabelText::escape_str(s)), + EscStr(ref s) => format!("\"{}\"", LabelText::escape_str(&s)), HtmlStr(ref s) => format!("<{}>", s), } } diff --git a/compiler/rustc_hir/src/arena.rs b/compiler/rustc_hir/src/arena.rs index f07e52e04d..f19ca497d8 100644 --- a/compiler/rustc_hir/src/arena.rs +++ b/compiler/rustc_hir/src/arena.rs @@ -1,55 +1,52 @@ -/// This declares a list of types which can be allocated by `Arena`. -/// -/// The `few` modifier will cause allocation to use the shared arena and recording the destructor. -/// This is faster and more memory efficient if there's only a few allocations of the type. -/// Leaving `few` out will cause the type to get its own dedicated `TypedArena` which is -/// faster and more memory efficient if there is lots of allocations. +/// This higher-order macro declares a list of types which can be allocated by `Arena`. /// /// Specifying the `decode` modifier will add decode impls for `&T` and `&[T]`, /// where `T` is the type listed. These impls will appear in the implement_ty_decoder! macro. #[macro_export] macro_rules! arena_types { - ($macro:path, $tcx:lifetime) => ( + ($macro:path) => ( $macro!([ // HIR types - [few] hir_krate: rustc_hir::Crate<$tcx>, - [] arm: rustc_hir::Arm<$tcx>, - [] asm_operand: (rustc_hir::InlineAsmOperand<$tcx>, Span), + [] hir_krate: rustc_hir::Crate<'tcx>, + [] arm: rustc_hir::Arm<'tcx>, + [] asm_operand: (rustc_hir::InlineAsmOperand<'tcx>, Span), [] asm_template: rustc_ast::InlineAsmTemplatePiece, [] attribute: rustc_ast::Attribute, - [] block: rustc_hir::Block<$tcx>, - [] bare_fn_ty: rustc_hir::BareFnTy<$tcx>, - [] generic_arg: rustc_hir::GenericArg<$tcx>, - [] generic_args: rustc_hir::GenericArgs<$tcx>, - [] generic_bound: rustc_hir::GenericBound<$tcx>, - [] generic_param: rustc_hir::GenericParam<$tcx>, - [] expr: rustc_hir::Expr<$tcx>, - [] expr_field: rustc_hir::ExprField<$tcx>, - [] pat_field: rustc_hir::PatField<$tcx>, - [] fn_decl: rustc_hir::FnDecl<$tcx>, - [] foreign_item: rustc_hir::ForeignItem<$tcx>, - [few] foreign_item_ref: rustc_hir::ForeignItemRef, - [] impl_item: rustc_hir::ImplItem<$tcx>, + [] block: rustc_hir::Block<'tcx>, + [] bare_fn_ty: rustc_hir::BareFnTy<'tcx>, + [] body: rustc_hir::Body<'tcx>, + [] generic_arg: rustc_hir::GenericArg<'tcx>, + [] generic_args: rustc_hir::GenericArgs<'tcx>, + [] generic_bound: rustc_hir::GenericBound<'tcx>, + [] generic_param: rustc_hir::GenericParam<'tcx>, + [] expr: rustc_hir::Expr<'tcx>, + [] expr_field: rustc_hir::ExprField<'tcx>, + [] pat_field: rustc_hir::PatField<'tcx>, + [] fn_decl: rustc_hir::FnDecl<'tcx>, + [] foreign_item: rustc_hir::ForeignItem<'tcx>, + [] foreign_item_ref: rustc_hir::ForeignItemRef, + [] impl_item: rustc_hir::ImplItem<'tcx>, [] impl_item_ref: rustc_hir::ImplItemRef, - [] item: rustc_hir::Item<$tcx>, - [few] inline_asm: rustc_hir::InlineAsm<$tcx>, - [few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>, - [] local: rustc_hir::Local<$tcx>, - [few] mod_: rustc_hir::Mod<$tcx>, - [] param: rustc_hir::Param<$tcx>, - [] pat: rustc_hir::Pat<$tcx>, - [] path: rustc_hir::Path<$tcx>, - [] path_segment: rustc_hir::PathSegment<$tcx>, - [] poly_trait_ref: rustc_hir::PolyTraitRef<$tcx>, - [] qpath: rustc_hir::QPath<$tcx>, - [] stmt: rustc_hir::Stmt<$tcx>, - [] field_def: rustc_hir::FieldDef<$tcx>, - [] trait_item: rustc_hir::TraitItem<$tcx>, + [] item: rustc_hir::Item<'tcx>, + [] inline_asm: rustc_hir::InlineAsm<'tcx>, + [] llvm_inline_asm: rustc_hir::LlvmInlineAsm<'tcx>, + [] local: rustc_hir::Local<'tcx>, + [] mod_: rustc_hir::Mod<'tcx>, + [] owner_info: rustc_hir::OwnerInfo<'tcx>, + [] param: rustc_hir::Param<'tcx>, + [] pat: rustc_hir::Pat<'tcx>, + [] path: rustc_hir::Path<'tcx>, + [] path_segment: rustc_hir::PathSegment<'tcx>, + [] poly_trait_ref: rustc_hir::PolyTraitRef<'tcx>, + [] qpath: rustc_hir::QPath<'tcx>, + [] stmt: rustc_hir::Stmt<'tcx>, + [] field_def: rustc_hir::FieldDef<'tcx>, + [] trait_item: rustc_hir::TraitItem<'tcx>, [] trait_item_ref: rustc_hir::TraitItemRef, - [] ty: rustc_hir::Ty<$tcx>, - [] type_binding: rustc_hir::TypeBinding<$tcx>, - [] variant: rustc_hir::Variant<$tcx>, - [] where_predicate: rustc_hir::WherePredicate<$tcx>, - ], $tcx); + [] ty: rustc_hir::Ty<'tcx>, + [] type_binding: rustc_hir::TypeBinding<'tcx>, + [] variant: rustc_hir::Variant<'tcx>, + [] where_predicate: rustc_hir::WherePredicate<'tcx>, + ]); ) } diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index cb668eb35e..60761a05de 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -104,8 +104,10 @@ pub enum DefKind { Use, /// An `extern` block. ForeignMod, - /// Anonymous constant, e.g. the `1 + 2` in `[u8; 1 + 2]`, or `const { 1 + 2}` + /// Anonymous constant, e.g. the `1 + 2` in `[u8; 1 + 2]` AnonConst, + /// An inline constant, e.g. `const { 1 + 2 }` + InlineConst, /// Opaque type, aka `impl Trait`. OpaqueTy, Field, @@ -155,6 +157,7 @@ impl DefKind { DefKind::Use => "import", DefKind::ForeignMod => "foreign module", DefKind::AnonConst => "constant expression", + DefKind::InlineConst => "inline constant", DefKind::Field => "field", DefKind::Impl => "implementation", DefKind::Closure => "closure", @@ -174,6 +177,7 @@ impl DefKind { | DefKind::OpaqueTy | DefKind::Impl | DefKind::Use + | DefKind::InlineConst | DefKind::ExternCrate => "an", DefKind::Macro(macro_kind) => macro_kind.article(), _ => "a", @@ -207,6 +211,7 @@ impl DefKind { // Not namespaced. DefKind::AnonConst + | DefKind::InlineConst | DefKind::Field | DefKind::LifetimeParam | DefKind::ExternCrate diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 11d0178e93..c67d3df3de 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1,6 +1,7 @@ use crate::def::{CtorKind, DefKind, Res}; -use crate::def_id::{DefId, CRATE_DEF_ID}; +use crate::def_id::DefId; crate use crate::hir_id::{HirId, ItemLocalId}; +use crate::intravisit::FnKind; use crate::LangItem; use rustc_ast::util::parser::ExprPrecedence; @@ -9,7 +10,9 @@ use rustc_ast::{Attribute, FloatTy, IntTy, Label, LitKind, StrStyle, TraitObject pub use rustc_ast::{BorrowKind, ImplPolarity, IsAuto}; pub use rustc_ast::{CaptureBy, Movability, Mutability}; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; +use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::sorted_map::SortedMap; use rustc_index::vec::IndexVec; use rustc_macros::HashStable_Generic; use rustc_span::source_map::Spanned; @@ -20,7 +23,6 @@ use rustc_target::asm::InlineAsmRegOrRegClass; use rustc_target::spec::abi::Abi; use smallvec::SmallVec; -use std::collections::BTreeMap; use std::fmt; #[derive(Copy, Clone, Encodable, HashStable_Generic)] @@ -121,7 +123,7 @@ impl LifetimeName { match *self { LifetimeName::ImplicitObjectLifetimeDefault | LifetimeName::Implicit - | LifetimeName::Error => Ident::invalid(), + | LifetimeName::Error => Ident::empty(), LifetimeName::Underscore => Ident::with_dummy_span(kw::UnderscoreLifetime), LifetimeName::Static => Ident::with_dummy_span(kw::StaticLifetime), LifetimeName::Param(param_name) => param_name.ident(), @@ -233,7 +235,7 @@ impl<'hir> PathSegment<'hir> { } pub fn invalid() -> Self { - Self::from_ident(Ident::invalid()) + Self::from_ident(Ident::empty()) } pub fn args(&self) -> &GenericArgs<'hir> { @@ -310,7 +312,7 @@ impl GenericArg<'_> { } pub fn is_synthetic(&self) -> bool { - matches!(self, GenericArg::Lifetime(lifetime) if lifetime.name.ident() == Ident::invalid()) + matches!(self, GenericArg::Lifetime(lifetime) if lifetime.name.ident() == Ident::empty()) } pub fn descr(&self) -> &'static str { @@ -502,7 +504,7 @@ pub enum GenericParamKind<'hir> { }, Type { default: Option<&'hir Ty<'hir>>, - synthetic: Option, + synthetic: bool, }, Const { ty: &'hir Ty<'hir>, @@ -575,16 +577,6 @@ impl Generics<'hir> { } } -/// Synthetic type parameters are converted to another form during lowering; this allows -/// us to track the original form they had, and is useful for error messages. -#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] -#[derive(HashStable_Generic)] -pub enum SyntheticTyParamKind { - ImplTrait, - // Created by the `#[rustc_synthetic]` attribute. - FromAttr, -} - /// A where-clause in a definition. #[derive(Debug, HashStable_Generic)] pub struct WhereClause<'hir> { @@ -645,6 +637,22 @@ pub struct WhereBoundPredicate<'hir> { pub bounds: GenericBounds<'hir>, } +impl WhereBoundPredicate<'hir> { + /// Returns `true` if `param_def_id` matches the `bounded_ty` of this predicate. + pub fn is_param_bound(&self, param_def_id: DefId) -> bool { + let path = match self.bounded_ty.kind { + TyKind::Path(QPath::Resolved(None, path)) => path, + _ => return false, + }; + match path.res { + Res::Def(DefKind::TyParam, def_id) | Res::SelfTy(Some(def_id), None) => { + def_id == param_def_id + } + _ => false, + } + } +} + /// A lifetime predicate (e.g., `'a: 'b + 'c`). #[derive(Debug, HashStable_Generic)] pub struct WhereRegionPredicate<'hir> { @@ -662,49 +670,84 @@ pub struct WhereEqPredicate<'hir> { pub rhs_ty: &'hir Ty<'hir>, } -/// The top-level data structure that stores the entire contents of -/// the crate currently being compiled. +/// HIR node coupled with its parent's id in the same HIR owner. /// -/// For more details, see the [rustc dev guide]. -/// -/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html -#[derive(Debug)] -pub struct Crate<'hir> { - pub owners: IndexVec>>, - pub bodies: BTreeMap>, - - /// Map indicating what traits are in scope for places where this - /// is relevant; generated by resolve. - pub trait_map: FxHashMap>>, - - /// Collected attributes from HIR nodes. - pub attrs: BTreeMap, +/// The parent is trash when the node is a HIR owner. +#[derive(Clone, Debug)] +pub struct ParentedNode<'tcx> { + pub parent: ItemLocalId, + pub node: Node<'tcx>, } -impl Crate<'hir> { - pub fn module(&self) -> &'hir Mod<'hir> { - if let Some(OwnerNode::Crate(m)) = self.owners[CRATE_DEF_ID] { m } else { panic!() } - } +/// Attributes owned by a HIR owner. +#[derive(Debug)] +pub struct AttributeMap<'tcx> { + pub map: SortedMap, + pub hash: Fingerprint, +} - pub fn item(&self, id: ItemId) -> &'hir Item<'hir> { - self.owners[id.def_id].as_ref().unwrap().expect_item() - } +impl<'tcx> AttributeMap<'tcx> { + pub const EMPTY: &'static AttributeMap<'static> = + &AttributeMap { map: SortedMap::new(), hash: Fingerprint::ZERO }; - pub fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> { - self.owners[id.def_id].as_ref().unwrap().expect_trait_item() + #[inline] + pub fn get(&self, id: ItemLocalId) -> &'tcx [Attribute] { + self.map.get(&id).copied().unwrap_or(&[]) } +} - pub fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> { - self.owners[id.def_id].as_ref().unwrap().expect_impl_item() - } +/// Map of all HIR nodes inside the current owner. +/// These nodes are mapped by `ItemLocalId` alongside the index of their parent node. +/// The HIR tree, including bodies, is pre-hashed. +#[derive(Debug)] +pub struct OwnerNodes<'tcx> { + /// Pre-computed hash of the full HIR. + pub hash_including_bodies: Fingerprint, + /// Pre-computed hash of the item signature, sithout recursing into the body. + pub hash_without_bodies: Fingerprint, + /// Full HIR for the current owner. + // The zeroth node's parent should never be accessed: the owner's parent is computed by the + // hir_owner_parent query. It is set to `ItemLocalId::INVALID` to force an ICE if accidentally + // used. + pub nodes: IndexVec>>, + /// Content of local bodies. + pub bodies: SortedMap>, +} + +/// Full information resulting from lowering an AST node. +#[derive(Debug, HashStable_Generic)] +pub struct OwnerInfo<'hir> { + /// Contents of the HIR. + pub nodes: OwnerNodes<'hir>, + /// Map from each nested owner to its parent's local id. + pub parenting: FxHashMap, + /// Collected attributes of the HIR nodes. + pub attrs: AttributeMap<'hir>, + /// Map indicating what traits are in scope for places where this + /// is relevant; generated by resolve. + pub trait_map: FxHashMap>, +} - pub fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir> { - self.owners[id.def_id].as_ref().unwrap().expect_foreign_item() +impl<'tcx> OwnerInfo<'tcx> { + #[inline] + pub fn node(&self) -> OwnerNode<'tcx> { + use rustc_index::vec::Idx; + let node = self.nodes.nodes[ItemLocalId::new(0)].as_ref().unwrap().node; + let node = node.as_owner().unwrap(); // Indexing must ensure it is an OwnerNode. + node } +} - pub fn body(&self, id: BodyId) -> &Body<'hir> { - &self.bodies[&id] - } +/// The top-level data structure that stores the entire contents of +/// the crate currently being compiled. +/// +/// For more details, see the [rustc dev guide]. +/// +/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html +#[derive(Debug)] +pub struct Crate<'hir> { + pub owners: IndexVec>>, + pub hir_hash: Fingerprint, } /// A block of statements `{ .. }`, which may have a label (in this case the @@ -1778,8 +1821,6 @@ impl<'hir> QPath<'hir> { pub enum LocalSource { /// A `match _ { .. }`. Normal, - /// A desugared `for _ in _ { .. }` loop. - ForLoopDesugar, /// When lowering async functions, we create locals within the `async move` so that /// all parameters are dropped after the future is polled. /// @@ -3222,6 +3263,32 @@ impl<'hir> Node<'hir> { _ => None, } } + + pub fn fn_kind(self) -> Option> { + match self { + Node::Item(i) => match i.kind { + ItemKind::Fn(ref sig, ref generics, _) => { + Some(FnKind::ItemFn(i.ident, generics, sig.header, &i.vis)) + } + _ => None, + }, + Node::TraitItem(ti) => match ti.kind { + TraitItemKind::Fn(ref sig, TraitFn::Provided(_)) => { + Some(FnKind::Method(ti.ident, sig, None)) + } + _ => None, + }, + Node::ImplItem(ii) => match ii.kind { + ImplItemKind::Fn(ref sig, _) => Some(FnKind::Method(ii.ident, sig, Some(&ii.vis))), + _ => None, + }, + Node::Expr(e) => match e.kind { + ExprKind::Closure(..) => Some(FnKind::Closure), + _ => None, + }, + _ => None, + } + } } // Some nodes are used a lot. Make sure they don't unintentionally get bigger. diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs index 0b25ebc27b..39552eb9f3 100644 --- a/compiler/rustc_hir/src/hir_id.rs +++ b/compiler/rustc_hir/src/hir_id.rs @@ -1,5 +1,4 @@ use crate::def_id::{LocalDefId, CRATE_DEF_INDEX}; -use rustc_index::vec::IndexVec; use std::fmt; /// Uniquely identifies a node in the HIR of the current crate. It is @@ -56,76 +55,13 @@ rustc_index::newtype_index! { pub struct ItemLocalId { .. } } rustc_data_structures::impl_stable_hash_via_hash!(ItemLocalId); +impl ItemLocalId { + /// Signal local id which should never be used. + pub const INVALID: ItemLocalId = ItemLocalId::MAX; +} /// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_INDEX`. pub const CRATE_HIR_ID: HirId = HirId { owner: LocalDefId { local_def_index: CRATE_DEF_INDEX }, 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>, -} - -impl HirIdVec { - pub fn push_owner(&mut self, id: LocalDefId) { - self.map.ensure_contains_elem(id, IndexVec::new); - } - - pub fn push(&mut self, id: HirId, value: T) { - if id.local_id == ItemLocalId::from_u32(0) { - self.push_owner(id.owner); - } - let submap = &mut self.map[id.owner]; - let _ret_id = submap.push(value); - debug_assert_eq!(_ret_id, id.local_id); - } - - pub fn push_sparse(&mut self, id: HirId, value: T) - where - T: Default, - { - self.map.ensure_contains_elem(id.owner, IndexVec::new); - let submap = &mut self.map[id.owner]; - let i = id.local_id.index(); - let len = submap.len(); - if i >= len { - submap.extend(std::iter::repeat_with(T::default).take(i - len + 1)); - } - submap[id.local_id] = value; - } - - pub fn get(&self, id: HirId) -> Option<&T> { - self.map.get(id.owner)?.get(id.local_id) - } - - pub fn get_owner(&self, id: LocalDefId) -> &IndexVec { - &self.map[id] - } - - pub fn iter(&self) -> impl Iterator { - self.map.iter().flat_map(|la| la.iter()) - } - - pub fn iter_enumerated(&self) -> impl Iterator { - self.map.iter_enumerated().flat_map(|(owner, la)| { - la.iter_enumerated().map(move |(local_id, attr)| (HirId { owner, local_id }, attr)) - }) - } -} - -impl std::ops::Index for HirIdVec { - type Output = T; - - fn index(&self, id: HirId) -> &T { - &self.map[id.owner][id.local_id] - } -} - -impl std::ops::IndexMut for HirIdVec { - fn index_mut(&mut self, id: HirId) -> &mut T { - &mut self.map[id.owner][id.local_id] - } -} diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 1ac2625dd4..cff543760f 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -117,6 +117,14 @@ impl<'a> FnKind<'a> { FnKind::Closure => None, } } + + pub fn constness(self) -> Constness { + self.header().map_or(Constness::NotConst, |header| header.constness) + } + + pub fn asyncness(self) -> IsAsync { + self.header().map_or(IsAsync::NotAsync, |header| header.asyncness) + } } /// An abstract representation of the HIR `rustc_middle::hir::map::Map`. @@ -130,6 +138,28 @@ pub trait Map<'hir> { fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir>; } +// Used when no map is actually available, forcing manual implementation of nested visitors. +impl Map<'hir> for ! { + fn find(&self, _: HirId) -> Option> { + unreachable!() + } + fn body(&self, _: BodyId) -> &'hir Body<'hir> { + unreachable!() + } + fn item(&self, _: ItemId) -> &'hir Item<'hir> { + unreachable!() + } + fn trait_item(&self, _: TraitItemId) -> &'hir TraitItem<'hir> { + unreachable!() + } + fn impl_item(&self, _: ImplItemId) -> &'hir ImplItem<'hir> { + unreachable!() + } + fn foreign_item(&self, _: ForeignItemId) -> &'hir ForeignItem<'hir> { + unreachable!() + } +} + /// An erased version of `Map<'hir>`, using dynamic dispatch. /// NOTE: This type is effectively only usable with `NestedVisitorMap::None`. pub struct ErasedMap<'hir>(&'hir dyn Map<'hir>); diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index f35353dbfb..05659e976d 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -268,6 +268,7 @@ language_item_table! { Future, sym::future_trait, future_trait, Target::Trait, GenericRequirement::Exact(0); GeneratorState, sym::generator_state, gen_state, Target::Enum, GenericRequirement::None; Generator, sym::generator, gen_trait, Target::Trait, GenericRequirement::Minimum(1); + GeneratorReturn, sym::generator_return, generator_return, Target::AssocTy, GenericRequirement::None; Unpin, sym::unpin, unpin_trait, Target::Trait, GenericRequirement::None; Pin, sym::pin, pin_type, Target::Struct, GenericRequirement::None; @@ -281,18 +282,17 @@ language_item_table! { // in the sense that a crate is not required to have it defined to use it, but a final product // is required to define it somewhere. Additionally, there are restrictions on crates that use // a weak lang item, but do not have it defined. - Panic, sym::panic, panic_fn, Target::Fn, GenericRequirement::None; + Panic, sym::panic, panic_fn, Target::Fn, GenericRequirement::Exact(0); PanicFmt, sym::panic_fmt, panic_fmt, Target::Fn, GenericRequirement::None; PanicDisplay, sym::panic_display, panic_display, Target::Fn, GenericRequirement::None; PanicStr, sym::panic_str, panic_str, Target::Fn, GenericRequirement::None; ConstPanicFmt, sym::const_panic_fmt, const_panic_fmt, Target::Fn, GenericRequirement::None; - PanicBoundsCheck, sym::panic_bounds_check, panic_bounds_check_fn, Target::Fn, GenericRequirement::None; + PanicBoundsCheck, sym::panic_bounds_check, panic_bounds_check_fn, Target::Fn, GenericRequirement::Exact(0); PanicInfo, sym::panic_info, panic_info, Target::Struct, GenericRequirement::None; PanicLocation, sym::panic_location, panic_location, Target::Struct, GenericRequirement::None; PanicImpl, sym::panic_impl, panic_impl, Target::Fn, GenericRequirement::None; /// libstd panic entry point. Necessary for const eval to be able to catch it BeginPanic, sym::begin_panic, begin_panic_fn, Target::Fn, GenericRequirement::None; - BeginPanicFmt, sym::begin_panic_fmt, begin_panic_fmt, Target::Fn, GenericRequirement::None; ExchangeMalloc, sym::exchange_malloc, exchange_malloc_fn, Target::Fn, GenericRequirement::None; BoxFree, sym::box_free, box_free_fn, Target::Fn, GenericRequirement::Minimum(1); diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index f5ea044e24..93224d388c 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -2,10 +2,12 @@ //! //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html +#![feature(const_btree_new)] #![feature(crate_visibility_modifier)] #![feature(in_band_lifetimes)] #![feature(once_cell)] #![feature(min_specialization)] +#![feature(never_type)] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_hir/src/pat_util.rs b/compiler/rustc_hir/src/pat_util.rs index b1f78a83e7..b30076100b 100644 --- a/compiler/rustc_hir/src/pat_util.rs +++ b/compiler/rustc_hir/src/pat_util.rs @@ -2,6 +2,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::hygiene::DesugaringKind; use rustc_span::symbol::Ident; use rustc_span::Span; @@ -143,4 +144,14 @@ impl hir::Pat<'_> { }); result } + + /// If the pattern is `Some()` from a desugared for loop, returns the inner pattern + pub fn for_loop_some(&self) -> Option<&Self> { + if self.span.desugaring_kind() == Some(DesugaringKind::ForLoop) { + if let hir::PatKind::Struct(_, [pat_field], _) = self.kind { + return Some(pat_field.pat); + } + } + None + } } diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs index 9d5ef279dd..6e7b765a0c 100644 --- a/compiler/rustc_hir/src/stable_hash_impls.rs +++ b/compiler/rustc_hir/src/stable_hash_impls.rs @@ -1,8 +1,8 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; use crate::hir::{ - BodyId, Expr, ForeignItem, ForeignItemId, ImplItem, ImplItemId, Item, ItemId, Mod, TraitItem, - TraitItemId, Ty, VisibilityKind, + AttributeMap, BodyId, Crate, Expr, ForeignItem, ForeignItemId, ImplItem, ImplItemId, Item, + ItemId, Mod, OwnerNodes, TraitCandidate, TraitItem, TraitItemId, Ty, VisibilityKind, }; use crate::hir_id::{HirId, ItemLocalId}; use rustc_span::def_id::DefPathHash; @@ -21,6 +21,7 @@ pub trait HashStableContext: fn hash_hir_ty(&mut self, _: &Ty<'_>, hasher: &mut StableHasher); fn hash_hir_visibility_kind(&mut self, _: &VisibilityKind<'_>, hasher: &mut StableHasher); fn hash_hir_item_like(&mut self, f: F); + fn hash_hir_trait_candidate(&mut self, _: &TraitCandidate, hasher: &mut StableHasher); } impl ToStableHashKey for HirId { @@ -209,3 +210,35 @@ impl HashStable for Item<'_> { }); } } + +impl HashStable for OwnerNodes<'tcx> { + fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { + // We ignore the `nodes` and `bodies` fields since these refer to information included in + // `hash` which is hashed in the collector and used for the crate hash. + let OwnerNodes { hash_including_bodies, hash_without_bodies: _, nodes: _, bodies: _ } = + *self; + hash_including_bodies.hash_stable(hcx, hasher); + } +} + +impl HashStable for AttributeMap<'tcx> { + fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { + // We ignore the `map` since it refers to information included in `hash` which is hashed in + // the collector and used for the crate hash. + let AttributeMap { hash, map: _ } = *self; + hash.hash_stable(hcx, hasher); + } +} + +impl HashStable for Crate<'_> { + fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { + let Crate { owners: _, hir_hash } = self; + hir_hash.hash_stable(hcx, hasher) + } +} + +impl HashStable for TraitCandidate { + fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { + hcx.hash_hir_trait_candidate(self, hasher) + } +} diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 9196344cb3..9c2927111a 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -15,7 +15,6 @@ use rustc_target::spec::abi::Abi; use std::borrow::Cow; use std::cell::Cell; -use std::collections::BTreeMap; use std::vec; pub fn id_to_string(map: &dyn rustc_hir::intravisit::Map<'_>, hir_id: hir::HirId) -> String { @@ -69,7 +68,7 @@ impl PpAnn for &dyn rustc_hir::intravisit::Map<'_> { pub struct State<'a> { pub s: pp::Printer, comments: Option>, - attrs: &'a BTreeMap, + attrs: &'a dyn Fn(hir::HirId) -> &'a [ast::Attribute], ann: &'a (dyn PpAnn + 'a), } @@ -146,17 +145,18 @@ pub const INDENT_UNIT: usize = 4; /// it can scan the input text for comments to copy forward. pub fn print_crate<'a>( sm: &'a SourceMap, - krate: &hir::Crate<'_>, + krate: &hir::Mod<'_>, filename: FileName, input: String, + attrs: &'a dyn Fn(hir::HirId) -> &'a [ast::Attribute], ann: &'a dyn PpAnn, ) -> String { - let mut s = State::new_from_input(sm, filename, input, &krate.attrs, ann); + let mut s = State::new_from_input(sm, filename, input, attrs, ann); // 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.module(), s.attrs(hir::CRATE_HIR_ID)); + s.print_mod(krate, (*attrs)(hir::CRATE_HIR_ID)); s.print_remaining_comments(); s.s.eof() } @@ -166,7 +166,7 @@ impl<'a> State<'a> { sm: &'a SourceMap, filename: FileName, input: String, - attrs: &'a BTreeMap, + attrs: &'a dyn Fn(hir::HirId) -> &'a [ast::Attribute], ann: &'a dyn PpAnn, ) -> State<'a> { State { @@ -178,7 +178,7 @@ impl<'a> State<'a> { } fn attrs(&self, id: hir::HirId) -> &'a [ast::Attribute] { - self.attrs.get(&id).map_or(&[], |la| *la) + (self.attrs)(id) } } @@ -186,8 +186,7 @@ pub fn to_string(ann: &dyn PpAnn, f: F) -> String where F: FnOnce(&mut State<'_>), { - let mut printer = - State { s: pp::mk_printer(), comments: None, attrs: &BTreeMap::default(), ann }; + let mut printer = State { s: pp::mk_printer(), comments: None, attrs: &|_| &[], ann }; f(&mut printer); printer.s.eof() } @@ -1168,7 +1167,7 @@ impl<'a> State<'a> { self.print_expr_cond_paren(expr, Self::cond_needs_par(expr) || npals()) } - // Does `expr` need parenthesis when printed in a condition position? + // Does `expr` need parentheses when printed in a condition position? // // These cases need parens due to the parse error observed in #26461: `if return {}` // parses as the erroneous construct `if (return {})`, not `if (return) {}`. diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index d42e2f7a99..571337a8dc 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -126,30 +126,36 @@ impl IfThisChanged<'tcx> { if attr.has_name(sym::rustc_if_this_changed) { let dep_node_interned = self.argument(attr); let dep_node = match dep_node_interned { - None => DepNode::from_def_path_hash(def_path_hash, DepKind::hir_owner), - Some(n) => match DepNode::from_label_string(&n.as_str(), def_path_hash) { - Ok(n) => n, - Err(()) => { - self.tcx.sess.span_fatal( - attr.span, - &format!("unrecognized DepNode variant {:?}", n), - ); + None => { + DepNode::from_def_path_hash(self.tcx, def_path_hash, DepKind::hir_owner) + } + Some(n) => { + match DepNode::from_label_string(self.tcx, &n.as_str(), def_path_hash) { + Ok(n) => n, + Err(()) => { + self.tcx.sess.span_fatal( + attr.span, + &format!("unrecognized DepNode variant {:?}", n), + ); + } } - }, + } }; self.if_this_changed.push((attr.span, def_id.to_def_id(), dep_node)); } else if attr.has_name(sym::rustc_then_this_would_need) { let dep_node_interned = self.argument(attr); let dep_node = match dep_node_interned { - Some(n) => match DepNode::from_label_string(&n.as_str(), def_path_hash) { - Ok(n) => n, - Err(()) => { - self.tcx.sess.span_fatal( - attr.span, - &format!("unrecognized DepNode variant {:?}", n), - ); + Some(n) => { + match DepNode::from_label_string(self.tcx, &n.as_str(), def_path_hash) { + Ok(n) => n, + Err(()) => { + self.tcx.sess.span_fatal( + attr.span, + &format!("unrecognized DepNode variant {:?}", n), + ); + } } - }, + } None => { self.tcx.sess.span_fatal(attr.span, "missing DepNode variant"); } diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs index f089cbcfca..dd3f8c937f 100644 --- a/compiler/rustc_incremental/src/lib.rs +++ b/compiler/rustc_incremental/src/lib.rs @@ -2,6 +2,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(in_band_lifetimes)] +#![feature(let_else)] #![feature(nll)] #![recursion_limit = "256"] diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index 55286384de..b2eaf61b7d 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -15,7 +15,7 @@ use rustc_ast::{self as ast, Attribute, NestedMetaItem}; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::Node as HirNode; @@ -302,18 +302,6 @@ impl DirtyCleanVisitor<'tcx> { out } - fn dep_nodes<'l>( - &self, - labels: &'l Labels, - def_id: DefId, - ) -> impl Iterator + 'l { - let def_path_hash = self.tcx.def_path_hash(def_id); - labels.iter().map(move |label| match DepNode::from_label_string(label, def_path_hash) { - Ok(dep_node) => dep_node, - Err(()) => unreachable!("label: {}", label), - }) - } - fn dep_node_str(&self, dep_node: &DepNode) -> String { if let Some(def_id) = dep_node.extract_def_id(self.tcx) { format!("{:?}({})", dep_node.kind, self.tcx.def_path_str(def_id)) @@ -345,16 +333,19 @@ impl DirtyCleanVisitor<'tcx> { } fn check_item(&mut self, item_id: LocalDefId, item_span: Span) { + let def_path_hash = self.tcx.def_path_hash(item_id.to_def_id()); for attr in self.tcx.get_attrs(item_id.to_def_id()).iter() { let assertion = match self.assertion_maybe(item_id, attr) { Some(a) => a, None => continue, }; self.checked_attrs.insert(attr.id); - for dep_node in self.dep_nodes(&assertion.clean, item_id.to_def_id()) { + for label in assertion.clean { + let dep_node = DepNode::from_label_string(self.tcx, &label, def_path_hash).unwrap(); self.assert_clean(item_span, dep_node); } - for dep_node in self.dep_nodes(&assertion.dirty, item_id.to_def_id()) { + for label in assertion.dirty { + let dep_node = DepNode::from_label_string(self.tcx, &label, def_path_hash).unwrap(); self.assert_dirty(item_span, dep_node); } } diff --git a/compiler/rustc_incremental/src/persist/file_format.rs b/compiler/rustc_incremental/src/persist/file_format.rs index 572a4fc697..392c5bdc15 100644 --- a/compiler/rustc_incremental/src/persist/file_format.rs +++ b/compiler/rustc_incremental/src/persist/file_format.rs @@ -95,6 +95,12 @@ where return; } + sess.prof.artifact_size( + &name.replace(' ', "_"), + path_buf.file_name().unwrap().to_string_lossy(), + encoder.position() as u64, + ); + debug!("save: data written to disk successfully"); } diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index 2ed0539841..c0137fc7a5 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -139,9 +139,6 @@ pub fn dep_graph_path(sess: &Session) -> PathBuf { 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) -} pub fn work_products_path(sess: &Session) -> PathBuf { in_incr_comp_dir_sess(sess, WORK_PRODUCTS_FILENAME) @@ -241,9 +238,7 @@ pub fn prepare_session_directory( // have already tried before. let source_directory = find_source_directory(&crate_dir, &source_directories_already_tried); - let source_directory = if let Some(dir) = source_directory { - dir - } else { + let Some(source_directory) = source_directory else { // There's nowhere to copy from, we're done debug!( "no source directory found. Continuing with empty session \ @@ -397,15 +392,14 @@ fn copy_files(sess: &Session, target_dir: &Path, source_dir: &Path) -> Result; +#[derive(Debug)] pub enum LoadResult { Ok { data: T }, DataOutOfDate, @@ -24,6 +26,26 @@ pub enum LoadResult { impl LoadResult { pub fn open(self, sess: &Session) -> T { + // Check for errors when using `-Zassert-incremental-state` + match (sess.opts.assert_incr_state, &self) { + (Some(IncrementalStateAssertion::NotLoaded), LoadResult::Ok { .. }) => { + sess.fatal( + "We asserted that the incremental cache should not be loaded, \ + but it was loaded.", + ); + } + ( + Some(IncrementalStateAssertion::Loaded), + LoadResult::Error { .. } | LoadResult::DataOutOfDate, + ) => { + sess.fatal( + "We asserted that an existing incremental cache directory should \ + be successfully loaded, but it was not.", + ); + } + _ => {} + }; + match self { LoadResult::Error { message } => { sess.warn(&message); @@ -33,7 +55,7 @@ impl LoadResult { if let Err(err) = delete_all_session_dir_contents(sess) { sess.err(&format!( "Failed to delete invalidated or incompatible \ - incremental compilation session directory contents `{}`: {}.", + incremental compilation session directory contents `{}`: {}.", dep_graph_path(sess).display(), err )); @@ -105,7 +127,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture { // Calling `sess.incr_comp_session_dir()` will panic if `sess.opts.incremental.is_none()`. // Fortunately, we just checked that this isn't the case. - let path = dep_graph_path_from(&sess.incr_comp_session_dir()); + let path = dep_graph_path(&sess); let report_incremental_info = sess.opts.debugging_opts.incremental_info; let expected_hash = sess.opts.dep_tracking_hash(false); diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index 573124c8ec..08f13d46ee 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -4,7 +4,7 @@ use std::fmt; use std::iter; use std::marker::PhantomData; use std::mem; -use std::ops::{BitAnd, BitAndAssign, BitOrAssign, Not, Range, Shl}; +use std::ops::{BitAnd, BitAndAssign, BitOrAssign, Bound, Not, Range, RangeBounds, Shl}; use std::slice; use rustc_macros::{Decodable, Encodable}; @@ -22,6 +22,29 @@ pub trait BitRelations { fn intersect(&mut self, other: &Rhs) -> bool; } +#[inline] +fn inclusive_start_end( + range: impl RangeBounds, + domain: usize, +) -> Option<(usize, usize)> { + // Both start and end are inclusive. + let start = match range.start_bound().cloned() { + Bound::Included(start) => start.index(), + Bound::Excluded(start) => start.index() + 1, + Bound::Unbounded => 0, + }; + let end = match range.end_bound().cloned() { + Bound::Included(end) => end.index(), + Bound::Excluded(end) => end.index().checked_sub(1)?, + Bound::Unbounded => domain - 1, + }; + assert!(end < domain); + if start > end { + return None; + } + Some((start, end)) +} + macro_rules! bit_relations_inherent_impls { () => { /// Sets `self = self | other` and returns `true` if `self` changed @@ -151,6 +174,33 @@ impl BitSet { new_word != word } + #[inline] + pub fn insert_range(&mut self, elems: impl RangeBounds) { + let Some((start, end)) = inclusive_start_end(elems, self.domain_size) else { + return; + }; + + let (start_word_index, start_mask) = word_index_and_mask(start); + let (end_word_index, end_mask) = word_index_and_mask(end); + + // Set all words in between start and end (exclusively of both). + for word_index in (start_word_index + 1)..end_word_index { + self.words[word_index] = !0; + } + + if start_word_index != end_word_index { + // Start and end are in different words, so we handle each in turn. + // + // We set all leading bits. This includes the start_mask bit. + self.words[start_word_index] |= !(start_mask - 1); + // And all trailing bits (i.e. from 0..=end) in the end word, + // including the end. + self.words[end_word_index] |= end_mask | end_mask - 1; + } else { + self.words[start_word_index] |= end_mask | (end_mask - start_mask); + } + } + /// Sets all bits to true. pub fn insert_all(&mut self) { for word in &mut self.words { @@ -227,6 +277,36 @@ impl BitSet { not_already } + fn last_set_in(&self, range: impl RangeBounds) -> Option { + let (start, end) = inclusive_start_end(range, self.domain_size)?; + let (start_word_index, _) = word_index_and_mask(start); + let (end_word_index, end_mask) = word_index_and_mask(end); + + let end_word = self.words[end_word_index] & (end_mask | (end_mask - 1)); + if end_word != 0 { + let pos = max_bit(end_word) + WORD_BITS * end_word_index; + if start <= pos { + return Some(T::new(pos)); + } + } + + // We exclude end_word_index from the range here, because we don't want + // to limit ourselves to *just* the last word: the bits set it in may be + // after `end`, so it may not work out. + if let Some(offset) = + self.words[start_word_index..end_word_index].iter().rposition(|&w| w != 0) + { + let word_idx = start_word_index + offset; + let start_word = self.words[word_idx]; + let pos = max_bit(start_word) + WORD_BITS * word_idx; + if start <= pos { + return Some(T::new(pos)); + } + } + + None + } + bit_relations_inherent_impls! {} } @@ -635,6 +715,16 @@ impl SparseBitSet { self.elems.iter() } + fn last_set_in(&self, range: impl RangeBounds) -> Option { + let mut last_leq = None; + for e in self.iter() { + if range.contains(e) { + last_leq = Some(*e); + } + } + last_leq + } + bit_relations_inherent_impls! {} } @@ -709,6 +799,16 @@ impl HybridBitSet { } } + /// Returns the previous element present in the bitset from `elem`, + /// inclusively of elem. That is, will return `Some(elem)` if elem is in the + /// bitset. + pub fn last_set_in(&self, range: impl RangeBounds) -> Option { + match self { + HybridBitSet::Sparse(sparse) => sparse.last_set_in(range), + HybridBitSet::Dense(dense) => dense.last_set_in(range), + } + } + pub fn insert(&mut self, elem: T) -> bool { // No need to check `elem` against `self.domain_size` here because all // the match cases check it, one way or another. @@ -734,6 +834,41 @@ impl HybridBitSet { } } + pub fn insert_range(&mut self, elems: impl RangeBounds) { + // No need to check `elem` against `self.domain_size` here because all + // the match cases check it, one way or another. + let start = match elems.start_bound().cloned() { + Bound::Included(start) => start.index(), + Bound::Excluded(start) => start.index() + 1, + Bound::Unbounded => 0, + }; + let end = match elems.end_bound().cloned() { + Bound::Included(end) => end.index() + 1, + Bound::Excluded(end) => end.index(), + Bound::Unbounded => self.domain_size() - 1, + }; + let len = if let Some(l) = end.checked_sub(start) { + l + } else { + return; + }; + match self { + HybridBitSet::Sparse(sparse) if sparse.len() + len < SPARSE_MAX => { + // The set is sparse and has space for `elems`. + for elem in start..end { + sparse.insert(T::new(elem)); + } + } + HybridBitSet::Sparse(sparse) => { + // The set is sparse and full. Convert to a dense set. + let mut dense = sparse.to_dense(); + dense.insert_range(elems); + *self = HybridBitSet::Dense(dense); + } + HybridBitSet::Dense(dense) => dense.insert_range(elems), + } + } + pub fn insert_all(&mut self) { let domain_size = self.domain_size(); match self { @@ -990,8 +1125,9 @@ impl BitMatrix { pub fn insert_all_into_row(&mut self, row: R) { assert!(row.index() < self.num_rows); let (start, end) = self.range(row); - for word in self.words[start..end].iter_mut() { - *word = !0; + let words = &mut self.words[..]; + for index in start..end { + words[index] = !0; } self.clear_excess_bits(row); } @@ -1143,7 +1279,7 @@ impl SparseBitMatrix { /// Iterates through all the columns set to true in a given row of /// the matrix. - pub fn iter(&self, row: R) -> impl Iterator + '_ { + pub fn iter<'a>(&'a self, row: R) -> impl Iterator + 'a { self.row(row).into_iter().flat_map(|r| r.iter()) } @@ -1204,6 +1340,11 @@ fn word_index_and_mask(elem: T) -> (usize, Word) { (word_index, mask) } +#[inline] +fn max_bit(word: Word) -> usize { + WORD_BITS - 1 - word.leading_zeros() as usize +} + /// Integral type used to represent the bit set. pub trait FiniteBitSetTy: BitAnd diff --git a/compiler/rustc_index/src/bit_set/tests.rs b/compiler/rustc_index/src/bit_set/tests.rs index aebc6d0ddd..e2b07305c9 100644 --- a/compiler/rustc_index/src/bit_set/tests.rs +++ b/compiler/rustc_index/src/bit_set/tests.rs @@ -370,6 +370,101 @@ fn sparse_matrix_operations() { } } +#[test] +fn dense_insert_range() { + #[track_caller] + fn check(domain: usize, range: R) + where + R: RangeBounds + Clone + IntoIterator + std::fmt::Debug, + { + let mut set = BitSet::new_empty(domain); + set.insert_range(range.clone()); + for i in set.iter() { + assert!(range.contains(&i)); + } + for i in range.clone() { + assert!(set.contains(i), "{} in {:?}, inserted {:?}", i, set, range); + } + } + check(300, 10..10); + check(300, WORD_BITS..WORD_BITS * 2); + check(300, WORD_BITS - 1..WORD_BITS * 2); + check(300, WORD_BITS - 1..WORD_BITS); + check(300, 10..100); + check(300, 10..30); + check(300, 0..5); + check(300, 0..250); + check(300, 200..250); + + check(300, 10..=10); + check(300, WORD_BITS..=WORD_BITS * 2); + check(300, WORD_BITS - 1..=WORD_BITS * 2); + check(300, WORD_BITS - 1..=WORD_BITS); + check(300, 10..=100); + check(300, 10..=30); + check(300, 0..=5); + check(300, 0..=250); + check(300, 200..=250); + + for i in 0..WORD_BITS * 2 { + for j in i..WORD_BITS * 2 { + check(WORD_BITS * 2, i..j); + check(WORD_BITS * 2, i..=j); + check(300, i..j); + check(300, i..=j); + } + } +} + +#[test] +fn dense_last_set_before() { + fn easy(set: &BitSet, needle: impl RangeBounds) -> Option { + let mut last_leq = None; + for e in set.iter() { + if needle.contains(&e) { + last_leq = Some(e); + } + } + last_leq + } + + #[track_caller] + fn cmp(set: &BitSet, needle: impl RangeBounds + Clone + std::fmt::Debug) { + assert_eq!( + set.last_set_in(needle.clone()), + easy(set, needle.clone()), + "{:?} in {:?}", + needle, + set + ); + } + let mut set = BitSet::new_empty(300); + cmp(&set, 50..=50); + set.insert(WORD_BITS); + cmp(&set, WORD_BITS..=WORD_BITS); + set.insert(WORD_BITS - 1); + cmp(&set, 0..=WORD_BITS - 1); + cmp(&set, 0..=5); + cmp(&set, 10..100); + set.insert(100); + cmp(&set, 100..110); + cmp(&set, 99..100); + cmp(&set, 99..=100); + + for i in 0..=WORD_BITS * 2 { + for j in i..=WORD_BITS * 2 { + for k in 0..WORD_BITS * 2 { + let mut set = BitSet::new_empty(300); + cmp(&set, i..j); + cmp(&set, i..=j); + set.insert(k); + cmp(&set, i..j); + cmp(&set, i..=j); + } + } + } +} + /// Merge dense hybrid set into empty sparse hybrid set. #[bench] fn union_hybrid_sparse_empty_to_dense(b: &mut Bencher) { diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs index a72a27e07b..5149322355 100644 --- a/compiler/rustc_index/src/lib.rs +++ b/compiler/rustc_index/src/lib.rs @@ -3,7 +3,9 @@ #![feature(extend_one)] #![feature(iter_zip)] #![feature(min_specialization)] +#![feature(step_trait)] #![feature(test)] +#![feature(let_else)] pub mod bit_set; pub mod vec; diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs index 69578e85f2..55ccfd0ad2 100644 --- a/compiler/rustc_index/src/vec.rs +++ b/compiler/rustc_index/src/vec.rs @@ -118,38 +118,54 @@ macro_rules! newtype_index { } impl $type { + /// Maximum value the index can take, as a `u32`. $v const MAX_AS_U32: u32 = $max; + /// Maximum value the index can take. $v const MAX: Self = Self::from_u32($max); + /// Creates a new index from a given `usize`. + /// + /// # Panics + /// + /// Will panic if `value` exceeds `MAX`. #[inline] $v const fn from_usize(value: usize) -> Self { - #[cfg(not(bootstrap))] assert!(value <= ($max as usize)); - #[cfg(bootstrap)] - [()][(value > ($max as usize)) as usize]; + // SAFETY: We just checked that `value <= max`. unsafe { Self::from_u32_unchecked(value as u32) } } + /// Creates a new index from a given `u32`. + /// + /// # Panics + /// + /// Will panic if `value` exceeds `MAX`. #[inline] $v const fn from_u32(value: u32) -> Self { - #[cfg(not(bootstrap))] assert!(value <= $max); - #[cfg(bootstrap)] - [()][(value > $max) as usize]; + // SAFETY: We just checked that `value <= max`. unsafe { Self::from_u32_unchecked(value) } } + /// Creates a new index from a given `u32`. + /// + /// # Safety + /// + /// The provided value must be less than or equal to the maximum value for the newtype. + /// Providing a value outside this range is undefined due to layout restrictions. + /// + /// Prefer using `from_u32`. #[inline] $v const unsafe fn from_u32_unchecked(value: u32) -> Self { Self { private: value } } - /// Extracts the value of this index as an integer. + /// Extracts the value of this index as a `usize`. #[inline] $v const fn index(self) -> usize { self.as_usize() @@ -634,15 +650,18 @@ impl IndexVec { } #[inline] - pub fn drain>(&mut self, range: R) -> impl Iterator + '_ { + pub fn drain<'a, R: RangeBounds>( + &'a mut self, + range: R, + ) -> impl Iterator + 'a { self.raw.drain(range) } #[inline] - pub fn drain_enumerated>( - &mut self, + pub fn drain_enumerated<'a, R: RangeBounds>( + &'a mut self, range: R, - ) -> impl Iterator + '_ { + ) -> impl Iterator + 'a { self.raw.drain(range).enumerate().map(|(n, t)| (I::new(n), t)) } diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 2296cc6129..5b4a9d9dfa 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -108,7 +108,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { let tcx = self.tcx; // Select everything, returning errors. - let true_errors = fulfill_cx.select_where_possible(self).err().unwrap_or_else(Vec::new); + let true_errors = fulfill_cx.select_where_possible(self); debug!("true_errors = {:#?}", true_errors); if !true_errors.is_empty() { @@ -118,7 +118,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { } // Anything left unselected *now* must be an ambiguity. - let ambig_errors = fulfill_cx.select_all_or_error(self).err().unwrap_or_else(Vec::new); + let ambig_errors = fulfill_cx.select_all_or_error(self); debug!("ambig_errors = {:#?}", ambig_errors); let region_obligations = self.take_registered_region_obligations(); diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index 3f54247ece..09bfb3290f 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -866,6 +866,7 @@ impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> { Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?)) } + #[tracing::instrument(level = "debug", skip(self))] fn tys(&mut self, t: Ty<'tcx>, _t: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { debug_assert_eq!(t, _t); debug!("ConstInferUnifier: t={:?}", t); @@ -941,6 +942,7 @@ impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> { } } + #[tracing::instrument(level = "debug", skip(self))] fn consts( &mut self, c: &'tcx ty::Const<'tcx>, @@ -951,29 +953,38 @@ impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> { match c.val { ty::ConstKind::Infer(InferConst::Var(vid)) => { - let mut inner = self.infcx.inner.borrow_mut(); - let variable_table = &mut inner.const_unification_table(); - // Check if the current unification would end up // unifying `target_vid` with a const which contains // an inference variable which is unioned with `target_vid`. // // Not doing so can easily result in stack overflows. - if variable_table.unioned(self.target_vid, vid) { + if self + .infcx + .inner + .borrow_mut() + .const_unification_table() + .unioned(self.target_vid, vid) + { return Err(TypeError::CyclicConst(c)); } - let var_value = variable_table.probe_value(vid); + let var_value = + self.infcx.inner.borrow_mut().const_unification_table().probe_value(vid); match var_value.val { ConstVariableValue::Known { value: u } => self.consts(u, u), ConstVariableValue::Unknown { universe } => { if self.for_universe.can_name(universe) { Ok(c) } else { - let new_var_id = variable_table.new_key(ConstVarValue { - origin: var_value.origin, - val: ConstVariableValue::Unknown { universe: self.for_universe }, - }); + let new_var_id = + self.infcx.inner.borrow_mut().const_unification_table().new_key( + ConstVarValue { + origin: var_value.origin, + val: ConstVariableValue::Unknown { + universe: self.for_universe, + }, + }, + ); Ok(self.tcx().mk_const_var(new_var_id, c.ty)) } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 126c25f0c3..85226e60bd 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -310,6 +310,34 @@ pub fn unexpected_hidden_region_diagnostic( err } +/// Structurally compares two types, modulo any inference variables. +/// +/// Returns `true` if two types are equal, or if one type is an inference variable compatible +/// with the other type. A TyVar inference type is compatible with any type, and an IntVar or +/// FloatVar inference type are compatible with themselves or their concrete types (Int and +/// Float types, respectively). When comparing two ADTs, these rules apply recursively. +pub fn same_type_modulo_infer(a: Ty<'tcx>, b: Ty<'ctx>) -> bool { + match (&a.kind(), &b.kind()) { + (&ty::Adt(did_a, substs_a), &ty::Adt(did_b, substs_b)) => { + if did_a != did_b { + return false; + } + + substs_a.types().zip(substs_b.types()).all(|(a, b)| same_type_modulo_infer(a, b)) + } + (&ty::Int(_), &ty::Infer(ty::InferTy::IntVar(_))) + | (&ty::Infer(ty::InferTy::IntVar(_)), &ty::Int(_) | &ty::Infer(ty::InferTy::IntVar(_))) + | (&ty::Float(_), &ty::Infer(ty::InferTy::FloatVar(_))) + | ( + &ty::Infer(ty::InferTy::FloatVar(_)), + &ty::Float(_) | &ty::Infer(ty::InferTy::FloatVar(_)), + ) + | (&ty::Infer(ty::InferTy::TyVar(_)), _) + | (_, &ty::Infer(ty::InferTy::TyVar(_))) => true, + _ => a == b, + } +} + impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn report_region_errors(&self, errors: &Vec>) { debug!("report_region_errors(): {} errors to start", errors.len()); @@ -386,21 +414,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.report_placeholder_failure(sup_origin, sub_r, sup_r).emit(); } - - RegionResolutionError::MemberConstraintFailure { - hidden_ty, - member_region, - span, - } => { - let hidden_ty = self.resolve_vars_if_possible(hidden_ty); - unexpected_hidden_region_diagnostic( - self.tcx, - span, - hidden_ty, - member_region, - ) - .emit(); - } } } } @@ -438,8 +451,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { RegionResolutionError::GenericBoundFailure(..) => true, RegionResolutionError::ConcreteFailure(..) | RegionResolutionError::SubSupConflict(..) - | RegionResolutionError::UpperBoundUniverseConflict(..) - | RegionResolutionError::MemberConstraintFailure { .. } => false, + | RegionResolutionError::UpperBoundUniverseConflict(..) => false, }; let mut errors = if errors.iter().all(|e| is_bound_failure(e)) { @@ -454,7 +466,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { RegionResolutionError::GenericBoundFailure(ref sro, _, _) => sro.span(), RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _) => rvo.span(), RegionResolutionError::UpperBoundUniverseConflict(_, ref rvo, _, _, _) => rvo.span(), - RegionResolutionError::MemberConstraintFailure { span, .. } => span, }); errors } @@ -1483,7 +1494,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let mut returned_async_output_error = false; for &sp in values { if sp.is_desugaring(DesugaringKind::Async) && !returned_async_output_error { - if &[sp] != err.span.primary_spans() { + if [sp] != err.span.primary_spans() { let mut span: MultiSpan = sp.into(); span.push_span_label( sp, @@ -1684,11 +1695,23 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } _ => exp_found, }; - debug!("exp_found {:?} terr {:?}", exp_found, terr); + debug!("exp_found {:?} terr {:?} cause.code {:?}", exp_found, terr, cause.code); if let Some(exp_found) = exp_found { - self.suggest_as_ref_where_appropriate(span, &exp_found, diag); - self.suggest_accessing_field_where_appropriate(cause, &exp_found, diag); - self.suggest_await_on_expect_found(cause, span, &exp_found, diag); + let should_suggest_fixes = if let ObligationCauseCode::Pattern { root_ty, .. } = + &cause.code + { + // Skip if the root_ty of the pattern is not the same as the expected_ty. + // If these types aren't equal then we've probably peeled off a layer of arrays. + same_type_modulo_infer(self.resolve_vars_if_possible(*root_ty), exp_found.expected) + } else { + true + }; + + if should_suggest_fixes { + self.suggest_as_ref_where_appropriate(span, &exp_found, diag); + self.suggest_accessing_field_where_appropriate(cause, &exp_found, diag); + self.suggest_await_on_expect_found(cause, span, &exp_found, diag); + } } // In some (most?) cases cause.body_id points to actual body, but in some cases @@ -1721,13 +1744,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { if let ty::Opaque(def_id, substs) = ty.kind() { let future_trait = self.tcx.require_lang_item(LangItem::Future, None); // Future::Output - let item_def_id = self - .tcx - .associated_items(future_trait) - .in_definition_order() - .next() - .unwrap() - .def_id; + let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0]; let bounds = self.tcx.explicit_item_bounds(*def_id); @@ -1784,7 +1801,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.get_impl_future_output_ty(exp_found.expected), self.get_impl_future_output_ty(exp_found.found), ) { - (Some(exp), Some(found)) if ty::TyS::same_type(exp, found) => match &cause.code { + (Some(exp), Some(found)) if same_type_modulo_infer(exp, found) => match &cause.code { ObligationCauseCode::IfExpression(box IfExpressionCause { then, .. }) => { diag.multipart_suggestion( "consider `await`ing on both `Future`s", @@ -1816,32 +1833,39 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { diag.help("consider `await`ing on both `Future`s"); } }, - (_, Some(ty)) if ty::TyS::same_type(exp_found.expected, ty) => { - let span = match cause.code { - // scrutinee's span - ObligationCauseCode::Pattern { span: Some(span), .. } => span, - _ => exp_span, - }; - diag.span_suggestion_verbose( - span.shrink_to_hi(), - "consider `await`ing on the `Future`", - ".await".to_string(), - Applicability::MaybeIncorrect, - ); - } - (Some(ty), _) if ty::TyS::same_type(ty, exp_found.found) => { - let span = match cause.code { - // scrutinee's span - ObligationCauseCode::Pattern { span: Some(span), .. } => span, - _ => exp_span, - }; + (_, Some(ty)) if same_type_modulo_infer(exp_found.expected, ty) => { diag.span_suggestion_verbose( - span.shrink_to_hi(), + exp_span.shrink_to_hi(), "consider `await`ing on the `Future`", ".await".to_string(), Applicability::MaybeIncorrect, ); } + (Some(ty), _) if same_type_modulo_infer(ty, exp_found.found) => match cause.code { + ObligationCauseCode::Pattern { span: Some(span), .. } + | ObligationCauseCode::IfExpression(box IfExpressionCause { then: span, .. }) => { + diag.span_suggestion_verbose( + span.shrink_to_hi(), + "consider `await`ing on the `Future`", + ".await".to_string(), + Applicability::MaybeIncorrect, + ); + } + ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { + ref prior_arms, + .. + }) => { + diag.multipart_suggestion_verbose( + "consider `await`ing on the `Future`", + prior_arms + .iter() + .map(|arm| (arm.shrink_to_hi(), ".await".to_string())) + .collect(), + Applicability::MaybeIncorrect, + ); + } + _ => {} + }, _ => {} } } @@ -1867,7 +1891,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .iter() .filter(|field| field.vis.is_accessible_from(field.did, self.tcx)) .map(|field| (field.ident.name, field.ty(self.tcx, expected_substs))) - .find(|(_, ty)| ty::TyS::same_type(ty, exp_found.found)) + .find(|(_, ty)| same_type_modulo_infer(ty, exp_found.found)) { if let ObligationCauseCode::Pattern { span: Some(span), .. } = cause.code { if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { @@ -1932,7 +1956,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { | (_, ty::Infer(_)) | (ty::Param(_), _) | (ty::Infer(_), _) => {} - _ if ty::TyS::same_type(exp_ty, found_ty) => {} + _ if same_type_modulo_infer(exp_ty, found_ty) => {} _ => show_suggestion = false, }; } @@ -2129,10 +2153,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { None }, self.tcx.generics_of(owner.to_def_id()), + hir.span(hir_id), ) }); + + let span = match generics { + // This is to get around the trait identity obligation, that has a `DUMMY_SP` as signal + // for other diagnostics, so we need to recover it here. + Some((_, _, node)) if span.is_dummy() => node, + _ => span, + }; + let type_param_span = match (generics, bound_kind) { - (Some((_, ref generics)), GenericKind::Param(ref param)) => { + (Some((_, ref generics, _)), GenericKind::Param(ref param)) => { // Account for the case where `param` corresponds to `Self`, // which doesn't have the expected type argument. if !(generics.has_self && param.index == 0) { @@ -2169,7 +2202,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }; let new_lt = generics .as_ref() - .and_then(|(parent_g, g)| { + .and_then(|(parent_g, g, _)| { let mut possible = (b'a'..=b'z').map(|c| format!("'{}", c as char)); let mut lts_names = g .params @@ -2191,7 +2224,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .unwrap_or("'lt".to_string()); let add_lt_sugg = generics .as_ref() - .and_then(|(_, g)| g.params.first()) + .and_then(|(_, g, _)| g.params.first()) .and_then(|param| param.def_id.as_local()) .map(|def_id| { ( @@ -2207,14 +2240,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { if let Some(SubregionOrigin::CompareImplMethodObligation { span, - item_name, impl_item_def_id, trait_item_def_id, }) = origin { return self.report_extra_impl_obligation( span, - item_name, impl_item_def_id, trait_item_def_id, &format!("`{}: {}`", bound_kind, sub), @@ -2547,7 +2578,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { infer::MiscVariable(_) => String::new(), infer::PatternRegion(_) => " for pattern".to_string(), infer::AddrOfRegion(_) => " for borrow expression".to_string(), - infer::Autoref(_, _) => " for autoref".to_string(), + infer::Autoref(_) => " for autoref".to_string(), infer::Coercion(_) => " for automatic coercion".to_string(), infer::LateBoundRegion(_, br, infer::FnCall) => { format!(" for lifetime parameter {}in function call", br_string(br)) 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 e00003face..a7e019a53e 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 @@ -5,13 +5,12 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Namespace}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; -use rustc_hir::{Body, Expr, ExprKind, FnRetTy, HirId, Local, Pat}; +use rustc_hir::{Body, Expr, ExprKind, FnRetTy, HirId, Local, MatchSource, Pat}; use rustc_middle::hir::map::Map; use rustc_middle::infer::unify_key::ConstVariableOriginKind; use rustc_middle::ty::print::Print; use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; use rustc_middle::ty::{self, DefIdTree, InferConst, Ty, TyCtxt}; -use rustc_span::source_map::DesugaringKind; use rustc_span::symbol::kw; use rustc_span::Span; use std::borrow::Cow; @@ -26,6 +25,7 @@ struct FindHirNodeVisitor<'a, 'tcx> { found_closure: Option<&'tcx Expr<'tcx>>, found_method_call: Option<&'tcx Expr<'tcx>>, found_exact_method_call: Option<&'tcx Expr<'tcx>>, + found_for_loop_iter: Option<&'tcx Expr<'tcx>>, found_use_diagnostic: Option>, } @@ -41,6 +41,7 @@ impl<'a, 'tcx> FindHirNodeVisitor<'a, 'tcx> { found_closure: None, found_method_call: None, found_exact_method_call: None, + found_for_loop_iter: None, found_use_diagnostic: None, } } @@ -111,6 +112,15 @@ impl<'a, 'tcx> Visitor<'tcx> for FindHirNodeVisitor<'a, 'tcx> { } fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { + if let ExprKind::Match(scrutinee, [_, arm], MatchSource::ForLoopDesugar) = expr.kind { + if let Some(pat) = arm.pat.for_loop_some() { + if let Some(ty) = self.node_ty_contains_target(pat.hir_id) { + self.found_for_loop_iter = Some(scrutinee); + self.found_node_ty = Some(ty); + return; + } + } + } if let ExprKind::MethodCall(_, call_span, exprs, _) = expr.kind { if call_span == self.target_span && Some(self.target) @@ -643,10 +653,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let msg = if let Some(simple_ident) = pattern.simple_ident() { match pattern.span.desugaring_kind() { None => format!("consider giving `{}` {}", simple_ident, suffix), - Some(DesugaringKind::ForLoop(_)) => { - "the element type for this iterator is not specified".to_string() - } - _ => format!("this needs {}", suffix), + Some(_) => format!("this needs {}", suffix), } } else { format!("consider giving this pattern {}", suffix) @@ -719,6 +726,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // = note: type must be known at this point self.annotate_method_call(segment, e, &mut err); } + } else if let Some(scrutinee) = local_visitor.found_for_loop_iter { + err.span_label( + scrutinee.span, + "the element type for this iterator is not specified".to_string(), + ); } // Instead of the following: // error[E0282]: type annotations needed diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs index 1b35c4032f..ac57796763 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs @@ -7,7 +7,10 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::SubregionOrigin; -use rustc_errors::{struct_span_err, ErrorReported}; +use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported}; +use rustc_hir as hir; +use rustc_hir::{GenericParamKind, Ty}; +use rustc_middle::ty::Region; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { /// Print the error message for lifetime errors when both the concerned regions are anonymous. @@ -160,11 +163,13 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } }; - let mut e = struct_span_err!(self.tcx().sess, span, E0623, "lifetime mismatch"); + let mut err = struct_span_err!(self.tcx().sess, span, E0623, "lifetime mismatch"); - e.span_label(span_1, main_label); - e.span_label(span_2, String::new()); - e.span_label(span, span_label); + err.span_label(span_1, main_label); + err.span_label(span_2, String::new()); + err.span_label(span, span_label); + + self.suggest_adding_lifetime_params(sub, ty_sup, ty_sub, &mut err); if let Some(t) = future_return_type { let snip = self @@ -178,14 +183,87 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { (_, "") => None, _ => Some(s), }) - .unwrap_or("{unnamed_type}".to_string()); + .unwrap_or_else(|| "{unnamed_type}".to_string()); - e.span_label( + err.span_label( t.span, &format!("this `async fn` implicitly returns an `impl Future`", snip), ); } - e.emit(); + err.emit(); Some(ErrorReported) } + + fn suggest_adding_lifetime_params( + &self, + sub: Region<'tcx>, + ty_sup: &Ty<'_>, + ty_sub: &Ty<'_>, + err: &mut DiagnosticBuilder<'_>, + ) { + if let ( + hir::Ty { kind: hir::TyKind::Rptr(lifetime_sub, _), .. }, + hir::Ty { kind: hir::TyKind::Rptr(lifetime_sup, _), .. }, + ) = (ty_sub, ty_sup) + { + if lifetime_sub.name.is_elided() && lifetime_sup.name.is_elided() { + if let Some(anon_reg) = self.tcx().is_suitable_region(sub) { + let hir_id = self.tcx().hir().local_def_id_to_hir_id(anon_reg.def_id); + if let hir::Node::Item(&hir::Item { + kind: hir::ItemKind::Fn(_, ref generics, ..), + .. + }) = self.tcx().hir().get(hir_id) + { + let (suggestion_param_name, introduce_new) = generics + .params + .iter() + .find(|p| matches!(p.kind, GenericParamKind::Lifetime { .. })) + .and_then(|p| self.tcx().sess.source_map().span_to_snippet(p.span).ok()) + .map(|name| (name, false)) + .unwrap_or_else(|| ("'a".to_string(), true)); + + let mut suggestions = vec![ + if let hir::LifetimeName::Underscore = lifetime_sub.name { + (lifetime_sub.span, suggestion_param_name.clone()) + } else { + ( + lifetime_sub.span.shrink_to_hi(), + suggestion_param_name.clone() + " ", + ) + }, + if let hir::LifetimeName::Underscore = lifetime_sup.name { + (lifetime_sup.span, suggestion_param_name.clone()) + } else { + ( + lifetime_sup.span.shrink_to_hi(), + suggestion_param_name.clone() + " ", + ) + }, + ]; + + if introduce_new { + let new_param_suggestion = match &generics.params { + [] => (generics.span, format!("<{}>", suggestion_param_name)), + [first, ..] => ( + first.span.shrink_to_lo(), + format!("{}, ", suggestion_param_name), + ), + }; + + suggestions.push(new_param_suggestion); + } + + err.multipart_suggestion( + "consider introducing a named lifetime parameter", + suggestions, + Applicability::MaybeIncorrect, + ); + err.note( + "each elided lifetime in input position becomes a distinct lifetime", + ); + } + } + } + } + } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs index 0878f8550d..eb1c80ecb0 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs @@ -3,8 +3,6 @@ use crate::infer::error_reporting::nice_region_error::find_anon_type::find_anon_type; use crate::infer::error_reporting::nice_region_error::NiceRegionError; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; -use rustc_hir::intravisit::Visitor; -use rustc_hir::FnRetTy; use rustc_middle::ty; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { @@ -48,19 +46,24 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { return None; // inapplicable }; + // Suggesting to add a `'static` lifetime to a parameter is nearly always incorrect, + // and can steer users down the wrong path. + if *named == ty::ReStatic { + return None; + } + debug!("try_report_named_anon_conflict: named = {:?}", named); debug!("try_report_named_anon_conflict: anon_param_info = {:?}", anon_param_info); debug!("try_report_named_anon_conflict: region_info = {:?}", region_info); - let (param, new_ty, new_ty_span, br, is_first, scope_def_id, is_impl_item) = ( - anon_param_info.param, - anon_param_info.param_ty, - anon_param_info.param_ty_span, - anon_param_info.bound_region, - anon_param_info.is_first, - region_info.def_id, - region_info.is_impl_item, - ); + let param = anon_param_info.param; + let new_ty = anon_param_info.param_ty; + let new_ty_span = anon_param_info.param_ty_span; + let br = anon_param_info.bound_region; + let is_first = anon_param_info.is_first; + let scope_def_id = region_info.def_id; + let is_impl_item = region_info.is_impl_item; + match br { ty::BrAnon(_) => {} _ => { @@ -75,26 +78,10 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { return None; } - if let Some((_, fndecl)) = find_anon_type(self.tcx(), anon, &br) { - if self.is_self_anon(is_first, scope_def_id) { - return None; - } - - if let FnRetTy::Return(ty) = &fndecl.output { - let mut v = ty::TraitObjectVisitor(vec![], self.tcx().hir()); - v.visit_ty(ty); - - debug!("try_report_named_anon_conflict: ret ty {:?}", ty); - if sub == &ty::ReStatic - && v.0.into_iter().any(|t| t.span.desugaring_kind().is_none()) - { - // If the failure is due to a `'static` requirement coming from a `dyn` or - // `impl` Trait that *isn't* caused by `async fn` desugaring, handle this case - // better in `static_impl_trait`. - debug!("try_report_named_anon_conflict: impl Trait + 'static"); - return None; - } - } + if find_anon_type(self.tcx(), anon, &br).is_some() + && self.is_self_anon(is_first, scope_def_id) + { + return None; } let (error_var, span_label_var) = match param.pat.simple_ident() { @@ -114,16 +101,12 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ); diag.span_label(span, format!("lifetime `{}` required", named)); - // Suggesting `'static` is nearly always incorrect, and can steer users - // down the wrong path. - if *named != ty::ReStatic { - diag.span_suggestion( - new_ty_span, - &format!("add explicit lifetime `{}` to {}", named, span_label_var), - new_ty.to_string(), - Applicability::Unspecified, - ); - } + diag.span_suggestion( + new_ty_span, + &format!("add explicit lifetime `{}` to {}", named, span_label_var), + new_ty.to_string(), + Applicability::Unspecified, + ); Some(diag) } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index 7fba6a823d..2aaebed28c 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -192,14 +192,16 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ObligationCauseCode::MatchImpl(parent, ..) => &parent.code, _ => &cause.code, }; - if let ObligationCauseCode::ItemObligation(item_def_id) = *code { + if let (ObligationCauseCode::ItemObligation(item_def_id), None) = + (code, override_error_code) + { // Same case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a `'static` // lifetime as above, but called using a fully-qualified path to the method: // `Foo::qux(bar)`. let mut v = TraitObjectVisitor(FxHashSet::default()); v.visit_ty(param.param_ty); if let Some((ident, self_ty)) = - self.get_impl_ident_and_self_ty_from_trait(item_def_id, &v.0) + self.get_impl_ident_and_self_ty_from_trait(*item_def_id, &v.0) { if self.suggest_constrain_dyn_trait_in_impl(&mut err, &v.0, ident, self_ty) { override_error_code = Some(ident); @@ -263,9 +265,7 @@ pub fn suggest_new_region_bound( match fn_return.kind { TyKind::OpaqueDef(item_id, _) => { let item = tcx.hir().item(item_id); - let opaque = if let ItemKind::OpaqueTy(opaque) = &item.kind { - opaque - } else { + let ItemKind::OpaqueTy(opaque) = &item.kind else { return; }; diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs index ea9d0eae17..cfa79213c8 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs @@ -9,10 +9,13 @@ use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; -use rustc_middle::ty::error::ExpectedFound; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::print::RegionHighlightMode; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitor}; + use rustc_span::{MultiSpan, Span, Symbol}; +use std::ops::ControlFlow; + impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { /// Print the error message for lifetime errors when the `impl` doesn't conform to the `trait`. pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option { @@ -51,12 +54,16 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { { if let SubregionOrigin::CompareImplTypeObligation { span, - item_name, impl_item_def_id, trait_item_def_id, } = origin { - self.emit_associated_type_err(span, item_name, impl_item_def_id, trait_item_def_id); + self.emit_associated_type_err( + span, + self.infcx.tcx.item_name(impl_item_def_id), + impl_item_def_id, + trait_item_def_id, + ); return Some(ErrorReported); } } @@ -69,6 +76,47 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { .tcx() .sess .struct_span_err(sp, "`impl` item signature doesn't match `trait` item signature"); + + // Mark all unnamed regions in the type with a number. + // This diagnostic is called in response to lifetime errors, so be informative. + struct HighlightBuilder<'tcx> { + highlight: RegionHighlightMode, + tcx: TyCtxt<'tcx>, + counter: usize, + } + + impl HighlightBuilder<'tcx> { + fn build(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> RegionHighlightMode { + let mut builder = + HighlightBuilder { highlight: RegionHighlightMode::default(), counter: 1, tcx }; + builder.visit_ty(ty); + builder.highlight + } + } + + impl<'tcx> ty::fold::TypeVisitor<'tcx> for HighlightBuilder<'tcx> { + fn tcx_for_anon_const_substs(&self) -> Option> { + Some(self.tcx) + } + + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + if !r.has_name() && self.counter <= 3 { + self.highlight.highlighting_region(r, self.counter); + self.counter += 1; + } + r.super_visit_with(self) + } + } + + let expected_highlight = HighlightBuilder::build(self.tcx(), expected); + let expected = self + .infcx + .extract_inference_diagnostics_data(expected.into(), Some(expected_highlight)) + .name; + let found_highlight = HighlightBuilder::build(self.tcx(), found); + let found = + self.infcx.extract_inference_diagnostics_data(found.into(), Some(found_highlight)).name; + err.span_label(sp, &format!("found `{}`", found)); err.span_label(trait_sp, &format!("expected `{}`", expected)); @@ -96,15 +144,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ); } - if let Some((expected, found)) = - self.infcx.expected_found_str_ty(ExpectedFound { expected, found }) - { - // Highlighted the differences when showing the "expected/found" note. - err.note_expected_found(&"", expected, &"", found); - } else { - // This fallback shouldn't be necessary, but let's keep it in just in case. - err.note(&format!("expected `{}`\n found `{}`", expected, found)); - } + err.note(&format!("expected `{}`\n found `{}`", expected, found)); + err.span_help( type_param_span, "the lifetime requirements from the `impl` do not correspond to the requirements in \ diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs index 8dcdd4b149..90bc5b3b2f 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs @@ -143,9 +143,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // similar to the asyncness fn in rustc_ty_utils::ty let hir_id = self.tcx().hir().local_def_id_to_hir_id(local_def_id); let node = self.tcx().hir().get(hir_id); - let fn_like = rustc_middle::hir::map::blocks::FnLikeNode::from_node(node)?; - - Some(fn_like.asyncness()) + let fn_kind = node.fn_kind()?; + Some(fn_kind.asyncness()) } // Here, we check for the case where the anonymous region diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index 5f99a23f86..6600c18351 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -53,9 +53,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { infer::RelateObjectBound(span) => { label_or_note(span, "...so that it can be closed over into an object"); } - infer::CallReturn(span) => { - label_or_note(span, "...so that return value is valid for the call"); - } infer::DataBorrowed(ty, span) => { label_or_note( span, @@ -281,23 +278,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ); err } - infer::CallReturn(span) => { - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0482, - "lifetime of return value does not outlive the function call" - ); - note_and_explain_region( - self.tcx, - &mut err, - "the return value is only valid for ", - sup, - "", - None, - ); - err - } infer::DataBorrowed(ty, span) => { let mut err = struct_span_err!( self.tcx.sess, @@ -350,30 +330,21 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ); err } - infer::CompareImplMethodObligation { - span, - item_name, - impl_item_def_id, - trait_item_def_id, - } => self.report_extra_impl_obligation( - span, - item_name, - impl_item_def_id, - trait_item_def_id, - &format!("`{}: {}`", sup, sub), - ), - infer::CompareImplTypeObligation { - span, - item_name, - impl_item_def_id, - trait_item_def_id, - } => self.report_extra_impl_obligation( - span, - item_name, - impl_item_def_id, - trait_item_def_id, - &format!("`{}: {}`", sup, sub), - ), + infer::CompareImplMethodObligation { span, impl_item_def_id, trait_item_def_id } => { + self.report_extra_impl_obligation( + span, + impl_item_def_id, + trait_item_def_id, + &format!("`{}: {}`", sup, sub), + ) + } + infer::CompareImplTypeObligation { span, impl_item_def_id, trait_item_def_id } => self + .report_extra_impl_obligation( + span, + impl_item_def_id, + trait_item_def_id, + &format!("`{}: {}`", sup, sub), + ), } } diff --git a/compiler/rustc_infer/src/infer/free_regions.rs b/compiler/rustc_infer/src/infer/free_regions.rs index 728dc2de37..4814b65e32 100644 --- a/compiler/rustc_infer/src/infer/free_regions.rs +++ b/compiler/rustc_infer/src/infer/free_regions.rs @@ -66,8 +66,6 @@ impl<'tcx> FreeRegionMap<'tcx> { /// follows. If we know that `r_b: 'static`, then this function /// will return true, even though we don't know anything that /// directly relates `r_a` and `r_b`. - /// - /// Also available through the `FreeRegionRelations` trait below. pub fn sub_free_regions( &self, tcx: TyCtxt<'tcx>, @@ -131,27 +129,6 @@ impl<'tcx> FreeRegionMap<'tcx> { } } -/// The NLL region handling code represents free region relations in a -/// slightly different way; this trait allows functions to be abstract -/// over which version is in use. -pub trait FreeRegionRelations<'tcx> { - /// Tests whether `r_a <= r_b`. Both must be free regions or - /// `'static`. - fn sub_free_regions( - &self, - tcx: TyCtxt<'tcx>, - shorter: ty::Region<'tcx>, - longer: ty::Region<'tcx>, - ) -> bool; -} - -impl<'tcx> FreeRegionRelations<'tcx> for FreeRegionMap<'tcx> { - fn sub_free_regions(&self, tcx: TyCtxt<'tcx>, r_a: Region<'tcx>, r_b: Region<'tcx>) -> bool { - // invoke the "inherent method" - self.sub_free_regions(tcx, r_a, r_b) - } -} - impl<'a, 'tcx> Lift<'tcx> for FreeRegionMap<'a> { type Lifted = FreeRegionMap<'tcx>; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option> { diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index 869fd225d5..4c9dcab26b 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -2,7 +2,6 @@ use crate::infer::region_constraints::Constraint; use crate::infer::region_constraints::GenericKind; -use crate::infer::region_constraints::MemberConstraint; use crate::infer::region_constraints::RegionConstraintData; use crate::infer::region_constraints::VarInfos; use crate::infer::region_constraints::VerifyBound; @@ -20,7 +19,6 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{ReEarlyBound, ReEmpty, ReErased, ReFree, ReStatic}; use rustc_middle::ty::{ReLateBound, RePlaceholder, ReVar}; use rustc_middle::ty::{Region, RegionVid}; -use rustc_span::Span; use std::fmt; /// This function performs lexical region resolution given a complete @@ -28,13 +26,13 @@ use std::fmt; /// iteration to find region values which satisfy all constraints, /// assuming such values can be found. It returns the final values of /// all the variables as well as a set of errors that must be reported. +#[instrument(level = "debug", skip(region_rels, var_infos, data))] pub fn resolve<'tcx>( region_rels: &RegionRelations<'_, 'tcx>, var_infos: VarInfos, data: RegionConstraintData<'tcx>, mode: RegionckMode, ) -> (LexicalRegionResolutions<'tcx>, Vec>) { - debug!("RegionConstraintData: resolve_regions()"); let mut errors = vec![]; let mut resolver = LexicalResolver { region_rels, var_infos, data }; match mode { @@ -109,11 +107,6 @@ pub enum RegionResolutionError<'tcx> { SubregionOrigin<'tcx>, // cause of the constraint Region<'tcx>, // the placeholder `'b` ), - - /// Indicates a failure of a `MemberConstraint`. These arise during - /// impl trait processing explicitly -- basically, the impl trait's hidden type - /// included some region that it was not supposed to. - MemberConstraintFailure { span: Span, hidden_ty: Ty<'tcx>, member_region: Region<'tcx> }, } struct RegionAndOrigin<'tcx> { @@ -150,12 +143,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { let graph = self.construct_graph(); self.expand_givens(&graph); - loop { - self.expansion(&mut var_data); - if !self.enforce_member_constraints(&graph, &mut var_data) { - break; - } - } + self.expansion(&mut var_data); self.collect_errors(&mut var_data, errors); self.collect_var_errors(&var_data, &graph, errors); var_data @@ -233,120 +221,6 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { } } - /// Enforce all member constraints and return true if anything - /// changed. See `enforce_member_constraint` for more details. - fn enforce_member_constraints( - &self, - graph: &RegionGraph<'tcx>, - var_values: &mut LexicalRegionResolutions<'tcx>, - ) -> bool { - // Note: we don't use the `any` combinator because we don't - // want to stop at the first constraint that makes a change. - let mut any_changed = false; - for member_constraint in &self.data.member_constraints { - any_changed |= self.enforce_member_constraint(graph, member_constraint, var_values); - } - any_changed - } - - /// Enforce a constraint like - /// - /// ``` - /// 'r member of ['c...] - /// ``` - /// - /// We look for all choice regions from the list `'c...` that: - /// - /// (a) are greater than the current value of `'r` (which is a lower bound) - /// - /// and - /// - /// (b) are compatible with the upper bounds of `'r` that we can - /// find by traversing the graph. - /// - /// From that list, we look for a *minimal* option `'c_min`. If we - /// find one, then we can enforce that `'r: 'c_min`. - fn enforce_member_constraint( - &self, - graph: &RegionGraph<'tcx>, - member_constraint: &MemberConstraint<'tcx>, - var_values: &mut LexicalRegionResolutions<'tcx>, - ) -> bool { - debug!("enforce_member_constraint(member_constraint={:#?})", member_constraint); - - // The constraint is some inference variable (`vid`) which - // must be equal to one of the options. - let member_vid = match member_constraint.member_region { - ty::ReVar(vid) => *vid, - _ => return false, - }; - - // The current value of `vid` is a lower bound LB -- i.e., we - // know that `LB <= vid` must be true. - let member_lower_bound: ty::Region<'tcx> = match var_values.value(member_vid) { - VarValue::ErrorValue => return false, - VarValue::Value(r) => r, - }; - - // Find all the "upper bounds" -- that is, each region `b` such that - // `r0 <= b` must hold. - let (member_upper_bounds, ..) = - self.collect_bounding_regions(graph, member_vid, OUTGOING, None); - - // Get an iterator over the *available choice* -- that is, - // each choice region `c` where `lb <= c` and `c <= ub` for all the - // upper bounds `ub`. - debug!("enforce_member_constraint: upper_bounds={:#?}", member_upper_bounds); - let mut options = member_constraint.choice_regions.iter().filter(|option| { - self.sub_concrete_regions(member_lower_bound, option) - && member_upper_bounds - .iter() - .all(|upper_bound| self.sub_concrete_regions(option, upper_bound.region)) - }); - - // If there is more than one option, we only make a choice if - // there is a single *least* choice -- i.e., some available - // region that is `<=` all the others. - let mut least_choice: ty::Region<'tcx> = match options.next() { - Some(&r) => r, - None => return false, - }; - debug!("enforce_member_constraint: least_choice={:?}", least_choice); - for &option in options { - debug!("enforce_member_constraint: option={:?}", option); - if !self.sub_concrete_regions(least_choice, option) { - if self.sub_concrete_regions(option, least_choice) { - debug!("enforce_member_constraint: new least choice"); - least_choice = option; - } else { - debug!("enforce_member_constraint: no least choice"); - return false; - } - } - } - - // (#72087) Different `ty::Regions` can be known to be equal, for - // example, we know that `'a` and `'static` are equal in a function - // with a parameter of type `&'static &'a ()`. - // - // When we have two equal regions like this `expansion` will use - // `lub_concrete_regions` to pick a canonical representative. The same - // choice is needed here so that we don't end up in a cycle of - // `expansion` changing the region one way and the code here changing - // it back. - let lub = self.lub_concrete_regions(least_choice, member_lower_bound); - debug!( - "enforce_member_constraint: final least choice = {:?}\nlub = {:?}", - least_choice, lub - ); - if lub != member_lower_bound { - *var_values.value_mut(member_vid) = VarValue::Value(least_choice); - true - } else { - false - } - } - fn expansion(&self, var_values: &mut LexicalRegionResolutions<'tcx>) { let mut constraints = IndexVec::from_elem_n(Vec::new(), var_values.values.len()); let mut changes = Vec::new(); @@ -461,6 +335,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { } /// True if `a <= b`, but not defined over inference variables. + #[instrument(level = "trace", skip(self))] fn sub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> bool { let tcx = self.tcx(); let sub_free_regions = |r1, r2| self.region_rels.free_regions.sub_free_regions(tcx, r1, r2); @@ -492,6 +367,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { /// /// Neither `a` nor `b` may be an inference variable (hence the /// term "concrete regions"). + #[instrument(level = "trace", skip(self))] fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> { let r = match (a, b) { (&ReLateBound(..), _) | (_, &ReLateBound(..)) | (&ReErased, _) | (_, &ReErased) => { @@ -562,13 +438,14 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { /// After expansion is complete, go and check upper bounds (i.e., /// cases where the region cannot grow larger than a fixed point) /// and check that they are satisfied. + #[instrument(skip(self, var_data, errors))] fn collect_errors( &self, var_data: &mut LexicalRegionResolutions<'tcx>, errors: &mut Vec>, ) { for (constraint, origin) in &self.data.constraints { - debug!("collect_errors: constraint={:?} origin={:?}", constraint, origin); + debug!(?constraint, ?origin); match *constraint { Constraint::RegSubVar(..) | Constraint::VarSubVar(..) => { // Expansion will ensure that these constraints hold. Ignore. @@ -580,7 +457,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { } debug!( - "collect_errors: region error at {:?}: \ + "region error at {:?}: \ cannot verify that {:?} <= {:?}", origin, sub, sup ); @@ -606,7 +483,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { // collect them later. if !self.sub_concrete_regions(a_region, b_region) { debug!( - "collect_errors: region error at {:?}: \ + "region error at {:?}: \ cannot verify that {:?}={:?} <= {:?}", origin, a_vid, a_region, b_region ); @@ -616,23 +493,6 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { } } - // Check that all member constraints are satisfied. - for member_constraint in &self.data.member_constraints { - let member_region = var_data.normalize(self.tcx(), member_constraint.member_region); - let choice_regions = member_constraint - .choice_regions - .iter() - .map(|&choice_region| var_data.normalize(self.tcx(), choice_region)); - if !choice_regions.clone().any(|choice_region| member_region == choice_region) { - let span = self.tcx().def_span(member_constraint.opaque_type_def_id); - errors.push(RegionResolutionError::MemberConstraintFailure { - span, - hidden_ty: member_constraint.hidden_ty, - member_region, - }); - } - } - for verify in &self.data.verifys { debug!("collect_errors: verify={:?}", verify); let sub = var_data.normalize(self.tcx(), verify.region); diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 18836d5a68..2fd01c2d59 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -95,9 +95,10 @@ pub(crate) type UnificationTable<'a, 'tcx, T> = ut::UnificationTable< /// This is used so that the region values inferred by HIR region solving are /// not exposed, and so that we can avoid doing work in HIR typeck that MIR /// typeck will also do. -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, Default)] pub enum RegionckMode { /// The default mode: report region errors, don't erase regions. + #[default] Solve, /// Erase the results of region after solving. Erase { @@ -108,12 +109,6 @@ pub enum RegionckMode { }, } -impl Default for RegionckMode { - fn default() -> Self { - RegionckMode::Solve - } -} - impl RegionckMode { /// Indicates that the MIR borrowck will repeat these region /// checks, so we should ignore errors if NLL is (unconditionally) @@ -417,26 +412,13 @@ pub enum SubregionOrigin<'tcx> { /// (&'a &'b T) where a >= b ReferenceOutlivesReferent(Ty<'tcx>, Span), - /// Region in return type of invoked fn must enclose call - CallReturn(Span), - /// Comparing the signature and requirements of an impl method against /// the containing trait. - CompareImplMethodObligation { - span: Span, - item_name: Symbol, - impl_item_def_id: DefId, - trait_item_def_id: DefId, - }, + CompareImplMethodObligation { span: Span, impl_item_def_id: DefId, trait_item_def_id: DefId }, /// Comparing the signature and requirements of an impl associated type /// against the containing trait - CompareImplTypeObligation { - span: Span, - item_name: Symbol, - impl_item_def_id: DefId, - trait_item_def_id: DefId, - }, + CompareImplTypeObligation { span: Span, impl_item_def_id: DefId, trait_item_def_id: DefId }, } // `SubregionOrigin` is used a lot. Make sure it doesn't unintentionally get bigger. @@ -472,7 +454,7 @@ pub enum RegionVariableOrigin { AddrOfRegion(Span), /// Regions created as part of an autoref of a method receiver - Autoref(Span, ty::AssocItem), + Autoref(Span), /// Regions created as part of an automatic coercion Coercion(Span), @@ -1255,16 +1237,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.tainted_by_errors_flag.set(true) } - /// Process the region constraints and report any errors that + /// Process the region constraints and return any any errors that /// result. After this, no more unification operations should be /// done -- or the compiler will panic -- but it is legal to use /// `resolve_vars_if_possible` as well as `fully_resolve`. - pub fn resolve_regions_and_report_errors( + pub fn resolve_regions( &self, region_context: DefId, outlives_env: &OutlivesEnvironment<'tcx>, mode: RegionckMode, - ) { + ) -> Vec> { let (var_infos, data) = { let mut inner = self.inner.borrow_mut(); let inner = &mut *inner; @@ -1290,6 +1272,21 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions)); assert!(old_value.is_none()); + errors + } + + /// Process the region constraints and report any errors that + /// result. After this, no more unification operations should be + /// done -- or the compiler will panic -- but it is legal to use + /// `resolve_vars_if_possible` as well as `fully_resolve`. + pub fn resolve_regions_and_report_errors( + &self, + region_context: DefId, + outlives_env: &OutlivesEnvironment<'tcx>, + mode: RegionckMode, + ) { + let errors = self.resolve_regions(region_context, outlives_env, mode); + if !self.is_tainted_by_errors() { // As a heuristic, just skip reporting region errors // altogether if other errors have been reported while @@ -1803,7 +1800,6 @@ impl<'tcx> SubregionOrigin<'tcx> { ReborrowUpvar(a, _) => a, DataBorrowed(_, a) => a, ReferenceOutlivesReferent(_, a) => a, - CallReturn(a) => a, CompareImplMethodObligation { span, .. } => span, CompareImplTypeObligation { span, .. } => span, } @@ -1819,23 +1815,19 @@ impl<'tcx> SubregionOrigin<'tcx> { } traits::ObligationCauseCode::CompareImplMethodObligation { - item_name, impl_item_def_id, trait_item_def_id, } => SubregionOrigin::CompareImplMethodObligation { span: cause.span, - item_name, impl_item_def_id, trait_item_def_id, }, traits::ObligationCauseCode::CompareImplTypeObligation { - item_name, impl_item_def_id, trait_item_def_id, } => SubregionOrigin::CompareImplTypeObligation { span: cause.span, - item_name, impl_item_def_id, trait_item_def_id, }, @@ -1851,7 +1843,7 @@ impl RegionVariableOrigin { MiscVariable(a) | PatternRegion(a) | AddrOfRegion(a) - | Autoref(a, _) + | Autoref(a) | Coercion(a) | EarlyBoundRegion(a, ..) | LateBoundRegion(a, ..) diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index d0883f23a4..e2e07f2072 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -1,8 +1,17 @@ +use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use crate::infer::{InferCtxt, InferOk}; +use crate::traits; +use rustc_data_structures::sync::Lrc; use rustc_data_structures::vec_map::VecMap; use rustc_hir as hir; -use rustc_middle::ty::{OpaqueTypeKey, Ty}; +use rustc_hir::def_id::LocalDefId; +use rustc_middle::ty::fold::BottomUpFolder; +use rustc_middle::ty::subst::{GenericArgKind, Subst}; +use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeVisitor}; use rustc_span::Span; +use std::ops::ControlFlow; + pub type OpaqueTypeMap<'tcx> = VecMap, OpaqueTypeDecl<'tcx>>; /// Information about the opaque types whose values we @@ -45,3 +54,584 @@ pub struct OpaqueTypeDecl<'tcx> { /// The origin of the opaque type. pub origin: hir::OpaqueTyOrigin, } + +impl<'a, 'tcx> InferCtxt<'a, 'tcx> { + /// Replaces all opaque types in `value` with fresh inference variables + /// and creates appropriate obligations. For example, given the input: + /// + /// impl Iterator + /// + /// this method would create two type variables, `?0` and `?1`. It would + /// return the type `?0` but also the obligations: + /// + /// ?0: Iterator + /// ?1: Debug + /// + /// Moreover, it returns an `OpaqueTypeMap` that would map `?0` to + /// info about the `impl Iterator<..>` type and `?1` to info about + /// the `impl Debug` type. + /// + /// # Parameters + /// + /// - `parent_def_id` -- the `DefId` of the function in which the opaque type + /// is defined + /// - `body_id` -- the body-id with which the resulting obligations should + /// be associated + /// - `param_env` -- the in-scope parameter environment to be used for + /// obligations + /// - `value` -- the value within which we are instantiating opaque types + /// - `value_span` -- the span where the value came from, used in error reporting + pub fn instantiate_opaque_types>( + &self, + body_id: hir::HirId, + param_env: ty::ParamEnv<'tcx>, + value: T, + value_span: Span, + ) -> InferOk<'tcx, T> { + debug!( + "instantiate_opaque_types(value={:?}, body_id={:?}, \ + param_env={:?}, value_span={:?})", + value, body_id, param_env, value_span, + ); + let mut instantiator = + Instantiator { infcx: self, body_id, param_env, value_span, obligations: vec![] }; + let value = instantiator.instantiate_opaque_types_in_map(value); + InferOk { value, obligations: instantiator.obligations } + } + + /// Given the map `opaque_types` containing the opaque + /// `impl Trait` types whose underlying, hidden types are being + /// inferred, this method adds constraints to the regions + /// appearing in those underlying hidden types to ensure that they + /// at least do not refer to random scopes within the current + /// function. These constraints are not (quite) sufficient to + /// guarantee that the regions are actually legal values; that + /// final condition is imposed after region inference is done. + /// + /// # The Problem + /// + /// Let's work through an example to explain how it works. Assume + /// the current function is as follows: + /// + /// ```text + /// fn foo<'a, 'b>(..) -> (impl Bar<'a>, impl Bar<'b>) + /// ``` + /// + /// Here, we have two `impl Trait` types whose values are being + /// inferred (the `impl Bar<'a>` and the `impl + /// Bar<'b>`). Conceptually, this is sugar for a setup where we + /// define underlying opaque types (`Foo1`, `Foo2`) and then, in + /// the return type of `foo`, we *reference* those definitions: + /// + /// ```text + /// type Foo1<'x> = impl Bar<'x>; + /// type Foo2<'x> = impl Bar<'x>; + /// fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. } + /// // ^^^^ ^^ + /// // | | + /// // | substs + /// // def_id + /// ``` + /// + /// As indicating in the comments above, each of those references + /// is (in the compiler) basically a substitution (`substs`) + /// applied to the type of a suitable `def_id` (which identifies + /// `Foo1` or `Foo2`). + /// + /// Now, at this point in compilation, what we have done is to + /// replace each of the references (`Foo1<'a>`, `Foo2<'b>`) with + /// fresh inference variables C1 and C2. We wish to use the values + /// of these variables to infer the underlying types of `Foo1` and + /// `Foo2`. That is, this gives rise to higher-order (pattern) unification + /// constraints like: + /// + /// ```text + /// for<'a> (Foo1<'a> = C1) + /// for<'b> (Foo1<'b> = C2) + /// ``` + /// + /// For these equation to be satisfiable, the types `C1` and `C2` + /// can only refer to a limited set of regions. For example, `C1` + /// can only refer to `'static` and `'a`, and `C2` can only refer + /// to `'static` and `'b`. The job of this function is to impose that + /// constraint. + /// + /// Up to this point, C1 and C2 are basically just random type + /// inference variables, and hence they may contain arbitrary + /// regions. In fact, it is fairly likely that they do! Consider + /// this possible definition of `foo`: + /// + /// ```text + /// fn foo<'a, 'b>(x: &'a i32, y: &'b i32) -> (impl Bar<'a>, impl Bar<'b>) { + /// (&*x, &*y) + /// } + /// ``` + /// + /// Here, the values for the concrete types of the two impl + /// traits will include inference variables: + /// + /// ```text + /// &'0 i32 + /// &'1 i32 + /// ``` + /// + /// Ordinarily, the subtyping rules would ensure that these are + /// sufficiently large. But since `impl Bar<'a>` isn't a specific + /// type per se, we don't get such constraints by default. This + /// is where this function comes into play. It adds extra + /// constraints to ensure that all the regions which appear in the + /// inferred type are regions that could validly appear. + /// + /// This is actually a bit of a tricky constraint in general. We + /// want to say that each variable (e.g., `'0`) can only take on + /// values that were supplied as arguments to the opaque type + /// (e.g., `'a` for `Foo1<'a>`) or `'static`, which is always in + /// scope. We don't have a constraint quite of this kind in the current + /// region checker. + /// + /// # The Solution + /// + /// We generally prefer to make `<=` constraints, since they + /// integrate best into the region solver. To do that, we find the + /// "minimum" of all the arguments that appear in the substs: that + /// is, some region which is less than all the others. In the case + /// of `Foo1<'a>`, that would be `'a` (it's the only choice, after + /// all). Then we apply that as a least bound to the variables + /// (e.g., `'a <= '0`). + /// + /// In some cases, there is no minimum. Consider this example: + /// + /// ```text + /// fn baz<'a, 'b>() -> impl Trait<'a, 'b> { ... } + /// ``` + /// + /// Here we would report a more complex "in constraint", like `'r + /// in ['a, 'b, 'static]` (where `'r` is some region appearing in + /// the hidden type). + /// + /// # Constrain regions, not the hidden concrete type + /// + /// Note that generating constraints on each region `Rc` is *not* + /// the same as generating an outlives constraint on `Tc` iself. + /// For example, if we had a function like this: + /// + /// ```rust + /// fn foo<'a, T>(x: &'a u32, y: T) -> impl Foo<'a> { + /// (x, y) + /// } + /// + /// // Equivalent to: + /// type FooReturn<'a, T> = impl Foo<'a>; + /// fn foo<'a, T>(..) -> FooReturn<'a, T> { .. } + /// ``` + /// + /// then the hidden type `Tc` would be `(&'0 u32, T)` (where `'0` + /// is an inference variable). If we generated a constraint that + /// `Tc: 'a`, then this would incorrectly require that `T: 'a` -- + /// but this is not necessary, because the opaque type we + /// create will be allowed to reference `T`. So we only generate a + /// constraint that `'0: 'a`. + /// + /// # The `free_region_relations` parameter + /// + /// The `free_region_relations` argument is used to find the + /// "minimum" of the regions supplied to a given opaque type. + /// It must be a relation that can answer whether `'a <= 'b`, + /// where `'a` and `'b` are regions that appear in the "substs" + /// for the opaque type references (the `<'a>` in `Foo1<'a>`). + /// + /// Note that we do not impose the constraints based on the + /// generic regions from the `Foo1` definition (e.g., `'x`). This + /// is because the constraints we are imposing here is basically + /// the concern of the one generating the constraining type C1, + /// which is the current function. It also means that we can + /// take "implied bounds" into account in some cases: + /// + /// ```text + /// trait SomeTrait<'a, 'b> { } + /// fn foo<'a, 'b>(_: &'a &'b u32) -> impl SomeTrait<'a, 'b> { .. } + /// ``` + /// + /// Here, the fact that `'b: 'a` is known only because of the + /// implied bounds from the `&'a &'b u32` parameter, and is not + /// "inherent" to the opaque type definition. + /// + /// # Parameters + /// + /// - `opaque_types` -- the map produced by `instantiate_opaque_types` + /// - `free_region_relations` -- something that can be used to relate + /// the free regions (`'a`) that appear in the impl trait. + #[instrument(level = "debug", skip(self))] + pub fn constrain_opaque_type( + &self, + opaque_type_key: OpaqueTypeKey<'tcx>, + opaque_defn: &OpaqueTypeDecl<'tcx>, + ) { + let def_id = opaque_type_key.def_id; + + let tcx = self.tcx; + + let concrete_ty = self.resolve_vars_if_possible(opaque_defn.concrete_ty); + + debug!(?concrete_ty); + + let first_own_region = match opaque_defn.origin { + hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => { + // We lower + // + // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm> + // + // into + // + // type foo::<'p0..'pn>::Foo<'q0..'qm> + // fn foo() -> foo::<'static..'static>::Foo<'l0..'lm>. + // + // For these types we only iterate over `'l0..lm` below. + tcx.generics_of(def_id).parent_count + } + // These opaque type inherit all lifetime parameters from their + // parent, so we have to check them all. + hir::OpaqueTyOrigin::TyAlias => 0, + }; + + // For a case like `impl Foo<'a, 'b>`, we would generate a constraint + // `'r in ['a, 'b, 'static]` for each region `'r` that appears in the + // hidden type (i.e., it must be equal to `'a`, `'b`, or `'static`). + // + // `conflict1` and `conflict2` are the two region bounds that we + // detected which were unrelated. They are used for diagnostics. + + // Create the set of choice regions: each region in the hidden + // type can be equal to any of the region parameters of the + // opaque type definition. + let choice_regions: Lrc>> = Lrc::new( + opaque_type_key.substs[first_own_region..] + .iter() + .filter_map(|arg| match arg.unpack() { + GenericArgKind::Lifetime(r) => Some(r), + GenericArgKind::Type(_) | GenericArgKind::Const(_) => None, + }) + .chain(std::iter::once(self.tcx.lifetimes.re_static)) + .collect(), + ); + + concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor { + tcx: self.tcx, + op: |r| { + self.member_constraint( + opaque_type_key.def_id, + opaque_defn.definition_span, + concrete_ty, + r, + &choice_regions, + ) + }, + }); + } +} + +// Visitor that requires that (almost) all regions in the type visited outlive +// `least_region`. We cannot use `push_outlives_components` because regions in +// closure signatures are not included in their outlives components. We need to +// ensure all regions outlive the given bound so that we don't end up with, +// say, `ReVar` appearing in a return type and causing ICEs when other +// functions end up with region constraints involving regions from other +// functions. +// +// We also cannot use `for_each_free_region` because for closures it includes +// the regions parameters from the enclosing item. +// +// We ignore any type parameters because impl trait values are assumed to +// capture all the in-scope type parameters. +struct ConstrainOpaqueTypeRegionVisitor<'tcx, OP> { + tcx: TyCtxt<'tcx>, + op: OP, +} + +impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<'tcx, OP> +where + OP: FnMut(ty::Region<'tcx>), +{ + fn tcx_for_anon_const_substs(&self) -> Option> { + Some(self.tcx) + } + + fn visit_binder>( + &mut self, + t: &ty::Binder<'tcx, T>, + ) -> ControlFlow { + t.as_ref().skip_binder().visit_with(self); + ControlFlow::CONTINUE + } + + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + match *r { + // ignore bound regions, keep visiting + ty::ReLateBound(_, _) => ControlFlow::CONTINUE, + _ => { + (self.op)(r); + ControlFlow::CONTINUE + } + } + } + + fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + // We're only interested in types involving regions + if !ty.flags().intersects(ty::TypeFlags::HAS_POTENTIAL_FREE_REGIONS) { + return ControlFlow::CONTINUE; + } + + match ty.kind() { + ty::Closure(_, ref substs) => { + // Skip lifetime parameters of the enclosing item(s) + + substs.as_closure().tupled_upvars_ty().visit_with(self); + substs.as_closure().sig_as_fn_ptr_ty().visit_with(self); + } + + ty::Generator(_, ref substs, _) => { + // Skip lifetime parameters of the enclosing item(s) + // Also skip the witness type, because that has no free regions. + + substs.as_generator().tupled_upvars_ty().visit_with(self); + substs.as_generator().return_ty().visit_with(self); + substs.as_generator().yield_ty().visit_with(self); + substs.as_generator().resume_ty().visit_with(self); + } + _ => { + ty.super_visit_with(self); + } + } + + ControlFlow::CONTINUE + } +} + +struct Instantiator<'a, 'tcx> { + infcx: &'a InferCtxt<'a, 'tcx>, + body_id: hir::HirId, + param_env: ty::ParamEnv<'tcx>, + value_span: Span, + obligations: Vec>, +} + +impl<'a, 'tcx> Instantiator<'a, 'tcx> { + fn instantiate_opaque_types_in_map>(&mut self, value: T) -> T { + let tcx = self.infcx.tcx; + value.fold_with(&mut BottomUpFolder { + tcx, + ty_op: |ty| { + if ty.references_error() { + return tcx.ty_error(); + } else if let ty::Opaque(def_id, substs) = ty.kind() { + // Check that this is `impl Trait` type is + // declared by `parent_def_id` -- i.e., one whose + // value we are inferring. At present, this is + // always true during the first phase of + // type-check, but not always true later on during + // NLL. Once we support named opaque types more fully, + // this same scenario will be able to arise during all phases. + // + // Here is an example using type alias `impl Trait` + // that indicates the distinction we are checking for: + // + // ```rust + // mod a { + // pub type Foo = impl Iterator; + // pub fn make_foo() -> Foo { .. } + // } + // + // mod b { + // fn foo() -> a::Foo { a::make_foo() } + // } + // ``` + // + // Here, the return type of `foo` references an + // `Opaque` indeed, but not one whose value is + // presently being inferred. You can get into a + // similar situation with closure return types + // today: + // + // ```rust + // fn foo() -> impl Iterator { .. } + // fn bar() { + // let x = || foo(); // returns the Opaque assoc with `foo` + // } + // ``` + if let Some(def_id) = def_id.as_local() { + let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let parent_def_id = self.infcx.defining_use_anchor; + let def_scope_default = || { + let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id); + parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id) + }; + let (in_definition_scope, origin) = + match tcx.hir().expect_item(opaque_hir_id).kind { + // Anonymous `impl Trait` + hir::ItemKind::OpaqueTy(hir::OpaqueTy { + impl_trait_fn: Some(parent), + origin, + .. + }) => (parent == parent_def_id.to_def_id(), origin), + // Named `type Foo = impl Bar;` + hir::ItemKind::OpaqueTy(hir::OpaqueTy { + impl_trait_fn: None, + origin, + .. + }) => ( + may_define_opaque_type(tcx, parent_def_id, opaque_hir_id), + origin, + ), + _ => (def_scope_default(), hir::OpaqueTyOrigin::TyAlias), + }; + if in_definition_scope { + let opaque_type_key = + OpaqueTypeKey { def_id: def_id.to_def_id(), substs }; + return self.fold_opaque_ty(ty, opaque_type_key, origin); + } + + debug!( + "instantiate_opaque_types_in_map: \ + encountered opaque outside its definition scope \ + def_id={:?}", + def_id, + ); + } + } + + ty + }, + lt_op: |lt| lt, + ct_op: |ct| ct, + }) + } + + #[instrument(skip(self), level = "debug")] + fn fold_opaque_ty( + &mut self, + ty: Ty<'tcx>, + opaque_type_key: OpaqueTypeKey<'tcx>, + origin: hir::OpaqueTyOrigin, + ) -> Ty<'tcx> { + let infcx = self.infcx; + let tcx = infcx.tcx; + let OpaqueTypeKey { def_id, substs } = opaque_type_key; + + // Use the same type variable if the exact same opaque type appears more + // than once in the return type (e.g., if it's passed to a type alias). + if let Some(opaque_defn) = infcx.inner.borrow().opaque_types.get(&opaque_type_key) { + debug!("re-using cached concrete type {:?}", opaque_defn.concrete_ty.kind()); + return opaque_defn.concrete_ty; + } + + let ty_var = infcx.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::TypeInference, + span: self.value_span, + }); + + // Ideally, we'd get the span where *this specific `ty` came + // from*, but right now we just use the span from the overall + // value being folded. In simple cases like `-> impl Foo`, + // these are the same span, but not in cases like `-> (impl + // Foo, impl Bar)`. + let definition_span = self.value_span; + + { + let mut infcx = self.infcx.inner.borrow_mut(); + infcx.opaque_types.insert( + OpaqueTypeKey { def_id, substs }, + OpaqueTypeDecl { opaque_type: ty, definition_span, concrete_ty: ty_var, origin }, + ); + infcx.opaque_types_vars.insert(ty_var, ty); + } + + debug!("generated new type inference var {:?}", ty_var.kind()); + + let item_bounds = tcx.explicit_item_bounds(def_id); + + self.obligations.reserve(item_bounds.len()); + for (predicate, _) in item_bounds { + debug!(?predicate); + let predicate = predicate.subst(tcx, substs); + debug!(?predicate); + + // We can't normalize associated types from `rustc_infer`, but we can eagerly register inference variables for them. + let predicate = predicate.fold_with(&mut BottomUpFolder { + tcx, + ty_op: |ty| match ty.kind() { + ty::Projection(projection_ty) => infcx.infer_projection( + self.param_env, + *projection_ty, + traits::ObligationCause::misc(self.value_span, self.body_id), + 0, + &mut self.obligations, + ), + _ => ty, + }, + lt_op: |lt| lt, + ct_op: |ct| ct, + }); + debug!(?predicate); + + if let ty::PredicateKind::Projection(projection) = predicate.kind().skip_binder() { + if projection.ty.references_error() { + // No point on adding these obligations since there's a type error involved. + return tcx.ty_error(); + } + } + // Change the predicate to refer to the type variable, + // which will be the concrete type instead of the opaque type. + // This also instantiates nested instances of `impl Trait`. + let predicate = self.instantiate_opaque_types_in_map(predicate); + + let cause = + traits::ObligationCause::new(self.value_span, self.body_id, traits::OpaqueType); + + // Require that the predicate holds for the concrete type. + debug!(?predicate); + self.obligations.push(traits::Obligation::new(cause, self.param_env, predicate)); + } + + ty_var + } +} + +/// Returns `true` if `opaque_hir_id` is a sibling or a child of a sibling of `def_id`. +/// +/// Example: +/// ```rust +/// pub mod foo { +/// pub mod bar { +/// pub trait Bar { .. } +/// +/// pub type Baz = impl Bar; +/// +/// fn f1() -> Baz { .. } +/// } +/// +/// fn f2() -> bar::Baz { .. } +/// } +/// ``` +/// +/// Here, `def_id` is the `LocalDefId` of the defining use of the opaque type (e.g., `f1` or `f2`), +/// and `opaque_hir_id` is the `HirId` of the definition of the opaque type `Baz`. +/// For the above example, this function returns `true` for `f1` and `false` for `f2`. +fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: LocalDefId, opaque_hir_id: hir::HirId) -> bool { + let mut hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + + // Named opaque types can be defined by any siblings or children of siblings. + let scope = tcx.hir().get_defining_scope(opaque_hir_id); + // We walk up the node tree until we hit the root or the scope of the opaque type. + while hir_id != scope && hir_id != hir::CRATE_HIR_ID { + hir_id = tcx.hir().get_parent_item(hir_id); + } + // Syntactically, we are allowed to define the concrete type if: + let res = hir_id == scope; + trace!( + "may_define_opaque_type(def={:?}, opaque_node={:?}) = {}", + tcx.hir().find(hir_id), + tcx.hir().get(opaque_hir_id), + res + ); + res +} diff --git a/compiler/rustc_infer/src/infer/outlives/env.rs b/compiler/rustc_infer/src/infer/outlives/env.rs index 9e04773c5f..3947282aa6 100644 --- a/compiler/rustc_infer/src/infer/outlives/env.rs +++ b/compiler/rustc_infer/src/infer/outlives/env.rs @@ -99,7 +99,7 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> { /// function. We can then add implied bounds and the like from the /// closure arguments into the environment -- these should only /// apply in the closure body, so once we exit, we invoke - /// `pop_snapshot_post_closure` to remove them. + /// `pop_snapshot_post_typeck_child` to remove them. /// /// Example: /// @@ -129,12 +129,12 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> { /// seems like it'd be readily fixed if we wanted. There are /// similar leaks around givens that seem equally suspicious, to /// be honest. --nmatsakis - pub fn push_snapshot_pre_closure(&self) -> usize { + pub fn push_snapshot_pre_typeck_child(&self) -> usize { self.region_bound_pairs_accum.len() } - /// See `push_snapshot_pre_closure`. - pub fn pop_snapshot_post_closure(&mut self, len: usize) { + /// See `push_snapshot_pre_typeck_child`. + pub fn pop_snapshot_post_typeck_child(&mut self, len: usize) { self.region_bound_pairs_accum.truncate(len); } diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index a4cfaddeeb..e4b407e7c1 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -15,8 +15,10 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(bool_to_option)] #![feature(box_patterns)] +#![feature(derive_default_enum)] #![feature(extend_one)] #![feature(iter_zip)] +#![feature(let_else)] #![feature(never_type)] #![feature(in_band_lifetimes)] #![feature(control_flow_enum)] diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index dce4a87b04..152a395c87 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -46,30 +46,25 @@ pub trait TraitEngine<'tcx>: 'tcx { obligation: PredicateObligation<'tcx>, ); - fn select_all_or_error( - &mut self, - infcx: &InferCtxt<'_, 'tcx>, - ) -> Result<(), Vec>>; + fn select_all_or_error(&mut self, infcx: &InferCtxt<'_, 'tcx>) -> Vec>; fn select_all_with_constness_or_error( &mut self, infcx: &InferCtxt<'_, 'tcx>, _constness: hir::Constness, - ) -> Result<(), Vec>> { + ) -> Vec> { self.select_all_or_error(infcx) } - fn select_where_possible( - &mut self, - infcx: &InferCtxt<'_, 'tcx>, - ) -> Result<(), Vec>>; + fn select_where_possible(&mut self, infcx: &InferCtxt<'_, 'tcx>) + -> Vec>; // FIXME(fee1-dead) this should not provide a default body for chalk as chalk should be updated fn select_with_constness_where_possible( &mut self, infcx: &InferCtxt<'_, 'tcx>, _constness: hir::Constness, - ) -> Result<(), Vec>> { + ) -> Vec> { self.select_where_possible(infcx) } diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs index 9dbfa3a850..c1f302e665 100644 --- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs @@ -6,7 +6,6 @@ use rustc_errors::{struct_span_err, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_middle::ty::TyCtxt; -use rustc_span::symbol::Symbol; use rustc_span::{MultiSpan, Span}; use std::fmt; use std::iter; @@ -15,8 +14,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn report_extra_impl_obligation( &self, error_span: Span, - item_name: Symbol, - _impl_item_def_id: DefId, + impl_item_def_id: DefId, trait_item_def_id: DefId, requirement: &dyn fmt::Display, ) -> DiagnosticBuilder<'tcx> { @@ -27,6 +25,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { if let Some(trait_item_span) = self.tcx.hir().span_if_local(trait_item_def_id) { let span = self.tcx.sess.source_map().guess_head_span(trait_item_span); + let item_name = self.tcx.item_name(impl_item_def_id); err.span_label(span, format!("definition of `{}` from trait", item_name)); } diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index e1d6982f16..e8622b3c81 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -10,7 +10,7 @@ pub mod util; use rustc_hir as hir; use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::{self, Const, Ty}; +use rustc_middle::ty::{self, Const, Ty, TyCtxt}; use rustc_span::Span; pub use self::FulfillmentErrorCode::*; @@ -55,6 +55,20 @@ pub struct Obligation<'tcx, T> { pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>; pub type TraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>; +impl PredicateObligation<'tcx> { + /// Flips the polarity of the inner predicate. + /// + /// Given `T: Trait` predicate it returns `T: !Trait` and given `T: !Trait` returns `T: Trait`. + pub fn flip_polarity(&self, tcx: TyCtxt<'tcx>) -> Option> { + Some(PredicateObligation { + cause: self.cause.clone(), + param_env: self.param_env, + predicate: self.predicate.flip_polarity(tcx)?, + recursion_depth: self.recursion_depth, + }) + } +} + // `PredicateObligation` 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!(PredicateObligation<'_>, 32); @@ -129,6 +143,10 @@ impl<'tcx> FulfillmentError<'tcx> { } impl<'tcx> TraitObligation<'tcx> { + pub fn polarity(&self) -> ty::ImplPolarity { + self.predicate.skip_binder().polarity + } + 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/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs index c4a2ecee09..b48ca3bd0c 100644 --- a/compiler/rustc_infer/src/traits/structural_impls.rs +++ b/compiler/rustc_infer/src/traits/structural_impls.rs @@ -70,6 +70,7 @@ impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { - self.predicate.visit_with(visitor) + self.predicate.visit_with(visitor)?; + self.param_env.visit_with(visitor) } } diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index c839f824d1..92f74af4eb 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -5,6 +5,7 @@ use crate::traits::{Obligation, ObligationCause, PredicateObligation}; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_middle::ty::{self, ToPredicate, TyCtxt, WithConstness}; use rustc_span::symbol::Ident; +use rustc_span::Span; pub fn anonymize_predicate<'tcx>( tcx: TyCtxt<'tcx>, @@ -97,6 +98,22 @@ pub fn elaborate_predicates<'tcx>( elaborate_obligations(tcx, obligations) } +pub fn elaborate_predicates_with_span<'tcx>( + tcx: TyCtxt<'tcx>, + predicates: impl Iterator, Span)>, +) -> Elaborator<'tcx> { + let obligations = predicates + .map(|(predicate, span)| { + predicate_obligation( + predicate, + ty::ParamEnv::empty(), + ObligationCause::dummy_with_span(span), + ) + }) + .collect(); + elaborate_obligations(tcx, obligations) +} + pub fn elaborate_obligations<'tcx>( tcx: TyCtxt<'tcx>, mut obligations: Vec>, diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 0861bd290d..2904b3f5b7 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -36,9 +36,10 @@ pub struct Compiler { pub(crate) input_path: Option, pub(crate) output_dir: Option, pub(crate) output_file: Option, + pub(crate) temps_dir: Option, pub(crate) register_lints: Option>, pub(crate) override_queries: - Option, + Option, } impl Compiler { @@ -57,6 +58,9 @@ impl Compiler { pub fn output_file(&self) -> &Option { &self.output_file } + pub fn temps_dir(&self) -> &Option { + &self.temps_dir + } pub fn register_lints(&self) -> &Option> { &self.register_lints } @@ -65,7 +69,14 @@ impl Compiler { sess: &Session, attrs: &[ast::Attribute], ) -> OutputFilenames { - util::build_output_filenames(&self.input, &self.output_dir, &self.output_file, attrs, sess) + util::build_output_filenames( + &self.input, + &self.output_dir, + &self.output_file, + &self.temps_dir, + attrs, + sess, + ) } } @@ -75,7 +86,10 @@ pub fn parse_cfgspecs(cfgspecs: Vec) -> FxHashSet<(String, Option, + Option, /// This is a callback from the driver that is called to create a codegen backend. pub make_codegen_backend: @@ -183,6 +197,8 @@ pub fn create_compiler_and_run(config: Config, f: impl FnOnce(&Compiler) -> R ); } + let temps_dir = sess.opts.debugging_opts.temps_dir.as_ref().map(|o| PathBuf::from(&o)); + let compiler = Compiler { sess, codegen_backend, @@ -190,6 +206,7 @@ pub fn create_compiler_and_run(config: Config, f: impl FnOnce(&Compiler) -> R input_path: config.input_path, output_dir: config.output_dir, output_file: config.output_file, + temps_dir, register_lints: config.register_lints, override_queries: config.override_queries, }; diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index bcfa0ef352..d3917dfb14 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -19,7 +19,7 @@ use rustc_metadata::creader::CStore; use rustc_metadata::{encode_metadata, EncodedMetadata}; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepGraph; -use rustc_middle::ty::query::Providers; +use rustc_middle::ty::query::{ExternProviders, Providers}; use rustc_middle::ty::{self, GlobalCtxt, ResolverOutputs, TyCtxt}; use rustc_mir_build as mir_build; use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str, validate_attr}; @@ -35,7 +35,7 @@ use rustc_session::output::{filename_for_input, filename_for_metadata}; use rustc_session::search_paths::PathKind; use rustc_session::{Limit, Session}; use rustc_span::symbol::{sym, Ident, Symbol}; -use rustc_span::FileName; +use rustc_span::{FileName, MultiSpan}; use rustc_trait_selection::traits; use rustc_typeck as typeck; use tempfile::Builder as TempFileBuilder; @@ -47,7 +47,7 @@ use std::ffi::OsString; use std::io::{self, BufWriter, Write}; use std::lazy::SyncLazy; use std::marker::PhantomPinned; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::pin::Pin; use std::rc::Rc; use std::{env, fs, iter}; @@ -450,6 +450,19 @@ pub fn configure_and_expand( }); } + // Gate identifiers containing invalid Unicode codepoints that were recovered during lexing. + sess.parse_sess.bad_unicode_identifiers.with_lock(|identifiers| { + let mut identifiers: Vec<_> = identifiers.drain().collect(); + identifiers.sort_by_key(|&(key, _)| key); + for (ident, mut spans) in identifiers.into_iter() { + spans.sort(); + sess.diagnostic().span_err( + MultiSpan::from(spans), + &format!("identifiers cannot contain emoji: `{}`", ident), + ); + } + }); + Ok(krate) } @@ -536,7 +549,7 @@ where None } -fn output_contains_path(output_paths: &[PathBuf], input_path: &PathBuf) -> bool { +fn output_contains_path(output_paths: &[PathBuf], input_path: &Path) -> bool { let input_path = input_path.canonicalize().ok(); if input_path.is_none() { return false; @@ -552,7 +565,7 @@ fn output_conflicts_with_dir(output_paths: &[PathBuf]) -> Option { check_output(output_paths, check) } -fn escape_dep_filename(filename: &String) -> String { +fn escape_dep_filename(filename: &str) -> String { // Apparently clang and gcc *only* escape spaces: // https://llvm.org/klaus/clang/commit/9d50634cfc268ecc9a7250226dd5ca0e945240d4 filename.replace(" ", "\\ ") @@ -692,6 +705,7 @@ pub fn prepare_outputs( &compiler.input, &compiler.output_dir, &compiler.output_file, + &compiler.temps_dir, &krate.attrs, sess, ); @@ -722,6 +736,13 @@ pub fn prepare_outputs( } } + if let Some(ref dir) = compiler.temps_dir { + if fs::create_dir_all(dir).is_err() { + sess.err("failed to find or create the directory specified by `--temps-dir`"); + return Err(ErrorReported); + } + } + write_out_deps(sess, boxed_resolver, &outputs, &output_paths); let only_dep_info = sess.opts.output_types.contains_key(&OutputType::DepInfo) @@ -764,8 +785,8 @@ pub static DEFAULT_QUERY_PROVIDERS: SyncLazy = SyncLazy::new(|| { *providers }); -pub static DEFAULT_EXTERN_QUERY_PROVIDERS: SyncLazy = SyncLazy::new(|| { - let mut extern_providers = *DEFAULT_QUERY_PROVIDERS; +pub static DEFAULT_EXTERN_QUERY_PROVIDERS: SyncLazy = SyncLazy::new(|| { + let mut extern_providers = ExternProviders::default(); rustc_metadata::provide_extern(&mut extern_providers); rustc_codegen_ssa::provide_extern(&mut extern_providers); extern_providers @@ -816,7 +837,6 @@ pub fn create_global_ctxt<'tcx>( codegen_backend.provide(&mut local_providers); let mut extern_providers = *DEFAULT_EXTERN_QUERY_PROVIDERS; - codegen_backend.provide(&mut extern_providers); codegen_backend.provide_extern(&mut extern_providers); if let Some(callback) = compiler.override_queries { @@ -838,6 +858,7 @@ pub fn create_global_ctxt<'tcx>( dep_graph, queries.on_disk_cache.as_ref().map(OnDiskCache::as_dyn), queries.as_dyn(), + rustc_query_impl::query_callbacks(arena), crate_name, outputs, ) diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 844e5ab56a..6147311af6 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -5,7 +5,9 @@ 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::{ + rustc_optgroups, ErrorOutputType, ExternLocation, LocationDetail, Options, Passes, +}; use rustc_session::config::{CFGuard, ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath}; use rustc_session::config::{ Externs, OutputType, OutputTypes, SymbolManglingVersion, WasiExecModel, @@ -18,7 +20,9 @@ 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, SanitizerSet, SplitDebuginfo, TlsModel}; +use rustc_target::spec::{ + RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel, +}; use std::collections::{BTreeMap, BTreeSet}; use std::iter::FromIterator; @@ -549,6 +553,7 @@ fn test_codegen_options_tracking_hash() { untracked!(remark, Passes::Some(vec![String::from("pass1"), String::from("pass2")])); untracked!(rpath, true); untracked!(save_temps, true); + untracked!(strip, Strip::Debuginfo); macro_rules! tracked { ($name: ident, $non_default_value: expr) => { @@ -633,6 +638,7 @@ fn test_debugging_options_tracking_hash() { // Make sure that changing an [UNTRACKED] option leaves the hash unchanged. // This list is in alphabetical order. + untracked!(assert_incr_state, Some(String::from("loaded"))); untracked!(ast_json, true); untracked!(ast_json_noexpand, true); untracked!(borrowck, String::from("other")); @@ -682,7 +688,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::Debuginfo); + untracked!(temps_dir, Some(String::from("abc"))); untracked!(terminal_width, Some(80)); untracked!(threads, 99); untracked!(time, true); @@ -709,8 +715,8 @@ fn test_debugging_options_tracking_hash() { // This list is in alphabetical order. tracked!(allow_features, Some(vec![String::from("lang_items")])); tracked!(always_encode_mir, true); - tracked!(assume_incomplete_release, true); tracked!(asm_comments, true); + tracked!(assume_incomplete_release, true); tracked!(binary_dep_depinfo, true); tracked!(chalk, true); tracked!(codegen_backend, Some("abc".to_string())); @@ -720,19 +726,19 @@ fn test_debugging_options_tracking_hash() { tracked!(dep_info_omit_d_target, true); tracked!(dual_proc_macros, true); tracked!(fewer_names, Some(true)); - tracked!(force_overflow_checks, Some(true)); tracked!(force_unstable_if_unmarked, true); tracked!(fuel, Some(("abc".to_string(), 99))); tracked!(function_sections, Some(false)); tracked!(human_readable_cgu_names, true); tracked!(inline_in_all_cgus, Some(true)); tracked!(inline_mir, Some(true)); - tracked!(inline_mir_threshold, Some(123)); tracked!(inline_mir_hint_threshold, Some(123)); + tracked!(inline_mir_threshold, Some(123)); tracked!(instrument_coverage, Some(InstrumentCoverage::All)); tracked!(instrument_mcount, true); tracked!(link_only, true); tracked!(llvm_plugins, vec![String::from("plugin_name")]); + tracked!(location_detail, LocationDetail { file: true, line: false, column: false }); tracked!(merge_functions, Some(MergeFunctions::Disabled)); tracked!(mir_emit_retag, true); tracked!(mir_opt_level, Some(4)); @@ -741,11 +747,13 @@ fn test_debugging_options_tracking_hash() { tracked!(new_llvm_pass_manager, Some(true)); tracked!(no_generate_arange_section, true); tracked!(no_link, true); + tracked!(no_unique_section_names, true); tracked!(no_profiler_runtime, true); tracked!(osx_rpath_install_name, true); tracked!(panic_abort_tests, true); tracked!(panic_in_drop, PanicStrategy::Abort); tracked!(partially_uninit_const_threshold, Some(123)); + tracked!(pick_stable_methods_before_any_unstable, false); tracked!(plt, Some(true)); tracked!(polonius, true); tracked!(precise_enum_drop_elaboration, false); @@ -757,7 +765,6 @@ fn test_debugging_options_tracking_hash() { tracked!(relax_elf_relocations, Some(true)); tracked!(relro_level, Some(RelroLevel::Full)); tracked!(remap_cwd_prefix, Some(PathBuf::from("abc"))); - tracked!(simulate_remapped_rust_src_base, Some(PathBuf::from("/rustc/abc"))); tracked!(report_delayed_bugs, true); tracked!(sanitizer, SanitizerSet::ADDRESS); tracked!(sanitizer_memory_track_origins, 2); @@ -765,15 +772,17 @@ fn test_debugging_options_tracking_hash() { tracked!(saturating_float_casts, Some(true)); tracked!(share_generics, Some(true)); tracked!(show_span, Some(String::from("abc"))); + tracked!(simulate_remapped_rust_src_base, Some(PathBuf::from("/rustc/abc"))); tracked!(src_hash_algorithm, Some(SourceFileHashAlgorithm::Sha1)); + tracked!(stack_protector, StackProtector::All); tracked!(symbol_mangling_version, Some(SymbolManglingVersion::V0)); tracked!(teach, true); tracked!(thinlto, Some(true)); tracked!(thir_unsafeck, true); - tracked!(tune_cpu, Some(String::from("abc"))); tracked!(tls_model, Some(TlsModel::GeneralDynamic)); tracked!(trap_unreachable, Some(false)); tracked!(treat_err_as_bug, NonZeroUsize::new(1)); + tracked!(tune_cpu, Some(String::from("abc"))); tracked!(unleash_the_miri_inside_of_you, true); tracked!(use_ctors_section, Some(true)); tracked!(verify_llvm_ir, true); diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index cffb087af1..04e183a9ba 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -604,6 +604,7 @@ pub fn build_output_filenames( input: &Input, odir: &Option, ofile: &Option, + temps_dir: &Option, attrs: &[ast::Attribute], sess: &Session, ) -> OutputFilenames { @@ -626,6 +627,7 @@ pub fn build_output_filenames( dirpath, stem, None, + temps_dir.clone(), sess.opts.cg.extra_filename.clone(), sess.opts.output_types.clone(), ) @@ -654,6 +656,7 @@ pub fn build_output_filenames( out_file.parent().unwrap_or_else(|| Path::new("")).to_path_buf(), out_file.file_stem().unwrap_or_default().to_str().unwrap().to_string(), ofile, + temps_dir.clone(), sess.opts.cg.extra_filename.clone(), sess.opts.output_types.clone(), ) @@ -776,7 +779,7 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> { fn visit_item_kind(&mut self, i: &mut ast::ItemKind) { let is_const = match i { ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => true, - ast::ItemKind::Fn(box ast::FnKind(_, ref sig, _, _)) => Self::is_sig_const(sig), + ast::ItemKind::Fn(box ast::Fn { ref sig, .. }) => Self::is_sig_const(sig), _ => false, }; self.run(is_const, |s| noop_visit_item_kind(i, s)) @@ -785,7 +788,7 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> { fn flat_map_trait_item(&mut self, i: P) -> SmallVec<[P; 1]> { let is_const = match i.kind { ast::AssocItemKind::Const(..) => true, - ast::AssocItemKind::Fn(box ast::FnKind(_, ref sig, _, _)) => Self::is_sig_const(sig), + ast::AssocItemKind::Fn(box ast::Fn { ref sig, .. }) => Self::is_sig_const(sig), _ => false, }; self.run(is_const, |s| noop_flat_map_assoc_item(i, s)) diff --git a/compiler/rustc_lexer/Cargo.toml b/compiler/rustc_lexer/Cargo.toml index 60c146f457..35af110537 100644 --- a/compiler/rustc_lexer/Cargo.toml +++ b/compiler/rustc_lexer/Cargo.toml @@ -17,6 +17,7 @@ doctest = false # Note that this crate purposefully does not depend on other rustc crates [dependencies] unicode-xid = "0.2.0" +unic-emoji-char = "0.9.0" [dev-dependencies] expect-test = "1.0" diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index b64a891cb2..44b002fa93 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -64,6 +64,8 @@ pub enum TokenKind { /// "ident" or "continue" /// At this step keywords are also considered identifiers. Ident, + /// Like the above, but containing invalid unicode codepoints. + InvalidIdent, /// "r#ident" RawIdent, /// An unknown prefix like `foo#`, `foo'`, `foo"`. Note that only the @@ -411,6 +413,10 @@ impl Cursor<'_> { let kind = Str { terminated }; Literal { kind, suffix_start } } + // Identifier starting with an emoji. Only lexed for graceful error recovery. + c if !c.is_ascii() && unic_emoji_char::is_emoji(c) => { + self.fake_ident_or_unknown_prefix() + } _ => Unknown, }; Token::new(token_kind, self.len_consumed()) @@ -492,10 +498,28 @@ impl Cursor<'_> { // we see a prefix here, it is definitely an unknown prefix. match self.first() { '#' | '"' | '\'' => UnknownPrefix, + c if !c.is_ascii() && unic_emoji_char::is_emoji(c) => { + self.fake_ident_or_unknown_prefix() + } _ => Ident, } } + fn fake_ident_or_unknown_prefix(&mut self) -> TokenKind { + // Start is already eaten, eat the rest of identifier. + self.eat_while(|c| { + unicode_xid::UnicodeXID::is_xid_continue(c) + || (!c.is_ascii() && unic_emoji_char::is_emoji(c)) + || c == '\u{200d}' + }); + // Known prefixes must have been handled earlier. So if + // we see a prefix here, it is definitely an unknown prefix. + match self.first() { + '#' | '"' | '\'' => UnknownPrefix, + _ => InvalidIdent, + } + } + fn number(&mut self, first_digit: char) -> LiteralKind { debug_assert!('0' <= self.prev() && self.prev() <= '9'); let mut base = Base::Decimal; diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs index 804dc657f2..d789237e69 100644 --- a/compiler/rustc_lexer/src/unescape.rs +++ b/compiler/rustc_lexer/src/unescape.rs @@ -329,7 +329,7 @@ where callback(start..end, Err(EscapeError::MultipleSkippedLinesWarning)); } let tail = &tail[first_non_space..]; - if let Some(c) = tail.chars().next() { + if let Some(c) = tail.chars().nth(0) { // For error reporting, we would like the span to contain the character that was not // skipped. The +1 is necessary to account for the leading \ that started the escape. let end = start + first_non_space + c.len_utf8() + 1; diff --git a/compiler/rustc_lint/src/array_into_iter.rs b/compiler/rustc_lint/src/array_into_iter.rs index d147148ac7..d8883b0e66 100644 --- a/compiler/rustc_lint/src/array_into_iter.rs +++ b/compiler/rustc_lint/src/array_into_iter.rs @@ -134,9 +134,8 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter { Applicability::MachineApplicable, ); if self.for_expr_span == expr.span { - let expr_span = expr.span.ctxt().outer_expn_data().call_site; diag.span_suggestion( - receiver_arg.span.shrink_to_hi().to(expr_span.shrink_to_hi()), + receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()), "or remove `.into_iter()` to iterate by value", String::new(), Applicability::MaybeIncorrect, diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 57c1c8f3ec..f2e4e70a19 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -32,8 +32,7 @@ use rustc_ast_pretty::pprust::{self, expr_to_string}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString}; -use rustc_feature::{deprecated_attributes, AttributeGate, AttributeTemplate, AttributeType}; -use rustc_feature::{GateIssue, Stability}; +use rustc_feature::{deprecated_attributes, AttributeGate, BuiltinAttribute, GateIssue, Stability}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID}; @@ -369,12 +368,12 @@ impl EarlyLintPass for UnsafeCode { fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) { match it.kind { - ast::ItemKind::Trait(box ast::TraitKind(_, ast::Unsafe::Yes(_), ..)) => self + ast::ItemKind::Trait(box ast::Trait { unsafety: ast::Unsafe::Yes(_), .. }) => self .report_unsafe(cx, it.span, |lint| { lint.build("declaration of an `unsafe` trait").emit() }), - ast::ItemKind::Impl(box ast::ImplKind { unsafety: ast::Unsafe::Yes(_), .. }) => self + ast::ItemKind::Impl(box ast::Impl { unsafety: ast::Unsafe::Yes(_), .. }) => self .report_unsafe(cx, it.span, |lint| { lint.build("implementation of an `unsafe` trait").emit() }), @@ -657,6 +656,24 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { return; } + // If the method is an impl for an item with docs_hidden, don't doc. + if method_context(cx, impl_item.hir_id()) == MethodLateContext::PlainImpl { + let parent = cx.tcx.hir().get_parent_did(impl_item.hir_id()); + let impl_ty = cx.tcx.type_of(parent); + let outerdef = match impl_ty.kind() { + ty::Adt(def, _) => Some(def.did), + ty::Foreign(def_id) => Some(*def_id), + _ => None, + }; + let is_hidden = match outerdef { + Some(id) => cx.tcx.is_doc_hidden(id), + None => false, + }; + if is_hidden { + return; + } + } + let (article, desc) = cx.tcx.article_and_description(impl_item.def_id.to_def_id()); self.check_missing_docs_attrs(cx, impl_item.def_id, impl_item.span, article, desc); } @@ -903,7 +920,7 @@ impl EarlyLintPass for AnonymousParameters { // This is a hard error in future editions; avoid linting and erroring return; } - if let ast::AssocItemKind::Fn(box FnKind(_, ref sig, _, _)) = it.kind { + if let ast::AssocItemKind::Fn(box Fn { ref sig, .. }) = it.kind { for arg in sig.decl.inputs.iter() { if let ast::PatKind::Ident(_, ident, None) = arg.pat.kind { if ident.name == kw::Empty { @@ -941,7 +958,7 @@ impl EarlyLintPass for AnonymousParameters { pub struct DeprecatedAttr { // This is not free to compute, so we want to keep it around, rather than // compute it for every attribute. - depr_attrs: Vec<&'static (Symbol, AttributeType, AttributeTemplate, AttributeGate)>, + depr_attrs: Vec<&'static BuiltinAttribute>, } impl_lint_pass!(DeprecatedAttr => []); @@ -972,14 +989,14 @@ fn lint_deprecated_attr( impl EarlyLintPass for DeprecatedAttr { fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) { - for &&(n, _, _, ref g) in &self.depr_attrs { - if attr.ident().map(|ident| ident.name) == Some(n) { + for BuiltinAttribute { name, gate, .. } in &self.depr_attrs { + if attr.ident().map(|ident| ident.name) == Some(*name) { if let &AttributeGate::Gated( Stability::Deprecated(link, suggestion), name, reason, _, - ) = g + ) = gate { let msg = format!("use of deprecated attribute `{}`: {}. See {}", name, reason, link); @@ -3112,18 +3129,13 @@ impl<'tcx> LateLintPass<'tcx> for DerefNullPtr { 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(); - }); - } + if let rustc_hir::ExprKind::Unary(rustc_hir::UnOp::Deref, expr_deref) = expr.kind { + 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(); + }); } } } @@ -3178,7 +3190,7 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels { let snippet = template_snippet.as_str(); if let Some(pos) = snippet.find(needle) { let end = pos - + &snippet[pos..] + + snippet[pos..] .find(|c| c == ':') .unwrap_or(snippet[pos..].len() - 1); let inner = InnerSpan::new(pos, end); diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 6fd0a5b95f..4c936dec6f 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -16,9 +16,9 @@ use self::TargetLint::*; -use crate::hidden_unicode_codepoints::UNICODE_TEXT_FLOW_CHARS; use crate::levels::{is_known_lint_tool, LintLevelsBuilder}; use crate::passes::{EarlyLintPassObject, LateLintPassObject}; +use ast::util::unicode::TEXT_FLOW_CONTROL_CHARS; use rustc_ast as ast; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync; @@ -602,7 +602,7 @@ pub trait LintContext: Sized { let spans: Vec<_> = content .char_indices() .filter_map(|(i, c)| { - UNICODE_TEXT_FLOW_CHARS.contains(&c).then(|| { + TEXT_FLOW_CONTROL_CHARS.contains(&c).then(|| { let lo = span.lo() + BytePos(2 + i as u32); (c, span.with_lo(lo).with_hi(lo + BytePos(c.len_utf8() as u32))) }) diff --git a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs index 1bcdcb806f..fde84be9a7 100644 --- a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs +++ b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs @@ -1,4 +1,5 @@ use crate::{EarlyContext, EarlyLintPass, LintContext}; +use ast::util::unicode::{contains_text_flow_control_chars, TEXT_FLOW_CONTROL_CHARS}; use rustc_ast as ast; use rustc_errors::{Applicability, SuggestionStyle}; use rustc_span::{BytePos, Span, Symbol}; @@ -37,11 +38,6 @@ declare_lint! { declare_lint_pass!(HiddenUnicodeCodepoints => [TEXT_DIRECTION_CODEPOINT_IN_LITERAL]); -crate const UNICODE_TEXT_FLOW_CHARS: &[char] = &[ - '\u{202A}', '\u{202B}', '\u{202D}', '\u{202E}', '\u{2066}', '\u{2067}', '\u{2068}', '\u{202C}', - '\u{2069}', -]; - impl HiddenUnicodeCodepoints { fn lint_text_direction_codepoint( &self, @@ -57,7 +53,7 @@ impl HiddenUnicodeCodepoints { .as_str() .char_indices() .filter_map(|(i, c)| { - UNICODE_TEXT_FLOW_CHARS.contains(&c).then(|| { + TEXT_FLOW_CONTROL_CHARS.contains(&c).then(|| { let lo = span.lo() + BytePos(i as u32 + padding); (c, span.with_lo(lo).with_hi(lo + BytePos(c.len_utf8() as u32))) }) @@ -131,7 +127,7 @@ impl HiddenUnicodeCodepoints { impl EarlyLintPass for HiddenUnicodeCodepoints { fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) { if let ast::AttrKind::DocComment(_, comment) = attr.kind { - if comment.as_str().contains(UNICODE_TEXT_FLOW_CHARS) { + if contains_text_flow_control_chars(&comment.as_str()) { self.lint_text_direction_codepoint(cx, comment, attr.span, 0, false, "doc comment"); } } @@ -142,7 +138,7 @@ impl EarlyLintPass for HiddenUnicodeCodepoints { let (text, span, padding) = match &expr.kind { ast::ExprKind::Lit(ast::Lit { token, kind, span }) => { let text = token.symbol; - if !text.as_str().contains(UNICODE_TEXT_FLOW_CHARS) { + if !contains_text_flow_control_chars(&text.as_str()) { return; } let padding = match kind { diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 50a0d211a3..c64a67b6b9 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -101,33 +101,31 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind { fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx Ty<'tcx>) { match &ty.kind { - TyKind::Path(qpath) => { - if let QPath::Resolved(_, path) = qpath { - if let Some(last) = path.segments.iter().last() { - if lint_ty_kind_usage(cx, last) { - cx.struct_span_lint(USAGE_OF_TY_TYKIND, path.span, |lint| { - lint.build("usage of `ty::TyKind`") - .help("try using `Ty` instead") - .emit(); - }) - } else { - if ty.span.from_expansion() { - return; - } - if let Some(t) = is_ty_or_ty_ctxt(cx, ty) { - if path.segments.len() > 1 { - cx.struct_span_lint(USAGE_OF_QUALIFIED_TY, path.span, |lint| { - lint.build(&format!("usage of qualified `ty::{}`", t)) - .span_suggestion( - path.span, - "try using it unqualified", - t, - // The import probably needs to be changed - Applicability::MaybeIncorrect, - ) - .emit(); - }) - } + TyKind::Path(QPath::Resolved(_, path)) => { + if let Some(last) = path.segments.iter().last() { + if lint_ty_kind_usage(cx, last) { + cx.struct_span_lint(USAGE_OF_TY_TYKIND, path.span, |lint| { + lint.build("usage of `ty::TyKind`") + .help("try using `Ty` instead") + .emit(); + }) + } else { + if ty.span.from_expansion() { + return; + } + if let Some(t) = is_ty_or_ty_ctxt(cx, ty) { + if path.segments.len() > 1 { + cx.struct_span_lint(USAGE_OF_QUALIFIED_TY, path.span, |lint| { + lint.build(&format!("usage of qualified `ty::{}`", t)) + .span_suggestion( + path.span, + "try using it unqualified", + t, + // The import probably needs to be changed + Applicability::MaybeIncorrect, + ) + .emit(); + }) } } } @@ -169,37 +167,30 @@ fn lint_ty_kind_usage(cx: &LateContext<'_>, segment: &PathSegment<'_>) -> bool { } fn is_ty_or_ty_ctxt(cx: &LateContext<'_>, ty: &Ty<'_>) -> Option { - if let TyKind::Path(qpath) = &ty.kind { - if let QPath::Resolved(_, path) = qpath { - match path.res { - Res::Def(_, def_id) => { - if let Some(name @ (sym::Ty | sym::TyCtxt)) = cx.tcx.get_diagnostic_name(def_id) - { - return Some(format!( - "{}{}", - name, - gen_args(path.segments.last().unwrap()) - )); - } + if let TyKind::Path(QPath::Resolved(_, path)) = &ty.kind { + match path.res { + Res::Def(_, def_id) => { + if let Some(name @ (sym::Ty | sym::TyCtxt)) = cx.tcx.get_diagnostic_name(def_id) { + return Some(format!("{}{}", name, gen_args(path.segments.last().unwrap()))); } - // Only lint on `&Ty` and `&TyCtxt` if it is used outside of a trait. - Res::SelfTy(None, Some((did, _))) => { - if let ty::Adt(adt, substs) = cx.tcx.type_of(did).kind() { - if let Some(name @ (sym::Ty | sym::TyCtxt)) = - cx.tcx.get_diagnostic_name(adt.did) - { - // NOTE: This path is currently unreachable as `Ty<'tcx>` is - // defined as a type alias meaning that `impl<'tcx> Ty<'tcx>` - // is not actually allowed. - // - // I(@lcnr) still kept this branch in so we don't miss this - // if we ever change it in the future. - return Some(format!("{}<{}>", name, substs[0])); - } + } + // Only lint on `&Ty` and `&TyCtxt` if it is used outside of a trait. + Res::SelfTy(None, Some((did, _))) => { + if let ty::Adt(adt, substs) = cx.tcx.type_of(did).kind() { + if let Some(name @ (sym::Ty | sym::TyCtxt)) = + cx.tcx.get_diagnostic_name(adt.did) + { + // NOTE: This path is currently unreachable as `Ty<'tcx>` is + // defined as a type alias meaning that `impl<'tcx> Ty<'tcx>` + // is not actually allowed. + // + // I(@lcnr) still kept this branch in so we don't miss this + // if we ever change it in the future. + return Some(format!("{}<{}>", name, substs[0])); } } - _ => (), } + _ => (), } } @@ -238,8 +229,7 @@ declare_lint_pass!(LintPassImpl => [LINT_PASS_IMPL_WITHOUT_MACRO]); impl EarlyLintPass for LintPassImpl { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) { - if let ast::ItemKind::Impl(box ast::ImplKind { of_trait: Some(lint_pass), .. }) = &item.kind - { + if let ast::ItemKind::Impl(box ast::Impl { of_trait: Some(lint_pass), .. }) = &item.kind { if let Some(last) = lint_pass.path.segments.last() { if last.ident.name == sym::LintPass { let expn_data = lint_pass.path.span.ctxt().outer_expn_data(); diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index f6514ddca9..507b4421fa 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -30,7 +30,7 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(crate_visibility_modifier)] -#![feature(format_args_capture)] +#![cfg_attr(bootstrap, feature(format_args_capture))] #![feature(iter_order_by)] #![feature(iter_zip)] #![feature(never_type)] diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 48b955e41a..da1edcf6fe 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -670,7 +670,7 @@ declare_lint! { /// /// ### Explanation /// - /// The parenthesis are not needed, and should be removed. This is the + /// The parentheses are not needed, and should be removed. This is the /// preferred style for writing these expressions. pub(super) UNUSED_PARENS, Warn, diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 8f4f54d026..c1a53c34b7 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -1959,7 +1959,7 @@ declare_lint! { /// [issue #50504]: https://github.com/rust-lang/rust/issues/50504 /// [future-incompatible]: ../index.md#future-incompatible-lints pub PROC_MACRO_DERIVE_RESOLUTION_FALLBACK, - Warn, + Deny, "detects proc macro derives using inaccessible names from parent modules", @future_incompatible = FutureIncompatibleInfo { reference: "issue #83583 ", @@ -3256,7 +3256,7 @@ declare_lint! { /// [issue #83125]: https://github.com/rust-lang/rust/issues/83125 /// [future-incompatible]: ../index.md#future-incompatible-lints pub PROC_MACRO_BACK_COMPAT, - Warn, + Deny, "detects usage of old versions of certain proc-macro crates", @future_incompatible = FutureIncompatibleInfo { reference: "issue #83125 ", diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs index 36a6d2cc33..943ce589c4 100644 --- a/compiler/rustc_llvm/build.rs +++ b/compiler/rustc_llvm/build.rs @@ -288,7 +288,7 @@ fn main() { let path = PathBuf::from(s); println!("cargo:rustc-link-search=native={}", path.parent().unwrap().display()); if target.contains("windows") { - println!("cargo:rustc-link-lib=static-nobundle={}", stdcppname); + println!("cargo:rustc-link-lib=static:-bundle={}", stdcppname); } else { println!("cargo:rustc-link-lib=static={}", stdcppname); } @@ -302,6 +302,6 @@ fn main() { // Libstdc++ depends on pthread which Rust doesn't link on MinGW // since nothing else requires it. if target.contains("windows-gnu") { - println!("cargo:rustc-link-lib=static-nobundle=pthread"); + println!("cargo:rustc-link-lib=static:-bundle=pthread"); } } diff --git a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp index 35cca04b20..8cd2bd1245 100644 --- a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp @@ -98,10 +98,7 @@ extern "C" void LLVMRustCoverageWriteMapSectionNameToString(LLVMModuleRef M, extern "C" void LLVMRustCoverageWriteFuncSectionNameToString(LLVMModuleRef M, RustStringRef Str) { -#if LLVM_VERSION_GE(11, 0) WriteSectionNameToString(M, IPSK_covfun, Str); -// else do nothing; the `Version` check will abort codegen on the Rust side -#endif } extern "C" void LLVMRustCoverageWriteMappingVarNameToString(RustStringRef Str) { @@ -111,9 +108,5 @@ extern "C" void LLVMRustCoverageWriteMappingVarNameToString(RustStringRef Str) { } extern "C" uint32_t LLVMRustCoverageMappingVersion() { -#if LLVM_VERSION_GE(11, 0) return coverage::CovMapVersion::Version4; -#else - return coverage::CovMapVersion::Version3; -#endif } diff --git a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h index 0b1b68d83b..e2ce7da0e8 100644 --- a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h +++ b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h @@ -18,7 +18,6 @@ #include "llvm/Support/Host.h" #include "llvm/Support/Memory.h" #include "llvm/Support/SourceMgr.h" -#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" @@ -80,6 +79,9 @@ enum LLVMRustAttribute { InaccessibleMemOnly = 27, SanitizeHWAddress = 28, WillReturn = 29, + StackProtectReq = 30, + StackProtectStrong = 31, + StackProtect = 32, }; typedef struct OpaqueRustString *RustStringRef; diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 87f423fb2d..4f77db8a24 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -21,6 +21,11 @@ #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Host.h" +#if LLVM_VERSION_LT(14, 0) +#include "llvm/Support/TargetRegistry.h" +#else +#include "llvm/MC/TargetRegistry.h" +#endif #include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/IPO/PassManagerBuilder.h" #include "llvm/Transforms/IPO/AlwaysInliner.h" @@ -49,10 +54,6 @@ typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef; DEFINE_STDCXX_CONVERSION_FUNCTIONS(Pass, LLVMPassRef) DEFINE_STDCXX_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef) -#if LLVM_VERSION_LT(11, 0) -DEFINE_STDCXX_CONVERSION_FUNCTIONS(PassManagerBuilder, - LLVMPassManagerBuilderRef) -#endif extern "C" void LLVMInitializePasses() { PassRegistry &Registry = *PassRegistry::getPassRegistry(); @@ -74,6 +75,10 @@ extern "C" void LLVMTimeTraceProfilerInitialize() { /* ProcName */ "rustc"); } +extern "C" void LLVMTimeTraceProfilerFinishThread() { + timeTraceProfilerFinishThread(); +} + extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) { StringRef FN(FileName); std::error_code EC; @@ -461,6 +466,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( LLVMRustCodeGenOptLevel RustOptLevel, bool UseSoftFloat, bool FunctionSections, bool DataSections, + bool UniqueSectionNames, bool TrapUnreachable, bool Singlethread, bool AsmComments, @@ -490,6 +496,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( } Options.DataSections = DataSections; Options.FunctionSections = FunctionSections; + Options.UniqueSectionNames = UniqueSectionNames; Options.MCOptions.AsmVerbose = AsmComments; Options.MCOptions.PreserveAsmComments = AsmComments; Options.MCOptions.ABIName = ABIStr; @@ -680,7 +687,6 @@ void LLVMSelfProfileInitializeCallbacks( PassInstrumentationCallbacks& PIC, void* LlvmSelfProfiler, LLVMRustSelfProfileBeforePassCallback BeforePassCallback, LLVMRustSelfProfileAfterPassCallback AfterPassCallback) { -#if LLVM_VERSION_GE(12, 0) PIC.registerBeforeNonSkippedPassCallback([LlvmSelfProfiler, BeforePassCallback]( StringRef Pass, llvm::Any Ir) { std::string PassName = Pass.str(); @@ -698,25 +704,6 @@ void LLVMSelfProfileInitializeCallbacks( [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, const PreservedAnalyses &Preserved) { AfterPassCallback(LlvmSelfProfiler); }); -#else - PIC.registerBeforePassCallback([LlvmSelfProfiler, BeforePassCallback]( - StringRef Pass, llvm::Any Ir) { - std::string PassName = Pass.str(); - std::string IrName = LLVMRustwrappedIrGetName(Ir); - BeforePassCallback(LlvmSelfProfiler, PassName.c_str(), IrName.c_str()); - return true; - }); - - PIC.registerAfterPassCallback( - [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, llvm::Any Ir) { - AfterPassCallback(LlvmSelfProfiler); - }); - - PIC.registerAfterPassInvalidatedCallback( - [LlvmSelfProfiler, AfterPassCallback](StringRef Pass) { - AfterPassCallback(LlvmSelfProfiler); - }); -#endif PIC.registerBeforeAnalysisCallback([LlvmSelfProfiler, BeforePassCallback]( StringRef Pass, llvm::Any Ir) { @@ -777,22 +764,13 @@ LLVMRustOptimizeWithNewPassManager( PTO.LoopInterleaving = UnrollLoops; PTO.LoopVectorization = LoopVectorize; PTO.SLPVectorization = SLPVectorize; -#if LLVM_VERSION_GE(12, 0) PTO.MergeFunctions = MergeFunctions; -#else - // MergeFunctions is not supported by NewPM in older LLVM versions. - (void) MergeFunctions; -#endif // FIXME: We may want to expose this as an option. bool DebugPassManager = false; PassInstrumentationCallbacks PIC; -#if LLVM_VERSION_GE(12, 0) StandardInstrumentations SI(DebugPassManager); -#else - StandardInstrumentations SI; -#endif SI.registerCallbacks(PIC); if (LlvmSelfProfiler){ @@ -816,18 +794,14 @@ LLVMRustOptimizeWithNewPassManager( PGOOptions::NoCSAction, DebugInfoForProfiling); } -#if LLVM_VERSION_GE(12, 0) && !LLVM_VERSION_GE(13,0) - PassBuilder PB(DebugPassManager, TM, PTO, PGOOpt, &PIC); -#else - PassBuilder PB(TM, PTO, PGOOpt, &PIC); -#endif - #if LLVM_VERSION_GE(13, 0) + PassBuilder PB(TM, PTO, PGOOpt, &PIC); LoopAnalysisManager LAM; FunctionAnalysisManager FAM; CGSCCAnalysisManager CGAM; ModuleAnalysisManager MAM; #else + PassBuilder PB(DebugPassManager, TM, PTO, PGOOpt, &PIC); LoopAnalysisManager LAM(DebugPassManager); FunctionAnalysisManager FAM(DebugPassManager); CGSCCAnalysisManager CGAM(DebugPassManager); @@ -852,13 +826,8 @@ LLVMRustOptimizeWithNewPassManager( // PassBuilder does not create a pipeline. std::vector> PipelineStartEPCallbacks; -#if LLVM_VERSION_GE(11, 0) std::vector> OptimizerLastEPCallbacks; -#else - std::vector> - OptimizerLastEPCallbacks; -#endif if (VerifyIR) { PipelineStartEPCallbacks.push_back( @@ -891,7 +860,6 @@ LLVMRustOptimizeWithNewPassManager( SanitizerOptions->SanitizeMemoryTrackOrigins, SanitizerOptions->SanitizeMemoryRecover, /*CompileKernel=*/false); -#if LLVM_VERSION_GE(11, 0) OptimizerLastEPCallbacks.push_back( [Options](ModulePassManager &MPM, OptimizationLevel Level) { #if LLVM_VERSION_GE(14, 0) @@ -902,22 +870,9 @@ LLVMRustOptimizeWithNewPassManager( MPM.addPass(createModuleToFunctionPassAdaptor(MemorySanitizerPass(Options))); } ); -#else - PipelineStartEPCallbacks.push_back( - [Options](ModulePassManager &MPM, OptimizationLevel Level) { - MPM.addPass(MemorySanitizerPass(Options)); - } - ); - OptimizerLastEPCallbacks.push_back( - [Options](FunctionPassManager &FPM, OptimizationLevel Level) { - FPM.addPass(MemorySanitizerPass(Options)); - } - ); -#endif } if (SanitizerOptions->SanitizeThread) { -#if LLVM_VERSION_GE(11, 0) OptimizerLastEPCallbacks.push_back( [](ModulePassManager &MPM, OptimizationLevel Level) { #if LLVM_VERSION_GE(14, 0) @@ -928,63 +883,31 @@ LLVMRustOptimizeWithNewPassManager( MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass())); } ); -#else - PipelineStartEPCallbacks.push_back( - [](ModulePassManager &MPM, OptimizationLevel Level) { - MPM.addPass(ThreadSanitizerPass()); - } - ); - OptimizerLastEPCallbacks.push_back( - [](FunctionPassManager &FPM, OptimizationLevel Level) { - FPM.addPass(ThreadSanitizerPass()); - } - ); -#endif } if (SanitizerOptions->SanitizeAddress) { -#if LLVM_VERSION_GE(11, 0) OptimizerLastEPCallbacks.push_back( [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) { MPM.addPass(RequireAnalysisPass()); - MPM.addPass(ModuleAddressSanitizerPass( - /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover)); #if LLVM_VERSION_GE(14, 0) - AddressSanitizerOptions opts(/*CompileKernel=*/false, - SanitizerOptions->SanitizeAddressRecover, - /*UseAfterScope=*/true, - AsanDetectStackUseAfterReturnMode::Runtime); - MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass(opts))); + AddressSanitizerOptions opts = AddressSanitizerOptions{ + /*CompileKernel=*/false, + SanitizerOptions->SanitizeAddressRecover, + /*UseAfterScope=*/true, + AsanDetectStackUseAfterReturnMode::Runtime, + }; + MPM.addPass(ModuleAddressSanitizerPass(opts)); #else + MPM.addPass(ModuleAddressSanitizerPass( + /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover)); MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass( /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover, /*UseAfterScope=*/true))); #endif } ); -#else - PipelineStartEPCallbacks.push_back( - [&](ModulePassManager &MPM, OptimizationLevel Level) { - MPM.addPass(RequireAnalysisPass()); - } - ); - OptimizerLastEPCallbacks.push_back( - [SanitizerOptions](FunctionPassManager &FPM, OptimizationLevel Level) { - FPM.addPass(AddressSanitizerPass( - /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover, - /*UseAfterScope=*/true)); - } - ); - PipelineStartEPCallbacks.push_back( - [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) { - MPM.addPass(ModuleAddressSanitizerPass( - /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover)); - } - ); -#endif } if (SanitizerOptions->SanitizeHWAddress) { -#if LLVM_VERSION_GE(11, 0) OptimizerLastEPCallbacks.push_back( [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) { #if LLVM_VERSION_GE(14, 0) @@ -998,14 +921,6 @@ LLVMRustOptimizeWithNewPassManager( #endif } ); -#else - PipelineStartEPCallbacks.push_back( - [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) { - MPM.addPass(HWAddressSanitizerPass( - /*CompileKernel=*/false, SanitizerOptions->SanitizeHWAddressRecover)); - } - ); -#endif } } @@ -1020,7 +935,6 @@ LLVMRustOptimizeWithNewPassManager( // At the same time, the LTO pipelines do support O0 and using them is required. bool IsLTO = OptStage == LLVMRustOptStage::ThinLTO || OptStage == LLVMRustOptStage::FatLTO; if (OptLevel == OptimizationLevel::O0 && !IsLTO) { -#if LLVM_VERSION_GE(12, 0) for (const auto &C : PipelineStartEPCallbacks) PB.registerPipelineStartEPCallback(C); for (const auto &C : OptimizerLastEPCallbacks) @@ -1028,40 +942,9 @@ LLVMRustOptimizeWithNewPassManager( // Pass false as we manually schedule ThinLTOBufferPasses below. MPM = PB.buildO0DefaultPipeline(OptLevel, /* PreLinkLTO */ false); -#else - for (const auto &C : PipelineStartEPCallbacks) - C(MPM, OptLevel); - -# if LLVM_VERSION_GE(11, 0) - for (const auto &C : OptimizerLastEPCallbacks) - C(MPM, OptLevel); -# else - if (!OptimizerLastEPCallbacks.empty()) { - FunctionPassManager FPM(DebugPassManager); - for (const auto &C : OptimizerLastEPCallbacks) - C(FPM, OptLevel); - MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); - } -# endif - - MPM.addPass(AlwaysInlinerPass(EmitLifetimeMarkers)); - - if (PGOOpt) { - PB.addPGOInstrPassesForO0( - MPM, DebugPassManager, PGOOpt->Action == PGOOptions::IRInstr, - /*IsCS=*/false, PGOOpt->ProfileFile, PGOOpt->ProfileRemappingFile); - } -#endif } else { -#if LLVM_VERSION_GE(12, 0) for (const auto &C : PipelineStartEPCallbacks) PB.registerPipelineStartEPCallback(C); -#else - for (const auto &C : PipelineStartEPCallbacks) - PB.registerPipelineStartEPCallback([C, OptLevel](ModulePassManager &MPM) { - C(MPM, OptLevel); - }); -#endif if (OptStage != LLVMRustOptStage::PreLinkThinLTO) { for (const auto &C : OptimizerLastEPCallbacks) PB.registerOptimizerLastEPCallback(C); @@ -1072,7 +955,6 @@ LLVMRustOptimizeWithNewPassManager( MPM = PB.buildPerModuleDefaultPipeline(OptLevel, DebugPassManager); break; case LLVMRustOptStage::PreLinkThinLTO: -#if LLVM_VERSION_GE(12, 0) MPM = PB.buildThinLTOPreLinkDefaultPipeline(OptLevel); // The ThinLTOPreLink pipeline already includes ThinLTOBuffer passes. However, callback // passes may still run afterwards. This means we need to run the buffer passes again. @@ -1080,44 +962,20 @@ LLVMRustOptimizeWithNewPassManager( // before the RequiredLTOPreLinkPasses, in which case we can remove these hacks. if (OptimizerLastEPCallbacks.empty()) NeedThinLTOBufferPasses = false; -#else - MPM = PB.buildThinLTOPreLinkDefaultPipeline(OptLevel, DebugPassManager); -#endif -#if LLVM_VERSION_GE(11, 0) for (const auto &C : OptimizerLastEPCallbacks) C(MPM, OptLevel); -#else - if (!OptimizerLastEPCallbacks.empty()) { - FunctionPassManager FPM(DebugPassManager); - for (const auto &C : OptimizerLastEPCallbacks) - C(FPM, OptLevel); - MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); - } -#endif break; case LLVMRustOptStage::PreLinkFatLTO: -#if LLVM_VERSION_GE(12, 0) MPM = PB.buildLTOPreLinkDefaultPipeline(OptLevel); NeedThinLTOBufferPasses = false; -#else - MPM = PB.buildLTOPreLinkDefaultPipeline(OptLevel, DebugPassManager); -#endif break; case LLVMRustOptStage::ThinLTO: // FIXME: Does it make sense to pass the ModuleSummaryIndex? // It only seems to be needed for C++ specific optimizations. -#if LLVM_VERSION_GE(12, 0) MPM = PB.buildThinLTODefaultPipeline(OptLevel, nullptr); -#else - MPM = PB.buildThinLTODefaultPipeline(OptLevel, DebugPassManager, nullptr); -#endif break; case LLVMRustOptStage::FatLTO: -#if LLVM_VERSION_GE(12, 0) MPM = PB.buildLTODefaultPipeline(OptLevel, nullptr); -#else - MPM = PB.buildLTODefaultPipeline(OptLevel, DebugPassManager, nullptr); -#endif break; } } @@ -1547,7 +1405,6 @@ LLVMRustFreeThinLTOData(LLVMRustThinLTOData *Data) { // `ProcessThinLTOModule` function. Here they're split up into separate steps // so rustc can save off the intermediate bytecode between each step. -#if LLVM_VERSION_GE(11, 0) static bool clearDSOLocalOnDeclarations(Module &Mod, TargetMachine &TM) { // When linking an ELF shared object, dso_local should be dropped. We @@ -1558,7 +1415,6 @@ clearDSOLocalOnDeclarations(Module &Mod, TargetMachine &TM) { Mod.getPIELevel() == PIELevel::Default; return ClearDSOLocalOnDeclarations; } -#endif extern "C" bool LLVMRustPrepareThinLTORename(const LLVMRustThinLTOData *Data, LLVMModuleRef M, @@ -1566,12 +1422,8 @@ LLVMRustPrepareThinLTORename(const LLVMRustThinLTOData *Data, LLVMModuleRef M, Module &Mod = *unwrap(M); TargetMachine &Target = *unwrap(TM); -#if LLVM_VERSION_GE(11, 0) bool ClearDSOLocal = clearDSOLocalOnDeclarations(Mod, Target); bool error = renameModuleForThinLTO(Mod, Data->Index, ClearDSOLocal); -#else - bool error = renameModuleForThinLTO(Mod, Data->Index); -#endif if (error) { LLVMRustSetLastError("renameModuleForThinLTO failed"); @@ -1640,12 +1492,8 @@ LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M, return MOrErr; }; -#if LLVM_VERSION_GE(11, 0) bool ClearDSOLocal = clearDSOLocalOnDeclarations(Mod, Target); FunctionImporter Importer(Data->Index, Loader, ClearDSOLocal); -#else - FunctionImporter Importer(Data->Index, Loader); -#endif Expected Result = Importer.importFunctions(Mod, ImportList); if (!Result) { LLVMRustSetLastError(toString(Result.takeError()).c_str()); diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index b7b0524e2a..bb6d42c1a9 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -124,8 +124,18 @@ extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M, extern "C" LLVMValueRef LLVMRustGetOrInsertGlobal(LLVMModuleRef M, const char *Name, size_t NameLen, LLVMTypeRef Ty) { + Module *Mod = unwrap(M); StringRef NameRef(Name, NameLen); - return wrap(unwrap(M)->getOrInsertGlobal(NameRef, unwrap(Ty))); + + // We don't use Module::getOrInsertGlobal because that returns a Constant*, + // which may either be the real GlobalVariable*, or a constant bitcast of it + // if our type doesn't match the original declaration. We always want the + // GlobalVariable* so we can access linkage, visibility, etc. + GlobalVariable *GV = Mod->getGlobalVariable(NameRef, true); + if (!GV) + GV = new GlobalVariable(*Mod, unwrap(Ty), false, + GlobalValue::ExternalLinkage, nullptr, NameRef); + return wrap(GV); } extern "C" LLVMValueRef @@ -203,6 +213,12 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) { return Attribute::SanitizeHWAddress; case WillReturn: return Attribute::WillReturn; + case StackProtectReq: + return Attribute::StackProtectReq; + case StackProtectStrong: + return Attribute::StackProtectStrong; + case StackProtect: + return Attribute::StackProtect; } report_fatal_error("bad AttributeKind"); } @@ -263,11 +279,7 @@ extern "C" void LLVMRustAddByValCallSiteAttr(LLVMValueRef Instr, unsigned Index, extern "C" void LLVMRustAddStructRetCallSiteAttr(LLVMValueRef Instr, unsigned Index, LLVMTypeRef Ty) { CallBase *Call = unwrap(Instr); -#if LLVM_VERSION_GE(12, 0) Attribute Attr = Attribute::getWithStructRetType(Call->getContext(), unwrap(Ty)); -#else - Attribute Attr = Attribute::get(Call->getContext(), Attribute::StructRet); -#endif AddAttribute(Call, Index, Attr); } @@ -311,11 +323,7 @@ extern "C" void LLVMRustAddByValAttr(LLVMValueRef Fn, unsigned Index, extern "C" void LLVMRustAddStructRetAttr(LLVMValueRef Fn, unsigned Index, LLVMTypeRef Ty) { Function *F = unwrap(Fn); -#if LLVM_VERSION_GE(12, 0) Attribute Attr = Attribute::getWithStructRetType(F->getContext(), unwrap(Ty)); -#else - Attribute Attr = Attribute::get(F->getContext(), Attribute::StructRet); -#endif AddAttribute(F, Index, Attr); } @@ -681,10 +689,8 @@ static Optional fromRust(LLVMRustChecksumKind Kind) { return DIFile::ChecksumKind::CSK_MD5; case LLVMRustChecksumKind::SHA1: return DIFile::ChecksumKind::CSK_SHA1; -#if (LLVM_VERSION_MAJOR >= 11) case LLVMRustChecksumKind::SHA256: return DIFile::ChecksumKind::CSK_SHA256; -#endif default: report_fatal_error("bad ChecksumKind."); } @@ -999,14 +1005,9 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType( extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter( LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, size_t NameLen, LLVMMetadataRef Ty) { -#if LLVM_VERSION_GE(11, 0) bool IsDefault = false; // FIXME: should we ever set this true? return wrap(Builder->createTemplateTypeParameter( unwrapDI(Scope), StringRef(Name, NameLen), unwrapDI(Ty), IsDefault)); -#else - return wrap(Builder->createTemplateTypeParameter( - unwrapDI(Scope), StringRef(Name, NameLen), unwrapDI(Ty))); -#endif } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateNameSpace( @@ -1031,17 +1032,11 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateDebugLocation(unsigned Line, unsigned Column, LLVMMetadataRef ScopeRef, LLVMMetadataRef InlinedAt) { -#if LLVM_VERSION_GE(12, 0) MDNode *Scope = unwrapDIPtr(ScopeRef); DILocation *Loc = DILocation::get( Scope->getContext(), Line, Column, Scope, unwrapDIPtr(InlinedAt)); return wrap(Loc); -#else - DebugLoc debug_loc = DebugLoc::get(Line, Column, unwrapDIPtr(ScopeRef), - unwrapDIPtr(InlinedAt)); - return wrap(debug_loc.getAsMDNode()); -#endif } extern "C" int64_t LLVMRustDIBuilderCreateOpDeref() { @@ -1246,27 +1241,18 @@ extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) { return LLVMArrayTypeKind; case Type::PointerTyID: return LLVMPointerTypeKind; -#if LLVM_VERSION_GE(11, 0) case Type::FixedVectorTyID: return LLVMVectorTypeKind; -#else - case Type::VectorTyID: - return LLVMVectorTypeKind; -#endif case Type::X86_MMXTyID: return LLVMX86_MMXTypeKind; case Type::TokenTyID: return LLVMTokenTypeKind; -#if LLVM_VERSION_GE(11, 0) case Type::ScalableVectorTyID: return LLVMScalableVectorTypeKind; case Type::BFloatTyID: return LLVMBFloatTypeKind; -#endif -#if LLVM_VERSION_GE(12, 0) case Type::X86_AMXTyID: return LLVMX86_AMXTypeKind; -#endif } report_fatal_error("Unhandled TypeID."); } @@ -1724,23 +1710,15 @@ LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) } extern "C" LLVMValueRef LLVMRustBuildVectorReduceFMin(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) { -#if LLVM_VERSION_GE(12, 0) Instruction *I = unwrap(B)->CreateFPMinReduce(unwrap(Src)); I->setHasNoNaNs(NoNaN); return wrap(I); -#else - return wrap(unwrap(B)->CreateFPMinReduce(unwrap(Src), NoNaN)); -#endif } extern "C" LLVMValueRef LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) { -#if LLVM_VERSION_GE(12, 0) Instruction *I = unwrap(B)->CreateFPMaxReduce(unwrap(Src)); I->setHasNoNaNs(NoNaN); return wrap(I); -#else - return wrap(unwrap(B)->CreateFPMaxReduce(unwrap(Src), NoNaN)); -#endif } extern "C" LLVMValueRef diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs index 6493bd91ca..8476c2bfcc 100644 --- a/compiler/rustc_llvm/src/lib.rs +++ b/compiler/rustc_llvm/src/lib.rs @@ -1,5 +1,5 @@ #![feature(nll)] -#![feature(static_nobundle)] +#![feature(native_link_modifiers)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] // NOTE: This crate only exists to allow linking on mingw targets. diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 005017185c..6dbba27436 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -36,7 +36,7 @@ enum QueryModifier { Storage(Type), /// Cache the query to disk if the `Expr` returns true. - Cache(Option<(IdentOrWild, IdentOrWild)>, Block), + Cache(Option, Block), /// Custom code to load the query from disk. LoadCached(Ident, Ident, Block), @@ -55,6 +55,9 @@ enum QueryModifier { /// Always evaluate the query, ignoring its dependencies EvalAlways(Ident), + + /// Use a separate query provider for local and extern crates + SeparateProvideExtern(Ident), } impl Parse for QueryModifier { @@ -87,9 +90,7 @@ impl Parse for QueryModifier { let args; parenthesized!(args in input); let tcx = args.parse()?; - args.parse::()?; - let value = args.parse()?; - Some((tcx, value)) + Some(tcx) } else { None }; @@ -120,6 +121,8 @@ impl Parse for QueryModifier { Ok(QueryModifier::Anon(modifier)) } else if modifier == "eval_always" { Ok(QueryModifier::EvalAlways(modifier)) + } else if modifier == "separate_provide_extern" { + Ok(QueryModifier::SeparateProvideExtern(modifier)) } else { Err(Error::new(modifier.span(), "unknown query modifier")) } @@ -197,7 +200,7 @@ struct QueryModifiers { storage: Option, /// Cache the query to disk if the `Block` returns true. - cache: Option<(Option<(IdentOrWild, IdentOrWild)>, Block)>, + cache: Option<(Option, Block)>, /// Custom code to load the query from disk. load_cached: Option<(Ident, Ident, Block)>, @@ -216,6 +219,9 @@ struct QueryModifiers { // Always evaluate the query, ignoring its dependencies eval_always: Option, + + /// Use a separate query provider for local and extern crates + separate_provide_extern: Option, } /// Process query modifiers into a struct, erroring on duplicates @@ -229,6 +235,7 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers { let mut no_hash = None; let mut anon = None; let mut eval_always = None; + let mut separate_provide_extern = None; for modifier in query.modifiers.0.drain(..) { match modifier { QueryModifier::LoadCached(tcx, id, block) => { @@ -319,6 +326,15 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers { } eval_always = Some(ident); } + QueryModifier::SeparateProvideExtern(ident) => { + if separate_provide_extern.is_some() { + panic!( + "duplicate modifier `separate_provide_extern` for query `{}`", + query.name + ); + } + separate_provide_extern = Some(ident); + } } } let desc = desc.unwrap_or_else(|| { @@ -334,6 +350,7 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers { no_hash, anon, eval_always, + separate_provide_extern, } } @@ -351,51 +368,30 @@ fn add_query_description_impl( let try_load_from_disk = if let Some((tcx, id, block)) = modifiers.load_cached.as_ref() { // Use custom code to load the query from disk quote! { - #[inline] - fn try_load_from_disk( - #tcx: QueryCtxt<'tcx>, - #id: SerializedDepNodeIndex - ) -> Option { - #block - } + const TRY_LOAD_FROM_DISK: Option, SerializedDepNodeIndex) -> Option> + = Some(|#tcx, #id| { #block }); } } else { // Use the default code to load the query from disk quote! { - #[inline] - fn try_load_from_disk( - tcx: QueryCtxt<'tcx>, - id: SerializedDepNodeIndex - ) -> Option { - tcx.on_disk_cache().as_ref()?.try_load_query_result(*tcx, id) - } + const TRY_LOAD_FROM_DISK: Option, SerializedDepNodeIndex) -> Option> + = Some(|tcx, id| tcx.on_disk_cache().as_ref()?.try_load_query_result(*tcx, id)); } }; let tcx = args .as_ref() .map(|t| { - let t = &(t.0).0; - quote! { #t } - }) - .unwrap_or_else(|| quote! { _ }); - let value = args - .as_ref() - .map(|t| { - let t = &(t.1).0; + let t = &t.0; quote! { #t } }) .unwrap_or_else(|| quote! { _ }); // expr is a `Block`, meaning that `{ #expr }` gets expanded // to `{ { stmts... } }`, which triggers the `unused_braces` lint. quote! { - #[inline] #[allow(unused_variables, unused_braces)] - fn cache_on_disk( - #tcx: QueryCtxt<'tcx>, - #key: &Self::Key, - #value: Option<&Self::Value> - ) -> bool { + #[inline] + fn cache_on_disk(#tcx: TyCtxt<'tcx>, #key: &Self::Key) -> bool { #expr } @@ -405,7 +401,14 @@ fn add_query_description_impl( if modifiers.load_cached.is_some() { panic!("load_cached modifier on query `{}` without a cache modifier", name); } - quote! {} + quote! { + #[inline] + fn cache_on_disk(_: TyCtxt<'tcx>, _: &Self::Key) -> bool { + false + } + + const TRY_LOAD_FROM_DISK: Option, SerializedDepNodeIndex) -> Option> = None; + } }; let (tcx, desc) = modifiers.desc; @@ -413,17 +416,17 @@ fn add_query_description_impl( let desc = quote! { #[allow(unused_variables)] - fn describe(tcx: QueryCtxt<'tcx>, key: Self::Key) -> String { + fn describe(tcx: QueryCtxt<$tcx>, key: Self::Key) -> String { let (#tcx, #key) = (*tcx, key); ::rustc_middle::ty::print::with_no_trimmed_paths(|| format!(#desc).into()) } }; impls.extend(quote! { - impl<'tcx> QueryDescription> for queries::#name<'tcx> { + (#name<$tcx:tt>) => { #desc #cache - } + }; }); } @@ -478,6 +481,10 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { if let Some(eval_always) = &modifiers.eval_always { attributes.push(quote! { (#eval_always) }); }; + // Pass on the separate_provide_extern modifier + if let Some(separate_provide_extern) = &modifiers.separate_provide_extern { + attributes.push(quote! { (#separate_provide_extern) }); + } // This uses the span of the query definition for the commas, // which can be important if we later encounter any ambiguity @@ -531,7 +538,7 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { } #[macro_export] macro_rules! rustc_query_description { - () => { #query_description_stream } + #query_description_stream } }) } diff --git a/compiler/rustc_macros/src/serialize.rs b/compiler/rustc_macros/src/serialize.rs index 7bc669f2b0..66e6b571be 100644 --- a/compiler/rustc_macros/src/serialize.rs +++ b/compiler/rustc_macros/src/serialize.rs @@ -247,13 +247,24 @@ fn encodable_body( }) .collect(); - let result = quote! { ::rustc_serialize::Encoder::emit_enum_variant( - __encoder, - #variant_name, - #variant_idx, - #field_idx, - |__encoder| { ::std::result::Result::Ok({ #encode_fields }) } - ) }; + let result = if field_idx != 0 { + quote! { + ::rustc_serialize::Encoder::emit_enum_variant( + __encoder, + #variant_name, + #variant_idx, + #field_idx, + |__encoder| { ::std::result::Result::Ok({ #encode_fields }) } + ) + } + } else { + quote! { + ::rustc_serialize::Encoder::emit_fieldless_enum_variant::<#variant_idx>( + __encoder, + #variant_name, + ) + } + }; variant_idx += 1; result }); diff --git a/compiler/rustc_macros/src/session_diagnostic.rs b/compiler/rustc_macros/src/session_diagnostic.rs index c8959dc86a..80dcf99da6 100644 --- a/compiler/rustc_macros/src/session_diagnostic.rs +++ b/compiler/rustc_macros/src/session_diagnostic.rs @@ -349,14 +349,14 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> { ) -> Result { let field_binding = &info.binding.binding; - let option_ty = option_inner_ty(info.ty); + let option_ty = option_inner_ty(&info.ty); let generated_code = self.generate_non_option_field_code( attr, FieldInfo { vis: info.vis, binding: info.binding, - ty: option_ty.unwrap_or(info.ty), + ty: option_ty.unwrap_or(&info.ty), span: info.span, }, )?; @@ -388,7 +388,7 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> { let formatted_str = self.build_format(&s.value(), attr.span()); match name { "message" => { - if type_matches_path(info.ty, &["rustc_span", "Span"]) { + if type_matches_path(&info.ty, &["rustc_span", "Span"]) { quote! { #diag.set_span(*#field_binding); #diag.set_primary_message(#formatted_str); @@ -401,7 +401,7 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> { } } "label" => { - if type_matches_path(info.ty, &["rustc_span", "Span"]) { + if type_matches_path(&info.ty, &["rustc_span", "Span"]) { quote! { #diag.span_label(*#field_binding, #formatted_str); } diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 95b74fd530..eb0a693226 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -29,6 +29,7 @@ use rustc_target::spec::{PanicStrategy, TargetTriple}; use proc_macro::bridge::client::ProcMacro; use std::collections::BTreeMap; +use std::ops::Fn; use std::path::Path; use std::{cmp, env}; use tracing::{debug, info}; diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 644b849a9f..6cf0dd8b1a 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -2,6 +2,7 @@ #![feature(crate_visibility_modifier)] #![feature(drain_filter)] #![feature(in_band_lifetimes)] +#![feature(let_else)] #![feature(nll)] #![feature(once_cell)] #![feature(proc_macro_internals)] diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index bbd30c9327..7cba16e0a9 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -236,7 +236,7 @@ use std::fmt::Write as _; use std::io::{Read, Result as IoResult, Write}; use std::path::{Path, PathBuf}; use std::{cmp, fmt, fs}; -use tracing::{debug, info, warn}; +use tracing::{debug, info}; #[derive(Clone)] crate struct CrateLocator<'a> { @@ -350,6 +350,7 @@ impl<'a> CrateLocator<'a> { self.crate_rejections.via_kind.clear(); self.crate_rejections.via_version.clear(); self.crate_rejections.via_filename.clear(); + self.crate_rejections.via_invalid.clear(); } crate fn maybe_load_library_crate(&mut self) -> Result, CrateError> { @@ -548,8 +549,18 @@ impl<'a> CrateLocator<'a> { continue; } } - Err(err) => { - warn!("no metadata found: {}", err); + Err(MetadataError::LoadFailure(err)) => { + info!("no metadata found: {}", err); + // The file was present and created by the same compiler version, but we + // couldn't load it for some reason. Give a hard error instead of silently + // ignoring it, but only if we would have given an error anyway. + self.crate_rejections + .via_invalid + .push(CrateMismatch { path: lib, got: err }); + continue; + } + Err(err @ MetadataError::NotPresent(_)) => { + info!("no metadata found: {}", err); continue; } }; @@ -726,25 +737,28 @@ impl<'a> CrateLocator<'a> { fn get_metadata_section( target: &Target, flavor: CrateFlavor, - filename: &Path, + filename: &'p Path, loader: &dyn MetadataLoader, -) -> Result { +) -> Result> { if !filename.exists() { - return Err(format!("no such file: '{}'", filename.display())); + return Err(MetadataError::NotPresent(filename)); } let raw_bytes: MetadataRef = match flavor { - CrateFlavor::Rlib => loader.get_rlib_metadata(target, filename)?, + CrateFlavor::Rlib => { + loader.get_rlib_metadata(target, filename).map_err(MetadataError::LoadFailure)? + } CrateFlavor::Dylib => { - let buf = loader.get_dylib_metadata(target, filename)?; + let buf = + loader.get_dylib_metadata(target, filename).map_err(MetadataError::LoadFailure)?; // The header is uncompressed let header_len = METADATA_HEADER.len(); debug!("checking {} bytes of metadata-version stamp", header_len); let header = &buf[..cmp::min(header_len, buf.len())]; if header != METADATA_HEADER { - return Err(format!( - "incompatible metadata version found: '{}'", + return Err(MetadataError::LoadFailure(format!( + "invalid metadata version found: {}", filename.display() - )); + ))); } // Header is okay -> inflate the actual metadata @@ -756,17 +770,28 @@ fn get_metadata_section( match FrameDecoder::new(compressed_bytes).read_to_end(&mut inflated) { Ok(_) => rustc_erase_owner!(OwningRef::new(inflated).map_owner_box()), Err(_) => { - return Err(format!("failed to decompress metadata: {}", filename.display())); + return Err(MetadataError::LoadFailure(format!( + "failed to decompress metadata: {}", + filename.display() + ))); } } } CrateFlavor::Rmeta => { // 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 file = std::fs::File::open(filename).map_err(|_| { + MetadataError::LoadFailure(format!( + "failed to open rmeta metadata: '{}'", + filename.display() + )) + })?; let mmap = unsafe { Mmap::map(file) }; - let mmap = mmap - .map_err(|_| format!("failed to mmap rmeta metadata: '{}'", filename.display()))?; + let mmap = mmap.map_err(|_| { + MetadataError::LoadFailure(format!( + "failed to mmap rmeta metadata: '{}'", + filename.display() + )) + })?; rustc_erase_owner!(OwningRef::new(mmap).map_owner_box()) } @@ -775,7 +800,10 @@ fn get_metadata_section( if blob.is_compatible() { Ok(blob) } else { - Err(format!("incompatible metadata version found: '{}'", filename.display())) + Err(MetadataError::LoadFailure(format!( + "invalid metadata version found: {}", + filename.display() + ))) } } @@ -854,6 +882,7 @@ struct CrateRejections { via_kind: Vec, via_version: Vec, via_filename: Vec, + via_invalid: Vec, } /// Candidate rejection reasons collected during crate search. @@ -883,6 +912,24 @@ crate enum CrateError { NonDylibPlugin(Symbol), } +enum MetadataError<'a> { + /// The file was missing. + NotPresent(&'a Path), + /// The file was present and invalid. + LoadFailure(String), +} + +impl fmt::Display for MetadataError<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + MetadataError::NotPresent(filename) => { + f.write_str(&format!("no such file: '{}'", filename.display())) + } + MetadataError::LoadFailure(msg) => f.write_str(msg), + } + } +} + impl CrateError { crate fn report(self, sess: &Session, span: Span, missing_core: bool) -> ! { let mut err = match self { @@ -1064,6 +1111,19 @@ impl CrateError { } err.note(&msg); err + } else if !locator.crate_rejections.via_invalid.is_empty() { + let mut err = struct_span_err!( + sess, + span, + E0786, + "found invalid metadata files for crate `{}`{}", + crate_name, + add, + ); + for CrateMismatch { path: _, got } in locator.crate_rejections.via_invalid { + err.note(&got); + } + err } else { let mut err = struct_span_err!( sess, diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 2431b819a3..bd5cda15b9 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -309,7 +309,7 @@ impl Collector<'tcx> { .libs .iter() .filter_map(|lib| lib.name.as_ref()) - .any(|n| &n.as_str() == &lib.name); + .any(|n| n.as_str() == lib.name); if new_name.is_empty() { self.tcx.sess.err(&format!( "an empty renaming target was specified for library `{}`", diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 89bb5797a8..b2c7818a54 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -472,9 +472,7 @@ impl<'a, 'tcx> Decodable> for Span { let len = BytePos::decode(decoder)?; let hi = lo + len; - let sess = if let Some(sess) = decoder.sess { - sess - } else { + let Some(sess) = decoder.sess else { bug!("Cannot decode Span without Session.") }; @@ -1181,7 +1179,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { let ctor_res = Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id); let mut vis = self.get_visibility(ctor_def_id.index); - if ctor_def_id == def_id && vis == ty::Visibility::Public { + if ctor_def_id == def_id && vis.is_public() { // For non-exhaustive variants lower the constructor visibility to // within the crate. We only need this for fictive constructors, // for other constructors correct visibilities @@ -1200,8 +1198,8 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } } - if let EntryKind::Mod(data) = kind { - for exp in data.decode((self, sess)).reexports.decode((self, sess)) { + if let EntryKind::Mod(exports) = kind { + for exp in exports.decode((self, sess)) { match exp.res { Res::Def(DefKind::Macro(..), _) => {} _ if macros_only => continue, @@ -1221,10 +1219,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } fn module_expansion(&self, id: DefIndex, sess: &Session) -> ExpnId { - if let EntryKind::Mod(m) = self.kind(id) { - m.decode((self, sess)).expansion - } else { - panic!("Expected module, found {:?}", self.local_def_id(id)) + match self.kind(id) { + EntryKind::Mod(_) | EntryKind::Enum(_) | EntryKind::Trait(_) => { + self.get_expn_that_defined(id, sess) + } + _ => panic!("Expected module, found {:?}", self.local_def_id(id)), } } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index e12f049a90..eeb0a77adc 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -10,7 +10,7 @@ use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; use rustc_middle::hir::exports::Export; use rustc_middle::middle::exported_symbols::ExportedSymbol; use rustc_middle::middle::stability::DeprecationEntry; -use rustc_middle::ty::query::Providers; +use rustc_middle::ty::query::{ExternProviders, Providers}; use rustc_middle::ty::{self, TyCtxt, Visibility}; use rustc_session::cstore::{CrateSource, CrateStore, ForeignModule}; use rustc_session::utils::NativeLibKind; @@ -26,7 +26,7 @@ use std::any::Any; macro_rules! provide { (<$lt:tt> $tcx:ident, $def_id:ident, $other:ident, $cdata:ident, $($name:ident => $compute:block)*) => { - pub fn provide_extern(providers: &mut Providers) { + pub fn provide_extern(providers: &mut ExternProviders) { $(fn $name<$lt>( $tcx: TyCtxt<$lt>, def_id_arg: ty::query::query_keys::$name<$lt>, @@ -51,7 +51,7 @@ macro_rules! provide { $compute })* - *providers = Providers { + *providers = ExternProviders { $($name,)* ..*providers }; @@ -318,7 +318,7 @@ pub fn provide(providers: &mut Providers) { } let mut add_child = |bfs_queue: &mut VecDeque<_>, child: &Export, parent: DefId| { - if child.vis != ty::Visibility::Public { + if !child.vis.is_public() { return; } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 20f7b059b5..d46829c2ce 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -797,6 +797,7 @@ fn should_encode_visibility(def_kind: DefKind) -> bool { | DefKind::ConstParam | DefKind::LifetimeParam | DefKind::AnonConst + | DefKind::InlineConst | DefKind::GlobalAsm | DefKind::Closure | DefKind::Generator @@ -832,6 +833,7 @@ fn should_encode_stability(def_kind: DefKind) -> bool { DefKind::Use | DefKind::LifetimeParam | DefKind::AnonConst + | DefKind::InlineConst | DefKind::GlobalAsm | DefKind::Closure | DefKind::Generator @@ -856,9 +858,11 @@ fn should_encode_mir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> (bool, bool) { (true, mir_opt_base) } // Constants - DefKind::AnonConst | DefKind::AssocConst | DefKind::Static | DefKind::Const => { - (true, false) - } + DefKind::AnonConst + | DefKind::InlineConst + | DefKind::AssocConst + | DefKind::Static + | DefKind::Const => (true, false), // Full-fledged functions DefKind::AssocFn | DefKind::Fn => { let generics = tcx.generics_of(def_id); @@ -914,6 +918,7 @@ fn should_encode_variances(def_kind: DefKind) -> bool { | DefKind::Use | DefKind::LifetimeParam | DefKind::AnonConst + | DefKind::InlineConst | DefKind::GlobalAsm | DefKind::Closure | DefKind::Generator @@ -939,6 +944,7 @@ fn should_encode_generics(def_kind: DefKind) -> bool { | DefKind::AssocFn | DefKind::AssocConst | DefKind::AnonConst + | DefKind::InlineConst | DefKind::OpaqueTy | DefKind::Impl | DefKind::Field @@ -1086,11 +1092,11 @@ impl EncodeContext<'a, 'tcx> { Lazy::empty() }; - let data = ModData { reexports, expansion: tcx.expn_that_defined(local_def_id) }; - - record!(self.tables.kind[def_id] <- EntryKind::Mod(self.lazy(data))); + record!(self.tables.kind[def_id] <- EntryKind::Mod(reexports)); if self.is_proc_macro { record!(self.tables.children[def_id] <- &[]); + // Encode this here because we don't do it in encode_def_ids. + record!(self.tables.expn_that_defined[def_id] <- tcx.expn_that_defined(local_def_id)); } else { record!(self.tables.children[def_id] <- md.item_ids.iter().map(|item_id| { item_id.def_id.local_def_index @@ -2187,5 +2193,8 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>) -> EncodedMetadata { result[header + 2] = (pos >> 8) as u8; result[header + 3] = (pos >> 0) as u8; + // Record metadata size for self-profiling + tcx.prof.artifact_size("crate_metadata", "crate_metadata", result.len() as u64); + EncodedMetadata { raw_data: result } } diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 42855e9d9d..4e09d23169 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -346,7 +346,7 @@ enum EntryKind { Union(Lazy, ReprOptions), Fn(Lazy), ForeignFn(Lazy), - Mod(Lazy), + Mod(Lazy<[Export]>), MacroDef(Lazy), ProcMacro(MacroKind), Closure, @@ -364,12 +364,6 @@ enum EntryKind { #[derive(Encodable, Decodable)] struct RenderedConst(String); -#[derive(MetadataEncodable, MetadataDecodable)] -struct ModData { - reexports: Lazy<[Export]>, - expansion: ExpnId, -} - #[derive(MetadataEncodable, MetadataDecodable)] struct FnData { asyncness: hir::IsAsync, diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml index d06c593d39..daeccde602 100644 --- a/compiler/rustc_middle/Cargo.toml +++ b/compiler/rustc_middle/Cargo.toml @@ -12,6 +12,7 @@ bitflags = "1.2.1" either = "1.5.0" gsgdt = "0.1.2" tracing = "0.1" +rustc-rayon = "0.3.1" rustc-rayon-core = "0.3.1" polonius-engine = "0.13.0" rustc_apfloat = { path = "../rustc_apfloat" } diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 962aea448b..ee2e190e7c 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -1,43 +1,38 @@ -/// This declares a list of types which can be allocated by `Arena`. -/// -/// The `few` modifier will cause allocation to use the shared arena and recording the destructor. -/// This is faster and more memory efficient if there's only a few allocations of the type. -/// Leaving `few` out will cause the type to get its own dedicated `TypedArena` which is -/// faster and more memory efficient if there is lots of allocations. +/// This higher-order macro declares a list of types which can be allocated by `Arena`. /// /// Specifying the `decode` modifier will add decode impls for `&T` and `&[T]` where `T` is the type /// listed. These impls will appear in the implement_ty_decoder! macro. #[macro_export] macro_rules! arena_types { - ($macro:path, $tcx:lifetime) => ( + ($macro:path) => ( $macro!([ [] layout: rustc_target::abi::Layout, - [] fn_abi: rustc_target::abi::call::FnAbi<$tcx, rustc_middle::ty::Ty<$tcx>>, + [] fn_abi: rustc_target::abi::call::FnAbi<'tcx, rustc_middle::ty::Ty<'tcx>>, // AdtDef are interned and compared by address [] adt_def: rustc_middle::ty::AdtDef, - [] steal_thir: rustc_data_structures::steal::Steal>, - [] steal_mir: rustc_data_structures::steal::Steal>, - [decode] mir: rustc_middle::mir::Body<$tcx>, + [] steal_thir: rustc_data_structures::steal::Steal>, + [] steal_mir: rustc_data_structures::steal::Steal>, + [decode] mir: rustc_middle::mir::Body<'tcx>, [] steal_promoted: rustc_data_structures::steal::Steal< rustc_index::vec::IndexVec< rustc_middle::mir::Promoted, - rustc_middle::mir::Body<$tcx> + rustc_middle::mir::Body<'tcx> > >, [decode] promoted: rustc_index::vec::IndexVec< rustc_middle::mir::Promoted, - rustc_middle::mir::Body<$tcx> + rustc_middle::mir::Body<'tcx> >, - [decode] typeck_results: rustc_middle::ty::TypeckResults<$tcx>, + [decode] typeck_results: rustc_middle::ty::TypeckResults<'tcx>, [decode] borrowck_result: - rustc_middle::mir::BorrowCheckResult<$tcx>, + rustc_middle::mir::BorrowCheckResult<'tcx>, [decode] unsafety_check_result: rustc_middle::mir::UnsafetyCheckResult, [decode] code_region: rustc_middle::mir::coverage::CodeRegion, [] const_allocs: rustc_middle::mir::interpret::Allocation, // Required for the incremental on-disk cache - [few] mir_keys: rustc_hir::def_id::DefIdSet, + [] mir_keys: rustc_hir::def_id::DefIdSet, [] region_scope_tree: rustc_middle::middle::region::ScopeTree, [] dropck_outlives: rustc_middle::infer::canonical::Canonical<'tcx, @@ -77,26 +72,20 @@ macro_rules! arena_types { rustc_middle::infer::canonical::Canonical<'tcx, rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Ty<'tcx>> >, - [few] all_traits: Vec, - [few] privacy_access_levels: rustc_middle::middle::privacy::AccessLevels, - [few] foreign_module: rustc_session::cstore::ForeignModule, - [few] foreign_modules: Vec, + [] all_traits: Vec, + [] privacy_access_levels: rustc_middle::middle::privacy::AccessLevels, + [] foreign_module: rustc_session::cstore::ForeignModule, + [] foreign_modules: Vec, [] upvars_mentioned: rustc_data_structures::fx::FxIndexMap, [] object_safety_violations: rustc_middle::traits::ObjectSafetyViolation, - [] codegen_unit: rustc_middle::mir::mono::CodegenUnit<$tcx>, + [] codegen_unit: rustc_middle::mir::mono::CodegenUnit<'tcx>, [] attribute: rustc_ast::Attribute, [] name_set: rustc_data_structures::fx::FxHashSet, [] hir_id_set: rustc_hir::HirIdSet, // Interned types - [] tys: rustc_middle::ty::TyS<$tcx>, - [] predicates: rustc_middle::ty::PredicateInner<$tcx>, - - // HIR query types - [few] indexed_hir: rustc_middle::hir::IndexedHir<$tcx>, - [few] hir_definitions: rustc_hir::definitions::Definitions, - [] hir_owner: rustc_middle::hir::Owner<$tcx>, - [] hir_owner_nodes: rustc_middle::hir::OwnerNodes<$tcx>, + [] tys: rustc_middle::ty::TyS<'tcx>, + [] predicates: rustc_middle::ty::PredicateInner<'tcx>, // Note that this deliberately duplicates items in the `rustc_hir::arena`, // since we need to allocate this type on both the `rustc_hir` arena @@ -106,8 +95,10 @@ macro_rules! arena_types { // This is used to decode the &'tcx [Span] for InlineAsm's line_spans. [decode] span: rustc_span::Span, [decode] used_trait_imports: rustc_data_structures::fx::FxHashSet, - ], $tcx); + + [] dep_kind: rustc_middle::dep_graph::DepKindStruct, + ]); ) } -arena_types!(rustc_arena::declare_arena, 'tcx); +arena_types!(rustc_arena::declare_arena); diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 23d475a595..f310001077 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -75,145 +75,71 @@ pub use rustc_query_system::dep_graph::{DepContext, DepNodeParams}; /// of the `DepKind`. Overall, this allows to implement `DepContext` using this manual /// jump table instead of large matches. pub struct DepKindStruct { - /// Whether the DepNode has parameters (query keys). - pub(super) has_params: bool, - /// Anonymous queries cannot be replayed from one compiler invocation to the next. /// When their result is needed, it is recomputed. They are useful for fine-grained /// dependency tracking, and caching within one compiler invocation. - pub(super) is_anon: bool, + pub is_anon: bool, /// Eval-always queries do not track their dependencies, and are always recomputed, even if /// their inputs have not changed since the last compiler invocation. The result is still /// cached within one compiler invocation. - pub(super) is_eval_always: bool, + pub is_eval_always: bool, /// Whether the query key can be recovered from the hashed fingerprint. /// See [DepNodeParams] trait for the behaviour of each key type. - // FIXME: Make this a simple boolean once DepNodeParams::fingerprint_style - // can be made a specialized associated const. - fingerprint_style: fn() -> FingerprintStyle, -} - -impl std::ops::Deref for DepKind { - type Target = DepKindStruct; - fn deref(&self) -> &DepKindStruct { - &DEP_KINDS[*self as usize] - } + pub fingerprint_style: FingerprintStyle, + + /// The red/green evaluation system will try to mark a specific DepNode in the + /// dependency graph as green by recursively trying to mark the dependencies of + /// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode` + /// where we don't know if it is red or green and we therefore actually have + /// to recompute its value in order to find out. Since the only piece of + /// information that we have at that point is the `DepNode` we are trying to + /// re-evaluate, we need some way to re-run a query from just that. This is what + /// `force_from_dep_node()` implements. + /// + /// In the general case, a `DepNode` consists of a `DepKind` and an opaque + /// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint + /// is usually constructed by computing a stable hash of the query-key that the + /// `DepNode` corresponds to. Consequently, it is not in general possible to go + /// back from hash to query-key (since hash functions are not reversible). For + /// this reason `force_from_dep_node()` is expected to fail from time to time + /// because we just cannot find out, from the `DepNode` alone, what the + /// corresponding query-key is and therefore cannot re-run the query. + /// + /// The system deals with this case letting `try_mark_green` fail which forces + /// the root query to be re-evaluated. + /// + /// Now, if `force_from_dep_node()` would always fail, it would be pretty useless. + /// Fortunately, we can use some contextual information that will allow us to + /// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we + /// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a + /// valid `DefPathHash`. Since we also always build a huge table that maps every + /// `DefPathHash` in the current codebase to the corresponding `DefId`, we have + /// everything we need to re-run the query. + /// + /// Take the `mir_promoted` query as an example. Like many other queries, it + /// just has a single parameter: the `DefId` of the item it will compute the + /// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode` + /// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode` + /// is actually a `DefPathHash`, and can therefore just look up the corresponding + /// `DefId` in `tcx.def_path_hash_to_def_id`. + pub force_from_dep_node: Option, dep_node: DepNode) -> bool>, + + /// Invoke a query to put the on-disk cached value in memory. + pub try_load_from_on_disk_cache: Option, DepNode)>, } impl DepKind { #[inline(always)] - pub fn fingerprint_style(&self) -> FingerprintStyle { + pub fn fingerprint_style(self, tcx: TyCtxt<'_>) -> FingerprintStyle { // Only fetch the DepKindStruct once. - let data: &DepKindStruct = &**self; + let data = tcx.query_kind(self); if data.is_anon { return FingerprintStyle::Opaque; } - - (data.fingerprint_style)() - } -} - -// erase!() just makes tokens go away. It's used to specify which macro argument -// is repeated (i.e., which sub-expression of the macro we are in) but don't need -// to actually use any of the arguments. -macro_rules! erase { - ($x:tt) => {{}}; -} - -macro_rules! is_anon_attr { - (anon) => { - true - }; - ($attr:ident) => { - false - }; -} - -macro_rules! is_eval_always_attr { - (eval_always) => { - true - }; - ($attr:ident) => { - false - }; -} - -macro_rules! contains_anon_attr { - ($(($attr:ident $($attr_args:tt)* )),*) => ({$(is_anon_attr!($attr) | )* false}); -} - -macro_rules! contains_eval_always_attr { - ($(($attr:ident $($attr_args:tt)* )),*) => ({$(is_eval_always_attr!($attr) | )* false}); -} - -#[allow(non_upper_case_globals)] -pub mod dep_kind { - use super::*; - use crate::ty::query::query_keys; - use rustc_query_system::dep_graph::FingerprintStyle; - - // We use this for most things when incr. comp. is turned off. - pub const Null: DepKindStruct = DepKindStruct { - has_params: false, - is_anon: false, - is_eval_always: false, - - fingerprint_style: || FingerprintStyle::Unit, - }; - - pub const TraitSelect: DepKindStruct = DepKindStruct { - has_params: false, - is_anon: true, - is_eval_always: false, - - fingerprint_style: || FingerprintStyle::Unit, - }; - - pub const CompileCodegenUnit: DepKindStruct = DepKindStruct { - has_params: true, - is_anon: false, - is_eval_always: false, - - fingerprint_style: || FingerprintStyle::Opaque, - }; - - pub const CompileMonoItem: DepKindStruct = DepKindStruct { - has_params: true, - is_anon: false, - is_eval_always: false, - - fingerprint_style: || FingerprintStyle::Opaque, - }; - - macro_rules! define_query_dep_kinds { - ($( - [$($attrs:tt)*] - $variant:ident $(( $tuple_arg_ty:ty $(,)? ))* - ,)*) => ( - $(pub const $variant: DepKindStruct = { - const has_params: bool = $({ erase!($tuple_arg_ty); true } |)* false; - const is_anon: bool = contains_anon_attr!($($attrs)*); - const is_eval_always: bool = contains_eval_always_attr!($($attrs)*); - - #[inline(always)] - fn fingerprint_style() -> rustc_query_system::dep_graph::FingerprintStyle { - as DepNodeParams>> - ::fingerprint_style() - } - - DepKindStruct { - has_params, - is_anon, - is_eval_always, - fingerprint_style, - } - };)* - ); + data.fingerprint_style } - - rustc_dep_node_append!([define_query_dep_kinds!][]); } macro_rules! define_dep_nodes { @@ -225,12 +151,10 @@ macro_rules! define_dep_nodes { ) => ( #[macro_export] macro_rules! make_dep_kind_array { - ($mod:ident) => {[ $(($mod::$variant),)* ]}; + ($mod:ident) => {[ $($mod::$variant()),* ]}; } - static DEP_KINDS: &[DepKindStruct] = &make_dep_kind_array!(dep_kind); - - /// This enum serves as an index into the `DEP_KINDS` array. + /// This enum serves as an index into arrays built by `make_dep_kind_array`. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Encodable, Decodable)] #[allow(non_camel_case_types)] pub enum DepKind { @@ -296,7 +220,7 @@ pub trait DepNodeExt: Sized { /// Construct a DepNode from the given DepKind and DefPathHash. This /// method will assert that the given DepKind actually requires a /// single DefId/DefPathHash parameter. - fn from_def_path_hash(def_path_hash: DefPathHash, kind: DepKind) -> Self; + fn from_def_path_hash(tcx: TyCtxt<'_>, def_path_hash: DefPathHash, kind: DepKind) -> Self; /// Extracts the DefId corresponding to this DepNode. This will work /// if two conditions are met: @@ -311,7 +235,11 @@ pub trait DepNodeExt: Sized { fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option; /// Used in testing - fn from_label_string(label: &str, def_path_hash: DefPathHash) -> Result; + fn from_label_string( + tcx: TyCtxt<'_>, + label: &str, + def_path_hash: DefPathHash, + ) -> Result; /// Used in testing fn has_label_string(label: &str) -> bool; @@ -321,8 +249,8 @@ impl DepNodeExt for DepNode { /// Construct a DepNode from the given DepKind and DefPathHash. This /// method will assert that the given DepKind actually requires a /// single DefId/DefPathHash parameter. - fn from_def_path_hash(def_path_hash: DefPathHash, kind: DepKind) -> DepNode { - debug_assert!(kind.fingerprint_style() == FingerprintStyle::DefPathHash); + fn from_def_path_hash(tcx: TyCtxt<'_>, def_path_hash: DefPathHash, kind: DepKind) -> DepNode { + debug_assert!(kind.fingerprint_style(tcx) == FingerprintStyle::DefPathHash); DepNode { kind, hash: def_path_hash.0.into() } } @@ -337,31 +265,27 @@ impl DepNodeExt for DepNode { /// refers to something from the previous compilation session that /// has been removed. fn extract_def_id(&self, tcx: TyCtxt<'tcx>) -> Option { - if self.kind.fingerprint_style() == FingerprintStyle::DefPathHash { - Some( - tcx.on_disk_cache - .as_ref()? - .def_path_hash_to_def_id(tcx, DefPathHash(self.hash.into())), - ) + if self.kind.fingerprint_style(tcx) == FingerprintStyle::DefPathHash { + Some(tcx.def_path_hash_to_def_id(DefPathHash(self.hash.into()))) } else { None } } /// Used in testing - fn from_label_string(label: &str, def_path_hash: DefPathHash) -> Result { + fn from_label_string( + tcx: TyCtxt<'_>, + label: &str, + def_path_hash: DefPathHash, + ) -> Result { let kind = dep_kind_from_label_string(label)?; - match kind.fingerprint_style() { + match kind.fingerprint_style(tcx) { FingerprintStyle::Opaque => Err(()), - FingerprintStyle::Unit => { - if !kind.has_params { - Ok(DepNode::new_no_params(kind)) - } else { - Err(()) - } + FingerprintStyle::Unit => Ok(DepNode::new_no_params(tcx, kind)), + FingerprintStyle::DefPathHash => { + Ok(DepNode::from_def_path_hash(tcx, def_path_hash, kind)) } - FingerprintStyle::DefPathHash => Ok(DepNode::from_def_path_hash(def_path_hash, kind)), } } @@ -377,10 +301,12 @@ impl<'tcx> DepNodeParams> for () { FingerprintStyle::Unit } + #[inline(always)] fn to_fingerprint(&self, _: TyCtxt<'tcx>) -> Fingerprint { Fingerprint::ZERO } + #[inline(always)] fn recover(_: TyCtxt<'tcx>, _: &DepNode) -> Option { Some(()) } @@ -392,14 +318,17 @@ impl<'tcx> DepNodeParams> for DefId { FingerprintStyle::DefPathHash } + #[inline(always)] fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { tcx.def_path_hash(*self).0 } + #[inline(always)] fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { tcx.def_path_str(*self) } + #[inline(always)] fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { dep_node.extract_def_id(tcx) } @@ -411,14 +340,17 @@ impl<'tcx> DepNodeParams> for LocalDefId { FingerprintStyle::DefPathHash } + #[inline(always)] fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { self.to_def_id().to_fingerprint(tcx) } + #[inline(always)] fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { self.to_def_id().to_debug_str(tcx) } + #[inline(always)] fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { dep_node.extract_def_id(tcx).map(|id| id.expect_local()) } @@ -430,15 +362,18 @@ impl<'tcx> DepNodeParams> for CrateNum { FingerprintStyle::DefPathHash } + #[inline(always)] fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { let def_id = DefId { krate: *self, index: CRATE_DEF_INDEX }; def_id.to_fingerprint(tcx) } + #[inline(always)] fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { tcx.crate_name(*self).to_string() } + #[inline(always)] fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { dep_node.extract_def_id(tcx).map(|id| id.krate) } @@ -453,6 +388,7 @@ impl<'tcx> DepNodeParams> for (DefId, DefId) { // We actually would not need to specialize the implementation of this // method but it's faster to combine the hashes than to instantiate a full // hashing context and stable-hashing state. + #[inline(always)] fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { let (def_id_0, def_id_1) = *self; @@ -462,6 +398,7 @@ impl<'tcx> DepNodeParams> for (DefId, DefId) { def_path_hash_0.0.combine(def_path_hash_1.0) } + #[inline(always)] fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { let (def_id_0, def_id_1) = *self; @@ -478,6 +415,7 @@ impl<'tcx> DepNodeParams> for HirId { // We actually would not need to specialize the implementation of this // method but it's faster to combine the hashes than to instantiate a full // hashing context and stable-hashing state. + #[inline(always)] fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { let HirId { owner, local_id } = *self; diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index cda9963907..79d7ca32f3 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -12,7 +12,7 @@ pub use rustc_query_system::dep_graph::{ SerializedDepNodeIndex, WorkProduct, WorkProductId, }; -pub use dep_node::{label_strs, DepKind, DepNode, DepNodeExt}; +pub use dep_node::{label_strs, DepKind, DepKindStruct, DepNode, DepNodeExt}; crate use dep_node::{make_compile_codegen_unit, make_compile_mono_item}; pub type DepGraph = rustc_query_system::dep_graph::DepGraph; @@ -24,29 +24,8 @@ pub type EdgeFilter = rustc_query_system::dep_graph::debug::EdgeFilter; impl rustc_query_system::dep_graph::DepKind for DepKind { const NULL: Self = DepKind::Null; - #[inline(always)] - fn fingerprint_style(&self) -> rustc_query_system::dep_graph::FingerprintStyle { - DepKind::fingerprint_style(self) - } - - #[inline(always)] - fn is_eval_always(&self) -> bool { - self.is_eval_always - } - - #[inline(always)] - fn has_params(&self) -> bool { - self.has_params - } - fn debug_node(node: &DepNode, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}", node.kind)?; - - if !node.kind.has_params && !node.kind.is_anon { - return Ok(()); - } - - write!(f, "(")?; + write!(f, "{:?}(", node.kind)?; ty::tls::with_opt(|opt_tcx| { if let Some(tcx) = opt_tcx { @@ -110,4 +89,51 @@ impl<'tcx> DepContext for TyCtxt<'tcx> { fn sess(&self) -> &Session { self.sess } + + #[inline(always)] + fn fingerprint_style(&self, kind: DepKind) -> rustc_query_system::dep_graph::FingerprintStyle { + kind.fingerprint_style(*self) + } + + #[inline(always)] + fn is_eval_always(&self, kind: DepKind) -> bool { + self.query_kind(kind).is_eval_always + } + + fn try_force_from_dep_node(&self, dep_node: DepNode) -> bool { + debug!("try_force_from_dep_node({:?}) --- trying to force", dep_node); + + // We must avoid ever having to call `force_from_dep_node()` for a + // `DepNode::codegen_unit`: + // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we + // would always end up having to evaluate the first caller of the + // `codegen_unit` query that *is* reconstructible. This might very well be + // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just + // to re-trigger calling the `codegen_unit` query with the right key. At + // that point we would already have re-done all the work we are trying to + // avoid doing in the first place. + // The solution is simple: Just explicitly call the `codegen_unit` query for + // each CGU, right after partitioning. This way `try_mark_green` will always + // hit the cache instead of having to go through `force_from_dep_node`. + // This assertion makes sure, we actually keep applying the solution above. + debug_assert!( + dep_node.kind != DepKind::codegen_unit, + "calling force_from_dep_node() on DepKind::codegen_unit" + ); + + let cb = self.query_kind(dep_node.kind); + if let Some(f) = cb.force_from_dep_node { + f(*self, dep_node); + true + } else { + false + } + } + + fn try_load_from_on_disk_cache(&self, dep_node: DepNode) { + let cb = self.query_kind(dep_node.kind); + if let Some(f) = cb.try_load_from_on_disk_cache { + f(*self, dep_node) + } + } } diff --git a/compiler/rustc_middle/src/hir/map/blocks.rs b/compiler/rustc_middle/src/hir/map/blocks.rs deleted file mode 100644 index 8efec8ef56..0000000000 --- a/compiler/rustc_middle/src/hir/map/blocks.rs +++ /dev/null @@ -1,239 +0,0 @@ -//! This module provides a simplified abstraction for working with -//! code blocks identified by their integer `NodeId`. In particular, -//! it captures a common set of attributes that all "function-like -//! things" (represented by `FnLike` instances) share. For example, -//! all `FnLike` instances have a type signature (be it explicit or -//! inferred). And all `FnLike` instances have a body, i.e., the code -//! that is run when the function-like thing it represents is invoked. -//! -//! With the above abstraction in place, one can treat the program -//! text as a collection of blocks of code (and most such blocks are -//! nested within a uniquely determined `FnLike`), and users can ask -//! for the `Code` associated with a particular NodeId. - -use crate::hir::map::Map; -use rustc_hir as hir; -use rustc_hir::intravisit::FnKind; -use rustc_hir::{Expr, FnDecl, Node}; -use rustc_span::symbol::Ident; -use rustc_span::Span; - -/// An FnLikeNode is a Node that is like a fn, in that it has a decl -/// and a body (as well as a NodeId, a span, etc). -/// -/// More specifically, it is one of either: -/// -/// - A function item, -/// - A closure expr (i.e., an ExprKind::Closure), or -/// - The default implementation for a trait method. -/// -/// To construct one, use the `Code::from_node` function. -#[derive(Copy, Clone, Debug)] -pub struct FnLikeNode<'a> { - node: Node<'a>, -} - -/// MaybeFnLike wraps a method that indicates if an object -/// corresponds to some FnLikeNode. -trait MaybeFnLike { - fn is_fn_like(&self) -> bool; -} - -impl MaybeFnLike for hir::Item<'_> { - fn is_fn_like(&self) -> bool { - matches!(self.kind, hir::ItemKind::Fn(..)) - } -} - -impl MaybeFnLike for hir::ImplItem<'_> { - fn is_fn_like(&self) -> bool { - matches!(self.kind, hir::ImplItemKind::Fn(..)) - } -} - -impl MaybeFnLike for hir::TraitItem<'_> { - fn is_fn_like(&self) -> bool { - matches!(self.kind, hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_))) - } -} - -impl MaybeFnLike for hir::Expr<'_> { - fn is_fn_like(&self) -> bool { - matches!(self.kind, hir::ExprKind::Closure(..)) - } -} - -/// Carries either an FnLikeNode or an Expr, as these are the two -/// constructs that correspond to "code" (as in, something from which -/// we can construct a control-flow graph). -#[derive(Copy, Clone)] -pub enum Code<'a> { - FnLike(FnLikeNode<'a>), - Expr(&'a Expr<'a>), -} - -impl<'a> Code<'a> { - pub fn id(&self) -> hir::HirId { - match *self { - Code::FnLike(node) => node.id(), - Code::Expr(block) => block.hir_id, - } - } - - /// Attempts to construct a Code from presumed FnLike or Expr node input. - pub fn from_node(map: &Map<'a>, id: hir::HirId) -> Option> { - match map.get(id) { - Node::Block(_) => { - // Use the parent, hopefully an expression node. - Code::from_node(map, map.get_parent_node(id)) - } - Node::Expr(expr) => Some(Code::Expr(expr)), - node => FnLikeNode::from_node(node).map(Code::FnLike), - } - } -} - -/// These are all the components one can extract from a fn item for -/// use when implementing FnLikeNode operations. -struct ItemFnParts<'a> { - ident: Ident, - decl: &'a hir::FnDecl<'a>, - header: hir::FnHeader, - vis: &'a hir::Visibility<'a>, - generics: &'a hir::Generics<'a>, - body: hir::BodyId, - id: hir::HirId, - span: Span, -} - -/// These are all the components one can extract from a closure expr -/// for use when implementing FnLikeNode operations. -struct ClosureParts<'a> { - decl: &'a FnDecl<'a>, - body: hir::BodyId, - id: hir::HirId, - span: Span, -} - -impl<'a> ClosureParts<'a> { - fn new(d: &'a FnDecl<'a>, b: hir::BodyId, id: hir::HirId, s: Span) -> Self { - ClosureParts { decl: d, body: b, id, span: s } - } -} - -impl<'a> FnLikeNode<'a> { - /// Attempts to construct a FnLikeNode from presumed FnLike node input. - pub fn from_node(node: Node<'_>) -> Option> { - let fn_like = match node { - Node::Item(item) => item.is_fn_like(), - Node::TraitItem(tm) => tm.is_fn_like(), - Node::ImplItem(it) => it.is_fn_like(), - Node::Expr(e) => e.is_fn_like(), - _ => false, - }; - fn_like.then_some(FnLikeNode { node }) - } - - pub fn body(self) -> hir::BodyId { - self.handle( - |i: ItemFnParts<'a>| i.body, - |_, _, _: &'a hir::FnSig<'a>, _, body: hir::BodyId, _| body, - |c: ClosureParts<'a>| c.body, - ) - } - - pub fn decl(self) -> &'a FnDecl<'a> { - self.handle( - |i: ItemFnParts<'a>| &*i.decl, - |_, _, sig: &'a hir::FnSig<'a>, _, _, _| &sig.decl, - |c: ClosureParts<'a>| c.decl, - ) - } - - pub fn span(self) -> Span { - self.handle( - |i: ItemFnParts<'_>| i.span, - |_, _, _: &'a hir::FnSig<'a>, _, _, span| span, - |c: ClosureParts<'_>| c.span, - ) - } - - pub fn id(self) -> hir::HirId { - self.handle( - |i: ItemFnParts<'_>| i.id, - |id, _, _: &'a hir::FnSig<'a>, _, _, _| id, - |c: ClosureParts<'_>| c.id, - ) - } - - pub fn constness(self) -> hir::Constness { - self.kind().header().map_or(hir::Constness::NotConst, |header| header.constness) - } - - pub fn asyncness(self) -> hir::IsAsync { - self.kind().header().map_or(hir::IsAsync::NotAsync, |header| header.asyncness) - } - - pub fn unsafety(self) -> hir::Unsafety { - self.kind().header().map_or(hir::Unsafety::Normal, |header| header.unsafety) - } - - pub fn kind(self) -> FnKind<'a> { - let item = |p: ItemFnParts<'a>| -> FnKind<'a> { - FnKind::ItemFn(p.ident, p.generics, p.header, p.vis) - }; - let closure = |_: ClosureParts<'a>| FnKind::Closure; - let method = - |_, ident: Ident, sig: &'a hir::FnSig<'a>, vis, _, _| FnKind::Method(ident, sig, vis); - self.handle(item, method, closure) - } - - fn handle(self, item_fn: I, method: M, closure: C) -> A - where - I: FnOnce(ItemFnParts<'a>) -> A, - M: FnOnce( - hir::HirId, - Ident, - &'a hir::FnSig<'a>, - Option<&'a hir::Visibility<'a>>, - hir::BodyId, - Span, - ) -> A, - C: FnOnce(ClosureParts<'a>) -> A, - { - match self.node { - Node::Item(i) => match i.kind { - hir::ItemKind::Fn(ref sig, ref generics, block) => item_fn(ItemFnParts { - id: i.hir_id(), - ident: i.ident, - decl: &sig.decl, - body: block, - vis: &i.vis, - span: i.span, - header: sig.header, - generics, - }), - _ => bug!("item FnLikeNode that is not fn-like"), - }, - Node::TraitItem(ti) => match ti.kind { - hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { - method(ti.hir_id(), ti.ident, sig, None, body, ti.span) - } - _ => bug!("trait method FnLikeNode that is not fn-like"), - }, - Node::ImplItem(ii) => match ii.kind { - hir::ImplItemKind::Fn(ref sig, body) => { - method(ii.hir_id(), ii.ident, sig, Some(&ii.vis), body, ii.span) - } - _ => bug!("impl method FnLikeNode that is not fn-like"), - }, - Node::Expr(e) => match e.kind { - hir::ExprKind::Closure(_, ref decl, block, _fn_decl_span, _gen) => { - closure(ClosureParts::new(&decl, block, e.hir_id, e.span)) - } - _ => bug!("expr FnLikeNode that is not fn-like"), - }, - _ => bug!("other FnLikeNode that is not fn-like"), - } - } -} diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index e6f56b0be9..d9d0781b37 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -1,6 +1,4 @@ -use self::collector::NodeCollector; - -use crate::hir::{AttributeMap, IndexedHir, ModuleItems, Owner}; +use crate::hir::{ModuleItems, Owner}; use crate::ty::TyCtxt; use rustc_ast as ast; use rustc_data_structures::fingerprint::Fingerprint; @@ -22,9 +20,6 @@ use rustc_span::Span; use rustc_target::spec::abi::Abi; use std::collections::VecDeque; -pub mod blocks; -mod collector; - fn fn_decl<'hir>(node: Node<'hir>) -> Option<&'hir FnDecl<'hir>> { match node { Node::Item(Item { kind: ItemKind::Fn(sig, _, _), .. }) @@ -166,8 +161,8 @@ impl<'hir> Map<'hir> { pub fn items(&self) -> impl Iterator> + 'hir { let krate = self.krate(); - krate.owners.iter().filter_map(|owner| match owner.as_ref()? { - OwnerNode::Item(item) => Some(*item), + krate.owners.iter().filter_map(|owner| match owner.as_ref()?.node() { + OwnerNode::Item(item) => Some(item), _ => None, }) } @@ -271,7 +266,15 @@ impl<'hir> Map<'hir> { }; DefKind::Ctor(ctor_of, def::CtorKind::from_hir(variant_data)) } - Node::AnonConst(_) => DefKind::AnonConst, + Node::AnonConst(_) => { + let inline = match self.find(self.get_parent_node(hir_id)) { + Some(Node::Expr(&Expr { + kind: ExprKind::ConstBlock(ref anon_const), .. + })) if anon_const.hir_id == hir_id => true, + _ => false, + }; + if inline { DefKind::InlineConst } else { DefKind::AnonConst } + } Node::Field(_) => DefKind::Field, Node::Expr(expr) => match expr.kind { ExprKind::Closure(.., None) => DefKind::Closure, @@ -318,7 +321,7 @@ impl<'hir> Map<'hir> { } pub fn get_parent_node(&self, hir_id: HirId) -> HirId { - self.find_parent_node(hir_id).unwrap_or(CRATE_HIR_ID) + self.find_parent_node(hir_id).unwrap() } /// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found. @@ -381,7 +384,7 @@ impl<'hir> Map<'hir> { } pub fn body(&self, id: BodyId) -> &'hir Body<'hir> { - self.tcx.hir_owner_nodes(id.hir_id.owner).unwrap().bodies.get(&id.hir_id.local_id).unwrap() + self.tcx.hir_owner_nodes(id.hir_id.owner).unwrap().bodies[&id.hir_id.local_id] } pub fn fn_decl_by_hir_id(&self, hir_id: HirId) -> Option<&'hir FnDecl<'hir>> { @@ -443,7 +446,7 @@ impl<'hir> Map<'hir> { pub fn body_param_names(&self, id: BodyId) -> impl Iterator + 'hir { self.body(id).params.iter().map(|arg| match arg.pat.kind { PatKind::Binding(_, _, ident, _) => ident, - _ => Ident::new(kw::Empty, rustc_span::DUMMY_SP), + _ => Ident::empty(), }) } @@ -495,11 +498,35 @@ impl<'hir> Map<'hir> { /// crate. If you would prefer to iterate over the bodies /// themselves, you can do `self.hir().krate().body_ids.iter()`. pub fn body_owners(self) -> impl Iterator + 'hir { - self.krate().bodies.keys().map(move |&body_id| self.body_owner_def_id(body_id)) + self.krate() + .owners + .iter_enumerated() + .flat_map(move |(owner, owner_info)| { + let bodies = &owner_info.as_ref()?.nodes.bodies; + Some(bodies.iter().map(move |&(local_id, _)| { + let hir_id = HirId { owner, local_id }; + let body_id = BodyId { hir_id }; + self.body_owner_def_id(body_id) + })) + }) + .flatten() } pub fn par_body_owners(self, f: F) { - par_for_each_in(&self.krate().bodies, |(&body_id, _)| f(self.body_owner_def_id(body_id))); + use rustc_data_structures::sync::{par_iter, ParallelIterator}; + #[cfg(parallel_compiler)] + use rustc_rayon::iter::IndexedParallelIterator; + + par_iter(&self.krate().owners.raw).enumerate().for_each(|(owner, owner_info)| { + let owner = LocalDefId::new(owner); + if let Some(owner_info) = owner_info { + par_iter(owner_info.nodes.bodies.range(..)).for_each(|(local_id, _)| { + let hir_id = HirId { owner, local_id: *local_id }; + let body_id = BodyId { hir_id }; + f(self.body_owner_def_id(body_id)) + }) + } + }); } pub fn ty_param_owner(&self, id: HirId) -> HirId { @@ -551,9 +578,14 @@ impl<'hir> Map<'hir> { /// Walks the attributes in a crate. pub fn walk_attributes(self, visitor: &mut impl Visitor<'hir>) { let krate = self.krate(); - for (&id, attrs) in krate.attrs.iter() { - for a in *attrs { - visitor.visit_attribute(id, a) + for (owner, info) in krate.owners.iter_enumerated() { + if let Some(info) = info { + for (local_id, attrs) in info.attrs.map.iter() { + let id = HirId { owner, local_id: *local_id }; + for a in *attrs { + visitor.visit_attribute(id, a) + } + } } } } @@ -572,7 +604,7 @@ impl<'hir> Map<'hir> { { let krate = self.krate(); for owner in krate.owners.iter().filter_map(Option::as_ref) { - match owner { + match owner.node() { OwnerNode::Item(item) => visitor.visit_item(item), OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item), OwnerNode::ImplItem(item) => visitor.visit_impl_item(item), @@ -588,7 +620,7 @@ impl<'hir> Map<'hir> { V: itemlikevisit::ParItemLikeVisitor<'hir> + Sync + Send, { let krate = self.krate(); - par_for_each_in(&krate.owners.raw, |owner| match owner.as_ref() { + par_for_each_in(&krate.owners.raw, |owner| match owner.as_ref().map(OwnerInfo::node) { Some(OwnerNode::Item(item)) => visitor.visit_item(item), Some(OwnerNode::ForeignItem(item)) => visitor.visit_foreign_item(item), Some(OwnerNode::ImplItem(item)) => visitor.visit_impl_item(item), @@ -839,21 +871,21 @@ impl<'hir> Map<'hir> { pub fn expect_item(&self, id: HirId) -> &'hir Item<'hir> { match self.tcx.hir_owner(id.expect_owner()) { - Some(Owner { node: OwnerNode::Item(item) }) => item, + Some(Owner { node: OwnerNode::Item(item), .. }) => item, _ => bug!("expected item, found {}", self.node_to_string(id)), } } pub fn expect_impl_item(&self, id: HirId) -> &'hir ImplItem<'hir> { match self.tcx.hir_owner(id.expect_owner()) { - Some(Owner { node: OwnerNode::ImplItem(item) }) => item, + Some(Owner { node: OwnerNode::ImplItem(item), .. }) => item, _ => bug!("expected impl item, found {}", self.node_to_string(id)), } } pub fn expect_trait_item(&self, id: HirId) -> &'hir TraitItem<'hir> { match self.tcx.hir_owner(id.expect_owner()) { - Some(Owner { node: OwnerNode::TraitItem(item) }) => item, + Some(Owner { node: OwnerNode::TraitItem(item), .. }) => item, _ => bug!("expected trait item, found {}", self.node_to_string(id)), } } @@ -867,7 +899,7 @@ impl<'hir> Map<'hir> { pub fn expect_foreign_item(&self, id: HirId) -> &'hir ForeignItem<'hir> { match self.tcx.hir_owner(id.expect_owner()) { - Some(Owner { node: OwnerNode::ForeignItem(item) }) => item, + Some(Owner { node: OwnerNode::ForeignItem(item), .. }) => item, _ => bug!("expected foreign item, found {}", self.node_to_string(id)), } } @@ -1032,42 +1064,10 @@ impl<'hir> intravisit::Map<'hir> for Map<'hir> { } } -pub(super) fn index_hir<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> &'tcx IndexedHir<'tcx> { - let _prof_timer = tcx.sess.prof.generic_activity("build_hir_map"); - - // We can access untracked state since we are an eval_always query. - let hcx = tcx.create_stable_hashing_context(); - let mut collector = NodeCollector::root( - tcx.sess, - &**tcx.arena, - tcx.untracked_crate, - &tcx.untracked_resolutions.definitions, - hcx, - ); - let top_mod = tcx.untracked_crate.module(); - collector.visit_mod(top_mod, top_mod.inner, CRATE_HIR_ID); - - let map = collector.finalize_and_compute_crate_hash(); - tcx.arena.alloc(map) -} - pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh { - assert_eq!(crate_num, LOCAL_CRATE); - - // We can access untracked state since we are an eval_always query. - let mut hcx = tcx.create_stable_hashing_context(); - - let mut hir_body_nodes: Vec<_> = tcx - .index_hir(()) - .map - .iter_enumerated() - .filter_map(|(def_id, hod)| { - let def_path_hash = tcx.untracked_resolutions.definitions.def_path_hash(def_id); - let hash = hod.as_ref()?.hash; - Some((def_path_hash, hash, def_id)) - }) - .collect(); - hir_body_nodes.sort_unstable_by_key(|bn| bn.0); + debug_assert_eq!(crate_num, LOCAL_CRATE); + let krate = tcx.hir_crate(()); + let hir_body_hash = krate.hir_hash; let upstream_crates = upstream_crates(tcx); @@ -1087,20 +1087,27 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh { source_file_names.sort_unstable(); + let mut hcx = tcx.create_stable_hashing_context(); let mut stable_hasher = StableHasher::new(); - for (def_path_hash, fingerprint, def_id) in hir_body_nodes.iter() { - def_path_hash.0.hash_stable(&mut hcx, &mut stable_hasher); - fingerprint.hash_stable(&mut hcx, &mut stable_hasher); - AttributeMap { map: &tcx.untracked_crate.attrs, prefix: *def_id } - .hash_stable(&mut hcx, &mut stable_hasher); - if tcx.sess.opts.debugging_opts.incremental_relative_spans { - let span = tcx.untracked_resolutions.definitions.def_span(*def_id); - debug_assert_eq!(span.parent(), None); - span.hash_stable(&mut hcx, &mut stable_hasher); - } - } + hir_body_hash.hash_stable(&mut hcx, &mut stable_hasher); upstream_crates.hash_stable(&mut hcx, &mut stable_hasher); source_file_names.hash_stable(&mut hcx, &mut stable_hasher); + if tcx.sess.opts.debugging_opts.incremental_relative_spans { + let definitions = &tcx.untracked_resolutions.definitions; + let mut owner_spans: Vec<_> = krate + .owners + .iter_enumerated() + .filter_map(|(def_id, info)| { + let _ = info.as_ref()?; + let def_path_hash = definitions.def_path_hash(def_id); + let span = definitions.def_span(def_id); + debug_assert_eq!(span.parent(), None); + Some((def_path_hash, span)) + }) + .collect(); + owner_spans.sort_unstable_by_key(|bn| bn.0); + owner_spans.hash_stable(&mut hcx, &mut stable_hasher); + } tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher); tcx.sess.local_stable_crate_id().hash_stable(&mut hcx, &mut stable_hasher); diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 5016c5ce95..95d7273b17 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -8,28 +8,12 @@ pub mod place; use crate::ty::query::Providers; use crate::ty::TyCtxt; -use rustc_ast::Attribute; 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::LocalDefId; use rustc_hir::*; -use rustc_index::vec::{Idx, IndexVec}; use rustc_query_system::ich::StableHashingContext; use rustc_span::DUMMY_SP; -use std::collections::BTreeMap; - -/// Result of HIR indexing. -#[derive(Debug)] -pub struct IndexedHir<'hir> { - /// Contents of the HIR owned by each definition. None for definitions that are not HIR owners. - // The `mut` comes from construction time, and is harmless since we only ever hand out - // immutable refs to IndexedHir. - map: IndexVec>>, - /// Map from each owner to its parent's HirId inside another owner. - // This map is separate from `map` to eventually allow for per-owner indexing. - parenting: FxHashMap, -} /// Top-level HIR node for current owner. This only contains the node for which /// `HirId::local_id == 0`, and excludes bodies. @@ -39,85 +23,14 @@ pub struct IndexedHir<'hir> { #[derive(Copy, Clone, Debug)] pub struct Owner<'tcx> { node: OwnerNode<'tcx>, + hash_without_bodies: Fingerprint, } impl<'a, 'tcx> HashStable> for Owner<'tcx> { + #[inline] fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let Owner { node } = self; - hcx.while_hashing_hir_bodies(false, |hcx| node.hash_stable(hcx, hasher)); - } -} - -/// HIR node coupled with its parent's id in the same HIR owner. -/// -/// The parent is trash when the node is a HIR owner. -#[derive(Clone, Debug)] -pub struct ParentedNode<'tcx> { - parent: ItemLocalId, - node: Node<'tcx>, -} - -#[derive(Debug)] -pub struct OwnerNodes<'tcx> { - /// Pre-computed hash of the full HIR. - hash: Fingerprint, - /// Full HIR for the current owner. - // The zeroth node's parent is trash, but is never accessed. - nodes: IndexVec>>, - /// Content of local bodies. - bodies: FxHashMap>, -} - -impl<'a, 'tcx> HashStable> for OwnerNodes<'tcx> { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - // We ignore the `nodes` and `bodies` fields since these refer to information included in - // `hash` which is hashed in the collector and used for the crate hash. - let OwnerNodes { hash, nodes: _, bodies: _ } = *self; - hash.hash_stable(hcx, hasher); - } -} - -/// Attributes owner by a HIR owner. It is build as a slice inside the attributes map, restricted -/// to the nodes whose `HirId::owner` is `prefix`. -#[derive(Copy, Clone)] -pub struct AttributeMap<'tcx> { - map: &'tcx BTreeMap, - prefix: LocalDefId, -} - -impl<'a, 'tcx> HashStable> for AttributeMap<'tcx> { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let range = self.range(); - - range.clone().count().hash_stable(hcx, hasher); - for (key, value) in range { - key.hash_stable(hcx, hasher); - value.hash_stable(hcx, hasher); - } - } -} - -impl<'tcx> std::fmt::Debug for AttributeMap<'tcx> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("AttributeMap") - .field("prefix", &self.prefix) - .field("range", &&self.range().collect::>()[..]) - .finish() - } -} - -impl<'tcx> AttributeMap<'tcx> { - fn get(&self, id: ItemLocalId) -> &'tcx [Attribute] { - self.map.get(&HirId { owner: self.prefix, local_id: id }).copied().unwrap_or(&[]) - } - - fn range(&self) -> std::collections::btree_map::Range<'_, rustc_hir::HirId, &[Attribute]> { - let local_zero = ItemLocalId::from_u32(0); - let range = HirId { owner: self.prefix, local_id: local_zero }..HirId { - owner: LocalDefId { local_def_index: self.prefix.local_def_index + 1 }, - local_id: local_zero, - }; - self.map.range(range) + let Owner { node: _, hash_without_bodies } = self; + hash_without_bodies.hash_stable(hcx, hasher) } } @@ -149,21 +62,32 @@ pub fn provide(providers: &mut Providers) { hir.local_def_id(hir.get_module_parent_node(hir.local_def_id_to_hir_id(id))) }; providers.hir_crate = |tcx, ()| tcx.untracked_crate; - providers.index_hir = map::index_hir; providers.crate_hash = map::crate_hash; providers.hir_module_items = map::hir_module_items; providers.hir_owner = |tcx, id| { - let owner = tcx.index_hir(()).map[id].as_ref()?; - let node = owner.nodes[ItemLocalId::new(0)].as_ref().unwrap().node; - let node = node.as_owner().unwrap(); // Indexing must ensure it is an OwnerNode. - Some(Owner { node }) + let owner = tcx.hir_crate(()).owners[id].as_ref()?; + let node = owner.node(); + Some(Owner { node, hash_without_bodies: owner.nodes.hash_without_bodies }) }; - providers.hir_owner_nodes = |tcx, id| tcx.index_hir(()).map[id].as_deref(); + providers.hir_owner_nodes = |tcx, id| tcx.hir_crate(()).owners[id].as_ref().map(|i| &i.nodes); providers.hir_owner_parent = |tcx, id| { - let index = tcx.index_hir(()); - index.parenting.get(&id).copied().unwrap_or(CRATE_HIR_ID) + // Accessing the def_key is ok since its value is hashed as part of `id`'s DefPathHash. + let parent = tcx.untracked_resolutions.definitions.def_key(id).parent; + let parent = parent.map_or(CRATE_HIR_ID, |local_def_index| { + let def_id = LocalDefId { local_def_index }; + let mut parent_hir_id = + tcx.untracked_resolutions.definitions.local_def_id_to_hir_id(def_id); + if let Some(local_id) = + tcx.hir_crate(()).owners[parent_hir_id.owner].as_ref().unwrap().parenting.get(&id) + { + parent_hir_id.local_id = *local_id; + } + parent_hir_id + }); + parent }; - providers.hir_attrs = |tcx, id| AttributeMap { map: &tcx.untracked_crate.attrs, prefix: id }; + providers.hir_attrs = + |tcx, id| tcx.hir_crate(()).owners[id].as_ref().map_or(AttributeMap::EMPTY, |o| &o.attrs); providers.source_span = |tcx, def_id| tcx.resolutions(()).definitions.def_span(def_id); providers.def_span = |tcx, def_id| tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP); providers.fn_arg_names = |tcx, id| { diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index e41f5add45..9ce9f65a49 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -30,6 +30,7 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(core_intrinsics)] +#![feature(derive_default_enum)] #![feature(discriminant_kind)] #![feature(exhaustive_patterns)] #![feature(if_let_guard)] @@ -39,6 +40,7 @@ #![feature(new_uninit)] #![feature(nll)] #![feature(once_cell)] +#![feature(let_else)] #![feature(min_specialization)] #![feature(trusted_len)] #![feature(in_band_lifetimes)] diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 1eba2994ed..881b14278e 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -248,8 +248,12 @@ pub fn struct_lint_level<'s, 'd>( (Level::Warn, None) => sess.struct_warn(""), (Level::ForceWarn, Some(span)) => sess.struct_span_force_warn(span, ""), (Level::ForceWarn, None) => sess.struct_force_warn(""), - (Level::Deny | Level::Forbid, Some(span)) => sess.struct_span_err(span, ""), - (Level::Deny | Level::Forbid, None) => sess.struct_err(""), + (Level::Deny | Level::Forbid, Some(span)) => { + let mut builder = sess.diagnostic().struct_err_lint(""); + builder.set_span(span); + builder + } + (Level::Deny | Level::Forbid, None) => sess.diagnostic().struct_err_lint(""), }; // If this code originates in a foreign macro, aka something that this crate @@ -391,7 +395,7 @@ pub fn in_external_macro(sess: &Session, span: Span) -> bool { match expn_data.kind { ExpnKind::Inlined | ExpnKind::Root - | ExpnKind::Desugaring(DesugaringKind::ForLoop(_) | DesugaringKind::WhileLoop) => false, + | ExpnKind::Desugaring(DesugaringKind::ForLoop | DesugaringKind::WhileLoop) => false, ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external" ExpnKind::Macro(MacroKind::Bang, _) => { // Dummy span for the `def_site` means it's an external macro. diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 597622b2eb..8a5fc5feeb 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -3,7 +3,7 @@ pub use self::StabilityLevel::*; -use crate::ty::{self, TyCtxt}; +use crate::ty::{self, DefIdTree, TyCtxt}; use rustc_ast::NodeId; use rustc_attr::{self as attr, ConstStability, Deprecation, Stability}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -90,6 +90,7 @@ pub fn report_unstable( feature: Symbol, reason: Option, issue: Option, + suggestion: Option<(Span, String, String, Applicability)>, is_soft: bool, span: Span, soft_handler: impl FnOnce(&'static Lint, Span, &str), @@ -116,8 +117,12 @@ pub fn report_unstable( if is_soft { soft_handler(SOFT_UNSTABLE, span, &msg) } else { - feature_err_issue(&sess.parse_sess, feature, span, GateIssue::Library(issue), &msg) - .emit(); + let mut err = + feature_err_issue(&sess.parse_sess, feature, span, GateIssue::Library(issue), &msg); + if let Some((inner_types, ref msg, sugg, applicability)) = suggestion { + err.span_suggestion(inner_types, msg, sugg, applicability); + } + err.emit(); } } } @@ -271,7 +276,13 @@ pub enum EvalResult { Allow, /// We cannot use the item because it is unstable and we did not provide the /// corresponding feature gate. - Deny { feature: Symbol, reason: Option, issue: Option, is_soft: bool }, + Deny { + feature: Symbol, + reason: Option, + issue: Option, + suggestion: Option<(Span, String, String, Applicability)>, + is_soft: bool, + }, /// The item does not have the `#[stable]` or `#[unstable]` marker assigned. Unmarked, } @@ -292,6 +303,32 @@ fn skip_stability_check_due_to_privacy(tcx: TyCtxt<'_>, def_id: DefId) -> bool { } } +// See issue #83250. +fn suggestion_for_allocator_api( + tcx: TyCtxt<'_>, + def_id: DefId, + span: Span, + feature: Symbol, +) -> Option<(Span, String, String, Applicability)> { + if feature == sym::allocator_api { + if let Some(trait_) = tcx.parent(def_id) { + if tcx.is_diagnostic_item(sym::Vec, trait_) { + let sm = tcx.sess.parse_sess.source_map(); + let inner_types = sm.span_extend_to_prev_char(span, '<', true); + if let Ok(snippet) = sm.span_to_snippet(inner_types) { + return Some(( + inner_types, + "consider wrapping the inner types in tuple".to_string(), + format!("({})", snippet), + Applicability::MaybeIncorrect, + )); + } + } + } + } + None +} + impl<'tcx> TyCtxt<'tcx> { /// Evaluates the stability of an item. /// @@ -406,7 +443,8 @@ impl<'tcx> TyCtxt<'tcx> { } } - EvalResult::Deny { feature, reason, issue, is_soft } + let suggestion = suggestion_for_allocator_api(self, def_id, span, feature); + EvalResult::Deny { feature, reason, issue, suggestion, is_soft } } Some(_) => { // Stable APIs are always ok to call and deprecated APIs are @@ -457,9 +495,16 @@ impl<'tcx> TyCtxt<'tcx> { }; match self.eval_stability(def_id, id, span, method_span) { EvalResult::Allow => {} - EvalResult::Deny { feature, reason, issue, is_soft } => { - report_unstable(self.sess, feature, reason, issue, is_soft, span, soft_handler) - } + EvalResult::Deny { feature, reason, issue, suggestion, is_soft } => report_unstable( + self.sess, + feature, + reason, + issue, + suggestion, + is_soft, + span, + soft_handler, + ), EvalResult::Unmarked => unmarked(span, def_id), } } diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 9472a287e5..7a51bb4a1f 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -538,12 +538,12 @@ impl InterpError<'_> { /// To avoid performance issues, there are places where we want to be sure to never raise these formatting errors, /// so this method lets us detect them and `bug!` on unexpected errors. pub fn formatted_string(&self) -> bool { - match self { + matches!( + self, InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_)) - | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure { .. }) - | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_)) => true, - _ => false, - } + | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure { .. }) + | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_)) + ) } /// Should this error be reported as a hard error, preventing compilation, or a soft error, diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 971556d446..4210e07d27 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2246,8 +2246,12 @@ pub enum BinOp { /// The `*` operator (multiplication) Mul, /// The `/` operator (division) + /// + /// Division by zero is UB. Div, /// The `%` operator (modulus) + /// + /// Using zero as the modulus (second operand) is UB. Rem, /// The `^` operator (bitwise xor) BitXor, @@ -2256,8 +2260,12 @@ pub enum BinOp { /// The `|` operator (bitwise or) BitOr, /// The `<<` operator (shift left) + /// + /// The offset is truncated to the size of the first operand before shifting. Shl, /// The `>>` operator (shift right) + /// + /// The offset is truncated to the size of the first operand before shifting. Shr, /// The `==` operator (equality) Eq, @@ -2665,7 +2673,7 @@ impl<'tcx> UserTypeProjections { mut self, mut f: impl FnMut(UserTypeProjection) -> UserTypeProjection, ) -> Self { - self.contents = self.contents.drain(..).map(|(proj, span)| (f(proj), span)).collect(); + self.contents = self.contents.into_iter().map(|(proj, span)| (f(proj), span)).collect(); self } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index db98cb7634..8e1b887f87 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -71,6 +71,7 @@ pub enum PassWhere { /// or `typeck` appears in the name. /// - `foo & nll | bar & typeck` == match if `foo` and `nll` both appear in the name /// or `typeck` and `bar` both appear in the name. +#[inline] pub fn dump_mir<'tcx, F>( tcx: TyCtxt<'tcx>, pass_num: Option<&dyn Display>, @@ -957,7 +958,7 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn Write) -> io::Res write!(w, "static {}", if tcx.is_mutable_static(def_id) { "mut " } else { "" })? } (_, _) if is_function => write!(w, "fn ")?, - (DefKind::AnonConst, _) => {} // things like anon const, not an item + (DefKind::AnonConst | DefKind::InlineConst, _) => {} // things like anon const, not an item _ => bug!("Unexpected def kind {:?}", kind), } diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index d5541d7890..cb3f385095 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -225,6 +225,7 @@ pub struct BorrowCheckResult<'tcx> { pub struct ConstQualifs { pub has_mut_interior: bool, pub needs_drop: bool, + pub needs_non_const_drop: bool, pub custom_eq: bool, pub error_occured: Option, } diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs index 42683dac42..1260c691e7 100644 --- a/compiler/rustc_middle/src/mir/spanview.rs +++ b/compiler/rustc_middle/src/mir/spanview.rs @@ -632,11 +632,11 @@ fn tooltip<'tcx>( for statement in statements { let source_range = source_range_no_file(tcx, &statement.source_info.span); text.push(format!( - "\n{}{}: {}: {}", + "\n{}{}: {}: {:?}", TOOLTIP_INDENT, source_range, statement_kind_name(&statement), - format!("{:?}", statement) + statement )); } if let Some(term) = terminator { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 4145cbd424..ca93efbf19 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -36,18 +36,9 @@ rustc_queries! { /// prefer wrappers like `tcx.visit_all_items_in_krate()`. query hir_crate(key: ()) -> &'tcx Crate<'tcx> { eval_always - no_hash desc { "get the crate HIR" } } - /// The indexed HIR. This can be conveniently accessed by `tcx.hir()`. - /// Avoid calling this query directly. - query index_hir(_: ()) -> &'tcx crate::hir::IndexedHir<'tcx> { - eval_always - no_hash - desc { "index HIR" } - } - /// The items in a module. /// /// This can be conveniently accessed by `tcx.hir().visit_item_likes_in_module`. @@ -62,7 +53,6 @@ rustc_queries! { /// This can be conveniently accessed by methods on `tcx.hir()`. /// Avoid calling this query directly. query hir_owner(key: LocalDefId) -> Option> { - eval_always desc { |tcx| "HIR owner of `{}`", tcx.def_path_str(key.to_def_id()) } } @@ -71,7 +61,6 @@ rustc_queries! { /// This can be conveniently accessed by methods on `tcx.hir()`. /// Avoid calling this query directly. query hir_owner_parent(key: LocalDefId) -> hir::HirId { - eval_always desc { |tcx| "HIR parent of `{}`", tcx.def_path_str(key.to_def_id()) } } @@ -79,8 +68,7 @@ rustc_queries! { /// /// This can be conveniently accessed by methods on `tcx.hir()`. /// Avoid calling this query directly. - query hir_owner_nodes(key: LocalDefId) -> Option<&'tcx crate::hir::OwnerNodes<'tcx>> { - eval_always + query hir_owner_nodes(key: LocalDefId) -> Option<&'tcx hir::OwnerNodes<'tcx>> { desc { |tcx| "HIR owner items in `{}`", tcx.def_path_str(key.to_def_id()) } } @@ -88,8 +76,7 @@ rustc_queries! { /// /// This can be conveniently accessed by methods on `tcx.hir()`. /// Avoid calling this query directly. - query hir_attrs(key: LocalDefId) -> rustc_middle::hir::AttributeMap<'tcx> { - eval_always + query hir_attrs(key: LocalDefId) -> &'tcx hir::AttributeMap<'tcx> { desc { |tcx| "HIR owner attributes in `{}`", tcx.def_path_str(key.to_def_id()) } } @@ -120,6 +107,7 @@ rustc_queries! { /// 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) } + separate_provide_extern } query default_anon_const_substs(key: DefId) -> SubstsRef<'tcx> { @@ -141,6 +129,7 @@ rustc_queries! { path = tcx.def_path_str(key), } cache_on_disk_if { key.is_local() } + separate_provide_extern } query analysis(key: ()) -> Result<(), ErrorReported> { @@ -154,6 +143,7 @@ rustc_queries! { desc { |tcx| "computing generics of `{}`", tcx.def_path_str(key) } storage(ArenaCacheSelector<'tcx>) cache_on_disk_if { key.is_local() } + separate_provide_extern } /// Maps from the `DefId` of an item (trait/struct/enum/fn) to the @@ -194,6 +184,7 @@ rustc_queries! { /// Bounds from the parent (e.g. with nested impl trait) are not included. query explicit_item_bounds(key: DefId) -> &'tcx [(ty::Predicate<'tcx>, Span)] { desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) } + separate_provide_extern } /// Elaborated version of the predicates from `explicit_item_bounds`. @@ -222,6 +213,7 @@ rustc_queries! { query native_libraries(_: CrateNum) -> Lrc> { desc { "looking up the native libraries of a linked crate" } + separate_provide_extern } query lint_levels(_: ()) -> LintLevelMap { @@ -239,11 +231,13 @@ rustc_queries! { // This query reads from untracked data in definitions. eval_always desc { |tcx| "expansion that defined `{}`", tcx.def_path_str(key) } + separate_provide_extern } query is_panic_runtime(_: CrateNum) -> bool { fatal_cycle desc { "checking if the crate is_panic_runtime" } + separate_provide_extern } /// Fetch the THIR for a given body. If typeck for that body failed, returns an empty `Thir`. @@ -273,6 +267,7 @@ rustc_queries! { query mir_const_qualif(key: DefId) -> mir::ConstQualifs { desc { |tcx| "const checking `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } + separate_provide_extern } query mir_const_qualif_const_arg( key: (LocalDefId, DefId) @@ -309,6 +304,7 @@ rustc_queries! { desc { |tcx| "building an abstract representation for {}", tcx.def_path_str(key), } + separate_provide_extern } /// Try to build an abstract representation of the given constant. query thir_abstract_const_of_const_arg( @@ -342,6 +338,7 @@ rustc_queries! { ) -> &'tcx mir::Body<'tcx> { desc { |tcx| "caching mir of `{}` for CTFE", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } + separate_provide_extern } query mir_for_ctfe_of_const_arg(key: (LocalDefId, DefId)) -> &'tcx mir::Body<'tcx> { @@ -379,6 +376,7 @@ rustc_queries! { query optimized_mir(key: DefId) -> &'tcx mir::Body<'tcx> { desc { |tcx| "optimizing MIR for `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } + separate_provide_extern } /// Returns coverage summary info for a function, after executing the `InstrumentCoverage` @@ -417,6 +415,7 @@ rustc_queries! { query promoted_mir(key: DefId) -> &'tcx IndexVec> { desc { |tcx| "optimizing promoted MIR for `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } + separate_provide_extern } query promoted_mir_of_const_arg( key: (LocalDefId, DefId) @@ -475,12 +474,14 @@ rustc_queries! { /// Returns the predicates written explicitly by the user. query explicit_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { desc { |tcx| "computing explicit predicates of `{}`", tcx.def_path_str(key) } + separate_provide_extern } /// Returns the inferred outlives predicates (e.g., for `struct /// Foo<'a, T> { x: &'a T }`, this would return `T: 'a`). query inferred_outlives_of(key: DefId) -> &'tcx [(ty::Predicate<'tcx>, Span)] { desc { |tcx| "computing inferred outlives predicates of `{}`", tcx.def_path_str(key) } + separate_provide_extern } /// Maps from the `DefId` of a trait to the list of @@ -491,6 +492,7 @@ rustc_queries! { /// additional acyclicity requirements). query super_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { desc { |tcx| "computing the super predicates of `{}`", tcx.def_path_str(key) } + separate_provide_extern } /// The `Option` is the name of an associated type. If it is `None`, then this query @@ -516,12 +518,15 @@ rustc_queries! { query trait_def(key: DefId) -> ty::TraitDef { desc { |tcx| "computing trait definition for `{}`", tcx.def_path_str(key) } storage(ArenaCacheSelector<'tcx>) + separate_provide_extern } query adt_def(key: DefId) -> &'tcx ty::AdtDef { desc { |tcx| "computing ADT definition for `{}`", tcx.def_path_str(key) } + separate_provide_extern } query adt_destructor(key: DefId) -> Option { desc { |tcx| "computing `Drop` impl for `{}`", tcx.def_path_str(key) } + separate_provide_extern } // The cycle error here should be reported as an error by `check_representable`. @@ -550,10 +555,12 @@ rustc_queries! { /// `is_const_fn` function. query is_const_fn_raw(key: DefId) -> bool { desc { |tcx| "checking if item is const fn: `{}`", tcx.def_path_str(key) } + separate_provide_extern } query asyncness(key: DefId) -> hir::IsAsync { desc { |tcx| "checking if the function is async: `{}`", tcx.def_path_str(key) } + separate_provide_extern } /// Returns `true` if calls to the function may be promoted. @@ -570,16 +577,19 @@ rustc_queries! { /// Returns `true` if this is a foreign item (i.e., linked via `extern { ... }`). query is_foreign_item(key: DefId) -> bool { desc { |tcx| "checking if `{}` is a foreign item", tcx.def_path_str(key) } + separate_provide_extern } /// Returns `Some(mutability)` if the node pointed to by `def_id` is a static item. query static_mutability(def_id: DefId) -> Option { desc { |tcx| "looking up static mutability of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern } /// Returns `Some(generator_kind)` if the node pointed to by `def_id` is a generator. query generator_kind(def_id: DefId) -> Option { desc { |tcx| "looking up generator kind of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern } /// Gets a map with the variance of every item; use `item_variance` instead. @@ -591,6 +601,7 @@ rustc_queries! { /// Maps from the `DefId` of a type or region parameter to its (inferred) variance. query variances_of(def_id: DefId) -> &'tcx [ty::Variance] { desc { |tcx| "computing the variances of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern } /// Maps from thee `DefId` of a type to its (inferred) outlives. @@ -602,12 +613,14 @@ rustc_queries! { /// Maps from an impl/trait `DefId` to a list of the `DefId`s of its items. query associated_item_def_ids(key: DefId) -> &'tcx [DefId] { desc { |tcx| "collecting associated items of `{}`", tcx.def_path_str(key) } + separate_provide_extern } /// Maps from a trait item to the trait item "descriptor". query associated_item(key: DefId) -> ty::AssocItem { desc { |tcx| "computing associated item data for `{}`", tcx.def_path_str(key) } storage(ArenaCacheSelector<'tcx>) + separate_provide_extern } /// Collects the associated items defined on a trait or impl. @@ -620,9 +633,11 @@ rustc_queries! { /// Return `None` if this is an inherent impl. query impl_trait_ref(impl_id: DefId) -> Option> { desc { |tcx| "computing trait implemented by `{}`", tcx.def_path_str(impl_id) } + separate_provide_extern } query impl_polarity(impl_id: DefId) -> ty::ImplPolarity { desc { |tcx| "computing implementation polarity of `{}`", tcx.def_path_str(impl_id) } + separate_provide_extern } query issue33140_self_ty(key: DefId) -> Option> { @@ -634,7 +649,7 @@ rustc_queries! { /// Methods in these implementations don't need to be exported. query inherent_impls(key: DefId) -> &'tcx [DefId] { desc { |tcx| "collecting inherent impls for `{}`", tcx.def_path_str(key) } - eval_always + separate_provide_extern } /// The result of unsafety-checking this `LocalDefId`. @@ -671,11 +686,13 @@ rustc_queries! { desc { |tcx| "processing `{}`", tcx.def_path_str(key.to_def_id()) } } - /// The signature of functions. + /// Computes the signature of the function. query fn_sig(key: DefId) -> ty::PolyFnSig<'tcx> { desc { |tcx| "computing function signature of `{}`", tcx.def_path_str(key) } + separate_provide_extern } + /// Performs lint checking for the module. query lint_mod(key: LocalDefId) -> () { desc { |tcx| "linting {}", describe_as_module(key, tcx) } } @@ -685,6 +702,7 @@ rustc_queries! { desc { |tcx| "checking attributes in {}", describe_as_module(key, tcx) } } + /// Checks for uses of unstable APIs in the module. query check_mod_unstable_api_usage(key: LocalDefId) -> () { desc { |tcx| "checking for unstable API usage in {}", describe_as_module(key, tcx) } } @@ -728,10 +746,10 @@ rustc_queries! { } /// Caches `CoerceUnsized` kinds for impls on custom types. - query coerce_unsized_info(key: DefId) - -> ty::adjustment::CoerceUnsizedInfo { - desc { |tcx| "computing CoerceUnsized info for `{}`", tcx.def_path_str(key) } - } + query coerce_unsized_info(key: DefId) -> ty::adjustment::CoerceUnsizedInfo { + desc { |tcx| "computing CoerceUnsized info for `{}`", tcx.def_path_str(key) } + separate_provide_extern + } query typeck_item_bodies(_: ()) -> () { desc { "type-checking all item bodies" } @@ -778,10 +796,7 @@ rustc_queries! { /// additional requirements that the closure's creator must verify. query mir_borrowck(key: LocalDefId) -> &'tcx mir::BorrowCheckResult<'tcx> { desc { |tcx| "borrow-checking `{}`", tcx.def_path_str(key.to_def_id()) } - cache_on_disk_if(tcx, opt_result) { - tcx.is_closure(key.to_def_id()) - || opt_result.map_or(false, |r| !r.concrete_opaque_types.is_empty()) - } + cache_on_disk_if(tcx) { tcx.is_typeck_child(key.to_def_id()) } } query mir_borrowck_const_arg(key: (LocalDefId, DefId)) -> &'tcx mir::BorrowCheckResult<'tcx> { desc { @@ -794,18 +809,23 @@ rustc_queries! { /// Not meant to be used directly outside of coherence. query crate_inherent_impls(k: ()) -> CrateInherentImpls { storage(ArenaCacheSelector<'tcx>) - eval_always desc { "all inherent impls defined in crate" } } /// Checks all types in the crate for overlap in their inherent impls. Reports errors. /// Not meant to be used directly outside of coherence. - query crate_inherent_impls_overlap_check(_: ()) - -> () { - eval_always + query crate_inherent_impls_overlap_check(_: ()) -> () { desc { "check for overlap between inherent impls defined in this crate" } } + /// Checks whether all impls in the crate pass the overlap check, returning + /// which impls fail it. If all impls are correct, the returned slice is empty. + query orphan_check_crate(_: ()) -> &'tcx [LocalDefId] { + desc { + "checking whether the immpl in the this crate follow the orphan rules", + } + } + /// Check whether the function has any recursion that could cause the inliner to trigger /// a cycle. Returns the call stack causing the cycle. The call stack does not contain the /// current function, just all intermediate functions. @@ -914,6 +934,7 @@ rustc_queries! { desc { |tcx| "computing drop scopes for `{}`", tcx.def_path_str(def_id) } } + /// Generates a MIR body for the shim. query mir_shims(key: ty::InstanceDef<'tcx>) -> mir::Body<'tcx> { storage(ArenaCacheSelector<'tcx>) desc { |tcx| "generating MIR shim for `{}`", tcx.def_path_str(key.def_id()) } @@ -929,28 +950,29 @@ rustc_queries! { query opt_def_kind(def_id: DefId) -> Option { desc { |tcx| "looking up definition kind of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern } + /// Gets the span for the definition. query def_span(def_id: DefId) -> Span { desc { |tcx| "looking up span for `{}`", tcx.def_path_str(def_id) } - // FIXME(mw): DefSpans are not really inputs since they are derived from - // HIR. But at the moment HIR hashing still contains some hacks that allow - // to make type debuginfo to be source location independent. Declaring - // DefSpan an input makes sure that changes to these are always detected - // regardless of HIR hashing. - eval_always + separate_provide_extern } + /// Gets the span for the identifier of the definition. query def_ident_span(def_id: DefId) -> Option { desc { |tcx| "looking up span for `{}`'s identifier", tcx.def_path_str(def_id) } + separate_provide_extern } query lookup_stability(def_id: DefId) -> Option<&'tcx attr::Stability> { desc { |tcx| "looking up stability of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern } query lookup_const_stability(def_id: DefId) -> Option<&'tcx attr::ConstStability> { desc { |tcx| "looking up const stability of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern } query should_inherit_track_caller(def_id: DefId) -> bool { @@ -959,10 +981,12 @@ rustc_queries! { query lookup_deprecation_entry(def_id: DefId) -> Option { desc { |tcx| "checking whether `{}` is deprecated", tcx.def_path_str(def_id) } + separate_provide_extern } query item_attrs(def_id: DefId) -> &'tcx [ast::Attribute] { desc { |tcx| "collecting attributes of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern } query codegen_fn_attrs(def_id: DefId) -> CodegenFnAttrs { @@ -973,27 +997,33 @@ rustc_queries! { query fn_arg_names(def_id: DefId) -> &'tcx [rustc_span::symbol::Ident] { desc { |tcx| "looking up function parameter names for `{}`", tcx.def_path_str(def_id) } + separate_provide_extern } /// Gets the rendered value of the specified constant or associated constant. /// Used by rustdoc. query rendered_const(def_id: DefId) -> String { desc { |tcx| "rendering constant intializer of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern } query impl_parent(def_id: DefId) -> Option { desc { |tcx| "computing specialization parent impl of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern } /// Given an `associated_item`, find the trait it belongs to. /// Return `None` if the `DefId` is not an associated item. query trait_of_item(associated_item: DefId) -> Option { desc { |tcx| "finding trait defining `{}`", tcx.def_path_str(associated_item) } + separate_provide_extern } query is_ctfe_mir_available(key: DefId) -> bool { desc { |tcx| "checking if item has ctfe mir available: `{}`", tcx.def_path_str(key) } + separate_provide_extern } query is_mir_available(key: DefId) -> bool { desc { |tcx| "checking if item has mir available: `{}`", tcx.def_path_str(key) } + separate_provide_extern } query own_existential_vtable_entries( @@ -1030,11 +1060,6 @@ rustc_queries! { } /// Return all `impl` blocks in the current crate. - /// - /// To allow caching this between crates, you must pass in [`LOCAL_CRATE`] as the crate number. - /// Passing in any other crate will cause an ICE. - /// - /// [`LOCAL_CRATE`]: rustc_hir::def_id::LOCAL_CRATE query all_local_trait_impls(_: ()) -> &'tcx BTreeMap> { desc { "local trait impls" } } @@ -1159,6 +1184,7 @@ rustc_queries! { query dylib_dependency_formats(_: CrateNum) -> &'tcx [(CrateNum, LinkagePreference)] { desc { "dylib dependency formats of crate" } + separate_provide_extern } query dependency_formats(_: ()) -> Lrc { @@ -1168,41 +1194,50 @@ rustc_queries! { query is_compiler_builtins(_: CrateNum) -> bool { fatal_cycle desc { "checking if the crate is_compiler_builtins" } + separate_provide_extern } 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" } + separate_provide_extern } query has_panic_handler(_: CrateNum) -> bool { fatal_cycle desc { "checking if the crate has_panic_handler" } + separate_provide_extern } query is_profiler_runtime(_: CrateNum) -> bool { fatal_cycle desc { "query a crate is `#![profiler_runtime]`" } + separate_provide_extern } query panic_strategy(_: CrateNum) -> PanicStrategy { fatal_cycle desc { "query a crate's configured panic strategy" } + separate_provide_extern } query panic_in_drop_strategy(_: CrateNum) -> PanicStrategy { fatal_cycle desc { "query a crate's configured panic-in-drop strategy" } + separate_provide_extern } query is_no_builtins(_: CrateNum) -> bool { fatal_cycle desc { "test whether a crate has `#![no_builtins]`" } + separate_provide_extern } query symbol_mangling_version(_: CrateNum) -> SymbolManglingVersion { fatal_cycle desc { "query a crate's symbol mangling version" } + separate_provide_extern } query extern_crate(def_id: DefId) -> Option<&'tcx ExternCrate> { eval_always desc { "getting crate's ExternCrateData" } + separate_provide_extern } query specializes(_: (DefId, DefId)) -> bool { @@ -1219,10 +1254,12 @@ rustc_queries! { query impl_defaultness(def_id: DefId) -> hir::Defaultness { desc { |tcx| "looking up whether `{}` is a default impl", tcx.def_path_str(def_id) } + separate_provide_extern } query impl_constness(def_id: DefId) -> hir::Constness { desc { |tcx| "looking up whether `{}` is a const impl", tcx.def_path_str(def_id) } + separate_provide_extern } query check_item_well_formed(key: LocalDefId) -> () { @@ -1251,9 +1288,11 @@ rustc_queries! { -> DefIdMap { storage(ArenaCacheSelector<'tcx>) desc { "looking up the exported symbols of a crate" } + separate_provide_extern } query is_reachable_non_generic(def_id: DefId) -> bool { desc { |tcx| "checking whether `{}` is an exported symbol", tcx.def_path_str(def_id) } + separate_provide_extern } query is_unreachable_local_definition(def_id: LocalDefId) -> bool { desc { |tcx| @@ -1286,6 +1325,7 @@ rustc_queries! { "collecting available upstream monomorphizations for `{}`", tcx.def_path_str(def_id), } + separate_provide_extern } /// Returns the upstream crate that exports drop-glue for the given @@ -1309,6 +1349,7 @@ rustc_queries! { query foreign_modules(_: CrateNum) -> Lrc> { desc { "looking up the foreign modules of a linked crate" } + separate_provide_extern } /// Identifies the entry-point (e.g., the `main` function) for a given @@ -1324,18 +1365,22 @@ rustc_queries! { query crate_hash(_: CrateNum) -> Svh { eval_always desc { "looking up the hash a crate" } + separate_provide_extern } query crate_host_hash(_: CrateNum) -> Option { eval_always desc { "looking up the hash of a host version of a crate" } + separate_provide_extern } query extra_filename(_: CrateNum) -> String { eval_always desc { "looking up the extra filename for a crate" } + separate_provide_extern } query crate_extern_paths(_: CrateNum) -> Vec { eval_always desc { "looking up the paths for extern crates" } + separate_provide_extern } /// Given a crate and a trait, look up all impls of that trait in the crate. @@ -1343,6 +1388,7 @@ rustc_queries! { query implementations_of_trait(_: (CrateNum, DefId)) -> &'tcx [(DefId, Option)] { desc { "looking up implementations of a trait in a crate" } + separate_provide_extern } /// Given a crate, look up all trait impls in that crate. @@ -1350,6 +1396,7 @@ rustc_queries! { query all_trait_implementations(_: CrateNum) -> &'tcx [(DefId, Option)] { desc { "looking up all (?) trait implementations" } + separate_provide_extern } query is_dllimport_foreign_item(def_id: DefId) -> bool { @@ -1406,6 +1453,7 @@ rustc_queries! { query visibility(def_id: DefId) -> ty::Visibility { desc { |tcx| "computing visibility of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern } /// Computes the set of modules from which this type is visibly uninhabited. @@ -1420,13 +1468,18 @@ rustc_queries! { query dep_kind(_: CrateNum) -> CrateDepKind { eval_always desc { "fetching what a dependency looks like" } + separate_provide_extern } + + /// Gets the name of the crate. query crate_name(_: CrateNum) -> Symbol { eval_always desc { "fetching what a crate is named" } + separate_provide_extern } query item_children(def_id: DefId) -> &'tcx [Export] { desc { |tcx| "collecting child items of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern } query extern_mod_stmt_cnum(def_id: LocalDefId) -> Option { desc { |tcx| "computing crate imported by `{}`", tcx.def_path_str(def_id.to_def_id()) } @@ -1440,6 +1493,7 @@ rustc_queries! { query defined_lib_features(_: CrateNum) -> &'tcx [(Symbol, Option)] { desc { "calculating the lib features defined in a crate" } + separate_provide_extern } /// Returns the lang items defined in another crate by loading it from metadata. query get_lang_items(_: ()) -> LanguageItems { @@ -1458,16 +1512,19 @@ rustc_queries! { /// Returns the lang items defined in another crate by loading it from metadata. query defined_lang_items(_: CrateNum) -> &'tcx [(DefId, usize)] { desc { "calculating the lang items defined in a crate" } + separate_provide_extern } /// Returns the diagnostic items defined in a crate. query diagnostic_items(_: CrateNum) -> rustc_hir::diagnostic_items::DiagnosticItems { storage(ArenaCacheSelector<'tcx>) desc { "calculating the diagnostic items map in a crate" } + separate_provide_extern } query missing_lang_items(_: CrateNum) -> &'tcx [LangItem] { desc { "calculating the missing lang items in a crate" } + separate_provide_extern } query visible_parent_map(_: ()) -> DefIdMap { storage(ArenaCacheSelector<'tcx>) @@ -1480,10 +1537,12 @@ rustc_queries! { query missing_extern_crate_item(_: CrateNum) -> bool { eval_always desc { "seeing if we're missing an `extern crate` item for this crate" } + separate_provide_extern } query used_crate_source(_: CrateNum) -> Lrc { eval_always desc { "looking at the source for a crate" } + separate_provide_extern } query postorder_cnums(_: ()) -> &'tcx [CrateNum] { eval_always @@ -1494,6 +1553,7 @@ rustc_queries! { query is_private_dep(c: CrateNum) -> bool { eval_always desc { "check whether crate {} is a private dependency", c } + separate_provide_extern } query allocator_kind(_: ()) -> Option { eval_always @@ -1502,7 +1562,6 @@ rustc_queries! { query upvars_mentioned(def_id: DefId) -> Option<&'tcx FxIndexMap> { desc { |tcx| "collecting upvars mentioned in `{}`", tcx.def_path_str(def_id) } - eval_always } query maybe_unused_trait_import(def_id: LocalDefId) -> bool { desc { |tcx| "maybe_unused_trait_import for `{}`", tcx.def_path_str(def_id.to_def_id()) } @@ -1539,6 +1598,7 @@ rustc_queries! { query exported_symbols(_: CrateNum) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportLevel)] { desc { "exported_symbols" } + separate_provide_extern } query collect_and_partition_mono_items(_: ()) -> (&'tcx DefIdSet, &'tcx [CodegenUnit<'tcx>]) { @@ -1564,6 +1624,7 @@ rustc_queries! { |tcx| "determining which generic parameters are unused by `{}`", tcx.def_path_str(key.def_id()) } + separate_provide_extern } query backend_optimization_level(_: ()) -> OptLevel { desc { "optimization level used by backend" } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index b089ae22d6..49a64cb246 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -7,6 +7,7 @@ pub mod query; pub mod select; pub mod specialization_graph; mod structural_impls; +pub mod util; use crate::infer::canonical::Canonical; use crate::thir::abstract_const::NotConstEvaluatable; @@ -23,6 +24,7 @@ use smallvec::SmallVec; use std::borrow::Cow; use std::fmt; +use std::hash::{Hash, Hasher}; use std::ops::Deref; pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache}; @@ -108,7 +110,7 @@ impl Deref for ObligationCause<'tcx> { } } -#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)] +#[derive(Clone, Debug, PartialEq, Eq, Lift)] pub struct ObligationCauseData<'tcx> { pub span: Span, @@ -123,6 +125,14 @@ pub struct ObligationCauseData<'tcx> { pub code: ObligationCauseCode<'tcx>, } +impl Hash for ObligationCauseData<'_> { + fn hash(&self, state: &mut H) { + self.body_id.hash(state); + self.span.hash(state); + std::mem::discriminant(&self.code).hash(state); + } +} + impl<'tcx> ObligationCause<'tcx> { #[inline] pub fn new( @@ -267,14 +277,12 @@ pub enum ObligationCauseCode<'tcx> { /// Error derived when matching traits/impls; see ObligationCause for more details CompareImplMethodObligation { - item_name: Symbol, impl_item_def_id: DefId, trait_item_def_id: DefId, }, /// Error derived when matching traits/impls; see ObligationCause for more details CompareImplTypeObligation { - item_name: Symbol, impl_item_def_id: DefId, trait_item_def_id: DefId, }, @@ -440,16 +448,28 @@ pub struct DerivedObligationCause<'tcx> { #[derive(Clone, Debug, TypeFoldable, Lift)] pub enum SelectionError<'tcx> { + /// The trait is not implemented. Unimplemented, + /// After a closure impl has selected, its "outputs" were evaluated + /// (which for closures includes the "input" type params) and they + /// didn't resolve. See `confirm_poly_trait_refs` for more. OutputTypeParameterMismatch( ty::PolyTraitRef<'tcx>, ty::PolyTraitRef<'tcx>, ty::error::TypeError<'tcx>, ), + /// The trait pointed by `DefId` is not object safe. TraitNotObjectSafe(DefId), + /// A given constant couldn't be evaluated. NotConstEvaluatable(NotConstEvaluatable), + /// Exceeded the recursion depth during type projection. Overflow, + /// Signaling that an error has already been emitted, to avoid + /// multiple errors being shown. ErrorReporting, + /// Multiple applicable `impl`s where found. The `DefId`s correspond to + /// all the `impl`s' Items. + Ambiguous(Vec), } /// When performing resolution, it is typically the case that there diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index 6720493cd3..560660517f 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -12,12 +12,14 @@ use rustc_hir::def_id::DefId; use rustc_query_system::cache::Cache; pub type SelectionCache<'tcx> = Cache< - ty::ConstnessAnd>>, + (ty::ConstnessAnd>>, ty::ImplPolarity), SelectionResult<'tcx, SelectionCandidate<'tcx>>, >; -pub type EvaluationCache<'tcx> = - Cache>>, EvaluationResult>; +pub type EvaluationCache<'tcx> = Cache< + (ty::ParamEnvAnd<'tcx, ty::ConstnessAnd>>, ty::ImplPolarity), + EvaluationResult, +>; /// The selection process begins by considering all impls, where /// clauses, and so forth that might resolve an obligation. Sometimes @@ -101,7 +103,7 @@ pub enum SelectionCandidate<'tcx> { /// `false` if there are no *further* obligations. has_nested: bool, }, - ParamCandidate(ty::ConstnessAnd>), + ParamCandidate((ty::ConstnessAnd>, ty::ImplPolarity)), ImplCandidate(DefId), AutoImplCandidate(DefId), diff --git a/compiler/rustc_middle/src/traits/util.rs b/compiler/rustc_middle/src/traits/util.rs new file mode 100644 index 0000000000..3490c68817 --- /dev/null +++ b/compiler/rustc_middle/src/traits/util.rs @@ -0,0 +1,49 @@ +use rustc_data_structures::stable_set::FxHashSet; + +use crate::ty::{PolyTraitRef, TyCtxt}; + +/// Given a PolyTraitRef, get the PolyTraitRefs of the trait's (transitive) supertraits. +/// +/// A simplfied version of the same function at `rustc_infer::traits::util::supertraits`. +pub fn supertraits<'tcx>( + tcx: TyCtxt<'tcx>, + trait_ref: PolyTraitRef<'tcx>, +) -> impl Iterator> { + Elaborator { tcx, visited: FxHashSet::from_iter([trait_ref]), stack: vec![trait_ref] } +} + +struct Elaborator<'tcx> { + tcx: TyCtxt<'tcx>, + visited: FxHashSet>, + stack: Vec>, +} + +impl<'tcx> Elaborator<'tcx> { + fn elaborate(&mut self, trait_ref: PolyTraitRef<'tcx>) { + let supertrait_refs = self + .tcx + .super_predicates_of(trait_ref.def_id()) + .predicates + .into_iter() + .flat_map(|(pred, _)| { + pred.subst_supertrait(self.tcx, &trait_ref).to_opt_poly_trait_ref() + }) + .map(|t| t.value) + .filter(|supertrait_ref| self.visited.insert(*supertrait_ref)); + + self.stack.extend(supertrait_refs); + } +} + +impl<'tcx> Iterator for Elaborator<'tcx> { + type Item = PolyTraitRef<'tcx>; + + fn next(&mut self) -> Option> { + if let Some(trait_ref) = self.stack.pop() { + self.elaborate(trait_ref); + Some(trait_ref) + } else { + None + } + } +} diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 434008ecb1..3f2b987b1e 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -417,17 +417,17 @@ macro_rules! __impl_decoder_methods { macro_rules! impl_arena_allocatable_decoder { ([]$args:tt) => {}; ([decode $(, $attrs:ident)*] - [[$name:ident: $ty:ty], $tcx:lifetime]) => { - impl<$tcx, D: TyDecoder<$tcx>> RefDecodable<$tcx, D> for $ty { + [$name:ident: $ty:ty]) => { + impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for $ty { #[inline] - fn decode(decoder: &mut D) -> Result<&$tcx Self, D::Error> { + fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { decode_arena_allocable(decoder) } } - impl<$tcx, D: TyDecoder<$tcx>> RefDecodable<$tcx, D> for [$ty] { + impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [$ty] { #[inline] - fn decode(decoder: &mut D) -> Result<&$tcx Self, D::Error> { + fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { decode_arena_allocable_slice(decoder) } } @@ -438,15 +438,15 @@ macro_rules! impl_arena_allocatable_decoder { } macro_rules! impl_arena_allocatable_decoders { - ([$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => { + ([$($a:tt $name:ident: $ty:ty,)*]) => { $( - impl_arena_allocatable_decoder!($a [[$name: $ty], $tcx]); + impl_arena_allocatable_decoder!($a [$name: $ty]); )* } } -rustc_hir::arena_types!(impl_arena_allocatable_decoders, 'tcx); -arena_types!(impl_arena_allocatable_decoders, 'tcx); +rustc_hir::arena_types!(impl_arena_allocatable_decoders); +arena_types!(impl_arena_allocatable_decoders); #[macro_export] macro_rules! implement_ty_decoder { diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 869b2ab9db..27e22ccac0 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -1,7 +1,9 @@ use crate::mir::interpret::ConstValue; use crate::mir::interpret::{LitToConstInput, Scalar}; -use crate::ty::{self, Ty, TyCtxt}; -use crate::ty::{ParamEnv, ParamEnvAnd}; +use crate::ty::{ + self, InlineConstSubsts, InlineConstSubstsParts, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, + TyCtxt, TypeFoldable, +}; use rustc_errors::ErrorReported; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -54,6 +56,24 @@ impl<'tcx> Const<'tcx> { let ty = tcx.type_of(def.def_id_for_type_of()); + match Self::try_eval_lit_or_param(tcx, ty, expr) { + Some(v) => v, + None => tcx.mk_const(ty::Const { + val: ty::ConstKind::Unevaluated(ty::Unevaluated { + def: def.to_global(), + substs_: None, + promoted: None, + }), + ty, + }), + } + } + + fn try_eval_lit_or_param( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>, + expr: &'tcx hir::Expr<'tcx>, + ) -> Option<&'tcx Self> { let lit_input = match expr.kind { hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }), hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => match expr.kind { @@ -69,7 +89,7 @@ impl<'tcx> Const<'tcx> { // If an error occurred, ignore that it's a literal and leave reporting the error up to // mir. if let Ok(c) = tcx.at(expr.span).lit_to_const(lit_input) { - return c; + return Some(c); } else { tcx.sess.delay_span_bug(expr.span, "Const::from_anon_const: couldn't lit_to_const"); } @@ -85,7 +105,7 @@ impl<'tcx> Const<'tcx> { }; use hir::{def::DefKind::ConstParam, def::Res, ExprKind, Path, QPath}; - let val = match expr.kind { + match expr.kind { ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => { // Find the name and index of the const parameter by indexing the generics of // the parent item and construct a `ParamConst`. @@ -95,16 +115,53 @@ impl<'tcx> Const<'tcx> { let generics = tcx.generics_of(item_def_id.to_def_id()); let index = generics.param_def_id_to_index[&def_id]; let name = tcx.hir().name(hir_id); - ty::ConstKind::Param(ty::ParamConst::new(index, name)) + Some(tcx.mk_const(ty::Const { + val: ty::ConstKind::Param(ty::ParamConst::new(index, name)), + ty, + })) } - _ => ty::ConstKind::Unevaluated(ty::Unevaluated { - def: def.to_global(), - substs_: None, - promoted: None, - }), + _ => None, + } + } + + pub fn from_inline_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx Self { + debug!("Const::from_inline_const(def_id={:?})", def_id); + + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + + let body_id = match tcx.hir().get(hir_id) { + hir::Node::AnonConst(ac) => ac.body, + _ => span_bug!( + tcx.def_span(def_id.to_def_id()), + "from_inline_const can only process anonymous constants" + ), }; - tcx.mk_const(ty::Const { val, ty }) + let expr = &tcx.hir().body(body_id).value; + + let ty = tcx.typeck(def_id).node_type(hir_id); + + let ret = match Self::try_eval_lit_or_param(tcx, ty, expr) { + Some(v) => v, + None => { + let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id()); + let parent_substs = + tcx.erase_regions(InternalSubsts::identity_for_item(tcx, typeck_root_def_id)); + let substs = + InlineConstSubsts::new(tcx, InlineConstSubstsParts { parent_substs, ty }) + .substs; + tcx.mk_const(ty::Const { + val: ty::ConstKind::Unevaluated(ty::Unevaluated { + def: ty::WithOptConstParam::unknown(def_id).to_global(), + substs_: Some(substs), + promoted: None, + }), + ty, + }) + } + }; + debug_assert!(!ret.has_free_regions(tcx)); + ret } /// Interns the given value as a constant. diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 83d7c307bd..8240273aca 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1,7 +1,7 @@ //! Type context book-keeping. use crate::arena::Arena; -use crate::dep_graph::DepGraph; +use crate::dep_graph::{DepGraph, DepKind, DepKindStruct}; use crate::hir::place::Place as HirPlace; use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos}; use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintLevelSource}; @@ -79,11 +79,6 @@ pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync { where Self: Sized; - /// Converts a `DefPathHash` to its corresponding `DefId` in the current compilation - /// session, if it still exists. This is used during incremental compilation to - /// turn a deserialized `DefPathHash` into its current `DefId`. - fn def_path_hash_to_def_id(&self, tcx: TyCtxt<'tcx>, def_path_hash: DefPathHash) -> DefId; - fn drop_serialized_data(&self, tcx: TyCtxt<'tcx>); fn serialize(&self, tcx: TyCtxt<'tcx>, encoder: &mut FileEncoder) -> FileEncodeResult; @@ -1016,6 +1011,7 @@ pub struct GlobalCtxt<'tcx> { pub queries: &'tcx dyn query::QueryEngine<'tcx>, pub query_caches: query::QueryCaches<'tcx>, + query_kinds: &'tcx [DepKindStruct], // Internal caches for metadata decoding. No need to track deps on this. pub ty_rcache: Lock>>, @@ -1149,6 +1145,7 @@ impl<'tcx> TyCtxt<'tcx> { dep_graph: DepGraph, on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>, queries: &'tcx dyn query::QueryEngine<'tcx>, + query_kinds: &'tcx [DepKindStruct], crate_name: &str, output_filenames: OutputFilenames, ) -> GlobalCtxt<'tcx> { @@ -1175,6 +1172,7 @@ impl<'tcx> TyCtxt<'tcx> { on_disk_cache, queries, query_caches: query::QueryCaches::default(), + query_kinds, ty_rcache: Default::default(), pred_rcache: Default::default(), selection_cache: Default::default(), @@ -1188,6 +1186,10 @@ impl<'tcx> TyCtxt<'tcx> { } } + crate fn query_kind(self, k: DepKind) -> &'tcx DepKindStruct { + &self.query_kinds[k as usize] + } + /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used. #[track_caller] pub fn ty_error(self) -> Ty<'tcx> { @@ -1301,6 +1303,27 @@ impl<'tcx> TyCtxt<'tcx> { } } + /// Converts a `DefPathHash` to its corresponding `DefId` in the current compilation + /// session, if it still exists. This is used during incremental compilation to + /// turn a deserialized `DefPathHash` into its current `DefId`. + pub fn def_path_hash_to_def_id(self, hash: DefPathHash) -> DefId { + debug!("def_path_hash_to_def_id({:?})", hash); + + let stable_crate_id = hash.stable_crate_id(); + + // If this is a DefPathHash from the local crate, we can look up the + // DefId in the tcx's `Definitions`. + if stable_crate_id == self.sess.local_stable_crate_id() { + self.untracked_resolutions.definitions.local_def_path_hash_to_def_id(hash).to_def_id() + } else { + // If this is a DefPathHash from an upstream crate, let the CrateStore map + // it to a DefId. + let cstore = &self.untracked_resolutions.cstore; + let cnum = cstore.stable_crate_id_to_crate_num(stable_crate_id); + cstore.def_path_hash_to_def_id(cnum, hash) + } + } + pub fn def_path_debug_str(self, def_id: DefId) -> String { // We are explicitly not going through queries here in order to get // crate name and stable crate id since this code is called from debug!() @@ -1337,20 +1360,15 @@ impl<'tcx> TyCtxt<'tcx> { #[inline(always)] pub fn create_stable_hashing_context(self) -> StableHashingContext<'tcx> { - let krate = self.gcx.untracked_crate; let resolutions = &self.gcx.untracked_resolutions; - - StableHashingContext::new(self.sess, krate, &resolutions.definitions, &*resolutions.cstore) + StableHashingContext::new(self.sess, &resolutions.definitions, &*resolutions.cstore) } #[inline(always)] pub fn create_no_span_stable_hashing_context(self) -> StableHashingContext<'tcx> { - let krate = self.gcx.untracked_crate; let resolutions = &self.gcx.untracked_resolutions; - StableHashingContext::ignore_spans( self.sess, - krate, &resolutions.definitions, &*resolutions.cstore, ) @@ -2823,7 +2841,8 @@ fn ptr_eq(t: *const T, u: *const U) -> bool { } pub fn provide(providers: &mut ty::query::Providers) { - providers.in_scope_traits_map = |tcx, id| tcx.hir_crate(()).trait_map.get(&id); + providers.in_scope_traits_map = + |tcx, id| tcx.hir_crate(()).owners[id].as_ref().map(|owner_info| &owner_info.trait_map); providers.resolutions = |tcx, ()| &tcx.untracked_resolutions; providers.module_exports = |tcx, id| tcx.resolutions(()).export_map.get(&id).map(|v| &v[..]); providers.crate_name = |tcx, id| { diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 092eae0fc5..1b32c8a669 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -221,9 +221,7 @@ pub fn suggest_constraining_type_param( ) -> bool { let param = generics.params.iter().find(|p| p.name.ident().as_str() == param_name); - let param = if let Some(param) = param { - param - } else { + let Some(param) = param else { return false; }; diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 08b4d3aecd..b14a698926 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -34,6 +34,7 @@ impl ExpectedFound { pub enum TypeError<'tcx> { Mismatch, ConstnessMismatch(ExpectedFound), + PolarityMismatch(ExpectedFound), UnsafetyMismatch(ExpectedFound), AbiMismatch(ExpectedFound), Mutability, @@ -41,6 +42,7 @@ pub enum TypeError<'tcx> { TupleSize(ExpectedFound), FixedArraySize(ExpectedFound), ArgCount, + FieldMisMatch(Symbol, Symbol), RegionsDoesNotOutlive(Region<'tcx>, Region<'tcx>), RegionsInsufficientlyPolymorphic(BoundRegionKind, Region<'tcx>), @@ -104,6 +106,9 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { ConstnessMismatch(values) => { write!(f, "expected {} bound, found {} bound", values.expected, values.found) } + PolarityMismatch(values) => { + write!(f, "expected {} polarity, found {} polarity", values.expected, values.found) + } UnsafetyMismatch(values) => { write!(f, "expected {} fn, found {} fn", values.expected, values.found) } @@ -130,6 +135,7 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { pluralize!(values.found) ), ArgCount => write!(f, "incorrect number of function parameters"), + FieldMisMatch(adt, field) => write!(f, "field type mismatch: {}.{}", adt, field), RegionsDoesNotOutlive(..) => write!(f, "lifetime mismatch"), RegionsInsufficientlyPolymorphic(br, _) => write!( f, @@ -212,15 +218,15 @@ impl<'tcx> TypeError<'tcx> { use self::TypeError::*; match self { CyclicTy(_) | CyclicConst(_) | UnsafetyMismatch(_) | ConstnessMismatch(_) - | Mismatch | AbiMismatch(_) | FixedArraySize(_) | ArgumentSorts(..) | Sorts(_) - | IntMismatch(_) | FloatMismatch(_) | VariadicMismatch(_) | TargetFeatureCast(_) => { - false - } + | PolarityMismatch(_) | Mismatch | AbiMismatch(_) | FixedArraySize(_) + | ArgumentSorts(..) | Sorts(_) | IntMismatch(_) | FloatMismatch(_) + | VariadicMismatch(_) | TargetFeatureCast(_) => false, Mutability | ArgumentMutability(_) | TupleSize(_) | ArgCount + | FieldMisMatch(..) | RegionsDoesNotOutlive(..) | RegionsInsufficientlyPolymorphic(..) | RegionsOverlyPolymorphic(..) @@ -769,11 +775,16 @@ fn foo(&self) -> Self::T { String::new() } ) -> bool { let assoc = self.associated_item(proj_ty.item_def_id); if let ty::Opaque(def_id, _) = *proj_ty.self_ty().kind() { - let opaque_local_def_id = def_id.expect_local(); - let opaque_hir_id = self.hir().local_def_id_to_hir_id(opaque_local_def_id); - let opaque_hir_ty = match &self.hir().expect_item(opaque_hir_id).kind { - hir::ItemKind::OpaqueTy(opaque_hir_ty) => opaque_hir_ty, - _ => bug!("The HirId comes from a `ty::Opaque`"), + let opaque_local_def_id = def_id.as_local(); + let opaque_hir_ty = if let Some(opaque_local_def_id) = opaque_local_def_id { + let hir = self.hir(); + let opaque_hir_id = hir.local_def_id_to_hir_id(opaque_local_def_id); + match &hir.expect_item(opaque_hir_id).kind { + hir::ItemKind::OpaqueTy(opaque_hir_ty) => opaque_hir_ty, + _ => bug!("The HirId comes from a `ty::Opaque`"), + } + } else { + return false; }; let (trait_ref, assoc_substs) = proj_ty.trait_ref_and_own_substs(self); diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 0f89581ae6..f53f187150 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -3,7 +3,6 @@ use crate::ty; use crate::ty::subst::{Subst, SubstsRef}; use rustc_ast as ast; use rustc_data_structures::fx::FxHashMap; -use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_span::symbol::Symbol; use rustc_span::Span; @@ -13,14 +12,8 @@ use super::{EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, Predi #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] pub enum GenericParamDefKind { Lifetime, - Type { - has_default: bool, - object_lifetime_default: ObjectLifetimeDefault, - synthetic: Option, - }, - Const { - has_default: bool, - }, + Type { has_default: bool, object_lifetime_default: ObjectLifetimeDefault, synthetic: bool }, + Const { has_default: bool }, } impl GenericParamDefKind { @@ -202,15 +195,7 @@ impl<'tcx> Generics { /// Returns `true` if `params` has `impl Trait`. pub fn has_impl_trait(&'tcx self) -> bool { self.params.iter().any(|param| { - matches!( - param.kind, - ty::GenericParamDefKind::Type { - synthetic: Some( - hir::SyntheticTyParamKind::ImplTrait | hir::SyntheticTyParamKind::FromAttr, - ), - .. - } - ) + matches!(param.kind, ty::GenericParamDefKind::Type { synthetic: true, .. }) }) } } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index d0c7379c2d..b87e23af72 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -755,17 +755,14 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } // Extract the number of elements from the layout of the array field: - let len = if let Ok(TyAndLayout { + let Ok(TyAndLayout { layout: Layout { fields: FieldsShape::Array { count, .. }, .. }, .. - }) = self.layout_of(f0_ty) - { - count - } else { + }) = self.layout_of(f0_ty) else { return Err(LayoutError::Unknown(ty)); }; - (*e_ty, *len, true) + (*e_ty, *count, true) } else { // First ADT field is not an array: (f0_ty, def.non_enum_variant().fields.len() as _, false) @@ -787,9 +784,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // Compute the ABI of the element type: let e_ly = self.layout_of(e_ty)?; - let e_abi = if let Abi::Scalar(scalar) = e_ly.abi { - scalar - } else { + let Abi::Scalar(e_abi) = e_ly.abi else { // This error isn't caught in typeck, e.g., if // the element type of the vector is generic. tcx.sess.fatal(&format!( @@ -3065,9 +3060,10 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // 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. + // Due to past miscompiles in LLVM, we apply a separate NoAliasMutRef attribute + // for UniqueBorrowed arguments, so that the codegen backend can decide whether + // or not to actually emit the attribute. It can also be controlled with the + // `-Zmutable-noalias` debugging option. let no_alias = match kind { PointerKind::Shared | PointerKind::UniqueBorrowed => false, PointerKind::UniqueOwned => true, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 20d07bdc48..673733faa7 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -74,9 +74,10 @@ pub use self::sty::{ 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, VarianceDiagInfo, VarianceDiagMutKind, + GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts, InlineConstSubstsParts, ParamConst, + ParamTy, PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyGenSig, + PolyTraitRef, ProjectionTy, Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, + UpvarSubsts, VarianceDiagInfo, VarianceDiagMutKind, }; pub use self::trait_def::TraitDef; @@ -164,7 +165,18 @@ pub struct ImplHeader<'tcx> { pub predicates: Vec>, } -#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] +#[derive( + Copy, + Clone, + PartialEq, + Eq, + Hash, + TyEncodable, + TyDecodable, + HashStable, + Debug, + TypeFoldable +)] pub enum ImplPolarity { /// `impl Trait for Type` Positive, @@ -177,6 +189,27 @@ pub enum ImplPolarity { Reservation, } +impl ImplPolarity { + /// Flips polarity by turning `Positive` into `Negative` and `Negative` into `Positive`. + pub fn flip(&self) -> Option { + match self { + ImplPolarity::Positive => Some(ImplPolarity::Negative), + ImplPolarity::Negative => Some(ImplPolarity::Positive), + ImplPolarity::Reservation => None, + } + } +} + +impl fmt::Display for ImplPolarity { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Positive => f.write_str("positive"), + Self::Negative => f.write_str("negative"), + Self::Reservation => f.write_str("reservation"), + } + } +} + #[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, TyEncodable, TyDecodable, HashStable)] pub enum Visibility { /// Visible everywhere (including in other crates). @@ -300,6 +333,10 @@ impl Visibility { Visibility::Invisible => false, } } + + pub fn is_public(self) -> bool { + matches!(self, Visibility::Public) + } } /// The crate variances map is computed during typeck and contains the @@ -459,6 +496,29 @@ impl<'tcx> Predicate<'tcx> { pub fn kind(self) -> Binder<'tcx, PredicateKind<'tcx>> { self.inner.kind } + + /// Flips the polarity of a Predicate. + /// + /// Given `T: Trait` predicate it returns `T: !Trait` and given `T: !Trait` returns `T: Trait`. + pub fn flip_polarity(&self, tcx: TyCtxt<'tcx>) -> Option> { + let kind = self + .inner + .kind + .map_bound(|kind| match kind { + PredicateKind::Trait(TraitPredicate { trait_ref, constness, polarity }) => { + Some(PredicateKind::Trait(TraitPredicate { + trait_ref, + constness, + polarity: polarity.flip()?, + })) + } + + _ => None, + }) + .transpose()?; + + Some(tcx.mk_predicate(kind)) + } } impl<'a, 'tcx> HashStable> for Predicate<'tcx> { @@ -654,6 +714,8 @@ pub struct TraitPredicate<'tcx> { pub trait_ref: TraitRef<'tcx>, pub constness: BoundConstness, + + pub polarity: ImplPolarity, } pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>; @@ -788,7 +850,11 @@ impl<'tcx> ToPredicate<'tcx> for ConstnessAnd> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { self.value .map_bound(|trait_ref| { - PredicateKind::Trait(ty::TraitPredicate { trait_ref, constness: self.constness }) + PredicateKind::Trait(ty::TraitPredicate { + trait_ref, + constness: self.constness, + polarity: ty::ImplPolarity::Positive, + }) }) .to_predicate(tcx) } @@ -1866,7 +1932,8 @@ impl<'tcx> TyCtxt<'tcx> { | DefKind::Static | DefKind::AssocConst | DefKind::Ctor(..) - | DefKind::AnonConst => self.mir_for_ctfe_opt_const_arg(def), + | DefKind::AnonConst + | DefKind::InlineConst => self.mir_for_ctfe_opt_const_arg(def), // If the caller wants `mir_for_ctfe` of a function they should not be using // `instance_mir`, so we'll assume const fn also wants the optimized version. _ => { diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 2610a76b28..175295b319 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -350,18 +350,26 @@ pub trait PrettyPrinter<'tcx>: match self.tcx().extern_crate(def_id) { Some(&ExternCrate { src, dependency_of, span, .. }) => match (src, dependency_of) { (ExternCrateSource::Extern(def_id), LOCAL_CRATE) => { - debug!("try_print_visible_def_path: def_id={:?}", def_id); - return Ok(( - if !span.is_dummy() { - self.print_def_path(def_id, &[])? - } else { - self.path_crate(cnum)? - }, - true, - )); + // NOTE(eddyb) the only reason `span` might be dummy, + // that we're aware of, is that it's the `std`/`core` + // `extern crate` injected by default. + // FIXME(eddyb) find something better to key this on, + // or avoid ending up with `ExternCrateSource::Extern`, + // for the injected `std`/`core`. + if span.is_dummy() { + return Ok((self.path_crate(cnum)?, true)); + } + + // Disable `try_print_trimmed_def_path` behavior within + // the `print_def_path` call, to avoid infinite recursion + // in cases where the `extern crate foo` has non-trivial + // parents, e.g. it's nested in `impl foo::Trait for Bar` + // (see also issues #55779 and #87932). + self = with_no_visible_paths(|| self.print_def_path(def_id, &[]))?; + + return Ok((self, true)); } (ExternCrateSource::Path, LOCAL_CRATE) => { - debug!("try_print_visible_def_path: def_id={:?}", def_id); return Ok((self.path_crate(cnum)?, true)); } _ => {} @@ -635,37 +643,8 @@ pub trait PrettyPrinter<'tcx>: } return Ok(self); } - // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, - // by looking up the projections associated with the def_id. - let bounds = self.tcx().explicit_item_bounds(def_id); - - let mut first = true; - let mut is_sized = false; - p!("impl"); - for (predicate, _) in bounds { - let predicate = predicate.subst(self.tcx(), substs); - let bound_predicate = predicate.kind(); - if let ty::PredicateKind::Trait(pred) = bound_predicate.skip_binder() { - let trait_ref = bound_predicate.rebind(pred.trait_ref); - // Don't print +Sized, but rather +?Sized if absent. - if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait() { - is_sized = true; - continue; - } - p!( - write("{}", if first { " " } else { "+" }), - print(trait_ref.print_only_trait_path()) - ); - first = false; - } - } - if !is_sized { - p!(write("{}?Sized", if first { " " } else { "+" })); - } else if first { - p!(" Sized"); - } - Ok(self) + self.pretty_print_opaque_impl_type(def_id, substs) }); } ty::Str => p!("str"), @@ -736,6 +715,7 @@ pub trait PrettyPrinter<'tcx>: p!(print_def_path(did, substs)); if !substs.as_closure().is_valid() { p!(" closure_substs=(unavailable)"); + p!(write(" substs={:?}", substs)); } else { p!(" closure_kind_ty=", print(substs.as_closure().kind_ty())); p!( @@ -773,6 +753,225 @@ pub trait PrettyPrinter<'tcx>: Ok(self) } + fn pretty_print_opaque_impl_type( + mut self, + def_id: DefId, + substs: &'tcx ty::List>, + ) -> Result { + define_scoped_cx!(self); + + // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, + // by looking up the projections associated with the def_id. + let bounds = self.tcx().explicit_item_bounds(def_id); + + let mut traits = BTreeMap::new(); + let mut fn_traits = BTreeMap::new(); + let mut is_sized = false; + + for (predicate, _) in bounds { + let predicate = predicate.subst(self.tcx(), substs); + let bound_predicate = predicate.kind(); + + match bound_predicate.skip_binder() { + ty::PredicateKind::Trait(pred) => { + let trait_ref = bound_predicate.rebind(pred.trait_ref); + + // Don't print + Sized, but rather + ?Sized if absent. + if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait() { + is_sized = true; + continue; + } + + self.insert_trait_and_projection(trait_ref, None, &mut traits, &mut fn_traits); + } + ty::PredicateKind::Projection(pred) => { + let proj_ref = bound_predicate.rebind(pred); + let trait_ref = proj_ref.required_poly_trait_ref(self.tcx()); + + // Projection type entry -- the def-id for naming, and the ty. + let proj_ty = (proj_ref.projection_def_id(), proj_ref.ty()); + + self.insert_trait_and_projection( + trait_ref, + Some(proj_ty), + &mut traits, + &mut fn_traits, + ); + } + _ => {} + } + } + + let mut first = true; + // Insert parenthesis around (Fn(A, B) -> C) if the opaque ty has more than one other trait + let paren_needed = fn_traits.len() > 1 || traits.len() > 0 || !is_sized; + + p!("impl"); + + for (fn_once_trait_ref, entry) in fn_traits { + // Get the (single) generic ty (the args) of this FnOnce trait ref. + let generics = self.generic_args_to_print( + self.tcx().generics_of(fn_once_trait_ref.def_id()), + fn_once_trait_ref.skip_binder().substs, + ); + + match (entry.return_ty, generics[0].expect_ty()) { + // We can only print `impl Fn() -> ()` if we have a tuple of args and we recorded + // a return type. + (Some(return_ty), arg_tys) if matches!(arg_tys.kind(), ty::Tuple(_)) => { + let name = if entry.fn_trait_ref.is_some() { + "Fn" + } else if entry.fn_mut_trait_ref.is_some() { + "FnMut" + } else { + "FnOnce" + }; + + p!( + write("{}", if first { " " } else { " + " }), + write("{}{}(", if paren_needed { "(" } else { "" }, name) + ); + + for (idx, ty) in arg_tys.tuple_fields().enumerate() { + if idx > 0 { + p!(", "); + } + p!(print(ty)); + } + + p!(")"); + if !return_ty.skip_binder().is_unit() { + p!("-> ", print(return_ty)); + } + p!(write("{}", if paren_needed { ")" } else { "" })); + + first = false; + } + // If we got here, we can't print as a `impl Fn(A, B) -> C`. Just record the + // trait_refs we collected in the OpaqueFnEntry as normal trait refs. + _ => { + if entry.has_fn_once { + traits.entry(fn_once_trait_ref).or_default().extend( + // Group the return ty with its def id, if we had one. + entry + .return_ty + .map(|ty| (self.tcx().lang_items().fn_once_output().unwrap(), ty)), + ); + } + if let Some(trait_ref) = entry.fn_mut_trait_ref { + traits.entry(trait_ref).or_default(); + } + if let Some(trait_ref) = entry.fn_trait_ref { + traits.entry(trait_ref).or_default(); + } + } + } + } + + // Print the rest of the trait types (that aren't Fn* family of traits) + for (trait_ref, assoc_items) in traits { + p!( + write("{}", if first { " " } else { " + " }), + print(trait_ref.skip_binder().print_only_trait_name()) + ); + + let generics = self.generic_args_to_print( + self.tcx().generics_of(trait_ref.def_id()), + trait_ref.skip_binder().substs, + ); + + if !generics.is_empty() || !assoc_items.is_empty() { + p!("<"); + let mut first = true; + + for ty in generics { + if !first { + p!(", "); + } + p!(print(trait_ref.rebind(*ty))); + first = false; + } + + for (assoc_item_def_id, ty) in assoc_items { + if !first { + p!(", "); + } + p!(write("{} = ", self.tcx().associated_item(assoc_item_def_id).ident)); + + // Skip printing `<[generator@] as Generator<_>>::Return` from async blocks + match ty.skip_binder().kind() { + ty::Projection(ty::ProjectionTy { item_def_id, .. }) + if Some(*item_def_id) == self.tcx().lang_items().generator_return() => + { + p!("[async output]") + } + _ => { + p!(print(ty)) + } + } + + first = false; + } + + p!(">"); + } + + first = false; + } + + if !is_sized { + p!(write("{}?Sized", if first { " " } else { " + " })); + } else if first { + p!(" Sized"); + } + + Ok(self) + } + + /// Insert the trait ref and optionally a projection type associated with it into either the + /// traits map or fn_traits map, depending on if the trait is in the Fn* family of traits. + fn insert_trait_and_projection( + &mut self, + trait_ref: ty::PolyTraitRef<'tcx>, + proj_ty: Option<(DefId, ty::Binder<'tcx, Ty<'tcx>>)>, + traits: &mut BTreeMap, BTreeMap>>>, + fn_traits: &mut BTreeMap, OpaqueFnEntry<'tcx>>, + ) { + let trait_def_id = trait_ref.def_id(); + + // If our trait_ref is FnOnce or any of its children, project it onto the parent FnOnce + // super-trait ref and record it there. + if let Some(fn_once_trait) = self.tcx().lang_items().fn_once_trait() { + // If we have a FnOnce, then insert it into + if trait_def_id == fn_once_trait { + let entry = fn_traits.entry(trait_ref).or_default(); + // Optionally insert the return_ty as well. + if let Some((_, ty)) = proj_ty { + entry.return_ty = Some(ty); + } + entry.has_fn_once = true; + return; + } else if Some(trait_def_id) == self.tcx().lang_items().fn_mut_trait() { + let super_trait_ref = crate::traits::util::supertraits(self.tcx(), trait_ref) + .find(|super_trait_ref| super_trait_ref.def_id() == fn_once_trait) + .unwrap(); + + fn_traits.entry(super_trait_ref).or_default().fn_mut_trait_ref = Some(trait_ref); + return; + } else if Some(trait_def_id) == self.tcx().lang_items().fn_trait() { + let super_trait_ref = crate::traits::util::supertraits(self.tcx(), trait_ref) + .find(|super_trait_ref| super_trait_ref.def_id() == fn_once_trait) + .unwrap(); + + fn_traits.entry(super_trait_ref).or_default().fn_trait_ref = Some(trait_ref); + return; + } + } + + // Otherwise, just group our traits and projection types. + traits.entry(trait_ref).or_default().extend(proj_ty); + } + fn pretty_print_bound_var( &mut self, debruijn: ty::DebruijnIndex, @@ -2395,7 +2594,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N // Iterate external crate defs but be mindful about visibility while let Some(def) = queue.pop() { for child in tcx.item_children(def).iter() { - if child.vis != ty::Visibility::Public { + if !child.vis.is_public() { continue; } @@ -2500,3 +2699,12 @@ fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap { pub fn provide(providers: &mut ty::query::Providers) { *providers = ty::query::Providers { trimmed_def_paths, ..*providers }; } + +#[derive(Default)] +pub struct OpaqueFnEntry<'tcx> { + // The trait ref is already stored as a key, so just track if we have it as a real predicate + has_fn_once: bool, + fn_mut_trait_ref: Option>, + fn_trait_ref: Option>, + return_ty: Option>>, +} diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs index b1bc073ca9..34f8062719 100644 --- a/compiler/rustc_middle/src/ty/query.rs +++ b/compiler/rustc_middle/src/ty/query.rs @@ -102,6 +102,10 @@ impl TyCtxt<'tcx> { } } +/// Helper for `TyCtxtEnsure` to avoid a closure. +#[inline(always)] +fn noop(_: &T) {} + macro_rules! query_helper_param_ty { (DefId) => { impl IntoQueryParam }; ($K:ty) => { $K }; @@ -119,6 +123,39 @@ macro_rules! query_storage { }; } +macro_rules! separate_provide_extern_decl { + ([][$name:ident]) => { + () + }; + ([(separate_provide_extern) $($rest:tt)*][$name:ident]) => { + for<'tcx> fn( + TyCtxt<'tcx>, + query_keys::$name<'tcx>, + ) -> query_values::$name<'tcx> + }; + ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => { + separate_provide_extern_decl!([$($modifiers)*][$($args)*]) + }; +} + +macro_rules! separate_provide_extern_default { + ([][$name:ident]) => { + () + }; + ([(separate_provide_extern) $($rest:tt)*][$name:ident]) => { + |_, key| bug!( + "`tcx.{}({:?})` unsupported by its crate; \ + perhaps the `{}` query was never assigned a provider function", + stringify!($name), + key, + stringify!($name), + ) + }; + ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => { + separate_provide_extern_default!([$($modifiers)*][$($args)*]) + }; +} + macro_rules! define_callbacks { (<$tcx:tt> $($(#[$attr:meta])* @@ -165,7 +202,7 @@ macro_rules! define_callbacks { #[inline(always)] pub fn $name(self, key: query_helper_param_ty!($($K)*)) { let key = key.into_query_param(); - let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, |_| {}); + let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, noop); let lookup = match cached { Ok(()) => return, @@ -192,9 +229,7 @@ macro_rules! define_callbacks { pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> query_stored::$name<$tcx> { let key = key.into_query_param(); - let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, |value| { - value.clone() - }); + let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, Clone::clone); let lookup = match cached { Ok(value) => return value, @@ -212,6 +247,10 @@ macro_rules! define_callbacks { ) -> query_values::$name<'tcx>,)* } + pub struct ExternProviders { + $(pub $name: separate_provide_extern_decl!([$($modifiers)*][$name]),)* + } + impl Default for Providers { fn default() -> Self { Providers { @@ -226,11 +265,24 @@ macro_rules! define_callbacks { } } + impl Default for ExternProviders { + fn default() -> Self { + ExternProviders { + $($name: separate_provide_extern_default!([$($modifiers)*][$name]),)* + } + } + } + impl Copy for Providers {} impl Clone for Providers { fn clone(&self) -> Self { *self } } + impl Copy for ExternProviders {} + impl Clone for ExternProviders { + fn clone(&self) -> Self { *self } + } + pub trait QueryEngine<'tcx>: rustc_data_structures::sync::Sync { fn as_any(&'tcx self) -> &'tcx dyn std::any::Any; diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 2c78653801..c7d8bec506 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -187,8 +187,12 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> { }) .enumerate() .map(|(i, r)| match r { - Err(TypeError::Sorts(exp_found)) => Err(TypeError::ArgumentSorts(exp_found, i)), - Err(TypeError::Mutability) => Err(TypeError::ArgumentMutability(i)), + Err(TypeError::Sorts(exp_found) | TypeError::ArgumentSorts(exp_found, _)) => { + Err(TypeError::ArgumentSorts(exp_found, i)) + } + Err(TypeError::Mutability | TypeError::ArgumentMutability(_)) => { + Err(TypeError::ArgumentMutability(i)) + } r => r, }); Ok(ty::FnSig { @@ -797,6 +801,20 @@ impl<'tcx> Relate<'tcx> for GenericArg<'tcx> { } } +impl<'tcx> Relate<'tcx> for ty::ImplPolarity { + fn relate>( + relation: &mut R, + a: ty::ImplPolarity, + b: ty::ImplPolarity, + ) -> RelateResult<'tcx, ty::ImplPolarity> { + if a != b { + Err(TypeError::PolarityMismatch(expected_found(relation, a, b))) + } else { + Ok(a) + } + } +} + impl<'tcx> Relate<'tcx> for ty::TraitPredicate<'tcx> { fn relate>( relation: &mut R, @@ -806,6 +824,7 @@ impl<'tcx> Relate<'tcx> for ty::TraitPredicate<'tcx> { Ok(ty::TraitPredicate { trait_ref: relation.relate(a.trait_ref, b.trait_ref)?, constness: relation.relate(a.constness, b.constness)?, + polarity: relation.relate(a.polarity, b.polarity)?, }) } } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 8f343ba9fe..0f8e80806e 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -157,7 +157,7 @@ impl fmt::Debug for ty::TraitPredicate<'tcx> { if let ty::BoundConstness::ConstIfConst = self.constness { write!(f, "~const ")?; } - write!(f, "TraitPredicate({:?})", self.trait_ref) + write!(f, "TraitPredicate({:?}, polarity:{:?})", self.trait_ref, self.polarity) } } @@ -365,8 +365,11 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ExistentialPredicate<'a> { impl<'a, 'tcx> Lift<'tcx> for ty::TraitPredicate<'a> { type Lifted = ty::TraitPredicate<'tcx>; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option> { - tcx.lift(self.trait_ref) - .map(|trait_ref| ty::TraitPredicate { trait_ref, constness: self.constness }) + tcx.lift(self.trait_ref).map(|trait_ref| ty::TraitPredicate { + trait_ref, + constness: self.constness, + polarity: self.polarity, + }) } } @@ -591,6 +594,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> { Some(match self { Mismatch => Mismatch, ConstnessMismatch(x) => ConstnessMismatch(x), + PolarityMismatch(x) => PolarityMismatch(x), UnsafetyMismatch(x) => UnsafetyMismatch(x), AbiMismatch(x) => AbiMismatch(x), Mutability => Mutability, @@ -598,6 +602,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> { TupleSize(x) => TupleSize(x), FixedArraySize(x) => FixedArraySize(x), ArgCount => ArgCount, + FieldMisMatch(x, y) => FieldMisMatch(x, y), RegionsDoesNotOutlive(a, b) => { return tcx.lift((a, b)).map(|(a, b)| RegionsDoesNotOutlive(a, b)); } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index d3094b3e6f..c2b32cd06e 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -704,6 +704,66 @@ impl<'tcx> UpvarSubsts<'tcx> { } } +/// An inline const is modeled like +/// +/// const InlineConst<'l0...'li, T0...Tj, R>: R; +/// +/// where: +/// +/// - 'l0...'li and T0...Tj are the generic parameters +/// inherited from the item that defined the inline const, +/// - R represents the type of the constant. +/// +/// When the inline const is instantiated, `R` is substituted as the actual inferred +/// type of the constant. The reason that `R` is represented as an extra type parameter +/// is the same reason that [`ClosureSubsts`] have `CS` and `U` as type parameters: +/// inline const can reference lifetimes that are internal to the creating function. +#[derive(Copy, Clone, Debug, TypeFoldable)] +pub struct InlineConstSubsts<'tcx> { + /// Generic parameters from the enclosing item, + /// concatenated with the inferred type of the constant. + pub substs: SubstsRef<'tcx>, +} + +/// Struct returned by `split()`. +pub struct InlineConstSubstsParts<'tcx, T> { + pub parent_substs: &'tcx [GenericArg<'tcx>], + pub ty: T, +} + +impl<'tcx> InlineConstSubsts<'tcx> { + /// Construct `InlineConstSubsts` from `InlineConstSubstsParts`. + pub fn new( + tcx: TyCtxt<'tcx>, + parts: InlineConstSubstsParts<'tcx, Ty<'tcx>>, + ) -> InlineConstSubsts<'tcx> { + InlineConstSubsts { + substs: tcx.mk_substs( + parts.parent_substs.iter().copied().chain(std::iter::once(parts.ty.into())), + ), + } + } + + /// Divides the inline const substs into their respective components. + /// The ordering assumed here must match that used by `InlineConstSubsts::new` above. + fn split(self) -> InlineConstSubstsParts<'tcx, GenericArg<'tcx>> { + match self.substs[..] { + [ref parent_substs @ .., ty] => InlineConstSubstsParts { parent_substs, ty }, + _ => bug!("inline const substs missing synthetics"), + } + } + + /// Returns the substitutions of the inline const's parent. + pub fn parent_substs(self) -> &'tcx [GenericArg<'tcx>] { + self.split().parent_substs + } + + /// Returns the type of this inline const. + pub fn ty(self) -> Ty<'tcx> { + self.split().ty.expect_ty() + } +} + #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash, TyEncodable, TyDecodable)] #[derive(HashStable, TypeFoldable)] pub enum ExistentialPredicate<'tcx> { @@ -830,7 +890,7 @@ impl<'tcx> List>> { /// /// Trait references also appear in object types like `Foo`, but in /// that case the `Self` parameter is absent from the substitutions. -#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] #[derive(HashStable, TypeFoldable)] pub struct TraitRef<'tcx> { pub def_id: DefId, @@ -882,6 +942,7 @@ impl<'tcx> PolyTraitRef<'tcx> { self.map_bound(|trait_ref| ty::TraitPredicate { trait_ref, constness: ty::BoundConstness::NotConst, + polarity: ty::ImplPolarity::Positive, }) } } @@ -1744,10 +1805,13 @@ impl<'tcx> TyS<'tcx> { pub fn simd_size_and_type(&self, tcx: TyCtxt<'tcx>) -> (u64, Ty<'tcx>) { match self.kind() { Adt(def, substs) => { + assert!(def.repr.simd(), "`simd_size_and_type` called on non-SIMD type"); let variant = def.non_enum_variant(); let f0_ty = variant.fields[0].ty(tcx, substs); match f0_ty.kind() { + // If the first field is an array, we assume it is the only field and its + // elements are the SIMD components. Array(f0_elem_ty, f0_len) => { // FIXME(repr_simd): https://github.com/rust-lang/rust/pull/78863#discussion_r522784112 // The way we evaluate the `N` in `[T; N]` here only works since we use @@ -1755,6 +1819,8 @@ impl<'tcx> TyS<'tcx> { // if we use it in generic code. See the `simd-array-trait` ui test. (f0_len.eval_usize(tcx, ParamEnv::empty()) as u64, f0_elem_ty) } + // Otherwise, the fields of this Adt are the SIMD components (and we assume they + // all have the same type). _ => (variant.fields.len() as u64, f0_ty), } } @@ -2006,7 +2072,9 @@ impl<'tcx> TyS<'tcx> { ) -> Option> { match self.kind() { TyKind::Adt(adt, _) if adt.variants.is_empty() => { - bug!("discriminant_for_variant called on zero variant enum"); + // This can actually happen during CTFE, see + // https://github.com/rust-lang/rust/issues/89765. + None } TyKind::Adt(adt, _) if adt.is_enum() => { Some(adt.discriminant_for_variant(tcx, variant_index)) @@ -2025,10 +2093,10 @@ impl<'tcx> TyS<'tcx> { ty::Generator(_, substs, _) => substs.as_generator().discr_ty(tcx), ty::Param(_) | ty::Projection(_) | ty::Opaque(..) | ty::Infer(ty::TyVar(_)) => { - let assoc_items = - tcx.associated_items(tcx.lang_items().discriminant_kind_trait().unwrap()); - let discriminant_def_id = assoc_items.in_definition_order().next().unwrap().def_id; - tcx.mk_projection(discriminant_def_id, tcx.mk_substs([self.into()].iter())) + let assoc_items = tcx.associated_item_def_ids( + tcx.require_lang_item(hir::LangItem::DiscriminantKind, None), + ); + tcx.mk_projection(assoc_items[0], tcx.intern_substs(&[self.into()])) } ty::Bool @@ -2195,10 +2263,11 @@ impl<'tcx> TyS<'tcx> { /// a miscompilation or unsoundness. /// /// When in doubt, use `VarianceDiagInfo::default()` -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)] pub enum VarianceDiagInfo<'tcx> { /// No additional information - this is the default. /// We will not add any additional information to error messages. + #[default] None, /// We switched our variance because a type occurs inside /// the generic argument of a mutable reference or pointer @@ -2233,9 +2302,3 @@ impl<'tcx> VarianceDiagInfo<'tcx> { } } } - -impl<'tcx> Default for VarianceDiagInfo<'tcx> { - fn default() -> Self { - Self::None - } -} diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 2438d1a160..73a8e18949 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -3,7 +3,7 @@ use crate::mir; use crate::ty::codec::{TyDecoder, TyEncoder}; use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; -use crate::ty::sty::{ClosureSubsts, GeneratorSubsts}; +use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts}; use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt}; use rustc_hir::def_id::DefId; @@ -204,6 +204,14 @@ impl<'a, 'tcx> InternalSubsts<'tcx> { GeneratorSubsts { substs: self } } + /// Interpret these substitutions as the substitutions of an inline const. + /// Inline const substitutions have a particular structure controlled by the + /// compiler that encodes information like the inferred type; + /// see `ty::InlineConstSubsts` struct for more comments. + pub fn as_inline_const(&'tcx self) -> InlineConstSubsts<'tcx> { + InlineConstSubsts { substs: self } + } + /// Creates an `InternalSubsts` that maps each generic parameter to itself. pub fn identity_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx> { Self::for_item(tcx, def_id, |param, _| tcx.mk_param_from_def(param)) diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 2c884813d2..6e7acb244d 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -325,9 +325,9 @@ impl<'tcx> TyCtxt<'tcx> { let ty = self.type_of(adt_did); let (did, constness) = self.find_map_relevant_impl(drop_trait, ty, |impl_did| { - if let Some(item) = self.associated_items(impl_did).in_definition_order().next() { + if let Some(item_id) = self.associated_item_def_ids(impl_did).first() { if validate(self, impl_did).is_ok() { - return Some((item.def_id, self.impl_constness(impl_did))); + return Some((*item_id, self.impl_constness(impl_did))); } } None @@ -423,6 +423,15 @@ impl<'tcx> TyCtxt<'tcx> { matches!(self.def_kind(def_id), DefKind::Closure | DefKind::Generator) } + /// Returns `true` if `def_id` refers to a definition that does not have its own + /// type-checking context, i.e. closure, generator or inline const. + pub fn is_typeck_child(self, def_id: DefId) -> bool { + matches!( + self.def_kind(def_id), + DefKind::Closure | DefKind::Generator | DefKind::InlineConst + ) + } + /// Returns `true` if `def_id` refers to a trait (i.e., `trait Foo { ... }`). pub fn is_trait(self, def_id: DefId) -> bool { self.def_kind(def_id) == DefKind::Trait @@ -440,16 +449,19 @@ impl<'tcx> TyCtxt<'tcx> { matches!(self.def_kind(def_id), DefKind::Ctor(..)) } - /// Given the def-ID of a fn or closure, returns the def-ID of - /// the innermost fn item that the closure is contained within. - /// This is a significant `DefId` because, when we do - /// type-checking, we type-check this fn item and all of its - /// (transitive) closures together. Therefore, when we fetch the + /// Given the `DefId`, returns the `DefId` of the innermost item that + /// has its own type-checking context or "inference enviornment". + /// + /// For example, a closure has its own `DefId`, but it is type-checked + /// with the containing item. Similarly, an inline const block has its + /// own `DefId` but it is type-checked together with the containing item. + /// + /// Therefore, when we fetch the /// `typeck` the closure, for example, we really wind up /// fetching the `typeck` the enclosing fn item. - pub fn closure_base_def_id(self, def_id: DefId) -> DefId { + pub fn typeck_root_def_id(self, def_id: DefId) -> DefId { let mut def_id = def_id; - while self.is_closure(def_id) { + while self.is_typeck_child(def_id) { def_id = self.parent(def_id).unwrap_or_else(|| { bug!("closure {:?} has no parent", def_id); }); diff --git a/compiler/rustc_middle/src/util/common.rs b/compiler/rustc_middle/src/util/common.rs index da857b0a40..08977049db 100644 --- a/compiler/rustc_middle/src/util/common.rs +++ b/compiler/rustc_middle/src/util/common.rs @@ -34,7 +34,7 @@ where let rv = f(); let duration = start.elapsed(); let mut accu = accu.lock(); - *accu = *accu + duration; + *accu += duration; rv } 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 05995ddcc0..c6a34ece24 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -221,15 +221,13 @@ fn to_upvars_resolved_place_builder<'a, 'tcx>( let closure_hir_id = tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local()); let closure_span = tcx.hir().span(closure_hir_id); - let (capture_index, capture) = if let Some(capture_details) = + let Some((capture_index, capture)) = find_capture_matching_projections( typeck_results, var_hir_id, closure_def_id, &from_builder.projection, - ) { - capture_details - } else { + ) else { if !enable_precise_capture(tcx, closure_span) { bug!( "No associated capture found for {:?}[{:#?}] even though \ diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 4df073c40e..e3a05e01ea 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -1606,13 +1606,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // encounter a candidate where the test is not relevant; at // that point, we stop sorting. while let Some(candidate) = candidates.first_mut() { - if let Some(idx) = self.sort_candidate(&match_place.clone(), &test, candidate) { - let (candidate, rest) = candidates.split_first_mut().unwrap(); - target_candidates[idx].push(candidate); - candidates = rest; - } else { + let Some(idx) = self.sort_candidate(&match_place.clone(), &test, candidate) else { break; - } + }; + let (candidate, rest) = candidates.split_first_mut().unwrap(); + target_candidates[idx].push(candidate); + candidates = rest; } // at least the first candidate ought to be tested assert!(total_candidate_count > candidates.len()); @@ -1762,8 +1761,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ) -> BlockAnd<()> { let expr_span = expr.span; let expr_place_builder = unpack!(block = self.lower_scrutinee(block, expr, expr_span)); - let mut guard_candidate = Candidate::new(expr_place_builder.clone(), &pat, false); let wildcard = Pat::wildcard_from_ty(pat.ty); + let mut guard_candidate = Candidate::new(expr_place_builder.clone(), &pat, false); let mut otherwise_candidate = Candidate::new(expr_place_builder.clone(), &wildcard, false); let fake_borrow_temps = self.lower_match_tree( block, diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 4108ad5047..cb94e75997 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -966,59 +966,58 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { DropKind::Value, ); - if let Some(arg) = arg_opt { - let pat = match tcx.hir().get(arg.pat.hir_id) { - Node::Pat(pat) | Node::Binding(pat) => pat, - node => bug!("pattern became {:?}", node), - }; - let pattern = pat_from_hir(tcx, self.param_env, self.typeck_results, pat); - let original_source_scope = self.source_scope; - let span = pattern.span; - self.set_correct_source_scope_for_arg(arg.hir_id, original_source_scope, span); - match *pattern.kind { - // Don't introduce extra copies for simple bindings - PatKind::Binding { - mutability, - var, - mode: BindingMode::ByValue, - subpattern: None, - .. - } => { - self.local_decls[local].mutability = mutability; - self.local_decls[local].source_info.scope = self.source_scope; - self.local_decls[local].local_info = if let Some(kind) = self_binding { - Some(Box::new(LocalInfo::User(ClearCrossCrate::Set( - BindingForm::ImplicitSelf(*kind), - )))) - } else { - let binding_mode = ty::BindingMode::BindByValue(mutability); - Some(Box::new(LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var( - VarBindingForm { - binding_mode, - opt_ty_info, - opt_match_place: Some((Some(place), span)), - pat_span: span, - }, - ))))) - }; - self.var_indices.insert(var, LocalsForNode::One(local)); - } - _ => { - scope = self.declare_bindings( - scope, - expr.span, - &pattern, - matches::ArmHasGuard(false), - Some((Some(&place), span)), - ); - let place_builder = PlaceBuilder::from(local); - unpack!( - block = self.place_into_pattern(block, pattern, place_builder, false) - ); - } + let Some(arg) = arg_opt else { + continue; + }; + let pat = match tcx.hir().get(arg.pat.hir_id) { + Node::Pat(pat) | Node::Binding(pat) => pat, + node => bug!("pattern became {:?}", node), + }; + let pattern = pat_from_hir(tcx, self.param_env, self.typeck_results, pat); + let original_source_scope = self.source_scope; + let span = pattern.span; + self.set_correct_source_scope_for_arg(arg.hir_id, original_source_scope, span); + match *pattern.kind { + // Don't introduce extra copies for simple bindings + PatKind::Binding { + mutability, + var, + mode: BindingMode::ByValue, + subpattern: None, + .. + } => { + self.local_decls[local].mutability = mutability; + self.local_decls[local].source_info.scope = self.source_scope; + self.local_decls[local].local_info = if let Some(kind) = self_binding { + Some(Box::new(LocalInfo::User(ClearCrossCrate::Set( + BindingForm::ImplicitSelf(*kind), + )))) + } else { + let binding_mode = ty::BindingMode::BindByValue(mutability); + Some(Box::new(LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var( + VarBindingForm { + binding_mode, + opt_ty_info, + opt_match_place: Some((Some(place), span)), + pat_span: span, + }, + ))))) + }; + self.var_indices.insert(var, LocalsForNode::One(local)); + } + _ => { + scope = self.declare_bindings( + scope, + expr.span, + &pattern, + matches::ArmHasGuard(false), + Some((Some(&place), span)), + ); + let place_builder = PlaceBuilder::from(local); + unpack!(block = self.place_into_pattern(block, pattern, place_builder, false)); } - self.source_scope = original_source_scope; } + self.source_scope = original_source_scope; } // Enter the argument pattern bindings source scope, if it exists. diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index b74208edaf..8dadbf5f02 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -362,11 +362,7 @@ impl DropTree { blocks: &IndexVec>, ) { for (drop_idx, drop_data) in self.drops.iter_enumerated().rev() { - let block = if let Some(block) = blocks[drop_idx] { - block - } else { - continue; - }; + let Some(block) = blocks[drop_idx] else { continue }; match drop_data.0.kind { DropKind::Value => { let terminator = TerminatorKind::Drop { diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 0e82b18720..7940bd1f33 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -256,23 +256,22 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { } PatKind::Binding { mode: BindingMode::ByRef(borrow_kind), ty, .. } => { if self.inside_adt { - if let ty::Ref(_, ty, _) = ty.kind() { - match borrow_kind { - BorrowKind::Shallow | BorrowKind::Shared | BorrowKind::Unique => { - if !ty.is_freeze(self.tcx.at(pat.span), self.param_env) { - self.requires_unsafe(pat.span, BorrowOfLayoutConstrainedField); - } - } - BorrowKind::Mut { .. } => { - self.requires_unsafe(pat.span, MutationOfLayoutConstrainedField); - } - } - } else { + let ty::Ref(_, ty, _) = ty.kind() else { span_bug!( pat.span, "BindingMode::ByRef in pattern, but found non-reference type {}", ty ); + }; + match borrow_kind { + BorrowKind::Shallow | BorrowKind::Shared | BorrowKind::Unique => { + if !ty.is_freeze(self.tcx.at(pat.span), self.param_env) { + self.requires_unsafe(pat.span, BorrowOfLayoutConstrainedField); + } + } + BorrowKind::Mut { .. } => { + self.requires_unsafe(pat.span, MutationOfLayoutConstrainedField); + } } } visit::walk_pat(self, pat); diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index 02023c48a6..b0f1e08562 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -6,6 +6,7 @@ #![feature(crate_visibility_modifier)] #![feature(bool_to_option)] #![feature(iter_zip)] +#![feature(let_else)] #![feature(once_cell)] #![feature(min_specialization)] #![recursion_limit = "256"] diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs index ef8bd20d51..e4c2d2dce6 100644 --- a/compiler/rustc_mir_build/src/lints.rs +++ b/compiler/rustc_mir_build/src/lints.rs @@ -2,7 +2,6 @@ use rustc_data_structures::graph::iterate::{ NodeStatus, TriColorDepthFirstSearch, TriColorVisitor, }; use rustc_hir::intravisit::FnKind; -use rustc_middle::hir::map::blocks::FnLikeNode; use rustc_middle::mir::{BasicBlock, Body, Operand, TerminatorKind}; use rustc_middle::ty::subst::{GenericArg, InternalSubsts}; use rustc_middle::ty::{self, AssocItem, AssocItemContainer, Instance, TyCtxt}; @@ -14,8 +13,8 @@ crate fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { let def_id = body.source.def_id().expect_local(); let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - if let Some(fn_like_node) = FnLikeNode::from_node(tcx.hir().get(hir_id)) { - if let FnKind::Closure = fn_like_node.kind() { + if let Some(fn_kind) = tcx.hir().get(hir_id).fn_kind() { + if let FnKind::Closure = fn_kind { // closures can't recur, so they don't matter. return; } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 17296a95bc..b4005ccd1c 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -578,7 +578,7 @@ impl<'tcx> Cx<'tcx> { hir::ExprKind::ConstBlock(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 value = ty::Const::from_inline_const(self.tcx, anon_const_def_id); ExprKind::ConstBlock { value } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index e28fd2c508..d74c53fae5 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -74,19 +74,16 @@ impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, '_, 'tcx> { let (msg, sp) = match loc.source { hir::LocalSource::Normal => ("local binding", Some(loc.span)), - hir::LocalSource::ForLoopDesugar => ("`for` loop binding", None), hir::LocalSource::AsyncFn => ("async fn binding", None), hir::LocalSource::AwaitDesugar => ("`await` future binding", None), hir::LocalSource::AssignDesugar(_) => ("destructuring assignment binding", None), }; self.check_irrefutable(&loc.pat, msg, sp); - self.check_patterns(&loc.pat, Irrefutable); } fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) { intravisit::walk_param(self, param); self.check_irrefutable(¶m.pat, "function argument", None); - self.check_patterns(¶m.pat, Irrefutable); } } @@ -161,12 +158,12 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { fn check_match( &mut self, scrut: &hir::Expr<'_>, - arms: &'tcx [hir::Arm<'tcx>], + hir_arms: &'tcx [hir::Arm<'tcx>], source: hir::MatchSource, ) { let mut cx = self.new_cx(scrut.hir_id); - for arm in arms { + for arm in hir_arms { // Check the arm for some things unrelated to exhaustiveness. self.check_patterns(&arm.pat, Refutable); if let Some(hir::Guard::IfLet(ref pat, _)) = arm.guard { @@ -178,7 +175,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { let mut have_errors = false; - let arms: Vec<_> = arms + let arms: Vec<_> = hir_arms .iter() .map(|hir::Arm { pat, guard, .. }| MatchArm { pat: self.lower_pattern(&mut cx, pat, &mut have_errors), @@ -196,6 +193,9 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { let report = compute_match_usefulness(&cx, &arms, scrut.hir_id, scrut_ty); match source { + // Don't report arm reachability of desugared `match $iter.into_iter() { iter => .. }` + // when the iterator is an uninhabited type. unreachable_code will trigger instead. + hir::MatchSource::ForLoopDesugar if arms.len() == 1 => {} hir::MatchSource::ForLoopDesugar | hir::MatchSource::Normal => { report_arm_reachability(&cx, &report) } @@ -208,7 +208,13 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { let is_empty_match = arms.is_empty(); let witnesses = report.non_exhaustiveness_witnesses; if !witnesses.is_empty() { - non_exhaustive_match(&cx, scrut_ty, scrut.span, witnesses, is_empty_match); + if source == hir::MatchSource::ForLoopDesugar && hir_arms.len() == 2 { + // the for loop pattern is not irrefutable + let pat = hir_arms[1].pat.for_loop_some().unwrap(); + self.check_irrefutable(pat, "`for` loop binding", None); + } else { + non_exhaustive_match(&cx, scrut_ty, scrut.span, witnesses, is_empty_match); + } } } @@ -225,6 +231,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { let witnesses = report.non_exhaustiveness_witnesses; if witnesses.is_empty() { // The pattern is irrefutable. + self.check_patterns(pat, Irrefutable); return; } 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 847b89f046..dd16e3cde7 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 @@ -130,6 +130,9 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { traits::NonStructuralMatchTy::Opaque => { "opaque types cannot be used in patterns".to_string() } + traits::NonStructuralMatchTy::Closure => { + "closures cannot be used in patterns".to_string() + } traits::NonStructuralMatchTy::Generator => { "generators cannot be used in patterns".to_string() } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index cb74ae4df2..ce80214c87 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -544,7 +544,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let (lit, neg) = match expr.kind { hir::ExprKind::ConstBlock(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 value = ty::Const::from_inline_const(self.tcx, anon_const_def_id); if matches!(value.val, ConstKind::Param(_)) { let span = self.tcx.hir().span(anon_const.hir_id); self.errors.push(PatternError::ConstParamInPattern(span)); diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs index d959d2f7f6..286473c38e 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs @@ -289,6 +289,7 @@ use super::deconstruct_pat::{Constructor, DeconstructedPat, Fields, SplitWildcar use rustc_data_structures::captures::Captures; use rustc_arena::TypedArena; +use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::def_id::DefId; use rustc_hir::HirId; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -443,9 +444,7 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> { /// expands it. fn push(&mut self, row: PatStack<'p, 'tcx>) { if !row.is_empty() && row.head().is_or_pat() { - for row in row.expand_or_pat() { - self.patterns.push(row); - } + self.patterns.extend(row.expand_or_pat()); } else { self.patterns.push(row); } @@ -797,7 +796,7 @@ fn is_useful<'p, 'tcx>( return ret; } - assert!(rows.iter().all(|r| r.len() == v.len())); + debug_assert!(rows.iter().all(|r| r.len() == v.len())); let ty = v.head().ty(); let is_non_exhaustive = cx.is_foreign_non_exhaustive_enum(ty); @@ -810,8 +809,9 @@ fn is_useful<'p, 'tcx>( // We try each or-pattern branch in turn. let mut matrix = matrix.clone(); for v in v.expand_or_pat() { - let usefulness = - is_useful(cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false); + let usefulness = ensure_sufficient_stack(|| { + is_useful(cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false) + }); ret.extend(usefulness); // If pattern has a guard don't add it to the matrix. if !is_under_guard { @@ -842,8 +842,9 @@ fn is_useful<'p, 'tcx>( // We cache the result of `Fields::wildcards` because it is used a lot. let spec_matrix = start_matrix.specialize_constructor(pcx, &ctor); let v = v.pop_head_constructor(cx, &ctor); - let usefulness = - is_useful(cx, &spec_matrix, &v, witness_preference, hir_id, is_under_guard, false); + let usefulness = ensure_sufficient_stack(|| { + is_useful(cx, &spec_matrix, &v, witness_preference, hir_id, is_under_guard, false) + }); let usefulness = usefulness.apply_constructor(pcx, start_matrix, &ctor); // When all the conditions are met we have a match with a `non_exhaustive` enum diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 7607ccc3ab..11856f6e04 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -604,7 +604,7 @@ where debug!("destructor_call_block({:?}, {:?})", self, succ); let tcx = self.tcx(); let drop_trait = tcx.require_lang_item(LangItem::Drop, None); - let drop_fn = tcx.associated_items(drop_trait).in_definition_order().next().unwrap(); + let drop_fn = tcx.associated_item_def_ids(drop_trait)[0]; let ty = self.place_ty(self.place); let substs = tcx.mk_substs_trait(ty, &[]); @@ -624,12 +624,7 @@ where )], terminator: Some(Terminator { kind: TerminatorKind::Call { - func: Operand::function_handle( - tcx, - drop_fn.def_id, - substs, - self.source_info.span, - ), + func: Operand::function_handle(tcx, drop_fn, substs, self.source_info.span), args: vec![Operand::Move(Place::from(ref_place))], destination: Some((unit_temp, succ)), cleanup: unwind.into_option(), diff --git a/compiler/rustc_mir_dataflow/src/framework/cursor.rs b/compiler/rustc_mir_dataflow/src/framework/cursor.rs index c000e49c14..ba6b566a30 100644 --- a/compiler/rustc_mir_dataflow/src/framework/cursor.rs +++ b/compiler/rustc_mir_dataflow/src/framework/cursor.rs @@ -64,6 +64,13 @@ where } } + /// Allows inspection of unreachable basic blocks even with `debug_assertions` enabled. + #[cfg(test)] + pub(crate) fn allow_unreachable(&mut self) { + #[cfg(debug_assertions)] + self.reachable_blocks.insert_all() + } + /// Returns the underlying `Results`. pub fn results(&self) -> &Results<'tcx, A> { &self.results.borrow() diff --git a/compiler/rustc_mir_dataflow/src/framework/tests.rs b/compiler/rustc_mir_dataflow/src/framework/tests.rs index a598912167..6efa8daec4 100644 --- a/compiler/rustc_mir_dataflow/src/framework/tests.rs +++ b/compiler/rustc_mir_dataflow/src/framework/tests.rs @@ -268,6 +268,8 @@ fn test_cursor(analysis: MockAnalysis<'tcx, D>) { let mut cursor = Results { entry_sets: analysis.mock_entry_sets(), analysis }.into_results_cursor(body); + cursor.allow_unreachable(); + let every_target = || { body.basic_blocks() .iter_enumerated() diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs index 158ba1b942..d38b567a95 100644 --- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs +++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs @@ -3,25 +3,14 @@ use super::*; use crate::{AnalysisDomain, GenKill, GenKillAnalysis}; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; -use rustc_middle::ty::{ParamEnv, TyCtxt}; -use rustc_span::DUMMY_SP; - -pub type MaybeMutBorrowedLocals<'mir, 'tcx> = MaybeBorrowedLocals>; /// A dataflow analysis that tracks whether a pointer or reference could possibly exist that points /// to a given local. /// -/// The `K` parameter determines what kind of borrows are tracked. By default, -/// `MaybeBorrowedLocals` looks for *any* borrow of a local. If you are only interested in borrows -/// that might allow mutation, use the `MaybeMutBorrowedLocals` type alias instead. -/// /// At present, this is used as a very limited form of alias analysis. For example, /// `MaybeBorrowedLocals` is used to compute which locals are live during a yield expression for -/// immovable generators. `MaybeMutBorrowedLocals` is used during const checking to prove that a -/// local has not been mutated via indirect assignment (e.g., `*p = 42`), the side-effects of a -/// function call or inline assembly. -pub struct MaybeBorrowedLocals { - kind: K, +/// immovable generators. +pub struct MaybeBorrowedLocals { ignore_borrow_on_drop: bool, } @@ -29,29 +18,11 @@ impl MaybeBorrowedLocals { /// A dataflow analysis that records whether a pointer or reference exists that may alias the /// given local. pub fn all_borrows() -> Self { - MaybeBorrowedLocals { kind: AnyBorrow, ignore_borrow_on_drop: false } - } -} - -impl MaybeMutBorrowedLocals<'mir, 'tcx> { - /// A dataflow analysis that records whether a pointer or reference exists that may *mutably* - /// alias the given local. - /// - /// This includes `&mut` and pointers derived from an `&mut`, as well as shared borrows of - /// types with interior mutability. - pub fn mut_borrows_only( - tcx: TyCtxt<'tcx>, - body: &'mir mir::Body<'tcx>, - param_env: ParamEnv<'tcx>, - ) -> Self { - MaybeBorrowedLocals { - kind: MutBorrow { body, tcx, param_env }, - ignore_borrow_on_drop: false, - } + MaybeBorrowedLocals { ignore_borrow_on_drop: false } } } -impl MaybeBorrowedLocals { +impl MaybeBorrowedLocals { /// During dataflow analysis, ignore the borrow that may occur when a place is dropped. /// /// Drop terminators may call custom drop glue (`Drop::drop`), which takes `&mut self` as a @@ -69,21 +40,14 @@ impl MaybeBorrowedLocals { MaybeBorrowedLocals { ignore_borrow_on_drop: true, ..self } } - fn transfer_function<'a, T>(&'a self, trans: &'a mut T) -> TransferFunction<'a, T, K> { - TransferFunction { - kind: &self.kind, - trans, - ignore_borrow_on_drop: self.ignore_borrow_on_drop, - } + fn transfer_function<'a, T>(&'a self, trans: &'a mut T) -> TransferFunction<'a, T> { + TransferFunction { trans, ignore_borrow_on_drop: self.ignore_borrow_on_drop } } } -impl AnalysisDomain<'tcx> for MaybeBorrowedLocals -where - K: BorrowAnalysisKind<'tcx>, -{ +impl AnalysisDomain<'tcx> for MaybeBorrowedLocals { type Domain = BitSet; - const NAME: &'static str = K::ANALYSIS_NAME; + const NAME: &'static str = "maybe_borrowed_locals"; fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain { // bottom = unborrowed @@ -95,10 +59,7 @@ where } } -impl GenKillAnalysis<'tcx> for MaybeBorrowedLocals -where - K: BorrowAnalysisKind<'tcx>, -{ +impl GenKillAnalysis<'tcx> for MaybeBorrowedLocals { type Idx = Local; fn statement_effect( @@ -131,16 +92,14 @@ where } /// A `Visitor` that defines the transfer function for `MaybeBorrowedLocals`. -struct TransferFunction<'a, T, K> { +struct TransferFunction<'a, T> { trans: &'a mut T, - kind: &'a K, ignore_borrow_on_drop: bool, } -impl Visitor<'tcx> for TransferFunction<'a, T, K> +impl Visitor<'tcx> for TransferFunction<'a, T> where T: GenKill, - K: BorrowAnalysisKind<'tcx>, { fn visit_statement(&mut self, stmt: &Statement<'tcx>, location: Location) { self.super_statement(stmt, location); @@ -156,14 +115,14 @@ where self.super_rvalue(rvalue, location); match rvalue { - mir::Rvalue::AddressOf(mt, borrowed_place) => { - if !borrowed_place.is_indirect() && self.kind.in_address_of(*mt, *borrowed_place) { + mir::Rvalue::AddressOf(_mt, borrowed_place) => { + if !borrowed_place.is_indirect() { self.trans.gen(borrowed_place.local); } } - mir::Rvalue::Ref(_, kind, borrowed_place) => { - if !borrowed_place.is_indirect() && self.kind.in_ref(*kind, *borrowed_place) { + mir::Rvalue::Ref(_, _kind, borrowed_place) => { + if !borrowed_place.is_indirect() { self.trans.gen(borrowed_place.local); } } @@ -211,64 +170,3 @@ where } } } - -pub struct AnyBorrow; - -pub struct MutBorrow<'mir, 'tcx> { - tcx: TyCtxt<'tcx>, - body: &'mir Body<'tcx>, - param_env: ParamEnv<'tcx>, -} - -impl MutBorrow<'mir, 'tcx> { - /// `&` and `&raw` only allow mutation if the borrowed place is `!Freeze`. - /// - /// This assumes that it is UB to take the address of a struct field whose type is - /// `Freeze`, then use pointer arithmetic to derive a pointer to a *different* field of - /// that same struct whose type is `!Freeze`. If we decide that this is not UB, we will - /// have to check the type of the borrowed **local** instead of the borrowed **place** - /// below. See [rust-lang/unsafe-code-guidelines#134]. - /// - /// [rust-lang/unsafe-code-guidelines#134]: https://github.com/rust-lang/unsafe-code-guidelines/issues/134 - fn shared_borrow_allows_mutation(&self, place: Place<'tcx>) -> bool { - !place.ty(self.body, self.tcx).ty.is_freeze(self.tcx.at(DUMMY_SP), self.param_env) - } -} - -pub trait BorrowAnalysisKind<'tcx> { - const ANALYSIS_NAME: &'static str; - - fn in_address_of(&self, mt: Mutability, place: Place<'tcx>) -> bool; - fn in_ref(&self, kind: mir::BorrowKind, place: Place<'tcx>) -> bool; -} - -impl BorrowAnalysisKind<'tcx> for AnyBorrow { - const ANALYSIS_NAME: &'static str = "maybe_borrowed_locals"; - - fn in_ref(&self, _: mir::BorrowKind, _: Place<'_>) -> bool { - true - } - fn in_address_of(&self, _: Mutability, _: Place<'_>) -> bool { - true - } -} - -impl BorrowAnalysisKind<'tcx> for MutBorrow<'mir, 'tcx> { - const ANALYSIS_NAME: &'static str = "maybe_mut_borrowed_locals"; - - fn in_ref(&self, kind: mir::BorrowKind, place: Place<'tcx>) -> bool { - match kind { - mir::BorrowKind::Mut { .. } => true, - mir::BorrowKind::Shared | mir::BorrowKind::Shallow | mir::BorrowKind::Unique => { - self.shared_borrow_allows_mutation(place) - } - } - } - - fn in_address_of(&self, mt: Mutability, place: Place<'tcx>) -> bool { - match mt { - Mutability::Mut => true, - Mutability::Not => self.shared_borrow_allows_mutation(place), - } - } -} diff --git a/compiler/rustc_mir_dataflow/src/impls/mod.rs b/compiler/rustc_mir_dataflow/src/impls/mod.rs index 474f4f2a79..2585701f60 100644 --- a/compiler/rustc_mir_dataflow/src/impls/mod.rs +++ b/compiler/rustc_mir_dataflow/src/impls/mod.rs @@ -4,17 +4,18 @@ use rustc_index::bit_set::BitSet; use rustc_index::vec::Idx; +use rustc_middle::mir::visit::{MirVisitable, Visitor}; use rustc_middle::mir::{self, Body, Location}; use rustc_middle::ty::{self, TyCtxt}; -use crate::drop_flag_effects; use crate::drop_flag_effects_for_function_entry; use crate::drop_flag_effects_for_location; use crate::elaborate_drops::DropFlagState; use crate::framework::SwitchIntEdgeEffects; -use crate::move_paths::{HasMoveData, InitIndex, InitKind, MoveData, MovePathIndex}; +use crate::move_paths::{HasMoveData, InitIndex, InitKind, LookupResult, MoveData, MovePathIndex}; use crate::on_lookup_result_bits; use crate::MoveDataParamEnv; +use crate::{drop_flag_effects, on_all_children_bits}; use crate::{lattice, AnalysisDomain, GenKill, GenKillAnalysis}; mod borrowed_locals; @@ -22,7 +23,7 @@ mod init_locals; mod liveness; mod storage_liveness; -pub use self::borrowed_locals::{MaybeBorrowedLocals, MaybeMutBorrowedLocals}; +pub use self::borrowed_locals::MaybeBorrowedLocals; pub use self::init_locals::MaybeInitializedLocals; pub use self::liveness::MaybeLiveLocals; pub use self::storage_liveness::{MaybeRequiresStorage, MaybeStorageLive}; @@ -307,22 +308,45 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { fn statement_effect( &self, trans: &mut impl GenKill, - _statement: &mir::Statement<'tcx>, + statement: &mir::Statement<'tcx>, location: Location, ) { drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| { Self::update_bits(trans, path, s) + }); + + if !self.tcx.sess.opts.debugging_opts.precise_enum_drop_elaboration { + return; + } + + // Mark all places as "maybe init" if they are mutably borrowed. See #90752. + for_each_mut_borrow(statement, location, |place| { + let LookupResult::Exact(mpi) = self.move_data().rev_lookup.find(place.as_ref()) else { return }; + on_all_children_bits(self.tcx, self.body, self.move_data(), mpi, |child| { + trans.gen(child); + }) }) } fn terminator_effect( &self, trans: &mut impl GenKill, - _terminator: &mir::Terminator<'tcx>, + terminator: &mir::Terminator<'tcx>, location: Location, ) { drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| { Self::update_bits(trans, path, s) + }); + + if !self.tcx.sess.opts.debugging_opts.precise_enum_drop_elaboration { + return; + } + + for_each_mut_borrow(terminator, location, |place| { + let LookupResult::Exact(mpi) = self.move_data().rev_lookup.find(place.as_ref()) else { return }; + on_all_children_bits(self.tcx, self.body, self.move_data(), mpi, |child| { + trans.gen(child); + }) }) } @@ -427,7 +451,10 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { ) { drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| { Self::update_bits(trans, path, s) - }) + }); + + // Unlike in `MaybeInitializedPlaces` above, we don't need to change the state when a + // mutable borrow occurs. Places cannot become uninitialized through a mutable reference. } fn terminator_effect( @@ -438,7 +465,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { ) { drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| { Self::update_bits(trans, path, s) - }) + }); } fn call_return_effect( @@ -704,3 +731,37 @@ fn switch_on_enum_discriminant( _ => None, } } + +struct OnMutBorrow(F); + +impl Visitor<'_> for OnMutBorrow +where + F: FnMut(&mir::Place<'_>), +{ + fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'_>, location: Location) { + // FIXME: Does `&raw const foo` allow mutation? See #90413. + match rvalue { + mir::Rvalue::Ref(_, mir::BorrowKind::Mut { .. }, place) + | mir::Rvalue::AddressOf(_, place) => (self.0)(place), + + _ => {} + } + + self.super_rvalue(rvalue, location) + } +} + +/// Calls `f` for each mutable borrow or raw reference in the program. +/// +/// This DOES NOT call `f` for a shared borrow of a type with interior mutability. That's okay for +/// initializedness, because we cannot move from an `UnsafeCell` (outside of `core::cell`), but +/// other analyses will likely need to check for `!Freeze`. +fn for_each_mut_borrow<'tcx>( + mir: &impl MirVisitable<'tcx>, + location: Location, + f: impl FnMut(&mir::Place<'_>), +) { + let mut vis = OnMutBorrow(f); + + mir.apply(location, &mut vis); +} diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index 402391b87e..77a72ce63c 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -2,10 +2,10 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] -#![cfg_attr(bootstrap, feature(const_panic))] #![feature(exact_size_is_empty)] #![feature(in_band_lifetimes)] #![feature(iter_zip)] +#![feature(let_else)] #![feature(min_specialization)] #![feature(once_cell)] #![feature(stmt_expr_attributes)] diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs index c0bf4b659a..28e5d76783 100644 --- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs +++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs @@ -11,8 +11,7 @@ use rustc_middle::mir::{self, Body, Local, Location}; use rustc_middle::ty::{self, Ty, TyCtxt}; use crate::impls::{ - DefinitelyInitializedPlaces, MaybeInitializedPlaces, MaybeLiveLocals, MaybeMutBorrowedLocals, - MaybeUninitializedPlaces, + DefinitelyInitializedPlaces, MaybeInitializedPlaces, MaybeLiveLocals, MaybeUninitializedPlaces, }; use crate::move_paths::{HasMoveData, MoveData}; use crate::move_paths::{LookupResult, MovePathIndex}; @@ -62,14 +61,6 @@ impl<'tcx> MirPass<'tcx> for SanityCheck { sanity_check_via_rustc_peek(tcx, body, &attributes, &flow_def_inits); } - if has_rustc_mir_with(sess, &attributes, sym::rustc_peek_indirectly_mutable).is_some() { - let flow_mut_borrowed = MaybeMutBorrowedLocals::mut_borrows_only(tcx, body, param_env) - .into_engine(tcx, body) - .iterate_to_fixpoint(); - - sanity_check_via_rustc_peek(tcx, body, &attributes, &flow_mut_borrowed); - } - if has_rustc_mir_with(sess, &attributes, sym::rustc_peek_liveness).is_some() { let flow_liveness = MaybeLiveLocals.into_engine(tcx, body).iterate_to_fixpoint(); @@ -281,28 +272,6 @@ where } } -impl<'tcx> RustcPeekAt<'tcx> for MaybeMutBorrowedLocals<'_, 'tcx> { - fn peek_at( - &self, - tcx: TyCtxt<'tcx>, - place: mir::Place<'tcx>, - flow_state: &BitSet, - call: PeekCall, - ) { - info!(?place, "peek_at"); - let local = if let Some(l) = place.as_local() { - l - } else { - tcx.sess.span_err(call.span, "rustc_peek: argument was not a local"); - return; - }; - - if !flow_state.contains(local) { - tcx.sess.span_err(call.span, "rustc_peek: bit not set"); - } - } -} - impl<'tcx> RustcPeekAt<'tcx> for MaybeLiveLocals { fn peek_at( &self, @@ -312,9 +281,7 @@ impl<'tcx> RustcPeekAt<'tcx> for MaybeLiveLocals { call: PeekCall, ) { info!(?place, "peek_at"); - let local = if let Some(l) = place.as_local() { - l - } else { + let Some(local) = place.as_local() else { tcx.sess.span_err(call.span, "rustc_peek: argument was not a local"); return; }; diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index 17790ec91c..63c637af5c 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -68,11 +68,10 @@ impl<'tcx> MirPass<'tcx> for ConstProp { return; } - use rustc_middle::hir::map::blocks::FnLikeNode; let def_id = body.source.def_id().expect_local(); let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let is_fn_like = FnLikeNode::from_node(tcx.hir().get(hir_id)).is_some(); + let is_fn_like = tcx.hir().get(hir_id).fn_kind().is_some(); let is_assoc_const = tcx.def_kind(def_id.to_def_id()) == DefKind::AssocConst; // Only run const prop on functions, methods, closures and associated constants diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 1c946bd2d8..6807d02519 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -14,13 +14,11 @@ use spans::{CoverageSpan, CoverageSpans}; use crate::MirPass; -use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::graph::WithNumNodes; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; use rustc_index::vec::IndexVec; use rustc_middle::hir; -use rustc_middle::hir::map::blocks::FnLikeNode; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::coverage::*; use rustc_middle::mir::dump_enabled; @@ -29,7 +27,6 @@ use rustc_middle::mir::{ TerminatorKind, }; use rustc_middle::ty::TyCtxt; -use rustc_query_system::ich::StableHashingContext; use rustc_span::def_id::DefId; use rustc_span::source_map::SourceMap; use rustc_span::{CharPos, ExpnKind, Pos, SourceFile, Span, Symbol}; @@ -66,7 +63,7 @@ impl<'tcx> MirPass<'tcx> for InstrumentCoverage { } let hir_id = tcx.hir().local_def_id_to_hir_id(mir_source.def_id().expect_local()); - let is_fn_like = FnLikeNode::from_node(tcx.hir().get(hir_id)).is_some(); + let is_fn_like = tcx.hir().get(hir_id).fn_kind().is_some(); // Only instrument functions, methods, and closures (not constants since they are evaluated // at compile time by Miri). @@ -76,7 +73,7 @@ impl<'tcx> MirPass<'tcx> for InstrumentCoverage { // be tricky if const expressions have no corresponding statements in the enclosing MIR. // Closures are carved out by their initial `Assign` statement.) if !is_fn_like { - trace!("InstrumentCoverage skipped for {:?} (not an FnLikeNode)", mir_source.def_id()); + trace!("InstrumentCoverage skipped for {:?} (not an fn-like)", mir_source.def_id()); return; } @@ -488,7 +485,7 @@ fn inject_statement( // Non-code expressions are injected into the coverage map, without generating executable code. fn inject_intermediate_expression(mir_body: &mut mir::Body<'tcx>, expression: CoverageKind) { - debug_assert!(if let CoverageKind::Expression { .. } = expression { true } else { false }); + debug_assert!(matches!(expression, CoverageKind::Expression { .. })); debug!(" injecting non-code expression {:?}", expression); let inject_in_bb = mir::START_BLOCK; let data = &mut mir_body[inject_in_bb]; @@ -574,15 +571,13 @@ fn get_body_span<'tcx>( } fn hash_mir_source<'tcx>(tcx: TyCtxt<'tcx>, hir_body: &'tcx rustc_hir::Body<'tcx>) -> u64 { + // FIXME(cjgillot) Stop hashing HIR manually here. let mut hcx = tcx.create_no_span_stable_hashing_context(); - hash(&mut hcx, &hir_body.value).to_smaller_hash() -} - -fn hash( - hcx: &mut StableHashingContext<'tcx>, - node: &impl HashStable>, -) -> Fingerprint { let mut stable_hasher = StableHasher::new(); - node.hash_stable(hcx, &mut stable_hasher); + let owner = hir_body.id().hir_id.owner; + let bodies = &tcx.hir_owner_nodes(owner).as_ref().unwrap().bodies; + hcx.with_hir_bodies(false, owner, bodies, |hcx| { + hir_body.value.hash_stable(hcx, &mut stable_hasher) + }); stable_hasher.finish() } diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index cc525a4d6b..d13fa0729c 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -94,10 +94,9 @@ impl CoverageSpan { stmt_index: usize, ) -> Self { let is_closure = match statement.kind { - StatementKind::Assign(box (_, Rvalue::Aggregate(box ref kind, _))) => match kind { - AggregateKind::Closure(_, _) | AggregateKind::Generator(_, _, _) => true, - _ => false, - }, + StatementKind::Assign(box (_, Rvalue::Aggregate(box ref kind, _))) => { + matches!(kind, AggregateKind::Closure(_, _) | AggregateKind::Generator(_, _, _)) + } _ => false, }; diff --git a/compiler/rustc_mir_transform/src/dump_mir.rs b/compiler/rustc_mir_transform/src/dump_mir.rs index 2a24e1ea8d..6b995141a2 100644 --- a/compiler/rustc_mir_transform/src/dump_mir.rs +++ b/compiler/rustc_mir_transform/src/dump_mir.rs @@ -1,13 +1,12 @@ //! This pass just dumps MIR at a specified point. use std::borrow::Cow; -use std::fmt; use std::fs::File; use std::io; use crate::MirPass; +use rustc_middle::mir::write_mir_pretty; use rustc_middle::mir::Body; -use rustc_middle::mir::{dump_enabled, dump_mir, write_mir_pretty}; use rustc_middle::ty::TyCtxt; use rustc_session::config::{OutputFilenames, OutputType}; @@ -21,29 +20,6 @@ impl<'tcx> MirPass<'tcx> for Marker { fn run_pass(&self, _tcx: TyCtxt<'tcx>, _body: &mut Body<'tcx>) {} } -pub struct Disambiguator { - is_after: bool, -} - -impl fmt::Display for Disambiguator { - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - let title = if self.is_after { "after" } else { "before" }; - write!(formatter, "{}", title) - } -} - -pub fn on_mir_pass<'tcx>( - tcx: TyCtxt<'tcx>, - pass_num: &dyn fmt::Display, - pass_name: &str, - body: &Body<'tcx>, - is_after: bool, -) { - if dump_enabled(tcx, pass_name, body.source.def_id()) { - dump_mir(tcx, Some(pass_num), pass_name, &Disambiguator { is_after }, body, |_, _| Ok(())); - } -} - pub fn emit_mir(tcx: TyCtxt<'_>, outputs: &OutputFilenames) -> io::Result<()> { let path = outputs.path(OutputType::Mir); let mut f = io::BufWriter::new(File::create(&path)?); diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index ee4e91ecb6..84a1e3fb60 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -673,9 +673,7 @@ impl Inliner<'tcx> { assert!(args.next().is_none()); let tuple = Place::from(tuple); - let tuple_tys = if let ty::Tuple(s) = tuple.ty(caller_body, tcx).ty.kind() { - s - } else { + let ty::Tuple(tuple_tys) = tuple.ty(caller_body, tcx).ty.kind() else { bug!("Closure arguments are not passed as a tuple"); }; diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 9b11c8f0b2..f9ef314627 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -1,9 +1,9 @@ #![feature(box_patterns)] #![feature(box_syntax)] #![feature(crate_visibility_modifier)] -#![cfg_attr(bootstrap, feature(const_panic))] #![feature(in_band_lifetimes)] #![feature(iter_zip)] +#![feature(let_else)] #![feature(map_try_insert)] #![feature(min_specialization)] #![feature(option_get_or_insert_default)] @@ -27,7 +27,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_index::vec::IndexVec; use rustc_middle::mir::visit::Visitor as _; -use rustc_middle::mir::{traversal, Body, ConstQualifs, MirPhase, Promoted}; +use rustc_middle::mir::{dump_mir, traversal, Body, ConstQualifs, MirPhase, Promoted}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt, TypeFoldable}; use rustc_span::{Span, Symbol}; @@ -65,6 +65,7 @@ mod remove_storage_markers; mod remove_unneeded_drops; mod remove_zsts; mod required_consts; +mod reveal_all; mod separate_const_switch; mod shim; mod simplify; @@ -187,12 +188,14 @@ fn run_passes( let mut index = 0; let mut run_pass = |pass: &dyn MirPass<'tcx>| { let run_hooks = |body: &_, index, is_after| { - dump_mir::on_mir_pass( + let disambiguator = if is_after { "after" } else { "before" }; + dump_mir( tcx, - &format_args!("{:03}-{:03}", phase_index, index), + Some(&format_args!("{:03}-{:03}", phase_index, index)), &pass.name(), + &disambiguator, body, - is_after, + |_, _| Ok(()), ); }; run_hooks(body, index, false); @@ -428,8 +431,7 @@ fn mir_drops_elaborated_and_const_checked<'tcx>( } let hir_id = tcx.hir().local_def_id_to_hir_id(def.did); - use rustc_middle::hir::map::blocks::FnLikeNode; - let is_fn_like = FnLikeNode::from_node(tcx.hir().get(hir_id)).is_some(); + let is_fn_like = tcx.hir().get(hir_id).fn_kind().is_some(); if is_fn_like { let did = def.did.to_def_id(); let def = ty::WithOptConstParam::unknown(did); @@ -488,6 +490,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // to them. We run some optimizations before that, because they may be harder to do on the state // machine than on MIR with async primitives. let optimizations_with_generators: &[&dyn MirPass<'tcx>] = &[ + &reveal_all::RevealAll, // has to be done before inlining, since inlined code is in RevealAll mode. &lower_slice_len::LowerSliceLenCalls, // has to be done before inlining, otherwise actual call will be almost always inlined. Also simple, so can just do first &normalize_array_len::NormalizeArrayLen, // has to run after `slice::len` lowering &unreachable_prop::UnreachablePropagation, diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs index a2cce9f1ed..822a372d8c 100644 --- a/compiler/rustc_mir_transform/src/lower_slice_len.rs +++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs @@ -17,9 +17,7 @@ impl<'tcx> MirPass<'tcx> for LowerSliceLenCalls { pub fn lower_slice_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let language_items = tcx.lang_items(); - let slice_len_fn_item_def_id = if let Some(slice_len_fn_item) = language_items.slice_len_fn() { - slice_len_fn_item - } else { + let Some(slice_len_fn_item_def_id) = language_items.slice_len_fn() else { // there is no language item to compare to :) return; }; diff --git a/compiler/rustc_mir_transform/src/normalize_array_len.rs b/compiler/rustc_mir_transform/src/normalize_array_len.rs index 76f0e83c8c..a04a0b5153 100644 --- a/compiler/rustc_mir_transform/src/normalize_array_len.rs +++ b/compiler/rustc_mir_transform/src/normalize_array_len.rs @@ -208,7 +208,7 @@ fn normalize_array_len_call<'tcx>( operand, cast_ty, ) => { - let local = if let Some(local) = place.as_local() { local } else { return }; + let Some(local) = place.as_local() else { return }; match operand { Operand::Copy(place) | Operand::Move(place) => { let operand_local = @@ -255,9 +255,7 @@ fn normalize_array_len_call<'tcx>( } } Rvalue::Len(place) => { - let local = if let Some(local) = place.local_or_deref_local() { - local - } else { + let Some(local) = place.local_or_deref_local() else { return; }; if let Some(cast_statement_idx) = state.get(&local).copied() { diff --git a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs index 5c9d04a08b..c71bc512c3 100644 --- a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs @@ -13,7 +13,7 @@ impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops { trace!("Running RemoveUnneededDrops on {:?}", body.source); let did = body.source.def_id(); - let param_env = tcx.param_env(did); + let param_env = tcx.param_env_reveal_all_normalized(did); let mut should_simplify = false; let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); diff --git a/compiler/rustc_mir_transform/src/reveal_all.rs b/compiler/rustc_mir_transform/src/reveal_all.rs new file mode 100644 index 0000000000..6c423a2bb5 --- /dev/null +++ b/compiler/rustc_mir_transform/src/reveal_all.rs @@ -0,0 +1,58 @@ +//! Normalizes MIR in RevealAll mode. + +use crate::MirPass; +use rustc_middle::mir::visit::*; +use rustc_middle::mir::*; +use rustc_middle::ty::{self, Ty, TyCtxt}; + +pub struct RevealAll; + +impl<'tcx> MirPass<'tcx> for RevealAll { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + // This pass must run before inlining, since we insert callee bodies in RevealAll mode. + // Do not apply this transformation to generators. + if (tcx.sess.mir_opt_level() >= 3 || super::inline::is_enabled(tcx)) + && body.generator.is_none() + { + let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); + RevealAllVisitor { tcx, param_env }.visit_body(body); + } + } +} + +struct RevealAllVisitor<'tcx> { + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, +} + +impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> { + #[inline] + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + #[inline] + fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) { + *ty = self.tcx.normalize_erasing_regions(self.param_env, ty); + } + + #[inline] + fn process_projection_elem( + &mut self, + elem: PlaceElem<'tcx>, + _: Location, + ) -> Option> { + match elem { + PlaceElem::Field(field, ty) => { + let new_ty = self.tcx.normalize_erasing_regions(self.param_env, ty); + if ty != new_ty { Some(PlaceElem::Field(field, new_ty)) } else { None } + } + // None of those contain a Ty. + PlaceElem::Index(..) + | PlaceElem::Deref + | PlaceElem::ConstantIndex { .. } + | PlaceElem::Subslice { .. } + | PlaceElem::Downcast(..) => None, + } + } +} diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index f2ea5fedc6..f59aaa664f 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -310,7 +310,6 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) - match self_ty.kind() { _ if is_copy => builder.copy_shim(), - ty::Array(ty, len) => builder.array_shim(dest, src, ty, len), ty::Closure(_, substs) => { builder.tuple_like_shim(dest, src, substs.as_closure().upvar_tys()) } @@ -459,154 +458,6 @@ impl CloneShimBuilder<'tcx> { ); } - fn loop_header( - &mut self, - beg: Place<'tcx>, - end: Place<'tcx>, - loop_body: BasicBlock, - loop_end: BasicBlock, - is_cleanup: bool, - ) { - let tcx = self.tcx; - - let cond = self.make_place(Mutability::Mut, tcx.types.bool); - let compute_cond = self.make_statement(StatementKind::Assign(Box::new(( - cond, - Rvalue::BinaryOp(BinOp::Ne, Box::new((Operand::Copy(end), Operand::Copy(beg)))), - )))); - - // `if end != beg { goto loop_body; } else { goto loop_end; }` - self.block( - vec![compute_cond], - TerminatorKind::if_(tcx, Operand::Move(cond), loop_body, loop_end), - is_cleanup, - ); - } - - fn make_usize(&self, value: u64) -> Box> { - Box::new(Constant { - span: self.span, - user_ty: None, - literal: ty::Const::from_usize(self.tcx, value).into(), - }) - } - - fn array_shim( - &mut self, - dest: Place<'tcx>, - src: Place<'tcx>, - ty: Ty<'tcx>, - len: &'tcx ty::Const<'tcx>, - ) { - let tcx = self.tcx; - let span = self.span; - - let beg = self.local_decls.push(LocalDecl::new(tcx.types.usize, span)); - let end = self.make_place(Mutability::Not, tcx.types.usize); - - // BB #0 - // `let mut beg = 0;` - // `let end = len;` - // `goto #1;` - let inits = vec![ - self.make_statement(StatementKind::Assign(Box::new(( - Place::from(beg), - Rvalue::Use(Operand::Constant(self.make_usize(0))), - )))), - self.make_statement(StatementKind::Assign(Box::new(( - end, - Rvalue::Use(Operand::Constant(Box::new(Constant { - span: self.span, - user_ty: None, - literal: len.into(), - }))), - )))), - ]; - self.block(inits, TerminatorKind::Goto { target: BasicBlock::new(1) }, false); - - // BB #1: loop { - // BB #2; - // BB #3; - // } - // BB #4; - self.loop_header(Place::from(beg), end, BasicBlock::new(2), BasicBlock::new(4), false); - - // BB #2 - // `dest[i] = Clone::clone(src[beg])`; - // Goto #3 if ok, #5 if unwinding happens. - let dest_field = self.tcx.mk_place_index(dest, beg); - let src_field = self.tcx.mk_place_index(src, beg); - self.make_clone_call(dest_field, src_field, ty, BasicBlock::new(3), BasicBlock::new(5)); - - // BB #3 - // `beg = beg + 1;` - // `goto #1`; - let statements = vec![self.make_statement(StatementKind::Assign(Box::new(( - Place::from(beg), - Rvalue::BinaryOp( - BinOp::Add, - Box::new((Operand::Copy(Place::from(beg)), Operand::Constant(self.make_usize(1)))), - ), - ))))]; - self.block(statements, TerminatorKind::Goto { target: BasicBlock::new(1) }, false); - - // BB #4 - // `return dest;` - self.block(vec![], TerminatorKind::Return, false); - - // BB #5 (cleanup) - // `let end = beg;` - // `let mut beg = 0;` - // goto #6; - let end = beg; - let beg = self.local_decls.push(LocalDecl::new(tcx.types.usize, span)); - let init = self.make_statement(StatementKind::Assign(Box::new(( - Place::from(beg), - Rvalue::Use(Operand::Constant(self.make_usize(0))), - )))); - self.block(vec![init], TerminatorKind::Goto { target: BasicBlock::new(6) }, true); - - // BB #6 (cleanup): loop { - // BB #7; - // BB #8; - // } - // BB #9; - self.loop_header( - Place::from(beg), - Place::from(end), - BasicBlock::new(7), - BasicBlock::new(9), - true, - ); - - // BB #7 (cleanup) - // `drop(dest[beg])`; - self.block( - vec![], - TerminatorKind::Drop { - place: self.tcx.mk_place_index(dest, beg), - target: BasicBlock::new(8), - unwind: None, - }, - true, - ); - - // BB #8 (cleanup) - // `beg = beg + 1;` - // `goto #6;` - let statement = self.make_statement(StatementKind::Assign(Box::new(( - Place::from(beg), - Rvalue::BinaryOp( - BinOp::Add, - Box::new((Operand::Copy(Place::from(beg)), Operand::Constant(self.make_usize(1)))), - ), - )))); - self.block(vec![statement], TerminatorKind::Goto { target: BasicBlock::new(6) }, true); - - // BB #9 (resume) - self.block(vec![], TerminatorKind::Resume, true); - } - fn tuple_like_shim(&mut self, dest: Place<'tcx>, src: Place<'tcx>, tys: I) where I: Iterator>, diff --git a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs index 5cef64d778..2aa5061129 100644 --- a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs @@ -83,12 +83,9 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching { let bb = BasicBlock::from_usize(bb); trace!("processing block {:?}", bb); - let discriminant_ty = - if let Some(ty) = get_switched_on_type(&body.basic_blocks()[bb], tcx, body) { - ty - } else { - continue; - }; + let Some(discriminant_ty) = get_switched_on_type(&body.basic_blocks()[bb], tcx, body) else { + continue; + }; let layout = tcx.layout_of(tcx.param_env(body.source.def_id()).and(discriminant_ty)); diff --git a/compiler/rustc_mir_transform/src/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs index baf381081d..64cd6f56a9 100644 --- a/compiler/rustc_mir_transform/src/unreachable_prop.rs +++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs @@ -27,9 +27,8 @@ impl MirPass<'_> for UnreachablePropagation { // This is a temporary solution that handles possibly diverging asm statements. // Accompanying testcases: mir-opt/unreachable_asm.rs and mir-opt/unreachable_asm_2.rs let asm_stmt_in_block = || { - bb_data.statements.iter().any(|stmt: &Statement<'_>| match stmt.kind { - StatementKind::LlvmInlineAsm(..) => true, - _ => false, + bb_data.statements.iter().any(|stmt: &Statement<'_>| { + matches!(stmt.kind, StatementKind::LlvmInlineAsm(..)) }) }; diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 5147408210..59988e69b5 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -806,13 +806,22 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { } } } + mir::TerminatorKind::Assert { ref msg, .. } => { + let lang_item = match msg { + mir::AssertKind::BoundsCheck { .. } => LangItem::PanicBoundsCheck, + _ => LangItem::Panic, + }; + let instance = Instance::mono(tcx, tcx.require_lang_item(lang_item, Some(source))); + if should_codegen_locally(tcx, &instance) { + self.output.push(create_fn_mono_item(tcx, instance, source)); + } + } mir::TerminatorKind::Goto { .. } | mir::TerminatorKind::SwitchInt { .. } | mir::TerminatorKind::Resume | mir::TerminatorKind::Abort | mir::TerminatorKind::Return - | mir::TerminatorKind::Unreachable - | mir::TerminatorKind::Assert { .. } => {} + | mir::TerminatorKind::Unreachable => {} mir::TerminatorKind::GeneratorDrop | mir::TerminatorKind::Yield { .. } | mir::TerminatorKind::FalseEdge { .. } diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index 08b1d7b7fa..f4082153b6 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -2,6 +2,7 @@ #![feature(bool_to_option)] #![feature(crate_visibility_modifier)] #![feature(control_flow_enum)] +#![feature(let_else)] #![feature(in_band_lifetimes)] #![recursion_limit = "256"] diff --git a/compiler/rustc_monomorphize/src/partitioning/default.rs b/compiler/rustc_monomorphize/src/partitioning/default.rs index be68208225..b41906111b 100644 --- a/compiler/rustc_monomorphize/src/partitioning/default.rs +++ b/compiler/rustc_monomorphize/src/partitioning/default.rs @@ -458,9 +458,7 @@ fn mono_item_visibility( let is_generic = instance.substs.non_erasable_generics().next().is_some(); // Upstream `DefId` instances get different handling than local ones. - let def_id = if let Some(def_id) = def_id.as_local() { - def_id - } else { + let Some(def_id) = def_id.as_local() else { return if export_generics && is_generic { // If it is an upstream monomorphization and we export generics, we must make // it available to downstream crates. diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs index 7a7a56a034..658c9028ca 100644 --- a/compiler/rustc_monomorphize/src/partitioning/mod.rs +++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs @@ -361,6 +361,17 @@ fn collect_and_partition_mono_items<'tcx>( ) }); + if tcx.prof.enabled() { + // Record CGU size estimates for self-profiling. + for cgu in codegen_units { + tcx.prof.artifact_size( + "codegen_unit_size_estimate", + &cgu.name().as_str()[..], + cgu.size_estimate() as u64, + ); + } + } + let mono_items: DefIdSet = items .iter() .filter_map(|mono_item| match *mono_item { diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index e6e4438b6d..595080619d 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -167,6 +167,7 @@ fn mark_used_by_default_parameters<'tcx>( | DefKind::Use | DefKind::ForeignMod | DefKind::AnonConst + | DefKind::InlineConst | DefKind::OpaqueTy | DefKind::Field | DefKind::LifetimeParam @@ -195,7 +196,7 @@ fn emit_unused_generic_params_error<'tcx>( generics: &'tcx ty::Generics, unused_parameters: &FiniteBitSet, ) { - let base_def_id = tcx.closure_base_def_id(def_id); + let base_def_id = tcx.typeck_root_def_id(def_id); if !tcx.get_attrs(base_def_id).iter().any(|a| a.has_name(sym::rustc_polymorphize_error)) { return; } @@ -303,7 +304,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { ControlFlow::CONTINUE } ty::ConstKind::Unevaluated(uv) - if self.tcx.def_kind(uv.def.did) == DefKind::AnonConst => + if matches!(self.tcx.def_kind(uv.def.did), DefKind::AnonConst | DefKind::InlineConst) => { self.visit_child_body(uv.def.did, uv.substs(self.tcx)); ControlFlow::CONTINUE diff --git a/compiler/rustc_monomorphize/src/util.rs b/compiler/rustc_monomorphize/src/util.rs index 799b4e18c2..4392c02f87 100644 --- a/compiler/rustc_monomorphize/src/util.rs +++ b/compiler/rustc_monomorphize/src/util.rs @@ -67,7 +67,7 @@ crate fn dump_closure_profile(tcx: TyCtxt<'tcx>, closure_instance: Instance<'tcx src_file.prefer_local(), line_nos ) { - eprintln!("Error writting to file {}", e.to_string()) + eprintln!("Error writing to file {}", e) } } } diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 8e90f73b44..1a620968d5 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -1,11 +1,13 @@ +use crate::lexer::unicode_chars::UNICODE_ARRAY; use rustc_ast::ast::{self, AttrStyle}; use rustc_ast::token::{self, CommentKind, Token, TokenKind}; use rustc_ast::tokenstream::{Spacing, TokenStream}; +use rustc_ast::util::unicode::contains_text_flow_control_chars; use rustc_errors::{error_code, Applicability, DiagnosticBuilder, FatalError, PResult}; use rustc_lexer::unescape::{self, Mode}; use rustc_lexer::{Base, DocStyle, RawStrError}; use rustc_session::lint::builtin::{ - TEXT_DIRECTION_CODEPOINT_IN_COMMENT, RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, + RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, TEXT_DIRECTION_CODEPOINT_IN_COMMENT, }; use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::parse::ParseSess; @@ -137,12 +139,8 @@ impl<'a> StringReader<'a> { // Opening delimiter of the length 2 is not included into the comment text. let content_start = start + BytePos(2); let content = self.str_from(content_start); - let span = self.mk_sp(start, self.pos); - const UNICODE_TEXT_FLOW_CHARS: &[char] = &[ - '\u{202A}', '\u{202B}', '\u{202D}', '\u{202E}', '\u{2066}', '\u{2067}', '\u{2068}', - '\u{202C}', '\u{2069}', - ]; - if content.contains(UNICODE_TEXT_FLOW_CHARS) { + if contains_text_flow_control_chars(content) { + let span = self.mk_sp(start, self.pos); self.sess.buffer_lint_with_diagnostic( &TEXT_DIRECTION_CODEPOINT_IN_COMMENT, span, @@ -225,6 +223,22 @@ impl<'a> StringReader<'a> { } token::Ident(sym, is_raw_ident) } + rustc_lexer::TokenKind::InvalidIdent + // Do not recover an identifier with emoji if the codepoint is a confusable + // with a recoverable substitution token, like `➖`. + if UNICODE_ARRAY + .iter() + .find(|&&(c, _, _)| { + let sym = self.str_from(start); + sym.chars().count() == 1 && c == sym.chars().next().unwrap() + }) + .is_none() => + { + let sym = nfc_normalize(self.str_from(start)); + let span = self.mk_sp(start, self.pos); + self.sess.bad_unicode_identifiers.borrow_mut().entry(sym).or_default().push(span); + token::Ident(sym, false) + } rustc_lexer::TokenKind::Literal { kind, suffix_start } => { let suffix_start = start + BytePos(suffix_start as u32); let (kind, symbol) = self.cook_lexer_literal(start, suffix_start, kind); @@ -296,7 +310,7 @@ impl<'a> StringReader<'a> { rustc_lexer::TokenKind::Caret => token::BinOp(token::Caret), rustc_lexer::TokenKind::Percent => token::BinOp(token::Percent), - rustc_lexer::TokenKind::Unknown => { + rustc_lexer::TokenKind::Unknown | rustc_lexer::TokenKind::InvalidIdent => { let c = self.str_from(start).chars().next().unwrap(); let mut err = self.struct_fatal_span_char(start, self.pos, "unknown start of token", c); diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs index 569f186a72..7f68112a42 100644 --- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs +++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs @@ -82,6 +82,33 @@ pub(crate) fn emit_unescape_error( Applicability::MachineApplicable, ); } + } else { + let printable: Vec = lit + .chars() + .filter(|&x| { + unicode_width::UnicodeWidthChar::width(x).unwrap_or(0) != 0 + && !x.is_whitespace() + }) + .collect(); + + if let [ch] = printable.as_slice() { + has_help = true; + + handler.span_note( + span, + &format!( + "there are non-printing characters, the full sequence is `{}`", + lit.escape_default(), + ), + ); + + handler.span_suggestion( + span, + "consider removing the non-printing characters", + ch.to_string(), + Applicability::MaybeIncorrect, + ); + } } if !has_help { diff --git a/compiler/rustc_parse/src/lexer/unicode_chars.rs b/compiler/rustc_parse/src/lexer/unicode_chars.rs index 3eebc088f3..ccd11f06bc 100644 --- a/compiler/rustc_parse/src/lexer/unicode_chars.rs +++ b/compiler/rustc_parse/src/lexer/unicode_chars.rs @@ -7,7 +7,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_span::{symbol::kw, BytePos, Pos, Span}; #[rustfmt::skip] // for line breaks -const UNICODE_ARRAY: &[(char, &str, char)] = &[ +pub(crate) const UNICODE_ARRAY: &[(char, &str, char)] = &[ ('
', "Line Separator", ' '), ('
', "Paragraph Separator", ' '), (' ', "Ogham Space mark", ' '), diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 8095f386fa..ce39d07656 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -6,9 +6,11 @@ use rustc_ast as ast; use rustc_ast::ptr::P; use rustc_ast::token::{self, Lit, LitKind, TokenKind}; use rustc_ast::util::parser::AssocOp; -use rustc_ast::{AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec}; -use rustc_ast::{BinOpKind, BindingMode, Block, BlockCheckMode, Expr, ExprKind, GenericArg, Item}; -use rustc_ast::{ItemKind, Mutability, Param, Pat, PatKind, Path, PathSegment, QSelf, Ty, TyKind}; +use rustc_ast::{ + AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingMode, Block, + BlockCheckMode, Expr, ExprKind, GenericArg, Generics, Item, ItemKind, Mutability, Param, Pat, + PatKind, Path, PathSegment, QSelf, Ty, TyKind, +}; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{pluralize, struct_span_err}; @@ -662,7 +664,7 @@ impl<'a> Parser<'a> { let snapshot = self.clone(); self.bump(); let lo = self.token.span; - match self.parse_angle_args() { + match self.parse_angle_args(None) { Ok(args) => { let span = lo.to(self.prev_token.span); // Detect trailing `>` like in `x.collect::Vec<_>>()`. @@ -719,7 +721,7 @@ impl<'a> Parser<'a> { let x = self.parse_seq_to_before_end( &token::Gt, SeqSep::trailing_allowed(token::Comma), - |p| p.parse_generic_arg(), + |p| p.parse_generic_arg(None), ); match x { Ok((_, _, false)) => { @@ -1103,7 +1105,7 @@ impl<'a> Parser<'a> { self.expect(&token::ModSep)?; let mut path = ast::Path { segments: Vec::new(), span: DUMMY_SP, tokens: None }; - self.parse_path_segments(&mut path.segments, T::PATH_STYLE)?; + self.parse_path_segments(&mut path.segments, T::PATH_STYLE, None)?; path.span = ty_span.to(self.prev_token.span); let ty_str = self.span_to_snippet(ty_span).unwrap_or_else(|_| pprust::ty_to_string(&ty)); @@ -1121,7 +1123,7 @@ impl<'a> Parser<'a> { Ok(P(T::recovered(Some(QSelf { ty, path_span, position: 0 }), path))) } - pub(super) fn maybe_consume_incorrect_semicolon(&mut self, items: &[P]) -> bool { + pub fn maybe_consume_incorrect_semicolon(&mut self, items: &[P]) -> bool { if self.eat(&token::Semi) { let mut err = self.struct_span_err(self.prev_token.span, "expected item, found `;`"); err.span_suggestion_short( @@ -1342,10 +1344,10 @@ impl<'a> Parser<'a> { self.struct_span_err( MultiSpan::from_spans(vec![begin_par_sp, self.prev_token.span]), - "unexpected parenthesis surrounding `for` loop head", + "unexpected parentheses surrounding `for` loop head", ) .multipart_suggestion( - "remove parenthesis in `for` loop", + "remove parentheses in `for` loop", vec![(begin_par_sp, String::new()), (self.prev_token.span, String::new())], // With e.g. `for (x) in y)` this would replace `(x) in y)` // with `x) in y)` which is syntactically invalid. @@ -1909,6 +1911,71 @@ impl<'a> Parser<'a> { Ok(expr) } + fn recover_const_param_decl( + &mut self, + ty_generics: Option<&Generics>, + ) -> PResult<'a, Option> { + let snapshot = self.clone(); + let param = match self.parse_const_param(vec![]) { + Ok(param) => param, + Err(mut err) => { + err.cancel(); + *self = snapshot; + return Err(err); + } + }; + let mut err = + self.struct_span_err(param.span(), "unexpected `const` parameter declaration"); + err.span_label(param.span(), "expected a `const` expression, not a parameter declaration"); + if let (Some(generics), Ok(snippet)) = + (ty_generics, self.sess.source_map().span_to_snippet(param.span())) + { + let (span, sugg) = match &generics.params[..] { + [] => (generics.span, format!("<{}>", snippet)), + [.., generic] => (generic.span().shrink_to_hi(), format!(", {}", snippet)), + }; + err.multipart_suggestion( + "`const` parameters must be declared for the `impl`", + vec![(span, sugg), (param.span(), param.ident.to_string())], + Applicability::MachineApplicable, + ); + } + let value = self.mk_expr_err(param.span()); + err.emit(); + return Ok(Some(GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value }))); + } + + pub fn recover_const_param_declaration( + &mut self, + ty_generics: Option<&Generics>, + ) -> PResult<'a, Option> { + // We have to check for a few different cases. + if let Ok(arg) = self.recover_const_param_decl(ty_generics) { + return Ok(arg); + } + + // We haven't consumed `const` yet. + let start = self.token.span; + self.bump(); // `const` + + // Detect and recover from the old, pre-RFC2000 syntax for const generics. + let mut err = self + .struct_span_err(start, "expected lifetime, type, or constant, found keyword `const`"); + if self.check_const_arg() { + err.span_suggestion_verbose( + start.until(self.token.span), + "the `const` keyword is only needed in the definition of the type", + String::new(), + Applicability::MaybeIncorrect, + ); + err.emit(); + Ok(Some(GenericArg::Const(self.parse_const_arg()?))) + } else { + let after_kw_const = self.token.span; + self.recover_const_arg(after_kw_const, err).map(Some) + } + } + /// Try to recover from possible generic const argument without `{` and `}`. /// /// When encountering code like `foo::< bar + 3 >` or `foo::< bar - baz >` we suggest diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 3d29d30502..f7ee874c83 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1032,6 +1032,8 @@ impl<'a> Parser<'a> { [IdentLike(_), Punct('+' | '-')] | // 1e+2 | 1e-2 [IdentLike(_), Punct('+' | '-'), IdentLike(_)] | + // 1.2e+ | 1.2e- + [IdentLike(_), Punct('.'), IdentLike(_), Punct('+' | '-')] | // 1.2e+3 | 1.2e-3 [IdentLike(_), Punct('.'), IdentLike(_), Punct('+' | '-'), IdentLike(_)] => { // See the FIXME about `TokenCursor` above. @@ -1148,7 +1150,7 @@ impl<'a> Parser<'a> { } let fn_span_lo = self.token.span; - let mut segment = self.parse_path_segment(PathStyle::Expr)?; + let mut segment = self.parse_path_segment(PathStyle::Expr, None)?; self.check_trailing_angle_brackets(&segment, &[&token::OpenDelim(token::Paren)]); self.check_turbofish_missing_angle_brackets(&mut segment); @@ -1241,7 +1243,7 @@ impl<'a> Parser<'a> { } else if self.eat_keyword(kw::Unsafe) { self.parse_block_expr(None, lo, BlockCheckMode::Unsafe(ast::UserProvided), attrs) } else if self.check_inline_const(0) { - self.parse_const_block(lo.to(self.token.span)) + self.parse_const_block(lo.to(self.token.span), false) } else if self.is_do_catch_block() { self.recover_do_catch(attrs) } else if self.is_try_block() { diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index f175c5b50b..a9ab2cd3f6 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -48,7 +48,10 @@ impl<'a> Parser<'a> { }) } - fn parse_const_param(&mut self, preceding_attrs: Vec) -> PResult<'a, GenericParam> { + crate fn parse_const_param( + &mut self, + preceding_attrs: Vec, + ) -> PResult<'a, GenericParam> { let const_span = self.token.span; self.expect_keyword(kw::Const)?; diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 624390a406..24a8df49ac 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -216,11 +216,11 @@ impl<'a> Parser<'a> { return Err(e); } - (Ident::invalid(), ItemKind::Use(tree)) + (Ident::empty(), ItemKind::Use(tree)) } else if self.check_fn_front_matter(def_final) { // FUNCTION ITEM let (ident, sig, generics, body) = self.parse_fn(attrs, req_name, lo)?; - (ident, ItemKind::Fn(Box::new(FnKind(def(), sig, generics, body)))) + (ident, ItemKind::Fn(Box::new(Fn { defaultness: def(), sig, generics, body }))) } else if self.eat_keyword(kw::Extern) { if self.eat_keyword(kw::Crate) { // EXTERN CRATE @@ -279,15 +279,15 @@ impl<'a> Parser<'a> { } else if self.eat_keyword(kw::Macro) { // MACROS 2.0 ITEM self.parse_item_decl_macro(lo)? - } else if self.is_macro_rules_item() { + } else if let IsMacroRulesItem::Yes { has_bang } = self.is_macro_rules_item() { // MACRO_RULES ITEM - self.parse_item_macro_rules(vis)? + self.parse_item_macro_rules(vis, has_bang)? } else if vis.kind.is_pub() && self.isnt_macro_invocation() { self.recover_missing_kw_before_item()?; return Ok(None); } else if macros_allowed && self.check_path() { // MACRO INVOCATION ITEM - (Ident::invalid(), ItemKind::MacCall(self.parse_item_macro(vis)?)) + (Ident::empty(), ItemKind::MacCall(self.parse_item_macro(vis)?)) } else { return Ok(None); }; @@ -300,7 +300,7 @@ impl<'a> Parser<'a> { || self.is_kw_followed_by_ident(kw::Union) // no: `union::b`, yes: `union U { .. }` || self.check_auto_or_unsafe_trait_item() // no: `auto::b`, yes: `auto trait X { .. }` || self.is_async_fn() // no(2015): `async::b`, yes: `async fn` - || self.is_macro_rules_item() // no: `macro_rules::b`, yes: `macro_rules! mac` + || matches!(self.is_macro_rules_item(), IsMacroRulesItem::Yes{..}) // no: `macro_rules::b`, yes: `macro_rules! mac` } /// Are we sure this could not possibly be a macro invocation? @@ -514,7 +514,7 @@ impl<'a> Parser<'a> { tokens: None, }) } else { - self.parse_ty()? + self.parse_ty_with_generics_recovery(&generics)? }; // If `for` is missing we try to recover. @@ -560,7 +560,7 @@ impl<'a> Parser<'a> { }; let trait_ref = TraitRef { path, ref_id: ty_first.id }; - ItemKind::Impl(Box::new(ImplKind { + ItemKind::Impl(Box::new(Impl { unsafety, polarity, defaultness, @@ -573,7 +573,7 @@ impl<'a> Parser<'a> { } None => { // impl Type - ItemKind::Impl(Box::new(ImplKind { + ItemKind::Impl(Box::new(Impl { unsafety, polarity, defaultness, @@ -586,7 +586,7 @@ impl<'a> Parser<'a> { } }; - Ok((Ident::invalid(), item_kind)) + Ok((Ident::empty(), item_kind)) } fn parse_item_list( @@ -682,7 +682,7 @@ impl<'a> Parser<'a> { self.expect_keyword(kw::Trait)?; let ident = self.parse_ident()?; - let mut tps = self.parse_generics()?; + let mut generics = self.parse_generics()?; // Parse optional colon and supertrait bounds. let had_colon = self.eat(&token::Colon); @@ -702,7 +702,7 @@ impl<'a> Parser<'a> { } let bounds = self.parse_generic_bounds(None)?; - tps.where_clause = self.parse_where_clause()?; + generics.where_clause = self.parse_where_clause()?; self.expect_semi()?; let whole_span = lo.to(self.prev_token.span); @@ -717,12 +717,15 @@ impl<'a> Parser<'a> { self.sess.gated_spans.gate(sym::trait_alias, whole_span); - Ok((ident, ItemKind::TraitAlias(tps, bounds))) + Ok((ident, ItemKind::TraitAlias(generics, bounds))) } else { // It's a normal trait. - tps.where_clause = self.parse_where_clause()?; + generics.where_clause = self.parse_where_clause()?; let items = self.parse_item_list(attrs, |p| p.parse_trait_item(ForceCollect::No))?; - Ok((ident, ItemKind::Trait(Box::new(TraitKind(is_auto, unsafety, tps, bounds, items))))) + Ok(( + ident, + ItemKind::Trait(Box::new(Trait { is_auto, unsafety, generics, bounds, items })), + )) } } @@ -769,7 +772,7 @@ impl<'a> Parser<'a> { /// TypeAlias = "type" Ident Generics {":" GenericBounds}? {"=" Ty}? ";" ; /// ``` /// The `"type"` has already been eaten. - fn parse_type_alias(&mut self, def: Defaultness) -> PResult<'a, ItemInfo> { + fn parse_type_alias(&mut self, defaultness: Defaultness) -> PResult<'a, ItemInfo> { let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; @@ -778,10 +781,10 @@ impl<'a> Parser<'a> { if self.eat(&token::Colon) { self.parse_generic_bounds(None)? } else { Vec::new() }; generics.where_clause = self.parse_where_clause()?; - let default = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None }; + let ty = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None }; self.expect_semi()?; - Ok((ident, ItemKind::TyAlias(Box::new(TyAliasKind(def, generics, bounds, default))))) + Ok((ident, ItemKind::TyAlias(Box::new(TyAlias { defaultness, generics, bounds, ty })))) } /// Parses a `UseTree`. @@ -933,7 +936,7 @@ impl<'a> Parser<'a> { let abi = self.parse_abi(); // ABI? 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))) + Ok((Ident::empty(), ItemKind::ForeignMod(module))) } /// Parses a foreign item (one in an `extern { ... }` block). @@ -1039,9 +1042,7 @@ impl<'a> Parser<'a> { }; match impl_info.1 { - ItemKind::Impl(box ImplKind { - of_trait: Some(ref trai), ref mut constness, .. - }) => { + ItemKind::Impl(box Impl { of_trait: Some(ref trai), ref mut constness, .. }) => { *constness = Const::Yes(const_span); let before_trait = trai.path.span.shrink_to_lo(); @@ -1534,18 +1535,43 @@ 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 definition? - fn is_macro_rules_item(&mut self) -> bool { - self.check_keyword(kw::MacroRules) - && self.look_ahead(1, |t| *t == token::Not) - && self.look_ahead(2, |t| t.is_ident()) + /// Is this a possibly malformed start of a `macro_rules! foo` item definition? + + fn is_macro_rules_item(&mut self) -> IsMacroRulesItem { + if self.check_keyword(kw::MacroRules) { + let macro_rules_span = self.token.span; + + if self.look_ahead(1, |t| *t == token::Not) && self.look_ahead(2, |t| t.is_ident()) { + return IsMacroRulesItem::Yes { has_bang: true }; + } else if self.look_ahead(1, |t| (t.is_ident())) { + // macro_rules foo + self.struct_span_err(macro_rules_span, "expected `!` after `macro_rules`") + .span_suggestion( + macro_rules_span, + "add a `!`", + "macro_rules!".to_owned(), + Applicability::MachineApplicable, + ) + .emit(); + + return IsMacroRulesItem::Yes { has_bang: false }; + } + } + + IsMacroRulesItem::No } /// Parses a `macro_rules! foo { ... }` declarative macro. - fn parse_item_macro_rules(&mut self, vis: &Visibility) -> PResult<'a, ItemInfo> { + fn parse_item_macro_rules( + &mut self, + vis: &Visibility, + has_bang: bool, + ) -> PResult<'a, ItemInfo> { self.expect_keyword(kw::MacroRules)?; // `macro_rules` - self.expect(&token::Not)?; // `!` + if has_bang { + self.expect(&token::Not)?; // `!` + } let ident = self.parse_ident()?; if self.eat(&token::Not) { @@ -2121,3 +2147,8 @@ impl<'a> Parser<'a> { } } } + +enum IsMacroRulesItem { + Yes { has_bang: bool }, + No, +} diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 5c701fefd1..9212aaa87d 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1095,8 +1095,12 @@ impl<'a> Parser<'a> { } /// Parses inline const expressions. - fn parse_const_block(&mut self, span: Span) -> PResult<'a, P> { - self.sess.gated_spans.gate(sym::inline_const, span); + fn parse_const_block(&mut self, span: Span, pat: bool) -> PResult<'a, P> { + if pat { + self.sess.gated_spans.gate(sym::inline_const_pat, span); + } else { + self.sess.gated_spans.gate(sym::inline_const, span); + } self.eat_keyword(kw::Const); let blk = self.parse_block()?; let anon_const = AnonConst { @@ -1258,7 +1262,7 @@ impl<'a> Parser<'a> { /// Parses `pub`, `pub(crate)` and `pub(in path)` plus shortcuts `crate` for `pub(crate)`, /// `pub(self)` for `pub(in self)` and `pub(super)` for `pub(in super)`. /// If the following element can't be a tuple (i.e., it's a function definition), then - /// it's not a tuple struct field), and the contents within the parentheses isn't valid, + /// it's not a tuple struct field), and the contents within the parentheses aren't valid, /// so emit a proper diagnostic. // Public for rustfmt usage. pub fn parse_visibility(&mut self, fbt: FollowedByType) -> PResult<'a, Visibility> { diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index b03b545998..bb3947bb47 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -437,7 +437,7 @@ impl<'a> Parser<'a> { PatKind::Box(pat) } else if self.check_inline_const(0) { // Parse `const pat` - let const_expr = self.parse_const_block(lo.to(self.token.span))?; + let const_expr = self.parse_const_block(lo.to(self.token.span), true)?; if let Some(re) = self.parse_range_end() { self.parse_pat_range_begin_with(const_expr, re)? @@ -817,7 +817,7 @@ impl<'a> Parser<'a> { // Ensure the user doesn't receive unhelpful unexpected token errors self.bump(); if self.is_pat_range_end_start(0) { - let _ = self.parse_pat_range_end(); + let _ = self.parse_pat_range_end().map_err(|mut e| e.cancel()); } self.error_inclusive_range_with_extra_equals(span_with_eq); @@ -884,7 +884,7 @@ impl<'a> Parser<'a> { fn parse_pat_range_end(&mut self) -> PResult<'a, P> { if self.check_inline_const(0) { - self.parse_const_block(self.token.span) + self.parse_const_block(self.token.span, true) } else if self.check_path() { let lo = self.token.span; let (qself, path) = if self.eat_lt() { diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index c7d080a80f..7f8fadb33b 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -3,10 +3,11 @@ use super::{Parser, TokenType}; use crate::maybe_whole; use rustc_ast::ptr::P; use rustc_ast::token::{self, Token}; -use rustc_ast::{self as ast, AngleBracketedArg, AngleBracketedArgs, ParenthesizedArgs}; -use rustc_ast::{AnonConst, AssocTyConstraint, AssocTyConstraintKind, BlockCheckMode}; -use rustc_ast::{GenericArg, GenericArgs}; -use rustc_ast::{Path, PathSegment, QSelf}; +use rustc_ast::{ + self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AssocTyConstraint, + AssocTyConstraintKind, BlockCheckMode, GenericArg, GenericArgs, Generics, ParenthesizedArgs, + Path, PathSegment, QSelf, +}; use rustc_errors::{pluralize, Applicability, PResult}; use rustc_span::source_map::{BytePos, Span}; use rustc_span::symbol::{kw, sym, Ident}; @@ -78,7 +79,7 @@ impl<'a> Parser<'a> { } let qself = QSelf { ty, path_span, position: path.segments.len() }; - self.parse_path_segments(&mut path.segments, style)?; + self.parse_path_segments(&mut path.segments, style, None)?; Ok(( qself, @@ -119,6 +120,10 @@ impl<'a> Parser<'a> { true } + pub(super) fn parse_path(&mut self, style: PathStyle) -> PResult<'a, Path> { + self.parse_path_inner(style, None) + } + /// Parses simple paths. /// /// `path = [::] segment+` @@ -129,7 +134,11 @@ impl<'a> Parser<'a> { /// `a::b::C::` (with disambiguator) /// `Fn(Args)` (without disambiguator) /// `Fn::(Args)` (with disambiguator) - pub(super) fn parse_path(&mut self, style: PathStyle) -> PResult<'a, Path> { + pub(super) fn parse_path_inner( + &mut self, + style: PathStyle, + ty_generics: Option<&Generics>, + ) -> PResult<'a, Path> { maybe_whole!(self, NtPath, |path| { if style == PathStyle::Mod && path.segments.iter().any(|segment| segment.args.is_some()) { @@ -152,7 +161,7 @@ impl<'a> Parser<'a> { if self.eat(&token::ModSep) { segments.push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt))); } - self.parse_path_segments(&mut segments, style)?; + self.parse_path_segments(&mut segments, style, ty_generics)?; Ok(Path { segments, span: lo.to(self.prev_token.span), tokens: None }) } @@ -161,9 +170,10 @@ impl<'a> Parser<'a> { &mut self, segments: &mut Vec, style: PathStyle, + ty_generics: Option<&Generics>, ) -> PResult<'a, ()> { loop { - let segment = self.parse_path_segment(style)?; + let segment = self.parse_path_segment(style, ty_generics)?; if style == PathStyle::Expr { // In order to check for trailing angle brackets, we must have finished // recursing (`parse_path_segment` can indirectly call this function), @@ -191,7 +201,11 @@ impl<'a> Parser<'a> { } } - pub(super) fn parse_path_segment(&mut self, style: PathStyle) -> PResult<'a, PathSegment> { + pub(super) fn parse_path_segment( + &mut self, + style: PathStyle, + ty_generics: Option<&Generics>, + ) -> PResult<'a, PathSegment> { let ident = self.parse_path_segment_ident()?; let is_args_start = |token: &Token| { matches!( @@ -229,8 +243,11 @@ impl<'a> Parser<'a> { let lo = self.token.span; let args = if self.eat_lt() { // `<'a, T, A = U>` - let args = - self.parse_angle_args_with_leading_angle_bracket_recovery(style, lo)?; + let args = self.parse_angle_args_with_leading_angle_bracket_recovery( + style, + lo, + ty_generics, + )?; self.expect_gt()?; let span = lo.to(self.prev_token.span); AngleBracketedArgs { args, span }.into() @@ -238,9 +255,9 @@ impl<'a> Parser<'a> { // `(T, U) -> R` let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?; let inputs_span = lo.to(self.prev_token.span); - let span = ident.span.to(self.prev_token.span); let output = self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?; + let span = ident.span.to(self.prev_token.span); ParenthesizedArgs { span, inputs, inputs_span, output }.into() }; @@ -275,6 +292,7 @@ impl<'a> Parser<'a> { &mut self, style: PathStyle, lo: Span, + ty_generics: Option<&Generics>, ) -> PResult<'a, Vec> { // We need to detect whether there are extra leading left angle brackets and produce an // appropriate error and suggestion. This cannot be implemented by looking ahead at @@ -350,7 +368,7 @@ impl<'a> Parser<'a> { let snapshot = if is_first_invocation { Some(self.clone()) } else { None }; debug!("parse_generic_args_with_leading_angle_bracket_recovery: (snapshotting)"); - match self.parse_angle_args() { + match self.parse_angle_args(ty_generics) { Ok(args) => Ok(args), Err(mut e) if is_first_invocation && self.unmatched_angle_bracket_count > 0 => { // Swap `self` with our backup of the parser state before attempting to parse @@ -403,7 +421,7 @@ impl<'a> Parser<'a> { .emit(); // Try again without unmatched angle bracket characters. - self.parse_angle_args() + self.parse_angle_args(ty_generics) } } Err(e) => Err(e), @@ -412,9 +430,12 @@ impl<'a> Parser<'a> { /// Parses (possibly empty) list of generic arguments / associated item constraints, /// possibly including trailing comma. - pub(super) fn parse_angle_args(&mut self) -> PResult<'a, Vec> { + pub(super) fn parse_angle_args( + &mut self, + ty_generics: Option<&Generics>, + ) -> PResult<'a, Vec> { let mut args = Vec::new(); - while let Some(arg) = self.parse_angle_arg()? { + while let Some(arg) = self.parse_angle_arg(ty_generics)? { args.push(arg); if !self.eat(&token::Comma) { if !self.token.kind.should_end_const_arg() { @@ -431,9 +452,12 @@ impl<'a> Parser<'a> { } /// Parses a single argument in the angle arguments `<...>` of a path segment. - fn parse_angle_arg(&mut self) -> PResult<'a, Option> { + fn parse_angle_arg( + &mut self, + ty_generics: Option<&Generics>, + ) -> PResult<'a, Option> { let lo = self.token.span; - let arg = self.parse_generic_arg()?; + let arg = self.parse_generic_arg(ty_generics)?; match arg { Some(arg) => { if self.check(&token::Colon) | self.check(&token::Eq) { @@ -476,7 +500,7 @@ impl<'a> Parser<'a> { /// That is, parse `` in `Item = `. /// Right now, this only admits types in ``. fn parse_assoc_equality_term(&mut self, ident: Ident, eq: Span) -> PResult<'a, P> { - let arg = self.parse_generic_arg()?; + let arg = self.parse_generic_arg(None)?; let span = ident.span.to(self.prev_token.span); match arg { Some(GenericArg::Type(ty)) => return Ok(ty), @@ -563,7 +587,10 @@ impl<'a> Parser<'a> { /// Parse a generic argument in a path segment. /// This does not include constraints, e.g., `Item = u8`, which is handled in `parse_angle_arg`. - pub(super) fn parse_generic_arg(&mut self) -> PResult<'a, Option> { + pub(super) fn parse_generic_arg( + &mut self, + ty_generics: Option<&Generics>, + ) -> PResult<'a, Option> { let start = self.token.span; let arg = if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) { // Parse lifetime argument. @@ -580,25 +607,8 @@ impl<'a> Parser<'a> { return self.recover_const_arg(start, err).map(Some); } } - } else if self.eat_keyword_noexpect(kw::Const) { - // Detect and recover from the old, pre-RFC2000 syntax for const generics. - let mut err = self.struct_span_err( - start, - "expected lifetime, type, or constant, found keyword `const`", - ); - if self.check_const_arg() { - err.span_suggestion_verbose( - start.until(self.token.span), - "the `const` keyword is only needed in the definition of the type", - String::new(), - Applicability::MaybeIncorrect, - ); - err.emit(); - GenericArg::Const(self.parse_const_arg()?) - } else { - let after_kw_const = self.token.span; - return self.recover_const_arg(after_kw_const, err).map(Some); - } + } else if self.token.is_keyword(kw::Const) { + return self.recover_const_param_declaration(ty_generics); } else { return Ok(None); }; diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 9ec6effeb4..01e751ea8b 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -16,7 +16,7 @@ use rustc_ast::{ }; use rustc_ast::{Block, BlockCheckMode, Expr, ExprKind, Local, Stmt}; use rustc_ast::{StmtKind, DUMMY_NODE_ID}; -use rustc_errors::{Applicability, PResult}; +use rustc_errors::{Applicability, DiagnosticBuilder, PResult}; use rustc_span::source_map::{BytePos, Span}; use rustc_span::symbol::{kw, sym}; @@ -300,6 +300,12 @@ impl<'a> Parser<'a> { None => LocalKind::Decl, Some(init) => { if self.eat_keyword(kw::Else) { + if self.token.is_keyword(kw::If) { + // `let...else if`. Emit the same error that `parse_block()` would, + // but explicitly point out that this pattern is not allowed. + let msg = "conditional `else if` is not supported for `let...else`"; + return Err(self.error_block_no_opening_brace_msg(msg)); + } let els = self.parse_block()?; self.check_let_else_init_bool_expr(&init); self.check_let_else_init_trailing_brace(&init); @@ -328,7 +334,7 @@ impl<'a> Parser<'a> { ), ) .multipart_suggestion( - "wrap the expression in parenthesis", + "wrap the expression in parentheses", suggs, Applicability::MachineApplicable, ) @@ -349,7 +355,7 @@ impl<'a> Parser<'a> { "right curly brace `}` before `else` in a `let...else` statement not allowed", ) .multipart_suggestion( - "try wrapping the expression in parenthesis", + "try wrapping the expression in parentheses", suggs, Applicability::MachineApplicable, ) @@ -392,10 +398,9 @@ impl<'a> Parser<'a> { Ok(block) } - fn error_block_no_opening_brace(&mut self) -> PResult<'a, T> { + fn error_block_no_opening_brace_msg(&mut self, msg: &str) -> DiagnosticBuilder<'a> { let sp = self.token.span; - let tok = super::token_descr(&self.token); - let mut e = self.struct_span_err(sp, &format!("expected `{{`, found {}", tok)); + let mut e = self.struct_span_err(sp, msg); let do_not_suggest_help = self.token.is_keyword(kw::In) || self.token == token::Colon; // Check to see if the user has written something like @@ -435,7 +440,13 @@ impl<'a> Parser<'a> { _ => {} } e.span_label(sp, "expected `{`"); - Err(e) + e + } + + fn error_block_no_opening_brace(&mut self) -> PResult<'a, T> { + let tok = super::token_descr(&self.token); + let msg = format!("expected `{{`, found {}", tok); + Err(self.error_block_no_opening_brace_msg(&msg)) } /// Parses a block. Inner attributes are allowed. diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 98400372c3..9bfde0e390 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -4,9 +4,10 @@ use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; use rustc_ast::ptr::P; use rustc_ast::token::{self, Token, TokenKind}; -use rustc_ast::{self as ast, BareFnTy, FnRetTy, GenericParam, Lifetime, MutTy, Ty, TyKind}; -use rustc_ast::{GenericBound, GenericBounds, MacCall, Mutability}; -use rustc_ast::{PolyTraitRef, TraitBoundModifier, TraitObjectSyntax}; +use rustc_ast::{ + self as ast, BareFnTy, FnRetTy, GenericBound, GenericBounds, GenericParam, Generics, Lifetime, + MacCall, MutTy, Mutability, PolyTraitRef, TraitBoundModifier, TraitObjectSyntax, Ty, TyKind, +}; use rustc_errors::{pluralize, struct_span_err, Applicability, PResult}; use rustc_span::source_map::Span; use rustc_span::symbol::{kw, sym}; @@ -98,6 +99,20 @@ impl<'a> Parser<'a> { AllowCVariadic::No, RecoverQPath::Yes, RecoverReturnSign::Yes, + None, + ) + } + + pub(super) fn parse_ty_with_generics_recovery( + &mut self, + ty_params: &Generics, + ) -> PResult<'a, P> { + self.parse_ty_common( + AllowPlus::Yes, + AllowCVariadic::No, + RecoverQPath::Yes, + RecoverReturnSign::Yes, + Some(ty_params), ) } @@ -110,6 +125,7 @@ impl<'a> Parser<'a> { AllowCVariadic::Yes, RecoverQPath::Yes, RecoverReturnSign::Yes, + None, ) } @@ -125,6 +141,7 @@ impl<'a> Parser<'a> { AllowCVariadic::No, RecoverQPath::Yes, RecoverReturnSign::Yes, + None, ) } @@ -135,6 +152,7 @@ impl<'a> Parser<'a> { AllowCVariadic::Yes, RecoverQPath::Yes, RecoverReturnSign::OnlyFatArrow, + None, ) } @@ -152,6 +170,7 @@ impl<'a> Parser<'a> { AllowCVariadic::No, recover_qpath, recover_return_sign, + None, )?; FnRetTy::Ty(ty) } else if recover_return_sign.can_recover(&self.token.kind) { @@ -171,6 +190,7 @@ impl<'a> Parser<'a> { AllowCVariadic::No, recover_qpath, recover_return_sign, + None, )?; FnRetTy::Ty(ty) } else { @@ -184,6 +204,7 @@ impl<'a> Parser<'a> { allow_c_variadic: AllowCVariadic, recover_qpath: RecoverQPath, recover_return_sign: RecoverReturnSign, + ty_generics: Option<&Generics>, ) -> PResult<'a, P> { let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes; maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery); @@ -233,7 +254,7 @@ impl<'a> Parser<'a> { let (qself, path) = self.parse_qpath(PathStyle::Type)?; TyKind::Path(Some(qself), path) } else if self.check_path() { - self.parse_path_start_ty(lo, allow_plus)? + self.parse_path_start_ty(lo, allow_plus, ty_generics)? } else if self.can_begin_bound() { self.parse_bare_trait_object(lo, allow_plus)? } else if self.eat(&token::DotDotDot) { @@ -430,7 +451,7 @@ impl<'a> Parser<'a> { } // Parses the `typeof(EXPR)`. - // To avoid ambiguity, the type is surrounded by parenthesis. + // To avoid ambiguity, the type is surrounded by parentheses. fn parse_typeof_ty(&mut self) -> PResult<'a, TyKind> { self.expect(&token::OpenDelim(token::Paren))?; let expr = self.parse_anon_const_expr()?; @@ -512,9 +533,14 @@ impl<'a> Parser<'a> { /// 1. a type macro, `mac!(...)`, /// 2. a bare trait object, `B0 + ... + Bn`, /// 3. or a path, `path::to::MyType`. - fn parse_path_start_ty(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> { + fn parse_path_start_ty( + &mut self, + lo: Span, + allow_plus: AllowPlus, + ty_generics: Option<&Generics>, + ) -> PResult<'a, TyKind> { // Simple path - let path = self.parse_path(PathStyle::Type)?; + let path = self.parse_path_inner(PathStyle::Type, ty_generics)?; if self.eat(&token::Not) { // Macro invocation in type position Ok(TyKind::MacCall(MacCall { diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index 2aa20d02c8..4781813ee8 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -5,7 +5,7 @@ use crate::parse_in; use rustc_ast::tokenstream::{DelimSpan, TokenTree}; use rustc_ast::{self as ast, Attribute, MacArgs, MacDelimiter, MetaItem, MetaItemKind}; use rustc_errors::{Applicability, FatalError, PResult}; -use rustc_feature::{AttributeTemplate, BUILTIN_ATTRIBUTE_MAP}; +use rustc_feature::{AttributeTemplate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT; use rustc_session::parse::ParseSess; use rustc_span::{sym, Symbol}; @@ -15,14 +15,13 @@ pub fn check_meta(sess: &ParseSess, attr: &Attribute) { return; } - let attr_info = - attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)).map(|a| **a); + let attr_info = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)); // Check input tokens for built-in and key-value attributes. match attr_info { // `rustc_dummy` doesn't have any restrictions specific to built-in attributes. - Some((name, _, template, _)) if name != sym::rustc_dummy => { - check_builtin_attribute(sess, attr, name, template) + Some(BuiltinAttribute { name, template, .. }) if *name != sym::rustc_dummy => { + check_builtin_attribute(sess, attr, *name, *template) } _ if let MacArgs::Eq(..) = attr.get_normal_item().args => { // All key-value attributes are restricted to meta-item syntax. @@ -168,7 +167,7 @@ pub fn emit_fatal_malformed_builtin_attribute( attr: &Attribute, name: Symbol, ) -> ! { - let template = BUILTIN_ATTRIBUTE_MAP.get(&name).expect("builtin attr defined").2; + let template = BUILTIN_ATTRIBUTE_MAP.get(&name).expect("builtin attr defined").template; emit_malformed_attribute(sess, attr, name, template); // This is fatal, otherwise it will likely cause a cascade of other errors // (and an error here is expected to be very rare). diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index e5fbddda74..f761eaae5a 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -9,9 +9,9 @@ use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_ast::{ast, AttrStyle, Attribute, Lit, LitKind, NestedMetaItem}; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashMap; use rustc_errors::{pluralize, struct_span_err, Applicability}; -use rustc_feature::{AttributeType, BUILTIN_ATTRIBUTE_MAP}; +use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; @@ -23,6 +23,7 @@ use rustc_session::lint::builtin::{ use rustc_session::parse::feature_err; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{MultiSpan, Span, DUMMY_SP}; +use std::collections::hash_map::Entry; pub(crate) fn target_from_impl_item<'tcx>( tcx: TyCtxt<'tcx>, @@ -69,7 +70,7 @@ impl CheckAttrVisitor<'tcx> { let mut doc_aliases = FxHashMap::default(); let mut is_valid = true; let mut specified_inline = None; - let mut seen = FxHashSet::default(); + let mut seen = FxHashMap::default(); let attrs = self.tcx.hir().attrs(hir_id); for attr in attrs { let attr_is_valid = match attr.name_or_empty() { @@ -112,6 +113,7 @@ impl CheckAttrVisitor<'tcx> { self.check_default_method_body_is_const(attr, span, target) } sym::must_not_suspend => self.check_must_not_suspend(&attr, span, target), + sym::must_use => self.check_must_use(hir_id, &attr, span, target), sym::rustc_const_unstable | sym::rustc_const_stable | sym::unstable @@ -147,8 +149,10 @@ impl CheckAttrVisitor<'tcx> { _ => {} } + let builtin = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)); + if hir_id != CRATE_HIR_ID { - if let Some((_, AttributeType::CrateLevel, ..)) = + if let Some(BuiltinAttribute { type_: AttributeType::CrateLevel, .. }) = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)) { self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| { @@ -164,21 +168,37 @@ impl CheckAttrVisitor<'tcx> { } } - // Duplicate attributes - match attr.name_or_empty() { - name @ sym::macro_use => { - let args = attr.meta_item_list().unwrap_or_else(Vec::new); - let args: Vec<_> = args.iter().map(|arg| arg.name_or_empty()).collect(); - if !seen.insert((name, args)) { - self.tcx.struct_span_lint_hir( - UNUSED_ATTRIBUTES, - hir_id, + if let Some(BuiltinAttribute { duplicates, .. }) = builtin { + check_duplicates(self.tcx, attr, hir_id, *duplicates, &mut seen); + } + + // Warn on useless empty attributes. + if matches!( + attr.name_or_empty(), + sym::macro_use + | sym::allow + | sym::warn + | sym::deny + | sym::forbid + | sym::feature + | sym::repr + | sym::target_feature + ) && attr.meta_item_list().map_or(false, |list| list.is_empty()) + { + self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| { + lint.build("unused attribute") + .span_suggestion( attr.span, - |lint| lint.build("unused attribute").emit(), - ); - } - } - _ => {} + "remove this attribute", + String::new(), + Applicability::MachineApplicable, + ) + .note(&format!( + "attribute `{}` with an empty list has no effect", + attr.name_or_empty() + )) + .emit(); + }); } } @@ -765,7 +785,7 @@ impl CheckAttrVisitor<'tcx> { "not a `use` item", ); } - err.note("read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#docno_inlinedocinline for more information") + err.note("read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline for more information") .emit(); }, ); @@ -962,7 +982,7 @@ impl CheckAttrVisitor<'tcx> { } sym::primitive => { - if !self.tcx.features().doc_primitive { + if !self.tcx.features().rustdoc_internals { self.tcx.struct_span_lint_hir( INVALID_DOC_ATTRIBUTES, hir_id, @@ -1046,6 +1066,37 @@ impl CheckAttrVisitor<'tcx> { is_valid } + /// Warns against some misuses of `#[must_use]` + fn check_must_use( + &self, + hir_id: HirId, + attr: &Attribute, + span: &Span, + _target: Target, + ) -> bool { + let node = self.tcx.hir().get(hir_id); + if let Some(fn_node) = node.fn_kind() { + if let rustc_hir::IsAsync::Async = fn_node.asyncness() { + self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| { + lint.build( + "`must_use` attribute on `async` functions \ + applies to the anonymous `Future` returned by the \ + function, not the value within", + ) + .span_label( + *span, + "this attribute does nothing, the `Future`s \ + returned by async functions are already `must_use`", + ) + .emit(); + }); + } + } + + // For now, its always valid + true + } + /// Checks if `#[must_not_suspend]` is applied to a function. Returns `true` if valid. fn check_must_not_suspend(&self, attr: &Attribute, span: &Span, target: Target) -> bool { match target { @@ -1958,3 +2009,77 @@ fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { check_mod_attrs, ..*providers }; } + +fn check_duplicates( + tcx: TyCtxt<'_>, + attr: &Attribute, + hir_id: HirId, + duplicates: AttributeDuplicates, + seen: &mut FxHashMap, +) { + use AttributeDuplicates::*; + if matches!(duplicates, WarnFollowingWordOnly) && !attr.is_word() { + return; + } + match duplicates { + DuplicatesOk => {} + WarnFollowing | FutureWarnFollowing | WarnFollowingWordOnly | FutureWarnPreceding => { + match seen.entry(attr.name_or_empty()) { + Entry::Occupied(mut entry) => { + let (this, other) = if matches!(duplicates, FutureWarnPreceding) { + let to_remove = entry.insert(attr.span); + (to_remove, attr.span) + } else { + (attr.span, *entry.get()) + }; + tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, this, |lint| { + let mut db = lint.build("unused attribute"); + db.span_note(other, "attribute also specified here").span_suggestion( + this, + "remove this attribute", + String::new(), + Applicability::MachineApplicable, + ); + if matches!(duplicates, FutureWarnFollowing | FutureWarnPreceding) { + db.warn( + "this was previously accepted by the compiler but is \ + being phased out; it will become a hard error in \ + a future release!", + ); + } + db.emit(); + }); + } + Entry::Vacant(entry) => { + entry.insert(attr.span); + } + } + } + ErrorFollowing | ErrorPreceding => match seen.entry(attr.name_or_empty()) { + Entry::Occupied(mut entry) => { + let (this, other) = if matches!(duplicates, ErrorPreceding) { + let to_remove = entry.insert(attr.span); + (to_remove, attr.span) + } else { + (attr.span, *entry.get()) + }; + tcx.sess + .struct_span_err( + this, + &format!("multiple `{}` attributes", attr.name_or_empty()), + ) + .span_note(other, "attribute also specified here") + .span_suggestion( + this, + "remove this attribute", + String::new(), + Applicability::MachineApplicable, + ) + .emit(); + } + Entry::Vacant(entry) => { + entry.insert(attr.span); + } + }, + } +} diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs index a0ceb567f2..9ccf76b570 100644 --- a/compiler/rustc_passes/src/check_const.rs +++ b/compiler/rustc_passes/src/check_const.rs @@ -173,6 +173,12 @@ impl<'tcx> CheckConstVisitor<'tcx> { None => return true, }; + // If the function belongs to a trait, then it must enable the const_trait_impl + // feature to use that trait function (with a const default body). + if tcx.trait_of_item(def_id).is_some() { + return true; + } + // If this crate is not using stability attributes, or this function is not claiming to be a // stable `const fn`, that is all that is required. if !tcx.features().staged_api || tcx.has_attr(def_id, sym::rustc_const_unstable) { @@ -210,10 +216,10 @@ impl<'tcx> CheckConstVisitor<'tcx> { required_gates.iter().copied().filter(|&g| !features.enabled(g)).collect(); match missing_gates.as_slice() { - &[] => struct_span_err!(tcx.sess, span, E0744, "{}", msg).emit(), + [] => struct_span_err!(tcx.sess, span, E0744, "{}", msg).emit(), - &[missing_primary, ref missing_secondary @ ..] => { - let mut err = feature_err(&tcx.sess.parse_sess, missing_primary, span, &msg); + [missing_primary, ref missing_secondary @ ..] => { + let mut err = feature_err(&tcx.sess.parse_sess, *missing_primary, span, &msg); // If multiple feature gates would be required to enable this expression, include // them as help messages. Don't emit a separate error for each missing feature gate. diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index 4adec3c4f6..af1c724410 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -7,7 +7,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(crate_visibility_modifier)] #![feature(in_band_lifetimes)] -#![feature(format_args_capture)] +#![cfg_attr(bootstrap, feature(format_args_capture))] #![feature(iter_zip)] #![feature(map_try_insert)] #![feature(min_specialization)] diff --git a/compiler/rustc_passes/src/region.rs b/compiler/rustc_passes/src/region.rs index 5fc8e230d7..6a8feb041d 100644 --- a/compiler/rustc_passes/src/region.rs +++ b/compiler/rustc_passes/src/region.rs @@ -334,9 +334,10 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h // properly, we can't miss any types. match expr.kind { - // Manually recurse over closures, because they are the only + // Manually recurse over closures and inline consts, because they are the only // case of nested bodies that share the parent environment. - hir::ExprKind::Closure(.., body, _, _) => { + hir::ExprKind::Closure(.., body, _, _) + | hir::ExprKind::ConstBlock(hir::AnonConst { body, .. }) => { let body = visitor.tcx.hir().body(body); visitor.visit_body(body); } @@ -817,9 +818,9 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> { } fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree { - let closure_base_def_id = tcx.closure_base_def_id(def_id); - if closure_base_def_id != def_id { - return tcx.region_scope_tree(closure_base_def_id); + let typeck_root_def_id = tcx.typeck_root_def_id(def_id); + if typeck_root_def_id != def_id { + return tcx.region_scope_tree(typeck_root_def_id); } let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index ae3a9c71c5..11668146f7 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -23,7 +23,7 @@ use rustc_middle::span_bug; use rustc_middle::thir::abstract_const::Node as ACNode; use rustc_middle::ty::fold::TypeVisitor; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::subst::{InternalSubsts, Subst}; +use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::{self, Const, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeFoldable}; use rustc_session::lint; use rustc_span::hygiene::Transparency; @@ -124,9 +124,11 @@ where fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow { match predicate.kind().skip_binder() { - ty::PredicateKind::Trait(ty::TraitPredicate { trait_ref, constness: _ }) => { - self.visit_trait(trait_ref) - } + ty::PredicateKind::Trait(ty::TraitPredicate { + trait_ref, + constness: _, + polarity: _, + }) => self.visit_trait(trait_ref), ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, ty }) => { ty.visit_with(self)?; self.visit_projection_ty(projection_ty) @@ -153,11 +155,8 @@ where tcx: TyCtxt<'tcx>, ct: AbstractConst<'tcx>, ) -> ControlFlow { - const_evaluatable::walk_abstract_const(tcx, ct, |node| match node.root() { - ACNode::Leaf(leaf) => { - let leaf = leaf.subst(tcx, ct.substs); - self.visit_const(leaf) - } + const_evaluatable::walk_abstract_const(tcx, ct, |node| match node.root(tcx) { + ACNode::Leaf(leaf) => self.visit_const(leaf), ACNode::Cast(_, _, ty) => self.visit_ty(ty), ACNode::Binop(..) | ACNode::UnaryOp(..) | ACNode::FunctionCall(_, _) => { ControlFlow::CONTINUE @@ -544,7 +543,7 @@ impl EmbargoVisitor<'tcx> { module: LocalDefId, ) { let level = Some(AccessLevel::Reachable); - if let ty::Visibility::Public = vis { + if vis.is_public() { self.update(def_id, level); } match def_kind { @@ -581,7 +580,7 @@ impl EmbargoVisitor<'tcx> { DefKind::Struct | DefKind::Union => { // While structs and unions have type privacy, their fields do not. - if let ty::Visibility::Public = vis { + if vis.is_public() { let item = self.tcx.hir().expect_item(self.tcx.hir().local_def_id_to_hir_id(def_id)); if let hir::ItemKind::Struct(ref struct_def, _) @@ -619,6 +618,7 @@ impl EmbargoVisitor<'tcx> { | DefKind::Use | DefKind::ForeignMod | DefKind::AnonConst + | DefKind::InlineConst | DefKind::Field | DefKind::GlobalAsm | DefKind::Impl @@ -933,7 +933,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { let def_id = self.tcx.hir().local_def_id(id); if let Some(exports) = self.tcx.module_exports(def_id) { for export in exports.iter() { - if export.vis == ty::Visibility::Public { + if export.vis.is_public() { if let Some(def_id) = export.res.opt_def_id() { if let Some(def_id) = def_id.as_local() { self.update(def_id, Some(AccessLevel::Exported)); @@ -1918,8 +1918,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'tcx> { /// 1. It's contained within a public type /// 2. It comes from a private crate fn leaks_private_dep(&self, item_id: DefId) -> bool { - let ret = self.required_visibility == ty::Visibility::Public - && self.tcx.is_private_dep(item_id.krate); + let ret = self.required_visibility.is_public() && self.tcx.is_private_dep(item_id.krate); tracing::debug!("leaks_private_dep(item_id={:?})={}", item_id, ret); ret diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index 89df3d4674..f984bb1872 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -7,9 +7,8 @@ edition = "2021" doctest = false [dependencies] -measureme = "9.0.0" +measureme = "10.0.0" rustc-rayon-core = "0.3.1" -tracing = "0.1" rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index e50a8c191a..440b6f1983 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -13,23 +13,19 @@ extern crate rustc_macros; #[macro_use] extern crate rustc_middle; -#[macro_use] -extern crate tracing; -use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_errors::DiagnosticBuilder; -use rustc_middle::dep_graph; +use rustc_middle::arena::Arena; +use rustc_middle::dep_graph::{self, DepKindStruct, SerializedDepNodeIndex}; use rustc_middle::ty::query::{query_keys, query_storage, query_stored, query_values}; -use rustc_middle::ty::query::{Providers, QueryEngine}; +use rustc_middle::ty::query::{ExternProviders, Providers, QueryEngine}; use rustc_middle::ty::{self, TyCtxt}; -use rustc_query_system::ich::StableHashingContext; +use rustc_span::def_id::LocalDefId; use rustc_span::Span; #[macro_use] mod plumbing; pub use plumbing::QueryCtxt; -use plumbing::QueryStruct; use rustc_query_system::query::*; mod stats; @@ -41,9 +37,8 @@ use keys::Key; mod values; use self::values::Value; -use rustc_query_system::query::QueryAccessors; pub use rustc_query_system::query::QueryConfig; -pub(crate) use rustc_query_system::query::QueryDescription; +pub(crate) use rustc_query_system::query::{QueryDescription, QueryVtable}; mod on_disk_cache; pub use on_disk_cache::OnDiskCache; @@ -53,6 +48,14 @@ pub use self::profiling_support::alloc_self_profile_query_strings; mod util; +fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String { + if def_id.is_top_level_module() { + "top-level module".to_string() + } else { + format!("module `{}`", tcx.def_path_str(def_id.to_def_id())) + } +} + rustc_query_append! { [define_queries!][<'tcx>] } impl<'tcx> Queries<'tcx> { diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs index 48eb488792..552906aac3 100644 --- a/compiler/rustc_query_impl/src/on_disk_cache.rs +++ b/compiler/rustc_query_impl/src/on_disk_cache.rs @@ -219,7 +219,7 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> { // Do this *before* we clone 'latest_foreign_def_path_hashes', since // loading existing queries may cause us to create new DepNodes, which // may in turn end up invoking `store_foreign_def_id_hash` - tcx.dep_graph.exec_cache_promotions(QueryCtxt::from_tcx(tcx)); + tcx.dep_graph.exec_cache_promotions(tcx); *self.serialized_data.write() = None; } @@ -358,23 +358,6 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> { Ok(()) }) } - - fn def_path_hash_to_def_id(&self, tcx: TyCtxt<'tcx>, hash: DefPathHash) -> DefId { - debug!("def_path_hash_to_def_id({:?})", hash); - - let stable_crate_id = hash.stable_crate_id(); - - // If this is a DefPathHash from the local crate, we can look up the - // DefId in the tcx's `Definitions`. - if stable_crate_id == tcx.sess.local_stable_crate_id() { - tcx.definitions_untracked().local_def_path_hash_to_def_id(hash).to_def_id() - } else { - // If this is a DefPathHash from an upstream crate, let the CrateStore map - // it to a DefId. - let cnum = tcx.cstore_untracked().stable_crate_id_to_crate_num(stable_crate_id); - tcx.cstore_untracked().def_path_hash_to_def_id(cnum, hash) - } - } } impl<'sess> OnDiskCache<'sess> { @@ -764,7 +747,7 @@ impl<'a, 'tcx> Decodable> for DefId { // If we get to this point, then all of the query inputs were green, // which means that the definition with this hash is guaranteed to // still exist in the current compilation session. - Ok(d.tcx().on_disk_cache.as_ref().unwrap().def_path_hash_to_def_id(d.tcx(), def_path_hash)) + Ok(d.tcx().def_path_hash_to_def_id(def_path_hash)) } } @@ -1035,7 +1018,7 @@ pub fn encode_query_results<'a, 'tcx, CTX, Q>( ) -> FileEncodeResult where CTX: QueryContext + 'tcx, - Q: super::QueryDescription + super::QueryAccessors, + Q: super::QueryDescription, Q::Value: Encodable>, { let _timer = tcx @@ -1050,7 +1033,7 @@ where if res.is_err() { return; } - if Q::cache_on_disk(tcx, &key, Some(value)) { + if Q::cache_on_disk(*tcx.dep_context(), &key) { let dep_node = SerializedDepNodeIndex::new(dep_node.index()); // Record position of the cache entry. diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 4d1e39db0e..81a36e0d59 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -2,20 +2,17 @@ //! generate the actual methods on tcx which find and execute the provider, //! manage the caches, and so forth. -use crate::{on_disk_cache, queries, Queries}; -use rustc_middle::dep_graph::{DepKind, DepNode, DepNodeIndex, SerializedDepNodeIndex}; +use crate::{on_disk_cache, Queries}; +use rustc_middle::dep_graph::{DepKind, DepNodeIndex, SerializedDepNodeIndex}; use rustc_middle::ty::tls::{self, ImplicitCtxt}; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::TyCtxt; use rustc_query_system::dep_graph::HasDepContext; -use rustc_query_system::query::{ - QueryContext, QueryDescription, QueryJobId, QueryMap, QuerySideEffects, -}; +use rustc_query_system::query::{QueryContext, QueryJobId, QueryMap, QuerySideEffects}; use rustc_data_structures::sync::Lock; use rustc_data_structures::thin_vec::ThinVec; use rustc_errors::{Diagnostic, Handler}; use rustc_serialize::opaque; -use rustc_span::def_id::LocalDefId; use std::any::Any; @@ -53,36 +50,6 @@ impl QueryContext for QueryCtxt<'tcx> { self.queries.try_collect_active_jobs(**self) } - fn try_load_from_on_disk_cache(&self, dep_node: &DepNode) { - let cb = &super::QUERY_CALLBACKS[dep_node.kind as usize]; - (cb.try_load_from_on_disk_cache)(*self, dep_node) - } - - fn try_force_from_dep_node(&self, dep_node: &DepNode) -> bool { - debug!("try_force_from_dep_node({:?}) --- trying to force", dep_node); - - // We must avoid ever having to call `force_from_dep_node()` for a - // `DepNode::codegen_unit`: - // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we - // would always end up having to evaluate the first caller of the - // `codegen_unit` query that *is* reconstructible. This might very well be - // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just - // to re-trigger calling the `codegen_unit` query with the right key. At - // that point we would already have re-done all the work we are trying to - // avoid doing in the first place. - // The solution is simple: Just explicitly call the `codegen_unit` query for - // each CGU, right after partitioning. This way `try_mark_green` will always - // hit the cache instead of having to go through `force_from_dep_node`. - // This assertion makes sure, we actually keep applying the solution above. - debug_assert!( - dep_node.kind != DepKind::codegen_unit, - "calling force_from_dep_node() on DepKind::codegen_unit" - ); - - let cb = &super::QUERY_CALLBACKS[dep_node.kind as usize]; - (cb.force_from_dep_node)(*self, dep_node) - } - // Interactions with on_disk_cache fn load_side_effects(&self, prev_dep_node_index: SerializedDepNodeIndex) -> QuerySideEffects { self.queries @@ -193,60 +160,6 @@ impl<'tcx> QueryCtxt<'tcx> { } } -/// This struct stores metadata about each Query. -/// -/// Information is retrieved by indexing the `QUERIES` array using the integer value -/// of the `DepKind`. Overall, this allows to implement `QueryContext` using this manual -/// jump table instead of large matches. -pub struct QueryStruct { - /// The red/green evaluation system will try to mark a specific DepNode in the - /// dependency graph as green by recursively trying to mark the dependencies of - /// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode` - /// where we don't know if it is red or green and we therefore actually have - /// to recompute its value in order to find out. Since the only piece of - /// information that we have at that point is the `DepNode` we are trying to - /// re-evaluate, we need some way to re-run a query from just that. This is what - /// `force_from_dep_node()` implements. - /// - /// In the general case, a `DepNode` consists of a `DepKind` and an opaque - /// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint - /// is usually constructed by computing a stable hash of the query-key that the - /// `DepNode` corresponds to. Consequently, it is not in general possible to go - /// back from hash to query-key (since hash functions are not reversible). For - /// this reason `force_from_dep_node()` is expected to fail from time to time - /// because we just cannot find out, from the `DepNode` alone, what the - /// corresponding query-key is and therefore cannot re-run the query. - /// - /// The system deals with this case letting `try_mark_green` fail which forces - /// the root query to be re-evaluated. - /// - /// Now, if `force_from_dep_node()` would always fail, it would be pretty useless. - /// Fortunately, we can use some contextual information that will allow us to - /// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we - /// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a - /// valid `DefPathHash`. Since we also always build a huge table that maps every - /// `DefPathHash` in the current codebase to the corresponding `DefId`, we have - /// everything we need to re-run the query. - /// - /// Take the `mir_promoted` query as an example. Like many other queries, it - /// just has a single parameter: the `DefId` of the item it will compute the - /// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode` - /// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode` - /// is actually a `DefPathHash`, and can therefore just look up the corresponding - /// `DefId` in `tcx.def_path_hash_to_def_id`. - /// - /// When you implement a new query, it will likely have a corresponding new - /// `DepKind`, and you'll have to support it here in `force_from_dep_node()`. As - /// a rule of thumb, if your query takes a `DefId` or `LocalDefId` as sole parameter, - /// then `force_from_dep_node()` should not fail for it. Otherwise, you can just - /// add it to the "We don't have enough information to reconstruct..." group in - /// the match below. - pub(crate) force_from_dep_node: fn(tcx: QueryCtxt<'_>, dep_node: &DepNode) -> bool, - - /// Invoke a query to put the on-disk cached value in memory. - pub(crate) try_load_from_on_disk_cache: fn(QueryCtxt<'_>, &DepNode), -} - macro_rules! handle_cycle_error { ([][$tcx: expr, $error:expr]) => {{ $error.emit(); @@ -291,14 +204,30 @@ macro_rules! is_eval_always { } macro_rules! hash_result { - ([][$hcx:expr, $result:expr]) => {{ - dep_graph::hash_result($hcx, &$result) + ([]) => {{ + Some(dep_graph::hash_result) }}; - ([(no_hash) $($rest:tt)*][$hcx:expr, $result:expr]) => {{ + ([(no_hash) $($rest:tt)*]) => {{ None }}; + ([$other:tt $($modifiers:tt)*]) => { + hash_result!([$($modifiers)*]) + }; +} + +macro_rules! get_provider { + ([][$tcx:expr, $name:ident, $key:expr]) => {{ + $tcx.queries.local_providers.$name + }}; + ([(separate_provide_extern) $($rest:tt)*][$tcx:expr, $name:ident, $key:expr]) => {{ + if $key.query_crate_is_local() { + $tcx.queries.local_providers.$name + } else { + $tcx.queries.extern_providers.$name + } + }}; ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => { - hash_result!([$($modifiers)*][$($args)*]) + get_provider!([$($modifiers)*][$($args)*]) }; } @@ -374,10 +303,8 @@ macro_rules! define_queries { const NAME: &'static str = stringify!($name); } - impl<$tcx> QueryAccessors> for queries::$name<$tcx> { - const ANON: bool = is_anon!([$($modifiers)*]); - const EVAL_ALWAYS: bool = is_eval_always!([$($modifiers)*]); - const DEP_KIND: dep_graph::DepKind = dep_graph::DepKind::$name; + impl<$tcx> QueryDescription> for queries::$name<$tcx> { + rustc_query_description! { $name<$tcx> } type Cache = query_storage::$name<$tcx>; @@ -396,32 +323,25 @@ macro_rules! define_queries { } #[inline] - fn compute_fn(tcx: QueryCtxt<'tcx>, key: &Self::Key) -> - fn(TyCtxt<'tcx>, Self::Key) -> Self::Value + fn make_vtable(tcx: QueryCtxt<'tcx>, key: &Self::Key) -> + QueryVtable, Self::Key, Self::Value> { - if key.query_crate_is_local() { - tcx.queries.local_providers.$name - } else { - tcx.queries.extern_providers.$name + let compute = get_provider!([$($modifiers)*][tcx, $name, key]); + let cache_on_disk = Self::cache_on_disk(tcx.tcx, key); + QueryVtable { + anon: is_anon!([$($modifiers)*]), + eval_always: is_eval_always!([$($modifiers)*]), + dep_kind: dep_graph::DepKind::$name, + hash_result: hash_result!([$($modifiers)*]), + handle_cycle_error: |tcx, mut error| handle_cycle_error!([$($modifiers)*][tcx, error]), + compute, + cache_on_disk, + try_load_from_disk: Self::TRY_LOAD_FROM_DISK, } } - - fn hash_result( - _hcx: &mut StableHashingContext<'_>, - _result: &Self::Value - ) -> Option { - hash_result!([$($modifiers)*][_hcx, _result]) - } - - fn handle_cycle_error( - tcx: QueryCtxt<'tcx>, - mut error: DiagnosticBuilder<'_>, - ) -> Self::Value { - handle_cycle_error!([$($modifiers)*][tcx, error]) - } })* - #[allow(non_upper_case_globals)] + #[allow(nonstandard_style)] pub mod query_callbacks { use super::*; use rustc_middle::dep_graph::DepNode; @@ -431,68 +351,100 @@ macro_rules! define_queries { use rustc_query_system::dep_graph::FingerprintStyle; // We use this for most things when incr. comp. is turned off. - pub const Null: QueryStruct = QueryStruct { - force_from_dep_node: |_, dep_node| bug!("force_from_dep_node: encountered {:?}", dep_node), - try_load_from_on_disk_cache: |_, _| {}, - }; + pub fn Null() -> DepKindStruct { + DepKindStruct { + is_anon: false, + is_eval_always: false, + fingerprint_style: FingerprintStyle::Unit, + force_from_dep_node: Some(|_, dep_node| bug!("force_from_dep_node: encountered {:?}", dep_node)), + try_load_from_on_disk_cache: None, + } + } - pub const TraitSelect: QueryStruct = QueryStruct { - force_from_dep_node: |_, _| false, - try_load_from_on_disk_cache: |_, _| {}, - }; + pub fn TraitSelect() -> DepKindStruct { + DepKindStruct { + is_anon: true, + is_eval_always: false, + fingerprint_style: FingerprintStyle::Unit, + force_from_dep_node: None, + try_load_from_on_disk_cache: None, + } + } - pub const CompileCodegenUnit: QueryStruct = QueryStruct { - force_from_dep_node: |_, _| false, - try_load_from_on_disk_cache: |_, _| {}, - }; + pub fn CompileCodegenUnit() -> DepKindStruct { + DepKindStruct { + is_anon: false, + is_eval_always: false, + fingerprint_style: FingerprintStyle::Opaque, + force_from_dep_node: None, + try_load_from_on_disk_cache: None, + } + } - pub const CompileMonoItem: QueryStruct = QueryStruct { - force_from_dep_node: |_, _| false, - try_load_from_on_disk_cache: |_, _| {}, - }; + pub fn CompileMonoItem() -> DepKindStruct { + DepKindStruct { + is_anon: false, + is_eval_always: false, + fingerprint_style: FingerprintStyle::Opaque, + force_from_dep_node: None, + try_load_from_on_disk_cache: None, + } + } - $(pub const $name: QueryStruct = { - const is_anon: bool = is_anon!([$($modifiers)*]); + $(pub fn $name()-> DepKindStruct { + let is_anon = is_anon!([$($modifiers)*]); + let is_eval_always = is_eval_always!([$($modifiers)*]); - #[inline(always)] - fn fingerprint_style() -> FingerprintStyle { - as DepNodeParams>> - ::fingerprint_style() - } + let fingerprint_style = + as DepNodeParams>>::fingerprint_style(); - fn recover<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option> { - as DepNodeParams>>::recover(tcx, dep_node) + if is_anon || !fingerprint_style.reconstructible() { + return DepKindStruct { + is_anon, + is_eval_always, + fingerprint_style, + force_from_dep_node: None, + try_load_from_on_disk_cache: None, + } } - fn force_from_dep_node(tcx: QueryCtxt<'_>, dep_node: &DepNode) -> bool { - force_query::, _>(tcx, dep_node) + #[inline(always)] + fn recover<'tcx>(tcx: TyCtxt<'tcx>, dep_node: DepNode) -> Option> { + as DepNodeParams>>::recover(tcx, &dep_node) } - fn try_load_from_on_disk_cache(tcx: QueryCtxt<'_>, dep_node: &DepNode) { - if is_anon { - return - } - - if !fingerprint_style().reconstructible() { - return + fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: DepNode) -> bool { + if let Some(key) = recover(tcx, dep_node) { + let tcx = QueryCtxt::from_tcx(tcx); + force_query::, _>(tcx, key, dep_node); + true + } else { + false } + } - debug_assert!(tcx.dep_graph.is_green(dep_node)); + fn try_load_from_on_disk_cache(tcx: TyCtxt<'_>, dep_node: DepNode) { + 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) { + 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) { let _ = tcx.$name(key); } } - QueryStruct { - force_from_dep_node, - try_load_from_on_disk_cache, + DepKindStruct { + is_anon, + is_eval_always, + fingerprint_style, + force_from_dep_node: Some(force_from_dep_node), + try_load_from_on_disk_cache: Some(try_load_from_on_disk_cache), } - };)* + })* } - static QUERY_CALLBACKS: &[QueryStruct] = &make_dep_kind_array!(query_callbacks); + pub fn query_callbacks<'tcx>(arena: &'tcx Arena<'tcx>) -> &'tcx [DepKindStruct] { + arena.alloc_from_iter(make_dep_kind_array!(query_callbacks)) + } } } @@ -504,7 +456,7 @@ macro_rules! define_queries_struct { input: ($(([$($modifiers:tt)*] [$($attr:tt)*] [$name:ident]))*)) => { pub struct Queries<$tcx> { local_providers: Box, - extern_providers: Box, + extern_providers: Box, pub on_disk_cache: Option>, @@ -517,7 +469,7 @@ macro_rules! define_queries_struct { impl<$tcx> Queries<$tcx> { pub fn new( local_providers: Providers, - extern_providers: Providers, + extern_providers: ExternProviders, on_disk_cache: Option>, ) -> Self { Queries { @@ -575,13 +527,3 @@ macro_rules! define_queries_struct { } }; } - -fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String { - if def_id.is_top_level_module() { - "top-level module".to_string() - } else { - format!("module `{}`", tcx.def_path_str(def_id.to_def_id())) - } -} - -rustc_query_description! {} 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 8602219a7f..c274c2cc26 100644 --- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs +++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs @@ -60,8 +60,11 @@ impl DepNode { /// Creates a new, parameterless DepNode. This method will assert /// that the DepNode corresponding to the given DepKind actually /// does not require any parameters. - pub fn new_no_params(kind: K) -> DepNode { - debug_assert!(!kind.has_params()); + pub fn new_no_params(tcx: Ctxt, kind: K) -> DepNode + where + Ctxt: super::DepContext, + { + debug_assert_eq!(tcx.fingerprint_style(kind), FingerprintStyle::Unit); DepNode { kind, hash: Fingerprint::ZERO.into() } } @@ -75,7 +78,7 @@ impl DepNode { #[cfg(debug_assertions)] { - if !kind.fingerprint_style().reconstructible() + if !tcx.fingerprint_style(kind).reconstructible() && (tcx.sess().opts.debugging_opts.incremental_info || tcx.sess().opts.debugging_opts.query_dep_graph) { @@ -121,11 +124,12 @@ impl DepNodeParams for T where T: for<'a> HashStable> + fmt::Debug, { - #[inline] + #[inline(always)] default fn fingerprint_style() -> FingerprintStyle { FingerprintStyle::Opaque } + #[inline(always)] default fn to_fingerprint(&self, tcx: Ctxt) -> Fingerprint { let mut hcx = tcx.create_stable_hashing_context(); let mut hasher = StableHasher::new(); @@ -135,10 +139,12 @@ where hasher.finish() } + #[inline(always)] default fn to_debug_str(&self, _: Ctxt) -> String { format!("{:?}", *self) } + #[inline(always)] default fn recover(_: Ctxt, _: &DepNode) -> Option { None } diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 114d12fb90..a8be1ca34c 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -33,12 +33,6 @@ pub struct DepGraph { /// each task has a `DepNodeIndex` that uniquely identifies it. This unique /// ID is used for self-profiling. virtual_dep_node_index: Lrc, - - /// The cached event id for profiling node interning. This saves us - /// from having to look up the event id every time we intern a node - /// which may incur too much overhead. - /// This will be None if self-profiling is disabled. - node_intern_event_id: Option, } rustc_index::newtype_index! { @@ -96,14 +90,13 @@ struct DepGraphData { dep_node_debug: Lock, String>>, } -pub fn hash_result(hcx: &mut StableHashingContext<'_>, result: &R) -> Option +pub fn hash_result(hcx: &mut StableHashingContext<'_>, result: &R) -> Fingerprint where R: for<'a> HashStable>, { let mut stable_hasher = StableHasher::new(); result.hash_stable(hcx, &mut stable_hasher); - - Some(stable_hasher.finish()) + stable_hasher.finish() } impl DepGraph { @@ -117,8 +110,13 @@ impl DepGraph { ) -> DepGraph { let prev_graph_node_count = prev_graph.node_count(); - let current = - CurrentDepGraph::new(prev_graph_node_count, encoder, record_graph, record_stats); + let current = CurrentDepGraph::new( + profiler, + prev_graph_node_count, + encoder, + record_graph, + record_stats, + ); // Instantiate a dependy-less node only once for anonymous queries. let _green_node_index = current.intern_new_node( @@ -129,10 +127,6 @@ impl DepGraph { ); debug_assert_eq!(_green_node_index, DepNodeIndex::SINGLETON_DEPENDENCYLESS_ANON_NODE); - let node_intern_event_id = profiler - .get_or_alloc_cached_string("incr_comp_intern_dep_graph_node") - .map(EventId::from_label); - DepGraph { data: Some(Lrc::new(DepGraphData { previous_work_products: prev_work_products, @@ -143,16 +137,11 @@ impl DepGraph { colors: DepNodeColorMap::new(prev_graph_node_count), })), virtual_dep_node_index: Lrc::new(AtomicU32::new(0)), - node_intern_event_id, } } pub fn new_disabled() -> DepGraph { - DepGraph { - data: None, - virtual_dep_node_index: Lrc::new(AtomicU32::new(0)), - node_intern_event_id: None, - } + DepGraph { data: None, virtual_dep_node_index: Lrc::new(AtomicU32::new(0)) } } /// Returns `true` if we are actually building the full dep-graph, and `false` otherwise. @@ -215,7 +204,7 @@ impl DepGraph { cx: Ctxt, arg: A, task: fn(Ctxt, A) -> R, - hash_result: fn(&mut StableHashingContext<'_>, &R) -> Option, + hash_result: Option, &R) -> Fingerprint>, ) -> (R, DepNodeIndex) { if self.is_fully_enabled() { self.with_task_impl(key, cx, arg, task, hash_result) @@ -234,7 +223,7 @@ impl DepGraph { cx: Ctxt, arg: A, task: fn(Ctxt, A) -> R, - hash_result: fn(&mut StableHashingContext<'_>, &R) -> Option, + hash_result: Option, &R) -> Fingerprint>, ) -> (R, DepNodeIndex) { // This function is only called when the graph is enabled. let data = self.data.as_ref().unwrap(); @@ -253,7 +242,7 @@ impl DepGraph { key ); - let task_deps = if key.kind.is_eval_always() { + let task_deps = if cx.dep_context().is_eval_always(key.kind) { None } else { Some(Lock::new(TaskDeps { @@ -268,15 +257,14 @@ impl DepGraph { let edges = task_deps.map_or_else(|| smallvec![], |lock| lock.into_inner().reads); let dcx = cx.dep_context(); - let mut hcx = dcx.create_stable_hashing_context(); let hashing_timer = dcx.profiler().incr_result_hashing(); - let current_fingerprint = hash_result(&mut hcx, &result); + let current_fingerprint = hash_result.map(|f| { + let mut hcx = dcx.create_stable_hashing_context(); + f(&mut hcx, &result) + }); let print_status = cfg!(debug_assertions) && dcx.sess().opts.debugging_opts.dep_tasks; - // Get timer for profiling `DepNode` interning - let node_intern_timer = - self.node_intern_event_id.map(|eid| dcx.profiler().generic_activity_with_event_id(eid)); // Intern the new `DepNode`. let (dep_node_index, prev_and_color) = data.current.intern_node( dcx.profiler(), @@ -286,7 +274,6 @@ impl DepGraph { current_fingerprint, print_status, ); - drop(node_intern_timer); hashing_timer.finish_with_query_invocation_id(dep_node_index.into()); @@ -315,7 +302,7 @@ impl DepGraph { where OP: FnOnce() -> R, { - debug_assert!(!dep_kind.is_eval_always()); + debug_assert!(!cx.is_eval_always(dep_kind)); if let Some(ref data) = self.data { let task_deps = Lock::new(TaskDeps::default()); @@ -492,7 +479,7 @@ impl DepGraph { tcx: Ctxt, dep_node: &DepNode, ) -> Option<(SerializedDepNodeIndex, DepNodeIndex)> { - debug_assert!(!dep_node.kind.is_eval_always()); + debug_assert!(!tcx.dep_context().is_eval_always(dep_node.kind)); // Return None if the dep graph is disabled let data = self.data.as_ref()?; @@ -552,7 +539,7 @@ impl DepGraph { // We don't know the state of this dependency. If it isn't // an eval_always node, let's try to mark it green recursively. - if !dep_dep_node.kind.is_eval_always() { + if !tcx.dep_context().is_eval_always(dep_dep_node.kind) { debug!( "try_mark_previous_green({:?}) --- state of dependency {:?} ({}) \ is unknown, trying to mark it green", @@ -575,7 +562,7 @@ impl DepGraph { "try_mark_previous_green({:?}) --- trying to force dependency {:?}", dep_node, dep_dep_node ); - if !tcx.try_force_from_dep_node(dep_dep_node) { + if !tcx.dep_context().try_force_from_dep_node(*dep_dep_node) { // The DepNode could not be forced. debug!( "try_mark_previous_green({:?}) - END - dependency {:?} could not be forced", @@ -642,7 +629,7 @@ impl DepGraph { } // We never try to mark eval_always nodes as green - debug_assert!(!dep_node.kind.is_eval_always()); + debug_assert!(!tcx.dep_context().is_eval_always(dep_node.kind)); debug_assert_eq!(data.previous.index_to_node(prev_dep_node_index), *dep_node); @@ -740,8 +727,7 @@ impl DepGraph { // // This method will only load queries that will end up in the disk cache. // Other queries will not be executed. - pub fn exec_cache_promotions>(&self, qcx: Ctxt) { - let tcx = qcx.dep_context(); + pub fn exec_cache_promotions>(&self, tcx: Ctxt) { let _prof_timer = tcx.profiler().generic_activity("incr_comp_query_cache_promotion"); let data = self.data.as_ref().unwrap(); @@ -749,7 +735,7 @@ impl DepGraph { match data.colors.get(prev_index) { Some(DepNodeColor::Green(_)) => { let dep_node = data.previous.index_to_node(prev_index); - qcx.try_load_from_on_disk_cache(&dep_node); + tcx.try_load_from_on_disk_cache(dep_node); } None | Some(DepNodeColor::Red) => { // We can skip red nodes because a node can only be marked @@ -876,10 +862,17 @@ pub(super) struct CurrentDepGraph { /// debugging and only active with `debug_assertions`. total_read_count: AtomicU64, total_duplicate_read_count: AtomicU64, + + /// The cached event id for profiling node interning. This saves us + /// from having to look up the event id every time we intern a node + /// which may incur too much overhead. + /// This will be None if self-profiling is disabled. + node_intern_event_id: Option, } impl CurrentDepGraph { fn new( + profiler: &SelfProfilerRef, prev_graph_node_count: usize, encoder: FileEncoder, record_graph: bool, @@ -908,6 +901,10 @@ impl CurrentDepGraph { let new_node_count_estimate = 102 * prev_graph_node_count / 100 + 200; + let node_intern_event_id = profiler + .get_or_alloc_cached_string("incr_comp_intern_dep_graph_node") + .map(EventId::from_label); + CurrentDepGraph { encoder: Steal::new(GraphEncoder::new( encoder, @@ -927,6 +924,7 @@ impl CurrentDepGraph { forbidden_edge, total_read_count: AtomicU64::new(0), total_duplicate_read_count: AtomicU64::new(0), + node_intern_event_id, } } @@ -970,6 +968,10 @@ impl CurrentDepGraph { ) -> (DepNodeIndex, Option<(SerializedDepNodeIndex, DepNodeColor)>) { let print_status = cfg!(debug_assertions) && print_status; + // Get timer for profiling `DepNode` interning + let _node_intern_timer = + self.node_intern_event_id.map(|eid| profiler.generic_activity_with_event_id(eid)); + 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 { diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index dcda572833..047fc9f10c 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -32,6 +32,17 @@ pub trait DepContext: Copy { /// Access the compiler session. fn sess(&self) -> &Session; + + /// Return whether this kind always require evaluation. + fn is_eval_always(&self, kind: Self::DepKind) -> bool; + + fn fingerprint_style(&self, kind: Self::DepKind) -> FingerprintStyle; + + /// Try to force a dep node to execute and see if it's green. + fn try_force_from_dep_node(&self, dep_node: DepNode) -> bool; + + /// Load data from the on-disk cache. + fn try_load_from_on_disk_cache(&self, dep_node: DepNode); } pub trait HasDepContext: Copy { @@ -51,7 +62,7 @@ impl HasDepContext for T { } /// Describes the contents of the fingerprint generated by a given query. -#[derive(PartialEq, Eq, Copy, Clone)] +#[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum FingerprintStyle { /// The fingerprint is actually a DefPathHash. DefPathHash, @@ -75,12 +86,6 @@ impl FingerprintStyle { pub trait DepKind: Copy + fmt::Debug + Eq + Hash + Send + Encodable + 'static { const NULL: Self; - /// Return whether this kind always require evaluation. - fn is_eval_always(&self) -> bool; - - /// Return whether this kind requires additional parameters to be executed. - fn has_params(&self) -> bool; - /// Implementation of `std::fmt::Debug` for `DepNode`. fn debug_node(node: &DepNode, f: &mut fmt::Formatter<'_>) -> fmt::Result; @@ -93,6 +98,4 @@ pub trait DepKind: Copy + fmt::Debug + Eq + Hash + Send + Encodable fn read_deps(op: OP) where OP: for<'a> FnOnce(Option<&'a Lock>>); - - fn fingerprint_style(&self) -> FingerprintStyle; } diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index f5f67fcd0a..47197a1e49 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -222,7 +222,7 @@ impl EncoderState { index } - fn finish(self) -> FileEncodeResult { + fn finish(self, profiler: &SelfProfilerRef) -> FileEncodeResult { let Self { mut encoder, total_node_count, total_edge_count, result, stats: _ } = self; let () = result?; @@ -235,7 +235,11 @@ impl EncoderState { IntEncodedWithFixedSize(edge_count).encode(&mut encoder)?; debug!("position: {:?}", encoder.position()); // Drop the encoder so that nothing is written after the counts. - encoder.flush() + let result = encoder.flush(); + // FIXME(rylev): we hardcode the dep graph file name so we don't need a dependency on + // rustc_incremental just for that. + profiler.artifact_size("dep_graph", "dep-graph.bin", encoder.position() as u64); + result } } @@ -332,6 +336,6 @@ impl> GraphEncoder { pub fn finish(self, profiler: &SelfProfilerRef) -> FileEncodeResult { let _prof_timer = profiler.generic_activity("incr_comp_encode_dep_graph"); - self.status.into_inner().finish() + self.status.into_inner().finish(profiler) } } diff --git a/compiler/rustc_query_system/src/ich/hcx.rs b/compiler/rustc_query_system/src/ich/hcx.rs index f2e935c59f..5f31fa04b8 100644 --- a/compiler/rustc_query_system/src/ich/hcx.rs +++ b/compiler/rustc_query_system/src/ich/hcx.rs @@ -1,6 +1,7 @@ use crate::ich; use rustc_ast as ast; use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; use rustc_hir as hir; @@ -27,7 +28,6 @@ pub struct StableHashingContext<'a> { cstore: &'a dyn CrateStore, pub(super) body_resolver: BodyResolver<'a>, hash_spans: bool, - hash_bodies: bool, pub(super) node_id_hashing_mode: NodeIdHashingMode, // Very often, we are hashing something that does not need the @@ -46,24 +46,19 @@ pub enum NodeIdHashingMode { /// We could also just store a plain reference to the `hir::Crate` but we want /// to avoid that the crate is used to get untracked access to all of the HIR. #[derive(Clone, Copy)] -pub(super) struct BodyResolver<'tcx>(&'tcx hir::Crate<'tcx>); - -impl<'tcx> BodyResolver<'tcx> { - /// Returns a reference to the `hir::Body` with the given `BodyId`. - /// **Does not do any tracking**; use carefully. - pub(super) fn body(self, id: hir::BodyId) -> &'tcx hir::Body<'tcx> { - self.0.body(id) - } +pub(super) enum BodyResolver<'tcx> { + Forbidden, + Traverse { + hash_bodies: bool, + owner: LocalDefId, + bodies: &'tcx SortedMap>, + }, } impl<'a> StableHashingContext<'a> { - /// The `krate` here is only used for mapping `BodyId`s to `Body`s. - /// Don't use it for anything else or you'll run the risk of - /// leaking data out of the tracking system. #[inline] fn new_with_or_without_spans( sess: &'a Session, - krate: &'a hir::Crate<'a>, definitions: &'a Definitions, cstore: &'a dyn CrateStore, always_ignore_spans: bool, @@ -72,13 +67,12 @@ impl<'a> StableHashingContext<'a> { !always_ignore_spans && !sess.opts.debugging_opts.incremental_ignore_spans; StableHashingContext { - body_resolver: BodyResolver(krate), + body_resolver: BodyResolver::Forbidden, definitions, cstore, caching_source_map: None, raw_source_map: sess.source_map(), hash_spans: hash_spans_initial, - hash_bodies: true, node_id_hashing_mode: NodeIdHashingMode::HashDefPath, } } @@ -86,13 +80,11 @@ impl<'a> StableHashingContext<'a> { #[inline] pub fn new( sess: &'a Session, - krate: &'a hir::Crate<'a>, definitions: &'a Definitions, cstore: &'a dyn CrateStore, ) -> Self { Self::new_with_or_without_spans( sess, - krate, definitions, cstore, /*always_ignore_spans=*/ false, @@ -102,20 +94,41 @@ impl<'a> StableHashingContext<'a> { #[inline] pub fn ignore_spans( sess: &'a Session, - krate: &'a hir::Crate<'a>, definitions: &'a Definitions, cstore: &'a dyn CrateStore, ) -> Self { let always_ignore_spans = true; - Self::new_with_or_without_spans(sess, krate, definitions, cstore, always_ignore_spans) + Self::new_with_or_without_spans(sess, definitions, cstore, always_ignore_spans) } + /// Allow hashing #[inline] - pub fn while_hashing_hir_bodies(&mut self, hash_bodies: bool, f: F) { - let prev_hash_bodies = self.hash_bodies; - self.hash_bodies = hash_bodies; + pub fn while_hashing_hir_bodies(&mut self, hb: bool, f: impl FnOnce(&mut Self)) { + let prev = match &mut self.body_resolver { + BodyResolver::Forbidden => panic!("Hashing HIR bodies is forbidden."), + BodyResolver::Traverse { ref mut hash_bodies, .. } => { + std::mem::replace(hash_bodies, hb) + } + }; f(self); - self.hash_bodies = prev_hash_bodies; + match &mut self.body_resolver { + BodyResolver::Forbidden => unreachable!(), + BodyResolver::Traverse { ref mut hash_bodies, .. } => *hash_bodies = prev, + } + } + + #[inline] + pub fn with_hir_bodies( + &mut self, + hash_bodies: bool, + owner: LocalDefId, + bodies: &'a SortedMap>, + f: impl FnOnce(&mut Self), + ) { + let prev = self.body_resolver; + self.body_resolver = BodyResolver::Traverse { hash_bodies, owner, bodies }; + f(self); + self.body_resolver = prev; } #[inline] @@ -152,11 +165,6 @@ impl<'a> StableHashingContext<'a> { self.definitions.def_path_hash(def_id) } - #[inline] - pub fn hash_bodies(&self) -> bool { - self.hash_bodies - } - #[inline] pub fn source_map(&mut self) -> &mut CachingSourceMapView<'a> { match self.caching_source_map { diff --git a/compiler/rustc_query_system/src/ich/impls_hir.rs b/compiler/rustc_query_system/src/ich/impls_hir.rs index 04eb263a97..3a0aab81fd 100644 --- a/compiler/rustc_query_system/src/ich/impls_hir.rs +++ b/compiler/rustc_query_system/src/ich/impls_hir.rs @@ -1,12 +1,11 @@ //! This module contains `HashStable` implementations for various HIR data //! types in no particular order. +use crate::ich::hcx::BodyResolver; use crate::ich::{NodeIdHashingMode, StableHashingContext}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; use rustc_hir as hir; -use rustc_hir::definitions::DefPathHash; -use smallvec::SmallVec; use std::mem; impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { @@ -29,8 +28,13 @@ impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { #[inline] fn hash_body_id(&mut self, id: hir::BodyId, hasher: &mut StableHasher) { let hcx = self; - if hcx.hash_bodies() { - hcx.body_resolver.body(id).hash_stable(hcx, hasher); + match hcx.body_resolver { + BodyResolver::Forbidden => panic!("Hashing HIR bodies is forbidden."), + BodyResolver::Traverse { hash_bodies: false, .. } => {} + BodyResolver::Traverse { hash_bodies: true, owner, bodies } => { + assert_eq!(id.hir_id.owner, owner); + bodies[&id.hir_id.local_id].hash_stable(hcx, hasher); + } } } @@ -115,6 +119,16 @@ impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { self.node_id_hashing_mode = prev_hash_node_ids; } + + #[inline] + fn hash_hir_trait_candidate(&mut self, tc: &hir::TraitCandidate, hasher: &mut StableHasher) { + self.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { + let hir::TraitCandidate { def_id, import_ids } = tc; + + def_id.hash_stable(hcx, hasher); + import_ids.hash_stable(hcx, hasher); + }); + } } impl<'a> HashStable> for hir::Body<'_> { @@ -129,27 +143,3 @@ impl<'a> HashStable> for hir::Body<'_> { }); } } - -impl<'a> HashStable> for hir::TraitCandidate { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { - let hir::TraitCandidate { def_id, import_ids } = self; - - def_id.hash_stable(hcx, hasher); - import_ids.hash_stable(hcx, hasher); - }); - } -} - -impl<'a> ToStableHashKey> for hir::TraitCandidate { - type KeyType = (DefPathHash, SmallVec<[DefPathHash; 1]>); - - fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> Self::KeyType { - let hir::TraitCandidate { def_id, import_ids } = self; - - ( - hcx.def_path_hash(*def_id), - import_ids.iter().map(|def_id| hcx.local_def_path_hash(*def_id)).collect(), - ) - } -} diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs index bc23de069b..b1295ba48c 100644 --- a/compiler/rustc_query_system/src/lib.rs +++ b/compiler/rustc_query_system/src/lib.rs @@ -3,8 +3,10 @@ #![feature(core_intrinsics)] #![feature(hash_raw_entry)] #![feature(iter_zip)] +#![feature(let_else)] #![feature(min_specialization)] #![feature(thread_local_const_init)] +#![feature(extern_types)] #[macro_use] extern crate tracing; diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs index 76a165ed8e..d2b102b6f8 100644 --- a/compiler/rustc_query_system/src/query/config.rs +++ b/compiler/rustc_query_system/src/query/config.rs @@ -19,15 +19,16 @@ pub trait QueryConfig { type Stored: Clone; } -pub(crate) struct QueryVtable { +pub struct QueryVtable { pub anon: bool, pub dep_kind: CTX::DepKind, pub eval_always: bool, + pub cache_on_disk: bool, - pub hash_result: fn(&mut StableHashingContext<'_>, &V) -> Option, + pub compute: fn(CTX::DepContext, K) -> V, + pub hash_result: Option, &V) -> Fingerprint>, pub handle_cycle_error: fn(CTX, DiagnosticBuilder<'_>) -> V, - pub cache_on_disk: fn(CTX, &K, Option<&V>) -> bool, - pub try_load_from_disk: fn(CTX, SerializedDepNodeIndex) -> Option, + pub try_load_from_disk: Option Option>, } impl QueryVtable { @@ -38,30 +39,25 @@ impl QueryVtable { DepNode::construct(tcx, self.dep_kind, key) } - pub(crate) fn hash_result( - &self, - hcx: &mut StableHashingContext<'_>, - value: &V, - ) -> Option { - (self.hash_result)(hcx, value) - } - - pub(crate) fn cache_on_disk(&self, tcx: CTX, key: &K, value: Option<&V>) -> bool { - (self.cache_on_disk)(tcx, key, value) + pub(crate) fn compute(&self, tcx: CTX::DepContext, key: K) -> V { + (self.compute)(tcx, key) } pub(crate) fn try_load_from_disk(&self, tcx: CTX, index: SerializedDepNodeIndex) -> Option { - (self.try_load_from_disk)(tcx, index) + self.try_load_from_disk + .expect("QueryDescription::load_from_disk() called for an unsupported query.")( + tcx, index, + ) } } -pub trait QueryAccessors: QueryConfig { - const ANON: bool; - const EVAL_ALWAYS: bool; - const DEP_KIND: CTX::DepKind; +pub trait QueryDescription: QueryConfig { + const TRY_LOAD_FROM_DISK: Option Option>; type Cache: QueryCache; + fn describe(tcx: CTX, key: Self::Key) -> String; + // Don't use this method to access query results, instead use the methods on TyCtxt fn query_state<'a>(tcx: CTX) -> &'a QueryState where @@ -73,43 +69,7 @@ pub trait QueryAccessors: QueryConfig { CTX: 'a; // Don't use this method to compute query results, instead use the methods on TyCtxt - fn compute_fn(tcx: CTX, key: &Self::Key) -> fn(CTX::DepContext, Self::Key) -> Self::Value; - - fn hash_result(hcx: &mut StableHashingContext<'_>, result: &Self::Value) - -> Option; - - fn handle_cycle_error(tcx: CTX, diag: DiagnosticBuilder<'_>) -> Self::Value; -} - -pub trait QueryDescription: QueryAccessors { - fn describe(tcx: CTX, key: Self::Key) -> String; - - #[inline] - fn cache_on_disk(_: CTX, _: &Self::Key, _: Option<&Self::Value>) -> bool { - false - } - - fn try_load_from_disk(_: CTX, _: SerializedDepNodeIndex) -> Option { - panic!("QueryDescription::load_from_disk() called for an unsupported query.") - } -} - -pub(crate) trait QueryVtableExt { - const VTABLE: QueryVtable; -} + fn make_vtable(tcx: CTX, key: &Self::Key) -> QueryVtable; -impl QueryVtableExt for Q -where - CTX: QueryContext, - Q: QueryDescription, -{ - const VTABLE: QueryVtable = QueryVtable { - anon: Q::ANON, - dep_kind: Q::DEP_KIND, - eval_always: Q::EVAL_ALWAYS, - hash_result: Q::hash_result, - handle_cycle_error: Q::handle_cycle_error, - cache_on_disk: Q::cache_on_disk, - try_load_from_disk: Q::try_load_from_disk, - }; + fn cache_on_disk(tcx: CTX::DepContext, key: &Self::Key) -> bool; } diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index 98b2a450b1..bd67303099 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -644,9 +644,7 @@ pub fn print_query_stack( if Some(i) == num_frames { break; } - let query_info = if let Some(info) = query_map.as_ref().and_then(|map| map.get(&query)) { - info - } else { + let Some(query_info) = query_map.as_ref().and_then(|map| map.get(&query)) else { break; }; let mut diag = Diagnostic::new( diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index dffe7f3689..a2f7843baa 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -12,9 +12,9 @@ pub use self::caches::{ }; mod config; -pub use self::config::{QueryAccessors, QueryConfig, QueryDescription}; +pub use self::config::{QueryConfig, QueryDescription, QueryVtable}; -use crate::dep_graph::{DepNode, DepNodeIndex, HasDepContext, SerializedDepNodeIndex}; +use crate::dep_graph::{DepNodeIndex, HasDepContext, SerializedDepNodeIndex}; use rustc_data_structures::sync::Lock; use rustc_data_structures::thin_vec::ThinVec; @@ -122,12 +122,6 @@ pub trait QueryContext: HasDepContext { fn try_collect_active_jobs(&self) -> Option>; - /// Load data from the on-disk cache. - fn try_load_from_on_disk_cache(&self, dep_node: &DepNode); - - /// Try to force a dep node to execute and see if it's green. - fn try_force_from_dep_node(&self, dep_node: &DepNode) -> bool; - /// Load side effects associated to the node in the previous session. fn load_side_effects(&self, prev_dep_node_index: SerializedDepNodeIndex) -> QuerySideEffects; diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 07d7205997..b08db39e24 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -2,9 +2,9 @@ //! generate the actual methods on tcx which find and execute the provider, //! manage the caches, and so forth. -use crate::dep_graph::{DepContext, DepKind, DepNode, DepNodeIndex, DepNodeParams}; +use crate::dep_graph::{DepContext, DepNode, DepNodeIndex, DepNodeParams}; use crate::query::caches::QueryCache; -use crate::query::config::{QueryDescription, QueryVtable, QueryVtableExt}; +use crate::query::config::{QueryDescription, QueryVtable}; use crate::query::job::{ report_cycle, QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryShardJobId, }; @@ -18,6 +18,7 @@ use rustc_data_structures::sharded::{get_shard_index_by_hash, Sharded}; use rustc_data_structures::sync::{Lock, LockGuard}; use rustc_data_structures::thin_vec::ThinVec; use rustc_errors::{DiagnosticBuilder, FatalError}; +use rustc_session::Session; use rustc_span::{Span, DUMMY_SP}; use std::cell::Cell; use std::collections::hash_map::Entry; @@ -382,7 +383,6 @@ fn try_execute_query( lookup: QueryLookup, dep_node: Option>, query: &QueryVtable, - compute: fn(CTX::DepContext, C::Key) -> C::Value, ) -> (C::Stored, Option) where C: QueryCache, @@ -398,7 +398,7 @@ where query.dep_kind, ) { TryGetJob::NotYetStarted(job) => { - let (result, dep_node_index) = execute_job(tcx, key, dep_node, query, job.id, compute); + let (result, dep_node_index) = execute_job(tcx, key, dep_node, query, job.id); let result = job.complete(cache, result, dep_node_index); (result, Some(dep_node_index)) } @@ -429,7 +429,6 @@ fn execute_job( mut dep_node_opt: Option>, query: &QueryVtable, job_id: QueryJobId, - compute: fn(CTX::DepContext, K) -> V, ) -> (V, DepNodeIndex) where K: Clone + DepNodeParams, @@ -441,7 +440,7 @@ where // Fast path for when incr. comp. is off. if !dep_graph.is_fully_enabled() { let prof_timer = tcx.dep_context().profiler().query_provider(); - let result = tcx.start_query(job_id, None, || compute(*tcx.dep_context(), key)); + let result = tcx.start_query(job_id, None, || query.compute(*tcx.dep_context(), key)); let dep_node_index = dep_graph.next_virtual_depnode_index(); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); return (result, dep_node_index); @@ -455,7 +454,7 @@ where // The diagnostics for this query will be promoted to the current session during // `try_mark_green()`, so we can ignore them here. if let Some(ret) = tcx.start_query(job_id, None, || { - try_load_from_disk_and_cache_in_memory(tcx, &key, &dep_node, query, compute) + try_load_from_disk_and_cache_in_memory(tcx, &key, &dep_node, query) }) { return ret; } @@ -467,14 +466,14 @@ where let (result, dep_node_index) = tcx.start_query(job_id, Some(&diagnostics), || { if query.anon { return dep_graph.with_anon_task(*tcx.dep_context(), query.dep_kind, || { - compute(*tcx.dep_context(), key) + query.compute(*tcx.dep_context(), key) }); } // `to_dep_node` is expensive for some `DepKind`s. let dep_node = dep_node_opt.unwrap_or_else(|| query.to_dep_node(*tcx.dep_context(), &key)); - dep_graph.with_task(dep_node, *tcx.dep_context(), key, compute, query.hash_result) + dep_graph.with_task(dep_node, *tcx.dep_context(), key, query.compute, query.hash_result) }); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); @@ -498,7 +497,6 @@ fn try_load_from_disk_and_cache_in_memory( key: &K, dep_node: &DepNode, query: &QueryVtable, - compute: fn(CTX::DepContext, K) -> V, ) -> Option<(V, DepNodeIndex)> where K: Clone, @@ -515,28 +513,41 @@ where // First we try to load the result from the on-disk cache. // Some things are never cached on disk. - if query.cache_on_disk(tcx, key, None) { + if query.cache_on_disk { let prof_timer = tcx.dep_context().profiler().incr_cache_loading(); let result = query.try_load_from_disk(tcx, prev_dep_node_index); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); - // We always expect to find a cached result for things that - // can be forced from `DepNode`. - debug_assert!( - !dep_node.kind.fingerprint_style().reconstructible() || result.is_some(), - "missing on-disk cache entry for {:?}", - dep_node - ); - if let Some(result) = result { + let prev_fingerprint = tcx + .dep_context() + .dep_graph() + .prev_fingerprint_of(dep_node) + .unwrap_or(Fingerprint::ZERO); // 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) { + // + // If not, we still seek to verify a subset of fingerprints loaded + // from disk. Re-hashing results is fairly expensive, so we can't + // currently afford to verify every hash. This subset should still + // give us some coverage of potential bugs though. + let try_verify = prev_fingerprint.as_value().1 % 32 == 0; + if unlikely!( + try_verify || tcx.dep_context().sess().opts.debugging_opts.incremental_verify_ich + ) { incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query); } return Some((result, dep_node_index)); } + + // We always expect to find a cached result for things that + // can be forced from `DepNode`. + debug_assert!( + !tcx.dep_context().fingerprint_style(dep_node.kind).reconstructible(), + "missing on-disk cache entry for {:?}", + dep_node + ); } // We could not load a result from the on-disk cache, so @@ -544,7 +555,7 @@ where let prof_timer = tcx.dep_context().profiler().query_provider(); // The dep-graph for this computation is already in-place. - let result = dep_graph.with_ignore(|| compute(*tcx.dep_context(), key.clone())); + let result = dep_graph.with_ignore(|| query.compute(*tcx.dep_context(), key.clone())); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); @@ -577,46 +588,94 @@ fn incremental_verify_ich( ); debug!("BEGIN verify_ich({:?})", dep_node); - let mut hcx = tcx.create_stable_hashing_context(); - - let new_hash = query.hash_result(&mut hcx, result).unwrap_or(Fingerprint::ZERO); - debug!("END verify_ich({:?})", dep_node); - + let new_hash = query.hash_result.map_or(Fingerprint::ZERO, |f| { + let mut hcx = tcx.create_stable_hashing_context(); + f(&mut hcx, result) + }); let old_hash = tcx.dep_graph().prev_fingerprint_of(dep_node); + debug!("END verify_ich({:?})", dep_node); 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 { - "`cargo clean`".to_string() - }; + incremental_verify_ich_cold(tcx.sess(), DebugArg::from(&dep_node), DebugArg::from(&result)); + } +} - // When we emit an error message and panic, we try to debug-print the `DepNode` - // and query result. Unforunately, this can cause us to run additional queries, - // which may result in another fingerprint mismatch while we're in the middle - // of processing this one. To avoid a double-panic (which kills the process - // before we can print out the query static), we print out a terse - // but 'safe' message if we detect a re-entrant call to this method. - thread_local! { - static INSIDE_VERIFY_PANIC: Cell = const { Cell::new(false) }; - }; +// This DebugArg business is largely a mirror of std::fmt::ArgumentV1, which is +// currently not exposed publicly. +// +// The PR which added this attempted to use `&dyn Debug` instead, but that +// showed statistically significant worse compiler performance. It's not +// actually clear what the cause there was -- the code should be cold. If this +// can be replaced with `&dyn Debug` with on perf impact, then it probably +// should be. +extern "C" { + type Opaque; +} - let old_in_panic = INSIDE_VERIFY_PANIC.with(|in_panic| in_panic.replace(true)); +struct DebugArg<'a> { + value: &'a Opaque, + fmt: fn(&Opaque, &mut std::fmt::Formatter<'_>) -> std::fmt::Result, +} - if old_in_panic { - tcx.sess().struct_err("internal compiler error: re-entrant incremental verify failure, suppressing message") - .emit(); - } else { - tcx.sess().struct_err(&format!("internal compiler error: encountered incremental compilation error with {:?}", dep_node)) +impl<'a, T> From<&'a T> for DebugArg<'a> +where + T: std::fmt::Debug, +{ + fn from(value: &'a T) -> DebugArg<'a> { + DebugArg { + value: unsafe { std::mem::transmute(value) }, + fmt: unsafe { + std::mem::transmute(::fmt as fn(_, _) -> std::fmt::Result) + }, + } + } +} + +impl std::fmt::Debug for DebugArg<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + (self.fmt)(self.value, f) + } +} + +// Note that this is marked #[cold] and intentionally takes the equivalent of +// `dyn Debug` for its arguments, as we want to avoid generating a bunch of +// different implementations for LLVM to chew on (and filling up the final +// binary, too). +#[cold] +fn incremental_verify_ich_cold(sess: &Session, dep_node: DebugArg<'_>, result: DebugArg<'_>) { + let run_cmd = if let Some(crate_name) = &sess.opts.crate_name { + format!("`cargo clean -p {}` or `cargo clean`", crate_name) + } else { + "`cargo clean`".to_string() + }; + + // When we emit an error message and panic, we try to debug-print the `DepNode` + // and query result. Unfortunately, this can cause us to run additional queries, + // which may result in another fingerprint mismatch while we're in the middle + // of processing this one. To avoid a double-panic (which kills the process + // before we can print out the query static), we print out a terse + // but 'safe' message if we detect a re-entrant call to this method. + thread_local! { + static INSIDE_VERIFY_PANIC: Cell = const { Cell::new(false) }; + }; + + let old_in_panic = INSIDE_VERIFY_PANIC.with(|in_panic| in_panic.replace(true)); + + if old_in_panic { + sess.struct_err( + "internal compiler error: re-entrant incremental verify failure, suppressing message", + ) + .emit(); + } else { + sess.struct_err(&format!("internal compiler error: encountered incremental compilation error with {:?}", dep_node)) .help(&format!("This is a known issue with the compiler. Run {} to allow your project to compile", run_cmd)) .note(&"Please follow the instructions below to create a bug report with the provided information") .note(&"See for more information") .emit(); - panic!("Found unstable fingerprints for {:?}: {:?}", dep_node, result); - } - - INSIDE_VERIFY_PANIC.with(|in_panic| in_panic.set(old_in_panic)); + panic!("Found unstable fingerprints for {:?}: {:?}", dep_node, result); } + + INSIDE_VERIFY_PANIC.with(|in_panic| in_panic.set(old_in_panic)); } /// Ensure that either this query has all green inputs or been executed. @@ -665,41 +724,6 @@ where } } -#[inline(never)] -fn force_query_impl( - tcx: CTX, - state: &QueryState, - cache: &QueryCacheStore, - key: C::Key, - dep_node: DepNode, - query: &QueryVtable, - compute: fn(CTX::DepContext, C::Key) -> C::Value, -) -> bool -where - C: QueryCache, - C::Key: DepNodeParams, - CTX: QueryContext, -{ - debug_assert!(!query.anon); - - // We may be concurrently trying both execute and force a query. - // Ensure that only one of them runs the query. - let cached = cache.cache.lookup(cache, &key, |_, index| { - if unlikely!(tcx.dep_context().profiler().enabled()) { - tcx.dep_context().profiler().query_cache_hit(index.into()); - } - }); - - let lookup = match cached { - Ok(()) => return true, - Err(lookup) => lookup, - }; - - let _ = - try_execute_query(tcx, state, cache, DUMMY_SP, key, lookup, Some(dep_node), query, compute); - true -} - pub enum QueryMode { Get, Ensure, @@ -717,9 +741,9 @@ where Q::Key: DepNodeParams, CTX: QueryContext, { - let query = &Q::VTABLE; + let query = Q::make_vtable(tcx, &key); let dep_node = if let QueryMode::Ensure = mode { - let (must_run, dep_node) = ensure_must_run(tcx, &key, query); + let (must_run, dep_node) = ensure_must_run(tcx, &key, &query); if !must_run { return None; } @@ -729,7 +753,6 @@ where }; debug!("ty::query::get_query<{}>(key={:?}, span={:?})", Q::NAME, key, span); - let compute = Q::compute_fn(tcx, &key); let (result, dep_node_index) = try_execute_query( tcx, Q::query_state(tcx), @@ -738,8 +761,7 @@ where key, lookup, dep_node, - query, - compute, + &query, ); if let Some(dep_node_index) = dep_node_index { tcx.dep_context().dep_graph().read_index(dep_node_index) @@ -747,36 +769,29 @@ where Some(result) } -pub fn force_query(tcx: CTX, dep_node: &DepNode) -> bool +pub fn force_query(tcx: CTX, key: Q::Key, dep_node: DepNode) where Q: QueryDescription, Q::Key: DepNodeParams, CTX: QueryContext, { - if Q::ANON { - return false; - } - - if !>::fingerprint_style().reconstructible() { - return false; - } + // We may be concurrently trying both execute and force a query. + // Ensure that only one of them runs the query. + let cache = Q::query_cache(tcx); + let cached = cache.cache.lookup(cache, &key, |_, index| { + if unlikely!(tcx.dep_context().profiler().enabled()) { + tcx.dep_context().profiler().query_cache_hit(index.into()); + } + }); - let key = if let Some(key) = - >::recover(*tcx.dep_context(), &dep_node) - { - key - } else { - return false; + let lookup = match cached { + Ok(()) => return, + Err(lookup) => lookup, }; - let compute = Q::compute_fn(tcx, &key); - force_query_impl( - tcx, - Q::query_state(tcx), - Q::query_cache(tcx), - key, - *dep_node, - &Q::VTABLE, - compute, - ) + let query = Q::make_vtable(tcx, &key); + let state = Q::query_state(tcx); + debug_assert!(!query.anon); + + try_execute_query(tcx, state, cache, DUMMY_SP, key, lookup, Some(dep_node), &query); } diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml index f1d3315d6e..bd27c16c73 100644 --- a/compiler/rustc_resolve/Cargo.toml +++ b/compiler/rustc_resolve/Cargo.toml @@ -23,6 +23,7 @@ rustc_feature = { path = "../rustc_feature" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_metadata = { path = "../rustc_metadata" } +rustc_query_system = { path = "../rustc_query_system" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 2a562a06cb..3cf9d324a3 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -15,7 +15,7 @@ use crate::{Resolver, ResolverArenas, Segment, ToNameBinding, VisResolutionError use rustc_ast::visit::{self, AssocCtxt, Visitor}; use rustc_ast::{self as ast, AssocItem, AssocItemKind, MetaItemKind, StmtKind}; -use rustc_ast::{Block, FnKind, ForeignItem, ForeignItemKind, ImplKind, Item, ItemKind, NodeId}; +use rustc_ast::{Block, Fn, ForeignItem, ForeignItemKind, Impl, Item, ItemKind, NodeId}; use rustc_ast_lowering::ResolverAstLowering; use rustc_attr as attr; use rustc_data_structures::sync::Lrc; @@ -145,17 +145,11 @@ impl<'a> Resolver<'a> { } else { def_key.disambiguated_data.data.get_opt_name().expect("module without name") }; - let expn_id = if def_kind == DefKind::Mod { - self.cstore().module_expansion_untracked(def_id, &self.session) - } else { - // FIXME: Parent expansions for enums and traits are not kept in metadata. - ExpnId::root() - }; Some(self.new_module( parent, ModuleKind::Def(def_kind, def_id, name), - expn_id, + self.cstore().module_expansion_untracked(def_id, &self.session), self.cstore().get_span_untracked(def_id, &self.session), // FIXME: Account for `#[no_implicit_prelude]` attributes. parent.map_or(false, |module| module.no_implicit_prelude), @@ -886,7 +880,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } // These items do not add names to modules. - ItemKind::Impl(box ImplKind { of_trait: Some(..), .. }) => { + ItemKind::Impl(box Impl { of_trait: Some(..), .. }) => { self.r.trait_impl_items.insert(local_def_id); } ItemKind::Impl { .. } | ItemKind::ForeignMod(..) | ItemKind::GlobalAsm(..) => {} @@ -973,6 +967,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { | DefKind::Use | DefKind::ForeignMod | DefKind::AnonConst + | DefKind::InlineConst | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm @@ -1199,15 +1194,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { // Mark the given macro as unused unless its name starts with `_`. // Macro uses will remove items from this set, and the remaining // items will be reported as `unused_macros`. - fn insert_unused_macro( - &mut self, - ident: Ident, - def_id: LocalDefId, - node_id: NodeId, - span: Span, - ) { + fn insert_unused_macro(&mut self, ident: Ident, def_id: LocalDefId, node_id: NodeId) { if !ident.as_str().starts_with('_') { - self.r.unused_macros.insert(def_id, (node_id, span)); + self.r.unused_macros.insert(def_id, (node_id, ident)); } } @@ -1251,7 +1240,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { self.r.define(module, ident, MacroNS, (res, vis, span, expansion, IsMacroExport)); } else { self.r.check_reserved_macro_name(ident, res); - self.insert_unused_macro(ident, def_id, item.id, span); + self.insert_unused_macro(ident, def_id, item.id); } self.r.visibilities.insert(def_id, vis); self.r.arenas.alloc_macro_rules_scope(MacroRulesScope::Binding( @@ -1272,7 +1261,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { _ => self.resolve_visibility(&item.vis), }; if vis != ty::Visibility::Public { - self.insert_unused_macro(ident, def_id, item.id, span); + self.insert_unused_macro(ident, def_id, item.id); } self.r.define(module, ident, MacroNS, (res, vis, span, expansion)); self.r.visibilities.insert(def_id, vis); @@ -1386,7 +1375,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { if ctxt == AssocCtxt::Trait { let (def_kind, ns) = match item.kind { AssocItemKind::Const(..) => (DefKind::AssocConst, ValueNS), - AssocItemKind::Fn(box FnKind(_, ref sig, _, _)) => { + AssocItemKind::Fn(box Fn { ref sig, .. }) => { if sig.decl.has_self() { self.r.has_self.insert(def_id); } diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 760b746996..63699128e9 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -32,7 +32,6 @@ use rustc_ast::visit::{self, Visitor}; use rustc_ast_lowering::ResolverAstLowering; use rustc_data_structures::fx::FxHashSet; use rustc_errors::pluralize; -use rustc_middle::ty; use rustc_session::lint::builtin::{MACRO_USE_EXTERN_CRATE, UNUSED_IMPORTS}; use rustc_session::lint::BuiltinLintDiagnostics; use rustc_span::{MultiSpan, Span, DUMMY_SP}; @@ -228,7 +227,7 @@ impl Resolver<'_> { for import in self.potentially_unused_imports.iter() { match import.kind { _ if import.used.get() - || import.vis.get() == ty::Visibility::Public + || import.vis.get().is_public() || import.span.is_dummy() => { if let ImportKind::MacroUse = import.kind { diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 05675e086d..2e4cb4ff72 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -11,7 +11,7 @@ use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::PrimTy; use rustc_middle::bug; -use rustc_middle::ty::{self, DefIdTree}; +use rustc_middle::ty::DefIdTree; use rustc_session::Session; use rustc_span::hygiene::MacroKind; use rustc_span::lev_distance::find_best_match_for_name; @@ -66,6 +66,8 @@ crate struct ImportSuggestion { pub descr: &'static str, pub path: Path, pub accessible: bool, + /// An extra note that should be issued if this item is suggested + pub note: Option, } /// Adjust the impl span so that just the `impl` keyword is taken by removing @@ -418,6 +420,10 @@ impl<'a> Resolver<'a> { err.span_label(span, label); if let Some((suggestions, msg, applicability)) = suggestion { + if suggestions.is_empty() { + err.help(&msg); + return err; + } err.multipart_suggestion(&msg, suggestions, applicability); } @@ -444,12 +450,24 @@ impl<'a> Resolver<'a> { // let foo =... // ^^^ given this Span // ------- get this Span to have an applicable suggestion + + // edit: + // only do this if the const and usage of the non-constant value are on the same line + // the further the two are apart, the higher the chance of the suggestion being wrong + // also make sure that the pos for the suggestion is not 0 (ICE #90878) + let sp = self.session.source_map().span_extend_to_prev_str(ident.span, current, true); - if sp.lo().0 == 0 { + + let pos_for_suggestion = sp.lo().0.saturating_sub(current.len() as u32); + + if sp.lo().0 == 0 + || pos_for_suggestion == 0 + || self.session.source_map().is_multiline(sp) + { err.span_label(ident.span, &format!("this would need to be a `{}`", sugg)); } else { - let sp = sp.with_lo(BytePos(sp.lo().0 - current.len() as u32)); + let sp = sp.with_lo(BytePos(pos_for_suggestion)); err.span_suggestion( sp, &format!("consider using `{}` instead of `{}`", sugg, current), @@ -725,7 +743,7 @@ impl<'a> Resolver<'a> { suggestions.extend( BUILTIN_ATTRIBUTES .iter() - .map(|(name, ..)| TypoSuggestion::typo_from_res(*name, res)), + .map(|attr| TypoSuggestion::typo_from_res(attr.name, res)), ); } } @@ -829,11 +847,22 @@ impl<'a> Resolver<'a> { return; } + // #90113: Do not count an inaccessible reexported item as a candidate. + if let NameBindingKind::Import { binding, .. } = name_binding.kind { + if this.is_accessible_from(binding.vis, parent_scope.module) + && !this.is_accessible_from(name_binding.vis, parent_scope.module) + { + return; + } + } + // collect results based on the filter function // avoid suggesting anything from the same module in which we are resolving + // avoid suggesting anything with a hygienic name if ident.name == lookup_ident.name && ns == namespace && !ptr::eq(in_module, parent_scope.module) + && !ident.span.normalize_to_macros_2_0().from_expansion() { let res = name_binding.res(); if filter_fn(res) { @@ -863,11 +892,38 @@ impl<'a> Resolver<'a> { } if candidates.iter().all(|v: &ImportSuggestion| v.did != did) { + // See if we're recommending TryFrom, TryInto, or FromIterator and add + // a note about editions + let note = if let Some(did) = did { + let requires_note = !did.is_local() + && this.cstore().item_attrs(did, this.session).iter().any( + |attr| { + if attr.has_name(sym::rustc_diagnostic_item) { + [sym::TryInto, sym::TryFrom, sym::FromIterator] + .map(|x| Some(x)) + .contains(&attr.value_str()) + } else { + false + } + }, + ); + + requires_note.then(|| { + format!( + "'{}' is included in the prelude starting in Edition 2021", + path_names_to_string(&path) + ) + }) + } else { + None + }; + candidates.push(ImportSuggestion { did, descr: res.descr(), path, accessible: child_accessible, + note, }); } } @@ -1156,14 +1212,9 @@ impl<'a> Resolver<'a> { (b1, b2, misc1, misc2, false) }; - let mut err = struct_span_err!( - self.session, - ident.span, - E0659, - "`{ident}` is ambiguous ({why})", - why = kind.descr() - ); + let mut err = struct_span_err!(self.session, ident.span, E0659, "`{ident}` is ambiguous"); err.span_label(ident.span, "ambiguous name"); + err.note(&format!("ambiguous because of {}", kind.descr())); let mut could_refer_to = |b: &NameBinding<'_>, misc: AmbiguityErrorMisc, also: &str| { let what = self.binding_description(b, ident, misc == AmbiguityErrorMisc::FromPrelude); @@ -1269,7 +1320,7 @@ impl<'a> Resolver<'a> { ); let def_span = self.session.source_map().guess_head_span(binding.span); let mut note_span = MultiSpan::from_span(def_span); - if !first && binding.vis == ty::Visibility::Public { + if !first && binding.vis.is_public() { note_span.push_span_label(def_span, "consider importing it directly".into()); } err.span_note(note_span, &msg); @@ -1327,7 +1378,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { if fst.ident.span.rust_2018() && !fst.ident.is_path_segment_keyword() => { // Insert a placeholder that's later replaced by `self`/`super`/etc. - path.insert(0, Segment::from_ident(Ident::invalid())); + path.insert(0, Segment::from_ident(Ident::empty())); } _ => return None, } @@ -1471,9 +1522,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { module: ModuleOrUniformRoot<'b>, ident: Ident, ) -> Option<(Option, Vec)> { - let mut crate_module = if let ModuleOrUniformRoot::Module(module) = module { - module - } else { + let ModuleOrUniformRoot::Module(mut crate_module) = module else { return None; }; @@ -1762,12 +1811,14 @@ crate fn show_candidates( return; } - let mut accessible_path_strings: Vec<(String, &str, Option)> = Vec::new(); - let mut inaccessible_path_strings: Vec<(String, &str, Option)> = Vec::new(); + let mut accessible_path_strings: Vec<(String, &str, Option, &Option)> = + Vec::new(); + let mut inaccessible_path_strings: Vec<(String, &str, Option, &Option)> = + Vec::new(); candidates.iter().for_each(|c| { (if c.accessible { &mut accessible_path_strings } else { &mut inaccessible_path_strings }) - .push((path_names_to_string(&c.path), c.descr, c.did)) + .push((path_names_to_string(&c.path), c.descr, c.did, &c.note)) }); // we want consistent results across executions, but candidates are produced @@ -1790,6 +1841,10 @@ crate fn show_candidates( let instead = if instead { " instead" } else { "" }; let mut msg = format!("consider importing {} {}{}", determiner, kind, instead); + for note in accessible_path_strings.iter().map(|cand| cand.3.as_ref()).flatten() { + err.note(note); + } + if let Some(span) = use_placement_span { for candidate in &mut accessible_path_strings { // produce an additional newline to separate the new use statement @@ -1818,7 +1873,7 @@ crate fn show_candidates( assert!(!inaccessible_path_strings.is_empty()); if inaccessible_path_strings.len() == 1 { - let (name, descr, def_id) = &inaccessible_path_strings[0]; + let (name, descr, def_id, note) = &inaccessible_path_strings[0]; let msg = format!("{} `{}` exists but is inaccessible", descr, name); if let Some(local_def_id) = def_id.and_then(|did| did.as_local()) { @@ -1830,12 +1885,15 @@ crate fn show_candidates( } else { err.note(&msg); } + if let Some(note) = (*note).as_deref() { + err.note(note); + } } else { - let (_, descr_first, _) = &inaccessible_path_strings[0]; + let (_, descr_first, _, _) = &inaccessible_path_strings[0]; let descr = if inaccessible_path_strings .iter() .skip(1) - .all(|(_, descr, _)| descr == descr_first) + .all(|(_, descr, _, _)| descr == descr_first) { descr_first.to_string() } else { @@ -1846,7 +1904,7 @@ crate fn show_candidates( let mut has_colon = false; let mut spans = Vec::new(); - for (name, _, def_id) in &inaccessible_path_strings { + for (name, _, def_id, _) in &inaccessible_path_strings { if let Some(local_def_id) = def_id.and_then(|did| did.as_local()) { let span = definitions.def_span(local_def_id); let span = session.source_map().guess_head_span(span); @@ -1866,6 +1924,10 @@ crate fn show_candidates( multi_span.push_span_label(span, format!("`{}`: not accessible", name)); } + for note in inaccessible_path_strings.iter().map(|cand| cand.3.as_ref()).flatten() { + err.note(note); + } + err.span_note(multi_span, &msg); } } diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 515b2c3fd2..bf4cece8bd 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -164,7 +164,7 @@ fn pub_use_of_private_extern_crate_hack(import: &Import<'_>, binding: &NameBindi import: Import { kind: ImportKind::ExternCrate { .. }, .. }, .. }, - ) => import.vis.get() == ty::Visibility::Public, + ) => import.vis.get().is_public(), _ => false, } } @@ -978,7 +978,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { // HACK(eddyb) `lint_if_path_starts_with_module` needs at least // 2 segments, so the `resolve_path` above won't trigger it. let mut full_path = import.module_path.clone(); - full_path.push(Segment::from_ident(Ident::invalid())); + full_path.push(Segment::from_ident(Ident::empty())); self.r.lint_if_path_starts_with_module( import.crate_lint(), &full_path, @@ -1180,11 +1180,17 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let mut reexport_error = None; let mut any_successful_reexport = false; + let mut crate_private_reexport = false; self.r.per_ns(|this, ns| { if let Ok(binding) = source_bindings[ns].get() { let vis = import.vis.get(); if !binding.vis.is_at_least(vis, &*this) { reexport_error = Some((ns, binding)); + if let ty::Visibility::Restricted(binding_def_id) = binding.vis { + if binding_def_id.is_top_level_module() { + crate_private_reexport = true; + } + } } else { any_successful_reexport = true; } @@ -1207,24 +1213,34 @@ impl<'a, 'b> ImportResolver<'a, 'b> { import.span, &msg, ); - } else if ns == TypeNS { - struct_span_err!( - self.r.session, - import.span, - E0365, - "`{}` is private, and cannot be re-exported", - ident - ) - .span_label(import.span, format!("re-export of private `{}`", ident)) - .note(&format!("consider declaring type or module `{}` with `pub`", ident)) - .emit(); } else { - let msg = format!("`{}` is private, and cannot be re-exported", ident); - let note_msg = - format!("consider marking `{}` as `pub` in the imported module", ident,); - struct_span_err!(self.r.session, import.span, E0364, "{}", &msg) - .span_note(import.span, ¬e_msg) - .emit(); + let error_msg = if crate_private_reexport { + format!( + "`{}` is only public within the crate, and cannot be re-exported outside", + ident + ) + } else { + format!("`{}` is private, and cannot be re-exported", ident) + }; + + if ns == TypeNS { + let label_msg = if crate_private_reexport { + format!("re-export of crate public `{}`", ident) + } else { + format!("re-export of private `{}`", ident) + }; + + struct_span_err!(self.r.session, import.span, E0365, "{}", error_msg) + .span_label(import.span, label_msg) + .note(&format!("consider declaring type or module `{}` with `pub`", ident)) + .emit(); + } else { + let note_msg = + format!("consider marking `{}` as `pub` in the imported module", ident); + struct_span_err!(self.r.session, import.span, E0364, "{}", error_msg) + .span_note(import.span, ¬e_msg) + .emit(); + } } } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 9563325796..12123c946c 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -431,6 +431,10 @@ struct LateResolutionVisitor<'a, 'b, 'ast> { /// Walks the whole crate in DFS order, visiting each item, resolving names as it goes. impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { + fn visit_attribute(&mut self, _: &'ast Attribute) { + // We do not want to resolve expressions that appear in attributes, + // as they do not correspond to actual code. + } fn visit_item(&mut self, item: &'ast Item) { let prev = replace(&mut self.diagnostic_metadata.current_item, Some(item)); // Always report errors in items we just entered. @@ -498,8 +502,8 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { } fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) { match foreign_item.kind { - ForeignItemKind::Fn(box FnKind(_, _, ref generics, _)) - | ForeignItemKind::TyAlias(box TyAliasKind(_, ref generics, ..)) => { + ForeignItemKind::Fn(box Fn { ref generics, .. }) + | ForeignItemKind::TyAlias(box TyAlias { ref generics, .. }) => { self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| { visit::walk_foreign_item(this, foreign_item); }); @@ -953,8 +957,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { debug!("(resolving item) resolving {} ({:?})", name, item.kind); match item.kind { - ItemKind::TyAlias(box TyAliasKind(_, ref generics, _, _)) - | ItemKind::Fn(box FnKind(_, _, ref generics, _)) => { + ItemKind::TyAlias(box TyAlias { ref generics, .. }) + | ItemKind::Fn(box Fn { ref generics, .. }) => { self.compute_num_lifetime_params(item.id, generics); self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| { visit::walk_item(this, item) @@ -968,7 +972,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { self.resolve_adt(item, generics); } - ItemKind::Impl(box ImplKind { + ItemKind::Impl(box Impl { ref generics, ref of_trait, ref self_ty, @@ -979,7 +983,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { self.resolve_implementation(generics, of_trait, &self_ty, item.id, impl_items); } - ItemKind::Trait(box TraitKind(.., ref generics, ref bounds, ref trait_items)) => { + ItemKind::Trait(box Trait { ref generics, ref bounds, ref items, .. }) => { self.compute_num_lifetime_params(item.id, generics); // Create a new rib for the trait-wide type parameters. self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| { @@ -994,8 +998,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { }); }; - this.with_trait_items(trait_items, |this| { - for item in trait_items { + this.with_trait_items(items, |this| { + for item in items { match &item.kind { AssocItemKind::Const(_, ty, default) => { this.visit_ty(ty); @@ -1015,10 +1019,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ); } } - AssocItemKind::Fn(box FnKind(_, _, generics, _)) => { + AssocItemKind::Fn(box Fn { generics, .. }) => { walk_assoc_item(this, generics, item); } - AssocItemKind::TyAlias(box TyAliasKind(_, generics, _, _)) => { + AssocItemKind::TyAlias(box TyAlias { generics, .. }) => { walk_assoc_item(this, generics, item); } AssocItemKind::MacCall(_) => { @@ -1338,7 +1342,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { }, ); } - AssocItemKind::Fn(box FnKind(.., generics, _)) => { + AssocItemKind::Fn(box Fn { generics, .. }) => { debug!("resolve_implementation AssocItemKind::Fn"); // We also need a new scope for the impl item type parameters. this.with_generic_param_rib( @@ -1363,12 +1367,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { }, ); } - AssocItemKind::TyAlias(box TyAliasKind( - _, - generics, - _, - _, - )) => { + AssocItemKind::TyAlias(box TyAlias { + generics, .. + }) => { debug!("resolve_implementation AssocItemKind::TyAlias"); // We also need a new scope for the impl item type parameters. this.with_generic_param_rib( @@ -1994,7 +1995,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { if ns == ValueNS { let item_name = path.last().unwrap().ident; let traits = self.traits_in_scope(item_name, ns); - self.r.trait_map.as_mut().unwrap().insert(id, traits); + self.r.trait_map.insert(id, traits); } if PrimTy::from_name(path[0].ident.name).is_some() { @@ -2479,12 +2480,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // the field name so that we can do some nice error reporting // later on in typeck. let traits = self.traits_in_scope(ident, ValueNS); - self.r.trait_map.as_mut().unwrap().insert(expr.id, traits); + self.r.trait_map.insert(expr.id, traits); } ExprKind::MethodCall(ref segment, ..) => { debug!("(recording candidate traits for expr) recording traits for {}", expr.id); let traits = self.traits_in_scope(segment.ident, ValueNS); - self.r.trait_map.as_mut().unwrap().insert(expr.id, traits); + self.r.trait_map.insert(expr.id, traits); } _ => { // Nothing to do. diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 7b0dd82f0e..d506931b51 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -333,7 +333,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { let candidates = self .r .lookup_import_candidates(ident, ns, &self.parent_scope, is_expected) - .drain(..) + .into_iter() .filter(|ImportSuggestion { did, .. }| { match (did, res.and_then(|res| res.opt_def_id())) { (Some(suggestion_did), Some(actual_did)) => *suggestion_did != actual_did, @@ -1235,9 +1235,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { if assoc_item.ident == ident { return Some(match &assoc_item.kind { ast::AssocItemKind::Const(..) => AssocSuggestion::AssocConst, - ast::AssocItemKind::Fn(box ast::FnKind(_, sig, ..)) - if sig.decl.has_self() => - { + ast::AssocItemKind::Fn(box ast::Fn { sig, .. }) if sig.decl.has_self() => { AssocSuggestion::MethodWithSelf } ast::AssocItemKind::Fn(..) => AssocSuggestion::AssocFn, @@ -1346,12 +1344,10 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { } else { // Search in module. let mod_path = &path[..path.len() - 1]; - if let PathResult::Module(module) = + if let PathResult::Module(ModuleOrUniformRoot::Module(module)) = self.resolve_path(mod_path, Some(TypeNS), false, span, CrateLint::No) { - if let ModuleOrUniformRoot::Module(module) = module { - self.r.add_module_candidates(module, &mut names, &filter_fn); - } + self.r.add_module_candidates(module, &mut names, &filter_fn); } } @@ -1502,6 +1498,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { descr: "module", path, accessible: true, + note: None, }, )); } else { @@ -1552,8 +1549,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { matches!(source, PathSource::TupleStruct(..)) || source.is_call(); if suggest_only_tuple_variants { // Suggest only tuple variants regardless of whether they have fields and do not - // suggest path with added parenthesis. - let mut suggestable_variants = variants + // suggest path with added parentheses. + let suggestable_variants = variants .iter() .filter(|(.., kind)| *kind == CtorKind::Fn) .map(|(variant, ..)| path_names_to_string(variant)) @@ -1579,7 +1576,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { err.span_suggestions( span, &msg, - suggestable_variants.drain(..), + suggestable_variants.into_iter(), Applicability::MaybeIncorrect, ); } @@ -1637,7 +1634,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { ); } - let mut suggestable_variants_with_placeholders = variants + let suggestable_variants_with_placeholders = variants .iter() .filter(|(_, def_id, kind)| needs_placeholder(*def_id, *kind)) .map(|(variant, _, kind)| (path_names_to_string(variant), kind)) @@ -1662,7 +1659,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { err.span_suggestions( span, msg, - suggestable_variants_with_placeholders.drain(..), + suggestable_variants_with_placeholders.into_iter(), Applicability::HasPlaceholders, ); } @@ -1813,12 +1810,10 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { let (span, sugg) = if let Some(param) = generics.params.iter().find(|p| { !matches!( p.kind, - hir::GenericParamKind::Type { - synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), - .. - } | hir::GenericParamKind::Lifetime { - kind: hir::LifetimeParamKind::Elided, - } + hir::GenericParamKind::Type { synthetic: true, .. } + | hir::GenericParamKind::Lifetime { + kind: hir::LifetimeParamKind::Elided, + } ) }) { (param.span.shrink_to_lo(), format!("{}, ", lifetime_ref)) @@ -2045,12 +2040,10 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { if let Some(param) = generics.params.iter().find(|p| { !matches!( p.kind, - hir::GenericParamKind::Type { - synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), - .. - } | hir::GenericParamKind::Lifetime { - kind: hir::LifetimeParamKind::Elided - } + hir::GenericParamKind::Type { synthetic: true, .. } + | hir::GenericParamKind::Lifetime { + kind: hir::LifetimeParamKind::Elided + } ) }) { (param.span.shrink_to_lo(), "'a, ".to_string()) diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index eb6f302a11..39e710cb77 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -540,7 +540,7 @@ fn is_late_bound_map<'tcx>( def_id: LocalDefId, ) -> Option<(LocalDefId, &'tcx FxHashSet)> { match tcx.def_kind(def_id) { - DefKind::AnonConst => { + DefKind::AnonConst | DefKind::InlineConst => { let mut def_id = tcx .parent(def_id.to_def_id()) .unwrap_or_else(|| bug!("anon const or closure without a parent")); @@ -887,10 +887,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let (lifetimes, binders): (FxIndexMap, Vec<_>) = c .generic_params .iter() - .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => Some(param), - _ => None, - }) + .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. })) .enumerate() .map(|(late_bound_idx, param)| { let pair = Region::late(late_bound_idx as u32, &self.tcx.hir(), param); @@ -1057,9 +1054,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { match param.kind { GenericParamKind::Lifetime { .. } => { let (name, reg) = Region::early(&self.tcx.hir(), &mut index, ¶m); - let def_id = if let Region::EarlyBound(_, def_id, _) = reg { - def_id - } else { + let Region::EarlyBound(_, def_id, _) = reg else { bug!(); }; // We cannot predict what lifetimes are unused in opaque type. @@ -1372,9 +1367,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let (lifetimes, binders): (FxIndexMap, Vec<_>) = bound_generic_params .iter() - .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => Some(param), - _ => None, + .filter(|param| { + matches!(param.kind, GenericParamKind::Lifetime { .. }) }) .enumerate() .map(|(late_bound_idx, param)| { @@ -1471,10 +1465,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let binders_iter = trait_ref .bound_generic_params .iter() - .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => Some(param), - _ => None, - }) + .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. })) .enumerate() .map(|(late_bound_idx, param)| { let pair = Region::late( @@ -1933,20 +1924,18 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { break; } } - hir::TyKind::Path(ref qpath) => { - if let QPath::Resolved(_, path) = qpath { - let last_segment = &path.segments[path.segments.len() - 1]; - let generics = last_segment.args(); - for arg in generics.args.iter() { - if let GenericArg::Lifetime(lt) = arg { - if lt.name.ident() == name { - elide_use = Some(lt.span); - break; - } + hir::TyKind::Path(QPath::Resolved(_, path)) => { + let last_segment = &path.segments[path.segments.len() - 1]; + let generics = last_segment.args(); + for arg in generics.args.iter() { + if let GenericArg::Lifetime(lt) = arg { + if lt.name.ident() == name { + elide_use = Some(lt.span); + break; } } - break; } + break; } _ => {} } @@ -2239,19 +2228,14 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { 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, + .filter(|param| { + matches!(param.kind, GenericParamKind::Lifetime { .. }) + && self.map.late_bound.contains(¶m.hir_id) }) .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 + late_region_as_bound_region(self.tcx, &pair.1) }) .collect(); self.map.late_bound_vars.insert(hir_id, binders); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 9652c48368..d17e8875a1 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -13,8 +13,9 @@ #![feature(drain_filter)] #![feature(bool_to_option)] #![feature(crate_visibility_modifier)] -#![feature(format_args_capture)] +#![cfg_attr(bootstrap, feature(format_args_capture))] #![feature(iter_zip)] +#![feature(let_else)] #![feature(never_type)] #![feature(nll)] #![recursion_limit = "256"] @@ -54,13 +55,14 @@ use rustc_middle::hir::exports::ExportMap; use rustc_middle::span_bug; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, DefIdTree, MainDefinition, ResolverOutputs}; +use rustc_query_system::ich::StableHashingContext; use rustc_session::cstore::{CrateStore, MetadataLoaderDyn}; use rustc_session::lint; use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer}; use rustc_session::Session; use rustc_span::edition::Edition; use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext, Transparency}; -use rustc_span::source_map::{CachingSourceMapView, Spanned}; +use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -725,23 +727,21 @@ enum AmbiguityKind { impl AmbiguityKind { fn descr(self) -> &'static str { match self { - AmbiguityKind::Import => "name vs any other name during import resolution", - AmbiguityKind::BuiltinAttr => "built-in attribute vs any other name", - AmbiguityKind::DeriveHelper => "derive helper attribute vs any other name", + AmbiguityKind::Import => "multiple potential import sources", + AmbiguityKind::BuiltinAttr => "a name conflict with a builtin attribute", + AmbiguityKind::DeriveHelper => "a name conflict with a derive helper attribute", AmbiguityKind::MacroRulesVsModularized => { - "`macro_rules` vs non-`macro_rules` from other module" + "a conflict between a `macro_rules` name and a non-`macro_rules` name from another module" } AmbiguityKind::GlobVsOuter => { - "glob import vs any other name from outer scope during import/macro resolution" + "a conflict between a name from a glob import and an outer scope during import or macro resolution" } - AmbiguityKind::GlobVsGlob => "glob import vs glob import in the same module", + AmbiguityKind::GlobVsGlob => "multiple glob imports of a name in the same module", AmbiguityKind::GlobVsExpanded => { - "glob import vs macro-expanded name in the same \ - module during import/macro resolution" + "a conflict between a name from a glob import and a macro-expanded name in the same module during import or macro resolution" } AmbiguityKind::MoreExpandedVsOuter => { - "macro-expanded name vs less macro-expanded name \ - from outer scope during import/macro resolution" + "a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution" } } } @@ -930,7 +930,7 @@ pub struct Resolver<'a> { /// `CrateNum` resolutions of `extern crate` items. extern_crate_map: FxHashMap, export_map: ExportMap, - trait_map: Option>>, + trait_map: NodeMap>, /// A map from nodes to anonymous modules. /// Anonymous modules are pseudo-modules that are implicitly created around items @@ -988,7 +988,7 @@ pub struct Resolver<'a> { non_macro_attr: Lrc, local_macro_def_scopes: FxHashMap>, ast_transform_scopes: FxHashMap>, - unused_macros: FxHashMap, + unused_macros: FxHashMap, proc_macro_stubs: FxHashSet, /// Traces collected during macro resolution and validated when it's complete. single_segment_macro_resolutions: @@ -1177,6 +1177,10 @@ impl ResolverAstLowering for Resolver<'_> { &mut self.definitions } + fn create_stable_hashing_context(&self) -> StableHashingContext<'_> { + StableHashingContext::new(self.session, &self.definitions, self.crate_loader.cstore()) + } + fn lint_buffer(&mut self) -> &mut LintBuffer { &mut self.lint_buffer } @@ -1185,8 +1189,8 @@ impl ResolverAstLowering for Resolver<'_> { self.next_node_id() } - fn take_trait_map(&mut self) -> NodeMap> { - std::mem::replace(&mut self.trait_map, None).unwrap() + fn take_trait_map(&mut self, node: NodeId) -> Option> { + self.trait_map.remove(&node) } fn opt_local_def_id(&self, node: NodeId) -> Option { @@ -1245,37 +1249,6 @@ impl ResolverAstLowering for Resolver<'_> { } } -struct ExpandHasher<'a, 'b> { - source_map: CachingSourceMapView<'a>, - resolver: &'a Resolver<'b>, -} - -impl<'a, 'b> rustc_span::HashStableContext for ExpandHasher<'a, 'b> { - #[inline] - fn hash_spans(&self) -> bool { - true - } - - #[inline] - fn def_span(&self, id: LocalDefId) -> Span { - self.resolver.def_span(id) - } - - #[inline] - fn def_path_hash(&self, def_id: DefId) -> DefPathHash { - self.resolver.def_path_hash(def_id) - } - - #[inline] - fn span_data_to_lines_and_cols( - &mut self, - span: &rustc_span::SpanData, - ) -> Option<(Lrc, usize, rustc_span::BytePos, usize, rustc_span::BytePos)> - { - self.source_map.span_data_to_lines_and_cols(span) - } -} - impl<'a> Resolver<'a> { pub fn new( session: &'a Session, @@ -1363,7 +1336,7 @@ impl<'a> Resolver<'a> { label_res_map: Default::default(), extern_crate_map: Default::default(), export_map: FxHashMap::default(), - trait_map: Some(NodeMap::default()), + trait_map: NodeMap::default(), underscore_disambiguator: 0, empty_module, module_map, @@ -1456,13 +1429,6 @@ impl<'a> Resolver<'a> { self.arenas.new_module(parent, kind, expn_id, span, no_implicit_prelude, module_map) } - fn create_stable_hashing_context(&self) -> ExpandHasher<'_, 'a> { - ExpandHasher { - source_map: CachingSourceMapView::new(self.session.source_map()), - resolver: self, - } - } - pub fn next_node_id(&mut self) -> NodeId { let next = self .next_node_id @@ -2557,19 +2523,29 @@ impl<'a> Resolver<'a> { } else { ( format!("use of undeclared crate or module `{}`", ident), - self.find_similarly_named_module_or_crate( - ident.name, - &parent_scope.module, - ) - .map(|sugg| { - ( - vec![(ident.span, sugg.to_string())], + if ident.name == sym::alloc { + Some(( + vec![], String::from( - "there is a crate or module with a similar name", + "add `extern crate alloc` to use the `alloc` crate", ), Applicability::MaybeIncorrect, + )) + } else { + self.find_similarly_named_module_or_crate( + ident.name, + &parent_scope.module, ) - }), + .map(|sugg| { + ( + vec![(ident.span, sugg.to_string())], + String::from( + "there is a crate or module with a similar name", + ), + Applicability::MaybeIncorrect, + ) + }) + }, ) } } else { diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 4f6e23d8f8..28dbce0471 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -315,8 +315,13 @@ impl<'a> ResolverExpand for Resolver<'a> { } fn check_unused_macros(&mut self) { - for (_, &(node_id, span)) in self.unused_macros.iter() { - self.lint_buffer.buffer_lint(UNUSED_MACROS, node_id, span, "unused macro definition"); + for (_, &(node_id, ident)) in self.unused_macros.iter() { + self.lint_buffer.buffer_lint( + UNUSED_MACROS, + node_id, + ident.span, + &format!("unused macro definition: `{}`", ident.as_str()), + ); } } @@ -1128,6 +1133,7 @@ impl<'a> Resolver<'a> { feature, reason, issue, + None, is_soft, span, soft_handler, diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs index f4567b3348..f1a5282b08 100644 --- a/compiler/rustc_save_analysis/src/dump_visitor.rs +++ b/compiler/rustc_save_analysis/src/dump_visitor.rs @@ -236,7 +236,7 @@ impl<'tcx> DumpVisitor<'tcx> { id, span, name: ident.to_string(), - qualname: format!("{}::{}", qualname, ident.to_string()), + qualname: format!("{}::{}", qualname, ident), value: typ, parent: None, children: vec![], @@ -889,7 +889,7 @@ impl<'tcx> DumpVisitor<'tcx> { // Rust uses the id of the pattern for var lookups, so we'll use it too. if !self.span.filter_generated(ident.span) { - let qualname = format!("{}${}", ident.to_string(), hir_id); + let qualname = format!("{}${}", ident, hir_id); let id = id_from_hir_id(hir_id, &self.save_ctxt); let span = self.span_from_span(ident.span); diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index 543cd0247a..c7f8fe3a88 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -739,6 +739,7 @@ impl<'tcx> SaveContext<'tcx> { | HirDefKind::ForeignMod | HirDefKind::LifetimeParam | HirDefKind::AnonConst + | HirDefKind::InlineConst | HirDefKind::Use | HirDefKind::Field | HirDefKind::GlobalAsm diff --git a/compiler/rustc_serialize/src/json.rs b/compiler/rustc_serialize/src/json.rs index e5369b4bbf..df78e1bcbf 100644 --- a/compiler/rustc_serialize/src/json.rs +++ b/compiler/rustc_serialize/src/json.rs @@ -589,6 +589,13 @@ impl<'a> crate::Encoder for Encoder<'a> { } } + fn emit_fieldless_enum_variant( + &mut self, + name: &str, + ) -> Result<(), Self::Error> { + escape_str(self.writer, name) + } + fn emit_enum_variant_arg(&mut self, first: bool, f: F) -> EncodeResult where F: FnOnce(&mut Encoder<'a>) -> EncodeResult, @@ -885,6 +892,13 @@ impl<'a> crate::Encoder for PrettyEncoder<'a> { } } + fn emit_fieldless_enum_variant( + &mut self, + name: &str, + ) -> Result<(), Self::Error> { + escape_str(self.writer, name) + } + fn emit_enum_variant_arg(&mut self, first: bool, f: F) -> EncodeResult where F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs index 6671c7c0fa..96a2231b59 100644 --- a/compiler/rustc_serialize/src/serialize.rs +++ b/compiler/rustc_serialize/src/serialize.rs @@ -58,6 +58,20 @@ pub trait Encoder { f(self) } + // We put the field index in a const generic to allow the emit_usize to be + // compiled into a more efficient form. In practice, the variant index is + // known at compile-time, and that knowledge allows much more efficient + // codegen than we'd otherwise get. LLVM isn't always able to make the + // optimization that would otherwise be necessary here, likely due to the + // multiple levels of inlining and const-prop that are needed. + #[inline] + fn emit_fieldless_enum_variant( + &mut self, + _v_name: &str, + ) -> Result<(), Self::Error> { + self.emit_usize(ID) + } + #[inline] fn emit_enum_variant_arg(&mut self, _first: bool, f: F) -> Result<(), Self::Error> where @@ -500,8 +514,8 @@ impl Decodable for [u8; N] { d.read_seq(|d, len| { assert!(len == N); let mut v = [0u8; N]; - for x in &mut v { - *x = d.read_seq_elt(|d| Decodable::decode(d))?; + for i in 0..len { + v[i] = d.read_seq_elt(|d| Decodable::decode(d))?; } Ok(v) }) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index ac4bce7350..ab3c122053 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -37,7 +37,7 @@ use std::iter::{self, FromIterator}; use std::path::{Path, PathBuf}; use std::str::{self, FromStr}; -/// The different settings that the `-Z strip` flag can have. +/// The different settings that the `-C strip` flag can have. #[derive(Clone, Copy, PartialEq, Hash, Debug)] pub enum Strip { /// Do not strip at all. @@ -165,6 +165,18 @@ pub enum LinkerPluginLto { Disabled, } +/// Used with `-Z assert-incr-state`. +#[derive(Clone, Copy, PartialEq, Hash, Debug)] +pub enum IncrementalStateAssertion { + /// Found and loaded an existing session directory. + /// + /// Note that this says nothing about whether any particular query + /// will be found to be red or green. + Loaded, + /// Did not load an existing session directory. + NotLoaded, +} + impl LinkerPluginLto { pub fn enabled(&self) -> bool { match *self { @@ -174,6 +186,20 @@ impl LinkerPluginLto { } } +/// The different settings that can be enabled via the `-Z location-detail` flag. +#[derive(Clone, PartialEq, Hash, Debug)] +pub struct LocationDetail { + pub file: bool, + pub line: bool, + pub column: bool, +} + +impl LocationDetail { + pub fn all() -> Self { + Self { file: true, line: true, column: true } + } +} + #[derive(Clone, PartialEq, Hash, Debug)] pub enum SwitchWithOptPath { Enabled(Option), @@ -309,9 +335,10 @@ impl Default for ErrorOutputType { } /// Parameter to control path trimming. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] pub enum TrimmedDefPaths { /// `try_print_trimmed_def_path` never prints a trimmed path and never calls the expensive query + #[default] Never, /// `try_print_trimmed_def_path` calls the expensive query, the query doesn't call `delay_good_path_bug` Always, @@ -319,12 +346,6 @@ pub enum TrimmedDefPaths { GoodPath, } -impl Default for TrimmedDefPaths { - fn default() -> Self { - Self::Never - } -} - /// Use tree-based collections to cheaply get a deterministic `Hash` implementation. /// *Do not* switch `BTreeMap` out for an unsorted container type! That would break /// dependency tracking for command-line arguments. Also only hash keys, since tracking @@ -512,6 +533,7 @@ pub enum PrintRequest { TlsModels, TargetSpec, NativeStaticLibs, + StackProtectorStrategies, } #[derive(Copy, Clone)] @@ -564,6 +586,7 @@ pub struct OutputFilenames { pub out_directory: PathBuf, filestem: String, pub single_output_file: Option, + pub temps_directory: Option, pub outputs: OutputTypes, } @@ -578,12 +601,14 @@ impl OutputFilenames { out_directory: PathBuf, out_filestem: String, single_output_file: Option, + temps_directory: Option, extra: String, outputs: OutputTypes, ) -> Self { OutputFilenames { out_directory, single_output_file, + temps_directory, outputs, filestem: format!("{}{}", out_filestem, extra), } @@ -594,7 +619,14 @@ impl OutputFilenames { .get(&flavor) .and_then(|p| p.to_owned()) .or_else(|| self.single_output_file.clone()) - .unwrap_or_else(|| self.temp_path(flavor, None)) + .unwrap_or_else(|| self.output_path(flavor)) + } + + /// Gets the output path where a compilation artifact of the given type + /// should be placed on disk. + pub fn output_path(&self, flavor: OutputType) -> PathBuf { + let extension = flavor.extension(); + self.with_directory_and_extension(&self.out_directory, &extension) } /// Gets the path where a compilation artifact of the given type for the @@ -629,11 +661,17 @@ impl OutputFilenames { extension.push_str(ext); } - self.with_extension(&extension) + let temps_directory = self.temps_directory.as_ref().unwrap_or(&self.out_directory); + + self.with_directory_and_extension(&temps_directory, &extension) } pub fn with_extension(&self, extension: &str) -> PathBuf { - let mut path = self.out_directory.join(&self.filestem); + self.with_directory_and_extension(&self.out_directory, extension) + } + + fn with_directory_and_extension(&self, directory: &PathBuf, extension: &str) -> PathBuf { + let mut path = directory.join(&self.filestem); path.set_extension(extension); path } @@ -674,6 +712,7 @@ pub fn host_triple() -> &'static str { impl Default for Options { fn default() -> Options { Options { + assert_incr_state: None, crate_types: Vec::new(), optimize: OptLevel::No, debuginfo: DebugInfo::None, @@ -900,7 +939,7 @@ pub fn build_configuration(sess: &Session, mut user_cfg: CrateConfig) -> CrateCo pub(super) fn build_target_config( opts: &Options, target_override: Option, - sysroot: &PathBuf, + sysroot: &Path, ) -> Target { let target_result = target_override.map_or_else( || Target::search(&opts.target_triple, sysroot), @@ -1067,8 +1106,8 @@ pub fn rustc_short_optgroups() -> Vec { "print", "Compiler information to print on stdout", "[crate-name|file-names|sysroot|target-libdir|cfg|target-list|\ - target-cpus|target-features|relocation-models|\ - code-models|tls-models|target-spec-json|native-static-libs]", + target-cpus|target-features|relocation-models|code-models|\ + tls-models|target-spec-json|native-static-libs|stack-protector-strategies]", ), opt::flagmulti_s("g", "", "Equivalent to -C debuginfo=2"), opt::flagmulti_s("O", "", "Equivalent to -C opt-level=2"), @@ -1484,6 +1523,7 @@ fn collect_print_requests( "code-models" => PrintRequest::CodeModels, "tls-models" => PrintRequest::TlsModels, "native-static-libs" => PrintRequest::NativeStaticLibs, + "stack-protector-strategies" => PrintRequest::StackProtectorStrategies, "target-spec-json" => { if dopts.unstable_options { PrintRequest::TargetSpec @@ -1596,6 +1636,21 @@ fn select_debuginfo( } } +crate fn parse_assert_incr_state( + opt_assertion: &Option, + error_format: ErrorOutputType, +) -> Option { + match opt_assertion { + Some(s) if s.as_str() == "loaded" => Some(IncrementalStateAssertion::Loaded), + Some(s) if s.as_str() == "not-loaded" => Some(IncrementalStateAssertion::NotLoaded), + Some(s) => early_error( + error_format, + &format!("unexpected incremental state assertion value: {}", s), + ), + None => None, + } +} + fn parse_native_lib_kind( matches: &getopts::Matches, kind: &str, @@ -1985,6 +2040,9 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { let incremental = cg.incremental.as_ref().map(PathBuf::from); + let assert_incr_state = + parse_assert_incr_state(&debugging_opts.assert_incr_state, error_format); + if debugging_opts.profile && incremental.is_some() { early_error( error_format, @@ -2149,6 +2207,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { }; Options { + assert_incr_state, crate_types, optimize: opt_level, debuginfo, @@ -2422,7 +2481,7 @@ crate mod dep_tracking { use super::LdImpl; use super::{ CFGuard, CrateType, DebugInfo, ErrorOutputType, InstrumentCoverage, LinkerPluginLto, - LtoCli, OptLevel, OutputType, OutputTypes, Passes, SourceFileHashAlgorithm, + LocationDetail, LtoCli, OptLevel, OutputType, OutputTypes, Passes, SourceFileHashAlgorithm, SwitchWithOptPath, SymbolManglingVersion, TrimmedDefPaths, }; use crate::lint; @@ -2432,7 +2491,9 @@ crate mod dep_tracking { use rustc_span::edition::Edition; use rustc_span::RealFileName; use rustc_target::spec::{CodeModel, MergeFunctions, PanicStrategy, RelocModel}; - use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, TargetTriple, TlsModel}; + use rustc_target::spec::{ + RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TargetTriple, TlsModel, + }; use std::collections::hash_map::DefaultHasher; use std::collections::BTreeMap; use std::hash::Hash; @@ -2506,6 +2567,7 @@ crate mod dep_tracking { Edition, LinkerPluginLto, SplitDebuginfo, + StackProtector, SwitchWithOptPath, SymbolManglingVersion, SourceFileHashAlgorithm, @@ -2513,6 +2575,7 @@ crate mod dep_tracking { Option, OutputType, RealFileName, + LocationDetail, ); impl DepTrackingHash for (T1, T2) diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index 6c86f86ecd..399b616915 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -1,4 +1,5 @@ #![feature(crate_visibility_modifier)] +#![feature(derive_default_enum)] #![feature(min_specialization)] #![feature(once_cell)] #![recursion_limit = "256"] diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index b3d36b396c..4165e750df 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -4,9 +4,10 @@ use crate::early_error; use crate::lint; use crate::search_paths::SearchPath; use crate::utils::NativeLib; - use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy, SanitizerSet}; -use rustc_target::spec::{RelocModel, RelroLevel, SplitDebuginfo, TargetTriple, TlsModel}; +use rustc_target::spec::{ + RelocModel, RelroLevel, SplitDebuginfo, StackProtector, TargetTriple, TlsModel, +}; use rustc_feature::UnstableFeatures; use rustc_span::edition::Edition; @@ -150,6 +151,7 @@ top_level_options!( /// If `Some`, enable incremental compilation, using the given /// directory to store intermediate results. incremental: Option [UNTRACKED], + assert_incr_state: Option [UNTRACKED], debugging_opts: DebuggingOptions [SUBSTRUCT], prints: Vec [UNTRACKED], @@ -219,7 +221,7 @@ top_level_options!( /// generated code to parse an option into its respective field in the struct. There are a few /// hand-written parsers for parsing specific types of values in this module. macro_rules! options { - ($struct_name:ident, $stat:ident, $prefix:expr, $outputname:expr, + ($struct_name:ident, $stat:ident, $optmod:ident, $prefix:expr, $outputname:expr, $($( #[$attr:meta] )* $opt:ident : $t:ty = ( $init:expr, $parse:ident, @@ -264,13 +266,15 @@ macro_rules! options { } pub const $stat: OptionDescrs<$struct_name> = - &[ $( (stringify!($opt), $opt, desc::$parse, $desc) ),* ]; + &[ $( (stringify!($opt), $optmod::$opt, desc::$parse, $desc) ),* ]; + mod $optmod { $( - fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool { - parse::$parse(&mut redirect_field!(cg.$opt), v) + pub(super) fn $opt(cg: &mut super::$struct_name, v: Option<&str>) -> bool { + super::parse::$parse(&mut redirect_field!(cg.$opt), v) } )* + } ) } @@ -351,8 +355,7 @@ mod desc { pub const parse_panic_strategy: &str = "either `unwind` or `abort`"; pub const parse_opt_panic_strategy: &str = parse_panic_strategy; pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`"; - pub const parse_sanitizers: &str = - "comma separated list of sanitizers: `address`, `hwaddress`, `leak`, `memory` or `thread`"; + pub const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `hwaddress`, `leak`, `memory` or `thread`"; pub const parse_sanitizer_memory_track_origins: &str = "0, 1, or 2"; pub const parse_cfguard: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`"; @@ -368,6 +371,8 @@ mod desc { "either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted"; pub const parse_linker_plugin_lto: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or the path to the linker plugin"; + pub const parse_location_detail: &str = + "comma seperated list of location details to track: `file`, `line`, or `column`"; pub const parse_switch_with_opt_path: &str = "an optional path to the profiling data output directory"; pub const parse_merge_functions: &str = "one of: `disabled`, `trampolines`, or `aliases`"; @@ -382,6 +387,8 @@ mod desc { pub const parse_split_debuginfo: &str = "one of supported split-debuginfo modes (`off`, `packed`, or `unpacked`)"; pub const parse_gcc_ld: &str = "one of: no value, `lld`"; + pub const parse_stack_protector: &str = + "one of (`none` (default), `basic`, `strong`, or `all`)"; } mod parse { @@ -484,6 +491,25 @@ mod parse { } } + crate fn parse_location_detail(ld: &mut LocationDetail, v: Option<&str>) -> bool { + if let Some(v) = v { + ld.line = false; + ld.file = false; + ld.column = false; + for s in v.split(',') { + match s { + "file" => ld.file = true, + "line" => ld.line = true, + "column" => ld.column = true, + _ => return false, + } + } + true + } else { + false + } + } + crate fn parse_opt_comma_list(slot: &mut Option>, v: Option<&str>) -> bool { match v { Some(s) => { @@ -584,6 +610,7 @@ mod parse { for s in v.split(',') { *slot |= match s { "address" => SanitizerSet::ADDRESS, + "cfi" => SanitizerSet::CFI, "leak" => SanitizerSet::LEAK, "memory" => SanitizerSet::MEMORY, "thread" => SanitizerSet::THREAD, @@ -860,7 +887,7 @@ mod parse { match v { Some(s) => { if !slot.is_empty() { - slot.push_str(","); + slot.push(','); } slot.push_str(s); true @@ -894,10 +921,18 @@ mod parse { } true } + + crate fn parse_stack_protector(slot: &mut StackProtector, v: Option<&str>) -> bool { + match v.and_then(|s| StackProtector::from_str(s).ok()) { + Some(ssp) => *slot = ssp, + _ => return false, + } + true + } } options! { - CodegenOptions, CG_OPTIONS, "C", "codegen", + CodegenOptions, CG_OPTIONS, cgopts, "C", "codegen", // This list is in alphabetical order. // @@ -992,6 +1027,8 @@ options! { "use soft float ABI (*eabihf targets only) (default: no)"), split_debuginfo: Option = (None, parse_split_debuginfo, [TRACKED], "how to handle split-debuginfo, a platform-specific option"), + strip: Strip = (Strip::None, parse_strip, [UNTRACKED], + "tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"), target_cpu: Option = (None, parse_opt_string, [TRACKED], "select target processor (`rustc --print target-cpus` for details)"), target_feature: String = (String::new(), parse_target_feature, [TRACKED], @@ -1006,7 +1043,7 @@ options! { } options! { - DebuggingOptions, DB_OPTIONS, "Z", "debugging", + DebuggingOptions, DB_OPTIONS, dbopts, "Z", "debugging", // This list is in alphabetical order. // @@ -1021,6 +1058,9 @@ options! { "make cfg(version) treat the current version as incomplete (default: no)"), asm_comments: bool = (false, parse_bool, [TRACKED], "generate comments into the assembly (may change behavior) (default: no)"), + assert_incr_state: Option = (None, parse_opt_string, [UNTRACKED], + "assert that the incremental cache is in given state: \ + either `loaded` or `not-loaded`."), ast_json: bool = (false, parse_bool, [UNTRACKED], "print the AST as JSON and halt (default: no)"), ast_json_noexpand: bool = (false, parse_bool, [UNTRACKED], @@ -1091,8 +1131,6 @@ options! { fewer_names: Option = (None, parse_opt_bool, [TRACKED], "reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR) \ (default: no)"), - force_overflow_checks: Option = (None, parse_opt_bool, [TRACKED], - "force overflow checks on or off"), force_unstable_if_unmarked: bool = (false, parse_bool, [TRACKED], "force all crates to be `rustc_private` unstable (default: no)"), fuel: Option<(String, u64)> = (None, parse_optimization_fuel, [TRACKED], @@ -1152,6 +1190,9 @@ options! { "a list LLVM plugins to enable (space separated)"), llvm_time_trace: bool = (false, parse_bool, [UNTRACKED], "generate JSON tracing data file from LLVM data (default: no)"), + location_detail: LocationDetail = (LocationDetail::all(), parse_location_detail, [TRACKED], + "comma seperated list of location details to be tracked when using caller_location \ + valid options are `file`, `line`, and `column` (default: all)"), ls: bool = (false, parse_bool, [UNTRACKED], "list the symbols defined by a library crate (default: no)"), macro_backtrace: bool = (false, parse_bool, [UNTRACKED], @@ -1169,7 +1210,7 @@ options! { move_size_limit: Option = (None, parse_opt_number, [TRACKED], "the size at which the `large_assignments` lint starts to be emitted"), mutable_noalias: Option = (None, parse_opt_bool, [TRACKED], - "emit noalias metadata for mutable references (default: yes for LLVM >= 12, otherwise no)"), + "emit noalias metadata for mutable references (default: yes)"), new_llvm_pass_manager: Option = (None, parse_opt_bool, [TRACKED], "use new LLVM pass manager (default: no)"), nll_facts: bool = (false, parse_bool, [UNTRACKED], @@ -1190,6 +1231,8 @@ options! { "compile without linking"), no_parallel_llvm: bool = (false, parse_no_flag, [UNTRACKED], "run LLVM in non-parallel mode (while keeping codegen-units and ThinLTO)"), + no_unique_section_names: bool = (false, parse_bool, [TRACKED], + "do not use unique names for text and data sections when -Z function-sections is used"), no_profiler_runtime: bool = (false, parse_no_flag, [TRACKED], "prevent automatic injection of the profiler_builtins crate"), normalize_docs: bool = (false, parse_bool, [TRACKED], @@ -1207,6 +1250,8 @@ options! { and set the maximum total size of a const allocation for which this is allowed (default: never)"), perf_stats: bool = (false, parse_bool, [UNTRACKED], "print some performance-related statistics (default: no)"), + pick_stable_methods_before_any_unstable: bool = (true, parse_bool, [TRACKED], + "try to pick stable methods first before picking any unstable methods (default: yes)"), plt: Option = (None, parse_opt_bool, [TRACKED], "whether to use the PLT when calling into shared libraries; only has effect for PIC code on systems with ELF binaries @@ -1283,7 +1328,7 @@ options! { "specify the events recorded by the self profiler; for example: `-Z self-profile-events=default,query-keys` all options: none, all, default, generic-activity, query-provider, query-cache-hit - query-blocked, incr-cache-load, incr-result-hashing, query-keys, function-args, args, llvm"), + query-blocked, incr-cache-load, incr-result-hashing, query-keys, function-args, args, llvm, artifact-sizes"), share_generics: Option = (None, parse_opt_bool, [TRACKED], "make the current crate share its generic instantiations"), show_span: Option = (None, parse_opt_string, [TRACKED], @@ -1295,6 +1340,8 @@ options! { "exclude spans when debug-printing compiler state (default: no)"), src_hash_algorithm: Option = (None, parse_src_file_hash, [TRACKED], "hash algorithm of source files in debug info (`md5`, `sha1`, or `sha256`)"), + stack_protector: StackProtector = (StackProtector::None, parse_stack_protector, [TRACKED], + "control stack smash protection strategy (`rustc --print stack-protector-strategies` for details)"), strip: Strip = (Strip::None, parse_strip, [UNTRACKED], "tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"), split_dwarf_inlining: bool = (true, parse_bool, [UNTRACKED], @@ -1305,6 +1352,8 @@ 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)"), + temps_dir: Option = (None, parse_opt_string, [UNTRACKED], + "the directory the intermediate files are written to"), terminal_width: Option = (None, parse_opt_number, [UNTRACKED], "set the current terminal width"), tune_cpu: Option = (None, parse_opt_string, [TRACKED], diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index a007b53030..d5b520325e 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -119,8 +119,13 @@ pub struct ParseSess { pub config: CrateConfig, pub edition: Edition, pub missing_fragment_specifiers: Lock>, - /// Places where raw identifiers were used. This is used for feature-gating raw identifiers. + /// Places where raw identifiers were used. This is used to avoid complaining about idents + /// clashing with keywords in new editions. pub raw_identifier_spans: Lock>, + /// Places where identifiers that contain invalid Unicode codepoints but that look like they + /// should be. Useful to avoid bad tokenization when encountering emoji. We group them to + /// provide a single error per unique incorrect identifier. + pub bad_unicode_identifiers: Lock>>, source_map: Lrc, pub buffered_lints: Lock>, /// Contains the spans of block expressions that could have been incomplete based on the @@ -160,6 +165,7 @@ impl ParseSess { edition: ExpnId::root().expn_data().edition, missing_fragment_specifiers: Default::default(), raw_identifier_spans: Lock::new(Vec::new()), + bad_unicode_identifiers: Lock::new(Default::default()), source_map, buffered_lints: Lock::new(vec![]), ambiguous_block_expr_parse: Lock::new(FxHashMap::default()), @@ -174,9 +180,14 @@ impl ParseSess { } } - pub fn with_silent_emitter() -> Self { + pub fn with_silent_emitter(fatal_note: Option) -> Self { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - let handler = Handler::with_emitter(false, None, Box::new(SilentEmitter)); + let fatal_handler = Handler::with_tty_emitter(ColorConfig::Auto, false, None, None); + let handler = Handler::with_emitter( + false, + None, + Box::new(SilentEmitter { fatal_handler, fatal_note }), + ); ParseSess::with_span_handler(handler, sm) } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index b6ba6cc1dd..54109559a3 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -27,7 +27,9 @@ 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::{SanitizerSet, SplitDebuginfo, Target, TargetTriple, TlsModel}; +use rustc_target::spec::{ + SanitizerSet, SplitDebuginfo, StackProtector, Target, TargetTriple, TlsModel, +}; use std::cell::{self, RefCell}; use std::env; @@ -411,7 +413,7 @@ impl Session { self.diagnostic().abort_if_errors(); } pub fn compile_status(&self) -> Result<(), ErrorReported> { - if self.has_errors() { + if self.diagnostic().has_errors_or_lint_errors() { self.diagnostic().emit_stashed_diagnostics(); Err(ErrorReported) } else { @@ -672,12 +674,11 @@ impl Session { pub fn is_nightly_build(&self) -> bool { self.opts.unstable_features.is_nightly_build() } + pub fn is_sanitizer_cfi_enabled(&self) -> bool { + self.opts.debugging_opts.sanitizer.contains(SanitizerSet::CFI) + } pub fn overflow_checks(&self) -> bool { - self.opts - .cg - .overflow_checks - .or(self.opts.debugging_opts.force_overflow_checks) - .unwrap_or(self.opts.debug_assertions) + self.opts.cg.overflow_checks.unwrap_or(self.opts.debug_assertions) } /// Check whether this compile session and crate type use static crt. @@ -729,6 +730,14 @@ impl Session { self.opts.cg.split_debuginfo.unwrap_or(self.target.split_debuginfo) } + pub fn stack_protector(&self) -> StackProtector { + if self.target.options.supports_stack_protector { + self.opts.debugging_opts.stack_protector + } else { + StackProtector::None + } + } + pub fn target_can_use_split_dwarf(&self) -> bool { !self.target.is_like_windows && !self.target.is_like_osx } @@ -1398,6 +1407,25 @@ fn validate_commandline_args_with_session_available(sess: &Session) { disable it using `-C target-feature=-crt-static`", ); } + + // LLVM CFI requires LTO. + if sess.is_sanitizer_cfi_enabled() { + if sess.opts.cg.lto == config::LtoCli::Unspecified + || sess.opts.cg.lto == config::LtoCli::No + || sess.opts.cg.lto == config::LtoCli::Thin + { + sess.err("`-Zsanitizer=cfi` requires `-Clto`"); + } + } + + if sess.opts.debugging_opts.stack_protector != StackProtector::None { + if !sess.target.options.supports_stack_protector { + sess.warn(&format!( + "`-Z stack-protector={}` is not supported for target {} and will be ignored", + sess.opts.debugging_opts.stack_protector, sess.opts.target_triple + )) + } + } } /// Holds data on the current incremental compilation session, if there is one. diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index aa15febe88..d590776676 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -709,7 +709,7 @@ impl SyntaxContext { /// pub fn f() {} // `f`'s `SyntaxContext` has a single `ExpnId` from `m`. /// pub fn $i() {} // `$i`'s `SyntaxContext` is empty. /// } - /// n(f); + /// n!(f); /// macro n($j:ident) { /// use foo::*; /// f(); // `f`'s `SyntaxContext` has a mark from `m` and a mark from `n` @@ -1099,18 +1099,11 @@ pub enum DesugaringKind { OpaqueTy, Async, Await, - ForLoop(ForLoopLoc), + ForLoop, LetElse, WhileLoop, } -/// A location in the desugaring of a `for` loop -#[derive(Clone, Copy, PartialEq, Debug, Encodable, Decodable, HashStable_Generic)] -pub enum ForLoopLoc { - Head, - IntoIter, -} - impl DesugaringKind { /// The description wording should combine well with "desugaring of {}". pub fn descr(self) -> &'static str { @@ -1121,7 +1114,7 @@ impl DesugaringKind { DesugaringKind::QuestionMark => "operator `?`", DesugaringKind::TryBlock => "`try` block", DesugaringKind::OpaqueTy => "`impl Trait`", - DesugaringKind::ForLoop(_) => "`for` loop", + DesugaringKind::ForLoop => "`for` loop", DesugaringKind::LetElse => "`let...else`", DesugaringKind::WhileLoop => "`while` loop", } diff --git a/compiler/rustc_span/src/lev_distance.rs b/compiler/rustc_span/src/lev_distance.rs index cea7871923..c10968e06d 100644 --- a/compiler/rustc_span/src/lev_distance.rs +++ b/compiler/rustc_span/src/lev_distance.rs @@ -58,34 +58,28 @@ pub fn find_best_match_for_name( let lookup = &lookup.as_str(); let max_dist = dist.unwrap_or_else(|| cmp::max(lookup.len(), 3) / 3); - let (case_insensitive_match, levenshtein_match) = name_vec + // Priority of matches: + // 1. Exact case insensitive match + // 2. Levenshtein distance match + // 3. Sorted word match + if let Some(case_insensitive_match) = + name_vec.iter().find(|candidate| candidate.as_str().to_uppercase() == lookup.to_uppercase()) + { + return Some(*case_insensitive_match); + } + let levenshtein_match = name_vec .iter() .filter_map(|&name| { let dist = lev_distance(lookup, &name.as_str()); if dist <= max_dist { Some((name, dist)) } else { None } }) // Here we are collecting the next structure: - // (case_insensitive_match, (levenshtein_match, levenshtein_distance)) - .fold((None, None), |result, (candidate, dist)| { - ( - if candidate.as_str().to_uppercase() == lookup.to_uppercase() { - Some(candidate) - } else { - result.0 - }, - match result.1 { - None => Some((candidate, dist)), - Some((c, d)) => Some(if dist < d { (candidate, dist) } else { (c, d) }), - }, - ) + // (levenshtein_match, levenshtein_distance) + .fold(None, |result, (candidate, dist)| match result { + None => Some((candidate, dist)), + Some((c, d)) => Some(if dist < d { (candidate, dist) } else { (c, d) }), }); - // Priority of matches: - // 1. Exact case insensitive match - // 2. Levenshtein distance match - // 3. Sorted word match - if let Some(candidate) = case_insensitive_match { - Some(candidate) - } else if levenshtein_match.is_some() { + if levenshtein_match.is_some() { levenshtein_match.map(|(candidate, _)| candidate) } else { find_match_by_sorted_words(name_vec, lookup) diff --git a/compiler/rustc_span/src/lev_distance/tests.rs b/compiler/rustc_span/src/lev_distance/tests.rs index 11822e9ef9..b32f8d32c1 100644 --- a/compiler/rustc_span/src/lev_distance/tests.rs +++ b/compiler/rustc_span/src/lev_distance/tests.rs @@ -31,16 +31,12 @@ fn test_find_best_match_for_name() { assert_eq!(find_best_match_for_name(&input, Symbol::intern("1111111111"), None), None); - let input = vec![Symbol::intern("aAAA")]; + let input = vec![Symbol::intern("AAAA")]; assert_eq!( - find_best_match_for_name(&input, Symbol::intern("AAAA"), None), - Some(Symbol::intern("aAAA")) + find_best_match_for_name(&input, Symbol::intern("aaaa"), None), + Some(Symbol::intern("AAAA")) ); - let input = vec![Symbol::intern("AAAA")]; - // Returns None because `lev_distance > max_dist / 3` - assert_eq!(find_best_match_for_name(&input, Symbol::intern("aaaa"), None), None); - let input = vec![Symbol::intern("AAAA")]; assert_eq!( find_best_match_for_name(&input, Symbol::intern("aaaa"), Some(4)), diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 032ae73bbf..66c01140ab 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -41,7 +41,7 @@ pub mod edition; use edition::Edition; pub mod hygiene; use hygiene::Transparency; -pub use hygiene::{DesugaringKind, ExpnKind, ForLoopLoc, MacroKind}; +pub use hygiene::{DesugaringKind, ExpnKind, MacroKind}; pub use hygiene::{ExpnData, ExpnHash, ExpnId, LocalExpnId, SyntaxContext}; pub mod def_id; use def_id::{CrateNum, DefId, DefPathHash, LocalDefId, LOCAL_CRATE}; @@ -194,10 +194,8 @@ impl Encodable for RealFileName { encoder.emit_enum(|encoder| match *self { RealFileName::LocalPath(ref local_path) => { encoder.emit_enum_variant("LocalPath", 0, 1, |encoder| { - Ok({ - encoder - .emit_enum_variant_arg(true, |encoder| local_path.encode(encoder))?; - }) + encoder.emit_enum_variant_arg(true, |encoder| local_path.encode(encoder))?; + Ok(()) }) } @@ -206,12 +204,9 @@ impl Encodable for RealFileName { // For privacy and build reproducibility, we must not embed host-dependant path in artifacts // if they have been remapped by --remap-path-prefix assert!(local_path.is_none()); - Ok({ - encoder - .emit_enum_variant_arg(true, |encoder| local_path.encode(encoder))?; - encoder - .emit_enum_variant_arg(false, |encoder| virtual_name.encode(encoder))?; - }) + encoder.emit_enum_variant_arg(true, |encoder| local_path.encode(encoder))?; + encoder.emit_enum_variant_arg(false, |encoder| virtual_name.encode(encoder))?; + Ok(()) }), }) } @@ -1940,6 +1935,7 @@ pub struct Loc { #[derive(Debug)] pub struct SourceFileAndLine { pub sf: Lrc, + /// Index of line, starting from 0. pub line: usize, } #[derive(Debug)] diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index 74958c4984..7414d201f5 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -593,14 +593,19 @@ impl SourceMap { } pub fn span_to_margin(&self, sp: Span) -> Option { - match self.span_to_prev_source(sp) { - Err(_) => None, - Ok(source) => { - let last_line = source.rsplit_once('\n').unwrap_or(("", &source)).1; + Some(self.indentation_before(sp)?.len()) + } - Some(last_line.len() - last_line.trim_start().len()) - } - } + pub fn indentation_before(&self, sp: Span) -> Option { + self.span_to_source(sp, |src, start_index, _| { + let before = &src[..start_index]; + let last_line = before.rsplit_once('\n').map_or(before, |(_, last)| last); + Ok(last_line + .split_once(|c: char| !c.is_whitespace()) + .map_or(last_line, |(indent, _)| indent) + .to_string()) + }) + .ok() } /// Returns the source snippet as `String` before the given `Span`. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 16205ad1cf..247d69d6ee 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -269,8 +269,8 @@ symbols! { __D, __H, __S, - __next, __try_var, + _args, _d, _e, _task_context, @@ -307,6 +307,7 @@ symbols! { alloc_layout, alloc_zeroed, allocator, + allocator_api, allocator_internals, allow, allow_fail, @@ -327,6 +328,9 @@ symbols! { as_ptr, as_str, asm, + asm_const, + asm_experimental_arch, + asm_sym, assert, assert_inhabited, assert_macro, @@ -355,7 +359,6 @@ symbols! { await_macro, bang, begin_panic, - begin_panic_fmt, bench, bin, bind_by_move_pattern_guards, @@ -408,6 +411,7 @@ symbols! { cfg_target_thread_local, cfg_target_vendor, cfg_version, + cfi, char, client, clippy, @@ -675,6 +679,7 @@ symbols! { gen_future, gen_kill, generator, + generator_return, generator_state, generators, generic_arg_infer, @@ -728,6 +733,7 @@ symbols! { inlateout, inline, inline_const, + inline_const_pat, inout, instruction_set, intel, @@ -1128,7 +1134,6 @@ symbols! { rustc_partition_reused, rustc_peek, rustc_peek_definite_init, - rustc_peek_indirectly_mutable, rustc_peek_liveness, rustc_peek_maybe_init, rustc_peek_maybe_uninit, @@ -1143,14 +1148,15 @@ symbols! { rustc_specialization_trait, rustc_stable, rustc_std_internal_symbol, + rustc_strict_coherence, rustc_symbol_name, - rustc_synthetic, rustc_test_marker, rustc_then_this_would_need, rustc_trivial_field_reads, rustc_unsafe_specialization_marker, rustc_variance, rustdoc, + rustdoc_internals, rustfmt, rvalue_static_promotion, s, @@ -1340,6 +1346,7 @@ symbols! { type_alias_enum_variants, type_alias_impl_trait, type_ascription, + type_changing_struct_update, type_id, type_length_limit, type_macros, @@ -1454,7 +1461,7 @@ impl Ident { } #[inline] - pub fn invalid() -> Ident { + pub fn empty() -> Ident { Ident::with_dummy_span(kw::Empty) } diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index 220c9f7e2e..bb7b452955 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -103,8 +103,9 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::mono::{InstantiationMode, MonoItem}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::subst::SubstsRef; -use rustc_middle::ty::{self, Instance, TyCtxt}; +use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_session::config::SymbolManglingVersion; +use rustc_target::abi::call::FnAbi; use tracing::debug; @@ -150,6 +151,11 @@ fn symbol_name_provider(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> ty::Symb ty::SymbolName::new(tcx, &symbol_name) } +/// This function computes the typeid for the given function ABI. +pub fn typeid_for_fnabi(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> String { + v0::mangle_typeid_for_fnabi(tcx, fn_abi) +} + /// Computes the symbol name for the given instance. This function will call /// `compute_instantiating_crate` if it needs to factor the instantiating crate /// into the symbol name. diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 521730dfeb..0363ddb0e6 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -9,6 +9,7 @@ use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::print::{Print, Printer}; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst}; use rustc_middle::ty::{self, FloatTy, Instance, IntTy, Ty, TyCtxt, TypeFoldable, UintTy}; +use rustc_target::abi::call::FnAbi; use rustc_target::abi::Integer; use rustc_target::spec::abi::Abi; @@ -55,6 +56,41 @@ pub(super) fn mangle( std::mem::take(&mut cx.out) } +pub(super) fn mangle_typeid_for_fnabi( + _tcx: TyCtxt<'tcx>, + fn_abi: &FnAbi<'tcx, Ty<'tcx>>, +) -> String { + // LLVM uses type metadata to allow IR modules to aggregate pointers by their types.[1] This + // type metadata is used by LLVM Control Flow Integrity to test whether a given pointer is + // associated with a type identifier (i.e., test type membership). + // + // Clang uses the Itanium C++ ABI's[2] virtual tables and RTTI typeinfo structure name[3] as + // type metadata identifiers for function pointers. The typeinfo name encoding is a + // two-character code (i.e., “TS”) prefixed to the type encoding for the function. + // + // For cross-language LLVM CFI support, a compatible encoding must be used by either + // + // a. Using a superset of types that encompasses types used by Clang (i.e., Itanium C++ ABI's + // type encodings[4]), or at least types used at the FFI boundary. + // b. Reducing the types to the least common denominator between types used by Clang (or at + // least types used at the FFI boundary) and Rust compilers (if even possible). + // c. Creating a new ABI for cross-language CFI and using it for Clang and Rust compilers (and + // possibly other compilers). + // + // Option (b) may weaken the protection for Rust-compiled only code, so it should be provided + // as an alternative to a Rust-specific encoding for when mixing Rust and C and C++ -compiled + // code. Option (c) would require changes to Clang to use the new ABI. + // + // [1] https://llvm.org/docs/TypeMetadata.html + // [2] https://itanium-cxx-abi.github.io/cxx-abi/abi.html + // [3] https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling-special-vtables + // [4] https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling-type + // + // FIXME(rcvalle): See comment above. + let arg_count = fn_abi.args.len() + fn_abi.ret.is_indirect() as usize; + format!("typeid{}", arg_count) +} + struct BinderLevel { /// The range of distances from the root of what's /// being printed, to the lifetimes in a binder. diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index d9eb299e2f..4768c9e2db 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -68,8 +68,10 @@ mod attr_impl { const NonNull = 1 << 3; const ReadOnly = 1 << 4; 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. + // Due to past miscompiles in LLVM, we use a separate attribute for + // &mut arguments, so that the codegen backend can decide whether + // or not to actually emit the attribute. It can also be controlled + // with the `-Zmutable-noalias` debugging option. const NoAliasMutRef = 1 << 6; } } diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 99699c50df..bff1324652 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -189,6 +189,7 @@ pub enum InlineAsmArch { S390x, SpirV, Wasm32, + Wasm64, Bpf, } @@ -212,6 +213,7 @@ impl FromStr for InlineAsmArch { "s390x" => Ok(Self::S390x), "spirv" => Ok(Self::SpirV), "wasm32" => Ok(Self::Wasm32), + "wasm64" => Ok(Self::Wasm64), "bpf" => Ok(Self::Bpf), _ => Err(()), } @@ -318,7 +320,7 @@ impl InlineAsmReg { InlineAsmArch::SpirV => { Self::SpirV(SpirVInlineAsmReg::parse(arch, has_feature, target, &name)?) } - InlineAsmArch::Wasm32 => { + InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => { Self::Wasm(WasmInlineAsmReg::parse(arch, has_feature, target, &name)?) } InlineAsmArch::Bpf => { @@ -529,7 +531,9 @@ impl InlineAsmRegClass { } InlineAsmArch::S390x => Self::S390x(S390xInlineAsmRegClass::parse(arch, name)?), InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmRegClass::parse(arch, name)?), - InlineAsmArch::Wasm32 => Self::Wasm(WasmInlineAsmRegClass::parse(arch, name)?), + InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => { + Self::Wasm(WasmInlineAsmRegClass::parse(arch, name)?) + } InlineAsmArch::Bpf => Self::Bpf(BpfInlineAsmRegClass::parse(arch, name)?), }) } @@ -725,7 +729,7 @@ pub fn allocatable_registers( spirv::fill_reg_map(arch, has_feature, target, &mut map); map } - InlineAsmArch::Wasm32 => { + InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => { let mut map = wasm::regclass_map(); wasm::fill_reg_map(arch, has_feature, target, &mut map); map diff --git a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs index dc91f12309..f01ff02da0 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs @@ -2,11 +2,11 @@ use crate::spec::{FramePointer, LinkerFlavor, SanitizerSet, Target, TargetOption pub fn target() -> Target { let mut base = super::apple_base::opts("macos"); - base.cpu = "apple-a12".to_string(); + base.cpu = "apple-a14".to_string(); base.max_atomic_width = Some(128); // FIXME: The leak sanitizer currently fails the tests, see #88132. - base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD; + base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | 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()); @@ -14,14 +14,13 @@ pub fn target() -> Target { // Clang automatically chooses a more specific target based on // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work // correctly, we do too. - let arch = "aarch64"; - let llvm_target = super::apple_base::macos_llvm_target(&arch); + let llvm_target = super::apple_base::macos_llvm_target("arm64"); Target { llvm_target, pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".to_string(), - arch: arch.to_string(), + arch: "aarch64".to_string(), options: TargetOptions { mcount: "\u{1}mcount".to_string(), frame_pointer: FramePointer::NonLeaf, diff --git a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs index 71ee6deb07..a393858879 100644 --- a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs @@ -8,6 +8,7 @@ pub fn target() -> Target { data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), arch: "aarch64".to_string(), options: TargetOptions { + features: "+outline-atomics".to_string(), max_atomic_width: Some(128), mcount: "\u{1}_mcount".to_string(), endian: Endian::Big, diff --git a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs index e05360ea45..e75100f143 100644 --- a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs +++ b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs @@ -12,6 +12,7 @@ pub fn target() -> Target { arch: "aarch64".to_string(), options: TargetOptions { abi: "ilp32".to_string(), + features: "+outline-atomics".to_string(), mcount: "\u{1}_mcount".to_string(), endian: Endian::Big, ..base diff --git a/compiler/rustc_target/src/spec/aarch64_fuchsia.rs b/compiler/rustc_target/src/spec/aarch64_fuchsia.rs index 56d71df6bd..05e0c65dd5 100644 --- a/compiler/rustc_target/src/spec/aarch64_fuchsia.rs +++ b/compiler/rustc_target/src/spec/aarch64_fuchsia.rs @@ -8,7 +8,7 @@ pub fn target() -> Target { arch: "aarch64".to_string(), options: TargetOptions { max_atomic_width: Some(128), - supported_sanitizers: SanitizerSet::ADDRESS, + supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::CFI, ..super::fuchsia_base::opts() }, } diff --git a/compiler/rustc_target/src/spec/aarch64_linux_android.rs b/compiler/rustc_target/src/spec/aarch64_linux_android.rs index 409cab72ec..1e9abbbe1e 100644 --- a/compiler/rustc_target/src/spec/aarch64_linux_android.rs +++ b/compiler/rustc_target/src/spec/aarch64_linux_android.rs @@ -14,7 +14,7 @@ pub fn target() -> Target { // As documented in https://developer.android.com/ndk/guides/cpu-features.html // the neon (ASIMD) and FP must exist on all android aarch64 targets. features: "+neon,+fp-armv8".to_string(), - supported_sanitizers: SanitizerSet::HWADDRESS, + supported_sanitizers: SanitizerSet::CFI | SanitizerSet::HWADDRESS, ..super::android_base::opts() }, } diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs index 0caecd2987..03ee7ba487 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs @@ -9,6 +9,7 @@ pub fn target() -> Target { options: TargetOptions { max_atomic_width: Some(128), supported_sanitizers: SanitizerSet::ADDRESS + | SanitizerSet::CFI | SanitizerSet::MEMORY | SanitizerSet::THREAD, ..super::freebsd_base::opts() 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 3e92ecbae0..850381f7fb 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs @@ -7,9 +7,11 @@ pub fn target() -> Target { data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), arch: "aarch64".to_string(), options: TargetOptions { + features: "+outline-atomics".to_string(), mcount: "\u{1}_mcount".to_string(), max_atomic_width: Some(128), supported_sanitizers: SanitizerSet::ADDRESS + | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::MEMORY | SanitizerSet::THREAD diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs index 8522405f61..1c931d5a70 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs @@ -8,6 +8,7 @@ pub fn target() -> Target { arch: "aarch64".to_string(), options: TargetOptions { abi: "ilp32".to_string(), + features: "+outline-atomics".to_string(), max_atomic_width: Some(128), mcount: "\u{1}_mcount".to_string(), ..super::linux_gnu_base::opts() diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs index a21b784e11..db6aee59a5 100644 --- a/compiler/rustc_target/src/spec/apple_base.rs +++ b/compiler/rustc_target/src/spec/apple_base.rs @@ -13,8 +13,10 @@ pub fn opts(os: &str) -> TargetOptions { // warnings about the usage of ELF TLS. // // Here we detect what version is being requested, defaulting to 10.7. ELF - // TLS is flagged as enabled if it looks to be supported. - let version = macos_deployment_target(); + // TLS is flagged as enabled if it looks to be supported. The architecture + // only matters for default deployment target which is 11.0 for ARM64 and + // 10.7 for everything else. + let has_elf_tls = macos_deployment_target("x86_64") >= (10, 7); TargetOptions { os: os.to_string(), @@ -31,7 +33,7 @@ pub fn opts(os: &str) -> TargetOptions { has_rpath: true, dll_suffix: ".dylib".to_string(), archive_format: "darwin".to_string(), - has_elf_tls: version >= (10, 7), + has_elf_tls, abi_return_struct_as_int: true, emit_debug_gdb_scripts: false, eh_frame_header: false, @@ -63,12 +65,17 @@ fn deployment_target(var_name: &str) -> Option<(u32, u32)> { .and_then(|(a, b)| a.parse::().and_then(|a| b.parse::().map(|b| (a, b))).ok()) } -fn macos_deployment_target() -> (u32, u32) { - deployment_target("MACOSX_DEPLOYMENT_TARGET").unwrap_or((10, 7)) +fn macos_default_deployment_target(arch: &str) -> (u32, u32) { + if arch == "arm64" { (11, 0) } else { (10, 7) } +} + +fn macos_deployment_target(arch: &str) -> (u32, u32) { + deployment_target("MACOSX_DEPLOYMENT_TARGET") + .unwrap_or_else(|| macos_default_deployment_target(arch)) } pub fn macos_llvm_target(arch: &str) -> String { - let (major, minor) = macos_deployment_target(); + let (major, minor) = macos_deployment_target(arch); format!("{}-apple-macosx{}.{}.0", arch, major, minor) } diff --git a/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs b/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs index 01f5c197d2..afe8bbb352 100644 --- a/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs +++ b/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs @@ -1,4 +1,4 @@ -use crate::spec::{LinkArgs, LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions}; +use crate::spec::{LinkArgs, LinkerFlavor, RelocModel, Target, TargetOptions}; /// A base target for Nintendo 3DS devices using the devkitARM toolchain. /// @@ -36,7 +36,6 @@ pub fn target() -> Target { features: "+vfp2".to_string(), pre_link_args, exe_suffix: ".elf".to_string(), - panic_strategy: PanicStrategy::Abort, ..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 c55a46e69a..ce3dad2645 100644 --- a/compiler/rustc_target/src/spec/hermit_kernel_base.rs +++ b/compiler/rustc_target/src/spec/hermit_kernel_base.rs @@ -1,4 +1,4 @@ -use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, PanicStrategy, TargetOptions, TlsModel}; +use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, PanicStrategy, TargetOptions}; pub fn opts() -> TargetOptions { let mut pre_link_args = LinkArgs::new(); @@ -8,17 +8,14 @@ pub fn opts() -> TargetOptions { ); TargetOptions { - os: "hermit".to_string(), linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), disable_redzone: true, linker: Some("rust-lld".to_owned()), executables: true, - has_elf_tls: true, pre_link_args, panic_strategy: PanicStrategy::Abort, position_independent_executables: true, static_position_independent_executables: true, - tls_model: TlsModel::InitialExec, ..Default::default() } } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index ff5dfa3f74..0d49c7f6ee 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -602,6 +602,7 @@ bitflags::bitflags! { const MEMORY = 1 << 2; const THREAD = 1 << 3; const HWADDRESS = 1 << 4; + const CFI = 1 << 5; } } @@ -612,6 +613,7 @@ impl SanitizerSet { fn as_str(self) -> Option<&'static str> { Some(match self { SanitizerSet::ADDRESS => "address", + SanitizerSet::CFI => "cfi", SanitizerSet::LEAK => "leak", SanitizerSet::MEMORY => "memory", SanitizerSet::THREAD => "thread", @@ -644,6 +646,7 @@ impl IntoIterator for SanitizerSet { fn into_iter(self) -> Self::IntoIter { [ SanitizerSet::ADDRESS, + SanitizerSet::CFI, SanitizerSet::LEAK, SanitizerSet::MEMORY, SanitizerSet::THREAD, @@ -709,6 +712,59 @@ impl ToJson for FramePointer { } } +/// Controls use of stack canaries. +#[derive(Clone, Copy, Debug, PartialEq, Hash, Eq)] +pub enum StackProtector { + /// Disable stack canary generation. + None, + + /// On LLVM, mark all generated LLVM functions with the `ssp` attribute (see + /// llvm/docs/LangRef.rst). This triggers stack canary generation in + /// functions which contain an array of a byte-sized type with more than + /// eight elements. + Basic, + + /// On LLVM, mark all generated LLVM functions with the `sspstrong` + /// attribute (see llvm/docs/LangRef.rst). This triggers stack canary + /// generation in functions which either contain an array, or which take + /// the address of a local variable. + Strong, + + /// Generate stack canaries in all functions. + All, +} + +impl StackProtector { + fn as_str(&self) -> &'static str { + match self { + StackProtector::None => "none", + StackProtector::Basic => "basic", + StackProtector::Strong => "strong", + StackProtector::All => "all", + } + } +} + +impl FromStr for StackProtector { + type Err = (); + + fn from_str(s: &str) -> Result { + Ok(match s { + "none" => StackProtector::None, + "basic" => StackProtector::Basic, + "strong" => StackProtector::Strong, + "all" => StackProtector::All, + _ => return Err(()), + }) + } +} + +impl fmt::Display for StackProtector { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(self.as_str()) + } +} + macro_rules! supported_targets { ( $(($( $triple:literal, )+ $module:ident ),)+ ) => { $(mod $module;)+ @@ -954,6 +1010,8 @@ supported_targets! { ("armv6k-nintendo-3ds", armv6k_nintendo_3ds), ("armv7-unknown-linux-uclibceabihf", armv7_unknown_linux_uclibceabihf), + + ("x86_64-unknown-none", x86_64_unknown_none), } /// Warnings encountered when parsing the target `json`. @@ -1352,6 +1410,13 @@ pub struct TargetOptions { /// Minimum number of bits in #[repr(C)] enum. Defaults to 32. pub c_enum_min_bits: u64, + + /// Whether or not the DWARF `.debug_aranges` section should be generated. + pub generate_arange_section: bool, + + /// Whether the target supports stack canary checks. `true` by default, + /// since this is most common among tier 1 and tier 2 targets. + pub supports_stack_protector: bool, } impl Default for TargetOptions { @@ -1457,6 +1522,8 @@ impl Default for TargetOptions { supported_sanitizers: SanitizerSet::empty(), default_adjusted_cabi: None, c_enum_min_bits: 32, + generate_arange_section: true, + supports_stack_protector: true, } } } @@ -1522,6 +1589,7 @@ impl Target { AmdGpuKernel => self.arch == "amdgcn", AvrInterrupt | AvrNonBlockingInterrupt => self.arch == "avr", Wasm => ["wasm32", "wasm64"].contains(&&self.arch[..]), + Thiscall { .. } => self.arch == "x86", // On windows these fall-back to platform native calling convention (C) when the // architecture is not supported. // @@ -1552,15 +1620,13 @@ impl Target { // > convention is used. // // -- https://docs.microsoft.com/en-us/cpp/cpp/argument-passing-and-naming-conventions - Stdcall { .. } | Fastcall | Thiscall { .. } | Vectorcall if self.is_like_windows => { - true - } + Stdcall { .. } | Fastcall | Vectorcall if self.is_like_windows => true, // Outside of Windows we want to only support these calling conventions for the // architectures for which these calling conventions are actually well defined. - Stdcall { .. } | Fastcall | Thiscall { .. } if self.arch == "x86" => true, + Stdcall { .. } | Fastcall if self.arch == "x86" => true, Vectorcall if ["x86", "x86_64"].contains(&&self.arch[..]) => true, // Return a `None` for other cases so that we know to emit a future compat lint. - Stdcall { .. } | Fastcall | Thiscall { .. } | Vectorcall => return None, + Stdcall { .. } | Fastcall | Vectorcall => return None, }) } @@ -1805,6 +1871,7 @@ impl Target { for s in a { base.$key_name |= match s.as_string() { Some("address") => SanitizerSet::ADDRESS, + Some("cfi") => SanitizerSet::CFI, Some("leak") => SanitizerSet::LEAK, Some("memory") => SanitizerSet::MEMORY, Some("thread") => SanitizerSet::THREAD, @@ -2042,6 +2109,8 @@ impl Target { key!(supported_sanitizers, SanitizerSet)?; key!(default_adjusted_cabi, Option)?; key!(c_enum_min_bits, u64); + key!(generate_arange_section, bool); + key!(supports_stack_protector, bool); if base.is_builtin { // This can cause unfortunate ICEs later down the line. @@ -2066,7 +2135,7 @@ impl Target { /// JSON decoding. pub fn search( target_triple: &TargetTriple, - sysroot: &PathBuf, + sysroot: &Path, ) -> Result<(Target, TargetWarnings), String> { use rustc_serialize::json; use std::env; @@ -2281,6 +2350,8 @@ impl ToJson for Target { target_option_val!(split_debuginfo); target_option_val!(supported_sanitizers); target_option_val!(c_enum_min_bits); + target_option_val!(generate_arange_section); + target_option_val!(supports_stack_protector); if let Some(abi) = self.default_adjusted_cabi { d.insert("default-adjusted-cabi".to_string(), Abi::name(abi).to_json()); diff --git a/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs b/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs index 083262cf35..ba32a31291 100644 --- a/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs +++ b/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs @@ -44,6 +44,10 @@ pub fn target() -> Target { // produce kernel functions that call other kernel functions. // This behavior is not supported by PTX ISA. merge_functions: MergeFunctions::Disabled, + + // The LLVM backend does not support stack canaries for this target + supports_stack_protector: false, + ..Default::default() }, } diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs index 86b1a75523..69a404ec56 100644 --- a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs +++ b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs @@ -37,7 +37,7 @@ pub fn target() -> Target { is_like_emscripten: true, panic_strategy: PanicStrategy::Unwind, post_link_args, - families: vec!["unix".to_string()], + families: vec!["unix".to_string(), "wasm".to_string()], ..options }; Target { diff --git a/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs index fb6526c0e7..6b7dfbb87d 100644 --- a/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs +++ b/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs @@ -23,11 +23,15 @@ pub fn target() -> Target { // 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()); + + let lld_args = options.pre_link_args.get_mut(&LinkerFlavor::Lld(LldFlavor::Wasm)).unwrap(); + lld_args.push("--no-entry".to_string()); + lld_args.push("-mwasm64".to_string()); + + // Any engine that implements wasm64 will surely implement the rest of these + // features since they were all merged into the official spec by the time + // wasm64 was designed. + options.features = "+bulk-memory,+mutable-globals,+sign-ext,+nontrapping-fptoint".to_string(); Target { llvm_target: "wasm64-unknown-unknown".to_string(), diff --git a/compiler/rustc_target/src/spec/wasm_base.rs b/compiler/rustc_target/src/spec/wasm_base.rs index 4c954a1e56..24e9c62516 100644 --- a/compiler/rustc_target/src/spec/wasm_base.rs +++ b/compiler/rustc_target/src/spec/wasm_base.rs @@ -128,6 +128,12 @@ pub fn options() -> TargetOptions { // gdb scripts don't work on wasm blobs emit_debug_gdb_scripts: false, + // There's more discussion of this at + // https://bugs.llvm.org/show_bug.cgi?id=52442 but the general result is + // that this isn't useful for wasm and has tricky issues with + // representation, so this is disabled. + generate_arange_section: false, + ..Default::default() } } 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 60fd42970c..22fdaabfcb 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs @@ -13,7 +13,8 @@ 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; + base.supported_sanitizers = + SanitizerSet::ADDRESS | SanitizerSet::CFI | 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_fuchsia.rs b/compiler/rustc_target/src/spec/x86_64_fuchsia.rs index aa65ebe1f9..c253c0c30b 100644 --- a/compiler/rustc_target/src/spec/x86_64_fuchsia.rs +++ b/compiler/rustc_target/src/spec/x86_64_fuchsia.rs @@ -6,7 +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; + base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI; Target { llvm_target: "x86_64-fuchsia".to_string(), diff --git a/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs b/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs index 34b6d2901c..6aa0728668 100644 --- a/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs +++ b/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs @@ -8,7 +8,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; + base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI; Target { llvm_target: "x86_64-pc-solaris".to_string(), 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 b5fc15f5e0..24cc7ae788 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs @@ -7,7 +7,8 @@ pub fn target() -> Target { 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; + base.supported_sanitizers = + SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::MEMORY | SanitizerSet::THREAD; Target { llvm_target: "x86_64-unknown-freebsd".to_string(), diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs b/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs index ec196a7f82..79ccf63acf 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs @@ -5,7 +5,7 @@ pub fn target() -> Target { base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string(), "-std=c99".to_string()]); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.supported_sanitizers = SanitizerSet::ADDRESS; + base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI; Target { // LLVM does not currently have a separate illumos target, 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 085079e06e..c2484f2d8f 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 @@ -7,8 +7,11 @@ pub fn target() -> Target { 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; + base.supported_sanitizers = SanitizerSet::ADDRESS + | SanitizerSet::CFI + | 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_musl.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs index 5ad243aa40..a5e7980333 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 @@ -8,8 +8,11 @@ pub fn target() -> Target { // 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; + base.supported_sanitizers = SanitizerSet::ADDRESS + | SanitizerSet::CFI + | 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 9ba86280d5..bdb2be4f86 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs @@ -7,8 +7,11 @@ pub fn target() -> Target { 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; + base.supported_sanitizers = SanitizerSet::ADDRESS + | SanitizerSet::CFI + | SanitizerSet::LEAK + | SanitizerSet::MEMORY + | SanitizerSet::THREAD; Target { llvm_target: "x86_64-unknown-netbsd".to_string(), diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_none.rs b/compiler/rustc_target/src/spec/x86_64_unknown_none.rs new file mode 100644 index 0000000000..722409dd16 --- /dev/null +++ b/compiler/rustc_target/src/spec/x86_64_unknown_none.rs @@ -0,0 +1,41 @@ +// Generic x86-64 target for bare-metal code - Floating point disabled +// +// Can be used in conjunction with the `target-feature` and +// `target-cpu` compiler flags to opt-in more hardware-specific +// features. + +use super::{ + CodeModel, LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, RelroLevel, StackProbeType, + Target, TargetOptions, +}; + +pub fn target() -> Target { + let opts = TargetOptions { + cpu: "x86-64".to_string(), + max_atomic_width: Some(64), + // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved + stack_probes: StackProbeType::Call, + position_independent_executables: true, + static_position_independent_executables: true, + relro_level: RelroLevel::Full, + relocation_model: RelocModel::Pic, + linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), + linker: Some("rust-lld".to_owned()), + features: + "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float" + .to_string(), + executables: true, + disable_redzone: true, + panic_strategy: PanicStrategy::Abort, + code_model: Some(CodeModel::Kernel), + ..Default::default() + }; + Target { + llvm_target: "x86_64-unknown-none-elf".to_string(), + pointer_width: 64, + data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + .to_string(), + arch: "x86_64".to_string(), + options: opts, + } +} diff --git a/compiler/rustc_trait_selection/src/autoderef.rs b/compiler/rustc_trait_selection/src/autoderef.rs index 53afe4ca06..4c80483fc1 100644 --- a/compiler/rustc_trait_selection/src/autoderef.rs +++ b/compiler/rustc_trait_selection/src/autoderef.rs @@ -152,11 +152,12 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { }, cause, ); - if let Err(e) = fulfillcx.select_where_possible(&self.infcx) { + let errors = fulfillcx.select_where_possible(&self.infcx); + if !errors.is_empty() { // This shouldn't happen, except for evaluate/fulfill mismatches, // but that's not a reason for an ICE (`predicate_may_hold` is conservative // by design). - debug!("overloaded_deref_ty: encountered errors {:?} while fulfilling", e); + debug!("overloaded_deref_ty: encountered errors {:?} while fulfilling", errors); return None; } let obligations = fulfillcx.pending_obligations(); diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 017a7c45bb..1820e33b19 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -14,9 +14,11 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(drain_filter)] +#![feature(derive_default_enum)] #![feature(hash_drain_filter)] #![feature(in_band_lifetimes)] #![feature(iter_zip)] +#![feature(let_else)] #![feature(never_type)] #![feature(crate_visibility_modifier)] #![feature(control_flow_enum)] diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index c220546268..75d57d78e3 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -1,61 +1,14 @@ -use crate::traits::{self, ObligationCause, PredicateObligation}; +use crate::traits; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::sync::Lrc; -use rustc_hir as hir; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::DefId; use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic; -use rustc_infer::infer::free_regions::FreeRegionRelations; -use rustc_infer::infer::opaque_types::OpaqueTypeDecl; -use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::infer::{self, InferCtxt, InferOk}; -use rustc_middle::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor}; -use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst}; +use rustc_infer::infer::InferCtxt; +use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; +use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts}; use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt}; use rustc_span::Span; -use std::ops::ControlFlow; - -/// Whether member constraints should be generated for all opaque types -#[derive(Debug)] -pub enum GenerateMemberConstraints { - /// The default, used by typeck - WhenRequired, - /// The borrow checker needs member constraints in any case where we don't - /// have a `'static` bound. This is because the borrow checker has more - /// flexibility in the values of regions. For example, given `f<'a, 'b>` - /// the borrow checker can have an inference variable outlive `'a` and `'b`, - /// but not be equal to `'static`. - IfNoStaticBound, -} - pub trait InferCtxtExt<'tcx> { - fn instantiate_opaque_types>( - &self, - body_id: hir::HirId, - param_env: ty::ParamEnv<'tcx>, - value: T, - value_span: Span, - ) -> InferOk<'tcx, T>; - - fn constrain_opaque_types>(&self, free_region_relations: &FRR); - - fn constrain_opaque_type>( - &self, - opaque_type_key: OpaqueTypeKey<'tcx>, - opaque_defn: &OpaqueTypeDecl<'tcx>, - mode: GenerateMemberConstraints, - free_region_relations: &FRR, - ); - - /*private*/ - fn generate_member_constraint( - &self, - concrete_ty: Ty<'tcx>, - opaque_defn: &OpaqueTypeDecl<'tcx>, - opaque_type_key: OpaqueTypeKey<'tcx>, - first_own_region_index: usize, - ); - fn infer_opaque_definition_from_instantiation( &self, opaque_type_key: OpaqueTypeKey<'tcx>, @@ -65,416 +18,6 @@ pub trait InferCtxtExt<'tcx> { } impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { - /// Replaces all opaque types in `value` with fresh inference variables - /// and creates appropriate obligations. For example, given the input: - /// - /// impl Iterator - /// - /// this method would create two type variables, `?0` and `?1`. It would - /// return the type `?0` but also the obligations: - /// - /// ?0: Iterator - /// ?1: Debug - /// - /// Moreover, it returns an `OpaqueTypeMap` that would map `?0` to - /// info about the `impl Iterator<..>` type and `?1` to info about - /// the `impl Debug` type. - /// - /// # Parameters - /// - /// - `parent_def_id` -- the `DefId` of the function in which the opaque type - /// is defined - /// - `body_id` -- the body-id with which the resulting obligations should - /// be associated - /// - `param_env` -- the in-scope parameter environment to be used for - /// obligations - /// - `value` -- the value within which we are instantiating opaque types - /// - `value_span` -- the span where the value came from, used in error reporting - fn instantiate_opaque_types>( - &self, - body_id: hir::HirId, - param_env: ty::ParamEnv<'tcx>, - value: T, - value_span: Span, - ) -> InferOk<'tcx, T> { - debug!( - "instantiate_opaque_types(value={:?}, body_id={:?}, \ - param_env={:?}, value_span={:?})", - value, body_id, param_env, value_span, - ); - let mut instantiator = - Instantiator { infcx: self, body_id, param_env, value_span, obligations: vec![] }; - let value = instantiator.instantiate_opaque_types_in_map(value); - InferOk { value, obligations: instantiator.obligations } - } - - /// Given the map `opaque_types` containing the opaque - /// `impl Trait` types whose underlying, hidden types are being - /// inferred, this method adds constraints to the regions - /// appearing in those underlying hidden types to ensure that they - /// at least do not refer to random scopes within the current - /// function. These constraints are not (quite) sufficient to - /// guarantee that the regions are actually legal values; that - /// final condition is imposed after region inference is done. - /// - /// # The Problem - /// - /// Let's work through an example to explain how it works. Assume - /// the current function is as follows: - /// - /// ```text - /// fn foo<'a, 'b>(..) -> (impl Bar<'a>, impl Bar<'b>) - /// ``` - /// - /// Here, we have two `impl Trait` types whose values are being - /// inferred (the `impl Bar<'a>` and the `impl - /// Bar<'b>`). Conceptually, this is sugar for a setup where we - /// define underlying opaque types (`Foo1`, `Foo2`) and then, in - /// the return type of `foo`, we *reference* those definitions: - /// - /// ```text - /// type Foo1<'x> = impl Bar<'x>; - /// type Foo2<'x> = impl Bar<'x>; - /// fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. } - /// // ^^^^ ^^ - /// // | | - /// // | substs - /// // def_id - /// ``` - /// - /// As indicating in the comments above, each of those references - /// is (in the compiler) basically a substitution (`substs`) - /// applied to the type of a suitable `def_id` (which identifies - /// `Foo1` or `Foo2`). - /// - /// Now, at this point in compilation, what we have done is to - /// replace each of the references (`Foo1<'a>`, `Foo2<'b>`) with - /// fresh inference variables C1 and C2. We wish to use the values - /// of these variables to infer the underlying types of `Foo1` and - /// `Foo2`. That is, this gives rise to higher-order (pattern) unification - /// constraints like: - /// - /// ```text - /// for<'a> (Foo1<'a> = C1) - /// for<'b> (Foo1<'b> = C2) - /// ``` - /// - /// For these equation to be satisfiable, the types `C1` and `C2` - /// can only refer to a limited set of regions. For example, `C1` - /// can only refer to `'static` and `'a`, and `C2` can only refer - /// to `'static` and `'b`. The job of this function is to impose that - /// constraint. - /// - /// Up to this point, C1 and C2 are basically just random type - /// inference variables, and hence they may contain arbitrary - /// regions. In fact, it is fairly likely that they do! Consider - /// this possible definition of `foo`: - /// - /// ```text - /// fn foo<'a, 'b>(x: &'a i32, y: &'b i32) -> (impl Bar<'a>, impl Bar<'b>) { - /// (&*x, &*y) - /// } - /// ``` - /// - /// Here, the values for the concrete types of the two impl - /// traits will include inference variables: - /// - /// ```text - /// &'0 i32 - /// &'1 i32 - /// ``` - /// - /// Ordinarily, the subtyping rules would ensure that these are - /// sufficiently large. But since `impl Bar<'a>` isn't a specific - /// type per se, we don't get such constraints by default. This - /// is where this function comes into play. It adds extra - /// constraints to ensure that all the regions which appear in the - /// inferred type are regions that could validly appear. - /// - /// This is actually a bit of a tricky constraint in general. We - /// want to say that each variable (e.g., `'0`) can only take on - /// values that were supplied as arguments to the opaque type - /// (e.g., `'a` for `Foo1<'a>`) or `'static`, which is always in - /// scope. We don't have a constraint quite of this kind in the current - /// region checker. - /// - /// # The Solution - /// - /// We generally prefer to make `<=` constraints, since they - /// integrate best into the region solver. To do that, we find the - /// "minimum" of all the arguments that appear in the substs: that - /// is, some region which is less than all the others. In the case - /// of `Foo1<'a>`, that would be `'a` (it's the only choice, after - /// all). Then we apply that as a least bound to the variables - /// (e.g., `'a <= '0`). - /// - /// In some cases, there is no minimum. Consider this example: - /// - /// ```text - /// fn baz<'a, 'b>() -> impl Trait<'a, 'b> { ... } - /// ``` - /// - /// Here we would report a more complex "in constraint", like `'r - /// in ['a, 'b, 'static]` (where `'r` is some region appearing in - /// the hidden type). - /// - /// # Constrain regions, not the hidden concrete type - /// - /// Note that generating constraints on each region `Rc` is *not* - /// the same as generating an outlives constraint on `Tc` iself. - /// For example, if we had a function like this: - /// - /// ```rust - /// fn foo<'a, T>(x: &'a u32, y: T) -> impl Foo<'a> { - /// (x, y) - /// } - /// - /// // Equivalent to: - /// type FooReturn<'a, T> = impl Foo<'a>; - /// fn foo<'a, T>(..) -> FooReturn<'a, T> { .. } - /// ``` - /// - /// then the hidden type `Tc` would be `(&'0 u32, T)` (where `'0` - /// is an inference variable). If we generated a constraint that - /// `Tc: 'a`, then this would incorrectly require that `T: 'a` -- - /// but this is not necessary, because the opaque type we - /// create will be allowed to reference `T`. So we only generate a - /// constraint that `'0: 'a`. - /// - /// # The `free_region_relations` parameter - /// - /// The `free_region_relations` argument is used to find the - /// "minimum" of the regions supplied to a given opaque type. - /// It must be a relation that can answer whether `'a <= 'b`, - /// where `'a` and `'b` are regions that appear in the "substs" - /// for the opaque type references (the `<'a>` in `Foo1<'a>`). - /// - /// Note that we do not impose the constraints based on the - /// generic regions from the `Foo1` definition (e.g., `'x`). This - /// is because the constraints we are imposing here is basically - /// the concern of the one generating the constraining type C1, - /// which is the current function. It also means that we can - /// take "implied bounds" into account in some cases: - /// - /// ```text - /// trait SomeTrait<'a, 'b> { } - /// fn foo<'a, 'b>(_: &'a &'b u32) -> impl SomeTrait<'a, 'b> { .. } - /// ``` - /// - /// Here, the fact that `'b: 'a` is known only because of the - /// implied bounds from the `&'a &'b u32` parameter, and is not - /// "inherent" to the opaque type definition. - /// - /// # Parameters - /// - /// - `opaque_types` -- the map produced by `instantiate_opaque_types` - /// - `free_region_relations` -- something that can be used to relate - /// the free regions (`'a`) that appear in the impl trait. - fn constrain_opaque_types>(&self, free_region_relations: &FRR) { - let opaque_types = self.inner.borrow().opaque_types.clone(); - for (opaque_type_key, opaque_defn) in opaque_types { - self.constrain_opaque_type( - opaque_type_key, - &opaque_defn, - GenerateMemberConstraints::WhenRequired, - free_region_relations, - ); - } - } - - /// See `constrain_opaque_types` for documentation. - #[instrument(level = "debug", skip(self, free_region_relations))] - fn constrain_opaque_type>( - &self, - opaque_type_key: OpaqueTypeKey<'tcx>, - opaque_defn: &OpaqueTypeDecl<'tcx>, - mode: GenerateMemberConstraints, - free_region_relations: &FRR, - ) { - let def_id = opaque_type_key.def_id; - - let tcx = self.tcx; - - let concrete_ty = self.resolve_vars_if_possible(opaque_defn.concrete_ty); - - debug!(?concrete_ty); - - let first_own_region = match opaque_defn.origin { - hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => { - // We lower - // - // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm> - // - // into - // - // type foo::<'p0..'pn>::Foo<'q0..'qm> - // fn foo() -> foo::<'static..'static>::Foo<'l0..'lm>. - // - // For these types we only iterate over `'l0..lm` below. - tcx.generics_of(def_id).parent_count - } - // These opaque type inherit all lifetime parameters from their - // parent, so we have to check them all. - hir::OpaqueTyOrigin::TyAlias => 0, - }; - - let span = tcx.def_span(def_id); - - // Check if the `impl Trait` bounds include region bounds. - // For example, this would be true for: - // - // fn foo<'a, 'b, 'c>() -> impl Trait<'c> + 'a + 'b - // - // but false for: - // - // fn foo<'c>() -> impl Trait<'c> - // - // unless `Trait` was declared like: - // - // trait Trait<'c>: 'c - // - // in which case it would be true. - // - // This is used during regionck to decide whether we need to - // impose any additional constraints to ensure that region - // variables in `concrete_ty` wind up being constrained to - // something from `substs` (or, at minimum, things that outlive - // the fn body). (Ultimately, writeback is responsible for this - // check.) - let bounds = tcx.explicit_item_bounds(def_id); - debug!("{:#?}", bounds); - let bounds = bounds.iter().map(|(bound, _)| bound.subst(tcx, opaque_type_key.substs)); - debug!("{:#?}", bounds); - let opaque_type = tcx.mk_opaque(def_id, opaque_type_key.substs); - - let required_region_bounds = required_region_bounds(tcx, opaque_type, bounds); - if !required_region_bounds.is_empty() { - for required_region in required_region_bounds { - concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor { - tcx, - op: |r| self.sub_regions(infer::CallReturn(span), required_region, r), - }); - } - if let GenerateMemberConstraints::IfNoStaticBound = mode { - self.generate_member_constraint( - concrete_ty, - opaque_defn, - opaque_type_key, - first_own_region, - ); - } - return; - } - - // There were no `required_region_bounds`, - // so we have to search for a `least_region`. - // Go through all the regions used as arguments to the - // opaque type. These are the parameters to the opaque - // type; so in our example above, `substs` would contain - // `['a]` for the first impl trait and `'b` for the - // second. - let mut least_region = None; - - for subst_arg in &opaque_type_key.substs[first_own_region..] { - let subst_region = match subst_arg.unpack() { - GenericArgKind::Lifetime(r) => r, - GenericArgKind::Type(_) | GenericArgKind::Const(_) => continue, - }; - - // Compute the least upper bound of it with the other regions. - debug!(?least_region); - debug!(?subst_region); - match least_region { - None => least_region = Some(subst_region), - Some(lr) => { - if free_region_relations.sub_free_regions(self.tcx, lr, subst_region) { - // keep the current least region - } else if free_region_relations.sub_free_regions(self.tcx, subst_region, lr) { - // switch to `subst_region` - least_region = Some(subst_region); - } else { - // There are two regions (`lr` and - // `subst_region`) which are not relatable. We - // can't find a best choice. Therefore, - // instead of creating a single bound like - // `'r: 'a` (which is our preferred choice), - // we will create a "in bound" like `'r in - // ['a, 'b, 'c]`, where `'a..'c` are the - // regions that appear in the impl trait. - - return self.generate_member_constraint( - concrete_ty, - opaque_defn, - opaque_type_key, - first_own_region, - ); - } - } - } - } - - let least_region = least_region.unwrap_or(tcx.lifetimes.re_static); - debug!(?least_region); - - if let GenerateMemberConstraints::IfNoStaticBound = mode { - if least_region != tcx.lifetimes.re_static { - self.generate_member_constraint( - concrete_ty, - opaque_defn, - opaque_type_key, - first_own_region, - ); - } - } - concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor { - tcx, - op: |r| self.sub_regions(infer::CallReturn(span), least_region, r), - }); - } - - /// As a fallback, we sometimes generate an "in constraint". For - /// a case like `impl Foo<'a, 'b>`, where `'a` and `'b` cannot be - /// related, we would generate a constraint `'r in ['a, 'b, - /// 'static]` for each region `'r` that appears in the hidden type - /// (i.e., it must be equal to `'a`, `'b`, or `'static`). - /// - /// `conflict1` and `conflict2` are the two region bounds that we - /// detected which were unrelated. They are used for diagnostics. - fn generate_member_constraint( - &self, - concrete_ty: Ty<'tcx>, - opaque_defn: &OpaqueTypeDecl<'tcx>, - opaque_type_key: OpaqueTypeKey<'tcx>, - first_own_region: usize, - ) { - // Create the set of choice regions: each region in the hidden - // type can be equal to any of the region parameters of the - // opaque type definition. - let choice_regions: Lrc>> = Lrc::new( - opaque_type_key.substs[first_own_region..] - .iter() - .filter_map(|arg| match arg.unpack() { - GenericArgKind::Lifetime(r) => Some(r), - GenericArgKind::Type(_) | GenericArgKind::Const(_) => None, - }) - .chain(std::iter::once(self.tcx.lifetimes.re_static)) - .collect(), - ); - - concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor { - tcx: self.tcx, - op: |r| { - self.member_constraint( - opaque_type_key.def_id, - opaque_defn.definition_span, - concrete_ty, - r, - &choice_regions, - ) - }, - }); - } - /// Given the fully resolved, instantiated type for an opaque /// type, i.e., the value of an inference variable like C1 or C2 /// (*), computes the "definition type" for an opaque type @@ -490,7 +33,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { /// purpose of this function is to do that translation. /// /// (*) C1 and C2 were introduced in the comments on - /// `constrain_opaque_types`. Read that comment for more context. + /// `constrain_opaque_type`. Read that comment for more context. /// /// # Parameters /// @@ -536,83 +79,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } } -// Visitor that requires that (almost) all regions in the type visited outlive -// `least_region`. We cannot use `push_outlives_components` because regions in -// closure signatures are not included in their outlives components. We need to -// ensure all regions outlive the given bound so that we don't end up with, -// say, `ReVar` appearing in a return type and causing ICEs when other -// functions end up with region constraints involving regions from other -// functions. -// -// We also cannot use `for_each_free_region` because for closures it includes -// the regions parameters from the enclosing item. -// -// We ignore any type parameters because impl trait values are assumed to -// capture all the in-scope type parameters. -struct ConstrainOpaqueTypeRegionVisitor<'tcx, OP> { - tcx: TyCtxt<'tcx>, - op: OP, -} - -impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<'tcx, OP> -where - OP: FnMut(ty::Region<'tcx>), -{ - fn tcx_for_anon_const_substs(&self) -> Option> { - Some(self.tcx) - } - - fn visit_binder>( - &mut self, - t: &ty::Binder<'tcx, T>, - ) -> ControlFlow { - t.as_ref().skip_binder().visit_with(self); - ControlFlow::CONTINUE - } - - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { - match *r { - // ignore bound regions, keep visiting - ty::ReLateBound(_, _) => ControlFlow::CONTINUE, - _ => { - (self.op)(r); - ControlFlow::CONTINUE - } - } - } - - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { - // We're only interested in types involving regions - if !ty.flags().intersects(ty::TypeFlags::HAS_POTENTIAL_FREE_REGIONS) { - return ControlFlow::CONTINUE; - } - - match ty.kind() { - ty::Closure(_, ref substs) => { - // Skip lifetime parameters of the enclosing item(s) - - substs.as_closure().tupled_upvars_ty().visit_with(self); - substs.as_closure().sig_as_fn_ptr_ty().visit_with(self); - } - - ty::Generator(_, ref substs, _) => { - // Skip lifetime parameters of the enclosing item(s) - // Also skip the witness type, because that has no free regions. - - substs.as_generator().tupled_upvars_ty().visit_with(self); - substs.as_generator().return_ty().visit_with(self); - substs.as_generator().yield_ty().visit_with(self); - substs.as_generator().resume_ty().visit_with(self); - } - _ => { - ty.super_visit_with(self); - } - } - - ControlFlow::CONTINUE - } -} - struct ReverseMapper<'tcx> { tcx: TyCtxt<'tcx>, @@ -855,235 +321,6 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { } } -struct Instantiator<'a, 'tcx> { - infcx: &'a InferCtxt<'a, 'tcx>, - body_id: hir::HirId, - param_env: ty::ParamEnv<'tcx>, - value_span: Span, - obligations: Vec>, -} - -impl<'a, 'tcx> Instantiator<'a, 'tcx> { - fn instantiate_opaque_types_in_map>(&mut self, value: T) -> T { - let tcx = self.infcx.tcx; - value.fold_with(&mut BottomUpFolder { - tcx, - ty_op: |ty| { - if ty.references_error() { - return tcx.ty_error(); - } else if let ty::Opaque(def_id, substs) = ty.kind() { - // Check that this is `impl Trait` type is - // declared by `parent_def_id` -- i.e., one whose - // value we are inferring. At present, this is - // always true during the first phase of - // type-check, but not always true later on during - // NLL. Once we support named opaque types more fully, - // this same scenario will be able to arise during all phases. - // - // Here is an example using type alias `impl Trait` - // that indicates the distinction we are checking for: - // - // ```rust - // mod a { - // pub type Foo = impl Iterator; - // pub fn make_foo() -> Foo { .. } - // } - // - // mod b { - // fn foo() -> a::Foo { a::make_foo() } - // } - // ``` - // - // Here, the return type of `foo` references an - // `Opaque` indeed, but not one whose value is - // presently being inferred. You can get into a - // similar situation with closure return types - // today: - // - // ```rust - // fn foo() -> impl Iterator { .. } - // fn bar() { - // let x = || foo(); // returns the Opaque assoc with `foo` - // } - // ``` - if let Some(def_id) = def_id.as_local() { - let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let parent_def_id = self.infcx.defining_use_anchor; - let def_scope_default = || { - let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id); - parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id) - }; - let (in_definition_scope, origin) = - match tcx.hir().expect_item(opaque_hir_id).kind { - // Anonymous `impl Trait` - hir::ItemKind::OpaqueTy(hir::OpaqueTy { - impl_trait_fn: Some(parent), - origin, - .. - }) => (parent == parent_def_id.to_def_id(), origin), - // Named `type Foo = impl Bar;` - hir::ItemKind::OpaqueTy(hir::OpaqueTy { - impl_trait_fn: None, - origin, - .. - }) => ( - may_define_opaque_type(tcx, parent_def_id, opaque_hir_id), - origin, - ), - _ => (def_scope_default(), hir::OpaqueTyOrigin::TyAlias), - }; - if in_definition_scope { - let opaque_type_key = - OpaqueTypeKey { def_id: def_id.to_def_id(), substs }; - return self.fold_opaque_ty(ty, opaque_type_key, origin); - } - - debug!( - "instantiate_opaque_types_in_map: \ - encountered opaque outside its definition scope \ - def_id={:?}", - def_id, - ); - } - } - - ty - }, - lt_op: |lt| lt, - ct_op: |ct| ct, - }) - } - - #[instrument(skip(self), level = "debug")] - fn fold_opaque_ty( - &mut self, - ty: Ty<'tcx>, - opaque_type_key: OpaqueTypeKey<'tcx>, - origin: hir::OpaqueTyOrigin, - ) -> Ty<'tcx> { - let infcx = self.infcx; - let tcx = infcx.tcx; - let OpaqueTypeKey { def_id, substs } = opaque_type_key; - - // Use the same type variable if the exact same opaque type appears more - // than once in the return type (e.g., if it's passed to a type alias). - if let Some(opaque_defn) = infcx.inner.borrow().opaque_types.get(&opaque_type_key) { - debug!("re-using cached concrete type {:?}", opaque_defn.concrete_ty.kind()); - return opaque_defn.concrete_ty; - } - - let ty_var = infcx.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::TypeInference, - span: self.value_span, - }); - - // Ideally, we'd get the span where *this specific `ty` came - // from*, but right now we just use the span from the overall - // value being folded. In simple cases like `-> impl Foo`, - // these are the same span, but not in cases like `-> (impl - // Foo, impl Bar)`. - let definition_span = self.value_span; - - { - let mut infcx = self.infcx.inner.borrow_mut(); - infcx.opaque_types.insert( - OpaqueTypeKey { def_id, substs }, - OpaqueTypeDecl { opaque_type: ty, definition_span, concrete_ty: ty_var, origin }, - ); - infcx.opaque_types_vars.insert(ty_var, ty); - } - - debug!("generated new type inference var {:?}", ty_var.kind()); - - let item_bounds = tcx.explicit_item_bounds(def_id); - - self.obligations.reserve(item_bounds.len()); - for (predicate, _) in item_bounds { - debug!(?predicate); - let predicate = predicate.subst(tcx, substs); - debug!(?predicate); - - // We can't normalize associated types from `rustc_infer`, but we can eagerly register inference variables for them. - let predicate = predicate.fold_with(&mut BottomUpFolder { - tcx, - ty_op: |ty| match ty.kind() { - ty::Projection(projection_ty) => infcx.infer_projection( - self.param_env, - *projection_ty, - ObligationCause::misc(self.value_span, self.body_id), - 0, - &mut self.obligations, - ), - _ => ty, - }, - lt_op: |lt| lt, - ct_op: |ct| ct, - }); - debug!(?predicate); - - if let ty::PredicateKind::Projection(projection) = predicate.kind().skip_binder() { - if projection.ty.references_error() { - // No point on adding these obligations since there's a type error involved. - return tcx.ty_error(); - } - } - // Change the predicate to refer to the type variable, - // which will be the concrete type instead of the opaque type. - // This also instantiates nested instances of `impl Trait`. - let predicate = self.instantiate_opaque_types_in_map(predicate); - - let cause = - traits::ObligationCause::new(self.value_span, self.body_id, traits::OpaqueType); - - // Require that the predicate holds for the concrete type. - debug!(?predicate); - self.obligations.push(traits::Obligation::new(cause, self.param_env, predicate)); - } - - ty_var - } -} - -/// Returns `true` if `opaque_hir_id` is a sibling or a child of a sibling of `def_id`. -/// -/// Example: -/// ```rust -/// pub mod foo { -/// pub mod bar { -/// pub trait Bar { .. } -/// -/// pub type Baz = impl Bar; -/// -/// fn f1() -> Baz { .. } -/// } -/// -/// fn f2() -> bar::Baz { .. } -/// } -/// ``` -/// -/// Here, `def_id` is the `LocalDefId` of the defining use of the opaque type (e.g., `f1` or `f2`), -/// and `opaque_hir_id` is the `HirId` of the definition of the opaque type `Baz`. -/// For the above example, this function returns `true` for `f1` and `false` for `f2`. -fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: LocalDefId, opaque_hir_id: hir::HirId) -> bool { - let mut hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - - // Named opaque types can be defined by any siblings or children of siblings. - let scope = tcx.hir().get_defining_scope(opaque_hir_id); - // We walk up the node tree until we hit the root or the scope of the opaque type. - while hir_id != scope && hir_id != hir::CRATE_HIR_ID { - hir_id = tcx.hir().get_parent_item(hir_id); - } - // Syntactically, we are allowed to define the concrete type if: - let res = hir_id == scope; - trace!( - "may_define_opaque_type(def={:?}, opaque_node={:?}) = {}", - tcx.hir().find(hir_id), - tcx.hir().get(opaque_hir_id), - res - ); - res -} - /// Given a set of predicates that apply to an object type, returns /// the region bounds that the (erased) `Self` type must /// outlive. Precisely *because* the `Self` type is erased, the diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 622c9edc43..54f7b91080 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -187,9 +187,11 @@ impl<'tcx> AutoTraitFinder<'tcx> { // an additional sanity check. let mut fulfill = FulfillmentContext::new(); fulfill.register_bound(&infcx, full_env, ty, trait_did, ObligationCause::dummy()); - fulfill.select_all_or_error(&infcx).unwrap_or_else(|e| { - panic!("Unable to fulfill trait {:?} for '{:?}': {:?}", trait_did, ty, e) - }); + let errors = fulfill.select_all_or_error(&infcx); + + if !errors.is_empty() { + panic!("Unable to fulfill trait {:?} for '{:?}': {:?}", trait_did, ty, errors); + } let body_id_map: FxHashMap<_, _> = infcx .inner @@ -286,6 +288,8 @@ impl AutoTraitFinder<'tcx> { substs: infcx.tcx.mk_substs_trait(ty, &[]), }, constness: ty::BoundConstness::NotConst, + // Auto traits are positive + polarity: ty::ImplPolarity::Positive, })); let computed_preds = param_env.caller_bounds().iter(); diff --git a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs index ec62ee4006..2ccb253491 100644 --- a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs @@ -49,34 +49,32 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> { self.obligations.insert(obligation); } - fn select_all_or_error( - &mut self, - infcx: &InferCtxt<'_, 'tcx>, - ) -> Result<(), Vec>> { - self.select_where_possible(infcx)?; - - if self.obligations.is_empty() { - Ok(()) - } else { - let errors = self - .obligations - .iter() - .map(|obligation| FulfillmentError { - obligation: obligation.clone(), - code: FulfillmentErrorCode::CodeAmbiguity, - // FIXME - does Chalk have a notation of 'root obligation'? - // This is just for diagnostics, so it's okay if this is wrong - root_obligation: obligation.clone(), - }) - .collect(); - Err(errors) + fn select_all_or_error(&mut self, infcx: &InferCtxt<'_, 'tcx>) -> Vec> { + { + let errors = self.select_where_possible(infcx); + + if !errors.is_empty() { + return errors; + } } + + // any remaining obligations are errors + self.obligations + .iter() + .map(|obligation| FulfillmentError { + obligation: obligation.clone(), + code: FulfillmentErrorCode::CodeAmbiguity, + // FIXME - does Chalk have a notation of 'root obligation'? + // This is just for diagnostics, so it's okay if this is wrong + root_obligation: obligation.clone(), + }) + .collect() } fn select_where_possible( &mut self, infcx: &InferCtxt<'_, 'tcx>, - ) -> Result<(), Vec>> { + ) -> Vec> { assert!(!infcx.is_in_snapshot()); let mut errors = Vec::new(); @@ -147,7 +145,7 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> { } } - if errors.is_empty() { Ok(()) } else { Err(errors) } + errors } fn pending_obligations(&self) -> Vec> { diff --git a/compiler/rustc_trait_selection/src/traits/codegen.rs b/compiler/rustc_trait_selection/src/traits/codegen.rs index f06f0e32f4..bdd4fdd404 100644 --- a/compiler/rustc_trait_selection/src/traits/codegen.rs +++ b/compiler/rustc_trait_selection/src/traits/codegen.rs @@ -120,7 +120,8 @@ where // In principle, we only need to do this so long as `result` // contains unbound type parameters. It could be a slight // optimization to stop iterating early. - if let Err(errors) = fulfill_cx.select_all_or_error(infcx) { + let errors = fulfill_cx.select_all_or_error(infcx); + if !errors.is_empty() { infcx.tcx.sess.delay_span_bug( rustc_span::DUMMY_SP, &format!("Encountered errors `{:?}` resolving bounds after type-checking", errors), diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 668a74bd69..42d3194aed 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -5,9 +5,12 @@ //! [trait-specialization]: https://rustc-dev-guide.rust-lang.org/traits/specialization.html use crate::infer::{CombinedSnapshot, InferOk, TyCtxtInferExt}; +use crate::traits::query::evaluate_obligation::InferCtxtExt; use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::SkipLeakCheck; -use crate::traits::{self, Normalized, Obligation, ObligationCause, SelectionContext}; +use crate::traits::{ + self, Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext, +}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::Subst; @@ -158,6 +161,19 @@ fn overlap_within_probe( b_def_id: DefId, snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> Option> { + fn loose_check(selcx: &mut SelectionContext<'cx, 'tcx>, o: &PredicateObligation<'tcx>) -> bool { + !selcx.predicate_may_hold_fatal(o) + } + + fn strict_check(selcx: &SelectionContext<'cx, 'tcx>, o: &PredicateObligation<'tcx>) -> bool { + let infcx = selcx.infcx(); + let tcx = infcx.tcx; + o.flip_polarity(tcx) + .as_ref() + .map(|o| selcx.infcx().predicate_must_hold_modulo_regions(o)) + .unwrap_or(false) + } + // For the purposes of this check, we don't bring any placeholder // types into scope; instead, we replace the generic types with // fresh type variables, and hence we do our evaluations in an @@ -184,8 +200,29 @@ fn overlap_within_probe( debug!("overlap: unification check succeeded"); - // Are any of the obligations unsatisfiable? If so, no overlap. + // There's no overlap if obligations are unsatisfiable or if the obligation negated is + // satisfied. + // + // For example, given these two impl headers: + // + // `impl<'a> From<&'a str> for Box` + // `impl From for Box where E: Error` + // + // So we have: + // + // `Box: From<&'?a str>` + // `Box: From` + // + // After equating the two headers: + // + // `Box = Box` + // So, `?E = &'?a str` and then given the where clause `&'?a str: Error`. + // + // If the obligation `&'?a str: Error` holds, it means that there's overlap. If that doesn't + // hold we need to check if `&'?a str: !Error` holds, if doesn't hold there's overlap because + // at some point an impl for `&'?a str: Error` could be added. let infcx = selcx.infcx(); + let tcx = infcx.tcx; let opt_failing_obligation = a_impl_header .predicates .iter() @@ -199,7 +236,17 @@ fn overlap_within_probe( predicate: p, }) .chain(obligations) - .find(|o| !selcx.predicate_may_hold_fatal(o)); + .find(|o| { + // if both impl headers are set to strict coherence it means that this will be accepted + // only if it's stated that T: !Trait. So only prove that the negated obligation holds. + if tcx.has_attr(a_def_id, sym::rustc_strict_coherence) + && tcx.has_attr(b_def_id, sym::rustc_strict_coherence) + { + strict_check(selcx, o) + } else { + loose_check(selcx, o) || tcx.features().negative_impls && strict_check(selcx, o) + } + }); // FIXME: the call to `selcx.predicate_may_hold_fatal` above should be ported // to the canonical trait query form, `infcx.predicate_may_hold`, once // the new system supports intercrate mode (which coherence needs). diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 1193d10d6a..6b5d37c0f4 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -80,9 +80,8 @@ pub fn is_const_evaluatable<'cx, 'tcx>( Concrete, } let mut failure_kind = FailureKind::Concrete; - walk_abstract_const::(tcx, ct, |node| match node.root() { + walk_abstract_const::(tcx, ct, |node| match node.root(tcx) { Node::Leaf(leaf) => { - let leaf = leaf.subst(tcx, ct.substs); if leaf.has_infer_types_or_consts() { failure_kind = FailureKind::MentionsInfer; } else if leaf.definitely_has_param_types_or_consts(tcx) { @@ -92,7 +91,6 @@ pub fn is_const_evaluatable<'cx, 'tcx>( ControlFlow::CONTINUE } Node::Cast(_, _, ty) => { - let ty = ty.subst(tcx, ct.substs); if ty.has_infer_types_or_consts() { failure_kind = FailureKind::MentionsInfer; } else if ty.definitely_has_param_types_or_consts(tcx) { @@ -153,7 +151,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>( if concrete.is_ok() && uv.substs(infcx.tcx).definitely_has_param_types_or_consts(infcx.tcx) { match infcx.tcx.def_kind(uv.def.did) { - DefKind::AnonConst => { + DefKind::AnonConst | DefKind::InlineConst => { let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(uv.def); if mir_body.is_polymorphic { @@ -187,8 +185,8 @@ pub fn is_const_evaluatable<'cx, 'tcx>( pub struct AbstractConst<'tcx> { // FIXME: Consider adding something like `IndexSlice` // and use this here. - pub inner: &'tcx [Node<'tcx>], - pub substs: SubstsRef<'tcx>, + inner: &'tcx [Node<'tcx>], + substs: SubstsRef<'tcx>, } impl<'tcx> AbstractConst<'tcx> { @@ -218,8 +216,14 @@ impl<'tcx> AbstractConst<'tcx> { } #[inline] - pub fn root(self) -> Node<'tcx> { - self.inner.last().copied().unwrap() + pub fn root(self, tcx: TyCtxt<'tcx>) -> Node<'tcx> { + let node = self.inner.last().copied().unwrap(); + match node { + Node::Leaf(leaf) => Node::Leaf(leaf.subst(tcx, self.substs)), + Node::Cast(kind, operand, ty) => Node::Cast(kind, operand, ty.subst(tcx, self.substs)), + // Don't perform substitution on the following as they can't directly contain generic params + Node::Binop(_, _, _) | Node::UnaryOp(_, _) | Node::FunctionCall(_, _) => node, + } } } @@ -491,7 +495,7 @@ pub(super) fn thir_abstract_const<'tcx>( // we want to look into them or treat them as opaque projections. // // Right now we do neither of that and simply always fail to unify them. - DefKind::AnonConst => (), + DefKind::AnonConst | DefKind::InlineConst => (), _ => return Ok(None), } @@ -542,7 +546,7 @@ where f: &mut dyn FnMut(AbstractConst<'tcx>) -> ControlFlow, ) -> ControlFlow { f(ct)?; - let root = ct.root(); + let root = ct.root(tcx); match root { Node::Leaf(_) => ControlFlow::CONTINUE, Node::Binop(_, l, r) => { @@ -570,16 +574,14 @@ pub(super) fn try_unify<'tcx>( // We substitute generics repeatedly to allow AbstractConsts to unify where a // ConstKind::Unevalated could be turned into an AbstractConst that would unify e.g. // Param(N) should unify with Param(T), substs: [Unevaluated("T2", [Unevaluated("T3", [Param(N)])])] - while let Node::Leaf(a_ct) = a.root() { - let a_ct = a_ct.subst(tcx, a.substs); + while let Node::Leaf(a_ct) = a.root(tcx) { match AbstractConst::from_const(tcx, a_ct) { Ok(Some(a_act)) => a = a_act, Ok(None) => break, Err(_) => return true, } } - while let Node::Leaf(b_ct) = b.root() { - let b_ct = b_ct.subst(tcx, b.substs); + while let Node::Leaf(b_ct) = b.root(tcx) { match AbstractConst::from_const(tcx, b_ct) { Ok(Some(b_act)) => b = b_act, Ok(None) => break, @@ -587,10 +589,8 @@ pub(super) fn try_unify<'tcx>( } } - match (a.root(), b.root()) { + match (a.root(tcx), b.root(tcx)) { (Node::Leaf(a_ct), Node::Leaf(b_ct)) => { - let a_ct = a_ct.subst(tcx, a.substs); - let b_ct = b_ct.subst(tcx, b.substs); if a_ct.ty != b_ct.ty { return 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 225ff5e597..f8df0e2595 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -34,6 +34,7 @@ use std::iter; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; use crate::traits::query::normalize::AtExt as _; +use crate::traits::specialize::to_pretty_impl_header; use on_unimplemented::InferCtxtExt as _; use suggestions::InferCtxtExt as _; @@ -241,6 +242,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let mut span = obligation.cause.span; let mut err = match *error { + SelectionError::Ambiguous(ref impls) => { + let mut err = self.tcx.sess.struct_span_err( + obligation.cause.span, + &format!("multiple applicable `impl`s for `{}`", obligation.predicate), + ); + self.annotate_source_of_ambiguity(&mut err, impls, obligation.predicate); + err.emit(); + return; + } SelectionError::Unimplemented => { // If this obligation was generated as a result of well-formedness checking, see if we // can get a better error message by performing HIR-based well-formedness checking. @@ -256,19 +266,16 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } } if let ObligationCauseCode::CompareImplMethodObligation { - item_name, impl_item_def_id, trait_item_def_id, } | ObligationCauseCode::CompareImplTypeObligation { - item_name, impl_item_def_id, trait_item_def_id, } = obligation.cause.code { self.report_extra_impl_obligation( span, - item_name, impl_item_def_id, trait_item_def_id, &format!("`{}`", obligation.predicate), @@ -1138,6 +1145,13 @@ trait InferCtxtPrivExt<'tcx> { obligation: &PredicateObligation<'tcx>, ); + fn annotate_source_of_ambiguity( + &self, + err: &mut DiagnosticBuilder<'tcx>, + impls: &[DefId], + predicate: ty::Predicate<'tcx>, + ); + fn maybe_suggest_unsized_generics( &self, err: &mut DiagnosticBuilder<'tcx>, @@ -1475,6 +1489,9 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { } } } + ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => { + self.get_parent_trait_ref(&parent_code) + } _ => None, } } @@ -1549,11 +1566,8 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { ?predicate, ?obligation.cause.code, ); - // Ambiguity errors are often caused as fallout from earlier - // errors. So just ignore them if this infcx is tainted. - if self.is_tainted_by_errors() { - return; - } + // Ambiguity errors are often caused as fallout from earlier errors. + // We ignore them if this `infcx` is tainted in some cases below. let bound_predicate = predicate.kind(); let mut err = match bound_predicate.skip_binder() { @@ -1601,10 +1615,19 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { // check upstream for type errors and don't add the obligations to // begin with in those cases. if self.tcx.lang_items().sized_trait() == Some(trait_ref.def_id()) { - self.emit_inference_failure_err(body_id, span, subst, vec![], ErrorCode::E0282) + if !self.is_tainted_by_errors() { + self.emit_inference_failure_err( + body_id, + span, + subst, + vec![], + ErrorCode::E0282, + ) .emit(); + } return; } + let impl_candidates = self.find_similar_impl_candidates(trait_ref); let mut err = self.emit_inference_failure_err( body_id, @@ -1613,7 +1636,29 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { impl_candidates, ErrorCode::E0283, ); - err.note(&format!("cannot satisfy `{}`", predicate)); + + let obligation = Obligation::new( + obligation.cause.clone(), + obligation.param_env, + trait_ref.to_poly_trait_predicate(), + ); + let mut selcx = SelectionContext::with_query_mode( + &self, + crate::traits::TraitQueryMode::Standard, + ); + match selcx.select_from_obligation(&obligation) { + Err(SelectionError::Ambiguous(impls)) if impls.len() > 1 => { + self.annotate_source_of_ambiguity(&mut err, &impls, predicate); + } + _ => { + if self.is_tainted_by_errors() { + err.cancel(); + return; + } + err.note(&format!("cannot satisfy `{}`", predicate)); + } + } + if let ObligationCauseCode::ItemObligation(def_id) = obligation.cause.code { self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id()); } else if let ( @@ -1674,7 +1719,10 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { ty::PredicateKind::WellFormed(arg) => { // Same hacky approach as above to avoid deluging user // with error messages. - if arg.references_error() || self.tcx.sess.has_errors() { + if arg.references_error() + || self.tcx.sess.has_errors() + || self.is_tainted_by_errors() + { return; } @@ -1682,7 +1730,10 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { } ty::PredicateKind::Subtype(data) => { - if data.references_error() || self.tcx.sess.has_errors() { + if data.references_error() + || self.tcx.sess.has_errors() + || self.is_tainted_by_errors() + { // no need to overload user in such cases return; } @@ -1694,7 +1745,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { ty::PredicateKind::Projection(data) => { let self_ty = data.projection_ty.self_ty(); let ty = data.ty; - if predicate.references_error() { + if predicate.references_error() || self.is_tainted_by_errors() { return; } if self_ty.needs_infer() && ty.needs_infer() { @@ -1722,7 +1773,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { } _ => { - if self.tcx.sess.has_errors() { + if self.tcx.sess.has_errors() || self.is_tainted_by_errors() { return; } let mut err = struct_span_err!( @@ -1740,6 +1791,96 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { err.emit(); } + fn annotate_source_of_ambiguity( + &self, + err: &mut DiagnosticBuilder<'tcx>, + impls: &[DefId], + predicate: ty::Predicate<'tcx>, + ) { + let mut spans = vec![]; + let mut crates = vec![]; + let mut post = vec![]; + for def_id in impls { + match self.tcx.span_of_impl(*def_id) { + Ok(span) => spans.push(self.tcx.sess.source_map().guess_head_span(span)), + Err(name) => { + crates.push(name); + if let Some(header) = to_pretty_impl_header(self.tcx, *def_id) { + post.push(header); + } + } + } + } + let msg = format!("multiple `impl`s satisfying `{}` found", predicate); + let mut crate_names: Vec<_> = crates.iter().map(|n| format!("`{}`", n)).collect(); + crate_names.sort(); + crate_names.dedup(); + post.sort(); + post.dedup(); + + if self.is_tainted_by_errors() + && crate_names.len() == 1 + && crate_names[0] == "`core`" + && spans.len() == 0 + { + // Avoid complaining about other inference issues for expressions like + // `42 >> 1`, where the types are still `{integer}`, but we want to + // Do we need `trait_ref.skip_binder().self_ty().is_numeric() &&` too? + err.cancel(); + return; + } + let post = if post.len() > 4 { + format!( + ":\n{}\nand {} more", + post.iter().map(|p| format!("- {}", p)).take(4).collect::>().join("\n"), + post.len() - 4, + ) + } else if post.len() > 1 || (post.len() == 1 && post[0].contains('\n')) { + format!(":\n{}", post.iter().map(|p| format!("- {}", p)).collect::>().join("\n"),) + } else if post.len() == 1 { + format!(": `{}`", post[0]) + } else { + String::new() + }; + + match (spans.len(), crates.len(), crate_names.len()) { + (0, 0, 0) => { + err.note(&format!("cannot satisfy `{}`", predicate)); + } + (0, _, 1) => { + err.note(&format!("{} in the `{}` crate{}", msg, crates[0], post,)); + } + (0, _, _) => { + err.note(&format!( + "{} in the following crates: {}{}", + msg, + crate_names.join(", "), + post, + )); + } + (_, 0, 0) => { + let span: MultiSpan = spans.into(); + err.span_note(span, &msg); + } + (_, 1, 1) => { + let span: MultiSpan = spans.into(); + err.span_note(span, &msg); + err.note( + &format!("and another `impl` found in the `{}` crate{}", crates[0], post,), + ); + } + _ => { + let span: MultiSpan = spans.into(); + err.span_note(span, &msg); + err.note(&format!( + "and more `impl`s found in the following crates: {}{}", + crate_names.join(", "), + post, + )); + } + } + } + /// Returns `true` if the trait predicate may apply for *some* assignment /// to the type parameters. fn predicate_can_apply( @@ -1856,23 +1997,31 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { let sized_trait = self.tcx.lang_items().sized_trait(); debug!("maybe_suggest_unsized_generics: generics.params={:?}", generics.params); debug!("maybe_suggest_unsized_generics: generics.where_clause={:?}", generics.where_clause); - let param = generics - .params - .iter() - .filter(|param| param.span == span) - .filter(|param| { - // Check that none of the explicit trait bounds is `Sized`. Assume that an explicit - // `Sized` bound is there intentionally and we don't need to suggest relaxing it. - param - .bounds - .iter() - .all(|bound| bound.trait_ref().and_then(|tr| tr.trait_def_id()) != sized_trait) - }) - .next(); + let param = generics.params.iter().filter(|param| param.span == span).find(|param| { + // Check that none of the explicit trait bounds is `Sized`. Assume that an explicit + // `Sized` bound is there intentionally and we don't need to suggest relaxing it. + param + .bounds + .iter() + .all(|bound| bound.trait_ref().and_then(|tr| tr.trait_def_id()) != sized_trait) + }); let param = match param { Some(param) => param, _ => return, }; + let param_def_id = self.tcx.hir().local_def_id(param.hir_id).to_def_id(); + let preds = generics.where_clause.predicates.iter(); + let explicitly_sized = preds + .filter_map(|pred| match pred { + hir::WherePredicate::BoundPredicate(bp) => Some(bp), + _ => None, + }) + .filter(|bp| bp.is_param_bound(param_def_id)) + .flat_map(|bp| bp.bounds) + .any(|bound| bound.trait_ref().and_then(|tr| tr.trait_def_id()) == sized_trait); + if explicitly_sized { + return; + } debug!("maybe_suggest_unsized_generics: param={:?}", param); match node { hir::Node::Item( 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 1a8f863952..a90140a9b5 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -27,7 +27,7 @@ use rustc_middle::ty::{TypeAndMut, TypeckResults}; use rustc_session::Limit; use rustc_span::def_id::LOCAL_CRATE; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::{BytePos, DesugaringKind, ExpnKind, ForLoopLoc, MultiSpan, Span, DUMMY_SP}; +use rustc_span::{BytePos, DesugaringKind, ExpnKind, MultiSpan, Span, DUMMY_SP}; use rustc_target::spec::abi; use std::fmt; @@ -151,7 +151,7 @@ pub trait InferCtxtExt<'tcx> { outer_generator: Option, trait_ref: ty::TraitRef<'tcx>, target_ty: Ty<'tcx>, - typeck_results: &ty::TypeckResults<'tcx>, + typeck_results: Option<&ty::TypeckResults<'tcx>>, obligation: &PredicateObligation<'tcx>, next_code: Option<&ObligationCauseCode<'tcx>>, ); @@ -290,27 +290,25 @@ fn suggest_restriction( } else { // Trivial case: `T` needs an extra bound: `T: Bound`. let (sp, suggestion) = match ( - generics.params.iter().find(|p| { - !matches!(p.kind, hir::GenericParamKind::Type { synthetic: Some(_), .. }) - }), + generics + .params + .iter() + .find(|p| !matches!(p.kind, hir::GenericParamKind::Type { synthetic: true, .. })), super_traits, ) { (_, None) => predicate_constraint( generics, trait_ref.without_const().to_predicate(tcx).to_string(), ), - (None, Some((ident, []))) => ( - ident.span.shrink_to_hi(), - format!(": {}", trait_ref.print_only_trait_path().to_string()), - ), - (_, Some((_, [.., bounds]))) => ( - bounds.span().shrink_to_hi(), - format!(" + {}", trait_ref.print_only_trait_path().to_string()), - ), - (Some(_), Some((_, []))) => ( - generics.span.shrink_to_hi(), - format!(": {}", trait_ref.print_only_trait_path().to_string()), - ), + (None, Some((ident, []))) => { + (ident.span.shrink_to_hi(), format!(": {}", trait_ref.print_only_trait_path())) + } + (_, Some((_, [.., bounds]))) => { + (bounds.span().shrink_to_hi(), format!(" + {}", trait_ref.print_only_trait_path())) + } + (Some(_), Some((_, []))) => { + (generics.span.shrink_to_hi(), format!(": {}", trait_ref.print_only_trait_path())) + } }; err.span_suggestion_verbose( @@ -687,7 +685,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &obligation.cause.code { parent_code.clone() - } else if let ExpnKind::Desugaring(DesugaringKind::ForLoop(ForLoopLoc::IntoIter)) = + } else if let ExpnKind::Desugaring(DesugaringKind::ForLoop) = span.ctxt().outer_expn_data().kind { Lrc::new(obligation.cause.code.clone()) @@ -709,36 +707,29 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } let param_env = obligation.param_env; - let trait_ref = poly_trait_ref.skip_binder(); - - let found_ty = trait_ref.self_ty(); - let found_ty_str = found_ty.to_string(); - let imm_borrowed_found_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, found_ty); - let imm_substs = self.tcx.mk_substs_trait(imm_borrowed_found_ty, &[]); - let mut_borrowed_found_ty = self.tcx.mk_mut_ref(self.tcx.lifetimes.re_static, found_ty); - let mut_substs = self.tcx.mk_substs_trait(mut_borrowed_found_ty, &[]); // Try to apply the original trait binding obligation by borrowing. - let mut try_borrowing = |new_imm_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, - new_mut_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, - expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, + let mut try_borrowing = |old_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, blacklist: &[DefId]| -> bool { - if blacklist.contains(&expected_trait_ref.def_id()) { + if blacklist.contains(&old_ref.def_id()) { return false; } - let imm_result = self.predicate_must_hold_modulo_regions(&Obligation::new( - ObligationCause::dummy(), - param_env, - new_imm_trait_ref.without_const().to_predicate(self.tcx), - )); - - let mut_result = self.predicate_must_hold_modulo_regions(&Obligation::new( - ObligationCause::dummy(), - param_env, - new_mut_trait_ref.without_const().to_predicate(self.tcx), - )); + let orig_ty = old_ref.self_ty().skip_binder(); + let mk_result = |new_ty| { + let new_ref = old_ref.rebind(ty::TraitRef::new( + old_ref.def_id(), + self.tcx.mk_substs_trait(new_ty, &old_ref.skip_binder().substs[1..]), + )); + self.predicate_must_hold_modulo_regions(&Obligation::new( + ObligationCause::dummy(), + param_env, + new_ref.without_const().to_predicate(self.tcx), + )) + }; + let imm_result = mk_result(self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, orig_ty)); + let mut_result = mk_result(self.tcx.mk_mut_ref(self.tcx.lifetimes.re_static, orig_ty)); if imm_result || mut_result { if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { @@ -750,8 +741,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let msg = format!( "the trait bound `{}: {}` is not satisfied", - found_ty_str, - expected_trait_ref.print_only_trait_path(), + orig_ty.to_string(), + old_ref.print_only_trait_path(), ); if has_custom_message { err.note(&msg); @@ -767,15 +758,14 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { span, &format!( "expected an implementor of trait `{}`", - expected_trait_ref.print_only_trait_path(), + old_ref.print_only_trait_path(), ), ); // This if is to prevent a special edge-case if matches!( span.ctxt().outer_expn_data().kind, - ExpnKind::Root - | ExpnKind::Desugaring(DesugaringKind::ForLoop(ForLoopLoc::IntoIter)) + ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) ) { // We don't want a borrowing suggestion on the fields in structs, // ``` @@ -810,21 +800,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { }; if let ObligationCauseCode::ImplDerivedObligation(obligation) = &*code { - let expected_trait_ref = obligation.parent_trait_ref; - let new_imm_trait_ref = poly_trait_ref - .rebind(ty::TraitRef::new(obligation.parent_trait_ref.def_id(), imm_substs)); - let new_mut_trait_ref = poly_trait_ref - .rebind(ty::TraitRef::new(obligation.parent_trait_ref.def_id(), mut_substs)); - return try_borrowing(new_imm_trait_ref, new_mut_trait_ref, expected_trait_ref, &[]); + try_borrowing(obligation.parent_trait_ref, &[]) } else if let ObligationCauseCode::BindingObligation(_, _) | ObligationCauseCode::ItemObligation(_) = &*code { - return try_borrowing( - poly_trait_ref.rebind(ty::TraitRef::new(trait_ref.def_id, imm_substs)), - poly_trait_ref.rebind(ty::TraitRef::new(trait_ref.def_id, mut_substs)), - *poly_trait_ref, - &never_suggest_borrow[..], - ); + try_borrowing(*poly_trait_ref, &never_suggest_borrow[..]) } else { false } @@ -1038,13 +1018,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let hir = self.tcx.hir(); let parent_node = hir.get_parent_node(obligation.cause.body_id); let node = hir.find(parent_node); - let (sig, body_id) = if let Some(hir::Node::Item(hir::Item { + let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. })) = node - { - (sig, body_id) - } else { + else { return false; }; let body = hir.body(*body_id); @@ -1427,6 +1405,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { while let Some(code) = next_code { debug!("maybe_note_obligation_cause_for_async_await: code={:?}", code); match code { + ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => { + next_code = Some(parent_code.as_ref()); + } ObligationCauseCode::DerivedObligation(derived_obligation) | ObligationCauseCode::BuiltinDerivedObligation(derived_obligation) | ObligationCauseCode::ImplDerivedObligation(derived_obligation) => { @@ -1465,11 +1446,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } // Only continue if a generator was found. - debug!( - "maybe_note_obligation_cause_for_async_await: generator={:?} trait_ref={:?} \ - target_ty={:?}", - generator, trait_ref, target_ty - ); + debug!(?generator, ?trait_ref, ?target_ty, "maybe_note_obligation_cause_for_async_await"); let (generator_did, trait_ref, target_ty) = match (generator, trait_ref, target_ty) { (Some(generator_did), Some(trait_ref), Some(target_ty)) => { (generator_did, trait_ref, target_ty) @@ -1479,16 +1456,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let span = self.tcx.def_span(generator_did); - // Do not ICE on closure typeck (#66868). - if !generator_did.is_local() { - return false; - } - - // Get the typeck results from the infcx if the generator is the function we are - // currently type-checking; otherwise, get them by performing a query. - // This is needed to avoid cycles. let in_progress_typeck_results = self.in_progress_typeck_results.map(|t| t.borrow()); - let generator_did_root = self.tcx.closure_base_def_id(generator_did); + let generator_did_root = self.tcx.typeck_root_def_id(generator_did); debug!( "maybe_note_obligation_cause_for_async_await: generator_did={:?} \ generator_did_root={:?} in_progress_typeck_results.hir_owner={:?} span={:?}", @@ -1497,14 +1466,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { in_progress_typeck_results.as_ref().map(|t| t.hir_owner), span ); - let query_typeck_results; - let typeck_results: &TypeckResults<'tcx> = match &in_progress_typeck_results { - Some(t) if t.hir_owner.to_def_id() == generator_did_root => t, - _ => { - query_typeck_results = self.tcx.typeck(generator_did.expect_local()); - &query_typeck_results - } - }; let generator_body = generator_did .as_local() @@ -1547,51 +1508,59 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let mut interior_or_upvar_span = None; let mut interior_extra_info = None; - if let Some(upvars) = self.tcx.upvars_mentioned(generator_did) { - interior_or_upvar_span = upvars.iter().find_map(|(upvar_id, upvar)| { - let upvar_ty = typeck_results.node_type(*upvar_id); - let upvar_ty = self.resolve_vars_if_possible(upvar_ty); - if ty_matches(ty::Binder::dummy(upvar_ty)) { - Some(GeneratorInteriorOrUpvar::Upvar(upvar.span)) - } else { - None - } - }); + // Get the typeck results from the infcx if the generator is the function we are currently + // type-checking; otherwise, get them by performing a query. This is needed to avoid + // cycles. If we can't use resolved types because the generator comes from another crate, + // we still provide a targeted error but without all the relevant spans. + let query_typeck_results; + let typeck_results: Option<&TypeckResults<'tcx>> = match &in_progress_typeck_results { + Some(t) if t.hir_owner.to_def_id() == generator_did_root => Some(&t), + _ if generator_did.is_local() => { + query_typeck_results = self.tcx.typeck(generator_did.expect_local()); + Some(&query_typeck_results) + } + _ => None, // Do not ICE on closure typeck (#66868). }; + if let Some(typeck_results) = typeck_results { + if let Some(upvars) = self.tcx.upvars_mentioned(generator_did) { + interior_or_upvar_span = upvars.iter().find_map(|(upvar_id, upvar)| { + let upvar_ty = typeck_results.node_type(*upvar_id); + let upvar_ty = self.resolve_vars_if_possible(upvar_ty); + if ty_matches(ty::Binder::dummy(upvar_ty)) { + Some(GeneratorInteriorOrUpvar::Upvar(upvar.span)) + } else { + None + } + }); + }; - // The generator interior types share the same binders - if let Some(cause) = - typeck_results.generator_interior_types.as_ref().skip_binder().iter().find( - |ty::GeneratorInteriorTypeCause { ty, .. }| { - ty_matches(typeck_results.generator_interior_types.rebind(ty)) - }, - ) - { - // Check to see if any awaited expressions have the target type. - let from_awaited_ty = visitor - .awaits - .into_iter() - .map(|id| hir.expect_expr(id)) - .find(|await_expr| { - let ty = typeck_results.expr_ty_adjusted(&await_expr); - debug!( - "maybe_note_obligation_cause_for_async_await: await_expr={:?}", - await_expr - ); - ty_matches(ty::Binder::dummy(ty)) - }) - .map(|expr| expr.span); - let ty::GeneratorInteriorTypeCause { span, scope_span, yield_span, expr, .. } = cause; + // The generator interior types share the same binders + if let Some(cause) = + typeck_results.generator_interior_types.as_ref().skip_binder().iter().find( + |ty::GeneratorInteriorTypeCause { ty, .. }| { + ty_matches(typeck_results.generator_interior_types.rebind(ty)) + }, + ) + { + // Check to see if any awaited expressions have the target type. + let from_awaited_ty = visitor + .awaits + .into_iter() + .map(|id| hir.expect_expr(id)) + .find(|await_expr| { + ty_matches(ty::Binder::dummy(typeck_results.expr_ty_adjusted(&await_expr))) + }) + .map(|expr| expr.span); + let ty::GeneratorInteriorTypeCause { span, scope_span, yield_span, expr, .. } = + cause; - interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(*span)); - interior_extra_info = Some((*scope_span, *yield_span, *expr, from_awaited_ty)); - }; + interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(*span)); + interior_extra_info = Some((*scope_span, *yield_span, *expr, from_awaited_ty)); + }; + } else { + interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(span)); + } - debug!( - "maybe_note_obligation_cause_for_async_await: interior_or_upvar={:?} \ - generator_interior_types={:?}", - interior_or_upvar_span, typeck_results.generator_interior_types - ); if let Some(interior_or_upvar_span) = interior_or_upvar_span { self.note_obligation_cause_for_async_await( err, @@ -1622,7 +1591,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { outer_generator: Option, trait_ref: ty::TraitRef<'tcx>, target_ty: Ty<'tcx>, - typeck_results: &ty::TypeckResults<'tcx>, + typeck_results: Option<&ty::TypeckResults<'tcx>>, obligation: &PredicateObligation<'tcx>, next_code: Option<&ObligationCauseCode<'tcx>>, ) { @@ -1833,7 +1802,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // Look at the last interior type to get a span for the `.await`. debug!( "note_obligation_cause_for_async_await generator_interior_types: {:#?}", - typeck_results.generator_interior_types + typeck_results.as_ref().map(|t| &t.generator_interior_types) ); explain_yield(interior_span, yield_span, scope_span); } @@ -1854,10 +1823,14 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // ^^^^^^^ a temporary `&T` created inside this method call due to `&self` // ``` // - let is_region_borrow = typeck_results - .expr_adjustments(expr) - .iter() - .any(|adj| adj.is_region_borrow()); + let is_region_borrow = if let Some(typeck_results) = typeck_results { + typeck_results + .expr_adjustments(expr) + .iter() + .any(|adj| adj.is_region_borrow()) + } else { + false + }; // ```rust // struct Foo(*const u8); @@ -1870,15 +1843,16 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { DefKind::Fn | DefKind::Ctor(..) => target_ty.is_unsafe_ptr(), _ => false, }; - - if (typeck_results.is_method_call(e) && is_region_borrow) - || is_raw_borrow_inside_fn_like_call - { - err.span_help( - parent_span, - "consider moving this into a `let` \ + if let Some(typeck_results) = typeck_results { + if (typeck_results.is_method_call(e) && is_region_borrow) + || is_raw_borrow_inside_fn_like_call + { + err.span_help( + parent_span, + "consider moving this into a `let` \ binding to create a shorter lived borrow", - ); + ); + } } } } @@ -1983,15 +1957,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { region, object_ty, )); } - ObligationCauseCode::ItemObligation(item_def_id) => { - let item_name = tcx.def_path_str(item_def_id); - let msg = format!("required by `{}`", item_name); - let sp = tcx - .hir() - .span_if_local(item_def_id) - .unwrap_or_else(|| tcx.def_span(item_def_id)); - let sp = tcx.sess.source_map().guess_head_span(sp); - err.span_note(sp, &msg); + ObligationCauseCode::ItemObligation(_item_def_id) => { + // We hold the `DefId` of the item introducing the obligation, but displaying it + // doesn't add user usable information. It always point at an associated item. } ObligationCauseCode::BindingObligation(item_def_id, span) => { let item_name = tcx.def_path_str(item_def_id); @@ -2363,11 +2331,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ) }); } - ObligationCauseCode::CompareImplMethodObligation { - item_name, - trait_item_def_id, - .. - } => { + ObligationCauseCode::CompareImplMethodObligation { trait_item_def_id, .. } => { + let item_name = self.tcx.item_name(trait_item_def_id); let msg = format!( "the requirement `{}` appears on the impl method `{}` but not on the \ corresponding trait method", @@ -2392,9 +2357,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } err.span_note(assoc_span, &msg); } - ObligationCauseCode::CompareImplTypeObligation { - item_name, trait_item_def_id, .. - } => { + ObligationCauseCode::CompareImplTypeObligation { trait_item_def_id, .. } => { + let item_name = self.tcx.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", @@ -2484,13 +2448,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { obligation.param_env, ); - let item_def_id = self - .tcx - .associated_items(future_trait) - .in_definition_order() - .next() - .unwrap() - .def_id; + let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0]; // `::Output` let projection_ty = ty::ProjectionTy { // `T` diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 465d1465d5..e121837c98 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -126,10 +126,7 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> { } /// Attempts to select obligations using `selcx`. - fn select( - &mut self, - selcx: &mut SelectionContext<'a, 'tcx>, - ) -> Result<(), Vec>> { + fn select(&mut self, selcx: &mut SelectionContext<'a, 'tcx>) -> Vec> { let span = debug_span!("select", obligation_forest_size = ?self.predicates.len()); let _enter = span.enter(); @@ -163,7 +160,7 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> { errors.len() ); - if errors.is_empty() { Ok(()) } else { Err(errors) } + errors } } @@ -223,41 +220,36 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { .register_obligation(PendingPredicateObligation { obligation, stalled_on: vec![] }); } - fn select_all_or_error( - &mut self, - infcx: &InferCtxt<'_, 'tcx>, - ) -> Result<(), Vec>> { - self.select_where_possible(infcx)?; - - let errors: Vec<_> = self - .predicates - .to_errors(CodeAmbiguity) - .into_iter() - .map(to_fulfillment_error) - .collect(); - if errors.is_empty() { Ok(()) } else { Err(errors) } + fn select_all_or_error(&mut self, infcx: &InferCtxt<'_, 'tcx>) -> Vec> { + { + let errors = self.select_where_possible(infcx); + if !errors.is_empty() { + return errors; + } + } + + self.predicates.to_errors(CodeAmbiguity).into_iter().map(to_fulfillment_error).collect() } fn select_all_with_constness_or_error( &mut self, infcx: &InferCtxt<'_, 'tcx>, constness: rustc_hir::Constness, - ) -> Result<(), Vec>> { - self.select_with_constness_where_possible(infcx, constness)?; - - let errors: Vec<_> = self - .predicates - .to_errors(CodeAmbiguity) - .into_iter() - .map(to_fulfillment_error) - .collect(); - if errors.is_empty() { Ok(()) } else { Err(errors) } + ) -> Vec> { + { + let errors = self.select_with_constness_where_possible(infcx, constness); + if !errors.is_empty() { + return errors; + } + } + + self.predicates.to_errors(CodeAmbiguity).into_iter().map(to_fulfillment_error).collect() } fn select_where_possible( &mut self, infcx: &InferCtxt<'_, 'tcx>, - ) -> Result<(), Vec>> { + ) -> Vec> { let mut selcx = SelectionContext::new(infcx); self.select(&mut selcx) } @@ -266,7 +258,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { &mut self, infcx: &InferCtxt<'_, 'tcx>, constness: hir::Constness, - ) -> Result<(), Vec>> { + ) -> Vec> { let mut selcx = SelectionContext::with_constness(infcx, constness); self.select(&mut selcx) } diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index cedd1aa54b..fa8890fc35 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -33,7 +33,8 @@ pub fn can_type_implement_copy( | ty::Char | ty::RawPtr(..) | ty::Never - | ty::Ref(_, _, hir::Mutability::Not) => return Ok(()), + | ty::Ref(_, _, hir::Mutability::Not) + | ty::Array(..) => return Ok(()), ty::Adt(adt, substs) => (adt, substs), diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index b31d6d68b0..4bc22d5d73 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -65,7 +65,8 @@ pub use self::specialize::{specialization_graph, translate_substs, OverlapError} pub use self::structural_match::search_for_structural_match_violation; pub use self::structural_match::NonStructuralMatchTy; pub use self::util::{ - elaborate_obligations, elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs, + elaborate_obligations, elaborate_predicates, elaborate_predicates_with_span, + elaborate_trait_ref, elaborate_trait_refs, }; pub use self::util::{expand_trait_aliases, TraitAliasExpander}; pub use self::util::{ @@ -81,9 +82,14 @@ pub use self::chalk_fulfill::FulfillmentContext as ChalkFulfillmentContext; pub use rustc_infer::traits::*; /// Whether to skip the leak check, as part of a future compatibility warning step. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +/// +/// The "default" for skip-leak-check corresponds to the current +/// behavior (do not skip the leak check) -- not the behavior we are +/// transitioning into. +#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)] pub enum SkipLeakCheck { Yes, + #[default] No, } @@ -93,15 +99,6 @@ impl SkipLeakCheck { } } -/// The "default" for skip-leak-check corresponds to the current -/// behavior (do not skip the leak check) -- not the behavior we are -/// transitioning into. -impl Default for SkipLeakCheck { - fn default() -> Self { - SkipLeakCheck::No - } -} - /// The mode that trait queries run in. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum TraitQueryMode { @@ -180,8 +177,8 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>( // Note: we only assume something is `Copy` if we can // *definitively* show that it implements `Copy`. Otherwise, // assume it is move; linear is always ok. - match fulfill_cx.select_all_or_error(infcx) { - Ok(()) => { + match fulfill_cx.select_all_or_error(infcx).as_slice() { + [] => { debug!( "type_known_to_meet_bound_modulo_regions: ty={:?} bound={} success", ty, @@ -189,12 +186,12 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>( ); true } - Err(e) => { + errors => { debug!( - "type_known_to_meet_bound_modulo_regions: ty={:?} bound={} errors={:?}", - ty, - infcx.tcx.def_path_str(def_id), - e + ?ty, + bound = %infcx.tcx.def_path_str(def_id), + ?errors, + "type_known_to_meet_bound_modulo_regions" ); false } @@ -410,7 +407,10 @@ where } debug!("fully_normalize: select_all_or_error start"); - fulfill_cx.select_all_or_error(infcx)?; + let errors = fulfill_cx.select_all_or_error(infcx); + if !errors.is_empty() { + return Err(errors); + } debug!("fully_normalize: select_all_or_error complete"); let resolved_value = infcx.resolve_vars_if_possible(normalized_value); debug!("fully_normalize: resolved_value={:?}", resolved_value); @@ -441,7 +441,9 @@ pub fn impossible_predicates<'tcx>( fulfill_cx.register_predicate_obligation(&infcx, obligation); } - fulfill_cx.select_all_or_error(&infcx).is_err() + let errors = fulfill_cx.select_all_or_error(&infcx); + + !errors.is_empty() }); debug!("impossible_predicates = {:?}", result); result @@ -748,6 +750,9 @@ fn vtable_trait_first_method_offset<'tcx>( ) -> usize { let (trait_to_be_found, trait_owning_vtable) = key; + // #90177 + let trait_to_be_found_erased = tcx.erase_regions(trait_to_be_found); + let vtable_segment_callback = { let mut vtable_base = 0; @@ -757,7 +762,7 @@ fn vtable_trait_first_method_offset<'tcx>( vtable_base += COMMON_VTABLE_ENTRIES.len(); } VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => { - if trait_ref == trait_to_be_found { + if tcx.erase_regions(trait_ref) == trait_to_be_found_erased { return ControlFlow::Break(vtable_base); } vtable_base += util::count_own_vtable_entries(tcx, trait_ref); @@ -804,6 +809,7 @@ pub fn vtable_trait_upcasting_coercion_new_vptr_slot( ty::Binder::dummy(ty::TraitPredicate { trait_ref, constness: ty::BoundConstness::NotConst, + polarity: ty::ImplPolarity::Positive, }), ); diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 0bb00dfeb4..afc546540d 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -647,9 +647,7 @@ fn receiver_is_dispatchable<'tcx>( debug!("receiver_is_dispatchable: method = {:?}, receiver_ty = {:?}", method, receiver_ty); let traits = (tcx.lang_items().unsize_trait(), tcx.lang_items().dispatch_from_dyn_trait()); - let (unsize_did, dispatch_from_dyn_did) = if let (Some(u), Some(cu)) = traits { - (u, cu) - } else { + let (Some(unsize_did), Some(dispatch_from_dyn_did)) = traits else { debug!("receiver_is_dispatchable: Missing Unsize or DispatchFromDyn traits"); return false; }; @@ -839,14 +837,13 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>( // constants which are not considered const evaluatable. use rustc_middle::thir::abstract_const::Node; if let Ok(Some(ct)) = AbstractConst::new(self.tcx, uv.shrink()) { - const_evaluatable::walk_abstract_const(self.tcx, ct, |node| match node.root() { - Node::Leaf(leaf) => { - let leaf = leaf.subst(self.tcx, ct.substs); - self.visit_const(leaf) - } - Node::Cast(_, _, ty) => self.visit_ty(ty), - Node::Binop(..) | Node::UnaryOp(..) | Node::FunctionCall(_, _) => { - ControlFlow::CONTINUE + const_evaluatable::walk_abstract_const(self.tcx, ct, |node| { + match node.root(self.tcx) { + Node::Leaf(leaf) => self.visit_const(leaf), + Node::Cast(_, _, ty) => self.visit_ty(ty), + Node::Binop(..) | Node::UnaryOp(..) | Node::FunctionCall(_, _) => { + ControlFlow::CONTINUE + } } }) } else { diff --git a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs index 209fd83b3a..85ca4db7d7 100644 --- a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs @@ -164,9 +164,7 @@ impl<'tcx> OnUnimplementedDirective { ) -> Result, ErrorReported> { let attrs = tcx.get_attrs(impl_def_id); - let attr = if let Some(item) = tcx.sess.find_by_name(&attrs, sym::rustc_on_unimplemented) { - item - } else { + let Some(attr) = tcx.sess.find_by_name(&attrs, sym::rustc_on_unimplemented) else { return Ok(None); }; diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index db8a6d9620..4a23206402 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -20,6 +20,7 @@ use super::{Normalized, NormalizedTy, ProjectionCacheEntry, ProjectionCacheKey}; use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime}; use crate::traits::error_reporting::InferCtxtExt as _; +use rustc_data_structures::sso::SsoHashSet; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::ErrorReported; use rustc_hir::def_id::DefId; @@ -944,9 +945,14 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( Normalized { value: projected_ty, obligations: projected_obligations } }; + let mut deduped: SsoHashSet<_> = Default::default(); let mut canonical = SelectionContext::with_query_mode(selcx.infcx(), TraitQueryMode::Canonical); + result.obligations.drain_filter(|projected_obligation| { + if !deduped.insert(projected_obligation.clone()) { + return true; + } // If any global obligations always apply, considering regions, then we don't // need to include them. The `is_global` check rules out inference variables, // so there's no need for the caller of `opt_normalize_projection_type` @@ -1734,7 +1740,7 @@ fn confirm_callable_candidate<'cx, 'tcx>( ty: ret_type, }); - confirm_param_env_candidate(selcx, obligation, predicate, false) + confirm_param_env_candidate(selcx, obligation, predicate, true) } fn confirm_param_env_candidate<'cx, 'tcx>( @@ -1754,8 +1760,18 @@ fn confirm_param_env_candidate<'cx, 'tcx>( ); let cache_projection = cache_entry.projection_ty; - let obligation_projection = obligation.predicate; let mut nested_obligations = Vec::new(); + let obligation_projection = obligation.predicate; + let obligation_projection = ensure_sufficient_stack(|| { + normalize_with_depth_to( + selcx, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + obligation_projection, + &mut nested_obligations, + ) + }); let cache_projection = if potentially_unnormalized_candidate { ensure_sufficient_stack(|| { normalize_with_depth_to( @@ -1771,6 +1787,8 @@ fn confirm_param_env_candidate<'cx, 'tcx>( cache_projection }; + debug!(?cache_projection, ?obligation_projection); + match infcx.at(cause, param_env).eq(cache_projection, obligation_projection) { Ok(InferOk { value: _, obligations }) => { nested_obligations.extend(obligations); diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs index b5398f8a43..0a85676f43 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs @@ -77,10 +77,11 @@ fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>( let InferOk { value, obligations } = infcx.commit_if_ok(|_| op())?; debug_assert!(obligations.iter().all(|o| o.cause.body_id == dummy_body_id)); fulfill_cx.register_predicate_obligations(infcx, obligations); - if let Err(e) = fulfill_cx.select_all_or_error(infcx) { + let errors = fulfill_cx.select_all_or_error(infcx); + if !errors.is_empty() { infcx.tcx.sess.diagnostic().delay_span_bug( DUMMY_SP, - &format!("errors selecting obligation during MIR typeck: {:?}", e), + &format!("errors selecting obligation during MIR typeck: {:?}", errors), ); } diff --git a/compiler/rustc_trait_selection/src/traits/relationships.rs b/compiler/rustc_trait_selection/src/traits/relationships.rs index 7751dd84f4..e0098cc92d 100644 --- a/compiler/rustc_trait_selection/src/traits/relationships.rs +++ b/compiler/rustc_trait_selection/src/traits/relationships.rs @@ -44,6 +44,7 @@ pub(crate) fn update<'tcx, T>( ty::PredicateKind::Trait(ty::TraitPredicate { trait_ref, constness: predicate.constness, + polarity: predicate.polarity, }) }) .to_predicate(infcx.tcx), diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 856ea43b1f..6e3e3b9b14 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -18,7 +18,7 @@ use crate::traits; use crate::traits::coherence::Conflict; use crate::traits::query::evaluate_obligation::InferCtxtExt; use crate::traits::{util, SelectionResult}; -use crate::traits::{ErrorReporting, Overflow, Unimplemented}; +use crate::traits::{Ambiguous, ErrorReporting, Overflow, Unimplemented}; use super::BuiltinImplConditions; use super::IntercrateAmbiguityCause; @@ -121,7 +121,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return Ok(None); } - let mut candidates = candidate_set.vec; + let candidates = candidate_set.vec; debug!(?stack, ?candidates, "assembled {} candidates", candidates.len()); @@ -134,6 +134,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // candidate which assumes $0 == int, one that assumes `$0 == // usize`, etc. This spells an ambiguity. + let mut candidates = self.filter_impls(candidates, stack.obligation); + // If there is more than one candidate, first winnow them down // by considering extra conditions (nested obligations and so // forth). We don't winnow if there is exactly one @@ -149,7 +151,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Instead, we select the right impl now but report "`Bar` does // not implement `Clone`". if candidates.len() == 1 { - return self.filter_impls(candidates.pop().unwrap(), stack.obligation); + return self.filter_reservation_impls(candidates.pop().unwrap(), stack.obligation); } // Winnow, but record the exact outcome of evaluation, which @@ -195,7 +197,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // and report ambiguity. if i > 1 { debug!("multiple matches, ambig"); - return Ok(None); + return Err(Ambiguous( + candidates + .into_iter() + .filter_map(|c| match c.candidate { + SelectionCandidate::ImplCandidate(def_id) => Some(def_id), + _ => None, + }) + .collect(), + )); } } } @@ -223,7 +233,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } // Just one candidate left. - self.filter_impls(candidates.pop().unwrap().candidate, stack.obligation) + self.filter_reservation_impls(candidates.pop().unwrap().candidate, stack.obligation) } #[instrument(skip(self, stack), level = "debug")] @@ -254,68 +264,75 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let mut candidates = SelectionCandidateSet { vec: Vec::new(), ambiguous: false }; - self.assemble_candidates_for_trait_alias(obligation, &mut candidates); - - // Other bounds. Consider both in-scope bounds from fn decl - // and applicable impls. There is a certain set of precedence rules here. - let def_id = obligation.predicate.def_id(); - let lang_items = self.tcx().lang_items(); - - if lang_items.copy_trait() == Some(def_id) { - debug!(obligation_self_ty = ?obligation.predicate.skip_binder().self_ty()); - - // User-defined copy impls are permitted, but only for - // structs and enums. + // The only way to prove a NotImplemented(T: Foo) predicate is via a negative impl. + // There are no compiler built-in rules for this. + if obligation.polarity() == ty::ImplPolarity::Negative { + self.assemble_candidates_for_trait_alias(obligation, &mut candidates); self.assemble_candidates_from_impls(obligation, &mut candidates); - - // For other types, we'll use the builtin rules. - let copy_conditions = self.copy_clone_conditions(obligation); - self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates); - } else if lang_items.discriminant_kind_trait() == Some(def_id) { - // `DiscriminantKind` is automatically implemented for every type. - candidates.vec.push(DiscriminantKindCandidate); - } else if lang_items.pointee_trait() == Some(def_id) { - // `Pointee` is automatically implemented for every type. - candidates.vec.push(PointeeCandidate); - } else if lang_items.sized_trait() == Some(def_id) { - // Sized is never implementable by end-users, it is - // always automatically computed. - let sized_conditions = self.sized_conditions(obligation); - self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates); - } else if lang_items.unsize_trait() == Some(def_id) { - self.assemble_candidates_for_unsizing(obligation, &mut candidates); - } else if lang_items.drop_trait() == Some(def_id) - && obligation.predicate.skip_binder().constness == ty::BoundConstness::ConstIfConst - { - if self.is_in_const_context { - self.assemble_const_drop_candidates(obligation, &mut candidates)?; - } else { - debug!("passing ~const Drop bound; in non-const context"); - // `~const Drop` when we are not in a const context has no effect. - candidates.vec.push(ConstDropCandidate) - } } else { - if lang_items.clone_trait() == Some(def_id) { - // Same builtin conditions as `Copy`, i.e., every type which has builtin support - // for `Copy` also has builtin support for `Clone`, and tuples/arrays of `Clone` - // types have builtin support for `Clone`. - let clone_conditions = self.copy_clone_conditions(obligation); - self.assemble_builtin_bound_candidates(clone_conditions, &mut candidates); - } + self.assemble_candidates_for_trait_alias(obligation, &mut candidates); + + // Other bounds. Consider both in-scope bounds from fn decl + // and applicable impls. There is a certain set of precedence rules here. + let def_id = obligation.predicate.def_id(); + let lang_items = self.tcx().lang_items(); + + if lang_items.copy_trait() == Some(def_id) { + debug!(obligation_self_ty = ?obligation.predicate.skip_binder().self_ty()); + + // User-defined copy impls are permitted, but only for + // structs and enums. + self.assemble_candidates_from_impls(obligation, &mut candidates); + + // For other types, we'll use the builtin rules. + let copy_conditions = self.copy_clone_conditions(obligation); + self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates); + } else if lang_items.discriminant_kind_trait() == Some(def_id) { + // `DiscriminantKind` is automatically implemented for every type. + candidates.vec.push(DiscriminantKindCandidate); + } else if lang_items.pointee_trait() == Some(def_id) { + // `Pointee` is automatically implemented for every type. + candidates.vec.push(PointeeCandidate); + } else if lang_items.sized_trait() == Some(def_id) { + // Sized is never implementable by end-users, it is + // always automatically computed. + let sized_conditions = self.sized_conditions(obligation); + self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates); + } else if lang_items.unsize_trait() == Some(def_id) { + self.assemble_candidates_for_unsizing(obligation, &mut candidates); + } else if lang_items.drop_trait() == Some(def_id) + && obligation.predicate.skip_binder().constness == ty::BoundConstness::ConstIfConst + { + if self.is_in_const_context { + self.assemble_const_drop_candidates(obligation, stack, &mut candidates)?; + } else { + debug!("passing ~const Drop bound; in non-const context"); + // `~const Drop` when we are not in a const context has no effect. + candidates.vec.push(ConstDropCandidate) + } + } else { + if lang_items.clone_trait() == Some(def_id) { + // Same builtin conditions as `Copy`, i.e., every type which has builtin support + // for `Copy` also has builtin support for `Clone`, and tuples/arrays of `Clone` + // types have builtin support for `Clone`. + let clone_conditions = self.copy_clone_conditions(obligation); + self.assemble_builtin_bound_candidates(clone_conditions, &mut candidates); + } - self.assemble_generator_candidates(obligation, &mut candidates); - self.assemble_closure_candidates(obligation, &mut candidates); - self.assemble_fn_pointer_candidates(obligation, &mut candidates); - self.assemble_candidates_from_impls(obligation, &mut candidates); - self.assemble_candidates_from_object_ty(obligation, &mut candidates); - } + self.assemble_generator_candidates(obligation, &mut candidates); + self.assemble_closure_candidates(obligation, &mut candidates); + self.assemble_fn_pointer_candidates(obligation, &mut candidates); + self.assemble_candidates_from_impls(obligation, &mut candidates); + self.assemble_candidates_from_object_ty(obligation, &mut candidates); + } - self.assemble_candidates_from_projected_tys(obligation, &mut candidates); - self.assemble_candidates_from_caller_bounds(stack, &mut candidates)?; - // Auto implementations have lower priority, so we only - // consider triggering a default if there is no other impl that can apply. - if candidates.vec.is_empty() { - self.assemble_candidates_from_auto_impls(obligation, &mut candidates); + self.assemble_candidates_from_projected_tys(obligation, &mut candidates); + self.assemble_candidates_from_caller_bounds(stack, &mut candidates)?; + // Auto implementations have lower priority, so we only + // consider triggering a default if there is no other impl that can apply. + if candidates.vec.is_empty() { + self.assemble_candidates_from_auto_impls(obligation, &mut candidates); + } } debug!("candidate list size: {}", candidates.vec.len()); Ok(candidates) @@ -376,7 +393,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { for bound in matching_bounds { let wc = self.evaluate_where_clause(stack, bound.value)?; if wc.may_apply() { - candidates.vec.push(ParamCandidate(bound)); + candidates.vec.push(ParamCandidate((bound, stack.obligation.polarity()))); } } @@ -519,7 +536,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // This helps us avoid overflow: see issue #72839 // Since compilation is already guaranteed to fail, this is just // to try to show the 'nicest' possible errors to the user. - if obligation.references_error() { + // We don't check for errors in the `ParamEnv` - in practice, + // it seems to cause us to be overly aggressive in deciding + // to give up searching for candidates, leading to spurious errors. + if obligation.predicate.references_error() { return; } @@ -716,9 +736,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { cause.clone(), ); - let data = if let ty::Dynamic(ref data, ..) = normalized_ty.kind() { - data - } else { + let ty::Dynamic(data, ..) = normalized_ty.kind() else { return None; }; @@ -896,9 +914,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - fn assemble_const_drop_candidates( + fn assemble_const_drop_candidates<'a>( &mut self, obligation: &TraitObligation<'tcx>, + obligation_stack: &TraitObligationStack<'a, 'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) -> Result<(), SelectionError<'tcx>> { let mut stack: Vec<(Ty<'tcx>, usize)> = vec![(obligation.self_ty().skip_binder(), 0)]; @@ -907,7 +926,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let mut noreturn = false; self.check_recursion_depth(depth, obligation)?; - let mut copy_candidates = SelectionCandidateSet { vec: Vec::new(), ambiguous: false }; + let mut new_candidates = SelectionCandidateSet { vec: Vec::new(), ambiguous: false }; let mut copy_obligation = obligation.with(obligation.predicate.rebind(ty::TraitPredicate { trait_ref: ty::TraitRef { @@ -915,15 +934,32 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { substs: self.tcx().mk_substs_trait(ty, &[]), }, constness: ty::BoundConstness::NotConst, + polarity: ty::ImplPolarity::Positive, })); copy_obligation.recursion_depth = depth + 1; - self.assemble_candidates_from_impls(©_obligation, &mut copy_candidates); + self.assemble_candidates_from_impls(©_obligation, &mut new_candidates); let copy_conditions = self.copy_clone_conditions(©_obligation); - self.assemble_builtin_bound_candidates(copy_conditions, &mut copy_candidates); - if !copy_candidates.vec.is_empty() { + self.assemble_builtin_bound_candidates(copy_conditions, &mut new_candidates); + let copy_stack = self.push_stack(obligation_stack.list(), ©_obligation); + self.assemble_candidates_from_caller_bounds(©_stack, &mut new_candidates)?; + + let const_drop_obligation = + obligation.with(obligation.predicate.rebind(ty::TraitPredicate { + trait_ref: ty::TraitRef { + def_id: self.tcx().require_lang_item(hir::LangItem::Drop, None), + substs: self.tcx().mk_substs_trait(ty, &[]), + }, + constness: ty::BoundConstness::ConstIfConst, + polarity: ty::ImplPolarity::Positive, + })); + + let const_drop_stack = self.push_stack(obligation_stack.list(), &const_drop_obligation); + self.assemble_candidates_from_caller_bounds(&const_drop_stack, &mut new_candidates)?; + + if !new_candidates.vec.is_empty() { noreturn = true; } - debug!(?copy_candidates.vec, "assemble_const_drop_candidates - copy"); + debug!(?new_candidates.vec, "assemble_const_drop_candidates"); match ty.kind() { ty::Int(_) diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index a36cb1358b..2f1f7971a7 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -58,8 +58,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ParamCandidate(param) => { - let obligations = self.confirm_param_candidate(obligation, param.value); - Ok(ImplSource::Param(obligations, param.constness)) + let obligations = self.confirm_param_candidate(obligation, param.0.value); + Ok(ImplSource::Param(obligations, param.0.constness)) } ImplCandidate(impl_def_id) => { @@ -620,23 +620,37 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { _ => bug!("closure candidate for non-closure {:?}", obligation), }; + let obligation_predicate = obligation.predicate.to_poly_trait_ref(); + let Normalized { value: obligation_predicate, mut obligations } = + ensure_sufficient_stack(|| { + normalize_with_depth( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + obligation_predicate, + ) + }); + let trait_ref = self.closure_trait_ref_unnormalized(obligation, substs); - let Normalized { value: trait_ref, mut obligations } = ensure_sufficient_stack(|| { - normalize_with_depth( - self, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth + 1, - trait_ref, - ) - }); + let Normalized { value: trait_ref, obligations: trait_ref_obligations } = + ensure_sufficient_stack(|| { + normalize_with_depth( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + trait_ref, + ) + }); debug!(?closure_def_id, ?trait_ref, ?obligations, "confirm closure candidate obligations"); + obligations.extend(trait_ref_obligations); obligations.extend(self.confirm_poly_trait_refs( obligation.cause.clone(), obligation.param_env, - obligation.predicate.to_poly_trait_ref(), + obligation_predicate, trait_ref, )?); @@ -948,52 +962,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let tail_field_ty = tcx.type_of(tail_field.did); let mut unsizing_params = GrowableBitSet::new_empty(); - if tcx.features().relaxed_struct_unsize { - for arg in tail_field_ty.walk(tcx) { - if let Some(i) = maybe_unsizing_param_idx(arg) { - unsizing_params.insert(i); - } - } - - // Ensure none of the other fields mention the parameters used - // in unsizing. - for field in prefix_fields { - for arg in tcx.type_of(field.did).walk(tcx) { - if let Some(i) = maybe_unsizing_param_idx(arg) { - unsizing_params.remove(i); - } - } + for arg in tail_field_ty.walk(tcx) { + if let Some(i) = maybe_unsizing_param_idx(arg) { + unsizing_params.insert(i); } + } - if unsizing_params.is_empty() { - return Err(Unimplemented); - } - } else { - let mut found = false; - for arg in tail_field_ty.walk(tcx) { + // Ensure none of the other fields mention the parameters used + // in unsizing. + for field in prefix_fields { + for arg in tcx.type_of(field.did).walk(tcx) { if let Some(i) = maybe_unsizing_param_idx(arg) { - unsizing_params.insert(i); - found = true; + unsizing_params.remove(i); } } - if !found { - return Err(Unimplemented); - } + } - // Ensure none of the other fields mention the parameters used - // in unsizing. - // FIXME(eddyb) cache this (including computing `unsizing_params`) - // by putting it in a query; it would only need the `DefId` as it - // looks at declared field types, not anything substituted. - for field in prefix_fields { - for arg in tcx.type_of(field.did).walk(tcx) { - if let Some(i) = maybe_unsizing_param_idx(arg) { - if unsizing_params.contains(i) { - return Err(Unimplemented); - } - } - } - } + if unsizing_params.is_empty() { + return Err(Unimplemented); } // Extract `TailField` and `TailField` from `Struct` and `Struct`. diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 85502a399d..2aa214694c 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -20,7 +20,7 @@ use super::ObligationCauseCode; use super::Selection; use super::SelectionResult; use super::TraitQueryMode; -use super::{ErrorReporting, Overflow, SelectionError, Unimplemented}; +use super::{ErrorReporting, Overflow, SelectionError}; use super::{ObligationCause, PredicateObligation, TraitObligation}; use crate::infer::{InferCtxt, InferOk, TypeFreshener}; @@ -320,10 +320,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// Returns `true` if the trait predicate is considerd `const` to this selection context. pub fn is_trait_predicate_const(&self, pred: ty::TraitPredicate<'_>) -> bool { - match pred.constness { - ty::BoundConstness::ConstIfConst if self.is_in_const_context => true, - _ => false, - } + matches!(pred.constness, ty::BoundConstness::ConstIfConst) && self.is_in_const_context } /// Returns `true` if the predicate is considered `const` to @@ -357,18 +354,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &TraitObligation<'tcx>, ) -> SelectionResult<'tcx, Selection<'tcx>> { - debug_assert!(!obligation.predicate.has_escaping_bound_vars()); - - let pec = &ProvisionalEvaluationCache::default(); - let stack = self.push_stack(TraitObligationStackList::empty(pec), obligation); - - let candidate = match self.candidate_from_obligation(&stack) { + let candidate = match self.select_from_obligation(obligation) { Err(SelectionError::Overflow) => { // In standard mode, overflow must have been caught and reported // earlier. assert!(self.query_mode == TraitQueryMode::Canonical); return Err(SelectionError::Overflow); } + Err(SelectionError::Ambiguous(_)) => { + return Ok(None); + } Err(e) => { return Err(e); } @@ -391,6 +386,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } + crate fn select_from_obligation( + &mut self, + obligation: &TraitObligation<'tcx>, + ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { + debug_assert!(!obligation.predicate.has_escaping_bound_vars()); + + let pec = &ProvisionalEvaluationCache::default(); + let stack = self.push_stack(TraitObligationStackList::empty(pec), obligation); + + self.candidate_from_obligation(&stack) + } + /////////////////////////////////////////////////////////////////////////// // EVALUATION // @@ -709,7 +716,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!(?fresh_trait_ref); - if let Some(result) = self.check_evaluation_cache(obligation.param_env, fresh_trait_ref) { + if let Some(result) = self.check_evaluation_cache( + obligation.param_env, + fresh_trait_ref, + obligation.polarity(), + ) { debug!(?result, "CACHE HIT"); return Ok(result); } @@ -739,12 +750,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let reached_depth = stack.reached_depth.get(); if reached_depth >= stack.depth { debug!(?result, "CACHE MISS"); - self.insert_evaluation_cache(obligation.param_env, fresh_trait_ref, dep_node, result); + self.insert_evaluation_cache( + obligation.param_env, + fresh_trait_ref, + obligation.polarity(), + dep_node, + result, + ); stack.cache().on_completion(stack.dfn, |fresh_trait_ref, provisional_result| { self.insert_evaluation_cache( obligation.param_env, fresh_trait_ref, + obligation.polarity(), dep_node, provisional_result.max(result), ); @@ -855,34 +873,39 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // precise still. let unbound_input_types = stack.fresh_trait_ref.value.skip_binder().substs.types().any(|ty| ty.is_fresh()); - // This check was an imperfect workaround for a bug in the old - // intercrate mode; it should be removed when that goes away. - if unbound_input_types && self.intercrate { - debug!("evaluate_stack --> unbound argument, intercrate --> ambiguous",); - // Heuristics: show the diagnostics when there are no candidates in crate. - if self.intercrate_ambiguity_causes.is_some() { - debug!("evaluate_stack: intercrate_ambiguity_causes is some"); - if let Ok(candidate_set) = self.assemble_candidates(stack) { - if !candidate_set.ambiguous && candidate_set.vec.is_empty() { - let trait_ref = stack.obligation.predicate.skip_binder().trait_ref; - let self_ty = trait_ref.self_ty(); - let cause = - with_no_trimmed_paths(|| IntercrateAmbiguityCause::DownstreamCrate { - trait_desc: trait_ref.print_only_trait_path().to_string(), - self_desc: if self_ty.has_concrete_skeleton() { - Some(self_ty.to_string()) - } else { - None - }, + + if stack.obligation.polarity() != ty::ImplPolarity::Negative { + // This check was an imperfect workaround for a bug in the old + // intercrate mode; it should be removed when that goes away. + if unbound_input_types && self.intercrate { + debug!("evaluate_stack --> unbound argument, intercrate --> ambiguous",); + // Heuristics: show the diagnostics when there are no candidates in crate. + if self.intercrate_ambiguity_causes.is_some() { + debug!("evaluate_stack: intercrate_ambiguity_causes is some"); + if let Ok(candidate_set) = self.assemble_candidates(stack) { + if !candidate_set.ambiguous && candidate_set.vec.is_empty() { + let trait_ref = stack.obligation.predicate.skip_binder().trait_ref; + let self_ty = trait_ref.self_ty(); + let cause = with_no_trimmed_paths(|| { + IntercrateAmbiguityCause::DownstreamCrate { + trait_desc: trait_ref.print_only_trait_path().to_string(), + self_desc: if self_ty.has_concrete_skeleton() { + Some(self_ty.to_string()) + } else { + None + }, + } }); - debug!(?cause, "evaluate_stack: pushing cause"); - self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause); + debug!(?cause, "evaluate_stack: pushing cause"); + self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause); + } } } + return Ok(EvaluatedToAmbig); } - return Ok(EvaluatedToAmbig); } + if unbound_input_types && stack.iter().skip(1).any(|prev| { stack.obligation.param_env == prev.obligation.param_env @@ -899,6 +922,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match self.candidate_from_obligation(stack) { Ok(Some(c)) => self.evaluate_candidate(stack, &c), + Err(SelectionError::Ambiguous(_)) => Ok(EvaluatedToAmbig), Ok(None) => Ok(EvaluatedToAmbig), Err(Overflow) => Err(OverflowError::Canonical), Err(ErrorReporting) => Err(OverflowError::ErrorReporting), @@ -977,6 +1001,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &self, param_env: ty::ParamEnv<'tcx>, trait_ref: ty::ConstnessAnd>, + polarity: ty::ImplPolarity, ) -> Option { // Neither the global nor local cache is aware of intercrate // mode, so don't do any caching. In particular, we might @@ -988,17 +1013,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let tcx = self.tcx(); if self.can_use_global_caches(param_env) { - if let Some(res) = tcx.evaluation_cache.get(¶m_env.and(trait_ref), tcx) { + if let Some(res) = tcx.evaluation_cache.get(&(param_env.and(trait_ref), polarity), tcx) + { return Some(res); } } - self.infcx.evaluation_cache.get(¶m_env.and(trait_ref), tcx) + self.infcx.evaluation_cache.get(&(param_env.and(trait_ref), polarity), tcx) } fn insert_evaluation_cache( &mut self, param_env: ty::ParamEnv<'tcx>, trait_ref: ty::ConstnessAnd>, + polarity: ty::ImplPolarity, dep_node: DepNodeIndex, result: EvaluationResult, ) { @@ -1023,13 +1050,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // FIXME: Due to #50507 this overwrites the different values // This should be changed to use HashMapExt::insert_same // when that is fixed - self.tcx().evaluation_cache.insert(param_env.and(trait_ref), dep_node, result); + self.tcx().evaluation_cache.insert( + (param_env.and(trait_ref), polarity), + dep_node, + result, + ); return; } } debug!(?trait_ref, ?result, "insert_evaluation_cache"); - self.infcx.evaluation_cache.insert(param_env.and(trait_ref), dep_node, result); + self.infcx.evaluation_cache.insert((param_env.and(trait_ref), polarity), dep_node, result); } /// For various reasons, it's possible for a subobligation @@ -1094,67 +1125,89 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { (result, dep_node) } + /// filter_impls filters constant trait obligations and candidates that have a positive impl + /// for a negative goal and a negative impl for a positive goal #[instrument(level = "debug", skip(self))] fn filter_impls( &mut self, - candidate: SelectionCandidate<'tcx>, + candidates: Vec>, obligation: &TraitObligation<'tcx>, - ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { + ) -> Vec> { let tcx = self.tcx(); - // Respect const trait obligations - if self.is_trait_predicate_const(obligation.predicate.skip_binder()) { - match candidate { - // const impl - ImplCandidate(def_id) if tcx.impl_constness(def_id) == hir::Constness::Const => {} - // const param - ParamCandidate(ty::ConstnessAnd { - constness: ty::BoundConstness::ConstIfConst, - .. - }) => {} - // auto trait impl - AutoImplCandidate(..) => {} - // generator, this will raise error in other places - // or ignore error with const_async_blocks feature - GeneratorCandidate => {} - // FnDef where the function is const - FnPointerCandidate { is_const: true } => {} - ConstDropCandidate => {} - _ => { - // reject all other types of candidates - return Err(Unimplemented); + let mut result = Vec::with_capacity(candidates.len()); + + for candidate in candidates { + // Respect const trait obligations + if self.is_trait_predicate_const(obligation.predicate.skip_binder()) { + match candidate { + // const impl + ImplCandidate(def_id) + if tcx.impl_constness(def_id) == hir::Constness::Const => {} + // const param + ParamCandidate(( + ty::ConstnessAnd { constness: ty::BoundConstness::ConstIfConst, .. }, + _, + )) => {} + // auto trait impl + AutoImplCandidate(..) => {} + // generator, this will raise error in other places + // or ignore error with const_async_blocks feature + GeneratorCandidate => {} + // FnDef where the function is const + FnPointerCandidate { is_const: true } => {} + ConstDropCandidate => {} + _ => { + // reject all other types of candidates + continue; + } + } + } + + if let ImplCandidate(def_id) = candidate { + if ty::ImplPolarity::Reservation == tcx.impl_polarity(def_id) + || obligation.polarity() == tcx.impl_polarity(def_id) + || self.allow_negative_impls + { + result.push(candidate); } + } else { + result.push(candidate); } } - // Treat negative impls as unimplemented, and reservation impls as ambiguity. + + result + } + + /// filter_reservation_impls filter reservation impl for any goal as ambiguous + #[instrument(level = "debug", skip(self))] + fn filter_reservation_impls( + &mut self, + candidate: SelectionCandidate<'tcx>, + obligation: &TraitObligation<'tcx>, + ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { + let tcx = self.tcx(); + // Treat reservation impls as ambiguity. if let ImplCandidate(def_id) = candidate { - match tcx.impl_polarity(def_id) { - ty::ImplPolarity::Negative if !self.allow_negative_impls => { - return Err(Unimplemented); - } - ty::ImplPolarity::Reservation => { - if let Some(intercrate_ambiguity_clauses) = - &mut self.intercrate_ambiguity_causes - { - let attrs = tcx.get_attrs(def_id); - let attr = tcx.sess.find_by_name(&attrs, sym::rustc_reservation_impl); - let value = attr.and_then(|a| a.value_str()); - if let Some(value) = value { - debug!( - "filter_impls: \ + if let ty::ImplPolarity::Reservation = tcx.impl_polarity(def_id) { + if let Some(intercrate_ambiguity_clauses) = &mut self.intercrate_ambiguity_causes { + let attrs = tcx.get_attrs(def_id); + let attr = tcx.sess.find_by_name(&attrs, sym::rustc_reservation_impl); + let value = attr.and_then(|a| a.value_str()); + if let Some(value) = value { + debug!( + "filter_reservation_impls: \ reservation impl ambiguity on {:?}", - def_id - ); - intercrate_ambiguity_clauses.push( - IntercrateAmbiguityCause::ReservationImpl { - message: value.to_string(), - }, - ); - } + def_id + ); + intercrate_ambiguity_clauses.push( + IntercrateAmbiguityCause::ReservationImpl { + message: value.to_string(), + }, + ); } - return Ok(None); } - _ => {} - }; + return Ok(None); + } } Ok(Some(candidate)) } @@ -1162,7 +1215,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Option { debug!("is_knowable(intercrate={:?})", self.intercrate); - if !self.intercrate { + if !self.intercrate || stack.obligation.polarity() == ty::ImplPolarity::Negative { return None; } @@ -1219,14 +1272,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if self.can_use_global_caches(param_env) { if let Some(res) = tcx .selection_cache - .get(¶m_env.and(trait_ref).with_constness(pred.constness), tcx) + .get(&(param_env.and(trait_ref).with_constness(pred.constness), pred.polarity), tcx) { return Some(res); } } self.infcx .selection_cache - .get(¶m_env.and(trait_ref).with_constness(pred.constness), tcx) + .get(&(param_env.and(trait_ref).with_constness(pred.constness), pred.polarity), tcx) } /// Determines whether can we safely cache the result @@ -1286,7 +1339,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!(?trait_ref, ?candidate, "insert_candidate_cache global"); // This may overwrite the cache with the same value. tcx.selection_cache.insert( - param_env.and(trait_ref).with_constness(pred.constness), + (param_env.and(trait_ref).with_constness(pred.constness), pred.polarity), dep_node, candidate, ); @@ -1297,7 +1350,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!(?trait_ref, ?candidate, "insert_candidate_cache local"); self.infcx.selection_cache.insert( - param_env.and(trait_ref).with_constness(pred.constness), + (param_env.and(trait_ref).with_constness(pred.constness), pred.polarity), dep_node, candidate, ); @@ -1491,8 +1544,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Check if a bound would previously have been removed when normalizing // the param_env so that it can be given the lowest priority. See // #50825 for the motivation for this. - let is_global = - |cand: &ty::PolyTraitRef<'_>| cand.is_known_global() && !cand.has_late_bound_regions(); + let is_global = |cand: &ty::PolyTraitRef<'tcx>| { + cand.is_global(self.infcx.tcx) && !cand.has_late_bound_regions() + }; // (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`, // and `DiscriminantKindCandidate` to anything else. @@ -1523,10 +1577,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ConstDropCandidate, ) => false, - (ParamCandidate(other), ParamCandidate(victim)) => { + ( + ParamCandidate((other, other_polarity)), + ParamCandidate((victim, victim_polarity)), + ) => { let same_except_bound_vars = other.value.skip_binder() == victim.value.skip_binder() && other.constness == victim.constness + && other_polarity == victim_polarity && !other.value.skip_binder().has_escaping_bound_vars(); if same_except_bound_vars { // See issue #84398. In short, we can generate multiple ParamCandidates which are @@ -1537,6 +1595,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { other.value.bound_vars().len() <= victim.value.bound_vars().len() } else if other.value == victim.value && victim.constness == ty::BoundConstness::NotConst + && other_polarity == victim_polarity { // Drop otherwise equivalent non-const candidates in favor of const candidates. true @@ -1566,11 +1625,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | TraitAliasCandidate(..) | ObjectCandidate(_) | ProjectionCandidate(_), - ) => !is_global(&cand.value), + ) => !is_global(&cand.0.value), (ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(ref cand)) => { // Prefer these to a global where-clause bound // (see issue #50825). - is_global(&cand.value) + is_global(&cand.0.value) } ( ImplCandidate(_) @@ -1586,7 +1645,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) => { // Prefer these to a global where-clause bound // (see issue #50825). - is_global(&cand.value) && other.evaluation.must_apply_modulo_regions() + is_global(&cand.0.value) && other.evaluation.must_apply_modulo_regions() } (ProjectionCandidate(i), ProjectionCandidate(j)) @@ -1800,7 +1859,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Char | ty::RawPtr(..) | ty::Never - | ty::Ref(_, _, hir::Mutability::Not) => { + | ty::Ref(_, _, hir::Mutability::Not) + | ty::Array(..) => { // Implementations provided in libcore None } @@ -1813,11 +1873,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Foreign(..) | ty::Ref(_, _, hir::Mutability::Mut) => None, - ty::Array(element_ty, _) => { - // (*) binder moved here - Where(obligation.predicate.rebind(vec![element_ty])) - } - ty::Tuple(tys) => { // (*) binder moved here Where(obligation.predicate.rebind(tys.iter().map(|k| k.expect_ty()).collect())) diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 88aca794a6..b64c555922 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -225,8 +225,18 @@ fn fulfill_implication<'a, 'tcx>( for oblig in obligations.chain(more_obligations) { fulfill_cx.register_predicate_obligation(&infcx, oblig); } - match fulfill_cx.select_all_or_error(infcx) { - Err(errors) => { + match fulfill_cx.select_all_or_error(infcx).as_slice() { + [] => { + debug!( + "fulfill_implication: an impl for {:?} specializes {:?}", + source_trait_ref, target_trait_ref + ); + + // Now resolve the *substitution* we built for the target earlier, replacing + // the inference variables inside with whatever we got from fulfillment. + Ok(infcx.resolve_vars_if_possible(target_substs)) + } + errors => { // no dice! debug!( "fulfill_implication: for impls on {:?} and {:?}, \ @@ -238,17 +248,6 @@ fn fulfill_implication<'a, 'tcx>( ); Err(()) } - - Ok(()) => { - debug!( - "fulfill_implication: an impl for {:?} specializes {:?}", - source_trait_ref, target_trait_ref - ); - - // Now resolve the *substitution* we built for the target earlier, replacing - // the inference variables inside with whatever we got from fulfillment. - Ok(infcx.resolve_vars_if_possible(target_substs)) - } } }) } @@ -292,6 +291,11 @@ pub(super) fn specialization_graph_provider( sg } +// This function is only used when +// encountering errors and inlining +// it negatively impacts perf. +#[cold] +#[inline(never)] fn report_overlap_conflict( tcx: TyCtxt<'_>, overlap: OverlapError, @@ -444,8 +448,12 @@ fn report_conflicting_impls( match used_to_be_allowed { None => { sg.has_errored = true; - let err = struct_span_err!(tcx.sess, impl_span, E0119, ""); - decorate(LintDiagnosticBuilder::new(err)); + if overlap.with_impl.is_local() || !tcx.orphan_check_crate(()).contains(&impl_def_id) { + let err = struct_span_err!(tcx.sess, impl_span, E0119, ""); + decorate(LintDiagnosticBuilder::new(err)); + } else { + tcx.sess.delay_span_bug(impl_span, "impl should have failed the orphan check"); + } } Some(kind) => { let lint = match kind { @@ -464,7 +472,7 @@ fn report_conflicting_impls( /// Recovers the "impl X for Y" signature from `impl_def_id` and returns it as a /// string. -fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option { +crate fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option { use std::fmt::Write; let trait_ref = tcx.impl_trait_ref(impl_def_id)?; diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs index ac8bab0cf3..3d71382227 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_match.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs @@ -17,6 +17,7 @@ pub enum NonStructuralMatchTy<'tcx> { Dynamic, Foreign, Opaque, + Closure, Generator, Projection, } @@ -102,7 +103,7 @@ fn type_marked_structural( // // 2. We are sometimes doing future-incompatibility lints for // now, so we do not want unconditional errors here. - fulfillment_cx.select_all_or_error(infcx).is_ok() + fulfillment_cx.select_all_or_error(infcx).is_empty() } /// This implements the traversal over the structure of a given type to try to @@ -154,6 +155,9 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> { ty::Projection(..) => { return ControlFlow::Break(NonStructuralMatchTy::Projection); } + ty::Closure(..) => { + return ControlFlow::Break(NonStructuralMatchTy::Closure); + } ty::Generator(..) | ty::GeneratorWitness(..) => { return ControlFlow::Break(NonStructuralMatchTy::Generator); } @@ -197,7 +201,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> { // First check all contained types and then tell the caller to continue searching. return ty.super_visit_with(self); } - ty::Closure(..) | ty::Infer(_) | ty::Placeholder(_) | ty::Bound(..) => { + ty::Infer(_) | ty::Placeholder(_) | ty::Bound(..) => { bug!("unexpected type during structural-match checking: {:?}", ty); } ty::Error(_) => { diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index ed49abbbed..6d2323abba 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -9,7 +9,9 @@ use rustc_middle::ty::subst::{GenericArg, Subst, SubstsRef}; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext}; -pub use rustc_infer::traits::util::*; +pub use rustc_infer::traits::{self, util::*}; + +use std::iter; /////////////////////////////////////////////////////////////////////////// // `TraitAliasExpander` iterator @@ -229,11 +231,16 @@ pub fn predicates_for_generics<'tcx>( ) -> impl Iterator> { debug!("predicates_for_generics(generic_bounds={:?})", generic_bounds); - generic_bounds.predicates.into_iter().map(move |predicate| Obligation { - cause: cause.clone(), - recursion_depth, - param_env, - predicate, + iter::zip(generic_bounds.predicates, generic_bounds.spans).map(move |(predicate, span)| { + let cause = match cause.code { + traits::ItemObligation(def_id) if !span.is_dummy() => traits::ObligationCause::new( + cause.span, + cause.body_id, + traits::BindingObligation(def_id, span), + ), + _ => cause.clone(), + }; + Obligation { cause, recursion_depth, param_env, predicate } }) } diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index cb47ba9c36..2a66684e2a 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -709,7 +709,12 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { 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)); + let code = if span.is_dummy() { + traits::MiscObligation + } else { + traits::BindingObligation(origin_def_id, span) + }; + let cause = self.cause(code); traits::Obligation::with_depth(cause, self.recursion_depth, self.param_env, pred) }) .filter(|pred| !pred.has_escaping_bound_vars()) diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs index 37e0073373..92f2760e62 100644 --- a/compiler/rustc_traits/src/implied_outlives_bounds.rs +++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs @@ -128,9 +128,9 @@ fn compute_implied_outlives_bounds<'tcx>( // Ensure that those obligations that we had to solve // get solved *here*. - match fulfill_cx.select_all_or_error(infcx) { - Ok(()) => Ok(implied_bounds), - Err(_) => Err(NoSolution), + match fulfill_cx.select_all_or_error(infcx).as_slice() { + [] => Ok(implied_bounds), + _ => Err(NoSolution), } } diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 87b729faa5..13ffb2a5ad 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -362,7 +362,7 @@ fn resolve_associated_item<'tcx>( let is_copy = self_ty.is_copy_modulo_regions(tcx.at(DUMMY_SP), param_env); match self_ty.kind() { _ if is_copy => (), - ty::Array(..) | ty::Closure(..) | ty::Tuple(..) => {} + ty::Closure(..) | ty::Tuple(..) => {} _ => return Ok(None), }; diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index 3f66e5b4eb..595b623b02 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -17,7 +17,8 @@ fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx> // needs drop. let adt_has_dtor = |adt_def: &ty::AdtDef| adt_def.destructor(tcx).map(|_| DtorType::Significant); - let res = drop_tys_helper(tcx, query.value, query.param_env, adt_has_dtor).next().is_some(); + let res = + drop_tys_helper(tcx, query.value, query.param_env, adt_has_dtor, false).next().is_some(); debug!("needs_drop_raw({:?}) = {:?}", query, res); res @@ -27,10 +28,15 @@ fn has_significant_drop_raw<'tcx>( tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, ) -> bool { - let res = - drop_tys_helper(tcx, query.value, query.param_env, adt_consider_insignificant_dtor(tcx)) - .next() - .is_some(); + let res = drop_tys_helper( + tcx, + query.value, + query.param_env, + adt_consider_insignificant_dtor(tcx), + true, + ) + .next() + .is_some(); debug!("has_significant_drop_raw({:?}) = {:?}", query, res); res } @@ -141,9 +147,9 @@ where Ok(tys) => tys, }; for required_ty in tys { - let subst_ty = + let required = tcx.normalize_erasing_regions(self.param_env, required_ty); - queue_type(self, subst_ty); + queue_type(self, required); } } ty::Array(..) | ty::Opaque(..) | ty::Projection(..) | ty::Param(_) => { @@ -186,16 +192,39 @@ fn drop_tys_helper<'tcx>( ty: Ty<'tcx>, param_env: rustc_middle::ty::ParamEnv<'tcx>, adt_has_dtor: impl Fn(&ty::AdtDef) -> Option, + only_significant: bool, ) -> impl Iterator>> { + fn with_query_cache<'tcx>( + tcx: TyCtxt<'tcx>, + iter: impl IntoIterator>, + only_significant: bool, + ) -> NeedsDropResult>> { + iter.into_iter().try_fold(Vec::new(), |mut vec, subty| { + match subty.kind() { + ty::Adt(adt_id, subst) => { + for subty in if only_significant { + tcx.adt_significant_drop_tys(adt_id.did)? + } else { + tcx.adt_drop_tys(adt_id.did)? + } { + vec.push(subty.subst(tcx, subst)); + } + } + _ => vec.push(subty), + }; + Ok(vec) + }) + } + let adt_components = move |adt_def: &ty::AdtDef, substs: SubstsRef<'tcx>| { if adt_def.is_manually_drop() { debug!("drop_tys_helper: `{:?}` is manually drop", adt_def); - return Ok(Vec::new().into_iter()); + Ok(Vec::new()) } else if let Some(dtor_info) = adt_has_dtor(adt_def) { match dtor_info { DtorType::Significant => { debug!("drop_tys_helper: `{:?}` implements `Drop`", adt_def); - return Err(AlwaysRequiresDrop); + Err(AlwaysRequiresDrop) } DtorType::Insignificant => { debug!("drop_tys_helper: `{:?}` drop is insignificant", adt_def); @@ -203,22 +232,27 @@ fn drop_tys_helper<'tcx>( // Since the destructor is insignificant, we just want to make sure all of // the passed in type parameters are also insignificant. // Eg: Vec dtor is insignificant when T=i32 but significant when T=Mutex. - return Ok(substs.types().collect::>>().into_iter()); + with_query_cache(tcx, substs.types(), only_significant) } } } else if adt_def.is_union() { debug!("drop_tys_helper: `{:?}` is a union", adt_def); - return Ok(Vec::new().into_iter()); + Ok(Vec::new()) + } else { + with_query_cache( + tcx, + adt_def.all_fields().map(|field| { + let r = tcx.type_of(field.did).subst(tcx, substs); + debug!( + "drop_tys_helper: Subst into {:?} with {:?} gettng {:?}", + field, substs, r + ); + r + }), + only_significant, + ) } - Ok(adt_def - .all_fields() - .map(|field| { - let r = tcx.type_of(field.did).subst(tcx, substs); - debug!("drop_tys_helper: Subst into {:?} with {:?} gettng {:?}", field, substs, r); - r - }) - .collect::>() - .into_iter()) + .map(|v| v.into_iter()) }; NeedsDropTypes::new(tcx, param_env, ty, adt_components) @@ -252,20 +286,24 @@ fn adt_drop_tys(tcx: TyCtxt<'_>, def_id: DefId) -> Result<&ty::List>, Alw // significant. let adt_has_dtor = |adt_def: &ty::AdtDef| adt_def.destructor(tcx).map(|_| DtorType::Significant); - drop_tys_helper(tcx, tcx.type_of(def_id), tcx.param_env(def_id), adt_has_dtor) + // `tcx.type_of(def_id)` identical to `tcx.make_adt(def, identity_substs)` + drop_tys_helper(tcx, tcx.type_of(def_id), tcx.param_env(def_id), adt_has_dtor, false) .collect::, _>>() .map(|components| tcx.intern_type_list(&components)) } - +// If `def_id` refers to a generic ADT, the queries above and below act as if they had been handed +// a `tcx.make_ty(def, identity_substs)` and as such it is legal to substitue the generic parameters +// of the ADT into the outputted `ty`s. fn adt_significant_drop_tys( tcx: TyCtxt<'_>, def_id: DefId, ) -> Result<&ty::List>, AlwaysRequiresDrop> { drop_tys_helper( tcx, - tcx.type_of(def_id), + tcx.type_of(def_id), // identical to `tcx.make_adt(def, identity_substs)` tcx.param_env(def_id), adt_consider_insignificant_dtor(tcx), + true, ) .collect::, _>>() .map(|components| tcx.intern_type_list(&components)) diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 7512403249..af3706f886 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -1,7 +1,6 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_middle::hir::map as hir_map; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{ self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt, WithConstness, @@ -490,11 +489,11 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync { let node = tcx.hir().get(hir_id); - let fn_like = hir_map::blocks::FnLikeNode::from_node(node).unwrap_or_else(|| { + let fn_kind = node.fn_kind().unwrap_or_else(|| { bug!("asyncness: expected fn-like node but got `{:?}`", def_id); }); - fn_like.asyncness() + fn_kind.asyncness() } /// Don't call this directly: use ``tcx.conservative_is_privately_uninhabited`` instead. diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 91dbbec782..f11c93e933 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -559,6 +559,7 @@ impl HashStable for FloatTy { impl HashStable for InferTy { fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { use InferTy::*; + discriminant(self).hash_stable(ctx, hasher); match self { TyVar(v) => v.as_u32().hash_stable(ctx, hasher), IntVar(v) => v.index.hash_stable(ctx, hasher), diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs index 5befe44802..e8bd038fed 100644 --- a/compiler/rustc_typeck/src/astconv/generics.rs +++ b/compiler/rustc_typeck/src/astconv/generics.rs @@ -344,7 +344,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { "reorder the arguments: {}: `<{}>`", param_types_present .into_iter() - .map(|ord| format!("{}s", ord.to_string())) + .map(|ord| format!("{}s", ord)) .collect::>() .join(", then "), ordered_params @@ -464,16 +464,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .params .iter() .filter(|param| { - matches!( - param.kind, - ty::GenericParamDefKind::Type { - synthetic: Some( - hir::SyntheticTyParamKind::ImplTrait - | hir::SyntheticTyParamKind::FromAttr - ), - .. - } - ) + matches!(param.kind, ty::GenericParamDefKind::Type { synthetic: true, .. }) }) .count() } else { @@ -672,6 +663,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { err.span_label(span, "explicit generic argument not allowed"); } + err.note( + "see issue #83701 \ + for more information", + ); + if tcx.sess.is_nightly_build() { + err.help( + "add `#![feature(explicit_generic_args_with_impl_trait)]` \ + to the crate attributes to enable", + ); + } + err.emit(); } diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 889b68773c..da751f2075 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -1916,9 +1916,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { debug!("qpath_to_ty: trait_def_id={:?}", trait_def_id); - let self_ty = if let Some(ty) = opt_self_ty { - ty - } else { + let Some(self_ty) = opt_self_ty else { let path_str = tcx.def_path_str(trait_def_id); let def_id = self.item_def_id(); diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs index 6a231e719e..a816031322 100644 --- a/compiler/rustc_typeck/src/check/_match.rs +++ b/compiler/rustc_typeck/src/check/_match.rs @@ -6,7 +6,6 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi use rustc_infer::traits::Obligation; use rustc_middle::ty::{self, ToPredicate, Ty, TyS}; use rustc_span::{MultiSpan, Span}; -use rustc_trait_selection::opaque_types::InferCtxtExt as _; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::{ IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode, @@ -531,6 +530,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { substs: self.infcx.tcx.mk_substs_trait(outer_ty, &[]), }, constness: t.constness, + polarity: t.polarity, })); let obl = Obligation::new( o.cause.clone(), diff --git a/compiler/rustc_typeck/src/check/callee.rs b/compiler/rustc_typeck/src/check/callee.rs index 06c4209879..635ed93819 100644 --- a/compiler/rustc_typeck/src/check/callee.rs +++ b/compiler/rustc_typeck/src/check/callee.rs @@ -300,7 +300,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let end = callee_span.shrink_to_hi(); err.multipart_suggestion( "if you meant to create this closure and immediately call it, surround the \ - closure with parenthesis", + closure with parentheses", vec![(start, "(".to_string()), (end, ")".to_string())], Applicability::MaybeIncorrect, ); @@ -349,9 +349,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::FnPtr(sig) => (sig, None), ref t => { let mut unit_variant = None; + let mut removal_span = call_expr.span; if let ty::Adt(adt_def, ..) = t { if adt_def.is_enum() { if let hir::ExprKind::Call(expr, _) = call_expr.kind { + removal_span = + expr.span.shrink_to_hi().to(call_expr.span.shrink_to_hi()); unit_variant = self.tcx.sess.source_map().span_to_snippet(expr.span).ok(); } @@ -379,14 +382,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); if let Some(ref path) = unit_variant { - err.span_suggestion( - call_expr.span, + err.span_suggestion_verbose( + removal_span, &format!( - "`{}` is a unit variant, you need to write it \ - without the parenthesis", + "`{}` is a unit variant, you need to write it without the parentheses", path ), - path.to_string(), + String::new(), Applicability::MachineApplicable, ); } diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs index 78849b276d..511a2d7dda 100644 --- a/compiler/rustc_typeck/src/check/cast.rs +++ b/compiler/rustc_typeck/src/check/cast.rs @@ -436,11 +436,8 @@ impl<'a, 'tcx> CastCheck<'tcx> { // Very crude check to see whether the expression must be wrapped // in parentheses for the suggestion to work (issue #89497). // Can/should be extended in the future. - let needs_parens = !has_parens - && match self.expr.kind { - hir::ExprKind::Cast(..) => true, - _ => false, - }; + let needs_parens = + !has_parens && matches!(self.expr.kind, hir::ExprKind::Cast(..)); let mut suggestion = vec![(self.expr.span.shrink_to_lo(), sugg)]; if needs_parens { diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 66316214e5..bb1d9744e6 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -21,7 +21,6 @@ use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVE 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_ty_utils::representability::{self, Representability}; @@ -372,16 +371,26 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b let param_env = tcx.param_env(item_def_id); for field in fields { let field_ty = field.ty(tcx, substs); - // We are currently checking the type this field came from, so it must be local. - let field_span = tcx.hir().span_if_local(field.did).unwrap(); if field_ty.needs_drop(tcx, param_env) { + let (field_span, ty_span) = match tcx.hir().get_if_local(field.did) { + // We are currently checking the type this field came from, so it must be local. + Some(Node::Field(field)) => (field.span, field.ty.span), + _ => unreachable!("mir field has to correspond to hir field"), + }; struct_span_err!( tcx.sess, field_span, E0740, "unions may not contain fields that need dropping" ) - .span_note(field_span, "`std::mem::ManuallyDrop` can be used to wrap the type") + .multipart_suggestion_verbose( + "wrap the type with `std::mem::ManuallyDrop` and ensure it is manually dropped", + vec![ + (ty_span.shrink_to_lo(), format!("std::mem::ManuallyDrop<")), + (ty_span.shrink_to_hi(), ">".into()), + ], + Applicability::MaybeIncorrect, + ) .emit(); return false; } @@ -664,8 +673,9 @@ fn check_opaque_meets_bounds<'tcx>( // Check that all obligations are satisfied by the implementation's // version. - if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(errors, None, false); + let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx); + if !errors.is_empty() { + infcx.report_fulfillment_errors(&errors, None, false); } // Finally, resolve all regions. This catches wily misuses of diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs index 410ac24b1f..4a41552a5f 100644 --- a/compiler/rustc_typeck/src/check/closure.rs +++ b/compiler/rustc_typeck/src/check/closure.rs @@ -92,7 +92,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let parent_substs = InternalSubsts::identity_for_item( self.tcx, - self.tcx.closure_base_def_id(expr_def_id.to_def_id()), + self.tcx.typeck_root_def_id(expr_def_id.to_def_id()), ); let tupled_upvars_ty = self.infcx.next_ty_var(TypeVariableOrigin { @@ -257,8 +257,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if is_gen { // Check that we deduce the signature from the `<_ as std::ops::Generator>::Return` // associated item and not yield. - let return_assoc_item = - self.tcx.associated_items(gen_trait).in_definition_order().nth(1).unwrap().def_id; + let return_assoc_item = self.tcx.associated_item_def_ids(gen_trait)[1]; if return_assoc_item != projection.projection_def_id() { debug!("deduce_sig_from_projection: not return assoc item of generator"); return None; @@ -694,8 +693,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // The `Future` trait has only one associted item, `Output`, // so check that this is what we see. - let output_assoc_item = - self.tcx.associated_items(future_trait).in_definition_order().next().unwrap().def_id; + let output_assoc_item = self.tcx.associated_item_def_ids(future_trait)[0]; if output_assoc_item != predicate.projection_ty.item_def_id { span_bug!( cause_span, diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index a87318ff34..77f7cccc04 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -185,9 +185,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { debug!("coerce: unsize not object safe"); return Err(TypeError::ObjectUnsafeCoercion(did)); } - Err(_) => {} + Err(error) => { + debug!(?error, "coerce: unsize failed"); + } } - debug!("coerce: unsize failed"); // Examine the supertype and consider auto-borrowing. match *b.kind() { @@ -521,9 +522,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let traits = (self.tcx.lang_items().unsize_trait(), self.tcx.lang_items().coerce_unsized_trait()); - let (unsize_did, coerce_unsized_did) = if let (Some(u), Some(cu)) = traits { - (u, cu) - } else { + let (Some(unsize_did), Some(coerce_unsized_did)) = traits else { debug!("missing Unsize or CoerceUnsized traits"); return Err(TypeError::Mismatch); }; @@ -951,7 +950,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let mut fcx = traits::FulfillmentContext::new_in_snapshot(); fcx.register_predicate_obligations(self, ok.obligations); - fcx.select_where_possible(&self).is_ok() + fcx.select_where_possible(&self).is_empty() }) } @@ -1459,7 +1458,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { cause, expected, found, - coercion_error, + coercion_error.clone(), fcx, parent_id, expression.map(|expr| (expr, blk_id)), @@ -1473,7 +1472,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { cause, expected, found, - coercion_error, + coercion_error.clone(), fcx, id, None, @@ -1484,7 +1483,12 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { } } _ => { - err = fcx.report_mismatched_types(cause, expected, found, coercion_error); + err = fcx.report_mismatched_types( + cause, + expected, + found, + coercion_error.clone(), + ); } } @@ -1493,7 +1497,14 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { } if let Some(expr) = expression { - fcx.emit_coerce_suggestions(&mut err, expr, found, expected, None); + fcx.emit_coerce_suggestions( + &mut err, + expr, + found, + expected, + None, + coercion_error, + ); } err.emit_unless(unsized_return); diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 5e12497f34..fdc5d16acc 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -92,7 +92,6 @@ fn compare_predicate_entailment<'tcx>( impl_m_span, impl_m_hir_id, ObligationCauseCode::CompareImplMethodObligation { - item_name: impl_m.ident.name, impl_item_def_id: impl_m.def_id, trait_item_def_id: trait_m.def_id, }, @@ -211,12 +210,8 @@ fn compare_predicate_entailment<'tcx>( let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_hir_id); let param_env = ty::ParamEnv::new(tcx.intern_predicates(&hybrid_preds.predicates), Reveal::UserFacing); - let param_env = traits::normalize_param_env_or_error( - tcx, - impl_m.def_id, - param_env, - normalize_cause.clone(), - ); + let param_env = + traits::normalize_param_env_or_error(tcx, impl_m.def_id, param_env, normalize_cause); tcx.infer_ctxt().enter(|infcx| { let inh = Inherited::new(infcx, impl_m.def_id.expect_local()); @@ -227,12 +222,15 @@ fn compare_predicate_entailment<'tcx>( let mut selcx = traits::SelectionContext::new(&infcx); let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_placeholder_substs); - for predicate in impl_m_own_bounds.predicates { + for (predicate, span) in iter::zip(impl_m_own_bounds.predicates, impl_m_own_bounds.spans) { + let normalize_cause = traits::ObligationCause::misc(span, impl_m_hir_id); let traits::Normalized { value: predicate, obligations } = - traits::normalize(&mut selcx, param_env, normalize_cause.clone(), predicate); + traits::normalize(&mut selcx, param_env, normalize_cause, predicate); inh.register_predicates(obligations); - inh.register_predicate(traits::Obligation::new(cause.clone(), param_env, predicate)); + let mut cause = cause.clone(); + cause.make_mut().span = span; + inh.register_predicate(traits::Obligation::new(cause, param_env, predicate)); } // We now need to check that the signature of the impl method is @@ -276,6 +274,12 @@ fn compare_predicate_entailment<'tcx>( let sub_result = infcx.at(&cause, param_env).sup(trait_fty, impl_fty).map( |InferOk { obligations, .. }| { + // FIXME: We'd want to keep more accurate spans than "the method signature" when + // processing the comparison between the trait and impl fn, but we sadly lose them + // and point at the whole signature when a trait bound or specific input or output + // type would be more appropriate. In other places we have a `Vec` + // corresponding to their `Vec`, but we don't have that here. + // Fixing this would improve the output of test `issue-83765.rs`. inh.register_predicates(obligations); }, ); @@ -386,8 +390,9 @@ fn compare_predicate_entailment<'tcx>( // Check that all obligations are satisfied by the implementation's // version. - if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(errors, None, false); + let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx); + if !errors.is_empty() { + infcx.report_fulfillment_errors(&errors, None, false); return Err(ErrorReported); } @@ -448,6 +453,7 @@ fn check_region_bounds_on_impl_item<'tcx>( Ok(()) } +#[instrument(level = "debug", skip(infcx))] fn extract_spans_for_error_reporting<'a, 'tcx>( infcx: &infer::InferCtxt<'a, 'tcx>, terr: &TypeError<'_>, @@ -601,10 +607,7 @@ fn compare_number_of_generics<'tcx>( .params .iter() .filter_map(|p| match p.kind { - GenericParamKind::Type { - synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), - .. - } => Some(p.span), + GenericParamKind::Type { synthetic: true, .. } => Some(p.span), _ => None, }) .collect(); @@ -621,10 +624,7 @@ fn compare_number_of_generics<'tcx>( .params .iter() .filter_map(|p| match p.kind { - GenericParamKind::Type { - synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), - .. - } => Some(p.span), + GenericParamKind::Type { synthetic: true, .. } => Some(p.span), _ => None, }) .collect(); @@ -817,7 +817,7 @@ fn compare_synthetic_generics<'tcx>( match (impl_synthetic, trait_synthetic) { // The case where the impl method uses `impl Trait` but the trait method uses // explicit generics - (Some(hir::SyntheticTyParamKind::ImplTrait), None) => { + (true, false) => { err.span_label(impl_span, "expected generic parameter, found `impl Trait`"); (|| { // try taking the name from the trait impl @@ -858,7 +858,7 @@ fn compare_synthetic_generics<'tcx>( } // The case where the trait method uses `impl Trait`, but the impl method uses // explicit generics. - (None, Some(hir::SyntheticTyParamKind::ImplTrait)) => { + (false, true) => { err.span_label(impl_span, "expected `impl Trait`, found generic parameter"); (|| { let impl_m = impl_m.def_id.as_local()?; @@ -1088,8 +1088,9 @@ crate fn compare_const_impl<'tcx>( // Check that all obligations are satisfied by the implementation's // version. - if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(errors, None, false); + let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx); + if !errors.is_empty() { + infcx.report_fulfillment_errors(&errors, None, false); return; } @@ -1159,7 +1160,6 @@ fn compare_type_predicate_entailment<'tcx>( impl_ty_span, impl_ty_hir_id, ObligationCauseCode::CompareImplTypeObligation { - item_name: impl_ty.ident.name, impl_item_def_id: impl_ty.def_id, trait_item_def_id: trait_ty.def_id, }, @@ -1204,8 +1204,9 @@ fn compare_type_predicate_entailment<'tcx>( // Check that all obligations are satisfied by the implementation's // version. - if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(errors, None, false); + let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx); + if !errors.is_empty() { + infcx.report_fulfillment_errors(&errors, None, false); return Err(ErrorReported); } @@ -1384,12 +1385,13 @@ pub fn check_type_bounds<'tcx>( let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local()); let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_hir_id); - let mk_cause = |span| { - ObligationCause::new( - impl_ty_span, - impl_ty_hir_id, - ObligationCauseCode::BindingObligation(trait_ty.def_id, span), - ) + let mk_cause = |span: Span| { + let code = if span.is_dummy() { + traits::MiscObligation + } else { + traits::BindingObligation(trait_ty.def_id, span) + }; + ObligationCause::new(impl_ty_span, impl_ty_hir_id, code) }; let obligations = tcx @@ -1421,10 +1423,10 @@ pub fn check_type_bounds<'tcx>( // Check that all obligations are satisfied by the implementation's // version. - if let Err(ref errors) = - inh.fulfillment_cx.borrow_mut().select_all_with_constness_or_error(&infcx, constness) - { - infcx.report_fulfillment_errors(errors, None, false); + let errors = + inh.fulfillment_cx.borrow_mut().select_all_with_constness_or_error(&infcx, constness); + if !errors.is_empty() { + infcx.report_fulfillment_errors(&errors, None, false); return Err(ErrorReported); } diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index 540365956a..12cd7ad184 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -10,6 +10,7 @@ use rustc_hir::lang_items::LangItem; use rustc_hir::{is_range_literal, Node}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::adjustment::AllowTwoPhase; +use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut}; use rustc_span::symbol::sym; @@ -27,8 +28,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr_ty: Ty<'tcx>, expected: Ty<'tcx>, expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>, + error: TypeError<'tcx>, ) { - self.annotate_expected_due_to_let_ty(err, expr); + self.annotate_expected_due_to_let_ty(err, expr, error); + self.suggest_box_deref(err, expr, expected, expr_ty); self.suggest_compatible_variants(err, expr, expected, expr_ty); self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr); if self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty) { @@ -144,9 +147,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let expr = expr.peel_drop_temps(); let cause = self.misc(expr.span); let expr_ty = self.resolve_vars_with_obligations(checked_ty); - let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e); + let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e.clone()); - self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected, expected_ty_expr); + self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected, expected_ty_expr, e); (expected, Some(err)) } @@ -155,15 +158,121 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, err: &mut DiagnosticBuilder<'_>, expr: &hir::Expr<'_>, + error: TypeError<'_>, ) { let parent = self.tcx.hir().get_parent_node(expr.hir_id); - if let Some(hir::Node::Local(hir::Local { ty: Some(ty), init: Some(init), .. })) = - self.tcx.hir().find(parent) - { - if init.hir_id == expr.hir_id { + match (self.tcx.hir().find(parent), error) { + (Some(hir::Node::Local(hir::Local { ty: Some(ty), init: Some(init), .. })), _) + if init.hir_id == expr.hir_id => + { // Point at `let` assignment type. err.span_label(ty.span, "expected due to this"); } + ( + Some(hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Assign(lhs, rhs, _), .. + })), + TypeError::Sorts(ExpectedFound { expected, .. }), + ) if rhs.hir_id == expr.hir_id && !expected.is_closure() => { + // We ignore closures explicitly because we already point at them elsewhere. + // Point at the assigned-to binding. + let mut primary_span = lhs.span; + let mut secondary_span = lhs.span; + let mut post_message = ""; + match lhs.kind { + hir::ExprKind::Path(hir::QPath::Resolved( + None, + hir::Path { + res: + hir::def::Res::Def( + hir::def::DefKind::Static | hir::def::DefKind::Const, + def_id, + ), + .. + }, + )) => { + if let Some(hir::Node::Item(hir::Item { + ident, + kind: hir::ItemKind::Static(ty, ..) | hir::ItemKind::Const(ty, ..), + .. + })) = self.tcx.hir().get_if_local(*def_id) + { + primary_span = ty.span; + secondary_span = ident.span; + post_message = " type"; + } + } + hir::ExprKind::Path(hir::QPath::Resolved( + None, + hir::Path { res: hir::def::Res::Local(hir_id), .. }, + )) => { + if let Some(hir::Node::Binding(pat)) = self.tcx.hir().find(*hir_id) { + let parent = self.tcx.hir().get_parent_node(pat.hir_id); + primary_span = pat.span; + secondary_span = pat.span; + match self.tcx.hir().find(parent) { + Some(hir::Node::Local(hir::Local { ty: Some(ty), .. })) => { + primary_span = ty.span; + post_message = " type"; + } + Some(hir::Node::Local(hir::Local { init: Some(init), .. })) => { + primary_span = init.span; + post_message = " value"; + } + Some(hir::Node::Param(hir::Param { ty_span, .. })) => { + primary_span = *ty_span; + post_message = " parameter type"; + } + _ => {} + } + } + } + _ => {} + } + + if primary_span != secondary_span + && self + .tcx + .sess + .source_map() + .is_multiline(secondary_span.shrink_to_hi().until(primary_span)) + { + // We are pointing at the binding's type or initializer value, but it's pattern + // is in a different line, so we point at both. + err.span_label(secondary_span, "expected due to the type of this binding"); + err.span_label(primary_span, &format!("expected due to this{}", post_message)); + } else if post_message == "" { + // We are pointing at either the assignment lhs or the binding def pattern. + err.span_label(primary_span, "expected due to the type of this binding"); + } else { + // We are pointing at the binding's type or initializer value. + err.span_label(primary_span, &format!("expected due to this{}", post_message)); + } + + if !lhs.is_syntactic_place_expr() { + // We already emitted E0070 "invalid left-hand side of assignment", so we + // silence this. + err.delay_as_bug(); + } + } + _ => {} + } + } + + fn suggest_box_deref( + &self, + err: &mut DiagnosticBuilder<'_>, + expr: &hir::Expr<'_>, + expected: Ty<'tcx>, + expr_ty: Ty<'tcx>, + ) { + if expr_ty.is_box() && expr_ty.boxed_ty() == expected { + err.span_suggestion_verbose( + expr.span.shrink_to_lo(), + "try dereferencing the `Box`", + "*".to_string(), + Applicability::MachineApplicable, + ); } } @@ -181,7 +290,50 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return; } - let mut compatible_variants = expected_adt + // If the expression is of type () and it's the return expression of a block, + // we suggest adding a separate return expression instead. + // (To avoid things like suggesting `Ok(while .. { .. })`.) + if expr_ty.is_unit() { + if let Some(hir::Node::Block(&hir::Block { + span: block_span, expr: Some(e), .. + })) = self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.hir_id)) + { + if e.hir_id == expr.hir_id { + if let Some(span) = expr.span.find_ancestor_inside(block_span) { + let return_suggestions = + if self.tcx.is_diagnostic_item(sym::Result, expected_adt.did) { + vec!["Ok(())".to_string()] + } else if self.tcx.is_diagnostic_item(sym::Option, expected_adt.did) + { + vec!["None".to_string(), "Some(())".to_string()] + } else { + return; + }; + if let Some(indent) = + self.tcx.sess.source_map().indentation_before(span.shrink_to_lo()) + { + // Add a semicolon, except after `}`. + let semicolon = + match self.tcx.sess.source_map().span_to_snippet(span) { + Ok(s) if s.ends_with('}') => "", + _ => ";", + }; + err.span_suggestions( + span.shrink_to_hi(), + "try adding an expression at the end of the block", + return_suggestions + .into_iter() + .map(|r| format!("{}\n{}{}", semicolon, indent, r)), + Applicability::MaybeIncorrect, + ); + } + return; + } + } + } + } + + let compatible_variants: Vec = expected_adt .variants .iter() .filter(|variant| variant.fields.len() == 1) @@ -202,19 +354,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None } }) - .peekable(); + .collect(); - if compatible_variants.peek().is_some() { - if let Ok(expr_text) = self.tcx.sess.source_map().span_to_snippet(expr.span) { - let suggestions = compatible_variants.map(|v| format!("{}({})", v, expr_text)); - let msg = "try using a variant of the expected enum"; - err.span_suggestions( - expr.span, - msg, - suggestions, - Applicability::MaybeIncorrect, - ); - } + if let [variant] = &compatible_variants[..] { + // Just a single matching variant. + err.multipart_suggestion( + &format!("try wrapping the expression in `{}`", variant), + vec![ + (expr.span.shrink_to_lo(), format!("{}(", variant)), + (expr.span.shrink_to_hi(), ")".to_string()), + ], + Applicability::MaybeIncorrect, + ); + } else if compatible_variants.len() > 1 { + // More than one matching variant. + err.multipart_suggestions( + &format!( + "try wrapping the expression in a variant of `{}`", + self.tcx.def_path_str(expected_adt.did) + ), + compatible_variants.into_iter().map(|variant| { + vec![ + (expr.span.shrink_to_lo(), format!("{}(", variant)), + (expr.span.shrink_to_hi(), ")".to_string()), + ] + }), + Applicability::MaybeIncorrect, + ); } } } @@ -428,7 +594,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (&ty::Str, &ty::Array(arr, _) | &ty::Slice(arr)) if arr == self.tcx.types.u8 => { if let hir::ExprKind::Lit(_) = expr.kind { if let Ok(src) = sm.span_to_snippet(sp) { - if let Some(_) = replace_prefix(&src, "b\"", "\"") { + if replace_prefix(&src, "b\"", "\"").is_some() { let pos = sp.lo() + BytePos(1); return Some(( sp.with_hi(pos), @@ -444,7 +610,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (&ty::Array(arr, _) | &ty::Slice(arr), &ty::Str) if arr == self.tcx.types.u8 => { if let hir::ExprKind::Lit(_) = expr.kind { if let Ok(src) = sm.span_to_snippet(sp) { - if let Some(_) = replace_prefix(&src, "\"", "b\"") { + if replace_prefix(&src, "\"", "b\"").is_some() { return Some(( sp.shrink_to_lo(), "consider adding a leading `b`", @@ -743,9 +909,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return false; } - let src = if let Ok(src) = self.tcx.sess.source_map().span_to_snippet(expr.span) { - src - } else { + let Ok(src) = self.tcx.sess.source_map().span_to_snippet(expr.span) else { return false; }; diff --git a/compiler/rustc_typeck/src/check/dropck.rs b/compiler/rustc_typeck/src/check/dropck.rs index 9e2460b570..4b4d29307f 100644 --- a/compiler/rustc_typeck/src/check/dropck.rs +++ b/compiler/rustc_typeck/src/check/dropck.rs @@ -113,9 +113,10 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>( } } - if let Err(ref errors) = fulfillment_cx.select_all_or_error(&infcx) { + let errors = fulfillment_cx.select_all_or_error(&infcx); + if !errors.is_empty() { // this could be reached when we get lazy normalization - infcx.report_fulfillment_errors(errors, None, false); + infcx.report_fulfillment_errors(&errors, None, false); return Err(ErrorReported); } diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 2d0a4068fb..eb997b014c 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -30,15 +30,17 @@ 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::intravisit::Visitor; use rustc_hir::{ExprKind, QPath}; use rustc_infer::infer; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_middle::ty; +use rustc_infer::infer::InferOk; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase}; +use rustc_middle::ty::error::TypeError::{FieldMisMatch, Sorts}; +use rustc_middle::ty::relate::expected_found_bool; use rustc_middle::ty::subst::SubstsRef; -use rustc_middle::ty::Ty; -use rustc_middle::ty::TypeFoldable; -use rustc_middle::ty::{AdtKind, Visibility}; +use rustc_middle::ty::{self, AdtKind, Ty, TypeFoldable}; +use rustc_session::parse::feature_err; use rustc_span::edition::LATEST_STABLE_EDITION; use rustc_span::hygiene::DesugaringKind; use rustc_span::lev_distance::find_best_match_for_name; @@ -323,7 +325,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } ExprKind::DropTemps(e) => self.check_expr_with_expectation(e, expected), ExprKind::Array(args) => self.check_expr_array(args, expected, expr), - ExprKind::ConstBlock(ref anon_const) => self.to_const(anon_const).ty, + ExprKind::ConstBlock(ref anon_const) => { + self.check_expr_const_block(anon_const, expected, expr) + } ExprKind::Repeat(element, ref count) => { self.check_expr_repeat(element, count, expected, expr) } @@ -829,7 +833,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, lhs: &'tcx hir::Expr<'tcx>, err_code: &'static str, - expr_span: &Span, + op_span: Span, ) { if lhs.is_syntactic_place_expr() { return; @@ -837,11 +841,58 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // FIXME: Make this use SessionDiagnostic once error codes can be dynamically set. let mut err = self.tcx.sess.struct_span_err_with_code( - *expr_span, + op_span, "invalid left-hand side of assignment", DiagnosticId::Error(err_code.into()), ); err.span_label(lhs.span, "cannot assign to this expression"); + + let mut parent = self.tcx.hir().get_parent_node(lhs.hir_id); + while let Some(node) = self.tcx.hir().find(parent) { + match node { + hir::Node::Expr(hir::Expr { + kind: + hir::ExprKind::Loop( + hir::Block { + expr: + Some(hir::Expr { + kind: + hir::ExprKind::Match(expr, ..) | hir::ExprKind::If(expr, ..), + .. + }), + .. + }, + _, + hir::LoopSource::While, + _, + ), + .. + }) => { + // We have a situation like `while Some(0) = value.get(0) {`, where `while let` + // was more likely intended. + err.span_suggestion_verbose( + expr.span.shrink_to_lo(), + "you might have meant to use pattern destructuring", + "let ".to_string(), + Applicability::MachineApplicable, + ); + if !self.sess().features_untracked().destructuring_assignment { + // We already emit an E0658 with a suggestion for `while let`, this is + // redundant output. + err.delay_as_bug(); + } + break; + } + hir::Node::Item(_) + | hir::Node::ImplItem(_) + | hir::Node::TraitItem(_) + | hir::Node::Crate(_) => break, + _ => { + parent = self.tcx.hir().get_parent_node(parent); + } + } + } + err.emit(); } @@ -949,7 +1000,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { (Applicability::MaybeIncorrect, false) }; - if !lhs.is_syntactic_place_expr() { + if !lhs.is_syntactic_place_expr() && !matches!(lhs.kind, hir::ExprKind::Lit(_)) { // Do not suggest `if let x = y` as `==` is way more likely to be the intention. let hir = self.tcx.hir(); if let hir::Node::Expr(hir::Expr { kind: ExprKind::If { .. }, .. }) = @@ -961,7 +1012,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "let ".to_string(), applicability, ); - } + }; } if eq { err.span_suggestion_verbose( @@ -982,7 +1033,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return self.tcx.ty_error(); } - self.check_lhs_assignable(lhs, "E0070", span); + self.check_lhs_assignable(lhs, "E0070", *span); let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace); let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty, Some(lhs)); @@ -1166,6 +1217,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.mk_array(element_ty, args.len() as u64) } + fn check_expr_const_block( + &self, + anon_const: &'tcx hir::AnonConst, + expected: Expectation<'tcx>, + _expr: &'tcx hir::Expr<'tcx>, + ) -> Ty<'tcx> { + let body = self.tcx.hir().body(anon_const.body); + + // Create a new function context. + let fcx = FnCtxt::new(self, self.param_env, body.value.hir_id); + crate::check::GatherLocalsVisitor::new(&fcx).visit_body(body); + + let ty = fcx.check_expr_with_expectation(&body.value, expected); + fcx.require_type_is_sized(ty, body.value.span, traits::ConstSized); + fcx.write_ty(anon_const.hir_id, ty); + ty + } + fn check_expr_repeat( &self, element: &'tcx hir::Expr<'tcx>, @@ -1262,49 +1331,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .emit_err(StructExprNonExhaustive { span: expr.span, what: adt.variant_descr() }); } - let error_happened = self.check_expr_struct_fields( + self.check_expr_struct_fields( adt_ty, expected, expr.hir_id, qpath.span(), variant, fields, - base_expr.is_none(), + base_expr, expr.span, ); - if let Some(base_expr) = base_expr { - // If check_expr_struct_fields hit an error, do not attempt to populate - // the fields with the base_expr. This could cause us to hit errors later - // when certain fields are assumed to exist that in fact do not. - if !error_happened { - self.check_expr_has_type_or_error(base_expr, adt_ty, |_| {}); - match adt_ty.kind() { - ty::Adt(adt, substs) if adt.is_struct() => { - let fru_field_types = adt - .non_enum_variant() - .fields - .iter() - .map(|f| { - self.normalize_associated_types_in( - expr.span, - f.ty(self.tcx, substs), - ) - }) - .collect(); - - self.typeck_results - .borrow_mut() - .fru_field_types_mut() - .insert(expr.hir_id, fru_field_types); - } - _ => { - self.tcx - .sess - .emit_err(FunctionalRecordUpdateOnNonStruct { span: base_expr.span }); - } - } - } - } + self.require_type_is_sized(adt_ty, expr.span, traits::StructInitializerSized); adt_ty } @@ -1317,9 +1354,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, variant: &'tcx ty::VariantDef, ast_fields: &'tcx [hir::ExprField<'tcx>], - check_completeness: bool, + base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>, expr_span: Span, - ) -> bool { + ) { let tcx = self.tcx; let adt_ty_hint = self @@ -1394,7 +1431,116 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) .emit(); } - } else if check_completeness && !error_happened && !remaining_fields.is_empty() { + } + + // If check_expr_struct_fields hit an error, do not attempt to populate + // the fields with the base_expr. This could cause us to hit errors later + // when certain fields are assumed to exist that in fact do not. + if error_happened { + return; + } + + if let Some(base_expr) = base_expr { + // FIXME: We are currently creating two branches here in order to maintain + // consistency. But they should be merged as much as possible. + let fru_tys = if self.tcx.features().type_changing_struct_update { + let base_ty = self.check_expr(base_expr); + match adt_ty.kind() { + ty::Adt(adt, substs) if adt.is_struct() => { + match base_ty.kind() { + ty::Adt(base_adt, base_subs) if adt == base_adt => { + variant + .fields + .iter() + .map(|f| { + let fru_ty = self.normalize_associated_types_in( + expr_span, + self.field_ty(base_expr.span, f, base_subs), + ); + let ident = self.tcx.adjust_ident(f.ident, variant.def_id); + if let Some(_) = remaining_fields.remove(&ident) { + let target_ty = + self.field_ty(base_expr.span, f, substs); + let cause = self.misc(base_expr.span); + match self + .at(&cause, self.param_env) + .sup(target_ty, fru_ty) + { + Ok(InferOk { obligations, value: () }) => { + self.register_predicates(obligations) + } + // FIXME: Need better diagnostics for `FieldMisMatch` error + Err(_) => self + .report_mismatched_types( + &cause, + target_ty, + fru_ty, + FieldMisMatch( + variant.ident.name, + ident.name, + ), + ) + .emit(), + } + } + fru_ty + }) + .collect() + } + _ => { + return self + .report_mismatched_types( + &self.misc(base_expr.span), + adt_ty, + base_ty, + Sorts(expected_found_bool(true, adt_ty, base_ty)), + ) + .emit(); + } + } + } + _ => { + return self + .tcx + .sess + .emit_err(FunctionalRecordUpdateOnNonStruct { span: base_expr.span }); + } + } + } else { + self.check_expr_has_type_or_error(base_expr, adt_ty, |_| { + let base_ty = self.check_expr(base_expr); + let same_adt = match (adt_ty.kind(), base_ty.kind()) { + (ty::Adt(adt, _), ty::Adt(base_adt, _)) if adt == base_adt => true, + _ => false, + }; + if self.tcx.sess.is_nightly_build() && same_adt { + feature_err( + &self.tcx.sess.parse_sess, + sym::type_changing_struct_update, + base_expr.span, + "type changing struct updating is experimental", + ) + .emit(); + } + }); + match adt_ty.kind() { + ty::Adt(adt, substs) if adt.is_struct() => variant + .fields + .iter() + .map(|f| { + self.normalize_associated_types_in(expr_span, f.ty(self.tcx, substs)) + }) + .collect(), + _ => { + return self + .tcx + .sess + .emit_err(FunctionalRecordUpdateOnNonStruct { span: base_expr.span }); + } + } + }; + self.typeck_results.borrow_mut().fru_field_types_mut().insert(expr_id, fru_tys); + } else if kind_name != "union" && !remaining_fields.is_empty() { let inaccessible_remaining_fields = remaining_fields.iter().any(|(_, (_, field))| { !field.vis.is_accessible_from(tcx.parent_module(expr_id).to_def_id(), tcx) }); @@ -1405,8 +1551,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.report_missing_fields(adt_ty, span, remaining_fields); } } - - error_happened } fn check_struct_fields_on_error( @@ -1632,7 +1776,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .filter_map(|field| { // ignore already set fields and private fields from non-local crates if skip.iter().any(|&x| x == field.ident.name) - || (!variant.def_id.is_local() && field.vis != Visibility::Public) + || (!variant.def_id.is_local() && !field.vis.is_public()) { None } else { @@ -1928,7 +2072,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn point_at_param_definition(&self, err: &mut DiagnosticBuilder<'_>, param: ty::ParamTy) { let generics = self.tcx.generics_of(self.body_id.owner.to_def_id()); let generic_param = generics.type_param(¶m, self.tcx); - if let ty::GenericParamDefKind::Type { synthetic: Some(..), .. } = generic_param.kind { + if let ty::GenericParamDefKind::Type { synthetic: true, .. } = generic_param.kind { return; } let param_def_id = generic_param.def_id; @@ -2058,8 +2202,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Option<(&Vec, SubstsRef<'tcx>)> { debug!("get_field_candidates(span: {:?}, base_t: {:?}", span, base_t); - let mut autoderef = self.autoderef(span, base_t); - while let Some((base_t, _)) = autoderef.next() { + for (base_t, _) in self.autoderef(span, base_t) { match base_t.kind() { ty::Adt(base_def, substs) if !base_def.is_enum() => { let fields = &base_def.non_enum_variant().fields; diff --git a/compiler/rustc_typeck/src/check/fallback.rs b/compiler/rustc_typeck/src/check/fallback.rs index 296e45337e..e5da33d113 100644 --- a/compiler/rustc_typeck/src/check/fallback.rs +++ b/compiler/rustc_typeck/src/check/fallback.rs @@ -176,7 +176,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { .type_var_origin(ty) .map(|origin| origin.span) .unwrap_or(rustc_span::DUMMY_SP); - let oty = self.inner.borrow().opaque_types_vars.get(ty).map(|v| *v); + let oty = self.inner.borrow().opaque_types_vars.get(ty).copied(); if let Some(opaque_ty) = oty { debug!( "fallback_opaque_type_vars(ty={:?}): falling back to opaque type {:?}", diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index ac4bb65224..142a0a8fc2 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -35,7 +35,6 @@ use rustc_span::source_map::{original_sp, DUMMY_SP}; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{self, BytePos, MultiSpan, Span}; use rustc_trait_selection::infer::InferCtxtExt as _; -use rustc_trait_selection::opaque_types::InferCtxtExt as _; use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; use rustc_trait_selection::traits::{ self, ObligationCause, ObligationCauseCode, StatementAsExpression, TraitEngine, TraitEngineExt, @@ -587,38 +586,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - /// Given a fully substituted set of bounds (`generic_bounds`), and the values with which each - /// type/region parameter was instantiated (`substs`), creates and registers suitable - /// trait/region obligations. - /// - /// For example, if there is a function: - /// - /// ``` - /// fn foo<'a,T:'a>(...) - /// ``` - /// - /// and a reference: - /// - /// ``` - /// let f = foo; - /// ``` - /// - /// Then we will create a fresh region variable `'$0` and a fresh type variable `$1` for `'a` - /// and `T`. This routine will add a region obligation `$1:'$0` and register it locally. - pub fn add_obligations_for_parameters( - &self, - cause: traits::ObligationCause<'tcx>, - predicates: ty::InstantiatedPredicates<'tcx>, - ) { - assert!(!predicates.has_escaping_bound_vars()); - - debug!("add_obligations_for_parameters(predicates={:?})", predicates); - - for obligation in traits::predicates_for_generics(cause, self.param_env, predicates) { - self.register_predicate(obligation); - } - } - // FIXME(arielb1): use this instead of field.ty everywhere // Only for fields! Returns for methods> // Indifferent to privacy flags @@ -643,11 +610,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { #[instrument(skip(self), level = "debug")] pub(in super::super) fn select_all_obligations_or_error(&self) { - if let Err(errors) = self + let errors = self .fulfillment_cx .borrow_mut() - .select_all_with_constness_or_error(&self, self.inh.constness) - { + .select_all_with_constness_or_error(&self, self.inh.constness); + + if !errors.is_empty() { self.report_fulfillment_errors(&errors, self.inh.body_id, false); } } @@ -658,13 +626,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fallback_has_occurred: bool, mutate_fulfillment_errors: impl Fn(&mut Vec>), ) { - let result = self + let mut result = self .fulfillment_cx .borrow_mut() .select_with_constness_where_possible(self, self.inh.constness); - if let Err(mut errors) = result { - mutate_fulfillment_errors(&mut errors); - self.report_fulfillment_errors(&errors, self.inh.body_id, fallback_has_occurred); + if !result.is_empty() { + mutate_fulfillment_errors(&mut result); + self.report_fulfillment_errors(&result, self.inh.body_id, fallback_has_occurred); } } @@ -794,14 +762,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // we can. We don't care if some things turn // out unconstrained or ambiguous, as we're // just trying to get hints here. - self.save_and_restore_in_snapshot_flag(|_| { + let errors = self.save_and_restore_in_snapshot_flag(|_| { let mut fulfill = >::new(self.tcx); for obligation in ok.obligations { fulfill.register_predicate_obligation(self, obligation); } fulfill.select_where_possible(self) - }) - .map_err(|_| ())?; + }); + + if !errors.is_empty() { + return Err(()); + } } Err(_) => return Err(()), } @@ -949,7 +920,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut err = rustc_errors::struct_span_err!( self.sess(), self_ty.span, - E0783, + E0782, "{}", msg, ); @@ -1519,20 +1490,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Add all the obligations that are required, substituting and normalized appropriately. #[tracing::instrument(level = "debug", skip(self, span, def_id, substs))] - fn add_required_obligations(&self, span: Span, def_id: DefId, substs: &SubstsRef<'tcx>) { - let (bounds, spans) = self.instantiate_bounds(span, def_id, &substs); + crate fn add_required_obligations(&self, span: Span, def_id: DefId, substs: &SubstsRef<'tcx>) { + let (bounds, _) = self.instantiate_bounds(span, def_id, &substs); - for (i, mut obligation) in traits::predicates_for_generics( + for obligation in traits::predicates_for_generics( traits::ObligationCause::new(span, self.body_id, traits::ItemObligation(def_id)), self.param_env, bounds, - ) - .enumerate() - { - // This makes the error point at the bound, but we want to point at the argument - if let Some(span) = spans.get(i) { - obligation.cause.make_mut().code = traits::BindingObligation(def_id, *span); - } + ) { self.register_predicate(obligation); } } diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index 551522334a..74d7f0a80b 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -370,6 +370,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise. let coerce_ty = expected.only_has_type(self).unwrap_or(formal_ty); + final_arg_types.push((i, checked_ty, coerce_ty)); + // Cause selection errors caused by resolving a single argument to point at the // argument and not the call. This is otherwise redundant with the `demand_coerce` // call immediately after, but it lets us customize the span pointed to in the @@ -377,38 +379,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let _ = self.resolve_vars_with_obligations_and_mutate_fulfillment( coerce_ty, |errors| { - // This is not coming from a macro or a `derive`. - if sp.desugaring_kind().is_none() - && !arg.span.from_expansion() - // Do not change the spans of `async fn`s. - && !matches!( - expr.kind, - hir::ExprKind::Call( - hir::Expr { - kind: hir::ExprKind::Path(hir::QPath::LangItem(_, _)), - .. - }, - _ - ) - ) { - for error in errors { - error.obligation.cause.make_mut().span = arg.span; - let code = error.obligation.cause.code.clone(); - error.obligation.cause.make_mut().code = - ObligationCauseCode::FunctionArgumentObligation { - arg_hir_id: arg.hir_id, - call_hir_id: expr.hir_id, - parent_code: Lrc::new(code), - }; - } - } + self.point_at_type_arg_instead_of_call_if_possible(errors, expr); + self.point_at_arg_instead_of_call_if_possible( + errors, + &final_arg_types, + expr, + sp, + args, + ); }, ); // We're processing function arguments so we definitely want to use // two-phase borrows. self.demand_coerce(&arg, checked_ty, coerce_ty, None, AllowTwoPhase::Yes); - final_arg_types.push((i, checked_ty, coerce_ty)); // 3. Relate the expected type and the formal one, // if the expected type was used for the coercion. @@ -525,10 +509,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.write_user_type_annotation_from_substs(hir_id, did, substs, None); // Check bounds on type arguments used in the path. - let (bounds, _) = self.instantiate_bounds(path_span, did, substs); - let cause = - traits::ObligationCause::new(path_span, self.body_id, traits::ItemObligation(did)); - self.add_obligations_for_parameters(cause, bounds); + self.add_required_obligations(path_span, did, substs); Some((variant, ty)) } else { @@ -756,6 +737,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &mut |err| { if let Some(expected_ty) = expected.only_has_type(self) { self.consider_hint_about_removing_semicolon(blk, expected_ty, err); + if expected_ty == self.tcx.types.bool { + // If this is caused by a missing `let` in a `while let`, + // silence this redundant error, as we already emit E0070. + let parent = self.tcx.hir().get_parent_node(blk.hir_id); + let parent = self.tcx.hir().get_parent_node(parent); + let parent = self.tcx.hir().get_parent_node(parent); + let parent = self.tcx.hir().get_parent_node(parent); + let parent = self.tcx.hir().get_parent_node(parent); + match self.tcx.hir().find(parent) { + Some(hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Loop(_, _, hir::LoopSource::While, _), + .. + })) => { + err.delay_as_bug(); + } + _ => {} + } + } } if let Some(fn_span) = fn_span { err.span_label( @@ -973,45 +972,79 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { continue; } - if let ty::PredicateKind::Trait(predicate) = - error.obligation.predicate.kind().skip_binder() - { - // Collect the argument position for all arguments that could have caused this - // `FulfillmentError`. - let mut referenced_in = final_arg_types - .iter() - .map(|&(i, checked_ty, _)| (i, checked_ty)) - .chain(final_arg_types.iter().map(|&(i, _, coerced_ty)| (i, coerced_ty))) - .flat_map(|(i, ty)| { - let ty = self.resolve_vars_if_possible(ty); - // We walk the argument type because the argument's type could have - // been `Option`, but the `FulfillmentError` references `T`. - if ty.walk(self.tcx).any(|arg| arg == predicate.self_ty().into()) { - Some(i) - } else { - None - } - }) - .collect::>(); - - // Both checked and coerced types could have matched, thus we need to remove - // duplicates. - - // We sort primitive type usize here and can use unstable sort - referenced_in.sort_unstable(); - referenced_in.dedup(); - - if let (Some(ref_in), None) = (referenced_in.pop(), referenced_in.pop()) { - // We make sure that only *one* argument matches the obligation failure - // and we assign the obligation's span to its expression's. - error.obligation.cause.make_mut().span = args[ref_in].span; - let code = error.obligation.cause.code.clone(); - error.obligation.cause.make_mut().code = - ObligationCauseCode::FunctionArgumentObligation { - arg_hir_id: args[ref_in].hir_id, - call_hir_id: expr.hir_id, - parent_code: Lrc::new(code), - }; + // Peel derived obligation, because it's the type that originally + // started this inference chain that matters, not the one we wound + // up with at the end. + fn unpeel_to_top( + mut code: Lrc>, + ) -> Lrc> { + let mut result_code = code.clone(); + loop { + let parent = match &*code { + ObligationCauseCode::BuiltinDerivedObligation(c) + | ObligationCauseCode::ImplDerivedObligation(c) + | ObligationCauseCode::DerivedObligation(c) => c.parent_code.clone(), + _ => break, + }; + result_code = std::mem::replace(&mut code, parent); + } + result_code + } + let self_: ty::subst::GenericArg<'_> = match &*unpeel_to_top(Lrc::new(error.obligation.cause.code.clone())) { + ObligationCauseCode::BuiltinDerivedObligation(code) | + ObligationCauseCode::ImplDerivedObligation(code) | + ObligationCauseCode::DerivedObligation(code) => { + code.parent_trait_ref.self_ty().skip_binder().into() + } + _ if let ty::PredicateKind::Trait(predicate) = + error.obligation.predicate.kind().skip_binder() => { + predicate.self_ty().into() + } + _ => continue, + }; + let self_ = self.resolve_vars_if_possible(self_); + + // Collect the argument position for all arguments that could have caused this + // `FulfillmentError`. + let mut referenced_in = final_arg_types + .iter() + .map(|&(i, checked_ty, _)| (i, checked_ty)) + .chain(final_arg_types.iter().map(|&(i, _, coerced_ty)| (i, coerced_ty))) + .flat_map(|(i, ty)| { + let ty = self.resolve_vars_if_possible(ty); + // We walk the argument type because the argument's type could have + // been `Option`, but the `FulfillmentError` references `T`. + if ty.walk(self.tcx).any(|arg| arg == self_) { Some(i) } else { None } + }) + .collect::>(); + + // Both checked and coerced types could have matched, thus we need to remove + // duplicates. + + // We sort primitive type usize here and can use unstable sort + referenced_in.sort_unstable(); + referenced_in.dedup(); + + if let (Some(ref_in), None) = (referenced_in.pop(), referenced_in.pop()) { + // Do not point at the inside of a macro. + // That would often result in poor error messages. + if args[ref_in].span.from_expansion() { + return; + } + // We make sure that only *one* argument matches the obligation failure + // and we assign the obligation's span to its expression's. + error.obligation.cause.make_mut().span = args[ref_in].span; + let code = error.obligation.cause.code.clone(); + error.obligation.cause.make_mut().code = + ObligationCauseCode::FunctionArgumentObligation { + arg_hir_id: args[ref_in].hir_id, + call_hir_id: expr.hir_id, + parent_code: Lrc::new(code), + }; + } else if error.obligation.cause.make_mut().span == call_sp { + // Make function calls point at the callee, not the whole thing. + if let hir::ExprKind::Call(callee, _) = expr.kind { + error.obligation.cause.make_mut().span = callee.span; } } } @@ -1027,34 +1060,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { call_expr: &'tcx hir::Expr<'tcx>, ) { if let hir::ExprKind::Call(path, _) = &call_expr.kind { - if let hir::ExprKind::Path(qpath) = &path.kind { - if let hir::QPath::Resolved(_, path) = &qpath { - for error in errors { - if let ty::PredicateKind::Trait(predicate) = - error.obligation.predicate.kind().skip_binder() + if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = &path.kind { + for error in errors { + if let ty::PredicateKind::Trait(predicate) = + error.obligation.predicate.kind().skip_binder() + { + // If any of the type arguments in this path segment caused the + // `FulfillmentError`, point at its span (#61860). + for arg in path + .segments + .iter() + .filter_map(|seg| seg.args.as_ref()) + .flat_map(|a| a.args.iter()) { - // If any of the type arguments in this path segment caused the - // `FulfillmentError`, point at its span (#61860). - for arg in path - .segments - .iter() - .filter_map(|seg| seg.args.as_ref()) - .flat_map(|a| a.args.iter()) - { - if let hir::GenericArg::Type(hir_ty) = &arg { - if let hir::TyKind::Path(hir::QPath::TypeRelative(..)) = - &hir_ty.kind - { - // Avoid ICE with associated types. As this is best - // effort only, it's ok to ignore the case. It - // would trigger in `is_send::();` - // from `typeck-default-trait-impl-assoc-type.rs`. - } else { - let ty = >::ast_ty_to_ty(self, hir_ty); - let ty = self.resolve_vars_if_possible(ty); - if ty == predicate.self_ty() { - error.obligation.cause.make_mut().span = hir_ty.span; - } + if let hir::GenericArg::Type(hir_ty) = &arg { + if let hir::TyKind::Path(hir::QPath::TypeRelative(..)) = + &hir_ty.kind + { + // Avoid ICE with associated types. As this is best + // effort only, it's ok to ignore the case. It + // would trigger in `is_send::();` + // from `typeck-default-trait-impl-assoc-type.rs`. + } else { + let ty = >::ast_ty_to_ty(self, hir_ty); + let ty = self.resolve_vars_if_possible(ty); + if ty == predicate.self_ty() { + error.obligation.cause.make_mut().span = hir_ty.span; } } } diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs index dcc635a1f0..6c7d3a0c9c 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs @@ -14,6 +14,7 @@ use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, Binder, Ty}; use rustc_span::symbol::{kw, sym}; +use rustc_middle::ty::subst::GenericArgKind; use std::iter; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -232,48 +233,72 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let is_struct_pat_shorthand_field = 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::zip(iter::repeat(&expr_text), &methods) - .filter_map(|(receiver, method)| { - let method_call = format!(".{}()", method.ident); - if receiver.ends_with(&method_call) { - None // do not suggest code that is already there (#53348) - } else { - let method_call_list = [".to_vec()", ".to_string()"]; - let mut sugg = if receiver.ends_with(".clone()") - && method_call_list.contains(&method_call.as_str()) - { - let max_len = receiver.rfind('.').unwrap(); - vec![( - expr.span, - format!("{}{}", &receiver[..max_len], method_call), - )] + if !methods.is_empty() { + if let Ok(expr_text) = self.sess().source_map().span_to_snippet(expr.span) { + 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) { + None // do not suggest code that is already there (#53348) } else { - if expr.precedence().order() < ExprPrecedence::MethodCall.order() { - vec![ - (expr.span.shrink_to_lo(), "(".to_string()), - (expr.span.shrink_to_hi(), format!("){}", method_call)), - ] + let method_call_list = [".to_vec()", ".to_string()"]; + let mut sugg = if receiver.ends_with(".clone()") + && method_call_list.contains(&method_call.as_str()) + { + let max_len = receiver.rfind('.').unwrap(); + vec![( + expr.span, + format!("{}{}", &receiver[..max_len], method_call), + )] } else { - vec![(expr.span.shrink_to_hi(), method_call)] + if expr.precedence().order() + < ExprPrecedence::MethodCall.order() + { + vec![ + (expr.span.shrink_to_lo(), "(".to_string()), + (expr.span.shrink_to_hi(), format!("){}", method_call)), + ] + } else { + vec![(expr.span.shrink_to_hi(), method_call)] + } + }; + if is_struct_pat_shorthand_field { + sugg.insert( + 0, + (expr.span.shrink_to_lo(), format!("{}: ", receiver)), + ); } - }; - if is_struct_pat_shorthand_field { - sugg.insert( - 0, - (expr.span.shrink_to_lo(), format!("{}: ", receiver)), + Some(sugg) + } + }) + .peekable(); + if suggestions.peek().is_some() { + err.multipart_suggestions( + "try using a conversion method", + suggestions, + Applicability::MaybeIncorrect, + ); + } + } + } else if found.to_string().starts_with("Option<") + && expected.to_string() == "Option<&str>" + { + if let ty::Adt(_def, subst) = found.kind() { + if subst.len() != 0 { + if let GenericArgKind::Type(ty) = subst[0].unpack() { + let peeled = ty.peel_refs().to_string(); + if peeled == "String" { + let ref_cnt = ty.to_string().len() - peeled.len(); + let result = format!(".map(|x| &*{}x)", "*".repeat(ref_cnt)); + err.span_suggestion_verbose( + expr.span.shrink_to_hi(), + "try converting the passed type into a `&str`", + result, + Applicability::MaybeIncorrect, ); } - Some(sugg) } - }) - .peekable(); - if suggestions.peek().is_some() { - err.multipart_suggestions( - "try using a conversion method", - suggestions, - Applicability::MaybeIncorrect, - ); + } } } } diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs index b0cb8443bf..6314f2aba4 100644 --- a/compiler/rustc_typeck/src/check/intrinsic.rs +++ b/compiler/rustc_typeck/src/check/intrinsic.rs @@ -324,9 +324,10 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { sym::unlikely => (0, vec![tcx.types.bool], tcx.types.bool), sym::discriminant_value => { - let assoc_items = - tcx.associated_items(tcx.lang_items().discriminant_kind_trait().unwrap()); - let discriminant_def_id = assoc_items.in_definition_order().next().unwrap().def_id; + let assoc_items = tcx.associated_item_def_ids( + tcx.require_lang_item(hir::LangItem::DiscriminantKind, None), + ); + let discriminant_def_id = assoc_items[0]; let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0) }; ( diff --git a/compiler/rustc_typeck/src/check/method/confirm.rs b/compiler/rustc_typeck/src/check/method/confirm.rs index dc54f63f49..dabfe92190 100644 --- a/compiler/rustc_typeck/src/check/method/confirm.rs +++ b/compiler/rustc_typeck/src/check/method/confirm.rs @@ -120,7 +120,12 @@ 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() { - self.add_obligations(self.tcx.mk_fn_ptr(method_sig), all_substs, method_predicates); + self.add_obligations( + self.tcx.mk_fn_ptr(method_sig), + all_substs, + method_predicates, + pick.item.def_id, + ); } // Create the final `MethodCallee`. @@ -162,7 +167,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { match &pick.autoref_or_ptr_adjustment { Some(probe::AutorefOrPtrAdjustment::Autoref { mutbl, unsize }) => { - let region = self.next_region_var(infer::Autoref(self.span, pick.item)); + let region = self.next_region_var(infer::Autoref(self.span)); target = self.tcx.mk_ref(region, ty::TypeAndMut { mutbl: *mutbl, ty: target }); let mutbl = match mutbl { hir::Mutability::Not => AutoBorrowMutability::Not, @@ -471,16 +476,23 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { fty: Ty<'tcx>, all_substs: SubstsRef<'tcx>, method_predicates: ty::InstantiatedPredicates<'tcx>, + def_id: DefId, ) { debug!( - "add_obligations: fty={:?} all_substs={:?} method_predicates={:?}", - fty, all_substs, method_predicates + "add_obligations: fty={:?} all_substs={:?} method_predicates={:?} def_id={:?}", + fty, all_substs, method_predicates, def_id ); - self.add_obligations_for_parameters( - traits::ObligationCause::misc(self.span, self.body_id), + // FIXME: could replace with the following, but we already calculated `method_predicates`, + // so we just call `predicates_for_generics` directly to avoid redoing work. + // `self.add_required_obligations(self.span, def_id, &all_substs);` + for obligation in traits::predicates_for_generics( + traits::ObligationCause::new(self.span, self.body_id, traits::ItemObligation(def_id)), + self.param_env, method_predicates, - ); + ) { + self.register_predicate(obligation); + } // this is a projection from a trait reference, so we have to // make sure that the trait reference inputs are well-formed. diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs index f0f2470e80..dbc1d4ec19 100644 --- a/compiler/rustc_typeck/src/check/method/mod.rs +++ b/compiler/rustc_typeck/src/check/method/mod.rs @@ -12,6 +12,7 @@ pub use self::CandidateSource::*; pub use self::MethodError::*; use crate::check::FnCtxt; +use crate::ObligationCause; use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; @@ -71,7 +72,8 @@ pub enum MethodError<'tcx> { #[derive(Debug)] pub struct NoMatchData<'tcx> { pub static_candidates: Vec, - pub unsatisfied_predicates: Vec<(ty::Predicate<'tcx>, Option>)>, + pub unsatisfied_predicates: + Vec<(ty::Predicate<'tcx>, Option>, Option>)>, pub out_of_scope_traits: Vec, pub lev_candidate: Option, pub mode: probe::Mode, @@ -80,7 +82,11 @@ pub struct NoMatchData<'tcx> { impl<'tcx> NoMatchData<'tcx> { pub fn new( static_candidates: Vec, - unsatisfied_predicates: Vec<(ty::Predicate<'tcx>, Option>)>, + unsatisfied_predicates: Vec<( + ty::Predicate<'tcx>, + Option>, + Option>, + )>, out_of_scope_traits: Vec, lev_candidate: Option, mode: probe::Mode, diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index 6eeb28e32f..9fd7e8c4da 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -78,7 +78,8 @@ struct ProbeContext<'a, 'tcx> { /// Collects near misses when trait bounds for type parameters are unsatisfied and is only used /// for error reporting - unsatisfied_predicates: Vec<(ty::Predicate<'tcx>, Option>)>, + unsatisfied_predicates: + Vec<(ty::Predicate<'tcx>, Option>, Option>)>, is_suggestion: IsSuggestion, @@ -92,7 +93,7 @@ impl<'a, 'tcx> Deref for ProbeContext<'a, 'tcx> { } } -#[derive(Debug)] +#[derive(Debug, Clone)] struct Candidate<'tcx> { // Candidates are (I'm not quite sure, but they are mostly) basically // some metadata on top of a `ty::AssocItem` (without substs). @@ -132,7 +133,7 @@ struct Candidate<'tcx> { import_ids: SmallVec<[LocalDefId; 1]>, } -#[derive(Debug)] +#[derive(Debug, Clone)] enum CandidateKind<'tcx> { InherentImplCandidate( SubstsRef<'tcx>, @@ -204,6 +205,7 @@ pub struct Pick<'tcx> { /// Indicates that we want to add an autoref (and maybe also unsize it), or if the receiver is /// `*mut T`, convert it to `*const T`. pub autoref_or_ptr_adjustment: Option>, + pub self_ty: Ty<'tcx>, } #[derive(Clone, Debug, PartialEq, Eq)] @@ -1101,13 +1103,37 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } fn pick_core(&mut self) -> Option> { - let steps = self.steps.clone(); + let mut unstable_candidates = Vec::new(); + let pick = self.pick_all_method(Some(&mut unstable_candidates)); + + // In this case unstable picking is done by `pick_method`. + if !self.tcx.sess.opts.debugging_opts.pick_stable_methods_before_any_unstable { + return pick; + } - // find the first step that works + match pick { + // Emit a lint if there are unstable candidates alongside the stable ones. + // + // We suppress warning if we're picking the method only because it is a + // suggestion. + Some(Ok(ref p)) if !self.is_suggestion.0 && !unstable_candidates.is_empty() => { + self.emit_unstable_name_collision_hint(p, &unstable_candidates); + pick + } + Some(_) => pick, + None => self.pick_all_method(None), + } + } + + fn pick_all_method( + &mut self, + mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>, + ) -> Option> { + let steps = self.steps.clone(); steps .iter() .filter(|step| { - debug!("pick_core: step={:?}", step); + debug!("pick_all_method: step={:?}", step); // skip types that are from a type error or that would require dereferencing // a raw pointer !step.self_ty.references_error() && !step.from_unsafe_deref @@ -1123,11 +1149,30 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { .unwrap_or_else(|_| { span_bug!(self.span, "{:?} was applicable but now isn't?", step.self_ty) }); - self.pick_by_value_method(step, self_ty).or_else(|| { - self.pick_autorefd_method(step, self_ty, hir::Mutability::Not) - .or_else(|| self.pick_autorefd_method(step, self_ty, hir::Mutability::Mut)) - .or_else(|| self.pick_const_ptr_method(step, self_ty)) - }) + self.pick_by_value_method(step, self_ty, unstable_candidates.as_deref_mut()) + .or_else(|| { + self.pick_autorefd_method( + step, + self_ty, + hir::Mutability::Not, + unstable_candidates.as_deref_mut(), + ) + .or_else(|| { + self.pick_autorefd_method( + step, + self_ty, + hir::Mutability::Mut, + unstable_candidates.as_deref_mut(), + ) + }) + .or_else(|| { + self.pick_const_ptr_method( + step, + self_ty, + unstable_candidates.as_deref_mut(), + ) + }) + }) }) .next() } @@ -1142,12 +1187,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { &mut self, step: &CandidateStep<'tcx>, self_ty: Ty<'tcx>, + unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>, ) -> Option> { if step.unsize { return None; } - self.pick_method(self_ty).map(|r| { + self.pick_method(self_ty, unstable_candidates).map(|r| { r.map(|mut pick| { pick.autoderefs = step.autoderefs; @@ -1170,6 +1216,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { step: &CandidateStep<'tcx>, self_ty: Ty<'tcx>, mutbl: hir::Mutability, + unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>, ) -> Option> { let tcx = self.tcx; @@ -1177,7 +1224,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let region = tcx.lifetimes.re_erased; let autoref_ty = tcx.mk_ref(region, ty::TypeAndMut { ty: self_ty, mutbl }); - self.pick_method(autoref_ty).map(|r| { + self.pick_method(autoref_ty, unstable_candidates).map(|r| { r.map(|mut pick| { pick.autoderefs = step.autoderefs; pick.autoref_or_ptr_adjustment = Some(AutorefOrPtrAdjustment::Autoref { @@ -1196,6 +1243,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { &mut self, step: &CandidateStep<'tcx>, self_ty: Ty<'tcx>, + unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>, ) -> Option> { // Don't convert an unsized reference to ptr if step.unsize { @@ -1209,7 +1257,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let const_self_ty = ty::TypeAndMut { ty, mutbl: hir::Mutability::Not }; let const_ptr_ty = self.tcx.mk_ptr(const_self_ty); - self.pick_method(const_ptr_ty).map(|r| { + self.pick_method(const_ptr_ty, unstable_candidates).map(|r| { r.map(|mut pick| { pick.autoderefs = step.autoderefs; pick.autoref_or_ptr_adjustment = Some(AutorefOrPtrAdjustment::ToConstPtr); @@ -1218,8 +1266,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { }) } - fn pick_method(&mut self, self_ty: Ty<'tcx>) -> Option> { - debug!("pick_method(self_ty={})", self.ty_to_string(self_ty)); + fn pick_method_with_unstable(&mut self, self_ty: Ty<'tcx>) -> Option> { + debug!("pick_method_with_unstable(self_ty={})", self.ty_to_string(self_ty)); let mut possibly_unsatisfied_predicates = Vec::new(); let mut unstable_candidates = Vec::new(); @@ -1241,7 +1289,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // // We suppress warning if we're picking the method only because it is a // suggestion. - self.emit_unstable_name_collision_hint(p, &unstable_candidates, self_ty); + self.emit_unstable_name_collision_hint(p, &unstable_candidates); } } return Some(pick); @@ -1251,7 +1299,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { debug!("searching unstable candidates"); let res = self.consider_candidates( self_ty, - unstable_candidates.into_iter().map(|(c, _)| c), + unstable_candidates.iter().map(|(c, _)| c), &mut possibly_unsatisfied_predicates, None, ); @@ -1261,6 +1309,42 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { res } + fn pick_method( + &mut self, + self_ty: Ty<'tcx>, + mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>, + ) -> Option> { + if !self.tcx.sess.opts.debugging_opts.pick_stable_methods_before_any_unstable { + return self.pick_method_with_unstable(self_ty); + } + + debug!("pick_method(self_ty={})", self.ty_to_string(self_ty)); + + let mut possibly_unsatisfied_predicates = Vec::new(); + + for (kind, candidates) in + &[("inherent", &self.inherent_candidates), ("extension", &self.extension_candidates)] + { + debug!("searching {} candidates", kind); + let res = self.consider_candidates( + self_ty, + candidates.iter(), + &mut possibly_unsatisfied_predicates, + unstable_candidates.as_deref_mut(), + ); + if let Some(pick) = res { + return Some(pick); + } + } + + // `pick_method` may be called twice for the same self_ty if no stable methods + // match. Only extend once. + if unstable_candidates.is_some() { + self.unsatisfied_predicates.extend(possibly_unsatisfied_predicates); + } + None + } + fn consider_candidates<'b, ProbesIter>( &self, self_ty: Ty<'tcx>, @@ -1268,11 +1352,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { possibly_unsatisfied_predicates: &mut Vec<( ty::Predicate<'tcx>, Option>, + Option>, )>, - unstable_candidates: Option<&mut Vec<(&'b Candidate<'tcx>, Symbol)>>, + unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>, ) -> Option> where ProbesIter: Iterator> + Clone, + 'tcx: 'b, { let mut applicable_candidates: Vec<_> = probes .clone() @@ -1285,7 +1371,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { debug!("applicable_candidates: {:?}", applicable_candidates); if applicable_candidates.len() > 1 { - if let Some(pick) = self.collapse_candidates_to_trait_pick(&applicable_candidates[..]) { + if let Some(pick) = + self.collapse_candidates_to_trait_pick(self_ty, &applicable_candidates[..]) + { return Some(Ok(pick)); } } @@ -1295,7 +1383,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { if let stability::EvalResult::Deny { feature, .. } = self.tcx.eval_stability(p.item.def_id, None, self.span, None) { - uc.push((p, feature)); + uc.push((p.clone(), feature)); return false; } true @@ -1309,7 +1397,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { applicable_candidates.pop().map(|(probe, status)| { if status == ProbeResult::Match { - Ok(probe.to_unadjusted_pick()) + Ok(probe.to_unadjusted_pick(self_ty)) } else { Err(MethodError::BadReturnType) } @@ -1319,8 +1407,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { fn emit_unstable_name_collision_hint( &self, stable_pick: &Pick<'_>, - unstable_candidates: &[(&Candidate<'tcx>, Symbol)], - self_ty: Ty<'tcx>, + unstable_candidates: &[(Candidate<'tcx>, Symbol)], ) { self.tcx.struct_span_lint_hir( lint::builtin::UNSTABLE_NAME_COLLISIONS, @@ -1351,7 +1438,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { "use the fully qualified path to the associated const", format!( "<{} as {}>::{}", - self_ty, + stable_pick.self_ty, self.tcx.def_path_str(def_id), stable_pick.item.ident ), @@ -1412,6 +1499,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { possibly_unsatisfied_predicates: &mut Vec<( ty::Predicate<'tcx>, Option>, + Option>, )>, ) -> ProbeResult { debug!("consider_probe: self_ty={:?} probe={:?}", self_ty, probe); @@ -1423,8 +1511,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { .sup(probe.xform_self_ty, self_ty) { Ok(InferOk { obligations, value: () }) => obligations, - Err(_) => { - debug!("--> cannot relate self-types"); + Err(err) => { + debug!("--> cannot relate self-types {:?}", err); return ProbeResult::NoMatch; } }; @@ -1473,7 +1561,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let o = self.resolve_vars_if_possible(o); if !self.predicate_may_hold(&o) { result = ProbeResult::NoMatch; - possibly_unsatisfied_predicates.push((o.predicate, None)); + possibly_unsatisfied_predicates.push(( + o.predicate, + None, + Some(o.cause), + )); } } } @@ -1519,8 +1611,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } else { Some(predicate) }; - possibly_unsatisfied_predicates - .push((nested_predicate, p)); + possibly_unsatisfied_predicates.push(( + nested_predicate, + p, + Some(obligation.cause.clone()), + )); } } } @@ -1528,7 +1623,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // Some nested subobligation of this predicate // failed. let predicate = self.resolve_vars_if_possible(predicate); - possibly_unsatisfied_predicates.push((predicate, None)); + possibly_unsatisfied_predicates.push((predicate, None, None)); } } false @@ -1547,7 +1642,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let o = self.resolve_vars_if_possible(o); if !self.predicate_may_hold(&o) { result = ProbeResult::NoMatch; - possibly_unsatisfied_predicates.push((o.predicate, None)); + possibly_unsatisfied_predicates.push((o.predicate, None, Some(o.cause))); } } @@ -1591,6 +1686,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { /// use, so it's ok to just commit to "using the method from the trait Foo". fn collapse_candidates_to_trait_pick( &self, + self_ty: Ty<'tcx>, probes: &[(&Candidate<'tcx>, ProbeResult)], ) -> Option> { // Do all probes correspond to the same trait? @@ -1610,6 +1706,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { import_ids: probes[0].0.import_ids.clone(), autoderefs: 0, autoref_or_ptr_adjustment: None, + self_ty, }) } @@ -1828,7 +1925,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } impl<'tcx> Candidate<'tcx> { - fn to_unadjusted_pick(&self) -> Pick<'tcx> { + fn to_unadjusted_pick(&self, self_ty: Ty<'tcx>) -> Pick<'tcx> { Pick { item: self.item, kind: match self.kind { @@ -1852,6 +1949,7 @@ impl<'tcx> Candidate<'tcx> { import_ids: self.import_ids.clone(), autoderefs: 0, autoref_or_ptr_adjustment: None, + self_ty, } } } diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 183ebc559a..ca174ed5e8 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -15,9 +15,11 @@ use rustc_middle::ty::print::with_crate_prefix; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; use rustc_span::lev_distance; use rustc_span::symbol::{kw, sym, Ident}; -use rustc_span::{source_map, FileName, MultiSpan, Span}; +use rustc_span::{source_map, FileName, MultiSpan, Span, Symbol}; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; -use rustc_trait_selection::traits::{FulfillmentError, Obligation}; +use rustc_trait_selection::traits::{ + FulfillmentError, Obligation, ObligationCause, ObligationCauseCode, +}; use std::cmp::Ordering; use std::iter; @@ -317,6 +319,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .span_to_snippet(lit.span) .unwrap_or_else(|_| "".to_owned()); + // If this is a floating point literal that ends with '.', + // get rid of it to stop this from becoming a member access. + let snippet = snippet.strip_suffix('.').unwrap_or(&snippet); + err.span_suggestion( lit.span, &format!( @@ -324,7 +330,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { like `{}`", concrete_type ), - format!("{}_{}", snippet, concrete_type), + format!("{snippet}_{concrete_type}"), Applicability::MaybeIncorrect, ); } @@ -478,6 +484,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut label_span_not_found = || { if unsatisfied_predicates.is_empty() { err.span_label(span, format!("{item_kind} not found in `{ty_str}`")); + let is_string_or_ref_str = match actual.kind() { + ty::Ref(_, ty, _) => { + ty.is_str() + || matches!( + ty.kind(), + ty::Adt(adt, _) if self.tcx.is_diagnostic_item(sym::String, adt.did) + ) + } + ty::Adt(adt, _) => self.tcx.is_diagnostic_item(sym::String, adt.did), + _ => false, + }; + if is_string_or_ref_str && item_name.name == sym::iter { + err.span_suggestion_verbose( + item_name.span, + "because of the in-memory representation of `&str`, to obtain \ + an `Iterator` over each of its codepoint use method `chars`", + String::from("chars"), + Applicability::MachineApplicable, + ); + } if let ty::Adt(adt, _) = rcvr_ty.kind() { let mut inherent_impls_candidate = self .tcx @@ -678,27 +704,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let (ty::Param(_), ty::PredicateKind::Trait(p)) = (self_ty.kind(), parent_pred.kind().skip_binder()) { - if let ty::Adt(def, _) = p.trait_ref.self_ty().kind() { - let node = def.did.as_local().map(|def_id| { + let node = match p.trait_ref.self_ty().kind() { + ty::Param(_) => { + // Account for `fn` items like in `issue-35677.rs` to + // suggest restricting its type params. + let did = self.tcx.hir().body_owner_def_id(hir::BodyId { + hir_id: self.body_id, + }); + Some( + self.tcx + .hir() + .get(self.tcx.hir().local_def_id_to_hir_id(did)), + ) + } + ty::Adt(def, _) => def.did.as_local().map(|def_id| { self.tcx .hir() .get(self.tcx.hir().local_def_id_to_hir_id(def_id)) - }); - if let Some(hir::Node::Item(hir::Item { kind, .. })) = node { - if let Some(g) = kind.generics() { - let key = match g.where_clause.predicates { - [.., pred] => (pred.span().shrink_to_hi(), false), - [] => ( - g.where_clause - .span_for_predicates_or_empty_place(), - true, - ), - }; - type_params - .entry(key) - .or_insert_with(FxHashSet::default) - .insert(obligation.to_owned()); - } + }), + _ => None, + }; + if let Some(hir::Node::Item(hir::Item { kind, .. })) = node { + if let Some(g) = kind.generics() { + let key = match g.where_clause.predicates { + [.., pred] => (pred.span().shrink_to_hi(), false), + [] => ( + g.where_clause.span_for_predicates_or_empty_place(), + true, + ), + }; + type_params + .entry(key) + .or_insert_with(FxHashSet::default) + .insert(obligation.to_owned()); } } } @@ -767,22 +805,109 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => None, } }; + + // Find all the requirements that come from a local `impl` block. + let mut skip_list: FxHashSet<_> = Default::default(); + let mut spanned_predicates: FxHashMap = Default::default(); + for (data, p, parent_p) in unsatisfied_predicates + .iter() + .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c))) + .filter_map(|(p, parent, c)| match c.code { + ObligationCauseCode::ImplDerivedObligation(ref data) => { + Some((data, p, parent)) + } + _ => None, + }) + { + let parent_trait_ref = data.parent_trait_ref; + let parent_def_id = parent_trait_ref.def_id(); + let path = parent_trait_ref.print_only_trait_path(); + let tr_self_ty = 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| match self.tcx.hir().get_if_local(impl_def_id) { + Some(Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { .. }), + .. + })) => { + candidates.push(impl_def_id); + } + _ => {} + }, + ); + if let [def_id] = &candidates[..] { + match self.tcx.hir().get_if_local(*def_id) { + Some(Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }), + .. + })) => { + if let Some(pred) = parent_p { + // Done to add the "doesn't satisfy" `span_label`. + let _ = format_pred(*pred); + } + skip_list.insert(p); + 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); + let entry = spanned_predicates.entry(spans.into()); + entry + .or_insert_with(|| (path, tr_self_ty, Vec::new())) + .2 + .push(p); + } + _ => {} + } + } + } + for (span, (path, self_ty, preds)) in spanned_predicates { + err.span_note( + span, + &format!( + "the following trait bounds were not satisfied because of the \ + requirements of the implementation of `{}` for `{}`:\n{}", + path, + self_ty, + preds + .into_iter() + // .map(|pred| format!("{:?}", pred)) + .filter_map(|pred| format_pred(*pred)) + .map(|(p, _)| format!("`{}`", p)) + .collect::>() + .join("\n"), + ), + ); + } + + // The requirements that didn't have an `impl` span to show. let mut bound_list = unsatisfied_predicates .iter() - .filter_map(|(pred, parent_pred)| { - format_pred(*pred).map(|(p, self_ty)| match parent_pred { - None => format!("`{}`", &p), - Some(parent_pred) => match format_pred(*parent_pred) { + .filter(|(pred, _, _parent_pred)| !skip_list.contains(&pred)) + .filter_map(|(pred, parent_pred, _cause)| { + format_pred(*pred).map(|(p, self_ty)| { + collect_type_param_suggestions(self_ty, pred, &p); + match parent_pred { None => format!("`{}`", &p), - Some((parent_p, _)) => { - collect_type_param_suggestions(self_ty, parent_pred, &p); - format!("`{}`\nwhich is required by `{}`", p, parent_p) - } - }, + Some(parent_pred) => match format_pred(*parent_pred) { + None => format!("`{}`", &p), + Some((parent_p, _)) => { + collect_type_param_suggestions( + self_ty, + parent_pred, + &p, + ); + format!("`{}`\nwhich is required by `{}`", p, parent_p) + } + }, + } }) }) .enumerate() .collect::>(); + for ((span, empty_where), obligations) in type_params.into_iter() { restrict_type_params = true; // #74886: Sort here so that the output is always the same. @@ -812,7 +937,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for (span, msg) in bound_spans.into_iter() { err.span_label(span, &msg); } - if !bound_list.is_empty() { + if !bound_list.is_empty() || !skip_list.is_empty() { let bound_list = bound_list .into_iter() .map(|(_, path)| path) @@ -822,9 +947,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.set_primary_message(&format!( "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied" )); - err.note(&format!( - "the following trait bounds were not satisfied:\n{bound_list}" - )); + if !bound_list.is_empty() { + err.note(&format!( + "the following trait bounds were not satisfied:\n{bound_list}" + )); + } self.suggest_derive(&mut err, &unsatisfied_predicates); unsatisfied_bounds = true; @@ -1038,18 +1165,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_note(spans, &msg); } - let preds: Vec<_> = errors.iter().map(|e| (e.obligation.predicate, None)).collect(); + let preds: Vec<_> = errors + .iter() + .map(|e| (e.obligation.predicate, None, Some(e.obligation.cause.clone()))) + .collect(); self.suggest_derive(err, &preds); } fn suggest_derive( &self, err: &mut DiagnosticBuilder<'_>, - unsatisfied_predicates: &Vec<(ty::Predicate<'tcx>, Option>)>, + unsatisfied_predicates: &Vec<( + ty::Predicate<'tcx>, + Option>, + Option>, + )>, ) { let mut derives = Vec::<(String, Span, String)>::new(); let mut traits = Vec::::new(); - for (pred, _) in unsatisfied_predicates { + for (pred, _, _) in unsatisfied_predicates { let trait_pred = match pred.kind().skip_binder() { ty::PredicateKind::Trait(trait_pred) => trait_pred, _ => continue, @@ -1203,6 +1337,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut candidates = valid_out_of_scope_traits; candidates.sort(); candidates.dedup(); + + // `TryFrom` and `FromIterator` have no methods + let edition_fix = candidates + .iter() + .find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did)) + .copied(); + err.help("items from traits can only be used if the trait is in scope"); let msg = format!( "the following {traits_are} implemented but not in scope; \ @@ -1212,6 +1353,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); self.suggest_use_candidates(err, msg, candidates); + if let Some(did) = edition_fix { + err.note(&format!( + "'{}' is included in the prelude starting in Edition 2021", + with_crate_prefix(|| self.tcx.def_path_str(did)) + )); + } + true } else { false @@ -1226,7 +1374,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_name: Ident, source: SelfSource<'tcx>, valid_out_of_scope_traits: Vec, - unsatisfied_predicates: &[(ty::Predicate<'tcx>, Option>)], + unsatisfied_predicates: &[( + ty::Predicate<'tcx>, + Option>, + Option>, + )], unsatisfied_bounds: bool, ) { let mut alt_rcvr_sugg = false; @@ -1237,6 +1389,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.lang_items().deref_trait(), self.tcx.lang_items().deref_mut_trait(), self.tcx.lang_items().drop_trait(), + self.tcx.get_diagnostic_item(sym::AsRef), ]; // Try alternative arbitrary self types that could fulfill this call. // FIXME: probe for all types that *could* be arbitrary self-types, not @@ -1286,7 +1439,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // 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); + // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not + // implement the `AsRef` trait. + let skip = skippable.contains(&did) + || (("Pin::new" == *pre) + && (Symbol::intern("as_ref") == item_name.name)); // 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` @@ -1337,7 +1494,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // this isn't perfect (that is, there are cases when // implementing a trait would be legal but is rejected // here). - unsatisfied_predicates.iter().all(|(p, _)| { + unsatisfied_predicates.iter().all(|(p, _, _)| { match p.kind().skip_binder() { // Hide traits if they are present in predicates as they can be fixed without // having to implement them. @@ -1391,7 +1548,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } // We only want to suggest public or local traits (#45781). - item.vis == ty::Visibility::Public || info.def_id.is_local() + item.vis.is_public() || info.def_id.is_local() }) .is_some() }) @@ -1451,7 +1608,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Node::GenericParam(param) => { let mut impl_trait = false; let has_bounds = - if let hir::GenericParamKind::Type { synthetic: Some(_), .. } = + if let hir::GenericParamKind::Type { synthetic: true, .. } = ¶m.kind { // We've found `fn foo(x: impl Trait)` instead of diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index a037bb6647..7bfd3f0ee8 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -297,9 +297,9 @@ fn primary_body_of( fn has_typeck_results(tcx: TyCtxt<'_>, def_id: DefId) -> bool { // Closures' typeck results come from their outermost function, // as they are part of the same "inference environment". - let outer_def_id = tcx.closure_base_def_id(def_id); - if outer_def_id != def_id { - return tcx.has_typeck_results(outer_def_id); + let typeck_root_def_id = tcx.typeck_root_def_id(def_id); + if typeck_root_def_id != def_id { + return tcx.has_typeck_results(typeck_root_def_id); } if let Some(def_id) = def_id.as_local() { @@ -348,9 +348,9 @@ fn typeck_with_fallback<'tcx>( ) -> &'tcx ty::TypeckResults<'tcx> { // Closures' typeck results come from their outermost function, // as they are part of the same "inference environment". - let outer_def_id = tcx.closure_base_def_id(def_id.to_def_id()).expect_local(); - if outer_def_id != def_id { - return tcx.typeck(outer_def_id); + let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id()).expect_local(); + if typeck_root_def_id != def_id { + return tcx.typeck(typeck_root_def_id); } let id = tcx.hir().local_def_id_to_hir_id(def_id); @@ -535,8 +535,8 @@ fn fn_maybe_err(tcx: TyCtxt<'_>, sp: Span, abi: Abi) { } fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId, span: Span) { - // Only restricted on wasm32 target for now - if !tcx.sess.opts.target_triple.triple().starts_with("wasm32") { + // Only restricted on wasm target for now + if !tcx.sess.target.is_like_wasm { return; } diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index 79e004a47d..f83209f57a 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -42,7 +42,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return_ty }; - self.check_lhs_assignable(lhs, "E0067", &op.span); + self.check_lhs_assignable(lhs, "E0067", op.span); ty } @@ -399,12 +399,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }; if let Ref(_, rty, _) = lhs_ty.kind() { - if { - self.infcx.type_is_copy_modulo_regions(self.param_env, rty, lhs_expr.span) - && self - .lookup_op_method(rty, &[rhs_ty], Op::Binary(op, is_assign)) - .is_ok() - } { + if self.infcx.type_is_copy_modulo_regions(self.param_env, rty, lhs_expr.span) + && self.lookup_op_method(rty, &[rhs_ty], Op::Binary(op, is_assign)).is_ok() + { if let Ok(lstring) = source_map.span_to_snippet(lhs_expr.span) { let msg = &format!( "`{}{}` can be used on `{}`, you can dereference `{}`", @@ -492,7 +489,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { other_ty: Ty<'tcx>, op: hir::BinOp, is_assign: IsAssign, - ) -> bool /* did we suggest to call a function because of missing parenthesis? */ { + ) -> bool /* did we suggest to call a function because of missing parentheses? */ { err.span_label(span, ty.to_string()); if let FnDef(def_id, _) = *ty.kind() { let source_map = self.tcx.sess.source_map(); @@ -502,9 +499,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // FIXME: Instead of exiting early when encountering bound vars in // the function signature, consider keeping the binder here and // propagating it downwards. - let fn_sig = if let Some(fn_sig) = self.tcx.fn_sig(def_id).no_bound_vars() { - fn_sig - } else { + let Some(fn_sig) = self.tcx.fn_sig(def_id).no_bound_vars() else { return false; }; @@ -831,10 +826,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.obligation_for_method(span, trait_did, lhs_ty, Some(other_tys)); let mut fulfill = >::new(self.tcx); fulfill.register_predicate_obligation(self, obligation); - Err(match fulfill.select_where_possible(&self.infcx) { - Err(errors) => errors, - _ => vec![], - }) + Err(fulfill.select_where_possible(&self.infcx)) } } } diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 635219146d..cbf33cf1b7 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -292,7 +292,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // String and byte-string literals result in types `&str` and `&[u8]` respectively. // All other literals result in non-reference types. // As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo {}`. - PatKind::Lit(lt) => match self.check_expr(lt).kind() { + // + // Call `resolve_vars_if_possible` here for inline const blocks. + PatKind::Lit(lt) => match self.resolve_vars_if_possible(self.check_expr(lt)).kind() { ty::Ref(..) => AdjustMode::Pass, _ => AdjustMode::Peel, }, @@ -718,10 +720,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ti: TopInfo<'tcx>, ) -> Ty<'tcx> { // Resolve the path and check the definition for errors. - let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(qpath, pat.hir_id) - { - variant_ty - } else { + let Some((variant, pat_ty)) = self.check_struct_path(qpath, pat.hir_id) else { let err = self.tcx.ty_error(); for field in fields { let ti = TopInfo { parent_pat: Some(pat), ..ti }; diff --git a/compiler/rustc_typeck/src/check/place_op.rs b/compiler/rustc_typeck/src/check/place_op.rs index 849bf1e455..5d9e6ebd50 100644 --- a/compiler/rustc_typeck/src/check/place_op.rs +++ b/compiler/rustc_typeck/src/check/place_op.rs @@ -411,9 +411,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!("convert_place_op_to_mutable: method={:?}", method); self.write_method_call(expr.hir_id, method); - let region = if let ty::Ref(r, _, hir::Mutability::Mut) = method.sig.inputs()[0].kind() { - r - } else { + let ty::Ref(region, _, hir::Mutability::Mut) = method.sig.inputs()[0].kind() else { span_bug!(expr.span, "input to mutable place op is not a mut ref?"); }; diff --git a/compiler/rustc_typeck/src/check/regionck.rs b/compiler/rustc_typeck/src/check/regionck.rs index 7c8b752718..d2d8b14dd9 100644 --- a/compiler/rustc_typeck/src/check/regionck.rs +++ b/compiler/rustc_typeck/src/check/regionck.rs @@ -88,7 +88,6 @@ use rustc_middle::hir::place::{PlaceBase, PlaceWithHirId}; use rustc_middle::ty::adjustment; use rustc_middle::ty::{self, Ty}; use rustc_span::Span; -use rustc_trait_selection::opaque_types::InferCtxtExt as _; use std::ops::Deref; // a variation on try that just returns unit @@ -104,7 +103,7 @@ macro_rules! ignore_err { }; } -trait OutlivesEnvironmentExt<'tcx> { +pub(crate) trait OutlivesEnvironmentExt<'tcx> { fn add_implied_bounds( &mut self, infcx: &InferCtxt<'a, 'tcx>, @@ -340,8 +339,29 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { self.link_fn_params(body.params); self.visit_body(body); self.visit_region_obligations(body_id.hir_id); + } + + fn visit_inline_const(&mut self, id: hir::HirId, body: &'tcx hir::Body<'tcx>) { + debug!("visit_inline_const(id={:?})", id); + + // Save state of current function. We will restore afterwards. + let old_body_id = self.body_id; + let old_body_owner = self.body_owner; + let env_snapshot = self.outlives_environment.push_snapshot_pre_typeck_child(); - self.constrain_opaque_types(self.outlives_environment.free_region_map()); + let body_id = body.id(); + self.body_id = body_id.hir_id; + self.body_owner = self.tcx.hir().body_owner_def_id(body_id); + + self.outlives_environment.save_implied_bounds(body_id.hir_id); + + self.visit_body(body); + self.visit_region_obligations(body_id.hir_id); + + // Restore state from previous function. + self.outlives_environment.pop_snapshot_post_typeck_child(env_snapshot); + self.body_id = old_body_id; + self.body_owner = old_body_owner; } fn visit_region_obligations(&mut self, hir_id: hir::HirId) { @@ -409,13 +429,13 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionCtxt<'a, 'tcx> { // `visit_fn_body`. We will restore afterwards. let old_body_id = self.body_id; let old_body_owner = self.body_owner; - let env_snapshot = self.outlives_environment.push_snapshot_pre_closure(); + let env_snapshot = self.outlives_environment.push_snapshot_pre_typeck_child(); let body = self.tcx.hir().body(body_id); self.visit_fn_body(hir_id, body, span); // Restore state from previous function. - self.outlives_environment.pop_snapshot_post_closure(env_snapshot); + self.outlives_environment.pop_snapshot_post_typeck_child(env_snapshot); self.body_id = old_body_id; self.body_owner = old_body_owner; } @@ -463,6 +483,11 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionCtxt<'a, 'tcx> { intravisit::walk_expr(self, expr); } + hir::ExprKind::ConstBlock(anon_const) => { + let body = self.tcx.hir().body(anon_const.body); + self.visit_inline_const(anon_const.hir_id, body); + } + _ => intravisit::walk_expr(self, expr), } } diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index 67c96703f2..5f5d308a33 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -148,10 +148,17 @@ impl<'a, 'tcx> Visitor<'tcx> for InferBorrowKindVisitor<'a, 'tcx> { } fn visit_expr(&mut self, expr: &'tcx hir::Expr<'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_id, body, cc); + match expr.kind { + hir::ExprKind::Closure(cc, _, body_id, _, _) => { + let body = self.fcx.tcx.hir().body(body_id); + self.visit_body(body); + self.fcx.analyze_closure(expr.hir_id, expr.span, body_id, body, cc); + } + hir::ExprKind::ConstBlock(anon_const) => { + let body = self.fcx.tcx.hir().body(anon_const.body); + self.visit_body(body); + } + _ => {} } intravisit::walk_expr(self, expr); @@ -930,8 +937,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.get_diagnostic_item(sym::unwind_safe_trait), self.tcx.get_diagnostic_item(sym::ref_unwind_safe_trait), ]; - let auto_traits = - vec!["`Clone`", "`Sync`", "`Send`", "`Unpin`", "`UnwindSafe`", "`RefUnwindSafe`"]; + const AUTO_TRAITS: [&str; 6] = + ["`Clone`", "`Sync`", "`Send`", "`Unpin`", "`UnwindSafe`", "`RefUnwindSafe`"]; let root_var_min_capture_list = min_captures.and_then(|m| m.get(&var_hir_id))?; @@ -1004,7 +1011,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // by the root variable but not by the capture for (idx, _) in obligations_should_hold.iter().enumerate() { if !obligations_holds_for_capture[idx] && obligations_should_hold[idx] { - capture_problems.insert(auto_traits[idx]); + capture_problems.insert(AUTO_TRAITS[idx]); } } @@ -1052,11 +1059,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return None; } - let root_var_min_capture_list = if let Some(root_var_min_capture_list) = - min_captures.and_then(|m| m.get(&var_hir_id)) - { - root_var_min_capture_list - } else { + let Some(root_var_min_capture_list) = min_captures.and_then(|m| m.get(&var_hir_id)) else { // The upvar is mentioned within the closure but no path starting from it is // used. This occurs when you have (e.g.) // @@ -1150,9 +1153,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { closure_clause: hir::CaptureBy, min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>, ) -> (Vec, MigrationWarningReason) { - let upvars = if let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) { - upvars - } else { + let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) else { return (Vec::new(), MigrationWarningReason::default()); }; @@ -1756,9 +1757,7 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { diag_expr_id: hir::HirId, ) { let tcx = self.fcx.tcx; - let upvar_id = if let PlaceBase::Upvar(upvar_id) = place_with_id.place.base { - upvar_id - } else { + let PlaceBase::Upvar(upvar_id) = place_with_id.place.base else { return; }; diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index d737fe9ac8..e58faf9a89 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -1,3 +1,4 @@ +use crate::check::regionck::OutlivesEnvironmentExt; use crate::check::{FnCtxt, Inherited}; use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter}; @@ -11,16 +12,21 @@ use rustc_hir::intravisit::Visitor; use rustc_hir::itemlikevisit::ParItemLikeVisitor; use rustc_hir::lang_items::LangItem; use rustc_hir::ItemKind; +use rustc_infer::infer::outlives::env::OutlivesEnvironment; +use rustc_infer::infer::outlives::obligations::TypeOutlives; +use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::infer::{self, RegionckMode, SubregionOrigin}; use rustc_middle::hir::map as hir_map; -use rustc_middle::ty::subst::{InternalSubsts, Subst}; +use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst}; use rustc_middle::ty::trait_def::TraitSpecializationKind; use rustc_middle::ty::{ - self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness, + self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitor, + WithConstness, }; use rustc_session::parse::feature_err; use rustc_span::symbol::{sym, Ident, Symbol}; -use rustc_span::Span; -use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; +use rustc_span::{Span, DUMMY_SP}; +use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, WellFormedLoc}; use std::convert::TryInto; @@ -253,6 +259,362 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { .emit(); } } + + check_gat_where_clauses(tcx, trait_item, encl_trait_def_id); +} + +/// Require that the user writes where clauses on GATs for the implicit +/// outlives bounds involving trait parameters in trait functions and +/// lifetimes passed as GAT substs. See `self-outlives-lint` test. +/// +/// This trait will be our running example. We are currently WF checking the `Item` item... +/// +/// ```rust +/// trait LendingIterator { +/// type Item<'me>; // <-- WF checking this trait item +/// +/// fn next<'a>(&'a mut self) -> Option>; +/// } +/// ``` +fn check_gat_where_clauses( + tcx: TyCtxt<'_>, + trait_item: &hir::TraitItem<'_>, + encl_trait_def_id: DefId, +) { + let item = tcx.associated_item(trait_item.def_id); + // If the current trait item isn't a type, it isn't a GAT + if !matches!(item.kind, ty::AssocKind::Type) { + return; + } + let generics: &ty::Generics = tcx.generics_of(trait_item.def_id); + // If the current associated type doesn't have any (own) params, it's not a GAT + // FIXME(jackh726): we can also warn in the more general case + if generics.params.len() == 0 { + return; + } + let associated_items: &ty::AssocItems<'_> = tcx.associated_items(encl_trait_def_id); + let mut clauses: Option>> = None; + // For every function in this trait... + // In our example, this would be the `next` method + for item in + associated_items.in_definition_order().filter(|item| matches!(item.kind, ty::AssocKind::Fn)) + { + // The clauses we that we would require from this function + let mut function_clauses = FxHashSet::default(); + + let id = hir::HirId::make_owner(item.def_id.expect_local()); + let param_env = tcx.param_env(item.def_id.expect_local()); + + let sig = tcx.fn_sig(item.def_id); + // Get the signature using placeholders. In our example, this would + // convert the late-bound 'a into a free region. + let sig = tcx.liberate_late_bound_regions(item.def_id, sig); + // Collect the arguments that are given to this GAT in the return type + // of the function signature. In our example, the GAT in the return + // type is `::Item<'a>`, so 'a and Self are arguments. + let (regions, types) = + GATSubstCollector::visit(tcx, trait_item.def_id.to_def_id(), sig.output()); + + // If both regions and types are empty, then this GAT isn't in the + // return type, and we shouldn't try to do clause analysis + // (particularly, doing so would end up with an empty set of clauses, + // since the current method would require none, and we take the + // intersection of requirements of all methods) + if types.is_empty() && regions.is_empty() { + continue; + } + + // The types we can assume to be well-formed. In our example, this + // would be &'a mut Self, from the first argument. + let mut wf_tys = FxHashSet::default(); + wf_tys.extend(sig.inputs()); + + // For each region argument (e.g., 'a in our example), check for a + // relationship to the type arguments (e.g., Self). If there is an + // outlives relationship (`Self: 'a`), then we want to ensure that is + // reflected in a where clause on the GAT itself. + for (region, region_idx) in ®ions { + for (ty, ty_idx) in &types { + // In our example, requires that Self: 'a + if ty_known_to_outlive(tcx, id, param_env, &wf_tys, *ty, *region) { + debug!(?ty_idx, ?region_idx); + debug!("required clause: {} must outlive {}", ty, region); + // Translate into the generic parameters of the GAT. In + // our example, the type was Self, which will also be + // Self in the GAT. + let ty_param = generics.param_at(*ty_idx, tcx); + let ty_param = tcx.mk_ty(ty::Param(ty::ParamTy { + index: ty_param.index, + name: ty_param.name, + })); + // Same for the region. In our example, 'a corresponds + // to the 'me parameter. + let region_param = generics.param_at(*region_idx, tcx); + let region_param = + tcx.mk_region(ty::RegionKind::ReEarlyBound(ty::EarlyBoundRegion { + def_id: region_param.def_id, + index: region_param.index, + name: region_param.name, + })); + // The predicate we expect to see. (In our example, + // `Self: 'me`.) + let clause = ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate( + ty_param, + region_param, + )); + let clause = tcx.mk_predicate(ty::Binder::dummy(clause)); + function_clauses.insert(clause); + } + } + } + + // For each region argument (e.g., 'a in our example), also check for a + // relationship to the other region arguments. If there is an + // outlives relationship, then we want to ensure that is + // reflected in a where clause on the GAT itself. + for (region_a, region_a_idx) in ®ions { + for (region_b, region_b_idx) in ®ions { + if region_a == region_b { + continue; + } + + if region_known_to_outlive(tcx, id, param_env, &wf_tys, *region_a, *region_b) { + debug!(?region_a_idx, ?region_b_idx); + debug!("required clause: {} must outlive {}", region_a, region_b); + // Translate into the generic parameters of the GAT. + let region_a_param = generics.param_at(*region_a_idx, tcx); + let region_a_param = + tcx.mk_region(ty::RegionKind::ReEarlyBound(ty::EarlyBoundRegion { + def_id: region_a_param.def_id, + index: region_a_param.index, + name: region_a_param.name, + })); + // Same for the region. + let region_b_param = generics.param_at(*region_b_idx, tcx); + let region_b_param = + tcx.mk_region(ty::RegionKind::ReEarlyBound(ty::EarlyBoundRegion { + def_id: region_b_param.def_id, + index: region_b_param.index, + name: region_b_param.name, + })); + // The predicate we expect to see. + let clause = ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate( + region_a_param, + region_b_param, + )); + let clause = tcx.mk_predicate(ty::Binder::dummy(clause)); + function_clauses.insert(clause); + } + } + } + + // Imagine we have: + // ``` + // trait Foo { + // type Bar<'me>; + // fn gimme(&self) -> Self::Bar<'_>; + // fn gimme_default(&self) -> Self::Bar<'static>; + // } + // ``` + // We only want to require clauses on `Bar` that we can prove from *all* functions (in this + // case, `'me` can be `static` from `gimme_default`) + match clauses.as_mut() { + Some(clauses) => { + clauses.drain_filter(|p| !function_clauses.contains(p)); + } + None => { + clauses = Some(function_clauses); + } + } + } + + // If there are any missing clauses, emit an error + let mut clauses = clauses.unwrap_or_default(); + debug!(?clauses); + if !clauses.is_empty() { + let written_predicates: ty::GenericPredicates<'_> = + tcx.explicit_predicates_of(trait_item.def_id); + let mut clauses: Vec<_> = clauses + .drain_filter(|clause| !written_predicates.predicates.iter().any(|p| &p.0 == clause)) + .map(|clause| format!("{}", clause)) + .collect(); + // We sort so that order is predictable + clauses.sort(); + if !clauses.is_empty() { + let mut err = tcx.sess.struct_span_err( + trait_item.span, + &format!("Missing required bounds on {}", trait_item.ident), + ); + + let suggestion = format!( + "{} {}", + if !trait_item.generics.where_clause.predicates.is_empty() { + "," + } else { + " where" + }, + clauses.join(", "), + ); + err.span_suggestion( + trait_item.generics.where_clause.tail_span_for_suggestion(), + "add the required where clauses", + suggestion, + Applicability::MachineApplicable, + ); + + err.emit() + } + } +} + +// FIXME(jackh726): refactor some of the shared logic between the two functions below + +/// Given a known `param_env` and a set of well formed types, can we prove that +/// `ty` outlives `region`. +fn ty_known_to_outlive<'tcx>( + tcx: TyCtxt<'tcx>, + id: hir::HirId, + param_env: ty::ParamEnv<'tcx>, + wf_tys: &FxHashSet>, + ty: Ty<'tcx>, + region: ty::Region<'tcx>, +) -> bool { + // Unfortunately, we have to use a new `InferCtxt` each call, because + // region constraints get added and solved there and we need to test each + // call individually. + tcx.infer_ctxt().enter(|infcx| { + let mut outlives_environment = OutlivesEnvironment::new(param_env); + outlives_environment.add_implied_bounds(&infcx, wf_tys.clone(), id, DUMMY_SP); + outlives_environment.save_implied_bounds(id); + let region_bound_pairs = outlives_environment.region_bound_pairs_map().get(&id).unwrap(); + + let cause = ObligationCause::new(DUMMY_SP, id, ObligationCauseCode::MiscObligation); + + let sup_type = ty; + let sub_region = region; + + let origin = SubregionOrigin::from_obligation_cause(&cause, || { + infer::RelateParamBound(cause.span, sup_type, None) + }); + + let outlives = &mut TypeOutlives::new( + &infcx, + tcx, + ®ion_bound_pairs, + Some(infcx.tcx.lifetimes.re_root_empty), + param_env, + ); + outlives.type_must_outlive(origin, sup_type, sub_region); + + let errors = infcx.resolve_regions( + id.expect_owner().to_def_id(), + &outlives_environment, + RegionckMode::default(), + ); + + debug!(?errors, "errors"); + + // If we were able to prove that the type outlives the region without + // an error, it must be because of the implied or explicit bounds... + errors.is_empty() + }) +} + +fn region_known_to_outlive<'tcx>( + tcx: TyCtxt<'tcx>, + id: hir::HirId, + param_env: ty::ParamEnv<'tcx>, + wf_tys: &FxHashSet>, + region_a: ty::Region<'tcx>, + region_b: ty::Region<'tcx>, +) -> bool { + // Unfortunately, we have to use a new `InferCtxt` each call, because + // region constraints get added and solved there and we need to test each + // call individually. + tcx.infer_ctxt().enter(|infcx| { + let mut outlives_environment = OutlivesEnvironment::new(param_env); + outlives_environment.add_implied_bounds(&infcx, wf_tys.clone(), id, DUMMY_SP); + outlives_environment.save_implied_bounds(id); + + let cause = ObligationCause::new(DUMMY_SP, id, ObligationCauseCode::MiscObligation); + + let origin = SubregionOrigin::from_obligation_cause(&cause, || { + infer::RelateRegionParamBound(cause.span) + }); + + use rustc_infer::infer::outlives::obligations::TypeOutlivesDelegate; + (&infcx).push_sub_region_constraint(origin, region_a, region_b); + + let errors = infcx.resolve_regions( + id.expect_owner().to_def_id(), + &outlives_environment, + RegionckMode::default(), + ); + + debug!(?errors, "errors"); + + // If we were able to prove that the type outlives the region without + // an error, it must be because of the implied or explicit bounds... + errors.is_empty() + }) +} + +/// TypeVisitor that looks for uses of GATs like +/// `>::GAT` and adds the arguments `P0..Pm` into +/// the two vectors, `regions` and `types` (depending on their kind). For each +/// parameter `Pi` also track the index `i`. +struct GATSubstCollector<'tcx> { + tcx: TyCtxt<'tcx>, + gat: DefId, + // Which region appears and which parameter index its subsituted for + regions: FxHashSet<(ty::Region<'tcx>, usize)>, + // Which params appears and which parameter index its subsituted for + types: FxHashSet<(Ty<'tcx>, usize)>, +} + +impl<'tcx> GATSubstCollector<'tcx> { + fn visit>( + tcx: TyCtxt<'tcx>, + gat: DefId, + t: T, + ) -> (FxHashSet<(ty::Region<'tcx>, usize)>, FxHashSet<(Ty<'tcx>, usize)>) { + let mut visitor = GATSubstCollector { + tcx, + gat, + regions: FxHashSet::default(), + types: FxHashSet::default(), + }; + t.visit_with(&mut visitor); + (visitor.regions, visitor.types) + } +} + +impl<'tcx> TypeVisitor<'tcx> for GATSubstCollector<'tcx> { + type BreakTy = !; + + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + match t.kind() { + ty::Projection(p) if p.item_def_id == self.gat => { + for (idx, subst) in p.substs.iter().enumerate() { + match subst.unpack() { + GenericArgKind::Lifetime(lt) => { + self.regions.insert((lt, idx)); + } + GenericArgKind::Type(t) => { + self.types.insert((t, idx)); + } + _ => {} + } + } + } + _ => {} + } + t.super_visit_with(self) + } + + fn tcx_for_anon_const_substs(&self) -> Option> { + Some(self.tcx) + } } fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool { @@ -1274,19 +1636,38 @@ fn report_bivariance(tcx: TyCtxt<'_>, param: &rustc_hir::GenericParam<'_>) { /// Feature gates RFC 2056 -- trivial bounds, checking for global bounds that /// aren't true. -fn check_false_global_bounds(fcx: &FnCtxt<'_, '_>, span: Span, id: hir::HirId) { +fn check_false_global_bounds(fcx: &FnCtxt<'_, '_>, mut span: Span, id: hir::HirId) { let empty_env = ty::ParamEnv::empty(); let def_id = fcx.tcx.hir().local_def_id(id); - let predicates = fcx.tcx.predicates_of(def_id).predicates.iter().map(|(p, _)| *p); + let predicates_with_span = + fcx.tcx.predicates_of(def_id).predicates.iter().map(|(p, span)| (*p, *span)); // Check elaborated bounds. - let implied_obligations = traits::elaborate_predicates(fcx.tcx, predicates); + let implied_obligations = traits::elaborate_predicates_with_span(fcx.tcx, predicates_with_span); for obligation in implied_obligations { let pred = obligation.predicate; // Match the existing behavior. if pred.is_global(fcx.tcx) && !pred.has_late_bound_regions() { let pred = fcx.normalize_associated_types_in(span, pred); + let hir_node = fcx.tcx.hir().find(id); + + // only use the span of the predicate clause (#90869) + + if let Some(hir::Generics { where_clause, .. }) = + hir_node.and_then(|node| node.generics()) + { + let obligation_span = obligation.cause.span(fcx.tcx); + + span = where_clause + .predicates + .iter() + // There seems to be no better way to find out which predicate we are in + .find(|pred| pred.span().contains(obligation_span)) + .map(|pred| pred.span()) + .unwrap_or(obligation_span); + } + let obligation = traits::Obligation::new( traits::ObligationCause::new(span, id, traits::TrivialBound), empty_env, diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index d951df94dc..fdc8b6b5e6 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -282,6 +282,12 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> { hir::ExprKind::Field(..) => { self.visit_field_id(e.hir_id); } + hir::ExprKind::ConstBlock(anon_const) => { + self.visit_node_id(e.span, anon_const.hir_id); + + let body = self.tcx().hir().body(anon_const.body); + self.visit_body(body); + } _ => {} } diff --git a/compiler/rustc_typeck/src/coherence/builtin.rs b/compiler/rustc_typeck/src/coherence/builtin.rs index 8cae61e8c2..372e83592b 100644 --- a/compiler/rustc_typeck/src/coherence/builtin.rs +++ b/compiler/rustc_typeck/src/coherence/builtin.rs @@ -180,14 +180,14 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef let coerced_fields = fields .iter() - .filter_map(|field| { + .filter(|field| { let ty_a = field.ty(tcx, substs_a); let ty_b = field.ty(tcx, substs_b); if let Ok(layout) = tcx.layout_of(param_env.and(ty_a)) { if layout.is_zst() && layout.align.abi.bytes() == 1 { // ignore ZST fields with alignment of 1 byte - return None; + return false; } } @@ -204,11 +204,11 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef )) .emit(); - return None; + return false; } } - Some(field) + return true; }) .collect::>(); @@ -263,7 +263,8 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef } // Check that all transitive obligations are satisfied. - if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) { + let errors = fulfill_cx.select_all_or_error(&infcx); + if !errors.is_empty() { infcx.report_fulfillment_errors(&errors, None, false); } @@ -522,7 +523,8 @@ pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedI fulfill_cx.register_predicate_obligation(&infcx, predicate); // Check that all transitive obligations are satisfied. - if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) { + let errors = fulfill_cx.select_all_or_error(&infcx); + if !errors.is_empty() { infcx.report_fulfillment_errors(&errors, None, false); } diff --git a/compiler/rustc_typeck/src/coherence/mod.rs b/compiler/rustc_typeck/src/coherence/mod.rs index 079604f128..377ebf1fe2 100644 --- a/compiler/rustc_typeck/src/coherence/mod.rs +++ b/compiler/rustc_typeck/src/coherence/mod.rs @@ -168,6 +168,7 @@ pub fn provide(providers: &mut Providers) { use self::builtin::coerce_unsized_info; use self::inherent_impls::{crate_inherent_impls, inherent_impls}; use self::inherent_impls_overlap::crate_inherent_impls_overlap_check; + use self::orphan::orphan_check_crate; *providers = Providers { coherent_trait, @@ -175,6 +176,7 @@ pub fn provide(providers: &mut Providers) { inherent_impls, crate_inherent_impls_overlap_check, coerce_unsized_info, + orphan_check_crate, ..*providers }; } @@ -195,13 +197,13 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) { } pub fn check_coherence(tcx: TyCtxt<'_>) { + tcx.sess.time("unsafety_checking", || unsafety::check(tcx)); + tcx.ensure().orphan_check_crate(()); + for &trait_def_id in tcx.all_local_trait_impls(()).keys() { tcx.ensure().coherent_trait(trait_def_id); } - tcx.sess.time("unsafety_checking", || unsafety::check(tcx)); - tcx.sess.time("orphan_checking", || orphan::check(tcx)); - // these queries are executed for side-effects (error reporting): tcx.ensure().crate_inherent_impls(()); tcx.ensure().crate_inherent_impls_overlap_check(()); diff --git a/compiler/rustc_typeck/src/coherence/orphan.rs b/compiler/rustc_typeck/src/coherence/orphan.rs index 0326d1fd74..b450d3f6c0 100644 --- a/compiler/rustc_typeck/src/coherence/orphan.rs +++ b/compiler/rustc_typeck/src/coherence/orphan.rs @@ -2,250 +2,266 @@ //! crate or pertains to a type defined in this crate. use rustc_errors::struct_span_err; +use rustc_errors::ErrorReported; use rustc_hir as hir; -use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::ty::{self, TyCtxt}; +use rustc_span::def_id::LocalDefId; +use rustc_span::Span; use rustc_trait_selection::traits; -pub fn check(tcx: TyCtxt<'_>) { - let mut orphan = OrphanChecker { tcx }; - tcx.hir().visit_all_item_likes(&mut orphan); +pub(super) fn orphan_check_crate(tcx: TyCtxt<'_>, (): ()) -> &[LocalDefId] { + let mut errors = Vec::new(); + for (_trait, impls_of_trait) in tcx.all_local_trait_impls(()) { + for &impl_of_trait in impls_of_trait { + match orphan_check_impl(tcx, impl_of_trait) { + Ok(()) => {} + Err(ErrorReported) => errors.push(impl_of_trait), + } + } + } + tcx.arena.alloc_slice(&errors) } -struct OrphanChecker<'tcx> { - tcx: TyCtxt<'tcx>, -} +#[instrument(skip(tcx), level = "debug")] +fn orphan_check_impl(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorReported> { + let trait_ref = tcx.impl_trait_ref(def_id).unwrap(); + let trait_def_id = trait_ref.def_id; -impl ItemLikeVisitor<'v> for OrphanChecker<'tcx> { - /// Checks exactly one impl for orphan rules and other such - /// restrictions. In this fn, it can happen that multiple errors - /// apply to a specific impl, so just return after reporting one - /// to prevent inundating the user with a bunch of similar error - /// reports. - fn visit_item(&mut self, item: &hir::Item<'_>) { - // "Trait" impl - if let hir::ItemKind::Impl(hir::Impl { - generics, of_trait: Some(ref tr), self_ty, .. - }) = &item.kind - { - debug!( - "coherence2::orphan check: trait impl {}", - self.tcx.hir().node_to_string(item.hir_id()) - ); - let trait_ref = self.tcx.impl_trait_ref(item.def_id).unwrap(); - let trait_def_id = trait_ref.def_id; - let sm = self.tcx.sess.source_map(); - let sp = sm.guess_head_span(item.span); - match traits::orphan_check(self.tcx, item.def_id.to_def_id()) { - Ok(()) => {} - Err(traits::OrphanCheckErr::NonLocalInputType(tys)) => { - let mut err = struct_span_err!( - self.tcx.sess, - sp, - E0117, - "only traits defined in the current crate can be implemented for \ - arbitrary types" - ); - err.span_label(sp, "impl doesn't use only types from inside the current crate"); - for (ty, is_target_ty) in &tys { - let mut ty = *ty; - self.tcx.infer_ctxt().enter(|infcx| { - // Remove the lifetimes unnecessary for this error. - ty = infcx.freshen(ty); - }); - ty = match ty.kind() { - // Remove the type arguments from the output, as they are not relevant. - // You can think of this as the reverse of `resolve_vars_if_possible`. - // That way if we had `Vec`, we will properly attribute the - // problem to `Vec` and avoid confusing the user if they were to see - // `MyType` in the error. - ty::Adt(def, _) => self.tcx.mk_adt(def, ty::List::empty()), - _ => ty, - }; - let this = "this".to_string(); - let (ty, postfix) = match &ty.kind() { - ty::Slice(_) => (this, " because slices are always foreign"), - ty::Array(..) => (this, " because arrays are always foreign"), - ty::Tuple(..) => (this, " because tuples are always foreign"), - _ => (format!("`{}`", ty), ""), - }; - let msg = format!("{} is not defined in the current crate{}", ty, postfix); - if *is_target_ty { - // Point at `D` in `impl for C in D` - err.span_label(self_ty.span, &msg); - } else { - // Point at `C` in `impl for C in D` - err.span_label(tr.path.span, &msg); - } - } - err.note("define and implement a trait or new type instead"); - err.emit(); - return; - } - Err(traits::OrphanCheckErr::UncoveredTy(param_ty, local_type)) => { - let mut sp = sp; - for param in generics.params { - if param.name.ident().to_string() == param_ty.to_string() { - sp = param.span; - } - } + let item = tcx.hir().item(hir::ItemId { def_id }); + let impl_ = match item.kind { + hir::ItemKind::Impl(ref impl_) => impl_, + _ => bug!("{:?} is not an impl: {:?}", def_id, item), + }; + let sp = tcx.sess.source_map().guess_head_span(item.span); + let tr = impl_.of_trait.as_ref().unwrap(); + match traits::orphan_check(tcx, item.def_id.to_def_id()) { + Ok(()) => {} + Err(err) => emit_orphan_check_error( + tcx, + sp, + tr.path.span, + impl_.self_ty.span, + &impl_.generics, + err, + )?, + } + + // In addition to the above rules, we restrict impls of auto traits + // so that they can only be implemented on nominal types, such as structs, + // enums or foreign types. To see why this restriction exists, consider the + // following example (#22978). Imagine that crate A defines an auto trait + // `Foo` and a fn that operates on pairs of types: + // + // ``` + // // Crate A + // auto trait Foo { } + // fn two_foos(..) { + // one_foo::<(A,B)>(..) + // } + // fn one_foo(..) { .. } + // ``` + // + // This type-checks fine; in particular the fn + // `two_foos` is able to conclude that `(A,B):Foo` + // because `A:Foo` and `B:Foo`. + // + // Now imagine that crate B comes along and does the following: + // + // ``` + // struct A { } + // struct B { } + // impl Foo for A { } + // impl Foo for B { } + // impl !Send for (A, B) { } + // ``` + // + // This final impl is legal according to the orphan + // rules, but it invalidates the reasoning from + // `two_foos` above. + debug!( + "trait_ref={:?} trait_def_id={:?} trait_is_auto={}", + trait_ref, + trait_def_id, + tcx.trait_is_auto(trait_def_id) + ); + + if tcx.trait_is_auto(trait_def_id) && !trait_def_id.is_local() { + let self_ty = trait_ref.self_ty(); + let opt_self_def_id = match *self_ty.kind() { + ty::Adt(self_def, _) => Some(self_def.did), + ty::Foreign(did) => Some(did), + _ => None, + }; - match local_type { - Some(local_type) => { - struct_span_err!( - self.tcx.sess, - sp, - E0210, - "type parameter `{}` must be covered by another type \ - when it appears before the first local type (`{}`)", - param_ty, - local_type - ) - .span_label( - sp, - format!( - "type parameter `{}` must be covered by another type \ - when it appears before the first local type (`{}`)", - param_ty, local_type - ), - ) - .note( - "implementing a foreign trait is only possible if at \ - least one of the types for which it is implemented is local, \ - and no uncovered type parameters appear before that first \ - local type", - ) - .note( - "in this case, 'before' refers to the following order: \ - `impl<..> ForeignTrait for T0`, \ - where `T0` is the first and `Tn` is the last", - ) - .emit(); - } - None => { - struct_span_err!( - self.tcx.sess, - sp, - E0210, - "type parameter `{}` must be used as the type parameter for some \ - local type (e.g., `MyStruct<{}>`)", - param_ty, - param_ty - ).span_label(sp, format!( - "type parameter `{}` must be used as the type parameter for some \ - local type", - param_ty, - )).note("implementing a foreign trait is only possible if at \ - least one of the types for which it is implemented is local" - ).note("only traits defined in the current crate can be \ - implemented for a type parameter" - ).emit(); - } - }; - return; + let msg = match opt_self_def_id { + // We only want to permit nominal types, but not *all* nominal types. + // They must be local to the current crate, so that people + // can't do `unsafe impl Send for Rc` or + // `impl !Send for Box`. + Some(self_def_id) => { + if self_def_id.is_local() { + None + } else { + Some(( + format!( + "cross-crate traits with a default impl, like `{}`, \ + can only be implemented for a struct/enum type \ + defined in the current crate", + tcx.def_path_str(trait_def_id) + ), + "can't implement cross-crate trait for type in another crate", + )) } } + _ => Some(( + format!( + "cross-crate traits with a default impl, like `{}`, can \ + only be implemented for a struct/enum type, not `{}`", + tcx.def_path_str(trait_def_id), + self_ty + ), + "can't implement cross-crate trait with a default impl for \ + non-struct/enum type", + )), + }; - // In addition to the above rules, we restrict impls of auto traits - // so that they can only be implemented on nominal types, such as structs, - // enums or foreign types. To see why this restriction exists, consider the - // following example (#22978). Imagine that crate A defines an auto trait - // `Foo` and a fn that operates on pairs of types: - // - // ``` - // // Crate A - // auto trait Foo { } - // fn two_foos(..) { - // one_foo::<(A,B)>(..) - // } - // fn one_foo(..) { .. } - // ``` - // - // This type-checks fine; in particular the fn - // `two_foos` is able to conclude that `(A,B):Foo` - // because `A:Foo` and `B:Foo`. - // - // Now imagine that crate B comes along and does the following: - // - // ``` - // struct A { } - // struct B { } - // impl Foo for A { } - // impl Foo for B { } - // impl !Send for (A, B) { } - // ``` - // - // This final impl is legal according to the orphan - // rules, but it invalidates the reasoning from - // `two_foos` above. - debug!( - "trait_ref={:?} trait_def_id={:?} trait_is_auto={}", - trait_ref, - trait_def_id, - self.tcx.trait_is_auto(trait_def_id) + if let Some((msg, label)) = msg { + struct_span_err!(tcx.sess, sp, E0321, "{}", msg).span_label(sp, label).emit(); + return Err(ErrorReported); + } + } + + if let ty::Opaque(def_id, _) = *trait_ref.self_ty().kind() { + tcx.sess + .struct_span_err(sp, "cannot implement trait on type alias impl trait") + .span_note(tcx.def_span(def_id), "type alias impl trait defined here") + .emit(); + return Err(ErrorReported); + } + + Ok(()) +} + +fn emit_orphan_check_error( + tcx: TyCtxt<'tcx>, + sp: Span, + trait_span: Span, + self_ty_span: Span, + generics: &hir::Generics<'tcx>, + err: traits::OrphanCheckErr<'tcx>, +) -> Result { + match err { + traits::OrphanCheckErr::NonLocalInputType(tys) => { + let mut err = struct_span_err!( + tcx.sess, + sp, + E0117, + "only traits defined in the current crate can be implemented for \ + arbitrary types" ); - if self.tcx.trait_is_auto(trait_def_id) && !trait_def_id.is_local() { - let self_ty = trait_ref.self_ty(); - let opt_self_def_id = match *self_ty.kind() { - ty::Adt(self_def, _) => Some(self_def.did), - ty::Foreign(did) => Some(did), - _ => None, + err.span_label(sp, "impl doesn't use only types from inside the current crate"); + for (ty, is_target_ty) in &tys { + let mut ty = *ty; + tcx.infer_ctxt().enter(|infcx| { + // Remove the lifetimes unnecessary for this error. + ty = infcx.freshen(ty); + }); + ty = match ty.kind() { + // Remove the type arguments from the output, as they are not relevant. + // You can think of this as the reverse of `resolve_vars_if_possible`. + // That way if we had `Vec`, we will properly attribute the + // problem to `Vec` and avoid confusing the user if they were to see + // `MyType` in the error. + ty::Adt(def, _) => tcx.mk_adt(def, ty::List::empty()), + _ => ty, }; - - let msg = match opt_self_def_id { - // We only want to permit nominal types, but not *all* nominal types. - // They must be local to the current crate, so that people - // can't do `unsafe impl Send for Rc` or - // `impl !Send for Box`. - Some(self_def_id) => { - if self_def_id.is_local() { - None - } else { - Some(( - format!( - "cross-crate traits with a default impl, like `{}`, \ - can only be implemented for a struct/enum type \ - defined in the current crate", - self.tcx.def_path_str(trait_def_id) - ), - "can't implement cross-crate trait for type in another crate", - )) - } - } - _ => Some(( - format!( - "cross-crate traits with a default impl, like `{}`, can \ - only be implemented for a struct/enum type, not `{}`", - self.tcx.def_path_str(trait_def_id), - self_ty - ), - "can't implement cross-crate trait with a default impl for \ - non-struct/enum type", - )), + let this = "this".to_string(); + let (ty, postfix) = match &ty.kind() { + ty::Slice(_) => (this, " because slices are always foreign"), + ty::Array(..) => (this, " because arrays are always foreign"), + ty::Tuple(..) => (this, " because tuples are always foreign"), + _ => (format!("`{}`", ty), ""), }; - - if let Some((msg, label)) = msg { - struct_span_err!(self.tcx.sess, sp, E0321, "{}", msg) - .span_label(sp, label) - .emit(); - return; + let msg = format!("{} is not defined in the current crate{}", ty, postfix); + if *is_target_ty { + // Point at `D` in `impl for C in D` + err.span_label(self_ty_span, &msg); + } else { + // Point at `C` in `impl for C in D` + err.span_label(trait_span, &msg); + } + } + err.note("define and implement a trait or new type instead"); + err.emit() + } + traits::OrphanCheckErr::UncoveredTy(param_ty, local_type) => { + let mut sp = sp; + for param in generics.params { + if param.name.ident().to_string() == param_ty.to_string() { + sp = param.span; } } - if let ty::Opaque(def_id, _) = *trait_ref.self_ty().kind() { - self.tcx - .sess - .struct_span_err(sp, "cannot implement trait on type alias impl trait") - .span_note(self.tcx.def_span(def_id), "type alias impl trait defined here") - .emit(); + match local_type { + Some(local_type) => struct_span_err!( + tcx.sess, + sp, + E0210, + "type parameter `{}` must be covered by another type \ + when it appears before the first local type (`{}`)", + param_ty, + local_type + ) + .span_label( + sp, + format!( + "type parameter `{}` must be covered by another type \ + when it appears before the first local type (`{}`)", + param_ty, local_type + ), + ) + .note( + "implementing a foreign trait is only possible if at \ + least one of the types for which it is implemented is local, \ + and no uncovered type parameters appear before that first \ + local type", + ) + .note( + "in this case, 'before' refers to the following order: \ + `impl<..> ForeignTrait for T0`, \ + where `T0` is the first and `Tn` is the last", + ) + .emit(), + None => struct_span_err!( + tcx.sess, + sp, + E0210, + "type parameter `{}` must be used as the type parameter for some \ + local type (e.g., `MyStruct<{}>`)", + param_ty, + param_ty + ) + .span_label( + sp, + format!( + "type parameter `{}` must be used as the type parameter for some \ + local type", + param_ty, + ), + ) + .note( + "implementing a foreign trait is only possible if at \ + least one of the types for which it is implemented is local", + ) + .note( + "only traits defined in the current crate can be \ + implemented for a type parameter", + ) + .emit(), } } } - fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {} - - fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {} - - fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {} + Err(ErrorReported) } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index df7f2aea9c..b9db8a6be5 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -28,7 +28,7 @@ use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_errors::{struct_span_err, Applicability}; use rustc_hir as hir; -use rustc_hir::def::{CtorKind, DefKind, Res}; +use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::weak_lang_items; @@ -668,6 +668,7 @@ impl ItemCtxt<'tcx> { }) .flat_map(|b| predicates_from_bound(self, ty, b)); + let param_def_id = self.tcx.hir().local_def_id(param_id).to_def_id(); let from_where_clauses = ast_generics .where_clause .predicates @@ -677,7 +678,7 @@ impl ItemCtxt<'tcx> { _ => None, }) .flat_map(|bp| { - let bt = if is_param(self.tcx, bp.bounded_ty, param_id) { + let bt = if bp.is_param_bound(param_def_id) { Some(ty) } else if !only_self_bounds.0 { Some(self.to_ty(bp.bounded_ty)) @@ -714,23 +715,6 @@ impl ItemCtxt<'tcx> { } } -/// Tests whether this is the AST for a reference to the type -/// parameter with ID `param_id`. We use this so as to avoid running -/// `ast_ty_to_ty`, because we want to avoid triggering an all-out -/// conversion of the type to avoid inducing unnecessary cycles. -fn is_param(tcx: TyCtxt<'_>, ast_ty: &hir::Ty<'_>, param_id: hir::HirId) -> bool { - if let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = ast_ty.kind { - match path.res { - Res::SelfTy(Some(def_id), None) | Res::Def(DefKind::TyParam, def_id) => { - def_id == tcx.hir().local_def_id(param_id).to_def_id() - } - _ => false, - } - } else { - false - } -} - fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { let it = tcx.hir().item(item_id); debug!("convert: item {} with id {}", it.ident, it.hir_id()); @@ -1494,13 +1478,15 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { { Some(parent_def_id.to_def_id()) } - + Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) => { + Some(tcx.typeck_root_def_id(def_id)) + } _ => None, } } } Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => { - Some(tcx.closure_base_def_id(def_id)) + Some(tcx.typeck_root_def_id(def_id)) } Node::Item(item) => match item.kind { ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => { @@ -1557,7 +1543,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { kind: ty::GenericParamDefKind::Type { has_default: false, object_lifetime_default: rl::Set1::Empty, - synthetic: None, + synthetic: false, }, }); @@ -1687,11 +1673,29 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { kind: ty::GenericParamDefKind::Type { has_default: false, object_lifetime_default: rl::Set1::Empty, - synthetic: None, + synthetic: false, }, })); } + // provide junk type parameter defs for const blocks. + if let Node::AnonConst(_) = node { + let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id)); + if let Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) = parent_node { + params.push(ty::GenericParamDef { + index: type_start, + name: Symbol::intern(""), + def_id, + pure_wrt_drop: false, + kind: ty::GenericParamDefKind::Type { + has_default: false, + object_lifetime_default: rl::Set1::Empty, + synthetic: false, + }, + }); + } + } + let param_def_id_to_index = params.iter().map(|param| (param.def_id, param.index)).collect(); ty::Generics { @@ -1986,16 +1990,12 @@ fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { // prove that the trait applies to the types that were // used, and adding the predicate into this list ensures // that this is done. - let mut span = tcx.def_span(def_id); - if tcx.sess.source_map().is_local_span(span) { - // `guess_head_span` reads the actual source file from - // disk to try to determine the 'head' snippet of the span. - // Don't do this for a span that comes from a file outside - // of our crate, since this would make our query output - // (and overall crate metadata) dependent on the - // *current* state of an external file. - span = tcx.sess.source_map().guess_head_span(span); - } + // + // We use a DUMMY_SP here as a way to signal trait bounds that come + // from the trait itself that *shouldn't* be shown as the source of + // an obligation and instead be skipped. Otherwise we'd use + // `tcx.def_span(def_id);` + let span = rustc_span::DUMMY_SP; result.predicates = tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once(( ty::TraitRef::identity(tcx, def_id).without_const().to_predicate(tcx), @@ -2861,14 +2861,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { } else if attr.has_name(sym::link_name) { codegen_fn_attrs.link_name = attr.value_str(); } else if attr.has_name(sym::link_ordinal) { - if link_ordinal_span.is_some() { - tcx.sess - .struct_span_err( - attr.span, - "multiple `link_ordinal` attributes on a single definition", - ) - .emit(); - } link_ordinal_span = Some(attr.span); if let ordinal @ Some(_) = check_link_ordinal(tcx, attr) { codegen_fn_attrs.link_ordinal = ordinal; @@ -2879,6 +2871,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { for item in list.iter() { if item.has_name(sym::address) { codegen_fn_attrs.no_sanitize |= SanitizerSet::ADDRESS; + } else if item.has_name(sym::cfi) { + codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI; } else if item.has_name(sym::memory) { codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY; } else if item.has_name(sym::thread) { diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index cee3679d0a..04a68250ce 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -292,7 +292,8 @@ pub(super) fn default_anon_const_substs(tcx: TyCtxt<'_>, def_id: DefId) -> Subst // Getting this wrong can lead to ICE and unsoundness, so we assert it here. for arg in substs.iter() { let allowed_flags = ty::TypeFlags::MAY_NEED_DEFAULT_CONST_SUBSTS - | ty::TypeFlags::STILL_FURTHER_SPECIALIZABLE; + | ty::TypeFlags::STILL_FURTHER_SPECIALIZABLE + | ty::TypeFlags::HAS_ERROR; assert!(!arg.has_type_flags(!allowed_flags)); } substs @@ -493,7 +494,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { Node::Expr(&Expr { kind: ExprKind::ConstBlock(ref anon_const), .. }) if anon_const.hir_id == hir_id => { - tcx.typeck(def_id).node_type(anon_const.hir_id) + let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); + substs.as_inline_const().ty() } Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. }) @@ -771,7 +773,7 @@ fn infer_placeholder_type<'a>( } else { err.span_note( tcx.hir().body(body_id).value.span, - &format!("however, the inferred type `{}` cannot be named", ty.to_string()), + &format!("however, the inferred type `{}` cannot be named", ty), ); } } @@ -795,7 +797,7 @@ fn infer_placeholder_type<'a>( } else { diag.span_note( tcx.hir().body(body_id).value.span, - &format!("however, the inferred type `{}` cannot be named", ty.to_string()), + &format!("however, the inferred type `{}` cannot be named", ty), ); } } diff --git a/compiler/rustc_typeck/src/hir_wf_check.rs b/compiler/rustc_typeck/src/hir_wf_check.rs index 39bcf89993..a49eda6572 100644 --- a/compiler/rustc_typeck/src/hir_wf_check.rs +++ b/compiler/rustc_typeck/src/hir_wf_check.rs @@ -88,7 +88,8 @@ fn diagnostic_hir_wf_check<'tcx>( ), ); - if let Err(errors) = fulfill.select_all_or_error(&infcx) { + let errors = fulfill.select_all_or_error(&infcx); + if !errors.is_empty() { tracing::debug!("Wf-check got errors for {:?}: {:?}", ty, errors); for error in errors { if error.obligation.predicate == self.predicate { diff --git a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs index f4bb5761c1..4fb422c801 100644 --- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs @@ -382,6 +382,7 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc ty::PredicateKind::Trait(ty::TraitPredicate { trait_ref, constness: ty::BoundConstness::NotConst, + polarity: _, }) => { if !matches!( trait_predicate_kind(tcx, predicate), @@ -413,6 +414,7 @@ fn trait_predicate_kind<'tcx>( ty::PredicateKind::Trait(ty::TraitPredicate { trait_ref, constness: ty::BoundConstness::NotConst, + polarity: _, }) => Some(tcx.trait_def(trait_ref.def_id).specialization_kind), ty::PredicateKind::Trait(_) | ty::PredicateKind::RegionOutlives(_) diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index 971776c882..0881cf0758 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -58,17 +58,19 @@ This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(bool_to_option)] #![feature(crate_visibility_modifier)] -#![feature(format_args_capture)] +#![cfg_attr(bootstrap, feature(format_args_capture))] #![feature(if_let_guard)] #![feature(in_band_lifetimes)] #![feature(is_sorted)] #![feature(iter_zip)] +#![feature(let_else)] #![feature(min_specialization)] #![feature(nll)] #![feature(try_blocks)] #![feature(never_type)] #![feature(slice_partition_dedup)] #![feature(control_flow_enum)] +#![feature(hash_drain_filter)] #![recursion_limit = "256"] #[macro_use] @@ -155,10 +157,10 @@ fn require_same_types<'tcx>( } } - match fulfill_cx.select_all_or_error(infcx) { - Ok(()) => true, - Err(errors) => { - infcx.report_fulfillment_errors(&errors, None, false); + match fulfill_cx.select_all_or_error(infcx).as_slice() { + [] => true, + errors => { + infcx.report_fulfillment_errors(errors, None, false); false } } @@ -350,8 +352,9 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { term_id, cause, ); - if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(&err, None, false); + let errors = fulfillment_cx.select_all_or_error(&infcx); + if !errors.is_empty() { + infcx.report_fulfillment_errors(&errors, None, false); error = true; } }); diff --git a/compiler/rustc_typeck/src/outlives/outlives_bounds.rs b/compiler/rustc_typeck/src/outlives/outlives_bounds.rs index 4ab5fe26ab..91727d57dd 100644 --- a/compiler/rustc_typeck/src/outlives/outlives_bounds.rs +++ b/compiler/rustc_typeck/src/outlives/outlives_bounds.rs @@ -83,7 +83,8 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { // variables. Process these constraints. let mut fulfill_cx = FulfillmentContext::new(); fulfill_cx.register_predicate_obligations(self, result.obligations); - if fulfill_cx.select_all_or_error(self).is_err() { + let errors = fulfill_cx.select_all_or_error(self); + if !errors.is_empty() { self.tcx.sess.delay_span_bug( span, "implied_outlives_bounds failed to solve obligations from instantiation", diff --git a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs index 8d3862ffc8..a1c2945770 100644 --- a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs @@ -300,7 +300,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { hir::TyKind::Path(hir::QPath::Resolved( None, hir::Path { res: hir::def::Res::Def(_, id), .. }, - )) if *id == def_id => true, + )) => *id == def_id, _ => false, }) }) diff --git a/compiler/rustc_typeck/src/variance/constraints.rs b/compiler/rustc_typeck/src/variance/constraints.rs index 1c8ac10818..33c27ce86d 100644 --- a/compiler/rustc_typeck/src/variance/constraints.rs +++ b/compiler/rustc_typeck/src/variance/constraints.rs @@ -223,8 +223,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraints_from_region(current, lt, variance_i) } GenericArgKind::Type(ty) => self.add_constraints_from_ty(current, ty, variance_i), - GenericArgKind::Const(_) => { - // Consts impose no constraints. + GenericArgKind::Const(val) => { + self.add_constraints_from_const(current, val, variance_i) } } } @@ -263,7 +263,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraints_from_mt(current, &ty::TypeAndMut { ty, mutbl }, variance); } - ty::Array(typ, _) => { + ty::Array(typ, len) => { + self.add_constraints_from_const(current, len, variance); self.add_constraints_from_ty(current, typ, variance); } @@ -385,13 +386,32 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraints_from_region(current, lt, variance_i) } GenericArgKind::Type(ty) => self.add_constraints_from_ty(current, ty, variance_i), - GenericArgKind::Const(_) => { - // Consts impose no constraints. + GenericArgKind::Const(val) => { + self.add_constraints_from_const(current, val, variance) } } } } + /// Adds constraints appropriate for a const expression `val` + /// in a context with ambient variance `variance` + fn add_constraints_from_const( + &mut self, + current: &CurrentItem, + val: &ty::Const<'tcx>, + variance: VarianceTermPtr<'a>, + ) { + debug!("add_constraints_from_const(val={:?}, variance={:?})", val, variance); + + match &val.val { + ty::ConstKind::Unevaluated(uv) => { + let substs = uv.substs(self.tcx()); + self.add_constraints_from_invariant_substs(current, substs, variance); + } + _ => {} + } + } + /// Adds constraints appropriate for a function with signature /// `sig` appearing in a context with ambient variance `variance` fn add_constraints_from_sig( diff --git a/config.toml.example b/config.toml.example index 61e57eee78..4dd953a495 100644 --- a/config.toml.example +++ b/config.toml.example @@ -68,6 +68,12 @@ changelog-seen = 2 # Indicates whether the LLVM assertions are enabled or not #assertions = false +# Indicates whether the LLVM testsuite is enabled in the build or not. Does +# not execute the tests as part of the build as part of x.py build et al, +# just makes it possible to do `ninja check-llvm` in the staged LLVM build +# directory when doing LLVM development as part of Rust development. +#tests = false + # Indicates whether the LLVM plugin is enabled or not #plugins = false @@ -603,7 +609,11 @@ changelog-seen = 2 # Enable symbol-mangling-version v0. This can be helpful when profiling rustc, # as generics will be preserved in symbols (rather than erased into opaque T). -#new-symbol-mangling = false +# When no setting is given, the new scheme will be used when compiling the +# compiler and its tools and the legacy scheme will be used when compiling the +# standard library. +# If an explicit setting is given, it will be used for all parts of the codebase. +#new-symbol-mangling = true|false (see comment) # ============================================================================= # Options for specific targets diff --git a/git-commit-hash b/git-commit-hash index 5a7b097227..0150433bdf 100644 --- a/git-commit-hash +++ b/git-commit-hash @@ -1 +1 @@ -f1edd0429582dd29cccacaf50fd134b05593bd9c \ No newline at end of file +db9d1b20bba1968c1ec1fc49616d4742c1725b4b \ No newline at end of file diff --git a/library/alloc/benches/btree/map.rs b/library/alloc/benches/btree/map.rs index c304f74884..89c21929db 100644 --- a/library/alloc/benches/btree/map.rs +++ b/library/alloc/benches/btree/map.rs @@ -290,7 +290,7 @@ where let mut c = 0; for i in 0..BENCH_RANGE_SIZE { for j in i + 1..BENCH_RANGE_SIZE { - black_box(map.range(f(i, j))); + let _ = black_box(map.range(f(i, j))); c += 1; } } @@ -322,7 +322,7 @@ fn bench_iter(b: &mut Bencher, repeats: i32, size: i32) { let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); b.iter(|| { for _ in 0..repeats { - black_box(map.iter()); + let _ = black_box(map.iter()); } }); } diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 4a5b0fcf03..66ef92558d 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -81,6 +81,7 @@ pub use std::alloc::Global; /// } /// ``` #[stable(feature = "global_alloc", since = "1.28.0")] +#[must_use = "losing the pointer will leak memory"] #[inline] pub unsafe fn alloc(layout: Layout) -> *mut u8 { unsafe { __rust_alloc(layout.size(), layout.align()) } @@ -117,6 +118,7 @@ pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) { /// /// See [`GlobalAlloc::realloc`]. #[stable(feature = "global_alloc", since = "1.28.0")] +#[must_use = "losing the pointer will leak memory"] #[inline] pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { unsafe { __rust_realloc(ptr, layout.size(), layout.align(), new_size) } @@ -150,6 +152,7 @@ pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 /// } /// ``` #[stable(feature = "global_alloc", since = "1.28.0")] +#[must_use = "losing the pointer will leak memory"] #[inline] pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { unsafe { __rust_alloc_zeroed(layout.size(), layout.align()) } diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index bd4f525604..f6332b072c 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -169,6 +169,9 @@ use crate::vec::Vec; #[lang = "owned_box"] #[fundamental] #[stable(feature = "rust1", since = "1.0.0")] +// The declaration of the `Box` struct must be kept in sync with the +// `alloc::alloc::box_free` function or ICEs will happen. See the comment +// on `box_free` for more details. pub struct Box< T: ?Sized, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs index 9bded6c0f1..7d87974b47 100644 --- a/library/alloc/src/collections/binary_heap.rs +++ b/library/alloc/src/collections/binary_heap.rs @@ -162,9 +162,9 @@ use super::SpecExtend; /// item's ordering relative to any other item, as determined by the [`Ord`] /// trait, changes while it is in the heap. This is normally only possible /// through [`Cell`], [`RefCell`], global state, I/O, or unsafe code. The -/// behavior resulting from such a logic error is not specified, but will -/// not result in undefined behavior. This could include panics, incorrect -/// results, aborts, memory leaks, and non-termination. +/// behavior resulting from such a logic error is not specified (it +/// could include panics, incorrect results, aborts, memory leaks, or +/// non-termination) but will not be undefined behavior. /// /// # Examples /// @@ -512,6 +512,7 @@ impl BinaryHeap { /// let vec = heap.into_sorted_vec(); /// assert_eq!(vec, [1, 2, 3, 4, 5, 6, 7]); /// ``` + #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "binary_heap_extras_15", since = "1.5.0")] pub fn into_sorted_vec(mut self) -> Vec { let mut end = self.len(); @@ -850,7 +851,6 @@ impl BinaryHeap { /// /// assert_eq!(heap.into_iter_sorted().take(2).collect::>(), vec![5, 4]); /// ``` - #[must_use = "`self` will be dropped if the result is not used"] #[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")] pub fn into_iter_sorted(self) -> IntoIterSorted { IntoIterSorted { inner: self } @@ -877,6 +877,7 @@ impl BinaryHeap { /// # Time complexity /// /// Cost is *O*(1) in the worst case. + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn peek(&self) -> Option<&T> { self.data.get(0) @@ -894,6 +895,7 @@ impl BinaryHeap { /// assert!(heap.capacity() >= 100); /// heap.push(4); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn capacity(&self) -> usize { self.data.capacity() @@ -1050,6 +1052,7 @@ impl BinaryHeap { /// /// assert_eq!(heap.len(), 2); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn len(&self) -> usize { self.data.len() @@ -1073,6 +1076,7 @@ impl BinaryHeap { /// /// assert!(!heap.is_empty()); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn is_empty(&self) -> bool { self.len() == 0 @@ -1203,6 +1207,7 @@ impl Drop for Hole<'_, T> { /// documentation for more. /// /// [`iter`]: BinaryHeap::iter +#[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] pub struct Iter<'a, T: 'a> { iter: slice::Iter<'a, T>, @@ -1337,6 +1342,7 @@ impl AsIntoIter for IntoIter { } } +#[must_use = "iterators are lazy and do nothing unless consumed"] #[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")] #[derive(Clone, Debug)] pub struct IntoIterSorted { @@ -1578,6 +1584,14 @@ impl> SpecExtend for BinaryHeap { } } +impl SpecExtend> for BinaryHeap { + fn spec_extend(&mut self, ref mut other: Vec) { + let start = self.data.len(); + self.data.append(other); + self.rebuild_tail(start); + } +} + impl SpecExtend> for BinaryHeap { fn spec_extend(&mut self, ref mut other: BinaryHeap) { self.append(other); diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index fa86e61156..2ff7b0fbb7 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -55,15 +55,15 @@ pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT; /// performance on *small* nodes of elements which are cheap to compare. However in the future we /// would like to further explore choosing the optimal search strategy based on the choice of B, /// and possibly other factors. Using linear search, searching for a random element is expected -/// to take O(B * log(n)) comparisons, which is generally worse than a BST. In practice, +/// to take B * log(n) comparisons, which is generally worse than a BST. In practice, /// however, performance is excellent. /// /// It is a logic error for a key to be modified in such a way that the key's ordering relative to /// any other key, as determined by the [`Ord`] trait, changes while it is in the map. This is /// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code. -/// The behavior resulting from such a logic error is not specified, but will not result in -/// undefined behavior. This could include panics, incorrect results, aborts, memory leaks, and -/// non-termination. +/// The behavior resulting from such a logic error is not specified (it could include panics, +/// incorrect results, aborts, memory leaks, or non-termination) but will not be undefined +/// behavior. /// /// [B-Tree]: https://en.wikipedia.org/wiki/B-tree /// [`Cell`]: core::cell::Cell @@ -288,6 +288,7 @@ where /// documentation for more. /// /// [`iter`]: BTreeMap::iter +#[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] pub struct Iter<'a, K: 'a, V: 'a> { range: LazyLeafRange, K, V>, @@ -316,6 +317,7 @@ pub struct IterMut<'a, K: 'a, V: 'a> { _marker: PhantomData<&'a mut (K, V)>, } +#[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "collection_debug", since = "1.17.0")] impl fmt::Debug for IterMut<'_, K, V> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -359,6 +361,7 @@ impl fmt::Debug for IntoIter { /// documentation for more. /// /// [`keys`]: BTreeMap::keys +#[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] pub struct Keys<'a, K: 'a, V: 'a> { inner: Iter<'a, K, V>, @@ -377,6 +380,7 @@ impl fmt::Debug for Keys<'_, K, V> { /// documentation for more. /// /// [`values`]: BTreeMap::values +#[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] pub struct Values<'a, K: 'a, V: 'a> { inner: Iter<'a, K, V>, @@ -395,6 +399,7 @@ impl fmt::Debug for Values<'_, K, V> { /// documentation for more. /// /// [`values_mut`]: BTreeMap::values_mut +#[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "map_values_mut", since = "1.10.0")] pub struct ValuesMut<'a, K: 'a, V: 'a> { inner: IterMut<'a, K, V>, @@ -413,6 +418,7 @@ impl fmt::Debug for ValuesMut<'_, K, V> { /// See its documentation for more. /// /// [`into_keys`]: BTreeMap::into_keys +#[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "map_into_keys_values", since = "1.54.0")] pub struct IntoKeys { inner: IntoIter, @@ -431,6 +437,7 @@ impl fmt::Debug for IntoKeys { /// See its documentation for more. /// /// [`into_values`]: BTreeMap::into_values +#[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "map_into_keys_values", since = "1.54.0")] pub struct IntoValues { inner: IntoIter, @@ -449,6 +456,7 @@ impl fmt::Debug for IntoValues { /// documentation for more. /// /// [`range`]: BTreeMap::range +#[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "btree_range", since = "1.17.0")] pub struct Range<'a, K: 'a, V: 'a> { inner: LeafRange, K, V>, @@ -467,6 +475,7 @@ impl fmt::Debug for Range<'_, K, V> { /// documentation for more. /// /// [`range_mut`]: BTreeMap::range_mut +#[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "btree_range", since = "1.17.0")] pub struct RangeMut<'a, K: 'a, V: 'a> { inner: LeafRange, K, V>, @@ -1265,7 +1274,6 @@ impl BTreeMap { /// assert_eq!(keys, [1, 2]); /// ``` #[inline] - #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "map_into_keys_values", since = "1.54.0")] pub fn into_keys(self) -> IntoKeys { IntoKeys { inner: self.into_iter() } @@ -1288,7 +1296,6 @@ impl BTreeMap { /// assert_eq!(values, ["hello", "goodbye"]); /// ``` #[inline] - #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "map_into_keys_values", since = "1.54.0")] pub fn into_values(self) -> IntoValues { IntoValues { inner: self.into_iter() } @@ -2205,6 +2212,7 @@ impl BTreeMap { /// a.insert(1, "a"); /// assert_eq!(a.len(), 1); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] pub const fn len(&self) -> usize { @@ -2225,6 +2233,7 @@ impl BTreeMap { /// a.insert(1, "a"); /// assert!(!a.is_empty()); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] pub const fn is_empty(&self) -> bool { diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs index 3e9048b176..5cef007a46 100644 --- a/library/alloc/src/collections/btree/map/entry.rs +++ b/library/alloc/src/collections/btree/map/entry.rs @@ -347,6 +347,7 @@ impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> { /// map.entry("poneyland").or_insert(12); /// assert_eq!(map.entry("poneyland").key(), &"poneyland"); /// ``` + #[must_use] #[stable(feature = "map_entry_keys", since = "1.10.0")] pub fn key(&self) -> &K { self.handle.reborrow().into_kv().0 @@ -391,6 +392,7 @@ impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> { /// assert_eq!(o.get(), &12); /// } /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn get(&self) -> &V { self.handle.reborrow().into_kv().1 diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs index 173960341f..17389657af 100644 --- a/library/alloc/src/collections/btree/map/tests.rs +++ b/library/alloc/src/collections/btree/map/tests.rs @@ -744,35 +744,35 @@ fn test_range_equal_empty_cases() { #[should_panic] fn test_range_equal_excluded() { let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect(); - map.range((Excluded(2), Excluded(2))); + let _ = map.range((Excluded(2), Excluded(2))); } #[test] #[should_panic] fn test_range_backwards_1() { let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect(); - map.range((Included(3), Included(2))); + let _ = map.range((Included(3), Included(2))); } #[test] #[should_panic] fn test_range_backwards_2() { let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect(); - map.range((Included(3), Excluded(2))); + let _ = map.range((Included(3), Excluded(2))); } #[test] #[should_panic] fn test_range_backwards_3() { let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect(); - map.range((Excluded(3), Included(2))); + let _ = map.range((Excluded(3), Included(2))); } #[test] #[should_panic] fn test_range_backwards_4() { let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect(); - map.range((Excluded(3), Excluded(2))); + let _ = map.range((Excluded(3), Excluded(2))); } #[test] @@ -783,7 +783,7 @@ fn test_range_finding_ill_order_in_map() { // we cause a different panic than `test_range_backwards_1` does. // A more refined `should_panic` would be welcome. if Cyclic3::C < Cyclic3::A { - map.range(Cyclic3::C..=Cyclic3::A); + let _ = map.range(Cyclic3::C..=Cyclic3::A); } } @@ -824,7 +824,7 @@ fn test_range_finding_ill_order_in_range_ord() { } let map = (0..12).map(|i| (CompositeKey(i, EvilTwin(i)), ())).collect::>(); - map.range(EvilTwin(5)..=EvilTwin(7)); + let _ = map.range(EvilTwin(5)..=EvilTwin(7)); } #[test] @@ -1239,32 +1239,32 @@ fn test_borrow() { #[allow(dead_code)] fn get(v: &BTreeMap, ()>, t: &T) { - v.get(t); + let _ = v.get(t); } #[allow(dead_code)] fn get_mut(v: &mut BTreeMap, ()>, t: &T) { - v.get_mut(t); + let _ = v.get_mut(t); } #[allow(dead_code)] fn get_key_value(v: &BTreeMap, ()>, t: &T) { - v.get_key_value(t); + let _ = v.get_key_value(t); } #[allow(dead_code)] fn contains_key(v: &BTreeMap, ()>, t: &T) { - v.contains_key(t); + let _ = v.contains_key(t); } #[allow(dead_code)] fn range(v: &BTreeMap, ()>, t: T) { - v.range(t..); + let _ = v.range(t..); } #[allow(dead_code)] fn range_mut(v: &mut BTreeMap, ()>, t: T) { - v.range_mut(t..); + let _ = v.range_mut(t..); } #[allow(dead_code)] diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index d732f65b0d..0322cabccd 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -23,9 +23,9 @@ use super::Recover; /// It is a logic error for an item to be modified in such a way that the item's ordering relative /// to any other item, as determined by the [`Ord`] trait, changes while it is in the set. This is /// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code. -/// The behavior resulting from such a logic error is not specified, but will not result in -/// undefined behavior. This could include panics, incorrect results, aborts, memory leaks, and -/// non-termination. +/// The behavior resulting from such a logic error is not specified (it could include panics, +/// incorrect results, aborts, memory leaks, or non-termination) but will not be undefined +/// behavior. /// /// [`Ord`]: core::cmp::Ord /// [`Cell`]: core::cell::Cell @@ -92,6 +92,7 @@ impl Clone for BTreeSet { /// See its documentation for more. /// /// [`iter`]: BTreeSet::iter +#[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] pub struct Iter<'a, T: 'a> { iter: Keys<'a, T, ()>, @@ -123,6 +124,7 @@ pub struct IntoIter { /// See its documentation for more. /// /// [`range`]: BTreeSet::range +#[must_use = "iterators are lazy and do nothing unless consumed"] #[derive(Debug)] #[stable(feature = "btree_range", since = "1.17.0")] pub struct Range<'a, T: 'a> { @@ -135,6 +137,8 @@ pub struct Range<'a, T: 'a> { /// See its documentation for more. /// /// [`difference`]: BTreeSet::difference +#[must_use = "this returns the difference as an iterator, \ + without modifying either input set"] #[stable(feature = "rust1", since = "1.0.0")] pub struct Difference<'a, T: 'a> { inner: DifferenceInner<'a, T>, @@ -167,6 +171,8 @@ impl fmt::Debug for Difference<'_, T> { /// [`BTreeSet`]. See its documentation for more. /// /// [`symmetric_difference`]: BTreeSet::symmetric_difference +#[must_use = "this returns the difference as an iterator, \ + without modifying either input set"] #[stable(feature = "rust1", since = "1.0.0")] pub struct SymmetricDifference<'a, T: 'a>(MergeIterInner>); @@ -183,6 +189,8 @@ impl fmt::Debug for SymmetricDifference<'_, T> { /// See its documentation for more. /// /// [`intersection`]: BTreeSet::intersection +#[must_use = "this returns the intersection as an iterator, \ + without modifying either input set"] #[stable(feature = "rust1", since = "1.0.0")] pub struct Intersection<'a, T: 'a> { inner: IntersectionInner<'a, T>, @@ -215,6 +223,8 @@ impl fmt::Debug for Intersection<'_, T> { /// See its documentation for more. /// /// [`union`]: BTreeSet::union +#[must_use = "this returns the union as an iterator, \ + without modifying either input set"] #[stable(feature = "rust1", since = "1.0.0")] pub struct Union<'a, T: 'a>(MergeIterInner>); @@ -668,6 +678,7 @@ impl BTreeSet { /// set.insert(2); /// assert_eq!(set.first(), Some(&1)); /// ``` + #[must_use] #[unstable(feature = "map_first_last", issue = "62924")] pub fn first(&self) -> Option<&T> where @@ -694,6 +705,7 @@ impl BTreeSet { /// set.insert(2); /// assert_eq!(set.last(), Some(&2)); /// ``` + #[must_use] #[unstable(feature = "map_first_last", issue = "62924")] pub fn last(&self) -> Option<&T> where @@ -1034,6 +1046,7 @@ impl BTreeSet { /// v.insert(1); /// assert_eq!(v.len(), 1); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] pub const fn len(&self) -> usize { @@ -1052,6 +1065,7 @@ impl BTreeSet { /// v.insert(1); /// assert!(!v.is_empty()); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] pub const fn is_empty(&self) -> bool { diff --git a/library/alloc/src/collections/btree/set/tests.rs b/library/alloc/src/collections/btree/set/tests.rs index 0a87ae12d6..2fc17a7c86 100644 --- a/library/alloc/src/collections/btree/set/tests.rs +++ b/library/alloc/src/collections/btree/set/tests.rs @@ -610,11 +610,11 @@ fn test_send() { #[test] fn test_ord_absence() { fn set(mut set: BTreeSet) { - set.is_empty(); - set.len(); + let _ = set.is_empty(); + let _ = set.len(); set.clear(); - set.iter(); - set.into_iter(); + let _ = set.iter(); + let _ = set.into_iter(); } fn set_debug(set: BTreeSet) { diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index ea010c1f89..e4913b16ad 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -64,6 +64,7 @@ struct Node { /// /// This `struct` is created by [`LinkedList::iter()`]. See its /// documentation for more. +#[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] pub struct Iter<'a, T: 'a> { head: Option>>, @@ -99,6 +100,7 @@ impl Clone for Iter<'_, T> { /// /// This `struct` is created by [`LinkedList::iter_mut()`]. See its /// documentation for more. +#[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] pub struct IterMut<'a, T: 'a> { head: Option>>, @@ -529,6 +531,7 @@ impl LinkedList { /// /// The cursor is pointing to the "ghost" non-element if the list is empty. #[inline] + #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn cursor_front(&self) -> Cursor<'_, T> { Cursor { index: 0, current: self.head, list: self } @@ -538,6 +541,7 @@ impl LinkedList { /// /// The cursor is pointing to the "ghost" non-element if the list is empty. #[inline] + #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn cursor_front_mut(&mut self) -> CursorMut<'_, T> { CursorMut { index: 0, current: self.head, list: self } @@ -547,6 +551,7 @@ impl LinkedList { /// /// The cursor is pointing to the "ghost" non-element if the list is empty. #[inline] + #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn cursor_back(&self) -> Cursor<'_, T> { Cursor { index: self.len.checked_sub(1).unwrap_or(0), current: self.tail, list: self } @@ -556,6 +561,7 @@ impl LinkedList { /// /// The cursor is pointing to the "ghost" non-element if the list is empty. #[inline] + #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn cursor_back_mut(&mut self) -> CursorMut<'_, T> { CursorMut { index: self.len.checked_sub(1).unwrap_or(0), current: self.tail, list: self } @@ -577,6 +583,7 @@ impl LinkedList { /// assert!(!dl.is_empty()); /// ``` #[inline] + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn is_empty(&self) -> bool { self.head.is_none() @@ -603,6 +610,7 @@ impl LinkedList { /// assert_eq!(dl.len(), 3); /// ``` #[inline] + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn len(&self) -> usize { self.len @@ -678,6 +686,7 @@ impl LinkedList { /// assert_eq!(dl.front(), Some(&1)); /// ``` #[inline] + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn front(&self) -> Option<&T> { unsafe { self.head.as_ref().map(|node| &node.as_ref().element) } @@ -706,6 +715,7 @@ impl LinkedList { /// assert_eq!(dl.front(), Some(&5)); /// ``` #[inline] + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn front_mut(&mut self) -> Option<&mut T> { unsafe { self.head.as_mut().map(|node| &mut node.as_mut().element) } @@ -728,6 +738,7 @@ impl LinkedList { /// assert_eq!(dl.back(), Some(&1)); /// ``` #[inline] + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn back(&self) -> Option<&T> { unsafe { self.tail.as_ref().map(|node| &node.as_ref().element) } @@ -1178,6 +1189,7 @@ impl<'a, T> Cursor<'a, T> { /// /// This returns `None` if the cursor is currently pointing to the /// "ghost" non-element. + #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn index(&self) -> Option { let _ = self.current?; @@ -1232,6 +1244,7 @@ impl<'a, T> Cursor<'a, T> { /// /// This returns `None` if the cursor is currently pointing to the /// "ghost" non-element. + #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn current(&self) -> Option<&'a T> { unsafe { self.current.map(|current| &(*current.as_ptr()).element) } @@ -1242,6 +1255,7 @@ impl<'a, T> Cursor<'a, T> { /// If the cursor is pointing to the "ghost" non-element then this returns /// the first element of the `LinkedList`. If it is pointing to the last /// element of the `LinkedList` then this returns `None`. + #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn peek_next(&self) -> Option<&'a T> { unsafe { @@ -1258,6 +1272,7 @@ impl<'a, T> Cursor<'a, T> { /// If the cursor is pointing to the "ghost" non-element then this returns /// the last element of the `LinkedList`. If it is pointing to the first /// element of the `LinkedList` then this returns `None`. + #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn peek_prev(&self) -> Option<&'a T> { unsafe { @@ -1271,6 +1286,7 @@ impl<'a, T> Cursor<'a, T> { /// Provides a reference to the front element of the cursor's parent list, /// or None if the list is empty. + #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn front(&self) -> Option<&'a T> { self.list.front() @@ -1278,6 +1294,7 @@ impl<'a, T> Cursor<'a, T> { /// Provides a reference to the back element of the cursor's parent list, /// or None if the list is empty. + #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn back(&self) -> Option<&'a T> { self.list.back() @@ -1289,6 +1306,7 @@ impl<'a, T> CursorMut<'a, T> { /// /// This returns `None` if the cursor is currently pointing to the /// "ghost" non-element. + #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn index(&self) -> Option { let _ = self.current?; @@ -1343,6 +1361,7 @@ impl<'a, T> CursorMut<'a, T> { /// /// This returns `None` if the cursor is currently pointing to the /// "ghost" non-element. + #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn current(&mut self) -> Option<&mut T> { unsafe { self.current.map(|current| &mut (*current.as_ptr()).element) } @@ -1631,6 +1650,7 @@ impl<'a, T> CursorMut<'a, T> { /// Provides a reference to the front element of the cursor's parent list, /// or None if the list is empty. + #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn front(&self) -> Option<&T> { self.list.front() @@ -1638,6 +1658,7 @@ impl<'a, T> CursorMut<'a, T> { /// Provides a mutable reference to the front element of the cursor's /// parent list, or None if the list is empty. + #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn front_mut(&mut self) -> Option<&mut T> { self.list.front_mut() @@ -1645,6 +1666,7 @@ impl<'a, T> CursorMut<'a, T> { /// Provides a reference to the back element of the cursor's parent list, /// or None if the list is empty. + #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn back(&self) -> Option<&T> { self.list.back() @@ -1671,6 +1693,7 @@ impl<'a, T> CursorMut<'a, T> { /// assert_eq!(contents.next(), Some(0)); /// assert_eq!(contents.next(), None); /// ``` + #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn back_mut(&mut self) -> Option<&mut T> { self.list.back_mut() diff --git a/library/alloc/src/collections/mod.rs b/library/alloc/src/collections/mod.rs index 77d28bdfe6..1ea135a2ae 100644 --- a/library/alloc/src/collections/mod.rs +++ b/library/alloc/src/collections/mod.rs @@ -65,6 +65,7 @@ pub struct TryReserveError { impl TryReserveError { /// Details about the allocation that caused the error #[inline] + #[must_use] #[unstable( feature = "try_reserve_kind", reason = "Uncertain how much info should be exposed", diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index c890ff4ac5..de607c8fda 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -543,9 +543,9 @@ impl VecDeque { /// ``` #[unstable(feature = "allocator_api", issue = "32838")] pub fn with_capacity_in(capacity: usize, alloc: A) -> VecDeque { + assert!(capacity < 1_usize << usize::BITS - 1, "capacity overflow"); // +1 since the ringbuffer always leaves one space empty let cap = cmp::max(capacity + 1, MINIMUM_CAPACITY + 1).next_power_of_two(); - assert!(cap > capacity, "capacity overflow"); VecDeque { tail: 0, head: 0, buf: RawVec::with_capacity_in(cap, alloc) } } diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs index 878d8dc550..b4d16d74db 100644 --- a/library/alloc/src/fmt.rs +++ b/library/alloc/src/fmt.rs @@ -17,6 +17,8 @@ //! format!("The number is {}", 1); // => "The number is 1" //! format!("{:?}", (3, 4)); // => "(3, 4)" //! format!("{value}", value=4); // => "4" +//! let people = "Rustaceans"; +//! format!("Hello {people}!"); // => "Hello Rustaceans!" //! format!("{} {}", 1, 2); // => "1 2" //! format!("{:04}", 42); // => "0042" with leading zeros //! format!("{:#?}", (100, 200)); // => "( @@ -80,6 +82,19 @@ //! format!("{a} {c} {b}", a="a", b='b', c=3); // => "a 3 b" //! ``` //! +//! If a named parameter does not appear in the argument list, `format!` will +//! reference a variable with that name in the current scope. +//! +//! ``` +//! let argument = 2 + 2; +//! format!("{argument}"); // => "4" +//! +//! fn make_string(a: u32, b: &str) -> String { +//! format!("{b} {a}") +//! } +//! make_string(927, "label"); // => "label 927" +//! ``` +//! //! It is not valid to put positional parameters (those without names) after //! arguments that have names. Like with positional parameters, it is not //! valid to provide named parameters that are unused by the format string. @@ -98,6 +113,8 @@ //! println!("Hello {:1$}!", "x", 5); //! println!("Hello {1:0$}!", 5, "x"); //! println!("Hello {:width$}!", "x", width = 5); +//! let width = 5; +//! println!("Hello {:width$}!", "x"); //! ``` //! //! This is a parameter for the "minimum width" that the format should take up. @@ -572,6 +589,7 @@ use crate::string; /// [`format_args!`]: core::format_args /// [`format!`]: crate::format #[cfg(not(no_global_oom_handling))] +#[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn format(args: Arguments<'_>) -> string::String { let capacity = args.estimated_capacity(); diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 635708fd4c..4a66c3f6b2 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -80,87 +80,91 @@ )] #![no_std] #![needs_allocator] +// +// Lints: +#![deny(unsafe_op_in_unsafe_fn)] #![warn(deprecated_in_future)] -#![warn(missing_docs)] #![warn(missing_debug_implementations)] +#![warn(missing_docs)] #![allow(explicit_outlives_requirements)] -#![deny(unsafe_op_in_unsafe_fn)] -#![feature(rustc_allow_const_fn_unstable)] -#![cfg_attr(not(test), feature(generator_trait))] -#![cfg_attr(test, feature(test))] -#![cfg_attr(test, feature(new_uninit))] +// +// Library features: +#![feature(alloc_layout_extra)] #![feature(allocator_api)] #![feature(array_chunks)] #![feature(array_methods)] #![feature(array_windows)] -#![feature(allow_internal_unstable)] -#![feature(arbitrary_self_types)] #![feature(async_stream)] -#![feature(box_patterns)] -#![feature(box_syntax)] -#![feature(cfg_sanitize)] -#![feature(cfg_target_has_atomic)] #![feature(coerce_unsized)] #![cfg_attr(not(no_global_oom_handling), feature(const_btree_new))] -#![feature(const_fn_trait_bound)] -#![feature(cow_is_borrowed)] #![feature(const_cow_is_borrowed)] -#![feature(const_trait_impl)] -#![feature(destructuring_assignment)] -#![feature(dispatch_from_dyn)] #![feature(core_intrinsics)] -#![feature(dropck_eyepatch)] +#![feature(dispatch_from_dyn)] #![feature(exact_size_is_empty)] -#![feature(exclusive_range_pattern)] #![feature(extend_one)] #![feature(fmt_internals)] #![feature(fn_traits)] -#![feature(fundamental)] +#![feature(inherent_ascii_escape)] +#![cfg_attr(bootstrap, feature(format_args_capture))] #![feature(inplace_iteration)] -// 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_advance_by)] #![feature(iter_zip)] -#![feature(lang_items)] #![feature(layout_for_ptr)] -#![feature(negative_impls)] -#![feature(never_type)] -#![feature(nll)] +#![feature(maybe_uninit_extra)] +#![feature(maybe_uninit_slice)] +#![cfg_attr(test, feature(new_uninit))] #![feature(nonnull_slice_from_raw_parts)] -#![feature(auto_traits)] -#![feature(option_result_unwrap_unchecked)] #![feature(pattern)] #![feature(ptr_internals)] -#![feature(rustc_attrs)] #![feature(receiver_trait)] -#![feature(min_specialization)] #![feature(set_ptr_value)] +#![feature(slice_group_by)] #![feature(slice_ptr_get)] #![feature(slice_ptr_len)] #![feature(slice_range)] -#![feature(staged_api)] #![feature(str_internals)] #![feature(trusted_len)] -#![feature(unboxed_closures)] +#![feature(trusted_random_access)] +#![feature(try_trait_v2)] #![feature(unicode_internals)] #![feature(unsize)] -#![feature(unsized_fn_params)] +// +// Language features: #![feature(allocator_internals)] -#![feature(slice_partition_dedup)] -#![feature(maybe_uninit_extra, maybe_uninit_slice, maybe_uninit_uninit_array)] -#![feature(alloc_layout_extra)] -#![feature(trusted_random_access)] -#![feature(try_trait_v2)] +#![feature(allow_internal_unstable)] #![feature(associated_type_bounds)] -#![feature(slice_group_by)] -#![feature(decl_macro)] +#![feature(box_syntax)] +#![feature(cfg_sanitize)] +#![feature(cfg_target_has_atomic)] +#![feature(const_fn_trait_bound)] +#![feature(const_trait_impl)] +#![feature(destructuring_assignment)] +#![feature(dropck_eyepatch)] +#![feature(exclusive_range_pattern)] +#![feature(fundamental)] +#![cfg_attr(not(test), feature(generator_trait))] +#![feature(lang_items)] +#![feature(min_specialization)] +#![feature(negative_impls)] +#![feature(never_type)] +#![feature(nll)] // Not necessary, but here to test the `nll` feature. +#![feature(rustc_allow_const_fn_unstable)] +#![feature(rustc_attrs)] +#![feature(staged_api)] +#![cfg_attr(test, feature(test))] +#![feature(unboxed_closures)] +#![feature(unsized_fn_params)] +// +// Rustdoc features: #![feature(doc_cfg)] -#![cfg_attr(not(bootstrap), feature(doc_cfg_hide))] -// Allow testing this library +#![feature(doc_cfg_hide)] +// 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)] +// Allow testing this library #[cfg(test)] #[macro_use] extern crate std; @@ -171,6 +175,8 @@ extern crate test; #[macro_use] mod macros; +mod raw_vec; + // Heaps provided for low-level allocation strategies pub mod alloc; @@ -189,7 +195,6 @@ mod boxed { pub mod borrow; pub mod collections; pub mod fmt; -pub mod raw_vec; pub mod rc; pub mod slice; pub mod str; diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 75dbd4678b..4ab38c802a 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -1,5 +1,4 @@ -#![unstable(feature = "raw_vec_internals", reason = "implementation detail", issue = "none")] -#![doc(hidden)] +#![unstable(feature = "raw_vec_internals", reason = "unstable const warnings", issue = "none")] use core::alloc::LayoutError; use core::cmp; @@ -50,7 +49,7 @@ enum AllocInit { /// `usize::MAX`. This means that you need to be careful when round-tripping this type with a /// `Box<[T]>`, since `capacity()` won't yield the length. #[allow(missing_debug_implementations)] -pub struct RawVec { +pub(crate) struct RawVec { ptr: Unique, cap: usize, alloc: A, @@ -87,7 +86,7 @@ impl RawVec { /// # Aborts /// /// Aborts on OOM. - #[cfg(not(no_global_oom_handling))] + #[cfg(not(any(no_global_oom_handling, test)))] #[must_use] #[inline] pub fn with_capacity(capacity: usize) -> Self { @@ -95,25 +94,12 @@ impl RawVec { } /// Like `with_capacity`, but guarantees the buffer is zeroed. - #[cfg(not(no_global_oom_handling))] + #[cfg(not(any(no_global_oom_handling, test)))] #[must_use] #[inline] pub fn with_capacity_zeroed(capacity: usize) -> Self { Self::with_capacity_zeroed_in(capacity, Global) } - - /// Reconstitutes a `RawVec` from a pointer and capacity. - /// - /// # Safety - /// - /// The `ptr` must be allocated (on the system heap), and with the given `capacity`. - /// The `capacity` cannot exceed `isize::MAX` for sized types. (only a concern on 32-bit - /// systems). ZST vectors may have a capacity up to `usize::MAX`. - /// If the `ptr` and `capacity` come from a `RawVec`, then this is guaranteed. - #[inline] - pub unsafe fn from_raw_parts(ptr: *mut T, capacity: usize) -> Self { - unsafe { Self::from_raw_parts_in(ptr, capacity, Global) } - } } impl RawVec { @@ -154,14 +140,6 @@ impl RawVec { Self::allocate_in(capacity, AllocInit::Zeroed, alloc) } - /// Converts a `Box<[T]>` into a `RawVec`. - pub fn from_box(slice: Box<[T], A>) -> Self { - unsafe { - let (slice, alloc) = Box::into_raw_with_allocator(slice); - RawVec::from_raw_parts_in(slice.as_mut_ptr(), slice.len(), alloc) - } - } - /// Converts the entire buffer into `Box<[MaybeUninit]>` with the specified `len`. /// /// Note that this will correctly reconstitute any `cap` changes @@ -290,37 +268,6 @@ impl RawVec { /// # Aborts /// /// Aborts on OOM. - /// - /// # Examples - /// - /// ``` - /// # #![feature(raw_vec_internals)] - /// # extern crate alloc; - /// # use std::ptr; - /// # use alloc::raw_vec::RawVec; - /// struct MyVec { - /// buf: RawVec, - /// len: usize, - /// } - /// - /// impl MyVec { - /// pub fn push_all(&mut self, elems: &[T]) { - /// self.buf.reserve(self.len, elems.len()); - /// // reserve would have aborted or panicked if the len exceeded - /// // `isize::MAX` so this is safe to do unchecked now. - /// for x in elems { - /// unsafe { - /// ptr::write(self.buf.ptr().add(self.len), x.clone()); - /// } - /// self.len += 1; - /// } - /// } - /// } - /// # fn main() { - /// # let mut vector = MyVec { buf: RawVec::new(), len: 0 }; - /// # vector.push_all(&[1, 3, 5, 7, 9]); - /// # } - /// ``` #[cfg(not(no_global_oom_handling))] #[inline] pub fn reserve(&mut self, len: usize, additional: usize) { diff --git a/library/alloc/src/raw_vec/tests.rs b/library/alloc/src/raw_vec/tests.rs index 8c15a24409..ff322f0da9 100644 --- a/library/alloc/src/raw_vec/tests.rs +++ b/library/alloc/src/raw_vec/tests.rs @@ -77,3 +77,87 @@ fn reserve_does_not_overallocate() { assert!(v.capacity() >= 12 + 12 / 2); } } + +struct ZST; + +// A `RawVec` holding zero-sized elements should always look like this. +fn zst_sanity(v: &RawVec) { + assert_eq!(v.capacity(), usize::MAX); + assert_eq!(v.ptr(), core::ptr::Unique::::dangling().as_ptr()); + assert_eq!(v.current_memory(), None); +} + +#[test] +fn zst() { + let cap_err = Err(crate::collections::TryReserveErrorKind::CapacityOverflow.into()); + + assert_eq!(std::mem::size_of::(), 0); + + // All these different ways of creating the RawVec produce the same thing. + + let v: RawVec = RawVec::new(); + zst_sanity(&v); + + let v: RawVec = RawVec::with_capacity_in(100, Global); + zst_sanity(&v); + + let v: RawVec = RawVec::with_capacity_in(100, Global); + zst_sanity(&v); + + let v: RawVec = RawVec::allocate_in(0, AllocInit::Uninitialized, Global); + zst_sanity(&v); + + let v: RawVec = RawVec::allocate_in(100, AllocInit::Uninitialized, Global); + zst_sanity(&v); + + let mut v: RawVec = RawVec::allocate_in(usize::MAX, AllocInit::Uninitialized, Global); + zst_sanity(&v); + + // Check all these operations work as expected with zero-sized elements. + + assert!(!v.needs_to_grow(100, usize::MAX - 100)); + assert!(v.needs_to_grow(101, usize::MAX - 100)); + zst_sanity(&v); + + v.reserve(100, usize::MAX - 100); + //v.reserve(101, usize::MAX - 100); // panics, in `zst_reserve_panic` below + zst_sanity(&v); + + v.reserve_exact(100, usize::MAX - 100); + //v.reserve_exact(101, usize::MAX - 100); // panics, in `zst_reserve_exact_panic` below + zst_sanity(&v); + + assert_eq!(v.try_reserve(100, usize::MAX - 100), Ok(())); + assert_eq!(v.try_reserve(101, usize::MAX - 100), cap_err); + zst_sanity(&v); + + assert_eq!(v.try_reserve_exact(100, usize::MAX - 100), Ok(())); + assert_eq!(v.try_reserve_exact(101, usize::MAX - 100), cap_err); + zst_sanity(&v); + + assert_eq!(v.grow_amortized(100, usize::MAX - 100), cap_err); + assert_eq!(v.grow_amortized(101, usize::MAX - 100), cap_err); + zst_sanity(&v); + + assert_eq!(v.grow_exact(100, usize::MAX - 100), cap_err); + assert_eq!(v.grow_exact(101, usize::MAX - 100), cap_err); + zst_sanity(&v); +} + +#[test] +#[should_panic(expected = "capacity overflow")] +fn zst_reserve_panic() { + let mut v: RawVec = RawVec::new(); + zst_sanity(&v); + + v.reserve(101, usize::MAX - 100); +} + +#[test] +#[should_panic(expected = "capacity overflow")] +fn zst_reserve_exact_panic() { + let mut v: RawVec = RawVec::new(); + zst_sanity(&v); + + v.reserve_exact(101, usize::MAX - 100); +} diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 493cf3117e..c4e5e44fec 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -41,7 +41,7 @@ //! use std::rc::Rc; //! //! let my_rc = Rc::new(()); -//! Rc::downgrade(&my_rc); +//! let my_weak = Rc::downgrade(&my_rc); //! ``` //! //! `Rc`'s implementations of traits like `Clone` may also be called using @@ -313,11 +313,19 @@ pub struct Rc { #[stable(feature = "rust1", since = "1.0.0")] impl !marker::Send for Rc {} + +// Note that this negative impl isn't strictly necessary for correctness, +// as `Rc` transitively contains a `Cell`, which is itself `!Sync`. +// However, given how important `Rc`'s `!Sync`-ness is, +// having an explicit negative impl is nice for documentation purposes +// and results in nicer error messages. #[stable(feature = "rust1", since = "1.0.0")] impl !marker::Sync for Rc {} #[stable(feature = "catch_unwind", since = "1.9.0")] impl UnwindSafe for Rc {} +#[stable(feature = "rc_ref_unwind_safe", since = "1.58.0")] +impl RefUnwindSafe for Rc {} #[unstable(feature = "coerce_unsized", issue = "27732")] impl, U: ?Sized> CoerceUnsized> for Rc {} @@ -333,12 +341,12 @@ impl Rc { unsafe { self.ptr.as_ref() } } - fn from_inner(ptr: NonNull>) -> Self { + unsafe fn from_inner(ptr: NonNull>) -> Self { Self { ptr, phantom: PhantomData } } unsafe fn from_ptr(ptr: *mut RcBox) -> Self { - Self::from_inner(unsafe { NonNull::new_unchecked(ptr) }) + unsafe { Self::from_inner(NonNull::new_unchecked(ptr)) } } } @@ -359,9 +367,11 @@ impl Rc { // pointers, which ensures that the weak destructor never frees // the allocation while the strong destructor is running, even // if the weak pointer is stored inside the strong one. - Self::from_inner( - Box::leak(box RcBox { strong: Cell::new(1), weak: Cell::new(1), value }).into(), - ) + unsafe { + Self::from_inner( + Box::leak(box RcBox { strong: Cell::new(1), weak: Cell::new(1), value }).into(), + ) + } } /// Constructs a new `Rc` using a weak reference to itself. Attempting @@ -412,16 +422,16 @@ impl Rc { // otherwise. let data = data_fn(&weak); - unsafe { + let strong = unsafe { let inner = init_ptr.as_ptr(); ptr::write(ptr::addr_of_mut!((*inner).value), data); let prev_value = (*inner).strong.get(); debug_assert_eq!(prev_value, 0, "No prior strong references should exist"); (*inner).strong.set(1); - } - let strong = Rc::from_inner(init_ptr); + Rc::from_inner(init_ptr) + }; // Strong references should collectively own a shared weak reference, // so don't run the destructor for our old weak reference. @@ -513,10 +523,12 @@ impl Rc { // pointers, which ensures that the weak destructor never frees // the allocation while the strong destructor is running, even // if the weak pointer is stored inside the strong one. - Ok(Self::from_inner( - Box::leak(Box::try_new(RcBox { strong: Cell::new(1), weak: Cell::new(1), value })?) - .into(), - )) + unsafe { + Ok(Self::from_inner( + Box::leak(Box::try_new(RcBox { strong: Cell::new(1), weak: Cell::new(1), value })?) + .into(), + )) + } } /// Constructs a new `Rc` with uninitialized contents, returning an error if the allocation fails @@ -738,7 +750,7 @@ impl Rc> { #[unstable(feature = "new_uninit", issue = "63291")] #[inline] pub unsafe fn assume_init(self) -> Rc { - Rc::from_inner(mem::ManuallyDrop::new(self).ptr.cast()) + unsafe { Rc::from_inner(mem::ManuallyDrop::new(self).ptr.cast()) } } } @@ -889,6 +901,8 @@ impl Rc { /// /// let weak_five = Rc::downgrade(&five); /// ``` + #[must_use = "this returns a new `Weak` pointer, \ + without modifying the original `Rc`"] #[stable(feature = "rc_weak", since = "1.4.0")] pub fn downgrade(this: &Self) -> Weak { this.inner().inc_weak(); @@ -1204,9 +1218,11 @@ impl Rc { /// ``` pub fn downcast(self) -> Result, Rc> { if (*self).is::() { - let ptr = self.ptr.cast::>(); - forget(self); - Ok(Rc::from_inner(ptr)) + unsafe { + let ptr = self.ptr.cast::>(); + forget(self); + Ok(Rc::from_inner(ptr)) + } } else { Err(self) } @@ -1479,8 +1495,10 @@ impl Clone for Rc { /// ``` #[inline] fn clone(&self) -> Rc { - self.inner().inc_strong(); - Self::from_inner(self.ptr) + unsafe { + self.inner().inc_strong(); + Self::from_inner(self.ptr) + } } } @@ -2235,17 +2253,21 @@ impl Weak { #[stable(feature = "rc_weak", since = "1.4.0")] pub fn upgrade(&self) -> Option> { let inner = self.inner()?; + if inner.strong() == 0 { None } else { - inner.inc_strong(); - Some(Rc::from_inner(self.ptr)) + unsafe { + inner.inc_strong(); + Some(Rc::from_inner(self.ptr)) + } } } /// Gets the number of strong (`Rc`) pointers pointing to this allocation. /// /// If `self` was created using [`Weak::new`], this will return 0. + #[must_use] #[stable(feature = "weak_counts", since = "1.41.0")] pub fn strong_count(&self) -> usize { if let Some(inner) = self.inner() { inner.strong() } else { 0 } @@ -2254,6 +2276,7 @@ impl Weak { /// Gets the number of `Weak` pointers pointing to this allocation. /// /// If no strong pointers remain, this will return zero. + #[must_use] #[stable(feature = "weak_counts", since = "1.41.0")] pub fn weak_count(&self) -> usize { self.inner() @@ -2324,6 +2347,7 @@ impl Weak { /// assert!(!first.ptr_eq(&third)); /// ``` #[inline] + #[must_use] #[stable(feature = "weak_ptr_eq", since = "1.39.0")] pub fn ptr_eq(&self, other: &Self) -> bool { self.ptr.as_ptr() == other.ptr.as_ptr() diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 860f21085f..ae730be0d2 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -108,6 +108,8 @@ pub use core::slice::ArrayChunks; pub use core::slice::ArrayChunksMut; #[unstable(feature = "array_windows", issue = "75027")] pub use core::slice::ArrayWindows; +#[unstable(feature = "inherent_ascii_escape", issue = "77174")] +pub use core::slice::EscapeAscii; #[stable(feature = "slice_get_slice", since = "1.28.0")] pub use core::slice::SliceIndex; #[stable(feature = "from_ref", since = "1.28.0")] @@ -130,6 +132,8 @@ pub use core::slice::{RChunks, RChunksExact, RChunksExactMut, RChunksMut}; pub use core::slice::{RSplit, RSplitMut}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::slice::{RSplitN, RSplitNMut, SplitN, SplitNMut}; +#[stable(feature = "split_inclusive", since = "1.51.0")] +pub use core::slice::{SplitInclusive, SplitInclusiveMut}; //////////////////////////////////////////////////////////////////////////////// // Basic slice extension methods diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index e1d0ee42f4..104f555656 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs @@ -46,7 +46,7 @@ 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")] +#[stable(feature = "split_inclusive", since = "1.51.0")] pub use core::str::SplitInclusive; #[stable(feature = "rust1", since = "1.0.0")] pub use core::str::SplitWhitespace; @@ -243,6 +243,7 @@ impl str { /// assert_eq!(*boxed_bytes, *s.as_bytes()); /// ``` #[stable(feature = "str_box_extras", since = "1.20.0")] + #[must_use = "`self` will be dropped if the result is not used"] #[inline] pub fn into_boxed_bytes(self: Box) -> Box<[u8]> { self.into() @@ -484,6 +485,7 @@ impl str { /// assert_eq!(boxed_str.into_string(), string); /// ``` #[stable(feature = "box_str", since = "1.4.0")] + #[must_use = "`self` will be dropped if the result is not used"] #[inline] pub fn into_string(self: Box) -> String { let slice = Box::<[u8]>::from(self); @@ -508,9 +510,10 @@ impl str { /// /// ```should_panic /// // this will panic at runtime - /// "0123456789abcdef".repeat(usize::MAX); + /// let huge = "0123456789abcdef".repeat(usize::MAX); /// ``` #[cfg(not(no_global_oom_handling))] + #[must_use] #[stable(feature = "repeat_str", since = "1.16.0")] pub fn repeat(&self, n: usize) -> String { unsafe { String::from_utf8_unchecked(self.as_bytes().repeat(n)) } diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index f479bf231b..906b0187f7 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -552,6 +552,7 @@ impl String { /// /// assert_eq!("Hello �World", output); /// ``` + #[must_use] #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] pub fn from_utf8_lossy(v: &[u8]) -> Cow<'_, str> { @@ -646,6 +647,7 @@ impl String { /// String::from_utf16_lossy(v)); /// ``` #[cfg(not(no_global_oom_handling))] + #[must_use] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn from_utf16_lossy(v: &[u16]) -> String { @@ -898,6 +900,7 @@ impl String { /// assert!(s.capacity() >= 10); /// ``` #[inline] + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn capacity(&self) -> usize { self.vec.capacity() @@ -1500,10 +1503,11 @@ impl String { /// /// # Safety /// - /// This function is unsafe because it does not check that the bytes passed - /// to it are valid UTF-8. If this constraint is violated, it may cause - /// memory unsafety issues with future users of the `String`, as the rest of - /// the standard library assumes that `String`s are valid UTF-8. + /// This function is unsafe because the returned `&mut Vec` allows writing + /// bytes which are not valid UTF-8. If this constraint is violated, using + /// the original `String` after dropping the `&mut Vec` may violate memory + /// safety, as the rest of the standard library assumes that `String`s are + /// valid UTF-8. /// /// # Examples /// @@ -1543,6 +1547,7 @@ impl String { /// assert_eq!(fancy_f.chars().count(), 3); /// ``` #[inline] + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn len(&self) -> usize { self.vec.len() @@ -1562,6 +1567,7 @@ impl String { /// assert!(!v.is_empty()); /// ``` #[inline] + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn is_empty(&self) -> bool { self.len() == 0 @@ -1822,6 +1828,7 @@ impl FromUtf8Error { /// // the first byte is invalid here /// assert_eq!(1, error.valid_up_to()); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn utf8_error(&self) -> Utf8Error { self.error diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index b75e9a2f3c..733a898b28 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -252,7 +252,7 @@ impl, U: ?Sized> CoerceUnsized> for Arc {} impl, U: ?Sized> DispatchFromDyn> for Arc {} impl Arc { - fn from_inner(ptr: NonNull>) -> Self { + unsafe fn from_inner(ptr: NonNull>) -> Self { Self { ptr, phantom: PhantomData } } @@ -348,7 +348,7 @@ impl Arc { weak: atomic::AtomicUsize::new(1), data, }; - Self::from_inner(Box::leak(x).into()) + unsafe { Self::from_inner(Box::leak(x).into()) } } /// Constructs a new `Arc` using a weak reference to itself. Attempting @@ -397,7 +397,7 @@ impl Arc { // Now we can properly initialize the inner value and turn our weak // reference into a strong reference. - unsafe { + let strong = unsafe { let inner = init_ptr.as_ptr(); ptr::write(ptr::addr_of_mut!((*inner).data), data); @@ -415,9 +415,9 @@ impl Arc { // possible with safe code alone. let prev_value = (*inner).strong.fetch_add(1, Release); debug_assert_eq!(prev_value, 0, "No prior strong references should exist"); - } - let strong = Arc::from_inner(init_ptr); + Arc::from_inner(init_ptr) + }; // Strong references should collectively own a shared weak reference, // so don't run the destructor for our old weak reference. @@ -529,7 +529,7 @@ impl Arc { weak: atomic::AtomicUsize::new(1), data, })?; - Ok(Self::from_inner(Box::leak(x).into())) + unsafe { Ok(Self::from_inner(Box::leak(x).into())) } } /// Constructs a new `Arc` with uninitialized contents, returning an error @@ -743,7 +743,7 @@ impl Arc> { #[must_use = "`self` will be dropped if the result is not used"] #[inline] pub unsafe fn assume_init(self) -> Arc { - Arc::from_inner(mem::ManuallyDrop::new(self).ptr.cast()) + unsafe { Arc::from_inner(mem::ManuallyDrop::new(self).ptr.cast()) } } } @@ -804,6 +804,7 @@ impl Arc { /// let x_ptr = Arc::into_raw(x); /// assert_eq!(unsafe { &*x_ptr }, "hello"); /// ``` + #[must_use = "losing the pointer will leak memory"] #[stable(feature = "rc_raw", since = "1.17.0")] pub fn into_raw(this: Self) -> *const T { let ptr = Self::as_ptr(&this); @@ -953,6 +954,7 @@ impl Arc { /// assert_eq!(1, Arc::weak_count(&five)); /// ``` #[inline] + #[must_use] #[stable(feature = "arc_counts", since = "1.15.0")] pub fn weak_count(this: &Self) -> usize { let cnt = this.inner().weak.load(SeqCst); @@ -982,6 +984,7 @@ impl Arc { /// assert_eq!(2, Arc::strong_count(&five)); /// ``` #[inline] + #[must_use] #[stable(feature = "arc_counts", since = "1.15.0")] pub fn strong_count(this: &Self) -> usize { this.inner().strong.load(SeqCst) @@ -1079,8 +1082,6 @@ impl Arc { drop(Weak { ptr: self.ptr }); } - #[inline] - #[stable(feature = "ptr_eq", since = "1.17.0")] /// Returns `true` if the two `Arc`s point to the same allocation /// (in a vein similar to [`ptr::eq`]). /// @@ -1098,6 +1099,9 @@ impl Arc { /// ``` /// /// [`ptr::eq`]: core::ptr::eq "ptr::eq" + #[inline] + #[must_use] + #[stable(feature = "ptr_eq", since = "1.17.0")] pub fn ptr_eq(this: &Self, other: &Self) -> bool { this.ptr.as_ptr() == other.ptr.as_ptr() } @@ -1337,7 +1341,7 @@ impl Clone for Arc { abort(); } - Self::from_inner(self.ptr) + unsafe { Self::from_inner(self.ptr) } } } @@ -1664,9 +1668,11 @@ impl Arc { T: Any + Send + Sync + 'static, { if (*self).is::() { - let ptr = self.ptr.cast::>(); - mem::forget(self); - Ok(Arc::from_inner(ptr)) + unsafe { + let ptr = self.ptr.cast::>(); + mem::forget(self); + Ok(Arc::from_inner(ptr)) + } } else { Err(self) } @@ -1895,7 +1901,7 @@ impl Weak { // value can be initialized after `Weak` references have already been created. In that case, we // expect to observe the fully initialized value. match inner.strong.compare_exchange_weak(n, n + 1, Acquire, Relaxed) { - Ok(_) => return Some(Arc::from_inner(self.ptr)), // null checked above + Ok(_) => return Some(unsafe { Arc::from_inner(self.ptr) }), // null checked above Err(old) => n = old, } } @@ -1904,6 +1910,7 @@ impl Weak { /// Gets the number of strong (`Arc`) pointers pointing to this allocation. /// /// If `self` was created using [`Weak::new`], this will return 0. + #[must_use] #[stable(feature = "weak_counts", since = "1.41.0")] pub fn strong_count(&self) -> usize { if let Some(inner) = self.inner() { inner.strong.load(SeqCst) } else { 0 } @@ -1920,6 +1927,7 @@ impl Weak { /// Due to implementation details, the returned value can be off by 1 in /// either direction when other threads are manipulating any `Arc`s or /// `Weak`s pointing to the same allocation. + #[must_use] #[stable(feature = "weak_counts", since = "1.41.0")] pub fn weak_count(&self) -> usize { self.inner() @@ -1999,6 +2007,7 @@ impl Weak { /// /// [`ptr::eq`]: core::ptr::eq "ptr::eq" #[inline] + #[must_use] #[stable(feature = "weak_ptr_eq", since = "1.39.0")] pub fn ptr_eq(&self, other: &Self) -> bool { self.ptr.as_ptr() == other.ptr.as_ptr() diff --git a/library/alloc/src/vec/drain.rs b/library/alloc/src/vec/drain.rs index e643940d01..ff98091a0d 100644 --- a/library/alloc/src/vec/drain.rs +++ b/library/alloc/src/vec/drain.rs @@ -60,6 +60,7 @@ impl<'a, T, A: Allocator> Drain<'a, T, A> { /// Returns a reference to the underlying allocator. #[unstable(feature = "allocator_api", issue = "32838")] + #[must_use] #[inline] pub fn allocator(&self) -> &A { unsafe { self.vec.as_ref().allocator() } diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 20a16869cb..8575991776 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1272,6 +1272,9 @@ impl Vec { /// The removed element is replaced by the last element of the vector. /// /// This does not preserve ordering, but is *O*(1). + /// If you need to preserve the element order, use [`remove`] instead. + /// + /// [`remove`]: Vec::remove /// /// # Panics /// @@ -1305,10 +1308,11 @@ impl Vec { // We replace self[index] with the last element. Note that if the // bounds check above succeeds there must be a last element (which // can be self[index] itself). - let last = ptr::read(self.as_ptr().add(len - 1)); - let hole = self.as_mut_ptr().add(index); + let value = ptr::read(self.as_ptr().add(index)); + let base_ptr = self.as_mut_ptr(); + ptr::copy(base_ptr.add(len - 1), base_ptr.add(index), 1); self.set_len(len - 1); - ptr::replace(hole, last) + value } } @@ -1367,7 +1371,7 @@ impl Vec { /// shifting all elements after it to the left. /// /// Note: Because this shifts over the remaining elements, it has a - /// worst-case performance of O(n). If you don't need the order of elements + /// worst-case performance of *O*(*n*). If you don't need the order of elements /// to be preserved, use [`swap_remove`] instead. /// /// [`swap_remove`]: Vec::swap_remove @@ -1443,6 +1447,34 @@ impl Vec { pub fn retain(&mut self, mut f: F) where F: FnMut(&T) -> bool, + { + self.retain_mut(|elem| f(elem)); + } + + /// Retains only the elements specified by the predicate, passing a mutable reference to it. + /// + /// In other words, remove all elements `e` such that `f(&mut e)` returns `false`. + /// This method operates in place, visiting each element exactly once in the + /// original order, and preserves the order of the retained elements. + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_retain_mut)] + /// + /// let mut vec = vec![1, 2, 3, 4]; + /// vec.retain_mut(|x| if *x > 3 { + /// false + /// } else { + /// *x += 1; + /// true + /// }); + /// assert_eq!(vec, [2, 3, 4]); + /// ``` + #[unstable(feature = "vec_retain_mut", issue = "90829")] + pub fn retain_mut(&mut self, mut f: F) + where + F: FnMut(&mut T) -> bool, { let original_len = self.len(); // Avoid double drop if the drop guard is not executed, @@ -1495,7 +1527,7 @@ impl Vec { g: &mut BackshiftOnDrop<'_, T, A>, ) -> bool where - F: FnMut(&T) -> bool, + F: FnMut(&mut T) -> bool, { // SAFETY: Unchecked element must be valid. let cur = unsafe { &mut *g.v.as_mut_ptr().add(g.processed_len) }; diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index 8c57c804ad..68e48348b0 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -25,6 +25,7 @@ #![feature(const_btree_new)] #![feature(const_default_impls)] #![feature(const_trait_impl)] +#![feature(const_str_from_utf8)] use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs index d3a87c056c..1b741f174f 100644 --- a/library/alloc/tests/str.rs +++ b/library/alloc/tests/str.rs @@ -1,3 +1,4 @@ +use std::assert_matches::assert_matches; use std::borrow::Cow; use std::cmp::Ordering::{Equal, Greater, Less}; use std::str::{from_utf8, from_utf8_unchecked}; @@ -883,6 +884,33 @@ fn test_is_utf8() { assert!(from_utf8(&[0xF4, 0x8F, 0xBF, 0xBF]).is_ok()); } +#[test] +fn test_const_is_utf8() { + const _: () = { + // deny overlong encodings + assert!(from_utf8(&[0xc0, 0x80]).is_err()); + assert!(from_utf8(&[0xc0, 0xae]).is_err()); + assert!(from_utf8(&[0xe0, 0x80, 0x80]).is_err()); + assert!(from_utf8(&[0xe0, 0x80, 0xaf]).is_err()); + assert!(from_utf8(&[0xe0, 0x81, 0x81]).is_err()); + assert!(from_utf8(&[0xf0, 0x82, 0x82, 0xac]).is_err()); + assert!(from_utf8(&[0xf4, 0x90, 0x80, 0x80]).is_err()); + + // deny surrogates + assert!(from_utf8(&[0xED, 0xA0, 0x80]).is_err()); + assert!(from_utf8(&[0xED, 0xBF, 0xBF]).is_err()); + + assert!(from_utf8(&[0xC2, 0x80]).is_ok()); + assert!(from_utf8(&[0xDF, 0xBF]).is_ok()); + assert!(from_utf8(&[0xE0, 0xA0, 0x80]).is_ok()); + assert!(from_utf8(&[0xED, 0x9F, 0xBF]).is_ok()); + assert!(from_utf8(&[0xEE, 0x80, 0x80]).is_ok()); + assert!(from_utf8(&[0xEF, 0xBF, 0xBF]).is_ok()); + assert!(from_utf8(&[0xF0, 0x90, 0x80, 0x80]).is_ok()); + assert!(from_utf8(&[0xF4, 0x8F, 0xBF, 0xBF]).is_ok()); + }; +} + #[test] fn from_utf8_mostly_ascii() { // deny invalid bytes embedded in long stretches of ascii @@ -895,13 +923,43 @@ fn from_utf8_mostly_ascii() { } } +#[test] +fn const_from_utf8_mostly_ascii() { + const _: () = { + // deny invalid bytes embedded in long stretches of ascii + let mut i = 32; + while i < 64 { + let mut data = [0; 128]; + data[i] = 0xC0; + assert!(from_utf8(&data).is_err()); + data[i] = 0xC2; + assert!(from_utf8(&data).is_err()); + + i = i + 1; + } + }; +} + #[test] fn from_utf8_error() { macro_rules! test { - ($input: expr, $expected_valid_up_to: expr, $expected_error_len: expr) => { + ($input: expr, $expected_valid_up_to:pat, $expected_error_len:pat) => { let error = from_utf8($input).unwrap_err(); - assert_eq!(error.valid_up_to(), $expected_valid_up_to); - assert_eq!(error.error_len(), $expected_error_len); + assert_matches!(error.valid_up_to(), $expected_valid_up_to); + assert_matches!(error.error_len(), $expected_error_len); + + const _: () = { + match from_utf8($input) { + Err(error) => { + let valid_up_to = error.valid_up_to(); + let error_len = error.error_len(); + + assert!(matches!(valid_up_to, $expected_valid_up_to)); + assert!(matches!(error_len, $expected_error_len)); + } + Ok(_) => unreachable!(), + } + }; }; } test!(b"A\xC3\xA9 \xFF ", 4, Some(1)); @@ -1031,7 +1089,7 @@ fn test_split_at_mut() { #[should_panic] fn test_split_at_boundscheck() { let s = "ศไทย中华Việt Nam"; - s.split_at(1); + let _ = s.split_at(1); } #[test] diff --git a/library/backtrace/.github/workflows/main.yml b/library/backtrace/.github/workflows/main.yml index 1e229f6f46..ef52903bb5 100644 --- a/library/backtrace/.github/workflows/main.yml +++ b/library/backtrace/.github/workflows/main.yml @@ -91,6 +91,11 @@ jobs: env: CARGO_PROFILE_DEV_SPLIT_DEBUGINFO: packed CARGO_PROFILE_TEST_SPLIT_DEBUGINFO: packed + # Test that, on macOS, binaries with no UUID work + - run: cargo clean && cargo test + if: matrix.os == 'macos-latest' + env: + RUSTFLAGS: "-C link-arg=-Wl,-no_uuid" # Test that, on Linux, packed/unpacked debuginfo both work - run: cargo clean && cargo test diff --git a/library/backtrace/Cargo.toml b/library/backtrace/Cargo.toml index 7c73584f19..7ad0bc9ca1 100644 --- a/library/backtrace/Cargo.toml +++ b/library/backtrace/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "backtrace" -version = "0.3.61" +version = "0.3.63" authors = ["The Rust Project Developers"] build = "build.rs" license = "MIT/Apache-2.0" @@ -40,10 +40,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.16.0", default-features = false } +addr2line = { version = "0.17.0", default-features = false } miniz_oxide = { version = "0.4.0", default-features = false } [dependencies.object] -version = "0.26.0" +version = "0.27.0" default-features = false features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive'] diff --git a/library/backtrace/crates/as-if-std/Cargo.toml b/library/backtrace/crates/as-if-std/Cargo.toml index c347935d19..13809b49a1 100644 --- a/library/backtrace/crates/as-if-std/Cargo.toml +++ b/library/backtrace/crates/as-if-std/Cargo.toml @@ -19,7 +19,7 @@ addr2line = { version = "0.16.0", default-features = false, optional = true } miniz_oxide = { version = "0.4.0", default-features = false } [dependencies.object] -version = "0.26" +version = "0.27" default-features = false optional = true features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive'] diff --git a/library/backtrace/src/backtrace/libunwind.rs b/library/backtrace/src/backtrace/libunwind.rs index 7919eb2d1c..ef77edda5d 100644 --- a/library/backtrace/src/backtrace/libunwind.rs +++ b/library/backtrace/src/backtrace/libunwind.rs @@ -55,14 +55,17 @@ impl Frame { return symbol_address; } - // It seems that on OSX `_Unwind_FindEnclosingFunction` returns a - // pointer to... something that's unclear. It's definitely not always - // the enclosing function for whatever reason. It's not entirely clear - // to me what's going on here, so pessimize this for now and just always + // The macOS linker emits a "compact" unwind table that only includes an + // entry for a function if that function either has an LSDA or its + // encoding differs from that of the previous entry. Consequently, on + // macOS, `_Unwind_FindEnclosingFunction` is unreliable (it can return a + // pointer to some totally unrelated function). Instead, we just always // return the ip. // - // Note the `skip_inner_frames.rs` test is skipped on OSX due to this - // clause, and if this is fixed that test in theory can be run on OSX! + // https://github.com/rust-lang/rust/issues/74771#issuecomment-664056788 + // + // Note the `skip_inner_frames.rs` test is skipped on macOS due to this + // clause, and if this is fixed that test in theory can be run on macOS! if cfg!(target_os = "macos") || cfg!(target_os = "ios") { self.ip() } else { @@ -143,142 +146,122 @@ mod uw { extern "C" fn(ctx: *mut _Unwind_Context, arg: *mut c_void) -> _Unwind_Reason_Code; extern "C" { - // No native _Unwind_Backtrace on iOS - #[cfg(not(all(target_os = "ios", target_arch = "arm")))] pub fn _Unwind_Backtrace( trace: _Unwind_Trace_Fn, trace_argument: *mut c_void, ) -> _Unwind_Reason_Code; + } + cfg_if::cfg_if! { // available since GCC 4.2.0, should be fine for our purpose - #[cfg(all( - not(all(target_os = "android", target_arch = "arm")), - not(all(target_os = "freebsd", target_arch = "arm")), - not(all(target_os = "linux", target_arch = "arm")) - ))] - pub fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> libc::uintptr_t; - - #[cfg(all( - not(all(target_os = "android", target_arch = "arm")), - not(all(target_os = "freebsd", target_arch = "arm")), - not(all(target_os = "linux", target_arch = "arm")) - ))] - pub fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void; - - #[cfg(all( + if #[cfg(all( not(all(target_os = "android", target_arch = "arm")), not(all(target_os = "freebsd", target_arch = "arm")), not(all(target_os = "linux", target_arch = "arm")), - not(all(target_os = "linux", target_arch = "s390x")) - ))] - // This function is a misnomer: rather than getting this frame's - // Canonical Frame Address (aka the caller frame's SP) it - // returns this frame's SP. - // - // https://github.com/libunwind/libunwind/blob/d32956507cf29d9b1a98a8bce53c78623908f4fe/src/unwind/GetCFA.c#L28-L35 - #[link_name = "_Unwind_GetCFA"] - pub fn get_sp(ctx: *mut _Unwind_Context) -> libc::uintptr_t; - } + not(all(target_os = "horizon", target_arch = "arm")) + ))] { + extern "C" { + pub fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> libc::uintptr_t; + pub fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void; - // s390x uses a biased CFA value, therefore we need to use - // _Unwind_GetGR to get the stack pointer register (%r15) - // instead of relying on _Unwind_GetCFA. - #[cfg(all(target_os = "linux", target_arch = "s390x"))] - pub unsafe fn get_sp(ctx: *mut _Unwind_Context) -> libc::uintptr_t { - extern "C" { - pub fn _Unwind_GetGR(ctx: *mut _Unwind_Context, index: libc::c_int) -> libc::uintptr_t; - } - _Unwind_GetGR(ctx, 15) - } + #[cfg(not(all(target_os = "linux", target_arch = "s390x")))] + // This function is a misnomer: rather than getting this frame's + // Canonical Frame Address (aka the caller frame's SP) it + // returns this frame's SP. + // + // https://github.com/libunwind/libunwind/blob/d32956507cf29d9b1a98a8bce53c78623908f4fe/src/unwind/GetCFA.c#L28-L35 + #[link_name = "_Unwind_GetCFA"] + pub fn get_sp(ctx: *mut _Unwind_Context) -> libc::uintptr_t; - // On android and arm, the function `_Unwind_GetIP` and a bunch of others - // are macros, so we define functions containing the expansion of the - // macros. - // - // TODO: link to the header file that defines these macros, if you can find - // it. (I, fitzgen, cannot find the header file that some of these macro - // expansions were originally borrowed from.) - #[cfg(any( - all(target_os = "android", target_arch = "arm"), - all(target_os = "freebsd", target_arch = "arm"), - all(target_os = "linux", target_arch = "arm") - ))] - pub use self::arm::*; - #[cfg(any( - all(target_os = "android", target_arch = "arm"), - all(target_os = "freebsd", target_arch = "arm"), - all(target_os = "linux", target_arch = "arm") - ))] - mod arm { - pub use super::*; - #[repr(C)] - enum _Unwind_VRS_Result { - _UVRSR_OK = 0, - _UVRSR_NOT_IMPLEMENTED = 1, - _UVRSR_FAILED = 2, - } - #[repr(C)] - enum _Unwind_VRS_RegClass { - _UVRSC_CORE = 0, - _UVRSC_VFP = 1, - _UVRSC_FPA = 2, - _UVRSC_WMMXD = 3, - _UVRSC_WMMXC = 4, - } - #[repr(C)] - enum _Unwind_VRS_DataRepresentation { - _UVRSD_UINT32 = 0, - _UVRSD_VFPX = 1, - _UVRSD_FPAX = 2, - _UVRSD_UINT64 = 3, - _UVRSD_FLOAT = 4, - _UVRSD_DOUBLE = 5, - } + } - type _Unwind_Word = libc::c_uint; - extern "C" { - fn _Unwind_VRS_Get( - ctx: *mut _Unwind_Context, - klass: _Unwind_VRS_RegClass, - word: _Unwind_Word, - repr: _Unwind_VRS_DataRepresentation, - data: *mut c_void, - ) -> _Unwind_VRS_Result; - } + // s390x uses a biased CFA value, therefore we need to use + // _Unwind_GetGR to get the stack pointer register (%r15) + // instead of relying on _Unwind_GetCFA. + #[cfg(all(target_os = "linux", target_arch = "s390x"))] + pub unsafe fn get_sp(ctx: *mut _Unwind_Context) -> libc::uintptr_t { + extern "C" { + pub fn _Unwind_GetGR(ctx: *mut _Unwind_Context, index: libc::c_int) -> libc::uintptr_t; + } + _Unwind_GetGR(ctx, 15) + } + } else { + // On android and arm, the function `_Unwind_GetIP` and a bunch of + // others are macros, so we define functions containing the + // expansion of the macros. + // + // TODO: link to the header file that defines these macros, if you + // can find it. (I, fitzgen, cannot find the header file that some + // of these macro expansions were originally borrowed from.) + #[repr(C)] + enum _Unwind_VRS_Result { + _UVRSR_OK = 0, + _UVRSR_NOT_IMPLEMENTED = 1, + _UVRSR_FAILED = 2, + } + #[repr(C)] + enum _Unwind_VRS_RegClass { + _UVRSC_CORE = 0, + _UVRSC_VFP = 1, + _UVRSC_FPA = 2, + _UVRSC_WMMXD = 3, + _UVRSC_WMMXC = 4, + } + #[repr(C)] + enum _Unwind_VRS_DataRepresentation { + _UVRSD_UINT32 = 0, + _UVRSD_VFPX = 1, + _UVRSD_FPAX = 2, + _UVRSD_UINT64 = 3, + _UVRSD_FLOAT = 4, + _UVRSD_DOUBLE = 5, + } - pub unsafe fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> libc::uintptr_t { - let mut val: _Unwind_Word = 0; - let ptr = &mut val as *mut _Unwind_Word; - let _ = _Unwind_VRS_Get( - ctx, - _Unwind_VRS_RegClass::_UVRSC_CORE, - 15, - _Unwind_VRS_DataRepresentation::_UVRSD_UINT32, - ptr as *mut c_void, - ); - (val & !1) as libc::uintptr_t - } + type _Unwind_Word = libc::c_uint; + extern "C" { + fn _Unwind_VRS_Get( + ctx: *mut _Unwind_Context, + klass: _Unwind_VRS_RegClass, + word: _Unwind_Word, + repr: _Unwind_VRS_DataRepresentation, + data: *mut c_void, + ) -> _Unwind_VRS_Result; + } - // R13 is the stack pointer on arm. - const SP: _Unwind_Word = 13; + pub unsafe fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> libc::uintptr_t { + let mut val: _Unwind_Word = 0; + let ptr = &mut val as *mut _Unwind_Word; + let _ = _Unwind_VRS_Get( + ctx, + _Unwind_VRS_RegClass::_UVRSC_CORE, + 15, + _Unwind_VRS_DataRepresentation::_UVRSD_UINT32, + ptr as *mut c_void, + ); + (val & !1) as libc::uintptr_t + } - pub unsafe fn get_sp(ctx: *mut _Unwind_Context) -> libc::uintptr_t { - let mut val: _Unwind_Word = 0; - let ptr = &mut val as *mut _Unwind_Word; - let _ = _Unwind_VRS_Get( - ctx, - _Unwind_VRS_RegClass::_UVRSC_CORE, - SP, - _Unwind_VRS_DataRepresentation::_UVRSD_UINT32, - ptr as *mut c_void, - ); - val as libc::uintptr_t - } + // R13 is the stack pointer on arm. + const SP: _Unwind_Word = 13; + + pub unsafe fn get_sp(ctx: *mut _Unwind_Context) -> libc::uintptr_t { + let mut val: _Unwind_Word = 0; + let ptr = &mut val as *mut _Unwind_Word; + let _ = _Unwind_VRS_Get( + ctx, + _Unwind_VRS_RegClass::_UVRSC_CORE, + SP, + _Unwind_VRS_DataRepresentation::_UVRSD_UINT32, + ptr as *mut c_void, + ); + val as libc::uintptr_t + } - // This function also doesn't exist on Android or ARM/Linux, so make it - // a no-op. - pub unsafe fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void { - pc + // This function also doesn't exist on Android or ARM/Linux, so make it + // a no-op. + pub unsafe fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void { + pc + } } } } diff --git a/library/backtrace/src/symbolize/gimli/macho.rs b/library/backtrace/src/symbolize/gimli/macho.rs index 9d21c7d294..ec56738434 100644 --- a/library/backtrace/src/symbolize/gimli/macho.rs +++ b/library/backtrace/src/symbolize/gimli/macho.rs @@ -22,7 +22,7 @@ impl Mapping { let map = super::mmap(path)?; let (macho, data) = find_header(&map)?; let endian = macho.endian().ok()?; - let uuid = macho.uuid(endian, data, 0).ok()??; + let uuid = macho.uuid(endian, data, 0).ok()?; // Next we need to look for a `*.dSYM` file. For now we just probe the // containing directory and look around for something that matches @@ -30,9 +30,11 @@ impl Mapping { // contains and try to find a macho file which has a matching UUID as // the one of our own file. If we find a match that's the dwarf file we // want to return. - if let Some(parent) = path.parent() { - if let Some(mapping) = Mapping::load_dsym(parent, uuid) { - return Some(mapping); + if let Some(uuid) = uuid { + if let Some(parent) = path.parent() { + if let Some(mapping) = Mapping::load_dsym(parent, uuid) { + return Some(mapping); + } } } diff --git a/library/backtrace/src/symbolize/mod.rs b/library/backtrace/src/symbolize/mod.rs index cf8d90f658..20ba4207fd 100644 --- a/library/backtrace/src/symbolize/mod.rs +++ b/library/backtrace/src/symbolize/mod.rs @@ -66,7 +66,7 @@ pub fn resolve(addr: *mut c_void, cb: F) { /// Resolve a previously capture frame to a symbol, passing the symbol to the /// specified closure. /// -/// This functin performs the same function as `resolve` except that it takes a +/// This function performs the same function as `resolve` except that it takes a /// `Frame` as an argument instead of an address. This can allow some platform /// implementations of backtracing to provide more accurate symbol information /// or information about inline frames for example. It's recommended to use this diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index 780f82d8af..9df0b5c551 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -104,6 +104,7 @@ impl Layout { /// The minimum size in bytes for a memory block of this layout. #[stable(feature = "alloc_layout", since = "1.28.0")] #[rustc_const_stable(feature = "const_alloc_layout", since = "1.50.0")] + #[must_use] #[inline] pub const fn size(&self) -> usize { self.size_ @@ -137,6 +138,7 @@ impl Layout { /// allocate backing structure for `T` (which could be a trait /// or other unsized type like a slice). #[stable(feature = "alloc_layout", since = "1.28.0")] + #[must_use] #[inline] pub fn for_value(t: &T) -> Self { let (size, align) = (mem::size_of_val(t), mem::align_of_val(t)); @@ -171,6 +173,7 @@ impl Layout { /// [trait object]: ../../book/ch17-02-trait-objects.html /// [extern type]: ../../unstable-book/language-features/extern-types.html #[unstable(feature = "layout_for_ptr", issue = "69835")] + #[must_use] pub unsafe fn for_value_raw(t: *const T) -> Self { // SAFETY: we pass along the prerequisites of these functions to the caller let (size, align) = unsafe { (mem::size_of_val_raw(t), mem::align_of_val_raw(t)) }; @@ -187,6 +190,7 @@ impl Layout { /// some other means. #[unstable(feature = "alloc_layout_extra", issue = "55724")] #[rustc_const_unstable(feature = "alloc_layout_extra", issue = "55724")] + #[must_use] #[inline] pub const fn dangling(&self) -> NonNull { // SAFETY: align is guaranteed to be non-zero @@ -277,7 +281,9 @@ impl Layout { // > `usize::MAX`) let new_size = self.size() + pad; - Layout::from_size_align(new_size, self.align()).unwrap() + // SAFETY: self.align is already known to be valid and new_size has been + // padded already. + unsafe { Layout::from_size_align_unchecked(new_size, self.align()) } } /// Creates a layout describing the record for `n` instances of @@ -399,9 +405,17 @@ impl Layout { #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] #[inline] pub fn array(n: usize) -> Result { - let (layout, offset) = Layout::new::().repeat(n)?; - debug_assert_eq!(offset, mem::size_of::()); - Ok(layout.pad_to_align()) + let array_size = mem::size_of::().checked_mul(n).ok_or(LayoutError)?; + + // SAFETY: + // - Size: `array_size` cannot be too big because `size_of::()` must + // be a multiple of `align_of::()`. Therefore, `array_size` + // rounded up to the nearest multiple of `align_of::()` is just + // `array_size`. And `array_size` cannot be too big because it was + // just checked by the `checked_mul()`. + // - Alignment: `align_of::()` will always give an acceptable + // (non-zero, power of two) alignment. + Ok(unsafe { Layout::from_size_align_unchecked(array_size, mem::align_of::()) }) } } diff --git a/library/core/src/any.rs b/library/core/src/any.rs index 19652106b3..1fd5aa27fc 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -458,6 +458,7 @@ impl TypeId { /// assert_eq!(is_string(&0), false); /// assert_eq!(is_string(&"cookie monster".to_string()), true); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_type_id", issue = "77125")] pub const fn of() -> TypeId { @@ -492,6 +493,7 @@ impl TypeId { /// "core::option::Option", /// ); /// ``` +#[must_use] #[stable(feature = "type_name", since = "1.38.0")] #[rustc_const_unstable(feature = "const_type_name", issue = "63084")] pub const fn type_name() -> &'static str { @@ -534,6 +536,7 @@ pub const fn type_name() -> &'static str { /// let y = 1.0; /// println!("{}", type_name_of_val(&y)); /// ``` +#[must_use] #[unstable(feature = "type_name_of_val", issue = "66359")] #[rustc_const_unstable(feature = "const_type_name", issue = "63084")] pub const fn type_name_of_val(_val: &T) -> &'static str { diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 8d5c051040..09bb451917 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -85,14 +85,16 @@ where /// Converts a reference to `T` into a reference to an array of length 1 (without copying). #[stable(feature = "array_from_ref", since = "1.53.0")] -pub fn from_ref(s: &T) -> &[T; 1] { +#[rustc_const_unstable(feature = "const_array_from_ref", issue = "90206")] +pub const 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). #[stable(feature = "array_from_ref", since = "1.53.0")] -pub fn from_mut(s: &mut T) -> &mut [T; 1] { +#[rustc_const_unstable(feature = "const_array_from_ref", issue = "90206")] +pub const 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]>() } } @@ -125,7 +127,8 @@ impl TryFromSliceError { } #[stable(feature = "try_from_slice_error", since = "1.36.0")] -impl From for TryFromSliceError { +#[rustc_const_unstable(feature = "const_convert", issue = "88674")] +impl const From for TryFromSliceError { fn from(x: Infallible) -> TryFromSliceError { match x {} } @@ -327,6 +330,47 @@ impl Ord for [T; N] { } } +#[cfg(not(bootstrap))] +#[stable(feature = "copy_clone_array_lib", since = "1.58.0")] +impl Copy for [T; N] {} + +#[cfg(not(bootstrap))] +#[stable(feature = "copy_clone_array_lib", since = "1.58.0")] +impl Clone for [T; N] { + #[inline] + fn clone(&self) -> Self { + SpecArrayClone::clone(self) + } + + #[inline] + fn clone_from(&mut self, other: &Self) { + self.clone_from_slice(other); + } +} + +#[cfg(not(bootstrap))] +trait SpecArrayClone: Clone { + fn clone(array: &[Self; N]) -> [Self; N]; +} + +#[cfg(not(bootstrap))] +impl SpecArrayClone for T { + #[inline] + default fn clone(array: &[T; N]) -> [T; N] { + // SAFETY: we know for certain that this iterator will yield exactly `N` + // items. + unsafe { collect_into_array_unchecked(&mut array.iter().cloned()) } + } +} + +#[cfg(not(bootstrap))] +impl SpecArrayClone for T { + #[inline] + fn clone(array: &[T; N]) -> [T; N] { + *array + } +} + // The Default impls cannot be done with const generics because `[T; 0]` doesn't // require Default to be implemented, and having different impl blocks for // different numbers isn't supported yet. @@ -499,6 +543,84 @@ impl [T; N] { // items. unsafe { collect_into_array_unchecked(&mut self.iter_mut()) } } + + /// Divides one array reference into two at an index. + /// + /// The first will contain all indices from `[0, M)` (excluding + /// the index `M` itself) and the second will contain all + /// indices from `[M, N)` (excluding the index `N` itself). + /// + /// # Panics + /// + /// Panics if `M > N`. + /// + /// # Examples + /// + /// ``` + /// #![feature(split_array)] + /// + /// let v = [1, 2, 3, 4, 5, 6]; + /// + /// { + /// let (left, right) = v.split_array_ref::<0>(); + /// assert_eq!(left, &[]); + /// assert_eq!(right, &[1, 2, 3, 4, 5, 6]); + /// } + /// + /// { + /// let (left, right) = v.split_array_ref::<2>(); + /// assert_eq!(left, &[1, 2]); + /// assert_eq!(right, &[3, 4, 5, 6]); + /// } + /// + /// { + /// let (left, right) = v.split_array_ref::<6>(); + /// assert_eq!(left, &[1, 2, 3, 4, 5, 6]); + /// assert_eq!(right, &[]); + /// } + /// ``` + #[unstable( + feature = "split_array", + reason = "return type should have array as 2nd element", + issue = "90091" + )] + #[inline] + pub fn split_array_ref(&self) -> (&[T; M], &[T]) { + (&self[..]).split_array_ref::() + } + + /// Divides one mutable array reference into two at an index. + /// + /// The first will contain all indices from `[0, M)` (excluding + /// the index `M` itself) and the second will contain all + /// indices from `[M, N)` (excluding the index `N` itself). + /// + /// # Panics + /// + /// Panics if `M > N`. + /// + /// # Examples + /// + /// ``` + /// #![feature(split_array)] + /// + /// let mut v = [1, 0, 3, 0, 5, 6]; + /// let (left, right) = v.split_array_mut::<2>(); + /// assert_eq!(left, &mut [1, 0][..]); + /// assert_eq!(right, &mut [3, 0, 5, 6]); + /// left[1] = 2; + /// right[1] = 4; + /// assert_eq!(v, [1, 2, 3, 4, 5, 6]); + /// ``` + #[unstable( + feature = "split_array", + reason = "return type should have array as 2nd element", + issue = "90091" + )] + #[inline] + pub fn split_array_mut(&mut self) -> (&mut [T; M], &mut [T]) { + (&mut self[..]).split_array_mut::() + } } /// Pulls `N` items from `iter` and returns them as an array. If the iterator diff --git a/library/core/src/ascii.rs b/library/core/src/ascii.rs index 0a456ee1eb..532208e41a 100644 --- a/library/core/src/ascii.rs +++ b/library/core/src/ascii.rs @@ -18,6 +18,7 @@ use crate::str::from_utf8_unchecked; /// /// This `struct` is created by the [`escape_default`] function. See its /// documentation for more. +#[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] #[derive(Clone)] pub struct EscapeDefault { diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 2ca077a98f..06dc5ecf2f 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -240,6 +240,11 @@ pub struct Cell { #[stable(feature = "rust1", since = "1.0.0")] unsafe impl Send for Cell where T: Send {} +// Note that this negative impl isn't strictly necessary for correctness, +// as `Cell` wraps `UnsafeCell`, which is itself `!Sync`. +// However, given how important `Cell`'s `!Sync`-ness is, +// having an explicit negative impl is nice for documentation purposes +// and results in nicer error messages. #[stable(feature = "rust1", since = "1.0.0")] impl !Sync for Cell {} @@ -308,7 +313,8 @@ impl Ord for Cell { } #[stable(feature = "cell_from", since = "1.12.0")] -impl From for Cell { +#[rustc_const_unstable(feature = "const_convert", issue = "88674")] +impl const From for Cell { fn from(t: T) -> Cell { Cell::new(t) } @@ -1236,7 +1242,8 @@ impl Ord for RefCell { } #[stable(feature = "cell_from", since = "1.12.0")] -impl From for RefCell { +#[rustc_const_unstable(feature = "const_convert", issue = "88674")] +impl const From for RefCell { fn from(t: T) -> RefCell { RefCell::new(t) } @@ -1333,6 +1340,7 @@ impl<'b, T: ?Sized> Ref<'b, T> { /// with the widespread use of `r.borrow().clone()` to clone the contents of /// a `RefCell`. #[stable(feature = "cell_extras", since = "1.15.0")] + #[must_use] #[inline] pub fn clone(orig: &Ref<'b, T>) -> Ref<'b, T> { Ref { value: orig.value, borrow: orig.borrow.clone() } @@ -1976,7 +1984,8 @@ impl Default for UnsafeCell { } #[stable(feature = "cell_from", since = "1.12.0")] -impl From for UnsafeCell { +#[rustc_const_unstable(feature = "const_convert", issue = "88674")] +impl const From for UnsafeCell { fn from(t: T) -> UnsafeCell { UnsafeCell::new(t) } diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs index 72921414fb..c4046d7496 100644 --- a/library/core/src/char/convert.rs +++ b/library/core/src/char/convert.rs @@ -51,8 +51,13 @@ use super::MAX; #[must_use] #[inline] #[stable(feature = "rust1", since = "1.0.0")] -pub fn from_u32(i: u32) -> Option { - char::try_from(i).ok() +#[rustc_const_unstable(feature = "const_char_convert", issue = "89259")] +pub const fn from_u32(i: u32) -> Option { + // FIXME: once Result::ok is const fn, use it here + match char_try_from_u32(i) { + Ok(c) => Some(c), + Err(_) => None, + } } /// Converts a `u32` to a `char`, ignoring validity. @@ -91,13 +96,15 @@ pub fn from_u32(i: u32) -> Option { #[inline] #[must_use] #[stable(feature = "char_from_unchecked", since = "1.5.0")] -pub unsafe fn from_u32_unchecked(i: u32) -> char { +#[rustc_const_unstable(feature = "const_char_convert", issue = "89259")] +pub const unsafe fn from_u32_unchecked(i: u32) -> char { // SAFETY: the caller must guarantee that `i` is a valid char value. if cfg!(debug_assertions) { char::from_u32(i).unwrap() } else { unsafe { transmute(i) } } } #[stable(feature = "char_convert", since = "1.13.0")] -impl From for u32 { +#[rustc_const_unstable(feature = "const_convert", issue = "88674")] +impl const From for u32 { /// Converts a [`char`] into a [`u32`]. /// /// # Examples @@ -116,7 +123,8 @@ impl From for u32 { } #[stable(feature = "more_char_conversions", since = "1.51.0")] -impl From for u64 { +#[rustc_const_unstable(feature = "const_convert", issue = "88674")] +impl const From for u64 { /// Converts a [`char`] into a [`u64`]. /// /// # Examples @@ -137,7 +145,8 @@ impl From for u64 { } #[stable(feature = "more_char_conversions", since = "1.51.0")] -impl From for u128 { +#[rustc_const_unstable(feature = "const_convert", issue = "88674")] +impl const From for u128 { /// Converts a [`char`] into a [`u128`]. /// /// # Examples @@ -176,7 +185,8 @@ impl From for u128 { /// for a superset of Windows-1252 that fills the remaining blanks with corresponding /// C0 and C1 control codes. #[stable(feature = "char_convert", since = "1.13.0")] -impl From for char { +#[rustc_const_unstable(feature = "const_convert", issue = "88674")] +impl const From for char { /// Converts a [`u8`] into a [`char`]. /// /// # Examples @@ -244,18 +254,23 @@ impl FromStr for char { } } +#[inline] +const fn char_try_from_u32(i: u32) -> Result { + if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) { + Err(CharTryFromError(())) + } else { + // SAFETY: checked that it's a legal unicode value + Ok(unsafe { transmute(i) }) + } +} + #[stable(feature = "try_from", since = "1.34.0")] impl TryFrom for char { type Error = CharTryFromError; #[inline] fn try_from(i: u32) -> Result { - if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) { - Err(CharTryFromError(())) - } else { - // SAFETY: checked that it's a legal unicode value - Ok(unsafe { transmute(i) }) - } + char_try_from_u32(i) } } @@ -323,7 +338,8 @@ impl fmt::Display for CharTryFromError { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] -pub fn from_digit(num: u32, radix: u32) -> Option { +#[rustc_const_unstable(feature = "const_char_convert", issue = "89259")] +pub const fn from_digit(num: u32, radix: u32) -> Option { if radix > 36 { panic!("from_digit: radix is too high (maximum 36)"); } diff --git a/library/core/src/char/decode.rs b/library/core/src/char/decode.rs index 4784418f98..5dd8c5ef78 100644 --- a/library/core/src/char/decode.rs +++ b/library/core/src/char/decode.rs @@ -128,6 +128,7 @@ impl> Iterator for DecodeUtf16 { impl DecodeUtf16Error { /// Returns the unpaired surrogate which caused this error. + #[must_use] #[stable(feature = "decode_utf16", since = "1.9.0")] pub fn unpaired_surrogate(&self) -> u16 { self.code diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 3c4972bd3c..7250dca2ad 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -136,9 +136,10 @@ impl char { /// assert_eq!(None, c); /// ``` #[stable(feature = "assoc_char_funcs", since = "1.52.0")] + #[rustc_const_unstable(feature = "const_char_convert", issue = "89259")] #[must_use] #[inline] - pub fn from_u32(i: u32) -> Option { + pub const fn from_u32(i: u32) -> Option { super::convert::from_u32(i) } @@ -178,9 +179,10 @@ impl char { /// assert_eq!('❤', c); /// ``` #[stable(feature = "assoc_char_funcs", since = "1.52.0")] + #[rustc_const_unstable(feature = "const_char_convert", issue = "89259")] #[must_use] #[inline] - pub unsafe fn from_u32_unchecked(i: u32) -> char { + pub const unsafe fn from_u32_unchecked(i: u32) -> char { // SAFETY: the safety contract must be upheld by the caller. unsafe { super::convert::from_u32_unchecked(i) } } @@ -235,9 +237,10 @@ impl char { /// let _c = char::from_digit(1, 37); /// ``` #[stable(feature = "assoc_char_funcs", since = "1.52.0")] + #[rustc_const_unstable(feature = "const_char_convert", issue = "89259")] #[must_use] #[inline] - pub fn from_digit(num: u32, radix: u32) -> Option { + pub const fn from_digit(num: u32, radix: u32) -> Option { super::convert::from_digit(num, radix) } @@ -331,10 +334,11 @@ impl char { /// let _ = '1'.to_digit(37); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_char_convert", issue = "89259")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn to_digit(self, radix: u32) -> Option { + pub const fn to_digit(self, radix: u32) -> Option { assert!(radix <= 36, "to_digit: radix is too high (maximum 36)"); // If not a digit, a number greater than radix will be created. let mut digit = (self as u32).wrapping_sub('0' as u32); @@ -345,7 +349,8 @@ impl char { // Force the 6th bit to be set to ensure ascii is lower case. digit = (self as u32 | 0b10_0000).wrapping_sub('a' as u32).saturating_add(10); } - (digit < radix).then_some(digit) + // FIXME: once then_some is const fn, use it here + if digit < radix { Some(digit) } else { None } } /// Returns an iterator that yields the hexadecimal Unicode escape of a @@ -1245,7 +1250,7 @@ impl char { /// let percent = '%'; /// let space = ' '; /// let lf = '\n'; - /// let esc: char = 0x1b_u8.into(); + /// let esc = '\x1b'; /// /// assert!(uppercase_a.is_ascii_alphabetic()); /// assert!(uppercase_g.is_ascii_alphabetic()); @@ -1279,7 +1284,7 @@ impl char { /// let percent = '%'; /// let space = ' '; /// let lf = '\n'; - /// let esc: char = 0x1b_u8.into(); + /// let esc = '\x1b'; /// /// assert!(uppercase_a.is_ascii_uppercase()); /// assert!(uppercase_g.is_ascii_uppercase()); @@ -1313,7 +1318,7 @@ impl char { /// let percent = '%'; /// let space = ' '; /// let lf = '\n'; - /// let esc: char = 0x1b_u8.into(); + /// let esc = '\x1b'; /// /// assert!(!uppercase_a.is_ascii_lowercase()); /// assert!(!uppercase_g.is_ascii_lowercase()); @@ -1350,7 +1355,7 @@ impl char { /// let percent = '%'; /// let space = ' '; /// let lf = '\n'; - /// let esc: char = 0x1b_u8.into(); + /// let esc = '\x1b'; /// /// assert!(uppercase_a.is_ascii_alphanumeric()); /// assert!(uppercase_g.is_ascii_alphanumeric()); @@ -1384,7 +1389,7 @@ impl char { /// let percent = '%'; /// let space = ' '; /// let lf = '\n'; - /// let esc: char = 0x1b_u8.into(); + /// let esc = '\x1b'; /// /// assert!(!uppercase_a.is_ascii_digit()); /// assert!(!uppercase_g.is_ascii_digit()); @@ -1421,7 +1426,7 @@ impl char { /// let percent = '%'; /// let space = ' '; /// let lf = '\n'; - /// let esc: char = 0x1b_u8.into(); + /// let esc = '\x1b'; /// /// assert!(uppercase_a.is_ascii_hexdigit()); /// assert!(!uppercase_g.is_ascii_hexdigit()); @@ -1459,7 +1464,7 @@ impl char { /// let percent = '%'; /// let space = ' '; /// let lf = '\n'; - /// let esc: char = 0x1b_u8.into(); + /// let esc = '\x1b'; /// /// assert!(!uppercase_a.is_ascii_punctuation()); /// assert!(!uppercase_g.is_ascii_punctuation()); @@ -1493,7 +1498,7 @@ impl char { /// let percent = '%'; /// let space = ' '; /// let lf = '\n'; - /// let esc: char = 0x1b_u8.into(); + /// let esc = '\x1b'; /// /// assert!(uppercase_a.is_ascii_graphic()); /// assert!(uppercase_g.is_ascii_graphic()); @@ -1544,7 +1549,7 @@ impl char { /// let percent = '%'; /// let space = ' '; /// let lf = '\n'; - /// let esc: char = 0x1b_u8.into(); + /// let esc = '\x1b'; /// /// assert!(!uppercase_a.is_ascii_whitespace()); /// assert!(!uppercase_g.is_ascii_whitespace()); @@ -1580,7 +1585,7 @@ impl char { /// let percent = '%'; /// let space = ' '; /// let lf = '\n'; - /// let esc: char = 0x1b_u8.into(); + /// let esc = '\x1b'; /// /// assert!(!uppercase_a.is_ascii_control()); /// assert!(!uppercase_g.is_ascii_control()); diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index b02333b028..6f9579043c 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -93,7 +93,6 @@ /// /// * Function item types (i.e., the distinct types defined for each function) /// * Function pointer types (e.g., `fn() -> i32`) -/// * Array types, for all sizes, if the item type also implements `Clone` (e.g., `[i32; 123456]`) /// * Tuple types, if each component also implements `Clone` (e.g., `()`, `(i32, bool)`) /// * Closure types, if they capture no value from the environment /// or if all such captured values implement `Clone` themselves. @@ -105,7 +104,7 @@ #[stable(feature = "rust1", since = "1.0.0")] #[lang = "clone"] #[rustc_diagnostic_item = "Clone"] -#[cfg_attr(not(bootstrap), rustc_trivial_field_reads)] +#[rustc_trivial_field_reads] pub trait Clone: Sized { /// Returns a copy of the value. /// diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index fb8305273a..5aa53deee3 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -545,7 +545,8 @@ where // From (and thus Into) is reflexive #[stable(feature = "rust1", since = "1.0.0")] -impl From for T { +#[rustc_const_unstable(feature = "const_convert", issue = "88674")] +impl const From for T { fn from(t: T) -> T { t } @@ -560,7 +561,8 @@ impl From for T { #[allow(unused_attributes)] // FIXME(#58633): do a principled fix instead. #[rustc_reservation_impl = "permitting this impl would forbid us from adding \ `impl From for T` later; see rust-lang/rust#64715 for details"] -impl From for T { +#[rustc_const_unstable(feature = "const_convert", issue = "88674")] +impl const From for T { fn from(t: !) -> T { t } @@ -726,7 +728,8 @@ impl Ord for Infallible { } #[stable(feature = "convert_infallible", since = "1.34.0")] -impl From for Infallible { +#[rustc_const_unstable(feature = "const_convert", issue = "88674")] +impl const From for Infallible { fn from(x: !) -> Self { x } diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs index 75ef873abc..2b6ea90bf0 100644 --- a/library/core/src/convert/num.rs +++ b/library/core/src/convert/num.rs @@ -390,7 +390,8 @@ use crate::num::NonZeroUsize; macro_rules! nzint_impl_from { ($Small: ty, $Large: ty, #[$attr:meta], $doc: expr) => { #[$attr] - impl From<$Small> for $Large { + #[rustc_const_unstable(feature = "const_num_from_num", issue = "87852")] + impl const From<$Small> for $Large { // Rustdocs on the impl block show a "[+] show undocumented items" toggle. // Rustdocs on functions do not. #[doc = $doc] @@ -398,7 +399,7 @@ macro_rules! nzint_impl_from { fn from(small: $Small) -> Self { // SAFETY: input type guarantees the value is non-zero unsafe { - Self::new_unchecked(small.get().into()) + Self::new_unchecked(From::from(small.get())) } } } diff --git a/library/core/src/default.rs b/library/core/src/default.rs index 0ee8cd59ba..fb862f7df9 100644 --- a/library/core/src/default.rs +++ b/library/core/src/default.rs @@ -155,6 +155,7 @@ pub trait Default: Sized { /// } /// ``` #[unstable(feature = "default_free_fn", issue = "73014")] +#[must_use] #[inline] pub fn default() -> T { Default::default() diff --git a/library/core/src/ffi.rs b/library/core/src/ffi.rs index b208ddd4b2..9c4cf89b6b 100644 --- a/library/core/src/ffi.rs +++ b/library/core/src/ffi.rs @@ -62,7 +62,7 @@ impl fmt::Debug for c_void { #[cfg(any( all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")), all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")), - target_arch = "wasm32", + target_family = "wasm", target_arch = "asmjs", windows ))] @@ -85,7 +85,7 @@ pub struct VaListImpl<'f> { #[cfg(any( all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")), all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")), - target_arch = "wasm32", + target_family = "wasm", target_arch = "asmjs", windows ))] @@ -185,7 +185,7 @@ pub struct VaList<'a, 'f: 'a> { not(target_arch = "x86_64") ), all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")), - target_arch = "wasm32", + target_family = "wasm", target_arch = "asmjs", windows ))] @@ -194,7 +194,7 @@ pub struct VaList<'a, 'f: 'a> { #[cfg(all( any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"), any(not(target_arch = "aarch64"), not(any(target_os = "macos", target_os = "ios"))), - not(target_arch = "wasm32"), + not(target_family = "wasm"), not(target_arch = "asmjs"), not(windows) ))] @@ -206,7 +206,7 @@ pub struct VaList<'a, 'f: 'a> { #[cfg(any( all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")), all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")), - target_arch = "wasm32", + target_family = "wasm", target_arch = "asmjs", windows ))] @@ -227,7 +227,7 @@ impl<'f> VaListImpl<'f> { #[cfg(all( any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"), any(not(target_arch = "aarch64"), not(any(target_os = "macos", target_os = "ios"))), - not(target_arch = "wasm32"), + not(target_family = "wasm"), not(target_arch = "asmjs"), not(windows) ))] diff --git a/library/core/src/fmt/float.rs b/library/core/src/fmt/float.rs index ba65f0fadb..89d5fac30d 100644 --- a/library/core/src/fmt/float.rs +++ b/library/core/src/fmt/float.rs @@ -3,6 +3,26 @@ use crate::mem::MaybeUninit; use crate::num::flt2dec; use crate::num::fmt as numfmt; +#[doc(hidden)] +trait GeneralFormat: PartialOrd { + /// Determines if a value should use exponential based on its magnitude, given the precondition + /// that it will not be rounded any further before it is displayed. + fn already_rounded_value_should_use_exponential(&self) -> bool; +} + +macro_rules! impl_general_format { + ($($t:ident)*) => { + $(impl GeneralFormat for $t { + fn already_rounded_value_should_use_exponential(&self) -> bool { + let abs = $t::abs_private(*self); + (abs != 0.0 && abs < 1e-4) || abs >= 1e+16 + } + })* + } +} + +impl_general_format! { f32 f64 } + // Don't inline this so callers don't use the stack space this function // requires unless they have to. #[inline(never)] @@ -54,8 +74,7 @@ where fmt.pad_formatted_parts(&formatted) } -// Common code of floating point Debug and Display. -fn float_to_decimal_common(fmt: &mut Formatter<'_>, num: &T, min_precision: usize) -> Result +fn float_to_decimal_display(fmt: &mut Formatter<'_>, num: &T) -> Result where T: flt2dec::DecodableFloat, { @@ -68,6 +87,7 @@ where if let Some(precision) = fmt.precision { float_to_decimal_common_exact(fmt, num, sign, precision) } else { + let min_precision = 0; float_to_decimal_common_shortest(fmt, num, sign, min_precision) } } @@ -145,19 +165,44 @@ where } } +fn float_to_general_debug(fmt: &mut Formatter<'_>, num: &T) -> Result +where + T: flt2dec::DecodableFloat + GeneralFormat, +{ + let force_sign = fmt.sign_plus(); + let sign = match force_sign { + false => flt2dec::Sign::Minus, + true => flt2dec::Sign::MinusPlus, + }; + + if let Some(precision) = fmt.precision { + // this behavior of {:.PREC?} predates exponential formatting for {:?} + float_to_decimal_common_exact(fmt, num, sign, precision) + } else { + // since there is no precision, there will be no rounding + if num.already_rounded_value_should_use_exponential() { + let upper = false; + float_to_exponential_common_shortest(fmt, num, sign, upper) + } else { + let min_precision = 1; + float_to_decimal_common_shortest(fmt, num, sign, min_precision) + } + } +} + macro_rules! floating { ($ty:ident) => { #[stable(feature = "rust1", since = "1.0.0")] impl Debug for $ty { fn fmt(&self, fmt: &mut Formatter<'_>) -> Result { - float_to_decimal_common(fmt, self, 1) + float_to_general_debug(fmt, self) } } #[stable(feature = "rust1", since = "1.0.0")] impl Display for $ty { fn fmt(&self, fmt: &mut Formatter<'_>) -> Result { - float_to_decimal_common(fmt, self, 0) + float_to_decimal_display(fmt, self) } } diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index b8ad7720e0..80d3270d73 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -374,7 +374,6 @@ impl<'a> Arguments<'a> { /// valid index of `args`. /// 3. Every [`Count::Param`] within `fmt` must contain a valid index of /// `args`. - #[cfg(not(bootstrap))] #[doc(hidden)] #[inline] #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] @@ -388,19 +387,6 @@ impl<'a> Arguments<'a> { Arguments { pieces, fmt: Some(fmt), args } } - #[cfg(bootstrap)] - #[doc(hidden)] - #[inline] - #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] - #[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")] - pub const unsafe fn new_v1_formatted( - pieces: &'a [&'static str], - args: &'a [ArgumentV1<'a>], - fmt: &'a [rt::v1::Argument], - ) -> Arguments<'a> { - Arguments { pieces, fmt: Some(fmt), args } - } - /// Estimates the length of the formatted text. /// /// This is intended to be used for setting initial `String` capacity @@ -619,7 +605,7 @@ impl Display for Arguments<'_> { )] #[doc(alias = "{:?}")] #[rustc_diagnostic_item = "Debug"] -#[cfg_attr(not(bootstrap), rustc_trivial_field_reads)] +#[rustc_trivial_field_reads] pub trait Debug { /// Formats the value using the given formatter. /// @@ -1618,6 +1604,7 @@ impl<'a> Formatter<'a> { } /// Flags for formatting + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated( since = "1.24.0", @@ -1655,6 +1642,7 @@ impl<'a> Formatter<'a> { /// assert_eq!(&format!("{:G>3}", Foo), "GGG"); /// assert_eq!(&format!("{:t>6}", Foo), "tttttt"); /// ``` + #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn fill(&self) -> char { self.fill @@ -1691,6 +1679,7 @@ impl<'a> Formatter<'a> { /// assert_eq!(&format!("{:^}", Foo), "center"); /// assert_eq!(&format!("{}", Foo), "into the void"); /// ``` + #[must_use] #[stable(feature = "fmt_flags_align", since = "1.28.0")] pub fn align(&self) -> Option { match self.align { @@ -1725,6 +1714,7 @@ impl<'a> Formatter<'a> { /// assert_eq!(&format!("{:10}", Foo(23)), "Foo(23) "); /// assert_eq!(&format!("{}", Foo(23)), "Foo(23)"); /// ``` + #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn width(&self) -> Option { self.width @@ -1755,6 +1745,7 @@ impl<'a> Formatter<'a> { /// assert_eq!(&format!("{:.4}", Foo(23.2)), "Foo(23.2000)"); /// assert_eq!(&format!("{}", Foo(23.2)), "Foo(23.20)"); /// ``` + #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn precision(&self) -> Option { self.precision @@ -1785,6 +1776,7 @@ impl<'a> Formatter<'a> { /// assert_eq!(&format!("{:+}", Foo(23)), "Foo(+23)"); /// assert_eq!(&format!("{}", Foo(23)), "Foo(23)"); /// ``` + #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn sign_plus(&self) -> bool { self.flags & (1 << FlagV1::SignPlus as u32) != 0 @@ -1813,6 +1805,7 @@ impl<'a> Formatter<'a> { /// assert_eq!(&format!("{:-}", Foo(23)), "-Foo(23)"); /// assert_eq!(&format!("{}", Foo(23)), "Foo(23)"); /// ``` + #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn sign_minus(&self) -> bool { self.flags & (1 << FlagV1::SignMinus as u32) != 0 @@ -1840,6 +1833,7 @@ impl<'a> Formatter<'a> { /// assert_eq!(&format!("{:#}", Foo(23)), "Foo(23)"); /// assert_eq!(&format!("{}", Foo(23)), "23"); /// ``` + #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn alternate(&self) -> bool { self.flags & (1 << FlagV1::Alternate as u32) != 0 @@ -1865,6 +1859,7 @@ impl<'a> Formatter<'a> { /// /// assert_eq!(&format!("{:04}", Foo(23)), "23"); /// ``` + #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn sign_aware_zero_pad(&self) -> bool { self.flags & (1 << FlagV1::SignAwareZeroPad as u32) != 0 diff --git a/library/core/src/future/mod.rs b/library/core/src/future/mod.rs index cdde094147..7a3af70d6d 100644 --- a/library/core/src/future/mod.rs +++ b/library/core/src/future/mod.rs @@ -90,6 +90,7 @@ where #[lang = "get_context"] #[doc(hidden)] #[unstable(feature = "gen_future", issue = "50547")] +#[must_use] #[inline] pub unsafe fn get_context<'a, 'b>(cx: ResumeTy) -> &'a mut Context<'b> { // SAFETY: the caller must guarantee that `cx.0` is a valid pointer diff --git a/library/core/src/internal_macros.rs b/library/core/src/internal_macros.rs index be12f90464..9c6acfb1e8 100644 --- a/library/core/src/internal_macros.rs +++ b/library/core/src/internal_macros.rs @@ -5,6 +5,23 @@ macro_rules! forward_ref_unop { forward_ref_unop!(impl $imp, $method for $t, #[stable(feature = "rust1", since = "1.0.0")]); }; + (impl const $imp:ident, $method:ident for $t:ty) => { + forward_ref_unop!(impl const $imp, $method for $t, + #[stable(feature = "rust1", since = "1.0.0")]); + }; + // Equivalent to the non-const version, with the addition of `rustc_const_unstable` + (impl const $imp:ident, $method:ident for $t:ty, #[$attr:meta]) => { + #[$attr] + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const $imp for &$t { + type Output = <$t as $imp>::Output; + + #[inline] + fn $method(self) -> <$t as $imp>::Output { + $imp::$method(*self) + } + } + }; (impl $imp:ident, $method:ident for $t:ty, #[$attr:meta]) => { #[$attr] impl $imp for &$t { @@ -25,6 +42,45 @@ macro_rules! forward_ref_binop { forward_ref_binop!(impl $imp, $method for $t, $u, #[stable(feature = "rust1", since = "1.0.0")]); }; + (impl const $imp:ident, $method:ident for $t:ty, $u:ty) => { + forward_ref_binop!(impl const $imp, $method for $t, $u, + #[stable(feature = "rust1", since = "1.0.0")]); + }; + // Equivalent to the non-const version, with the addition of `rustc_const_unstable` + (impl const $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => { + #[$attr] + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl<'a> const $imp<$u> for &'a $t { + type Output = <$t as $imp<$u>>::Output; + + #[inline] + fn $method(self, other: $u) -> <$t as $imp<$u>>::Output { + $imp::$method(*self, other) + } + } + + #[$attr] + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const $imp<&$u> for $t { + type Output = <$t as $imp<$u>>::Output; + + #[inline] + fn $method(self, other: &$u) -> <$t as $imp<$u>>::Output { + $imp::$method(self, *other) + } + } + + #[$attr] + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const $imp<&$u> for &$t { + type Output = <$t as $imp<$u>>::Output; + + #[inline] + fn $method(self, other: &$u) -> <$t as $imp<$u>>::Output { + $imp::$method(*self, *other) + } + } + }; (impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => { #[$attr] impl<'a> $imp<$u> for &'a $t { @@ -65,6 +121,21 @@ macro_rules! forward_ref_op_assign { forward_ref_op_assign!(impl $imp, $method for $t, $u, #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]); }; + (impl const $imp:ident, $method:ident for $t:ty, $u:ty) => { + forward_ref_op_assign!(impl const $imp, $method for $t, $u, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]); + }; + // Equivalent to the non-const version, with the addition of `rustc_const_unstable` + (impl const $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => { + #[$attr] + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const $imp<&$u> for $t { + #[inline] + fn $method(&mut self, other: &$u) { + $imp::$method(self, *other); + } + } + }; (impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => { #[$attr] impl $imp<&$u> for $t { diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 1aeb83931e..0f57fb5b14 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1951,6 +1951,19 @@ pub(crate) fn is_aligned_and_not_null(ptr: *const T) -> bool { !ptr.is_null() && ptr as usize % mem::align_of::() == 0 } +/// Checks whether the regions of memory starting at `src` and `dst` of size +/// `count * size_of::()` do *not* overlap. +#[cfg(debug_assertions)] +pub(crate) fn is_nonoverlapping(src: *const T, dst: *const T, count: usize) -> bool { + let src_usize = src as usize; + let dst_usize = dst as usize; + let size = mem::size_of::().checked_mul(count).unwrap(); + let diff = if src_usize > dst_usize { src_usize - dst_usize } else { dst_usize - src_usize }; + // If the absolute distance between the ptrs is at least as big as the size of the buffer, + // they do not overlap. + diff >= size +} + /// Copies `count * size_of::()` bytes from `src` to `dst`. The source /// and destination must *not* overlap. /// @@ -2042,15 +2055,24 @@ pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: us pub fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); } - // FIXME: Perform these checks only at run time - /*if cfg!(debug_assertions) - && !(is_aligned_and_not_null(src) - && is_aligned_and_not_null(dst) - && is_nonoverlapping(src, dst, count)) - { - // Not panicking to keep codegen impact smaller. - abort(); - }*/ + #[cfg(debug_assertions)] + fn runtime_check(src: *const T, dst: *mut T, count: usize) { + if !is_aligned_and_not_null(src) + || !is_aligned_and_not_null(dst) + || !is_nonoverlapping(src, dst, count) + { + // Not panicking to keep codegen impact smaller. + abort(); + } + } + #[cfg(debug_assertions)] + const fn compiletime_check(_src: *const T, _dst: *mut T, _count: usize) {} + #[cfg(debug_assertions)] + // SAFETY: runtime debug-assertions are a best-effort basis; it's fine to + // not do them during compile time + unsafe { + const_eval_select((src, dst, count), compiletime_check, runtime_check); + } // SAFETY: the safety contract for `copy_nonoverlapping` must be // upheld by the caller. @@ -2127,11 +2149,21 @@ pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { fn copy(src: *const T, dst: *mut T, count: usize); } - // FIXME: Perform these checks only at run time - /*if cfg!(debug_assertions) && !(is_aligned_and_not_null(src) && is_aligned_and_not_null(dst)) { - // Not panicking to keep codegen impact smaller. - abort(); - }*/ + #[cfg(debug_assertions)] + fn runtime_check(src: *const T, dst: *mut T) { + if !is_aligned_and_not_null(src) || !is_aligned_and_not_null(dst) { + // Not panicking to keep codegen impact smaller. + abort(); + } + } + #[cfg(debug_assertions)] + const fn compiletime_check(_src: *const T, _dst: *mut T) {} + #[cfg(debug_assertions)] + // SAFETY: runtime debug-assertions are a best-effort basis; it's fine to + // not do them during compile time + unsafe { + const_eval_select((src, dst), compiletime_check, runtime_check); + } // SAFETY: the safety contract for `copy` must be upheld by the caller. unsafe { copy(src, dst, count) } @@ -2252,7 +2284,6 @@ pub unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { /// or have any other observable side-effects, the behavior is undefined. /// /// [referential transparency]: https://en.wikipedia.org/wiki/Referential_transparency -#[cfg(not(bootstrap))] #[unstable( feature = "const_eval_select", issue = "none", @@ -2273,7 +2304,6 @@ where called_at_rt.call_once(arg) } -#[cfg(not(bootstrap))] #[unstable( feature = "const_eval_select", issue = "none", diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs index 2b7287a413..4b89bc3632 100644 --- a/library/core/src/iter/adapters/zip.rs +++ b/library/core/src/iter/adapters/zip.rs @@ -427,13 +427,9 @@ where } } +// Since SourceIter forwards the left hand side we do the same here #[unstable(issue = "none", feature = "inplace_iteration")] -// Limited to Item: Copy since interaction between Zip's use of TrustedRandomAccess -// and Drop implementation of the source is unclear. -// -// An additional method returning the number of times the source has been logically advanced -// (without calling next()) would be needed to properly drop the remainder of the source. -unsafe impl InPlaceIterable for Zip where A::Item: Copy {} +unsafe impl InPlaceIterable for Zip {} #[stable(feature = "rust1", since = "1.0.0")] impl Debug for Zip { diff --git a/library/core/src/iter/sources/empty.rs b/library/core/src/iter/sources/empty.rs index a7d4646f5c..7abe01d17c 100644 --- a/library/core/src/iter/sources/empty.rs +++ b/library/core/src/iter/sources/empty.rs @@ -25,6 +25,7 @@ pub const fn empty() -> Empty { /// An iterator that yields nothing. /// /// This `struct` is created by the [`empty()`] function. See its documentation for more. +#[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "iter_empty", since = "1.2.0")] pub struct Empty(marker::PhantomData); diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index f53d6cac7e..d957a7527c 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -2837,12 +2837,12 @@ pub trait Iterator { /// Basic usage: /// /// ``` - /// let a = [(1, 2), (3, 4)]; + /// let a = [(1, 2), (3, 4), (5, 6)]; /// /// let (left, right): (Vec<_>, Vec<_>) = a.iter().cloned().unzip(); /// - /// assert_eq!(left, [1, 3]); - /// assert_eq!(right, [2, 4]); + /// assert_eq!(left, [1, 3, 5]); + /// assert_eq!(right, [2, 4, 6]); /// /// // you can also unzip multiple nested tuples at once /// let a = [(1, (2, 3)), (4, (5, 6))]; diff --git a/library/core/src/lazy.rs b/library/core/src/lazy.rs index d109141216..2b8a5f3cbf 100644 --- a/library/core/src/lazy.rs +++ b/library/core/src/lazy.rs @@ -74,7 +74,7 @@ impl PartialEq for OnceCell { impl Eq for OnceCell {} #[unstable(feature = "once_cell", issue = "74465")] -impl From for OnceCell { +impl const From for OnceCell { fn from(value: T) -> Self { OnceCell { inner: UnsafeCell::new(Some(value)) } } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 13b80c05db..cb2854bc5f 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -97,6 +97,7 @@ #![allow(explicit_outlives_requirements)] // // Library features for const fns: +#![feature(const_align_offset)] #![feature(const_align_of_val)] #![feature(const_alloc_layout)] #![feature(const_arguments_as_str)] @@ -104,9 +105,12 @@ #![feature(const_bigint_helper_methods)] #![feature(const_caller_location)] #![feature(const_cell_into_inner)] +#![feature(const_char_convert)] #![feature(const_discriminant)] +#![feature(const_eval_select)] #![feature(const_float_bits_conv)] #![feature(const_float_classify)] +#![feature(const_fmt_arguments_new)] #![feature(const_heap)] #![feature(const_inherent_unchecked_arith)] #![feature(const_int_unchecked_arith)] @@ -115,6 +119,8 @@ #![feature(const_likely)] #![feature(const_maybe_uninit_as_ptr)] #![feature(const_maybe_uninit_assume_init)] +#![feature(const_num_from_num)] +#![feature(const_ops)] #![feature(const_option)] #![feature(const_pin)] #![feature(const_replace)] @@ -126,15 +132,19 @@ #![feature(const_size_of_val)] #![feature(const_slice_from_raw_parts)] #![feature(const_slice_ptr_len)] +#![feature(const_str_from_utf8_unchecked_mut)] #![feature(const_swap)] #![feature(const_trait_impl)] #![feature(const_type_id)] #![feature(const_type_name)] #![feature(const_default_impls)] -#![feature(duration_consts_2)] +#![feature(duration_consts_float)] #![feature(ptr_metadata)] #![feature(slice_ptr_get)] +#![feature(str_internals)] #![feature(variant_count)] +#![feature(const_array_from_ref)] +#![feature(const_slice_from_ref)] // // Language features: #![feature(abi_unadjusted)] @@ -149,16 +159,17 @@ #![feature(const_fn_trait_bound)] #![feature(const_impl_trait)] #![feature(const_mut_refs)] -#![cfg_attr(bootstrap, feature(const_panic))] #![feature(const_precise_live_drops)] -#![feature(const_raw_ptr_deref)] +#![cfg_attr(bootstrap, feature(const_raw_ptr_deref))] #![feature(const_refs_to_cell)] #![feature(decl_macro)] +#![feature(derive_default_enum)] #![feature(doc_cfg)] #![feature(doc_notable_trait)] -#![feature(doc_primitive)] +#![cfg_attr(bootstrap, feature(doc_primitive))] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] #![feature(exhaustive_patterns)] -#![cfg_attr(not(bootstrap), feature(doc_cfg_hide))] +#![feature(doc_cfg_hide)] #![feature(extern_types)] #![feature(fundamental)] #![feature(if_let_guard)] @@ -169,7 +180,7 @@ #![feature(llvm_asm)] #![feature(min_specialization)] #![feature(mixed_integer_ops)] -#![cfg_attr(not(bootstrap), feature(must_not_suspend))] +#![feature(must_not_suspend)] #![feature(negative_impls)] #![feature(never_type)] #![feature(no_core)] @@ -188,6 +199,7 @@ #![feature(try_blocks)] #![feature(unboxed_closures)] #![feature(unsized_fn_params)] +#![cfg_attr(not(bootstrap), feature(asm_const))] // // Target features: #![feature(aarch64_target_feature)] diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 5b3e988caa..993ae72322 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -554,7 +554,10 @@ macro_rules! writeln { /// /// # Panics /// -/// This will always [`panic!`]. +/// This will always [`panic!`] because `unreachable!` is just a shorthand for `panic!` with a +/// fixed, specific message. +/// +/// Like `panic!`, this macro has a second form for displaying custom values. /// /// # Examples /// @@ -581,7 +584,7 @@ macro_rules! writeln { /// if 3*i < i { panic!("u32 overflow"); } /// if x < 3*i { return i-1; } /// } -/// unreachable!(); +/// unreachable!("The loop should always return"); /// } /// ``` #[macro_export] diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index e5c3fafe5f..71eea43aa5 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -30,8 +30,7 @@ use crate::hash::Hasher; /// [arc]: ../../std/sync/struct.Arc.html /// [ub]: ../../reference/behavior-considered-undefined.html #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(all(not(test), bootstrap), rustc_diagnostic_item = "send_trait")] -#[cfg_attr(all(not(test), not(bootstrap)), rustc_diagnostic_item = "Send")] +#[cfg_attr(not(test), rustc_diagnostic_item = "Send")] #[rustc_on_unimplemented( message = "`{Self}` cannot be sent between threads safely", label = "`{Self}` cannot be sent between threads safely" @@ -360,7 +359,6 @@ pub trait StructuralEq { /// /// * Function item types (i.e., the distinct types defined for each function) /// * Function pointer types (e.g., `fn() -> i32`) -/// * Array types, for all sizes, if the item type also implements `Copy` (e.g., `[i32; 123456]`) /// * Tuple types, if each component also implements `Copy` (e.g., `()`, `(i32, bool)`) /// * Closure types, if they capture no value from the environment /// or if all such captured values implement `Copy` themselves. diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 894ae10e1b..7d005666a7 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -296,6 +296,7 @@ pub fn forget_unsized(t: T) { /// /// [alignment]: align_of #[inline(always)] +#[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] #[rustc_const_stable(feature = "const_size_of", since = "1.24.0")] @@ -324,6 +325,7 @@ pub const fn size_of() -> usize { /// assert_eq!(13, mem::size_of_val(y)); /// ``` #[inline] +#[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_size_of_val", issue = "46571")] #[cfg_attr(not(test), rustc_diagnostic_item = "mem_size_of_val")] @@ -373,6 +375,7 @@ pub const fn size_of_val(val: &T) -> usize { /// assert_eq!(13, unsafe { mem::size_of_val_raw(y) }); /// ``` #[inline] +#[must_use] #[unstable(feature = "layout_for_ptr", issue = "69835")] #[rustc_const_unstable(feature = "const_size_of_val_raw", issue = "46571")] pub const unsafe fn size_of_val_raw(val: *const T) -> usize { @@ -397,6 +400,7 @@ pub const unsafe fn size_of_val_raw(val: *const T) -> usize { /// assert_eq!(4, mem::min_align_of::()); /// ``` #[inline] +#[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated(reason = "use `align_of` instead", since = "1.2.0")] pub fn min_align_of() -> usize { @@ -418,6 +422,7 @@ pub fn min_align_of() -> usize { /// assert_eq!(4, mem::min_align_of_val(&5i32)); /// ``` #[inline] +#[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated(reason = "use `align_of_val` instead", since = "1.2.0")] pub fn min_align_of_val(val: &T) -> usize { @@ -441,6 +446,7 @@ pub fn min_align_of_val(val: &T) -> usize { /// assert_eq!(4, mem::align_of::()); /// ``` #[inline(always)] +#[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] #[rustc_const_stable(feature = "const_align_of", since = "1.24.0")] @@ -462,6 +468,7 @@ pub const fn align_of() -> usize { /// assert_eq!(4, mem::align_of_val(&5i32)); /// ``` #[inline] +#[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_align_of_val", issue = "46571")] #[allow(deprecated)] @@ -507,6 +514,7 @@ pub const fn align_of_val(val: &T) -> usize { /// assert_eq!(4, unsafe { mem::align_of_val_raw(&5i32) }); /// ``` #[inline] +#[must_use] #[unstable(feature = "layout_for_ptr", issue = "69835")] #[rustc_const_unstable(feature = "const_align_of_val_raw", issue = "46571")] pub const unsafe fn align_of_val_raw(val: *const T) -> usize { @@ -571,6 +579,7 @@ pub const unsafe fn align_of_val_raw(val: *const T) -> usize { /// } /// ``` #[inline] +#[must_use] #[stable(feature = "needs_drop", since = "1.21.0")] #[rustc_const_stable(feature = "const_needs_drop", since = "1.36.0")] #[rustc_diagnostic_item = "needs_drop"] @@ -618,6 +627,7 @@ pub const fn needs_drop() -> bool { /// let _y: fn() = unsafe { mem::zeroed() }; // And again! /// ``` #[inline(always)] +#[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated_in_future)] #[allow(deprecated)] @@ -653,6 +663,7 @@ pub unsafe fn zeroed() -> T { /// [assume_init]: MaybeUninit::assume_init /// [inv]: MaybeUninit#initialization-invariant #[inline(always)] +#[must_use] #[rustc_deprecated(since = "1.39.0", reason = "use `mem::MaybeUninit` instead")] #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated_in_future)] @@ -938,6 +949,7 @@ pub fn drop(_x: T) {} /// assert_eq!(foo_array, [10]); /// ``` #[inline] +#[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_transmute_copy", issue = "83165")] pub const unsafe fn transmute_copy(src: &T) -> U { @@ -1051,6 +1063,7 @@ pub const fn discriminant(v: &T) -> Discriminant { /// assert_eq!(mem::variant_count::>(), 2); /// ``` #[inline(always)] +#[must_use] #[unstable(feature = "variant_count", issue = "73662")] #[rustc_const_unstable(feature = "variant_count", issue = "73662")] #[rustc_diagnostic_item = "mem_variant_count"] diff --git a/library/core/src/num/error.rs b/library/core/src/num/error.rs index cdeba9c079..8a9ecbe98d 100644 --- a/library/core/src/num/error.rs +++ b/library/core/src/num/error.rs @@ -29,14 +29,15 @@ impl fmt::Display for TryFromIntError { } #[stable(feature = "try_from", since = "1.34.0")] -impl From for TryFromIntError { +#[rustc_const_unstable(feature = "const_convert", issue = "88674")] +impl const From for TryFromIntError { fn from(x: Infallible) -> TryFromIntError { match x {} } } #[unstable(feature = "never_type", issue = "35121")] -impl From for TryFromIntError { +impl const From for TryFromIntError { fn from(never: !) -> TryFromIntError { // Match rather than coerce to make sure that code like // `From for TryFromIntError` above will keep working @@ -114,6 +115,7 @@ pub enum IntErrorKind { impl ParseIntError { /// Outputs the detailed cause of parsing an integer failing. + #[must_use] #[stable(feature = "int_error_matching", since = "1.55.0")] pub fn kind(&self) -> &IntErrorKind { &self.kind diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index ad8106df19..c4a232ef36 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -449,7 +449,7 @@ impl f32 { // private use internally. #[inline] #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] - const fn abs_private(self) -> f32 { + pub(crate) const fn abs_private(self) -> f32 { f32::from_bits(self.to_bits() & 0x7fff_ffff) } @@ -673,6 +673,9 @@ impl f32 { /// Returns the maximum of the two numbers. /// + /// Follows the IEEE-754 2008 semantics for maxNum, except for handling of signaling NaNs. + /// This matches the behavior of libm’s fmin. + /// /// ``` /// let x = 1.0f32; /// let y = 2.0f32; @@ -689,6 +692,9 @@ impl f32 { /// Returns the minimum of the two numbers. /// + /// Follows the IEEE-754 2008 semantics for minNum, except for handling of signaling NaNs. + /// This matches the behavior of libm’s fmin. + /// /// ``` /// let x = 1.0f32; /// let y = 2.0f32; @@ -703,6 +709,68 @@ impl f32 { intrinsics::minnumf32(self, other) } + /// Returns the maximum of the two numbers, propagating NaNs. + /// + /// This returns NaN when *either* argument is NaN, as opposed to + /// [`f32::max`] which only returns NaN when *both* arguments are NaN. + /// + /// ``` + /// #![feature(float_minimum_maximum)] + /// let x = 1.0f32; + /// let y = 2.0f32; + /// + /// assert_eq!(x.maximum(y), y); + /// assert!(x.maximum(f32::NAN).is_nan()); + /// ``` + /// + /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the greater + /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0. + /// Note that this follows the semantics specified in IEEE 754-2019. + #[unstable(feature = "float_minimum_maximum", issue = "91079")] + #[inline] + pub fn maximum(self, other: f32) -> f32 { + if self > other { + self + } else if other > self { + other + } else if self == other { + if self.is_sign_positive() && other.is_sign_negative() { self } else { other } + } else { + self + other + } + } + + /// Returns the minimum of the two numbers, propagating NaNs. + /// + /// This returns NaN when *either* argument is NaN, as opposed to + /// [`f32::min`] which only returns NaN when *both* arguments are NaN. + /// + /// ``` + /// #![feature(float_minimum_maximum)] + /// let x = 1.0f32; + /// let y = 2.0f32; + /// + /// assert_eq!(x.minimum(y), x); + /// assert!(x.minimum(f32::NAN).is_nan()); + /// ``` + /// + /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the lesser + /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0. + /// Note that this follows the semantics specified in IEEE 754-2019. + #[unstable(feature = "float_minimum_maximum", issue = "91079")] + #[inline] + pub fn minimum(self, other: f32) -> f32 { + if self < other { + self + } else if other < self { + other + } else if self == other { + if self.is_sign_negative() && other.is_sign_positive() { self } else { other } + } else { + self + other + } + } + /// Rounds toward zero and converts to any primitive integer type, /// assuming that the value is finite and fits in that type. /// @@ -980,6 +1048,7 @@ impl f32 { /// # .all(|(a, b)| a.to_bits() == b.to_bits())) /// ``` #[unstable(feature = "total_cmp", issue = "72599")] + #[must_use] #[inline] pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering { let mut left = self.to_bits() as i32; diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 6a48101e04..85ee6aa2cb 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -448,7 +448,7 @@ impl f64 { // private use internally. #[inline] #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] - const fn abs_private(self) -> f64 { + pub(crate) const fn abs_private(self) -> f64 { f64::from_bits(self.to_bits() & 0x7fff_ffff_ffff_ffff) } @@ -689,6 +689,9 @@ impl f64 { /// Returns the maximum of the two numbers. /// + /// Follows the IEEE-754 2008 semantics for maxNum, except for handling of signaling NaNs. + /// This matches the behavior of libm’s fmin. + /// /// ``` /// let x = 1.0_f64; /// let y = 2.0_f64; @@ -705,6 +708,9 @@ impl f64 { /// Returns the minimum of the two numbers. /// + /// Follows the IEEE-754 2008 semantics for minNum, except for handling of signaling NaNs. + /// This matches the behavior of libm’s fmin. + /// /// ``` /// let x = 1.0_f64; /// let y = 2.0_f64; @@ -719,6 +725,68 @@ impl f64 { intrinsics::minnumf64(self, other) } + /// Returns the maximum of the two numbers, propagating NaNs. + /// + /// This returns NaN when *either* argument is NaN, as opposed to + /// [`f64::max`] which only returns NaN when *both* arguments are NaN. + /// + /// ``` + /// #![feature(float_minimum_maximum)] + /// let x = 1.0_f64; + /// let y = 2.0_f64; + /// + /// assert_eq!(x.maximum(y), y); + /// assert!(x.maximum(f64::NAN).is_nan()); + /// ``` + /// + /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the greater + /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0. + /// Note that this follows the semantics specified in IEEE 754-2019. + #[unstable(feature = "float_minimum_maximum", issue = "91079")] + #[inline] + pub fn maximum(self, other: f64) -> f64 { + if self > other { + self + } else if other > self { + other + } else if self == other { + if self.is_sign_positive() && other.is_sign_negative() { self } else { other } + } else { + self + other + } + } + + /// Returns the minimum of the two numbers, propagating NaNs. + /// + /// This returns NaN when *either* argument is NaN, as opposed to + /// [`f64::min`] which only returns NaN when *both* arguments are NaN. + /// + /// ``` + /// #![feature(float_minimum_maximum)] + /// let x = 1.0_f64; + /// let y = 2.0_f64; + /// + /// assert_eq!(x.minimum(y), x); + /// assert!(x.minimum(f64::NAN).is_nan()); + /// ``` + /// + /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the lesser + /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0. + /// Note that this follows the semantics specified in IEEE 754-2019. + #[unstable(feature = "float_minimum_maximum", issue = "91079")] + #[inline] + pub fn minimum(self, other: f64) -> f64 { + if self < other { + self + } else if other < self { + other + } else if self == other { + if self.is_sign_negative() && other.is_sign_positive() { self } else { other } + } else { + self + other + } + } + /// Rounds toward zero and converts to any primitive integer type, /// assuming that the value is finite and fits in that type. /// @@ -996,6 +1064,7 @@ impl f64 { /// # .all(|(a, b)| a.to_bits() == b.to_bits())) /// ``` #[unstable(feature = "total_cmp", issue = "72599")] + #[must_use] #[inline] pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering { let mut left = self.to_bits() as i64; diff --git a/library/core/src/num/fmt.rs b/library/core/src/num/fmt.rs index 8cff266642..578288bda2 100644 --- a/library/core/src/num/fmt.rs +++ b/library/core/src/num/fmt.rs @@ -31,10 +31,8 @@ impl<'a> Part<'a> { } else { 3 } - } else if v < 10_000 { - 4 } else { - 5 + if v < 10_000 { 4 } else { 5 } } } Part::Copy(buf) => buf.len(), diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 0bdc933013..9a668d34b6 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -608,8 +608,7 @@ macro_rules! int_impl { without modifying the original"] #[inline] pub const fn checked_div(self, rhs: Self) -> Option { - // Using `&` helps LLVM see that it is the same check made in division. - if unlikely!(rhs == 0 || ((self == Self::MIN) & (rhs == -1))) { + if unlikely!(rhs == 0 || ((self == Self::MIN) && (rhs == -1))) { None } else { // SAFETY: div by zero and by INT_MIN have been checked above @@ -662,8 +661,7 @@ macro_rules! int_impl { without modifying the original"] #[inline] pub const fn checked_rem(self, rhs: Self) -> Option { - // Using `&` helps LLVM see that it is the same check made in division. - if unlikely!(rhs == 0 || ((self == Self::MIN) & (rhs == -1))) { + if unlikely!(rhs == 0 || ((self == Self::MIN) && (rhs == -1))) { None } else { // SAFETY: div by zero and by INT_MIN have been checked above @@ -1055,8 +1053,6 @@ macro_rules! int_impl { /// Basic usage: /// /// ``` - /// #![feature(saturating_div)] - /// #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".saturating_div(2), 2);")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.saturating_div(-1), ", stringify!($SelfT), "::MIN + 1);")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_div(-1), ", stringify!($SelfT), "::MAX);")] @@ -1064,13 +1060,10 @@ macro_rules! int_impl { /// ``` /// /// ```should_panic - /// #![feature(saturating_div)] - /// #[doc = concat!("let _ = 1", stringify!($SelfT), ".saturating_div(0);")] /// /// ``` - #[unstable(feature = "saturating_div", issue = "87920")] - #[rustc_const_unstable(feature = "saturating_div", issue = "87920")] + #[stable(feature = "saturating_div", since = "1.58.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1518,33 +1511,6 @@ macro_rules! int_impl { (a as Self, b) } - /// Calculates `self + rhs + carry` without the ability to overflow. - /// - /// Performs "ternary addition" which takes in an extra bit to add, and may return an - /// additional bit of overflow. This allows for chaining together multiple additions - /// to create "big integers" which represent larger values. - /// - /// # Examples - /// - /// Basic usage - /// - /// ``` - /// #![feature(bigint_helper_methods)] - #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".carrying_add(2, false), (7, false));")] - #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".carrying_add(2, true), (8, false));")] - #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, false), (", stringify!($SelfT), "::MIN, false));")] - #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, true), (", stringify!($SelfT), "::MIN + 1, false));")] - /// ``` - #[unstable(feature = "bigint_helper_methods", issue = "85532")] - #[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn carrying_add(self, rhs: Self, carry: bool) -> (Self, bool) { - let (sum, carry) = (self as $UnsignedT).carrying_add(rhs as $UnsignedT, carry); - (sum as $SelfT, carry) - } - /// Calculates `self` + `rhs` with an unsigned `rhs` /// /// Returns a tuple of the addition along with a boolean indicating @@ -1596,33 +1562,6 @@ macro_rules! int_impl { (a as Self, b) } - /// Calculates `self - rhs - borrow` without the ability to overflow. - /// - /// Performs "ternary subtraction" which takes in an extra bit to subtract, and may return - /// an additional bit of overflow. This allows for chaining together multiple subtractions - /// to create "big integers" which represent larger values. - /// - /// # Examples - /// - /// Basic usage - /// - /// ``` - /// #![feature(bigint_helper_methods)] - #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".borrowing_sub(2, false), (3, false));")] - #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".borrowing_sub(2, true), (2, false));")] - #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.borrowing_sub(1, false), (", stringify!($SelfT), "::MAX, false));")] - #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.borrowing_sub(1, true), (", stringify!($SelfT), "::MAX - 1, false));")] - /// ``` - #[unstable(feature = "bigint_helper_methods", issue = "85532")] - #[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn borrowing_sub(self, rhs: Self, borrow: bool) -> (Self, bool) { - let (sum, borrow) = (self as $UnsignedT).borrowing_sub(rhs as $UnsignedT, borrow); - (sum as $SelfT, borrow) - } - /// Calculates `self` - `rhs` with an unsigned `rhs` /// /// Returns a tuple of the subtraction along with a boolean indicating diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 18ebf1cbb1..e3eab07b9d 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -94,7 +94,7 @@ depending on the target pointer size. } macro_rules! widening_impl { - ($SelfT:ty, $WideT:ty, $BITS:literal) => { + ($SelfT:ty, $WideT:ty, $BITS:literal, unsigned) => { /// Calculates the complete product `self * rhs` without the possibility to overflow. /// /// This returns the low-order (wrapping) bits and the high-order (overflow) bits @@ -148,6 +148,33 @@ macro_rules! widening_impl { /// assert_eq!(5u32.carrying_mul(2, 10), (20, 0)); /// assert_eq!(1_000_000_000u32.carrying_mul(10, 0), (1410065408, 2)); /// assert_eq!(1_000_000_000u32.carrying_mul(10, 10), (1410065418, 2)); + #[doc = concat!("assert_eq!(", + stringify!($SelfT), "::MAX.carrying_mul(", stringify!($SelfT), "::MAX, ", stringify!($SelfT), "::MAX), ", + "(0, ", stringify!($SelfT), "::MAX));" + )] + /// ``` + /// + /// If `carry` is zero, this is similar to [`overflowing_mul`](Self::overflowing_mul), + /// except that it gives the value of the overflow instead of just whether one happened: + /// + /// ``` + /// #![feature(bigint_helper_methods)] + /// let r = u8::carrying_mul(7, 13, 0); + /// assert_eq!((r.0, r.1 != 0), u8::overflowing_mul(7, 13)); + /// let r = u8::carrying_mul(13, 42, 0); + /// assert_eq!((r.0, r.1 != 0), u8::overflowing_mul(13, 42)); + /// ``` + /// + /// The value of the first field in the returned tuple matches what you'd get + /// by combining the [`wrapping_mul`](Self::wrapping_mul) and + /// [`wrapping_add`](Self::wrapping_add) methods: + /// + /// ``` + /// #![feature(bigint_helper_methods)] + /// assert_eq!( + /// 789_u16.carrying_mul(456, 123).0, + /// 789_u16.wrapping_mul(456).wrapping_add(123), + /// ); /// ``` #[unstable(feature = "bigint_helper_methods", issue = "85532")] #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] @@ -168,21 +195,18 @@ macro_rules! widening_impl { #[lang = "i8"] impl i8 { - widening_impl! { i8, i16, 8 } int_impl! { i8, i8, u8, 8, 7, -128, 127, 2, "-0x7e", "0xa", "0x12", "0x12", "0x48", "[0x12]", "[0x12]", "", "" } } #[lang = "i16"] impl i16 { - widening_impl! { i16, i32, 16 } int_impl! { i16, i16, u16, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" } } #[lang = "i32"] impl i32 { - widening_impl! { i32, i64, 32 } int_impl! { i32, i32, u32, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" } @@ -190,7 +214,6 @@ impl i32 { #[lang = "i64"] impl i64 { - widening_impl! { i64, i128, 64 } int_impl! { i64, i64, u64, 64, 63, -9223372036854775808, 9223372036854775807, 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", @@ -212,7 +235,6 @@ impl i128 { #[cfg(target_pointer_width = "16")] #[lang = "isize"] impl isize { - widening_impl! { isize, i32, 16 } int_impl! { isize, i16, usize, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } @@ -221,7 +243,6 @@ impl isize { #[cfg(target_pointer_width = "32")] #[lang = "isize"] impl isize { - widening_impl! { isize, i64, 32 } int_impl! { isize, i32, usize, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", @@ -231,12 +252,11 @@ impl isize { #[cfg(target_pointer_width = "64")] #[lang = "isize"] impl isize { - widening_impl! { isize, i128, 64 } int_impl! { isize, i64, usize, 64, 63, -9223372036854775808, 9223372036854775807, 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", - "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", - usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } + "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", + "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", + usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } } /// If 6th bit set ascii is upper case. @@ -244,9 +264,9 @@ const ASCII_CASE_MASK: u8 = 0b0010_0000; #[lang = "u8"] impl u8 { - widening_impl! { u8, u16, 8 } uint_impl! { u8, u8, i8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]", "[0x12]", "", "" } + widening_impl! { u8, u16, 8, unsigned } /// Checks if the value is within the ASCII range. /// @@ -408,7 +428,7 @@ impl u8 { /// let percent = b'%'; /// let space = b' '; /// let lf = b'\n'; - /// let esc = 0x1b_u8; + /// let esc = b'\x1b'; /// /// assert!(uppercase_a.is_ascii_alphabetic()); /// assert!(uppercase_g.is_ascii_alphabetic()); @@ -442,7 +462,7 @@ impl u8 { /// let percent = b'%'; /// let space = b' '; /// let lf = b'\n'; - /// let esc = 0x1b_u8; + /// let esc = b'\x1b'; /// /// assert!(uppercase_a.is_ascii_uppercase()); /// assert!(uppercase_g.is_ascii_uppercase()); @@ -476,7 +496,7 @@ impl u8 { /// let percent = b'%'; /// let space = b' '; /// let lf = b'\n'; - /// let esc = 0x1b_u8; + /// let esc = b'\x1b'; /// /// assert!(!uppercase_a.is_ascii_lowercase()); /// assert!(!uppercase_g.is_ascii_lowercase()); @@ -513,7 +533,7 @@ impl u8 { /// let percent = b'%'; /// let space = b' '; /// let lf = b'\n'; - /// let esc = 0x1b_u8; + /// let esc = b'\x1b'; /// /// assert!(uppercase_a.is_ascii_alphanumeric()); /// assert!(uppercase_g.is_ascii_alphanumeric()); @@ -547,7 +567,7 @@ impl u8 { /// let percent = b'%'; /// let space = b' '; /// let lf = b'\n'; - /// let esc = 0x1b_u8; + /// let esc = b'\x1b'; /// /// assert!(!uppercase_a.is_ascii_digit()); /// assert!(!uppercase_g.is_ascii_digit()); @@ -584,7 +604,7 @@ impl u8 { /// let percent = b'%'; /// let space = b' '; /// let lf = b'\n'; - /// let esc = 0x1b_u8; + /// let esc = b'\x1b'; /// /// assert!(uppercase_a.is_ascii_hexdigit()); /// assert!(!uppercase_g.is_ascii_hexdigit()); @@ -622,7 +642,7 @@ impl u8 { /// let percent = b'%'; /// let space = b' '; /// let lf = b'\n'; - /// let esc = 0x1b_u8; + /// let esc = b'\x1b'; /// /// assert!(!uppercase_a.is_ascii_punctuation()); /// assert!(!uppercase_g.is_ascii_punctuation()); @@ -656,7 +676,7 @@ impl u8 { /// let percent = b'%'; /// let space = b' '; /// let lf = b'\n'; - /// let esc = 0x1b_u8; + /// let esc = b'\x1b'; /// /// assert!(uppercase_a.is_ascii_graphic()); /// assert!(uppercase_g.is_ascii_graphic()); @@ -707,7 +727,7 @@ impl u8 { /// let percent = b'%'; /// let space = b' '; /// let lf = b'\n'; - /// let esc = 0x1b_u8; + /// let esc = b'\x1b'; /// /// assert!(!uppercase_a.is_ascii_whitespace()); /// assert!(!uppercase_g.is_ascii_whitespace()); @@ -743,7 +763,7 @@ impl u8 { /// let percent = b'%'; /// let space = b' '; /// let lf = b'\n'; - /// let esc = 0x1b_u8; + /// let esc = b'\x1b'; /// /// assert!(!uppercase_a.is_ascii_control()); /// assert!(!uppercase_g.is_ascii_control()); @@ -793,26 +813,26 @@ impl u8 { #[lang = "u16"] impl u16 { - widening_impl! { u16, u32, 16 } uint_impl! { u16, u16, i16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" } + widening_impl! { u16, u32, 16, unsigned } } #[lang = "u32"] impl u32 { - widening_impl! { u32, u64, 32 } uint_impl! { u32, u32, i32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" } + widening_impl! { u32, u64, 32, unsigned } } #[lang = "u64"] impl u64 { - widening_impl! { u64, u128, 64 } uint_impl! { u64, u64, i64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", "", ""} + widening_impl! { u64, u128, 64, unsigned } } #[lang = "u128"] @@ -830,29 +850,29 @@ impl u128 { #[cfg(target_pointer_width = "16")] #[lang = "usize"] impl usize { - widening_impl! { usize, u32, 16 } uint_impl! { usize, u16, isize, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } + widening_impl! { usize, u32, 16, unsigned } } #[cfg(target_pointer_width = "32")] #[lang = "usize"] impl usize { - widening_impl! { usize, u64, 32 } uint_impl! { usize, u32, isize, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } + widening_impl! { usize, u64, 32, unsigned } } #[cfg(target_pointer_width = "64")] #[lang = "usize"] impl usize { - widening_impl! { usize, u128, 64 } uint_impl! { usize, u64, isize, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", + "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } + widening_impl! { usize, u128, 64, unsigned } } /// A classification of floating point numbers. diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 89fd9fbaf4..7708094e1f 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -82,7 +82,8 @@ macro_rules! nonzero_integers { } #[stable(feature = "from_nonzero", since = "1.31.0")] - impl From<$Ty> for $Int { + #[rustc_const_unstable(feature = "const_num_from_num", issue = "87852")] + impl const From<$Ty> for $Int { #[doc = concat!("Converts a `", stringify!($Ty), "` into an `", stringify!($Int), "`")] #[inline] fn from(nonzero: $Ty) -> Self { @@ -91,7 +92,8 @@ macro_rules! nonzero_integers { } #[stable(feature = "nonzero_bitor", since = "1.45.0")] - impl BitOr for $Ty { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const BitOr for $Ty { type Output = Self; #[inline] fn bitor(self, rhs: Self) -> Self::Output { @@ -102,7 +104,8 @@ macro_rules! nonzero_integers { } #[stable(feature = "nonzero_bitor", since = "1.45.0")] - impl BitOr<$Int> for $Ty { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const BitOr<$Int> for $Ty { type Output = Self; #[inline] fn bitor(self, rhs: $Int) -> Self::Output { @@ -114,7 +117,8 @@ macro_rules! nonzero_integers { } #[stable(feature = "nonzero_bitor", since = "1.45.0")] - impl BitOr<$Ty> for $Int { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const BitOr<$Ty> for $Int { type Output = $Ty; #[inline] fn bitor(self, rhs: $Ty) -> Self::Output { @@ -126,7 +130,8 @@ macro_rules! nonzero_integers { } #[stable(feature = "nonzero_bitor", since = "1.45.0")] - impl BitOrAssign for $Ty { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const BitOrAssign for $Ty { #[inline] fn bitor_assign(&mut self, rhs: Self) { *self = *self | rhs; @@ -134,7 +139,8 @@ macro_rules! nonzero_integers { } #[stable(feature = "nonzero_bitor", since = "1.45.0")] - impl BitOrAssign<$Int> for $Ty { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const BitOrAssign<$Int> for $Ty { #[inline] fn bitor_assign(&mut self, rhs: $Int) { *self = *self | rhs; @@ -256,7 +262,8 @@ macro_rules! nonzero_integers_div { ( $( $Ty: ident($Int: ty); )+ ) => { $( #[stable(feature = "nonzero_div", since = "1.51.0")] - impl Div<$Ty> for $Int { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Div<$Ty> for $Int { type Output = $Int; /// This operation rounds towards zero, /// truncating any fractional part of the exact result, and cannot panic. @@ -269,7 +276,8 @@ macro_rules! nonzero_integers_div { } #[stable(feature = "nonzero_div", since = "1.51.0")] - impl Rem<$Ty> for $Int { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Rem<$Ty> for $Int { type Output = $Int; /// This operation satisfies `n % d == n - (n / d) * d`, and cannot panic. #[inline] diff --git a/library/core/src/num/saturating.rs b/library/core/src/num/saturating.rs index c764f420e2..ba81f3f9fd 100644 --- a/library/core/src/num/saturating.rs +++ b/library/core/src/num/saturating.rs @@ -273,7 +273,7 @@ macro_rules! saturating_impl { /// Basic usage: /// /// ``` - /// #![feature(saturating_int_impl, saturating_div)] + /// #![feature(saturating_int_impl)] /// use std::num::Saturating; /// #[doc = concat!("assert_eq!(Saturating(2", stringify!($t), "), Saturating(5", stringify!($t), ") / Saturating(2));")] @@ -282,7 +282,7 @@ macro_rules! saturating_impl { /// ``` /// /// ```should_panic - /// #![feature(saturating_int_impl, saturating_div)] + /// #![feature(saturating_int_impl)] /// use std::num::Saturating; /// #[doc = concat!("let _ = Saturating(0", stringify!($t), ") / Saturating(0);")] diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index c3b2ecdb30..a15eabf796 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1120,20 +1120,15 @@ macro_rules! uint_impl { /// Basic usage: /// /// ``` - /// #![feature(saturating_div)] - /// #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".saturating_div(2), 2);")] /// /// ``` /// /// ```should_panic - /// #![feature(saturating_div)] - /// #[doc = concat!("let _ = 1", stringify!($SelfT), ".saturating_div(0);")] /// /// ``` - #[unstable(feature = "saturating_div", issue = "87920")] - #[rustc_const_unstable(feature = "saturating_div", issue = "87920")] + #[stable(feature = "saturating_div", since = "1.58.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1509,6 +1504,8 @@ macro_rules! uint_impl { /// additional bit of overflow. This allows for chaining together multiple additions /// to create "big integers" which represent larger values. /// + #[doc = concat!("This can be thought of as a ", stringify!($BITS), "-bit \"full adder\", in the electronics sense.")] + /// /// # Examples /// /// Basic usage @@ -1518,7 +1515,20 @@ macro_rules! uint_impl { #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".carrying_add(2, false), (7, false));")] #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".carrying_add(2, true), (8, false));")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, false), (0, true));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(0, true), (0, true));")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, true), (1, true));")] + #[doc = concat!("assert_eq!(", + stringify!($SelfT), "::MAX.carrying_add(", stringify!($SelfT), "::MAX, true), ", + "(", stringify!($SelfT), "::MAX, true));" + )] + /// ``` + /// + /// If `carry` is false, this method is equivalent to [`overflowing_add`](Self::overflowing_add): + /// + /// ``` + /// #![feature(bigint_helper_methods)] + #[doc = concat!("assert_eq!(5_", stringify!($SelfT), ".carrying_add(2, false), 5_", stringify!($SelfT), ".overflowing_add(2));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, false), ", stringify!($SelfT), "::MAX.overflowing_add(1));")] /// ``` #[unstable(feature = "bigint_helper_methods", issue = "85532")] #[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")] @@ -1530,7 +1540,7 @@ macro_rules! uint_impl { // to generate optimal code for now, and LLVM doesn't have an equivalent intrinsic let (a, b) = self.overflowing_add(rhs); let (c, d) = a.overflowing_add(carry as $SelfT); - (c, b | d) + (c, b || d) } /// Calculates `self` + `rhs` with a signed `rhs` @@ -1611,7 +1621,7 @@ macro_rules! uint_impl { // to generate optimal code for now, and LLVM doesn't have an equivalent intrinsic let (a, b) = self.overflowing_sub(rhs); let (c, d) = a.overflowing_sub(borrow as $SelfT); - (c, b | d) + (c, b || d) } /// Computes the absolute difference between `self` and `other`. diff --git a/library/core/src/num/wrapping.rs b/library/core/src/num/wrapping.rs index f387bd5b41..a0e42c51e4 100644 --- a/library/core/src/num/wrapping.rs +++ b/library/core/src/num/wrapping.rs @@ -87,7 +87,8 @@ impl fmt::UpperHex for Wrapping { macro_rules! sh_impl_signed { ($t:ident, $f:ident) => { #[stable(feature = "rust1", since = "1.0.0")] - impl Shl<$f> for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Shl<$f> for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -99,20 +100,22 @@ macro_rules! sh_impl_signed { } } } - forward_ref_binop! { impl Shl, shl for Wrapping<$t>, $f, + forward_ref_binop! { impl const Shl, shl for Wrapping<$t>, $f, #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl ShlAssign<$f> for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const ShlAssign<$f> for Wrapping<$t> { #[inline] fn shl_assign(&mut self, other: $f) { *self = *self << other; } } - forward_ref_op_assign! { impl ShlAssign, shl_assign for Wrapping<$t>, $f } + forward_ref_op_assign! { impl const ShlAssign, shl_assign for Wrapping<$t>, $f } #[stable(feature = "rust1", since = "1.0.0")] - impl Shr<$f> for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Shr<$f> for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -124,24 +127,26 @@ macro_rules! sh_impl_signed { } } } - forward_ref_binop! { impl Shr, shr for Wrapping<$t>, $f, + forward_ref_binop! { impl const Shr, shr for Wrapping<$t>, $f, #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl ShrAssign<$f> for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const ShrAssign<$f> for Wrapping<$t> { #[inline] fn shr_assign(&mut self, other: $f) { *self = *self >> other; } } - forward_ref_op_assign! { impl ShrAssign, shr_assign for Wrapping<$t>, $f } + forward_ref_op_assign! { impl const ShrAssign, shr_assign for Wrapping<$t>, $f } }; } macro_rules! sh_impl_unsigned { ($t:ident, $f:ident) => { #[stable(feature = "rust1", since = "1.0.0")] - impl Shl<$f> for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Shl<$f> for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -149,20 +154,22 @@ macro_rules! sh_impl_unsigned { Wrapping(self.0.wrapping_shl((other & self::shift_max::$t as $f) as u32)) } } - forward_ref_binop! { impl Shl, shl for Wrapping<$t>, $f, + forward_ref_binop! { impl const Shl, shl for Wrapping<$t>, $f, #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl ShlAssign<$f> for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const ShlAssign<$f> for Wrapping<$t> { #[inline] fn shl_assign(&mut self, other: $f) { *self = *self << other; } } - forward_ref_op_assign! { impl ShlAssign, shl_assign for Wrapping<$t>, $f } + forward_ref_op_assign! { impl const ShlAssign, shl_assign for Wrapping<$t>, $f } #[stable(feature = "rust1", since = "1.0.0")] - impl Shr<$f> for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Shr<$f> for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -170,17 +177,18 @@ macro_rules! sh_impl_unsigned { Wrapping(self.0.wrapping_shr((other & self::shift_max::$t as $f) as u32)) } } - forward_ref_binop! { impl Shr, shr for Wrapping<$t>, $f, + forward_ref_binop! { impl const Shr, shr for Wrapping<$t>, $f, #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl ShrAssign<$f> for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const ShrAssign<$f> for Wrapping<$t> { #[inline] fn shr_assign(&mut self, other: $f) { *self = *self >> other; } } - forward_ref_op_assign! { impl ShrAssign, shr_assign for Wrapping<$t>, $f } + forward_ref_op_assign! { impl const ShrAssign, shr_assign for Wrapping<$t>, $f } }; } @@ -209,7 +217,8 @@ sh_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } macro_rules! wrapping_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - impl Add for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Add for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -217,20 +226,22 @@ macro_rules! wrapping_impl { Wrapping(self.0.wrapping_add(other.0)) } } - forward_ref_binop! { impl Add, add for Wrapping<$t>, Wrapping<$t>, + forward_ref_binop! { impl const Add, add for Wrapping<$t>, Wrapping<$t>, #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl AddAssign for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const AddAssign for Wrapping<$t> { #[inline] fn add_assign(&mut self, other: Wrapping<$t>) { *self = *self + other; } } - forward_ref_op_assign! { impl AddAssign, add_assign for Wrapping<$t>, Wrapping<$t> } + forward_ref_op_assign! { impl const AddAssign, add_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "rust1", since = "1.0.0")] - impl Sub for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Sub for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -238,20 +249,22 @@ macro_rules! wrapping_impl { Wrapping(self.0.wrapping_sub(other.0)) } } - forward_ref_binop! { impl Sub, sub for Wrapping<$t>, Wrapping<$t>, + forward_ref_binop! { impl const Sub, sub for Wrapping<$t>, Wrapping<$t>, #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl SubAssign for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const SubAssign for Wrapping<$t> { #[inline] fn sub_assign(&mut self, other: Wrapping<$t>) { *self = *self - other; } } - forward_ref_op_assign! { impl SubAssign, sub_assign for Wrapping<$t>, Wrapping<$t> } + forward_ref_op_assign! { impl const SubAssign, sub_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "rust1", since = "1.0.0")] - impl Mul for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Mul for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -263,16 +276,18 @@ macro_rules! wrapping_impl { #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl MulAssign for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const MulAssign for Wrapping<$t> { #[inline] fn mul_assign(&mut self, other: Wrapping<$t>) { *self = *self * other; } } - forward_ref_op_assign! { impl MulAssign, mul_assign for Wrapping<$t>, Wrapping<$t> } + forward_ref_op_assign! { impl const MulAssign, mul_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "wrapping_div", since = "1.3.0")] - impl Div for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Div for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -280,20 +295,22 @@ macro_rules! wrapping_impl { Wrapping(self.0.wrapping_div(other.0)) } } - forward_ref_binop! { impl Div, div for Wrapping<$t>, Wrapping<$t>, + forward_ref_binop! { impl const Div, div for Wrapping<$t>, Wrapping<$t>, #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl DivAssign for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const DivAssign for Wrapping<$t> { #[inline] fn div_assign(&mut self, other: Wrapping<$t>) { *self = *self / other; } } - forward_ref_op_assign! { impl DivAssign, div_assign for Wrapping<$t>, Wrapping<$t> } + forward_ref_op_assign! { impl const DivAssign, div_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "wrapping_impls", since = "1.7.0")] - impl Rem for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Rem for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -301,20 +318,22 @@ macro_rules! wrapping_impl { Wrapping(self.0.wrapping_rem(other.0)) } } - forward_ref_binop! { impl Rem, rem for Wrapping<$t>, Wrapping<$t>, + forward_ref_binop! { impl const Rem, rem for Wrapping<$t>, Wrapping<$t>, #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl RemAssign for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const RemAssign for Wrapping<$t> { #[inline] fn rem_assign(&mut self, other: Wrapping<$t>) { *self = *self % other; } } - forward_ref_op_assign! { impl RemAssign, rem_assign for Wrapping<$t>, Wrapping<$t> } + forward_ref_op_assign! { impl const RemAssign, rem_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "rust1", since = "1.0.0")] - impl Not for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Not for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -322,11 +341,12 @@ macro_rules! wrapping_impl { Wrapping(!self.0) } } - forward_ref_unop! { impl Not, not for Wrapping<$t>, + forward_ref_unop! { impl const Not, not for Wrapping<$t>, #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "rust1", since = "1.0.0")] - impl BitXor for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const BitXor for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -334,20 +354,22 @@ macro_rules! wrapping_impl { Wrapping(self.0 ^ other.0) } } - forward_ref_binop! { impl BitXor, bitxor for Wrapping<$t>, Wrapping<$t>, + forward_ref_binop! { impl const BitXor, bitxor for Wrapping<$t>, Wrapping<$t>, #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl BitXorAssign for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const BitXorAssign for Wrapping<$t> { #[inline] fn bitxor_assign(&mut self, other: Wrapping<$t>) { *self = *self ^ other; } } - forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for Wrapping<$t>, Wrapping<$t> } + forward_ref_op_assign! { impl const BitXorAssign, bitxor_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "rust1", since = "1.0.0")] - impl BitOr for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const BitOr for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -355,20 +377,22 @@ macro_rules! wrapping_impl { Wrapping(self.0 | other.0) } } - forward_ref_binop! { impl BitOr, bitor for Wrapping<$t>, Wrapping<$t>, + forward_ref_binop! { impl const BitOr, bitor for Wrapping<$t>, Wrapping<$t>, #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl BitOrAssign for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const BitOrAssign for Wrapping<$t> { #[inline] fn bitor_assign(&mut self, other: Wrapping<$t>) { *self = *self | other; } } - forward_ref_op_assign! { impl BitOrAssign, bitor_assign for Wrapping<$t>, Wrapping<$t> } + forward_ref_op_assign! { impl const BitOrAssign, bitor_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "rust1", since = "1.0.0")] - impl BitAnd for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const BitAnd for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -376,27 +400,29 @@ macro_rules! wrapping_impl { Wrapping(self.0 & other.0) } } - forward_ref_binop! { impl BitAnd, bitand for Wrapping<$t>, Wrapping<$t>, + forward_ref_binop! { impl const BitAnd, bitand for Wrapping<$t>, Wrapping<$t>, #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl BitAndAssign for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const BitAndAssign for Wrapping<$t> { #[inline] fn bitand_assign(&mut self, other: Wrapping<$t>) { *self = *self & other; } } - forward_ref_op_assign! { impl BitAndAssign, bitand_assign for Wrapping<$t>, Wrapping<$t> } + forward_ref_op_assign! { impl const BitAndAssign, bitand_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "wrapping_neg", since = "1.10.0")] - impl Neg for Wrapping<$t> { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Neg for Wrapping<$t> { type Output = Self; #[inline] fn neg(self) -> Self { Wrapping(0) - self } } - forward_ref_unop! { impl Neg, neg for Wrapping<$t>, + forward_ref_unop! { impl const Neg, neg for Wrapping<$t>, #[stable(feature = "wrapping_ref", since = "1.14.0")] } )*) diff --git a/library/core/src/ops/arith.rs b/library/core/src/ops/arith.rs index a0577b287c..e954742938 100644 --- a/library/core/src/ops/arith.rs +++ b/library/core/src/ops/arith.rs @@ -92,7 +92,8 @@ pub trait Add { macro_rules! add_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - impl Add for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Add for $t { type Output = $t; #[inline] @@ -100,7 +101,7 @@ macro_rules! add_impl { fn add(self, other: $t) -> $t { self + other } } - forward_ref_binop! { impl Add, add for $t, $t } + forward_ref_binop! { impl const Add, add for $t, $t } )*) } @@ -198,7 +199,8 @@ pub trait Sub { macro_rules! sub_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - impl Sub for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Sub for $t { type Output = $t; #[inline] @@ -206,7 +208,7 @@ macro_rules! sub_impl { fn sub(self, other: $t) -> $t { self - other } } - forward_ref_binop! { impl Sub, sub for $t, $t } + forward_ref_binop! { impl const Sub, sub for $t, $t } )*) } @@ -326,7 +328,8 @@ pub trait Mul { macro_rules! mul_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - impl Mul for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Mul for $t { type Output = $t; #[inline] @@ -334,7 +337,7 @@ macro_rules! mul_impl { fn mul(self, other: $t) -> $t { self * other } } - forward_ref_binop! { impl Mul, mul for $t, $t } + forward_ref_binop! { impl const Mul, mul for $t, $t } )*) } @@ -464,14 +467,15 @@ macro_rules! div_impl_integer { /// #[doc = $panic] #[stable(feature = "rust1", since = "1.0.0")] - impl Div for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Div for $t { type Output = $t; #[inline] fn div(self, other: $t) -> $t { self / other } } - forward_ref_binop! { impl Div, div for $t, $t } + forward_ref_binop! { impl const Div, div for $t, $t } )*)*) } @@ -483,14 +487,15 @@ div_impl_integer! { macro_rules! div_impl_float { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - impl Div for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Div for $t { type Output = $t; #[inline] fn div(self, other: $t) -> $t { self / other } } - forward_ref_binop! { impl Div, div for $t, $t } + forward_ref_binop! { impl const Div, div for $t, $t } )*) } @@ -564,14 +569,15 @@ macro_rules! rem_impl_integer { /// #[doc = $panic] #[stable(feature = "rust1", since = "1.0.0")] - impl Rem for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Rem for $t { type Output = $t; #[inline] fn rem(self, other: $t) -> $t { self % other } } - forward_ref_binop! { impl Rem, rem for $t, $t } + forward_ref_binop! { impl const Rem, rem for $t, $t } )*)*) } @@ -598,14 +604,15 @@ macro_rules! rem_impl_float { /// assert_eq!(x % y, remainder); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - impl Rem for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Rem for $t { type Output = $t; #[inline] fn rem(self, other: $t) -> $t { self % other } } - forward_ref_binop! { impl Rem, rem for $t, $t } + forward_ref_binop! { impl const Rem, rem for $t, $t } )*) } @@ -671,7 +678,8 @@ pub trait Neg { macro_rules! neg_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - impl Neg for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Neg for $t { type Output = $t; #[inline] @@ -679,7 +687,7 @@ macro_rules! neg_impl { fn neg(self) -> $t { -self } } - forward_ref_unop! { impl Neg, neg for $t } + forward_ref_unop! { impl const Neg, neg for $t } )*) } @@ -739,13 +747,14 @@ pub trait AddAssign { macro_rules! add_assign_impl { ($($t:ty)+) => ($( #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl AddAssign for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const AddAssign for $t { #[inline] #[rustc_inherit_overflow_checks] fn add_assign(&mut self, other: $t) { *self += other } } - forward_ref_op_assign! { impl AddAssign, add_assign for $t, $t } + forward_ref_op_assign! { impl const AddAssign, add_assign for $t, $t } )+) } @@ -805,13 +814,14 @@ pub trait SubAssign { macro_rules! sub_assign_impl { ($($t:ty)+) => ($( #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl SubAssign for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const SubAssign for $t { #[inline] #[rustc_inherit_overflow_checks] fn sub_assign(&mut self, other: $t) { *self -= other } } - forward_ref_op_assign! { impl SubAssign, sub_assign for $t, $t } + forward_ref_op_assign! { impl const SubAssign, sub_assign for $t, $t } )+) } @@ -862,13 +872,14 @@ pub trait MulAssign { macro_rules! mul_assign_impl { ($($t:ty)+) => ($( #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl MulAssign for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const MulAssign for $t { #[inline] #[rustc_inherit_overflow_checks] fn mul_assign(&mut self, other: $t) { *self *= other } } - forward_ref_op_assign! { impl MulAssign, mul_assign for $t, $t } + forward_ref_op_assign! { impl const MulAssign, mul_assign for $t, $t } )+) } @@ -919,12 +930,13 @@ pub trait DivAssign { macro_rules! div_assign_impl { ($($t:ty)+) => ($( #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl DivAssign for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const DivAssign for $t { #[inline] fn div_assign(&mut self, other: $t) { *self /= other } } - forward_ref_op_assign! { impl DivAssign, div_assign for $t, $t } + forward_ref_op_assign! { impl const DivAssign, div_assign for $t, $t } )+) } @@ -979,12 +991,13 @@ pub trait RemAssign { macro_rules! rem_assign_impl { ($($t:ty)+) => ($( #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl RemAssign for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const RemAssign for $t { #[inline] fn rem_assign(&mut self, other: $t) { *self %= other } } - forward_ref_op_assign! { impl RemAssign, rem_assign for $t, $t } + forward_ref_op_assign! { impl const RemAssign, rem_assign for $t, $t } )+) } diff --git a/library/core/src/ops/bit.rs b/library/core/src/ops/bit.rs index 92f45ac9e7..255f6cb793 100644 --- a/library/core/src/ops/bit.rs +++ b/library/core/src/ops/bit.rs @@ -54,14 +54,15 @@ pub trait Not { macro_rules! not_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - impl Not for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Not for $t { type Output = $t; #[inline] fn not(self) -> $t { !self } } - forward_ref_unop! { impl Not, not for $t } + forward_ref_unop! { impl const Not, not for $t } )*) } @@ -154,14 +155,15 @@ pub trait BitAnd { macro_rules! bitand_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - impl BitAnd for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const BitAnd for $t { type Output = $t; #[inline] fn bitand(self, rhs: $t) -> $t { self & rhs } } - forward_ref_binop! { impl BitAnd, bitand for $t, $t } + forward_ref_binop! { impl const BitAnd, bitand for $t, $t } )*) } @@ -254,14 +256,15 @@ pub trait BitOr { macro_rules! bitor_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - impl BitOr for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const BitOr for $t { type Output = $t; #[inline] fn bitor(self, rhs: $t) -> $t { self | rhs } } - forward_ref_binop! { impl BitOr, bitor for $t, $t } + forward_ref_binop! { impl const BitOr, bitor for $t, $t } )*) } @@ -354,14 +357,15 @@ pub trait BitXor { macro_rules! bitxor_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - impl BitXor for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const BitXor for $t { type Output = $t; #[inline] fn bitxor(self, other: $t) -> $t { self ^ other } } - forward_ref_binop! { impl BitXor, bitxor for $t, $t } + forward_ref_binop! { impl const BitXor, bitxor for $t, $t } )*) } @@ -451,7 +455,8 @@ pub trait Shl { macro_rules! shl_impl { ($t:ty, $f:ty) => { #[stable(feature = "rust1", since = "1.0.0")] - impl Shl<$f> for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Shl<$f> for $t { type Output = $t; #[inline] @@ -461,7 +466,7 @@ macro_rules! shl_impl { } } - forward_ref_binop! { impl Shl, shl for $t, $f } + forward_ref_binop! { impl const Shl, shl for $t, $f } }; } @@ -569,7 +574,8 @@ pub trait Shr { macro_rules! shr_impl { ($t:ty, $f:ty) => { #[stable(feature = "rust1", since = "1.0.0")] - impl Shr<$f> for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Shr<$f> for $t { type Output = $t; #[inline] @@ -579,7 +585,7 @@ macro_rules! shr_impl { } } - forward_ref_binop! { impl Shr, shr for $t, $f } + forward_ref_binop! { impl const Shr, shr for $t, $f } }; } @@ -704,12 +710,13 @@ pub trait BitAndAssign { macro_rules! bitand_assign_impl { ($($t:ty)+) => ($( #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl BitAndAssign for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const BitAndAssign for $t { #[inline] fn bitand_assign(&mut self, other: $t) { *self &= other } } - forward_ref_op_assign! { impl BitAndAssign, bitand_assign for $t, $t } + forward_ref_op_assign! { impl const BitAndAssign, bitand_assign for $t, $t } )+) } @@ -775,12 +782,13 @@ pub trait BitOrAssign { macro_rules! bitor_assign_impl { ($($t:ty)+) => ($( #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl BitOrAssign for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const BitOrAssign for $t { #[inline] fn bitor_assign(&mut self, other: $t) { *self |= other } } - forward_ref_op_assign! { impl BitOrAssign, bitor_assign for $t, $t } + forward_ref_op_assign! { impl const BitOrAssign, bitor_assign for $t, $t } )+) } @@ -846,12 +854,13 @@ pub trait BitXorAssign { macro_rules! bitxor_assign_impl { ($($t:ty)+) => ($( #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl BitXorAssign for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const BitXorAssign for $t { #[inline] fn bitxor_assign(&mut self, other: $t) { *self ^= other } } - forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for $t, $t } + forward_ref_op_assign! { impl const BitXorAssign, bitxor_assign for $t, $t } )+) } @@ -907,7 +916,8 @@ pub trait ShlAssign { macro_rules! shl_assign_impl { ($t:ty, $f:ty) => { #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl ShlAssign<$f> for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const ShlAssign<$f> for $t { #[inline] #[rustc_inherit_overflow_checks] fn shl_assign(&mut self, other: $f) { @@ -915,7 +925,7 @@ macro_rules! shl_assign_impl { } } - forward_ref_op_assign! { impl ShlAssign, shl_assign for $t, $f } + forward_ref_op_assign! { impl const ShlAssign, shl_assign for $t, $f } }; } @@ -989,7 +999,8 @@ pub trait ShrAssign { macro_rules! shr_assign_impl { ($t:ty, $f:ty) => { #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl ShrAssign<$f> for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const ShrAssign<$f> for $t { #[inline] #[rustc_inherit_overflow_checks] fn shr_assign(&mut self, other: $f) { @@ -997,7 +1008,7 @@ macro_rules! shr_assign_impl { } } - forward_ref_op_assign! { impl ShrAssign, shr_assign for $t, $f } + forward_ref_op_assign! { impl const ShrAssign, shr_assign for $t, $f } }; } diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index cd2d57699c..b0c15898a1 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -7,6 +7,10 @@ use crate::{convert, ops}; /// Having the enum makes it clearer -- no more wondering "wait, what did `false` /// mean again?" -- and allows including a value. /// +/// Similar to [`Option`] and [`Result`], this enum can be used with the `?` operator +/// to return immediately if the [`Break`] variant is present or otherwise continue normally +/// with the value inside the [`Continue`] variant. +/// /// # Examples /// /// Early-exiting from [`Iterator::try_for_each`]: @@ -24,7 +28,7 @@ use crate::{convert, ops}; /// ``` /// /// A basic tree traversal: -/// ```no_run +/// ``` /// use std::ops::ControlFlow; /// /// pub struct TreeNode { @@ -34,18 +38,46 @@ use crate::{convert, ops}; /// } /// /// impl TreeNode { -/// pub fn traverse_inorder(&self, mut f: impl FnMut(&T) -> ControlFlow) -> ControlFlow { +/// pub fn traverse_inorder(&self, f: &mut impl FnMut(&T) -> ControlFlow) -> ControlFlow { /// if let Some(left) = &self.left { -/// left.traverse_inorder(&mut f)?; +/// left.traverse_inorder(f)?; /// } /// f(&self.value)?; /// if let Some(right) = &self.right { -/// right.traverse_inorder(&mut f)?; +/// right.traverse_inorder(f)?; /// } /// ControlFlow::Continue(()) /// } +/// fn leaf(value: T) -> Option>> { +/// Some(Box::new(Self { value, left: None, right: None })) +/// } /// } +/// +/// let node = TreeNode { +/// value: 0, +/// left: TreeNode::leaf(1), +/// right: Some(Box::new(TreeNode { +/// value: -1, +/// left: TreeNode::leaf(5), +/// right: TreeNode::leaf(2), +/// })) +/// }; +/// let mut sum = 0; +/// +/// let res = node.traverse_inorder(&mut |val| { +/// if *val < 0 { +/// ControlFlow::Break(*val) +/// } else { +/// sum += *val; +/// ControlFlow::Continue(()) +/// } +/// }); +/// assert_eq!(res, ControlFlow::Break(-1)); +/// assert_eq!(sum, 6); /// ``` +/// +/// [`Break`]: ControlFlow::Break +/// [`Continue`]: ControlFlow::Continue #[stable(feature = "control_flow_enum_type", since = "1.55.0")] #[derive(Debug, Clone, Copy, PartialEq)] pub enum ControlFlow { diff --git a/library/core/src/ops/generator.rs b/library/core/src/ops/generator.rs index 4f23620b92..b527c4b04a 100644 --- a/library/core/src/ops/generator.rs +++ b/library/core/src/ops/generator.rs @@ -82,6 +82,7 @@ pub trait Generator { /// `return` statement or implicitly as the last expression of a generator /// literal. For example futures would use this as `Result` as it /// represents a completed future. + #[cfg_attr(not(bootstrap), lang = "generator_return")] type Return; /// Resumes the execution of this generator. diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs index 347a346359..b74ba92c76 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -743,6 +743,7 @@ impl Bound<&T> { /// assert_eq!((1..12).start_bound(), Included(&1)); /// assert_eq!((1..12).start_bound().cloned(), Included(1)); /// ``` + #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "bound_cloned", since = "1.55.0")] pub fn cloned(self) -> Bound { match self { diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 8850583215..baf9948857 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -800,19 +800,17 @@ impl Option { /// # Examples /// /// ``` - /// #![feature(option_result_unwrap_unchecked)] /// let x = Some("air"); /// assert_eq!(unsafe { x.unwrap_unchecked() }, "air"); /// ``` /// /// ```no_run - /// #![feature(option_result_unwrap_unchecked)] /// let x: Option<&str> = None; /// assert_eq!(unsafe { x.unwrap_unchecked() }, "air"); // Undefined behavior! /// ``` #[inline] #[track_caller] - #[unstable(feature = "option_result_unwrap_unchecked", reason = "newly added", issue = "81383")] + #[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")] pub unsafe fn unwrap_unchecked(self) -> T { debug_assert!(self.is_some()); match self { @@ -1451,6 +1449,7 @@ impl Option<&T> { /// let copied = opt_x.copied(); /// assert_eq!(copied, Some(12)); /// ``` + #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "copied", since = "1.35.0")] #[rustc_const_unstable(feature = "const_option", issue = "67441")] pub const fn copied(self) -> Option { @@ -1723,7 +1722,8 @@ impl<'a, T> IntoIterator for &'a mut Option { } #[stable(since = "1.12.0", feature = "option_from")] -impl From for Option { +#[rustc_const_unstable(feature = "const_convert", issue = "88674")] +impl const From for Option { /// Moves `val` into a new [`Some`]. /// /// # Examples @@ -1739,7 +1739,8 @@ impl From for Option { } #[stable(feature = "option_ref_from_ref_option", since = "1.30.0")] -impl<'a, T> From<&'a Option> for Option<&'a T> { +#[rustc_const_unstable(feature = "const_convert", issue = "88674")] +impl<'a, T> const From<&'a Option> for Option<&'a T> { /// Converts from `&Option` to `Option<&T>`. /// /// # Examples @@ -1766,7 +1767,8 @@ impl<'a, T> From<&'a Option> for Option<&'a T> { } #[stable(feature = "option_ref_from_ref_option", since = "1.30.0")] -impl<'a, T> From<&'a mut Option> for Option<&'a mut T> { +#[rustc_const_unstable(feature = "const_convert", issue = "88674")] +impl<'a, T> const From<&'a mut Option> for Option<&'a mut T> { /// Converts from `&mut Option` to `Option<&mut T>` /// /// # Examples @@ -2052,7 +2054,7 @@ impl ops::Try for Option { } #[unstable(feature = "try_trait_v2", issue = "84277")] -impl ops::FromResidual for Option { +impl const ops::FromResidual for Option { #[inline] fn from_residual(residual: Option) -> Self { match residual { diff --git a/library/core/src/panic/location.rs b/library/core/src/panic/location.rs index a482414caa..714e9b73c7 100644 --- a/library/core/src/panic/location.rs +++ b/library/core/src/panic/location.rs @@ -79,6 +79,7 @@ impl<'a> Location<'a> { /// assert_ne!(this_location.line(), another_location.line()); /// assert_ne!(this_location.column(), another_location.column()); /// ``` + #[must_use] #[stable(feature = "track_caller", since = "1.46.0")] #[rustc_const_unstable(feature = "const_caller_location", issue = "76156")] #[track_caller] @@ -119,6 +120,7 @@ impl<'a> Location<'a> { /// /// panic!("Normal panic"); /// ``` + #[must_use] #[stable(feature = "panic_hooks", since = "1.10.0")] pub fn file(&self) -> &str { self.file @@ -141,6 +143,7 @@ impl<'a> Location<'a> { /// /// panic!("Normal panic"); /// ``` + #[must_use] #[stable(feature = "panic_hooks", since = "1.10.0")] pub fn line(&self) -> u32 { self.line @@ -163,6 +166,7 @@ impl<'a> Location<'a> { /// /// panic!("Normal panic"); /// ``` + #[must_use] #[stable(feature = "panic_col", since = "1.25.0")] pub fn column(&self) -> u32 { self.col diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs index a52a0022e5..d8e421df5d 100644 --- a/library/core/src/panic/panic_info.rs +++ b/library/core/src/panic/panic_info.rs @@ -81,6 +81,7 @@ impl<'a> PanicInfo<'a> { /// /// panic!("Normal panic"); /// ``` + #[must_use] #[stable(feature = "panic_hooks", since = "1.10.0")] pub fn payload(&self) -> &(dyn Any + Send) { self.payload @@ -89,6 +90,7 @@ impl<'a> PanicInfo<'a> { /// If the `panic!` macro from the `core` crate (not from `std`) /// was used with a formatting string and some additional arguments, /// returns that message ready to be used for example with [`fmt::write`] + #[must_use] #[unstable(feature = "panic_info_message", issue = "66745")] pub fn message(&self) -> Option<&fmt::Arguments<'_>> { self.message @@ -118,10 +120,11 @@ impl<'a> PanicInfo<'a> { /// /// panic!("Normal panic"); /// ``` + #[must_use] #[stable(feature = "panic_hooks", since = "1.10.0")] pub fn location(&self) -> Option<&Location<'_>> { // NOTE: If this is changed to sometimes return None, - // deal with that case in std::panicking::default_hook and std::panicking::begin_panic_fmt. + // deal with that case in std::panicking::default_hook and core::panicking::panic_fmt. Some(&self.location) } } diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index 6d3ec6ae86..eedea6562b 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -34,13 +34,11 @@ use crate::panic::{Location, PanicInfo}; // never inline unless panic_immediate_abort to avoid code // bloat at the call sites as much as possible #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] +#[rustc_const_unstable(feature = "core_panic", issue = "none")] #[lang = "panic"] // needed by codegen for panic on overflow and other `Assert` MIR terminators -pub fn panic(expr: &'static str) -> ! { - if cfg!(feature = "panic_immediate_abort") { - super::intrinsics::abort() - } - +pub const fn panic(expr: &'static str) -> ! { // Use Arguments::new_v1 instead of format_args!("{}", expr) to potentially // reduce size overhead. The format_args! macro uses str's Display trait to // write expr, which calls Formatter::pad, which must accommodate string @@ -52,15 +50,16 @@ pub fn panic(expr: &'static str) -> ! { #[inline] #[track_caller] -#[lang = "panic_str"] // needed for const-evaluated panics -pub fn panic_str(expr: &str) -> ! { - panic_fmt(format_args!("{}", expr)); +#[lang = "panic_str"] // needed for `non-fmt-panics` lint +pub const fn panic_str(expr: &str) -> ! { + panic_display(&expr); } #[inline] #[track_caller] -#[cfg_attr(not(bootstrap), lang = "panic_display")] // needed for const-evaluated panics -pub fn panic_display(x: &T) -> ! { +#[lang = "panic_display"] // needed for const-evaluated panics +#[rustc_do_not_const_check] // hooked by const-eval +pub const fn panic_display(x: &T) -> ! { panic_fmt(format_args!("{}", *x)); } @@ -76,13 +75,21 @@ fn panic_bounds_check(index: usize, len: usize) -> ! { panic!("index out of bounds: the len is {} but the index is {}", len, index) } -/// The underlying implementation of libcore's `panic!` macro when formatting is used. +/// The entry point for panicking with a formatted message. +/// +/// This is designed to reduce the amount of code required at the call +/// site as much as possible (so that `panic!()` has as low an impact +/// on (e.g.) the inlining of other functions as possible), by moving +/// the actual formatting into this shared place. #[cold] +// If panic_immediate_abort, inline the abort call, +// otherwise avoid inlining because of it is cold path. #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] #[lang = "panic_fmt"] // needed for const-evaluated panics -pub fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { +#[rustc_do_not_const_check] // hooked by const-eval +pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { if cfg!(feature = "panic_immediate_abort") { super::intrinsics::abort() } diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 34fc874ada..09fc6df542 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -705,6 +705,7 @@ impl<'a, T: ?Sized> Pin<&'a T> { /// /// ["pinning projections"]: self#projections-and-structural-pinning #[inline(always)] + #[must_use] #[rustc_const_unstable(feature = "const_pin", issue = "76654")] #[stable(feature = "pin", since = "1.33.0")] pub const fn get_ref(self) -> &'a T { diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 0de9126dab..f47a30c9b5 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1104,11 +1104,10 @@ mod prim_usize {} /// * [`Clone`] \(Note that this will not defer to `T`'s `Clone` implementation if it exists!) /// * [`Deref`] /// * [`Borrow`] -/// * [`Pointer`] +/// * [`fmt::Pointer`] /// /// [`Deref`]: ops::Deref /// [`Borrow`]: borrow::Borrow -/// [`Pointer`]: fmt::Pointer /// /// `&mut T` references get all of the above except `Copy` and `Clone` (to prevent creating /// multiple simultaneous mutable borrows), plus the following, regardless of the type of its @@ -1124,7 +1123,7 @@ mod prim_usize {} /// The following traits are implemented on `&T` references if the underlying `T` also implements /// that trait: /// -/// * All the traits in [`std::fmt`] except [`Pointer`] and [`fmt::Write`] +/// * All the traits in [`std::fmt`] except [`fmt::Pointer`] (which is implemented regardless of the type of its referent) and [`fmt::Write`] /// * [`PartialOrd`] /// * [`Ord`] /// * [`PartialEq`] @@ -1133,9 +1132,9 @@ mod prim_usize {} /// * [`Fn`] \(in addition, `&T` references get [`FnMut`] and [`FnOnce`] if `T: Fn`) /// * [`Hash`] /// * [`ToSocketAddrs`] +/// * [`Send`] \(`&T` references also require T: [Sync]) /// /// [`std::fmt`]: fmt -/// ['Pointer`]: fmt::Pointer /// [`Hash`]: hash::Hash #[doc = concat!("[`ToSocketAddrs`]: ", include_str!("../primitive_docs/net_tosocketaddrs.md"))] /// @@ -1150,7 +1149,6 @@ mod prim_usize {} /// * [`ExactSizeIterator`] /// * [`FusedIterator`] /// * [`TrustedLen`] -/// * [`Send`] \(note that `&T` references only get `Send` if T: [Sync]) /// * [`io::Write`] /// * [`Read`] /// * [`Seek`] diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 95e86a688b..344b483662 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -879,15 +879,30 @@ impl *const T { /// # } } /// ``` #[stable(feature = "align_offset", since = "1.36.0")] - pub fn align_offset(self, align: usize) -> usize + #[rustc_const_unstable(feature = "const_align_offset", issue = "90962")] + pub const fn align_offset(self, align: usize) -> usize where T: Sized, { if !align.is_power_of_two() { panic!("align_offset: align is not a power-of-two"); } - // SAFETY: `align` has been checked to be a power of 2 above - unsafe { align_offset(self, align) } + + fn rt_impl(p: *const T, align: usize) -> usize { + // SAFETY: `align` has been checked to be a power of 2 above + unsafe { align_offset(p, align) } + } + + const fn ctfe_impl(_: *const T, _: usize) -> usize { + usize::MAX + } + + // SAFETY: + // It is permisseble for `align_offset` to always return `usize::MAX`, + // algorithm correctness can not depend on `align_offset` returning non-max values. + // + // As such the behaviour can't change after replacing `align_offset` with `usize::MAX`, only performance can. + unsafe { intrinsics::const_eval_select((self, align), ctfe_impl, rt_impl) } } } diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 014170604e..8ab72e6aee 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -204,6 +204,7 @@ pub unsafe fn drop_in_place(to_drop: *mut T) { /// assert!(p.is_null()); /// ``` #[inline(always)] +#[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] #[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")] @@ -223,6 +224,7 @@ pub const fn null() -> *const T { /// assert!(p.is_null()); /// ``` #[inline(always)] +#[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] #[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")] diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index adc64cb2bd..f3b2bdfefe 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1092,8 +1092,9 @@ impl *mut T { /// /// [`ptr::swap`]: crate::ptr::swap() #[stable(feature = "pointer_methods", since = "1.26.0")] + #[rustc_const_unstable(feature = "const_swap", issue = "83163")] #[inline(always)] - pub unsafe fn swap(self, with: *mut T) + pub const unsafe fn swap(self, with: *mut T) where T: Sized, { @@ -1141,15 +1142,30 @@ impl *mut T { /// # } } /// ``` #[stable(feature = "align_offset", since = "1.36.0")] - pub fn align_offset(self, align: usize) -> usize + #[rustc_const_unstable(feature = "const_align_offset", issue = "90962")] + pub const fn align_offset(self, align: usize) -> usize where T: Sized, { if !align.is_power_of_two() { panic!("align_offset: align is not a power-of-two"); } - // SAFETY: `align` has been checked to be a power of 2 above - unsafe { align_offset(self, align) } + + fn rt_impl(p: *mut T, align: usize) -> usize { + // SAFETY: `align` has been checked to be a power of 2 above + unsafe { align_offset(p, align) } + } + + const fn ctfe_impl(_: *mut T, _: usize) -> usize { + usize::MAX + } + + // SAFETY: + // It is permisseble for `align_offset` to always return `usize::MAX`, + // algorithm correctness can not depend on `align_offset` returning non-max values. + // + // As such the behaviour can't change after replacing `align_offset` with `usize::MAX`, only performance can. + unsafe { intrinsics::const_eval_select((self, align), ctfe_impl, rt_impl) } } } diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index ee93f00a7f..58110b0680 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -83,6 +83,7 @@ impl NonNull { /// ``` #[stable(feature = "nonnull", since = "1.25.0")] #[rustc_const_stable(feature = "const_nonnull_dangling", since = "1.36.0")] + #[must_use] #[inline] pub const fn dangling() -> Self { // SAFETY: mem::align_of() returns a non-zero usize which is then casted @@ -423,6 +424,7 @@ impl NonNull<[T]> { /// but `let slice = NonNull::from(&x[..]);` would be a better way to write code like this.) #[unstable(feature = "nonnull_slice_from_raw_parts", issue = "71941")] #[rustc_const_unstable(feature = "const_nonnull_slice_from_raw_parts", issue = "71941")] + #[must_use] #[inline] pub const fn slice_from_raw_parts(data: NonNull, len: usize) -> Self { // SAFETY: `data` is a `NonNull` pointer which is necessarily non-null @@ -447,6 +449,7 @@ impl NonNull<[T]> { /// ``` #[unstable(feature = "slice_ptr_len", issue = "71146")] #[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "71146")] + #[must_use] #[inline] pub const fn len(self) -> usize { self.as_ptr().len() @@ -698,7 +701,8 @@ impl hash::Hash for NonNull { } #[unstable(feature = "ptr_internals", issue = "none")] -impl From> for NonNull { +#[rustc_const_unstable(feature = "const_convert", issue = "88674")] +impl const From> for NonNull { #[inline] fn from(unique: Unique) -> Self { // SAFETY: A Unique pointer cannot be null, so the conditions for @@ -708,7 +712,8 @@ impl From> for NonNull { } #[stable(feature = "nonnull", since = "1.25.0")] -impl From<&mut T> for NonNull { +#[rustc_const_unstable(feature = "const_convert", issue = "88674")] +impl const From<&mut T> for NonNull { #[inline] fn from(reference: &mut T) -> Self { // SAFETY: A mutable reference cannot be null. @@ -717,7 +722,8 @@ impl From<&mut T> for NonNull { } #[stable(feature = "nonnull", since = "1.25.0")] -impl From<&T> for NonNull { +#[rustc_const_unstable(feature = "const_convert", issue = "88674")] +impl const From<&T> for NonNull { #[inline] fn from(reference: &T) -> Self { // SAFETY: A reference cannot be null, so the conditions for diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs index 5baceefb50..d650a6f974 100644 --- a/library/core/src/ptr/unique.rs +++ b/library/core/src/ptr/unique.rs @@ -68,6 +68,7 @@ impl Unique { /// a `T`, which means this must not be used as a "not yet initialized" /// sentinel value. Types that lazily allocate must track initialization by /// some other means. + #[must_use] #[inline] pub const fn dangling() -> Self { // SAFETY: mem::align_of() returns a valid, non-null pointer. The @@ -176,7 +177,7 @@ impl fmt::Pointer for Unique { } #[unstable(feature = "ptr_internals", issue = "none")] -impl From<&mut T> for Unique { +impl const From<&mut T> for Unique { #[inline] fn from(reference: &mut T) -> Self { // SAFETY: A mutable reference cannot be null diff --git a/library/core/src/result.rs b/library/core/src/result.rs index dda827900d..8fec2e928a 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -729,7 +729,8 @@ impl Result { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn as_mut(&mut self) -> Result<&mut T, &mut E> { + #[rustc_const_unstable(feature = "const_result", issue = "82814")] + pub const fn as_mut(&mut self) -> Result<&mut T, &mut E> { match *self { Ok(ref mut x) => Ok(x), Err(ref mut x) => Err(x), @@ -1095,19 +1096,17 @@ impl Result { /// # Examples /// /// ``` - /// #![feature(option_result_unwrap_unchecked)] /// let x: Result = Ok(2); /// assert_eq!(unsafe { x.unwrap_unchecked() }, 2); /// ``` /// /// ```no_run - /// #![feature(option_result_unwrap_unchecked)] /// let x: Result = Err("emergency failure"); /// unsafe { x.unwrap_unchecked(); } // Undefined behavior! /// ``` #[inline] #[track_caller] - #[unstable(feature = "option_result_unwrap_unchecked", reason = "newly added", issue = "81383")] + #[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")] pub unsafe fn unwrap_unchecked(self) -> T { debug_assert!(self.is_ok()); match self { @@ -1129,19 +1128,17 @@ impl Result { /// # Examples /// /// ```no_run - /// #![feature(option_result_unwrap_unchecked)] /// let x: Result = Ok(2); /// unsafe { x.unwrap_err_unchecked() }; // Undefined behavior! /// ``` /// /// ``` - /// #![feature(option_result_unwrap_unchecked)] /// let x: Result = Err("emergency failure"); /// assert_eq!(unsafe { x.unwrap_err_unchecked() }, "emergency failure"); /// ``` #[inline] #[track_caller] - #[unstable(feature = "option_result_unwrap_unchecked", reason = "newly added", issue = "81383")] + #[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")] pub unsafe fn unwrap_err_unchecked(self) -> E { debug_assert!(self.is_err()); match self { diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index cbb5627cef..080256f493 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -11,6 +11,7 @@ use crate::ops; impl [u8] { /// Checks if all bytes in this slice are within the ASCII range. #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[must_use] #[inline] pub fn is_ascii(&self) -> bool { is_ascii(self) @@ -21,6 +22,7 @@ impl [u8] { /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`, /// but without allocating and copying temporaries. #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[must_use] #[inline] pub fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool { self.len() == other.len() && iter::zip(self, other).all(|(a, b)| a.eq_ignore_ascii_case(b)) diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index dbf97851b0..ad1d6b8b84 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -839,7 +839,6 @@ impl FusedIterator for SplitInclusiveMut<'_, T, P> where P: FnMut(&T) -> b /// [`rsplit`]: slice::rsplit /// [slices]: slice #[stable(feature = "slice_rsplit", since = "1.27.0")] -#[derive(Clone)] // Is this correct, or does it incorrectly require `T: Clone`? pub struct RSplit<'a, T: 'a, P> where P: FnMut(&T) -> bool, @@ -867,6 +866,17 @@ where } } +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` +#[stable(feature = "slice_rsplit", since = "1.27.0")] +impl Clone for RSplit<'_, T, P> +where + P: Clone + FnMut(&T) -> bool, +{ + fn clone(&self) -> Self { + RSplit { inner: self.inner.clone() } + } +} + #[stable(feature = "slice_rsplit", since = "1.27.0")] impl<'a, T, P> Iterator for RSplit<'a, T, P> where @@ -1714,6 +1724,7 @@ impl<'a, T> ChunksExact<'a, T> { /// Returns the remainder of the original slice that is not going to be /// returned by the iterator. The returned slice has at most `chunk_size-1` /// elements. + #[must_use] #[stable(feature = "chunks_exact", since = "1.31.0")] pub fn remainder(&self) -> &'a [T] { self.rem @@ -2143,6 +2154,7 @@ impl<'a, T, const N: usize> ArrayChunks<'a, T, N> { /// Returns the remainder of the original slice that is not going to be /// returned by the iterator. The returned slice has at most `N-1` /// elements. + #[must_use] #[unstable(feature = "array_chunks", issue = "74985")] pub fn remainder(&self) -> &'a [T] { self.rem @@ -2718,6 +2730,7 @@ impl<'a, T> RChunksExact<'a, T> { /// Returns the remainder of the original slice that is not going to be /// returned by the iterator. The returned slice has at most `chunk_size-1` /// elements. + #[must_use] #[stable(feature = "rchunks", since = "1.31.0")] pub fn remainder(&self) -> &'a [T] { self.rem diff --git a/library/core/src/slice/memchr.rs b/library/core/src/slice/memchr.rs index 08077c700d..6da99055f2 100644 --- a/library/core/src/slice/memchr.rs +++ b/library/core/src/slice/memchr.rs @@ -37,6 +37,7 @@ fn repeat_byte(b: u8) -> usize { } /// Returns the first index matching the byte `x` in `text`. +#[must_use] #[inline] pub fn memchr(x: u8, text: &[u8]) -> Option { // Fast path for small slices @@ -91,6 +92,7 @@ fn memchr_general_case(x: u8, text: &[u8]) -> Option { } /// Returns the last index matching the byte `x` in `text`. +#[must_use] pub fn memrchr(x: u8, text: &[u8]) -> Option { // Scan for a single byte value by reading two `usize` words at a time. // diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index c0e0589d5e..34754cffae 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -553,13 +553,14 @@ impl [T] { /// # Examples /// /// ``` - /// let mut v = ["a", "b", "c", "d"]; - /// v.swap(1, 3); - /// assert!(v == ["a", "d", "c", "b"]); + /// let mut v = ["a", "b", "c", "d", "e"]; + /// v.swap(2, 4); + /// assert!(v == ["a", "b", "e", "d", "c"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_swap", issue = "83163")] #[inline] - pub fn swap(&mut self, a: usize, b: usize) { + pub const fn swap(&mut self, a: usize, b: usize) { let _ = &self[a]; let _ = &self[b]; @@ -595,7 +596,8 @@ impl [T] { /// [`swap`]: slice::swap /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html #[unstable(feature = "slice_swap_unchecked", issue = "88539")] - pub unsafe fn swap_unchecked(&mut self, a: usize, b: usize) { + #[rustc_const_unstable(feature = "const_swap", issue = "83163")] + pub const unsafe fn swap_unchecked(&mut self, a: usize, b: usize) { #[cfg(debug_assertions)] { let _ = &self[a]; @@ -621,100 +623,41 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn reverse(&mut self) { - let mut i: usize = 0; - let ln = self.len(); - - // For very small types, all the individual reads in the normal - // path perform poorly. We can do better, given efficient unaligned - // load/store, by loading a larger chunk and reversing a register. - - // Ideally LLVM would do this for us, as it knows better than we do - // whether unaligned reads are efficient (since that changes between - // different ARM versions, for example) and what the best chunk size - // would be. Unfortunately, as of LLVM 4.0 (2017-05) it only unrolls - // the loop, so we need to do this ourselves. (Hypothesis: reverse - // is troublesome because the sides can be aligned differently -- - // will be, when the length is odd -- so there's no way of emitting - // pre- and postludes to use fully-aligned SIMD in the middle.) - - let fast_unaligned = cfg!(any(target_arch = "x86", target_arch = "x86_64")); - - if fast_unaligned && mem::size_of::() == 1 { - // Use the llvm.bswap intrinsic to reverse u8s in a usize - let chunk = mem::size_of::(); - while i + chunk - 1 < ln / 2 { - // SAFETY: There are several things to check here: - // - // - Note that `chunk` is either 4 or 8 due to the cfg check - // above. So `chunk - 1` is positive. - // - Indexing with index `i` is fine as the loop check guarantees - // `i + chunk - 1 < ln / 2` - // <=> `i < ln / 2 - (chunk - 1) < ln / 2 < ln`. - // - Indexing with index `ln - i - chunk = ln - (i + chunk)` is fine: - // - `i + chunk > 0` is trivially true. - // - The loop check guarantees: - // `i + chunk - 1 < ln / 2` - // <=> `i + chunk ≤ ln / 2 ≤ ln`, thus subtraction does not underflow. - // - The `read_unaligned` and `write_unaligned` calls are fine: - // - `pa` points to index `i` where `i < ln / 2 - (chunk - 1)` - // (see above) and `pb` points to index `ln - i - chunk`, so - // both are at least `chunk` - // many bytes away from the end of `self`. - // - Any initialized memory is valid `usize`. - unsafe { - let ptr = self.as_mut_ptr(); - let pa = ptr.add(i); - let pb = ptr.add(ln - i - chunk); - let va = ptr::read_unaligned(pa as *mut usize); - let vb = ptr::read_unaligned(pb as *mut usize); - ptr::write_unaligned(pa as *mut usize, vb.swap_bytes()); - ptr::write_unaligned(pb as *mut usize, va.swap_bytes()); - } - i += chunk; - } - } + let half_len = self.len() / 2; + let Range { start, end } = self.as_mut_ptr_range(); + + // These slices will skip the middle item for an odd length, + // since that one doesn't need to move. + let (front_half, back_half) = + // SAFETY: Both are subparts of the original slice, so the memory + // range is valid, and they don't overlap because they're each only + // half (or less) of the original slice. + unsafe { + ( + slice::from_raw_parts_mut(start, half_len), + slice::from_raw_parts_mut(end.sub(half_len), half_len), + ) + }; - if fast_unaligned && mem::size_of::() == 2 { - // Use rotate-by-16 to reverse u16s in a u32 - let chunk = mem::size_of::() / 2; - while i + chunk - 1 < ln / 2 { - // SAFETY: An unaligned u32 can be read from `i` if `i + 1 < ln` - // (and obviously `i < ln`), because each element is 2 bytes and - // we're reading 4. - // - // `i + chunk - 1 < ln / 2` # while condition - // `i + 2 - 1 < ln / 2` - // `i + 1 < ln / 2` - // - // Since it's less than the length divided by 2, then it must be - // in bounds. - // - // This also means that the condition `0 < i + chunk <= ln` is - // always respected, ensuring the `pb` pointer can be used - // safely. - unsafe { - let ptr = self.as_mut_ptr(); - let pa = ptr.add(i); - let pb = ptr.add(ln - i - chunk); - let va = ptr::read_unaligned(pa as *mut u32); - let vb = ptr::read_unaligned(pb as *mut u32); - ptr::write_unaligned(pa as *mut u32, vb.rotate_left(16)); - ptr::write_unaligned(pb as *mut u32, va.rotate_left(16)); - } - i += chunk; - } - } + // Introducing a function boundary here means that the two halves + // get `noalias` markers, allowing better optimization as LLVM + // knows that they're disjoint, unlike in the original slice. + revswap(front_half, back_half, half_len); - while i < ln / 2 { - // SAFETY: `i` is inferior to half the length of the slice so - // accessing `i` and `ln - i - 1` is safe (`i` starts at 0 and - // will not go further than `ln / 2 - 1`). - // The resulting pointers `pa` and `pb` are therefore valid and - // aligned, and can be read from and written to. - unsafe { - self.swap_unchecked(i, ln - i - 1); + #[inline] + fn revswap(a: &mut [T], b: &mut [T], n: usize) { + debug_assert_eq!(a.len(), n); + debug_assert_eq!(b.len(), n); + + // Because this function is first compiled in isolation, + // this check tells LLVM that the indexing below is + // in-bounds. Then after inlining -- once the actual + // lengths of the slices are known -- it's removed. + let (a, b) = (&mut a[..n], &mut b[..n]); + + for i in 0..n { + mem::swap(&mut a[i], &mut b[n - 1 - i]); } - i += 1; } } @@ -1665,6 +1608,80 @@ impl [T] { unsafe { (from_raw_parts_mut(ptr, mid), from_raw_parts_mut(ptr.add(mid), len - mid)) } } + /// Divides one slice into an array and a remainder slice at an index. + /// + /// The array will contain all indices from `[0, N)` (excluding + /// the index `N` itself) and the slice will contain all + /// indices from `[N, len)` (excluding the index `len` itself). + /// + /// # Panics + /// + /// Panics if `N > len`. + /// + /// # Examples + /// + /// ``` + /// #![feature(split_array)] + /// + /// let v = &[1, 2, 3, 4, 5, 6][..]; + /// + /// { + /// let (left, right) = v.split_array_ref::<0>(); + /// assert_eq!(left, &[]); + /// assert_eq!(right, [1, 2, 3, 4, 5, 6]); + /// } + /// + /// { + /// let (left, right) = v.split_array_ref::<2>(); + /// assert_eq!(left, &[1, 2]); + /// assert_eq!(right, [3, 4, 5, 6]); + /// } + /// + /// { + /// let (left, right) = v.split_array_ref::<6>(); + /// assert_eq!(left, &[1, 2, 3, 4, 5, 6]); + /// assert_eq!(right, []); + /// } + /// ``` + #[unstable(feature = "split_array", reason = "new API", issue = "90091")] + #[inline] + pub fn split_array_ref(&self) -> (&[T; N], &[T]) { + let (a, b) = self.split_at(N); + // SAFETY: a points to [T; N]? Yes it's [T] of length N (checked by split_at) + unsafe { (&*(a.as_ptr() as *const [T; N]), b) } + } + + /// Divides one mutable slice into an array and a remainder slice at an index. + /// + /// The array will contain all indices from `[0, N)` (excluding + /// the index `N` itself) and the slice will contain all + /// indices from `[N, len)` (excluding the index `len` itself). + /// + /// # Panics + /// + /// Panics if `N > len`. + /// + /// # Examples + /// + /// ``` + /// #![feature(split_array)] + /// + /// let mut v = &mut [1, 0, 3, 0, 5, 6][..]; + /// let (left, right) = v.split_array_mut::<2>(); + /// assert_eq!(left, &mut [1, 0]); + /// assert_eq!(right, [3, 0, 5, 6]); + /// left[1] = 2; + /// right[1] = 4; + /// assert_eq!(v, [1, 2, 3, 4, 5, 6]); + /// ``` + #[unstable(feature = "split_array", reason = "new API", issue = "90091")] + #[inline] + pub fn split_array_mut(&mut self) -> (&mut [T; N], &mut [T]) { + let (a, b) = self.split_at_mut(N); + // SAFETY: a points to [T; N]? Yes it's [T] of length N (checked by split_at_mut) + unsafe { (&mut *(a.as_mut_ptr() as *mut [T; N]), b) } + } + /// Returns an iterator over subslices separated by elements that match /// `pred`. The matched element is not contained in the subslices. /// @@ -2953,9 +2970,6 @@ impl [T] { /// /// The length of `src` must be the same as `self`. /// - /// If `T` implements `Copy`, it can be more performant to use - /// [`copy_from_slice`]. - /// /// # Panics /// /// This function will panic if the two slices have different lengths. @@ -3005,6 +3019,7 @@ impl [T] { /// [`copy_from_slice`]: slice::copy_from_slice /// [`split_at_mut`]: slice::split_at_mut #[stable(feature = "clone_from_slice", since = "1.7.0")] + #[track_caller] pub fn clone_from_slice(&mut self, src: &[T]) where T: Clone, @@ -3068,6 +3083,7 @@ impl [T] { /// [`split_at_mut`]: slice::split_at_mut #[doc(alias = "memcpy")] #[stable(feature = "copy_from_slice", since = "1.9.0")] + #[track_caller] pub fn copy_from_slice(&mut self, src: &[T]) where T: Copy, @@ -3188,6 +3204,7 @@ impl [T] { /// /// [`split_at_mut`]: slice::split_at_mut #[stable(feature = "swap_with_slice", since = "1.27.0")] + #[track_caller] pub fn swap_with_slice(&mut self, other: &mut [T]) { assert!(self.len() == other.len(), "destination and source slices have different lengths"); // SAFETY: `self` is valid for `self.len()` elements by definition, and `src` was @@ -3510,6 +3527,7 @@ impl CloneFromSpec for [T] where T: Clone, { + #[track_caller] default fn spec_clone_from(&mut self, src: &[T]) { assert!(self.len() == src.len(), "destination and source slices have different lengths"); // NOTE: We need to explicitly slice them to the same length @@ -3527,6 +3545,7 @@ impl CloneFromSpec for [T] where T: Copy, { + #[track_caller] fn spec_clone_from(&mut self, src: &[T]) { self.copy_from_slice(src); } diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index eda50dc287..81bb16d540 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -1,8 +1,6 @@ //! Free functions to create `&[T]` and `&mut [T]`. use crate::array; -use crate::intrinsics::is_aligned_and_not_null; -use crate::mem; use crate::ptr; /// Forms a slice from a pointer and a length. @@ -85,12 +83,10 @@ use crate::ptr; /// [`NonNull::dangling()`]: ptr::NonNull::dangling #[inline] #[stable(feature = "rust1", since = "1.0.0")] -pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { - debug_assert!(is_aligned_and_not_null(data), "attempt to create unaligned or null slice"); - debug_assert!( - mem::size_of::().saturating_mul(len) <= isize::MAX as usize, - "attempt to create slice covering at least half the address space" - ); +#[rustc_const_unstable(feature = "const_slice_from_raw_parts", issue = "67456")] +pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { + debug_check_data_len(data, len); + // SAFETY: the caller must uphold the safety contract for `from_raw_parts`. unsafe { &*ptr::slice_from_raw_parts(data, len) } } @@ -126,24 +122,58 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { /// [`NonNull::dangling()`]: ptr::NonNull::dangling #[inline] #[stable(feature = "rust1", since = "1.0.0")] -pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] { - debug_assert!(is_aligned_and_not_null(data), "attempt to create unaligned or null slice"); - debug_assert!( - mem::size_of::().saturating_mul(len) <= isize::MAX as usize, - "attempt to create slice covering at least half the address space" - ); +#[rustc_const_unstable(feature = "const_slice_from_raw_parts", issue = "67456")] +pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] { + debug_check_data_len(data as _, len); + // SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`. unsafe { &mut *ptr::slice_from_raw_parts_mut(data, len) } } +// In debug builds checks that `data` pointer is aligned and non-null and that slice with given `len` would cover less than half the address space +#[cfg(all(not(bootstrap), debug_assertions))] +#[unstable(feature = "const_slice_from_raw_parts", issue = "67456")] +#[rustc_const_unstable(feature = "const_slice_from_raw_parts", issue = "67456")] +const fn debug_check_data_len(data: *const T, len: usize) { + fn rt_check(data: *const T) { + use crate::intrinsics::is_aligned_and_not_null; + + assert!(is_aligned_and_not_null(data), "attempt to create unaligned or null slice"); + } + + const fn noop(_: *const T) {} + + // SAFETY: + // + // `rt_check` is just a debug assert to hint users that they are causing UB, + // it is not required for safety (the safety must be guatanteed by + // the `from_raw_parts[_mut]` caller). + // + // Since the checks are not required, we ignore them in CTFE as they can't + // be done there (alignment does not make much sense there). + unsafe { + crate::intrinsics::const_eval_select((data,), noop, rt_check); + } + + assert!( + crate::mem::size_of::().saturating_mul(len) <= isize::MAX as usize, + "attempt to create slice covering at least half the address space" + ); +} + +#[cfg(not(all(not(bootstrap), debug_assertions)))] +const fn debug_check_data_len(_data: *const T, _len: usize) {} + /// Converts a reference to T into a slice of length 1 (without copying). #[stable(feature = "from_ref", since = "1.28.0")] -pub fn from_ref(s: &T) -> &[T] { +#[rustc_const_unstable(feature = "const_slice_from_ref", issue = "90206")] +pub const fn from_ref(s: &T) -> &[T] { array::from_ref(s) } /// Converts a reference to T into a slice of length 1 (without copying). #[stable(feature = "from_ref", since = "1.28.0")] -pub fn from_mut(s: &mut T) -> &mut [T] { +#[rustc_const_unstable(feature = "const_slice_from_ref", issue = "90206")] +pub const fn from_mut(s: &mut T) -> &mut [T] { array::from_mut(s) } diff --git a/library/core/src/str/converts.rs b/library/core/src/str/converts.rs index ed9f49f159..ef26cbfb64 100644 --- a/library/core/src/str/converts.rs +++ b/library/core/src/str/converts.rs @@ -82,10 +82,16 @@ use super::Utf8Error; /// assert_eq!("💖", sparkle_heart); /// ``` #[stable(feature = "rust1", since = "1.0.0")] -pub fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> { - run_utf8_validation(v)?; - // SAFETY: Just ran validation. - Ok(unsafe { from_utf8_unchecked(v) }) +#[rustc_const_unstable(feature = "const_str_from_utf8", issue = "91006")] +pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> { + // This should use `?` again, once it's `const` + match run_utf8_validation(v) { + Ok(_) => { + // SAFETY: validation succeeded. + Ok(unsafe { from_utf8_unchecked(v) }) + } + Err(err) => Err(err), + } } /// Converts a mutable slice of bytes to a mutable string slice. @@ -119,10 +125,16 @@ pub fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> { /// See the docs for [`Utf8Error`] for more details on the kinds of /// errors that can be returned. #[stable(feature = "str_mut_extras", since = "1.20.0")] -pub fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> { - run_utf8_validation(v)?; - // SAFETY: Just ran validation. - Ok(unsafe { from_utf8_unchecked_mut(v) }) +#[rustc_const_unstable(feature = "const_str_from_utf8", issue = "91006")] +pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> { + // This should use `?` again, once it's `const` + match run_utf8_validation(v) { + Ok(_) => { + // SAFETY: validation succeeded. + Ok(unsafe { from_utf8_unchecked_mut(v) }) + } + Err(err) => Err(err), + } } /// Converts a slice of bytes to a string slice without checking @@ -184,7 +196,8 @@ pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str { #[inline] #[must_use] #[stable(feature = "str_mut_extras", since = "1.20.0")] -pub unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str { +#[rustc_const_unstable(feature = "const_str_from_utf8_unchecked_mut", issue = "91005")] +pub const unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str { // SAFETY: the caller must guarantee that the bytes `v` // are valid UTF-8, thus the cast to `*mut str` is safe. // Also, the pointer dereference is safe because that pointer diff --git a/library/core/src/str/error.rs b/library/core/src/str/error.rs index aa735a14cb..a127dd57ee 100644 --- a/library/core/src/str/error.rs +++ b/library/core/src/str/error.rs @@ -72,8 +72,10 @@ impl Utf8Error { /// assert_eq!(1, error.valid_up_to()); /// ``` #[stable(feature = "utf8_error", since = "1.5.0")] + #[rustc_const_unstable(feature = "const_str_from_utf8", issue = "91006")] + #[must_use] #[inline] - pub fn valid_up_to(&self) -> usize { + pub const fn valid_up_to(&self) -> usize { self.valid_up_to } @@ -93,9 +95,15 @@ impl Utf8Error { /// /// [U+FFFD]: ../../std/char/constant.REPLACEMENT_CHARACTER.html #[stable(feature = "utf8_error_error_len", since = "1.20.0")] + #[rustc_const_unstable(feature = "const_str_from_utf8", issue = "91006")] + #[must_use] #[inline] - pub fn error_len(&self) -> Option { - self.error_len.map(|len| len as usize) + pub const fn error_len(&self) -> Option { + // This should become `map` again, once it's `const` + match self.error_len { + Some(len) => Some(len as usize), + None => None, + } } } diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index 94cb81e9d4..4841044671 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -27,6 +27,7 @@ use super::{IsAsciiWhitespace, IsNotEmpty, IsWhitespace}; /// [`char`]: prim@char /// [`chars`]: str::chars #[derive(Clone)] +#[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] pub struct Chars<'a> { pub(super) iter: slice::Iter<'a, u8>, @@ -38,10 +39,9 @@ impl<'a> Iterator for Chars<'a> { #[inline] fn next(&mut self) -> Option { - next_code_point(&mut self.iter).map(|ch| { - // SAFETY: `str` invariant says `ch` is a valid Unicode Scalar Value. - unsafe { char::from_u32_unchecked(ch) } - }) + // SAFETY: `str` invariant says `self.iter` is a valid UTF-8 string and + // the resulting `ch` is a valid Unicode Scalar Value. + unsafe { next_code_point(&mut self.iter).map(|ch| char::from_u32_unchecked(ch)) } } #[inline] @@ -80,10 +80,9 @@ impl fmt::Debug for Chars<'_> { impl<'a> DoubleEndedIterator for Chars<'a> { #[inline] fn next_back(&mut self) -> Option { - next_code_point_reverse(&mut self.iter).map(|ch| { - // SAFETY: `str` invariant says `ch` is a valid Unicode Scalar Value. - unsafe { char::from_u32_unchecked(ch) } - }) + // SAFETY: `str` invariant says `self.iter` is a valid UTF-8 string and + // the resulting `ch` is a valid Unicode Scalar Value. + unsafe { next_code_point_reverse(&mut self.iter).map(|ch| char::from_u32_unchecked(ch)) } } } @@ -125,6 +124,7 @@ impl<'a> Chars<'a> { /// [`char`]: prim@char /// [`char_indices`]: str::char_indices #[derive(Clone, Debug)] +#[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] pub struct CharIndices<'a> { pub(super) front_offset: usize, @@ -211,6 +211,7 @@ impl<'a> CharIndices<'a> { /// assert_eq!(chars.next(), None); /// ``` #[inline] + #[must_use] #[unstable(feature = "char_indices_offset", issue = "83871")] pub fn offset(&self) -> usize { self.front_offset @@ -223,6 +224,7 @@ impl<'a> CharIndices<'a> { /// See its documentation for more. /// /// [`bytes`]: str::bytes +#[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] #[derive(Clone, Debug)] pub struct Bytes<'a>(pub(super) Copied>); @@ -1089,6 +1091,7 @@ generate_pattern_iterators! { /// /// [`lines`]: str::lines #[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] #[derive(Clone, Debug)] pub struct Lines<'a>(pub(super) Map, LinesAnyMap>); @@ -1128,6 +1131,7 @@ impl FusedIterator for Lines<'_> {} /// [`lines_any`]: str::lines_any #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated(since = "1.4.0", reason = "use lines()/Lines instead now")] +#[must_use = "iterators are lazy and do nothing unless consumed"] #[derive(Clone, Debug)] #[allow(deprecated)] pub struct LinesAny<'a>(pub(super) Lines<'a>); diff --git a/library/core/src/str/lossy.rs b/library/core/src/str/lossy.rs index d3c9d21c3c..6c21a5e802 100644 --- a/library/core/src/str/lossy.rs +++ b/library/core/src/str/lossy.rs @@ -29,6 +29,7 @@ impl Utf8Lossy { } /// Iterator over lossy UTF-8 string +#[must_use = "iterators are lazy and do nothing unless consumed"] #[unstable(feature = "str_internals", issue = "none")] #[allow(missing_debug_implementations)] pub struct Utf8LossyChunksIter<'a> { diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 607a0179ff..cd5ed35be7 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -140,6 +140,7 @@ impl str { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_str_len", since = "1.39.0")] + #[must_use] #[inline] pub const fn len(&self) -> usize { self.as_bytes().len() @@ -158,9 +159,10 @@ impl str { /// let s = "not empty"; /// assert!(!s.is_empty()); /// ``` - #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_str_is_empty", since = "1.39.0")] + #[must_use] + #[inline] pub const fn is_empty(&self) -> bool { self.len() == 0 } @@ -498,6 +500,7 @@ impl str { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated(since = "1.29.0", reason = "use `get_unchecked(begin..end)` instead")] + #[must_use] #[inline] pub unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str { // SAFETY: the caller must uphold the safety contract for `get_unchecked`; @@ -570,6 +573,7 @@ impl str { /// assert_eq!(" Martin-Löf", last); /// ``` #[inline] + #[must_use] #[stable(feature = "str_split_at", since = "1.4.0")] pub fn split_at(&self, mid: usize) -> (&str, &str) { // is_char_boundary checks that the index is in [0, .len()] @@ -613,6 +617,7 @@ impl str { /// assert_eq!("PER Martin-Löf", s); /// ``` #[inline] + #[must_use] #[stable(feature = "str_split_at", since = "1.4.0")] pub fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str) { // is_char_boundary checks that the index is in [0, .len()] @@ -1663,7 +1668,7 @@ impl str { /// If the pattern allows a reverse search but its results might differ /// from a forward search, the [`rmatch_indices`] method can be used. /// - /// [`rmatch_indices`]: str::match_indices + /// [`rmatch_indices`]: str::rmatch_indices /// /// # Examples /// @@ -2255,6 +2260,7 @@ impl str { /// assert!(!non_ascii.is_ascii()); /// ``` #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[must_use] #[inline] pub fn is_ascii(&self) -> bool { // We can treat each byte as character here: all multibyte characters @@ -2276,6 +2282,7 @@ impl str { /// assert!(!"Ferrös".eq_ignore_ascii_case("FERRÖS")); /// ``` #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[must_use] #[inline] pub fn eq_ignore_ascii_case(&self, other: &str) -> bool { self.as_bytes().eq_ignore_ascii_case(other.as_bytes()) diff --git a/library/core/src/str/pattern.rs b/library/core/src/str/pattern.rs index 55ac1aa765..031fb8e8b2 100644 --- a/library/core/src/str/pattern.rs +++ b/library/core/src/str/pattern.rs @@ -22,6 +22,8 @@ //! assert_eq!(s.find("you"), Some(4)); //! // char pattern //! assert_eq!(s.find('n'), Some(2)); +//! // array of chars pattern +//! assert_eq!(s.find(&['a', 'e', 'i', 'o', 'u']), Some(1)); //! // slice of chars pattern //! assert_eq!(s.find(&['a', 'e', 'i', 'o', 'u'][..]), Some(1)); //! // closure pattern @@ -79,6 +81,11 @@ use crate::slice::memchr; /// assert_eq!("abaaa".find('b'), Some(1)); /// assert_eq!("abaaa".find('c'), None); /// +/// // &[char; N] +/// assert_eq!("ab".find(&['b', 'a']), Some(0)); +/// assert_eq!("abaaa".find(&['a', 'z']), Some(0)); +/// assert_eq!("abaaa".find(&['c', 'd']), None); +/// /// // &[char] /// assert_eq!("ab".find(&['b', 'a'][..]), Some(0)); /// assert_eq!("abaaa".find(&['a', 'z'][..]), Some(0)); @@ -601,6 +608,20 @@ where } } +impl MultiCharEq for [char; N] { + #[inline] + fn matches(&mut self, c: char) -> bool { + self.iter().any(|&m| m == c) + } +} + +impl MultiCharEq for &[char; N] { + #[inline] + fn matches(&mut self, c: char) -> bool { + self.iter().any(|&m| m == c) + } +} + impl MultiCharEq for &[char] { #[inline] fn matches(&mut self, c: char) -> bool { @@ -752,6 +773,58 @@ macro_rules! searcher_methods { }; } +/// Associated type for `<[char; N] as Pattern<'a>>::Searcher`. +#[derive(Clone, Debug)] +pub struct CharArraySearcher<'a, const N: usize>( + as Pattern<'a>>::Searcher, +); + +/// Associated type for `<&[char; N] as Pattern<'a>>::Searcher`. +#[derive(Clone, Debug)] +pub struct CharArrayRefSearcher<'a, 'b, const N: usize>( + as Pattern<'a>>::Searcher, +); + +/// Searches for chars that are equal to any of the [`char`]s in the array. +/// +/// # Examples +/// +/// ``` +/// assert_eq!("Hello world".find(['l', 'l']), Some(2)); +/// assert_eq!("Hello world".find(['l', 'l']), Some(2)); +/// ``` +impl<'a, const N: usize> Pattern<'a> for [char; N] { + pattern_methods!(CharArraySearcher<'a, N>, MultiCharEqPattern, CharArraySearcher); +} + +unsafe impl<'a, const N: usize> Searcher<'a> for CharArraySearcher<'a, N> { + searcher_methods!(forward); +} + +unsafe impl<'a, const N: usize> ReverseSearcher<'a> for CharArraySearcher<'a, N> { + searcher_methods!(reverse); +} + +/// Searches for chars that are equal to any of the [`char`]s in the array. +/// +/// # Examples +/// +/// ``` +/// assert_eq!("Hello world".find(&['l', 'l']), Some(2)); +/// assert_eq!("Hello world".find(&['l', 'l']), Some(2)); +/// ``` +impl<'a, 'b, const N: usize> Pattern<'a> for &'b [char; N] { + pattern_methods!(CharArrayRefSearcher<'a, 'b, N>, MultiCharEqPattern, CharArrayRefSearcher); +} + +unsafe impl<'a, 'b, const N: usize> Searcher<'a> for CharArrayRefSearcher<'a, 'b, N> { + searcher_methods!(forward); +} + +unsafe impl<'a, 'b, const N: usize> ReverseSearcher<'a> for CharArrayRefSearcher<'a, 'b, N> { + searcher_methods!(reverse); +} + ///////////////////////////////////////////////////////////////////////////// // Impl for &[char] ///////////////////////////////////////////////////////////////////////////// diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs index e225776bc6..9526762474 100644 --- a/library/core/src/str/traits.rs +++ b/library/core/src/str/traits.rs @@ -234,7 +234,7 @@ unsafe impl SliceIndex for ops::Range { /// Implements substring slicing with syntax `&self[.. end]` or `&mut /// self[.. end]`. /// -/// Returns a slice of the given string from the byte range [`0`, `end`). +/// Returns a slice of the given string from the byte range \[0, `end`). /// Equivalent to `&self[0 .. end]` or `&mut self[0 .. end]`. /// /// This operation is *O*(1). @@ -304,9 +304,8 @@ unsafe impl SliceIndex for ops::RangeTo { /// Implements substring slicing with syntax `&self[begin ..]` or `&mut /// self[begin ..]`. /// -/// Returns a slice of the given string from the byte range [`begin`, -/// `len`). Equivalent to `&self[begin .. len]` or `&mut self[begin .. -/// len]`. +/// Returns a slice of the given string from the byte range \[`begin`, `len`). +/// Equivalent to `&self[begin .. len]` or `&mut self[begin .. len]`. /// /// This operation is *O*(1). /// @@ -433,7 +432,7 @@ unsafe impl SliceIndex for ops::RangeInclusive { /// Implements substring slicing with syntax `&self[..= end]` or `&mut /// self[..= end]`. /// -/// Returns a slice of the given string from the byte range [0, `end`]. +/// Returns a slice of the given string from the byte range \[0, `end`\]. /// Equivalent to `&self [0 .. end + 1]`, except if `end` has the maximum /// value for `usize`. /// diff --git a/library/core/src/str/validations.rs b/library/core/src/str/validations.rs index 093c9c37b6..b2ea86d699 100644 --- a/library/core/src/str/validations.rs +++ b/library/core/src/str/validations.rs @@ -8,36 +8,32 @@ use super::Utf8Error; /// The first byte is special, only want bottom 5 bits for width 2, 4 bits /// for width 3, and 3 bits for width 4. #[inline] -fn utf8_first_byte(byte: u8, width: u32) -> u32 { +const fn utf8_first_byte(byte: u8, width: u32) -> u32 { (byte & (0x7F >> width)) as u32 } /// Returns the value of `ch` updated with continuation byte `byte`. #[inline] -fn utf8_acc_cont_byte(ch: u32, byte: u8) -> u32 { +const fn utf8_acc_cont_byte(ch: u32, byte: u8) -> u32 { (ch << 6) | (byte & CONT_MASK) as u32 } /// Checks whether the byte is a UTF-8 continuation byte (i.e., starts with the /// bits `10`). #[inline] -pub(super) fn utf8_is_cont_byte(byte: u8) -> bool { +pub(super) const fn utf8_is_cont_byte(byte: u8) -> bool { (byte as i8) < -64 } -#[inline] -fn unwrap_or_0(opt: Option<&u8>) -> u8 { - match opt { - Some(&byte) => byte, - None => 0, - } -} - /// Reads the next code point out of a byte iterator (assuming a /// UTF-8-like encoding). +/// +/// # Safety +/// +/// `bytes` must produce a valid UTF-8-like (UTF-8 or WTF-8) string #[unstable(feature = "str_internals", issue = "none")] #[inline] -pub fn next_code_point<'a, I: Iterator>(bytes: &mut I) -> Option { +pub unsafe fn next_code_point<'a, I: Iterator>(bytes: &mut I) -> Option { // Decode UTF-8 let x = *bytes.next()?; if x < 128 { @@ -48,18 +44,24 @@ pub fn next_code_point<'a, I: Iterator>(bytes: &mut I) -> Option< // Decode from a byte combination out of: [[[x y] z] w] // NOTE: Performance is sensitive to the exact formulation here let init = utf8_first_byte(x, 2); - let y = unwrap_or_0(bytes.next()); + // SAFETY: `bytes` produces an UTF-8-like string, + // so the iterator must produce a value here. + let y = unsafe { *bytes.next().unwrap_unchecked() }; let mut ch = utf8_acc_cont_byte(init, y); if x >= 0xE0 { // [[x y z] w] case // 5th bit in 0xE0 .. 0xEF is always clear, so `init` is still valid - let z = unwrap_or_0(bytes.next()); + // SAFETY: `bytes` produces an UTF-8-like string, + // so the iterator must produce a value here. + let z = unsafe { *bytes.next().unwrap_unchecked() }; let y_z = utf8_acc_cont_byte((y & CONT_MASK) as u32, z); ch = init << 12 | y_z; if x >= 0xF0 { // [x y z w] case // use only the lower 3 bits of `init` - let w = unwrap_or_0(bytes.next()); + // SAFETY: `bytes` produces an UTF-8-like string, + // so the iterator must produce a value here. + let w = unsafe { *bytes.next().unwrap_unchecked() }; ch = (init & 7) << 18 | utf8_acc_cont_byte(y_z, w); } } @@ -69,8 +71,12 @@ pub fn next_code_point<'a, I: Iterator>(bytes: &mut I) -> Option< /// Reads the last code point out of a byte iterator (assuming a /// UTF-8-like encoding). +/// +/// # Safety +/// +/// `bytes` must produce a valid UTF-8-like (UTF-8 or WTF-8) string #[inline] -pub(super) fn next_code_point_reverse<'a, I>(bytes: &mut I) -> Option +pub(super) unsafe fn next_code_point_reverse<'a, I>(bytes: &mut I) -> Option where I: DoubleEndedIterator, { @@ -83,13 +89,19 @@ where // Multibyte case follows // Decode from a byte combination out of: [x [y [z w]]] let mut ch; - let z = unwrap_or_0(bytes.next_back()); + // SAFETY: `bytes` produces an UTF-8-like string, + // so the iterator must produce a value here. + let z = unsafe { *bytes.next_back().unwrap_unchecked() }; ch = utf8_first_byte(z, 2); if utf8_is_cont_byte(z) { - let y = unwrap_or_0(bytes.next_back()); + // SAFETY: `bytes` produces an UTF-8-like string, + // so the iterator must produce a value here. + let y = unsafe { *bytes.next_back().unwrap_unchecked() }; ch = utf8_first_byte(y, 3); if utf8_is_cont_byte(y) { - let x = unwrap_or_0(bytes.next_back()); + // SAFETY: `bytes` produces an UTF-8-like string, + // so the iterator must produce a value here. + let x = unsafe { *bytes.next_back().unwrap_unchecked() }; ch = utf8_first_byte(x, 4); ch = utf8_acc_cont_byte(ch, y); } @@ -105,14 +117,15 @@ const NONASCII_MASK: usize = 0x80808080_80808080u64 as usize; /// Returns `true` if any byte in the word `x` is nonascii (>= 128). #[inline] -fn contains_nonascii(x: usize) -> bool { +const fn contains_nonascii(x: usize) -> bool { (x & NONASCII_MASK) != 0 } /// Walks through `v` checking that it's a valid UTF-8 sequence, /// returning `Ok(())` in that case, or, if it is invalid, `Err(err)`. #[inline(always)] -pub(super) fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> { +#[rustc_const_unstable(feature = "str_internals", issue = "none")] +pub(super) const fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> { let mut index = 0; let len = v.len(); @@ -142,7 +155,7 @@ pub(super) fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> { let first = v[index]; if first >= 128 { - let w = UTF8_CHAR_WIDTH[first as usize]; + let w = utf8_char_width(first); // 2-byte encoding is for codepoints \u{0080} to \u{07ff} // first C2 80 last DF BF // 3-byte encoding is for codepoints \u{0800} to \u{ffff} @@ -210,7 +223,7 @@ pub(super) fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> { // break if there is a nonascii byte let zu = contains_nonascii(*block); let zv = contains_nonascii(*block.offset(1)); - if zu | zv { + if zu || zv { break; } } @@ -230,29 +243,31 @@ pub(super) fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> { } // https://tools.ietf.org/html/rfc3629 -static UTF8_CHAR_WIDTH: [u8; 256] = [ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, // 0x1F - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, // 0x3F - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, // 0x5F - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, // 0x7F - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, // 0x9F - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, // 0xBF - 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, // 0xDF - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xEF - 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xFF +const UTF8_CHAR_WIDTH: &[u8; 256] = &[ + // 1 2 3 4 5 6 7 8 9 A B C D E F + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B + 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // D + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // E + 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // F ]; /// Given a first byte, determines how many bytes are in this UTF-8 character. #[unstable(feature = "str_internals", issue = "none")] +#[must_use] #[inline] -pub fn utf8_char_width(b: u8) -> usize { +pub const fn utf8_char_width(b: u8) -> usize { UTF8_CHAR_WIDTH[b as usize] as usize } diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 1247f33087..1dd3b2d8e3 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -1273,7 +1273,8 @@ impl AtomicPtr { #[cfg(target_has_atomic_load_store = "8")] #[stable(feature = "atomic_bool_from", since = "1.24.0")] -impl From for AtomicBool { +#[rustc_const_unstable(feature = "const_convert", issue = "88674")] +impl const From for AtomicBool { /// Converts a `bool` into an `AtomicBool`. /// /// # Examples @@ -1291,7 +1292,8 @@ impl From for AtomicBool { #[cfg(target_has_atomic_load_store = "ptr")] #[stable(feature = "atomic_from", since = "1.23.0")] -impl From<*mut T> for AtomicPtr { +#[rustc_const_unstable(feature = "const_convert", issue = "88674")] +impl const From<*mut T> for AtomicPtr { #[inline] fn from(p: *mut T) -> Self { Self::new(p) @@ -1363,7 +1365,8 @@ macro_rules! atomic_int { } #[$stable_from] - impl From<$int_type> for $atomic_type { + #[rustc_const_unstable(feature = "const_num_from_num", issue = "87852")] + impl const From<$int_type> for $atomic_type { #[doc = concat!("Converts an `", stringify!($int_type), "` into an `", stringify!($atomic_type), "`.")] #[inline] fn from(v: $int_type) -> Self { Self::new(v) } diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs index 80e1458dc9..72a030617a 100644 --- a/library/core/src/task/poll.rs +++ b/library/core/src/task/poll.rs @@ -241,7 +241,8 @@ impl Poll>> { } #[stable(feature = "futures_api", since = "1.36.0")] -impl From for Poll { +#[rustc_const_unstable(feature = "const_convert", issue = "88674")] +impl const From for Poll { /// Convert to a `Ready` variant. /// /// # Example diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 620bff5387..6cba781c2e 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -167,6 +167,7 @@ impl<'a> Context<'a> { /// Returns a reference to the `Waker` for the current task. #[stable(feature = "futures_api", since = "1.36.0")] + #[must_use] #[inline] pub fn waker(&self) -> &'a Waker { &self.waker @@ -242,6 +243,7 @@ impl Waker { /// /// This function is primarily used for optimization purposes. #[inline] + #[must_use] #[stable(feature = "futures_api", since = "1.36.0")] pub fn will_wake(&self, other: &Waker) -> bool { self.waker == other.waker diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 5a74f39e8b..5efa04f7e5 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -180,8 +180,9 @@ impl Duration { /// ``` #[stable(feature = "duration", since = "1.3.0")] #[inline] - #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] #[must_use] + #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_panic))] pub const fn new(secs: u64, nanos: u32) -> Duration { let secs = match secs.checked_add((nanos / NANOS_PER_SEC) as u64) { Some(secs) => secs, @@ -357,6 +358,7 @@ impl Duration { /// ``` #[stable(feature = "duration_extras", since = "1.27.0")] #[rustc_const_stable(feature = "duration_extras", since = "1.32.0")] + #[must_use] #[inline] pub const fn subsec_millis(&self) -> u32 { self.nanos / NANOS_PER_MILLI @@ -379,6 +381,7 @@ impl Duration { /// ``` #[stable(feature = "duration_extras", since = "1.27.0")] #[rustc_const_stable(feature = "duration_extras", since = "1.32.0")] + #[must_use] #[inline] pub const fn subsec_micros(&self) -> u32 { self.nanos / NANOS_PER_MICRO @@ -401,6 +404,7 @@ impl Duration { /// ``` #[stable(feature = "duration", since = "1.3.0")] #[rustc_const_stable(feature = "duration", since = "1.32.0")] + #[must_use] #[inline] pub const fn subsec_nanos(&self) -> u32 { self.nanos @@ -477,7 +481,8 @@ impl Duration { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] + #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_panic))] pub const fn checked_add(self, rhs: Duration) -> Option { if let Some(mut secs) = self.secs.checked_add(rhs.secs) { let mut nanos = self.nanos + rhs.nanos; @@ -512,7 +517,7 @@ impl Duration { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] + #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] pub const fn saturating_add(self, rhs: Duration) -> Duration { match self.checked_add(rhs) { Some(res) => res, @@ -537,7 +542,8 @@ impl Duration { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] + #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_panic))] pub const fn checked_sub(self, rhs: Duration) -> Option { if let Some(mut secs) = self.secs.checked_sub(rhs.secs) { let nanos = if self.nanos >= rhs.nanos { @@ -570,7 +576,7 @@ impl Duration { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] + #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] pub const fn saturating_sub(self, rhs: Duration) -> Duration { match self.checked_sub(rhs) { Some(res) => res, @@ -595,7 +601,8 @@ impl Duration { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] + #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_panic))] pub const fn checked_mul(self, rhs: u32) -> Option { // Multiply nanoseconds as u64, because it cannot overflow that way. let total_nanos = self.nanos as u64 * rhs as u64; @@ -626,7 +633,7 @@ impl Duration { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] + #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] pub const fn saturating_mul(self, rhs: u32) -> Duration { match self.checked_mul(rhs) { Some(res) => res, @@ -652,7 +659,8 @@ impl Duration { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] + #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_panic))] pub const fn checked_div(self, rhs: u32) -> Option { if rhs != 0 { let secs = self.secs / (rhs as u64); @@ -680,7 +688,7 @@ impl Duration { #[stable(feature = "duration_float", since = "1.38.0")] #[must_use] #[inline] - #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] + #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] pub const fn as_secs_f64(&self) -> f64 { (self.secs as f64) + (self.nanos as f64) / (NANOS_PER_SEC as f64) } @@ -699,7 +707,7 @@ impl Duration { #[stable(feature = "duration_float", since = "1.38.0")] #[must_use] #[inline] - #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] + #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] pub const fn as_secs_f32(&self) -> f32 { (self.secs as f32) + (self.nanos as f32) / (NANOS_PER_SEC as f32) } @@ -720,11 +728,11 @@ impl Duration { #[stable(feature = "duration_float", since = "1.38.0")] #[must_use] #[inline] - #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] + #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] pub const fn from_secs_f64(secs: f64) -> Duration { match Duration::try_from_secs_f64(secs) { Ok(v) => v, - Err(e) => crate::panicking::panic(e.description()), + Err(e) => panic!("{}", e.description()), } } @@ -737,7 +745,6 @@ impl Duration { /// # Examples /// ``` /// #![feature(duration_checked_float)] - /// /// use std::time::Duration; /// /// let dur = Duration::try_from_secs_f64(2.7); @@ -756,7 +763,7 @@ impl Duration { } else if nanos >= MAX_NANOS_F64 { Err(FromSecsError { kind: FromSecsErrorKind::Overflow }) } else if nanos < 0.0 { - Err(FromSecsError { kind: FromSecsErrorKind::Underflow }) + Err(FromSecsError { kind: FromSecsErrorKind::Negative }) } else { let nanos = nanos as u128; Ok(Duration { @@ -782,11 +789,11 @@ impl Duration { #[stable(feature = "duration_float", since = "1.38.0")] #[must_use] #[inline] - #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] + #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] pub const fn from_secs_f32(secs: f32) -> Duration { match Duration::try_from_secs_f32(secs) { Ok(v) => v, - Err(e) => crate::panicking::panic(e.description()), + Err(e) => panic!("{}", e.description()), } } @@ -799,7 +806,6 @@ impl Duration { /// # Examples /// ``` /// #![feature(duration_checked_float)] - /// /// use std::time::Duration; /// /// let dur = Duration::try_from_secs_f32(2.7); @@ -818,7 +824,7 @@ impl Duration { } else if nanos >= MAX_NANOS_F32 { Err(FromSecsError { kind: FromSecsErrorKind::Overflow }) } else if nanos < 0.0 { - Err(FromSecsError { kind: FromSecsErrorKind::Underflow }) + Err(FromSecsError { kind: FromSecsErrorKind::Negative }) } else { let nanos = nanos as u128; Ok(Duration { @@ -845,7 +851,7 @@ impl Duration { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] + #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] pub const fn mul_f64(self, rhs: f64) -> Duration { Duration::from_secs_f64(rhs * self.as_secs_f64()) } @@ -869,7 +875,7 @@ impl Duration { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] + #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] pub const fn mul_f32(self, rhs: f32) -> Duration { Duration::from_secs_f32(rhs * self.as_secs_f32()) } @@ -892,7 +898,7 @@ impl Duration { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] + #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] pub const fn div_f64(self, rhs: f64) -> Duration { Duration::from_secs_f64(self.as_secs_f64() / rhs) } @@ -917,7 +923,7 @@ impl Duration { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] + #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] pub const fn div_f32(self, rhs: f32) -> Duration { Duration::from_secs_f32(self.as_secs_f32() / rhs) } @@ -937,7 +943,7 @@ impl Duration { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] + #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] pub const fn div_duration_f64(self, rhs: Duration) -> f64 { self.as_secs_f64() / rhs.as_secs_f64() } @@ -957,7 +963,7 @@ impl Duration { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] + #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] pub const fn div_duration_f32(self, rhs: Duration) -> f32 { self.as_secs_f32() / rhs.as_secs_f32() } @@ -1258,7 +1264,6 @@ impl fmt::Debug for Duration { /// /// ``` /// #![feature(duration_checked_float)] -/// /// use std::time::Duration; /// /// if let Err(e) = Duration::try_from_secs_f32(-1.0) { @@ -1274,11 +1279,9 @@ pub struct FromSecsError { impl FromSecsError { const fn description(&self) -> &'static str { match self.kind { - FromSecsErrorKind::NonFinite => { - "got non-finite value when converting float to duration" - } + FromSecsErrorKind::NonFinite => "non-finite value when converting float to duration", FromSecsErrorKind::Overflow => "overflow when converting float to duration", - FromSecsErrorKind::Underflow => "underflow when converting float to duration", + FromSecsErrorKind::Negative => "negative value when converting float to duration", } } } @@ -1292,10 +1295,10 @@ impl fmt::Display for FromSecsError { #[derive(Debug, Clone, PartialEq, Eq)] enum FromSecsErrorKind { - // Value is not a finite value (either infinity or NaN). + // Value is not a finite value (either + or - infinity or NaN). NonFinite, // Value is too large to store in a `Duration`. Overflow, - // Value is less than `0.0`. - Underflow, + // Value is negative. + Negative, } diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs index b3af1328c9..7dc071b742 100644 --- a/library/core/tests/array.rs +++ b/library/core/tests/array.rs @@ -7,6 +7,11 @@ fn array_from_ref() { let value: String = "Hello World!".into(); let arr: &[String; 1] = array::from_ref(&value); assert_eq!(&[value.clone()], arr); + + const VALUE: &&str = &"Hello World!"; + const ARR: &[&str; 1] = array::from_ref(VALUE); + assert_eq!(&[*VALUE], ARR); + assert!(core::ptr::eq(VALUE, &ARR[0])); } #[test] @@ -436,3 +441,36 @@ where std::panic::set_hook(prev_hook); result } + +#[test] +fn array_split_array_mut() { + let mut v = [1, 2, 3, 4, 5, 6]; + + { + let (left, right) = v.split_array_mut::<0>(); + assert_eq!(left, &mut []); + assert_eq!(right, &mut [1, 2, 3, 4, 5, 6]); + } + + { + let (left, right) = v.split_array_mut::<6>(); + assert_eq!(left, &mut [1, 2, 3, 4, 5, 6]); + assert_eq!(right, &mut []); + } +} + +#[should_panic] +#[test] +fn array_split_array_ref_out_of_bounds() { + let v = [1, 2, 3, 4, 5, 6]; + + v.split_array_ref::<7>(); +} + +#[should_panic] +#[test] +fn array_split_array_mut_out_of_bounds() { + let mut v = [1, 2, 3, 4, 5, 6]; + + v.split_array_mut::<7>(); +} diff --git a/library/core/tests/ascii.rs b/library/core/tests/ascii.rs index 66c25e449d..6d2cf3e83b 100644 --- a/library/core/tests/ascii.rs +++ b/library/core/tests/ascii.rs @@ -115,7 +115,7 @@ fn test_eq_ignore_ascii_case() { #[test] fn inference_works() { let x = "a".to_string(); - x.eq_ignore_ascii_case("A"); + let _ = x.eq_ignore_ascii_case("A"); } // Shorthands used by the is_ascii_* tests. diff --git a/library/core/tests/atomic.rs b/library/core/tests/atomic.rs index b735957666..7f8672f035 100644 --- a/library/core/tests/atomic.rs +++ b/library/core/tests/atomic.rs @@ -220,3 +220,10 @@ fn atomic_compare_exchange() { ATOMIC.compare_exchange_weak(0, 1, SeqCst, Acquire).ok(); ATOMIC.compare_exchange_weak(0, 1, SeqCst, SeqCst).ok(); } + +#[test] +fn atomic_const_from() { + const _ATOMIC_U8: AtomicU8 = AtomicU8::from(1); + const _ATOMIC_BOOL: AtomicBool = AtomicBool::from(true); + const _ATOMIC_PTR: AtomicPtr = AtomicPtr::from(core::ptr::null_mut()); +} diff --git a/library/core/tests/cell.rs b/library/core/tests/cell.rs index 85a006c5d5..4707cc7076 100644 --- a/library/core/tests/cell.rs +++ b/library/core/tests/cell.rs @@ -465,4 +465,13 @@ fn const_cells() { const CELL: Cell = Cell::new(3); const _: i32 = CELL.into_inner(); + + const UNSAFE_CELL_FROM: UnsafeCell = UnsafeCell::from(3); + const _: i32 = UNSAFE_CELL.into_inner(); + + const REF_CELL_FROM: RefCell = RefCell::from(3); + const _: i32 = REF_CELL.into_inner(); + + const CELL_FROM: Cell = Cell::from(3); + const _: i32 = CELL.into_inner(); } diff --git a/library/core/tests/char.rs b/library/core/tests/char.rs index 51eca1e05d..6e434cf1a8 100644 --- a/library/core/tests/char.rs +++ b/library/core/tests/char.rs @@ -5,6 +5,8 @@ use std::{char, str}; #[test] fn test_convert() { assert_eq!(u32::from('a'), 0x61); + assert_eq!(u64::from('b'), 0x62); + assert_eq!(u128::from('c'), 0x63); assert_eq!(char::from(b'\0'), '\0'); assert_eq!(char::from(b'a'), 'a'); assert_eq!(char::from(b'\xFF'), '\u{FF}'); @@ -19,6 +21,16 @@ fn test_convert() { assert!(char::try_from(0xFFFF_FFFF_u32).is_err()); } +#[test] +const fn test_convert_const() { + assert!(u32::from('a') == 0x61); + assert!(u64::from('b') == 0x62); + assert!(u128::from('c') == 0x63); + assert!(char::from(b'\0') == '\0'); + assert!(char::from(b'a') == 'a'); + assert!(char::from(b'\xFF') == '\u{FF}'); +} + #[test] fn test_from_str() { assert_eq!(char::from_str("a").unwrap(), 'a'); diff --git a/library/core/tests/fmt/float.rs b/library/core/tests/fmt/float.rs index bd0daf7a8e..47a7400f76 100644 --- a/library/core/tests/fmt/float.rs +++ b/library/core/tests/fmt/float.rs @@ -12,6 +12,16 @@ fn test_format_f64() { assert_eq!("1.23456789E3", format!("{:E}", 1234.56789f64)); assert_eq!("0.0", format!("{:?}", 0.0f64)); assert_eq!("1.01", format!("{:?}", 1.01f64)); + + let high_cutoff = 1e16_f64; + assert_eq!("1e16", format!("{:?}", high_cutoff)); + assert_eq!("-1e16", format!("{:?}", -high_cutoff)); + assert!(!is_exponential(&format!("{:?}", high_cutoff * (1.0 - 2.0 * f64::EPSILON)))); + assert_eq!("-3.0", format!("{:?}", -3f64)); + assert_eq!("0.0001", format!("{:?}", 0.0001f64)); + assert_eq!("9e-5", format!("{:?}", 0.00009f64)); + assert_eq!("1234567.9", format!("{:.1?}", 1234567.89f64)); + assert_eq!("1234.6", format!("{:.1?}", 1234.56789f64)); } #[test] @@ -28,4 +38,18 @@ fn test_format_f32() { assert_eq!("1.2345679E3", format!("{:E}", 1234.56789f32)); assert_eq!("0.0", format!("{:?}", 0.0f32)); assert_eq!("1.01", format!("{:?}", 1.01f32)); + + let high_cutoff = 1e16_f32; + assert_eq!("1e16", format!("{:?}", high_cutoff)); + assert_eq!("-1e16", format!("{:?}", -high_cutoff)); + assert!(!is_exponential(&format!("{:?}", high_cutoff * (1.0 - 2.0 * f32::EPSILON)))); + assert_eq!("-3.0", format!("{:?}", -3f32)); + assert_eq!("0.0001", format!("{:?}", 0.0001f32)); + assert_eq!("9e-5", format!("{:?}", 0.00009f32)); + assert_eq!("1234567.9", format!("{:.1?}", 1234567.89f32)); + assert_eq!("1234.6", format!("{:.1?}", 1234.56789f32)); +} + +fn is_exponential(s: &str) -> bool { + s.contains("e") || s.contains("E") } diff --git a/library/core/tests/lazy.rs b/library/core/tests/lazy.rs index 24f921ca7e..064024ab87 100644 --- a/library/core/tests/lazy.rs +++ b/library/core/tests/lazy.rs @@ -47,6 +47,12 @@ fn unsync_once_cell_drop_empty() { drop(x); } +#[test] +const fn once_cell_const() { + let _once_cell: OnceCell = OnceCell::new(); + let _once_cell: OnceCell = OnceCell::from(32); +} + #[test] fn clone() { let s = OnceCell::new(); diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index cf669163d3..4d37ed1942 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -9,8 +9,8 @@ #![feature(cfg_target_has_atomic)] #![feature(const_assume)] #![feature(const_cell_into_inner)] +#![feature(const_convert)] #![feature(const_maybe_uninit_assume_init)] -#![cfg_attr(bootstrap, feature(const_panic))] #![feature(const_ptr_read)] #![feature(const_ptr_write)] #![feature(const_ptr_offset)] @@ -21,12 +21,13 @@ #![feature(core_private_diy_float)] #![feature(dec2flt)] #![feature(div_duration)] -#![feature(duration_consts_2)] +#![feature(duration_consts_float)] #![feature(duration_constants)] #![feature(exact_size_is_empty)] #![feature(extern_types)] #![feature(flt2dec)] #![feature(fmt_internals)] +#![feature(float_minimum_maximum)] #![feature(array_from_fn)] #![feature(hashmap_internals)] #![feature(try_find)] @@ -56,21 +57,24 @@ #![feature(const_mut_refs)] #![feature(const_pin)] #![feature(const_slice_from_raw_parts)] -#![feature(const_raw_ptr_deref)] +#![cfg_attr(bootstrap, feature(const_raw_ptr_deref))] #![feature(never_type)] #![feature(unwrap_infallible)] -#![feature(option_result_unwrap_unchecked)] #![feature(result_into_ok_or_err)] #![feature(ptr_metadata)] #![feature(once_cell)] #![feature(unsized_tuple_coercion)] #![feature(const_option)] +#![feature(const_result)] #![feature(integer_atomics)] #![feature(int_roundings)] #![feature(slice_group_by)] +#![feature(split_array)] #![feature(trusted_random_access)] #![feature(unsize)] #![feature(unzip_option)] +#![feature(const_array_from_ref)] +#![feature(const_slice_from_ref)] #![deny(unsafe_op_in_unsafe_fn)] extern crate test; diff --git a/library/core/tests/nonzero.rs b/library/core/tests/nonzero.rs index c2c08522d0..a0ca919a85 100644 --- a/library/core/tests/nonzero.rs +++ b/library/core/tests/nonzero.rs @@ -204,9 +204,9 @@ fn nonzero_const() { // test that the methods of `NonZeroX>` are usable in a const context // Note: only tests NonZero8 - const NONZERO: NonZeroU8 = unsafe { NonZeroU8::new_unchecked(5) }; + const NONZERO_U8: NonZeroU8 = unsafe { NonZeroU8::new_unchecked(5) }; - const GET: u8 = NONZERO.get(); + const GET: u8 = NONZERO_U8.get(); assert_eq!(GET, 5); const ZERO: Option = NonZeroU8::new(0); @@ -214,6 +214,12 @@ fn nonzero_const() { const ONE: Option = NonZeroU8::new(1); assert!(ONE.is_some()); + + const FROM_NONZERO_U8: u8 = u8::from(NONZERO_U8); + assert_eq!(FROM_NONZERO_U8, 5); + + const NONZERO_CONVERT: NonZeroU32 = NonZeroU32::from(NONZERO_U8); + assert_eq!(NONZERO_CONVERT.get(), 5); } #[test] diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs index 37b5e9127d..4f773a824e 100644 --- a/library/core/tests/num/mod.rs +++ b/library/core/tests/num/mod.rs @@ -715,6 +715,67 @@ macro_rules! test_float { assert!(($nan as $fty).max($nan).is_nan()); } #[test] + fn minimum() { + assert_eq!((0.0 as $fty).minimum(0.0), 0.0); + assert!((0.0 as $fty).minimum(0.0).is_sign_positive()); + assert_eq!((-0.0 as $fty).minimum(0.0), -0.0); + assert!((-0.0 as $fty).minimum(0.0).is_sign_negative()); + assert_eq!((-0.0 as $fty).minimum(-0.0), -0.0); + assert!((-0.0 as $fty).minimum(-0.0).is_sign_negative()); + assert_eq!((9.0 as $fty).minimum(9.0), 9.0); + assert_eq!((-9.0 as $fty).minimum(0.0), -9.0); + assert_eq!((0.0 as $fty).minimum(9.0), 0.0); + assert!((0.0 as $fty).minimum(9.0).is_sign_positive()); + assert_eq!((-0.0 as $fty).minimum(9.0), -0.0); + assert!((-0.0 as $fty).minimum(9.0).is_sign_negative()); + assert_eq!((-0.0 as $fty).minimum(-9.0), -9.0); + assert_eq!(($inf as $fty).minimum(9.0), 9.0); + assert_eq!((9.0 as $fty).minimum($inf), 9.0); + assert_eq!(($inf as $fty).minimum(-9.0), -9.0); + assert_eq!((-9.0 as $fty).minimum($inf), -9.0); + assert_eq!(($neginf as $fty).minimum(9.0), $neginf); + assert_eq!((9.0 as $fty).minimum($neginf), $neginf); + assert_eq!(($neginf as $fty).minimum(-9.0), $neginf); + assert_eq!((-9.0 as $fty).minimum($neginf), $neginf); + assert!(($nan as $fty).minimum(9.0).is_nan()); + assert!(($nan as $fty).minimum(-9.0).is_nan()); + assert!((9.0 as $fty).minimum($nan).is_nan()); + assert!((-9.0 as $fty).minimum($nan).is_nan()); + assert!(($nan as $fty).minimum($nan).is_nan()); + } + #[test] + fn maximum() { + assert_eq!((0.0 as $fty).maximum(0.0), 0.0); + assert!((0.0 as $fty).maximum(0.0).is_sign_positive()); + assert_eq!((-0.0 as $fty).maximum(0.0), 0.0); + assert!((-0.0 as $fty).maximum(0.0).is_sign_positive()); + assert_eq!((-0.0 as $fty).maximum(-0.0), -0.0); + assert!((-0.0 as $fty).maximum(-0.0).is_sign_negative()); + assert_eq!((9.0 as $fty).maximum(9.0), 9.0); + assert_eq!((-9.0 as $fty).maximum(0.0), 0.0); + assert!((-9.0 as $fty).maximum(0.0).is_sign_positive()); + assert_eq!((-9.0 as $fty).maximum(-0.0), -0.0); + assert!((-9.0 as $fty).maximum(-0.0).is_sign_negative()); + assert_eq!((0.0 as $fty).maximum(9.0), 9.0); + assert_eq!((0.0 as $fty).maximum(-9.0), 0.0); + assert!((0.0 as $fty).maximum(-9.0).is_sign_positive()); + assert_eq!((-0.0 as $fty).maximum(-9.0), -0.0); + assert!((-0.0 as $fty).maximum(-9.0).is_sign_negative()); + assert_eq!(($inf as $fty).maximum(9.0), $inf); + assert_eq!((9.0 as $fty).maximum($inf), $inf); + assert_eq!(($inf as $fty).maximum(-9.0), $inf); + assert_eq!((-9.0 as $fty).maximum($inf), $inf); + assert_eq!(($neginf as $fty).maximum(9.0), 9.0); + assert_eq!((9.0 as $fty).maximum($neginf), 9.0); + assert_eq!(($neginf as $fty).maximum(-9.0), -9.0); + assert_eq!((-9.0 as $fty).maximum($neginf), -9.0); + assert!(($nan as $fty).maximum(9.0).is_nan()); + assert!(($nan as $fty).maximum(-9.0).is_nan()); + assert!((9.0 as $fty).maximum($nan).is_nan()); + assert!((-9.0 as $fty).maximum($nan).is_nan()); + assert!(($nan as $fty).maximum($nan).is_nan()); + } + #[test] fn rem_euclid() { let a: $fty = 42.0; assert!($inf.rem_euclid(a).is_nan()); diff --git a/library/core/tests/option.rs b/library/core/tests/option.rs index c9508c1452..cd07d6c52c 100644 --- a/library/core/tests/option.rs +++ b/library/core/tests/option.rs @@ -358,10 +358,17 @@ fn option_const() { // test that the methods of `Option` are usable in a const context const OPTION: Option = Some(32); + assert_eq!(OPTION, Some(32)); + + const OPTION_FROM: Option = Option::from(32); + assert_eq!(OPTION_FROM, Some(32)); const REF: Option<&usize> = OPTION.as_ref(); assert_eq!(REF, Some(&32)); + const REF_FROM: Option<&usize> = Option::from(&OPTION); + assert_eq!(REF_FROM, Some(&32)); + const IS_SOME: bool = OPTION.is_some(); assert!(IS_SOME); @@ -388,6 +395,14 @@ const fn option_const_mut() { None => unreachable!(), } } + + { + let as_mut: Option<&mut usize> = Option::from(&mut option); + match as_mut { + Some(v) => *v = 42, + None => unreachable!(), + } + } } #[test] diff --git a/library/core/tests/result.rs b/library/core/tests/result.rs index 612f083a5c..1652c1b83d 100644 --- a/library/core/tests/result.rs +++ b/library/core/tests/result.rs @@ -352,6 +352,29 @@ fn result_const() { assert!(!IS_ERR) } +#[test] +const fn result_const_mut() { + let mut result: Result = Ok(32); + + { + let as_mut = result.as_mut(); + match as_mut { + Ok(v) => *v = 42, + Err(_) => unreachable!(), + } + } + + let mut result_err: Result = Err(false); + + { + let as_mut = result_err.as_mut(); + match as_mut { + Ok(_) => unreachable!(), + Err(v) => *v = true, + } + } +} + #[test] fn result_opt_conversions() { #[derive(Copy, Clone, Debug, PartialEq)] diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index b6a326f3d7..8d05e47edf 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -2146,6 +2146,14 @@ fn test_slice_run_destructors() { assert_eq!(x.get(), 1); } +#[test] +fn test_const_from_ref() { + const VALUE: &i32 = &1; + const SLICE: &[i32] = core::slice::from_ref(VALUE); + + assert!(core::ptr::eq(VALUE, &SLICE[0])) +} + #[test] fn test_slice_fill_with_uninit() { // This should not UB. See #87891 @@ -2191,3 +2199,36 @@ mod swap_panics { x.swap(2, 5); } } + +#[test] +fn slice_split_array_mut() { + let v = &mut [1, 2, 3, 4, 5, 6][..]; + + { + let (left, right) = v.split_array_mut::<0>(); + assert_eq!(left, &mut []); + assert_eq!(right, [1, 2, 3, 4, 5, 6]); + } + + { + let (left, right) = v.split_array_mut::<6>(); + assert_eq!(left, &mut [1, 2, 3, 4, 5, 6]); + assert_eq!(right, []); + } +} + +#[should_panic] +#[test] +fn slice_split_array_ref_out_of_bounds() { + let v = &[1, 2, 3, 4, 5, 6][..]; + + v.split_array_ref::<7>(); +} + +#[should_panic] +#[test] +fn slice_split_array_mut_out_of_bounds() { + let v = &mut [1, 2, 3, 4, 5, 6][..]; + + v.split_array_mut::<7>(); +} diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs index ac75ce7f22..dec5e0b212 100644 --- a/library/panic_abort/src/lib.rs +++ b/library/panic_abort/src/lib.rs @@ -117,7 +117,7 @@ pub unsafe extern "C-unwind" fn __rust_start_panic(_payload: *mut &mut dyn BoxMe pub mod personalities { #[rustc_std_internal_symbol] #[cfg(not(any( - all(target_arch = "wasm32", not(target_os = "emscripten"),), + all(target_family = "wasm", not(target_os = "emscripten")), all(target_os = "windows", target_env = "gnu", target_arch = "x86_64",), )))] pub extern "C" fn rust_eh_personality() {} diff --git a/library/panic_unwind/src/dummy.rs b/library/panic_unwind/src/dummy.rs index 4667ede2ba..a4bcd216c6 100644 --- a/library/panic_unwind/src/dummy.rs +++ b/library/panic_unwind/src/dummy.rs @@ -1,6 +1,6 @@ -//! Unwinding for *wasm32* target. +//! Unwinding for unsupported target. //! -//! Right now we don't support this, so this is just stubs. +//! Stubs that simply abort for targets that don't support unwinding otherwise. use alloc::boxed::Box; use core::any::Any; diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs index b5d0ca2572..e5753ccae2 100644 --- a/library/panic_unwind/src/lib.rs +++ b/library/panic_unwind/src/lib.rs @@ -56,7 +56,7 @@ cfg_if::cfg_if! { mod real_imp; } else { // Targets that don't support unwinding. - // - arch=wasm32 + // - family=wasm // - os=none ("bare metal" targets) // - os=uefi // - os=espidf diff --git a/library/portable-simd/.github/ISSUE_TEMPLATE/blank_issue.md b/library/portable-simd/.github/ISSUE_TEMPLATE/blank_issue.md new file mode 100644 index 0000000000..9aef3ebe63 --- /dev/null +++ b/library/portable-simd/.github/ISSUE_TEMPLATE/blank_issue.md @@ -0,0 +1,4 @@ +--- +name: Blank Issue +about: Create a blank issue. +--- diff --git a/library/portable-simd/.github/ISSUE_TEMPLATE/bug_report.md b/library/portable-simd/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000000..16a8251d52 --- /dev/null +++ b/library/portable-simd/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,50 @@ +--- +name: Bug Report +about: Create a bug report for Rust. +labels: C-bug +--- + + +I tried this code: + +```rust + +``` + +I expected to see this happen: *explanation* + +Instead, this happened: *explanation* + +### Meta + +`rustc --version --verbose`: +``` + +``` + + +`crate version in Cargo.toml`: +```toml +[dependencies] +stdsimd = +``` + + + + +
Backtrace +

+ +``` + +``` + +

+
diff --git a/library/portable-simd/.github/ISSUE_TEMPLATE/config.yml b/library/portable-simd/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..1567542c01 --- /dev/null +++ b/library/portable-simd/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,10 @@ +# This only controls whether a tiny, hard-to-find "open a blank issue" link appears at the end of +# the template list. +blank_issues_enabled: true +contact_links: + - name: Intrinsic Support + url: https://github.com/rust-lang/stdarch/issues + about: Please direct issues about Rust's support for vendor intrinsics to core::arch + - name: Internal Compiler Error + url: https://github.com/rust-lang/rust/issues + about: Please report ICEs to the rustc repository diff --git a/library/portable-simd/.github/ISSUE_TEMPLATE/feature_request.md b/library/portable-simd/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000000..be6c9e3d17 --- /dev/null +++ b/library/portable-simd/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,14 @@ +--- +name: Feature Request +about: Request an addition to the core::simd API +labels: C-feature-request +--- + diff --git a/library/portable-simd/.github/PULL_REQUEST_TEMPLATE.md b/library/portable-simd/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000000..31422b7934 --- /dev/null +++ b/library/portable-simd/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,18 @@ +Hello, welcome to `std::simd`! + +It seems this pull request template checklist was created while a lot of vector math ops were being implemented, and only really applies to ops. Feel free to delete everything here if it's not applicable, or ask for help if you're not sure what it means! + +For a given vector math operation on TxN, please add tests for interactions with: + - [ ] `T::MAX` + - [ ] `T::MIN` + - [ ] -1 + - [ ] 1 + - [ ] 0 + + +For a given vector math operation on TxN where T is a float, please add tests for test interactions with: + - [ ] a really large number, larger than the mantissa + - [ ] a really small "subnormal" number + - [ ] NaN + - [ ] Infinity + - [ ] Negative Infinity diff --git a/library/portable-simd/.github/workflows/ci.yml b/library/portable-simd/.github/workflows/ci.yml new file mode 100644 index 0000000000..d50dfa1be4 --- /dev/null +++ b/library/portable-simd/.github/workflows/ci.yml @@ -0,0 +1,260 @@ +name: CI + +on: + pull_request: + push: + branches: + - master + +env: + CARGO_NET_RETRY: 10 + RUSTUP_MAX_RETRIES: 10 + +jobs: + rustfmt: + name: "rustfmt" + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Setup Rust + run: | + rustup update nightly --no-self-update + rustup default nightly + rustup component add rustfmt + - name: Run rustfmt + run: cargo fmt --all -- --check + + clippy: + name: "clippy on ${{ matrix.target }}" + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + target: + # We shouldn't really have any OS-specific code, so think of this as a list of architectures + - x86_64-unknown-linux-gnu + - i686-unknown-linux-gnu + - i586-unknown-linux-gnu + - aarch64-unknown-linux-gnu + - armv7-unknown-linux-gnueabihf + - mips-unknown-linux-gnu + - mips64-unknown-linux-gnuabi64 + - powerpc-unknown-linux-gnu + - powerpc64-unknown-linux-gnu + - riscv64gc-unknown-linux-gnu + - s390x-unknown-linux-gnu + - sparc64-unknown-linux-gnu + - wasm32-unknown-unknown + + steps: + - uses: actions/checkout@v2 + - name: Setup Rust + run: | + rustup update nightly --no-self-update + rustup default nightly + rustup target add ${{ matrix.target }} + rustup component add clippy + - name: Run Clippy + run: cargo clippy --all-targets --target ${{ matrix.target }} + + x86-tests: + name: "${{ matrix.target_feature }} on ${{ matrix.target }}" + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + target: [x86_64-pc-windows-msvc, i686-pc-windows-msvc, i586-pc-windows-msvc, x86_64-unknown-linux-gnu, x86_64-apple-darwin] + # `default` means we use the default target config for the target, + # `native` means we run with `-Ctarget-cpu=native`, and anything else is + # an arg to `-Ctarget-feature` + target_feature: [default, native, +sse3, +ssse3, +sse4.1, +sse4.2, +avx, +avx2] + + exclude: + # The macos runners seem to only reliably support up to `avx`. + - { target: x86_64-apple-darwin, target_feature: +avx2 } + # These features are statically known to be present for all 64 bit + # macs, and thus are covered by the `default` test + - { target: x86_64-apple-darwin, target_feature: +sse3 } + - { target: x86_64-apple-darwin, target_feature: +ssse3 } + # -Ctarget-cpu=native sounds like bad-news if target != host + - { target: i686-pc-windows-msvc, target_feature: native } + - { target: i586-pc-windows-msvc, target_feature: native } + + include: + # Populate the `matrix.os` field + - { target: x86_64-apple-darwin, os: macos-latest } + - { target: x86_64-unknown-linux-gnu, os: ubuntu-latest } + - { target: x86_64-pc-windows-msvc, os: windows-latest } + - { target: i686-pc-windows-msvc, os: windows-latest } + - { target: i586-pc-windows-msvc, os: windows-latest } + + # These are globally available on all the other targets. + - { target: i586-pc-windows-msvc, target_feature: +sse, os: windows-latest } + - { target: i586-pc-windows-msvc, target_feature: +sse2, os: windows-latest } + + # Annoyingly, the x86_64-unknown-linux-gnu runner *almost* always has + # avx512vl, but occasionally doesn't. Maybe one day we can enable it. + + steps: + - uses: actions/checkout@v2 + - name: Setup Rust + run: | + rustup update nightly --no-self-update + rustup default nightly + rustup target add ${{ matrix.target }} + + - name: Configure RUSTFLAGS + shell: bash + run: | + case "${{ matrix.target_feature }}" in + default) + echo "RUSTFLAGS=-Dwarnings" >> $GITHUB_ENV;; + native) + echo "RUSTFLAGS=-Dwarnings -Ctarget-cpu=native" >> $GITHUB_ENV + ;; + *) + echo "RUSTFLAGS=-Dwarnings -Ctarget-feature=${{ matrix.target_feature }}" >> $GITHUB_ENV + ;; + esac + + # Super useful for debugging why a SIGILL occurred. + - name: Dump target configuration and support + run: | + rustc -Vv + + echo "Caveat: not all target features are expected to be logged" + + echo "## Requested target configuration (RUSTFLAGS=$RUSTFLAGS)" + rustc --print=cfg --target=${{ matrix.target }} $RUSTFLAGS + + echo "## Supported target configuration for --target=${{ matrix.target }}" + rustc --print=cfg --target=${{ matrix.target }} -Ctarget-cpu=native + + echo "## Natively supported target configuration" + rustc --print=cfg -Ctarget-cpu=native + + - name: Test (debug) + run: cargo test --verbose --target=${{ matrix.target }} + + - name: Test (release) + run: cargo test --verbose --target=${{ matrix.target }} --release + + wasm-tests: + name: "wasm (firefox, ${{ matrix.name }})" + runs-on: ubuntu-latest + strategy: + matrix: + include: + - { name: default, RUSTFLAGS: "" } + - { name: simd128, RUSTFLAGS: "-C target-feature=+simd128" } + steps: + - uses: actions/checkout@v2 + - name: Setup Rust + run: | + rustup update nightly --no-self-update + rustup default nightly + - name: Install wasm-pack + run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh + - name: Test (debug) + run: wasm-pack test --firefox --headless crates/core_simd + env: + RUSTFLAGS: ${{ matrix.rustflags }} + - name: Test (release) + run: wasm-pack test --firefox --headless crates/core_simd --release + env: + RUSTFLAGS: ${{ matrix.rustflags }} + + cross-tests: + name: "${{ matrix.target }} (via cross)" + runs-on: ubuntu-latest + strategy: + fail-fast: false + # TODO: Sadly, we cant configure target-feature in a meaningful way + # because `cross` doesn't tell qemu to enable any non-default cpu + # features, nor does it give us a way to do so. + # + # Ultimately, we'd like to do something like [rust-lang/stdarch][stdarch]. + # This is a lot more complex... but in practice it's likely that we can just + # snarf the docker config from around [here][1000-dockerfiles]. + # + # [stdarch]: https://github.com/rust-lang/stdarch/blob/a5db4eaf/.github/workflows/main.yml#L67 + # [1000-dockerfiles]: https://github.com/rust-lang/stdarch/tree/a5db4eaf/ci/docker + + matrix: + target: + - i586-unknown-linux-gnu + # 32-bit arm has a few idiosyncracies like having subnormal flushing + # to zero on by default. Ideally we'd set + - armv7-unknown-linux-gnueabihf + - aarch64-unknown-linux-gnu + # Note: The issue above means neither of these mips targets will use + # MSA (mips simd) but MIPS uses a nonstandard binary representation + # for NaNs which makes it worth testing on despite that. + - mips-unknown-linux-gnu + - mips64-unknown-linux-gnuabi64 + - riscv64gc-unknown-linux-gnu + # TODO this test works, but it appears to time out + # - powerpc-unknown-linux-gnu + # TODO this test is broken, but it appears to be a problem with QEMU, not us. + # - powerpc64le-unknown-linux-gnu + # TODO enable this once a new version of cross is released + # - powerpc64-unknown-linux-gnu + + steps: + - uses: actions/checkout@v2 + - name: Setup Rust + run: | + rustup update nightly --no-self-update + rustup default nightly + rustup target add ${{ matrix.target }} + rustup component add rust-src + + - name: Install Cross + # Equivalent to `cargo install cross`, but downloading a prebuilt + # binary. Ideally we wouldn't hardcode a version, but the version number + # being part of the tarball means we can't just use the download/latest + # URL :( + run: | + CROSS_URL=https://github.com/rust-embedded/cross/releases/download/v0.2.1/cross-v0.2.1-x86_64-unknown-linux-gnu.tar.gz + mkdir -p "$HOME/.bin" + curl -sfSL --retry-delay 10 --retry 5 "${CROSS_URL}" | tar zxf - -C "$HOME/.bin" + echo "$HOME/.bin" >> $GITHUB_PATH + + - name: Test (debug) + run: cross test --verbose --target=${{ matrix.target }} + + - name: Test (release) + run: cross test --verbose --target=${{ matrix.target }} --release + + features: + name: "Check cargo features (${{ matrix.simd }} × ${{ matrix.features }})" + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + simd: + - "" + - "avx512" + features: + - "" + - "--features std" + - "--features generic_const_exprs" + - "--features std --features generic_const_exprs" + + steps: + - uses: actions/checkout@v2 + - name: Setup Rust + run: | + rustup update nightly --no-self-update + rustup default nightly + - name: Detect AVX512 + run: echo "CPU_FEATURE=$(lscpu | grep -o avx512[a-z]* | sed s/avx/+avx/ | tr '\n' ',' )" >> $GITHUB_ENV + - name: Check build + if: ${{ matrix.simd == '' }} + run: RUSTFLAGS="-Dwarnings" cargo check --all-targets --no-default-features ${{ matrix.features }} + - name: Check AVX + if: ${{ matrix.simd == 'avx512' && contains(env.CPU_FEATURE, 'avx512') }} + run: | + echo "Found AVX features: $CPU_FEATURE" + RUSTFLAGS="-Dwarnings -Ctarget-feature=$CPU_FEATURE" cargo check --all-targets --no-default-features ${{ matrix.features }} diff --git a/library/portable-simd/.github/workflows/doc.yml b/library/portable-simd/.github/workflows/doc.yml new file mode 100644 index 0000000000..9d1fa66ccb --- /dev/null +++ b/library/portable-simd/.github/workflows/doc.yml @@ -0,0 +1,30 @@ +name: Documentation + +on: + push: + branches: + - master + +jobs: + release: + name: Deploy Documentation + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@v1 + + - name: Setup Rust + run: | + rustup update nightly --no-self-update + rustup default nightly + + - name: Build Documentation + run: cargo doc --no-deps + + - name: Deploy Documentation + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_branch: gh-pages + publish_dir: ./target/doc diff --git a/library/portable-simd/CONTRIBUTING.md b/library/portable-simd/CONTRIBUTING.md new file mode 100644 index 0000000000..f9ba12d3a1 --- /dev/null +++ b/library/portable-simd/CONTRIBUTING.md @@ -0,0 +1,32 @@ +# Contributing to `std::simd` + +Simple version: +1. Fork it and `git clone` it +2. Create your feature branch: `git checkout -b my-branch` +3. Write your changes. +4. Test it: `cargo test`. Remember to enable whatever SIMD features you intend to test by setting `RUSTFLAGS`. +5. Commit your changes: `git commit add ./path/to/changes && git commit -m 'Fix some bug'` +6. Push the branch: `git push --set-upstream origin my-branch` +7. Submit a pull request! + +## Taking on an Issue + +SIMD can be quite complex, and even a "simple" issue can be huge. If an issue is organized like a tracking issue, with an itemized list of items that don't necessarily have to be done in a specific order, please take the issue one item at a time. This will help by letting work proceed apace on the rest of the issue. If it's a (relatively) small issue, feel free to announce your intention to solve it on the issue tracker and take it in one go! + +## CI + +We currently have 2 CI matrices through Travis CI and GitHub Actions that will automatically build and test your change in order to verify that `std::simd`'s portable API is, in fact, portable. If your change builds locally, but does not build on either, this is likely due to a platform-specific concern that your code has not addressed. Please consult the build logs and address the error, or ask for help if you need it. + +## Beyond stdsimd + +A large amount of the core SIMD implementation is found in the rustc_codegen_* crates in the [main rustc repo](https://github.com/rust-lang/rust). In addition, actual platform-specific functions are implemented in [stdarch]. Not all changes to `std::simd` require interacting with either of these, but if you're wondering where something is and it doesn't seem to be in this repository, those might be where to start looking. + +## Questions? Concerns? Need Help? + +Please feel free to ask in the [#project-portable-simd][zulip-portable-simd] stream on the [rust-lang Zulip][zulip] for help with making changes to `std::simd`! +If your changes include directly modifying the compiler, it might also be useful to ask in [#t-compiler/help][zulip-compiler-help]. + +[zulip-portable-simd]: https://rust-lang.zulipchat.com/#narrow/stream/257879-project-portable-simd +[zulip-compiler-help]: https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp +[zulip]: https://rust-lang.zulipchat.com +[stdarch]: https://github.com/rust-lang/stdarch diff --git a/library/portable-simd/Cargo.toml b/library/portable-simd/Cargo.toml new file mode 100644 index 0000000000..3f1abd7351 --- /dev/null +++ b/library/portable-simd/Cargo.toml @@ -0,0 +1,6 @@ +[workspace] + +members = [ + "crates/core_simd", + "crates/test_helpers", +] diff --git a/library/portable-simd/LICENSE-APACHE b/library/portable-simd/LICENSE-APACHE new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/library/portable-simd/LICENSE-APACHE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/library/portable-simd/LICENSE-MIT b/library/portable-simd/LICENSE-MIT new file mode 100644 index 0000000000..0e9d2f43a0 --- /dev/null +++ b/library/portable-simd/LICENSE-MIT @@ -0,0 +1,19 @@ +Copyright (c) 2020 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/library/portable-simd/README.md b/library/portable-simd/README.md new file mode 100644 index 0000000000..da536a4d6f --- /dev/null +++ b/library/portable-simd/README.md @@ -0,0 +1,69 @@ +# The Rust standard library's portable SIMD API +[![Build Status](https://travis-ci.com/rust-lang/portable-simd.svg?branch=master)](https://travis-ci.com/rust-lang/portable-simd) + +Code repository for the [Portable SIMD Project Group](https://github.com/rust-lang/project-portable-simd). +Please refer to [CONTRIBUTING.md](./CONTRIBUTING.md) for our contributing guidelines. + +The docs for this crate are published from the main branch. +You can [read them here][docs]. + +If you have questions about SIMD, we have begun writing a [guide][simd-guide]. +We can also be found on [Zulip][zulip-project-portable-simd]. + +If you are interested in support for a specific architecture, you may want [stdarch] instead. + +## Hello World + +Now we're gonna dip our toes into this world with a small SIMD "Hello, World!" example. Make sure your compiler is up to date and using `nightly`. We can do that by running + +```bash +rustup update -- nightly +``` + +or by setting up `rustup default nightly` or else with `cargo +nightly {build,test,run}`. After updating, run +```bash +cargo new hellosimd +``` +to create a new crate. Edit `hellosimd/Cargo.toml` to be +```toml +[package] +name = "hellosimd" +version = "0.1.0" +edition = "2018" +[dependencies] +core_simd = { git = "https://github.com/rust-lang/portable-simd" } +``` + +and finally write this in `src/main.rs`: +```rust +use core_simd::*; +fn main() { + let a = f32x4::splat(10.0); + let b = f32x4::from_array([1.0, 2.0, 3.0, 4.0]); + println!("{:?}", a + b); +} +``` + +Explanation: We import all the bindings from the crate with the first line. Then, we construct our SIMD vectors with methods like `splat` or `from_array`. Finally, we can use operators on them like `+` and the appropriate SIMD instructions will be carried out. When we run `cargo run` you should get `[11.0, 12.0, 13.0, 14.0]`. + +## Code Organization + +Currently the crate is organized so that each element type is a file, and then the 64-bit, 128-bit, 256-bit, and 512-bit vectors using those types are contained in said file. + +All types are then exported as a single, flat module. + +Depending on the size of the primitive type, the number of lanes the vector will have varies. For example, 128-bit vectors have four `f32` lanes and two `f64` lanes. + +The supported element types are as follows: +* **Floating Point:** `f32`, `f64` +* **Signed Integers:** `i8`, `i16`, `i32`, `i64`, `i128`, `isize` +* **Unsigned Integers:** `u8`, `u16`, `u32`, `u64`, `u128`, `usize` +* **Masks:** `mask8`, `mask16`, `mask32`, `mask64`, `mask128`, `masksize` + +Floating point, signed integers, and unsigned integers are the [primitive types](https://doc.rust-lang.org/core/primitive/index.html) you're already used to. +The `mask` types are "truthy" values, but they use the number of bits in their name instead of just 1 bit like a normal `bool` uses. + +[simd-guide]: ./beginners-guide.md +[zulip-project-portable-simd]: https://rust-lang.zulipchat.com/#narrow/stream/257879-project-portable-simd +[stdarch]: https://github.com/rust-lang/stdarch +[docs]: https://rust-lang.github.io/portable-simd/core_simd diff --git a/library/portable-simd/beginners-guide.md b/library/portable-simd/beginners-guide.md new file mode 100644 index 0000000000..dfd357c459 --- /dev/null +++ b/library/portable-simd/beginners-guide.md @@ -0,0 +1,86 @@ + +# Beginner's Guide To SIMD + +Hello and welcome to our SIMD basics guide! + +Because SIMD is a subject that many programmers haven't worked with before, we thought that it's best to outline some terms and other basics for you to get started with. + +## Quick Background + +**SIMD** stands for *Single Instruction, Multiple Data*. In other words, SIMD is when the CPU performs a single action on more than one logical piece of data at the same time. Instead of adding two registers that each contain one `f32` value and getting an `f32` as the result, you might add two registers that each contain `f32x4` (128 bits of data) and then you get an `f32x4` as the output. + +This might seem a tiny bit weird at first, but there's a good reason for it. Back in the day, as CPUs got faster and faster, eventually they got so fast that the CPU would just melt itself. The heat management (heat sinks, fans, etc) simply couldn't keep up with how much electricity was going through the metal. Two main strategies were developed to help get around the limits of physics. +* One of them you're probably familiar with: Multi-core processors. By giving a processor more than one core, each core can do its own work, and because they're physically distant (at least on the CPU's scale) the heat can still be managed. Unfortunately, not all tasks can just be split up across cores in an efficient way. +* The second strategy is SIMD. If you can't make the register go any faster, you can still make the register *wider*. This lets you process more data at a time, which is *almost* as good as just having a faster CPU. As with multi-core programming, SIMD doesn't fit every kind of task, so you have to know when it will improve your program. + +## Terms + +SIMD has a few special vocabulary terms you should know: + +* **Vector:** A SIMD value is called a vector. This shouldn't be confused with the `Vec` type. A SIMD vector has a fixed size, known at compile time. All of the elements within the vector are of the same type. This makes vectors *similar to* arrays. One difference is that a vector is generally aligned to its *entire* size (eg: 16 bytes, 32 bytes, etc), not just the size of an individual element. Sometimes vector data is called "packed" data. + +* **Vectorize**: An operation that uses SIMD instructions to operate over a vector is often referred to as "vectorized". + +* **Autovectorization**: Also known as _implicit vectorization_. This is when a compiler can automatically recognize a situation where scalar instructions may be replaced with SIMD instructions, and use those instead. + +* **Scalar:** "Scalar" in mathematical contexts refers to values that can be represented as a single element, mostly numbers like 6, 3.14, or -2. It can also be used to describe "scalar operations" that use strictly scalar values, like addition. This term is mostly used to differentiate between vectorized operations that use SIMD instructions and scalar operations that don't. + +* **Lane:** A single element position within a vector is called a lane. If you have `N` lanes available then they're numbered from `0` to `N-1` when referring to them, again like an array. The biggest difference between an array element and a vector lane is that in general is *relatively costly* to access an individual lane value. On most architectures, the vector has to be pushed out of the SIMD register onto the stack, then an individual lane is accessed while it's on the stack (and possibly the stack value is read back into a register). For this reason, when working with SIMD you should avoid reading or writing the value of an individual lane during hot loops. + +* **Bit Widths:** When talking about SIMD, the bit widths used are the bit size of the vectors involved, *not* the individual elements. So "128-bit SIMD" has 128-bit vectors, and that might be `f32x4`, `i32x4`, `i16x8`, or other variations. While 128-bit SIMD is the most common, there's also 64-bit, 256-bit, and even 512-bit on the newest CPUs. + +* **Vector Register:** The extra-wide registers that are used for SIMD operations are commonly called vector registers, though you may also see "SIMD registers", vendor names for specific features, or even "floating-point register" as it is common for the same registers to be used with both scalar and vectorized floating-point operations. + +* **Vertical:** When an operation is "vertical", each lane processes individually without regard to the other lanes in the same vector. For example, a "vertical add" between two vectors would add lane 0 in `a` with lane 0 in `b`, with the total in lane 0 of `out`, and then the same thing for lanes 1, 2, etc. Most SIMD operations are vertical operations, so if your problem is a vertical problem then you can probably solve it with SIMD. + +* **Horizontal:** When an operation is "horizontal", the lanes within a single vector interact in some way. A "horizontal add" might add up lane 0 of `a` with lane 1 of `a`, with the total in lane 0 of `out`. + +* **Target Feature:** Rust calls a CPU architecture extension a `target_feature`. Proper SIMD requires various CPU extensions to be enabled (details below). Don't confuse this with `feature`, which is a Cargo crate concept. + +## Target Features + +When using SIMD, you should be familiar with the CPU feature set that you're targeting. + +On `arm` and `aarch64` it's fairly simple. There's just one CPU feature that controls if SIMD is available: `neon` (or "NEON", all caps, as the ARM docs often put it). Neon registers can be used as 64-bit or 128-bit. When doing 128-bit operations it just uses two 64-bit registers as a single 128-bit register. + +> By default, the `aarch64`, `arm`, and `thumb` Rust targets generally do not enable `neon` unless it's in the target string. + +On `x86` and `x86_64` it's slightly more complicated. The SIMD support is split into many levels: +* 128-bit: `sse`, `sse2`, `sse3`, `ssse3` (not a typo!), `sse4.1`, `sse4.2`, `sse4a` (AMD only) +* 256-bit (mostly): `avx`, `avx2`, `fma` +* 512-bit (mostly): a *wide* range of `avx512` variations + +The list notes the bit widths available at each feature level, though the operations of the more advanced features can generally be used with the smaller register sizes as well. For example, new operations introduced in `avx` generally have a 128-bit form as well as a 256-bit form. This means that even if you only do 128-bit work you can still benefit from the later feature levels. + +> By default, the `i686` and `x86_64` Rust targets enable `sse` and `sse2`. + +### Selecting Additional Target Features + +If you want to enable support for a target feature within your build, generally you should use a [target-feature](https://rust-lang.github.io/packed_simd/perf-guide/target-feature/rustflags.html#target-feature) setting within you `RUSTFLAGS` setting. + +If you know that you're targeting a specific CPU you can instead use the [target-cpu](https://rust-lang.github.io/packed_simd/perf-guide/target-feature/rustflags.html#target-cpu) flag and the compiler will enable the correct set of features for that CPU. + +The [Steam Hardware Survey](https://store.steampowered.com/hwsurvey/Steam-Hardware-Software-Survey-Welcome-to-Steam) is one of the few places with data on how common various CPU features are. The dataset is limited to "the kinds of computers owned by people who play computer games", so the info only covers `x86`/`x86_64`, and it also probably skews to slightly higher quality computers than average. Still, we can see that the `sse` levels have very high support, `avx` and `avx2` are quite common as well, and the `avx-512` family is still so early in adoption you can barely find it in consumer grade stuff. + +## Running a program compiled for a CPU feature level that the CPU doesn't support is automatic undefined behavior. + +This means that if you build your program with `avx` support enabled and run it on a CPU without `avx` support, it's **instantly** undefined behavior. + +Even without an `unsafe` block in sight. + +This is no bug in Rust, or soundness hole in the type system. You just plain can't make a CPU do what it doesn't know how to do. + +This is why the various Rust targets *don't* enable many CPU feature flags by default: requiring a more advanced CPU makes the final binary *less* portable. + +So please select an appropriate CPU feature level when building your programs. + +## Size, Alignment, and Unsafe Code + +Most of the portable SIMD API is designed to allow the user to gloss over the details of different architectures and avoid using unsafe code. However, there are plenty of reasons to want to use unsafe code with these SIMD types, such as using an intrinsic function from `core::arch` to further accelerate particularly specialized SIMD operations on a given platform, while still using the portable API elsewhere. For these cases, there are some rules to keep in mind. + +Fortunately, most SIMD types have a fairly predictable size. `i32x4` is bit-equivalent to `[i32; 4]` and so can be bitcast to it, e.g. using [`mem::transmute`], though the API usually offers a safe cast you can use instead. + +However, this is not the same as alignment. Computer architectures generally prefer aligned accesses, especially when moving data between memory and vector registers, and while some support specialized operations that can bend the rules to help with this, unaligned access is still typically slow, or even undefined behavior. In addition, different architectures can require different alignments when interacting with their native SIMD types. For this reason, any `#[repr(simd)]` type has a non-portable alignment. If it is necessary to directly interact with the alignment of these types, it should be via [`mem::align_of`]. + +[`mem::transmute`]: https://doc.rust-lang.org/core/mem/fn.transmute.html +[`mem::align_of`]: https://doc.rust-lang.org/core/mem/fn.align_of.html \ No newline at end of file diff --git a/library/portable-simd/crates/core_simd/Cargo.toml b/library/portable-simd/crates/core_simd/Cargo.toml new file mode 100644 index 0000000000..a103ef115a --- /dev/null +++ b/library/portable-simd/crates/core_simd/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "core_simd" +version = "0.1.0" +edition = "2021" +homepage = "https://github.com/rust-lang/portable-simd" +repository = "https://github.com/rust-lang/portable-simd" +keywords = ["core", "simd", "intrinsics"] +categories = ["hardware-support", "no-std"] +license = "MIT OR Apache-2.0" + +[features] +default = ["std", "generic_const_exprs"] +std = [] +generic_const_exprs = [] + +[target.'cfg(target_arch = "wasm32")'.dev-dependencies.wasm-bindgen] +version = "0.2" + +[dev-dependencies.wasm-bindgen-test] +version = "0.3" + +[dev-dependencies.proptest] +version = "0.10" +default-features = false +features = ["alloc"] + +[dev-dependencies.test_helpers] +path = "../test_helpers" diff --git a/library/portable-simd/crates/core_simd/LICENSE-APACHE b/library/portable-simd/crates/core_simd/LICENSE-APACHE new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/library/portable-simd/crates/core_simd/LICENSE-APACHE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/library/portable-simd/crates/core_simd/LICENSE-MIT b/library/portable-simd/crates/core_simd/LICENSE-MIT new file mode 100644 index 0000000000..0e9d2f43a0 --- /dev/null +++ b/library/portable-simd/crates/core_simd/LICENSE-MIT @@ -0,0 +1,19 @@ +Copyright (c) 2020 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/library/portable-simd/crates/core_simd/examples/matrix_inversion.rs b/library/portable-simd/crates/core_simd/examples/matrix_inversion.rs new file mode 100644 index 0000000000..c51a566deb --- /dev/null +++ b/library/portable-simd/crates/core_simd/examples/matrix_inversion.rs @@ -0,0 +1,316 @@ +//! 4x4 matrix inverse +// Code ported from the `packed_simd` crate +// Run this code with `cargo test --example matrix_inversion` +#![feature(array_chunks, portable_simd)] +use core_simd::simd::*; +use Which::*; + +// Gotta define our own 4x4 matrix since Rust doesn't ship multidim arrays yet :^) +#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)] +pub struct Matrix4x4([[f32; 4]; 4]); + +#[allow(clippy::too_many_lines)] +pub fn scalar_inv4x4(m: Matrix4x4) -> Option { + let m = m.0; + + #[rustfmt::skip] + let mut inv = [ + // row 0: + [ + // 0,0: + m[1][1] * m[2][2] * m[3][3] - + m[1][1] * m[2][3] * m[3][2] - + m[2][1] * m[1][2] * m[3][3] + + m[2][1] * m[1][3] * m[3][2] + + m[3][1] * m[1][2] * m[2][3] - + m[3][1] * m[1][3] * m[2][2], + // 0,1: + -m[0][1] * m[2][2] * m[3][3] + + m[0][1] * m[2][3] * m[3][2] + + m[2][1] * m[0][2] * m[3][3] - + m[2][1] * m[0][3] * m[3][2] - + m[3][1] * m[0][2] * m[2][3] + + m[3][1] * m[0][3] * m[2][2], + // 0,2: + m[0][1] * m[1][2] * m[3][3] - + m[0][1] * m[1][3] * m[3][2] - + m[1][1] * m[0][2] * m[3][3] + + m[1][1] * m[0][3] * m[3][2] + + m[3][1] * m[0][2] * m[1][3] - + m[3][1] * m[0][3] * m[1][2], + // 0,3: + -m[0][1] * m[1][2] * m[2][3] + + m[0][1] * m[1][3] * m[2][2] + + m[1][1] * m[0][2] * m[2][3] - + m[1][1] * m[0][3] * m[2][2] - + m[2][1] * m[0][2] * m[1][3] + + m[2][1] * m[0][3] * m[1][2], + ], + // row 1 + [ + // 1,0: + -m[1][0] * m[2][2] * m[3][3] + + m[1][0] * m[2][3] * m[3][2] + + m[2][0] * m[1][2] * m[3][3] - + m[2][0] * m[1][3] * m[3][2] - + m[3][0] * m[1][2] * m[2][3] + + m[3][0] * m[1][3] * m[2][2], + // 1,1: + m[0][0] * m[2][2] * m[3][3] - + m[0][0] * m[2][3] * m[3][2] - + m[2][0] * m[0][2] * m[3][3] + + m[2][0] * m[0][3] * m[3][2] + + m[3][0] * m[0][2] * m[2][3] - + m[3][0] * m[0][3] * m[2][2], + // 1,2: + -m[0][0] * m[1][2] * m[3][3] + + m[0][0] * m[1][3] * m[3][2] + + m[1][0] * m[0][2] * m[3][3] - + m[1][0] * m[0][3] * m[3][2] - + m[3][0] * m[0][2] * m[1][3] + + m[3][0] * m[0][3] * m[1][2], + // 1,3: + m[0][0] * m[1][2] * m[2][3] - + m[0][0] * m[1][3] * m[2][2] - + m[1][0] * m[0][2] * m[2][3] + + m[1][0] * m[0][3] * m[2][2] + + m[2][0] * m[0][2] * m[1][3] - + m[2][0] * m[0][3] * m[1][2], + ], + // row 2 + [ + // 2,0: + m[1][0] * m[2][1] * m[3][3] - + m[1][0] * m[2][3] * m[3][1] - + m[2][0] * m[1][1] * m[3][3] + + m[2][0] * m[1][3] * m[3][1] + + m[3][0] * m[1][1] * m[2][3] - + m[3][0] * m[1][3] * m[2][1], + // 2,1: + -m[0][0] * m[2][1] * m[3][3] + + m[0][0] * m[2][3] * m[3][1] + + m[2][0] * m[0][1] * m[3][3] - + m[2][0] * m[0][3] * m[3][1] - + m[3][0] * m[0][1] * m[2][3] + + m[3][0] * m[0][3] * m[2][1], + // 2,2: + m[0][0] * m[1][1] * m[3][3] - + m[0][0] * m[1][3] * m[3][1] - + m[1][0] * m[0][1] * m[3][3] + + m[1][0] * m[0][3] * m[3][1] + + m[3][0] * m[0][1] * m[1][3] - + m[3][0] * m[0][3] * m[1][1], + // 2,3: + -m[0][0] * m[1][1] * m[2][3] + + m[0][0] * m[1][3] * m[2][1] + + m[1][0] * m[0][1] * m[2][3] - + m[1][0] * m[0][3] * m[2][1] - + m[2][0] * m[0][1] * m[1][3] + + m[2][0] * m[0][3] * m[1][1], + ], + // row 3 + [ + // 3,0: + -m[1][0] * m[2][1] * m[3][2] + + m[1][0] * m[2][2] * m[3][1] + + m[2][0] * m[1][1] * m[3][2] - + m[2][0] * m[1][2] * m[3][1] - + m[3][0] * m[1][1] * m[2][2] + + m[3][0] * m[1][2] * m[2][1], + // 3,1: + m[0][0] * m[2][1] * m[3][2] - + m[0][0] * m[2][2] * m[3][1] - + m[2][0] * m[0][1] * m[3][2] + + m[2][0] * m[0][2] * m[3][1] + + m[3][0] * m[0][1] * m[2][2] - + m[3][0] * m[0][2] * m[2][1], + // 3,2: + -m[0][0] * m[1][1] * m[3][2] + + m[0][0] * m[1][2] * m[3][1] + + m[1][0] * m[0][1] * m[3][2] - + m[1][0] * m[0][2] * m[3][1] - + m[3][0] * m[0][1] * m[1][2] + + m[3][0] * m[0][2] * m[1][1], + // 3,3: + m[0][0] * m[1][1] * m[2][2] - + m[0][0] * m[1][2] * m[2][1] - + m[1][0] * m[0][1] * m[2][2] + + m[1][0] * m[0][2] * m[2][1] + + m[2][0] * m[0][1] * m[1][2] - + m[2][0] * m[0][2] * m[1][1], + ], + ]; + + let det = m[0][0] * inv[0][0] + m[0][1] * inv[1][0] + m[0][2] * inv[2][0] + m[0][3] * inv[3][0]; + if det == 0. { + return None; + } + + let det_inv = 1. / det; + + for row in &mut inv { + for elem in row.iter_mut() { + *elem *= det_inv; + } + } + + Some(Matrix4x4(inv)) +} + +pub fn simd_inv4x4(m: Matrix4x4) -> Option { + let m = m.0; + let m_0 = f32x4::from_array(m[0]); + let m_1 = f32x4::from_array(m[1]); + let m_2 = f32x4::from_array(m[2]); + let m_3 = f32x4::from_array(m[3]); + + const SHUFFLE01: [Which; 4] = [First(0), First(1), Second(0), Second(1)]; + const SHUFFLE02: [Which; 4] = [First(0), First(2), Second(0), Second(2)]; + const SHUFFLE13: [Which; 4] = [First(1), First(3), Second(1), Second(3)]; + const SHUFFLE23: [Which; 4] = [First(2), First(3), Second(2), Second(3)]; + + let tmp = simd_swizzle!(m_0, m_1, SHUFFLE01); + let row1 = simd_swizzle!(m_2, m_3, SHUFFLE01); + + let row0 = simd_swizzle!(tmp, row1, SHUFFLE02); + let row1 = simd_swizzle!(row1, tmp, SHUFFLE13); + + let tmp = simd_swizzle!(m_0, m_1, SHUFFLE23); + let row3 = simd_swizzle!(m_2, m_3, SHUFFLE23); + let row2 = simd_swizzle!(tmp, row3, SHUFFLE02); + let row3 = simd_swizzle!(row3, tmp, SHUFFLE13); + + let tmp = (row2 * row3).reverse().rotate_lanes_right::<2>(); + let minor0 = row1 * tmp; + let minor1 = row0 * tmp; + let tmp = tmp.rotate_lanes_right::<2>(); + let minor0 = (row1 * tmp) - minor0; + let minor1 = (row0 * tmp) - minor1; + let minor1 = minor1.rotate_lanes_right::<2>(); + + let tmp = (row1 * row2).reverse().rotate_lanes_right::<2>(); + let minor0 = (row3 * tmp) + minor0; + let minor3 = row0 * tmp; + let tmp = tmp.rotate_lanes_right::<2>(); + + let minor0 = minor0 - row3 * tmp; + let minor3 = row0 * tmp - minor3; + let minor3 = minor3.rotate_lanes_right::<2>(); + + let tmp = (row3 * row1.rotate_lanes_right::<2>()) + .reverse() + .rotate_lanes_right::<2>(); + let row2 = row2.rotate_lanes_right::<2>(); + let minor0 = row2 * tmp + minor0; + let minor2 = row0 * tmp; + let tmp = tmp.rotate_lanes_right::<2>(); + let minor0 = minor0 - row2 * tmp; + let minor2 = row0 * tmp - minor2; + let minor2 = minor2.rotate_lanes_right::<2>(); + + let tmp = (row0 * row1).reverse().rotate_lanes_right::<2>(); + let minor2 = minor2 + row3 * tmp; + let minor3 = row2 * tmp - minor3; + let tmp = tmp.rotate_lanes_right::<2>(); + let minor2 = row3 * tmp - minor2; + let minor3 = minor3 - row2 * tmp; + + let tmp = (row0 * row3).reverse().rotate_lanes_right::<2>(); + let minor1 = minor1 - row2 * tmp; + let minor2 = row1 * tmp + minor2; + let tmp = tmp.rotate_lanes_right::<2>(); + let minor1 = row2 * tmp + minor1; + let minor2 = minor2 - row1 * tmp; + + let tmp = (row0 * row2).reverse().rotate_lanes_right::<2>(); + let minor1 = row3 * tmp + minor1; + let minor3 = minor3 - row1 * tmp; + let tmp = tmp.rotate_lanes_right::<2>(); + let minor1 = minor1 - row3 * tmp; + let minor3 = row1 * tmp + minor3; + + let det = row0 * minor0; + let det = det.rotate_lanes_right::<2>() + det; + let det = det.reverse().rotate_lanes_right::<2>() + det; + + if det.horizontal_sum() == 0. { + return None; + } + // calculate the reciprocal + let tmp = f32x4::splat(1.0) / det; + let det = tmp + tmp - det * tmp * tmp; + + let res0 = minor0 * det; + let res1 = minor1 * det; + let res2 = minor2 * det; + let res3 = minor3 * det; + + let mut m = m; + + m[0] = res0.to_array(); + m[1] = res1.to_array(); + m[2] = res2.to_array(); + m[3] = res3.to_array(); + + Some(Matrix4x4(m)) +} + +#[cfg(test)] +#[rustfmt::skip] +mod tests { + use super::*; + + #[test] + fn test() { + let tests: &[(Matrix4x4, Option)] = &[ + // Identity: + (Matrix4x4([ + [1., 0., 0., 0.], + [0., 1., 0., 0.], + [0., 0., 1., 0.], + [0., 0., 0., 1.], + ]), + Some(Matrix4x4([ + [1., 0., 0., 0.], + [0., 1., 0., 0.], + [0., 0., 1., 0.], + [0., 0., 0., 1.], + ])) + ), + // None: + (Matrix4x4([ + [1., 2., 3., 4.], + [12., 11., 10., 9.], + [5., 6., 7., 8.], + [16., 15., 14., 13.], + ]), + None + ), + // Other: + (Matrix4x4([ + [1., 1., 1., 0.], + [0., 3., 1., 2.], + [2., 3., 1., 0.], + [1., 0., 2., 1.], + ]), + Some(Matrix4x4([ + [-3., -0.5, 1.5, 1.0], + [ 1., 0.25, -0.25, -0.5], + [ 3., 0.25, -1.25, -0.5], + [-3., 0.0, 1.0, 1.0], + ])) + ), + + + ]; + + for &(input, output) in tests { + assert_eq!(scalar_inv4x4(input), output); + assert_eq!(simd_inv4x4(input), output); + } + } +} + +fn main() { + // Empty main to make cargo happy +} diff --git a/library/portable-simd/crates/core_simd/examples/nbody.rs b/library/portable-simd/crates/core_simd/examples/nbody.rs new file mode 100644 index 0000000000..779575985e --- /dev/null +++ b/library/portable-simd/crates/core_simd/examples/nbody.rs @@ -0,0 +1,193 @@ +#![cfg_attr(feature = "std", feature(portable_simd))] + +/// Benchmarks game nbody code +/// Taken from the `packed_simd` crate +/// Run this benchmark with `cargo test --example nbody` +#[cfg(feature = "std")] +mod nbody { + use core_simd::*; + + use std::f64::consts::PI; + const SOLAR_MASS: f64 = 4.0 * PI * PI; + const DAYS_PER_YEAR: f64 = 365.24; + + #[derive(Debug, Clone, Copy)] + struct Body { + pub x: f64x4, + pub v: f64x4, + pub mass: f64, + } + + const N_BODIES: usize = 5; + const BODIES: [Body; N_BODIES] = [ + // sun: + Body { + x: f64x4::from_array([0., 0., 0., 0.]), + v: f64x4::from_array([0., 0., 0., 0.]), + mass: SOLAR_MASS, + }, + // jupiter: + Body { + x: f64x4::from_array([ + 4.84143144246472090e+00, + -1.16032004402742839e+00, + -1.03622044471123109e-01, + 0., + ]), + v: f64x4::from_array([ + 1.66007664274403694e-03 * DAYS_PER_YEAR, + 7.69901118419740425e-03 * DAYS_PER_YEAR, + -6.90460016972063023e-05 * DAYS_PER_YEAR, + 0., + ]), + mass: 9.54791938424326609e-04 * SOLAR_MASS, + }, + // saturn: + Body { + x: f64x4::from_array([ + 8.34336671824457987e+00, + 4.12479856412430479e+00, + -4.03523417114321381e-01, + 0., + ]), + v: f64x4::from_array([ + -2.76742510726862411e-03 * DAYS_PER_YEAR, + 4.99852801234917238e-03 * DAYS_PER_YEAR, + 2.30417297573763929e-05 * DAYS_PER_YEAR, + 0., + ]), + mass: 2.85885980666130812e-04 * SOLAR_MASS, + }, + // uranus: + Body { + x: f64x4::from_array([ + 1.28943695621391310e+01, + -1.51111514016986312e+01, + -2.23307578892655734e-01, + 0., + ]), + v: f64x4::from_array([ + 2.96460137564761618e-03 * DAYS_PER_YEAR, + 2.37847173959480950e-03 * DAYS_PER_YEAR, + -2.96589568540237556e-05 * DAYS_PER_YEAR, + 0., + ]), + mass: 4.36624404335156298e-05 * SOLAR_MASS, + }, + // neptune: + Body { + x: f64x4::from_array([ + 1.53796971148509165e+01, + -2.59193146099879641e+01, + 1.79258772950371181e-01, + 0., + ]), + v: f64x4::from_array([ + 2.68067772490389322e-03 * DAYS_PER_YEAR, + 1.62824170038242295e-03 * DAYS_PER_YEAR, + -9.51592254519715870e-05 * DAYS_PER_YEAR, + 0., + ]), + mass: 5.15138902046611451e-05 * SOLAR_MASS, + }, + ]; + + fn offset_momentum(bodies: &mut [Body; N_BODIES]) { + let (sun, rest) = bodies.split_at_mut(1); + let sun = &mut sun[0]; + for body in rest { + let m_ratio = body.mass / SOLAR_MASS; + sun.v -= body.v * m_ratio; + } + } + + fn energy(bodies: &[Body; N_BODIES]) -> f64 { + let mut e = 0.; + for i in 0..N_BODIES { + let bi = &bodies[i]; + e += bi.mass * (bi.v * bi.v).horizontal_sum() * 0.5; + for bj in bodies.iter().take(N_BODIES).skip(i + 1) { + let dx = bi.x - bj.x; + e -= bi.mass * bj.mass / (dx * dx).horizontal_sum().sqrt() + } + } + e + } + + fn advance(bodies: &mut [Body; N_BODIES], dt: f64) { + const N: usize = N_BODIES * (N_BODIES - 1) / 2; + + // compute distance between bodies: + let mut r = [f64x4::splat(0.); N]; + { + let mut i = 0; + for j in 0..N_BODIES { + for k in j + 1..N_BODIES { + r[i] = bodies[j].x - bodies[k].x; + i += 1; + } + } + } + + let mut mag = [0.0; N]; + for i in (0..N).step_by(2) { + let d2s = f64x2::from_array([ + (r[i] * r[i]).horizontal_sum(), + (r[i + 1] * r[i + 1]).horizontal_sum(), + ]); + let dmags = f64x2::splat(dt) / (d2s * d2s.sqrt()); + mag[i] = dmags[0]; + mag[i + 1] = dmags[1]; + } + + let mut i = 0; + for j in 0..N_BODIES { + for k in j + 1..N_BODIES { + let f = r[i] * mag[i]; + bodies[j].v -= f * bodies[k].mass; + bodies[k].v += f * bodies[j].mass; + i += 1 + } + } + for body in bodies { + body.x += dt * body.v + } + } + + pub fn run(n: usize) -> (f64, f64) { + let mut bodies = BODIES; + offset_momentum(&mut bodies); + let energy_before = energy(&bodies); + for _ in 0..n { + advance(&mut bodies, 0.01); + } + let energy_after = energy(&bodies); + + (energy_before, energy_after) + } +} + +#[cfg(feature = "std")] +#[cfg(test)] +mod tests { + // Good enough for demonstration purposes, not going for strictness here. + fn approx_eq_f64(a: f64, b: f64) -> bool { + (a - b).abs() < 0.00001 + } + #[test] + fn test() { + const OUTPUT: [f64; 2] = [-0.169075164, -0.169087605]; + let (energy_before, energy_after) = super::nbody::run(1000); + assert!(approx_eq_f64(energy_before, OUTPUT[0])); + assert!(approx_eq_f64(energy_after, OUTPUT[1])); + } +} + +fn main() { + #[cfg(feature = "std")] + { + let (energy_before, energy_after) = nbody::run(1000); + println!("Energy before: {}", energy_before); + println!("Energy after: {}", energy_after); + } +} diff --git a/library/portable-simd/crates/core_simd/src/comparisons.rs b/library/portable-simd/crates/core_simd/src/comparisons.rs new file mode 100644 index 0000000000..8c51baca8e --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/comparisons.rs @@ -0,0 +1,50 @@ +use crate::simd::intrinsics; +use crate::simd::{LaneCount, Mask, Simd, SimdElement, SupportedLaneCount}; + +impl Simd +where + T: SimdElement + PartialEq, + LaneCount: SupportedLaneCount, +{ + /// Test if each lane is equal to the corresponding lane in `other`. + #[inline] + pub fn lanes_eq(self, other: Self) -> Mask { + unsafe { Mask::from_int_unchecked(intrinsics::simd_eq(self, other)) } + } + + /// Test if each lane is not equal to the corresponding lane in `other`. + #[inline] + pub fn lanes_ne(self, other: Self) -> Mask { + unsafe { Mask::from_int_unchecked(intrinsics::simd_ne(self, other)) } + } +} + +impl Simd +where + T: SimdElement + PartialOrd, + LaneCount: SupportedLaneCount, +{ + /// Test if each lane is less than the corresponding lane in `other`. + #[inline] + pub fn lanes_lt(self, other: Self) -> Mask { + unsafe { Mask::from_int_unchecked(intrinsics::simd_lt(self, other)) } + } + + /// Test if each lane is greater than the corresponding lane in `other`. + #[inline] + pub fn lanes_gt(self, other: Self) -> Mask { + unsafe { Mask::from_int_unchecked(intrinsics::simd_gt(self, other)) } + } + + /// Test if each lane is less than or equal to the corresponding lane in `other`. + #[inline] + pub fn lanes_le(self, other: Self) -> Mask { + unsafe { Mask::from_int_unchecked(intrinsics::simd_le(self, other)) } + } + + /// Test if each lane is greater than or equal to the corresponding lane in `other`. + #[inline] + pub fn lanes_ge(self, other: Self) -> Mask { + unsafe { Mask::from_int_unchecked(intrinsics::simd_ge(self, other)) } + } +} diff --git a/library/portable-simd/crates/core_simd/src/core_simd_docs.md b/library/portable-simd/crates/core_simd/src/core_simd_docs.md new file mode 100644 index 0000000000..15e8ed0253 --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/core_simd_docs.md @@ -0,0 +1,4 @@ +Portable SIMD module. + +This module offers a portable abstraction for SIMD operations +that is not bound to any particular hardware architecture. diff --git a/library/portable-simd/crates/core_simd/src/fmt.rs b/library/portable-simd/crates/core_simd/src/fmt.rs new file mode 100644 index 0000000000..dbd9839c4b --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/fmt.rs @@ -0,0 +1,39 @@ +use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount}; +use core::fmt; + +macro_rules! impl_fmt_trait { + { $($trait:ident,)* } => { + $( + impl fmt::$trait for Simd + where + LaneCount: SupportedLaneCount, + T: SimdElement + fmt::$trait, + { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + #[repr(transparent)] + struct Wrapper<'a, T: fmt::$trait>(&'a T); + + impl fmt::Debug for Wrapper<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } + } + + f.debug_list() + .entries(self.as_array().iter().map(|x| Wrapper(x))) + .finish() + } + } + )* + } +} + +impl_fmt_trait! { + Debug, + Binary, + LowerExp, + UpperExp, + Octal, + LowerHex, + UpperHex, +} diff --git a/library/portable-simd/crates/core_simd/src/intrinsics.rs b/library/portable-simd/crates/core_simd/src/intrinsics.rs new file mode 100644 index 0000000000..6a6d26d10a --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/intrinsics.rs @@ -0,0 +1,115 @@ +//! This module contains the LLVM intrinsics bindings that provide the functionality for this +//! crate. +//! +//! The LLVM assembly language is documented here: + +/// These intrinsics aren't linked directly from LLVM and are mostly undocumented, however they are +/// simply lowered to the matching LLVM instructions by the compiler. The associated instruction +/// is documented alongside each intrinsic. +extern "platform-intrinsic" { + /// add/fadd + pub(crate) fn simd_add(x: T, y: T) -> T; + + /// sub/fsub + pub(crate) fn simd_sub(x: T, y: T) -> T; + + /// mul/fmul + pub(crate) fn simd_mul(x: T, y: T) -> T; + + /// udiv/sdiv/fdiv + pub(crate) fn simd_div(x: T, y: T) -> T; + + /// urem/srem/frem + pub(crate) fn simd_rem(x: T, y: T) -> T; + + /// shl + pub(crate) fn simd_shl(x: T, y: T) -> T; + + /// lshr/ashr + pub(crate) fn simd_shr(x: T, y: T) -> T; + + /// and + pub(crate) fn simd_and(x: T, y: T) -> T; + + /// or + pub(crate) fn simd_or(x: T, y: T) -> T; + + /// xor + pub(crate) fn simd_xor(x: T, y: T) -> T; + + /// fptoui/fptosi/uitofp/sitofp + pub(crate) fn simd_cast(x: T) -> U; + + /// neg/fneg + pub(crate) fn simd_neg(x: T) -> T; + + /// fabs + pub(crate) fn simd_fabs(x: T) -> T; + + pub(crate) fn simd_eq(x: T, y: T) -> U; + pub(crate) fn simd_ne(x: T, y: T) -> U; + pub(crate) fn simd_lt(x: T, y: T) -> U; + pub(crate) fn simd_le(x: T, y: T) -> U; + pub(crate) fn simd_gt(x: T, y: T) -> U; + pub(crate) fn simd_ge(x: T, y: T) -> U; + + // shufflevector + pub(crate) fn simd_shuffle(x: T, y: T, idx: U) -> V; + + pub(crate) fn simd_gather(val: T, ptr: U, mask: V) -> T; + pub(crate) fn simd_scatter(val: T, ptr: U, mask: V); + + // {s,u}add.sat + pub(crate) fn simd_saturating_add(x: T, y: T) -> T; + + // {s,u}sub.sat + pub(crate) fn simd_saturating_sub(x: T, y: T) -> T; + + // reductions + pub(crate) fn simd_reduce_add_ordered(x: T, y: U) -> U; + pub(crate) fn simd_reduce_mul_ordered(x: T, y: U) -> U; + #[allow(unused)] + pub(crate) fn simd_reduce_all(x: T) -> bool; + #[allow(unused)] + pub(crate) fn simd_reduce_any(x: T) -> bool; + pub(crate) fn simd_reduce_max(x: T) -> U; + pub(crate) fn simd_reduce_min(x: T) -> U; + pub(crate) fn simd_reduce_and(x: T) -> U; + pub(crate) fn simd_reduce_or(x: T) -> U; + pub(crate) fn simd_reduce_xor(x: T) -> U; + + // truncate integer vector to bitmask + #[allow(unused)] + pub(crate) fn simd_bitmask(x: T) -> U; + + // select + pub(crate) fn simd_select(m: M, a: T, b: T) -> T; + #[allow(unused)] + pub(crate) fn simd_select_bitmask(m: M, a: T, b: T) -> T; +} + +#[cfg(feature = "std")] +mod std { + extern "platform-intrinsic" { + // ceil + pub(crate) fn simd_ceil(x: T) -> T; + + // floor + pub(crate) fn simd_floor(x: T) -> T; + + // round + pub(crate) fn simd_round(x: T) -> T; + + // trunc + pub(crate) fn simd_trunc(x: T) -> T; + + // fsqrt + pub(crate) fn simd_fsqrt(x: T) -> T; + + // fma + pub(crate) fn simd_fma(x: T, y: T, z: T) -> T; + } +} + +#[cfg(feature = "std")] +pub(crate) use crate::simd::intrinsics::std::*; diff --git a/library/portable-simd/crates/core_simd/src/iter.rs b/library/portable-simd/crates/core_simd/src/iter.rs new file mode 100644 index 0000000000..3275b4db8e --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/iter.rs @@ -0,0 +1,58 @@ +use crate::simd::{LaneCount, Simd, SupportedLaneCount}; +use core::{ + iter::{Product, Sum}, + ops::{Add, Mul}, +}; + +macro_rules! impl_traits { + { $type:ty } => { + impl Sum for Simd<$type, LANES> + where + LaneCount: SupportedLaneCount, + { + fn sum>(iter: I) -> Self { + iter.fold(Simd::splat(0 as $type), Add::add) + } + } + + impl Product for Simd<$type, LANES> + where + LaneCount: SupportedLaneCount, + { + fn product>(iter: I) -> Self { + iter.fold(Simd::splat(1 as $type), Mul::mul) + } + } + + impl<'a, const LANES: usize> Sum<&'a Self> for Simd<$type, LANES> + where + LaneCount: SupportedLaneCount, + { + fn sum>(iter: I) -> Self { + iter.fold(Simd::splat(0 as $type), Add::add) + } + } + + impl<'a, const LANES: usize> Product<&'a Self> for Simd<$type, LANES> + where + LaneCount: SupportedLaneCount, + { + fn product>(iter: I) -> Self { + iter.fold(Simd::splat(1 as $type), Mul::mul) + } + } + } +} + +impl_traits! { f32 } +impl_traits! { f64 } +impl_traits! { u8 } +impl_traits! { u16 } +impl_traits! { u32 } +impl_traits! { u64 } +impl_traits! { usize } +impl_traits! { i8 } +impl_traits! { i16 } +impl_traits! { i32 } +impl_traits! { i64 } +impl_traits! { isize } diff --git a/library/portable-simd/crates/core_simd/src/lane_count.rs b/library/portable-simd/crates/core_simd/src/lane_count.rs new file mode 100644 index 0000000000..b017e7d137 --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/lane_count.rs @@ -0,0 +1,48 @@ +mod sealed { + pub trait Sealed {} +} +use sealed::Sealed; + +/// A type representing a vector lane count. +pub struct LaneCount; + +impl LaneCount { + /// The number of bytes in a bitmask with this many lanes. + pub const BITMASK_LEN: usize = (LANES + 7) / 8; +} + +/// Helper trait for vector lane counts. +pub trait SupportedLaneCount: Sealed { + #[doc(hidden)] + type BitMask: Copy + Default + AsRef<[u8]> + AsMut<[u8]>; + + #[doc(hidden)] + type IntBitMask; +} + +impl Sealed for LaneCount {} + +impl SupportedLaneCount for LaneCount<1> { + type BitMask = [u8; 1]; + type IntBitMask = u8; +} +impl SupportedLaneCount for LaneCount<2> { + type BitMask = [u8; 1]; + type IntBitMask = u8; +} +impl SupportedLaneCount for LaneCount<4> { + type BitMask = [u8; 1]; + type IntBitMask = u8; +} +impl SupportedLaneCount for LaneCount<8> { + type BitMask = [u8; 1]; + type IntBitMask = u8; +} +impl SupportedLaneCount for LaneCount<16> { + type BitMask = [u8; 2]; + type IntBitMask = u16; +} +impl SupportedLaneCount for LaneCount<32> { + type BitMask = [u8; 4]; + type IntBitMask = u32; +} diff --git a/library/portable-simd/crates/core_simd/src/lib.rs b/library/portable-simd/crates/core_simd/src/lib.rs new file mode 100644 index 0000000000..960a664008 --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/lib.rs @@ -0,0 +1,21 @@ +#![cfg_attr(not(feature = "std"), no_std)] +#![feature( + const_fn_trait_bound, + decl_macro, + platform_intrinsics, + repr_simd, + simd_ffi, + staged_api, + stdsimd +)] +#![cfg_attr(feature = "generic_const_exprs", feature(generic_const_exprs))] +#![cfg_attr(feature = "generic_const_exprs", allow(incomplete_features))] +#![warn(missing_docs)] +#![deny(unsafe_op_in_unsafe_fn)] +#![unstable(feature = "portable_simd", issue = "86656")] +//! Portable SIMD module. + +#[path = "mod.rs"] +mod core_simd; +pub use self::core_simd::simd; +pub use simd::*; diff --git a/library/portable-simd/crates/core_simd/src/masks.rs b/library/portable-simd/crates/core_simd/src/masks.rs new file mode 100644 index 0000000000..d460da0d04 --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/masks.rs @@ -0,0 +1,545 @@ +//! Types and traits associated with masking lanes of vectors. +//! Types representing +#![allow(non_camel_case_types)] + +#[cfg_attr( + not(all(target_arch = "x86_64", target_feature = "avx512f")), + path = "masks/full_masks.rs" +)] +#[cfg_attr( + all(target_arch = "x86_64", target_feature = "avx512f"), + path = "masks/bitmask.rs" +)] +mod mask_impl; + +use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount}; +use core::cmp::Ordering; +use core::fmt; + +mod sealed { + use super::*; + + /// Not only does this seal the `MaskElement` trait, but these functions prevent other traits + /// from bleeding into the parent bounds. + /// + /// For example, `eq` could be provided by requiring `MaskElement: PartialEq`, but that would + /// prevent us from ever removing that bound, or from implementing `MaskElement` on + /// non-`PartialEq` types in the future. + pub trait Sealed { + fn valid(values: Simd) -> bool + where + LaneCount: SupportedLaneCount, + Self: SimdElement; + + fn eq(self, other: Self) -> bool; + + const TRUE: Self; + + const FALSE: Self; + } +} +use sealed::Sealed; + +/// Marker trait for types that may be used as SIMD mask elements. +pub unsafe trait MaskElement: SimdElement + Sealed {} + +macro_rules! impl_element { + { $ty:ty } => { + impl Sealed for $ty { + fn valid(value: Simd) -> bool + where + LaneCount: SupportedLaneCount, + { + (value.lanes_eq(Simd::splat(0)) | value.lanes_eq(Simd::splat(-1))).all() + } + + fn eq(self, other: Self) -> bool { self == other } + + const TRUE: Self = -1; + const FALSE: Self = 0; + } + + unsafe impl MaskElement for $ty {} + } +} + +impl_element! { i8 } +impl_element! { i16 } +impl_element! { i32 } +impl_element! { i64 } +impl_element! { isize } + +/// A SIMD vector mask for `LANES` elements of width specified by `Element`. +/// +/// The layout of this type is unspecified. +#[repr(transparent)] +pub struct Mask(mask_impl::Mask) +where + T: MaskElement, + LaneCount: SupportedLaneCount; + +impl Copy for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ +} + +impl Clone for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + fn clone(&self) -> Self { + *self + } +} + +impl Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + /// Construct a mask by setting all lanes to the given value. + pub fn splat(value: bool) -> Self { + Self(mask_impl::Mask::splat(value)) + } + + /// Converts an array to a SIMD vector. + pub fn from_array(array: [bool; LANES]) -> Self { + let mut vector = Self::splat(false); + for (i, v) in array.iter().enumerate() { + vector.set(i, *v); + } + vector + } + + /// Converts a SIMD vector to an array. + pub fn to_array(self) -> [bool; LANES] { + let mut array = [false; LANES]; + for (i, v) in array.iter_mut().enumerate() { + *v = self.test(i); + } + array + } + + /// Converts a vector of integers to a mask, where 0 represents `false` and -1 + /// represents `true`. + /// + /// # Safety + /// All lanes must be either 0 or -1. + #[inline] + pub unsafe fn from_int_unchecked(value: Simd) -> Self { + unsafe { Self(mask_impl::Mask::from_int_unchecked(value)) } + } + + /// Converts a vector of integers to a mask, where 0 represents `false` and -1 + /// represents `true`. + /// + /// # Panics + /// Panics if any lane is not 0 or -1. + #[inline] + pub fn from_int(value: Simd) -> Self { + assert!(T::valid(value), "all values must be either 0 or -1",); + unsafe { Self::from_int_unchecked(value) } + } + + /// Converts the mask to a vector of integers, where 0 represents `false` and -1 + /// represents `true`. + #[inline] + pub fn to_int(self) -> Simd { + self.0.to_int() + } + + /// Tests the value of the specified lane. + /// + /// # Safety + /// `lane` must be less than `LANES`. + #[inline] + pub unsafe fn test_unchecked(&self, lane: usize) -> bool { + unsafe { self.0.test_unchecked(lane) } + } + + /// Tests the value of the specified lane. + /// + /// # Panics + /// Panics if `lane` is greater than or equal to the number of lanes in the vector. + #[inline] + pub fn test(&self, lane: usize) -> bool { + assert!(lane < LANES, "lane index out of range"); + unsafe { self.test_unchecked(lane) } + } + + /// Sets the value of the specified lane. + /// + /// # Safety + /// `lane` must be less than `LANES`. + #[inline] + pub unsafe fn set_unchecked(&mut self, lane: usize, value: bool) { + unsafe { + self.0.set_unchecked(lane, value); + } + } + + /// Sets the value of the specified lane. + /// + /// # Panics + /// Panics if `lane` is greater than or equal to the number of lanes in the vector. + #[inline] + pub fn set(&mut self, lane: usize, value: bool) { + assert!(lane < LANES, "lane index out of range"); + unsafe { + self.set_unchecked(lane, value); + } + } + + /// Convert this mask to a bitmask, with one bit set per lane. + #[cfg(feature = "generic_const_exprs")] + pub fn to_bitmask(self) -> [u8; LaneCount::::BITMASK_LEN] { + self.0.to_bitmask() + } + + /// Convert a bitmask to a mask. + #[cfg(feature = "generic_const_exprs")] + pub fn from_bitmask(bitmask: [u8; LaneCount::::BITMASK_LEN]) -> Self { + Self(mask_impl::Mask::from_bitmask(bitmask)) + } + + /// Returns true if any lane is set, or false otherwise. + #[inline] + pub fn any(self) -> bool { + self.0.any() + } + + /// Returns true if all lanes are set, or false otherwise. + #[inline] + pub fn all(self) -> bool { + self.0.all() + } +} + +// vector/array conversion +impl From<[bool; LANES]> for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + fn from(array: [bool; LANES]) -> Self { + Self::from_array(array) + } +} + +impl From> for [bool; LANES] +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + fn from(vector: Mask) -> Self { + vector.to_array() + } +} + +impl Default for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + #[inline] + fn default() -> Self { + Self::splat(false) + } +} + +impl PartialEq for Mask +where + T: MaskElement + PartialEq, + LaneCount: SupportedLaneCount, +{ + #[inline] + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } +} + +impl PartialOrd for Mask +where + T: MaskElement + PartialOrd, + LaneCount: SupportedLaneCount, +{ + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + self.0.partial_cmp(&other.0) + } +} + +impl fmt::Debug for Mask +where + T: MaskElement + fmt::Debug, + LaneCount: SupportedLaneCount, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list() + .entries((0..LANES).map(|lane| self.test(lane))) + .finish() + } +} + +impl core::ops::BitAnd for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + type Output = Self; + #[inline] + fn bitand(self, rhs: Self) -> Self { + Self(self.0 & rhs.0) + } +} + +impl core::ops::BitAnd for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + type Output = Self; + #[inline] + fn bitand(self, rhs: bool) -> Self { + self & Self::splat(rhs) + } +} + +impl core::ops::BitAnd> for bool +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + type Output = Mask; + #[inline] + fn bitand(self, rhs: Mask) -> Mask { + Mask::splat(self) & rhs + } +} + +impl core::ops::BitOr for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + type Output = Self; + #[inline] + fn bitor(self, rhs: Self) -> Self { + Self(self.0 | rhs.0) + } +} + +impl core::ops::BitOr for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + type Output = Self; + #[inline] + fn bitor(self, rhs: bool) -> Self { + self | Self::splat(rhs) + } +} + +impl core::ops::BitOr> for bool +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + type Output = Mask; + #[inline] + fn bitor(self, rhs: Mask) -> Mask { + Mask::splat(self) | rhs + } +} + +impl core::ops::BitXor for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + type Output = Self; + #[inline] + fn bitxor(self, rhs: Self) -> Self::Output { + Self(self.0 ^ rhs.0) + } +} + +impl core::ops::BitXor for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + type Output = Self; + #[inline] + fn bitxor(self, rhs: bool) -> Self::Output { + self ^ Self::splat(rhs) + } +} + +impl core::ops::BitXor> for bool +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + type Output = Mask; + #[inline] + fn bitxor(self, rhs: Mask) -> Self::Output { + Mask::splat(self) ^ rhs + } +} + +impl core::ops::Not for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + type Output = Mask; + #[inline] + fn not(self) -> Self::Output { + Self(!self.0) + } +} + +impl core::ops::BitAndAssign for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + #[inline] + fn bitand_assign(&mut self, rhs: Self) { + self.0 = self.0 & rhs.0; + } +} + +impl core::ops::BitAndAssign for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + #[inline] + fn bitand_assign(&mut self, rhs: bool) { + *self &= Self::splat(rhs); + } +} + +impl core::ops::BitOrAssign for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + #[inline] + fn bitor_assign(&mut self, rhs: Self) { + self.0 = self.0 | rhs.0; + } +} + +impl core::ops::BitOrAssign for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + #[inline] + fn bitor_assign(&mut self, rhs: bool) { + *self |= Self::splat(rhs); + } +} + +impl core::ops::BitXorAssign for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + #[inline] + fn bitxor_assign(&mut self, rhs: Self) { + self.0 = self.0 ^ rhs.0; + } +} + +impl core::ops::BitXorAssign for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + #[inline] + fn bitxor_assign(&mut self, rhs: bool) { + *self ^= Self::splat(rhs); + } +} + +/// Vector of eight 8-bit masks +pub type mask8x8 = Mask; + +/// Vector of 16 8-bit masks +pub type mask8x16 = Mask; + +/// Vector of 32 8-bit masks +pub type mask8x32 = Mask; + +/// Vector of 16 8-bit masks +pub type mask8x64 = Mask; + +/// Vector of four 16-bit masks +pub type mask16x4 = Mask; + +/// Vector of eight 16-bit masks +pub type mask16x8 = Mask; + +/// Vector of 16 16-bit masks +pub type mask16x16 = Mask; + +/// Vector of 32 16-bit masks +pub type mask16x32 = Mask; + +/// Vector of two 32-bit masks +pub type mask32x2 = Mask; + +/// Vector of four 32-bit masks +pub type mask32x4 = Mask; + +/// Vector of eight 32-bit masks +pub type mask32x8 = Mask; + +/// Vector of 16 32-bit masks +pub type mask32x16 = Mask; + +/// Vector of two 64-bit masks +pub type mask64x2 = Mask; + +/// Vector of four 64-bit masks +pub type mask64x4 = Mask; + +/// Vector of eight 64-bit masks +pub type mask64x8 = Mask; + +/// Vector of two pointer-width masks +pub type masksizex2 = Mask; + +/// Vector of four pointer-width masks +pub type masksizex4 = Mask; + +/// Vector of eight pointer-width masks +pub type masksizex8 = Mask; + +macro_rules! impl_from { + { $from:ty => $($to:ty),* } => { + $( + impl From> for Mask<$to, LANES> + where + LaneCount: SupportedLaneCount, + { + fn from(value: Mask<$from, LANES>) -> Self { + Self(value.0.convert()) + } + } + )* + } +} +impl_from! { i8 => i16, i32, i64, isize } +impl_from! { i16 => i32, i64, isize, i8 } +impl_from! { i32 => i64, isize, i8, i16 } +impl_from! { i64 => isize, i8, i16, i32 } +impl_from! { isize => i8, i16, i32, i64 } diff --git a/library/portable-simd/crates/core_simd/src/masks/bitmask.rs b/library/portable-simd/crates/core_simd/src/masks/bitmask.rs new file mode 100644 index 0000000000..2689e1a88a --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/masks/bitmask.rs @@ -0,0 +1,220 @@ +use super::MaskElement; +use crate::simd::intrinsics; +use crate::simd::{LaneCount, Simd, SupportedLaneCount}; +use core::marker::PhantomData; + +/// A mask where each lane is represented by a single bit. +#[repr(transparent)] +pub struct Mask( + as SupportedLaneCount>::BitMask, + PhantomData, +) +where + T: MaskElement, + LaneCount: SupportedLaneCount; + +impl Copy for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ +} + +impl Clone for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + fn clone(&self) -> Self { + *self + } +} + +impl PartialEq for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + fn eq(&self, other: &Self) -> bool { + self.0.as_ref() == other.0.as_ref() + } +} + +impl PartialOrd for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + fn partial_cmp(&self, other: &Self) -> Option { + self.0.as_ref().partial_cmp(other.0.as_ref()) + } +} + +impl Eq for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ +} + +impl Ord for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + fn cmp(&self, other: &Self) -> core::cmp::Ordering { + self.0.as_ref().cmp(other.0.as_ref()) + } +} + +impl Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + #[inline] + pub fn splat(value: bool) -> Self { + let mut mask = as SupportedLaneCount>::BitMask::default(); + if value { + mask.as_mut().fill(u8::MAX) + } else { + mask.as_mut().fill(u8::MIN) + } + if LANES % 8 > 0 { + *mask.as_mut().last_mut().unwrap() &= u8::MAX >> (8 - LANES % 8); + } + Self(mask, PhantomData) + } + + #[inline] + pub unsafe fn test_unchecked(&self, lane: usize) -> bool { + (self.0.as_ref()[lane / 8] >> (lane % 8)) & 0x1 > 0 + } + + #[inline] + pub unsafe fn set_unchecked(&mut self, lane: usize, value: bool) { + unsafe { + self.0.as_mut()[lane / 8] ^= ((value ^ self.test_unchecked(lane)) as u8) << (lane % 8) + } + } + + #[inline] + pub fn to_int(self) -> Simd { + unsafe { + let mask: as SupportedLaneCount>::IntBitMask = + core::mem::transmute_copy(&self); + intrinsics::simd_select_bitmask(mask, Simd::splat(T::TRUE), Simd::splat(T::FALSE)) + } + } + + #[inline] + pub unsafe fn from_int_unchecked(value: Simd) -> Self { + // TODO remove the transmute when rustc is more flexible + assert_eq!( + core::mem::size_of::< as SupportedLaneCount>::BitMask>(), + core::mem::size_of::< as SupportedLaneCount>::IntBitMask>(), + ); + unsafe { + let mask: as SupportedLaneCount>::IntBitMask = + intrinsics::simd_bitmask(value); + Self(core::mem::transmute_copy(&mask), PhantomData) + } + } + + #[cfg(feature = "generic_const_exprs")] + #[inline] + pub fn to_bitmask(self) -> [u8; LaneCount::::BITMASK_LEN] { + // Safety: these are the same type and we are laundering the generic + unsafe { core::mem::transmute_copy(&self.0) } + } + + #[cfg(feature = "generic_const_exprs")] + #[inline] + pub fn from_bitmask(bitmask: [u8; LaneCount::::BITMASK_LEN]) -> Self { + // Safety: these are the same type and we are laundering the generic + Self(unsafe { core::mem::transmute_copy(&bitmask) }, PhantomData) + } + + #[inline] + pub fn convert(self) -> Mask + where + U: MaskElement, + { + unsafe { core::mem::transmute_copy(&self) } + } + + #[inline] + pub fn any(self) -> bool { + self != Self::splat(false) + } + + #[inline] + pub fn all(self) -> bool { + self == Self::splat(true) + } +} + +impl core::ops::BitAnd for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, + as SupportedLaneCount>::BitMask: AsRef<[u8]> + AsMut<[u8]>, +{ + type Output = Self; + #[inline] + fn bitand(mut self, rhs: Self) -> Self { + for (l, r) in self.0.as_mut().iter_mut().zip(rhs.0.as_ref().iter()) { + *l &= r; + } + self + } +} + +impl core::ops::BitOr for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, + as SupportedLaneCount>::BitMask: AsRef<[u8]> + AsMut<[u8]>, +{ + type Output = Self; + #[inline] + fn bitor(mut self, rhs: Self) -> Self { + for (l, r) in self.0.as_mut().iter_mut().zip(rhs.0.as_ref().iter()) { + *l |= r; + } + self + } +} + +impl core::ops::BitXor for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + type Output = Self; + #[inline] + fn bitxor(mut self, rhs: Self) -> Self::Output { + for (l, r) in self.0.as_mut().iter_mut().zip(rhs.0.as_ref().iter()) { + *l ^= r; + } + self + } +} + +impl core::ops::Not for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + type Output = Self; + #[inline] + fn not(mut self) -> Self::Output { + for x in self.0.as_mut() { + *x = !*x; + } + if LANES % 8 > 0 { + *self.0.as_mut().last_mut().unwrap() &= u8::MAX >> (8 - LANES % 8); + } + self + } +} diff --git a/library/portable-simd/crates/core_simd/src/masks/full_masks.rs b/library/portable-simd/crates/core_simd/src/masks/full_masks.rs new file mode 100644 index 0000000000..dd981cedb9 --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/masks/full_masks.rs @@ -0,0 +1,228 @@ +//! Masks that take up full SIMD vector registers. + +use super::MaskElement; +use crate::simd::intrinsics; +use crate::simd::{LaneCount, Simd, SupportedLaneCount}; + +#[repr(transparent)] +pub struct Mask(Simd) +where + T: MaskElement, + LaneCount: SupportedLaneCount; + +impl Copy for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ +} + +impl Clone for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + #[inline] + fn clone(&self) -> Self { + *self + } +} + +impl PartialEq for Mask +where + T: MaskElement + PartialEq, + LaneCount: SupportedLaneCount, +{ + fn eq(&self, other: &Self) -> bool { + self.0.eq(&other.0) + } +} + +impl PartialOrd for Mask +where + T: MaskElement + PartialOrd, + LaneCount: SupportedLaneCount, +{ + fn partial_cmp(&self, other: &Self) -> Option { + self.0.partial_cmp(&other.0) + } +} + +impl Eq for Mask +where + T: MaskElement + Eq, + LaneCount: SupportedLaneCount, +{ +} + +impl Ord for Mask +where + T: MaskElement + Ord, + LaneCount: SupportedLaneCount, +{ + fn cmp(&self, other: &Self) -> core::cmp::Ordering { + self.0.cmp(&other.0) + } +} + +impl Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + pub fn splat(value: bool) -> Self { + Self(Simd::splat(if value { T::TRUE } else { T::FALSE })) + } + + #[inline] + pub unsafe fn test_unchecked(&self, lane: usize) -> bool { + T::eq(self.0[lane], T::TRUE) + } + + #[inline] + pub unsafe fn set_unchecked(&mut self, lane: usize, value: bool) { + self.0[lane] = if value { T::TRUE } else { T::FALSE } + } + + #[inline] + pub fn to_int(self) -> Simd { + self.0 + } + + #[inline] + pub unsafe fn from_int_unchecked(value: Simd) -> Self { + Self(value) + } + + #[inline] + pub fn convert(self) -> Mask + where + U: MaskElement, + { + unsafe { Mask(intrinsics::simd_cast(self.0)) } + } + + #[cfg(feature = "generic_const_exprs")] + #[inline] + pub fn to_bitmask(self) -> [u8; LaneCount::::BITMASK_LEN] { + unsafe { + // TODO remove the transmute when rustc can use arrays of u8 as bitmasks + assert_eq!( + core::mem::size_of::< as SupportedLaneCount>::IntBitMask>(), + LaneCount::::BITMASK_LEN, + ); + let bitmask: as SupportedLaneCount>::IntBitMask = + intrinsics::simd_bitmask(self.0); + let mut bitmask: [u8; LaneCount::::BITMASK_LEN] = + core::mem::transmute_copy(&bitmask); + + // There is a bug where LLVM appears to implement this operation with the wrong + // bit order. + // TODO fix this in a better way + if cfg!(target_endian = "big") { + for x in bitmask.as_mut() { + *x = x.reverse_bits(); + } + } + + bitmask + } + } + + #[cfg(feature = "generic_const_exprs")] + #[inline] + pub fn from_bitmask(mut bitmask: [u8; LaneCount::::BITMASK_LEN]) -> Self { + unsafe { + // There is a bug where LLVM appears to implement this operation with the wrong + // bit order. + // TODO fix this in a better way + if cfg!(target_endian = "big") { + for x in bitmask.as_mut() { + *x = x.reverse_bits(); + } + } + + // TODO remove the transmute when rustc can use arrays of u8 as bitmasks + assert_eq!( + core::mem::size_of::< as SupportedLaneCount>::IntBitMask>(), + LaneCount::::BITMASK_LEN, + ); + let bitmask: as SupportedLaneCount>::IntBitMask = + core::mem::transmute_copy(&bitmask); + + Self::from_int_unchecked(intrinsics::simd_select_bitmask( + bitmask, + Self::splat(true).to_int(), + Self::splat(false).to_int(), + )) + } + } + + #[inline] + pub fn any(self) -> bool { + unsafe { intrinsics::simd_reduce_any(self.to_int()) } + } + + #[inline] + pub fn all(self) -> bool { + unsafe { intrinsics::simd_reduce_all(self.to_int()) } + } +} + +impl core::convert::From> for Simd +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + fn from(value: Mask) -> Self { + value.0 + } +} + +impl core::ops::BitAnd for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + type Output = Self; + #[inline] + fn bitand(self, rhs: Self) -> Self { + unsafe { Self(intrinsics::simd_and(self.0, rhs.0)) } + } +} + +impl core::ops::BitOr for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + type Output = Self; + #[inline] + fn bitor(self, rhs: Self) -> Self { + unsafe { Self(intrinsics::simd_or(self.0, rhs.0)) } + } +} + +impl core::ops::BitXor for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + type Output = Self; + #[inline] + fn bitxor(self, rhs: Self) -> Self { + unsafe { Self(intrinsics::simd_xor(self.0, rhs.0)) } + } +} + +impl core::ops::Not for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + type Output = Self; + #[inline] + fn not(self) -> Self::Output { + Self::splat(true) ^ self + } +} diff --git a/library/portable-simd/crates/core_simd/src/math.rs b/library/portable-simd/crates/core_simd/src/math.rs new file mode 100644 index 0000000000..2bae414ebf --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/math.rs @@ -0,0 +1,159 @@ +use crate::simd::intrinsics::{simd_saturating_add, simd_saturating_sub}; +use crate::simd::{LaneCount, Simd, SupportedLaneCount}; + +macro_rules! impl_uint_arith { + ($($ty:ty),+) => { + $( impl Simd<$ty, LANES> where LaneCount: SupportedLaneCount { + + /// Lanewise saturating add. + /// + /// # Examples + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "std")] use core_simd::Simd; + /// # #[cfg(not(feature = "std"))] use core::simd::Simd; + #[doc = concat!("# use core::", stringify!($ty), "::MAX;")] + /// let x = Simd::from_array([2, 1, 0, MAX]); + /// let max = Simd::splat(MAX); + /// let unsat = x + max; + /// let sat = x.saturating_add(max); + /// assert_eq!(x - 1, unsat); + /// assert_eq!(sat, max); + /// ``` + #[inline] + pub fn saturating_add(self, second: Self) -> Self { + unsafe { simd_saturating_add(self, second) } + } + + /// Lanewise saturating subtract. + /// + /// # Examples + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "std")] use core_simd::Simd; + /// # #[cfg(not(feature = "std"))] use core::simd::Simd; + #[doc = concat!("# use core::", stringify!($ty), "::MAX;")] + /// let x = Simd::from_array([2, 1, 0, MAX]); + /// let max = Simd::splat(MAX); + /// let unsat = x - max; + /// let sat = x.saturating_sub(max); + /// assert_eq!(unsat, x + 1); + /// assert_eq!(sat, Simd::splat(0)); + #[inline] + pub fn saturating_sub(self, second: Self) -> Self { + unsafe { simd_saturating_sub(self, second) } + } + })+ + } +} + +macro_rules! impl_int_arith { + ($($ty:ty),+) => { + $( impl Simd<$ty, LANES> where LaneCount: SupportedLaneCount { + + /// Lanewise saturating add. + /// + /// # Examples + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "std")] use core_simd::Simd; + /// # #[cfg(not(feature = "std"))] use core::simd::Simd; + #[doc = concat!("# use core::", stringify!($ty), "::{MIN, MAX};")] + /// let x = Simd::from_array([MIN, 0, 1, MAX]); + /// let max = Simd::splat(MAX); + /// let unsat = x + max; + /// let sat = x.saturating_add(max); + /// assert_eq!(unsat, Simd::from_array([-1, MAX, MIN, -2])); + /// assert_eq!(sat, Simd::from_array([-1, MAX, MAX, MAX])); + /// ``` + #[inline] + pub fn saturating_add(self, second: Self) -> Self { + unsafe { simd_saturating_add(self, second) } + } + + /// Lanewise saturating subtract. + /// + /// # Examples + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "std")] use core_simd::Simd; + /// # #[cfg(not(feature = "std"))] use core::simd::Simd; + #[doc = concat!("# use core::", stringify!($ty), "::{MIN, MAX};")] + /// let x = Simd::from_array([MIN, -2, -1, MAX]); + /// let max = Simd::splat(MAX); + /// let unsat = x - max; + /// let sat = x.saturating_sub(max); + /// assert_eq!(unsat, Simd::from_array([1, MAX, MIN, 0])); + /// assert_eq!(sat, Simd::from_array([MIN, MIN, MIN, 0])); + #[inline] + pub fn saturating_sub(self, second: Self) -> Self { + unsafe { simd_saturating_sub(self, second) } + } + + /// Lanewise absolute value, implemented in Rust. + /// Every lane becomes its absolute value. + /// + /// # Examples + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "std")] use core_simd::Simd; + /// # #[cfg(not(feature = "std"))] use core::simd::Simd; + #[doc = concat!("# use core::", stringify!($ty), "::{MIN, MAX};")] + /// let xs = Simd::from_array([MIN, MIN +1, -5, 0]); + /// assert_eq!(xs.abs(), Simd::from_array([MIN, MAX, 5, 0])); + /// ``` + #[inline] + pub fn abs(self) -> Self { + const SHR: $ty = <$ty>::BITS as $ty - 1; + let m = self >> SHR; + (self^m) - m + } + + /// Lanewise saturating absolute value, implemented in Rust. + /// As abs(), except the MIN value becomes MAX instead of itself. + /// + /// # Examples + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "std")] use core_simd::Simd; + /// # #[cfg(not(feature = "std"))] use core::simd::Simd; + #[doc = concat!("# use core::", stringify!($ty), "::{MIN, MAX};")] + /// let xs = Simd::from_array([MIN, -2, 0, 3]); + /// let unsat = xs.abs(); + /// let sat = xs.saturating_abs(); + /// assert_eq!(unsat, Simd::from_array([MIN, 2, 0, 3])); + /// assert_eq!(sat, Simd::from_array([MAX, 2, 0, 3])); + /// ``` + #[inline] + pub fn saturating_abs(self) -> Self { + // arith shift for -1 or 0 mask based on sign bit, giving 2s complement + const SHR: $ty = <$ty>::BITS as $ty - 1; + let m = self >> SHR; + (self^m).saturating_sub(m) + } + + /// Lanewise saturating negation, implemented in Rust. + /// As neg(), except the MIN value becomes MAX instead of itself. + /// + /// # Examples + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "std")] use core_simd::Simd; + /// # #[cfg(not(feature = "std"))] use core::simd::Simd; + #[doc = concat!("# use core::", stringify!($ty), "::{MIN, MAX};")] + /// let x = Simd::from_array([MIN, -2, 3, MAX]); + /// let unsat = -x; + /// let sat = x.saturating_neg(); + /// assert_eq!(unsat, Simd::from_array([MIN, 2, -3, MIN + 1])); + /// assert_eq!(sat, Simd::from_array([MAX, 2, -3, MIN + 1])); + /// ``` + #[inline] + pub fn saturating_neg(self) -> Self { + Self::splat(0).saturating_sub(self) + } + })+ + } +} + +impl_uint_arith! { u8, u16, u32, u64, usize } +impl_int_arith! { i8, i16, i32, i64, isize } diff --git a/library/portable-simd/crates/core_simd/src/mod.rs b/library/portable-simd/crates/core_simd/src/mod.rs new file mode 100644 index 0000000000..ec874a2238 --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/mod.rs @@ -0,0 +1,33 @@ +#[macro_use] +mod reduction; + +#[macro_use] +mod swizzle; + +pub(crate) mod intrinsics; + +#[cfg(feature = "generic_const_exprs")] +mod to_bytes; + +mod comparisons; +mod fmt; +mod iter; +mod lane_count; +mod masks; +mod math; +mod ops; +mod round; +mod select; +mod vector; +mod vendor; + +#[doc = include_str!("core_simd_docs.md")] +pub mod simd { + pub(crate) use crate::core_simd::intrinsics; + + pub use crate::core_simd::lane_count::{LaneCount, SupportedLaneCount}; + pub use crate::core_simd::masks::*; + pub use crate::core_simd::select::Select; + pub use crate::core_simd::swizzle::*; + pub use crate::core_simd::vector::*; +} diff --git a/library/portable-simd/crates/core_simd/src/ops.rs b/library/portable-simd/crates/core_simd/src/ops.rs new file mode 100644 index 0000000000..5d7af474ca --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/ops.rs @@ -0,0 +1,644 @@ +use crate::simd::intrinsics; +use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount}; + +impl core::ops::Index for Simd +where + T: SimdElement, + LaneCount: SupportedLaneCount, + I: core::slice::SliceIndex<[T]>, +{ + type Output = I::Output; + fn index(&self, index: I) -> &Self::Output { + &self.as_array()[index] + } +} + +impl core::ops::IndexMut for Simd +where + T: SimdElement, + LaneCount: SupportedLaneCount, + I: core::slice::SliceIndex<[T]>, +{ + fn index_mut(&mut self, index: I) -> &mut Self::Output { + &mut self.as_mut_array()[index] + } +} + +/// Checks if the right-hand side argument of a left- or right-shift would cause overflow. +fn invalid_shift_rhs(rhs: T) -> bool +where + T: Default + PartialOrd + core::convert::TryFrom, + >::Error: core::fmt::Debug, +{ + let bits_in_type = T::try_from(8 * core::mem::size_of::()).unwrap(); + rhs < T::default() || rhs >= bits_in_type +} + +/// Automatically implements operators over references in addition to the provided operator. +macro_rules! impl_ref_ops { + // binary op + { + impl core::ops::$trait:ident<$rhs:ty> for $type:ty + where + LaneCount<$lanes2:ident>: SupportedLaneCount, + { + type Output = $output:ty; + + $(#[$attrs:meta])* + fn $fn:ident($self_tok:ident, $rhs_arg:ident: $rhs_arg_ty:ty) -> Self::Output $body:tt + } + } => { + impl core::ops::$trait<$rhs> for $type + where + LaneCount<$lanes2>: SupportedLaneCount, + { + type Output = $output; + + $(#[$attrs])* + fn $fn($self_tok, $rhs_arg: $rhs_arg_ty) -> Self::Output $body + } + + impl core::ops::$trait<&'_ $rhs> for $type + where + LaneCount<$lanes2>: SupportedLaneCount, + { + type Output = <$type as core::ops::$trait<$rhs>>::Output; + + $(#[$attrs])* + fn $fn($self_tok, $rhs_arg: &$rhs) -> Self::Output { + core::ops::$trait::$fn($self_tok, *$rhs_arg) + } + } + + impl core::ops::$trait<$rhs> for &'_ $type + where + LaneCount<$lanes2>: SupportedLaneCount, + { + type Output = <$type as core::ops::$trait<$rhs>>::Output; + + $(#[$attrs])* + fn $fn($self_tok, $rhs_arg: $rhs) -> Self::Output { + core::ops::$trait::$fn(*$self_tok, $rhs_arg) + } + } + + impl core::ops::$trait<&'_ $rhs> for &'_ $type + where + LaneCount<$lanes2>: SupportedLaneCount, + { + type Output = <$type as core::ops::$trait<$rhs>>::Output; + + $(#[$attrs])* + fn $fn($self_tok, $rhs_arg: &$rhs) -> Self::Output { + core::ops::$trait::$fn(*$self_tok, *$rhs_arg) + } + } + }; + + // binary assignment op + { + impl core::ops::$trait:ident<$rhs:ty> for $type:ty + where + LaneCount<$lanes2:ident>: SupportedLaneCount, + { + $(#[$attrs:meta])* + fn $fn:ident(&mut $self_tok:ident, $rhs_arg:ident: $rhs_arg_ty:ty) $body:tt + } + } => { + impl core::ops::$trait<$rhs> for $type + where + LaneCount<$lanes2>: SupportedLaneCount, + { + $(#[$attrs])* + fn $fn(&mut $self_tok, $rhs_arg: $rhs_arg_ty) $body + } + + impl core::ops::$trait<&'_ $rhs> for $type + where + LaneCount<$lanes2>: SupportedLaneCount, + { + $(#[$attrs])* + fn $fn(&mut $self_tok, $rhs_arg: &$rhs_arg_ty) { + core::ops::$trait::$fn($self_tok, *$rhs_arg) + } + } + }; + + // unary op + { + impl core::ops::$trait:ident for $type:ty + where + LaneCount<$lanes2:ident>: SupportedLaneCount, + { + type Output = $output:ty; + fn $fn:ident($self_tok:ident) -> Self::Output $body:tt + } + } => { + impl core::ops::$trait for $type + where + LaneCount<$lanes2>: SupportedLaneCount, + { + type Output = $output; + fn $fn($self_tok) -> Self::Output $body + } + + impl core::ops::$trait for &'_ $type + where + LaneCount<$lanes2>: SupportedLaneCount, + { + type Output = <$type as core::ops::$trait>::Output; + fn $fn($self_tok) -> Self::Output { + core::ops::$trait::$fn(*$self_tok) + } + } + } +} + +/// Automatically implements operators over vectors and scalars for a particular vector. +macro_rules! impl_op { + { impl Add for $scalar:ty } => { + impl_op! { @binary $scalar, Add::add, AddAssign::add_assign, simd_add } + }; + { impl Sub for $scalar:ty } => { + impl_op! { @binary $scalar, Sub::sub, SubAssign::sub_assign, simd_sub } + }; + { impl Mul for $scalar:ty } => { + impl_op! { @binary $scalar, Mul::mul, MulAssign::mul_assign, simd_mul } + }; + { impl Div for $scalar:ty } => { + impl_op! { @binary $scalar, Div::div, DivAssign::div_assign, simd_div } + }; + { impl Rem for $scalar:ty } => { + impl_op! { @binary $scalar, Rem::rem, RemAssign::rem_assign, simd_rem } + }; + { impl Shl for $scalar:ty } => { + impl_op! { @binary $scalar, Shl::shl, ShlAssign::shl_assign, simd_shl } + }; + { impl Shr for $scalar:ty } => { + impl_op! { @binary $scalar, Shr::shr, ShrAssign::shr_assign, simd_shr } + }; + { impl BitAnd for $scalar:ty } => { + impl_op! { @binary $scalar, BitAnd::bitand, BitAndAssign::bitand_assign, simd_and } + }; + { impl BitOr for $scalar:ty } => { + impl_op! { @binary $scalar, BitOr::bitor, BitOrAssign::bitor_assign, simd_or } + }; + { impl BitXor for $scalar:ty } => { + impl_op! { @binary $scalar, BitXor::bitxor, BitXorAssign::bitxor_assign, simd_xor } + }; + + { impl Not for $scalar:ty } => { + impl_ref_ops! { + impl core::ops::Not for Simd<$scalar, LANES> + where + LaneCount: SupportedLaneCount, + { + type Output = Self; + fn not(self) -> Self::Output { + self ^ Self::splat(!<$scalar>::default()) + } + } + } + }; + + { impl Neg for $scalar:ty } => { + impl_ref_ops! { + impl core::ops::Neg for Simd<$scalar, LANES> + where + LaneCount: SupportedLaneCount, + { + type Output = Self; + fn neg(self) -> Self::Output { + unsafe { intrinsics::simd_neg(self) } + } + } + } + }; + + // generic binary op with assignment when output is `Self` + { @binary $scalar:ty, $trait:ident :: $trait_fn:ident, $assign_trait:ident :: $assign_trait_fn:ident, $intrinsic:ident } => { + impl_ref_ops! { + impl core::ops::$trait for Simd<$scalar, LANES> + where + LaneCount: SupportedLaneCount, + { + type Output = Self; + + #[inline] + fn $trait_fn(self, rhs: Self) -> Self::Output { + unsafe { + intrinsics::$intrinsic(self, rhs) + } + } + } + } + + impl_ref_ops! { + impl core::ops::$trait<$scalar> for Simd<$scalar, LANES> + where + LaneCount: SupportedLaneCount, + { + type Output = Self; + + #[inline] + fn $trait_fn(self, rhs: $scalar) -> Self::Output { + core::ops::$trait::$trait_fn(self, Self::splat(rhs)) + } + } + } + + impl_ref_ops! { + impl core::ops::$trait> for $scalar + where + LaneCount: SupportedLaneCount, + { + type Output = Simd<$scalar, LANES>; + + #[inline] + fn $trait_fn(self, rhs: Simd<$scalar, LANES>) -> Self::Output { + core::ops::$trait::$trait_fn(Simd::splat(self), rhs) + } + } + } + + impl_ref_ops! { + impl core::ops::$assign_trait for Simd<$scalar, LANES> + where + LaneCount: SupportedLaneCount, + { + #[inline] + fn $assign_trait_fn(&mut self, rhs: Self) { + unsafe { + *self = intrinsics::$intrinsic(*self, rhs); + } + } + } + } + + impl_ref_ops! { + impl core::ops::$assign_trait<$scalar> for Simd<$scalar, LANES> + where + LaneCount: SupportedLaneCount, + { + #[inline] + fn $assign_trait_fn(&mut self, rhs: $scalar) { + core::ops::$assign_trait::$assign_trait_fn(self, Self::splat(rhs)); + } + } + } + }; +} + +/// Implements floating-point operators for the provided types. +macro_rules! impl_float_ops { + { $($scalar:ty),* } => { + $( + impl_op! { impl Add for $scalar } + impl_op! { impl Sub for $scalar } + impl_op! { impl Mul for $scalar } + impl_op! { impl Div for $scalar } + impl_op! { impl Rem for $scalar } + impl_op! { impl Neg for $scalar } + )* + }; +} + +/// Implements unsigned integer operators for the provided types. +macro_rules! impl_unsigned_int_ops { + { $($scalar:ty),* } => { + $( + impl_op! { impl Add for $scalar } + impl_op! { impl Sub for $scalar } + impl_op! { impl Mul for $scalar } + impl_op! { impl BitAnd for $scalar } + impl_op! { impl BitOr for $scalar } + impl_op! { impl BitXor for $scalar } + impl_op! { impl Not for $scalar } + + // Integers panic on divide by 0 + impl_ref_ops! { + impl core::ops::Div for Simd<$scalar, LANES> + where + LaneCount: SupportedLaneCount, + { + type Output = Self; + + #[inline] + fn div(self, rhs: Self) -> Self::Output { + if rhs.as_array() + .iter() + .any(|x| *x == 0) + { + panic!("attempt to divide by zero"); + } + + // Guards for div(MIN, -1), + // this check only applies to signed ints + if <$scalar>::MIN != 0 && self.as_array().iter() + .zip(rhs.as_array().iter()) + .any(|(x,y)| *x == <$scalar>::MIN && *y == -1 as _) { + panic!("attempt to divide with overflow"); + } + unsafe { intrinsics::simd_div(self, rhs) } + } + } + } + + impl_ref_ops! { + impl core::ops::Div<$scalar> for Simd<$scalar, LANES> + where + LaneCount: SupportedLaneCount, + { + type Output = Self; + + #[inline] + fn div(self, rhs: $scalar) -> Self::Output { + if rhs == 0 { + panic!("attempt to divide by zero"); + } + if <$scalar>::MIN != 0 && + self.as_array().iter().any(|x| *x == <$scalar>::MIN) && + rhs == -1 as _ { + panic!("attempt to divide with overflow"); + } + let rhs = Self::splat(rhs); + unsafe { intrinsics::simd_div(self, rhs) } + } + } + } + + impl_ref_ops! { + impl core::ops::Div> for $scalar + where + LaneCount: SupportedLaneCount, + { + type Output = Simd<$scalar, LANES>; + + #[inline] + fn div(self, rhs: Simd<$scalar, LANES>) -> Self::Output { + Simd::splat(self) / rhs + } + } + } + + impl_ref_ops! { + impl core::ops::DivAssign for Simd<$scalar, LANES> + where + LaneCount: SupportedLaneCount, + { + #[inline] + fn div_assign(&mut self, rhs: Self) { + *self = *self / rhs; + } + } + } + + impl_ref_ops! { + impl core::ops::DivAssign<$scalar> for Simd<$scalar, LANES> + where + LaneCount: SupportedLaneCount, + { + #[inline] + fn div_assign(&mut self, rhs: $scalar) { + *self = *self / rhs; + } + } + } + + // remainder panics on zero divisor + impl_ref_ops! { + impl core::ops::Rem for Simd<$scalar, LANES> + where + LaneCount: SupportedLaneCount, + { + type Output = Self; + + #[inline] + fn rem(self, rhs: Self) -> Self::Output { + if rhs.as_array() + .iter() + .any(|x| *x == 0) + { + panic!("attempt to calculate the remainder with a divisor of zero"); + } + + // Guards for rem(MIN, -1) + // this branch applies the check only to signed ints + if <$scalar>::MIN != 0 && self.as_array().iter() + .zip(rhs.as_array().iter()) + .any(|(x,y)| *x == <$scalar>::MIN && *y == -1 as _) { + panic!("attempt to calculate the remainder with overflow"); + } + unsafe { intrinsics::simd_rem(self, rhs) } + } + } + } + + impl_ref_ops! { + impl core::ops::Rem<$scalar> for Simd<$scalar, LANES> + where + LaneCount: SupportedLaneCount, + { + type Output = Self; + + #[inline] + fn rem(self, rhs: $scalar) -> Self::Output { + if rhs == 0 { + panic!("attempt to calculate the remainder with a divisor of zero"); + } + if <$scalar>::MIN != 0 && + self.as_array().iter().any(|x| *x == <$scalar>::MIN) && + rhs == -1 as _ { + panic!("attempt to calculate the remainder with overflow"); + } + let rhs = Self::splat(rhs); + unsafe { intrinsics::simd_rem(self, rhs) } + } + } + } + + impl_ref_ops! { + impl core::ops::Rem> for $scalar + where + LaneCount: SupportedLaneCount, + { + type Output = Simd<$scalar, LANES>; + + #[inline] + fn rem(self, rhs: Simd<$scalar, LANES>) -> Self::Output { + Simd::splat(self) % rhs + } + } + } + + impl_ref_ops! { + impl core::ops::RemAssign for Simd<$scalar, LANES> + where + LaneCount: SupportedLaneCount, + { + #[inline] + fn rem_assign(&mut self, rhs: Self) { + *self = *self % rhs; + } + } + } + + impl_ref_ops! { + impl core::ops::RemAssign<$scalar> for Simd<$scalar, LANES> + where + LaneCount: SupportedLaneCount, + { + #[inline] + fn rem_assign(&mut self, rhs: $scalar) { + *self = *self % rhs; + } + } + } + + // shifts panic on overflow + impl_ref_ops! { + impl core::ops::Shl for Simd<$scalar, LANES> + where + LaneCount: SupportedLaneCount, + { + type Output = Self; + + #[inline] + fn shl(self, rhs: Self) -> Self::Output { + // TODO there is probably a better way of doing this + if rhs.as_array() + .iter() + .copied() + .any(invalid_shift_rhs) + { + panic!("attempt to shift left with overflow"); + } + unsafe { intrinsics::simd_shl(self, rhs) } + } + } + } + + impl_ref_ops! { + impl core::ops::Shl<$scalar> for Simd<$scalar, LANES> + where + LaneCount: SupportedLaneCount, + { + type Output = Self; + + #[inline] + fn shl(self, rhs: $scalar) -> Self::Output { + if invalid_shift_rhs(rhs) { + panic!("attempt to shift left with overflow"); + } + let rhs = Self::splat(rhs); + unsafe { intrinsics::simd_shl(self, rhs) } + } + } + } + + + impl_ref_ops! { + impl core::ops::ShlAssign for Simd<$scalar, LANES> + where + LaneCount: SupportedLaneCount, + { + #[inline] + fn shl_assign(&mut self, rhs: Self) { + *self = *self << rhs; + } + } + } + + impl_ref_ops! { + impl core::ops::ShlAssign<$scalar> for Simd<$scalar, LANES> + where + LaneCount: SupportedLaneCount, + { + #[inline] + fn shl_assign(&mut self, rhs: $scalar) { + *self = *self << rhs; + } + } + } + + impl_ref_ops! { + impl core::ops::Shr for Simd<$scalar, LANES> + where + LaneCount: SupportedLaneCount, + { + type Output = Self; + + #[inline] + fn shr(self, rhs: Self) -> Self::Output { + // TODO there is probably a better way of doing this + if rhs.as_array() + .iter() + .copied() + .any(invalid_shift_rhs) + { + panic!("attempt to shift with overflow"); + } + unsafe { intrinsics::simd_shr(self, rhs) } + } + } + } + + impl_ref_ops! { + impl core::ops::Shr<$scalar> for Simd<$scalar, LANES> + where + LaneCount: SupportedLaneCount, + { + type Output = Self; + + #[inline] + fn shr(self, rhs: $scalar) -> Self::Output { + if invalid_shift_rhs(rhs) { + panic!("attempt to shift with overflow"); + } + let rhs = Self::splat(rhs); + unsafe { intrinsics::simd_shr(self, rhs) } + } + } + } + + + impl_ref_ops! { + impl core::ops::ShrAssign for Simd<$scalar, LANES> + where + LaneCount: SupportedLaneCount, + { + #[inline] + fn shr_assign(&mut self, rhs: Self) { + *self = *self >> rhs; + } + } + } + + impl_ref_ops! { + impl core::ops::ShrAssign<$scalar> for Simd<$scalar, LANES> + where + LaneCount: SupportedLaneCount, + { + #[inline] + fn shr_assign(&mut self, rhs: $scalar) { + *self = *self >> rhs; + } + } + } + )* + }; +} + +/// Implements unsigned integer operators for the provided types. +macro_rules! impl_signed_int_ops { + { $($scalar:ty),* } => { + impl_unsigned_int_ops! { $($scalar),* } + $( // scalar + impl_op! { impl Neg for $scalar } + )* + }; +} + +impl_unsigned_int_ops! { u8, u16, u32, u64, usize } +impl_signed_int_ops! { i8, i16, i32, i64, isize } +impl_float_ops! { f32, f64 } diff --git a/library/portable-simd/crates/core_simd/src/reduction.rs b/library/portable-simd/crates/core_simd/src/reduction.rs new file mode 100644 index 0000000000..db0640aae7 --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/reduction.rs @@ -0,0 +1,123 @@ +use crate::simd::intrinsics::{ + simd_reduce_add_ordered, simd_reduce_and, simd_reduce_max, simd_reduce_min, + simd_reduce_mul_ordered, simd_reduce_or, simd_reduce_xor, +}; +use crate::simd::{LaneCount, Simd, SupportedLaneCount}; + +macro_rules! impl_integer_reductions { + { $scalar:ty } => { + impl Simd<$scalar, LANES> + where + LaneCount: SupportedLaneCount, + { + /// Horizontal wrapping add. Returns the sum of the lanes of the vector, with wrapping addition. + #[inline] + pub fn horizontal_sum(self) -> $scalar { + unsafe { simd_reduce_add_ordered(self, 0) } + } + + /// Horizontal wrapping multiply. Returns the product of the lanes of the vector, with wrapping multiplication. + #[inline] + pub fn horizontal_product(self) -> $scalar { + unsafe { simd_reduce_mul_ordered(self, 1) } + } + + /// Horizontal bitwise "and". Returns the cumulative bitwise "and" across the lanes of + /// the vector. + #[inline] + pub fn horizontal_and(self) -> $scalar { + unsafe { simd_reduce_and(self) } + } + + /// Horizontal bitwise "or". Returns the cumulative bitwise "or" across the lanes of + /// the vector. + #[inline] + pub fn horizontal_or(self) -> $scalar { + unsafe { simd_reduce_or(self) } + } + + /// Horizontal bitwise "xor". Returns the cumulative bitwise "xor" across the lanes of + /// the vector. + #[inline] + pub fn horizontal_xor(self) -> $scalar { + unsafe { simd_reduce_xor(self) } + } + + /// Horizontal maximum. Returns the maximum lane in the vector. + #[inline] + pub fn horizontal_max(self) -> $scalar { + unsafe { simd_reduce_max(self) } + } + + /// Horizontal minimum. Returns the minimum lane in the vector. + #[inline] + pub fn horizontal_min(self) -> $scalar { + unsafe { simd_reduce_min(self) } + } + } + } +} + +impl_integer_reductions! { i8 } +impl_integer_reductions! { i16 } +impl_integer_reductions! { i32 } +impl_integer_reductions! { i64 } +impl_integer_reductions! { isize } +impl_integer_reductions! { u8 } +impl_integer_reductions! { u16 } +impl_integer_reductions! { u32 } +impl_integer_reductions! { u64 } +impl_integer_reductions! { usize } + +macro_rules! impl_float_reductions { + { $scalar:ty } => { + impl Simd<$scalar, LANES> + where + LaneCount: SupportedLaneCount, + { + + /// Horizontal add. Returns the sum of the lanes of the vector. + #[inline] + pub fn horizontal_sum(self) -> $scalar { + // LLVM sum is inaccurate on i586 + if cfg!(all(target_arch = "x86", not(target_feature = "sse2"))) { + self.as_array().iter().sum() + } else { + unsafe { simd_reduce_add_ordered(self, 0.) } + } + } + + /// Horizontal multiply. Returns the product of the lanes of the vector. + #[inline] + pub fn horizontal_product(self) -> $scalar { + // LLVM product is inaccurate on i586 + if cfg!(all(target_arch = "x86", not(target_feature = "sse2"))) { + self.as_array().iter().product() + } else { + unsafe { simd_reduce_mul_ordered(self, 1.) } + } + } + + /// Horizontal maximum. Returns the maximum lane in the vector. + /// + /// Returns values based on equality, so a vector containing both `0.` and `-0.` may + /// return either. This function will not return `NaN` unless all lanes are `NaN`. + #[inline] + pub fn horizontal_max(self) -> $scalar { + unsafe { simd_reduce_max(self) } + } + + /// Horizontal minimum. Returns the minimum lane in the vector. + /// + /// Returns values based on equality, so a vector containing both `0.` and `-0.` may + /// return either. This function will not return `NaN` unless all lanes are `NaN`. + #[inline] + pub fn horizontal_min(self) -> $scalar { + unsafe { simd_reduce_min(self) } + } + } + } +} + +impl_float_reductions! { f32 } +impl_float_reductions! { f64 } diff --git a/library/portable-simd/crates/core_simd/src/round.rs b/library/portable-simd/crates/core_simd/src/round.rs new file mode 100644 index 0000000000..09789e1149 --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/round.rs @@ -0,0 +1,78 @@ +use crate::simd::intrinsics; +use crate::simd::{LaneCount, Simd, SupportedLaneCount}; + +macro_rules! implement { + { + $type:ty, $int_type:ty + } => { + #[cfg(feature = "std")] + impl Simd<$type, LANES> + where + LaneCount: SupportedLaneCount, + { + /// Returns the smallest integer greater than or equal to each lane. + #[must_use = "method returns a new vector and does not mutate the original value"] + #[inline] + pub fn ceil(self) -> Self { + unsafe { intrinsics::simd_ceil(self) } + } + + /// Returns the largest integer value less than or equal to each lane. + #[must_use = "method returns a new vector and does not mutate the original value"] + #[inline] + pub fn floor(self) -> Self { + unsafe { intrinsics::simd_floor(self) } + } + + /// Rounds to the nearest integer value. Ties round toward zero. + #[must_use = "method returns a new vector and does not mutate the original value"] + #[inline] + pub fn round(self) -> Self { + unsafe { intrinsics::simd_round(self) } + } + + /// Returns the floating point's integer value, with its fractional part removed. + #[must_use = "method returns a new vector and does not mutate the original value"] + #[inline] + pub fn trunc(self) -> Self { + unsafe { intrinsics::simd_trunc(self) } + } + + /// Returns the floating point's fractional value, with its integer part removed. + #[must_use = "method returns a new vector and does not mutate the original value"] + #[inline] + pub fn fract(self) -> Self { + self - self.trunc() + } + } + + impl Simd<$type, LANES> + where + LaneCount: SupportedLaneCount, + { + /// Rounds toward zero and converts to the same-width integer type, assuming that + /// the value is finite and fits in that type. + /// + /// # Safety + /// The value must: + /// + /// * Not be NaN + /// * Not be infinite + /// * Be representable in the return type, after truncating off its fractional part + #[inline] + pub unsafe fn to_int_unchecked(self) -> Simd<$int_type, LANES> { + unsafe { intrinsics::simd_cast(self) } + } + + /// Creates a floating-point vector from an integer vector. Rounds values that are + /// not exactly representable. + #[inline] + pub fn round_from_int(value: Simd<$int_type, LANES>) -> Self { + unsafe { intrinsics::simd_cast(value) } + } + } + } +} + +implement! { f32, i32 } +implement! { f64, i64 } diff --git a/library/portable-simd/crates/core_simd/src/select.rs b/library/portable-simd/crates/core_simd/src/select.rs new file mode 100644 index 0000000000..d976231a03 --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/select.rs @@ -0,0 +1,86 @@ +use crate::simd::intrinsics; +use crate::simd::{LaneCount, Mask, MaskElement, Simd, SimdElement, SupportedLaneCount}; + +mod sealed { + pub trait Sealed { + fn select(mask: Mask, true_values: Self, false_values: Self) -> Self; + } +} +use sealed::Sealed; + +/// Supporting trait for vector `select` function +pub trait Select: Sealed {} + +impl Sealed> for Simd +where + T: SimdElement, + LaneCount: SupportedLaneCount, +{ + #[inline] + fn select(mask: Mask, true_values: Self, false_values: Self) -> Self { + unsafe { intrinsics::simd_select(mask.to_int(), true_values, false_values) } + } +} + +impl Select> for Simd +where + T: SimdElement, + LaneCount: SupportedLaneCount, +{ +} + +impl Sealed for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + #[inline] + fn select(mask: Self, true_values: Self, false_values: Self) -> Self { + mask & true_values | !mask & false_values + } +} + +impl Select for Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ +} + +impl Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + /// Choose lanes from two vectors. + /// + /// For each lane in the mask, choose the corresponding lane from `true_values` if + /// that lane mask is true, and `false_values` if that lane mask is false. + /// + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "std")] use core_simd::{Simd, Mask}; + /// # #[cfg(not(feature = "std"))] use core::simd::{Simd, Mask}; + /// let a = Simd::from_array([0, 1, 2, 3]); + /// let b = Simd::from_array([4, 5, 6, 7]); + /// let mask = Mask::from_array([true, false, false, true]); + /// let c = mask.select(a, b); + /// assert_eq!(c.to_array(), [0, 5, 6, 3]); + /// ``` + /// + /// `select` can also be used on masks: + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "std")] use core_simd::Mask; + /// # #[cfg(not(feature = "std"))] use core::simd::Mask; + /// let a = Mask::::from_array([true, true, false, false]); + /// let b = Mask::::from_array([false, false, true, true]); + /// let mask = Mask::::from_array([true, false, false, true]); + /// let c = mask.select(a, b); + /// assert_eq!(c.to_array(), [true, false, true, false]); + /// ``` + #[inline] + pub fn select>(self, true_values: S, false_values: S) -> S { + S::select(self, true_values, false_values) + } +} diff --git a/library/portable-simd/crates/core_simd/src/swizzle.rs b/library/portable-simd/crates/core_simd/src/swizzle.rs new file mode 100644 index 0000000000..62cda68f0a --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/swizzle.rs @@ -0,0 +1,374 @@ +use crate::simd::intrinsics; +use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount}; + +/// Constructs a new vector by selecting values from the lanes of the source vector or vectors to use. +/// +/// When swizzling one vector, the indices of the result vector are indicated by a `const` array +/// of `usize`, like [`Swizzle`]. +/// When swizzling two vectors, the indices are indicated by a `const` array of [`Which`], like +/// [`Swizzle2`]. +/// +/// # Examples +/// ## One source vector +/// ``` +/// # #![feature(portable_simd)] +/// # #[cfg(feature = "std")] use core_simd::{Simd, simd_swizzle}; +/// # #[cfg(not(feature = "std"))] use core::simd::{Simd, simd_swizzle}; +/// let v = Simd::::from_array([0., 1., 2., 3.]); +/// +/// // Keeping the same size +/// let r = simd_swizzle!(v, [3, 0, 1, 2]); +/// assert_eq!(r.to_array(), [3., 0., 1., 2.]); +/// +/// // Changing the number of lanes +/// let r = simd_swizzle!(v, [3, 1]); +/// assert_eq!(r.to_array(), [3., 1.]); +/// ``` +/// +/// ## Two source vectors +/// ``` +/// # #![feature(portable_simd)] +/// # #[cfg(feature = "std")] use core_simd::{Simd, simd_swizzle, Which}; +/// # #[cfg(not(feature = "std"))] use core::simd::{Simd, simd_swizzle, Which}; +/// use Which::*; +/// let a = Simd::::from_array([0., 1., 2., 3.]); +/// let b = Simd::::from_array([4., 5., 6., 7.]); +/// +/// // Keeping the same size +/// let r = simd_swizzle!(a, b, [First(0), First(1), Second(2), Second(3)]); +/// assert_eq!(r.to_array(), [0., 1., 6., 7.]); +/// +/// // Changing the number of lanes +/// let r = simd_swizzle!(a, b, [First(0), Second(0)]); +/// assert_eq!(r.to_array(), [0., 4.]); +/// ``` +#[allow(unused_macros)] +pub macro simd_swizzle { + ( + $vector:expr, $index:expr $(,)? + ) => { + { + use $crate::simd::Swizzle; + struct Impl; + impl Swizzle for Impl { + const INDEX: [usize; {$index.len()}] = $index; + } + Impl::swizzle($vector) + } + }, + ( + $first:expr, $second:expr, $index:expr $(,)? + ) => { + { + use $crate::simd::{Which, Swizzle2}; + struct Impl; + impl Swizzle2 for Impl { + const INDEX: [Which; {$index.len()}] = $index; + } + Impl::swizzle2($first, $second) + } + } +} + +/// An index into one of two vectors. +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum Which { + /// Indexes the first vector. + First(usize), + /// Indexes the second vector. + Second(usize), +} + +/// Create a vector from the elements of another vector. +pub trait Swizzle { + /// Map from the lanes of the input vector to the output vector. + const INDEX: [usize; OUTPUT_LANES]; + + /// Create a new vector from the lanes of `vector`. + /// + /// Lane `i` of the output is `vector[Self::INDEX[i]]`. + fn swizzle(vector: Simd) -> Simd + where + T: SimdElement, + LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, + { + unsafe { intrinsics::simd_shuffle(vector, vector, Self::INDEX_IMPL) } + } +} + +/// Create a vector from the elements of two other vectors. +pub trait Swizzle2 { + /// Map from the lanes of the input vectors to the output vector + const INDEX: [Which; OUTPUT_LANES]; + + /// Create a new vector from the lanes of `first` and `second`. + /// + /// Lane `i` is `first[j]` when `Self::INDEX[i]` is `First(j)`, or `second[j]` when it is + /// `Second(j)`. + fn swizzle2( + first: Simd, + second: Simd, + ) -> Simd + where + T: SimdElement, + LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, + { + unsafe { intrinsics::simd_shuffle(first, second, Self::INDEX_IMPL) } + } +} + +/// The `simd_shuffle` intrinsic expects `u32`, so do error checking and conversion here. +/// This trait hides `INDEX_IMPL` from the public API. +trait SwizzleImpl { + const INDEX_IMPL: [u32; OUTPUT_LANES]; +} + +impl SwizzleImpl + for T +where + T: Swizzle + ?Sized, +{ + const INDEX_IMPL: [u32; OUTPUT_LANES] = { + let mut output = [0; OUTPUT_LANES]; + let mut i = 0; + while i < OUTPUT_LANES { + let index = Self::INDEX[i]; + assert!(index as u32 as usize == index); + assert!(index < INPUT_LANES, "source lane exceeds input lane count",); + output[i] = index as u32; + i += 1; + } + output + }; +} + +/// The `simd_shuffle` intrinsic expects `u32`, so do error checking and conversion here. +/// This trait hides `INDEX_IMPL` from the public API. +trait Swizzle2Impl { + const INDEX_IMPL: [u32; OUTPUT_LANES]; +} + +impl Swizzle2Impl + for T +where + T: Swizzle2 + ?Sized, +{ + const INDEX_IMPL: [u32; OUTPUT_LANES] = { + let mut output = [0; OUTPUT_LANES]; + let mut i = 0; + while i < OUTPUT_LANES { + let (offset, index) = match Self::INDEX[i] { + Which::First(index) => (false, index), + Which::Second(index) => (true, index), + }; + assert!(index < INPUT_LANES, "source lane exceeds input lane count",); + + // lanes are indexed by the first vector, then second vector + let index = if offset { index + INPUT_LANES } else { index }; + assert!(index as u32 as usize == index); + output[i] = index as u32; + i += 1; + } + output + }; +} + +impl Simd +where + T: SimdElement, + LaneCount: SupportedLaneCount, +{ + /// Reverse the order of the lanes in the vector. + #[inline] + pub fn reverse(self) -> Self { + const fn reverse_index() -> [usize; LANES] { + let mut index = [0; LANES]; + let mut i = 0; + while i < LANES { + index[i] = LANES - i - 1; + i += 1; + } + index + } + + struct Reverse; + + impl Swizzle for Reverse { + const INDEX: [usize; LANES] = reverse_index::(); + } + + Reverse::swizzle(self) + } + + /// Rotates the vector such that the first `OFFSET` elements of the slice move to the end + /// while the last `LANES - OFFSET` elements move to the front. After calling `rotate_lanes_left`, + /// the element previously in lane `OFFSET` will become the first element in the slice. + #[inline] + pub fn rotate_lanes_left(self) -> Self { + const fn rotate_index() -> [usize; LANES] { + let offset = OFFSET % LANES; + let mut index = [0; LANES]; + let mut i = 0; + while i < LANES { + index[i] = (i + offset) % LANES; + i += 1; + } + index + } + + struct Rotate; + + impl Swizzle for Rotate { + const INDEX: [usize; LANES] = rotate_index::(); + } + + Rotate::::swizzle(self) + } + + /// Rotates the vector such that the first `LANES - OFFSET` elements of the vector move to + /// the end while the last `OFFSET` elements move to the front. After calling `rotate_lanes_right`, + /// the element previously at index `LANES - OFFSET` will become the first element in the slice. + #[inline] + pub fn rotate_lanes_right(self) -> Self { + const fn rotate_index() -> [usize; LANES] { + let offset = LANES - OFFSET % LANES; + let mut index = [0; LANES]; + let mut i = 0; + while i < LANES { + index[i] = (i + offset) % LANES; + i += 1; + } + index + } + + struct Rotate; + + impl Swizzle for Rotate { + const INDEX: [usize; LANES] = rotate_index::(); + } + + Rotate::::swizzle(self) + } + + /// Interleave two vectors. + /// + /// Produces two vectors with lanes taken alternately from `self` and `other`. + /// + /// The first result contains the first `LANES / 2` lanes from `self` and `other`, + /// alternating, starting with the first lane of `self`. + /// + /// The second result contains the last `LANES / 2` lanes from `self` and `other`, + /// alternating, starting with the lane `LANES / 2` from the start of `self`. + /// + /// ``` + /// #![feature(portable_simd)] + /// # #[cfg(feature = "std")] use core_simd::Simd; + /// # #[cfg(not(feature = "std"))] use core::simd::Simd; + /// let a = Simd::from_array([0, 1, 2, 3]); + /// let b = Simd::from_array([4, 5, 6, 7]); + /// let (x, y) = a.interleave(b); + /// assert_eq!(x.to_array(), [0, 4, 1, 5]); + /// assert_eq!(y.to_array(), [2, 6, 3, 7]); + /// ``` + #[inline] + pub fn interleave(self, other: Self) -> (Self, Self) { + const fn lo() -> [Which; LANES] { + let mut idx = [Which::First(0); LANES]; + let mut i = 0; + while i < LANES { + let offset = i / 2; + idx[i] = if i % 2 == 0 { + Which::First(offset) + } else { + Which::Second(offset) + }; + i += 1; + } + idx + } + const fn hi() -> [Which; LANES] { + let mut idx = [Which::First(0); LANES]; + let mut i = 0; + while i < LANES { + let offset = (LANES + i) / 2; + idx[i] = if i % 2 == 0 { + Which::First(offset) + } else { + Which::Second(offset) + }; + i += 1; + } + idx + } + + struct Lo; + struct Hi; + + impl Swizzle2 for Lo { + const INDEX: [Which; LANES] = lo::(); + } + + impl Swizzle2 for Hi { + const INDEX: [Which; LANES] = hi::(); + } + + (Lo::swizzle2(self, other), Hi::swizzle2(self, other)) + } + + /// Deinterleave two vectors. + /// + /// The first result takes every other lane of `self` and then `other`, starting with + /// the first lane. + /// + /// The second result takes every other lane of `self` and then `other`, starting with + /// the second lane. + /// + /// ``` + /// #![feature(portable_simd)] + /// # #[cfg(feature = "std")] use core_simd::Simd; + /// # #[cfg(not(feature = "std"))] use core::simd::Simd; + /// let a = Simd::from_array([0, 4, 1, 5]); + /// let b = Simd::from_array([2, 6, 3, 7]); + /// let (x, y) = a.deinterleave(b); + /// assert_eq!(x.to_array(), [0, 1, 2, 3]); + /// assert_eq!(y.to_array(), [4, 5, 6, 7]); + /// ``` + #[inline] + pub fn deinterleave(self, other: Self) -> (Self, Self) { + const fn even() -> [Which; LANES] { + let mut idx = [Which::First(0); LANES]; + let mut i = 0; + while i < LANES / 2 { + idx[i] = Which::First(2 * i); + idx[i + LANES / 2] = Which::Second(2 * i); + i += 1; + } + idx + } + const fn odd() -> [Which; LANES] { + let mut idx = [Which::First(0); LANES]; + let mut i = 0; + while i < LANES / 2 { + idx[i] = Which::First(2 * i + 1); + idx[i + LANES / 2] = Which::Second(2 * i + 1); + i += 1; + } + idx + } + + struct Even; + struct Odd; + + impl Swizzle2 for Even { + const INDEX: [Which; LANES] = even::(); + } + + impl Swizzle2 for Odd { + const INDEX: [Which; LANES] = odd::(); + } + + (Even::swizzle2(self, other), Odd::swizzle2(self, other)) + } +} diff --git a/library/portable-simd/crates/core_simd/src/to_bytes.rs b/library/portable-simd/crates/core_simd/src/to_bytes.rs new file mode 100644 index 0000000000..8d9b3e8ff8 --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/to_bytes.rs @@ -0,0 +1,39 @@ +macro_rules! impl_to_bytes { + { $ty:ty, $size:literal } => { + impl crate::simd::Simd<$ty, LANES> + where + crate::simd::LaneCount: crate::simd::SupportedLaneCount, + crate::simd::LaneCount<{{ $size * LANES }}>: crate::simd::SupportedLaneCount, + { + /// Return the memory representation of this integer as a byte array in native byte + /// order. + pub fn to_ne_bytes(self) -> crate::simd::Simd { + unsafe { core::mem::transmute_copy(&self) } + } + + /// Create a native endian integer value from its memory representation as a byte array + /// in native endianness. + pub fn from_ne_bytes(bytes: crate::simd::Simd) -> Self { + unsafe { core::mem::transmute_copy(&bytes) } + } + } + } +} + +impl_to_bytes! { u8, 1 } +impl_to_bytes! { u16, 2 } +impl_to_bytes! { u32, 4 } +impl_to_bytes! { u64, 8 } +#[cfg(target_pointer_width = "32")] +impl_to_bytes! { usize, 4 } +#[cfg(target_pointer_width = "64")] +impl_to_bytes! { usize, 8 } + +impl_to_bytes! { i8, 1 } +impl_to_bytes! { i16, 2 } +impl_to_bytes! { i32, 4 } +impl_to_bytes! { i64, 8 } +#[cfg(target_pointer_width = "32")] +impl_to_bytes! { isize, 4 } +#[cfg(target_pointer_width = "64")] +impl_to_bytes! { isize, 8 } diff --git a/library/portable-simd/crates/core_simd/src/vector.rs b/library/portable-simd/crates/core_simd/src/vector.rs new file mode 100644 index 0000000000..7c5ec2bc31 --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/vector.rs @@ -0,0 +1,528 @@ +mod float; +mod int; +mod uint; + +pub use float::*; +pub use int::*; +pub use uint::*; + +// Vectors of pointers are not for public use at the current time. +pub(crate) mod ptr; + +use crate::simd::intrinsics; +use crate::simd::{LaneCount, Mask, MaskElement, SupportedLaneCount}; + +/// A SIMD vector of `LANES` elements of type `T`. +#[repr(simd)] +pub struct Simd([T; LANES]) +where + T: SimdElement, + LaneCount: SupportedLaneCount; + +impl Simd +where + LaneCount: SupportedLaneCount, + T: SimdElement, +{ + /// Number of lanes in this vector. + pub const LANES: usize = LANES; + + /// Get the number of lanes in this vector. + pub const fn lanes(&self) -> usize { + LANES + } + + /// Construct a SIMD vector by setting all lanes to the given value. + pub const fn splat(value: T) -> Self { + Self([value; LANES]) + } + + /// Returns an array reference containing the entire SIMD vector. + pub const fn as_array(&self) -> &[T; LANES] { + &self.0 + } + + /// Returns a mutable array reference containing the entire SIMD vector. + pub fn as_mut_array(&mut self) -> &mut [T; LANES] { + &mut self.0 + } + + /// Converts an array to a SIMD vector. + pub const fn from_array(array: [T; LANES]) -> Self { + Self(array) + } + + /// Converts a SIMD vector to an array. + pub const fn to_array(self) -> [T; LANES] { + self.0 + } + + /// Converts a slice to a SIMD vector containing `slice[..LANES]` + /// # Panics + /// `from_slice` will panic if the slice's `len` is less than the vector's `Simd::LANES`. + #[must_use] + pub const fn from_slice(slice: &[T]) -> Self { + assert!( + slice.len() >= LANES, + "slice length must be at least the number of lanes" + ); + let mut array = [slice[0]; LANES]; + let mut i = 0; + while i < LANES { + array[i] = slice[i]; + i += 1; + } + Self(array) + } + + /// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector. + /// If an index is out-of-bounds, the lane is instead selected from the `or` vector. + /// + /// # Examples + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "std")] use core_simd::Simd; + /// # #[cfg(not(feature = "std"))] use core::simd::Simd; + /// let vec: Vec = vec![10, 11, 12, 13, 14, 15, 16, 17, 18]; + /// let idxs = Simd::from_array([9, 3, 0, 5]); + /// let alt = Simd::from_array([-5, -4, -3, -2]); + /// + /// let result = Simd::gather_or(&vec, idxs, alt); // Note the lane that is out-of-bounds. + /// assert_eq!(result, Simd::from_array([-5, 13, 10, 15])); + /// ``` + #[must_use] + #[inline] + pub fn gather_or(slice: &[T], idxs: Simd, or: Self) -> Self { + Self::gather_select(slice, Mask::splat(true), idxs, or) + } + + /// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector. + /// If an index is out-of-bounds, the lane is set to the default value for the type. + /// + /// # Examples + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "std")] use core_simd::Simd; + /// # #[cfg(not(feature = "std"))] use core::simd::Simd; + /// let vec: Vec = vec![10, 11, 12, 13, 14, 15, 16, 17, 18]; + /// let idxs = Simd::from_array([9, 3, 0, 5]); + /// + /// let result = Simd::gather_or_default(&vec, idxs); // Note the lane that is out-of-bounds. + /// assert_eq!(result, Simd::from_array([0, 13, 10, 15])); + /// ``` + #[must_use] + #[inline] + pub fn gather_or_default(slice: &[T], idxs: Simd) -> Self + where + T: Default, + { + Self::gather_or(slice, idxs, Self::splat(T::default())) + } + + /// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector. + /// The mask `enable`s all `true` lanes and disables all `false` lanes. + /// If an index is disabled or is out-of-bounds, the lane is selected from the `or` vector. + /// + /// # Examples + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "std")] use core_simd::{Simd, Mask}; + /// # #[cfg(not(feature = "std"))] use core::simd::{Simd, Mask}; + /// let vec: Vec = vec![10, 11, 12, 13, 14, 15, 16, 17, 18]; + /// let idxs = Simd::from_array([9, 3, 0, 5]); + /// let alt = Simd::from_array([-5, -4, -3, -2]); + /// let enable = Mask::from_array([true, true, true, false]); // Note the mask of the last lane. + /// + /// let result = Simd::gather_select(&vec, enable, idxs, alt); // Note the lane that is out-of-bounds. + /// assert_eq!(result, Simd::from_array([-5, 13, 10, -2])); + /// ``` + #[must_use] + #[inline] + pub fn gather_select( + slice: &[T], + enable: Mask, + idxs: Simd, + or: Self, + ) -> Self { + let enable: Mask = enable & idxs.lanes_lt(Simd::splat(slice.len())); + // SAFETY: We have masked-off out-of-bounds lanes. + unsafe { Self::gather_select_unchecked(slice, enable, idxs, or) } + } + + /// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector. + /// The mask `enable`s all `true` lanes and disables all `false` lanes. + /// If an index is disabled, the lane is selected from the `or` vector. + /// + /// # Safety + /// + /// Calling this function with an `enable`d out-of-bounds index is *[undefined behavior]* + /// even if the resulting value is not used. + /// + /// # Examples + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "std")] use core_simd::{Simd, Mask}; + /// # #[cfg(not(feature = "std"))] use core::simd::{Simd, Mask}; + /// let vec: Vec = vec![10, 11, 12, 13, 14, 15, 16, 17, 18]; + /// let idxs = Simd::from_array([9, 3, 0, 5]); + /// let alt = Simd::from_array([-5, -4, -3, -2]); + /// let enable = Mask::from_array([true, true, true, false]); // Note the final mask lane. + /// // If this mask was used to gather, it would be unsound. Let's fix that. + /// let enable = enable & idxs.lanes_lt(Simd::splat(vec.len())); + /// + /// // We have masked the OOB lane, so it's safe to gather now. + /// let result = unsafe { Simd::gather_select_unchecked(&vec, enable, idxs, alt) }; + /// assert_eq!(result, Simd::from_array([-5, 13, 10, -2])); + /// ``` + /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html + #[must_use] + #[inline] + pub unsafe fn gather_select_unchecked( + slice: &[T], + enable: Mask, + idxs: Simd, + or: Self, + ) -> Self { + let base_ptr = crate::simd::ptr::SimdConstPtr::splat(slice.as_ptr()); + // Ferris forgive me, I have done pointer arithmetic here. + let ptrs = base_ptr.wrapping_add(idxs); + // SAFETY: The ptrs have been bounds-masked to prevent memory-unsafe reads insha'allah + unsafe { intrinsics::simd_gather(or, ptrs, enable.to_int()) } + } + + /// Writes the values in a SIMD vector to potentially discontiguous indices in `slice`. + /// If two lanes in the scattered vector would write to the same index + /// only the last lane is guaranteed to actually be written. + /// + /// # Examples + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "std")] use core_simd::Simd; + /// # #[cfg(not(feature = "std"))] use core::simd::Simd; + /// let mut vec: Vec = vec![10, 11, 12, 13, 14, 15, 16, 17, 18]; + /// let idxs = Simd::from_array([9, 3, 0, 0]); + /// let vals = Simd::from_array([-27, 82, -41, 124]); + /// + /// vals.scatter(&mut vec, idxs); // index 0 receives two writes. + /// assert_eq!(vec, vec![124, 11, 12, 82, 14, 15, 16, 17, 18]); + /// ``` + #[inline] + pub fn scatter(self, slice: &mut [T], idxs: Simd) { + self.scatter_select(slice, Mask::splat(true), idxs) + } + + /// Writes the values in a SIMD vector to multiple potentially discontiguous indices in `slice`. + /// The mask `enable`s all `true` lanes and disables all `false` lanes. + /// If an enabled index is out-of-bounds, the lane is not written. + /// If two enabled lanes in the scattered vector would write to the same index, + /// only the last lane is guaranteed to actually be written. + /// + /// # Examples + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "std")] use core_simd::{Simd, Mask}; + /// # #[cfg(not(feature = "std"))] use core::simd::{Simd, Mask}; + /// let mut vec: Vec = vec![10, 11, 12, 13, 14, 15, 16, 17, 18]; + /// let idxs = Simd::from_array([9, 3, 0, 0]); + /// let vals = Simd::from_array([-27, 82, -41, 124]); + /// let enable = Mask::from_array([true, true, true, false]); // Note the mask of the last lane. + /// + /// vals.scatter_select(&mut vec, enable, idxs); // index 0's second write is masked, thus omitted. + /// assert_eq!(vec, vec![-41, 11, 12, 82, 14, 15, 16, 17, 18]); + /// ``` + #[inline] + pub fn scatter_select( + self, + slice: &mut [T], + enable: Mask, + idxs: Simd, + ) { + let enable: Mask = enable & idxs.lanes_lt(Simd::splat(slice.len())); + // SAFETY: We have masked-off out-of-bounds lanes. + unsafe { self.scatter_select_unchecked(slice, enable, idxs) } + } + + /// Writes the values in a SIMD vector to multiple potentially discontiguous indices in `slice`. + /// The mask `enable`s all `true` lanes and disables all `false` lanes. + /// If two enabled lanes in the scattered vector would write to the same index, + /// only the last lane is guaranteed to actually be written. + /// + /// # Safety + /// + /// Calling this function with an enabled out-of-bounds index is *[undefined behavior]*, + /// and may lead to memory corruption. + /// + /// # Examples + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "std")] use core_simd::{Simd, Mask}; + /// # #[cfg(not(feature = "std"))] use core::simd::{Simd, Mask}; + /// let mut vec: Vec = vec![10, 11, 12, 13, 14, 15, 16, 17, 18]; + /// let idxs = Simd::from_array([9, 3, 0, 0]); + /// let vals = Simd::from_array([-27, 82, -41, 124]); + /// let enable = Mask::from_array([true, true, true, false]); // Note the mask of the last lane. + /// // If this mask was used to scatter, it would be unsound. Let's fix that. + /// let enable = enable & idxs.lanes_lt(Simd::splat(vec.len())); + /// + /// // We have masked the OOB lane, so it's safe to scatter now. + /// unsafe { vals.scatter_select_unchecked(&mut vec, enable, idxs); } + /// // index 0's second write is masked, thus was omitted. + /// assert_eq!(vec, vec![-41, 11, 12, 82, 14, 15, 16, 17, 18]); + /// ``` + /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html + #[inline] + pub unsafe fn scatter_select_unchecked( + self, + slice: &mut [T], + enable: Mask, + idxs: Simd, + ) { + // SAFETY: This block works with *mut T derived from &mut 'a [T], + // which means it is delicate in Rust's borrowing model, circa 2021: + // &mut 'a [T] asserts uniqueness, so deriving &'a [T] invalidates live *mut Ts! + // Even though this block is largely safe methods, it must be exactly this way + // to prevent invalidating the raw ptrs while they're live. + // Thus, entering this block requires all values to use being already ready: + // 0. idxs we want to write to, which are used to construct the mask. + // 1. enable, which depends on an initial &'a [T] and the idxs. + // 2. actual values to scatter (self). + // 3. &mut [T] which will become our base ptr. + unsafe { + // Now Entering ☢️ *mut T Zone + let base_ptr = crate::simd::ptr::SimdMutPtr::splat(slice.as_mut_ptr()); + // Ferris forgive me, I have done pointer arithmetic here. + let ptrs = base_ptr.wrapping_add(idxs); + // The ptrs have been bounds-masked to prevent memory-unsafe writes insha'allah + intrinsics::simd_scatter(self, ptrs, enable.to_int()) + // Cleared ☢️ *mut T Zone + } + } +} + +impl Copy for Simd +where + T: SimdElement, + LaneCount: SupportedLaneCount, +{ +} + +impl Clone for Simd +where + T: SimdElement, + LaneCount: SupportedLaneCount, +{ + fn clone(&self) -> Self { + *self + } +} + +impl Default for Simd +where + LaneCount: SupportedLaneCount, + T: SimdElement + Default, +{ + #[inline] + fn default() -> Self { + Self::splat(T::default()) + } +} + +impl PartialEq for Simd +where + LaneCount: SupportedLaneCount, + T: SimdElement + PartialEq, +{ + #[inline] + fn eq(&self, other: &Self) -> bool { + // TODO use SIMD equality + self.to_array() == other.to_array() + } +} + +impl PartialOrd for Simd +where + LaneCount: SupportedLaneCount, + T: SimdElement + PartialOrd, +{ + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + // TODO use SIMD equality + self.to_array().partial_cmp(other.as_ref()) + } +} + +impl Eq for Simd +where + LaneCount: SupportedLaneCount, + T: SimdElement + Eq, +{ +} + +impl Ord for Simd +where + LaneCount: SupportedLaneCount, + T: SimdElement + Ord, +{ + #[inline] + fn cmp(&self, other: &Self) -> core::cmp::Ordering { + // TODO use SIMD equality + self.to_array().cmp(other.as_ref()) + } +} + +impl core::hash::Hash for Simd +where + LaneCount: SupportedLaneCount, + T: SimdElement + core::hash::Hash, +{ + #[inline] + fn hash(&self, state: &mut H) + where + H: core::hash::Hasher, + { + self.as_array().hash(state) + } +} + +// array references +impl AsRef<[T; LANES]> for Simd +where + LaneCount: SupportedLaneCount, + T: SimdElement, +{ + #[inline] + fn as_ref(&self) -> &[T; LANES] { + &self.0 + } +} + +impl AsMut<[T; LANES]> for Simd +where + LaneCount: SupportedLaneCount, + T: SimdElement, +{ + #[inline] + fn as_mut(&mut self) -> &mut [T; LANES] { + &mut self.0 + } +} + +// slice references +impl AsRef<[T]> for Simd +where + LaneCount: SupportedLaneCount, + T: SimdElement, +{ + #[inline] + fn as_ref(&self) -> &[T] { + &self.0 + } +} + +impl AsMut<[T]> for Simd +where + LaneCount: SupportedLaneCount, + T: SimdElement, +{ + #[inline] + fn as_mut(&mut self) -> &mut [T] { + &mut self.0 + } +} + +// vector/array conversion +impl From<[T; LANES]> for Simd +where + LaneCount: SupportedLaneCount, + T: SimdElement, +{ + fn from(array: [T; LANES]) -> Self { + Self(array) + } +} + +impl From> for [T; LANES] +where + LaneCount: SupportedLaneCount, + T: SimdElement, +{ + fn from(vector: Simd) -> Self { + vector.to_array() + } +} + +mod sealed { + pub trait Sealed {} +} +use sealed::Sealed; + +/// Marker trait for types that may be used as SIMD vector elements. +/// SAFETY: This trait, when implemented, asserts the compiler can monomorphize +/// `#[repr(simd)]` structs with the marked type as an element. +/// Strictly, it is valid to impl if the vector will not be miscompiled. +/// Practically, it is user-unfriendly to impl it if the vector won't compile, +/// even when no soundness guarantees are broken by allowing the user to try. +pub unsafe trait SimdElement: Sealed + Copy { + /// The mask element type corresponding to this element type. + type Mask: MaskElement; +} + +impl Sealed for u8 {} +unsafe impl SimdElement for u8 { + type Mask = i8; +} + +impl Sealed for u16 {} +unsafe impl SimdElement for u16 { + type Mask = i16; +} + +impl Sealed for u32 {} +unsafe impl SimdElement for u32 { + type Mask = i32; +} + +impl Sealed for u64 {} +unsafe impl SimdElement for u64 { + type Mask = i64; +} + +impl Sealed for usize {} +unsafe impl SimdElement for usize { + type Mask = isize; +} + +impl Sealed for i8 {} +unsafe impl SimdElement for i8 { + type Mask = i8; +} + +impl Sealed for i16 {} +unsafe impl SimdElement for i16 { + type Mask = i16; +} + +impl Sealed for i32 {} +unsafe impl SimdElement for i32 { + type Mask = i32; +} + +impl Sealed for i64 {} +unsafe impl SimdElement for i64 { + type Mask = i64; +} + +impl Sealed for isize {} +unsafe impl SimdElement for isize { + type Mask = isize; +} + +impl Sealed for f32 {} +unsafe impl SimdElement for f32 { + type Mask = i32; +} + +impl Sealed for f64 {} +unsafe impl SimdElement for f64 { + type Mask = i64; +} diff --git a/library/portable-simd/crates/core_simd/src/vector/float.rs b/library/portable-simd/crates/core_simd/src/vector/float.rs new file mode 100644 index 0000000000..c09d0ac84d --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/vector/float.rs @@ -0,0 +1,210 @@ +#![allow(non_camel_case_types)] + +use crate::simd::intrinsics; +use crate::simd::{LaneCount, Mask, Simd, SupportedLaneCount}; + +/// Implements inherent methods for a float vector containing multiple +/// `$lanes` of float `$type`, which uses `$bits_ty` as its binary +/// representation. +macro_rules! impl_float_vector { + { $type:ty, $bits_ty:ty, $mask_ty:ty } => { + impl Simd<$type, LANES> + where + LaneCount: SupportedLaneCount, + { + /// Raw transmutation to an unsigned integer vector type with the + /// same size and number of lanes. + #[inline] + pub fn to_bits(self) -> Simd<$bits_ty, LANES> { + assert_eq!(core::mem::size_of::(), core::mem::size_of::>()); + unsafe { core::mem::transmute_copy(&self) } + } + + /// Raw transmutation from an unsigned integer vector type with the + /// same size and number of lanes. + #[inline] + pub fn from_bits(bits: Simd<$bits_ty, LANES>) -> Self { + assert_eq!(core::mem::size_of::(), core::mem::size_of::>()); + unsafe { core::mem::transmute_copy(&bits) } + } + + /// Produces a vector where every lane has the absolute value of the + /// equivalently-indexed lane in `self`. + #[inline] + pub fn abs(self) -> Self { + unsafe { intrinsics::simd_fabs(self) } + } + + /// Fused multiply-add. Computes `(self * a) + b` with only one rounding error, + /// yielding a more accurate result than an unfused multiply-add. + /// + /// Using `mul_add` *may* be more performant than an unfused multiply-add if the target + /// architecture has a dedicated `fma` CPU instruction. However, this is not always + /// true, and will be heavily dependent on designing algorithms with specific target + /// hardware in mind. + #[cfg(feature = "std")] + #[inline] + pub fn mul_add(self, a: Self, b: Self) -> Self { + unsafe { intrinsics::simd_fma(self, a, b) } + } + + /// Produces a vector where every lane has the square root value + /// of the equivalently-indexed lane in `self` + #[inline] + #[cfg(feature = "std")] + pub fn sqrt(self) -> Self { + unsafe { intrinsics::simd_fsqrt(self) } + } + + /// Takes the reciprocal (inverse) of each lane, `1/x`. + #[inline] + pub fn recip(self) -> Self { + Self::splat(1.0) / self + } + + /// Converts each lane from radians to degrees. + #[inline] + pub fn to_degrees(self) -> Self { + // to_degrees uses a special constant for better precision, so extract that constant + self * Self::splat(<$type>::to_degrees(1.)) + } + + /// Converts each lane from degrees to radians. + #[inline] + pub fn to_radians(self) -> Self { + self * Self::splat(<$type>::to_radians(1.)) + } + + /// Returns true for each lane if it has a positive sign, including + /// `+0.0`, `NaN`s with positive sign bit and positive infinity. + #[inline] + pub fn is_sign_positive(self) -> Mask<$mask_ty, LANES> { + !self.is_sign_negative() + } + + /// Returns true for each lane if it has a negative sign, including + /// `-0.0`, `NaN`s with negative sign bit and negative infinity. + #[inline] + pub fn is_sign_negative(self) -> Mask<$mask_ty, LANES> { + let sign_bits = self.to_bits() & Simd::splat((!0 >> 1) + 1); + sign_bits.lanes_gt(Simd::splat(0)) + } + + /// Returns true for each lane if its value is `NaN`. + #[inline] + pub fn is_nan(self) -> Mask<$mask_ty, LANES> { + self.lanes_ne(self) + } + + /// Returns true for each lane if its value is positive infinity or negative infinity. + #[inline] + pub fn is_infinite(self) -> Mask<$mask_ty, LANES> { + self.abs().lanes_eq(Self::splat(<$type>::INFINITY)) + } + + /// Returns true for each lane if its value is neither infinite nor `NaN`. + #[inline] + pub fn is_finite(self) -> Mask<$mask_ty, LANES> { + self.abs().lanes_lt(Self::splat(<$type>::INFINITY)) + } + + /// Returns true for each lane if its value is subnormal. + #[inline] + pub fn is_subnormal(self) -> Mask<$mask_ty, LANES> { + self.abs().lanes_ne(Self::splat(0.0)) & (self.to_bits() & Self::splat(<$type>::INFINITY).to_bits()).lanes_eq(Simd::splat(0)) + } + + /// Returns true for each lane if its value is neither neither zero, infinite, + /// subnormal, or `NaN`. + #[inline] + pub fn is_normal(self) -> Mask<$mask_ty, LANES> { + !(self.abs().lanes_eq(Self::splat(0.0)) | self.is_nan() | self.is_subnormal() | self.is_infinite()) + } + + /// Replaces each lane with a number that represents its sign. + /// + /// * `1.0` if the number is positive, `+0.0`, or `INFINITY` + /// * `-1.0` if the number is negative, `-0.0`, or `NEG_INFINITY` + /// * `NAN` if the number is `NAN` + #[inline] + pub fn signum(self) -> Self { + self.is_nan().select(Self::splat(<$type>::NAN), Self::splat(1.0).copysign(self)) + } + + /// Returns each lane with the magnitude of `self` and the sign of `sign`. + /// + /// If any lane is a `NAN`, then a `NAN` with the sign of `sign` is returned. + #[inline] + pub fn copysign(self, sign: Self) -> Self { + let sign_bit = sign.to_bits() & Self::splat(-0.).to_bits(); + let magnitude = self.to_bits() & !Self::splat(-0.).to_bits(); + Self::from_bits(sign_bit | magnitude) + } + + /// Returns the minimum of each lane. + /// + /// If one of the values is `NAN`, then the other value is returned. + #[inline] + pub fn min(self, other: Self) -> Self { + // TODO consider using an intrinsic + self.is_nan().select( + other, + self.lanes_ge(other).select(other, self) + ) + } + + /// Returns the maximum of each lane. + /// + /// If one of the values is `NAN`, then the other value is returned. + #[inline] + pub fn max(self, other: Self) -> Self { + // TODO consider using an intrinsic + self.is_nan().select( + other, + self.lanes_le(other).select(other, self) + ) + } + + /// Restrict each lane to a certain interval unless it is NaN. + /// + /// For each lane in `self`, returns the corresponding lane in `max` if the lane is + /// greater than `max`, and the corresponding lane in `min` if the lane is less + /// than `min`. Otherwise returns the lane in `self`. + #[inline] + pub fn clamp(self, min: Self, max: Self) -> Self { + assert!( + min.lanes_le(max).all(), + "each lane in `min` must be less than or equal to the corresponding lane in `max`", + ); + let mut x = self; + x = x.lanes_lt(min).select(min, x); + x = x.lanes_gt(max).select(max, x); + x + } + } + }; +} + +impl_float_vector! { f32, u32, i32 } +impl_float_vector! { f64, u64, i64 } + +/// Vector of two `f32` values +pub type f32x2 = Simd; + +/// Vector of four `f32` values +pub type f32x4 = Simd; + +/// Vector of eight `f32` values +pub type f32x8 = Simd; + +/// Vector of 16 `f32` values +pub type f32x16 = Simd; + +/// Vector of two `f64` values +pub type f64x2 = Simd; + +/// Vector of four `f64` values +pub type f64x4 = Simd; + +/// Vector of eight `f64` values +pub type f64x8 = Simd; diff --git a/library/portable-simd/crates/core_simd/src/vector/int.rs b/library/portable-simd/crates/core_simd/src/vector/int.rs new file mode 100644 index 0000000000..3eac02a276 --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/vector/int.rs @@ -0,0 +1,103 @@ +#![allow(non_camel_case_types)] + +use crate::simd::{LaneCount, Mask, Simd, SupportedLaneCount}; + +/// Implements additional integer traits (Eq, Ord, Hash) on the specified vector `$name`, holding multiple `$lanes` of `$type`. +macro_rules! impl_integer_vector { + { $type:ty } => { + impl Simd<$type, LANES> + where + LaneCount: SupportedLaneCount, + { + /// Returns true for each positive lane and false if it is zero or negative. + #[inline] + pub fn is_positive(self) -> Mask<$type, LANES> { + self.lanes_gt(Self::splat(0)) + } + + /// Returns true for each negative lane and false if it is zero or positive. + #[inline] + pub fn is_negative(self) -> Mask<$type, LANES> { + self.lanes_lt(Self::splat(0)) + } + + /// Returns numbers representing the sign of each lane. + /// * `0` if the number is zero + /// * `1` if the number is positive + /// * `-1` if the number is negative + #[inline] + pub fn signum(self) -> Self { + self.is_positive().select( + Self::splat(1), + self.is_negative().select(Self::splat(-1), Self::splat(0)) + ) + } + } + } +} + +impl_integer_vector! { isize } +impl_integer_vector! { i16 } +impl_integer_vector! { i32 } +impl_integer_vector! { i64 } +impl_integer_vector! { i8 } + +/// Vector of two `isize` values +pub type isizex2 = Simd; + +/// Vector of four `isize` values +pub type isizex4 = Simd; + +/// Vector of eight `isize` values +pub type isizex8 = Simd; + +/// Vector of two `i16` values +pub type i16x2 = Simd; + +/// Vector of four `i16` values +pub type i16x4 = Simd; + +/// Vector of eight `i16` values +pub type i16x8 = Simd; + +/// Vector of 16 `i16` values +pub type i16x16 = Simd; + +/// Vector of 32 `i16` values +pub type i16x32 = Simd; + +/// Vector of two `i32` values +pub type i32x2 = Simd; + +/// Vector of four `i32` values +pub type i32x4 = Simd; + +/// Vector of eight `i32` values +pub type i32x8 = Simd; + +/// Vector of 16 `i32` values +pub type i32x16 = Simd; + +/// Vector of two `i64` values +pub type i64x2 = Simd; + +/// Vector of four `i64` values +pub type i64x4 = Simd; + +/// Vector of eight `i64` values +pub type i64x8 = Simd; + +/// Vector of four `i8` values +pub type i8x4 = Simd; + +/// Vector of eight `i8` values +pub type i8x8 = Simd; + +/// Vector of 16 `i8` values +pub type i8x16 = Simd; + +/// Vector of 32 `i8` values +pub type i8x32 = Simd; + +/// Vector of 64 `i8` values +pub type i8x64 = Simd; diff --git a/library/portable-simd/crates/core_simd/src/vector/ptr.rs b/library/portable-simd/crates/core_simd/src/vector/ptr.rs new file mode 100644 index 0000000000..ac9b98ca03 --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/vector/ptr.rs @@ -0,0 +1,55 @@ +//! Private implementation details of public gather/scatter APIs. +use crate::simd::{LaneCount, Simd, SupportedLaneCount}; +use core::mem; + +/// A vector of *const T. +#[derive(Debug, Copy, Clone)] +#[repr(simd)] +pub(crate) struct SimdConstPtr([*const T; LANES]); + +impl SimdConstPtr +where + LaneCount: SupportedLaneCount, + T: Sized, +{ + #[inline] + #[must_use] + pub fn splat(ptr: *const T) -> Self { + Self([ptr; LANES]) + } + + #[inline] + #[must_use] + pub fn wrapping_add(self, addend: Simd) -> Self { + unsafe { + let x: Simd = mem::transmute_copy(&self); + mem::transmute_copy(&{ x + (addend * mem::size_of::()) }) + } + } +} + +/// A vector of *mut T. Be very careful around potential aliasing. +#[derive(Debug, Copy, Clone)] +#[repr(simd)] +pub(crate) struct SimdMutPtr([*mut T; LANES]); + +impl SimdMutPtr +where + LaneCount: SupportedLaneCount, + T: Sized, +{ + #[inline] + #[must_use] + pub fn splat(ptr: *mut T) -> Self { + Self([ptr; LANES]) + } + + #[inline] + #[must_use] + pub fn wrapping_add(self, addend: Simd) -> Self { + unsafe { + let x: Simd = mem::transmute_copy(&self); + mem::transmute_copy(&{ x + (addend * mem::size_of::()) }) + } + } +} diff --git a/library/portable-simd/crates/core_simd/src/vector/uint.rs b/library/portable-simd/crates/core_simd/src/vector/uint.rs new file mode 100644 index 0000000000..ed91fc3640 --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/vector/uint.rs @@ -0,0 +1,63 @@ +#![allow(non_camel_case_types)] + +use crate::simd::Simd; + +/// Vector of two `usize` values +pub type usizex2 = Simd; + +/// Vector of four `usize` values +pub type usizex4 = Simd; + +/// Vector of eight `usize` values +pub type usizex8 = Simd; + +/// Vector of two `u16` values +pub type u16x2 = Simd; + +/// Vector of four `u16` values +pub type u16x4 = Simd; + +/// Vector of eight `u16` values +pub type u16x8 = Simd; + +/// Vector of 16 `u16` values +pub type u16x16 = Simd; + +/// Vector of 32 `u16` values +pub type u16x32 = Simd; + +/// Vector of two `u32` values +pub type u32x2 = Simd; + +/// Vector of four `u32` values +pub type u32x4 = Simd; + +/// Vector of eight `u32` values +pub type u32x8 = Simd; + +/// Vector of 16 `u32` values +pub type u32x16 = Simd; + +/// Vector of two `u64` values +pub type u64x2 = Simd; + +/// Vector of four `u64` values +pub type u64x4 = Simd; + +/// Vector of eight `u64` values +pub type u64x8 = Simd; + +/// Vector of four `u8` values +pub type u8x4 = Simd; + +/// Vector of eight `u8` values +pub type u8x8 = Simd; + +/// Vector of 16 `u8` values +pub type u8x16 = Simd; + +/// Vector of 32 `u8` values +pub type u8x32 = Simd; + +/// Vector of 64 `u8` values +pub type u8x64 = Simd; diff --git a/library/portable-simd/crates/core_simd/src/vendor.rs b/library/portable-simd/crates/core_simd/src/vendor.rs new file mode 100644 index 0000000000..e8ce7176b4 --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/vendor.rs @@ -0,0 +1,29 @@ +/// Provides implementations of `From<$a> for $b` and `From<$b> for $a` that transmutes the value. +#[allow(unused)] +macro_rules! from_transmute { + { unsafe $a:ty => $b:ty } => { + from_transmute!{ @impl $a => $b } + from_transmute!{ @impl $b => $a } + }; + { @impl $from:ty => $to:ty } => { + impl core::convert::From<$from> for $to { + #[inline] + fn from(value: $from) -> $to { + unsafe { core::mem::transmute(value) } + } + } + }; +} + +/// Conversions to x86's SIMD types. +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +mod x86; + +#[cfg(any(target_arch = "wasm32"))] +mod wasm32; + +#[cfg(any(target_arch = "aarch64", target_arch = "arm",))] +mod arm; + +#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))] +mod powerpc; diff --git a/library/portable-simd/crates/core_simd/src/vendor/arm.rs b/library/portable-simd/crates/core_simd/src/vendor/arm.rs new file mode 100644 index 0000000000..ff3b69ccf9 --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/vendor/arm.rs @@ -0,0 +1,76 @@ +#![allow(unused)] +use crate::simd::*; + +#[cfg(target_arch = "arm")] +use core::arch::arm::*; + +#[cfg(target_arch = "aarch64")] +use core::arch::aarch64::*; + +#[cfg(any( + target_arch = "aarch64", + all(target_arch = "arm", target_feature = "v7"), +))] +mod neon { + use super::*; + + from_transmute! { unsafe f32x2 => float32x2_t } + from_transmute! { unsafe f32x4 => float32x4_t } + + from_transmute! { unsafe u8x8 => uint8x8_t } + from_transmute! { unsafe u8x16 => uint8x16_t } + from_transmute! { unsafe i8x8 => int8x8_t } + from_transmute! { unsafe i8x16 => int8x16_t } + from_transmute! { unsafe u8x8 => poly8x8_t } + from_transmute! { unsafe u8x16 => poly8x16_t } + + from_transmute! { unsafe u16x4 => uint16x4_t } + from_transmute! { unsafe u16x8 => uint16x8_t } + from_transmute! { unsafe i16x4 => int16x4_t } + from_transmute! { unsafe i16x8 => int16x8_t } + from_transmute! { unsafe u16x4 => poly16x4_t } + from_transmute! { unsafe u16x8 => poly16x8_t } + + from_transmute! { unsafe u32x2 => uint32x2_t } + from_transmute! { unsafe u32x4 => uint32x4_t } + from_transmute! { unsafe i32x2 => int32x2_t } + from_transmute! { unsafe i32x4 => int32x4_t } + + from_transmute! { unsafe Simd => uint64x1_t } + from_transmute! { unsafe u64x2 => uint64x2_t } + from_transmute! { unsafe Simd => int64x1_t } + from_transmute! { unsafe i64x2 => int64x2_t } + from_transmute! { unsafe Simd => poly64x1_t } + from_transmute! { unsafe u64x2 => poly64x2_t } +} + +#[cfg(any( + all(target_feature = "v5te", not(target_feature = "mclass")), + all(target_feature = "mclass", target_feature = "dsp"), +))] +mod dsp { + use super::*; + + from_transmute! { unsafe Simd => uint16x2_t } + from_transmute! { unsafe Simd => int16x2_t } +} + +#[cfg(any( + all(target_feature = "v6", not(target_feature = "mclass")), + all(target_feature = "mclass", target_feature = "dsp"), +))] +mod simd32 { + use super::*; + + from_transmute! { unsafe Simd => uint8x4_t } + from_transmute! { unsafe Simd => int8x4_t } +} + +#[cfg(target_arch = "aarch64")] +mod aarch64 { + use super::neon::*; + use super::*; + + from_transmute! { unsafe Simd => float64x1_t } + from_transmute! { unsafe f64x2 => float64x2_t } +} diff --git a/library/portable-simd/crates/core_simd/src/vendor/powerpc.rs b/library/portable-simd/crates/core_simd/src/vendor/powerpc.rs new file mode 100644 index 0000000000..92f97d471b --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/vendor/powerpc.rs @@ -0,0 +1,11 @@ +use crate::simd::*; + +#[cfg(target_arch = "powerpc")] +use core::arch::powerpc::*; + +#[cfg(target_arch = "powerpc64")] +use core::arch::powerpc64::*; + +from_transmute! { unsafe f64x2 => vector_double } +from_transmute! { unsafe i64x2 => vector_signed_long } +from_transmute! { unsafe u64x2 => vector_unsigned_long } diff --git a/library/portable-simd/crates/core_simd/src/vendor/wasm32.rs b/library/portable-simd/crates/core_simd/src/vendor/wasm32.rs new file mode 100644 index 0000000000..ef3baf885b --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/vendor/wasm32.rs @@ -0,0 +1,30 @@ +use crate::simd::*; +use core::arch::wasm32::v128; + +from_transmute! { unsafe u8x16 => v128 } +from_transmute! { unsafe i8x16 => v128 } + +from_transmute! { unsafe u16x8 => v128 } +from_transmute! { unsafe i16x8 => v128 } + +from_transmute! { unsafe u32x4 => v128 } +from_transmute! { unsafe i32x4 => v128 } +from_transmute! { unsafe f32x4 => v128 } + +from_transmute! { unsafe u64x2 => v128 } +from_transmute! { unsafe i64x2 => v128 } +from_transmute! { unsafe f64x2 => v128 } + +#[cfg(target_pointer_width = "32")] +mod p32 { + use super::*; + from_transmute! { unsafe usizex4 => v128 } + from_transmute! { unsafe isizex4 => v128 } +} + +#[cfg(target_pointer_width = "64")] +mod p64 { + use super::*; + from_transmute! { unsafe usizex2 => v128 } + from_transmute! { unsafe isizex2 => v128 } +} diff --git a/library/portable-simd/crates/core_simd/src/vendor/x86.rs b/library/portable-simd/crates/core_simd/src/vendor/x86.rs new file mode 100644 index 0000000000..d3c19ccc53 --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/vendor/x86.rs @@ -0,0 +1,63 @@ +use crate::simd::*; + +#[cfg(any(target_arch = "x86"))] +use core::arch::x86::*; + +#[cfg(target_arch = "x86_64")] +use core::arch::x86_64::*; + +from_transmute! { unsafe u8x16 => __m128i } +from_transmute! { unsafe u8x32 => __m256i } +//from_transmute! { unsafe u8x64 => __m512i } +from_transmute! { unsafe i8x16 => __m128i } +from_transmute! { unsafe i8x32 => __m256i } +//from_transmute! { unsafe i8x64 => __m512i } + +from_transmute! { unsafe u16x8 => __m128i } +from_transmute! { unsafe u16x16 => __m256i } +from_transmute! { unsafe u16x32 => __m512i } +from_transmute! { unsafe i16x8 => __m128i } +from_transmute! { unsafe i16x16 => __m256i } +from_transmute! { unsafe i16x32 => __m512i } + +from_transmute! { unsafe u32x4 => __m128i } +from_transmute! { unsafe u32x8 => __m256i } +from_transmute! { unsafe u32x16 => __m512i } +from_transmute! { unsafe i32x4 => __m128i } +from_transmute! { unsafe i32x8 => __m256i } +from_transmute! { unsafe i32x16 => __m512i } +from_transmute! { unsafe f32x4 => __m128 } +from_transmute! { unsafe f32x8 => __m256 } +from_transmute! { unsafe f32x16 => __m512 } + +from_transmute! { unsafe u64x2 => __m128i } +from_transmute! { unsafe u64x4 => __m256i } +from_transmute! { unsafe u64x8 => __m512i } +from_transmute! { unsafe i64x2 => __m128i } +from_transmute! { unsafe i64x4 => __m256i } +from_transmute! { unsafe i64x8 => __m512i } +from_transmute! { unsafe f64x2 => __m128d } +from_transmute! { unsafe f64x4 => __m256d } +from_transmute! { unsafe f64x8 => __m512d } + +#[cfg(target_pointer_width = "32")] +mod p32 { + use super::*; + from_transmute! { unsafe usizex4 => __m128i } + from_transmute! { unsafe usizex8 => __m256i } + from_transmute! { unsafe Simd => __m512i } + from_transmute! { unsafe isizex4 => __m128i } + from_transmute! { unsafe isizex8 => __m256i } + from_transmute! { unsafe Simd => __m512i } +} + +#[cfg(target_pointer_width = "64")] +mod p64 { + use super::*; + from_transmute! { unsafe usizex2 => __m128i } + from_transmute! { unsafe usizex4 => __m256i } + from_transmute! { unsafe usizex8 => __m512i } + from_transmute! { unsafe isizex2 => __m128i } + from_transmute! { unsafe isizex4 => __m256i } + from_transmute! { unsafe isizex8 => __m512i } +} diff --git a/library/portable-simd/crates/core_simd/tests/f32_ops.rs b/library/portable-simd/crates/core_simd/tests/f32_ops.rs new file mode 100644 index 0000000000..414a832b1b --- /dev/null +++ b/library/portable-simd/crates/core_simd/tests/f32_ops.rs @@ -0,0 +1,5 @@ +#![feature(portable_simd)] + +#[macro_use] +mod ops_macros; +impl_float_tests! { f32, i32 } diff --git a/library/portable-simd/crates/core_simd/tests/f64_ops.rs b/library/portable-simd/crates/core_simd/tests/f64_ops.rs new file mode 100644 index 0000000000..e0a1fa33f3 --- /dev/null +++ b/library/portable-simd/crates/core_simd/tests/f64_ops.rs @@ -0,0 +1,5 @@ +#![feature(portable_simd)] + +#[macro_use] +mod ops_macros; +impl_float_tests! { f64, i64 } diff --git a/library/portable-simd/crates/core_simd/tests/i16_ops.rs b/library/portable-simd/crates/core_simd/tests/i16_ops.rs new file mode 100644 index 0000000000..f6c5d74fbb --- /dev/null +++ b/library/portable-simd/crates/core_simd/tests/i16_ops.rs @@ -0,0 +1,5 @@ +#![feature(portable_simd)] + +#[macro_use] +mod ops_macros; +impl_signed_tests! { i16 } diff --git a/library/portable-simd/crates/core_simd/tests/i32_ops.rs b/library/portable-simd/crates/core_simd/tests/i32_ops.rs new file mode 100644 index 0000000000..69a831c52a --- /dev/null +++ b/library/portable-simd/crates/core_simd/tests/i32_ops.rs @@ -0,0 +1,5 @@ +#![feature(portable_simd)] + +#[macro_use] +mod ops_macros; +impl_signed_tests! { i32 } diff --git a/library/portable-simd/crates/core_simd/tests/i64_ops.rs b/library/portable-simd/crates/core_simd/tests/i64_ops.rs new file mode 100644 index 0000000000..37ac081174 --- /dev/null +++ b/library/portable-simd/crates/core_simd/tests/i64_ops.rs @@ -0,0 +1,5 @@ +#![feature(portable_simd)] + +#[macro_use] +mod ops_macros; +impl_signed_tests! { i64 } diff --git a/library/portable-simd/crates/core_simd/tests/i8_ops.rs b/library/portable-simd/crates/core_simd/tests/i8_ops.rs new file mode 100644 index 0000000000..11e4a5cd6a --- /dev/null +++ b/library/portable-simd/crates/core_simd/tests/i8_ops.rs @@ -0,0 +1,5 @@ +#![feature(portable_simd)] + +#[macro_use] +mod ops_macros; +impl_signed_tests! { i8 } diff --git a/library/portable-simd/crates/core_simd/tests/isize_ops.rs b/library/portable-simd/crates/core_simd/tests/isize_ops.rs new file mode 100644 index 0000000000..5cc9de2b7f --- /dev/null +++ b/library/portable-simd/crates/core_simd/tests/isize_ops.rs @@ -0,0 +1,5 @@ +#![feature(portable_simd)] + +#[macro_use] +mod ops_macros; +impl_signed_tests! { isize } diff --git a/library/portable-simd/crates/core_simd/tests/mask_ops.rs b/library/portable-simd/crates/core_simd/tests/mask_ops.rs new file mode 100644 index 0000000000..f113b50cb7 --- /dev/null +++ b/library/portable-simd/crates/core_simd/tests/mask_ops.rs @@ -0,0 +1,3 @@ +#![feature(portable_simd)] + +mod mask_ops_impl; diff --git a/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask16.rs b/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask16.rs new file mode 100644 index 0000000000..0fe82fa680 --- /dev/null +++ b/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask16.rs @@ -0,0 +1,4 @@ +mask_tests! { mask16x4, 4 } +mask_tests! { mask16x8, 8 } +mask_tests! { mask16x16, 16 } +mask_tests! { mask16x32, 32 } diff --git a/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask32.rs b/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask32.rs new file mode 100644 index 0000000000..66d987a43c --- /dev/null +++ b/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask32.rs @@ -0,0 +1,4 @@ +mask_tests! { mask32x2, 2 } +mask_tests! { mask32x4, 4 } +mask_tests! { mask32x8, 8 } +mask_tests! { mask32x16, 16 } diff --git a/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask64.rs b/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask64.rs new file mode 100644 index 0000000000..a1f1f67b23 --- /dev/null +++ b/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask64.rs @@ -0,0 +1,3 @@ +mask_tests! { mask64x2, 2 } +mask_tests! { mask64x4, 4 } +mask_tests! { mask64x8, 8 } diff --git a/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask8.rs b/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask8.rs new file mode 100644 index 0000000000..9c06fbc041 --- /dev/null +++ b/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask8.rs @@ -0,0 +1,3 @@ +mask_tests! { mask8x8, 8 } +mask_tests! { mask8x16, 16 } +mask_tests! { mask8x32, 32 } diff --git a/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask_macros.rs b/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask_macros.rs new file mode 100644 index 0000000000..795f9e27c4 --- /dev/null +++ b/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask_macros.rs @@ -0,0 +1,225 @@ +macro_rules! mask_tests { + { $vector:ident, $lanes:literal } => { + #[cfg(test)] + mod $vector { + use core_simd::$vector as Vector; + const LANES: usize = $lanes; + + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::*; + + #[cfg(target_arch = "wasm32")] + wasm_bindgen_test_configure!(run_in_browser); + + fn from_slice(slice: &[bool]) -> Vector { + let mut value = Vector::default(); + for (i, b) in slice.iter().take(LANES).enumerate() { + value.set(i, *b); + } + value + } + + fn apply_unary_lanewise(x: Vector, f: impl Fn(bool) -> bool) -> Vector { + let mut value = Vector::default(); + for i in 0..LANES { + value.set(i, f(x.test(i))); + } + value + } + + fn apply_binary_lanewise(x: Vector, y: Vector, f: impl Fn(bool, bool) -> bool) -> Vector { + let mut value = Vector::default(); + for i in 0..LANES { + value.set(i, f(x.test(i), y.test(i))); + } + value + } + + fn apply_binary_scalar_lhs_lanewise(x: bool, mut y: Vector, f: impl Fn(bool, bool) -> bool) -> Vector { + for i in 0..LANES { + y.set(i, f(x, y.test(i))); + } + y + } + + fn apply_binary_scalar_rhs_lanewise(mut x: Vector, y: bool, f: impl Fn(bool, bool) -> bool) -> Vector { + for i in 0..LANES { + x.set(i, f(x.test(i), y)); + } + x + } + + const A: [bool; 64] = [ + false, true, false, true, false, false, true, true, + false, true, false, true, false, false, true, true, + false, true, false, true, false, false, true, true, + false, true, false, true, false, false, true, true, + false, true, false, true, false, false, true, true, + false, true, false, true, false, false, true, true, + false, true, false, true, false, false, true, true, + false, true, false, true, false, false, true, true, + ]; + const B: [bool; 64] = [ + false, false, true, true, false, true, false, true, + false, false, true, true, false, true, false, true, + false, false, true, true, false, true, false, true, + false, false, true, true, false, true, false, true, + false, false, true, true, false, true, false, true, + false, false, true, true, false, true, false, true, + false, false, true, true, false, true, false, true, + false, false, true, true, false, true, false, true, + ]; + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn bitand() { + let a = from_slice(&A); + let b = from_slice(&B); + let expected = apply_binary_lanewise(a, b, core::ops::BitAnd::bitand); + assert_eq!(a & b, expected); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn bitand_assign() { + let mut a = from_slice(&A); + let b = from_slice(&B); + let expected = apply_binary_lanewise(a, b, core::ops::BitAnd::bitand); + a &= b; + assert_eq!(a, expected); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn bitand_scalar_rhs() { + let a = from_slice(&A); + let expected = a; + assert_eq!(a & true, expected); + assert_eq!(a & false, Vector::splat(false)); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn bitand_scalar_lhs() { + let a = from_slice(&A); + let expected = a; + assert_eq!(true & a, expected); + assert_eq!(false & a, Vector::splat(false)); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn bitand_assign_scalar() { + let mut a = from_slice(&A); + let expected = a; + a &= true; + assert_eq!(a, expected); + a &= false; + assert_eq!(a, Vector::splat(false)); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn bitor() { + let a = from_slice(&A); + let b = from_slice(&B); + let expected = apply_binary_lanewise(a, b, core::ops::BitOr::bitor); + assert_eq!(a | b, expected); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn bitor_assign() { + let mut a = from_slice(&A); + let b = from_slice(&B); + let expected = apply_binary_lanewise(a, b, core::ops::BitOr::bitor); + a |= b; + assert_eq!(a, expected); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn bitor_scalar_rhs() { + let a = from_slice(&A); + assert_eq!(a | false, a); + assert_eq!(a | true, Vector::splat(true)); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn bitor_scalar_lhs() { + let a = from_slice(&A); + assert_eq!(false | a, a); + assert_eq!(true | a, Vector::splat(true)); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn bitor_assign_scalar() { + let mut a = from_slice(&A); + let expected = a; + a |= false; + assert_eq!(a, expected); + a |= true; + assert_eq!(a, Vector::splat(true)); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn bitxor() { + let a = from_slice(&A); + let b = from_slice(&B); + let expected = apply_binary_lanewise(a, b, core::ops::BitXor::bitxor); + assert_eq!(a ^ b, expected); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn bitxor_assign() { + let mut a = from_slice(&A); + let b = from_slice(&B); + let expected = apply_binary_lanewise(a, b, core::ops::BitXor::bitxor); + a ^= b; + assert_eq!(a, expected); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn bitxor_scalar_rhs() { + let a = from_slice(&A); + let expected = apply_binary_scalar_rhs_lanewise(a, true, core::ops::BitXor::bitxor); + assert_eq!(a ^ false, a); + assert_eq!(a ^ true, expected); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn bitxor_scalar_lhs() { + let a = from_slice(&A); + let expected = apply_binary_scalar_lhs_lanewise(true, a, core::ops::BitXor::bitxor); + assert_eq!(false ^ a, a); + assert_eq!(true ^ a, expected); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn bitxor_assign_scalar() { + let mut a = from_slice(&A); + let expected_unset = a; + let expected_set = apply_binary_scalar_rhs_lanewise(a, true, core::ops::BitXor::bitxor); + a ^= false; + assert_eq!(a, expected_unset); + a ^= true; + assert_eq!(a, expected_set); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn not() { + let v = from_slice(&A); + let expected = apply_unary_lanewise(v, core::ops::Not::not); + assert_eq!(!v, expected); + } + } + } +} diff --git a/library/portable-simd/crates/core_simd/tests/mask_ops_impl/masksize.rs b/library/portable-simd/crates/core_simd/tests/mask_ops_impl/masksize.rs new file mode 100644 index 0000000000..e0a44d870c --- /dev/null +++ b/library/portable-simd/crates/core_simd/tests/mask_ops_impl/masksize.rs @@ -0,0 +1,3 @@ +mask_tests! { masksizex2, 2 } +mask_tests! { masksizex4, 4 } +mask_tests! { masksizex8, 8 } diff --git a/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mod.rs b/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mod.rs new file mode 100644 index 0000000000..b9ec8462a0 --- /dev/null +++ b/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mod.rs @@ -0,0 +1,9 @@ +#[macro_use] +mod mask_macros; + +#[rustfmt::skip] +mod mask8; +mod mask16; +mod mask32; +mod mask64; +mod masksize; diff --git a/library/portable-simd/crates/core_simd/tests/masks.rs b/library/portable-simd/crates/core_simd/tests/masks.rs new file mode 100644 index 0000000000..6a8ecd33a7 --- /dev/null +++ b/library/portable-simd/crates/core_simd/tests/masks.rs @@ -0,0 +1,102 @@ +#![feature(portable_simd)] + +#[cfg(target_arch = "wasm32")] +use wasm_bindgen_test::*; + +#[cfg(target_arch = "wasm32")] +wasm_bindgen_test_configure!(run_in_browser); + +macro_rules! test_mask_api { + { $type:ident } => { + #[allow(non_snake_case)] + mod $type { + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::*; + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn set_and_test() { + let values = [true, false, false, true, false, false, true, false]; + let mut mask = core_simd::Mask::<$type, 8>::splat(false); + for (lane, value) in values.iter().copied().enumerate() { + mask.set(lane, value); + } + for (lane, value) in values.iter().copied().enumerate() { + assert_eq!(mask.test(lane), value); + } + } + + #[test] + #[should_panic] + fn set_invalid_lane() { + let mut mask = core_simd::Mask::<$type, 8>::splat(false); + mask.set(8, true); + let _ = mask; + } + + #[test] + #[should_panic] + fn test_invalid_lane() { + let mask = core_simd::Mask::<$type, 8>::splat(false); + let _ = mask.test(8); + } + + #[test] + fn any() { + assert!(!core_simd::Mask::<$type, 8>::splat(false).any()); + assert!(core_simd::Mask::<$type, 8>::splat(true).any()); + let mut v = core_simd::Mask::<$type, 8>::splat(false); + v.set(2, true); + assert!(v.any()); + } + + #[test] + fn all() { + assert!(!core_simd::Mask::<$type, 8>::splat(false).all()); + assert!(core_simd::Mask::<$type, 8>::splat(true).all()); + let mut v = core_simd::Mask::<$type, 8>::splat(false); + v.set(2, true); + assert!(!v.all()); + } + + #[test] + fn roundtrip_int_conversion() { + let values = [true, false, false, true, false, false, true, false]; + let mask = core_simd::Mask::<$type, 8>::from_array(values); + let int = mask.to_int(); + assert_eq!(int.to_array(), [-1, 0, 0, -1, 0, 0, -1, 0]); + assert_eq!(core_simd::Mask::<$type, 8>::from_int(int), mask); + } + + #[cfg(feature = "generic_const_exprs")] + #[test] + fn roundtrip_bitmask_conversion() { + let values = [ + true, false, false, true, false, false, true, false, + true, true, false, false, false, false, false, true, + ]; + let mask = core_simd::Mask::<$type, 16>::from_array(values); + let bitmask = mask.to_bitmask(); + assert_eq!(bitmask, [0b01001001, 0b10000011]); + assert_eq!(core_simd::Mask::<$type, 16>::from_bitmask(bitmask), mask); + } + } + } +} + +mod mask_api { + test_mask_api! { i8 } + test_mask_api! { i16 } + test_mask_api! { i32 } + test_mask_api! { i64 } + test_mask_api! { isize } +} + +#[test] +fn convert() { + let values = [true, false, false, true, false, false, true, false]; + assert_eq!( + core_simd::Mask::::from_array(values), + core_simd::Mask::::from_array(values).into() + ); +} diff --git a/library/portable-simd/crates/core_simd/tests/ops_macros.rs b/library/portable-simd/crates/core_simd/tests/ops_macros.rs new file mode 100644 index 0000000000..31b7ee2069 --- /dev/null +++ b/library/portable-simd/crates/core_simd/tests/ops_macros.rs @@ -0,0 +1,618 @@ +/// Implements a test on a unary operation using proptest. +/// +/// Compares the vector operation to the equivalent scalar operation. +#[macro_export] +macro_rules! impl_unary_op_test { + { $scalar:ty, $trait:ident :: $fn:ident, $scalar_fn:expr } => { + test_helpers::test_lanes! { + fn $fn() { + test_helpers::test_unary_elementwise( + & as core::ops::$trait>::$fn, + &$scalar_fn, + &|_| true, + ); + } + } + }; + { $scalar:ty, $trait:ident :: $fn:ident } => { + impl_unary_op_test! { $scalar, $trait::$fn, <$scalar as core::ops::$trait>::$fn } + }; +} + +/// Implements a test on a binary operation using proptest. +/// +/// Compares the vector operation to the equivalent scalar operation. +#[macro_export] +macro_rules! impl_binary_op_test { + { $scalar:ty, $trait:ident :: $fn:ident, $trait_assign:ident :: $fn_assign:ident, $scalar_fn:expr } => { + mod $fn { + use super::*; + use core_simd::Simd; + + test_helpers::test_lanes! { + fn normal() { + test_helpers::test_binary_elementwise( + & as core::ops::$trait>::$fn, + &$scalar_fn, + &|_, _| true, + ); + } + + fn scalar_rhs() { + test_helpers::test_binary_scalar_rhs_elementwise( + & as core::ops::$trait<$scalar>>::$fn, + &$scalar_fn, + &|_, _| true, + ); + } + + fn scalar_lhs() { + test_helpers::test_binary_scalar_lhs_elementwise( + &<$scalar as core::ops::$trait>>::$fn, + &$scalar_fn, + &|_, _| true, + ); + } + + fn assign() { + test_helpers::test_binary_elementwise( + &|mut a, b| { as core::ops::$trait_assign>::$fn_assign(&mut a, b); a }, + &$scalar_fn, + &|_, _| true, + ); + } + + fn assign_scalar_rhs() { + test_helpers::test_binary_scalar_rhs_elementwise( + &|mut a, b| { as core::ops::$trait_assign<$scalar>>::$fn_assign(&mut a, b); a }, + &$scalar_fn, + &|_, _| true, + ); + } + } + } + }; + { $scalar:ty, $trait:ident :: $fn:ident, $trait_assign:ident :: $fn_assign:ident } => { + impl_binary_op_test! { $scalar, $trait::$fn, $trait_assign::$fn_assign, <$scalar as core::ops::$trait>::$fn } + }; +} + +/// Implements a test on a binary operation using proptest. +/// +/// Like `impl_binary_op_test`, but allows providing a function for rejecting particular inputs +/// (like the `proptest_assume` macro). +/// +/// Compares the vector operation to the equivalent scalar operation. +#[macro_export] +macro_rules! impl_binary_checked_op_test { + { $scalar:ty, $trait:ident :: $fn:ident, $trait_assign:ident :: $fn_assign:ident, $scalar_fn:expr, $check_fn:expr } => { + mod $fn { + use super::*; + use core_simd::Simd; + + test_helpers::test_lanes! { + fn normal() { + test_helpers::test_binary_elementwise( + & as core::ops::$trait>::$fn, + &$scalar_fn, + &|x, y| x.iter().zip(y.iter()).all(|(x, y)| $check_fn(*x, *y)), + ); + } + + fn scalar_rhs() { + test_helpers::test_binary_scalar_rhs_elementwise( + & as core::ops::$trait<$scalar>>::$fn, + &$scalar_fn, + &|x, y| x.iter().all(|x| $check_fn(*x, y)), + ); + } + + fn scalar_lhs() { + test_helpers::test_binary_scalar_lhs_elementwise( + &<$scalar as core::ops::$trait>>::$fn, + &$scalar_fn, + &|x, y| y.iter().all(|y| $check_fn(x, *y)), + ); + } + + fn assign() { + test_helpers::test_binary_elementwise( + &|mut a, b| { as core::ops::$trait_assign>::$fn_assign(&mut a, b); a }, + &$scalar_fn, + &|x, y| x.iter().zip(y.iter()).all(|(x, y)| $check_fn(*x, *y)), + ) + } + + fn assign_scalar_rhs() { + test_helpers::test_binary_scalar_rhs_elementwise( + &|mut a, b| { as core::ops::$trait_assign<$scalar>>::$fn_assign(&mut a, b); a }, + &$scalar_fn, + &|x, y| x.iter().all(|x| $check_fn(*x, y)), + ) + } + } + } + }; + { $scalar:ty, $trait:ident :: $fn:ident, $trait_assign:ident :: $fn_assign:ident, $check_fn:expr } => { + impl_binary_checked_op_test! { $scalar, $trait::$fn, $trait_assign::$fn_assign, <$scalar as core::ops::$trait>::$fn, $check_fn } + }; +} + +#[macro_export] +macro_rules! impl_common_integer_tests { + { $vector:ident, $scalar:ident } => { + test_helpers::test_lanes! { + fn horizontal_sum() { + test_helpers::test_1(&|x| { + test_helpers::prop_assert_biteq! ( + $vector::::from_array(x).horizontal_sum(), + x.iter().copied().fold(0 as $scalar, $scalar::wrapping_add), + ); + Ok(()) + }); + } + + fn horizontal_product() { + test_helpers::test_1(&|x| { + test_helpers::prop_assert_biteq! ( + $vector::::from_array(x).horizontal_product(), + x.iter().copied().fold(1 as $scalar, $scalar::wrapping_mul), + ); + Ok(()) + }); + } + + fn horizontal_and() { + test_helpers::test_1(&|x| { + test_helpers::prop_assert_biteq! ( + $vector::::from_array(x).horizontal_and(), + x.iter().copied().fold(-1i8 as $scalar, <$scalar as core::ops::BitAnd>::bitand), + ); + Ok(()) + }); + } + + fn horizontal_or() { + test_helpers::test_1(&|x| { + test_helpers::prop_assert_biteq! ( + $vector::::from_array(x).horizontal_or(), + x.iter().copied().fold(0 as $scalar, <$scalar as core::ops::BitOr>::bitor), + ); + Ok(()) + }); + } + + fn horizontal_xor() { + test_helpers::test_1(&|x| { + test_helpers::prop_assert_biteq! ( + $vector::::from_array(x).horizontal_xor(), + x.iter().copied().fold(0 as $scalar, <$scalar as core::ops::BitXor>::bitxor), + ); + Ok(()) + }); + } + + fn horizontal_max() { + test_helpers::test_1(&|x| { + test_helpers::prop_assert_biteq! ( + $vector::::from_array(x).horizontal_max(), + x.iter().copied().max().unwrap(), + ); + Ok(()) + }); + } + + fn horizontal_min() { + test_helpers::test_1(&|x| { + test_helpers::prop_assert_biteq! ( + $vector::::from_array(x).horizontal_min(), + x.iter().copied().min().unwrap(), + ); + Ok(()) + }); + } + } + } +} + +/// Implement tests for signed integers. +#[macro_export] +macro_rules! impl_signed_tests { + { $scalar:tt } => { + mod $scalar { + type Vector = core_simd::Simd; + type Scalar = $scalar; + + impl_common_integer_tests! { Vector, Scalar } + + test_helpers::test_lanes! { + fn neg() { + test_helpers::test_unary_elementwise( + & as core::ops::Neg>::neg, + &::neg, + &|x| !x.contains(&Scalar::MIN), + ); + } + + fn is_positive() { + test_helpers::test_unary_mask_elementwise( + &Vector::::is_positive, + &Scalar::is_positive, + &|_| true, + ); + } + + fn is_negative() { + test_helpers::test_unary_mask_elementwise( + &Vector::::is_negative, + &Scalar::is_negative, + &|_| true, + ); + } + + fn signum() { + test_helpers::test_unary_elementwise( + &Vector::::signum, + &Scalar::signum, + &|_| true, + ) + } + + } + + test_helpers::test_lanes_panic! { + fn div_min_overflow_panics() { + let a = Vector::::splat(Scalar::MIN); + let b = Vector::::splat(-1); + let _ = a / b; + } + + fn div_by_all_zeros_panics() { + let a = Vector::::splat(42); + let b = Vector::::splat(0); + let _ = a / b; + } + + fn div_by_one_zero_panics() { + let a = Vector::::splat(42); + let mut b = Vector::::splat(21); + b[0] = 0 as _; + let _ = a / b; + } + + fn rem_min_overflow_panic() { + let a = Vector::::splat(Scalar::MIN); + let b = Vector::::splat(-1); + let _ = a % b; + } + + fn rem_zero_panic() { + let a = Vector::::splat(42); + let b = Vector::::splat(0); + let _ = a % b; + } + } + + test_helpers::test_lanes! { + fn div_neg_one_no_panic() { + let a = Vector::::splat(42); + let b = Vector::::splat(-1); + let _ = a / b; + } + + fn rem_neg_one_no_panic() { + let a = Vector::::splat(42); + let b = Vector::::splat(-1); + let _ = a % b; + } + } + + impl_binary_op_test!(Scalar, Add::add, AddAssign::add_assign, Scalar::wrapping_add); + impl_binary_op_test!(Scalar, Sub::sub, SubAssign::sub_assign, Scalar::wrapping_sub); + impl_binary_op_test!(Scalar, Mul::mul, MulAssign::mul_assign, Scalar::wrapping_mul); + + // Exclude Div and Rem panicking cases + impl_binary_checked_op_test!(Scalar, Div::div, DivAssign::div_assign, Scalar::wrapping_div, |x, y| y != 0 && !(x == Scalar::MIN && y == -1)); + impl_binary_checked_op_test!(Scalar, Rem::rem, RemAssign::rem_assign, Scalar::wrapping_rem, |x, y| y != 0 && !(x == Scalar::MIN && y == -1)); + + impl_unary_op_test!(Scalar, Not::not); + impl_binary_op_test!(Scalar, BitAnd::bitand, BitAndAssign::bitand_assign); + impl_binary_op_test!(Scalar, BitOr::bitor, BitOrAssign::bitor_assign); + impl_binary_op_test!(Scalar, BitXor::bitxor, BitXorAssign::bitxor_assign); + } + } +} + +/// Implement tests for unsigned integers. +#[macro_export] +macro_rules! impl_unsigned_tests { + { $scalar:tt } => { + mod $scalar { + type Vector = core_simd::Simd; + type Scalar = $scalar; + + impl_common_integer_tests! { Vector, Scalar } + + test_helpers::test_lanes_panic! { + fn rem_zero_panic() { + let a = Vector::::splat(42); + let b = Vector::::splat(0); + let _ = a % b; + } + } + + impl_binary_op_test!(Scalar, Add::add, AddAssign::add_assign, Scalar::wrapping_add); + impl_binary_op_test!(Scalar, Sub::sub, SubAssign::sub_assign, Scalar::wrapping_sub); + impl_binary_op_test!(Scalar, Mul::mul, MulAssign::mul_assign, Scalar::wrapping_mul); + + // Exclude Div and Rem panicking cases + impl_binary_checked_op_test!(Scalar, Div::div, DivAssign::div_assign, Scalar::wrapping_div, |_, y| y != 0); + impl_binary_checked_op_test!(Scalar, Rem::rem, RemAssign::rem_assign, Scalar::wrapping_rem, |_, y| y != 0); + + impl_unary_op_test!(Scalar, Not::not); + impl_binary_op_test!(Scalar, BitAnd::bitand, BitAndAssign::bitand_assign); + impl_binary_op_test!(Scalar, BitOr::bitor, BitOrAssign::bitor_assign); + impl_binary_op_test!(Scalar, BitXor::bitxor, BitXorAssign::bitxor_assign); + } + } +} + +/// Implement tests for floating point numbers. +#[macro_export] +macro_rules! impl_float_tests { + { $scalar:tt, $int_scalar:tt } => { + mod $scalar { + type Vector = core_simd::Simd; + type Scalar = $scalar; + + impl_unary_op_test!(Scalar, Neg::neg); + impl_binary_op_test!(Scalar, Add::add, AddAssign::add_assign); + impl_binary_op_test!(Scalar, Sub::sub, SubAssign::sub_assign); + impl_binary_op_test!(Scalar, Mul::mul, MulAssign::mul_assign); + impl_binary_op_test!(Scalar, Div::div, DivAssign::div_assign); + impl_binary_op_test!(Scalar, Rem::rem, RemAssign::rem_assign); + + test_helpers::test_lanes! { + fn is_sign_positive() { + test_helpers::test_unary_mask_elementwise( + &Vector::::is_sign_positive, + &Scalar::is_sign_positive, + &|_| true, + ); + } + + fn is_sign_negative() { + test_helpers::test_unary_mask_elementwise( + &Vector::::is_sign_negative, + &Scalar::is_sign_negative, + &|_| true, + ); + } + + fn is_finite() { + test_helpers::test_unary_mask_elementwise( + &Vector::::is_finite, + &Scalar::is_finite, + &|_| true, + ); + } + + fn is_infinite() { + test_helpers::test_unary_mask_elementwise( + &Vector::::is_infinite, + &Scalar::is_infinite, + &|_| true, + ); + } + + fn is_nan() { + test_helpers::test_unary_mask_elementwise( + &Vector::::is_nan, + &Scalar::is_nan, + &|_| true, + ); + } + + fn is_normal() { + test_helpers::test_unary_mask_elementwise( + &Vector::::is_normal, + &Scalar::is_normal, + &|_| true, + ); + } + + fn is_subnormal() { + test_helpers::test_unary_mask_elementwise( + &Vector::::is_subnormal, + &Scalar::is_subnormal, + &|_| true, + ); + } + + fn abs() { + test_helpers::test_unary_elementwise( + &Vector::::abs, + &Scalar::abs, + &|_| true, + ) + } + + fn recip() { + test_helpers::test_unary_elementwise( + &Vector::::recip, + &Scalar::recip, + &|_| true, + ) + } + + fn to_degrees() { + test_helpers::test_unary_elementwise( + &Vector::::to_degrees, + &Scalar::to_degrees, + &|_| true, + ) + } + + fn to_radians() { + test_helpers::test_unary_elementwise( + &Vector::::to_radians, + &Scalar::to_radians, + &|_| true, + ) + } + + fn signum() { + test_helpers::test_unary_elementwise( + &Vector::::signum, + &Scalar::signum, + &|_| true, + ) + } + + fn copysign() { + test_helpers::test_binary_elementwise( + &Vector::::copysign, + &Scalar::copysign, + &|_, _| true, + ) + } + + fn min() { + // Regular conditions (both values aren't zero) + test_helpers::test_binary_elementwise( + &Vector::::min, + &Scalar::min, + // Reject the case where both values are zero with different signs + &|a, b| { + for (a, b) in a.iter().zip(b.iter()) { + if *a == 0. && *b == 0. && a.signum() != b.signum() { + return false; + } + } + true + } + ); + + // Special case where both values are zero + let p_zero = Vector::::splat(0.); + let n_zero = Vector::::splat(-0.); + assert!(p_zero.min(n_zero).to_array().iter().all(|x| *x == 0.)); + assert!(n_zero.min(p_zero).to_array().iter().all(|x| *x == 0.)); + } + + fn max() { + // Regular conditions (both values aren't zero) + test_helpers::test_binary_elementwise( + &Vector::::max, + &Scalar::max, + // Reject the case where both values are zero with different signs + &|a, b| { + for (a, b) in a.iter().zip(b.iter()) { + if *a == 0. && *b == 0. && a.signum() != b.signum() { + return false; + } + } + true + } + ); + + // Special case where both values are zero + let p_zero = Vector::::splat(0.); + let n_zero = Vector::::splat(-0.); + assert!(p_zero.max(n_zero).to_array().iter().all(|x| *x == 0.)); + assert!(n_zero.max(p_zero).to_array().iter().all(|x| *x == 0.)); + } + + fn clamp() { + test_helpers::test_3(&|value: [Scalar; LANES], mut min: [Scalar; LANES], mut max: [Scalar; LANES]| { + for (min, max) in min.iter_mut().zip(max.iter_mut()) { + if max < min { + core::mem::swap(min, max); + } + if min.is_nan() { + *min = Scalar::NEG_INFINITY; + } + if max.is_nan() { + *max = Scalar::INFINITY; + } + } + + let mut result_scalar = [Scalar::default(); LANES]; + for i in 0..LANES { + result_scalar[i] = value[i].clamp(min[i], max[i]); + } + let result_vector = Vector::from_array(value).clamp(min.into(), max.into()).to_array(); + test_helpers::prop_assert_biteq!(result_scalar, result_vector); + Ok(()) + }) + } + + fn horizontal_sum() { + test_helpers::test_1(&|x| { + test_helpers::prop_assert_biteq! ( + Vector::::from_array(x).horizontal_sum(), + x.iter().sum(), + ); + Ok(()) + }); + } + + fn horizontal_product() { + test_helpers::test_1(&|x| { + test_helpers::prop_assert_biteq! ( + Vector::::from_array(x).horizontal_product(), + x.iter().product(), + ); + Ok(()) + }); + } + + fn horizontal_max() { + test_helpers::test_1(&|x| { + let vmax = Vector::::from_array(x).horizontal_max(); + let smax = x.iter().copied().fold(Scalar::NAN, Scalar::max); + // 0 and -0 are treated the same + if !(x.contains(&0.) && x.contains(&-0.) && vmax.abs() == 0. && smax.abs() == 0.) { + test_helpers::prop_assert_biteq!(vmax, smax); + } + Ok(()) + }); + } + + fn horizontal_min() { + test_helpers::test_1(&|x| { + let vmax = Vector::::from_array(x).horizontal_min(); + let smax = x.iter().copied().fold(Scalar::NAN, Scalar::min); + // 0 and -0 are treated the same + if !(x.contains(&0.) && x.contains(&-0.) && vmax.abs() == 0. && smax.abs() == 0.) { + test_helpers::prop_assert_biteq!(vmax, smax); + } + Ok(()) + }); + } + } + + #[cfg(feature = "std")] + mod std { + use super::*; + test_helpers::test_lanes! { + fn sqrt() { + test_helpers::test_unary_elementwise( + &Vector::::sqrt, + &Scalar::sqrt, + &|_| true, + ) + } + + fn mul_add() { + test_helpers::test_ternary_elementwise( + &Vector::::mul_add, + &Scalar::mul_add, + &|_, _, _| true, + ) + } + } + } + } + } +} diff --git a/library/portable-simd/crates/core_simd/tests/round.rs b/library/portable-simd/crates/core_simd/tests/round.rs new file mode 100644 index 0000000000..11d617a6c2 --- /dev/null +++ b/library/portable-simd/crates/core_simd/tests/round.rs @@ -0,0 +1,92 @@ +#![feature(portable_simd)] + +macro_rules! float_rounding_test { + { $scalar:tt, $int_scalar:tt } => { + mod $scalar { + type Vector = core_simd::Simd<$scalar, LANES>; + type Scalar = $scalar; + type IntScalar = $int_scalar; + + #[cfg(feature = "std")] + test_helpers::test_lanes! { + fn ceil() { + test_helpers::test_unary_elementwise( + &Vector::::ceil, + &Scalar::ceil, + &|_| true, + ) + } + + fn floor() { + test_helpers::test_unary_elementwise( + &Vector::::floor, + &Scalar::floor, + &|_| true, + ) + } + + fn round() { + test_helpers::test_unary_elementwise( + &Vector::::round, + &Scalar::round, + &|_| true, + ) + } + + fn trunc() { + test_helpers::test_unary_elementwise( + &Vector::::trunc, + &Scalar::trunc, + &|_| true, + ) + } + + fn fract() { + test_helpers::test_unary_elementwise( + &Vector::::fract, + &Scalar::fract, + &|_| true, + ) + } + } + + test_helpers::test_lanes! { + fn from_int() { + test_helpers::test_unary_elementwise( + &Vector::::round_from_int, + &|x| x as Scalar, + &|_| true, + ) + } + + fn to_int_unchecked() { + // The maximum integer that can be represented by the equivalently sized float has + // all of the mantissa digits set to 1, pushed up to the MSB. + const ALL_MANTISSA_BITS: IntScalar = ((1 << ::MANTISSA_DIGITS) - 1); + const MAX_REPRESENTABLE_VALUE: Scalar = + (ALL_MANTISSA_BITS << (core::mem::size_of::() * 8 - ::MANTISSA_DIGITS as usize - 1)) as Scalar; + + let mut runner = proptest::test_runner::TestRunner::default(); + runner.run( + &test_helpers::array::UniformArrayStrategy::new(-MAX_REPRESENTABLE_VALUE..MAX_REPRESENTABLE_VALUE), + |x| { + let result_1 = unsafe { Vector::from_array(x).to_int_unchecked().to_array() }; + let result_2 = { + let mut result = [0; LANES]; + for (i, o) in x.iter().zip(result.iter_mut()) { + *o = unsafe { i.to_int_unchecked() }; + } + result + }; + test_helpers::prop_assert_biteq!(result_1, result_2); + Ok(()) + }, + ).unwrap(); + } + } + } + } +} + +float_rounding_test! { f32, i32 } +float_rounding_test! { f64, i64 } diff --git a/library/portable-simd/crates/core_simd/tests/swizzle.rs b/library/portable-simd/crates/core_simd/tests/swizzle.rs new file mode 100644 index 0000000000..51c63611ab --- /dev/null +++ b/library/portable-simd/crates/core_simd/tests/swizzle.rs @@ -0,0 +1,62 @@ +#![feature(portable_simd)] +use core_simd::{Simd, Swizzle}; + +#[cfg(target_arch = "wasm32")] +use wasm_bindgen_test::*; + +#[cfg(target_arch = "wasm32")] +wasm_bindgen_test_configure!(run_in_browser); + +#[test] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +fn swizzle() { + struct Index; + impl Swizzle<4, 4> for Index { + const INDEX: [usize; 4] = [2, 1, 3, 0]; + } + impl Swizzle<4, 2> for Index { + const INDEX: [usize; 2] = [1, 1]; + } + + let vector = Simd::from_array([2, 4, 1, 9]); + assert_eq!(Index::swizzle(vector).to_array(), [1, 4, 9, 2]); + assert_eq!(Index::swizzle(vector).to_array(), [4, 4]); +} + +#[test] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +fn reverse() { + let a = Simd::from_array([1, 2, 3, 4]); + assert_eq!(a.reverse().to_array(), [4, 3, 2, 1]); +} + +#[test] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +fn rotate() { + let a = Simd::from_array([1, 2, 3, 4]); + assert_eq!(a.rotate_lanes_left::<0>().to_array(), [1, 2, 3, 4]); + assert_eq!(a.rotate_lanes_left::<1>().to_array(), [2, 3, 4, 1]); + assert_eq!(a.rotate_lanes_left::<2>().to_array(), [3, 4, 1, 2]); + assert_eq!(a.rotate_lanes_left::<3>().to_array(), [4, 1, 2, 3]); + assert_eq!(a.rotate_lanes_left::<4>().to_array(), [1, 2, 3, 4]); + assert_eq!(a.rotate_lanes_left::<5>().to_array(), [2, 3, 4, 1]); + assert_eq!(a.rotate_lanes_right::<0>().to_array(), [1, 2, 3, 4]); + assert_eq!(a.rotate_lanes_right::<1>().to_array(), [4, 1, 2, 3]); + assert_eq!(a.rotate_lanes_right::<2>().to_array(), [3, 4, 1, 2]); + assert_eq!(a.rotate_lanes_right::<3>().to_array(), [2, 3, 4, 1]); + assert_eq!(a.rotate_lanes_right::<4>().to_array(), [1, 2, 3, 4]); + assert_eq!(a.rotate_lanes_right::<5>().to_array(), [4, 1, 2, 3]); +} + +#[test] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +fn interleave() { + let a = Simd::from_array([0, 1, 2, 3, 4, 5, 6, 7]); + let b = Simd::from_array([8, 9, 10, 11, 12, 13, 14, 15]); + let (lo, hi) = a.interleave(b); + assert_eq!(lo.to_array(), [0, 8, 1, 9, 2, 10, 3, 11]); + assert_eq!(hi.to_array(), [4, 12, 5, 13, 6, 14, 7, 15]); + let (even, odd) = lo.deinterleave(hi); + assert_eq!(even, a); + assert_eq!(odd, b); +} diff --git a/library/portable-simd/crates/core_simd/tests/to_bytes.rs b/library/portable-simd/crates/core_simd/tests/to_bytes.rs new file mode 100644 index 0000000000..debb4335e2 --- /dev/null +++ b/library/portable-simd/crates/core_simd/tests/to_bytes.rs @@ -0,0 +1,14 @@ +#![feature(portable_simd, generic_const_exprs, adt_const_params)] +#![allow(incomplete_features)] +#![cfg(feature = "generic_const_exprs")] + +use core_simd::Simd; + +#[test] +fn byte_convert() { + let int = Simd::::from_array([0xdeadbeef, 0x8badf00d]); + let bytes = int.to_ne_bytes(); + assert_eq!(int[0].to_ne_bytes(), bytes[..4]); + assert_eq!(int[1].to_ne_bytes(), bytes[4..]); + assert_eq!(Simd::::from_ne_bytes(bytes), int); +} diff --git a/library/portable-simd/crates/core_simd/tests/u16_ops.rs b/library/portable-simd/crates/core_simd/tests/u16_ops.rs new file mode 100644 index 0000000000..9ae3bd6a47 --- /dev/null +++ b/library/portable-simd/crates/core_simd/tests/u16_ops.rs @@ -0,0 +1,5 @@ +#![feature(portable_simd)] + +#[macro_use] +mod ops_macros; +impl_unsigned_tests! { u16 } diff --git a/library/portable-simd/crates/core_simd/tests/u32_ops.rs b/library/portable-simd/crates/core_simd/tests/u32_ops.rs new file mode 100644 index 0000000000..de34b73d65 --- /dev/null +++ b/library/portable-simd/crates/core_simd/tests/u32_ops.rs @@ -0,0 +1,5 @@ +#![feature(portable_simd)] + +#[macro_use] +mod ops_macros; +impl_unsigned_tests! { u32 } diff --git a/library/portable-simd/crates/core_simd/tests/u64_ops.rs b/library/portable-simd/crates/core_simd/tests/u64_ops.rs new file mode 100644 index 0000000000..8ee5a318c8 --- /dev/null +++ b/library/portable-simd/crates/core_simd/tests/u64_ops.rs @@ -0,0 +1,5 @@ +#![feature(portable_simd)] + +#[macro_use] +mod ops_macros; +impl_unsigned_tests! { u64 } diff --git a/library/portable-simd/crates/core_simd/tests/u8_ops.rs b/library/portable-simd/crates/core_simd/tests/u8_ops.rs new file mode 100644 index 0000000000..6d72111212 --- /dev/null +++ b/library/portable-simd/crates/core_simd/tests/u8_ops.rs @@ -0,0 +1,5 @@ +#![feature(portable_simd)] + +#[macro_use] +mod ops_macros; +impl_unsigned_tests! { u8 } diff --git a/library/portable-simd/crates/core_simd/tests/usize_ops.rs b/library/portable-simd/crates/core_simd/tests/usize_ops.rs new file mode 100644 index 0000000000..9c7b1687a0 --- /dev/null +++ b/library/portable-simd/crates/core_simd/tests/usize_ops.rs @@ -0,0 +1,5 @@ +#![feature(portable_simd)] + +#[macro_use] +mod ops_macros; +impl_unsigned_tests! { usize } diff --git a/library/portable-simd/crates/core_simd/webdriver.json b/library/portable-simd/crates/core_simd/webdriver.json new file mode 100644 index 0000000000..f1d5734f1c --- /dev/null +++ b/library/portable-simd/crates/core_simd/webdriver.json @@ -0,0 +1,7 @@ +{ + "goog:chromeOptions": { + "args": [ + "--enable-features=WebAssemblySimd" + ] + } +} diff --git a/library/portable-simd/crates/test_helpers/Cargo.toml b/library/portable-simd/crates/test_helpers/Cargo.toml new file mode 100644 index 0000000000..a04b0961d7 --- /dev/null +++ b/library/portable-simd/crates/test_helpers/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "test_helpers" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies.proptest] +version = "0.10" +default-features = false +features = ["alloc"] diff --git a/library/portable-simd/crates/test_helpers/src/array.rs b/library/portable-simd/crates/test_helpers/src/array.rs new file mode 100644 index 0000000000..5ffc922697 --- /dev/null +++ b/library/portable-simd/crates/test_helpers/src/array.rs @@ -0,0 +1,97 @@ +//! Generic-length array strategy. + +// Adapted from proptest's array code +// Copyright 2017 Jason Lingle + +use core::{marker::PhantomData, mem::MaybeUninit}; +use proptest::{ + strategy::{NewTree, Strategy, ValueTree}, + test_runner::TestRunner, +}; + +#[must_use = "strategies do nothing unless used"] +#[derive(Clone, Copy, Debug)] +pub struct UniformArrayStrategy { + strategy: S, + _marker: PhantomData, +} + +impl UniformArrayStrategy { + pub const fn new(strategy: S) -> Self { + Self { + strategy, + _marker: PhantomData, + } + } +} + +pub struct ArrayValueTree { + tree: T, + shrinker: usize, + last_shrinker: Option, +} + +impl Strategy for UniformArrayStrategy +where + T: core::fmt::Debug, + S: Strategy, +{ + type Tree = ArrayValueTree<[S::Tree; LANES]>; + type Value = [T; LANES]; + + fn new_tree(&self, runner: &mut TestRunner) -> NewTree { + let tree: [S::Tree; LANES] = unsafe { + let mut tree: [MaybeUninit; LANES] = MaybeUninit::uninit().assume_init(); + for t in tree.iter_mut() { + *t = MaybeUninit::new(self.strategy.new_tree(runner)?) + } + core::mem::transmute_copy(&tree) + }; + Ok(ArrayValueTree { + tree, + shrinker: 0, + last_shrinker: None, + }) + } +} + +impl ValueTree for ArrayValueTree<[T; LANES]> { + type Value = [T::Value; LANES]; + + fn current(&self) -> Self::Value { + unsafe { + let mut value: [MaybeUninit; LANES] = MaybeUninit::uninit().assume_init(); + for (tree_elem, value_elem) in self.tree.iter().zip(value.iter_mut()) { + *value_elem = MaybeUninit::new(tree_elem.current()); + } + core::mem::transmute_copy(&value) + } + } + + fn simplify(&mut self) -> bool { + while self.shrinker < LANES { + if self.tree[self.shrinker].simplify() { + self.last_shrinker = Some(self.shrinker); + return true; + } else { + self.shrinker += 1; + } + } + + false + } + + fn complicate(&mut self) -> bool { + if let Some(shrinker) = self.last_shrinker { + self.shrinker = shrinker; + if self.tree[shrinker].complicate() { + true + } else { + self.last_shrinker = None; + false + } + } else { + false + } + } +} diff --git a/library/portable-simd/crates/test_helpers/src/biteq.rs b/library/portable-simd/crates/test_helpers/src/biteq.rs new file mode 100644 index 0000000000..00350e2241 --- /dev/null +++ b/library/portable-simd/crates/test_helpers/src/biteq.rs @@ -0,0 +1,106 @@ +//! Compare numeric types by exact bit value. + +pub trait BitEq { + fn biteq(&self, other: &Self) -> bool; + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result; +} + +impl BitEq for bool { + fn biteq(&self, other: &Self) -> bool { + self == other + } + + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(f, "{:?}", self) + } +} + +macro_rules! impl_integer_biteq { + { $($type:ty),* } => { + $( + impl BitEq for $type { + fn biteq(&self, other: &Self) -> bool { + self == other + } + + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(f, "{:?} ({:x})", self, self) + } + } + )* + }; +} + +impl_integer_biteq! { u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize } + +macro_rules! impl_float_biteq { + { $($type:ty),* } => { + $( + impl BitEq for $type { + fn biteq(&self, other: &Self) -> bool { + if self.is_nan() && other.is_nan() { + true // exact nan bits don't matter + } else { + self.to_bits() == other.to_bits() + } + } + + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(f, "{:?} ({:x})", self, self.to_bits()) + } + } + )* + }; +} + +impl_float_biteq! { f32, f64 } + +impl BitEq for [T; N] { + fn biteq(&self, other: &Self) -> bool { + self.iter() + .zip(other.iter()) + .fold(true, |value, (left, right)| value && left.biteq(right)) + } + + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + #[repr(transparent)] + struct Wrapper<'a, T: BitEq>(&'a T); + + impl core::fmt::Debug for Wrapper<'_, T> { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + self.0.fmt(f) + } + } + + f.debug_list() + .entries(self.iter().map(|x| Wrapper(x))) + .finish() + } +} + +#[doc(hidden)] +pub struct BitEqWrapper<'a, T>(pub &'a T); + +impl PartialEq for BitEqWrapper<'_, T> { + fn eq(&self, other: &Self) -> bool { + self.0.biteq(other.0) + } +} + +impl core::fmt::Debug for BitEqWrapper<'_, T> { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + self.0.fmt(f) + } +} + +#[macro_export] +macro_rules! prop_assert_biteq { + { $a:expr, $b:expr $(,)? } => { + { + use $crate::biteq::BitEqWrapper; + let a = $a; + let b = $b; + proptest::prop_assert_eq!(BitEqWrapper(&a), BitEqWrapper(&b)); + } + } +} diff --git a/library/portable-simd/crates/test_helpers/src/lib.rs b/library/portable-simd/crates/test_helpers/src/lib.rs new file mode 100644 index 0000000000..5c6478876f --- /dev/null +++ b/library/portable-simd/crates/test_helpers/src/lib.rs @@ -0,0 +1,437 @@ +pub mod array; + +#[cfg(target_arch = "wasm32")] +pub mod wasm; + +#[macro_use] +pub mod biteq; + +/// Specifies the default strategy for testing a type. +/// +/// This strategy should be what "makes sense" to test. +pub trait DefaultStrategy { + type Strategy: proptest::strategy::Strategy; + fn default_strategy() -> Self::Strategy; +} + +macro_rules! impl_num { + { $type:tt } => { + impl DefaultStrategy for $type { + type Strategy = proptest::num::$type::Any; + fn default_strategy() -> Self::Strategy { + proptest::num::$type::ANY + } + } + } +} + +impl_num! { i8 } +impl_num! { i16 } +impl_num! { i32 } +impl_num! { i64 } +impl_num! { isize } +impl_num! { u8 } +impl_num! { u16 } +impl_num! { u32 } +impl_num! { u64 } +impl_num! { usize } +impl_num! { f32 } +impl_num! { f64 } + +#[cfg(not(target_arch = "wasm32"))] +impl DefaultStrategy for u128 { + type Strategy = proptest::num::u128::Any; + fn default_strategy() -> Self::Strategy { + proptest::num::u128::ANY + } +} + +#[cfg(not(target_arch = "wasm32"))] +impl DefaultStrategy for i128 { + type Strategy = proptest::num::i128::Any; + fn default_strategy() -> Self::Strategy { + proptest::num::i128::ANY + } +} + +#[cfg(target_arch = "wasm32")] +impl DefaultStrategy for u128 { + type Strategy = crate::wasm::u128::Any; + fn default_strategy() -> Self::Strategy { + crate::wasm::u128::ANY + } +} + +#[cfg(target_arch = "wasm32")] +impl DefaultStrategy for i128 { + type Strategy = crate::wasm::i128::Any; + fn default_strategy() -> Self::Strategy { + crate::wasm::i128::ANY + } +} + +impl DefaultStrategy for [T; LANES] { + type Strategy = crate::array::UniformArrayStrategy; + fn default_strategy() -> Self::Strategy { + Self::Strategy::new(T::default_strategy()) + } +} + +/// Test a function that takes a single value. +pub fn test_1( + f: &dyn Fn(A) -> proptest::test_runner::TestCaseResult, +) { + let mut runner = proptest::test_runner::TestRunner::default(); + runner.run(&A::default_strategy(), f).unwrap(); +} + +/// Test a function that takes two values. +pub fn test_2( + f: &dyn Fn(A, B) -> proptest::test_runner::TestCaseResult, +) { + let mut runner = proptest::test_runner::TestRunner::default(); + runner + .run(&(A::default_strategy(), B::default_strategy()), |(a, b)| { + f(a, b) + }) + .unwrap(); +} + +/// Test a function that takes two values. +pub fn test_3< + A: core::fmt::Debug + DefaultStrategy, + B: core::fmt::Debug + DefaultStrategy, + C: core::fmt::Debug + DefaultStrategy, +>( + f: &dyn Fn(A, B, C) -> proptest::test_runner::TestCaseResult, +) { + let mut runner = proptest::test_runner::TestRunner::default(); + runner + .run( + &( + A::default_strategy(), + B::default_strategy(), + C::default_strategy(), + ), + |(a, b, c)| f(a, b, c), + ) + .unwrap(); +} + +/// Test a unary vector function against a unary scalar function, applied elementwise. +#[inline(never)] +pub fn test_unary_elementwise( + fv: &dyn Fn(Vector) -> VectorResult, + fs: &dyn Fn(Scalar) -> ScalarResult, + check: &dyn Fn([Scalar; LANES]) -> bool, +) where + Scalar: Copy + Default + core::fmt::Debug + DefaultStrategy, + ScalarResult: Copy + Default + biteq::BitEq + core::fmt::Debug + DefaultStrategy, + Vector: Into<[Scalar; LANES]> + From<[Scalar; LANES]> + Copy, + VectorResult: Into<[ScalarResult; LANES]> + From<[ScalarResult; LANES]> + Copy, +{ + test_1(&|x: [Scalar; LANES]| { + proptest::prop_assume!(check(x)); + let result_1: [ScalarResult; LANES] = fv(x.into()).into(); + let result_2: [ScalarResult; LANES] = { + let mut result = [ScalarResult::default(); LANES]; + for (i, o) in x.iter().zip(result.iter_mut()) { + *o = fs(*i); + } + result + }; + crate::prop_assert_biteq!(result_1, result_2); + Ok(()) + }); +} + +/// Test a unary vector function against a unary scalar function, applied elementwise. +#[inline(never)] +pub fn test_unary_mask_elementwise( + fv: &dyn Fn(Vector) -> Mask, + fs: &dyn Fn(Scalar) -> bool, + check: &dyn Fn([Scalar; LANES]) -> bool, +) where + Scalar: Copy + Default + core::fmt::Debug + DefaultStrategy, + Vector: Into<[Scalar; LANES]> + From<[Scalar; LANES]> + Copy, + Mask: Into<[bool; LANES]> + From<[bool; LANES]> + Copy, +{ + test_1(&|x: [Scalar; LANES]| { + proptest::prop_assume!(check(x)); + let result_1: [bool; LANES] = fv(x.into()).into(); + let result_2: [bool; LANES] = { + let mut result = [false; LANES]; + for (i, o) in x.iter().zip(result.iter_mut()) { + *o = fs(*i); + } + result + }; + crate::prop_assert_biteq!(result_1, result_2); + Ok(()) + }); +} + +/// Test a binary vector function against a binary scalar function, applied elementwise. +#[inline(never)] +pub fn test_binary_elementwise< + Scalar1, + Scalar2, + ScalarResult, + Vector1, + Vector2, + VectorResult, + const LANES: usize, +>( + fv: &dyn Fn(Vector1, Vector2) -> VectorResult, + fs: &dyn Fn(Scalar1, Scalar2) -> ScalarResult, + check: &dyn Fn([Scalar1; LANES], [Scalar2; LANES]) -> bool, +) where + Scalar1: Copy + Default + core::fmt::Debug + DefaultStrategy, + Scalar2: Copy + Default + core::fmt::Debug + DefaultStrategy, + ScalarResult: Copy + Default + biteq::BitEq + core::fmt::Debug + DefaultStrategy, + Vector1: Into<[Scalar1; LANES]> + From<[Scalar1; LANES]> + Copy, + Vector2: Into<[Scalar2; LANES]> + From<[Scalar2; LANES]> + Copy, + VectorResult: Into<[ScalarResult; LANES]> + From<[ScalarResult; LANES]> + Copy, +{ + test_2(&|x: [Scalar1; LANES], y: [Scalar2; LANES]| { + proptest::prop_assume!(check(x, y)); + let result_1: [ScalarResult; LANES] = fv(x.into(), y.into()).into(); + let result_2: [ScalarResult; LANES] = { + let mut result = [ScalarResult::default(); LANES]; + for ((i1, i2), o) in x.iter().zip(y.iter()).zip(result.iter_mut()) { + *o = fs(*i1, *i2); + } + result + }; + crate::prop_assert_biteq!(result_1, result_2); + Ok(()) + }); +} + +/// Test a binary vector-scalar function against a binary scalar function, applied elementwise. +#[inline(never)] +pub fn test_binary_scalar_rhs_elementwise< + Scalar1, + Scalar2, + ScalarResult, + Vector, + VectorResult, + const LANES: usize, +>( + fv: &dyn Fn(Vector, Scalar2) -> VectorResult, + fs: &dyn Fn(Scalar1, Scalar2) -> ScalarResult, + check: &dyn Fn([Scalar1; LANES], Scalar2) -> bool, +) where + Scalar1: Copy + Default + core::fmt::Debug + DefaultStrategy, + Scalar2: Copy + Default + core::fmt::Debug + DefaultStrategy, + ScalarResult: Copy + Default + biteq::BitEq + core::fmt::Debug + DefaultStrategy, + Vector: Into<[Scalar1; LANES]> + From<[Scalar1; LANES]> + Copy, + VectorResult: Into<[ScalarResult; LANES]> + From<[ScalarResult; LANES]> + Copy, +{ + test_2(&|x: [Scalar1; LANES], y: Scalar2| { + proptest::prop_assume!(check(x, y)); + let result_1: [ScalarResult; LANES] = fv(x.into(), y).into(); + let result_2: [ScalarResult; LANES] = { + let mut result = [ScalarResult::default(); LANES]; + for (i, o) in x.iter().zip(result.iter_mut()) { + *o = fs(*i, y); + } + result + }; + crate::prop_assert_biteq!(result_1, result_2); + Ok(()) + }); +} + +/// Test a binary vector-scalar function against a binary scalar function, applied elementwise. +#[inline(never)] +pub fn test_binary_scalar_lhs_elementwise< + Scalar1, + Scalar2, + ScalarResult, + Vector, + VectorResult, + const LANES: usize, +>( + fv: &dyn Fn(Scalar1, Vector) -> VectorResult, + fs: &dyn Fn(Scalar1, Scalar2) -> ScalarResult, + check: &dyn Fn(Scalar1, [Scalar2; LANES]) -> bool, +) where + Scalar1: Copy + Default + core::fmt::Debug + DefaultStrategy, + Scalar2: Copy + Default + core::fmt::Debug + DefaultStrategy, + ScalarResult: Copy + Default + biteq::BitEq + core::fmt::Debug + DefaultStrategy, + Vector: Into<[Scalar2; LANES]> + From<[Scalar2; LANES]> + Copy, + VectorResult: Into<[ScalarResult; LANES]> + From<[ScalarResult; LANES]> + Copy, +{ + test_2(&|x: Scalar1, y: [Scalar2; LANES]| { + proptest::prop_assume!(check(x, y)); + let result_1: [ScalarResult; LANES] = fv(x, y.into()).into(); + let result_2: [ScalarResult; LANES] = { + let mut result = [ScalarResult::default(); LANES]; + for (i, o) in y.iter().zip(result.iter_mut()) { + *o = fs(x, *i); + } + result + }; + crate::prop_assert_biteq!(result_1, result_2); + Ok(()) + }); +} + +/// Test a ternary vector function against a ternary scalar function, applied elementwise. +#[inline(never)] +pub fn test_ternary_elementwise< + Scalar1, + Scalar2, + Scalar3, + ScalarResult, + Vector1, + Vector2, + Vector3, + VectorResult, + const LANES: usize, +>( + fv: &dyn Fn(Vector1, Vector2, Vector3) -> VectorResult, + fs: &dyn Fn(Scalar1, Scalar2, Scalar3) -> ScalarResult, + check: &dyn Fn([Scalar1; LANES], [Scalar2; LANES], [Scalar3; LANES]) -> bool, +) where + Scalar1: Copy + Default + core::fmt::Debug + DefaultStrategy, + Scalar2: Copy + Default + core::fmt::Debug + DefaultStrategy, + Scalar3: Copy + Default + core::fmt::Debug + DefaultStrategy, + ScalarResult: Copy + Default + biteq::BitEq + core::fmt::Debug + DefaultStrategy, + Vector1: Into<[Scalar1; LANES]> + From<[Scalar1; LANES]> + Copy, + Vector2: Into<[Scalar2; LANES]> + From<[Scalar2; LANES]> + Copy, + Vector3: Into<[Scalar3; LANES]> + From<[Scalar3; LANES]> + Copy, + VectorResult: Into<[ScalarResult; LANES]> + From<[ScalarResult; LANES]> + Copy, +{ + test_3( + &|x: [Scalar1; LANES], y: [Scalar2; LANES], z: [Scalar3; LANES]| { + proptest::prop_assume!(check(x, y, z)); + let result_1: [ScalarResult; LANES] = fv(x.into(), y.into(), z.into()).into(); + let result_2: [ScalarResult; LANES] = { + let mut result = [ScalarResult::default(); LANES]; + for ((i1, (i2, i3)), o) in + x.iter().zip(y.iter().zip(z.iter())).zip(result.iter_mut()) + { + *o = fs(*i1, *i2, *i3); + } + result + }; + crate::prop_assert_biteq!(result_1, result_2); + Ok(()) + }, + ); +} + +/// Expand a const-generic test into separate tests for each possible lane count. +#[macro_export] +macro_rules! test_lanes { + { + $(fn $test:ident() $body:tt)* + } => { + $( + mod $test { + use super::*; + + fn implementation() + where + core_simd::LaneCount<$lanes>: core_simd::SupportedLaneCount, + $body + + #[cfg(target_arch = "wasm32")] + wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] + fn lanes_1() { + implementation::<1>(); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] + fn lanes_2() { + implementation::<2>(); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] + fn lanes_4() { + implementation::<4>(); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] + fn lanes_8() { + implementation::<8>(); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] + fn lanes_16() { + implementation::<16>(); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] + fn lanes_32() { + implementation::<32>(); + } + } + )* + } +} + +/// Expand a const-generic `#[should_panic]` test into separate tests for each possible lane count. +#[macro_export] +macro_rules! test_lanes_panic { + { + $(fn $test:ident() $body:tt)* + } => { + $( + mod $test { + use super::*; + + fn implementation() + where + core_simd::LaneCount<$lanes>: core_simd::SupportedLaneCount, + $body + + #[test] + #[should_panic] + fn lanes_1() { + implementation::<1>(); + } + + #[test] + #[should_panic] + fn lanes_2() { + implementation::<2>(); + } + + #[test] + #[should_panic] + fn lanes_4() { + implementation::<4>(); + } + + #[test] + #[should_panic] + fn lanes_8() { + implementation::<8>(); + } + + #[test] + #[should_panic] + fn lanes_16() { + implementation::<16>(); + } + + #[test] + #[should_panic] + fn lanes_32() { + implementation::<32>(); + } + } + )* + } +} diff --git a/library/portable-simd/crates/test_helpers/src/wasm.rs b/library/portable-simd/crates/test_helpers/src/wasm.rs new file mode 100644 index 0000000000..3f11d67cbf --- /dev/null +++ b/library/portable-simd/crates/test_helpers/src/wasm.rs @@ -0,0 +1,51 @@ +//! Strategies for `u128` and `i128`, since proptest doesn't provide them for the wasm target. + +macro_rules! impl_num { + { $name:ident } => { + pub(crate) mod $name { + type InnerStrategy = crate::array::UniformArrayStrategy; + use proptest::strategy::{Strategy, ValueTree, NewTree}; + + + #[must_use = "strategies do nothing unless used"] + #[derive(Clone, Copy, Debug)] + pub struct Any { + strategy: InnerStrategy, + } + + pub struct BinarySearch { + inner: ::Tree, + } + + impl ValueTree for BinarySearch { + type Value = $name; + + fn current(&self) -> $name { + unsafe { core::mem::transmute(self.inner.current()) } + } + + fn simplify(&mut self) -> bool { + self.inner.simplify() + } + + fn complicate(&mut self) -> bool { + self.inner.complicate() + } + } + + impl Strategy for Any { + type Tree = BinarySearch; + type Value = $name; + + fn new_tree(&self, runner: &mut proptest::test_runner::TestRunner) -> NewTree { + Ok(BinarySearch { inner: self.strategy.new_tree(runner)? }) + } + } + + pub const ANY: Any = Any { strategy: InnerStrategy::new(proptest::num::u64::ANY) }; + } + } +} + +impl_num! { u128 } +impl_num! { i128 } diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index bb05506def..2df287f7d9 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -62,6 +62,7 @@ macro_rules! with_api { fn clone($self: &$S::TokenStream) -> $S::TokenStream; fn new() -> $S::TokenStream; fn is_empty($self: &$S::TokenStream) -> bool; + fn expand_expr($self: &$S::TokenStream) -> Result<$S::TokenStream, ()>; fn from_str(src: &str) -> $S::TokenStream; fn to_string($self: &$S::TokenStream) -> String; fn from_token_tree( diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 3a06cd04ab..ef96d72a38 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -88,12 +88,6 @@ impl !Sync for TokenStream {} #[derive(Debug)] pub struct LexError; -impl LexError { - fn new() -> Self { - LexError - } -} - #[stable(feature = "proc_macro_lexerror_impls", since = "1.44.0")] impl fmt::Display for LexError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -109,6 +103,28 @@ impl !Send for LexError {} #[stable(feature = "proc_macro_lib", since = "1.15.0")] impl !Sync for LexError {} +/// Error returned from `TokenStream::expand_expr`. +#[unstable(feature = "proc_macro_expand", issue = "90765")] +#[non_exhaustive] +#[derive(Debug)] +pub struct ExpandError; + +#[unstable(feature = "proc_macro_expand", issue = "90765")] +impl fmt::Display for ExpandError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("macro expansion failed") + } +} + +#[unstable(feature = "proc_macro_expand", issue = "90765")] +impl error::Error for ExpandError {} + +#[unstable(feature = "proc_macro_expand", issue = "90765")] +impl !Send for ExpandError {} + +#[unstable(feature = "proc_macro_expand", issue = "90765")] +impl !Sync for ExpandError {} + impl TokenStream { /// Returns an empty `TokenStream` containing no token trees. #[stable(feature = "proc_macro_lib2", since = "1.29.0")] @@ -121,6 +137,24 @@ impl TokenStream { pub fn is_empty(&self) -> bool { self.0.is_empty() } + + /// Parses this `TokenStream` as an expression and attempts to expand any + /// macros within it. Returns the expanded `TokenStream`. + /// + /// Currently only expressions expanding to literals will succeed, although + /// this may be relaxed in the future. + /// + /// NOTE: In error conditions, `expand_expr` may leave macros unexpanded, + /// report an error, failing compilation, and/or return an `Err(..)`. The + /// specific behavior for any error condition, and what conditions are + /// considered errors, is unspecified and may change in the future. + #[unstable(feature = "proc_macro_expand", issue = "90765")] + pub fn expand_expr(&self) -> Result { + match bridge::client::TokenStream::expand_expr(&self.0) { + Ok(stream) => Ok(TokenStream(stream)), + Err(_) => Err(ExpandError), + } + } } /// Attempts to break the string into tokens and parse those tokens into a token stream. @@ -1074,7 +1108,11 @@ impl Literal { if !n.is_finite() { panic!("Invalid float literal {}", n); } - Literal(bridge::client::Literal::float(&n.to_string())) + let mut repr = n.to_string(); + if !repr.contains('.') { + repr.push_str(".0"); + } + Literal(bridge::client::Literal::float(&repr)) } /// Creates a new suffixed floating-point literal. @@ -1115,7 +1153,11 @@ impl Literal { if !n.is_finite() { panic!("Invalid float literal {}", n); } - Literal(bridge::client::Literal::float(&n.to_string())) + let mut repr = n.to_string(); + if !repr.contains('.') { + repr.push_str(".0"); + } + Literal(bridge::client::Literal::float(&repr)) } /// Creates a new suffixed floating-point literal. @@ -1203,7 +1245,7 @@ impl FromStr for Literal { fn from_str(src: &str) -> Result { match bridge::client::Literal::from_str(src) { Ok(literal) => Ok(Literal(literal)), - Err(()) => Err(LexError::new()), + Err(()) => Err(LexError), } } } diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 6bc445c6f2..4147f7ee52 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -15,8 +15,8 @@ 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.103", default-features = false, features = ['rustc-dep-of-std'] } -compiler_builtins = { version = "0.1.44" } +libc = { version = "0.2.106", default-features = false, features = ['rustc-dep-of-std'] } +compiler_builtins = { version = "0.1.53" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } hashbrown = { version = "0.11", default-features = false, features = ['rustc-dep-of-std'] } @@ -35,8 +35,8 @@ features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive'] [dev-dependencies] rand = "0.7" -[target.'cfg(any(all(target_arch = "wasm32", not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies] -dlmalloc = { version = "0.2.1", features = ['rustc-dep-of-std'] } +[target.'cfg(any(all(target_family = "wasm", not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies] +dlmalloc = { version = "0.2.3", features = ['rustc-dep-of-std'] } [target.x86_64-fortanix-unknown-sgx.dependencies] fortanix-sgx-abi = { version = "0.3.2", features = ['rustc-dep-of-std'] } diff --git a/library/std/build.rs b/library/std/build.rs index cc7184d57f..43168e7729 100644 --- a/library/std/build.rs +++ b/library/std/build.rs @@ -25,6 +25,7 @@ fn main() { || target.contains("haiku") || target.contains("vxworks") || target.contains("wasm32") + || target.contains("wasm64") || target.contains("asmjs") || target.contains("espidf") || target.contains("solid") diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs index 9ace3e1b60..0b86b4f30b 100644 --- a/library/std/src/backtrace.rs +++ b/library/std/src/backtrace.rs @@ -110,6 +110,7 @@ use crate::vec::Vec; /// previous point in time. In some instances the `Backtrace` type may /// internally be empty due to configuration. For more information see /// `Backtrace::capture`. +#[must_use] pub struct Backtrace { inner: Inner, } @@ -355,6 +356,7 @@ impl Backtrace { /// Returns the status of this backtrace, indicating whether this backtrace /// request was unsupported, disabled, or a stack trace was actually /// captured. + #[must_use] pub fn status(&self) -> BacktraceStatus { match self.inner { Inner::Unsupported => BacktraceStatus::Unsupported, @@ -366,6 +368,7 @@ impl Backtrace { impl<'a> Backtrace { /// Returns an iterator over the backtrace frames. + #[must_use] #[unstable(feature = "backtrace_frames", issue = "79676")] pub fn frames(&'a self) -> &'a [BacktraceFrame] { if let Inner::Captured(c) = &self.inner { &c.force().frames } else { &[] } diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 01019344f4..12246b5173 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -1707,6 +1707,7 @@ impl<'a, K, V, S> RawEntryMut<'a, K, V, S> { impl<'a, K, V, S> RawOccupiedEntryMut<'a, K, V, S> { /// Gets a reference to the key in the entry. #[inline] + #[must_use] #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn key(&self) -> &K { self.base.key() @@ -1714,6 +1715,7 @@ impl<'a, K, V, S> RawOccupiedEntryMut<'a, K, V, S> { /// Gets a mutable reference to the key in the entry. #[inline] + #[must_use] #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn key_mut(&mut self) -> &mut K { self.base.key_mut() @@ -1730,6 +1732,7 @@ impl<'a, K, V, S> RawOccupiedEntryMut<'a, K, V, S> { /// Gets a reference to the value in the entry. #[inline] + #[must_use] #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn get(&self) -> &V { self.base.get() @@ -1746,6 +1749,7 @@ impl<'a, K, V, S> RawOccupiedEntryMut<'a, K, V, S> { /// Gets a mutable reference to the value in the entry. #[inline] + #[must_use] #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn get_mut(&mut self) -> &mut V { self.base.get_mut() @@ -1753,6 +1757,7 @@ impl<'a, K, V, S> RawOccupiedEntryMut<'a, K, V, S> { /// Gets a reference to the key and value in the entry. #[inline] + #[must_use] #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn get_key_value(&mut self) -> (&K, &V) { self.base.get_key_value() diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index 5804701892..1fc1d39b18 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -38,8 +38,8 @@ use super::map::{map_try_reserve_error, RandomState}; /// determined by the [`Eq`] trait, changes while it is in the set. This is /// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or /// unsafe code. The behavior resulting from such a logic error is not -/// specified, but will not result in undefined behavior. This could include -/// panics, incorrect results, aborts, memory leaks, and non-termination. +/// specified (it could include panics, incorrect results, aborts, memory +/// leaks, or non-termination) but will not be undefined behavior. /// /// # Examples /// @@ -1320,6 +1320,8 @@ where /// /// let mut intersection = a.intersection(&b); /// ``` +#[must_use = "this returns the intersection as an iterator, \ + without modifying either input set"] #[stable(feature = "rust1", since = "1.0.0")] pub struct Intersection<'a, T: 'a, S: 'a> { // iterator of the first set @@ -1345,6 +1347,8 @@ pub struct Intersection<'a, T: 'a, S: 'a> { /// /// let mut difference = a.difference(&b); /// ``` +#[must_use = "this returns the difference as an iterator, \ + without modifying either input set"] #[stable(feature = "rust1", since = "1.0.0")] pub struct Difference<'a, T: 'a, S: 'a> { // iterator of the first set @@ -1370,6 +1374,8 @@ pub struct Difference<'a, T: 'a, S: 'a> { /// /// let mut intersection = a.symmetric_difference(&b); /// ``` +#[must_use = "this returns the difference as an iterator, \ + without modifying either input set"] #[stable(feature = "rust1", since = "1.0.0")] pub struct SymmetricDifference<'a, T: 'a, S: 'a> { iter: Chain, Difference<'a, T, S>>, @@ -1392,6 +1398,8 @@ pub struct SymmetricDifference<'a, T: 'a, S: 'a> { /// /// let mut union_iter = a.union(&b); /// ``` +#[must_use = "this returns the union as an iterator, \ + without modifying either input set"] #[stable(feature = "rust1", since = "1.0.0")] pub struct Union<'a, T: 'a, S: 'a> { iter: Chain, Difference<'a, T, S>>, diff --git a/library/std/src/collections/mod.rs b/library/std/src/collections/mod.rs index a19c343198..8b004525b4 100644 --- a/library/std/src/collections/mod.rs +++ b/library/std/src/collections/mod.rs @@ -268,7 +268,7 @@ //! not. Normally, this would require a `find` followed by an `insert`, //! effectively duplicating the search effort on each insertion. //! -//! When a user calls `map.entry(&key)`, the map will search for the key and +//! When a user calls `map.entry(key)`, the map will search for the key and //! then yield a variant of the `Entry` enum. //! //! If a `Vacant(entry)` is yielded, then the key *was not* found. In this case diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 40b46878cd..c6af708f6c 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -113,6 +113,7 @@ pub struct VarsOs { /// ``` /// /// [`env::vars_os()`]: vars_os +#[must_use] #[stable(feature = "env", since = "1.0.0")] pub fn vars() -> Vars { Vars { inner: vars_os() } @@ -140,6 +141,7 @@ pub fn vars() -> Vars { /// println!("{:?}: {:?}", key, value); /// } /// ``` +#[must_use] #[stable(feature = "env", since = "1.0.0")] pub fn vars_os() -> VarsOs { VarsOs { inner: os_imp::env() } @@ -244,6 +246,7 @@ fn _var(key: &OsStr) -> Result { /// None => println!("{} is not defined in the environment.", key) /// } /// ``` +#[must_use] #[stable(feature = "env", since = "1.0.0")] pub fn var_os>(key: K) -> Option { _var_os(key.as_ref()) @@ -384,6 +387,7 @@ fn _remove_var(key: &OsStr) { /// documentation for more. /// /// [`env::split_paths()`]: split_paths +#[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "env", since = "1.0.0")] pub struct SplitPaths<'a> { inner: os_imp::SplitPaths<'a>, @@ -564,6 +568,7 @@ impl Error for JoinPathsError { reason = "This function's behavior is unexpected and probably not what you want. \ Consider using a crate from crates.io instead." )] +#[must_use] #[stable(feature = "env", since = "1.0.0")] pub fn home_dir() -> Option { os_imp::home_dir() @@ -603,6 +608,7 @@ pub fn home_dir() -> Option { /// println!("Temporary directory: {}", dir.display()); /// } /// ``` +#[must_use] #[stable(feature = "env", since = "1.0.0")] pub fn temp_dir() -> PathBuf { os_imp::temp_dir() @@ -690,6 +696,7 @@ pub fn current_exe() -> io::Result { /// should not be relied upon for security purposes. /// /// [`env::args()`]: args +#[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "env", since = "1.0.0")] pub struct Args { inner: ArgsOs, @@ -706,6 +713,7 @@ pub struct Args { /// should not be relied upon for security purposes. /// /// [`env::args_os()`]: args_os +#[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "env", since = "1.0.0")] pub struct ArgsOs { inner: sys::args::Args, diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index 0b392897f9..d23f5244d8 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -878,40 +878,4 @@ impl f32 { pub fn atanh(self) -> f32 { 0.5 * ((2.0 * self) / (1.0 - self)).ln_1p() } - - /// Linear interpolation between `start` and `end`. - /// - /// This enables linear interpolation between `start` and `end`, where start is represented by - /// `self == 0.0` and `end` is represented by `self == 1.0`. This is the basis of all - /// "transition", "easing", or "step" functions; if you change `self` from 0.0 to 1.0 - /// at a given rate, the result will change from `start` to `end` at a similar rate. - /// - /// Values below 0.0 or above 1.0 are allowed, allowing you to extrapolate values outside the - /// range from `start` to `end`. This also is useful for transition functions which might - /// move slightly past the end or start for a desired effect. Mathematically, the values - /// returned are equivalent to `start + self * (end - start)`, although we make a few specific - /// guarantees that are useful specifically to linear interpolation. - /// - /// These guarantees are: - /// - /// * If `start` and `end` are [finite], the value at 0.0 is always `start` and the - /// value at 1.0 is always `end`. (exactness) - /// * If `start` and `end` are [finite], the values will always move in the direction from - /// `start` to `end` (monotonicity) - /// * If `self` is [finite] and `start == end`, the value at any point will always be - /// `start == end`. (consistency) - /// - /// [finite]: #method.is_finite - #[must_use = "method returns a new number and does not mutate the original value"] - #[unstable(feature = "float_interpolation", issue = "86269")] - pub fn lerp(self, start: f32, end: f32) -> f32 { - // consistent - if start == end { - start - - // exact/monotonic - } else { - self.mul_add(end, (-self).mul_add(start, start)) - } - } } diff --git a/library/std/src/f32/tests.rs b/library/std/src/f32/tests.rs index fe66a73afd..69fa203ff4 100644 --- a/library/std/src/f32/tests.rs +++ b/library/std/src/f32/tests.rs @@ -19,6 +19,18 @@ fn test_max_nan() { assert_eq!(2.0f32.max(f32::NAN), 2.0); } +#[test] +fn test_minimum() { + assert!(f32::NAN.minimum(2.0).is_nan()); + assert!(2.0f32.minimum(f32::NAN).is_nan()); +} + +#[test] +fn test_maximum() { + assert!(f32::NAN.maximum(2.0).is_nan()); + assert!(2.0f32.maximum(f32::NAN).is_nan()); +} + #[test] fn test_nan() { let nan: f32 = f32::NAN; @@ -757,66 +769,3 @@ fn test_total_cmp() { assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f32::INFINITY)); assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan())); } - -#[test] -fn test_lerp_exact() { - // simple values - assert_eq!(f32::lerp(0.0, 2.0, 4.0), 2.0); - assert_eq!(f32::lerp(1.0, 2.0, 4.0), 4.0); - - // boundary values - assert_eq!(f32::lerp(0.0, f32::MIN, f32::MAX), f32::MIN); - assert_eq!(f32::lerp(1.0, f32::MIN, f32::MAX), f32::MAX); -} - -#[test] -fn test_lerp_consistent() { - assert_eq!(f32::lerp(f32::MAX, f32::MIN, f32::MIN), f32::MIN); - assert_eq!(f32::lerp(f32::MIN, f32::MAX, f32::MAX), f32::MAX); - - // as long as t is finite, a/b can be infinite - assert_eq!(f32::lerp(f32::MAX, f32::NEG_INFINITY, f32::NEG_INFINITY), f32::NEG_INFINITY); - assert_eq!(f32::lerp(f32::MIN, f32::INFINITY, f32::INFINITY), f32::INFINITY); -} - -#[test] -fn test_lerp_nan_infinite() { - // non-finite t is not NaN if a/b different - assert!(!f32::lerp(f32::INFINITY, f32::MIN, f32::MAX).is_nan()); - assert!(!f32::lerp(f32::NEG_INFINITY, f32::MIN, f32::MAX).is_nan()); -} - -#[test] -fn test_lerp_values() { - // just a few basic values - assert_eq!(f32::lerp(0.25, 1.0, 2.0), 1.25); - assert_eq!(f32::lerp(0.50, 1.0, 2.0), 1.50); - assert_eq!(f32::lerp(0.75, 1.0, 2.0), 1.75); -} - -#[test] -fn test_lerp_monotonic() { - // near 0 - let below_zero = f32::lerp(-f32::EPSILON, f32::MIN, f32::MAX); - let zero = f32::lerp(0.0, f32::MIN, f32::MAX); - let above_zero = f32::lerp(f32::EPSILON, f32::MIN, f32::MAX); - assert!(below_zero <= zero); - assert!(zero <= above_zero); - assert!(below_zero <= above_zero); - - // near 0.5 - let below_half = f32::lerp(0.5 - f32::EPSILON, f32::MIN, f32::MAX); - let half = f32::lerp(0.5, f32::MIN, f32::MAX); - let above_half = f32::lerp(0.5 + f32::EPSILON, f32::MIN, f32::MAX); - assert!(below_half <= half); - assert!(half <= above_half); - assert!(below_half <= above_half); - - // near 1 - let below_one = f32::lerp(1.0 - f32::EPSILON, f32::MIN, f32::MAX); - let one = f32::lerp(1.0, f32::MIN, f32::MAX); - let above_one = f32::lerp(1.0 + f32::EPSILON, f32::MIN, f32::MAX); - assert!(below_one <= one); - assert!(one <= above_one); - assert!(below_one <= above_one); -} diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index 602cceb5d1..55e17b4719 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -881,42 +881,6 @@ impl f64 { 0.5 * ((2.0 * self) / (1.0 - self)).ln_1p() } - /// Linear interpolation between `start` and `end`. - /// - /// This enables linear interpolation between `start` and `end`, where start is represented by - /// `self == 0.0` and `end` is represented by `self == 1.0`. This is the basis of all - /// "transition", "easing", or "step" functions; if you change `self` from 0.0 to 1.0 - /// at a given rate, the result will change from `start` to `end` at a similar rate. - /// - /// Values below 0.0 or above 1.0 are allowed, allowing you to extrapolate values outside the - /// range from `start` to `end`. This also is useful for transition functions which might - /// move slightly past the end or start for a desired effect. Mathematically, the values - /// returned are equivalent to `start + self * (end - start)`, although we make a few specific - /// guarantees that are useful specifically to linear interpolation. - /// - /// These guarantees are: - /// - /// * If `start` and `end` are [finite], the value at 0.0 is always `start` and the - /// value at 1.0 is always `end`. (exactness) - /// * If `start` and `end` are [finite], the values will always move in the direction from - /// `start` to `end` (monotonicity) - /// * If `self` is [finite] and `start == end`, the value at any point will always be - /// `start == end`. (consistency) - /// - /// [finite]: #method.is_finite - #[must_use = "method returns a new number and does not mutate the original value"] - #[unstable(feature = "float_interpolation", issue = "86269")] - pub fn lerp(self, start: f64, end: f64) -> f64 { - // consistent - if start == end { - start - - // exact/monotonic - } else { - self.mul_add(end, (-self).mul_add(start, start)) - } - } - // Solaris/Illumos requires a wrapper around log, log2, and log10 functions // because of their non-standard behavior (e.g., log(-n) returns -Inf instead // of expected NaN). diff --git a/library/std/src/f64/tests.rs b/library/std/src/f64/tests.rs index 04cb010926..5c163cfe90 100644 --- a/library/std/src/f64/tests.rs +++ b/library/std/src/f64/tests.rs @@ -753,58 +753,3 @@ fn test_total_cmp() { assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f64::INFINITY)); assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan())); } - -#[test] -fn test_lerp_exact() { - // simple values - assert_eq!(f64::lerp(0.0, 2.0, 4.0), 2.0); - assert_eq!(f64::lerp(1.0, 2.0, 4.0), 4.0); - - // boundary values - assert_eq!(f64::lerp(0.0, f64::MIN, f64::MAX), f64::MIN); - assert_eq!(f64::lerp(1.0, f64::MIN, f64::MAX), f64::MAX); -} - -#[test] -fn test_lerp_consistent() { - assert_eq!(f64::lerp(f64::MAX, f64::MIN, f64::MIN), f64::MIN); - assert_eq!(f64::lerp(f64::MIN, f64::MAX, f64::MAX), f64::MAX); - - // as long as t is finite, a/b can be infinite - assert_eq!(f64::lerp(f64::MAX, f64::NEG_INFINITY, f64::NEG_INFINITY), f64::NEG_INFINITY); - assert_eq!(f64::lerp(f64::MIN, f64::INFINITY, f64::INFINITY), f64::INFINITY); -} - -#[test] -fn test_lerp_nan_infinite() { - // non-finite t is not NaN if a/b different - assert!(!f64::lerp(f64::INFINITY, f64::MIN, f64::MAX).is_nan()); - assert!(!f64::lerp(f64::NEG_INFINITY, f64::MIN, f64::MAX).is_nan()); -} - -#[test] -fn test_lerp_values() { - // just a few basic values - assert_eq!(f64::lerp(0.25, 1.0, 2.0), 1.25); - assert_eq!(f64::lerp(0.50, 1.0, 2.0), 1.50); - assert_eq!(f64::lerp(0.75, 1.0, 2.0), 1.75); -} - -#[test] -fn test_lerp_monotonic() { - // near 0 - let below_zero = f64::lerp(-f64::EPSILON, f64::MIN, f64::MAX); - let zero = f64::lerp(0.0, f64::MIN, f64::MAX); - let above_zero = f64::lerp(f64::EPSILON, f64::MIN, f64::MAX); - assert!(below_zero <= zero); - assert!(zero <= above_zero); - assert!(below_zero <= above_zero); - - // near 1 - let below_one = f64::lerp(1.0 - f64::EPSILON, f64::MIN, f64::MAX); - let one = f64::lerp(1.0, f64::MIN, f64::MAX); - let above_one = f64::lerp(1.0 + f64::EPSILON, f64::MIN, f64::MAX); - assert!(below_one <= one); - assert!(one <= above_one); - assert!(below_one <= above_one); -} diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs index 6827d3a8d2..465bbae863 100644 --- a/library/std/src/ffi/c_str.rs +++ b/library/std/src/ffi/c_str.rs @@ -251,13 +251,12 @@ pub struct FromBytesWithNulError { /// # Examples /// /// ``` -/// #![feature(cstring_from_vec_with_nul)] /// use std::ffi::{CString, FromVecWithNulError}; /// /// let _: FromVecWithNulError = CString::from_vec_with_nul(b"f\0oo".to_vec()).unwrap_err(); /// ``` #[derive(Clone, PartialEq, Eq, Debug)] -#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")] +#[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] pub struct FromVecWithNulError { error_kind: FromBytesWithNulErrorKind, bytes: Vec, @@ -278,7 +277,7 @@ impl FromBytesWithNulError { } } -#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")] +#[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] impl FromVecWithNulError { /// Returns a slice of [`u8`]s bytes that were attempted to convert to a [`CString`]. /// @@ -287,7 +286,6 @@ impl FromVecWithNulError { /// Basic usage: /// /// ``` - /// #![feature(cstring_from_vec_with_nul)] /// use std::ffi::CString; /// /// // Some invalid bytes in a vector @@ -298,6 +296,7 @@ impl FromVecWithNulError { /// assert_eq!(&bytes[..], value.unwrap_err().as_bytes()); /// ``` #[must_use] + #[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] pub fn as_bytes(&self) -> &[u8] { &self.bytes[..] } @@ -313,7 +312,6 @@ impl FromVecWithNulError { /// Basic usage: /// /// ``` - /// #![feature(cstring_from_vec_with_nul)] /// use std::ffi::CString; /// /// // Some invalid bytes in a vector @@ -324,6 +322,7 @@ impl FromVecWithNulError { /// assert_eq!(bytes, value.unwrap_err().into_bytes()); /// ``` #[must_use = "`self` will be dropped if the result is not used"] + #[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] pub fn into_bytes(self) -> Vec { self.bytes } @@ -704,7 +703,6 @@ impl CString { /// # Example /// /// ``` - /// #![feature(cstring_from_vec_with_nul)] /// use std::ffi::CString; /// assert_eq!( /// unsafe { CString::from_vec_with_nul_unchecked(b"abc\0".to_vec()) }, @@ -712,7 +710,7 @@ impl CString { /// ); /// ``` #[must_use] - #[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")] + #[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] pub unsafe fn from_vec_with_nul_unchecked(v: Vec) -> Self { Self { inner: v.into_boxed_slice() } } @@ -733,7 +731,6 @@ impl CString { /// when called without the ending nul byte. /// /// ``` - /// #![feature(cstring_from_vec_with_nul)] /// use std::ffi::CString; /// assert_eq!( /// CString::from_vec_with_nul(b"abc\0".to_vec()) @@ -745,14 +742,13 @@ impl CString { /// An incorrectly formatted [`Vec`] will produce an error. /// /// ``` - /// #![feature(cstring_from_vec_with_nul)] /// use std::ffi::{CString, FromVecWithNulError}; /// // Interior nul byte /// let _: FromVecWithNulError = CString::from_vec_with_nul(b"a\0bc".to_vec()).unwrap_err(); /// // No nul byte /// let _: FromVecWithNulError = CString::from_vec_with_nul(b"abc".to_vec()).unwrap_err(); /// ``` - #[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")] + #[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] pub fn from_vec_with_nul(v: Vec) -> Result { let nul_pos = memchr::memchr(0, &v); match nul_pos { @@ -1013,6 +1009,7 @@ impl NulError { /// let nul_error = CString::new("foo bar\0").unwrap_err(); /// assert_eq!(nul_error.nul_position(), 7); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn nul_position(&self) -> usize { self.0 @@ -1084,10 +1081,10 @@ impl fmt::Display for FromBytesWithNulError { } } -#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")] +#[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] impl Error for FromVecWithNulError {} -#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")] +#[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] impl fmt::Display for FromVecWithNulError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.error_kind { @@ -1111,6 +1108,7 @@ impl IntoStringError { } /// Access the underlying UTF-8 error that was the cause of this error. + #[must_use] #[stable(feature = "cstring_into", since = "1.7.0")] pub fn utf8_error(&self) -> Utf8Error { self.error @@ -1175,6 +1173,7 @@ impl CStr { /// } /// # } /// ``` + #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr { @@ -1260,7 +1259,7 @@ impl CStr { #[inline] #[must_use] #[stable(feature = "cstr_from_bytes", since = "1.10.0")] - #[rustc_const_unstable(feature = "const_cstr_unchecked", issue = "none")] + #[rustc_const_unstable(feature = "const_cstr_unchecked", issue = "90343")] pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr { // SAFETY: Casting to CStr is safe because its internal representation // is a [u8] too (safe only inside std). @@ -1459,6 +1458,7 @@ impl CStr { /// let boxed = c_string.into_boxed_c_str(); /// assert_eq!(boxed.into_c_string(), CString::new("foo").expect("CString::new failed")); /// ``` + #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "into_boxed_c_str", since = "1.20.0")] pub fn into_c_string(self: Box) -> CString { let raw = Box::into_raw(self) as *mut [u8]; diff --git a/library/std/src/ffi/mod.rs b/library/std/src/ffi/mod.rs index 82a76aa73c..7f3bb83675 100644 --- a/library/std/src/ffi/mod.rs +++ b/library/std/src/ffi/mod.rs @@ -145,7 +145,7 @@ #[stable(feature = "cstr_from_bytes", since = "1.10.0")] pub use self::c_str::FromBytesWithNulError; -#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")] +#[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] pub use self::c_str::FromVecWithNulError; #[stable(feature = "rust1", since = "1.0.0")] pub use self::c_str::{CStr, CString, IntoStringError, NulError}; diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index 46c9aa5e62..0f9912fa64 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -239,6 +239,7 @@ impl OsString { /// assert!(os_string.capacity() >= 10); /// ``` #[stable(feature = "osstring_simple_functions", since = "1.9.0")] + #[must_use] #[inline] pub fn capacity(&self) -> usize { self.inner.capacity() @@ -669,6 +670,7 @@ impl OsStr { /// assert!(!os_str.is_empty()); /// ``` #[stable(feature = "osstring_simple_functions", since = "1.9.0")] + #[must_use] #[inline] pub fn is_empty(&self) -> bool { self.inner.inner.is_empty() @@ -700,6 +702,7 @@ impl OsStr { /// assert_eq!(os_str.len(), 3); /// ``` #[stable(feature = "osstring_simple_functions", since = "1.9.0")] + #[must_use] #[inline] pub fn len(&self) -> usize { self.inner.inner.len() @@ -707,6 +710,7 @@ impl OsStr { /// Converts a [Box]<[OsStr]> into an [`OsString`] without copying or allocating. #[stable(feature = "into_boxed_os_str", since = "1.20.0")] + #[must_use = "`self` will be dropped if the result is not used"] pub fn into_os_string(self: Box) -> OsString { let boxed = unsafe { Box::from_raw(Box::into_raw(self) as *mut Slice) }; OsString { inner: Buf::from_box(boxed) } @@ -829,6 +833,7 @@ impl OsStr { /// assert!(!non_ascii.is_ascii()); /// ``` #[stable(feature = "osstring_ascii", since = "1.53.0")] + #[must_use] #[inline] pub fn is_ascii(&self) -> bool { self.inner.is_ascii() diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 9f45e89aa7..f7f7a9ba4e 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -358,7 +358,7 @@ impl File { /// /// It is equivalent to `OpenOptions::new()` but allows you to write more /// readable code. Instead of `OpenOptions::new().read(true).open("foo.txt")` - /// you can write `File::with_options().read(true).open("foo.txt")`. This + /// you can write `File::options().read(true).open("foo.txt")`. This /// also avoids the need to import `OpenOptions`. /// /// See the [`OpenOptions::new`] function for more details. @@ -366,16 +366,16 @@ impl File { /// # Examples /// /// ```no_run - /// #![feature(with_options)] /// use std::fs::File; /// /// fn main() -> std::io::Result<()> { - /// let mut f = File::with_options().read(true).open("foo.txt")?; + /// let mut f = File::options().read(true).open("foo.txt")?; /// Ok(()) /// } /// ``` - #[unstable(feature = "with_options", issue = "65439")] - pub fn with_options() -> OpenOptions { + #[must_use] + #[stable(feature = "with_options", since = "1.58.0")] + pub fn options() -> OpenOptions { OpenOptions::new() } @@ -983,6 +983,7 @@ impl Metadata { /// Ok(()) /// } /// ``` + #[must_use] #[stable(feature = "file_type", since = "1.1.0")] pub fn file_type(&self) -> FileType { FileType(self.0.file_type()) @@ -1046,7 +1047,6 @@ impl Metadata { /// #[cfg_attr(unix, doc = "```no_run")] #[cfg_attr(not(unix), doc = "```ignore")] - /// #![feature(is_symlink)] /// use std::fs; /// use std::path::Path; /// use std::os::unix::fs::symlink; @@ -1062,7 +1062,7 @@ impl Metadata { /// } /// ``` #[must_use] - #[unstable(feature = "is_symlink", issue = "85748")] + #[stable(feature = "is_symlink", since = "1.57.0")] pub fn is_symlink(&self) -> bool { self.file_type().is_symlink() } @@ -1081,6 +1081,7 @@ impl Metadata { /// Ok(()) /// } /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn len(&self) -> u64 { self.0.size() @@ -1100,6 +1101,7 @@ impl Metadata { /// Ok(()) /// } /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn permissions(&self) -> Permissions { Permissions(self.0.perm()) @@ -1247,6 +1249,7 @@ impl Permissions { /// Ok(()) /// } /// ``` + #[must_use = "call `set_readonly` to modify the readonly flag"] #[stable(feature = "rust1", since = "1.0.0")] pub fn readonly(&self) -> bool { self.0.readonly() @@ -1441,6 +1444,7 @@ impl DirEntry { /// ``` /// /// The exact text, of course, depends on what files you have in `.`. + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn path(&self) -> PathBuf { self.0.path() @@ -1536,6 +1540,7 @@ impl DirEntry { /// } /// } /// ``` + #[must_use] #[stable(feature = "dir_entry_ext", since = "1.1.0")] pub fn file_name(&self) -> OsString { self.0.file_name() @@ -2040,13 +2045,17 @@ pub fn remove_dir>(path: P) -> io::Result<()> { /// /// # Platform-specific behavior /// -/// This function currently corresponds to `opendir`, `lstat`, `rm` and `rmdir` functions on Unix -/// and the `FindFirstFile`, `GetFileAttributesEx`, `DeleteFile`, and `RemoveDirectory` functions -/// on Windows. -/// Note that, this [may change in the future][changes]. +/// This function currently corresponds to `openat`, `fdopendir`, `unlinkat` and `lstat` functions +/// on Unix (except for macOS before version 10.10 and REDOX) and the `CreateFileW`, +/// `GetFileInformationByHandleEx`, `SetFileInformationByHandle`, and `NtOpenFile` functions on +/// Windows. Note that, this [may change in the future][changes]. /// /// [changes]: io#platform-specific-behavior /// +/// On macOS before version 10.10 and REDOX this function is not protected against time-of-check to +/// time-of-use (TOCTOU) race conditions, and should not be used in security-sensitive code on +/// those platforms. All other platforms are protected. +/// /// # Errors /// /// See [`fs::remove_file`] and [`fs::remove_dir`]. diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 13dbae3b7b..4d1959258b 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -4,8 +4,10 @@ use crate::fs::{self, File, OpenOptions}; use crate::io::{ErrorKind, SeekFrom}; use crate::path::Path; use crate::str; +use crate::sync::Arc; use crate::sys_common::io::test::{tmpdir, TempDir}; use crate::thread; +use crate::time::{Duration, Instant}; use rand::{rngs::StdRng, RngCore, SeedableRng}; @@ -602,6 +604,21 @@ fn recursive_rmdir_of_symlink() { assert!(canary.exists()); } +#[test] +fn recursive_rmdir_of_file_fails() { + // test we do not delete a directly specified file. + let tmpdir = tmpdir(); + let canary = tmpdir.join("do_not_delete"); + check!(check!(File::create(&canary)).write(b"foo")); + let result = fs::remove_dir_all(&canary); + #[cfg(unix)] + error!(result, "Not a directory"); + #[cfg(windows)] + error!(result, 267); // ERROR_DIRECTORY - The directory name is invalid. + assert!(result.is_err()); + assert!(canary.exists()); +} + #[test] // only Windows makes a distinction between file and directory symlinks. #[cfg(windows)] @@ -621,6 +638,59 @@ fn recursive_rmdir_of_file_symlink() { } } +#[test] +#[ignore] // takes too much time +fn recursive_rmdir_toctou() { + // Test for time-of-check to time-of-use issues. + // + // Scenario: + // The attacker wants to get directory contents deleted, to which he does not have access. + // He has a way to get a privileged Rust binary call `std::fs::remove_dir_all()` on a + // directory he controls, e.g. in his home directory. + // + // The POC sets up the `attack_dest/attack_file` which the attacker wants to have deleted. + // The attacker repeatedly creates a directory and replaces it with a symlink from + // `victim_del` to `attack_dest` while the victim code calls `std::fs::remove_dir_all()` + // on `victim_del`. After a few seconds the attack has succeeded and + // `attack_dest/attack_file` is deleted. + let tmpdir = tmpdir(); + let victim_del_path = tmpdir.join("victim_del"); + let victim_del_path_clone = victim_del_path.clone(); + + // setup dest + let attack_dest_dir = tmpdir.join("attack_dest"); + let attack_dest_dir = attack_dest_dir.as_path(); + fs::create_dir(attack_dest_dir).unwrap(); + let attack_dest_file = tmpdir.join("attack_dest/attack_file"); + File::create(&attack_dest_file).unwrap(); + + let drop_canary_arc = Arc::new(()); + let drop_canary_weak = Arc::downgrade(&drop_canary_arc); + + eprintln!("x: {:?}", &victim_del_path); + + // victim just continuously removes `victim_del` + thread::spawn(move || { + while drop_canary_weak.upgrade().is_some() { + let _ = fs::remove_dir_all(&victim_del_path_clone); + } + }); + + // attacker (could of course be in a separate process) + let start_time = Instant::now(); + while Instant::now().duration_since(start_time) < Duration::from_secs(1000) { + if !attack_dest_file.exists() { + panic!( + "Victim deleted symlinked file outside of victim_del. Attack succeeded in {:?}.", + Instant::now().duration_since(start_time) + ); + } + let _ = fs::create_dir(&victim_del_path); + let _ = fs::remove_dir(&victim_del_path); + let _ = symlink_dir(attack_dest_dir, &victim_del_path); + } +} + #[test] fn unicode_path_is_dir() { assert!(Path::new(".").is_dir()); @@ -833,20 +903,11 @@ fn symlink_noexist() { fn read_link() { if cfg!(windows) { // directory symlink - assert_eq!( - check!(fs::read_link(r"C:\Users\All Users")).to_str().unwrap(), - r"C:\ProgramData" - ); + assert_eq!(check!(fs::read_link(r"C:\Users\All Users")), Path::new(r"C:\ProgramData")); // junction - assert_eq!( - check!(fs::read_link(r"C:\Users\Default User")).to_str().unwrap(), - r"C:\Users\Default" - ); + assert_eq!(check!(fs::read_link(r"C:\Users\Default User")), Path::new(r"C:\Users\Default")); // junction with special permissions - assert_eq!( - check!(fs::read_link(r"C:\Documents and Settings\")).to_str().unwrap(), - r"C:\Users" - ); + assert_eq!(check!(fs::read_link(r"C:\Documents and Settings\")), Path::new(r"C:\Users")); } let tmpdir = tmpdir(); let link = tmpdir.join("link"); @@ -1411,3 +1472,36 @@ fn symlink_hard_link() { // "hard_link" should still appear as a symlink. assert!(check!(fs::symlink_metadata(tmpdir.join("hard_link"))).file_type().is_symlink()); } + +/// Ensure `fs::create_dir` works on Windows with longer paths. +#[test] +#[cfg(windows)] +fn create_dir_long_paths() { + use crate::{ffi::OsStr, iter, os::windows::ffi::OsStrExt}; + const PATH_LEN: usize = 247; + + let tmpdir = tmpdir(); + let mut path = tmpdir.path().to_path_buf(); + path.push("a"); + let mut path = path.into_os_string(); + + let utf16_len = path.encode_wide().count(); + if utf16_len >= PATH_LEN { + // Skip the test in the unlikely event the local user has a long temp directory path. + // This should not affect CI. + return; + } + // Increase the length of the path. + path.extend(iter::repeat(OsStr::new("a")).take(PATH_LEN - utf16_len)); + + // This should succeed. + fs::create_dir(&path).unwrap(); + + // This will fail if the path isn't converted to verbatim. + path.push("a"); + fs::create_dir(&path).unwrap(); + + // #90940: Ensure an empty path returns the "Not Found" error. + let path = Path::new(""); + assert_eq!(path.canonicalize().unwrap_err().kind(), crate::io::ErrorKind::NotFound); +} diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 59a9cd781c..d93c6172cf 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -392,6 +392,9 @@ impl Error { /// originate from the OS itself. The `error` argument is an arbitrary /// payload which will be contained in this [`Error`]. /// + /// If no extra payload is required, use the `From` conversion from + /// `ErrorKind`. + /// /// # Examples /// /// ``` @@ -402,6 +405,9 @@ impl Error { /// /// // errors can also be created from other errors /// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error); + /// + /// // creating an error without payload + /// let eof_error = Error::from(ErrorKind::UnexpectedEof); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn new(kind: ErrorKind, error: E) -> Error @@ -442,6 +448,7 @@ impl Error { /// println!("last OS error: {:?}", Error::last_os_error()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] #[inline] pub fn last_os_error() -> Error { Error::from_raw_os_error(sys::os::errno() as i32) @@ -509,6 +516,7 @@ impl Error { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] #[inline] pub fn raw_os_error(&self) -> Option { match self.repr { @@ -547,6 +555,7 @@ impl Error { /// } /// ``` #[stable(feature = "io_error_inner", since = "1.3.0")] + #[must_use] #[inline] pub fn get_ref(&self) -> Option<&(dyn error::Error + Send + Sync + 'static)> { match self.repr { @@ -620,6 +629,7 @@ impl Error { /// } /// ``` #[stable(feature = "io_error_inner", since = "1.3.0")] + #[must_use] #[inline] pub fn get_mut(&mut self) -> Option<&mut (dyn error::Error + Send + Sync + 'static)> { match self.repr { @@ -688,6 +698,7 @@ impl Error { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] #[inline] pub fn kind(&self) -> ErrorKind { match self.repr { diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index abe29ba0f7..8cc9156641 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -299,9 +299,7 @@ mod util; const DEFAULT_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE; -pub(crate) fn cleanup() { - stdio::cleanup() -} +pub(crate) use stdio::cleanup; struct Guard<'a> { buf: &'a mut Vec, @@ -1310,6 +1308,7 @@ pub struct Initializer(bool); impl Initializer { /// Returns a new `Initializer` which will zero out buffers. #[unstable(feature = "read_initializer", issue = "42788")] + #[must_use] #[inline] pub fn zeroing() -> Initializer { Initializer(true) @@ -1324,6 +1323,7 @@ impl Initializer { /// the method accurately reflects the number of bytes that have been /// written to the head of the buffer. #[unstable(feature = "read_initializer", issue = "42788")] + #[must_use] #[inline] pub unsafe fn nop() -> Initializer { Initializer(false) @@ -1331,6 +1331,7 @@ impl Initializer { /// Indicates if a buffer should be initialized. #[unstable(feature = "read_initializer", issue = "42788")] + #[must_use] #[inline] pub fn should_initialize(&self) -> bool { self.0 diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 9389501e01..f7fc23c1e8 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -301,6 +301,7 @@ pub struct StdinLock<'a> { /// Ok(()) /// } /// ``` +#[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn stdin() -> Stdin { static INSTANCE: SyncOnceCell>> = SyncOnceCell::new(); @@ -487,6 +488,7 @@ impl Stdin { /// println!("got a chunk: {}", String::from_utf8_lossy(&split.unwrap())); /// } /// ``` + #[must_use = "`self` will be dropped if the result is not used"] #[unstable(feature = "stdin_forwarders", issue = "87096")] pub fn split(self, byte: u8) -> Split> { self.into_locked().split(byte) @@ -673,6 +675,7 @@ static STDOUT: SyncOnceCell>>> = Sy /// Ok(()) /// } /// ``` +#[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn stdout() -> Stdout { Stdout { @@ -953,6 +956,7 @@ pub struct StderrLock<'a> { /// Ok(()) /// } /// ``` +#[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn stderr() -> Stderr { // Note that unlike `stdout()` we don't use `at_exit` here to register a diff --git a/library/std/src/io/util.rs b/library/std/src/io/util.rs index 2f3520ae7a..9cd7c51484 100644 --- a/library/std/src/io/util.rs +++ b/library/std/src/io/util.rs @@ -32,6 +32,7 @@ pub struct Empty; /// io::empty().read_to_string(&mut buffer).unwrap(); /// assert!(buffer.is_empty()); /// ``` +#[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_io_structs", issue = "78812")] pub const fn empty() -> Empty { @@ -112,6 +113,7 @@ pub struct Repeat { /// io::repeat(0b101).read_exact(&mut buffer).unwrap(); /// assert_eq!(buffer, [0b101, 0b101, 0b101]); /// ``` +#[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_io_structs", issue = "78812")] pub const fn repeat(byte: u8) -> Repeat { @@ -192,6 +194,7 @@ pub struct Sink; /// let num_bytes = io::sink().write(&buffer).unwrap(); /// assert_eq!(num_bytes, 5); /// ``` +#[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_io_structs", issue = "78812")] pub const fn sink() -> Sink { diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs index 2e93807037..a370485102 100644 --- a/library/std/src/keyword_docs.rs +++ b/library/std/src/keyword_docs.rs @@ -182,7 +182,7 @@ mod break_keyword {} /// T` and `*mut T`. More about `const` as used in raw pointers can be read at the Rust docs for the [pointer primitive]. /// /// [pointer primitive]: pointer -/// [Rust Book]: ../book/ch03-01-variables-and-mutability.html#differences-between-variables-and-constants +/// [Rust Book]: ../book/ch03-01-variables-and-mutability.html#constants /// [Reference]: ../reference/items/constant-items.html /// [const-eval]: ../reference/const_eval.html mod const_keyword {} @@ -549,13 +549,10 @@ mod fn_keyword {} /// { /// let result = match IntoIterator::into_iter(iterator) { /// mut iter => loop { -/// let next; /// match iter.next() { -/// Some(val) => next = val, /// None => break, +/// Some(loop_variable) => { code(); }, /// }; -/// let loop_variable = next; -/// let () = { code(); }; /// }, /// }; /// result diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 1d2d26b8f0..133cda4f45 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -257,13 +257,15 @@ #![feature(const_cstr_unchecked)] #![feature(const_fn_floating_point_arithmetic)] #![feature(const_fn_fn_ptr_basics)] +#![feature(const_fn_trait_bound)] #![feature(const_format_args)] #![feature(const_io_structs)] #![feature(const_ip)] #![feature(const_ipv4)] #![feature(const_ipv6)] #![feature(const_option)] -#![feature(const_raw_ptr_deref)] +#![cfg_attr(bootstrap, feature(const_raw_ptr_deref))] +#![cfg_attr(not(bootstrap), feature(const_mut_refs))] #![feature(const_socketaddr)] #![feature(const_trait_impl)] #![feature(container_error_extra)] @@ -272,11 +274,12 @@ #![feature(custom_test_frameworks)] #![feature(decl_macro)] #![feature(doc_cfg)] -#![cfg_attr(not(bootstrap), feature(doc_cfg_hide))] -#![feature(doc_keyword)] +#![feature(doc_cfg_hide)] +#![cfg_attr(bootstrap, feature(doc_primitive))] +#![cfg_attr(bootstrap, feature(doc_keyword))] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] #![feature(doc_masked)] #![feature(doc_notable_trait)] -#![feature(doc_primitive)] #![feature(dropck_eyepatch)] #![feature(duration_checked_float)] #![feature(duration_constants)] @@ -284,8 +287,8 @@ #![feature(exact_size_is_empty)] #![feature(exhaustive_patterns)] #![feature(extend_one)] -#![feature(float_interpolation)] #![feature(fn_traits)] +#![feature(float_minimum_maximum)] #![feature(format_args_nl)] #![feature(gen_future)] #![feature(generator_trait)] @@ -308,7 +311,7 @@ #![feature(maybe_uninit_uninit_array)] #![feature(min_specialization)] #![feature(mixed_integer_ops)] -#![cfg_attr(not(bootstrap), feature(must_not_suspend))] +#![feature(must_not_suspend)] #![feature(needs_panic_runtime)] #![feature(negative_impls)] #![feature(never_type)] @@ -324,7 +327,6 @@ #![feature(ptr_internals)] #![feature(rustc_attrs)] #![feature(rustc_private)] -#![feature(saturating_div)] #![feature(saturating_int_impl)] #![feature(slice_concat_ext)] #![feature(slice_internals)] diff --git a/library/std/src/net/addr.rs b/library/std/src/net/addr.rs index a689d2a56b..201cbf3f08 100644 --- a/library/std/src/net/addr.rs +++ b/library/std/src/net/addr.rs @@ -149,6 +149,7 @@ impl SocketAddr { /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))); /// ``` + #[must_use] #[stable(feature = "ip_addr", since = "1.7.0")] #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] pub const fn ip(&self) -> IpAddr { @@ -189,6 +190,7 @@ impl SocketAddr { /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); /// assert_eq!(socket.port(), 8080); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] pub const fn port(&self) -> u16 { @@ -297,6 +299,7 @@ impl SocketAddrV4 { /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); /// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1)); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] pub const fn ip(&self) -> &Ipv4Addr { @@ -331,6 +334,7 @@ impl SocketAddrV4 { /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); /// assert_eq!(socket.port(), 8080); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] pub const fn port(&self) -> u16 { @@ -396,6 +400,7 @@ impl SocketAddrV6 { /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0); /// assert_eq!(socket.ip(), &Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] pub const fn ip(&self) -> &Ipv6Addr { @@ -428,6 +433,7 @@ impl SocketAddrV6 { /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0); /// assert_eq!(socket.port(), 8080); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] pub const fn port(&self) -> u16 { @@ -470,6 +476,7 @@ impl SocketAddrV6 { /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 10, 0); /// assert_eq!(socket.flowinfo(), 10); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] pub const fn flowinfo(&self) -> u32 { @@ -509,6 +516,7 @@ impl SocketAddrV6 { /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 78); /// assert_eq!(socket.scope_id(), 78); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] pub const fn scope_id(&self) -> u32 { diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs index e5e9fedb61..da95fe21ac 100644 --- a/library/std/src/net/ip.rs +++ b/library/std/src/net/ip.rs @@ -59,7 +59,8 @@ 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]. +/// Notably, octal numbers (which are indicated with a leading `0`) and hexadecimal numbers (which +/// are indicated with a leading `0x`) are not allowed per [IETF RFC 6943]. /// /// [IETF RFC 6943]: https://tools.ietf.org/html/rfc6943#section-3.1.1 /// [`FromStr`]: crate::str::FromStr @@ -72,6 +73,9 @@ pub enum IpAddr { /// let localhost = Ipv4Addr::new(127, 0, 0, 1); /// assert_eq!("127.0.0.1".parse(), Ok(localhost)); /// assert_eq!(localhost.is_loopback(), true); +/// assert!("012.004.002.000".parse::().is_err()); // all octets are in octal +/// assert!("0000000.0.0.0".parse::().is_err()); // first octet is a zero in octal +/// assert!("0xcb.0x0.0x71.0x00".parse::().is_err()); // all octets are in hex /// ``` #[derive(Copy)] #[stable(feature = "rust1", since = "1.0.0")] @@ -514,6 +518,7 @@ impl Ipv4Addr { /// ``` #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")] #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] #[inline] pub const fn octets(&self) -> [u8; 4] { // This returns the order we want because s_addr is stored in big-endian. @@ -873,12 +878,7 @@ impl Ipv4Addr { #[must_use] #[inline] pub const fn is_documentation(&self) -> bool { - match self.octets() { - [192, 0, 2, _] => true, - [198, 51, 100, _] => true, - [203, 0, 113, _] => true, - _ => false, - } + matches!(self.octets(), [192, 0, 2, _] | [198, 51, 100, _] | [203, 0, 113, _]) } /// Converts this address to an [IPv4-compatible] [`IPv6` address]. @@ -1280,6 +1280,7 @@ impl Ipv6Addr { /// ``` #[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")] #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] #[inline] pub const fn segments(&self) -> [u16; 8] { // All elements in `s6_addr` must be big endian. @@ -1590,6 +1591,7 @@ impl Ipv6Addr { /// ``` #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] + #[must_use] #[inline] pub const fn multicast_scope(&self) -> Option { if self.is_multicast() { @@ -1740,6 +1742,7 @@ impl Ipv6Addr { /// ``` #[rustc_const_stable(feature = "const_ipv6", since = "1.32.0")] #[stable(feature = "ipv6_to_octets", since = "1.12.0")] + #[must_use] #[inline] pub const fn octets(&self) -> [u8; 16] { self.inner.s6_addr diff --git a/library/std/src/net/ip/tests.rs b/library/std/src/net/ip/tests.rs index babc854cd1..17581f3302 100644 --- a/library/std/src/net/ip/tests.rs +++ b/library/std/src/net/ip/tests.rs @@ -20,6 +20,14 @@ fn test_from_str_ipv4() { // no number between dots let none: Option = "255.0..1".parse().ok(); assert_eq!(None, none); + // octal + let none: Option = "255.0.0.01".parse().ok(); + assert_eq!(None, none); + // octal zero + let none: Option = "255.0.0.00".parse().ok(); + assert_eq!(None, none); + let none: Option = "255.0.00.0".parse().ok(); + assert_eq!(None, none); } #[test] diff --git a/library/std/src/net/parser.rs b/library/std/src/net/parser.rs index 88a8cb76be..4e16a55ede 100644 --- a/library/std/src/net/parser.rs +++ b/library/std/src/net/parser.rs @@ -111,10 +111,12 @@ impl<'a> Parser<'a> { &mut self, radix: u32, max_digits: Option, + allow_zero_prefix: bool, ) -> Option { self.read_atomically(move |p| { let mut result = T::ZERO; let mut digit_count = 0; + let has_leading_zero = p.peek_char() == Some('0'); while let Some(digit) = p.read_atomically(|p| p.read_char()?.to_digit(radix)) { result = result.checked_mul(radix)?; @@ -127,7 +129,13 @@ impl<'a> Parser<'a> { } } - if digit_count == 0 { None } else { Some(result) } + if digit_count == 0 { + None + } else if !allow_zero_prefix && has_leading_zero && digit_count > 1 { + None + } else { + Some(result) + } }) } @@ -140,10 +148,7 @@ impl<'a> Parser<'a> { *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, - } + p.read_number(10, Some(3), false) })?; } @@ -175,7 +180,7 @@ impl<'a> Parser<'a> { } } - let group = p.read_separator(':', i, |p| p.read_number(16, Some(4))); + let group = p.read_separator(':', i, |p| p.read_number(16, Some(4), true)); match group { Some(g) => *slot = g, @@ -227,7 +232,7 @@ impl<'a> Parser<'a> { fn read_port(&mut self) -> Option { self.read_atomically(|p| { p.read_given_char(':')?; - p.read_number(10, None) + p.read_number(10, None, true) }) } @@ -235,7 +240,7 @@ impl<'a> Parser<'a> { fn read_scope_id(&mut self) -> Option { self.read_atomically(|p| { p.read_given_char('%')?; - p.read_number(10, None) + p.read_number(10, None, true) }) } @@ -281,7 +286,12 @@ impl FromStr for IpAddr { impl FromStr for Ipv4Addr { type Err = AddrParseError; fn from_str(s: &str) -> Result { - Parser::new(s).parse_with(|p| p.read_ipv4_addr()) + // don't try to parse if too long + if s.len() > 15 { + Err(AddrParseError(())) + } else { + Parser::new(s).parse_with(|p| p.read_ipv4_addr()) + } } } diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs index 2c6e393005..5738862fb5 100644 --- a/library/std/src/net/tcp.rs +++ b/library/std/src/net/tcp.rs @@ -90,6 +90,7 @@ pub struct TcpListener(net_imp::TcpListener); /// See its documentation for more. /// /// [`accept`]: TcpListener::accept +#[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] #[derive(Debug)] pub struct Incoming<'a> { diff --git a/library/std/src/os/raw/mod.rs b/library/std/src/os/raw/mod.rs index 30eeac14b4..01392ffab7 100644 --- a/library/std/src/os/raw/mod.rs +++ b/library/std/src/os/raw/mod.rs @@ -165,7 +165,14 @@ pub use core::ffi::c_void; #[unstable(feature = "c_size_t", issue = "88345")] pub type c_size_t = usize; -/// Equivalent to C's `ssize_t` type, from `stddef.h` (or `cstddef` for C++). +/// Equivalent to C's `ptrdiff_t` type, from `stddef.h` (or `cstddef` for C++). +/// +/// This type is currently always [`isize`], however in the future there may be +/// platforms where this is not the case. +#[unstable(feature = "c_size_t", issue = "88345")] +pub type c_ptrdiff_t = isize; + +/// Equivalent to C's `ssize_t` (on POSIX) or `SSIZE_T` (on Windows) type. /// /// This type is currently always [`isize`], however in the future there may be /// platforms where this is not the case. diff --git a/library/std/src/os/unix/net/addr.rs b/library/std/src/os/unix/net/addr.rs index 887f605993..f450e41bfe 100644 --- a/library/std/src/os/unix/net/addr.rs +++ b/library/std/src/os/unix/net/addr.rs @@ -159,7 +159,7 @@ impl SocketAddr { #[must_use] #[stable(feature = "unix_socket", since = "1.10.0")] pub fn is_unnamed(&self) -> bool { - if let AddressKind::Unnamed = self.address() { true } else { false } + matches!(self.address(), AddressKind::Unnamed) } /// Returns the contents of this address if it is a `pathname` address. diff --git a/library/std/src/os/unix/net/ancillary.rs b/library/std/src/os/unix/net/ancillary.rs index 57bb61903c..6e6f5212b4 100644 --- a/library/std/src/os/unix/net/ancillary.rs +++ b/library/std/src/os/unix/net/ancillary.rs @@ -201,6 +201,7 @@ impl SocketCred { } /// Get the current PID. + #[must_use] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn get_pid(&self) -> libc::pid_t { self.0.pid @@ -213,6 +214,7 @@ impl SocketCred { } /// Get the current UID. + #[must_use] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn get_uid(&self) -> libc::uid_t { self.0.uid @@ -225,6 +227,7 @@ impl SocketCred { } /// Get the current GID. + #[must_use] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn get_gid(&self) -> libc::gid_t { self.0.gid @@ -330,6 +333,7 @@ impl<'a> AncillaryData<'a> { } /// This struct is used to iterate through the control messages. +#[must_use = "iterators are lazy and do nothing unless consumed"] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub struct Messages<'a> { buffer: &'a [u8], @@ -425,18 +429,21 @@ impl<'a> SocketAncillary<'a> { } /// Returns the capacity of the buffer. + #[must_use] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn capacity(&self) -> usize { self.buffer.len() } /// Returns `true` if the ancillary data is empty. + #[must_use] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn is_empty(&self) -> bool { self.length == 0 } /// Returns the number of used bytes. + #[must_use] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn len(&self) -> usize { self.length @@ -471,6 +478,7 @@ impl<'a> SocketAncillary<'a> { /// Ok(()) /// } /// ``` + #[must_use] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn truncated(&self) -> bool { self.truncated diff --git a/library/std/src/os/unix/net/listener.rs b/library/std/src/os/unix/net/listener.rs index 97348afe7d..b23dd6062f 100644 --- a/library/std/src/os/unix/net/listener.rs +++ b/library/std/src/os/unix/net/listener.rs @@ -365,6 +365,7 @@ impl<'a> IntoIterator for &'a UnixListener { /// } /// ``` #[derive(Debug)] +#[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "unix_socket", since = "1.10.0")] pub struct Incoming<'a> { listener: &'a UnixListener, diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs index 4d23805e47..855f900430 100644 --- a/library/std/src/os/unix/process.rs +++ b/library/std/src/os/unix/process.rs @@ -39,7 +39,7 @@ pub trait CommandExt: Sealed { /// Sets the supplementary group IDs for the calling process. Translates to /// a `setgroups` call in the child process. - #[unstable(feature = "setgroups", issue = "38527", reason = "")] + #[unstable(feature = "setgroups", issue = "90747")] fn groups( &mut self, #[cfg(not(target_os = "vxworks"))] groups: &[u32], @@ -207,7 +207,7 @@ impl CommandExt for process::Command { /// [`ExitStatusError`](process::ExitStatusError). /// /// On Unix, `ExitStatus` **does not necessarily represent an exit status**, as -/// passed to the `exit` system call or returned by +/// passed to the `_exit` system call or returned by /// [`ExitStatus::code()`](crate::process::ExitStatus::code). It represents **any wait status** /// as returned by one of the `wait` family of system /// calls. @@ -239,27 +239,27 @@ pub trait ExitStatusExt: Sealed { fn signal(&self) -> Option; /// If the process was terminated by a signal, says whether it dumped core. - #[unstable(feature = "unix_process_wait_more", issue = "80695")] + #[stable(feature = "unix_process_wait_more", since = "1.58.0")] fn core_dumped(&self) -> bool; /// 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`, and was then converted into an `ExitStatus`. - #[unstable(feature = "unix_process_wait_more", issue = "80695")] + #[stable(feature = "unix_process_wait_more", since = "1.58.0")] 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`, and was then converted into an `ExitStatus`. - #[unstable(feature = "unix_process_wait_more", issue = "80695")] + #[stable(feature = "unix_process_wait_more", since = "1.58.0")] fn continued(&self) -> bool; /// Returns the underlying raw `wait` status. /// /// The returned integer is a **wait status, not an exit status**. - #[unstable(feature = "unix_process_wait_more", issue = "80695")] + #[stable(feature = "unix_process_wait_more", since = "1.58.0")] fn into_raw(self) -> i32; } @@ -436,6 +436,7 @@ impl From for OwnedFd { } /// Returns the OS-assigned process identifier associated with this process's parent. +#[must_use] #[stable(feature = "unix_ppid", since = "1.27.0")] pub fn parent_id() -> u32 { crate::sys::os::getppid() diff --git a/library/std/src/os/wasi/fs.rs b/library/std/src/os/wasi/fs.rs index 907368061d..5c62679f55 100644 --- a/library/std/src/os/wasi/fs.rs +++ b/library/std/src/os/wasi/fs.rs @@ -444,18 +444,22 @@ pub trait FileTypeExt { /// Returns `true` if this file type is a block device. fn is_block_device(&self) -> bool; /// Returns `true` if this file type is a character device. - fn is_character_device(&self) -> bool; + fn is_char_device(&self) -> bool; /// Returns `true` if this file type is a socket datagram. fn is_socket_dgram(&self) -> bool; /// Returns `true` if this file type is a socket stream. fn is_socket_stream(&self) -> bool; + /// Returns `true` if this file type is any type of socket. + fn is_socket(&self) -> bool { + self.is_socket_stream() || self.is_socket_dgram() + } } impl FileTypeExt for fs::FileType { fn is_block_device(&self) -> bool { self.as_inner().bits() == wasi::FILETYPE_BLOCK_DEVICE } - fn is_character_device(&self) -> bool { + fn is_char_device(&self) -> bool { self.as_inner().bits() == wasi::FILETYPE_CHARACTER_DEVICE } fn is_socket_dgram(&self) -> bool { diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index 21e9669c11..c0605b2f41 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -25,7 +25,7 @@ pub macro panic_2015 { $crate::rt::panic_display(&$arg) }), ($fmt:expr, $($arg:tt)+) => ({ - $crate::rt::begin_panic_fmt(&$crate::const_format_args!($fmt, $($arg)+)) + $crate::rt::panic_fmt($crate::const_format_args!($fmt, $($arg)+)) }), } diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 231c9fc19c..6fc6b8daec 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -160,6 +160,7 @@ pub fn set_hook(hook: Box) + 'static + Sync + Send>) { /// /// panic!("Normal panic"); /// ``` +#[must_use] #[stable(feature = "panic_hooks", since = "1.10.0")] pub fn take_hook() -> Box) + 'static + Sync + Send> { if thread::panicking() { @@ -284,11 +285,13 @@ pub mod panic_count { } // Disregards ALWAYS_ABORT_FLAG + #[must_use] pub fn get_count() -> usize { LOCAL_PANIC_COUNT.with(|c| c.get()) } // Disregards ALWAYS_ABORT_FLAG + #[must_use] #[inline] pub fn count_is_zero() -> bool { if GLOBAL_PANIC_COUNT.load(Ordering::Relaxed) & !ALWAYS_ABORT_FLAG == 0 { @@ -437,31 +440,9 @@ pub fn panicking() -> bool { !panic_count::count_is_zero() } -/// The entry point for panicking with a formatted message. -/// -/// This is designed to reduce the amount of code required at the call -/// site as much as possible (so that `panic!()` has as low an impact -/// on (e.g.) the inlining of other functions as possible), by moving -/// the actual formatting into this shared place. -#[unstable(feature = "libstd_sys_internals", reason = "used by the panic! macro", issue = "none")] -#[cold] -// If panic_immediate_abort, inline the abort call, -// otherwise avoid inlining because of it is cold path. -#[cfg_attr(not(feature = "panic_immediate_abort"), track_caller)] -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] -#[cfg_attr(feature = "panic_immediate_abort", inline)] -#[cfg_attr(not(test), lang = "begin_panic_fmt")] -pub fn begin_panic_fmt(msg: &fmt::Arguments<'_>) -> ! { - if cfg!(feature = "panic_immediate_abort") { - intrinsics::abort() - } - - let info = PanicInfo::internal_constructor(Some(msg), Location::caller()); - begin_panic_handler(&info) -} - /// Entry point of panics from the libcore crate (`panic_impl` lang item). -#[cfg_attr(not(test), panic_handler)] +#[cfg(not(test))] +#[panic_handler] pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! { struct PanicPayload<'a> { inner: &'a fmt::Arguments<'a>, @@ -534,7 +515,8 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! { #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] #[cold] #[track_caller] -pub fn begin_panic(msg: M) -> ! { +#[rustc_do_not_const_check] // hooked by const-eval +pub const fn begin_panic(msg: M) -> ! { if cfg!(feature = "panic_immediate_abort") { intrinsics::abort() } diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 8f00d2260e..cf2cd5adc4 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -422,6 +422,7 @@ impl<'a> PrefixComponent<'a> { /// See [`Prefix`]'s documentation for more information on the different /// kinds of prefixes. #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] #[inline] pub fn kind(&self) -> Prefix<'a> { self.parsed @@ -583,6 +584,7 @@ impl AsRef for Component<'_> { /// /// [`components`]: Path::components #[derive(Clone)] +#[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] pub struct Components<'a> { // The path left to parse components from @@ -609,6 +611,7 @@ pub struct Components<'a> { /// /// [`iter`]: Path::iter #[derive(Clone)] +#[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] pub struct Iter<'a> { inner: Components<'a>, @@ -976,6 +979,25 @@ impl FusedIterator for Components<'_> {} impl<'a> cmp::PartialEq for Components<'a> { #[inline] fn eq(&self, other: &Components<'a>) -> bool { + let Components { path: _, front: _, back: _, has_physical_root: _, prefix: _ } = self; + + // Fast path for exact matches, e.g. for hashmap lookups. + // Don't explicitly compare the prefix or has_physical_root fields since they'll + // either be covered by the `path` buffer or are only relevant for `prefix_verbatim()`. + if self.path.len() == other.path.len() + && self.front == other.front + && self.back == State::Body + && other.back == State::Body + && self.prefix_verbatim() == other.prefix_verbatim() + { + // possible future improvement: this could bail out earlier if there were a + // reverse memcmp/bcmp comparing back to front + if self.path == other.path { + return true; + } + } + + // compare back to front since absolute paths often share long prefixes Iterator::eq(self.clone().rev(), other.clone().rev()) } } @@ -1010,13 +1032,12 @@ fn compare_components(mut left: Components<'_>, mut right: Components<'_>) -> cm // The fast path isn't taken for paths with a PrefixComponent to avoid backtracking into // the middle of one if left.prefix.is_none() && right.prefix.is_none() && left.front == right.front { - // this might benefit from a [u8]::first_mismatch simd implementation, if it existed - let first_difference = - match left.path.iter().zip(right.path.iter()).position(|(&a, &b)| a != b) { - None if left.path.len() == right.path.len() => return cmp::Ordering::Equal, - None => left.path.len().min(right.path.len()), - Some(diff) => diff, - }; + // possible future improvement: a [u8]::first_mismatch simd implementation + let first_difference = match left.path.iter().zip(right.path).position(|(&a, &b)| a != b) { + None if left.path.len() == right.path.len() => return cmp::Ordering::Equal, + None => left.path.len().min(right.path.len()), + Some(diff) => diff, + }; if let Some(previous_sep) = left.path[..first_difference].iter().rposition(|&b| left.is_sep_byte(b)) @@ -1051,6 +1072,7 @@ fn compare_components(mut left: Components<'_>, mut right: Components<'_>) -> cm /// /// [`ancestors`]: Path::ancestors #[derive(Copy, Clone, Debug)] +#[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "path_ancestors", since = "1.28.0")] pub struct Ancestors<'a> { next: Option<&'a Path>, @@ -1459,6 +1481,7 @@ impl PathBuf { /// /// [`capacity`]: OsString::capacity #[stable(feature = "path_buf_capacity", since = "1.44.0")] + #[must_use] #[inline] pub fn capacity(&self) -> usize { self.inner.capacity() @@ -2103,6 +2126,7 @@ impl Path { /// assert_eq!(grand_parent.parent(), None); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] pub fn parent(&self) -> Option<&Path> { let mut comps = self.components(); let comp = comps.next_back(); @@ -2169,6 +2193,7 @@ impl Path { /// assert_eq!(None, Path::new("/").file_name()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] pub fn file_name(&self) -> Option<&OsStr> { self.components().next_back().and_then(|p| match p { Component::Normal(p) => Some(p), @@ -2241,6 +2266,7 @@ impl Path { /// assert!(!Path::new("/etc/foo.rs").starts_with("/etc/foo")); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] pub fn starts_with>(&self, base: P) -> bool { self._starts_with(base.as_ref()) } @@ -2268,6 +2294,7 @@ impl Path { /// assert!(!path.ends_with("conf")); // use .extension() instead /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] pub fn ends_with>(&self, child: P) -> bool { self._ends_with(child.as_ref()) } @@ -2303,6 +2330,7 @@ impl Path { /// [`Path::file_prefix`]: Path::file_prefix /// #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] pub fn file_stem(&self) -> Option<&OsStr> { self.file_name().map(rsplit_file_at_dot).and_then(|(before, after)| before.or(after)) } @@ -2336,6 +2364,7 @@ impl Path { /// [`Path::file_stem`]: Path::file_stem /// #[unstable(feature = "path_file_prefix", issue = "86319")] + #[must_use] pub fn file_prefix(&self) -> Option<&OsStr> { self.file_name().map(split_file_at_dot).and_then(|(before, _after)| Some(before)) } @@ -2360,6 +2389,7 @@ impl Path { /// assert_eq!("gz", Path::new("foo.tar.gz").extension().unwrap()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] pub fn extension(&self) -> Option<&OsStr> { self.file_name().map(rsplit_file_at_dot).and_then(|(before, after)| before.and(after)) } @@ -2403,6 +2433,7 @@ impl Path { /// assert_eq!(path.with_file_name("var"), PathBuf::from("/var")); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] pub fn with_file_name>(&self, file_name: S) -> PathBuf { self._with_file_name(file_name.as_ref()) } @@ -2660,6 +2691,7 @@ impl Path { /// This is a convenience function that coerces errors to false. If you want to /// check errors, call [`fs::metadata`]. #[stable(feature = "path_ext", since = "1.5.0")] + #[must_use] #[inline] pub fn exists(&self) -> bool { fs::metadata(self).is_ok() @@ -2751,7 +2783,7 @@ impl Path { fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false) } - /// Returns true if the path exists on disk and is pointing at a symbolic link. + /// Returns `true` if the path exists on disk and is pointing at a symbolic link. /// /// This function will not traverse symbolic links. /// In case of a broken symbolic link this will also return true. @@ -2763,7 +2795,6 @@ impl Path { /// #[cfg_attr(unix, doc = "```no_run")] #[cfg_attr(not(unix), doc = "```ignore")] - /// #![feature(is_symlink)] /// use std::path::Path; /// use std::os::unix::fs::symlink; /// @@ -2772,8 +2803,14 @@ impl Path { /// assert_eq!(link_path.is_symlink(), true); /// assert_eq!(link_path.exists(), false); /// ``` - #[unstable(feature = "is_symlink", issue = "85748")] + /// + /// # See Also + /// + /// This is a convenience function that coerces errors to false. If you want to + /// check errors, call [`fs::symlink_metadata`] and handle its [`Result`]. Then call + /// [`fs::Metadata::is_symlink`] if it was [`Ok`]. #[must_use] + #[stable(feature = "is_symlink", since = "1.57.0")] pub fn is_symlink(&self) -> bool { fs::symlink_metadata(self).map(|m| m.is_symlink()).unwrap_or(false) } @@ -2781,6 +2818,7 @@ impl Path { /// Converts a [`Box`](Box) into a [`PathBuf`] without copying or /// allocating. #[stable(feature = "into_boxed_path", since = "1.20.0")] + #[must_use = "`self` will be dropped if the result is not used"] pub fn into_path_buf(self: Box) -> PathBuf { let rw = Box::into_raw(self) as *mut OsStr; let inner = unsafe { Box::from_raw(rw) }; @@ -2853,9 +2891,43 @@ impl cmp::PartialEq for Path { #[stable(feature = "rust1", since = "1.0.0")] impl Hash for Path { fn hash(&self, h: &mut H) { - for component in self.components() { - component.hash(h); + let bytes = self.as_u8_slice(); + let prefix_len = match parse_prefix(&self.inner) { + Some(prefix) => { + prefix.hash(h); + prefix.len() + } + None => 0, + }; + let bytes = &bytes[prefix_len..]; + + let mut component_start = 0; + let mut bytes_hashed = 0; + + for i in 0..bytes.len() { + if is_sep_byte(bytes[i]) { + if i > component_start { + let to_hash = &bytes[component_start..i]; + h.write(to_hash); + bytes_hashed += to_hash.len(); + } + + // skip over separator and optionally a following CurDir item + // since components() would normalize these away + component_start = i + match bytes[i..] { + [_, b'.', b'/', ..] | [_, b'.'] => 2, + _ => 1, + }; + } + } + + if component_start < bytes.len() { + let to_hash = &bytes[component_start..]; + h.write(to_hash); + bytes_hashed += to_hash.len(); } + + h.write_usize(bytes_hashed); } } diff --git a/library/std/src/path/tests.rs b/library/std/src/path/tests.rs index 0a16ff2a72..2bf499e1ab 100644 --- a/library/std/src/path/tests.rs +++ b/library/std/src/path/tests.rs @@ -1,6 +1,8 @@ use super::*; -use crate::collections::BTreeSet; +use crate::collections::hash_map::DefaultHasher; +use crate::collections::{BTreeSet, HashSet}; +use crate::hash::Hasher; use crate::rc::Rc; use crate::sync::Arc; use core::hint::black_box; @@ -1632,7 +1634,25 @@ fn into_rc() { fn test_ord() { macro_rules! ord( ($ord:ident, $left:expr, $right:expr) => ( { - assert_eq!(Path::new($left).cmp(&Path::new($right)), core::cmp::Ordering::$ord); + use core::cmp::Ordering; + + let left = Path::new($left); + let right = Path::new($right); + assert_eq!(left.cmp(&right), Ordering::$ord); + if (core::cmp::Ordering::$ord == Ordering::Equal) { + assert_eq!(left, right); + + let mut hasher = DefaultHasher::new(); + left.hash(&mut hasher); + let left_hash = hasher.finish(); + hasher = DefaultHasher::new(); + right.hash(&mut hasher); + let right_hash = hasher.finish(); + + assert_eq!(left_hash, right_hash, "hashes for {:?} and {:?} must match", left, right); + } else { + assert_ne!(left, right); + } }); ); @@ -1693,3 +1713,59 @@ fn bench_path_cmp_fast_path_short(b: &mut test::Bencher) { set.insert(paths[500].as_path()); }); } + +#[bench] +fn bench_path_hashset(b: &mut test::Bencher) { + let prefix = "/my/home/is/my/castle/and/my/castle/has/a/rusty/workbench/"; + let paths: Vec<_> = + (0..1000).map(|num| PathBuf::from(prefix).join(format!("file {}.rs", num))).collect(); + + let mut set = HashSet::new(); + + paths.iter().for_each(|p| { + set.insert(p.as_path()); + }); + + b.iter(|| { + set.remove(paths[500].as_path()); + set.insert(black_box(paths[500].as_path())) + }); +} + +#[bench] +fn bench_path_hashset_miss(b: &mut test::Bencher) { + let prefix = "/my/home/is/my/castle/and/my/castle/has/a/rusty/workbench/"; + let paths: Vec<_> = + (0..1000).map(|num| PathBuf::from(prefix).join(format!("file {}.rs", num))).collect(); + + let mut set = HashSet::new(); + + paths.iter().for_each(|p| { + set.insert(p.as_path()); + }); + + let probe = PathBuf::from(prefix).join("other"); + + b.iter(|| set.remove(black_box(probe.as_path()))); +} + +#[bench] +fn bench_hash_path_short(b: &mut test::Bencher) { + let mut hasher = DefaultHasher::new(); + let path = Path::new("explorer.exe"); + + b.iter(|| black_box(path).hash(&mut hasher)); + + black_box(hasher.finish()); +} + +#[bench] +fn bench_hash_path_long(b: &mut test::Bencher) { + let mut hasher = DefaultHasher::new(); + let path = + Path::new("/aaaaa/aaaaaa/./../aaaaaaaa/bbbbbbbbbbbbb/ccccccccccc/ddddddddd/eeeeeee.fff"); + + b.iter(|| black_box(path).hash(&mut hasher)); + + black_box(hasher.finish()); +} diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index 0de9126dab..f47a30c9b5 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -1104,11 +1104,10 @@ mod prim_usize {} /// * [`Clone`] \(Note that this will not defer to `T`'s `Clone` implementation if it exists!) /// * [`Deref`] /// * [`Borrow`] -/// * [`Pointer`] +/// * [`fmt::Pointer`] /// /// [`Deref`]: ops::Deref /// [`Borrow`]: borrow::Borrow -/// [`Pointer`]: fmt::Pointer /// /// `&mut T` references get all of the above except `Copy` and `Clone` (to prevent creating /// multiple simultaneous mutable borrows), plus the following, regardless of the type of its @@ -1124,7 +1123,7 @@ mod prim_usize {} /// The following traits are implemented on `&T` references if the underlying `T` also implements /// that trait: /// -/// * All the traits in [`std::fmt`] except [`Pointer`] and [`fmt::Write`] +/// * All the traits in [`std::fmt`] except [`fmt::Pointer`] (which is implemented regardless of the type of its referent) and [`fmt::Write`] /// * [`PartialOrd`] /// * [`Ord`] /// * [`PartialEq`] @@ -1133,9 +1132,9 @@ mod prim_usize {} /// * [`Fn`] \(in addition, `&T` references get [`FnMut`] and [`FnOnce`] if `T: Fn`) /// * [`Hash`] /// * [`ToSocketAddrs`] +/// * [`Send`] \(`&T` references also require T: [Sync]) /// /// [`std::fmt`]: fmt -/// ['Pointer`]: fmt::Pointer /// [`Hash`]: hash::Hash #[doc = concat!("[`ToSocketAddrs`]: ", include_str!("../primitive_docs/net_tosocketaddrs.md"))] /// @@ -1150,7 +1149,6 @@ mod prim_usize {} /// * [`ExactSizeIterator`] /// * [`FusedIterator`] /// * [`TrustedLen`] -/// * [`Send`] \(note that `&T` references only get `Send` if T: [Sync]) /// * [`io::Write`] /// * [`Read`] /// * [`Seek`] diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 4bd06475e2..4e9fd51f28 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -106,6 +106,7 @@ mod tests; use crate::io::prelude::*; +use crate::convert::Infallible; use crate::ffi::OsStr; use crate::fmt; use crate::fs; @@ -948,6 +949,7 @@ impl Command { /// let cmd = Command::new("echo"); /// assert_eq!(cmd.get_program(), "echo"); /// ``` + #[must_use] #[stable(feature = "command_access", since = "1.57.0")] pub fn get_program(&self) -> &OsStr { self.inner.get_program() @@ -1021,6 +1023,7 @@ impl Command { /// cmd.current_dir("/bin"); /// assert_eq!(cmd.get_current_dir(), Some(Path::new("/bin"))); /// ``` + #[must_use] #[stable(feature = "command_access", since = "1.57.0")] pub fn get_current_dir(&self) -> Option<&Path> { self.inner.get_current_dir() @@ -1053,6 +1056,7 @@ impl AsInnerMut for Command { /// /// This struct is created by [`Command::get_args`]. See its documentation for /// more. +#[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "command_access", since = "1.57.0")] #[derive(Debug)] pub struct CommandArgs<'a> { @@ -1183,6 +1187,7 @@ impl Stdio { /// its entire stdin before writing more than a pipe buffer's worth of output. /// The size of a pipe buffer varies on different targets. /// + #[must_use] #[stable(feature = "process", since = "1.0.0")] pub fn piped() -> Stdio { Stdio(imp::Stdio::MakePipe) @@ -1222,6 +1227,7 @@ impl Stdio { /// print!("You piped in the reverse of: "); /// io::stdout().write_all(&output.stdout).unwrap(); /// ``` + #[must_use] #[stable(feature = "process", since = "1.0.0")] pub fn inherit() -> Stdio { Stdio(imp::Stdio::Inherit) @@ -1261,6 +1267,7 @@ impl Stdio { /// assert_eq!(String::from_utf8_lossy(&output.stdout), ""); /// // Ignores any piped-in input /// ``` + #[must_use] #[stable(feature = "process", since = "1.0.0")] pub fn null() -> Stdio { Stdio(imp::Stdio::Null) @@ -1411,6 +1418,11 @@ impl From for Stdio { /// /// [`status`]: Command::status /// [`wait`]: Child::wait +// +// We speak slightly loosely (here and in various other places in the stdlib docs) about `exit` +// vs `_exit`. Naming of Unix system calls is not standardised across Unices, so terminology is a +// matter of convention and tradition. For clarity we usually speak of `exit`, even when we might +// mean an underlying system call such as `_exit`. #[derive(PartialEq, Eq, Clone, Copy, Debug)] #[stable(feature = "process", since = "1.0.0")] pub struct ExitStatus(imp::ExitStatus); @@ -1462,6 +1474,7 @@ impl ExitStatus { /// println!("failed to create 'projects/' directory: {}", status); /// } /// ``` + #[must_use] #[stable(feature = "process", since = "1.0.0")] pub fn success(&self) -> bool { self.0.exit_ok().is_ok() @@ -1493,6 +1506,7 @@ impl ExitStatus { /// None => println!("Process terminated by signal") /// } /// ``` + #[must_use] #[stable(feature = "process", since = "1.0.0")] pub fn code(&self) -> Option { self.0.code() @@ -1580,6 +1594,7 @@ impl ExitStatusError { /// assert_eq!(bad.code(), Some(1)); /// # } // #[cfg(unix)] /// ``` + #[must_use] pub fn code(&self) -> Option { self.code_nonzero().map(Into::into) } @@ -1605,11 +1620,13 @@ impl ExitStatusError { /// assert_eq!(bad.code_nonzero().unwrap(), NonZeroI32::try_from(1).unwrap()); /// # } // cfg!(unix) /// ``` + #[must_use] pub fn code_nonzero(&self) -> Option { self.0.code() } /// Converts an `ExitStatusError` (back) to an `ExitStatus`. + #[must_use] pub fn into_status(&self) -> ExitStatus { ExitStatus(self.0.into()) } @@ -1718,6 +1735,7 @@ impl Child { /// println!("ls command didn't start"); /// } /// ``` + #[must_use] #[stable(feature = "process_id", since = "1.3.0")] pub fn id(&self) -> u32 { self.handle.id() @@ -1988,6 +2006,7 @@ pub fn abort() -> ! { /// ``` /// /// +#[must_use] #[stable(feature = "getpid", since = "1.26.0")] pub fn id() -> u32 { crate::sys::os::getpid() @@ -2047,6 +2066,14 @@ impl Termination for Result { } } +#[unstable(feature = "termination_trait_lib", issue = "43301")] +impl Termination for Result { + fn report(self) -> i32 { + let Err(err) = self; + Err::(err).report() + } +} + #[unstable(feature = "termination_trait_lib", issue = "43301")] impl Termination for ExitCode { #[inline] diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs index bc71c15055..e5cdc47370 100644 --- a/library/std/src/process/tests.rs +++ b/library/std/src/process/tests.rs @@ -4,15 +4,27 @@ use super::{Command, Output, Stdio}; use crate::io::ErrorKind; use crate::str; -// FIXME(#10380) these tests should not all be ignored on android. +fn known_command() -> Command { + if cfg!(windows) { Command::new("help") } else { Command::new("echo") } +} + +#[cfg(target_os = "android")] +fn shell_cmd() -> Command { + Command::new("/system/bin/sh") +} + +#[cfg(not(target_os = "android"))] +fn shell_cmd() -> Command { + Command::new("/bin/sh") +} #[test] -#[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] +#[cfg_attr(any(target_os = "vxworks"), ignore)] fn smoke() { let p = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "exit 0"]).spawn() } else { - Command::new("true").spawn() + shell_cmd().arg("-c").arg("true").spawn() }; assert!(p.is_ok()); let mut p = p.unwrap(); @@ -29,12 +41,12 @@ fn smoke_failure() { } #[test] -#[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] +#[cfg_attr(any(target_os = "vxworks"), ignore)] fn exit_reported_right() { let p = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "exit 1"]).spawn() } else { - Command::new("false").spawn() + shell_cmd().arg("-c").arg("false").spawn() }; assert!(p.is_ok()); let mut p = p.unwrap(); @@ -44,12 +56,11 @@ fn exit_reported_right() { #[test] #[cfg(unix)] -#[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] +#[cfg_attr(any(target_os = "vxworks"), ignore)] fn signal_reported_right() { use crate::os::unix::process::ExitStatusExt; - let mut p = - Command::new("/bin/sh").arg("-c").arg("read a").stdin(Stdio::piped()).spawn().unwrap(); + let mut p = shell_cmd().arg("-c").arg("read a").stdin(Stdio::piped()).spawn().unwrap(); p.kill().unwrap(); match p.wait().unwrap().signal() { Some(9) => {} @@ -69,31 +80,31 @@ pub fn run_output(mut cmd: Command) -> String { } #[test] -#[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] +#[cfg_attr(any(target_os = "vxworks"), ignore)] fn stdout_works() { if cfg!(target_os = "windows") { let mut cmd = Command::new("cmd"); cmd.args(&["/C", "echo foobar"]).stdout(Stdio::piped()); assert_eq!(run_output(cmd), "foobar\r\n"); } else { - let mut cmd = Command::new("echo"); - cmd.arg("foobar").stdout(Stdio::piped()); + let mut cmd = shell_cmd(); + cmd.arg("-c").arg("echo foobar").stdout(Stdio::piped()); assert_eq!(run_output(cmd), "foobar\n"); } } #[test] -#[cfg_attr(any(windows, target_os = "android", target_os = "vxworks"), ignore)] +#[cfg_attr(any(windows, target_os = "vxworks"), ignore)] fn set_current_dir_works() { - let mut cmd = Command::new("/bin/sh"); + let mut cmd = shell_cmd(); cmd.arg("-c").arg("pwd").current_dir("/").stdout(Stdio::piped()); assert_eq!(run_output(cmd), "/\n"); } #[test] -#[cfg_attr(any(windows, target_os = "android", target_os = "vxworks"), ignore)] +#[cfg_attr(any(windows, target_os = "vxworks"), ignore)] fn stdin_works() { - let mut p = Command::new("/bin/sh") + let mut p = shell_cmd() .arg("-c") .arg("read line; echo $line") .stdin(Stdio::piped()) @@ -109,19 +120,19 @@ fn stdin_works() { } #[test] -#[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] +#[cfg_attr(any(target_os = "vxworks"), ignore)] fn test_process_status() { let mut status = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "exit 1"]).status().unwrap() } else { - Command::new("false").status().unwrap() + shell_cmd().arg("-c").arg("false").status().unwrap() }; assert!(status.code() == Some(1)); status = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "exit 0"]).status().unwrap() } else { - Command::new("true").status().unwrap() + shell_cmd().arg("-c").arg("true").status().unwrap() }; assert!(status.success()); } @@ -135,12 +146,12 @@ fn test_process_output_fail_to_start() { } #[test] -#[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] +#[cfg_attr(any(target_os = "vxworks"), ignore)] fn test_process_output_output() { let Output { status, stdout, stderr } = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "echo hello"]).output().unwrap() } else { - Command::new("echo").arg("hello").output().unwrap() + shell_cmd().arg("-c").arg("echo hello").output().unwrap() }; let output_str = str::from_utf8(&stdout).unwrap(); @@ -150,7 +161,7 @@ fn test_process_output_output() { } #[test] -#[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] +#[cfg_attr(any(target_os = "vxworks"), ignore)] fn test_process_output_error() { let Output { status, stdout, stderr } = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "mkdir ."]).output().unwrap() @@ -158,41 +169,42 @@ fn test_process_output_error() { Command::new("mkdir").arg("./").output().unwrap() }; - assert!(status.code() == Some(1)); + assert!(status.code().is_some()); + assert!(status.code() != Some(0)); assert_eq!(stdout, Vec::new()); assert!(!stderr.is_empty()); } #[test] -#[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] +#[cfg_attr(any(target_os = "vxworks"), ignore)] fn test_finish_once() { let mut prog = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "exit 1"]).spawn().unwrap() } else { - Command::new("false").spawn().unwrap() + shell_cmd().arg("-c").arg("false").spawn().unwrap() }; assert!(prog.wait().unwrap().code() == Some(1)); } #[test] -#[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] +#[cfg_attr(any(target_os = "vxworks"), ignore)] fn test_finish_twice() { let mut prog = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "exit 1"]).spawn().unwrap() } else { - Command::new("false").spawn().unwrap() + shell_cmd().arg("-c").arg("false").spawn().unwrap() }; assert!(prog.wait().unwrap().code() == Some(1)); assert!(prog.wait().unwrap().code() == Some(1)); } #[test] -#[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] +#[cfg_attr(any(target_os = "vxworks"), ignore)] fn test_wait_with_output_once() { let prog = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "echo hello"]).stdout(Stdio::piped()).spawn().unwrap() } else { - Command::new("echo").arg("hello").stdout(Stdio::piped()).spawn().unwrap() + shell_cmd().arg("-c").arg("echo hello").stdout(Stdio::piped()).spawn().unwrap() }; let Output { status, stdout, stderr } = prog.wait_with_output().unwrap(); @@ -297,7 +309,7 @@ fn test_interior_nul_in_progname_is_error() { #[test] fn test_interior_nul_in_arg_is_error() { - match Command::new("echo").arg("has-some-\0\0s-inside").spawn() { + match known_command().arg("has-some-\0\0s-inside").spawn() { Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput), Ok(_) => panic!(), } @@ -305,7 +317,7 @@ fn test_interior_nul_in_arg_is_error() { #[test] fn test_interior_nul_in_args_is_error() { - match Command::new("echo").args(&["has-some-\0\0s-inside"]).spawn() { + match known_command().args(&["has-some-\0\0s-inside"]).spawn() { Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput), Ok(_) => panic!(), } @@ -313,7 +325,7 @@ fn test_interior_nul_in_args_is_error() { #[test] fn test_interior_nul_in_current_dir_is_error() { - match Command::new("echo").current_dir("has-some-\0\0s-inside").spawn() { + match known_command().current_dir("has-some-\0\0s-inside").spawn() { Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput), Ok(_) => panic!(), } @@ -408,3 +420,22 @@ fn env_empty() { let p = Command::new("cmd").args(&["/C", "exit 0"]).env_clear().spawn(); assert!(p.is_ok()); } + +// See issue #91991 +#[test] +#[cfg(windows)] +fn run_bat_script() { + let tempdir = crate::sys_common::io::test::tmpdir(); + let script_path = tempdir.join("hello.cmd"); + + crate::fs::write(&script_path, "@echo Hello, %~1!").unwrap(); + let output = Command::new(&script_path) + .arg("fellow Rustaceans") + .stdout(crate::process::Stdio::piped()) + .spawn() + .unwrap() + .wait_with_output() + .unwrap(); + assert!(output.status.success()); + assert_eq!(String::from_utf8_lossy(&output.stdout).trim(), "Hello, fellow Rustaceans!"); +} diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs index 4d72aff011..08e5825757 100644 --- a/library/std/src/rt.rs +++ b/library/std/src/rt.rs @@ -19,8 +19,8 @@ use crate::ffi::CString; // Re-export some of our utilities which are expected by other crates. -pub use crate::panicking::{begin_panic, begin_panic_fmt, panic_count}; -pub use core::panicking::panic_display; +pub use crate::panicking::{begin_panic, panic_count}; +pub use core::panicking::{panic_display, panic_fmt}; use crate::sync::Once; use crate::sys; @@ -128,8 +128,7 @@ fn lang_start_internal( let ret_code = panic::catch_unwind(move || panic::catch_unwind(main).unwrap_or(101) as isize) .map_err(move |e| { mem::forget(e); - rtprintpanic!("drop of the panic payload panicked"); - sys::abort_internal() + rtabort!("drop of the panic payload panicked"); }); panic::catch_unwind(cleanup).map_err(rt_abort)?; ret_code diff --git a/library/std/src/sync/barrier.rs b/library/std/src/sync/barrier.rs index 133c3e46cd..11836b7b69 100644 --- a/library/std/src/sync/barrier.rs +++ b/library/std/src/sync/barrier.rs @@ -130,7 +130,7 @@ impl Barrier { if lock.count < self.num_threads { // We need a while loop to guard against spurious wakeups. // https://en.wikipedia.org/wiki/Spurious_wakeup - while local_gen == lock.generation_id && lock.count < self.num_threads { + while local_gen == lock.generation_id { lock = self.cvar.wait(lock).unwrap(); } BarrierWaitResult(false) diff --git a/library/std/src/sync/condvar.rs b/library/std/src/sync/condvar.rs index d8aca9651b..b41918ec1c 100644 --- a/library/std/src/sync/condvar.rs +++ b/library/std/src/sync/condvar.rs @@ -61,6 +61,7 @@ impl WaitTimeoutResult { /// } /// } /// ``` + #[must_use] #[stable(feature = "wait_timeout", since = "1.5.0")] pub fn timed_out(&self) -> bool { self.0 diff --git a/library/std/src/sync/mpsc/cache_aligned.rs b/library/std/src/sync/mpsc/cache_aligned.rs index b084214432..f95b0ddd58 100644 --- a/library/std/src/sync/mpsc/cache_aligned.rs +++ b/library/std/src/sync/mpsc/cache_aligned.rs @@ -2,10 +2,7 @@ use crate::ops::{Deref, DerefMut}; #[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(align(64))] -pub(super) struct Aligner; - -#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub(super) struct CacheAligned(pub T, pub Aligner); +pub(super) struct CacheAligned(pub T); impl Deref for CacheAligned { type Target = T; @@ -22,6 +19,6 @@ impl DerefMut for CacheAligned { impl CacheAligned { pub(super) fn new(t: T) -> Self { - CacheAligned(t, Aligner) + CacheAligned(t) } } diff --git a/library/std/src/sync/mpsc/mod.rs b/library/std/src/sync/mpsc/mod.rs index b4f4456537..2cf678ef69 100644 --- a/library/std/src/sync/mpsc/mod.rs +++ b/library/std/src/sync/mpsc/mod.rs @@ -707,6 +707,7 @@ impl UnsafeFlavor for Receiver { /// // Let's see what that answer was /// println!("{:?}", receiver.recv().unwrap()); /// ``` +#[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn channel() -> (Sender, Receiver) { let a = Arc::new(oneshot::Packet::new()); @@ -755,6 +756,7 @@ pub fn channel() -> (Sender, Receiver) { /// assert_eq!(receiver.recv().unwrap(), 1); /// assert_eq!(receiver.recv().unwrap(), 2); /// ``` +#[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn sync_channel(bound: usize) -> (SyncSender, Receiver) { let a = Arc::new(sync::Packet::new(bound)); diff --git a/library/std/src/sys/common/alloc.rs b/library/std/src/sys/common/alloc.rs index 576667c017..9665d1fa89 100644 --- a/library/std/src/sys/common/alloc.rs +++ b/library/std/src/sys/common/alloc.rs @@ -24,7 +24,8 @@ pub const MIN_ALIGN: usize = 8; target_arch = "mips64", target_arch = "s390x", target_arch = "sparc64", - target_arch = "riscv64" + target_arch = "riscv64", + target_arch = "wasm64", )))] pub const MIN_ALIGN: usize = 16; diff --git a/library/std/src/sys/hermit/condvar.rs b/library/std/src/sys/hermit/condvar.rs index fa8ef8fc37..b62f21a9da 100644 --- a/library/std/src/sys/hermit/condvar.rs +++ b/library/std/src/sys/hermit/condvar.rs @@ -55,8 +55,20 @@ impl Condvar { mutex.lock(); } - pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool { - panic!("wait_timeout not supported on hermit"); + pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool { + self.counter.fetch_add(1, SeqCst); + mutex.unlock(); + let millis = dur.as_millis().min(u32::MAX as u128) as u32; + + let res = if millis > 0 { + abi::sem_timedwait(self.sem1, millis) + } else { + abi::sem_trywait(self.sem1) + }; + + abi::sem_post(self.sem2); + mutex.lock(); + res == 0 } pub unsafe fn destroy(&self) { diff --git a/library/std/src/sys/hermit/mutex.rs b/library/std/src/sys/hermit/mutex.rs index 691e7e0790..415cbba101 100644 --- a/library/std/src/sys/hermit/mutex.rs +++ b/library/std/src/sys/hermit/mutex.rs @@ -46,8 +46,17 @@ impl Spinlock { #[inline] fn obtain_lock(&self) { let ticket = self.queue.fetch_add(1, Ordering::SeqCst) + 1; + let mut counter: u16 = 0; while self.dequeue.load(Ordering::SeqCst) != ticket { - hint::spin_loop(); + counter += 1; + if counter < 100 { + hint::spin_loop(); + } else { + counter = 0; + unsafe { + abi::yield_now(); + } + } } } diff --git a/library/std/src/sys/hermit/net.rs b/library/std/src/sys/hermit/net.rs index 880ef678a4..1a6b3bc63e 100644 --- a/library/std/src/sys/hermit/net.rs +++ b/library/std/src/sys/hermit/net.rs @@ -182,7 +182,7 @@ impl TcpStream { Ok(self.clone()) } - pub fn set_linger(&self, linger: Option) -> io::Result<()> { + pub fn set_linger(&self, _linger: Option) -> io::Result<()> { unsupported() } diff --git a/library/std/src/sys/itron/thread.rs b/library/std/src/sys/itron/thread.rs index 4feb9c5a6d..bb9fa54d02 100644 --- a/library/std/src/sys/itron/thread.rs +++ b/library/std/src/sys/itron/thread.rs @@ -347,6 +347,6 @@ unsafe fn terminate_and_delete_current_task() -> ! { unsafe { crate::hint::unreachable_unchecked() }; } -pub fn available_concurrency() -> io::Result { +pub fn available_parallelism() -> io::Result { super::unsupported() } diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index 8b8be6ebc2..167c918c94 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -40,7 +40,7 @@ cfg_if::cfg_if! { } else if #[cfg(target_os = "wasi")] { mod wasi; pub use self::wasi::*; - } else if #[cfg(target_arch = "wasm32")] { + } else if #[cfg(target_family = "wasm")] { mod wasm; pub use self::wasm::*; } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] { diff --git a/library/std/src/sys/solid/abi/mod.rs b/library/std/src/sys/solid/abi/mod.rs index 3526440fb8..3205f0db85 100644 --- a/library/std/src/sys/solid/abi/mod.rs +++ b/library/std/src/sys/solid/abi/mod.rs @@ -4,17 +4,15 @@ mod fs; pub mod sockets; pub use self::fs::*; -pub const SOLID_BP_PROGRAM_EXITED: usize = 15; -pub const SOLID_BP_CSABORT: usize = 16; - #[inline(always)] pub fn breakpoint_program_exited(tid: usize) { unsafe { match () { + // SOLID_BP_PROGRAM_EXITED = 15 #[cfg(target_arch = "arm")] - () => asm!("bkpt #{}", const SOLID_BP_PROGRAM_EXITED, in("r0") tid), + () => asm!("bkpt #15", in("r0") tid), #[cfg(target_arch = "aarch64")] - () => asm!("hlt #{}", const SOLID_BP_PROGRAM_EXITED, in("x0") tid), + () => asm!("hlt #15", in("x0") tid), } } } @@ -23,10 +21,11 @@ pub fn breakpoint_program_exited(tid: usize) { pub fn breakpoint_abort() { unsafe { match () { + // SOLID_BP_CSABORT = 16 #[cfg(target_arch = "arm")] - () => asm!("bkpt #{}", const SOLID_BP_CSABORT), + () => asm!("bkpt #16"), #[cfg(target_arch = "aarch64")] - () => asm!("hlt #{}", const SOLID_BP_CSABORT), + () => asm!("hlt #16"), } } } diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index a4fff9b2e6..111639d92b 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -64,7 +64,7 @@ use libc::{ dirent64, fstat64, ftruncate64, lseek64, lstat64, off64_t, open64, readdir64_r, stat64, }; -pub use crate::sys_common::fs::{remove_dir_all, try_exists}; +pub use crate::sys_common::fs::try_exists; pub struct File(FileDesc); @@ -228,7 +228,7 @@ pub struct DirEntry { target_os = "fuchsia", target_os = "redox" ))] - name: Box<[u8]>, + name: CString, } #[derive(Clone, Debug)] @@ -455,8 +455,6 @@ impl Iterator for ReadDir { target_os = "illumos" ))] fn next(&mut self) -> Option> { - use crate::slice; - unsafe { loop { // Although readdir_r(3) would be a correct function to use here because @@ -474,14 +472,10 @@ impl Iterator for ReadDir { }; } - let name = (*entry_ptr).d_name.as_ptr(); - let namelen = libc::strlen(name) as usize; - let ret = DirEntry { entry: *entry_ptr, - name: slice::from_raw_parts(name as *const u8, namelen as usize) - .to_owned() - .into_boxed_slice(), + // d_name is guaranteed to be null-terminated. + name: CStr::from_ptr((*entry_ptr).d_name.as_ptr()).to_owned(), dir: Arc::clone(&self.inner), }; if ret.name_bytes() != b"." && ret.name_bytes() != b".." { @@ -664,7 +658,21 @@ impl DirEntry { target_os = "redox" ))] fn name_bytes(&self) -> &[u8] { - &*self.name + self.name.as_bytes() + } + + #[cfg(not(any( + target_os = "solaris", + target_os = "illumos", + target_os = "fuchsia", + target_os = "redox" + )))] + fn name_cstr(&self) -> &CStr { + unsafe { CStr::from_ptr(self.entry.d_name.as_ptr()) } + } + #[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "fuchsia"))] + fn name_cstr(&self) -> &CStr { + &self.name } pub fn file_name_os_str(&self) -> &OsStr { @@ -1439,3 +1447,258 @@ pub fn chroot(dir: &Path) -> io::Result<()> { cvt(unsafe { libc::chroot(dir.as_ptr()) })?; Ok(()) } + +pub use remove_dir_impl::remove_dir_all; + +// Fallback for REDOX +#[cfg(target_os = "redox")] +mod remove_dir_impl { + pub use crate::sys_common::fs::remove_dir_all; +} + +// Dynamically choose implementation Macos x86-64: modern for 10.10+, fallback for older versions +#[cfg(all(target_os = "macos", target_arch = "x86_64"))] +mod remove_dir_impl { + use super::{cstr, lstat, Dir, InnerReadDir, ReadDir}; + use crate::ffi::CStr; + use crate::io; + use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd}; + use crate::os::unix::prelude::{OwnedFd, RawFd}; + use crate::path::{Path, PathBuf}; + use crate::sync::Arc; + use crate::sys::weak::weak; + use crate::sys::{cvt, cvt_r}; + use libc::{c_char, c_int, DIR}; + + pub fn openat_nofollow_dironly(parent_fd: Option, p: &CStr) -> io::Result { + weak!(fn openat(c_int, *const c_char, c_int) -> c_int); + let fd = cvt_r(|| unsafe { + openat.get().unwrap()( + parent_fd.unwrap_or(libc::AT_FDCWD), + p.as_ptr(), + libc::O_CLOEXEC | libc::O_RDONLY | libc::O_NOFOLLOW | libc::O_DIRECTORY, + ) + })?; + Ok(unsafe { OwnedFd::from_raw_fd(fd) }) + } + + fn fdreaddir(dir_fd: OwnedFd) -> io::Result<(ReadDir, RawFd)> { + weak!(fn fdopendir(c_int) -> *mut DIR, "fdopendir$INODE64"); + let ptr = unsafe { fdopendir.get().unwrap()(dir_fd.as_raw_fd()) }; + if ptr.is_null() { + return Err(io::Error::last_os_error()); + } + let dirp = Dir(ptr); + // file descriptor is automatically closed by libc::closedir() now, so give up ownership + let new_parent_fd = dir_fd.into_raw_fd(); + // a valid root is not needed because we do not call any functions involving the full path + // of the DirEntrys. + let dummy_root = PathBuf::new(); + Ok(( + ReadDir { + inner: Arc::new(InnerReadDir { dirp, root: dummy_root }), + end_of_stream: false, + }, + new_parent_fd, + )) + } + + fn remove_dir_all_recursive(parent_fd: Option, p: &Path) -> io::Result<()> { + weak!(fn unlinkat(c_int, *const c_char, c_int) -> c_int); + + let pcstr = cstr(p)?; + + // entry is expected to be a directory, open as such + let fd = openat_nofollow_dironly(parent_fd, &pcstr)?; + + // open the directory passing ownership of the fd + let (dir, fd) = fdreaddir(fd)?; + for child in dir { + let child = child?; + match child.entry.d_type { + libc::DT_DIR => { + remove_dir_all_recursive(Some(fd), Path::new(&child.file_name()))?; + } + libc::DT_UNKNOWN => { + match cvt(unsafe { unlinkat.get().unwrap()(fd, child.name_cstr().as_ptr(), 0) }) + { + // type unknown - try to unlink + Err(err) if err.raw_os_error() == Some(libc::EPERM) => { + // if the file is a directory unlink fails with EPERM + remove_dir_all_recursive(Some(fd), Path::new(&child.file_name()))?; + } + result => { + result?; + } + } + } + _ => { + // not a directory -> unlink + cvt(unsafe { unlinkat.get().unwrap()(fd, child.name_cstr().as_ptr(), 0) })?; + } + } + } + + // unlink the directory after removing its contents + cvt(unsafe { + unlinkat.get().unwrap()( + parent_fd.unwrap_or(libc::AT_FDCWD), + pcstr.as_ptr(), + libc::AT_REMOVEDIR, + ) + })?; + Ok(()) + } + + fn remove_dir_all_modern(p: &Path) -> io::Result<()> { + // We cannot just call remove_dir_all_recursive() here because that would not delete a passed + // symlink. No need to worry about races, because remove_dir_all_recursive() does not recurse + // into symlinks. + let attr = lstat(p)?; + if attr.file_type().is_symlink() { + crate::fs::remove_file(p) + } else { + remove_dir_all_recursive(None, p) + } + } + + pub fn remove_dir_all(p: &Path) -> io::Result<()> { + weak!(fn openat(c_int, *const c_char, c_int) -> c_int); + if openat.get().is_some() { + // openat() is available with macOS 10.10+, just like unlinkat() and fdopendir() + remove_dir_all_modern(p) + } else { + // fall back to classic implementation + crate::sys_common::fs::remove_dir_all(p) + } + } +} + +// Modern implementation using openat(), unlinkat() and fdopendir() +#[cfg(not(any(all(target_os = "macos", target_arch = "x86_64"), target_os = "redox")))] +mod remove_dir_impl { + use super::{cstr, lstat, Dir, DirEntry, InnerReadDir, ReadDir}; + use crate::ffi::CStr; + use crate::io; + use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd}; + use crate::os::unix::prelude::{OwnedFd, RawFd}; + use crate::path::{Path, PathBuf}; + use crate::sync::Arc; + use crate::sys::{cvt, cvt_r}; + use libc::{fdopendir, openat, unlinkat}; + + pub fn openat_nofollow_dironly(parent_fd: Option, p: &CStr) -> io::Result { + let fd = cvt_r(|| unsafe { + openat( + parent_fd.unwrap_or(libc::AT_FDCWD), + p.as_ptr(), + libc::O_CLOEXEC | libc::O_RDONLY | libc::O_NOFOLLOW | libc::O_DIRECTORY, + ) + })?; + Ok(unsafe { OwnedFd::from_raw_fd(fd) }) + } + + fn fdreaddir(dir_fd: OwnedFd) -> io::Result<(ReadDir, RawFd)> { + let ptr = unsafe { fdopendir(dir_fd.as_raw_fd()) }; + if ptr.is_null() { + return Err(io::Error::last_os_error()); + } + let dirp = Dir(ptr); + // file descriptor is automatically closed by libc::closedir() now, so give up ownership + let new_parent_fd = dir_fd.into_raw_fd(); + // a valid root is not needed because we do not call any functions involving the full path + // of the DirEntrys. + let dummy_root = PathBuf::new(); + Ok(( + ReadDir { + inner: Arc::new(InnerReadDir { dirp, root: dummy_root }), + #[cfg(not(any( + target_os = "solaris", + target_os = "illumos", + target_os = "fuchsia", + target_os = "redox", + )))] + end_of_stream: false, + }, + new_parent_fd, + )) + } + + #[cfg(any( + target_os = "solaris", + target_os = "illumos", + target_os = "haiku", + target_os = "vxworks", + target_os = "fuchsia" + ))] + fn is_dir(_ent: &DirEntry) -> Option { + None + } + + #[cfg(not(any( + target_os = "solaris", + target_os = "illumos", + target_os = "haiku", + target_os = "vxworks", + target_os = "fuchsia" + )))] + fn is_dir(ent: &DirEntry) -> Option { + match ent.entry.d_type { + libc::DT_UNKNOWN => None, + libc::DT_DIR => Some(true), + _ => Some(false), + } + } + + fn remove_dir_all_recursive(parent_fd: Option, p: &Path) -> io::Result<()> { + let pcstr = cstr(p)?; + + // entry is expected to be a directory, open as such + let fd = openat_nofollow_dironly(parent_fd, &pcstr)?; + + // open the directory passing ownership of the fd + let (dir, fd) = fdreaddir(fd)?; + for child in dir { + let child = child?; + match is_dir(&child) { + Some(true) => { + remove_dir_all_recursive(Some(fd), Path::new(&child.file_name()))?; + } + Some(false) => { + cvt(unsafe { unlinkat(fd, child.name_cstr().as_ptr(), 0) })?; + } + None => match cvt(unsafe { unlinkat(fd, child.name_cstr().as_ptr(), 0) }) { + // type unknown - try to unlink + Err(err) + if err.raw_os_error() == Some(libc::EISDIR) + || err.raw_os_error() == Some(libc::EPERM) => + { + // if the file is a directory unlink fails with EISDIR on Linux and EPERM everyhwere else + remove_dir_all_recursive(Some(fd), Path::new(&child.file_name()))?; + } + result => { + result?; + } + }, + } + } + + // unlink the directory after removing its contents + cvt(unsafe { + unlinkat(parent_fd.unwrap_or(libc::AT_FDCWD), pcstr.as_ptr(), libc::AT_REMOVEDIR) + })?; + Ok(()) + } + + pub fn remove_dir_all(p: &Path) -> io::Result<()> { + // We cannot just call remove_dir_all_recursive() here because that would not delete a passed + // symlink. No need to worry about races, because remove_dir_all_recursive() does not recurse + // into symlinks. + let attr = lstat(p)?; + if attr.file_type().is_symlink() { + crate::fs::remove_file(p) + } else { + remove_dir_all_recursive(None, p) + } + } +} diff --git a/library/std/src/sys/unix/kernel_copy.rs b/library/std/src/sys/unix/kernel_copy.rs index a6b43229ba..f3155fbc06 100644 --- a/library/std/src/sys/unix/kernel_copy.rs +++ b/library/std/src/sys/unix/kernel_copy.rs @@ -576,7 +576,7 @@ pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) -> return match err.raw_os_error() { // when file offset + max_length > u64::MAX Some(EOVERFLOW) => CopyResult::Fallback(written), - Some(ENOSYS | EXDEV | EINVAL | EPERM | EOPNOTSUPP | EBADF) => { + Some(ENOSYS | EXDEV | EINVAL | EPERM | EOPNOTSUPP | EBADF) if written == 0 => { // Try fallback io::copy if either: // - Kernel version is < 4.5 (ENOSYS¹) // - Files are mounted on different fs (EXDEV) @@ -584,12 +584,14 @@ pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) -> // - copy_file_range file is immutable or syscall is blocked by seccomp¹ (EPERM) // - copy_file_range cannot be used with pipes or device nodes (EINVAL) // - the writer fd was opened with O_APPEND (EBADF²) + // and no bytes were written successfully yet. (All these errnos should + // not be returned if something was already written, but they happen in + // the wild, see #91152.) // // ¹ these cases should be detected by the initial probe but we handle them here // anyway in case syscall interception changes during runtime // ² actually invalid file descriptors would cause this too, but in that case // the fallback code path is expected to encounter the same error again - assert_eq!(written, 0); CopyResult::Fallback(0) } _ => CopyResult::Error(err, written), diff --git a/library/std/src/sys/unix/path.rs b/library/std/src/sys/unix/path.rs index 840a7ae042..717add9ec4 100644 --- a/library/std/src/sys/unix/path.rs +++ b/library/std/src/sys/unix/path.rs @@ -11,6 +11,7 @@ pub fn is_verbatim_sep(b: u8) -> bool { b == b'/' } +#[inline] pub fn parse_prefix(_: &OsStr) -> Option> { None } diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs index 326382d903..3bf1493f3b 100644 --- a/library/std/src/sys/unix/process/process_unix.rs +++ b/library/std/src/sys/unix/process/process_unix.rs @@ -617,6 +617,9 @@ impl Process { } /// Unix exit statuses +// +// This is not actually an "exit status" in Unix terminology. Rather, it is a "wait status". +// See the discussion in comments and doc comments for `std::process::ExitStatus`. #[derive(PartialEq, Eq, Clone, Copy)] pub struct ExitStatus(c_int); diff --git a/library/std/src/sys/unix/stack_overflow.rs b/library/std/src/sys/unix/stack_overflow.rs index db1a2a26a8..1e8d1137ac 100644 --- a/library/std/src/sys/unix/stack_overflow.rs +++ b/library/std/src/sys/unix/stack_overflow.rs @@ -6,7 +6,7 @@ pub use self::imp::cleanup; pub use self::imp::init; pub struct Handler { - _data: *mut libc::c_void, + data: *mut libc::c_void, } impl Handler { @@ -15,14 +15,14 @@ impl Handler { } fn null() -> Handler { - Handler { _data: crate::ptr::null_mut() } + Handler { data: crate::ptr::null_mut() } } } impl Drop for Handler { fn drop(&mut self) { unsafe { - drop_handler(self); + drop_handler(self.data); } } } @@ -134,12 +134,12 @@ mod imp { } let handler = make_handler(); - MAIN_ALTSTACK.store(handler._data, Ordering::Relaxed); + MAIN_ALTSTACK.store(handler.data, Ordering::Relaxed); mem::forget(handler); } pub unsafe fn cleanup() { - Handler { _data: MAIN_ALTSTACK.load(Ordering::Relaxed) }; + drop_handler(MAIN_ALTSTACK.load(Ordering::Relaxed)); } unsafe fn get_stackp() -> *mut libc::c_void { @@ -176,14 +176,14 @@ mod imp { if stack.ss_flags & SS_DISABLE != 0 { stack = get_stack(); sigaltstack(&stack, ptr::null_mut()); - Handler { _data: stack.ss_sp as *mut libc::c_void } + Handler { data: stack.ss_sp as *mut libc::c_void } } else { Handler::null() } } - pub unsafe fn drop_handler(handler: &mut Handler) { - if !handler._data.is_null() { + pub unsafe fn drop_handler(data: *mut libc::c_void) { + if !data.is_null() { let stack = libc::stack_t { ss_sp: ptr::null_mut(), ss_flags: SS_DISABLE, @@ -196,7 +196,7 @@ mod imp { sigaltstack(&stack, ptr::null_mut()); // We know from `get_stackp` that the alternate stack we installed is part of a mapping // that started one page earlier, so walk back a page and unmap from there. - munmap(handler._data.sub(page_size()), SIGSTKSZ + page_size()); + munmap(data.sub(page_size()), SIGSTKSZ + page_size()); } } } @@ -220,5 +220,5 @@ mod imp { super::Handler::null() } - pub unsafe fn drop_handler(_handler: &mut super::Handler) {} + pub unsafe fn drop_handler(_data: *mut libc::c_void) {} } diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index 6f4863057a..b99eb2e553 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -275,6 +275,14 @@ pub fn available_parallelism() -> io::Result { target_os = "solaris", target_os = "illumos", ))] { + #[cfg(any(target_os = "android", target_os = "linux"))] + { + let mut set: libc::cpu_set_t = unsafe { mem::zeroed() }; + if unsafe { libc::sched_getaffinity(0, mem::size_of::(), &mut set) } == 0 { + let count = unsafe { libc::CPU_COUNT(&set) }; + return Ok(unsafe { NonZeroUsize::new_unchecked(count as usize) }); + } + } match unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) } { -1 => Err(io::Error::last_os_error()), 0 => Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")), diff --git a/library/std/src/sys/unix/weak.rs b/library/std/src/sys/unix/weak.rs index ba432ec549..83ff78fa7a 100644 --- a/library/std/src/sys/unix/weak.rs +++ b/library/std/src/sys/unix/weak.rs @@ -28,9 +28,12 @@ use crate::sync::atomic::{self, AtomicUsize, Ordering}; pub(crate) macro weak { (fn $name:ident($($t:ty),*) -> $ret:ty) => ( + weak!(fn $name($($t),*) -> $ret, stringify!($name)); + ), + (fn $name:ident($($t:ty),*) -> $ret:ty, $sym:expr) => ( #[allow(non_upper_case_globals)] static $name: crate::sys::weak::Weak $ret> = - crate::sys::weak::Weak::new(concat!(stringify!($name), '\0')); + crate::sys::weak::Weak::new(concat!($sym, '\0')); ) } diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs index 984dda8dc0..00b9ab3b86 100644 --- a/library/std/src/sys/wasi/fs.rs +++ b/library/std/src/sys/wasi/fs.rs @@ -16,7 +16,7 @@ use crate::sys::time::SystemTime; use crate::sys::unsupported; use crate::sys_common::{AsInner, FromInner, IntoInner}; -pub use crate::sys_common::fs::{remove_dir_all, try_exists}; +pub use crate::sys_common::fs::try_exists; pub struct File { fd: WasiFd, @@ -130,6 +130,18 @@ impl FileType { } } +impl ReadDir { + fn new(dir: File, root: PathBuf) -> ReadDir { + ReadDir { + cookie: Some(0), + buf: vec![0; 128], + offset: 0, + cap: 0, + inner: Arc::new(ReadDirInner { dir, root }), + } + } +} + impl fmt::Debug for ReadDir { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("ReadDir").finish_non_exhaustive() @@ -512,13 +524,7 @@ pub fn readdir(p: &Path) -> io::Result { opts.directory(true); opts.read(true); let dir = File::open(p, &opts)?; - Ok(ReadDir { - cookie: Some(0), - buf: vec![0; 128], - offset: 0, - cap: 0, - inner: Arc::new(ReadDirInner { dir, root: p.to_path_buf() }), - }) + Ok(ReadDir::new(dir, p.to_path_buf())) } pub fn unlink(p: &Path) -> io::Result<()> { @@ -712,3 +718,52 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { io::copy(&mut reader, &mut writer) } + +pub fn remove_dir_all(path: &Path) -> io::Result<()> { + let (parent, path) = open_parent(path)?; + remove_dir_all_recursive(&parent, &path) +} + +fn remove_dir_all_recursive(parent: &WasiFd, path: &Path) -> io::Result<()> { + // Open up a file descriptor for the directory itself. Note that we don't + // follow symlinks here and we specifically open directories. + // + // At the root invocation of this function this will correctly handle + // symlinks passed to the top-level `remove_dir_all`. At the recursive + // level this will double-check that after the `readdir` call deduced this + // was a directory it's still a directory by the time we open it up. + // + // If the opened file was actually a symlink then the symlink is deleted, + // not the directory recursively. + let mut opts = OpenOptions::new(); + opts.lookup_flags(0); + opts.directory(true); + opts.read(true); + let fd = open_at(parent, path, &opts)?; + if fd.file_attr()?.file_type().is_symlink() { + return parent.unlink_file(osstr2str(path.as_ref())?); + } + + // this "root" is only used by `DirEntry::path` which we don't use below so + // it's ok for this to be a bogus value + let dummy_root = PathBuf::new(); + + // Iterate over all the entries in this directory, and travel recursively if + // necessary + for entry in ReadDir::new(fd, dummy_root) { + let entry = entry?; + let path = crate::str::from_utf8(&entry.name).map_err(|_| { + io::Error::new_const(io::ErrorKind::Uncategorized, &"invalid utf-8 file name found") + })?; + + if entry.file_type()?.is_dir() { + remove_dir_all_recursive(&entry.inner.dir.fd, path.as_ref())?; + } else { + entry.inner.dir.fd.unlink_file(path)?; + } + } + + // Once all this directory's contents are deleted it should be safe to + // delete the directory tiself. + parent.remove_directory(osstr2str(path.as_ref())?) +} diff --git a/library/std/src/sys/wasm/alloc.rs b/library/std/src/sys/wasm/alloc.rs index ef0ca3dd47..3223e89410 100644 --- a/library/std/src/sys/wasm/alloc.rs +++ b/library/std/src/sys/wasm/alloc.rs @@ -1,8 +1,8 @@ -//! This is an implementation of a global allocator on the wasm32 platform when +//! This is an implementation of a global allocator on wasm targets when //! emscripten is not in use. In that situation there's no actual runtime for us //! to lean on for allocation, so instead we provide our own! //! -//! The wasm32 instruction set has two instructions for getting the current +//! The wasm instruction set has two instructions for getting the current //! amount of memory and growing the amount of memory. These instructions are the //! foundation on which we're able to build an allocator, so we do so! Note that //! the instructions are also pretty "global" and this is the "global" allocator diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index e5c550802a..1ef6addc11 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -4,6 +4,7 @@ #![cfg_attr(test, allow(dead_code))] #![unstable(issue = "none", feature = "windows_c")] +use crate::mem; use crate::os::raw::NonZero_c_ulong; use crate::os::raw::{c_char, c_int, c_long, c_longlong, c_uint, c_ulong, c_ushort}; use crate::ptr; @@ -36,6 +37,7 @@ pub type USHORT = c_ushort; pub type SIZE_T = usize; pub type WORD = u16; pub type CHAR = c_char; +pub type CCHAR = c_char; pub type ULONG_PTR = usize; pub type ULONG = c_ulong; pub type NTSTATUS = LONG; @@ -86,16 +88,21 @@ pub const FILE_SHARE_DELETE: DWORD = 0x4; pub const FILE_SHARE_READ: DWORD = 0x1; pub const FILE_SHARE_WRITE: DWORD = 0x2; +pub const FILE_OPEN_REPARSE_POINT: ULONG = 0x200000; +pub const OBJ_DONT_REPARSE: ULONG = 0x1000; + pub const CREATE_ALWAYS: DWORD = 2; pub const CREATE_NEW: DWORD = 1; pub const OPEN_ALWAYS: DWORD = 4; pub const OPEN_EXISTING: DWORD = 3; pub const TRUNCATE_EXISTING: DWORD = 5; +pub const FILE_LIST_DIRECTORY: DWORD = 0x1; pub const FILE_WRITE_DATA: DWORD = 0x00000002; pub const FILE_APPEND_DATA: DWORD = 0x00000004; pub const FILE_WRITE_EA: DWORD = 0x00000010; pub const FILE_WRITE_ATTRIBUTES: DWORD = 0x00000100; +pub const DELETE: DWORD = 0x10000; pub const READ_CONTROL: DWORD = 0x00020000; pub const SYNCHRONIZE: DWORD = 0x00100000; pub const GENERIC_READ: DWORD = 0x80000000; @@ -261,9 +268,61 @@ pub const FD_SETSIZE: usize = 64; pub const STACK_SIZE_PARAM_IS_A_RESERVATION: DWORD = 0x00010000; pub const STATUS_SUCCESS: NTSTATUS = 0x00000000; +pub const STATUS_DELETE_PENDING: NTSTATUS = 0xc0000056_u32 as _; +pub const STATUS_INVALID_PARAMETER: NTSTATUS = 0xc000000d_u32 as _; + +// Equivalent to the `NT_SUCCESS` C preprocessor macro. +// See: https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/using-ntstatus-values +pub fn nt_success(status: NTSTATUS) -> bool { + status >= 0 +} pub const BCRYPT_USE_SYSTEM_PREFERRED_RNG: DWORD = 0x00000002; +#[repr(C)] +pub struct UNICODE_STRING { + pub Length: u16, + pub MaximumLength: u16, + pub Buffer: *mut u16, +} +impl UNICODE_STRING { + pub fn from_ref(slice: &[u16]) -> Self { + let len = slice.len() * mem::size_of::(); + Self { Length: len as _, MaximumLength: len as _, Buffer: slice.as_ptr() as _ } + } +} +#[repr(C)] +pub struct OBJECT_ATTRIBUTES { + pub Length: ULONG, + pub RootDirectory: HANDLE, + pub ObjectName: *const UNICODE_STRING, + pub Attributes: ULONG, + pub SecurityDescriptor: *mut c_void, + pub SecurityQualityOfService: *mut c_void, +} +impl Default for OBJECT_ATTRIBUTES { + fn default() -> Self { + Self { + Length: mem::size_of::() as _, + RootDirectory: ptr::null_mut(), + ObjectName: ptr::null_mut(), + Attributes: 0, + SecurityDescriptor: ptr::null_mut(), + SecurityQualityOfService: ptr::null_mut(), + } + } +} +#[repr(C)] +pub struct IO_STATUS_BLOCK { + pub Pointer: *mut c_void, + pub Information: usize, +} +impl Default for IO_STATUS_BLOCK { + fn default() -> Self { + Self { Pointer: ptr::null_mut(), Information: 0 } + } +} + #[repr(C)] #[cfg(not(target_pointer_width = "64"))] pub struct WSADATA { @@ -353,9 +412,43 @@ pub enum FILE_INFO_BY_HANDLE_CLASS { FileIdInfo = 18, // 0x12 FileIdExtdDirectoryInfo = 19, // 0x13 FileIdExtdDirectoryRestartInfo = 20, // 0x14 + FileDispositionInfoEx = 21, // 0x15, Windows 10 version 1607 MaximumFileInfoByHandlesClass, } +#[repr(C)] +pub struct FILE_DISPOSITION_INFO { + pub DeleteFile: BOOLEAN, +} + +pub const FILE_DISPOSITION_DELETE: DWORD = 0x1; +pub const FILE_DISPOSITION_POSIX_SEMANTICS: DWORD = 0x2; +pub const FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE: DWORD = 0x10; + +#[repr(C)] +pub struct FILE_DISPOSITION_INFO_EX { + pub Flags: DWORD, +} + +#[repr(C)] +#[derive(Default)] +pub struct FILE_ID_BOTH_DIR_INFO { + pub NextEntryOffset: DWORD, + pub FileIndex: DWORD, + pub CreationTime: LARGE_INTEGER, + pub LastAccessTime: LARGE_INTEGER, + pub LastWriteTime: LARGE_INTEGER, + pub ChangeTime: LARGE_INTEGER, + pub EndOfFile: LARGE_INTEGER, + pub AllocationSize: LARGE_INTEGER, + pub FileAttributes: DWORD, + pub FileNameLength: DWORD, + pub EaSize: DWORD, + pub ShortNameLength: CCHAR, + pub ShortName: [WCHAR; 12], + pub FileId: LARGE_INTEGER, + pub FileName: [WCHAR; 1], +} #[repr(C)] pub struct FILE_BASIC_INFO { pub CreationTime: LARGE_INTEGER, @@ -734,6 +827,7 @@ if #[cfg(not(target_vendor = "uwp"))] { lpSecurityAttributes: LPSECURITY_ATTRIBUTES, ) -> BOOL; pub fn SetThreadStackGuarantee(_size: *mut c_ulong) -> BOOL; + pub fn GetWindowsDirectoryW(lpBuffer: LPWSTR, uSize: UINT) -> UINT; } } } @@ -749,16 +843,6 @@ if #[cfg(target_vendor = "uwp")] { pub DeletePending: BOOLEAN, pub Directory: BOOLEAN, } - - #[link(name = "kernel32")] - extern "system" { - pub fn GetFileInformationByHandleEx( - hFile: HANDLE, - fileInfoClass: FILE_INFO_BY_HANDLE_CLASS, - lpFileInformation: LPVOID, - dwBufferSize: DWORD, - ) -> BOOL; - } } } @@ -773,6 +857,7 @@ extern "system" { pub fn LeaveCriticalSection(CriticalSection: *mut CRITICAL_SECTION); pub fn DeleteCriticalSection(CriticalSection: *mut CRITICAL_SECTION); + pub fn GetSystemDirectoryW(lpBuffer: LPWSTR, uSize: UINT) -> UINT; pub fn RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL; pub fn SetFileAttributesW(lpFileName: LPCWSTR, dwFileAttributes: DWORD) -> BOOL; pub fn SetLastError(dwErrCode: DWORD); @@ -947,6 +1032,12 @@ extern "system" { cchFilePath: DWORD, dwFlags: DWORD, ) -> DWORD; + pub fn GetFileInformationByHandleEx( + hFile: HANDLE, + fileInfoClass: FILE_INFO_BY_HANDLE_CLASS, + lpFileInformation: LPVOID, + dwBufferSize: DWORD, + ) -> BOOL; pub fn SetFileInformationByHandle( hFile: HANDLE, FileInformationClass: FILE_INFO_BY_HANDLE_CLASS, @@ -977,6 +1068,12 @@ extern "system" { cchCount2: c_int, bIgnoreCase: BOOL, ) -> c_int; + pub fn GetFullPathNameW( + lpFileName: LPCWSTR, + nBufferLength: DWORD, + lpBuffer: LPWSTR, + lpFilePart: *mut LPWSTR, + ) -> DWORD; } #[link(name = "ws2_32")] @@ -1125,6 +1222,21 @@ compat_fn! { compat_fn! { "ntdll": + pub fn NtOpenFile( + FileHandle: *mut HANDLE, + DesiredAccess: ACCESS_MASK, + ObjectAttributes: *const OBJECT_ATTRIBUTES, + IoStatusBlock: *mut IO_STATUS_BLOCK, + ShareAccess: ULONG, + OpenOptions: ULONG + ) -> NTSTATUS { + panic!("`NtOpenFile` not available"); + } + pub fn RtlNtStatusToDosError( + Status: NTSTATUS + ) -> ULONG { + panic!("`RtlNtStatusToDosError` not available"); + } pub fn NtCreateKeyedEvent( KeyedEventHandle: LPHANDLE, DesiredAccess: ACCESS_MASK, diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index ad550a823a..5894c68034 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -14,6 +14,7 @@ use crate::sys::time::SystemTime; use crate::sys::{c, cvt}; use crate::sys_common::{AsInner, FromInner, IntoInner}; +use super::path::maybe_verbatim; use super::to_u16s; pub struct File { @@ -281,7 +282,7 @@ impl OpenOptions { impl File { pub fn open(path: &Path, opts: &OpenOptions) -> io::Result { - let path = to_u16s(path)?; + let path = maybe_verbatim(path)?; let handle = unsafe { c::CreateFileW( path.as_ptr(), @@ -542,6 +543,218 @@ impl File { })?; Ok(()) } + /// Get only basic file information such as attributes and file times. + fn basic_info(&self) -> io::Result { + unsafe { + let mut info: c::FILE_BASIC_INFO = mem::zeroed(); + let size = mem::size_of_val(&info); + cvt(c::GetFileInformationByHandleEx( + self.handle.as_raw_handle(), + c::FileBasicInfo, + &mut info as *mut _ as *mut libc::c_void, + size as c::DWORD, + ))?; + Ok(info) + } + } + /// Delete using POSIX semantics. + /// + /// Files will be deleted as soon as the handle is closed. This is supported + /// for Windows 10 1607 (aka RS1) and later. However some filesystem + /// drivers will not support it even then, e.g. FAT32. + /// + /// If the operation is not supported for this filesystem or OS version + /// then errors will be `ERROR_NOT_SUPPORTED` or `ERROR_INVALID_PARAMETER`. + fn posix_delete(&self) -> io::Result<()> { + let mut info = c::FILE_DISPOSITION_INFO_EX { + Flags: c::FILE_DISPOSITION_DELETE + | c::FILE_DISPOSITION_POSIX_SEMANTICS + | c::FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE, + }; + let size = mem::size_of_val(&info); + cvt(unsafe { + c::SetFileInformationByHandle( + self.handle.as_raw_handle(), + c::FileDispositionInfoEx, + &mut info as *mut _ as *mut _, + size as c::DWORD, + ) + })?; + Ok(()) + } + + /// Delete a file using win32 semantics. The file won't actually be deleted + /// until all file handles are closed. However, marking a file for deletion + /// will prevent anyone from opening a new handle to the file. + fn win32_delete(&self) -> io::Result<()> { + let mut info = c::FILE_DISPOSITION_INFO { DeleteFile: c::TRUE as _ }; + let size = mem::size_of_val(&info); + cvt(unsafe { + c::SetFileInformationByHandle( + self.handle.as_raw_handle(), + c::FileDispositionInfo, + &mut info as *mut _ as *mut _, + size as c::DWORD, + ) + })?; + Ok(()) + } + + /// Fill the given buffer with as many directory entries as will fit. + /// This will remember its position and continue from the last call unless + /// `restart` is set to `true`. + /// + /// The returned bool indicates if there are more entries or not. + /// It is an error if `self` is not a directory. + /// + /// # Symlinks and other reparse points + /// + /// On Windows a file is either a directory or a non-directory. + /// A symlink directory is simply an empty directory with some "reparse" metadata attached. + /// So if you open a link (not its target) and iterate the directory, + /// you will always iterate an empty directory regardless of the target. + fn fill_dir_buff(&self, buffer: &mut DirBuff, restart: bool) -> io::Result { + let class = + if restart { c::FileIdBothDirectoryRestartInfo } else { c::FileIdBothDirectoryInfo }; + + unsafe { + let result = cvt(c::GetFileInformationByHandleEx( + self.handle.as_raw_handle(), + class, + buffer.as_mut_ptr().cast(), + buffer.capacity() as _, + )); + match result { + Ok(_) => Ok(true), + Err(e) if e.raw_os_error() == Some(c::ERROR_NO_MORE_FILES as _) => Ok(false), + Err(e) => Err(e), + } + } + } +} + +/// A buffer for holding directory entries. +struct DirBuff { + buffer: Vec, +} +impl DirBuff { + fn new() -> Self { + const BUFFER_SIZE: usize = 1024; + Self { buffer: vec![0_u8; BUFFER_SIZE] } + } + fn capacity(&self) -> usize { + self.buffer.len() + } + fn as_mut_ptr(&mut self) -> *mut u8 { + self.buffer.as_mut_ptr().cast() + } + /// Returns a `DirBuffIter`. + fn iter(&self) -> DirBuffIter<'_> { + DirBuffIter::new(self) + } +} +impl AsRef<[u8]> for DirBuff { + fn as_ref(&self) -> &[u8] { + &self.buffer + } +} + +/// An iterator over entries stored in a `DirBuff`. +/// +/// Currently only returns file names (UTF-16 encoded). +struct DirBuffIter<'a> { + buffer: Option<&'a [u8]>, + cursor: usize, +} +impl<'a> DirBuffIter<'a> { + fn new(buffer: &'a DirBuff) -> Self { + Self { buffer: Some(buffer.as_ref()), cursor: 0 } + } +} +impl<'a> Iterator for DirBuffIter<'a> { + type Item = &'a [u16]; + fn next(&mut self) -> Option { + use crate::mem::size_of; + let buffer = &self.buffer?[self.cursor..]; + + // Get the name and next entry from the buffer. + // SAFETY: The buffer contains a `FILE_ID_BOTH_DIR_INFO` struct but the + // last field (the file name) is unsized. So an offset has to be + // used to get the file name slice. + let (name, next_entry) = unsafe { + let info = buffer.as_ptr().cast::(); + let next_entry = (*info).NextEntryOffset as usize; + let name = crate::slice::from_raw_parts( + (*info).FileName.as_ptr().cast::(), + (*info).FileNameLength as usize / size_of::(), + ); + (name, next_entry) + }; + + if next_entry == 0 { + self.buffer = None + } else { + self.cursor += next_entry + } + + // Skip `.` and `..` pseudo entries. + const DOT: u16 = b'.' as u16; + match name { + [DOT] | [DOT, DOT] => self.next(), + _ => Some(name), + } + } +} + +/// Open a link relative to the parent directory, ensure no symlinks are followed. +fn open_link_no_reparse(parent: &File, name: &[u16], access: u32) -> io::Result { + // This is implemented using the lower level `NtOpenFile` function as + // unfortunately opening a file relative to a parent is not supported by + // win32 functions. It is however a fundamental feature of the NT kernel. + // + // See https://docs.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntopenfile + unsafe { + let mut handle = ptr::null_mut(); + let mut io_status = c::IO_STATUS_BLOCK::default(); + let name_str = c::UNICODE_STRING::from_ref(name); + use crate::sync::atomic::{AtomicU32, Ordering}; + // The `OBJ_DONT_REPARSE` attribute ensures that we haven't been + // tricked into following a symlink. However, it may not be available in + // earlier versions of Windows. + static ATTRIBUTES: AtomicU32 = AtomicU32::new(c::OBJ_DONT_REPARSE); + let object = c::OBJECT_ATTRIBUTES { + ObjectName: &name_str, + RootDirectory: parent.as_raw_handle(), + Attributes: ATTRIBUTES.load(Ordering::Relaxed), + ..c::OBJECT_ATTRIBUTES::default() + }; + let status = c::NtOpenFile( + &mut handle, + access, + &object, + &mut io_status, + c::FILE_SHARE_DELETE | c::FILE_SHARE_READ | c::FILE_SHARE_WRITE, + // If `name` is a symlink then open the link rather than the target. + c::FILE_OPEN_REPARSE_POINT, + ); + // Convert an NTSTATUS to the more familiar Win32 error codes (aka "DosError") + if c::nt_success(status) { + Ok(File::from_raw_handle(handle)) + } else if status == c::STATUS_DELETE_PENDING { + // We make a special exception for `STATUS_DELETE_PENDING` because + // otherwise this will be mapped to `ERROR_ACCESS_DENIED` which is + // very unhelpful. + Err(io::Error::from_raw_os_error(c::ERROR_DELETE_PENDING as _)) + } else if status == c::STATUS_INVALID_PARAMETER + && ATTRIBUTES.load(Ordering::Relaxed) == c::OBJ_DONT_REPARSE + { + // Try without `OBJ_DONT_REPARSE`. See above. + ATTRIBUTES.store(0, Ordering::Relaxed); + open_link_no_reparse(parent, name, access) + } else { + Err(io::Error::from_raw_os_error(c::RtlNtStatusToDosError(status) as _)) + } + } } impl AsInner for File { @@ -706,7 +919,7 @@ impl DirBuilder { } pub fn mkdir(&self, p: &Path) -> io::Result<()> { - let p = to_u16s(p)?; + let p = maybe_verbatim(p)?; cvt(unsafe { c::CreateDirectoryW(p.as_ptr(), ptr::null_mut()) })?; Ok(()) } @@ -715,7 +928,7 @@ impl DirBuilder { pub fn readdir(p: &Path) -> io::Result { let root = p.to_path_buf(); let star = p.join("*"); - let path = to_u16s(&star)?; + let path = maybe_verbatim(&star)?; unsafe { let mut wfd = mem::zeroed(); @@ -733,48 +946,124 @@ pub fn readdir(p: &Path) -> io::Result { } pub fn unlink(p: &Path) -> io::Result<()> { - let p_u16s = to_u16s(p)?; + let p_u16s = maybe_verbatim(p)?; cvt(unsafe { c::DeleteFileW(p_u16s.as_ptr()) })?; Ok(()) } pub fn rename(old: &Path, new: &Path) -> io::Result<()> { - let old = to_u16s(old)?; - let new = to_u16s(new)?; + let old = maybe_verbatim(old)?; + let new = maybe_verbatim(new)?; cvt(unsafe { c::MoveFileExW(old.as_ptr(), new.as_ptr(), c::MOVEFILE_REPLACE_EXISTING) })?; Ok(()) } pub fn rmdir(p: &Path) -> io::Result<()> { - let p = to_u16s(p)?; + let p = maybe_verbatim(p)?; cvt(unsafe { c::RemoveDirectoryW(p.as_ptr()) })?; Ok(()) } +/// Open a file or directory without following symlinks. +fn open_link(path: &Path, access_mode: u32) -> io::Result { + let mut opts = OpenOptions::new(); + opts.access_mode(access_mode); + // `FILE_FLAG_BACKUP_SEMANTICS` allows opening directories. + // `FILE_FLAG_OPEN_REPARSE_POINT` opens a link instead of its target. + opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS | c::FILE_FLAG_OPEN_REPARSE_POINT); + File::open(path, &opts) +} + pub fn remove_dir_all(path: &Path) -> io::Result<()> { - let filetype = lstat(path)?.file_type(); - if filetype.is_symlink() { - // On Windows symlinks to files and directories are removed differently. - // rmdir only deletes dir symlinks and junctions, not file symlinks. - rmdir(path) + let file = open_link(path, c::DELETE | c::FILE_LIST_DIRECTORY)?; + + // Test if the file is not a directory or a symlink to a directory. + if (file.basic_info()?.FileAttributes & c::FILE_ATTRIBUTE_DIRECTORY) == 0 { + return Err(io::Error::from_raw_os_error(c::ERROR_DIRECTORY as _)); + } + let mut delete: fn(&File) -> io::Result<()> = File::posix_delete; + let result = match delete(&file) { + Err(e) if e.kind() == io::ErrorKind::DirectoryNotEmpty => { + match remove_dir_all_recursive(&file, delete) { + // Return unexpected errors. + Err(e) if e.kind() != io::ErrorKind::DirectoryNotEmpty => return Err(e), + result => result, + } + } + // If POSIX delete is not supported for this filesystem then fallback to win32 delete. + Err(e) + if e.raw_os_error() == Some(c::ERROR_NOT_SUPPORTED as i32) + || e.raw_os_error() == Some(c::ERROR_INVALID_PARAMETER as i32) => + { + delete = File::win32_delete; + Err(e) + } + result => result, + }; + if result.is_ok() { + Ok(()) } else { - remove_dir_all_recursive(path) + // This is a fallback to make sure the directory is actually deleted. + // Otherwise this function is prone to failing with `DirectoryNotEmpty` + // due to possible delays between marking a file for deletion and the + // file actually being deleted from the filesystem. + // + // So we retry a few times before giving up. + for _ in 0..5 { + match remove_dir_all_recursive(&file, delete) { + Err(e) if e.kind() == io::ErrorKind::DirectoryNotEmpty => {} + result => return result, + } + } + // Try one last time. + delete(&file) } } -fn remove_dir_all_recursive(path: &Path) -> io::Result<()> { - for child in readdir(path)? { - let child = child?; - let child_type = child.file_type()?; - if child_type.is_dir() { - remove_dir_all_recursive(&child.path())?; - } else if child_type.is_symlink_dir() { - rmdir(&child.path())?; - } else { - unlink(&child.path())?; +fn remove_dir_all_recursive(f: &File, delete: fn(&File) -> io::Result<()>) -> io::Result<()> { + let mut buffer = DirBuff::new(); + let mut restart = true; + // Fill the buffer and iterate the entries. + while f.fill_dir_buff(&mut buffer, restart)? { + for name in buffer.iter() { + // Open the file without following symlinks and try deleting it. + // We try opening will all needed permissions and if that is denied + // fallback to opening without `FILE_LIST_DIRECTORY` permission. + // Note `SYNCHRONIZE` permission is needed for synchronous access. + let mut result = + open_link_no_reparse(&f, name, c::SYNCHRONIZE | c::DELETE | c::FILE_LIST_DIRECTORY); + if matches!(&result, Err(e) if e.kind() == io::ErrorKind::PermissionDenied) { + result = open_link_no_reparse(&f, name, c::SYNCHRONIZE | c::DELETE); + } + match result { + Ok(file) => match delete(&file) { + Err(e) if e.kind() == io::ErrorKind::DirectoryNotEmpty => { + // Iterate the directory's files. + // Ignore `DirectoryNotEmpty` errors here. They will be + // caught when `remove_dir_all` tries to delete the top + // level directory. It can then decide if to retry or not. + match remove_dir_all_recursive(&file, delete) { + Err(e) if e.kind() == io::ErrorKind::DirectoryNotEmpty => {} + result => result?, + } + } + result => result?, + }, + // Ignore error if a delete is already in progress or the file + // has already been deleted. It also ignores sharing violations + // (where a file is locked by another process) as these are + // usually temporary. + Err(e) + if e.raw_os_error() == Some(c::ERROR_DELETE_PENDING as _) + || e.kind() == io::ErrorKind::NotFound + || e.raw_os_error() == Some(c::ERROR_SHARING_VIOLATION as _) => {} + Err(e) => return Err(e), + } } + // Continue reading directory entries without restarting from the beginning, + restart = false; } - rmdir(path) + delete(&f) } pub fn readlink(path: &Path) -> io::Result { @@ -794,7 +1083,7 @@ pub fn symlink(original: &Path, link: &Path) -> io::Result<()> { pub fn symlink_inner(original: &Path, link: &Path, dir: bool) -> io::Result<()> { let original = to_u16s(original)?; - let link = to_u16s(link)?; + let link = maybe_verbatim(link)?; let flags = if dir { c::SYMBOLIC_LINK_FLAG_DIRECTORY } else { 0 }; // Formerly, symlink creation required the SeCreateSymbolicLink privilege. For the Windows 10 // Creators Update, Microsoft loosened this to allow unprivileged symlink creation if the @@ -823,8 +1112,8 @@ pub fn symlink_inner(original: &Path, link: &Path, dir: bool) -> io::Result<()> #[cfg(not(target_vendor = "uwp"))] pub fn link(original: &Path, link: &Path) -> io::Result<()> { - let original = to_u16s(original)?; - let link = to_u16s(link)?; + let original = maybe_verbatim(original)?; + let link = maybe_verbatim(link)?; cvt(unsafe { c::CreateHardLinkW(link.as_ptr(), original.as_ptr(), ptr::null_mut()) })?; Ok(()) } @@ -857,7 +1146,7 @@ pub fn lstat(path: &Path) -> io::Result { } pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> { - let p = to_u16s(p)?; + let p = maybe_verbatim(p)?; unsafe { cvt(c::SetFileAttributesW(p.as_ptr(), perm.attrs))?; Ok(()) @@ -900,8 +1189,8 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { } c::PROGRESS_CONTINUE } - let pfrom = to_u16s(from)?; - let pto = to_u16s(to)?; + let pfrom = maybe_verbatim(from)?; + let pto = maybe_verbatim(to)?; let mut size = 0i64; cvt(unsafe { c::CopyFileExW( diff --git a/library/std/src/sys/windows/os.rs b/library/std/src/sys/windows/os.rs index 883690c483..b5209aa690 100644 --- a/library/std/src/sys/windows/os.rs +++ b/library/std/src/sys/windows/os.rs @@ -281,6 +281,10 @@ pub fn temp_dir() -> PathBuf { #[cfg(not(target_vendor = "uwp"))] fn home_dir_crt() -> Option { unsafe { + // The magic constant -4 can be used as the token passed to GetUserProfileDirectoryW below + // instead of us having to go through these multiple steps to get a token. However this is + // not implemented on Windows 7, only Windows 8 and up. When we drop support for Windows 7 + // we can simplify this code. See #90144 for details. use crate::sys::handle::Handle; let me = c::GetCurrentProcess(); diff --git a/library/std/src/sys/windows/path.rs b/library/std/src/sys/windows/path.rs index b8f512f6a2..79e0eaf6c3 100644 --- a/library/std/src/sys/windows/path.rs +++ b/library/std/src/sys/windows/path.rs @@ -1,6 +1,9 @@ -use crate::ffi::OsStr; +use super::{c, fill_utf16_buf, to_u16s}; +use crate::ffi::{OsStr, OsString}; +use crate::io; use crate::mem; -use crate::path::Prefix; +use crate::path::{Path, PathBuf, Prefix}; +use crate::ptr; #[cfg(test)] mod tests; @@ -28,6 +31,25 @@ pub fn is_verbatim_sep(b: u8) -> bool { b == b'\\' } +/// Returns true if `path` looks like a lone filename. +pub(crate) fn is_file_name(path: &OsStr) -> bool { + !path.bytes().iter().copied().any(is_sep_byte) +} +pub(crate) fn has_trailing_slash(path: &OsStr) -> bool { + let is_verbatim = path.bytes().starts_with(br"\\?\"); + let is_separator = if is_verbatim { is_verbatim_sep } else { is_sep_byte }; + if let Some(&c) = path.bytes().last() { is_separator(c) } else { false } +} + +/// Appends a suffix to a path. +/// +/// Can be used to append an extension without removing an existing extension. +pub(crate) fn append_suffix(path: PathBuf, suffix: &OsStr) -> PathBuf { + let mut path = OsString::from(path); + path.push(suffix); + path.into() +} + pub fn parse_prefix(path: &OsStr) -> Option> { use Prefix::{DeviceNS, Disk, Verbatim, VerbatimDisk, VerbatimUNC, UNC}; @@ -141,3 +163,100 @@ fn parse_next_component(path: &OsStr, verbatim: bool) -> (&OsStr, &OsStr) { None => (path, OsStr::new("")), } } + +/// Returns a UTF-16 encoded path capable of bypassing the legacy `MAX_PATH` limits. +/// +/// This path may or may not have a verbatim prefix. +pub(crate) fn maybe_verbatim(path: &Path) -> io::Result> { + // Normally the MAX_PATH is 260 UTF-16 code units (including the NULL). + // However, for APIs such as CreateDirectory[1], the limit is 248. + // + // [1]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createdirectorya#parameters + const LEGACY_MAX_PATH: usize = 248; + // UTF-16 encoded code points, used in parsing and building UTF-16 paths. + // All of these are in the ASCII range so they can be cast directly to `u16`. + const SEP: u16 = b'\\' as _; + const ALT_SEP: u16 = b'/' as _; + const QUERY: u16 = b'?' as _; + const COLON: u16 = b':' as _; + const DOT: u16 = b'.' as _; + const U: u16 = b'U' as _; + const N: u16 = b'N' as _; + const C: u16 = b'C' as _; + + // \\?\ + const VERBATIM_PREFIX: &[u16] = &[SEP, SEP, QUERY, SEP]; + // \??\ + const NT_PREFIX: &[u16] = &[SEP, QUERY, QUERY, SEP]; + // \\?\UNC\ + const UNC_PREFIX: &[u16] = &[SEP, SEP, QUERY, SEP, U, N, C, SEP]; + + let mut path = to_u16s(path)?; + if path.starts_with(VERBATIM_PREFIX) || path.starts_with(NT_PREFIX) || path == &[0] { + // Early return for paths that are already verbatim or empty. + return Ok(path); + } else if path.len() < LEGACY_MAX_PATH { + // Early return if an absolute path is less < 260 UTF-16 code units. + // This is an optimization to avoid calling `GetFullPathNameW` unnecessarily. + match path.as_slice() { + // Starts with `D:`, `D:\`, `D:/`, etc. + // Does not match if the path starts with a `\` or `/`. + [drive, COLON, 0] | [drive, COLON, SEP | ALT_SEP, ..] + if *drive != SEP && *drive != ALT_SEP => + { + return Ok(path); + } + // Starts with `\\`, `//`, etc + [SEP | ALT_SEP, SEP | ALT_SEP, ..] => return Ok(path), + _ => {} + } + } + + // Firstly, get the absolute path using `GetFullPathNameW`. + // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfullpathnamew + let lpfilename = path.as_ptr(); + fill_utf16_buf( + // SAFETY: `fill_utf16_buf` ensures the `buffer` and `size` are valid. + // `lpfilename` is a pointer to a null terminated string that is not + // invalidated until after `GetFullPathNameW` returns successfully. + |buffer, size| unsafe { + // While the docs for `GetFullPathNameW` have the standard note + // about needing a `\\?\` path for a long lpfilename, this does not + // appear to be true in practice. + // See: + // https://stackoverflow.com/questions/38036943/getfullpathnamew-and-long-windows-file-paths + // https://googleprojectzero.blogspot.com/2016/02/the-definitive-guide-on-win32-to-nt.html + c::GetFullPathNameW(lpfilename, size, buffer, ptr::null_mut()) + }, + |mut absolute| { + path.clear(); + + // Secondly, add the verbatim prefix. This is easier here because we know the + // path is now absolute and fully normalized (e.g. `/` has been changed to `\`). + let prefix = match absolute { + // C:\ => \\?\C:\ + [_, COLON, SEP, ..] => VERBATIM_PREFIX, + // \\.\ => \\?\ + [SEP, SEP, DOT, SEP, ..] => { + absolute = &absolute[4..]; + VERBATIM_PREFIX + } + // Leave \\?\ and \??\ as-is. + [SEP, SEP, QUERY, SEP, ..] | [SEP, QUERY, QUERY, SEP, ..] => &[], + // \\ => \\?\UNC\ + [SEP, SEP, ..] => { + absolute = &absolute[2..]; + UNC_PREFIX + } + // Anything else we leave alone. + _ => &[], + }; + + path.reserve_exact(prefix.len() + absolute.len() + 1); + path.extend_from_slice(prefix); + path.extend_from_slice(absolute); + path.push(0); + }, + )?; + Ok(path) +} diff --git a/library/std/src/sys/windows/path/tests.rs b/library/std/src/sys/windows/path/tests.rs index 9675da6ff8..425c2011b3 100644 --- a/library/std/src/sys/windows/path/tests.rs +++ b/library/std/src/sys/windows/path/tests.rs @@ -42,3 +42,55 @@ fn test_parse_next_component() { (OsStr::new(r"server"), OsStr::new(r"\\\\\\\\\\\\\share")) ); } + +#[test] +fn verbatim() { + use crate::path::Path; + fn check(path: &str, expected: &str) { + let verbatim = maybe_verbatim(Path::new(path)).unwrap(); + let verbatim = String::from_utf16_lossy(verbatim.strip_suffix(&[0]).unwrap()); + assert_eq!(&verbatim, expected, "{}", path); + } + + // Ensure long paths are correctly prefixed. + check( + r"C:\Program Files\Rust\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\foo.txt", + r"\\?\C:\Program Files\Rust\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\foo.txt", + ); + check( + r"\\server\share\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\foo.txt", + r"\\?\UNC\server\share\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\foo.txt", + ); + check( + r"\\.\PIPE\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\foo.txt", + r"\\?\PIPE\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\foo.txt", + ); + // `\\?\` prefixed paths are left unchanged... + check( + r"\\?\verbatim.\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\foo.txt", + r"\\?\verbatim.\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\foo.txt", + ); + // But `//?/` is not a verbatim prefix so it will be normalized. + check( + r"//?/E:/verbatim.\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\foo.txt", + r"\\?\E:\verbatim\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\foo.txt", + ); + + // For performance, short absolute paths are left unchanged. + check(r"C:\Program Files\Rust", r"C:\Program Files\Rust"); + check(r"\\server\share", r"\\server\share"); + check(r"\\.\COM1", r"\\.\COM1"); + + // Check that paths of length 247 are converted to verbatim. + // This is necessary for `CreateDirectory`. + check( + r"C:\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + r"\\?\C:\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + ); + + // Make sure opening a drive will work. + check("Z:", "Z:"); + + // A path that contains null is not a valid path. + assert!(maybe_verbatim(Path::new("\0")).is_err()); +} diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs index ccff90629a..e84dfbce4a 100644 --- a/library/std/src/sys/windows/process.rs +++ b/library/std/src/sys/windows/process.rs @@ -7,24 +7,24 @@ use crate::cmp; use crate::collections::BTreeMap; use crate::convert::{TryFrom, TryInto}; use crate::env; -use crate::env::split_paths; +use crate::env::consts::{EXE_EXTENSION, EXE_SUFFIX}; use crate::ffi::{OsStr, OsString}; use crate::fmt; -use crate::fs; use crate::io::{self, Error, ErrorKind}; use crate::mem; use crate::num::NonZeroI32; -use crate::os::windows::ffi::OsStrExt; +use crate::os::windows::ffi::{OsStrExt, OsStringExt}; use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle}; -use crate::path::Path; +use crate::path::{Path, PathBuf}; use crate::ptr; use crate::sys::c; use crate::sys::c::NonZeroDWORD; -use crate::sys::cvt; use crate::sys::fs::{File, OpenOptions}; use crate::sys::handle::Handle; +use crate::sys::path; use crate::sys::pipe::{self, AnonPipe}; use crate::sys::stdio; +use crate::sys::{cvt, to_u16s}; use crate::sys_common::mutex::StaticMutex; use crate::sys_common::process::{CommandEnv, CommandEnvs}; use crate::sys_common::{AsInner, IntoInner}; @@ -258,31 +258,19 @@ impl Command { needs_stdin: bool, ) -> io::Result<(Process, StdioPipes)> { let maybe_env = self.env.capture_if_changed(); - // To have the spawning semantics of unix/windows stay the same, we need - // to read the *child's* PATH if one is provided. See #15149 for more - // details. - let program = maybe_env.as_ref().and_then(|env| { - if let Some(v) = env.get(&EnvKey::new("PATH")) { - // Split the value and test each path to see if the - // program exists. - for path in split_paths(&v) { - let path = path - .join(self.program.to_str().unwrap()) - .with_extension(env::consts::EXE_EXTENSION); - if fs::metadata(&path).is_ok() { - return Some(path.into_os_string()); - } - } - } - None - }); let mut si = zeroed_startupinfo(); si.cb = mem::size_of::() as c::DWORD; si.dwFlags = c::STARTF_USESTDHANDLES; - let program = program.as_ref().unwrap_or(&self.program); - let mut cmd_str = make_command_line(program, &self.args, self.force_quotes_enabled)?; + let child_paths = if let Some(env) = maybe_env.as_ref() { + env.get(&EnvKey::new("PATH")).map(|s| s.as_os_str()) + } else { + None + }; + let program = resolve_exe(&self.program, child_paths)?; + let mut cmd_str = + make_command_line(program.as_os_str(), &self.args, self.force_quotes_enabled)?; cmd_str.push(0); // add null terminator // stolen from the libuv code. @@ -321,9 +309,10 @@ impl Command { si.hStdOutput = stdout.as_raw_handle(); si.hStdError = stderr.as_raw_handle(); + let program = to_u16s(&program)?; unsafe { cvt(c::CreateProcessW( - ptr::null(), + program.as_ptr(), cmd_str.as_mut_ptr(), ptr::null_mut(), ptr::null_mut(), @@ -361,6 +350,132 @@ impl fmt::Debug for Command { } } +// Resolve `exe_path` to the executable name. +// +// * If the path is simply a file name then use the paths given by `search_paths` to find the executable. +// * Otherwise use the `exe_path` as given. +// +// This function may also append `.exe` to the name. The rationale for doing so is as follows: +// +// It is a very strong convention that Windows executables have the `exe` extension. +// In Rust, it is common to omit this extension. +// Therefore this functions first assumes `.exe` was intended. +// It falls back to the plain file name if a full path is given and the extension is omitted +// or if only a file name is given and it already contains an extension. +fn resolve_exe<'a>(exe_path: &'a OsStr, child_paths: Option<&OsStr>) -> io::Result { + // Early return if there is no filename. + if exe_path.is_empty() || path::has_trailing_slash(exe_path) { + return Err(io::Error::new_const( + io::ErrorKind::InvalidInput, + &"program path has no file name", + )); + } + // Test if the file name has the `exe` extension. + // This does a case-insensitive `ends_with`. + let has_exe_suffix = if exe_path.len() >= EXE_SUFFIX.len() { + exe_path.bytes()[exe_path.len() - EXE_SUFFIX.len()..] + .eq_ignore_ascii_case(EXE_SUFFIX.as_bytes()) + } else { + false + }; + + // If `exe_path` is an absolute path or a sub-path then don't search `PATH` for it. + if !path::is_file_name(exe_path) { + if has_exe_suffix { + // The application name is a path to a `.exe` file. + // Let `CreateProcessW` figure out if it exists or not. + return Ok(exe_path.into()); + } + let mut path = PathBuf::from(exe_path); + + // Append `.exe` if not already there. + path = path::append_suffix(path, EXE_SUFFIX.as_ref()); + if path.try_exists().unwrap_or(false) { + return Ok(path); + } else { + // It's ok to use `set_extension` here because the intent is to + // remove the extension that was just added. + path.set_extension(""); + return Ok(path); + } + } else { + ensure_no_nuls(exe_path)?; + // From the `CreateProcessW` docs: + // > If the file name does not contain an extension, .exe is appended. + // Note that this rule only applies when searching paths. + let has_extension = exe_path.bytes().contains(&b'.'); + + // Search the directories given by `search_paths`. + let result = search_paths(child_paths, |mut path| { + path.push(&exe_path); + if !has_extension { + path.set_extension(EXE_EXTENSION); + } + if let Ok(true) = path.try_exists() { Some(path) } else { None } + }); + if let Some(path) = result { + return Ok(path); + } + } + // If we get here then the executable cannot be found. + Err(io::Error::new_const(io::ErrorKind::NotFound, &"program not found")) +} + +// Calls `f` for every path that should be used to find an executable. +// Returns once `f` returns the path to an executable or all paths have been searched. +fn search_paths(child_paths: Option<&OsStr>, mut f: F) -> Option +where + F: FnMut(PathBuf) -> Option, +{ + // 1. Child paths + // This is for consistency with Rust's historic behaviour. + if let Some(paths) = child_paths { + for path in env::split_paths(paths).filter(|p| !p.as_os_str().is_empty()) { + if let Some(path) = f(path) { + return Some(path); + } + } + } + + // 2. Application path + if let Ok(mut app_path) = env::current_exe() { + app_path.pop(); + if let Some(path) = f(app_path) { + return Some(path); + } + } + + // 3 & 4. System paths + // SAFETY: This uses `fill_utf16_buf` to safely call the OS functions. + unsafe { + if let Ok(Some(path)) = super::fill_utf16_buf( + |buf, size| c::GetSystemDirectoryW(buf, size), + |buf| f(PathBuf::from(OsString::from_wide(buf))), + ) { + return Some(path); + } + #[cfg(not(target_vendor = "uwp"))] + { + if let Ok(Some(path)) = super::fill_utf16_buf( + |buf, size| c::GetWindowsDirectoryW(buf, size), + |buf| f(PathBuf::from(OsString::from_wide(buf))), + ) { + return Some(path); + } + } + } + + // 5. Parent paths + if let Some(parent_paths) = env::var_os("PATH") { + for path in env::split_paths(&parent_paths).filter(|p| !p.as_os_str().is_empty()) { + if let Some(path) = f(path) { + return Some(path); + } + } + } + None +} + impl Stdio { fn to_handle(&self, stdio_id: c::DWORD, pipe: &mut Option) -> io::Result { match *self { @@ -589,6 +704,19 @@ fn make_command_line(prog: &OsStr, args: &[Arg], force_quotes: bool) -> io::Resu // Encode the command and arguments in a command line string such // that the spawned process may recover them using CommandLineToArgvW. let mut cmd: Vec = Vec::new(); + + // CreateFileW has special handling for .bat and .cmd files, which means we + // need to add an extra pair of quotes surrounding the whole command line + // so they are properly passed on to the script. + // See issue #91991. + let is_batch_file = Path::new(prog) + .extension() + .map(|ext| ext.eq_ignore_ascii_case("cmd") || ext.eq_ignore_ascii_case("bat")) + .unwrap_or(false); + if is_batch_file { + cmd.push(b'"' as u16); + } + // Always quote the program name so CreateProcess doesn't interpret args as // part of the name if the binary wasn't found first time. append_arg(&mut cmd, prog, Quote::Always)?; @@ -600,6 +728,9 @@ fn make_command_line(prog: &OsStr, args: &[Arg], force_quotes: bool) -> io::Resu }; append_arg(&mut cmd, arg, quote)?; } + if is_batch_file { + cmd.push(b'"' as u16); + } return Ok(cmd); fn append_arg(cmd: &mut Vec, arg: &OsStr, quote: Quote) -> io::Result<()> { diff --git a/library/std/src/sys/windows/process/tests.rs b/library/std/src/sys/windows/process/tests.rs index 3b65856dca..6159a679c0 100644 --- a/library/std/src/sys/windows/process/tests.rs +++ b/library/std/src/sys/windows/process/tests.rs @@ -128,3 +128,59 @@ fn windows_env_unicode_case() { } } } + +// UWP applications run in a restricted environment which means this test may not work. +#[cfg(not(target_vendor = "uwp"))] +#[test] +fn windows_exe_resolver() { + use super::resolve_exe; + use crate::io; + + // Test a full path, with and without the `exe` extension. + let mut current_exe = env::current_exe().unwrap(); + assert!(resolve_exe(current_exe.as_ref(), None).is_ok()); + current_exe.set_extension(""); + assert!(resolve_exe(current_exe.as_ref(), None).is_ok()); + + // Test lone file names. + assert!(resolve_exe(OsStr::new("cmd"), None).is_ok()); + assert!(resolve_exe(OsStr::new("cmd.exe"), None).is_ok()); + assert!(resolve_exe(OsStr::new("cmd.EXE"), None).is_ok()); + assert!(resolve_exe(OsStr::new("fc"), None).is_ok()); + + // Invalid file names should return InvalidInput. + assert_eq!(resolve_exe(OsStr::new(""), None).unwrap_err().kind(), io::ErrorKind::InvalidInput); + assert_eq!( + resolve_exe(OsStr::new("\0"), None).unwrap_err().kind(), + io::ErrorKind::InvalidInput + ); + // Trailing slash, therefore there's no file name component. + assert_eq!( + resolve_exe(OsStr::new(r"C:\Path\to\"), None).unwrap_err().kind(), + io::ErrorKind::InvalidInput + ); + + /* FIXME: fix and re-enable these tests before making changes to the resolver. + + /* + Some of the following tests may need to be changed if you are deliberately + changing the behaviour of `resolve_exe`. + */ + + let paths = env::var_os("PATH").unwrap(); + env::set_var("PATH", ""); + + assert_eq!(resolve_exe(OsStr::new("rustc"), None).unwrap_err().kind(), io::ErrorKind::NotFound); + + let child_paths = Some(paths.as_os_str()); + assert!(resolve_exe(OsStr::new("rustc"), child_paths).is_ok()); + + // The resolver looks in system directories even when `PATH` is empty. + assert!(resolve_exe(OsStr::new("cmd.exe"), None).is_ok()); + + // The application's directory is also searched. + let current_exe = env::current_exe().unwrap(); + assert!(resolve_exe(current_exe.file_name().unwrap().as_ref(), None).is_ok()); + + */ +} diff --git a/library/std/src/sys/windows/thread_local_dtor.rs b/library/std/src/sys/windows/thread_local_dtor.rs index 7be13bc4b2..25d1c6e8e8 100644 --- a/library/std/src/sys/windows/thread_local_dtor.rs +++ b/library/std/src/sys/windows/thread_local_dtor.rs @@ -1,4 +1,28 @@ +//! Implements thread-local destructors that are not associated with any +//! particular data. + #![unstable(feature = "thread_local_internals", issue = "none")] #![cfg(target_thread_local)] -pub use crate::sys_common::thread_local_dtor::register_dtor_fallback as register_dtor; +// Using a per-thread list avoids the problems in synchronizing global state. +#[thread_local] +static mut DESTRUCTORS: Vec<(*mut u8, unsafe extern "C" fn(*mut u8))> = Vec::new(); + +pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { + DESTRUCTORS.push((t, dtor)); +} + +/// Runs destructors. This should not be called until thread exit. +pub unsafe fn run_keyless_dtors() { + // Drop all the destructors. + // + // Note: While this is potentially an infinite loop, it *should* be + // the case that this loop always terminates because we provide the + // guarantee that a TLS key cannot be set after it is flagged for + // destruction. + while let Some((ptr, dtor)) = DESTRUCTORS.pop() { + (dtor)(ptr); + } + // We're done so free the memory. + DESTRUCTORS = Vec::new(); +} diff --git a/library/std/src/sys/windows/thread_local_key.rs b/library/std/src/sys/windows/thread_local_key.rs index 0bc5111466..ec670238e6 100644 --- a/library/std/src/sys/windows/thread_local_key.rs +++ b/library/std/src/sys/windows/thread_local_key.rs @@ -196,6 +196,8 @@ pub static p_thread_callback: unsafe extern "system" fn(c::LPVOID, c::DWORD, c:: unsafe extern "system" fn on_tls_callback(h: c::LPVOID, dwReason: c::DWORD, pv: c::LPVOID) { if dwReason == c::DLL_THREAD_DETACH || dwReason == c::DLL_PROCESS_DETACH { run_dtors(); + #[cfg(target_thread_local)] + super::thread_local_dtor::run_keyless_dtors(); } // See comments above for what this is doing. Note that we don't need this diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs index 5a5913ebd7..804727fbc5 100644 --- a/library/std/src/sys_common/mod.rs +++ b/library/std/src/sys_common/mod.rs @@ -40,7 +40,7 @@ cfg_if::cfg_if! { if #[cfg(any(target_os = "l4re", target_os = "hermit", feature = "restricted-std", - all(target_arch = "wasm32", not(target_os = "emscripten")), + all(target_family = "wasm", not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx")))] { pub use crate::sys::net; } else { diff --git a/library/std/src/sys_common/process.rs b/library/std/src/sys_common/process.rs index 3d71219756..2cd1e29f6c 100644 --- a/library/std/src/sys_common/process.rs +++ b/library/std/src/sys_common/process.rs @@ -106,6 +106,7 @@ impl CommandEnv { /// This struct is created by /// [`Command::get_envs`][crate::process::Command::get_envs]. See its /// documentation for more. +#[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "command_access", since = "1.57.0")] #[derive(Debug)] pub struct CommandEnvs<'a> { diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs index 9508bd7da5..6e29bc6145 100644 --- a/library/std/src/sys_common/wtf8.rs +++ b/library/std/src/sys_common/wtf8.rs @@ -686,7 +686,7 @@ impl Wtf8 { } } -/// Returns a slice of the given string for the byte range [`begin`..`end`). +/// Returns a slice of the given string for the byte range \[`begin`..`end`). /// /// # Panics /// @@ -809,7 +809,8 @@ impl<'a> Iterator for Wtf8CodePoints<'a> { #[inline] fn next(&mut self) -> Option { - next_code_point(&mut self.bytes).map(|c| CodePoint { value: c }) + // SAFETY: `self.bytes` has been created from a WTF-8 string + unsafe { next_code_point(&mut self.bytes).map(|c| CodePoint { value: c }) } } #[inline] diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index c53290ec0c..4da59577d7 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -165,6 +165,7 @@ macro_rules! __thread_local_inner { #[cfg_attr(not(windows), inline)] // see comments below unsafe fn __getit() -> $crate::option::Option<&'static $t> { const _REQUIRE_UNSTABLE: () = $crate::thread::require_unstable_const_init_thread_local(); + const INIT_EXPR: $t = $init; // wasm without atomics maps directly to `static mut`, and dtors // aren't implemented because thread dtors aren't really a thing @@ -172,30 +173,29 @@ macro_rules! __thread_local_inner { // // FIXME(#84224) this should come after the `target_thread_local` // block. - #[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))] + #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))] { - static mut VAL: $t = $init; + static mut VAL: $t = INIT_EXPR; 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"))), + not(all(target_family = "wasm", not(target_feature = "atomics"))), ))] { + #[thread_local] + static mut VAL: $t = INIT_EXPR; + // 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 @@ -238,11 +238,11 @@ macro_rules! __thread_local_inner { // same implementation as below for os thread locals. #[cfg(all( not(target_thread_local), - not(all(target_arch = "wasm32", not(target_feature = "atomics"))), + not(all(target_family = "wasm", not(target_feature = "atomics"))), ))] { #[inline] - const fn __init() -> $t { $init } + const fn __init() -> $t { INIT_EXPR } static __KEY: $crate::thread::__OsLocalKeyInner<$t> = $crate::thread::__OsLocalKeyInner::new(); #[allow(unused_unsafe)] @@ -285,21 +285,21 @@ macro_rules! __thread_local_inner { // The issue of "should enable on Windows sometimes" is #84933 #[cfg_attr(not(windows), inline)] unsafe fn __getit() -> $crate::option::Option<&'static $t> { - #[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))] + #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))] static __KEY: $crate::thread::__StaticLocalKeyInner<$t> = $crate::thread::__StaticLocalKeyInner::new(); #[thread_local] #[cfg(all( target_thread_local, - not(all(target_arch = "wasm32", not(target_feature = "atomics"))), + not(all(target_family = "wasm", not(target_feature = "atomics"))), ))] static __KEY: $crate::thread::__FastLocalKeyInner<$t> = $crate::thread::__FastLocalKeyInner::new(); #[cfg(all( not(target_thread_local), - not(all(target_arch = "wasm32", not(target_feature = "atomics"))), + not(all(target_family = "wasm", not(target_feature = "atomics"))), ))] static __KEY: $crate::thread::__OsLocalKeyInner<$t> = $crate::thread::__OsLocalKeyInner::new(); @@ -479,10 +479,10 @@ mod lazy { } } -/// On some platforms like wasm32 there's no threads, so no need to generate +/// On some targets like wasm there's no threads, so no need to generate /// thread locals and we can instead just use plain statics! #[doc(hidden)] -#[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))] +#[cfg(all(target_family = "wasm", not(target_feature = "atomics")))] pub mod statik { use super::lazy::LazyKeyInner; use crate::fmt; diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index b2aa500a0f..39b53b51bf 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -200,7 +200,7 @@ pub use self::local::fast::Key as __FastLocalKeyInner; #[doc(hidden)] pub use self::local::os::Key as __OsLocalKeyInner; #[unstable(feature = "libstd_thread_internals", issue = "none")] -#[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))] +#[cfg(all(target_family = "wasm", not(target_feature = "atomics")))] #[doc(hidden)] pub use self::local::statik::Key as __StaticLocalKeyInner; @@ -257,6 +257,7 @@ pub const fn require_unstable_const_init_thread_local() {} /// [`unwrap`]: crate::result::Result::unwrap /// [naming-threads]: ./index.html#naming-threads /// [stack-size]: ./index.html#stack-size +#[must_use = "must eventually spawn the thread"] #[stable(feature = "rust1", since = "1.0.0")] #[derive(Debug)] pub struct Builder { @@ -649,6 +650,7 @@ where /// /// handler.join().unwrap(); /// ``` +#[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn current() -> Thread { thread_info::current_thread().expect( @@ -737,6 +739,7 @@ pub fn yield_now() { /// /// [Mutex]: crate::sync::Mutex #[inline] +#[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn panicking() -> bool { panicking::panicking() @@ -1131,6 +1134,7 @@ impl Thread { /// assert!(thread::current().id() != other_thread_id); /// ``` #[stable(feature = "thread_id", since = "1.19.0")] + #[must_use] pub fn id(&self) -> ThreadId { self.inner.id } @@ -1173,6 +1177,7 @@ impl Thread { /// /// [naming-threads]: ./index.html#naming-threads #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] pub fn name(&self) -> Option<&str> { self.cname().map(|s| unsafe { str::from_utf8_unchecked(s.to_bytes()) }) } @@ -1360,6 +1365,7 @@ impl JoinHandle { /// println!("thread id: {:?}", thread.id()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] pub fn thread(&self) -> &Thread { &self.0.thread } @@ -1401,6 +1407,15 @@ impl JoinHandle { pub fn join(mut self) -> Result { self.0.join() } + + /// Checks if the the associated thread is still running its main function. + /// + /// This might return `false` for a brief moment after the thread's main + /// function has returned, but before the thread itself has stopped running. + #[unstable(feature = "thread_is_running", issue = "90470")] + pub fn is_running(&self) -> bool { + Arc::strong_count(&self.0.packet.0) > 1 + } } impl AsInner for JoinHandle { @@ -1449,6 +1464,10 @@ fn _assert_sync_and_send() { /// global state in order to more accurately query the amount of available /// parallelism. /// +/// Resource limits can be changed during the runtime of a program, therefore the value is +/// not cached and instead recomputed every time this function is called. It should not be +/// called from hot code. +/// /// The value returned by this function should be considered a simplified /// approximation of the actual amount of parallelism available at any given /// time. To get a more detailed or precise overview of the amount of diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs index 16ad366fc1..ca0d88135a 100644 --- a/library/std/src/thread/tests.rs +++ b/library/std/src/thread/tests.rs @@ -2,9 +2,13 @@ use super::Builder; use crate::any::Any; use crate::mem; use crate::result; -use crate::sync::mpsc::{channel, Sender}; +use crate::sync::{ + mpsc::{channel, Sender}, + Arc, Barrier, +}; use crate::thread::{self, ThreadId}; use crate::time::Duration; +use crate::time::Instant; // !!! These tests are dangerous. If something is buggy, they will hang, !!! // !!! instead of exiting cleanly. This might wedge the buildbots. !!! @@ -46,6 +50,36 @@ fn test_run_basic() { rx.recv().unwrap(); } +#[test] +fn test_is_running() { + let b = Arc::new(Barrier::new(2)); + let t = thread::spawn({ + let b = b.clone(); + move || { + b.wait(); + 1234 + } + }); + + // Thread is definitely running here, since it's still waiting for the barrier. + assert_eq!(t.is_running(), true); + + // Unblock the barrier. + b.wait(); + + // Now check that t.is_running() becomes false within a reasonable time. + let start = Instant::now(); + while t.is_running() { + assert!(start.elapsed() < Duration::from_secs(2)); + thread::sleep(Duration::from_millis(15)); + } + + // Joining the thread should not block for a significant time now. + let join_time = Instant::now(); + assert_eq!(t.join().unwrap(), 1234); + assert!(join_time.elapsed() < Duration::from_secs(2)); +} + #[test] fn test_join_panic() { match thread::spawn(move || panic!()).join() { diff --git a/library/std/src/time.rs b/library/std/src/time.rs index 3e27e3a429..a5e3bd0c29 100644 --- a/library/std/src/time.rs +++ b/library/std/src/time.rs @@ -239,6 +239,7 @@ impl Instant { /// /// let now = Instant::now(); /// ``` + #[must_use] #[stable(feature = "time2", since = "1.8.0")] pub fn now() -> Instant { let os_now = time::Instant::now(); @@ -306,6 +307,7 @@ impl Instant { /// let new_now = Instant::now(); /// println!("{:?}", new_now.duration_since(now)); /// ``` + #[must_use] #[stable(feature = "time2", since = "1.8.0")] pub fn duration_since(&self, earlier: Instant) -> Duration { self.0.checked_sub_instant(&earlier.0).expect("supplied instant is later than self") @@ -326,6 +328,7 @@ impl Instant { /// println!("{:?}", new_now.checked_duration_since(now)); /// println!("{:?}", now.checked_duration_since(new_now)); // None /// ``` + #[must_use] #[stable(feature = "checked_duration_since", since = "1.39.0")] pub fn checked_duration_since(&self, earlier: Instant) -> Option { self.0.checked_sub_instant(&earlier.0) @@ -346,6 +349,7 @@ impl Instant { /// println!("{:?}", new_now.saturating_duration_since(now)); /// println!("{:?}", now.saturating_duration_since(new_now)); // 0ns /// ``` + #[must_use] #[stable(feature = "checked_duration_since", since = "1.39.0")] pub fn saturating_duration_since(&self, earlier: Instant) -> Duration { self.checked_duration_since(earlier).unwrap_or_default() @@ -370,6 +374,7 @@ impl Instant { /// sleep(three_secs); /// assert!(instant.elapsed() >= three_secs); /// ``` + #[must_use] #[stable(feature = "time2", since = "1.8.0")] pub fn elapsed(&self) -> Duration { Instant::now() - *self @@ -476,6 +481,7 @@ impl SystemTime { /// /// let sys_time = SystemTime::now(); /// ``` + #[must_use] #[stable(feature = "time2", since = "1.8.0")] pub fn now() -> SystemTime { SystemTime(time::SystemTime::now()) @@ -644,6 +650,7 @@ impl SystemTimeError { /// Err(e) => println!("SystemTimeError difference: {:?}", e.duration()), /// } /// ``` + #[must_use] #[stable(feature = "time2", since = "1.8.0")] pub fn duration(&self) -> Duration { self.0 diff --git a/library/std/src/time/tests.rs b/library/std/src/time/tests.rs index dc44c9346b..7279925a6d 100644 --- a/library/std/src/time/tests.rs +++ b/library/std/src/time/tests.rs @@ -48,7 +48,7 @@ fn instant_monotonic_concurrent() -> crate::thread::Result<()> { #[test] fn instant_elapsed() { let a = Instant::now(); - a.elapsed(); + let _ = a.elapsed(); } #[test] @@ -93,7 +93,7 @@ fn instant_math_is_associative() { #[should_panic] fn instant_duration_since_panic() { let a = Instant::now(); - (a - Duration::SECOND).duration_since(a); + let _ = (a - Duration::SECOND).duration_since(a); } #[test] diff --git a/library/stdarch/.github/workflows/main.yml b/library/stdarch/.github/workflows/main.yml index 516ddd49f4..6412075a4a 100644 --- a/library/stdarch/.github/workflows/main.yml +++ b/library/stdarch/.github/workflows/main.yml @@ -171,6 +171,8 @@ jobs: steps: - uses: actions/checkout@master + with: + submodules: recursive - name: Install Rust (rustup) run: | rustup update nightly --no-self-update @@ -189,7 +191,6 @@ jobs: 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' diff --git a/library/stdarch/ci/run.sh b/library/stdarch/ci/run.sh index 1d501492b6..b8482478f6 100755 --- a/library/stdarch/ci/run.sh +++ b/library/stdarch/ci/run.sh @@ -122,7 +122,7 @@ esac if [ "${TARGET}" = "aarch64-unknown-linux-gnu" ]; then export CPPFLAGS="-fuse-ld=lld -I/usr/aarch64-linux-gnu/include/ -I/usr/aarch64-linux-gnu/include/c++/9/aarch64-linux-gnu/" - cargo run ${INTRINSIC_TEST} --release --bin intrinsic-test -- crates/intrinsic-test/neon-intrinsics.csv --runner "${CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUNNER}" --cppcompiler "clang++-12" + cargo run ${INTRINSIC_TEST} --release --bin intrinsic-test -- crates/intrinsic-test/acle/tools/intrinsic_db/advsimd.csv --runner "${CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUNNER}" --cppcompiler "clang++-12" --skip crates/intrinsic-test/missing.txt fi if [ "$NORUN" != "1" ] && [ "$NOSTD" != 1 ]; then diff --git a/library/stdarch/crates/core_arch/MISSING.md b/library/stdarch/crates/core_arch/MISSING.md new file mode 100644 index 0000000000..c948f3f8c9 --- /dev/null +++ b/library/stdarch/crates/core_arch/MISSING.md @@ -0,0 +1,116 @@ +## The following neon instructions are currently not implemented in stdarch + +### Not implemented on arm: + +`vcadd_rot270_f32` + +`vcadd_rot90_f32` + +`vcaddq_rot270_f32` + +`vcaddq_rot90_f32` + +`vdot_s32` + +`vdot_u32` + +`vdotq_s32` + +`vdotq_u32` + +`vdot_lane_s32` + +`vdot_lane_u32` + +`vdotq_lane_s32` + +`vdotq_lane_u32` + +`vcmla_f32` + +`vcmla_lane_f32` + +`vcmla_laneq_f32` + +`vcmla_rot180_f32` + +`vcmla_rot180_lane_f32` + +`vcmla_rot180_laneq_f32` + +`vcmla_rot270_f32` + +`vcmla_rot270_lane_f32` + +`vcmla_rot270_laneq_f32` + +`vcmla_rot90_f32` + +`vcmla_rot90_lane_f32` + +`vcmla_rot90_laneq_f32` + +`vcmlaq_f32` + +`vcmlaq_lane_f32` + +`vcmlaq_laneq_f32` + +`vcmlaq_rot180_f32` + +`vcmlaq_rot180_lane_f32` + +`vcmlaq_rot180_laneq_f32` + +`vcmlaq_rot270_f32` + +`vcmlaq_rot270_lane_f32` + +`vcmlaq_rot270_laneq_f32` + +`vcmlaq_rot90_f32` + +`vcmlaq_rot90_lane_f32` + +`vcmlaq_rot90_laneq_f32` + +### Not implemented in LLVM: + +`vrnd32x_f64` + +`vrnd32xq_f64` + +`vrnd32z_f64` + +`vrnd32zq_f64` + +`vrnd64x_f64` + +`vrnd64xq_f64` + +`vrnd64z_f64` + +`vrnd64zq_f64` + +### LLVM Select errors may occur: + +`vsudot_lane_s32` + +`vsudot_laneq_s32` + +`vsudotq_lane_s32` + +`vsudotq_laneq_s32` + +`vusdot_lane_s32` + +`vusdot_laneq_s32` + +`vusdot_s32` + +`vusdotq_lane_s32` + +`vusdotq_laneq_s32` + +`vusdotq_s32v` + diff --git a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs index d441ee562a..5bfa4fa59b 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs @@ -9,6 +9,110 @@ use super::*; #[cfg(test)] use stdarch_test::assert_instr; +/// Three-way exclusive OR +#[inline] +#[target_feature(enable = "neon,sha3")] +#[cfg_attr(test, assert_instr(eor3))] +pub unsafe fn veor3q_s8(a: int8x16_t, b: int8x16_t, c: int8x16_t) -> int8x16_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.eor3s.v16i8")] + fn veor3q_s8_(a: int8x16_t, b: int8x16_t, c: int8x16_t) -> int8x16_t; + } + veor3q_s8_(a, b, c) +} + +/// Three-way exclusive OR +#[inline] +#[target_feature(enable = "neon,sha3")] +#[cfg_attr(test, assert_instr(eor3))] +pub unsafe fn veor3q_s16(a: int16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.eor3s.v8i16")] + fn veor3q_s16_(a: int16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8_t; + } + veor3q_s16_(a, b, c) +} + +/// Three-way exclusive OR +#[inline] +#[target_feature(enable = "neon,sha3")] +#[cfg_attr(test, assert_instr(eor3))] +pub unsafe fn veor3q_s32(a: int32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.eor3s.v4i32")] + fn veor3q_s32_(a: int32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4_t; + } + veor3q_s32_(a, b, c) +} + +/// Three-way exclusive OR +#[inline] +#[target_feature(enable = "neon,sha3")] +#[cfg_attr(test, assert_instr(eor3))] +pub unsafe fn veor3q_s64(a: int64x2_t, b: int64x2_t, c: int64x2_t) -> int64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.eor3s.v2i64")] + fn veor3q_s64_(a: int64x2_t, b: int64x2_t, c: int64x2_t) -> int64x2_t; + } + veor3q_s64_(a, b, c) +} + +/// Three-way exclusive OR +#[inline] +#[target_feature(enable = "neon,sha3")] +#[cfg_attr(test, assert_instr(eor3))] +pub unsafe fn veor3q_u8(a: uint8x16_t, b: uint8x16_t, c: uint8x16_t) -> uint8x16_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.eor3u.v16i8")] + fn veor3q_u8_(a: uint8x16_t, b: uint8x16_t, c: uint8x16_t) -> uint8x16_t; + } + veor3q_u8_(a, b, c) +} + +/// Three-way exclusive OR +#[inline] +#[target_feature(enable = "neon,sha3")] +#[cfg_attr(test, assert_instr(eor3))] +pub unsafe fn veor3q_u16(a: uint16x8_t, b: uint16x8_t, c: uint16x8_t) -> uint16x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.eor3u.v8i16")] + fn veor3q_u16_(a: uint16x8_t, b: uint16x8_t, c: uint16x8_t) -> uint16x8_t; + } + veor3q_u16_(a, b, c) +} + +/// Three-way exclusive OR +#[inline] +#[target_feature(enable = "neon,sha3")] +#[cfg_attr(test, assert_instr(eor3))] +pub unsafe fn veor3q_u32(a: uint32x4_t, b: uint32x4_t, c: uint32x4_t) -> uint32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.eor3u.v4i32")] + fn veor3q_u32_(a: uint32x4_t, b: uint32x4_t, c: uint32x4_t) -> uint32x4_t; + } + veor3q_u32_(a, b, c) +} + +/// Three-way exclusive OR +#[inline] +#[target_feature(enable = "neon,sha3")] +#[cfg_attr(test, assert_instr(eor3))] +pub unsafe fn veor3q_u64(a: uint64x2_t, b: uint64x2_t, c: uint64x2_t) -> uint64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.eor3u.v2i64")] + fn veor3q_u64_(a: uint64x2_t, b: uint64x2_t, c: uint64x2_t) -> uint64x2_t; + } + veor3q_u64_(a, b, c) +} + /// Absolute difference between the arguments of Floating #[inline] #[target_feature(enable = "neon")] @@ -35,6 +139,22 @@ pub unsafe fn vabdq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { vabdq_f64_(a, b) } +/// Floating-point absolute difference +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(fabd))] +pub unsafe fn vabds_f32(a: f32, b: f32) -> f32 { + simd_extract(vabd_f32(vdup_n_f32(a), vdup_n_f32(b)), 0) +} + +/// Floating-point absolute difference +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(fabd))] +pub unsafe fn vabdd_f64(a: f64, b: f64) -> f64 { + simd_extract(vabd_f64(vdup_n_f64(a), vdup_n_f64(b)), 0) +} + /// Unsigned Absolute difference Long #[inline] #[target_feature(enable = "neon")] @@ -162,6 +282,38 @@ pub unsafe fn vceqq_f64(a: float64x2_t, b: float64x2_t) -> uint64x2_t { simd_eq(a, b) } +/// Compare bitwise equal +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(cmp))] +pub unsafe fn vceqd_s64(a: i64, b: i64) -> u64 { + transmute(vceq_s64(transmute(a), transmute(b))) +} + +/// Compare bitwise equal +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(cmp))] +pub unsafe fn vceqd_u64(a: u64, b: u64) -> u64 { + transmute(vceq_u64(transmute(a), transmute(b))) +} + +/// Floating-point compare equal +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(fcmp))] +pub unsafe fn vceqs_f32(a: f32, b: f32) -> u32 { + simd_extract(vceq_f32(vdup_n_f32(a), vdup_n_f32(b)), 0) +} + +/// Floating-point compare equal +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(fcmp))] +pub unsafe fn vceqd_f64(a: f64, b: f64) -> u64 { + simd_extract(vceq_f64(vdup_n_f64(a), vdup_n_f64(b)), 0) +} + /// Signed compare bitwise equal to zero #[inline] #[target_feature(enable = "neon")] @@ -378,6 +530,38 @@ pub unsafe fn vceqzq_f64(a: float64x2_t) -> uint64x2_t { simd_eq(a, transmute(b)) } +/// Compare bitwise equal to zero +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(cmp))] +pub unsafe fn vceqzd_s64(a: i64) -> u64 { + transmute(vceqz_s64(transmute(a))) +} + +/// Compare bitwise equal to zero +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(cmp))] +pub unsafe fn vceqzd_u64(a: u64) -> u64 { + transmute(vceqz_u64(transmute(a))) +} + +/// Floating-point compare bitwise equal to zero +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(fcmp))] +pub unsafe fn vceqzs_f32(a: f32) -> u32 { + simd_extract(vceqz_f32(vdup_n_f32(a)), 0) +} + +/// Floating-point compare bitwise equal to zero +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(fcmp))] +pub unsafe fn vceqzd_f64(a: f64) -> u64 { + simd_extract(vceqz_f64(vdup_n_f64(a)), 0) +} + /// Signed compare bitwise Test bits nonzero #[inline] #[target_feature(enable = "neon")] @@ -438,6 +622,64 @@ pub unsafe fn vtstq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { simd_ne(c, transmute(d)) } +/// Compare bitwise test bits nonzero +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(tst))] +pub unsafe fn vtstd_s64(a: i64, b: i64) -> u64 { + transmute(vtst_s64(transmute(a), transmute(b))) +} + +/// Compare bitwise test bits nonzero +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(tst))] +pub unsafe fn vtstd_u64(a: u64, b: u64) -> u64 { + transmute(vtst_u64(transmute(a), transmute(b))) +} + +/// Signed saturating accumulate of unsigned value +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(suqadd))] +pub unsafe fn vuqadds_s32(a: i32, b: u32) -> i32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.suqadd.i32")] + fn vuqadds_s32_(a: i32, b: u32) -> i32; + } + vuqadds_s32_(a, b) +} + +/// Signed saturating accumulate of unsigned value +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(suqadd))] +pub unsafe fn vuqaddd_s64(a: i64, b: u64) -> i64 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.suqadd.i64")] + fn vuqaddd_s64_(a: i64, b: u64) -> i64; + } + vuqaddd_s64_(a, b) +} + +/// Signed saturating accumulate of unsigned value +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(suqadd))] +pub unsafe fn vuqaddb_s8(a: i8, b: u8) -> i8 { + simd_extract(vuqadd_s8(vdup_n_s8(a), vdup_n_u8(b)), 0) +} + +/// Signed saturating accumulate of unsigned value +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(suqadd))] +pub unsafe fn vuqaddh_s16(a: i16, b: u16) -> i16 { + simd_extract(vuqadd_s16(vdup_n_s16(a), vdup_n_u16(b)), 0) +} + /// Floating-point absolute value #[inline] #[target_feature(enable = "neon")] @@ -502,6 +744,38 @@ pub unsafe fn vcgtq_f64(a: float64x2_t, b: float64x2_t) -> uint64x2_t { simd_gt(a, b) } +/// Compare greater than +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(cmp))] +pub unsafe fn vcgtd_s64(a: i64, b: i64) -> u64 { + transmute(vcgt_s64(transmute(a), transmute(b))) +} + +/// Compare greater than +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(cmp))] +pub unsafe fn vcgtd_u64(a: u64, b: u64) -> u64 { + transmute(vcgt_u64(transmute(a), transmute(b))) +} + +/// Floating-point compare greater than +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(fcmp))] +pub unsafe fn vcgts_f32(a: f32, b: f32) -> u32 { + simd_extract(vcgt_f32(vdup_n_f32(a), vdup_n_f32(b)), 0) +} + +/// Floating-point compare greater than +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(fcmp))] +pub unsafe fn vcgtd_f64(a: f64, b: f64) -> u64 { + simd_extract(vcgt_f64(vdup_n_f64(a), vdup_n_f64(b)), 0) +} + /// Compare signed less than #[inline] #[target_feature(enable = "neon")] @@ -550,6 +824,38 @@ pub unsafe fn vcltq_f64(a: float64x2_t, b: float64x2_t) -> uint64x2_t { simd_lt(a, b) } +/// Compare less than +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(cmp))] +pub unsafe fn vcltd_s64(a: i64, b: i64) -> u64 { + transmute(vclt_s64(transmute(a), transmute(b))) +} + +/// Compare less than +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(cmp))] +pub unsafe fn vcltd_u64(a: u64, b: u64) -> u64 { + transmute(vclt_u64(transmute(a), transmute(b))) +} + +/// Floating-point compare less than +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(fcmp))] +pub unsafe fn vclts_f32(a: f32, b: f32) -> u32 { + simd_extract(vclt_f32(vdup_n_f32(a), vdup_n_f32(b)), 0) +} + +/// Floating-point compare less than +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(fcmp))] +pub unsafe fn vcltd_f64(a: f64, b: f64) -> u64 { + simd_extract(vclt_f64(vdup_n_f64(a), vdup_n_f64(b)), 0) +} + /// Compare signed less than or equal #[inline] #[target_feature(enable = "neon")] @@ -566,6 +872,38 @@ pub unsafe fn vcleq_s64(a: int64x2_t, b: int64x2_t) -> uint64x2_t { simd_le(a, b) } +/// Compare greater than or equal +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(cmp))] +pub unsafe fn vcged_s64(a: i64, b: i64) -> u64 { + transmute(vcge_s64(transmute(a), transmute(b))) +} + +/// Compare greater than or equal +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(cmp))] +pub unsafe fn vcged_u64(a: u64, b: u64) -> u64 { + transmute(vcge_u64(transmute(a), transmute(b))) +} + +/// Floating-point compare greater than or equal +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(fcmp))] +pub unsafe fn vcges_f32(a: f32, b: f32) -> u32 { + simd_extract(vcge_f32(vdup_n_f32(a), vdup_n_f32(b)), 0) +} + +/// Floating-point compare greater than or equal +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(fcmp))] +pub unsafe fn vcged_f64(a: f64, b: f64) -> u64 { + simd_extract(vcge_f64(vdup_n_f64(a), vdup_n_f64(b)), 0) +} + /// Compare unsigned less than or equal #[inline] #[target_feature(enable = "neon")] @@ -598,6 +936,38 @@ pub unsafe fn vcleq_f64(a: float64x2_t, b: float64x2_t) -> uint64x2_t { simd_le(a, b) } +/// Compare less than or equal +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(cmp))] +pub unsafe fn vcled_s64(a: i64, b: i64) -> u64 { + transmute(vcle_s64(transmute(a), transmute(b))) +} + +/// Compare less than or equal +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(cmp))] +pub unsafe fn vcled_u64(a: u64, b: u64) -> u64 { + transmute(vcle_u64(transmute(a), transmute(b))) +} + +/// Floating-point compare less than or equal +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(fcmp))] +pub unsafe fn vcles_f32(a: f32, b: f32) -> u32 { + simd_extract(vcle_f32(vdup_n_f32(a), vdup_n_f32(b)), 0) +} + +/// Floating-point compare less than or equal +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(fcmp))] +pub unsafe fn vcled_f64(a: f64, b: f64) -> u64 { + simd_extract(vcle_f64(vdup_n_f64(a), vdup_n_f64(b)), 0) +} + /// Compare signed greater than or equal #[inline] #[target_feature(enable = "neon")] @@ -754,6 +1124,30 @@ pub unsafe fn vcgezq_f64(a: float64x2_t) -> uint64x2_t { simd_ge(a, transmute(b)) } +/// Compare signed greater than or equal to zero +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(eor))] +pub unsafe fn vcgezd_s64(a: i64) -> u64 { + transmute(vcgez_s64(transmute(a))) +} + +/// Floating-point compare greater than or equal to zero +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(fcmp))] +pub unsafe fn vcgezs_f32(a: f32) -> u32 { + simd_extract(vcgez_f32(vdup_n_f32(a)), 0) +} + +/// Floating-point compare greater than or equal to zero +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(fcmp))] +pub unsafe fn vcgezd_f64(a: f64) -> u64 { + simd_extract(vcgez_f64(vdup_n_f64(a)), 0) +} + /// Compare signed greater than zero #[inline] #[target_feature(enable = "neon")] @@ -862,6 +1256,30 @@ pub unsafe fn vcgtzq_f64(a: float64x2_t) -> uint64x2_t { simd_gt(a, transmute(b)) } +/// Compare signed greater than zero +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(cmp))] +pub unsafe fn vcgtzd_s64(a: i64) -> u64 { + transmute(vcgtz_s64(transmute(a))) +} + +/// Floating-point compare greater than zero +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(fcmp))] +pub unsafe fn vcgtzs_f32(a: f32) -> u32 { + simd_extract(vcgtz_f32(vdup_n_f32(a)), 0) +} + +/// Floating-point compare greater than zero +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(fcmp))] +pub unsafe fn vcgtzd_f64(a: f64) -> u64 { + simd_extract(vcgtz_f64(vdup_n_f64(a)), 0) +} + /// Compare signed less than or equal to zero #[inline] #[target_feature(enable = "neon")] @@ -970,6 +1388,30 @@ pub unsafe fn vclezq_f64(a: float64x2_t) -> uint64x2_t { simd_le(a, transmute(b)) } +/// Compare less than or equal to zero +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(cmp))] +pub unsafe fn vclezd_s64(a: i64) -> u64 { + transmute(vclez_s64(transmute(a))) +} + +/// Floating-point compare less than or equal to zero +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(fcmp))] +pub unsafe fn vclezs_f32(a: f32) -> u32 { + simd_extract(vclez_f32(vdup_n_f32(a)), 0) +} + +/// Floating-point compare less than or equal to zero +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(fcmp))] +pub unsafe fn vclezd_f64(a: f64) -> u64 { + simd_extract(vclez_f64(vdup_n_f64(a)), 0) +} + /// Compare signed less than zero #[inline] #[target_feature(enable = "neon")] @@ -1078,6 +1520,30 @@ pub unsafe fn vcltzq_f64(a: float64x2_t) -> uint64x2_t { simd_lt(a, transmute(b)) } +/// Compare less than zero +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(asr))] +pub unsafe fn vcltzd_s64(a: i64) -> u64 { + transmute(vcltz_s64(transmute(a))) +} + +/// Floating-point compare less than zero +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(fcmp))] +pub unsafe fn vcltzs_f32(a: f32) -> u32 { + simd_extract(vcltz_f32(vdup_n_f32(a)), 0) +} + +/// Floating-point compare less than zero +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(fcmp))] +pub unsafe fn vcltzd_f64(a: f64) -> u64 { + simd_extract(vcltz_f64(vdup_n_f64(a)), 0) +} + /// Floating-point absolute compare greater than #[inline] #[target_feature(enable = "neon")] @@ -1104,7 +1570,33 @@ pub unsafe fn vcagtq_f64(a: float64x2_t, b: float64x2_t) -> uint64x2_t { vcagtq_f64_(a, b) } -/// Floating-point absolute compare greater than or equal +/// Floating-point absolute compare greater than +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(facgt))] +pub unsafe fn vcagts_f32(a: f32, b: f32) -> u32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.facgt.i32.f32")] + fn vcagts_f32_(a: f32, b: f32) -> u32; + } + vcagts_f32_(a, b) +} + +/// Floating-point absolute compare greater than +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(facgt))] +pub unsafe fn vcagtd_f64(a: f64, b: f64) -> u64 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.facgt.i64.f64")] + fn vcagtd_f64_(a: f64, b: f64) -> u64; + } + vcagtd_f64_(a, b) +} + +/// Floating-point absolute compare greater than or equal #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(facge))] @@ -1130,6 +1622,32 @@ pub unsafe fn vcageq_f64(a: float64x2_t, b: float64x2_t) -> uint64x2_t { vcageq_f64_(a, b) } +/// Floating-point absolute compare greater than or equal +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(facge))] +pub unsafe fn vcages_f32(a: f32, b: f32) -> u32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.facge.i32.f32")] + fn vcages_f32_(a: f32, b: f32) -> u32; + } + vcages_f32_(a, b) +} + +/// Floating-point absolute compare greater than or equal +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(facge))] +pub unsafe fn vcaged_f64(a: f64, b: f64) -> u64 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.facge.i64.f64")] + fn vcaged_f64_(a: f64, b: f64) -> u64; + } + vcaged_f64_(a, b) +} + /// Floating-point absolute compare less than #[inline] #[target_feature(enable = "neon")] @@ -1146,6 +1664,22 @@ pub unsafe fn vcaltq_f64(a: float64x2_t, b: float64x2_t) -> uint64x2_t { vcagtq_f64(b, a) } +/// Floating-point absolute compare less than +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(facgt))] +pub unsafe fn vcalts_f32(a: f32, b: f32) -> u32 { + vcagts_f32(b, a) +} + +/// Floating-point absolute compare less than +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(facgt))] +pub unsafe fn vcaltd_f64(a: f64, b: f64) -> u64 { + vcagtd_f64(b, a) +} + /// Floating-point absolute compare less than or equal #[inline] #[target_feature(enable = "neon")] @@ -1162,6 +1696,22 @@ pub unsafe fn vcaleq_f64(a: float64x2_t, b: float64x2_t) -> uint64x2_t { vcageq_f64(b, a) } +/// Floating-point absolute compare less than or equal +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(facge))] +pub unsafe fn vcales_f32(a: f32, b: f32) -> u32 { + vcages_f32(b, a) +} + +/// Floating-point absolute compare less than or equal +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(facge))] +pub unsafe fn vcaled_f64(a: f64, b: f64) -> u64 { + vcaged_f64(b, a) +} + /// Insert vector element from another vector element #[inline] #[target_feature(enable = "neon")] @@ -2110,6 +2660,14 @@ pub unsafe fn vcvtx_f32_f64(a: float64x2_t) -> float32x2_t { vcvtx_f32_f64_(a) } +/// Floating-point convert to lower precision narrow, rounding to odd +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(fcvtxn))] +pub unsafe fn vcvtxd_f32_f64(a: f64) -> f32 { + simd_extract(vcvtx_f32_f64(vdupq_n_f64(a)), 0) +} + /// Floating-point convert to lower precision narrow, rounding to odd #[inline] #[target_feature(enable = "neon")] @@ -3892,6 +4450,14 @@ pub unsafe fn vnegq_s64(a: int64x2_t) -> int64x2_t { simd_neg(a) } +/// Negate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(neg))] +pub unsafe fn vnegd_s64(a: i64) -> i64 { + -a +} + /// Negate #[inline] #[target_feature(enable = "neon")] @@ -3934,6 +4500,38 @@ pub unsafe fn vqnegq_s64(a: int64x2_t) -> int64x2_t { vqnegq_s64_(a) } +/// Signed saturating negate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(sqneg))] +pub unsafe fn vqnegb_s8(a: i8) -> i8 { + simd_extract(vqneg_s8(vdup_n_s8(a)), 0) +} + +/// Signed saturating negate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(sqneg))] +pub unsafe fn vqnegh_s16(a: i16) -> i16 { + simd_extract(vqneg_s16(vdup_n_s16(a)), 0) +} + +/// Signed saturating negate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(sqneg))] +pub unsafe fn vqnegs_s32(a: i32) -> i32 { + simd_extract(vqneg_s32(vdup_n_s32(a)), 0) +} + +/// Signed saturating negate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(sqneg))] +pub unsafe fn vqnegd_s64(a: i64) -> i64 { + simd_extract(vqneg_s64(vdup_n_s64(a)), 0) +} + /// Saturating subtract #[inline] #[target_feature(enable = "neon")] @@ -4214,6 +4812,19 @@ pub unsafe fn vrndnq_f64(a: float64x2_t) -> float64x2_t { vrndnq_f64_(a) } +/// Floating-point round to integral, to nearest with ties to even +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(frintn))] +pub unsafe fn vrndns_f32(a: f32) -> f32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.roundeven.f32")] + fn vrndns_f32_(a: f32) -> f32; + } + vrndns_f32_(a) +} + /// Floating-point round to integral, toward minus infinity #[inline] #[target_feature(enable = "neon")] @@ -4592,9531 +5203,14700 @@ pub unsafe fn vld1q_f64_x4(a: *const f64) -> float64x2x4_t { vld1q_f64_x4_(a) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(st1))] -pub unsafe fn vst1_f64_x2(a: *mut f64, b: float64x1x2_t) { +#[cfg_attr(test, assert_instr(ld2))] +pub unsafe fn vld2q_s64(a: *const i64) -> int64x2x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x2.v1f64.p0f64")] - fn vst1_f64_x2_(a: float64x1_t, b: float64x1_t, ptr: *mut f64); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2.v2i64.p0v2i64")] + fn vld2q_s64_(ptr: *const int64x2_t) -> int64x2x2_t; } - vst1_f64_x2_(b.0, b.1, a) + vld2q_s64_(a.cast()) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(st1))] -pub unsafe fn vst1q_f64_x2(a: *mut f64, b: float64x2x2_t) { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x2.v2f64.p0f64")] - fn vst1q_f64_x2_(a: float64x2_t, b: float64x2_t, ptr: *mut f64); - } - vst1q_f64_x2_(b.0, b.1, a) +#[cfg_attr(test, assert_instr(ld2))] +pub unsafe fn vld2q_u64(a: *const u64) -> uint64x2x2_t { + transmute(vld2q_s64(transmute(a))) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 2-element structures to two registers +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(test, assert_instr(ld2))] +pub unsafe fn vld2q_p64(a: *const p64) -> poly64x2x2_t { + transmute(vld2q_s64(transmute(a))) +} + +/// Load multiple 2-element structures to two registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(st1))] -pub unsafe fn vst1_f64_x3(a: *mut f64, b: float64x1x3_t) { +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vld2_f64(a: *const f64) -> float64x1x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x3.v1f64.p0f64")] - fn vst1_f64_x3_(a: float64x1_t, b: float64x1_t, c: float64x1_t, ptr: *mut f64); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2.v1f64.p0v1f64")] + fn vld2_f64_(ptr: *const float64x1_t) -> float64x1x2_t; } - vst1_f64_x3_(b.0, b.1, b.2, a) + vld2_f64_(a.cast()) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(st1))] -pub unsafe fn vst1q_f64_x3(a: *mut f64, b: float64x2x3_t) { +#[cfg_attr(test, assert_instr(ld2))] +pub unsafe fn vld2q_f64(a: *const f64) -> float64x2x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x3.v2f64.p0f64")] - fn vst1q_f64_x3_(a: float64x2_t, b: float64x2_t, c: float64x2_t, ptr: *mut f64); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2.v2f64.p0v2f64")] + fn vld2q_f64_(ptr: *const float64x2_t) -> float64x2x2_t; } - vst1q_f64_x3_(b.0, b.1, b.2, a) + vld2q_f64_(a.cast()) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(st1))] -pub unsafe fn vst1_f64_x4(a: *mut f64, b: float64x1x4_t) { +#[cfg_attr(test, assert_instr(ld2r))] +pub unsafe fn vld2q_dup_s64(a: *const i64) -> int64x2x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x4.v1f64.p0f64")] - fn vst1_f64_x4_(a: float64x1_t, b: float64x1_t, c: float64x1_t, d: float64x1_t, ptr: *mut f64); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2r.v2i64.p0i64")] + fn vld2q_dup_s64_(ptr: *const i64) -> int64x2x2_t; } - vst1_f64_x4_(b.0, b.1, b.2, b.3, a) + vld2q_dup_s64_(a.cast()) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(st1))] -pub unsafe fn vst1q_f64_x4(a: *mut f64, b: float64x2x4_t) { +#[cfg_attr(test, assert_instr(ld2r))] +pub unsafe fn vld2q_dup_u64(a: *const u64) -> uint64x2x2_t { + transmute(vld2q_dup_s64(transmute(a))) +} + +/// Load single 2-element structure and replicate to all lanes of two registers +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(test, assert_instr(ld2r))] +pub unsafe fn vld2q_dup_p64(a: *const p64) -> poly64x2x2_t { + transmute(vld2q_dup_s64(transmute(a))) +} + +/// Load single 2-element structure and replicate to all lanes of two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(ld2r))] +pub unsafe fn vld2_dup_f64(a: *const f64) -> float64x1x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x4.v2f64.p0f64")] - fn vst1q_f64_x4_(a: float64x2_t, b: float64x2_t, c: float64x2_t, d: float64x2_t, ptr: *mut f64); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2r.v1f64.p0f64")] + fn vld2_dup_f64_(ptr: *const f64) -> float64x1x2_t; } - vst1q_f64_x4_(b.0, b.1, b.2, b.3, a) + vld2_dup_f64_(a.cast()) } -/// Multiply +/// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmul))] -pub unsafe fn vmul_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { - simd_mul(a, b) +#[cfg_attr(test, assert_instr(ld2r))] +pub unsafe fn vld2q_dup_f64(a: *const f64) -> float64x2x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2r.v2f64.p0f64")] + fn vld2q_dup_f64_(ptr: *const f64) -> float64x2x2_t; + } + vld2q_dup_f64_(a.cast()) } -/// Multiply +/// Load multiple 2-element structures to two registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmul))] -pub unsafe fn vmulq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { - simd_mul(a, b) +#[cfg_attr(test, assert_instr(ld2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld2q_lane_s8(a: *const i8, b: int8x16x2_t) -> int8x16x2_t { + static_assert_imm4!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2lane.v16i8.p0i8")] + fn vld2q_lane_s8_(a: int8x16_t, b: int8x16_t, n: i64, ptr: *const i8) -> int8x16x2_t; + } + vld2q_lane_s8_(b.0, b.1, LANE as i64, a.cast()) } -/// Vector multiply by scalar +/// Load multiple 2-element structures to two registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmul))] -pub unsafe fn vmul_n_f64(a: float64x1_t, b: f64) -> float64x1_t { - simd_mul(a, vdup_n_f64(b)) +#[cfg_attr(test, assert_instr(ld2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld2_lane_s64(a: *const i64, b: int64x1x2_t) -> int64x1x2_t { + static_assert!(LANE : i32 where LANE == 0); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2lane.v1i64.p0i8")] + fn vld2_lane_s64_(a: int64x1_t, b: int64x1_t, n: i64, ptr: *const i8) -> int64x1x2_t; + } + vld2_lane_s64_(b.0, b.1, LANE as i64, a.cast()) } -/// Vector multiply by scalar +/// Load multiple 2-element structures to two registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmul))] -pub unsafe fn vmulq_n_f64(a: float64x2_t, b: f64) -> float64x2_t { - simd_mul(a, vdupq_n_f64(b)) +#[cfg_attr(test, assert_instr(ld2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld2q_lane_s64(a: *const i64, b: int64x2x2_t) -> int64x2x2_t { + static_assert_imm1!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2lane.v2i64.p0i8")] + fn vld2q_lane_s64_(a: int64x2_t, b: int64x2_t, n: i64, ptr: *const i8) -> int64x2x2_t; + } + vld2q_lane_s64_(b.0, b.1, LANE as i64, a.cast()) } -/// Floating-point multiply +/// Load multiple 2-element structures to two registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmul, LANE = 0))] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(test, assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmul_lane_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { +pub unsafe fn vld2_lane_p64(a: *const p64, b: poly64x1x2_t) -> poly64x1x2_t { static_assert!(LANE : i32 where LANE == 0); - simd_mul(a, transmute::(simd_extract(b, LANE as u32))) + transmute(vld2_lane_s64::(transmute(a), transmute(b))) } -/// Floating-point multiply +/// Load multiple 2-element structures to two registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmul, LANE = 0))] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(test, assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmul_laneq_f64(a: float64x1_t, b: float64x2_t) -> float64x1_t { +pub unsafe fn vld2q_lane_p64(a: *const p64, b: poly64x2x2_t) -> poly64x2x2_t { static_assert_imm1!(LANE); - simd_mul(a, transmute::(simd_extract(b, LANE as u32))) + transmute(vld2q_lane_s64::(transmute(a), transmute(b))) } -/// Floating-point multiply +/// Load multiple 2-element structures to two registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmul, LANE = 0))] +#[cfg_attr(test, assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmulq_lane_f64(a: float64x2_t, b: float64x1_t) -> float64x2_t { - static_assert!(LANE : i32 where LANE == 0); - simd_mul(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) +pub unsafe fn vld2q_lane_u8(a: *const u8, b: uint8x16x2_t) -> uint8x16x2_t { + static_assert_imm4!(LANE); + transmute(vld2q_lane_s8::(transmute(a), transmute(b))) } -/// Floating-point multiply +/// Load multiple 2-element structures to two registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmul, LANE = 0))] +#[cfg_attr(test, assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmulq_laneq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { - static_assert_imm1!(LANE); - simd_mul(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) +pub unsafe fn vld2_lane_u64(a: *const u64, b: uint64x1x2_t) -> uint64x1x2_t { + static_assert!(LANE : i32 where LANE == 0); + transmute(vld2_lane_s64::(transmute(a), transmute(b))) } -/// Floating-point multiply +/// Load multiple 2-element structures to two registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmul, LANE = 0))] +#[cfg_attr(test, assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmuls_lane_f32(a: f32, b: float32x2_t) -> f32 { +pub unsafe fn vld2q_lane_u64(a: *const u64, b: uint64x2x2_t) -> uint64x2x2_t { static_assert_imm1!(LANE); - let b: f32 = simd_extract(b, LANE as u32); - a * b + transmute(vld2q_lane_s64::(transmute(a), transmute(b))) } -/// Floating-point multiply +/// Load multiple 2-element structures to two registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmul, LANE = 0))] +#[cfg_attr(test, assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmuls_laneq_f32(a: f32, b: float32x4_t) -> f32 { - static_assert_imm2!(LANE); - let b: f32 = simd_extract(b, LANE as u32); - a * b +pub unsafe fn vld2q_lane_p8(a: *const p8, b: poly8x16x2_t) -> poly8x16x2_t { + static_assert_imm4!(LANE); + transmute(vld2q_lane_s8::(transmute(a), transmute(b))) } -/// Floating-point multiply +/// Load multiple 2-element structures to two registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmul, LANE = 0))] +#[cfg_attr(test, assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmuld_lane_f64(a: f64, b: float64x1_t) -> f64 { +pub unsafe fn vld2_lane_f64(a: *const f64, b: float64x1x2_t) -> float64x1x2_t { static_assert!(LANE : i32 where LANE == 0); - let b: f64 = simd_extract(b, LANE as u32); - a * b + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2lane.v1f64.p0i8")] + fn vld2_lane_f64_(a: float64x1_t, b: float64x1_t, n: i64, ptr: *const i8) -> float64x1x2_t; + } + vld2_lane_f64_(b.0, b.1, LANE as i64, a.cast()) } -/// Floating-point multiply +/// Load multiple 2-element structures to two registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmul, LANE = 0))] +#[cfg_attr(test, assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmuld_laneq_f64(a: f64, b: float64x2_t) -> f64 { +pub unsafe fn vld2q_lane_f64(a: *const f64, b: float64x2x2_t) -> float64x2x2_t { static_assert_imm1!(LANE); - let b: f64 = simd_extract(b, LANE as u32); - a * b + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2lane.v2f64.p0i8")] + fn vld2q_lane_f64_(a: float64x2_t, b: float64x2_t, n: i64, ptr: *const i8) -> float64x2x2_t; + } + vld2q_lane_f64_(b.0, b.1, LANE as i64, a.cast()) } -/// Signed multiply long +/// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(smull2))] -pub unsafe fn vmull_high_s8(a: int8x16_t, b: int8x16_t) -> int16x8_t { - let a: int8x8_t = simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]); - let b: int8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); - vmull_s8(a, b) +#[cfg_attr(test, assert_instr(ld3))] +pub unsafe fn vld3q_s64(a: *const i64) -> int64x2x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3.v2i64.p0v2i64")] + fn vld3q_s64_(ptr: *const int64x2_t) -> int64x2x3_t; + } + vld3q_s64_(a.cast()) } -/// Signed multiply long +/// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(smull2))] -pub unsafe fn vmull_high_s16(a: int16x8_t, b: int16x8_t) -> int32x4_t { - let a: int16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); - let b: int16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); - vmull_s16(a, b) +#[cfg_attr(test, assert_instr(ld3))] +pub unsafe fn vld3q_u64(a: *const u64) -> uint64x2x3_t { + transmute(vld3q_s64(transmute(a))) } -/// Signed multiply long +/// Load multiple 3-element structures to three registers +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(test, assert_instr(ld3))] +pub unsafe fn vld3q_p64(a: *const p64) -> poly64x2x3_t { + transmute(vld3q_s64(transmute(a))) +} + +/// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(smull2))] -pub unsafe fn vmull_high_s32(a: int32x4_t, b: int32x4_t) -> int64x2_t { - let a: int32x2_t = simd_shuffle2!(a, a, [2, 3]); - let b: int32x2_t = simd_shuffle2!(b, b, [2, 3]); - vmull_s32(a, b) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vld3_f64(a: *const f64) -> float64x1x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3.v1f64.p0v1f64")] + fn vld3_f64_(ptr: *const float64x1_t) -> float64x1x3_t; + } + vld3_f64_(a.cast()) } -/// Unsigned multiply long +/// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(umull2))] -pub unsafe fn vmull_high_u8(a: uint8x16_t, b: uint8x16_t) -> uint16x8_t { - let a: uint8x8_t = simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]); - let b: uint8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); - vmull_u8(a, b) +#[cfg_attr(test, assert_instr(ld3))] +pub unsafe fn vld3q_f64(a: *const f64) -> float64x2x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3.v2f64.p0v2f64")] + fn vld3q_f64_(ptr: *const float64x2_t) -> float64x2x3_t; + } + vld3q_f64_(a.cast()) } -/// Unsigned multiply long +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(umull2))] -pub unsafe fn vmull_high_u16(a: uint16x8_t, b: uint16x8_t) -> uint32x4_t { - let a: uint16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); - let b: uint16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); - vmull_u16(a, b) +#[cfg_attr(test, assert_instr(ld3r))] +pub unsafe fn vld3q_dup_s64(a: *const i64) -> int64x2x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3r.v2i64.p0i64")] + fn vld3q_dup_s64_(ptr: *const i64) -> int64x2x3_t; + } + vld3q_dup_s64_(a.cast()) } -/// Unsigned multiply long +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(umull2))] -pub unsafe fn vmull_high_u32(a: uint32x4_t, b: uint32x4_t) -> uint64x2_t { - let a: uint32x2_t = simd_shuffle2!(a, a, [2, 3]); - let b: uint32x2_t = simd_shuffle2!(b, b, [2, 3]); - vmull_u32(a, b) +#[cfg_attr(test, assert_instr(ld3r))] +pub unsafe fn vld3q_dup_u64(a: *const u64) -> uint64x2x3_t { + transmute(vld3q_dup_s64(transmute(a))) } -/// Polynomial multiply long +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[target_feature(enable = "neon,aes")] -#[cfg_attr(test, assert_instr(pmull))] -pub unsafe fn vmull_p64(a: p64, b: p64) -> p128 { +#[cfg_attr(test, assert_instr(ld3r))] +pub unsafe fn vld3q_dup_p64(a: *const p64) -> poly64x2x3_t { + transmute(vld3q_dup_s64(transmute(a))) +} + +/// Load single 3-element structure and replicate to all lanes of three registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(ld3r))] +pub unsafe fn vld3_dup_f64(a: *const f64) -> float64x1x3_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.pmull64")] - fn vmull_p64_(a: p64, b: p64) -> int8x16_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3r.v1f64.p0f64")] + fn vld3_dup_f64_(ptr: *const f64) -> float64x1x3_t; } - transmute(vmull_p64_(a, b)) + vld3_dup_f64_(a.cast()) } -/// Polynomial multiply long +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(pmull))] -pub unsafe fn vmull_high_p8(a: poly8x16_t, b: poly8x16_t) -> poly16x8_t { - let a: poly8x8_t = simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]); - let b: poly8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); - vmull_p8(a, b) +#[cfg_attr(test, assert_instr(ld3r))] +pub unsafe fn vld3q_dup_f64(a: *const f64) -> float64x2x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3r.v2f64.p0f64")] + fn vld3q_dup_f64_(ptr: *const f64) -> float64x2x3_t; + } + vld3q_dup_f64_(a.cast()) } -/// Polynomial multiply long +/// Load multiple 3-element structures to two registers #[inline] -#[target_feature(enable = "neon,aes")] -#[cfg_attr(test, assert_instr(pmull))] -pub unsafe fn vmull_high_p64(a: poly64x2_t, b: poly64x2_t) -> p128 { - vmull_p64(simd_extract(a, 1), simd_extract(b, 1)) +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(ld3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld3q_lane_s8(a: *const i8, b: int8x16x3_t) -> int8x16x3_t { + static_assert_imm4!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3lane.v16i8.p0i8")] + fn vld3q_lane_s8_(a: int8x16_t, b: int8x16_t, c: int8x16_t, n: i64, ptr: *const i8) -> int8x16x3_t; + } + vld3q_lane_s8_(b.0, b.1, b.2, LANE as i64, a.cast()) } -/// Multiply long +/// Load multiple 3-element structures to two registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(smull2))] -pub unsafe fn vmull_high_n_s16(a: int16x8_t, b: i16) -> int32x4_t { - vmull_high_s16(a, vdupq_n_s16(b)) +#[cfg_attr(test, assert_instr(ld3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld3_lane_s64(a: *const i64, b: int64x1x3_t) -> int64x1x3_t { + static_assert!(LANE : i32 where LANE == 0); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3lane.v1i64.p0i8")] + fn vld3_lane_s64_(a: int64x1_t, b: int64x1_t, c: int64x1_t, n: i64, ptr: *const i8) -> int64x1x3_t; + } + vld3_lane_s64_(b.0, b.1, b.2, LANE as i64, a.cast()) } -/// Multiply long +/// Load multiple 3-element structures to two registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(smull2))] -pub unsafe fn vmull_high_n_s32(a: int32x4_t, b: i32) -> int64x2_t { - vmull_high_s32(a, vdupq_n_s32(b)) +#[cfg_attr(test, assert_instr(ld3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld3q_lane_s64(a: *const i64, b: int64x2x3_t) -> int64x2x3_t { + static_assert_imm1!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3lane.v2i64.p0i8")] + fn vld3q_lane_s64_(a: int64x2_t, b: int64x2_t, c: int64x2_t, n: i64, ptr: *const i8) -> int64x2x3_t; + } + vld3q_lane_s64_(b.0, b.1, b.2, LANE as i64, a.cast()) } -/// Multiply long +/// Load multiple 3-element structures to three registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(umull2))] -pub unsafe fn vmull_high_n_u16(a: uint16x8_t, b: u16) -> uint32x4_t { - vmull_high_u16(a, vdupq_n_u16(b)) +#[target_feature(enable = "neon,aes")] +#[cfg_attr(test, assert_instr(ld3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld3_lane_p64(a: *const p64, b: poly64x1x3_t) -> poly64x1x3_t { + static_assert!(LANE : i32 where LANE == 0); + transmute(vld3_lane_s64::(transmute(a), transmute(b))) } -/// Multiply long +/// Load multiple 3-element structures to three registers +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(test, assert_instr(ld3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld3q_lane_p64(a: *const p64, b: poly64x2x3_t) -> poly64x2x3_t { + static_assert_imm1!(LANE); + transmute(vld3q_lane_s64::(transmute(a), transmute(b))) +} + +/// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(umull2))] -pub unsafe fn vmull_high_n_u32(a: uint32x4_t, b: u32) -> uint64x2_t { - vmull_high_u32(a, vdupq_n_u32(b)) +#[cfg_attr(test, assert_instr(ld3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld3q_lane_p8(a: *const p8, b: poly8x16x3_t) -> poly8x16x3_t { + static_assert_imm4!(LANE); + transmute(vld3q_lane_s8::(transmute(a), transmute(b))) } -/// Multiply long +/// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(smull2, LANE = 1))] +#[cfg_attr(test, assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmull_high_lane_s16(a: int16x8_t, b: int16x4_t) -> int32x4_t { - static_assert_imm2!(LANE); - vmull_high_s16(a, simd_shuffle8!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) +pub unsafe fn vld3q_lane_u8(a: *const u8, b: uint8x16x3_t) -> uint8x16x3_t { + static_assert_imm4!(LANE); + transmute(vld3q_lane_s8::(transmute(a), transmute(b))) } -/// Multiply long +/// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(smull2, LANE = 1))] +#[cfg_attr(test, assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmull_high_laneq_s16(a: int16x8_t, b: int16x8_t) -> int32x4_t { - static_assert_imm3!(LANE); - vmull_high_s16(a, simd_shuffle8!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) +pub unsafe fn vld3_lane_u64(a: *const u64, b: uint64x1x3_t) -> uint64x1x3_t { + static_assert!(LANE : i32 where LANE == 0); + transmute(vld3_lane_s64::(transmute(a), transmute(b))) } -/// Multiply long +/// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(smull2, LANE = 1))] +#[cfg_attr(test, assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmull_high_lane_s32(a: int32x4_t, b: int32x2_t) -> int64x2_t { +pub unsafe fn vld3q_lane_u64(a: *const u64, b: uint64x2x3_t) -> uint64x2x3_t { static_assert_imm1!(LANE); - vmull_high_s32(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) + transmute(vld3q_lane_s64::(transmute(a), transmute(b))) } -/// Multiply long +/// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(smull2, LANE = 1))] +#[cfg_attr(test, assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmull_high_laneq_s32(a: int32x4_t, b: int32x4_t) -> int64x2_t { - static_assert_imm2!(LANE); - vmull_high_s32(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) +pub unsafe fn vld3_lane_f64(a: *const f64, b: float64x1x3_t) -> float64x1x3_t { + static_assert!(LANE : i32 where LANE == 0); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3lane.v1f64.p0i8")] + fn vld3_lane_f64_(a: float64x1_t, b: float64x1_t, c: float64x1_t, n: i64, ptr: *const i8) -> float64x1x3_t; + } + vld3_lane_f64_(b.0, b.1, b.2, LANE as i64, a.cast()) } -/// Multiply long +/// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(umull2, LANE = 1))] +#[cfg_attr(test, assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmull_high_lane_u16(a: uint16x8_t, b: uint16x4_t) -> uint32x4_t { - static_assert_imm2!(LANE); - vmull_high_u16(a, simd_shuffle8!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) +pub unsafe fn vld3q_lane_f64(a: *const f64, b: float64x2x3_t) -> float64x2x3_t { + static_assert_imm1!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3lane.v2f64.p0i8")] + fn vld3q_lane_f64_(a: float64x2_t, b: float64x2_t, c: float64x2_t, n: i64, ptr: *const i8) -> float64x2x3_t; + } + vld3q_lane_f64_(b.0, b.1, b.2, LANE as i64, a.cast()) } -/// Multiply long +/// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(umull2, LANE = 1))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vmull_high_laneq_u16(a: uint16x8_t, b: uint16x8_t) -> uint32x4_t { - static_assert_imm3!(LANE); - vmull_high_u16(a, simd_shuffle8!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) +#[cfg_attr(test, assert_instr(ld4))] +pub unsafe fn vld4q_s64(a: *const i64) -> int64x2x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4.v2i64.p0v2i64")] + fn vld4q_s64_(ptr: *const int64x2_t) -> int64x2x4_t; + } + vld4q_s64_(a.cast()) } -/// Multiply long +/// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(umull2, LANE = 1))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vmull_high_lane_u32(a: uint32x4_t, b: uint32x2_t) -> uint64x2_t { - static_assert_imm1!(LANE); - vmull_high_u32(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) +#[cfg_attr(test, assert_instr(ld4))] +pub unsafe fn vld4q_u64(a: *const u64) -> uint64x2x4_t { + transmute(vld4q_s64(transmute(a))) } -/// Multiply long +/// Load multiple 4-element structures to four registers +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(test, assert_instr(ld4))] +pub unsafe fn vld4q_p64(a: *const p64) -> poly64x2x4_t { + transmute(vld4q_s64(transmute(a))) +} + +/// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(umull2, LANE = 1))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vmull_high_laneq_u32(a: uint32x4_t, b: uint32x4_t) -> uint64x2_t { - static_assert_imm2!(LANE); - vmull_high_u32(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vld4_f64(a: *const f64) -> float64x1x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4.v1f64.p0v1f64")] + fn vld4_f64_(ptr: *const float64x1_t) -> float64x1x4_t; + } + vld4_f64_(a.cast()) } -/// Floating-point multiply extended +/// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmulx))] -pub unsafe fn vmulx_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { +#[cfg_attr(test, assert_instr(ld4))] +pub unsafe fn vld4q_f64(a: *const f64) -> float64x2x4_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmulx.v2f32")] - fn vmulx_f32_(a: float32x2_t, b: float32x2_t) -> float32x2_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4.v2f64.p0v2f64")] + fn vld4q_f64_(ptr: *const float64x2_t) -> float64x2x4_t; } - vmulx_f32_(a, b) + vld4q_f64_(a.cast()) } -/// Floating-point multiply extended +/// Load single 4-element structure and replicate to all lanes of four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmulx))] -pub unsafe fn vmulxq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { +#[cfg_attr(test, assert_instr(ld4r))] +pub unsafe fn vld4q_dup_s64(a: *const i64) -> int64x2x4_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmulx.v4f32")] - fn vmulxq_f32_(a: float32x4_t, b: float32x4_t) -> float32x4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4r.v2i64.p0i64")] + fn vld4q_dup_s64_(ptr: *const i64) -> int64x2x4_t; } - vmulxq_f32_(a, b) + vld4q_dup_s64_(a.cast()) } -/// Floating-point multiply extended +/// Load single 4-element structure and replicate to all lanes of four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmulx))] -pub unsafe fn vmulx_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { +#[cfg_attr(test, assert_instr(ld4r))] +pub unsafe fn vld4q_dup_u64(a: *const u64) -> uint64x2x4_t { + transmute(vld4q_dup_s64(transmute(a))) +} + +/// Load single 4-element structure and replicate to all lanes of four registers +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(test, assert_instr(ld4r))] +pub unsafe fn vld4q_dup_p64(a: *const p64) -> poly64x2x4_t { + transmute(vld4q_dup_s64(transmute(a))) +} + +/// Load single 4-element structure and replicate to all lanes of four registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(ld4r))] +pub unsafe fn vld4_dup_f64(a: *const f64) -> float64x1x4_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmulx.v1f64")] - fn vmulx_f64_(a: float64x1_t, b: float64x1_t) -> float64x1_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4r.v1f64.p0f64")] + fn vld4_dup_f64_(ptr: *const f64) -> float64x1x4_t; } - vmulx_f64_(a, b) + vld4_dup_f64_(a.cast()) } -/// Floating-point multiply extended +/// Load single 4-element structure and replicate to all lanes of four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmulx))] -pub unsafe fn vmulxq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { +#[cfg_attr(test, assert_instr(ld4r))] +pub unsafe fn vld4q_dup_f64(a: *const f64) -> float64x2x4_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmulx.v2f64")] - fn vmulxq_f64_(a: float64x2_t, b: float64x2_t) -> float64x2_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4r.v2f64.p0f64")] + fn vld4q_dup_f64_(ptr: *const f64) -> float64x2x4_t; } - vmulxq_f64_(a, b) + vld4q_dup_f64_(a.cast()) } -/// Floating-point multiply extended +/// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmulx, LANE = 0))] +#[cfg_attr(test, assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmulx_lane_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { - static_assert!(LANE : i32 where LANE == 0); - vmulx_f64(a, transmute::(simd_extract(b, LANE as u32))) +pub unsafe fn vld4q_lane_s8(a: *const i8, b: int8x16x4_t) -> int8x16x4_t { + static_assert_imm4!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4lane.v16i8.p0i8")] + fn vld4q_lane_s8_(a: int8x16_t, b: int8x16_t, c: int8x16_t, d: int8x16_t, n: i64, ptr: *const i8) -> int8x16x4_t; + } + vld4q_lane_s8_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) } -/// Floating-point multiply extended +/// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmulx, LANE = 0))] +#[cfg_attr(test, assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmulx_laneq_f64(a: float64x1_t, b: float64x2_t) -> float64x1_t { - static_assert_imm1!(LANE); - vmulx_f64(a, transmute::(simd_extract(b, LANE as u32))) +pub unsafe fn vld4_lane_s64(a: *const i64, b: int64x1x4_t) -> int64x1x4_t { + static_assert!(LANE : i32 where LANE == 0); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4lane.v1i64.p0i8")] + fn vld4_lane_s64_(a: int64x1_t, b: int64x1_t, c: int64x1_t, d: int64x1_t, n: i64, ptr: *const i8) -> int64x1x4_t; + } + vld4_lane_s64_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) } -/// Floating-point multiply extended +/// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmulx, LANE = 0))] +#[cfg_attr(test, assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmulx_lane_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { +pub unsafe fn vld4q_lane_s64(a: *const i64, b: int64x2x4_t) -> int64x2x4_t { static_assert_imm1!(LANE); - vmulx_f32(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4lane.v2i64.p0i8")] + fn vld4q_lane_s64_(a: int64x2_t, b: int64x2_t, c: int64x2_t, d: int64x2_t, n: i64, ptr: *const i8) -> int64x2x4_t; + } + vld4q_lane_s64_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) } -/// Floating-point multiply extended +/// Load multiple 4-element structures to four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmulx, LANE = 0))] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(test, assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmulx_laneq_f32(a: float32x2_t, b: float32x4_t) -> float32x2_t { - static_assert_imm2!(LANE); - vmulx_f32(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) +pub unsafe fn vld4_lane_p64(a: *const p64, b: poly64x1x4_t) -> poly64x1x4_t { + static_assert!(LANE : i32 where LANE == 0); + transmute(vld4_lane_s64::(transmute(a), transmute(b))) } -/// Floating-point multiply extended +/// Load multiple 4-element structures to four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmulx, LANE = 0))] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(test, assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmulxq_lane_f32(a: float32x4_t, b: float32x2_t) -> float32x4_t { +pub unsafe fn vld4q_lane_p64(a: *const p64, b: poly64x2x4_t) -> poly64x2x4_t { static_assert_imm1!(LANE); - vmulxq_f32(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) + transmute(vld4q_lane_s64::(transmute(a), transmute(b))) } -/// Floating-point multiply extended +/// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmulx, LANE = 0))] +#[cfg_attr(test, assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmulxq_laneq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { - static_assert_imm2!(LANE); - vmulxq_f32(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) +pub unsafe fn vld4q_lane_p8(a: *const p8, b: poly8x16x4_t) -> poly8x16x4_t { + static_assert_imm4!(LANE); + transmute(vld4q_lane_s8::(transmute(a), transmute(b))) } -/// Floating-point multiply extended +/// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmulx, LANE = 0))] +#[cfg_attr(test, assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmulxq_lane_f64(a: float64x2_t, b: float64x1_t) -> float64x2_t { +pub unsafe fn vld4q_lane_u8(a: *const u8, b: uint8x16x4_t) -> uint8x16x4_t { + static_assert_imm4!(LANE); + transmute(vld4q_lane_s8::(transmute(a), transmute(b))) +} + +/// Load multiple 4-element structures to four registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(ld4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld4_lane_u64(a: *const u64, b: uint64x1x4_t) -> uint64x1x4_t { static_assert!(LANE : i32 where LANE == 0); - vmulxq_f64(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) + transmute(vld4_lane_s64::(transmute(a), transmute(b))) } -/// Floating-point multiply extended +/// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmulx, LANE = 0))] +#[cfg_attr(test, assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmulxq_laneq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { +pub unsafe fn vld4q_lane_u64(a: *const u64, b: uint64x2x4_t) -> uint64x2x4_t { static_assert_imm1!(LANE); - vmulxq_f64(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) + transmute(vld4q_lane_s64::(transmute(a), transmute(b))) } -/// Floating-point multiply extended +/// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmulx))] -pub unsafe fn vmulxs_f32(a: f32, b: f32) -> f32 { +#[cfg_attr(test, assert_instr(ld4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld4_lane_f64(a: *const f64, b: float64x1x4_t) -> float64x1x4_t { + static_assert!(LANE : i32 where LANE == 0); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmulx.f32")] - fn vmulxs_f32_(a: f32, b: f32) -> f32; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4lane.v1f64.p0i8")] + fn vld4_lane_f64_(a: float64x1_t, b: float64x1_t, c: float64x1_t, d: float64x1_t, n: i64, ptr: *const i8) -> float64x1x4_t; } - vmulxs_f32_(a, b) + vld4_lane_f64_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) } -/// Floating-point multiply extended +/// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmulx))] -pub unsafe fn vmulxd_f64(a: f64, b: f64) -> f64 { +#[cfg_attr(test, assert_instr(ld4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld4q_lane_f64(a: *const f64, b: float64x2x4_t) -> float64x2x4_t { + static_assert_imm1!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmulx.f64")] - fn vmulxd_f64_(a: f64, b: f64) -> f64; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4lane.v2f64.p0i8")] + fn vld4q_lane_f64_(a: float64x2_t, b: float64x2_t, c: float64x2_t, d: float64x2_t, n: i64, ptr: *const i8) -> float64x2x4_t; } - vmulxd_f64_(a, b) + vld4q_lane_f64_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) } -/// Floating-point multiply extended +/// Store multiple single-element structures from one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmulx, LANE = 0))] +#[cfg_attr(test, assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmulxs_lane_f32(a: f32, b: float32x2_t) -> f32 { - static_assert_imm1!(LANE); - vmulxs_f32(a, simd_extract(b, LANE as u32)) +pub unsafe fn vst1_lane_f64(a: *mut f64, b: float64x1_t) { + static_assert!(LANE : i32 where LANE == 0); + *a = simd_extract(b, LANE as u32); } -/// Floating-point multiply extended +/// Store multiple single-element structures from one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmulx, LANE = 0))] +#[cfg_attr(test, assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmulxs_laneq_f32(a: f32, b: float32x4_t) -> f32 { - static_assert_imm2!(LANE); - vmulxs_f32(a, simd_extract(b, LANE as u32)) +pub unsafe fn vst1q_lane_f64(a: *mut f64, b: float64x2_t) { + static_assert_imm1!(LANE); + *a = simd_extract(b, LANE as u32); } -/// Floating-point multiply extended +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmulx, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vmulxd_lane_f64(a: f64, b: float64x1_t) -> f64 { - static_assert!(LANE : i32 where LANE == 0); - vmulxd_f64(a, simd_extract(b, LANE as u32)) +#[cfg_attr(test, assert_instr(st1))] +pub unsafe fn vst1_f64_x2(a: *mut f64, b: float64x1x2_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x2.v1f64.p0f64")] + fn vst1_f64_x2_(a: float64x1_t, b: float64x1_t, ptr: *mut f64); + } + vst1_f64_x2_(b.0, b.1, a) } -/// Floating-point multiply extended +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmulx, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vmulxd_laneq_f64(a: f64, b: float64x2_t) -> f64 { - static_assert_imm1!(LANE); - vmulxd_f64(a, simd_extract(b, LANE as u32)) +#[cfg_attr(test, assert_instr(st1))] +pub unsafe fn vst1q_f64_x2(a: *mut f64, b: float64x2x2_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x2.v2f64.p0f64")] + fn vst1q_f64_x2_(a: float64x2_t, b: float64x2_t, ptr: *mut f64); + } + vst1q_f64_x2_(b.0, b.1, a) } -/// Floating-point fused Multiply-Add to accumulator(vector) +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmadd))] -pub unsafe fn vfma_f64(a: float64x1_t, b: float64x1_t, c: float64x1_t) -> float64x1_t { +#[cfg_attr(test, assert_instr(st1))] +pub unsafe fn vst1_f64_x3(a: *mut f64, b: float64x1x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.fma.v1f64")] - fn vfma_f64_(a: float64x1_t, b: float64x1_t, c: float64x1_t) -> float64x1_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x3.v1f64.p0f64")] + fn vst1_f64_x3_(a: float64x1_t, b: float64x1_t, c: float64x1_t, ptr: *mut f64); } - vfma_f64_(b, c, a) + vst1_f64_x3_(b.0, b.1, b.2, a) } -/// Floating-point fused Multiply-Add to accumulator(vector) +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmla))] -pub unsafe fn vfmaq_f64(a: float64x2_t, b: float64x2_t, c: float64x2_t) -> float64x2_t { +#[cfg_attr(test, assert_instr(st1))] +pub unsafe fn vst1q_f64_x3(a: *mut f64, b: float64x2x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.fma.v2f64")] - fn vfmaq_f64_(a: float64x2_t, b: float64x2_t, c: float64x2_t) -> float64x2_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x3.v2f64.p0f64")] + fn vst1q_f64_x3_(a: float64x2_t, b: float64x2_t, c: float64x2_t, ptr: *mut f64); } - vfmaq_f64_(b, c, a) + vst1q_f64_x3_(b.0, b.1, b.2, a) } -/// Floating-point fused Multiply-Add to accumulator(vector) +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmadd))] -pub unsafe fn vfma_n_f64(a: float64x1_t, b: float64x1_t, c: f64) -> float64x1_t { - vfma_f64(a, b, vdup_n_f64(c)) +#[cfg_attr(test, assert_instr(st1))] +pub unsafe fn vst1_f64_x4(a: *mut f64, b: float64x1x4_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x4.v1f64.p0f64")] + fn vst1_f64_x4_(a: float64x1_t, b: float64x1_t, c: float64x1_t, d: float64x1_t, ptr: *mut f64); + } + vst1_f64_x4_(b.0, b.1, b.2, b.3, a) } -/// Floating-point fused Multiply-Add to accumulator(vector) +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmla))] -pub unsafe fn vfmaq_n_f64(a: float64x2_t, b: float64x2_t, c: f64) -> float64x2_t { - vfmaq_f64(a, b, vdupq_n_f64(c)) +#[cfg_attr(test, assert_instr(st1))] +pub unsafe fn vst1q_f64_x4(a: *mut f64, b: float64x2x4_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x4.v2f64.p0f64")] + fn vst1q_f64_x4_(a: float64x2_t, b: float64x2_t, c: float64x2_t, d: float64x2_t, ptr: *mut f64); + } + vst1q_f64_x4_(b.0, b.1, b.2, b.3, a) } -/// Floating-point fused multiply-add to accumulator +/// Store multiple 2-element structures from two registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmla, LANE = 0))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vfma_lane_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t { - static_assert_imm1!(LANE); - vfma_f32(a, b, vdup_n_f32(simd_extract(c, LANE as u32))) +#[cfg_attr(test, assert_instr(st2))] +pub unsafe fn vst2q_s64(a: *mut i64, b: int64x2x2_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2.v2i64.p0i8")] + fn vst2q_s64_(a: int64x2_t, b: int64x2_t, ptr: *mut i8); + } + vst2q_s64_(b.0, b.1, a.cast()) } -/// Floating-point fused multiply-add to accumulator +/// Store multiple 2-element structures from two registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmla, LANE = 0))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vfma_laneq_f32(a: float32x2_t, b: float32x2_t, c: float32x4_t) -> float32x2_t { - static_assert_imm2!(LANE); - vfma_f32(a, b, vdup_n_f32(simd_extract(c, LANE as u32))) +#[cfg_attr(test, assert_instr(st2))] +pub unsafe fn vst2q_u64(a: *mut u64, b: uint64x2x2_t) { + transmute(vst2q_s64(transmute(a), transmute(b))) } -/// Floating-point fused multiply-add to accumulator +/// Store multiple 2-element structures from two registers +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(test, assert_instr(st2))] +pub unsafe fn vst2q_p64(a: *mut p64, b: poly64x2x2_t) { + transmute(vst2q_s64(transmute(a), transmute(b))) +} + +/// Store multiple 2-element structures from two registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmla, LANE = 0))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vfmaq_lane_f32(a: float32x4_t, b: float32x4_t, c: float32x2_t) -> float32x4_t { - static_assert_imm1!(LANE); - vfmaq_f32(a, b, vdupq_n_f32(simd_extract(c, LANE as u32))) +#[cfg_attr(test, assert_instr(st1))] +pub unsafe fn vst2_f64(a: *mut f64, b: float64x1x2_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2.v1f64.p0i8")] + fn vst2_f64_(a: float64x1_t, b: float64x1_t, ptr: *mut i8); + } + vst2_f64_(b.0, b.1, a.cast()) } -/// Floating-point fused multiply-add to accumulator +/// Store multiple 2-element structures from two registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmla, LANE = 0))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vfmaq_laneq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t { - static_assert_imm2!(LANE); - vfmaq_f32(a, b, vdupq_n_f32(simd_extract(c, LANE as u32))) +#[cfg_attr(test, assert_instr(st2))] +pub unsafe fn vst2q_f64(a: *mut f64, b: float64x2x2_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2.v2f64.p0i8")] + fn vst2q_f64_(a: float64x2_t, b: float64x2_t, ptr: *mut i8); + } + vst2q_f64_(b.0, b.1, a.cast()) } -/// Floating-point fused multiply-add to accumulator +/// Store multiple 2-element structures from two registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmadd, LANE = 0))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vfma_lane_f64(a: float64x1_t, b: float64x1_t, c: float64x1_t) -> float64x1_t { +#[cfg_attr(test, assert_instr(st2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2q_lane_s8(a: *mut i8, b: int8x16x2_t) { + static_assert_imm4!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2lane.v16i8.p0i8")] + fn vst2q_lane_s8_(a: int8x16_t, b: int8x16_t, n: i64, ptr: *mut i8); + } + vst2q_lane_s8_(b.0, b.1, LANE as i64, a.cast()) +} + +/// Store multiple 2-element structures from two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(st2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2_lane_s64(a: *mut i64, b: int64x1x2_t) { static_assert!(LANE : i32 where LANE == 0); - vfma_f64(a, b, vdup_n_f64(simd_extract(c, LANE as u32))) + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2lane.v1i64.p0i8")] + fn vst2_lane_s64_(a: int64x1_t, b: int64x1_t, n: i64, ptr: *mut i8); + } + vst2_lane_s64_(b.0, b.1, LANE as i64, a.cast()) } -/// Floating-point fused multiply-add to accumulator +/// Store multiple 2-element structures from two registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmla, LANE = 0))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vfma_laneq_f64(a: float64x1_t, b: float64x1_t, c: float64x2_t) -> float64x1_t { +#[cfg_attr(test, assert_instr(st2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2q_lane_s64(a: *mut i64, b: int64x2x2_t) { static_assert_imm1!(LANE); - vfma_f64(a, b, vdup_n_f64(simd_extract(c, LANE as u32))) + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2lane.v2i64.p0i8")] + fn vst2q_lane_s64_(a: int64x2_t, b: int64x2_t, n: i64, ptr: *mut i8); + } + vst2q_lane_s64_(b.0, b.1, LANE as i64, a.cast()) } -/// Floating-point fused multiply-add to accumulator +/// Store multiple 2-element structures from two registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmla, LANE = 0))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vfmaq_lane_f64(a: float64x2_t, b: float64x2_t, c: float64x1_t) -> float64x2_t { +#[cfg_attr(test, assert_instr(st2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2q_lane_u8(a: *mut u8, b: uint8x16x2_t) { + static_assert_imm4!(LANE); + transmute(vst2q_lane_s8::(transmute(a), transmute(b))) +} + +/// Store multiple 2-element structures from two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(st2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2_lane_u64(a: *mut u64, b: uint64x1x2_t) { static_assert!(LANE : i32 where LANE == 0); - vfmaq_f64(a, b, vdupq_n_f64(simd_extract(c, LANE as u32))) + transmute(vst2_lane_s64::(transmute(a), transmute(b))) } -/// Floating-point fused multiply-add to accumulator +/// Store multiple 2-element structures from two registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmla, LANE = 0))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vfmaq_laneq_f64(a: float64x2_t, b: float64x2_t, c: float64x2_t) -> float64x2_t { +#[cfg_attr(test, assert_instr(st2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2q_lane_u64(a: *mut u64, b: uint64x2x2_t) { static_assert_imm1!(LANE); - vfmaq_f64(a, b, vdupq_n_f64(simd_extract(c, LANE as u32))) + transmute(vst2q_lane_s64::(transmute(a), transmute(b))) } -/// Floating-point fused multiply-add to accumulator +/// Store multiple 2-element structures from two registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmla, LANE = 0))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vfmas_lane_f32(a: f32, b: f32, c: float32x2_t) -> f32 { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.fma.f32")] - fn vfmas_lane_f32_(a: f32, b: f32, c: f32) -> f32; - } +#[cfg_attr(test, assert_instr(st2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2q_lane_p8(a: *mut p8, b: poly8x16x2_t) { + static_assert_imm4!(LANE); + transmute(vst2q_lane_s8::(transmute(a), transmute(b))) +} + +/// Store multiple 2-element structures from two registers +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(test, assert_instr(st2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2_lane_p64(a: *mut p64, b: poly64x1x2_t) { + static_assert!(LANE : i32 where LANE == 0); + transmute(vst2_lane_s64::(transmute(a), transmute(b))) +} + +/// Store multiple 2-element structures from two registers +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(test, assert_instr(st2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2q_lane_p64(a: *mut p64, b: poly64x2x2_t) { static_assert_imm1!(LANE); - let c: f32 = simd_extract(c, LANE as u32); - vfmas_lane_f32_(b, c, a) + transmute(vst2q_lane_s64::(transmute(a), transmute(b))) } -/// Floating-point fused multiply-add to accumulator +/// Store multiple 2-element structures from two registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmla, LANE = 0))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vfmas_laneq_f32(a: f32, b: f32, c: float32x4_t) -> f32 { +#[cfg_attr(test, assert_instr(st2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2_lane_f64(a: *mut f64, b: float64x1x2_t) { + static_assert!(LANE : i32 where LANE == 0); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.fma.f32")] - fn vfmas_laneq_f32_(a: f32, b: f32, c: f32) -> f32; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2lane.v1f64.p0i8")] + fn vst2_lane_f64_(a: float64x1_t, b: float64x1_t, n: i64, ptr: *mut i8); } - static_assert_imm2!(LANE); - let c: f32 = simd_extract(c, LANE as u32); - vfmas_laneq_f32_(b, c, a) + vst2_lane_f64_(b.0, b.1, LANE as i64, a.cast()) } -/// Floating-point fused multiply-add to accumulator +/// Store multiple 2-element structures from two registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmadd, LANE = 0))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vfmad_lane_f64(a: f64, b: f64, c: float64x1_t) -> f64 { +#[cfg_attr(test, assert_instr(st2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2q_lane_f64(a: *mut f64, b: float64x2x2_t) { + static_assert_imm1!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.fma.f64")] - fn vfmad_lane_f64_(a: f64, b: f64, c: f64) -> f64; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2lane.v2f64.p0i8")] + fn vst2q_lane_f64_(a: float64x2_t, b: float64x2_t, n: i64, ptr: *mut i8); } - static_assert!(LANE : i32 where LANE == 0); - let c: f64 = simd_extract(c, LANE as u32); - vfmad_lane_f64_(b, c, a) + vst2q_lane_f64_(b.0, b.1, LANE as i64, a.cast()) } -/// Floating-point fused multiply-add to accumulator +/// Store multiple 3-element structures from three registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmla, LANE = 0))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vfmad_laneq_f64(a: f64, b: f64, c: float64x2_t) -> f64 { +#[cfg_attr(test, assert_instr(st3))] +pub unsafe fn vst3q_s64(a: *mut i64, b: int64x2x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.fma.f64")] - fn vfmad_laneq_f64_(a: f64, b: f64, c: f64) -> f64; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3.v2i64.p0i8")] + fn vst3q_s64_(a: int64x2_t, b: int64x2_t, c: int64x2_t, ptr: *mut i8); } - static_assert_imm1!(LANE); - let c: f64 = simd_extract(c, LANE as u32); - vfmad_laneq_f64_(b, c, a) + vst3q_s64_(b.0, b.1, b.2, a.cast()) } -/// Floating-point fused multiply-subtract from accumulator +/// Store multiple 3-element structures from three registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmsub))] -pub unsafe fn vfms_f64(a: float64x1_t, b: float64x1_t, c: float64x1_t) -> float64x1_t { - let b: float64x1_t = simd_neg(b); - vfma_f64(a, b, c) +#[cfg_attr(test, assert_instr(st3))] +pub unsafe fn vst3q_u64(a: *mut u64, b: uint64x2x3_t) { + transmute(vst3q_s64(transmute(a), transmute(b))) } -/// Floating-point fused multiply-subtract from accumulator +/// Store multiple 3-element structures from three registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmls))] -pub unsafe fn vfmsq_f64(a: float64x2_t, b: float64x2_t, c: float64x2_t) -> float64x2_t { - let b: float64x2_t = simd_neg(b); - vfmaq_f64(a, b, c) +#[target_feature(enable = "neon,aes")] +#[cfg_attr(test, assert_instr(st3))] +pub unsafe fn vst3q_p64(a: *mut p64, b: poly64x2x3_t) { + transmute(vst3q_s64(transmute(a), transmute(b))) } -/// Floating-point fused Multiply-subtract to accumulator(vector) +/// Store multiple 3-element structures from three registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmsub))] -pub unsafe fn vfms_n_f64(a: float64x1_t, b: float64x1_t, c: f64) -> float64x1_t { - vfms_f64(a, b, vdup_n_f64(c)) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vst3_f64(a: *mut f64, b: float64x1x3_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3.v1f64.p0i8")] + fn vst3_f64_(a: float64x1_t, b: float64x1_t, c: float64x1_t, ptr: *mut i8); + } + vst3_f64_(b.0, b.1, b.2, a.cast()) } -/// Floating-point fused Multiply-subtract to accumulator(vector) +/// Store multiple 3-element structures from three registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmls))] -pub unsafe fn vfmsq_n_f64(a: float64x2_t, b: float64x2_t, c: f64) -> float64x2_t { - vfmsq_f64(a, b, vdupq_n_f64(c)) +#[cfg_attr(test, assert_instr(st3))] +pub unsafe fn vst3q_f64(a: *mut f64, b: float64x2x3_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3.v2f64.p0i8")] + fn vst3q_f64_(a: float64x2_t, b: float64x2_t, c: float64x2_t, ptr: *mut i8); + } + vst3q_f64_(b.0, b.1, b.2, a.cast()) } -/// Floating-point fused multiply-subtract to accumulator +/// Store multiple 3-element structures from three registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmls, LANE = 0))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vfms_lane_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t { - static_assert_imm1!(LANE); - vfms_f32(a, b, vdup_n_f32(simd_extract(c, LANE as u32))) +#[cfg_attr(test, assert_instr(st3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3q_lane_s8(a: *mut i8, b: int8x16x3_t) { + static_assert_imm4!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3lane.v16i8.p0i8")] + fn vst3q_lane_s8_(a: int8x16_t, b: int8x16_t, c: int8x16_t, n: i64, ptr: *mut i8); + } + vst3q_lane_s8_(b.0, b.1, b.2, LANE as i64, a.cast()) } -/// Floating-point fused multiply-subtract to accumulator +/// Store multiple 3-element structures from three registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmls, LANE = 0))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vfms_laneq_f32(a: float32x2_t, b: float32x2_t, c: float32x4_t) -> float32x2_t { - static_assert_imm2!(LANE); - vfms_f32(a, b, vdup_n_f32(simd_extract(c, LANE as u32))) +#[cfg_attr(test, assert_instr(st3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3_lane_s64(a: *mut i64, b: int64x1x3_t) { + static_assert!(LANE : i32 where LANE == 0); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3lane.v1i64.p0i8")] + fn vst3_lane_s64_(a: int64x1_t, b: int64x1_t, c: int64x1_t, n: i64, ptr: *mut i8); + } + vst3_lane_s64_(b.0, b.1, b.2, LANE as i64, a.cast()) } -/// Floating-point fused multiply-subtract to accumulator +/// Store multiple 3-element structures from three registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmls, LANE = 0))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vfmsq_lane_f32(a: float32x4_t, b: float32x4_t, c: float32x2_t) -> float32x4_t { +#[cfg_attr(test, assert_instr(st3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3q_lane_s64(a: *mut i64, b: int64x2x3_t) { static_assert_imm1!(LANE); - vfmsq_f32(a, b, vdupq_n_f32(simd_extract(c, LANE as u32))) + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3lane.v2i64.p0i8")] + fn vst3q_lane_s64_(a: int64x2_t, b: int64x2_t, c: int64x2_t, n: i64, ptr: *mut i8); + } + vst3q_lane_s64_(b.0, b.1, b.2, LANE as i64, a.cast()) } -/// Floating-point fused multiply-subtract to accumulator +/// Store multiple 3-element structures from three registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmls, LANE = 0))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vfmsq_laneq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t { - static_assert_imm2!(LANE); - vfmsq_f32(a, b, vdupq_n_f32(simd_extract(c, LANE as u32))) +#[cfg_attr(test, assert_instr(st3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3q_lane_u8(a: *mut u8, b: uint8x16x3_t) { + static_assert_imm4!(LANE); + transmute(vst3q_lane_s8::(transmute(a), transmute(b))) } -/// Floating-point fused multiply-subtract to accumulator +/// Store multiple 3-element structures from three registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmsub, LANE = 0))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vfms_lane_f64(a: float64x1_t, b: float64x1_t, c: float64x1_t) -> float64x1_t { +#[cfg_attr(test, assert_instr(st3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3_lane_u64(a: *mut u64, b: uint64x1x3_t) { static_assert!(LANE : i32 where LANE == 0); - vfms_f64(a, b, vdup_n_f64(simd_extract(c, LANE as u32))) + transmute(vst3_lane_s64::(transmute(a), transmute(b))) } -/// Floating-point fused multiply-subtract to accumulator +/// Store multiple 3-element structures from three registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmls, LANE = 0))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vfms_laneq_f64(a: float64x1_t, b: float64x1_t, c: float64x2_t) -> float64x1_t { +#[cfg_attr(test, assert_instr(st3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3q_lane_u64(a: *mut u64, b: uint64x2x3_t) { static_assert_imm1!(LANE); - vfms_f64(a, b, vdup_n_f64(simd_extract(c, LANE as u32))) -} - -/// Floating-point fused multiply-subtract to accumulator -#[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmls, LANE = 0))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vfmsq_lane_f64(a: float64x2_t, b: float64x2_t, c: float64x1_t) -> float64x2_t { - static_assert!(LANE : i32 where LANE == 0); - vfmsq_f64(a, b, vdupq_n_f64(simd_extract(c, LANE as u32))) + transmute(vst3q_lane_s64::(transmute(a), transmute(b))) } -/// Floating-point fused multiply-subtract to accumulator +/// Store multiple 3-element structures from three registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmls, LANE = 0))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vfmsq_laneq_f64(a: float64x2_t, b: float64x2_t, c: float64x2_t) -> float64x2_t { - static_assert_imm1!(LANE); - vfmsq_f64(a, b, vdupq_n_f64(simd_extract(c, LANE as u32))) +#[cfg_attr(test, assert_instr(st3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3q_lane_p8(a: *mut p8, b: poly8x16x3_t) { + static_assert_imm4!(LANE); + transmute(vst3q_lane_s8::(transmute(a), transmute(b))) } -/// Floating-point fused multiply-subtract to accumulator +/// Store multiple 3-element structures from three registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmls, LANE = 0))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vfmss_lane_f32(a: f32, b: f32, c: float32x2_t) -> f32 { - vfmas_lane_f32::(a, -b, c) +#[target_feature(enable = "neon,aes")] +#[cfg_attr(test, assert_instr(st3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3_lane_p64(a: *mut p64, b: poly64x1x3_t) { + static_assert!(LANE : i32 where LANE == 0); + transmute(vst3_lane_s64::(transmute(a), transmute(b))) } -/// Floating-point fused multiply-subtract to accumulator +/// Store multiple 3-element structures from three registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmls, LANE = 0))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vfmss_laneq_f32(a: f32, b: f32, c: float32x4_t) -> f32 { - vfmas_laneq_f32::(a, -b, c) +#[target_feature(enable = "neon,aes")] +#[cfg_attr(test, assert_instr(st3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3q_lane_p64(a: *mut p64, b: poly64x2x3_t) { + static_assert_imm1!(LANE); + transmute(vst3q_lane_s64::(transmute(a), transmute(b))) } -/// Floating-point fused multiply-subtract to accumulator +/// Store multiple 3-element structures from three registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmsub, LANE = 0))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vfmsd_lane_f64(a: f64, b: f64, c: float64x1_t) -> f64 { - vfmad_lane_f64::(a, -b, c) +#[cfg_attr(test, assert_instr(st3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3_lane_f64(a: *mut f64, b: float64x1x3_t) { + static_assert!(LANE : i32 where LANE == 0); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3lane.v1f64.p0i8")] + fn vst3_lane_f64_(a: float64x1_t, b: float64x1_t, c: float64x1_t, n: i64, ptr: *mut i8); + } + vst3_lane_f64_(b.0, b.1, b.2, LANE as i64, a.cast()) } -/// Floating-point fused multiply-subtract to accumulator +/// Store multiple 3-element structures from three registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmls, LANE = 0))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vfmsd_laneq_f64(a: f64, b: f64, c: float64x2_t) -> f64 { - vfmad_laneq_f64::(a, -b, c) +#[cfg_attr(test, assert_instr(st3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3q_lane_f64(a: *mut f64, b: float64x2x3_t) { + static_assert_imm1!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3lane.v2f64.p0i8")] + fn vst3q_lane_f64_(a: float64x2_t, b: float64x2_t, c: float64x2_t, n: i64, ptr: *mut i8); + } + vst3q_lane_f64_(b.0, b.1, b.2, LANE as i64, a.cast()) } -/// Divide +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fdiv))] -pub unsafe fn vdiv_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { - simd_div(a, b) +#[cfg_attr(test, assert_instr(st4))] +pub unsafe fn vst4q_s64(a: *mut i64, b: int64x2x4_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4.v2i64.p0i8")] + fn vst4q_s64_(a: int64x2_t, b: int64x2_t, c: int64x2_t, d: int64x2_t, ptr: *mut i8); + } + vst4q_s64_(b.0, b.1, b.2, b.3, a.cast()) } -/// Divide +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fdiv))] -pub unsafe fn vdivq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { - simd_div(a, b) +#[cfg_attr(test, assert_instr(st4))] +pub unsafe fn vst4q_u64(a: *mut u64, b: uint64x2x4_t) { + transmute(vst4q_s64(transmute(a), transmute(b))) } -/// Divide +/// Store multiple 4-element structures from four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fdiv))] -pub unsafe fn vdiv_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { - simd_div(a, b) +#[target_feature(enable = "neon,aes")] +#[cfg_attr(test, assert_instr(st4))] +pub unsafe fn vst4q_p64(a: *mut p64, b: poly64x2x4_t) { + transmute(vst4q_s64(transmute(a), transmute(b))) } -/// Divide +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fdiv))] -pub unsafe fn vdivq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { - simd_div(a, b) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vst4_f64(a: *mut f64, b: float64x1x4_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4.v1f64.p0i8")] + fn vst4_f64_(a: float64x1_t, b: float64x1_t, c: float64x1_t, d: float64x1_t, ptr: *mut i8); + } + vst4_f64_(b.0, b.1, b.2, b.3, a.cast()) } -/// Subtract +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fsub))] -pub unsafe fn vsub_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { - simd_sub(a, b) +#[cfg_attr(test, assert_instr(st4))] +pub unsafe fn vst4q_f64(a: *mut f64, b: float64x2x4_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4.v2f64.p0i8")] + fn vst4q_f64_(a: float64x2_t, b: float64x2_t, c: float64x2_t, d: float64x2_t, ptr: *mut i8); + } + vst4q_f64_(b.0, b.1, b.2, b.3, a.cast()) } -/// Subtract +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fsub))] -pub unsafe fn vsubq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { - simd_sub(a, b) +#[cfg_attr(test, assert_instr(st4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4q_lane_s8(a: *mut i8, b: int8x16x4_t) { + static_assert_imm4!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4lane.v16i8.p0i8")] + fn vst4q_lane_s8_(a: int8x16_t, b: int8x16_t, c: int8x16_t, d: int8x16_t, n: i64, ptr: *mut i8); + } + vst4q_lane_s8_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) } -/// Signed Add Long across Vector +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(saddlv))] -pub unsafe fn vaddlv_s16(a: int16x4_t) -> i32 { +#[cfg_attr(test, assert_instr(st4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4_lane_s64(a: *mut i64, b: int64x1x4_t) { + static_assert!(LANE : i32 where LANE == 0); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.saddlv.i32.v4i16")] - fn vaddlv_s16_(a: int16x4_t) -> i32; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4lane.v1i64.p0i8")] + fn vst4_lane_s64_(a: int64x1_t, b: int64x1_t, c: int64x1_t, d: int64x1_t, n: i64, ptr: *mut i8); } - vaddlv_s16_(a) + vst4_lane_s64_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) } -/// Signed Add Long across Vector +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(saddlv))] -pub unsafe fn vaddlvq_s16(a: int16x8_t) -> i32 { +#[cfg_attr(test, assert_instr(st4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4q_lane_s64(a: *mut i64, b: int64x2x4_t) { + static_assert_imm1!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.saddlv.i32.v8i16")] - fn vaddlvq_s16_(a: int16x8_t) -> i32; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4lane.v2i64.p0i8")] + fn vst4q_lane_s64_(a: int64x2_t, b: int64x2_t, c: int64x2_t, d: int64x2_t, n: i64, ptr: *mut i8); } - vaddlvq_s16_(a) + vst4q_lane_s64_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) } -/// Signed Add Long across Vector +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(saddlp))] -pub unsafe fn vaddlv_s32(a: int32x2_t) -> i64 { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.saddlv.i64.v2i32")] - fn vaddlv_s32_(a: int32x2_t) -> i64; - } - vaddlv_s32_(a) +#[cfg_attr(test, assert_instr(st4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4q_lane_u8(a: *mut u8, b: uint8x16x4_t) { + static_assert_imm4!(LANE); + transmute(vst4q_lane_s8::(transmute(a), transmute(b))) } -/// Signed Add Long across Vector +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(saddlv))] -pub unsafe fn vaddlvq_s32(a: int32x4_t) -> i64 { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.saddlv.i64.v4i32")] - fn vaddlvq_s32_(a: int32x4_t) -> i64; - } - vaddlvq_s32_(a) +#[cfg_attr(test, assert_instr(st4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4_lane_u64(a: *mut u64, b: uint64x1x4_t) { + static_assert!(LANE : i32 where LANE == 0); + transmute(vst4_lane_s64::(transmute(a), transmute(b))) } -/// Unsigned Add Long across Vector +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uaddlv))] -pub unsafe fn vaddlv_u16(a: uint16x4_t) -> u32 { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uaddlv.i32.v4i16")] - fn vaddlv_u16_(a: uint16x4_t) -> u32; - } - vaddlv_u16_(a) +#[cfg_attr(test, assert_instr(st4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4q_lane_u64(a: *mut u64, b: uint64x2x4_t) { + static_assert_imm1!(LANE); + transmute(vst4q_lane_s64::(transmute(a), transmute(b))) } -/// Unsigned Add Long across Vector +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uaddlv))] -pub unsafe fn vaddlvq_u16(a: uint16x8_t) -> u32 { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uaddlv.i32.v8i16")] - fn vaddlvq_u16_(a: uint16x8_t) -> u32; - } - vaddlvq_u16_(a) +#[cfg_attr(test, assert_instr(st4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4q_lane_p8(a: *mut p8, b: poly8x16x4_t) { + static_assert_imm4!(LANE); + transmute(vst4q_lane_s8::(transmute(a), transmute(b))) } -/// Unsigned Add Long across Vector +/// Store multiple 4-element structures from four registers +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(test, assert_instr(st4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4_lane_p64(a: *mut p64, b: poly64x1x4_t) { + static_assert!(LANE : i32 where LANE == 0); + transmute(vst4_lane_s64::(transmute(a), transmute(b))) +} + +/// Store multiple 4-element structures from four registers +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(test, assert_instr(st4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4q_lane_p64(a: *mut p64, b: poly64x2x4_t) { + static_assert_imm1!(LANE); + transmute(vst4q_lane_s64::(transmute(a), transmute(b))) +} + +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uaddlp))] -pub unsafe fn vaddlv_u32(a: uint32x2_t) -> u64 { +#[cfg_attr(test, assert_instr(st4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4_lane_f64(a: *mut f64, b: float64x1x4_t) { + static_assert!(LANE : i32 where LANE == 0); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uaddlv.i64.v2i32")] - fn vaddlv_u32_(a: uint32x2_t) -> u64; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4lane.v1f64.p0i8")] + fn vst4_lane_f64_(a: float64x1_t, b: float64x1_t, c: float64x1_t, d: float64x1_t, n: i64, ptr: *mut i8); } - vaddlv_u32_(a) + vst4_lane_f64_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) } -/// Unsigned Add Long across Vector +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uaddlv))] -pub unsafe fn vaddlvq_u32(a: uint32x4_t) -> u64 { +#[cfg_attr(test, assert_instr(st4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4q_lane_f64(a: *mut f64, b: float64x2x4_t) { + static_assert_imm1!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uaddlv.i64.v4i32")] - fn vaddlvq_u32_(a: uint32x4_t) -> u64; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4lane.v2f64.p0i8")] + fn vst4q_lane_f64_(a: float64x2_t, b: float64x2_t, c: float64x2_t, d: float64x2_t, n: i64, ptr: *mut i8); } - vaddlvq_u32_(a) + vst4q_lane_f64_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) } -/// Signed Subtract Wide +/// Multiply #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(ssubw))] -pub unsafe fn vsubw_high_s8(a: int16x8_t, b: int8x16_t) -> int16x8_t { - let c: int8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); - simd_sub(a, simd_cast(c)) +#[cfg_attr(test, assert_instr(fmul))] +pub unsafe fn vmul_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { + simd_mul(a, b) } -/// Signed Subtract Wide +/// Multiply #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(ssubw))] -pub unsafe fn vsubw_high_s16(a: int32x4_t, b: int16x8_t) -> int32x4_t { - let c: int16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); - simd_sub(a, simd_cast(c)) +#[cfg_attr(test, assert_instr(fmul))] +pub unsafe fn vmulq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { + simd_mul(a, b) } -/// Signed Subtract Wide +/// Vector multiply by scalar #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(ssubw))] -pub unsafe fn vsubw_high_s32(a: int64x2_t, b: int32x4_t) -> int64x2_t { - let c: int32x2_t = simd_shuffle2!(b, b, [2, 3]); - simd_sub(a, simd_cast(c)) +#[cfg_attr(test, assert_instr(fmul))] +pub unsafe fn vmul_n_f64(a: float64x1_t, b: f64) -> float64x1_t { + simd_mul(a, vdup_n_f64(b)) } -/// Unsigned Subtract Wide +/// Vector multiply by scalar #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(usubw))] -pub unsafe fn vsubw_high_u8(a: uint16x8_t, b: uint8x16_t) -> uint16x8_t { - let c: uint8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); - simd_sub(a, simd_cast(c)) +#[cfg_attr(test, assert_instr(fmul))] +pub unsafe fn vmulq_n_f64(a: float64x2_t, b: f64) -> float64x2_t { + simd_mul(a, vdupq_n_f64(b)) } -/// Unsigned Subtract Wide +/// Floating-point multiply #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(usubw))] -pub unsafe fn vsubw_high_u16(a: uint32x4_t, b: uint16x8_t) -> uint32x4_t { - let c: uint16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); - simd_sub(a, simd_cast(c)) +#[cfg_attr(test, assert_instr(fmul, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmul_lane_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { + static_assert!(LANE : i32 where LANE == 0); + simd_mul(a, transmute::(simd_extract(b, LANE as u32))) } -/// Unsigned Subtract Wide +/// Floating-point multiply #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(usubw))] -pub unsafe fn vsubw_high_u32(a: uint64x2_t, b: uint32x4_t) -> uint64x2_t { - let c: uint32x2_t = simd_shuffle2!(b, b, [2, 3]); - simd_sub(a, simd_cast(c)) +#[cfg_attr(test, assert_instr(fmul, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmul_laneq_f64(a: float64x1_t, b: float64x2_t) -> float64x1_t { + static_assert_imm1!(LANE); + simd_mul(a, transmute::(simd_extract(b, LANE as u32))) } -/// Signed Subtract Long +/// Floating-point multiply #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(ssubl))] -pub unsafe fn vsubl_high_s8(a: int8x16_t, b: int8x16_t) -> int16x8_t { - let c: int8x8_t = simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]); - let d: int16x8_t = simd_cast(c); - let e: int8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); - let f: int16x8_t = simd_cast(e); - simd_sub(d, f) +#[cfg_attr(test, assert_instr(fmul, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmulq_lane_f64(a: float64x2_t, b: float64x1_t) -> float64x2_t { + static_assert!(LANE : i32 where LANE == 0); + simd_mul(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) } -/// Signed Subtract Long +/// Floating-point multiply #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(ssubl))] -pub unsafe fn vsubl_high_s16(a: int16x8_t, b: int16x8_t) -> int32x4_t { - let c: int16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); - let d: int32x4_t = simd_cast(c); - let e: int16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); - let f: int32x4_t = simd_cast(e); - simd_sub(d, f) +#[cfg_attr(test, assert_instr(fmul, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmulq_laneq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { + static_assert_imm1!(LANE); + simd_mul(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) } -/// Signed Subtract Long +/// Floating-point multiply #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(ssubl))] -pub unsafe fn vsubl_high_s32(a: int32x4_t, b: int32x4_t) -> int64x2_t { - let c: int32x2_t = simd_shuffle2!(a, a, [2, 3]); - let d: int64x2_t = simd_cast(c); - let e: int32x2_t = simd_shuffle2!(b, b, [2, 3]); - let f: int64x2_t = simd_cast(e); - simd_sub(d, f) +#[cfg_attr(test, assert_instr(fmul, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmuls_lane_f32(a: f32, b: float32x2_t) -> f32 { + static_assert_imm1!(LANE); + let b: f32 = simd_extract(b, LANE as u32); + a * b } -/// Unsigned Subtract Long +/// Floating-point multiply #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(usubl))] -pub unsafe fn vsubl_high_u8(a: uint8x16_t, b: uint8x16_t) -> uint16x8_t { - let c: uint8x8_t = simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]); - let d: uint16x8_t = simd_cast(c); - let e: uint8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); - let f: uint16x8_t = simd_cast(e); - simd_sub(d, f) +#[cfg_attr(test, assert_instr(fmul, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmuls_laneq_f32(a: f32, b: float32x4_t) -> f32 { + static_assert_imm2!(LANE); + let b: f32 = simd_extract(b, LANE as u32); + a * b } -/// Unsigned Subtract Long +/// Floating-point multiply #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(usubl))] -pub unsafe fn vsubl_high_u16(a: uint16x8_t, b: uint16x8_t) -> uint32x4_t { - let c: uint16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); - let d: uint32x4_t = simd_cast(c); - let e: uint16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); - let f: uint32x4_t = simd_cast(e); - simd_sub(d, f) +#[cfg_attr(test, assert_instr(fmul, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmuld_lane_f64(a: f64, b: float64x1_t) -> f64 { + static_assert!(LANE : i32 where LANE == 0); + let b: f64 = simd_extract(b, LANE as u32); + a * b } -/// Unsigned Subtract Long +/// Floating-point multiply #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(usubl))] -pub unsafe fn vsubl_high_u32(a: uint32x4_t, b: uint32x4_t) -> uint64x2_t { - let c: uint32x2_t = simd_shuffle2!(a, a, [2, 3]); - let d: uint64x2_t = simd_cast(c); - let e: uint32x2_t = simd_shuffle2!(b, b, [2, 3]); - let f: uint64x2_t = simd_cast(e); - simd_sub(d, f) +#[cfg_attr(test, assert_instr(fmul, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmuld_laneq_f64(a: f64, b: float64x2_t) -> f64 { + static_assert_imm1!(LANE); + let b: f64 = simd_extract(b, LANE as u32); + a * b } -/// Maximum (vector) +/// Signed multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmax))] -pub unsafe fn vmax_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmax.v1f64")] - fn vmax_f64_(a: float64x1_t, b: float64x1_t) -> float64x1_t; - } - vmax_f64_(a, b) +#[cfg_attr(test, assert_instr(smull2))] +pub unsafe fn vmull_high_s8(a: int8x16_t, b: int8x16_t) -> int16x8_t { + let a: int8x8_t = simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]); + let b: int8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); + vmull_s8(a, b) } -/// Maximum (vector) +/// Signed multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmax))] -pub unsafe fn vmaxq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmax.v2f64")] - fn vmaxq_f64_(a: float64x2_t, b: float64x2_t) -> float64x2_t; - } - vmaxq_f64_(a, b) +#[cfg_attr(test, assert_instr(smull2))] +pub unsafe fn vmull_high_s16(a: int16x8_t, b: int16x8_t) -> int32x4_t { + let a: int16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); + let b: int16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); + vmull_s16(a, b) } -/// Floating-point Maximun Number (vector) +/// Signed multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmaxnm))] -pub unsafe fn vmaxnm_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmaxnm.v1f64")] - fn vmaxnm_f64_(a: float64x1_t, b: float64x1_t) -> float64x1_t; - } - vmaxnm_f64_(a, b) +#[cfg_attr(test, assert_instr(smull2))] +pub unsafe fn vmull_high_s32(a: int32x4_t, b: int32x4_t) -> int64x2_t { + let a: int32x2_t = simd_shuffle2!(a, a, [2, 3]); + let b: int32x2_t = simd_shuffle2!(b, b, [2, 3]); + vmull_s32(a, b) } -/// Floating-point Maximun Number (vector) +/// Unsigned multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmaxnm))] -pub unsafe fn vmaxnmq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmaxnm.v2f64")] - fn vmaxnmq_f64_(a: float64x2_t, b: float64x2_t) -> float64x2_t; - } - vmaxnmq_f64_(a, b) +#[cfg_attr(test, assert_instr(umull2))] +pub unsafe fn vmull_high_u8(a: uint8x16_t, b: uint8x16_t) -> uint16x8_t { + let a: uint8x8_t = simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]); + let b: uint8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); + vmull_u8(a, b) } -/// Floating-point Maximum Number Pairwise (vector). +/// Unsigned multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmaxnmp))] -pub unsafe fn vpmaxnm_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmaxnmp.v2f32")] - fn vpmaxnm_f32_(a: float32x2_t, b: float32x2_t) -> float32x2_t; - } - vpmaxnm_f32_(a, b) +#[cfg_attr(test, assert_instr(umull2))] +pub unsafe fn vmull_high_u16(a: uint16x8_t, b: uint16x8_t) -> uint32x4_t { + let a: uint16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); + let b: uint16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); + vmull_u16(a, b) } -/// Floating-point Maximum Number Pairwise (vector). +/// Unsigned multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmaxnmp))] -pub unsafe fn vpmaxnmq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmaxnmp.v2f64")] - fn vpmaxnmq_f64_(a: float64x2_t, b: float64x2_t) -> float64x2_t; - } - vpmaxnmq_f64_(a, b) +#[cfg_attr(test, assert_instr(umull2))] +pub unsafe fn vmull_high_u32(a: uint32x4_t, b: uint32x4_t) -> uint64x2_t { + let a: uint32x2_t = simd_shuffle2!(a, a, [2, 3]); + let b: uint32x2_t = simd_shuffle2!(b, b, [2, 3]); + vmull_u32(a, b) } -/// Floating-point Maximum Number Pairwise (vector). +/// Polynomial multiply long #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmaxnmp))] -pub unsafe fn vpmaxnmq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { +#[target_feature(enable = "neon,aes")] +#[cfg_attr(test, assert_instr(pmull))] +pub unsafe fn vmull_p64(a: p64, b: p64) -> p128 { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmaxnmp.v4f32")] - fn vpmaxnmq_f32_(a: float32x4_t, b: float32x4_t) -> float32x4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.pmull64")] + fn vmull_p64_(a: p64, b: p64) -> int8x16_t; } - vpmaxnmq_f32_(a, b) + transmute(vmull_p64_(a, b)) } -/// Minimum (vector) +/// Polynomial multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmin))] -pub unsafe fn vmin_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmin.v1f64")] - fn vmin_f64_(a: float64x1_t, b: float64x1_t) -> float64x1_t; - } - vmin_f64_(a, b) +#[cfg_attr(test, assert_instr(pmull))] +pub unsafe fn vmull_high_p8(a: poly8x16_t, b: poly8x16_t) -> poly16x8_t { + let a: poly8x8_t = simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]); + let b: poly8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); + vmull_p8(a, b) } -/// Minimum (vector) +/// Polynomial multiply long #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fmin))] -pub unsafe fn vminq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmin.v2f64")] - fn vminq_f64_(a: float64x2_t, b: float64x2_t) -> float64x2_t; - } - vminq_f64_(a, b) +#[target_feature(enable = "neon,aes")] +#[cfg_attr(test, assert_instr(pmull))] +pub unsafe fn vmull_high_p64(a: poly64x2_t, b: poly64x2_t) -> p128 { + vmull_p64(simd_extract(a, 1), simd_extract(b, 1)) } -/// Floating-point Minimun Number (vector) +/// Multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fminnm))] -pub unsafe fn vminnm_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fminnm.v1f64")] - fn vminnm_f64_(a: float64x1_t, b: float64x1_t) -> float64x1_t; - } - vminnm_f64_(a, b) +#[cfg_attr(test, assert_instr(smull2))] +pub unsafe fn vmull_high_n_s16(a: int16x8_t, b: i16) -> int32x4_t { + vmull_high_s16(a, vdupq_n_s16(b)) } -/// Floating-point Minimun Number (vector) +/// Multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fminnm))] -pub unsafe fn vminnmq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fminnm.v2f64")] - fn vminnmq_f64_(a: float64x2_t, b: float64x2_t) -> float64x2_t; - } - vminnmq_f64_(a, b) +#[cfg_attr(test, assert_instr(smull2))] +pub unsafe fn vmull_high_n_s32(a: int32x4_t, b: i32) -> int64x2_t { + vmull_high_s32(a, vdupq_n_s32(b)) } -/// Floating-point Minimum Number Pairwise (vector). +/// Multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fminnmp))] -pub unsafe fn vpminnm_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fminnmp.v2f32")] - fn vpminnm_f32_(a: float32x2_t, b: float32x2_t) -> float32x2_t; - } - vpminnm_f32_(a, b) +#[cfg_attr(test, assert_instr(umull2))] +pub unsafe fn vmull_high_n_u16(a: uint16x8_t, b: u16) -> uint32x4_t { + vmull_high_u16(a, vdupq_n_u16(b)) } -/// Floating-point Minimum Number Pairwise (vector). +/// Multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fminnmp))] -pub unsafe fn vpminnmq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fminnmp.v2f64")] - fn vpminnmq_f64_(a: float64x2_t, b: float64x2_t) -> float64x2_t; - } - vpminnmq_f64_(a, b) +#[cfg_attr(test, assert_instr(umull2))] +pub unsafe fn vmull_high_n_u32(a: uint32x4_t, b: u32) -> uint64x2_t { + vmull_high_u32(a, vdupq_n_u32(b)) } -/// Floating-point Minimum Number Pairwise (vector). +/// Multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fminnmp))] -pub unsafe fn vpminnmq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fminnmp.v4f32")] - fn vpminnmq_f32_(a: float32x4_t, b: float32x4_t) -> float32x4_t; - } - vpminnmq_f32_(a, b) +#[cfg_attr(test, assert_instr(smull2, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmull_high_lane_s16(a: int16x8_t, b: int16x4_t) -> int32x4_t { + static_assert_imm2!(LANE); + vmull_high_s16(a, simd_shuffle8!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) } -/// Signed saturating doubling multiply long +/// Multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmull))] -pub unsafe fn vqdmullh_s16(a: i16, b: i16) -> i32 { - let a: int16x4_t = vdup_n_s16(a); - let b: int16x4_t = vdup_n_s16(b); - simd_extract(vqdmull_s16(a, b), 0) +#[cfg_attr(test, assert_instr(smull2, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmull_high_laneq_s16(a: int16x8_t, b: int16x8_t) -> int32x4_t { + static_assert_imm3!(LANE); + vmull_high_s16(a, simd_shuffle8!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) } -/// Signed saturating doubling multiply long +/// Multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmull))] -pub unsafe fn vqdmulls_s32(a: i32, b: i32) -> i64 { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqdmulls.scalar")] - fn vqdmulls_s32_(a: i32, b: i32) -> i64; - } - vqdmulls_s32_(a, b) +#[cfg_attr(test, assert_instr(smull2, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmull_high_lane_s32(a: int32x4_t, b: int32x2_t) -> int64x2_t { + static_assert_imm1!(LANE); + vmull_high_s32(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) } -/// Signed saturating doubling multiply long +/// Multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmull2))] -pub unsafe fn vqdmull_high_s16(a: int16x8_t, b: int16x8_t) -> int32x4_t { - let a: int16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); - let b: int16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); - vqdmull_s16(a, b) +#[cfg_attr(test, assert_instr(smull2, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmull_high_laneq_s32(a: int32x4_t, b: int32x4_t) -> int64x2_t { + static_assert_imm2!(LANE); + vmull_high_s32(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) } -/// Signed saturating doubling multiply long +/// Multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmull2))] -pub unsafe fn vqdmull_high_s32(a: int32x4_t, b: int32x4_t) -> int64x2_t { - let a: int32x2_t = simd_shuffle2!(a, a, [2, 3]); - let b: int32x2_t = simd_shuffle2!(b, b, [2, 3]); - vqdmull_s32(a, b) +#[cfg_attr(test, assert_instr(umull2, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmull_high_lane_u16(a: uint16x8_t, b: uint16x4_t) -> uint32x4_t { + static_assert_imm2!(LANE); + vmull_high_u16(a, simd_shuffle8!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) } -/// Signed saturating doubling multiply long +/// Multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmull2))] -pub unsafe fn vqdmull_high_n_s16(a: int16x8_t, b: i16) -> int32x4_t { - let a: int16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); - let b: int16x4_t = vdup_n_s16(b); - vqdmull_s16(a, b) +#[cfg_attr(test, assert_instr(umull2, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmull_high_laneq_u16(a: uint16x8_t, b: uint16x8_t) -> uint32x4_t { + static_assert_imm3!(LANE); + vmull_high_u16(a, simd_shuffle8!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) } -/// Signed saturating doubling multiply long +/// Multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmull2))] -pub unsafe fn vqdmull_high_n_s32(a: int32x4_t, b: i32) -> int64x2_t { - let a: int32x2_t = simd_shuffle2!(a, a, [2, 3]); - let b: int32x2_t = vdup_n_s32(b); - vqdmull_s32(a, b) +#[cfg_attr(test, assert_instr(umull2, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmull_high_lane_u32(a: uint32x4_t, b: uint32x2_t) -> uint64x2_t { + static_assert_imm1!(LANE); + vmull_high_u32(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) } -/// Vector saturating doubling long multiply by scalar +/// Multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmull, N = 4))] +#[cfg_attr(test, assert_instr(umull2, LANE = 1))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vqdmull_laneq_s16(a: int16x4_t, b: int16x8_t) -> int32x4_t { - static_assert_imm3!(N); - let b: int16x4_t = simd_shuffle4!(b, b, [N as u32, N as u32, N as u32, N as u32]); - vqdmull_s16(a, b) +pub unsafe fn vmull_high_laneq_u32(a: uint32x4_t, b: uint32x4_t) -> uint64x2_t { + static_assert_imm2!(LANE); + vmull_high_u32(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) } -/// Vector saturating doubling long multiply by scalar +/// Floating-point multiply extended #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmull, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqdmull_laneq_s32(a: int32x2_t, b: int32x4_t) -> int64x2_t { - static_assert_imm2!(N); - let b: int32x2_t = simd_shuffle2!(b, b, [N as u32, N as u32]); - vqdmull_s32(a, b) +#[cfg_attr(test, assert_instr(fmulx))] +pub unsafe fn vmulx_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmulx.v2f32")] + fn vmulx_f32_(a: float32x2_t, b: float32x2_t) -> float32x2_t; + } + vmulx_f32_(a, b) } -/// Signed saturating doubling multiply long +/// Floating-point multiply extended #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmull, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqdmullh_lane_s16(a: i16, b: int16x4_t) -> i32 { - static_assert_imm2!(N); - let b: i16 = simd_extract(b, N as u32); - vqdmullh_s16(a, b) +#[cfg_attr(test, assert_instr(fmulx))] +pub unsafe fn vmulxq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmulx.v4f32")] + fn vmulxq_f32_(a: float32x4_t, b: float32x4_t) -> float32x4_t; + } + vmulxq_f32_(a, b) } -/// Signed saturating doubling multiply long +/// Floating-point multiply extended #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmull, N = 4))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqdmullh_laneq_s16(a: i16, b: int16x8_t) -> i32 { - static_assert_imm3!(N); - let b: i16 = simd_extract(b, N as u32); - vqdmullh_s16(a, b) +#[cfg_attr(test, assert_instr(fmulx))] +pub unsafe fn vmulx_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmulx.v1f64")] + fn vmulx_f64_(a: float64x1_t, b: float64x1_t) -> float64x1_t; + } + vmulx_f64_(a, b) } -/// Signed saturating doubling multiply long +/// Floating-point multiply extended #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmull, N = 1))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqdmulls_lane_s32(a: i32, b: int32x2_t) -> i64 { - static_assert_imm1!(N); - let b: i32 = simd_extract(b, N as u32); - vqdmulls_s32(a, b) +#[cfg_attr(test, assert_instr(fmulx))] +pub unsafe fn vmulxq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmulx.v2f64")] + fn vmulxq_f64_(a: float64x2_t, b: float64x2_t) -> float64x2_t; + } + vmulxq_f64_(a, b) } -/// Signed saturating doubling multiply long +/// Floating-point multiply extended #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmull, N = 2))] +#[cfg_attr(test, assert_instr(fmulx, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vqdmulls_laneq_s32(a: i32, b: int32x4_t) -> i64 { - static_assert_imm2!(N); - let b: i32 = simd_extract(b, N as u32); - vqdmulls_s32(a, b) +pub unsafe fn vmulx_lane_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { + static_assert!(LANE : i32 where LANE == 0); + vmulx_f64(a, transmute::(simd_extract(b, LANE as u32))) } -/// Signed saturating doubling multiply long +/// Floating-point multiply extended #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmull2, N = 2))] +#[cfg_attr(test, assert_instr(fmulx, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vqdmull_high_lane_s16(a: int16x8_t, b: int16x4_t) -> int32x4_t { - static_assert_imm2!(N); - let a: int16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); - let b: int16x4_t = simd_shuffle4!(b, b, [N as u32, N as u32, N as u32, N as u32]); - vqdmull_s16(a, b) +pub unsafe fn vmulx_laneq_f64(a: float64x1_t, b: float64x2_t) -> float64x1_t { + static_assert_imm1!(LANE); + vmulx_f64(a, transmute::(simd_extract(b, LANE as u32))) } -/// Signed saturating doubling multiply long +/// Floating-point multiply extended #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmull2, N = 1))] +#[cfg_attr(test, assert_instr(fmulx, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vqdmull_high_lane_s32(a: int32x4_t, b: int32x2_t) -> int64x2_t { - static_assert_imm1!(N); - let a: int32x2_t = simd_shuffle2!(a, a, [2, 3]); - let b: int32x2_t = simd_shuffle2!(b, b, [N as u32, N as u32]); - vqdmull_s32(a, b) +pub unsafe fn vmulx_lane_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { + static_assert_imm1!(LANE); + vmulx_f32(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) } -/// Signed saturating doubling multiply long +/// Floating-point multiply extended #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmull2, N = 4))] +#[cfg_attr(test, assert_instr(fmulx, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vqdmull_high_laneq_s16(a: int16x8_t, b: int16x8_t) -> int32x4_t { - static_assert_imm3!(N); - let a: int16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); - let b: int16x4_t = simd_shuffle4!(b, b, [N as u32, N as u32, N as u32, N as u32]); - vqdmull_s16(a, b) +pub unsafe fn vmulx_laneq_f32(a: float32x2_t, b: float32x4_t) -> float32x2_t { + static_assert_imm2!(LANE); + vmulx_f32(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) } -/// Signed saturating doubling multiply long +/// Floating-point multiply extended #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmull2, N = 2))] +#[cfg_attr(test, assert_instr(fmulx, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vqdmull_high_laneq_s32(a: int32x4_t, b: int32x4_t) -> int64x2_t { - static_assert_imm2!(N); - let a: int32x2_t = simd_shuffle2!(a, a, [2, 3]); - let b: int32x2_t = simd_shuffle2!(b, b, [N as u32, N as u32]); - vqdmull_s32(a, b) +pub unsafe fn vmulxq_lane_f32(a: float32x4_t, b: float32x2_t) -> float32x4_t { + static_assert_imm1!(LANE); + vmulxq_f32(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) } -/// Signed saturating doubling multiply-add long +/// Floating-point multiply extended #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmlal2))] -pub unsafe fn vqdmlal_high_s16(a: int32x4_t, b: int16x8_t, c: int16x8_t) -> int32x4_t { - vqaddq_s32(a, vqdmull_high_s16(b, c)) +#[cfg_attr(test, assert_instr(fmulx, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmulxq_laneq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { + static_assert_imm2!(LANE); + vmulxq_f32(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) } -/// Signed saturating doubling multiply-add long +/// Floating-point multiply extended #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmlal2))] -pub unsafe fn vqdmlal_high_s32(a: int64x2_t, b: int32x4_t, c: int32x4_t) -> int64x2_t { - vqaddq_s64(a, vqdmull_high_s32(b, c)) +#[cfg_attr(test, assert_instr(fmulx, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmulxq_lane_f64(a: float64x2_t, b: float64x1_t) -> float64x2_t { + static_assert!(LANE : i32 where LANE == 0); + vmulxq_f64(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) } -/// Signed saturating doubling multiply-add long +/// Floating-point multiply extended #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmlal2))] -pub unsafe fn vqdmlal_high_n_s16(a: int32x4_t, b: int16x8_t, c: i16) -> int32x4_t { - vqaddq_s32(a, vqdmull_high_n_s16(b, c)) +#[cfg_attr(test, assert_instr(fmulx, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmulxq_laneq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { + static_assert_imm1!(LANE); + vmulxq_f64(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) } -/// Signed saturating doubling multiply-add long +/// Floating-point multiply extended #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmlal2))] -pub unsafe fn vqdmlal_high_n_s32(a: int64x2_t, b: int32x4_t, c: i32) -> int64x2_t { - vqaddq_s64(a, vqdmull_high_n_s32(b, c)) +#[cfg_attr(test, assert_instr(fmulx))] +pub unsafe fn vmulxs_f32(a: f32, b: f32) -> f32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmulx.f32")] + fn vmulxs_f32_(a: f32, b: f32) -> f32; + } + vmulxs_f32_(a, b) } -/// Vector widening saturating doubling multiply accumulate with scalar +/// Floating-point multiply extended #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmlal, N = 2))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqdmlal_laneq_s16(a: int32x4_t, b: int16x4_t, c: int16x8_t) -> int32x4_t { - static_assert_imm3!(N); - vqaddq_s32(a, vqdmull_laneq_s16::(b, c)) +#[cfg_attr(test, assert_instr(fmulx))] +pub unsafe fn vmulxd_f64(a: f64, b: f64) -> f64 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmulx.f64")] + fn vmulxd_f64_(a: f64, b: f64) -> f64; + } + vmulxd_f64_(a, b) } -/// Vector widening saturating doubling multiply accumulate with scalar +/// Floating-point multiply extended #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmlal, N = 1))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqdmlal_laneq_s32(a: int64x2_t, b: int32x2_t, c: int32x4_t) -> int64x2_t { - static_assert_imm2!(N); - vqaddq_s64(a, vqdmull_laneq_s32::(b, c)) +#[cfg_attr(test, assert_instr(fmulx, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmulxs_lane_f32(a: f32, b: float32x2_t) -> f32 { + static_assert_imm1!(LANE); + vmulxs_f32(a, simd_extract(b, LANE as u32)) } -/// Signed saturating doubling multiply-add long +/// Floating-point multiply extended #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmlal2, N = 1))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqdmlal_high_lane_s16(a: int32x4_t, b: int16x8_t, c: int16x4_t) -> int32x4_t { - static_assert_imm2!(N); - vqaddq_s32(a, vqdmull_high_lane_s16::(b, c)) +#[cfg_attr(test, assert_instr(fmulx, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmulxs_laneq_f32(a: f32, b: float32x4_t) -> f32 { + static_assert_imm2!(LANE); + vmulxs_f32(a, simd_extract(b, LANE as u32)) } -/// Signed saturating doubling multiply-add long +/// Floating-point multiply extended #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmlal2, N = 1))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqdmlal_high_laneq_s16(a: int32x4_t, b: int16x8_t, c: int16x8_t) -> int32x4_t { - static_assert_imm3!(N); - vqaddq_s32(a, vqdmull_high_laneq_s16::(b, c)) +#[cfg_attr(test, assert_instr(fmulx, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmulxd_lane_f64(a: f64, b: float64x1_t) -> f64 { + static_assert!(LANE : i32 where LANE == 0); + vmulxd_f64(a, simd_extract(b, LANE as u32)) } -/// Signed saturating doubling multiply-add long +/// Floating-point multiply extended #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmlal2, N = 1))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqdmlal_high_lane_s32(a: int64x2_t, b: int32x4_t, c: int32x2_t) -> int64x2_t { - static_assert_imm1!(N); - vqaddq_s64(a, vqdmull_high_lane_s32::(b, c)) +#[cfg_attr(test, assert_instr(fmulx, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmulxd_laneq_f64(a: f64, b: float64x2_t) -> f64 { + static_assert_imm1!(LANE); + vmulxd_f64(a, simd_extract(b, LANE as u32)) } -/// Signed saturating doubling multiply-add long +/// Floating-point fused Multiply-Add to accumulator(vector) #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmlal2, N = 1))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqdmlal_high_laneq_s32(a: int64x2_t, b: int32x4_t, c: int32x4_t) -> int64x2_t { - static_assert_imm2!(N); - vqaddq_s64(a, vqdmull_high_laneq_s32::(b, c)) +#[cfg_attr(test, assert_instr(fmadd))] +pub unsafe fn vfma_f64(a: float64x1_t, b: float64x1_t, c: float64x1_t) -> float64x1_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.fma.v1f64")] + fn vfma_f64_(a: float64x1_t, b: float64x1_t, c: float64x1_t) -> float64x1_t; + } + vfma_f64_(b, c, a) } -/// Signed saturating doubling multiply-subtract long +/// Floating-point fused Multiply-Add to accumulator(vector) #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmlsl2))] -pub unsafe fn vqdmlsl_high_s16(a: int32x4_t, b: int16x8_t, c: int16x8_t) -> int32x4_t { - vqsubq_s32(a, vqdmull_high_s16(b, c)) +#[cfg_attr(test, assert_instr(fmla))] +pub unsafe fn vfmaq_f64(a: float64x2_t, b: float64x2_t, c: float64x2_t) -> float64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.fma.v2f64")] + fn vfmaq_f64_(a: float64x2_t, b: float64x2_t, c: float64x2_t) -> float64x2_t; + } + vfmaq_f64_(b, c, a) } -/// Signed saturating doubling multiply-subtract long +/// Floating-point fused Multiply-Add to accumulator(vector) #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmlsl2))] -pub unsafe fn vqdmlsl_high_s32(a: int64x2_t, b: int32x4_t, c: int32x4_t) -> int64x2_t { - vqsubq_s64(a, vqdmull_high_s32(b, c)) +#[cfg_attr(test, assert_instr(fmadd))] +pub unsafe fn vfma_n_f64(a: float64x1_t, b: float64x1_t, c: f64) -> float64x1_t { + vfma_f64(a, b, vdup_n_f64(c)) } -/// Signed saturating doubling multiply-subtract long +/// Floating-point fused Multiply-Add to accumulator(vector) #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmlsl2))] -pub unsafe fn vqdmlsl_high_n_s16(a: int32x4_t, b: int16x8_t, c: i16) -> int32x4_t { - vqsubq_s32(a, vqdmull_high_n_s16(b, c)) +#[cfg_attr(test, assert_instr(fmla))] +pub unsafe fn vfmaq_n_f64(a: float64x2_t, b: float64x2_t, c: f64) -> float64x2_t { + vfmaq_f64(a, b, vdupq_n_f64(c)) } -/// Signed saturating doubling multiply-subtract long +/// Floating-point fused multiply-add to accumulator #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmlsl2))] -pub unsafe fn vqdmlsl_high_n_s32(a: int64x2_t, b: int32x4_t, c: i32) -> int64x2_t { - vqsubq_s64(a, vqdmull_high_n_s32(b, c)) +#[cfg_attr(test, assert_instr(fmla, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vfma_lane_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t { + static_assert_imm1!(LANE); + vfma_f32(a, b, vdup_n_f32(simd_extract(c, LANE as u32))) } -/// Vector widening saturating doubling multiply subtract with scalar +/// Floating-point fused multiply-add to accumulator #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmlsl, N = 2))] +#[cfg_attr(test, assert_instr(fmla, LANE = 0))] #[rustc_legacy_const_generics(3)] -pub unsafe fn vqdmlsl_laneq_s16(a: int32x4_t, b: int16x4_t, c: int16x8_t) -> int32x4_t { - static_assert_imm3!(N); - vqsubq_s32(a, vqdmull_laneq_s16::(b, c)) +pub unsafe fn vfma_laneq_f32(a: float32x2_t, b: float32x2_t, c: float32x4_t) -> float32x2_t { + static_assert_imm2!(LANE); + vfma_f32(a, b, vdup_n_f32(simd_extract(c, LANE as u32))) } -/// Vector widening saturating doubling multiply subtract with scalar +/// Floating-point fused multiply-add to accumulator #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmlsl, N = 1))] +#[cfg_attr(test, assert_instr(fmla, LANE = 0))] #[rustc_legacy_const_generics(3)] -pub unsafe fn vqdmlsl_laneq_s32(a: int64x2_t, b: int32x2_t, c: int32x4_t) -> int64x2_t { - static_assert_imm2!(N); - vqsubq_s64(a, vqdmull_laneq_s32::(b, c)) +pub unsafe fn vfmaq_lane_f32(a: float32x4_t, b: float32x4_t, c: float32x2_t) -> float32x4_t { + static_assert_imm1!(LANE); + vfmaq_f32(a, b, vdupq_n_f32(simd_extract(c, LANE as u32))) } -/// Signed saturating doubling multiply-subtract long +/// Floating-point fused multiply-add to accumulator #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmlsl2, N = 1))] +#[cfg_attr(test, assert_instr(fmla, LANE = 0))] #[rustc_legacy_const_generics(3)] -pub unsafe fn vqdmlsl_high_lane_s16(a: int32x4_t, b: int16x8_t, c: int16x4_t) -> int32x4_t { - static_assert_imm2!(N); - vqsubq_s32(a, vqdmull_high_lane_s16::(b, c)) +pub unsafe fn vfmaq_laneq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t { + static_assert_imm2!(LANE); + vfmaq_f32(a, b, vdupq_n_f32(simd_extract(c, LANE as u32))) } -/// Signed saturating doubling multiply-subtract long +/// Floating-point fused multiply-add to accumulator #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmlsl2, N = 1))] +#[cfg_attr(test, assert_instr(fmadd, LANE = 0))] #[rustc_legacy_const_generics(3)] -pub unsafe fn vqdmlsl_high_laneq_s16(a: int32x4_t, b: int16x8_t, c: int16x8_t) -> int32x4_t { - static_assert_imm3!(N); - vqsubq_s32(a, vqdmull_high_laneq_s16::(b, c)) +pub unsafe fn vfma_lane_f64(a: float64x1_t, b: float64x1_t, c: float64x1_t) -> float64x1_t { + static_assert!(LANE : i32 where LANE == 0); + vfma_f64(a, b, vdup_n_f64(simd_extract(c, LANE as u32))) } -/// Signed saturating doubling multiply-subtract long +/// Floating-point fused multiply-add to accumulator #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmlsl2, N = 1))] +#[cfg_attr(test, assert_instr(fmla, LANE = 0))] #[rustc_legacy_const_generics(3)] -pub unsafe fn vqdmlsl_high_lane_s32(a: int64x2_t, b: int32x4_t, c: int32x2_t) -> int64x2_t { - static_assert_imm1!(N); - vqsubq_s64(a, vqdmull_high_lane_s32::(b, c)) +pub unsafe fn vfma_laneq_f64(a: float64x1_t, b: float64x1_t, c: float64x2_t) -> float64x1_t { + static_assert_imm1!(LANE); + vfma_f64(a, b, vdup_n_f64(simd_extract(c, LANE as u32))) } -/// Signed saturating doubling multiply-subtract long +/// Floating-point fused multiply-add to accumulator #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmlsl2, N = 1))] +#[cfg_attr(test, assert_instr(fmla, LANE = 0))] #[rustc_legacy_const_generics(3)] -pub unsafe fn vqdmlsl_high_laneq_s32(a: int64x2_t, b: int32x4_t, c: int32x4_t) -> int64x2_t { - static_assert_imm2!(N); - vqsubq_s64(a, vqdmull_high_laneq_s32::(b, c)) +pub unsafe fn vfmaq_lane_f64(a: float64x2_t, b: float64x2_t, c: float64x1_t) -> float64x2_t { + static_assert!(LANE : i32 where LANE == 0); + vfmaq_f64(a, b, vdupq_n_f64(simd_extract(c, LANE as u32))) } -/// Signed saturating doubling multiply returning high half +/// Floating-point fused multiply-add to accumulator #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmulh))] -pub unsafe fn vqdmulhh_s16(a: i16, b: i16) -> i16 { - let a: int16x4_t = vdup_n_s16(a); - let b: int16x4_t = vdup_n_s16(b); - simd_extract(vqdmulh_s16(a, b), 0) +#[cfg_attr(test, assert_instr(fmla, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vfmaq_laneq_f64(a: float64x2_t, b: float64x2_t, c: float64x2_t) -> float64x2_t { + static_assert_imm1!(LANE); + vfmaq_f64(a, b, vdupq_n_f64(simd_extract(c, LANE as u32))) } -/// Signed saturating doubling multiply returning high half +/// Floating-point fused multiply-add to accumulator #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmulh))] -pub unsafe fn vqdmulhs_s32(a: i32, b: i32) -> i32 { - let a: int32x2_t = vdup_n_s32(a); - let b: int32x2_t = vdup_n_s32(b); - simd_extract(vqdmulh_s32(a, b), 0) +#[cfg_attr(test, assert_instr(fmla, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vfmas_lane_f32(a: f32, b: f32, c: float32x2_t) -> f32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.fma.f32")] + fn vfmas_lane_f32_(a: f32, b: f32, c: f32) -> f32; + } + static_assert_imm1!(LANE); + let c: f32 = simd_extract(c, LANE as u32); + vfmas_lane_f32_(b, c, a) } -/// Signed saturating doubling multiply returning high half +/// Floating-point fused multiply-add to accumulator #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmulh, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqdmulhh_lane_s16(a: i16, b: int16x4_t) -> i16 { - static_assert_imm2!(N); - let b: i16 = simd_extract(b, N as u32); - vqdmulhh_s16(a, b) +#[cfg_attr(test, assert_instr(fmla, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vfmas_laneq_f32(a: f32, b: f32, c: float32x4_t) -> f32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.fma.f32")] + fn vfmas_laneq_f32_(a: f32, b: f32, c: f32) -> f32; + } + static_assert_imm2!(LANE); + let c: f32 = simd_extract(c, LANE as u32); + vfmas_laneq_f32_(b, c, a) } -/// Signed saturating doubling multiply returning high half +/// Floating-point fused multiply-add to accumulator #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmulh, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqdmulhh_laneq_s16(a: i16, b: int16x8_t) -> i16 { - static_assert_imm3!(N); - let b: i16 = simd_extract(b, N as u32); - vqdmulhh_s16(a, b) +#[cfg_attr(test, assert_instr(fmadd, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vfmad_lane_f64(a: f64, b: f64, c: float64x1_t) -> f64 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.fma.f64")] + fn vfmad_lane_f64_(a: f64, b: f64, c: f64) -> f64; + } + static_assert!(LANE : i32 where LANE == 0); + let c: f64 = simd_extract(c, LANE as u32); + vfmad_lane_f64_(b, c, a) } -/// Signed saturating doubling multiply returning high half +/// Floating-point fused multiply-add to accumulator #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmulh, N = 1))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqdmulhs_lane_s32(a: i32, b: int32x2_t) -> i32 { - static_assert_imm1!(N); - let b: i32 = simd_extract(b, N as u32); - vqdmulhs_s32(a, b) +#[cfg_attr(test, assert_instr(fmla, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vfmad_laneq_f64(a: f64, b: f64, c: float64x2_t) -> f64 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.fma.f64")] + fn vfmad_laneq_f64_(a: f64, b: f64, c: f64) -> f64; + } + static_assert_imm1!(LANE); + let c: f64 = simd_extract(c, LANE as u32); + vfmad_laneq_f64_(b, c, a) } -/// Signed saturating doubling multiply returning high half +/// Floating-point fused multiply-subtract from accumulator #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqdmulh, N = 1))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqdmulhs_laneq_s32(a: i32, b: int32x4_t) -> i32 { - static_assert_imm2!(N); - let b: i32 = simd_extract(b, N as u32); - vqdmulhs_s32(a, b) +#[cfg_attr(test, assert_instr(fmsub))] +pub unsafe fn vfms_f64(a: float64x1_t, b: float64x1_t, c: float64x1_t) -> float64x1_t { + let b: float64x1_t = simd_neg(b); + vfma_f64(a, b, c) } -/// Saturating extract narrow +/// Floating-point fused multiply-subtract from accumulator #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqxtn))] -pub unsafe fn vqmovnh_s16(a: i16) -> i8 { - simd_extract(vqmovn_s16(vdupq_n_s16(a)), 0) +#[cfg_attr(test, assert_instr(fmls))] +pub unsafe fn vfmsq_f64(a: float64x2_t, b: float64x2_t, c: float64x2_t) -> float64x2_t { + let b: float64x2_t = simd_neg(b); + vfmaq_f64(a, b, c) } -/// Saturating extract narrow +/// Floating-point fused Multiply-subtract to accumulator(vector) #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqxtn))] -pub unsafe fn vqmovns_s32(a: i32) -> i16 { - simd_extract(vqmovn_s32(vdupq_n_s32(a)), 0) +#[cfg_attr(test, assert_instr(fmsub))] +pub unsafe fn vfms_n_f64(a: float64x1_t, b: float64x1_t, c: f64) -> float64x1_t { + vfms_f64(a, b, vdup_n_f64(c)) } -/// Saturating extract narrow +/// Floating-point fused Multiply-subtract to accumulator(vector) #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uqxtn))] -pub unsafe fn vqmovnh_u16(a: u16) -> u8 { - simd_extract(vqmovn_u16(vdupq_n_u16(a)), 0) +#[cfg_attr(test, assert_instr(fmls))] +pub unsafe fn vfmsq_n_f64(a: float64x2_t, b: float64x2_t, c: f64) -> float64x2_t { + vfmsq_f64(a, b, vdupq_n_f64(c)) } -/// Saturating extract narrow +/// Floating-point fused multiply-subtract to accumulator #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uqxtn))] -pub unsafe fn vqmovns_u32(a: u32) -> u16 { - simd_extract(vqmovn_u32(vdupq_n_u32(a)), 0) +#[cfg_attr(test, assert_instr(fmls, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vfms_lane_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t { + static_assert_imm1!(LANE); + vfms_f32(a, b, vdup_n_f32(simd_extract(c, LANE as u32))) } -/// Saturating extract narrow +/// Floating-point fused multiply-subtract to accumulator #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqxtn))] -pub unsafe fn vqmovnd_s64(a: i64) -> i32 { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.scalar.sqxtn.i32.i64")] - fn vqmovnd_s64_(a: i64) -> i32; - } - vqmovnd_s64_(a) +#[cfg_attr(test, assert_instr(fmls, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vfms_laneq_f32(a: float32x2_t, b: float32x2_t, c: float32x4_t) -> float32x2_t { + static_assert_imm2!(LANE); + vfms_f32(a, b, vdup_n_f32(simd_extract(c, LANE as u32))) } -/// Saturating extract narrow +/// Floating-point fused multiply-subtract to accumulator #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uqxtn))] -pub unsafe fn vqmovnd_u64(a: u64) -> u32 { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.scalar.uqxtn.i32.i64")] - fn vqmovnd_u64_(a: u64) -> u32; - } - vqmovnd_u64_(a) +#[cfg_attr(test, assert_instr(fmls, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vfmsq_lane_f32(a: float32x4_t, b: float32x4_t, c: float32x2_t) -> float32x4_t { + static_assert_imm1!(LANE); + vfmsq_f32(a, b, vdupq_n_f32(simd_extract(c, LANE as u32))) } -/// Signed saturating extract narrow +/// Floating-point fused multiply-subtract to accumulator #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqxtn2))] -pub unsafe fn vqmovn_high_s16(a: int8x8_t, b: int16x8_t) -> int8x16_t { - simd_shuffle16!(a, vqmovn_s16(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) +#[cfg_attr(test, assert_instr(fmls, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vfmsq_laneq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t { + static_assert_imm2!(LANE); + vfmsq_f32(a, b, vdupq_n_f32(simd_extract(c, LANE as u32))) } -/// Signed saturating extract narrow +/// Floating-point fused multiply-subtract to accumulator #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqxtn2))] -pub unsafe fn vqmovn_high_s32(a: int16x4_t, b: int32x4_t) -> int16x8_t { - simd_shuffle8!(a, vqmovn_s32(b), [0, 1, 2, 3, 4, 5, 6, 7]) +#[cfg_attr(test, assert_instr(fmsub, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vfms_lane_f64(a: float64x1_t, b: float64x1_t, c: float64x1_t) -> float64x1_t { + static_assert!(LANE : i32 where LANE == 0); + vfms_f64(a, b, vdup_n_f64(simd_extract(c, LANE as u32))) } -/// Signed saturating extract narrow +/// Floating-point fused multiply-subtract to accumulator #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqxtn2))] -pub unsafe fn vqmovn_high_s64(a: int32x2_t, b: int64x2_t) -> int32x4_t { - simd_shuffle4!(a, vqmovn_s64(b), [0, 1, 2, 3]) +#[cfg_attr(test, assert_instr(fmls, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vfms_laneq_f64(a: float64x1_t, b: float64x1_t, c: float64x2_t) -> float64x1_t { + static_assert_imm1!(LANE); + vfms_f64(a, b, vdup_n_f64(simd_extract(c, LANE as u32))) } -/// Signed saturating extract narrow +/// Floating-point fused multiply-subtract to accumulator #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uqxtn2))] -pub unsafe fn vqmovn_high_u16(a: uint8x8_t, b: uint16x8_t) -> uint8x16_t { - simd_shuffle16!(a, vqmovn_u16(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) +#[cfg_attr(test, assert_instr(fmls, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vfmsq_lane_f64(a: float64x2_t, b: float64x2_t, c: float64x1_t) -> float64x2_t { + static_assert!(LANE : i32 where LANE == 0); + vfmsq_f64(a, b, vdupq_n_f64(simd_extract(c, LANE as u32))) } -/// Signed saturating extract narrow +/// Floating-point fused multiply-subtract to accumulator #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uqxtn2))] -pub unsafe fn vqmovn_high_u32(a: uint16x4_t, b: uint32x4_t) -> uint16x8_t { - simd_shuffle8!(a, vqmovn_u32(b), [0, 1, 2, 3, 4, 5, 6, 7]) +#[cfg_attr(test, assert_instr(fmls, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vfmsq_laneq_f64(a: float64x2_t, b: float64x2_t, c: float64x2_t) -> float64x2_t { + static_assert_imm1!(LANE); + vfmsq_f64(a, b, vdupq_n_f64(simd_extract(c, LANE as u32))) } -/// Signed saturating extract narrow +/// Floating-point fused multiply-subtract to accumulator #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uqxtn2))] -pub unsafe fn vqmovn_high_u64(a: uint32x2_t, b: uint64x2_t) -> uint32x4_t { - simd_shuffle4!(a, vqmovn_u64(b), [0, 1, 2, 3]) +#[cfg_attr(test, assert_instr(fmls, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vfmss_lane_f32(a: f32, b: f32, c: float32x2_t) -> f32 { + vfmas_lane_f32::(a, -b, c) } -/// Signed saturating extract unsigned narrow +/// Floating-point fused multiply-subtract to accumulator #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqxtun))] -pub unsafe fn vqmovunh_s16(a: i16) -> u8 { - simd_extract(vqmovun_s16(vdupq_n_s16(a)), 0) +#[cfg_attr(test, assert_instr(fmls, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vfmss_laneq_f32(a: f32, b: f32, c: float32x4_t) -> f32 { + vfmas_laneq_f32::(a, -b, c) } -/// Signed saturating extract unsigned narrow +/// Floating-point fused multiply-subtract to accumulator #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqxtun))] -pub unsafe fn vqmovuns_s32(a: i32) -> u16 { - simd_extract(vqmovun_s32(vdupq_n_s32(a)), 0) +#[cfg_attr(test, assert_instr(fmsub, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vfmsd_lane_f64(a: f64, b: f64, c: float64x1_t) -> f64 { + vfmad_lane_f64::(a, -b, c) } -/// Signed saturating extract unsigned narrow +/// Floating-point fused multiply-subtract to accumulator #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqxtun))] -pub unsafe fn vqmovund_s64(a: i64) -> u32 { - simd_extract(vqmovun_s64(vdupq_n_s64(a)), 0) +#[cfg_attr(test, assert_instr(fmls, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vfmsd_laneq_f64(a: f64, b: f64, c: float64x2_t) -> f64 { + vfmad_laneq_f64::(a, -b, c) } -/// Signed saturating extract unsigned narrow +/// Divide #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqxtun2))] -pub unsafe fn vqmovun_high_s16(a: uint8x8_t, b: int16x8_t) -> uint8x16_t { - simd_shuffle16!(a, vqmovun_s16(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) +#[cfg_attr(test, assert_instr(fdiv))] +pub unsafe fn vdiv_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { + simd_div(a, b) } -/// Signed saturating extract unsigned narrow +/// Divide #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqxtun2))] -pub unsafe fn vqmovun_high_s32(a: uint16x4_t, b: int32x4_t) -> uint16x8_t { - simd_shuffle8!(a, vqmovun_s32(b), [0, 1, 2, 3, 4, 5, 6, 7]) -} - -/// Signed saturating extract unsigned narrow -#[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqxtun2))] -pub unsafe fn vqmovun_high_s64(a: uint32x2_t, b: int64x2_t) -> uint32x4_t { - simd_shuffle4!(a, vqmovun_s64(b), [0, 1, 2, 3]) -} - -/// Signed saturating rounding doubling multiply returning high half -#[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrdmulh))] -pub unsafe fn vqrdmulhh_s16(a: i16, b: i16) -> i16 { - simd_extract(vqrdmulh_s16(vdup_n_s16(a), vdup_n_s16(b)), 0) +#[cfg_attr(test, assert_instr(fdiv))] +pub unsafe fn vdivq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { + simd_div(a, b) } -/// Signed saturating rounding doubling multiply returning high half +/// Divide #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrdmulh))] -pub unsafe fn vqrdmulhs_s32(a: i32, b: i32) -> i32 { - simd_extract(vqrdmulh_s32(vdup_n_s32(a), vdup_n_s32(b)), 0) +#[cfg_attr(test, assert_instr(fdiv))] +pub unsafe fn vdiv_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { + simd_div(a, b) } -/// Signed saturating rounding doubling multiply returning high half +/// Divide #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqrdmulhh_lane_s16(a: i16, b: int16x4_t) -> i16 { - static_assert_imm2!(LANE); - vqrdmulhh_s16(a, simd_extract(b, LANE as u32)) +#[cfg_attr(test, assert_instr(fdiv))] +pub unsafe fn vdivq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { + simd_div(a, b) } -/// Signed saturating rounding doubling multiply returning high half +/// Subtract #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqrdmulhh_laneq_s16(a: i16, b: int16x8_t) -> i16 { - static_assert_imm3!(LANE); - vqrdmulhh_s16(a, simd_extract(b, LANE as u32)) +#[cfg_attr(test, assert_instr(fsub))] +pub unsafe fn vsub_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { + simd_sub(a, b) } -/// Signed saturating rounding doubling multiply returning high half +/// Subtract #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqrdmulhs_lane_s32(a: i32, b: int32x2_t) -> i32 { - static_assert_imm1!(LANE); - vqrdmulhs_s32(a, simd_extract(b, LANE as u32)) +#[cfg_attr(test, assert_instr(fsub))] +pub unsafe fn vsubq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { + simd_sub(a, b) } -/// Signed saturating rounding doubling multiply returning high half +/// Subtract #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqrdmulhs_laneq_s32(a: i32, b: int32x4_t) -> i32 { - static_assert_imm2!(LANE); - vqrdmulhs_s32(a, simd_extract(b, LANE as u32)) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vsubd_s64(a: i64, b: i64) -> i64 { + a - b } -/// Signed saturating rounding doubling multiply accumulate returning high half +/// Subtract #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrdmulh))] -pub unsafe fn vqrdmlahh_s16(a: i16, b: i16, c: i16) -> i16 { - vqaddh_s16(a, vqrdmulhh_s16(b, c)) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vsubd_u64(a: u64, b: u64) -> u64 { + a - b } -/// Signed saturating rounding doubling multiply accumulate returning high half +/// Add #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrdmulh))] -pub unsafe fn vqrdmlahs_s32(a: i32, b: i32, c: i32) -> i32 { - vqadds_s32(a, vqrdmulhs_s32(b, c)) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vaddd_s64(a: i64, b: i64) -> i64 { + a + b } -/// Signed saturating rounding doubling multiply accumulate returning high half +/// Add #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqrdmlahh_lane_s16(a: i16, b: i16, c: int16x4_t) -> i16 { - static_assert_imm2!(LANE); - vqaddh_s16(a, vqrdmulhh_lane_s16::(b, c)) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vaddd_u64(a: u64, b: u64) -> u64 { + a + b } -/// Signed saturating rounding doubling multiply accumulate returning high half +/// Floating-point add across vector #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqrdmlahh_laneq_s16(a: i16, b: i16, c: int16x8_t) -> i16 { - static_assert_imm3!(LANE); - vqaddh_s16(a, vqrdmulhh_laneq_s16::(b, c)) +#[cfg_attr(test, assert_instr(faddp))] +pub unsafe fn vaddv_f32(a: float32x2_t) -> f32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.faddv.f32.v2f32")] + fn vaddv_f32_(a: float32x2_t) -> f32; + } + vaddv_f32_(a) } -/// Signed saturating rounding doubling multiply accumulate returning high half +/// Floating-point add across vector #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqrdmlahs_lane_s32(a: i32, b: i32, c: int32x2_t) -> i32 { - static_assert_imm1!(LANE); - vqadds_s32(a, vqrdmulhs_lane_s32::(b, c)) +#[cfg_attr(test, assert_instr(faddp))] +pub unsafe fn vaddvq_f32(a: float32x4_t) -> f32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.faddv.f32.v4f32")] + fn vaddvq_f32_(a: float32x4_t) -> f32; + } + vaddvq_f32_(a) } -/// Signed saturating rounding doubling multiply accumulate returning high half +/// Floating-point add across vector #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqrdmlahs_laneq_s32(a: i32, b: i32, c: int32x4_t) -> i32 { - static_assert_imm2!(LANE); - vqadds_s32(a, vqrdmulhs_laneq_s32::(b, c)) +#[cfg_attr(test, assert_instr(faddp))] +pub unsafe fn vaddvq_f64(a: float64x2_t) -> f64 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.faddv.f64.v2f64")] + fn vaddvq_f64_(a: float64x2_t) -> f64; + } + vaddvq_f64_(a) } -/// Signed saturating rounding doubling multiply subtract returning high half +/// Signed Add Long across Vector #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrdmulh))] -pub unsafe fn vqrdmlshh_s16(a: i16, b: i16, c: i16) -> i16 { - vqsubh_s16(a, vqrdmulhh_s16(b, c)) +#[cfg_attr(test, assert_instr(saddlv))] +pub unsafe fn vaddlv_s16(a: int16x4_t) -> i32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.saddlv.i32.v4i16")] + fn vaddlv_s16_(a: int16x4_t) -> i32; + } + vaddlv_s16_(a) } -/// Signed saturating rounding doubling multiply subtract returning high half +/// Signed Add Long across Vector #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrdmulh))] -pub unsafe fn vqrdmlshs_s32(a: i32, b: i32, c: i32) -> i32 { - vqsubs_s32(a, vqrdmulhs_s32(b, c)) +#[cfg_attr(test, assert_instr(saddlv))] +pub unsafe fn vaddlvq_s16(a: int16x8_t) -> i32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.saddlv.i32.v8i16")] + fn vaddlvq_s16_(a: int16x8_t) -> i32; + } + vaddlvq_s16_(a) } -/// Signed saturating rounding doubling multiply subtract returning high half +/// Signed Add Long across Vector #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqrdmlshh_lane_s16(a: i16, b: i16, c: int16x4_t) -> i16 { - static_assert_imm2!(LANE); - vqsubh_s16(a, vqrdmulhh_lane_s16::(b, c)) +#[cfg_attr(test, assert_instr(saddlp))] +pub unsafe fn vaddlv_s32(a: int32x2_t) -> i64 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.saddlv.i64.v2i32")] + fn vaddlv_s32_(a: int32x2_t) -> i64; + } + vaddlv_s32_(a) } -/// Signed saturating rounding doubling multiply subtract returning high half +/// Signed Add Long across Vector #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqrdmlshh_laneq_s16(a: i16, b: i16, c: int16x8_t) -> i16 { - static_assert_imm3!(LANE); - vqsubh_s16(a, vqrdmulhh_laneq_s16::(b, c)) +#[cfg_attr(test, assert_instr(saddlv))] +pub unsafe fn vaddlvq_s32(a: int32x4_t) -> i64 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.saddlv.i64.v4i32")] + fn vaddlvq_s32_(a: int32x4_t) -> i64; + } + vaddlvq_s32_(a) } -/// Signed saturating rounding doubling multiply subtract returning high half +/// Unsigned Add Long across Vector #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqrdmlshs_lane_s32(a: i32, b: i32, c: int32x2_t) -> i32 { - static_assert_imm1!(LANE); - vqsubs_s32(a, vqrdmulhs_lane_s32::(b, c)) +#[cfg_attr(test, assert_instr(uaddlv))] +pub unsafe fn vaddlv_u16(a: uint16x4_t) -> u32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uaddlv.i32.v4i16")] + fn vaddlv_u16_(a: uint16x4_t) -> u32; + } + vaddlv_u16_(a) } -/// Signed saturating rounding doubling multiply subtract returning high half +/// Unsigned Add Long across Vector #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqrdmlshs_laneq_s32(a: i32, b: i32, c: int32x4_t) -> i32 { - static_assert_imm2!(LANE); - vqsubs_s32(a, vqrdmulhs_laneq_s32::(b, c)) +#[cfg_attr(test, assert_instr(uaddlv))] +pub unsafe fn vaddlvq_u16(a: uint16x8_t) -> u32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uaddlv.i32.v8i16")] + fn vaddlvq_u16_(a: uint16x8_t) -> u32; + } + vaddlvq_u16_(a) } -/// Signed saturating rounding shift left +/// Unsigned Add Long across Vector #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrshl))] -pub unsafe fn vqrshls_s32(a: i32, b: i32) -> i32 { +#[cfg_attr(test, assert_instr(uaddlp))] +pub unsafe fn vaddlv_u32(a: uint32x2_t) -> u64 { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshl.i32")] - fn vqrshls_s32_(a: i32, b: i32) -> i32; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uaddlv.i64.v2i32")] + fn vaddlv_u32_(a: uint32x2_t) -> u64; } - vqrshls_s32_(a, b) + vaddlv_u32_(a) } -/// Signed saturating rounding shift left +/// Unsigned Add Long across Vector #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrshl))] -pub unsafe fn vqrshld_s64(a: i64, b: i64) -> i64 { +#[cfg_attr(test, assert_instr(uaddlv))] +pub unsafe fn vaddlvq_u32(a: uint32x4_t) -> u64 { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshl.i64")] - fn vqrshld_s64_(a: i64, b: i64) -> i64; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uaddlv.i64.v4i32")] + fn vaddlvq_u32_(a: uint32x4_t) -> u64; } - vqrshld_s64_(a, b) + vaddlvq_u32_(a) } -/// Signed saturating rounding shift left +/// Signed Subtract Wide #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrshl))] -pub unsafe fn vqrshlb_s8(a: i8, b: i8) -> i8 { - let a: int8x8_t = vdup_n_s8(a); - let b: int8x8_t = vdup_n_s8(b); - simd_extract(vqrshl_s8(a, b), 0) +#[cfg_attr(test, assert_instr(ssubw))] +pub unsafe fn vsubw_high_s8(a: int16x8_t, b: int8x16_t) -> int16x8_t { + let c: int8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); + simd_sub(a, simd_cast(c)) } -/// Signed saturating rounding shift left +/// Signed Subtract Wide #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrshl))] -pub unsafe fn vqrshlh_s16(a: i16, b: i16) -> i16 { - let a: int16x4_t = vdup_n_s16(a); - let b: int16x4_t = vdup_n_s16(b); - simd_extract(vqrshl_s16(a, b), 0) +#[cfg_attr(test, assert_instr(ssubw))] +pub unsafe fn vsubw_high_s16(a: int32x4_t, b: int16x8_t) -> int32x4_t { + let c: int16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); + simd_sub(a, simd_cast(c)) } -/// Unsigned signed saturating rounding shift left +/// Signed Subtract Wide #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uqrshl))] -pub unsafe fn vqrshls_u32(a: u32, b: i32) -> u32 { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqrshl.i32")] - fn vqrshls_u32_(a: u32, b: i32) -> u32; - } - vqrshls_u32_(a, b) +#[cfg_attr(test, assert_instr(ssubw))] +pub unsafe fn vsubw_high_s32(a: int64x2_t, b: int32x4_t) -> int64x2_t { + let c: int32x2_t = simd_shuffle2!(b, b, [2, 3]); + simd_sub(a, simd_cast(c)) } -/// Unsigned signed saturating rounding shift left +/// Unsigned Subtract Wide #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uqrshl))] -pub unsafe fn vqrshld_u64(a: u64, b: i64) -> u64 { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqrshl.i64")] - fn vqrshld_u64_(a: u64, b: i64) -> u64; - } - vqrshld_u64_(a, b) +#[cfg_attr(test, assert_instr(usubw))] +pub unsafe fn vsubw_high_u8(a: uint16x8_t, b: uint8x16_t) -> uint16x8_t { + let c: uint8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); + simd_sub(a, simd_cast(c)) } -/// Unsigned signed saturating rounding shift left +/// Unsigned Subtract Wide #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uqrshl))] -pub unsafe fn vqrshlb_u8(a: u8, b: i8) -> u8 { - let a: uint8x8_t = vdup_n_u8(a); - let b: int8x8_t = vdup_n_s8(b); - simd_extract(vqrshl_u8(a, b), 0) +#[cfg_attr(test, assert_instr(usubw))] +pub unsafe fn vsubw_high_u16(a: uint32x4_t, b: uint16x8_t) -> uint32x4_t { + let c: uint16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); + simd_sub(a, simd_cast(c)) } -/// Unsigned signed saturating rounding shift left +/// Unsigned Subtract Wide #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uqrshl))] -pub unsafe fn vqrshlh_u16(a: u16, b: i16) -> u16 { - let a: uint16x4_t = vdup_n_u16(a); - let b: int16x4_t = vdup_n_s16(b); - simd_extract(vqrshl_u16(a, b), 0) +#[cfg_attr(test, assert_instr(usubw))] +pub unsafe fn vsubw_high_u32(a: uint64x2_t, b: uint32x4_t) -> uint64x2_t { + let c: uint32x2_t = simd_shuffle2!(b, b, [2, 3]); + simd_sub(a, simd_cast(c)) } -/// Signed saturating rounded shift right narrow +/// Signed Subtract Long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqrshrnh_n_s16(a: i16) -> i8 { - static_assert!(N : i32 where N >= 1 && N <= 8); - let a: int16x8_t = vdupq_n_s16(a); - simd_extract(vqrshrn_n_s16::(a), 0) +#[cfg_attr(test, assert_instr(ssubl))] +pub unsafe fn vsubl_high_s8(a: int8x16_t, b: int8x16_t) -> int16x8_t { + let c: int8x8_t = simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]); + let d: int16x8_t = simd_cast(c); + let e: int8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); + let f: int16x8_t = simd_cast(e); + simd_sub(d, f) } -/// Signed saturating rounded shift right narrow +/// Signed Subtract Long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqrshrns_n_s32(a: i32) -> i16 { - static_assert!(N : i32 where N >= 1 && N <= 16); - let a: int32x4_t = vdupq_n_s32(a); - simd_extract(vqrshrn_n_s32::(a), 0) +#[cfg_attr(test, assert_instr(ssubl))] +pub unsafe fn vsubl_high_s16(a: int16x8_t, b: int16x8_t) -> int32x4_t { + let c: int16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); + let d: int32x4_t = simd_cast(c); + let e: int16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); + let f: int32x4_t = simd_cast(e); + simd_sub(d, f) } -/// Signed saturating rounded shift right narrow +/// Signed Subtract Long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqrshrnd_n_s64(a: i64) -> i32 { - static_assert!(N : i32 where N >= 1 && N <= 32); - let a: int64x2_t = vdupq_n_s64(a); - simd_extract(vqrshrn_n_s64::(a), 0) +#[cfg_attr(test, assert_instr(ssubl))] +pub unsafe fn vsubl_high_s32(a: int32x4_t, b: int32x4_t) -> int64x2_t { + let c: int32x2_t = simd_shuffle2!(a, a, [2, 3]); + let d: int64x2_t = simd_cast(c); + let e: int32x2_t = simd_shuffle2!(b, b, [2, 3]); + let f: int64x2_t = simd_cast(e); + simd_sub(d, f) } -/// Signed saturating rounded shift right narrow +/// Unsigned Subtract Long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrshrn2, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqrshrn_high_n_s16(a: int8x8_t, b: int16x8_t) -> int8x16_t { - static_assert!(N : i32 where N >= 1 && N <= 8); - simd_shuffle16!(a, vqrshrn_n_s16::(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) +#[cfg_attr(test, assert_instr(usubl))] +pub unsafe fn vsubl_high_u8(a: uint8x16_t, b: uint8x16_t) -> uint16x8_t { + let c: uint8x8_t = simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]); + let d: uint16x8_t = simd_cast(c); + let e: uint8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); + let f: uint16x8_t = simd_cast(e); + simd_sub(d, f) } -/// Signed saturating rounded shift right narrow +/// Unsigned Subtract Long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrshrn2, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqrshrn_high_n_s32(a: int16x4_t, b: int32x4_t) -> int16x8_t { - static_assert!(N : i32 where N >= 1 && N <= 16); - simd_shuffle8!(a, vqrshrn_n_s32::(b), [0, 1, 2, 3, 4, 5, 6, 7]) +#[cfg_attr(test, assert_instr(usubl))] +pub unsafe fn vsubl_high_u16(a: uint16x8_t, b: uint16x8_t) -> uint32x4_t { + let c: uint16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); + let d: uint32x4_t = simd_cast(c); + let e: uint16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); + let f: uint32x4_t = simd_cast(e); + simd_sub(d, f) } -/// Signed saturating rounded shift right narrow +/// Unsigned Subtract Long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrshrn2, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqrshrn_high_n_s64(a: int32x2_t, b: int64x2_t) -> int32x4_t { - static_assert!(N : i32 where N >= 1 && N <= 32); - simd_shuffle4!(a, vqrshrn_n_s64::(b), [0, 1, 2, 3]) +#[cfg_attr(test, assert_instr(usubl))] +pub unsafe fn vsubl_high_u32(a: uint32x4_t, b: uint32x4_t) -> uint64x2_t { + let c: uint32x2_t = simd_shuffle2!(a, a, [2, 3]); + let d: uint64x2_t = simd_cast(c); + let e: uint32x2_t = simd_shuffle2!(b, b, [2, 3]); + let f: uint64x2_t = simd_cast(e); + simd_sub(d, f) } -/// Unsigned saturating rounded shift right narrow +/// Bit clear and exclusive OR #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uqrshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqrshrnh_n_u16(a: u16) -> u8 { - static_assert!(N : i32 where N >= 1 && N <= 8); - let a: uint16x8_t = vdupq_n_u16(a); - simd_extract(vqrshrn_n_u16::(a), 0) +#[target_feature(enable = "neon,sha3")] +#[cfg_attr(test, assert_instr(bcax))] +pub unsafe fn vbcaxq_s8(a: int8x16_t, b: int8x16_t, c: int8x16_t) -> int8x16_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.bcaxs.v16i8")] + fn vbcaxq_s8_(a: int8x16_t, b: int8x16_t, c: int8x16_t) -> int8x16_t; + } + vbcaxq_s8_(a, b, c) } -/// Unsigned saturating rounded shift right narrow +/// Bit clear and exclusive OR #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uqrshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqrshrns_n_u32(a: u32) -> u16 { - static_assert!(N : i32 where N >= 1 && N <= 16); - let a: uint32x4_t = vdupq_n_u32(a); - simd_extract(vqrshrn_n_u32::(a), 0) +#[target_feature(enable = "neon,sha3")] +#[cfg_attr(test, assert_instr(bcax))] +pub unsafe fn vbcaxq_s16(a: int16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.bcaxs.v8i16")] + fn vbcaxq_s16_(a: int16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8_t; + } + vbcaxq_s16_(a, b, c) } -/// Unsigned saturating rounded shift right narrow +/// Bit clear and exclusive OR #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uqrshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqrshrnd_n_u64(a: u64) -> u32 { - static_assert!(N : i32 where N >= 1 && N <= 32); - let a: uint64x2_t = vdupq_n_u64(a); - simd_extract(vqrshrn_n_u64::(a), 0) +#[target_feature(enable = "neon,sha3")] +#[cfg_attr(test, assert_instr(bcax))] +pub unsafe fn vbcaxq_s32(a: int32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.bcaxs.v4i32")] + fn vbcaxq_s32_(a: int32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4_t; + } + vbcaxq_s32_(a, b, c) } -/// Unsigned saturating rounded shift right narrow +/// Bit clear and exclusive OR #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uqrshrn2, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqrshrn_high_n_u16(a: uint8x8_t, b: uint16x8_t) -> uint8x16_t { - static_assert!(N : i32 where N >= 1 && N <= 8); - simd_shuffle16!(a, vqrshrn_n_u16::(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) +#[target_feature(enable = "neon,sha3")] +#[cfg_attr(test, assert_instr(bcax))] +pub unsafe fn vbcaxq_s64(a: int64x2_t, b: int64x2_t, c: int64x2_t) -> int64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.bcaxs.v2i64")] + fn vbcaxq_s64_(a: int64x2_t, b: int64x2_t, c: int64x2_t) -> int64x2_t; + } + vbcaxq_s64_(a, b, c) } -/// Unsigned saturating rounded shift right narrow +/// Bit clear and exclusive OR #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uqrshrn2, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqrshrn_high_n_u32(a: uint16x4_t, b: uint32x4_t) -> uint16x8_t { - static_assert!(N : i32 where N >= 1 && N <= 16); - simd_shuffle8!(a, vqrshrn_n_u32::(b), [0, 1, 2, 3, 4, 5, 6, 7]) +#[target_feature(enable = "neon,sha3")] +#[cfg_attr(test, assert_instr(bcax))] +pub unsafe fn vbcaxq_u8(a: uint8x16_t, b: uint8x16_t, c: uint8x16_t) -> uint8x16_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.bcaxu.v16i8")] + fn vbcaxq_u8_(a: uint8x16_t, b: uint8x16_t, c: uint8x16_t) -> uint8x16_t; + } + vbcaxq_u8_(a, b, c) } -/// Unsigned saturating rounded shift right narrow +/// Bit clear and exclusive OR #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uqrshrn2, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqrshrn_high_n_u64(a: uint32x2_t, b: uint64x2_t) -> uint32x4_t { - static_assert!(N : i32 where N >= 1 && N <= 32); - simd_shuffle4!(a, vqrshrn_n_u64::(b), [0, 1, 2, 3]) +#[target_feature(enable = "neon,sha3")] +#[cfg_attr(test, assert_instr(bcax))] +pub unsafe fn vbcaxq_u16(a: uint16x8_t, b: uint16x8_t, c: uint16x8_t) -> uint16x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.bcaxu.v8i16")] + fn vbcaxq_u16_(a: uint16x8_t, b: uint16x8_t, c: uint16x8_t) -> uint16x8_t; + } + vbcaxq_u16_(a, b, c) } -/// Signed saturating rounded shift right unsigned narrow +/// Bit clear and exclusive OR #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrshrun, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqrshrunh_n_s16(a: i16) -> u8 { - static_assert!(N : i32 where N >= 1 && N <= 8); - let a: int16x8_t = vdupq_n_s16(a); - simd_extract(vqrshrun_n_s16::(a), 0) +#[target_feature(enable = "neon,sha3")] +#[cfg_attr(test, assert_instr(bcax))] +pub unsafe fn vbcaxq_u32(a: uint32x4_t, b: uint32x4_t, c: uint32x4_t) -> uint32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.bcaxu.v4i32")] + fn vbcaxq_u32_(a: uint32x4_t, b: uint32x4_t, c: uint32x4_t) -> uint32x4_t; + } + vbcaxq_u32_(a, b, c) } -/// Signed saturating rounded shift right unsigned narrow +/// Bit clear and exclusive OR #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrshrun, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqrshruns_n_s32(a: i32) -> u16 { - static_assert!(N : i32 where N >= 1 && N <= 16); - let a: int32x4_t = vdupq_n_s32(a); - simd_extract(vqrshrun_n_s32::(a), 0) +#[target_feature(enable = "neon,sha3")] +#[cfg_attr(test, assert_instr(bcax))] +pub unsafe fn vbcaxq_u64(a: uint64x2_t, b: uint64x2_t, c: uint64x2_t) -> uint64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.bcaxu.v2i64")] + fn vbcaxq_u64_(a: uint64x2_t, b: uint64x2_t, c: uint64x2_t) -> uint64x2_t; + } + vbcaxq_u64_(a, b, c) } -/// Signed saturating rounded shift right unsigned narrow +/// Floating-point complex add #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrshrun, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqrshrund_n_s64(a: i64) -> u32 { - static_assert!(N : i32 where N >= 1 && N <= 32); - let a: int64x2_t = vdupq_n_s64(a); - simd_extract(vqrshrun_n_s64::(a), 0) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcadd))] +pub unsafe fn vcadd_rot270_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcadd.rot270.v2f32")] + fn vcadd_rot270_f32_(a: float32x2_t, b: float32x2_t) -> float32x2_t; + } + vcadd_rot270_f32_(a, b) } -/// Signed saturating rounded shift right unsigned narrow +/// Floating-point complex add #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrshrun2, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqrshrun_high_n_s16(a: uint8x8_t, b: int16x8_t) -> uint8x16_t { - static_assert!(N : i32 where N >= 1 && N <= 8); - simd_shuffle16!(a, vqrshrun_n_s16::(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcadd))] +pub unsafe fn vcaddq_rot270_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcadd.rot270.v4f32")] + fn vcaddq_rot270_f32_(a: float32x4_t, b: float32x4_t) -> float32x4_t; + } + vcaddq_rot270_f32_(a, b) } -/// Signed saturating rounded shift right unsigned narrow +/// Floating-point complex add #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrshrun2, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqrshrun_high_n_s32(a: uint16x4_t, b: int32x4_t) -> uint16x8_t { - static_assert!(N : i32 where N >= 1 && N <= 16); - simd_shuffle8!(a, vqrshrun_n_s32::(b), [0, 1, 2, 3, 4, 5, 6, 7]) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcadd))] +pub unsafe fn vcaddq_rot270_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcadd.rot270.v2f64")] + fn vcaddq_rot270_f64_(a: float64x2_t, b: float64x2_t) -> float64x2_t; + } + vcaddq_rot270_f64_(a, b) } -/// Signed saturating rounded shift right unsigned narrow +/// Floating-point complex add #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqrshrun2, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqrshrun_high_n_s64(a: uint32x2_t, b: int64x2_t) -> uint32x4_t { - static_assert!(N : i32 where N >= 1 && N <= 32); - simd_shuffle4!(a, vqrshrun_n_s64::(b), [0, 1, 2, 3]) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcadd))] +pub unsafe fn vcadd_rot90_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcadd.rot90.v2f32")] + fn vcadd_rot90_f32_(a: float32x2_t, b: float32x2_t) -> float32x2_t; + } + vcadd_rot90_f32_(a, b) } -/// Signed saturating shift left +/// Floating-point complex add #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqshl))] -pub unsafe fn vqshld_s64(a: i64, b: i64) -> i64 { +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcadd))] +pub unsafe fn vcaddq_rot90_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshl.i64")] - fn vqshld_s64_(a: i64, b: i64) -> i64; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcadd.rot90.v4f32")] + fn vcaddq_rot90_f32_(a: float32x4_t, b: float32x4_t) -> float32x4_t; } - vqshld_s64_(a, b) + vcaddq_rot90_f32_(a, b) } -/// Signed saturating shift left +/// Floating-point complex add #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqshl))] -pub unsafe fn vqshlb_s8(a: i8, b: i8) -> i8 { - let c: int8x8_t = vqshl_s8(vdup_n_s8(a), vdup_n_s8(b)); - simd_extract(c, 0) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcadd))] +pub unsafe fn vcaddq_rot90_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcadd.rot90.v2f64")] + fn vcaddq_rot90_f64_(a: float64x2_t, b: float64x2_t) -> float64x2_t; + } + vcaddq_rot90_f64_(a, b) } -/// Signed saturating shift left +/// Floating-point complex multiply accumulate #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqshl))] -pub unsafe fn vqshlh_s16(a: i16, b: i16) -> i16 { - let c: int16x4_t = vqshl_s16(vdup_n_s16(a), vdup_n_s16(b)); - simd_extract(c, 0) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcmla))] +pub unsafe fn vcmla_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcmla.rot0.v2f32")] + fn vcmla_f32_(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t; + } + vcmla_f32_(a, b, c) } -/// Signed saturating shift left +/// Floating-point complex multiply accumulate #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqshl))] -pub unsafe fn vqshls_s32(a: i32, b: i32) -> i32 { - let c: int32x2_t = vqshl_s32(vdup_n_s32(a), vdup_n_s32(b)); - simd_extract(c, 0) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcmla))] +pub unsafe fn vcmlaq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcmla.rot0.v4f32")] + fn vcmlaq_f32_(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t; + } + vcmlaq_f32_(a, b, c) } -/// Unsigned saturating shift left +/// Floating-point complex multiply accumulate #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uqshl))] -pub unsafe fn vqshld_u64(a: u64, b: i64) -> u64 { +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcmla))] +pub unsafe fn vcmlaq_f64(a: float64x2_t, b: float64x2_t, c: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqshl.i64")] - fn vqshld_u64_(a: u64, b: i64) -> u64; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcmla.rot0.v2f64")] + fn vcmlaq_f64_(a: float64x2_t, b: float64x2_t, c: float64x2_t) -> float64x2_t; } - vqshld_u64_(a, b) + vcmlaq_f64_(a, b, c) } -/// Unsigned saturating shift left +/// Floating-point complex multiply accumulate #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uqshl))] -pub unsafe fn vqshlb_u8(a: u8, b: i8) -> u8 { - let c: uint8x8_t = vqshl_u8(vdup_n_u8(a), vdup_n_s8(b)); - simd_extract(c, 0) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcmla))] +pub unsafe fn vcmla_rot90_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcmla.rot90.v2f32")] + fn vcmla_rot90_f32_(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t; + } + vcmla_rot90_f32_(a, b, c) } -/// Unsigned saturating shift left +/// Floating-point complex multiply accumulate #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uqshl))] -pub unsafe fn vqshlh_u16(a: u16, b: i16) -> u16 { - let c: uint16x4_t = vqshl_u16(vdup_n_u16(a), vdup_n_s16(b)); - simd_extract(c, 0) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcmla))] +pub unsafe fn vcmlaq_rot90_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcmla.rot90.v4f32")] + fn vcmlaq_rot90_f32_(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t; + } + vcmlaq_rot90_f32_(a, b, c) } -/// Unsigned saturating shift left +/// Floating-point complex multiply accumulate #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uqshl))] -pub unsafe fn vqshls_u32(a: u32, b: i32) -> u32 { - let c: uint32x2_t = vqshl_u32(vdup_n_u32(a), vdup_n_s32(b)); - simd_extract(c, 0) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcmla))] +pub unsafe fn vcmlaq_rot90_f64(a: float64x2_t, b: float64x2_t, c: float64x2_t) -> float64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcmla.rot90.v2f64")] + fn vcmlaq_rot90_f64_(a: float64x2_t, b: float64x2_t, c: float64x2_t) -> float64x2_t; + } + vcmlaq_rot90_f64_(a, b, c) } -/// Signed saturating shift left +/// Floating-point complex multiply accumulate #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqshl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshlb_n_s8(a: i8) -> i8 { - static_assert_imm3!(N); - simd_extract(vqshl_n_s8::(vdup_n_s8(a)), 0) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcmla))] +pub unsafe fn vcmla_rot180_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcmla.rot180.v2f32")] + fn vcmla_rot180_f32_(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t; + } + vcmla_rot180_f32_(a, b, c) } -/// Signed saturating shift left +/// Floating-point complex multiply accumulate #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqshl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshlh_n_s16(a: i16) -> i16 { - static_assert_imm4!(N); - simd_extract(vqshl_n_s16::(vdup_n_s16(a)), 0) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcmla))] +pub unsafe fn vcmlaq_rot180_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcmla.rot180.v4f32")] + fn vcmlaq_rot180_f32_(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t; + } + vcmlaq_rot180_f32_(a, b, c) } -/// Signed saturating shift left +/// Floating-point complex multiply accumulate #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqshl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshls_n_s32(a: i32) -> i32 { - static_assert_imm5!(N); - simd_extract(vqshl_n_s32::(vdup_n_s32(a)), 0) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcmla))] +pub unsafe fn vcmlaq_rot180_f64(a: float64x2_t, b: float64x2_t, c: float64x2_t) -> float64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcmla.rot180.v2f64")] + fn vcmlaq_rot180_f64_(a: float64x2_t, b: float64x2_t, c: float64x2_t) -> float64x2_t; + } + vcmlaq_rot180_f64_(a, b, c) } -/// Signed saturating shift left +/// Floating-point complex multiply accumulate #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqshl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshld_n_s64(a: i64) -> i64 { - static_assert_imm6!(N); - simd_extract(vqshl_n_s64::(vdup_n_s64(a)), 0) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcmla))] +pub unsafe fn vcmla_rot270_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcmla.rot270.v2f32")] + fn vcmla_rot270_f32_(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t; + } + vcmla_rot270_f32_(a, b, c) } -/// Unsigned saturating shift left +/// Floating-point complex multiply accumulate #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uqshl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshlb_n_u8(a: u8) -> u8 { - static_assert_imm3!(N); - simd_extract(vqshl_n_u8::(vdup_n_u8(a)), 0) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcmla))] +pub unsafe fn vcmlaq_rot270_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcmla.rot270.v4f32")] + fn vcmlaq_rot270_f32_(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t; + } + vcmlaq_rot270_f32_(a, b, c) } -/// Unsigned saturating shift left +/// Floating-point complex multiply accumulate #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uqshl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshlh_n_u16(a: u16) -> u16 { - static_assert_imm4!(N); - simd_extract(vqshl_n_u16::(vdup_n_u16(a)), 0) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcmla))] +pub unsafe fn vcmlaq_rot270_f64(a: float64x2_t, b: float64x2_t, c: float64x2_t) -> float64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcmla.rot270.v2f64")] + fn vcmlaq_rot270_f64_(a: float64x2_t, b: float64x2_t, c: float64x2_t) -> float64x2_t; + } + vcmlaq_rot270_f64_(a, b, c) } -/// Unsigned saturating shift left +/// Floating-point complex multiply accumulate #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uqshl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshls_n_u32(a: u32) -> u32 { - static_assert_imm5!(N); - simd_extract(vqshl_n_u32::(vdup_n_u32(a)), 0) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcmla, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vcmla_lane_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t { + static_assert!(LANE : i32 where LANE == 0); + let c: float32x2_t = simd_shuffle2!(c, c, [2 * LANE as u32, 2 * LANE as u32 + 1]); + vcmla_f32(a, b, c) } -/// Unsigned saturating shift left +/// Floating-point complex multiply accumulate #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uqshl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshld_n_u64(a: u64) -> u64 { - static_assert_imm6!(N); - simd_extract(vqshl_n_u64::(vdup_n_u64(a)), 0) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcmla, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vcmla_laneq_f32(a: float32x2_t, b: float32x2_t, c: float32x4_t) -> float32x2_t { + static_assert_imm1!(LANE); + let c: float32x2_t = simd_shuffle2!(c, c, [2 * LANE as u32, 2 * LANE as u32 + 1]); + vcmla_f32(a, b, c) } -/// Signed saturating shift right narrow +/// Floating-point complex multiply accumulate #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshrnd_n_s64(a: i64) -> i32 { - static_assert!(N : i32 where N >= 1 && N <= 32); - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshrn.i32")] - fn vqshrnd_n_s64_(a: i64, n: i32) -> i32; - } - vqshrnd_n_s64_(a, N) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcmla, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vcmlaq_lane_f32(a: float32x4_t, b: float32x4_t, c: float32x2_t) -> float32x4_t { + static_assert!(LANE : i32 where LANE == 0); + let c: float32x4_t = simd_shuffle4!(c, c, [2 * LANE as u32, 2 * LANE as u32 + 1, 2 * LANE as u32, 2 * LANE as u32 + 1]); + vcmlaq_f32(a, b, c) } -/// Signed saturating shift right narrow +/// Floating-point complex multiply accumulate #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshrnh_n_s16(a: i16) -> i8 { - static_assert!(N : i32 where N >= 1 && N <= 8); - simd_extract(vqshrn_n_s16::(vdupq_n_s16(a)), 0) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcmla, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vcmlaq_laneq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t { + static_assert_imm1!(LANE); + let c: float32x4_t = simd_shuffle4!(c, c, [2 * LANE as u32, 2 * LANE as u32 + 1, 2 * LANE as u32, 2 * LANE as u32 + 1]); + vcmlaq_f32(a, b, c) } -/// Signed saturating shift right narrow +/// Floating-point complex multiply accumulate #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshrns_n_s32(a: i32) -> i16 { - static_assert!(N : i32 where N >= 1 && N <= 16); - simd_extract(vqshrn_n_s32::(vdupq_n_s32(a)), 0) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcmla, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vcmla_rot90_lane_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t { + static_assert!(LANE : i32 where LANE == 0); + let c: float32x2_t = simd_shuffle2!(c, c, [2 * LANE as u32, 2 * LANE as u32 + 1]); + vcmla_rot90_f32(a, b, c) } -/// Signed saturating shift right narrow +/// Floating-point complex multiply accumulate #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqshrn2, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqshrn_high_n_s16(a: int8x8_t, b: int16x8_t) -> int8x16_t { - static_assert!(N : i32 where N >= 1 && N <= 8); - simd_shuffle16!(a, vqshrn_n_s16::(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcmla, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vcmla_rot90_laneq_f32(a: float32x2_t, b: float32x2_t, c: float32x4_t) -> float32x2_t { + static_assert_imm1!(LANE); + let c: float32x2_t = simd_shuffle2!(c, c, [2 * LANE as u32, 2 * LANE as u32 + 1]); + vcmla_rot90_f32(a, b, c) } -/// Signed saturating shift right narrow +/// Floating-point complex multiply accumulate #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqshrn2, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqshrn_high_n_s32(a: int16x4_t, b: int32x4_t) -> int16x8_t { - static_assert!(N : i32 where N >= 1 && N <= 16); - simd_shuffle8!(a, vqshrn_n_s32::(b), [0, 1, 2, 3, 4, 5, 6, 7]) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcmla, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vcmlaq_rot90_lane_f32(a: float32x4_t, b: float32x4_t, c: float32x2_t) -> float32x4_t { + static_assert!(LANE : i32 where LANE == 0); + let c: float32x4_t = simd_shuffle4!(c, c, [2 * LANE as u32, 2 * LANE as u32 + 1, 2 * LANE as u32, 2 * LANE as u32 + 1]); + vcmlaq_rot90_f32(a, b, c) } -/// Signed saturating shift right narrow +/// Floating-point complex multiply accumulate #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqshrn2, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqshrn_high_n_s64(a: int32x2_t, b: int64x2_t) -> int32x4_t { - static_assert!(N : i32 where N >= 1 && N <= 32); - simd_shuffle4!(a, vqshrn_n_s64::(b), [0, 1, 2, 3]) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcmla, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vcmlaq_rot90_laneq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t { + static_assert_imm1!(LANE); + let c: float32x4_t = simd_shuffle4!(c, c, [2 * LANE as u32, 2 * LANE as u32 + 1, 2 * LANE as u32, 2 * LANE as u32 + 1]); + vcmlaq_rot90_f32(a, b, c) } -/// Unsigned saturating shift right narrow +/// Floating-point complex multiply accumulate #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uqshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshrnd_n_u64(a: u64) -> u32 { - static_assert!(N : i32 where N >= 1 && N <= 32); - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqshrn.i32")] - fn vqshrnd_n_u64_(a: u64, n: i32) -> u32; - } - vqshrnd_n_u64_(a, N) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcmla, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vcmla_rot180_lane_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t { + static_assert!(LANE : i32 where LANE == 0); + let c: float32x2_t = simd_shuffle2!(c, c, [2 * LANE as u32, 2 * LANE as u32 + 1]); + vcmla_rot180_f32(a, b, c) } -/// Unsigned saturating shift right narrow +/// Floating-point complex multiply accumulate #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uqshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshrnh_n_u16(a: u16) -> u8 { - static_assert!(N : i32 where N >= 1 && N <= 8); - simd_extract(vqshrn_n_u16::(vdupq_n_u16(a)), 0) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcmla, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vcmla_rot180_laneq_f32(a: float32x2_t, b: float32x2_t, c: float32x4_t) -> float32x2_t { + static_assert_imm1!(LANE); + let c: float32x2_t = simd_shuffle2!(c, c, [2 * LANE as u32, 2 * LANE as u32 + 1]); + vcmla_rot180_f32(a, b, c) } -/// Unsigned saturating shift right narrow +/// Floating-point complex multiply accumulate #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uqshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshrns_n_u32(a: u32) -> u16 { - static_assert!(N : i32 where N >= 1 && N <= 16); - simd_extract(vqshrn_n_u32::(vdupq_n_u32(a)), 0) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcmla, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vcmlaq_rot180_lane_f32(a: float32x4_t, b: float32x4_t, c: float32x2_t) -> float32x4_t { + static_assert!(LANE : i32 where LANE == 0); + let c: float32x4_t = simd_shuffle4!(c, c, [2 * LANE as u32, 2 * LANE as u32 + 1, 2 * LANE as u32, 2 * LANE as u32 + 1]); + vcmlaq_rot180_f32(a, b, c) } -/// Unsigned saturating shift right narrow +/// Floating-point complex multiply accumulate #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uqshrn2, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqshrn_high_n_u16(a: uint8x8_t, b: uint16x8_t) -> uint8x16_t { - static_assert!(N : i32 where N >= 1 && N <= 8); - simd_shuffle16!(a, vqshrn_n_u16::(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcmla, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vcmlaq_rot180_laneq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t { + static_assert_imm1!(LANE); + let c: float32x4_t = simd_shuffle4!(c, c, [2 * LANE as u32, 2 * LANE as u32 + 1, 2 * LANE as u32, 2 * LANE as u32 + 1]); + vcmlaq_rot180_f32(a, b, c) } -/// Unsigned saturating shift right narrow +/// Floating-point complex multiply accumulate #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uqshrn2, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqshrn_high_n_u32(a: uint16x4_t, b: uint32x4_t) -> uint16x8_t { - static_assert!(N : i32 where N >= 1 && N <= 16); - simd_shuffle8!(a, vqshrn_n_u32::(b), [0, 1, 2, 3, 4, 5, 6, 7]) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcmla, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vcmla_rot270_lane_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t { + static_assert!(LANE : i32 where LANE == 0); + let c: float32x2_t = simd_shuffle2!(c, c, [2 * LANE as u32, 2 * LANE as u32 + 1]); + vcmla_rot270_f32(a, b, c) } -/// Unsigned saturating shift right narrow +/// Floating-point complex multiply accumulate #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uqshrn2, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqshrn_high_n_u64(a: uint32x2_t, b: uint64x2_t) -> uint32x4_t { - static_assert!(N : i32 where N >= 1 && N <= 32); - simd_shuffle4!(a, vqshrn_n_u64::(b), [0, 1, 2, 3]) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcmla, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vcmla_rot270_laneq_f32(a: float32x2_t, b: float32x2_t, c: float32x4_t) -> float32x2_t { + static_assert_imm1!(LANE); + let c: float32x2_t = simd_shuffle2!(c, c, [2 * LANE as u32, 2 * LANE as u32 + 1]); + vcmla_rot270_f32(a, b, c) } -/// Signed saturating shift right unsigned narrow +/// Floating-point complex multiply accumulate #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqshrun, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshrunh_n_s16(a: i16) -> u8 { - static_assert!(N : i32 where N >= 1 && N <= 8); - simd_extract(vqshrun_n_s16::(vdupq_n_s16(a)), 0) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcmla, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vcmlaq_rot270_lane_f32(a: float32x4_t, b: float32x4_t, c: float32x2_t) -> float32x4_t { + static_assert!(LANE : i32 where LANE == 0); + let c: float32x4_t = simd_shuffle4!(c, c, [2 * LANE as u32, 2 * LANE as u32 + 1, 2 * LANE as u32, 2 * LANE as u32 + 1]); + vcmlaq_rot270_f32(a, b, c) } -/// Signed saturating shift right unsigned narrow +/// Floating-point complex multiply accumulate #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqshrun, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshruns_n_s32(a: i32) -> u16 { - static_assert!(N : i32 where N >= 1 && N <= 16); - simd_extract(vqshrun_n_s32::(vdupq_n_s32(a)), 0) +#[target_feature(enable = "neon,fcma")] +#[cfg_attr(test, assert_instr(fcmla, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vcmlaq_rot270_laneq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t { + static_assert_imm1!(LANE); + let c: float32x4_t = simd_shuffle4!(c, c, [2 * LANE as u32, 2 * LANE as u32 + 1, 2 * LANE as u32, 2 * LANE as u32 + 1]); + vcmlaq_rot270_f32(a, b, c) } -/// Signed saturating shift right unsigned narrow +/// Dot product arithmetic #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqshrun, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshrund_n_s64(a: i64) -> u32 { - static_assert!(N : i32 where N >= 1 && N <= 32); - simd_extract(vqshrun_n_s64::(vdupq_n_s64(a)), 0) +#[target_feature(enable = "neon,dotprod")] +#[cfg_attr(test, assert_instr(sdot))] +pub unsafe fn vdot_s32(a: int32x2_t, b: int8x8_t, c: int8x8_t) -> int32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sdot.v2i32.v8i8")] + fn vdot_s32_(a: int32x2_t, b: int8x8_t, c: int8x8_t) -> int32x2_t; + } + vdot_s32_(a, b, c) } -/// Signed saturating shift right unsigned narrow +/// Dot product arithmetic #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqshrun2, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqshrun_high_n_s16(a: uint8x8_t, b: int16x8_t) -> uint8x16_t { - static_assert!(N : i32 where N >= 1 && N <= 8); - simd_shuffle16!(a, vqshrun_n_s16::(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) +#[target_feature(enable = "neon,dotprod")] +#[cfg_attr(test, assert_instr(sdot))] +pub unsafe fn vdotq_s32(a: int32x4_t, b: int8x16_t, c: int8x16_t) -> int32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sdot.v4i32.v16i8")] + fn vdotq_s32_(a: int32x4_t, b: int8x16_t, c: int8x16_t) -> int32x4_t; + } + vdotq_s32_(a, b, c) } -/// Signed saturating shift right unsigned narrow +/// Dot product arithmetic #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqshrun2, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqshrun_high_n_s32(a: uint16x4_t, b: int32x4_t) -> uint16x8_t { - static_assert!(N : i32 where N >= 1 && N <= 16); - simd_shuffle8!(a, vqshrun_n_s32::(b), [0, 1, 2, 3, 4, 5, 6, 7]) +#[target_feature(enable = "neon,dotprod")] +#[cfg_attr(test, assert_instr(udot))] +pub unsafe fn vdot_u32(a: uint32x2_t, b: uint8x8_t, c: uint8x8_t) -> uint32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.udot.v2i32.v8i8")] + fn vdot_u32_(a: uint32x2_t, b: uint8x8_t, c: uint8x8_t) -> uint32x2_t; + } + vdot_u32_(a, b, c) } -/// Signed saturating shift right unsigned narrow +/// Dot product arithmetic #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqshrun2, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqshrun_high_n_s64(a: uint32x2_t, b: int64x2_t) -> uint32x4_t { - static_assert!(N : i32 where N >= 1 && N <= 32); - simd_shuffle4!(a, vqshrun_n_s64::(b), [0, 1, 2, 3]) +#[target_feature(enable = "neon,dotprod")] +#[cfg_attr(test, assert_instr(udot))] +pub unsafe fn vdotq_u32(a: uint32x4_t, b: uint8x16_t, c: uint8x16_t) -> uint32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.udot.v4i32.v16i8")] + fn vdotq_u32_(a: uint32x4_t, b: uint8x16_t, c: uint8x16_t) -> uint32x4_t; + } + vdotq_u32_(a, b, c) } -/// Calculates the square root of each lane. +/// Dot product arithmetic #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fsqrt))] -pub unsafe fn vsqrt_f32(a: float32x2_t) -> float32x2_t { - simd_fsqrt(a) +#[target_feature(enable = "neon,dotprod")] +#[cfg_attr(test, assert_instr(sdot, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vdot_lane_s32(a: int32x2_t, b: int8x8_t, c: int8x8_t) -> int32x2_t { + static_assert_imm1!(LANE); + let c: int8x8_t = simd_shuffle8!(c, c, [4 * LANE as u32, 4 * LANE as u32 + 1, 4 * LANE as u32 + 2, 4 * LANE as u32 + 3, 4 * LANE as u32, 4 * LANE as u32 + 1, 4 * LANE as u32 + 2, 4 * LANE as u32 + 3]); + vdot_s32(a, b, c) } -/// Calculates the square root of each lane. +/// Dot product arithmetic #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fsqrt))] -pub unsafe fn vsqrtq_f32(a: float32x4_t) -> float32x4_t { - simd_fsqrt(a) +#[target_feature(enable = "neon,dotprod")] +#[cfg_attr(test, assert_instr(sdot, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vdot_laneq_s32(a: int32x2_t, b: int8x8_t, c: int8x16_t) -> int32x2_t { + static_assert_imm2!(LANE); + let c: int8x8_t = simd_shuffle8!(c, c, [4 * LANE as u32, 4 * LANE as u32 + 1, 4 * LANE as u32 + 2, 4 * LANE as u32 + 3, 4 * LANE as u32, 4 * LANE as u32 + 1, 4 * LANE as u32 + 2, 4 * LANE as u32 + 3]); + vdot_s32(a, b, c) } -/// Calculates the square root of each lane. +/// Dot product arithmetic #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fsqrt))] -pub unsafe fn vsqrt_f64(a: float64x1_t) -> float64x1_t { - simd_fsqrt(a) +#[target_feature(enable = "neon,dotprod")] +#[cfg_attr(test, assert_instr(sdot, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vdotq_lane_s32(a: int32x4_t, b: int8x16_t, c: int8x8_t) -> int32x4_t { + static_assert_imm1!(LANE); + let c: int8x16_t = simd_shuffle16!(c, c, [4 * LANE as u32, 4 * LANE as u32 + 1, 4 * LANE as u32 + 2, 4 * LANE as u32 + 3, 4 * LANE as u32, 4 * LANE as u32 + 1, 4 * LANE as u32 + 2, 4 * LANE as u32 + 3, 4 * LANE as u32, 4 * LANE as u32 + 1, 4 * LANE as u32 + 2, 4 * LANE as u32 + 3, 4 * LANE as u32, 4 * LANE as u32 + 1, 4 * LANE as u32 + 2, 4 * LANE as u32 + 3]); + vdotq_s32(a, b, c) } -/// Calculates the square root of each lane. +/// Dot product arithmetic #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fsqrt))] -pub unsafe fn vsqrtq_f64(a: float64x2_t) -> float64x2_t { - simd_fsqrt(a) +#[target_feature(enable = "neon,dotprod")] +#[cfg_attr(test, assert_instr(sdot, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vdotq_laneq_s32(a: int32x4_t, b: int8x16_t, c: int8x16_t) -> int32x4_t { + static_assert_imm2!(LANE); + let c: int8x16_t = simd_shuffle16!(c, c, [4 * LANE as u32, 4 * LANE as u32 + 1, 4 * LANE as u32 + 2, 4 * LANE as u32 + 3, 4 * LANE as u32, 4 * LANE as u32 + 1, 4 * LANE as u32 + 2, 4 * LANE as u32 + 3, 4 * LANE as u32, 4 * LANE as u32 + 1, 4 * LANE as u32 + 2, 4 * LANE as u32 + 3, 4 * LANE as u32, 4 * LANE as u32 + 1, 4 * LANE as u32 + 2, 4 * LANE as u32 + 3]); + vdotq_s32(a, b, c) } -/// Reciprocal square-root estimate. +/// Dot product arithmetic +#[inline] +#[target_feature(enable = "neon,dotprod")] +#[cfg_attr(test, assert_instr(udot, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vdot_lane_u32(a: uint32x2_t, b: uint8x8_t, c: uint8x8_t) -> uint32x2_t { + static_assert_imm1!(LANE); + let c: uint8x8_t = simd_shuffle8!(c, c, [4 * LANE as u32, 4 * LANE as u32 + 1, 4 * LANE as u32 + 2, 4 * LANE as u32 + 3, 4 * LANE as u32, 4 * LANE as u32 + 1, 4 * LANE as u32 + 2, 4 * LANE as u32 + 3]); + vdot_u32(a, b, c) +} + +/// Dot product arithmetic +#[inline] +#[target_feature(enable = "neon,dotprod")] +#[cfg_attr(test, assert_instr(udot, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vdot_laneq_u32(a: uint32x2_t, b: uint8x8_t, c: uint8x16_t) -> uint32x2_t { + static_assert_imm2!(LANE); + let c: uint8x8_t = simd_shuffle8!(c, c, [4 * LANE as u32, 4 * LANE as u32 + 1, 4 * LANE as u32 + 2, 4 * LANE as u32 + 3, 4 * LANE as u32, 4 * LANE as u32 + 1, 4 * LANE as u32 + 2, 4 * LANE as u32 + 3]); + vdot_u32(a, b, c) +} + +/// Dot product arithmetic +#[inline] +#[target_feature(enable = "neon,dotprod")] +#[cfg_attr(test, assert_instr(udot, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vdotq_lane_u32(a: uint32x4_t, b: uint8x16_t, c: uint8x8_t) -> uint32x4_t { + static_assert_imm1!(LANE); + let c: uint8x16_t = simd_shuffle16!(c, c, [4 * LANE as u32, 4 * LANE as u32 + 1, 4 * LANE as u32 + 2, 4 * LANE as u32 + 3, 4 * LANE as u32, 4 * LANE as u32 + 1, 4 * LANE as u32 + 2, 4 * LANE as u32 + 3, 4 * LANE as u32, 4 * LANE as u32 + 1, 4 * LANE as u32 + 2, 4 * LANE as u32 + 3, 4 * LANE as u32, 4 * LANE as u32 + 1, 4 * LANE as u32 + 2, 4 * LANE as u32 + 3]); + vdotq_u32(a, b, c) +} + +/// Dot product arithmetic +#[inline] +#[target_feature(enable = "neon,dotprod")] +#[cfg_attr(test, assert_instr(udot, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vdotq_laneq_u32(a: uint32x4_t, b: uint8x16_t, c: uint8x16_t) -> uint32x4_t { + static_assert_imm2!(LANE); + let c: uint8x16_t = simd_shuffle16!(c, c, [4 * LANE as u32, 4 * LANE as u32 + 1, 4 * LANE as u32 + 2, 4 * LANE as u32 + 3, 4 * LANE as u32, 4 * LANE as u32 + 1, 4 * LANE as u32 + 2, 4 * LANE as u32 + 3, 4 * LANE as u32, 4 * LANE as u32 + 1, 4 * LANE as u32 + 2, 4 * LANE as u32 + 3, 4 * LANE as u32, 4 * LANE as u32 + 1, 4 * LANE as u32 + 2, 4 * LANE as u32 + 3]); + vdotq_u32(a, b, c) +} + +/// Maximum (vector) #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(frsqrte))] -pub unsafe fn vrsqrte_f64(a: float64x1_t) -> float64x1_t { +#[cfg_attr(test, assert_instr(fmax))] +pub unsafe fn vmax_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frsqrte.v1f64")] - fn vrsqrte_f64_(a: float64x1_t) -> float64x1_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmax.v1f64")] + fn vmax_f64_(a: float64x1_t, b: float64x1_t) -> float64x1_t; } - vrsqrte_f64_(a) + vmax_f64_(a, b) } -/// Reciprocal square-root estimate. +/// Maximum (vector) #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(frsqrte))] -pub unsafe fn vrsqrteq_f64(a: float64x2_t) -> float64x2_t { +#[cfg_attr(test, assert_instr(fmax))] +pub unsafe fn vmaxq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frsqrte.v2f64")] - fn vrsqrteq_f64_(a: float64x2_t) -> float64x2_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmax.v2f64")] + fn vmaxq_f64_(a: float64x2_t, b: float64x2_t) -> float64x2_t; } - vrsqrteq_f64_(a) + vmaxq_f64_(a, b) } -/// Reciprocal estimate. +/// Floating-point Maximun Number (vector) #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(frecpe))] -pub unsafe fn vrecpe_f64(a: float64x1_t) -> float64x1_t { +#[cfg_attr(test, assert_instr(fmaxnm))] +pub unsafe fn vmaxnm_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frecpe.v1f64")] - fn vrecpe_f64_(a: float64x1_t) -> float64x1_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmaxnm.v1f64")] + fn vmaxnm_f64_(a: float64x1_t, b: float64x1_t) -> float64x1_t; } - vrecpe_f64_(a) + vmaxnm_f64_(a, b) } -/// Reciprocal estimate. +/// Floating-point Maximun Number (vector) #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(frecpe))] -pub unsafe fn vrecpeq_f64(a: float64x2_t) -> float64x2_t { +#[cfg_attr(test, assert_instr(fmaxnm))] +pub unsafe fn vmaxnmq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frecpe.v2f64")] - fn vrecpeq_f64_(a: float64x2_t) -> float64x2_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmaxnm.v2f64")] + fn vmaxnmq_f64_(a: float64x2_t, b: float64x2_t) -> float64x2_t; } - vrecpeq_f64_(a) + vmaxnmq_f64_(a, b) } -/// Vector reinterpret cast operation +/// Floating-point maximum number across vector #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_s64_p64(a: poly64x1_t) -> int64x1_t { - transmute(a) +#[cfg_attr(test, assert_instr(fmaxnmp))] +pub unsafe fn vmaxnmv_f32(a: float32x2_t) -> f32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmaxnmv.f32.v2f32")] + fn vmaxnmv_f32_(a: float32x2_t) -> f32; + } + vmaxnmv_f32_(a) } -/// Vector reinterpret cast operation +/// Floating-point maximum number across vector #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_u64_p64(a: poly64x1_t) -> uint64x1_t { - transmute(a) +#[cfg_attr(test, assert_instr(fmaxnmp))] +pub unsafe fn vmaxnmvq_f64(a: float64x2_t) -> f64 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmaxnmv.f64.v2f64")] + fn vmaxnmvq_f64_(a: float64x2_t) -> f64; + } + vmaxnmvq_f64_(a) } -/// Vector reinterpret cast operation +/// Floating-point maximum number across vector #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_p64_s64(a: int64x1_t) -> poly64x1_t { - transmute(a) +#[cfg_attr(test, assert_instr(fmaxnmv))] +pub unsafe fn vmaxnmvq_f32(a: float32x4_t) -> f32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmaxnmv.f32.v4f32")] + fn vmaxnmvq_f32_(a: float32x4_t) -> f32; + } + vmaxnmvq_f32_(a) } -/// Vector reinterpret cast operation +/// Floating-point Maximum Number Pairwise (vector). #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_p64_u64(a: uint64x1_t) -> poly64x1_t { - transmute(a) +#[cfg_attr(test, assert_instr(fmaxnmp))] +pub unsafe fn vpmaxnm_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmaxnmp.v2f32")] + fn vpmaxnm_f32_(a: float32x2_t, b: float32x2_t) -> float32x2_t; + } + vpmaxnm_f32_(a, b) } -/// Vector reinterpret cast operation +/// Floating-point Maximum Number Pairwise (vector). #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_s64_p64(a: poly64x2_t) -> int64x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(fmaxnmp))] +pub unsafe fn vpmaxnmq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmaxnmp.v2f64")] + fn vpmaxnmq_f64_(a: float64x2_t, b: float64x2_t) -> float64x2_t; + } + vpmaxnmq_f64_(a, b) } -/// Vector reinterpret cast operation +/// Floating-point Maximum Number Pairwise (vector). #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_u64_p64(a: poly64x2_t) -> uint64x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(fmaxnmp))] +pub unsafe fn vpmaxnmq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmaxnmp.v4f32")] + fn vpmaxnmq_f32_(a: float32x4_t, b: float32x4_t) -> float32x4_t; + } + vpmaxnmq_f32_(a, b) } -/// Vector reinterpret cast operation +/// Floating-point maximum number pairwise #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_p64_s64(a: int64x2_t) -> poly64x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(fmaxnmp))] +pub unsafe fn vpmaxnms_f32(a: float32x2_t) -> f32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmaxnmv.f32.v2f32")] + fn vpmaxnms_f32_(a: float32x2_t) -> f32; + } + vpmaxnms_f32_(a) } -/// Vector reinterpret cast operation +/// Floating-point maximum number pairwise #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_p64_u64(a: uint64x2_t) -> poly64x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(fmaxnmp))] +pub unsafe fn vpmaxnmqd_f64(a: float64x2_t) -> f64 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmaxnmv.f64.v2f64")] + fn vpmaxnmqd_f64_(a: float64x2_t) -> f64; + } + vpmaxnmqd_f64_(a) } -/// Vector reinterpret cast operation +/// Floating-point maximum pairwise #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_s32_p64(a: poly64x1_t) -> int32x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(fmaxp))] +pub unsafe fn vpmaxs_f32(a: float32x2_t) -> f32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmaxv.f32.v2f32")] + fn vpmaxs_f32_(a: float32x2_t) -> f32; + } + vpmaxs_f32_(a) } -/// Vector reinterpret cast operation +/// Floating-point maximum pairwise #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_u32_p64(a: poly64x1_t) -> uint32x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(fmaxp))] +pub unsafe fn vpmaxqd_f64(a: float64x2_t) -> f64 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmaxv.f64.v2f64")] + fn vpmaxqd_f64_(a: float64x2_t) -> f64; + } + vpmaxqd_f64_(a) } -/// Vector reinterpret cast operation +/// Minimum (vector) #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_s32_p64(a: poly64x2_t) -> int32x4_t { - transmute(a) +#[cfg_attr(test, assert_instr(fmin))] +pub unsafe fn vmin_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmin.v1f64")] + fn vmin_f64_(a: float64x1_t, b: float64x1_t) -> float64x1_t; + } + vmin_f64_(a, b) } -/// Vector reinterpret cast operation +/// Minimum (vector) #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_u32_p64(a: poly64x2_t) -> uint32x4_t { - transmute(a) +#[cfg_attr(test, assert_instr(fmin))] +pub unsafe fn vminq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmin.v2f64")] + fn vminq_f64_(a: float64x2_t, b: float64x2_t) -> float64x2_t; + } + vminq_f64_(a, b) } -/// Vector reinterpret cast operation +/// Floating-point Minimun Number (vector) #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_p64_s32(a: int32x2_t) -> poly64x1_t { - transmute(a) +#[cfg_attr(test, assert_instr(fminnm))] +pub unsafe fn vminnm_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fminnm.v1f64")] + fn vminnm_f64_(a: float64x1_t, b: float64x1_t) -> float64x1_t; + } + vminnm_f64_(a, b) } -/// Vector reinterpret cast operation +/// Floating-point Minimun Number (vector) #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_p64_u32(a: uint32x2_t) -> poly64x1_t { - transmute(a) +#[cfg_attr(test, assert_instr(fminnm))] +pub unsafe fn vminnmq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fminnm.v2f64")] + fn vminnmq_f64_(a: float64x2_t, b: float64x2_t) -> float64x2_t; + } + vminnmq_f64_(a, b) } -/// Vector reinterpret cast operation +/// Floating-point minimum number across vector #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_p64_s32(a: int32x4_t) -> poly64x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(fminnmp))] +pub unsafe fn vminnmv_f32(a: float32x2_t) -> f32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fminnmv.f32.v2f32")] + fn vminnmv_f32_(a: float32x2_t) -> f32; + } + vminnmv_f32_(a) } -/// Vector reinterpret cast operation +/// Floating-point minimum number across vector #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_p64_u32(a: uint32x4_t) -> poly64x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(fminnmp))] +pub unsafe fn vminnmvq_f64(a: float64x2_t) -> f64 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fminnmv.f64.v2f64")] + fn vminnmvq_f64_(a: float64x2_t) -> f64; + } + vminnmvq_f64_(a) } -/// Vector reinterpret cast operation +/// Floating-point minimum number across vector #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_s16_p64(a: poly64x1_t) -> int16x4_t { - transmute(a) +#[cfg_attr(test, assert_instr(fminnmv))] +pub unsafe fn vminnmvq_f32(a: float32x4_t) -> f32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fminnmv.f32.v4f32")] + fn vminnmvq_f32_(a: float32x4_t) -> f32; + } + vminnmvq_f32_(a) } -/// Vector reinterpret cast operation +/// Vector move #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_u16_p64(a: poly64x1_t) -> uint16x4_t { - transmute(a) +#[cfg_attr(test, assert_instr(sxtl2))] +pub unsafe fn vmovl_high_s8(a: int8x16_t) -> int16x8_t { + let a: int8x8_t = simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]); + vmovl_s8(a) } -/// Vector reinterpret cast operation +/// Vector move #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_p16_p64(a: poly64x1_t) -> poly16x4_t { - transmute(a) +#[cfg_attr(test, assert_instr(sxtl2))] +pub unsafe fn vmovl_high_s16(a: int16x8_t) -> int32x4_t { + let a: int16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); + vmovl_s16(a) } -/// Vector reinterpret cast operation +/// Vector move #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_s16_p64(a: poly64x2_t) -> int16x8_t { - transmute(a) +#[cfg_attr(test, assert_instr(sxtl2))] +pub unsafe fn vmovl_high_s32(a: int32x4_t) -> int64x2_t { + let a: int32x2_t = simd_shuffle2!(a, a, [2, 3]); + vmovl_s32(a) } -/// Vector reinterpret cast operation +/// Vector move #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_u16_p64(a: poly64x2_t) -> uint16x8_t { - transmute(a) +#[cfg_attr(test, assert_instr(uxtl2))] +pub unsafe fn vmovl_high_u8(a: uint8x16_t) -> uint16x8_t { + let a: uint8x8_t = simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]); + vmovl_u8(a) } -/// Vector reinterpret cast operation +/// Vector move #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_p16_p64(a: poly64x2_t) -> poly16x8_t { - transmute(a) +#[cfg_attr(test, assert_instr(uxtl2))] +pub unsafe fn vmovl_high_u16(a: uint16x8_t) -> uint32x4_t { + let a: uint16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); + vmovl_u16(a) } -/// Vector reinterpret cast operation +/// Vector move #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_p64_p16(a: poly16x4_t) -> poly64x1_t { - transmute(a) +#[cfg_attr(test, assert_instr(uxtl2))] +pub unsafe fn vmovl_high_u32(a: uint32x4_t) -> uint64x2_t { + let a: uint32x2_t = simd_shuffle2!(a, a, [2, 3]); + vmovl_u32(a) } -/// Vector reinterpret cast operation +/// Floating-point add pairwise #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_p64_s16(a: int16x4_t) -> poly64x1_t { - transmute(a) +#[cfg_attr(test, assert_instr(faddp))] +pub unsafe fn vpaddq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.faddp.v4f32")] + fn vpaddq_f32_(a: float32x4_t, b: float32x4_t) -> float32x4_t; + } + vpaddq_f32_(a, b) } -/// Vector reinterpret cast operation +/// Floating-point add pairwise #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_p64_u16(a: uint16x4_t) -> poly64x1_t { - transmute(a) +#[cfg_attr(test, assert_instr(faddp))] +pub unsafe fn vpaddq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.faddp.v2f64")] + fn vpaddq_f64_(a: float64x2_t, b: float64x2_t) -> float64x2_t; + } + vpaddq_f64_(a, b) } -/// Vector reinterpret cast operation +/// Floating-point add pairwise #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_p64_p16(a: poly16x8_t) -> poly64x2_t { - transmute(a) +pub unsafe fn vpadds_f32(a: float32x2_t) -> f32 { + let a1: f32 = simd_extract(a, 0); + let a2: f32 = simd_extract(a, 1); + a1 + a2 } -/// Vector reinterpret cast operation +/// Floating-point add pairwise #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_p64_s16(a: int16x8_t) -> poly64x2_t { - transmute(a) +pub unsafe fn vpaddd_f64(a: float64x2_t) -> f64 { + let a1: f64 = simd_extract(a, 0); + let a2: f64 = simd_extract(a, 1); + a1 + a2 } -/// Vector reinterpret cast operation +/// Floating-point Minimum Number Pairwise (vector). #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_p64_u16(a: uint16x8_t) -> poly64x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(fminnmp))] +pub unsafe fn vpminnm_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fminnmp.v2f32")] + fn vpminnm_f32_(a: float32x2_t, b: float32x2_t) -> float32x2_t; + } + vpminnm_f32_(a, b) } -/// Vector reinterpret cast operation +/// Floating-point Minimum Number Pairwise (vector). #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_s8_p64(a: poly64x1_t) -> int8x8_t { - transmute(a) +#[cfg_attr(test, assert_instr(fminnmp))] +pub unsafe fn vpminnmq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fminnmp.v2f64")] + fn vpminnmq_f64_(a: float64x2_t, b: float64x2_t) -> float64x2_t; + } + vpminnmq_f64_(a, b) } -/// Vector reinterpret cast operation +/// Floating-point Minimum Number Pairwise (vector). #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_u8_p64(a: poly64x1_t) -> uint8x8_t { - transmute(a) +#[cfg_attr(test, assert_instr(fminnmp))] +pub unsafe fn vpminnmq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fminnmp.v4f32")] + fn vpminnmq_f32_(a: float32x4_t, b: float32x4_t) -> float32x4_t; + } + vpminnmq_f32_(a, b) } -/// Vector reinterpret cast operation +/// Floating-point minimum number pairwise #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_p8_p64(a: poly64x1_t) -> poly8x8_t { - transmute(a) +#[cfg_attr(test, assert_instr(fminnmp))] +pub unsafe fn vpminnms_f32(a: float32x2_t) -> f32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fminnmv.f32.v2f32")] + fn vpminnms_f32_(a: float32x2_t) -> f32; + } + vpminnms_f32_(a) } -/// Vector reinterpret cast operation +/// Floating-point minimum number pairwise #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_s8_p64(a: poly64x2_t) -> int8x16_t { - transmute(a) +#[cfg_attr(test, assert_instr(fminnmp))] +pub unsafe fn vpminnmqd_f64(a: float64x2_t) -> f64 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fminnmv.f64.v2f64")] + fn vpminnmqd_f64_(a: float64x2_t) -> f64; + } + vpminnmqd_f64_(a) } -/// Vector reinterpret cast operation +/// Floating-point minimum pairwise #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_u8_p64(a: poly64x2_t) -> uint8x16_t { - transmute(a) +#[cfg_attr(test, assert_instr(fminp))] +pub unsafe fn vpmins_f32(a: float32x2_t) -> f32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fminv.f32.v2f32")] + fn vpmins_f32_(a: float32x2_t) -> f32; + } + vpmins_f32_(a) } -/// Vector reinterpret cast operation +/// Floating-point minimum pairwise #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_p8_p64(a: poly64x2_t) -> poly8x16_t { - transmute(a) +#[cfg_attr(test, assert_instr(fminp))] +pub unsafe fn vpminqd_f64(a: float64x2_t) -> f64 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fminv.f64.v2f64")] + fn vpminqd_f64_(a: float64x2_t) -> f64; + } + vpminqd_f64_(a) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_p64_p8(a: poly8x8_t) -> poly64x1_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmull))] +pub unsafe fn vqdmullh_s16(a: i16, b: i16) -> i32 { + let a: int16x4_t = vdup_n_s16(a); + let b: int16x4_t = vdup_n_s16(b); + simd_extract(vqdmull_s16(a, b), 0) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_p64_s8(a: int8x8_t) -> poly64x1_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmull))] +pub unsafe fn vqdmulls_s32(a: i32, b: i32) -> i64 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqdmulls.scalar")] + fn vqdmulls_s32_(a: i32, b: i32) -> i64; + } + vqdmulls_s32_(a, b) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_p64_u8(a: uint8x8_t) -> poly64x1_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmull2))] +pub unsafe fn vqdmull_high_s16(a: int16x8_t, b: int16x8_t) -> int32x4_t { + let a: int16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); + let b: int16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); + vqdmull_s16(a, b) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_p64_p8(a: poly8x16_t) -> poly64x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmull2))] +pub unsafe fn vqdmull_high_s32(a: int32x4_t, b: int32x4_t) -> int64x2_t { + let a: int32x2_t = simd_shuffle2!(a, a, [2, 3]); + let b: int32x2_t = simd_shuffle2!(b, b, [2, 3]); + vqdmull_s32(a, b) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_p64_s8(a: int8x16_t) -> poly64x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmull2))] +pub unsafe fn vqdmull_high_n_s16(a: int16x8_t, b: i16) -> int32x4_t { + let a: int16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); + let b: int16x4_t = vdup_n_s16(b); + vqdmull_s16(a, b) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_p64_u8(a: uint8x16_t) -> poly64x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmull2))] +pub unsafe fn vqdmull_high_n_s32(a: int32x4_t, b: i32) -> int64x2_t { + let a: int32x2_t = simd_shuffle2!(a, a, [2, 3]); + let b: int32x2_t = vdup_n_s32(b); + vqdmull_s32(a, b) } -/// Vector reinterpret cast operation +/// Vector saturating doubling long multiply by scalar #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_s8_f64(a: float64x1_t) -> int8x8_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmull, N = 4))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqdmull_laneq_s16(a: int16x4_t, b: int16x8_t) -> int32x4_t { + static_assert_imm3!(N); + let b: int16x4_t = simd_shuffle4!(b, b, [N as u32, N as u32, N as u32, N as u32]); + vqdmull_s16(a, b) } -/// Vector reinterpret cast operation +/// Vector saturating doubling long multiply by scalar #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_s16_f64(a: float64x1_t) -> int16x4_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmull, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqdmull_laneq_s32(a: int32x2_t, b: int32x4_t) -> int64x2_t { + static_assert_imm2!(N); + let b: int32x2_t = simd_shuffle2!(b, b, [N as u32, N as u32]); + vqdmull_s32(a, b) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_s32_f64(a: float64x1_t) -> int32x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmull, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqdmullh_lane_s16(a: i16, b: int16x4_t) -> i32 { + static_assert_imm2!(N); + let b: i16 = simd_extract(b, N as u32); + vqdmullh_s16(a, b) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_s64_f64(a: float64x1_t) -> int64x1_t { - transmute(a) -} - -/// Vector reinterpret cast operation -#[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_s8_f64(a: float64x2_t) -> int8x16_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmull, N = 4))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqdmullh_laneq_s16(a: i16, b: int16x8_t) -> i32 { + static_assert_imm3!(N); + let b: i16 = simd_extract(b, N as u32); + vqdmullh_s16(a, b) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_s16_f64(a: float64x2_t) -> int16x8_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmull, N = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqdmulls_lane_s32(a: i32, b: int32x2_t) -> i64 { + static_assert_imm1!(N); + let b: i32 = simd_extract(b, N as u32); + vqdmulls_s32(a, b) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_s32_f64(a: float64x2_t) -> int32x4_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmull, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqdmulls_laneq_s32(a: i32, b: int32x4_t) -> i64 { + static_assert_imm2!(N); + let b: i32 = simd_extract(b, N as u32); + vqdmulls_s32(a, b) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_s64_f64(a: float64x2_t) -> int64x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmull2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqdmull_high_lane_s16(a: int16x8_t, b: int16x4_t) -> int32x4_t { + static_assert_imm2!(N); + let a: int16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); + let b: int16x4_t = simd_shuffle4!(b, b, [N as u32, N as u32, N as u32, N as u32]); + vqdmull_s16(a, b) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_u8_f64(a: float64x1_t) -> uint8x8_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmull2, N = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqdmull_high_lane_s32(a: int32x4_t, b: int32x2_t) -> int64x2_t { + static_assert_imm1!(N); + let a: int32x2_t = simd_shuffle2!(a, a, [2, 3]); + let b: int32x2_t = simd_shuffle2!(b, b, [N as u32, N as u32]); + vqdmull_s32(a, b) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_u16_f64(a: float64x1_t) -> uint16x4_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmull2, N = 4))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqdmull_high_laneq_s16(a: int16x8_t, b: int16x8_t) -> int32x4_t { + static_assert_imm3!(N); + let a: int16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); + let b: int16x4_t = simd_shuffle4!(b, b, [N as u32, N as u32, N as u32, N as u32]); + vqdmull_s16(a, b) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_u32_f64(a: float64x1_t) -> uint32x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmull2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqdmull_high_laneq_s32(a: int32x4_t, b: int32x4_t) -> int64x2_t { + static_assert_imm2!(N); + let a: int32x2_t = simd_shuffle2!(a, a, [2, 3]); + let b: int32x2_t = simd_shuffle2!(b, b, [N as u32, N as u32]); + vqdmull_s32(a, b) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply-add long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_u64_f64(a: float64x1_t) -> uint64x1_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmlal2))] +pub unsafe fn vqdmlal_high_s16(a: int32x4_t, b: int16x8_t, c: int16x8_t) -> int32x4_t { + vqaddq_s32(a, vqdmull_high_s16(b, c)) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply-add long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_u8_f64(a: float64x2_t) -> uint8x16_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmlal2))] +pub unsafe fn vqdmlal_high_s32(a: int64x2_t, b: int32x4_t, c: int32x4_t) -> int64x2_t { + vqaddq_s64(a, vqdmull_high_s32(b, c)) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply-add long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_u16_f64(a: float64x2_t) -> uint16x8_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmlal2))] +pub unsafe fn vqdmlal_high_n_s16(a: int32x4_t, b: int16x8_t, c: i16) -> int32x4_t { + vqaddq_s32(a, vqdmull_high_n_s16(b, c)) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply-add long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_u32_f64(a: float64x2_t) -> uint32x4_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmlal2))] +pub unsafe fn vqdmlal_high_n_s32(a: int64x2_t, b: int32x4_t, c: i32) -> int64x2_t { + vqaddq_s64(a, vqdmull_high_n_s32(b, c)) } -/// Vector reinterpret cast operation +/// Vector widening saturating doubling multiply accumulate with scalar #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_u64_f64(a: float64x2_t) -> uint64x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmlal, N = 2))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqdmlal_laneq_s16(a: int32x4_t, b: int16x4_t, c: int16x8_t) -> int32x4_t { + static_assert_imm3!(N); + vqaddq_s32(a, vqdmull_laneq_s16::(b, c)) } -/// Vector reinterpret cast operation +/// Vector widening saturating doubling multiply accumulate with scalar #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_p8_f64(a: float64x1_t) -> poly8x8_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmlal, N = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqdmlal_laneq_s32(a: int64x2_t, b: int32x2_t, c: int32x4_t) -> int64x2_t { + static_assert_imm2!(N); + vqaddq_s64(a, vqdmull_laneq_s32::(b, c)) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply-add long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_p16_f64(a: float64x1_t) -> poly16x4_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmlal2, N = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqdmlal_high_lane_s16(a: int32x4_t, b: int16x8_t, c: int16x4_t) -> int32x4_t { + static_assert_imm2!(N); + vqaddq_s32(a, vqdmull_high_lane_s16::(b, c)) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply-add long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_p64_f32(a: float32x2_t) -> poly64x1_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmlal2, N = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqdmlal_high_laneq_s16(a: int32x4_t, b: int16x8_t, c: int16x8_t) -> int32x4_t { + static_assert_imm3!(N); + vqaddq_s32(a, vqdmull_high_laneq_s16::(b, c)) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply-add long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_p64_f64(a: float64x1_t) -> poly64x1_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmlal2, N = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqdmlal_high_lane_s32(a: int64x2_t, b: int32x4_t, c: int32x2_t) -> int64x2_t { + static_assert_imm1!(N); + vqaddq_s64(a, vqdmull_high_lane_s32::(b, c)) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply-add long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_p8_f64(a: float64x2_t) -> poly8x16_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmlal2, N = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqdmlal_high_laneq_s32(a: int64x2_t, b: int32x4_t, c: int32x4_t) -> int64x2_t { + static_assert_imm2!(N); + vqaddq_s64(a, vqdmull_high_laneq_s32::(b, c)) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply-add long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_p16_f64(a: float64x2_t) -> poly16x8_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmull))] +pub unsafe fn vqdmlalh_s16(a: i32, b: i16, c: i16) -> i32 { + let x: int32x4_t = vqdmull_s16(vdup_n_s16(b), vdup_n_s16(c)); + vqadds_s32(a, simd_extract(x, 0)) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply-add long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_p64_f32(a: float32x4_t) -> poly64x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmull))] +pub unsafe fn vqdmlals_s32(a: i64, b: i32, c: i32) -> i64 { + let x: int64x2_t = vqdmull_s32(vdup_n_s32(b), vdup_n_s32(c)); + vqaddd_s64(a, simd_extract(x, 0)) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply-add long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_p64_f64(a: float64x2_t) -> poly64x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmlal, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqdmlalh_lane_s16(a: i32, b: i16, c: int16x4_t) -> i32 { + static_assert_imm2!(LANE); + vqdmlalh_s16(a, b, simd_extract(c, LANE as u32)) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply-add long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_f64_s8(a: int8x8_t) -> float64x1_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmlal, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqdmlalh_laneq_s16(a: i32, b: i16, c: int16x8_t) -> i32 { + static_assert_imm3!(LANE); + vqdmlalh_s16(a, b, simd_extract(c, LANE as u32)) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply-add long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_f64_s16(a: int16x4_t) -> float64x1_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmull, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqdmlals_lane_s32(a: i64, b: i32, c: int32x2_t) -> i64 { + static_assert_imm1!(LANE); + vqdmlals_s32(a, b, simd_extract(c, LANE as u32)) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply-add long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_f64_s32(a: int32x2_t) -> float64x1_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmull, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqdmlals_laneq_s32(a: i64, b: i32, c: int32x4_t) -> i64 { + static_assert_imm2!(LANE); + vqdmlals_s32(a, b, simd_extract(c, LANE as u32)) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply-subtract long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_f64_s64(a: int64x1_t) -> float64x1_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmlsl2))] +pub unsafe fn vqdmlsl_high_s16(a: int32x4_t, b: int16x8_t, c: int16x8_t) -> int32x4_t { + vqsubq_s32(a, vqdmull_high_s16(b, c)) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply-subtract long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_f64_s8(a: int8x16_t) -> float64x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmlsl2))] +pub unsafe fn vqdmlsl_high_s32(a: int64x2_t, b: int32x4_t, c: int32x4_t) -> int64x2_t { + vqsubq_s64(a, vqdmull_high_s32(b, c)) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply-subtract long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_f64_s16(a: int16x8_t) -> float64x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmlsl2))] +pub unsafe fn vqdmlsl_high_n_s16(a: int32x4_t, b: int16x8_t, c: i16) -> int32x4_t { + vqsubq_s32(a, vqdmull_high_n_s16(b, c)) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply-subtract long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_f64_s32(a: int32x4_t) -> float64x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmlsl2))] +pub unsafe fn vqdmlsl_high_n_s32(a: int64x2_t, b: int32x4_t, c: i32) -> int64x2_t { + vqsubq_s64(a, vqdmull_high_n_s32(b, c)) } -/// Vector reinterpret cast operation +/// Vector widening saturating doubling multiply subtract with scalar #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_f64_s64(a: int64x2_t) -> float64x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmlsl, N = 2))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqdmlsl_laneq_s16(a: int32x4_t, b: int16x4_t, c: int16x8_t) -> int32x4_t { + static_assert_imm3!(N); + vqsubq_s32(a, vqdmull_laneq_s16::(b, c)) } -/// Vector reinterpret cast operation +/// Vector widening saturating doubling multiply subtract with scalar #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_f64_p8(a: poly8x8_t) -> float64x1_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmlsl, N = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqdmlsl_laneq_s32(a: int64x2_t, b: int32x2_t, c: int32x4_t) -> int64x2_t { + static_assert_imm2!(N); + vqsubq_s64(a, vqdmull_laneq_s32::(b, c)) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply-subtract long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_f64_u16(a: uint16x4_t) -> float64x1_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmlsl2, N = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqdmlsl_high_lane_s16(a: int32x4_t, b: int16x8_t, c: int16x4_t) -> int32x4_t { + static_assert_imm2!(N); + vqsubq_s32(a, vqdmull_high_lane_s16::(b, c)) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply-subtract long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_f64_u32(a: uint32x2_t) -> float64x1_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmlsl2, N = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqdmlsl_high_laneq_s16(a: int32x4_t, b: int16x8_t, c: int16x8_t) -> int32x4_t { + static_assert_imm3!(N); + vqsubq_s32(a, vqdmull_high_laneq_s16::(b, c)) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply-subtract long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_f64_u64(a: uint64x1_t) -> float64x1_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmlsl2, N = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqdmlsl_high_lane_s32(a: int64x2_t, b: int32x4_t, c: int32x2_t) -> int64x2_t { + static_assert_imm1!(N); + vqsubq_s64(a, vqdmull_high_lane_s32::(b, c)) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply-subtract long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_f64_p8(a: poly8x16_t) -> float64x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmlsl2, N = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqdmlsl_high_laneq_s32(a: int64x2_t, b: int32x4_t, c: int32x4_t) -> int64x2_t { + static_assert_imm2!(N); + vqsubq_s64(a, vqdmull_high_laneq_s32::(b, c)) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply-subtract long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_f64_u16(a: uint16x8_t) -> float64x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmull))] +pub unsafe fn vqdmlslh_s16(a: i32, b: i16, c: i16) -> i32 { + let x: int32x4_t = vqdmull_s16(vdup_n_s16(b), vdup_n_s16(c)); + vqsubs_s32(a, simd_extract(x, 0)) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply-subtract long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_f64_u32(a: uint32x4_t) -> float64x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmull))] +pub unsafe fn vqdmlsls_s32(a: i64, b: i32, c: i32) -> i64 { + let x: int64x2_t = vqdmull_s32(vdup_n_s32(b), vdup_n_s32(c)); + vqsubd_s64(a, simd_extract(x, 0)) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply-subtract long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_f64_u64(a: uint64x2_t) -> float64x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmlsl, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqdmlslh_lane_s16(a: i32, b: i16, c: int16x4_t) -> i32 { + static_assert_imm2!(LANE); + vqdmlslh_s16(a, b, simd_extract(c, LANE as u32)) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply-subtract long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_f64_u8(a: uint8x8_t) -> float64x1_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmlsl, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqdmlslh_laneq_s16(a: i32, b: i16, c: int16x8_t) -> i32 { + static_assert_imm3!(LANE); + vqdmlslh_s16(a, b, simd_extract(c, LANE as u32)) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply-subtract long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_f64_p16(a: poly16x4_t) -> float64x1_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmull, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqdmlsls_lane_s32(a: i64, b: i32, c: int32x2_t) -> i64 { + static_assert_imm1!(LANE); + vqdmlsls_s32(a, b, simd_extract(c, LANE as u32)) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply-subtract long #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_f64_p64(a: poly64x1_t) -> float64x1_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmull, LANE = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqdmlsls_laneq_s32(a: i64, b: i32, c: int32x4_t) -> i64 { + static_assert_imm2!(LANE); + vqdmlsls_s32(a, b, simd_extract(c, LANE as u32)) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply returning high half #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_f32_p64(a: poly64x1_t) -> float32x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmulh))] +pub unsafe fn vqdmulhh_s16(a: i16, b: i16) -> i16 { + let a: int16x4_t = vdup_n_s16(a); + let b: int16x4_t = vdup_n_s16(b); + simd_extract(vqdmulh_s16(a, b), 0) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply returning high half #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_f64_u8(a: uint8x16_t) -> float64x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmulh))] +pub unsafe fn vqdmulhs_s32(a: i32, b: i32) -> i32 { + let a: int32x2_t = vdup_n_s32(a); + let b: int32x2_t = vdup_n_s32(b); + simd_extract(vqdmulh_s32(a, b), 0) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply returning high half #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_f64_p16(a: poly16x8_t) -> float64x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmulh, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqdmulhh_lane_s16(a: i16, b: int16x4_t) -> i16 { + static_assert_imm2!(N); + let b: i16 = simd_extract(b, N as u32); + vqdmulhh_s16(a, b) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply returning high half #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_f64_p64(a: poly64x2_t) -> float64x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmulh, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqdmulhh_laneq_s16(a: i16, b: int16x8_t) -> i16 { + static_assert_imm3!(N); + let b: i16 = simd_extract(b, N as u32); + vqdmulhh_s16(a, b) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply returning high half #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_f32_p64(a: poly64x2_t) -> float32x4_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmulh, N = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqdmulhs_lane_s32(a: i32, b: int32x2_t) -> i32 { + static_assert_imm1!(N); + let b: i32 = simd_extract(b, N as u32); + vqdmulhs_s32(a, b) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply returning high half #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_f64_f32(a: float32x2_t) -> float64x1_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmulh, N = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqdmulhs_laneq_s32(a: i32, b: int32x4_t) -> i32 { + static_assert_imm2!(N); + let b: i32 = simd_extract(b, N as u32); + vqdmulhs_s32(a, b) } -/// Vector reinterpret cast operation +/// Vector saturating doubling multiply high by scalar #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpret_f32_f64(a: float64x1_t) -> float32x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmulh, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqdmulh_lane_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { + static_assert_imm2!(LANE); + vqdmulh_s16(a, vdup_n_s16(simd_extract(b, LANE as u32))) } -/// Vector reinterpret cast operation +/// Vector saturating doubling multiply high by scalar #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_f64_f32(a: float32x4_t) -> float64x2_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmulh, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqdmulhq_lane_s16(a: int16x8_t, b: int16x4_t) -> int16x8_t { + static_assert_imm2!(LANE); + vqdmulhq_s16(a, vdupq_n_s16(simd_extract(b, LANE as u32))) } -/// Vector reinterpret cast operation +/// Vector saturating doubling multiply high by scalar #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop))] -pub unsafe fn vreinterpretq_f32_f64(a: float64x2_t) -> float32x4_t { - transmute(a) +#[cfg_attr(test, assert_instr(sqdmulh, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqdmulh_lane_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { + static_assert_imm1!(LANE); + vqdmulh_s32(a, vdup_n_s32(simd_extract(b, LANE as u32))) } -/// Signed rounding shift left +/// Vector saturating doubling multiply high by scalar #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(srshl))] -pub unsafe fn vrshld_s64(a: i64, b: i64) -> i64 { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.srshl.i64")] - fn vrshld_s64_(a: i64, b: i64) -> i64; - } - vrshld_s64_(a, b) +#[cfg_attr(test, assert_instr(sqdmulh, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqdmulhq_lane_s32(a: int32x4_t, b: int32x2_t) -> int32x4_t { + static_assert_imm1!(LANE); + vqdmulhq_s32(a, vdupq_n_s32(simd_extract(b, LANE as u32))) } -/// Unsigned rounding shift left +/// Saturating extract narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(urshl))] -pub unsafe fn vrshld_u64(a: u64, b: i64) -> u64 { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.urshl.i64")] - fn vrshld_u64_(a: u64, b: i64) -> u64; - } - vrshld_u64_(a, b) +#[cfg_attr(test, assert_instr(sqxtn))] +pub unsafe fn vqmovnh_s16(a: i16) -> i8 { + simd_extract(vqmovn_s16(vdupq_n_s16(a)), 0) } -/// Signed rounding shift right +/// Saturating extract narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(srshr, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vrshrd_n_s64(a: i64) -> i64 { - static_assert!(N : i32 where N >= 1 && N <= 64); - vrshld_s64(a, -N as i64) +#[cfg_attr(test, assert_instr(sqxtn))] +pub unsafe fn vqmovns_s32(a: i32) -> i16 { + simd_extract(vqmovn_s32(vdupq_n_s32(a)), 0) } -/// Unsigned rounding shift right +/// Saturating extract narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(urshr, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vrshrd_n_u64(a: u64) -> u64 { - static_assert!(N : i32 where N >= 1 && N <= 64); - vrshld_u64(a, -N as i64) +#[cfg_attr(test, assert_instr(uqxtn))] +pub unsafe fn vqmovnh_u16(a: u16) -> u8 { + simd_extract(vqmovn_u16(vdupq_n_u16(a)), 0) } -/// Rounding shift right narrow +/// Saturating extract narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(rshrn2, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vrshrn_high_n_s16(a: int8x8_t, b: int16x8_t) -> int8x16_t { - static_assert!(N : i32 where N >= 1 && N <= 8); - simd_shuffle16!(a, vrshrn_n_s16::(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) +#[cfg_attr(test, assert_instr(uqxtn))] +pub unsafe fn vqmovns_u32(a: u32) -> u16 { + simd_extract(vqmovn_u32(vdupq_n_u32(a)), 0) } -/// Rounding shift right narrow +/// Saturating extract narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(rshrn2, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vrshrn_high_n_s32(a: int16x4_t, b: int32x4_t) -> int16x8_t { - static_assert!(N : i32 where N >= 1 && N <= 16); - simd_shuffle8!(a, vrshrn_n_s32::(b), [0, 1, 2, 3, 4, 5, 6, 7]) +#[cfg_attr(test, assert_instr(sqxtn))] +pub unsafe fn vqmovnd_s64(a: i64) -> i32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.scalar.sqxtn.i32.i64")] + fn vqmovnd_s64_(a: i64) -> i32; + } + vqmovnd_s64_(a) } -/// Rounding shift right narrow +/// Saturating extract narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(rshrn2, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vrshrn_high_n_s64(a: int32x2_t, b: int64x2_t) -> int32x4_t { - static_assert!(N : i32 where N >= 1 && N <= 32); - simd_shuffle4!(a, vrshrn_n_s64::(b), [0, 1, 2, 3]) +#[cfg_attr(test, assert_instr(uqxtn))] +pub unsafe fn vqmovnd_u64(a: u64) -> u32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.scalar.uqxtn.i32.i64")] + fn vqmovnd_u64_(a: u64) -> u32; + } + vqmovnd_u64_(a) } -/// Rounding shift right narrow +/// Signed saturating extract narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(rshrn2, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vrshrn_high_n_u16(a: uint8x8_t, b: uint16x8_t) -> uint8x16_t { - static_assert!(N : i32 where N >= 1 && N <= 8); - simd_shuffle16!(a, vrshrn_n_u16::(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) +#[cfg_attr(test, assert_instr(sqxtn2))] +pub unsafe fn vqmovn_high_s16(a: int8x8_t, b: int16x8_t) -> int8x16_t { + simd_shuffle16!(a, vqmovn_s16(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) } -/// Rounding shift right narrow +/// Signed saturating extract narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(rshrn2, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vrshrn_high_n_u32(a: uint16x4_t, b: uint32x4_t) -> uint16x8_t { - static_assert!(N : i32 where N >= 1 && N <= 16); - simd_shuffle8!(a, vrshrn_n_u32::(b), [0, 1, 2, 3, 4, 5, 6, 7]) +#[cfg_attr(test, assert_instr(sqxtn2))] +pub unsafe fn vqmovn_high_s32(a: int16x4_t, b: int32x4_t) -> int16x8_t { + simd_shuffle8!(a, vqmovn_s32(b), [0, 1, 2, 3, 4, 5, 6, 7]) } -/// Rounding shift right narrow +/// Signed saturating extract narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(rshrn2, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vrshrn_high_n_u64(a: uint32x2_t, b: uint64x2_t) -> uint32x4_t { - static_assert!(N : i32 where N >= 1 && N <= 32); - simd_shuffle4!(a, vrshrn_n_u64::(b), [0, 1, 2, 3]) +#[cfg_attr(test, assert_instr(sqxtn2))] +pub unsafe fn vqmovn_high_s64(a: int32x2_t, b: int64x2_t) -> int32x4_t { + simd_shuffle4!(a, vqmovn_s64(b), [0, 1, 2, 3]) } -/// Signed rounding shift right and accumulate. +/// Signed saturating extract narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(srsra, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vrsrad_n_s64(a: i64, b: i64) -> i64 { - static_assert!(N : i32 where N >= 1 && N <= 64); - let b: i64 = vrshrd_n_s64::(b); - a + b +#[cfg_attr(test, assert_instr(uqxtn2))] +pub unsafe fn vqmovn_high_u16(a: uint8x8_t, b: uint16x8_t) -> uint8x16_t { + simd_shuffle16!(a, vqmovn_u16(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) } -/// Ungisned rounding shift right and accumulate. +/// Signed saturating extract narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(ursra, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vrsrad_n_u64(a: u64, b: u64) -> u64 { - static_assert!(N : i32 where N >= 1 && N <= 64); - let b: u64 = vrshrd_n_u64::(b); - a + b +#[cfg_attr(test, assert_instr(uqxtn2))] +pub unsafe fn vqmovn_high_u32(a: uint16x4_t, b: uint32x4_t) -> uint16x8_t { + simd_shuffle8!(a, vqmovn_u32(b), [0, 1, 2, 3, 4, 5, 6, 7]) } -/// Insert vector element from another vector element +/// Signed saturating extract narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vset_lane_f64(a: f64, b: float64x1_t) -> float64x1_t { - static_assert!(LANE : i32 where LANE == 0); - simd_insert(b, LANE as u32, a) +#[cfg_attr(test, assert_instr(uqxtn2))] +pub unsafe fn vqmovn_high_u64(a: uint32x2_t, b: uint64x2_t) -> uint32x4_t { + simd_shuffle4!(a, vqmovn_u64(b), [0, 1, 2, 3]) } -/// Insert vector element from another vector element +/// Signed saturating extract unsigned narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(nop, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vsetq_lane_f64(a: f64, b: float64x2_t) -> float64x2_t { - static_assert_imm1!(LANE); - simd_insert(b, LANE as u32, a) +#[cfg_attr(test, assert_instr(sqxtun))] +pub unsafe fn vqmovunh_s16(a: i16) -> u8 { + simd_extract(vqmovun_s16(vdupq_n_s16(a)), 0) } -/// Signed Shift left +/// Signed saturating extract unsigned narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sshl))] -pub unsafe fn vshld_s64(a: i64, b: i64) -> i64 { - transmute(vshl_s64(transmute(a), transmute(b))) +#[cfg_attr(test, assert_instr(sqxtun))] +pub unsafe fn vqmovuns_s32(a: i32) -> u16 { + simd_extract(vqmovun_s32(vdupq_n_s32(a)), 0) } -/// Unsigned Shift left +/// Signed saturating extract unsigned narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(ushl))] -pub unsafe fn vshld_u64(a: u64, b: i64) -> u64 { - transmute(vshl_u64(transmute(a), transmute(b))) +#[cfg_attr(test, assert_instr(sqxtun))] +pub unsafe fn vqmovund_s64(a: i64) -> u32 { + simd_extract(vqmovun_s64(vdupq_n_s64(a)), 0) } -/// Signed shift left long +/// Signed saturating extract unsigned narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sshll2, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vshll_high_n_s8(a: int8x16_t) -> int16x8_t { - static_assert!(N : i32 where N >= 0 && N <= 8); - let b: int8x8_t = simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]); - vshll_n_s8::(b) +#[cfg_attr(test, assert_instr(sqxtun2))] +pub unsafe fn vqmovun_high_s16(a: uint8x8_t, b: int16x8_t) -> uint8x16_t { + simd_shuffle16!(a, vqmovun_s16(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) } -/// Signed shift left long +/// Signed saturating extract unsigned narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sshll2, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vshll_high_n_s16(a: int16x8_t) -> int32x4_t { - static_assert!(N : i32 where N >= 0 && N <= 16); - let b: int16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); - vshll_n_s16::(b) +#[cfg_attr(test, assert_instr(sqxtun2))] +pub unsafe fn vqmovun_high_s32(a: uint16x4_t, b: int32x4_t) -> uint16x8_t { + simd_shuffle8!(a, vqmovun_s32(b), [0, 1, 2, 3, 4, 5, 6, 7]) } -/// Signed shift left long +/// Signed saturating extract unsigned narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sshll2, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vshll_high_n_s32(a: int32x4_t) -> int64x2_t { - static_assert!(N : i32 where N >= 0 && N <= 32); - let b: int32x2_t = simd_shuffle2!(a, a, [2, 3]); - vshll_n_s32::(b) +#[cfg_attr(test, assert_instr(sqxtun2))] +pub unsafe fn vqmovun_high_s64(a: uint32x2_t, b: int64x2_t) -> uint32x4_t { + simd_shuffle4!(a, vqmovun_s64(b), [0, 1, 2, 3]) } -/// Signed shift left long +/// Signed saturating rounding doubling multiply returning high half #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(ushll2, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vshll_high_n_u8(a: uint8x16_t) -> uint16x8_t { - static_assert!(N : i32 where N >= 0 && N <= 8); - let b: uint8x8_t = simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]); - vshll_n_u8::(b) +#[cfg_attr(test, assert_instr(sqrdmulh))] +pub unsafe fn vqrdmulhh_s16(a: i16, b: i16) -> i16 { + simd_extract(vqrdmulh_s16(vdup_n_s16(a), vdup_n_s16(b)), 0) } -/// Signed shift left long +/// Signed saturating rounding doubling multiply returning high half #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(ushll2, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vshll_high_n_u16(a: uint16x8_t) -> uint32x4_t { - static_assert!(N : i32 where N >= 0 && N <= 16); - let b: uint16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); - vshll_n_u16::(b) +#[cfg_attr(test, assert_instr(sqrdmulh))] +pub unsafe fn vqrdmulhs_s32(a: i32, b: i32) -> i32 { + simd_extract(vqrdmulh_s32(vdup_n_s32(a), vdup_n_s32(b)), 0) } -/// Signed shift left long +/// Signed saturating rounding doubling multiply returning high half #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(ushll2, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vshll_high_n_u32(a: uint32x4_t) -> uint64x2_t { - static_assert!(N : i32 where N >= 0 && N <= 32); - let b: uint32x2_t = simd_shuffle2!(a, a, [2, 3]); - vshll_n_u32::(b) +#[cfg_attr(test, assert_instr(sqrdmulh, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqrdmulhh_lane_s16(a: i16, b: int16x4_t) -> i16 { + static_assert_imm2!(LANE); + vqrdmulhh_s16(a, simd_extract(b, LANE as u32)) } -/// Shift right narrow +/// Signed saturating rounding doubling multiply returning high half #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(shrn2, N = 2))] +#[cfg_attr(test, assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vshrn_high_n_s16(a: int8x8_t, b: int16x8_t) -> int8x16_t { - static_assert!(N : i32 where N >= 1 && N <= 8); - simd_shuffle16!(a, vshrn_n_s16::(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) +pub unsafe fn vqrdmulhh_laneq_s16(a: i16, b: int16x8_t) -> i16 { + static_assert_imm3!(LANE); + vqrdmulhh_s16(a, simd_extract(b, LANE as u32)) } -/// Shift right narrow +/// Signed saturating rounding doubling multiply returning high half #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(shrn2, N = 2))] +#[cfg_attr(test, assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vshrn_high_n_s32(a: int16x4_t, b: int32x4_t) -> int16x8_t { - static_assert!(N : i32 where N >= 1 && N <= 16); - simd_shuffle8!(a, vshrn_n_s32::(b), [0, 1, 2, 3, 4, 5, 6, 7]) +pub unsafe fn vqrdmulhs_lane_s32(a: i32, b: int32x2_t) -> i32 { + static_assert_imm1!(LANE); + vqrdmulhs_s32(a, simd_extract(b, LANE as u32)) } -/// Shift right narrow +/// Signed saturating rounding doubling multiply returning high half #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(shrn2, N = 2))] +#[cfg_attr(test, assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vshrn_high_n_s64(a: int32x2_t, b: int64x2_t) -> int32x4_t { - static_assert!(N : i32 where N >= 1 && N <= 32); - simd_shuffle4!(a, vshrn_n_s64::(b), [0, 1, 2, 3]) +pub unsafe fn vqrdmulhs_laneq_s32(a: i32, b: int32x4_t) -> i32 { + static_assert_imm2!(LANE); + vqrdmulhs_s32(a, simd_extract(b, LANE as u32)) } -/// Shift right narrow +/// Signed saturating rounding doubling multiply accumulate returning high half #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(shrn2, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vshrn_high_n_u16(a: uint8x8_t, b: uint16x8_t) -> uint8x16_t { - static_assert!(N : i32 where N >= 1 && N <= 8); - simd_shuffle16!(a, vshrn_n_u16::(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) +#[target_feature(enable = "rdm")] +#[cfg_attr(test, assert_instr(sqrdmlah))] +pub unsafe fn vqrdmlah_s16(a: int16x4_t, b: int16x4_t, c: int16x4_t) -> int16x4_t { + vqadd_s16(a, vqrdmulh_s16(b, c)) } -/// Shift right narrow +/// Signed saturating rounding doubling multiply accumulate returning high half #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(shrn2, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vshrn_high_n_u32(a: uint16x4_t, b: uint32x4_t) -> uint16x8_t { - static_assert!(N : i32 where N >= 1 && N <= 16); - simd_shuffle8!(a, vshrn_n_u32::(b), [0, 1, 2, 3, 4, 5, 6, 7]) +#[target_feature(enable = "rdm")] +#[cfg_attr(test, assert_instr(sqrdmlah))] +pub unsafe fn vqrdmlahq_s16(a: int16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8_t { + vqaddq_s16(a, vqrdmulhq_s16(b, c)) } -/// Shift right narrow +/// Signed saturating rounding doubling multiply accumulate returning high half #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(shrn2, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vshrn_high_n_u64(a: uint32x2_t, b: uint64x2_t) -> uint32x4_t { - static_assert!(N : i32 where N >= 1 && N <= 32); - simd_shuffle4!(a, vshrn_n_u64::(b), [0, 1, 2, 3]) +#[target_feature(enable = "rdm")] +#[cfg_attr(test, assert_instr(sqrdmlah))] +pub unsafe fn vqrdmlah_s32(a: int32x2_t, b: int32x2_t, c: int32x2_t) -> int32x2_t { + vqadd_s32(a, vqrdmulh_s32(b, c)) } -/// Transpose vectors +/// Signed saturating rounding doubling multiply accumulate returning high half #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(trn1))] -pub unsafe fn vtrn1_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { - simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]) +#[target_feature(enable = "rdm")] +#[cfg_attr(test, assert_instr(sqrdmlah))] +pub unsafe fn vqrdmlahq_s32(a: int32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4_t { + vqaddq_s32(a, vqrdmulhq_s32(b, c)) } -/// Transpose vectors +/// Signed saturating rounding doubling multiply accumulate returning high half #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(trn1))] -pub unsafe fn vtrn1q_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { - simd_shuffle16!(a, b, [0, 16, 2, 18, 4, 20, 6, 22, 8, 24, 10, 26, 12, 28, 14, 30]) +#[target_feature(enable = "rdm")] +#[cfg_attr(test, assert_instr(sqrdmlah))] +pub unsafe fn vqrdmlahh_s16(a: i16, b: i16, c: i16) -> i16 { + let a: int16x4_t = vdup_n_s16(a); + let b: int16x4_t = vdup_n_s16(b); + let c: int16x4_t = vdup_n_s16(c); + simd_extract(vqrdmlah_s16(a, b, c), 0) } -/// Transpose vectors +/// Signed saturating rounding doubling multiply accumulate returning high half #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(trn1))] -pub unsafe fn vtrn1_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { - simd_shuffle4!(a, b, [0, 4, 2, 6]) +#[target_feature(enable = "rdm")] +#[cfg_attr(test, assert_instr(sqrdmlah))] +pub unsafe fn vqrdmlahs_s32(a: i32, b: i32, c: i32) -> i32 { + let a: int32x2_t = vdup_n_s32(a); + let b: int32x2_t = vdup_n_s32(b); + let c: int32x2_t = vdup_n_s32(c); + simd_extract(vqrdmlah_s32(a, b, c), 0) } -/// Transpose vectors +/// Signed saturating rounding doubling multiply accumulate returning high half #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(trn1))] -pub unsafe fn vtrn1q_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { - simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]) +#[target_feature(enable = "rdm")] +#[cfg_attr(test, assert_instr(sqrdmlah, LANE = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqrdmlah_lane_s16(a: int16x4_t, b: int16x4_t, c: int16x4_t) -> int16x4_t { + static_assert_imm2!(LANE); + vqadd_s16(a, vqrdmulh_lane_s16::(b, c)) } -/// Transpose vectors +/// Signed saturating rounding doubling multiply accumulate returning high half #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(trn1))] -pub unsafe fn vtrn1q_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { - simd_shuffle4!(a, b, [0, 4, 2, 6]) +#[target_feature(enable = "rdm")] +#[cfg_attr(test, assert_instr(sqrdmlah, LANE = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqrdmlah_laneq_s16(a: int16x4_t, b: int16x4_t, c: int16x8_t) -> int16x4_t { + static_assert_imm3!(LANE); + vqadd_s16(a, vqrdmulh_laneq_s16::(b, c)) } -/// Transpose vectors +/// Signed saturating rounding doubling multiply accumulate returning high half #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(trn1))] -pub unsafe fn vtrn1_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { - simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]) +#[target_feature(enable = "rdm")] +#[cfg_attr(test, assert_instr(sqrdmlah, LANE = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqrdmlahq_lane_s16(a: int16x8_t, b: int16x8_t, c: int16x4_t) -> int16x8_t { + static_assert_imm2!(LANE); + vqaddq_s16(a, vqrdmulhq_lane_s16::(b, c)) } -/// Transpose vectors -#[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(trn1))] -pub unsafe fn vtrn1q_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { - simd_shuffle16!(a, b, [0, 16, 2, 18, 4, 20, 6, 22, 8, 24, 10, 26, 12, 28, 14, 30]) -} - -/// Transpose vectors +/// Signed saturating rounding doubling multiply accumulate returning high half #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(trn1))] -pub unsafe fn vtrn1_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { - simd_shuffle4!(a, b, [0, 4, 2, 6]) +#[target_feature(enable = "rdm")] +#[cfg_attr(test, assert_instr(sqrdmlah, LANE = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqrdmlahq_laneq_s16(a: int16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8_t { + static_assert_imm3!(LANE); + vqaddq_s16(a, vqrdmulhq_laneq_s16::(b, c)) } -/// Transpose vectors +/// Signed saturating rounding doubling multiply accumulate returning high half #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(trn1))] -pub unsafe fn vtrn1q_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { - simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]) +#[target_feature(enable = "rdm")] +#[cfg_attr(test, assert_instr(sqrdmlah, LANE = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqrdmlah_lane_s32(a: int32x2_t, b: int32x2_t, c: int32x2_t) -> int32x2_t { + static_assert_imm1!(LANE); + vqadd_s32(a, vqrdmulh_lane_s32::(b, c)) } -/// Transpose vectors +/// Signed saturating rounding doubling multiply accumulate returning high half #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(trn1))] -pub unsafe fn vtrn1q_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { - simd_shuffle4!(a, b, [0, 4, 2, 6]) +#[target_feature(enable = "rdm")] +#[cfg_attr(test, assert_instr(sqrdmlah, LANE = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqrdmlah_laneq_s32(a: int32x2_t, b: int32x2_t, c: int32x4_t) -> int32x2_t { + static_assert_imm2!(LANE); + vqadd_s32(a, vqrdmulh_laneq_s32::(b, c)) } -/// Transpose vectors +/// Signed saturating rounding doubling multiply accumulate returning high half #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(trn1))] -pub unsafe fn vtrn1_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { - simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]) +#[target_feature(enable = "rdm")] +#[cfg_attr(test, assert_instr(sqrdmlah, LANE = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqrdmlahq_lane_s32(a: int32x4_t, b: int32x4_t, c: int32x2_t) -> int32x4_t { + static_assert_imm1!(LANE); + vqaddq_s32(a, vqrdmulhq_lane_s32::(b, c)) } -/// Transpose vectors +/// Signed saturating rounding doubling multiply accumulate returning high half #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(trn1))] -pub unsafe fn vtrn1q_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { - simd_shuffle16!(a, b, [0, 16, 2, 18, 4, 20, 6, 22, 8, 24, 10, 26, 12, 28, 14, 30]) +#[target_feature(enable = "rdm")] +#[cfg_attr(test, assert_instr(sqrdmlah, LANE = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqrdmlahq_laneq_s32(a: int32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4_t { + static_assert_imm2!(LANE); + vqaddq_s32(a, vqrdmulhq_laneq_s32::(b, c)) } -/// Transpose vectors +/// Signed saturating rounding doubling multiply accumulate returning high half #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(trn1))] -pub unsafe fn vtrn1_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t { - simd_shuffle4!(a, b, [0, 4, 2, 6]) +#[target_feature(enable = "rdm")] +#[cfg_attr(test, assert_instr(sqrdmlah, LANE = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqrdmlahh_lane_s16(a: i16, b: i16, c: int16x4_t) -> i16 { + static_assert_imm2!(LANE); + vqrdmlahh_s16(a, b, simd_extract(c, LANE as u32)) } -/// Transpose vectors +/// Signed saturating rounding doubling multiply accumulate returning high half #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(trn1))] -pub unsafe fn vtrn1q_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { - simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]) +#[target_feature(enable = "rdm")] +#[cfg_attr(test, assert_instr(sqrdmlah, LANE = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqrdmlahh_laneq_s16(a: i16, b: i16, c: int16x8_t) -> i16 { + static_assert_imm3!(LANE); + vqrdmlahh_s16(a, b, simd_extract(c, LANE as u32)) } -/// Transpose vectors +/// Signed saturating rounding doubling multiply accumulate returning high half #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vtrn1_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { - simd_shuffle2!(a, b, [0, 2]) +#[target_feature(enable = "rdm")] +#[cfg_attr(test, assert_instr(sqrdmlah, LANE = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqrdmlahs_lane_s32(a: i32, b: i32, c: int32x2_t) -> i32 { + static_assert_imm1!(LANE); + vqrdmlahs_s32(a, b, simd_extract(c, LANE as u32)) } -/// Transpose vectors +/// Signed saturating rounding doubling multiply accumulate returning high half #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vtrn1q_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { - simd_shuffle2!(a, b, [0, 2]) +#[target_feature(enable = "rdm")] +#[cfg_attr(test, assert_instr(sqrdmlah, LANE = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqrdmlahs_laneq_s32(a: i32, b: i32, c: int32x4_t) -> i32 { + static_assert_imm2!(LANE); + vqrdmlahs_s32(a, b, simd_extract(c, LANE as u32)) } -/// Transpose vectors +/// Signed saturating rounding doubling multiply subtract returning high half #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vtrn1_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { - simd_shuffle2!(a, b, [0, 2]) +#[cfg_attr(test, assert_instr(sqrdmulh))] +pub unsafe fn vqrdmlshh_s16(a: i16, b: i16, c: i16) -> i16 { + vqsubh_s16(a, vqrdmulhh_s16(b, c)) } -/// Transpose vectors +/// Signed saturating rounding doubling multiply subtract returning high half #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vtrn1q_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { - simd_shuffle2!(a, b, [0, 2]) +#[cfg_attr(test, assert_instr(sqrdmulh))] +pub unsafe fn vqrdmlshs_s32(a: i32, b: i32, c: i32) -> i32 { + vqsubs_s32(a, vqrdmulhs_s32(b, c)) } -/// Transpose vectors +/// Signed saturating rounding doubling multiply subtract returning high half #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vtrn1q_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { - simd_shuffle2!(a, b, [0, 2]) +#[cfg_attr(test, assert_instr(sqrdmulh, LANE = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqrdmlshh_lane_s16(a: i16, b: i16, c: int16x4_t) -> i16 { + static_assert_imm2!(LANE); + vqsubh_s16(a, vqrdmulhh_lane_s16::(b, c)) } -/// Transpose vectors +/// Signed saturating rounding doubling multiply subtract returning high half #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(trn1))] -pub unsafe fn vtrn1q_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { - simd_shuffle4!(a, b, [0, 4, 2, 6]) +#[cfg_attr(test, assert_instr(sqrdmulh, LANE = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqrdmlshh_laneq_s16(a: i16, b: i16, c: int16x8_t) -> i16 { + static_assert_imm3!(LANE); + vqsubh_s16(a, vqrdmulhh_laneq_s16::(b, c)) } -/// Transpose vectors +/// Signed saturating rounding doubling multiply subtract returning high half #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vtrn1_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { - simd_shuffle2!(a, b, [0, 2]) +#[cfg_attr(test, assert_instr(sqrdmulh, LANE = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqrdmlshs_lane_s32(a: i32, b: i32, c: int32x2_t) -> i32 { + static_assert_imm1!(LANE); + vqsubs_s32(a, vqrdmulhs_lane_s32::(b, c)) } -/// Transpose vectors +/// Signed saturating rounding doubling multiply subtract returning high half #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vtrn1q_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { - simd_shuffle2!(a, b, [0, 2]) +#[cfg_attr(test, assert_instr(sqrdmulh, LANE = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqrdmlshs_laneq_s32(a: i32, b: i32, c: int32x4_t) -> i32 { + static_assert_imm2!(LANE); + vqsubs_s32(a, vqrdmulhs_laneq_s32::(b, c)) } -/// Transpose vectors +/// Signed saturating rounding shift left #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(trn2))] -pub unsafe fn vtrn2_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { - simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]) +#[cfg_attr(test, assert_instr(sqrshl))] +pub unsafe fn vqrshls_s32(a: i32, b: i32) -> i32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshl.i32")] + fn vqrshls_s32_(a: i32, b: i32) -> i32; + } + vqrshls_s32_(a, b) } -/// Transpose vectors +/// Signed saturating rounding shift left #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(trn2))] -pub unsafe fn vtrn2q_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { - simd_shuffle16!(a, b, [1, 17, 3, 19, 5, 21, 7, 23, 9, 25, 11, 27, 13, 29, 15, 31]) +#[cfg_attr(test, assert_instr(sqrshl))] +pub unsafe fn vqrshld_s64(a: i64, b: i64) -> i64 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshl.i64")] + fn vqrshld_s64_(a: i64, b: i64) -> i64; + } + vqrshld_s64_(a, b) } -/// Transpose vectors +/// Signed saturating rounding shift left #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(trn2))] -pub unsafe fn vtrn2_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { - simd_shuffle4!(a, b, [1, 5, 3, 7]) +#[cfg_attr(test, assert_instr(sqrshl))] +pub unsafe fn vqrshlb_s8(a: i8, b: i8) -> i8 { + let a: int8x8_t = vdup_n_s8(a); + let b: int8x8_t = vdup_n_s8(b); + simd_extract(vqrshl_s8(a, b), 0) } -/// Transpose vectors +/// Signed saturating rounding shift left #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(trn2))] -pub unsafe fn vtrn2q_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { - simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]) +#[cfg_attr(test, assert_instr(sqrshl))] +pub unsafe fn vqrshlh_s16(a: i16, b: i16) -> i16 { + let a: int16x4_t = vdup_n_s16(a); + let b: int16x4_t = vdup_n_s16(b); + simd_extract(vqrshl_s16(a, b), 0) } -/// Transpose vectors +/// Unsigned signed saturating rounding shift left #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(trn2))] -pub unsafe fn vtrn2q_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { - simd_shuffle4!(a, b, [1, 5, 3, 7]) +#[cfg_attr(test, assert_instr(uqrshl))] +pub unsafe fn vqrshls_u32(a: u32, b: i32) -> u32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqrshl.i32")] + fn vqrshls_u32_(a: u32, b: i32) -> u32; + } + vqrshls_u32_(a, b) } -/// Transpose vectors +/// Unsigned signed saturating rounding shift left #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(trn2))] -pub unsafe fn vtrn2_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { - simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]) +#[cfg_attr(test, assert_instr(uqrshl))] +pub unsafe fn vqrshld_u64(a: u64, b: i64) -> u64 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqrshl.i64")] + fn vqrshld_u64_(a: u64, b: i64) -> u64; + } + vqrshld_u64_(a, b) } -/// Transpose vectors +/// Unsigned signed saturating rounding shift left #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(trn2))] -pub unsafe fn vtrn2q_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { - simd_shuffle16!(a, b, [1, 17, 3, 19, 5, 21, 7, 23, 9, 25, 11, 27, 13, 29, 15, 31]) +#[cfg_attr(test, assert_instr(uqrshl))] +pub unsafe fn vqrshlb_u8(a: u8, b: i8) -> u8 { + let a: uint8x8_t = vdup_n_u8(a); + let b: int8x8_t = vdup_n_s8(b); + simd_extract(vqrshl_u8(a, b), 0) } -/// Transpose vectors +/// Unsigned signed saturating rounding shift left #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(trn2))] -pub unsafe fn vtrn2_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { - simd_shuffle4!(a, b, [1, 5, 3, 7]) +#[cfg_attr(test, assert_instr(uqrshl))] +pub unsafe fn vqrshlh_u16(a: u16, b: i16) -> u16 { + let a: uint16x4_t = vdup_n_u16(a); + let b: int16x4_t = vdup_n_s16(b); + simd_extract(vqrshl_u16(a, b), 0) } -/// Transpose vectors +/// Signed saturating rounded shift right narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(trn2))] -pub unsafe fn vtrn2q_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { - simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]) +#[cfg_attr(test, assert_instr(sqrshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqrshrnh_n_s16(a: i16) -> i8 { + static_assert!(N : i32 where N >= 1 && N <= 8); + let a: int16x8_t = vdupq_n_s16(a); + simd_extract(vqrshrn_n_s16::(a), 0) } -/// Transpose vectors +/// Signed saturating rounded shift right narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(trn2))] -pub unsafe fn vtrn2q_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { - simd_shuffle4!(a, b, [1, 5, 3, 7]) +#[cfg_attr(test, assert_instr(sqrshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqrshrns_n_s32(a: i32) -> i16 { + static_assert!(N : i32 where N >= 1 && N <= 16); + let a: int32x4_t = vdupq_n_s32(a); + simd_extract(vqrshrn_n_s32::(a), 0) } -/// Transpose vectors +/// Signed saturating rounded shift right narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(trn2))] -pub unsafe fn vtrn2_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { - simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]) +#[cfg_attr(test, assert_instr(sqrshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqrshrnd_n_s64(a: i64) -> i32 { + static_assert!(N : i32 where N >= 1 && N <= 32); + let a: int64x2_t = vdupq_n_s64(a); + simd_extract(vqrshrn_n_s64::(a), 0) } -/// Transpose vectors +/// Signed saturating rounded shift right narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(trn2))] -pub unsafe fn vtrn2q_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { - simd_shuffle16!(a, b, [1, 17, 3, 19, 5, 21, 7, 23, 9, 25, 11, 27, 13, 29, 15, 31]) +#[cfg_attr(test, assert_instr(sqrshrn2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqrshrn_high_n_s16(a: int8x8_t, b: int16x8_t) -> int8x16_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + simd_shuffle16!(a, vqrshrn_n_s16::(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) } -/// Transpose vectors +/// Signed saturating rounded shift right narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(trn2))] -pub unsafe fn vtrn2_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t { - simd_shuffle4!(a, b, [1, 5, 3, 7]) +#[cfg_attr(test, assert_instr(sqrshrn2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqrshrn_high_n_s32(a: int16x4_t, b: int32x4_t) -> int16x8_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + simd_shuffle8!(a, vqrshrn_n_s32::(b), [0, 1, 2, 3, 4, 5, 6, 7]) } -/// Transpose vectors +/// Signed saturating rounded shift right narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(trn2))] -pub unsafe fn vtrn2q_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { - simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]) +#[cfg_attr(test, assert_instr(sqrshrn2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqrshrn_high_n_s64(a: int32x2_t, b: int64x2_t) -> int32x4_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + simd_shuffle4!(a, vqrshrn_n_s64::(b), [0, 1, 2, 3]) } -/// Transpose vectors +/// Unsigned saturating rounded shift right narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vtrn2_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { - simd_shuffle2!(a, b, [1, 3]) +#[cfg_attr(test, assert_instr(uqrshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqrshrnh_n_u16(a: u16) -> u8 { + static_assert!(N : i32 where N >= 1 && N <= 8); + let a: uint16x8_t = vdupq_n_u16(a); + simd_extract(vqrshrn_n_u16::(a), 0) } -/// Transpose vectors +/// Unsigned saturating rounded shift right narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vtrn2q_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { - simd_shuffle2!(a, b, [1, 3]) +#[cfg_attr(test, assert_instr(uqrshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqrshrns_n_u32(a: u32) -> u16 { + static_assert!(N : i32 where N >= 1 && N <= 16); + let a: uint32x4_t = vdupq_n_u32(a); + simd_extract(vqrshrn_n_u32::(a), 0) } -/// Transpose vectors +/// Unsigned saturating rounded shift right narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vtrn2_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { - simd_shuffle2!(a, b, [1, 3]) +#[cfg_attr(test, assert_instr(uqrshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqrshrnd_n_u64(a: u64) -> u32 { + static_assert!(N : i32 where N >= 1 && N <= 32); + let a: uint64x2_t = vdupq_n_u64(a); + simd_extract(vqrshrn_n_u64::(a), 0) } -/// Transpose vectors +/// Unsigned saturating rounded shift right narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vtrn2q_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { - simd_shuffle2!(a, b, [1, 3]) +#[cfg_attr(test, assert_instr(uqrshrn2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqrshrn_high_n_u16(a: uint8x8_t, b: uint16x8_t) -> uint8x16_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + simd_shuffle16!(a, vqrshrn_n_u16::(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) } -/// Transpose vectors +/// Unsigned saturating rounded shift right narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vtrn2q_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { - simd_shuffle2!(a, b, [1, 3]) +#[cfg_attr(test, assert_instr(uqrshrn2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqrshrn_high_n_u32(a: uint16x4_t, b: uint32x4_t) -> uint16x8_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + simd_shuffle8!(a, vqrshrn_n_u32::(b), [0, 1, 2, 3, 4, 5, 6, 7]) } -/// Transpose vectors +/// Unsigned saturating rounded shift right narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(trn2))] -pub unsafe fn vtrn2q_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { - simd_shuffle4!(a, b, [1, 5, 3, 7]) +#[cfg_attr(test, assert_instr(uqrshrn2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqrshrn_high_n_u64(a: uint32x2_t, b: uint64x2_t) -> uint32x4_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + simd_shuffle4!(a, vqrshrn_n_u64::(b), [0, 1, 2, 3]) } -/// Transpose vectors +/// Signed saturating rounded shift right unsigned narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vtrn2_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { - simd_shuffle2!(a, b, [1, 3]) +#[cfg_attr(test, assert_instr(sqrshrun, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqrshrunh_n_s16(a: i16) -> u8 { + static_assert!(N : i32 where N >= 1 && N <= 8); + let a: int16x8_t = vdupq_n_s16(a); + simd_extract(vqrshrun_n_s16::(a), 0) } -/// Transpose vectors +/// Signed saturating rounded shift right unsigned narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vtrn2q_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { - simd_shuffle2!(a, b, [1, 3]) +#[cfg_attr(test, assert_instr(sqrshrun, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqrshruns_n_s32(a: i32) -> u16 { + static_assert!(N : i32 where N >= 1 && N <= 16); + let a: int32x4_t = vdupq_n_s32(a); + simd_extract(vqrshrun_n_s32::(a), 0) } -/// Zip vectors +/// Signed saturating rounded shift right unsigned narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vzip1_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { - simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]) +#[cfg_attr(test, assert_instr(sqrshrun, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqrshrund_n_s64(a: i64) -> u32 { + static_assert!(N : i32 where N >= 1 && N <= 32); + let a: int64x2_t = vdupq_n_s64(a); + simd_extract(vqrshrun_n_s64::(a), 0) } -/// Zip vectors +/// Signed saturating rounded shift right unsigned narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vzip1q_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { - simd_shuffle16!(a, b, [0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23]) +#[cfg_attr(test, assert_instr(sqrshrun2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqrshrun_high_n_s16(a: uint8x8_t, b: int16x8_t) -> uint8x16_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + simd_shuffle16!(a, vqrshrun_n_s16::(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) } -/// Zip vectors +/// Signed saturating rounded shift right unsigned narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vzip1_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { - simd_shuffle4!(a, b, [0, 4, 1, 5]) +#[cfg_attr(test, assert_instr(sqrshrun2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqrshrun_high_n_s32(a: uint16x4_t, b: int32x4_t) -> uint16x8_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + simd_shuffle8!(a, vqrshrun_n_s32::(b), [0, 1, 2, 3, 4, 5, 6, 7]) } -/// Zip vectors +/// Signed saturating rounded shift right unsigned narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vzip1q_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { - simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]) +#[cfg_attr(test, assert_instr(sqrshrun2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqrshrun_high_n_s64(a: uint32x2_t, b: int64x2_t) -> uint32x4_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + simd_shuffle4!(a, vqrshrun_n_s64::(b), [0, 1, 2, 3]) } -/// Zip vectors +/// Signed saturating shift left #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vzip1_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { - simd_shuffle2!(a, b, [0, 2]) +#[cfg_attr(test, assert_instr(sqshl))] +pub unsafe fn vqshld_s64(a: i64, b: i64) -> i64 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshl.i64")] + fn vqshld_s64_(a: i64, b: i64) -> i64; + } + vqshld_s64_(a, b) } -/// Zip vectors +/// Signed saturating shift left #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vzip1q_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { - simd_shuffle4!(a, b, [0, 4, 1, 5]) +#[cfg_attr(test, assert_instr(sqshl))] +pub unsafe fn vqshlb_s8(a: i8, b: i8) -> i8 { + let c: int8x8_t = vqshl_s8(vdup_n_s8(a), vdup_n_s8(b)); + simd_extract(c, 0) } -/// Zip vectors +/// Signed saturating shift left #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vzip1q_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { - simd_shuffle2!(a, b, [0, 2]) +#[cfg_attr(test, assert_instr(sqshl))] +pub unsafe fn vqshlh_s16(a: i16, b: i16) -> i16 { + let c: int16x4_t = vqshl_s16(vdup_n_s16(a), vdup_n_s16(b)); + simd_extract(c, 0) } -/// Zip vectors +/// Signed saturating shift left #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vzip1_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { - simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]) +#[cfg_attr(test, assert_instr(sqshl))] +pub unsafe fn vqshls_s32(a: i32, b: i32) -> i32 { + let c: int32x2_t = vqshl_s32(vdup_n_s32(a), vdup_n_s32(b)); + simd_extract(c, 0) } -/// Zip vectors +/// Unsigned saturating shift left #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vzip1q_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { - simd_shuffle16!(a, b, [0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23]) +#[cfg_attr(test, assert_instr(uqshl))] +pub unsafe fn vqshld_u64(a: u64, b: i64) -> u64 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqshl.i64")] + fn vqshld_u64_(a: u64, b: i64) -> u64; + } + vqshld_u64_(a, b) } -/// Zip vectors +/// Unsigned saturating shift left #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vzip1_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { - simd_shuffle4!(a, b, [0, 4, 1, 5]) +#[cfg_attr(test, assert_instr(uqshl))] +pub unsafe fn vqshlb_u8(a: u8, b: i8) -> u8 { + let c: uint8x8_t = vqshl_u8(vdup_n_u8(a), vdup_n_s8(b)); + simd_extract(c, 0) } -/// Zip vectors +/// Unsigned saturating shift left #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vzip1q_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { - simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]) +#[cfg_attr(test, assert_instr(uqshl))] +pub unsafe fn vqshlh_u16(a: u16, b: i16) -> u16 { + let c: uint16x4_t = vqshl_u16(vdup_n_u16(a), vdup_n_s16(b)); + simd_extract(c, 0) } -/// Zip vectors +/// Unsigned saturating shift left #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vzip1_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { - simd_shuffle2!(a, b, [0, 2]) +#[cfg_attr(test, assert_instr(uqshl))] +pub unsafe fn vqshls_u32(a: u32, b: i32) -> u32 { + let c: uint32x2_t = vqshl_u32(vdup_n_u32(a), vdup_n_s32(b)); + simd_extract(c, 0) } -/// Zip vectors +/// Signed saturating shift left #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vzip1q_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { - simd_shuffle4!(a, b, [0, 4, 1, 5]) +#[cfg_attr(test, assert_instr(sqshl, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshlb_n_s8(a: i8) -> i8 { + static_assert_imm3!(N); + simd_extract(vqshl_n_s8::(vdup_n_s8(a)), 0) } -/// Zip vectors +/// Signed saturating shift left #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vzip1q_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { - simd_shuffle2!(a, b, [0, 2]) +#[cfg_attr(test, assert_instr(sqshl, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshlh_n_s16(a: i16) -> i16 { + static_assert_imm4!(N); + simd_extract(vqshl_n_s16::(vdup_n_s16(a)), 0) } -/// Zip vectors +/// Signed saturating shift left #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vzip1_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { - simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]) +#[cfg_attr(test, assert_instr(sqshl, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshls_n_s32(a: i32) -> i32 { + static_assert_imm5!(N); + simd_extract(vqshl_n_s32::(vdup_n_s32(a)), 0) } -/// Zip vectors +/// Signed saturating shift left #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vzip1q_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { - simd_shuffle16!(a, b, [0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23]) +#[cfg_attr(test, assert_instr(sqshl, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshld_n_s64(a: i64) -> i64 { + static_assert_imm6!(N); + simd_extract(vqshl_n_s64::(vdup_n_s64(a)), 0) } -/// Zip vectors +/// Unsigned saturating shift left #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vzip1_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t { - simd_shuffle4!(a, b, [0, 4, 1, 5]) +#[cfg_attr(test, assert_instr(uqshl, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshlb_n_u8(a: u8) -> u8 { + static_assert_imm3!(N); + simd_extract(vqshl_n_u8::(vdup_n_u8(a)), 0) } -/// Zip vectors +/// Unsigned saturating shift left #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vzip1q_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { - simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]) +#[cfg_attr(test, assert_instr(uqshl, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshlh_n_u16(a: u16) -> u16 { + static_assert_imm4!(N); + simd_extract(vqshl_n_u16::(vdup_n_u16(a)), 0) } -/// Zip vectors +/// Unsigned saturating shift left #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vzip1q_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { - simd_shuffle2!(a, b, [0, 2]) +#[cfg_attr(test, assert_instr(uqshl, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshls_n_u32(a: u32) -> u32 { + static_assert_imm5!(N); + simd_extract(vqshl_n_u32::(vdup_n_u32(a)), 0) } -/// Zip vectors +/// Unsigned saturating shift left #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vzip1_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { - simd_shuffle2!(a, b, [0, 2]) +#[cfg_attr(test, assert_instr(uqshl, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshld_n_u64(a: u64) -> u64 { + static_assert_imm6!(N); + simd_extract(vqshl_n_u64::(vdup_n_u64(a)), 0) } -/// Zip vectors +/// Signed saturating shift left unsigned #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vzip1q_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { - simd_shuffle4!(a, b, [0, 4, 1, 5]) +#[cfg_attr(test, assert_instr(sqshlu, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshlub_n_s8(a: i8) -> u8 { + static_assert_imm3!(N); + simd_extract(vqshlu_n_s8::(vdup_n_s8(a)), 0) } -/// Zip vectors +/// Signed saturating shift left unsigned #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vzip1q_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { - simd_shuffle2!(a, b, [0, 2]) +#[cfg_attr(test, assert_instr(sqshlu, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshluh_n_s16(a: i16) -> u16 { + static_assert_imm4!(N); + simd_extract(vqshlu_n_s16::(vdup_n_s16(a)), 0) } -/// Zip vectors +/// Signed saturating shift left unsigned #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vzip2_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { - simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]) +#[cfg_attr(test, assert_instr(sqshlu, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshlus_n_s32(a: i32) -> u32 { + static_assert_imm5!(N); + simd_extract(vqshlu_n_s32::(vdup_n_s32(a)), 0) } -/// Zip vectors +/// Signed saturating shift left unsigned #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vzip2q_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { - simd_shuffle16!(a, b, [8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31]) +#[cfg_attr(test, assert_instr(sqshlu, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshlud_n_s64(a: i64) -> u64 { + static_assert_imm6!(N); + simd_extract(vqshlu_n_s64::(vdup_n_s64(a)), 0) } -/// Zip vectors +/// Signed saturating shift right narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vzip2_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { - simd_shuffle4!(a, b, [2, 6, 3, 7]) +#[cfg_attr(test, assert_instr(sqshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshrnd_n_s64(a: i64) -> i32 { + static_assert!(N : i32 where N >= 1 && N <= 32); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshrn.i32")] + fn vqshrnd_n_s64_(a: i64, n: i32) -> i32; + } + vqshrnd_n_s64_(a, N) } -/// Zip vectors +/// Signed saturating shift right narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vzip2q_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { - simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]) +#[cfg_attr(test, assert_instr(sqshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshrnh_n_s16(a: i16) -> i8 { + static_assert!(N : i32 where N >= 1 && N <= 8); + simd_extract(vqshrn_n_s16::(vdupq_n_s16(a)), 0) } -/// Zip vectors +/// Signed saturating shift right narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vzip2_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { - simd_shuffle2!(a, b, [1, 3]) +#[cfg_attr(test, assert_instr(sqshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshrns_n_s32(a: i32) -> i16 { + static_assert!(N : i32 where N >= 1 && N <= 16); + simd_extract(vqshrn_n_s32::(vdupq_n_s32(a)), 0) } -/// Zip vectors +/// Signed saturating shift right narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vzip2q_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { - simd_shuffle4!(a, b, [2, 6, 3, 7]) +#[cfg_attr(test, assert_instr(sqshrn2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqshrn_high_n_s16(a: int8x8_t, b: int16x8_t) -> int8x16_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + simd_shuffle16!(a, vqshrn_n_s16::(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) } -/// Zip vectors +/// Signed saturating shift right narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vzip2q_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { - simd_shuffle2!(a, b, [1, 3]) +#[cfg_attr(test, assert_instr(sqshrn2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqshrn_high_n_s32(a: int16x4_t, b: int32x4_t) -> int16x8_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + simd_shuffle8!(a, vqshrn_n_s32::(b), [0, 1, 2, 3, 4, 5, 6, 7]) } -/// Zip vectors +/// Signed saturating shift right narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vzip2_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { - simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]) +#[cfg_attr(test, assert_instr(sqshrn2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqshrn_high_n_s64(a: int32x2_t, b: int64x2_t) -> int32x4_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + simd_shuffle4!(a, vqshrn_n_s64::(b), [0, 1, 2, 3]) } -/// Zip vectors +/// Unsigned saturating shift right narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vzip2q_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { - simd_shuffle16!(a, b, [8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31]) +#[cfg_attr(test, assert_instr(uqshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshrnd_n_u64(a: u64) -> u32 { + static_assert!(N : i32 where N >= 1 && N <= 32); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqshrn.i32")] + fn vqshrnd_n_u64_(a: u64, n: i32) -> u32; + } + vqshrnd_n_u64_(a, N) } -/// Zip vectors +/// Unsigned saturating shift right narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vzip2_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { - simd_shuffle4!(a, b, [2, 6, 3, 7]) +#[cfg_attr(test, assert_instr(uqshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshrnh_n_u16(a: u16) -> u8 { + static_assert!(N : i32 where N >= 1 && N <= 8); + simd_extract(vqshrn_n_u16::(vdupq_n_u16(a)), 0) } -/// Zip vectors +/// Unsigned saturating shift right narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vzip2q_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { - simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]) +#[cfg_attr(test, assert_instr(uqshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshrns_n_u32(a: u32) -> u16 { + static_assert!(N : i32 where N >= 1 && N <= 16); + simd_extract(vqshrn_n_u32::(vdupq_n_u32(a)), 0) } -/// Zip vectors +/// Unsigned saturating shift right narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vzip2_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { - simd_shuffle2!(a, b, [1, 3]) +#[cfg_attr(test, assert_instr(uqshrn2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqshrn_high_n_u16(a: uint8x8_t, b: uint16x8_t) -> uint8x16_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + simd_shuffle16!(a, vqshrn_n_u16::(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) } -/// Zip vectors +/// Unsigned saturating shift right narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vzip2q_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { - simd_shuffle4!(a, b, [2, 6, 3, 7]) +#[cfg_attr(test, assert_instr(uqshrn2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqshrn_high_n_u32(a: uint16x4_t, b: uint32x4_t) -> uint16x8_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + simd_shuffle8!(a, vqshrn_n_u32::(b), [0, 1, 2, 3, 4, 5, 6, 7]) } -/// Zip vectors +/// Unsigned saturating shift right narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vzip2q_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { - simd_shuffle2!(a, b, [1, 3]) +#[cfg_attr(test, assert_instr(uqshrn2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqshrn_high_n_u64(a: uint32x2_t, b: uint64x2_t) -> uint32x4_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + simd_shuffle4!(a, vqshrn_n_u64::(b), [0, 1, 2, 3]) } -/// Zip vectors +/// Signed saturating shift right unsigned narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vzip2_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { - simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]) +#[cfg_attr(test, assert_instr(sqshrun, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshrunh_n_s16(a: i16) -> u8 { + static_assert!(N : i32 where N >= 1 && N <= 8); + simd_extract(vqshrun_n_s16::(vdupq_n_s16(a)), 0) } -/// Zip vectors +/// Signed saturating shift right unsigned narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vzip2q_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { - simd_shuffle16!(a, b, [8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31]) +#[cfg_attr(test, assert_instr(sqshrun, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshruns_n_s32(a: i32) -> u16 { + static_assert!(N : i32 where N >= 1 && N <= 16); + simd_extract(vqshrun_n_s32::(vdupq_n_s32(a)), 0) } -/// Zip vectors +/// Signed saturating shift right unsigned narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vzip2_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t { - simd_shuffle4!(a, b, [2, 6, 3, 7]) +#[cfg_attr(test, assert_instr(sqshrun, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshrund_n_s64(a: i64) -> u32 { + static_assert!(N : i32 where N >= 1 && N <= 32); + simd_extract(vqshrun_n_s64::(vdupq_n_s64(a)), 0) } -/// Zip vectors +/// Signed saturating shift right unsigned narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vzip2q_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { - simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]) +#[cfg_attr(test, assert_instr(sqshrun2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqshrun_high_n_s16(a: uint8x8_t, b: int16x8_t) -> uint8x16_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + simd_shuffle16!(a, vqshrun_n_s16::(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) } -/// Zip vectors +/// Signed saturating shift right unsigned narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vzip2q_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { - simd_shuffle2!(a, b, [1, 3]) +#[cfg_attr(test, assert_instr(sqshrun2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqshrun_high_n_s32(a: uint16x4_t, b: int32x4_t) -> uint16x8_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + simd_shuffle8!(a, vqshrun_n_s32::(b), [0, 1, 2, 3, 4, 5, 6, 7]) } -/// Zip vectors +/// Signed saturating shift right unsigned narrow #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vzip2_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { - simd_shuffle2!(a, b, [1, 3]) +#[cfg_attr(test, assert_instr(sqshrun2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqshrun_high_n_s64(a: uint32x2_t, b: int64x2_t) -> uint32x4_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + simd_shuffle4!(a, vqshrun_n_s64::(b), [0, 1, 2, 3]) } -/// Zip vectors +/// Unsigned saturating accumulate of signed value #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vzip2q_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { - simd_shuffle4!(a, b, [2, 6, 3, 7]) +#[cfg_attr(test, assert_instr(usqadd))] +pub unsafe fn vsqaddb_u8(a: u8, b: i8) -> u8 { + simd_extract(vsqadd_u8(vdup_n_u8(a), vdup_n_s8(b)), 0) } -/// Zip vectors +/// Unsigned saturating accumulate of signed value #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vzip2q_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { - simd_shuffle2!(a, b, [1, 3]) +#[cfg_attr(test, assert_instr(usqadd))] +pub unsafe fn vsqaddh_u16(a: u16, b: i16) -> u16 { + simd_extract(vsqadd_u16(vdup_n_u16(a), vdup_n_s16(b)), 0) } -/// Unzip vectors +/// Unsigned saturating accumulate of signed value #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uzp1))] -pub unsafe fn vuzp1_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { - simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]) +#[cfg_attr(test, assert_instr(usqadd))] +pub unsafe fn vsqadds_u32(a: u32, b: i32) -> u32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.usqadd.i32")] + fn vsqadds_u32_(a: u32, b: i32) -> u32; + } + vsqadds_u32_(a, b) } -/// Unzip vectors +/// Unsigned saturating accumulate of signed value #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uzp1))] -pub unsafe fn vuzp1q_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { - simd_shuffle16!(a, b, [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30]) +#[cfg_attr(test, assert_instr(usqadd))] +pub unsafe fn vsqaddd_u64(a: u64, b: i64) -> u64 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.usqadd.i64")] + fn vsqaddd_u64_(a: u64, b: i64) -> u64; + } + vsqaddd_u64_(a, b) } -/// Unzip vectors +/// Calculates the square root of each lane. #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uzp1))] -pub unsafe fn vuzp1_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { - simd_shuffle4!(a, b, [0, 2, 4, 6]) +#[cfg_attr(test, assert_instr(fsqrt))] +pub unsafe fn vsqrt_f32(a: float32x2_t) -> float32x2_t { + simd_fsqrt(a) } -/// Unzip vectors +/// Calculates the square root of each lane. #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uzp1))] -pub unsafe fn vuzp1q_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { - simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]) +#[cfg_attr(test, assert_instr(fsqrt))] +pub unsafe fn vsqrtq_f32(a: float32x4_t) -> float32x4_t { + simd_fsqrt(a) } -/// Unzip vectors +/// Calculates the square root of each lane. #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uzp1))] -pub unsafe fn vuzp1q_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { - simd_shuffle4!(a, b, [0, 2, 4, 6]) +#[cfg_attr(test, assert_instr(fsqrt))] +pub unsafe fn vsqrt_f64(a: float64x1_t) -> float64x1_t { + simd_fsqrt(a) } -/// Unzip vectors +/// Calculates the square root of each lane. #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uzp1))] -pub unsafe fn vuzp1_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { - simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]) +#[cfg_attr(test, assert_instr(fsqrt))] +pub unsafe fn vsqrtq_f64(a: float64x2_t) -> float64x2_t { + simd_fsqrt(a) } -/// Unzip vectors +/// Reciprocal square-root estimate. #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uzp1))] -pub unsafe fn vuzp1q_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { - simd_shuffle16!(a, b, [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30]) +#[cfg_attr(test, assert_instr(frsqrte))] +pub unsafe fn vrsqrte_f64(a: float64x1_t) -> float64x1_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frsqrte.v1f64")] + fn vrsqrte_f64_(a: float64x1_t) -> float64x1_t; + } + vrsqrte_f64_(a) } -/// Unzip vectors +/// Reciprocal square-root estimate. #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uzp1))] -pub unsafe fn vuzp1_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { - simd_shuffle4!(a, b, [0, 2, 4, 6]) +#[cfg_attr(test, assert_instr(frsqrte))] +pub unsafe fn vrsqrteq_f64(a: float64x2_t) -> float64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frsqrte.v2f64")] + fn vrsqrteq_f64_(a: float64x2_t) -> float64x2_t; + } + vrsqrteq_f64_(a) } -/// Unzip vectors +/// Reciprocal square-root estimate. #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uzp1))] -pub unsafe fn vuzp1q_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { - simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]) +#[cfg_attr(test, assert_instr(frsqrte))] +pub unsafe fn vrsqrtes_f32(a: f32) -> f32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frsqrte.f32")] + fn vrsqrtes_f32_(a: f32) -> f32; + } + vrsqrtes_f32_(a) } -/// Unzip vectors +/// Reciprocal square-root estimate. #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uzp1))] -pub unsafe fn vuzp1q_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { - simd_shuffle4!(a, b, [0, 2, 4, 6]) +#[cfg_attr(test, assert_instr(frsqrte))] +pub unsafe fn vrsqrted_f64(a: f64) -> f64 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frsqrte.f64")] + fn vrsqrted_f64_(a: f64) -> f64; + } + vrsqrted_f64_(a) } -/// Unzip vectors +/// Floating-point reciprocal square root step #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uzp1))] -pub unsafe fn vuzp1_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { - simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]) +#[cfg_attr(test, assert_instr(frsqrts))] +pub unsafe fn vrsqrts_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frsqrts.v1f64")] + fn vrsqrts_f64_(a: float64x1_t, b: float64x1_t) -> float64x1_t; + } + vrsqrts_f64_(a, b) } -/// Unzip vectors +/// Floating-point reciprocal square root step #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uzp1))] -pub unsafe fn vuzp1q_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { - simd_shuffle16!(a, b, [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30]) +#[cfg_attr(test, assert_instr(frsqrts))] +pub unsafe fn vrsqrtsq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frsqrts.v2f64")] + fn vrsqrtsq_f64_(a: float64x2_t, b: float64x2_t) -> float64x2_t; + } + vrsqrtsq_f64_(a, b) } -/// Unzip vectors +/// Floating-point reciprocal square root step #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uzp1))] -pub unsafe fn vuzp1_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t { - simd_shuffle4!(a, b, [0, 2, 4, 6]) +#[cfg_attr(test, assert_instr(frsqrts))] +pub unsafe fn vrsqrtss_f32(a: f32, b: f32) -> f32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frsqrts.f32")] + fn vrsqrtss_f32_(a: f32, b: f32) -> f32; + } + vrsqrtss_f32_(a, b) } -/// Unzip vectors +/// Floating-point reciprocal square root step #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uzp1))] -pub unsafe fn vuzp1q_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { - simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]) +#[cfg_attr(test, assert_instr(frsqrts))] +pub unsafe fn vrsqrtsd_f64(a: f64, b: f64) -> f64 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frsqrts.f64")] + fn vrsqrtsd_f64_(a: f64, b: f64) -> f64; + } + vrsqrtsd_f64_(a, b) } -/// Unzip vectors +/// Reciprocal estimate. #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vuzp1_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { - simd_shuffle2!(a, b, [0, 2]) +#[cfg_attr(test, assert_instr(frecpe))] +pub unsafe fn vrecpe_f64(a: float64x1_t) -> float64x1_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frecpe.v1f64")] + fn vrecpe_f64_(a: float64x1_t) -> float64x1_t; + } + vrecpe_f64_(a) } -/// Unzip vectors +/// Reciprocal estimate. #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vuzp1q_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { - simd_shuffle2!(a, b, [0, 2]) +#[cfg_attr(test, assert_instr(frecpe))] +pub unsafe fn vrecpeq_f64(a: float64x2_t) -> float64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frecpe.v2f64")] + fn vrecpeq_f64_(a: float64x2_t) -> float64x2_t; + } + vrecpeq_f64_(a) } -/// Unzip vectors +/// Reciprocal estimate. #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vuzp1_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { - simd_shuffle2!(a, b, [0, 2]) +#[cfg_attr(test, assert_instr(frecpe))] +pub unsafe fn vrecpes_f32(a: f32) -> f32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frecpe.f32")] + fn vrecpes_f32_(a: f32) -> f32; + } + vrecpes_f32_(a) } -/// Unzip vectors +/// Reciprocal estimate. #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vuzp1q_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { - simd_shuffle2!(a, b, [0, 2]) +#[cfg_attr(test, assert_instr(frecpe))] +pub unsafe fn vrecped_f64(a: f64) -> f64 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frecpe.f64")] + fn vrecped_f64_(a: f64) -> f64; + } + vrecped_f64_(a) } -/// Unzip vectors +/// Floating-point reciprocal step #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vuzp1q_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { - simd_shuffle2!(a, b, [0, 2]) +#[cfg_attr(test, assert_instr(frecps))] +pub unsafe fn vrecps_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frecps.v1f64")] + fn vrecps_f64_(a: float64x1_t, b: float64x1_t) -> float64x1_t; + } + vrecps_f64_(a, b) } -/// Unzip vectors +/// Floating-point reciprocal step #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uzp1))] -pub unsafe fn vuzp1q_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { - simd_shuffle4!(a, b, [0, 2, 4, 6]) +#[cfg_attr(test, assert_instr(frecps))] +pub unsafe fn vrecpsq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frecps.v2f64")] + fn vrecpsq_f64_(a: float64x2_t, b: float64x2_t) -> float64x2_t; + } + vrecpsq_f64_(a, b) } -/// Unzip vectors +/// Floating-point reciprocal step #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vuzp1_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { - simd_shuffle2!(a, b, [0, 2]) +#[cfg_attr(test, assert_instr(frecps))] +pub unsafe fn vrecpss_f32(a: f32, b: f32) -> f32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frecps.f32")] + fn vrecpss_f32_(a: f32, b: f32) -> f32; + } + vrecpss_f32_(a, b) } -/// Unzip vectors +/// Floating-point reciprocal step #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip1))] -pub unsafe fn vuzp1q_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { - simd_shuffle2!(a, b, [0, 2]) +#[cfg_attr(test, assert_instr(frecps))] +pub unsafe fn vrecpsd_f64(a: f64, b: f64) -> f64 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frecps.f64")] + fn vrecpsd_f64_(a: f64, b: f64) -> f64; + } + vrecpsd_f64_(a, b) } -/// Unzip vectors +/// Floating-point reciprocal exponent #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uzp2))] -pub unsafe fn vuzp2_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { - simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]) +#[cfg_attr(test, assert_instr(frecpx))] +pub unsafe fn vrecpxs_f32(a: f32) -> f32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frecpx.f32")] + fn vrecpxs_f32_(a: f32) -> f32; + } + vrecpxs_f32_(a) } -/// Unzip vectors +/// Floating-point reciprocal exponent #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uzp2))] -pub unsafe fn vuzp2q_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { - simd_shuffle16!(a, b, [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31]) +#[cfg_attr(test, assert_instr(frecpx))] +pub unsafe fn vrecpxd_f64(a: f64) -> f64 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frecpx.f64")] + fn vrecpxd_f64_(a: f64) -> f64; + } + vrecpxd_f64_(a) } -/// Unzip vectors +/// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uzp2))] -pub unsafe fn vuzp2_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { - simd_shuffle4!(a, b, [1, 3, 5, 7]) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpret_s64_p64(a: poly64x1_t) -> int64x1_t { + transmute(a) } -/// Unzip vectors +/// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uzp2))] -pub unsafe fn vuzp2q_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { - simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpret_u64_p64(a: poly64x1_t) -> uint64x1_t { + transmute(a) } -/// Unzip vectors +/// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uzp2))] -pub unsafe fn vuzp2q_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { - simd_shuffle4!(a, b, [1, 3, 5, 7]) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpret_p64_s64(a: int64x1_t) -> poly64x1_t { + transmute(a) } -/// Unzip vectors +/// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uzp2))] -pub unsafe fn vuzp2_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { - simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpret_p64_u64(a: uint64x1_t) -> poly64x1_t { + transmute(a) } -/// Unzip vectors +/// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uzp2))] -pub unsafe fn vuzp2q_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { - simd_shuffle16!(a, b, [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31]) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_s64_p64(a: poly64x2_t) -> int64x2_t { + transmute(a) } -/// Unzip vectors +/// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uzp2))] -pub unsafe fn vuzp2_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { - simd_shuffle4!(a, b, [1, 3, 5, 7]) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_u64_p64(a: poly64x2_t) -> uint64x2_t { + transmute(a) } -/// Unzip vectors +/// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uzp2))] -pub unsafe fn vuzp2q_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { - simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_p64_s64(a: int64x2_t) -> poly64x2_t { + transmute(a) } -/// Unzip vectors +/// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uzp2))] -pub unsafe fn vuzp2q_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { - simd_shuffle4!(a, b, [1, 3, 5, 7]) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_p64_u64(a: uint64x2_t) -> poly64x2_t { + transmute(a) } -/// Unzip vectors +/// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uzp2))] -pub unsafe fn vuzp2_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { - simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpret_s8_f64(a: float64x1_t) -> int8x8_t { + transmute(a) } -/// Unzip vectors +/// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uzp2))] -pub unsafe fn vuzp2q_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { - simd_shuffle16!(a, b, [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31]) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpret_s16_f64(a: float64x1_t) -> int16x4_t { + transmute(a) } -/// Unzip vectors +/// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uzp2))] -pub unsafe fn vuzp2_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t { - simd_shuffle4!(a, b, [1, 3, 5, 7]) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpret_s32_f64(a: float64x1_t) -> int32x2_t { + transmute(a) } -/// Unzip vectors +/// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uzp2))] -pub unsafe fn vuzp2q_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { - simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpret_s64_f64(a: float64x1_t) -> int64x1_t { + transmute(a) } -/// Unzip vectors +/// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vuzp2_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { - simd_shuffle2!(a, b, [1, 3]) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_s8_f64(a: float64x2_t) -> int8x16_t { + transmute(a) } -/// Unzip vectors +/// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vuzp2q_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { - simd_shuffle2!(a, b, [1, 3]) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_s16_f64(a: float64x2_t) -> int16x8_t { + transmute(a) } -/// Unzip vectors +/// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vuzp2_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { - simd_shuffle2!(a, b, [1, 3]) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_s32_f64(a: float64x2_t) -> int32x4_t { + transmute(a) } -/// Unzip vectors +/// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vuzp2q_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { - simd_shuffle2!(a, b, [1, 3]) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_s64_f64(a: float64x2_t) -> int64x2_t { + transmute(a) } -/// Unzip vectors +/// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vuzp2q_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { - simd_shuffle2!(a, b, [1, 3]) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpret_u8_f64(a: float64x1_t) -> uint8x8_t { + transmute(a) } -/// Unzip vectors +/// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uzp2))] -pub unsafe fn vuzp2q_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { - simd_shuffle4!(a, b, [1, 3, 5, 7]) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpret_u16_f64(a: float64x1_t) -> uint16x4_t { + transmute(a) } -/// Unzip vectors +/// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vuzp2_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { - simd_shuffle2!(a, b, [1, 3]) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpret_u32_f64(a: float64x1_t) -> uint32x2_t { + transmute(a) } -/// Unzip vectors +/// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(zip2))] -pub unsafe fn vuzp2q_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { - simd_shuffle2!(a, b, [1, 3]) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpret_u64_f64(a: float64x1_t) -> uint64x1_t { + transmute(a) } -/// Unsigned Absolute difference and Accumulate Long +/// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uabal))] -pub unsafe fn vabal_high_u8(a: uint16x8_t, b: uint8x16_t, c: uint8x16_t) -> uint16x8_t { - let d: uint8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); - let e: uint8x8_t = simd_shuffle8!(c, c, [8, 9, 10, 11, 12, 13, 14, 15]); - let f: uint8x8_t = vabd_u8(d, e); - simd_add(a, simd_cast(f)) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_u8_f64(a: float64x2_t) -> uint8x16_t { + transmute(a) } -/// Unsigned Absolute difference and Accumulate Long +/// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uabal))] -pub unsafe fn vabal_high_u16(a: uint32x4_t, b: uint16x8_t, c: uint16x8_t) -> uint32x4_t { - let d: uint16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); - let e: uint16x4_t = simd_shuffle4!(c, c, [4, 5, 6, 7]); - let f: uint16x4_t = vabd_u16(d, e); - simd_add(a, simd_cast(f)) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_u16_f64(a: float64x2_t) -> uint16x8_t { + transmute(a) } -/// Unsigned Absolute difference and Accumulate Long +/// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(uabal))] -pub unsafe fn vabal_high_u32(a: uint64x2_t, b: uint32x4_t, c: uint32x4_t) -> uint64x2_t { - let d: uint32x2_t = simd_shuffle2!(b, b, [2, 3]); - let e: uint32x2_t = simd_shuffle2!(c, c, [2, 3]); - let f: uint32x2_t = vabd_u32(d, e); - simd_add(a, simd_cast(f)) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_u32_f64(a: float64x2_t) -> uint32x4_t { + transmute(a) } -/// Signed Absolute difference and Accumulate Long +/// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sabal))] -pub unsafe fn vabal_high_s8(a: int16x8_t, b: int8x16_t, c: int8x16_t) -> int16x8_t { - let d: int8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); - let e: int8x8_t = simd_shuffle8!(c, c, [8, 9, 10, 11, 12, 13, 14, 15]); - let f: int8x8_t = vabd_s8(d, e); - let f: uint8x8_t = simd_cast(f); - simd_add(a, simd_cast(f)) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_u64_f64(a: float64x2_t) -> uint64x2_t { + transmute(a) } -/// Signed Absolute difference and Accumulate Long +/// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sabal))] -pub unsafe fn vabal_high_s16(a: int32x4_t, b: int16x8_t, c: int16x8_t) -> int32x4_t { - let d: int16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); - let e: int16x4_t = simd_shuffle4!(c, c, [4, 5, 6, 7]); - let f: int16x4_t = vabd_s16(d, e); - let f: uint16x4_t = simd_cast(f); - simd_add(a, simd_cast(f)) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpret_p8_f64(a: float64x1_t) -> poly8x8_t { + transmute(a) } -/// Signed Absolute difference and Accumulate Long +/// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sabal))] -pub unsafe fn vabal_high_s32(a: int64x2_t, b: int32x4_t, c: int32x4_t) -> int64x2_t { - let d: int32x2_t = simd_shuffle2!(b, b, [2, 3]); - let e: int32x2_t = simd_shuffle2!(c, c, [2, 3]); - let f: int32x2_t = vabd_s32(d, e); - let f: uint32x2_t = simd_cast(f); - simd_add(a, simd_cast(f)) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpret_p16_f64(a: float64x1_t) -> poly16x4_t { + transmute(a) } -/// Singned saturating Absolute value +/// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqabs))] -pub unsafe fn vqabs_s64(a: int64x1_t) -> int64x1_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqabs.v1i64")] - fn vqabs_s64_(a: int64x1_t) -> int64x1_t; - } - vqabs_s64_(a) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpret_p64_f32(a: float32x2_t) -> poly64x1_t { + transmute(a) } -/// Singned saturating Absolute value +/// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(sqabs))] -pub unsafe fn vqabsq_s64(a: int64x2_t) -> int64x2_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqabs.v2i64")] - fn vqabsq_s64_(a: int64x2_t) -> int64x2_t; - } - vqabsq_s64_(a) +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpret_p64_f64(a: float64x1_t) -> poly64x1_t { + transmute(a) } -#[cfg(test)] -mod test { - use super::*; - use crate::core_arch::simd::*; - use std::mem::transmute; - use stdarch_test::simd_test; +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_p8_f64(a: float64x2_t) -> poly8x16_t { + transmute(a) +} - #[simd_test(enable = "neon")] - unsafe fn test_vabd_f64() { - let a: f64 = 1.0; - let b: f64 = 9.0; - let e: f64 = 8.0; +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_p16_f64(a: float64x2_t) -> poly16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_p64_f32(a: float32x4_t) -> poly64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_p64_f64(a: float64x2_t) -> poly64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_p128_f64(a: float64x2_t) -> p128 { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpret_f64_s8(a: int8x8_t) -> float64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpret_f64_s16(a: int16x4_t) -> float64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpret_f64_s32(a: int32x2_t) -> float64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpret_f64_s64(a: int64x1_t) -> float64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_f64_s8(a: int8x16_t) -> float64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_f64_s16(a: int16x8_t) -> float64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_f64_s32(a: int32x4_t) -> float64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_f64_s64(a: int64x2_t) -> float64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpret_f64_p8(a: poly8x8_t) -> float64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpret_f64_u16(a: uint16x4_t) -> float64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpret_f64_u32(a: uint32x2_t) -> float64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpret_f64_u64(a: uint64x1_t) -> float64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_f64_p8(a: poly8x16_t) -> float64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_f64_u16(a: uint16x8_t) -> float64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_f64_u32(a: uint32x4_t) -> float64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_f64_u64(a: uint64x2_t) -> float64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpret_f64_u8(a: uint8x8_t) -> float64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpret_f64_p16(a: poly16x4_t) -> float64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpret_f64_p64(a: poly64x1_t) -> float64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpret_f32_p64(a: poly64x1_t) -> float32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_f64_u8(a: uint8x16_t) -> float64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_f64_p16(a: poly16x8_t) -> float64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_f64_p64(a: poly64x2_t) -> float64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_f32_p64(a: poly64x2_t) -> float32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_f64_p128(a: p128) -> float64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpret_f64_f32(a: float32x2_t) -> float64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpret_f32_f64(a: float64x1_t) -> float32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_f64_f32(a: float32x4_t) -> float64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop))] +pub unsafe fn vreinterpretq_f32_f64(a: float64x2_t) -> float32x4_t { + transmute(a) +} + +/// Signed rounding shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(srshl))] +pub unsafe fn vrshld_s64(a: i64, b: i64) -> i64 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.srshl.i64")] + fn vrshld_s64_(a: i64, b: i64) -> i64; + } + vrshld_s64_(a, b) +} + +/// Unsigned rounding shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(urshl))] +pub unsafe fn vrshld_u64(a: u64, b: i64) -> u64 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.urshl.i64")] + fn vrshld_u64_(a: u64, b: i64) -> u64; + } + vrshld_u64_(a, b) +} + +/// Signed rounding shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(srshr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vrshrd_n_s64(a: i64) -> i64 { + static_assert!(N : i32 where N >= 1 && N <= 64); + vrshld_s64(a, -N as i64) +} + +/// Unsigned rounding shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(urshr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vrshrd_n_u64(a: u64) -> u64 { + static_assert!(N : i32 where N >= 1 && N <= 64); + vrshld_u64(a, -N as i64) +} + +/// Rounding shift right narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(rshrn2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vrshrn_high_n_s16(a: int8x8_t, b: int16x8_t) -> int8x16_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + simd_shuffle16!(a, vrshrn_n_s16::(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) +} + +/// Rounding shift right narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(rshrn2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vrshrn_high_n_s32(a: int16x4_t, b: int32x4_t) -> int16x8_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + simd_shuffle8!(a, vrshrn_n_s32::(b), [0, 1, 2, 3, 4, 5, 6, 7]) +} + +/// Rounding shift right narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(rshrn2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vrshrn_high_n_s64(a: int32x2_t, b: int64x2_t) -> int32x4_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + simd_shuffle4!(a, vrshrn_n_s64::(b), [0, 1, 2, 3]) +} + +/// Rounding shift right narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(rshrn2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vrshrn_high_n_u16(a: uint8x8_t, b: uint16x8_t) -> uint8x16_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + simd_shuffle16!(a, vrshrn_n_u16::(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) +} + +/// Rounding shift right narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(rshrn2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vrshrn_high_n_u32(a: uint16x4_t, b: uint32x4_t) -> uint16x8_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + simd_shuffle8!(a, vrshrn_n_u32::(b), [0, 1, 2, 3, 4, 5, 6, 7]) +} + +/// Rounding shift right narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(rshrn2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vrshrn_high_n_u64(a: uint32x2_t, b: uint64x2_t) -> uint32x4_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + simd_shuffle4!(a, vrshrn_n_u64::(b), [0, 1, 2, 3]) +} + +/// Signed rounding shift right and accumulate. +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(srsra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vrsrad_n_s64(a: i64, b: i64) -> i64 { + static_assert!(N : i32 where N >= 1 && N <= 64); + let b: i64 = vrshrd_n_s64::(b); + a + b +} + +/// Ungisned rounding shift right and accumulate. +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(ursra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vrsrad_n_u64(a: u64, b: u64) -> u64 { + static_assert!(N : i32 where N >= 1 && N <= 64); + let b: u64 = vrshrd_n_u64::(b); + a + b +} + +/// Rounding subtract returning high narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(rsubhn2))] +pub unsafe fn vrsubhn_high_s16(a: int8x8_t, b: int16x8_t, c: int16x8_t) -> int8x16_t { + let x: int8x8_t = vrsubhn_s16(b, c); + simd_shuffle16!(a, x, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) +} + +/// Rounding subtract returning high narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(rsubhn2))] +pub unsafe fn vrsubhn_high_s32(a: int16x4_t, b: int32x4_t, c: int32x4_t) -> int16x8_t { + let x: int16x4_t = vrsubhn_s32(b, c); + simd_shuffle8!(a, x, [0, 1, 2, 3, 4, 5, 6, 7]) +} + +/// Rounding subtract returning high narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(rsubhn2))] +pub unsafe fn vrsubhn_high_s64(a: int32x2_t, b: int64x2_t, c: int64x2_t) -> int32x4_t { + let x: int32x2_t = vrsubhn_s64(b, c); + simd_shuffle4!(a, x, [0, 1, 2, 3]) +} + +/// Rounding subtract returning high narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(rsubhn2))] +pub unsafe fn vrsubhn_high_u16(a: uint8x8_t, b: uint16x8_t, c: uint16x8_t) -> uint8x16_t { + let x: uint8x8_t = vrsubhn_u16(b, c); + simd_shuffle16!(a, x, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) +} + +/// Rounding subtract returning high narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(rsubhn2))] +pub unsafe fn vrsubhn_high_u32(a: uint16x4_t, b: uint32x4_t, c: uint32x4_t) -> uint16x8_t { + let x: uint16x4_t = vrsubhn_u32(b, c); + simd_shuffle8!(a, x, [0, 1, 2, 3, 4, 5, 6, 7]) +} + +/// Rounding subtract returning high narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(rsubhn2))] +pub unsafe fn vrsubhn_high_u64(a: uint32x2_t, b: uint64x2_t, c: uint64x2_t) -> uint32x4_t { + let x: uint32x2_t = vrsubhn_u64(b, c); + simd_shuffle4!(a, x, [0, 1, 2, 3]) +} + +/// Insert vector element from another vector element +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vset_lane_f64(a: f64, b: float64x1_t) -> float64x1_t { + static_assert!(LANE : i32 where LANE == 0); + simd_insert(b, LANE as u32, a) +} + +/// Insert vector element from another vector element +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsetq_lane_f64(a: f64, b: float64x2_t) -> float64x2_t { + static_assert_imm1!(LANE); + simd_insert(b, LANE as u32, a) +} + +/// Signed Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(sshl))] +pub unsafe fn vshld_s64(a: i64, b: i64) -> i64 { + transmute(vshl_s64(transmute(a), transmute(b))) +} + +/// Unsigned Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(ushl))] +pub unsafe fn vshld_u64(a: u64, b: i64) -> u64 { + transmute(vshl_u64(transmute(a), transmute(b))) +} + +/// Signed shift left long +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(sshll2, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshll_high_n_s8(a: int8x16_t) -> int16x8_t { + static_assert!(N : i32 where N >= 0 && N <= 8); + let b: int8x8_t = simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]); + vshll_n_s8::(b) +} + +/// Signed shift left long +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(sshll2, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshll_high_n_s16(a: int16x8_t) -> int32x4_t { + static_assert!(N : i32 where N >= 0 && N <= 16); + let b: int16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); + vshll_n_s16::(b) +} + +/// Signed shift left long +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(sshll2, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshll_high_n_s32(a: int32x4_t) -> int64x2_t { + static_assert!(N : i32 where N >= 0 && N <= 32); + let b: int32x2_t = simd_shuffle2!(a, a, [2, 3]); + vshll_n_s32::(b) +} + +/// Signed shift left long +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(ushll2, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshll_high_n_u8(a: uint8x16_t) -> uint16x8_t { + static_assert!(N : i32 where N >= 0 && N <= 8); + let b: uint8x8_t = simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]); + vshll_n_u8::(b) +} + +/// Signed shift left long +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(ushll2, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshll_high_n_u16(a: uint16x8_t) -> uint32x4_t { + static_assert!(N : i32 where N >= 0 && N <= 16); + let b: uint16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); + vshll_n_u16::(b) +} + +/// Signed shift left long +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(ushll2, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshll_high_n_u32(a: uint32x4_t) -> uint64x2_t { + static_assert!(N : i32 where N >= 0 && N <= 32); + let b: uint32x2_t = simd_shuffle2!(a, a, [2, 3]); + vshll_n_u32::(b) +} + +/// Shift right narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(shrn2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vshrn_high_n_s16(a: int8x8_t, b: int16x8_t) -> int8x16_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + simd_shuffle16!(a, vshrn_n_s16::(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) +} + +/// Shift right narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(shrn2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vshrn_high_n_s32(a: int16x4_t, b: int32x4_t) -> int16x8_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + simd_shuffle8!(a, vshrn_n_s32::(b), [0, 1, 2, 3, 4, 5, 6, 7]) +} + +/// Shift right narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(shrn2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vshrn_high_n_s64(a: int32x2_t, b: int64x2_t) -> int32x4_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + simd_shuffle4!(a, vshrn_n_s64::(b), [0, 1, 2, 3]) +} + +/// Shift right narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(shrn2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vshrn_high_n_u16(a: uint8x8_t, b: uint16x8_t) -> uint8x16_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + simd_shuffle16!(a, vshrn_n_u16::(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) +} + +/// Shift right narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(shrn2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vshrn_high_n_u32(a: uint16x4_t, b: uint32x4_t) -> uint16x8_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + simd_shuffle8!(a, vshrn_n_u32::(b), [0, 1, 2, 3, 4, 5, 6, 7]) +} + +/// Shift right narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(shrn2, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vshrn_high_n_u64(a: uint32x2_t, b: uint64x2_t) -> uint32x4_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + simd_shuffle4!(a, vshrn_n_u64::(b), [0, 1, 2, 3]) +} + +/// SM3PARTW1 +#[inline] +#[target_feature(enable = "neon,sm4")] +#[cfg_attr(test, assert_instr(sm3partw1))] +pub unsafe fn vsm3partw1q_u32(a: uint32x4_t, b: uint32x4_t, c: uint32x4_t) -> uint32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.sm3partw1")] + fn vsm3partw1q_u32_(a: uint32x4_t, b: uint32x4_t, c: uint32x4_t) -> uint32x4_t; + } + vsm3partw1q_u32_(a, b, c) +} + +/// SM3PARTW2 +#[inline] +#[target_feature(enable = "neon,sm4")] +#[cfg_attr(test, assert_instr(sm3partw2))] +pub unsafe fn vsm3partw2q_u32(a: uint32x4_t, b: uint32x4_t, c: uint32x4_t) -> uint32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.sm3partw2")] + fn vsm3partw2q_u32_(a: uint32x4_t, b: uint32x4_t, c: uint32x4_t) -> uint32x4_t; + } + vsm3partw2q_u32_(a, b, c) +} + +/// SM3SS1 +#[inline] +#[target_feature(enable = "neon,sm4")] +#[cfg_attr(test, assert_instr(sm3ss1))] +pub unsafe fn vsm3ss1q_u32(a: uint32x4_t, b: uint32x4_t, c: uint32x4_t) -> uint32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.sm3ss1")] + fn vsm3ss1q_u32_(a: uint32x4_t, b: uint32x4_t, c: uint32x4_t) -> uint32x4_t; + } + vsm3ss1q_u32_(a, b, c) +} + +/// SM4 key +#[inline] +#[target_feature(enable = "neon,sm4")] +#[cfg_attr(test, assert_instr(sm4ekey))] +pub unsafe fn vsm4ekeyq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.sm4ekey")] + fn vsm4ekeyq_u32_(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t; + } + vsm4ekeyq_u32_(a, b) +} + +/// SM4 encode +#[inline] +#[target_feature(enable = "neon,sm4")] +#[cfg_attr(test, assert_instr(sm4e))] +pub unsafe fn vsm4eq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.sm4e")] + fn vsm4eq_u32_(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t; + } + vsm4eq_u32_(a, b) +} + +/// Rotate and exclusive OR +#[inline] +#[target_feature(enable = "neon,sha3")] +#[cfg_attr(test, assert_instr(rax1))] +pub unsafe fn vrax1q_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.rax1")] + fn vrax1q_u64_(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t; + } + vrax1q_u64_(a, b) +} + +/// SHA512 hash update part 1 +#[inline] +#[target_feature(enable = "neon,sha3")] +#[cfg_attr(test, assert_instr(sha512h))] +pub unsafe fn vsha512hq_u64(a: uint64x2_t, b: uint64x2_t, c: uint64x2_t) -> uint64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.sha512h")] + fn vsha512hq_u64_(a: uint64x2_t, b: uint64x2_t, c: uint64x2_t) -> uint64x2_t; + } + vsha512hq_u64_(a, b, c) +} + +/// SHA512 hash update part 2 +#[inline] +#[target_feature(enable = "neon,sha3")] +#[cfg_attr(test, assert_instr(sha512h2))] +pub unsafe fn vsha512h2q_u64(a: uint64x2_t, b: uint64x2_t, c: uint64x2_t) -> uint64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.sha512h2")] + fn vsha512h2q_u64_(a: uint64x2_t, b: uint64x2_t, c: uint64x2_t) -> uint64x2_t; + } + vsha512h2q_u64_(a, b, c) +} + +/// SHA512 schedule update 0 +#[inline] +#[target_feature(enable = "neon,sha3")] +#[cfg_attr(test, assert_instr(sha512su0))] +pub unsafe fn vsha512su0q_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.sha512su0")] + fn vsha512su0q_u64_(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t; + } + vsha512su0q_u64_(a, b) +} + +/// SHA512 schedule update 1 +#[inline] +#[target_feature(enable = "neon,sha3")] +#[cfg_attr(test, assert_instr(sha512su1))] +pub unsafe fn vsha512su1q_u64(a: uint64x2_t, b: uint64x2_t, c: uint64x2_t) -> uint64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.sha512su1")] + fn vsha512su1q_u64_(a: uint64x2_t, b: uint64x2_t, c: uint64x2_t) -> uint64x2_t; + } + vsha512su1q_u64_(a, b, c) +} + +/// Floating-point round to 32-bit integer, using current rounding mode +#[inline] +#[target_feature(enable = "neon,frintts")] +#[cfg_attr(test, assert_instr(frint32x))] +pub unsafe fn vrnd32x_f32(a: float32x2_t) -> float32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frint32x.v2f32")] + fn vrnd32x_f32_(a: float32x2_t) -> float32x2_t; + } + vrnd32x_f32_(a) +} + +/// Floating-point round to 32-bit integer, using current rounding mode +#[inline] +#[target_feature(enable = "neon,frintts")] +#[cfg_attr(test, assert_instr(frint32x))] +pub unsafe fn vrnd32xq_f32(a: float32x4_t) -> float32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frint32x.v4f32")] + fn vrnd32xq_f32_(a: float32x4_t) -> float32x4_t; + } + vrnd32xq_f32_(a) +} + +/// Floating-point round to 32-bit integer toward zero +#[inline] +#[target_feature(enable = "neon,frintts")] +#[cfg_attr(test, assert_instr(frint32z))] +pub unsafe fn vrnd32z_f32(a: float32x2_t) -> float32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frint32z.v2f32")] + fn vrnd32z_f32_(a: float32x2_t) -> float32x2_t; + } + vrnd32z_f32_(a) +} + +/// Floating-point round to 32-bit integer toward zero +#[inline] +#[target_feature(enable = "neon,frintts")] +#[cfg_attr(test, assert_instr(frint32z))] +pub unsafe fn vrnd32zq_f32(a: float32x4_t) -> float32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frint32z.v4f32")] + fn vrnd32zq_f32_(a: float32x4_t) -> float32x4_t; + } + vrnd32zq_f32_(a) +} + +/// Floating-point round to 64-bit integer, using current rounding mode +#[inline] +#[target_feature(enable = "neon,frintts")] +#[cfg_attr(test, assert_instr(frint64x))] +pub unsafe fn vrnd64x_f32(a: float32x2_t) -> float32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frint64x.v2f32")] + fn vrnd64x_f32_(a: float32x2_t) -> float32x2_t; + } + vrnd64x_f32_(a) +} + +/// Floating-point round to 64-bit integer, using current rounding mode +#[inline] +#[target_feature(enable = "neon,frintts")] +#[cfg_attr(test, assert_instr(frint64x))] +pub unsafe fn vrnd64xq_f32(a: float32x4_t) -> float32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frint64x.v4f32")] + fn vrnd64xq_f32_(a: float32x4_t) -> float32x4_t; + } + vrnd64xq_f32_(a) +} + +/// Floating-point round to 64-bit integer toward zero +#[inline] +#[target_feature(enable = "neon,frintts")] +#[cfg_attr(test, assert_instr(frint64z))] +pub unsafe fn vrnd64z_f32(a: float32x2_t) -> float32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frint64z.v2f32")] + fn vrnd64z_f32_(a: float32x2_t) -> float32x2_t; + } + vrnd64z_f32_(a) +} + +/// Floating-point round to 64-bit integer toward zero +#[inline] +#[target_feature(enable = "neon,frintts")] +#[cfg_attr(test, assert_instr(frint64z))] +pub unsafe fn vrnd64zq_f32(a: float32x4_t) -> float32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frint64z.v4f32")] + fn vrnd64zq_f32_(a: float32x4_t) -> float32x4_t; + } + vrnd64zq_f32_(a) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(trn1))] +pub unsafe fn vtrn1_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { + simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(trn1))] +pub unsafe fn vtrn1q_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { + simd_shuffle16!(a, b, [0, 16, 2, 18, 4, 20, 6, 22, 8, 24, 10, 26, 12, 28, 14, 30]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(trn1))] +pub unsafe fn vtrn1_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { + simd_shuffle4!(a, b, [0, 4, 2, 6]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(trn1))] +pub unsafe fn vtrn1q_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { + simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(trn1))] +pub unsafe fn vtrn1q_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { + simd_shuffle4!(a, b, [0, 4, 2, 6]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(trn1))] +pub unsafe fn vtrn1_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { + simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(trn1))] +pub unsafe fn vtrn1q_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { + simd_shuffle16!(a, b, [0, 16, 2, 18, 4, 20, 6, 22, 8, 24, 10, 26, 12, 28, 14, 30]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(trn1))] +pub unsafe fn vtrn1_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { + simd_shuffle4!(a, b, [0, 4, 2, 6]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(trn1))] +pub unsafe fn vtrn1q_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { + simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(trn1))] +pub unsafe fn vtrn1q_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { + simd_shuffle4!(a, b, [0, 4, 2, 6]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(trn1))] +pub unsafe fn vtrn1_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { + simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(trn1))] +pub unsafe fn vtrn1q_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { + simd_shuffle16!(a, b, [0, 16, 2, 18, 4, 20, 6, 22, 8, 24, 10, 26, 12, 28, 14, 30]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(trn1))] +pub unsafe fn vtrn1_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t { + simd_shuffle4!(a, b, [0, 4, 2, 6]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(trn1))] +pub unsafe fn vtrn1q_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { + simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vtrn1_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { + simd_shuffle2!(a, b, [0, 2]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vtrn1q_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { + simd_shuffle2!(a, b, [0, 2]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vtrn1_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { + simd_shuffle2!(a, b, [0, 2]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vtrn1q_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { + simd_shuffle2!(a, b, [0, 2]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vtrn1q_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { + simd_shuffle2!(a, b, [0, 2]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(trn1))] +pub unsafe fn vtrn1q_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { + simd_shuffle4!(a, b, [0, 4, 2, 6]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vtrn1_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { + simd_shuffle2!(a, b, [0, 2]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vtrn1q_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { + simd_shuffle2!(a, b, [0, 2]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(trn2))] +pub unsafe fn vtrn2_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { + simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(trn2))] +pub unsafe fn vtrn2q_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { + simd_shuffle16!(a, b, [1, 17, 3, 19, 5, 21, 7, 23, 9, 25, 11, 27, 13, 29, 15, 31]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(trn2))] +pub unsafe fn vtrn2_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { + simd_shuffle4!(a, b, [1, 5, 3, 7]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(trn2))] +pub unsafe fn vtrn2q_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { + simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(trn2))] +pub unsafe fn vtrn2q_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { + simd_shuffle4!(a, b, [1, 5, 3, 7]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(trn2))] +pub unsafe fn vtrn2_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { + simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(trn2))] +pub unsafe fn vtrn2q_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { + simd_shuffle16!(a, b, [1, 17, 3, 19, 5, 21, 7, 23, 9, 25, 11, 27, 13, 29, 15, 31]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(trn2))] +pub unsafe fn vtrn2_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { + simd_shuffle4!(a, b, [1, 5, 3, 7]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(trn2))] +pub unsafe fn vtrn2q_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { + simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(trn2))] +pub unsafe fn vtrn2q_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { + simd_shuffle4!(a, b, [1, 5, 3, 7]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(trn2))] +pub unsafe fn vtrn2_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { + simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(trn2))] +pub unsafe fn vtrn2q_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { + simd_shuffle16!(a, b, [1, 17, 3, 19, 5, 21, 7, 23, 9, 25, 11, 27, 13, 29, 15, 31]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(trn2))] +pub unsafe fn vtrn2_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t { + simd_shuffle4!(a, b, [1, 5, 3, 7]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(trn2))] +pub unsafe fn vtrn2q_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { + simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vtrn2_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { + simd_shuffle2!(a, b, [1, 3]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vtrn2q_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { + simd_shuffle2!(a, b, [1, 3]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vtrn2_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { + simd_shuffle2!(a, b, [1, 3]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vtrn2q_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { + simd_shuffle2!(a, b, [1, 3]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vtrn2q_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { + simd_shuffle2!(a, b, [1, 3]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(trn2))] +pub unsafe fn vtrn2q_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { + simd_shuffle4!(a, b, [1, 5, 3, 7]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vtrn2_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { + simd_shuffle2!(a, b, [1, 3]) +} + +/// Transpose vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vtrn2q_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { + simd_shuffle2!(a, b, [1, 3]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vzip1_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { + simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vzip1q_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { + simd_shuffle16!(a, b, [0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vzip1_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { + simd_shuffle4!(a, b, [0, 4, 1, 5]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vzip1q_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { + simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vzip1_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { + simd_shuffle2!(a, b, [0, 2]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vzip1q_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { + simd_shuffle4!(a, b, [0, 4, 1, 5]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vzip1q_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { + simd_shuffle2!(a, b, [0, 2]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vzip1_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { + simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vzip1q_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { + simd_shuffle16!(a, b, [0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vzip1_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { + simd_shuffle4!(a, b, [0, 4, 1, 5]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vzip1q_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { + simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vzip1_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { + simd_shuffle2!(a, b, [0, 2]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vzip1q_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { + simd_shuffle4!(a, b, [0, 4, 1, 5]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vzip1q_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { + simd_shuffle2!(a, b, [0, 2]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vzip1_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { + simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vzip1q_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { + simd_shuffle16!(a, b, [0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vzip1_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t { + simd_shuffle4!(a, b, [0, 4, 1, 5]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vzip1q_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { + simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vzip1q_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { + simd_shuffle2!(a, b, [0, 2]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vzip1_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { + simd_shuffle2!(a, b, [0, 2]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vzip1q_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { + simd_shuffle4!(a, b, [0, 4, 1, 5]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vzip1q_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { + simd_shuffle2!(a, b, [0, 2]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vzip2_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { + simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vzip2q_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { + simd_shuffle16!(a, b, [8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vzip2_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { + simd_shuffle4!(a, b, [2, 6, 3, 7]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vzip2q_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { + simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vzip2_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { + simd_shuffle2!(a, b, [1, 3]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vzip2q_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { + simd_shuffle4!(a, b, [2, 6, 3, 7]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vzip2q_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { + simd_shuffle2!(a, b, [1, 3]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vzip2_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { + simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vzip2q_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { + simd_shuffle16!(a, b, [8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vzip2_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { + simd_shuffle4!(a, b, [2, 6, 3, 7]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vzip2q_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { + simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vzip2_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { + simd_shuffle2!(a, b, [1, 3]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vzip2q_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { + simd_shuffle4!(a, b, [2, 6, 3, 7]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vzip2q_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { + simd_shuffle2!(a, b, [1, 3]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vzip2_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { + simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vzip2q_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { + simd_shuffle16!(a, b, [8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vzip2_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t { + simd_shuffle4!(a, b, [2, 6, 3, 7]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vzip2q_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { + simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vzip2q_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { + simd_shuffle2!(a, b, [1, 3]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vzip2_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { + simd_shuffle2!(a, b, [1, 3]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vzip2q_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { + simd_shuffle4!(a, b, [2, 6, 3, 7]) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vzip2q_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { + simd_shuffle2!(a, b, [1, 3]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uzp1))] +pub unsafe fn vuzp1_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { + simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uzp1))] +pub unsafe fn vuzp1q_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { + simd_shuffle16!(a, b, [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uzp1))] +pub unsafe fn vuzp1_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { + simd_shuffle4!(a, b, [0, 2, 4, 6]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uzp1))] +pub unsafe fn vuzp1q_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { + simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uzp1))] +pub unsafe fn vuzp1q_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { + simd_shuffle4!(a, b, [0, 2, 4, 6]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uzp1))] +pub unsafe fn vuzp1_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { + simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uzp1))] +pub unsafe fn vuzp1q_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { + simd_shuffle16!(a, b, [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uzp1))] +pub unsafe fn vuzp1_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { + simd_shuffle4!(a, b, [0, 2, 4, 6]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uzp1))] +pub unsafe fn vuzp1q_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { + simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uzp1))] +pub unsafe fn vuzp1q_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { + simd_shuffle4!(a, b, [0, 2, 4, 6]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uzp1))] +pub unsafe fn vuzp1_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { + simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uzp1))] +pub unsafe fn vuzp1q_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { + simd_shuffle16!(a, b, [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uzp1))] +pub unsafe fn vuzp1_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t { + simd_shuffle4!(a, b, [0, 2, 4, 6]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uzp1))] +pub unsafe fn vuzp1q_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { + simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vuzp1_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { + simd_shuffle2!(a, b, [0, 2]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vuzp1q_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { + simd_shuffle2!(a, b, [0, 2]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vuzp1_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { + simd_shuffle2!(a, b, [0, 2]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vuzp1q_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { + simd_shuffle2!(a, b, [0, 2]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vuzp1q_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { + simd_shuffle2!(a, b, [0, 2]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uzp1))] +pub unsafe fn vuzp1q_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { + simd_shuffle4!(a, b, [0, 2, 4, 6]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vuzp1_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { + simd_shuffle2!(a, b, [0, 2]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip1))] +pub unsafe fn vuzp1q_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { + simd_shuffle2!(a, b, [0, 2]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uzp2))] +pub unsafe fn vuzp2_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { + simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uzp2))] +pub unsafe fn vuzp2q_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { + simd_shuffle16!(a, b, [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uzp2))] +pub unsafe fn vuzp2_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { + simd_shuffle4!(a, b, [1, 3, 5, 7]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uzp2))] +pub unsafe fn vuzp2q_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { + simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uzp2))] +pub unsafe fn vuzp2q_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { + simd_shuffle4!(a, b, [1, 3, 5, 7]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uzp2))] +pub unsafe fn vuzp2_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { + simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uzp2))] +pub unsafe fn vuzp2q_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { + simd_shuffle16!(a, b, [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uzp2))] +pub unsafe fn vuzp2_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { + simd_shuffle4!(a, b, [1, 3, 5, 7]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uzp2))] +pub unsafe fn vuzp2q_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { + simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uzp2))] +pub unsafe fn vuzp2q_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { + simd_shuffle4!(a, b, [1, 3, 5, 7]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uzp2))] +pub unsafe fn vuzp2_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { + simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uzp2))] +pub unsafe fn vuzp2q_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { + simd_shuffle16!(a, b, [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uzp2))] +pub unsafe fn vuzp2_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t { + simd_shuffle4!(a, b, [1, 3, 5, 7]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uzp2))] +pub unsafe fn vuzp2q_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { + simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vuzp2_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { + simd_shuffle2!(a, b, [1, 3]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vuzp2q_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { + simd_shuffle2!(a, b, [1, 3]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vuzp2_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { + simd_shuffle2!(a, b, [1, 3]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vuzp2q_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { + simd_shuffle2!(a, b, [1, 3]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vuzp2q_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { + simd_shuffle2!(a, b, [1, 3]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uzp2))] +pub unsafe fn vuzp2q_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { + simd_shuffle4!(a, b, [1, 3, 5, 7]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vuzp2_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { + simd_shuffle2!(a, b, [1, 3]) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(zip2))] +pub unsafe fn vuzp2q_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { + simd_shuffle2!(a, b, [1, 3]) +} + +/// Unsigned Absolute difference and Accumulate Long +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uabal))] +pub unsafe fn vabal_high_u8(a: uint16x8_t, b: uint8x16_t, c: uint8x16_t) -> uint16x8_t { + let d: uint8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); + let e: uint8x8_t = simd_shuffle8!(c, c, [8, 9, 10, 11, 12, 13, 14, 15]); + let f: uint8x8_t = vabd_u8(d, e); + simd_add(a, simd_cast(f)) +} + +/// Unsigned Absolute difference and Accumulate Long +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uabal))] +pub unsafe fn vabal_high_u16(a: uint32x4_t, b: uint16x8_t, c: uint16x8_t) -> uint32x4_t { + let d: uint16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); + let e: uint16x4_t = simd_shuffle4!(c, c, [4, 5, 6, 7]); + let f: uint16x4_t = vabd_u16(d, e); + simd_add(a, simd_cast(f)) +} + +/// Unsigned Absolute difference and Accumulate Long +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(uabal))] +pub unsafe fn vabal_high_u32(a: uint64x2_t, b: uint32x4_t, c: uint32x4_t) -> uint64x2_t { + let d: uint32x2_t = simd_shuffle2!(b, b, [2, 3]); + let e: uint32x2_t = simd_shuffle2!(c, c, [2, 3]); + let f: uint32x2_t = vabd_u32(d, e); + simd_add(a, simd_cast(f)) +} + +/// Signed Absolute difference and Accumulate Long +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(sabal))] +pub unsafe fn vabal_high_s8(a: int16x8_t, b: int8x16_t, c: int8x16_t) -> int16x8_t { + let d: int8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); + let e: int8x8_t = simd_shuffle8!(c, c, [8, 9, 10, 11, 12, 13, 14, 15]); + let f: int8x8_t = vabd_s8(d, e); + let f: uint8x8_t = simd_cast(f); + simd_add(a, simd_cast(f)) +} + +/// Signed Absolute difference and Accumulate Long +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(sabal))] +pub unsafe fn vabal_high_s16(a: int32x4_t, b: int16x8_t, c: int16x8_t) -> int32x4_t { + let d: int16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); + let e: int16x4_t = simd_shuffle4!(c, c, [4, 5, 6, 7]); + let f: int16x4_t = vabd_s16(d, e); + let f: uint16x4_t = simd_cast(f); + simd_add(a, simd_cast(f)) +} + +/// Signed Absolute difference and Accumulate Long +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(sabal))] +pub unsafe fn vabal_high_s32(a: int64x2_t, b: int32x4_t, c: int32x4_t) -> int64x2_t { + let d: int32x2_t = simd_shuffle2!(b, b, [2, 3]); + let e: int32x2_t = simd_shuffle2!(c, c, [2, 3]); + let f: int32x2_t = vabd_s32(d, e); + let f: uint32x2_t = simd_cast(f); + simd_add(a, simd_cast(f)) +} + +/// Singned saturating Absolute value +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(sqabs))] +pub unsafe fn vqabs_s64(a: int64x1_t) -> int64x1_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqabs.v1i64")] + fn vqabs_s64_(a: int64x1_t) -> int64x1_t; + } + vqabs_s64_(a) +} + +/// Singned saturating Absolute value +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(sqabs))] +pub unsafe fn vqabsq_s64(a: int64x2_t) -> int64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqabs.v2i64")] + fn vqabsq_s64_(a: int64x2_t) -> int64x2_t; + } + vqabsq_s64_(a) +} + +/// Signed saturating absolute value +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(sqabs))] +pub unsafe fn vqabsb_s8(a: i8) -> i8 { + simd_extract(vqabs_s8(vdup_n_s8(a)), 0) +} + +/// Signed saturating absolute value +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(sqabs))] +pub unsafe fn vqabsh_s16(a: i16) -> i16 { + simd_extract(vqabs_s16(vdup_n_s16(a)), 0) +} + +/// Signed saturating absolute value +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(sqabs))] +pub unsafe fn vqabss_s32(a: i32) -> i32 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqabs.i32")] + fn vqabss_s32_(a: i32) -> i32; + } + vqabss_s32_(a) +} + +/// Signed saturating absolute value +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(sqabs))] +pub unsafe fn vqabsd_s64(a: i64) -> i64 { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqabs.i64")] + fn vqabsd_s64_(a: i64) -> i64; + } + vqabsd_s64_(a) +} + +/// Shift left and insert +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(sli, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vslid_n_s64(a: i64, b: i64) -> i64 { + static_assert!(N : i32 where N >= 0 && N <= 63); + transmute(vsli_n_s64::(transmute(a), transmute(b))) +} + +/// Shift left and insert +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(sli, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vslid_n_u64(a: u64, b: u64) -> u64 { + static_assert!(N : i32 where N >= 0 && N <= 63); + transmute(vsli_n_u64::(transmute(a), transmute(b))) +} + +/// Shift right and insert +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(sri, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsrid_n_s64(a: i64, b: i64) -> i64 { + static_assert!(N : i32 where N >= 1 && N <= 64); + transmute(vsri_n_s64::(transmute(a), transmute(b))) +} + +/// Shift right and insert +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(sri, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsrid_n_u64(a: u64, b: u64) -> u64 { + static_assert!(N : i32 where N >= 1 && N <= 64); + transmute(vsri_n_u64::(transmute(a), transmute(b))) +} + +#[cfg(test)] +mod test { + use super::*; + use crate::core_arch::simd::*; + use std::mem::transmute; + use stdarch_test::simd_test; + + #[simd_test(enable = "neon,sha3")] + unsafe fn test_veor3q_s8() { + let a: i8x16 = i8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F); + let b: i8x16 = i8x16::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let c: i8x16 = i8x16::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let e: i8x16 = i8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F); + let r: i8x16 = transmute(veor3q_s8(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon,sha3")] + unsafe fn test_veor3q_s16() { + let a: i16x8 = i16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let b: i16x8 = i16x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let c: i16x8 = i16x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let e: i16x8 = i16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let r: i16x8 = transmute(veor3q_s16(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon,sha3")] + unsafe fn test_veor3q_s32() { + let a: i32x4 = i32x4::new(0x00, 0x01, 0x02, 0x03); + let b: i32x4 = i32x4::new(0x00, 0x00, 0x00, 0x00); + let c: i32x4 = i32x4::new(0x00, 0x00, 0x00, 0x00); + let e: i32x4 = i32x4::new(0x00, 0x01, 0x02, 0x03); + let r: i32x4 = transmute(veor3q_s32(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon,sha3")] + unsafe fn test_veor3q_s64() { + let a: i64x2 = i64x2::new(0x00, 0x01); + let b: i64x2 = i64x2::new(0x00, 0x00); + let c: i64x2 = i64x2::new(0x00, 0x00); + let e: i64x2 = i64x2::new(0x00, 0x01); + let r: i64x2 = transmute(veor3q_s64(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon,sha3")] + unsafe fn test_veor3q_u8() { + let a: u8x16 = u8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F); + let b: u8x16 = u8x16::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let c: u8x16 = u8x16::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let e: u8x16 = u8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F); + let r: u8x16 = transmute(veor3q_u8(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon,sha3")] + unsafe fn test_veor3q_u16() { + let a: u16x8 = u16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let b: u16x8 = u16x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let c: u16x8 = u16x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let e: u16x8 = u16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let r: u16x8 = transmute(veor3q_u16(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon,sha3")] + unsafe fn test_veor3q_u32() { + let a: u32x4 = u32x4::new(0x00, 0x01, 0x02, 0x03); + let b: u32x4 = u32x4::new(0x00, 0x00, 0x00, 0x00); + let c: u32x4 = u32x4::new(0x00, 0x00, 0x00, 0x00); + let e: u32x4 = u32x4::new(0x00, 0x01, 0x02, 0x03); + let r: u32x4 = transmute(veor3q_u32(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon,sha3")] + unsafe fn test_veor3q_u64() { + let a: u64x2 = u64x2::new(0x00, 0x01); + let b: u64x2 = u64x2::new(0x00, 0x00); + let c: u64x2 = u64x2::new(0x00, 0x00); + let e: u64x2 = u64x2::new(0x00, 0x01); + let r: u64x2 = transmute(veor3q_u64(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabd_f64() { + let a: f64 = 1.0; + let b: f64 = 9.0; + let e: f64 = 8.0; let r: f64 = transmute(vabd_f64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vabdq_f64() { - let a: f64x2 = f64x2::new(1.0, 2.0); - let b: f64x2 = f64x2::new(9.0, 3.0); - let e: f64x2 = f64x2::new(8.0, 1.0); - let r: f64x2 = transmute(vabdq_f64(transmute(a), transmute(b))); + unsafe fn test_vabdq_f64() { + let a: f64x2 = f64x2::new(1.0, 2.0); + let b: f64x2 = f64x2::new(9.0, 3.0); + let e: f64x2 = f64x2::new(8.0, 1.0); + let r: f64x2 = transmute(vabdq_f64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabds_f32() { + let a: f32 = 1.0; + let b: f32 = 9.0; + let e: f32 = 8.0; + let r: f32 = transmute(vabds_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabdd_f64() { + let a: f64 = 1.0; + let b: f64 = 9.0; + let e: f64 = 8.0; + let r: f64 = transmute(vabdd_f64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabdl_high_u8() { + let a: u8x16 = u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let b: u8x16 = u8x16::new(10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10); + let e: u16x8 = u16x8::new(1, 0, 1, 2, 3, 4, 5, 6); + let r: u16x8 = transmute(vabdl_high_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabdl_high_u16() { + let a: u16x8 = u16x8::new(1, 2, 3, 4, 8, 9, 11, 12); + let b: u16x8 = u16x8::new(10, 10, 10, 10, 10, 10, 10, 10); + let e: u32x4 = u32x4::new(2, 1, 1, 2); + let r: u32x4 = transmute(vabdl_high_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabdl_high_u32() { + let a: u32x4 = u32x4::new(1, 2, 3, 4); + let b: u32x4 = u32x4::new(10, 10, 10, 10); + let e: u64x2 = u64x2::new(7, 6); + let r: u64x2 = transmute(vabdl_high_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabdl_high_s8() { + let a: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let b: i8x16 = i8x16::new(10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10); + let e: i16x8 = i16x8::new(1, 0, 1, 2, 3, 4, 5, 6); + let r: i16x8 = transmute(vabdl_high_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabdl_high_s16() { + let a: i16x8 = i16x8::new(1, 2, 3, 4, 9, 10, 11, 12); + let b: i16x8 = i16x8::new(10, 10, 10, 10, 10, 10, 10, 10); + let e: i32x4 = i32x4::new(1, 0, 1, 2); + let r: i32x4 = transmute(vabdl_high_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabdl_high_s32() { + let a: i32x4 = i32x4::new(1, 2, 3, 4); + let b: i32x4 = i32x4::new(10, 10, 10, 10); + let e: i64x2 = i64x2::new(7, 6); + let r: i64x2 = transmute(vabdl_high_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceq_u64() { + let a: u64x1 = u64x1::new(0); + let b: u64x1 = u64x1::new(0); + let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x1 = transmute(vceq_u64(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: u64x1 = u64x1::new(0); + let b: u64x1 = u64x1::new(0); + let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x1 = transmute(vceq_u64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqq_u64() { + let a: u64x2 = u64x2::new(0, 0x01); + let b: u64x2 = u64x2::new(0, 0x01); + let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x2 = transmute(vceqq_u64(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: u64x2 = u64x2::new(0, 0); + let b: u64x2 = u64x2::new(0, 0xFF_FF_FF_FF_FF_FF_FF_FF); + let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0); + let r: u64x2 = transmute(vceqq_u64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceq_s64() { + let a: i64x1 = i64x1::new(-9223372036854775808); + let b: i64x1 = i64x1::new(-9223372036854775808); + let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x1 = transmute(vceq_s64(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: i64x1 = i64x1::new(-9223372036854775808); + let b: i64x1 = i64x1::new(-9223372036854775808); + let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x1 = transmute(vceq_s64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqq_s64() { + let a: i64x2 = i64x2::new(-9223372036854775808, 0x01); + let b: i64x2 = i64x2::new(-9223372036854775808, 0x01); + let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x2 = transmute(vceqq_s64(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: i64x2 = i64x2::new(-9223372036854775808, -9223372036854775808); + let b: i64x2 = i64x2::new(-9223372036854775808, 0x7F_FF_FF_FF_FF_FF_FF_FF); + let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0); + let r: u64x2 = transmute(vceqq_s64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceq_p64() { + let a: i64x1 = i64x1::new(-9223372036854775808); + let b: i64x1 = i64x1::new(-9223372036854775808); + let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x1 = transmute(vceq_p64(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: i64x1 = i64x1::new(-9223372036854775808); + let b: i64x1 = i64x1::new(-9223372036854775808); + let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x1 = transmute(vceq_p64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqq_p64() { + let a: i64x2 = i64x2::new(-9223372036854775808, 0x01); + let b: i64x2 = i64x2::new(-9223372036854775808, 0x01); + let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x2 = transmute(vceqq_p64(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: i64x2 = i64x2::new(-9223372036854775808, -9223372036854775808); + let b: i64x2 = i64x2::new(-9223372036854775808, 0x7F_FF_FF_FF_FF_FF_FF_FF); + let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0); + let r: u64x2 = transmute(vceqq_p64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceq_f64() { + let a: f64 = 1.2; + let b: f64 = 1.2; + let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x1 = transmute(vceq_f64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqq_f64() { + let a: f64x2 = f64x2::new(1.2, 3.4); + let b: f64x2 = f64x2::new(1.2, 3.4); + let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x2 = transmute(vceqq_f64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqd_s64() { + let a: i64 = 1; + let b: i64 = 2; + let e: u64 = 0; + let r: u64 = transmute(vceqd_s64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqd_u64() { + let a: u64 = 1; + let b: u64 = 2; + let e: u64 = 0; + let r: u64 = transmute(vceqd_u64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqs_f32() { + let a: f32 = 1.; + let b: f32 = 2.; + let e: u32 = 0; + let r: u32 = transmute(vceqs_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqd_f64() { + let a: f64 = 1.; + let b: f64 = 2.; + let e: u64 = 0; + let r: u64 = transmute(vceqd_f64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqz_s8() { + let a: i8x8 = i8x8::new(-128, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); + let e: u8x8 = u8x8::new(0, 0xFF, 0, 0, 0, 0, 0, 0); + let r: u8x8 = transmute(vceqz_s8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqzq_s8() { + let a: i8x16 = i8x16::new(-128, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x7F); + let e: u8x16 = u8x16::new(0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + let r: u8x16 = transmute(vceqzq_s8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqz_s16() { + let a: i16x4 = i16x4::new(-32768, 0x00, 0x01, 0x02); + let e: u16x4 = u16x4::new(0, 0xFF_FF, 0, 0); + let r: u16x4 = transmute(vceqz_s16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqzq_s16() { + let a: i16x8 = i16x8::new(-32768, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); + let e: u16x8 = u16x8::new(0, 0xFF_FF, 0, 0, 0, 0, 0, 0); + let r: u16x8 = transmute(vceqzq_s16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqz_s32() { + let a: i32x2 = i32x2::new(-2147483648, 0x00); + let e: u32x2 = u32x2::new(0, 0xFF_FF_FF_FF); + let r: u32x2 = transmute(vceqz_s32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqzq_s32() { + let a: i32x4 = i32x4::new(-2147483648, 0x00, 0x01, 0x02); + let e: u32x4 = u32x4::new(0, 0xFF_FF_FF_FF, 0, 0); + let r: u32x4 = transmute(vceqzq_s32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqz_s64() { + let a: i64x1 = i64x1::new(-9223372036854775808); + let e: u64x1 = u64x1::new(0); + let r: u64x1 = transmute(vceqz_s64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqzq_s64() { + let a: i64x2 = i64x2::new(-9223372036854775808, 0x00); + let e: u64x2 = u64x2::new(0, 0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x2 = transmute(vceqzq_s64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqz_p8() { + let a: i8x8 = i8x8::new(-128, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); + let e: u8x8 = u8x8::new(0, 0xFF, 0, 0, 0, 0, 0, 0); + let r: u8x8 = transmute(vceqz_p8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqzq_p8() { + let a: i8x16 = i8x16::new(-128, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x7F); + let e: u8x16 = u8x16::new(0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + let r: u8x16 = transmute(vceqzq_p8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqz_p64() { + let a: i64x1 = i64x1::new(-9223372036854775808); + let e: u64x1 = u64x1::new(0); + let r: u64x1 = transmute(vceqz_p64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqzq_p64() { + let a: i64x2 = i64x2::new(-9223372036854775808, 0x00); + let e: u64x2 = u64x2::new(0, 0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x2 = transmute(vceqzq_p64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqz_u8() { + let a: u8x8 = u8x8::new(0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); + let e: u8x8 = u8x8::new(0xFF, 0xFF, 0, 0, 0, 0, 0, 0); + let r: u8x8 = transmute(vceqz_u8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqzq_u8() { + let a: u8x16 = u8x16::new(0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0xFF); + let e: u8x16 = u8x16::new(0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + let r: u8x16 = transmute(vceqzq_u8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqz_u16() { + let a: u16x4 = u16x4::new(0, 0x00, 0x01, 0x02); + let e: u16x4 = u16x4::new(0xFF_FF, 0xFF_FF, 0, 0); + let r: u16x4 = transmute(vceqz_u16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqzq_u16() { + let a: u16x8 = u16x8::new(0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); + let e: u16x8 = u16x8::new(0xFF_FF, 0xFF_FF, 0, 0, 0, 0, 0, 0); + let r: u16x8 = transmute(vceqzq_u16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqz_u32() { + let a: u32x2 = u32x2::new(0, 0x00); + let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x2 = transmute(vceqz_u32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqzq_u32() { + let a: u32x4 = u32x4::new(0, 0x00, 0x01, 0x02); + let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0, 0); + let r: u32x4 = transmute(vceqzq_u32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqz_u64() { + let a: u64x1 = u64x1::new(0); + let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x1 = transmute(vceqz_u64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqzq_u64() { + let a: u64x2 = u64x2::new(0, 0x00); + let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x2 = transmute(vceqzq_u64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqz_f32() { + let a: f32x2 = f32x2::new(0.0, 1.2); + let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0); + let r: u32x2 = transmute(vceqz_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqzq_f32() { + let a: f32x4 = f32x4::new(0.0, 1.2, 3.4, 5.6); + let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0, 0, 0); + let r: u32x4 = transmute(vceqzq_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqz_f64() { + let a: f64 = 0.0; + let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x1 = transmute(vceqz_f64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqzq_f64() { + let a: f64x2 = f64x2::new(0.0, 1.2); + let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0); + let r: u64x2 = transmute(vceqzq_f64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqzd_s64() { + let a: i64 = 1; + let e: u64 = 0; + let r: u64 = transmute(vceqzd_s64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqzd_u64() { + let a: u64 = 1; + let e: u64 = 0; + let r: u64 = transmute(vceqzd_u64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqzs_f32() { + let a: f32 = 1.; + let e: u32 = 0; + let r: u32 = transmute(vceqzs_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqzd_f64() { + let a: f64 = 1.; + let e: u64 = 0; + let r: u64 = transmute(vceqzd_f64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtst_s64() { + let a: i64x1 = i64x1::new(-9223372036854775808); + let b: i64x1 = i64x1::new(-9223372036854775808); + let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x1 = transmute(vtst_s64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtstq_s64() { + let a: i64x2 = i64x2::new(-9223372036854775808, 0x00); + let b: i64x2 = i64x2::new(-9223372036854775808, 0x00); + let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0); + let r: u64x2 = transmute(vtstq_s64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtst_p64() { + let a: i64x1 = i64x1::new(-9223372036854775808); + let b: i64x1 = i64x1::new(-9223372036854775808); + let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x1 = transmute(vtst_p64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtstq_p64() { + let a: i64x2 = i64x2::new(-9223372036854775808, 0x00); + let b: i64x2 = i64x2::new(-9223372036854775808, 0x00); + let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0); + let r: u64x2 = transmute(vtstq_p64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtst_u64() { + let a: u64x1 = u64x1::new(0); + let b: u64x1 = u64x1::new(0); + let e: u64x1 = u64x1::new(0); + let r: u64x1 = transmute(vtst_u64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtstq_u64() { + let a: u64x2 = u64x2::new(0, 0x00); + let b: u64x2 = u64x2::new(0, 0x00); + let e: u64x2 = u64x2::new(0, 0); + let r: u64x2 = transmute(vtstq_u64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtstd_s64() { + let a: i64 = 0; + let b: i64 = 0; + let e: u64 = 0; + let r: u64 = transmute(vtstd_s64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtstd_u64() { + let a: u64 = 0; + let b: u64 = 0; + let e: u64 = 0; + let r: u64 = transmute(vtstd_u64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vuqadds_s32() { + let a: i32 = 1; + let b: u32 = 1; + let e: i32 = 2; + let r: i32 = transmute(vuqadds_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vuqaddd_s64() { + let a: i64 = 1; + let b: u64 = 1; + let e: i64 = 2; + let r: i64 = transmute(vuqaddd_s64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vuqaddb_s8() { + let a: i8 = 1; + let b: u8 = 2; + let e: i8 = 3; + let r: i8 = transmute(vuqaddb_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vuqaddh_s16() { + let a: i16 = 1; + let b: u16 = 2; + let e: i16 = 3; + let r: i16 = transmute(vuqaddh_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabs_f64() { + let a: f64 = -0.1; + let e: f64 = 0.1; + let r: f64 = transmute(vabs_f64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabsq_f64() { + let a: f64x2 = f64x2::new(-0.1, -2.2); + let e: f64x2 = f64x2::new(0.1, 2.2); + let r: f64x2 = transmute(vabsq_f64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgt_s64() { + let a: i64x1 = i64x1::new(1); + let b: i64x1 = i64x1::new(0); + let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x1 = transmute(vcgt_s64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgtq_s64() { + let a: i64x2 = i64x2::new(1, 2); + let b: i64x2 = i64x2::new(0, 1); + let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x2 = transmute(vcgtq_s64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgt_u64() { + let a: u64x1 = u64x1::new(1); + let b: u64x1 = u64x1::new(0); + let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x1 = transmute(vcgt_u64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgtq_u64() { + let a: u64x2 = u64x2::new(1, 2); + let b: u64x2 = u64x2::new(0, 1); + let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x2 = transmute(vcgtq_u64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgt_f64() { + let a: f64 = 1.2; + let b: f64 = 0.1; + let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x1 = transmute(vcgt_f64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgtq_f64() { + let a: f64x2 = f64x2::new(1.2, 2.3); + let b: f64x2 = f64x2::new(0.1, 1.2); + let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x2 = transmute(vcgtq_f64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgtd_s64() { + let a: i64 = 1; + let b: i64 = 2; + let e: u64 = 0; + let r: u64 = transmute(vcgtd_s64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgtd_u64() { + let a: u64 = 1; + let b: u64 = 2; + let e: u64 = 0; + let r: u64 = transmute(vcgtd_u64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgts_f32() { + let a: f32 = 1.; + let b: f32 = 2.; + let e: u32 = 0; + let r: u32 = transmute(vcgts_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgtd_f64() { + let a: f64 = 1.; + let b: f64 = 2.; + let e: u64 = 0; + let r: u64 = transmute(vcgtd_f64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclt_s64() { + let a: i64x1 = i64x1::new(0); + let b: i64x1 = i64x1::new(1); + let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x1 = transmute(vclt_s64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcltq_s64() { + let a: i64x2 = i64x2::new(0, 1); + let b: i64x2 = i64x2::new(1, 2); + let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x2 = transmute(vcltq_s64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclt_u64() { + let a: u64x1 = u64x1::new(0); + let b: u64x1 = u64x1::new(1); + let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x1 = transmute(vclt_u64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcltq_u64() { + let a: u64x2 = u64x2::new(0, 1); + let b: u64x2 = u64x2::new(1, 2); + let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x2 = transmute(vcltq_u64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclt_f64() { + let a: f64 = 0.1; + let b: f64 = 1.2; + let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x1 = transmute(vclt_f64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcltq_f64() { + let a: f64x2 = f64x2::new(0.1, 1.2); + let b: f64x2 = f64x2::new(1.2, 2.3); + let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x2 = transmute(vcltq_f64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcltd_s64() { + let a: i64 = 2; + let b: i64 = 1; + let e: u64 = 0; + let r: u64 = transmute(vcltd_s64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcltd_u64() { + let a: u64 = 2; + let b: u64 = 1; + let e: u64 = 0; + let r: u64 = transmute(vcltd_u64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclts_f32() { + let a: f32 = 2.; + let b: f32 = 1.; + let e: u32 = 0; + let r: u32 = transmute(vclts_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcltd_f64() { + let a: f64 = 2.; + let b: f64 = 1.; + let e: u64 = 0; + let r: u64 = transmute(vcltd_f64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcle_s64() { + let a: i64x1 = i64x1::new(0); + let b: i64x1 = i64x1::new(1); + let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x1 = transmute(vcle_s64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcleq_s64() { + let a: i64x2 = i64x2::new(0, 1); + let b: i64x2 = i64x2::new(1, 2); + let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x2 = transmute(vcleq_s64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcged_s64() { + let a: i64 = 1; + let b: i64 = 2; + let e: u64 = 0; + let r: u64 = transmute(vcged_s64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcged_u64() { + let a: u64 = 1; + let b: u64 = 2; + let e: u64 = 0; + let r: u64 = transmute(vcged_u64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcges_f32() { + let a: f32 = 1.; + let b: f32 = 2.; + let e: u32 = 0; + let r: u32 = transmute(vcges_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcged_f64() { + let a: f64 = 1.; + let b: f64 = 2.; + let e: u64 = 0; + let r: u64 = transmute(vcged_f64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcle_u64() { + let a: u64x1 = u64x1::new(0); + let b: u64x1 = u64x1::new(1); + let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x1 = transmute(vcle_u64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcleq_u64() { + let a: u64x2 = u64x2::new(0, 1); + let b: u64x2 = u64x2::new(1, 2); + let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x2 = transmute(vcleq_u64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcle_f64() { + let a: f64 = 0.1; + let b: f64 = 1.2; + let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x1 = transmute(vcle_f64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcleq_f64() { + let a: f64x2 = f64x2::new(0.1, 1.2); + let b: f64x2 = f64x2::new(1.2, 2.3); + let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x2 = transmute(vcleq_f64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcled_s64() { + let a: i64 = 2; + let b: i64 = 1; + let e: u64 = 0; + let r: u64 = transmute(vcled_s64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcled_u64() { + let a: u64 = 2; + let b: u64 = 1; + let e: u64 = 0; + let r: u64 = transmute(vcled_u64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcles_f32() { + let a: f32 = 2.; + let b: f32 = 1.; + let e: u32 = 0; + let r: u32 = transmute(vcles_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcled_f64() { + let a: f64 = 2.; + let b: f64 = 1.; + let e: u64 = 0; + let r: u64 = transmute(vcled_f64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcge_s64() { + let a: i64x1 = i64x1::new(1); + let b: i64x1 = i64x1::new(0); + let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x1 = transmute(vcge_s64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgeq_s64() { + let a: i64x2 = i64x2::new(1, 2); + let b: i64x2 = i64x2::new(0, 1); + let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x2 = transmute(vcgeq_s64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcge_u64() { + let a: u64x1 = u64x1::new(1); + let b: u64x1 = u64x1::new(0); + let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x1 = transmute(vcge_u64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgeq_u64() { + let a: u64x2 = u64x2::new(1, 2); + let b: u64x2 = u64x2::new(0, 1); + let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x2 = transmute(vcgeq_u64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcge_f64() { + let a: f64 = 1.2; + let b: f64 = 0.1; + let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x1 = transmute(vcge_f64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgeq_f64() { + let a: f64x2 = f64x2::new(1.2, 2.3); + let b: f64x2 = f64x2::new(0.1, 1.2); + let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x2 = transmute(vcgeq_f64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgez_s8() { + let a: i8x8 = i8x8::new(-128, -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05); + let e: u8x8 = u8x8::new(0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x8 = transmute(vcgez_s8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgezq_s8() { + let a: i8x16 = i8x16::new(-128, -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x7F); + let e: u8x16 = u8x16::new(0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x16 = transmute(vcgezq_s8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgez_s16() { + let a: i16x4 = i16x4::new(-32768, -1, 0x00, 0x01); + let e: u16x4 = u16x4::new(0, 0, 0xFF_FF, 0xFF_FF); + let r: u16x4 = transmute(vcgez_s16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgezq_s16() { + let a: i16x8 = i16x8::new(-32768, -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05); + let e: u16x8 = u16x8::new(0, 0, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); + let r: u16x8 = transmute(vcgezq_s16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgez_s32() { + let a: i32x2 = i32x2::new(-2147483648, -1); + let e: u32x2 = u32x2::new(0, 0); + let r: u32x2 = transmute(vcgez_s32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgezq_s32() { + let a: i32x4 = i32x4::new(-2147483648, -1, 0x00, 0x01); + let e: u32x4 = u32x4::new(0, 0, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x4 = transmute(vcgezq_s32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgez_s64() { + let a: i64x1 = i64x1::new(-9223372036854775808); + let e: u64x1 = u64x1::new(0); + let r: u64x1 = transmute(vcgez_s64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgezq_s64() { + let a: i64x2 = i64x2::new(-9223372036854775808, -1); + let e: u64x2 = u64x2::new(0, 0); + let r: u64x2 = transmute(vcgezq_s64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgez_f32() { + let a: f32x2 = f32x2::new(-1.2, 0.0); + let e: u32x2 = u32x2::new(0, 0xFF_FF_FF_FF); + let r: u32x2 = transmute(vcgez_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgezq_f32() { + let a: f32x4 = f32x4::new(-1.2, 0.0, 1.2, 2.3); + let e: u32x4 = u32x4::new(0, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x4 = transmute(vcgezq_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgez_f64() { + let a: f64 = -1.2; + let e: u64x1 = u64x1::new(0); + let r: u64x1 = transmute(vcgez_f64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgezq_f64() { + let a: f64x2 = f64x2::new(-1.2, 0.0); + let e: u64x2 = u64x2::new(0, 0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x2 = transmute(vcgezq_f64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgezd_s64() { + let a: i64 = -1; + let e: u64 = 0; + let r: u64 = transmute(vcgezd_s64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgezs_f32() { + let a: f32 = -1.; + let e: u32 = 0; + let r: u32 = transmute(vcgezs_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgezd_f64() { + let a: f64 = -1.; + let e: u64 = 0; + let r: u64 = transmute(vcgezd_f64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgtz_s8() { + let a: i8x8 = i8x8::new(-128, -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05); + let e: u8x8 = u8x8::new(0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x8 = transmute(vcgtz_s8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgtzq_s8() { + let a: i8x16 = i8x16::new(-128, -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x7F); + let e: u8x16 = u8x16::new(0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x16 = transmute(vcgtzq_s8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgtz_s16() { + let a: i16x4 = i16x4::new(-32768, -1, 0x00, 0x01); + let e: u16x4 = u16x4::new(0, 0, 0, 0xFF_FF); + let r: u16x4 = transmute(vcgtz_s16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgtzq_s16() { + let a: i16x8 = i16x8::new(-32768, -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05); + let e: u16x8 = u16x8::new(0, 0, 0, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); + let r: u16x8 = transmute(vcgtzq_s16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgtz_s32() { + let a: i32x2 = i32x2::new(-2147483648, -1); + let e: u32x2 = u32x2::new(0, 0); + let r: u32x2 = transmute(vcgtz_s32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgtzq_s32() { + let a: i32x4 = i32x4::new(-2147483648, -1, 0x00, 0x01); + let e: u32x4 = u32x4::new(0, 0, 0, 0xFF_FF_FF_FF); + let r: u32x4 = transmute(vcgtzq_s32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgtz_s64() { + let a: i64x1 = i64x1::new(-9223372036854775808); + let e: u64x1 = u64x1::new(0); + let r: u64x1 = transmute(vcgtz_s64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgtzq_s64() { + let a: i64x2 = i64x2::new(-9223372036854775808, -1); + let e: u64x2 = u64x2::new(0, 0); + let r: u64x2 = transmute(vcgtzq_s64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgtz_f32() { + let a: f32x2 = f32x2::new(-1.2, 0.0); + let e: u32x2 = u32x2::new(0, 0); + let r: u32x2 = transmute(vcgtz_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgtzq_f32() { + let a: f32x4 = f32x4::new(-1.2, 0.0, 1.2, 2.3); + let e: u32x4 = u32x4::new(0, 0, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x4 = transmute(vcgtzq_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgtz_f64() { + let a: f64 = -1.2; + let e: u64x1 = u64x1::new(0); + let r: u64x1 = transmute(vcgtz_f64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgtzq_f64() { + let a: f64x2 = f64x2::new(-1.2, 0.0); + let e: u64x2 = u64x2::new(0, 0); + let r: u64x2 = transmute(vcgtzq_f64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgtzd_s64() { + let a: i64 = -1; + let e: u64 = 0; + let r: u64 = transmute(vcgtzd_s64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgtzs_f32() { + let a: f32 = -1.; + let e: u32 = 0; + let r: u32 = transmute(vcgtzs_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgtzd_f64() { + let a: f64 = -1.; + let e: u64 = 0; + let r: u64 = transmute(vcgtzd_f64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclez_s8() { + let a: i8x8 = i8x8::new(-128, -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05); + let e: u8x8 = u8x8::new(0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0); + let r: u8x8 = transmute(vclez_s8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclezq_s8() { + let a: i8x16 = i8x16::new(-128, -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x7F); + let e: u8x16 = u8x16::new(0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + let r: u8x16 = transmute(vclezq_s8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclez_s16() { + let a: i16x4 = i16x4::new(-32768, -1, 0x00, 0x01); + let e: u16x4 = u16x4::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0); + let r: u16x4 = transmute(vclez_s16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclezq_s16() { + let a: i16x8 = i16x8::new(-32768, -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05); + let e: u16x8 = u16x8::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0, 0, 0, 0, 0); + let r: u16x8 = transmute(vclezq_s16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclez_s32() { + let a: i32x2 = i32x2::new(-2147483648, -1); + let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x2 = transmute(vclez_s32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclezq_s32() { + let a: i32x4 = i32x4::new(-2147483648, -1, 0x00, 0x01); + let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0); + let r: u32x4 = transmute(vclezq_s32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclez_s64() { + let a: i64x1 = i64x1::new(-9223372036854775808); + let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x1 = transmute(vclez_s64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclezq_s64() { + let a: i64x2 = i64x2::new(-9223372036854775808, -1); + let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x2 = transmute(vclezq_s64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclez_f32() { + let a: f32x2 = f32x2::new(-1.2, 0.0); + let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x2 = transmute(vclez_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclezq_f32() { + let a: f32x4 = f32x4::new(-1.2, 0.0, 1.2, 2.3); + let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0, 0); + let r: u32x4 = transmute(vclezq_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclez_f64() { + let a: f64 = -1.2; + let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x1 = transmute(vclez_f64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclezq_f64() { + let a: f64x2 = f64x2::new(-1.2, 0.0); + let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x2 = transmute(vclezq_f64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclezd_s64() { + let a: i64 = 2; + let e: u64 = 0; + let r: u64 = transmute(vclezd_s64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclezs_f32() { + let a: f32 = 2.; + let e: u32 = 0; + let r: u32 = transmute(vclezs_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclezd_f64() { + let a: f64 = 2.; + let e: u64 = 0; + let r: u64 = transmute(vclezd_f64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcltz_s8() { + let a: i8x8 = i8x8::new(-128, -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05); + let e: u8x8 = u8x8::new(0xFF, 0xFF, 0, 0, 0, 0, 0, 0); + let r: u8x8 = transmute(vcltz_s8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcltzq_s8() { + let a: i8x16 = i8x16::new(-128, -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x7F); + let e: u8x16 = u8x16::new(0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + let r: u8x16 = transmute(vcltzq_s8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcltz_s16() { + let a: i16x4 = i16x4::new(-32768, -1, 0x00, 0x01); + let e: u16x4 = u16x4::new(0xFF_FF, 0xFF_FF, 0, 0); + let r: u16x4 = transmute(vcltz_s16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcltzq_s16() { + let a: i16x8 = i16x8::new(-32768, -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05); + let e: u16x8 = u16x8::new(0xFF_FF, 0xFF_FF, 0, 0, 0, 0, 0, 0); + let r: u16x8 = transmute(vcltzq_s16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcltz_s32() { + let a: i32x2 = i32x2::new(-2147483648, -1); + let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x2 = transmute(vcltz_s32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcltzq_s32() { + let a: i32x4 = i32x4::new(-2147483648, -1, 0x00, 0x01); + let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0, 0); + let r: u32x4 = transmute(vcltzq_s32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcltz_s64() { + let a: i64x1 = i64x1::new(-9223372036854775808); + let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x1 = transmute(vcltz_s64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcltzq_s64() { + let a: i64x2 = i64x2::new(-9223372036854775808, -1); + let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x2 = transmute(vcltzq_s64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcltz_f32() { + let a: f32x2 = f32x2::new(-1.2, 0.0); + let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0); + let r: u32x2 = transmute(vcltz_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcltzq_f32() { + let a: f32x4 = f32x4::new(-1.2, 0.0, 1.2, 2.3); + let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0, 0, 0); + let r: u32x4 = transmute(vcltzq_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcltz_f64() { + let a: f64 = -1.2; + let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x1 = transmute(vcltz_f64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcltzq_f64() { + let a: f64x2 = f64x2::new(-1.2, 0.0); + let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0); + let r: u64x2 = transmute(vcltzq_f64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcltzd_s64() { + let a: i64 = 2; + let e: u64 = 0; + let r: u64 = transmute(vcltzd_s64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcltzs_f32() { + let a: f32 = 2.; + let e: u32 = 0; + let r: u32 = transmute(vcltzs_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcltzd_f64() { + let a: f64 = 2.; + let e: u64 = 0; + let r: u64 = transmute(vcltzd_f64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcagt_f64() { + let a: f64 = -1.2; + let b: f64 = -1.1; + let e: u64x1 = u64x1::new(!0); + let r: u64x1 = transmute(vcagt_f64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcagtq_f64() { + let a: f64x2 = f64x2::new(-1.2, 0.0); + let b: f64x2 = f64x2::new(-1.1, 0.0); + let e: u64x2 = u64x2::new(!0, 0); + let r: u64x2 = transmute(vcagtq_f64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcagts_f32() { + let a: f32 = -1.2; + let b: f32 = -1.1; + let e: u32 = !0; + let r: u32 = transmute(vcagts_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcagtd_f64() { + let a: f64 = -1.2; + let b: f64 = -1.1; + let e: u64 = !0; + let r: u64 = transmute(vcagtd_f64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcage_f64() { + let a: f64 = -1.2; + let b: f64 = -1.1; + let e: u64x1 = u64x1::new(!0); + let r: u64x1 = transmute(vcage_f64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcageq_f64() { + let a: f64x2 = f64x2::new(-1.2, 0.0); + let b: f64x2 = f64x2::new(-1.1, 0.0); + let e: u64x2 = u64x2::new(!0, 0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x2 = transmute(vcageq_f64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcages_f32() { + let a: f32 = -1.2; + let b: f32 = -1.1; + let e: u32 = !0; + let r: u32 = transmute(vcages_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcaged_f64() { + let a: f64 = -1.2; + let b: f64 = -1.1; + let e: u64 = !0; + let r: u64 = transmute(vcaged_f64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcalt_f64() { + let a: f64 = -1.2; + let b: f64 = -1.1; + let e: u64x1 = u64x1::new(0); + let r: u64x1 = transmute(vcalt_f64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcaltq_f64() { + let a: f64x2 = f64x2::new(-1.2, 0.0); + let b: f64x2 = f64x2::new(-1.1, 0.0); + let e: u64x2 = u64x2::new(0, 0); + let r: u64x2 = transmute(vcaltq_f64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcalts_f32() { + let a: f32 = -1.2; + let b: f32 = -1.1; + let e: u32 = 0; + let r: u32 = transmute(vcalts_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcaltd_f64() { + let a: f64 = -1.2; + let b: f64 = -1.1; + let e: u64 = 0; + let r: u64 = transmute(vcaltd_f64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcale_f64() { + let a: f64 = -1.2; + let b: f64 = -1.1; + let e: u64x1 = u64x1::new(0); + let r: u64x1 = transmute(vcale_f64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcaleq_f64() { + let a: f64x2 = f64x2::new(-1.2, 0.0); + let b: f64x2 = f64x2::new(-1.1, 0.0); + let e: u64x2 = u64x2::new(0, 0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x2 = transmute(vcaleq_f64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcales_f32() { + let a: f32 = -1.2; + let b: f32 = -1.1; + let e: u32 = 0; + let r: u32 = transmute(vcales_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcaled_f64() { + let a: f64 = -1.2; + let b: f64 = -1.1; + let e: u64 = 0; + let r: u64 = transmute(vcaled_f64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopy_lane_s8() { + let a: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let b: i8x8 = i8x8::new(0, 0x7F, 0, 0, 0, 0, 0, 0); + let e: i8x8 = i8x8::new(0x7F, 2, 3, 4, 5, 6, 7, 8); + let r: i8x8 = transmute(vcopy_lane_s8::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopyq_laneq_s8() { + let a: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let b: i8x16 = i8x16::new(0, 0x7F, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + let e: i8x16 = i8x16::new(0x7F, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let r: i8x16 = transmute(vcopyq_laneq_s8::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopy_lane_s16() { + let a: i16x4 = i16x4::new(1, 2, 3, 4); + let b: i16x4 = i16x4::new(0, 0x7F_FF, 0, 0); + let e: i16x4 = i16x4::new(0x7F_FF, 2, 3, 4); + let r: i16x4 = transmute(vcopy_lane_s16::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopyq_laneq_s16() { + let a: i16x8 = i16x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let b: i16x8 = i16x8::new(0, 0x7F_FF, 0, 0, 0, 0, 0, 0); + let e: i16x8 = i16x8::new(0x7F_FF, 2, 3, 4, 5, 6, 7, 8); + let r: i16x8 = transmute(vcopyq_laneq_s16::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopy_lane_s32() { + let a: i32x2 = i32x2::new(1, 2); + let b: i32x2 = i32x2::new(0, 0x7F_FF_FF_FF); + let e: i32x2 = i32x2::new(0x7F_FF_FF_FF, 2); + let r: i32x2 = transmute(vcopy_lane_s32::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopyq_laneq_s32() { + let a: i32x4 = i32x4::new(1, 2, 3, 4); + let b: i32x4 = i32x4::new(0, 0x7F_FF_FF_FF, 0, 0); + let e: i32x4 = i32x4::new(0x7F_FF_FF_FF, 2, 3, 4); + let r: i32x4 = transmute(vcopyq_laneq_s32::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopyq_laneq_s64() { + let a: i64x2 = i64x2::new(1, 2); + let b: i64x2 = i64x2::new(0, 0x7F_FF_FF_FF_FF_FF_FF_FF); + let e: i64x2 = i64x2::new(0x7F_FF_FF_FF_FF_FF_FF_FF, 2); + let r: i64x2 = transmute(vcopyq_laneq_s64::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopy_lane_u8() { + let a: u8x8 = u8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let b: u8x8 = u8x8::new(0, 0xFF, 0, 0, 0, 0, 0, 0); + let e: u8x8 = u8x8::new(0xFF, 2, 3, 4, 5, 6, 7, 8); + let r: u8x8 = transmute(vcopy_lane_u8::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopyq_laneq_u8() { + let a: u8x16 = u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let b: u8x16 = u8x16::new(0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + let e: u8x16 = u8x16::new(0xFF, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let r: u8x16 = transmute(vcopyq_laneq_u8::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopy_lane_u16() { + let a: u16x4 = u16x4::new(1, 2, 3, 4); + let b: u16x4 = u16x4::new(0, 0xFF_FF, 0, 0); + let e: u16x4 = u16x4::new(0xFF_FF, 2, 3, 4); + let r: u16x4 = transmute(vcopy_lane_u16::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopyq_laneq_u16() { + let a: u16x8 = u16x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let b: u16x8 = u16x8::new(0, 0xFF_FF, 0, 0, 0, 0, 0, 0); + let e: u16x8 = u16x8::new(0xFF_FF, 2, 3, 4, 5, 6, 7, 8); + let r: u16x8 = transmute(vcopyq_laneq_u16::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopy_lane_u32() { + let a: u32x2 = u32x2::new(1, 2); + let b: u32x2 = u32x2::new(0, 0xFF_FF_FF_FF); + let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 2); + let r: u32x2 = transmute(vcopy_lane_u32::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopyq_laneq_u32() { + let a: u32x4 = u32x4::new(1, 2, 3, 4); + let b: u32x4 = u32x4::new(0, 0xFF_FF_FF_FF, 0, 0); + let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 2, 3, 4); + let r: u32x4 = transmute(vcopyq_laneq_u32::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopyq_laneq_u64() { + let a: u64x2 = u64x2::new(1, 2); + let b: u64x2 = u64x2::new(0, 0xFF_FF_FF_FF_FF_FF_FF_FF); + let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 2); + let r: u64x2 = transmute(vcopyq_laneq_u64::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopy_lane_p8() { + let a: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let b: i8x8 = i8x8::new(0, 0x7F, 0, 0, 0, 0, 0, 0); + let e: i8x8 = i8x8::new(0x7F, 2, 3, 4, 5, 6, 7, 8); + let r: i8x8 = transmute(vcopy_lane_p8::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopyq_laneq_p8() { + let a: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let b: i8x16 = i8x16::new(0, 0x7F, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + let e: i8x16 = i8x16::new(0x7F, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let r: i8x16 = transmute(vcopyq_laneq_p8::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopy_lane_p16() { + let a: i16x4 = i16x4::new(1, 2, 3, 4); + let b: i16x4 = i16x4::new(0, 0x7F_FF, 0, 0); + let e: i16x4 = i16x4::new(0x7F_FF, 2, 3, 4); + let r: i16x4 = transmute(vcopy_lane_p16::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopyq_laneq_p16() { + let a: i16x8 = i16x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let b: i16x8 = i16x8::new(0, 0x7F_FF, 0, 0, 0, 0, 0, 0); + let e: i16x8 = i16x8::new(0x7F_FF, 2, 3, 4, 5, 6, 7, 8); + let r: i16x8 = transmute(vcopyq_laneq_p16::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopyq_laneq_p64() { + let a: i64x2 = i64x2::new(1, 2); + let b: i64x2 = i64x2::new(0, 0x7F_FF_FF_FF_FF_FF_FF_FF); + let e: i64x2 = i64x2::new(0x7F_FF_FF_FF_FF_FF_FF_FF, 2); + let r: i64x2 = transmute(vcopyq_laneq_p64::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopy_lane_f32() { + let a: f32x2 = f32x2::new(1., 2.); + let b: f32x2 = f32x2::new(0., 0.5); + let e: f32x2 = f32x2::new(0.5, 2.); + let r: f32x2 = transmute(vcopy_lane_f32::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopyq_laneq_f32() { + let a: f32x4 = f32x4::new(1., 2., 3., 4.); + let b: f32x4 = f32x4::new(0., 0.5, 0., 0.); + let e: f32x4 = f32x4::new(0.5, 2., 3., 4.); + let r: f32x4 = transmute(vcopyq_laneq_f32::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopyq_laneq_f64() { + let a: f64x2 = f64x2::new(1., 2.); + let b: f64x2 = f64x2::new(0., 0.5); + let e: f64x2 = f64x2::new(0.5, 2.); + let r: f64x2 = transmute(vcopyq_laneq_f64::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopy_laneq_s8() { + let a: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let b: i8x16 = i8x16::new(0, 0x7F, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + let e: i8x8 = i8x8::new(0x7F, 2, 3, 4, 5, 6, 7, 8); + let r: i8x8 = transmute(vcopy_laneq_s8::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopy_laneq_s16() { + let a: i16x4 = i16x4::new(1, 2, 3, 4); + let b: i16x8 = i16x8::new(0, 0x7F_FF, 0, 0, 0, 0, 0, 0); + let e: i16x4 = i16x4::new(0x7F_FF, 2, 3, 4); + let r: i16x4 = transmute(vcopy_laneq_s16::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopy_laneq_s32() { + let a: i32x2 = i32x2::new(1, 2); + let b: i32x4 = i32x4::new(0, 0x7F_FF_FF_FF, 0, 0); + let e: i32x2 = i32x2::new(0x7F_FF_FF_FF, 2); + let r: i32x2 = transmute(vcopy_laneq_s32::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopy_laneq_u8() { + let a: u8x8 = u8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let b: u8x16 = u8x16::new(0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + let e: u8x8 = u8x8::new(0xFF, 2, 3, 4, 5, 6, 7, 8); + let r: u8x8 = transmute(vcopy_laneq_u8::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopy_laneq_u16() { + let a: u16x4 = u16x4::new(1, 2, 3, 4); + let b: u16x8 = u16x8::new(0, 0xFF_FF, 0, 0, 0, 0, 0, 0); + let e: u16x4 = u16x4::new(0xFF_FF, 2, 3, 4); + let r: u16x4 = transmute(vcopy_laneq_u16::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopy_laneq_u32() { + let a: u32x2 = u32x2::new(1, 2); + let b: u32x4 = u32x4::new(0, 0xFF_FF_FF_FF, 0, 0); + let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 2); + let r: u32x2 = transmute(vcopy_laneq_u32::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopy_laneq_p8() { + let a: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let b: i8x16 = i8x16::new(0, 0x7F, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + let e: i8x8 = i8x8::new(0x7F, 2, 3, 4, 5, 6, 7, 8); + let r: i8x8 = transmute(vcopy_laneq_p8::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopy_laneq_p16() { + let a: i16x4 = i16x4::new(1, 2, 3, 4); + let b: i16x8 = i16x8::new(0, 0x7F_FF, 0, 0, 0, 0, 0, 0); + let e: i16x4 = i16x4::new(0x7F_FF, 2, 3, 4); + let r: i16x4 = transmute(vcopy_laneq_p16::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopy_laneq_f32() { + let a: f32x2 = f32x2::new(1., 2.); + let b: f32x4 = f32x4::new(0., 0.5, 0., 0.); + let e: f32x2 = f32x2::new(0.5, 2.); + let r: f32x2 = transmute(vcopy_laneq_f32::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopyq_lane_s8() { + let a: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let b: i8x8 = i8x8::new(0, 0x7F, 0, 0, 0, 0, 0, 0); + let e: i8x16 = i8x16::new(0x7F, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let r: i8x16 = transmute(vcopyq_lane_s8::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopyq_lane_s16() { + let a: i16x8 = i16x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let b: i16x4 = i16x4::new(0, 0x7F_FF, 0, 0); + let e: i16x8 = i16x8::new(0x7F_FF, 2, 3, 4, 5, 6, 7, 8); + let r: i16x8 = transmute(vcopyq_lane_s16::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopyq_lane_s32() { + let a: i32x4 = i32x4::new(1, 2, 3, 4); + let b: i32x2 = i32x2::new(0, 0x7F_FF_FF_FF); + let e: i32x4 = i32x4::new(0x7F_FF_FF_FF, 2, 3, 4); + let r: i32x4 = transmute(vcopyq_lane_s32::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopyq_lane_u8() { + let a: u8x16 = u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let b: u8x8 = u8x8::new(0, 0xFF, 0, 0, 0, 0, 0, 0); + let e: u8x16 = u8x16::new(0xFF, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let r: u8x16 = transmute(vcopyq_lane_u8::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopyq_lane_u16() { + let a: u16x8 = u16x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let b: u16x4 = u16x4::new(0, 0xFF_FF, 0, 0); + let e: u16x8 = u16x8::new(0xFF_FF, 2, 3, 4, 5, 6, 7, 8); + let r: u16x8 = transmute(vcopyq_lane_u16::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopyq_lane_u32() { + let a: u32x4 = u32x4::new(1, 2, 3, 4); + let b: u32x2 = u32x2::new(0, 0xFF_FF_FF_FF); + let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 2, 3, 4); + let r: u32x4 = transmute(vcopyq_lane_u32::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopyq_lane_p8() { + let a: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let b: i8x8 = i8x8::new(0, 0x7F, 0, 0, 0, 0, 0, 0); + let e: i8x16 = i8x16::new(0x7F, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let r: i8x16 = transmute(vcopyq_lane_p8::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopyq_lane_p16() { + let a: i16x8 = i16x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let b: i16x4 = i16x4::new(0, 0x7F_FF, 0, 0); + let e: i16x8 = i16x8::new(0x7F_FF, 2, 3, 4, 5, 6, 7, 8); + let r: i16x8 = transmute(vcopyq_lane_p16::<0, 1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopyq_lane_s64() { + let a: i64x2 = i64x2::new(1, 2); + let b: i64x1 = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); + let e: i64x2 = i64x2::new(1, 0x7F_FF_FF_FF_FF_FF_FF_FF); + let r: i64x2 = transmute(vcopyq_lane_s64::<1, 0>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcopyq_lane_u64() { + let a: u64x2 = u64x2::new(1, 2); + let b: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let e: u64x2 = u64x2::new(1, 0xFF_FF_FF_FF_FF_FF_FF_FF); + let r: u64x2 = transmute(vcopyq_lane_u64::<1, 0>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vabdl_high_u8() { - let a: u8x16 = u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let b: u8x16 = u8x16::new(10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10); - let e: u16x8 = u16x8::new(1, 0, 1, 2, 3, 4, 5, 6); - let r: u16x8 = transmute(vabdl_high_u8(transmute(a), transmute(b))); + unsafe fn test_vcopyq_lane_p64() { + let a: i64x2 = i64x2::new(1, 2); + let b: i64x1 = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); + let e: i64x2 = i64x2::new(1, 0x7F_FF_FF_FF_FF_FF_FF_FF); + let r: i64x2 = transmute(vcopyq_lane_p64::<1, 0>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vabdl_high_u16() { - let a: u16x8 = u16x8::new(1, 2, 3, 4, 8, 9, 11, 12); - let b: u16x8 = u16x8::new(10, 10, 10, 10, 10, 10, 10, 10); - let e: u32x4 = u32x4::new(2, 1, 1, 2); - let r: u32x4 = transmute(vabdl_high_u16(transmute(a), transmute(b))); + unsafe fn test_vcopyq_lane_f32() { + let a: f32x4 = f32x4::new(1., 2., 3., 4.); + let b: f32x2 = f32x2::new(0.5, 0.); + let e: f32x4 = f32x4::new(1., 0.5, 3., 4.); + let r: f32x4 = transmute(vcopyq_lane_f32::<1, 0>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vabdl_high_u32() { - let a: u32x4 = u32x4::new(1, 2, 3, 4); - let b: u32x4 = u32x4::new(10, 10, 10, 10); - let e: u64x2 = u64x2::new(7, 6); - let r: u64x2 = transmute(vabdl_high_u32(transmute(a), transmute(b))); + unsafe fn test_vcopyq_lane_f64() { + let a: f64x2 = f64x2::new(1., 2.); + let b: f64 = 0.5; + let e: f64x2 = f64x2::new(1., 0.5); + let r: f64x2 = transmute(vcopyq_lane_f64::<1, 0>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vabdl_high_s8() { - let a: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let b: i8x16 = i8x16::new(10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10); - let e: i16x8 = i16x8::new(1, 0, 1, 2, 3, 4, 5, 6); - let r: i16x8 = transmute(vabdl_high_s8(transmute(a), transmute(b))); + unsafe fn test_vcreate_f64() { + let a: u64 = 0; + let e: f64 = 0.; + let r: f64 = transmute(vcreate_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vabdl_high_s16() { - let a: i16x8 = i16x8::new(1, 2, 3, 4, 9, 10, 11, 12); - let b: i16x8 = i16x8::new(10, 10, 10, 10, 10, 10, 10, 10); - let e: i32x4 = i32x4::new(1, 0, 1, 2); - let r: i32x4 = transmute(vabdl_high_s16(transmute(a), transmute(b))); + unsafe fn test_vcvt_f64_s64() { + let a: i64x1 = i64x1::new(1); + let e: f64 = 1.; + let r: f64 = transmute(vcvt_f64_s64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vabdl_high_s32() { - let a: i32x4 = i32x4::new(1, 2, 3, 4); - let b: i32x4 = i32x4::new(10, 10, 10, 10); - let e: i64x2 = i64x2::new(7, 6); - let r: i64x2 = transmute(vabdl_high_s32(transmute(a), transmute(b))); + unsafe fn test_vcvtq_f64_s64() { + let a: i64x2 = i64x2::new(1, 2); + let e: f64x2 = f64x2::new(1., 2.); + let r: f64x2 = transmute(vcvtq_f64_s64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceq_u64() { - let a: u64x1 = u64x1::new(0); - let b: u64x1 = u64x1::new(0); - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vceq_u64(transmute(a), transmute(b))); + unsafe fn test_vcvt_f64_u64() { + let a: u64x1 = u64x1::new(1); + let e: f64 = 1.; + let r: f64 = transmute(vcvt_f64_u64(transmute(a))); assert_eq!(r, e); + } - let a: u64x1 = u64x1::new(0); - let b: u64x1 = u64x1::new(0); - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vceq_u64(transmute(a), transmute(b))); + #[simd_test(enable = "neon")] + unsafe fn test_vcvtq_f64_u64() { + let a: u64x2 = u64x2::new(1, 2); + let e: f64x2 = f64x2::new(1., 2.); + let r: f64x2 = transmute(vcvtq_f64_u64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqq_u64() { - let a: u64x2 = u64x2::new(0, 0x01); - let b: u64x2 = u64x2::new(0, 0x01); - let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x2 = transmute(vceqq_u64(transmute(a), transmute(b))); + unsafe fn test_vcvt_f64_f32() { + let a: f32x2 = f32x2::new(-1.2, 1.2); + let e: f64x2 = f64x2::new(-1.2f32 as f64, 1.2f32 as f64); + let r: f64x2 = transmute(vcvt_f64_f32(transmute(a))); assert_eq!(r, e); + } - let a: u64x2 = u64x2::new(0, 0); - let b: u64x2 = u64x2::new(0, 0xFF_FF_FF_FF_FF_FF_FF_FF); - let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0); - let r: u64x2 = transmute(vceqq_u64(transmute(a), transmute(b))); + #[simd_test(enable = "neon")] + unsafe fn test_vcvt_high_f64_f32() { + let a: f32x4 = f32x4::new(-1.2, 1.2, 2.3, 3.4); + let e: f64x2 = f64x2::new(2.3f32 as f64, 3.4f32 as f64); + let r: f64x2 = transmute(vcvt_high_f64_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceq_s64() { - let a: i64x1 = i64x1::new(-9223372036854775808); - let b: i64x1 = i64x1::new(-9223372036854775808); - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vceq_s64(transmute(a), transmute(b))); + unsafe fn test_vcvt_f32_f64() { + let a: f64x2 = f64x2::new(-1.2, 1.2); + let e: f32x2 = f32x2::new(-1.2f64 as f32, 1.2f64 as f32); + let r: f32x2 = transmute(vcvt_f32_f64(transmute(a))); assert_eq!(r, e); + } - let a: i64x1 = i64x1::new(-9223372036854775808); - let b: i64x1 = i64x1::new(-9223372036854775808); - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vceq_s64(transmute(a), transmute(b))); + #[simd_test(enable = "neon")] + unsafe fn test_vcvt_high_f32_f64() { + let a: f32x2 = f32x2::new(-1.2, 1.2); + let b: f64x2 = f64x2::new(-2.3, 3.4); + let e: f32x4 = f32x4::new(-1.2, 1.2, -2.3f64 as f32, 3.4f64 as f32); + let r: f32x4 = transmute(vcvt_high_f32_f64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqq_s64() { - let a: i64x2 = i64x2::new(-9223372036854775808, 0x01); - let b: i64x2 = i64x2::new(-9223372036854775808, 0x01); - let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x2 = transmute(vceqq_s64(transmute(a), transmute(b))); + unsafe fn test_vcvtx_f32_f64() { + let a: f64x2 = f64x2::new(-1.0, 2.0); + let e: f32x2 = f32x2::new(-1.0, 2.0); + let r: f32x2 = transmute(vcvtx_f32_f64(transmute(a))); assert_eq!(r, e); + } - let a: i64x2 = i64x2::new(-9223372036854775808, -9223372036854775808); - let b: i64x2 = i64x2::new(-9223372036854775808, 0x7F_FF_FF_FF_FF_FF_FF_FF); - let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0); - let r: u64x2 = transmute(vceqq_s64(transmute(a), transmute(b))); + #[simd_test(enable = "neon")] + unsafe fn test_vcvtxd_f32_f64() { + let a: f64 = -1.0; + let e: f32 = -1.0; + let r: f32 = transmute(vcvtxd_f32_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceq_p64() { - let a: i64x1 = i64x1::new(-9223372036854775808); - let b: i64x1 = i64x1::new(-9223372036854775808); - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vceq_p64(transmute(a), transmute(b))); + unsafe fn test_vcvtx_high_f32_f64() { + let a: f32x2 = f32x2::new(-1.0, 2.0); + let b: f64x2 = f64x2::new(-3.0, 4.0); + let e: f32x4 = f32x4::new(-1.0, 2.0, -3.0, 4.0); + let r: f32x4 = transmute(vcvtx_high_f32_f64(transmute(a), transmute(b))); assert_eq!(r, e); + } - let a: i64x1 = i64x1::new(-9223372036854775808); - let b: i64x1 = i64x1::new(-9223372036854775808); - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vceq_p64(transmute(a), transmute(b))); + #[simd_test(enable = "neon")] + unsafe fn test_vcvt_n_f64_s64() { + let a: i64x1 = i64x1::new(1); + let e: f64 = 0.25; + let r: f64 = transmute(vcvt_n_f64_s64::<2>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqq_p64() { - let a: i64x2 = i64x2::new(-9223372036854775808, 0x01); - let b: i64x2 = i64x2::new(-9223372036854775808, 0x01); - let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x2 = transmute(vceqq_p64(transmute(a), transmute(b))); + unsafe fn test_vcvtq_n_f64_s64() { + let a: i64x2 = i64x2::new(1, 2); + let e: f64x2 = f64x2::new(0.25, 0.5); + let r: f64x2 = transmute(vcvtq_n_f64_s64::<2>(transmute(a))); assert_eq!(r, e); + } - let a: i64x2 = i64x2::new(-9223372036854775808, -9223372036854775808); - let b: i64x2 = i64x2::new(-9223372036854775808, 0x7F_FF_FF_FF_FF_FF_FF_FF); - let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0); - let r: u64x2 = transmute(vceqq_p64(transmute(a), transmute(b))); + #[simd_test(enable = "neon")] + unsafe fn test_vcvts_n_f32_s32() { + let a: i32 = 1; + let e: f32 = 0.25; + let r: f32 = transmute(vcvts_n_f32_s32::<2>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceq_f64() { - let a: f64 = 1.2; - let b: f64 = 1.2; - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vceq_f64(transmute(a), transmute(b))); + unsafe fn test_vcvtd_n_f64_s64() { + let a: i64 = 1; + let e: f64 = 0.25; + let r: f64 = transmute(vcvtd_n_f64_s64::<2>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqq_f64() { - let a: f64x2 = f64x2::new(1.2, 3.4); - let b: f64x2 = f64x2::new(1.2, 3.4); - let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x2 = transmute(vceqq_f64(transmute(a), transmute(b))); + unsafe fn test_vcvt_n_f64_u64() { + let a: u64x1 = u64x1::new(1); + let e: f64 = 0.25; + let r: f64 = transmute(vcvt_n_f64_u64::<2>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqz_s8() { - let a: i8x8 = i8x8::new(-128, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); - let e: u8x8 = u8x8::new(0, 0xFF, 0, 0, 0, 0, 0, 0); - let r: u8x8 = transmute(vceqz_s8(transmute(a))); + unsafe fn test_vcvtq_n_f64_u64() { + let a: u64x2 = u64x2::new(1, 2); + let e: f64x2 = f64x2::new(0.25, 0.5); + let r: f64x2 = transmute(vcvtq_n_f64_u64::<2>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqzq_s8() { - let a: i8x16 = i8x16::new(-128, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x7F); - let e: u8x16 = u8x16::new(0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - let r: u8x16 = transmute(vceqzq_s8(transmute(a))); + unsafe fn test_vcvts_n_f32_u32() { + let a: u32 = 1; + let e: f32 = 0.25; + let r: f32 = transmute(vcvts_n_f32_u32::<2>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqz_s16() { - let a: i16x4 = i16x4::new(-32768, 0x00, 0x01, 0x02); - let e: u16x4 = u16x4::new(0, 0xFF_FF, 0, 0); - let r: u16x4 = transmute(vceqz_s16(transmute(a))); + unsafe fn test_vcvtd_n_f64_u64() { + let a: u64 = 1; + let e: f64 = 0.25; + let r: f64 = transmute(vcvtd_n_f64_u64::<2>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqzq_s16() { - let a: i16x8 = i16x8::new(-32768, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); - let e: u16x8 = u16x8::new(0, 0xFF_FF, 0, 0, 0, 0, 0, 0); - let r: u16x8 = transmute(vceqzq_s16(transmute(a))); + unsafe fn test_vcvt_n_s64_f64() { + let a: f64 = 0.25; + let e: i64x1 = i64x1::new(1); + let r: i64x1 = transmute(vcvt_n_s64_f64::<2>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqz_s32() { - let a: i32x2 = i32x2::new(-2147483648, 0x00); - let e: u32x2 = u32x2::new(0, 0xFF_FF_FF_FF); - let r: u32x2 = transmute(vceqz_s32(transmute(a))); + unsafe fn test_vcvtq_n_s64_f64() { + let a: f64x2 = f64x2::new(0.25, 0.5); + let e: i64x2 = i64x2::new(1, 2); + let r: i64x2 = transmute(vcvtq_n_s64_f64::<2>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqzq_s32() { - let a: i32x4 = i32x4::new(-2147483648, 0x00, 0x01, 0x02); - let e: u32x4 = u32x4::new(0, 0xFF_FF_FF_FF, 0, 0); - let r: u32x4 = transmute(vceqzq_s32(transmute(a))); + unsafe fn test_vcvts_n_s32_f32() { + let a: f32 = 0.25; + let e: i32 = 1; + let r: i32 = transmute(vcvts_n_s32_f32::<2>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqz_s64() { - let a: i64x1 = i64x1::new(-9223372036854775808); - let e: u64x1 = u64x1::new(0); - let r: u64x1 = transmute(vceqz_s64(transmute(a))); + unsafe fn test_vcvtd_n_s64_f64() { + let a: f64 = 0.25; + let e: i64 = 1; + let r: i64 = transmute(vcvtd_n_s64_f64::<2>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqzq_s64() { - let a: i64x2 = i64x2::new(-9223372036854775808, 0x00); - let e: u64x2 = u64x2::new(0, 0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x2 = transmute(vceqzq_s64(transmute(a))); + unsafe fn test_vcvt_n_u64_f64() { + let a: f64 = 0.25; + let e: u64x1 = u64x1::new(1); + let r: u64x1 = transmute(vcvt_n_u64_f64::<2>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqz_p8() { - let a: i8x8 = i8x8::new(-128, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); - let e: u8x8 = u8x8::new(0, 0xFF, 0, 0, 0, 0, 0, 0); - let r: u8x8 = transmute(vceqz_p8(transmute(a))); + unsafe fn test_vcvtq_n_u64_f64() { + let a: f64x2 = f64x2::new(0.25, 0.5); + let e: u64x2 = u64x2::new(1, 2); + let r: u64x2 = transmute(vcvtq_n_u64_f64::<2>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqzq_p8() { - let a: i8x16 = i8x16::new(-128, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x7F); - let e: u8x16 = u8x16::new(0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - let r: u8x16 = transmute(vceqzq_p8(transmute(a))); + unsafe fn test_vcvts_n_u32_f32() { + let a: f32 = 0.25; + let e: u32 = 1; + let r: u32 = transmute(vcvts_n_u32_f32::<2>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqz_p64() { - let a: i64x1 = i64x1::new(-9223372036854775808); - let e: u64x1 = u64x1::new(0); - let r: u64x1 = transmute(vceqz_p64(transmute(a))); + unsafe fn test_vcvtd_n_u64_f64() { + let a: f64 = 0.25; + let e: u64 = 1; + let r: u64 = transmute(vcvtd_n_u64_f64::<2>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqzq_p64() { - let a: i64x2 = i64x2::new(-9223372036854775808, 0x00); - let e: u64x2 = u64x2::new(0, 0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x2 = transmute(vceqzq_p64(transmute(a))); + unsafe fn test_vcvts_f32_s32() { + let a: i32 = 1; + let e: f32 = 1.; + let r: f32 = transmute(vcvts_f32_s32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqz_u8() { - let a: u8x8 = u8x8::new(0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); - let e: u8x8 = u8x8::new(0xFF, 0xFF, 0, 0, 0, 0, 0, 0); - let r: u8x8 = transmute(vceqz_u8(transmute(a))); + unsafe fn test_vcvtd_f64_s64() { + let a: i64 = 1; + let e: f64 = 1.; + let r: f64 = transmute(vcvtd_f64_s64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqzq_u8() { - let a: u8x16 = u8x16::new(0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0xFF); - let e: u8x16 = u8x16::new(0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - let r: u8x16 = transmute(vceqzq_u8(transmute(a))); + unsafe fn test_vcvts_f32_u32() { + let a: u32 = 1; + let e: f32 = 1.; + let r: f32 = transmute(vcvts_f32_u32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqz_u16() { - let a: u16x4 = u16x4::new(0, 0x00, 0x01, 0x02); - let e: u16x4 = u16x4::new(0xFF_FF, 0xFF_FF, 0, 0); - let r: u16x4 = transmute(vceqz_u16(transmute(a))); + unsafe fn test_vcvtd_f64_u64() { + let a: u64 = 1; + let e: f64 = 1.; + let r: f64 = transmute(vcvtd_f64_u64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqzq_u16() { - let a: u16x8 = u16x8::new(0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); - let e: u16x8 = u16x8::new(0xFF_FF, 0xFF_FF, 0, 0, 0, 0, 0, 0); - let r: u16x8 = transmute(vceqzq_u16(transmute(a))); + unsafe fn test_vcvts_s32_f32() { + let a: f32 = 1.; + let e: i32 = 1; + let r: i32 = transmute(vcvts_s32_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqz_u32() { - let a: u32x2 = u32x2::new(0, 0x00); - let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x2 = transmute(vceqz_u32(transmute(a))); + unsafe fn test_vcvtd_s64_f64() { + let a: f64 = 1.; + let e: i64 = 1; + let r: i64 = transmute(vcvtd_s64_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqzq_u32() { - let a: u32x4 = u32x4::new(0, 0x00, 0x01, 0x02); - let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0, 0); - let r: u32x4 = transmute(vceqzq_u32(transmute(a))); + unsafe fn test_vcvts_u32_f32() { + let a: f32 = 1.; + let e: u32 = 1; + let r: u32 = transmute(vcvts_u32_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqz_u64() { - let a: u64x1 = u64x1::new(0); - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vceqz_u64(transmute(a))); + unsafe fn test_vcvtd_u64_f64() { + let a: f64 = 1.; + let e: u64 = 1; + let r: u64 = transmute(vcvtd_u64_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqzq_u64() { - let a: u64x2 = u64x2::new(0, 0x00); - let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x2 = transmute(vceqzq_u64(transmute(a))); + unsafe fn test_vcvt_s64_f64() { + let a: f64 = -1.1; + let e: i64x1 = i64x1::new(-1); + let r: i64x1 = transmute(vcvt_s64_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqz_f32() { - let a: f32x2 = f32x2::new(0.0, 1.2); - let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0); - let r: u32x2 = transmute(vceqz_f32(transmute(a))); + unsafe fn test_vcvtq_s64_f64() { + let a: f64x2 = f64x2::new(-1.1, 2.1); + let e: i64x2 = i64x2::new(-1, 2); + let r: i64x2 = transmute(vcvtq_s64_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqzq_f32() { - let a: f32x4 = f32x4::new(0.0, 1.2, 3.4, 5.6); - let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0, 0, 0); - let r: u32x4 = transmute(vceqzq_f32(transmute(a))); + unsafe fn test_vcvt_u64_f64() { + let a: f64 = 1.1; + let e: u64x1 = u64x1::new(1); + let r: u64x1 = transmute(vcvt_u64_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqz_f64() { - let a: f64 = 0.0; - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vceqz_f64(transmute(a))); + unsafe fn test_vcvtq_u64_f64() { + let a: f64x2 = f64x2::new(1.1, 2.1); + let e: u64x2 = u64x2::new(1, 2); + let r: u64x2 = transmute(vcvtq_u64_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqzq_f64() { - let a: f64x2 = f64x2::new(0.0, 1.2); - let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0); - let r: u64x2 = transmute(vceqzq_f64(transmute(a))); + unsafe fn test_vcvta_s32_f32() { + let a: f32x2 = f32x2::new(-1.1, 2.1); + let e: i32x2 = i32x2::new(-1, 2); + let r: i32x2 = transmute(vcvta_s32_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vtst_s64() { - let a: i64x1 = i64x1::new(-9223372036854775808); - let b: i64x1 = i64x1::new(-9223372036854775808); - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vtst_s64(transmute(a), transmute(b))); + unsafe fn test_vcvtaq_s32_f32() { + let a: f32x4 = f32x4::new(-1.1, 2.1, -2.9, 3.9); + let e: i32x4 = i32x4::new(-1, 2, -3, 4); + let r: i32x4 = transmute(vcvtaq_s32_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vtstq_s64() { - let a: i64x2 = i64x2::new(-9223372036854775808, 0x00); - let b: i64x2 = i64x2::new(-9223372036854775808, 0x00); - let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0); - let r: u64x2 = transmute(vtstq_s64(transmute(a), transmute(b))); + unsafe fn test_vcvta_s64_f64() { + let a: f64 = -1.1; + let e: i64x1 = i64x1::new(-1); + let r: i64x1 = transmute(vcvta_s64_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vtst_p64() { - let a: i64x1 = i64x1::new(-9223372036854775808); - let b: i64x1 = i64x1::new(-9223372036854775808); - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vtst_p64(transmute(a), transmute(b))); + unsafe fn test_vcvtaq_s64_f64() { + let a: f64x2 = f64x2::new(-1.1, 2.1); + let e: i64x2 = i64x2::new(-1, 2); + let r: i64x2 = transmute(vcvtaq_s64_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vtstq_p64() { - let a: i64x2 = i64x2::new(-9223372036854775808, 0x00); - let b: i64x2 = i64x2::new(-9223372036854775808, 0x00); - let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0); - let r: u64x2 = transmute(vtstq_p64(transmute(a), transmute(b))); + unsafe fn test_vcvtas_s32_f32() { + let a: f32 = 2.9; + let e: i32 = 3; + let r: i32 = transmute(vcvtas_s32_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vtst_u64() { - let a: u64x1 = u64x1::new(0); - let b: u64x1 = u64x1::new(0); - let e: u64x1 = u64x1::new(0); - let r: u64x1 = transmute(vtst_u64(transmute(a), transmute(b))); + unsafe fn test_vcvtad_s64_f64() { + let a: f64 = 2.9; + let e: i64 = 3; + let r: i64 = transmute(vcvtad_s64_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vtstq_u64() { - let a: u64x2 = u64x2::new(0, 0x00); - let b: u64x2 = u64x2::new(0, 0x00); - let e: u64x2 = u64x2::new(0, 0); - let r: u64x2 = transmute(vtstq_u64(transmute(a), transmute(b))); + unsafe fn test_vcvtas_u32_f32() { + let a: f32 = 2.9; + let e: u32 = 3; + let r: u32 = transmute(vcvtas_u32_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vabs_f64() { - let a: f64 = -0.1; - let e: f64 = 0.1; - let r: f64 = transmute(vabs_f64(transmute(a))); + unsafe fn test_vcvtad_u64_f64() { + let a: f64 = 2.9; + let e: u64 = 3; + let r: u64 = transmute(vcvtad_u64_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vabsq_f64() { - let a: f64x2 = f64x2::new(-0.1, -2.2); - let e: f64x2 = f64x2::new(0.1, 2.2); - let r: f64x2 = transmute(vabsq_f64(transmute(a))); + unsafe fn test_vcvtn_s32_f32() { + let a: f32x2 = f32x2::new(-1.5, 2.1); + let e: i32x2 = i32x2::new(-2, 2); + let r: i32x2 = transmute(vcvtn_s32_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgt_s64() { - let a: i64x1 = i64x1::new(1); - let b: i64x1 = i64x1::new(0); - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vcgt_s64(transmute(a), transmute(b))); + unsafe fn test_vcvtnq_s32_f32() { + let a: f32x4 = f32x4::new(-1.5, 2.1, -2.9, 3.9); + let e: i32x4 = i32x4::new(-2, 2, -3, 4); + let r: i32x4 = transmute(vcvtnq_s32_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgtq_s64() { - let a: i64x2 = i64x2::new(1, 2); - let b: i64x2 = i64x2::new(0, 1); - let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x2 = transmute(vcgtq_s64(transmute(a), transmute(b))); + unsafe fn test_vcvtn_s64_f64() { + let a: f64 = -1.5; + let e: i64x1 = i64x1::new(-2); + let r: i64x1 = transmute(vcvtn_s64_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgt_u64() { - let a: u64x1 = u64x1::new(1); - let b: u64x1 = u64x1::new(0); - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vcgt_u64(transmute(a), transmute(b))); + unsafe fn test_vcvtnq_s64_f64() { + let a: f64x2 = f64x2::new(-1.5, 2.1); + let e: i64x2 = i64x2::new(-2, 2); + let r: i64x2 = transmute(vcvtnq_s64_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgtq_u64() { - let a: u64x2 = u64x2::new(1, 2); - let b: u64x2 = u64x2::new(0, 1); - let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x2 = transmute(vcgtq_u64(transmute(a), transmute(b))); + unsafe fn test_vcvtns_s32_f32() { + let a: f32 = -1.5; + let e: i32 = -2; + let r: i32 = transmute(vcvtns_s32_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgt_f64() { - let a: f64 = 1.2; - let b: f64 = 0.1; - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vcgt_f64(transmute(a), transmute(b))); + unsafe fn test_vcvtnd_s64_f64() { + let a: f64 = -1.5; + let e: i64 = -2; + let r: i64 = transmute(vcvtnd_s64_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgtq_f64() { - let a: f64x2 = f64x2::new(1.2, 2.3); - let b: f64x2 = f64x2::new(0.1, 1.2); - let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x2 = transmute(vcgtq_f64(transmute(a), transmute(b))); + unsafe fn test_vcvtm_s32_f32() { + let a: f32x2 = f32x2::new(-1.1, 2.1); + let e: i32x2 = i32x2::new(-2, 2); + let r: i32x2 = transmute(vcvtm_s32_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclt_s64() { - let a: i64x1 = i64x1::new(0); - let b: i64x1 = i64x1::new(1); - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vclt_s64(transmute(a), transmute(b))); + unsafe fn test_vcvtmq_s32_f32() { + let a: f32x4 = f32x4::new(-1.1, 2.1, -2.9, 3.9); + let e: i32x4 = i32x4::new(-2, 2, -3, 3); + let r: i32x4 = transmute(vcvtmq_s32_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcltq_s64() { - let a: i64x2 = i64x2::new(0, 1); - let b: i64x2 = i64x2::new(1, 2); - let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x2 = transmute(vcltq_s64(transmute(a), transmute(b))); + unsafe fn test_vcvtm_s64_f64() { + let a: f64 = -1.1; + let e: i64x1 = i64x1::new(-2); + let r: i64x1 = transmute(vcvtm_s64_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclt_u64() { - let a: u64x1 = u64x1::new(0); - let b: u64x1 = u64x1::new(1); - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vclt_u64(transmute(a), transmute(b))); + unsafe fn test_vcvtmq_s64_f64() { + let a: f64x2 = f64x2::new(-1.1, 2.1); + let e: i64x2 = i64x2::new(-2, 2); + let r: i64x2 = transmute(vcvtmq_s64_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcltq_u64() { - let a: u64x2 = u64x2::new(0, 1); - let b: u64x2 = u64x2::new(1, 2); - let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x2 = transmute(vcltq_u64(transmute(a), transmute(b))); + unsafe fn test_vcvtms_s32_f32() { + let a: f32 = -1.1; + let e: i32 = -2; + let r: i32 = transmute(vcvtms_s32_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclt_f64() { - let a: f64 = 0.1; - let b: f64 = 1.2; - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vclt_f64(transmute(a), transmute(b))); + unsafe fn test_vcvtmd_s64_f64() { + let a: f64 = -1.1; + let e: i64 = -2; + let r: i64 = transmute(vcvtmd_s64_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcltq_f64() { - let a: f64x2 = f64x2::new(0.1, 1.2); - let b: f64x2 = f64x2::new(1.2, 2.3); - let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x2 = transmute(vcltq_f64(transmute(a), transmute(b))); + unsafe fn test_vcvtp_s32_f32() { + let a: f32x2 = f32x2::new(-1.1, 2.1); + let e: i32x2 = i32x2::new(-1, 3); + let r: i32x2 = transmute(vcvtp_s32_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcle_s64() { - let a: i64x1 = i64x1::new(0); - let b: i64x1 = i64x1::new(1); - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vcle_s64(transmute(a), transmute(b))); + unsafe fn test_vcvtpq_s32_f32() { + let a: f32x4 = f32x4::new(-1.1, 2.1, -2.9, 3.9); + let e: i32x4 = i32x4::new(-1, 3, -2, 4); + let r: i32x4 = transmute(vcvtpq_s32_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcleq_s64() { - let a: i64x2 = i64x2::new(0, 1); - let b: i64x2 = i64x2::new(1, 2); - let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x2 = transmute(vcleq_s64(transmute(a), transmute(b))); + unsafe fn test_vcvtp_s64_f64() { + let a: f64 = -1.1; + let e: i64x1 = i64x1::new(-1); + let r: i64x1 = transmute(vcvtp_s64_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcle_u64() { - let a: u64x1 = u64x1::new(0); - let b: u64x1 = u64x1::new(1); - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vcle_u64(transmute(a), transmute(b))); + unsafe fn test_vcvtpq_s64_f64() { + let a: f64x2 = f64x2::new(-1.1, 2.1); + let e: i64x2 = i64x2::new(-1, 3); + let r: i64x2 = transmute(vcvtpq_s64_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcleq_u64() { - let a: u64x2 = u64x2::new(0, 1); - let b: u64x2 = u64x2::new(1, 2); - let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x2 = transmute(vcleq_u64(transmute(a), transmute(b))); + unsafe fn test_vcvtps_s32_f32() { + let a: f32 = -1.1; + let e: i32 = -1; + let r: i32 = transmute(vcvtps_s32_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcle_f64() { - let a: f64 = 0.1; - let b: f64 = 1.2; - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vcle_f64(transmute(a), transmute(b))); + unsafe fn test_vcvtpd_s64_f64() { + let a: f64 = -1.1; + let e: i64 = -1; + let r: i64 = transmute(vcvtpd_s64_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcleq_f64() { - let a: f64x2 = f64x2::new(0.1, 1.2); - let b: f64x2 = f64x2::new(1.2, 2.3); - let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x2 = transmute(vcleq_f64(transmute(a), transmute(b))); + unsafe fn test_vcvta_u32_f32() { + let a: f32x2 = f32x2::new(1.1, 2.1); + let e: u32x2 = u32x2::new(1, 2); + let r: u32x2 = transmute(vcvta_u32_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcge_s64() { - let a: i64x1 = i64x1::new(1); - let b: i64x1 = i64x1::new(0); - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vcge_s64(transmute(a), transmute(b))); + unsafe fn test_vcvtaq_u32_f32() { + let a: f32x4 = f32x4::new(1.1, 2.1, 2.9, 3.9); + let e: u32x4 = u32x4::new(1, 2, 3, 4); + let r: u32x4 = transmute(vcvtaq_u32_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgeq_s64() { - let a: i64x2 = i64x2::new(1, 2); - let b: i64x2 = i64x2::new(0, 1); - let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x2 = transmute(vcgeq_s64(transmute(a), transmute(b))); + unsafe fn test_vcvta_u64_f64() { + let a: f64 = 1.1; + let e: u64x1 = u64x1::new(1); + let r: u64x1 = transmute(vcvta_u64_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcge_u64() { - let a: u64x1 = u64x1::new(1); - let b: u64x1 = u64x1::new(0); - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vcge_u64(transmute(a), transmute(b))); + unsafe fn test_vcvtaq_u64_f64() { + let a: f64x2 = f64x2::new(1.1, 2.1); + let e: u64x2 = u64x2::new(1, 2); + let r: u64x2 = transmute(vcvtaq_u64_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgeq_u64() { - let a: u64x2 = u64x2::new(1, 2); - let b: u64x2 = u64x2::new(0, 1); - let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x2 = transmute(vcgeq_u64(transmute(a), transmute(b))); + unsafe fn test_vcvtn_u32_f32() { + let a: f32x2 = f32x2::new(1.5, 2.1); + let e: u32x2 = u32x2::new(2, 2); + let r: u32x2 = transmute(vcvtn_u32_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcge_f64() { - let a: f64 = 1.2; - let b: f64 = 0.1; - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vcge_f64(transmute(a), transmute(b))); + unsafe fn test_vcvtnq_u32_f32() { + let a: f32x4 = f32x4::new(1.5, 2.1, 2.9, 3.9); + let e: u32x4 = u32x4::new(2, 2, 3, 4); + let r: u32x4 = transmute(vcvtnq_u32_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgeq_f64() { - let a: f64x2 = f64x2::new(1.2, 2.3); - let b: f64x2 = f64x2::new(0.1, 1.2); - let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x2 = transmute(vcgeq_f64(transmute(a), transmute(b))); + unsafe fn test_vcvtn_u64_f64() { + let a: f64 = 1.5; + let e: u64x1 = u64x1::new(2); + let r: u64x1 = transmute(vcvtn_u64_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgez_s8() { - let a: i8x8 = i8x8::new(-128, -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05); - let e: u8x8 = u8x8::new(0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x8 = transmute(vcgez_s8(transmute(a))); + unsafe fn test_vcvtnq_u64_f64() { + let a: f64x2 = f64x2::new(1.5, 2.1); + let e: u64x2 = u64x2::new(2, 2); + let r: u64x2 = transmute(vcvtnq_u64_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgezq_s8() { - let a: i8x16 = i8x16::new(-128, -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x7F); - let e: u8x16 = u8x16::new(0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x16 = transmute(vcgezq_s8(transmute(a))); + unsafe fn test_vcvtns_u32_f32() { + let a: f32 = 1.5; + let e: u32 = 2; + let r: u32 = transmute(vcvtns_u32_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgez_s16() { - let a: i16x4 = i16x4::new(-32768, -1, 0x00, 0x01); - let e: u16x4 = u16x4::new(0, 0, 0xFF_FF, 0xFF_FF); - let r: u16x4 = transmute(vcgez_s16(transmute(a))); + unsafe fn test_vcvtnd_u64_f64() { + let a: f64 = 1.5; + let e: u64 = 2; + let r: u64 = transmute(vcvtnd_u64_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgezq_s16() { - let a: i16x8 = i16x8::new(-32768, -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05); - let e: u16x8 = u16x8::new(0, 0, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); - let r: u16x8 = transmute(vcgezq_s16(transmute(a))); + unsafe fn test_vcvtm_u32_f32() { + let a: f32x2 = f32x2::new(1.1, 2.1); + let e: u32x2 = u32x2::new(1, 2); + let r: u32x2 = transmute(vcvtm_u32_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgez_s32() { - let a: i32x2 = i32x2::new(-2147483648, -1); - let e: u32x2 = u32x2::new(0, 0); - let r: u32x2 = transmute(vcgez_s32(transmute(a))); + unsafe fn test_vcvtmq_u32_f32() { + let a: f32x4 = f32x4::new(1.1, 2.1, 2.9, 3.9); + let e: u32x4 = u32x4::new(1, 2, 2, 3); + let r: u32x4 = transmute(vcvtmq_u32_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgezq_s32() { - let a: i32x4 = i32x4::new(-2147483648, -1, 0x00, 0x01); - let e: u32x4 = u32x4::new(0, 0, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x4 = transmute(vcgezq_s32(transmute(a))); + unsafe fn test_vcvtm_u64_f64() { + let a: f64 = 1.1; + let e: u64x1 = u64x1::new(1); + let r: u64x1 = transmute(vcvtm_u64_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgez_s64() { - let a: i64x1 = i64x1::new(-9223372036854775808); - let e: u64x1 = u64x1::new(0); - let r: u64x1 = transmute(vcgez_s64(transmute(a))); + unsafe fn test_vcvtmq_u64_f64() { + let a: f64x2 = f64x2::new(1.1, 2.1); + let e: u64x2 = u64x2::new(1, 2); + let r: u64x2 = transmute(vcvtmq_u64_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgezq_s64() { - let a: i64x2 = i64x2::new(-9223372036854775808, -1); - let e: u64x2 = u64x2::new(0, 0); - let r: u64x2 = transmute(vcgezq_s64(transmute(a))); + unsafe fn test_vcvtms_u32_f32() { + let a: f32 = 1.1; + let e: u32 = 1; + let r: u32 = transmute(vcvtms_u32_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgez_f32() { - let a: f32x2 = f32x2::new(-1.2, 0.0); - let e: u32x2 = u32x2::new(0, 0xFF_FF_FF_FF); - let r: u32x2 = transmute(vcgez_f32(transmute(a))); + unsafe fn test_vcvtmd_u64_f64() { + let a: f64 = 1.1; + let e: u64 = 1; + let r: u64 = transmute(vcvtmd_u64_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgezq_f32() { - let a: f32x4 = f32x4::new(-1.2, 0.0, 1.2, 2.3); - let e: u32x4 = u32x4::new(0, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x4 = transmute(vcgezq_f32(transmute(a))); + unsafe fn test_vcvtp_u32_f32() { + let a: f32x2 = f32x2::new(1.1, 2.1); + let e: u32x2 = u32x2::new(2, 3); + let r: u32x2 = transmute(vcvtp_u32_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgez_f64() { - let a: f64 = -1.2; - let e: u64x1 = u64x1::new(0); - let r: u64x1 = transmute(vcgez_f64(transmute(a))); + unsafe fn test_vcvtpq_u32_f32() { + let a: f32x4 = f32x4::new(1.1, 2.1, 2.9, 3.9); + let e: u32x4 = u32x4::new(2, 3, 3, 4); + let r: u32x4 = transmute(vcvtpq_u32_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgezq_f64() { - let a: f64x2 = f64x2::new(-1.2, 0.0); - let e: u64x2 = u64x2::new(0, 0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x2 = transmute(vcgezq_f64(transmute(a))); + unsafe fn test_vcvtp_u64_f64() { + let a: f64 = 1.1; + let e: u64x1 = u64x1::new(2); + let r: u64x1 = transmute(vcvtp_u64_f64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcvtpq_u64_f64() { + let a: f64x2 = f64x2::new(1.1, 2.1); + let e: u64x2 = u64x2::new(2, 3); + let r: u64x2 = transmute(vcvtpq_u64_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgtz_s8() { - let a: i8x8 = i8x8::new(-128, -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05); - let e: u8x8 = u8x8::new(0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x8 = transmute(vcgtz_s8(transmute(a))); + unsafe fn test_vcvtps_u32_f32() { + let a: f32 = 1.1; + let e: u32 = 2; + let r: u32 = transmute(vcvtps_u32_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgtzq_s8() { - let a: i8x16 = i8x16::new(-128, -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x7F); - let e: u8x16 = u8x16::new(0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x16 = transmute(vcgtzq_s8(transmute(a))); + unsafe fn test_vcvtpd_u64_f64() { + let a: f64 = 1.1; + let e: u64 = 2; + let r: u64 = transmute(vcvtpd_u64_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgtz_s16() { - let a: i16x4 = i16x4::new(-32768, -1, 0x00, 0x01); - let e: u16x4 = u16x4::new(0, 0, 0, 0xFF_FF); - let r: u16x4 = transmute(vcgtz_s16(transmute(a))); + unsafe fn test_vdupq_laneq_p64() { + let a: i64x2 = i64x2::new(1, 1); + let e: i64x2 = i64x2::new(1, 1); + let r: i64x2 = transmute(vdupq_laneq_p64::<1>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgtzq_s16() { - let a: i16x8 = i16x8::new(-32768, -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05); - let e: u16x8 = u16x8::new(0, 0, 0, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); - let r: u16x8 = transmute(vcgtzq_s16(transmute(a))); + unsafe fn test_vdupq_lane_p64() { + let a: i64x1 = i64x1::new(1); + let e: i64x2 = i64x2::new(1, 1); + let r: i64x2 = transmute(vdupq_lane_p64::<0>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgtz_s32() { - let a: i32x2 = i32x2::new(-2147483648, -1); - let e: u32x2 = u32x2::new(0, 0); - let r: u32x2 = transmute(vcgtz_s32(transmute(a))); + unsafe fn test_vdupq_laneq_f64() { + let a: f64x2 = f64x2::new(1., 1.); + let e: f64x2 = f64x2::new(1., 1.); + let r: f64x2 = transmute(vdupq_laneq_f64::<1>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgtzq_s32() { - let a: i32x4 = i32x4::new(-2147483648, -1, 0x00, 0x01); - let e: u32x4 = u32x4::new(0, 0, 0, 0xFF_FF_FF_FF); - let r: u32x4 = transmute(vcgtzq_s32(transmute(a))); + unsafe fn test_vdupq_lane_f64() { + let a: f64 = 1.; + let e: f64x2 = f64x2::new(1., 1.); + let r: f64x2 = transmute(vdupq_lane_f64::<0>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgtz_s64() { - let a: i64x1 = i64x1::new(-9223372036854775808); - let e: u64x1 = u64x1::new(0); - let r: u64x1 = transmute(vcgtz_s64(transmute(a))); + unsafe fn test_vdup_lane_p64() { + let a: i64x1 = i64x1::new(0); + let e: i64x1 = i64x1::new(0); + let r: i64x1 = transmute(vdup_lane_p64::<0>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgtzq_s64() { - let a: i64x2 = i64x2::new(-9223372036854775808, -1); - let e: u64x2 = u64x2::new(0, 0); - let r: u64x2 = transmute(vcgtzq_s64(transmute(a))); + unsafe fn test_vdup_lane_f64() { + let a: f64 = 0.; + let e: f64 = 0.; + let r: f64 = transmute(vdup_lane_f64::<0>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgtz_f32() { - let a: f32x2 = f32x2::new(-1.2, 0.0); - let e: u32x2 = u32x2::new(0, 0); - let r: u32x2 = transmute(vcgtz_f32(transmute(a))); + unsafe fn test_vdup_laneq_p64() { + let a: i64x2 = i64x2::new(0, 1); + let e: i64x1 = i64x1::new(1); + let r: i64x1 = transmute(vdup_laneq_p64::<1>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgtzq_f32() { - let a: f32x4 = f32x4::new(-1.2, 0.0, 1.2, 2.3); - let e: u32x4 = u32x4::new(0, 0, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x4 = transmute(vcgtzq_f32(transmute(a))); + unsafe fn test_vdup_laneq_f64() { + let a: f64x2 = f64x2::new(0., 1.); + let e: f64 = 1.; + let r: f64 = transmute(vdup_laneq_f64::<1>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgtz_f64() { - let a: f64 = -1.2; - let e: u64x1 = u64x1::new(0); - let r: u64x1 = transmute(vcgtz_f64(transmute(a))); + unsafe fn test_vdupb_lane_s8() { + let a: i8x8 = i8x8::new(1, 1, 1, 4, 1, 6, 7, 8); + let e: i8 = 1; + let r: i8 = transmute(vdupb_lane_s8::<4>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgtzq_f64() { - let a: f64x2 = f64x2::new(-1.2, 0.0); - let e: u64x2 = u64x2::new(0, 0); - let r: u64x2 = transmute(vcgtzq_f64(transmute(a))); + unsafe fn test_vdupb_laneq_s8() { + let a: i8x16 = i8x16::new(1, 1, 1, 4, 1, 6, 7, 8, 1, 10, 11, 12, 13, 14, 15, 16); + let e: i8 = 1; + let r: i8 = transmute(vdupb_laneq_s8::<8>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclez_s8() { - let a: i8x8 = i8x8::new(-128, -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05); - let e: u8x8 = u8x8::new(0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0); - let r: u8x8 = transmute(vclez_s8(transmute(a))); + unsafe fn test_vduph_lane_s16() { + let a: i16x4 = i16x4::new(1, 1, 1, 4); + let e: i16 = 1; + let r: i16 = transmute(vduph_lane_s16::<2>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclezq_s8() { - let a: i8x16 = i8x16::new(-128, -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x7F); - let e: u8x16 = u8x16::new(0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - let r: u8x16 = transmute(vclezq_s8(transmute(a))); + unsafe fn test_vduph_laneq_s16() { + let a: i16x8 = i16x8::new(1, 1, 1, 4, 1, 6, 7, 8); + let e: i16 = 1; + let r: i16 = transmute(vduph_laneq_s16::<4>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclez_s16() { - let a: i16x4 = i16x4::new(-32768, -1, 0x00, 0x01); - let e: u16x4 = u16x4::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0); - let r: u16x4 = transmute(vclez_s16(transmute(a))); + unsafe fn test_vdups_lane_s32() { + let a: i32x2 = i32x2::new(1, 1); + let e: i32 = 1; + let r: i32 = transmute(vdups_lane_s32::<1>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclezq_s16() { - let a: i16x8 = i16x8::new(-32768, -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05); - let e: u16x8 = u16x8::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0, 0, 0, 0, 0); - let r: u16x8 = transmute(vclezq_s16(transmute(a))); + unsafe fn test_vdups_laneq_s32() { + let a: i32x4 = i32x4::new(1, 1, 1, 4); + let e: i32 = 1; + let r: i32 = transmute(vdups_laneq_s32::<2>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclez_s32() { - let a: i32x2 = i32x2::new(-2147483648, -1); - let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x2 = transmute(vclez_s32(transmute(a))); + unsafe fn test_vdupd_lane_s64() { + let a: i64x1 = i64x1::new(1); + let e: i64 = 1; + let r: i64 = transmute(vdupd_lane_s64::<0>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclezq_s32() { - let a: i32x4 = i32x4::new(-2147483648, -1, 0x00, 0x01); - let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0); - let r: u32x4 = transmute(vclezq_s32(transmute(a))); + unsafe fn test_vdupd_laneq_s64() { + let a: i64x2 = i64x2::new(1, 1); + let e: i64 = 1; + let r: i64 = transmute(vdupd_laneq_s64::<1>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclez_s64() { - let a: i64x1 = i64x1::new(-9223372036854775808); - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vclez_s64(transmute(a))); + unsafe fn test_vdupb_lane_u8() { + let a: u8x8 = u8x8::new(1, 1, 1, 4, 1, 6, 7, 8); + let e: u8 = 1; + let r: u8 = transmute(vdupb_lane_u8::<4>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclezq_s64() { - let a: i64x2 = i64x2::new(-9223372036854775808, -1); - let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x2 = transmute(vclezq_s64(transmute(a))); + unsafe fn test_vdupb_laneq_u8() { + let a: u8x16 = u8x16::new(1, 1, 1, 4, 1, 6, 7, 8, 1, 10, 11, 12, 13, 14, 15, 16); + let e: u8 = 1; + let r: u8 = transmute(vdupb_laneq_u8::<8>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclez_f32() { - let a: f32x2 = f32x2::new(-1.2, 0.0); - let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x2 = transmute(vclez_f32(transmute(a))); + unsafe fn test_vduph_lane_u16() { + let a: u16x4 = u16x4::new(1, 1, 1, 4); + let e: u16 = 1; + let r: u16 = transmute(vduph_lane_u16::<2>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclezq_f32() { - let a: f32x4 = f32x4::new(-1.2, 0.0, 1.2, 2.3); - let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0, 0); - let r: u32x4 = transmute(vclezq_f32(transmute(a))); + unsafe fn test_vduph_laneq_u16() { + let a: u16x8 = u16x8::new(1, 1, 1, 4, 1, 6, 7, 8); + let e: u16 = 1; + let r: u16 = transmute(vduph_laneq_u16::<4>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclez_f64() { - let a: f64 = -1.2; - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vclez_f64(transmute(a))); + unsafe fn test_vdups_lane_u32() { + let a: u32x2 = u32x2::new(1, 1); + let e: u32 = 1; + let r: u32 = transmute(vdups_lane_u32::<1>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclezq_f64() { - let a: f64x2 = f64x2::new(-1.2, 0.0); - let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x2 = transmute(vclezq_f64(transmute(a))); + unsafe fn test_vdups_laneq_u32() { + let a: u32x4 = u32x4::new(1, 1, 1, 4); + let e: u32 = 1; + let r: u32 = transmute(vdups_laneq_u32::<2>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcltz_s8() { - let a: i8x8 = i8x8::new(-128, -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05); - let e: u8x8 = u8x8::new(0xFF, 0xFF, 0, 0, 0, 0, 0, 0); - let r: u8x8 = transmute(vcltz_s8(transmute(a))); + unsafe fn test_vdupd_lane_u64() { + let a: u64x1 = u64x1::new(1); + let e: u64 = 1; + let r: u64 = transmute(vdupd_lane_u64::<0>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcltzq_s8() { - let a: i8x16 = i8x16::new(-128, -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x7F); - let e: u8x16 = u8x16::new(0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - let r: u8x16 = transmute(vcltzq_s8(transmute(a))); + unsafe fn test_vdupd_laneq_u64() { + let a: u64x2 = u64x2::new(1, 1); + let e: u64 = 1; + let r: u64 = transmute(vdupd_laneq_u64::<1>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcltz_s16() { - let a: i16x4 = i16x4::new(-32768, -1, 0x00, 0x01); - let e: u16x4 = u16x4::new(0xFF_FF, 0xFF_FF, 0, 0); - let r: u16x4 = transmute(vcltz_s16(transmute(a))); + unsafe fn test_vdupb_lane_p8() { + let a: i8x8 = i8x8::new(1, 1, 1, 4, 1, 6, 7, 8); + let e: p8 = 1; + let r: p8 = transmute(vdupb_lane_p8::<4>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcltzq_s16() { - let a: i16x8 = i16x8::new(-32768, -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05); - let e: u16x8 = u16x8::new(0xFF_FF, 0xFF_FF, 0, 0, 0, 0, 0, 0); - let r: u16x8 = transmute(vcltzq_s16(transmute(a))); + unsafe fn test_vdupb_laneq_p8() { + let a: i8x16 = i8x16::new(1, 1, 1, 4, 1, 6, 7, 8, 1, 10, 11, 12, 13, 14, 15, 16); + let e: p8 = 1; + let r: p8 = transmute(vdupb_laneq_p8::<8>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcltz_s32() { - let a: i32x2 = i32x2::new(-2147483648, -1); - let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x2 = transmute(vcltz_s32(transmute(a))); + unsafe fn test_vduph_lane_p16() { + let a: i16x4 = i16x4::new(1, 1, 1, 4); + let e: p16 = 1; + let r: p16 = transmute(vduph_lane_p16::<2>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcltzq_s32() { - let a: i32x4 = i32x4::new(-2147483648, -1, 0x00, 0x01); - let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0, 0); - let r: u32x4 = transmute(vcltzq_s32(transmute(a))); + unsafe fn test_vduph_laneq_p16() { + let a: i16x8 = i16x8::new(1, 1, 1, 4, 1, 6, 7, 8); + let e: p16 = 1; + let r: p16 = transmute(vduph_laneq_p16::<4>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcltz_s64() { - let a: i64x1 = i64x1::new(-9223372036854775808); - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vcltz_s64(transmute(a))); + unsafe fn test_vdups_lane_f32() { + let a: f32x2 = f32x2::new(1., 1.); + let e: f32 = 1.; + let r: f32 = transmute(vdups_lane_f32::<1>(transmute(a))); assert_eq!(r, e); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vcltzq_s64() { - let a: i64x2 = i64x2::new(-9223372036854775808, -1); - let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x2 = transmute(vcltzq_s64(transmute(a))); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdups_laneq_f32() { + let a: f32x4 = f32x4::new(1., 1., 1., 4.); + let e: f32 = 1.; + let r: f32 = transmute(vdups_laneq_f32::<2>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcltz_f32() { - let a: f32x2 = f32x2::new(-1.2, 0.0); - let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0); - let r: u32x2 = transmute(vcltz_f32(transmute(a))); + unsafe fn test_vdupd_lane_f64() { + let a: f64 = 1.; + let e: f64 = 1.; + let r: f64 = transmute(vdupd_lane_f64::<0>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcltzq_f32() { - let a: f32x4 = f32x4::new(-1.2, 0.0, 1.2, 2.3); - let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0, 0, 0); - let r: u32x4 = transmute(vcltzq_f32(transmute(a))); + unsafe fn test_vdupd_laneq_f64() { + let a: f64x2 = f64x2::new(1., 1.); + let e: f64 = 1.; + let r: f64 = transmute(vdupd_laneq_f64::<1>(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcltz_f64() { - let a: f64 = -1.2; - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vcltz_f64(transmute(a))); + unsafe fn test_vextq_p64() { + let a: i64x2 = i64x2::new(0, 8); + let b: i64x2 = i64x2::new(9, 11); + let e: i64x2 = i64x2::new(8, 9); + let r: i64x2 = transmute(vextq_p64::<1>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcltzq_f64() { - let a: f64x2 = f64x2::new(-1.2, 0.0); - let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0); - let r: u64x2 = transmute(vcltzq_f64(transmute(a))); + unsafe fn test_vextq_f64() { + let a: f64x2 = f64x2::new(0., 2.); + let b: f64x2 = f64x2::new(3., 4.); + let e: f64x2 = f64x2::new(2., 3.); + let r: f64x2 = transmute(vextq_f64::<1>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcagt_f64() { - let a: f64 = -1.2; - let b: f64 = -1.1; - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vcagt_f64(transmute(a), transmute(b))); + unsafe fn test_vmla_f64() { + let a: f64 = 0.; + let b: f64 = 2.; + let c: f64 = 3.; + let e: f64 = 6.; + let r: f64 = transmute(vmla_f64(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcagtq_f64() { - let a: f64x2 = f64x2::new(-1.2, 0.0); - let b: f64x2 = f64x2::new(-1.1, 0.0); - let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0); - let r: u64x2 = transmute(vcagtq_f64(transmute(a), transmute(b))); + unsafe fn test_vmlaq_f64() { + let a: f64x2 = f64x2::new(0., 1.); + let b: f64x2 = f64x2::new(2., 2.); + let c: f64x2 = f64x2::new(3., 3.); + let e: f64x2 = f64x2::new(6., 7.); + let r: f64x2 = transmute(vmlaq_f64(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcage_f64() { - let a: f64 = -1.2; - let b: f64 = -1.1; - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vcage_f64(transmute(a), transmute(b))); + unsafe fn test_vmlal_high_s8() { + let a: i16x8 = i16x8::new(8, 7, 6, 5, 4, 3, 2, 1); + let b: i8x16 = i8x16::new(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); + let c: i8x16 = i8x16::new(3, 3, 0, 1, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7); + let e: i16x8 = i16x8::new(8, 9, 10, 11, 12, 13, 14, 15); + let r: i16x8 = transmute(vmlal_high_s8(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcageq_f64() { - let a: f64x2 = f64x2::new(-1.2, 0.0); - let b: f64x2 = f64x2::new(-1.1, 0.0); - let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x2 = transmute(vcageq_f64(transmute(a), transmute(b))); + unsafe fn test_vmlal_high_s16() { + let a: i32x4 = i32x4::new(8, 7, 6, 5); + let b: i16x8 = i16x8::new(2, 2, 2, 2, 2, 2, 2, 2); + let c: i16x8 = i16x8::new(3, 3, 0, 1, 0, 1, 2, 3); + let e: i32x4 = i32x4::new(8, 9, 10, 11); + let r: i32x4 = transmute(vmlal_high_s16(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcalt_f64() { - let a: f64 = -1.2; - let b: f64 = -1.1; - let e: u64x1 = u64x1::new(0); - let r: u64x1 = transmute(vcalt_f64(transmute(a), transmute(b))); + unsafe fn test_vmlal_high_s32() { + let a: i64x2 = i64x2::new(8, 7); + let b: i32x4 = i32x4::new(2, 2, 2, 2); + let c: i32x4 = i32x4::new(3, 3, 0, 1); + let e: i64x2 = i64x2::new(8, 9); + let r: i64x2 = transmute(vmlal_high_s32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcaltq_f64() { - let a: f64x2 = f64x2::new(-1.2, 0.0); - let b: f64x2 = f64x2::new(-1.1, 0.0); - let e: u64x2 = u64x2::new(0, 0); - let r: u64x2 = transmute(vcaltq_f64(transmute(a), transmute(b))); + unsafe fn test_vmlal_high_u8() { + let a: u16x8 = u16x8::new(8, 7, 6, 5, 4, 3, 2, 1); + let b: u8x16 = u8x16::new(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); + let c: u8x16 = u8x16::new(3, 3, 0, 1, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7); + let e: u16x8 = u16x8::new(8, 9, 10, 11, 12, 13, 14, 15); + let r: u16x8 = transmute(vmlal_high_u8(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcale_f64() { - let a: f64 = -1.2; - let b: f64 = -1.1; - let e: u64x1 = u64x1::new(0); - let r: u64x1 = transmute(vcale_f64(transmute(a), transmute(b))); + unsafe fn test_vmlal_high_u16() { + let a: u32x4 = u32x4::new(8, 7, 6, 5); + let b: u16x8 = u16x8::new(2, 2, 2, 2, 2, 2, 2, 2); + let c: u16x8 = u16x8::new(3, 3, 0, 1, 0, 1, 2, 3); + let e: u32x4 = u32x4::new(8, 9, 10, 11); + let r: u32x4 = transmute(vmlal_high_u16(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcaleq_f64() { - let a: f64x2 = f64x2::new(-1.2, 0.0); - let b: f64x2 = f64x2::new(-1.1, 0.0); - let e: u64x2 = u64x2::new(0, 0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x2 = transmute(vcaleq_f64(transmute(a), transmute(b))); + unsafe fn test_vmlal_high_u32() { + let a: u64x2 = u64x2::new(8, 7); + let b: u32x4 = u32x4::new(2, 2, 2, 2); + let c: u32x4 = u32x4::new(3, 3, 0, 1); + let e: u64x2 = u64x2::new(8, 9); + let r: u64x2 = transmute(vmlal_high_u32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_lane_s8() { - let a: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let b: i8x8 = i8x8::new(0, 0x7F, 0, 0, 0, 0, 0, 0); - let e: i8x8 = i8x8::new(0x7F, 2, 3, 4, 5, 6, 7, 8); - let r: i8x8 = transmute(vcopy_lane_s8::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmlal_high_n_s16() { + let a: i32x4 = i32x4::new(8, 7, 6, 5); + let b: i16x8 = i16x8::new(3, 3, 0, 1, 0, 1, 2, 3); + let c: i16 = 2; + let e: i32x4 = i32x4::new(8, 9, 10, 11); + let r: i32x4 = transmute(vmlal_high_n_s16(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopyq_laneq_s8() { - let a: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let b: i8x16 = i8x16::new(0, 0x7F, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - let e: i8x16 = i8x16::new(0x7F, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let r: i8x16 = transmute(vcopyq_laneq_s8::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmlal_high_n_s32() { + let a: i64x2 = i64x2::new(8, 7); + let b: i32x4 = i32x4::new(3, 3, 0, 1); + let c: i32 = 2; + let e: i64x2 = i64x2::new(8, 9); + let r: i64x2 = transmute(vmlal_high_n_s32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_lane_s16() { - let a: i16x4 = i16x4::new(1, 2, 3, 4); - let b: i16x4 = i16x4::new(0, 0x7F_FF, 0, 0); - let e: i16x4 = i16x4::new(0x7F_FF, 2, 3, 4); - let r: i16x4 = transmute(vcopy_lane_s16::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmlal_high_n_u16() { + let a: u32x4 = u32x4::new(8, 7, 6, 5); + let b: u16x8 = u16x8::new(3, 3, 0, 1, 0, 1, 2, 3); + let c: u16 = 2; + let e: u32x4 = u32x4::new(8, 9, 10, 11); + let r: u32x4 = transmute(vmlal_high_n_u16(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopyq_laneq_s16() { - let a: i16x8 = i16x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let b: i16x8 = i16x8::new(0, 0x7F_FF, 0, 0, 0, 0, 0, 0); - let e: i16x8 = i16x8::new(0x7F_FF, 2, 3, 4, 5, 6, 7, 8); - let r: i16x8 = transmute(vcopyq_laneq_s16::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmlal_high_n_u32() { + let a: u64x2 = u64x2::new(8, 7); + let b: u32x4 = u32x4::new(3, 3, 0, 1); + let c: u32 = 2; + let e: u64x2 = u64x2::new(8, 9); + let r: u64x2 = transmute(vmlal_high_n_u32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_lane_s32() { - let a: i32x2 = i32x2::new(1, 2); - let b: i32x2 = i32x2::new(0, 0x7F_FF_FF_FF); - let e: i32x2 = i32x2::new(0x7F_FF_FF_FF, 2); - let r: i32x2 = transmute(vcopy_lane_s32::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmlal_high_lane_s16() { + let a: i32x4 = i32x4::new(8, 7, 6, 5); + let b: i16x8 = i16x8::new(3, 3, 0, 1, 0, 1, 2, 3); + let c: i16x4 = i16x4::new(0, 2, 0, 0); + let e: i32x4 = i32x4::new(8, 9, 10, 11); + let r: i32x4 = transmute(vmlal_high_lane_s16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopyq_laneq_s32() { - let a: i32x4 = i32x4::new(1, 2, 3, 4); - let b: i32x4 = i32x4::new(0, 0x7F_FF_FF_FF, 0, 0); - let e: i32x4 = i32x4::new(0x7F_FF_FF_FF, 2, 3, 4); - let r: i32x4 = transmute(vcopyq_laneq_s32::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmlal_high_laneq_s16() { + let a: i32x4 = i32x4::new(8, 7, 6, 5); + let b: i16x8 = i16x8::new(3, 3, 0, 1, 0, 1, 2, 3); + let c: i16x8 = i16x8::new(0, 2, 0, 0, 0, 0, 0, 0); + let e: i32x4 = i32x4::new(8, 9, 10, 11); + let r: i32x4 = transmute(vmlal_high_laneq_s16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopyq_laneq_s64() { - let a: i64x2 = i64x2::new(1, 2); - let b: i64x2 = i64x2::new(0, 0x7F_FF_FF_FF_FF_FF_FF_FF); - let e: i64x2 = i64x2::new(0x7F_FF_FF_FF_FF_FF_FF_FF, 2); - let r: i64x2 = transmute(vcopyq_laneq_s64::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmlal_high_lane_s32() { + let a: i64x2 = i64x2::new(8, 7); + let b: i32x4 = i32x4::new(3, 3, 0, 1); + let c: i32x2 = i32x2::new(0, 2); + let e: i64x2 = i64x2::new(8, 9); + let r: i64x2 = transmute(vmlal_high_lane_s32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_lane_u8() { - let a: u8x8 = u8x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let b: u8x8 = u8x8::new(0, 0xFF, 0, 0, 0, 0, 0, 0); - let e: u8x8 = u8x8::new(0xFF, 2, 3, 4, 5, 6, 7, 8); - let r: u8x8 = transmute(vcopy_lane_u8::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmlal_high_laneq_s32() { + let a: i64x2 = i64x2::new(8, 7); + let b: i32x4 = i32x4::new(3, 3, 0, 1); + let c: i32x4 = i32x4::new(0, 2, 0, 0); + let e: i64x2 = i64x2::new(8, 9); + let r: i64x2 = transmute(vmlal_high_laneq_s32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopyq_laneq_u8() { - let a: u8x16 = u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let b: u8x16 = u8x16::new(0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - let e: u8x16 = u8x16::new(0xFF, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let r: u8x16 = transmute(vcopyq_laneq_u8::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmlal_high_lane_u16() { + let a: u32x4 = u32x4::new(8, 7, 6, 5); + let b: u16x8 = u16x8::new(3, 3, 0, 1, 0, 1, 2, 3); + let c: u16x4 = u16x4::new(0, 2, 0, 0); + let e: u32x4 = u32x4::new(8, 9, 10, 11); + let r: u32x4 = transmute(vmlal_high_lane_u16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_lane_u16() { - let a: u16x4 = u16x4::new(1, 2, 3, 4); - let b: u16x4 = u16x4::new(0, 0xFF_FF, 0, 0); - let e: u16x4 = u16x4::new(0xFF_FF, 2, 3, 4); - let r: u16x4 = transmute(vcopy_lane_u16::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmlal_high_laneq_u16() { + let a: u32x4 = u32x4::new(8, 7, 6, 5); + let b: u16x8 = u16x8::new(3, 3, 0, 1, 0, 1, 2, 3); + let c: u16x8 = u16x8::new(0, 2, 0, 0, 0, 0, 0, 0); + let e: u32x4 = u32x4::new(8, 9, 10, 11); + let r: u32x4 = transmute(vmlal_high_laneq_u16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopyq_laneq_u16() { - let a: u16x8 = u16x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let b: u16x8 = u16x8::new(0, 0xFF_FF, 0, 0, 0, 0, 0, 0); - let e: u16x8 = u16x8::new(0xFF_FF, 2, 3, 4, 5, 6, 7, 8); - let r: u16x8 = transmute(vcopyq_laneq_u16::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmlal_high_lane_u32() { + let a: u64x2 = u64x2::new(8, 7); + let b: u32x4 = u32x4::new(3, 3, 0, 1); + let c: u32x2 = u32x2::new(0, 2); + let e: u64x2 = u64x2::new(8, 9); + let r: u64x2 = transmute(vmlal_high_lane_u32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_lane_u32() { - let a: u32x2 = u32x2::new(1, 2); - let b: u32x2 = u32x2::new(0, 0xFF_FF_FF_FF); - let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 2); - let r: u32x2 = transmute(vcopy_lane_u32::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmlal_high_laneq_u32() { + let a: u64x2 = u64x2::new(8, 7); + let b: u32x4 = u32x4::new(3, 3, 0, 1); + let c: u32x4 = u32x4::new(0, 2, 0, 0); + let e: u64x2 = u64x2::new(8, 9); + let r: u64x2 = transmute(vmlal_high_laneq_u32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopyq_laneq_u32() { - let a: u32x4 = u32x4::new(1, 2, 3, 4); - let b: u32x4 = u32x4::new(0, 0xFF_FF_FF_FF, 0, 0); - let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 2, 3, 4); - let r: u32x4 = transmute(vcopyq_laneq_u32::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmls_f64() { + let a: f64 = 6.; + let b: f64 = 2.; + let c: f64 = 3.; + let e: f64 = 0.; + let r: f64 = transmute(vmls_f64(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopyq_laneq_u64() { - let a: u64x2 = u64x2::new(1, 2); - let b: u64x2 = u64x2::new(0, 0xFF_FF_FF_FF_FF_FF_FF_FF); - let e: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 2); - let r: u64x2 = transmute(vcopyq_laneq_u64::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmlsq_f64() { + let a: f64x2 = f64x2::new(6., 7.); + let b: f64x2 = f64x2::new(2., 2.); + let c: f64x2 = f64x2::new(3., 3.); + let e: f64x2 = f64x2::new(0., 1.); + let r: f64x2 = transmute(vmlsq_f64(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_lane_p8() { - let a: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let b: i8x8 = i8x8::new(0, 0x7F, 0, 0, 0, 0, 0, 0); - let e: i8x8 = i8x8::new(0x7F, 2, 3, 4, 5, 6, 7, 8); - let r: i8x8 = transmute(vcopy_lane_p8::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmlsl_high_s8() { + let a: i16x8 = i16x8::new(14, 15, 16, 17, 18, 19, 20, 21); + let b: i8x16 = i8x16::new(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); + let c: i8x16 = i8x16::new(3, 3, 0, 1, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7); + let e: i16x8 = i16x8::new(14, 13, 12, 11, 10, 9, 8, 7); + let r: i16x8 = transmute(vmlsl_high_s8(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopyq_laneq_p8() { - let a: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let b: i8x16 = i8x16::new(0, 0x7F, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - let e: i8x16 = i8x16::new(0x7F, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let r: i8x16 = transmute(vcopyq_laneq_p8::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmlsl_high_s16() { + let a: i32x4 = i32x4::new(14, 15, 16, 17); + let b: i16x8 = i16x8::new(2, 2, 2, 2, 2, 2, 2, 2); + let c: i16x8 = i16x8::new(3, 3, 0, 1, 0, 1, 2, 3); + let e: i32x4 = i32x4::new(14, 13, 12, 11); + let r: i32x4 = transmute(vmlsl_high_s16(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_lane_p16() { - let a: i16x4 = i16x4::new(1, 2, 3, 4); - let b: i16x4 = i16x4::new(0, 0x7F_FF, 0, 0); - let e: i16x4 = i16x4::new(0x7F_FF, 2, 3, 4); - let r: i16x4 = transmute(vcopy_lane_p16::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmlsl_high_s32() { + let a: i64x2 = i64x2::new(14, 15); + let b: i32x4 = i32x4::new(2, 2, 2, 2); + let c: i32x4 = i32x4::new(3, 3, 0, 1); + let e: i64x2 = i64x2::new(14, 13); + let r: i64x2 = transmute(vmlsl_high_s32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopyq_laneq_p16() { - let a: i16x8 = i16x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let b: i16x8 = i16x8::new(0, 0x7F_FF, 0, 0, 0, 0, 0, 0); - let e: i16x8 = i16x8::new(0x7F_FF, 2, 3, 4, 5, 6, 7, 8); - let r: i16x8 = transmute(vcopyq_laneq_p16::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmlsl_high_u8() { + let a: u16x8 = u16x8::new(14, 15, 16, 17, 18, 19, 20, 21); + let b: u8x16 = u8x16::new(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); + let c: u8x16 = u8x16::new(3, 3, 0, 1, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7); + let e: u16x8 = u16x8::new(14, 13, 12, 11, 10, 9, 8, 7); + let r: u16x8 = transmute(vmlsl_high_u8(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopyq_laneq_p64() { - let a: i64x2 = i64x2::new(1, 2); - let b: i64x2 = i64x2::new(0, 0x7F_FF_FF_FF_FF_FF_FF_FF); - let e: i64x2 = i64x2::new(0x7F_FF_FF_FF_FF_FF_FF_FF, 2); - let r: i64x2 = transmute(vcopyq_laneq_p64::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmlsl_high_u16() { + let a: u32x4 = u32x4::new(14, 15, 16, 17); + let b: u16x8 = u16x8::new(2, 2, 2, 2, 2, 2, 2, 2); + let c: u16x8 = u16x8::new(3, 3, 0, 1, 0, 1, 2, 3); + let e: u32x4 = u32x4::new(14, 13, 12, 11); + let r: u32x4 = transmute(vmlsl_high_u16(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_lane_f32() { - let a: f32x2 = f32x2::new(1., 2.); - let b: f32x2 = f32x2::new(0., 0.5); - let e: f32x2 = f32x2::new(0.5, 2.); - let r: f32x2 = transmute(vcopy_lane_f32::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmlsl_high_u32() { + let a: u64x2 = u64x2::new(14, 15); + let b: u32x4 = u32x4::new(2, 2, 2, 2); + let c: u32x4 = u32x4::new(3, 3, 0, 1); + let e: u64x2 = u64x2::new(14, 13); + let r: u64x2 = transmute(vmlsl_high_u32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopyq_laneq_f32() { - let a: f32x4 = f32x4::new(1., 2., 3., 4.); - let b: f32x4 = f32x4::new(0., 0.5, 0., 0.); - let e: f32x4 = f32x4::new(0.5, 2., 3., 4.); - let r: f32x4 = transmute(vcopyq_laneq_f32::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmlsl_high_n_s16() { + let a: i32x4 = i32x4::new(14, 15, 16, 17); + let b: i16x8 = i16x8::new(3, 3, 0, 1, 0, 1, 2, 3); + let c: i16 = 2; + let e: i32x4 = i32x4::new(14, 13, 12, 11); + let r: i32x4 = transmute(vmlsl_high_n_s16(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopyq_laneq_f64() { - let a: f64x2 = f64x2::new(1., 2.); - let b: f64x2 = f64x2::new(0., 0.5); - let e: f64x2 = f64x2::new(0.5, 2.); - let r: f64x2 = transmute(vcopyq_laneq_f64::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmlsl_high_n_s32() { + let a: i64x2 = i64x2::new(14, 15); + let b: i32x4 = i32x4::new(3, 3, 0, 1); + let c: i32 = 2; + let e: i64x2 = i64x2::new(14, 13); + let r: i64x2 = transmute(vmlsl_high_n_s32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_laneq_s8() { - let a: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let b: i8x16 = i8x16::new(0, 0x7F, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - let e: i8x8 = i8x8::new(0x7F, 2, 3, 4, 5, 6, 7, 8); - let r: i8x8 = transmute(vcopy_laneq_s8::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmlsl_high_n_u16() { + let a: u32x4 = u32x4::new(14, 15, 16, 17); + let b: u16x8 = u16x8::new(3, 3, 0, 1, 0, 1, 2, 3); + let c: u16 = 2; + let e: u32x4 = u32x4::new(14, 13, 12, 11); + let r: u32x4 = transmute(vmlsl_high_n_u16(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_laneq_s16() { - let a: i16x4 = i16x4::new(1, 2, 3, 4); - let b: i16x8 = i16x8::new(0, 0x7F_FF, 0, 0, 0, 0, 0, 0); - let e: i16x4 = i16x4::new(0x7F_FF, 2, 3, 4); - let r: i16x4 = transmute(vcopy_laneq_s16::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmlsl_high_n_u32() { + let a: u64x2 = u64x2::new(14, 15); + let b: u32x4 = u32x4::new(3, 3, 0, 1); + let c: u32 = 2; + let e: u64x2 = u64x2::new(14, 13); + let r: u64x2 = transmute(vmlsl_high_n_u32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_laneq_s32() { - let a: i32x2 = i32x2::new(1, 2); - let b: i32x4 = i32x4::new(0, 0x7F_FF_FF_FF, 0, 0); - let e: i32x2 = i32x2::new(0x7F_FF_FF_FF, 2); - let r: i32x2 = transmute(vcopy_laneq_s32::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmlsl_high_lane_s16() { + let a: i32x4 = i32x4::new(14, 15, 16, 17); + let b: i16x8 = i16x8::new(3, 3, 0, 1, 0, 1, 2, 3); + let c: i16x4 = i16x4::new(0, 2, 0, 0); + let e: i32x4 = i32x4::new(14, 13, 12, 11); + let r: i32x4 = transmute(vmlsl_high_lane_s16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_laneq_u8() { - let a: u8x8 = u8x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let b: u8x16 = u8x16::new(0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - let e: u8x8 = u8x8::new(0xFF, 2, 3, 4, 5, 6, 7, 8); - let r: u8x8 = transmute(vcopy_laneq_u8::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmlsl_high_laneq_s16() { + let a: i32x4 = i32x4::new(14, 15, 16, 17); + let b: i16x8 = i16x8::new(3, 3, 0, 1, 0, 1, 2, 3); + let c: i16x8 = i16x8::new(0, 2, 0, 0, 0, 0, 0, 0); + let e: i32x4 = i32x4::new(14, 13, 12, 11); + let r: i32x4 = transmute(vmlsl_high_laneq_s16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_laneq_u16() { - let a: u16x4 = u16x4::new(1, 2, 3, 4); - let b: u16x8 = u16x8::new(0, 0xFF_FF, 0, 0, 0, 0, 0, 0); - let e: u16x4 = u16x4::new(0xFF_FF, 2, 3, 4); - let r: u16x4 = transmute(vcopy_laneq_u16::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmlsl_high_lane_s32() { + let a: i64x2 = i64x2::new(14, 15); + let b: i32x4 = i32x4::new(3, 3, 0, 1); + let c: i32x2 = i32x2::new(0, 2); + let e: i64x2 = i64x2::new(14, 13); + let r: i64x2 = transmute(vmlsl_high_lane_s32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_laneq_u32() { - let a: u32x2 = u32x2::new(1, 2); - let b: u32x4 = u32x4::new(0, 0xFF_FF_FF_FF, 0, 0); - let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 2); - let r: u32x2 = transmute(vcopy_laneq_u32::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmlsl_high_laneq_s32() { + let a: i64x2 = i64x2::new(14, 15); + let b: i32x4 = i32x4::new(3, 3, 0, 1); + let c: i32x4 = i32x4::new(0, 2, 0, 0); + let e: i64x2 = i64x2::new(14, 13); + let r: i64x2 = transmute(vmlsl_high_laneq_s32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_laneq_p8() { - let a: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let b: i8x16 = i8x16::new(0, 0x7F, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - let e: i8x8 = i8x8::new(0x7F, 2, 3, 4, 5, 6, 7, 8); - let r: i8x8 = transmute(vcopy_laneq_p8::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmlsl_high_lane_u16() { + let a: u32x4 = u32x4::new(14, 15, 16, 17); + let b: u16x8 = u16x8::new(3, 3, 0, 1, 0, 1, 2, 3); + let c: u16x4 = u16x4::new(0, 2, 0, 0); + let e: u32x4 = u32x4::new(14, 13, 12, 11); + let r: u32x4 = transmute(vmlsl_high_lane_u16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_laneq_p16() { - let a: i16x4 = i16x4::new(1, 2, 3, 4); - let b: i16x8 = i16x8::new(0, 0x7F_FF, 0, 0, 0, 0, 0, 0); - let e: i16x4 = i16x4::new(0x7F_FF, 2, 3, 4); - let r: i16x4 = transmute(vcopy_laneq_p16::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmlsl_high_laneq_u16() { + let a: u32x4 = u32x4::new(14, 15, 16, 17); + let b: u16x8 = u16x8::new(3, 3, 0, 1, 0, 1, 2, 3); + let c: u16x8 = u16x8::new(0, 2, 0, 0, 0, 0, 0, 0); + let e: u32x4 = u32x4::new(14, 13, 12, 11); + let r: u32x4 = transmute(vmlsl_high_laneq_u16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_laneq_f32() { - let a: f32x2 = f32x2::new(1., 2.); - let b: f32x4 = f32x4::new(0., 0.5, 0., 0.); - let e: f32x2 = f32x2::new(0.5, 2.); - let r: f32x2 = transmute(vcopy_laneq_f32::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmlsl_high_lane_u32() { + let a: u64x2 = u64x2::new(14, 15); + let b: u32x4 = u32x4::new(3, 3, 0, 1); + let c: u32x2 = u32x2::new(0, 2); + let e: u64x2 = u64x2::new(14, 13); + let r: u64x2 = transmute(vmlsl_high_lane_u32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopyq_lane_s8() { - let a: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let b: i8x8 = i8x8::new(0, 0x7F, 0, 0, 0, 0, 0, 0); - let e: i8x16 = i8x16::new(0x7F, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let r: i8x16 = transmute(vcopyq_lane_s8::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmlsl_high_laneq_u32() { + let a: u64x2 = u64x2::new(14, 15); + let b: u32x4 = u32x4::new(3, 3, 0, 1); + let c: u32x4 = u32x4::new(0, 2, 0, 0); + let e: u64x2 = u64x2::new(14, 13); + let r: u64x2 = transmute(vmlsl_high_laneq_u32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopyq_lane_s16() { - let a: i16x8 = i16x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let b: i16x4 = i16x4::new(0, 0x7F_FF, 0, 0); - let e: i16x8 = i16x8::new(0x7F_FF, 2, 3, 4, 5, 6, 7, 8); - let r: i16x8 = transmute(vcopyq_lane_s16::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmovn_high_s16() { + let a: i8x8 = i8x8::new(0, 1, 2, 3, 2, 3, 4, 5); + let b: i16x8 = i16x8::new(2, 3, 4, 5, 12, 13, 14, 15); + let e: i8x16 = i8x16::new(0, 1, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 12, 13, 14, 15); + let r: i8x16 = transmute(vmovn_high_s16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopyq_lane_s32() { - let a: i32x4 = i32x4::new(1, 2, 3, 4); - let b: i32x2 = i32x2::new(0, 0x7F_FF_FF_FF); - let e: i32x4 = i32x4::new(0x7F_FF_FF_FF, 2, 3, 4); - let r: i32x4 = transmute(vcopyq_lane_s32::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmovn_high_s32() { + let a: i16x4 = i16x4::new(0, 1, 2, 3); + let b: i32x4 = i32x4::new(2, 3, 4, 5); + let e: i16x8 = i16x8::new(0, 1, 2, 3, 2, 3, 4, 5); + let r: i16x8 = transmute(vmovn_high_s32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopyq_lane_u8() { - let a: u8x16 = u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let b: u8x8 = u8x8::new(0, 0xFF, 0, 0, 0, 0, 0, 0); - let e: u8x16 = u8x16::new(0xFF, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let r: u8x16 = transmute(vcopyq_lane_u8::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmovn_high_s64() { + let a: i32x2 = i32x2::new(0, 1); + let b: i64x2 = i64x2::new(2, 3); + let e: i32x4 = i32x4::new(0, 1, 2, 3); + let r: i32x4 = transmute(vmovn_high_s64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmovn_high_u16() { + let a: u8x8 = u8x8::new(0, 1, 2, 3, 2, 3, 4, 5); + let b: u16x8 = u16x8::new(2, 3, 4, 5, 12, 13, 14, 15); + let e: u8x16 = u8x16::new(0, 1, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 12, 13, 14, 15); + let r: u8x16 = transmute(vmovn_high_u16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopyq_lane_u16() { - let a: u16x8 = u16x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let b: u16x4 = u16x4::new(0, 0xFF_FF, 0, 0); - let e: u16x8 = u16x8::new(0xFF_FF, 2, 3, 4, 5, 6, 7, 8); - let r: u16x8 = transmute(vcopyq_lane_u16::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmovn_high_u32() { + let a: u16x4 = u16x4::new(0, 1, 2, 3); + let b: u32x4 = u32x4::new(2, 3, 4, 5); + let e: u16x8 = u16x8::new(0, 1, 2, 3, 2, 3, 4, 5); + let r: u16x8 = transmute(vmovn_high_u32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopyq_lane_u32() { - let a: u32x4 = u32x4::new(1, 2, 3, 4); - let b: u32x2 = u32x2::new(0, 0xFF_FF_FF_FF); - let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 2, 3, 4); - let r: u32x4 = transmute(vcopyq_lane_u32::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vmovn_high_u64() { + let a: u32x2 = u32x2::new(0, 1); + let b: u64x2 = u64x2::new(2, 3); + let e: u32x4 = u32x4::new(0, 1, 2, 3); + let r: u32x4 = transmute(vmovn_high_u64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopyq_lane_p8() { - let a: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let b: i8x8 = i8x8::new(0, 0x7F, 0, 0, 0, 0, 0, 0); - let e: i8x16 = i8x16::new(0x7F, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let r: i8x16 = transmute(vcopyq_lane_p8::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vneg_s64() { + let a: i64x1 = i64x1::new(0); + let e: i64x1 = i64x1::new(0); + let r: i64x1 = transmute(vneg_s64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopyq_lane_p16() { - let a: i16x8 = i16x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let b: i16x4 = i16x4::new(0, 0x7F_FF, 0, 0); - let e: i16x8 = i16x8::new(0x7F_FF, 2, 3, 4, 5, 6, 7, 8); - let r: i16x8 = transmute(vcopyq_lane_p16::<0, 1>(transmute(a), transmute(b))); + unsafe fn test_vnegq_s64() { + let a: i64x2 = i64x2::new(0, 1); + let e: i64x2 = i64x2::new(0, -1); + let r: i64x2 = transmute(vnegq_s64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopyq_lane_s64() { - let a: i64x2 = i64x2::new(1, 2); - let b: i64x1 = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); - let e: i64x2 = i64x2::new(1, 0x7F_FF_FF_FF_FF_FF_FF_FF); - let r: i64x2 = transmute(vcopyq_lane_s64::<1, 0>(transmute(a), transmute(b))); + unsafe fn test_vnegd_s64() { + let a: i64 = 1; + let e: i64 = -1; + let r: i64 = transmute(vnegd_s64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopyq_lane_u64() { - let a: u64x2 = u64x2::new(1, 2); - let b: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let e: u64x2 = u64x2::new(1, 0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x2 = transmute(vcopyq_lane_u64::<1, 0>(transmute(a), transmute(b))); + unsafe fn test_vneg_f64() { + let a: f64 = 0.; + let e: f64 = 0.; + let r: f64 = transmute(vneg_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopyq_lane_p64() { - let a: i64x2 = i64x2::new(1, 2); - let b: i64x1 = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); - let e: i64x2 = i64x2::new(1, 0x7F_FF_FF_FF_FF_FF_FF_FF); - let r: i64x2 = transmute(vcopyq_lane_p64::<1, 0>(transmute(a), transmute(b))); + unsafe fn test_vnegq_f64() { + let a: f64x2 = f64x2::new(0., 1.); + let e: f64x2 = f64x2::new(0., -1.); + let r: f64x2 = transmute(vnegq_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopyq_lane_f32() { - let a: f32x4 = f32x4::new(1., 2., 3., 4.); - let b: f32x2 = f32x2::new(0.5, 0.); - let e: f32x4 = f32x4::new(1., 0.5, 3., 4.); - let r: f32x4 = transmute(vcopyq_lane_f32::<1, 0>(transmute(a), transmute(b))); + unsafe fn test_vqneg_s64() { + let a: i64x1 = i64x1::new(-9223372036854775808); + let e: i64x1 = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); + let r: i64x1 = transmute(vqneg_s64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopyq_lane_f64() { - let a: f64x2 = f64x2::new(1., 2.); - let b: f64 = 0.5; - let e: f64x2 = f64x2::new(1., 0.5); - let r: f64x2 = transmute(vcopyq_lane_f64::<1, 0>(transmute(a), transmute(b))); + unsafe fn test_vqnegq_s64() { + let a: i64x2 = i64x2::new(-9223372036854775808, 0); + let e: i64x2 = i64x2::new(0x7F_FF_FF_FF_FF_FF_FF_FF, 0); + let r: i64x2 = transmute(vqnegq_s64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcreate_f64() { - let a: u64 = 0; - let e: f64 = 0.; - let r: f64 = transmute(vcreate_f64(transmute(a))); + unsafe fn test_vqnegb_s8() { + let a: i8 = 1; + let e: i8 = -1; + let r: i8 = transmute(vqnegb_s8(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvt_f64_s64() { - let a: i64x1 = i64x1::new(1); - let e: f64 = 1.; - let r: f64 = transmute(vcvt_f64_s64(transmute(a))); + unsafe fn test_vqnegh_s16() { + let a: i16 = 1; + let e: i16 = -1; + let r: i16 = transmute(vqnegh_s16(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtq_f64_s64() { - let a: i64x2 = i64x2::new(1, 2); - let e: f64x2 = f64x2::new(1., 2.); - let r: f64x2 = transmute(vcvtq_f64_s64(transmute(a))); + unsafe fn test_vqnegs_s32() { + let a: i32 = 1; + let e: i32 = -1; + let r: i32 = transmute(vqnegs_s32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvt_f64_u64() { - let a: u64x1 = u64x1::new(1); - let e: f64 = 1.; - let r: f64 = transmute(vcvt_f64_u64(transmute(a))); + unsafe fn test_vqnegd_s64() { + let a: i64 = 1; + let e: i64 = -1; + let r: i64 = transmute(vqnegd_s64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtq_f64_u64() { - let a: u64x2 = u64x2::new(1, 2); - let e: f64x2 = f64x2::new(1., 2.); - let r: f64x2 = transmute(vcvtq_f64_u64(transmute(a))); + unsafe fn test_vqsubb_s8() { + let a: i8 = 42; + let b: i8 = 1; + let e: i8 = 41; + let r: i8 = transmute(vqsubb_s8(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvt_f64_f32() { - let a: f32x2 = f32x2::new(-1.2, 1.2); - let e: f64x2 = f64x2::new(-1.2f32 as f64, 1.2f32 as f64); - let r: f64x2 = transmute(vcvt_f64_f32(transmute(a))); + unsafe fn test_vqsubh_s16() { + let a: i16 = 42; + let b: i16 = 1; + let e: i16 = 41; + let r: i16 = transmute(vqsubh_s16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvt_high_f64_f32() { - let a: f32x4 = f32x4::new(-1.2, 1.2, 2.3, 3.4); - let e: f64x2 = f64x2::new(2.3f32 as f64, 3.4f32 as f64); - let r: f64x2 = transmute(vcvt_high_f64_f32(transmute(a))); + unsafe fn test_vqsubb_u8() { + let a: u8 = 42; + let b: u8 = 1; + let e: u8 = 41; + let r: u8 = transmute(vqsubb_u8(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvt_f32_f64() { - let a: f64x2 = f64x2::new(-1.2, 1.2); - let e: f32x2 = f32x2::new(-1.2f64 as f32, 1.2f64 as f32); - let r: f32x2 = transmute(vcvt_f32_f64(transmute(a))); + unsafe fn test_vqsubh_u16() { + let a: u16 = 42; + let b: u16 = 1; + let e: u16 = 41; + let r: u16 = transmute(vqsubh_u16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvt_high_f32_f64() { - let a: f32x2 = f32x2::new(-1.2, 1.2); - let b: f64x2 = f64x2::new(-2.3, 3.4); - let e: f32x4 = f32x4::new(-1.2, 1.2, -2.3f64 as f32, 3.4f64 as f32); - let r: f32x4 = transmute(vcvt_high_f32_f64(transmute(a), transmute(b))); + unsafe fn test_vqsubs_u32() { + let a: u32 = 42; + let b: u32 = 1; + let e: u32 = 41; + let r: u32 = transmute(vqsubs_u32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtx_f32_f64() { - let a: f64x2 = f64x2::new(-1.0, 2.0); - let e: f32x2 = f32x2::new(-1.0, 2.0); - let r: f32x2 = transmute(vcvtx_f32_f64(transmute(a))); + unsafe fn test_vqsubd_u64() { + let a: u64 = 42; + let b: u64 = 1; + let e: u64 = 41; + let r: u64 = transmute(vqsubd_u64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtx_high_f32_f64() { - let a: f32x2 = f32x2::new(-1.0, 2.0); - let b: f64x2 = f64x2::new(-3.0, 4.0); - let e: f32x4 = f32x4::new(-1.0, 2.0, -3.0, 4.0); - let r: f32x4 = transmute(vcvtx_high_f32_f64(transmute(a), transmute(b))); + unsafe fn test_vqsubs_s32() { + let a: i32 = 42; + let b: i32 = 1; + let e: i32 = 41; + let r: i32 = transmute(vqsubs_s32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvt_n_f64_s64() { - let a: i64x1 = i64x1::new(1); - let e: f64 = 0.25; - let r: f64 = transmute(vcvt_n_f64_s64::<2>(transmute(a))); + unsafe fn test_vqsubd_s64() { + let a: i64 = 42; + let b: i64 = 1; + let e: i64 = 41; + let r: i64 = transmute(vqsubd_s64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtq_n_f64_s64() { - let a: i64x2 = i64x2::new(1, 2); - let e: f64x2 = f64x2::new(0.25, 0.5); - let r: f64x2 = transmute(vcvtq_n_f64_s64::<2>(transmute(a))); + unsafe fn test_vrbit_s8() { + let a: i8x8 = i8x8::new(0, 2, 4, 6, 8, 10, 12, 14); + let e: i8x8 = i8x8::new(0, 64, 32, 96, 16, 80, 48, 112); + let r: i8x8 = transmute(vrbit_s8(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvts_n_f32_s32() { - let a: i32 = 1; - let e: f32 = 0.25; - let r: f32 = transmute(vcvts_n_f32_s32::<2>(transmute(a))); + unsafe fn test_vrbitq_s8() { + let a: i8x16 = i8x16::new(0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30); + let e: i8x16 = i8x16::new(0, 64, 32, 96, 16, 80, 48, 112, 8, 72, 40, 104, 24, 88, 56, 120); + let r: i8x16 = transmute(vrbitq_s8(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtd_n_f64_s64() { - let a: i64 = 1; - let e: f64 = 0.25; - let r: f64 = transmute(vcvtd_n_f64_s64::<2>(transmute(a))); + unsafe fn test_vrbit_u8() { + let a: u8x8 = u8x8::new(0, 2, 4, 6, 8, 10, 12, 14); + let e: u8x8 = u8x8::new(0, 64, 32, 96, 16, 80, 48, 112); + let r: u8x8 = transmute(vrbit_u8(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvt_n_f64_u64() { - let a: u64x1 = u64x1::new(1); - let e: f64 = 0.25; - let r: f64 = transmute(vcvt_n_f64_u64::<2>(transmute(a))); + unsafe fn test_vrbitq_u8() { + let a: u8x16 = u8x16::new(0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30); + let e: u8x16 = u8x16::new(0, 64, 32, 96, 16, 80, 48, 112, 8, 72, 40, 104, 24, 88, 56, 120); + let r: u8x16 = transmute(vrbitq_u8(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtq_n_f64_u64() { - let a: u64x2 = u64x2::new(1, 2); - let e: f64x2 = f64x2::new(0.25, 0.5); - let r: f64x2 = transmute(vcvtq_n_f64_u64::<2>(transmute(a))); + unsafe fn test_vrbit_p8() { + let a: i8x8 = i8x8::new(0, 2, 4, 6, 8, 10, 12, 14); + let e: i8x8 = i8x8::new(0, 64, 32, 96, 16, 80, 48, 112); + let r: i8x8 = transmute(vrbit_p8(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvts_n_f32_u32() { - let a: u32 = 1; - let e: f32 = 0.25; - let r: f32 = transmute(vcvts_n_f32_u32::<2>(transmute(a))); + unsafe fn test_vrbitq_p8() { + let a: i8x16 = i8x16::new(0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30); + let e: i8x16 = i8x16::new(0, 64, 32, 96, 16, 80, 48, 112, 8, 72, 40, 104, 24, 88, 56, 120); + let r: i8x16 = transmute(vrbitq_p8(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtd_n_f64_u64() { - let a: u64 = 1; - let e: f64 = 0.25; - let r: f64 = transmute(vcvtd_n_f64_u64::<2>(transmute(a))); + unsafe fn test_vrndx_f32() { + let a: f32x2 = f32x2::new(-1.5, 0.5); + let e: f32x2 = f32x2::new(-2.0, 0.0); + let r: f32x2 = transmute(vrndx_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvt_n_s64_f64() { - let a: f64 = 0.25; - let e: i64x1 = i64x1::new(1); - let r: i64x1 = transmute(vcvt_n_s64_f64::<2>(transmute(a))); + unsafe fn test_vrndxq_f32() { + let a: f32x4 = f32x4::new(-1.5, 0.5, 1.5, 2.5); + let e: f32x4 = f32x4::new(-2.0, 0.0, 2.0, 2.0); + let r: f32x4 = transmute(vrndxq_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtq_n_s64_f64() { - let a: f64x2 = f64x2::new(0.25, 0.5); - let e: i64x2 = i64x2::new(1, 2); - let r: i64x2 = transmute(vcvtq_n_s64_f64::<2>(transmute(a))); + unsafe fn test_vrndx_f64() { + let a: f64 = -1.5; + let e: f64 = -2.0; + let r: f64 = transmute(vrndx_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvts_n_s32_f32() { - let a: f32 = 0.25; - let e: i32 = 1; - let r: i32 = transmute(vcvts_n_s32_f32::<2>(transmute(a))); + unsafe fn test_vrndxq_f64() { + let a: f64x2 = f64x2::new(-1.5, 0.5); + let e: f64x2 = f64x2::new(-2.0, 0.0); + let r: f64x2 = transmute(vrndxq_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtd_n_s64_f64() { - let a: f64 = 0.25; - let e: i64 = 1; - let r: i64 = transmute(vcvtd_n_s64_f64::<2>(transmute(a))); + unsafe fn test_vrnda_f32() { + let a: f32x2 = f32x2::new(-1.5, 0.5); + let e: f32x2 = f32x2::new(-2.0, 1.0); + let r: f32x2 = transmute(vrnda_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvt_n_u64_f64() { - let a: f64 = 0.25; - let e: u64x1 = u64x1::new(1); - let r: u64x1 = transmute(vcvt_n_u64_f64::<2>(transmute(a))); + unsafe fn test_vrndaq_f32() { + let a: f32x4 = f32x4::new(-1.5, 0.5, 1.5, 2.5); + let e: f32x4 = f32x4::new(-2.0, 1.0, 2.0, 3.0); + let r: f32x4 = transmute(vrndaq_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtq_n_u64_f64() { - let a: f64x2 = f64x2::new(0.25, 0.5); - let e: u64x2 = u64x2::new(1, 2); - let r: u64x2 = transmute(vcvtq_n_u64_f64::<2>(transmute(a))); + unsafe fn test_vrnda_f64() { + let a: f64 = -1.5; + let e: f64 = -2.0; + let r: f64 = transmute(vrnda_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvts_n_u32_f32() { - let a: f32 = 0.25; - let e: u32 = 1; - let r: u32 = transmute(vcvts_n_u32_f32::<2>(transmute(a))); + unsafe fn test_vrndaq_f64() { + let a: f64x2 = f64x2::new(-1.5, 0.5); + let e: f64x2 = f64x2::new(-2.0, 1.0); + let r: f64x2 = transmute(vrndaq_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtd_n_u64_f64() { - let a: f64 = 0.25; - let e: u64 = 1; - let r: u64 = transmute(vcvtd_n_u64_f64::<2>(transmute(a))); + unsafe fn test_vrndn_f64() { + let a: f64 = -1.5; + let e: f64 = -2.0; + let r: f64 = transmute(vrndn_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvts_f32_s32() { - let a: i32 = 1; - let e: f32 = 1.; - let r: f32 = transmute(vcvts_f32_s32(transmute(a))); + unsafe fn test_vrndnq_f64() { + let a: f64x2 = f64x2::new(-1.5, 0.5); + let e: f64x2 = f64x2::new(-2.0, 0.0); + let r: f64x2 = transmute(vrndnq_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtd_f64_s64() { - let a: i64 = 1; - let e: f64 = 1.; - let r: f64 = transmute(vcvtd_f64_s64(transmute(a))); + unsafe fn test_vrndns_f32() { + let a: f32 = -1.5; + let e: f32 = -2.0; + let r: f32 = transmute(vrndns_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvts_f32_u32() { - let a: u32 = 1; - let e: f32 = 1.; - let r: f32 = transmute(vcvts_f32_u32(transmute(a))); + unsafe fn test_vrndm_f32() { + let a: f32x2 = f32x2::new(-1.5, 0.5); + let e: f32x2 = f32x2::new(-2.0, 0.0); + let r: f32x2 = transmute(vrndm_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtd_f64_u64() { - let a: u64 = 1; - let e: f64 = 1.; - let r: f64 = transmute(vcvtd_f64_u64(transmute(a))); + unsafe fn test_vrndmq_f32() { + let a: f32x4 = f32x4::new(-1.5, 0.5, 1.5, 2.5); + let e: f32x4 = f32x4::new(-2.0, 0.0, 1.0, 2.0); + let r: f32x4 = transmute(vrndmq_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvts_s32_f32() { - let a: f32 = 1.; - let e: i32 = 1; - let r: i32 = transmute(vcvts_s32_f32(transmute(a))); + unsafe fn test_vrndm_f64() { + let a: f64 = -1.5; + let e: f64 = -2.0; + let r: f64 = transmute(vrndm_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtd_s64_f64() { - let a: f64 = 1.; - let e: i64 = 1; - let r: i64 = transmute(vcvtd_s64_f64(transmute(a))); + unsafe fn test_vrndmq_f64() { + let a: f64x2 = f64x2::new(-1.5, 0.5); + let e: f64x2 = f64x2::new(-2.0, 0.0); + let r: f64x2 = transmute(vrndmq_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvts_u32_f32() { - let a: f32 = 1.; - let e: u32 = 1; - let r: u32 = transmute(vcvts_u32_f32(transmute(a))); + unsafe fn test_vrndp_f32() { + let a: f32x2 = f32x2::new(-1.5, 0.5); + let e: f32x2 = f32x2::new(-1.0, 1.0); + let r: f32x2 = transmute(vrndp_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtd_u64_f64() { - let a: f64 = 1.; - let e: u64 = 1; - let r: u64 = transmute(vcvtd_u64_f64(transmute(a))); + unsafe fn test_vrndpq_f32() { + let a: f32x4 = f32x4::new(-1.5, 0.5, 1.5, 2.5); + let e: f32x4 = f32x4::new(-1.0, 1.0, 2.0, 3.0); + let r: f32x4 = transmute(vrndpq_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvt_s64_f64() { - let a: f64 = -1.1; - let e: i64x1 = i64x1::new(-1); - let r: i64x1 = transmute(vcvt_s64_f64(transmute(a))); + unsafe fn test_vrndp_f64() { + let a: f64 = -1.5; + let e: f64 = -1.0; + let r: f64 = transmute(vrndp_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtq_s64_f64() { - let a: f64x2 = f64x2::new(-1.1, 2.1); - let e: i64x2 = i64x2::new(-1, 2); - let r: i64x2 = transmute(vcvtq_s64_f64(transmute(a))); + unsafe fn test_vrndpq_f64() { + let a: f64x2 = f64x2::new(-1.5, 0.5); + let e: f64x2 = f64x2::new(-1.0, 1.0); + let r: f64x2 = transmute(vrndpq_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvt_u64_f64() { - let a: f64 = 1.1; - let e: u64x1 = u64x1::new(1); - let r: u64x1 = transmute(vcvt_u64_f64(transmute(a))); + unsafe fn test_vrnd_f32() { + let a: f32x2 = f32x2::new(-1.5, 0.5); + let e: f32x2 = f32x2::new(-1.0, 0.0); + let r: f32x2 = transmute(vrnd_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtq_u64_f64() { - let a: f64x2 = f64x2::new(1.1, 2.1); - let e: u64x2 = u64x2::new(1, 2); - let r: u64x2 = transmute(vcvtq_u64_f64(transmute(a))); + unsafe fn test_vrndq_f32() { + let a: f32x4 = f32x4::new(-1.5, 0.5, 1.5, 2.5); + let e: f32x4 = f32x4::new(-1.0, 0.0, 1.0, 2.0); + let r: f32x4 = transmute(vrndq_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvta_s32_f32() { - let a: f32x2 = f32x2::new(-1.1, 2.1); - let e: i32x2 = i32x2::new(-1, 2); - let r: i32x2 = transmute(vcvta_s32_f32(transmute(a))); + unsafe fn test_vrnd_f64() { + let a: f64 = -1.5; + let e: f64 = -1.0; + let r: f64 = transmute(vrnd_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtaq_s32_f32() { - let a: f32x4 = f32x4::new(-1.1, 2.1, -2.9, 3.9); - let e: i32x4 = i32x4::new(-1, 2, -3, 4); - let r: i32x4 = transmute(vcvtaq_s32_f32(transmute(a))); + unsafe fn test_vrndq_f64() { + let a: f64x2 = f64x2::new(-1.5, 0.5); + let e: f64x2 = f64x2::new(-1.0, 0.0); + let r: f64x2 = transmute(vrndq_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvta_s64_f64() { - let a: f64 = -1.1; - let e: i64x1 = i64x1::new(-1); - let r: i64x1 = transmute(vcvta_s64_f64(transmute(a))); + unsafe fn test_vrndi_f32() { + let a: f32x2 = f32x2::new(-1.5, 0.5); + let e: f32x2 = f32x2::new(-2.0, 0.0); + let r: f32x2 = transmute(vrndi_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtaq_s64_f64() { - let a: f64x2 = f64x2::new(-1.1, 2.1); - let e: i64x2 = i64x2::new(-1, 2); - let r: i64x2 = transmute(vcvtaq_s64_f64(transmute(a))); + unsafe fn test_vrndiq_f32() { + let a: f32x4 = f32x4::new(-1.5, 0.5, 1.5, 2.5); + let e: f32x4 = f32x4::new(-2.0, 0.0, 2.0, 2.0); + let r: f32x4 = transmute(vrndiq_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtas_s32_f32() { - let a: f32 = 2.9; - let e: i32 = 3; - let r: i32 = transmute(vcvtas_s32_f32(transmute(a))); + unsafe fn test_vrndi_f64() { + let a: f64 = -1.5; + let e: f64 = -2.0; + let r: f64 = transmute(vrndi_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtad_s64_f64() { - let a: f64 = 2.9; - let e: i64 = 3; - let r: i64 = transmute(vcvtad_s64_f64(transmute(a))); + unsafe fn test_vrndiq_f64() { + let a: f64x2 = f64x2::new(-1.5, 0.5); + let e: f64x2 = f64x2::new(-2.0, 0.0); + let r: f64x2 = transmute(vrndiq_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtas_u32_f32() { - let a: f32 = 2.9; - let e: u32 = 3; - let r: u32 = transmute(vcvtas_u32_f32(transmute(a))); + unsafe fn test_vqaddb_s8() { + let a: i8 = 42; + let b: i8 = 1; + let e: i8 = 43; + let r: i8 = transmute(vqaddb_s8(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtad_u64_f64() { - let a: f64 = 2.9; - let e: u64 = 3; - let r: u64 = transmute(vcvtad_u64_f64(transmute(a))); + unsafe fn test_vqaddh_s16() { + let a: i16 = 42; + let b: i16 = 1; + let e: i16 = 43; + let r: i16 = transmute(vqaddh_s16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtn_s32_f32() { - let a: f32x2 = f32x2::new(-1.5, 2.1); - let e: i32x2 = i32x2::new(-2, 2); - let r: i32x2 = transmute(vcvtn_s32_f32(transmute(a))); + unsafe fn test_vqaddb_u8() { + let a: u8 = 42; + let b: u8 = 1; + let e: u8 = 43; + let r: u8 = transmute(vqaddb_u8(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtnq_s32_f32() { - let a: f32x4 = f32x4::new(-1.5, 2.1, -2.9, 3.9); - let e: i32x4 = i32x4::new(-2, 2, -3, 4); - let r: i32x4 = transmute(vcvtnq_s32_f32(transmute(a))); + unsafe fn test_vqaddh_u16() { + let a: u16 = 42; + let b: u16 = 1; + let e: u16 = 43; + let r: u16 = transmute(vqaddh_u16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtn_s64_f64() { - let a: f64 = -1.5; - let e: i64x1 = i64x1::new(-2); - let r: i64x1 = transmute(vcvtn_s64_f64(transmute(a))); + unsafe fn test_vqadds_u32() { + let a: u32 = 42; + let b: u32 = 1; + let e: u32 = 43; + let r: u32 = transmute(vqadds_u32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtnq_s64_f64() { - let a: f64x2 = f64x2::new(-1.5, 2.1); - let e: i64x2 = i64x2::new(-2, 2); - let r: i64x2 = transmute(vcvtnq_s64_f64(transmute(a))); + unsafe fn test_vqaddd_u64() { + let a: u64 = 42; + let b: u64 = 1; + let e: u64 = 43; + let r: u64 = transmute(vqaddd_u64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtns_s32_f32() { - let a: f32 = -1.5; - let e: i32 = -2; - let r: i32 = transmute(vcvtns_s32_f32(transmute(a))); + unsafe fn test_vqadds_s32() { + let a: i32 = 42; + let b: i32 = 1; + let e: i32 = 43; + let r: i32 = transmute(vqadds_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqaddd_s64() { + let a: i64 = 42; + let b: i64 = 1; + let e: i64 = 43; + let r: i64 = transmute(vqaddd_s64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtnd_s64_f64() { - let a: f64 = -1.5; - let e: i64 = -2; - let r: i64 = transmute(vcvtnd_s64_f64(transmute(a))); + unsafe fn test_vld1_f64_x2() { + let a: [f64; 3] = [0., 1., 2.]; + let e: [f64; 2] = [1., 2.]; + let r: [f64; 2] = transmute(vld1_f64_x2(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtm_s32_f32() { - let a: f32x2 = f32x2::new(-1.1, 2.1); - let e: i32x2 = i32x2::new(-2, 2); - let r: i32x2 = transmute(vcvtm_s32_f32(transmute(a))); + unsafe fn test_vld1q_f64_x2() { + let a: [f64; 5] = [0., 1., 2., 3., 4.]; + let e: [f64x2; 2] = [f64x2::new(1., 2.), f64x2::new(3., 4.)]; + let r: [f64x2; 2] = transmute(vld1q_f64_x2(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtmq_s32_f32() { - let a: f32x4 = f32x4::new(-1.1, 2.1, -2.9, 3.9); - let e: i32x4 = i32x4::new(-2, 2, -3, 3); - let r: i32x4 = transmute(vcvtmq_s32_f32(transmute(a))); + unsafe fn test_vld1_f64_x3() { + let a: [f64; 4] = [0., 1., 2., 3.]; + let e: [f64; 3] = [1., 2., 3.]; + let r: [f64; 3] = transmute(vld1_f64_x3(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtm_s64_f64() { - let a: f64 = -1.1; - let e: i64x1 = i64x1::new(-2); - let r: i64x1 = transmute(vcvtm_s64_f64(transmute(a))); + unsafe fn test_vld1q_f64_x3() { + let a: [f64; 7] = [0., 1., 2., 3., 4., 5., 6.]; + let e: [f64x2; 3] = [f64x2::new(1., 2.), f64x2::new(3., 4.), f64x2::new(5., 6.)]; + let r: [f64x2; 3] = transmute(vld1q_f64_x3(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtmq_s64_f64() { - let a: f64x2 = f64x2::new(-1.1, 2.1); - let e: i64x2 = i64x2::new(-2, 2); - let r: i64x2 = transmute(vcvtmq_s64_f64(transmute(a))); + unsafe fn test_vld1_f64_x4() { + let a: [f64; 5] = [0., 1., 2., 3., 4.]; + let e: [f64; 4] = [1., 2., 3., 4.]; + let r: [f64; 4] = transmute(vld1_f64_x4(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtms_s32_f32() { - let a: f32 = -1.1; - let e: i32 = -2; - let r: i32 = transmute(vcvtms_s32_f32(transmute(a))); + unsafe fn test_vld1q_f64_x4() { + let a: [f64; 9] = [0., 1., 2., 3., 4., 5., 6., 7., 8.]; + let e: [f64x2; 4] = [f64x2::new(1., 2.), f64x2::new(3., 4.), f64x2::new(5., 6.), f64x2::new(7., 8.)]; + let r: [f64x2; 4] = transmute(vld1q_f64_x4(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtmd_s64_f64() { - let a: f64 = -1.1; - let e: i64 = -2; - let r: i64 = transmute(vcvtmd_s64_f64(transmute(a))); + unsafe fn test_vld2q_s64() { + let a: [i64; 5] = [0, 1, 2, 2, 3]; + let e: [i64x2; 2] = [i64x2::new(1, 2), i64x2::new(2, 3)]; + let r: [i64x2; 2] = transmute(vld2q_s64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtp_s32_f32() { - let a: f32x2 = f32x2::new(-1.1, 2.1); - let e: i32x2 = i32x2::new(-1, 3); - let r: i32x2 = transmute(vcvtp_s32_f32(transmute(a))); + unsafe fn test_vld2q_u64() { + let a: [u64; 5] = [0, 1, 2, 2, 3]; + let e: [u64x2; 2] = [u64x2::new(1, 2), u64x2::new(2, 3)]; + let r: [u64x2; 2] = transmute(vld2q_u64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtpq_s32_f32() { - let a: f32x4 = f32x4::new(-1.1, 2.1, -2.9, 3.9); - let e: i32x4 = i32x4::new(-1, 3, -2, 4); - let r: i32x4 = transmute(vcvtpq_s32_f32(transmute(a))); + unsafe fn test_vld2q_p64() { + let a: [u64; 5] = [0, 1, 2, 2, 3]; + let e: [i64x2; 2] = [i64x2::new(1, 2), i64x2::new(2, 3)]; + let r: [i64x2; 2] = transmute(vld2q_p64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtp_s64_f64() { - let a: f64 = -1.1; - let e: i64x1 = i64x1::new(-1); - let r: i64x1 = transmute(vcvtp_s64_f64(transmute(a))); + unsafe fn test_vld2_f64() { + let a: [f64; 3] = [0., 1., 2.]; + let e: [f64; 2] = [1., 2.]; + let r: [f64; 2] = transmute(vld2_f64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtpq_s64_f64() { - let a: f64x2 = f64x2::new(-1.1, 2.1); - let e: i64x2 = i64x2::new(-1, 3); - let r: i64x2 = transmute(vcvtpq_s64_f64(transmute(a))); + unsafe fn test_vld2q_f64() { + let a: [f64; 5] = [0., 1., 2., 2., 3.]; + let e: [f64x2; 2] = [f64x2::new(1., 2.), f64x2::new(2., 3.)]; + let r: [f64x2; 2] = transmute(vld2q_f64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtps_s32_f32() { - let a: f32 = -1.1; - let e: i32 = -1; - let r: i32 = transmute(vcvtps_s32_f32(transmute(a))); + unsafe fn test_vld2q_dup_s64() { + let a: [i64; 5] = [0, 1, 1, 2, 3]; + let e: [i64x2; 2] = [i64x2::new(1, 1), i64x2::new(1, 1)]; + let r: [i64x2; 2] = transmute(vld2q_dup_s64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtpd_s64_f64() { - let a: f64 = -1.1; - let e: i64 = -1; - let r: i64 = transmute(vcvtpd_s64_f64(transmute(a))); + unsafe fn test_vld2q_dup_u64() { + let a: [u64; 5] = [0, 1, 1, 2, 3]; + let e: [u64x2; 2] = [u64x2::new(1, 1), u64x2::new(1, 1)]; + let r: [u64x2; 2] = transmute(vld2q_dup_u64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvta_u32_f32() { - let a: f32x2 = f32x2::new(1.1, 2.1); - let e: u32x2 = u32x2::new(1, 2); - let r: u32x2 = transmute(vcvta_u32_f32(transmute(a))); + unsafe fn test_vld2q_dup_p64() { + let a: [u64; 5] = [0, 1, 1, 2, 3]; + let e: [i64x2; 2] = [i64x2::new(1, 1), i64x2::new(1, 1)]; + let r: [i64x2; 2] = transmute(vld2q_dup_p64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtaq_u32_f32() { - let a: f32x4 = f32x4::new(1.1, 2.1, 2.9, 3.9); - let e: u32x4 = u32x4::new(1, 2, 3, 4); - let r: u32x4 = transmute(vcvtaq_u32_f32(transmute(a))); + unsafe fn test_vld2_dup_f64() { + let a: [f64; 3] = [0., 1., 1.]; + let e: [f64; 2] = [1., 1.]; + let r: [f64; 2] = transmute(vld2_dup_f64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvta_u64_f64() { - let a: f64 = 1.1; - let e: u64x1 = u64x1::new(1); - let r: u64x1 = transmute(vcvta_u64_f64(transmute(a))); + unsafe fn test_vld2q_dup_f64() { + let a: [f64; 5] = [0., 1., 1., 2., 3.]; + let e: [f64x2; 2] = [f64x2::new(1., 1.), f64x2::new(1., 1.)]; + let r: [f64x2; 2] = transmute(vld2q_dup_f64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtaq_u64_f64() { - let a: f64x2 = f64x2::new(1.1, 2.1); - let e: u64x2 = u64x2::new(1, 2); - let r: u64x2 = transmute(vcvtaq_u64_f64(transmute(a))); + unsafe fn test_vld2q_lane_s8() { + let a: [i8; 33] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [i8x16; 2] = [i8x16::new(0, 2, 2, 14, 2, 16, 17, 18, 2, 20, 21, 22, 23, 24, 25, 26), i8x16::new(11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26)]; + let e: [i8x16; 2] = [i8x16::new(1, 2, 2, 14, 2, 16, 17, 18, 2, 20, 21, 22, 23, 24, 25, 26), i8x16::new(2, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26)]; + let r: [i8x16; 2] = transmute(vld2q_lane_s8::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtn_u32_f32() { - let a: f32x2 = f32x2::new(1.5, 2.1); - let e: u32x2 = u32x2::new(2, 2); - let r: u32x2 = transmute(vcvtn_u32_f32(transmute(a))); + unsafe fn test_vld2_lane_s64() { + let a: [i64; 3] = [0, 1, 2]; + let b: [i64x1; 2] = [i64x1::new(0), i64x1::new(2)]; + let e: [i64x1; 2] = [i64x1::new(1), i64x1::new(2)]; + let r: [i64x1; 2] = transmute(vld2_lane_s64::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtnq_u32_f32() { - let a: f32x4 = f32x4::new(1.5, 2.1, 2.9, 3.9); - let e: u32x4 = u32x4::new(2, 2, 3, 4); - let r: u32x4 = transmute(vcvtnq_u32_f32(transmute(a))); + unsafe fn test_vld2q_lane_s64() { + let a: [i64; 5] = [0, 1, 2, 3, 4]; + let b: [i64x2; 2] = [i64x2::new(0, 2), i64x2::new(2, 14)]; + let e: [i64x2; 2] = [i64x2::new(1, 2), i64x2::new(2, 14)]; + let r: [i64x2; 2] = transmute(vld2q_lane_s64::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtn_u64_f64() { - let a: f64 = 1.5; - let e: u64x1 = u64x1::new(2); - let r: u64x1 = transmute(vcvtn_u64_f64(transmute(a))); + unsafe fn test_vld2_lane_p64() { + let a: [u64; 3] = [0, 1, 2]; + let b: [i64x1; 2] = [i64x1::new(0), i64x1::new(2)]; + let e: [i64x1; 2] = [i64x1::new(1), i64x1::new(2)]; + let r: [i64x1; 2] = transmute(vld2_lane_p64::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtnq_u64_f64() { - let a: f64x2 = f64x2::new(1.5, 2.1); - let e: u64x2 = u64x2::new(2, 2); - let r: u64x2 = transmute(vcvtnq_u64_f64(transmute(a))); + unsafe fn test_vld2q_lane_p64() { + let a: [u64; 5] = [0, 1, 2, 3, 4]; + let b: [i64x2; 2] = [i64x2::new(0, 2), i64x2::new(2, 14)]; + let e: [i64x2; 2] = [i64x2::new(1, 2), i64x2::new(2, 14)]; + let r: [i64x2; 2] = transmute(vld2q_lane_p64::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtns_u32_f32() { - let a: f32 = 1.5; - let e: u32 = 2; - let r: u32 = transmute(vcvtns_u32_f32(transmute(a))); + unsafe fn test_vld2q_lane_u8() { + let a: [u8; 33] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [u8x16; 2] = [u8x16::new(0, 2, 2, 14, 2, 16, 17, 18, 2, 20, 21, 22, 23, 24, 25, 26), u8x16::new(11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26)]; + let e: [u8x16; 2] = [u8x16::new(1, 2, 2, 14, 2, 16, 17, 18, 2, 20, 21, 22, 23, 24, 25, 26), u8x16::new(2, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26)]; + let r: [u8x16; 2] = transmute(vld2q_lane_u8::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtnd_u64_f64() { - let a: f64 = 1.5; - let e: u64 = 2; - let r: u64 = transmute(vcvtnd_u64_f64(transmute(a))); + unsafe fn test_vld2_lane_u64() { + let a: [u64; 3] = [0, 1, 2]; + let b: [u64x1; 2] = [u64x1::new(0), u64x1::new(2)]; + let e: [u64x1; 2] = [u64x1::new(1), u64x1::new(2)]; + let r: [u64x1; 2] = transmute(vld2_lane_u64::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtm_u32_f32() { - let a: f32x2 = f32x2::new(1.1, 2.1); - let e: u32x2 = u32x2::new(1, 2); - let r: u32x2 = transmute(vcvtm_u32_f32(transmute(a))); + unsafe fn test_vld2q_lane_u64() { + let a: [u64; 5] = [0, 1, 2, 3, 4]; + let b: [u64x2; 2] = [u64x2::new(0, 2), u64x2::new(2, 14)]; + let e: [u64x2; 2] = [u64x2::new(1, 2), u64x2::new(2, 14)]; + let r: [u64x2; 2] = transmute(vld2q_lane_u64::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtmq_u32_f32() { - let a: f32x4 = f32x4::new(1.1, 2.1, 2.9, 3.9); - let e: u32x4 = u32x4::new(1, 2, 2, 3); - let r: u32x4 = transmute(vcvtmq_u32_f32(transmute(a))); + unsafe fn test_vld2q_lane_p8() { + let a: [u8; 33] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [i8x16; 2] = [i8x16::new(0, 2, 2, 14, 2, 16, 17, 18, 2, 20, 21, 22, 23, 24, 25, 26), i8x16::new(11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26)]; + let e: [i8x16; 2] = [i8x16::new(1, 2, 2, 14, 2, 16, 17, 18, 2, 20, 21, 22, 23, 24, 25, 26), i8x16::new(2, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26)]; + let r: [i8x16; 2] = transmute(vld2q_lane_p8::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtm_u64_f64() { - let a: f64 = 1.1; - let e: u64x1 = u64x1::new(1); - let r: u64x1 = transmute(vcvtm_u64_f64(transmute(a))); + unsafe fn test_vld2_lane_f64() { + let a: [f64; 3] = [0., 1., 2.]; + let b: [f64; 2] = [0., 2.]; + let e: [f64; 2] = [1., 2.]; + let r: [f64; 2] = transmute(vld2_lane_f64::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtmq_u64_f64() { - let a: f64x2 = f64x2::new(1.1, 2.1); - let e: u64x2 = u64x2::new(1, 2); - let r: u64x2 = transmute(vcvtmq_u64_f64(transmute(a))); + unsafe fn test_vld2q_lane_f64() { + let a: [f64; 5] = [0., 1., 2., 3., 4.]; + let b: [f64x2; 2] = [f64x2::new(0., 2.), f64x2::new(2., 14.)]; + let e: [f64x2; 2] = [f64x2::new(1., 2.), f64x2::new(2., 14.)]; + let r: [f64x2; 2] = transmute(vld2q_lane_f64::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtms_u32_f32() { - let a: f32 = 1.1; - let e: u32 = 1; - let r: u32 = transmute(vcvtms_u32_f32(transmute(a))); + unsafe fn test_vld3q_s64() { + let a: [i64; 7] = [0, 1, 2, 2, 2, 4, 4]; + let e: [i64x2; 3] = [i64x2::new(1, 2), i64x2::new(2, 4), i64x2::new(2, 4)]; + let r: [i64x2; 3] = transmute(vld3q_s64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtmd_u64_f64() { - let a: f64 = 1.1; - let e: u64 = 1; - let r: u64 = transmute(vcvtmd_u64_f64(transmute(a))); + unsafe fn test_vld3q_u64() { + let a: [u64; 7] = [0, 1, 2, 2, 2, 4, 4]; + let e: [u64x2; 3] = [u64x2::new(1, 2), u64x2::new(2, 4), u64x2::new(2, 4)]; + let r: [u64x2; 3] = transmute(vld3q_u64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtp_u32_f32() { - let a: f32x2 = f32x2::new(1.1, 2.1); - let e: u32x2 = u32x2::new(2, 3); - let r: u32x2 = transmute(vcvtp_u32_f32(transmute(a))); + unsafe fn test_vld3q_p64() { + let a: [u64; 7] = [0, 1, 2, 2, 2, 4, 4]; + let e: [i64x2; 3] = [i64x2::new(1, 2), i64x2::new(2, 4), i64x2::new(2, 4)]; + let r: [i64x2; 3] = transmute(vld3q_p64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtpq_u32_f32() { - let a: f32x4 = f32x4::new(1.1, 2.1, 2.9, 3.9); - let e: u32x4 = u32x4::new(2, 3, 3, 4); - let r: u32x4 = transmute(vcvtpq_u32_f32(transmute(a))); + unsafe fn test_vld3_f64() { + let a: [f64; 4] = [0., 1., 2., 2.]; + let e: [f64; 3] = [1., 2., 2.]; + let r: [f64; 3] = transmute(vld3_f64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtp_u64_f64() { - let a: f64 = 1.1; - let e: u64x1 = u64x1::new(2); - let r: u64x1 = transmute(vcvtp_u64_f64(transmute(a))); + unsafe fn test_vld3q_f64() { + let a: [f64; 7] = [0., 1., 2., 2., 2., 4., 4.]; + let e: [f64x2; 3] = [f64x2::new(1., 2.), f64x2::new(2., 4.), f64x2::new(2., 4.)]; + let r: [f64x2; 3] = transmute(vld3q_f64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtpq_u64_f64() { - let a: f64x2 = f64x2::new(1.1, 2.1); - let e: u64x2 = u64x2::new(2, 3); - let r: u64x2 = transmute(vcvtpq_u64_f64(transmute(a))); + unsafe fn test_vld3q_dup_s64() { + let a: [i64; 7] = [0, 1, 1, 1, 3, 1, 4]; + let e: [i64x2; 3] = [i64x2::new(1, 1), i64x2::new(1, 1), i64x2::new(1, 1)]; + let r: [i64x2; 3] = transmute(vld3q_dup_s64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtps_u32_f32() { - let a: f32 = 1.1; - let e: u32 = 2; - let r: u32 = transmute(vcvtps_u32_f32(transmute(a))); + unsafe fn test_vld3q_dup_u64() { + let a: [u64; 7] = [0, 1, 1, 1, 3, 1, 4]; + let e: [u64x2; 3] = [u64x2::new(1, 1), u64x2::new(1, 1), u64x2::new(1, 1)]; + let r: [u64x2; 3] = transmute(vld3q_dup_u64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtpd_u64_f64() { - let a: f64 = 1.1; - let e: u64 = 2; - let r: u64 = transmute(vcvtpd_u64_f64(transmute(a))); + unsafe fn test_vld3q_dup_p64() { + let a: [u64; 7] = [0, 1, 1, 1, 3, 1, 4]; + let e: [i64x2; 3] = [i64x2::new(1, 1), i64x2::new(1, 1), i64x2::new(1, 1)]; + let r: [i64x2; 3] = transmute(vld3q_dup_p64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupq_laneq_p64() { - let a: i64x2 = i64x2::new(1, 1); - let e: i64x2 = i64x2::new(1, 1); - let r: i64x2 = transmute(vdupq_laneq_p64::<1>(transmute(a))); + unsafe fn test_vld3_dup_f64() { + let a: [f64; 4] = [0., 1., 1., 1.]; + let e: [f64; 3] = [1., 1., 1.]; + let r: [f64; 3] = transmute(vld3_dup_f64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupq_lane_p64() { - let a: i64x1 = i64x1::new(1); - let e: i64x2 = i64x2::new(1, 1); - let r: i64x2 = transmute(vdupq_lane_p64::<0>(transmute(a))); + unsafe fn test_vld3q_dup_f64() { + let a: [f64; 7] = [0., 1., 1., 1., 3., 1., 4.]; + let e: [f64x2; 3] = [f64x2::new(1., 1.), f64x2::new(1., 1.), f64x2::new(1., 1.)]; + let r: [f64x2; 3] = transmute(vld3q_dup_f64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupq_laneq_f64() { - let a: f64x2 = f64x2::new(1., 1.); - let e: f64x2 = f64x2::new(1., 1.); - let r: f64x2 = transmute(vdupq_laneq_f64::<1>(transmute(a))); + unsafe fn test_vld3q_lane_s8() { + let a: [i8; 49] = [0, 1, 2, 2, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [i8x16; 3] = [i8x16::new(0, 2, 2, 14, 2, 16, 17, 18, 2, 20, 21, 22, 23, 24, 25, 26), i8x16::new(11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26), i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8)]; + let e: [i8x16; 3] = [i8x16::new(1, 2, 2, 14, 2, 16, 17, 18, 2, 20, 21, 22, 23, 24, 25, 26), i8x16::new(2, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26), i8x16::new(2, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8)]; + let r: [i8x16; 3] = transmute(vld3q_lane_s8::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupq_lane_f64() { - let a: f64 = 1.; - let e: f64x2 = f64x2::new(1., 1.); - let r: f64x2 = transmute(vdupq_lane_f64::<0>(transmute(a))); + unsafe fn test_vld3_lane_s64() { + let a: [i64; 4] = [0, 1, 2, 2]; + let b: [i64x1; 3] = [i64x1::new(0), i64x1::new(2), i64x1::new(2)]; + let e: [i64x1; 3] = [i64x1::new(1), i64x1::new(2), i64x1::new(2)]; + let r: [i64x1; 3] = transmute(vld3_lane_s64::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdup_lane_p64() { - let a: i64x1 = i64x1::new(0); - let e: i64x1 = i64x1::new(0); - let r: i64x1 = transmute(vdup_lane_p64::<0>(transmute(a))); + unsafe fn test_vld3q_lane_s64() { + let a: [i64; 7] = [0, 1, 2, 2, 4, 5, 6]; + let b: [i64x2; 3] = [i64x2::new(0, 2), i64x2::new(2, 14), i64x2::new(2, 16)]; + let e: [i64x2; 3] = [i64x2::new(1, 2), i64x2::new(2, 14), i64x2::new(2, 16)]; + let r: [i64x2; 3] = transmute(vld3q_lane_s64::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdup_lane_f64() { - let a: f64 = 0.; - let e: f64 = 0.; - let r: f64 = transmute(vdup_lane_f64::<0>(transmute(a))); + unsafe fn test_vld3_lane_p64() { + let a: [u64; 4] = [0, 1, 2, 2]; + let b: [i64x1; 3] = [i64x1::new(0), i64x1::new(2), i64x1::new(2)]; + let e: [i64x1; 3] = [i64x1::new(1), i64x1::new(2), i64x1::new(2)]; + let r: [i64x1; 3] = transmute(vld3_lane_p64::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdup_laneq_p64() { - let a: i64x2 = i64x2::new(0, 1); - let e: i64x1 = i64x1::new(1); - let r: i64x1 = transmute(vdup_laneq_p64::<1>(transmute(a))); + unsafe fn test_vld3q_lane_p64() { + let a: [u64; 7] = [0, 1, 2, 2, 4, 5, 6]; + let b: [i64x2; 3] = [i64x2::new(0, 2), i64x2::new(2, 14), i64x2::new(2, 16)]; + let e: [i64x2; 3] = [i64x2::new(1, 2), i64x2::new(2, 14), i64x2::new(2, 16)]; + let r: [i64x2; 3] = transmute(vld3q_lane_p64::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdup_laneq_f64() { - let a: f64x2 = f64x2::new(0., 1.); - let e: f64 = 1.; - let r: f64 = transmute(vdup_laneq_f64::<1>(transmute(a))); + unsafe fn test_vld3q_lane_p8() { + let a: [u8; 49] = [0, 1, 2, 2, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [i8x16; 3] = [i8x16::new(0, 2, 2, 14, 2, 16, 17, 18, 2, 20, 21, 22, 23, 24, 25, 26), i8x16::new(11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26), i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8)]; + let e: [i8x16; 3] = [i8x16::new(1, 2, 2, 14, 2, 16, 17, 18, 2, 20, 21, 22, 23, 24, 25, 26), i8x16::new(2, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26), i8x16::new(2, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8)]; + let r: [i8x16; 3] = transmute(vld3q_lane_p8::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupb_lane_s8() { - let a: i8x8 = i8x8::new(1, 1, 1, 4, 1, 6, 7, 8); - let e: i8 = 1; - let r: i8 = transmute(vdupb_lane_s8::<4>(transmute(a))); + unsafe fn test_vld3q_lane_u8() { + let a: [u8; 49] = [0, 1, 2, 2, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [u8x16; 3] = [u8x16::new(0, 2, 2, 14, 2, 16, 17, 18, 2, 20, 21, 22, 23, 24, 25, 26), u8x16::new(11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26), u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8)]; + let e: [u8x16; 3] = [u8x16::new(1, 2, 2, 14, 2, 16, 17, 18, 2, 20, 21, 22, 23, 24, 25, 26), u8x16::new(2, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26), u8x16::new(2, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8)]; + let r: [u8x16; 3] = transmute(vld3q_lane_u8::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupb_laneq_s8() { - let a: i8x16 = i8x16::new(1, 1, 1, 4, 1, 6, 7, 8, 1, 10, 11, 12, 13, 14, 15, 16); - let e: i8 = 1; - let r: i8 = transmute(vdupb_laneq_s8::<8>(transmute(a))); + unsafe fn test_vld3_lane_u64() { + let a: [u64; 4] = [0, 1, 2, 2]; + let b: [u64x1; 3] = [u64x1::new(0), u64x1::new(2), u64x1::new(2)]; + let e: [u64x1; 3] = [u64x1::new(1), u64x1::new(2), u64x1::new(2)]; + let r: [u64x1; 3] = transmute(vld3_lane_u64::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vduph_lane_s16() { - let a: i16x4 = i16x4::new(1, 1, 1, 4); - let e: i16 = 1; - let r: i16 = transmute(vduph_lane_s16::<2>(transmute(a))); + unsafe fn test_vld3q_lane_u64() { + let a: [u64; 7] = [0, 1, 2, 2, 4, 5, 6]; + let b: [u64x2; 3] = [u64x2::new(0, 2), u64x2::new(2, 14), u64x2::new(2, 16)]; + let e: [u64x2; 3] = [u64x2::new(1, 2), u64x2::new(2, 14), u64x2::new(2, 16)]; + let r: [u64x2; 3] = transmute(vld3q_lane_u64::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vduph_laneq_s16() { - let a: i16x8 = i16x8::new(1, 1, 1, 4, 1, 6, 7, 8); - let e: i16 = 1; - let r: i16 = transmute(vduph_laneq_s16::<4>(transmute(a))); + unsafe fn test_vld3_lane_f64() { + let a: [f64; 4] = [0., 1., 2., 2.]; + let b: [f64; 3] = [0., 2., 2.]; + let e: [f64; 3] = [1., 2., 2.]; + let r: [f64; 3] = transmute(vld3_lane_f64::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdups_lane_s32() { - let a: i32x2 = i32x2::new(1, 1); - let e: i32 = 1; - let r: i32 = transmute(vdups_lane_s32::<1>(transmute(a))); + unsafe fn test_vld3q_lane_f64() { + let a: [f64; 7] = [0., 1., 2., 2., 4., 5., 6.]; + let b: [f64x2; 3] = [f64x2::new(0., 2.), f64x2::new(2., 14.), f64x2::new(9., 16.)]; + let e: [f64x2; 3] = [f64x2::new(1., 2.), f64x2::new(2., 14.), f64x2::new(2., 16.)]; + let r: [f64x2; 3] = transmute(vld3q_lane_f64::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdups_laneq_s32() { - let a: i32x4 = i32x4::new(1, 1, 1, 4); - let e: i32 = 1; - let r: i32 = transmute(vdups_laneq_s32::<2>(transmute(a))); + unsafe fn test_vld4q_s64() { + let a: [i64; 9] = [0, 1, 2, 2, 6, 2, 6, 6, 8]; + let e: [i64x2; 4] = [i64x2::new(1, 2), i64x2::new(2, 6), i64x2::new(2, 6), i64x2::new(6, 8)]; + let r: [i64x2; 4] = transmute(vld4q_s64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupd_lane_s64() { - let a: i64x1 = i64x1::new(1); - let e: i64 = 1; - let r: i64 = transmute(vdupd_lane_s64::<0>(transmute(a))); + unsafe fn test_vld4q_u64() { + let a: [u64; 9] = [0, 1, 2, 2, 6, 2, 6, 6, 8]; + let e: [u64x2; 4] = [u64x2::new(1, 2), u64x2::new(2, 6), u64x2::new(2, 6), u64x2::new(6, 8)]; + let r: [u64x2; 4] = transmute(vld4q_u64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupd_laneq_s64() { - let a: i64x2 = i64x2::new(1, 1); - let e: i64 = 1; - let r: i64 = transmute(vdupd_laneq_s64::<1>(transmute(a))); + unsafe fn test_vld4q_p64() { + let a: [u64; 9] = [0, 1, 2, 2, 6, 2, 6, 6, 8]; + let e: [i64x2; 4] = [i64x2::new(1, 2), i64x2::new(2, 6), i64x2::new(2, 6), i64x2::new(6, 8)]; + let r: [i64x2; 4] = transmute(vld4q_p64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupb_lane_u8() { - let a: u8x8 = u8x8::new(1, 1, 1, 4, 1, 6, 7, 8); - let e: u8 = 1; - let r: u8 = transmute(vdupb_lane_u8::<4>(transmute(a))); + unsafe fn test_vld4_f64() { + let a: [f64; 5] = [0., 1., 2., 2., 6.]; + let e: [f64; 4] = [1., 2., 2., 6.]; + let r: [f64; 4] = transmute(vld4_f64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupb_laneq_u8() { - let a: u8x16 = u8x16::new(1, 1, 1, 4, 1, 6, 7, 8, 1, 10, 11, 12, 13, 14, 15, 16); - let e: u8 = 1; - let r: u8 = transmute(vdupb_laneq_u8::<8>(transmute(a))); + unsafe fn test_vld4q_f64() { + let a: [f64; 9] = [0., 1., 2., 2., 6., 2., 6., 6., 8.]; + let e: [f64x2; 4] = [f64x2::new(1., 2.), f64x2::new(2., 6.), f64x2::new(2., 6.), f64x2::new(6., 8.)]; + let r: [f64x2; 4] = transmute(vld4q_f64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vduph_lane_u16() { - let a: u16x4 = u16x4::new(1, 1, 1, 4); - let e: u16 = 1; - let r: u16 = transmute(vduph_lane_u16::<2>(transmute(a))); + unsafe fn test_vld4q_dup_s64() { + let a: [i64; 9] = [0, 1, 1, 1, 1, 2, 4, 3, 5]; + let e: [i64x2; 4] = [i64x2::new(1, 1), i64x2::new(1, 1), i64x2::new(1, 1), i64x2::new(1, 1)]; + let r: [i64x2; 4] = transmute(vld4q_dup_s64(a[1..].as_ptr())); assert_eq!(r, e); } - #[simd_test(enable = "neon")] - unsafe fn test_vduph_laneq_u16() { - let a: u16x8 = u16x8::new(1, 1, 1, 4, 1, 6, 7, 8); - let e: u16 = 1; - let r: u16 = transmute(vduph_laneq_u16::<4>(transmute(a))); + #[simd_test(enable = "neon")] + unsafe fn test_vld4q_dup_u64() { + let a: [u64; 9] = [0, 1, 1, 1, 1, 2, 4, 3, 5]; + let e: [u64x2; 4] = [u64x2::new(1, 1), u64x2::new(1, 1), u64x2::new(1, 1), u64x2::new(1, 1)]; + let r: [u64x2; 4] = transmute(vld4q_dup_u64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdups_lane_u32() { - let a: u32x2 = u32x2::new(1, 1); - let e: u32 = 1; - let r: u32 = transmute(vdups_lane_u32::<1>(transmute(a))); + unsafe fn test_vld4q_dup_p64() { + let a: [u64; 9] = [0, 1, 1, 1, 1, 2, 4, 3, 5]; + let e: [i64x2; 4] = [i64x2::new(1, 1), i64x2::new(1, 1), i64x2::new(1, 1), i64x2::new(1, 1)]; + let r: [i64x2; 4] = transmute(vld4q_dup_p64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdups_laneq_u32() { - let a: u32x4 = u32x4::new(1, 1, 1, 4); - let e: u32 = 1; - let r: u32 = transmute(vdups_laneq_u32::<2>(transmute(a))); + unsafe fn test_vld4_dup_f64() { + let a: [f64; 5] = [0., 1., 1., 1., 1.]; + let e: [f64; 4] = [1., 1., 1., 1.]; + let r: [f64; 4] = transmute(vld4_dup_f64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupd_lane_u64() { - let a: u64x1 = u64x1::new(1); - let e: u64 = 1; - let r: u64 = transmute(vdupd_lane_u64::<0>(transmute(a))); + unsafe fn test_vld4q_dup_f64() { + let a: [f64; 9] = [0., 1., 1., 1., 1., 6., 4., 3., 5.]; + let e: [f64x2; 4] = [f64x2::new(1., 1.), f64x2::new(1., 1.), f64x2::new(1., 1.), f64x2::new(1., 1.)]; + let r: [f64x2; 4] = transmute(vld4q_dup_f64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupd_laneq_u64() { - let a: u64x2 = u64x2::new(1, 1); - let e: u64 = 1; - let r: u64 = transmute(vdupd_laneq_u64::<1>(transmute(a))); + unsafe fn test_vld4q_lane_s8() { + let a: [i8; 65] = [0, 1, 2, 2, 2, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16]; + let b: [i8x16; 4] = [i8x16::new(0, 2, 2, 2, 2, 16, 2, 18, 2, 20, 21, 22, 2, 24, 25, 26), i8x16::new(11, 12, 13, 14, 15, 16, 2, 18, 2, 20, 21, 22, 23, 24, 25, 26), i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8), i8x16::new(1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16)]; + let e: [i8x16; 4] = [i8x16::new(1, 2, 2, 2, 2, 16, 2, 18, 2, 20, 21, 22, 2, 24, 25, 26), i8x16::new(2, 12, 13, 14, 15, 16, 2, 18, 2, 20, 21, 22, 23, 24, 25, 26), i8x16::new(2, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8), i8x16::new(2, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16)]; + let r: [i8x16; 4] = transmute(vld4q_lane_s8::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupb_lane_p8() { - let a: i8x8 = i8x8::new(1, 1, 1, 4, 1, 6, 7, 8); - let e: p8 = 1; - let r: p8 = transmute(vdupb_lane_p8::<4>(transmute(a))); + unsafe fn test_vld4_lane_s64() { + let a: [i64; 5] = [0, 1, 2, 2, 2]; + let b: [i64x1; 4] = [i64x1::new(0), i64x1::new(2), i64x1::new(2), i64x1::new(2)]; + let e: [i64x1; 4] = [i64x1::new(1), i64x1::new(2), i64x1::new(2), i64x1::new(2)]; + let r: [i64x1; 4] = transmute(vld4_lane_s64::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupb_laneq_p8() { - let a: i8x16 = i8x16::new(1, 1, 1, 4, 1, 6, 7, 8, 1, 10, 11, 12, 13, 14, 15, 16); - let e: p8 = 1; - let r: p8 = transmute(vdupb_laneq_p8::<8>(transmute(a))); + unsafe fn test_vld4q_lane_s64() { + let a: [i64; 9] = [0, 1, 2, 2, 2, 5, 6, 7, 8]; + let b: [i64x2; 4] = [i64x2::new(0, 2), i64x2::new(2, 2), i64x2::new(2, 16), i64x2::new(2, 18)]; + let e: [i64x2; 4] = [i64x2::new(1, 2), i64x2::new(2, 2), i64x2::new(2, 16), i64x2::new(2, 18)]; + let r: [i64x2; 4] = transmute(vld4q_lane_s64::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vduph_lane_p16() { - let a: i16x4 = i16x4::new(1, 1, 1, 4); - let e: p16 = 1; - let r: p16 = transmute(vduph_lane_p16::<2>(transmute(a))); + unsafe fn test_vld4_lane_p64() { + let a: [u64; 5] = [0, 1, 2, 2, 2]; + let b: [i64x1; 4] = [i64x1::new(0), i64x1::new(2), i64x1::new(2), i64x1::new(2)]; + let e: [i64x1; 4] = [i64x1::new(1), i64x1::new(2), i64x1::new(2), i64x1::new(2)]; + let r: [i64x1; 4] = transmute(vld4_lane_p64::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vduph_laneq_p16() { - let a: i16x8 = i16x8::new(1, 1, 1, 4, 1, 6, 7, 8); - let e: p16 = 1; - let r: p16 = transmute(vduph_laneq_p16::<4>(transmute(a))); + unsafe fn test_vld4q_lane_p64() { + let a: [u64; 9] = [0, 1, 2, 2, 2, 5, 6, 7, 8]; + let b: [i64x2; 4] = [i64x2::new(0, 2), i64x2::new(2, 2), i64x2::new(2, 16), i64x2::new(2, 18)]; + let e: [i64x2; 4] = [i64x2::new(1, 2), i64x2::new(2, 2), i64x2::new(2, 16), i64x2::new(2, 18)]; + let r: [i64x2; 4] = transmute(vld4q_lane_p64::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdups_lane_f32() { - let a: f32x2 = f32x2::new(1., 1.); - let e: f32 = 1.; - let r: f32 = transmute(vdups_lane_f32::<1>(transmute(a))); + unsafe fn test_vld4q_lane_p8() { + let a: [u8; 65] = [0, 1, 2, 2, 2, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16]; + let b: [i8x16; 4] = [i8x16::new(0, 2, 2, 2, 2, 16, 2, 18, 2, 20, 21, 22, 2, 24, 25, 26), i8x16::new(11, 12, 13, 14, 15, 16, 2, 18, 2, 20, 21, 22, 23, 24, 25, 26), i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8), i8x16::new(1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16)]; + let e: [i8x16; 4] = [i8x16::new(1, 2, 2, 2, 2, 16, 2, 18, 2, 20, 21, 22, 2, 24, 25, 26), i8x16::new(2, 12, 13, 14, 15, 16, 2, 18, 2, 20, 21, 22, 23, 24, 25, 26), i8x16::new(2, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8), i8x16::new(2, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16)]; + let r: [i8x16; 4] = transmute(vld4q_lane_p8::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdups_laneq_f32() { - let a: f32x4 = f32x4::new(1., 1., 1., 4.); - let e: f32 = 1.; - let r: f32 = transmute(vdups_laneq_f32::<2>(transmute(a))); + unsafe fn test_vld4q_lane_u8() { + let a: [u8; 65] = [0, 1, 2, 2, 2, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16]; + let b: [u8x16; 4] = [u8x16::new(0, 2, 2, 2, 2, 16, 2, 18, 2, 20, 21, 22, 2, 24, 25, 26), u8x16::new(11, 12, 13, 14, 15, 16, 2, 18, 2, 20, 21, 22, 23, 24, 25, 26), u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8), u8x16::new(1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16)]; + let e: [u8x16; 4] = [u8x16::new(1, 2, 2, 2, 2, 16, 2, 18, 2, 20, 21, 22, 2, 24, 25, 26), u8x16::new(2, 12, 13, 14, 15, 16, 2, 18, 2, 20, 21, 22, 23, 24, 25, 26), u8x16::new(2, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8), u8x16::new(2, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16)]; + let r: [u8x16; 4] = transmute(vld4q_lane_u8::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupd_lane_f64() { - let a: f64 = 1.; - let e: f64 = 1.; - let r: f64 = transmute(vdupd_lane_f64::<0>(transmute(a))); + unsafe fn test_vld4_lane_u64() { + let a: [u64; 5] = [0, 1, 2, 2, 2]; + let b: [u64x1; 4] = [u64x1::new(0), u64x1::new(2), u64x1::new(2), u64x1::new(2)]; + let e: [u64x1; 4] = [u64x1::new(1), u64x1::new(2), u64x1::new(2), u64x1::new(2)]; + let r: [u64x1; 4] = transmute(vld4_lane_u64::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupd_laneq_f64() { - let a: f64x2 = f64x2::new(1., 1.); - let e: f64 = 1.; - let r: f64 = transmute(vdupd_laneq_f64::<1>(transmute(a))); + unsafe fn test_vld4q_lane_u64() { + let a: [u64; 9] = [0, 1, 2, 2, 2, 5, 6, 7, 8]; + let b: [u64x2; 4] = [u64x2::new(0, 2), u64x2::new(2, 2), u64x2::new(2, 16), u64x2::new(2, 18)]; + let e: [u64x2; 4] = [u64x2::new(1, 2), u64x2::new(2, 2), u64x2::new(2, 16), u64x2::new(2, 18)]; + let r: [u64x2; 4] = transmute(vld4q_lane_u64::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vextq_p64() { - let a: i64x2 = i64x2::new(0, 8); - let b: i64x2 = i64x2::new(9, 11); - let e: i64x2 = i64x2::new(8, 9); - let r: i64x2 = transmute(vextq_p64::<1>(transmute(a), transmute(b))); + unsafe fn test_vld4_lane_f64() { + let a: [f64; 5] = [0., 1., 2., 2., 2.]; + let b: [f64; 4] = [0., 2., 2., 2.]; + let e: [f64; 4] = [1., 2., 2., 2.]; + let r: [f64; 4] = transmute(vld4_lane_f64::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vextq_f64() { - let a: f64x2 = f64x2::new(0., 2.); - let b: f64x2 = f64x2::new(3., 4.); - let e: f64x2 = f64x2::new(2., 3.); - let r: f64x2 = transmute(vextq_f64::<1>(transmute(a), transmute(b))); + unsafe fn test_vld4q_lane_f64() { + let a: [f64; 9] = [0., 1., 2., 2., 2., 5., 6., 7., 8.]; + let b: [f64x2; 4] = [f64x2::new(0., 2.), f64x2::new(2., 2.), f64x2::new(2., 16.), f64x2::new(2., 18.)]; + let e: [f64x2; 4] = [f64x2::new(1., 2.), f64x2::new(2., 2.), f64x2::new(2., 16.), f64x2::new(2., 18.)]; + let r: [f64x2; 4] = transmute(vld4q_lane_f64::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmla_f64() { - let a: f64 = 0.; - let b: f64 = 2.; - let c: f64 = 3.; - let e: f64 = 6.; - let r: f64 = transmute(vmla_f64(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst1_lane_f64() { + let a: [f64; 2] = [0., 1.]; + let e: [f64; 1] = [1.]; + let mut r: [f64; 1] = [0f64; 1]; + vst1_lane_f64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlaq_f64() { - let a: f64x2 = f64x2::new(0., 1.); - let b: f64x2 = f64x2::new(2., 2.); - let c: f64x2 = f64x2::new(3., 3.); - let e: f64x2 = f64x2::new(6., 7.); - let r: f64x2 = transmute(vmlaq_f64(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst1q_lane_f64() { + let a: [f64; 3] = [0., 1., 2.]; + let e: [f64; 2] = [1., 0.]; + let mut r: [f64; 2] = [0f64; 2]; + vst1q_lane_f64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_high_s8() { - let a: i16x8 = i16x8::new(8, 7, 6, 5, 4, 3, 2, 1); - let b: i8x16 = i8x16::new(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); - let c: i8x16 = i8x16::new(3, 3, 0, 1, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7); - let e: i16x8 = i16x8::new(8, 9, 10, 11, 12, 13, 14, 15); - let r: i16x8 = transmute(vmlal_high_s8(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst1_f64_x2() { + let a: [f64; 3] = [0., 1., 2.]; + let e: [f64; 2] = [1., 2.]; + let mut r: [f64; 2] = [0f64; 2]; + vst1_f64_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_high_s16() { - let a: i32x4 = i32x4::new(8, 7, 6, 5); - let b: i16x8 = i16x8::new(2, 2, 2, 2, 2, 2, 2, 2); - let c: i16x8 = i16x8::new(3, 3, 0, 1, 0, 1, 2, 3); - let e: i32x4 = i32x4::new(8, 9, 10, 11); - let r: i32x4 = transmute(vmlal_high_s16(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst1q_f64_x2() { + let a: [f64; 5] = [0., 1., 2., 3., 4.]; + let e: [f64; 4] = [1., 2., 3., 4.]; + let mut r: [f64; 4] = [0f64; 4]; + vst1q_f64_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_high_s32() { - let a: i64x2 = i64x2::new(8, 7); - let b: i32x4 = i32x4::new(2, 2, 2, 2); - let c: i32x4 = i32x4::new(3, 3, 0, 1); - let e: i64x2 = i64x2::new(8, 9); - let r: i64x2 = transmute(vmlal_high_s32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst1_f64_x3() { + let a: [f64; 4] = [0., 1., 2., 3.]; + let e: [f64; 3] = [1., 2., 3.]; + let mut r: [f64; 3] = [0f64; 3]; + vst1_f64_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_high_u8() { - let a: u16x8 = u16x8::new(8, 7, 6, 5, 4, 3, 2, 1); - let b: u8x16 = u8x16::new(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); - let c: u8x16 = u8x16::new(3, 3, 0, 1, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7); - let e: u16x8 = u16x8::new(8, 9, 10, 11, 12, 13, 14, 15); - let r: u16x8 = transmute(vmlal_high_u8(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst1q_f64_x3() { + let a: [f64; 7] = [0., 1., 2., 3., 4., 5., 6.]; + let e: [f64; 6] = [1., 2., 3., 4., 5., 6.]; + let mut r: [f64; 6] = [0f64; 6]; + vst1q_f64_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_high_u16() { - let a: u32x4 = u32x4::new(8, 7, 6, 5); - let b: u16x8 = u16x8::new(2, 2, 2, 2, 2, 2, 2, 2); - let c: u16x8 = u16x8::new(3, 3, 0, 1, 0, 1, 2, 3); - let e: u32x4 = u32x4::new(8, 9, 10, 11); - let r: u32x4 = transmute(vmlal_high_u16(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst1_f64_x4() { + let a: [f64; 5] = [0., 1., 2., 3., 4.]; + let e: [f64; 4] = [1., 2., 3., 4.]; + let mut r: [f64; 4] = [0f64; 4]; + vst1_f64_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_high_u32() { - let a: u64x2 = u64x2::new(8, 7); - let b: u32x4 = u32x4::new(2, 2, 2, 2); - let c: u32x4 = u32x4::new(3, 3, 0, 1); - let e: u64x2 = u64x2::new(8, 9); - let r: u64x2 = transmute(vmlal_high_u32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst1q_f64_x4() { + let a: [f64; 9] = [0., 1., 2., 3., 4., 5., 6., 7., 8.]; + let e: [f64; 8] = [1., 2., 3., 4., 5., 6., 7., 8.]; + let mut r: [f64; 8] = [0f64; 8]; + vst1q_f64_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_high_n_s16() { - let a: i32x4 = i32x4::new(8, 7, 6, 5); - let b: i16x8 = i16x8::new(3, 3, 0, 1, 0, 1, 2, 3); - let c: i16 = 2; - let e: i32x4 = i32x4::new(8, 9, 10, 11); - let r: i32x4 = transmute(vmlal_high_n_s16(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst2q_s64() { + let a: [i64; 5] = [0, 1, 2, 2, 3]; + let e: [i64; 4] = [1, 2, 2, 3]; + let mut r: [i64; 4] = [0i64; 4]; + vst2q_s64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_high_n_s32() { - let a: i64x2 = i64x2::new(8, 7); - let b: i32x4 = i32x4::new(3, 3, 0, 1); - let c: i32 = 2; - let e: i64x2 = i64x2::new(8, 9); - let r: i64x2 = transmute(vmlal_high_n_s32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst2q_u64() { + let a: [u64; 5] = [0, 1, 2, 2, 3]; + let e: [u64; 4] = [1, 2, 2, 3]; + let mut r: [u64; 4] = [0u64; 4]; + vst2q_u64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_high_n_u16() { - let a: u32x4 = u32x4::new(8, 7, 6, 5); - let b: u16x8 = u16x8::new(3, 3, 0, 1, 0, 1, 2, 3); - let c: u16 = 2; - let e: u32x4 = u32x4::new(8, 9, 10, 11); - let r: u32x4 = transmute(vmlal_high_n_u16(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst2q_p64() { + let a: [u64; 5] = [0, 1, 2, 2, 3]; + let e: [u64; 4] = [1, 2, 2, 3]; + let mut r: [u64; 4] = [0u64; 4]; + vst2q_p64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_high_n_u32() { - let a: u64x2 = u64x2::new(8, 7); - let b: u32x4 = u32x4::new(3, 3, 0, 1); - let c: u32 = 2; - let e: u64x2 = u64x2::new(8, 9); - let r: u64x2 = transmute(vmlal_high_n_u32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst2_f64() { + let a: [f64; 3] = [0., 1., 2.]; + let e: [f64; 2] = [1., 2.]; + let mut r: [f64; 2] = [0f64; 2]; + vst2_f64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_high_lane_s16() { - let a: i32x4 = i32x4::new(8, 7, 6, 5); - let b: i16x8 = i16x8::new(3, 3, 0, 1, 0, 1, 2, 3); - let c: i16x4 = i16x4::new(0, 2, 0, 0); - let e: i32x4 = i32x4::new(8, 9, 10, 11); - let r: i32x4 = transmute(vmlal_high_lane_s16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst2q_f64() { + let a: [f64; 5] = [0., 1., 2., 2., 3.]; + let e: [f64; 4] = [1., 2., 2., 3.]; + let mut r: [f64; 4] = [0f64; 4]; + vst2q_f64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_high_laneq_s16() { - let a: i32x4 = i32x4::new(8, 7, 6, 5); - let b: i16x8 = i16x8::new(3, 3, 0, 1, 0, 1, 2, 3); - let c: i16x8 = i16x8::new(0, 2, 0, 0, 0, 0, 0, 0); - let e: i32x4 = i32x4::new(8, 9, 10, 11); - let r: i32x4 = transmute(vmlal_high_laneq_s16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst2q_lane_s8() { + let a: [i8; 33] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]; + let e: [i8; 32] = [1, 2, 0, 0, 0, 0, 0, 0, 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 mut r: [i8; 32] = [0i8; 32]; + vst2q_lane_s8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_high_lane_s32() { - let a: i64x2 = i64x2::new(8, 7); - let b: i32x4 = i32x4::new(3, 3, 0, 1); - let c: i32x2 = i32x2::new(0, 2); - let e: i64x2 = i64x2::new(8, 9); - let r: i64x2 = transmute(vmlal_high_lane_s32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst2_lane_s64() { + let a: [i64; 3] = [0, 1, 2]; + let e: [i64; 2] = [1, 2]; + let mut r: [i64; 2] = [0i64; 2]; + vst2_lane_s64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_high_laneq_s32() { - let a: i64x2 = i64x2::new(8, 7); - let b: i32x4 = i32x4::new(3, 3, 0, 1); - let c: i32x4 = i32x4::new(0, 2, 0, 0); - let e: i64x2 = i64x2::new(8, 9); - let r: i64x2 = transmute(vmlal_high_laneq_s32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst2q_lane_s64() { + let a: [i64; 5] = [0, 1, 2, 2, 3]; + let e: [i64; 4] = [1, 2, 0, 0]; + let mut r: [i64; 4] = [0i64; 4]; + vst2q_lane_s64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_high_lane_u16() { - let a: u32x4 = u32x4::new(8, 7, 6, 5); - let b: u16x8 = u16x8::new(3, 3, 0, 1, 0, 1, 2, 3); - let c: u16x4 = u16x4::new(0, 2, 0, 0); - let e: u32x4 = u32x4::new(8, 9, 10, 11); - let r: u32x4 = transmute(vmlal_high_lane_u16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst2q_lane_u8() { + let a: [u8; 33] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]; + let e: [u8; 32] = [1, 2, 0, 0, 0, 0, 0, 0, 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 mut r: [u8; 32] = [0u8; 32]; + vst2q_lane_u8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_high_laneq_u16() { - let a: u32x4 = u32x4::new(8, 7, 6, 5); - let b: u16x8 = u16x8::new(3, 3, 0, 1, 0, 1, 2, 3); - let c: u16x8 = u16x8::new(0, 2, 0, 0, 0, 0, 0, 0); - let e: u32x4 = u32x4::new(8, 9, 10, 11); - let r: u32x4 = transmute(vmlal_high_laneq_u16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst2_lane_u64() { + let a: [u64; 3] = [0, 1, 2]; + let e: [u64; 2] = [1, 2]; + let mut r: [u64; 2] = [0u64; 2]; + vst2_lane_u64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_high_lane_u32() { - let a: u64x2 = u64x2::new(8, 7); - let b: u32x4 = u32x4::new(3, 3, 0, 1); - let c: u32x2 = u32x2::new(0, 2); - let e: u64x2 = u64x2::new(8, 9); - let r: u64x2 = transmute(vmlal_high_lane_u32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst2q_lane_u64() { + let a: [u64; 5] = [0, 1, 2, 2, 3]; + let e: [u64; 4] = [1, 2, 0, 0]; + let mut r: [u64; 4] = [0u64; 4]; + vst2q_lane_u64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_high_laneq_u32() { - let a: u64x2 = u64x2::new(8, 7); - let b: u32x4 = u32x4::new(3, 3, 0, 1); - let c: u32x4 = u32x4::new(0, 2, 0, 0); - let e: u64x2 = u64x2::new(8, 9); - let r: u64x2 = transmute(vmlal_high_laneq_u32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst2q_lane_p8() { + let a: [u8; 33] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]; + let e: [u8; 32] = [1, 2, 0, 0, 0, 0, 0, 0, 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 mut r: [u8; 32] = [0u8; 32]; + vst2q_lane_p8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmls_f64() { - let a: f64 = 6.; - let b: f64 = 2.; - let c: f64 = 3.; - let e: f64 = 0.; - let r: f64 = transmute(vmls_f64(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst2_lane_p64() { + let a: [u64; 3] = [0, 1, 2]; + let e: [u64; 2] = [1, 2]; + let mut r: [u64; 2] = [0u64; 2]; + vst2_lane_p64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsq_f64() { - let a: f64x2 = f64x2::new(6., 7.); - let b: f64x2 = f64x2::new(2., 2.); - let c: f64x2 = f64x2::new(3., 3.); - let e: f64x2 = f64x2::new(0., 1.); - let r: f64x2 = transmute(vmlsq_f64(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst2q_lane_p64() { + let a: [u64; 5] = [0, 1, 2, 2, 3]; + let e: [u64; 4] = [1, 2, 0, 0]; + let mut r: [u64; 4] = [0u64; 4]; + vst2q_lane_p64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_high_s8() { - let a: i16x8 = i16x8::new(14, 15, 16, 17, 18, 19, 20, 21); - let b: i8x16 = i8x16::new(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); - let c: i8x16 = i8x16::new(3, 3, 0, 1, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7); - let e: i16x8 = i16x8::new(14, 13, 12, 11, 10, 9, 8, 7); - let r: i16x8 = transmute(vmlsl_high_s8(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst2_lane_f64() { + let a: [f64; 3] = [0., 1., 2.]; + let e: [f64; 2] = [1., 2.]; + let mut r: [f64; 2] = [0f64; 2]; + vst2_lane_f64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_high_s16() { - let a: i32x4 = i32x4::new(14, 15, 16, 17); - let b: i16x8 = i16x8::new(2, 2, 2, 2, 2, 2, 2, 2); - let c: i16x8 = i16x8::new(3, 3, 0, 1, 0, 1, 2, 3); - let e: i32x4 = i32x4::new(14, 13, 12, 11); - let r: i32x4 = transmute(vmlsl_high_s16(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst2q_lane_f64() { + let a: [f64; 5] = [0., 1., 2., 2., 3.]; + let e: [f64; 4] = [1., 2., 0., 0.]; + let mut r: [f64; 4] = [0f64; 4]; + vst2q_lane_f64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_high_s32() { - let a: i64x2 = i64x2::new(14, 15); - let b: i32x4 = i32x4::new(2, 2, 2, 2); - let c: i32x4 = i32x4::new(3, 3, 0, 1); - let e: i64x2 = i64x2::new(14, 13); - let r: i64x2 = transmute(vmlsl_high_s32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst3q_s64() { + let a: [i64; 7] = [0, 1, 2, 2, 4, 2, 4]; + let e: [i64; 6] = [1, 2, 2, 2, 4, 4]; + let mut r: [i64; 6] = [0i64; 6]; + vst3q_s64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_high_u8() { - let a: u16x8 = u16x8::new(14, 15, 16, 17, 18, 19, 20, 21); - let b: u8x16 = u8x16::new(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); - let c: u8x16 = u8x16::new(3, 3, 0, 1, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7); - let e: u16x8 = u16x8::new(14, 13, 12, 11, 10, 9, 8, 7); - let r: u16x8 = transmute(vmlsl_high_u8(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst3q_u64() { + let a: [u64; 7] = [0, 1, 2, 2, 4, 2, 4]; + let e: [u64; 6] = [1, 2, 2, 2, 4, 4]; + let mut r: [u64; 6] = [0u64; 6]; + vst3q_u64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } - #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_high_u16() { - let a: u32x4 = u32x4::new(14, 15, 16, 17); - let b: u16x8 = u16x8::new(2, 2, 2, 2, 2, 2, 2, 2); - let c: u16x8 = u16x8::new(3, 3, 0, 1, 0, 1, 2, 3); - let e: u32x4 = u32x4::new(14, 13, 12, 11); - let r: u32x4 = transmute(vmlsl_high_u16(transmute(a), transmute(b), transmute(c))); + #[simd_test(enable = "neon")] + unsafe fn test_vst3q_p64() { + let a: [u64; 7] = [0, 1, 2, 2, 4, 2, 4]; + let e: [u64; 6] = [1, 2, 2, 2, 4, 4]; + let mut r: [u64; 6] = [0u64; 6]; + vst3q_p64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_high_u32() { - let a: u64x2 = u64x2::new(14, 15); - let b: u32x4 = u32x4::new(2, 2, 2, 2); - let c: u32x4 = u32x4::new(3, 3, 0, 1); - let e: u64x2 = u64x2::new(14, 13); - let r: u64x2 = transmute(vmlsl_high_u32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst3_f64() { + let a: [f64; 4] = [0., 1., 2., 2.]; + let e: [f64; 3] = [1., 2., 2.]; + let mut r: [f64; 3] = [0f64; 3]; + vst3_f64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_high_n_s16() { - let a: i32x4 = i32x4::new(14, 15, 16, 17); - let b: i16x8 = i16x8::new(3, 3, 0, 1, 0, 1, 2, 3); - let c: i16 = 2; - let e: i32x4 = i32x4::new(14, 13, 12, 11); - let r: i32x4 = transmute(vmlsl_high_n_s16(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst3q_f64() { + let a: [f64; 7] = [0., 1., 2., 2., 4., 2., 4.]; + let e: [f64; 6] = [1., 2., 2., 2., 4., 4.]; + let mut r: [f64; 6] = [0f64; 6]; + vst3q_f64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_high_n_s32() { - let a: i64x2 = i64x2::new(14, 15); - let b: i32x4 = i32x4::new(3, 3, 0, 1); - let c: i32 = 2; - let e: i64x2 = i64x2::new(14, 13); - let r: i64x2 = transmute(vmlsl_high_n_s32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst3q_lane_s8() { + let a: [i8; 49] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16, 25, 26, 27, 28, 29, 30, 31, 32, 2, 4, 7, 8, 13, 14, 15, 16, 41, 42, 43, 44, 45, 46, 47, 48]; + let e: [i8; 48] = [1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 mut r: [i8; 48] = [0i8; 48]; + vst3q_lane_s8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_high_n_u16() { - let a: u32x4 = u32x4::new(14, 15, 16, 17); - let b: u16x8 = u16x8::new(3, 3, 0, 1, 0, 1, 2, 3); - let c: u16 = 2; - let e: u32x4 = u32x4::new(14, 13, 12, 11); - let r: u32x4 = transmute(vmlsl_high_n_u16(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst3_lane_s64() { + let a: [i64; 4] = [0, 1, 2, 2]; + let e: [i64; 3] = [1, 2, 2]; + let mut r: [i64; 3] = [0i64; 3]; + vst3_lane_s64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_high_n_u32() { - let a: u64x2 = u64x2::new(14, 15); - let b: u32x4 = u32x4::new(3, 3, 0, 1); - let c: u32 = 2; - let e: u64x2 = u64x2::new(14, 13); - let r: u64x2 = transmute(vmlsl_high_n_u32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst3q_lane_s64() { + let a: [i64; 7] = [0, 1, 2, 2, 4, 2, 4]; + let e: [i64; 6] = [1, 2, 2, 0, 0, 0]; + let mut r: [i64; 6] = [0i64; 6]; + vst3q_lane_s64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_high_lane_s16() { - let a: i32x4 = i32x4::new(14, 15, 16, 17); - let b: i16x8 = i16x8::new(3, 3, 0, 1, 0, 1, 2, 3); - let c: i16x4 = i16x4::new(0, 2, 0, 0); - let e: i32x4 = i32x4::new(14, 13, 12, 11); - let r: i32x4 = transmute(vmlsl_high_lane_s16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst3q_lane_u8() { + let a: [u8; 49] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16, 25, 26, 27, 28, 29, 30, 31, 32, 2, 4, 7, 8, 13, 14, 15, 16, 41, 42, 43, 44, 45, 46, 47, 48]; + let e: [u8; 48] = [1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 mut r: [u8; 48] = [0u8; 48]; + vst3q_lane_u8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_high_laneq_s16() { - let a: i32x4 = i32x4::new(14, 15, 16, 17); - let b: i16x8 = i16x8::new(3, 3, 0, 1, 0, 1, 2, 3); - let c: i16x8 = i16x8::new(0, 2, 0, 0, 0, 0, 0, 0); - let e: i32x4 = i32x4::new(14, 13, 12, 11); - let r: i32x4 = transmute(vmlsl_high_laneq_s16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst3_lane_u64() { + let a: [u64; 4] = [0, 1, 2, 2]; + let e: [u64; 3] = [1, 2, 2]; + let mut r: [u64; 3] = [0u64; 3]; + vst3_lane_u64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_high_lane_s32() { - let a: i64x2 = i64x2::new(14, 15); - let b: i32x4 = i32x4::new(3, 3, 0, 1); - let c: i32x2 = i32x2::new(0, 2); - let e: i64x2 = i64x2::new(14, 13); - let r: i64x2 = transmute(vmlsl_high_lane_s32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst3q_lane_u64() { + let a: [u64; 7] = [0, 1, 2, 2, 4, 2, 4]; + let e: [u64; 6] = [1, 2, 2, 0, 0, 0]; + let mut r: [u64; 6] = [0u64; 6]; + vst3q_lane_u64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_high_laneq_s32() { - let a: i64x2 = i64x2::new(14, 15); - let b: i32x4 = i32x4::new(3, 3, 0, 1); - let c: i32x4 = i32x4::new(0, 2, 0, 0); - let e: i64x2 = i64x2::new(14, 13); - let r: i64x2 = transmute(vmlsl_high_laneq_s32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst3q_lane_p8() { + let a: [u8; 49] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16, 25, 26, 27, 28, 29, 30, 31, 32, 2, 4, 7, 8, 13, 14, 15, 16, 41, 42, 43, 44, 45, 46, 47, 48]; + let e: [u8; 48] = [1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 mut r: [u8; 48] = [0u8; 48]; + vst3q_lane_p8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_high_lane_u16() { - let a: u32x4 = u32x4::new(14, 15, 16, 17); - let b: u16x8 = u16x8::new(3, 3, 0, 1, 0, 1, 2, 3); - let c: u16x4 = u16x4::new(0, 2, 0, 0); - let e: u32x4 = u32x4::new(14, 13, 12, 11); - let r: u32x4 = transmute(vmlsl_high_lane_u16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst3_lane_p64() { + let a: [u64; 4] = [0, 1, 2, 2]; + let e: [u64; 3] = [1, 2, 2]; + let mut r: [u64; 3] = [0u64; 3]; + vst3_lane_p64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_high_laneq_u16() { - let a: u32x4 = u32x4::new(14, 15, 16, 17); - let b: u16x8 = u16x8::new(3, 3, 0, 1, 0, 1, 2, 3); - let c: u16x8 = u16x8::new(0, 2, 0, 0, 0, 0, 0, 0); - let e: u32x4 = u32x4::new(14, 13, 12, 11); - let r: u32x4 = transmute(vmlsl_high_laneq_u16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst3q_lane_p64() { + let a: [u64; 7] = [0, 1, 2, 2, 4, 2, 4]; + let e: [u64; 6] = [1, 2, 2, 0, 0, 0]; + let mut r: [u64; 6] = [0u64; 6]; + vst3q_lane_p64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_high_lane_u32() { - let a: u64x2 = u64x2::new(14, 15); - let b: u32x4 = u32x4::new(3, 3, 0, 1); - let c: u32x2 = u32x2::new(0, 2); - let e: u64x2 = u64x2::new(14, 13); - let r: u64x2 = transmute(vmlsl_high_lane_u32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst3_lane_f64() { + let a: [f64; 4] = [0., 1., 2., 2.]; + let e: [f64; 3] = [1., 2., 2.]; + let mut r: [f64; 3] = [0f64; 3]; + vst3_lane_f64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_high_laneq_u32() { - let a: u64x2 = u64x2::new(14, 15); - let b: u32x4 = u32x4::new(3, 3, 0, 1); - let c: u32x4 = u32x4::new(0, 2, 0, 0); - let e: u64x2 = u64x2::new(14, 13); - let r: u64x2 = transmute(vmlsl_high_laneq_u32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vst3q_lane_f64() { + let a: [f64; 7] = [0., 1., 2., 2., 3., 2., 3.]; + let e: [f64; 6] = [1., 2., 2., 0., 0., 0.]; + let mut r: [f64; 6] = [0f64; 6]; + vst3q_lane_f64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmovn_high_s16() { - let a: i8x8 = i8x8::new(0, 1, 2, 3, 2, 3, 4, 5); - let b: i16x8 = i16x8::new(2, 3, 4, 5, 12, 13, 14, 15); - let e: i8x16 = i8x16::new(0, 1, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 12, 13, 14, 15); - let r: i8x16 = transmute(vmovn_high_s16(transmute(a), transmute(b))); + unsafe fn test_vst4q_s64() { + let a: [i64; 9] = [0, 1, 2, 2, 6, 2, 6, 6, 8]; + let e: [i64; 8] = [1, 2, 2, 6, 2, 6, 6, 8]; + let mut r: [i64; 8] = [0i64; 8]; + vst4q_s64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmovn_high_s32() { - let a: i16x4 = i16x4::new(0, 1, 2, 3); - let b: i32x4 = i32x4::new(2, 3, 4, 5); - let e: i16x8 = i16x8::new(0, 1, 2, 3, 2, 3, 4, 5); - let r: i16x8 = transmute(vmovn_high_s32(transmute(a), transmute(b))); + unsafe fn test_vst4q_u64() { + let a: [u64; 9] = [0, 1, 2, 2, 6, 2, 6, 6, 8]; + let e: [u64; 8] = [1, 2, 2, 6, 2, 6, 6, 8]; + let mut r: [u64; 8] = [0u64; 8]; + vst4q_u64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmovn_high_s64() { - let a: i32x2 = i32x2::new(0, 1); - let b: i64x2 = i64x2::new(2, 3); - let e: i32x4 = i32x4::new(0, 1, 2, 3); - let r: i32x4 = transmute(vmovn_high_s64(transmute(a), transmute(b))); + unsafe fn test_vst4q_p64() { + let a: [u64; 9] = [0, 1, 2, 2, 6, 2, 6, 6, 8]; + let e: [u64; 8] = [1, 2, 2, 6, 2, 6, 6, 8]; + let mut r: [u64; 8] = [0u64; 8]; + vst4q_p64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmovn_high_u16() { - let a: u8x8 = u8x8::new(0, 1, 2, 3, 2, 3, 4, 5); - let b: u16x8 = u16x8::new(2, 3, 4, 5, 12, 13, 14, 15); - let e: u8x16 = u8x16::new(0, 1, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 12, 13, 14, 15); - let r: u8x16 = transmute(vmovn_high_u16(transmute(a), transmute(b))); + unsafe fn test_vst4_f64() { + let a: [f64; 5] = [0., 1., 2., 2., 6.]; + let e: [f64; 4] = [1., 2., 2., 6.]; + let mut r: [f64; 4] = [0f64; 4]; + vst4_f64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmovn_high_u32() { - let a: u16x4 = u16x4::new(0, 1, 2, 3); - let b: u32x4 = u32x4::new(2, 3, 4, 5); - let e: u16x8 = u16x8::new(0, 1, 2, 3, 2, 3, 4, 5); - let r: u16x8 = transmute(vmovn_high_u32(transmute(a), transmute(b))); + unsafe fn test_vst4q_f64() { + let a: [f64; 9] = [0., 1., 2., 2., 6., 2., 6., 6., 8.]; + let e: [f64; 8] = [1., 2., 2., 6., 2., 6., 6., 8.]; + let mut r: [f64; 8] = [0f64; 8]; + vst4q_f64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmovn_high_u64() { - let a: u32x2 = u32x2::new(0, 1); - let b: u64x2 = u64x2::new(2, 3); - let e: u32x4 = u32x4::new(0, 1, 2, 3); - let r: u32x4 = transmute(vmovn_high_u64(transmute(a), transmute(b))); + unsafe fn test_vst4q_lane_s8() { + let a: [i8; 65] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48, 6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64]; + let e: [i8; 64] = [1, 2, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 mut r: [i8; 64] = [0i8; 64]; + vst4q_lane_s8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vneg_s64() { - let a: i64x1 = i64x1::new(0); - let e: i64x1 = i64x1::new(0); - let r: i64x1 = transmute(vneg_s64(transmute(a))); + unsafe fn test_vst4_lane_s64() { + let a: [i64; 5] = [0, 1, 2, 2, 6]; + let e: [i64; 4] = [1, 2, 2, 6]; + let mut r: [i64; 4] = [0i64; 4]; + vst4_lane_s64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vnegq_s64() { - let a: i64x2 = i64x2::new(0, 1); - let e: i64x2 = i64x2::new(0, -1); - let r: i64x2 = transmute(vnegq_s64(transmute(a))); + unsafe fn test_vst4q_lane_s64() { + let a: [i64; 9] = [0, 1, 2, 2, 6, 2, 6, 6, 8]; + let e: [i64; 8] = [1, 2, 2, 6, 0, 0, 0, 0]; + let mut r: [i64; 8] = [0i64; 8]; + vst4q_lane_s64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vneg_f64() { - let a: f64 = 0.; - let e: f64 = 0.; - let r: f64 = transmute(vneg_f64(transmute(a))); + unsafe fn test_vst4q_lane_u8() { + let a: [u8; 65] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48, 6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64]; + let e: [u8; 64] = [1, 2, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 mut r: [u8; 64] = [0u8; 64]; + vst4q_lane_u8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vnegq_f64() { - let a: f64x2 = f64x2::new(0., 1.); - let e: f64x2 = f64x2::new(0., -1.); - let r: f64x2 = transmute(vnegq_f64(transmute(a))); + unsafe fn test_vst4_lane_u64() { + let a: [u64; 5] = [0, 1, 2, 2, 6]; + let e: [u64; 4] = [1, 2, 2, 6]; + let mut r: [u64; 4] = [0u64; 4]; + vst4_lane_u64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqneg_s64() { - let a: i64x1 = i64x1::new(-9223372036854775808); - let e: i64x1 = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); - let r: i64x1 = transmute(vqneg_s64(transmute(a))); + unsafe fn test_vst4q_lane_u64() { + let a: [u64; 9] = [0, 1, 2, 2, 6, 2, 6, 6, 8]; + let e: [u64; 8] = [1, 2, 2, 6, 0, 0, 0, 0]; + let mut r: [u64; 8] = [0u64; 8]; + vst4q_lane_u64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqnegq_s64() { - let a: i64x2 = i64x2::new(-9223372036854775808, 0); - let e: i64x2 = i64x2::new(0x7F_FF_FF_FF_FF_FF_FF_FF, 0); - let r: i64x2 = transmute(vqnegq_s64(transmute(a))); + unsafe fn test_vst4q_lane_p8() { + let a: [u8; 65] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48, 6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64]; + let e: [u8; 64] = [1, 2, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 mut r: [u8; 64] = [0u8; 64]; + vst4q_lane_p8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqsubb_s8() { - let a: i8 = 42; - let b: i8 = 1; - let e: i8 = 41; - let r: i8 = transmute(vqsubb_s8(transmute(a), transmute(b))); + unsafe fn test_vst4_lane_p64() { + let a: [u64; 5] = [0, 1, 2, 2, 6]; + let e: [u64; 4] = [1, 2, 2, 6]; + let mut r: [u64; 4] = [0u64; 4]; + vst4_lane_p64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqsubh_s16() { - let a: i16 = 42; - let b: i16 = 1; - let e: i16 = 41; - let r: i16 = transmute(vqsubh_s16(transmute(a), transmute(b))); + unsafe fn test_vst4q_lane_p64() { + let a: [u64; 9] = [0, 1, 2, 2, 6, 2, 6, 6, 8]; + let e: [u64; 8] = [1, 2, 2, 6, 0, 0, 0, 0]; + let mut r: [u64; 8] = [0u64; 8]; + vst4q_lane_p64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqsubb_u8() { - let a: u8 = 42; - let b: u8 = 1; - let e: u8 = 41; - let r: u8 = transmute(vqsubb_u8(transmute(a), transmute(b))); + unsafe fn test_vst4_lane_f64() { + let a: [f64; 5] = [0., 1., 2., 2., 6.]; + let e: [f64; 4] = [1., 2., 2., 6.]; + let mut r: [f64; 4] = [0f64; 4]; + vst4_lane_f64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqsubh_u16() { - let a: u16 = 42; - let b: u16 = 1; - let e: u16 = 41; - let r: u16 = transmute(vqsubh_u16(transmute(a), transmute(b))); + unsafe fn test_vst4q_lane_f64() { + let a: [f64; 9] = [0., 1., 2., 2., 6., 2., 6., 6., 8.]; + let e: [f64; 8] = [1., 2., 2., 6., 0., 0., 0., 0.]; + let mut r: [f64; 8] = [0f64; 8]; + vst4q_lane_f64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqsubs_u32() { - let a: u32 = 42; - let b: u32 = 1; - let e: u32 = 41; - let r: u32 = transmute(vqsubs_u32(transmute(a), transmute(b))); + unsafe fn test_vmul_f64() { + let a: f64 = 1.0; + let b: f64 = 2.0; + let e: f64 = 2.0; + let r: f64 = transmute(vmul_f64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqsubd_u64() { - let a: u64 = 42; - let b: u64 = 1; - let e: u64 = 41; - let r: u64 = transmute(vqsubd_u64(transmute(a), transmute(b))); + unsafe fn test_vmulq_f64() { + let a: f64x2 = f64x2::new(1.0, 2.0); + let b: f64x2 = f64x2::new(2.0, 3.0); + let e: f64x2 = f64x2::new(2.0, 6.0); + let r: f64x2 = transmute(vmulq_f64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqsubs_s32() { - let a: i32 = 42; - let b: i32 = 1; - let e: i32 = 41; - let r: i32 = transmute(vqsubs_s32(transmute(a), transmute(b))); + unsafe fn test_vmul_n_f64() { + let a: f64 = 1.; + let b: f64 = 2.; + let e: f64 = 2.; + let r: f64 = transmute(vmul_n_f64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqsubd_s64() { - let a: i64 = 42; - let b: i64 = 1; - let e: i64 = 41; - let r: i64 = transmute(vqsubd_s64(transmute(a), transmute(b))); + unsafe fn test_vmulq_n_f64() { + let a: f64x2 = f64x2::new(1., 2.); + let b: f64 = 2.; + let e: f64x2 = f64x2::new(2., 4.); + let r: f64x2 = transmute(vmulq_n_f64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrbit_s8() { - let a: i8x8 = i8x8::new(0, 2, 4, 6, 8, 10, 12, 14); - let e: i8x8 = i8x8::new(0, 64, 32, 96, 16, 80, 48, 112); - let r: i8x8 = transmute(vrbit_s8(transmute(a))); + unsafe fn test_vmul_lane_f64() { + let a: f64 = 1.; + let b: f64 = 2.; + let e: f64 = 2.; + let r: f64 = transmute(vmul_lane_f64::<0>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrbitq_s8() { - let a: i8x16 = i8x16::new(0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30); - let e: i8x16 = i8x16::new(0, 64, 32, 96, 16, 80, 48, 112, 8, 72, 40, 104, 24, 88, 56, 120); - let r: i8x16 = transmute(vrbitq_s8(transmute(a))); + unsafe fn test_vmul_laneq_f64() { + let a: f64 = 1.; + let b: f64x2 = f64x2::new(2., 0.); + let e: f64 = 2.; + let r: f64 = transmute(vmul_laneq_f64::<0>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrbit_u8() { - let a: u8x8 = u8x8::new(0, 2, 4, 6, 8, 10, 12, 14); - let e: u8x8 = u8x8::new(0, 64, 32, 96, 16, 80, 48, 112); - let r: u8x8 = transmute(vrbit_u8(transmute(a))); + unsafe fn test_vmulq_lane_f64() { + let a: f64x2 = f64x2::new(1., 2.); + let b: f64 = 2.; + let e: f64x2 = f64x2::new(2., 4.); + let r: f64x2 = transmute(vmulq_lane_f64::<0>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrbitq_u8() { - let a: u8x16 = u8x16::new(0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30); - let e: u8x16 = u8x16::new(0, 64, 32, 96, 16, 80, 48, 112, 8, 72, 40, 104, 24, 88, 56, 120); - let r: u8x16 = transmute(vrbitq_u8(transmute(a))); + unsafe fn test_vmulq_laneq_f64() { + let a: f64x2 = f64x2::new(1., 2.); + let b: f64x2 = f64x2::new(2., 0.); + let e: f64x2 = f64x2::new(2., 4.); + let r: f64x2 = transmute(vmulq_laneq_f64::<0>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrbit_p8() { - let a: i8x8 = i8x8::new(0, 2, 4, 6, 8, 10, 12, 14); - let e: i8x8 = i8x8::new(0, 64, 32, 96, 16, 80, 48, 112); - let r: i8x8 = transmute(vrbit_p8(transmute(a))); + unsafe fn test_vmuls_lane_f32() { + let a: f32 = 1.; + let b: f32x2 = f32x2::new(2., 0.); + let e: f32 = 2.; + let r: f32 = transmute(vmuls_lane_f32::<0>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmuls_laneq_f32() { + let a: f32 = 1.; + let b: f32x4 = f32x4::new(2., 0., 0., 0.); + let e: f32 = 2.; + let r: f32 = transmute(vmuls_laneq_f32::<0>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmuld_lane_f64() { + let a: f64 = 1.; + let b: f64 = 2.; + let e: f64 = 2.; + let r: f64 = transmute(vmuld_lane_f64::<0>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrbitq_p8() { - let a: i8x16 = i8x16::new(0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30); - let e: i8x16 = i8x16::new(0, 64, 32, 96, 16, 80, 48, 112, 8, 72, 40, 104, 24, 88, 56, 120); - let r: i8x16 = transmute(vrbitq_p8(transmute(a))); + unsafe fn test_vmuld_laneq_f64() { + let a: f64 = 1.; + let b: f64x2 = f64x2::new(2., 0.); + let e: f64 = 2.; + let r: f64 = transmute(vmuld_laneq_f64::<0>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrndx_f32() { - let a: f32x2 = f32x2::new(-1.5, 0.5); - let e: f32x2 = f32x2::new(-2.0, 0.0); - let r: f32x2 = transmute(vrndx_f32(transmute(a))); + unsafe fn test_vmull_high_s8() { + let a: i8x16 = i8x16::new(1, 2, 9, 10, 9, 10, 11, 12, 9, 10, 11, 12, 13, 14, 15, 16); + let b: i8x16 = i8x16::new(1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2); + let e: i16x8 = i16x8::new(9, 20, 11, 24, 13, 28, 15, 32); + let r: i16x8 = transmute(vmull_high_s8(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrndxq_f32() { - let a: f32x4 = f32x4::new(-1.5, 0.5, 1.5, 2.5); - let e: f32x4 = f32x4::new(-2.0, 0.0, 2.0, 2.0); - let r: f32x4 = transmute(vrndxq_f32(transmute(a))); + unsafe fn test_vmull_high_s16() { + let a: i16x8 = i16x8::new(1, 2, 9, 10, 9, 10, 11, 12); + let b: i16x8 = i16x8::new(1, 2, 1, 2, 1, 2, 1, 2); + let e: i32x4 = i32x4::new(9, 20, 11, 24); + let r: i32x4 = transmute(vmull_high_s16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrndx_f64() { - let a: f64 = -1.5; - let e: f64 = -2.0; - let r: f64 = transmute(vrndx_f64(transmute(a))); + unsafe fn test_vmull_high_s32() { + let a: i32x4 = i32x4::new(1, 2, 9, 10); + let b: i32x4 = i32x4::new(1, 2, 1, 2); + let e: i64x2 = i64x2::new(9, 20); + let r: i64x2 = transmute(vmull_high_s32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrndxq_f64() { - let a: f64x2 = f64x2::new(-1.5, 0.5); - let e: f64x2 = f64x2::new(-2.0, 0.0); - let r: f64x2 = transmute(vrndxq_f64(transmute(a))); + unsafe fn test_vmull_high_u8() { + let a: u8x16 = u8x16::new(1, 2, 9, 10, 9, 10, 11, 12, 9, 10, 11, 12, 13, 14, 15, 16); + let b: u8x16 = u8x16::new(1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2); + let e: u16x8 = u16x8::new(9, 20, 11, 24, 13, 28, 15, 32); + let r: u16x8 = transmute(vmull_high_u8(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrnda_f32() { - let a: f32x2 = f32x2::new(-1.5, 0.5); - let e: f32x2 = f32x2::new(-2.0, 1.0); - let r: f32x2 = transmute(vrnda_f32(transmute(a))); + unsafe fn test_vmull_high_u16() { + let a: u16x8 = u16x8::new(1, 2, 9, 10, 9, 10, 11, 12); + let b: u16x8 = u16x8::new(1, 2, 1, 2, 1, 2, 1, 2); + let e: u32x4 = u32x4::new(9, 20, 11, 24); + let r: u32x4 = transmute(vmull_high_u16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrndaq_f32() { - let a: f32x4 = f32x4::new(-1.5, 0.5, 1.5, 2.5); - let e: f32x4 = f32x4::new(-2.0, 1.0, 2.0, 3.0); - let r: f32x4 = transmute(vrndaq_f32(transmute(a))); + unsafe fn test_vmull_high_u32() { + let a: u32x4 = u32x4::new(1, 2, 9, 10); + let b: u32x4 = u32x4::new(1, 2, 1, 2); + let e: u64x2 = u64x2::new(9, 20); + let r: u64x2 = transmute(vmull_high_u32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrnda_f64() { - let a: f64 = -1.5; - let e: f64 = -2.0; - let r: f64 = transmute(vrnda_f64(transmute(a))); + unsafe fn test_vmull_p64() { + let a: p64 = 15; + let b: p64 = 3; + let e: p128 = 17; + let r: p128 = transmute(vmull_p64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrndaq_f64() { - let a: f64x2 = f64x2::new(-1.5, 0.5); - let e: f64x2 = f64x2::new(-2.0, 1.0); - let r: f64x2 = transmute(vrndaq_f64(transmute(a))); + unsafe fn test_vmull_high_p8() { + let a: i8x16 = i8x16::new(1, 2, 9, 10, 9, 10, 11, 12, 9, 10, 11, 12, 13, 14, 15, 16); + let b: i8x16 = i8x16::new(1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3); + let e: i16x8 = i16x8::new(9, 30, 11, 20, 13, 18, 15, 48); + let r: i16x8 = transmute(vmull_high_p8(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrndn_f64() { - let a: f64 = -1.5; - let e: f64 = -2.0; - let r: f64 = transmute(vrndn_f64(transmute(a))); + unsafe fn test_vmull_high_p64() { + let a: i64x2 = i64x2::new(1, 15); + let b: i64x2 = i64x2::new(1, 3); + let e: p128 = 17; + let r: p128 = transmute(vmull_high_p64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrndnq_f64() { - let a: f64x2 = f64x2::new(-1.5, 0.5); - let e: f64x2 = f64x2::new(-2.0, 0.0); - let r: f64x2 = transmute(vrndnq_f64(transmute(a))); + unsafe fn test_vmull_high_n_s16() { + let a: i16x8 = i16x8::new(1, 2, 9, 10, 9, 10, 11, 12); + let b: i16 = 2; + let e: i32x4 = i32x4::new(18, 20, 22, 24); + let r: i32x4 = transmute(vmull_high_n_s16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrndm_f32() { - let a: f32x2 = f32x2::new(-1.5, 0.5); - let e: f32x2 = f32x2::new(-2.0, 0.0); - let r: f32x2 = transmute(vrndm_f32(transmute(a))); + unsafe fn test_vmull_high_n_s32() { + let a: i32x4 = i32x4::new(1, 2, 9, 10); + let b: i32 = 2; + let e: i64x2 = i64x2::new(18, 20); + let r: i64x2 = transmute(vmull_high_n_s32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrndmq_f32() { - let a: f32x4 = f32x4::new(-1.5, 0.5, 1.5, 2.5); - let e: f32x4 = f32x4::new(-2.0, 0.0, 1.0, 2.0); - let r: f32x4 = transmute(vrndmq_f32(transmute(a))); + unsafe fn test_vmull_high_n_u16() { + let a: u16x8 = u16x8::new(1, 2, 9, 10, 9, 10, 11, 12); + let b: u16 = 2; + let e: u32x4 = u32x4::new(18, 20, 22, 24); + let r: u32x4 = transmute(vmull_high_n_u16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrndm_f64() { - let a: f64 = -1.5; - let e: f64 = -2.0; - let r: f64 = transmute(vrndm_f64(transmute(a))); + unsafe fn test_vmull_high_n_u32() { + let a: u32x4 = u32x4::new(1, 2, 9, 10); + let b: u32 = 2; + let e: u64x2 = u64x2::new(18, 20); + let r: u64x2 = transmute(vmull_high_n_u32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrndmq_f64() { - let a: f64x2 = f64x2::new(-1.5, 0.5); - let e: f64x2 = f64x2::new(-2.0, 0.0); - let r: f64x2 = transmute(vrndmq_f64(transmute(a))); + unsafe fn test_vmull_high_lane_s16() { + let a: i16x8 = i16x8::new(1, 2, 9, 10, 9, 10, 11, 12); + let b: i16x4 = i16x4::new(0, 2, 0, 0); + let e: i32x4 = i32x4::new(18, 20, 22, 24); + let r: i32x4 = transmute(vmull_high_lane_s16::<1>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrndp_f32() { - let a: f32x2 = f32x2::new(-1.5, 0.5); - let e: f32x2 = f32x2::new(-1.0, 1.0); - let r: f32x2 = transmute(vrndp_f32(transmute(a))); + unsafe fn test_vmull_high_laneq_s16() { + let a: i16x8 = i16x8::new(1, 2, 9, 10, 9, 10, 11, 12); + let b: i16x8 = i16x8::new(0, 2, 0, 0, 0, 0, 0, 0); + let e: i32x4 = i32x4::new(18, 20, 22, 24); + let r: i32x4 = transmute(vmull_high_laneq_s16::<1>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrndpq_f32() { - let a: f32x4 = f32x4::new(-1.5, 0.5, 1.5, 2.5); - let e: f32x4 = f32x4::new(-1.0, 1.0, 2.0, 3.0); - let r: f32x4 = transmute(vrndpq_f32(transmute(a))); + unsafe fn test_vmull_high_lane_s32() { + let a: i32x4 = i32x4::new(1, 2, 9, 10); + let b: i32x2 = i32x2::new(0, 2); + let e: i64x2 = i64x2::new(18, 20); + let r: i64x2 = transmute(vmull_high_lane_s32::<1>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrndp_f64() { - let a: f64 = -1.5; - let e: f64 = -1.0; - let r: f64 = transmute(vrndp_f64(transmute(a))); + unsafe fn test_vmull_high_laneq_s32() { + let a: i32x4 = i32x4::new(1, 2, 9, 10); + let b: i32x4 = i32x4::new(0, 2, 0, 0); + let e: i64x2 = i64x2::new(18, 20); + let r: i64x2 = transmute(vmull_high_laneq_s32::<1>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrndpq_f64() { - let a: f64x2 = f64x2::new(-1.5, 0.5); - let e: f64x2 = f64x2::new(-1.0, 1.0); - let r: f64x2 = transmute(vrndpq_f64(transmute(a))); + unsafe fn test_vmull_high_lane_u16() { + let a: u16x8 = u16x8::new(1, 2, 9, 10, 9, 10, 11, 12); + let b: u16x4 = u16x4::new(0, 2, 0, 0); + let e: u32x4 = u32x4::new(18, 20, 22, 24); + let r: u32x4 = transmute(vmull_high_lane_u16::<1>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrnd_f32() { - let a: f32x2 = f32x2::new(-1.5, 0.5); - let e: f32x2 = f32x2::new(-1.0, 0.0); - let r: f32x2 = transmute(vrnd_f32(transmute(a))); + unsafe fn test_vmull_high_laneq_u16() { + let a: u16x8 = u16x8::new(1, 2, 9, 10, 9, 10, 11, 12); + let b: u16x8 = u16x8::new(0, 2, 0, 0, 0, 0, 0, 0); + let e: u32x4 = u32x4::new(18, 20, 22, 24); + let r: u32x4 = transmute(vmull_high_laneq_u16::<1>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrndq_f32() { - let a: f32x4 = f32x4::new(-1.5, 0.5, 1.5, 2.5); - let e: f32x4 = f32x4::new(-1.0, 0.0, 1.0, 2.0); - let r: f32x4 = transmute(vrndq_f32(transmute(a))); + unsafe fn test_vmull_high_lane_u32() { + let a: u32x4 = u32x4::new(1, 2, 9, 10); + let b: u32x2 = u32x2::new(0, 2); + let e: u64x2 = u64x2::new(18, 20); + let r: u64x2 = transmute(vmull_high_lane_u32::<1>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrnd_f64() { - let a: f64 = -1.5; - let e: f64 = -1.0; - let r: f64 = transmute(vrnd_f64(transmute(a))); + unsafe fn test_vmull_high_laneq_u32() { + let a: u32x4 = u32x4::new(1, 2, 9, 10); + let b: u32x4 = u32x4::new(0, 2, 0, 0); + let e: u64x2 = u64x2::new(18, 20); + let r: u64x2 = transmute(vmull_high_laneq_u32::<1>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrndq_f64() { - let a: f64x2 = f64x2::new(-1.5, 0.5); - let e: f64x2 = f64x2::new(-1.0, 0.0); - let r: f64x2 = transmute(vrndq_f64(transmute(a))); + unsafe fn test_vmulx_f32() { + let a: f32x2 = f32x2::new(1., 2.); + let b: f32x2 = f32x2::new(2., 2.); + let e: f32x2 = f32x2::new(2., 4.); + let r: f32x2 = transmute(vmulx_f32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrndi_f32() { - let a: f32x2 = f32x2::new(-1.5, 0.5); - let e: f32x2 = f32x2::new(-2.0, 0.0); - let r: f32x2 = transmute(vrndi_f32(transmute(a))); + unsafe fn test_vmulxq_f32() { + let a: f32x4 = f32x4::new(1., 2., 3., 4.); + let b: f32x4 = f32x4::new(2., 2., 2., 2.); + let e: f32x4 = f32x4::new(2., 4., 6., 8.); + let r: f32x4 = transmute(vmulxq_f32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrndiq_f32() { - let a: f32x4 = f32x4::new(-1.5, 0.5, 1.5, 2.5); - let e: f32x4 = f32x4::new(-2.0, 0.0, 2.0, 2.0); - let r: f32x4 = transmute(vrndiq_f32(transmute(a))); + unsafe fn test_vmulx_f64() { + let a: f64 = 1.; + let b: f64 = 2.; + let e: f64 = 2.; + let r: f64 = transmute(vmulx_f64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrndi_f64() { - let a: f64 = -1.5; - let e: f64 = -2.0; - let r: f64 = transmute(vrndi_f64(transmute(a))); + unsafe fn test_vmulxq_f64() { + let a: f64x2 = f64x2::new(1., 2.); + let b: f64x2 = f64x2::new(2., 2.); + let e: f64x2 = f64x2::new(2., 4.); + let r: f64x2 = transmute(vmulxq_f64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrndiq_f64() { - let a: f64x2 = f64x2::new(-1.5, 0.5); - let e: f64x2 = f64x2::new(-2.0, 0.0); - let r: f64x2 = transmute(vrndiq_f64(transmute(a))); + unsafe fn test_vmulx_lane_f64() { + let a: f64 = 1.; + let b: f64 = 2.; + let e: f64 = 2.; + let r: f64 = transmute(vmulx_lane_f64::<0>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqaddb_s8() { - let a: i8 = 42; - let b: i8 = 1; - let e: i8 = 43; - let r: i8 = transmute(vqaddb_s8(transmute(a), transmute(b))); + unsafe fn test_vmulx_laneq_f64() { + let a: f64 = 1.; + let b: f64x2 = f64x2::new(2., 0.); + let e: f64 = 2.; + let r: f64 = transmute(vmulx_laneq_f64::<0>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqaddh_s16() { - let a: i16 = 42; - let b: i16 = 1; - let e: i16 = 43; - let r: i16 = transmute(vqaddh_s16(transmute(a), transmute(b))); + unsafe fn test_vmulx_lane_f32() { + let a: f32x2 = f32x2::new(1., 2.); + let b: f32x2 = f32x2::new(2., 0.); + let e: f32x2 = f32x2::new(2., 4.); + let r: f32x2 = transmute(vmulx_lane_f32::<0>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqaddb_u8() { - let a: u8 = 42; - let b: u8 = 1; - let e: u8 = 43; - let r: u8 = transmute(vqaddb_u8(transmute(a), transmute(b))); + unsafe fn test_vmulx_laneq_f32() { + let a: f32x2 = f32x2::new(1., 2.); + let b: f32x4 = f32x4::new(2., 0., 0., 0.); + let e: f32x2 = f32x2::new(2., 4.); + let r: f32x2 = transmute(vmulx_laneq_f32::<0>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqaddh_u16() { - let a: u16 = 42; - let b: u16 = 1; - let e: u16 = 43; - let r: u16 = transmute(vqaddh_u16(transmute(a), transmute(b))); + unsafe fn test_vmulxq_lane_f32() { + let a: f32x4 = f32x4::new(1., 2., 3., 4.); + let b: f32x2 = f32x2::new(2., 0.); + let e: f32x4 = f32x4::new(2., 4., 6., 8.); + let r: f32x4 = transmute(vmulxq_lane_f32::<0>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqadds_u32() { - let a: u32 = 42; - let b: u32 = 1; - let e: u32 = 43; - let r: u32 = transmute(vqadds_u32(transmute(a), transmute(b))); + unsafe fn test_vmulxq_laneq_f32() { + let a: f32x4 = f32x4::new(1., 2., 3., 4.); + let b: f32x4 = f32x4::new(2., 0., 0., 0.); + let e: f32x4 = f32x4::new(2., 4., 6., 8.); + let r: f32x4 = transmute(vmulxq_laneq_f32::<0>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqaddd_u64() { - let a: u64 = 42; - let b: u64 = 1; - let e: u64 = 43; - let r: u64 = transmute(vqaddd_u64(transmute(a), transmute(b))); + unsafe fn test_vmulxq_lane_f64() { + let a: f64x2 = f64x2::new(1., 2.); + let b: f64 = 2.; + let e: f64x2 = f64x2::new(2., 4.); + let r: f64x2 = transmute(vmulxq_lane_f64::<0>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqadds_s32() { - let a: i32 = 42; - let b: i32 = 1; - let e: i32 = 43; - let r: i32 = transmute(vqadds_s32(transmute(a), transmute(b))); + unsafe fn test_vmulxq_laneq_f64() { + let a: f64x2 = f64x2::new(1., 2.); + let b: f64x2 = f64x2::new(2., 0.); + let e: f64x2 = f64x2::new(2., 4.); + let r: f64x2 = transmute(vmulxq_laneq_f64::<0>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqaddd_s64() { - let a: i64 = 42; - let b: i64 = 1; - let e: i64 = 43; - let r: i64 = transmute(vqaddd_s64(transmute(a), transmute(b))); + unsafe fn test_vmulxs_f32() { + let a: f32 = 2.; + let b: f32 = 3.; + let e: f32 = 6.; + let r: f32 = transmute(vmulxs_f32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_f64_x2() { - let a: [f64; 3] = [0., 1., 2.]; - let e: [f64; 2] = [1., 2.]; - let r: [f64; 2] = transmute(vld1_f64_x2(a[1..].as_ptr())); + unsafe fn test_vmulxd_f64() { + let a: f64 = 2.; + let b: f64 = 3.; + let e: f64 = 6.; + let r: f64 = transmute(vmulxd_f64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_f64_x2() { - let a: [f64; 5] = [0., 1., 2., 3., 4.]; - let e: [f64x2; 2] = [f64x2::new(1., 2.), f64x2::new(3., 4.)]; - let r: [f64x2; 2] = transmute(vld1q_f64_x2(a[1..].as_ptr())); + unsafe fn test_vmulxs_lane_f32() { + let a: f32 = 2.; + let b: f32x2 = f32x2::new(3., 0.); + let e: f32 = 6.; + let r: f32 = transmute(vmulxs_lane_f32::<0>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_f64_x3() { - let a: [f64; 4] = [0., 1., 2., 3.]; - let e: [f64; 3] = [1., 2., 3.]; - let r: [f64; 3] = transmute(vld1_f64_x3(a[1..].as_ptr())); + unsafe fn test_vmulxs_laneq_f32() { + let a: f32 = 2.; + let b: f32x4 = f32x4::new(3., 0., 0., 0.); + let e: f32 = 6.; + let r: f32 = transmute(vmulxs_laneq_f32::<0>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_f64_x3() { - let a: [f64; 7] = [0., 1., 2., 3., 4., 5., 6.]; - let e: [f64x2; 3] = [f64x2::new(1., 2.), f64x2::new(3., 4.), f64x2::new(5., 6.)]; - let r: [f64x2; 3] = transmute(vld1q_f64_x3(a[1..].as_ptr())); + unsafe fn test_vmulxd_lane_f64() { + let a: f64 = 2.; + let b: f64 = 3.; + let e: f64 = 6.; + let r: f64 = transmute(vmulxd_lane_f64::<0>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_f64_x4() { - let a: [f64; 5] = [0., 1., 2., 3., 4.]; - let e: [f64; 4] = [1., 2., 3., 4.]; - let r: [f64; 4] = transmute(vld1_f64_x4(a[1..].as_ptr())); + unsafe fn test_vmulxd_laneq_f64() { + let a: f64 = 2.; + let b: f64x2 = f64x2::new(3., 0.); + let e: f64 = 6.; + let r: f64 = transmute(vmulxd_laneq_f64::<0>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_f64_x4() { - let a: [f64; 9] = [0., 1., 2., 3., 4., 5., 6., 7., 8.]; - let e: [f64x2; 4] = [f64x2::new(1., 2.), f64x2::new(3., 4.), f64x2::new(5., 6.), f64x2::new(7., 8.)]; - let r: [f64x2; 4] = transmute(vld1q_f64_x4(a[1..].as_ptr())); + unsafe fn test_vfma_f64() { + let a: f64 = 8.0; + let b: f64 = 6.0; + let c: f64 = 2.0; + let e: f64 = 20.0; + let r: f64 = transmute(vfma_f64(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_f64_x2() { - let a: [f64; 3] = [0., 1., 2.]; - let e: [f64; 2] = [1., 2.]; - let mut r: [f64; 2] = [0f64; 2]; - vst1_f64_x2(r.as_mut_ptr(), vld1_f64_x2(a[1..].as_ptr())); + unsafe fn test_vfmaq_f64() { + let a: f64x2 = f64x2::new(8.0, 18.0); + let b: f64x2 = f64x2::new(6.0, 4.0); + let c: f64x2 = f64x2::new(2.0, 3.0); + let e: f64x2 = f64x2::new(20.0, 30.0); + let r: f64x2 = transmute(vfmaq_f64(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_f64_x2() { - let a: [f64; 5] = [0., 1., 2., 3., 4.]; - let e: [f64; 4] = [1., 2., 3., 4.]; - let mut r: [f64; 4] = [0f64; 4]; - vst1q_f64_x2(r.as_mut_ptr(), vld1q_f64_x2(a[1..].as_ptr())); + unsafe fn test_vfma_n_f64() { + let a: f64 = 2.0; + let b: f64 = 6.0; + let c: f64 = 8.0; + let e: f64 = 50.0; + let r: f64 = transmute(vfma_n_f64(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_f64_x3() { - let a: [f64; 4] = [0., 1., 2., 3.]; - let e: [f64; 3] = [1., 2., 3.]; - let mut r: [f64; 3] = [0f64; 3]; - vst1_f64_x3(r.as_mut_ptr(), vld1_f64_x3(a[1..].as_ptr())); + unsafe fn test_vfmaq_n_f64() { + let a: f64x2 = f64x2::new(2.0, 3.0); + let b: f64x2 = f64x2::new(6.0, 4.0); + let c: f64 = 8.0; + let e: f64x2 = f64x2::new(50.0, 35.0); + let r: f64x2 = transmute(vfmaq_n_f64(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_f64_x3() { - let a: [f64; 7] = [0., 1., 2., 3., 4., 5., 6.]; - let e: [f64; 6] = [1., 2., 3., 4., 5., 6.]; - let mut r: [f64; 6] = [0f64; 6]; - vst1q_f64_x3(r.as_mut_ptr(), vld1q_f64_x3(a[1..].as_ptr())); + unsafe fn test_vfma_lane_f32() { + let a: f32x2 = f32x2::new(2., 3.); + let b: f32x2 = f32x2::new(6., 4.); + let c: f32x2 = f32x2::new(2., 0.); + let e: f32x2 = f32x2::new(14., 11.); + let r: f32x2 = transmute(vfma_lane_f32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_f64_x4() { - let a: [f64; 5] = [0., 1., 2., 3., 4.]; - let e: [f64; 4] = [1., 2., 3., 4.]; - let mut r: [f64; 4] = [0f64; 4]; - vst1_f64_x4(r.as_mut_ptr(), vld1_f64_x4(a[1..].as_ptr())); + unsafe fn test_vfma_laneq_f32() { + let a: f32x2 = f32x2::new(2., 3.); + let b: f32x2 = f32x2::new(6., 4.); + let c: f32x4 = f32x4::new(2., 0., 0., 0.); + let e: f32x2 = f32x2::new(14., 11.); + let r: f32x2 = transmute(vfma_laneq_f32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_f64_x4() { - let a: [f64; 9] = [0., 1., 2., 3., 4., 5., 6., 7., 8.]; - let e: [f64; 8] = [1., 2., 3., 4., 5., 6., 7., 8.]; - let mut r: [f64; 8] = [0f64; 8]; - vst1q_f64_x4(r.as_mut_ptr(), vld1q_f64_x4(a[1..].as_ptr())); + unsafe fn test_vfmaq_lane_f32() { + let a: f32x4 = f32x4::new(2., 3., 4., 5.); + let b: f32x4 = f32x4::new(6., 4., 7., 8.); + let c: f32x2 = f32x2::new(2., 0.); + let e: f32x4 = f32x4::new(14., 11., 18., 21.); + let r: f32x4 = transmute(vfmaq_lane_f32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmul_f64() { - let a: f64 = 1.0; - let b: f64 = 2.0; - let e: f64 = 2.0; - let r: f64 = transmute(vmul_f64(transmute(a), transmute(b))); + unsafe fn test_vfmaq_laneq_f32() { + let a: f32x4 = f32x4::new(2., 3., 4., 5.); + let b: f32x4 = f32x4::new(6., 4., 7., 8.); + let c: f32x4 = f32x4::new(2., 0., 0., 0.); + let e: f32x4 = f32x4::new(14., 11., 18., 21.); + let r: f32x4 = transmute(vfmaq_laneq_f32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmulq_f64() { - let a: f64x2 = f64x2::new(1.0, 2.0); - let b: f64x2 = f64x2::new(2.0, 3.0); - let e: f64x2 = f64x2::new(2.0, 6.0); - let r: f64x2 = transmute(vmulq_f64(transmute(a), transmute(b))); + unsafe fn test_vfma_lane_f64() { + let a: f64 = 2.; + let b: f64 = 6.; + let c: f64 = 2.; + let e: f64 = 14.; + let r: f64 = transmute(vfma_lane_f64::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmul_n_f64() { - let a: f64 = 1.; - let b: f64 = 2.; - let e: f64 = 2.; - let r: f64 = transmute(vmul_n_f64(transmute(a), transmute(b))); + unsafe fn test_vfma_laneq_f64() { + let a: f64 = 2.; + let b: f64 = 6.; + let c: f64x2 = f64x2::new(2., 0.); + let e: f64 = 14.; + let r: f64 = transmute(vfma_laneq_f64::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmulq_n_f64() { - let a: f64x2 = f64x2::new(1., 2.); - let b: f64 = 2.; - let e: f64x2 = f64x2::new(2., 4.); - let r: f64x2 = transmute(vmulq_n_f64(transmute(a), transmute(b))); + unsafe fn test_vfmaq_lane_f64() { + let a: f64x2 = f64x2::new(2., 3.); + let b: f64x2 = f64x2::new(6., 4.); + let c: f64 = 2.; + let e: f64x2 = f64x2::new(14., 11.); + let r: f64x2 = transmute(vfmaq_lane_f64::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmul_lane_f64() { - let a: f64 = 1.; - let b: f64 = 2.; - let e: f64 = 2.; - let r: f64 = transmute(vmul_lane_f64::<0>(transmute(a), transmute(b))); + unsafe fn test_vfmaq_laneq_f64() { + let a: f64x2 = f64x2::new(2., 3.); + let b: f64x2 = f64x2::new(6., 4.); + let c: f64x2 = f64x2::new(2., 0.); + let e: f64x2 = f64x2::new(14., 11.); + let r: f64x2 = transmute(vfmaq_laneq_f64::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmul_laneq_f64() { - let a: f64 = 1.; - let b: f64x2 = f64x2::new(2., 0.); - let e: f64 = 2.; - let r: f64 = transmute(vmul_laneq_f64::<0>(transmute(a), transmute(b))); + unsafe fn test_vfmas_lane_f32() { + let a: f32 = 2.; + let b: f32 = 6.; + let c: f32x2 = f32x2::new(3., 0.); + let e: f32 = 20.; + let r: f32 = transmute(vfmas_lane_f32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmulq_lane_f64() { - let a: f64x2 = f64x2::new(1., 2.); - let b: f64 = 2.; - let e: f64x2 = f64x2::new(2., 4.); - let r: f64x2 = transmute(vmulq_lane_f64::<0>(transmute(a), transmute(b))); + unsafe fn test_vfmas_laneq_f32() { + let a: f32 = 2.; + let b: f32 = 6.; + let c: f32x4 = f32x4::new(3., 0., 0., 0.); + let e: f32 = 20.; + let r: f32 = transmute(vfmas_laneq_f32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmulq_laneq_f64() { - let a: f64x2 = f64x2::new(1., 2.); - let b: f64x2 = f64x2::new(2., 0.); - let e: f64x2 = f64x2::new(2., 4.); - let r: f64x2 = transmute(vmulq_laneq_f64::<0>(transmute(a), transmute(b))); + unsafe fn test_vfmad_lane_f64() { + let a: f64 = 2.; + let b: f64 = 6.; + let c: f64 = 3.; + let e: f64 = 20.; + let r: f64 = transmute(vfmad_lane_f64::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmuls_lane_f32() { - let a: f32 = 1.; - let b: f32x2 = f32x2::new(2., 0.); - let e: f32 = 2.; - let r: f32 = transmute(vmuls_lane_f32::<0>(transmute(a), transmute(b))); + unsafe fn test_vfmad_laneq_f64() { + let a: f64 = 2.; + let b: f64 = 6.; + let c: f64x2 = f64x2::new(3., 0.); + let e: f64 = 20.; + let r: f64 = transmute(vfmad_laneq_f64::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmuls_laneq_f32() { - let a: f32 = 1.; - let b: f32x4 = f32x4::new(2., 0., 0., 0.); - let e: f32 = 2.; - let r: f32 = transmute(vmuls_laneq_f32::<0>(transmute(a), transmute(b))); + unsafe fn test_vfms_f64() { + let a: f64 = 20.0; + let b: f64 = 6.0; + let c: f64 = 2.0; + let e: f64 = 8.0; + let r: f64 = transmute(vfms_f64(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmuld_lane_f64() { - let a: f64 = 1.; - let b: f64 = 2.; - let e: f64 = 2.; - let r: f64 = transmute(vmuld_lane_f64::<0>(transmute(a), transmute(b))); + unsafe fn test_vfmsq_f64() { + let a: f64x2 = f64x2::new(20.0, 30.0); + let b: f64x2 = f64x2::new(6.0, 4.0); + let c: f64x2 = f64x2::new(2.0, 3.0); + let e: f64x2 = f64x2::new(8.0, 18.0); + let r: f64x2 = transmute(vfmsq_f64(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmuld_laneq_f64() { - let a: f64 = 1.; - let b: f64x2 = f64x2::new(2., 0.); - let e: f64 = 2.; - let r: f64 = transmute(vmuld_laneq_f64::<0>(transmute(a), transmute(b))); + unsafe fn test_vfms_n_f64() { + let a: f64 = 50.0; + let b: f64 = 6.0; + let c: f64 = 8.0; + let e: f64 = 2.0; + let r: f64 = transmute(vfms_n_f64(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmull_high_s8() { - let a: i8x16 = i8x16::new(1, 2, 9, 10, 9, 10, 11, 12, 9, 10, 11, 12, 13, 14, 15, 16); - let b: i8x16 = i8x16::new(1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2); - let e: i16x8 = i16x8::new(9, 20, 11, 24, 13, 28, 15, 32); - let r: i16x8 = transmute(vmull_high_s8(transmute(a), transmute(b))); + unsafe fn test_vfmsq_n_f64() { + let a: f64x2 = f64x2::new(50.0, 35.0); + let b: f64x2 = f64x2::new(6.0, 4.0); + let c: f64 = 8.0; + let e: f64x2 = f64x2::new(2.0, 3.0); + let r: f64x2 = transmute(vfmsq_n_f64(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmull_high_s16() { - let a: i16x8 = i16x8::new(1, 2, 9, 10, 9, 10, 11, 12); - let b: i16x8 = i16x8::new(1, 2, 1, 2, 1, 2, 1, 2); - let e: i32x4 = i32x4::new(9, 20, 11, 24); - let r: i32x4 = transmute(vmull_high_s16(transmute(a), transmute(b))); + unsafe fn test_vfms_lane_f32() { + let a: f32x2 = f32x2::new(14., 11.); + let b: f32x2 = f32x2::new(6., 4.); + let c: f32x2 = f32x2::new(2., 0.); + let e: f32x2 = f32x2::new(2., 3.); + let r: f32x2 = transmute(vfms_lane_f32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmull_high_s32() { - let a: i32x4 = i32x4::new(1, 2, 9, 10); - let b: i32x4 = i32x4::new(1, 2, 1, 2); - let e: i64x2 = i64x2::new(9, 20); - let r: i64x2 = transmute(vmull_high_s32(transmute(a), transmute(b))); + unsafe fn test_vfms_laneq_f32() { + let a: f32x2 = f32x2::new(14., 11.); + let b: f32x2 = f32x2::new(6., 4.); + let c: f32x4 = f32x4::new(2., 0., 0., 0.); + let e: f32x2 = f32x2::new(2., 3.); + let r: f32x2 = transmute(vfms_laneq_f32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmull_high_u8() { - let a: u8x16 = u8x16::new(1, 2, 9, 10, 9, 10, 11, 12, 9, 10, 11, 12, 13, 14, 15, 16); - let b: u8x16 = u8x16::new(1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2); - let e: u16x8 = u16x8::new(9, 20, 11, 24, 13, 28, 15, 32); - let r: u16x8 = transmute(vmull_high_u8(transmute(a), transmute(b))); + unsafe fn test_vfmsq_lane_f32() { + let a: f32x4 = f32x4::new(14., 11., 18., 21.); + let b: f32x4 = f32x4::new(6., 4., 7., 8.); + let c: f32x2 = f32x2::new(2., 0.); + let e: f32x4 = f32x4::new(2., 3., 4., 5.); + let r: f32x4 = transmute(vfmsq_lane_f32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmull_high_u16() { - let a: u16x8 = u16x8::new(1, 2, 9, 10, 9, 10, 11, 12); - let b: u16x8 = u16x8::new(1, 2, 1, 2, 1, 2, 1, 2); - let e: u32x4 = u32x4::new(9, 20, 11, 24); - let r: u32x4 = transmute(vmull_high_u16(transmute(a), transmute(b))); + unsafe fn test_vfmsq_laneq_f32() { + let a: f32x4 = f32x4::new(14., 11., 18., 21.); + let b: f32x4 = f32x4::new(6., 4., 7., 8.); + let c: f32x4 = f32x4::new(2., 0., 0., 0.); + let e: f32x4 = f32x4::new(2., 3., 4., 5.); + let r: f32x4 = transmute(vfmsq_laneq_f32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmull_high_u32() { - let a: u32x4 = u32x4::new(1, 2, 9, 10); - let b: u32x4 = u32x4::new(1, 2, 1, 2); - let e: u64x2 = u64x2::new(9, 20); - let r: u64x2 = transmute(vmull_high_u32(transmute(a), transmute(b))); + unsafe fn test_vfms_lane_f64() { + let a: f64 = 14.; + let b: f64 = 6.; + let c: f64 = 2.; + let e: f64 = 2.; + let r: f64 = transmute(vfms_lane_f64::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmull_p64() { - let a: p64 = 15; - let b: p64 = 3; - let e: p128 = 17; - let r: p128 = transmute(vmull_p64(transmute(a), transmute(b))); + unsafe fn test_vfms_laneq_f64() { + let a: f64 = 14.; + let b: f64 = 6.; + let c: f64x2 = f64x2::new(2., 0.); + let e: f64 = 2.; + let r: f64 = transmute(vfms_laneq_f64::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmull_high_p8() { - let a: i8x16 = i8x16::new(1, 2, 9, 10, 9, 10, 11, 12, 9, 10, 11, 12, 13, 14, 15, 16); - let b: i8x16 = i8x16::new(1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3); - let e: i16x8 = i16x8::new(9, 30, 11, 20, 13, 18, 15, 48); - let r: i16x8 = transmute(vmull_high_p8(transmute(a), transmute(b))); + unsafe fn test_vfmsq_lane_f64() { + let a: f64x2 = f64x2::new(14., 11.); + let b: f64x2 = f64x2::new(6., 4.); + let c: f64 = 2.; + let e: f64x2 = f64x2::new(2., 3.); + let r: f64x2 = transmute(vfmsq_lane_f64::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmull_high_p64() { - let a: i64x2 = i64x2::new(1, 15); - let b: i64x2 = i64x2::new(1, 3); - let e: p128 = 17; - let r: p128 = transmute(vmull_high_p64(transmute(a), transmute(b))); + unsafe fn test_vfmsq_laneq_f64() { + let a: f64x2 = f64x2::new(14., 11.); + let b: f64x2 = f64x2::new(6., 4.); + let c: f64x2 = f64x2::new(2., 0.); + let e: f64x2 = f64x2::new(2., 3.); + let r: f64x2 = transmute(vfmsq_laneq_f64::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmull_high_n_s16() { - let a: i16x8 = i16x8::new(1, 2, 9, 10, 9, 10, 11, 12); - let b: i16 = 2; - let e: i32x4 = i32x4::new(18, 20, 22, 24); - let r: i32x4 = transmute(vmull_high_n_s16(transmute(a), transmute(b))); + unsafe fn test_vfmss_lane_f32() { + let a: f32 = 14.; + let b: f32 = 6.; + let c: f32x2 = f32x2::new(2., 0.); + let e: f32 = 2.; + let r: f32 = transmute(vfmss_lane_f32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmull_high_n_s32() { - let a: i32x4 = i32x4::new(1, 2, 9, 10); - let b: i32 = 2; - let e: i64x2 = i64x2::new(18, 20); - let r: i64x2 = transmute(vmull_high_n_s32(transmute(a), transmute(b))); + unsafe fn test_vfmss_laneq_f32() { + let a: f32 = 14.; + let b: f32 = 6.; + let c: f32x4 = f32x4::new(2., 0., 0., 0.); + let e: f32 = 2.; + let r: f32 = transmute(vfmss_laneq_f32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmull_high_n_u16() { - let a: u16x8 = u16x8::new(1, 2, 9, 10, 9, 10, 11, 12); - let b: u16 = 2; - let e: u32x4 = u32x4::new(18, 20, 22, 24); - let r: u32x4 = transmute(vmull_high_n_u16(transmute(a), transmute(b))); + unsafe fn test_vfmsd_lane_f64() { + let a: f64 = 14.; + let b: f64 = 6.; + let c: f64 = 2.; + let e: f64 = 2.; + let r: f64 = transmute(vfmsd_lane_f64::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmull_high_n_u32() { - let a: u32x4 = u32x4::new(1, 2, 9, 10); - let b: u32 = 2; - let e: u64x2 = u64x2::new(18, 20); - let r: u64x2 = transmute(vmull_high_n_u32(transmute(a), transmute(b))); + unsafe fn test_vfmsd_laneq_f64() { + let a: f64 = 14.; + let b: f64 = 6.; + let c: f64x2 = f64x2::new(2., 0.); + let e: f64 = 2.; + let r: f64 = transmute(vfmsd_laneq_f64::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmull_high_lane_s16() { - let a: i16x8 = i16x8::new(1, 2, 9, 10, 9, 10, 11, 12); - let b: i16x4 = i16x4::new(0, 2, 0, 0); - let e: i32x4 = i32x4::new(18, 20, 22, 24); - let r: i32x4 = transmute(vmull_high_lane_s16::<1>(transmute(a), transmute(b))); + unsafe fn test_vdiv_f32() { + let a: f32x2 = f32x2::new(2.0, 6.0); + let b: f32x2 = f32x2::new(1.0, 2.0); + let e: f32x2 = f32x2::new(2.0, 3.0); + let r: f32x2 = transmute(vdiv_f32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmull_high_laneq_s16() { - let a: i16x8 = i16x8::new(1, 2, 9, 10, 9, 10, 11, 12); - let b: i16x8 = i16x8::new(0, 2, 0, 0, 0, 0, 0, 0); - let e: i32x4 = i32x4::new(18, 20, 22, 24); - let r: i32x4 = transmute(vmull_high_laneq_s16::<1>(transmute(a), transmute(b))); + unsafe fn test_vdivq_f32() { + let a: f32x4 = f32x4::new(2.0, 6.0, 4.0, 10.0); + let b: f32x4 = f32x4::new(1.0, 2.0, 1.0, 2.0); + let e: f32x4 = f32x4::new(2.0, 3.0, 4.0, 5.0); + let r: f32x4 = transmute(vdivq_f32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmull_high_lane_s32() { - let a: i32x4 = i32x4::new(1, 2, 9, 10); - let b: i32x2 = i32x2::new(0, 2); - let e: i64x2 = i64x2::new(18, 20); - let r: i64x2 = transmute(vmull_high_lane_s32::<1>(transmute(a), transmute(b))); + unsafe fn test_vdiv_f64() { + let a: f64 = 2.0; + let b: f64 = 1.0; + let e: f64 = 2.0; + let r: f64 = transmute(vdiv_f64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmull_high_laneq_s32() { - let a: i32x4 = i32x4::new(1, 2, 9, 10); - let b: i32x4 = i32x4::new(0, 2, 0, 0); - let e: i64x2 = i64x2::new(18, 20); - let r: i64x2 = transmute(vmull_high_laneq_s32::<1>(transmute(a), transmute(b))); + unsafe fn test_vdivq_f64() { + let a: f64x2 = f64x2::new(2.0, 6.0); + let b: f64x2 = f64x2::new(1.0, 2.0); + let e: f64x2 = f64x2::new(2.0, 3.0); + let r: f64x2 = transmute(vdivq_f64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vsub_f64() { + let a: f64 = 1.0; + let b: f64 = 1.0; + let e: f64 = 0.0; + let r: f64 = transmute(vsub_f64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmull_high_lane_u16() { - let a: u16x8 = u16x8::new(1, 2, 9, 10, 9, 10, 11, 12); - let b: u16x4 = u16x4::new(0, 2, 0, 0); - let e: u32x4 = u32x4::new(18, 20, 22, 24); - let r: u32x4 = transmute(vmull_high_lane_u16::<1>(transmute(a), transmute(b))); + unsafe fn test_vsubq_f64() { + let a: f64x2 = f64x2::new(1.0, 4.0); + let b: f64x2 = f64x2::new(1.0, 2.0); + let e: f64x2 = f64x2::new(0.0, 2.0); + let r: f64x2 = transmute(vsubq_f64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmull_high_laneq_u16() { - let a: u16x8 = u16x8::new(1, 2, 9, 10, 9, 10, 11, 12); - let b: u16x8 = u16x8::new(0, 2, 0, 0, 0, 0, 0, 0); - let e: u32x4 = u32x4::new(18, 20, 22, 24); - let r: u32x4 = transmute(vmull_high_laneq_u16::<1>(transmute(a), transmute(b))); + unsafe fn test_vsubd_s64() { + let a: i64 = 3; + let b: i64 = 2; + let e: i64 = 1; + let r: i64 = transmute(vsubd_s64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmull_high_lane_u32() { - let a: u32x4 = u32x4::new(1, 2, 9, 10); - let b: u32x2 = u32x2::new(0, 2); - let e: u64x2 = u64x2::new(18, 20); - let r: u64x2 = transmute(vmull_high_lane_u32::<1>(transmute(a), transmute(b))); + unsafe fn test_vsubd_u64() { + let a: u64 = 3; + let b: u64 = 2; + let e: u64 = 1; + let r: u64 = transmute(vsubd_u64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmull_high_laneq_u32() { - let a: u32x4 = u32x4::new(1, 2, 9, 10); - let b: u32x4 = u32x4::new(0, 2, 0, 0); - let e: u64x2 = u64x2::new(18, 20); - let r: u64x2 = transmute(vmull_high_laneq_u32::<1>(transmute(a), transmute(b))); + unsafe fn test_vaddd_s64() { + let a: i64 = 1; + let b: i64 = 2; + let e: i64 = 3; + let r: i64 = transmute(vaddd_s64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmulx_f32() { - let a: f32x2 = f32x2::new(1., 2.); - let b: f32x2 = f32x2::new(2., 2.); - let e: f32x2 = f32x2::new(2., 4.); - let r: f32x2 = transmute(vmulx_f32(transmute(a), transmute(b))); + unsafe fn test_vaddd_u64() { + let a: u64 = 1; + let b: u64 = 2; + let e: u64 = 3; + let r: u64 = transmute(vaddd_u64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmulxq_f32() { - let a: f32x4 = f32x4::new(1., 2., 3., 4.); - let b: f32x4 = f32x4::new(2., 2., 2., 2.); - let e: f32x4 = f32x4::new(2., 4., 6., 8.); - let r: f32x4 = transmute(vmulxq_f32(transmute(a), transmute(b))); + unsafe fn test_vaddv_f32() { + let a: f32x2 = f32x2::new(1., 2.); + let e: f32 = 3.; + let r: f32 = transmute(vaddv_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmulx_f64() { - let a: f64 = 1.; - let b: f64 = 2.; - let e: f64 = 2.; - let r: f64 = transmute(vmulx_f64(transmute(a), transmute(b))); + unsafe fn test_vaddvq_f32() { + let a: f32x4 = f32x4::new(1., 2., 0., 0.); + let e: f32 = 3.; + let r: f32 = transmute(vaddvq_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmulxq_f64() { + unsafe fn test_vaddvq_f64() { let a: f64x2 = f64x2::new(1., 2.); - let b: f64x2 = f64x2::new(2., 2.); - let e: f64x2 = f64x2::new(2., 4.); - let r: f64x2 = transmute(vmulxq_f64(transmute(a), transmute(b))); + let e: f64 = 3.; + let r: f64 = transmute(vaddvq_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmulx_lane_f64() { - let a: f64 = 1.; - let b: f64 = 2.; - let e: f64 = 2.; - let r: f64 = transmute(vmulx_lane_f64::<0>(transmute(a), transmute(b))); + unsafe fn test_vaddlv_s16() { + let a: i16x4 = i16x4::new(1, 2, 3, 4); + let e: i32 = 10; + let r: i32 = transmute(vaddlv_s16(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmulx_laneq_f64() { - let a: f64 = 1.; - let b: f64x2 = f64x2::new(2., 0.); - let e: f64 = 2.; - let r: f64 = transmute(vmulx_laneq_f64::<0>(transmute(a), transmute(b))); + unsafe fn test_vaddlvq_s16() { + let a: i16x8 = i16x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let e: i32 = 36; + let r: i32 = transmute(vaddlvq_s16(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmulx_lane_f32() { - let a: f32x2 = f32x2::new(1., 2.); - let b: f32x2 = f32x2::new(2., 0.); - let e: f32x2 = f32x2::new(2., 4.); - let r: f32x2 = transmute(vmulx_lane_f32::<0>(transmute(a), transmute(b))); + unsafe fn test_vaddlv_s32() { + let a: i32x2 = i32x2::new(1, 2); + let e: i64 = 3; + let r: i64 = transmute(vaddlv_s32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmulx_laneq_f32() { - let a: f32x2 = f32x2::new(1., 2.); - let b: f32x4 = f32x4::new(2., 0., 0., 0.); - let e: f32x2 = f32x2::new(2., 4.); - let r: f32x2 = transmute(vmulx_laneq_f32::<0>(transmute(a), transmute(b))); + unsafe fn test_vaddlvq_s32() { + let a: i32x4 = i32x4::new(1, 2, 3, 4); + let e: i64 = 10; + let r: i64 = transmute(vaddlvq_s32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmulxq_lane_f32() { - let a: f32x4 = f32x4::new(1., 2., 3., 4.); - let b: f32x2 = f32x2::new(2., 0.); - let e: f32x4 = f32x4::new(2., 4., 6., 8.); - let r: f32x4 = transmute(vmulxq_lane_f32::<0>(transmute(a), transmute(b))); + unsafe fn test_vaddlv_u16() { + let a: u16x4 = u16x4::new(1, 2, 3, 4); + let e: u32 = 10; + let r: u32 = transmute(vaddlv_u16(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmulxq_laneq_f32() { - let a: f32x4 = f32x4::new(1., 2., 3., 4.); - let b: f32x4 = f32x4::new(2., 0., 0., 0.); - let e: f32x4 = f32x4::new(2., 4., 6., 8.); - let r: f32x4 = transmute(vmulxq_laneq_f32::<0>(transmute(a), transmute(b))); + unsafe fn test_vaddlvq_u16() { + let a: u16x8 = u16x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let e: u32 = 36; + let r: u32 = transmute(vaddlvq_u16(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmulxq_lane_f64() { - let a: f64x2 = f64x2::new(1., 2.); - let b: f64 = 2.; - let e: f64x2 = f64x2::new(2., 4.); - let r: f64x2 = transmute(vmulxq_lane_f64::<0>(transmute(a), transmute(b))); + unsafe fn test_vaddlv_u32() { + let a: u32x2 = u32x2::new(1, 2); + let e: u64 = 3; + let r: u64 = transmute(vaddlv_u32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmulxq_laneq_f64() { - let a: f64x2 = f64x2::new(1., 2.); - let b: f64x2 = f64x2::new(2., 0.); - let e: f64x2 = f64x2::new(2., 4.); - let r: f64x2 = transmute(vmulxq_laneq_f64::<0>(transmute(a), transmute(b))); + unsafe fn test_vaddlvq_u32() { + let a: u32x4 = u32x4::new(1, 2, 3, 4); + let e: u64 = 10; + let r: u64 = transmute(vaddlvq_u32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmulxs_f32() { - let a: f32 = 2.; - let b: f32 = 3.; - let e: f32 = 6.; - let r: f32 = transmute(vmulxs_f32(transmute(a), transmute(b))); + unsafe fn test_vsubw_high_s8() { + let a: i16x8 = i16x8::new(8, 9, 10, 12, 13, 14, 15, 16); + let b: i8x16 = i8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15, 16); + let e: i16x8 = i16x8::new(0, 0, 0, 0, 0, 0, 0, 0); + let r: i16x8 = transmute(vsubw_high_s8(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmulxd_f64() { - let a: f64 = 2.; - let b: f64 = 3.; - let e: f64 = 6.; - let r: f64 = transmute(vmulxd_f64(transmute(a), transmute(b))); + unsafe fn test_vsubw_high_s16() { + let a: i32x4 = i32x4::new(8, 9, 10, 11); + let b: i16x8 = i16x8::new(0, 1, 2, 3, 8, 9, 10, 11); + let e: i32x4 = i32x4::new(0, 0, 0, 0); + let r: i32x4 = transmute(vsubw_high_s16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmulxs_lane_f32() { - let a: f32 = 2.; - let b: f32x2 = f32x2::new(3., 0.); - let e: f32 = 6.; - let r: f32 = transmute(vmulxs_lane_f32::<0>(transmute(a), transmute(b))); + unsafe fn test_vsubw_high_s32() { + let a: i64x2 = i64x2::new(8, 9); + let b: i32x4 = i32x4::new(6, 7, 8, 9); + let e: i64x2 = i64x2::new(0, 0); + let r: i64x2 = transmute(vsubw_high_s32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmulxs_laneq_f32() { - let a: f32 = 2.; - let b: f32x4 = f32x4::new(3., 0., 0., 0.); - let e: f32 = 6.; - let r: f32 = transmute(vmulxs_laneq_f32::<0>(transmute(a), transmute(b))); + unsafe fn test_vsubw_high_u8() { + let a: u16x8 = u16x8::new(8, 9, 10, 11, 12, 13, 14, 15); + let b: u8x16 = u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let e: u16x8 = u16x8::new(0, 0, 0, 0, 0, 0, 0, 0); + let r: u16x8 = transmute(vsubw_high_u8(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmulxd_lane_f64() { - let a: f64 = 2.; - let b: f64 = 3.; - let e: f64 = 6.; - let r: f64 = transmute(vmulxd_lane_f64::<0>(transmute(a), transmute(b))); + unsafe fn test_vsubw_high_u16() { + let a: u32x4 = u32x4::new(8, 9, 10, 11); + let b: u16x8 = u16x8::new(0, 1, 2, 3, 8, 9, 10, 11); + let e: u32x4 = u32x4::new(0, 0, 0, 0); + let r: u32x4 = transmute(vsubw_high_u16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmulxd_laneq_f64() { - let a: f64 = 2.; - let b: f64x2 = f64x2::new(3., 0.); - let e: f64 = 6.; - let r: f64 = transmute(vmulxd_laneq_f64::<0>(transmute(a), transmute(b))); + unsafe fn test_vsubw_high_u32() { + let a: u64x2 = u64x2::new(8, 9); + let b: u32x4 = u32x4::new(6, 7, 8, 9); + let e: u64x2 = u64x2::new(0, 0); + let r: u64x2 = transmute(vsubw_high_u32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vfma_f64() { - let a: f64 = 8.0; - let b: f64 = 6.0; - let c: f64 = 2.0; - let e: f64 = 20.0; - let r: f64 = transmute(vfma_f64(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vsubl_high_s8() { + let a: i8x16 = i8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let b: i8x16 = i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2); + let e: i16x8 = i16x8::new(6, 7, 8, 9, 10, 11, 12, 13); + let r: i16x8 = transmute(vsubl_high_s8(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vfmaq_f64() { - let a: f64x2 = f64x2::new(8.0, 18.0); - let b: f64x2 = f64x2::new(6.0, 4.0); - let c: f64x2 = f64x2::new(2.0, 3.0); - let e: f64x2 = f64x2::new(20.0, 30.0); - let r: f64x2 = transmute(vfmaq_f64(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vsubl_high_s16() { + let a: i16x8 = i16x8::new(8, 9, 10, 11, 12, 13, 14, 15); + let b: i16x8 = i16x8::new(6, 6, 6, 6, 8, 8, 8, 8); + let e: i32x4 = i32x4::new(4, 5, 6, 7); + let r: i32x4 = transmute(vsubl_high_s16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vfma_n_f64() { - let a: f64 = 2.0; - let b: f64 = 6.0; - let c: f64 = 8.0; - let e: f64 = 50.0; - let r: f64 = transmute(vfma_n_f64(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vsubl_high_s32() { + let a: i32x4 = i32x4::new(12, 13, 14, 15); + let b: i32x4 = i32x4::new(6, 6, 8, 8); + let e: i64x2 = i64x2::new(6, 7); + let r: i64x2 = transmute(vsubl_high_s32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vfmaq_n_f64() { - let a: f64x2 = f64x2::new(2.0, 3.0); - let b: f64x2 = f64x2::new(6.0, 4.0); - let c: f64 = 8.0; - let e: f64x2 = f64x2::new(50.0, 35.0); - let r: f64x2 = transmute(vfmaq_n_f64(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vsubl_high_u8() { + let a: u8x16 = u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let b: u8x16 = u8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2); + let e: u16x8 = u16x8::new(6, 7, 8, 9, 10, 11, 12, 13); + let r: u16x8 = transmute(vsubl_high_u8(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vfma_lane_f32() { - let a: f32x2 = f32x2::new(2., 3.); - let b: f32x2 = f32x2::new(6., 4.); - let c: f32x2 = f32x2::new(2., 0.); - let e: f32x2 = f32x2::new(14., 11.); - let r: f32x2 = transmute(vfma_lane_f32::<0>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vsubl_high_u16() { + let a: u16x8 = u16x8::new(8, 9, 10, 11, 12, 13, 14, 15); + let b: u16x8 = u16x8::new(6, 6, 6, 6, 8, 8, 8, 8); + let e: u32x4 = u32x4::new(4, 5, 6, 7); + let r: u32x4 = transmute(vsubl_high_u16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vfma_laneq_f32() { - let a: f32x2 = f32x2::new(2., 3.); - let b: f32x2 = f32x2::new(6., 4.); - let c: f32x4 = f32x4::new(2., 0., 0., 0.); - let e: f32x2 = f32x2::new(14., 11.); - let r: f32x2 = transmute(vfma_laneq_f32::<0>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vsubl_high_u32() { + let a: u32x4 = u32x4::new(12, 13, 14, 15); + let b: u32x4 = u32x4::new(6, 6, 8, 8); + let e: u64x2 = u64x2::new(6, 7); + let r: u64x2 = transmute(vsubl_high_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon,sha3")] + unsafe fn test_vbcaxq_s8() { + let a: i8x16 = i8x16::new(1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0); + let b: i8x16 = i8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let c: i8x16 = i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); + let e: i8x16 = i8x16::new(1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14); + let r: i8x16 = transmute(vbcaxq_s8(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } - #[simd_test(enable = "neon")] - unsafe fn test_vfmaq_lane_f32() { - let a: f32x4 = f32x4::new(2., 3., 4., 5.); - let b: f32x4 = f32x4::new(6., 4., 7., 8.); - let c: f32x2 = f32x2::new(2., 0.); - let e: f32x4 = f32x4::new(14., 11., 18., 21.); - let r: f32x4 = transmute(vfmaq_lane_f32::<0>(transmute(a), transmute(b), transmute(c))); + #[simd_test(enable = "neon,sha3")] + unsafe fn test_vbcaxq_s16() { + let a: i16x8 = i16x8::new(1, 0, 1, 0, 1, 0, 1, 0); + let b: i16x8 = i16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let c: i16x8 = i16x8::new(1, 1, 1, 1, 1, 1, 1, 1); + let e: i16x8 = i16x8::new(1, 0, 3, 2, 5, 4, 7, 6); + let r: i16x8 = transmute(vbcaxq_s16(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } - #[simd_test(enable = "neon")] - unsafe fn test_vfmaq_laneq_f32() { - let a: f32x4 = f32x4::new(2., 3., 4., 5.); - let b: f32x4 = f32x4::new(6., 4., 7., 8.); - let c: f32x4 = f32x4::new(2., 0., 0., 0.); - let e: f32x4 = f32x4::new(14., 11., 18., 21.); - let r: f32x4 = transmute(vfmaq_laneq_f32::<0>(transmute(a), transmute(b), transmute(c))); + #[simd_test(enable = "neon,sha3")] + unsafe fn test_vbcaxq_s32() { + let a: i32x4 = i32x4::new(1, 0, 1, 0); + let b: i32x4 = i32x4::new(0, 1, 2, 3); + let c: i32x4 = i32x4::new(1, 1, 1, 1); + let e: i32x4 = i32x4::new(1, 0, 3, 2); + let r: i32x4 = transmute(vbcaxq_s32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } - #[simd_test(enable = "neon")] - unsafe fn test_vfma_lane_f64() { - let a: f64 = 2.; - let b: f64 = 6.; - let c: f64 = 2.; - let e: f64 = 14.; - let r: f64 = transmute(vfma_lane_f64::<0>(transmute(a), transmute(b), transmute(c))); + #[simd_test(enable = "neon,sha3")] + unsafe fn test_vbcaxq_s64() { + let a: i64x2 = i64x2::new(1, 0); + let b: i64x2 = i64x2::new(0, 1); + let c: i64x2 = i64x2::new(1, 1); + let e: i64x2 = i64x2::new(1, 0); + let r: i64x2 = transmute(vbcaxq_s64(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } - #[simd_test(enable = "neon")] - unsafe fn test_vfma_laneq_f64() { - let a: f64 = 2.; - let b: f64 = 6.; - let c: f64x2 = f64x2::new(2., 0.); - let e: f64 = 14.; - let r: f64 = transmute(vfma_laneq_f64::<0>(transmute(a), transmute(b), transmute(c))); + #[simd_test(enable = "neon,sha3")] + unsafe fn test_vbcaxq_u8() { + let a: u8x16 = u8x16::new(1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0); + let b: u8x16 = u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let c: u8x16 = u8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); + let e: u8x16 = u8x16::new(1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14); + let r: u8x16 = transmute(vbcaxq_u8(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } - #[simd_test(enable = "neon")] - unsafe fn test_vfmaq_lane_f64() { - let a: f64x2 = f64x2::new(2., 3.); - let b: f64x2 = f64x2::new(6., 4.); - let c: f64 = 2.; - let e: f64x2 = f64x2::new(14., 11.); - let r: f64x2 = transmute(vfmaq_lane_f64::<0>(transmute(a), transmute(b), transmute(c))); + #[simd_test(enable = "neon,sha3")] + unsafe fn test_vbcaxq_u16() { + let a: u16x8 = u16x8::new(1, 0, 1, 0, 1, 0, 1, 0); + let b: u16x8 = u16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let c: u16x8 = u16x8::new(1, 1, 1, 1, 1, 1, 1, 1); + let e: u16x8 = u16x8::new(1, 0, 3, 2, 5, 4, 7, 6); + let r: u16x8 = transmute(vbcaxq_u16(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } - #[simd_test(enable = "neon")] - unsafe fn test_vfmaq_laneq_f64() { - let a: f64x2 = f64x2::new(2., 3.); - let b: f64x2 = f64x2::new(6., 4.); - let c: f64x2 = f64x2::new(2., 0.); - let e: f64x2 = f64x2::new(14., 11.); - let r: f64x2 = transmute(vfmaq_laneq_f64::<0>(transmute(a), transmute(b), transmute(c))); + #[simd_test(enable = "neon,sha3")] + unsafe fn test_vbcaxq_u32() { + let a: u32x4 = u32x4::new(1, 0, 1, 0); + let b: u32x4 = u32x4::new(0, 1, 2, 3); + let c: u32x4 = u32x4::new(1, 1, 1, 1); + let e: u32x4 = u32x4::new(1, 0, 3, 2); + let r: u32x4 = transmute(vbcaxq_u32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } - #[simd_test(enable = "neon")] - unsafe fn test_vfmas_lane_f32() { - let a: f32 = 2.; - let b: f32 = 6.; - let c: f32x2 = f32x2::new(3., 0.); - let e: f32 = 20.; - let r: f32 = transmute(vfmas_lane_f32::<0>(transmute(a), transmute(b), transmute(c))); + #[simd_test(enable = "neon,sha3")] + unsafe fn test_vbcaxq_u64() { + let a: u64x2 = u64x2::new(1, 0); + let b: u64x2 = u64x2::new(0, 1); + let c: u64x2 = u64x2::new(1, 1); + let e: u64x2 = u64x2::new(1, 0); + let r: u64x2 = transmute(vbcaxq_u64(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vfmas_laneq_f32() { - let a: f32 = 2.; - let b: f32 = 6.; - let c: f32x4 = f32x4::new(3., 0., 0., 0.); - let e: f32 = 20.; - let r: f32 = transmute(vfmas_laneq_f32::<0>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vcadd_rot270_f32() { + let a: f32x2 = f32x2::new(1., -1.); + let b: f32x2 = f32x2::new(-1., 1.); + let e: f32x2 = f32x2::new(2., 0.); + let r: f32x2 = transmute(vcadd_rot270_f32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vfmad_lane_f64() { - let a: f64 = 2.; - let b: f64 = 6.; - let c: f64 = 3.; - let e: f64 = 20.; - let r: f64 = transmute(vfmad_lane_f64::<0>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vcaddq_rot270_f32() { + let a: f32x4 = f32x4::new(1., -1., 1., -1.); + let b: f32x4 = f32x4::new(-1., 1., -1., 1.); + let e: f32x4 = f32x4::new(2., 0., 2., 0.); + let r: f32x4 = transmute(vcaddq_rot270_f32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vfmad_laneq_f64() { - let a: f64 = 2.; - let b: f64 = 6.; - let c: f64x2 = f64x2::new(3., 0.); - let e: f64 = 20.; - let r: f64 = transmute(vfmad_laneq_f64::<0>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vcaddq_rot270_f64() { + let a: f64x2 = f64x2::new(1., -1.); + let b: f64x2 = f64x2::new(-1., 1.); + let e: f64x2 = f64x2::new(2., 0.); + let r: f64x2 = transmute(vcaddq_rot270_f64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vfms_f64() { - let a: f64 = 20.0; - let b: f64 = 6.0; - let c: f64 = 2.0; - let e: f64 = 8.0; - let r: f64 = transmute(vfms_f64(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vcadd_rot90_f32() { + let a: f32x2 = f32x2::new(1., -1.); + let b: f32x2 = f32x2::new(-1., 1.); + let e: f32x2 = f32x2::new(0., -2.); + let r: f32x2 = transmute(vcadd_rot90_f32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vfmsq_f64() { - let a: f64x2 = f64x2::new(20.0, 30.0); - let b: f64x2 = f64x2::new(6.0, 4.0); - let c: f64x2 = f64x2::new(2.0, 3.0); - let e: f64x2 = f64x2::new(8.0, 18.0); - let r: f64x2 = transmute(vfmsq_f64(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vcaddq_rot90_f32() { + let a: f32x4 = f32x4::new(1., -1., 1., -1.); + let b: f32x4 = f32x4::new(-1., 1., -1., 1.); + let e: f32x4 = f32x4::new(0., -2., 0., -2.); + let r: f32x4 = transmute(vcaddq_rot90_f32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vfms_n_f64() { - let a: f64 = 50.0; - let b: f64 = 6.0; - let c: f64 = 8.0; - let e: f64 = 2.0; - let r: f64 = transmute(vfms_n_f64(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vcaddq_rot90_f64() { + let a: f64x2 = f64x2::new(1., -1.); + let b: f64x2 = f64x2::new(-1., 1.); + let e: f64x2 = f64x2::new(0., -2.); + let r: f64x2 = transmute(vcaddq_rot90_f64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vfmsq_n_f64() { - let a: f64x2 = f64x2::new(50.0, 35.0); - let b: f64x2 = f64x2::new(6.0, 4.0); - let c: f64 = 8.0; - let e: f64x2 = f64x2::new(2.0, 3.0); - let r: f64x2 = transmute(vfmsq_n_f64(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vcmla_f32() { + let a: f32x2 = f32x2::new(1., -1.); + let b: f32x2 = f32x2::new(-1., 1.); + let c: f32x2 = f32x2::new(1., 1.); + let e: f32x2 = f32x2::new(0., -2.); + let r: f32x2 = transmute(vcmla_f32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vfms_lane_f32() { - let a: f32x2 = f32x2::new(14., 11.); - let b: f32x2 = f32x2::new(6., 4.); - let c: f32x2 = f32x2::new(2., 0.); - let e: f32x2 = f32x2::new(2., 3.); - let r: f32x2 = transmute(vfms_lane_f32::<0>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vcmlaq_f32() { + let a: f32x4 = f32x4::new(1., -1., 1., -1.); + let b: f32x4 = f32x4::new(-1., 1., -1., 1.); + let c: f32x4 = f32x4::new(1., 1., -1., -1.); + let e: f32x4 = f32x4::new(0., -2., 2., 0.); + let r: f32x4 = transmute(vcmlaq_f32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vfms_laneq_f32() { - let a: f32x2 = f32x2::new(14., 11.); - let b: f32x2 = f32x2::new(6., 4.); - let c: f32x4 = f32x4::new(2., 0., 0., 0.); - let e: f32x2 = f32x2::new(2., 3.); - let r: f32x2 = transmute(vfms_laneq_f32::<0>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vcmlaq_f64() { + let a: f64x2 = f64x2::new(1., -1.); + let b: f64x2 = f64x2::new(-1., 1.); + let c: f64x2 = f64x2::new(1., 1.); + let e: f64x2 = f64x2::new(0., -2.); + let r: f64x2 = transmute(vcmlaq_f64(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vfmsq_lane_f32() { - let a: f32x4 = f32x4::new(14., 11., 18., 21.); - let b: f32x4 = f32x4::new(6., 4., 7., 8.); - let c: f32x2 = f32x2::new(2., 0.); - let e: f32x4 = f32x4::new(2., 3., 4., 5.); - let r: f32x4 = transmute(vfmsq_lane_f32::<0>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vcmla_rot90_f32() { + let a: f32x2 = f32x2::new(1., 1.); + let b: f32x2 = f32x2::new(1., -1.); + let c: f32x2 = f32x2::new(1., 1.); + let e: f32x2 = f32x2::new(2., 0.); + let r: f32x2 = transmute(vcmla_rot90_f32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vfmsq_laneq_f32() { - let a: f32x4 = f32x4::new(14., 11., 18., 21.); - let b: f32x4 = f32x4::new(6., 4., 7., 8.); - let c: f32x4 = f32x4::new(2., 0., 0., 0.); - let e: f32x4 = f32x4::new(2., 3., 4., 5.); - let r: f32x4 = transmute(vfmsq_laneq_f32::<0>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vcmlaq_rot90_f32() { + let a: f32x4 = f32x4::new(1., 1., 1., 1.); + let b: f32x4 = f32x4::new(1., -1., 1., -1.); + let c: f32x4 = f32x4::new(1., 1., 1., 1.); + let e: f32x4 = f32x4::new(2., 0., 2., 0.); + let r: f32x4 = transmute(vcmlaq_rot90_f32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vfms_lane_f64() { - let a: f64 = 14.; - let b: f64 = 6.; - let c: f64 = 2.; - let e: f64 = 2.; - let r: f64 = transmute(vfms_lane_f64::<0>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vcmlaq_rot90_f64() { + let a: f64x2 = f64x2::new(1., 1.); + let b: f64x2 = f64x2::new(1., -1.); + let c: f64x2 = f64x2::new(1., 1.); + let e: f64x2 = f64x2::new(2., 0.); + let r: f64x2 = transmute(vcmlaq_rot90_f64(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vfms_laneq_f64() { - let a: f64 = 14.; - let b: f64 = 6.; - let c: f64x2 = f64x2::new(2., 0.); - let e: f64 = 2.; - let r: f64 = transmute(vfms_laneq_f64::<0>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vcmla_rot180_f32() { + let a: f32x2 = f32x2::new(1., 1.); + let b: f32x2 = f32x2::new(1., -1.); + let c: f32x2 = f32x2::new(1., 1.); + let e: f32x2 = f32x2::new(0., 0.); + let r: f32x2 = transmute(vcmla_rot180_f32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vfmsq_lane_f64() { - let a: f64x2 = f64x2::new(14., 11.); - let b: f64x2 = f64x2::new(6., 4.); - let c: f64 = 2.; - let e: f64x2 = f64x2::new(2., 3.); - let r: f64x2 = transmute(vfmsq_lane_f64::<0>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vcmlaq_rot180_f32() { + let a: f32x4 = f32x4::new(1., 1., 1., 1.); + let b: f32x4 = f32x4::new(1., -1., 1., -1.); + let c: f32x4 = f32x4::new(1., 1., 1., 1.); + let e: f32x4 = f32x4::new(0., 0., 0., 0.); + let r: f32x4 = transmute(vcmlaq_rot180_f32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vfmsq_laneq_f64() { - let a: f64x2 = f64x2::new(14., 11.); - let b: f64x2 = f64x2::new(6., 4.); - let c: f64x2 = f64x2::new(2., 0.); - let e: f64x2 = f64x2::new(2., 3.); - let r: f64x2 = transmute(vfmsq_laneq_f64::<0>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vcmlaq_rot180_f64() { + let a: f64x2 = f64x2::new(1., 1.); + let b: f64x2 = f64x2::new(1., -1.); + let c: f64x2 = f64x2::new(1., 1.); + let e: f64x2 = f64x2::new(0., 0.); + let r: f64x2 = transmute(vcmlaq_rot180_f64(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vfmss_lane_f32() { - let a: f32 = 14.; - let b: f32 = 6.; - let c: f32x2 = f32x2::new(2., 0.); - let e: f32 = 2.; - let r: f32 = transmute(vfmss_lane_f32::<0>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vcmla_rot270_f32() { + let a: f32x2 = f32x2::new(1., 1.); + let b: f32x2 = f32x2::new(1., -1.); + let c: f32x2 = f32x2::new(1., 1.); + let e: f32x2 = f32x2::new(0., 2.); + let r: f32x2 = transmute(vcmla_rot270_f32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vfmss_laneq_f32() { - let a: f32 = 14.; - let b: f32 = 6.; - let c: f32x4 = f32x4::new(2., 0., 0., 0.); - let e: f32 = 2.; - let r: f32 = transmute(vfmss_laneq_f32::<0>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vcmlaq_rot270_f32() { + let a: f32x4 = f32x4::new(1., 1., 1., 1.); + let b: f32x4 = f32x4::new(1., -1., 1., -1.); + let c: f32x4 = f32x4::new(1., 1., 1., 1.); + let e: f32x4 = f32x4::new(0., 2., 0., 2.); + let r: f32x4 = transmute(vcmlaq_rot270_f32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vfmsd_lane_f64() { - let a: f64 = 14.; - let b: f64 = 6.; - let c: f64 = 2.; - let e: f64 = 2.; - let r: f64 = transmute(vfmsd_lane_f64::<0>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vcmlaq_rot270_f64() { + let a: f64x2 = f64x2::new(1., 1.); + let b: f64x2 = f64x2::new(1., -1.); + let c: f64x2 = f64x2::new(1., 1.); + let e: f64x2 = f64x2::new(0., 2.); + let r: f64x2 = transmute(vcmlaq_rot270_f64(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vfmsd_laneq_f64() { - let a: f64 = 14.; - let b: f64 = 6.; - let c: f64x2 = f64x2::new(2., 0.); - let e: f64 = 2.; - let r: f64 = transmute(vfmsd_laneq_f64::<0>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vcmla_lane_f32() { + let a: f32x2 = f32x2::new(1., -1.); + let b: f32x2 = f32x2::new(-1., 1.); + let c: f32x2 = f32x2::new(1., 1.); + let e: f32x2 = f32x2::new(0., -2.); + let r: f32x2 = transmute(vcmla_lane_f32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdiv_f32() { - let a: f32x2 = f32x2::new(2.0, 6.0); - let b: f32x2 = f32x2::new(1.0, 2.0); - let e: f32x2 = f32x2::new(2.0, 3.0); - let r: f32x2 = transmute(vdiv_f32(transmute(a), transmute(b))); + unsafe fn test_vcmla_laneq_f32() { + let a: f32x2 = f32x2::new(1., -1.); + let b: f32x2 = f32x2::new(-1., 1.); + let c: f32x4 = f32x4::new(1., 1., -1., -1.); + let e: f32x2 = f32x2::new(0., -2.); + let r: f32x2 = transmute(vcmla_laneq_f32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdivq_f32() { - let a: f32x4 = f32x4::new(2.0, 6.0, 4.0, 10.0); - let b: f32x4 = f32x4::new(1.0, 2.0, 1.0, 2.0); - let e: f32x4 = f32x4::new(2.0, 3.0, 4.0, 5.0); - let r: f32x4 = transmute(vdivq_f32(transmute(a), transmute(b))); + unsafe fn test_vcmlaq_lane_f32() { + let a: f32x4 = f32x4::new(1., -1., 1., -1.); + let b: f32x4 = f32x4::new(-1., 1., -1., 1.); + let c: f32x2 = f32x2::new(1., 1.); + let e: f32x4 = f32x4::new(0., -2., 0., -2.); + let r: f32x4 = transmute(vcmlaq_lane_f32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdiv_f64() { - let a: f64 = 2.0; - let b: f64 = 1.0; - let e: f64 = 2.0; - let r: f64 = transmute(vdiv_f64(transmute(a), transmute(b))); + unsafe fn test_vcmlaq_laneq_f32() { + let a: f32x4 = f32x4::new(1., -1., 1., -1.); + let b: f32x4 = f32x4::new(-1., 1., -1., 1.); + let c: f32x4 = f32x4::new(1., 1., -1., -1.); + let e: f32x4 = f32x4::new(0., -2., 0., -2.); + let r: f32x4 = transmute(vcmlaq_laneq_f32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdivq_f64() { - let a: f64x2 = f64x2::new(2.0, 6.0); - let b: f64x2 = f64x2::new(1.0, 2.0); - let e: f64x2 = f64x2::new(2.0, 3.0); - let r: f64x2 = transmute(vdivq_f64(transmute(a), transmute(b))); + unsafe fn test_vcmla_rot90_lane_f32() { + let a: f32x2 = f32x2::new(1., -1.); + let b: f32x2 = f32x2::new(-1., 1.); + let c: f32x2 = f32x2::new(1., 1.); + let e: f32x2 = f32x2::new(0., 0.); + let r: f32x2 = transmute(vcmla_rot90_lane_f32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vsub_f64() { - let a: f64 = 1.0; - let b: f64 = 1.0; - let e: f64 = 0.0; - let r: f64 = transmute(vsub_f64(transmute(a), transmute(b))); + unsafe fn test_vcmla_rot90_laneq_f32() { + let a: f32x2 = f32x2::new(1., -1.); + let b: f32x2 = f32x2::new(-1., 1.); + let c: f32x4 = f32x4::new(1., 1., -1., -1.); + let e: f32x2 = f32x2::new(0., 0.); + let r: f32x2 = transmute(vcmla_rot90_laneq_f32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vsubq_f64() { - let a: f64x2 = f64x2::new(1.0, 4.0); - let b: f64x2 = f64x2::new(1.0, 2.0); - let e: f64x2 = f64x2::new(0.0, 2.0); - let r: f64x2 = transmute(vsubq_f64(transmute(a), transmute(b))); + unsafe fn test_vcmlaq_rot90_lane_f32() { + let a: f32x4 = f32x4::new(1., -1., 1., -1.); + let b: f32x4 = f32x4::new(-1., 1., -1., 1.); + let c: f32x2 = f32x2::new(1., 1.); + let e: f32x4 = f32x4::new(0., 0., 0., 0.); + let r: f32x4 = transmute(vcmlaq_rot90_lane_f32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vaddlv_s16() { - let a: i16x4 = i16x4::new(1, 2, 3, 4); - let e: i32 = 10; - let r: i32 = transmute(vaddlv_s16(transmute(a))); + unsafe fn test_vcmlaq_rot90_laneq_f32() { + let a: f32x4 = f32x4::new(1., -1., 1., -1.); + let b: f32x4 = f32x4::new(-1., 1., -1., 1.); + let c: f32x4 = f32x4::new(1., 1., -1., -1.); + let e: f32x4 = f32x4::new(0., 0., 0., 0.); + let r: f32x4 = transmute(vcmlaq_rot90_laneq_f32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vaddlvq_s16() { - let a: i16x8 = i16x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let e: i32 = 36; - let r: i32 = transmute(vaddlvq_s16(transmute(a))); + unsafe fn test_vcmla_rot180_lane_f32() { + let a: f32x2 = f32x2::new(1., -1.); + let b: f32x2 = f32x2::new(-1., 1.); + let c: f32x2 = f32x2::new(1., 1.); + let e: f32x2 = f32x2::new(2., 0.); + let r: f32x2 = transmute(vcmla_rot180_lane_f32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vaddlv_s32() { - let a: i32x2 = i32x2::new(1, 2); - let e: i64 = 3; - let r: i64 = transmute(vaddlv_s32(transmute(a))); + unsafe fn test_vcmla_rot180_laneq_f32() { + let a: f32x2 = f32x2::new(1., -1.); + let b: f32x2 = f32x2::new(-1., 1.); + let c: f32x4 = f32x4::new(1., 1., -1., -1.); + let e: f32x2 = f32x2::new(2., 0.); + let r: f32x2 = transmute(vcmla_rot180_laneq_f32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vaddlvq_s32() { - let a: i32x4 = i32x4::new(1, 2, 3, 4); - let e: i64 = 10; - let r: i64 = transmute(vaddlvq_s32(transmute(a))); + unsafe fn test_vcmlaq_rot180_lane_f32() { + let a: f32x4 = f32x4::new(1., -1., 1., -1.); + let b: f32x4 = f32x4::new(-1., 1., -1., 1.); + let c: f32x2 = f32x2::new(1., 1.); + let e: f32x4 = f32x4::new(2., 0., 2., 0.); + let r: f32x4 = transmute(vcmlaq_rot180_lane_f32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vaddlv_u16() { - let a: u16x4 = u16x4::new(1, 2, 3, 4); - let e: u32 = 10; - let r: u32 = transmute(vaddlv_u16(transmute(a))); + unsafe fn test_vcmlaq_rot180_laneq_f32() { + let a: f32x4 = f32x4::new(1., -1., 1., -1.); + let b: f32x4 = f32x4::new(-1., 1., -1., 1.); + let c: f32x4 = f32x4::new(1., 1., -1., -1.); + let e: f32x4 = f32x4::new(2., 0., 2., 0.); + let r: f32x4 = transmute(vcmlaq_rot180_laneq_f32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vaddlvq_u16() { - let a: u16x8 = u16x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let e: u32 = 36; - let r: u32 = transmute(vaddlvq_u16(transmute(a))); + unsafe fn test_vcmla_rot270_lane_f32() { + let a: f32x2 = f32x2::new(1., -1.); + let b: f32x2 = f32x2::new(-1., 1.); + let c: f32x2 = f32x2::new(1., 1.); + let e: f32x2 = f32x2::new(2., -2.); + let r: f32x2 = transmute(vcmla_rot270_lane_f32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vaddlv_u32() { - let a: u32x2 = u32x2::new(1, 2); - let e: u64 = 3; - let r: u64 = transmute(vaddlv_u32(transmute(a))); + unsafe fn test_vcmla_rot270_laneq_f32() { + let a: f32x2 = f32x2::new(1., -1.); + let b: f32x2 = f32x2::new(-1., 1.); + let c: f32x4 = f32x4::new(1., 1., -1., -1.); + let e: f32x2 = f32x2::new(2., -2.); + let r: f32x2 = transmute(vcmla_rot270_laneq_f32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vaddlvq_u32() { - let a: u32x4 = u32x4::new(1, 2, 3, 4); - let e: u64 = 10; - let r: u64 = transmute(vaddlvq_u32(transmute(a))); + unsafe fn test_vcmlaq_rot270_lane_f32() { + let a: f32x4 = f32x4::new(1., -1., 1., -1.); + let b: f32x4 = f32x4::new(-1., 1., -1., 1.); + let c: f32x2 = f32x2::new(1., 1.); + let e: f32x4 = f32x4::new(2., -2., 2., -2.); + let r: f32x4 = transmute(vcmlaq_rot270_lane_f32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vsubw_high_s8() { - let a: i16x8 = i16x8::new(8, 9, 10, 12, 13, 14, 15, 16); - let b: i8x16 = i8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15, 16); - let e: i16x8 = i16x8::new(0, 0, 0, 0, 0, 0, 0, 0); - let r: i16x8 = transmute(vsubw_high_s8(transmute(a), transmute(b))); + unsafe fn test_vcmlaq_rot270_laneq_f32() { + let a: f32x4 = f32x4::new(1., -1., 1., -1.); + let b: f32x4 = f32x4::new(-1., 1., -1., 1.); + let c: f32x4 = f32x4::new(1., 1., -1., -1.); + let e: f32x4 = f32x4::new(2., -2., 2., -2.); + let r: f32x4 = transmute(vcmlaq_rot270_laneq_f32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vsubw_high_s16() { - let a: i32x4 = i32x4::new(8, 9, 10, 11); - let b: i16x8 = i16x8::new(0, 1, 2, 3, 8, 9, 10, 11); - let e: i32x4 = i32x4::new(0, 0, 0, 0); - let r: i32x4 = transmute(vsubw_high_s16(transmute(a), transmute(b))); + unsafe fn test_vdot_s32() { + let a: i32x2 = i32x2::new(1, 2); + let b: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let c: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let e: i32x2 = i32x2::new(31, 176); + let r: i32x2 = transmute(vdot_s32(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdotq_s32() { + let a: i32x4 = i32x4::new(1, 2, 1, 2); + let b: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8); + let c: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8); + let e: i32x4 = i32x4::new(31, 176, 31, 176); + let r: i32x4 = transmute(vdotq_s32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vsubw_high_s32() { - let a: i64x2 = i64x2::new(8, 9); - let b: i32x4 = i32x4::new(6, 7, 8, 9); - let e: i64x2 = i64x2::new(0, 0); - let r: i64x2 = transmute(vsubw_high_s32(transmute(a), transmute(b))); + unsafe fn test_vdot_u32() { + let a: u32x2 = u32x2::new(1, 2); + let b: u8x8 = u8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let c: u8x8 = u8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let e: u32x2 = u32x2::new(31, 176); + let r: u32x2 = transmute(vdot_u32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vsubw_high_u8() { - let a: u16x8 = u16x8::new(8, 9, 10, 11, 12, 13, 14, 15); - let b: u8x16 = u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - let e: u16x8 = u16x8::new(0, 0, 0, 0, 0, 0, 0, 0); - let r: u16x8 = transmute(vsubw_high_u8(transmute(a), transmute(b))); + unsafe fn test_vdotq_u32() { + let a: u32x4 = u32x4::new(1, 2, 1, 2); + let b: u8x16 = u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8); + let c: u8x16 = u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8); + let e: u32x4 = u32x4::new(31, 176, 31, 176); + let r: u32x4 = transmute(vdotq_u32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vsubw_high_u16() { - let a: u32x4 = u32x4::new(8, 9, 10, 11); - let b: u16x8 = u16x8::new(0, 1, 2, 3, 8, 9, 10, 11); - let e: u32x4 = u32x4::new(0, 0, 0, 0); - let r: u32x4 = transmute(vsubw_high_u16(transmute(a), transmute(b))); + unsafe fn test_vdot_lane_s32() { + let a: i32x2 = i32x2::new(1, 2); + let b: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let c: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let e: i32x2 = i32x2::new(31, 72); + let r: i32x2 = transmute(vdot_lane_s32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vsubw_high_u32() { - let a: u64x2 = u64x2::new(8, 9); - let b: u32x4 = u32x4::new(6, 7, 8, 9); - let e: u64x2 = u64x2::new(0, 0); - let r: u64x2 = transmute(vsubw_high_u32(transmute(a), transmute(b))); + unsafe fn test_vdot_laneq_s32() { + let a: i32x2 = i32x2::new(1, 2); + let b: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let c: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8); + let e: i32x2 = i32x2::new(31, 72); + let r: i32x2 = transmute(vdot_laneq_s32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vsubl_high_s8() { - let a: i8x16 = i8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - let b: i8x16 = i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2); - let e: i16x8 = i16x8::new(6, 7, 8, 9, 10, 11, 12, 13); - let r: i16x8 = transmute(vsubl_high_s8(transmute(a), transmute(b))); + unsafe fn test_vdotq_lane_s32() { + let a: i32x4 = i32x4::new(1, 2, 1, 2); + let b: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8); + let c: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let e: i32x4 = i32x4::new(31, 72, 31, 72); + let r: i32x4 = transmute(vdotq_lane_s32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vsubl_high_s16() { - let a: i16x8 = i16x8::new(8, 9, 10, 11, 12, 13, 14, 15); - let b: i16x8 = i16x8::new(6, 6, 6, 6, 8, 8, 8, 8); - let e: i32x4 = i32x4::new(4, 5, 6, 7); - let r: i32x4 = transmute(vsubl_high_s16(transmute(a), transmute(b))); + unsafe fn test_vdotq_laneq_s32() { + let a: i32x4 = i32x4::new(1, 2, 1, 2); + let b: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8); + let c: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8); + let e: i32x4 = i32x4::new(31, 72, 31, 72); + let r: i32x4 = transmute(vdotq_laneq_s32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vsubl_high_s32() { - let a: i32x4 = i32x4::new(12, 13, 14, 15); - let b: i32x4 = i32x4::new(6, 6, 8, 8); - let e: i64x2 = i64x2::new(6, 7); - let r: i64x2 = transmute(vsubl_high_s32(transmute(a), transmute(b))); + unsafe fn test_vdot_lane_u32() { + let a: u32x2 = u32x2::new(1, 2); + let b: u8x8 = u8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let c: u8x8 = u8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let e: u32x2 = u32x2::new(31, 72); + let r: u32x2 = transmute(vdot_lane_u32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vsubl_high_u8() { - let a: u8x16 = u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - let b: u8x16 = u8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2); - let e: u16x8 = u16x8::new(6, 7, 8, 9, 10, 11, 12, 13); - let r: u16x8 = transmute(vsubl_high_u8(transmute(a), transmute(b))); + unsafe fn test_vdot_laneq_u32() { + let a: u32x2 = u32x2::new(1, 2); + let b: u8x8 = u8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let c: u8x16 = u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8); + let e: u32x2 = u32x2::new(31, 72); + let r: u32x2 = transmute(vdot_laneq_u32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vsubl_high_u16() { - let a: u16x8 = u16x8::new(8, 9, 10, 11, 12, 13, 14, 15); - let b: u16x8 = u16x8::new(6, 6, 6, 6, 8, 8, 8, 8); - let e: u32x4 = u32x4::new(4, 5, 6, 7); - let r: u32x4 = transmute(vsubl_high_u16(transmute(a), transmute(b))); + unsafe fn test_vdotq_lane_u32() { + let a: u32x4 = u32x4::new(1, 2, 1, 2); + let b: u8x16 = u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8); + let c: u8x8 = u8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let e: u32x4 = u32x4::new(31, 72, 31, 72); + let r: u32x4 = transmute(vdotq_lane_u32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vsubl_high_u32() { - let a: u32x4 = u32x4::new(12, 13, 14, 15); - let b: u32x4 = u32x4::new(6, 6, 8, 8); - let e: u64x2 = u64x2::new(6, 7); - let r: u64x2 = transmute(vsubl_high_u32(transmute(a), transmute(b))); + unsafe fn test_vdotq_laneq_u32() { + let a: u32x4 = u32x4::new(1, 2, 1, 2); + let b: u8x16 = u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8); + let c: u8x16 = u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8); + let e: u32x4 = u32x4::new(31, 72, 31, 72); + let r: u32x4 = transmute(vdotq_laneq_u32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } @@ -14156,6 +19936,30 @@ mod test { assert_eq!(r, e); } + #[simd_test(enable = "neon")] + unsafe fn test_vmaxnmv_f32() { + let a: f32x2 = f32x2::new(1., 2.); + let e: f32 = 2.; + let r: f32 = transmute(vmaxnmv_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmaxnmvq_f64() { + let a: f64x2 = f64x2::new(1., 2.); + let e: f64 = 2.; + let r: f64 = transmute(vmaxnmvq_f64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmaxnmvq_f32() { + let a: f32x4 = f32x4::new(1., 2., 0., 1.); + let e: f32 = 2.; + let r: f32 = transmute(vmaxnmvq_f32(transmute(a))); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vpmaxnm_f32() { let a: f32x2 = f32x2::new(1.0, 2.0); @@ -14183,6 +19987,38 @@ mod test { assert_eq!(r, e); } + #[simd_test(enable = "neon")] + unsafe fn test_vpmaxnms_f32() { + let a: f32x2 = f32x2::new(1., 2.); + let e: f32 = 2.; + let r: f32 = transmute(vpmaxnms_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vpmaxnmqd_f64() { + let a: f64x2 = f64x2::new(1., 2.); + let e: f64 = 2.; + let r: f64 = transmute(vpmaxnmqd_f64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vpmaxs_f32() { + let a: f32x2 = f32x2::new(1., 2.); + let e: f32 = 2.; + let r: f32 = transmute(vpmaxs_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vpmaxqd_f64() { + let a: f64x2 = f64x2::new(1., 2.); + let e: f64 = 2.; + let r: f64 = transmute(vpmaxqd_f64(transmute(a))); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vmin_f64() { let a: f64 = 1.0; @@ -14219,6 +20055,112 @@ mod test { assert_eq!(r, e); } + #[simd_test(enable = "neon")] + unsafe fn test_vminnmv_f32() { + let a: f32x2 = f32x2::new(1., 0.); + let e: f32 = 0.; + let r: f32 = transmute(vminnmv_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vminnmvq_f64() { + let a: f64x2 = f64x2::new(1., 0.); + let e: f64 = 0.; + let r: f64 = transmute(vminnmvq_f64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vminnmvq_f32() { + let a: f32x4 = f32x4::new(1., 0., 2., 3.); + let e: f32 = 0.; + let r: f32 = transmute(vminnmvq_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmovl_high_s8() { + let a: i8x16 = i8x16::new(1, 2, 3, 4, 3, 4, 5, 6, 3, 4, 5, 6, 7, 8, 9, 10); + let e: i16x8 = i16x8::new(3, 4, 5, 6, 7, 8, 9, 10); + let r: i16x8 = transmute(vmovl_high_s8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmovl_high_s16() { + let a: i16x8 = i16x8::new(1, 2, 3, 4, 3, 4, 5, 6); + let e: i32x4 = i32x4::new(3, 4, 5, 6); + let r: i32x4 = transmute(vmovl_high_s16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmovl_high_s32() { + let a: i32x4 = i32x4::new(1, 2, 3, 4); + let e: i64x2 = i64x2::new(3, 4); + let r: i64x2 = transmute(vmovl_high_s32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmovl_high_u8() { + let a: u8x16 = u8x16::new(1, 2, 3, 4, 3, 4, 5, 6, 3, 4, 5, 6, 7, 8, 9, 10); + let e: u16x8 = u16x8::new(3, 4, 5, 6, 7, 8, 9, 10); + let r: u16x8 = transmute(vmovl_high_u8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmovl_high_u16() { + let a: u16x8 = u16x8::new(1, 2, 3, 4, 3, 4, 5, 6); + let e: u32x4 = u32x4::new(3, 4, 5, 6); + let r: u32x4 = transmute(vmovl_high_u16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmovl_high_u32() { + let a: u32x4 = u32x4::new(1, 2, 3, 4); + let e: u64x2 = u64x2::new(3, 4); + let r: u64x2 = transmute(vmovl_high_u32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vpaddq_f32() { + let a: f32x4 = f32x4::new(1., 2., 3., 4.); + let b: f32x4 = f32x4::new(3., 4., 5., 6.); + let e: f32x4 = f32x4::new(3., 7., 7., 11.); + let r: f32x4 = transmute(vpaddq_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vpaddq_f64() { + let a: f64x2 = f64x2::new(1., 2.); + let b: f64x2 = f64x2::new(3., 4.); + let e: f64x2 = f64x2::new(3., 7.); + let r: f64x2 = transmute(vpaddq_f64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vpadds_f32() { + let a: f32x2 = f32x2::new(1., 2.); + let e: f32 = 3.; + let r: f32 = transmute(vpadds_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vpaddd_f64() { + let a: f64x2 = f64x2::new(1., 2.); + let e: f64 = 3.; + let r: f64 = transmute(vpaddd_f64(transmute(a))); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vpminnm_f32() { let a: f32x2 = f32x2::new(1.0, 2.0); @@ -14246,6 +20188,38 @@ mod test { assert_eq!(r, e); } + #[simd_test(enable = "neon")] + unsafe fn test_vpminnms_f32() { + let a: f32x2 = f32x2::new(1., 2.); + let e: f32 = 1.; + let r: f32 = transmute(vpminnms_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vpminnmqd_f64() { + let a: f64x2 = f64x2::new(1., 2.); + let e: f64 = 1.; + let r: f64 = transmute(vpminnmqd_f64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vpmins_f32() { + let a: f32x2 = f32x2::new(1., 2.); + let e: f32 = 1.; + let r: f32 = transmute(vpmins_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vpminqd_f64() { + let a: f64x2 = f64x2::new(1., 2.); + let e: f64 = 1.; + let r: f64 = transmute(vpminqd_f64(transmute(a))); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vqdmullh_s16() { let a: i16 = 2; @@ -14490,6 +20464,66 @@ mod test { assert_eq!(r, e); } + #[simd_test(enable = "neon")] + unsafe fn test_vqdmlalh_s16() { + let a: i32 = 1; + let b: i16 = 1; + let c: i16 = 2; + let e: i32 = 5; + let r: i32 = transmute(vqdmlalh_s16(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqdmlals_s32() { + let a: i64 = 1; + let b: i32 = 1; + let c: i32 = 2; + let e: i64 = 5; + let r: i64 = transmute(vqdmlals_s32(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqdmlalh_lane_s16() { + let a: i32 = 1; + let b: i16 = 1; + let c: i16x4 = i16x4::new(2, 1, 1, 1); + let e: i32 = 5; + let r: i32 = transmute(vqdmlalh_lane_s16::<0>(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqdmlalh_laneq_s16() { + let a: i32 = 1; + let b: i16 = 1; + let c: i16x8 = i16x8::new(2, 1, 1, 1, 1, 1, 1, 1); + let e: i32 = 5; + let r: i32 = transmute(vqdmlalh_laneq_s16::<0>(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqdmlals_lane_s32() { + let a: i64 = 1; + let b: i32 = 1; + let c: i32x2 = i32x2::new(2, 1); + let e: i64 = 5; + let r: i64 = transmute(vqdmlals_lane_s32::<0>(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqdmlals_laneq_s32() { + let a: i64 = 1; + let b: i32 = 1; + let c: i32x4 = i32x4::new(2, 1, 1, 1); + let e: i64 = 5; + let r: i64 = transmute(vqdmlals_laneq_s32::<0>(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vqdmlsl_high_s16() { let a: i32x4 = i32x4::new(39, 58, 81, 108); @@ -14571,22 +20605,82 @@ mod test { } #[simd_test(enable = "neon")] - unsafe fn test_vqdmlsl_high_lane_s32() { - let a: i64x2 = i64x2::new(15, 18); - let b: i32x4 = i32x4::new(0, 1, 4, 5); - let c: i32x2 = i32x2::new(0, 2); - let e: i64x2 = i64x2::new(-1, -2); - let r: i64x2 = transmute(vqdmlsl_high_lane_s32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vqdmlsl_high_lane_s32() { + let a: i64x2 = i64x2::new(15, 18); + let b: i32x4 = i32x4::new(0, 1, 4, 5); + let c: i32x2 = i32x2::new(0, 2); + let e: i64x2 = i64x2::new(-1, -2); + let r: i64x2 = transmute(vqdmlsl_high_lane_s32::<1>(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqdmlsl_high_laneq_s32() { + let a: i64x2 = i64x2::new(15, 18); + let b: i32x4 = i32x4::new(0, 1, 4, 5); + let c: i32x4 = i32x4::new(0, 2, 0, 0); + let e: i64x2 = i64x2::new(-1, -2); + let r: i64x2 = transmute(vqdmlsl_high_laneq_s32::<1>(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqdmlslh_s16() { + let a: i32 = 10; + let b: i16 = 1; + let c: i16 = 2; + let e: i32 = 6; + let r: i32 = transmute(vqdmlslh_s16(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqdmlsls_s32() { + let a: i64 = 10; + let b: i32 = 1; + let c: i32 = 2; + let e: i64 = 6; + let r: i64 = transmute(vqdmlsls_s32(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqdmlslh_lane_s16() { + let a: i32 = 10; + let b: i16 = 1; + let c: i16x4 = i16x4::new(2, 1, 1, 1); + let e: i32 = 6; + let r: i32 = transmute(vqdmlslh_lane_s16::<0>(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqdmlslh_laneq_s16() { + let a: i32 = 10; + let b: i16 = 1; + let c: i16x8 = i16x8::new(2, 1, 1, 1, 1, 1, 1, 1); + let e: i32 = 6; + let r: i32 = transmute(vqdmlslh_laneq_s16::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqdmlsl_high_laneq_s32() { - let a: i64x2 = i64x2::new(15, 18); - let b: i32x4 = i32x4::new(0, 1, 4, 5); - let c: i32x4 = i32x4::new(0, 2, 0, 0); - let e: i64x2 = i64x2::new(-1, -2); - let r: i64x2 = transmute(vqdmlsl_high_laneq_s32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vqdmlsls_lane_s32() { + let a: i64 = 10; + let b: i32 = 1; + let c: i32x2 = i32x2::new(2, 1); + let e: i64 = 6; + let r: i64 = transmute(vqdmlsls_lane_s32::<0>(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqdmlsls_laneq_s32() { + let a: i64 = 10; + let b: i32 = 1; + let c: i32x4 = i32x4::new(2, 1, 1, 1); + let e: i64 = 6; + let r: i64 = transmute(vqdmlsls_laneq_s32::<0>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } @@ -14644,6 +20738,42 @@ mod test { assert_eq!(r, e); } + #[simd_test(enable = "neon")] + unsafe fn test_vqdmulh_lane_s16() { + let a: i16x4 = i16x4::new(0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF); + let b: i16x4 = i16x4::new(2, 1, 1, 1); + let e: i16x4 = i16x4::new(1, 1, 1, 1); + let r: i16x4 = transmute(vqdmulh_lane_s16::<0>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqdmulhq_lane_s16() { + let a: i16x8 = i16x8::new(0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF); + let b: i16x4 = i16x4::new(2, 1, 1, 1); + let e: i16x8 = i16x8::new(1, 1, 1, 1, 1, 1, 1, 1); + let r: i16x8 = transmute(vqdmulhq_lane_s16::<0>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqdmulh_lane_s32() { + let a: i32x2 = i32x2::new(0x7F_FF_FF_FF, 0x7F_FF_FF_FF); + let b: i32x2 = i32x2::new(2, 1); + let e: i32x2 = i32x2::new(1, 1); + let r: i32x2 = transmute(vqdmulh_lane_s32::<0>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqdmulhq_lane_s32() { + let a: i32x4 = i32x4::new(0x7F_FF_FF_FF, 0x7F_FF_FF_FF, 0x7F_FF_FF_FF, 0x7F_FF_FF_FF); + let b: i32x2 = i32x2::new(2, 1); + let e: i32x4 = i32x4::new(1, 1, 1, 1); + let r: i32x4 = transmute(vqdmulhq_lane_s32::<0>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vqmovnh_s16() { let a: i16 = 1; @@ -14851,6 +20981,46 @@ mod test { assert_eq!(r, e); } + #[simd_test(enable = "neon")] + unsafe fn test_vqrdmlah_s16() { + let a: i16x4 = i16x4::new(1, 1, 1, 1); + let b: i16x4 = i16x4::new(0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF); + let c: i16x4 = i16x4::new(2, 2, 2, 2); + let e: i16x4 = i16x4::new(3, 3, 3, 3); + let r: i16x4 = transmute(vqrdmlah_s16(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqrdmlahq_s16() { + let a: i16x8 = i16x8::new(1, 1, 1, 1, 1, 1, 1, 1); + let b: i16x8 = i16x8::new(0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF); + let c: i16x8 = i16x8::new(2, 2, 2, 2, 2, 2, 2, 2); + let e: i16x8 = i16x8::new(3, 3, 3, 3, 3, 3, 3, 3); + let r: i16x8 = transmute(vqrdmlahq_s16(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqrdmlah_s32() { + let a: i32x2 = i32x2::new(1, 1); + let b: i32x2 = i32x2::new(0x7F_FF_FF_FF, 0x7F_FF_FF_FF); + let c: i32x2 = i32x2::new(2, 2); + let e: i32x2 = i32x2::new(3, 3); + let r: i32x2 = transmute(vqrdmlah_s32(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqrdmlahq_s32() { + let a: i32x4 = i32x4::new(1, 1, 1, 1); + let b: i32x4 = i32x4::new(0x7F_FF_FF_FF, 0x7F_FF_FF_FF, 0x7F_FF_FF_FF, 0x7F_FF_FF_FF); + let c: i32x4 = i32x4::new(2, 2, 2, 2); + let e: i32x4 = i32x4::new(3, 3, 3, 3); + let r: i32x4 = transmute(vqrdmlahq_s32(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vqrdmlahh_s16() { let a: i16 = 1; @@ -14871,6 +21041,86 @@ mod test { assert_eq!(r, e); } + #[simd_test(enable = "neon")] + unsafe fn test_vqrdmlah_lane_s16() { + let a: i16x4 = i16x4::new(1, 1, 1, 1); + let b: i16x4 = i16x4::new(0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF); + let c: i16x4 = i16x4::new(0, 2, 0, 0); + let e: i16x4 = i16x4::new(3, 3, 3, 3); + let r: i16x4 = transmute(vqrdmlah_lane_s16::<1>(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqrdmlah_laneq_s16() { + let a: i16x4 = i16x4::new(1, 1, 1, 1); + let b: i16x4 = i16x4::new(0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF); + let c: i16x8 = i16x8::new(0, 2, 0, 0, 0, 0, 0, 0); + let e: i16x4 = i16x4::new(3, 3, 3, 3); + let r: i16x4 = transmute(vqrdmlah_laneq_s16::<1>(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqrdmlahq_lane_s16() { + let a: i16x8 = i16x8::new(1, 1, 1, 1, 1, 1, 1, 1); + let b: i16x8 = i16x8::new(0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF); + let c: i16x4 = i16x4::new(0, 2, 0, 0); + let e: i16x8 = i16x8::new(3, 3, 3, 3, 3, 3, 3, 3); + let r: i16x8 = transmute(vqrdmlahq_lane_s16::<1>(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqrdmlahq_laneq_s16() { + let a: i16x8 = i16x8::new(1, 1, 1, 1, 1, 1, 1, 1); + let b: i16x8 = i16x8::new(0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF); + let c: i16x8 = i16x8::new(0, 2, 0, 0, 0, 0, 0, 0); + let e: i16x8 = i16x8::new(3, 3, 3, 3, 3, 3, 3, 3); + let r: i16x8 = transmute(vqrdmlahq_laneq_s16::<1>(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqrdmlah_lane_s32() { + let a: i32x2 = i32x2::new(1, 1); + let b: i32x2 = i32x2::new(0x7F_FF_FF_FF, 0x7F_FF_FF_FF); + let c: i32x2 = i32x2::new(0, 2); + let e: i32x2 = i32x2::new(3, 3); + let r: i32x2 = transmute(vqrdmlah_lane_s32::<1>(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqrdmlah_laneq_s32() { + let a: i32x2 = i32x2::new(1, 1); + let b: i32x2 = i32x2::new(0x7F_FF_FF_FF, 0x7F_FF_FF_FF); + let c: i32x4 = i32x4::new(0, 2, 0, 0); + let e: i32x2 = i32x2::new(3, 3); + let r: i32x2 = transmute(vqrdmlah_laneq_s32::<1>(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqrdmlahq_lane_s32() { + let a: i32x4 = i32x4::new(1, 1, 1, 1); + let b: i32x4 = i32x4::new(0x7F_FF_FF_FF, 0x7F_FF_FF_FF, 0x7F_FF_FF_FF, 0x7F_FF_FF_FF); + let c: i32x2 = i32x2::new(0, 2); + let e: i32x4 = i32x4::new(3, 3, 3, 3); + let r: i32x4 = transmute(vqrdmlahq_lane_s32::<1>(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqrdmlahq_laneq_s32() { + let a: i32x4 = i32x4::new(1, 1, 1, 1); + let b: i32x4 = i32x4::new(0x7F_FF_FF_FF, 0x7F_FF_FF_FF, 0x7F_FF_FF_FF, 0x7F_FF_FF_FF); + let c: i32x4 = i32x4::new(0, 2, 0, 0); + let e: i32x4 = i32x4::new(3, 3, 3, 3); + let r: i32x4 = transmute(vqrdmlahq_laneq_s32::<1>(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vqrdmlahh_lane_s16() { let a: i16 = 1; @@ -15332,6 +21582,38 @@ mod test { assert_eq!(r, e); } + #[simd_test(enable = "neon")] + unsafe fn test_vqshlub_n_s8() { + let a: i8 = 1; + let e: u8 = 4; + let r: u8 = transmute(vqshlub_n_s8::<2>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqshluh_n_s16() { + let a: i16 = 1; + let e: u16 = 4; + let r: u16 = transmute(vqshluh_n_s16::<2>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqshlus_n_s32() { + let a: i32 = 1; + let e: u32 = 4; + let r: u32 = transmute(vqshlus_n_s32::<2>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqshlud_n_s64() { + let a: i64 = 1; + let e: u64 = 4; + let r: u64 = transmute(vqshlud_n_s64::<2>(transmute(a))); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vqshrnd_n_s64() { let a: i64 = 0; @@ -15486,386 +21768,286 @@ mod test { } #[simd_test(enable = "neon")] - unsafe fn test_vsqrt_f32() { - let a: f32x2 = f32x2::new(4.0, 9.0); - let e: f32x2 = f32x2::new(2.0, 3.0); - let r: f32x2 = transmute(vsqrt_f32(transmute(a))); - assert_eq!(r, e); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vsqrtq_f32() { - let a: f32x4 = f32x4::new(4.0, 9.0, 16.0, 25.0); - let e: f32x4 = f32x4::new(2.0, 3.0, 4.0, 5.0); - let r: f32x4 = transmute(vsqrtq_f32(transmute(a))); - assert_eq!(r, e); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vsqrt_f64() { - let a: f64 = 4.0; - let e: f64 = 2.0; - let r: f64 = transmute(vsqrt_f64(transmute(a))); - assert_eq!(r, e); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vsqrtq_f64() { - let a: f64x2 = f64x2::new(4.0, 9.0); - let e: f64x2 = f64x2::new(2.0, 3.0); - let r: f64x2 = transmute(vsqrtq_f64(transmute(a))); - assert_eq!(r, e); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vrsqrte_f64() { - let a: f64 = 1.0; - let e: f64 = 0.998046875; - let r: f64 = transmute(vrsqrte_f64(transmute(a))); - assert_eq!(r, e); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vrsqrteq_f64() { - let a: f64x2 = f64x2::new(1.0, 2.0); - let e: f64x2 = f64x2::new(0.998046875, 0.705078125); - let r: f64x2 = transmute(vrsqrteq_f64(transmute(a))); - assert_eq!(r, e); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vrecpe_f64() { - let a: f64 = 4.0; - let e: f64 = 0.24951171875; - let r: f64 = transmute(vrecpe_f64(transmute(a))); - assert_eq!(r, e); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vrecpeq_f64() { - let a: f64x2 = f64x2::new(4.0, 3.0); - let e: f64x2 = f64x2::new(0.24951171875, 0.3330078125); - let r: f64x2 = transmute(vrecpeq_f64(transmute(a))); - assert_eq!(r, e); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vreinterpret_s64_p64() { - let a: i64x1 = i64x1::new(0); - let e: i64x1 = i64x1::new(0); - let r: i64x1 = transmute(vreinterpret_s64_p64(transmute(a))); - assert_eq!(r, e); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vreinterpret_u64_p64() { - let a: i64x1 = i64x1::new(0); - let e: u64x1 = u64x1::new(0); - let r: u64x1 = transmute(vreinterpret_u64_p64(transmute(a))); - assert_eq!(r, e); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vreinterpret_p64_s64() { - let a: i64x1 = i64x1::new(0); - let e: i64x1 = i64x1::new(0); - let r: i64x1 = transmute(vreinterpret_p64_s64(transmute(a))); - assert_eq!(r, e); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vreinterpret_p64_u64() { - let a: u64x1 = u64x1::new(0); - let e: i64x1 = i64x1::new(0); - let r: i64x1 = transmute(vreinterpret_p64_u64(transmute(a))); - assert_eq!(r, e); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vreinterpretq_s64_p64() { - let a: i64x2 = i64x2::new(0, 1); - let e: i64x2 = i64x2::new(0, 1); - let r: i64x2 = transmute(vreinterpretq_s64_p64(transmute(a))); - assert_eq!(r, e); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vreinterpretq_u64_p64() { - let a: i64x2 = i64x2::new(0, 1); - let e: u64x2 = u64x2::new(0, 1); - let r: u64x2 = transmute(vreinterpretq_u64_p64(transmute(a))); - assert_eq!(r, e); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vreinterpretq_p64_s64() { - let a: i64x2 = i64x2::new(0, 1); - let e: i64x2 = i64x2::new(0, 1); - let r: i64x2 = transmute(vreinterpretq_p64_s64(transmute(a))); + unsafe fn test_vsqaddb_u8() { + let a: u8 = 2; + let b: i8 = 2; + let e: u8 = 4; + let r: u8 = transmute(vsqaddb_u8(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpretq_p64_u64() { - let a: u64x2 = u64x2::new(0, 1); - let e: i64x2 = i64x2::new(0, 1); - let r: i64x2 = transmute(vreinterpretq_p64_u64(transmute(a))); + unsafe fn test_vsqaddh_u16() { + let a: u16 = 2; + let b: i16 = 2; + let e: u16 = 4; + let r: u16 = transmute(vsqaddh_u16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpret_s32_p64() { - let a: i64x1 = i64x1::new(0); - let e: i32x2 = i32x2::new(0, 0); - let r: i32x2 = transmute(vreinterpret_s32_p64(transmute(a))); + unsafe fn test_vsqadds_u32() { + let a: u32 = 2; + let b: i32 = 2; + let e: u32 = 4; + let r: u32 = transmute(vsqadds_u32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpret_u32_p64() { - let a: i64x1 = i64x1::new(0); - let e: u32x2 = u32x2::new(0, 0); - let r: u32x2 = transmute(vreinterpret_u32_p64(transmute(a))); + unsafe fn test_vsqaddd_u64() { + let a: u64 = 2; + let b: i64 = 2; + let e: u64 = 4; + let r: u64 = transmute(vsqaddd_u64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpretq_s32_p64() { - let a: i64x2 = i64x2::new(0, 1); - let e: i32x4 = i32x4::new(0, 0, 1, 0); - let r: i32x4 = transmute(vreinterpretq_s32_p64(transmute(a))); + unsafe fn test_vsqrt_f32() { + let a: f32x2 = f32x2::new(4.0, 9.0); + let e: f32x2 = f32x2::new(2.0, 3.0); + let r: f32x2 = transmute(vsqrt_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpretq_u32_p64() { - let a: i64x2 = i64x2::new(0, 1); - let e: u32x4 = u32x4::new(0, 0, 1, 0); - let r: u32x4 = transmute(vreinterpretq_u32_p64(transmute(a))); + unsafe fn test_vsqrtq_f32() { + let a: f32x4 = f32x4::new(4.0, 9.0, 16.0, 25.0); + let e: f32x4 = f32x4::new(2.0, 3.0, 4.0, 5.0); + let r: f32x4 = transmute(vsqrtq_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpret_p64_s32() { - let a: i32x2 = i32x2::new(0, 0); - let e: i64x1 = i64x1::new(0); - let r: i64x1 = transmute(vreinterpret_p64_s32(transmute(a))); + unsafe fn test_vsqrt_f64() { + let a: f64 = 4.0; + let e: f64 = 2.0; + let r: f64 = transmute(vsqrt_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpret_p64_u32() { - let a: u32x2 = u32x2::new(0, 0); - let e: i64x1 = i64x1::new(0); - let r: i64x1 = transmute(vreinterpret_p64_u32(transmute(a))); + unsafe fn test_vsqrtq_f64() { + let a: f64x2 = f64x2::new(4.0, 9.0); + let e: f64x2 = f64x2::new(2.0, 3.0); + let r: f64x2 = transmute(vsqrtq_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpretq_p64_s32() { - let a: i32x4 = i32x4::new(0, 0, 1, 0); - let e: i64x2 = i64x2::new(0, 1); - let r: i64x2 = transmute(vreinterpretq_p64_s32(transmute(a))); + unsafe fn test_vrsqrte_f64() { + let a: f64 = 1.0; + let e: f64 = 0.998046875; + let r: f64 = transmute(vrsqrte_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpretq_p64_u32() { - let a: u32x4 = u32x4::new(0, 0, 1, 0); - let e: i64x2 = i64x2::new(0, 1); - let r: i64x2 = transmute(vreinterpretq_p64_u32(transmute(a))); + unsafe fn test_vrsqrteq_f64() { + let a: f64x2 = f64x2::new(1.0, 2.0); + let e: f64x2 = f64x2::new(0.998046875, 0.705078125); + let r: f64x2 = transmute(vrsqrteq_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpret_s16_p64() { - let a: i64x1 = i64x1::new(0); - let e: i16x4 = i16x4::new(0, 0, 0, 0); - let r: i16x4 = transmute(vreinterpret_s16_p64(transmute(a))); + unsafe fn test_vrsqrtes_f32() { + let a: f32 = 1.0; + let e: f32 = 0.998046875; + let r: f32 = transmute(vrsqrtes_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpret_u16_p64() { - let a: i64x1 = i64x1::new(0); - let e: u16x4 = u16x4::new(0, 0, 0, 0); - let r: u16x4 = transmute(vreinterpret_u16_p64(transmute(a))); + unsafe fn test_vrsqrted_f64() { + let a: f64 = 1.0; + let e: f64 = 0.998046875; + let r: f64 = transmute(vrsqrted_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpret_p16_p64() { - let a: i64x1 = i64x1::new(0); - let e: i16x4 = i16x4::new(0, 0, 0, 0); - let r: i16x4 = transmute(vreinterpret_p16_p64(transmute(a))); + unsafe fn test_vrsqrts_f64() { + let a: f64 = 1.0; + let b: f64 = 1.0; + let e: f64 = 1.; + let r: f64 = transmute(vrsqrts_f64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpretq_s16_p64() { - let a: i64x2 = i64x2::new(0, 1); - let e: i16x8 = i16x8::new(0, 0, 0, 0, 1, 0, 0, 0); - let r: i16x8 = transmute(vreinterpretq_s16_p64(transmute(a))); + unsafe fn test_vrsqrtsq_f64() { + let a: f64x2 = f64x2::new(1.0, 2.0); + let b: f64x2 = f64x2::new(1.0, 2.0); + let e: f64x2 = f64x2::new(1., -0.5); + let r: f64x2 = transmute(vrsqrtsq_f64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpretq_u16_p64() { - let a: i64x2 = i64x2::new(0, 1); - let e: u16x8 = u16x8::new(0, 0, 0, 0, 1, 0, 0, 0); - let r: u16x8 = transmute(vreinterpretq_u16_p64(transmute(a))); + unsafe fn test_vrsqrtss_f32() { + let a: f32 = 1.0; + let b: f32 = 1.0; + let e: f32 = 1.; + let r: f32 = transmute(vrsqrtss_f32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpretq_p16_p64() { - let a: i64x2 = i64x2::new(0, 1); - let e: i16x8 = i16x8::new(0, 0, 0, 0, 1, 0, 0, 0); - let r: i16x8 = transmute(vreinterpretq_p16_p64(transmute(a))); + unsafe fn test_vrsqrtsd_f64() { + let a: f64 = 1.0; + let b: f64 = 1.0; + let e: f64 = 1.; + let r: f64 = transmute(vrsqrtsd_f64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpret_p64_p16() { - let a: i16x4 = i16x4::new(0, 0, 0, 0); - let e: i64x1 = i64x1::new(0); - let r: i64x1 = transmute(vreinterpret_p64_p16(transmute(a))); + unsafe fn test_vrecpe_f64() { + let a: f64 = 4.0; + let e: f64 = 0.24951171875; + let r: f64 = transmute(vrecpe_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpret_p64_s16() { - let a: i16x4 = i16x4::new(0, 0, 0, 0); - let e: i64x1 = i64x1::new(0); - let r: i64x1 = transmute(vreinterpret_p64_s16(transmute(a))); + unsafe fn test_vrecpeq_f64() { + let a: f64x2 = f64x2::new(4.0, 3.0); + let e: f64x2 = f64x2::new(0.24951171875, 0.3330078125); + let r: f64x2 = transmute(vrecpeq_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpret_p64_u16() { - let a: u16x4 = u16x4::new(0, 0, 0, 0); - let e: i64x1 = i64x1::new(0); - let r: i64x1 = transmute(vreinterpret_p64_u16(transmute(a))); + unsafe fn test_vrecpes_f32() { + let a: f32 = 4.0; + let e: f32 = 0.24951171875; + let r: f32 = transmute(vrecpes_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpretq_p64_p16() { - let a: i16x8 = i16x8::new(0, 0, 0, 0, 1, 0, 0, 0); - let e: i64x2 = i64x2::new(0, 1); - let r: i64x2 = transmute(vreinterpretq_p64_p16(transmute(a))); + unsafe fn test_vrecped_f64() { + let a: f64 = 4.0; + let e: f64 = 0.24951171875; + let r: f64 = transmute(vrecped_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpretq_p64_s16() { - let a: i16x8 = i16x8::new(0, 0, 0, 0, 1, 0, 0, 0); - let e: i64x2 = i64x2::new(0, 1); - let r: i64x2 = transmute(vreinterpretq_p64_s16(transmute(a))); + unsafe fn test_vrecps_f64() { + let a: f64 = 4.0; + let b: f64 = 4.0; + let e: f64 = -14.; + let r: f64 = transmute(vrecps_f64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpretq_p64_u16() { - let a: u16x8 = u16x8::new(0, 0, 0, 0, 1, 0, 0, 0); - let e: i64x2 = i64x2::new(0, 1); - let r: i64x2 = transmute(vreinterpretq_p64_u16(transmute(a))); + unsafe fn test_vrecpsq_f64() { + let a: f64x2 = f64x2::new(4.0, 3.0); + let b: f64x2 = f64x2::new(4.0, 3.0); + let e: f64x2 = f64x2::new(-14., -7.); + let r: f64x2 = transmute(vrecpsq_f64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpret_s8_p64() { - let a: i64x1 = i64x1::new(0); - let e: i8x8 = i8x8::new(0, 0, 0, 0, 0, 0, 0, 0); - let r: i8x8 = transmute(vreinterpret_s8_p64(transmute(a))); + unsafe fn test_vrecpss_f32() { + let a: f32 = 4.0; + let b: f32 = 4.0; + let e: f32 = -14.; + let r: f32 = transmute(vrecpss_f32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpret_u8_p64() { - let a: i64x1 = i64x1::new(0); - let e: u8x8 = u8x8::new(0, 0, 0, 0, 0, 0, 0, 0); - let r: u8x8 = transmute(vreinterpret_u8_p64(transmute(a))); + unsafe fn test_vrecpsd_f64() { + let a: f64 = 4.0; + let b: f64 = 4.0; + let e: f64 = -14.; + let r: f64 = transmute(vrecpsd_f64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpret_p8_p64() { - let a: i64x1 = i64x1::new(0); - let e: i8x8 = i8x8::new(0, 0, 0, 0, 0, 0, 0, 0); - let r: i8x8 = transmute(vreinterpret_p8_p64(transmute(a))); + unsafe fn test_vrecpxs_f32() { + let a: f32 = 4.0; + let e: f32 = 0.5; + let r: f32 = transmute(vrecpxs_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpretq_s8_p64() { - let a: i64x2 = i64x2::new(0, 1); - let e: i8x16 = i8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0); - let r: i8x16 = transmute(vreinterpretq_s8_p64(transmute(a))); + unsafe fn test_vrecpxd_f64() { + let a: f64 = 4.0; + let e: f64 = 0.5; + let r: f64 = transmute(vrecpxd_f64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpretq_u8_p64() { - let a: i64x2 = i64x2::new(0, 1); - let e: u8x16 = u8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0); - let r: u8x16 = transmute(vreinterpretq_u8_p64(transmute(a))); + unsafe fn test_vreinterpret_s64_p64() { + let a: i64x1 = i64x1::new(0); + let e: i64x1 = i64x1::new(0); + let r: i64x1 = transmute(vreinterpret_s64_p64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpretq_p8_p64() { - let a: i64x2 = i64x2::new(0, 1); - let e: i8x16 = i8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0); - let r: i8x16 = transmute(vreinterpretq_p8_p64(transmute(a))); + unsafe fn test_vreinterpret_u64_p64() { + let a: i64x1 = i64x1::new(0); + let e: u64x1 = u64x1::new(0); + let r: u64x1 = transmute(vreinterpret_u64_p64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpret_p64_p8() { - let a: i8x8 = i8x8::new(0, 0, 0, 0, 0, 0, 0, 0); + unsafe fn test_vreinterpret_p64_s64() { + let a: i64x1 = i64x1::new(0); let e: i64x1 = i64x1::new(0); - let r: i64x1 = transmute(vreinterpret_p64_p8(transmute(a))); + let r: i64x1 = transmute(vreinterpret_p64_s64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpret_p64_s8() { - let a: i8x8 = i8x8::new(0, 0, 0, 0, 0, 0, 0, 0); + unsafe fn test_vreinterpret_p64_u64() { + let a: u64x1 = u64x1::new(0); let e: i64x1 = i64x1::new(0); - let r: i64x1 = transmute(vreinterpret_p64_s8(transmute(a))); + let r: i64x1 = transmute(vreinterpret_p64_u64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpret_p64_u8() { - let a: u8x8 = u8x8::new(0, 0, 0, 0, 0, 0, 0, 0); - let e: i64x1 = i64x1::new(0); - let r: i64x1 = transmute(vreinterpret_p64_u8(transmute(a))); + unsafe fn test_vreinterpretq_s64_p64() { + let a: i64x2 = i64x2::new(0, 1); + let e: i64x2 = i64x2::new(0, 1); + let r: i64x2 = transmute(vreinterpretq_s64_p64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpretq_p64_p8() { - let a: i8x16 = i8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0); - let e: i64x2 = i64x2::new(0, 1); - let r: i64x2 = transmute(vreinterpretq_p64_p8(transmute(a))); + unsafe fn test_vreinterpretq_u64_p64() { + let a: i64x2 = i64x2::new(0, 1); + let e: u64x2 = u64x2::new(0, 1); + let r: u64x2 = transmute(vreinterpretq_u64_p64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpretq_p64_s8() { - let a: i8x16 = i8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0); + unsafe fn test_vreinterpretq_p64_s64() { + let a: i64x2 = i64x2::new(0, 1); let e: i64x2 = i64x2::new(0, 1); - let r: i64x2 = transmute(vreinterpretq_p64_s8(transmute(a))); + let r: i64x2 = transmute(vreinterpretq_p64_s64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpretq_p64_u8() { - let a: u8x16 = u8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0); + unsafe fn test_vreinterpretq_p64_u64() { + let a: u64x2 = u64x2::new(0, 1); let e: i64x2 = i64x2::new(0, 1); - let r: i64x2 = transmute(vreinterpretq_p64_u8(transmute(a))); + let r: i64x2 = transmute(vreinterpretq_p64_u64(transmute(a))); assert_eq!(r, e); } @@ -16061,6 +22243,14 @@ mod test { assert_eq!(r, e); } + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_p128_f64() { + let a: f64x2 = f64x2::new(0., 0.); + let e: p128 = 0; + let r: p128 = transmute(vreinterpretq_p128_f64(transmute(a))); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vreinterpret_f64_s8() { let a: i8x8 = i8x8::new(0, 0, 0, 0, 0, 0, 0, 0); @@ -16253,6 +22443,14 @@ mod test { assert_eq!(r, e); } + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_f64_p128() { + let a: p128 = 0; + let e: f64x2 = f64x2::new(0., 0.); + let r: f64x2 = transmute(vreinterpretq_f64_p128(transmute(a))); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vreinterpret_f64_f32() { let a: f32x2 = f32x2::new(0., 0.); @@ -16391,6 +22589,66 @@ mod test { assert_eq!(r, e); } + #[simd_test(enable = "neon")] + unsafe fn test_vrsubhn_high_s16() { + let a: i8x8 = i8x8::new(1, 2, 0, 0, 0, 0, 0, 0); + let b: i16x8 = i16x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let c: i16x8 = i16x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let e: i8x16 = i8x16::new(1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + let r: i8x16 = transmute(vrsubhn_high_s16(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vrsubhn_high_s32() { + let a: i16x4 = i16x4::new(1, 2, 0, 0); + let b: i32x4 = i32x4::new(1, 2, 3, 4); + let c: i32x4 = i32x4::new(1, 2, 3, 4); + let e: i16x8 = i16x8::new(1, 2, 0, 0, 0, 0, 0, 0); + let r: i16x8 = transmute(vrsubhn_high_s32(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vrsubhn_high_s64() { + let a: i32x2 = i32x2::new(1, 2); + let b: i64x2 = i64x2::new(1, 2); + let c: i64x2 = i64x2::new(1, 2); + let e: i32x4 = i32x4::new(1, 2, 0, 0); + let r: i32x4 = transmute(vrsubhn_high_s64(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vrsubhn_high_u16() { + let a: u8x8 = u8x8::new(1, 2, 0, 0, 0, 0, 0, 0); + let b: u16x8 = u16x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let c: u16x8 = u16x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let e: u8x16 = u8x16::new(1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + let r: u8x16 = transmute(vrsubhn_high_u16(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vrsubhn_high_u32() { + let a: u16x4 = u16x4::new(1, 2, 0, 0); + let b: u32x4 = u32x4::new(1, 2, 3, 4); + let c: u32x4 = u32x4::new(1, 2, 3, 4); + let e: u16x8 = u16x8::new(1, 2, 0, 0, 0, 0, 0, 0); + let r: u16x8 = transmute(vrsubhn_high_u32(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vrsubhn_high_u64() { + let a: u32x2 = u32x2::new(1, 2); + let b: u64x2 = u64x2::new(1, 2); + let c: u64x2 = u64x2::new(1, 2); + let e: u32x4 = u32x4::new(1, 2, 0, 0); + let r: u32x4 = transmute(vrsubhn_high_u64(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vset_lane_f64() { let a: f64 = 1.; @@ -16529,6 +22787,166 @@ mod test { assert_eq!(r, e); } + #[simd_test(enable = "neon,sm4")] + unsafe fn test_vsm3partw1q_u32() { + let a: u32x4 = u32x4::new(1, 2, 3, 4); + let b: u32x4 = u32x4::new(1, 2, 3, 4); + let c: u32x4 = u32x4::new(1, 2, 3, 4); + let e: u32x4 = u32x4::new(2147549312, 3221323968, 131329, 2684362752); + let r: u32x4 = transmute(vsm3partw1q_u32(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon,sm4")] + unsafe fn test_vsm3partw2q_u32() { + let a: u32x4 = u32x4::new(1, 2, 3, 4); + let b: u32x4 = u32x4::new(1, 2, 3, 4); + let c: u32x4 = u32x4::new(1, 2, 3, 4); + let e: u32x4 = u32x4::new(128, 256, 384, 1077977696); + let r: u32x4 = transmute(vsm3partw2q_u32(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon,sm4")] + unsafe fn test_vsm3ss1q_u32() { + let a: u32x4 = u32x4::new(1, 2, 3, 4); + let b: u32x4 = u32x4::new(1, 2, 3, 4); + let c: u32x4 = u32x4::new(1, 2, 3, 4); + let e: u32x4 = u32x4::new(0, 0, 0, 2098176); + let r: u32x4 = transmute(vsm3ss1q_u32(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon,sm4")] + unsafe fn test_vsm4ekeyq_u32() { + let a: u32x4 = u32x4::new(1, 2, 3, 4); + let b: u32x4 = u32x4::new(1, 2, 3, 4); + let e: u32x4 = u32x4::new(1784948604, 136020997, 2940231695, 3789947679); + let r: u32x4 = transmute(vsm4ekeyq_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon,sm4")] + unsafe fn test_vsm4eq_u32() { + let a: u32x4 = u32x4::new(1, 2, 3, 4); + let b: u32x4 = u32x4::new(1, 2, 3, 4); + let e: u32x4 = u32x4::new(1093874472, 3616769504, 3878330411, 2765298765); + let r: u32x4 = transmute(vsm4eq_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon,sha3")] + unsafe fn test_vrax1q_u64() { + let a: u64x2 = u64x2::new(1, 2); + let b: u64x2 = u64x2::new(3, 4); + let e: u64x2 = u64x2::new(7, 10); + let r: u64x2 = transmute(vrax1q_u64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon,sha3")] + unsafe fn test_vsha512hq_u64() { + let a: u64x2 = u64x2::new(1, 2); + let b: u64x2 = u64x2::new(3, 4); + let c: u64x2 = u64x2::new(5, 6); + let e: u64x2 = u64x2::new(11189044327219203, 7177611956453380); + let r: u64x2 = transmute(vsha512hq_u64(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon,sha3")] + unsafe fn test_vsha512h2q_u64() { + let a: u64x2 = u64x2::new(1, 2); + let b: u64x2 = u64x2::new(3, 4); + let c: u64x2 = u64x2::new(5, 6); + let e: u64x2 = u64x2::new(5770237651009406214, 349133864969); + let r: u64x2 = transmute(vsha512h2q_u64(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon,sha3")] + unsafe fn test_vsha512su0q_u64() { + let a: u64x2 = u64x2::new(1, 2); + let b: u64x2 = u64x2::new(3, 4); + let e: u64x2 = u64x2::new(144115188075855874, 9439544818968559619); + let r: u64x2 = transmute(vsha512su0q_u64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon,sha3")] + unsafe fn test_vsha512su1q_u64() { + let a: u64x2 = u64x2::new(1, 2); + let b: u64x2 = u64x2::new(3, 4); + let c: u64x2 = u64x2::new(5, 6); + let e: u64x2 = u64x2::new(105553116266526, 140737488355368); + let r: u64x2 = transmute(vsha512su1q_u64(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon,frintts")] + unsafe fn test_vrnd32x_f32() { + let a: f32x2 = f32x2::new(1.1, 1.9); + let e: f32x2 = f32x2::new(1.0, 2.0); + let r: f32x2 = transmute(vrnd32x_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon,frintts")] + unsafe fn test_vrnd32xq_f32() { + let a: f32x4 = f32x4::new(1.1, 1.9, -1.7, -2.3); + let e: f32x4 = f32x4::new(1.0, 2.0, -2.0, -2.0); + let r: f32x4 = transmute(vrnd32xq_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon,frintts")] + unsafe fn test_vrnd32z_f32() { + let a: f32x2 = f32x2::new(1.1, 1.9); + let e: f32x2 = f32x2::new(1.0, 1.0); + let r: f32x2 = transmute(vrnd32z_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon,frintts")] + unsafe fn test_vrnd32zq_f32() { + let a: f32x4 = f32x4::new(1.1, 1.9, -1.7, -2.3); + let e: f32x4 = f32x4::new(1.0, 1.0, -1.0, -2.0); + let r: f32x4 = transmute(vrnd32zq_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon,frintts")] + unsafe fn test_vrnd64x_f32() { + let a: f32x2 = f32x2::new(1.1, 1.9); + let e: f32x2 = f32x2::new(1.0, 2.0); + let r: f32x2 = transmute(vrnd64x_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon,frintts")] + unsafe fn test_vrnd64xq_f32() { + let a: f32x4 = f32x4::new(1.1, 1.9, -1.7, -2.3); + let e: f32x4 = f32x4::new(1.0, 2.0, -2.0, -2.0); + let r: f32x4 = transmute(vrnd64xq_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon,frintts")] + unsafe fn test_vrnd64z_f32() { + let a: f32x2 = f32x2::new(1.1, 1.9); + let e: f32x2 = f32x2::new(1.0, 1.0); + let r: f32x2 = transmute(vrnd64z_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon,frintts")] + unsafe fn test_vrnd64zq_f32() { + let a: f32x4 = f32x4::new(1.1, 1.9, -1.7, -2.3); + let e: f32x4 = f32x4::new(1.0, 1.0, -1.0, -2.0); + let r: f32x4 = transmute(vrnd64zq_f32(transmute(a))); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vtrn1_s8() { let a: i8x8 = i8x8::new(0, 2, 4, 6, 8, 10, 12, 14); @@ -17792,4 +24210,72 @@ mod test { let r: i64x2 = transmute(vqabsq_s64(transmute(a))); assert_eq!(r, e); } + + #[simd_test(enable = "neon")] + unsafe fn test_vqabsb_s8() { + let a: i8 = -7; + let e: i8 = 7; + let r: i8 = transmute(vqabsb_s8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqabsh_s16() { + let a: i16 = -7; + let e: i16 = 7; + let r: i16 = transmute(vqabsh_s16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqabss_s32() { + let a: i32 = -7; + let e: i32 = 7; + let r: i32 = transmute(vqabss_s32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqabsd_s64() { + let a: i64 = -7; + let e: i64 = 7; + let r: i64 = transmute(vqabsd_s64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vslid_n_s64() { + let a: i64 = 333; + let b: i64 = 2042; + let e: i64 = 8169; + let r: i64 = transmute(vslid_n_s64::<2>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vslid_n_u64() { + let a: u64 = 333; + let b: u64 = 2042; + let e: u64 = 8169; + let r: u64 = transmute(vslid_n_u64::<2>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vsrid_n_s64() { + let a: i64 = 333; + let b: i64 = 2042; + let e: i64 = 510; + let r: i64 = transmute(vsrid_n_s64::<2>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vsrid_n_u64() { + let a: u64 = 333; + let b: u64 = 2042; + let e: u64 = 510; + let r: u64 = transmute(vsrid_n_u64::<2>(transmute(a), transmute(b))); + assert_eq!(r, e); + } } diff --git a/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs b/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs index f40ed5c338..ff895f9875 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs @@ -26,13 +26,13 @@ types! { } /// ARM-specific type containing two `float64x1_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct float64x1x2_t(pub float64x1_t, pub float64x1_t); /// ARM-specific type containing three `float64x1_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct float64x1x3_t(pub float64x1_t, pub float64x1_t, pub float64x1_t); /// ARM-specific type containing four `float64x1_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct float64x1x4_t( pub float64x1_t, pub float64x1_t, @@ -41,13 +41,13 @@ pub struct float64x1x4_t( ); /// ARM-specific type containing two `float64x2_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct float64x2x2_t(pub float64x2_t, pub float64x2_t); /// ARM-specific type containing three `float64x2_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct float64x2x3_t(pub float64x2_t, pub float64x2_t, pub float64x2_t); /// ARM-specific type containing four `float64x2_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct float64x2x4_t( pub float64x2_t, pub float64x2_t, @@ -103,6 +103,8 @@ extern "unadjusted" { fn vpaddq_s16_(a: int16x8_t, b: int16x8_t) -> int16x8_t; #[link_name = "llvm.aarch64.neon.addp.v4i32"] fn vpaddq_s32_(a: int32x4_t, b: int32x4_t) -> int32x4_t; + #[link_name = "llvm.aarch64.neon.addp.v2i64"] + fn vpaddq_s64_(a: int64x2_t, b: int64x2_t) -> int64x2_t; #[link_name = "llvm.aarch64.neon.addp.v16i8"] fn vpaddq_s8_(a: int8x16_t, b: int8x16_t) -> int8x16_t; @@ -678,7 +680,7 @@ pub unsafe fn vld1_dup_f64(ptr: *const f64) -> float64x1_t { /// Load multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(ldr))] +#[cfg_attr(test, assert_instr(ld1r))] pub unsafe fn vld1q_dup_f64(ptr: *const f64) -> float64x2_t { let x = vld1q_lane_f64::<0>(ptr, transmute(f64x2::splat(0.))); simd_shuffle2!(x, x, [0, 0]) @@ -698,7 +700,7 @@ pub unsafe fn vld1_lane_f64(ptr: *const f64, src: float64x1_t) #[inline] #[target_feature(enable = "neon")] #[rustc_legacy_const_generics(2)] -#[cfg_attr(test, assert_instr(ldr, LANE = 1))] +#[cfg_attr(test, assert_instr(ld1, LANE = 1))] pub unsafe fn vld1q_lane_f64(ptr: *const f64, src: float64x2_t) -> float64x2_t { static_assert_imm1!(LANE); simd_insert(src, LANE as u32, *ptr) @@ -886,7 +888,7 @@ pub unsafe fn vst1q_p16(ptr: *mut p16, a: poly16x8_t) { // Store multiple single-element structures from one, two, three, or four registers. #[inline] -#[target_feature(enable = "neon")] +#[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] pub unsafe fn vst1_p64(ptr: *mut p64, a: poly64x1_t) { @@ -895,7 +897,7 @@ pub unsafe fn vst1_p64(ptr: *mut p64, a: poly64x1_t) { // Store multiple single-element structures from one, two, three, or four registers. #[inline] -#[target_feature(enable = "neon")] +#[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] pub unsafe fn vst1q_p64(ptr: *mut p64, a: poly64x2_t) { @@ -1137,6 +1139,20 @@ pub unsafe fn vpaddq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(addp))] +pub unsafe fn vpaddq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { + vpaddq_s64_(a, b) +} +/// Add pairwise +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(addp))] +pub unsafe fn vpaddq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { + transmute(vpaddq_s64_(transmute(a), transmute(b))) +} +/// Add pairwise +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(addp))] pub unsafe fn vpaddq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { vpaddq_s8_(a, b) } @@ -2772,7 +2788,8 @@ pub unsafe fn vshld_n_u64(a: u64) -> u64 { #[rustc_legacy_const_generics(1)] pub unsafe fn vshrd_n_s64(a: i64) -> i64 { static_assert!(N : i32 where N >= 1 && N <= 64); - a >> N + let n: i32 = if N == 64 { 63 } else { N }; + a >> n } /// Unsigned shift right @@ -2782,7 +2799,12 @@ pub unsafe fn vshrd_n_s64(a: i64) -> i64 { #[rustc_legacy_const_generics(1)] pub unsafe fn vshrd_n_u64(a: u64) -> u64 { static_assert!(N : i32 where N >= 1 && N <= 64); - a >> N + let n: i32 = if N == 64 { + return 0; + } else { + N + }; + a >> n } /// Signed shift right and accumulate @@ -2792,7 +2814,7 @@ pub unsafe fn vshrd_n_u64(a: u64) -> u64 { #[rustc_legacy_const_generics(2)] pub unsafe fn vsrad_n_s64(a: i64, b: i64) -> i64 { static_assert!(N : i32 where N >= 1 && N <= 64); - a + (b >> N) + a + vshrd_n_s64::(b) } /// Unsigned shift right and accumulate @@ -2802,7 +2824,7 @@ pub unsafe fn vsrad_n_s64(a: i64, b: i64) -> i64 { #[rustc_legacy_const_generics(2)] pub unsafe fn vsrad_n_u64(a: u64, b: u64) -> u64 { static_assert!(N : i32 where N >= 1 && N <= 64); - a + (b >> N) + a + vshrd_n_u64::(b) } /// Shift Left and Insert (immediate) @@ -2985,7 +3007,24 @@ pub unsafe fn vsliq_n_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x static_assert_imm4!(N); transmute(vsliq_n_s16_(transmute(a), transmute(b), N)) } - +/// Shift Left and Insert (immediate) +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(test, assert_instr(sli, N = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsli_n_p64(a: poly64x1_t, b: poly64x1_t) -> poly64x1_t { + static_assert!(N: i32 where N >= 0 && N <= 63); + transmute(vsli_n_s64_(transmute(a), transmute(b), N)) +} +/// Shift Left and Insert (immediate) +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(test, assert_instr(sli, N = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsliq_n_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { + static_assert!(N: i32 where N >= 0 && N <= 63); + transmute(vsliq_n_s64_(transmute(a), transmute(b), N)) +} /// Shift Right and Insert (immediate) #[inline] #[target_feature(enable = "neon")] @@ -3166,6 +3205,115 @@ pub unsafe fn vsriq_n_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x static_assert!(N: i32 where N >= 1 && N <= 16); transmute(vsriq_n_s16_(transmute(a), transmute(b), N)) } +/// Shift Right and Insert (immediate) +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(test, assert_instr(sri, N = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsri_n_p64(a: poly64x1_t, b: poly64x1_t) -> poly64x1_t { + static_assert!(N: i32 where N >= 1 && N <= 64); + transmute(vsri_n_s64_(transmute(a), transmute(b), N)) +} +/// Shift Right and Insert (immediate) +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(test, assert_instr(sri, N = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsriq_n_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { + static_assert!(N: i32 where N >= 1 && N <= 64); + transmute(vsriq_n_s64_(transmute(a), transmute(b), N)) +} + +/// SM3TT1A +#[inline] +#[target_feature(enable = "neon,sm4")] +#[cfg_attr(test, assert_instr(sm3tt1a, IMM2 = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vsm3tt1aq_u32( + a: uint32x4_t, + b: uint32x4_t, + c: uint32x4_t, +) -> uint32x4_t { + static_assert_imm2!(IMM2); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.sm3tt1a")] + fn vsm3tt1aq_u32_(a: uint32x4_t, b: uint32x4_t, c: uint32x4_t, imm2: i64) -> uint32x4_t; + } + vsm3tt1aq_u32_(a, b, c, IMM2 as i64) +} + +/// SM3TT1B +#[inline] +#[target_feature(enable = "neon,sm4")] +#[cfg_attr(test, assert_instr(sm3tt1b, IMM2 = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vsm3tt1bq_u32( + a: uint32x4_t, + b: uint32x4_t, + c: uint32x4_t, +) -> uint32x4_t { + static_assert_imm2!(IMM2); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.sm3tt1b")] + fn vsm3tt1bq_u32_(a: uint32x4_t, b: uint32x4_t, c: uint32x4_t, imm2: i64) -> uint32x4_t; + } + vsm3tt1bq_u32_(a, b, c, IMM2 as i64) +} + +/// SM3TT2A +#[inline] +#[target_feature(enable = "neon,sm4")] +#[cfg_attr(test, assert_instr(sm3tt2a, IMM2 = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vsm3tt2aq_u32( + a: uint32x4_t, + b: uint32x4_t, + c: uint32x4_t, +) -> uint32x4_t { + static_assert_imm2!(IMM2); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.sm3tt2a")] + fn vsm3tt2aq_u32_(a: uint32x4_t, b: uint32x4_t, c: uint32x4_t, imm2: i64) -> uint32x4_t; + } + vsm3tt2aq_u32_(a, b, c, IMM2 as i64) +} + +/// SM3TT2B +#[inline] +#[target_feature(enable = "neon,sm4")] +#[cfg_attr(test, assert_instr(sm3tt2b, IMM2 = 0))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vsm3tt2bq_u32( + a: uint32x4_t, + b: uint32x4_t, + c: uint32x4_t, +) -> uint32x4_t { + static_assert_imm2!(IMM2); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.sm3tt2b")] + fn vsm3tt2bq_u32_(a: uint32x4_t, b: uint32x4_t, c: uint32x4_t, imm2: i64) -> uint32x4_t; + } + vsm3tt2bq_u32_(a, b, c, IMM2 as i64) +} + +/// Exclusive OR and rotate +#[inline] +#[target_feature(enable = "neon,sha3")] +#[cfg_attr(test, assert_instr(xar, IMM6 = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vxarq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { + static_assert_imm6!(IMM6); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.xar")] + fn vxarq_u64_(a: uint64x2_t, b: uint64x2_t, n: i64) -> uint64x2_t; + } + vxarq_u64_(a, b, IMM6 as i64) +} #[cfg(test)] mod tests { @@ -3356,6 +3504,14 @@ mod tests { assert_eq!(r, e); } #[simd_test(enable = "neon")] + unsafe fn test_vpaddq_s64() { + let a = i64x2::new(1, 2); + let b = i64x2::new(0, -1); + let r: i64x2 = transmute(vpaddq_s64(transmute(a), transmute(b))); + let e = i64x2::new(3, -1); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vpaddq_s8() { let a = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); let b = i8x16::new( @@ -3384,6 +3540,14 @@ mod tests { assert_eq!(r, e); } #[simd_test(enable = "neon")] + unsafe fn test_vpaddq_u64() { + let a = u64x2::new(0, 1); + let b = u64x2::new(17, 18); + let r: u64x2 = transmute(vpaddq_u64(transmute(a), transmute(b))); + let e = u64x2::new(1, 35); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vpaddq_u8() { let a = i8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); let b = i8x16::new( @@ -4803,29 +4967,6 @@ mod tests { assert_eq!(r, e) } - #[simd_test(enable = "neon")] - unsafe fn test_vst1_p64() { - let mut vals = [0_u64; 2]; - let a = u64x1::new(1); - - vst1_p64(vals[1..].as_mut_ptr(), transmute(a)); - - assert_eq!(vals[0], 0); - assert_eq!(vals[1], 1); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vst1q_p64() { - let mut vals = [0_u64; 3]; - let a = u64x2::new(1, 2); - - vst1q_p64(vals[1..].as_mut_ptr(), transmute(a)); - - assert_eq!(vals[0], 0); - assert_eq!(vals[1], 1); - assert_eq!(vals[2], 2); - } - #[simd_test(enable = "neon")] unsafe fn test_vst1_f64() { let mut vals = [0_f64; 2]; @@ -4848,6 +4989,55 @@ mod tests { assert_eq!(vals[1], 1.); assert_eq!(vals[2], 2.); } + + #[simd_test(enable = "neon,sm4")] + unsafe fn test_vsm3tt1aq_u32() { + let a: u32x4 = u32x4::new(1, 2, 3, 4); + let b: u32x4 = u32x4::new(1, 2, 3, 4); + let c: u32x4 = u32x4::new(1, 2, 3, 4); + let e: u32x4 = u32x4::new(2, 1536, 4, 16395); + let r: u32x4 = transmute(vsm3tt1aq_u32::<0>(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon,sm4")] + unsafe fn test_vsm3tt1bq_u32() { + let a: u32x4 = u32x4::new(1, 2, 3, 4); + let b: u32x4 = u32x4::new(1, 2, 3, 4); + let c: u32x4 = u32x4::new(1, 2, 3, 4); + let e: u32x4 = u32x4::new(2, 1536, 4, 16392); + let r: u32x4 = transmute(vsm3tt1bq_u32::<0>(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon,sm4")] + unsafe fn test_vsm3tt2aq_u32() { + let a: u32x4 = u32x4::new(1, 2, 3, 4); + let b: u32x4 = u32x4::new(1, 2, 3, 4); + let c: u32x4 = u32x4::new(1, 2, 3, 4); + let e: u32x4 = u32x4::new(2, 1572864, 4, 1447435); + let r: u32x4 = transmute(vsm3tt2aq_u32::<0>(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon,sm4")] + unsafe fn test_vsm3tt2bq_u32() { + let a: u32x4 = u32x4::new(1, 2, 3, 4); + let b: u32x4 = u32x4::new(1, 2, 3, 4); + let c: u32x4 = u32x4::new(1, 2, 3, 4); + let e: u32x4 = u32x4::new(2, 1572864, 4, 1052680); + let r: u32x4 = transmute(vsm3tt2bq_u32::<0>(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon,sha3")] + unsafe fn test_vxarq_u64() { + let a: u64x2 = u64x2::new(1, 2); + let b: u64x2 = u64x2::new(3, 4); + let e: u64x2 = u64x2::new(2, 6); + let r: u64x2 = transmute(vxarq_u64::<0>(transmute(a), transmute(b))); + assert_eq!(r, e); + } } #[cfg(test)] diff --git a/library/stdarch/crates/core_arch/src/arm/neon.rs b/library/stdarch/crates/core_arch/src/arm/neon.rs index ebcff041a6..a0ad92c33a 100644 --- a/library/stdarch/crates/core_arch/src/arm/neon.rs +++ b/library/stdarch/crates/core_arch/src/arm/neon.rs @@ -480,6 +480,22 @@ pub unsafe fn vst1q_p16(ptr: *mut p16, a: poly16x8_t) { vst1q_v8i16(ptr as *const i8, transmute(a), align_of::() as i32) } +/// Store multiple single-element structures from one, two, three, or four registers. +#[inline] +#[target_feature(enable = "neon,aes,v8")] +#[cfg_attr(test, assert_instr("vst1.64"))] +pub unsafe fn vst1_p64(ptr: *mut p64, a: poly64x1_t) { + vst1_v1i64(ptr as *const i8, transmute(a), align_of::() as i32) +} + +/// Store multiple single-element structures from one, two, three, or four registers. +#[inline] +#[target_feature(enable = "neon,aes,v8")] +#[cfg_attr(test, assert_instr("vst1.64"))] +pub unsafe fn vst1q_p64(ptr: *mut p64, a: poly64x2_t) { + vst1q_v2i64(ptr as *const i8, transmute(a), align_of::() as i32) +} + // Store multiple single-element structures from one, two, three, or four registers. #[inline] #[target_feature(enable = "neon,v7")] @@ -1031,7 +1047,32 @@ pub unsafe fn vsliq_n_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x int16x8_t(n, n, n, n, n, n, n, n), )) } - +/// Shift Left and Insert (immediate) +#[inline] +#[target_feature(enable = "neon,v7,aes")] +#[cfg_attr(test, assert_instr("vsli.64", N = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsli_n_p64(a: poly64x1_t, b: poly64x1_t) -> poly64x1_t { + static_assert!(N : i32 where 0 <= N && N <= 63); + transmute(vshiftins_v1i64( + transmute(a), + transmute(b), + int64x1_t(N as i64), + )) +} +/// Shift Left and Insert (immediate) +#[inline] +#[target_feature(enable = "neon,v7,aes")] +#[cfg_attr(test, assert_instr("vsli.64", N = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsliq_n_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { + static_assert!(N : i32 where 0 <= N && N <= 63); + transmute(vshiftins_v2i64( + transmute(a), + transmute(b), + int64x2_t(N as i64, N as i64), + )) +} /// Shift Right and Insert (immediate) #[inline] #[target_feature(enable = "neon,v7")] @@ -1276,6 +1317,32 @@ pub unsafe fn vsriq_n_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x int16x8_t(n, n, n, n, n, n, n, n), )) } +/// Shift Right and Insert (immediate) +#[inline] +#[target_feature(enable = "neon,v7,aes")] +#[cfg_attr(test, assert_instr("vsri.64", N = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsri_n_p64(a: poly64x1_t, b: poly64x1_t) -> poly64x1_t { + static_assert!(N : i32 where 1 <= N && N <= 64); + transmute(vshiftins_v1i64( + transmute(a), + transmute(b), + int64x1_t(-N as i64), + )) +} +/// Shift Right and Insert (immediate) +#[inline] +#[target_feature(enable = "neon,v7,aes")] +#[cfg_attr(test, assert_instr("vsri.64", N = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsriq_n_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { + static_assert!(N : i32 where 1 <= N && N <= 64); + transmute(vshiftins_v2i64( + transmute(a), + transmute(b), + int64x2_t(-N as i64, -N as i64), + )) +} #[cfg(test)] mod tests { diff --git a/library/stdarch/crates/core_arch/src/arm_shared/crypto.rs b/library/stdarch/crates/core_arch/src/arm_shared/crypto.rs index 56b99088bf..3e9515e59e 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/crypto.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/crypto.rs @@ -51,8 +51,6 @@ extern "unadjusted" { #[cfg(test)] use stdarch_test::assert_instr; -// TODO: Use AES for ARM when the minimum LLVM version includes b8baa2a9132498ea286dbb0d03f005760ecc6fdb - /// AES single round encryption. #[inline] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "aes"))] diff --git a/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs b/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs index 69d8da1795..2f93c65262 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs @@ -1780,7 +1780,67 @@ pub unsafe fn vclsq_s32(a: int32x4_t) -> int32x4_t { vclsq_s32_(a) } -/// Signed count leading sign bits +/// Count leading sign bits +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcls))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))] +pub unsafe fn vcls_u8(a: uint8x8_t) -> uint8x8_t { + transmute(vcls_s8(transmute(a))) +} + +/// Count leading sign bits +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcls))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))] +pub unsafe fn vclsq_u8(a: uint8x16_t) -> uint8x16_t { + transmute(vclsq_s8(transmute(a))) +} + +/// Count leading sign bits +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcls))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))] +pub unsafe fn vcls_u16(a: uint16x4_t) -> uint16x4_t { + transmute(vcls_s16(transmute(a))) +} + +/// Count leading sign bits +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcls))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))] +pub unsafe fn vclsq_u16(a: uint16x8_t) -> uint16x8_t { + transmute(vclsq_s16(transmute(a))) +} + +/// Count leading sign bits +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcls))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))] +pub unsafe fn vcls_u32(a: uint32x2_t) -> uint32x2_t { + transmute(vcls_s32(transmute(a))) +} + +/// Count leading sign bits +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcls))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))] +pub unsafe fn vclsq_u32(a: uint32x4_t) -> uint32x4_t { + transmute(vclsq_s32(transmute(a))) +} + +/// Count leading zero bits #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] @@ -1790,7 +1850,7 @@ pub unsafe fn vclz_s8(a: int8x8_t) -> int8x8_t { vclz_s8_(a) } -/// Signed count leading sign bits +/// Count leading zero bits #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] @@ -1800,7 +1860,7 @@ pub unsafe fn vclzq_s8(a: int8x16_t) -> int8x16_t { vclzq_s8_(a) } -/// Signed count leading sign bits +/// Count leading zero bits #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] @@ -1810,7 +1870,7 @@ pub unsafe fn vclz_s16(a: int16x4_t) -> int16x4_t { vclz_s16_(a) } -/// Signed count leading sign bits +/// Count leading zero bits #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] @@ -1820,7 +1880,7 @@ pub unsafe fn vclzq_s16(a: int16x8_t) -> int16x8_t { vclzq_s16_(a) } -/// Signed count leading sign bits +/// Count leading zero bits #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] @@ -1830,7 +1890,7 @@ pub unsafe fn vclz_s32(a: int32x2_t) -> int32x2_t { vclz_s32_(a) } -/// Signed count leading sign bits +/// Count leading zero bits #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] @@ -1840,7 +1900,7 @@ pub unsafe fn vclzq_s32(a: int32x4_t) -> int32x4_t { vclzq_s32_(a) } -/// Unsigned count leading sign bits +/// Count leading zero bits #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] @@ -1850,7 +1910,7 @@ pub unsafe fn vclz_u8(a: uint8x8_t) -> uint8x8_t { transmute(vclz_s8_(transmute(a))) } -/// Unsigned count leading sign bits +/// Count leading zero bits #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] @@ -1860,7 +1920,7 @@ pub unsafe fn vclzq_u8(a: uint8x16_t) -> uint8x16_t { transmute(vclzq_s8_(transmute(a))) } -/// Unsigned count leading sign bits +/// Count leading zero bits #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] @@ -1870,7 +1930,7 @@ pub unsafe fn vclz_u16(a: uint16x4_t) -> uint16x4_t { transmute(vclz_s16_(transmute(a))) } -/// Unsigned count leading sign bits +/// Count leading zero bits #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] @@ -1880,7 +1940,7 @@ pub unsafe fn vclzq_u16(a: uint16x8_t) -> uint16x8_t { transmute(vclzq_s16_(transmute(a))) } -/// Unsigned count leading sign bits +/// Count leading zero bits #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] @@ -1890,7 +1950,7 @@ pub unsafe fn vclz_u32(a: uint32x2_t) -> uint32x2_t { transmute(vclz_s32_(transmute(a))) } -/// Unsigned count leading sign bits +/// Count leading zero bits #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] @@ -2014,6 +2074,16 @@ pub unsafe fn vcreate_s8(a: u64) -> int8x8_t { transmute(a) } +/// Insert vector element from another vector element +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vcreate_s16(a: u64) -> int16x4_t { + transmute(a) +} + /// Insert vector element from another vector element #[inline] #[target_feature(enable = "neon")] @@ -2044,6 +2114,16 @@ pub unsafe fn vcreate_u8(a: u64) -> uint8x8_t { transmute(a) } +/// Insert vector element from another vector element +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vcreate_u16(a: u64) -> uint16x4_t { + transmute(a) +} + /// Insert vector element from another vector element #[inline] #[target_feature(enable = "neon")] @@ -6616,7 +6696,7 @@ pub unsafe fn vld1_p64_x2(a: *const p64) -> poly64x1x2_t { #[inline] #[target_feature(enable = "neon,aes")] #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(ldr))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] pub unsafe fn vld1_p64_x3(a: *const p64) -> poly64x1x3_t { transmute(vld1_s64_x3(transmute(a))) @@ -6626,7 +6706,7 @@ pub unsafe fn vld1_p64_x3(a: *const p64) -> poly64x1x3_t { #[inline] #[target_feature(enable = "neon,aes")] #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(ldr))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] pub unsafe fn vld1_p64_x4(a: *const p64) -> poly64x1x4_t { transmute(vld1_s64_x4(transmute(a))) @@ -6636,7 +6716,7 @@ pub unsafe fn vld1_p64_x4(a: *const p64) -> poly64x1x4_t { #[inline] #[target_feature(enable = "neon,aes")] #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(ldr))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] pub unsafe fn vld1q_p64_x2(a: *const p64) -> poly64x2x2_t { transmute(vld1q_s64_x2(transmute(a))) @@ -6646,7 +6726,7 @@ pub unsafe fn vld1q_p64_x2(a: *const p64) -> poly64x2x2_t { #[inline] #[target_feature(enable = "neon,aes")] #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(ldr))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] pub unsafe fn vld1q_p64_x3(a: *const p64) -> poly64x2x3_t { transmute(vld1q_s64_x3(transmute(a))) @@ -6656,7 +6736,7 @@ pub unsafe fn vld1q_p64_x3(a: *const p64) -> poly64x2x3_t { #[inline] #[target_feature(enable = "neon,aes")] #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(ldr))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] pub unsafe fn vld1q_p64_x4(a: *const p64) -> poly64x2x4_t { transmute(vld1q_s64_x4(transmute(a))) @@ -6758,15476 +6838,25495 @@ pub unsafe fn vld1q_f32_x4(a: *const f32) -> float32x4x4_t { vld1q_f32_x4_(a) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -pub unsafe fn vst1_s8_x2(a: *mut i8, b: int8x8x2_t) { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +pub unsafe fn vld2_s8(a: *const i8) -> int8x8x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x2.p0i8.v8i8")] - fn vst1_s8_x2_(ptr: *mut i8, a: int8x8_t, b: int8x8_t); + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2.v8i8.p0i8")] + fn vld2_s8_(ptr: *const i8, size: i32) -> int8x8x2_t; } -vst1_s8_x2_(a, b.0, b.1) +vld2_s8_(a as *const i8, 1) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_s8_x2(a: *mut i8, b: int8x8x2_t) { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +pub unsafe fn vld2_s8(a: *const i8) -> int8x8x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x2.v8i8.p0i8")] - fn vst1_s8_x2_(a: int8x8_t, b: int8x8_t, ptr: *mut i8); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2.v8i8.p0v8i8")] + fn vld2_s8_(ptr: *const int8x8_t) -> int8x8x2_t; } -vst1_s8_x2_(b.0, b.1, a) +vld2_s8_(a.cast()) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -pub unsafe fn vst1_s16_x2(a: *mut i16, b: int16x4x2_t) { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +pub unsafe fn vld2_s16(a: *const i16) -> int16x4x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x2.p0i16.v4i16")] - fn vst1_s16_x2_(ptr: *mut i16, a: int16x4_t, b: int16x4_t); + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2.v4i16.p0i8")] + fn vld2_s16_(ptr: *const i8, size: i32) -> int16x4x2_t; } -vst1_s16_x2_(a, b.0, b.1) +vld2_s16_(a as *const i8, 2) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_s16_x2(a: *mut i16, b: int16x4x2_t) { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +pub unsafe fn vld2_s16(a: *const i16) -> int16x4x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x2.v4i16.p0i16")] - fn vst1_s16_x2_(a: int16x4_t, b: int16x4_t, ptr: *mut i16); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2.v4i16.p0v4i16")] + fn vld2_s16_(ptr: *const int16x4_t) -> int16x4x2_t; } -vst1_s16_x2_(b.0, b.1, a) +vld2_s16_(a.cast()) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -pub unsafe fn vst1_s32_x2(a: *mut i32, b: int32x2x2_t) { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +pub unsafe fn vld2_s32(a: *const i32) -> int32x2x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x2.p0i32.v2i32")] - fn vst1_s32_x2_(ptr: *mut i32, a: int32x2_t, b: int32x2_t); + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2.v2i32.p0i8")] + fn vld2_s32_(ptr: *const i8, size: i32) -> int32x2x2_t; } -vst1_s32_x2_(a, b.0, b.1) +vld2_s32_(a as *const i8, 4) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_s32_x2(a: *mut i32, b: int32x2x2_t) { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +pub unsafe fn vld2_s32(a: *const i32) -> int32x2x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x2.v2i32.p0i32")] - fn vst1_s32_x2_(a: int32x2_t, b: int32x2_t, ptr: *mut i32); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2.v2i32.p0v2i32")] + fn vld2_s32_(ptr: *const int32x2_t) -> int32x2x2_t; } -vst1_s32_x2_(b.0, b.1, a) +vld2_s32_(a.cast()) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -pub unsafe fn vst1_s64_x2(a: *mut i64, b: int64x1x2_t) { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +pub unsafe fn vld2q_s8(a: *const i8) -> int8x16x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x2.p0i64.v1i64")] - fn vst1_s64_x2_(ptr: *mut i64, a: int64x1_t, b: int64x1_t); + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2.v16i8.p0i8")] + fn vld2q_s8_(ptr: *const i8, size: i32) -> int8x16x2_t; } -vst1_s64_x2_(a, b.0, b.1) +vld2q_s8_(a as *const i8, 1) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_s64_x2(a: *mut i64, b: int64x1x2_t) { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +pub unsafe fn vld2q_s8(a: *const i8) -> int8x16x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x2.v1i64.p0i64")] - fn vst1_s64_x2_(a: int64x1_t, b: int64x1_t, ptr: *mut i64); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2.v16i8.p0v16i8")] + fn vld2q_s8_(ptr: *const int8x16_t) -> int8x16x2_t; } -vst1_s64_x2_(b.0, b.1, a) +vld2q_s8_(a.cast()) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -pub unsafe fn vst1q_s8_x2(a: *mut i8, b: int8x16x2_t) { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +pub unsafe fn vld2q_s16(a: *const i16) -> int16x8x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x2.p0i8.v16i8")] - fn vst1q_s8_x2_(ptr: *mut i8, a: int8x16_t, b: int8x16_t); + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2.v8i16.p0i8")] + fn vld2q_s16_(ptr: *const i8, size: i32) -> int16x8x2_t; } -vst1q_s8_x2_(a, b.0, b.1) +vld2q_s16_(a as *const i8, 2) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_s8_x2(a: *mut i8, b: int8x16x2_t) { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +pub unsafe fn vld2q_s16(a: *const i16) -> int16x8x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x2.v16i8.p0i8")] - fn vst1q_s8_x2_(a: int8x16_t, b: int8x16_t, ptr: *mut i8); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2.v8i16.p0v8i16")] + fn vld2q_s16_(ptr: *const int16x8_t) -> int16x8x2_t; } -vst1q_s8_x2_(b.0, b.1, a) +vld2q_s16_(a.cast()) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -pub unsafe fn vst1q_s16_x2(a: *mut i16, b: int16x8x2_t) { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +pub unsafe fn vld2q_s32(a: *const i32) -> int32x4x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x2.p0i16.v8i16")] - fn vst1q_s16_x2_(ptr: *mut i16, a: int16x8_t, b: int16x8_t); + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2.v4i32.p0i8")] + fn vld2q_s32_(ptr: *const i8, size: i32) -> int32x4x2_t; } -vst1q_s16_x2_(a, b.0, b.1) +vld2q_s32_(a as *const i8, 4) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_s16_x2(a: *mut i16, b: int16x8x2_t) { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +pub unsafe fn vld2q_s32(a: *const i32) -> int32x4x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x2.v8i16.p0i16")] - fn vst1q_s16_x2_(a: int16x8_t, b: int16x8_t, ptr: *mut i16); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2.v4i32.p0v4i32")] + fn vld2q_s32_(ptr: *const int32x4_t) -> int32x4x2_t; } -vst1q_s16_x2_(b.0, b.1, a) +vld2q_s32_(a.cast()) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -pub unsafe fn vst1q_s32_x2(a: *mut i32, b: int32x4x2_t) { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +pub unsafe fn vld2_s64(a: *const i64) -> int64x1x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x2.p0i32.v4i32")] - fn vst1q_s32_x2_(ptr: *mut i32, a: int32x4_t, b: int32x4_t); + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2.v1i64.p0i8")] + fn vld2_s64_(ptr: *const i8, size: i32) -> int64x1x2_t; } -vst1q_s32_x2_(a, b.0, b.1) +vld2_s64_(a as *const i8, 8) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_s32_x2(a: *mut i32, b: int32x4x2_t) { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vld2_s64(a: *const i64) -> int64x1x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x2.v4i32.p0i32")] - fn vst1q_s32_x2_(a: int32x4_t, b: int32x4_t, ptr: *mut i32); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2.v1i64.p0v1i64")] + fn vld2_s64_(ptr: *const int64x1_t) -> int64x1x2_t; } -vst1q_s32_x2_(b.0, b.1, a) +vld2_s64_(a.cast()) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load multiple 2-element structures to two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +pub unsafe fn vld2_u8(a: *const u8) -> uint8x8x2_t { + transmute(vld2_s8(transmute(a))) +} + +/// Load multiple 2-element structures to two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +pub unsafe fn vld2_u16(a: *const u16) -> uint16x4x2_t { + transmute(vld2_s16(transmute(a))) +} + +/// Load multiple 2-element structures to two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +pub unsafe fn vld2_u32(a: *const u32) -> uint32x2x2_t { + transmute(vld2_s32(transmute(a))) +} + +/// Load multiple 2-element structures to two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +pub unsafe fn vld2q_u8(a: *const u8) -> uint8x16x2_t { + transmute(vld2q_s8(transmute(a))) +} + +/// Load multiple 2-element structures to two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +pub unsafe fn vld2q_u16(a: *const u16) -> uint16x8x2_t { + transmute(vld2q_s16(transmute(a))) +} + +/// Load multiple 2-element structures to two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +pub unsafe fn vld2q_u32(a: *const u32) -> uint32x4x2_t { + transmute(vld2q_s32(transmute(a))) +} + +/// Load multiple 2-element structures to two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +pub unsafe fn vld2_p8(a: *const p8) -> poly8x8x2_t { + transmute(vld2_s8(transmute(a))) +} + +/// Load multiple 2-element structures to two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +pub unsafe fn vld2_p16(a: *const p16) -> poly16x4x2_t { + transmute(vld2_s16(transmute(a))) +} + +/// Load multiple 2-element structures to two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +pub unsafe fn vld2q_p8(a: *const p8) -> poly8x16x2_t { + transmute(vld2q_s8(transmute(a))) +} + +/// Load multiple 2-element structures to two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +pub unsafe fn vld2q_p16(a: *const p16) -> poly16x8x2_t { + transmute(vld2q_s16(transmute(a))) +} + +/// Load multiple 2-element structures to two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vld2_u64(a: *const u64) -> uint64x1x2_t { + transmute(vld2_s64(transmute(a))) +} + +/// Load multiple 2-element structures to two registers +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vld2_p64(a: *const p64) -> poly64x1x2_t { + transmute(vld2_s64(transmute(a))) +} + +/// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -pub unsafe fn vst1q_s64_x2(a: *mut i64, b: int64x2x2_t) { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +pub unsafe fn vld2_f32(a: *const f32) -> float32x2x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x2.p0i64.v2i64")] - fn vst1q_s64_x2_(ptr: *mut i64, a: int64x2_t, b: int64x2_t); + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2.v2f32.p0i8")] + fn vld2_f32_(ptr: *const i8, size: i32) -> float32x2x2_t; } -vst1q_s64_x2_(a, b.0, b.1) +vld2_f32_(a as *const i8, 4) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_s64_x2(a: *mut i64, b: int64x2x2_t) { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +pub unsafe fn vld2_f32(a: *const f32) -> float32x2x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x2.v2i64.p0i64")] - fn vst1q_s64_x2_(a: int64x2_t, b: int64x2_t, ptr: *mut i64); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2.v2f32.p0v2f32")] + fn vld2_f32_(ptr: *const float32x2_t) -> float32x2x2_t; } -vst1q_s64_x2_(b.0, b.1, a) +vld2_f32_(a.cast()) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -pub unsafe fn vst1_s8_x3(a: *mut i8, b: int8x8x3_t) { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +pub unsafe fn vld2q_f32(a: *const f32) -> float32x4x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x3.p0i8.v8i8")] - fn vst1_s8_x3_(ptr: *mut i8, a: int8x8_t, b: int8x8_t, c: int8x8_t); + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2.v4f32.p0i8")] + fn vld2q_f32_(ptr: *const i8, size: i32) -> float32x4x2_t; } -vst1_s8_x3_(a, b.0, b.1, b.2) +vld2q_f32_(a as *const i8, 4) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_s8_x3(a: *mut i8, b: int8x8x3_t) { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +pub unsafe fn vld2q_f32(a: *const f32) -> float32x4x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x3.v8i8.p0i8")] - fn vst1_s8_x3_(a: int8x8_t, b: int8x8_t, c: int8x8_t, ptr: *mut i8); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2.v4f32.p0v4f32")] + fn vld2q_f32_(ptr: *const float32x4_t) -> float32x4x2_t; } -vst1_s8_x3_(b.0, b.1, b.2, a) +vld2q_f32_(a.cast()) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -pub unsafe fn vst1_s16_x3(a: *mut i16, b: int16x4x3_t) { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +pub unsafe fn vld2_dup_s8(a: *const i8) -> int8x8x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x3.p0i16.v4i16")] - fn vst1_s16_x3_(ptr: *mut i16, a: int16x4_t, b: int16x4_t, c: int16x4_t); + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2dup.v8i8.p0i8")] + fn vld2_dup_s8_(ptr: *const i8, size: i32) -> int8x8x2_t; } -vst1_s16_x3_(a, b.0, b.1, b.2) +vld2_dup_s8_(a as *const i8, 1) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_s16_x3(a: *mut i16, b: int16x4x3_t) { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +pub unsafe fn vld2_dup_s8(a: *const i8) -> int8x8x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x3.v4i16.p0i16")] - fn vst1_s16_x3_(a: int16x4_t, b: int16x4_t, c: int16x4_t, ptr: *mut i16); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2r.v8i8.p0i8")] + fn vld2_dup_s8_(ptr: *const i8) -> int8x8x2_t; } -vst1_s16_x3_(b.0, b.1, b.2, a) +vld2_dup_s8_(a.cast()) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -pub unsafe fn vst1_s32_x3(a: *mut i32, b: int32x2x3_t) { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +pub unsafe fn vld2_dup_s16(a: *const i16) -> int16x4x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x3.p0i32.v2i32")] - fn vst1_s32_x3_(ptr: *mut i32, a: int32x2_t, b: int32x2_t, c: int32x2_t); + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2dup.v4i16.p0i8")] + fn vld2_dup_s16_(ptr: *const i8, size: i32) -> int16x4x2_t; } -vst1_s32_x3_(a, b.0, b.1, b.2) +vld2_dup_s16_(a as *const i8, 2) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_s32_x3(a: *mut i32, b: int32x2x3_t) { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +pub unsafe fn vld2_dup_s16(a: *const i16) -> int16x4x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x3.v2i32.p0i32")] - fn vst1_s32_x3_(a: int32x2_t, b: int32x2_t, c: int32x2_t, ptr: *mut i32); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2r.v4i16.p0i16")] + fn vld2_dup_s16_(ptr: *const i16) -> int16x4x2_t; } -vst1_s32_x3_(b.0, b.1, b.2, a) +vld2_dup_s16_(a.cast()) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -pub unsafe fn vst1_s64_x3(a: *mut i64, b: int64x1x3_t) { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +pub unsafe fn vld2_dup_s32(a: *const i32) -> int32x2x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x3.p0i64.v1i64")] - fn vst1_s64_x3_(ptr: *mut i64, a: int64x1_t, b: int64x1_t, c: int64x1_t); + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2dup.v2i32.p0i8")] + fn vld2_dup_s32_(ptr: *const i8, size: i32) -> int32x2x2_t; } -vst1_s64_x3_(a, b.0, b.1, b.2) +vld2_dup_s32_(a as *const i8, 4) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_s64_x3(a: *mut i64, b: int64x1x3_t) { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +pub unsafe fn vld2_dup_s32(a: *const i32) -> int32x2x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x3.v1i64.p0i64")] - fn vst1_s64_x3_(a: int64x1_t, b: int64x1_t, c: int64x1_t, ptr: *mut i64); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2r.v2i32.p0i32")] + fn vld2_dup_s32_(ptr: *const i32) -> int32x2x2_t; } -vst1_s64_x3_(b.0, b.1, b.2, a) +vld2_dup_s32_(a.cast()) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -pub unsafe fn vst1q_s8_x3(a: *mut i8, b: int8x16x3_t) { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +pub unsafe fn vld2q_dup_s8(a: *const i8) -> int8x16x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x3.p0i8.v16i8")] - fn vst1q_s8_x3_(ptr: *mut i8, a: int8x16_t, b: int8x16_t, c: int8x16_t); + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2dup.v16i8.p0i8")] + fn vld2q_dup_s8_(ptr: *const i8, size: i32) -> int8x16x2_t; } -vst1q_s8_x3_(a, b.0, b.1, b.2) +vld2q_dup_s8_(a as *const i8, 1) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_s8_x3(a: *mut i8, b: int8x16x3_t) { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +pub unsafe fn vld2q_dup_s8(a: *const i8) -> int8x16x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x3.v16i8.p0i8")] - fn vst1q_s8_x3_(a: int8x16_t, b: int8x16_t, c: int8x16_t, ptr: *mut i8); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2r.v16i8.p0i8")] + fn vld2q_dup_s8_(ptr: *const i8) -> int8x16x2_t; } -vst1q_s8_x3_(b.0, b.1, b.2, a) +vld2q_dup_s8_(a.cast()) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -pub unsafe fn vst1q_s16_x3(a: *mut i16, b: int16x8x3_t) { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +pub unsafe fn vld2q_dup_s16(a: *const i16) -> int16x8x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x3.p0i16.v8i16")] - fn vst1q_s16_x3_(ptr: *mut i16, a: int16x8_t, b: int16x8_t, c: int16x8_t); + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2dup.v8i16.p0i8")] + fn vld2q_dup_s16_(ptr: *const i8, size: i32) -> int16x8x2_t; } -vst1q_s16_x3_(a, b.0, b.1, b.2) +vld2q_dup_s16_(a as *const i8, 2) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_s16_x3(a: *mut i16, b: int16x8x3_t) { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +pub unsafe fn vld2q_dup_s16(a: *const i16) -> int16x8x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x3.v8i16.p0i16")] - fn vst1q_s16_x3_(a: int16x8_t, b: int16x8_t, c: int16x8_t, ptr: *mut i16); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2r.v8i16.p0i16")] + fn vld2q_dup_s16_(ptr: *const i16) -> int16x8x2_t; } -vst1q_s16_x3_(b.0, b.1, b.2, a) +vld2q_dup_s16_(a.cast()) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -pub unsafe fn vst1q_s32_x3(a: *mut i32, b: int32x4x3_t) { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +pub unsafe fn vld2q_dup_s32(a: *const i32) -> int32x4x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x3.p0i32.v4i32")] - fn vst1q_s32_x3_(ptr: *mut i32, a: int32x4_t, b: int32x4_t, c: int32x4_t); + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2dup.v4i32.p0i8")] + fn vld2q_dup_s32_(ptr: *const i8, size: i32) -> int32x4x2_t; } -vst1q_s32_x3_(a, b.0, b.1, b.2) +vld2q_dup_s32_(a as *const i8, 4) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_s32_x3(a: *mut i32, b: int32x4x3_t) { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +pub unsafe fn vld2q_dup_s32(a: *const i32) -> int32x4x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x3.v4i32.p0i32")] - fn vst1q_s32_x3_(a: int32x4_t, b: int32x4_t, c: int32x4_t, ptr: *mut i32); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2r.v4i32.p0i32")] + fn vld2q_dup_s32_(ptr: *const i32) -> int32x4x2_t; } -vst1q_s32_x3_(b.0, b.1, b.2, a) +vld2q_dup_s32_(a.cast()) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -pub unsafe fn vst1q_s64_x3(a: *mut i64, b: int64x2x3_t) { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +pub unsafe fn vld2_dup_s64(a: *const i64) -> int64x1x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x3.p0i64.v2i64")] - fn vst1q_s64_x3_(ptr: *mut i64, a: int64x2_t, b: int64x2_t, c: int64x2_t); + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2dup.v1i64.p0i8")] + fn vld2_dup_s64_(ptr: *const i8, size: i32) -> int64x1x2_t; } -vst1q_s64_x3_(a, b.0, b.1, b.2) +vld2_dup_s64_(a as *const i8, 8) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_s64_x3(a: *mut i64, b: int64x2x3_t) { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +pub unsafe fn vld2_dup_s64(a: *const i64) -> int64x1x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x3.v2i64.p0i64")] - fn vst1q_s64_x3_(a: int64x2_t, b: int64x2_t, c: int64x2_t, ptr: *mut i64); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2r.v1i64.p0i64")] + fn vld2_dup_s64_(ptr: *const i64) -> int64x1x2_t; } -vst1q_s64_x3_(b.0, b.1, b.2, a) +vld2_dup_s64_(a.cast()) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load single 2-element structure and replicate to all lanes of two registers #[inline] -#[cfg(target_arch = "arm")] -#[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -pub unsafe fn vst1_s8_x4(a: *mut i8, b: int8x8x4_t) { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x4.p0i8.v8i8")] - fn vst1_s8_x4_(ptr: *mut i8, a: int8x8_t, b: int8x8_t, c: int8x8_t, d: int8x8_t); - } -vst1_s8_x4_(a, b.0, b.1, b.2, b.3) +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +pub unsafe fn vld2_dup_u8(a: *const u8) -> uint8x8x2_t { + transmute(vld2_dup_s8(transmute(a))) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load single 2-element structure and replicate to all lanes of two registers #[inline] -#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_s8_x4(a: *mut i8, b: int8x8x4_t) { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x4.v8i8.p0i8")] - fn vst1_s8_x4_(a: int8x8_t, b: int8x8_t, c: int8x8_t, d: int8x8_t, ptr: *mut i8); - } -vst1_s8_x4_(b.0, b.1, b.2, b.3, a) +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +pub unsafe fn vld2_dup_u16(a: *const u16) -> uint16x4x2_t { + transmute(vld2_dup_s16(transmute(a))) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load single 2-element structure and replicate to all lanes of two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +pub unsafe fn vld2_dup_u32(a: *const u32) -> uint32x2x2_t { + transmute(vld2_dup_s32(transmute(a))) +} + +/// Load single 2-element structure and replicate to all lanes of two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +pub unsafe fn vld2q_dup_u8(a: *const u8) -> uint8x16x2_t { + transmute(vld2q_dup_s8(transmute(a))) +} + +/// Load single 2-element structure and replicate to all lanes of two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +pub unsafe fn vld2q_dup_u16(a: *const u16) -> uint16x8x2_t { + transmute(vld2q_dup_s16(transmute(a))) +} + +/// Load single 2-element structure and replicate to all lanes of two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +pub unsafe fn vld2q_dup_u32(a: *const u32) -> uint32x4x2_t { + transmute(vld2q_dup_s32(transmute(a))) +} + +/// Load single 2-element structure and replicate to all lanes of two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +pub unsafe fn vld2_dup_p8(a: *const p8) -> poly8x8x2_t { + transmute(vld2_dup_s8(transmute(a))) +} + +/// Load single 2-element structure and replicate to all lanes of two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +pub unsafe fn vld2_dup_p16(a: *const p16) -> poly16x4x2_t { + transmute(vld2_dup_s16(transmute(a))) +} + +/// Load single 2-element structure and replicate to all lanes of two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +pub unsafe fn vld2q_dup_p8(a: *const p8) -> poly8x16x2_t { + transmute(vld2q_dup_s8(transmute(a))) +} + +/// Load single 2-element structure and replicate to all lanes of two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +pub unsafe fn vld2q_dup_p16(a: *const p16) -> poly16x8x2_t { + transmute(vld2q_dup_s16(transmute(a))) +} + +/// Load single 2-element structure and replicate to all lanes of two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +pub unsafe fn vld2_dup_u64(a: *const u64) -> uint64x1x2_t { + transmute(vld2_dup_s64(transmute(a))) +} + +/// Load single 2-element structure and replicate to all lanes of two registers +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +pub unsafe fn vld2_dup_p64(a: *const p64) -> poly64x1x2_t { + transmute(vld2_dup_s64(transmute(a))) +} + +/// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -pub unsafe fn vst1_s16_x4(a: *mut i16, b: int16x4x4_t) { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +pub unsafe fn vld2_dup_f32(a: *const f32) -> float32x2x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x4.p0i16.v4i16")] - fn vst1_s16_x4_(ptr: *mut i16, a: int16x4_t, b: int16x4_t, c: int16x4_t, d: int16x4_t); + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2dup.v2f32.p0i8")] + fn vld2_dup_f32_(ptr: *const i8, size: i32) -> float32x2x2_t; } -vst1_s16_x4_(a, b.0, b.1, b.2, b.3) +vld2_dup_f32_(a as *const i8, 4) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_s16_x4(a: *mut i16, b: int16x4x4_t) { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +pub unsafe fn vld2_dup_f32(a: *const f32) -> float32x2x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x4.v4i16.p0i16")] - fn vst1_s16_x4_(a: int16x4_t, b: int16x4_t, c: int16x4_t, d: int16x4_t, ptr: *mut i16); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2r.v2f32.p0f32")] + fn vld2_dup_f32_(ptr: *const f32) -> float32x2x2_t; } -vst1_s16_x4_(b.0, b.1, b.2, b.3, a) +vld2_dup_f32_(a.cast()) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -pub unsafe fn vst1_s32_x4(a: *mut i32, b: int32x2x4_t) { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +pub unsafe fn vld2q_dup_f32(a: *const f32) -> float32x4x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x4.p0i32.v2i32")] - fn vst1_s32_x4_(ptr: *mut i32, a: int32x2_t, b: int32x2_t, c: int32x2_t, d: int32x2_t); + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2dup.v4f32.p0i8")] + fn vld2q_dup_f32_(ptr: *const i8, size: i32) -> float32x4x2_t; } -vst1_s32_x4_(a, b.0, b.1, b.2, b.3) +vld2q_dup_f32_(a as *const i8, 4) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_s32_x4(a: *mut i32, b: int32x2x4_t) { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +pub unsafe fn vld2q_dup_f32(a: *const f32) -> float32x4x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x4.v2i32.p0i32")] - fn vst1_s32_x4_(a: int32x2_t, b: int32x2_t, c: int32x2_t, d: int32x2_t, ptr: *mut i32); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2r.v4f32.p0f32")] + fn vld2q_dup_f32_(ptr: *const f32) -> float32x4x2_t; } -vst1_s32_x4_(b.0, b.1, b.2, b.3, a) +vld2q_dup_f32_(a.cast()) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -pub unsafe fn vst1_s64_x4(a: *mut i64, b: int64x1x4_t) { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld2_lane_s8(a: *const i8, b: int8x8x2_t) -> int8x8x2_t { + static_assert_imm3!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x4.p0i64.v1i64")] - fn vst1_s64_x4_(ptr: *mut i64, a: int64x1_t, b: int64x1_t, c: int64x1_t, d: int64x1_t); + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2lane.v8i8.p0i8")] + fn vld2_lane_s8_(ptr: *const i8, a: int8x8_t, b: int8x8_t, n: i32, size: i32) -> int8x8x2_t; } -vst1_s64_x4_(a, b.0, b.1, b.2, b.3) +vld2_lane_s8_(a.cast(), b.0, b.1, LANE, 1) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_s64_x4(a: *mut i64, b: int64x1x4_t) { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld2_lane_s8(a: *const i8, b: int8x8x2_t) -> int8x8x2_t { + static_assert_imm3!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x4.v1i64.p0i64")] - fn vst1_s64_x4_(a: int64x1_t, b: int64x1_t, c: int64x1_t, d: int64x1_t, ptr: *mut i64); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2lane.v8i8.p0i8")] + fn vld2_lane_s8_(a: int8x8_t, b: int8x8_t, n: i64, ptr: *const i8) -> int8x8x2_t; } -vst1_s64_x4_(b.0, b.1, b.2, b.3, a) +vld2_lane_s8_(b.0, b.1, LANE as i64, a.cast()) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -pub unsafe fn vst1q_s8_x4(a: *mut i8, b: int8x16x4_t) { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld2_lane_s16(a: *const i16, b: int16x4x2_t) -> int16x4x2_t { + static_assert_imm2!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x4.p0i8.v16i8")] - fn vst1q_s8_x4_(ptr: *mut i8, a: int8x16_t, b: int8x16_t, c: int8x16_t, d: int8x16_t); + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2lane.v4i16.p0i8")] + fn vld2_lane_s16_(ptr: *const i8, a: int16x4_t, b: int16x4_t, n: i32, size: i32) -> int16x4x2_t; } -vst1q_s8_x4_(a, b.0, b.1, b.2, b.3) +vld2_lane_s16_(a.cast(), b.0, b.1, LANE, 2) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_s8_x4(a: *mut i8, b: int8x16x4_t) { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld2_lane_s16(a: *const i16, b: int16x4x2_t) -> int16x4x2_t { + static_assert_imm2!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x4.v16i8.p0i8")] - fn vst1q_s8_x4_(a: int8x16_t, b: int8x16_t, c: int8x16_t, d: int8x16_t, ptr: *mut i8); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2lane.v4i16.p0i8")] + fn vld2_lane_s16_(a: int16x4_t, b: int16x4_t, n: i64, ptr: *const i8) -> int16x4x2_t; } -vst1q_s8_x4_(b.0, b.1, b.2, b.3, a) +vld2_lane_s16_(b.0, b.1, LANE as i64, a.cast()) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -pub unsafe fn vst1q_s16_x4(a: *mut i16, b: int16x8x4_t) { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld2_lane_s32(a: *const i32, b: int32x2x2_t) -> int32x2x2_t { + static_assert_imm1!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x4.p0i16.v8i16")] - fn vst1q_s16_x4_(ptr: *mut i16, a: int16x8_t, b: int16x8_t, c: int16x8_t, d: int16x8_t); + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2lane.v2i32.p0i8")] + fn vld2_lane_s32_(ptr: *const i8, a: int32x2_t, b: int32x2_t, n: i32, size: i32) -> int32x2x2_t; } -vst1q_s16_x4_(a, b.0, b.1, b.2, b.3) +vld2_lane_s32_(a.cast(), b.0, b.1, LANE, 4) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_s16_x4(a: *mut i16, b: int16x8x4_t) { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld2_lane_s32(a: *const i32, b: int32x2x2_t) -> int32x2x2_t { + static_assert_imm1!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x4.v8i16.p0i16")] - fn vst1q_s16_x4_(a: int16x8_t, b: int16x8_t, c: int16x8_t, d: int16x8_t, ptr: *mut i16); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2lane.v2i32.p0i8")] + fn vld2_lane_s32_(a: int32x2_t, b: int32x2_t, n: i64, ptr: *const i8) -> int32x2x2_t; } -vst1q_s16_x4_(b.0, b.1, b.2, b.3, a) +vld2_lane_s32_(b.0, b.1, LANE as i64, a.cast()) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -pub unsafe fn vst1q_s32_x4(a: *mut i32, b: int32x4x4_t) { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld2q_lane_s16(a: *const i16, b: int16x8x2_t) -> int16x8x2_t { + static_assert_imm3!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x4.p0i32.v4i32")] - fn vst1q_s32_x4_(ptr: *mut i32, a: int32x4_t, b: int32x4_t, c: int32x4_t, d: int32x4_t); + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2lane.v8i16.p0i8")] + fn vld2q_lane_s16_(ptr: *const i8, a: int16x8_t, b: int16x8_t, n: i32, size: i32) -> int16x8x2_t; } -vst1q_s32_x4_(a, b.0, b.1, b.2, b.3) +vld2q_lane_s16_(a.cast(), b.0, b.1, LANE, 2) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_s32_x4(a: *mut i32, b: int32x4x4_t) { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld2q_lane_s16(a: *const i16, b: int16x8x2_t) -> int16x8x2_t { + static_assert_imm3!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x4.v4i32.p0i32")] - fn vst1q_s32_x4_(a: int32x4_t, b: int32x4_t, c: int32x4_t, d: int32x4_t, ptr: *mut i32); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2lane.v8i16.p0i8")] + fn vld2q_lane_s16_(a: int16x8_t, b: int16x8_t, n: i64, ptr: *const i8) -> int16x8x2_t; } -vst1q_s32_x4_(b.0, b.1, b.2, b.3, a) +vld2q_lane_s16_(b.0, b.1, LANE as i64, a.cast()) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -pub unsafe fn vst1q_s64_x4(a: *mut i64, b: int64x2x4_t) { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld2q_lane_s32(a: *const i32, b: int32x4x2_t) -> int32x4x2_t { + static_assert_imm2!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x4.p0i64.v2i64")] - fn vst1q_s64_x4_(ptr: *mut i64, a: int64x2_t, b: int64x2_t, c: int64x2_t, d: int64x2_t); + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2lane.v4i32.p0i8")] + fn vld2q_lane_s32_(ptr: *const i8, a: int32x4_t, b: int32x4_t, n: i32, size: i32) -> int32x4x2_t; } -vst1q_s64_x4_(a, b.0, b.1, b.2, b.3) +vld2q_lane_s32_(a.cast(), b.0, b.1, LANE, 4) } -/// Store multiple single-element structures from one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_s64_x4(a: *mut i64, b: int64x2x4_t) { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld2q_lane_s32(a: *const i32, b: int32x4x2_t) -> int32x4x2_t { + static_assert_imm2!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x4.v2i64.p0i64")] - fn vst1q_s64_x4_(a: int64x2_t, b: int64x2_t, c: int64x2_t, d: int64x2_t, ptr: *mut i64); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2lane.v4i32.p0i8")] + fn vld2q_lane_s32_(a: int32x4_t, b: int32x4_t, n: i64, ptr: *const i8) -> int32x4x2_t; } -vst1q_s64_x4_(b.0, b.1, b.2, b.3, a) +vld2q_lane_s32_(b.0, b.1, LANE as i64, a.cast()) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_u8_x2(a: *mut u8, b: uint8x8x2_t) { - vst1_s8_x2(transmute(a), transmute(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld2_lane_u8(a: *const u8, b: uint8x8x2_t) -> uint8x8x2_t { + static_assert_imm3!(LANE); + transmute(vld2_lane_s8::(transmute(a), transmute(b))) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_u16_x2(a: *mut u16, b: uint16x4x2_t) { - vst1_s16_x2(transmute(a), transmute(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld2_lane_u16(a: *const u16, b: uint16x4x2_t) -> uint16x4x2_t { + static_assert_imm2!(LANE); + transmute(vld2_lane_s16::(transmute(a), transmute(b))) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_u32_x2(a: *mut u32, b: uint32x2x2_t) { - vst1_s32_x2(transmute(a), transmute(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld2_lane_u32(a: *const u32, b: uint32x2x2_t) -> uint32x2x2_t { + static_assert_imm1!(LANE); + transmute(vld2_lane_s32::(transmute(a), transmute(b))) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_u64_x2(a: *mut u64, b: uint64x1x2_t) { - vst1_s64_x2(transmute(a), transmute(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld2q_lane_u16(a: *const u16, b: uint16x8x2_t) -> uint16x8x2_t { + static_assert_imm3!(LANE); + transmute(vld2q_lane_s16::(transmute(a), transmute(b))) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_u8_x2(a: *mut u8, b: uint8x16x2_t) { - vst1q_s8_x2(transmute(a), transmute(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld2q_lane_u32(a: *const u32, b: uint32x4x2_t) -> uint32x4x2_t { + static_assert_imm2!(LANE); + transmute(vld2q_lane_s32::(transmute(a), transmute(b))) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_u16_x2(a: *mut u16, b: uint16x8x2_t) { - vst1q_s16_x2(transmute(a), transmute(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld2_lane_p8(a: *const p8, b: poly8x8x2_t) -> poly8x8x2_t { + static_assert_imm3!(LANE); + transmute(vld2_lane_s8::(transmute(a), transmute(b))) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_u32_x2(a: *mut u32, b: uint32x4x2_t) { - vst1q_s32_x2(transmute(a), transmute(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld2_lane_p16(a: *const p16, b: poly16x4x2_t) -> poly16x4x2_t { + static_assert_imm2!(LANE); + transmute(vld2_lane_s16::(transmute(a), transmute(b))) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 2-element structures to two registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_u64_x2(a: *mut u64, b: uint64x2x2_t) { - vst1q_s64_x2(transmute(a), transmute(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld2q_lane_p16(a: *const p16, b: poly16x8x2_t) -> poly16x8x2_t { + static_assert_imm3!(LANE); + transmute(vld2q_lane_s16::(transmute(a), transmute(b))) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 2-element structures to two registers +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld2_lane_f32(a: *const f32, b: float32x2x2_t) -> float32x2x2_t { + static_assert_imm1!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2lane.v2f32.p0i8")] + fn vld2_lane_f32_(ptr: *const i8, a: float32x2_t, b: float32x2_t, n: i32, size: i32) -> float32x2x2_t; + } +vld2_lane_f32_(a.cast(), b.0, b.1, LANE, 4) +} + +/// Load multiple 2-element structures to two registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_u8_x3(a: *mut u8, b: uint8x8x3_t) { - vst1_s8_x3(transmute(a), transmute(b)) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld2_lane_f32(a: *const f32, b: float32x2x2_t) -> float32x2x2_t { + static_assert_imm1!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2lane.v2f32.p0i8")] + fn vld2_lane_f32_(a: float32x2_t, b: float32x2_t, n: i64, ptr: *const i8) -> float32x2x2_t; + } +vld2_lane_f32_(b.0, b.1, LANE as i64, a.cast()) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 2-element structures to two registers +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld2q_lane_f32(a: *const f32, b: float32x4x2_t) -> float32x4x2_t { + static_assert_imm2!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2lane.v4f32.p0i8")] + fn vld2q_lane_f32_(ptr: *const i8, a: float32x4_t, b: float32x4_t, n: i32, size: i32) -> float32x4x2_t; + } +vld2q_lane_f32_(a.cast(), b.0, b.1, LANE, 4) +} + +/// Load multiple 2-element structures to two registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_u16_x3(a: *mut u16, b: uint16x4x3_t) { - vst1_s16_x3(transmute(a), transmute(b)) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld2q_lane_f32(a: *const f32, b: float32x4x2_t) -> float32x4x2_t { + static_assert_imm2!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2lane.v4f32.p0i8")] + fn vld2q_lane_f32_(a: float32x4_t, b: float32x4_t, n: i64, ptr: *const i8) -> float32x4x2_t; + } +vld2q_lane_f32_(b.0, b.1, LANE as i64, a.cast()) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 3-element structures to three registers +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +pub unsafe fn vld3_s8(a: *const i8) -> int8x8x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3.v8i8.p0i8")] + fn vld3_s8_(ptr: *const i8, size: i32) -> int8x8x3_t; + } +vld3_s8_(a as *const i8, 1) +} + +/// Load multiple 3-element structures to three registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_u32_x3(a: *mut u32, b: uint32x2x3_t) { - vst1_s32_x3(transmute(a), transmute(b)) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +pub unsafe fn vld3_s8(a: *const i8) -> int8x8x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3.v8i8.p0v8i8")] + fn vld3_s8_(ptr: *const int8x8_t) -> int8x8x3_t; + } +vld3_s8_(a.cast()) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 3-element structures to three registers +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +pub unsafe fn vld3_s16(a: *const i16) -> int16x4x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3.v4i16.p0i8")] + fn vld3_s16_(ptr: *const i8, size: i32) -> int16x4x3_t; + } +vld3_s16_(a as *const i8, 2) +} + +/// Load multiple 3-element structures to three registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_u64_x3(a: *mut u64, b: uint64x1x3_t) { - vst1_s64_x3(transmute(a), transmute(b)) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +pub unsafe fn vld3_s16(a: *const i16) -> int16x4x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3.v4i16.p0v4i16")] + fn vld3_s16_(ptr: *const int16x4_t) -> int16x4x3_t; + } +vld3_s16_(a.cast()) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 3-element structures to three registers +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +pub unsafe fn vld3_s32(a: *const i32) -> int32x2x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3.v2i32.p0i8")] + fn vld3_s32_(ptr: *const i8, size: i32) -> int32x2x3_t; + } +vld3_s32_(a as *const i8, 4) +} + +/// Load multiple 3-element structures to three registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_u8_x3(a: *mut u8, b: uint8x16x3_t) { - vst1q_s8_x3(transmute(a), transmute(b)) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +pub unsafe fn vld3_s32(a: *const i32) -> int32x2x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3.v2i32.p0v2i32")] + fn vld3_s32_(ptr: *const int32x2_t) -> int32x2x3_t; + } +vld3_s32_(a.cast()) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 3-element structures to three registers +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +pub unsafe fn vld3q_s8(a: *const i8) -> int8x16x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3.v16i8.p0i8")] + fn vld3q_s8_(ptr: *const i8, size: i32) -> int8x16x3_t; + } +vld3q_s8_(a as *const i8, 1) +} + +/// Load multiple 3-element structures to three registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_u16_x3(a: *mut u16, b: uint16x8x3_t) { - vst1q_s16_x3(transmute(a), transmute(b)) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +pub unsafe fn vld3q_s8(a: *const i8) -> int8x16x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3.v16i8.p0v16i8")] + fn vld3q_s8_(ptr: *const int8x16_t) -> int8x16x3_t; + } +vld3q_s8_(a.cast()) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 3-element structures to three registers +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +pub unsafe fn vld3q_s16(a: *const i16) -> int16x8x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3.v8i16.p0i8")] + fn vld3q_s16_(ptr: *const i8, size: i32) -> int16x8x3_t; + } +vld3q_s16_(a as *const i8, 2) +} + +/// Load multiple 3-element structures to three registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_u32_x3(a: *mut u32, b: uint32x4x3_t) { - vst1q_s32_x3(transmute(a), transmute(b)) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +pub unsafe fn vld3q_s16(a: *const i16) -> int16x8x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3.v8i16.p0v8i16")] + fn vld3q_s16_(ptr: *const int16x8_t) -> int16x8x3_t; + } +vld3q_s16_(a.cast()) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 3-element structures to three registers +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +pub unsafe fn vld3q_s32(a: *const i32) -> int32x4x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3.v4i32.p0i8")] + fn vld3q_s32_(ptr: *const i8, size: i32) -> int32x4x3_t; + } +vld3q_s32_(a as *const i8, 4) +} + +/// Load multiple 3-element structures to three registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_u64_x3(a: *mut u64, b: uint64x2x3_t) { - vst1q_s64_x3(transmute(a), transmute(b)) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +pub unsafe fn vld3q_s32(a: *const i32) -> int32x4x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3.v4i32.p0v4i32")] + fn vld3q_s32_(ptr: *const int32x4_t) -> int32x4x3_t; + } +vld3q_s32_(a.cast()) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 3-element structures to three registers +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +pub unsafe fn vld3_s64(a: *const i64) -> int64x1x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3.v1i64.p0i8")] + fn vld3_s64_(ptr: *const i8, size: i32) -> int64x1x3_t; + } +vld3_s64_(a as *const i8, 8) +} + +/// Load multiple 3-element structures to three registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_u8_x4(a: *mut u8, b: uint8x8x4_t) { - vst1_s8_x4(transmute(a), transmute(b)) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vld3_s64(a: *const i64) -> int64x1x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3.v1i64.p0v1i64")] + fn vld3_s64_(ptr: *const int64x1_t) -> int64x1x3_t; + } +vld3_s64_(a.cast()) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_u16_x4(a: *mut u16, b: uint16x4x4_t) { - vst1_s16_x4(transmute(a), transmute(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +pub unsafe fn vld3_u8(a: *const u8) -> uint8x8x3_t { + transmute(vld3_s8(transmute(a))) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_u32_x4(a: *mut u32, b: uint32x2x4_t) { - vst1_s32_x4(transmute(a), transmute(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +pub unsafe fn vld3_u16(a: *const u16) -> uint16x4x3_t { + transmute(vld3_s16(transmute(a))) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_u64_x4(a: *mut u64, b: uint64x1x4_t) { - vst1_s64_x4(transmute(a), transmute(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +pub unsafe fn vld3_u32(a: *const u32) -> uint32x2x3_t { + transmute(vld3_s32(transmute(a))) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_u8_x4(a: *mut u8, b: uint8x16x4_t) { - vst1q_s8_x4(transmute(a), transmute(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +pub unsafe fn vld3q_u8(a: *const u8) -> uint8x16x3_t { + transmute(vld3q_s8(transmute(a))) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_u16_x4(a: *mut u16, b: uint16x8x4_t) { - vst1q_s16_x4(transmute(a), transmute(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +pub unsafe fn vld3q_u16(a: *const u16) -> uint16x8x3_t { + transmute(vld3q_s16(transmute(a))) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_u32_x4(a: *mut u32, b: uint32x4x4_t) { - vst1q_s32_x4(transmute(a), transmute(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +pub unsafe fn vld3q_u32(a: *const u32) -> uint32x4x3_t { + transmute(vld3q_s32(transmute(a))) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_u64_x4(a: *mut u64, b: uint64x2x4_t) { - vst1q_s64_x4(transmute(a), transmute(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +pub unsafe fn vld3_p8(a: *const p8) -> poly8x8x3_t { + transmute(vld3_s8(transmute(a))) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_p8_x2(a: *mut p8, b: poly8x8x2_t) { - vst1_s8_x2(transmute(a), transmute(b)) -} - -/// Store multiple single-element structures to one, two, three, or four registers -#[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_p8_x3(a: *mut p8, b: poly8x8x3_t) { - vst1_s8_x3(transmute(a), transmute(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +pub unsafe fn vld3_p16(a: *const p16) -> poly16x4x3_t { + transmute(vld3_s16(transmute(a))) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_p8_x4(a: *mut p8, b: poly8x8x4_t) { - vst1_s8_x4(transmute(a), transmute(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +pub unsafe fn vld3q_p8(a: *const p8) -> poly8x16x3_t { + transmute(vld3q_s8(transmute(a))) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_p8_x2(a: *mut p8, b: poly8x16x2_t) { - vst1q_s8_x2(transmute(a), transmute(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +pub unsafe fn vld3q_p16(a: *const p16) -> poly16x8x3_t { + transmute(vld3q_s16(transmute(a))) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_p8_x3(a: *mut p8, b: poly8x16x3_t) { - vst1q_s8_x3(transmute(a), transmute(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vld3_u64(a: *const u64) -> uint64x1x3_t { + transmute(vld3_s64(transmute(a))) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 3-element structures to three registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_p8_x4(a: *mut p8, b: poly8x16x4_t) { - vst1q_s8_x4(transmute(a), transmute(b)) +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vld3_p64(a: *const p64) -> poly64x1x3_t { + transmute(vld3_s64(transmute(a))) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 3-element structures to three registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_p16_x2(a: *mut p16, b: poly16x4x2_t) { - vst1_s16_x2(transmute(a), transmute(b)) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +pub unsafe fn vld3_f32(a: *const f32) -> float32x2x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3.v2f32.p0i8")] + fn vld3_f32_(ptr: *const i8, size: i32) -> float32x2x3_t; + } +vld3_f32_(a as *const i8, 4) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 3-element structures to three registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_p16_x3(a: *mut p16, b: poly16x4x3_t) { - vst1_s16_x3(transmute(a), transmute(b)) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +pub unsafe fn vld3_f32(a: *const f32) -> float32x2x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3.v2f32.p0v2f32")] + fn vld3_f32_(ptr: *const float32x2_t) -> float32x2x3_t; + } +vld3_f32_(a.cast()) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 3-element structures to three registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_p16_x4(a: *mut p16, b: poly16x4x4_t) { - vst1_s16_x4(transmute(a), transmute(b)) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +pub unsafe fn vld3q_f32(a: *const f32) -> float32x4x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3.v4f32.p0i8")] + fn vld3q_f32_(ptr: *const i8, size: i32) -> float32x4x3_t; + } +vld3q_f32_(a as *const i8, 4) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load multiple 3-element structures to three registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_p16_x2(a: *mut p16, b: poly16x8x2_t) { - vst1q_s16_x2(transmute(a), transmute(b)) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +pub unsafe fn vld3q_f32(a: *const f32) -> float32x4x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3.v4f32.p0v4f32")] + fn vld3q_f32_(ptr: *const float32x4_t) -> float32x4x3_t; + } +vld3q_f32_(a.cast()) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_p16_x3(a: *mut p16, b: poly16x8x3_t) { - vst1q_s16_x3(transmute(a), transmute(b)) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +pub unsafe fn vld3_dup_s8(a: *const i8) -> int8x8x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3dup.v8i8.p0i8")] + fn vld3_dup_s8_(ptr: *const i8, size: i32) -> int8x8x3_t; + } +vld3_dup_s8_(a as *const i8, 1) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_p16_x4(a: *mut p16, b: poly16x8x4_t) { - vst1q_s16_x4(transmute(a), transmute(b)) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +pub unsafe fn vld3_dup_s8(a: *const i8) -> int8x8x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3r.v8i8.p0i8")] + fn vld3_dup_s8_(ptr: *const i8) -> int8x8x3_t; + } +vld3_dup_s8_(a.cast()) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -pub unsafe fn vst1_f32_x2(a: *mut f32, b: float32x2x2_t) { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +pub unsafe fn vld3_dup_s16(a: *const i16) -> int16x4x3_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x2.p0f32.v2f32")] - fn vst1_f32_x2_(ptr: *mut f32, a: float32x2_t, b: float32x2_t); + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3dup.v4i16.p0i8")] + fn vld3_dup_s16_(ptr: *const i8, size: i32) -> int16x4x3_t; } -vst1_f32_x2_(a, b.0, b.1) +vld3_dup_s16_(a as *const i8, 2) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_f32_x2(a: *mut f32, b: float32x2x2_t) { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +pub unsafe fn vld3_dup_s16(a: *const i16) -> int16x4x3_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x2.v2f32.p0f32")] - fn vst1_f32_x2_(a: float32x2_t, b: float32x2_t, ptr: *mut f32); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3r.v4i16.p0i16")] + fn vld3_dup_s16_(ptr: *const i16) -> int16x4x3_t; } -vst1_f32_x2_(b.0, b.1, a) +vld3_dup_s16_(a.cast()) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -pub unsafe fn vst1q_f32_x2(a: *mut f32, b: float32x4x2_t) { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +pub unsafe fn vld3_dup_s32(a: *const i32) -> int32x2x3_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x2.p0f32.v4f32")] - fn vst1q_f32_x2_(ptr: *mut f32, a: float32x4_t, b: float32x4_t); + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3dup.v2i32.p0i8")] + fn vld3_dup_s32_(ptr: *const i8, size: i32) -> int32x2x3_t; } -vst1q_f32_x2_(a, b.0, b.1) +vld3_dup_s32_(a as *const i8, 4) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_f32_x2(a: *mut f32, b: float32x4x2_t) { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +pub unsafe fn vld3_dup_s32(a: *const i32) -> int32x2x3_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x2.v4f32.p0f32")] - fn vst1q_f32_x2_(a: float32x4_t, b: float32x4_t, ptr: *mut f32); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3r.v2i32.p0i32")] + fn vld3_dup_s32_(ptr: *const i32) -> int32x2x3_t; } -vst1q_f32_x2_(b.0, b.1, a) +vld3_dup_s32_(a.cast()) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -pub unsafe fn vst1_f32_x3(a: *mut f32, b: float32x2x3_t) { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +pub unsafe fn vld3q_dup_s8(a: *const i8) -> int8x16x3_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x3.p0f32.v2f32")] - fn vst1_f32_x3_(ptr: *mut f32, a: float32x2_t, b: float32x2_t, c: float32x2_t); + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3dup.v16i8.p0i8")] + fn vld3q_dup_s8_(ptr: *const i8, size: i32) -> int8x16x3_t; } -vst1_f32_x3_(a, b.0, b.1, b.2) +vld3q_dup_s8_(a as *const i8, 1) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_f32_x3(a: *mut f32, b: float32x2x3_t) { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +pub unsafe fn vld3q_dup_s8(a: *const i8) -> int8x16x3_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x3.v2f32.p0f32")] - fn vst1_f32_x3_(a: float32x2_t, b: float32x2_t, c: float32x2_t, ptr: *mut f32); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3r.v16i8.p0i8")] + fn vld3q_dup_s8_(ptr: *const i8) -> int8x16x3_t; } -vst1_f32_x3_(b.0, b.1, b.2, a) +vld3q_dup_s8_(a.cast()) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -pub unsafe fn vst1q_f32_x3(a: *mut f32, b: float32x4x3_t) { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +pub unsafe fn vld3q_dup_s16(a: *const i16) -> int16x8x3_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x3.p0f32.v4f32")] - fn vst1q_f32_x3_(ptr: *mut f32, a: float32x4_t, b: float32x4_t, c: float32x4_t); + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3dup.v8i16.p0i8")] + fn vld3q_dup_s16_(ptr: *const i8, size: i32) -> int16x8x3_t; } -vst1q_f32_x3_(a, b.0, b.1, b.2) +vld3q_dup_s16_(a as *const i8, 2) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_f32_x3(a: *mut f32, b: float32x4x3_t) { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +pub unsafe fn vld3q_dup_s16(a: *const i16) -> int16x8x3_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x3.v4f32.p0f32")] - fn vst1q_f32_x3_(a: float32x4_t, b: float32x4_t, c: float32x4_t, ptr: *mut f32); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3r.v8i16.p0i16")] + fn vld3q_dup_s16_(ptr: *const i16) -> int16x8x3_t; } -vst1q_f32_x3_(b.0, b.1, b.2, a) +vld3q_dup_s16_(a.cast()) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -pub unsafe fn vst1_f32_x4(a: *mut f32, b: float32x2x4_t) { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +pub unsafe fn vld3q_dup_s32(a: *const i32) -> int32x4x3_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x4.p0f32.v2f32")] - fn vst1_f32_x4_(ptr: *mut f32, a: float32x2_t, b: float32x2_t, c: float32x2_t, d: float32x2_t); + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3dup.v4i32.p0i8")] + fn vld3q_dup_s32_(ptr: *const i8, size: i32) -> int32x4x3_t; } -vst1_f32_x4_(a, b.0, b.1, b.2, b.3) +vld3q_dup_s32_(a as *const i8, 4) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1_f32_x4(a: *mut f32, b: float32x2x4_t) { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +pub unsafe fn vld3q_dup_s32(a: *const i32) -> int32x4x3_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x4.v2f32.p0f32")] - fn vst1_f32_x4_(a: float32x2_t, b: float32x2_t, c: float32x2_t, d: float32x2_t, ptr: *mut f32); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3r.v4i32.p0i32")] + fn vld3q_dup_s32_(ptr: *const i32) -> int32x4x3_t; } -vst1_f32_x4_(b.0, b.1, b.2, b.3, a) +vld3q_dup_s32_(a.cast()) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] -pub unsafe fn vst1q_f32_x4(a: *mut f32, b: float32x4x4_t) { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +pub unsafe fn vld3_dup_s64(a: *const i64) -> int64x1x3_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x4.p0f32.v4f32")] - fn vst1q_f32_x4_(ptr: *mut f32, a: float32x4_t, b: float32x4_t, c: float32x4_t, d: float32x4_t); + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3dup.v1i64.p0i8")] + fn vld3_dup_s64_(ptr: *const i8, size: i32) -> int64x1x3_t; } -vst1q_f32_x4_(a, b.0, b.1, b.2, b.3) +vld3_dup_s64_(a as *const i8, 8) } -/// Store multiple single-element structures to one, two, three, or four registers +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] -pub unsafe fn vst1q_f32_x4(a: *mut f32, b: float32x4x4_t) { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +pub unsafe fn vld3_dup_s64(a: *const i64) -> int64x1x3_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x4.v4f32.p0f32")] - fn vst1q_f32_x4_(a: float32x4_t, b: float32x4_t, c: float32x4_t, d: float32x4_t, ptr: *mut f32); + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3r.v1i64.p0i64")] + fn vld3_dup_s64_(ptr: *const i64) -> int64x1x3_t; } -vst1q_f32_x4_(b.0, b.1, b.2, b.3, a) +vld3_dup_s64_(a.cast()) } -/// Multiply +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i8"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] -pub unsafe fn vmul_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { - simd_mul(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +pub unsafe fn vld3_dup_u8(a: *const u8) -> uint8x8x3_t { + transmute(vld3_dup_s8(transmute(a))) } -/// Multiply +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i8"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] -pub unsafe fn vmulq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { - simd_mul(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +pub unsafe fn vld3_dup_u16(a: *const u16) -> uint16x4x3_t { + transmute(vld3_dup_s16(transmute(a))) } -/// Multiply +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i16"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] -pub unsafe fn vmul_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { - simd_mul(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +pub unsafe fn vld3_dup_u32(a: *const u32) -> uint32x2x3_t { + transmute(vld3_dup_s32(transmute(a))) } -/// Multiply +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i16"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] -pub unsafe fn vmulq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { - simd_mul(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +pub unsafe fn vld3q_dup_u8(a: *const u8) -> uint8x16x3_t { + transmute(vld3q_dup_s8(transmute(a))) } -/// Multiply +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i32"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] -pub unsafe fn vmul_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { - simd_mul(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +pub unsafe fn vld3q_dup_u16(a: *const u16) -> uint16x8x3_t { + transmute(vld3q_dup_s16(transmute(a))) } -/// Multiply +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i32"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] -pub unsafe fn vmulq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { - simd_mul(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +pub unsafe fn vld3q_dup_u32(a: *const u32) -> uint32x4x3_t { + transmute(vld3q_dup_s32(transmute(a))) } -/// Multiply +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i8"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] -pub unsafe fn vmul_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { - simd_mul(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +pub unsafe fn vld3_dup_p8(a: *const p8) -> poly8x8x3_t { + transmute(vld3_dup_s8(transmute(a))) } -/// Multiply +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i8"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] -pub unsafe fn vmulq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { - simd_mul(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +pub unsafe fn vld3_dup_p16(a: *const p16) -> poly16x4x3_t { + transmute(vld3_dup_s16(transmute(a))) } -/// Multiply +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i16"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] -pub unsafe fn vmul_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { - simd_mul(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +pub unsafe fn vld3q_dup_p8(a: *const p8) -> poly8x16x3_t { + transmute(vld3q_dup_s8(transmute(a))) } -/// Multiply +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i16"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] -pub unsafe fn vmulq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { - simd_mul(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +pub unsafe fn vld3q_dup_p16(a: *const p16) -> poly16x8x3_t { + transmute(vld3q_dup_s16(transmute(a))) } -/// Multiply +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i32"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] -pub unsafe fn vmul_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { - simd_mul(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +pub unsafe fn vld3_dup_u64(a: *const u64) -> uint64x1x3_t { + transmute(vld3_dup_s64(transmute(a))) } -/// Multiply +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i32"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] -pub unsafe fn vmulq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { - simd_mul(a, b) +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +pub unsafe fn vld3_dup_p64(a: *const p64) -> poly64x1x3_t { + transmute(vld3_dup_s64(transmute(a))) } -/// Polynomial multiply +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(pmul))] -pub unsafe fn vmul_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +pub unsafe fn vld3_dup_f32(a: *const f32) -> float32x2x3_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmulp.v8i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.pmul.v8i8")] - fn vmul_p8_(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3dup.v2f32.p0i8")] + fn vld3_dup_f32_(ptr: *const i8, size: i32) -> float32x2x3_t; } -vmul_p8_(a, b) +vld3_dup_f32_(a as *const i8, 4) } -/// Polynomial multiply +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(pmul))] -pub unsafe fn vmulq_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +pub unsafe fn vld3_dup_f32(a: *const f32) -> float32x2x3_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmulp.v16i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.pmul.v16i8")] - fn vmulq_p8_(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3r.v2f32.p0f32")] + fn vld3_dup_f32_(ptr: *const f32) -> float32x2x3_t; } -vmulq_p8_(a, b) -} - -/// Multiply -#[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.f32"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))] -pub unsafe fn vmul_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { - simd_mul(a, b) +vld3_dup_f32_(a.cast()) } -/// Multiply +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.f32"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))] -pub unsafe fn vmulq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { - simd_mul(a, b) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +pub unsafe fn vld3q_dup_f32(a: *const f32) -> float32x4x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3dup.v4f32.p0i8")] + fn vld3q_dup_f32_(ptr: *const i8, size: i32) -> float32x4x3_t; + } +vld3q_dup_f32_(a as *const i8, 4) } -/// Vector multiply by scalar +/// Load single 3-element structure and replicate to all lanes of three registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] -pub unsafe fn vmul_n_s16(a: int16x4_t, b: i16) -> int16x4_t { - simd_mul(a, vdup_n_s16(b)) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +pub unsafe fn vld3q_dup_f32(a: *const f32) -> float32x4x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3r.v4f32.p0f32")] + fn vld3q_dup_f32_(ptr: *const f32) -> float32x4x3_t; + } +vld3q_dup_f32_(a.cast()) } -/// Vector multiply by scalar +/// Load multiple 3-element structures to two registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] -pub unsafe fn vmulq_n_s16(a: int16x8_t, b: i16) -> int16x8_t { - simd_mul(a, vdupq_n_s16(b)) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld3_lane_s8(a: *const i8, b: int8x8x3_t) -> int8x8x3_t { + static_assert_imm3!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3lane.v8i8.p0i8")] + fn vld3_lane_s8_(ptr: *const i8, a: int8x8_t, b: int8x8_t, c: int8x8_t, n: i32, size: i32) -> int8x8x3_t; + } +vld3_lane_s8_(a.cast(), b.0, b.1, b.2, LANE, 1) } -/// Vector multiply by scalar +/// Load multiple 3-element structures to two registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] -pub unsafe fn vmul_n_s32(a: int32x2_t, b: i32) -> int32x2_t { - simd_mul(a, vdup_n_s32(b)) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld3_lane_s8(a: *const i8, b: int8x8x3_t) -> int8x8x3_t { + static_assert_imm3!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3lane.v8i8.p0i8")] + fn vld3_lane_s8_(a: int8x8_t, b: int8x8_t, c: int8x8_t, n: i64, ptr: *const i8) -> int8x8x3_t; + } +vld3_lane_s8_(b.0, b.1, b.2, LANE as i64, a.cast()) } -/// Vector multiply by scalar +/// Load multiple 3-element structures to two registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] -pub unsafe fn vmulq_n_s32(a: int32x4_t, b: i32) -> int32x4_t { - simd_mul(a, vdupq_n_s32(b)) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld3_lane_s16(a: *const i16, b: int16x4x3_t) -> int16x4x3_t { + static_assert_imm2!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3lane.v4i16.p0i8")] + fn vld3_lane_s16_(ptr: *const i8, a: int16x4_t, b: int16x4_t, c: int16x4_t, n: i32, size: i32) -> int16x4x3_t; + } +vld3_lane_s16_(a.cast(), b.0, b.1, b.2, LANE, 2) } -/// Vector multiply by scalar +/// Load multiple 3-element structures to two registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] -pub unsafe fn vmul_n_u16(a: uint16x4_t, b: u16) -> uint16x4_t { - simd_mul(a, vdup_n_u16(b)) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld3_lane_s16(a: *const i16, b: int16x4x3_t) -> int16x4x3_t { + static_assert_imm2!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3lane.v4i16.p0i8")] + fn vld3_lane_s16_(a: int16x4_t, b: int16x4_t, c: int16x4_t, n: i64, ptr: *const i8) -> int16x4x3_t; + } +vld3_lane_s16_(b.0, b.1, b.2, LANE as i64, a.cast()) } -/// Vector multiply by scalar +/// Load multiple 3-element structures to two registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] -pub unsafe fn vmulq_n_u16(a: uint16x8_t, b: u16) -> uint16x8_t { - simd_mul(a, vdupq_n_u16(b)) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld3_lane_s32(a: *const i32, b: int32x2x3_t) -> int32x2x3_t { + static_assert_imm1!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3lane.v2i32.p0i8")] + fn vld3_lane_s32_(ptr: *const i8, a: int32x2_t, b: int32x2_t, c: int32x2_t, n: i32, size: i32) -> int32x2x3_t; + } +vld3_lane_s32_(a.cast(), b.0, b.1, b.2, LANE, 4) } -/// Vector multiply by scalar +/// Load multiple 3-element structures to two registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] -pub unsafe fn vmul_n_u32(a: uint32x2_t, b: u32) -> uint32x2_t { - simd_mul(a, vdup_n_u32(b)) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld3_lane_s32(a: *const i32, b: int32x2x3_t) -> int32x2x3_t { + static_assert_imm1!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3lane.v2i32.p0i8")] + fn vld3_lane_s32_(a: int32x2_t, b: int32x2_t, c: int32x2_t, n: i64, ptr: *const i8) -> int32x2x3_t; + } +vld3_lane_s32_(b.0, b.1, b.2, LANE as i64, a.cast()) } -/// Vector multiply by scalar +/// Load multiple 3-element structures to two registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] -pub unsafe fn vmulq_n_u32(a: uint32x4_t, b: u32) -> uint32x4_t { - simd_mul(a, vdupq_n_u32(b)) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld3q_lane_s16(a: *const i16, b: int16x8x3_t) -> int16x8x3_t { + static_assert_imm3!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3lane.v8i16.p0i8")] + fn vld3q_lane_s16_(ptr: *const i8, a: int16x8_t, b: int16x8_t, c: int16x8_t, n: i32, size: i32) -> int16x8x3_t; + } +vld3q_lane_s16_(a.cast(), b.0, b.1, b.2, LANE, 2) } -/// Vector multiply by scalar +/// Load multiple 3-element structures to two registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))] -pub unsafe fn vmul_n_f32(a: float32x2_t, b: f32) -> float32x2_t { - simd_mul(a, vdup_n_f32(b)) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld3q_lane_s16(a: *const i16, b: int16x8x3_t) -> int16x8x3_t { + static_assert_imm3!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3lane.v8i16.p0i8")] + fn vld3q_lane_s16_(a: int16x8_t, b: int16x8_t, c: int16x8_t, n: i64, ptr: *const i8) -> int16x8x3_t; + } +vld3q_lane_s16_(b.0, b.1, b.2, LANE as i64, a.cast()) } -/// Vector multiply by scalar +/// Load multiple 3-element structures to two registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))] -pub unsafe fn vmulq_n_f32(a: float32x4_t, b: f32) -> float32x4_t { - simd_mul(a, vdupq_n_f32(b)) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld3q_lane_s32(a: *const i32, b: int32x4x3_t) -> int32x4x3_t { + static_assert_imm2!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3lane.v4i32.p0i8")] + fn vld3q_lane_s32_(ptr: *const i8, a: int32x4_t, b: int32x4_t, c: int32x4_t, n: i32, size: i32) -> int32x4x3_t; + } +vld3q_lane_s32_(a.cast(), b.0, b.1, b.2, LANE, 4) } -/// Multiply +/// Load multiple 3-element structures to two registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmul_lane_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { +pub unsafe fn vld3q_lane_s32(a: *const i32, b: int32x4x3_t) -> int32x4x3_t { static_assert_imm2!(LANE); - simd_mul(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3lane.v4i32.p0i8")] + fn vld3q_lane_s32_(a: int32x4_t, b: int32x4_t, c: int32x4_t, n: i64, ptr: *const i8) -> int32x4x3_t; + } +vld3q_lane_s32_(b.0, b.1, b.2, LANE as i64, a.cast()) } -/// Multiply +/// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmul_laneq_s16(a: int16x4_t, b: int16x8_t) -> int16x4_t { +pub unsafe fn vld3_lane_u8(a: *const u8, b: uint8x8x3_t) -> uint8x8x3_t { static_assert_imm3!(LANE); - simd_mul(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) + transmute(vld3_lane_s8::(transmute(a), transmute(b))) } -/// Multiply +/// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmulq_lane_s16(a: int16x8_t, b: int16x4_t) -> int16x8_t { +pub unsafe fn vld3_lane_u16(a: *const u16, b: uint16x4x3_t) -> uint16x4x3_t { static_assert_imm2!(LANE); - simd_mul(a, simd_shuffle8!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) + transmute(vld3_lane_s16::(transmute(a), transmute(b))) } -/// Multiply +/// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmulq_laneq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { - static_assert_imm3!(LANE); - simd_mul(a, simd_shuffle8!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) +pub unsafe fn vld3_lane_u32(a: *const u32, b: uint32x2x3_t) -> uint32x2x3_t { + static_assert_imm1!(LANE); + transmute(vld3_lane_s32::(transmute(a), transmute(b))) } -/// Multiply +/// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmul_lane_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { - static_assert_imm1!(LANE); - simd_mul(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) +pub unsafe fn vld3q_lane_u16(a: *const u16, b: uint16x8x3_t) -> uint16x8x3_t { + static_assert_imm3!(LANE); + transmute(vld3q_lane_s16::(transmute(a), transmute(b))) } -/// Multiply +/// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmul_laneq_s32(a: int32x2_t, b: int32x4_t) -> int32x2_t { +pub unsafe fn vld3q_lane_u32(a: *const u32, b: uint32x4x3_t) -> uint32x4x3_t { static_assert_imm2!(LANE); - simd_mul(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) + transmute(vld3q_lane_s32::(transmute(a), transmute(b))) } -/// Multiply +/// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmulq_lane_s32(a: int32x4_t, b: int32x2_t) -> int32x4_t { - static_assert_imm1!(LANE); - simd_mul(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) +pub unsafe fn vld3_lane_p8(a: *const p8, b: poly8x8x3_t) -> poly8x8x3_t { + static_assert_imm3!(LANE); + transmute(vld3_lane_s8::(transmute(a), transmute(b))) } -/// Multiply +/// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmulq_laneq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { +pub unsafe fn vld3_lane_p16(a: *const p16, b: poly16x4x3_t) -> poly16x4x3_t { static_assert_imm2!(LANE); - simd_mul(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) + transmute(vld3_lane_s16::(transmute(a), transmute(b))) } -/// Multiply +/// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmul_lane_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { - static_assert_imm2!(LANE); - simd_mul(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) +pub unsafe fn vld3q_lane_p16(a: *const p16, b: poly16x8x3_t) -> poly16x8x3_t { + static_assert_imm3!(LANE); + transmute(vld3q_lane_s16::(transmute(a), transmute(b))) } -/// Multiply +/// Load multiple 3-element structures to three registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmul_laneq_u16(a: uint16x4_t, b: uint16x8_t) -> uint16x4_t { - static_assert_imm3!(LANE); - simd_mul(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) +pub unsafe fn vld3_lane_f32(a: *const f32, b: float32x2x3_t) -> float32x2x3_t { + static_assert_imm1!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3lane.v2f32.p0i8")] + fn vld3_lane_f32_(ptr: *const i8, a: float32x2_t, b: float32x2_t, c: float32x2_t, n: i32, size: i32) -> float32x2x3_t; + } +vld3_lane_f32_(a.cast(), b.0, b.1, b.2, LANE, 4) } -/// Multiply +/// Load multiple 3-element structures to three registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmulq_lane_u16(a: uint16x8_t, b: uint16x4_t) -> uint16x8_t { - static_assert_imm2!(LANE); - simd_mul(a, simd_shuffle8!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) +pub unsafe fn vld3_lane_f32(a: *const f32, b: float32x2x3_t) -> float32x2x3_t { + static_assert_imm1!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3lane.v2f32.p0i8")] + fn vld3_lane_f32_(a: float32x2_t, b: float32x2_t, c: float32x2_t, n: i64, ptr: *const i8) -> float32x2x3_t; + } +vld3_lane_f32_(b.0, b.1, b.2, LANE as i64, a.cast()) } -/// Multiply +/// Load multiple 3-element structures to three registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmulq_laneq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { - static_assert_imm3!(LANE); - simd_mul(a, simd_shuffle8!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) +pub unsafe fn vld3q_lane_f32(a: *const f32, b: float32x4x3_t) -> float32x4x3_t { + static_assert_imm2!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3lane.v4f32.p0i8")] + fn vld3q_lane_f32_(ptr: *const i8, a: float32x4_t, b: float32x4_t, c: float32x4_t, n: i32, size: i32) -> float32x4x3_t; + } +vld3q_lane_f32_(a.cast(), b.0, b.1, b.2, LANE, 4) } -/// Multiply +/// Load multiple 3-element structures to three registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vmul_lane_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { - static_assert_imm1!(LANE); - simd_mul(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) +pub unsafe fn vld3q_lane_f32(a: *const f32, b: float32x4x3_t) -> float32x4x3_t { + static_assert_imm2!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3lane.v4f32.p0i8")] + fn vld3q_lane_f32_(a: float32x4_t, b: float32x4_t, c: float32x4_t, n: i64, ptr: *const i8) -> float32x4x3_t; + } +vld3q_lane_f32_(b.0, b.1, b.2, LANE as i64, a.cast()) } -/// Multiply +/// Load multiple 4-element structures to four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vmul_laneq_u32(a: uint32x2_t, b: uint32x4_t) -> uint32x2_t { - static_assert_imm2!(LANE); - simd_mul(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +pub unsafe fn vld4_s8(a: *const i8) -> int8x8x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4.v8i8.p0i8")] + fn vld4_s8_(ptr: *const i8, size: i32) -> int8x8x4_t; + } +vld4_s8_(a as *const i8, 1) } -/// Multiply +/// Load multiple 4-element structures to four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vmulq_lane_u32(a: uint32x4_t, b: uint32x2_t) -> uint32x4_t { - static_assert_imm1!(LANE); - simd_mul(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +pub unsafe fn vld4_s8(a: *const i8) -> int8x8x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4.v8i8.p0v8i8")] + fn vld4_s8_(ptr: *const int8x8_t) -> int8x8x4_t; + } +vld4_s8_(a.cast()) } -/// Multiply +/// Load multiple 4-element structures to four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vmulq_laneq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { - static_assert_imm2!(LANE); - simd_mul(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +pub unsafe fn vld4_s16(a: *const i16) -> int16x4x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4.v4i16.p0i8")] + fn vld4_s16_(ptr: *const i8, size: i32) -> int16x4x4_t; + } +vld4_s16_(a as *const i8, 2) } -/// Floating-point multiply +/// Load multiple 4-element structures to four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vmul_lane_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { - static_assert_imm1!(LANE); - simd_mul(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +pub unsafe fn vld4_s16(a: *const i16) -> int16x4x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4.v4i16.p0v4i16")] + fn vld4_s16_(ptr: *const int16x4_t) -> int16x4x4_t; + } +vld4_s16_(a.cast()) } -/// Floating-point multiply +/// Load multiple 4-element structures to four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vmul_laneq_f32(a: float32x2_t, b: float32x4_t) -> float32x2_t { - static_assert_imm2!(LANE); - simd_mul(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +pub unsafe fn vld4_s32(a: *const i32) -> int32x2x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4.v2i32.p0i8")] + fn vld4_s32_(ptr: *const i8, size: i32) -> int32x2x4_t; + } +vld4_s32_(a as *const i8, 4) } -/// Floating-point multiply +/// Load multiple 4-element structures to four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vmulq_lane_f32(a: float32x4_t, b: float32x2_t) -> float32x4_t { - static_assert_imm1!(LANE); - simd_mul(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +pub unsafe fn vld4_s32(a: *const i32) -> int32x2x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4.v2i32.p0v2i32")] + fn vld4_s32_(ptr: *const int32x2_t) -> int32x2x4_t; + } +vld4_s32_(a.cast()) } -/// Floating-point multiply +/// Load multiple 4-element structures to four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vmulq_laneq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { - static_assert_imm2!(LANE); - simd_mul(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +pub unsafe fn vld4q_s8(a: *const i8) -> int8x16x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4.v16i8.p0i8")] + fn vld4q_s8_(ptr: *const i8, size: i32) -> int8x16x4_t; + } +vld4q_s8_(a as *const i8, 1) } -/// Signed multiply long +/// Load multiple 4-element structures to four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmull.s8"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull))] -pub unsafe fn vmull_s8(a: int8x8_t, b: int8x8_t) -> int16x8_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +pub unsafe fn vld4q_s8(a: *const i8) -> int8x16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmulls.v8i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.smull.v8i8")] - fn vmull_s8_(a: int8x8_t, b: int8x8_t) -> int16x8_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4.v16i8.p0v16i8")] + fn vld4q_s8_(ptr: *const int8x16_t) -> int8x16x4_t; } -vmull_s8_(a, b) +vld4q_s8_(a.cast()) } -/// Signed multiply long +/// Load multiple 4-element structures to four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmull.s16"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull))] -pub unsafe fn vmull_s16(a: int16x4_t, b: int16x4_t) -> int32x4_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +pub unsafe fn vld4q_s16(a: *const i16) -> int16x8x4_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmulls.v4i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.smull.v4i16")] - fn vmull_s16_(a: int16x4_t, b: int16x4_t) -> int32x4_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4.v8i16.p0i8")] + fn vld4q_s16_(ptr: *const i8, size: i32) -> int16x8x4_t; } -vmull_s16_(a, b) +vld4q_s16_(a as *const i8, 2) } -/// Signed multiply long +/// Load multiple 4-element structures to four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmull.s32"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull))] -pub unsafe fn vmull_s32(a: int32x2_t, b: int32x2_t) -> int64x2_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +pub unsafe fn vld4q_s16(a: *const i16) -> int16x8x4_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmulls.v2i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.smull.v2i32")] - fn vmull_s32_(a: int32x2_t, b: int32x2_t) -> int64x2_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4.v8i16.p0v8i16")] + fn vld4q_s16_(ptr: *const int16x8_t) -> int16x8x4_t; } -vmull_s32_(a, b) +vld4q_s16_(a.cast()) } -/// Unsigned multiply long +/// Load multiple 4-element structures to four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmull.u8"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull))] -pub unsafe fn vmull_u8(a: uint8x8_t, b: uint8x8_t) -> uint16x8_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +pub unsafe fn vld4q_s32(a: *const i32) -> int32x4x4_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmullu.v8i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.umull.v8i8")] - fn vmull_u8_(a: uint8x8_t, b: uint8x8_t) -> uint16x8_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4.v4i32.p0i8")] + fn vld4q_s32_(ptr: *const i8, size: i32) -> int32x4x4_t; } -vmull_u8_(a, b) +vld4q_s32_(a as *const i8, 4) } -/// Unsigned multiply long +/// Load multiple 4-element structures to four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmull.u16"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull))] -pub unsafe fn vmull_u16(a: uint16x4_t, b: uint16x4_t) -> uint32x4_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +pub unsafe fn vld4q_s32(a: *const i32) -> int32x4x4_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmullu.v4i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.umull.v4i16")] - fn vmull_u16_(a: uint16x4_t, b: uint16x4_t) -> uint32x4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4.v4i32.p0v4i32")] + fn vld4q_s32_(ptr: *const int32x4_t) -> int32x4x4_t; } -vmull_u16_(a, b) +vld4q_s32_(a.cast()) } -/// Unsigned multiply long +/// Load multiple 4-element structures to four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmull.u32"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull))] -pub unsafe fn vmull_u32(a: uint32x2_t, b: uint32x2_t) -> uint64x2_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +pub unsafe fn vld4_s64(a: *const i64) -> int64x1x4_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmullu.v2i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.umull.v2i32")] - fn vmull_u32_(a: uint32x2_t, b: uint32x2_t) -> uint64x2_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4.v1i64.p0i8")] + fn vld4_s64_(ptr: *const i8, size: i32) -> int64x1x4_t; } -vmull_u32_(a, b) +vld4_s64_(a as *const i8, 8) } -/// Polynomial multiply long +/// Load multiple 4-element structures to four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmull.p8"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(pmull))] -pub unsafe fn vmull_p8(a: poly8x8_t, b: poly8x8_t) -> poly16x8_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vld4_s64(a: *const i64) -> int64x1x4_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmullp.v8i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.pmull.v8i8")] - fn vmull_p8_(a: poly8x8_t, b: poly8x8_t) -> poly16x8_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4.v1i64.p0v1i64")] + fn vld4_s64_(ptr: *const int64x1_t) -> int64x1x4_t; } -vmull_p8_(a, b) +vld4_s64_(a.cast()) } -/// Vector long multiply with scalar +/// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull))] -pub unsafe fn vmull_n_s16(a: int16x4_t, b: i16) -> int32x4_t { - vmull_s16(a, vdup_n_s16(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +pub unsafe fn vld4_u8(a: *const u8) -> uint8x8x4_t { + transmute(vld4_s8(transmute(a))) } -/// Vector long multiply with scalar +/// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull))] -pub unsafe fn vmull_n_s32(a: int32x2_t, b: i32) -> int64x2_t { - vmull_s32(a, vdup_n_s32(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +pub unsafe fn vld4_u16(a: *const u16) -> uint16x4x4_t { + transmute(vld4_s16(transmute(a))) } -/// Vector long multiply with scalar +/// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull))] -pub unsafe fn vmull_n_u16(a: uint16x4_t, b: u16) -> uint32x4_t { - vmull_u16(a, vdup_n_u16(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +pub unsafe fn vld4_u32(a: *const u32) -> uint32x2x4_t { + transmute(vld4_s32(transmute(a))) } -/// Vector long multiply with scalar +/// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull))] -pub unsafe fn vmull_n_u32(a: uint32x2_t, b: u32) -> uint64x2_t { - vmull_u32(a, vdup_n_u32(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +pub unsafe fn vld4q_u8(a: *const u8) -> uint8x16x4_t { + transmute(vld4q_s8(transmute(a))) } -/// Vector long multiply by scalar +/// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull, LANE = 1))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vmull_lane_s16(a: int16x4_t, b: int16x4_t) -> int32x4_t { - static_assert_imm2!(LANE); - vmull_s16(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +pub unsafe fn vld4q_u16(a: *const u16) -> uint16x8x4_t { + transmute(vld4q_s16(transmute(a))) } -/// Vector long multiply by scalar +/// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull, LANE = 1))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vmull_laneq_s16(a: int16x4_t, b: int16x8_t) -> int32x4_t { - static_assert_imm3!(LANE); - vmull_s16(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +pub unsafe fn vld4q_u32(a: *const u32) -> uint32x4x4_t { + transmute(vld4q_s32(transmute(a))) } -/// Vector long multiply by scalar +/// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull, LANE = 1))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vmull_lane_s32(a: int32x2_t, b: int32x2_t) -> int64x2_t { - static_assert_imm1!(LANE); - vmull_s32(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +pub unsafe fn vld4_p8(a: *const p8) -> poly8x8x4_t { + transmute(vld4_s8(transmute(a))) } -/// Vector long multiply by scalar +/// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull, LANE = 1))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vmull_laneq_s32(a: int32x2_t, b: int32x4_t) -> int64x2_t { - static_assert_imm2!(LANE); - vmull_s32(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +pub unsafe fn vld4_p16(a: *const p16) -> poly16x4x4_t { + transmute(vld4_s16(transmute(a))) } -/// Vector long multiply by scalar +/// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull, LANE = 1))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vmull_lane_u16(a: uint16x4_t, b: uint16x4_t) -> uint32x4_t { - static_assert_imm2!(LANE); - vmull_u16(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +pub unsafe fn vld4q_p8(a: *const p8) -> poly8x16x4_t { + transmute(vld4q_s8(transmute(a))) } -/// Vector long multiply by scalar +/// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull, LANE = 1))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vmull_laneq_u16(a: uint16x4_t, b: uint16x8_t) -> uint32x4_t { - static_assert_imm3!(LANE); - vmull_u16(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +pub unsafe fn vld4q_p16(a: *const p16) -> poly16x8x4_t { + transmute(vld4q_s16(transmute(a))) } -/// Vector long multiply by scalar +/// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull, LANE = 1))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vmull_lane_u32(a: uint32x2_t, b: uint32x2_t) -> uint64x2_t { - static_assert_imm1!(LANE); - vmull_u32(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vld4_u64(a: *const u64) -> uint64x1x4_t { + transmute(vld4_s64(transmute(a))) } -/// Vector long multiply by scalar +/// Load multiple 4-element structures to four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull, LANE = 1))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vmull_laneq_u32(a: uint32x2_t, b: uint32x4_t) -> uint64x2_t { - static_assert_imm2!(LANE); - vmull_u32(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vld4_p64(a: *const p64) -> poly64x1x4_t { + transmute(vld4_s64(transmute(a))) } -/// Floating-point fused Multiply-Add to accumulator(vector) +/// Load multiple 4-element structures to four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "vfp4"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vfma))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmla))] -pub unsafe fn vfma_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +pub unsafe fn vld4_f32(a: *const f32) -> float32x2x4_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.fma.v2f32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.fma.v2f32")] - fn vfma_f32_(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4.v2f32.p0i8")] + fn vld4_f32_(ptr: *const i8, size: i32) -> float32x2x4_t; } -vfma_f32_(b, c, a) +vld4_f32_(a as *const i8, 4) } -/// Floating-point fused Multiply-Add to accumulator(vector) +/// Load multiple 4-element structures to four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "vfp4"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vfma))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmla))] -pub unsafe fn vfmaq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +pub unsafe fn vld4_f32(a: *const f32) -> float32x2x4_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.fma.v4f32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.fma.v4f32")] - fn vfmaq_f32_(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4.v2f32.p0v2f32")] + fn vld4_f32_(ptr: *const float32x2_t) -> float32x2x4_t; } -vfmaq_f32_(b, c, a) +vld4_f32_(a.cast()) } -/// Floating-point fused Multiply-Add to accumulator(vector) +/// Load multiple 4-element structures to four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "vfp4"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vfma))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmla))] -pub unsafe fn vfma_n_f32(a: float32x2_t, b: float32x2_t, c: f32) -> float32x2_t { - vfma_f32(a, b, vdup_n_f32_vfp4(c)) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +pub unsafe fn vld4q_f32(a: *const f32) -> float32x4x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4.v4f32.p0i8")] + fn vld4q_f32_(ptr: *const i8, size: i32) -> float32x4x4_t; + } +vld4q_f32_(a as *const i8, 4) } -/// Floating-point fused Multiply-Add to accumulator(vector) +/// Load multiple 4-element structures to four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "vfp4"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vfma))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmla))] -pub unsafe fn vfmaq_n_f32(a: float32x4_t, b: float32x4_t, c: f32) -> float32x4_t { - vfmaq_f32(a, b, vdupq_n_f32_vfp4(c)) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +pub unsafe fn vld4q_f32(a: *const f32) -> float32x4x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4.v4f32.p0v4f32")] + fn vld4q_f32_(ptr: *const float32x4_t) -> float32x4x4_t; + } +vld4q_f32_(a.cast()) } -/// Floating-point fused multiply-subtract from accumulator +/// Load single 4-element structure and replicate to all lanes of four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "vfp4"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vfms))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmls))] -pub unsafe fn vfms_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t { - let b: float32x2_t = simd_neg(b); - vfma_f32(a, b, c) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +pub unsafe fn vld4_dup_s8(a: *const i8) -> int8x8x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4dup.v8i8.p0i8")] + fn vld4_dup_s8_(ptr: *const i8, size: i32) -> int8x8x4_t; + } +vld4_dup_s8_(a as *const i8, 1) } -/// Floating-point fused multiply-subtract from accumulator +/// Load single 4-element structure and replicate to all lanes of four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "vfp4"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vfms))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmls))] -pub unsafe fn vfmsq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t { - let b: float32x4_t = simd_neg(b); - vfmaq_f32(a, b, c) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +pub unsafe fn vld4_dup_s8(a: *const i8) -> int8x8x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4r.v8i8.p0i8")] + fn vld4_dup_s8_(ptr: *const i8) -> int8x8x4_t; + } +vld4_dup_s8_(a.cast()) } -/// Floating-point fused Multiply-subtract to accumulator(vector) +/// Load single 4-element structure and replicate to all lanes of four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "vfp4"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vfms))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmls))] -pub unsafe fn vfms_n_f32(a: float32x2_t, b: float32x2_t, c: f32) -> float32x2_t { - vfms_f32(a, b, vdup_n_f32_vfp4(c)) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +pub unsafe fn vld4_dup_s16(a: *const i16) -> int16x4x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4dup.v4i16.p0i8")] + fn vld4_dup_s16_(ptr: *const i8, size: i32) -> int16x4x4_t; + } +vld4_dup_s16_(a as *const i8, 2) } -/// Floating-point fused Multiply-subtract to accumulator(vector) +/// Load single 4-element structure and replicate to all lanes of four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "vfp4"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vfms))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmls))] -pub unsafe fn vfmsq_n_f32(a: float32x4_t, b: float32x4_t, c: f32) -> float32x4_t { - vfmsq_f32(a, b, vdupq_n_f32_vfp4(c)) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +pub unsafe fn vld4_dup_s16(a: *const i16) -> int16x4x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4r.v4i16.p0i16")] + fn vld4_dup_s16_(ptr: *const i16) -> int16x4x4_t; + } +vld4_dup_s16_(a.cast()) } -/// Subtract +/// Load single 4-element structure and replicate to all lanes of four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i8"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] -pub unsafe fn vsub_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { - simd_sub(a, b) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +pub unsafe fn vld4_dup_s32(a: *const i32) -> int32x2x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4dup.v2i32.p0i8")] + fn vld4_dup_s32_(ptr: *const i8, size: i32) -> int32x2x4_t; + } +vld4_dup_s32_(a as *const i8, 4) } -/// Subtract +/// Load single 4-element structure and replicate to all lanes of four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i8"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] -pub unsafe fn vsubq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { - simd_sub(a, b) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +pub unsafe fn vld4_dup_s32(a: *const i32) -> int32x2x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4r.v2i32.p0i32")] + fn vld4_dup_s32_(ptr: *const i32) -> int32x2x4_t; + } +vld4_dup_s32_(a.cast()) } -/// Subtract +/// Load single 4-element structure and replicate to all lanes of four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i16"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] -pub unsafe fn vsub_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { - simd_sub(a, b) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +pub unsafe fn vld4q_dup_s8(a: *const i8) -> int8x16x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4dup.v16i8.p0i8")] + fn vld4q_dup_s8_(ptr: *const i8, size: i32) -> int8x16x4_t; + } +vld4q_dup_s8_(a as *const i8, 1) } -/// Subtract +/// Load single 4-element structure and replicate to all lanes of four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i16"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] -pub unsafe fn vsubq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { - simd_sub(a, b) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +pub unsafe fn vld4q_dup_s8(a: *const i8) -> int8x16x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4r.v16i8.p0i8")] + fn vld4q_dup_s8_(ptr: *const i8) -> int8x16x4_t; + } +vld4q_dup_s8_(a.cast()) } -/// Subtract +/// Load single 4-element structure and replicate to all lanes of four registers +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +pub unsafe fn vld4q_dup_s16(a: *const i16) -> int16x8x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4dup.v8i16.p0i8")] + fn vld4q_dup_s16_(ptr: *const i8, size: i32) -> int16x8x4_t; + } +vld4q_dup_s16_(a as *const i8, 2) +} + +/// Load single 4-element structure and replicate to all lanes of four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i32"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] -pub unsafe fn vsub_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { - simd_sub(a, b) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +pub unsafe fn vld4q_dup_s16(a: *const i16) -> int16x8x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4r.v8i16.p0i16")] + fn vld4q_dup_s16_(ptr: *const i16) -> int16x8x4_t; + } +vld4q_dup_s16_(a.cast()) } -/// Subtract +/// Load single 4-element structure and replicate to all lanes of four registers +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +pub unsafe fn vld4q_dup_s32(a: *const i32) -> int32x4x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4dup.v4i32.p0i8")] + fn vld4q_dup_s32_(ptr: *const i8, size: i32) -> int32x4x4_t; + } +vld4q_dup_s32_(a as *const i8, 4) +} + +/// Load single 4-element structure and replicate to all lanes of four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i32"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] -pub unsafe fn vsubq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { - simd_sub(a, b) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +pub unsafe fn vld4q_dup_s32(a: *const i32) -> int32x4x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4r.v4i32.p0i32")] + fn vld4q_dup_s32_(ptr: *const i32) -> int32x4x4_t; + } +vld4q_dup_s32_(a.cast()) } -/// Subtract +/// Load single 4-element structure and replicate to all lanes of four registers +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +pub unsafe fn vld4_dup_s64(a: *const i64) -> int64x1x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4dup.v1i64.p0i8")] + fn vld4_dup_s64_(ptr: *const i8, size: i32) -> int64x1x4_t; + } +vld4_dup_s64_(a as *const i8, 8) +} + +/// Load single 4-element structure and replicate to all lanes of four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i8"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] -pub unsafe fn vsub_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { - simd_sub(a, b) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +pub unsafe fn vld4_dup_s64(a: *const i64) -> int64x1x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4r.v1i64.p0i64")] + fn vld4_dup_s64_(ptr: *const i64) -> int64x1x4_t; + } +vld4_dup_s64_(a.cast()) } -/// Subtract +/// Load single 4-element structure and replicate to all lanes of four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i8"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] -pub unsafe fn vsubq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { - simd_sub(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +pub unsafe fn vld4_dup_u8(a: *const u8) -> uint8x8x4_t { + transmute(vld4_dup_s8(transmute(a))) } -/// Subtract +/// Load single 4-element structure and replicate to all lanes of four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i16"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] -pub unsafe fn vsub_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { - simd_sub(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +pub unsafe fn vld4_dup_u16(a: *const u16) -> uint16x4x4_t { + transmute(vld4_dup_s16(transmute(a))) } -/// Subtract +/// Load single 4-element structure and replicate to all lanes of four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i16"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] -pub unsafe fn vsubq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { - simd_sub(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +pub unsafe fn vld4_dup_u32(a: *const u32) -> uint32x2x4_t { + transmute(vld4_dup_s32(transmute(a))) } -/// Subtract +/// Load single 4-element structure and replicate to all lanes of four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i32"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] -pub unsafe fn vsub_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { - simd_sub(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +pub unsafe fn vld4q_dup_u8(a: *const u8) -> uint8x16x4_t { + transmute(vld4q_dup_s8(transmute(a))) } -/// Subtract +/// Load single 4-element structure and replicate to all lanes of four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i32"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] -pub unsafe fn vsubq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { - simd_sub(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +pub unsafe fn vld4q_dup_u16(a: *const u16) -> uint16x8x4_t { + transmute(vld4q_dup_s16(transmute(a))) } -/// Subtract +/// Load single 4-element structure and replicate to all lanes of four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i64"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] -pub unsafe fn vsub_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { - simd_sub(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +pub unsafe fn vld4q_dup_u32(a: *const u32) -> uint32x4x4_t { + transmute(vld4q_dup_s32(transmute(a))) } -/// Subtract +/// Load single 4-element structure and replicate to all lanes of four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i64"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] -pub unsafe fn vsubq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { - simd_sub(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +pub unsafe fn vld4_dup_p8(a: *const p8) -> poly8x8x4_t { + transmute(vld4_dup_s8(transmute(a))) } -/// Subtract +/// Load single 4-element structure and replicate to all lanes of four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i64"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] -pub unsafe fn vsub_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { - simd_sub(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +pub unsafe fn vld4_dup_p16(a: *const p16) -> poly16x4x4_t { + transmute(vld4_dup_s16(transmute(a))) } -/// Subtract +/// Load single 4-element structure and replicate to all lanes of four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i64"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] -pub unsafe fn vsubq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { - simd_sub(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +pub unsafe fn vld4q_dup_p8(a: *const p8) -> poly8x16x4_t { + transmute(vld4q_dup_s8(transmute(a))) } -/// Subtract +/// Load single 4-element structure and replicate to all lanes of four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.f32"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fsub))] -pub unsafe fn vsub_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { - simd_sub(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +pub unsafe fn vld4q_dup_p16(a: *const p16) -> poly16x8x4_t { + transmute(vld4q_dup_s16(transmute(a))) } -/// Subtract +/// Load single 4-element structure and replicate to all lanes of four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.f32"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fsub))] -pub unsafe fn vsubq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { - simd_sub(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +pub unsafe fn vld4_dup_u64(a: *const u64) -> uint64x1x4_t { + transmute(vld4_dup_s64(transmute(a))) } -/// Subtract returning high narrow +/// Load single 4-element structure and replicate to all lanes of four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn))] -pub unsafe fn vsubhn_s16(a: int16x8_t, b: int16x8_t) -> int8x8_t { - let c: i16x8 = i16x8::new(8, 8, 8, 8, 8, 8, 8, 8); - simd_cast(simd_shr(simd_sub(a, b), transmute(c))) +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +pub unsafe fn vld4_dup_p64(a: *const p64) -> poly64x1x4_t { + transmute(vld4_dup_s64(transmute(a))) } -/// Subtract returning high narrow +/// Load single 4-element structure and replicate to all lanes of four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn))] -pub unsafe fn vsubhn_s32(a: int32x4_t, b: int32x4_t) -> int16x4_t { - let c: i32x4 = i32x4::new(16, 16, 16, 16); - simd_cast(simd_shr(simd_sub(a, b), transmute(c))) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +pub unsafe fn vld4_dup_f32(a: *const f32) -> float32x2x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4dup.v2f32.p0i8")] + fn vld4_dup_f32_(ptr: *const i8, size: i32) -> float32x2x4_t; + } +vld4_dup_f32_(a as *const i8, 4) } -/// Subtract returning high narrow +/// Load single 4-element structure and replicate to all lanes of four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn))] -pub unsafe fn vsubhn_s64(a: int64x2_t, b: int64x2_t) -> int32x2_t { - let c: i64x2 = i64x2::new(32, 32); - simd_cast(simd_shr(simd_sub(a, b), transmute(c))) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +pub unsafe fn vld4_dup_f32(a: *const f32) -> float32x2x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4r.v2f32.p0f32")] + fn vld4_dup_f32_(ptr: *const f32) -> float32x2x4_t; + } +vld4_dup_f32_(a.cast()) } -/// Subtract returning high narrow +/// Load single 4-element structure and replicate to all lanes of four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn))] -pub unsafe fn vsubhn_u16(a: uint16x8_t, b: uint16x8_t) -> uint8x8_t { - let c: u16x8 = u16x8::new(8, 8, 8, 8, 8, 8, 8, 8); - simd_cast(simd_shr(simd_sub(a, b), transmute(c))) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +pub unsafe fn vld4q_dup_f32(a: *const f32) -> float32x4x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4dup.v4f32.p0i8")] + fn vld4q_dup_f32_(ptr: *const i8, size: i32) -> float32x4x4_t; + } +vld4q_dup_f32_(a as *const i8, 4) } -/// Subtract returning high narrow +/// Load single 4-element structure and replicate to all lanes of four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn))] -pub unsafe fn vsubhn_u32(a: uint32x4_t, b: uint32x4_t) -> uint16x4_t { - let c: u32x4 = u32x4::new(16, 16, 16, 16); - simd_cast(simd_shr(simd_sub(a, b), transmute(c))) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +pub unsafe fn vld4q_dup_f32(a: *const f32) -> float32x4x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4r.v4f32.p0f32")] + fn vld4q_dup_f32_(ptr: *const f32) -> float32x4x4_t; + } +vld4q_dup_f32_(a.cast()) } -/// Subtract returning high narrow +/// Load multiple 4-element structures to four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn))] -pub unsafe fn vsubhn_u64(a: uint64x2_t, b: uint64x2_t) -> uint32x2_t { - let c: u64x2 = u64x2::new(32, 32); - simd_cast(simd_shr(simd_sub(a, b), transmute(c))) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld4_lane_s8(a: *const i8, b: int8x8x4_t) -> int8x8x4_t { + static_assert_imm3!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4lane.v8i8.p0i8")] + fn vld4_lane_s8_(ptr: *const i8, a: int8x8_t, b: int8x8_t, c: int8x8_t, d: int8x8_t, n: i32, size: i32) -> int8x8x4_t; + } +vld4_lane_s8_(a.cast(), b.0, b.1, b.2, b.3, LANE, 1) } -/// Subtract returning high narrow +/// Load multiple 4-element structures to four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn2))] -pub unsafe fn vsubhn_high_s16(a: int8x8_t, b: int16x8_t, c: int16x8_t) -> int8x16_t { - let d: int8x8_t = vsubhn_s16(b, c); - simd_shuffle16!(a, d, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld4_lane_s8(a: *const i8, b: int8x8x4_t) -> int8x8x4_t { + static_assert_imm3!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4lane.v8i8.p0i8")] + fn vld4_lane_s8_(a: int8x8_t, b: int8x8_t, c: int8x8_t, d: int8x8_t, n: i64, ptr: *const i8) -> int8x8x4_t; + } +vld4_lane_s8_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) } -/// Subtract returning high narrow +/// Load multiple 4-element structures to four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn2))] -pub unsafe fn vsubhn_high_s32(a: int16x4_t, b: int32x4_t, c: int32x4_t) -> int16x8_t { - let d: int16x4_t = vsubhn_s32(b, c); - simd_shuffle8!(a, d, [0, 1, 2, 3, 4, 5, 6, 7]) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld4_lane_s16(a: *const i16, b: int16x4x4_t) -> int16x4x4_t { + static_assert_imm2!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4lane.v4i16.p0i8")] + fn vld4_lane_s16_(ptr: *const i8, a: int16x4_t, b: int16x4_t, c: int16x4_t, d: int16x4_t, n: i32, size: i32) -> int16x4x4_t; + } +vld4_lane_s16_(a.cast(), b.0, b.1, b.2, b.3, LANE, 2) } -/// Subtract returning high narrow +/// Load multiple 4-element structures to four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn2))] -pub unsafe fn vsubhn_high_s64(a: int32x2_t, b: int64x2_t, c: int64x2_t) -> int32x4_t { - let d: int32x2_t = vsubhn_s64(b, c); - simd_shuffle4!(a, d, [0, 1, 2, 3]) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld4_lane_s16(a: *const i16, b: int16x4x4_t) -> int16x4x4_t { + static_assert_imm2!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4lane.v4i16.p0i8")] + fn vld4_lane_s16_(a: int16x4_t, b: int16x4_t, c: int16x4_t, d: int16x4_t, n: i64, ptr: *const i8) -> int16x4x4_t; + } +vld4_lane_s16_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) } -/// Subtract returning high narrow +/// Load multiple 4-element structures to four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn2))] -pub unsafe fn vsubhn_high_u16(a: uint8x8_t, b: uint16x8_t, c: uint16x8_t) -> uint8x16_t { - let d: uint8x8_t = vsubhn_u16(b, c); - simd_shuffle16!(a, d, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld4_lane_s32(a: *const i32, b: int32x2x4_t) -> int32x2x4_t { + static_assert_imm1!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4lane.v2i32.p0i8")] + fn vld4_lane_s32_(ptr: *const i8, a: int32x2_t, b: int32x2_t, c: int32x2_t, d: int32x2_t, n: i32, size: i32) -> int32x2x4_t; + } +vld4_lane_s32_(a.cast(), b.0, b.1, b.2, b.3, LANE, 4) } -/// Subtract returning high narrow +/// Load multiple 4-element structures to four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn2))] -pub unsafe fn vsubhn_high_u32(a: uint16x4_t, b: uint32x4_t, c: uint32x4_t) -> uint16x8_t { - let d: uint16x4_t = vsubhn_u32(b, c); - simd_shuffle8!(a, d, [0, 1, 2, 3, 4, 5, 6, 7]) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld4_lane_s32(a: *const i32, b: int32x2x4_t) -> int32x2x4_t { + static_assert_imm1!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4lane.v2i32.p0i8")] + fn vld4_lane_s32_(a: int32x2_t, b: int32x2_t, c: int32x2_t, d: int32x2_t, n: i64, ptr: *const i8) -> int32x2x4_t; + } +vld4_lane_s32_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) } -/// Subtract returning high narrow +/// Load multiple 4-element structures to four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn2))] -pub unsafe fn vsubhn_high_u64(a: uint32x2_t, b: uint64x2_t, c: uint64x2_t) -> uint32x4_t { - let d: uint32x2_t = vsubhn_u64(b, c); - simd_shuffle4!(a, d, [0, 1, 2, 3]) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld4q_lane_s16(a: *const i16, b: int16x8x4_t) -> int16x8x4_t { + static_assert_imm3!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4lane.v8i16.p0i8")] + fn vld4q_lane_s16_(ptr: *const i8, a: int16x8_t, b: int16x8_t, c: int16x8_t, d: int16x8_t, n: i32, size: i32) -> int16x8x4_t; + } +vld4q_lane_s16_(a.cast(), b.0, b.1, b.2, b.3, LANE, 2) } -/// Signed halving subtract +/// Load multiple 4-element structures to four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.u8"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhsub))] -pub unsafe fn vhsub_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld4q_lane_s16(a: *const i16, b: int16x8x4_t) -> int16x8x4_t { + static_assert_imm3!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhsubu.v8i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uhsub.v8i8")] - fn vhsub_u8_(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4lane.v8i16.p0i8")] + fn vld4q_lane_s16_(a: int16x8_t, b: int16x8_t, c: int16x8_t, d: int16x8_t, n: i64, ptr: *const i8) -> int16x8x4_t; } -vhsub_u8_(a, b) +vld4q_lane_s16_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) } -/// Signed halving subtract +/// Load multiple 4-element structures to four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.u8"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhsub))] -pub unsafe fn vhsubq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld4q_lane_s32(a: *const i32, b: int32x4x4_t) -> int32x4x4_t { + static_assert_imm2!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhsubu.v16i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uhsub.v16i8")] - fn vhsubq_u8_(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4lane.v4i32.p0i8")] + fn vld4q_lane_s32_(ptr: *const i8, a: int32x4_t, b: int32x4_t, c: int32x4_t, d: int32x4_t, n: i32, size: i32) -> int32x4x4_t; } -vhsubq_u8_(a, b) +vld4q_lane_s32_(a.cast(), b.0, b.1, b.2, b.3, LANE, 4) } -/// Signed halving subtract +/// Load multiple 4-element structures to four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.u16"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhsub))] -pub unsafe fn vhsub_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld4q_lane_s32(a: *const i32, b: int32x4x4_t) -> int32x4x4_t { + static_assert_imm2!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhsubu.v4i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uhsub.v4i16")] - fn vhsub_u16_(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4lane.v4i32.p0i8")] + fn vld4q_lane_s32_(a: int32x4_t, b: int32x4_t, c: int32x4_t, d: int32x4_t, n: i64, ptr: *const i8) -> int32x4x4_t; } -vhsub_u16_(a, b) +vld4q_lane_s32_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) } -/// Signed halving subtract +/// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.u16"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhsub))] -pub unsafe fn vhsubq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhsubu.v8i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uhsub.v8i16")] - fn vhsubq_u16_(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t; - } -vhsubq_u16_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld4_lane_u8(a: *const u8, b: uint8x8x4_t) -> uint8x8x4_t { + static_assert_imm3!(LANE); + transmute(vld4_lane_s8::(transmute(a), transmute(b))) } -/// Signed halving subtract +/// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.u32"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhsub))] -pub unsafe fn vhsub_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhsubu.v2i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uhsub.v2i32")] - fn vhsub_u32_(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t; - } -vhsub_u32_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld4_lane_u16(a: *const u16, b: uint16x4x4_t) -> uint16x4x4_t { + static_assert_imm2!(LANE); + transmute(vld4_lane_s16::(transmute(a), transmute(b))) } -/// Signed halving subtract +/// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.u32"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhsub))] -pub unsafe fn vhsubq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhsubu.v4i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uhsub.v4i32")] - fn vhsubq_u32_(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t; - } -vhsubq_u32_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld4_lane_u32(a: *const u32, b: uint32x2x4_t) -> uint32x2x4_t { + static_assert_imm1!(LANE); + transmute(vld4_lane_s32::(transmute(a), transmute(b))) } -/// Signed halving subtract +/// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.s8"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shsub))] -pub unsafe fn vhsub_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhsubs.v8i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.shsub.v8i8")] - fn vhsub_s8_(a: int8x8_t, b: int8x8_t) -> int8x8_t; - } -vhsub_s8_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld4q_lane_u16(a: *const u16, b: uint16x8x4_t) -> uint16x8x4_t { + static_assert_imm3!(LANE); + transmute(vld4q_lane_s16::(transmute(a), transmute(b))) } -/// Signed halving subtract +/// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.s8"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shsub))] -pub unsafe fn vhsubq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhsubs.v16i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.shsub.v16i8")] - fn vhsubq_s8_(a: int8x16_t, b: int8x16_t) -> int8x16_t; - } -vhsubq_s8_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld4q_lane_u32(a: *const u32, b: uint32x4x4_t) -> uint32x4x4_t { + static_assert_imm2!(LANE); + transmute(vld4q_lane_s32::(transmute(a), transmute(b))) } -/// Signed halving subtract +/// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.s16"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shsub))] -pub unsafe fn vhsub_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhsubs.v4i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.shsub.v4i16")] - fn vhsub_s16_(a: int16x4_t, b: int16x4_t) -> int16x4_t; - } -vhsub_s16_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld4_lane_p8(a: *const p8, b: poly8x8x4_t) -> poly8x8x4_t { + static_assert_imm3!(LANE); + transmute(vld4_lane_s8::(transmute(a), transmute(b))) } -/// Signed halving subtract +/// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.s16"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shsub))] -pub unsafe fn vhsubq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld4_lane_p16(a: *const p16, b: poly16x4x4_t) -> poly16x4x4_t { + static_assert_imm2!(LANE); + transmute(vld4_lane_s16::(transmute(a), transmute(b))) +} + +/// Load multiple 4-element structures to four registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld4q_lane_p16(a: *const p16, b: poly16x8x4_t) -> poly16x8x4_t { + static_assert_imm3!(LANE); + transmute(vld4q_lane_s16::(transmute(a), transmute(b))) +} + +/// Load multiple 4-element structures to four registers +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld4_lane_f32(a: *const f32, b: float32x2x4_t) -> float32x2x4_t { + static_assert_imm1!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhsubs.v8i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.shsub.v8i16")] - fn vhsubq_s16_(a: int16x8_t, b: int16x8_t) -> int16x8_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4lane.v2f32.p0i8")] + fn vld4_lane_f32_(ptr: *const i8, a: float32x2_t, b: float32x2_t, c: float32x2_t, d: float32x2_t, n: i32, size: i32) -> float32x2x4_t; } -vhsubq_s16_(a, b) +vld4_lane_f32_(a.cast(), b.0, b.1, b.2, b.3, LANE, 4) } -/// Signed halving subtract +/// Load multiple 4-element structures to four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.s32"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shsub))] -pub unsafe fn vhsub_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld4_lane_f32(a: *const f32, b: float32x2x4_t) -> float32x2x4_t { + static_assert_imm1!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhsubs.v2i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.shsub.v2i32")] - fn vhsub_s32_(a: int32x2_t, b: int32x2_t) -> int32x2_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4lane.v2f32.p0i8")] + fn vld4_lane_f32_(a: float32x2_t, b: float32x2_t, c: float32x2_t, d: float32x2_t, n: i64, ptr: *const i8) -> float32x2x4_t; } -vhsub_s32_(a, b) +vld4_lane_f32_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) } -/// Signed halving subtract +/// Load multiple 4-element structures to four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.s32"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shsub))] -pub unsafe fn vhsubq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld4q_lane_f32(a: *const f32, b: float32x4x4_t) -> float32x4x4_t { + static_assert_imm2!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhsubs.v4i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.shsub.v4i32")] - fn vhsubq_s32_(a: int32x4_t, b: int32x4_t) -> int32x4_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4lane.v4f32.p0i8")] + fn vld4q_lane_f32_(ptr: *const i8, a: float32x4_t, b: float32x4_t, c: float32x4_t, d: float32x4_t, n: i32, size: i32) -> float32x4x4_t; } -vhsubq_s32_(a, b) +vld4q_lane_f32_(a.cast(), b.0, b.1, b.2, b.3, LANE, 4) } -/// Signed Subtract Wide +/// Load multiple 4-element structures to four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubw))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssubw))] -pub unsafe fn vsubw_s8(a: int16x8_t, b: int8x8_t) -> int16x8_t { - simd_sub(a, simd_cast(b)) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vld4q_lane_f32(a: *const f32, b: float32x4x4_t) -> float32x4x4_t { + static_assert_imm2!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4lane.v4f32.p0i8")] + fn vld4q_lane_f32_(a: float32x4_t, b: float32x4_t, c: float32x4_t, d: float32x4_t, n: i64, ptr: *const i8) -> float32x4x4_t; + } +vld4q_lane_f32_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) } -/// Signed Subtract Wide +/// Store multiple single-element structures from one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubw))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssubw))] -pub unsafe fn vsubw_s16(a: int32x4_t, b: int16x4_t) -> int32x4_t { - simd_sub(a, simd_cast(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst1_lane_s8(a: *mut i8, b: int8x8_t) { + static_assert_imm3!(LANE); + *a = simd_extract(b, LANE as u32); } -/// Signed Subtract Wide +/// Store multiple single-element structures from one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubw))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssubw))] -pub unsafe fn vsubw_s32(a: int64x2_t, b: int32x2_t) -> int64x2_t { - simd_sub(a, simd_cast(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst1_lane_s16(a: *mut i16, b: int16x4_t) { + static_assert_imm2!(LANE); + *a = simd_extract(b, LANE as u32); } -/// Unsigned Subtract Wide +/// Store multiple single-element structures from one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubw))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usubw))] -pub unsafe fn vsubw_u8(a: uint16x8_t, b: uint8x8_t) -> uint16x8_t { - simd_sub(a, simd_cast(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst1_lane_s32(a: *mut i32, b: int32x2_t) { + static_assert_imm1!(LANE); + *a = simd_extract(b, LANE as u32); } -/// Unsigned Subtract Wide +/// Store multiple single-element structures from one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubw))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usubw))] -pub unsafe fn vsubw_u16(a: uint32x4_t, b: uint16x4_t) -> uint32x4_t { - simd_sub(a, simd_cast(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst1_lane_s64(a: *mut i64, b: int64x1_t) { + static_assert!(LANE : i32 where LANE == 0); + *a = simd_extract(b, LANE as u32); } -/// Unsigned Subtract Wide +/// Store multiple single-element structures from one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubw))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usubw))] -pub unsafe fn vsubw_u32(a: uint64x2_t, b: uint32x2_t) -> uint64x2_t { - simd_sub(a, simd_cast(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst1q_lane_s8(a: *mut i8, b: int8x16_t) { + static_assert_imm4!(LANE); + *a = simd_extract(b, LANE as u32); } -/// Signed Subtract Long +/// Store multiple single-element structures from one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssubl))] -pub unsafe fn vsubl_s8(a: int8x8_t, b: int8x8_t) -> int16x8_t { - let c: int16x8_t = simd_cast(a); - let d: int16x8_t = simd_cast(b); - simd_sub(c, d) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst1q_lane_s16(a: *mut i16, b: int16x8_t) { + static_assert_imm3!(LANE); + *a = simd_extract(b, LANE as u32); } -/// Signed Subtract Long +/// Store multiple single-element structures from one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssubl))] -pub unsafe fn vsubl_s16(a: int16x4_t, b: int16x4_t) -> int32x4_t { - let c: int32x4_t = simd_cast(a); - let d: int32x4_t = simd_cast(b); - simd_sub(c, d) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst1q_lane_s32(a: *mut i32, b: int32x4_t) { + static_assert_imm2!(LANE); + *a = simd_extract(b, LANE as u32); } -/// Signed Subtract Long +/// Store multiple single-element structures from one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssubl))] -pub unsafe fn vsubl_s32(a: int32x2_t, b: int32x2_t) -> int64x2_t { - let c: int64x2_t = simd_cast(a); - let d: int64x2_t = simd_cast(b); - simd_sub(c, d) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst1q_lane_s64(a: *mut i64, b: int64x2_t) { + static_assert_imm1!(LANE); + *a = simd_extract(b, LANE as u32); } -/// Unsigned Subtract Long +/// Store multiple single-element structures from one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usubl))] -pub unsafe fn vsubl_u8(a: uint8x8_t, b: uint8x8_t) -> uint16x8_t { - let c: uint16x8_t = simd_cast(a); - let d: uint16x8_t = simd_cast(b); - simd_sub(c, d) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst1_lane_u8(a: *mut u8, b: uint8x8_t) { + static_assert_imm3!(LANE); + *a = simd_extract(b, LANE as u32); } -/// Unsigned Subtract Long +/// Store multiple single-element structures from one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usubl))] -pub unsafe fn vsubl_u16(a: uint16x4_t, b: uint16x4_t) -> uint32x4_t { - let c: uint32x4_t = simd_cast(a); - let d: uint32x4_t = simd_cast(b); - simd_sub(c, d) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst1_lane_u16(a: *mut u16, b: uint16x4_t) { + static_assert_imm2!(LANE); + *a = simd_extract(b, LANE as u32); } -/// Unsigned Subtract Long +/// Store multiple single-element structures from one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usubl))] -pub unsafe fn vsubl_u32(a: uint32x2_t, b: uint32x2_t) -> uint64x2_t { - let c: uint64x2_t = simd_cast(a); - let d: uint64x2_t = simd_cast(b); - simd_sub(c, d) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst1_lane_u32(a: *mut u32, b: uint32x2_t) { + static_assert_imm1!(LANE); + *a = simd_extract(b, LANE as u32); } -/// Maximum (vector) +/// Store multiple single-element structures from one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smax))] -pub unsafe fn vmax_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxs.v8i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.smax.v8i8")] - fn vmax_s8_(a: int8x8_t, b: int8x8_t) -> int8x8_t; - } -vmax_s8_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst1_lane_u64(a: *mut u64, b: uint64x1_t) { + static_assert!(LANE : i32 where LANE == 0); + *a = simd_extract(b, LANE as u32); } -/// Maximum (vector) +/// Store multiple single-element structures from one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smax))] -pub unsafe fn vmaxq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxs.v16i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.smax.v16i8")] - fn vmaxq_s8_(a: int8x16_t, b: int8x16_t) -> int8x16_t; - } -vmaxq_s8_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst1q_lane_u8(a: *mut u8, b: uint8x16_t) { + static_assert_imm4!(LANE); + *a = simd_extract(b, LANE as u32); } -/// Maximum (vector) +/// Store multiple single-element structures from one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smax))] -pub unsafe fn vmax_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxs.v4i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.smax.v4i16")] - fn vmax_s16_(a: int16x4_t, b: int16x4_t) -> int16x4_t; - } -vmax_s16_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst1q_lane_u16(a: *mut u16, b: uint16x8_t) { + static_assert_imm3!(LANE); + *a = simd_extract(b, LANE as u32); } -/// Maximum (vector) +/// Store multiple single-element structures from one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smax))] -pub unsafe fn vmaxq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxs.v8i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.smax.v8i16")] - fn vmaxq_s16_(a: int16x8_t, b: int16x8_t) -> int16x8_t; - } -vmaxq_s16_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst1q_lane_u32(a: *mut u32, b: uint32x4_t) { + static_assert_imm2!(LANE); + *a = simd_extract(b, LANE as u32); } -/// Maximum (vector) +/// Store multiple single-element structures from one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smax))] -pub unsafe fn vmax_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxs.v2i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.smax.v2i32")] - fn vmax_s32_(a: int32x2_t, b: int32x2_t) -> int32x2_t; - } -vmax_s32_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst1q_lane_u64(a: *mut u64, b: uint64x2_t) { + static_assert_imm1!(LANE); + *a = simd_extract(b, LANE as u32); } -/// Maximum (vector) +/// Store multiple single-element structures from one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smax))] -pub unsafe fn vmaxq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxs.v4i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.smax.v4i32")] - fn vmaxq_s32_(a: int32x4_t, b: int32x4_t) -> int32x4_t; - } -vmaxq_s32_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst1_lane_p8(a: *mut p8, b: poly8x8_t) { + static_assert_imm3!(LANE); + *a = simd_extract(b, LANE as u32); } -/// Maximum (vector) +/// Store multiple single-element structures from one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umax))] -pub unsafe fn vmax_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxu.v8i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.umax.v8i8")] - fn vmax_u8_(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t; - } -vmax_u8_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst1_lane_p16(a: *mut p16, b: poly16x4_t) { + static_assert_imm2!(LANE); + *a = simd_extract(b, LANE as u32); } -/// Maximum (vector) +/// Store multiple single-element structures from one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umax))] -pub unsafe fn vmaxq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxu.v16i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.umax.v16i8")] - fn vmaxq_u8_(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t; - } -vmaxq_u8_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst1q_lane_p8(a: *mut p8, b: poly8x16_t) { + static_assert_imm4!(LANE); + *a = simd_extract(b, LANE as u32); } -/// Maximum (vector) +/// Store multiple single-element structures from one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umax))] -pub unsafe fn vmax_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxu.v4i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.umax.v4i16")] - fn vmax_u16_(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t; - } -vmax_u16_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst1q_lane_p16(a: *mut p16, b: poly16x8_t) { + static_assert_imm3!(LANE); + *a = simd_extract(b, LANE as u32); } -/// Maximum (vector) +/// Store multiple single-element structures from one, two, three, or four registers +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst1_lane_p64(a: *mut p64, b: poly64x1_t) { + static_assert!(LANE : i32 where LANE == 0); + *a = simd_extract(b, LANE as u32); +} + +/// Store multiple single-element structures from one, two, three, or four registers +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst1q_lane_p64(a: *mut p64, b: poly64x2_t) { + static_assert_imm1!(LANE); + *a = simd_extract(b, LANE as u32); +} + +/// Store multiple single-element structures from one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umax))] -pub unsafe fn vmaxq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxu.v8i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.umax.v8i16")] - fn vmaxq_u16_(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t; - } -vmaxq_u16_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst1_lane_f32(a: *mut f32, b: float32x2_t) { + static_assert_imm1!(LANE); + *a = simd_extract(b, LANE as u32); } -/// Maximum (vector) +/// Store multiple single-element structures from one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umax))] -pub unsafe fn vmax_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst1q_lane_f32(a: *mut f32, b: float32x4_t) { + static_assert_imm2!(LANE); + *a = simd_extract(b, LANE as u32); +} + +/// Store multiple single-element structures from one, two, three, or four registers +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +pub unsafe fn vst1_s8_x2(a: *mut i8, b: int8x8x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxu.v2i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.umax.v2i32")] - fn vmax_u32_(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x2.p0i8.v8i8")] + fn vst1_s8_x2_(ptr: *mut i8, a: int8x8_t, b: int8x8_t); } -vmax_u32_(a, b) +vst1_s8_x2_(a, b.0, b.1) } -/// Maximum (vector) +/// Store multiple single-element structures from one, two, three, or four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umax))] -pub unsafe fn vmaxq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_s8_x2(a: *mut i8, b: int8x8x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxu.v4i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.umax.v4i32")] - fn vmaxq_u32_(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x2.v8i8.p0i8")] + fn vst1_s8_x2_(a: int8x8_t, b: int8x8_t, ptr: *mut i8); } -vmaxq_u32_(a, b) +vst1_s8_x2_(b.0, b.1, a) } -/// Maximum (vector) +/// Store multiple single-element structures from one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmax))] -pub unsafe fn vmax_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +pub unsafe fn vst1_s16_x2(a: *mut i16, b: int16x4x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxs.v2f32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmax.v2f32")] - fn vmax_f32_(a: float32x2_t, b: float32x2_t) -> float32x2_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x2.p0i16.v4i16")] + fn vst1_s16_x2_(ptr: *mut i16, a: int16x4_t, b: int16x4_t); } -vmax_f32_(a, b) +vst1_s16_x2_(a, b.0, b.1) } -/// Maximum (vector) +/// Store multiple single-element structures from one, two, three, or four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmax))] -pub unsafe fn vmaxq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_s16_x2(a: *mut i16, b: int16x4x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxs.v4f32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmax.v4f32")] - fn vmaxq_f32_(a: float32x4_t, b: float32x4_t) -> float32x4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x2.v4i16.p0i16")] + fn vst1_s16_x2_(a: int16x4_t, b: int16x4_t, ptr: *mut i16); } -vmaxq_f32_(a, b) +vst1_s16_x2_(b.0, b.1, a) } -/// Floating-point Maximun Number (vector) +/// Store multiple single-element structures from one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "fp-armv8,v8"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmaxnm))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmaxnm))] -pub unsafe fn vmaxnm_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +pub unsafe fn vst1_s32_x2(a: *mut i32, b: int32x2x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxnm.v2f32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmaxnm.v2f32")] - fn vmaxnm_f32_(a: float32x2_t, b: float32x2_t) -> float32x2_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x2.p0i32.v2i32")] + fn vst1_s32_x2_(ptr: *mut i32, a: int32x2_t, b: int32x2_t); } -vmaxnm_f32_(a, b) +vst1_s32_x2_(a, b.0, b.1) } -/// Floating-point Maximun Number (vector) +/// Store multiple single-element structures from one, two, three, or four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "fp-armv8,v8"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmaxnm))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmaxnm))] -pub unsafe fn vmaxnmq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_s32_x2(a: *mut i32, b: int32x2x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxnm.v4f32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmaxnm.v4f32")] - fn vmaxnmq_f32_(a: float32x4_t, b: float32x4_t) -> float32x4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x2.v2i32.p0i32")] + fn vst1_s32_x2_(a: int32x2_t, b: int32x2_t, ptr: *mut i32); } -vmaxnmq_f32_(a, b) +vst1_s32_x2_(b.0, b.1, a) } -/// Minimum (vector) +/// Store multiple single-element structures from one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smin))] -pub unsafe fn vmin_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +pub unsafe fn vst1_s64_x2(a: *mut i64, b: int64x1x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmins.v8i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.smin.v8i8")] - fn vmin_s8_(a: int8x8_t, b: int8x8_t) -> int8x8_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x2.p0i64.v1i64")] + fn vst1_s64_x2_(ptr: *mut i64, a: int64x1_t, b: int64x1_t); } -vmin_s8_(a, b) +vst1_s64_x2_(a, b.0, b.1) } -/// Minimum (vector) +/// Store multiple single-element structures from one, two, three, or four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smin))] -pub unsafe fn vminq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_s64_x2(a: *mut i64, b: int64x1x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmins.v16i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.smin.v16i8")] - fn vminq_s8_(a: int8x16_t, b: int8x16_t) -> int8x16_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x2.v1i64.p0i64")] + fn vst1_s64_x2_(a: int64x1_t, b: int64x1_t, ptr: *mut i64); } -vminq_s8_(a, b) +vst1_s64_x2_(b.0, b.1, a) } -/// Minimum (vector) +/// Store multiple single-element structures from one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smin))] -pub unsafe fn vmin_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +pub unsafe fn vst1q_s8_x2(a: *mut i8, b: int8x16x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmins.v4i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.smin.v4i16")] - fn vmin_s16_(a: int16x4_t, b: int16x4_t) -> int16x4_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x2.p0i8.v16i8")] + fn vst1q_s8_x2_(ptr: *mut i8, a: int8x16_t, b: int8x16_t); } -vmin_s16_(a, b) +vst1q_s8_x2_(a, b.0, b.1) } -/// Minimum (vector) +/// Store multiple single-element structures from one, two, three, or four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smin))] -pub unsafe fn vminq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_s8_x2(a: *mut i8, b: int8x16x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmins.v8i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.smin.v8i16")] - fn vminq_s16_(a: int16x8_t, b: int16x8_t) -> int16x8_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x2.v16i8.p0i8")] + fn vst1q_s8_x2_(a: int8x16_t, b: int8x16_t, ptr: *mut i8); } -vminq_s16_(a, b) +vst1q_s8_x2_(b.0, b.1, a) } -/// Minimum (vector) +/// Store multiple single-element structures from one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smin))] -pub unsafe fn vmin_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +pub unsafe fn vst1q_s16_x2(a: *mut i16, b: int16x8x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmins.v2i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.smin.v2i32")] - fn vmin_s32_(a: int32x2_t, b: int32x2_t) -> int32x2_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x2.p0i16.v8i16")] + fn vst1q_s16_x2_(ptr: *mut i16, a: int16x8_t, b: int16x8_t); } -vmin_s32_(a, b) +vst1q_s16_x2_(a, b.0, b.1) } -/// Minimum (vector) +/// Store multiple single-element structures from one, two, three, or four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smin))] -pub unsafe fn vminq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_s16_x2(a: *mut i16, b: int16x8x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmins.v4i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.smin.v4i32")] - fn vminq_s32_(a: int32x4_t, b: int32x4_t) -> int32x4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x2.v8i16.p0i16")] + fn vst1q_s16_x2_(a: int16x8_t, b: int16x8_t, ptr: *mut i16); } -vminq_s32_(a, b) +vst1q_s16_x2_(b.0, b.1, a) } -/// Minimum (vector) +/// Store multiple single-element structures from one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umin))] -pub unsafe fn vmin_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +pub unsafe fn vst1q_s32_x2(a: *mut i32, b: int32x4x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vminu.v8i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.umin.v8i8")] - fn vmin_u8_(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x2.p0i32.v4i32")] + fn vst1q_s32_x2_(ptr: *mut i32, a: int32x4_t, b: int32x4_t); } -vmin_u8_(a, b) +vst1q_s32_x2_(a, b.0, b.1) } -/// Minimum (vector) +/// Store multiple single-element structures from one, two, three, or four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umin))] -pub unsafe fn vminq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_s32_x2(a: *mut i32, b: int32x4x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vminu.v16i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.umin.v16i8")] - fn vminq_u8_(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x2.v4i32.p0i32")] + fn vst1q_s32_x2_(a: int32x4_t, b: int32x4_t, ptr: *mut i32); } -vminq_u8_(a, b) +vst1q_s32_x2_(b.0, b.1, a) } -/// Minimum (vector) +/// Store multiple single-element structures from one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umin))] -pub unsafe fn vmin_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +pub unsafe fn vst1q_s64_x2(a: *mut i64, b: int64x2x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vminu.v4i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.umin.v4i16")] - fn vmin_u16_(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x2.p0i64.v2i64")] + fn vst1q_s64_x2_(ptr: *mut i64, a: int64x2_t, b: int64x2_t); } -vmin_u16_(a, b) +vst1q_s64_x2_(a, b.0, b.1) } -/// Minimum (vector) +/// Store multiple single-element structures from one, two, three, or four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umin))] -pub unsafe fn vminq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_s64_x2(a: *mut i64, b: int64x2x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vminu.v8i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.umin.v8i16")] - fn vminq_u16_(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x2.v2i64.p0i64")] + fn vst1q_s64_x2_(a: int64x2_t, b: int64x2_t, ptr: *mut i64); } -vminq_u16_(a, b) +vst1q_s64_x2_(b.0, b.1, a) } -/// Minimum (vector) +/// Store multiple single-element structures from one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umin))] -pub unsafe fn vmin_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +pub unsafe fn vst1_s8_x3(a: *mut i8, b: int8x8x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vminu.v2i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.umin.v2i32")] - fn vmin_u32_(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x3.p0i8.v8i8")] + fn vst1_s8_x3_(ptr: *mut i8, a: int8x8_t, b: int8x8_t, c: int8x8_t); } -vmin_u32_(a, b) +vst1_s8_x3_(a, b.0, b.1, b.2) } -/// Minimum (vector) +/// Store multiple single-element structures from one, two, three, or four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umin))] -pub unsafe fn vminq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_s8_x3(a: *mut i8, b: int8x8x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vminu.v4i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.umin.v4i32")] - fn vminq_u32_(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x3.v8i8.p0i8")] + fn vst1_s8_x3_(a: int8x8_t, b: int8x8_t, c: int8x8_t, ptr: *mut i8); } -vminq_u32_(a, b) +vst1_s8_x3_(b.0, b.1, b.2, a) } -/// Minimum (vector) +/// Store multiple single-element structures from one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmin))] -pub unsafe fn vmin_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +pub unsafe fn vst1_s16_x3(a: *mut i16, b: int16x4x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmins.v2f32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmin.v2f32")] - fn vmin_f32_(a: float32x2_t, b: float32x2_t) -> float32x2_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x3.p0i16.v4i16")] + fn vst1_s16_x3_(ptr: *mut i16, a: int16x4_t, b: int16x4_t, c: int16x4_t); } -vmin_f32_(a, b) +vst1_s16_x3_(a, b.0, b.1, b.2) } -/// Minimum (vector) +/// Store multiple single-element structures from one, two, three, or four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmin))] -pub unsafe fn vminq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_s16_x3(a: *mut i16, b: int16x4x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmins.v4f32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmin.v4f32")] - fn vminq_f32_(a: float32x4_t, b: float32x4_t) -> float32x4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x3.v4i16.p0i16")] + fn vst1_s16_x3_(a: int16x4_t, b: int16x4_t, c: int16x4_t, ptr: *mut i16); } -vminq_f32_(a, b) +vst1_s16_x3_(b.0, b.1, b.2, a) } -/// Floating-point Minimun Number (vector) +/// Store multiple single-element structures from one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "fp-armv8,v8"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vminnm))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fminnm))] -pub unsafe fn vminnm_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +pub unsafe fn vst1_s32_x3(a: *mut i32, b: int32x2x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vminnm.v2f32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fminnm.v2f32")] - fn vminnm_f32_(a: float32x2_t, b: float32x2_t) -> float32x2_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x3.p0i32.v2i32")] + fn vst1_s32_x3_(ptr: *mut i32, a: int32x2_t, b: int32x2_t, c: int32x2_t); } -vminnm_f32_(a, b) +vst1_s32_x3_(a, b.0, b.1, b.2) } -/// Floating-point Minimun Number (vector) +/// Store multiple single-element structures from one, two, three, or four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "fp-armv8,v8"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vminnm))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fminnm))] -pub unsafe fn vminnmq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_s32_x3(a: *mut i32, b: int32x2x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vminnm.v4f32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fminnm.v4f32")] - fn vminnmq_f32_(a: float32x4_t, b: float32x4_t) -> float32x4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x3.v2i32.p0i32")] + fn vst1_s32_x3_(a: int32x2_t, b: int32x2_t, c: int32x2_t, ptr: *mut i32); } -vminnmq_f32_(a, b) +vst1_s32_x3_(b.0, b.1, b.2, a) } -/// Signed saturating doubling multiply long +/// Store multiple single-element structures from one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmull))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmull))] -pub unsafe fn vqdmull_s16(a: int16x4_t, b: int16x4_t) -> int32x4_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +pub unsafe fn vst1_s64_x3(a: *mut i64, b: int64x1x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqdmull.v4i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqdmull.v4i32")] - fn vqdmull_s16_(a: int16x4_t, b: int16x4_t) -> int32x4_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x3.p0i64.v1i64")] + fn vst1_s64_x3_(ptr: *mut i64, a: int64x1_t, b: int64x1_t, c: int64x1_t); } -vqdmull_s16_(a, b) +vst1_s64_x3_(a, b.0, b.1, b.2) } -/// Signed saturating doubling multiply long +/// Store multiple single-element structures from one, two, three, or four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmull))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmull))] -pub unsafe fn vqdmull_s32(a: int32x2_t, b: int32x2_t) -> int64x2_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_s64_x3(a: *mut i64, b: int64x1x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqdmull.v2i64")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqdmull.v2i64")] - fn vqdmull_s32_(a: int32x2_t, b: int32x2_t) -> int64x2_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x3.v1i64.p0i64")] + fn vst1_s64_x3_(a: int64x1_t, b: int64x1_t, c: int64x1_t, ptr: *mut i64); } -vqdmull_s32_(a, b) +vst1_s64_x3_(b.0, b.1, b.2, a) } -/// Vector saturating doubling long multiply with scalar +/// Store multiple single-element structures from one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmull))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmull))] -pub unsafe fn vqdmull_n_s16(a: int16x4_t, b: i16) -> int32x4_t { - vqdmull_s16(a, vdup_n_s16(b)) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +pub unsafe fn vst1q_s8_x3(a: *mut i8, b: int8x16x3_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x3.p0i8.v16i8")] + fn vst1q_s8_x3_(ptr: *mut i8, a: int8x16_t, b: int8x16_t, c: int8x16_t); + } +vst1q_s8_x3_(a, b.0, b.1, b.2) } -/// Vector saturating doubling long multiply with scalar +/// Store multiple single-element structures from one, two, three, or four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmull))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmull))] -pub unsafe fn vqdmull_n_s32(a: int32x2_t, b: i32) -> int64x2_t { - vqdmull_s32(a, vdup_n_s32(b)) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_s8_x3(a: *mut i8, b: int8x16x3_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x3.v16i8.p0i8")] + fn vst1q_s8_x3_(a: int8x16_t, b: int8x16_t, c: int8x16_t, ptr: *mut i8); + } +vst1q_s8_x3_(b.0, b.1, b.2, a) } -/// Vector saturating doubling long multiply by scalar +/// Store multiple single-element structures from one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmull, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmull, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqdmull_lane_s16(a: int16x4_t, b: int16x4_t) -> int32x4_t { - static_assert_imm2!(N); - let b: int16x4_t = simd_shuffle4!(b, b, [N as u32, N as u32, N as u32, N as u32]); - vqdmull_s16(a, b) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +pub unsafe fn vst1q_s16_x3(a: *mut i16, b: int16x8x3_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x3.p0i16.v8i16")] + fn vst1q_s16_x3_(ptr: *mut i16, a: int16x8_t, b: int16x8_t, c: int16x8_t); + } +vst1q_s16_x3_(a, b.0, b.1, b.2) } -/// Vector saturating doubling long multiply by scalar +/// Store multiple single-element structures from one, two, three, or four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmull, N = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmull, N = 1))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqdmull_lane_s32(a: int32x2_t, b: int32x2_t) -> int64x2_t { - static_assert_imm1!(N); - let b: int32x2_t = simd_shuffle2!(b, b, [N as u32, N as u32]); - vqdmull_s32(a, b) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_s16_x3(a: *mut i16, b: int16x8x3_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x3.v8i16.p0i16")] + fn vst1q_s16_x3_(a: int16x8_t, b: int16x8_t, c: int16x8_t, ptr: *mut i16); + } +vst1q_s16_x3_(b.0, b.1, b.2, a) } -/// Signed saturating doubling multiply-add long +/// Store multiple single-element structures from one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlal))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlal))] -pub unsafe fn vqdmlal_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t { - vqaddq_s32(a, vqdmull_s16(b, c)) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +pub unsafe fn vst1q_s32_x3(a: *mut i32, b: int32x4x3_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x3.p0i32.v4i32")] + fn vst1q_s32_x3_(ptr: *mut i32, a: int32x4_t, b: int32x4_t, c: int32x4_t); + } +vst1q_s32_x3_(a, b.0, b.1, b.2) } -/// Signed saturating doubling multiply-add long +/// Store multiple single-element structures from one, two, three, or four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlal))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlal))] -pub unsafe fn vqdmlal_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t { - vqaddq_s64(a, vqdmull_s32(b, c)) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_s32_x3(a: *mut i32, b: int32x4x3_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x3.v4i32.p0i32")] + fn vst1q_s32_x3_(a: int32x4_t, b: int32x4_t, c: int32x4_t, ptr: *mut i32); + } +vst1q_s32_x3_(b.0, b.1, b.2, a) } -/// Vector widening saturating doubling multiply accumulate with scalar +/// Store multiple single-element structures from one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlal))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlal))] -pub unsafe fn vqdmlal_n_s16(a: int32x4_t, b: int16x4_t, c: i16) -> int32x4_t { - vqaddq_s32(a, vqdmull_n_s16(b, c)) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +pub unsafe fn vst1q_s64_x3(a: *mut i64, b: int64x2x3_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x3.p0i64.v2i64")] + fn vst1q_s64_x3_(ptr: *mut i64, a: int64x2_t, b: int64x2_t, c: int64x2_t); + } +vst1q_s64_x3_(a, b.0, b.1, b.2) } -/// Vector widening saturating doubling multiply accumulate with scalar +/// Store multiple single-element structures from one, two, three, or four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlal))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlal))] -pub unsafe fn vqdmlal_n_s32(a: int64x2_t, b: int32x2_t, c: i32) -> int64x2_t { - vqaddq_s64(a, vqdmull_n_s32(b, c)) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_s64_x3(a: *mut i64, b: int64x2x3_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x3.v2i64.p0i64")] + fn vst1q_s64_x3_(a: int64x2_t, b: int64x2_t, c: int64x2_t, ptr: *mut i64); + } +vst1q_s64_x3_(b.0, b.1, b.2, a) } -/// Vector widening saturating doubling multiply accumulate with scalar +/// Store multiple single-element structures from one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlal, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlal, N = 2))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqdmlal_lane_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t { - static_assert_imm2!(N); - vqaddq_s32(a, vqdmull_lane_s16::(b, c)) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +pub unsafe fn vst1_s8_x4(a: *mut i8, b: int8x8x4_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x4.p0i8.v8i8")] + fn vst1_s8_x4_(ptr: *mut i8, a: int8x8_t, b: int8x8_t, c: int8x8_t, d: int8x8_t); + } +vst1_s8_x4_(a, b.0, b.1, b.2, b.3) } -/// Vector widening saturating doubling multiply accumulate with scalar +/// Store multiple single-element structures from one, two, three, or four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlal, N = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlal, N = 1))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqdmlal_lane_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t { - static_assert_imm1!(N); - vqaddq_s64(a, vqdmull_lane_s32::(b, c)) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_s8_x4(a: *mut i8, b: int8x8x4_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x4.v8i8.p0i8")] + fn vst1_s8_x4_(a: int8x8_t, b: int8x8_t, c: int8x8_t, d: int8x8_t, ptr: *mut i8); + } +vst1_s8_x4_(b.0, b.1, b.2, b.3, a) } -/// Signed saturating doubling multiply-subtract long +/// Store multiple single-element structures from one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlsl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlsl))] -pub unsafe fn vqdmlsl_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t { - vqsubq_s32(a, vqdmull_s16(b, c)) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +pub unsafe fn vst1_s16_x4(a: *mut i16, b: int16x4x4_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x4.p0i16.v4i16")] + fn vst1_s16_x4_(ptr: *mut i16, a: int16x4_t, b: int16x4_t, c: int16x4_t, d: int16x4_t); + } +vst1_s16_x4_(a, b.0, b.1, b.2, b.3) } -/// Signed saturating doubling multiply-subtract long +/// Store multiple single-element structures from one, two, three, or four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlsl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlsl))] -pub unsafe fn vqdmlsl_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t { - vqsubq_s64(a, vqdmull_s32(b, c)) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_s16_x4(a: *mut i16, b: int16x4x4_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x4.v4i16.p0i16")] + fn vst1_s16_x4_(a: int16x4_t, b: int16x4_t, c: int16x4_t, d: int16x4_t, ptr: *mut i16); + } +vst1_s16_x4_(b.0, b.1, b.2, b.3, a) } -/// Vector widening saturating doubling multiply subtract with scalar +/// Store multiple single-element structures from one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlsl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlsl))] -pub unsafe fn vqdmlsl_n_s16(a: int32x4_t, b: int16x4_t, c: i16) -> int32x4_t { - vqsubq_s32(a, vqdmull_n_s16(b, c)) -} - -/// Vector widening saturating doubling multiply subtract with scalar -#[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlsl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlsl))] -pub unsafe fn vqdmlsl_n_s32(a: int64x2_t, b: int32x2_t, c: i32) -> int64x2_t { - vqsubq_s64(a, vqdmull_n_s32(b, c)) -} - -/// Vector widening saturating doubling multiply subtract with scalar -#[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlsl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlsl, N = 2))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqdmlsl_lane_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t { - static_assert_imm2!(N); - vqsubq_s32(a, vqdmull_lane_s16::(b, c)) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +pub unsafe fn vst1_s32_x4(a: *mut i32, b: int32x2x4_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x4.p0i32.v2i32")] + fn vst1_s32_x4_(ptr: *mut i32, a: int32x2_t, b: int32x2_t, c: int32x2_t, d: int32x2_t); + } +vst1_s32_x4_(a, b.0, b.1, b.2, b.3) } -/// Vector widening saturating doubling multiply subtract with scalar +/// Store multiple single-element structures from one, two, three, or four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlsl, N = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlsl, N = 1))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqdmlsl_lane_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t { - static_assert_imm1!(N); - vqsubq_s64(a, vqdmull_lane_s32::(b, c)) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_s32_x4(a: *mut i32, b: int32x2x4_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x4.v2i32.p0i32")] + fn vst1_s32_x4_(a: int32x2_t, b: int32x2_t, c: int32x2_t, d: int32x2_t, ptr: *mut i32); + } +vst1_s32_x4_(b.0, b.1, b.2, b.3, a) } -/// Signed saturating doubling multiply returning high half +/// Store multiple single-element structures from one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh))] -pub unsafe fn vqdmulh_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +pub unsafe fn vst1_s64_x4(a: *mut i64, b: int64x1x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqdmulh.v4i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqdmulh.v4i16")] - fn vqdmulh_s16_(a: int16x4_t, b: int16x4_t) -> int16x4_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x4.p0i64.v1i64")] + fn vst1_s64_x4_(ptr: *mut i64, a: int64x1_t, b: int64x1_t, c: int64x1_t, d: int64x1_t); } -vqdmulh_s16_(a, b) +vst1_s64_x4_(a, b.0, b.1, b.2, b.3) } -/// Signed saturating doubling multiply returning high half +/// Store multiple single-element structures from one, two, three, or four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh))] -pub unsafe fn vqdmulhq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_s64_x4(a: *mut i64, b: int64x1x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqdmulh.v8i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqdmulh.v8i16")] - fn vqdmulhq_s16_(a: int16x8_t, b: int16x8_t) -> int16x8_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x4.v1i64.p0i64")] + fn vst1_s64_x4_(a: int64x1_t, b: int64x1_t, c: int64x1_t, d: int64x1_t, ptr: *mut i64); } -vqdmulhq_s16_(a, b) +vst1_s64_x4_(b.0, b.1, b.2, b.3, a) } -/// Signed saturating doubling multiply returning high half +/// Store multiple single-element structures from one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh))] -pub unsafe fn vqdmulh_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +pub unsafe fn vst1q_s8_x4(a: *mut i8, b: int8x16x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqdmulh.v2i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqdmulh.v2i32")] - fn vqdmulh_s32_(a: int32x2_t, b: int32x2_t) -> int32x2_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x4.p0i8.v16i8")] + fn vst1q_s8_x4_(ptr: *mut i8, a: int8x16_t, b: int8x16_t, c: int8x16_t, d: int8x16_t); } -vqdmulh_s32_(a, b) +vst1q_s8_x4_(a, b.0, b.1, b.2, b.3) } -/// Signed saturating doubling multiply returning high half +/// Store multiple single-element structures from one, two, three, or four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh))] -pub unsafe fn vqdmulhq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_s8_x4(a: *mut i8, b: int8x16x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqdmulh.v4i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqdmulh.v4i32")] - fn vqdmulhq_s32_(a: int32x4_t, b: int32x4_t) -> int32x4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x4.v16i8.p0i8")] + fn vst1q_s8_x4_(a: int8x16_t, b: int8x16_t, c: int8x16_t, d: int8x16_t, ptr: *mut i8); } -vqdmulhq_s32_(a, b) +vst1q_s8_x4_(b.0, b.1, b.2, b.3, a) } -/// Vector saturating doubling multiply high with scalar +/// Store multiple single-element structures from one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh))] -pub unsafe fn vqdmulh_n_s16(a: int16x4_t, b: i16) -> int16x4_t { - let b: int16x4_t = vdup_n_s16(b); - vqdmulh_s16(a, b) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +pub unsafe fn vst1q_s16_x4(a: *mut i16, b: int16x8x4_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x4.p0i16.v8i16")] + fn vst1q_s16_x4_(ptr: *mut i16, a: int16x8_t, b: int16x8_t, c: int16x8_t, d: int16x8_t); + } +vst1q_s16_x4_(a, b.0, b.1, b.2, b.3) } -/// Vector saturating doubling multiply high with scalar +/// Store multiple single-element structures from one, two, three, or four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh))] -pub unsafe fn vqdmulh_n_s32(a: int32x2_t, b: i32) -> int32x2_t { - let b: int32x2_t = vdup_n_s32(b); - vqdmulh_s32(a, b) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_s16_x4(a: *mut i16, b: int16x8x4_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x4.v8i16.p0i16")] + fn vst1q_s16_x4_(a: int16x8_t, b: int16x8_t, c: int16x8_t, d: int16x8_t, ptr: *mut i16); + } +vst1q_s16_x4_(b.0, b.1, b.2, b.3, a) } -/// Vector saturating doubling multiply high with scalar +/// Store multiple single-element structures from one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh))] -pub unsafe fn vqdmulhq_n_s16(a: int16x8_t, b: i16) -> int16x8_t { - let b: int16x8_t = vdupq_n_s16(b); - vqdmulhq_s16(a, b) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +pub unsafe fn vst1q_s32_x4(a: *mut i32, b: int32x4x4_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x4.p0i32.v4i32")] + fn vst1q_s32_x4_(ptr: *mut i32, a: int32x4_t, b: int32x4_t, c: int32x4_t, d: int32x4_t); + } +vst1q_s32_x4_(a, b.0, b.1, b.2, b.3) } -/// Vector saturating doubling multiply high with scalar +/// Store multiple single-element structures from one, two, three, or four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh))] -pub unsafe fn vqdmulhq_n_s32(a: int32x4_t, b: i32) -> int32x4_t { - let b: int32x4_t = vdupq_n_s32(b); - vqdmulhq_s32(a, b) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_s32_x4(a: *mut i32, b: int32x4x4_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x4.v4i32.p0i32")] + fn vst1q_s32_x4_(a: int32x4_t, b: int32x4_t, c: int32x4_t, d: int32x4_t, ptr: *mut i32); + } +vst1q_s32_x4_(b.0, b.1, b.2, b.3, a) } -/// Signed saturating extract narrow +/// Store multiple single-element structures from one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovn))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqxtn))] -pub unsafe fn vqmovn_s16(a: int16x8_t) -> int8x8_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +pub unsafe fn vst1q_s64_x4(a: *mut i64, b: int64x2x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqmovns.v8i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqxtn.v8i8")] - fn vqmovn_s16_(a: int16x8_t) -> int8x8_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x4.p0i64.v2i64")] + fn vst1q_s64_x4_(ptr: *mut i64, a: int64x2_t, b: int64x2_t, c: int64x2_t, d: int64x2_t); } -vqmovn_s16_(a) +vst1q_s64_x4_(a, b.0, b.1, b.2, b.3) } -/// Signed saturating extract narrow +/// Store multiple single-element structures from one, two, three, or four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovn))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqxtn))] -pub unsafe fn vqmovn_s32(a: int32x4_t) -> int16x4_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_s64_x4(a: *mut i64, b: int64x2x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqmovns.v4i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqxtn.v4i16")] - fn vqmovn_s32_(a: int32x4_t) -> int16x4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x4.v2i64.p0i64")] + fn vst1q_s64_x4_(a: int64x2_t, b: int64x2_t, c: int64x2_t, d: int64x2_t, ptr: *mut i64); } -vqmovn_s32_(a) +vst1q_s64_x4_(b.0, b.1, b.2, b.3, a) } -/// Signed saturating extract narrow +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovn))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqxtn))] -pub unsafe fn vqmovn_s64(a: int64x2_t) -> int32x2_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqmovns.v2i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqxtn.v2i32")] - fn vqmovn_s64_(a: int64x2_t) -> int32x2_t; - } -vqmovn_s64_(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_u8_x2(a: *mut u8, b: uint8x8x2_t) { + vst1_s8_x2(transmute(a), transmute(b)) } -/// Unsigned saturating extract narrow +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovn))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqxtn))] -pub unsafe fn vqmovn_u16(a: uint16x8_t) -> uint8x8_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqmovnu.v8i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqxtn.v8i8")] - fn vqmovn_u16_(a: uint16x8_t) -> uint8x8_t; - } -vqmovn_u16_(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_u16_x2(a: *mut u16, b: uint16x4x2_t) { + vst1_s16_x2(transmute(a), transmute(b)) } -/// Unsigned saturating extract narrow +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovn))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqxtn))] -pub unsafe fn vqmovn_u32(a: uint32x4_t) -> uint16x4_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqmovnu.v4i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqxtn.v4i16")] - fn vqmovn_u32_(a: uint32x4_t) -> uint16x4_t; - } -vqmovn_u32_(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_u32_x2(a: *mut u32, b: uint32x2x2_t) { + vst1_s32_x2(transmute(a), transmute(b)) } -/// Unsigned saturating extract narrow +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovn))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqxtn))] -pub unsafe fn vqmovn_u64(a: uint64x2_t) -> uint32x2_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqmovnu.v2i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqxtn.v2i32")] - fn vqmovn_u64_(a: uint64x2_t) -> uint32x2_t; - } -vqmovn_u64_(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_u64_x2(a: *mut u64, b: uint64x1x2_t) { + vst1_s64_x2(transmute(a), transmute(b)) } -/// Signed saturating extract unsigned narrow +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovun))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqxtun))] -pub unsafe fn vqmovun_s16(a: int16x8_t) -> uint8x8_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqmovnsu.v8i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqxtun.v8i8")] - fn vqmovun_s16_(a: int16x8_t) -> uint8x8_t; - } -vqmovun_s16_(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_u8_x2(a: *mut u8, b: uint8x16x2_t) { + vst1q_s8_x2(transmute(a), transmute(b)) } -/// Signed saturating extract unsigned narrow +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovun))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqxtun))] -pub unsafe fn vqmovun_s32(a: int32x4_t) -> uint16x4_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqmovnsu.v4i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqxtun.v4i16")] - fn vqmovun_s32_(a: int32x4_t) -> uint16x4_t; - } -vqmovun_s32_(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_u16_x2(a: *mut u16, b: uint16x8x2_t) { + vst1q_s16_x2(transmute(a), transmute(b)) } -/// Signed saturating extract unsigned narrow +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovun))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqxtun))] -pub unsafe fn vqmovun_s64(a: int64x2_t) -> uint32x2_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqmovnsu.v2i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqxtun.v2i32")] - fn vqmovun_s64_(a: int64x2_t) -> uint32x2_t; - } -vqmovun_s64_(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_u32_x2(a: *mut u32, b: uint32x4x2_t) { + vst1q_s32_x2(transmute(a), transmute(b)) } -/// Signed saturating rounding doubling multiply returning high half +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] -pub unsafe fn vqrdmulh_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrdmulh.v4i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrdmulh.v4i16")] - fn vqrdmulh_s16_(a: int16x4_t, b: int16x4_t) -> int16x4_t; - } -vqrdmulh_s16_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_u64_x2(a: *mut u64, b: uint64x2x2_t) { + vst1q_s64_x2(transmute(a), transmute(b)) } -/// Signed saturating rounding doubling multiply returning high half +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] -pub unsafe fn vqrdmulhq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrdmulh.v8i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrdmulh.v8i16")] - fn vqrdmulhq_s16_(a: int16x8_t, b: int16x8_t) -> int16x8_t; - } -vqrdmulhq_s16_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_u8_x3(a: *mut u8, b: uint8x8x3_t) { + vst1_s8_x3(transmute(a), transmute(b)) } -/// Signed saturating rounding doubling multiply returning high half +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] -pub unsafe fn vqrdmulh_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrdmulh.v2i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrdmulh.v2i32")] - fn vqrdmulh_s32_(a: int32x2_t, b: int32x2_t) -> int32x2_t; - } -vqrdmulh_s32_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_u16_x3(a: *mut u16, b: uint16x4x3_t) { + vst1_s16_x3(transmute(a), transmute(b)) } -/// Signed saturating rounding doubling multiply returning high half +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] -pub unsafe fn vqrdmulhq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrdmulh.v4i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrdmulh.v4i32")] - fn vqrdmulhq_s32_(a: int32x4_t, b: int32x4_t) -> int32x4_t; - } -vqrdmulhq_s32_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_u32_x3(a: *mut u32, b: uint32x2x3_t) { + vst1_s32_x3(transmute(a), transmute(b)) } -/// Vector saturating rounding doubling multiply high with scalar +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] -pub unsafe fn vqrdmulh_n_s16(a: int16x4_t, b: i16) -> int16x4_t { - vqrdmulh_s16(a, vdup_n_s16(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_u64_x3(a: *mut u64, b: uint64x1x3_t) { + vst1_s64_x3(transmute(a), transmute(b)) } -/// Vector saturating rounding doubling multiply high with scalar +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] -pub unsafe fn vqrdmulhq_n_s16(a: int16x8_t, b: i16) -> int16x8_t { - vqrdmulhq_s16(a, vdupq_n_s16(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_u8_x3(a: *mut u8, b: uint8x16x3_t) { + vst1q_s8_x3(transmute(a), transmute(b)) } -/// Vector saturating rounding doubling multiply high with scalar +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] -pub unsafe fn vqrdmulh_n_s32(a: int32x2_t, b: i32) -> int32x2_t { - vqrdmulh_s32(a, vdup_n_s32(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_u16_x3(a: *mut u16, b: uint16x8x3_t) { + vst1q_s16_x3(transmute(a), transmute(b)) } -/// Vector saturating rounding doubling multiply high with scalar +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] -pub unsafe fn vqrdmulhq_n_s32(a: int32x4_t, b: i32) -> int32x4_t { - vqrdmulhq_s32(a, vdupq_n_s32(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_u32_x3(a: *mut u32, b: uint32x4x3_t) { + vst1q_s32_x3(transmute(a), transmute(b)) } -/// Vector rounding saturating doubling multiply high by scalar +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqrdmulh_lane_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { - static_assert_imm2!(LANE); - let b: int16x4_t = simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32]); - vqrdmulh_s16(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_u64_x3(a: *mut u64, b: uint64x2x3_t) { + vst1q_s64_x3(transmute(a), transmute(b)) } -/// Vector rounding saturating doubling multiply high by scalar +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqrdmulh_laneq_s16(a: int16x4_t, b: int16x8_t) -> int16x4_t { - static_assert_imm3!(LANE); - let b: int16x4_t = simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32]); - vqrdmulh_s16(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_u8_x4(a: *mut u8, b: uint8x8x4_t) { + vst1_s8_x4(transmute(a), transmute(b)) } -/// Vector rounding saturating doubling multiply high by scalar +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqrdmulhq_lane_s16(a: int16x8_t, b: int16x4_t) -> int16x8_t { - static_assert_imm2!(LANE); - let b: int16x8_t = simd_shuffle8!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32]); - vqrdmulhq_s16(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_u16_x4(a: *mut u16, b: uint16x4x4_t) { + vst1_s16_x4(transmute(a), transmute(b)) } -/// Vector rounding saturating doubling multiply high by scalar +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqrdmulhq_laneq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { - static_assert_imm3!(LANE); - let b: int16x8_t = simd_shuffle8!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32]); - vqrdmulhq_s16(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_u32_x4(a: *mut u32, b: uint32x2x4_t) { + vst1_s32_x4(transmute(a), transmute(b)) } -/// Vector rounding saturating doubling multiply high by scalar +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqrdmulh_lane_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { - static_assert_imm1!(LANE); - let b: int32x2_t = simd_shuffle2!(b, b, [LANE as u32, LANE as u32]); - vqrdmulh_s32(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_u64_x4(a: *mut u64, b: uint64x1x4_t) { + vst1_s64_x4(transmute(a), transmute(b)) } -/// Vector rounding saturating doubling multiply high by scalar +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqrdmulh_laneq_s32(a: int32x2_t, b: int32x4_t) -> int32x2_t { - static_assert_imm2!(LANE); - let b: int32x2_t = simd_shuffle2!(b, b, [LANE as u32, LANE as u32]); - vqrdmulh_s32(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_u8_x4(a: *mut u8, b: uint8x16x4_t) { + vst1q_s8_x4(transmute(a), transmute(b)) } -/// Vector rounding saturating doubling multiply high by scalar +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqrdmulhq_lane_s32(a: int32x4_t, b: int32x2_t) -> int32x4_t { - static_assert_imm1!(LANE); - let b: int32x4_t = simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32]); - vqrdmulhq_s32(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_u16_x4(a: *mut u16, b: uint16x8x4_t) { + vst1q_s16_x4(transmute(a), transmute(b)) } -/// Vector rounding saturating doubling multiply high by scalar +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vqrdmulhq_laneq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { - static_assert_imm2!(LANE); - let b: int32x4_t = simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32]); - vqrdmulhq_s32(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_u32_x4(a: *mut u32, b: uint32x4x4_t) { + vst1q_s32_x4(transmute(a), transmute(b)) } -/// Signed saturating rounding doubling multiply accumulate returning high half +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] -pub unsafe fn vqrdmlah_s16(a: int16x4_t, b: int16x4_t, c: int16x4_t) -> int16x4_t { - vqadd_s16(a, vqrdmulh_s16(b, c)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_u64_x4(a: *mut u64, b: uint64x2x4_t) { + vst1q_s64_x4(transmute(a), transmute(b)) } -/// Signed saturating rounding doubling multiply accumulate returning high half +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] -pub unsafe fn vqrdmlahq_s16(a: int16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8_t { - vqaddq_s16(a, vqrdmulhq_s16(b, c)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_p8_x2(a: *mut p8, b: poly8x8x2_t) { + vst1_s8_x2(transmute(a), transmute(b)) } -/// Signed saturating rounding doubling multiply accumulate returning high half +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] -pub unsafe fn vqrdmlah_s32(a: int32x2_t, b: int32x2_t, c: int32x2_t) -> int32x2_t { - vqadd_s32(a, vqrdmulh_s32(b, c)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_p8_x3(a: *mut p8, b: poly8x8x3_t) { + vst1_s8_x3(transmute(a), transmute(b)) } -/// Signed saturating rounding doubling multiply accumulate returning high half +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] -pub unsafe fn vqrdmlahq_s32(a: int32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4_t { - vqaddq_s32(a, vqrdmulhq_s32(b, c)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_p8_x4(a: *mut p8, b: poly8x8x4_t) { + vst1_s8_x4(transmute(a), transmute(b)) } -/// Signed saturating rounding doubling multiply accumulate returning high half +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqrdmlah_lane_s16(a: int16x4_t, b: int16x4_t, c: int16x4_t) -> int16x4_t { - static_assert_imm2!(LANE); - vqadd_s16(a, vqrdmulh_lane_s16::(b, c)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_p8_x2(a: *mut p8, b: poly8x16x2_t) { + vst1q_s8_x2(transmute(a), transmute(b)) } -/// Signed saturating rounding doubling multiply accumulate returning high half +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqrdmlah_laneq_s16(a: int16x4_t, b: int16x4_t, c: int16x8_t) -> int16x4_t { - static_assert_imm3!(LANE); - vqadd_s16(a, vqrdmulh_laneq_s16::(b, c)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_p8_x3(a: *mut p8, b: poly8x16x3_t) { + vst1q_s8_x3(transmute(a), transmute(b)) } -/// Signed saturating rounding doubling multiply accumulate returning high half +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqrdmlahq_lane_s16(a: int16x8_t, b: int16x8_t, c: int16x4_t) -> int16x8_t { - static_assert_imm2!(LANE); - vqaddq_s16(a, vqrdmulhq_lane_s16::(b, c)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_p8_x4(a: *mut p8, b: poly8x16x4_t) { + vst1q_s8_x4(transmute(a), transmute(b)) } -/// Signed saturating rounding doubling multiply accumulate returning high half +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqrdmlahq_laneq_s16(a: int16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8_t { - static_assert_imm3!(LANE); - vqaddq_s16(a, vqrdmulhq_laneq_s16::(b, c)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_p16_x2(a: *mut p16, b: poly16x4x2_t) { + vst1_s16_x2(transmute(a), transmute(b)) } -/// Signed saturating rounding doubling multiply accumulate returning high half +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqrdmlah_lane_s32(a: int32x2_t, b: int32x2_t, c: int32x2_t) -> int32x2_t { - static_assert_imm1!(LANE); - vqadd_s32(a, vqrdmulh_lane_s32::(b, c)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_p16_x3(a: *mut p16, b: poly16x4x3_t) { + vst1_s16_x3(transmute(a), transmute(b)) } -/// Signed saturating rounding doubling multiply accumulate returning high half +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqrdmlah_laneq_s32(a: int32x2_t, b: int32x2_t, c: int32x4_t) -> int32x2_t { - static_assert_imm2!(LANE); - vqadd_s32(a, vqrdmulh_laneq_s32::(b, c)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_p16_x4(a: *mut p16, b: poly16x4x4_t) { + vst1_s16_x4(transmute(a), transmute(b)) } -/// Signed saturating rounding doubling multiply accumulate returning high half +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqrdmlahq_lane_s32(a: int32x4_t, b: int32x4_t, c: int32x2_t) -> int32x4_t { - static_assert_imm1!(LANE); - vqaddq_s32(a, vqrdmulhq_lane_s32::(b, c)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_p16_x2(a: *mut p16, b: poly16x8x2_t) { + vst1q_s16_x2(transmute(a), transmute(b)) } -/// Signed saturating rounding doubling multiply accumulate returning high half +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqrdmlahq_laneq_s32(a: int32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4_t { - static_assert_imm2!(LANE); - vqaddq_s32(a, vqrdmulhq_laneq_s32::(b, c)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_p16_x3(a: *mut p16, b: poly16x8x3_t) { + vst1q_s16_x3(transmute(a), transmute(b)) } -/// Signed saturating rounding doubling multiply subtract returning high half +/// Store multiple single-element structures to one, two, three, or four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] -pub unsafe fn vqrdmlsh_s16(a: int16x4_t, b: int16x4_t, c: int16x4_t) -> int16x4_t { - vqsub_s16(a, vqrdmulh_s16(b, c)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_p16_x4(a: *mut p16, b: poly16x8x4_t) { + vst1q_s16_x4(transmute(a), transmute(b)) } -/// Signed saturating rounding doubling multiply subtract returning high half +/// Store multiple single-element structures to one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] -pub unsafe fn vqrdmlshq_s16(a: int16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8_t { - vqsubq_s16(a, vqrdmulhq_s16(b, c)) +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_p64_x2(a: *mut p64, b: poly64x1x2_t) { + vst1_s64_x2(transmute(a), transmute(b)) } -/// Signed saturating rounding doubling multiply subtract returning high half +/// Store multiple single-element structures to one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] -pub unsafe fn vqrdmlsh_s32(a: int32x2_t, b: int32x2_t, c: int32x2_t) -> int32x2_t { - vqsub_s32(a, vqrdmulh_s32(b, c)) +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_p64_x3(a: *mut p64, b: poly64x1x3_t) { + vst1_s64_x3(transmute(a), transmute(b)) } -/// Signed saturating rounding doubling multiply subtract returning high half +/// Store multiple single-element structures to one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] -pub unsafe fn vqrdmlshq_s32(a: int32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4_t { - vqsubq_s32(a, vqrdmulhq_s32(b, c)) +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_p64_x4(a: *mut p64, b: poly64x1x4_t) { + vst1_s64_x4(transmute(a), transmute(b)) } -/// Signed saturating rounding doubling multiply subtract returning high half +/// Store multiple single-element structures to one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqrdmlsh_lane_s16(a: int16x4_t, b: int16x4_t, c: int16x4_t) -> int16x4_t { - static_assert_imm2!(LANE); - vqsub_s16(a, vqrdmulh_lane_s16::(b, c)) +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_p64_x2(a: *mut p64, b: poly64x2x2_t) { + vst1q_s64_x2(transmute(a), transmute(b)) } -/// Signed saturating rounding doubling multiply subtract returning high half +/// Store multiple single-element structures to one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqrdmlsh_laneq_s16(a: int16x4_t, b: int16x4_t, c: int16x8_t) -> int16x4_t { - static_assert_imm3!(LANE); - vqsub_s16(a, vqrdmulh_laneq_s16::(b, c)) +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_p64_x3(a: *mut p64, b: poly64x2x3_t) { + vst1q_s64_x3(transmute(a), transmute(b)) } -/// Signed saturating rounding doubling multiply subtract returning high half +/// Store multiple single-element structures to one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqrdmlshq_lane_s16(a: int16x8_t, b: int16x8_t, c: int16x4_t) -> int16x8_t { - static_assert_imm2!(LANE); - vqsubq_s16(a, vqrdmulhq_lane_s16::(b, c)) +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_p64_x4(a: *mut p64, b: poly64x2x4_t) { + vst1q_s64_x4(transmute(a), transmute(b)) } -/// Signed saturating rounding doubling multiply subtract returning high half +/// Store multiple single-element structures to one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqrdmlshq_laneq_s16(a: int16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8_t { - static_assert_imm3!(LANE); - vqsubq_s16(a, vqrdmulhq_laneq_s16::(b, c)) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +pub unsafe fn vst1_f32_x2(a: *mut f32, b: float32x2x2_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x2.p0f32.v2f32")] + fn vst1_f32_x2_(ptr: *mut f32, a: float32x2_t, b: float32x2_t); + } +vst1_f32_x2_(a, b.0, b.1) } -/// Signed saturating rounding doubling multiply subtract returning high half +/// Store multiple single-element structures to one, two, three, or four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqrdmlsh_lane_s32(a: int32x2_t, b: int32x2_t, c: int32x2_t) -> int32x2_t { - static_assert_imm1!(LANE); - vqsub_s32(a, vqrdmulh_lane_s32::(b, c)) -} - -/// Signed saturating rounding doubling multiply subtract returning high half -#[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqrdmlsh_laneq_s32(a: int32x2_t, b: int32x2_t, c: int32x4_t) -> int32x2_t { - static_assert_imm2!(LANE); - vqsub_s32(a, vqrdmulh_laneq_s32::(b, c)) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_f32_x2(a: *mut f32, b: float32x2x2_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x2.v2f32.p0f32")] + fn vst1_f32_x2_(a: float32x2_t, b: float32x2_t, ptr: *mut f32); + } +vst1_f32_x2_(b.0, b.1, a) } -/// Signed saturating rounding doubling multiply subtract returning high half +/// Store multiple single-element structures to one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqrdmlshq_lane_s32(a: int32x4_t, b: int32x4_t, c: int32x2_t) -> int32x4_t { - static_assert_imm1!(LANE); - vqsubq_s32(a, vqrdmulhq_lane_s32::(b, c)) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +pub unsafe fn vst1q_f32_x2(a: *mut f32, b: float32x4x2_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x2.p0f32.v4f32")] + fn vst1q_f32_x2_(ptr: *mut f32, a: float32x4_t, b: float32x4_t); + } +vst1q_f32_x2_(a, b.0, b.1) } -/// Signed saturating rounding doubling multiply subtract returning high half +/// Store multiple single-element structures to one, two, three, or four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] -#[rustc_legacy_const_generics(3)] -pub unsafe fn vqrdmlshq_laneq_s32(a: int32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4_t { - static_assert_imm2!(LANE); - vqsubq_s32(a, vqrdmulhq_laneq_s32::(b, c)) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_f32_x2(a: *mut f32, b: float32x4x2_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x2.v4f32.p0f32")] + fn vst1q_f32_x2_(a: float32x4_t, b: float32x4_t, ptr: *mut f32); + } +vst1q_f32_x2_(b.0, b.1, a) } -/// Signed saturating rounding shift left +/// Store multiple single-element structures to one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))] -pub unsafe fn vqrshl_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +pub unsafe fn vst1_f32_x3(a: *mut f32, b: float32x2x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshifts.v8i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshl.v8i8")] - fn vqrshl_s8_(a: int8x8_t, b: int8x8_t) -> int8x8_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x3.p0f32.v2f32")] + fn vst1_f32_x3_(ptr: *mut f32, a: float32x2_t, b: float32x2_t, c: float32x2_t); } -vqrshl_s8_(a, b) +vst1_f32_x3_(a, b.0, b.1, b.2) } -/// Signed saturating rounding shift left +/// Store multiple single-element structures to one, two, three, or four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))] -pub unsafe fn vqrshlq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_f32_x3(a: *mut f32, b: float32x2x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshifts.v16i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshl.v16i8")] - fn vqrshlq_s8_(a: int8x16_t, b: int8x16_t) -> int8x16_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x3.v2f32.p0f32")] + fn vst1_f32_x3_(a: float32x2_t, b: float32x2_t, c: float32x2_t, ptr: *mut f32); } -vqrshlq_s8_(a, b) +vst1_f32_x3_(b.0, b.1, b.2, a) } -/// Signed saturating rounding shift left +/// Store multiple single-element structures to one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))] -pub unsafe fn vqrshl_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +pub unsafe fn vst1q_f32_x3(a: *mut f32, b: float32x4x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshifts.v4i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshl.v4i16")] - fn vqrshl_s16_(a: int16x4_t, b: int16x4_t) -> int16x4_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x3.p0f32.v4f32")] + fn vst1q_f32_x3_(ptr: *mut f32, a: float32x4_t, b: float32x4_t, c: float32x4_t); } -vqrshl_s16_(a, b) +vst1q_f32_x3_(a, b.0, b.1, b.2) } -/// Signed saturating rounding shift left +/// Store multiple single-element structures to one, two, three, or four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))] -pub unsafe fn vqrshlq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_f32_x3(a: *mut f32, b: float32x4x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshifts.v8i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshl.v8i16")] - fn vqrshlq_s16_(a: int16x8_t, b: int16x8_t) -> int16x8_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x3.v4f32.p0f32")] + fn vst1q_f32_x3_(a: float32x4_t, b: float32x4_t, c: float32x4_t, ptr: *mut f32); } -vqrshlq_s16_(a, b) +vst1q_f32_x3_(b.0, b.1, b.2, a) } -/// Signed saturating rounding shift left +/// Store multiple single-element structures to one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))] -pub unsafe fn vqrshl_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +pub unsafe fn vst1_f32_x4(a: *mut f32, b: float32x2x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshifts.v2i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshl.v2i32")] - fn vqrshl_s32_(a: int32x2_t, b: int32x2_t) -> int32x2_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x4.p0f32.v2f32")] + fn vst1_f32_x4_(ptr: *mut f32, a: float32x2_t, b: float32x2_t, c: float32x2_t, d: float32x2_t); } -vqrshl_s32_(a, b) +vst1_f32_x4_(a, b.0, b.1, b.2, b.3) } -/// Signed saturating rounding shift left +/// Store multiple single-element structures to one, two, three, or four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))] -pub unsafe fn vqrshlq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1_f32_x4(a: *mut f32, b: float32x2x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshifts.v4i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshl.v4i32")] - fn vqrshlq_s32_(a: int32x4_t, b: int32x4_t) -> int32x4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x4.v2f32.p0f32")] + fn vst1_f32_x4_(a: float32x2_t, b: float32x2_t, c: float32x2_t, d: float32x2_t, ptr: *mut f32); } -vqrshlq_s32_(a, b) +vst1_f32_x4_(b.0, b.1, b.2, b.3, a) } -/// Signed saturating rounding shift left +/// Store multiple single-element structures to one, two, three, or four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))] -pub unsafe fn vqrshl_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +pub unsafe fn vst1q_f32_x4(a: *mut f32, b: float32x4x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshifts.v1i64")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshl.v1i64")] - fn vqrshl_s64_(a: int64x1_t, b: int64x1_t) -> int64x1_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst1x4.p0f32.v4f32")] + fn vst1q_f32_x4_(ptr: *mut f32, a: float32x4_t, b: float32x4_t, c: float32x4_t, d: float32x4_t); } -vqrshl_s64_(a, b) +vst1q_f32_x4_(a, b.0, b.1, b.2, b.3) } -/// Signed saturating rounding shift left +/// Store multiple single-element structures to one, two, three, or four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))] -pub unsafe fn vqrshlq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +pub unsafe fn vst1q_f32_x4(a: *mut f32, b: float32x4x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshifts.v2i64")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshl.v2i64")] - fn vqrshlq_s64_(a: int64x2_t, b: int64x2_t) -> int64x2_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st1x4.v4f32.p0f32")] + fn vst1q_f32_x4_(a: float32x4_t, b: float32x4_t, c: float32x4_t, d: float32x4_t, ptr: *mut f32); } -vqrshlq_s64_(a, b) +vst1q_f32_x4_(b.0, b.1, b.2, b.3, a) } -/// Unsigned signed saturating rounding shift left +/// Store multiple 2-element structures from two registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))] -pub unsafe fn vqrshl_u8(a: uint8x8_t, b: int8x8_t) -> uint8x8_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] +pub unsafe fn vst2_s8(a: *mut i8, b: int8x8x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftu.v8i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqrshl.v8i8")] - fn vqrshl_u8_(a: uint8x8_t, b: int8x8_t) -> uint8x8_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2.p0i8.v8i8")] + fn vst2_s8_(ptr: *mut i8, a: int8x8_t, b: int8x8_t, size: i32); } -vqrshl_u8_(a, b) +vst2_s8_(a.cast(), b.0, b.1, 1) } -/// Unsigned signed saturating rounding shift left +/// Store multiple 2-element structures from two registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))] -pub unsafe fn vqrshlq_u8(a: uint8x16_t, b: int8x16_t) -> uint8x16_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +pub unsafe fn vst2_s8(a: *mut i8, b: int8x8x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftu.v16i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqrshl.v16i8")] - fn vqrshlq_u8_(a: uint8x16_t, b: int8x16_t) -> uint8x16_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2.v8i8.p0i8")] + fn vst2_s8_(a: int8x8_t, b: int8x8_t, ptr: *mut i8); } -vqrshlq_u8_(a, b) +vst2_s8_(b.0, b.1, a.cast()) } -/// Unsigned signed saturating rounding shift left +/// Store multiple 2-element structures from two registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))] -pub unsafe fn vqrshl_u16(a: uint16x4_t, b: int16x4_t) -> uint16x4_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] +pub unsafe fn vst2_s16(a: *mut i16, b: int16x4x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftu.v4i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqrshl.v4i16")] - fn vqrshl_u16_(a: uint16x4_t, b: int16x4_t) -> uint16x4_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2.p0i8.v4i16")] + fn vst2_s16_(ptr: *mut i8, a: int16x4_t, b: int16x4_t, size: i32); } -vqrshl_u16_(a, b) +vst2_s16_(a.cast(), b.0, b.1, 2) } -/// Unsigned signed saturating rounding shift left +/// Store multiple 2-element structures from two registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))] -pub unsafe fn vqrshlq_u16(a: uint16x8_t, b: int16x8_t) -> uint16x8_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +pub unsafe fn vst2_s16(a: *mut i16, b: int16x4x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftu.v8i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqrshl.v8i16")] - fn vqrshlq_u16_(a: uint16x8_t, b: int16x8_t) -> uint16x8_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2.v4i16.p0i8")] + fn vst2_s16_(a: int16x4_t, b: int16x4_t, ptr: *mut i8); } -vqrshlq_u16_(a, b) +vst2_s16_(b.0, b.1, a.cast()) } -/// Unsigned signed saturating rounding shift left +/// Store multiple 2-element structures from two registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))] -pub unsafe fn vqrshl_u32(a: uint32x2_t, b: int32x2_t) -> uint32x2_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] +pub unsafe fn vst2_s32(a: *mut i32, b: int32x2x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftu.v2i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqrshl.v2i32")] - fn vqrshl_u32_(a: uint32x2_t, b: int32x2_t) -> uint32x2_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2.p0i8.v2i32")] + fn vst2_s32_(ptr: *mut i8, a: int32x2_t, b: int32x2_t, size: i32); } -vqrshl_u32_(a, b) +vst2_s32_(a.cast(), b.0, b.1, 4) } -/// Unsigned signed saturating rounding shift left +/// Store multiple 2-element structures from two registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))] -pub unsafe fn vqrshlq_u32(a: uint32x4_t, b: int32x4_t) -> uint32x4_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +pub unsafe fn vst2_s32(a: *mut i32, b: int32x2x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftu.v4i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqrshl.v4i32")] - fn vqrshlq_u32_(a: uint32x4_t, b: int32x4_t) -> uint32x4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2.v2i32.p0i8")] + fn vst2_s32_(a: int32x2_t, b: int32x2_t, ptr: *mut i8); } -vqrshlq_u32_(a, b) +vst2_s32_(b.0, b.1, a.cast()) } -/// Unsigned signed saturating rounding shift left +/// Store multiple 2-element structures from two registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))] -pub unsafe fn vqrshl_u64(a: uint64x1_t, b: int64x1_t) -> uint64x1_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] +pub unsafe fn vst2q_s8(a: *mut i8, b: int8x16x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftu.v1i64")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqrshl.v1i64")] - fn vqrshl_u64_(a: uint64x1_t, b: int64x1_t) -> uint64x1_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2.p0i8.v16i8")] + fn vst2q_s8_(ptr: *mut i8, a: int8x16_t, b: int8x16_t, size: i32); } -vqrshl_u64_(a, b) +vst2q_s8_(a.cast(), b.0, b.1, 1) } -/// Unsigned signed saturating rounding shift left +/// Store multiple 2-element structures from two registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))] -pub unsafe fn vqrshlq_u64(a: uint64x2_t, b: int64x2_t) -> uint64x2_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +pub unsafe fn vst2q_s8(a: *mut i8, b: int8x16x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftu.v2i64")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqrshl.v2i64")] - fn vqrshlq_u64_(a: uint64x2_t, b: int64x2_t) -> uint64x2_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2.v16i8.p0i8")] + fn vst2q_s8_(a: int8x16_t, b: int8x16_t, ptr: *mut i8); } -vqrshlq_u64_(a, b) +vst2q_s8_(b.0, b.1, a.cast()) } -/// Signed saturating rounded shift right narrow +/// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqrshrn_n_s16(a: int16x8_t) -> int8x8_t { - static_assert!(N : i32 where N >= 1 && N <= 8); +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] +pub unsafe fn vst2q_s16(a: *mut i16, b: int16x8x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftns.v8i8")] - fn vqrshrn_n_s16_(a: int16x8_t, n: int16x8_t) -> int8x8_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2.p0i8.v8i16")] + fn vst2q_s16_(ptr: *mut i8, a: int16x8_t, b: int16x8_t, size: i32); } -vqrshrn_n_s16_(a, int16x8_t(-N as i16, -N as i16, -N as i16, -N as i16, -N as i16, -N as i16, -N as i16, -N as i16)) +vst2q_s16_(a.cast(), b.0, b.1, 2) } -/// Signed saturating rounded shift right narrow +/// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqrshrn_n_s16(a: int16x8_t) -> int8x8_t { - static_assert!(N : i32 where N >= 1 && N <= 8); +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +pub unsafe fn vst2q_s16(a: *mut i16, b: int16x8x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshrn.v8i8")] - fn vqrshrn_n_s16_(a: int16x8_t, n: i32) -> int8x8_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2.v8i16.p0i8")] + fn vst2q_s16_(a: int16x8_t, b: int16x8_t, ptr: *mut i8); } -vqrshrn_n_s16_(a, N) +vst2q_s16_(b.0, b.1, a.cast()) } -/// Signed saturating rounded shift right narrow +/// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqrshrn_n_s32(a: int32x4_t) -> int16x4_t { - static_assert!(N : i32 where N >= 1 && N <= 16); +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] +pub unsafe fn vst2q_s32(a: *mut i32, b: int32x4x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftns.v4i16")] - fn vqrshrn_n_s32_(a: int32x4_t, n: int32x4_t) -> int16x4_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2.p0i8.v4i32")] + fn vst2q_s32_(ptr: *mut i8, a: int32x4_t, b: int32x4_t, size: i32); } -vqrshrn_n_s32_(a, int32x4_t(-N as i32, -N as i32, -N as i32, -N as i32)) +vst2q_s32_(a.cast(), b.0, b.1, 4) } -/// Signed saturating rounded shift right narrow +/// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqrshrn_n_s32(a: int32x4_t) -> int16x4_t { - static_assert!(N : i32 where N >= 1 && N <= 16); +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +pub unsafe fn vst2q_s32(a: *mut i32, b: int32x4x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshrn.v4i16")] - fn vqrshrn_n_s32_(a: int32x4_t, n: i32) -> int16x4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2.v4i32.p0i8")] + fn vst2q_s32_(a: int32x4_t, b: int32x4_t, ptr: *mut i8); } -vqrshrn_n_s32_(a, N) +vst2q_s32_(b.0, b.1, a.cast()) } -/// Signed saturating rounded shift right narrow +/// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqrshrn_n_s64(a: int64x2_t) -> int32x2_t { - static_assert!(N : i32 where N >= 1 && N <= 32); +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +pub unsafe fn vst2_s64(a: *mut i64, b: int64x1x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftns.v2i32")] - fn vqrshrn_n_s64_(a: int64x2_t, n: int64x2_t) -> int32x2_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2.p0i8.v1i64")] + fn vst2_s64_(ptr: *mut i8, a: int64x1_t, b: int64x1_t, size: i32); } -vqrshrn_n_s64_(a, int64x2_t(-N as i64, -N as i64)) +vst2_s64_(a.cast(), b.0, b.1, 8) } -/// Signed saturating rounded shift right narrow +/// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqrshrn_n_s64(a: int64x2_t) -> int32x2_t { - static_assert!(N : i32 where N >= 1 && N <= 32); +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vst2_s64(a: *mut i64, b: int64x1x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshrn.v2i32")] - fn vqrshrn_n_s64_(a: int64x2_t, n: i32) -> int32x2_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2.v1i64.p0i8")] + fn vst2_s64_(a: int64x1_t, b: int64x1_t, ptr: *mut i8); } -vqrshrn_n_s64_(a, N) +vst2_s64_(b.0, b.1, a.cast()) } -/// Unsigned signed saturating rounded shift right narrow +/// Store multiple 2-element structures from two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +pub unsafe fn vst2_u8(a: *mut u8, b: uint8x8x2_t) { + transmute(vst2_s8(transmute(a), transmute(b))) +} + +/// Store multiple 2-element structures from two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +pub unsafe fn vst2_u16(a: *mut u16, b: uint16x4x2_t) { + transmute(vst2_s16(transmute(a), transmute(b))) +} + +/// Store multiple 2-element structures from two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +pub unsafe fn vst2_u32(a: *mut u32, b: uint32x2x2_t) { + transmute(vst2_s32(transmute(a), transmute(b))) +} + +/// Store multiple 2-element structures from two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +pub unsafe fn vst2q_u8(a: *mut u8, b: uint8x16x2_t) { + transmute(vst2q_s8(transmute(a), transmute(b))) +} + +/// Store multiple 2-element structures from two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +pub unsafe fn vst2q_u16(a: *mut u16, b: uint16x8x2_t) { + transmute(vst2q_s16(transmute(a), transmute(b))) +} + +/// Store multiple 2-element structures from two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +pub unsafe fn vst2q_u32(a: *mut u32, b: uint32x4x2_t) { + transmute(vst2q_s32(transmute(a), transmute(b))) +} + +/// Store multiple 2-element structures from two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +pub unsafe fn vst2_p8(a: *mut p8, b: poly8x8x2_t) { + transmute(vst2_s8(transmute(a), transmute(b))) +} + +/// Store multiple 2-element structures from two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +pub unsafe fn vst2_p16(a: *mut p16, b: poly16x4x2_t) { + transmute(vst2_s16(transmute(a), transmute(b))) +} + +/// Store multiple 2-element structures from two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +pub unsafe fn vst2q_p8(a: *mut p8, b: poly8x16x2_t) { + transmute(vst2q_s8(transmute(a), transmute(b))) +} + +/// Store multiple 2-element structures from two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +pub unsafe fn vst2q_p16(a: *mut p16, b: poly16x8x2_t) { + transmute(vst2q_s16(transmute(a), transmute(b))) +} + +/// Store multiple 2-element structures from two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vst2_u64(a: *mut u64, b: uint64x1x2_t) { + transmute(vst2_s64(transmute(a), transmute(b))) +} + +/// Store multiple 2-element structures from two registers +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vst2_p64(a: *mut p64, b: poly64x1x2_t) { + transmute(vst2_s64(transmute(a), transmute(b))) +} + +/// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqrshrn_n_u16(a: uint16x8_t) -> uint8x8_t { - static_assert!(N : i32 where N >= 1 && N <= 8); +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] +pub unsafe fn vst2_f32(a: *mut f32, b: float32x2x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftnu.v8i8")] - fn vqrshrn_n_u16_(a: uint16x8_t, n: uint16x8_t) -> uint8x8_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2.p0i8.v2f32")] + fn vst2_f32_(ptr: *mut i8, a: float32x2_t, b: float32x2_t, size: i32); } -vqrshrn_n_u16_(a, uint16x8_t(-N as u16, -N as u16, -N as u16, -N as u16, -N as u16, -N as u16, -N as u16, -N as u16)) +vst2_f32_(a.cast(), b.0, b.1, 4) } -/// Unsigned signed saturating rounded shift right narrow +/// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqrshrn_n_u16(a: uint16x8_t) -> uint8x8_t { - static_assert!(N : i32 where N >= 1 && N <= 8); +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +pub unsafe fn vst2_f32(a: *mut f32, b: float32x2x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqrshrn.v8i8")] - fn vqrshrn_n_u16_(a: uint16x8_t, n: i32) -> uint8x8_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2.v2f32.p0i8")] + fn vst2_f32_(a: float32x2_t, b: float32x2_t, ptr: *mut i8); } -vqrshrn_n_u16_(a, N) +vst2_f32_(b.0, b.1, a.cast()) } -/// Unsigned signed saturating rounded shift right narrow +/// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqrshrn_n_u32(a: uint32x4_t) -> uint16x4_t { - static_assert!(N : i32 where N >= 1 && N <= 16); +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] +pub unsafe fn vst2q_f32(a: *mut f32, b: float32x4x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftnu.v4i16")] - fn vqrshrn_n_u32_(a: uint32x4_t, n: uint32x4_t) -> uint16x4_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2.p0i8.v4f32")] + fn vst2q_f32_(ptr: *mut i8, a: float32x4_t, b: float32x4_t, size: i32); } -vqrshrn_n_u32_(a, uint32x4_t(-N as u32, -N as u32, -N as u32, -N as u32)) +vst2q_f32_(a.cast(), b.0, b.1, 4) } -/// Unsigned signed saturating rounded shift right narrow +/// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqrshrn_n_u32(a: uint32x4_t) -> uint16x4_t { - static_assert!(N : i32 where N >= 1 && N <= 16); +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +pub unsafe fn vst2q_f32(a: *mut f32, b: float32x4x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqrshrn.v4i16")] - fn vqrshrn_n_u32_(a: uint32x4_t, n: i32) -> uint16x4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2.v4f32.p0i8")] + fn vst2q_f32_(a: float32x4_t, b: float32x4_t, ptr: *mut i8); } -vqrshrn_n_u32_(a, N) +vst2q_f32_(b.0, b.1, a.cast()) } -/// Unsigned signed saturating rounded shift right narrow +/// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqrshrn_n_u64(a: uint64x2_t) -> uint32x2_t { - static_assert!(N : i32 where N >= 1 && N <= 32); +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2_lane_s8(a: *mut i8, b: int8x8x2_t) { + static_assert_imm3!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftnu.v2i32")] - fn vqrshrn_n_u64_(a: uint64x2_t, n: uint64x2_t) -> uint32x2_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2lane.p0i8.v8i8")] + fn vst2_lane_s8_(ptr: *mut i8, a: int8x8_t, b: int8x8_t, n: i32, size: i32); } -vqrshrn_n_u64_(a, uint64x2_t(-N as u64, -N as u64)) +vst2_lane_s8_(a.cast(), b.0, b.1, LANE, 1) } -/// Unsigned signed saturating rounded shift right narrow +/// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqrshrn_n_u64(a: uint64x2_t) -> uint32x2_t { - static_assert!(N : i32 where N >= 1 && N <= 32); +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2_lane_s8(a: *mut i8, b: int8x8x2_t) { + static_assert_imm3!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqrshrn.v2i32")] - fn vqrshrn_n_u64_(a: uint64x2_t, n: i32) -> uint32x2_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2lane.v8i8.p0i8")] + fn vst2_lane_s8_(a: int8x8_t, b: int8x8_t, n: i64, ptr: *mut i8); } -vqrshrn_n_u64_(a, N) +vst2_lane_s8_(b.0, b.1, LANE as i64, a.cast()) } -/// Signed saturating rounded shift right unsigned narrow +/// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshrun, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqrshrun_n_s16(a: int16x8_t) -> uint8x8_t { - static_assert!(N : i32 where N >= 1 && N <= 8); +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2_lane_s16(a: *mut i16, b: int16x4x2_t) { + static_assert_imm2!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftnsu.v8i8")] - fn vqrshrun_n_s16_(a: int16x8_t, n: int16x8_t) -> uint8x8_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2lane.p0i8.v4i16")] + fn vst2_lane_s16_(ptr: *mut i8, a: int16x4_t, b: int16x4_t, n: i32, size: i32); } -vqrshrun_n_s16_(a, int16x8_t(-N as i16, -N as i16, -N as i16, -N as i16, -N as i16, -N as i16, -N as i16, -N as i16)) +vst2_lane_s16_(a.cast(), b.0, b.1, LANE, 2) } -/// Signed saturating rounded shift right unsigned narrow +/// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshrun, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqrshrun_n_s16(a: int16x8_t) -> uint8x8_t { - static_assert!(N : i32 where N >= 1 && N <= 8); +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2_lane_s16(a: *mut i16, b: int16x4x2_t) { + static_assert_imm2!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshrun.v8i8")] - fn vqrshrun_n_s16_(a: int16x8_t, n: i32) -> uint8x8_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2lane.v4i16.p0i8")] + fn vst2_lane_s16_(a: int16x4_t, b: int16x4_t, n: i64, ptr: *mut i8); } -vqrshrun_n_s16_(a, N) +vst2_lane_s16_(b.0, b.1, LANE as i64, a.cast()) } -/// Signed saturating rounded shift right unsigned narrow +/// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshrun, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqrshrun_n_s32(a: int32x4_t) -> uint16x4_t { - static_assert!(N : i32 where N >= 1 && N <= 16); +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2_lane_s32(a: *mut i32, b: int32x2x2_t) { + static_assert_imm1!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftnsu.v4i16")] - fn vqrshrun_n_s32_(a: int32x4_t, n: int32x4_t) -> uint16x4_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2lane.p0i8.v2i32")] + fn vst2_lane_s32_(ptr: *mut i8, a: int32x2_t, b: int32x2_t, n: i32, size: i32); } -vqrshrun_n_s32_(a, int32x4_t(-N as i32, -N as i32, -N as i32, -N as i32)) +vst2_lane_s32_(a.cast(), b.0, b.1, LANE, 4) } -/// Signed saturating rounded shift right unsigned narrow +/// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshrun, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqrshrun_n_s32(a: int32x4_t) -> uint16x4_t { - static_assert!(N : i32 where N >= 1 && N <= 16); +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2_lane_s32(a: *mut i32, b: int32x2x2_t) { + static_assert_imm1!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshrun.v4i16")] - fn vqrshrun_n_s32_(a: int32x4_t, n: i32) -> uint16x4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2lane.v2i32.p0i8")] + fn vst2_lane_s32_(a: int32x2_t, b: int32x2_t, n: i64, ptr: *mut i8); } -vqrshrun_n_s32_(a, N) +vst2_lane_s32_(b.0, b.1, LANE as i64, a.cast()) } -/// Signed saturating rounded shift right unsigned narrow +/// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshrun, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqrshrun_n_s64(a: int64x2_t) -> uint32x2_t { - static_assert!(N : i32 where N >= 1 && N <= 32); +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2q_lane_s16(a: *mut i16, b: int16x8x2_t) { + static_assert_imm3!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftnsu.v2i32")] - fn vqrshrun_n_s64_(a: int64x2_t, n: int64x2_t) -> uint32x2_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2lane.p0i8.v8i16")] + fn vst2q_lane_s16_(ptr: *mut i8, a: int16x8_t, b: int16x8_t, n: i32, size: i32); } -vqrshrun_n_s64_(a, int64x2_t(-N as i64, -N as i64)) +vst2q_lane_s16_(a.cast(), b.0, b.1, LANE, 2) } -/// Signed saturating rounded shift right unsigned narrow +/// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshrun, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqrshrun_n_s64(a: int64x2_t) -> uint32x2_t { - static_assert!(N : i32 where N >= 1 && N <= 32); +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2q_lane_s16(a: *mut i16, b: int16x8x2_t) { + static_assert_imm3!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshrun.v2i32")] - fn vqrshrun_n_s64_(a: int64x2_t, n: i32) -> uint32x2_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2lane.v8i16.p0i8")] + fn vst2q_lane_s16_(a: int16x8_t, b: int16x8_t, n: i64, ptr: *mut i8); } -vqrshrun_n_s64_(a, N) +vst2q_lane_s16_(b.0, b.1, LANE as i64, a.cast()) } -/// Signed saturating shift left +/// Store multiple 2-element structures from two registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))] -pub unsafe fn vqshl_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2q_lane_s32(a: *mut i32, b: int32x4x2_t) { + static_assert_imm2!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshifts.v8i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshl.v8i8")] - fn vqshl_s8_(a: int8x8_t, b: int8x8_t) -> int8x8_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2lane.p0i8.v4i32")] + fn vst2q_lane_s32_(ptr: *mut i8, a: int32x4_t, b: int32x4_t, n: i32, size: i32); } -vqshl_s8_(a, b) +vst2q_lane_s32_(a.cast(), b.0, b.1, LANE, 4) } -/// Signed saturating shift left +/// Store multiple 2-element structures from two registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))] -pub unsafe fn vqshlq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2q_lane_s32(a: *mut i32, b: int32x4x2_t) { + static_assert_imm2!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshifts.v16i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshl.v16i8")] - fn vqshlq_s8_(a: int8x16_t, b: int8x16_t) -> int8x16_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2lane.v4i32.p0i8")] + fn vst2q_lane_s32_(a: int32x4_t, b: int32x4_t, n: i64, ptr: *mut i8); } -vqshlq_s8_(a, b) +vst2q_lane_s32_(b.0, b.1, LANE as i64, a.cast()) } -/// Signed saturating shift left +/// Store multiple 2-element structures from two registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))] -pub unsafe fn vqshl_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshifts.v4i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshl.v4i16")] - fn vqshl_s16_(a: int16x4_t, b: int16x4_t) -> int16x4_t; - } -vqshl_s16_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2_lane_u8(a: *mut u8, b: uint8x8x2_t) { + static_assert_imm3!(LANE); + transmute(vst2_lane_s8::(transmute(a), transmute(b))) } -/// Signed saturating shift left +/// Store multiple 2-element structures from two registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))] -pub unsafe fn vqshlq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshifts.v8i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshl.v8i16")] - fn vqshlq_s16_(a: int16x8_t, b: int16x8_t) -> int16x8_t; - } -vqshlq_s16_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2_lane_u16(a: *mut u16, b: uint16x4x2_t) { + static_assert_imm2!(LANE); + transmute(vst2_lane_s16::(transmute(a), transmute(b))) } -/// Signed saturating shift left +/// Store multiple 2-element structures from two registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))] -pub unsafe fn vqshl_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshifts.v2i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshl.v2i32")] - fn vqshl_s32_(a: int32x2_t, b: int32x2_t) -> int32x2_t; - } -vqshl_s32_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2_lane_u32(a: *mut u32, b: uint32x2x2_t) { + static_assert_imm1!(LANE); + transmute(vst2_lane_s32::(transmute(a), transmute(b))) } -/// Signed saturating shift left +/// Store multiple 2-element structures from two registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))] -pub unsafe fn vqshlq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshifts.v4i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshl.v4i32")] - fn vqshlq_s32_(a: int32x4_t, b: int32x4_t) -> int32x4_t; - } -vqshlq_s32_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2q_lane_u16(a: *mut u16, b: uint16x8x2_t) { + static_assert_imm3!(LANE); + transmute(vst2q_lane_s16::(transmute(a), transmute(b))) } -/// Signed saturating shift left +/// Store multiple 2-element structures from two registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))] -pub unsafe fn vqshl_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2q_lane_u32(a: *mut u32, b: uint32x4x2_t) { + static_assert_imm2!(LANE); + transmute(vst2q_lane_s32::(transmute(a), transmute(b))) +} + +/// Store multiple 2-element structures from two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2_lane_p8(a: *mut p8, b: poly8x8x2_t) { + static_assert_imm3!(LANE); + transmute(vst2_lane_s8::(transmute(a), transmute(b))) +} + +/// Store multiple 2-element structures from two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2_lane_p16(a: *mut p16, b: poly16x4x2_t) { + static_assert_imm2!(LANE); + transmute(vst2_lane_s16::(transmute(a), transmute(b))) +} + +/// Store multiple 2-element structures from two registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2q_lane_p16(a: *mut p16, b: poly16x8x2_t) { + static_assert_imm3!(LANE); + transmute(vst2q_lane_s16::(transmute(a), transmute(b))) +} + +/// Store multiple 2-element structures from two registers +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2_lane_f32(a: *mut f32, b: float32x2x2_t) { + static_assert_imm1!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshifts.v1i64")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshl.v1i64")] - fn vqshl_s64_(a: int64x1_t, b: int64x1_t) -> int64x1_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2lane.p0i8.v2f32")] + fn vst2_lane_f32_(ptr: *mut i8, a: float32x2_t, b: float32x2_t, n: i32, size: i32); } -vqshl_s64_(a, b) +vst2_lane_f32_(a.cast(), b.0, b.1, LANE, 4) } -/// Signed saturating shift left +/// Store multiple 2-element structures from two registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))] -pub unsafe fn vqshlq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2_lane_f32(a: *mut f32, b: float32x2x2_t) { + static_assert_imm1!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshifts.v2i64")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshl.v2i64")] - fn vqshlq_s64_(a: int64x2_t, b: int64x2_t) -> int64x2_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2lane.v2f32.p0i8")] + fn vst2_lane_f32_(a: float32x2_t, b: float32x2_t, n: i64, ptr: *mut i8); } -vqshlq_s64_(a, b) +vst2_lane_f32_(b.0, b.1, LANE as i64, a.cast()) } -/// Unsigned saturating shift left +/// Store multiple 2-element structures from two registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))] -pub unsafe fn vqshl_u8(a: uint8x8_t, b: int8x8_t) -> uint8x8_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2q_lane_f32(a: *mut f32, b: float32x4x2_t) { + static_assert_imm2!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftu.v8i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqshl.v8i8")] - fn vqshl_u8_(a: uint8x8_t, b: int8x8_t) -> uint8x8_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2lane.p0i8.v4f32")] + fn vst2q_lane_f32_(ptr: *mut i8, a: float32x4_t, b: float32x4_t, n: i32, size: i32); } -vqshl_u8_(a, b) +vst2q_lane_f32_(a.cast(), b.0, b.1, LANE, 4) } -/// Unsigned saturating shift left +/// Store multiple 2-element structures from two registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))] -pub unsafe fn vqshlq_u8(a: uint8x16_t, b: int8x16_t) -> uint8x16_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst2q_lane_f32(a: *mut f32, b: float32x4x2_t) { + static_assert_imm2!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftu.v16i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqshl.v16i8")] - fn vqshlq_u8_(a: uint8x16_t, b: int8x16_t) -> uint8x16_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2lane.v4f32.p0i8")] + fn vst2q_lane_f32_(a: float32x4_t, b: float32x4_t, n: i64, ptr: *mut i8); } -vqshlq_u8_(a, b) +vst2q_lane_f32_(b.0, b.1, LANE as i64, a.cast()) } -/// Unsigned saturating shift left +/// Store multiple 3-element structures from three registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))] -pub unsafe fn vqshl_u16(a: uint16x4_t, b: int16x4_t) -> uint16x4_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] +pub unsafe fn vst3_s8(a: *mut i8, b: int8x8x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftu.v4i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqshl.v4i16")] - fn vqshl_u16_(a: uint16x4_t, b: int16x4_t) -> uint16x4_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3.p0i8.v8i8")] + fn vst3_s8_(ptr: *mut i8, a: int8x8_t, b: int8x8_t, c: int8x8_t, size: i32); } -vqshl_u16_(a, b) +vst3_s8_(a.cast(), b.0, b.1, b.2, 1) } -/// Unsigned saturating shift left +/// Store multiple 3-element structures from three registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))] -pub unsafe fn vqshlq_u16(a: uint16x8_t, b: int16x8_t) -> uint16x8_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +pub unsafe fn vst3_s8(a: *mut i8, b: int8x8x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftu.v8i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqshl.v8i16")] - fn vqshlq_u16_(a: uint16x8_t, b: int16x8_t) -> uint16x8_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3.v8i8.p0i8")] + fn vst3_s8_(a: int8x8_t, b: int8x8_t, c: int8x8_t, ptr: *mut i8); } -vqshlq_u16_(a, b) +vst3_s8_(b.0, b.1, b.2, a.cast()) } -/// Unsigned saturating shift left +/// Store multiple 3-element structures from three registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))] -pub unsafe fn vqshl_u32(a: uint32x2_t, b: int32x2_t) -> uint32x2_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] +pub unsafe fn vst3_s16(a: *mut i16, b: int16x4x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftu.v2i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqshl.v2i32")] - fn vqshl_u32_(a: uint32x2_t, b: int32x2_t) -> uint32x2_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3.p0i8.v4i16")] + fn vst3_s16_(ptr: *mut i8, a: int16x4_t, b: int16x4_t, c: int16x4_t, size: i32); } -vqshl_u32_(a, b) +vst3_s16_(a.cast(), b.0, b.1, b.2, 2) } -/// Unsigned saturating shift left +/// Store multiple 3-element structures from three registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))] -pub unsafe fn vqshlq_u32(a: uint32x4_t, b: int32x4_t) -> uint32x4_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +pub unsafe fn vst3_s16(a: *mut i16, b: int16x4x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftu.v4i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqshl.v4i32")] - fn vqshlq_u32_(a: uint32x4_t, b: int32x4_t) -> uint32x4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3.v4i16.p0i8")] + fn vst3_s16_(a: int16x4_t, b: int16x4_t, c: int16x4_t, ptr: *mut i8); } -vqshlq_u32_(a, b) +vst3_s16_(b.0, b.1, b.2, a.cast()) } -/// Unsigned saturating shift left +/// Store multiple 3-element structures from three registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))] -pub unsafe fn vqshl_u64(a: uint64x1_t, b: int64x1_t) -> uint64x1_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] +pub unsafe fn vst3_s32(a: *mut i32, b: int32x2x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftu.v1i64")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqshl.v1i64")] - fn vqshl_u64_(a: uint64x1_t, b: int64x1_t) -> uint64x1_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3.p0i8.v2i32")] + fn vst3_s32_(ptr: *mut i8, a: int32x2_t, b: int32x2_t, c: int32x2_t, size: i32); } -vqshl_u64_(a, b) +vst3_s32_(a.cast(), b.0, b.1, b.2, 4) } -/// Unsigned saturating shift left +/// Store multiple 3-element structures from three registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))] -pub unsafe fn vqshlq_u64(a: uint64x2_t, b: int64x2_t) -> uint64x2_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +pub unsafe fn vst3_s32(a: *mut i32, b: int32x2x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftu.v2i64")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqshl.v2i64")] - fn vqshlq_u64_(a: uint64x2_t, b: int64x2_t) -> uint64x2_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3.v2i32.p0i8")] + fn vst3_s32_(a: int32x2_t, b: int32x2_t, c: int32x2_t, ptr: *mut i8); } -vqshlq_u64_(a, b) +vst3_s32_(b.0, b.1, b.2, a.cast()) } -/// Signed saturating shift left +/// Store multiple 3-element structures from three registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshl_n_s8(a: int8x8_t) -> int8x8_t { - static_assert_imm3!(N); - vqshl_s8(a, vdup_n_s8(N.try_into().unwrap())) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] +pub unsafe fn vst3q_s8(a: *mut i8, b: int8x16x3_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3.p0i8.v16i8")] + fn vst3q_s8_(ptr: *mut i8, a: int8x16_t, b: int8x16_t, c: int8x16_t, size: i32); + } +vst3q_s8_(a.cast(), b.0, b.1, b.2, 1) } -/// Signed saturating shift left +/// Store multiple 3-element structures from three registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshlq_n_s8(a: int8x16_t) -> int8x16_t { - static_assert_imm3!(N); - vqshlq_s8(a, vdupq_n_s8(N.try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +pub unsafe fn vst3q_s8(a: *mut i8, b: int8x16x3_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3.v16i8.p0i8")] + fn vst3q_s8_(a: int8x16_t, b: int8x16_t, c: int8x16_t, ptr: *mut i8); + } +vst3q_s8_(b.0, b.1, b.2, a.cast()) } -/// Signed saturating shift left +/// Store multiple 3-element structures from three registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshl_n_s16(a: int16x4_t) -> int16x4_t { - static_assert_imm4!(N); - vqshl_s16(a, vdup_n_s16(N.try_into().unwrap())) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] +pub unsafe fn vst3q_s16(a: *mut i16, b: int16x8x3_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3.p0i8.v8i16")] + fn vst3q_s16_(ptr: *mut i8, a: int16x8_t, b: int16x8_t, c: int16x8_t, size: i32); + } +vst3q_s16_(a.cast(), b.0, b.1, b.2, 2) } -/// Signed saturating shift left +/// Store multiple 3-element structures from three registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshlq_n_s16(a: int16x8_t) -> int16x8_t { - static_assert_imm4!(N); - vqshlq_s16(a, vdupq_n_s16(N.try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +pub unsafe fn vst3q_s16(a: *mut i16, b: int16x8x3_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3.v8i16.p0i8")] + fn vst3q_s16_(a: int16x8_t, b: int16x8_t, c: int16x8_t, ptr: *mut i8); + } +vst3q_s16_(b.0, b.1, b.2, a.cast()) } -/// Signed saturating shift left +/// Store multiple 3-element structures from three registers +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] +pub unsafe fn vst3q_s32(a: *mut i32, b: int32x4x3_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3.p0i8.v4i32")] + fn vst3q_s32_(ptr: *mut i8, a: int32x4_t, b: int32x4_t, c: int32x4_t, size: i32); + } +vst3q_s32_(a.cast(), b.0, b.1, b.2, 4) +} + +/// Store multiple 3-element structures from three registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshl_n_s32(a: int32x2_t) -> int32x2_t { - static_assert_imm5!(N); - vqshl_s32(a, vdup_n_s32(N.try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +pub unsafe fn vst3q_s32(a: *mut i32, b: int32x4x3_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3.v4i32.p0i8")] + fn vst3q_s32_(a: int32x4_t, b: int32x4_t, c: int32x4_t, ptr: *mut i8); + } +vst3q_s32_(b.0, b.1, b.2, a.cast()) } -/// Signed saturating shift left +/// Store multiple 3-element structures from three registers +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +pub unsafe fn vst3_s64(a: *mut i64, b: int64x1x3_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3.p0i8.v1i64")] + fn vst3_s64_(ptr: *mut i8, a: int64x1_t, b: int64x1_t, c: int64x1_t, size: i32); + } +vst3_s64_(a.cast(), b.0, b.1, b.2, 8) +} + +/// Store multiple 3-element structures from three registers +#[inline] +#[cfg(target_arch = "aarch64")] +#[target_feature(enable = "neon")] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vst3_s64(a: *mut i64, b: int64x1x3_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3.v1i64.p0i8")] + fn vst3_s64_(a: int64x1_t, b: int64x1_t, c: int64x1_t, ptr: *mut i8); + } +vst3_s64_(b.0, b.1, b.2, a.cast()) +} + +/// Store multiple 3-element structures from three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshlq_n_s32(a: int32x4_t) -> int32x4_t { - static_assert_imm5!(N); - vqshlq_s32(a, vdupq_n_s32(N.try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +pub unsafe fn vst3_u8(a: *mut u8, b: uint8x8x3_t) { + transmute(vst3_s8(transmute(a), transmute(b))) } -/// Signed saturating shift left +/// Store multiple 3-element structures from three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshl_n_s64(a: int64x1_t) -> int64x1_t { - static_assert_imm6!(N); - vqshl_s64(a, vdup_n_s64(N.try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +pub unsafe fn vst3_u16(a: *mut u16, b: uint16x4x3_t) { + transmute(vst3_s16(transmute(a), transmute(b))) } -/// Signed saturating shift left +/// Store multiple 3-element structures from three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshlq_n_s64(a: int64x2_t) -> int64x2_t { - static_assert_imm6!(N); - vqshlq_s64(a, vdupq_n_s64(N.try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +pub unsafe fn vst3_u32(a: *mut u32, b: uint32x2x3_t) { + transmute(vst3_s32(transmute(a), transmute(b))) } -/// Unsigned saturating shift left +/// Store multiple 3-element structures from three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshl_n_u8(a: uint8x8_t) -> uint8x8_t { - static_assert_imm3!(N); - vqshl_u8(a, vdup_n_s8(N.try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +pub unsafe fn vst3q_u8(a: *mut u8, b: uint8x16x3_t) { + transmute(vst3q_s8(transmute(a), transmute(b))) } -/// Unsigned saturating shift left +/// Store multiple 3-element structures from three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshlq_n_u8(a: uint8x16_t) -> uint8x16_t { - static_assert_imm3!(N); - vqshlq_u8(a, vdupq_n_s8(N.try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +pub unsafe fn vst3q_u16(a: *mut u16, b: uint16x8x3_t) { + transmute(vst3q_s16(transmute(a), transmute(b))) } -/// Unsigned saturating shift left +/// Store multiple 3-element structures from three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshl_n_u16(a: uint16x4_t) -> uint16x4_t { - static_assert_imm4!(N); - vqshl_u16(a, vdup_n_s16(N.try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +pub unsafe fn vst3q_u32(a: *mut u32, b: uint32x4x3_t) { + transmute(vst3q_s32(transmute(a), transmute(b))) } -/// Unsigned saturating shift left +/// Store multiple 3-element structures from three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshlq_n_u16(a: uint16x8_t) -> uint16x8_t { - static_assert_imm4!(N); - vqshlq_u16(a, vdupq_n_s16(N.try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +pub unsafe fn vst3_p8(a: *mut p8, b: poly8x8x3_t) { + transmute(vst3_s8(transmute(a), transmute(b))) } -/// Unsigned saturating shift left +/// Store multiple 3-element structures from three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshl_n_u32(a: uint32x2_t) -> uint32x2_t { - static_assert_imm5!(N); - vqshl_u32(a, vdup_n_s32(N.try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +pub unsafe fn vst3_p16(a: *mut p16, b: poly16x4x3_t) { + transmute(vst3_s16(transmute(a), transmute(b))) } -/// Unsigned saturating shift left +/// Store multiple 3-element structures from three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshlq_n_u32(a: uint32x4_t) -> uint32x4_t { - static_assert_imm5!(N); - vqshlq_u32(a, vdupq_n_s32(N.try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +pub unsafe fn vst3q_p8(a: *mut p8, b: poly8x16x3_t) { + transmute(vst3q_s8(transmute(a), transmute(b))) } -/// Unsigned saturating shift left +/// Store multiple 3-element structures from three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshl_n_u64(a: uint64x1_t) -> uint64x1_t { - static_assert_imm6!(N); - vqshl_u64(a, vdup_n_s64(N.try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +pub unsafe fn vst3q_p16(a: *mut p16, b: poly16x8x3_t) { + transmute(vst3q_s16(transmute(a), transmute(b))) } -/// Unsigned saturating shift left +/// Store multiple 3-element structures from three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshlq_n_u64(a: uint64x2_t) -> uint64x2_t { - static_assert_imm6!(N); - vqshlq_u64(a, vdupq_n_s64(N.try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vst3_u64(a: *mut u64, b: uint64x1x3_t) { + transmute(vst3_s64(transmute(a), transmute(b))) } -/// Signed saturating shift right narrow +/// Store multiple 3-element structures from three registers +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vst3_p64(a: *mut p64, b: poly64x1x3_t) { + transmute(vst3_s64(transmute(a), transmute(b))) +} + +/// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshrn_n_s16(a: int16x8_t) -> int8x8_t { - static_assert!(N : i32 where N >= 1 && N <= 8); +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] +pub unsafe fn vst3_f32(a: *mut f32, b: float32x2x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftns.v8i8")] - fn vqshrn_n_s16_(a: int16x8_t, n: int16x8_t) -> int8x8_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3.p0i8.v2f32")] + fn vst3_f32_(ptr: *mut i8, a: float32x2_t, b: float32x2_t, c: float32x2_t, size: i32); } -vqshrn_n_s16_(a, int16x8_t(-N as i16, -N as i16, -N as i16, -N as i16, -N as i16, -N as i16, -N as i16, -N as i16)) +vst3_f32_(a.cast(), b.0, b.1, b.2, 4) } -/// Signed saturating shift right narrow +/// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshrn_n_s16(a: int16x8_t) -> int8x8_t { - static_assert!(N : i32 where N >= 1 && N <= 8); +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +pub unsafe fn vst3_f32(a: *mut f32, b: float32x2x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshrn.v8i8")] - fn vqshrn_n_s16_(a: int16x8_t, n: i32) -> int8x8_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3.v2f32.p0i8")] + fn vst3_f32_(a: float32x2_t, b: float32x2_t, c: float32x2_t, ptr: *mut i8); } -vqshrn_n_s16_(a, N) +vst3_f32_(b.0, b.1, b.2, a.cast()) } -/// Signed saturating shift right narrow +/// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshrn_n_s32(a: int32x4_t) -> int16x4_t { - static_assert!(N : i32 where N >= 1 && N <= 16); +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] +pub unsafe fn vst3q_f32(a: *mut f32, b: float32x4x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftns.v4i16")] - fn vqshrn_n_s32_(a: int32x4_t, n: int32x4_t) -> int16x4_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3.p0i8.v4f32")] + fn vst3q_f32_(ptr: *mut i8, a: float32x4_t, b: float32x4_t, c: float32x4_t, size: i32); } -vqshrn_n_s32_(a, int32x4_t(-N as i32, -N as i32, -N as i32, -N as i32)) +vst3q_f32_(a.cast(), b.0, b.1, b.2, 4) } -/// Signed saturating shift right narrow +/// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshrn_n_s32(a: int32x4_t) -> int16x4_t { - static_assert!(N : i32 where N >= 1 && N <= 16); +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +pub unsafe fn vst3q_f32(a: *mut f32, b: float32x4x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshrn.v4i16")] - fn vqshrn_n_s32_(a: int32x4_t, n: i32) -> int16x4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3.v4f32.p0i8")] + fn vst3q_f32_(a: float32x4_t, b: float32x4_t, c: float32x4_t, ptr: *mut i8); } -vqshrn_n_s32_(a, N) +vst3q_f32_(b.0, b.1, b.2, a.cast()) } -/// Signed saturating shift right narrow +/// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshrn_n_s64(a: int64x2_t) -> int32x2_t { - static_assert!(N : i32 where N >= 1 && N <= 32); +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3_lane_s8(a: *mut i8, b: int8x8x3_t) { + static_assert_imm3!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftns.v2i32")] - fn vqshrn_n_s64_(a: int64x2_t, n: int64x2_t) -> int32x2_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3lane.p0i8.v8i8")] + fn vst3_lane_s8_(ptr: *mut i8, a: int8x8_t, b: int8x8_t, c: int8x8_t, n: i32, size: i32); } -vqshrn_n_s64_(a, int64x2_t(-N as i64, -N as i64)) +vst3_lane_s8_(a.cast(), b.0, b.1, b.2, LANE, 1) } -/// Signed saturating shift right narrow +/// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshrn_n_s64(a: int64x2_t) -> int32x2_t { - static_assert!(N : i32 where N >= 1 && N <= 32); +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3_lane_s8(a: *mut i8, b: int8x8x3_t) { + static_assert_imm3!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshrn.v2i32")] - fn vqshrn_n_s64_(a: int64x2_t, n: i32) -> int32x2_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3lane.v8i8.p0i8")] + fn vst3_lane_s8_(a: int8x8_t, b: int8x8_t, c: int8x8_t, n: i64, ptr: *mut i8); } -vqshrn_n_s64_(a, N) +vst3_lane_s8_(b.0, b.1, b.2, LANE as i64, a.cast()) } -/// Unsigned saturating shift right narrow +/// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshrn_n_u16(a: uint16x8_t) -> uint8x8_t { - static_assert!(N : i32 where N >= 1 && N <= 8); +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3_lane_s16(a: *mut i16, b: int16x4x3_t) { + static_assert_imm2!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftnu.v8i8")] - fn vqshrn_n_u16_(a: uint16x8_t, n: uint16x8_t) -> uint8x8_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3lane.p0i8.v4i16")] + fn vst3_lane_s16_(ptr: *mut i8, a: int16x4_t, b: int16x4_t, c: int16x4_t, n: i32, size: i32); } -vqshrn_n_u16_(a, uint16x8_t(-N as u16, -N as u16, -N as u16, -N as u16, -N as u16, -N as u16, -N as u16, -N as u16)) +vst3_lane_s16_(a.cast(), b.0, b.1, b.2, LANE, 2) } -/// Unsigned saturating shift right narrow +/// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshrn_n_u16(a: uint16x8_t) -> uint8x8_t { - static_assert!(N : i32 where N >= 1 && N <= 8); +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3_lane_s16(a: *mut i16, b: int16x4x3_t) { + static_assert_imm2!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqshrn.v8i8")] - fn vqshrn_n_u16_(a: uint16x8_t, n: i32) -> uint8x8_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3lane.v4i16.p0i8")] + fn vst3_lane_s16_(a: int16x4_t, b: int16x4_t, c: int16x4_t, n: i64, ptr: *mut i8); } -vqshrn_n_u16_(a, N) +vst3_lane_s16_(b.0, b.1, b.2, LANE as i64, a.cast()) } -/// Unsigned saturating shift right narrow +/// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshrn_n_u32(a: uint32x4_t) -> uint16x4_t { - static_assert!(N : i32 where N >= 1 && N <= 16); +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3_lane_s32(a: *mut i32, b: int32x2x3_t) { + static_assert_imm1!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftnu.v4i16")] - fn vqshrn_n_u32_(a: uint32x4_t, n: uint32x4_t) -> uint16x4_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3lane.p0i8.v2i32")] + fn vst3_lane_s32_(ptr: *mut i8, a: int32x2_t, b: int32x2_t, c: int32x2_t, n: i32, size: i32); } -vqshrn_n_u32_(a, uint32x4_t(-N as u32, -N as u32, -N as u32, -N as u32)) +vst3_lane_s32_(a.cast(), b.0, b.1, b.2, LANE, 4) } -/// Unsigned saturating shift right narrow +/// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshrn_n_u32(a: uint32x4_t) -> uint16x4_t { - static_assert!(N : i32 where N >= 1 && N <= 16); +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3_lane_s32(a: *mut i32, b: int32x2x3_t) { + static_assert_imm1!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqshrn.v4i16")] - fn vqshrn_n_u32_(a: uint32x4_t, n: i32) -> uint16x4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3lane.v2i32.p0i8")] + fn vst3_lane_s32_(a: int32x2_t, b: int32x2_t, c: int32x2_t, n: i64, ptr: *mut i8); } -vqshrn_n_u32_(a, N) +vst3_lane_s32_(b.0, b.1, b.2, LANE as i64, a.cast()) } -/// Unsigned saturating shift right narrow +/// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshrn_n_u64(a: uint64x2_t) -> uint32x2_t { - static_assert!(N : i32 where N >= 1 && N <= 32); +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3q_lane_s16(a: *mut i16, b: int16x8x3_t) { + static_assert_imm3!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftnu.v2i32")] - fn vqshrn_n_u64_(a: uint64x2_t, n: uint64x2_t) -> uint32x2_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3lane.p0i8.v8i16")] + fn vst3q_lane_s16_(ptr: *mut i8, a: int16x8_t, b: int16x8_t, c: int16x8_t, n: i32, size: i32); } -vqshrn_n_u64_(a, uint64x2_t(-N as u64, -N as u64)) +vst3q_lane_s16_(a.cast(), b.0, b.1, b.2, LANE, 2) } -/// Unsigned saturating shift right narrow +/// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshrn_n_u64(a: uint64x2_t) -> uint32x2_t { - static_assert!(N : i32 where N >= 1 && N <= 32); +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3q_lane_s16(a: *mut i16, b: int16x8x3_t) { + static_assert_imm3!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqshrn.v2i32")] - fn vqshrn_n_u64_(a: uint64x2_t, n: i32) -> uint32x2_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3lane.v8i16.p0i8")] + fn vst3q_lane_s16_(a: int16x8_t, b: int16x8_t, c: int16x8_t, n: i64, ptr: *mut i8); } -vqshrn_n_u64_(a, N) +vst3q_lane_s16_(b.0, b.1, b.2, LANE as i64, a.cast()) } -/// Signed saturating shift right unsigned narrow +/// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshrun, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshrun_n_s16(a: int16x8_t) -> uint8x8_t { - static_assert!(N : i32 where N >= 1 && N <= 8); +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3q_lane_s32(a: *mut i32, b: int32x4x3_t) { + static_assert_imm2!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftnsu.v8i8")] - fn vqshrun_n_s16_(a: int16x8_t, n: int16x8_t) -> uint8x8_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3lane.p0i8.v4i32")] + fn vst3q_lane_s32_(ptr: *mut i8, a: int32x4_t, b: int32x4_t, c: int32x4_t, n: i32, size: i32); } -vqshrun_n_s16_(a, int16x8_t(-N as i16, -N as i16, -N as i16, -N as i16, -N as i16, -N as i16, -N as i16, -N as i16)) +vst3q_lane_s32_(a.cast(), b.0, b.1, b.2, LANE, 4) } -/// Signed saturating shift right unsigned narrow +/// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshrun, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshrun_n_s16(a: int16x8_t) -> uint8x8_t { - static_assert!(N : i32 where N >= 1 && N <= 8); +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3q_lane_s32(a: *mut i32, b: int32x4x3_t) { + static_assert_imm2!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshrun.v8i8")] - fn vqshrun_n_s16_(a: int16x8_t, n: i32) -> uint8x8_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3lane.v4i32.p0i8")] + fn vst3q_lane_s32_(a: int32x4_t, b: int32x4_t, c: int32x4_t, n: i64, ptr: *mut i8); } -vqshrun_n_s16_(a, N) +vst3q_lane_s32_(b.0, b.1, b.2, LANE as i64, a.cast()) } -/// Signed saturating shift right unsigned narrow +/// Store multiple 3-element structures from three registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3_lane_u8(a: *mut u8, b: uint8x8x3_t) { + static_assert_imm3!(LANE); + transmute(vst3_lane_s8::(transmute(a), transmute(b))) +} + +/// Store multiple 3-element structures from three registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3_lane_u16(a: *mut u16, b: uint16x4x3_t) { + static_assert_imm2!(LANE); + transmute(vst3_lane_s16::(transmute(a), transmute(b))) +} + +/// Store multiple 3-element structures from three registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3_lane_u32(a: *mut u32, b: uint32x2x3_t) { + static_assert_imm1!(LANE); + transmute(vst3_lane_s32::(transmute(a), transmute(b))) +} + +/// Store multiple 3-element structures from three registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3q_lane_u16(a: *mut u16, b: uint16x8x3_t) { + static_assert_imm3!(LANE); + transmute(vst3q_lane_s16::(transmute(a), transmute(b))) +} + +/// Store multiple 3-element structures from three registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3q_lane_u32(a: *mut u32, b: uint32x4x3_t) { + static_assert_imm2!(LANE); + transmute(vst3q_lane_s32::(transmute(a), transmute(b))) +} + +/// Store multiple 3-element structures from three registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3_lane_p8(a: *mut p8, b: poly8x8x3_t) { + static_assert_imm3!(LANE); + transmute(vst3_lane_s8::(transmute(a), transmute(b))) +} + +/// Store multiple 3-element structures from three registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3_lane_p16(a: *mut p16, b: poly16x4x3_t) { + static_assert_imm2!(LANE); + transmute(vst3_lane_s16::(transmute(a), transmute(b))) +} + +/// Store multiple 3-element structures from three registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3q_lane_p16(a: *mut p16, b: poly16x8x3_t) { + static_assert_imm3!(LANE); + transmute(vst3q_lane_s16::(transmute(a), transmute(b))) +} + +/// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshrun, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshrun_n_s32(a: int32x4_t) -> uint16x4_t { - static_assert!(N : i32 where N >= 1 && N <= 16); +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3_lane_f32(a: *mut f32, b: float32x2x3_t) { + static_assert_imm1!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftnsu.v4i16")] - fn vqshrun_n_s32_(a: int32x4_t, n: int32x4_t) -> uint16x4_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3lane.p0i8.v2f32")] + fn vst3_lane_f32_(ptr: *mut i8, a: float32x2_t, b: float32x2_t, c: float32x2_t, n: i32, size: i32); } -vqshrun_n_s32_(a, int32x4_t(-N as i32, -N as i32, -N as i32, -N as i32)) +vst3_lane_f32_(a.cast(), b.0, b.1, b.2, LANE, 4) } -/// Signed saturating shift right unsigned narrow +/// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshrun, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshrun_n_s32(a: int32x4_t) -> uint16x4_t { - static_assert!(N : i32 where N >= 1 && N <= 16); +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3_lane_f32(a: *mut f32, b: float32x2x3_t) { + static_assert_imm1!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshrun.v4i16")] - fn vqshrun_n_s32_(a: int32x4_t, n: i32) -> uint16x4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3lane.v2f32.p0i8")] + fn vst3_lane_f32_(a: float32x2_t, b: float32x2_t, c: float32x2_t, n: i64, ptr: *mut i8); } -vqshrun_n_s32_(a, N) +vst3_lane_f32_(b.0, b.1, b.2, LANE as i64, a.cast()) } -/// Signed saturating shift right unsigned narrow +/// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshrun, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshrun_n_s64(a: int64x2_t) -> uint32x2_t { - static_assert!(N : i32 where N >= 1 && N <= 32); +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3q_lane_f32(a: *mut f32, b: float32x4x3_t) { + static_assert_imm2!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftnsu.v2i32")] - fn vqshrun_n_s64_(a: int64x2_t, n: int64x2_t) -> uint32x2_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3lane.p0i8.v4f32")] + fn vst3q_lane_f32_(ptr: *mut i8, a: float32x4_t, b: float32x4_t, c: float32x4_t, n: i32, size: i32); } -vqshrun_n_s64_(a, int64x2_t(-N as i64, -N as i64)) +vst3q_lane_f32_(a.cast(), b.0, b.1, b.2, LANE, 4) } -/// Signed saturating shift right unsigned narrow +/// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshrun, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vqshrun_n_s64(a: int64x2_t) -> uint32x2_t { - static_assert!(N : i32 where N >= 1 && N <= 32); +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst3q_lane_f32(a: *mut f32, b: float32x4x3_t) { + static_assert_imm2!(LANE); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshrun.v2i32")] - fn vqshrun_n_s64_(a: int64x2_t, n: i32) -> uint32x2_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3lane.v4f32.p0i8")] + fn vst3q_lane_f32_(a: float32x4_t, b: float32x4_t, c: float32x4_t, n: i64, ptr: *mut i8); } -vqshrun_n_s64_(a, N) +vst3q_lane_f32_(b.0, b.1, b.2, LANE as i64, a.cast()) } -/// Reciprocal square-root estimate. +/// Store multiple 4-element structures from four registers +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] +pub unsafe fn vst4_s8(a: *mut i8, b: int8x8x4_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4.p0i8.v8i8")] + fn vst4_s8_(ptr: *mut i8, a: int8x8_t, b: int8x8_t, c: int8x8_t, d: int8x8_t, size: i32); + } +vst4_s8_(a.cast(), b.0, b.1, b.2, b.3, 1) +} + +/// Store multiple 4-element structures from four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsqrte))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frsqrte))] -pub unsafe fn vrsqrte_f32(a: float32x2_t) -> float32x2_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +pub unsafe fn vst4_s8(a: *mut i8, b: int8x8x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrsqrte.v2f32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frsqrte.v2f32")] - fn vrsqrte_f32_(a: float32x2_t) -> float32x2_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4.v8i8.p0i8")] + fn vst4_s8_(a: int8x8_t, b: int8x8_t, c: int8x8_t, d: int8x8_t, ptr: *mut i8); } -vrsqrte_f32_(a) +vst4_s8_(b.0, b.1, b.2, b.3, a.cast()) } -/// Reciprocal square-root estimate. +/// Store multiple 4-element structures from four registers +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] +pub unsafe fn vst4_s16(a: *mut i16, b: int16x4x4_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4.p0i8.v4i16")] + fn vst4_s16_(ptr: *mut i8, a: int16x4_t, b: int16x4_t, c: int16x4_t, d: int16x4_t, size: i32); + } +vst4_s16_(a.cast(), b.0, b.1, b.2, b.3, 2) +} + +/// Store multiple 4-element structures from four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsqrte))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frsqrte))] -pub unsafe fn vrsqrteq_f32(a: float32x4_t) -> float32x4_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +pub unsafe fn vst4_s16(a: *mut i16, b: int16x4x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrsqrte.v4f32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frsqrte.v4f32")] - fn vrsqrteq_f32_(a: float32x4_t) -> float32x4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4.v4i16.p0i8")] + fn vst4_s16_(a: int16x4_t, b: int16x4_t, c: int16x4_t, d: int16x4_t, ptr: *mut i8); } -vrsqrteq_f32_(a) +vst4_s16_(b.0, b.1, b.2, b.3, a.cast()) } -/// Reciprocal estimate. +/// Store multiple 4-element structures from four registers +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] +pub unsafe fn vst4_s32(a: *mut i32, b: int32x2x4_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4.p0i8.v2i32")] + fn vst4_s32_(ptr: *mut i8, a: int32x2_t, b: int32x2_t, c: int32x2_t, d: int32x2_t, size: i32); + } +vst4_s32_(a.cast(), b.0, b.1, b.2, b.3, 4) +} + +/// Store multiple 4-element structures from four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrecpe))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frecpe))] -pub unsafe fn vrecpe_f32(a: float32x2_t) -> float32x2_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +pub unsafe fn vst4_s32(a: *mut i32, b: int32x2x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrecpe.v2f32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frecpe.v2f32")] - fn vrecpe_f32_(a: float32x2_t) -> float32x2_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4.v2i32.p0i8")] + fn vst4_s32_(a: int32x2_t, b: int32x2_t, c: int32x2_t, d: int32x2_t, ptr: *mut i8); } -vrecpe_f32_(a) +vst4_s32_(b.0, b.1, b.2, b.3, a.cast()) } -/// Reciprocal estimate. +/// Store multiple 4-element structures from four registers +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] +pub unsafe fn vst4q_s8(a: *mut i8, b: int8x16x4_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4.p0i8.v16i8")] + fn vst4q_s8_(ptr: *mut i8, a: int8x16_t, b: int8x16_t, c: int8x16_t, d: int8x16_t, size: i32); + } +vst4q_s8_(a.cast(), b.0, b.1, b.2, b.3, 1) +} + +/// Store multiple 4-element structures from four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrecpe))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frecpe))] -pub unsafe fn vrecpeq_f32(a: float32x4_t) -> float32x4_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +pub unsafe fn vst4q_s8(a: *mut i8, b: int8x16x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrecpe.v4f32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frecpe.v4f32")] - fn vrecpeq_f32_(a: float32x4_t) -> float32x4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4.v16i8.p0i8")] + fn vst4q_s8_(a: int8x16_t, b: int8x16_t, c: int8x16_t, d: int8x16_t, ptr: *mut i8); } -vrecpeq_f32_(a) +vst4q_s8_(b.0, b.1, b.2, b.3, a.cast()) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] +pub unsafe fn vst4q_s16(a: *mut i16, b: int16x8x4_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4.p0i8.v8i16")] + fn vst4q_s16_(ptr: *mut i8, a: int16x8_t, b: int16x8_t, c: int16x8_t, d: int16x8_t, size: i32); + } +vst4q_s16_(a.cast(), b.0, b.1, b.2, b.3, 2) +} + +/// Store multiple 4-element structures from four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s8_u8(a: uint8x8_t) -> int8x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +pub unsafe fn vst4q_s16(a: *mut i16, b: int16x8x4_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4.v8i16.p0i8")] + fn vst4q_s16_(a: int16x8_t, b: int16x8_t, c: int16x8_t, d: int16x8_t, ptr: *mut i8); + } +vst4q_s16_(b.0, b.1, b.2, b.3, a.cast()) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] +pub unsafe fn vst4q_s32(a: *mut i32, b: int32x4x4_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4.p0i8.v4i32")] + fn vst4q_s32_(ptr: *mut i8, a: int32x4_t, b: int32x4_t, c: int32x4_t, d: int32x4_t, size: i32); + } +vst4q_s32_(a.cast(), b.0, b.1, b.2, b.3, 4) +} + +/// Store multiple 4-element structures from four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +pub unsafe fn vst4q_s32(a: *mut i32, b: int32x4x4_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4.v4i32.p0i8")] + fn vst4q_s32_(a: int32x4_t, b: int32x4_t, c: int32x4_t, d: int32x4_t, ptr: *mut i8); + } +vst4q_s32_(b.0, b.1, b.2, b.3, a.cast()) +} + +/// Store multiple 4-element structures from four registers +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s8_p8(a: poly8x8_t) -> int8x8_t { - transmute(a) +pub unsafe fn vst4_s64(a: *mut i64, b: int64x1x4_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4.p0i8.v1i64")] + fn vst4_s64_(ptr: *mut i8, a: int64x1_t, b: int64x1_t, c: int64x1_t, d: int64x1_t, size: i32); + } +vst4_s64_(a.cast(), b.0, b.1, b.2, b.3, 8) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s16_p16(a: poly16x4_t) -> int16x4_t { - transmute(a) +pub unsafe fn vst4_s64(a: *mut i64, b: int64x1x4_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4.v1i64.p0i8")] + fn vst4_s64_(a: int64x1_t, b: int64x1_t, c: int64x1_t, d: int64x1_t, ptr: *mut i8); + } +vst4_s64_(b.0, b.1, b.2, b.3, a.cast()) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s16_u16(a: uint16x4_t) -> int16x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +pub unsafe fn vst4_u8(a: *mut u8, b: uint8x8x4_t) { + transmute(vst4_s8(transmute(a), transmute(b))) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s32_u32(a: uint32x2_t) -> int32x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +pub unsafe fn vst4_u16(a: *mut u16, b: uint16x4x4_t) { + transmute(vst4_s16(transmute(a), transmute(b))) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s64_u64(a: uint64x1_t) -> int64x1_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +pub unsafe fn vst4_u32(a: *mut u32, b: uint32x2x4_t) { + transmute(vst4_s32(transmute(a), transmute(b))) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s8_u8(a: uint8x16_t) -> int8x16_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +pub unsafe fn vst4q_u8(a: *mut u8, b: uint8x16x4_t) { + transmute(vst4q_s8(transmute(a), transmute(b))) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s8_p8(a: poly8x16_t) -> int8x16_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +pub unsafe fn vst4q_u16(a: *mut u16, b: uint16x8x4_t) { + transmute(vst4q_s16(transmute(a), transmute(b))) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s16_p16(a: poly16x8_t) -> int16x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +pub unsafe fn vst4q_u32(a: *mut u32, b: uint32x4x4_t) { + transmute(vst4q_s32(transmute(a), transmute(b))) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s16_u16(a: uint16x8_t) -> int16x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +pub unsafe fn vst4_p8(a: *mut p8, b: poly8x8x4_t) { + transmute(vst4_s8(transmute(a), transmute(b))) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s32_u32(a: uint32x4_t) -> int32x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +pub unsafe fn vst4_p16(a: *mut p16, b: poly16x4x4_t) { + transmute(vst4_s16(transmute(a), transmute(b))) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s64_u64(a: uint64x2_t) -> int64x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +pub unsafe fn vst4q_p8(a: *mut p8, b: poly8x16x4_t) { + transmute(vst4q_s8(transmute(a), transmute(b))) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u8_p8(a: poly8x8_t) -> uint8x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +pub unsafe fn vst4q_p16(a: *mut p16, b: poly16x8x4_t) { + transmute(vst4q_s16(transmute(a), transmute(b))) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u8_s8(a: int8x8_t) -> uint8x8_t { - transmute(a) +pub unsafe fn vst4_u64(a: *mut u64, b: uint64x1x4_t) { + transmute(vst4_s64(transmute(a), transmute(b))) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u16_p16(a: poly16x4_t) -> uint16x4_t { - transmute(a) +pub unsafe fn vst4_p64(a: *mut p64, b: poly64x1x4_t) { + transmute(vst4_s64(transmute(a), transmute(b))) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u16_s16(a: int16x4_t) -> uint16x4_t { - transmute(a) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] +pub unsafe fn vst4_f32(a: *mut f32, b: float32x2x4_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4.p0i8.v2f32")] + fn vst4_f32_(ptr: *mut i8, a: float32x2_t, b: float32x2_t, c: float32x2_t, d: float32x2_t, size: i32); + } +vst4_f32_(a.cast(), b.0, b.1, b.2, b.3, 4) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u32_s32(a: int32x2_t) -> uint32x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +pub unsafe fn vst4_f32(a: *mut f32, b: float32x2x4_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4.v2f32.p0i8")] + fn vst4_f32_(a: float32x2_t, b: float32x2_t, c: float32x2_t, d: float32x2_t, ptr: *mut i8); + } +vst4_f32_(b.0, b.1, b.2, b.3, a.cast()) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u64_s64(a: int64x1_t) -> uint64x1_t { - transmute(a) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] +pub unsafe fn vst4q_f32(a: *mut f32, b: float32x4x4_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4.p0i8.v4f32")] + fn vst4q_f32_(ptr: *mut i8, a: float32x4_t, b: float32x4_t, c: float32x4_t, d: float32x4_t, size: i32); + } +vst4q_f32_(a.cast(), b.0, b.1, b.2, b.3, 4) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u8_p8(a: poly8x16_t) -> uint8x16_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +pub unsafe fn vst4q_f32(a: *mut f32, b: float32x4x4_t) { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4.v4f32.p0i8")] + fn vst4q_f32_(a: float32x4_t, b: float32x4_t, c: float32x4_t, d: float32x4_t, ptr: *mut i8); + } +vst4q_f32_(b.0, b.1, b.2, b.3, a.cast()) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u8_s8(a: int8x16_t) -> uint8x16_t { - transmute(a) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4_lane_s8(a: *mut i8, b: int8x8x4_t) { + static_assert_imm3!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4lane.p0i8.v8i8")] + fn vst4_lane_s8_(ptr: *mut i8, a: int8x8_t, b: int8x8_t, c: int8x8_t, d: int8x8_t, n: i32, size: i32); + } +vst4_lane_s8_(a.cast(), b.0, b.1, b.2, b.3, LANE, 1) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u16_p16(a: poly16x8_t) -> uint16x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4_lane_s8(a: *mut i8, b: int8x8x4_t) { + static_assert_imm3!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4lane.v8i8.p0i8")] + fn vst4_lane_s8_(a: int8x8_t, b: int8x8_t, c: int8x8_t, d: int8x8_t, n: i64, ptr: *mut i8); + } +vst4_lane_s8_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u16_s16(a: int16x8_t) -> uint16x8_t { - transmute(a) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4_lane_s16(a: *mut i16, b: int16x4x4_t) { + static_assert_imm2!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4lane.p0i8.v4i16")] + fn vst4_lane_s16_(ptr: *mut i8, a: int16x4_t, b: int16x4_t, c: int16x4_t, d: int16x4_t, n: i32, size: i32); + } +vst4_lane_s16_(a.cast(), b.0, b.1, b.2, b.3, LANE, 2) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u32_s32(a: int32x4_t) -> uint32x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4_lane_s16(a: *mut i16, b: int16x4x4_t) { + static_assert_imm2!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4lane.v4i16.p0i8")] + fn vst4_lane_s16_(a: int16x4_t, b: int16x4_t, c: int16x4_t, d: int16x4_t, n: i64, ptr: *mut i8); + } +vst4_lane_s16_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u64_s64(a: int64x2_t) -> uint64x2_t { - transmute(a) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4_lane_s32(a: *mut i32, b: int32x2x4_t) { + static_assert_imm1!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4lane.p0i8.v2i32")] + fn vst4_lane_s32_(ptr: *mut i8, a: int32x2_t, b: int32x2_t, c: int32x2_t, d: int32x2_t, n: i32, size: i32); + } +vst4_lane_s32_(a.cast(), b.0, b.1, b.2, b.3, LANE, 4) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_p8_s8(a: int8x8_t) -> poly8x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4_lane_s32(a: *mut i32, b: int32x2x4_t) { + static_assert_imm1!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4lane.v2i32.p0i8")] + fn vst4_lane_s32_(a: int32x2_t, b: int32x2_t, c: int32x2_t, d: int32x2_t, n: i64, ptr: *mut i8); + } +vst4_lane_s32_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_p8_u8(a: uint8x8_t) -> poly8x8_t { - transmute(a) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4q_lane_s16(a: *mut i16, b: int16x8x4_t) { + static_assert_imm3!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4lane.p0i8.v8i16")] + fn vst4q_lane_s16_(ptr: *mut i8, a: int16x8_t, b: int16x8_t, c: int16x8_t, d: int16x8_t, n: i32, size: i32); + } +vst4q_lane_s16_(a.cast(), b.0, b.1, b.2, b.3, LANE, 2) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_p16_s16(a: int16x4_t) -> poly16x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4q_lane_s16(a: *mut i16, b: int16x8x4_t) { + static_assert_imm3!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4lane.v8i16.p0i8")] + fn vst4q_lane_s16_(a: int16x8_t, b: int16x8_t, c: int16x8_t, d: int16x8_t, n: i64, ptr: *mut i8); + } +vst4q_lane_s16_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4q_lane_s32(a: *mut i32, b: int32x4x4_t) { + static_assert_imm2!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4lane.p0i8.v4i32")] + fn vst4q_lane_s32_(ptr: *mut i8, a: int32x4_t, b: int32x4_t, c: int32x4_t, d: int32x4_t, n: i32, size: i32); + } +vst4q_lane_s32_(a.cast(), b.0, b.1, b.2, b.3, LANE, 4) +} + +/// Store multiple 4-element structures from four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_p16_u16(a: uint16x4_t) -> poly16x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4q_lane_s32(a: *mut i32, b: int32x4x4_t) { + static_assert_imm2!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4lane.v4i32.p0i8")] + fn vst4q_lane_s32_(a: int32x4_t, b: int32x4_t, c: int32x4_t, d: int32x4_t, n: i64, ptr: *mut i8); + } +vst4q_lane_s32_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_p8_s8(a: int8x16_t) -> poly8x16_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4_lane_u8(a: *mut u8, b: uint8x8x4_t) { + static_assert_imm3!(LANE); + transmute(vst4_lane_s8::(transmute(a), transmute(b))) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_p8_u8(a: uint8x16_t) -> poly8x16_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4_lane_u16(a: *mut u16, b: uint16x4x4_t) { + static_assert_imm2!(LANE); + transmute(vst4_lane_s16::(transmute(a), transmute(b))) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_p16_s16(a: int16x8_t) -> poly16x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4_lane_u32(a: *mut u32, b: uint32x2x4_t) { + static_assert_imm1!(LANE); + transmute(vst4_lane_s32::(transmute(a), transmute(b))) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_p16_u16(a: uint16x8_t) -> poly16x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4q_lane_u16(a: *mut u16, b: uint16x8x4_t) { + static_assert_imm3!(LANE); + transmute(vst4q_lane_s16::(transmute(a), transmute(b))) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s8_s16(a: int16x4_t) -> int8x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4q_lane_u32(a: *mut u32, b: uint32x4x4_t) { + static_assert_imm2!(LANE); + transmute(vst4q_lane_s32::(transmute(a), transmute(b))) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s8_u16(a: uint16x4_t) -> int8x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4_lane_p8(a: *mut p8, b: poly8x8x4_t) { + static_assert_imm3!(LANE); + transmute(vst4_lane_s8::(transmute(a), transmute(b))) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s8_p16(a: poly16x4_t) -> int8x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4_lane_p16(a: *mut p16, b: poly16x4x4_t) { + static_assert_imm2!(LANE); + transmute(vst4_lane_s16::(transmute(a), transmute(b))) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s16_s32(a: int32x2_t) -> int16x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4q_lane_p16(a: *mut p16, b: poly16x8x4_t) { + static_assert_imm3!(LANE); + transmute(vst4q_lane_s16::(transmute(a), transmute(b))) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s16_u32(a: uint32x2_t) -> int16x4_t { - transmute(a) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4_lane_f32(a: *mut f32, b: float32x2x4_t) { + static_assert_imm1!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4lane.p0i8.v2f32")] + fn vst4_lane_f32_(ptr: *mut i8, a: float32x2_t, b: float32x2_t, c: float32x2_t, d: float32x2_t, n: i32, size: i32); + } +vst4_lane_f32_(a.cast(), b.0, b.1, b.2, b.3, LANE, 4) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s32_s64(a: int64x1_t) -> int32x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4_lane_f32(a: *mut f32, b: float32x2x4_t) { + static_assert_imm1!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4lane.v2f32.p0i8")] + fn vst4_lane_f32_(a: float32x2_t, b: float32x2_t, c: float32x2_t, d: float32x2_t, n: i64, ptr: *mut i8); + } +vst4_lane_f32_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) } -/// Vector reinterpret cast operation +/// Store multiple 4-element structures from four registers +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4q_lane_f32(a: *mut f32, b: float32x4x4_t) { + static_assert_imm2!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4lane.p0i8.v4f32")] + fn vst4q_lane_f32_(ptr: *mut i8, a: float32x4_t, b: float32x4_t, c: float32x4_t, d: float32x4_t, n: i32, size: i32); + } +vst4q_lane_f32_(a.cast(), b.0, b.1, b.2, b.3, LANE, 4) +} + +/// Store multiple 4-element structures from four registers #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s32_u64(a: uint64x1_t) -> int32x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vst4q_lane_f32(a: *mut f32, b: float32x4x4_t) { + static_assert_imm2!(LANE); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4lane.v4f32.p0i8")] + fn vst4q_lane_f32_(a: float32x4_t, b: float32x4_t, c: float32x4_t, d: float32x4_t, n: i64, ptr: *mut i8); + } +vst4q_lane_f32_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) } -/// Vector reinterpret cast operation +/// Multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s8_s16(a: int16x8_t) -> int8x16_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i8"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +pub unsafe fn vmul_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { + simd_mul(a, b) } -/// Vector reinterpret cast operation +/// Multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s8_u16(a: uint16x8_t) -> int8x16_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i8"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +pub unsafe fn vmulq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { + simd_mul(a, b) } -/// Vector reinterpret cast operation +/// Multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s8_p16(a: poly16x8_t) -> int8x16_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i16"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +pub unsafe fn vmul_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { + simd_mul(a, b) } -/// Vector reinterpret cast operation +/// Multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s16_s32(a: int32x4_t) -> int16x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i16"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +pub unsafe fn vmulq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { + simd_mul(a, b) } -/// Vector reinterpret cast operation +/// Multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s16_u32(a: uint32x4_t) -> int16x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i32"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +pub unsafe fn vmul_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { + simd_mul(a, b) } -/// Vector reinterpret cast operation +/// Multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s32_s64(a: int64x2_t) -> int32x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i32"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +pub unsafe fn vmulq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { + simd_mul(a, b) } -/// Vector reinterpret cast operation +/// Multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s32_u64(a: uint64x2_t) -> int32x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i8"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +pub unsafe fn vmul_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { + simd_mul(a, b) } -/// Vector reinterpret cast operation +/// Multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u8_p16(a: poly16x4_t) -> uint8x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i8"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +pub unsafe fn vmulq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { + simd_mul(a, b) } -/// Vector reinterpret cast operation +/// Multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u8_s16(a: int16x4_t) -> uint8x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i16"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +pub unsafe fn vmul_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { + simd_mul(a, b) } -/// Vector reinterpret cast operation +/// Multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u8_u16(a: uint16x4_t) -> uint8x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i16"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +pub unsafe fn vmulq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { + simd_mul(a, b) } -/// Vector reinterpret cast operation +/// Multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u16_s32(a: int32x2_t) -> uint16x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i32"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +pub unsafe fn vmul_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { + simd_mul(a, b) } -/// Vector reinterpret cast operation +/// Multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u16_u32(a: uint32x2_t) -> uint16x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i32"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +pub unsafe fn vmulq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { + simd_mul(a, b) } -/// Vector reinterpret cast operation +/// Polynomial multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u32_s64(a: int64x1_t) -> uint32x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(pmul))] +pub unsafe fn vmul_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmulp.v8i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.pmul.v8i8")] + fn vmul_p8_(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t; + } +vmul_p8_(a, b) } -/// Vector reinterpret cast operation +/// Polynomial multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u32_u64(a: uint64x1_t) -> uint32x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(pmul))] +pub unsafe fn vmulq_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmulp.v16i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.pmul.v16i8")] + fn vmulq_p8_(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t; + } +vmulq_p8_(a, b) } -/// Vector reinterpret cast operation +/// Multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u8_p16(a: poly16x8_t) -> uint8x16_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.f32"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))] +pub unsafe fn vmul_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { + simd_mul(a, b) } -/// Vector reinterpret cast operation +/// Multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u8_s16(a: int16x8_t) -> uint8x16_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.f32"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))] +pub unsafe fn vmulq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { + simd_mul(a, b) } -/// Vector reinterpret cast operation +/// Vector multiply by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u8_u16(a: uint16x8_t) -> uint8x16_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +pub unsafe fn vmul_n_s16(a: int16x4_t, b: i16) -> int16x4_t { + simd_mul(a, vdup_n_s16(b)) } -/// Vector reinterpret cast operation +/// Vector multiply by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u16_s32(a: int32x4_t) -> uint16x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +pub unsafe fn vmulq_n_s16(a: int16x8_t, b: i16) -> int16x8_t { + simd_mul(a, vdupq_n_s16(b)) } -/// Vector reinterpret cast operation +/// Vector multiply by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u16_u32(a: uint32x4_t) -> uint16x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +pub unsafe fn vmul_n_s32(a: int32x2_t, b: i32) -> int32x2_t { + simd_mul(a, vdup_n_s32(b)) } -/// Vector reinterpret cast operation +/// Vector multiply by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u32_s64(a: int64x2_t) -> uint32x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +pub unsafe fn vmulq_n_s32(a: int32x4_t, b: i32) -> int32x4_t { + simd_mul(a, vdupq_n_s32(b)) } -/// Vector reinterpret cast operation +/// Vector multiply by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u32_u64(a: uint64x2_t) -> uint32x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +pub unsafe fn vmul_n_u16(a: uint16x4_t, b: u16) -> uint16x4_t { + simd_mul(a, vdup_n_u16(b)) } -/// Vector reinterpret cast operation +/// Vector multiply by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_p8_p16(a: poly16x4_t) -> poly8x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +pub unsafe fn vmulq_n_u16(a: uint16x8_t, b: u16) -> uint16x8_t { + simd_mul(a, vdupq_n_u16(b)) } -/// Vector reinterpret cast operation +/// Vector multiply by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_p8_s16(a: int16x4_t) -> poly8x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +pub unsafe fn vmul_n_u32(a: uint32x2_t, b: u32) -> uint32x2_t { + simd_mul(a, vdup_n_u32(b)) } -/// Vector reinterpret cast operation +/// Vector multiply by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_p8_u16(a: uint16x4_t) -> poly8x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +pub unsafe fn vmulq_n_u32(a: uint32x4_t, b: u32) -> uint32x4_t { + simd_mul(a, vdupq_n_u32(b)) } -/// Vector reinterpret cast operation +/// Vector multiply by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_p16_s32(a: int32x2_t) -> poly16x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))] +pub unsafe fn vmul_n_f32(a: float32x2_t, b: f32) -> float32x2_t { + simd_mul(a, vdup_n_f32(b)) } -/// Vector reinterpret cast operation +/// Vector multiply by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_p16_u32(a: uint32x2_t) -> poly16x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))] +pub unsafe fn vmulq_n_f32(a: float32x4_t, b: f32) -> float32x4_t { + simd_mul(a, vdupq_n_f32(b)) } -/// Vector reinterpret cast operation +/// Multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_p8_p16(a: poly16x8_t) -> poly8x16_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmul_lane_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { + static_assert_imm2!(LANE); + simd_mul(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) } -/// Vector reinterpret cast operation +/// Multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_p8_s16(a: int16x8_t) -> poly8x16_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmul_laneq_s16(a: int16x4_t, b: int16x8_t) -> int16x4_t { + static_assert_imm3!(LANE); + simd_mul(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) } -/// Vector reinterpret cast operation +/// Multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_p8_u16(a: uint16x8_t) -> poly8x16_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmulq_lane_s16(a: int16x8_t, b: int16x4_t) -> int16x8_t { + static_assert_imm2!(LANE); + simd_mul(a, simd_shuffle8!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) } -/// Vector reinterpret cast operation +/// Multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_p16_s32(a: int32x4_t) -> poly16x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmulq_laneq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { + static_assert_imm3!(LANE); + simd_mul(a, simd_shuffle8!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) } -/// Vector reinterpret cast operation +/// Multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_p16_u32(a: uint32x4_t) -> poly16x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmul_lane_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { + static_assert_imm1!(LANE); + simd_mul(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) } -/// Vector reinterpret cast operation +/// Multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s16_p8(a: poly8x8_t) -> int16x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmul_laneq_s32(a: int32x2_t, b: int32x4_t) -> int32x2_t { + static_assert_imm2!(LANE); + simd_mul(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) } -/// Vector reinterpret cast operation +/// Multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s16_s8(a: int8x8_t) -> int16x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmulq_lane_s32(a: int32x4_t, b: int32x2_t) -> int32x4_t { + static_assert_imm1!(LANE); + simd_mul(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) } -/// Vector reinterpret cast operation +/// Multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s16_u8(a: uint8x8_t) -> int16x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmulq_laneq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { + static_assert_imm2!(LANE); + simd_mul(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) } -/// Vector reinterpret cast operation +/// Multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s32_p16(a: poly16x4_t) -> int32x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmul_lane_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { + static_assert_imm2!(LANE); + simd_mul(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) } -/// Vector reinterpret cast operation +/// Multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s32_s16(a: int16x4_t) -> int32x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmul_laneq_u16(a: uint16x4_t, b: uint16x8_t) -> uint16x4_t { + static_assert_imm3!(LANE); + simd_mul(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) } -/// Vector reinterpret cast operation +/// Multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s32_u16(a: uint16x4_t) -> int32x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmulq_lane_u16(a: uint16x8_t, b: uint16x4_t) -> uint16x8_t { + static_assert_imm2!(LANE); + simd_mul(a, simd_shuffle8!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) } -/// Vector reinterpret cast operation +/// Multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s64_s32(a: int32x2_t) -> int64x1_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmulq_laneq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { + static_assert_imm3!(LANE); + simd_mul(a, simd_shuffle8!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) } -/// Vector reinterpret cast operation +/// Multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s64_u32(a: uint32x2_t) -> int64x1_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmul_lane_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { + static_assert_imm1!(LANE); + simd_mul(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) } -/// Vector reinterpret cast operation +/// Multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s16_p8(a: poly8x16_t) -> int16x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmul_laneq_u32(a: uint32x2_t, b: uint32x4_t) -> uint32x2_t { + static_assert_imm2!(LANE); + simd_mul(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) } -/// Vector reinterpret cast operation +/// Multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s16_s8(a: int8x16_t) -> int16x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmulq_lane_u32(a: uint32x4_t, b: uint32x2_t) -> uint32x4_t { + static_assert_imm1!(LANE); + simd_mul(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) } -/// Vector reinterpret cast operation +/// Multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s16_u8(a: uint8x16_t) -> int16x8_t { - transmute(a) -} - -/// Vector reinterpret cast operation -#[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s32_p16(a: poly16x8_t) -> int32x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmulq_laneq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { + static_assert_imm2!(LANE); + simd_mul(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) } -/// Vector reinterpret cast operation +/// Floating-point multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s32_s16(a: int16x8_t) -> int32x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmul_lane_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { + static_assert_imm1!(LANE); + simd_mul(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) } -/// Vector reinterpret cast operation +/// Floating-point multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s32_u16(a: uint16x8_t) -> int32x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmul_laneq_f32(a: float32x2_t, b: float32x4_t) -> float32x2_t { + static_assert_imm2!(LANE); + simd_mul(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) } -/// Vector reinterpret cast operation +/// Floating-point multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s64_s32(a: int32x4_t) -> int64x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmulq_lane_f32(a: float32x4_t, b: float32x2_t) -> float32x4_t { + static_assert_imm1!(LANE); + simd_mul(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) } -/// Vector reinterpret cast operation +/// Floating-point multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s64_u32(a: uint32x4_t) -> int64x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmulq_laneq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { + static_assert_imm2!(LANE); + simd_mul(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) } -/// Vector reinterpret cast operation +/// Signed multiply long #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u16_p8(a: poly8x8_t) -> uint16x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmull.s8"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull))] +pub unsafe fn vmull_s8(a: int8x8_t, b: int8x8_t) -> int16x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmulls.v8i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.smull.v8i8")] + fn vmull_s8_(a: int8x8_t, b: int8x8_t) -> int16x8_t; + } +vmull_s8_(a, b) } -/// Vector reinterpret cast operation +/// Signed multiply long #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u16_s8(a: int8x8_t) -> uint16x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmull.s16"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull))] +pub unsafe fn vmull_s16(a: int16x4_t, b: int16x4_t) -> int32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmulls.v4i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.smull.v4i16")] + fn vmull_s16_(a: int16x4_t, b: int16x4_t) -> int32x4_t; + } +vmull_s16_(a, b) } -/// Vector reinterpret cast operation +/// Signed multiply long #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u16_u8(a: uint8x8_t) -> uint16x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmull.s32"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull))] +pub unsafe fn vmull_s32(a: int32x2_t, b: int32x2_t) -> int64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmulls.v2i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.smull.v2i32")] + fn vmull_s32_(a: int32x2_t, b: int32x2_t) -> int64x2_t; + } +vmull_s32_(a, b) } -/// Vector reinterpret cast operation +/// Unsigned multiply long #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u32_p16(a: poly16x4_t) -> uint32x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmull.u8"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull))] +pub unsafe fn vmull_u8(a: uint8x8_t, b: uint8x8_t) -> uint16x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmullu.v8i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.umull.v8i8")] + fn vmull_u8_(a: uint8x8_t, b: uint8x8_t) -> uint16x8_t; + } +vmull_u8_(a, b) } -/// Vector reinterpret cast operation +/// Unsigned multiply long #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u32_s16(a: int16x4_t) -> uint32x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmull.u16"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull))] +pub unsafe fn vmull_u16(a: uint16x4_t, b: uint16x4_t) -> uint32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmullu.v4i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.umull.v4i16")] + fn vmull_u16_(a: uint16x4_t, b: uint16x4_t) -> uint32x4_t; + } +vmull_u16_(a, b) } -/// Vector reinterpret cast operation +/// Unsigned multiply long #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u32_u16(a: uint16x4_t) -> uint32x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmull.u32"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull))] +pub unsafe fn vmull_u32(a: uint32x2_t, b: uint32x2_t) -> uint64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmullu.v2i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.umull.v2i32")] + fn vmull_u32_(a: uint32x2_t, b: uint32x2_t) -> uint64x2_t; + } +vmull_u32_(a, b) } -/// Vector reinterpret cast operation +/// Polynomial multiply long #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u64_s32(a: int32x2_t) -> uint64x1_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmull.p8"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(pmull))] +pub unsafe fn vmull_p8(a: poly8x8_t, b: poly8x8_t) -> poly16x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmullp.v8i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.pmull.v8i8")] + fn vmull_p8_(a: poly8x8_t, b: poly8x8_t) -> poly16x8_t; + } +vmull_p8_(a, b) } -/// Vector reinterpret cast operation +/// Vector long multiply with scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u64_u32(a: uint32x2_t) -> uint64x1_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull))] +pub unsafe fn vmull_n_s16(a: int16x4_t, b: i16) -> int32x4_t { + vmull_s16(a, vdup_n_s16(b)) } -/// Vector reinterpret cast operation +/// Vector long multiply with scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u16_p8(a: poly8x16_t) -> uint16x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull))] +pub unsafe fn vmull_n_s32(a: int32x2_t, b: i32) -> int64x2_t { + vmull_s32(a, vdup_n_s32(b)) } -/// Vector reinterpret cast operation +/// Vector long multiply with scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u16_s8(a: int8x16_t) -> uint16x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull))] +pub unsafe fn vmull_n_u16(a: uint16x4_t, b: u16) -> uint32x4_t { + vmull_u16(a, vdup_n_u16(b)) } -/// Vector reinterpret cast operation +/// Vector long multiply with scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u16_u8(a: uint8x16_t) -> uint16x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull))] +pub unsafe fn vmull_n_u32(a: uint32x2_t, b: u32) -> uint64x2_t { + vmull_u32(a, vdup_n_u32(b)) } -/// Vector reinterpret cast operation +/// Vector long multiply by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u32_p16(a: poly16x8_t) -> uint32x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmull_lane_s16(a: int16x4_t, b: int16x4_t) -> int32x4_t { + static_assert_imm2!(LANE); + vmull_s16(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) } -/// Vector reinterpret cast operation +/// Vector long multiply by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u32_s16(a: int16x8_t) -> uint32x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmull_laneq_s16(a: int16x4_t, b: int16x8_t) -> int32x4_t { + static_assert_imm3!(LANE); + vmull_s16(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) } -/// Vector reinterpret cast operation +/// Vector long multiply by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u32_u16(a: uint16x8_t) -> uint32x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmull_lane_s32(a: int32x2_t, b: int32x2_t) -> int64x2_t { + static_assert_imm1!(LANE); + vmull_s32(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) } -/// Vector reinterpret cast operation +/// Vector long multiply by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u64_s32(a: int32x4_t) -> uint64x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmull_laneq_s32(a: int32x2_t, b: int32x4_t) -> int64x2_t { + static_assert_imm2!(LANE); + vmull_s32(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) } -/// Vector reinterpret cast operation +/// Vector long multiply by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u64_u32(a: uint32x4_t) -> uint64x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmull_lane_u16(a: uint16x4_t, b: uint16x4_t) -> uint32x4_t { + static_assert_imm2!(LANE); + vmull_u16(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) } -/// Vector reinterpret cast operation +/// Vector long multiply by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_p16_p8(a: poly8x8_t) -> poly16x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmull_laneq_u16(a: uint16x4_t, b: uint16x8_t) -> uint32x4_t { + static_assert_imm3!(LANE); + vmull_u16(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) } -/// Vector reinterpret cast operation +/// Vector long multiply by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_p16_s8(a: int8x8_t) -> poly16x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmull_lane_u32(a: uint32x2_t, b: uint32x2_t) -> uint64x2_t { + static_assert_imm1!(LANE); + vmull_u32(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) } -/// Vector reinterpret cast operation +/// Vector long multiply by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_p16_u8(a: uint8x8_t) -> poly16x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vmull_laneq_u32(a: uint32x2_t, b: uint32x4_t) -> uint64x2_t { + static_assert_imm2!(LANE); + vmull_u32(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) } -/// Vector reinterpret cast operation +/// Floating-point fused Multiply-Add to accumulator(vector) #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_p16_p8(a: poly8x16_t) -> poly16x8_t { - transmute(a) +#[cfg_attr(target_arch = "arm", target_feature(enable = "vfp4"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vfma))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmla))] +pub unsafe fn vfma_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.fma.v2f32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.fma.v2f32")] + fn vfma_f32_(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t; + } +vfma_f32_(b, c, a) } -/// Vector reinterpret cast operation +/// Floating-point fused Multiply-Add to accumulator(vector) #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_p16_s8(a: int8x16_t) -> poly16x8_t { - transmute(a) +#[cfg_attr(target_arch = "arm", target_feature(enable = "vfp4"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vfma))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmla))] +pub unsafe fn vfmaq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.fma.v4f32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.fma.v4f32")] + fn vfmaq_f32_(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t; + } +vfmaq_f32_(b, c, a) } -/// Vector reinterpret cast operation +/// Floating-point fused Multiply-Add to accumulator(vector) #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_p16_u8(a: uint8x16_t) -> poly16x8_t { - transmute(a) +#[cfg_attr(target_arch = "arm", target_feature(enable = "vfp4"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vfma))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmla))] +pub unsafe fn vfma_n_f32(a: float32x2_t, b: float32x2_t, c: f32) -> float32x2_t { + vfma_f32(a, b, vdup_n_f32_vfp4(c)) } -/// Vector reinterpret cast operation +/// Floating-point fused Multiply-Add to accumulator(vector) #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s8_s32(a: int32x2_t) -> int8x8_t { - transmute(a) +#[cfg_attr(target_arch = "arm", target_feature(enable = "vfp4"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vfma))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmla))] +pub unsafe fn vfmaq_n_f32(a: float32x4_t, b: float32x4_t, c: f32) -> float32x4_t { + vfmaq_f32(a, b, vdupq_n_f32_vfp4(c)) } -/// Vector reinterpret cast operation +/// Floating-point fused multiply-subtract from accumulator #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s8_u32(a: uint32x2_t) -> int8x8_t { - transmute(a) +#[cfg_attr(target_arch = "arm", target_feature(enable = "vfp4"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vfms))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmls))] +pub unsafe fn vfms_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t { + let b: float32x2_t = simd_neg(b); + vfma_f32(a, b, c) } -/// Vector reinterpret cast operation +/// Floating-point fused multiply-subtract from accumulator #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s16_s64(a: int64x1_t) -> int16x4_t { - transmute(a) +#[cfg_attr(target_arch = "arm", target_feature(enable = "vfp4"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vfms))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmls))] +pub unsafe fn vfmsq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t { + let b: float32x4_t = simd_neg(b); + vfmaq_f32(a, b, c) } -/// Vector reinterpret cast operation +/// Floating-point fused Multiply-subtract to accumulator(vector) #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s16_u64(a: uint64x1_t) -> int16x4_t { - transmute(a) +#[cfg_attr(target_arch = "arm", target_feature(enable = "vfp4"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vfms))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmls))] +pub unsafe fn vfms_n_f32(a: float32x2_t, b: float32x2_t, c: f32) -> float32x2_t { + vfms_f32(a, b, vdup_n_f32_vfp4(c)) } -/// Vector reinterpret cast operation +/// Floating-point fused Multiply-subtract to accumulator(vector) #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s8_s32(a: int32x4_t) -> int8x16_t { - transmute(a) +#[cfg_attr(target_arch = "arm", target_feature(enable = "vfp4"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vfms))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmls))] +pub unsafe fn vfmsq_n_f32(a: float32x4_t, b: float32x4_t, c: f32) -> float32x4_t { + vfmsq_f32(a, b, vdupq_n_f32_vfp4(c)) } -/// Vector reinterpret cast operation +/// Subtract #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s8_u32(a: uint32x4_t) -> int8x16_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i8"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +pub unsafe fn vsub_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { + simd_sub(a, b) } -/// Vector reinterpret cast operation +/// Subtract #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s16_s64(a: int64x2_t) -> int16x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i8"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +pub unsafe fn vsubq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { + simd_sub(a, b) } -/// Vector reinterpret cast operation +/// Subtract #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s16_u64(a: uint64x2_t) -> int16x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i16"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +pub unsafe fn vsub_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { + simd_sub(a, b) } -/// Vector reinterpret cast operation +/// Subtract #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u8_s32(a: int32x2_t) -> uint8x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i16"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +pub unsafe fn vsubq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { + simd_sub(a, b) } -/// Vector reinterpret cast operation +/// Subtract #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u8_u32(a: uint32x2_t) -> uint8x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i32"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +pub unsafe fn vsub_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { + simd_sub(a, b) } -/// Vector reinterpret cast operation +/// Subtract #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u16_s64(a: int64x1_t) -> uint16x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i32"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +pub unsafe fn vsubq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { + simd_sub(a, b) } -/// Vector reinterpret cast operation +/// Subtract #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u16_u64(a: uint64x1_t) -> uint16x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i8"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +pub unsafe fn vsub_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { + simd_sub(a, b) } -/// Vector reinterpret cast operation +/// Subtract #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u8_s32(a: int32x4_t) -> uint8x16_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i8"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +pub unsafe fn vsubq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { + simd_sub(a, b) } -/// Vector reinterpret cast operation +/// Subtract #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u8_u32(a: uint32x4_t) -> uint8x16_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i16"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +pub unsafe fn vsub_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { + simd_sub(a, b) } -/// Vector reinterpret cast operation +/// Subtract #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u16_s64(a: int64x2_t) -> uint16x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i16"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +pub unsafe fn vsubq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { + simd_sub(a, b) } -/// Vector reinterpret cast operation +/// Subtract #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u16_u64(a: uint64x2_t) -> uint16x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i32"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +pub unsafe fn vsub_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { + simd_sub(a, b) } -/// Vector reinterpret cast operation +/// Subtract #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_p8_s32(a: int32x2_t) -> poly8x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i32"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +pub unsafe fn vsubq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { + simd_sub(a, b) } -/// Vector reinterpret cast operation +/// Subtract #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_p8_u32(a: uint32x2_t) -> poly8x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i64"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +pub unsafe fn vsub_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { + simd_sub(a, b) } -/// Vector reinterpret cast operation +/// Subtract #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_p16_s64(a: int64x1_t) -> poly16x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i64"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +pub unsafe fn vsubq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { + simd_sub(a, b) } -/// Vector reinterpret cast operation +/// Subtract #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_p16_u64(a: uint64x1_t) -> poly16x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i64"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +pub unsafe fn vsub_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { + simd_sub(a, b) } -/// Vector reinterpret cast operation +/// Subtract #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_p8_s32(a: int32x4_t) -> poly8x16_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i64"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +pub unsafe fn vsubq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { + simd_sub(a, b) } -/// Vector reinterpret cast operation +/// Subtract #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_p8_u32(a: uint32x4_t) -> poly8x16_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.f32"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fsub))] +pub unsafe fn vsub_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { + simd_sub(a, b) } -/// Vector reinterpret cast operation +/// Subtract #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_p16_s64(a: int64x2_t) -> poly16x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.f32"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fsub))] +pub unsafe fn vsubq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { + simd_sub(a, b) } -/// Vector reinterpret cast operation +/// Bitwise exclusive OR #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_p16_u64(a: uint64x2_t) -> poly16x8_t { - transmute(a) +pub unsafe fn vadd_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { + simd_xor(a, b) } -/// Vector reinterpret cast operation +/// Bitwise exclusive OR #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s32_p8(a: poly8x8_t) -> int32x2_t { - transmute(a) +pub unsafe fn vadd_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t { + simd_xor(a, b) } -/// Vector reinterpret cast operation +/// Bitwise exclusive OR #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s32_s8(a: int8x8_t) -> int32x2_t { - transmute(a) +pub unsafe fn vaddq_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { + simd_xor(a, b) } -/// Vector reinterpret cast operation +/// Bitwise exclusive OR #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s32_u8(a: uint8x8_t) -> int32x2_t { - transmute(a) +pub unsafe fn vaddq_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { + simd_xor(a, b) } -/// Vector reinterpret cast operation +/// Bitwise exclusive OR #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s64_p16(a: poly16x4_t) -> int64x1_t { - transmute(a) +pub unsafe fn vadd_p64(a: poly64x1_t, b: poly64x1_t) -> poly64x1_t { + simd_xor(a, b) } -/// Vector reinterpret cast operation +/// Bitwise exclusive OR #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s64_s16(a: int16x4_t) -> int64x1_t { - transmute(a) +pub unsafe fn vaddq_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { + simd_xor(a, b) } -/// Vector reinterpret cast operation +/// Bitwise exclusive OR #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s64_u16(a: uint16x4_t) -> int64x1_t { - transmute(a) +pub unsafe fn vaddq_p128(a: p128, b: p128) -> p128 { + a ^ b } -/// Vector reinterpret cast operation +/// Subtract returning high narrow #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s32_p8(a: poly8x16_t) -> int32x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn))] +pub unsafe fn vsubhn_s16(a: int16x8_t, b: int16x8_t) -> int8x8_t { + let c: i16x8 = i16x8::new(8, 8, 8, 8, 8, 8, 8, 8); + simd_cast(simd_shr(simd_sub(a, b), transmute(c))) } -/// Vector reinterpret cast operation +/// Subtract returning high narrow #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s32_s8(a: int8x16_t) -> int32x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn))] +pub unsafe fn vsubhn_s32(a: int32x4_t, b: int32x4_t) -> int16x4_t { + let c: i32x4 = i32x4::new(16, 16, 16, 16); + simd_cast(simd_shr(simd_sub(a, b), transmute(c))) } -/// Vector reinterpret cast operation +/// Subtract returning high narrow #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s32_u8(a: uint8x16_t) -> int32x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn))] +pub unsafe fn vsubhn_s64(a: int64x2_t, b: int64x2_t) -> int32x2_t { + let c: i64x2 = i64x2::new(32, 32); + simd_cast(simd_shr(simd_sub(a, b), transmute(c))) } -/// Vector reinterpret cast operation +/// Subtract returning high narrow #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s64_p16(a: poly16x8_t) -> int64x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn))] +pub unsafe fn vsubhn_u16(a: uint16x8_t, b: uint16x8_t) -> uint8x8_t { + let c: u16x8 = u16x8::new(8, 8, 8, 8, 8, 8, 8, 8); + simd_cast(simd_shr(simd_sub(a, b), transmute(c))) } -/// Vector reinterpret cast operation +/// Subtract returning high narrow #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s64_s16(a: int16x8_t) -> int64x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn))] +pub unsafe fn vsubhn_u32(a: uint32x4_t, b: uint32x4_t) -> uint16x4_t { + let c: u32x4 = u32x4::new(16, 16, 16, 16); + simd_cast(simd_shr(simd_sub(a, b), transmute(c))) } -/// Vector reinterpret cast operation +/// Subtract returning high narrow #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s64_u16(a: uint16x8_t) -> int64x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn))] +pub unsafe fn vsubhn_u64(a: uint64x2_t, b: uint64x2_t) -> uint32x2_t { + let c: u64x2 = u64x2::new(32, 32); + simd_cast(simd_shr(simd_sub(a, b), transmute(c))) } -/// Vector reinterpret cast operation +/// Subtract returning high narrow #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u32_p8(a: poly8x8_t) -> uint32x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn2))] +pub unsafe fn vsubhn_high_s16(a: int8x8_t, b: int16x8_t, c: int16x8_t) -> int8x16_t { + let d: int8x8_t = vsubhn_s16(b, c); + simd_shuffle16!(a, d, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) } -/// Vector reinterpret cast operation +/// Subtract returning high narrow #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u32_s8(a: int8x8_t) -> uint32x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn2))] +pub unsafe fn vsubhn_high_s32(a: int16x4_t, b: int32x4_t, c: int32x4_t) -> int16x8_t { + let d: int16x4_t = vsubhn_s32(b, c); + simd_shuffle8!(a, d, [0, 1, 2, 3, 4, 5, 6, 7]) } -/// Vector reinterpret cast operation +/// Subtract returning high narrow #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u32_u8(a: uint8x8_t) -> uint32x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn2))] +pub unsafe fn vsubhn_high_s64(a: int32x2_t, b: int64x2_t, c: int64x2_t) -> int32x4_t { + let d: int32x2_t = vsubhn_s64(b, c); + simd_shuffle4!(a, d, [0, 1, 2, 3]) } -/// Vector reinterpret cast operation +/// Subtract returning high narrow #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u64_p16(a: poly16x4_t) -> uint64x1_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn2))] +pub unsafe fn vsubhn_high_u16(a: uint8x8_t, b: uint16x8_t, c: uint16x8_t) -> uint8x16_t { + let d: uint8x8_t = vsubhn_u16(b, c); + simd_shuffle16!(a, d, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) } -/// Vector reinterpret cast operation +/// Subtract returning high narrow #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u64_s16(a: int16x4_t) -> uint64x1_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn2))] +pub unsafe fn vsubhn_high_u32(a: uint16x4_t, b: uint32x4_t, c: uint32x4_t) -> uint16x8_t { + let d: uint16x4_t = vsubhn_u32(b, c); + simd_shuffle8!(a, d, [0, 1, 2, 3, 4, 5, 6, 7]) } -/// Vector reinterpret cast operation +/// Subtract returning high narrow #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u64_u16(a: uint16x4_t) -> uint64x1_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn2))] +pub unsafe fn vsubhn_high_u64(a: uint32x2_t, b: uint64x2_t, c: uint64x2_t) -> uint32x4_t { + let d: uint32x2_t = vsubhn_u64(b, c); + simd_shuffle4!(a, d, [0, 1, 2, 3]) } -/// Vector reinterpret cast operation +/// Signed halving subtract #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u32_p8(a: poly8x16_t) -> uint32x4_t { - transmute(a) -} - -/// Vector reinterpret cast operation -#[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u32_s8(a: int8x16_t) -> uint32x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.u8"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhsub))] +pub unsafe fn vhsub_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhsubu.v8i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uhsub.v8i8")] + fn vhsub_u8_(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t; + } +vhsub_u8_(a, b) } -/// Vector reinterpret cast operation +/// Signed halving subtract #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u32_u8(a: uint8x16_t) -> uint32x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.u8"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhsub))] +pub unsafe fn vhsubq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhsubu.v16i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uhsub.v16i8")] + fn vhsubq_u8_(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t; + } +vhsubq_u8_(a, b) } -/// Vector reinterpret cast operation +/// Signed halving subtract #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u64_p16(a: poly16x8_t) -> uint64x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.u16"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhsub))] +pub unsafe fn vhsub_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhsubu.v4i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uhsub.v4i16")] + fn vhsub_u16_(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t; + } +vhsub_u16_(a, b) } -/// Vector reinterpret cast operation +/// Signed halving subtract #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u64_s16(a: int16x8_t) -> uint64x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.u16"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhsub))] +pub unsafe fn vhsubq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhsubu.v8i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uhsub.v8i16")] + fn vhsubq_u16_(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t; + } +vhsubq_u16_(a, b) } -/// Vector reinterpret cast operation +/// Signed halving subtract #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u64_u16(a: uint16x8_t) -> uint64x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.u32"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhsub))] +pub unsafe fn vhsub_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhsubu.v2i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uhsub.v2i32")] + fn vhsub_u32_(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t; + } +vhsub_u32_(a, b) } -/// Vector reinterpret cast operation +/// Signed halving subtract #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s8_s64(a: int64x1_t) -> int8x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.u32"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhsub))] +pub unsafe fn vhsubq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhsubu.v4i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uhsub.v4i32")] + fn vhsubq_u32_(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t; + } +vhsubq_u32_(a, b) } -/// Vector reinterpret cast operation +/// Signed halving subtract #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s8_u64(a: uint64x1_t) -> int8x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.s8"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shsub))] +pub unsafe fn vhsub_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhsubs.v8i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.shsub.v8i8")] + fn vhsub_s8_(a: int8x8_t, b: int8x8_t) -> int8x8_t; + } +vhsub_s8_(a, b) } -/// Vector reinterpret cast operation +/// Signed halving subtract #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u8_s64(a: int64x1_t) -> uint8x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.s8"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shsub))] +pub unsafe fn vhsubq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhsubs.v16i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.shsub.v16i8")] + fn vhsubq_s8_(a: int8x16_t, b: int8x16_t) -> int8x16_t; + } +vhsubq_s8_(a, b) } -/// Vector reinterpret cast operation +/// Signed halving subtract #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u8_u64(a: uint64x1_t) -> uint8x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.s16"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shsub))] +pub unsafe fn vhsub_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhsubs.v4i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.shsub.v4i16")] + fn vhsub_s16_(a: int16x4_t, b: int16x4_t) -> int16x4_t; + } +vhsub_s16_(a, b) } -/// Vector reinterpret cast operation +/// Signed halving subtract #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_p8_s64(a: int64x1_t) -> poly8x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.s16"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shsub))] +pub unsafe fn vhsubq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhsubs.v8i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.shsub.v8i16")] + fn vhsubq_s16_(a: int16x8_t, b: int16x8_t) -> int16x8_t; + } +vhsubq_s16_(a, b) } -/// Vector reinterpret cast operation +/// Signed halving subtract #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_p8_u64(a: uint64x1_t) -> poly8x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.s32"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shsub))] +pub unsafe fn vhsub_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhsubs.v2i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.shsub.v2i32")] + fn vhsub_s32_(a: int32x2_t, b: int32x2_t) -> int32x2_t; + } +vhsub_s32_(a, b) } -/// Vector reinterpret cast operation +/// Signed halving subtract #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s8_s64(a: int64x2_t) -> int8x16_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.s32"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shsub))] +pub unsafe fn vhsubq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhsubs.v4i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.shsub.v4i32")] + fn vhsubq_s32_(a: int32x4_t, b: int32x4_t) -> int32x4_t; + } +vhsubq_s32_(a, b) } -/// Vector reinterpret cast operation +/// Signed Subtract Wide #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s8_u64(a: uint64x2_t) -> int8x16_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubw))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssubw))] +pub unsafe fn vsubw_s8(a: int16x8_t, b: int8x8_t) -> int16x8_t { + simd_sub(a, simd_cast(b)) } -/// Vector reinterpret cast operation +/// Signed Subtract Wide #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u8_s64(a: int64x2_t) -> uint8x16_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubw))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssubw))] +pub unsafe fn vsubw_s16(a: int32x4_t, b: int16x4_t) -> int32x4_t { + simd_sub(a, simd_cast(b)) } -/// Vector reinterpret cast operation +/// Signed Subtract Wide #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u8_u64(a: uint64x2_t) -> uint8x16_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubw))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssubw))] +pub unsafe fn vsubw_s32(a: int64x2_t, b: int32x2_t) -> int64x2_t { + simd_sub(a, simd_cast(b)) } -/// Vector reinterpret cast operation +/// Unsigned Subtract Wide #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_p8_s64(a: int64x2_t) -> poly8x16_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubw))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usubw))] +pub unsafe fn vsubw_u8(a: uint16x8_t, b: uint8x8_t) -> uint16x8_t { + simd_sub(a, simd_cast(b)) } -/// Vector reinterpret cast operation +/// Unsigned Subtract Wide #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_p8_u64(a: uint64x2_t) -> poly8x16_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubw))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usubw))] +pub unsafe fn vsubw_u16(a: uint32x4_t, b: uint16x4_t) -> uint32x4_t { + simd_sub(a, simd_cast(b)) } -/// Vector reinterpret cast operation +/// Unsigned Subtract Wide #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s64_p8(a: poly8x8_t) -> int64x1_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubw))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usubw))] +pub unsafe fn vsubw_u32(a: uint64x2_t, b: uint32x2_t) -> uint64x2_t { + simd_sub(a, simd_cast(b)) } -/// Vector reinterpret cast operation +/// Signed Subtract Long #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s64_s8(a: int8x8_t) -> int64x1_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssubl))] +pub unsafe fn vsubl_s8(a: int8x8_t, b: int8x8_t) -> int16x8_t { + let c: int16x8_t = simd_cast(a); + let d: int16x8_t = simd_cast(b); + simd_sub(c, d) } -/// Vector reinterpret cast operation +/// Signed Subtract Long #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s64_u8(a: uint8x8_t) -> int64x1_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssubl))] +pub unsafe fn vsubl_s16(a: int16x4_t, b: int16x4_t) -> int32x4_t { + let c: int32x4_t = simd_cast(a); + let d: int32x4_t = simd_cast(b); + simd_sub(c, d) } -/// Vector reinterpret cast operation +/// Signed Subtract Long #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u64_p8(a: poly8x8_t) -> uint64x1_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssubl))] +pub unsafe fn vsubl_s32(a: int32x2_t, b: int32x2_t) -> int64x2_t { + let c: int64x2_t = simd_cast(a); + let d: int64x2_t = simd_cast(b); + simd_sub(c, d) } -/// Vector reinterpret cast operation +/// Unsigned Subtract Long #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u64_s8(a: int8x8_t) -> uint64x1_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usubl))] +pub unsafe fn vsubl_u8(a: uint8x8_t, b: uint8x8_t) -> uint16x8_t { + let c: uint16x8_t = simd_cast(a); + let d: uint16x8_t = simd_cast(b); + simd_sub(c, d) } -/// Vector reinterpret cast operation +/// Unsigned Subtract Long #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u64_u8(a: uint8x8_t) -> uint64x1_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usubl))] +pub unsafe fn vsubl_u16(a: uint16x4_t, b: uint16x4_t) -> uint32x4_t { + let c: uint32x4_t = simd_cast(a); + let d: uint32x4_t = simd_cast(b); + simd_sub(c, d) } -/// Vector reinterpret cast operation +/// Unsigned Subtract Long #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s64_p8(a: poly8x16_t) -> int64x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usubl))] +pub unsafe fn vsubl_u32(a: uint32x2_t, b: uint32x2_t) -> uint64x2_t { + let c: uint64x2_t = simd_cast(a); + let d: uint64x2_t = simd_cast(b); + simd_sub(c, d) } -/// Vector reinterpret cast operation +/// Maximum (vector) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s64_s8(a: int8x16_t) -> int64x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smax))] +pub unsafe fn vmax_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxs.v8i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.smax.v8i8")] + fn vmax_s8_(a: int8x8_t, b: int8x8_t) -> int8x8_t; + } +vmax_s8_(a, b) } -/// Vector reinterpret cast operation +/// Maximum (vector) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s64_u8(a: uint8x16_t) -> int64x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smax))] +pub unsafe fn vmaxq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxs.v16i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.smax.v16i8")] + fn vmaxq_s8_(a: int8x16_t, b: int8x16_t) -> int8x16_t; + } +vmaxq_s8_(a, b) } -/// Vector reinterpret cast operation +/// Maximum (vector) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u64_p8(a: poly8x16_t) -> uint64x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smax))] +pub unsafe fn vmax_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxs.v4i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.smax.v4i16")] + fn vmax_s16_(a: int16x4_t, b: int16x4_t) -> int16x4_t; + } +vmax_s16_(a, b) } -/// Vector reinterpret cast operation +/// Maximum (vector) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u64_s8(a: int8x16_t) -> uint64x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smax))] +pub unsafe fn vmaxq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxs.v8i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.smax.v8i16")] + fn vmaxq_s16_(a: int16x8_t, b: int16x8_t) -> int16x8_t; + } +vmaxq_s16_(a, b) } -/// Vector reinterpret cast operation +/// Maximum (vector) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u64_u8(a: uint8x16_t) -> uint64x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smax))] +pub unsafe fn vmax_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxs.v2i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.smax.v2i32")] + fn vmax_s32_(a: int32x2_t, b: int32x2_t) -> int32x2_t; + } +vmax_s32_(a, b) } -/// Vector reinterpret cast operation +/// Maximum (vector) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s8_f32(a: float32x2_t) -> int8x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smax))] +pub unsafe fn vmaxq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxs.v4i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.smax.v4i32")] + fn vmaxq_s32_(a: int32x4_t, b: int32x4_t) -> int32x4_t; + } +vmaxq_s32_(a, b) } -/// Vector reinterpret cast operation +/// Maximum (vector) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s16_f32(a: float32x2_t) -> int16x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umax))] +pub unsafe fn vmax_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxu.v8i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.umax.v8i8")] + fn vmax_u8_(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t; + } +vmax_u8_(a, b) } -/// Vector reinterpret cast operation +/// Maximum (vector) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s32_f32(a: float32x2_t) -> int32x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umax))] +pub unsafe fn vmaxq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxu.v16i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.umax.v16i8")] + fn vmaxq_u8_(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t; + } +vmaxq_u8_(a, b) } -/// Vector reinterpret cast operation +/// Maximum (vector) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_s64_f32(a: float32x2_t) -> int64x1_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umax))] +pub unsafe fn vmax_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxu.v4i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.umax.v4i16")] + fn vmax_u16_(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t; + } +vmax_u16_(a, b) } -/// Vector reinterpret cast operation +/// Maximum (vector) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s8_f32(a: float32x4_t) -> int8x16_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umax))] +pub unsafe fn vmaxq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxu.v8i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.umax.v8i16")] + fn vmaxq_u16_(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t; + } +vmaxq_u16_(a, b) } -/// Vector reinterpret cast operation +/// Maximum (vector) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s16_f32(a: float32x4_t) -> int16x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umax))] +pub unsafe fn vmax_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxu.v2i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.umax.v2i32")] + fn vmax_u32_(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t; + } +vmax_u32_(a, b) } -/// Vector reinterpret cast operation +/// Maximum (vector) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s32_f32(a: float32x4_t) -> int32x4_t { - transmute(a) -} - -/// Vector reinterpret cast operation -#[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_s64_f32(a: float32x4_t) -> int64x2_t { - transmute(a) -} - -/// Vector reinterpret cast operation -#[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u8_f32(a: float32x2_t) -> uint8x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umax))] +pub unsafe fn vmaxq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxu.v4i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.umax.v4i32")] + fn vmaxq_u32_(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t; + } +vmaxq_u32_(a, b) } -/// Vector reinterpret cast operation +/// Maximum (vector) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u16_f32(a: float32x2_t) -> uint16x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmax))] +pub unsafe fn vmax_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxs.v2f32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmax.v2f32")] + fn vmax_f32_(a: float32x2_t, b: float32x2_t) -> float32x2_t; + } +vmax_f32_(a, b) } -/// Vector reinterpret cast operation +/// Maximum (vector) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u32_f32(a: float32x2_t) -> uint32x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmax))] +pub unsafe fn vmaxq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxs.v4f32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmax.v4f32")] + fn vmaxq_f32_(a: float32x4_t, b: float32x4_t) -> float32x4_t; + } +vmaxq_f32_(a, b) } -/// Vector reinterpret cast operation +/// Floating-point Maximun Number (vector) #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_u64_f32(a: float32x2_t) -> uint64x1_t { - transmute(a) +#[cfg_attr(target_arch = "arm", target_feature(enable = "fp-armv8,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmaxnm))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmaxnm))] +pub unsafe fn vmaxnm_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxnm.v2f32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmaxnm.v2f32")] + fn vmaxnm_f32_(a: float32x2_t, b: float32x2_t) -> float32x2_t; + } +vmaxnm_f32_(a, b) } -/// Vector reinterpret cast operation +/// Floating-point Maximun Number (vector) #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u8_f32(a: float32x4_t) -> uint8x16_t { - transmute(a) +#[cfg_attr(target_arch = "arm", target_feature(enable = "fp-armv8,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmaxnm))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmaxnm))] +pub unsafe fn vmaxnmq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmaxnm.v4f32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmaxnm.v4f32")] + fn vmaxnmq_f32_(a: float32x4_t, b: float32x4_t) -> float32x4_t; + } +vmaxnmq_f32_(a, b) } -/// Vector reinterpret cast operation +/// Minimum (vector) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u16_f32(a: float32x4_t) -> uint16x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smin))] +pub unsafe fn vmin_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmins.v8i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.smin.v8i8")] + fn vmin_s8_(a: int8x8_t, b: int8x8_t) -> int8x8_t; + } +vmin_s8_(a, b) } -/// Vector reinterpret cast operation +/// Minimum (vector) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u32_f32(a: float32x4_t) -> uint32x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smin))] +pub unsafe fn vminq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmins.v16i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.smin.v16i8")] + fn vminq_s8_(a: int8x16_t, b: int8x16_t) -> int8x16_t; + } +vminq_s8_(a, b) } -/// Vector reinterpret cast operation +/// Minimum (vector) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_u64_f32(a: float32x4_t) -> uint64x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smin))] +pub unsafe fn vmin_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmins.v4i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.smin.v4i16")] + fn vmin_s16_(a: int16x4_t, b: int16x4_t) -> int16x4_t; + } +vmin_s16_(a, b) } -/// Vector reinterpret cast operation +/// Minimum (vector) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_p8_f32(a: float32x2_t) -> poly8x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smin))] +pub unsafe fn vminq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmins.v8i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.smin.v8i16")] + fn vminq_s16_(a: int16x8_t, b: int16x8_t) -> int16x8_t; + } +vminq_s16_(a, b) } -/// Vector reinterpret cast operation +/// Minimum (vector) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_p16_f32(a: float32x2_t) -> poly16x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smin))] +pub unsafe fn vmin_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmins.v2i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.smin.v2i32")] + fn vmin_s32_(a: int32x2_t, b: int32x2_t) -> int32x2_t; + } +vmin_s32_(a, b) } -/// Vector reinterpret cast operation +/// Minimum (vector) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_p8_f32(a: float32x4_t) -> poly8x16_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smin))] +pub unsafe fn vminq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmins.v4i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.smin.v4i32")] + fn vminq_s32_(a: int32x4_t, b: int32x4_t) -> int32x4_t; + } +vminq_s32_(a, b) } -/// Vector reinterpret cast operation +/// Minimum (vector) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_p16_f32(a: float32x4_t) -> poly16x8_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umin))] +pub unsafe fn vmin_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vminu.v8i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.umin.v8i8")] + fn vmin_u8_(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t; + } +vmin_u8_(a, b) } -/// Vector reinterpret cast operation +/// Minimum (vector) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_f32_s8(a: int8x8_t) -> float32x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umin))] +pub unsafe fn vminq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vminu.v16i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.umin.v16i8")] + fn vminq_u8_(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t; + } +vminq_u8_(a, b) } -/// Vector reinterpret cast operation +/// Minimum (vector) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_f32_s16(a: int16x4_t) -> float32x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umin))] +pub unsafe fn vmin_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vminu.v4i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.umin.v4i16")] + fn vmin_u16_(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t; + } +vmin_u16_(a, b) } -/// Vector reinterpret cast operation +/// Minimum (vector) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_f32_s32(a: int32x2_t) -> float32x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umin))] +pub unsafe fn vminq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vminu.v8i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.umin.v8i16")] + fn vminq_u16_(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t; + } +vminq_u16_(a, b) } -/// Vector reinterpret cast operation +/// Minimum (vector) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_f32_s64(a: int64x1_t) -> float32x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umin))] +pub unsafe fn vmin_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vminu.v2i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.umin.v2i32")] + fn vmin_u32_(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t; + } +vmin_u32_(a, b) } -/// Vector reinterpret cast operation +/// Minimum (vector) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_f32_s8(a: int8x16_t) -> float32x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umin))] +pub unsafe fn vminq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vminu.v4i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.umin.v4i32")] + fn vminq_u32_(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t; + } +vminq_u32_(a, b) } -/// Vector reinterpret cast operation +/// Minimum (vector) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_f32_s16(a: int16x8_t) -> float32x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmin))] +pub unsafe fn vmin_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmins.v2f32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmin.v2f32")] + fn vmin_f32_(a: float32x2_t, b: float32x2_t) -> float32x2_t; + } +vmin_f32_(a, b) } -/// Vector reinterpret cast operation +/// Minimum (vector) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_f32_s32(a: int32x4_t) -> float32x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmin))] +pub unsafe fn vminq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vmins.v4f32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmin.v4f32")] + fn vminq_f32_(a: float32x4_t, b: float32x4_t) -> float32x4_t; + } +vminq_f32_(a, b) } -/// Vector reinterpret cast operation +/// Floating-point Minimun Number (vector) #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_f32_s64(a: int64x2_t) -> float32x4_t { - transmute(a) +#[cfg_attr(target_arch = "arm", target_feature(enable = "fp-armv8,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vminnm))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fminnm))] +pub unsafe fn vminnm_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vminnm.v2f32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fminnm.v2f32")] + fn vminnm_f32_(a: float32x2_t, b: float32x2_t) -> float32x2_t; + } +vminnm_f32_(a, b) } -/// Vector reinterpret cast operation +/// Floating-point Minimun Number (vector) +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "fp-armv8,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vminnm))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fminnm))] +pub unsafe fn vminnmq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vminnm.v4f32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fminnm.v4f32")] + fn vminnmq_f32_(a: float32x4_t, b: float32x4_t) -> float32x4_t; + } +vminnmq_f32_(a, b) +} + +/// Floating-point add pairwise #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_f32_u8(a: uint8x8_t) -> float32x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpadd))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(faddp))] +pub unsafe fn vpadd_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vpadd.v2f32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.faddp.v2f32")] + fn vpadd_f32_(a: float32x2_t, b: float32x2_t) -> float32x2_t; + } +vpadd_f32_(a, b) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply long #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_f32_u16(a: uint16x4_t) -> float32x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmull))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmull))] +pub unsafe fn vqdmull_s16(a: int16x4_t, b: int16x4_t) -> int32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqdmull.v4i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqdmull.v4i32")] + fn vqdmull_s16_(a: int16x4_t, b: int16x4_t) -> int32x4_t; + } +vqdmull_s16_(a, b) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply long #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_f32_u32(a: uint32x2_t) -> float32x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmull))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmull))] +pub unsafe fn vqdmull_s32(a: int32x2_t, b: int32x2_t) -> int64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqdmull.v2i64")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqdmull.v2i64")] + fn vqdmull_s32_(a: int32x2_t, b: int32x2_t) -> int64x2_t; + } +vqdmull_s32_(a, b) } -/// Vector reinterpret cast operation +/// Vector saturating doubling long multiply with scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_f32_u64(a: uint64x1_t) -> float32x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmull))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmull))] +pub unsafe fn vqdmull_n_s16(a: int16x4_t, b: i16) -> int32x4_t { + vqdmull_s16(a, vdup_n_s16(b)) } -/// Vector reinterpret cast operation +/// Vector saturating doubling long multiply with scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_f32_u8(a: uint8x16_t) -> float32x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmull))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmull))] +pub unsafe fn vqdmull_n_s32(a: int32x2_t, b: i32) -> int64x2_t { + vqdmull_s32(a, vdup_n_s32(b)) } -/// Vector reinterpret cast operation +/// Vector saturating doubling long multiply by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_f32_u16(a: uint16x8_t) -> float32x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmull, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmull, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqdmull_lane_s16(a: int16x4_t, b: int16x4_t) -> int32x4_t { + static_assert_imm2!(N); + let b: int16x4_t = simd_shuffle4!(b, b, [N as u32, N as u32, N as u32, N as u32]); + vqdmull_s16(a, b) } -/// Vector reinterpret cast operation +/// Vector saturating doubling long multiply by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_f32_u32(a: uint32x4_t) -> float32x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmull, N = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmull, N = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqdmull_lane_s32(a: int32x2_t, b: int32x2_t) -> int64x2_t { + static_assert_imm1!(N); + let b: int32x2_t = simd_shuffle2!(b, b, [N as u32, N as u32]); + vqdmull_s32(a, b) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply-add long #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_f32_u64(a: uint64x2_t) -> float32x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlal))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlal))] +pub unsafe fn vqdmlal_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t { + vqaddq_s32(a, vqdmull_s16(b, c)) } -/// Vector reinterpret cast operation +/// Signed saturating doubling multiply-add long #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_f32_p8(a: poly8x8_t) -> float32x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlal))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlal))] +pub unsafe fn vqdmlal_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t { + vqaddq_s64(a, vqdmull_s32(b, c)) } -/// Vector reinterpret cast operation +/// Vector widening saturating doubling multiply accumulate with scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpret_f32_p16(a: poly16x4_t) -> float32x2_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlal))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlal))] +pub unsafe fn vqdmlal_n_s16(a: int32x4_t, b: int16x4_t, c: i16) -> int32x4_t { + vqaddq_s32(a, vqdmull_n_s16(b, c)) } -/// Vector reinterpret cast operation +/// Vector widening saturating doubling multiply accumulate with scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_f32_p8(a: poly8x16_t) -> float32x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlal))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlal))] +pub unsafe fn vqdmlal_n_s32(a: int64x2_t, b: int32x2_t, c: i32) -> int64x2_t { + vqaddq_s64(a, vqdmull_n_s32(b, c)) } -/// Vector reinterpret cast operation +/// Vector widening saturating doubling multiply accumulate with scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] -pub unsafe fn vreinterpretq_f32_p16(a: poly16x8_t) -> float32x4_t { - transmute(a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlal, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlal, N = 2))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqdmlal_lane_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t { + static_assert_imm2!(N); + vqaddq_s32(a, vqdmull_lane_s16::(b, c)) } -/// Signed rounding shift left +/// Vector widening saturating doubling multiply accumulate with scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))] -pub unsafe fn vrshl_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshifts.v8i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.srshl.v8i8")] - fn vrshl_s8_(a: int8x8_t, b: int8x8_t) -> int8x8_t; - } -vrshl_s8_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlal, N = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlal, N = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqdmlal_lane_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t { + static_assert_imm1!(N); + vqaddq_s64(a, vqdmull_lane_s32::(b, c)) } -/// Signed rounding shift left +/// Signed saturating doubling multiply-subtract long #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))] -pub unsafe fn vrshlq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshifts.v16i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.srshl.v16i8")] - fn vrshlq_s8_(a: int8x16_t, b: int8x16_t) -> int8x16_t; - } -vrshlq_s8_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlsl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlsl))] +pub unsafe fn vqdmlsl_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t { + vqsubq_s32(a, vqdmull_s16(b, c)) } -/// Signed rounding shift left +/// Signed saturating doubling multiply-subtract long #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))] -pub unsafe fn vrshl_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshifts.v4i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.srshl.v4i16")] - fn vrshl_s16_(a: int16x4_t, b: int16x4_t) -> int16x4_t; - } -vrshl_s16_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlsl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlsl))] +pub unsafe fn vqdmlsl_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t { + vqsubq_s64(a, vqdmull_s32(b, c)) } -/// Signed rounding shift left +/// Vector widening saturating doubling multiply subtract with scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))] -pub unsafe fn vrshlq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshifts.v8i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.srshl.v8i16")] - fn vrshlq_s16_(a: int16x8_t, b: int16x8_t) -> int16x8_t; - } -vrshlq_s16_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlsl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlsl))] +pub unsafe fn vqdmlsl_n_s16(a: int32x4_t, b: int16x4_t, c: i16) -> int32x4_t { + vqsubq_s32(a, vqdmull_n_s16(b, c)) } -/// Signed rounding shift left +/// Vector widening saturating doubling multiply subtract with scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))] -pub unsafe fn vrshl_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshifts.v2i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.srshl.v2i32")] - fn vrshl_s32_(a: int32x2_t, b: int32x2_t) -> int32x2_t; - } -vrshl_s32_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlsl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlsl))] +pub unsafe fn vqdmlsl_n_s32(a: int64x2_t, b: int32x2_t, c: i32) -> int64x2_t { + vqsubq_s64(a, vqdmull_n_s32(b, c)) } -/// Signed rounding shift left +/// Vector widening saturating doubling multiply subtract with scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))] -pub unsafe fn vrshlq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshifts.v4i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.srshl.v4i32")] - fn vrshlq_s32_(a: int32x4_t, b: int32x4_t) -> int32x4_t; - } -vrshlq_s32_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlsl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlsl, N = 2))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqdmlsl_lane_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t { + static_assert_imm2!(N); + vqsubq_s32(a, vqdmull_lane_s16::(b, c)) } -/// Signed rounding shift left +/// Vector widening saturating doubling multiply subtract with scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))] -pub unsafe fn vrshl_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshifts.v1i64")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.srshl.v1i64")] - fn vrshl_s64_(a: int64x1_t, b: int64x1_t) -> int64x1_t; - } -vrshl_s64_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlsl, N = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlsl, N = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqdmlsl_lane_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t { + static_assert_imm1!(N); + vqsubq_s64(a, vqdmull_lane_s32::(b, c)) } -/// Signed rounding shift left +/// Signed saturating doubling multiply returning high half #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))] -pub unsafe fn vrshlq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh))] +pub unsafe fn vqdmulh_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshifts.v2i64")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.srshl.v2i64")] - fn vrshlq_s64_(a: int64x2_t, b: int64x2_t) -> int64x2_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqdmulh.v4i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqdmulh.v4i16")] + fn vqdmulh_s16_(a: int16x4_t, b: int16x4_t) -> int16x4_t; } -vrshlq_s64_(a, b) +vqdmulh_s16_(a, b) } -/// Unsigned rounding shift left +/// Signed saturating doubling multiply returning high half #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))] -pub unsafe fn vrshl_u8(a: uint8x8_t, b: int8x8_t) -> uint8x8_t { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh))] +pub unsafe fn vqdmulhq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshiftu.v8i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.urshl.v8i8")] - fn vrshl_u8_(a: uint8x8_t, b: int8x8_t) -> uint8x8_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqdmulh.v8i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqdmulh.v8i16")] + fn vqdmulhq_s16_(a: int16x8_t, b: int16x8_t) -> int16x8_t; } -vrshl_u8_(a, b) +vqdmulhq_s16_(a, b) } -/// Unsigned rounding shift left +/// Signed saturating doubling multiply returning high half #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))] -pub unsafe fn vrshlq_u8(a: uint8x16_t, b: int8x16_t) -> uint8x16_t { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh))] +pub unsafe fn vqdmulh_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshiftu.v16i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.urshl.v16i8")] - fn vrshlq_u8_(a: uint8x16_t, b: int8x16_t) -> uint8x16_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqdmulh.v2i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqdmulh.v2i32")] + fn vqdmulh_s32_(a: int32x2_t, b: int32x2_t) -> int32x2_t; } -vrshlq_u8_(a, b) +vqdmulh_s32_(a, b) } -/// Unsigned rounding shift left +/// Signed saturating doubling multiply returning high half #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))] -pub unsafe fn vrshl_u16(a: uint16x4_t, b: int16x4_t) -> uint16x4_t { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh))] +pub unsafe fn vqdmulhq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshiftu.v4i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.urshl.v4i16")] - fn vrshl_u16_(a: uint16x4_t, b: int16x4_t) -> uint16x4_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqdmulh.v4i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqdmulh.v4i32")] + fn vqdmulhq_s32_(a: int32x4_t, b: int32x4_t) -> int32x4_t; } -vrshl_u16_(a, b) +vqdmulhq_s32_(a, b) } -/// Unsigned rounding shift left +/// Vector saturating doubling multiply high with scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))] -pub unsafe fn vrshlq_u16(a: uint16x8_t, b: int16x8_t) -> uint16x8_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshiftu.v8i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.urshl.v8i16")] - fn vrshlq_u16_(a: uint16x8_t, b: int16x8_t) -> uint16x8_t; - } -vrshlq_u16_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh))] +pub unsafe fn vqdmulh_n_s16(a: int16x4_t, b: i16) -> int16x4_t { + let b: int16x4_t = vdup_n_s16(b); + vqdmulh_s16(a, b) } -/// Unsigned rounding shift left +/// Vector saturating doubling multiply high with scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))] -pub unsafe fn vrshl_u32(a: uint32x2_t, b: int32x2_t) -> uint32x2_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshiftu.v2i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.urshl.v2i32")] - fn vrshl_u32_(a: uint32x2_t, b: int32x2_t) -> uint32x2_t; - } -vrshl_u32_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh))] +pub unsafe fn vqdmulh_n_s32(a: int32x2_t, b: i32) -> int32x2_t { + let b: int32x2_t = vdup_n_s32(b); + vqdmulh_s32(a, b) } -/// Unsigned rounding shift left +/// Vector saturating doubling multiply high with scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))] -pub unsafe fn vrshlq_u32(a: uint32x4_t, b: int32x4_t) -> uint32x4_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshiftu.v4i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.urshl.v4i32")] - fn vrshlq_u32_(a: uint32x4_t, b: int32x4_t) -> uint32x4_t; - } -vrshlq_u32_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh))] +pub unsafe fn vqdmulhq_n_s16(a: int16x8_t, b: i16) -> int16x8_t { + let b: int16x8_t = vdupq_n_s16(b); + vqdmulhq_s16(a, b) } -/// Unsigned rounding shift left +/// Vector saturating doubling multiply high with scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))] -pub unsafe fn vrshl_u64(a: uint64x1_t, b: int64x1_t) -> uint64x1_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshiftu.v1i64")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.urshl.v1i64")] - fn vrshl_u64_(a: uint64x1_t, b: int64x1_t) -> uint64x1_t; - } -vrshl_u64_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh))] +pub unsafe fn vqdmulhq_n_s32(a: int32x4_t, b: i32) -> int32x4_t { + let b: int32x4_t = vdupq_n_s32(b); + vqdmulhq_s32(a, b) } -/// Unsigned rounding shift left +/// Vector saturating doubling multiply high by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))] -pub unsafe fn vrshlq_u64(a: uint64x2_t, b: int64x2_t) -> uint64x2_t { - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshiftu.v2i64")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.urshl.v2i64")] - fn vrshlq_u64_(a: uint64x2_t, b: int64x2_t) -> uint64x2_t; - } -vrshlq_u64_(a, b) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqdmulhq_laneq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { + static_assert_imm3!(LANE); + vqdmulhq_s16(a, vdupq_n_s16(simd_extract(b, LANE as u32))) } -/// Signed rounding shift right +/// Vector saturating doubling multiply high by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vrshr_n_s8(a: int8x8_t) -> int8x8_t { - static_assert!(N : i32 where N >= 1 && N <= 8); - vrshl_s8(a, vdup_n_s8((-N).try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqdmulh_laneq_s16(a: int16x4_t, b: int16x8_t) -> int16x4_t { + static_assert_imm3!(LANE); + vqdmulh_s16(a, vdup_n_s16(simd_extract(b, LANE as u32))) } -/// Signed rounding shift right +/// Vector saturating doubling multiply high by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vrshrq_n_s8(a: int8x16_t) -> int8x16_t { - static_assert!(N : i32 where N >= 1 && N <= 8); - vrshlq_s8(a, vdupq_n_s8((-N).try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqdmulhq_laneq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { + static_assert_imm2!(LANE); + vqdmulhq_s32(a, vdupq_n_s32(simd_extract(b, LANE as u32))) } -/// Signed rounding shift right +/// Vector saturating doubling multiply high by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vrshr_n_s16(a: int16x4_t) -> int16x4_t { - static_assert!(N : i32 where N >= 1 && N <= 16); - vrshl_s16(a, vdup_n_s16((-N).try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqdmulh_laneq_s32(a: int32x2_t, b: int32x4_t) -> int32x2_t { + static_assert_imm2!(LANE); + vqdmulh_s32(a, vdup_n_s32(simd_extract(b, LANE as u32))) } -/// Signed rounding shift right +/// Signed saturating extract narrow #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vrshrq_n_s16(a: int16x8_t) -> int16x8_t { - static_assert!(N : i32 where N >= 1 && N <= 16); - vrshlq_s16(a, vdupq_n_s16((-N).try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqxtn))] +pub unsafe fn vqmovn_s16(a: int16x8_t) -> int8x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqmovns.v8i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqxtn.v8i8")] + fn vqmovn_s16_(a: int16x8_t) -> int8x8_t; + } +vqmovn_s16_(a) } -/// Signed rounding shift right +/// Signed saturating extract narrow #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vrshr_n_s32(a: int32x2_t) -> int32x2_t { - static_assert!(N : i32 where N >= 1 && N <= 32); - vrshl_s32(a, vdup_n_s32((-N).try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqxtn))] +pub unsafe fn vqmovn_s32(a: int32x4_t) -> int16x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqmovns.v4i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqxtn.v4i16")] + fn vqmovn_s32_(a: int32x4_t) -> int16x4_t; + } +vqmovn_s32_(a) } -/// Signed rounding shift right +/// Signed saturating extract narrow #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vrshrq_n_s32(a: int32x4_t) -> int32x4_t { - static_assert!(N : i32 where N >= 1 && N <= 32); - vrshlq_s32(a, vdupq_n_s32((-N).try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqxtn))] +pub unsafe fn vqmovn_s64(a: int64x2_t) -> int32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqmovns.v2i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqxtn.v2i32")] + fn vqmovn_s64_(a: int64x2_t) -> int32x2_t; + } +vqmovn_s64_(a) } -/// Signed rounding shift right +/// Unsigned saturating extract narrow #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vrshr_n_s64(a: int64x1_t) -> int64x1_t { - static_assert!(N : i32 where N >= 1 && N <= 64); - vrshl_s64(a, vdup_n_s64((-N).try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqxtn))] +pub unsafe fn vqmovn_u16(a: uint16x8_t) -> uint8x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqmovnu.v8i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqxtn.v8i8")] + fn vqmovn_u16_(a: uint16x8_t) -> uint8x8_t; + } +vqmovn_u16_(a) } -/// Signed rounding shift right +/// Unsigned saturating extract narrow #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vrshrq_n_s64(a: int64x2_t) -> int64x2_t { - static_assert!(N : i32 where N >= 1 && N <= 64); - vrshlq_s64(a, vdupq_n_s64((-N).try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqxtn))] +pub unsafe fn vqmovn_u32(a: uint32x4_t) -> uint16x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqmovnu.v4i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqxtn.v4i16")] + fn vqmovn_u32_(a: uint32x4_t) -> uint16x4_t; + } +vqmovn_u32_(a) } -/// Unsigned rounding shift right +/// Unsigned saturating extract narrow #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vrshr_n_u8(a: uint8x8_t) -> uint8x8_t { - static_assert!(N : i32 where N >= 1 && N <= 8); - vrshl_u8(a, vdup_n_s8((-N).try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqxtn))] +pub unsafe fn vqmovn_u64(a: uint64x2_t) -> uint32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqmovnu.v2i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqxtn.v2i32")] + fn vqmovn_u64_(a: uint64x2_t) -> uint32x2_t; + } +vqmovn_u64_(a) } -/// Unsigned rounding shift right +/// Signed saturating extract unsigned narrow #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vrshrq_n_u8(a: uint8x16_t) -> uint8x16_t { - static_assert!(N : i32 where N >= 1 && N <= 8); - vrshlq_u8(a, vdupq_n_s8((-N).try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovun))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqxtun))] +pub unsafe fn vqmovun_s16(a: int16x8_t) -> uint8x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqmovnsu.v8i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqxtun.v8i8")] + fn vqmovun_s16_(a: int16x8_t) -> uint8x8_t; + } +vqmovun_s16_(a) } -/// Unsigned rounding shift right +/// Signed saturating extract unsigned narrow #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vrshr_n_u16(a: uint16x4_t) -> uint16x4_t { - static_assert!(N : i32 where N >= 1 && N <= 16); - vrshl_u16(a, vdup_n_s16((-N).try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovun))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqxtun))] +pub unsafe fn vqmovun_s32(a: int32x4_t) -> uint16x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqmovnsu.v4i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqxtun.v4i16")] + fn vqmovun_s32_(a: int32x4_t) -> uint16x4_t; + } +vqmovun_s32_(a) } -/// Unsigned rounding shift right +/// Signed saturating extract unsigned narrow #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vrshrq_n_u16(a: uint16x8_t) -> uint16x8_t { - static_assert!(N : i32 where N >= 1 && N <= 16); - vrshlq_u16(a, vdupq_n_s16((-N).try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovun))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqxtun))] +pub unsafe fn vqmovun_s64(a: int64x2_t) -> uint32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqmovnsu.v2i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqxtun.v2i32")] + fn vqmovun_s64_(a: int64x2_t) -> uint32x2_t; + } +vqmovun_s64_(a) } -/// Unsigned rounding shift right +/// Signed saturating rounding doubling multiply returning high half #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vrshr_n_u32(a: uint32x2_t) -> uint32x2_t { - static_assert!(N : i32 where N >= 1 && N <= 32); - vrshl_u32(a, vdup_n_s32((-N).try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] +pub unsafe fn vqrdmulh_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrdmulh.v4i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrdmulh.v4i16")] + fn vqrdmulh_s16_(a: int16x4_t, b: int16x4_t) -> int16x4_t; + } +vqrdmulh_s16_(a, b) } -/// Unsigned rounding shift right +/// Signed saturating rounding doubling multiply returning high half #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vrshrq_n_u32(a: uint32x4_t) -> uint32x4_t { - static_assert!(N : i32 where N >= 1 && N <= 32); - vrshlq_u32(a, vdupq_n_s32((-N).try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] +pub unsafe fn vqrdmulhq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrdmulh.v8i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrdmulh.v8i16")] + fn vqrdmulhq_s16_(a: int16x8_t, b: int16x8_t) -> int16x8_t; + } +vqrdmulhq_s16_(a, b) } -/// Unsigned rounding shift right +/// Signed saturating rounding doubling multiply returning high half #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vrshr_n_u64(a: uint64x1_t) -> uint64x1_t { - static_assert!(N : i32 where N >= 1 && N <= 64); - vrshl_u64(a, vdup_n_s64((-N).try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] +pub unsafe fn vqrdmulh_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrdmulh.v2i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrdmulh.v2i32")] + fn vqrdmulh_s32_(a: int32x2_t, b: int32x2_t) -> int32x2_t; + } +vqrdmulh_s32_(a, b) } -/// Unsigned rounding shift right +/// Signed saturating rounding doubling multiply returning high half #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vrshrq_n_u64(a: uint64x2_t) -> uint64x2_t { - static_assert!(N : i32 where N >= 1 && N <= 64); - vrshlq_u64(a, vdupq_n_s64((-N).try_into().unwrap())) -} - -/// Rounding shift right narrow -#[inline] -#[cfg(target_arch = "arm")] -#[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vrshrn_n_s16(a: int16x8_t) -> int8x8_t { - static_assert!(N : i32 where N >= 1 && N <= 8); +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] +pub unsafe fn vqrdmulhq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshiftn.v8i8")] - fn vrshrn_n_s16_(a: int16x8_t, n: int16x8_t) -> int8x8_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrdmulh.v4i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrdmulh.v4i32")] + fn vqrdmulhq_s32_(a: int32x4_t, b: int32x4_t) -> int32x4_t; } -vrshrn_n_s16_(a, int16x8_t(-N as i16, -N as i16, -N as i16, -N as i16, -N as i16, -N as i16, -N as i16, -N as i16)) +vqrdmulhq_s32_(a, b) } -/// Rounding shift right narrow +/// Vector saturating rounding doubling multiply high with scalar #[inline] -#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vrshrn_n_s16(a: int16x8_t) -> int8x8_t { - static_assert!(N : i32 where N >= 1 && N <= 8); - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.rshrn.v8i8")] - fn vrshrn_n_s16_(a: int16x8_t, n: i32) -> int8x8_t; - } -vrshrn_n_s16_(a, N) -} - -/// Rounding shift right narrow -#[inline] -#[cfg(target_arch = "arm")] -#[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vrshrn_n_s32(a: int32x4_t) -> int16x4_t { - static_assert!(N : i32 where N >= 1 && N <= 16); - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshiftn.v4i16")] - fn vrshrn_n_s32_(a: int32x4_t, n: int32x4_t) -> int16x4_t; - } -vrshrn_n_s32_(a, int32x4_t(-N as i32, -N as i32, -N as i32, -N as i32)) +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] +pub unsafe fn vqrdmulh_n_s16(a: int16x4_t, b: i16) -> int16x4_t { + vqrdmulh_s16(a, vdup_n_s16(b)) } -/// Rounding shift right narrow +/// Vector saturating rounding doubling multiply high with scalar #[inline] -#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vrshrn_n_s32(a: int32x4_t) -> int16x4_t { - static_assert!(N : i32 where N >= 1 && N <= 16); - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.rshrn.v4i16")] - fn vrshrn_n_s32_(a: int32x4_t, n: i32) -> int16x4_t; - } -vrshrn_n_s32_(a, N) -} - -/// Rounding shift right narrow -#[inline] -#[cfg(target_arch = "arm")] -#[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vrshrn_n_s64(a: int64x2_t) -> int32x2_t { - static_assert!(N : i32 where N >= 1 && N <= 32); - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshiftn.v2i32")] - fn vrshrn_n_s64_(a: int64x2_t, n: int64x2_t) -> int32x2_t; - } -vrshrn_n_s64_(a, int64x2_t(-N as i64, -N as i64)) +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] +pub unsafe fn vqrdmulhq_n_s16(a: int16x8_t, b: i16) -> int16x8_t { + vqrdmulhq_s16(a, vdupq_n_s16(b)) } -/// Rounding shift right narrow +/// Vector saturating rounding doubling multiply high with scalar #[inline] -#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vrshrn_n_s64(a: int64x2_t) -> int32x2_t { - static_assert!(N : i32 where N >= 1 && N <= 32); - #[allow(improper_ctypes)] - extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.rshrn.v2i32")] - fn vrshrn_n_s64_(a: int64x2_t, n: i32) -> int32x2_t; - } -vrshrn_n_s64_(a, N) +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] +pub unsafe fn vqrdmulh_n_s32(a: int32x2_t, b: i32) -> int32x2_t { + vqrdmulh_s32(a, vdup_n_s32(b)) } -/// Rounding shift right narrow +/// Vector saturating rounding doubling multiply high with scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshrn, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vrshrn_n_u16(a: uint16x8_t) -> uint8x8_t { - static_assert!(N : i32 where N >= 1 && N <= 8); - transmute(vrshrn_n_s16::(transmute(a))) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] +pub unsafe fn vqrdmulhq_n_s32(a: int32x4_t, b: i32) -> int32x4_t { + vqrdmulhq_s32(a, vdupq_n_s32(b)) } -/// Rounding shift right narrow +/// Vector rounding saturating doubling multiply high by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshrn, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vrshrn_n_u32(a: uint32x4_t) -> uint16x4_t { - static_assert!(N : i32 where N >= 1 && N <= 16); - transmute(vrshrn_n_s32::(transmute(a))) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqrdmulh_lane_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { + static_assert_imm2!(LANE); + let b: int16x4_t = simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32]); + vqrdmulh_s16(a, b) } -/// Rounding shift right narrow +/// Vector rounding saturating doubling multiply high by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshrn, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rshrn, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vrshrn_n_u64(a: uint64x2_t) -> uint32x2_t { - static_assert!(N : i32 where N >= 1 && N <= 32); - transmute(vrshrn_n_s64::(transmute(a))) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vqrdmulh_laneq_s16(a: int16x4_t, b: int16x8_t) -> int16x4_t { + static_assert_imm3!(LANE); + let b: int16x4_t = simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32]); + vqrdmulh_s16(a, b) } -/// Signed rounding shift right and accumulate +/// Vector rounding saturating doubling multiply high by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vrsra_n_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { - static_assert!(N : i32 where N >= 1 && N <= 8); - simd_add(a, vrshr_n_s8::(b)) +pub unsafe fn vqrdmulhq_lane_s16(a: int16x8_t, b: int16x4_t) -> int16x8_t { + static_assert_imm2!(LANE); + let b: int16x8_t = simd_shuffle8!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32]); + vqrdmulhq_s16(a, b) } -/// Signed rounding shift right and accumulate +/// Vector rounding saturating doubling multiply high by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vrsraq_n_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { - static_assert!(N : i32 where N >= 1 && N <= 8); - simd_add(a, vrshrq_n_s8::(b)) +pub unsafe fn vqrdmulhq_laneq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { + static_assert_imm3!(LANE); + let b: int16x8_t = simd_shuffle8!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32]); + vqrdmulhq_s16(a, b) } -/// Signed rounding shift right and accumulate +/// Vector rounding saturating doubling multiply high by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vrsra_n_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { - static_assert!(N : i32 where N >= 1 && N <= 16); - simd_add(a, vrshr_n_s16::(b)) +pub unsafe fn vqrdmulh_lane_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { + static_assert_imm1!(LANE); + let b: int32x2_t = simd_shuffle2!(b, b, [LANE as u32, LANE as u32]); + vqrdmulh_s32(a, b) } -/// Signed rounding shift right and accumulate +/// Vector rounding saturating doubling multiply high by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vrsraq_n_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { - static_assert!(N : i32 where N >= 1 && N <= 16); - simd_add(a, vrshrq_n_s16::(b)) +pub unsafe fn vqrdmulh_laneq_s32(a: int32x2_t, b: int32x4_t) -> int32x2_t { + static_assert_imm2!(LANE); + let b: int32x2_t = simd_shuffle2!(b, b, [LANE as u32, LANE as u32]); + vqrdmulh_s32(a, b) } -/// Signed rounding shift right and accumulate +/// Vector rounding saturating doubling multiply high by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vrsra_n_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { - static_assert!(N : i32 where N >= 1 && N <= 32); - simd_add(a, vrshr_n_s32::(b)) +pub unsafe fn vqrdmulhq_lane_s32(a: int32x4_t, b: int32x2_t) -> int32x4_t { + static_assert_imm1!(LANE); + let b: int32x4_t = simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32]); + vqrdmulhq_s32(a, b) } -/// Signed rounding shift right and accumulate +/// Vector rounding saturating doubling multiply high by scalar #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(2)] -pub unsafe fn vrsraq_n_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { - static_assert!(N : i32 where N >= 1 && N <= 32); - simd_add(a, vrshrq_n_s32::(b)) +pub unsafe fn vqrdmulhq_laneq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { + static_assert_imm2!(LANE); + let b: int32x4_t = simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32]); + vqrdmulhq_s32(a, b) } -/// Signed rounding shift right and accumulate +/// Signed saturating rounding doubling multiply subtract returning high half #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vrsra_n_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { - static_assert!(N : i32 where N >= 1 && N <= 64); - simd_add(a, vrshr_n_s64::(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] +pub unsafe fn vqrdmlsh_s16(a: int16x4_t, b: int16x4_t, c: int16x4_t) -> int16x4_t { + vqsub_s16(a, vqrdmulh_s16(b, c)) } -/// Signed rounding shift right and accumulate +/// Signed saturating rounding doubling multiply subtract returning high half #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vrsraq_n_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { - static_assert!(N : i32 where N >= 1 && N <= 64); - simd_add(a, vrshrq_n_s64::(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] +pub unsafe fn vqrdmlshq_s16(a: int16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8_t { + vqsubq_s16(a, vqrdmulhq_s16(b, c)) } -/// Unsigned rounding shift right and accumulate +/// Signed saturating rounding doubling multiply subtract returning high half #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vrsra_n_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { - static_assert!(N : i32 where N >= 1 && N <= 8); - simd_add(a, vrshr_n_u8::(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] +pub unsafe fn vqrdmlsh_s32(a: int32x2_t, b: int32x2_t, c: int32x2_t) -> int32x2_t { + vqsub_s32(a, vqrdmulh_s32(b, c)) } -/// Unsigned rounding shift right and accumulate +/// Signed saturating rounding doubling multiply subtract returning high half #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vrsraq_n_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { - static_assert!(N : i32 where N >= 1 && N <= 8); - simd_add(a, vrshrq_n_u8::(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] +pub unsafe fn vqrdmlshq_s32(a: int32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4_t { + vqsubq_s32(a, vqrdmulhq_s32(b, c)) } -/// Unsigned rounding shift right and accumulate +/// Signed saturating rounding doubling multiply subtract returning high half #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vrsra_n_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { - static_assert!(N : i32 where N >= 1 && N <= 16); - simd_add(a, vrshr_n_u16::(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqrdmlsh_lane_s16(a: int16x4_t, b: int16x4_t, c: int16x4_t) -> int16x4_t { + static_assert_imm2!(LANE); + vqsub_s16(a, vqrdmulh_lane_s16::(b, c)) } -/// Unsigned rounding shift right and accumulate +/// Signed saturating rounding doubling multiply subtract returning high half #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vrsraq_n_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { - static_assert!(N : i32 where N >= 1 && N <= 16); - simd_add(a, vrshrq_n_u16::(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqrdmlsh_laneq_s16(a: int16x4_t, b: int16x4_t, c: int16x8_t) -> int16x4_t { + static_assert_imm3!(LANE); + vqsub_s16(a, vqrdmulh_laneq_s16::(b, c)) } -/// Unsigned rounding shift right and accumulate +/// Signed saturating rounding doubling multiply subtract returning high half #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vrsra_n_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { - static_assert!(N : i32 where N >= 1 && N <= 32); - simd_add(a, vrshr_n_u32::(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqrdmlshq_lane_s16(a: int16x8_t, b: int16x8_t, c: int16x4_t) -> int16x8_t { + static_assert_imm2!(LANE); + vqsubq_s16(a, vqrdmulhq_lane_s16::(b, c)) } -/// Unsigned rounding shift right and accumulate +/// Signed saturating rounding doubling multiply subtract returning high half #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vrsraq_n_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { - static_assert!(N : i32 where N >= 1 && N <= 32); - simd_add(a, vrshrq_n_u32::(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqrdmlshq_laneq_s16(a: int16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8_t { + static_assert_imm3!(LANE); + vqsubq_s16(a, vqrdmulhq_laneq_s16::(b, c)) } -/// Unsigned rounding shift right and accumulate +/// Signed saturating rounding doubling multiply subtract returning high half #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vrsra_n_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { - static_assert!(N : i32 where N >= 1 && N <= 64); - simd_add(a, vrshr_n_u64::(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqrdmlsh_lane_s32(a: int32x2_t, b: int32x2_t, c: int32x2_t) -> int32x2_t { + static_assert_imm1!(LANE); + vqsub_s32(a, vqrdmulh_lane_s32::(b, c)) } -/// Unsigned rounding shift right and accumulate +/// Signed saturating rounding doubling multiply subtract returning high half #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vrsraq_n_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { - static_assert!(N : i32 where N >= 1 && N <= 64); - simd_add(a, vrshrq_n_u64::(b)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqrdmlsh_laneq_s32(a: int32x2_t, b: int32x2_t, c: int32x4_t) -> int32x2_t { + static_assert_imm2!(LANE); + vqsub_s32(a, vqrdmulh_laneq_s32::(b, c)) } -/// Insert vector element from another vector element +/// Signed saturating rounding doubling multiply subtract returning high half #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vset_lane_s8(a: i8, b: int8x8_t) -> int8x8_t { - static_assert_imm3!(LANE); - simd_insert(b, LANE as u32, a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqrdmlshq_lane_s32(a: int32x4_t, b: int32x4_t, c: int32x2_t) -> int32x4_t { + static_assert_imm1!(LANE); + vqsubq_s32(a, vqrdmulhq_lane_s32::(b, c)) } -/// Insert vector element from another vector element +/// Signed saturating rounding doubling multiply subtract returning high half #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vset_lane_s16(a: i16, b: int16x4_t) -> int16x4_t { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] +#[rustc_legacy_const_generics(3)] +pub unsafe fn vqrdmlshq_laneq_s32(a: int32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4_t { static_assert_imm2!(LANE); - simd_insert(b, LANE as u32, a) + vqsubq_s32(a, vqrdmulhq_laneq_s32::(b, c)) } -/// Insert vector element from another vector element +/// Signed saturating rounding shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vset_lane_s32(a: i32, b: int32x2_t) -> int32x2_t { - static_assert_imm1!(LANE); - simd_insert(b, LANE as u32, a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))] +pub unsafe fn vqrshl_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshifts.v8i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshl.v8i8")] + fn vqrshl_s8_(a: int8x8_t, b: int8x8_t) -> int8x8_t; + } +vqrshl_s8_(a, b) } -/// Insert vector element from another vector element +/// Signed saturating rounding shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vset_lane_s64(a: i64, b: int64x1_t) -> int64x1_t { - static_assert!(LANE : i32 where LANE == 0); - simd_insert(b, LANE as u32, a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))] +pub unsafe fn vqrshlq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshifts.v16i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshl.v16i8")] + fn vqrshlq_s8_(a: int8x16_t, b: int8x16_t) -> int8x16_t; + } +vqrshlq_s8_(a, b) } -/// Insert vector element from another vector element +/// Signed saturating rounding shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vset_lane_u8(a: u8, b: uint8x8_t) -> uint8x8_t { - static_assert_imm3!(LANE); - simd_insert(b, LANE as u32, a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))] +pub unsafe fn vqrshl_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshifts.v4i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshl.v4i16")] + fn vqrshl_s16_(a: int16x4_t, b: int16x4_t) -> int16x4_t; + } +vqrshl_s16_(a, b) } -/// Insert vector element from another vector element +/// Signed saturating rounding shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vset_lane_u16(a: u16, b: uint16x4_t) -> uint16x4_t { - static_assert_imm2!(LANE); - simd_insert(b, LANE as u32, a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))] +pub unsafe fn vqrshlq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshifts.v8i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshl.v8i16")] + fn vqrshlq_s16_(a: int16x8_t, b: int16x8_t) -> int16x8_t; + } +vqrshlq_s16_(a, b) } -/// Insert vector element from another vector element +/// Signed saturating rounding shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vset_lane_u32(a: u32, b: uint32x2_t) -> uint32x2_t { - static_assert_imm1!(LANE); - simd_insert(b, LANE as u32, a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))] +pub unsafe fn vqrshl_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshifts.v2i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshl.v2i32")] + fn vqrshl_s32_(a: int32x2_t, b: int32x2_t) -> int32x2_t; + } +vqrshl_s32_(a, b) } -/// Insert vector element from another vector element +/// Signed saturating rounding shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vset_lane_u64(a: u64, b: uint64x1_t) -> uint64x1_t { - static_assert!(LANE : i32 where LANE == 0); - simd_insert(b, LANE as u32, a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))] +pub unsafe fn vqrshlq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshifts.v4i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshl.v4i32")] + fn vqrshlq_s32_(a: int32x4_t, b: int32x4_t) -> int32x4_t; + } +vqrshlq_s32_(a, b) } -/// Insert vector element from another vector element +/// Signed saturating rounding shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vset_lane_p8(a: p8, b: poly8x8_t) -> poly8x8_t { - static_assert_imm3!(LANE); - simd_insert(b, LANE as u32, a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))] +pub unsafe fn vqrshl_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshifts.v1i64")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshl.v1i64")] + fn vqrshl_s64_(a: int64x1_t, b: int64x1_t) -> int64x1_t; + } +vqrshl_s64_(a, b) } -/// Insert vector element from another vector element +/// Signed saturating rounding shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vset_lane_p16(a: p16, b: poly16x4_t) -> poly16x4_t { - static_assert_imm2!(LANE); - simd_insert(b, LANE as u32, a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))] +pub unsafe fn vqrshlq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshifts.v2i64")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshl.v2i64")] + fn vqrshlq_s64_(a: int64x2_t, b: int64x2_t) -> int64x2_t; + } +vqrshlq_s64_(a, b) } -/// Insert vector element from another vector element -#[inline] -#[target_feature(enable = "neon,aes")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vset_lane_p64(a: p64, b: poly64x1_t) -> poly64x1_t { - static_assert!(LANE : i32 where LANE == 0); - simd_insert(b, LANE as u32, a) -} - -/// Insert vector element from another vector element +/// Unsigned signed saturating rounding shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vsetq_lane_s8(a: i8, b: int8x16_t) -> int8x16_t { - static_assert_imm4!(LANE); - simd_insert(b, LANE as u32, a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))] +pub unsafe fn vqrshl_u8(a: uint8x8_t, b: int8x8_t) -> uint8x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftu.v8i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqrshl.v8i8")] + fn vqrshl_u8_(a: uint8x8_t, b: int8x8_t) -> uint8x8_t; + } +vqrshl_u8_(a, b) } -/// Insert vector element from another vector element +/// Unsigned signed saturating rounding shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vsetq_lane_s16(a: i16, b: int16x8_t) -> int16x8_t { - static_assert_imm3!(LANE); - simd_insert(b, LANE as u32, a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))] +pub unsafe fn vqrshlq_u8(a: uint8x16_t, b: int8x16_t) -> uint8x16_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftu.v16i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqrshl.v16i8")] + fn vqrshlq_u8_(a: uint8x16_t, b: int8x16_t) -> uint8x16_t; + } +vqrshlq_u8_(a, b) } -/// Insert vector element from another vector element +/// Unsigned signed saturating rounding shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vsetq_lane_s32(a: i32, b: int32x4_t) -> int32x4_t { - static_assert_imm2!(LANE); - simd_insert(b, LANE as u32, a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))] +pub unsafe fn vqrshl_u16(a: uint16x4_t, b: int16x4_t) -> uint16x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftu.v4i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqrshl.v4i16")] + fn vqrshl_u16_(a: uint16x4_t, b: int16x4_t) -> uint16x4_t; + } +vqrshl_u16_(a, b) } -/// Insert vector element from another vector element +/// Unsigned signed saturating rounding shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vsetq_lane_s64(a: i64, b: int64x2_t) -> int64x2_t { - static_assert_imm1!(LANE); - simd_insert(b, LANE as u32, a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))] +pub unsafe fn vqrshlq_u16(a: uint16x8_t, b: int16x8_t) -> uint16x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftu.v8i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqrshl.v8i16")] + fn vqrshlq_u16_(a: uint16x8_t, b: int16x8_t) -> uint16x8_t; + } +vqrshlq_u16_(a, b) } -/// Insert vector element from another vector element +/// Unsigned signed saturating rounding shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vsetq_lane_u8(a: u8, b: uint8x16_t) -> uint8x16_t { - static_assert_imm4!(LANE); - simd_insert(b, LANE as u32, a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))] +pub unsafe fn vqrshl_u32(a: uint32x2_t, b: int32x2_t) -> uint32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftu.v2i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqrshl.v2i32")] + fn vqrshl_u32_(a: uint32x2_t, b: int32x2_t) -> uint32x2_t; + } +vqrshl_u32_(a, b) } -/// Insert vector element from another vector element +/// Unsigned signed saturating rounding shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vsetq_lane_u16(a: u16, b: uint16x8_t) -> uint16x8_t { - static_assert_imm3!(LANE); - simd_insert(b, LANE as u32, a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))] +pub unsafe fn vqrshlq_u32(a: uint32x4_t, b: int32x4_t) -> uint32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftu.v4i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqrshl.v4i32")] + fn vqrshlq_u32_(a: uint32x4_t, b: int32x4_t) -> uint32x4_t; + } +vqrshlq_u32_(a, b) } -/// Insert vector element from another vector element +/// Unsigned signed saturating rounding shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vsetq_lane_u32(a: u32, b: uint32x4_t) -> uint32x4_t { - static_assert_imm2!(LANE); - simd_insert(b, LANE as u32, a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))] +pub unsafe fn vqrshl_u64(a: uint64x1_t, b: int64x1_t) -> uint64x1_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftu.v1i64")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqrshl.v1i64")] + fn vqrshl_u64_(a: uint64x1_t, b: int64x1_t) -> uint64x1_t; + } +vqrshl_u64_(a, b) } -/// Insert vector element from another vector element +/// Unsigned signed saturating rounding shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vsetq_lane_u64(a: u64, b: uint64x2_t) -> uint64x2_t { - static_assert_imm1!(LANE); - simd_insert(b, LANE as u32, a) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))] +pub unsafe fn vqrshlq_u64(a: uint64x2_t, b: int64x2_t) -> uint64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftu.v2i64")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqrshl.v2i64")] + fn vqrshlq_u64_(a: uint64x2_t, b: int64x2_t) -> uint64x2_t; + } +vqrshlq_u64_(a, b) } -/// Insert vector element from another vector element +/// Signed saturating rounded shift right narrow #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vsetq_lane_p8(a: p8, b: poly8x16_t) -> poly8x16_t { - static_assert_imm4!(LANE); - simd_insert(b, LANE as u32, a) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqrshrn_n_s16(a: int16x8_t) -> int8x8_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftns.v8i8")] + fn vqrshrn_n_s16_(a: int16x8_t, n: int16x8_t) -> int8x8_t; + } +vqrshrn_n_s16_(a, int16x8_t(-N as i16, -N as i16, -N as i16, -N as i16, -N as i16, -N as i16, -N as i16, -N as i16)) } -/// Insert vector element from another vector element +/// Signed saturating rounded shift right narrow #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vsetq_lane_p16(a: p16, b: poly16x8_t) -> poly16x8_t { - static_assert_imm3!(LANE); - simd_insert(b, LANE as u32, a) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqrshrn_n_s16(a: int16x8_t) -> int8x8_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshrn.v8i8")] + fn vqrshrn_n_s16_(a: int16x8_t, n: i32) -> int8x8_t; + } +vqrshrn_n_s16_(a, N) } -/// Insert vector element from another vector element +/// Signed saturating rounded shift right narrow #[inline] -#[target_feature(enable = "neon,aes")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vsetq_lane_p64(a: p64, b: poly64x2_t) -> poly64x2_t { - static_assert_imm1!(LANE); - simd_insert(b, LANE as u32, a) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqrshrn_n_s32(a: int32x4_t) -> int16x4_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftns.v4i16")] + fn vqrshrn_n_s32_(a: int32x4_t, n: int32x4_t) -> int16x4_t; + } +vqrshrn_n_s32_(a, int32x4_t(-N as i32, -N as i32, -N as i32, -N as i32)) } -/// Insert vector element from another vector element +/// Signed saturating rounded shift right narrow #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vset_lane_f32(a: f32, b: float32x2_t) -> float32x2_t { - static_assert_imm1!(LANE); - simd_insert(b, LANE as u32, a) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqrshrn_n_s32(a: int32x4_t) -> int16x4_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshrn.v4i16")] + fn vqrshrn_n_s32_(a: int32x4_t, n: i32) -> int16x4_t; + } +vqrshrn_n_s32_(a, N) } -/// Insert vector element from another vector element +/// Signed saturating rounded shift right narrow +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqrshrn_n_s64(a: int64x2_t) -> int32x2_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftns.v2i32")] + fn vqrshrn_n_s64_(a: int64x2_t, n: int64x2_t) -> int32x2_t; + } +vqrshrn_n_s64_(a, int64x2_t(-N as i64, -N as i64)) +} + +/// Signed saturating rounded shift right narrow #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vsetq_lane_f32(a: f32, b: float32x4_t) -> float32x4_t { - static_assert_imm2!(LANE); - simd_insert(b, LANE as u32, a) -} - -/// Signed Shift left -#[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))] -pub unsafe fn vshl_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqrshrn_n_s64(a: int64x2_t) -> int32x2_t { + static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshifts.v8i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sshl.v8i8")] - fn vshl_s8_(a: int8x8_t, b: int8x8_t) -> int8x8_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshrn.v2i32")] + fn vqrshrn_n_s64_(a: int64x2_t, n: i32) -> int32x2_t; } -vshl_s8_(a, b) +vqrshrn_n_s64_(a, N) } -/// Signed Shift left +/// Unsigned signed saturating rounded shift right narrow #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))] -pub unsafe fn vshlq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqrshrn_n_u16(a: uint16x8_t) -> uint8x8_t { + static_assert!(N : i32 where N >= 1 && N <= 8); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshifts.v16i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sshl.v16i8")] - fn vshlq_s8_(a: int8x16_t, b: int8x16_t) -> int8x16_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftnu.v8i8")] + fn vqrshrn_n_u16_(a: uint16x8_t, n: uint16x8_t) -> uint8x8_t; } -vshlq_s8_(a, b) +vqrshrn_n_u16_(a, uint16x8_t(-N as u16, -N as u16, -N as u16, -N as u16, -N as u16, -N as u16, -N as u16, -N as u16)) } -/// Signed Shift left +/// Unsigned signed saturating rounded shift right narrow #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))] -pub unsafe fn vshl_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqrshrn_n_u16(a: uint16x8_t) -> uint8x8_t { + static_assert!(N : i32 where N >= 1 && N <= 8); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshifts.v4i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sshl.v4i16")] - fn vshl_s16_(a: int16x4_t, b: int16x4_t) -> int16x4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqrshrn.v8i8")] + fn vqrshrn_n_u16_(a: uint16x8_t, n: i32) -> uint8x8_t; } -vshl_s16_(a, b) +vqrshrn_n_u16_(a, N) } -/// Signed Shift left +/// Unsigned signed saturating rounded shift right narrow #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))] -pub unsafe fn vshlq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqrshrn_n_u32(a: uint32x4_t) -> uint16x4_t { + static_assert!(N : i32 where N >= 1 && N <= 16); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshifts.v8i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sshl.v8i16")] - fn vshlq_s16_(a: int16x8_t, b: int16x8_t) -> int16x8_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftnu.v4i16")] + fn vqrshrn_n_u32_(a: uint32x4_t, n: uint32x4_t) -> uint16x4_t; } -vshlq_s16_(a, b) +vqrshrn_n_u32_(a, uint32x4_t(-N as u32, -N as u32, -N as u32, -N as u32)) } -/// Signed Shift left +/// Unsigned signed saturating rounded shift right narrow #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))] -pub unsafe fn vshl_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqrshrn_n_u32(a: uint32x4_t) -> uint16x4_t { + static_assert!(N : i32 where N >= 1 && N <= 16); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshifts.v2i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sshl.v2i32")] - fn vshl_s32_(a: int32x2_t, b: int32x2_t) -> int32x2_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqrshrn.v4i16")] + fn vqrshrn_n_u32_(a: uint32x4_t, n: i32) -> uint16x4_t; } -vshl_s32_(a, b) +vqrshrn_n_u32_(a, N) } -/// Signed Shift left +/// Unsigned signed saturating rounded shift right narrow #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))] -pub unsafe fn vshlq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqrshrn_n_u64(a: uint64x2_t) -> uint32x2_t { + static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshifts.v4i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sshl.v4i32")] - fn vshlq_s32_(a: int32x4_t, b: int32x4_t) -> int32x4_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftnu.v2i32")] + fn vqrshrn_n_u64_(a: uint64x2_t, n: uint64x2_t) -> uint32x2_t; } -vshlq_s32_(a, b) +vqrshrn_n_u64_(a, uint64x2_t(-N as u64, -N as u64)) } -/// Signed Shift left +/// Unsigned signed saturating rounded shift right narrow #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))] -pub unsafe fn vshl_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqrshrn_n_u64(a: uint64x2_t) -> uint32x2_t { + static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshifts.v1i64")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sshl.v1i64")] - fn vshl_s64_(a: int64x1_t, b: int64x1_t) -> int64x1_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqrshrn.v2i32")] + fn vqrshrn_n_u64_(a: uint64x2_t, n: i32) -> uint32x2_t; } -vshl_s64_(a, b) +vqrshrn_n_u64_(a, N) } -/// Signed Shift left +/// Signed saturating rounded shift right unsigned narrow #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))] -pub unsafe fn vshlq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshrun, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqrshrun_n_s16(a: int16x8_t) -> uint8x8_t { + static_assert!(N : i32 where N >= 1 && N <= 8); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshifts.v2i64")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sshl.v2i64")] - fn vshlq_s64_(a: int64x2_t, b: int64x2_t) -> int64x2_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftnsu.v8i8")] + fn vqrshrun_n_s16_(a: int16x8_t, n: int16x8_t) -> uint8x8_t; } -vshlq_s64_(a, b) +vqrshrun_n_s16_(a, int16x8_t(-N as i16, -N as i16, -N as i16, -N as i16, -N as i16, -N as i16, -N as i16, -N as i16)) } -/// Unsigned Shift left +/// Signed saturating rounded shift right unsigned narrow #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))] -pub unsafe fn vshl_u8(a: uint8x8_t, b: int8x8_t) -> uint8x8_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshrun, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqrshrun_n_s16(a: int16x8_t) -> uint8x8_t { + static_assert!(N : i32 where N >= 1 && N <= 8); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshiftu.v8i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ushl.v8i8")] - fn vshl_u8_(a: uint8x8_t, b: int8x8_t) -> uint8x8_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshrun.v8i8")] + fn vqrshrun_n_s16_(a: int16x8_t, n: i32) -> uint8x8_t; } -vshl_u8_(a, b) +vqrshrun_n_s16_(a, N) } -/// Unsigned Shift left +/// Signed saturating rounded shift right unsigned narrow #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))] -pub unsafe fn vshlq_u8(a: uint8x16_t, b: int8x16_t) -> uint8x16_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshrun, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqrshrun_n_s32(a: int32x4_t) -> uint16x4_t { + static_assert!(N : i32 where N >= 1 && N <= 16); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshiftu.v16i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ushl.v16i8")] - fn vshlq_u8_(a: uint8x16_t, b: int8x16_t) -> uint8x16_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftnsu.v4i16")] + fn vqrshrun_n_s32_(a: int32x4_t, n: int32x4_t) -> uint16x4_t; } -vshlq_u8_(a, b) +vqrshrun_n_s32_(a, int32x4_t(-N as i32, -N as i32, -N as i32, -N as i32)) } -/// Unsigned Shift left +/// Signed saturating rounded shift right unsigned narrow #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))] -pub unsafe fn vshl_u16(a: uint16x4_t, b: int16x4_t) -> uint16x4_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshrun, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqrshrun_n_s32(a: int32x4_t) -> uint16x4_t { + static_assert!(N : i32 where N >= 1 && N <= 16); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshiftu.v4i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ushl.v4i16")] - fn vshl_u16_(a: uint16x4_t, b: int16x4_t) -> uint16x4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshrun.v4i16")] + fn vqrshrun_n_s32_(a: int32x4_t, n: i32) -> uint16x4_t; } -vshl_u16_(a, b) +vqrshrun_n_s32_(a, N) } -/// Unsigned Shift left +/// Signed saturating rounded shift right unsigned narrow #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))] -pub unsafe fn vshlq_u16(a: uint16x8_t, b: int16x8_t) -> uint16x8_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshrun, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqrshrun_n_s64(a: int64x2_t) -> uint32x2_t { + static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshiftu.v8i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ushl.v8i16")] - fn vshlq_u16_(a: uint16x8_t, b: int16x8_t) -> uint16x8_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqrshiftnsu.v2i32")] + fn vqrshrun_n_s64_(a: int64x2_t, n: int64x2_t) -> uint32x2_t; } -vshlq_u16_(a, b) +vqrshrun_n_s64_(a, int64x2_t(-N as i64, -N as i64)) } -/// Unsigned Shift left +/// Signed saturating rounded shift right unsigned narrow #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))] -pub unsafe fn vshl_u32(a: uint32x2_t, b: int32x2_t) -> uint32x2_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshrun, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqrshrun_n_s64(a: int64x2_t) -> uint32x2_t { + static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshiftu.v2i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ushl.v2i32")] - fn vshl_u32_(a: uint32x2_t, b: int32x2_t) -> uint32x2_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshrun.v2i32")] + fn vqrshrun_n_s64_(a: int64x2_t, n: i32) -> uint32x2_t; } -vshl_u32_(a, b) +vqrshrun_n_s64_(a, N) } -/// Unsigned Shift left +/// Signed saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))] -pub unsafe fn vshlq_u32(a: uint32x4_t, b: int32x4_t) -> uint32x4_t { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))] +pub unsafe fn vqshl_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshiftu.v4i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ushl.v4i32")] - fn vshlq_u32_(a: uint32x4_t, b: int32x4_t) -> uint32x4_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshifts.v8i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshl.v8i8")] + fn vqshl_s8_(a: int8x8_t, b: int8x8_t) -> int8x8_t; } -vshlq_u32_(a, b) +vqshl_s8_(a, b) } -/// Unsigned Shift left +/// Signed saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))] -pub unsafe fn vshl_u64(a: uint64x1_t, b: int64x1_t) -> uint64x1_t { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))] +pub unsafe fn vqshlq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshiftu.v1i64")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ushl.v1i64")] - fn vshl_u64_(a: uint64x1_t, b: int64x1_t) -> uint64x1_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshifts.v16i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshl.v16i8")] + fn vqshlq_s8_(a: int8x16_t, b: int8x16_t) -> int8x16_t; } -vshl_u64_(a, b) +vqshlq_s8_(a, b) } -/// Unsigned Shift left +/// Signed saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))] -pub unsafe fn vshlq_u64(a: uint64x2_t, b: int64x2_t) -> uint64x2_t { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))] +pub unsafe fn vqshl_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshiftu.v2i64")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ushl.v2i64")] - fn vshlq_u64_(a: uint64x2_t, b: int64x2_t) -> uint64x2_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshifts.v4i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshl.v4i16")] + fn vqshl_s16_(a: int16x4_t, b: int16x4_t) -> int16x4_t; } -vshlq_u64_(a, b) +vqshl_s16_(a, b) } -/// Shift left +/// Signed saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vshl_n_s8(a: int8x8_t) -> int8x8_t { - static_assert_imm3!(N); - simd_shl(a, vdup_n_s8(N.try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))] +pub unsafe fn vqshlq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshifts.v8i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshl.v8i16")] + fn vqshlq_s16_(a: int16x8_t, b: int16x8_t) -> int16x8_t; + } +vqshlq_s16_(a, b) } -/// Shift left +/// Signed saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vshlq_n_s8(a: int8x16_t) -> int8x16_t { - static_assert_imm3!(N); - simd_shl(a, vdupq_n_s8(N.try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))] +pub unsafe fn vqshl_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshifts.v2i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshl.v2i32")] + fn vqshl_s32_(a: int32x2_t, b: int32x2_t) -> int32x2_t; + } +vqshl_s32_(a, b) } -/// Shift left +/// Signed saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vshl_n_s16(a: int16x4_t) -> int16x4_t { - static_assert_imm4!(N); - simd_shl(a, vdup_n_s16(N.try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))] +pub unsafe fn vqshlq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshifts.v4i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshl.v4i32")] + fn vqshlq_s32_(a: int32x4_t, b: int32x4_t) -> int32x4_t; + } +vqshlq_s32_(a, b) } -/// Shift left +/// Signed saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vshlq_n_s16(a: int16x8_t) -> int16x8_t { - static_assert_imm4!(N); - simd_shl(a, vdupq_n_s16(N.try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))] +pub unsafe fn vqshl_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshifts.v1i64")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshl.v1i64")] + fn vqshl_s64_(a: int64x1_t, b: int64x1_t) -> int64x1_t; + } +vqshl_s64_(a, b) } -/// Shift left +/// Signed saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vshl_n_s32(a: int32x2_t) -> int32x2_t { - static_assert_imm5!(N); - simd_shl(a, vdup_n_s32(N.try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))] +pub unsafe fn vqshlq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshifts.v2i64")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshl.v2i64")] + fn vqshlq_s64_(a: int64x2_t, b: int64x2_t) -> int64x2_t; + } +vqshlq_s64_(a, b) } -/// Shift left +/// Unsigned saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vshlq_n_s32(a: int32x4_t) -> int32x4_t { - static_assert_imm5!(N); - simd_shl(a, vdupq_n_s32(N.try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))] +pub unsafe fn vqshl_u8(a: uint8x8_t, b: int8x8_t) -> uint8x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftu.v8i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqshl.v8i8")] + fn vqshl_u8_(a: uint8x8_t, b: int8x8_t) -> uint8x8_t; + } +vqshl_u8_(a, b) } -/// Shift left +/// Unsigned saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vshl_n_u8(a: uint8x8_t) -> uint8x8_t { - static_assert_imm3!(N); - simd_shl(a, vdup_n_u8(N.try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))] +pub unsafe fn vqshlq_u8(a: uint8x16_t, b: int8x16_t) -> uint8x16_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftu.v16i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqshl.v16i8")] + fn vqshlq_u8_(a: uint8x16_t, b: int8x16_t) -> uint8x16_t; + } +vqshlq_u8_(a, b) } -/// Shift left +/// Unsigned saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vshlq_n_u8(a: uint8x16_t) -> uint8x16_t { - static_assert_imm3!(N); - simd_shl(a, vdupq_n_u8(N.try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))] +pub unsafe fn vqshl_u16(a: uint16x4_t, b: int16x4_t) -> uint16x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftu.v4i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqshl.v4i16")] + fn vqshl_u16_(a: uint16x4_t, b: int16x4_t) -> uint16x4_t; + } +vqshl_u16_(a, b) } -/// Shift left +/// Unsigned saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vshl_n_u16(a: uint16x4_t) -> uint16x4_t { - static_assert_imm4!(N); - simd_shl(a, vdup_n_u16(N.try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))] +pub unsafe fn vqshlq_u16(a: uint16x8_t, b: int16x8_t) -> uint16x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftu.v8i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqshl.v8i16")] + fn vqshlq_u16_(a: uint16x8_t, b: int16x8_t) -> uint16x8_t; + } +vqshlq_u16_(a, b) } -/// Shift left +/// Unsigned saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vshlq_n_u16(a: uint16x8_t) -> uint16x8_t { - static_assert_imm4!(N); - simd_shl(a, vdupq_n_u16(N.try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))] +pub unsafe fn vqshl_u32(a: uint32x2_t, b: int32x2_t) -> uint32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftu.v2i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqshl.v2i32")] + fn vqshl_u32_(a: uint32x2_t, b: int32x2_t) -> uint32x2_t; + } +vqshl_u32_(a, b) } -/// Shift left +/// Unsigned saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vshl_n_u32(a: uint32x2_t) -> uint32x2_t { - static_assert_imm5!(N); - simd_shl(a, vdup_n_u32(N.try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))] +pub unsafe fn vqshlq_u32(a: uint32x4_t, b: int32x4_t) -> uint32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftu.v4i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqshl.v4i32")] + fn vqshlq_u32_(a: uint32x4_t, b: int32x4_t) -> uint32x4_t; + } +vqshlq_u32_(a, b) } -/// Shift left +/// Unsigned saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vshlq_n_u32(a: uint32x4_t) -> uint32x4_t { - static_assert_imm5!(N); - simd_shl(a, vdupq_n_u32(N.try_into().unwrap())) -} - -/// Shift left -#[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vshl_n_s64(a: int64x1_t) -> int64x1_t { - static_assert_imm6!(N); - simd_shl(a, vdup_n_s64(N.try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))] +pub unsafe fn vqshl_u64(a: uint64x1_t, b: int64x1_t) -> uint64x1_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftu.v1i64")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqshl.v1i64")] + fn vqshl_u64_(a: uint64x1_t, b: int64x1_t) -> uint64x1_t; + } +vqshl_u64_(a, b) } -/// Shift left +/// Unsigned saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] -#[rustc_legacy_const_generics(1)] -pub unsafe fn vshlq_n_s64(a: int64x2_t) -> int64x2_t { - static_assert_imm6!(N); - simd_shl(a, vdupq_n_s64(N.try_into().unwrap())) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))] +pub unsafe fn vqshlq_u64(a: uint64x2_t, b: int64x2_t) -> uint64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftu.v2i64")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqshl.v2i64")] + fn vqshlq_u64_(a: uint64x2_t, b: int64x2_t) -> uint64x2_t; + } +vqshlq_u64_(a, b) } -/// Shift left +/// Signed saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))] #[rustc_legacy_const_generics(1)] -pub unsafe fn vshl_n_u64(a: uint64x1_t) -> uint64x1_t { - static_assert_imm6!(N); - simd_shl(a, vdup_n_u64(N.try_into().unwrap())) +pub unsafe fn vqshl_n_s8(a: int8x8_t) -> int8x8_t { + static_assert_imm3!(N); + vqshl_s8(a, vdup_n_s8(N.try_into().unwrap())) } -/// Shift left +/// Signed saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))] #[rustc_legacy_const_generics(1)] -pub unsafe fn vshlq_n_u64(a: uint64x2_t) -> uint64x2_t { - static_assert_imm6!(N); - simd_shl(a, vdupq_n_u64(N.try_into().unwrap())) +pub unsafe fn vqshlq_n_s8(a: int8x16_t) -> int8x16_t { + static_assert_imm3!(N); + vqshlq_s8(a, vdupq_n_s8(N.try_into().unwrap())) } -/// Signed shift left long +/// Signed saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshll.s8", N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshll, N = 2))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))] #[rustc_legacy_const_generics(1)] -pub unsafe fn vshll_n_s8(a: int8x8_t) -> int16x8_t { - static_assert!(N : i32 where N >= 0 && N <= 8); - simd_shl(simd_cast(a), vdupq_n_s16(N.try_into().unwrap())) +pub unsafe fn vqshl_n_s16(a: int16x4_t) -> int16x4_t { + static_assert_imm4!(N); + vqshl_s16(a, vdup_n_s16(N.try_into().unwrap())) } -/// Signed shift left long +/// Signed saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshll.s16", N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshll, N = 2))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))] #[rustc_legacy_const_generics(1)] -pub unsafe fn vshll_n_s16(a: int16x4_t) -> int32x4_t { - static_assert!(N : i32 where N >= 0 && N <= 16); - simd_shl(simd_cast(a), vdupq_n_s32(N.try_into().unwrap())) +pub unsafe fn vqshlq_n_s16(a: int16x8_t) -> int16x8_t { + static_assert_imm4!(N); + vqshlq_s16(a, vdupq_n_s16(N.try_into().unwrap())) } -/// Signed shift left long +/// Signed saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshll.s32", N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshll, N = 2))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))] #[rustc_legacy_const_generics(1)] -pub unsafe fn vshll_n_s32(a: int32x2_t) -> int64x2_t { - static_assert!(N : i32 where N >= 0 && N <= 32); - simd_shl(simd_cast(a), vdupq_n_s64(N.try_into().unwrap())) +pub unsafe fn vqshl_n_s32(a: int32x2_t) -> int32x2_t { + static_assert_imm5!(N); + vqshl_s32(a, vdup_n_s32(N.try_into().unwrap())) } -/// Signed shift left long +/// Signed saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshll.u8", N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushll, N = 2))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))] #[rustc_legacy_const_generics(1)] -pub unsafe fn vshll_n_u8(a: uint8x8_t) -> uint16x8_t { - static_assert!(N : i32 where N >= 0 && N <= 8); - simd_shl(simd_cast(a), vdupq_n_u16(N.try_into().unwrap())) +pub unsafe fn vqshlq_n_s32(a: int32x4_t) -> int32x4_t { + static_assert_imm5!(N); + vqshlq_s32(a, vdupq_n_s32(N.try_into().unwrap())) } -/// Signed shift left long +/// Signed saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshll.u16", N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushll, N = 2))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))] #[rustc_legacy_const_generics(1)] -pub unsafe fn vshll_n_u16(a: uint16x4_t) -> uint32x4_t { - static_assert!(N : i32 where N >= 0 && N <= 16); - simd_shl(simd_cast(a), vdupq_n_u32(N.try_into().unwrap())) +pub unsafe fn vqshl_n_s64(a: int64x1_t) -> int64x1_t { + static_assert_imm6!(N); + vqshl_s64(a, vdup_n_s64(N.try_into().unwrap())) } -/// Signed shift left long +/// Signed saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshll.u32", N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushll, N = 2))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))] #[rustc_legacy_const_generics(1)] -pub unsafe fn vshll_n_u32(a: uint32x2_t) -> uint64x2_t { - static_assert!(N : i32 where N >= 0 && N <= 32); - simd_shl(simd_cast(a), vdupq_n_u64(N.try_into().unwrap())) +pub unsafe fn vqshlq_n_s64(a: int64x2_t) -> int64x2_t { + static_assert_imm6!(N); + vqshlq_s64(a, vdupq_n_s64(N.try_into().unwrap())) } -/// Shift right +/// Unsigned saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s8", N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))] #[rustc_legacy_const_generics(1)] -pub unsafe fn vshr_n_s8(a: int8x8_t) -> int8x8_t { - static_assert!(N : i32 where N >= 1 && N <= 8); - simd_shr(a, vdup_n_s8(N.try_into().unwrap())) +pub unsafe fn vqshl_n_u8(a: uint8x8_t) -> uint8x8_t { + static_assert_imm3!(N); + vqshl_u8(a, vdup_n_s8(N.try_into().unwrap())) } -/// Shift right +/// Unsigned saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s8", N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))] #[rustc_legacy_const_generics(1)] -pub unsafe fn vshrq_n_s8(a: int8x16_t) -> int8x16_t { - static_assert!(N : i32 where N >= 1 && N <= 8); - simd_shr(a, vdupq_n_s8(N.try_into().unwrap())) +pub unsafe fn vqshlq_n_u8(a: uint8x16_t) -> uint8x16_t { + static_assert_imm3!(N); + vqshlq_u8(a, vdupq_n_s8(N.try_into().unwrap())) } -/// Shift right +/// Unsigned saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s16", N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))] #[rustc_legacy_const_generics(1)] -pub unsafe fn vshr_n_s16(a: int16x4_t) -> int16x4_t { - static_assert!(N : i32 where N >= 1 && N <= 16); - simd_shr(a, vdup_n_s16(N.try_into().unwrap())) +pub unsafe fn vqshl_n_u16(a: uint16x4_t) -> uint16x4_t { + static_assert_imm4!(N); + vqshl_u16(a, vdup_n_s16(N.try_into().unwrap())) } -/// Shift right +/// Unsigned saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s16", N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))] #[rustc_legacy_const_generics(1)] -pub unsafe fn vshrq_n_s16(a: int16x8_t) -> int16x8_t { - static_assert!(N : i32 where N >= 1 && N <= 16); - simd_shr(a, vdupq_n_s16(N.try_into().unwrap())) +pub unsafe fn vqshlq_n_u16(a: uint16x8_t) -> uint16x8_t { + static_assert_imm4!(N); + vqshlq_u16(a, vdupq_n_s16(N.try_into().unwrap())) } -/// Shift right +/// Unsigned saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s32", N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))] #[rustc_legacy_const_generics(1)] -pub unsafe fn vshr_n_s32(a: int32x2_t) -> int32x2_t { - static_assert!(N : i32 where N >= 1 && N <= 32); - simd_shr(a, vdup_n_s32(N.try_into().unwrap())) +pub unsafe fn vqshl_n_u32(a: uint32x2_t) -> uint32x2_t { + static_assert_imm5!(N); + vqshl_u32(a, vdup_n_s32(N.try_into().unwrap())) } -/// Shift right +/// Unsigned saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s32", N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))] #[rustc_legacy_const_generics(1)] -pub unsafe fn vshrq_n_s32(a: int32x4_t) -> int32x4_t { - static_assert!(N : i32 where N >= 1 && N <= 32); - simd_shr(a, vdupq_n_s32(N.try_into().unwrap())) +pub unsafe fn vqshlq_n_u32(a: uint32x4_t) -> uint32x4_t { + static_assert_imm5!(N); + vqshlq_u32(a, vdupq_n_s32(N.try_into().unwrap())) } -/// Shift right +/// Unsigned saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s64", N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))] #[rustc_legacy_const_generics(1)] -pub unsafe fn vshr_n_s64(a: int64x1_t) -> int64x1_t { - static_assert!(N : i32 where N >= 1 && N <= 64); - simd_shr(a, vdup_n_s64(N.try_into().unwrap())) +pub unsafe fn vqshl_n_u64(a: uint64x1_t) -> uint64x1_t { + static_assert_imm6!(N); + vqshl_u64(a, vdup_n_s64(N.try_into().unwrap())) } -/// Shift right +/// Unsigned saturating shift left #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s64", N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))] #[rustc_legacy_const_generics(1)] -pub unsafe fn vshrq_n_s64(a: int64x2_t) -> int64x2_t { - static_assert!(N : i32 where N >= 1 && N <= 64); - simd_shr(a, vdupq_n_s64(N.try_into().unwrap())) +pub unsafe fn vqshlq_n_u64(a: uint64x2_t) -> uint64x2_t { + static_assert_imm6!(N); + vqshlq_u64(a, vdupq_n_s64(N.try_into().unwrap())) } -/// Shift right +/// Signed saturating shift left unsigned #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u8", N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshlu, N = 2))] #[rustc_legacy_const_generics(1)] -pub unsafe fn vshr_n_u8(a: uint8x8_t) -> uint8x8_t { - static_assert!(N : i32 where N >= 1 && N <= 8); - simd_shr(a, vdup_n_u8(N.try_into().unwrap())) +pub unsafe fn vqshlu_n_s8(a: int8x8_t) -> uint8x8_t { + static_assert_imm3!(N); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftsu.v8i8")] + fn vqshlu_n_s8_(a: int8x8_t, n: int8x8_t) -> uint8x8_t; + } +vqshlu_n_s8_(a, int8x8_t(N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8)) } -/// Shift right +/// Signed saturating shift left unsigned #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u8", N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshlu, N = 2))] #[rustc_legacy_const_generics(1)] -pub unsafe fn vshrq_n_u8(a: uint8x16_t) -> uint8x16_t { - static_assert!(N : i32 where N >= 1 && N <= 8); - simd_shr(a, vdupq_n_u8(N.try_into().unwrap())) +pub unsafe fn vqshlu_n_s8(a: int8x8_t) -> uint8x8_t { + static_assert_imm3!(N); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshlu.v8i8")] + fn vqshlu_n_s8_(a: int8x8_t, n: int8x8_t) -> uint8x8_t; + } +vqshlu_n_s8_(a, int8x8_t(N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8)) } -/// Shift right +/// Signed saturating shift left unsigned #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u16", N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshlu, N = 2))] #[rustc_legacy_const_generics(1)] -pub unsafe fn vshr_n_u16(a: uint16x4_t) -> uint16x4_t { - static_assert!(N : i32 where N >= 1 && N <= 16); - simd_shr(a, vdup_n_u16(N.try_into().unwrap())) +pub unsafe fn vqshlu_n_s16(a: int16x4_t) -> uint16x4_t { + static_assert_imm4!(N); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftsu.v4i16")] + fn vqshlu_n_s16_(a: int16x4_t, n: int16x4_t) -> uint16x4_t; + } +vqshlu_n_s16_(a, int16x4_t(N as i16, N as i16, N as i16, N as i16)) } -/// Shift right +/// Signed saturating shift left unsigned #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u16", N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshlu, N = 2))] #[rustc_legacy_const_generics(1)] -pub unsafe fn vshrq_n_u16(a: uint16x8_t) -> uint16x8_t { - static_assert!(N : i32 where N >= 1 && N <= 16); - simd_shr(a, vdupq_n_u16(N.try_into().unwrap())) +pub unsafe fn vqshlu_n_s16(a: int16x4_t) -> uint16x4_t { + static_assert_imm4!(N); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshlu.v4i16")] + fn vqshlu_n_s16_(a: int16x4_t, n: int16x4_t) -> uint16x4_t; + } +vqshlu_n_s16_(a, int16x4_t(N as i16, N as i16, N as i16, N as i16)) } -/// Shift right +/// Signed saturating shift left unsigned #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u32", N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshlu, N = 2))] #[rustc_legacy_const_generics(1)] -pub unsafe fn vshr_n_u32(a: uint32x2_t) -> uint32x2_t { - static_assert!(N : i32 where N >= 1 && N <= 32); - simd_shr(a, vdup_n_u32(N.try_into().unwrap())) +pub unsafe fn vqshlu_n_s32(a: int32x2_t) -> uint32x2_t { + static_assert_imm5!(N); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftsu.v2i32")] + fn vqshlu_n_s32_(a: int32x2_t, n: int32x2_t) -> uint32x2_t; + } +vqshlu_n_s32_(a, int32x2_t(N as i32, N as i32)) } -/// Shift right +/// Signed saturating shift left unsigned #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u32", N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshlu, N = 2))] #[rustc_legacy_const_generics(1)] -pub unsafe fn vshrq_n_u32(a: uint32x4_t) -> uint32x4_t { - static_assert!(N : i32 where N >= 1 && N <= 32); - simd_shr(a, vdupq_n_u32(N.try_into().unwrap())) +pub unsafe fn vqshlu_n_s32(a: int32x2_t) -> uint32x2_t { + static_assert_imm5!(N); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshlu.v2i32")] + fn vqshlu_n_s32_(a: int32x2_t, n: int32x2_t) -> uint32x2_t; + } +vqshlu_n_s32_(a, int32x2_t(N as i32, N as i32)) } -/// Shift right +/// Signed saturating shift left unsigned #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u64", N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshlu, N = 2))] #[rustc_legacy_const_generics(1)] -pub unsafe fn vshr_n_u64(a: uint64x1_t) -> uint64x1_t { - static_assert!(N : i32 where N >= 1 && N <= 64); - simd_shr(a, vdup_n_u64(N.try_into().unwrap())) +pub unsafe fn vqshlu_n_s64(a: int64x1_t) -> uint64x1_t { + static_assert_imm6!(N); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftsu.v1i64")] + fn vqshlu_n_s64_(a: int64x1_t, n: int64x1_t) -> uint64x1_t; + } +vqshlu_n_s64_(a, int64x1_t(N as i64)) } -/// Shift right +/// Signed saturating shift left unsigned #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u64", N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshlu, N = 2))] #[rustc_legacy_const_generics(1)] -pub unsafe fn vshrq_n_u64(a: uint64x2_t) -> uint64x2_t { - static_assert!(N : i32 where N >= 1 && N <= 64); - simd_shr(a, vdupq_n_u64(N.try_into().unwrap())) +pub unsafe fn vqshlu_n_s64(a: int64x1_t) -> uint64x1_t { + static_assert_imm6!(N); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshlu.v1i64")] + fn vqshlu_n_s64_(a: int64x1_t, n: int64x1_t) -> uint64x1_t; + } +vqshlu_n_s64_(a, int64x1_t(N as i64)) } -/// Shift right narrow +/// Signed saturating shift left unsigned #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshrn.i16", N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shrn, N = 2))] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshlu, N = 2))] #[rustc_legacy_const_generics(1)] -pub unsafe fn vshrn_n_s16(a: int16x8_t) -> int8x8_t { - static_assert!(N : i32 where N >= 1 && N <= 8); - simd_cast(simd_shr(a, vdupq_n_s16(N.try_into().unwrap()))) +pub unsafe fn vqshluq_n_s8(a: int8x16_t) -> uint8x16_t { + static_assert_imm3!(N); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftsu.v16i8")] + fn vqshluq_n_s8_(a: int8x16_t, n: int8x16_t) -> uint8x16_t; + } +vqshluq_n_s8_(a, int8x16_t(N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8)) } -/// Shift right narrow +/// Signed saturating shift left unsigned #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshrn.i32", N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shrn, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshlu, N = 2))] #[rustc_legacy_const_generics(1)] -pub unsafe fn vshrn_n_s32(a: int32x4_t) -> int16x4_t { - static_assert!(N : i32 where N >= 1 && N <= 16); - simd_cast(simd_shr(a, vdupq_n_s32(N.try_into().unwrap()))) +pub unsafe fn vqshluq_n_s8(a: int8x16_t) -> uint8x16_t { + static_assert_imm3!(N); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshlu.v16i8")] + fn vqshluq_n_s8_(a: int8x16_t, n: int8x16_t) -> uint8x16_t; + } +vqshluq_n_s8_(a, int8x16_t(N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8)) } -/// Shift right narrow +/// Signed saturating shift left unsigned #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshrn.i64", N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shrn, N = 2))] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshlu, N = 2))] #[rustc_legacy_const_generics(1)] -pub unsafe fn vshrn_n_s64(a: int64x2_t) -> int32x2_t { - static_assert!(N : i32 where N >= 1 && N <= 32); - simd_cast(simd_shr(a, vdupq_n_s64(N.try_into().unwrap()))) +pub unsafe fn vqshluq_n_s16(a: int16x8_t) -> uint16x8_t { + static_assert_imm4!(N); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftsu.v8i16")] + fn vqshluq_n_s16_(a: int16x8_t, n: int16x8_t) -> uint16x8_t; + } +vqshluq_n_s16_(a, int16x8_t(N as i16, N as i16, N as i16, N as i16, N as i16, N as i16, N as i16, N as i16)) } -/// Shift right narrow +/// Signed saturating shift left unsigned #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshrn.i16", N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shrn, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshlu, N = 2))] #[rustc_legacy_const_generics(1)] -pub unsafe fn vshrn_n_u16(a: uint16x8_t) -> uint8x8_t { - static_assert!(N : i32 where N >= 1 && N <= 8); - simd_cast(simd_shr(a, vdupq_n_u16(N.try_into().unwrap()))) +pub unsafe fn vqshluq_n_s16(a: int16x8_t) -> uint16x8_t { + static_assert_imm4!(N); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshlu.v8i16")] + fn vqshluq_n_s16_(a: int16x8_t, n: int16x8_t) -> uint16x8_t; + } +vqshluq_n_s16_(a, int16x8_t(N as i16, N as i16, N as i16, N as i16, N as i16, N as i16, N as i16, N as i16)) } -/// Shift right narrow +/// Signed saturating shift left unsigned #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshrn.i32", N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shrn, N = 2))] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshlu, N = 2))] #[rustc_legacy_const_generics(1)] -pub unsafe fn vshrn_n_u32(a: uint32x4_t) -> uint16x4_t { - static_assert!(N : i32 where N >= 1 && N <= 16); - simd_cast(simd_shr(a, vdupq_n_u32(N.try_into().unwrap()))) +pub unsafe fn vqshluq_n_s32(a: int32x4_t) -> uint32x4_t { + static_assert_imm5!(N); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftsu.v4i32")] + fn vqshluq_n_s32_(a: int32x4_t, n: int32x4_t) -> uint32x4_t; + } +vqshluq_n_s32_(a, int32x4_t(N as i32, N as i32, N as i32, N as i32)) } -/// Shift right narrow +/// Signed saturating shift left unsigned #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshrn.i64", N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shrn, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshlu, N = 2))] #[rustc_legacy_const_generics(1)] -pub unsafe fn vshrn_n_u64(a: uint64x2_t) -> uint32x2_t { - static_assert!(N : i32 where N >= 1 && N <= 32); - simd_cast(simd_shr(a, vdupq_n_u64(N.try_into().unwrap()))) +pub unsafe fn vqshluq_n_s32(a: int32x4_t) -> uint32x4_t { + static_assert_imm5!(N); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshlu.v4i32")] + fn vqshluq_n_s32_(a: int32x4_t, n: int32x4_t) -> uint32x4_t; + } +vqshluq_n_s32_(a, int32x4_t(N as i32, N as i32, N as i32, N as i32)) } -/// Signed shift right and accumulate +/// Signed saturating shift left unsigned +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshlu, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshluq_n_s64(a: int64x2_t) -> uint64x2_t { + static_assert_imm6!(N); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftsu.v2i64")] + fn vqshluq_n_s64_(a: int64x2_t, n: int64x2_t) -> uint64x2_t; + } +vqshluq_n_s64_(a, int64x2_t(N as i64, N as i64)) +} + +/// Signed saturating shift left unsigned #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vsra_n_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshlu, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshluq_n_s64(a: int64x2_t) -> uint64x2_t { + static_assert_imm6!(N); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshlu.v2i64")] + fn vqshluq_n_s64_(a: int64x2_t, n: int64x2_t) -> uint64x2_t; + } +vqshluq_n_s64_(a, int64x2_t(N as i64, N as i64)) +} + +/// Signed saturating shift right narrow +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshrn_n_s16(a: int16x8_t) -> int8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); - simd_add(a, vshr_n_s8::(b)) + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftns.v8i8")] + fn vqshrn_n_s16_(a: int16x8_t, n: int16x8_t) -> int8x8_t; + } +vqshrn_n_s16_(a, int16x8_t(-N as i16, -N as i16, -N as i16, -N as i16, -N as i16, -N as i16, -N as i16, -N as i16)) } -/// Signed shift right and accumulate +/// Signed saturating shift right narrow #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vsraq_n_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshrn_n_s16(a: int16x8_t) -> int8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); - simd_add(a, vshrq_n_s8::(b)) + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshrn.v8i8")] + fn vqshrn_n_s16_(a: int16x8_t, n: i32) -> int8x8_t; + } +vqshrn_n_s16_(a, N) } -/// Signed shift right and accumulate +/// Signed saturating shift right narrow #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vsra_n_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshrn_n_s32(a: int32x4_t) -> int16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); - simd_add(a, vshr_n_s16::(b)) + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftns.v4i16")] + fn vqshrn_n_s32_(a: int32x4_t, n: int32x4_t) -> int16x4_t; + } +vqshrn_n_s32_(a, int32x4_t(-N as i32, -N as i32, -N as i32, -N as i32)) } -/// Signed shift right and accumulate +/// Signed saturating shift right narrow #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vsraq_n_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshrn_n_s32(a: int32x4_t) -> int16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); - simd_add(a, vshrq_n_s16::(b)) + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshrn.v4i16")] + fn vqshrn_n_s32_(a: int32x4_t, n: i32) -> int16x4_t; + } +vqshrn_n_s32_(a, N) } -/// Signed shift right and accumulate +/// Signed saturating shift right narrow #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vsra_n_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshrn_n_s64(a: int64x2_t) -> int32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); - simd_add(a, vshr_n_s32::(b)) + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftns.v2i32")] + fn vqshrn_n_s64_(a: int64x2_t, n: int64x2_t) -> int32x2_t; + } +vqshrn_n_s64_(a, int64x2_t(-N as i64, -N as i64)) } -/// Signed shift right and accumulate +/// Signed saturating shift right narrow #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vsraq_n_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshrn_n_s64(a: int64x2_t) -> int32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); - simd_add(a, vshrq_n_s32::(b)) -} - -/// Signed shift right and accumulate -#[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vsra_n_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { - static_assert!(N : i32 where N >= 1 && N <= 64); - simd_add(a, vshr_n_s64::(b)) -} - -/// Signed shift right and accumulate -#[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vsraq_n_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { - static_assert!(N : i32 where N >= 1 && N <= 64); - simd_add(a, vshrq_n_s64::(b)) + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshrn.v2i32")] + fn vqshrn_n_s64_(a: int64x2_t, n: i32) -> int32x2_t; + } +vqshrn_n_s64_(a, N) } -/// Unsigned shift right and accumulate +/// Unsigned saturating shift right narrow #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vsra_n_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshrn_n_u16(a: uint16x8_t) -> uint8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); - simd_add(a, vshr_n_u8::(b)) + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftnu.v8i8")] + fn vqshrn_n_u16_(a: uint16x8_t, n: uint16x8_t) -> uint8x8_t; + } +vqshrn_n_u16_(a, uint16x8_t(-N as u16, -N as u16, -N as u16, -N as u16, -N as u16, -N as u16, -N as u16, -N as u16)) } -/// Unsigned shift right and accumulate +/// Unsigned saturating shift right narrow #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vsraq_n_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshrn_n_u16(a: uint16x8_t) -> uint8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); - simd_add(a, vshrq_n_u8::(b)) + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqshrn.v8i8")] + fn vqshrn_n_u16_(a: uint16x8_t, n: i32) -> uint8x8_t; + } +vqshrn_n_u16_(a, N) } -/// Unsigned shift right and accumulate +/// Unsigned saturating shift right narrow #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vsra_n_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshrn_n_u32(a: uint32x4_t) -> uint16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); - simd_add(a, vshr_n_u16::(b)) + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftnu.v4i16")] + fn vqshrn_n_u32_(a: uint32x4_t, n: uint32x4_t) -> uint16x4_t; + } +vqshrn_n_u32_(a, uint32x4_t(-N as u32, -N as u32, -N as u32, -N as u32)) } -/// Unsigned shift right and accumulate +/// Unsigned saturating shift right narrow #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vsraq_n_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshrn_n_u32(a: uint32x4_t) -> uint16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); - simd_add(a, vshrq_n_u16::(b)) + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqshrn.v4i16")] + fn vqshrn_n_u32_(a: uint32x4_t, n: i32) -> uint16x4_t; + } +vqshrn_n_u32_(a, N) } -/// Unsigned shift right and accumulate +/// Unsigned saturating shift right narrow #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vsra_n_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshrn_n_u64(a: uint64x2_t) -> uint32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); - simd_add(a, vshr_n_u32::(b)) + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftnu.v2i32")] + fn vqshrn_n_u64_(a: uint64x2_t, n: uint64x2_t) -> uint32x2_t; + } +vqshrn_n_u64_(a, uint64x2_t(-N as u64, -N as u64)) } -/// Unsigned shift right and accumulate +/// Unsigned saturating shift right narrow #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vsraq_n_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshrn_n_u64(a: uint64x2_t) -> uint32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); - simd_add(a, vshrq_n_u32::(b)) + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqshrn.v2i32")] + fn vqshrn_n_u64_(a: uint64x2_t, n: i32) -> uint32x2_t; + } +vqshrn_n_u64_(a, N) } -/// Unsigned shift right and accumulate +/// Signed saturating shift right unsigned narrow #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vsra_n_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { - static_assert!(N : i32 where N >= 1 && N <= 64); - simd_add(a, vshr_n_u64::(b)) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshrun, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshrun_n_s16(a: int16x8_t) -> uint8x8_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftnsu.v8i8")] + fn vqshrun_n_s16_(a: int16x8_t, n: int16x8_t) -> uint8x8_t; + } +vqshrun_n_s16_(a, int16x8_t(-N as i16, -N as i16, -N as i16, -N as i16, -N as i16, -N as i16, -N as i16, -N as i16)) } -/// Unsigned shift right and accumulate +/// Signed saturating shift right unsigned narrow #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))] -#[rustc_legacy_const_generics(2)] -pub unsafe fn vsraq_n_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { - static_assert!(N : i32 where N >= 1 && N <= 64); - simd_add(a, vshrq_n_u64::(b)) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshrun, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshrun_n_s16(a: int16x8_t) -> uint8x8_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshrun.v8i8")] + fn vqshrun_n_s16_(a: int16x8_t, n: i32) -> uint8x8_t; + } +vqshrun_n_s16_(a, N) } -/// Unsigned Absolute difference and Accumulate Long +/// Signed saturating shift right unsigned narrow #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabal.u8"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabal))] -pub unsafe fn vabal_u8(a: uint16x8_t, b: uint8x8_t, c: uint8x8_t) -> uint16x8_t { - let d: uint8x8_t = vabd_u8(b, c); - simd_add(a, simd_cast(d)) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshrun, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshrun_n_s32(a: int32x4_t) -> uint16x4_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftnsu.v4i16")] + fn vqshrun_n_s32_(a: int32x4_t, n: int32x4_t) -> uint16x4_t; + } +vqshrun_n_s32_(a, int32x4_t(-N as i32, -N as i32, -N as i32, -N as i32)) } -/// Unsigned Absolute difference and Accumulate Long +/// Signed saturating shift right unsigned narrow #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabal.u16"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabal))] -pub unsafe fn vabal_u16(a: uint32x4_t, b: uint16x4_t, c: uint16x4_t) -> uint32x4_t { - let d: uint16x4_t = vabd_u16(b, c); - simd_add(a, simd_cast(d)) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshrun, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshrun_n_s32(a: int32x4_t) -> uint16x4_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshrun.v4i16")] + fn vqshrun_n_s32_(a: int32x4_t, n: i32) -> uint16x4_t; + } +vqshrun_n_s32_(a, N) } -/// Unsigned Absolute difference and Accumulate Long +/// Signed saturating shift right unsigned narrow #[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabal.u32"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabal))] -pub unsafe fn vabal_u32(a: uint64x2_t, b: uint32x2_t, c: uint32x2_t) -> uint64x2_t { - let d: uint32x2_t = vabd_u32(b, c); - simd_add(a, simd_cast(d)) +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshrun, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshrun_n_s64(a: int64x2_t) -> uint32x2_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftnsu.v2i32")] + fn vqshrun_n_s64_(a: int64x2_t, n: int64x2_t) -> uint32x2_t; + } +vqshrun_n_s64_(a, int64x2_t(-N as i64, -N as i64)) } -/// Signed Absolute difference and Accumulate Long +/// Signed saturating shift right unsigned narrow #[inline] +#[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabal.s8"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabal))] -pub unsafe fn vabal_s8(a: int16x8_t, b: int8x8_t, c: int8x8_t) -> int16x8_t { - let d: int8x8_t = vabd_s8(b, c); - let e: uint8x8_t = simd_cast(d); - simd_add(a, simd_cast(e)) +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshrun, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vqshrun_n_s64(a: int64x2_t) -> uint32x2_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshrun.v2i32")] + fn vqshrun_n_s64_(a: int64x2_t, n: i32) -> uint32x2_t; + } +vqshrun_n_s64_(a, N) } -/// Signed Absolute difference and Accumulate Long +/// Reciprocal square-root estimate. #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabal.s16"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabal))] -pub unsafe fn vabal_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t { - let d: int16x4_t = vabd_s16(b, c); - let e: uint16x4_t = simd_cast(d); - simd_add(a, simd_cast(e)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsqrte))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frsqrte))] +pub unsafe fn vrsqrte_f32(a: float32x2_t) -> float32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrsqrte.v2f32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frsqrte.v2f32")] + fn vrsqrte_f32_(a: float32x2_t) -> float32x2_t; + } +vrsqrte_f32_(a) } -/// Signed Absolute difference and Accumulate Long +/// Reciprocal square-root estimate. #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabal.s32"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabal))] -pub unsafe fn vabal_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t { - let d: int32x2_t = vabd_s32(b, c); - let e: uint32x2_t = simd_cast(d); - simd_add(a, simd_cast(e)) +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsqrte))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frsqrte))] +pub unsafe fn vrsqrteq_f32(a: float32x4_t) -> float32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrsqrte.v4f32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frsqrte.v4f32")] + fn vrsqrteq_f32_(a: float32x4_t) -> float32x4_t; + } +vrsqrteq_f32_(a) } -/// Singned saturating Absolute value +/// Unsigned reciprocal square root estimate #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqabs.s8"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqabs))] -pub unsafe fn vqabs_s8(a: int8x8_t) -> int8x8_t { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsqrte))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursqrte))] +pub unsafe fn vrsqrte_u32(a: uint32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqabs.v8i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqabs.v8i8")] - fn vqabs_s8_(a: int8x8_t) -> int8x8_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrsqrte.v2i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ursqrte.v2i32")] + fn vrsqrte_u32_(a: uint32x2_t) -> uint32x2_t; } -vqabs_s8_(a) +vrsqrte_u32_(a) } -/// Singned saturating Absolute value +/// Unsigned reciprocal square root estimate #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqabs.s8"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqabs))] -pub unsafe fn vqabsq_s8(a: int8x16_t) -> int8x16_t { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsqrte))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursqrte))] +pub unsafe fn vrsqrteq_u32(a: uint32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqabs.v16i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqabs.v16i8")] - fn vqabsq_s8_(a: int8x16_t) -> int8x16_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrsqrte.v4i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ursqrte.v4i32")] + fn vrsqrteq_u32_(a: uint32x4_t) -> uint32x4_t; } -vqabsq_s8_(a) +vrsqrteq_u32_(a) } -/// Singned saturating Absolute value +/// Floating-point reciprocal square root step #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqabs.s16"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqabs))] -pub unsafe fn vqabs_s16(a: int16x4_t) -> int16x4_t { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsqrts))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frsqrts))] +pub unsafe fn vrsqrts_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqabs.v4i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqabs.v4i16")] - fn vqabs_s16_(a: int16x4_t) -> int16x4_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrsqrts.v2f32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frsqrts.v2f32")] + fn vrsqrts_f32_(a: float32x2_t, b: float32x2_t) -> float32x2_t; } -vqabs_s16_(a) +vrsqrts_f32_(a, b) } -/// Singned saturating Absolute value +/// Floating-point reciprocal square root step #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqabs.s16"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqabs))] -pub unsafe fn vqabsq_s16(a: int16x8_t) -> int16x8_t { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsqrts))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frsqrts))] +pub unsafe fn vrsqrtsq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqabs.v8i16")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqabs.v8i16")] - fn vqabsq_s16_(a: int16x8_t) -> int16x8_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrsqrts.v4f32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frsqrts.v4f32")] + fn vrsqrtsq_f32_(a: float32x4_t, b: float32x4_t) -> float32x4_t; } -vqabsq_s16_(a) +vrsqrtsq_f32_(a, b) } -/// Singned saturating Absolute value +/// Reciprocal estimate. #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqabs.s32"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqabs))] -pub unsafe fn vqabs_s32(a: int32x2_t) -> int32x2_t { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrecpe))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frecpe))] +pub unsafe fn vrecpe_f32(a: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqabs.v2i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqabs.v2i32")] - fn vqabs_s32_(a: int32x2_t) -> int32x2_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrecpe.v2f32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frecpe.v2f32")] + fn vrecpe_f32_(a: float32x2_t) -> float32x2_t; } -vqabs_s32_(a) +vrecpe_f32_(a) } -/// Singned saturating Absolute value +/// Reciprocal estimate. #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqabs.s32"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqabs))] -pub unsafe fn vqabsq_s32(a: int32x4_t) -> int32x4_t { +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrecpe))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frecpe))] +pub unsafe fn vrecpeq_f32(a: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqabs.v4i32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqabs.v4i32")] - fn vqabsq_s32_(a: int32x4_t) -> int32x4_t; + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrecpe.v4f32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frecpe.v4f32")] + fn vrecpeq_f32_(a: float32x4_t) -> float32x4_t; } -vqabsq_s32_(a) +vrecpeq_f32_(a) } -#[cfg(test)] -#[allow(overflowing_literals)] -mod test { - use super::*; - use crate::core_arch::simd::*; - use std::mem::transmute; - use stdarch_test::simd_test; - - #[simd_test(enable = "neon")] - unsafe fn test_vand_s8() { - let a: i8x8 = i8x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let b: i8x8 = i8x8::new(0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F); - let e: i8x8 = i8x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let r: i8x8 = transmute(vand_s8(transmute(a), transmute(b))); - assert_eq!(r, e); - - let a: i8x8 = i8x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let b: i8x8 = i8x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - let e: i8x8 = i8x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - let r: i8x8 = transmute(vand_s8(transmute(a), transmute(b))); - assert_eq!(r, e); +/// Unsigned reciprocal estimate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrecpe))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urecpe))] +pub unsafe fn vrecpe_u32(a: uint32x2_t) -> uint32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrecpe.v2i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.urecpe.v2i32")] + fn vrecpe_u32_(a: uint32x2_t) -> uint32x2_t; } +vrecpe_u32_(a) +} - #[simd_test(enable = "neon")] - unsafe fn test_vandq_s8() { - let a: i8x16 = i8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x00); - let b: i8x16 = i8x16::new(0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F); - let e: i8x16 = i8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x00); - let r: i8x16 = transmute(vandq_s8(transmute(a), transmute(b))); - assert_eq!(r, e); - - let a: i8x16 = i8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x00); - let b: i8x16 = i8x16::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - let e: i8x16 = i8x16::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - let r: i8x16 = transmute(vandq_s8(transmute(a), transmute(b))); - assert_eq!(r, e); +/// Unsigned reciprocal estimate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrecpe))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urecpe))] +pub unsafe fn vrecpeq_u32(a: uint32x4_t) -> uint32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrecpe.v4i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.urecpe.v4i32")] + fn vrecpeq_u32_(a: uint32x4_t) -> uint32x4_t; } +vrecpeq_u32_(a) +} - #[simd_test(enable = "neon")] - unsafe fn test_vand_s16() { - let a: i16x4 = i16x4::new(0x00, 0x01, 0x02, 0x03); - let b: i16x4 = i16x4::new(0x0F, 0x0F, 0x0F, 0x0F); - let e: i16x4 = i16x4::new(0x00, 0x01, 0x02, 0x03); - let r: i16x4 = transmute(vand_s16(transmute(a), transmute(b))); - assert_eq!(r, e); +/// Floating-point reciprocal step +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrecps))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frecps))] +pub unsafe fn vrecps_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrecps.v2f32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frecps.v2f32")] + fn vrecps_f32_(a: float32x2_t, b: float32x2_t) -> float32x2_t; + } +vrecps_f32_(a, b) +} - let a: i16x4 = i16x4::new(0x00, 0x01, 0x02, 0x03); - let b: i16x4 = i16x4::new(0x00, 0x00, 0x00, 0x00); - let e: i16x4 = i16x4::new(0x00, 0x00, 0x00, 0x00); - let r: i16x4 = transmute(vand_s16(transmute(a), transmute(b))); - assert_eq!(r, e); +/// Floating-point reciprocal step +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrecps))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frecps))] +pub unsafe fn vrecpsq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrecps.v4f32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frecps.v4f32")] + fn vrecpsq_f32_(a: float32x4_t, b: float32x4_t) -> float32x4_t; } +vrecpsq_f32_(a, b) +} - #[simd_test(enable = "neon")] - unsafe fn test_vandq_s16() { - let a: i16x8 = i16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let b: i16x8 = i16x8::new(0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F); - let e: i16x8 = i16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let r: i16x8 = transmute(vandq_s16(transmute(a), transmute(b))); - assert_eq!(r, e); +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s8_u8(a: uint8x8_t) -> int8x8_t { + transmute(a) +} - let a: i16x8 = i16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let b: i16x8 = i16x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - let e: i16x8 = i16x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - let r: i16x8 = transmute(vandq_s16(transmute(a), transmute(b))); - assert_eq!(r, e); - } +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s8_p8(a: poly8x8_t) -> int8x8_t { + transmute(a) +} - #[simd_test(enable = "neon")] - unsafe fn test_vand_s32() { - let a: i32x2 = i32x2::new(0x00, 0x01); - let b: i32x2 = i32x2::new(0x0F, 0x0F); - let e: i32x2 = i32x2::new(0x00, 0x01); - let r: i32x2 = transmute(vand_s32(transmute(a), transmute(b))); - assert_eq!(r, e); +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s16_p16(a: poly16x4_t) -> int16x4_t { + transmute(a) +} - let a: i32x2 = i32x2::new(0x00, 0x01); - let b: i32x2 = i32x2::new(0x00, 0x00); - let e: i32x2 = i32x2::new(0x00, 0x00); - let r: i32x2 = transmute(vand_s32(transmute(a), transmute(b))); +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s16_u16(a: uint16x4_t) -> int16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s32_u32(a: uint32x2_t) -> int32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s64_u64(a: uint64x1_t) -> int64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s8_u8(a: uint8x16_t) -> int8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s8_p8(a: poly8x16_t) -> int8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s16_p16(a: poly16x8_t) -> int16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s16_u16(a: uint16x8_t) -> int16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s32_u32(a: uint32x4_t) -> int32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s64_u64(a: uint64x2_t) -> int64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u8_p8(a: poly8x8_t) -> uint8x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u8_s8(a: int8x8_t) -> uint8x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u16_p16(a: poly16x4_t) -> uint16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u16_s16(a: int16x4_t) -> uint16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u32_s32(a: int32x2_t) -> uint32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u64_s64(a: int64x1_t) -> uint64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u8_p8(a: poly8x16_t) -> uint8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u8_s8(a: int8x16_t) -> uint8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u16_p16(a: poly16x8_t) -> uint16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u16_s16(a: int16x8_t) -> uint16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u32_s32(a: int32x4_t) -> uint32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u64_s64(a: int64x2_t) -> uint64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_p8_s8(a: int8x8_t) -> poly8x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_p8_u8(a: uint8x8_t) -> poly8x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_p16_s16(a: int16x4_t) -> poly16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_p16_u16(a: uint16x4_t) -> poly16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p8_s8(a: int8x16_t) -> poly8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p8_u8(a: uint8x16_t) -> poly8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p16_s16(a: int16x8_t) -> poly16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p16_u16(a: uint16x8_t) -> poly16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s8_s16(a: int16x4_t) -> int8x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s8_u16(a: uint16x4_t) -> int8x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s8_p16(a: poly16x4_t) -> int8x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s16_s32(a: int32x2_t) -> int16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s16_u32(a: uint32x2_t) -> int16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s32_s64(a: int64x1_t) -> int32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s32_u64(a: uint64x1_t) -> int32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s8_s16(a: int16x8_t) -> int8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s8_u16(a: uint16x8_t) -> int8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s8_p16(a: poly16x8_t) -> int8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s16_s32(a: int32x4_t) -> int16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s16_u32(a: uint32x4_t) -> int16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s32_s64(a: int64x2_t) -> int32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s32_u64(a: uint64x2_t) -> int32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u8_p16(a: poly16x4_t) -> uint8x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u8_s16(a: int16x4_t) -> uint8x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u8_u16(a: uint16x4_t) -> uint8x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u16_s32(a: int32x2_t) -> uint16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u16_u32(a: uint32x2_t) -> uint16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u32_s64(a: int64x1_t) -> uint32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u32_u64(a: uint64x1_t) -> uint32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u8_p16(a: poly16x8_t) -> uint8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u8_s16(a: int16x8_t) -> uint8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u8_u16(a: uint16x8_t) -> uint8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u16_s32(a: int32x4_t) -> uint16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u16_u32(a: uint32x4_t) -> uint16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u32_s64(a: int64x2_t) -> uint32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u32_u64(a: uint64x2_t) -> uint32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_p8_p16(a: poly16x4_t) -> poly8x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_p8_s16(a: int16x4_t) -> poly8x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_p8_u16(a: uint16x4_t) -> poly8x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_p16_s32(a: int32x2_t) -> poly16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_p16_u32(a: uint32x2_t) -> poly16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p8_p16(a: poly16x8_t) -> poly8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p8_s16(a: int16x8_t) -> poly8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p8_u16(a: uint16x8_t) -> poly8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p16_s32(a: int32x4_t) -> poly16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p16_u32(a: uint32x4_t) -> poly16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s32_p64(a: poly64x1_t) -> int32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u32_p64(a: poly64x1_t) -> uint32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s32_p64(a: poly64x2_t) -> int32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u32_p64(a: poly64x2_t) -> uint32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s64_p128(a: p128) -> int64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u64_p128(a: p128) -> uint64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p64_p128(a: p128) -> poly64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s16_p8(a: poly8x8_t) -> int16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s16_s8(a: int8x8_t) -> int16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s16_u8(a: uint8x8_t) -> int16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s32_p16(a: poly16x4_t) -> int32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s32_s16(a: int16x4_t) -> int32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s32_u16(a: uint16x4_t) -> int32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s64_s32(a: int32x2_t) -> int64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s64_u32(a: uint32x2_t) -> int64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s16_p8(a: poly8x16_t) -> int16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s16_s8(a: int8x16_t) -> int16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s16_u8(a: uint8x16_t) -> int16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s32_p16(a: poly16x8_t) -> int32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s32_s16(a: int16x8_t) -> int32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s32_u16(a: uint16x8_t) -> int32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s64_s32(a: int32x4_t) -> int64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s64_u32(a: uint32x4_t) -> int64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u16_p8(a: poly8x8_t) -> uint16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u16_s8(a: int8x8_t) -> uint16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u16_u8(a: uint8x8_t) -> uint16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u32_p16(a: poly16x4_t) -> uint32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u32_s16(a: int16x4_t) -> uint32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u32_u16(a: uint16x4_t) -> uint32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u64_s32(a: int32x2_t) -> uint64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u64_u32(a: uint32x2_t) -> uint64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u16_p8(a: poly8x16_t) -> uint16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u16_s8(a: int8x16_t) -> uint16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u16_u8(a: uint8x16_t) -> uint16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u32_p16(a: poly16x8_t) -> uint32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u32_s16(a: int16x8_t) -> uint32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u32_u16(a: uint16x8_t) -> uint32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u64_s32(a: int32x4_t) -> uint64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u64_u32(a: uint32x4_t) -> uint64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_p16_p8(a: poly8x8_t) -> poly16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_p16_s8(a: int8x8_t) -> poly16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_p16_u8(a: uint8x8_t) -> poly16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p16_p8(a: poly8x16_t) -> poly16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p16_s8(a: int8x16_t) -> poly16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p16_u8(a: uint8x16_t) -> poly16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_p64_s32(a: int32x2_t) -> poly64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_p64_u32(a: uint32x2_t) -> poly64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p64_s32(a: int32x4_t) -> poly64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p64_u32(a: uint32x4_t) -> poly64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p128_s64(a: int64x2_t) -> p128 { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p128_u64(a: uint64x2_t) -> p128 { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p128_p64(a: poly64x2_t) -> p128 { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s8_s32(a: int32x2_t) -> int8x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s8_u32(a: uint32x2_t) -> int8x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s16_s64(a: int64x1_t) -> int16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s16_u64(a: uint64x1_t) -> int16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s8_s32(a: int32x4_t) -> int8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s8_u32(a: uint32x4_t) -> int8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s16_s64(a: int64x2_t) -> int16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s16_u64(a: uint64x2_t) -> int16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u8_s32(a: int32x2_t) -> uint8x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u8_u32(a: uint32x2_t) -> uint8x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u16_s64(a: int64x1_t) -> uint16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u16_u64(a: uint64x1_t) -> uint16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u8_s32(a: int32x4_t) -> uint8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u8_u32(a: uint32x4_t) -> uint8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u16_s64(a: int64x2_t) -> uint16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u16_u64(a: uint64x2_t) -> uint16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_p8_s32(a: int32x2_t) -> poly8x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_p8_u32(a: uint32x2_t) -> poly8x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_p16_s64(a: int64x1_t) -> poly16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_p16_u64(a: uint64x1_t) -> poly16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p8_s32(a: int32x4_t) -> poly8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p8_u32(a: uint32x4_t) -> poly8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p16_s64(a: int64x2_t) -> poly16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p16_u64(a: uint64x2_t) -> poly16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s16_p64(a: poly64x1_t) -> int16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u16_p64(a: poly64x1_t) -> uint16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_p16_p64(a: poly64x1_t) -> poly16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s16_p64(a: poly64x2_t) -> int16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u16_p64(a: poly64x2_t) -> uint16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p16_p64(a: poly64x2_t) -> poly16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s32_p128(a: p128) -> int32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u32_p128(a: p128) -> uint32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s32_p8(a: poly8x8_t) -> int32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s32_s8(a: int8x8_t) -> int32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s32_u8(a: uint8x8_t) -> int32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s64_p16(a: poly16x4_t) -> int64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s64_s16(a: int16x4_t) -> int64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s64_u16(a: uint16x4_t) -> int64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s32_p8(a: poly8x16_t) -> int32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s32_s8(a: int8x16_t) -> int32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s32_u8(a: uint8x16_t) -> int32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s64_p16(a: poly16x8_t) -> int64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s64_s16(a: int16x8_t) -> int64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s64_u16(a: uint16x8_t) -> int64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u32_p8(a: poly8x8_t) -> uint32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u32_s8(a: int8x8_t) -> uint32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u32_u8(a: uint8x8_t) -> uint32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u64_p16(a: poly16x4_t) -> uint64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u64_s16(a: int16x4_t) -> uint64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u64_u16(a: uint16x4_t) -> uint64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u32_p8(a: poly8x16_t) -> uint32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u32_s8(a: int8x16_t) -> uint32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u32_u8(a: uint8x16_t) -> uint32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u64_p16(a: poly16x8_t) -> uint64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u64_s16(a: int16x8_t) -> uint64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u64_u16(a: uint16x8_t) -> uint64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_p64_p16(a: poly16x4_t) -> poly64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_p64_s16(a: int16x4_t) -> poly64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_p64_u16(a: uint16x4_t) -> poly64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p64_p16(a: poly16x8_t) -> poly64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p64_s16(a: int16x8_t) -> poly64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p64_u16(a: uint16x8_t) -> poly64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p128_s32(a: int32x4_t) -> p128 { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p128_u32(a: uint32x4_t) -> p128 { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s8_s64(a: int64x1_t) -> int8x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s8_u64(a: uint64x1_t) -> int8x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u8_s64(a: int64x1_t) -> uint8x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u8_u64(a: uint64x1_t) -> uint8x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_p8_s64(a: int64x1_t) -> poly8x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_p8_u64(a: uint64x1_t) -> poly8x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s8_s64(a: int64x2_t) -> int8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s8_u64(a: uint64x2_t) -> int8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u8_s64(a: int64x2_t) -> uint8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u8_u64(a: uint64x2_t) -> uint8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p8_s64(a: int64x2_t) -> poly8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p8_u64(a: uint64x2_t) -> poly8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s8_p64(a: poly64x1_t) -> int8x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u8_p64(a: poly64x1_t) -> uint8x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_p8_p64(a: poly64x1_t) -> poly8x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s8_p64(a: poly64x2_t) -> int8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u8_p64(a: poly64x2_t) -> uint8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p8_p64(a: poly64x2_t) -> poly8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s16_p128(a: p128) -> int16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u16_p128(a: p128) -> uint16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p16_p128(a: p128) -> poly16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s64_p8(a: poly8x8_t) -> int64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s64_s8(a: int8x8_t) -> int64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s64_u8(a: uint8x8_t) -> int64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u64_p8(a: poly8x8_t) -> uint64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u64_s8(a: int8x8_t) -> uint64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u64_u8(a: uint8x8_t) -> uint64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s64_p8(a: poly8x16_t) -> int64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s64_s8(a: int8x16_t) -> int64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s64_u8(a: uint8x16_t) -> int64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u64_p8(a: poly8x16_t) -> uint64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u64_s8(a: int8x16_t) -> uint64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u64_u8(a: uint8x16_t) -> uint64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_p64_p8(a: poly8x8_t) -> poly64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_p64_s8(a: int8x8_t) -> poly64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_p64_u8(a: uint8x8_t) -> poly64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p64_p8(a: poly8x16_t) -> poly64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p64_s8(a: int8x16_t) -> poly64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p64_u8(a: uint8x16_t) -> poly64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p128_s16(a: int16x8_t) -> p128 { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p128_u16(a: uint16x8_t) -> p128 { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p128_p16(a: poly16x8_t) -> p128 { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p128_s8(a: int8x16_t) -> p128 { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p128_u8(a: uint8x16_t) -> p128 { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p128_p8(a: poly8x16_t) -> p128 { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s8_p128(a: p128) -> int8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u8_p128(a: p128) -> uint8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p8_p128(a: p128) -> poly8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s8_f32(a: float32x2_t) -> int8x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s16_f32(a: float32x2_t) -> int16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s32_f32(a: float32x2_t) -> int32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_s64_f32(a: float32x2_t) -> int64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s8_f32(a: float32x4_t) -> int8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s16_f32(a: float32x4_t) -> int16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s32_f32(a: float32x4_t) -> int32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_s64_f32(a: float32x4_t) -> int64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u8_f32(a: float32x2_t) -> uint8x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u16_f32(a: float32x2_t) -> uint16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u32_f32(a: float32x2_t) -> uint32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_u64_f32(a: float32x2_t) -> uint64x1_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u8_f32(a: float32x4_t) -> uint8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u16_f32(a: float32x4_t) -> uint16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u32_f32(a: float32x4_t) -> uint32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_u64_f32(a: float32x4_t) -> uint64x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_p8_f32(a: float32x2_t) -> poly8x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_p16_f32(a: float32x2_t) -> poly16x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p8_f32(a: float32x4_t) -> poly8x16_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p16_f32(a: float32x4_t) -> poly16x8_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_p128_f32(a: float32x4_t) -> p128 { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_f32_s8(a: int8x8_t) -> float32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_f32_s16(a: int16x4_t) -> float32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_f32_s32(a: int32x2_t) -> float32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_f32_s64(a: int64x1_t) -> float32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_f32_s8(a: int8x16_t) -> float32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_f32_s16(a: int16x8_t) -> float32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_f32_s32(a: int32x4_t) -> float32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_f32_s64(a: int64x2_t) -> float32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_f32_u8(a: uint8x8_t) -> float32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_f32_u16(a: uint16x4_t) -> float32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_f32_u32(a: uint32x2_t) -> float32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_f32_u64(a: uint64x1_t) -> float32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_f32_u8(a: uint8x16_t) -> float32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_f32_u16(a: uint16x8_t) -> float32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_f32_u32(a: uint32x4_t) -> float32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_f32_u64(a: uint64x2_t) -> float32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_f32_p8(a: poly8x8_t) -> float32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpret_f32_p16(a: poly16x4_t) -> float32x2_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_f32_p8(a: poly8x16_t) -> float32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_f32_p16(a: poly16x8_t) -> float32x4_t { + transmute(a) +} + +/// Vector reinterpret cast operation +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vreinterpretq_f32_p128(a: p128) -> float32x4_t { + transmute(a) +} + +/// Signed rounding shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))] +pub unsafe fn vrshl_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshifts.v8i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.srshl.v8i8")] + fn vrshl_s8_(a: int8x8_t, b: int8x8_t) -> int8x8_t; + } +vrshl_s8_(a, b) +} + +/// Signed rounding shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))] +pub unsafe fn vrshlq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshifts.v16i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.srshl.v16i8")] + fn vrshlq_s8_(a: int8x16_t, b: int8x16_t) -> int8x16_t; + } +vrshlq_s8_(a, b) +} + +/// Signed rounding shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))] +pub unsafe fn vrshl_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshifts.v4i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.srshl.v4i16")] + fn vrshl_s16_(a: int16x4_t, b: int16x4_t) -> int16x4_t; + } +vrshl_s16_(a, b) +} + +/// Signed rounding shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))] +pub unsafe fn vrshlq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshifts.v8i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.srshl.v8i16")] + fn vrshlq_s16_(a: int16x8_t, b: int16x8_t) -> int16x8_t; + } +vrshlq_s16_(a, b) +} + +/// Signed rounding shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))] +pub unsafe fn vrshl_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshifts.v2i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.srshl.v2i32")] + fn vrshl_s32_(a: int32x2_t, b: int32x2_t) -> int32x2_t; + } +vrshl_s32_(a, b) +} + +/// Signed rounding shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))] +pub unsafe fn vrshlq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshifts.v4i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.srshl.v4i32")] + fn vrshlq_s32_(a: int32x4_t, b: int32x4_t) -> int32x4_t; + } +vrshlq_s32_(a, b) +} + +/// Signed rounding shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))] +pub unsafe fn vrshl_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshifts.v1i64")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.srshl.v1i64")] + fn vrshl_s64_(a: int64x1_t, b: int64x1_t) -> int64x1_t; + } +vrshl_s64_(a, b) +} + +/// Signed rounding shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))] +pub unsafe fn vrshlq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshifts.v2i64")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.srshl.v2i64")] + fn vrshlq_s64_(a: int64x2_t, b: int64x2_t) -> int64x2_t; + } +vrshlq_s64_(a, b) +} + +/// Unsigned rounding shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))] +pub unsafe fn vrshl_u8(a: uint8x8_t, b: int8x8_t) -> uint8x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshiftu.v8i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.urshl.v8i8")] + fn vrshl_u8_(a: uint8x8_t, b: int8x8_t) -> uint8x8_t; + } +vrshl_u8_(a, b) +} + +/// Unsigned rounding shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))] +pub unsafe fn vrshlq_u8(a: uint8x16_t, b: int8x16_t) -> uint8x16_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshiftu.v16i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.urshl.v16i8")] + fn vrshlq_u8_(a: uint8x16_t, b: int8x16_t) -> uint8x16_t; + } +vrshlq_u8_(a, b) +} + +/// Unsigned rounding shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))] +pub unsafe fn vrshl_u16(a: uint16x4_t, b: int16x4_t) -> uint16x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshiftu.v4i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.urshl.v4i16")] + fn vrshl_u16_(a: uint16x4_t, b: int16x4_t) -> uint16x4_t; + } +vrshl_u16_(a, b) +} + +/// Unsigned rounding shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))] +pub unsafe fn vrshlq_u16(a: uint16x8_t, b: int16x8_t) -> uint16x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshiftu.v8i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.urshl.v8i16")] + fn vrshlq_u16_(a: uint16x8_t, b: int16x8_t) -> uint16x8_t; + } +vrshlq_u16_(a, b) +} + +/// Unsigned rounding shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))] +pub unsafe fn vrshl_u32(a: uint32x2_t, b: int32x2_t) -> uint32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshiftu.v2i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.urshl.v2i32")] + fn vrshl_u32_(a: uint32x2_t, b: int32x2_t) -> uint32x2_t; + } +vrshl_u32_(a, b) +} + +/// Unsigned rounding shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))] +pub unsafe fn vrshlq_u32(a: uint32x4_t, b: int32x4_t) -> uint32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshiftu.v4i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.urshl.v4i32")] + fn vrshlq_u32_(a: uint32x4_t, b: int32x4_t) -> uint32x4_t; + } +vrshlq_u32_(a, b) +} + +/// Unsigned rounding shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))] +pub unsafe fn vrshl_u64(a: uint64x1_t, b: int64x1_t) -> uint64x1_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshiftu.v1i64")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.urshl.v1i64")] + fn vrshl_u64_(a: uint64x1_t, b: int64x1_t) -> uint64x1_t; + } +vrshl_u64_(a, b) +} + +/// Unsigned rounding shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))] +pub unsafe fn vrshlq_u64(a: uint64x2_t, b: int64x2_t) -> uint64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshiftu.v2i64")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.urshl.v2i64")] + fn vrshlq_u64_(a: uint64x2_t, b: int64x2_t) -> uint64x2_t; + } +vrshlq_u64_(a, b) +} + +/// Signed rounding shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vrshr_n_s8(a: int8x8_t) -> int8x8_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + vrshl_s8(a, vdup_n_s8((-N).try_into().unwrap())) +} + +/// Signed rounding shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vrshrq_n_s8(a: int8x16_t) -> int8x16_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + vrshlq_s8(a, vdupq_n_s8((-N).try_into().unwrap())) +} + +/// Signed rounding shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vrshr_n_s16(a: int16x4_t) -> int16x4_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + vrshl_s16(a, vdup_n_s16((-N).try_into().unwrap())) +} + +/// Signed rounding shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vrshrq_n_s16(a: int16x8_t) -> int16x8_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + vrshlq_s16(a, vdupq_n_s16((-N).try_into().unwrap())) +} + +/// Signed rounding shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vrshr_n_s32(a: int32x2_t) -> int32x2_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + vrshl_s32(a, vdup_n_s32((-N).try_into().unwrap())) +} + +/// Signed rounding shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vrshrq_n_s32(a: int32x4_t) -> int32x4_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + vrshlq_s32(a, vdupq_n_s32((-N).try_into().unwrap())) +} + +/// Signed rounding shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vrshr_n_s64(a: int64x1_t) -> int64x1_t { + static_assert!(N : i32 where N >= 1 && N <= 64); + vrshl_s64(a, vdup_n_s64((-N).try_into().unwrap())) +} + +/// Signed rounding shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vrshrq_n_s64(a: int64x2_t) -> int64x2_t { + static_assert!(N : i32 where N >= 1 && N <= 64); + vrshlq_s64(a, vdupq_n_s64((-N).try_into().unwrap())) +} + +/// Unsigned rounding shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vrshr_n_u8(a: uint8x8_t) -> uint8x8_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + vrshl_u8(a, vdup_n_s8((-N).try_into().unwrap())) +} + +/// Unsigned rounding shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vrshrq_n_u8(a: uint8x16_t) -> uint8x16_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + vrshlq_u8(a, vdupq_n_s8((-N).try_into().unwrap())) +} + +/// Unsigned rounding shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vrshr_n_u16(a: uint16x4_t) -> uint16x4_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + vrshl_u16(a, vdup_n_s16((-N).try_into().unwrap())) +} + +/// Unsigned rounding shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vrshrq_n_u16(a: uint16x8_t) -> uint16x8_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + vrshlq_u16(a, vdupq_n_s16((-N).try_into().unwrap())) +} + +/// Unsigned rounding shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vrshr_n_u32(a: uint32x2_t) -> uint32x2_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + vrshl_u32(a, vdup_n_s32((-N).try_into().unwrap())) +} + +/// Unsigned rounding shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vrshrq_n_u32(a: uint32x4_t) -> uint32x4_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + vrshlq_u32(a, vdupq_n_s32((-N).try_into().unwrap())) +} + +/// Unsigned rounding shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vrshr_n_u64(a: uint64x1_t) -> uint64x1_t { + static_assert!(N : i32 where N >= 1 && N <= 64); + vrshl_u64(a, vdup_n_s64((-N).try_into().unwrap())) +} + +/// Unsigned rounding shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vrshrq_n_u64(a: uint64x2_t) -> uint64x2_t { + static_assert!(N : i32 where N >= 1 && N <= 64); + vrshlq_u64(a, vdupq_n_s64((-N).try_into().unwrap())) +} + +/// Rounding shift right narrow +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vrshrn_n_s16(a: int16x8_t) -> int8x8_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshiftn.v8i8")] + fn vrshrn_n_s16_(a: int16x8_t, n: int16x8_t) -> int8x8_t; + } +vrshrn_n_s16_(a, int16x8_t(-N as i16, -N as i16, -N as i16, -N as i16, -N as i16, -N as i16, -N as i16, -N as i16)) +} + +/// Rounding shift right narrow +#[inline] +#[cfg(target_arch = "aarch64")] +#[target_feature(enable = "neon")] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vrshrn_n_s16(a: int16x8_t) -> int8x8_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.rshrn.v8i8")] + fn vrshrn_n_s16_(a: int16x8_t, n: i32) -> int8x8_t; + } +vrshrn_n_s16_(a, N) +} + +/// Rounding shift right narrow +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vrshrn_n_s32(a: int32x4_t) -> int16x4_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshiftn.v4i16")] + fn vrshrn_n_s32_(a: int32x4_t, n: int32x4_t) -> int16x4_t; + } +vrshrn_n_s32_(a, int32x4_t(-N as i32, -N as i32, -N as i32, -N as i32)) +} + +/// Rounding shift right narrow +#[inline] +#[cfg(target_arch = "aarch64")] +#[target_feature(enable = "neon")] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vrshrn_n_s32(a: int32x4_t) -> int16x4_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.rshrn.v4i16")] + fn vrshrn_n_s32_(a: int32x4_t, n: i32) -> int16x4_t; + } +vrshrn_n_s32_(a, N) +} + +/// Rounding shift right narrow +#[inline] +#[cfg(target_arch = "arm")] +#[target_feature(enable = "neon,v7")] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vrshrn_n_s64(a: int64x2_t) -> int32x2_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrshiftn.v2i32")] + fn vrshrn_n_s64_(a: int64x2_t, n: int64x2_t) -> int32x2_t; + } +vrshrn_n_s64_(a, int64x2_t(-N as i64, -N as i64)) +} + +/// Rounding shift right narrow +#[inline] +#[cfg(target_arch = "aarch64")] +#[target_feature(enable = "neon")] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vrshrn_n_s64(a: int64x2_t) -> int32x2_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.rshrn.v2i32")] + fn vrshrn_n_s64_(a: int64x2_t, n: i32) -> int32x2_t; + } +vrshrn_n_s64_(a, N) +} + +/// Rounding shift right narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshrn, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vrshrn_n_u16(a: uint16x8_t) -> uint8x8_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + transmute(vrshrn_n_s16::(transmute(a))) +} + +/// Rounding shift right narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshrn, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vrshrn_n_u32(a: uint32x4_t) -> uint16x4_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + transmute(vrshrn_n_s32::(transmute(a))) +} + +/// Rounding shift right narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshrn, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rshrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vrshrn_n_u64(a: uint64x2_t) -> uint32x2_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + transmute(vrshrn_n_s64::(transmute(a))) +} + +/// Signed rounding shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vrsra_n_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + simd_add(a, vrshr_n_s8::(b)) +} + +/// Signed rounding shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vrsraq_n_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + simd_add(a, vrshrq_n_s8::(b)) +} + +/// Signed rounding shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vrsra_n_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + simd_add(a, vrshr_n_s16::(b)) +} + +/// Signed rounding shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vrsraq_n_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + simd_add(a, vrshrq_n_s16::(b)) +} + +/// Signed rounding shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vrsra_n_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + simd_add(a, vrshr_n_s32::(b)) +} + +/// Signed rounding shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vrsraq_n_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + simd_add(a, vrshrq_n_s32::(b)) +} + +/// Signed rounding shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vrsra_n_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { + static_assert!(N : i32 where N >= 1 && N <= 64); + simd_add(a, vrshr_n_s64::(b)) +} + +/// Signed rounding shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vrsraq_n_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { + static_assert!(N : i32 where N >= 1 && N <= 64); + simd_add(a, vrshrq_n_s64::(b)) +} + +/// Unsigned rounding shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vrsra_n_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + simd_add(a, vrshr_n_u8::(b)) +} + +/// Unsigned rounding shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vrsraq_n_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + simd_add(a, vrshrq_n_u8::(b)) +} + +/// Unsigned rounding shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vrsra_n_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + simd_add(a, vrshr_n_u16::(b)) +} + +/// Unsigned rounding shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vrsraq_n_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + simd_add(a, vrshrq_n_u16::(b)) +} + +/// Unsigned rounding shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vrsra_n_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + simd_add(a, vrshr_n_u32::(b)) +} + +/// Unsigned rounding shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vrsraq_n_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + simd_add(a, vrshrq_n_u32::(b)) +} + +/// Unsigned rounding shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vrsra_n_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { + static_assert!(N : i32 where N >= 1 && N <= 64); + simd_add(a, vrshr_n_u64::(b)) +} + +/// Unsigned rounding shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vrsraq_n_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { + static_assert!(N : i32 where N >= 1 && N <= 64); + simd_add(a, vrshrq_n_u64::(b)) +} + +/// Rounding subtract returning high narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsubhn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rsubhn))] +pub unsafe fn vrsubhn_s16(a: int16x8_t, b: int16x8_t) -> int8x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrsubhn.v8i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.rsubhn.v8i8")] + fn vrsubhn_s16_(a: int16x8_t, b: int16x8_t) -> int8x8_t; + } +vrsubhn_s16_(a, b) +} + +/// Rounding subtract returning high narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsubhn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rsubhn))] +pub unsafe fn vrsubhn_s32(a: int32x4_t, b: int32x4_t) -> int16x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrsubhn.v4i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.rsubhn.v4i16")] + fn vrsubhn_s32_(a: int32x4_t, b: int32x4_t) -> int16x4_t; + } +vrsubhn_s32_(a, b) +} + +/// Rounding subtract returning high narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsubhn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rsubhn))] +pub unsafe fn vrsubhn_s64(a: int64x2_t, b: int64x2_t) -> int32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrsubhn.v2i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.rsubhn.v2i32")] + fn vrsubhn_s64_(a: int64x2_t, b: int64x2_t) -> int32x2_t; + } +vrsubhn_s64_(a, b) +} + +/// Rounding subtract returning high narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsubhn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rsubhn))] +pub unsafe fn vrsubhn_u16(a: uint16x8_t, b: uint16x8_t) -> uint8x8_t { + transmute(vrsubhn_s16(transmute(a), transmute(b))) +} + +/// Rounding subtract returning high narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsubhn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rsubhn))] +pub unsafe fn vrsubhn_u32(a: uint32x4_t, b: uint32x4_t) -> uint16x4_t { + transmute(vrsubhn_s32(transmute(a), transmute(b))) +} + +/// Rounding subtract returning high narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsubhn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rsubhn))] +pub unsafe fn vrsubhn_u64(a: uint64x2_t, b: uint64x2_t) -> uint32x2_t { + transmute(vrsubhn_s64(transmute(a), transmute(b))) +} + +/// Insert vector element from another vector element +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vset_lane_s8(a: i8, b: int8x8_t) -> int8x8_t { + static_assert_imm3!(LANE); + simd_insert(b, LANE as u32, a) +} + +/// Insert vector element from another vector element +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vset_lane_s16(a: i16, b: int16x4_t) -> int16x4_t { + static_assert_imm2!(LANE); + simd_insert(b, LANE as u32, a) +} + +/// Insert vector element from another vector element +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vset_lane_s32(a: i32, b: int32x2_t) -> int32x2_t { + static_assert_imm1!(LANE); + simd_insert(b, LANE as u32, a) +} + +/// Insert vector element from another vector element +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vset_lane_s64(a: i64, b: int64x1_t) -> int64x1_t { + static_assert!(LANE : i32 where LANE == 0); + simd_insert(b, LANE as u32, a) +} + +/// Insert vector element from another vector element +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vset_lane_u8(a: u8, b: uint8x8_t) -> uint8x8_t { + static_assert_imm3!(LANE); + simd_insert(b, LANE as u32, a) +} + +/// Insert vector element from another vector element +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vset_lane_u16(a: u16, b: uint16x4_t) -> uint16x4_t { + static_assert_imm2!(LANE); + simd_insert(b, LANE as u32, a) +} + +/// Insert vector element from another vector element +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vset_lane_u32(a: u32, b: uint32x2_t) -> uint32x2_t { + static_assert_imm1!(LANE); + simd_insert(b, LANE as u32, a) +} + +/// Insert vector element from another vector element +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vset_lane_u64(a: u64, b: uint64x1_t) -> uint64x1_t { + static_assert!(LANE : i32 where LANE == 0); + simd_insert(b, LANE as u32, a) +} + +/// Insert vector element from another vector element +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vset_lane_p8(a: p8, b: poly8x8_t) -> poly8x8_t { + static_assert_imm3!(LANE); + simd_insert(b, LANE as u32, a) +} + +/// Insert vector element from another vector element +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vset_lane_p16(a: p16, b: poly16x4_t) -> poly16x4_t { + static_assert_imm2!(LANE); + simd_insert(b, LANE as u32, a) +} + +/// Insert vector element from another vector element +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vset_lane_p64(a: p64, b: poly64x1_t) -> poly64x1_t { + static_assert!(LANE : i32 where LANE == 0); + simd_insert(b, LANE as u32, a) +} + +/// Insert vector element from another vector element +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsetq_lane_s8(a: i8, b: int8x16_t) -> int8x16_t { + static_assert_imm4!(LANE); + simd_insert(b, LANE as u32, a) +} + +/// Insert vector element from another vector element +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsetq_lane_s16(a: i16, b: int16x8_t) -> int16x8_t { + static_assert_imm3!(LANE); + simd_insert(b, LANE as u32, a) +} + +/// Insert vector element from another vector element +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsetq_lane_s32(a: i32, b: int32x4_t) -> int32x4_t { + static_assert_imm2!(LANE); + simd_insert(b, LANE as u32, a) +} + +/// Insert vector element from another vector element +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsetq_lane_s64(a: i64, b: int64x2_t) -> int64x2_t { + static_assert_imm1!(LANE); + simd_insert(b, LANE as u32, a) +} + +/// Insert vector element from another vector element +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsetq_lane_u8(a: u8, b: uint8x16_t) -> uint8x16_t { + static_assert_imm4!(LANE); + simd_insert(b, LANE as u32, a) +} + +/// Insert vector element from another vector element +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsetq_lane_u16(a: u16, b: uint16x8_t) -> uint16x8_t { + static_assert_imm3!(LANE); + simd_insert(b, LANE as u32, a) +} + +/// Insert vector element from another vector element +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsetq_lane_u32(a: u32, b: uint32x4_t) -> uint32x4_t { + static_assert_imm2!(LANE); + simd_insert(b, LANE as u32, a) +} + +/// Insert vector element from another vector element +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsetq_lane_u64(a: u64, b: uint64x2_t) -> uint64x2_t { + static_assert_imm1!(LANE); + simd_insert(b, LANE as u32, a) +} + +/// Insert vector element from another vector element +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsetq_lane_p8(a: p8, b: poly8x16_t) -> poly8x16_t { + static_assert_imm4!(LANE); + simd_insert(b, LANE as u32, a) +} + +/// Insert vector element from another vector element +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsetq_lane_p16(a: p16, b: poly16x8_t) -> poly16x8_t { + static_assert_imm3!(LANE); + simd_insert(b, LANE as u32, a) +} + +/// Insert vector element from another vector element +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsetq_lane_p64(a: p64, b: poly64x2_t) -> poly64x2_t { + static_assert_imm1!(LANE); + simd_insert(b, LANE as u32, a) +} + +/// Insert vector element from another vector element +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vset_lane_f32(a: f32, b: float32x2_t) -> float32x2_t { + static_assert_imm1!(LANE); + simd_insert(b, LANE as u32, a) +} + +/// Insert vector element from another vector element +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsetq_lane_f32(a: f32, b: float32x4_t) -> float32x4_t { + static_assert_imm2!(LANE); + simd_insert(b, LANE as u32, a) +} + +/// Signed Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))] +pub unsafe fn vshl_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshifts.v8i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sshl.v8i8")] + fn vshl_s8_(a: int8x8_t, b: int8x8_t) -> int8x8_t; + } +vshl_s8_(a, b) +} + +/// Signed Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))] +pub unsafe fn vshlq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshifts.v16i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sshl.v16i8")] + fn vshlq_s8_(a: int8x16_t, b: int8x16_t) -> int8x16_t; + } +vshlq_s8_(a, b) +} + +/// Signed Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))] +pub unsafe fn vshl_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshifts.v4i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sshl.v4i16")] + fn vshl_s16_(a: int16x4_t, b: int16x4_t) -> int16x4_t; + } +vshl_s16_(a, b) +} + +/// Signed Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))] +pub unsafe fn vshlq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshifts.v8i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sshl.v8i16")] + fn vshlq_s16_(a: int16x8_t, b: int16x8_t) -> int16x8_t; + } +vshlq_s16_(a, b) +} + +/// Signed Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))] +pub unsafe fn vshl_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshifts.v2i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sshl.v2i32")] + fn vshl_s32_(a: int32x2_t, b: int32x2_t) -> int32x2_t; + } +vshl_s32_(a, b) +} + +/// Signed Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))] +pub unsafe fn vshlq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshifts.v4i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sshl.v4i32")] + fn vshlq_s32_(a: int32x4_t, b: int32x4_t) -> int32x4_t; + } +vshlq_s32_(a, b) +} + +/// Signed Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))] +pub unsafe fn vshl_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshifts.v1i64")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sshl.v1i64")] + fn vshl_s64_(a: int64x1_t, b: int64x1_t) -> int64x1_t; + } +vshl_s64_(a, b) +} + +/// Signed Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))] +pub unsafe fn vshlq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshifts.v2i64")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sshl.v2i64")] + fn vshlq_s64_(a: int64x2_t, b: int64x2_t) -> int64x2_t; + } +vshlq_s64_(a, b) +} + +/// Unsigned Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))] +pub unsafe fn vshl_u8(a: uint8x8_t, b: int8x8_t) -> uint8x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshiftu.v8i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ushl.v8i8")] + fn vshl_u8_(a: uint8x8_t, b: int8x8_t) -> uint8x8_t; + } +vshl_u8_(a, b) +} + +/// Unsigned Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))] +pub unsafe fn vshlq_u8(a: uint8x16_t, b: int8x16_t) -> uint8x16_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshiftu.v16i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ushl.v16i8")] + fn vshlq_u8_(a: uint8x16_t, b: int8x16_t) -> uint8x16_t; + } +vshlq_u8_(a, b) +} + +/// Unsigned Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))] +pub unsafe fn vshl_u16(a: uint16x4_t, b: int16x4_t) -> uint16x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshiftu.v4i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ushl.v4i16")] + fn vshl_u16_(a: uint16x4_t, b: int16x4_t) -> uint16x4_t; + } +vshl_u16_(a, b) +} + +/// Unsigned Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))] +pub unsafe fn vshlq_u16(a: uint16x8_t, b: int16x8_t) -> uint16x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshiftu.v8i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ushl.v8i16")] + fn vshlq_u16_(a: uint16x8_t, b: int16x8_t) -> uint16x8_t; + } +vshlq_u16_(a, b) +} + +/// Unsigned Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))] +pub unsafe fn vshl_u32(a: uint32x2_t, b: int32x2_t) -> uint32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshiftu.v2i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ushl.v2i32")] + fn vshl_u32_(a: uint32x2_t, b: int32x2_t) -> uint32x2_t; + } +vshl_u32_(a, b) +} + +/// Unsigned Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))] +pub unsafe fn vshlq_u32(a: uint32x4_t, b: int32x4_t) -> uint32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshiftu.v4i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ushl.v4i32")] + fn vshlq_u32_(a: uint32x4_t, b: int32x4_t) -> uint32x4_t; + } +vshlq_u32_(a, b) +} + +/// Unsigned Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))] +pub unsafe fn vshl_u64(a: uint64x1_t, b: int64x1_t) -> uint64x1_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshiftu.v1i64")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ushl.v1i64")] + fn vshl_u64_(a: uint64x1_t, b: int64x1_t) -> uint64x1_t; + } +vshl_u64_(a, b) +} + +/// Unsigned Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))] +pub unsafe fn vshlq_u64(a: uint64x2_t, b: int64x2_t) -> uint64x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vshiftu.v2i64")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ushl.v2i64")] + fn vshlq_u64_(a: uint64x2_t, b: int64x2_t) -> uint64x2_t; + } +vshlq_u64_(a, b) +} + +/// Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshl_n_s8(a: int8x8_t) -> int8x8_t { + static_assert_imm3!(N); + simd_shl(a, vdup_n_s8(N.try_into().unwrap())) +} + +/// Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshlq_n_s8(a: int8x16_t) -> int8x16_t { + static_assert_imm3!(N); + simd_shl(a, vdupq_n_s8(N.try_into().unwrap())) +} + +/// Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshl_n_s16(a: int16x4_t) -> int16x4_t { + static_assert_imm4!(N); + simd_shl(a, vdup_n_s16(N.try_into().unwrap())) +} + +/// Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshlq_n_s16(a: int16x8_t) -> int16x8_t { + static_assert_imm4!(N); + simd_shl(a, vdupq_n_s16(N.try_into().unwrap())) +} + +/// Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshl_n_s32(a: int32x2_t) -> int32x2_t { + static_assert_imm5!(N); + simd_shl(a, vdup_n_s32(N.try_into().unwrap())) +} + +/// Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshlq_n_s32(a: int32x4_t) -> int32x4_t { + static_assert_imm5!(N); + simd_shl(a, vdupq_n_s32(N.try_into().unwrap())) +} + +/// Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshl_n_u8(a: uint8x8_t) -> uint8x8_t { + static_assert_imm3!(N); + simd_shl(a, vdup_n_u8(N.try_into().unwrap())) +} + +/// Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshlq_n_u8(a: uint8x16_t) -> uint8x16_t { + static_assert_imm3!(N); + simd_shl(a, vdupq_n_u8(N.try_into().unwrap())) +} + +/// Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshl_n_u16(a: uint16x4_t) -> uint16x4_t { + static_assert_imm4!(N); + simd_shl(a, vdup_n_u16(N.try_into().unwrap())) +} + +/// Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshlq_n_u16(a: uint16x8_t) -> uint16x8_t { + static_assert_imm4!(N); + simd_shl(a, vdupq_n_u16(N.try_into().unwrap())) +} + +/// Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshl_n_u32(a: uint32x2_t) -> uint32x2_t { + static_assert_imm5!(N); + simd_shl(a, vdup_n_u32(N.try_into().unwrap())) +} + +/// Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshlq_n_u32(a: uint32x4_t) -> uint32x4_t { + static_assert_imm5!(N); + simd_shl(a, vdupq_n_u32(N.try_into().unwrap())) +} + +/// Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshl_n_s64(a: int64x1_t) -> int64x1_t { + static_assert_imm6!(N); + simd_shl(a, vdup_n_s64(N.try_into().unwrap())) +} + +/// Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshlq_n_s64(a: int64x2_t) -> int64x2_t { + static_assert_imm6!(N); + simd_shl(a, vdupq_n_s64(N.try_into().unwrap())) +} + +/// Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshl_n_u64(a: uint64x1_t) -> uint64x1_t { + static_assert_imm6!(N); + simd_shl(a, vdup_n_u64(N.try_into().unwrap())) +} + +/// Shift left +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshlq_n_u64(a: uint64x2_t) -> uint64x2_t { + static_assert_imm6!(N); + simd_shl(a, vdupq_n_u64(N.try_into().unwrap())) +} + +/// Signed shift left long +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshll.s8", N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshll, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshll_n_s8(a: int8x8_t) -> int16x8_t { + static_assert!(N : i32 where N >= 0 && N <= 8); + simd_shl(simd_cast(a), vdupq_n_s16(N.try_into().unwrap())) +} + +/// Signed shift left long +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshll.s16", N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshll, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshll_n_s16(a: int16x4_t) -> int32x4_t { + static_assert!(N : i32 where N >= 0 && N <= 16); + simd_shl(simd_cast(a), vdupq_n_s32(N.try_into().unwrap())) +} + +/// Signed shift left long +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshll.s32", N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshll, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshll_n_s32(a: int32x2_t) -> int64x2_t { + static_assert!(N : i32 where N >= 0 && N <= 32); + simd_shl(simd_cast(a), vdupq_n_s64(N.try_into().unwrap())) +} + +/// Signed shift left long +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshll.u8", N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushll, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshll_n_u8(a: uint8x8_t) -> uint16x8_t { + static_assert!(N : i32 where N >= 0 && N <= 8); + simd_shl(simd_cast(a), vdupq_n_u16(N.try_into().unwrap())) +} + +/// Signed shift left long +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshll.u16", N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushll, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshll_n_u16(a: uint16x4_t) -> uint32x4_t { + static_assert!(N : i32 where N >= 0 && N <= 16); + simd_shl(simd_cast(a), vdupq_n_u32(N.try_into().unwrap())) +} + +/// Signed shift left long +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshll.u32", N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushll, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshll_n_u32(a: uint32x2_t) -> uint64x2_t { + static_assert!(N : i32 where N >= 0 && N <= 32); + simd_shl(simd_cast(a), vdupq_n_u64(N.try_into().unwrap())) +} + +/// Shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s8", N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshr_n_s8(a: int8x8_t) -> int8x8_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + let n: i32 = if N == 8 { 7 } else { N }; + simd_shr(a, vdup_n_s8(n.try_into().unwrap())) +} + +/// Shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s8", N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshrq_n_s8(a: int8x16_t) -> int8x16_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + let n: i32 = if N == 8 { 7 } else { N }; + simd_shr(a, vdupq_n_s8(n.try_into().unwrap())) +} + +/// Shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s16", N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshr_n_s16(a: int16x4_t) -> int16x4_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + let n: i32 = if N == 16 { 15 } else { N }; + simd_shr(a, vdup_n_s16(n.try_into().unwrap())) +} + +/// Shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s16", N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshrq_n_s16(a: int16x8_t) -> int16x8_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + let n: i32 = if N == 16 { 15 } else { N }; + simd_shr(a, vdupq_n_s16(n.try_into().unwrap())) +} + +/// Shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s32", N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshr_n_s32(a: int32x2_t) -> int32x2_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + let n: i32 = if N == 32 { 31 } else { N }; + simd_shr(a, vdup_n_s32(n.try_into().unwrap())) +} + +/// Shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s32", N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshrq_n_s32(a: int32x4_t) -> int32x4_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + let n: i32 = if N == 32 { 31 } else { N }; + simd_shr(a, vdupq_n_s32(n.try_into().unwrap())) +} + +/// Shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s64", N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshr_n_s64(a: int64x1_t) -> int64x1_t { + static_assert!(N : i32 where N >= 1 && N <= 64); + let n: i32 = if N == 64 { 63 } else { N }; + simd_shr(a, vdup_n_s64(n.try_into().unwrap())) +} + +/// Shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s64", N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshrq_n_s64(a: int64x2_t) -> int64x2_t { + static_assert!(N : i32 where N >= 1 && N <= 64); + let n: i32 = if N == 64 { 63 } else { N }; + simd_shr(a, vdupq_n_s64(n.try_into().unwrap())) +} + +/// Shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u8", N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshr_n_u8(a: uint8x8_t) -> uint8x8_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + let n: i32 = if N == 8 { return vdup_n_u8(0); } else { N }; + simd_shr(a, vdup_n_u8(n.try_into().unwrap())) +} + +/// Shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u8", N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshrq_n_u8(a: uint8x16_t) -> uint8x16_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + let n: i32 = if N == 8 { return vdupq_n_u8(0); } else { N }; + simd_shr(a, vdupq_n_u8(n.try_into().unwrap())) +} + +/// Shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u16", N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshr_n_u16(a: uint16x4_t) -> uint16x4_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + let n: i32 = if N == 16 { return vdup_n_u16(0); } else { N }; + simd_shr(a, vdup_n_u16(n.try_into().unwrap())) +} + +/// Shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u16", N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshrq_n_u16(a: uint16x8_t) -> uint16x8_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + let n: i32 = if N == 16 { return vdupq_n_u16(0); } else { N }; + simd_shr(a, vdupq_n_u16(n.try_into().unwrap())) +} + +/// Shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u32", N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshr_n_u32(a: uint32x2_t) -> uint32x2_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + let n: i32 = if N == 32 { return vdup_n_u32(0); } else { N }; + simd_shr(a, vdup_n_u32(n.try_into().unwrap())) +} + +/// Shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u32", N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshrq_n_u32(a: uint32x4_t) -> uint32x4_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + let n: i32 = if N == 32 { return vdupq_n_u32(0); } else { N }; + simd_shr(a, vdupq_n_u32(n.try_into().unwrap())) +} + +/// Shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u64", N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshr_n_u64(a: uint64x1_t) -> uint64x1_t { + static_assert!(N : i32 where N >= 1 && N <= 64); + let n: i32 = if N == 64 { return vdup_n_u64(0); } else { N }; + simd_shr(a, vdup_n_u64(n.try_into().unwrap())) +} + +/// Shift right +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u64", N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshrq_n_u64(a: uint64x2_t) -> uint64x2_t { + static_assert!(N : i32 where N >= 1 && N <= 64); + let n: i32 = if N == 64 { return vdupq_n_u64(0); } else { N }; + simd_shr(a, vdupq_n_u64(n.try_into().unwrap())) +} + +/// Shift right narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshrn.i16", N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshrn_n_s16(a: int16x8_t) -> int8x8_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + simd_cast(simd_shr(a, vdupq_n_s16(N.try_into().unwrap()))) +} + +/// Shift right narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshrn.i32", N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshrn_n_s32(a: int32x4_t) -> int16x4_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + simd_cast(simd_shr(a, vdupq_n_s32(N.try_into().unwrap()))) +} + +/// Shift right narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshrn.i64", N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshrn_n_s64(a: int64x2_t) -> int32x2_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + simd_cast(simd_shr(a, vdupq_n_s64(N.try_into().unwrap()))) +} + +/// Shift right narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshrn.i16", N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshrn_n_u16(a: uint16x8_t) -> uint8x8_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + simd_cast(simd_shr(a, vdupq_n_u16(N.try_into().unwrap()))) +} + +/// Shift right narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshrn.i32", N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshrn_n_u32(a: uint32x4_t) -> uint16x4_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + simd_cast(simd_shr(a, vdupq_n_u32(N.try_into().unwrap()))) +} + +/// Shift right narrow +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshrn.i64", N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shrn, N = 2))] +#[rustc_legacy_const_generics(1)] +pub unsafe fn vshrn_n_u64(a: uint64x2_t) -> uint32x2_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + simd_cast(simd_shr(a, vdupq_n_u64(N.try_into().unwrap()))) +} + +/// Signed shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsra_n_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + simd_add(a, vshr_n_s8::(b)) +} + +/// Signed shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsraq_n_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + simd_add(a, vshrq_n_s8::(b)) +} + +/// Signed shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsra_n_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + simd_add(a, vshr_n_s16::(b)) +} + +/// Signed shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsraq_n_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + simd_add(a, vshrq_n_s16::(b)) +} + +/// Signed shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsra_n_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + simd_add(a, vshr_n_s32::(b)) +} + +/// Signed shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsraq_n_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + simd_add(a, vshrq_n_s32::(b)) +} + +/// Signed shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsra_n_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { + static_assert!(N : i32 where N >= 1 && N <= 64); + simd_add(a, vshr_n_s64::(b)) +} + +/// Signed shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsraq_n_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { + static_assert!(N : i32 where N >= 1 && N <= 64); + simd_add(a, vshrq_n_s64::(b)) +} + +/// Unsigned shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsra_n_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + simd_add(a, vshr_n_u8::(b)) +} + +/// Unsigned shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsraq_n_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { + static_assert!(N : i32 where N >= 1 && N <= 8); + simd_add(a, vshrq_n_u8::(b)) +} + +/// Unsigned shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsra_n_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + simd_add(a, vshr_n_u16::(b)) +} + +/// Unsigned shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsraq_n_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { + static_assert!(N : i32 where N >= 1 && N <= 16); + simd_add(a, vshrq_n_u16::(b)) +} + +/// Unsigned shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsra_n_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + simd_add(a, vshr_n_u32::(b)) +} + +/// Unsigned shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsraq_n_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { + static_assert!(N : i32 where N >= 1 && N <= 32); + simd_add(a, vshrq_n_u32::(b)) +} + +/// Unsigned shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsra_n_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { + static_assert!(N : i32 where N >= 1 && N <= 64); + simd_add(a, vshr_n_u64::(b)) +} + +/// Unsigned shift right and accumulate +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))] +#[rustc_legacy_const_generics(2)] +pub unsafe fn vsraq_n_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { + static_assert!(N : i32 where N >= 1 && N <= 64); + simd_add(a, vshrq_n_u64::(b)) +} + +/// Transpose elements +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))] +pub unsafe fn vtrn_s8(a: int8x8_t, b: int8x8_t) -> int8x8x2_t { + let a1: int8x8_t = simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]); + let b1: int8x8_t = simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]); + transmute((a1, b1)) +} + +/// Transpose elements +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))] +pub unsafe fn vtrn_s16(a: int16x4_t, b: int16x4_t) -> int16x4x2_t { + let a1: int16x4_t = simd_shuffle4!(a, b, [0, 4, 2, 6]); + let b1: int16x4_t = simd_shuffle4!(a, b, [1, 5, 3, 7]); + transmute((a1, b1)) +} + +/// Transpose elements +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))] +pub unsafe fn vtrnq_s8(a: int8x16_t, b: int8x16_t) -> int8x16x2_t { + let a1: int8x16_t = simd_shuffle16!(a, b, [0, 16, 2, 18, 4, 20, 6, 22, 8, 24, 10, 26, 12, 28, 14, 30]); + let b1: int8x16_t = simd_shuffle16!(a, b, [1, 17, 3, 19, 5, 21, 7, 23, 9, 25, 11, 27, 13, 29, 15, 31]); + transmute((a1, b1)) +} + +/// Transpose elements +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))] +pub unsafe fn vtrnq_s16(a: int16x8_t, b: int16x8_t) -> int16x8x2_t { + let a1: int16x8_t = simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]); + let b1: int16x8_t = simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]); + transmute((a1, b1)) +} + +/// Transpose elements +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))] +pub unsafe fn vtrnq_s32(a: int32x4_t, b: int32x4_t) -> int32x4x2_t { + let a1: int32x4_t = simd_shuffle4!(a, b, [0, 4, 2, 6]); + let b1: int32x4_t = simd_shuffle4!(a, b, [1, 5, 3, 7]); + transmute((a1, b1)) +} + +/// Transpose elements +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))] +pub unsafe fn vtrn_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8x2_t { + let a1: uint8x8_t = simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]); + let b1: uint8x8_t = simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]); + transmute((a1, b1)) +} + +/// Transpose elements +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))] +pub unsafe fn vtrn_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4x2_t { + let a1: uint16x4_t = simd_shuffle4!(a, b, [0, 4, 2, 6]); + let b1: uint16x4_t = simd_shuffle4!(a, b, [1, 5, 3, 7]); + transmute((a1, b1)) +} + +/// Transpose elements +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))] +pub unsafe fn vtrnq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16x2_t { + let a1: uint8x16_t = simd_shuffle16!(a, b, [0, 16, 2, 18, 4, 20, 6, 22, 8, 24, 10, 26, 12, 28, 14, 30]); + let b1: uint8x16_t = simd_shuffle16!(a, b, [1, 17, 3, 19, 5, 21, 7, 23, 9, 25, 11, 27, 13, 29, 15, 31]); + transmute((a1, b1)) +} + +/// Transpose elements +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))] +pub unsafe fn vtrnq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8x2_t { + let a1: uint16x8_t = simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]); + let b1: uint16x8_t = simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]); + transmute((a1, b1)) +} + +/// Transpose elements +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))] +pub unsafe fn vtrnq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4x2_t { + let a1: uint32x4_t = simd_shuffle4!(a, b, [0, 4, 2, 6]); + let b1: uint32x4_t = simd_shuffle4!(a, b, [1, 5, 3, 7]); + transmute((a1, b1)) +} + +/// Transpose elements +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))] +pub unsafe fn vtrn_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8x2_t { + let a1: poly8x8_t = simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]); + let b1: poly8x8_t = simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]); + transmute((a1, b1)) +} + +/// Transpose elements +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))] +pub unsafe fn vtrn_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4x2_t { + let a1: poly16x4_t = simd_shuffle4!(a, b, [0, 4, 2, 6]); + let b1: poly16x4_t = simd_shuffle4!(a, b, [1, 5, 3, 7]); + transmute((a1, b1)) +} + +/// Transpose elements +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))] +pub unsafe fn vtrnq_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16x2_t { + let a1: poly8x16_t = simd_shuffle16!(a, b, [0, 16, 2, 18, 4, 20, 6, 22, 8, 24, 10, 26, 12, 28, 14, 30]); + let b1: poly8x16_t = simd_shuffle16!(a, b, [1, 17, 3, 19, 5, 21, 7, 23, 9, 25, 11, 27, 13, 29, 15, 31]); + transmute((a1, b1)) +} + +/// Transpose elements +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))] +pub unsafe fn vtrnq_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8x2_t { + let a1: poly16x8_t = simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]); + let b1: poly16x8_t = simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]); + transmute((a1, b1)) +} + +/// Transpose elements +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))] +pub unsafe fn vtrn_s32(a: int32x2_t, b: int32x2_t) -> int32x2x2_t { + let a1: int32x2_t = simd_shuffle2!(a, b, [0, 2]); + let b1: int32x2_t = simd_shuffle2!(a, b, [1, 3]); + transmute((a1, b1)) +} + +/// Transpose elements +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))] +pub unsafe fn vtrn_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2x2_t { + let a1: uint32x2_t = simd_shuffle2!(a, b, [0, 2]); + let b1: uint32x2_t = simd_shuffle2!(a, b, [1, 3]); + transmute((a1, b1)) +} + +/// Transpose elements +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))] +pub unsafe fn vtrn_f32(a: float32x2_t, b: float32x2_t) -> float32x2x2_t { + let a1: float32x2_t = simd_shuffle2!(a, b, [0, 2]); + let b1: float32x2_t = simd_shuffle2!(a, b, [1, 3]); + transmute((a1, b1)) +} + +/// Transpose elements +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))] +pub unsafe fn vtrnq_f32(a: float32x4_t, b: float32x4_t) -> float32x4x2_t { + let a1: float32x4_t = simd_shuffle4!(a, b, [0, 4, 2, 6]); + let b1: float32x4_t = simd_shuffle4!(a, b, [1, 5, 3, 7]); + transmute((a1, b1)) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))] +pub unsafe fn vzip_s8(a: int8x8_t, b: int8x8_t) -> int8x8x2_t { + let a0: int8x8_t = simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]); + let b0: int8x8_t = simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]); + transmute((a0, b0)) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))] +pub unsafe fn vzip_s16(a: int16x4_t, b: int16x4_t) -> int16x4x2_t { + let a0: int16x4_t = simd_shuffle4!(a, b, [0, 4, 1, 5]); + let b0: int16x4_t = simd_shuffle4!(a, b, [2, 6, 3, 7]); + transmute((a0, b0)) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))] +pub unsafe fn vzip_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8x2_t { + let a0: uint8x8_t = simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]); + let b0: uint8x8_t = simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]); + transmute((a0, b0)) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))] +pub unsafe fn vzip_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4x2_t { + let a0: uint16x4_t = simd_shuffle4!(a, b, [0, 4, 1, 5]); + let b0: uint16x4_t = simd_shuffle4!(a, b, [2, 6, 3, 7]); + transmute((a0, b0)) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))] +pub unsafe fn vzip_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8x2_t { + let a0: poly8x8_t = simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]); + let b0: poly8x8_t = simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]); + transmute((a0, b0)) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))] +pub unsafe fn vzip_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4x2_t { + let a0: poly16x4_t = simd_shuffle4!(a, b, [0, 4, 1, 5]); + let b0: poly16x4_t = simd_shuffle4!(a, b, [2, 6, 3, 7]); + transmute((a0, b0)) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))] +pub unsafe fn vzip_s32(a: int32x2_t, b: int32x2_t) -> int32x2x2_t { + let a0: int32x2_t = simd_shuffle2!(a, b, [0, 2]); + let b0: int32x2_t = simd_shuffle2!(a, b, [1, 3]); + transmute((a0, b0)) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))] +pub unsafe fn vzip_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2x2_t { + let a0: uint32x2_t = simd_shuffle2!(a, b, [0, 2]); + let b0: uint32x2_t = simd_shuffle2!(a, b, [1, 3]); + transmute((a0, b0)) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))] +pub unsafe fn vzipq_s8(a: int8x16_t, b: int8x16_t) -> int8x16x2_t { + let a0: int8x16_t = simd_shuffle16!(a, b, [0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23]); + let b0: int8x16_t = simd_shuffle16!(a, b, [8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31]); + transmute((a0, b0)) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))] +pub unsafe fn vzipq_s16(a: int16x8_t, b: int16x8_t) -> int16x8x2_t { + let a0: int16x8_t = simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]); + let b0: int16x8_t = simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]); + transmute((a0, b0)) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))] +pub unsafe fn vzipq_s32(a: int32x4_t, b: int32x4_t) -> int32x4x2_t { + let a0: int32x4_t = simd_shuffle4!(a, b, [0, 4, 1, 5]); + let b0: int32x4_t = simd_shuffle4!(a, b, [2, 6, 3, 7]); + transmute((a0, b0)) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))] +pub unsafe fn vzipq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16x2_t { + let a0: uint8x16_t = simd_shuffle16!(a, b, [0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23]); + let b0: uint8x16_t = simd_shuffle16!(a, b, [8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31]); + transmute((a0, b0)) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))] +pub unsafe fn vzipq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8x2_t { + let a0: uint16x8_t = simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]); + let b0: uint16x8_t = simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]); + transmute((a0, b0)) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))] +pub unsafe fn vzipq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4x2_t { + let a0: uint32x4_t = simd_shuffle4!(a, b, [0, 4, 1, 5]); + let b0: uint32x4_t = simd_shuffle4!(a, b, [2, 6, 3, 7]); + transmute((a0, b0)) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))] +pub unsafe fn vzipq_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16x2_t { + let a0: poly8x16_t = simd_shuffle16!(a, b, [0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23]); + let b0: poly8x16_t = simd_shuffle16!(a, b, [8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31]); + transmute((a0, b0)) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))] +pub unsafe fn vzipq_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8x2_t { + let a0: poly16x8_t = simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]); + let b0: poly16x8_t = simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]); + transmute((a0, b0)) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))] +pub unsafe fn vzip_f32(a: float32x2_t, b: float32x2_t) -> float32x2x2_t { + let a0: float32x2_t = simd_shuffle2!(a, b, [0, 2]); + let b0: float32x2_t = simd_shuffle2!(a, b, [1, 3]); + transmute((a0, b0)) +} + +/// Zip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))] +pub unsafe fn vzipq_f32(a: float32x4_t, b: float32x4_t) -> float32x4x2_t { + let a0: float32x4_t = simd_shuffle4!(a, b, [0, 4, 1, 5]); + let b0: float32x4_t = simd_shuffle4!(a, b, [2, 6, 3, 7]); + transmute((a0, b0)) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))] +pub unsafe fn vuzp_s8(a: int8x8_t, b: int8x8_t) -> int8x8x2_t { + let a0: int8x8_t = simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]); + let b0: int8x8_t = simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]); + transmute((a0, b0)) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))] +pub unsafe fn vuzp_s16(a: int16x4_t, b: int16x4_t) -> int16x4x2_t { + let a0: int16x4_t = simd_shuffle4!(a, b, [0, 2, 4, 6]); + let b0: int16x4_t = simd_shuffle4!(a, b, [1, 3, 5, 7]); + transmute((a0, b0)) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))] +pub unsafe fn vuzpq_s8(a: int8x16_t, b: int8x16_t) -> int8x16x2_t { + let a0: int8x16_t = simd_shuffle16!(a, b, [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30]); + let b0: int8x16_t = simd_shuffle16!(a, b, [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31]); + transmute((a0, b0)) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))] +pub unsafe fn vuzpq_s16(a: int16x8_t, b: int16x8_t) -> int16x8x2_t { + let a0: int16x8_t = simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]); + let b0: int16x8_t = simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]); + transmute((a0, b0)) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))] +pub unsafe fn vuzpq_s32(a: int32x4_t, b: int32x4_t) -> int32x4x2_t { + let a0: int32x4_t = simd_shuffle4!(a, b, [0, 2, 4, 6]); + let b0: int32x4_t = simd_shuffle4!(a, b, [1, 3, 5, 7]); + transmute((a0, b0)) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))] +pub unsafe fn vuzp_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8x2_t { + let a0: uint8x8_t = simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]); + let b0: uint8x8_t = simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]); + transmute((a0, b0)) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))] +pub unsafe fn vuzp_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4x2_t { + let a0: uint16x4_t = simd_shuffle4!(a, b, [0, 2, 4, 6]); + let b0: uint16x4_t = simd_shuffle4!(a, b, [1, 3, 5, 7]); + transmute((a0, b0)) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))] +pub unsafe fn vuzpq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16x2_t { + let a0: uint8x16_t = simd_shuffle16!(a, b, [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30]); + let b0: uint8x16_t = simd_shuffle16!(a, b, [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31]); + transmute((a0, b0)) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))] +pub unsafe fn vuzpq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8x2_t { + let a0: uint16x8_t = simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]); + let b0: uint16x8_t = simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]); + transmute((a0, b0)) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))] +pub unsafe fn vuzpq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4x2_t { + let a0: uint32x4_t = simd_shuffle4!(a, b, [0, 2, 4, 6]); + let b0: uint32x4_t = simd_shuffle4!(a, b, [1, 3, 5, 7]); + transmute((a0, b0)) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))] +pub unsafe fn vuzp_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8x2_t { + let a0: poly8x8_t = simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]); + let b0: poly8x8_t = simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]); + transmute((a0, b0)) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))] +pub unsafe fn vuzp_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4x2_t { + let a0: poly16x4_t = simd_shuffle4!(a, b, [0, 2, 4, 6]); + let b0: poly16x4_t = simd_shuffle4!(a, b, [1, 3, 5, 7]); + transmute((a0, b0)) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))] +pub unsafe fn vuzpq_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16x2_t { + let a0: poly8x16_t = simd_shuffle16!(a, b, [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30]); + let b0: poly8x16_t = simd_shuffle16!(a, b, [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31]); + transmute((a0, b0)) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))] +pub unsafe fn vuzpq_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8x2_t { + let a0: poly16x8_t = simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]); + let b0: poly16x8_t = simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]); + transmute((a0, b0)) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))] +pub unsafe fn vuzp_s32(a: int32x2_t, b: int32x2_t) -> int32x2x2_t { + let a0: int32x2_t = simd_shuffle2!(a, b, [0, 2]); + let b0: int32x2_t = simd_shuffle2!(a, b, [1, 3]); + transmute((a0, b0)) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))] +pub unsafe fn vuzp_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2x2_t { + let a0: uint32x2_t = simd_shuffle2!(a, b, [0, 2]); + let b0: uint32x2_t = simd_shuffle2!(a, b, [1, 3]); + transmute((a0, b0)) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))] +pub unsafe fn vuzp_f32(a: float32x2_t, b: float32x2_t) -> float32x2x2_t { + let a0: float32x2_t = simd_shuffle2!(a, b, [0, 2]); + let b0: float32x2_t = simd_shuffle2!(a, b, [1, 3]); + transmute((a0, b0)) +} + +/// Unzip vectors +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))] +pub unsafe fn vuzpq_f32(a: float32x4_t, b: float32x4_t) -> float32x4x2_t { + let a0: float32x4_t = simd_shuffle4!(a, b, [0, 2, 4, 6]); + let b0: float32x4_t = simd_shuffle4!(a, b, [1, 3, 5, 7]); + transmute((a0, b0)) +} + +/// Unsigned Absolute difference and Accumulate Long +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabal.u8"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabal))] +pub unsafe fn vabal_u8(a: uint16x8_t, b: uint8x8_t, c: uint8x8_t) -> uint16x8_t { + let d: uint8x8_t = vabd_u8(b, c); + simd_add(a, simd_cast(d)) +} + +/// Unsigned Absolute difference and Accumulate Long +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabal.u16"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabal))] +pub unsafe fn vabal_u16(a: uint32x4_t, b: uint16x4_t, c: uint16x4_t) -> uint32x4_t { + let d: uint16x4_t = vabd_u16(b, c); + simd_add(a, simd_cast(d)) +} + +/// Unsigned Absolute difference and Accumulate Long +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabal.u32"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabal))] +pub unsafe fn vabal_u32(a: uint64x2_t, b: uint32x2_t, c: uint32x2_t) -> uint64x2_t { + let d: uint32x2_t = vabd_u32(b, c); + simd_add(a, simd_cast(d)) +} + +/// Signed Absolute difference and Accumulate Long +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabal.s8"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabal))] +pub unsafe fn vabal_s8(a: int16x8_t, b: int8x8_t, c: int8x8_t) -> int16x8_t { + let d: int8x8_t = vabd_s8(b, c); + let e: uint8x8_t = simd_cast(d); + simd_add(a, simd_cast(e)) +} + +/// Signed Absolute difference and Accumulate Long +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabal.s16"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabal))] +pub unsafe fn vabal_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t { + let d: int16x4_t = vabd_s16(b, c); + let e: uint16x4_t = simd_cast(d); + simd_add(a, simd_cast(e)) +} + +/// Signed Absolute difference and Accumulate Long +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabal.s32"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabal))] +pub unsafe fn vabal_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t { + let d: int32x2_t = vabd_s32(b, c); + let e: uint32x2_t = simd_cast(d); + simd_add(a, simd_cast(e)) +} + +/// Singned saturating Absolute value +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqabs.s8"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqabs))] +pub unsafe fn vqabs_s8(a: int8x8_t) -> int8x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqabs.v8i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqabs.v8i8")] + fn vqabs_s8_(a: int8x8_t) -> int8x8_t; + } +vqabs_s8_(a) +} + +/// Singned saturating Absolute value +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqabs.s8"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqabs))] +pub unsafe fn vqabsq_s8(a: int8x16_t) -> int8x16_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqabs.v16i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqabs.v16i8")] + fn vqabsq_s8_(a: int8x16_t) -> int8x16_t; + } +vqabsq_s8_(a) +} + +/// Singned saturating Absolute value +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqabs.s16"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqabs))] +pub unsafe fn vqabs_s16(a: int16x4_t) -> int16x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqabs.v4i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqabs.v4i16")] + fn vqabs_s16_(a: int16x4_t) -> int16x4_t; + } +vqabs_s16_(a) +} + +/// Singned saturating Absolute value +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqabs.s16"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqabs))] +pub unsafe fn vqabsq_s16(a: int16x8_t) -> int16x8_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqabs.v8i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqabs.v8i16")] + fn vqabsq_s16_(a: int16x8_t) -> int16x8_t; + } +vqabsq_s16_(a) +} + +/// Singned saturating Absolute value +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqabs.s32"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqabs))] +pub unsafe fn vqabs_s32(a: int32x2_t) -> int32x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqabs.v2i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqabs.v2i32")] + fn vqabs_s32_(a: int32x2_t) -> int32x2_t; + } +vqabs_s32_(a) +} + +/// Singned saturating Absolute value +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqabs.s32"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqabs))] +pub unsafe fn vqabsq_s32(a: int32x4_t) -> int32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqabs.v4i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqabs.v4i32")] + fn vqabsq_s32_(a: int32x4_t) -> int32x4_t; + } +vqabsq_s32_(a) +} + +#[cfg(test)] +#[allow(overflowing_literals)] +mod test { + use super::*; + use crate::core_arch::simd::*; + use std::mem::transmute; + use stdarch_test::simd_test; + + #[simd_test(enable = "neon")] + unsafe fn test_vand_s8() { + let a: i8x8 = i8x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let b: i8x8 = i8x8::new(0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F); + let e: i8x8 = i8x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let r: i8x8 = transmute(vand_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: i8x8 = i8x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let b: i8x8 = i8x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let e: i8x8 = i8x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let r: i8x8 = transmute(vand_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vandq_s8() { + let a: i8x16 = i8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x00); + let b: i8x16 = i8x16::new(0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F); + let e: i8x16 = i8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x00); + let r: i8x16 = transmute(vandq_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: i8x16 = i8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x00); + let b: i8x16 = i8x16::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let e: i8x16 = i8x16::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let r: i8x16 = transmute(vandq_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vand_s16() { + let a: i16x4 = i16x4::new(0x00, 0x01, 0x02, 0x03); + let b: i16x4 = i16x4::new(0x0F, 0x0F, 0x0F, 0x0F); + let e: i16x4 = i16x4::new(0x00, 0x01, 0x02, 0x03); + let r: i16x4 = transmute(vand_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: i16x4 = i16x4::new(0x00, 0x01, 0x02, 0x03); + let b: i16x4 = i16x4::new(0x00, 0x00, 0x00, 0x00); + let e: i16x4 = i16x4::new(0x00, 0x00, 0x00, 0x00); + let r: i16x4 = transmute(vand_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vandq_s16() { + let a: i16x8 = i16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let b: i16x8 = i16x8::new(0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F); + let e: i16x8 = i16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let r: i16x8 = transmute(vandq_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: i16x8 = i16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let b: i16x8 = i16x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let e: i16x8 = i16x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let r: i16x8 = transmute(vandq_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vand_s32() { + let a: i32x2 = i32x2::new(0x00, 0x01); + let b: i32x2 = i32x2::new(0x0F, 0x0F); + let e: i32x2 = i32x2::new(0x00, 0x01); + let r: i32x2 = transmute(vand_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: i32x2 = i32x2::new(0x00, 0x01); + let b: i32x2 = i32x2::new(0x00, 0x00); + let e: i32x2 = i32x2::new(0x00, 0x00); + let r: i32x2 = transmute(vand_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vandq_s32() { + let a: i32x4 = i32x4::new(0x00, 0x01, 0x02, 0x03); + let b: i32x4 = i32x4::new(0x0F, 0x0F, 0x0F, 0x0F); + let e: i32x4 = i32x4::new(0x00, 0x01, 0x02, 0x03); + let r: i32x4 = transmute(vandq_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: i32x4 = i32x4::new(0x00, 0x01, 0x02, 0x03); + let b: i32x4 = i32x4::new(0x00, 0x00, 0x00, 0x00); + let e: i32x4 = i32x4::new(0x00, 0x00, 0x00, 0x00); + let r: i32x4 = transmute(vandq_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vand_u8() { + let a: u8x8 = u8x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let b: u8x8 = u8x8::new(0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F); + let e: u8x8 = u8x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let r: u8x8 = transmute(vand_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: u8x8 = u8x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let b: u8x8 = u8x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let e: u8x8 = u8x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let r: u8x8 = transmute(vand_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vandq_u8() { + let a: u8x16 = u8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x00); + let b: u8x16 = u8x16::new(0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F); + let e: u8x16 = u8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x00); + let r: u8x16 = transmute(vandq_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: u8x16 = u8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x00); + let b: u8x16 = u8x16::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let e: u8x16 = u8x16::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let r: u8x16 = transmute(vandq_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vand_u16() { + let a: u16x4 = u16x4::new(0x00, 0x01, 0x02, 0x03); + let b: u16x4 = u16x4::new(0x0F, 0x0F, 0x0F, 0x0F); + let e: u16x4 = u16x4::new(0x00, 0x01, 0x02, 0x03); + let r: u16x4 = transmute(vand_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: u16x4 = u16x4::new(0x00, 0x01, 0x02, 0x03); + let b: u16x4 = u16x4::new(0x00, 0x00, 0x00, 0x00); + let e: u16x4 = u16x4::new(0x00, 0x00, 0x00, 0x00); + let r: u16x4 = transmute(vand_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vandq_u16() { + let a: u16x8 = u16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let b: u16x8 = u16x8::new(0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F); + let e: u16x8 = u16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let r: u16x8 = transmute(vandq_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: u16x8 = u16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let b: u16x8 = u16x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let e: u16x8 = u16x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let r: u16x8 = transmute(vandq_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vand_u32() { + let a: u32x2 = u32x2::new(0x00, 0x01); + let b: u32x2 = u32x2::new(0x0F, 0x0F); + let e: u32x2 = u32x2::new(0x00, 0x01); + let r: u32x2 = transmute(vand_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: u32x2 = u32x2::new(0x00, 0x01); + let b: u32x2 = u32x2::new(0x00, 0x00); + let e: u32x2 = u32x2::new(0x00, 0x00); + let r: u32x2 = transmute(vand_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vandq_u32() { + let a: u32x4 = u32x4::new(0x00, 0x01, 0x02, 0x03); + let b: u32x4 = u32x4::new(0x0F, 0x0F, 0x0F, 0x0F); + let e: u32x4 = u32x4::new(0x00, 0x01, 0x02, 0x03); + let r: u32x4 = transmute(vandq_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: u32x4 = u32x4::new(0x00, 0x01, 0x02, 0x03); + let b: u32x4 = u32x4::new(0x00, 0x00, 0x00, 0x00); + let e: u32x4 = u32x4::new(0x00, 0x00, 0x00, 0x00); + let r: u32x4 = transmute(vandq_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vand_s64() { + let a: i64x1 = i64x1::new(0x00); + let b: i64x1 = i64x1::new(0x0F); + let e: i64x1 = i64x1::new(0x00); + let r: i64x1 = transmute(vand_s64(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: i64x1 = i64x1::new(0x00); + let b: i64x1 = i64x1::new(0x00); + let e: i64x1 = i64x1::new(0x00); + let r: i64x1 = transmute(vand_s64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vandq_s64() { + let a: i64x2 = i64x2::new(0x00, 0x01); + let b: i64x2 = i64x2::new(0x0F, 0x0F); + let e: i64x2 = i64x2::new(0x00, 0x01); + let r: i64x2 = transmute(vandq_s64(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: i64x2 = i64x2::new(0x00, 0x01); + let b: i64x2 = i64x2::new(0x00, 0x00); + let e: i64x2 = i64x2::new(0x00, 0x00); + let r: i64x2 = transmute(vandq_s64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vand_u64() { + let a: u64x1 = u64x1::new(0x00); + let b: u64x1 = u64x1::new(0x0F); + let e: u64x1 = u64x1::new(0x00); + let r: u64x1 = transmute(vand_u64(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: u64x1 = u64x1::new(0x00); + let b: u64x1 = u64x1::new(0x00); + let e: u64x1 = u64x1::new(0x00); + let r: u64x1 = transmute(vand_u64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vandq_u64() { + let a: u64x2 = u64x2::new(0x00, 0x01); + let b: u64x2 = u64x2::new(0x0F, 0x0F); + let e: u64x2 = u64x2::new(0x00, 0x01); + let r: u64x2 = transmute(vandq_u64(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: u64x2 = u64x2::new(0x00, 0x01); + let b: u64x2 = u64x2::new(0x00, 0x00); + let e: u64x2 = u64x2::new(0x00, 0x00); + let r: u64x2 = transmute(vandq_u64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vorr_s8() { + let a: i8x8 = i8x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let b: i8x8 = i8x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let e: i8x8 = i8x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let r: i8x8 = transmute(vorr_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vorrq_s8() { + let a: i8x16 = i8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F); + let b: i8x16 = i8x16::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let e: i8x16 = i8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F); + let r: i8x16 = transmute(vorrq_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vorr_s16() { + let a: i16x4 = i16x4::new(0x00, 0x01, 0x02, 0x03); + let b: i16x4 = i16x4::new(0x00, 0x00, 0x00, 0x00); + let e: i16x4 = i16x4::new(0x00, 0x01, 0x02, 0x03); + let r: i16x4 = transmute(vorr_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vorrq_s16() { + let a: i16x8 = i16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let b: i16x8 = i16x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let e: i16x8 = i16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let r: i16x8 = transmute(vorrq_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vorr_s32() { + let a: i32x2 = i32x2::new(0x00, 0x01); + let b: i32x2 = i32x2::new(0x00, 0x00); + let e: i32x2 = i32x2::new(0x00, 0x01); + let r: i32x2 = transmute(vorr_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vorrq_s32() { + let a: i32x4 = i32x4::new(0x00, 0x01, 0x02, 0x03); + let b: i32x4 = i32x4::new(0x00, 0x00, 0x00, 0x00); + let e: i32x4 = i32x4::new(0x00, 0x01, 0x02, 0x03); + let r: i32x4 = transmute(vorrq_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vorr_u8() { + let a: u8x8 = u8x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let b: u8x8 = u8x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let e: u8x8 = u8x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let r: u8x8 = transmute(vorr_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vorrq_u8() { + let a: u8x16 = u8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F); + let b: u8x16 = u8x16::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let e: u8x16 = u8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F); + let r: u8x16 = transmute(vorrq_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vorr_u16() { + let a: u16x4 = u16x4::new(0x00, 0x01, 0x02, 0x03); + let b: u16x4 = u16x4::new(0x00, 0x00, 0x00, 0x00); + let e: u16x4 = u16x4::new(0x00, 0x01, 0x02, 0x03); + let r: u16x4 = transmute(vorr_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vorrq_u16() { + let a: u16x8 = u16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let b: u16x8 = u16x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let e: u16x8 = u16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let r: u16x8 = transmute(vorrq_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vorr_u32() { + let a: u32x2 = u32x2::new(0x00, 0x01); + let b: u32x2 = u32x2::new(0x00, 0x00); + let e: u32x2 = u32x2::new(0x00, 0x01); + let r: u32x2 = transmute(vorr_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vorrq_u32() { + let a: u32x4 = u32x4::new(0x00, 0x01, 0x02, 0x03); + let b: u32x4 = u32x4::new(0x00, 0x00, 0x00, 0x00); + let e: u32x4 = u32x4::new(0x00, 0x01, 0x02, 0x03); + let r: u32x4 = transmute(vorrq_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vorr_s64() { + let a: i64x1 = i64x1::new(0x00); + let b: i64x1 = i64x1::new(0x00); + let e: i64x1 = i64x1::new(0x00); + let r: i64x1 = transmute(vorr_s64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vorrq_s64() { + let a: i64x2 = i64x2::new(0x00, 0x01); + let b: i64x2 = i64x2::new(0x00, 0x00); + let e: i64x2 = i64x2::new(0x00, 0x01); + let r: i64x2 = transmute(vorrq_s64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vorr_u64() { + let a: u64x1 = u64x1::new(0x00); + let b: u64x1 = u64x1::new(0x00); + let e: u64x1 = u64x1::new(0x00); + let r: u64x1 = transmute(vorr_u64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vorrq_u64() { + let a: u64x2 = u64x2::new(0x00, 0x01); + let b: u64x2 = u64x2::new(0x00, 0x00); + let e: u64x2 = u64x2::new(0x00, 0x01); + let r: u64x2 = transmute(vorrq_u64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_veor_s8() { + let a: i8x8 = i8x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let b: i8x8 = i8x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let e: i8x8 = i8x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let r: i8x8 = transmute(veor_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_veorq_s8() { + let a: i8x16 = i8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F); + let b: i8x16 = i8x16::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let e: i8x16 = i8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F); + let r: i8x16 = transmute(veorq_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_veor_s16() { + let a: i16x4 = i16x4::new(0x00, 0x01, 0x02, 0x03); + let b: i16x4 = i16x4::new(0x00, 0x00, 0x00, 0x00); + let e: i16x4 = i16x4::new(0x00, 0x01, 0x02, 0x03); + let r: i16x4 = transmute(veor_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_veorq_s16() { + let a: i16x8 = i16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let b: i16x8 = i16x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let e: i16x8 = i16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let r: i16x8 = transmute(veorq_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_veor_s32() { + let a: i32x2 = i32x2::new(0x00, 0x01); + let b: i32x2 = i32x2::new(0x00, 0x00); + let e: i32x2 = i32x2::new(0x00, 0x01); + let r: i32x2 = transmute(veor_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_veorq_s32() { + let a: i32x4 = i32x4::new(0x00, 0x01, 0x02, 0x03); + let b: i32x4 = i32x4::new(0x00, 0x00, 0x00, 0x00); + let e: i32x4 = i32x4::new(0x00, 0x01, 0x02, 0x03); + let r: i32x4 = transmute(veorq_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_veor_u8() { + let a: u8x8 = u8x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let b: u8x8 = u8x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let e: u8x8 = u8x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let r: u8x8 = transmute(veor_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_veorq_u8() { + let a: u8x16 = u8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F); + let b: u8x16 = u8x16::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let e: u8x16 = u8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F); + let r: u8x16 = transmute(veorq_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_veor_u16() { + let a: u16x4 = u16x4::new(0x00, 0x01, 0x02, 0x03); + let b: u16x4 = u16x4::new(0x00, 0x00, 0x00, 0x00); + let e: u16x4 = u16x4::new(0x00, 0x01, 0x02, 0x03); + let r: u16x4 = transmute(veor_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_veorq_u16() { + let a: u16x8 = u16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let b: u16x8 = u16x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let e: u16x8 = u16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let r: u16x8 = transmute(veorq_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_veor_u32() { + let a: u32x2 = u32x2::new(0x00, 0x01); + let b: u32x2 = u32x2::new(0x00, 0x00); + let e: u32x2 = u32x2::new(0x00, 0x01); + let r: u32x2 = transmute(veor_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_veorq_u32() { + let a: u32x4 = u32x4::new(0x00, 0x01, 0x02, 0x03); + let b: u32x4 = u32x4::new(0x00, 0x00, 0x00, 0x00); + let e: u32x4 = u32x4::new(0x00, 0x01, 0x02, 0x03); + let r: u32x4 = transmute(veorq_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_veor_s64() { + let a: i64x1 = i64x1::new(0x00); + let b: i64x1 = i64x1::new(0x00); + let e: i64x1 = i64x1::new(0x00); + let r: i64x1 = transmute(veor_s64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_veorq_s64() { + let a: i64x2 = i64x2::new(0x00, 0x01); + let b: i64x2 = i64x2::new(0x00, 0x00); + let e: i64x2 = i64x2::new(0x00, 0x01); + let r: i64x2 = transmute(veorq_s64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_veor_u64() { + let a: u64x1 = u64x1::new(0x00); + let b: u64x1 = u64x1::new(0x00); + let e: u64x1 = u64x1::new(0x00); + let r: u64x1 = transmute(veor_u64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_veorq_u64() { + let a: u64x2 = u64x2::new(0x00, 0x01); + let b: u64x2 = u64x2::new(0x00, 0x00); + let e: u64x2 = u64x2::new(0x00, 0x01); + let r: u64x2 = transmute(veorq_u64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabd_s8() { + let a: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let b: i8x8 = i8x8::new(16, 15, 14, 13, 12, 11, 10, 9); + let e: i8x8 = i8x8::new(15, 13, 11, 9, 7, 5, 3, 1); + let r: i8x8 = transmute(vabd_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabdq_s8() { + let a: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let b: i8x16 = i8x16::new(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); + let e: i8x16 = i8x16::new(15, 13, 11, 9, 7, 5, 3, 1, 1, 3, 5, 7, 9, 11, 13, 15); + let r: i8x16 = transmute(vabdq_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabd_s16() { + let a: i16x4 = i16x4::new(1, 2, 3, 4); + let b: i16x4 = i16x4::new(16, 15, 14, 13); + let e: i16x4 = i16x4::new(15, 13, 11, 9); + let r: i16x4 = transmute(vabd_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabdq_s16() { + let a: i16x8 = i16x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let b: i16x8 = i16x8::new(16, 15, 14, 13, 12, 11, 10, 9); + let e: i16x8 = i16x8::new(15, 13, 11, 9, 7, 5, 3, 1); + let r: i16x8 = transmute(vabdq_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabd_s32() { + let a: i32x2 = i32x2::new(1, 2); + let b: i32x2 = i32x2::new(16, 15); + let e: i32x2 = i32x2::new(15, 13); + let r: i32x2 = transmute(vabd_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabdq_s32() { + let a: i32x4 = i32x4::new(1, 2, 3, 4); + let b: i32x4 = i32x4::new(16, 15, 14, 13); + let e: i32x4 = i32x4::new(15, 13, 11, 9); + let r: i32x4 = transmute(vabdq_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabd_u8() { + let a: u8x8 = u8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let b: u8x8 = u8x8::new(16, 15, 14, 13, 12, 11, 10, 9); + let e: u8x8 = u8x8::new(15, 13, 11, 9, 7, 5, 3, 1); + let r: u8x8 = transmute(vabd_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabdq_u8() { + let a: u8x16 = u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let b: u8x16 = u8x16::new(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); + let e: u8x16 = u8x16::new(15, 13, 11, 9, 7, 5, 3, 1, 1, 3, 5, 7, 9, 11, 13, 15); + let r: u8x16 = transmute(vabdq_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabd_u16() { + let a: u16x4 = u16x4::new(1, 2, 3, 4); + let b: u16x4 = u16x4::new(16, 15, 14, 13); + let e: u16x4 = u16x4::new(15, 13, 11, 9); + let r: u16x4 = transmute(vabd_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabdq_u16() { + let a: u16x8 = u16x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let b: u16x8 = u16x8::new(16, 15, 14, 13, 12, 11, 10, 9); + let e: u16x8 = u16x8::new(15, 13, 11, 9, 7, 5, 3, 1); + let r: u16x8 = transmute(vabdq_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabd_u32() { + let a: u32x2 = u32x2::new(1, 2); + let b: u32x2 = u32x2::new(16, 15); + let e: u32x2 = u32x2::new(15, 13); + let r: u32x2 = transmute(vabd_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabdq_u32() { + let a: u32x4 = u32x4::new(1, 2, 3, 4); + let b: u32x4 = u32x4::new(16, 15, 14, 13); + let e: u32x4 = u32x4::new(15, 13, 11, 9); + let r: u32x4 = transmute(vabdq_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabd_f32() { + let a: f32x2 = f32x2::new(1.0, 2.0); + let b: f32x2 = f32x2::new(9.0, 3.0); + let e: f32x2 = f32x2::new(8.0, 1.0); + let r: f32x2 = transmute(vabd_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabdq_f32() { + let a: f32x4 = f32x4::new(1.0, 2.0, 5.0, -4.0); + let b: f32x4 = f32x4::new(9.0, 3.0, 2.0, 8.0); + let e: f32x4 = f32x4::new(8.0, 1.0, 3.0, 12.0); + let r: f32x4 = transmute(vabdq_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabdl_u8() { + let a: u8x8 = u8x8::new(1, 2, 3, 4, 4, 3, 2, 1); + let b: u8x8 = u8x8::new(10, 10, 10, 10, 10, 10, 10, 10); + let e: u16x8 = u16x8::new(9, 8, 7, 6, 6, 7, 8, 9); + let r: u16x8 = transmute(vabdl_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabdl_u16() { + let a: u16x4 = u16x4::new(1, 2, 3, 4); + let b: u16x4 = u16x4::new(10, 10, 10, 10); + let e: u32x4 = u32x4::new(9, 8, 7, 6); + let r: u32x4 = transmute(vabdl_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabdl_u32() { + let a: u32x2 = u32x2::new(1, 2); + let b: u32x2 = u32x2::new(10, 10); + let e: u64x2 = u64x2::new(9, 8); + let r: u64x2 = transmute(vabdl_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabdl_s8() { + let a: i8x8 = i8x8::new(1, 2, 3, 4, 4, 3, 2, 1); + let b: i8x8 = i8x8::new(10, 10, 10, 10, 10, 10, 10, 10); + let e: i16x8 = i16x8::new(9, 8, 7, 6, 6, 7, 8, 9); + let r: i16x8 = transmute(vabdl_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabdl_s16() { + let a: i16x4 = i16x4::new(1, 2, 11, 12); + let b: i16x4 = i16x4::new(10, 10, 10, 10); + let e: i32x4 = i32x4::new(9, 8, 1, 2); + let r: i32x4 = transmute(vabdl_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabdl_s32() { + let a: i32x2 = i32x2::new(1, 11); + let b: i32x2 = i32x2::new(10, 10); + let e: i64x2 = i64x2::new(9, 1); + let r: i64x2 = transmute(vabdl_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceq_u8() { + let a: u8x8 = u8x8::new(0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let b: u8x8 = u8x8::new(0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let e: u8x8 = u8x8::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x8 = transmute(vceq_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: u8x8 = u8x8::new(0, 0, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let b: u8x8 = u8x8::new(0, 0xFF, 0x02, 0x04, 0x04, 0x00, 0x06, 0x08); + let e: u8x8 = u8x8::new(0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0); + let r: u8x8 = transmute(vceq_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqq_u8() { + let a: u8x16 = u8x16::new(0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0xFF); + let b: u8x16 = u8x16::new(0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0xFF); + let e: u8x16 = u8x16::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x16 = transmute(vceqq_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: u8x16 = u8x16::new(0, 0, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0xCC, 0x0D, 0xEE, 0xFF); + let b: u8x16 = u8x16::new(0, 0xFF, 0x02, 0x04, 0x04, 0x00, 0x06, 0x08, 0x08, 0x00, 0x0A, 0x0A, 0xCC, 0xD0, 0xEE, 0); + let e: u8x16 = u8x16::new(0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0); + let r: u8x16 = transmute(vceqq_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceq_u16() { + let a: u16x4 = u16x4::new(0, 0x01, 0x02, 0x03); + let b: u16x4 = u16x4::new(0, 0x01, 0x02, 0x03); + let e: u16x4 = u16x4::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); + let r: u16x4 = transmute(vceq_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: u16x4 = u16x4::new(0, 0, 0x02, 0x03); + let b: u16x4 = u16x4::new(0, 0xFF_FF, 0x02, 0x04); + let e: u16x4 = u16x4::new(0xFF_FF, 0, 0xFF_FF, 0); + let r: u16x4 = transmute(vceq_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqq_u16() { + let a: u16x8 = u16x8::new(0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let b: u16x8 = u16x8::new(0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let e: u16x8 = u16x8::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); + let r: u16x8 = transmute(vceqq_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: u16x8 = u16x8::new(0, 0, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let b: u16x8 = u16x8::new(0, 0xFF_FF, 0x02, 0x04, 0x04, 0x00, 0x06, 0x08); + let e: u16x8 = u16x8::new(0xFF_FF, 0, 0xFF_FF, 0, 0xFF_FF, 0, 0xFF_FF, 0); + let r: u16x8 = transmute(vceqq_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceq_u32() { + let a: u32x2 = u32x2::new(0, 0x01); + let b: u32x2 = u32x2::new(0, 0x01); + let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x2 = transmute(vceq_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: u32x2 = u32x2::new(0, 0); + let b: u32x2 = u32x2::new(0, 0xFF_FF_FF_FF); + let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0); + let r: u32x2 = transmute(vceq_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqq_u32() { + let a: u32x4 = u32x4::new(0, 0x01, 0x02, 0x03); + let b: u32x4 = u32x4::new(0, 0x01, 0x02, 0x03); + let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x4 = transmute(vceqq_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: u32x4 = u32x4::new(0, 0, 0x02, 0x03); + let b: u32x4 = u32x4::new(0, 0xFF_FF_FF_FF, 0x02, 0x04); + let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0, 0xFF_FF_FF_FF, 0); + let r: u32x4 = transmute(vceqq_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceq_s8() { + let a: i8x8 = i8x8::new(-128, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let b: i8x8 = i8x8::new(-128, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let e: u8x8 = u8x8::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x8 = transmute(vceq_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: i8x8 = i8x8::new(-128, -128, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let b: i8x8 = i8x8::new(-128, 0x7F, 0x02, 0x04, 0x04, 0x00, 0x06, 0x08); + let e: u8x8 = u8x8::new(0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0); + let r: u8x8 = transmute(vceq_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqq_s8() { + let a: i8x16 = i8x16::new(-128, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x7F); + let b: i8x16 = i8x16::new(-128, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x7F); + let e: u8x16 = u8x16::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x16 = transmute(vceqq_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: i8x16 = i8x16::new(-128, -128, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0xCC, 0x0D, 0xEE, 0x7F); + let b: i8x16 = i8x16::new(-128, 0x7F, 0x02, 0x04, 0x04, 0x00, 0x06, 0x08, 0x08, 0x00, 0x0A, 0x0A, 0xCC, 0xD0, 0xEE, -128); + let e: u8x16 = u8x16::new(0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0); + let r: u8x16 = transmute(vceqq_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceq_s16() { + let a: i16x4 = i16x4::new(-32768, 0x01, 0x02, 0x03); + let b: i16x4 = i16x4::new(-32768, 0x01, 0x02, 0x03); + let e: u16x4 = u16x4::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); + let r: u16x4 = transmute(vceq_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: i16x4 = i16x4::new(-32768, -32768, 0x02, 0x03); + let b: i16x4 = i16x4::new(-32768, 0x7F_FF, 0x02, 0x04); + let e: u16x4 = u16x4::new(0xFF_FF, 0, 0xFF_FF, 0); + let r: u16x4 = transmute(vceq_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqq_s16() { + let a: i16x8 = i16x8::new(-32768, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let b: i16x8 = i16x8::new(-32768, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let e: u16x8 = u16x8::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); + let r: u16x8 = transmute(vceqq_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: i16x8 = i16x8::new(-32768, -32768, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let b: i16x8 = i16x8::new(-32768, 0x7F_FF, 0x02, 0x04, 0x04, 0x00, 0x06, 0x08); + let e: u16x8 = u16x8::new(0xFF_FF, 0, 0xFF_FF, 0, 0xFF_FF, 0, 0xFF_FF, 0); + let r: u16x8 = transmute(vceqq_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceq_s32() { + let a: i32x2 = i32x2::new(-2147483648, 0x01); + let b: i32x2 = i32x2::new(-2147483648, 0x01); + let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x2 = transmute(vceq_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: i32x2 = i32x2::new(-2147483648, -2147483648); + let b: i32x2 = i32x2::new(-2147483648, 0x7F_FF_FF_FF); + let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0); + let r: u32x2 = transmute(vceq_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqq_s32() { + let a: i32x4 = i32x4::new(-2147483648, 0x01, 0x02, 0x03); + let b: i32x4 = i32x4::new(-2147483648, 0x01, 0x02, 0x03); + let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x4 = transmute(vceqq_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: i32x4 = i32x4::new(-2147483648, -2147483648, 0x02, 0x03); + let b: i32x4 = i32x4::new(-2147483648, 0x7F_FF_FF_FF, 0x02, 0x04); + let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0, 0xFF_FF_FF_FF, 0); + let r: u32x4 = transmute(vceqq_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceq_p8() { + let a: i8x8 = i8x8::new(-128, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let b: i8x8 = i8x8::new(-128, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let e: u8x8 = u8x8::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x8 = transmute(vceq_p8(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: i8x8 = i8x8::new(-128, -128, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + let b: i8x8 = i8x8::new(-128, 0x7F, 0x02, 0x04, 0x04, 0x00, 0x06, 0x08); + let e: u8x8 = u8x8::new(0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0); + let r: u8x8 = transmute(vceq_p8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqq_p8() { + let a: i8x16 = i8x16::new(-128, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x7F); + let b: i8x16 = i8x16::new(-128, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x7F); + let e: u8x16 = u8x16::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x16 = transmute(vceqq_p8(transmute(a), transmute(b))); + assert_eq!(r, e); + + let a: i8x16 = i8x16::new(-128, -128, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0xCC, 0x0D, 0xEE, 0x7F); + let b: i8x16 = i8x16::new(-128, 0x7F, 0x02, 0x04, 0x04, 0x00, 0x06, 0x08, 0x08, 0x00, 0x0A, 0x0A, 0xCC, 0xD0, 0xEE, -128); + let e: u8x16 = u8x16::new(0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0); + let r: u8x16 = transmute(vceqq_p8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceq_f32() { + let a: f32x2 = f32x2::new(1.2, 3.4); + let b: f32x2 = f32x2::new(1.2, 3.4); + let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x2 = transmute(vceq_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vceqq_f32() { + let a: f32x4 = f32x4::new(1.2, 3.4, 5.6, 7.8); + let b: f32x4 = f32x4::new(1.2, 3.4, 5.6, 7.8); + let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x4 = transmute(vceqq_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtst_s8() { + let a: i8x8 = i8x8::new(-128, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); + let b: i8x8 = i8x8::new(-128, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); + let e: u8x8 = u8x8::new(0xFF, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x8 = transmute(vtst_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtstq_s8() { + let a: i8x16 = i8x16::new(-128, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x7F); + let b: i8x16 = i8x16::new(-128, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x7F); + let e: u8x16 = u8x16::new(0xFF, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x16 = transmute(vtstq_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtst_s16() { + let a: i16x4 = i16x4::new(-32768, 0x00, 0x01, 0x02); + let b: i16x4 = i16x4::new(-32768, 0x00, 0x01, 0x02); + let e: u16x4 = u16x4::new(0xFF_FF, 0, 0xFF_FF, 0xFF_FF); + let r: u16x4 = transmute(vtst_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtstq_s16() { + let a: i16x8 = i16x8::new(-32768, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); + let b: i16x8 = i16x8::new(-32768, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); + let e: u16x8 = u16x8::new(0xFF_FF, 0, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); + let r: u16x8 = transmute(vtstq_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtst_s32() { + let a: i32x2 = i32x2::new(-2147483648, 0x00); + let b: i32x2 = i32x2::new(-2147483648, 0x00); + let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0); + let r: u32x2 = transmute(vtst_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtstq_s32() { + let a: i32x4 = i32x4::new(-2147483648, 0x00, 0x01, 0x02); + let b: i32x4 = i32x4::new(-2147483648, 0x00, 0x01, 0x02); + let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x4 = transmute(vtstq_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtst_p8() { + let a: i8x8 = i8x8::new(-128, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); + let b: i8x8 = i8x8::new(-128, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); + let e: u8x8 = u8x8::new(0xFF, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x8 = transmute(vtst_p8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtstq_p8() { + let a: i8x16 = i8x16::new(-128, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x7F); + let b: i8x16 = i8x16::new(-128, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x7F); + let e: u8x16 = u8x16::new(0xFF, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x16 = transmute(vtstq_p8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtst_u8() { + let a: u8x8 = u8x8::new(0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); + let b: u8x8 = u8x8::new(0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); + let e: u8x8 = u8x8::new(0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x8 = transmute(vtst_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtstq_u8() { + let a: u8x16 = u8x16::new(0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0xFF); + let b: u8x16 = u8x16::new(0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0xFF); + let e: u8x16 = u8x16::new(0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x16 = transmute(vtstq_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtst_u16() { + let a: u16x4 = u16x4::new(0, 0x00, 0x01, 0x02); + let b: u16x4 = u16x4::new(0, 0x00, 0x01, 0x02); + let e: u16x4 = u16x4::new(0, 0, 0xFF_FF, 0xFF_FF); + let r: u16x4 = transmute(vtst_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtstq_u16() { + let a: u16x8 = u16x8::new(0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); + let b: u16x8 = u16x8::new(0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); + let e: u16x8 = u16x8::new(0, 0, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); + let r: u16x8 = transmute(vtstq_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtst_u32() { + let a: u32x2 = u32x2::new(0, 0x00); + let b: u32x2 = u32x2::new(0, 0x00); + let e: u32x2 = u32x2::new(0, 0); + let r: u32x2 = transmute(vtst_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtstq_u32() { + let a: u32x4 = u32x4::new(0, 0x00, 0x01, 0x02); + let b: u32x4 = u32x4::new(0, 0x00, 0x01, 0x02); + let e: u32x4 = u32x4::new(0, 0, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x4 = transmute(vtstq_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabs_f32() { + let a: f32x2 = f32x2::new(-0.1, -2.2); + let e: f32x2 = f32x2::new(0.1, 2.2); + let r: f32x2 = transmute(vabs_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabsq_f32() { + let a: f32x4 = f32x4::new(-0.1, -2.2, -3.3, -6.6); + let e: f32x4 = f32x4::new(0.1, 2.2, 3.3, 6.6); + let r: f32x4 = transmute(vabsq_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgt_s8() { + let a: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let b: i8x8 = i8x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let e: u8x8 = u8x8::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x8 = transmute(vcgt_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgtq_s8() { + let a: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let b: i8x16 = i8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let e: u8x16 = u8x16::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x16 = transmute(vcgtq_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgt_s16() { + let a: i16x4 = i16x4::new(1, 2, 3, 4); + let b: i16x4 = i16x4::new(0, 1, 2, 3); + let e: u16x4 = u16x4::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); + let r: u16x4 = transmute(vcgt_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgtq_s16() { + let a: i16x8 = i16x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let b: i16x8 = i16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let e: u16x8 = u16x8::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); + let r: u16x8 = transmute(vcgtq_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgt_s32() { + let a: i32x2 = i32x2::new(1, 2); + let b: i32x2 = i32x2::new(0, 1); + let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x2 = transmute(vcgt_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgtq_s32() { + let a: i32x4 = i32x4::new(1, 2, 3, 4); + let b: i32x4 = i32x4::new(0, 1, 2, 3); + let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x4 = transmute(vcgtq_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgt_u8() { + let a: u8x8 = u8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let b: u8x8 = u8x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let e: u8x8 = u8x8::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x8 = transmute(vcgt_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgtq_u8() { + let a: u8x16 = u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let b: u8x16 = u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let e: u8x16 = u8x16::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x16 = transmute(vcgtq_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgt_u16() { + let a: u16x4 = u16x4::new(1, 2, 3, 4); + let b: u16x4 = u16x4::new(0, 1, 2, 3); + let e: u16x4 = u16x4::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); + let r: u16x4 = transmute(vcgt_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgtq_u16() { + let a: u16x8 = u16x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let b: u16x8 = u16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let e: u16x8 = u16x8::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); + let r: u16x8 = transmute(vcgtq_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgt_u32() { + let a: u32x2 = u32x2::new(1, 2); + let b: u32x2 = u32x2::new(0, 1); + let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x2 = transmute(vcgt_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgtq_u32() { + let a: u32x4 = u32x4::new(1, 2, 3, 4); + let b: u32x4 = u32x4::new(0, 1, 2, 3); + let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x4 = transmute(vcgtq_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgt_f32() { + let a: f32x2 = f32x2::new(1.2, 2.3); + let b: f32x2 = f32x2::new(0.1, 1.2); + let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x2 = transmute(vcgt_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgtq_f32() { + let a: f32x4 = f32x4::new(1.2, 2.3, 3.4, 4.5); + let b: f32x4 = f32x4::new(0.1, 1.2, 2.3, 3.4); + let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x4 = transmute(vcgtq_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclt_s8() { + let a: i8x8 = i8x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let b: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let e: u8x8 = u8x8::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x8 = transmute(vclt_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcltq_s8() { + let a: i8x16 = i8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let b: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let e: u8x16 = u8x16::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x16 = transmute(vcltq_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclt_s16() { + let a: i16x4 = i16x4::new(0, 1, 2, 3); + let b: i16x4 = i16x4::new(1, 2, 3, 4); + let e: u16x4 = u16x4::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); + let r: u16x4 = transmute(vclt_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcltq_s16() { + let a: i16x8 = i16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let b: i16x8 = i16x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let e: u16x8 = u16x8::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); + let r: u16x8 = transmute(vcltq_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclt_s32() { + let a: i32x2 = i32x2::new(0, 1); + let b: i32x2 = i32x2::new(1, 2); + let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x2 = transmute(vclt_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcltq_s32() { + let a: i32x4 = i32x4::new(0, 1, 2, 3); + let b: i32x4 = i32x4::new(1, 2, 3, 4); + let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x4 = transmute(vcltq_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclt_u8() { + let a: u8x8 = u8x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let b: u8x8 = u8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let e: u8x8 = u8x8::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x8 = transmute(vclt_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcltq_u8() { + let a: u8x16 = u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let b: u8x16 = u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let e: u8x16 = u8x16::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x16 = transmute(vcltq_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclt_u16() { + let a: u16x4 = u16x4::new(0, 1, 2, 3); + let b: u16x4 = u16x4::new(1, 2, 3, 4); + let e: u16x4 = u16x4::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); + let r: u16x4 = transmute(vclt_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcltq_u16() { + let a: u16x8 = u16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let b: u16x8 = u16x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let e: u16x8 = u16x8::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); + let r: u16x8 = transmute(vcltq_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclt_u32() { + let a: u32x2 = u32x2::new(0, 1); + let b: u32x2 = u32x2::new(1, 2); + let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x2 = transmute(vclt_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcltq_u32() { + let a: u32x4 = u32x4::new(0, 1, 2, 3); + let b: u32x4 = u32x4::new(1, 2, 3, 4); + let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x4 = transmute(vcltq_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclt_f32() { + let a: f32x2 = f32x2::new(0.1, 1.2); + let b: f32x2 = f32x2::new(1.2, 2.3); + let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x2 = transmute(vclt_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcltq_f32() { + let a: f32x4 = f32x4::new(0.1, 1.2, 2.3, 3.4); + let b: f32x4 = f32x4::new(1.2, 2.3, 3.4, 4.5); + let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x4 = transmute(vcltq_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcle_s8() { + let a: i8x8 = i8x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let b: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let e: u8x8 = u8x8::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x8 = transmute(vcle_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcleq_s8() { + let a: i8x16 = i8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let b: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let e: u8x16 = u8x16::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x16 = transmute(vcleq_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcle_s16() { + let a: i16x4 = i16x4::new(0, 1, 2, 3); + let b: i16x4 = i16x4::new(1, 2, 3, 4); + let e: u16x4 = u16x4::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); + let r: u16x4 = transmute(vcle_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcleq_s16() { + let a: i16x8 = i16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let b: i16x8 = i16x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let e: u16x8 = u16x8::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); + let r: u16x8 = transmute(vcleq_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcle_s32() { + let a: i32x2 = i32x2::new(0, 1); + let b: i32x2 = i32x2::new(1, 2); + let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x2 = transmute(vcle_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcleq_s32() { + let a: i32x4 = i32x4::new(0, 1, 2, 3); + let b: i32x4 = i32x4::new(1, 2, 3, 4); + let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x4 = transmute(vcleq_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcle_u8() { + let a: u8x8 = u8x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let b: u8x8 = u8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let e: u8x8 = u8x8::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x8 = transmute(vcle_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcleq_u8() { + let a: u8x16 = u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let b: u8x16 = u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let e: u8x16 = u8x16::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x16 = transmute(vcleq_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcle_u16() { + let a: u16x4 = u16x4::new(0, 1, 2, 3); + let b: u16x4 = u16x4::new(1, 2, 3, 4); + let e: u16x4 = u16x4::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); + let r: u16x4 = transmute(vcle_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcleq_u16() { + let a: u16x8 = u16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let b: u16x8 = u16x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let e: u16x8 = u16x8::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); + let r: u16x8 = transmute(vcleq_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcle_u32() { + let a: u32x2 = u32x2::new(0, 1); + let b: u32x2 = u32x2::new(1, 2); + let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x2 = transmute(vcle_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcleq_u32() { + let a: u32x4 = u32x4::new(0, 1, 2, 3); + let b: u32x4 = u32x4::new(1, 2, 3, 4); + let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x4 = transmute(vcleq_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcle_f32() { + let a: f32x2 = f32x2::new(0.1, 1.2); + let b: f32x2 = f32x2::new(1.2, 2.3); + let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x2 = transmute(vcle_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcleq_f32() { + let a: f32x4 = f32x4::new(0.1, 1.2, 2.3, 3.4); + let b: f32x4 = f32x4::new(1.2, 2.3, 3.4, 4.5); + let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x4 = transmute(vcleq_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcge_s8() { + let a: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let b: i8x8 = i8x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let e: u8x8 = u8x8::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x8 = transmute(vcge_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgeq_s8() { + let a: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let b: i8x16 = i8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let e: u8x16 = u8x16::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x16 = transmute(vcgeq_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcge_s16() { + let a: i16x4 = i16x4::new(1, 2, 3, 4); + let b: i16x4 = i16x4::new(0, 1, 2, 3); + let e: u16x4 = u16x4::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); + let r: u16x4 = transmute(vcge_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgeq_s16() { + let a: i16x8 = i16x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let b: i16x8 = i16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let e: u16x8 = u16x8::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); + let r: u16x8 = transmute(vcgeq_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcge_s32() { + let a: i32x2 = i32x2::new(1, 2); + let b: i32x2 = i32x2::new(0, 1); + let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x2 = transmute(vcge_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgeq_s32() { + let a: i32x4 = i32x4::new(1, 2, 3, 4); + let b: i32x4 = i32x4::new(0, 1, 2, 3); + let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x4 = transmute(vcgeq_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcge_u8() { + let a: u8x8 = u8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let b: u8x8 = u8x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let e: u8x8 = u8x8::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x8 = transmute(vcge_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgeq_u8() { + let a: u8x16 = u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let b: u8x16 = u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let e: u8x16 = u8x16::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let r: u8x16 = transmute(vcgeq_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcge_u16() { + let a: u16x4 = u16x4::new(1, 2, 3, 4); + let b: u16x4 = u16x4::new(0, 1, 2, 3); + let e: u16x4 = u16x4::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); + let r: u16x4 = transmute(vcge_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgeq_u16() { + let a: u16x8 = u16x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let b: u16x8 = u16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let e: u16x8 = u16x8::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); + let r: u16x8 = transmute(vcgeq_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcge_u32() { + let a: u32x2 = u32x2::new(1, 2); + let b: u32x2 = u32x2::new(0, 1); + let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x2 = transmute(vcge_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgeq_u32() { + let a: u32x4 = u32x4::new(1, 2, 3, 4); + let b: u32x4 = u32x4::new(0, 1, 2, 3); + let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x4 = transmute(vcgeq_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcge_f32() { + let a: f32x2 = f32x2::new(1.2, 2.3); + let b: f32x2 = f32x2::new(0.1, 1.2); + let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x2 = transmute(vcge_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcgeq_f32() { + let a: f32x4 = f32x4::new(1.2, 2.3, 3.4, 4.5); + let b: f32x4 = f32x4::new(0.1, 1.2, 2.3, 3.4); + let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); + let r: u32x4 = transmute(vcgeq_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcls_s8() { + let a: i8x8 = i8x8::new(-128, -1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let e: i8x8 = i8x8::new(0, 7, 7, 7, 7, 7, 7, 7); + let r: i8x8 = transmute(vcls_s8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclsq_s8() { + let a: i8x16 = i8x16::new(-128, -1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F); + let e: i8x16 = i8x16::new(0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0); + let r: i8x16 = transmute(vclsq_s8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcls_s16() { + let a: i16x4 = i16x4::new(-32768, -1, 0x00, 0x00); + let e: i16x4 = i16x4::new(0, 15, 15, 15); + let r: i16x4 = transmute(vcls_s16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclsq_s16() { + let a: i16x8 = i16x8::new(-32768, -1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let e: i16x8 = i16x8::new(0, 15, 15, 15, 15, 15, 15, 15); + let r: i16x8 = transmute(vclsq_s16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcls_s32() { + let a: i32x2 = i32x2::new(-2147483648, -1); + let e: i32x2 = i32x2::new(0, 31); + let r: i32x2 = transmute(vcls_s32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclsq_s32() { + let a: i32x4 = i32x4::new(-2147483648, -1, 0x00, 0x00); + let e: i32x4 = i32x4::new(0, 31, 31, 31); + let r: i32x4 = transmute(vclsq_s32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcls_u8() { + let a: u8x8 = u8x8::new(0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let e: u8x8 = u8x8::new(7, 7, 7, 7, 7, 7, 7, 7); + let r: u8x8 = transmute(vcls_u8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclsq_u8() { + let a: u8x16 = u8x16::new(0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF); + let e: u8x16 = u8x16::new(7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7); + let r: u8x16 = transmute(vclsq_u8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcls_u16() { + let a: u16x4 = u16x4::new(0, 0xFF_FF, 0x00, 0x00); + let e: u16x4 = u16x4::new(15, 15, 15, 15); + let r: u16x4 = transmute(vcls_u16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclsq_u16() { + let a: u16x8 = u16x8::new(0, 0xFF_FF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + let e: u16x8 = u16x8::new(15, 15, 15, 15, 15, 15, 15, 15); + let r: u16x8 = transmute(vclsq_u16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcls_u32() { + let a: u32x2 = u32x2::new(0, 0xFF_FF_FF_FF); + let e: u32x2 = u32x2::new(31, 31); + let r: u32x2 = transmute(vcls_u32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclsq_u32() { + let a: u32x4 = u32x4::new(0, 0xFF_FF_FF_FF, 0x00, 0x00); + let e: u32x4 = u32x4::new(31, 31, 31, 31); + let r: u32x4 = transmute(vclsq_u32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclz_s8() { + let a: i8x8 = i8x8::new(-128, -1, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01); + let e: i8x8 = i8x8::new(0, 0, 8, 7, 7, 7, 7, 7); + let r: i8x8 = transmute(vclz_s8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclzq_s8() { + let a: i8x16 = i8x16::new(-128, -1, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x7F); + let e: i8x16 = i8x16::new(0, 0, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 1); + let r: i8x16 = transmute(vclzq_s8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclz_s16() { + let a: i16x4 = i16x4::new(-32768, -1, 0x00, 0x01); + let e: i16x4 = i16x4::new(0, 0, 16, 15); + let r: i16x4 = transmute(vclz_s16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclzq_s16() { + let a: i16x8 = i16x8::new(-32768, -1, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01); + let e: i16x8 = i16x8::new(0, 0, 16, 15, 15, 15, 15, 15); + let r: i16x8 = transmute(vclzq_s16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclz_s32() { + let a: i32x2 = i32x2::new(-2147483648, -1); + let e: i32x2 = i32x2::new(0, 0); + let r: i32x2 = transmute(vclz_s32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclzq_s32() { + let a: i32x4 = i32x4::new(-2147483648, -1, 0x00, 0x01); + let e: i32x4 = i32x4::new(0, 0, 32, 31); + let r: i32x4 = transmute(vclzq_s32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclz_u8() { + let a: u8x8 = u8x8::new(0, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01); + let e: u8x8 = u8x8::new(8, 8, 7, 7, 7, 7, 7, 7); + let r: u8x8 = transmute(vclz_u8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclzq_u8() { + let a: u8x16 = u8x16::new(0, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF); + let e: u8x16 = u8x16::new(8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0); + let r: u8x16 = transmute(vclzq_u8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclz_u16() { + let a: u16x4 = u16x4::new(0, 0x00, 0x01, 0x01); + let e: u16x4 = u16x4::new(16, 16, 15, 15); + let r: u16x4 = transmute(vclz_u16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclzq_u16() { + let a: u16x8 = u16x8::new(0, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01); + let e: u16x8 = u16x8::new(16, 16, 15, 15, 15, 15, 15, 15); + let r: u16x8 = transmute(vclzq_u16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclz_u32() { + let a: u32x2 = u32x2::new(0, 0x00); + let e: u32x2 = u32x2::new(32, 32); + let r: u32x2 = transmute(vclz_u32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vclzq_u32() { + let a: u32x4 = u32x4::new(0, 0x00, 0x01, 0x01); + let e: u32x4 = u32x4::new(32, 32, 31, 31); + let r: u32x4 = transmute(vclzq_u32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcagt_f32() { + let a: f32x2 = f32x2::new(-1.2, 0.0); + let b: f32x2 = f32x2::new(-1.1, 0.0); + let e: u32x2 = u32x2::new(!0, 0); + let r: u32x2 = transmute(vcagt_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcagtq_f32() { + let a: f32x4 = f32x4::new(-1.2, 0.0, 1.2, 2.3); + let b: f32x4 = f32x4::new(-1.1, 0.0, 1.1, 2.4); + let e: u32x4 = u32x4::new(!0, 0, 0xFF_FF_FF_FF, 0); + let r: u32x4 = transmute(vcagtq_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcage_f32() { + let a: f32x2 = f32x2::new(-1.2, 0.0); + let b: f32x2 = f32x2::new(-1.1, 0.0); + let e: u32x2 = u32x2::new(!0, 0xFF_FF_FF_FF); + let r: u32x2 = transmute(vcage_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcageq_f32() { + let a: f32x4 = f32x4::new(-1.2, 0.0, 1.2, 2.3); + let b: f32x4 = f32x4::new(-1.1, 0.0, 1.1, 2.4); + let e: u32x4 = u32x4::new(!0, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0); + let r: u32x4 = transmute(vcageq_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcalt_f32() { + let a: f32x2 = f32x2::new(-1.2, 0.0); + let b: f32x2 = f32x2::new(-1.1, 0.0); + let e: u32x2 = u32x2::new(0, 0); + let r: u32x2 = transmute(vcalt_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcaltq_f32() { + let a: f32x4 = f32x4::new(-1.2, 0.0, 1.2, 2.3); + let b: f32x4 = f32x4::new(-1.1, 0.0, 1.1, 2.4); + let e: u32x4 = u32x4::new(0, 0, 0, 0xFF_FF_FF_FF); + let r: u32x4 = transmute(vcaltq_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcale_f32() { + let a: f32x2 = f32x2::new(-1.2, 0.0); + let b: f32x2 = f32x2::new(-1.1, 0.0); + let e: u32x2 = u32x2::new(0, 0xFF_FF_FF_FF); + let r: u32x2 = transmute(vcale_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcaleq_f32() { + let a: f32x4 = f32x4::new(-1.2, 0.0, 1.2, 2.3); + let b: f32x4 = f32x4::new(-1.1, 0.0, 1.1, 2.4); + let e: u32x4 = u32x4::new(0, 0xFF_FF_FF_FF, 0, 0xFF_FF_FF_FF); + let r: u32x4 = transmute(vcaleq_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcreate_s8() { + let a: u64 = 1; + let e: i8x8 = i8x8::new(1, 0, 0, 0, 0, 0, 0, 0); + let r: i8x8 = transmute(vcreate_s8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcreate_s16() { + let a: u64 = 1; + let e: i16x4 = i16x4::new(1, 0, 0, 0); + let r: i16x4 = transmute(vcreate_s16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcreate_s32() { + let a: u64 = 1; + let e: i32x2 = i32x2::new(1, 0); + let r: i32x2 = transmute(vcreate_s32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcreate_s64() { + let a: u64 = 1; + let e: i64x1 = i64x1::new(1); + let r: i64x1 = transmute(vcreate_s64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcreate_u8() { + let a: u64 = 1; + let e: u8x8 = u8x8::new(1, 0, 0, 0, 0, 0, 0, 0); + let r: u8x8 = transmute(vcreate_u8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcreate_u16() { + let a: u64 = 1; + let e: u16x4 = u16x4::new(1, 0, 0, 0); + let r: u16x4 = transmute(vcreate_u16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcreate_u32() { + let a: u64 = 1; + let e: u32x2 = u32x2::new(1, 0); + let r: u32x2 = transmute(vcreate_u32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcreate_u64() { + let a: u64 = 1; + let e: u64x1 = u64x1::new(1); + let r: u64x1 = transmute(vcreate_u64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcreate_p8() { + let a: u64 = 1; + let e: i8x8 = i8x8::new(1, 0, 0, 0, 0, 0, 0, 0); + let r: i8x8 = transmute(vcreate_p8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcreate_p16() { + let a: u64 = 1; + let e: i16x4 = i16x4::new(1, 0, 0, 0); + let r: i16x4 = transmute(vcreate_p16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcreate_p64() { + let a: u64 = 1; + let e: i64x1 = i64x1::new(1); + let r: i64x1 = transmute(vcreate_p64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcreate_f32() { + let a: u64 = 0; + let e: f32x2 = f32x2::new(0., 0.); + let r: f32x2 = transmute(vcreate_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcvt_f32_s32() { + let a: i32x2 = i32x2::new(1, 2); + let e: f32x2 = f32x2::new(1., 2.); + let r: f32x2 = transmute(vcvt_f32_s32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcvtq_f32_s32() { + let a: i32x4 = i32x4::new(1, 2, 3, 4); + let e: f32x4 = f32x4::new(1., 2., 3., 4.); + let r: f32x4 = transmute(vcvtq_f32_s32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcvt_f32_u32() { + let a: u32x2 = u32x2::new(1, 2); + let e: f32x2 = f32x2::new(1., 2.); + let r: f32x2 = transmute(vcvt_f32_u32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcvtq_f32_u32() { + let a: u32x4 = u32x4::new(1, 2, 3, 4); + let e: f32x4 = f32x4::new(1., 2., 3., 4.); + let r: f32x4 = transmute(vcvtq_f32_u32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcvt_n_f32_s32() { + let a: i32x2 = i32x2::new(1, 2); + let e: f32x2 = f32x2::new(0.25, 0.5); + let r: f32x2 = transmute(vcvt_n_f32_s32::<2>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcvtq_n_f32_s32() { + let a: i32x4 = i32x4::new(1, 2, 3, 4); + let e: f32x4 = f32x4::new(0.25, 0.5, 0.75, 1.); + let r: f32x4 = transmute(vcvtq_n_f32_s32::<2>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcvt_n_f32_u32() { + let a: u32x2 = u32x2::new(1, 2); + let e: f32x2 = f32x2::new(0.25, 0.5); + let r: f32x2 = transmute(vcvt_n_f32_u32::<2>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcvtq_n_f32_u32() { + let a: u32x4 = u32x4::new(1, 2, 3, 4); + let e: f32x4 = f32x4::new(0.25, 0.5, 0.75, 1.); + let r: f32x4 = transmute(vcvtq_n_f32_u32::<2>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcvt_n_s32_f32() { + let a: f32x2 = f32x2::new(0.25, 0.5); + let e: i32x2 = i32x2::new(1, 2); + let r: i32x2 = transmute(vcvt_n_s32_f32::<2>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcvtq_n_s32_f32() { + let a: f32x4 = f32x4::new(0.25, 0.5, 0.75, 1.); + let e: i32x4 = i32x4::new(1, 2, 3, 4); + let r: i32x4 = transmute(vcvtq_n_s32_f32::<2>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcvt_n_u32_f32() { + let a: f32x2 = f32x2::new(0.25, 0.5); + let e: u32x2 = u32x2::new(1, 2); + let r: u32x2 = transmute(vcvt_n_u32_f32::<2>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcvtq_n_u32_f32() { + let a: f32x4 = f32x4::new(0.25, 0.5, 0.75, 1.); + let e: u32x4 = u32x4::new(1, 2, 3, 4); + let r: u32x4 = transmute(vcvtq_n_u32_f32::<2>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcvt_s32_f32() { + let a: f32x2 = f32x2::new(-1.1, 2.1); + let e: i32x2 = i32x2::new(-1, 2); + let r: i32x2 = transmute(vcvt_s32_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcvtq_s32_f32() { + let a: f32x4 = f32x4::new(-1.1, 2.1, -2.9, 3.9); + let e: i32x4 = i32x4::new(-1, 2, -2, 3); + let r: i32x4 = transmute(vcvtq_s32_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcvt_u32_f32() { + let a: f32x2 = f32x2::new(1.1, 2.1); + let e: u32x2 = u32x2::new(1, 2); + let r: u32x2 = transmute(vcvt_u32_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vcvtq_u32_f32() { + let a: f32x4 = f32x4::new(1.1, 2.1, 2.9, 3.9); + let e: u32x4 = u32x4::new(1, 2, 2, 3); + let r: u32x4 = transmute(vcvtq_u32_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdup_lane_s8() { + let a: i8x8 = i8x8::new(1, 1, 1, 4, 1, 6, 7, 8); + let e: i8x8 = i8x8::new(1, 1, 1, 1, 1, 1, 1, 1); + let r: i8x8 = transmute(vdup_lane_s8::<4>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdupq_laneq_s8() { + let a: i8x16 = i8x16::new(1, 1, 1, 4, 1, 6, 7, 8, 1, 10, 11, 12, 13, 14, 15, 16); + let e: i8x16 = i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); + let r: i8x16 = transmute(vdupq_laneq_s8::<8>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdup_lane_s16() { + let a: i16x4 = i16x4::new(1, 1, 1, 4); + let e: i16x4 = i16x4::new(1, 1, 1, 1); + let r: i16x4 = transmute(vdup_lane_s16::<2>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdupq_laneq_s16() { + let a: i16x8 = i16x8::new(1, 1, 1, 4, 1, 6, 7, 8); + let e: i16x8 = i16x8::new(1, 1, 1, 1, 1, 1, 1, 1); + let r: i16x8 = transmute(vdupq_laneq_s16::<4>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdup_lane_s32() { + let a: i32x2 = i32x2::new(1, 1); + let e: i32x2 = i32x2::new(1, 1); + let r: i32x2 = transmute(vdup_lane_s32::<1>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdupq_laneq_s32() { + let a: i32x4 = i32x4::new(1, 1, 1, 4); + let e: i32x4 = i32x4::new(1, 1, 1, 1); + let r: i32x4 = transmute(vdupq_laneq_s32::<2>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdup_laneq_s8() { + let a: i8x16 = i8x16::new(1, 1, 1, 4, 1, 6, 7, 8, 1, 10, 11, 12, 13, 14, 15, 16); + let e: i8x8 = i8x8::new(1, 1, 1, 1, 1, 1, 1, 1); + let r: i8x8 = transmute(vdup_laneq_s8::<8>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdup_laneq_s16() { + let a: i16x8 = i16x8::new(1, 1, 1, 4, 1, 6, 7, 8); + let e: i16x4 = i16x4::new(1, 1, 1, 1); + let r: i16x4 = transmute(vdup_laneq_s16::<4>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdup_laneq_s32() { + let a: i32x4 = i32x4::new(1, 1, 1, 4); + let e: i32x2 = i32x2::new(1, 1); + let r: i32x2 = transmute(vdup_laneq_s32::<2>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdupq_lane_s8() { + let a: i8x8 = i8x8::new(1, 1, 1, 4, 1, 6, 7, 8); + let e: i8x16 = i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); + let r: i8x16 = transmute(vdupq_lane_s8::<4>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdupq_lane_s16() { + let a: i16x4 = i16x4::new(1, 1, 1, 4); + let e: i16x8 = i16x8::new(1, 1, 1, 1, 1, 1, 1, 1); + let r: i16x8 = transmute(vdupq_lane_s16::<2>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdupq_lane_s32() { + let a: i32x2 = i32x2::new(1, 1); + let e: i32x4 = i32x4::new(1, 1, 1, 1); + let r: i32x4 = transmute(vdupq_lane_s32::<1>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdup_lane_u8() { + let a: u8x8 = u8x8::new(1, 1, 1, 4, 1, 6, 7, 8); + let e: u8x8 = u8x8::new(1, 1, 1, 1, 1, 1, 1, 1); + let r: u8x8 = transmute(vdup_lane_u8::<4>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdupq_laneq_u8() { + let a: u8x16 = u8x16::new(1, 1, 1, 4, 1, 6, 7, 8, 1, 10, 11, 12, 13, 14, 15, 16); + let e: u8x16 = u8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); + let r: u8x16 = transmute(vdupq_laneq_u8::<8>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdup_lane_u16() { + let a: u16x4 = u16x4::new(1, 1, 1, 4); + let e: u16x4 = u16x4::new(1, 1, 1, 1); + let r: u16x4 = transmute(vdup_lane_u16::<2>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdupq_laneq_u16() { + let a: u16x8 = u16x8::new(1, 1, 1, 4, 1, 6, 7, 8); + let e: u16x8 = u16x8::new(1, 1, 1, 1, 1, 1, 1, 1); + let r: u16x8 = transmute(vdupq_laneq_u16::<4>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdup_lane_u32() { + let a: u32x2 = u32x2::new(1, 1); + let e: u32x2 = u32x2::new(1, 1); + let r: u32x2 = transmute(vdup_lane_u32::<1>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdupq_laneq_u32() { + let a: u32x4 = u32x4::new(1, 1, 1, 4); + let e: u32x4 = u32x4::new(1, 1, 1, 1); + let r: u32x4 = transmute(vdupq_laneq_u32::<2>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdup_laneq_u8() { + let a: u8x16 = u8x16::new(1, 1, 1, 4, 1, 6, 7, 8, 1, 10, 11, 12, 13, 14, 15, 16); + let e: u8x8 = u8x8::new(1, 1, 1, 1, 1, 1, 1, 1); + let r: u8x8 = transmute(vdup_laneq_u8::<8>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdup_laneq_u16() { + let a: u16x8 = u16x8::new(1, 1, 1, 4, 1, 6, 7, 8); + let e: u16x4 = u16x4::new(1, 1, 1, 1); + let r: u16x4 = transmute(vdup_laneq_u16::<4>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdup_laneq_u32() { + let a: u32x4 = u32x4::new(1, 1, 1, 4); + let e: u32x2 = u32x2::new(1, 1); + let r: u32x2 = transmute(vdup_laneq_u32::<2>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdupq_lane_u8() { + let a: u8x8 = u8x8::new(1, 1, 1, 4, 1, 6, 7, 8); + let e: u8x16 = u8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); + let r: u8x16 = transmute(vdupq_lane_u8::<4>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdupq_lane_u16() { + let a: u16x4 = u16x4::new(1, 1, 1, 4); + let e: u16x8 = u16x8::new(1, 1, 1, 1, 1, 1, 1, 1); + let r: u16x8 = transmute(vdupq_lane_u16::<2>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdupq_lane_u32() { + let a: u32x2 = u32x2::new(1, 1); + let e: u32x4 = u32x4::new(1, 1, 1, 1); + let r: u32x4 = transmute(vdupq_lane_u32::<1>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdup_lane_p8() { + let a: i8x8 = i8x8::new(1, 1, 1, 4, 1, 6, 7, 8); + let e: i8x8 = i8x8::new(1, 1, 1, 1, 1, 1, 1, 1); + let r: i8x8 = transmute(vdup_lane_p8::<4>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdupq_laneq_p8() { + let a: i8x16 = i8x16::new(1, 1, 1, 4, 1, 6, 7, 8, 1, 10, 11, 12, 13, 14, 15, 16); + let e: i8x16 = i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); + let r: i8x16 = transmute(vdupq_laneq_p8::<8>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdup_lane_p16() { + let a: i16x4 = i16x4::new(1, 1, 1, 4); + let e: i16x4 = i16x4::new(1, 1, 1, 1); + let r: i16x4 = transmute(vdup_lane_p16::<2>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdupq_laneq_p16() { + let a: i16x8 = i16x8::new(1, 1, 1, 4, 1, 6, 7, 8); + let e: i16x8 = i16x8::new(1, 1, 1, 1, 1, 1, 1, 1); + let r: i16x8 = transmute(vdupq_laneq_p16::<4>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdup_laneq_p8() { + let a: i8x16 = i8x16::new(1, 1, 1, 4, 1, 6, 7, 8, 1, 10, 11, 12, 13, 14, 15, 16); + let e: i8x8 = i8x8::new(1, 1, 1, 1, 1, 1, 1, 1); + let r: i8x8 = transmute(vdup_laneq_p8::<8>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdup_laneq_p16() { + let a: i16x8 = i16x8::new(1, 1, 1, 4, 1, 6, 7, 8); + let e: i16x4 = i16x4::new(1, 1, 1, 1); + let r: i16x4 = transmute(vdup_laneq_p16::<4>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdupq_lane_p8() { + let a: i8x8 = i8x8::new(1, 1, 1, 4, 1, 6, 7, 8); + let e: i8x16 = i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); + let r: i8x16 = transmute(vdupq_lane_p8::<4>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdupq_lane_p16() { + let a: i16x4 = i16x4::new(1, 1, 1, 4); + let e: i16x8 = i16x8::new(1, 1, 1, 1, 1, 1, 1, 1); + let r: i16x8 = transmute(vdupq_lane_p16::<2>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdupq_laneq_s64() { + let a: i64x2 = i64x2::new(1, 1); + let e: i64x2 = i64x2::new(1, 1); + let r: i64x2 = transmute(vdupq_laneq_s64::<1>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdupq_lane_s64() { + let a: i64x1 = i64x1::new(1); + let e: i64x2 = i64x2::new(1, 1); + let r: i64x2 = transmute(vdupq_lane_s64::<0>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdupq_laneq_u64() { + let a: u64x2 = u64x2::new(1, 1); + let e: u64x2 = u64x2::new(1, 1); + let r: u64x2 = transmute(vdupq_laneq_u64::<1>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdupq_lane_u64() { + let a: u64x1 = u64x1::new(1); + let e: u64x2 = u64x2::new(1, 1); + let r: u64x2 = transmute(vdupq_lane_u64::<0>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdup_lane_f32() { + let a: f32x2 = f32x2::new(1., 1.); + let e: f32x2 = f32x2::new(1., 1.); + let r: f32x2 = transmute(vdup_lane_f32::<1>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdupq_laneq_f32() { + let a: f32x4 = f32x4::new(1., 1., 1., 4.); + let e: f32x4 = f32x4::new(1., 1., 1., 1.); + let r: f32x4 = transmute(vdupq_laneq_f32::<2>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdup_laneq_f32() { + let a: f32x4 = f32x4::new(1., 1., 1., 4.); + let e: f32x2 = f32x2::new(1., 1.); + let r: f32x2 = transmute(vdup_laneq_f32::<2>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdupq_lane_f32() { + let a: f32x2 = f32x2::new(1., 1.); + let e: f32x4 = f32x4::new(1., 1., 1., 1.); + let r: f32x4 = transmute(vdupq_lane_f32::<1>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdup_lane_s64() { + let a: i64x1 = i64x1::new(0); + let e: i64x1 = i64x1::new(0); + let r: i64x1 = transmute(vdup_lane_s64::<0>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdup_lane_u64() { + let a: u64x1 = u64x1::new(0); + let e: u64x1 = u64x1::new(0); + let r: u64x1 = transmute(vdup_lane_u64::<0>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdup_laneq_s64() { + let a: i64x2 = i64x2::new(0, 1); + let e: i64x1 = i64x1::new(1); + let r: i64x1 = transmute(vdup_laneq_s64::<1>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vdup_laneq_u64() { + let a: u64x2 = u64x2::new(0, 1); + let e: u64x1 = u64x1::new(1); + let r: u64x1 = transmute(vdup_laneq_u64::<1>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vext_s8() { + let a: i8x8 = i8x8::new(0, 8, 8, 9, 8, 9, 9, 11); + let b: i8x8 = i8x8::new(9, 11, 14, 15, 16, 17, 18, 19); + let e: i8x8 = i8x8::new(8, 9, 9, 11, 9, 11, 14, 15); + let r: i8x8 = transmute(vext_s8::<4>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vextq_s8() { + let a: i8x16 = i8x16::new(0, 8, 8, 9, 8, 9, 9, 11, 8, 9, 9, 11, 9, 11, 14, 15); + let b: i8x16 = i8x16::new(9, 11, 14, 15, 16, 17, 18, 19, 0, 8, 8, 9, 8, 9, 9, 11); + let e: i8x16 = i8x16::new(8, 9, 9, 11, 9, 11, 14, 15, 9, 11, 14, 15, 16, 17, 18, 19); + let r: i8x16 = transmute(vextq_s8::<8>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vext_s16() { + let a: i16x4 = i16x4::new(0, 8, 8, 9); + let b: i16x4 = i16x4::new(9, 11, 14, 15); + let e: i16x4 = i16x4::new(8, 9, 9, 11); + let r: i16x4 = transmute(vext_s16::<2>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vextq_s16() { + let a: i16x8 = i16x8::new(0, 8, 8, 9, 8, 9, 9, 11); + let b: i16x8 = i16x8::new(9, 11, 14, 15, 16, 17, 18, 19); + let e: i16x8 = i16x8::new(8, 9, 9, 11, 9, 11, 14, 15); + let r: i16x8 = transmute(vextq_s16::<4>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vext_s32() { + let a: i32x2 = i32x2::new(0, 8); + let b: i32x2 = i32x2::new(9, 11); + let e: i32x2 = i32x2::new(8, 9); + let r: i32x2 = transmute(vext_s32::<1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vextq_s32() { + let a: i32x4 = i32x4::new(0, 8, 8, 9); + let b: i32x4 = i32x4::new(9, 11, 14, 15); + let e: i32x4 = i32x4::new(8, 9, 9, 11); + let r: i32x4 = transmute(vextq_s32::<2>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vext_u8() { + let a: u8x8 = u8x8::new(0, 8, 8, 9, 8, 9, 9, 11); + let b: u8x8 = u8x8::new(9, 11, 14, 15, 16, 17, 18, 19); + let e: u8x8 = u8x8::new(8, 9, 9, 11, 9, 11, 14, 15); + let r: u8x8 = transmute(vext_u8::<4>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vextq_u8() { + let a: u8x16 = u8x16::new(0, 8, 8, 9, 8, 9, 9, 11, 8, 9, 9, 11, 9, 11, 14, 15); + let b: u8x16 = u8x16::new(9, 11, 14, 15, 16, 17, 18, 19, 0, 8, 8, 9, 8, 9, 9, 11); + let e: u8x16 = u8x16::new(8, 9, 9, 11, 9, 11, 14, 15, 9, 11, 14, 15, 16, 17, 18, 19); + let r: u8x16 = transmute(vextq_u8::<8>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vext_u16() { + let a: u16x4 = u16x4::new(0, 8, 8, 9); + let b: u16x4 = u16x4::new(9, 11, 14, 15); + let e: u16x4 = u16x4::new(8, 9, 9, 11); + let r: u16x4 = transmute(vext_u16::<2>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vextq_u16() { + let a: u16x8 = u16x8::new(0, 8, 8, 9, 8, 9, 9, 11); + let b: u16x8 = u16x8::new(9, 11, 14, 15, 16, 17, 18, 19); + let e: u16x8 = u16x8::new(8, 9, 9, 11, 9, 11, 14, 15); + let r: u16x8 = transmute(vextq_u16::<4>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vext_u32() { + let a: u32x2 = u32x2::new(0, 8); + let b: u32x2 = u32x2::new(9, 11); + let e: u32x2 = u32x2::new(8, 9); + let r: u32x2 = transmute(vext_u32::<1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vextq_u32() { + let a: u32x4 = u32x4::new(0, 8, 8, 9); + let b: u32x4 = u32x4::new(9, 11, 14, 15); + let e: u32x4 = u32x4::new(8, 9, 9, 11); + let r: u32x4 = transmute(vextq_u32::<2>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vext_p8() { + let a: i8x8 = i8x8::new(0, 8, 8, 9, 8, 9, 9, 11); + let b: i8x8 = i8x8::new(9, 11, 14, 15, 16, 17, 18, 19); + let e: i8x8 = i8x8::new(8, 9, 9, 11, 9, 11, 14, 15); + let r: i8x8 = transmute(vext_p8::<4>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vextq_p8() { + let a: i8x16 = i8x16::new(0, 8, 8, 9, 8, 9, 9, 11, 8, 9, 9, 11, 9, 11, 14, 15); + let b: i8x16 = i8x16::new(9, 11, 14, 15, 16, 17, 18, 19, 0, 8, 8, 9, 8, 9, 9, 11); + let e: i8x16 = i8x16::new(8, 9, 9, 11, 9, 11, 14, 15, 9, 11, 14, 15, 16, 17, 18, 19); + let r: i8x16 = transmute(vextq_p8::<8>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vext_p16() { + let a: i16x4 = i16x4::new(0, 8, 8, 9); + let b: i16x4 = i16x4::new(9, 11, 14, 15); + let e: i16x4 = i16x4::new(8, 9, 9, 11); + let r: i16x4 = transmute(vext_p16::<2>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vextq_p16() { + let a: i16x8 = i16x8::new(0, 8, 8, 9, 8, 9, 9, 11); + let b: i16x8 = i16x8::new(9, 11, 14, 15, 16, 17, 18, 19); + let e: i16x8 = i16x8::new(8, 9, 9, 11, 9, 11, 14, 15); + let r: i16x8 = transmute(vextq_p16::<4>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vextq_s64() { + let a: i64x2 = i64x2::new(0, 8); + let b: i64x2 = i64x2::new(9, 11); + let e: i64x2 = i64x2::new(8, 9); + let r: i64x2 = transmute(vextq_s64::<1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vextq_u64() { + let a: u64x2 = u64x2::new(0, 8); + let b: u64x2 = u64x2::new(9, 11); + let e: u64x2 = u64x2::new(8, 9); + let r: u64x2 = transmute(vextq_u64::<1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vext_f32() { + let a: f32x2 = f32x2::new(0., 2.); + let b: f32x2 = f32x2::new(3., 4.); + let e: f32x2 = f32x2::new(2., 3.); + let r: f32x2 = transmute(vext_f32::<1>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vextq_f32() { + let a: f32x4 = f32x4::new(0., 2., 2., 3.); + let b: f32x4 = f32x4::new(3., 4., 5., 6.); + let e: f32x4 = f32x4::new(2., 3., 3., 4.); + let r: f32x4 = transmute(vextq_f32::<2>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmla_s8() { + let a: i8x8 = i8x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let b: i8x8 = i8x8::new(2, 2, 2, 2, 2, 2, 2, 2); + let c: i8x8 = i8x8::new(3, 3, 3, 3, 3, 3, 3, 3); + let e: i8x8 = i8x8::new(6, 7, 8, 9, 10, 11, 12, 13); + let r: i8x8 = transmute(vmla_s8(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmlaq_s8() { + let a: i8x16 = i8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let b: i8x16 = i8x16::new(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); + let c: i8x16 = i8x16::new(3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3); + let e: i8x16 = i8x16::new(6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21); + let r: i8x16 = transmute(vmlaq_s8(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmla_s16() { + let a: i16x4 = i16x4::new(0, 1, 2, 3); + let b: i16x4 = i16x4::new(2, 2, 2, 2); + let c: i16x4 = i16x4::new(3, 3, 3, 3); + let e: i16x4 = i16x4::new(6, 7, 8, 9); + let r: i16x4 = transmute(vmla_s16(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmlaq_s16() { + let a: i16x8 = i16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let b: i16x8 = i16x8::new(2, 2, 2, 2, 2, 2, 2, 2); + let c: i16x8 = i16x8::new(3, 3, 3, 3, 3, 3, 3, 3); + let e: i16x8 = i16x8::new(6, 7, 8, 9, 10, 11, 12, 13); + let r: i16x8 = transmute(vmlaq_s16(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmla_s32() { + let a: i32x2 = i32x2::new(0, 1); + let b: i32x2 = i32x2::new(2, 2); + let c: i32x2 = i32x2::new(3, 3); + let e: i32x2 = i32x2::new(6, 7); + let r: i32x2 = transmute(vmla_s32(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmlaq_s32() { + let a: i32x4 = i32x4::new(0, 1, 2, 3); + let b: i32x4 = i32x4::new(2, 2, 2, 2); + let c: i32x4 = i32x4::new(3, 3, 3, 3); + let e: i32x4 = i32x4::new(6, 7, 8, 9); + let r: i32x4 = transmute(vmlaq_s32(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmla_u8() { + let a: u8x8 = u8x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let b: u8x8 = u8x8::new(2, 2, 2, 2, 2, 2, 2, 2); + let c: u8x8 = u8x8::new(3, 3, 3, 3, 3, 3, 3, 3); + let e: u8x8 = u8x8::new(6, 7, 8, 9, 10, 11, 12, 13); + let r: u8x8 = transmute(vmla_u8(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmlaq_u8() { + let a: u8x16 = u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let b: u8x16 = u8x16::new(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); + let c: u8x16 = u8x16::new(3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3); + let e: u8x16 = u8x16::new(6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21); + let r: u8x16 = transmute(vmlaq_u8(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmla_u16() { + let a: u16x4 = u16x4::new(0, 1, 2, 3); + let b: u16x4 = u16x4::new(2, 2, 2, 2); + let c: u16x4 = u16x4::new(3, 3, 3, 3); + let e: u16x4 = u16x4::new(6, 7, 8, 9); + let r: u16x4 = transmute(vmla_u16(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmlaq_u16() { + let a: u16x8 = u16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let b: u16x8 = u16x8::new(2, 2, 2, 2, 2, 2, 2, 2); + let c: u16x8 = u16x8::new(3, 3, 3, 3, 3, 3, 3, 3); + let e: u16x8 = u16x8::new(6, 7, 8, 9, 10, 11, 12, 13); + let r: u16x8 = transmute(vmlaq_u16(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmla_u32() { + let a: u32x2 = u32x2::new(0, 1); + let b: u32x2 = u32x2::new(2, 2); + let c: u32x2 = u32x2::new(3, 3); + let e: u32x2 = u32x2::new(6, 7); + let r: u32x2 = transmute(vmla_u32(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmlaq_u32() { + let a: u32x4 = u32x4::new(0, 1, 2, 3); + let b: u32x4 = u32x4::new(2, 2, 2, 2); + let c: u32x4 = u32x4::new(3, 3, 3, 3); + let e: u32x4 = u32x4::new(6, 7, 8, 9); + let r: u32x4 = transmute(vmlaq_u32(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmla_f32() { + let a: f32x2 = f32x2::new(0., 1.); + let b: f32x2 = f32x2::new(2., 2.); + let c: f32x2 = f32x2::new(3., 3.); + let e: f32x2 = f32x2::new(6., 7.); + let r: f32x2 = transmute(vmla_f32(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmlaq_f32() { + let a: f32x4 = f32x4::new(0., 1., 2., 3.); + let b: f32x4 = f32x4::new(2., 2., 2., 2.); + let c: f32x4 = f32x4::new(3., 3., 3., 3.); + let e: f32x4 = f32x4::new(6., 7., 8., 9.); + let r: f32x4 = transmute(vmlaq_f32(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmla_n_s16() { + let a: i16x4 = i16x4::new(0, 1, 2, 3); + let b: i16x4 = i16x4::new(2, 2, 2, 2); + let c: i16 = 3; + let e: i16x4 = i16x4::new(6, 7, 8, 9); + let r: i16x4 = transmute(vmla_n_s16(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmlaq_n_s16() { + let a: i16x8 = i16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let b: i16x8 = i16x8::new(2, 2, 2, 2, 2, 2, 2, 2); + let c: i16 = 3; + let e: i16x8 = i16x8::new(6, 7, 8, 9, 10, 11, 12, 13); + let r: i16x8 = transmute(vmlaq_n_s16(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmla_n_s32() { + let a: i32x2 = i32x2::new(0, 1); + let b: i32x2 = i32x2::new(2, 2); + let c: i32 = 3; + let e: i32x2 = i32x2::new(6, 7); + let r: i32x2 = transmute(vmla_n_s32(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmlaq_n_s32() { + let a: i32x4 = i32x4::new(0, 1, 2, 3); + let b: i32x4 = i32x4::new(2, 2, 2, 2); + let c: i32 = 3; + let e: i32x4 = i32x4::new(6, 7, 8, 9); + let r: i32x4 = transmute(vmlaq_n_s32(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmla_n_u16() { + let a: u16x4 = u16x4::new(0, 1, 2, 3); + let b: u16x4 = u16x4::new(2, 2, 2, 2); + let c: u16 = 3; + let e: u16x4 = u16x4::new(6, 7, 8, 9); + let r: u16x4 = transmute(vmla_n_u16(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmlaq_n_u16() { + let a: u16x8 = u16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let b: u16x8 = u16x8::new(2, 2, 2, 2, 2, 2, 2, 2); + let c: u16 = 3; + let e: u16x8 = u16x8::new(6, 7, 8, 9, 10, 11, 12, 13); + let r: u16x8 = transmute(vmlaq_n_u16(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmla_n_u32() { + let a: u32x2 = u32x2::new(0, 1); + let b: u32x2 = u32x2::new(2, 2); + let c: u32 = 3; + let e: u32x2 = u32x2::new(6, 7); + let r: u32x2 = transmute(vmla_n_u32(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vmlaq_n_u32() { + let a: u32x4 = u32x4::new(0, 1, 2, 3); + let b: u32x4 = u32x4::new(2, 2, 2, 2); + let c: u32 = 3; + let e: u32x4 = u32x4::new(6, 7, 8, 9); + let r: u32x4 = transmute(vmlaq_n_u32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vandq_s32() { - let a: i32x4 = i32x4::new(0x00, 0x01, 0x02, 0x03); - let b: i32x4 = i32x4::new(0x0F, 0x0F, 0x0F, 0x0F); - let e: i32x4 = i32x4::new(0x00, 0x01, 0x02, 0x03); - let r: i32x4 = transmute(vandq_s32(transmute(a), transmute(b))); - assert_eq!(r, e); - - let a: i32x4 = i32x4::new(0x00, 0x01, 0x02, 0x03); - let b: i32x4 = i32x4::new(0x00, 0x00, 0x00, 0x00); - let e: i32x4 = i32x4::new(0x00, 0x00, 0x00, 0x00); - let r: i32x4 = transmute(vandq_s32(transmute(a), transmute(b))); + unsafe fn test_vmla_n_f32() { + let a: f32x2 = f32x2::new(0., 1.); + let b: f32x2 = f32x2::new(2., 2.); + let c: f32 = 3.; + let e: f32x2 = f32x2::new(6., 7.); + let r: f32x2 = transmute(vmla_n_f32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vand_u8() { - let a: u8x8 = u8x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let b: u8x8 = u8x8::new(0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F); - let e: u8x8 = u8x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let r: u8x8 = transmute(vand_u8(transmute(a), transmute(b))); + unsafe fn test_vmlaq_n_f32() { + let a: f32x4 = f32x4::new(0., 1., 2., 3.); + let b: f32x4 = f32x4::new(2., 2., 2., 2.); + let c: f32 = 3.; + let e: f32x4 = f32x4::new(6., 7., 8., 9.); + let r: f32x4 = transmute(vmlaq_n_f32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); + } - let a: u8x8 = u8x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let b: u8x8 = u8x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - let e: u8x8 = u8x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - let r: u8x8 = transmute(vand_u8(transmute(a), transmute(b))); + #[simd_test(enable = "neon")] + unsafe fn test_vmla_lane_s16() { + let a: i16x4 = i16x4::new(0, 1, 2, 3); + let b: i16x4 = i16x4::new(2, 2, 2, 2); + let c: i16x4 = i16x4::new(0, 3, 0, 0); + let e: i16x4 = i16x4::new(6, 7, 8, 9); + let r: i16x4 = transmute(vmla_lane_s16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vandq_u8() { - let a: u8x16 = u8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x00); - let b: u8x16 = u8x16::new(0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F); - let e: u8x16 = u8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x00); - let r: u8x16 = transmute(vandq_u8(transmute(a), transmute(b))); + unsafe fn test_vmla_laneq_s16() { + let a: i16x4 = i16x4::new(0, 1, 2, 3); + let b: i16x4 = i16x4::new(2, 2, 2, 2); + let c: i16x8 = i16x8::new(0, 3, 0, 0, 0, 0, 0, 0); + let e: i16x4 = i16x4::new(6, 7, 8, 9); + let r: i16x4 = transmute(vmla_laneq_s16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); + } - let a: u8x16 = u8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x00); - let b: u8x16 = u8x16::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - let e: u8x16 = u8x16::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - let r: u8x16 = transmute(vandq_u8(transmute(a), transmute(b))); + #[simd_test(enable = "neon")] + unsafe fn test_vmlaq_lane_s16() { + let a: i16x8 = i16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let b: i16x8 = i16x8::new(2, 2, 2, 2, 2, 2, 2, 2); + let c: i16x4 = i16x4::new(0, 3, 0, 0); + let e: i16x8 = i16x8::new(6, 7, 8, 9, 10, 11, 12, 13); + let r: i16x8 = transmute(vmlaq_lane_s16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vand_u16() { - let a: u16x4 = u16x4::new(0x00, 0x01, 0x02, 0x03); - let b: u16x4 = u16x4::new(0x0F, 0x0F, 0x0F, 0x0F); - let e: u16x4 = u16x4::new(0x00, 0x01, 0x02, 0x03); - let r: u16x4 = transmute(vand_u16(transmute(a), transmute(b))); + unsafe fn test_vmlaq_laneq_s16() { + let a: i16x8 = i16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let b: i16x8 = i16x8::new(2, 2, 2, 2, 2, 2, 2, 2); + let c: i16x8 = i16x8::new(0, 3, 0, 0, 0, 0, 0, 0); + let e: i16x8 = i16x8::new(6, 7, 8, 9, 10, 11, 12, 13); + let r: i16x8 = transmute(vmlaq_laneq_s16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); + } - let a: u16x4 = u16x4::new(0x00, 0x01, 0x02, 0x03); - let b: u16x4 = u16x4::new(0x00, 0x00, 0x00, 0x00); - let e: u16x4 = u16x4::new(0x00, 0x00, 0x00, 0x00); - let r: u16x4 = transmute(vand_u16(transmute(a), transmute(b))); + #[simd_test(enable = "neon")] + unsafe fn test_vmla_lane_s32() { + let a: i32x2 = i32x2::new(0, 1); + let b: i32x2 = i32x2::new(2, 2); + let c: i32x2 = i32x2::new(0, 3); + let e: i32x2 = i32x2::new(6, 7); + let r: i32x2 = transmute(vmla_lane_s32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vandq_u16() { - let a: u16x8 = u16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let b: u16x8 = u16x8::new(0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F); - let e: u16x8 = u16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let r: u16x8 = transmute(vandq_u16(transmute(a), transmute(b))); + unsafe fn test_vmla_laneq_s32() { + let a: i32x2 = i32x2::new(0, 1); + let b: i32x2 = i32x2::new(2, 2); + let c: i32x4 = i32x4::new(0, 3, 0, 0); + let e: i32x2 = i32x2::new(6, 7); + let r: i32x2 = transmute(vmla_laneq_s32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); + } - let a: u16x8 = u16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let b: u16x8 = u16x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - let e: u16x8 = u16x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - let r: u16x8 = transmute(vandq_u16(transmute(a), transmute(b))); + #[simd_test(enable = "neon")] + unsafe fn test_vmlaq_lane_s32() { + let a: i32x4 = i32x4::new(0, 1, 2, 3); + let b: i32x4 = i32x4::new(2, 2, 2, 2); + let c: i32x2 = i32x2::new(0, 3); + let e: i32x4 = i32x4::new(6, 7, 8, 9); + let r: i32x4 = transmute(vmlaq_lane_s32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vand_u32() { - let a: u32x2 = u32x2::new(0x00, 0x01); - let b: u32x2 = u32x2::new(0x0F, 0x0F); - let e: u32x2 = u32x2::new(0x00, 0x01); - let r: u32x2 = transmute(vand_u32(transmute(a), transmute(b))); + unsafe fn test_vmlaq_laneq_s32() { + let a: i32x4 = i32x4::new(0, 1, 2, 3); + let b: i32x4 = i32x4::new(2, 2, 2, 2); + let c: i32x4 = i32x4::new(0, 3, 0, 0); + let e: i32x4 = i32x4::new(6, 7, 8, 9); + let r: i32x4 = transmute(vmlaq_laneq_s32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); + } - let a: u32x2 = u32x2::new(0x00, 0x01); - let b: u32x2 = u32x2::new(0x00, 0x00); - let e: u32x2 = u32x2::new(0x00, 0x00); - let r: u32x2 = transmute(vand_u32(transmute(a), transmute(b))); + #[simd_test(enable = "neon")] + unsafe fn test_vmla_lane_u16() { + let a: u16x4 = u16x4::new(0, 1, 2, 3); + let b: u16x4 = u16x4::new(2, 2, 2, 2); + let c: u16x4 = u16x4::new(0, 3, 0, 0); + let e: u16x4 = u16x4::new(6, 7, 8, 9); + let r: u16x4 = transmute(vmla_lane_u16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vandq_u32() { - let a: u32x4 = u32x4::new(0x00, 0x01, 0x02, 0x03); - let b: u32x4 = u32x4::new(0x0F, 0x0F, 0x0F, 0x0F); - let e: u32x4 = u32x4::new(0x00, 0x01, 0x02, 0x03); - let r: u32x4 = transmute(vandq_u32(transmute(a), transmute(b))); + unsafe fn test_vmla_laneq_u16() { + let a: u16x4 = u16x4::new(0, 1, 2, 3); + let b: u16x4 = u16x4::new(2, 2, 2, 2); + let c: u16x8 = u16x8::new(0, 3, 0, 0, 0, 0, 0, 0); + let e: u16x4 = u16x4::new(6, 7, 8, 9); + let r: u16x4 = transmute(vmla_laneq_u16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); + } - let a: u32x4 = u32x4::new(0x00, 0x01, 0x02, 0x03); - let b: u32x4 = u32x4::new(0x00, 0x00, 0x00, 0x00); - let e: u32x4 = u32x4::new(0x00, 0x00, 0x00, 0x00); - let r: u32x4 = transmute(vandq_u32(transmute(a), transmute(b))); + #[simd_test(enable = "neon")] + unsafe fn test_vmlaq_lane_u16() { + let a: u16x8 = u16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let b: u16x8 = u16x8::new(2, 2, 2, 2, 2, 2, 2, 2); + let c: u16x4 = u16x4::new(0, 3, 0, 0); + let e: u16x8 = u16x8::new(6, 7, 8, 9, 10, 11, 12, 13); + let r: u16x8 = transmute(vmlaq_lane_u16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vand_s64() { - let a: i64x1 = i64x1::new(0x00); - let b: i64x1 = i64x1::new(0x0F); - let e: i64x1 = i64x1::new(0x00); - let r: i64x1 = transmute(vand_s64(transmute(a), transmute(b))); + unsafe fn test_vmlaq_laneq_u16() { + let a: u16x8 = u16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let b: u16x8 = u16x8::new(2, 2, 2, 2, 2, 2, 2, 2); + let c: u16x8 = u16x8::new(0, 3, 0, 0, 0, 0, 0, 0); + let e: u16x8 = u16x8::new(6, 7, 8, 9, 10, 11, 12, 13); + let r: u16x8 = transmute(vmlaq_laneq_u16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); + } - let a: i64x1 = i64x1::new(0x00); - let b: i64x1 = i64x1::new(0x00); - let e: i64x1 = i64x1::new(0x00); - let r: i64x1 = transmute(vand_s64(transmute(a), transmute(b))); + #[simd_test(enable = "neon")] + unsafe fn test_vmla_lane_u32() { + let a: u32x2 = u32x2::new(0, 1); + let b: u32x2 = u32x2::new(2, 2); + let c: u32x2 = u32x2::new(0, 3); + let e: u32x2 = u32x2::new(6, 7); + let r: u32x2 = transmute(vmla_lane_u32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vandq_s64() { - let a: i64x2 = i64x2::new(0x00, 0x01); - let b: i64x2 = i64x2::new(0x0F, 0x0F); - let e: i64x2 = i64x2::new(0x00, 0x01); - let r: i64x2 = transmute(vandq_s64(transmute(a), transmute(b))); + unsafe fn test_vmla_laneq_u32() { + let a: u32x2 = u32x2::new(0, 1); + let b: u32x2 = u32x2::new(2, 2); + let c: u32x4 = u32x4::new(0, 3, 0, 0); + let e: u32x2 = u32x2::new(6, 7); + let r: u32x2 = transmute(vmla_laneq_u32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); + } - let a: i64x2 = i64x2::new(0x00, 0x01); - let b: i64x2 = i64x2::new(0x00, 0x00); - let e: i64x2 = i64x2::new(0x00, 0x00); - let r: i64x2 = transmute(vandq_s64(transmute(a), transmute(b))); + #[simd_test(enable = "neon")] + unsafe fn test_vmlaq_lane_u32() { + let a: u32x4 = u32x4::new(0, 1, 2, 3); + let b: u32x4 = u32x4::new(2, 2, 2, 2); + let c: u32x2 = u32x2::new(0, 3); + let e: u32x4 = u32x4::new(6, 7, 8, 9); + let r: u32x4 = transmute(vmlaq_lane_u32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vand_u64() { - let a: u64x1 = u64x1::new(0x00); - let b: u64x1 = u64x1::new(0x0F); - let e: u64x1 = u64x1::new(0x00); - let r: u64x1 = transmute(vand_u64(transmute(a), transmute(b))); + unsafe fn test_vmlaq_laneq_u32() { + let a: u32x4 = u32x4::new(0, 1, 2, 3); + let b: u32x4 = u32x4::new(2, 2, 2, 2); + let c: u32x4 = u32x4::new(0, 3, 0, 0); + let e: u32x4 = u32x4::new(6, 7, 8, 9); + let r: u32x4 = transmute(vmlaq_laneq_u32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); + } - let a: u64x1 = u64x1::new(0x00); - let b: u64x1 = u64x1::new(0x00); - let e: u64x1 = u64x1::new(0x00); - let r: u64x1 = transmute(vand_u64(transmute(a), transmute(b))); + #[simd_test(enable = "neon")] + unsafe fn test_vmla_lane_f32() { + let a: f32x2 = f32x2::new(0., 1.); + let b: f32x2 = f32x2::new(2., 2.); + let c: f32x2 = f32x2::new(0., 3.); + let e: f32x2 = f32x2::new(6., 7.); + let r: f32x2 = transmute(vmla_lane_f32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vandq_u64() { - let a: u64x2 = u64x2::new(0x00, 0x01); - let b: u64x2 = u64x2::new(0x0F, 0x0F); - let e: u64x2 = u64x2::new(0x00, 0x01); - let r: u64x2 = transmute(vandq_u64(transmute(a), transmute(b))); + unsafe fn test_vmla_laneq_f32() { + let a: f32x2 = f32x2::new(0., 1.); + let b: f32x2 = f32x2::new(2., 2.); + let c: f32x4 = f32x4::new(0., 3., 0., 0.); + let e: f32x2 = f32x2::new(6., 7.); + let r: f32x2 = transmute(vmla_laneq_f32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); + } - let a: u64x2 = u64x2::new(0x00, 0x01); - let b: u64x2 = u64x2::new(0x00, 0x00); - let e: u64x2 = u64x2::new(0x00, 0x00); - let r: u64x2 = transmute(vandq_u64(transmute(a), transmute(b))); + #[simd_test(enable = "neon")] + unsafe fn test_vmlaq_lane_f32() { + let a: f32x4 = f32x4::new(0., 1., 2., 3.); + let b: f32x4 = f32x4::new(2., 2., 2., 2.); + let c: f32x2 = f32x2::new(0., 3.); + let e: f32x4 = f32x4::new(6., 7., 8., 9.); + let r: f32x4 = transmute(vmlaq_lane_f32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vorr_s8() { - let a: i8x8 = i8x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let b: i8x8 = i8x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - let e: i8x8 = i8x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let r: i8x8 = transmute(vorr_s8(transmute(a), transmute(b))); + unsafe fn test_vmlaq_laneq_f32() { + let a: f32x4 = f32x4::new(0., 1., 2., 3.); + let b: f32x4 = f32x4::new(2., 2., 2., 2.); + let c: f32x4 = f32x4::new(0., 3., 0., 0.); + let e: f32x4 = f32x4::new(6., 7., 8., 9.); + let r: f32x4 = transmute(vmlaq_laneq_f32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vorrq_s8() { - let a: i8x16 = i8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F); - let b: i8x16 = i8x16::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - let e: i8x16 = i8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F); - let r: i8x16 = transmute(vorrq_s8(transmute(a), transmute(b))); + unsafe fn test_vmlal_s8() { + let a: i16x8 = i16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let b: i8x8 = i8x8::new(2, 2, 2, 2, 2, 2, 2, 2); + let c: i8x8 = i8x8::new(3, 3, 3, 3, 3, 3, 3, 3); + let e: i16x8 = i16x8::new(6, 7, 8, 9, 10, 11, 12, 13); + let r: i16x8 = transmute(vmlal_s8(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vorr_s16() { - let a: i16x4 = i16x4::new(0x00, 0x01, 0x02, 0x03); - let b: i16x4 = i16x4::new(0x00, 0x00, 0x00, 0x00); - let e: i16x4 = i16x4::new(0x00, 0x01, 0x02, 0x03); - let r: i16x4 = transmute(vorr_s16(transmute(a), transmute(b))); + unsafe fn test_vmlal_s16() { + let a: i32x4 = i32x4::new(0, 1, 2, 3); + let b: i16x4 = i16x4::new(2, 2, 2, 2); + let c: i16x4 = i16x4::new(3, 3, 3, 3); + let e: i32x4 = i32x4::new(6, 7, 8, 9); + let r: i32x4 = transmute(vmlal_s16(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vorrq_s16() { - let a: i16x8 = i16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let b: i16x8 = i16x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - let e: i16x8 = i16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let r: i16x8 = transmute(vorrq_s16(transmute(a), transmute(b))); + unsafe fn test_vmlal_s32() { + let a: i64x2 = i64x2::new(0, 1); + let b: i32x2 = i32x2::new(2, 2); + let c: i32x2 = i32x2::new(3, 3); + let e: i64x2 = i64x2::new(6, 7); + let r: i64x2 = transmute(vmlal_s32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vorr_s32() { - let a: i32x2 = i32x2::new(0x00, 0x01); - let b: i32x2 = i32x2::new(0x00, 0x00); - let e: i32x2 = i32x2::new(0x00, 0x01); - let r: i32x2 = transmute(vorr_s32(transmute(a), transmute(b))); + unsafe fn test_vmlal_u8() { + let a: u16x8 = u16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let b: u8x8 = u8x8::new(2, 2, 2, 2, 2, 2, 2, 2); + let c: u8x8 = u8x8::new(3, 3, 3, 3, 3, 3, 3, 3); + let e: u16x8 = u16x8::new(6, 7, 8, 9, 10, 11, 12, 13); + let r: u16x8 = transmute(vmlal_u8(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vorrq_s32() { - let a: i32x4 = i32x4::new(0x00, 0x01, 0x02, 0x03); - let b: i32x4 = i32x4::new(0x00, 0x00, 0x00, 0x00); - let e: i32x4 = i32x4::new(0x00, 0x01, 0x02, 0x03); - let r: i32x4 = transmute(vorrq_s32(transmute(a), transmute(b))); + unsafe fn test_vmlal_u16() { + let a: u32x4 = u32x4::new(0, 1, 2, 3); + let b: u16x4 = u16x4::new(2, 2, 2, 2); + let c: u16x4 = u16x4::new(3, 3, 3, 3); + let e: u32x4 = u32x4::new(6, 7, 8, 9); + let r: u32x4 = transmute(vmlal_u16(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vorr_u8() { - let a: u8x8 = u8x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let b: u8x8 = u8x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - let e: u8x8 = u8x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let r: u8x8 = transmute(vorr_u8(transmute(a), transmute(b))); + unsafe fn test_vmlal_u32() { + let a: u64x2 = u64x2::new(0, 1); + let b: u32x2 = u32x2::new(2, 2); + let c: u32x2 = u32x2::new(3, 3); + let e: u64x2 = u64x2::new(6, 7); + let r: u64x2 = transmute(vmlal_u32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vorrq_u8() { - let a: u8x16 = u8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F); - let b: u8x16 = u8x16::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - let e: u8x16 = u8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F); - let r: u8x16 = transmute(vorrq_u8(transmute(a), transmute(b))); + unsafe fn test_vmlal_n_s16() { + let a: i32x4 = i32x4::new(0, 1, 2, 3); + let b: i16x4 = i16x4::new(2, 2, 2, 2); + let c: i16 = 3; + let e: i32x4 = i32x4::new(6, 7, 8, 9); + let r: i32x4 = transmute(vmlal_n_s16(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vorr_u16() { - let a: u16x4 = u16x4::new(0x00, 0x01, 0x02, 0x03); - let b: u16x4 = u16x4::new(0x00, 0x00, 0x00, 0x00); - let e: u16x4 = u16x4::new(0x00, 0x01, 0x02, 0x03); - let r: u16x4 = transmute(vorr_u16(transmute(a), transmute(b))); + unsafe fn test_vmlal_n_s32() { + let a: i64x2 = i64x2::new(0, 1); + let b: i32x2 = i32x2::new(2, 2); + let c: i32 = 3; + let e: i64x2 = i64x2::new(6, 7); + let r: i64x2 = transmute(vmlal_n_s32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vorrq_u16() { - let a: u16x8 = u16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let b: u16x8 = u16x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - let e: u16x8 = u16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let r: u16x8 = transmute(vorrq_u16(transmute(a), transmute(b))); + unsafe fn test_vmlal_n_u16() { + let a: u32x4 = u32x4::new(0, 1, 2, 3); + let b: u16x4 = u16x4::new(2, 2, 2, 2); + let c: u16 = 3; + let e: u32x4 = u32x4::new(6, 7, 8, 9); + let r: u32x4 = transmute(vmlal_n_u16(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vorr_u32() { - let a: u32x2 = u32x2::new(0x00, 0x01); - let b: u32x2 = u32x2::new(0x00, 0x00); - let e: u32x2 = u32x2::new(0x00, 0x01); - let r: u32x2 = transmute(vorr_u32(transmute(a), transmute(b))); + unsafe fn test_vmlal_n_u32() { + let a: u64x2 = u64x2::new(0, 1); + let b: u32x2 = u32x2::new(2, 2); + let c: u32 = 3; + let e: u64x2 = u64x2::new(6, 7); + let r: u64x2 = transmute(vmlal_n_u32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vorrq_u32() { - let a: u32x4 = u32x4::new(0x00, 0x01, 0x02, 0x03); - let b: u32x4 = u32x4::new(0x00, 0x00, 0x00, 0x00); - let e: u32x4 = u32x4::new(0x00, 0x01, 0x02, 0x03); - let r: u32x4 = transmute(vorrq_u32(transmute(a), transmute(b))); + unsafe fn test_vmlal_lane_s16() { + let a: i32x4 = i32x4::new(0, 1, 2, 3); + let b: i16x4 = i16x4::new(2, 2, 2, 2); + let c: i16x4 = i16x4::new(0, 3, 0, 0); + let e: i32x4 = i32x4::new(6, 7, 8, 9); + let r: i32x4 = transmute(vmlal_lane_s16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vorr_s64() { - let a: i64x1 = i64x1::new(0x00); - let b: i64x1 = i64x1::new(0x00); - let e: i64x1 = i64x1::new(0x00); - let r: i64x1 = transmute(vorr_s64(transmute(a), transmute(b))); + unsafe fn test_vmlal_laneq_s16() { + let a: i32x4 = i32x4::new(0, 1, 2, 3); + let b: i16x4 = i16x4::new(2, 2, 2, 2); + let c: i16x8 = i16x8::new(0, 3, 0, 0, 0, 0, 0, 0); + let e: i32x4 = i32x4::new(6, 7, 8, 9); + let r: i32x4 = transmute(vmlal_laneq_s16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vorrq_s64() { - let a: i64x2 = i64x2::new(0x00, 0x01); - let b: i64x2 = i64x2::new(0x00, 0x00); - let e: i64x2 = i64x2::new(0x00, 0x01); - let r: i64x2 = transmute(vorrq_s64(transmute(a), transmute(b))); + unsafe fn test_vmlal_lane_s32() { + let a: i64x2 = i64x2::new(0, 1); + let b: i32x2 = i32x2::new(2, 2); + let c: i32x2 = i32x2::new(0, 3); + let e: i64x2 = i64x2::new(6, 7); + let r: i64x2 = transmute(vmlal_lane_s32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vorr_u64() { - let a: u64x1 = u64x1::new(0x00); - let b: u64x1 = u64x1::new(0x00); - let e: u64x1 = u64x1::new(0x00); - let r: u64x1 = transmute(vorr_u64(transmute(a), transmute(b))); + unsafe fn test_vmlal_laneq_s32() { + let a: i64x2 = i64x2::new(0, 1); + let b: i32x2 = i32x2::new(2, 2); + let c: i32x4 = i32x4::new(0, 3, 0, 0); + let e: i64x2 = i64x2::new(6, 7); + let r: i64x2 = transmute(vmlal_laneq_s32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vorrq_u64() { - let a: u64x2 = u64x2::new(0x00, 0x01); - let b: u64x2 = u64x2::new(0x00, 0x00); - let e: u64x2 = u64x2::new(0x00, 0x01); - let r: u64x2 = transmute(vorrq_u64(transmute(a), transmute(b))); + unsafe fn test_vmlal_lane_u16() { + let a: u32x4 = u32x4::new(0, 1, 2, 3); + let b: u16x4 = u16x4::new(2, 2, 2, 2); + let c: u16x4 = u16x4::new(0, 3, 0, 0); + let e: u32x4 = u32x4::new(6, 7, 8, 9); + let r: u32x4 = transmute(vmlal_lane_u16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_veor_s8() { - let a: i8x8 = i8x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let b: i8x8 = i8x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - let e: i8x8 = i8x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let r: i8x8 = transmute(veor_s8(transmute(a), transmute(b))); + unsafe fn test_vmlal_laneq_u16() { + let a: u32x4 = u32x4::new(0, 1, 2, 3); + let b: u16x4 = u16x4::new(2, 2, 2, 2); + let c: u16x8 = u16x8::new(0, 3, 0, 0, 0, 0, 0, 0); + let e: u32x4 = u32x4::new(6, 7, 8, 9); + let r: u32x4 = transmute(vmlal_laneq_u16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_veorq_s8() { - let a: i8x16 = i8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F); - let b: i8x16 = i8x16::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - let e: i8x16 = i8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F); - let r: i8x16 = transmute(veorq_s8(transmute(a), transmute(b))); + unsafe fn test_vmlal_lane_u32() { + let a: u64x2 = u64x2::new(0, 1); + let b: u32x2 = u32x2::new(2, 2); + let c: u32x2 = u32x2::new(0, 3); + let e: u64x2 = u64x2::new(6, 7); + let r: u64x2 = transmute(vmlal_lane_u32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_veor_s16() { - let a: i16x4 = i16x4::new(0x00, 0x01, 0x02, 0x03); - let b: i16x4 = i16x4::new(0x00, 0x00, 0x00, 0x00); - let e: i16x4 = i16x4::new(0x00, 0x01, 0x02, 0x03); - let r: i16x4 = transmute(veor_s16(transmute(a), transmute(b))); + unsafe fn test_vmlal_laneq_u32() { + let a: u64x2 = u64x2::new(0, 1); + let b: u32x2 = u32x2::new(2, 2); + let c: u32x4 = u32x4::new(0, 3, 0, 0); + let e: u64x2 = u64x2::new(6, 7); + let r: u64x2 = transmute(vmlal_laneq_u32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_veorq_s16() { - let a: i16x8 = i16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let b: i16x8 = i16x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - let e: i16x8 = i16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let r: i16x8 = transmute(veorq_s16(transmute(a), transmute(b))); + unsafe fn test_vmls_s8() { + let a: i8x8 = i8x8::new(6, 7, 8, 9, 10, 11, 12, 13); + let b: i8x8 = i8x8::new(2, 2, 2, 2, 2, 2, 2, 2); + let c: i8x8 = i8x8::new(3, 3, 3, 3, 3, 3, 3, 3); + let e: i8x8 = i8x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let r: i8x8 = transmute(vmls_s8(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_veor_s32() { - let a: i32x2 = i32x2::new(0x00, 0x01); - let b: i32x2 = i32x2::new(0x00, 0x00); - let e: i32x2 = i32x2::new(0x00, 0x01); - let r: i32x2 = transmute(veor_s32(transmute(a), transmute(b))); + unsafe fn test_vmlsq_s8() { + let a: i8x16 = i8x16::new(6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21); + let b: i8x16 = i8x16::new(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); + let c: i8x16 = i8x16::new(3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3); + let e: i8x16 = i8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let r: i8x16 = transmute(vmlsq_s8(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_veorq_s32() { - let a: i32x4 = i32x4::new(0x00, 0x01, 0x02, 0x03); - let b: i32x4 = i32x4::new(0x00, 0x00, 0x00, 0x00); - let e: i32x4 = i32x4::new(0x00, 0x01, 0x02, 0x03); - let r: i32x4 = transmute(veorq_s32(transmute(a), transmute(b))); + unsafe fn test_vmls_s16() { + let a: i16x4 = i16x4::new(6, 7, 8, 9); + let b: i16x4 = i16x4::new(2, 2, 2, 2); + let c: i16x4 = i16x4::new(3, 3, 3, 3); + let e: i16x4 = i16x4::new(0, 1, 2, 3); + let r: i16x4 = transmute(vmls_s16(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_veor_u8() { - let a: u8x8 = u8x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let b: u8x8 = u8x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - let e: u8x8 = u8x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let r: u8x8 = transmute(veor_u8(transmute(a), transmute(b))); + unsafe fn test_vmlsq_s16() { + let a: i16x8 = i16x8::new(6, 7, 8, 9, 10, 11, 12, 13); + let b: i16x8 = i16x8::new(2, 2, 2, 2, 2, 2, 2, 2); + let c: i16x8 = i16x8::new(3, 3, 3, 3, 3, 3, 3, 3); + let e: i16x8 = i16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let r: i16x8 = transmute(vmlsq_s16(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_veorq_u8() { - let a: u8x16 = u8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F); - let b: u8x16 = u8x16::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - let e: u8x16 = u8x16::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F); - let r: u8x16 = transmute(veorq_u8(transmute(a), transmute(b))); + unsafe fn test_vmls_s32() { + let a: i32x2 = i32x2::new(6, 7); + let b: i32x2 = i32x2::new(2, 2); + let c: i32x2 = i32x2::new(3, 3); + let e: i32x2 = i32x2::new(0, 1); + let r: i32x2 = transmute(vmls_s32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_veor_u16() { - let a: u16x4 = u16x4::new(0x00, 0x01, 0x02, 0x03); - let b: u16x4 = u16x4::new(0x00, 0x00, 0x00, 0x00); - let e: u16x4 = u16x4::new(0x00, 0x01, 0x02, 0x03); - let r: u16x4 = transmute(veor_u16(transmute(a), transmute(b))); + unsafe fn test_vmlsq_s32() { + let a: i32x4 = i32x4::new(6, 7, 8, 9); + let b: i32x4 = i32x4::new(2, 2, 2, 2); + let c: i32x4 = i32x4::new(3, 3, 3, 3); + let e: i32x4 = i32x4::new(0, 1, 2, 3); + let r: i32x4 = transmute(vmlsq_s32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_veorq_u16() { - let a: u16x8 = u16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let b: u16x8 = u16x8::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - let e: u16x8 = u16x8::new(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let r: u16x8 = transmute(veorq_u16(transmute(a), transmute(b))); + unsafe fn test_vmls_u8() { + let a: u8x8 = u8x8::new(6, 7, 8, 9, 10, 11, 12, 13); + let b: u8x8 = u8x8::new(2, 2, 2, 2, 2, 2, 2, 2); + let c: u8x8 = u8x8::new(3, 3, 3, 3, 3, 3, 3, 3); + let e: u8x8 = u8x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let r: u8x8 = transmute(vmls_u8(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_veor_u32() { - let a: u32x2 = u32x2::new(0x00, 0x01); - let b: u32x2 = u32x2::new(0x00, 0x00); - let e: u32x2 = u32x2::new(0x00, 0x01); - let r: u32x2 = transmute(veor_u32(transmute(a), transmute(b))); + unsafe fn test_vmlsq_u8() { + let a: u8x16 = u8x16::new(6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21); + let b: u8x16 = u8x16::new(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); + let c: u8x16 = u8x16::new(3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3); + let e: u8x16 = u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let r: u8x16 = transmute(vmlsq_u8(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_veorq_u32() { - let a: u32x4 = u32x4::new(0x00, 0x01, 0x02, 0x03); - let b: u32x4 = u32x4::new(0x00, 0x00, 0x00, 0x00); - let e: u32x4 = u32x4::new(0x00, 0x01, 0x02, 0x03); - let r: u32x4 = transmute(veorq_u32(transmute(a), transmute(b))); + unsafe fn test_vmls_u16() { + let a: u16x4 = u16x4::new(6, 7, 8, 9); + let b: u16x4 = u16x4::new(2, 2, 2, 2); + let c: u16x4 = u16x4::new(3, 3, 3, 3); + let e: u16x4 = u16x4::new(0, 1, 2, 3); + let r: u16x4 = transmute(vmls_u16(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_veor_s64() { - let a: i64x1 = i64x1::new(0x00); - let b: i64x1 = i64x1::new(0x00); - let e: i64x1 = i64x1::new(0x00); - let r: i64x1 = transmute(veor_s64(transmute(a), transmute(b))); + unsafe fn test_vmlsq_u16() { + let a: u16x8 = u16x8::new(6, 7, 8, 9, 10, 11, 12, 13); + let b: u16x8 = u16x8::new(2, 2, 2, 2, 2, 2, 2, 2); + let c: u16x8 = u16x8::new(3, 3, 3, 3, 3, 3, 3, 3); + let e: u16x8 = u16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let r: u16x8 = transmute(vmlsq_u16(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_veorq_s64() { - let a: i64x2 = i64x2::new(0x00, 0x01); - let b: i64x2 = i64x2::new(0x00, 0x00); - let e: i64x2 = i64x2::new(0x00, 0x01); - let r: i64x2 = transmute(veorq_s64(transmute(a), transmute(b))); + unsafe fn test_vmls_u32() { + let a: u32x2 = u32x2::new(6, 7); + let b: u32x2 = u32x2::new(2, 2); + let c: u32x2 = u32x2::new(3, 3); + let e: u32x2 = u32x2::new(0, 1); + let r: u32x2 = transmute(vmls_u32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_veor_u64() { - let a: u64x1 = u64x1::new(0x00); - let b: u64x1 = u64x1::new(0x00); - let e: u64x1 = u64x1::new(0x00); - let r: u64x1 = transmute(veor_u64(transmute(a), transmute(b))); + unsafe fn test_vmlsq_u32() { + let a: u32x4 = u32x4::new(6, 7, 8, 9); + let b: u32x4 = u32x4::new(2, 2, 2, 2); + let c: u32x4 = u32x4::new(3, 3, 3, 3); + let e: u32x4 = u32x4::new(0, 1, 2, 3); + let r: u32x4 = transmute(vmlsq_u32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_veorq_u64() { - let a: u64x2 = u64x2::new(0x00, 0x01); - let b: u64x2 = u64x2::new(0x00, 0x00); - let e: u64x2 = u64x2::new(0x00, 0x01); - let r: u64x2 = transmute(veorq_u64(transmute(a), transmute(b))); + unsafe fn test_vmls_f32() { + let a: f32x2 = f32x2::new(6., 7.); + let b: f32x2 = f32x2::new(2., 2.); + let c: f32x2 = f32x2::new(3., 3.); + let e: f32x2 = f32x2::new(0., 1.); + let r: f32x2 = transmute(vmls_f32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vabd_s8() { - let a: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let b: i8x8 = i8x8::new(16, 15, 14, 13, 12, 11, 10, 9); - let e: i8x8 = i8x8::new(15, 13, 11, 9, 7, 5, 3, 1); - let r: i8x8 = transmute(vabd_s8(transmute(a), transmute(b))); + unsafe fn test_vmlsq_f32() { + let a: f32x4 = f32x4::new(6., 7., 8., 9.); + let b: f32x4 = f32x4::new(2., 2., 2., 2.); + let c: f32x4 = f32x4::new(3., 3., 3., 3.); + let e: f32x4 = f32x4::new(0., 1., 2., 3.); + let r: f32x4 = transmute(vmlsq_f32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vabdq_s8() { - let a: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let b: i8x16 = i8x16::new(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); - let e: i8x16 = i8x16::new(15, 13, 11, 9, 7, 5, 3, 1, 1, 3, 5, 7, 9, 11, 13, 15); - let r: i8x16 = transmute(vabdq_s8(transmute(a), transmute(b))); + unsafe fn test_vmls_n_s16() { + let a: i16x4 = i16x4::new(6, 7, 8, 9); + let b: i16x4 = i16x4::new(2, 2, 2, 2); + let c: i16 = 3; + let e: i16x4 = i16x4::new(0, 1, 2, 3); + let r: i16x4 = transmute(vmls_n_s16(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vabd_s16() { - let a: i16x4 = i16x4::new(1, 2, 3, 4); - let b: i16x4 = i16x4::new(16, 15, 14, 13); - let e: i16x4 = i16x4::new(15, 13, 11, 9); - let r: i16x4 = transmute(vabd_s16(transmute(a), transmute(b))); + unsafe fn test_vmlsq_n_s16() { + let a: i16x8 = i16x8::new(6, 7, 8, 9, 10, 11, 12, 13); + let b: i16x8 = i16x8::new(2, 2, 2, 2, 2, 2, 2, 2); + let c: i16 = 3; + let e: i16x8 = i16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let r: i16x8 = transmute(vmlsq_n_s16(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vabdq_s16() { - let a: i16x8 = i16x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let b: i16x8 = i16x8::new(16, 15, 14, 13, 12, 11, 10, 9); - let e: i16x8 = i16x8::new(15, 13, 11, 9, 7, 5, 3, 1); - let r: i16x8 = transmute(vabdq_s16(transmute(a), transmute(b))); + unsafe fn test_vmls_n_s32() { + let a: i32x2 = i32x2::new(6, 7); + let b: i32x2 = i32x2::new(2, 2); + let c: i32 = 3; + let e: i32x2 = i32x2::new(0, 1); + let r: i32x2 = transmute(vmls_n_s32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vabd_s32() { - let a: i32x2 = i32x2::new(1, 2); - let b: i32x2 = i32x2::new(16, 15); - let e: i32x2 = i32x2::new(15, 13); - let r: i32x2 = transmute(vabd_s32(transmute(a), transmute(b))); + unsafe fn test_vmlsq_n_s32() { + let a: i32x4 = i32x4::new(6, 7, 8, 9); + let b: i32x4 = i32x4::new(2, 2, 2, 2); + let c: i32 = 3; + let e: i32x4 = i32x4::new(0, 1, 2, 3); + let r: i32x4 = transmute(vmlsq_n_s32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vabdq_s32() { - let a: i32x4 = i32x4::new(1, 2, 3, 4); - let b: i32x4 = i32x4::new(16, 15, 14, 13); - let e: i32x4 = i32x4::new(15, 13, 11, 9); - let r: i32x4 = transmute(vabdq_s32(transmute(a), transmute(b))); + unsafe fn test_vmls_n_u16() { + let a: u16x4 = u16x4::new(6, 7, 8, 9); + let b: u16x4 = u16x4::new(2, 2, 2, 2); + let c: u16 = 3; + let e: u16x4 = u16x4::new(0, 1, 2, 3); + let r: u16x4 = transmute(vmls_n_u16(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vabd_u8() { - let a: u8x8 = u8x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let b: u8x8 = u8x8::new(16, 15, 14, 13, 12, 11, 10, 9); - let e: u8x8 = u8x8::new(15, 13, 11, 9, 7, 5, 3, 1); - let r: u8x8 = transmute(vabd_u8(transmute(a), transmute(b))); + unsafe fn test_vmlsq_n_u16() { + let a: u16x8 = u16x8::new(6, 7, 8, 9, 10, 11, 12, 13); + let b: u16x8 = u16x8::new(2, 2, 2, 2, 2, 2, 2, 2); + let c: u16 = 3; + let e: u16x8 = u16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let r: u16x8 = transmute(vmlsq_n_u16(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vabdq_u8() { - let a: u8x16 = u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let b: u8x16 = u8x16::new(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); - let e: u8x16 = u8x16::new(15, 13, 11, 9, 7, 5, 3, 1, 1, 3, 5, 7, 9, 11, 13, 15); - let r: u8x16 = transmute(vabdq_u8(transmute(a), transmute(b))); + unsafe fn test_vmls_n_u32() { + let a: u32x2 = u32x2::new(6, 7); + let b: u32x2 = u32x2::new(2, 2); + let c: u32 = 3; + let e: u32x2 = u32x2::new(0, 1); + let r: u32x2 = transmute(vmls_n_u32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vabd_u16() { - let a: u16x4 = u16x4::new(1, 2, 3, 4); - let b: u16x4 = u16x4::new(16, 15, 14, 13); - let e: u16x4 = u16x4::new(15, 13, 11, 9); - let r: u16x4 = transmute(vabd_u16(transmute(a), transmute(b))); + unsafe fn test_vmlsq_n_u32() { + let a: u32x4 = u32x4::new(6, 7, 8, 9); + let b: u32x4 = u32x4::new(2, 2, 2, 2); + let c: u32 = 3; + let e: u32x4 = u32x4::new(0, 1, 2, 3); + let r: u32x4 = transmute(vmlsq_n_u32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vabdq_u16() { - let a: u16x8 = u16x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let b: u16x8 = u16x8::new(16, 15, 14, 13, 12, 11, 10, 9); - let e: u16x8 = u16x8::new(15, 13, 11, 9, 7, 5, 3, 1); - let r: u16x8 = transmute(vabdq_u16(transmute(a), transmute(b))); + unsafe fn test_vmls_n_f32() { + let a: f32x2 = f32x2::new(6., 7.); + let b: f32x2 = f32x2::new(2., 2.); + let c: f32 = 3.; + let e: f32x2 = f32x2::new(0., 1.); + let r: f32x2 = transmute(vmls_n_f32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vabd_u32() { - let a: u32x2 = u32x2::new(1, 2); - let b: u32x2 = u32x2::new(16, 15); - let e: u32x2 = u32x2::new(15, 13); - let r: u32x2 = transmute(vabd_u32(transmute(a), transmute(b))); + unsafe fn test_vmlsq_n_f32() { + let a: f32x4 = f32x4::new(6., 7., 8., 9.); + let b: f32x4 = f32x4::new(2., 2., 2., 2.); + let c: f32 = 3.; + let e: f32x4 = f32x4::new(0., 1., 2., 3.); + let r: f32x4 = transmute(vmlsq_n_f32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vabdq_u32() { - let a: u32x4 = u32x4::new(1, 2, 3, 4); - let b: u32x4 = u32x4::new(16, 15, 14, 13); - let e: u32x4 = u32x4::new(15, 13, 11, 9); - let r: u32x4 = transmute(vabdq_u32(transmute(a), transmute(b))); + unsafe fn test_vmls_lane_s16() { + let a: i16x4 = i16x4::new(6, 7, 8, 9); + let b: i16x4 = i16x4::new(2, 2, 2, 2); + let c: i16x4 = i16x4::new(0, 3, 0, 0); + let e: i16x4 = i16x4::new(0, 1, 2, 3); + let r: i16x4 = transmute(vmls_lane_s16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vabd_f32() { - let a: f32x2 = f32x2::new(1.0, 2.0); - let b: f32x2 = f32x2::new(9.0, 3.0); - let e: f32x2 = f32x2::new(8.0, 1.0); - let r: f32x2 = transmute(vabd_f32(transmute(a), transmute(b))); + unsafe fn test_vmls_laneq_s16() { + let a: i16x4 = i16x4::new(6, 7, 8, 9); + let b: i16x4 = i16x4::new(2, 2, 2, 2); + let c: i16x8 = i16x8::new(0, 3, 0, 0, 0, 0, 0, 0); + let e: i16x4 = i16x4::new(0, 1, 2, 3); + let r: i16x4 = transmute(vmls_laneq_s16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vabdq_f32() { - let a: f32x4 = f32x4::new(1.0, 2.0, 5.0, -4.0); - let b: f32x4 = f32x4::new(9.0, 3.0, 2.0, 8.0); - let e: f32x4 = f32x4::new(8.0, 1.0, 3.0, 12.0); - let r: f32x4 = transmute(vabdq_f32(transmute(a), transmute(b))); + unsafe fn test_vmlsq_lane_s16() { + let a: i16x8 = i16x8::new(6, 7, 8, 9, 10, 11, 12, 13); + let b: i16x8 = i16x8::new(2, 2, 2, 2, 2, 2, 2, 2); + let c: i16x4 = i16x4::new(0, 3, 0, 0); + let e: i16x8 = i16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let r: i16x8 = transmute(vmlsq_lane_s16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vabdl_u8() { - let a: u8x8 = u8x8::new(1, 2, 3, 4, 4, 3, 2, 1); - let b: u8x8 = u8x8::new(10, 10, 10, 10, 10, 10, 10, 10); - let e: u16x8 = u16x8::new(9, 8, 7, 6, 6, 7, 8, 9); - let r: u16x8 = transmute(vabdl_u8(transmute(a), transmute(b))); + unsafe fn test_vmlsq_laneq_s16() { + let a: i16x8 = i16x8::new(6, 7, 8, 9, 10, 11, 12, 13); + let b: i16x8 = i16x8::new(2, 2, 2, 2, 2, 2, 2, 2); + let c: i16x8 = i16x8::new(0, 3, 0, 0, 0, 0, 0, 0); + let e: i16x8 = i16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let r: i16x8 = transmute(vmlsq_laneq_s16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vabdl_u16() { - let a: u16x4 = u16x4::new(1, 2, 3, 4); - let b: u16x4 = u16x4::new(10, 10, 10, 10); - let e: u32x4 = u32x4::new(9, 8, 7, 6); - let r: u32x4 = transmute(vabdl_u16(transmute(a), transmute(b))); + unsafe fn test_vmls_lane_s32() { + let a: i32x2 = i32x2::new(6, 7); + let b: i32x2 = i32x2::new(2, 2); + let c: i32x2 = i32x2::new(0, 3); + let e: i32x2 = i32x2::new(0, 1); + let r: i32x2 = transmute(vmls_lane_s32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vabdl_u32() { - let a: u32x2 = u32x2::new(1, 2); - let b: u32x2 = u32x2::new(10, 10); - let e: u64x2 = u64x2::new(9, 8); - let r: u64x2 = transmute(vabdl_u32(transmute(a), transmute(b))); + unsafe fn test_vmls_laneq_s32() { + let a: i32x2 = i32x2::new(6, 7); + let b: i32x2 = i32x2::new(2, 2); + let c: i32x4 = i32x4::new(0, 3, 0, 0); + let e: i32x2 = i32x2::new(0, 1); + let r: i32x2 = transmute(vmls_laneq_s32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vabdl_s8() { - let a: i8x8 = i8x8::new(1, 2, 3, 4, 4, 3, 2, 1); - let b: i8x8 = i8x8::new(10, 10, 10, 10, 10, 10, 10, 10); - let e: i16x8 = i16x8::new(9, 8, 7, 6, 6, 7, 8, 9); - let r: i16x8 = transmute(vabdl_s8(transmute(a), transmute(b))); + unsafe fn test_vmlsq_lane_s32() { + let a: i32x4 = i32x4::new(6, 7, 8, 9); + let b: i32x4 = i32x4::new(2, 2, 2, 2); + let c: i32x2 = i32x2::new(0, 3); + let e: i32x4 = i32x4::new(0, 1, 2, 3); + let r: i32x4 = transmute(vmlsq_lane_s32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vabdl_s16() { - let a: i16x4 = i16x4::new(1, 2, 11, 12); - let b: i16x4 = i16x4::new(10, 10, 10, 10); - let e: i32x4 = i32x4::new(9, 8, 1, 2); - let r: i32x4 = transmute(vabdl_s16(transmute(a), transmute(b))); + unsafe fn test_vmlsq_laneq_s32() { + let a: i32x4 = i32x4::new(6, 7, 8, 9); + let b: i32x4 = i32x4::new(2, 2, 2, 2); + let c: i32x4 = i32x4::new(0, 3, 0, 0); + let e: i32x4 = i32x4::new(0, 1, 2, 3); + let r: i32x4 = transmute(vmlsq_laneq_s32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vabdl_s32() { - let a: i32x2 = i32x2::new(1, 11); - let b: i32x2 = i32x2::new(10, 10); - let e: i64x2 = i64x2::new(9, 1); - let r: i64x2 = transmute(vabdl_s32(transmute(a), transmute(b))); + unsafe fn test_vmls_lane_u16() { + let a: u16x4 = u16x4::new(6, 7, 8, 9); + let b: u16x4 = u16x4::new(2, 2, 2, 2); + let c: u16x4 = u16x4::new(0, 3, 0, 0); + let e: u16x4 = u16x4::new(0, 1, 2, 3); + let r: u16x4 = transmute(vmls_lane_u16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceq_u8() { - let a: u8x8 = u8x8::new(0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let b: u8x8 = u8x8::new(0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let e: u8x8 = u8x8::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x8 = transmute(vceq_u8(transmute(a), transmute(b))); - assert_eq!(r, e); - - let a: u8x8 = u8x8::new(0, 0, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let b: u8x8 = u8x8::new(0, 0xFF, 0x02, 0x04, 0x04, 0x00, 0x06, 0x08); - let e: u8x8 = u8x8::new(0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0); - let r: u8x8 = transmute(vceq_u8(transmute(a), transmute(b))); + unsafe fn test_vmls_laneq_u16() { + let a: u16x4 = u16x4::new(6, 7, 8, 9); + let b: u16x4 = u16x4::new(2, 2, 2, 2); + let c: u16x8 = u16x8::new(0, 3, 0, 0, 0, 0, 0, 0); + let e: u16x4 = u16x4::new(0, 1, 2, 3); + let r: u16x4 = transmute(vmls_laneq_u16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqq_u8() { - let a: u8x16 = u8x16::new(0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0xFF); - let b: u8x16 = u8x16::new(0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0xFF); - let e: u8x16 = u8x16::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x16 = transmute(vceqq_u8(transmute(a), transmute(b))); - assert_eq!(r, e); - - let a: u8x16 = u8x16::new(0, 0, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0xCC, 0x0D, 0xEE, 0xFF); - let b: u8x16 = u8x16::new(0, 0xFF, 0x02, 0x04, 0x04, 0x00, 0x06, 0x08, 0x08, 0x00, 0x0A, 0x0A, 0xCC, 0xD0, 0xEE, 0); - let e: u8x16 = u8x16::new(0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0); - let r: u8x16 = transmute(vceqq_u8(transmute(a), transmute(b))); + unsafe fn test_vmlsq_lane_u16() { + let a: u16x8 = u16x8::new(6, 7, 8, 9, 10, 11, 12, 13); + let b: u16x8 = u16x8::new(2, 2, 2, 2, 2, 2, 2, 2); + let c: u16x4 = u16x4::new(0, 3, 0, 0); + let e: u16x8 = u16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let r: u16x8 = transmute(vmlsq_lane_u16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceq_u16() { - let a: u16x4 = u16x4::new(0, 0x01, 0x02, 0x03); - let b: u16x4 = u16x4::new(0, 0x01, 0x02, 0x03); - let e: u16x4 = u16x4::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); - let r: u16x4 = transmute(vceq_u16(transmute(a), transmute(b))); - assert_eq!(r, e); - - let a: u16x4 = u16x4::new(0, 0, 0x02, 0x03); - let b: u16x4 = u16x4::new(0, 0xFF_FF, 0x02, 0x04); - let e: u16x4 = u16x4::new(0xFF_FF, 0, 0xFF_FF, 0); - let r: u16x4 = transmute(vceq_u16(transmute(a), transmute(b))); + unsafe fn test_vmlsq_laneq_u16() { + let a: u16x8 = u16x8::new(6, 7, 8, 9, 10, 11, 12, 13); + let b: u16x8 = u16x8::new(2, 2, 2, 2, 2, 2, 2, 2); + let c: u16x8 = u16x8::new(0, 3, 0, 0, 0, 0, 0, 0); + let e: u16x8 = u16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let r: u16x8 = transmute(vmlsq_laneq_u16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqq_u16() { - let a: u16x8 = u16x8::new(0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let b: u16x8 = u16x8::new(0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let e: u16x8 = u16x8::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); - let r: u16x8 = transmute(vceqq_u16(transmute(a), transmute(b))); - assert_eq!(r, e); - - let a: u16x8 = u16x8::new(0, 0, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let b: u16x8 = u16x8::new(0, 0xFF_FF, 0x02, 0x04, 0x04, 0x00, 0x06, 0x08); - let e: u16x8 = u16x8::new(0xFF_FF, 0, 0xFF_FF, 0, 0xFF_FF, 0, 0xFF_FF, 0); - let r: u16x8 = transmute(vceqq_u16(transmute(a), transmute(b))); + unsafe fn test_vmls_lane_u32() { + let a: u32x2 = u32x2::new(6, 7); + let b: u32x2 = u32x2::new(2, 2); + let c: u32x2 = u32x2::new(0, 3); + let e: u32x2 = u32x2::new(0, 1); + let r: u32x2 = transmute(vmls_lane_u32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceq_u32() { - let a: u32x2 = u32x2::new(0, 0x01); - let b: u32x2 = u32x2::new(0, 0x01); - let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x2 = transmute(vceq_u32(transmute(a), transmute(b))); - assert_eq!(r, e); - - let a: u32x2 = u32x2::new(0, 0); - let b: u32x2 = u32x2::new(0, 0xFF_FF_FF_FF); - let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0); - let r: u32x2 = transmute(vceq_u32(transmute(a), transmute(b))); + unsafe fn test_vmls_laneq_u32() { + let a: u32x2 = u32x2::new(6, 7); + let b: u32x2 = u32x2::new(2, 2); + let c: u32x4 = u32x4::new(0, 3, 0, 0); + let e: u32x2 = u32x2::new(0, 1); + let r: u32x2 = transmute(vmls_laneq_u32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqq_u32() { - let a: u32x4 = u32x4::new(0, 0x01, 0x02, 0x03); - let b: u32x4 = u32x4::new(0, 0x01, 0x02, 0x03); - let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x4 = transmute(vceqq_u32(transmute(a), transmute(b))); - assert_eq!(r, e); - - let a: u32x4 = u32x4::new(0, 0, 0x02, 0x03); - let b: u32x4 = u32x4::new(0, 0xFF_FF_FF_FF, 0x02, 0x04); - let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0, 0xFF_FF_FF_FF, 0); - let r: u32x4 = transmute(vceqq_u32(transmute(a), transmute(b))); + unsafe fn test_vmlsq_lane_u32() { + let a: u32x4 = u32x4::new(6, 7, 8, 9); + let b: u32x4 = u32x4::new(2, 2, 2, 2); + let c: u32x2 = u32x2::new(0, 3); + let e: u32x4 = u32x4::new(0, 1, 2, 3); + let r: u32x4 = transmute(vmlsq_lane_u32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceq_s8() { - let a: i8x8 = i8x8::new(-128, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let b: i8x8 = i8x8::new(-128, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let e: u8x8 = u8x8::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x8 = transmute(vceq_s8(transmute(a), transmute(b))); - assert_eq!(r, e); - - let a: i8x8 = i8x8::new(-128, -128, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let b: i8x8 = i8x8::new(-128, 0x7F, 0x02, 0x04, 0x04, 0x00, 0x06, 0x08); - let e: u8x8 = u8x8::new(0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0); - let r: u8x8 = transmute(vceq_s8(transmute(a), transmute(b))); + unsafe fn test_vmlsq_laneq_u32() { + let a: u32x4 = u32x4::new(6, 7, 8, 9); + let b: u32x4 = u32x4::new(2, 2, 2, 2); + let c: u32x4 = u32x4::new(0, 3, 0, 0); + let e: u32x4 = u32x4::new(0, 1, 2, 3); + let r: u32x4 = transmute(vmlsq_laneq_u32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqq_s8() { - let a: i8x16 = i8x16::new(-128, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x7F); - let b: i8x16 = i8x16::new(-128, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x7F); - let e: u8x16 = u8x16::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x16 = transmute(vceqq_s8(transmute(a), transmute(b))); - assert_eq!(r, e); - - let a: i8x16 = i8x16::new(-128, -128, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0xCC, 0x0D, 0xEE, 0x7F); - let b: i8x16 = i8x16::new(-128, 0x7F, 0x02, 0x04, 0x04, 0x00, 0x06, 0x08, 0x08, 0x00, 0x0A, 0x0A, 0xCC, 0xD0, 0xEE, -128); - let e: u8x16 = u8x16::new(0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0); - let r: u8x16 = transmute(vceqq_s8(transmute(a), transmute(b))); + unsafe fn test_vmls_lane_f32() { + let a: f32x2 = f32x2::new(6., 7.); + let b: f32x2 = f32x2::new(2., 2.); + let c: f32x2 = f32x2::new(0., 3.); + let e: f32x2 = f32x2::new(0., 1.); + let r: f32x2 = transmute(vmls_lane_f32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceq_s16() { - let a: i16x4 = i16x4::new(-32768, 0x01, 0x02, 0x03); - let b: i16x4 = i16x4::new(-32768, 0x01, 0x02, 0x03); - let e: u16x4 = u16x4::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); - let r: u16x4 = transmute(vceq_s16(transmute(a), transmute(b))); + unsafe fn test_vmls_laneq_f32() { + let a: f32x2 = f32x2::new(6., 7.); + let b: f32x2 = f32x2::new(2., 2.); + let c: f32x4 = f32x4::new(0., 3., 0., 0.); + let e: f32x2 = f32x2::new(0., 1.); + let r: f32x2 = transmute(vmls_laneq_f32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); + } - let a: i16x4 = i16x4::new(-32768, -32768, 0x02, 0x03); - let b: i16x4 = i16x4::new(-32768, 0x7F_FF, 0x02, 0x04); - let e: u16x4 = u16x4::new(0xFF_FF, 0, 0xFF_FF, 0); - let r: u16x4 = transmute(vceq_s16(transmute(a), transmute(b))); + #[simd_test(enable = "neon")] + unsafe fn test_vmlsq_lane_f32() { + let a: f32x4 = f32x4::new(6., 7., 8., 9.); + let b: f32x4 = f32x4::new(2., 2., 2., 2.); + let c: f32x2 = f32x2::new(0., 3.); + let e: f32x4 = f32x4::new(0., 1., 2., 3.); + let r: f32x4 = transmute(vmlsq_lane_f32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqq_s16() { - let a: i16x8 = i16x8::new(-32768, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let b: i16x8 = i16x8::new(-32768, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let e: u16x8 = u16x8::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); - let r: u16x8 = transmute(vceqq_s16(transmute(a), transmute(b))); + unsafe fn test_vmlsq_laneq_f32() { + let a: f32x4 = f32x4::new(6., 7., 8., 9.); + let b: f32x4 = f32x4::new(2., 2., 2., 2.); + let c: f32x4 = f32x4::new(0., 3., 0., 0.); + let e: f32x4 = f32x4::new(0., 1., 2., 3.); + let r: f32x4 = transmute(vmlsq_laneq_f32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); + } - let a: i16x8 = i16x8::new(-32768, -32768, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let b: i16x8 = i16x8::new(-32768, 0x7F_FF, 0x02, 0x04, 0x04, 0x00, 0x06, 0x08); - let e: u16x8 = u16x8::new(0xFF_FF, 0, 0xFF_FF, 0, 0xFF_FF, 0, 0xFF_FF, 0); - let r: u16x8 = transmute(vceqq_s16(transmute(a), transmute(b))); + #[simd_test(enable = "neon")] + unsafe fn test_vmlsl_s8() { + let a: i16x8 = i16x8::new(6, 7, 8, 9, 10, 11, 12, 13); + let b: i8x8 = i8x8::new(2, 2, 2, 2, 2, 2, 2, 2); + let c: i8x8 = i8x8::new(3, 3, 3, 3, 3, 3, 3, 3); + let e: i16x8 = i16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let r: i16x8 = transmute(vmlsl_s8(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceq_s32() { - let a: i32x2 = i32x2::new(-2147483648, 0x01); - let b: i32x2 = i32x2::new(-2147483648, 0x01); - let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x2 = transmute(vceq_s32(transmute(a), transmute(b))); + unsafe fn test_vmlsl_s16() { + let a: i32x4 = i32x4::new(6, 7, 8, 9); + let b: i16x4 = i16x4::new(2, 2, 2, 2); + let c: i16x4 = i16x4::new(3, 3, 3, 3); + let e: i32x4 = i32x4::new(0, 1, 2, 3); + let r: i32x4 = transmute(vmlsl_s16(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); + } - let a: i32x2 = i32x2::new(-2147483648, -2147483648); - let b: i32x2 = i32x2::new(-2147483648, 0x7F_FF_FF_FF); - let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0); - let r: u32x2 = transmute(vceq_s32(transmute(a), transmute(b))); + #[simd_test(enable = "neon")] + unsafe fn test_vmlsl_s32() { + let a: i64x2 = i64x2::new(6, 7); + let b: i32x2 = i32x2::new(2, 2); + let c: i32x2 = i32x2::new(3, 3); + let e: i64x2 = i64x2::new(0, 1); + let r: i64x2 = transmute(vmlsl_s32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqq_s32() { - let a: i32x4 = i32x4::new(-2147483648, 0x01, 0x02, 0x03); - let b: i32x4 = i32x4::new(-2147483648, 0x01, 0x02, 0x03); - let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x4 = transmute(vceqq_s32(transmute(a), transmute(b))); - assert_eq!(r, e); - - let a: i32x4 = i32x4::new(-2147483648, -2147483648, 0x02, 0x03); - let b: i32x4 = i32x4::new(-2147483648, 0x7F_FF_FF_FF, 0x02, 0x04); - let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0, 0xFF_FF_FF_FF, 0); - let r: u32x4 = transmute(vceqq_s32(transmute(a), transmute(b))); + unsafe fn test_vmlsl_u8() { + let a: u16x8 = u16x8::new(6, 7, 8, 9, 10, 11, 12, 13); + let b: u8x8 = u8x8::new(2, 2, 2, 2, 2, 2, 2, 2); + let c: u8x8 = u8x8::new(3, 3, 3, 3, 3, 3, 3, 3); + let e: u16x8 = u16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let r: u16x8 = transmute(vmlsl_u8(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceq_p8() { - let a: i8x8 = i8x8::new(-128, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let b: i8x8 = i8x8::new(-128, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let e: u8x8 = u8x8::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x8 = transmute(vceq_p8(transmute(a), transmute(b))); + unsafe fn test_vmlsl_u16() { + let a: u32x4 = u32x4::new(6, 7, 8, 9); + let b: u16x4 = u16x4::new(2, 2, 2, 2); + let c: u16x4 = u16x4::new(3, 3, 3, 3); + let e: u32x4 = u32x4::new(0, 1, 2, 3); + let r: u32x4 = transmute(vmlsl_u16(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); + } - let a: i8x8 = i8x8::new(-128, -128, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); - let b: i8x8 = i8x8::new(-128, 0x7F, 0x02, 0x04, 0x04, 0x00, 0x06, 0x08); - let e: u8x8 = u8x8::new(0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0); - let r: u8x8 = transmute(vceq_p8(transmute(a), transmute(b))); + #[simd_test(enable = "neon")] + unsafe fn test_vmlsl_u32() { + let a: u64x2 = u64x2::new(6, 7); + let b: u32x2 = u32x2::new(2, 2); + let c: u32x2 = u32x2::new(3, 3); + let e: u64x2 = u64x2::new(0, 1); + let r: u64x2 = transmute(vmlsl_u32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqq_p8() { - let a: i8x16 = i8x16::new(-128, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x7F); - let b: i8x16 = i8x16::new(-128, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x7F); - let e: u8x16 = u8x16::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x16 = transmute(vceqq_p8(transmute(a), transmute(b))); + unsafe fn test_vmlsl_n_s16() { + let a: i32x4 = i32x4::new(6, 7, 8, 9); + let b: i16x4 = i16x4::new(2, 2, 2, 2); + let c: i16 = 3; + let e: i32x4 = i32x4::new(0, 1, 2, 3); + let r: i32x4 = transmute(vmlsl_n_s16(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); + } - let a: i8x16 = i8x16::new(-128, -128, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0xCC, 0x0D, 0xEE, 0x7F); - let b: i8x16 = i8x16::new(-128, 0x7F, 0x02, 0x04, 0x04, 0x00, 0x06, 0x08, 0x08, 0x00, 0x0A, 0x0A, 0xCC, 0xD0, 0xEE, -128); - let e: u8x16 = u8x16::new(0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0); - let r: u8x16 = transmute(vceqq_p8(transmute(a), transmute(b))); + #[simd_test(enable = "neon")] + unsafe fn test_vmlsl_n_s32() { + let a: i64x2 = i64x2::new(6, 7); + let b: i32x2 = i32x2::new(2, 2); + let c: i32 = 3; + let e: i64x2 = i64x2::new(0, 1); + let r: i64x2 = transmute(vmlsl_n_s32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceq_f32() { - let a: f32x2 = f32x2::new(1.2, 3.4); - let b: f32x2 = f32x2::new(1.2, 3.4); - let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x2 = transmute(vceq_f32(transmute(a), transmute(b))); + unsafe fn test_vmlsl_n_u16() { + let a: u32x4 = u32x4::new(6, 7, 8, 9); + let b: u16x4 = u16x4::new(2, 2, 2, 2); + let c: u16 = 3; + let e: u32x4 = u32x4::new(0, 1, 2, 3); + let r: u32x4 = transmute(vmlsl_n_u16(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vceqq_f32() { - let a: f32x4 = f32x4::new(1.2, 3.4, 5.6, 7.8); - let b: f32x4 = f32x4::new(1.2, 3.4, 5.6, 7.8); - let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x4 = transmute(vceqq_f32(transmute(a), transmute(b))); + unsafe fn test_vmlsl_n_u32() { + let a: u64x2 = u64x2::new(6, 7); + let b: u32x2 = u32x2::new(2, 2); + let c: u32 = 3; + let e: u64x2 = u64x2::new(0, 1); + let r: u64x2 = transmute(vmlsl_n_u32(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vtst_s8() { - let a: i8x8 = i8x8::new(-128, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); - let b: i8x8 = i8x8::new(-128, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); - let e: u8x8 = u8x8::new(0xFF, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x8 = transmute(vtst_s8(transmute(a), transmute(b))); + unsafe fn test_vmlsl_lane_s16() { + let a: i32x4 = i32x4::new(6, 7, 8, 9); + let b: i16x4 = i16x4::new(2, 2, 2, 2); + let c: i16x4 = i16x4::new(0, 3, 0, 0); + let e: i32x4 = i32x4::new(0, 1, 2, 3); + let r: i32x4 = transmute(vmlsl_lane_s16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vtstq_s8() { - let a: i8x16 = i8x16::new(-128, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x7F); - let b: i8x16 = i8x16::new(-128, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x7F); - let e: u8x16 = u8x16::new(0xFF, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x16 = transmute(vtstq_s8(transmute(a), transmute(b))); + unsafe fn test_vmlsl_laneq_s16() { + let a: i32x4 = i32x4::new(6, 7, 8, 9); + let b: i16x4 = i16x4::new(2, 2, 2, 2); + let c: i16x8 = i16x8::new(0, 3, 0, 0, 0, 0, 0, 0); + let e: i32x4 = i32x4::new(0, 1, 2, 3); + let r: i32x4 = transmute(vmlsl_laneq_s16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vtst_s16() { - let a: i16x4 = i16x4::new(-32768, 0x00, 0x01, 0x02); - let b: i16x4 = i16x4::new(-32768, 0x00, 0x01, 0x02); - let e: u16x4 = u16x4::new(0xFF_FF, 0, 0xFF_FF, 0xFF_FF); - let r: u16x4 = transmute(vtst_s16(transmute(a), transmute(b))); + unsafe fn test_vmlsl_lane_s32() { + let a: i64x2 = i64x2::new(6, 7); + let b: i32x2 = i32x2::new(2, 2); + let c: i32x2 = i32x2::new(0, 3); + let e: i64x2 = i64x2::new(0, 1); + let r: i64x2 = transmute(vmlsl_lane_s32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vtstq_s16() { - let a: i16x8 = i16x8::new(-32768, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); - let b: i16x8 = i16x8::new(-32768, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); - let e: u16x8 = u16x8::new(0xFF_FF, 0, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); - let r: u16x8 = transmute(vtstq_s16(transmute(a), transmute(b))); + unsafe fn test_vmlsl_laneq_s32() { + let a: i64x2 = i64x2::new(6, 7); + let b: i32x2 = i32x2::new(2, 2); + let c: i32x4 = i32x4::new(0, 3, 0, 0); + let e: i64x2 = i64x2::new(0, 1); + let r: i64x2 = transmute(vmlsl_laneq_s32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vtst_s32() { - let a: i32x2 = i32x2::new(-2147483648, 0x00); - let b: i32x2 = i32x2::new(-2147483648, 0x00); - let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0); - let r: u32x2 = transmute(vtst_s32(transmute(a), transmute(b))); + unsafe fn test_vmlsl_lane_u16() { + let a: u32x4 = u32x4::new(6, 7, 8, 9); + let b: u16x4 = u16x4::new(2, 2, 2, 2); + let c: u16x4 = u16x4::new(0, 3, 0, 0); + let e: u32x4 = u32x4::new(0, 1, 2, 3); + let r: u32x4 = transmute(vmlsl_lane_u16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vtstq_s32() { - let a: i32x4 = i32x4::new(-2147483648, 0x00, 0x01, 0x02); - let b: i32x4 = i32x4::new(-2147483648, 0x00, 0x01, 0x02); - let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x4 = transmute(vtstq_s32(transmute(a), transmute(b))); + unsafe fn test_vmlsl_laneq_u16() { + let a: u32x4 = u32x4::new(6, 7, 8, 9); + let b: u16x4 = u16x4::new(2, 2, 2, 2); + let c: u16x8 = u16x8::new(0, 3, 0, 0, 0, 0, 0, 0); + let e: u32x4 = u32x4::new(0, 1, 2, 3); + let r: u32x4 = transmute(vmlsl_laneq_u16::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vtst_p8() { - let a: i8x8 = i8x8::new(-128, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); - let b: i8x8 = i8x8::new(-128, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); - let e: u8x8 = u8x8::new(0xFF, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x8 = transmute(vtst_p8(transmute(a), transmute(b))); + unsafe fn test_vmlsl_lane_u32() { + let a: u64x2 = u64x2::new(6, 7); + let b: u32x2 = u32x2::new(2, 2); + let c: u32x2 = u32x2::new(0, 3); + let e: u64x2 = u64x2::new(0, 1); + let r: u64x2 = transmute(vmlsl_lane_u32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vtstq_p8() { - let a: i8x16 = i8x16::new(-128, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x7F); - let b: i8x16 = i8x16::new(-128, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x7F); - let e: u8x16 = u8x16::new(0xFF, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x16 = transmute(vtstq_p8(transmute(a), transmute(b))); + unsafe fn test_vmlsl_laneq_u32() { + let a: u64x2 = u64x2::new(6, 7); + let b: u32x2 = u32x2::new(2, 2); + let c: u32x4 = u32x4::new(0, 3, 0, 0); + let e: u64x2 = u64x2::new(0, 1); + let r: u64x2 = transmute(vmlsl_laneq_u32::<1>(transmute(a), transmute(b), transmute(c))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vtst_u8() { - let a: u8x8 = u8x8::new(0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); - let b: u8x8 = u8x8::new(0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); - let e: u8x8 = u8x8::new(0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x8 = transmute(vtst_u8(transmute(a), transmute(b))); + unsafe fn test_vneg_s8() { + let a: i8x8 = i8x8::new(0, 1, -1, 2, -2, 3, -3, 4); + let e: i8x8 = i8x8::new(0, -1, 1, -2, 2, -3, 3, -4); + let r: i8x8 = transmute(vneg_s8(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vtstq_u8() { - let a: u8x16 = u8x16::new(0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0xFF); - let b: u8x16 = u8x16::new(0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0xFF); - let e: u8x16 = u8x16::new(0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x16 = transmute(vtstq_u8(transmute(a), transmute(b))); + unsafe fn test_vnegq_s8() { + let a: i8x16 = i8x16::new(0, 1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, 7, -7, 8); + let e: i8x16 = i8x16::new(0, -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7, -8); + let r: i8x16 = transmute(vnegq_s8(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vtst_u16() { - let a: u16x4 = u16x4::new(0, 0x00, 0x01, 0x02); - let b: u16x4 = u16x4::new(0, 0x00, 0x01, 0x02); - let e: u16x4 = u16x4::new(0, 0, 0xFF_FF, 0xFF_FF); - let r: u16x4 = transmute(vtst_u16(transmute(a), transmute(b))); + unsafe fn test_vneg_s16() { + let a: i16x4 = i16x4::new(0, 1, -1, 2); + let e: i16x4 = i16x4::new(0, -1, 1, -2); + let r: i16x4 = transmute(vneg_s16(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vtstq_u16() { - let a: u16x8 = u16x8::new(0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); - let b: u16x8 = u16x8::new(0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); - let e: u16x8 = u16x8::new(0, 0, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); - let r: u16x8 = transmute(vtstq_u16(transmute(a), transmute(b))); + unsafe fn test_vnegq_s16() { + let a: i16x8 = i16x8::new(0, 1, -1, 2, -2, 3, -3, 4); + let e: i16x8 = i16x8::new(0, -1, 1, -2, 2, -3, 3, -4); + let r: i16x8 = transmute(vnegq_s16(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vtst_u32() { - let a: u32x2 = u32x2::new(0, 0x00); - let b: u32x2 = u32x2::new(0, 0x00); - let e: u32x2 = u32x2::new(0, 0); - let r: u32x2 = transmute(vtst_u32(transmute(a), transmute(b))); + unsafe fn test_vneg_s32() { + let a: i32x2 = i32x2::new(0, 1); + let e: i32x2 = i32x2::new(0, -1); + let r: i32x2 = transmute(vneg_s32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vtstq_u32() { - let a: u32x4 = u32x4::new(0, 0x00, 0x01, 0x02); - let b: u32x4 = u32x4::new(0, 0x00, 0x01, 0x02); - let e: u32x4 = u32x4::new(0, 0, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x4 = transmute(vtstq_u32(transmute(a), transmute(b))); + unsafe fn test_vnegq_s32() { + let a: i32x4 = i32x4::new(0, 1, -1, 2); + let e: i32x4 = i32x4::new(0, -1, 1, -2); + let r: i32x4 = transmute(vnegq_s32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vabs_f32() { - let a: f32x2 = f32x2::new(-0.1, -2.2); - let e: f32x2 = f32x2::new(0.1, 2.2); - let r: f32x2 = transmute(vabs_f32(transmute(a))); + unsafe fn test_vneg_f32() { + let a: f32x2 = f32x2::new(0., 1.); + let e: f32x2 = f32x2::new(0., -1.); + let r: f32x2 = transmute(vneg_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vabsq_f32() { - let a: f32x4 = f32x4::new(-0.1, -2.2, -3.3, -6.6); - let e: f32x4 = f32x4::new(0.1, 2.2, 3.3, 6.6); - let r: f32x4 = transmute(vabsq_f32(transmute(a))); + unsafe fn test_vnegq_f32() { + let a: f32x4 = f32x4::new(0., 1., -1., 2.); + let e: f32x4 = f32x4::new(0., -1., 1., -2.); + let r: f32x4 = transmute(vnegq_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgt_s8() { - let a: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let b: i8x8 = i8x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let e: u8x8 = u8x8::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x8 = transmute(vcgt_s8(transmute(a), transmute(b))); + unsafe fn test_vqneg_s8() { + let a: i8x8 = i8x8::new(-128, 0, 1, -1, 2, -2, 3, -3); + let e: i8x8 = i8x8::new(0x7F, 0, -1, 1, -2, 2, -3, 3); + let r: i8x8 = transmute(vqneg_s8(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgtq_s8() { - let a: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let b: i8x16 = i8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - let e: u8x16 = u8x16::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x16 = transmute(vcgtq_s8(transmute(a), transmute(b))); + unsafe fn test_vqnegq_s8() { + let a: i8x16 = i8x16::new(-128, 0, 1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, 7, -7); + let e: i8x16 = i8x16::new(0x7F, 0, -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7); + let r: i8x16 = transmute(vqnegq_s8(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgt_s16() { - let a: i16x4 = i16x4::new(1, 2, 3, 4); - let b: i16x4 = i16x4::new(0, 1, 2, 3); - let e: u16x4 = u16x4::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); - let r: u16x4 = transmute(vcgt_s16(transmute(a), transmute(b))); + unsafe fn test_vqneg_s16() { + let a: i16x4 = i16x4::new(-32768, 0, 1, -1); + let e: i16x4 = i16x4::new(0x7F_FF, 0, -1, 1); + let r: i16x4 = transmute(vqneg_s16(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgtq_s16() { - let a: i16x8 = i16x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let b: i16x8 = i16x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let e: u16x8 = u16x8::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); - let r: u16x8 = transmute(vcgtq_s16(transmute(a), transmute(b))); + unsafe fn test_vqnegq_s16() { + let a: i16x8 = i16x8::new(-32768, 0, 1, -1, 2, -2, 3, -3); + let e: i16x8 = i16x8::new(0x7F_FF, 0, -1, 1, -2, 2, -3, 3); + let r: i16x8 = transmute(vqnegq_s16(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgt_s32() { - let a: i32x2 = i32x2::new(1, 2); - let b: i32x2 = i32x2::new(0, 1); - let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x2 = transmute(vcgt_s32(transmute(a), transmute(b))); + unsafe fn test_vqneg_s32() { + let a: i32x2 = i32x2::new(-2147483648, 0); + let e: i32x2 = i32x2::new(0x7F_FF_FF_FF, 0); + let r: i32x2 = transmute(vqneg_s32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgtq_s32() { - let a: i32x4 = i32x4::new(1, 2, 3, 4); - let b: i32x4 = i32x4::new(0, 1, 2, 3); - let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x4 = transmute(vcgtq_s32(transmute(a), transmute(b))); + unsafe fn test_vqnegq_s32() { + let a: i32x4 = i32x4::new(-2147483648, 0, 1, -1); + let e: i32x4 = i32x4::new(0x7F_FF_FF_FF, 0, -1, 1); + let r: i32x4 = transmute(vqnegq_s32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgt_u8() { - let a: u8x8 = u8x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let b: u8x8 = u8x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let e: u8x8 = u8x8::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x8 = transmute(vcgt_u8(transmute(a), transmute(b))); + unsafe fn test_vqsub_u8() { + let a: u8x8 = u8x8::new(42, 42, 42, 42, 42, 42, 42, 42); + let b: u8x8 = u8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let e: u8x8 = u8x8::new(41, 40, 39, 38, 37, 36, 35, 34); + let r: u8x8 = transmute(vqsub_u8(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgtq_u8() { - let a: u8x16 = u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let b: u8x16 = u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - let e: u8x16 = u8x16::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x16 = transmute(vcgtq_u8(transmute(a), transmute(b))); + unsafe fn test_vqsubq_u8() { + let a: u8x16 = u8x16::new(42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42); + let b: u8x16 = u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let e: u8x16 = u8x16::new(41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26); + let r: u8x16 = transmute(vqsubq_u8(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgt_u16() { - let a: u16x4 = u16x4::new(1, 2, 3, 4); - let b: u16x4 = u16x4::new(0, 1, 2, 3); - let e: u16x4 = u16x4::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); - let r: u16x4 = transmute(vcgt_u16(transmute(a), transmute(b))); + unsafe fn test_vqsub_u16() { + let a: u16x4 = u16x4::new(42, 42, 42, 42); + let b: u16x4 = u16x4::new(1, 2, 3, 4); + let e: u16x4 = u16x4::new(41, 40, 39, 38); + let r: u16x4 = transmute(vqsub_u16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgtq_u16() { - let a: u16x8 = u16x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let b: u16x8 = u16x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let e: u16x8 = u16x8::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); - let r: u16x8 = transmute(vcgtq_u16(transmute(a), transmute(b))); + unsafe fn test_vqsubq_u16() { + let a: u16x8 = u16x8::new(42, 42, 42, 42, 42, 42, 42, 42); + let b: u16x8 = u16x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let e: u16x8 = u16x8::new(41, 40, 39, 38, 37, 36, 35, 34); + let r: u16x8 = transmute(vqsubq_u16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgt_u32() { - let a: u32x2 = u32x2::new(1, 2); - let b: u32x2 = u32x2::new(0, 1); - let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x2 = transmute(vcgt_u32(transmute(a), transmute(b))); + unsafe fn test_vqsub_u32() { + let a: u32x2 = u32x2::new(42, 42); + let b: u32x2 = u32x2::new(1, 2); + let e: u32x2 = u32x2::new(41, 40); + let r: u32x2 = transmute(vqsub_u32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgtq_u32() { - let a: u32x4 = u32x4::new(1, 2, 3, 4); - let b: u32x4 = u32x4::new(0, 1, 2, 3); - let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x4 = transmute(vcgtq_u32(transmute(a), transmute(b))); + unsafe fn test_vqsubq_u32() { + let a: u32x4 = u32x4::new(42, 42, 42, 42); + let b: u32x4 = u32x4::new(1, 2, 3, 4); + let e: u32x4 = u32x4::new(41, 40, 39, 38); + let r: u32x4 = transmute(vqsubq_u32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgt_f32() { - let a: f32x2 = f32x2::new(1.2, 2.3); - let b: f32x2 = f32x2::new(0.1, 1.2); - let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x2 = transmute(vcgt_f32(transmute(a), transmute(b))); + unsafe fn test_vqsub_u64() { + let a: u64x1 = u64x1::new(42); + let b: u64x1 = u64x1::new(1); + let e: u64x1 = u64x1::new(41); + let r: u64x1 = transmute(vqsub_u64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgtq_f32() { - let a: f32x4 = f32x4::new(1.2, 2.3, 3.4, 4.5); - let b: f32x4 = f32x4::new(0.1, 1.2, 2.3, 3.4); - let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x4 = transmute(vcgtq_f32(transmute(a), transmute(b))); + unsafe fn test_vqsubq_u64() { + let a: u64x2 = u64x2::new(42, 42); + let b: u64x2 = u64x2::new(1, 2); + let e: u64x2 = u64x2::new(41, 40); + let r: u64x2 = transmute(vqsubq_u64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclt_s8() { - let a: i8x8 = i8x8::new(0, 1, 2, 3, 4, 5, 6, 7); + unsafe fn test_vqsub_s8() { + let a: i8x8 = i8x8::new(42, 42, 42, 42, 42, 42, 42, 42); let b: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let e: u8x8 = u8x8::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x8 = transmute(vclt_s8(transmute(a), transmute(b))); + let e: i8x8 = i8x8::new(41, 40, 39, 38, 37, 36, 35, 34); + let r: i8x8 = transmute(vqsub_s8(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcltq_s8() { - let a: i8x16 = i8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + unsafe fn test_vqsubq_s8() { + let a: i8x16 = i8x16::new(42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42); let b: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let e: u8x16 = u8x16::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x16 = transmute(vcltq_s8(transmute(a), transmute(b))); + let e: i8x16 = i8x16::new(41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26); + let r: i8x16 = transmute(vqsubq_s8(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclt_s16() { - let a: i16x4 = i16x4::new(0, 1, 2, 3); + unsafe fn test_vqsub_s16() { + let a: i16x4 = i16x4::new(42, 42, 42, 42); let b: i16x4 = i16x4::new(1, 2, 3, 4); - let e: u16x4 = u16x4::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); - let r: u16x4 = transmute(vclt_s16(transmute(a), transmute(b))); + let e: i16x4 = i16x4::new(41, 40, 39, 38); + let r: i16x4 = transmute(vqsub_s16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcltq_s16() { - let a: i16x8 = i16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + unsafe fn test_vqsubq_s16() { + let a: i16x8 = i16x8::new(42, 42, 42, 42, 42, 42, 42, 42); let b: i16x8 = i16x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let e: u16x8 = u16x8::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); - let r: u16x8 = transmute(vcltq_s16(transmute(a), transmute(b))); + let e: i16x8 = i16x8::new(41, 40, 39, 38, 37, 36, 35, 34); + let r: i16x8 = transmute(vqsubq_s16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclt_s32() { - let a: i32x2 = i32x2::new(0, 1); + unsafe fn test_vqsub_s32() { + let a: i32x2 = i32x2::new(42, 42); let b: i32x2 = i32x2::new(1, 2); - let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x2 = transmute(vclt_s32(transmute(a), transmute(b))); + let e: i32x2 = i32x2::new(41, 40); + let r: i32x2 = transmute(vqsub_s32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcltq_s32() { - let a: i32x4 = i32x4::new(0, 1, 2, 3); + unsafe fn test_vqsubq_s32() { + let a: i32x4 = i32x4::new(42, 42, 42, 42); let b: i32x4 = i32x4::new(1, 2, 3, 4); - let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x4 = transmute(vcltq_s32(transmute(a), transmute(b))); + let e: i32x4 = i32x4::new(41, 40, 39, 38); + let r: i32x4 = transmute(vqsubq_s32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclt_u8() { - let a: u8x8 = u8x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let b: u8x8 = u8x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let e: u8x8 = u8x8::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x8 = transmute(vclt_u8(transmute(a), transmute(b))); + unsafe fn test_vqsub_s64() { + let a: i64x1 = i64x1::new(42); + let b: i64x1 = i64x1::new(1); + let e: i64x1 = i64x1::new(41); + let r: i64x1 = transmute(vqsub_s64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcltq_u8() { - let a: u8x16 = u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - let b: u8x16 = u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let e: u8x16 = u8x16::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x16 = transmute(vcltq_u8(transmute(a), transmute(b))); + unsafe fn test_vqsubq_s64() { + let a: i64x2 = i64x2::new(42, 42); + let b: i64x2 = i64x2::new(1, 2); + let e: i64x2 = i64x2::new(41, 40); + let r: i64x2 = transmute(vqsubq_s64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclt_u16() { - let a: u16x4 = u16x4::new(0, 1, 2, 3); - let b: u16x4 = u16x4::new(1, 2, 3, 4); - let e: u16x4 = u16x4::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); - let r: u16x4 = transmute(vclt_u16(transmute(a), transmute(b))); + unsafe fn test_vhadd_u8() { + let a: u8x8 = u8x8::new(42, 42, 42, 42, 42, 42, 42, 42); + let b: u8x8 = u8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let e: u8x8 = u8x8::new(21, 22, 22, 23, 23, 24, 24, 25); + let r: u8x8 = transmute(vhadd_u8(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcltq_u16() { - let a: u16x8 = u16x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let b: u16x8 = u16x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let e: u16x8 = u16x8::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); - let r: u16x8 = transmute(vcltq_u16(transmute(a), transmute(b))); + unsafe fn test_vhaddq_u8() { + let a: u8x16 = u8x16::new(42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42); + let b: u8x16 = u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let e: u8x16 = u8x16::new(21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29); + let r: u8x16 = transmute(vhaddq_u8(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclt_u32() { - let a: u32x2 = u32x2::new(0, 1); - let b: u32x2 = u32x2::new(1, 2); - let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x2 = transmute(vclt_u32(transmute(a), transmute(b))); + unsafe fn test_vhadd_u16() { + let a: u16x4 = u16x4::new(42, 42, 42, 42); + let b: u16x4 = u16x4::new(1, 2, 3, 4); + let e: u16x4 = u16x4::new(21, 22, 22, 23); + let r: u16x4 = transmute(vhadd_u16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcltq_u32() { - let a: u32x4 = u32x4::new(0, 1, 2, 3); - let b: u32x4 = u32x4::new(1, 2, 3, 4); - let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x4 = transmute(vcltq_u32(transmute(a), transmute(b))); + unsafe fn test_vhaddq_u16() { + let a: u16x8 = u16x8::new(42, 42, 42, 42, 42, 42, 42, 42); + let b: u16x8 = u16x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let e: u16x8 = u16x8::new(21, 22, 22, 23, 23, 24, 24, 25); + let r: u16x8 = transmute(vhaddq_u16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclt_f32() { - let a: f32x2 = f32x2::new(0.1, 1.2); - let b: f32x2 = f32x2::new(1.2, 2.3); - let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x2 = transmute(vclt_f32(transmute(a), transmute(b))); + unsafe fn test_vhadd_u32() { + let a: u32x2 = u32x2::new(42, 42); + let b: u32x2 = u32x2::new(1, 2); + let e: u32x2 = u32x2::new(21, 22); + let r: u32x2 = transmute(vhadd_u32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcltq_f32() { - let a: f32x4 = f32x4::new(0.1, 1.2, 2.3, 3.4); - let b: f32x4 = f32x4::new(1.2, 2.3, 3.4, 4.5); - let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x4 = transmute(vcltq_f32(transmute(a), transmute(b))); + unsafe fn test_vhaddq_u32() { + let a: u32x4 = u32x4::new(42, 42, 42, 42); + let b: u32x4 = u32x4::new(1, 2, 3, 4); + let e: u32x4 = u32x4::new(21, 22, 22, 23); + let r: u32x4 = transmute(vhaddq_u32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcle_s8() { - let a: i8x8 = i8x8::new(0, 1, 2, 3, 4, 5, 6, 7); + unsafe fn test_vhadd_s8() { + let a: i8x8 = i8x8::new(42, 42, 42, 42, 42, 42, 42, 42); let b: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let e: u8x8 = u8x8::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x8 = transmute(vcle_s8(transmute(a), transmute(b))); + let e: i8x8 = i8x8::new(21, 22, 22, 23, 23, 24, 24, 25); + let r: i8x8 = transmute(vhadd_s8(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcleq_s8() { - let a: i8x16 = i8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + unsafe fn test_vhaddq_s8() { + let a: i8x16 = i8x16::new(42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42); let b: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let e: u8x16 = u8x16::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x16 = transmute(vcleq_s8(transmute(a), transmute(b))); + let e: i8x16 = i8x16::new(21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29); + let r: i8x16 = transmute(vhaddq_s8(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcle_s16() { - let a: i16x4 = i16x4::new(0, 1, 2, 3); + unsafe fn test_vhadd_s16() { + let a: i16x4 = i16x4::new(42, 42, 42, 42); let b: i16x4 = i16x4::new(1, 2, 3, 4); - let e: u16x4 = u16x4::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); - let r: u16x4 = transmute(vcle_s16(transmute(a), transmute(b))); + let e: i16x4 = i16x4::new(21, 22, 22, 23); + let r: i16x4 = transmute(vhadd_s16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcleq_s16() { - let a: i16x8 = i16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + unsafe fn test_vhaddq_s16() { + let a: i16x8 = i16x8::new(42, 42, 42, 42, 42, 42, 42, 42); let b: i16x8 = i16x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let e: u16x8 = u16x8::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); - let r: u16x8 = transmute(vcleq_s16(transmute(a), transmute(b))); + let e: i16x8 = i16x8::new(21, 22, 22, 23, 23, 24, 24, 25); + let r: i16x8 = transmute(vhaddq_s16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcle_s32() { - let a: i32x2 = i32x2::new(0, 1); + unsafe fn test_vhadd_s32() { + let a: i32x2 = i32x2::new(42, 42); let b: i32x2 = i32x2::new(1, 2); - let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x2 = transmute(vcle_s32(transmute(a), transmute(b))); + let e: i32x2 = i32x2::new(21, 22); + let r: i32x2 = transmute(vhadd_s32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcleq_s32() { - let a: i32x4 = i32x4::new(0, 1, 2, 3); + unsafe fn test_vhaddq_s32() { + let a: i32x4 = i32x4::new(42, 42, 42, 42); let b: i32x4 = i32x4::new(1, 2, 3, 4); - let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x4 = transmute(vcleq_s32(transmute(a), transmute(b))); + let e: i32x4 = i32x4::new(21, 22, 22, 23); + let r: i32x4 = transmute(vhaddq_s32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcle_u8() { - let a: u8x8 = u8x8::new(0, 1, 2, 3, 4, 5, 6, 7); + unsafe fn test_vrhadd_u8() { + let a: u8x8 = u8x8::new(42, 42, 42, 42, 42, 42, 42, 42); let b: u8x8 = u8x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let e: u8x8 = u8x8::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x8 = transmute(vcle_u8(transmute(a), transmute(b))); + let e: u8x8 = u8x8::new(22, 22, 23, 23, 24, 24, 25, 25); + let r: u8x8 = transmute(vrhadd_u8(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcleq_u8() { - let a: u8x16 = u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + unsafe fn test_vrhaddq_u8() { + let a: u8x16 = u8x16::new(42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42); let b: u8x16 = u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let e: u8x16 = u8x16::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x16 = transmute(vcleq_u8(transmute(a), transmute(b))); + let e: u8x16 = u8x16::new(22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29); + let r: u8x16 = transmute(vrhaddq_u8(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcle_u16() { - let a: u16x4 = u16x4::new(0, 1, 2, 3); + unsafe fn test_vrhadd_u16() { + let a: u16x4 = u16x4::new(42, 42, 42, 42); let b: u16x4 = u16x4::new(1, 2, 3, 4); - let e: u16x4 = u16x4::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); - let r: u16x4 = transmute(vcle_u16(transmute(a), transmute(b))); + let e: u16x4 = u16x4::new(22, 22, 23, 23); + let r: u16x4 = transmute(vrhadd_u16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcleq_u16() { - let a: u16x8 = u16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + unsafe fn test_vrhaddq_u16() { + let a: u16x8 = u16x8::new(42, 42, 42, 42, 42, 42, 42, 42); let b: u16x8 = u16x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let e: u16x8 = u16x8::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); - let r: u16x8 = transmute(vcleq_u16(transmute(a), transmute(b))); + let e: u16x8 = u16x8::new(22, 22, 23, 23, 24, 24, 25, 25); + let r: u16x8 = transmute(vrhaddq_u16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcle_u32() { - let a: u32x2 = u32x2::new(0, 1); + unsafe fn test_vrhadd_u32() { + let a: u32x2 = u32x2::new(42, 42); let b: u32x2 = u32x2::new(1, 2); - let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x2 = transmute(vcle_u32(transmute(a), transmute(b))); + let e: u32x2 = u32x2::new(22, 22); + let r: u32x2 = transmute(vrhadd_u32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcleq_u32() { - let a: u32x4 = u32x4::new(0, 1, 2, 3); + unsafe fn test_vrhaddq_u32() { + let a: u32x4 = u32x4::new(42, 42, 42, 42); let b: u32x4 = u32x4::new(1, 2, 3, 4); - let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x4 = transmute(vcleq_u32(transmute(a), transmute(b))); + let e: u32x4 = u32x4::new(22, 22, 23, 23); + let r: u32x4 = transmute(vrhaddq_u32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcle_f32() { - let a: f32x2 = f32x2::new(0.1, 1.2); - let b: f32x2 = f32x2::new(1.2, 2.3); - let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x2 = transmute(vcle_f32(transmute(a), transmute(b))); + unsafe fn test_vrhadd_s8() { + let a: i8x8 = i8x8::new(42, 42, 42, 42, 42, 42, 42, 42); + let b: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let e: i8x8 = i8x8::new(22, 22, 23, 23, 24, 24, 25, 25); + let r: i8x8 = transmute(vrhadd_s8(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcleq_f32() { - let a: f32x4 = f32x4::new(0.1, 1.2, 2.3, 3.4); - let b: f32x4 = f32x4::new(1.2, 2.3, 3.4, 4.5); - let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x4 = transmute(vcleq_f32(transmute(a), transmute(b))); + unsafe fn test_vrhaddq_s8() { + let a: i8x16 = i8x16::new(42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42); + let b: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let e: i8x16 = i8x16::new(22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29); + let r: i8x16 = transmute(vrhaddq_s8(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcge_s8() { - let a: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let b: i8x8 = i8x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let e: u8x8 = u8x8::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x8 = transmute(vcge_s8(transmute(a), transmute(b))); + unsafe fn test_vrhadd_s16() { + let a: i16x4 = i16x4::new(42, 42, 42, 42); + let b: i16x4 = i16x4::new(1, 2, 3, 4); + let e: i16x4 = i16x4::new(22, 22, 23, 23); + let r: i16x4 = transmute(vrhadd_s16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgeq_s8() { - let a: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let b: i8x16 = i8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - let e: u8x16 = u8x16::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x16 = transmute(vcgeq_s8(transmute(a), transmute(b))); + unsafe fn test_vrhaddq_s16() { + let a: i16x8 = i16x8::new(42, 42, 42, 42, 42, 42, 42, 42); + let b: i16x8 = i16x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let e: i16x8 = i16x8::new(22, 22, 23, 23, 24, 24, 25, 25); + let r: i16x8 = transmute(vrhaddq_s16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcge_s16() { - let a: i16x4 = i16x4::new(1, 2, 3, 4); - let b: i16x4 = i16x4::new(0, 1, 2, 3); - let e: u16x4 = u16x4::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); - let r: u16x4 = transmute(vcge_s16(transmute(a), transmute(b))); + unsafe fn test_vrhadd_s32() { + let a: i32x2 = i32x2::new(42, 42); + let b: i32x2 = i32x2::new(1, 2); + let e: i32x2 = i32x2::new(22, 22); + let r: i32x2 = transmute(vrhadd_s32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgeq_s16() { - let a: i16x8 = i16x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let b: i16x8 = i16x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let e: u16x8 = u16x8::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); - let r: u16x8 = transmute(vcgeq_s16(transmute(a), transmute(b))); + unsafe fn test_vrhaddq_s32() { + let a: i32x4 = i32x4::new(42, 42, 42, 42); + let b: i32x4 = i32x4::new(1, 2, 3, 4); + let e: i32x4 = i32x4::new(22, 22, 23, 23); + let r: i32x4 = transmute(vrhaddq_s32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcge_s32() { - let a: i32x2 = i32x2::new(1, 2); - let b: i32x2 = i32x2::new(0, 1); - let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x2 = transmute(vcge_s32(transmute(a), transmute(b))); + unsafe fn test_vrndn_f32() { + let a: f32x2 = f32x2::new(-1.5, 0.5); + let e: f32x2 = f32x2::new(-2.0, 0.0); + let r: f32x2 = transmute(vrndn_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgeq_s32() { - let a: i32x4 = i32x4::new(1, 2, 3, 4); - let b: i32x4 = i32x4::new(0, 1, 2, 3); - let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x4 = transmute(vcgeq_s32(transmute(a), transmute(b))); + unsafe fn test_vrndnq_f32() { + let a: f32x4 = f32x4::new(-1.5, 0.5, 1.5, 2.5); + let e: f32x4 = f32x4::new(-2.0, 0.0, 2.0, 2.0); + let r: f32x4 = transmute(vrndnq_f32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcge_u8() { - let a: u8x8 = u8x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let b: u8x8 = u8x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let e: u8x8 = u8x8::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x8 = transmute(vcge_u8(transmute(a), transmute(b))); + unsafe fn test_vqadd_u8() { + let a: u8x8 = u8x8::new(42, 42, 42, 42, 42, 42, 42, 42); + let b: u8x8 = u8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let e: u8x8 = u8x8::new(43, 44, 45, 46, 47, 48, 49, 50); + let r: u8x8 = transmute(vqadd_u8(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgeq_u8() { - let a: u8x16 = u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let b: u8x16 = u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - let e: u8x16 = u8x16::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - let r: u8x16 = transmute(vcgeq_u8(transmute(a), transmute(b))); + unsafe fn test_vqaddq_u8() { + let a: u8x16 = u8x16::new(42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42); + let b: u8x16 = u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let e: u8x16 = u8x16::new(43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58); + let r: u8x16 = transmute(vqaddq_u8(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcge_u16() { - let a: u16x4 = u16x4::new(1, 2, 3, 4); - let b: u16x4 = u16x4::new(0, 1, 2, 3); - let e: u16x4 = u16x4::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); - let r: u16x4 = transmute(vcge_u16(transmute(a), transmute(b))); + unsafe fn test_vqadd_u16() { + let a: u16x4 = u16x4::new(42, 42, 42, 42); + let b: u16x4 = u16x4::new(1, 2, 3, 4); + let e: u16x4 = u16x4::new(43, 44, 45, 46); + let r: u16x4 = transmute(vqadd_u16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgeq_u16() { - let a: u16x8 = u16x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let b: u16x8 = u16x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let e: u16x8 = u16x8::new(0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); - let r: u16x8 = transmute(vcgeq_u16(transmute(a), transmute(b))); + unsafe fn test_vqaddq_u16() { + let a: u16x8 = u16x8::new(42, 42, 42, 42, 42, 42, 42, 42); + let b: u16x8 = u16x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let e: u16x8 = u16x8::new(43, 44, 45, 46, 47, 48, 49, 50); + let r: u16x8 = transmute(vqaddq_u16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcge_u32() { - let a: u32x2 = u32x2::new(1, 2); - let b: u32x2 = u32x2::new(0, 1); - let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x2 = transmute(vcge_u32(transmute(a), transmute(b))); + unsafe fn test_vqadd_u32() { + let a: u32x2 = u32x2::new(42, 42); + let b: u32x2 = u32x2::new(1, 2); + let e: u32x2 = u32x2::new(43, 44); + let r: u32x2 = transmute(vqadd_u32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgeq_u32() { - let a: u32x4 = u32x4::new(1, 2, 3, 4); - let b: u32x4 = u32x4::new(0, 1, 2, 3); - let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x4 = transmute(vcgeq_u32(transmute(a), transmute(b))); + unsafe fn test_vqaddq_u32() { + let a: u32x4 = u32x4::new(42, 42, 42, 42); + let b: u32x4 = u32x4::new(1, 2, 3, 4); + let e: u32x4 = u32x4::new(43, 44, 45, 46); + let r: u32x4 = transmute(vqaddq_u32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcge_f32() { - let a: f32x2 = f32x2::new(1.2, 2.3); - let b: f32x2 = f32x2::new(0.1, 1.2); - let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x2 = transmute(vcge_f32(transmute(a), transmute(b))); + unsafe fn test_vqadd_u64() { + let a: u64x1 = u64x1::new(42); + let b: u64x1 = u64x1::new(1); + let e: u64x1 = u64x1::new(43); + let r: u64x1 = transmute(vqadd_u64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcgeq_f32() { - let a: f32x4 = f32x4::new(1.2, 2.3, 3.4, 4.5); - let b: f32x4 = f32x4::new(0.1, 1.2, 2.3, 3.4); - let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x4 = transmute(vcgeq_f32(transmute(a), transmute(b))); + unsafe fn test_vqaddq_u64() { + let a: u64x2 = u64x2::new(42, 42); + let b: u64x2 = u64x2::new(1, 2); + let e: u64x2 = u64x2::new(43, 44); + let r: u64x2 = transmute(vqaddq_u64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqadd_s8() { + let a: i8x8 = i8x8::new(42, 42, 42, 42, 42, 42, 42, 42); + let b: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let e: i8x8 = i8x8::new(43, 44, 45, 46, 47, 48, 49, 50); + let r: i8x8 = transmute(vqadd_s8(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcls_s8() { - let a: i8x8 = i8x8::new(-128, -1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - let e: i8x8 = i8x8::new(0, 7, 7, 7, 7, 7, 7, 7); - let r: i8x8 = transmute(vcls_s8(transmute(a))); + unsafe fn test_vqaddq_s8() { + let a: i8x16 = i8x16::new(42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42); + let b: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let e: i8x16 = i8x16::new(43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58); + let r: i8x16 = transmute(vqaddq_s8(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclsq_s8() { - let a: i8x16 = i8x16::new(-128, -1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F); - let e: i8x16 = i8x16::new(0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0); - let r: i8x16 = transmute(vclsq_s8(transmute(a))); + unsafe fn test_vqadd_s16() { + let a: i16x4 = i16x4::new(42, 42, 42, 42); + let b: i16x4 = i16x4::new(1, 2, 3, 4); + let e: i16x4 = i16x4::new(43, 44, 45, 46); + let r: i16x4 = transmute(vqadd_s16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcls_s16() { - let a: i16x4 = i16x4::new(-32768, -1, 0x00, 0x00); - let e: i16x4 = i16x4::new(0, 15, 15, 15); - let r: i16x4 = transmute(vcls_s16(transmute(a))); + unsafe fn test_vqaddq_s16() { + let a: i16x8 = i16x8::new(42, 42, 42, 42, 42, 42, 42, 42); + let b: i16x8 = i16x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let e: i16x8 = i16x8::new(43, 44, 45, 46, 47, 48, 49, 50); + let r: i16x8 = transmute(vqaddq_s16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclsq_s16() { - let a: i16x8 = i16x8::new(-32768, -1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - let e: i16x8 = i16x8::new(0, 15, 15, 15, 15, 15, 15, 15); - let r: i16x8 = transmute(vclsq_s16(transmute(a))); + unsafe fn test_vqadd_s32() { + let a: i32x2 = i32x2::new(42, 42); + let b: i32x2 = i32x2::new(1, 2); + let e: i32x2 = i32x2::new(43, 44); + let r: i32x2 = transmute(vqadd_s32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcls_s32() { - let a: i32x2 = i32x2::new(-2147483648, -1); - let e: i32x2 = i32x2::new(0, 31); - let r: i32x2 = transmute(vcls_s32(transmute(a))); + unsafe fn test_vqaddq_s32() { + let a: i32x4 = i32x4::new(42, 42, 42, 42); + let b: i32x4 = i32x4::new(1, 2, 3, 4); + let e: i32x4 = i32x4::new(43, 44, 45, 46); + let r: i32x4 = transmute(vqaddq_s32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclsq_s32() { - let a: i32x4 = i32x4::new(-2147483648, -1, 0x00, 0x00); - let e: i32x4 = i32x4::new(0, 31, 31, 31); - let r: i32x4 = transmute(vclsq_s32(transmute(a))); + unsafe fn test_vqadd_s64() { + let a: i64x1 = i64x1::new(42); + let b: i64x1 = i64x1::new(1); + let e: i64x1 = i64x1::new(43); + let r: i64x1 = transmute(vqadd_s64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclz_s8() { - let a: i8x8 = i8x8::new(-128, -1, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01); - let e: i8x8 = i8x8::new(0, 0, 8, 7, 7, 7, 7, 7); - let r: i8x8 = transmute(vclz_s8(transmute(a))); + unsafe fn test_vqaddq_s64() { + let a: i64x2 = i64x2::new(42, 42); + let b: i64x2 = i64x2::new(1, 2); + let e: i64x2 = i64x2::new(43, 44); + let r: i64x2 = transmute(vqaddq_s64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclzq_s8() { - let a: i8x16 = i8x16::new(-128, -1, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x7F); - let e: i8x16 = i8x16::new(0, 0, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 1); - let r: i8x16 = transmute(vclzq_s8(transmute(a))); + unsafe fn test_vld1_s8_x2() { + let a: [i8; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let e: [i8x8; 2] = [i8x8::new(1, 2, 3, 4, 5, 6, 7, 8), i8x8::new(9, 10, 11, 12, 13, 14, 15, 16)]; + let r: [i8x8; 2] = transmute(vld1_s8_x2(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclz_s16() { - let a: i16x4 = i16x4::new(-32768, -1, 0x00, 0x01); - let e: i16x4 = i16x4::new(0, 0, 16, 15); - let r: i16x4 = transmute(vclz_s16(transmute(a))); + unsafe fn test_vld1_s16_x2() { + let a: [i16; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let e: [i16x4; 2] = [i16x4::new(1, 2, 3, 4), i16x4::new(5, 6, 7, 8)]; + let r: [i16x4; 2] = transmute(vld1_s16_x2(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclzq_s16() { - let a: i16x8 = i16x8::new(-32768, -1, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01); - let e: i16x8 = i16x8::new(0, 0, 16, 15, 15, 15, 15, 15); - let r: i16x8 = transmute(vclzq_s16(transmute(a))); + unsafe fn test_vld1_s32_x2() { + let a: [i32; 5] = [0, 1, 2, 3, 4]; + let e: [i32x2; 2] = [i32x2::new(1, 2), i32x2::new(3, 4)]; + let r: [i32x2; 2] = transmute(vld1_s32_x2(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclz_s32() { - let a: i32x2 = i32x2::new(-2147483648, -1); - let e: i32x2 = i32x2::new(0, 0); - let r: i32x2 = transmute(vclz_s32(transmute(a))); + unsafe fn test_vld1_s64_x2() { + let a: [i64; 3] = [0, 1, 2]; + let e: [i64x1; 2] = [i64x1::new(1), i64x1::new(2)]; + let r: [i64x1; 2] = transmute(vld1_s64_x2(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclzq_s32() { - let a: i32x4 = i32x4::new(-2147483648, -1, 0x00, 0x01); - let e: i32x4 = i32x4::new(0, 0, 32, 31); - let r: i32x4 = transmute(vclzq_s32(transmute(a))); + unsafe fn test_vld1q_s8_x2() { + let a: [i8; 33] = [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]; + let e: [i8x16; 2] = [i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), i8x16::new(17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32)]; + let r: [i8x16; 2] = transmute(vld1q_s8_x2(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclz_u8() { - let a: u8x8 = u8x8::new(0, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01); - let e: u8x8 = u8x8::new(8, 8, 7, 7, 7, 7, 7, 7); - let r: u8x8 = transmute(vclz_u8(transmute(a))); + unsafe fn test_vld1q_s16_x2() { + let a: [i16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let e: [i16x8; 2] = [i16x8::new(1, 2, 3, 4, 5, 6, 7, 8), i16x8::new(9, 10, 11, 12, 13, 14, 15, 16)]; + let r: [i16x8; 2] = transmute(vld1q_s16_x2(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclzq_u8() { - let a: u8x16 = u8x16::new(0, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF); - let e: u8x16 = u8x16::new(8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0); - let r: u8x16 = transmute(vclzq_u8(transmute(a))); + unsafe fn test_vld1q_s32_x2() { + let a: [i32; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let e: [i32x4; 2] = [i32x4::new(1, 2, 3, 4), i32x4::new(5, 6, 7, 8)]; + let r: [i32x4; 2] = transmute(vld1q_s32_x2(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclz_u16() { - let a: u16x4 = u16x4::new(0, 0x00, 0x01, 0x01); - let e: u16x4 = u16x4::new(16, 16, 15, 15); - let r: u16x4 = transmute(vclz_u16(transmute(a))); + unsafe fn test_vld1q_s64_x2() { + let a: [i64; 5] = [0, 1, 2, 3, 4]; + let e: [i64x2; 2] = [i64x2::new(1, 2), i64x2::new(3, 4)]; + let r: [i64x2; 2] = transmute(vld1q_s64_x2(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclzq_u16() { - let a: u16x8 = u16x8::new(0, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01); - let e: u16x8 = u16x8::new(16, 16, 15, 15, 15, 15, 15, 15); - let r: u16x8 = transmute(vclzq_u16(transmute(a))); + unsafe fn test_vld1_s8_x3() { + let a: [i8; 25] = [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]; + let e: [i8x8; 3] = [i8x8::new(1, 2, 3, 4, 5, 6, 7, 8), i8x8::new(9, 10, 11, 12, 13, 14, 15, 16), i8x8::new(17, 18, 19, 20, 21, 22, 23, 24)]; + let r: [i8x8; 3] = transmute(vld1_s8_x3(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclz_u32() { - let a: u32x2 = u32x2::new(0, 0x00); - let e: u32x2 = u32x2::new(32, 32); - let r: u32x2 = transmute(vclz_u32(transmute(a))); + unsafe fn test_vld1_s16_x3() { + let a: [i16; 13] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + let e: [i16x4; 3] = [i16x4::new(1, 2, 3, 4), i16x4::new(5, 6, 7, 8), i16x4::new(9, 10, 11, 12)]; + let r: [i16x4; 3] = transmute(vld1_s16_x3(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vclzq_u32() { - let a: u32x4 = u32x4::new(0, 0x00, 0x01, 0x01); - let e: u32x4 = u32x4::new(32, 32, 31, 31); - let r: u32x4 = transmute(vclzq_u32(transmute(a))); + unsafe fn test_vld1_s32_x3() { + let a: [i32; 7] = [0, 1, 2, 3, 4, 5, 6]; + let e: [i32x2; 3] = [i32x2::new(1, 2), i32x2::new(3, 4), i32x2::new(5, 6)]; + let r: [i32x2; 3] = transmute(vld1_s32_x3(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcagt_f32() { - let a: f32x2 = f32x2::new(-1.2, 0.0); - let b: f32x2 = f32x2::new(-1.1, 0.0); - let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0); - let r: u32x2 = transmute(vcagt_f32(transmute(a), transmute(b))); + unsafe fn test_vld1_s64_x3() { + let a: [i64; 4] = [0, 1, 2, 3]; + let e: [i64x1; 3] = [i64x1::new(1), i64x1::new(2), i64x1::new(3)]; + let r: [i64x1; 3] = transmute(vld1_s64_x3(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcagtq_f32() { - let a: f32x4 = f32x4::new(-1.2, 0.0, 1.2, 2.3); - let b: f32x4 = f32x4::new(-1.1, 0.0, 1.1, 2.4); - let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0, 0xFF_FF_FF_FF, 0); - let r: u32x4 = transmute(vcagtq_f32(transmute(a), transmute(b))); + unsafe fn test_vld1q_s8_x3() { + let a: [i8; 49] = [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, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let e: [i8x16; 3] = [i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), i8x16::new(17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32), i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)]; + let r: [i8x16; 3] = transmute(vld1q_s8_x3(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcage_f32() { - let a: f32x2 = f32x2::new(-1.2, 0.0); - let b: f32x2 = f32x2::new(-1.1, 0.0); - let e: u32x2 = u32x2::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF); - let r: u32x2 = transmute(vcage_f32(transmute(a), transmute(b))); + unsafe fn test_vld1q_s16_x3() { + let a: [i16; 25] = [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]; + let e: [i16x8; 3] = [i16x8::new(1, 2, 3, 4, 5, 6, 7, 8), i16x8::new(9, 10, 11, 12, 13, 14, 15, 16), i16x8::new(17, 18, 19, 20, 21, 22, 23, 24)]; + let r: [i16x8; 3] = transmute(vld1q_s16_x3(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcageq_f32() { - let a: f32x4 = f32x4::new(-1.2, 0.0, 1.2, 2.3); - let b: f32x4 = f32x4::new(-1.1, 0.0, 1.1, 2.4); - let e: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0xFF_FF_FF_FF, 0); - let r: u32x4 = transmute(vcageq_f32(transmute(a), transmute(b))); + unsafe fn test_vld1q_s32_x3() { + let a: [i32; 13] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + let e: [i32x4; 3] = [i32x4::new(1, 2, 3, 4), i32x4::new(5, 6, 7, 8), i32x4::new(9, 10, 11, 12)]; + let r: [i32x4; 3] = transmute(vld1q_s32_x3(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcalt_f32() { - let a: f32x2 = f32x2::new(-1.2, 0.0); - let b: f32x2 = f32x2::new(-1.1, 0.0); - let e: u32x2 = u32x2::new(0, 0); - let r: u32x2 = transmute(vcalt_f32(transmute(a), transmute(b))); + unsafe fn test_vld1q_s64_x3() { + let a: [i64; 7] = [0, 1, 2, 3, 4, 5, 6]; + let e: [i64x2; 3] = [i64x2::new(1, 2), i64x2::new(3, 4), i64x2::new(5, 6)]; + let r: [i64x2; 3] = transmute(vld1q_s64_x3(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcaltq_f32() { - let a: f32x4 = f32x4::new(-1.2, 0.0, 1.2, 2.3); - let b: f32x4 = f32x4::new(-1.1, 0.0, 1.1, 2.4); - let e: u32x4 = u32x4::new(0, 0, 0, 0xFF_FF_FF_FF); - let r: u32x4 = transmute(vcaltq_f32(transmute(a), transmute(b))); + unsafe fn test_vld1_s8_x4() { + let a: [i8; 33] = [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]; + let e: [i8x8; 4] = [i8x8::new(1, 2, 3, 4, 5, 6, 7, 8), i8x8::new(9, 10, 11, 12, 13, 14, 15, 16), i8x8::new(17, 18, 19, 20, 21, 22, 23, 24), i8x8::new(25, 26, 27, 28, 29, 30, 31, 32)]; + let r: [i8x8; 4] = transmute(vld1_s8_x4(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcale_f32() { - let a: f32x2 = f32x2::new(-1.2, 0.0); - let b: f32x2 = f32x2::new(-1.1, 0.0); - let e: u32x2 = u32x2::new(0, 0xFF_FF_FF_FF); - let r: u32x2 = transmute(vcale_f32(transmute(a), transmute(b))); + unsafe fn test_vld1_s16_x4() { + let a: [i16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let e: [i16x4; 4] = [i16x4::new(1, 2, 3, 4), i16x4::new(5, 6, 7, 8), i16x4::new(9, 10, 11, 12), i16x4::new(13, 14, 15, 16)]; + let r: [i16x4; 4] = transmute(vld1_s16_x4(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcaleq_f32() { - let a: f32x4 = f32x4::new(-1.2, 0.0, 1.2, 2.3); - let b: f32x4 = f32x4::new(-1.1, 0.0, 1.1, 2.4); - let e: u32x4 = u32x4::new(0, 0xFF_FF_FF_FF, 0, 0xFF_FF_FF_FF); - let r: u32x4 = transmute(vcaleq_f32(transmute(a), transmute(b))); + unsafe fn test_vld1_s32_x4() { + let a: [i32; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let e: [i32x2; 4] = [i32x2::new(1, 2), i32x2::new(3, 4), i32x2::new(5, 6), i32x2::new(7, 8)]; + let r: [i32x2; 4] = transmute(vld1_s32_x4(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcreate_s8() { - let a: u64 = 1; - let e: i8x8 = i8x8::new(1, 0, 0, 0, 0, 0, 0, 0); - let r: i8x8 = transmute(vcreate_s8(transmute(a))); + unsafe fn test_vld1_s64_x4() { + let a: [i64; 5] = [0, 1, 2, 3, 4]; + let e: [i64x1; 4] = [i64x1::new(1), i64x1::new(2), i64x1::new(3), i64x1::new(4)]; + let r: [i64x1; 4] = transmute(vld1_s64_x4(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcreate_s32() { - let a: u64 = 1; - let e: i32x2 = i32x2::new(1, 0); - let r: i32x2 = transmute(vcreate_s32(transmute(a))); + unsafe fn test_vld1q_s8_x4() { + let a: [i8; 65] = [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, 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 e: [i8x16; 4] = [i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), i8x16::new(17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32), i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), i8x16::new(17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32)]; + let r: [i8x16; 4] = transmute(vld1q_s8_x4(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcreate_s64() { - let a: u64 = 1; - let e: i64x1 = i64x1::new(1); - let r: i64x1 = transmute(vcreate_s64(transmute(a))); + unsafe fn test_vld1q_s16_x4() { + let a: [i16; 33] = [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]; + let e: [i16x8; 4] = [i16x8::new(1, 2, 3, 4, 5, 6, 7, 8), i16x8::new(9, 10, 11, 12, 13, 14, 15, 16), i16x8::new(17, 18, 19, 20, 21, 22, 23, 24), i16x8::new(25, 26, 27, 28, 29, 30, 31, 32)]; + let r: [i16x8; 4] = transmute(vld1q_s16_x4(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcreate_u8() { - let a: u64 = 1; - let e: u8x8 = u8x8::new(1, 0, 0, 0, 0, 0, 0, 0); - let r: u8x8 = transmute(vcreate_u8(transmute(a))); + unsafe fn test_vld1q_s32_x4() { + let a: [i32; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let e: [i32x4; 4] = [i32x4::new(1, 2, 3, 4), i32x4::new(5, 6, 7, 8), i32x4::new(9, 10, 11, 12), i32x4::new(13, 14, 15, 16)]; + let r: [i32x4; 4] = transmute(vld1q_s32_x4(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcreate_u32() { - let a: u64 = 1; - let e: u32x2 = u32x2::new(1, 0); - let r: u32x2 = transmute(vcreate_u32(transmute(a))); + unsafe fn test_vld1q_s64_x4() { + let a: [i64; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let e: [i64x2; 4] = [i64x2::new(1, 2), i64x2::new(3, 4), i64x2::new(5, 6), i64x2::new(7, 8)]; + let r: [i64x2; 4] = transmute(vld1q_s64_x4(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcreate_u64() { - let a: u64 = 1; - let e: u64x1 = u64x1::new(1); - let r: u64x1 = transmute(vcreate_u64(transmute(a))); + unsafe fn test_vld1_u8_x2() { + let a: [u8; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let e: [u8x8; 2] = [u8x8::new(1, 2, 3, 4, 5, 6, 7, 8), u8x8::new(9, 10, 11, 12, 13, 14, 15, 16)]; + let r: [u8x8; 2] = transmute(vld1_u8_x2(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcreate_p8() { - let a: u64 = 1; - let e: i8x8 = i8x8::new(1, 0, 0, 0, 0, 0, 0, 0); - let r: i8x8 = transmute(vcreate_p8(transmute(a))); + unsafe fn test_vld1_u16_x2() { + let a: [u16; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let e: [u16x4; 2] = [u16x4::new(1, 2, 3, 4), u16x4::new(5, 6, 7, 8)]; + let r: [u16x4; 2] = transmute(vld1_u16_x2(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcreate_p16() { - let a: u64 = 1; - let e: i16x4 = i16x4::new(1, 0, 0, 0); - let r: i16x4 = transmute(vcreate_p16(transmute(a))); + unsafe fn test_vld1_u32_x2() { + let a: [u32; 5] = [0, 1, 2, 3, 4]; + let e: [u32x2; 2] = [u32x2::new(1, 2), u32x2::new(3, 4)]; + let r: [u32x2; 2] = transmute(vld1_u32_x2(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcreate_p64() { - let a: u64 = 1; - let e: i64x1 = i64x1::new(1); - let r: i64x1 = transmute(vcreate_p64(transmute(a))); + unsafe fn test_vld1_u64_x2() { + let a: [u64; 3] = [0, 1, 2]; + let e: [u64x1; 2] = [u64x1::new(1), u64x1::new(2)]; + let r: [u64x1; 2] = transmute(vld1_u64_x2(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcreate_f32() { - let a: u64 = 0; - let e: f32x2 = f32x2::new(0., 0.); - let r: f32x2 = transmute(vcreate_f32(transmute(a))); + unsafe fn test_vld1q_u8_x2() { + let a: [u8; 33] = [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]; + let e: [u8x16; 2] = [u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), u8x16::new(17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32)]; + let r: [u8x16; 2] = transmute(vld1q_u8_x2(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvt_f32_s32() { - let a: i32x2 = i32x2::new(1, 2); - let e: f32x2 = f32x2::new(1., 2.); - let r: f32x2 = transmute(vcvt_f32_s32(transmute(a))); + unsafe fn test_vld1q_u16_x2() { + let a: [u16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let e: [u16x8; 2] = [u16x8::new(1, 2, 3, 4, 5, 6, 7, 8), u16x8::new(9, 10, 11, 12, 13, 14, 15, 16)]; + let r: [u16x8; 2] = transmute(vld1q_u16_x2(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtq_f32_s32() { - let a: i32x4 = i32x4::new(1, 2, 3, 4); - let e: f32x4 = f32x4::new(1., 2., 3., 4.); - let r: f32x4 = transmute(vcvtq_f32_s32(transmute(a))); + unsafe fn test_vld1q_u32_x2() { + let a: [u32; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let e: [u32x4; 2] = [u32x4::new(1, 2, 3, 4), u32x4::new(5, 6, 7, 8)]; + let r: [u32x4; 2] = transmute(vld1q_u32_x2(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvt_f32_u32() { - let a: u32x2 = u32x2::new(1, 2); - let e: f32x2 = f32x2::new(1., 2.); - let r: f32x2 = transmute(vcvt_f32_u32(transmute(a))); + unsafe fn test_vld1q_u64_x2() { + let a: [u64; 5] = [0, 1, 2, 3, 4]; + let e: [u64x2; 2] = [u64x2::new(1, 2), u64x2::new(3, 4)]; + let r: [u64x2; 2] = transmute(vld1q_u64_x2(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtq_f32_u32() { - let a: u32x4 = u32x4::new(1, 2, 3, 4); - let e: f32x4 = f32x4::new(1., 2., 3., 4.); - let r: f32x4 = transmute(vcvtq_f32_u32(transmute(a))); + unsafe fn test_vld1_u8_x3() { + let a: [u8; 25] = [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]; + let e: [u8x8; 3] = [u8x8::new(1, 2, 3, 4, 5, 6, 7, 8), u8x8::new(9, 10, 11, 12, 13, 14, 15, 16), u8x8::new(17, 18, 19, 20, 21, 22, 23, 24)]; + let r: [u8x8; 3] = transmute(vld1_u8_x3(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvt_n_f32_s32() { - let a: i32x2 = i32x2::new(1, 2); - let e: f32x2 = f32x2::new(0.25, 0.5); - let r: f32x2 = transmute(vcvt_n_f32_s32::<2>(transmute(a))); + unsafe fn test_vld1_u16_x3() { + let a: [u16; 13] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + let e: [u16x4; 3] = [u16x4::new(1, 2, 3, 4), u16x4::new(5, 6, 7, 8), u16x4::new(9, 10, 11, 12)]; + let r: [u16x4; 3] = transmute(vld1_u16_x3(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtq_n_f32_s32() { - let a: i32x4 = i32x4::new(1, 2, 3, 4); - let e: f32x4 = f32x4::new(0.25, 0.5, 0.75, 1.); - let r: f32x4 = transmute(vcvtq_n_f32_s32::<2>(transmute(a))); + unsafe fn test_vld1_u32_x3() { + let a: [u32; 7] = [0, 1, 2, 3, 4, 5, 6]; + let e: [u32x2; 3] = [u32x2::new(1, 2), u32x2::new(3, 4), u32x2::new(5, 6)]; + let r: [u32x2; 3] = transmute(vld1_u32_x3(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvt_n_f32_u32() { - let a: u32x2 = u32x2::new(1, 2); - let e: f32x2 = f32x2::new(0.25, 0.5); - let r: f32x2 = transmute(vcvt_n_f32_u32::<2>(transmute(a))); + unsafe fn test_vld1_u64_x3() { + let a: [u64; 4] = [0, 1, 2, 3]; + let e: [u64x1; 3] = [u64x1::new(1), u64x1::new(2), u64x1::new(3)]; + let r: [u64x1; 3] = transmute(vld1_u64_x3(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtq_n_f32_u32() { - let a: u32x4 = u32x4::new(1, 2, 3, 4); - let e: f32x4 = f32x4::new(0.25, 0.5, 0.75, 1.); - let r: f32x4 = transmute(vcvtq_n_f32_u32::<2>(transmute(a))); + unsafe fn test_vld1q_u8_x3() { + let a: [u8; 49] = [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, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let e: [u8x16; 3] = [u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), u8x16::new(17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32), u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)]; + let r: [u8x16; 3] = transmute(vld1q_u8_x3(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvt_n_s32_f32() { - let a: f32x2 = f32x2::new(0.25, 0.5); - let e: i32x2 = i32x2::new(1, 2); - let r: i32x2 = transmute(vcvt_n_s32_f32::<2>(transmute(a))); + unsafe fn test_vld1q_u16_x3() { + let a: [u16; 25] = [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]; + let e: [u16x8; 3] = [u16x8::new(1, 2, 3, 4, 5, 6, 7, 8), u16x8::new(9, 10, 11, 12, 13, 14, 15, 16), u16x8::new(17, 18, 19, 20, 21, 22, 23, 24)]; + let r: [u16x8; 3] = transmute(vld1q_u16_x3(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtq_n_s32_f32() { - let a: f32x4 = f32x4::new(0.25, 0.5, 0.75, 1.); - let e: i32x4 = i32x4::new(1, 2, 3, 4); - let r: i32x4 = transmute(vcvtq_n_s32_f32::<2>(transmute(a))); + unsafe fn test_vld1q_u32_x3() { + let a: [u32; 13] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + let e: [u32x4; 3] = [u32x4::new(1, 2, 3, 4), u32x4::new(5, 6, 7, 8), u32x4::new(9, 10, 11, 12)]; + let r: [u32x4; 3] = transmute(vld1q_u32_x3(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvt_n_u32_f32() { - let a: f32x2 = f32x2::new(0.25, 0.5); - let e: u32x2 = u32x2::new(1, 2); - let r: u32x2 = transmute(vcvt_n_u32_f32::<2>(transmute(a))); + unsafe fn test_vld1q_u64_x3() { + let a: [u64; 7] = [0, 1, 2, 3, 4, 5, 6]; + let e: [u64x2; 3] = [u64x2::new(1, 2), u64x2::new(3, 4), u64x2::new(5, 6)]; + let r: [u64x2; 3] = transmute(vld1q_u64_x3(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtq_n_u32_f32() { - let a: f32x4 = f32x4::new(0.25, 0.5, 0.75, 1.); - let e: u32x4 = u32x4::new(1, 2, 3, 4); - let r: u32x4 = transmute(vcvtq_n_u32_f32::<2>(transmute(a))); + unsafe fn test_vld1_u8_x4() { + let a: [u8; 33] = [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]; + let e: [u8x8; 4] = [u8x8::new(1, 2, 3, 4, 5, 6, 7, 8), u8x8::new(9, 10, 11, 12, 13, 14, 15, 16), u8x8::new(17, 18, 19, 20, 21, 22, 23, 24), u8x8::new(25, 26, 27, 28, 29, 30, 31, 32)]; + let r: [u8x8; 4] = transmute(vld1_u8_x4(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvt_s32_f32() { - let a: f32x2 = f32x2::new(-1.1, 2.1); - let e: i32x2 = i32x2::new(-1, 2); - let r: i32x2 = transmute(vcvt_s32_f32(transmute(a))); + unsafe fn test_vld1_u16_x4() { + let a: [u16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let e: [u16x4; 4] = [u16x4::new(1, 2, 3, 4), u16x4::new(5, 6, 7, 8), u16x4::new(9, 10, 11, 12), u16x4::new(13, 14, 15, 16)]; + let r: [u16x4; 4] = transmute(vld1_u16_x4(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtq_s32_f32() { - let a: f32x4 = f32x4::new(-1.1, 2.1, -2.9, 3.9); - let e: i32x4 = i32x4::new(-1, 2, -2, 3); - let r: i32x4 = transmute(vcvtq_s32_f32(transmute(a))); + unsafe fn test_vld1_u32_x4() { + let a: [u32; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let e: [u32x2; 4] = [u32x2::new(1, 2), u32x2::new(3, 4), u32x2::new(5, 6), u32x2::new(7, 8)]; + let r: [u32x2; 4] = transmute(vld1_u32_x4(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvt_u32_f32() { - let a: f32x2 = f32x2::new(1.1, 2.1); - let e: u32x2 = u32x2::new(1, 2); - let r: u32x2 = transmute(vcvt_u32_f32(transmute(a))); + unsafe fn test_vld1_u64_x4() { + let a: [u64; 5] = [0, 1, 2, 3, 4]; + let e: [u64x1; 4] = [u64x1::new(1), u64x1::new(2), u64x1::new(3), u64x1::new(4)]; + let r: [u64x1; 4] = transmute(vld1_u64_x4(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcvtq_u32_f32() { - let a: f32x4 = f32x4::new(1.1, 2.1, 2.9, 3.9); - let e: u32x4 = u32x4::new(1, 2, 2, 3); - let r: u32x4 = transmute(vcvtq_u32_f32(transmute(a))); + unsafe fn test_vld1q_u8_x4() { + let a: [u8; 65] = [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, 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 e: [u8x16; 4] = [u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), u8x16::new(17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32), u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), u8x16::new(17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32)]; + let r: [u8x16; 4] = transmute(vld1q_u8_x4(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdup_lane_s8() { - let a: i8x8 = i8x8::new(1, 1, 1, 4, 1, 6, 7, 8); - let e: i8x8 = i8x8::new(1, 1, 1, 1, 1, 1, 1, 1); - let r: i8x8 = transmute(vdup_lane_s8::<4>(transmute(a))); + unsafe fn test_vld1q_u16_x4() { + let a: [u16; 33] = [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]; + let e: [u16x8; 4] = [u16x8::new(1, 2, 3, 4, 5, 6, 7, 8), u16x8::new(9, 10, 11, 12, 13, 14, 15, 16), u16x8::new(17, 18, 19, 20, 21, 22, 23, 24), u16x8::new(25, 26, 27, 28, 29, 30, 31, 32)]; + let r: [u16x8; 4] = transmute(vld1q_u16_x4(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupq_laneq_s8() { - let a: i8x16 = i8x16::new(1, 1, 1, 4, 1, 6, 7, 8, 1, 10, 11, 12, 13, 14, 15, 16); - let e: i8x16 = i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); - let r: i8x16 = transmute(vdupq_laneq_s8::<8>(transmute(a))); + unsafe fn test_vld1q_u32_x4() { + let a: [u32; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let e: [u32x4; 4] = [u32x4::new(1, 2, 3, 4), u32x4::new(5, 6, 7, 8), u32x4::new(9, 10, 11, 12), u32x4::new(13, 14, 15, 16)]; + let r: [u32x4; 4] = transmute(vld1q_u32_x4(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdup_lane_s16() { - let a: i16x4 = i16x4::new(1, 1, 1, 4); - let e: i16x4 = i16x4::new(1, 1, 1, 1); - let r: i16x4 = transmute(vdup_lane_s16::<2>(transmute(a))); + unsafe fn test_vld1q_u64_x4() { + let a: [u64; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let e: [u64x2; 4] = [u64x2::new(1, 2), u64x2::new(3, 4), u64x2::new(5, 6), u64x2::new(7, 8)]; + let r: [u64x2; 4] = transmute(vld1q_u64_x4(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupq_laneq_s16() { - let a: i16x8 = i16x8::new(1, 1, 1, 4, 1, 6, 7, 8); - let e: i16x8 = i16x8::new(1, 1, 1, 1, 1, 1, 1, 1); - let r: i16x8 = transmute(vdupq_laneq_s16::<4>(transmute(a))); + unsafe fn test_vld1_p8_x2() { + let a: [u8; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let e: [i8x8; 2] = [i8x8::new(1, 2, 3, 4, 5, 6, 7, 8), i8x8::new(9, 10, 11, 12, 13, 14, 15, 16)]; + let r: [i8x8; 2] = transmute(vld1_p8_x2(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdup_lane_s32() { - let a: i32x2 = i32x2::new(1, 1); - let e: i32x2 = i32x2::new(1, 1); - let r: i32x2 = transmute(vdup_lane_s32::<1>(transmute(a))); + unsafe fn test_vld1_p8_x3() { + let a: [u8; 25] = [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]; + let e: [i8x8; 3] = [i8x8::new(1, 2, 3, 4, 5, 6, 7, 8), i8x8::new(9, 10, 11, 12, 13, 14, 15, 16), i8x8::new(17, 18, 19, 20, 21, 22, 23, 24)]; + let r: [i8x8; 3] = transmute(vld1_p8_x3(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupq_laneq_s32() { - let a: i32x4 = i32x4::new(1, 1, 1, 4); - let e: i32x4 = i32x4::new(1, 1, 1, 1); - let r: i32x4 = transmute(vdupq_laneq_s32::<2>(transmute(a))); + unsafe fn test_vld1_p8_x4() { + let a: [u8; 33] = [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]; + let e: [i8x8; 4] = [i8x8::new(1, 2, 3, 4, 5, 6, 7, 8), i8x8::new(9, 10, 11, 12, 13, 14, 15, 16), i8x8::new(17, 18, 19, 20, 21, 22, 23, 24), i8x8::new(25, 26, 27, 28, 29, 30, 31, 32)]; + let r: [i8x8; 4] = transmute(vld1_p8_x4(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdup_laneq_s8() { - let a: i8x16 = i8x16::new(1, 1, 1, 4, 1, 6, 7, 8, 1, 10, 11, 12, 13, 14, 15, 16); - let e: i8x8 = i8x8::new(1, 1, 1, 1, 1, 1, 1, 1); - let r: i8x8 = transmute(vdup_laneq_s8::<8>(transmute(a))); + unsafe fn test_vld1q_p8_x2() { + let a: [u8; 33] = [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]; + let e: [i8x16; 2] = [i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), i8x16::new(17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32)]; + let r: [i8x16; 2] = transmute(vld1q_p8_x2(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdup_laneq_s16() { - let a: i16x8 = i16x8::new(1, 1, 1, 4, 1, 6, 7, 8); - let e: i16x4 = i16x4::new(1, 1, 1, 1); - let r: i16x4 = transmute(vdup_laneq_s16::<4>(transmute(a))); + unsafe fn test_vld1q_p8_x3() { + let a: [u8; 49] = [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, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let e: [i8x16; 3] = [i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), i8x16::new(17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32), i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)]; + let r: [i8x16; 3] = transmute(vld1q_p8_x3(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdup_laneq_s32() { - let a: i32x4 = i32x4::new(1, 1, 1, 4); - let e: i32x2 = i32x2::new(1, 1); - let r: i32x2 = transmute(vdup_laneq_s32::<2>(transmute(a))); + unsafe fn test_vld1q_p8_x4() { + let a: [u8; 65] = [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, 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 e: [i8x16; 4] = [i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), i8x16::new(17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32), i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), i8x16::new(17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32)]; + let r: [i8x16; 4] = transmute(vld1q_p8_x4(a[1..].as_ptr())); assert_eq!(r, e); } - - #[simd_test(enable = "neon")] - unsafe fn test_vdupq_lane_s8() { - let a: i8x8 = i8x8::new(1, 1, 1, 4, 1, 6, 7, 8); - let e: i8x16 = i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); - let r: i8x16 = transmute(vdupq_lane_s8::<4>(transmute(a))); + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_p16_x2() { + let a: [u16; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let e: [i16x4; 2] = [i16x4::new(1, 2, 3, 4), i16x4::new(5, 6, 7, 8)]; + let r: [i16x4; 2] = transmute(vld1_p16_x2(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupq_lane_s16() { - let a: i16x4 = i16x4::new(1, 1, 1, 4); - let e: i16x8 = i16x8::new(1, 1, 1, 1, 1, 1, 1, 1); - let r: i16x8 = transmute(vdupq_lane_s16::<2>(transmute(a))); + unsafe fn test_vld1_p16_x3() { + let a: [u16; 13] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + let e: [i16x4; 3] = [i16x4::new(1, 2, 3, 4), i16x4::new(5, 6, 7, 8), i16x4::new(9, 10, 11, 12)]; + let r: [i16x4; 3] = transmute(vld1_p16_x3(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupq_lane_s32() { - let a: i32x2 = i32x2::new(1, 1); - let e: i32x4 = i32x4::new(1, 1, 1, 1); - let r: i32x4 = transmute(vdupq_lane_s32::<1>(transmute(a))); + unsafe fn test_vld1_p16_x4() { + let a: [u16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let e: [i16x4; 4] = [i16x4::new(1, 2, 3, 4), i16x4::new(5, 6, 7, 8), i16x4::new(9, 10, 11, 12), i16x4::new(13, 14, 15, 16)]; + let r: [i16x4; 4] = transmute(vld1_p16_x4(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdup_lane_u8() { - let a: u8x8 = u8x8::new(1, 1, 1, 4, 1, 6, 7, 8); - let e: u8x8 = u8x8::new(1, 1, 1, 1, 1, 1, 1, 1); - let r: u8x8 = transmute(vdup_lane_u8::<4>(transmute(a))); + unsafe fn test_vld1q_p16_x2() { + let a: [u16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let e: [i16x8; 2] = [i16x8::new(1, 2, 3, 4, 5, 6, 7, 8), i16x8::new(9, 10, 11, 12, 13, 14, 15, 16)]; + let r: [i16x8; 2] = transmute(vld1q_p16_x2(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupq_laneq_u8() { - let a: u8x16 = u8x16::new(1, 1, 1, 4, 1, 6, 7, 8, 1, 10, 11, 12, 13, 14, 15, 16); - let e: u8x16 = u8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); - let r: u8x16 = transmute(vdupq_laneq_u8::<8>(transmute(a))); + unsafe fn test_vld1q_p16_x3() { + let a: [u16; 25] = [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]; + let e: [i16x8; 3] = [i16x8::new(1, 2, 3, 4, 5, 6, 7, 8), i16x8::new(9, 10, 11, 12, 13, 14, 15, 16), i16x8::new(17, 18, 19, 20, 21, 22, 23, 24)]; + let r: [i16x8; 3] = transmute(vld1q_p16_x3(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdup_lane_u16() { - let a: u16x4 = u16x4::new(1, 1, 1, 4); - let e: u16x4 = u16x4::new(1, 1, 1, 1); - let r: u16x4 = transmute(vdup_lane_u16::<2>(transmute(a))); + unsafe fn test_vld1q_p16_x4() { + let a: [u16; 33] = [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]; + let e: [i16x8; 4] = [i16x8::new(1, 2, 3, 4, 5, 6, 7, 8), i16x8::new(9, 10, 11, 12, 13, 14, 15, 16), i16x8::new(17, 18, 19, 20, 21, 22, 23, 24), i16x8::new(25, 26, 27, 28, 29, 30, 31, 32)]; + let r: [i16x8; 4] = transmute(vld1q_p16_x4(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupq_laneq_u16() { - let a: u16x8 = u16x8::new(1, 1, 1, 4, 1, 6, 7, 8); - let e: u16x8 = u16x8::new(1, 1, 1, 1, 1, 1, 1, 1); - let r: u16x8 = transmute(vdupq_laneq_u16::<4>(transmute(a))); + unsafe fn test_vld1_p64_x2() { + let a: [u64; 3] = [0, 1, 2]; + let e: [i64x1; 2] = [i64x1::new(1), i64x1::new(2)]; + let r: [i64x1; 2] = transmute(vld1_p64_x2(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdup_lane_u32() { - let a: u32x2 = u32x2::new(1, 1); - let e: u32x2 = u32x2::new(1, 1); - let r: u32x2 = transmute(vdup_lane_u32::<1>(transmute(a))); + unsafe fn test_vld1_p64_x3() { + let a: [u64; 4] = [0, 1, 2, 3]; + let e: [i64x1; 3] = [i64x1::new(1), i64x1::new(2), i64x1::new(3)]; + let r: [i64x1; 3] = transmute(vld1_p64_x3(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupq_laneq_u32() { - let a: u32x4 = u32x4::new(1, 1, 1, 4); - let e: u32x4 = u32x4::new(1, 1, 1, 1); - let r: u32x4 = transmute(vdupq_laneq_u32::<2>(transmute(a))); + unsafe fn test_vld1_p64_x4() { + let a: [u64; 5] = [0, 1, 2, 3, 4]; + let e: [i64x1; 4] = [i64x1::new(1), i64x1::new(2), i64x1::new(3), i64x1::new(4)]; + let r: [i64x1; 4] = transmute(vld1_p64_x4(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdup_laneq_u8() { - let a: u8x16 = u8x16::new(1, 1, 1, 4, 1, 6, 7, 8, 1, 10, 11, 12, 13, 14, 15, 16); - let e: u8x8 = u8x8::new(1, 1, 1, 1, 1, 1, 1, 1); - let r: u8x8 = transmute(vdup_laneq_u8::<8>(transmute(a))); + unsafe fn test_vld1q_p64_x2() { + let a: [u64; 5] = [0, 1, 2, 3, 4]; + let e: [i64x2; 2] = [i64x2::new(1, 2), i64x2::new(3, 4)]; + let r: [i64x2; 2] = transmute(vld1q_p64_x2(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdup_laneq_u16() { - let a: u16x8 = u16x8::new(1, 1, 1, 4, 1, 6, 7, 8); - let e: u16x4 = u16x4::new(1, 1, 1, 1); - let r: u16x4 = transmute(vdup_laneq_u16::<4>(transmute(a))); + unsafe fn test_vld1q_p64_x3() { + let a: [u64; 7] = [0, 1, 2, 3, 4, 5, 6]; + let e: [i64x2; 3] = [i64x2::new(1, 2), i64x2::new(3, 4), i64x2::new(5, 6)]; + let r: [i64x2; 3] = transmute(vld1q_p64_x3(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdup_laneq_u32() { - let a: u32x4 = u32x4::new(1, 1, 1, 4); - let e: u32x2 = u32x2::new(1, 1); - let r: u32x2 = transmute(vdup_laneq_u32::<2>(transmute(a))); + unsafe fn test_vld1q_p64_x4() { + let a: [u64; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let e: [i64x2; 4] = [i64x2::new(1, 2), i64x2::new(3, 4), i64x2::new(5, 6), i64x2::new(7, 8)]; + let r: [i64x2; 4] = transmute(vld1q_p64_x4(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupq_lane_u8() { - let a: u8x8 = u8x8::new(1, 1, 1, 4, 1, 6, 7, 8); - let e: u8x16 = u8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); - let r: u8x16 = transmute(vdupq_lane_u8::<4>(transmute(a))); + unsafe fn test_vld1_f32_x2() { + let a: [f32; 5] = [0., 1., 2., 3., 4.]; + let e: [f32x2; 2] = [f32x2::new(1., 2.), f32x2::new(3., 4.)]; + let r: [f32x2; 2] = transmute(vld1_f32_x2(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupq_lane_u16() { - let a: u16x4 = u16x4::new(1, 1, 1, 4); - let e: u16x8 = u16x8::new(1, 1, 1, 1, 1, 1, 1, 1); - let r: u16x8 = transmute(vdupq_lane_u16::<2>(transmute(a))); + unsafe fn test_vld1q_f32_x2() { + let a: [f32; 9] = [0., 1., 2., 3., 4., 5., 6., 7., 8.]; + let e: [f32x4; 2] = [f32x4::new(1., 2., 3., 4.), f32x4::new(5., 6., 7., 8.)]; + let r: [f32x4; 2] = transmute(vld1q_f32_x2(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupq_lane_u32() { - let a: u32x2 = u32x2::new(1, 1); - let e: u32x4 = u32x4::new(1, 1, 1, 1); - let r: u32x4 = transmute(vdupq_lane_u32::<1>(transmute(a))); + unsafe fn test_vld1_f32_x3() { + let a: [f32; 7] = [0., 1., 2., 3., 4., 5., 6.]; + let e: [f32x2; 3] = [f32x2::new(1., 2.), f32x2::new(3., 4.), f32x2::new(5., 6.)]; + let r: [f32x2; 3] = transmute(vld1_f32_x3(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdup_lane_p8() { - let a: i8x8 = i8x8::new(1, 1, 1, 4, 1, 6, 7, 8); - let e: i8x8 = i8x8::new(1, 1, 1, 1, 1, 1, 1, 1); - let r: i8x8 = transmute(vdup_lane_p8::<4>(transmute(a))); + unsafe fn test_vld1q_f32_x3() { + let a: [f32; 13] = [0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; + let e: [f32x4; 3] = [f32x4::new(1., 2., 3., 4.), f32x4::new(5., 6., 7., 8.), f32x4::new(9., 10., 11., 12.)]; + let r: [f32x4; 3] = transmute(vld1q_f32_x3(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupq_laneq_p8() { - let a: i8x16 = i8x16::new(1, 1, 1, 4, 1, 6, 7, 8, 1, 10, 11, 12, 13, 14, 15, 16); - let e: i8x16 = i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); - let r: i8x16 = transmute(vdupq_laneq_p8::<8>(transmute(a))); + unsafe fn test_vld1_f32_x4() { + let a: [f32; 9] = [0., 1., 2., 3., 4., 5., 6., 7., 8.]; + let e: [f32x2; 4] = [f32x2::new(1., 2.), f32x2::new(3., 4.), f32x2::new(5., 6.), f32x2::new(7., 8.)]; + let r: [f32x2; 4] = transmute(vld1_f32_x4(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdup_lane_p16() { - let a: i16x4 = i16x4::new(1, 1, 1, 4); - let e: i16x4 = i16x4::new(1, 1, 1, 1); - let r: i16x4 = transmute(vdup_lane_p16::<2>(transmute(a))); + unsafe fn test_vld1q_f32_x4() { + let a: [f32; 17] = [0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16.]; + let e: [f32x4; 4] = [f32x4::new(1., 2., 3., 4.), f32x4::new(5., 6., 7., 8.), f32x4::new(9., 10., 11., 12.), f32x4::new(13., 14., 15., 16.)]; + let r: [f32x4; 4] = transmute(vld1q_f32_x4(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupq_laneq_p16() { - let a: i16x8 = i16x8::new(1, 1, 1, 4, 1, 6, 7, 8); - let e: i16x8 = i16x8::new(1, 1, 1, 1, 1, 1, 1, 1); - let r: i16x8 = transmute(vdupq_laneq_p16::<4>(transmute(a))); + unsafe fn test_vld2_s8() { + let a: [i8; 17] = [0, 1, 2, 2, 3, 2, 4, 3, 5, 2, 6, 3, 7, 4, 8, 5, 9]; + let e: [i8x8; 2] = [i8x8::new(1, 2, 2, 3, 2, 3, 4, 5), i8x8::new(2, 3, 4, 5, 6, 7, 8, 9)]; + let r: [i8x8; 2] = transmute(vld2_s8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdup_laneq_p8() { - let a: i8x16 = i8x16::new(1, 1, 1, 4, 1, 6, 7, 8, 1, 10, 11, 12, 13, 14, 15, 16); - let e: i8x8 = i8x8::new(1, 1, 1, 1, 1, 1, 1, 1); - let r: i8x8 = transmute(vdup_laneq_p8::<8>(transmute(a))); + unsafe fn test_vld2_s16() { + let a: [i16; 9] = [0, 1, 2, 2, 3, 2, 4, 3, 5]; + let e: [i16x4; 2] = [i16x4::new(1, 2, 2, 3), i16x4::new(2, 3, 4, 5)]; + let r: [i16x4; 2] = transmute(vld2_s16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdup_laneq_p16() { - let a: i16x8 = i16x8::new(1, 1, 1, 4, 1, 6, 7, 8); - let e: i16x4 = i16x4::new(1, 1, 1, 1); - let r: i16x4 = transmute(vdup_laneq_p16::<4>(transmute(a))); + unsafe fn test_vld2_s32() { + let a: [i32; 5] = [0, 1, 2, 2, 3]; + let e: [i32x2; 2] = [i32x2::new(1, 2), i32x2::new(2, 3)]; + let r: [i32x2; 2] = transmute(vld2_s32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupq_lane_p8() { - let a: i8x8 = i8x8::new(1, 1, 1, 4, 1, 6, 7, 8); - let e: i8x16 = i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); - let r: i8x16 = transmute(vdupq_lane_p8::<4>(transmute(a))); + unsafe fn test_vld2q_s8() { + let a: [i8; 33] = [0, 1, 2, 2, 3, 2, 4, 3, 5, 2, 6, 3, 7, 4, 8, 5, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15, 8, 16, 9, 17]; + let e: [i8x16; 2] = [i8x16::new(1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9), i8x16::new(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17)]; + let r: [i8x16; 2] = transmute(vld2q_s8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupq_lane_p16() { - let a: i16x4 = i16x4::new(1, 1, 1, 4); - let e: i16x8 = i16x8::new(1, 1, 1, 1, 1, 1, 1, 1); - let r: i16x8 = transmute(vdupq_lane_p16::<2>(transmute(a))); + unsafe fn test_vld2q_s16() { + let a: [i16; 17] = [0, 1, 2, 2, 3, 2, 4, 3, 5, 2, 6, 3, 7, 4, 8, 5, 9]; + let e: [i16x8; 2] = [i16x8::new(1, 2, 2, 3, 2, 3, 4, 5), i16x8::new(2, 3, 4, 5, 6, 7, 8, 9)]; + let r: [i16x8; 2] = transmute(vld2q_s16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupq_laneq_s64() { - let a: i64x2 = i64x2::new(1, 1); - let e: i64x2 = i64x2::new(1, 1); - let r: i64x2 = transmute(vdupq_laneq_s64::<1>(transmute(a))); + unsafe fn test_vld2q_s32() { + let a: [i32; 9] = [0, 1, 2, 2, 3, 2, 4, 3, 5]; + let e: [i32x4; 2] = [i32x4::new(1, 2, 2, 3), i32x4::new(2, 3, 4, 5)]; + let r: [i32x4; 2] = transmute(vld2q_s32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupq_lane_s64() { - let a: i64x1 = i64x1::new(1); - let e: i64x2 = i64x2::new(1, 1); - let r: i64x2 = transmute(vdupq_lane_s64::<0>(transmute(a))); + unsafe fn test_vld2_s64() { + let a: [i64; 3] = [0, 1, 2]; + let e: [i64x1; 2] = [i64x1::new(1), i64x1::new(2)]; + let r: [i64x1; 2] = transmute(vld2_s64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupq_laneq_u64() { - let a: u64x2 = u64x2::new(1, 1); - let e: u64x2 = u64x2::new(1, 1); - let r: u64x2 = transmute(vdupq_laneq_u64::<1>(transmute(a))); + unsafe fn test_vld2_u8() { + let a: [u8; 17] = [0, 1, 2, 2, 3, 2, 4, 3, 5, 2, 6, 3, 7, 4, 8, 5, 9]; + let e: [u8x8; 2] = [u8x8::new(1, 2, 2, 3, 2, 3, 4, 5), u8x8::new(2, 3, 4, 5, 6, 7, 8, 9)]; + let r: [u8x8; 2] = transmute(vld2_u8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupq_lane_u64() { - let a: u64x1 = u64x1::new(1); - let e: u64x2 = u64x2::new(1, 1); - let r: u64x2 = transmute(vdupq_lane_u64::<0>(transmute(a))); + unsafe fn test_vld2_u16() { + let a: [u16; 9] = [0, 1, 2, 2, 3, 2, 4, 3, 5]; + let e: [u16x4; 2] = [u16x4::new(1, 2, 2, 3), u16x4::new(2, 3, 4, 5)]; + let r: [u16x4; 2] = transmute(vld2_u16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdup_lane_f32() { - let a: f32x2 = f32x2::new(1., 1.); - let e: f32x2 = f32x2::new(1., 1.); - let r: f32x2 = transmute(vdup_lane_f32::<1>(transmute(a))); + unsafe fn test_vld2_u32() { + let a: [u32; 5] = [0, 1, 2, 2, 3]; + let e: [u32x2; 2] = [u32x2::new(1, 2), u32x2::new(2, 3)]; + let r: [u32x2; 2] = transmute(vld2_u32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupq_laneq_f32() { - let a: f32x4 = f32x4::new(1., 1., 1., 4.); - let e: f32x4 = f32x4::new(1., 1., 1., 1.); - let r: f32x4 = transmute(vdupq_laneq_f32::<2>(transmute(a))); + unsafe fn test_vld2q_u8() { + let a: [u8; 33] = [0, 1, 2, 2, 3, 2, 4, 3, 5, 2, 6, 3, 7, 4, 8, 5, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15, 8, 16, 9, 17]; + let e: [u8x16; 2] = [u8x16::new(1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9), u8x16::new(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17)]; + let r: [u8x16; 2] = transmute(vld2q_u8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdup_laneq_f32() { - let a: f32x4 = f32x4::new(1., 1., 1., 4.); - let e: f32x2 = f32x2::new(1., 1.); - let r: f32x2 = transmute(vdup_laneq_f32::<2>(transmute(a))); + unsafe fn test_vld2q_u16() { + let a: [u16; 17] = [0, 1, 2, 2, 3, 2, 4, 3, 5, 2, 6, 3, 7, 4, 8, 5, 9]; + let e: [u16x8; 2] = [u16x8::new(1, 2, 2, 3, 2, 3, 4, 5), u16x8::new(2, 3, 4, 5, 6, 7, 8, 9)]; + let r: [u16x8; 2] = transmute(vld2q_u16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupq_lane_f32() { - let a: f32x2 = f32x2::new(1., 1.); - let e: f32x4 = f32x4::new(1., 1., 1., 1.); - let r: f32x4 = transmute(vdupq_lane_f32::<1>(transmute(a))); + unsafe fn test_vld2q_u32() { + let a: [u32; 9] = [0, 1, 2, 2, 3, 2, 4, 3, 5]; + let e: [u32x4; 2] = [u32x4::new(1, 2, 2, 3), u32x4::new(2, 3, 4, 5)]; + let r: [u32x4; 2] = transmute(vld2q_u32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdup_lane_s64() { - let a: i64x1 = i64x1::new(0); - let e: i64x1 = i64x1::new(0); - let r: i64x1 = transmute(vdup_lane_s64::<0>(transmute(a))); + unsafe fn test_vld2_p8() { + let a: [u8; 17] = [0, 1, 2, 2, 3, 2, 4, 3, 5, 2, 6, 3, 7, 4, 8, 5, 9]; + let e: [i8x8; 2] = [i8x8::new(1, 2, 2, 3, 2, 3, 4, 5), i8x8::new(2, 3, 4, 5, 6, 7, 8, 9)]; + let r: [i8x8; 2] = transmute(vld2_p8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdup_lane_u64() { - let a: u64x1 = u64x1::new(0); - let e: u64x1 = u64x1::new(0); - let r: u64x1 = transmute(vdup_lane_u64::<0>(transmute(a))); + unsafe fn test_vld2_p16() { + let a: [u16; 9] = [0, 1, 2, 2, 3, 2, 4, 3, 5]; + let e: [i16x4; 2] = [i16x4::new(1, 2, 2, 3), i16x4::new(2, 3, 4, 5)]; + let r: [i16x4; 2] = transmute(vld2_p16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdup_laneq_s64() { - let a: i64x2 = i64x2::new(0, 1); - let e: i64x1 = i64x1::new(1); - let r: i64x1 = transmute(vdup_laneq_s64::<1>(transmute(a))); + unsafe fn test_vld2q_p8() { + let a: [u8; 33] = [0, 1, 2, 2, 3, 2, 4, 3, 5, 2, 6, 3, 7, 4, 8, 5, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15, 8, 16, 9, 17]; + let e: [i8x16; 2] = [i8x16::new(1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9), i8x16::new(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17)]; + let r: [i8x16; 2] = transmute(vld2q_p8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdup_laneq_u64() { - let a: u64x2 = u64x2::new(0, 1); - let e: u64x1 = u64x1::new(1); - let r: u64x1 = transmute(vdup_laneq_u64::<1>(transmute(a))); + unsafe fn test_vld2q_p16() { + let a: [u16; 17] = [0, 1, 2, 2, 3, 2, 4, 3, 5, 2, 6, 3, 7, 4, 8, 5, 9]; + let e: [i16x8; 2] = [i16x8::new(1, 2, 2, 3, 2, 3, 4, 5), i16x8::new(2, 3, 4, 5, 6, 7, 8, 9)]; + let r: [i16x8; 2] = transmute(vld2q_p16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vext_s8() { - let a: i8x8 = i8x8::new(0, 8, 8, 9, 8, 9, 9, 11); - let b: i8x8 = i8x8::new(9, 11, 14, 15, 16, 17, 18, 19); - let e: i8x8 = i8x8::new(8, 9, 9, 11, 9, 11, 14, 15); - let r: i8x8 = transmute(vext_s8::<4>(transmute(a), transmute(b))); + unsafe fn test_vld2_u64() { + let a: [u64; 3] = [0, 1, 2]; + let e: [u64x1; 2] = [u64x1::new(1), u64x1::new(2)]; + let r: [u64x1; 2] = transmute(vld2_u64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vextq_s8() { - let a: i8x16 = i8x16::new(0, 8, 8, 9, 8, 9, 9, 11, 8, 9, 9, 11, 9, 11, 14, 15); - let b: i8x16 = i8x16::new(9, 11, 14, 15, 16, 17, 18, 19, 0, 8, 8, 9, 8, 9, 9, 11); - let e: i8x16 = i8x16::new(8, 9, 9, 11, 9, 11, 14, 15, 9, 11, 14, 15, 16, 17, 18, 19); - let r: i8x16 = transmute(vextq_s8::<8>(transmute(a), transmute(b))); + unsafe fn test_vld2_p64() { + let a: [u64; 3] = [0, 1, 2]; + let e: [i64x1; 2] = [i64x1::new(1), i64x1::new(2)]; + let r: [i64x1; 2] = transmute(vld2_p64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vext_s16() { - let a: i16x4 = i16x4::new(0, 8, 8, 9); - let b: i16x4 = i16x4::new(9, 11, 14, 15); - let e: i16x4 = i16x4::new(8, 9, 9, 11); - let r: i16x4 = transmute(vext_s16::<2>(transmute(a), transmute(b))); + unsafe fn test_vld2_f32() { + let a: [f32; 5] = [0., 1., 2., 2., 3.]; + let e: [f32x2; 2] = [f32x2::new(1., 2.), f32x2::new(2., 3.)]; + let r: [f32x2; 2] = transmute(vld2_f32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vextq_s16() { - let a: i16x8 = i16x8::new(0, 8, 8, 9, 8, 9, 9, 11); - let b: i16x8 = i16x8::new(9, 11, 14, 15, 16, 17, 18, 19); - let e: i16x8 = i16x8::new(8, 9, 9, 11, 9, 11, 14, 15); - let r: i16x8 = transmute(vextq_s16::<4>(transmute(a), transmute(b))); + unsafe fn test_vld2q_f32() { + let a: [f32; 9] = [0., 1., 2., 2., 3., 2., 4., 3., 5.]; + let e: [f32x4; 2] = [f32x4::new(1., 2., 2., 3.), f32x4::new(2., 3., 4., 5.)]; + let r: [f32x4; 2] = transmute(vld2q_f32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vext_s32() { - let a: i32x2 = i32x2::new(0, 8); - let b: i32x2 = i32x2::new(9, 11); - let e: i32x2 = i32x2::new(8, 9); - let r: i32x2 = transmute(vext_s32::<1>(transmute(a), transmute(b))); + unsafe fn test_vld2_dup_s8() { + let a: [i8; 17] = [0, 1, 1, 2, 3, 1, 4, 3, 5, 1, 6, 3, 7, 4, 8, 5, 9]; + let e: [i8x8; 2] = [i8x8::new(1, 1, 1, 1, 1, 1, 1, 1), i8x8::new(1, 1, 1, 1, 1, 1, 1, 1)]; + let r: [i8x8; 2] = transmute(vld2_dup_s8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vextq_s32() { - let a: i32x4 = i32x4::new(0, 8, 8, 9); - let b: i32x4 = i32x4::new(9, 11, 14, 15); - let e: i32x4 = i32x4::new(8, 9, 9, 11); - let r: i32x4 = transmute(vextq_s32::<2>(transmute(a), transmute(b))); + unsafe fn test_vld2_dup_s16() { + let a: [i16; 9] = [0, 1, 1, 2, 3, 1, 4, 3, 5]; + let e: [i16x4; 2] = [i16x4::new(1, 1, 1, 1), i16x4::new(1, 1, 1, 1)]; + let r: [i16x4; 2] = transmute(vld2_dup_s16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vext_u8() { - let a: u8x8 = u8x8::new(0, 8, 8, 9, 8, 9, 9, 11); - let b: u8x8 = u8x8::new(9, 11, 14, 15, 16, 17, 18, 19); - let e: u8x8 = u8x8::new(8, 9, 9, 11, 9, 11, 14, 15); - let r: u8x8 = transmute(vext_u8::<4>(transmute(a), transmute(b))); + unsafe fn test_vld2_dup_s32() { + let a: [i32; 5] = [0, 1, 1, 2, 3]; + let e: [i32x2; 2] = [i32x2::new(1, 1), i32x2::new(1, 1)]; + let r: [i32x2; 2] = transmute(vld2_dup_s32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vextq_u8() { - let a: u8x16 = u8x16::new(0, 8, 8, 9, 8, 9, 9, 11, 8, 9, 9, 11, 9, 11, 14, 15); - let b: u8x16 = u8x16::new(9, 11, 14, 15, 16, 17, 18, 19, 0, 8, 8, 9, 8, 9, 9, 11); - let e: u8x16 = u8x16::new(8, 9, 9, 11, 9, 11, 14, 15, 9, 11, 14, 15, 16, 17, 18, 19); - let r: u8x16 = transmute(vextq_u8::<8>(transmute(a), transmute(b))); + unsafe fn test_vld2q_dup_s8() { + let a: [i8; 33] = [0, 1, 1, 2, 3, 1, 4, 3, 5, 1, 6, 3, 7, 4, 8, 5, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15, 8, 16, 9, 17]; + let e: [i8x16; 2] = [i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)]; + let r: [i8x16; 2] = transmute(vld2q_dup_s8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vext_u16() { - let a: u16x4 = u16x4::new(0, 8, 8, 9); - let b: u16x4 = u16x4::new(9, 11, 14, 15); - let e: u16x4 = u16x4::new(8, 9, 9, 11); - let r: u16x4 = transmute(vext_u16::<2>(transmute(a), transmute(b))); + unsafe fn test_vld2q_dup_s16() { + let a: [i16; 17] = [0, 1, 1, 2, 3, 1, 4, 3, 5, 1, 6, 3, 7, 4, 8, 5, 9]; + let e: [i16x8; 2] = [i16x8::new(1, 1, 1, 1, 1, 1, 1, 1), i16x8::new(1, 1, 1, 1, 1, 1, 1, 1)]; + let r: [i16x8; 2] = transmute(vld2q_dup_s16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vextq_u16() { - let a: u16x8 = u16x8::new(0, 8, 8, 9, 8, 9, 9, 11); - let b: u16x8 = u16x8::new(9, 11, 14, 15, 16, 17, 18, 19); - let e: u16x8 = u16x8::new(8, 9, 9, 11, 9, 11, 14, 15); - let r: u16x8 = transmute(vextq_u16::<4>(transmute(a), transmute(b))); + unsafe fn test_vld2q_dup_s32() { + let a: [i32; 9] = [0, 1, 1, 2, 3, 1, 4, 3, 5]; + let e: [i32x4; 2] = [i32x4::new(1, 1, 1, 1), i32x4::new(1, 1, 1, 1)]; + let r: [i32x4; 2] = transmute(vld2q_dup_s32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vext_u32() { - let a: u32x2 = u32x2::new(0, 8); - let b: u32x2 = u32x2::new(9, 11); - let e: u32x2 = u32x2::new(8, 9); - let r: u32x2 = transmute(vext_u32::<1>(transmute(a), transmute(b))); + unsafe fn test_vld2_dup_s64() { + let a: [i64; 3] = [0, 1, 1]; + let e: [i64x1; 2] = [i64x1::new(1), i64x1::new(1)]; + let r: [i64x1; 2] = transmute(vld2_dup_s64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vextq_u32() { - let a: u32x4 = u32x4::new(0, 8, 8, 9); - let b: u32x4 = u32x4::new(9, 11, 14, 15); - let e: u32x4 = u32x4::new(8, 9, 9, 11); - let r: u32x4 = transmute(vextq_u32::<2>(transmute(a), transmute(b))); + unsafe fn test_vld2_dup_u8() { + let a: [u8; 17] = [0, 1, 1, 2, 3, 1, 4, 3, 5, 1, 6, 3, 7, 4, 8, 5, 9]; + let e: [u8x8; 2] = [u8x8::new(1, 1, 1, 1, 1, 1, 1, 1), u8x8::new(1, 1, 1, 1, 1, 1, 1, 1)]; + let r: [u8x8; 2] = transmute(vld2_dup_u8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vext_p8() { - let a: i8x8 = i8x8::new(0, 8, 8, 9, 8, 9, 9, 11); - let b: i8x8 = i8x8::new(9, 11, 14, 15, 16, 17, 18, 19); - let e: i8x8 = i8x8::new(8, 9, 9, 11, 9, 11, 14, 15); - let r: i8x8 = transmute(vext_p8::<4>(transmute(a), transmute(b))); + unsafe fn test_vld2_dup_u16() { + let a: [u16; 9] = [0, 1, 1, 2, 3, 1, 4, 3, 5]; + let e: [u16x4; 2] = [u16x4::new(1, 1, 1, 1), u16x4::new(1, 1, 1, 1)]; + let r: [u16x4; 2] = transmute(vld2_dup_u16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vextq_p8() { - let a: i8x16 = i8x16::new(0, 8, 8, 9, 8, 9, 9, 11, 8, 9, 9, 11, 9, 11, 14, 15); - let b: i8x16 = i8x16::new(9, 11, 14, 15, 16, 17, 18, 19, 0, 8, 8, 9, 8, 9, 9, 11); - let e: i8x16 = i8x16::new(8, 9, 9, 11, 9, 11, 14, 15, 9, 11, 14, 15, 16, 17, 18, 19); - let r: i8x16 = transmute(vextq_p8::<8>(transmute(a), transmute(b))); + unsafe fn test_vld2_dup_u32() { + let a: [u32; 5] = [0, 1, 1, 2, 3]; + let e: [u32x2; 2] = [u32x2::new(1, 1), u32x2::new(1, 1)]; + let r: [u32x2; 2] = transmute(vld2_dup_u32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vext_p16() { - let a: i16x4 = i16x4::new(0, 8, 8, 9); - let b: i16x4 = i16x4::new(9, 11, 14, 15); - let e: i16x4 = i16x4::new(8, 9, 9, 11); - let r: i16x4 = transmute(vext_p16::<2>(transmute(a), transmute(b))); + unsafe fn test_vld2q_dup_u8() { + let a: [u8; 33] = [0, 1, 1, 2, 3, 1, 4, 3, 5, 1, 6, 3, 7, 4, 8, 5, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15, 8, 16, 9, 17]; + let e: [u8x16; 2] = [u8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), u8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)]; + let r: [u8x16; 2] = transmute(vld2q_dup_u8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vextq_p16() { - let a: i16x8 = i16x8::new(0, 8, 8, 9, 8, 9, 9, 11); - let b: i16x8 = i16x8::new(9, 11, 14, 15, 16, 17, 18, 19); - let e: i16x8 = i16x8::new(8, 9, 9, 11, 9, 11, 14, 15); - let r: i16x8 = transmute(vextq_p16::<4>(transmute(a), transmute(b))); + unsafe fn test_vld2q_dup_u16() { + let a: [u16; 17] = [0, 1, 1, 2, 3, 1, 4, 3, 5, 1, 6, 3, 7, 4, 8, 5, 9]; + let e: [u16x8; 2] = [u16x8::new(1, 1, 1, 1, 1, 1, 1, 1), u16x8::new(1, 1, 1, 1, 1, 1, 1, 1)]; + let r: [u16x8; 2] = transmute(vld2q_dup_u16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vextq_s64() { - let a: i64x2 = i64x2::new(0, 8); - let b: i64x2 = i64x2::new(9, 11); - let e: i64x2 = i64x2::new(8, 9); - let r: i64x2 = transmute(vextq_s64::<1>(transmute(a), transmute(b))); + unsafe fn test_vld2q_dup_u32() { + let a: [u32; 9] = [0, 1, 1, 2, 3, 1, 4, 3, 5]; + let e: [u32x4; 2] = [u32x4::new(1, 1, 1, 1), u32x4::new(1, 1, 1, 1)]; + let r: [u32x4; 2] = transmute(vld2q_dup_u32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vextq_u64() { - let a: u64x2 = u64x2::new(0, 8); - let b: u64x2 = u64x2::new(9, 11); - let e: u64x2 = u64x2::new(8, 9); - let r: u64x2 = transmute(vextq_u64::<1>(transmute(a), transmute(b))); + unsafe fn test_vld2_dup_p8() { + let a: [u8; 17] = [0, 1, 1, 2, 3, 1, 4, 3, 5, 1, 6, 3, 7, 4, 8, 5, 9]; + let e: [i8x8; 2] = [i8x8::new(1, 1, 1, 1, 1, 1, 1, 1), i8x8::new(1, 1, 1, 1, 1, 1, 1, 1)]; + let r: [i8x8; 2] = transmute(vld2_dup_p8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vext_f32() { - let a: f32x2 = f32x2::new(0., 2.); - let b: f32x2 = f32x2::new(3., 4.); - let e: f32x2 = f32x2::new(2., 3.); - let r: f32x2 = transmute(vext_f32::<1>(transmute(a), transmute(b))); + unsafe fn test_vld2_dup_p16() { + let a: [u16; 9] = [0, 1, 1, 2, 3, 1, 4, 3, 5]; + let e: [i16x4; 2] = [i16x4::new(1, 1, 1, 1), i16x4::new(1, 1, 1, 1)]; + let r: [i16x4; 2] = transmute(vld2_dup_p16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vextq_f32() { - let a: f32x4 = f32x4::new(0., 2., 2., 3.); - let b: f32x4 = f32x4::new(3., 4., 5., 6.); - let e: f32x4 = f32x4::new(2., 3., 3., 4.); - let r: f32x4 = transmute(vextq_f32::<2>(transmute(a), transmute(b))); + unsafe fn test_vld2q_dup_p8() { + let a: [u8; 33] = [0, 1, 1, 2, 3, 1, 4, 3, 5, 1, 6, 3, 7, 4, 8, 5, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15, 8, 16, 9, 17]; + let e: [i8x16; 2] = [i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)]; + let r: [i8x16; 2] = transmute(vld2q_dup_p8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmla_s8() { - let a: i8x8 = i8x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let b: i8x8 = i8x8::new(2, 2, 2, 2, 2, 2, 2, 2); - let c: i8x8 = i8x8::new(3, 3, 3, 3, 3, 3, 3, 3); - let e: i8x8 = i8x8::new(6, 7, 8, 9, 10, 11, 12, 13); - let r: i8x8 = transmute(vmla_s8(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld2q_dup_p16() { + let a: [u16; 17] = [0, 1, 1, 2, 3, 1, 4, 3, 5, 1, 6, 3, 7, 4, 8, 5, 9]; + let e: [i16x8; 2] = [i16x8::new(1, 1, 1, 1, 1, 1, 1, 1), i16x8::new(1, 1, 1, 1, 1, 1, 1, 1)]; + let r: [i16x8; 2] = transmute(vld2q_dup_p16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlaq_s8() { - let a: i8x16 = i8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - let b: i8x16 = i8x16::new(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); - let c: i8x16 = i8x16::new(3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3); - let e: i8x16 = i8x16::new(6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21); - let r: i8x16 = transmute(vmlaq_s8(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld2_dup_u64() { + let a: [u64; 3] = [0, 1, 1]; + let e: [u64x1; 2] = [u64x1::new(1), u64x1::new(1)]; + let r: [u64x1; 2] = transmute(vld2_dup_u64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmla_s16() { - let a: i16x4 = i16x4::new(0, 1, 2, 3); - let b: i16x4 = i16x4::new(2, 2, 2, 2); - let c: i16x4 = i16x4::new(3, 3, 3, 3); - let e: i16x4 = i16x4::new(6, 7, 8, 9); - let r: i16x4 = transmute(vmla_s16(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld2_dup_p64() { + let a: [u64; 3] = [0, 1, 1]; + let e: [i64x1; 2] = [i64x1::new(1), i64x1::new(1)]; + let r: [i64x1; 2] = transmute(vld2_dup_p64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlaq_s16() { - let a: i16x8 = i16x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let b: i16x8 = i16x8::new(2, 2, 2, 2, 2, 2, 2, 2); - let c: i16x8 = i16x8::new(3, 3, 3, 3, 3, 3, 3, 3); - let e: i16x8 = i16x8::new(6, 7, 8, 9, 10, 11, 12, 13); - let r: i16x8 = transmute(vmlaq_s16(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld2_dup_f32() { + let a: [f32; 5] = [0., 1., 1., 2., 3.]; + let e: [f32x2; 2] = [f32x2::new(1., 1.), f32x2::new(1., 1.)]; + let r: [f32x2; 2] = transmute(vld2_dup_f32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmla_s32() { - let a: i32x2 = i32x2::new(0, 1); - let b: i32x2 = i32x2::new(2, 2); - let c: i32x2 = i32x2::new(3, 3); - let e: i32x2 = i32x2::new(6, 7); - let r: i32x2 = transmute(vmla_s32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld2q_dup_f32() { + let a: [f32; 9] = [0., 1., 1., 2., 3., 1., 4., 3., 5.]; + let e: [f32x4; 2] = [f32x4::new(1., 1., 1., 1.), f32x4::new(1., 1., 1., 1.)]; + let r: [f32x4; 2] = transmute(vld2q_dup_f32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlaq_s32() { - let a: i32x4 = i32x4::new(0, 1, 2, 3); - let b: i32x4 = i32x4::new(2, 2, 2, 2); - let c: i32x4 = i32x4::new(3, 3, 3, 3); - let e: i32x4 = i32x4::new(6, 7, 8, 9); - let r: i32x4 = transmute(vmlaq_s32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld2_lane_s8() { + let a: [i8; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [i8x8; 2] = [i8x8::new(0, 2, 2, 14, 2, 16, 17, 18), i8x8::new(2, 20, 21, 22, 23, 24, 25, 26)]; + let e: [i8x8; 2] = [i8x8::new(1, 2, 2, 14, 2, 16, 17, 18), i8x8::new(2, 20, 21, 22, 23, 24, 25, 26)]; + let r: [i8x8; 2] = transmute(vld2_lane_s8::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmla_u8() { - let a: u8x8 = u8x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let b: u8x8 = u8x8::new(2, 2, 2, 2, 2, 2, 2, 2); - let c: u8x8 = u8x8::new(3, 3, 3, 3, 3, 3, 3, 3); - let e: u8x8 = u8x8::new(6, 7, 8, 9, 10, 11, 12, 13); - let r: u8x8 = transmute(vmla_u8(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld2_lane_s16() { + let a: [i16; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [i16x4; 2] = [i16x4::new(0, 2, 2, 14), i16x4::new(2, 16, 17, 18)]; + let e: [i16x4; 2] = [i16x4::new(1, 2, 2, 14), i16x4::new(2, 16, 17, 18)]; + let r: [i16x4; 2] = transmute(vld2_lane_s16::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlaq_u8() { - let a: u8x16 = u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - let b: u8x16 = u8x16::new(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); - let c: u8x16 = u8x16::new(3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3); - let e: u8x16 = u8x16::new(6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21); - let r: u8x16 = transmute(vmlaq_u8(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld2_lane_s32() { + let a: [i32; 5] = [0, 1, 2, 3, 4]; + let b: [i32x2; 2] = [i32x2::new(0, 2), i32x2::new(2, 14)]; + let e: [i32x2; 2] = [i32x2::new(1, 2), i32x2::new(2, 14)]; + let r: [i32x2; 2] = transmute(vld2_lane_s32::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmla_u16() { - let a: u16x4 = u16x4::new(0, 1, 2, 3); - let b: u16x4 = u16x4::new(2, 2, 2, 2); - let c: u16x4 = u16x4::new(3, 3, 3, 3); - let e: u16x4 = u16x4::new(6, 7, 8, 9); - let r: u16x4 = transmute(vmla_u16(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld2q_lane_s16() { + let a: [i16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [i16x8; 2] = [i16x8::new(0, 2, 2, 14, 2, 16, 17, 18), i16x8::new(2, 20, 21, 22, 23, 24, 25, 26)]; + let e: [i16x8; 2] = [i16x8::new(1, 2, 2, 14, 2, 16, 17, 18), i16x8::new(2, 20, 21, 22, 23, 24, 25, 26)]; + let r: [i16x8; 2] = transmute(vld2q_lane_s16::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlaq_u16() { - let a: u16x8 = u16x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let b: u16x8 = u16x8::new(2, 2, 2, 2, 2, 2, 2, 2); - let c: u16x8 = u16x8::new(3, 3, 3, 3, 3, 3, 3, 3); - let e: u16x8 = u16x8::new(6, 7, 8, 9, 10, 11, 12, 13); - let r: u16x8 = transmute(vmlaq_u16(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld2q_lane_s32() { + let a: [i32; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [i32x4; 2] = [i32x4::new(0, 2, 2, 14), i32x4::new(2, 16, 17, 18)]; + let e: [i32x4; 2] = [i32x4::new(1, 2, 2, 14), i32x4::new(2, 16, 17, 18)]; + let r: [i32x4; 2] = transmute(vld2q_lane_s32::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmla_u32() { - let a: u32x2 = u32x2::new(0, 1); - let b: u32x2 = u32x2::new(2, 2); - let c: u32x2 = u32x2::new(3, 3); - let e: u32x2 = u32x2::new(6, 7); - let r: u32x2 = transmute(vmla_u32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld2_lane_u8() { + let a: [u8; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [u8x8; 2] = [u8x8::new(0, 2, 2, 14, 2, 16, 17, 18), u8x8::new(2, 20, 21, 22, 23, 24, 25, 26)]; + let e: [u8x8; 2] = [u8x8::new(1, 2, 2, 14, 2, 16, 17, 18), u8x8::new(2, 20, 21, 22, 23, 24, 25, 26)]; + let r: [u8x8; 2] = transmute(vld2_lane_u8::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlaq_u32() { - let a: u32x4 = u32x4::new(0, 1, 2, 3); - let b: u32x4 = u32x4::new(2, 2, 2, 2); - let c: u32x4 = u32x4::new(3, 3, 3, 3); - let e: u32x4 = u32x4::new(6, 7, 8, 9); - let r: u32x4 = transmute(vmlaq_u32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld2_lane_u16() { + let a: [u16; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [u16x4; 2] = [u16x4::new(0, 2, 2, 14), u16x4::new(2, 16, 17, 18)]; + let e: [u16x4; 2] = [u16x4::new(1, 2, 2, 14), u16x4::new(2, 16, 17, 18)]; + let r: [u16x4; 2] = transmute(vld2_lane_u16::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmla_f32() { - let a: f32x2 = f32x2::new(0., 1.); - let b: f32x2 = f32x2::new(2., 2.); - let c: f32x2 = f32x2::new(3., 3.); - let e: f32x2 = f32x2::new(6., 7.); - let r: f32x2 = transmute(vmla_f32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld2_lane_u32() { + let a: [u32; 5] = [0, 1, 2, 3, 4]; + let b: [u32x2; 2] = [u32x2::new(0, 2), u32x2::new(2, 14)]; + let e: [u32x2; 2] = [u32x2::new(1, 2), u32x2::new(2, 14)]; + let r: [u32x2; 2] = transmute(vld2_lane_u32::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlaq_f32() { - let a: f32x4 = f32x4::new(0., 1., 2., 3.); - let b: f32x4 = f32x4::new(2., 2., 2., 2.); - let c: f32x4 = f32x4::new(3., 3., 3., 3.); - let e: f32x4 = f32x4::new(6., 7., 8., 9.); - let r: f32x4 = transmute(vmlaq_f32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld2q_lane_u16() { + let a: [u16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [u16x8; 2] = [u16x8::new(0, 2, 2, 14, 2, 16, 17, 18), u16x8::new(2, 20, 21, 22, 23, 24, 25, 26)]; + let e: [u16x8; 2] = [u16x8::new(1, 2, 2, 14, 2, 16, 17, 18), u16x8::new(2, 20, 21, 22, 23, 24, 25, 26)]; + let r: [u16x8; 2] = transmute(vld2q_lane_u16::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmla_n_s16() { - let a: i16x4 = i16x4::new(0, 1, 2, 3); - let b: i16x4 = i16x4::new(2, 2, 2, 2); - let c: i16 = 3; - let e: i16x4 = i16x4::new(6, 7, 8, 9); - let r: i16x4 = transmute(vmla_n_s16(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld2q_lane_u32() { + let a: [u32; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [u32x4; 2] = [u32x4::new(0, 2, 2, 14), u32x4::new(2, 16, 17, 18)]; + let e: [u32x4; 2] = [u32x4::new(1, 2, 2, 14), u32x4::new(2, 16, 17, 18)]; + let r: [u32x4; 2] = transmute(vld2q_lane_u32::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlaq_n_s16() { - let a: i16x8 = i16x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let b: i16x8 = i16x8::new(2, 2, 2, 2, 2, 2, 2, 2); - let c: i16 = 3; - let e: i16x8 = i16x8::new(6, 7, 8, 9, 10, 11, 12, 13); - let r: i16x8 = transmute(vmlaq_n_s16(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld2_lane_p8() { + let a: [u8; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [i8x8; 2] = [i8x8::new(0, 2, 2, 14, 2, 16, 17, 18), i8x8::new(2, 20, 21, 22, 23, 24, 25, 26)]; + let e: [i8x8; 2] = [i8x8::new(1, 2, 2, 14, 2, 16, 17, 18), i8x8::new(2, 20, 21, 22, 23, 24, 25, 26)]; + let r: [i8x8; 2] = transmute(vld2_lane_p8::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmla_n_s32() { - let a: i32x2 = i32x2::new(0, 1); - let b: i32x2 = i32x2::new(2, 2); - let c: i32 = 3; - let e: i32x2 = i32x2::new(6, 7); - let r: i32x2 = transmute(vmla_n_s32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld2_lane_p16() { + let a: [u16; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [i16x4; 2] = [i16x4::new(0, 2, 2, 14), i16x4::new(2, 16, 17, 18)]; + let e: [i16x4; 2] = [i16x4::new(1, 2, 2, 14), i16x4::new(2, 16, 17, 18)]; + let r: [i16x4; 2] = transmute(vld2_lane_p16::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlaq_n_s32() { - let a: i32x4 = i32x4::new(0, 1, 2, 3); - let b: i32x4 = i32x4::new(2, 2, 2, 2); - let c: i32 = 3; - let e: i32x4 = i32x4::new(6, 7, 8, 9); - let r: i32x4 = transmute(vmlaq_n_s32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld2q_lane_p16() { + let a: [u16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [i16x8; 2] = [i16x8::new(0, 2, 2, 14, 2, 16, 17, 18), i16x8::new(2, 20, 21, 22, 23, 24, 25, 26)]; + let e: [i16x8; 2] = [i16x8::new(1, 2, 2, 14, 2, 16, 17, 18), i16x8::new(2, 20, 21, 22, 23, 24, 25, 26)]; + let r: [i16x8; 2] = transmute(vld2q_lane_p16::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmla_n_u16() { - let a: u16x4 = u16x4::new(0, 1, 2, 3); - let b: u16x4 = u16x4::new(2, 2, 2, 2); - let c: u16 = 3; - let e: u16x4 = u16x4::new(6, 7, 8, 9); - let r: u16x4 = transmute(vmla_n_u16(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld2_lane_f32() { + let a: [f32; 5] = [0., 1., 2., 3., 4.]; + let b: [f32x2; 2] = [f32x2::new(0., 2.), f32x2::new(2., 14.)]; + let e: [f32x2; 2] = [f32x2::new(1., 2.), f32x2::new(2., 14.)]; + let r: [f32x2; 2] = transmute(vld2_lane_f32::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlaq_n_u16() { - let a: u16x8 = u16x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let b: u16x8 = u16x8::new(2, 2, 2, 2, 2, 2, 2, 2); - let c: u16 = 3; - let e: u16x8 = u16x8::new(6, 7, 8, 9, 10, 11, 12, 13); - let r: u16x8 = transmute(vmlaq_n_u16(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld2q_lane_f32() { + let a: [f32; 9] = [0., 1., 2., 3., 4., 5., 6., 7., 8.]; + let b: [f32x4; 2] = [f32x4::new(0., 2., 2., 14.), f32x4::new(2., 16., 17., 18.)]; + let e: [f32x4; 2] = [f32x4::new(1., 2., 2., 14.), f32x4::new(2., 16., 17., 18.)]; + let r: [f32x4; 2] = transmute(vld2q_lane_f32::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmla_n_u32() { - let a: u32x2 = u32x2::new(0, 1); - let b: u32x2 = u32x2::new(2, 2); - let c: u32 = 3; - let e: u32x2 = u32x2::new(6, 7); - let r: u32x2 = transmute(vmla_n_u32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_s8() { + let a: [i8; 25] = [0, 1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8, 2, 13, 13, 4, 14, 14, 7, 15, 15, 8, 16, 16]; + let e: [i8x8; 3] = [i8x8::new(1, 2, 2, 4, 2, 4, 7, 8), i8x8::new(2, 4, 7, 8, 13, 14, 15, 16), i8x8::new(2, 4, 7, 8, 13, 14, 15, 16)]; + let r: [i8x8; 3] = transmute(vld3_s8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlaq_n_u32() { - let a: u32x4 = u32x4::new(0, 1, 2, 3); - let b: u32x4 = u32x4::new(2, 2, 2, 2); - let c: u32 = 3; - let e: u32x4 = u32x4::new(6, 7, 8, 9); - let r: u32x4 = transmute(vmlaq_n_u32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_s16() { + let a: [i16; 13] = [0, 1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8]; + let e: [i16x4; 3] = [i16x4::new(1, 2, 2, 4), i16x4::new(2, 4, 7, 8), i16x4::new(2, 4, 7, 8)]; + let r: [i16x4; 3] = transmute(vld3_s16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmla_n_f32() { - let a: f32x2 = f32x2::new(0., 1.); - let b: f32x2 = f32x2::new(2., 2.); - let c: f32 = 3.; - let e: f32x2 = f32x2::new(6., 7.); - let r: f32x2 = transmute(vmla_n_f32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_s32() { + let a: [i32; 7] = [0, 1, 2, 2, 2, 4, 4]; + let e: [i32x2; 3] = [i32x2::new(1, 2), i32x2::new(2, 4), i32x2::new(2, 4)]; + let r: [i32x2; 3] = transmute(vld3_s32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlaq_n_f32() { - let a: f32x4 = f32x4::new(0., 1., 2., 3.); - let b: f32x4 = f32x4::new(2., 2., 2., 2.); - let c: f32 = 3.; - let e: f32x4 = f32x4::new(6., 7., 8., 9.); - let r: f32x4 = transmute(vmlaq_n_f32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3q_s8() { + let a: [i8; 49] = [0, 1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8, 2, 13, 13, 4, 14, 14, 7, 15, 15, 8, 16, 16, 2, 25, 41, 4, 26, 42, 7, 27, 43, 8, 28, 44, 13, 29, 45, 14, 30, 46, 15, 31, 47, 16, 32, 48]; + let e: [i8x16; 3] = [i8x16::new(1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16), i8x16::new(2, 4, 7, 8, 13, 14, 15, 16, 25, 26, 27, 28, 29, 30, 31, 32), i8x16::new(2, 4, 7, 8, 13, 14, 15, 16, 41, 42, 43, 44, 45, 46, 47, 48)]; + let r: [i8x16; 3] = transmute(vld3q_s8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmla_lane_s16() { - let a: i16x4 = i16x4::new(0, 1, 2, 3); - let b: i16x4 = i16x4::new(2, 2, 2, 2); - let c: i16x4 = i16x4::new(0, 3, 0, 0); - let e: i16x4 = i16x4::new(6, 7, 8, 9); - let r: i16x4 = transmute(vmla_lane_s16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3q_s16() { + let a: [i16; 25] = [0, 1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8, 2, 13, 13, 4, 14, 14, 7, 15, 15, 8, 16, 16]; + let e: [i16x8; 3] = [i16x8::new(1, 2, 2, 4, 2, 4, 7, 8), i16x8::new(2, 4, 7, 8, 13, 14, 15, 16), i16x8::new(2, 4, 7, 8, 13, 14, 15, 16)]; + let r: [i16x8; 3] = transmute(vld3q_s16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmla_laneq_s16() { - let a: i16x4 = i16x4::new(0, 1, 2, 3); - let b: i16x4 = i16x4::new(2, 2, 2, 2); - let c: i16x8 = i16x8::new(0, 3, 0, 0, 0, 0, 0, 0); - let e: i16x4 = i16x4::new(6, 7, 8, 9); - let r: i16x4 = transmute(vmla_laneq_s16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3q_s32() { + let a: [i32; 13] = [0, 1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8]; + let e: [i32x4; 3] = [i32x4::new(1, 2, 2, 4), i32x4::new(2, 4, 7, 8), i32x4::new(2, 4, 7, 8)]; + let r: [i32x4; 3] = transmute(vld3q_s32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlaq_lane_s16() { - let a: i16x8 = i16x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let b: i16x8 = i16x8::new(2, 2, 2, 2, 2, 2, 2, 2); - let c: i16x4 = i16x4::new(0, 3, 0, 0); - let e: i16x8 = i16x8::new(6, 7, 8, 9, 10, 11, 12, 13); - let r: i16x8 = transmute(vmlaq_lane_s16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_s64() { + let a: [i64; 4] = [0, 1, 2, 2]; + let e: [i64x1; 3] = [i64x1::new(1), i64x1::new(2), i64x1::new(2)]; + let r: [i64x1; 3] = transmute(vld3_s64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlaq_laneq_s16() { - let a: i16x8 = i16x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let b: i16x8 = i16x8::new(2, 2, 2, 2, 2, 2, 2, 2); - let c: i16x8 = i16x8::new(0, 3, 0, 0, 0, 0, 0, 0); - let e: i16x8 = i16x8::new(6, 7, 8, 9, 10, 11, 12, 13); - let r: i16x8 = transmute(vmlaq_laneq_s16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_u8() { + let a: [u8; 25] = [0, 1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8, 2, 13, 13, 4, 14, 14, 7, 15, 15, 8, 16, 16]; + let e: [u8x8; 3] = [u8x8::new(1, 2, 2, 4, 2, 4, 7, 8), u8x8::new(2, 4, 7, 8, 13, 14, 15, 16), u8x8::new(2, 4, 7, 8, 13, 14, 15, 16)]; + let r: [u8x8; 3] = transmute(vld3_u8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmla_lane_s32() { - let a: i32x2 = i32x2::new(0, 1); - let b: i32x2 = i32x2::new(2, 2); - let c: i32x2 = i32x2::new(0, 3); - let e: i32x2 = i32x2::new(6, 7); - let r: i32x2 = transmute(vmla_lane_s32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_u16() { + let a: [u16; 13] = [0, 1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8]; + let e: [u16x4; 3] = [u16x4::new(1, 2, 2, 4), u16x4::new(2, 4, 7, 8), u16x4::new(2, 4, 7, 8)]; + let r: [u16x4; 3] = transmute(vld3_u16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmla_laneq_s32() { - let a: i32x2 = i32x2::new(0, 1); - let b: i32x2 = i32x2::new(2, 2); - let c: i32x4 = i32x4::new(0, 3, 0, 0); - let e: i32x2 = i32x2::new(6, 7); - let r: i32x2 = transmute(vmla_laneq_s32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_u32() { + let a: [u32; 7] = [0, 1, 2, 2, 2, 4, 4]; + let e: [u32x2; 3] = [u32x2::new(1, 2), u32x2::new(2, 4), u32x2::new(2, 4)]; + let r: [u32x2; 3] = transmute(vld3_u32(a[1..].as_ptr())); assert_eq!(r, e); } - #[simd_test(enable = "neon")] - unsafe fn test_vmlaq_lane_s32() { - let a: i32x4 = i32x4::new(0, 1, 2, 3); - let b: i32x4 = i32x4::new(2, 2, 2, 2); - let c: i32x2 = i32x2::new(0, 3); - let e: i32x4 = i32x4::new(6, 7, 8, 9); - let r: i32x4 = transmute(vmlaq_lane_s32::<1>(transmute(a), transmute(b), transmute(c))); + #[simd_test(enable = "neon")] + unsafe fn test_vld3q_u8() { + let a: [u8; 49] = [0, 1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8, 2, 13, 13, 4, 14, 14, 7, 15, 15, 8, 16, 16, 2, 25, 41, 4, 26, 42, 7, 27, 43, 8, 28, 44, 13, 29, 45, 14, 30, 46, 15, 31, 47, 16, 32, 48]; + let e: [u8x16; 3] = [u8x16::new(1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16), u8x16::new(2, 4, 7, 8, 13, 14, 15, 16, 25, 26, 27, 28, 29, 30, 31, 32), u8x16::new(2, 4, 7, 8, 13, 14, 15, 16, 41, 42, 43, 44, 45, 46, 47, 48)]; + let r: [u8x16; 3] = transmute(vld3q_u8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlaq_laneq_s32() { - let a: i32x4 = i32x4::new(0, 1, 2, 3); - let b: i32x4 = i32x4::new(2, 2, 2, 2); - let c: i32x4 = i32x4::new(0, 3, 0, 0); - let e: i32x4 = i32x4::new(6, 7, 8, 9); - let r: i32x4 = transmute(vmlaq_laneq_s32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3q_u16() { + let a: [u16; 25] = [0, 1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8, 2, 13, 13, 4, 14, 14, 7, 15, 15, 8, 16, 16]; + let e: [u16x8; 3] = [u16x8::new(1, 2, 2, 4, 2, 4, 7, 8), u16x8::new(2, 4, 7, 8, 13, 14, 15, 16), u16x8::new(2, 4, 7, 8, 13, 14, 15, 16)]; + let r: [u16x8; 3] = transmute(vld3q_u16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmla_lane_u16() { - let a: u16x4 = u16x4::new(0, 1, 2, 3); - let b: u16x4 = u16x4::new(2, 2, 2, 2); - let c: u16x4 = u16x4::new(0, 3, 0, 0); - let e: u16x4 = u16x4::new(6, 7, 8, 9); - let r: u16x4 = transmute(vmla_lane_u16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3q_u32() { + let a: [u32; 13] = [0, 1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8]; + let e: [u32x4; 3] = [u32x4::new(1, 2, 2, 4), u32x4::new(2, 4, 7, 8), u32x4::new(2, 4, 7, 8)]; + let r: [u32x4; 3] = transmute(vld3q_u32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmla_laneq_u16() { - let a: u16x4 = u16x4::new(0, 1, 2, 3); - let b: u16x4 = u16x4::new(2, 2, 2, 2); - let c: u16x8 = u16x8::new(0, 3, 0, 0, 0, 0, 0, 0); - let e: u16x4 = u16x4::new(6, 7, 8, 9); - let r: u16x4 = transmute(vmla_laneq_u16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_p8() { + let a: [u8; 25] = [0, 1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8, 2, 13, 13, 4, 14, 14, 7, 15, 15, 8, 16, 16]; + let e: [i8x8; 3] = [i8x8::new(1, 2, 2, 4, 2, 4, 7, 8), i8x8::new(2, 4, 7, 8, 13, 14, 15, 16), i8x8::new(2, 4, 7, 8, 13, 14, 15, 16)]; + let r: [i8x8; 3] = transmute(vld3_p8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlaq_lane_u16() { - let a: u16x8 = u16x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let b: u16x8 = u16x8::new(2, 2, 2, 2, 2, 2, 2, 2); - let c: u16x4 = u16x4::new(0, 3, 0, 0); - let e: u16x8 = u16x8::new(6, 7, 8, 9, 10, 11, 12, 13); - let r: u16x8 = transmute(vmlaq_lane_u16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_p16() { + let a: [u16; 13] = [0, 1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8]; + let e: [i16x4; 3] = [i16x4::new(1, 2, 2, 4), i16x4::new(2, 4, 7, 8), i16x4::new(2, 4, 7, 8)]; + let r: [i16x4; 3] = transmute(vld3_p16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlaq_laneq_u16() { - let a: u16x8 = u16x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let b: u16x8 = u16x8::new(2, 2, 2, 2, 2, 2, 2, 2); - let c: u16x8 = u16x8::new(0, 3, 0, 0, 0, 0, 0, 0); - let e: u16x8 = u16x8::new(6, 7, 8, 9, 10, 11, 12, 13); - let r: u16x8 = transmute(vmlaq_laneq_u16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3q_p8() { + let a: [u8; 49] = [0, 1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8, 2, 13, 13, 4, 14, 14, 7, 15, 15, 8, 16, 16, 2, 25, 41, 4, 26, 42, 7, 27, 43, 8, 28, 44, 13, 29, 45, 14, 30, 46, 15, 31, 47, 16, 32, 48]; + let e: [i8x16; 3] = [i8x16::new(1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16), i8x16::new(2, 4, 7, 8, 13, 14, 15, 16, 25, 26, 27, 28, 29, 30, 31, 32), i8x16::new(2, 4, 7, 8, 13, 14, 15, 16, 41, 42, 43, 44, 45, 46, 47, 48)]; + let r: [i8x16; 3] = transmute(vld3q_p8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmla_lane_u32() { - let a: u32x2 = u32x2::new(0, 1); - let b: u32x2 = u32x2::new(2, 2); - let c: u32x2 = u32x2::new(0, 3); - let e: u32x2 = u32x2::new(6, 7); - let r: u32x2 = transmute(vmla_lane_u32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3q_p16() { + let a: [u16; 25] = [0, 1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8, 2, 13, 13, 4, 14, 14, 7, 15, 15, 8, 16, 16]; + let e: [i16x8; 3] = [i16x8::new(1, 2, 2, 4, 2, 4, 7, 8), i16x8::new(2, 4, 7, 8, 13, 14, 15, 16), i16x8::new(2, 4, 7, 8, 13, 14, 15, 16)]; + let r: [i16x8; 3] = transmute(vld3q_p16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmla_laneq_u32() { - let a: u32x2 = u32x2::new(0, 1); - let b: u32x2 = u32x2::new(2, 2); - let c: u32x4 = u32x4::new(0, 3, 0, 0); - let e: u32x2 = u32x2::new(6, 7); - let r: u32x2 = transmute(vmla_laneq_u32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_u64() { + let a: [u64; 4] = [0, 1, 2, 2]; + let e: [u64x1; 3] = [u64x1::new(1), u64x1::new(2), u64x1::new(2)]; + let r: [u64x1; 3] = transmute(vld3_u64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlaq_lane_u32() { - let a: u32x4 = u32x4::new(0, 1, 2, 3); - let b: u32x4 = u32x4::new(2, 2, 2, 2); - let c: u32x2 = u32x2::new(0, 3); - let e: u32x4 = u32x4::new(6, 7, 8, 9); - let r: u32x4 = transmute(vmlaq_lane_u32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_p64() { + let a: [u64; 4] = [0, 1, 2, 2]; + let e: [i64x1; 3] = [i64x1::new(1), i64x1::new(2), i64x1::new(2)]; + let r: [i64x1; 3] = transmute(vld3_p64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlaq_laneq_u32() { - let a: u32x4 = u32x4::new(0, 1, 2, 3); - let b: u32x4 = u32x4::new(2, 2, 2, 2); - let c: u32x4 = u32x4::new(0, 3, 0, 0); - let e: u32x4 = u32x4::new(6, 7, 8, 9); - let r: u32x4 = transmute(vmlaq_laneq_u32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_f32() { + let a: [f32; 7] = [0., 1., 2., 2., 2., 4., 4.]; + let e: [f32x2; 3] = [f32x2::new(1., 2.), f32x2::new(2., 4.), f32x2::new(2., 4.)]; + let r: [f32x2; 3] = transmute(vld3_f32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmla_lane_f32() { - let a: f32x2 = f32x2::new(0., 1.); - let b: f32x2 = f32x2::new(2., 2.); - let c: f32x2 = f32x2::new(0., 3.); - let e: f32x2 = f32x2::new(6., 7.); - let r: f32x2 = transmute(vmla_lane_f32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3q_f32() { + let a: [f32; 13] = [0., 1., 2., 2., 2., 4., 4., 2., 7., 7., 4., 8., 8.]; + let e: [f32x4; 3] = [f32x4::new(1., 2., 2., 4.), f32x4::new(2., 4., 7., 8.), f32x4::new(2., 4., 7., 8.)]; + let r: [f32x4; 3] = transmute(vld3q_f32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmla_laneq_f32() { - let a: f32x2 = f32x2::new(0., 1.); - let b: f32x2 = f32x2::new(2., 2.); - let c: f32x4 = f32x4::new(0., 3., 0., 0.); - let e: f32x2 = f32x2::new(6., 7.); - let r: f32x2 = transmute(vmla_laneq_f32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_dup_s8() { + let a: [i8; 25] = [0, 1, 1, 1, 3, 1, 4, 3, 5, 1, 6, 3, 7, 4, 8, 5, 9, 2, 10, 3, 11, 4, 12, 5, 13]; + let e: [i8x8; 3] = [i8x8::new(1, 1, 1, 1, 1, 1, 1, 1), i8x8::new(1, 1, 1, 1, 1, 1, 1, 1), i8x8::new(1, 1, 1, 1, 1, 1, 1, 1)]; + let r: [i8x8; 3] = transmute(vld3_dup_s8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlaq_lane_f32() { - let a: f32x4 = f32x4::new(0., 1., 2., 3.); - let b: f32x4 = f32x4::new(2., 2., 2., 2.); - let c: f32x2 = f32x2::new(0., 3.); - let e: f32x4 = f32x4::new(6., 7., 8., 9.); - let r: f32x4 = transmute(vmlaq_lane_f32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_dup_s16() { + let a: [i16; 13] = [0, 1, 1, 1, 3, 1, 4, 3, 5, 1, 6, 3, 7]; + let e: [i16x4; 3] = [i16x4::new(1, 1, 1, 1), i16x4::new(1, 1, 1, 1), i16x4::new(1, 1, 1, 1)]; + let r: [i16x4; 3] = transmute(vld3_dup_s16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlaq_laneq_f32() { - let a: f32x4 = f32x4::new(0., 1., 2., 3.); - let b: f32x4 = f32x4::new(2., 2., 2., 2.); - let c: f32x4 = f32x4::new(0., 3., 0., 0.); - let e: f32x4 = f32x4::new(6., 7., 8., 9.); - let r: f32x4 = transmute(vmlaq_laneq_f32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_dup_s32() { + let a: [i32; 7] = [0, 1, 1, 1, 3, 1, 4]; + let e: [i32x2; 3] = [i32x2::new(1, 1), i32x2::new(1, 1), i32x2::new(1, 1)]; + let r: [i32x2; 3] = transmute(vld3_dup_s32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_s8() { - let a: i16x8 = i16x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let b: i8x8 = i8x8::new(2, 2, 2, 2, 2, 2, 2, 2); - let c: i8x8 = i8x8::new(3, 3, 3, 3, 3, 3, 3, 3); - let e: i16x8 = i16x8::new(6, 7, 8, 9, 10, 11, 12, 13); - let r: i16x8 = transmute(vmlal_s8(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3q_dup_s8() { + let a: [i8; 49] = [0, 1, 1, 1, 3, 1, 4, 3, 5, 1, 6, 3, 7, 4, 8, 5, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15, 8, 16, 9, 17, 6, 14, 7, 15, 8, 16, 9, 17, 6, 14, 7, 15, 8, 16, 9, 17]; + let e: [i8x16; 3] = [i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)]; + let r: [i8x16; 3] = transmute(vld3q_dup_s8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_s16() { - let a: i32x4 = i32x4::new(0, 1, 2, 3); - let b: i16x4 = i16x4::new(2, 2, 2, 2); - let c: i16x4 = i16x4::new(3, 3, 3, 3); - let e: i32x4 = i32x4::new(6, 7, 8, 9); - let r: i32x4 = transmute(vmlal_s16(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3q_dup_s16() { + let a: [i16; 25] = [0, 1, 1, 1, 3, 1, 4, 3, 5, 1, 6, 3, 7, 4, 8, 5, 9, 2, 10, 3, 11, 4, 12, 5, 13]; + let e: [i16x8; 3] = [i16x8::new(1, 1, 1, 1, 1, 1, 1, 1), i16x8::new(1, 1, 1, 1, 1, 1, 1, 1), i16x8::new(1, 1, 1, 1, 1, 1, 1, 1)]; + let r: [i16x8; 3] = transmute(vld3q_dup_s16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_s32() { - let a: i64x2 = i64x2::new(0, 1); - let b: i32x2 = i32x2::new(2, 2); - let c: i32x2 = i32x2::new(3, 3); - let e: i64x2 = i64x2::new(6, 7); - let r: i64x2 = transmute(vmlal_s32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3q_dup_s32() { + let a: [i32; 13] = [0, 1, 1, 1, 3, 1, 4, 3, 5, 1, 6, 3, 7]; + let e: [i32x4; 3] = [i32x4::new(1, 1, 1, 1), i32x4::new(1, 1, 1, 1), i32x4::new(1, 1, 1, 1)]; + let r: [i32x4; 3] = transmute(vld3q_dup_s32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_u8() { - let a: u16x8 = u16x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let b: u8x8 = u8x8::new(2, 2, 2, 2, 2, 2, 2, 2); - let c: u8x8 = u8x8::new(3, 3, 3, 3, 3, 3, 3, 3); - let e: u16x8 = u16x8::new(6, 7, 8, 9, 10, 11, 12, 13); - let r: u16x8 = transmute(vmlal_u8(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_dup_s64() { + let a: [i64; 4] = [0, 1, 1, 1]; + let e: [i64x1; 3] = [i64x1::new(1), i64x1::new(1), i64x1::new(1)]; + let r: [i64x1; 3] = transmute(vld3_dup_s64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_u16() { - let a: u32x4 = u32x4::new(0, 1, 2, 3); - let b: u16x4 = u16x4::new(2, 2, 2, 2); - let c: u16x4 = u16x4::new(3, 3, 3, 3); - let e: u32x4 = u32x4::new(6, 7, 8, 9); - let r: u32x4 = transmute(vmlal_u16(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_dup_u8() { + let a: [u8; 25] = [0, 1, 1, 1, 3, 1, 4, 3, 5, 1, 6, 3, 7, 4, 8, 5, 9, 2, 10, 3, 11, 4, 12, 5, 13]; + let e: [u8x8; 3] = [u8x8::new(1, 1, 1, 1, 1, 1, 1, 1), u8x8::new(1, 1, 1, 1, 1, 1, 1, 1), u8x8::new(1, 1, 1, 1, 1, 1, 1, 1)]; + let r: [u8x8; 3] = transmute(vld3_dup_u8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_u32() { - let a: u64x2 = u64x2::new(0, 1); - let b: u32x2 = u32x2::new(2, 2); - let c: u32x2 = u32x2::new(3, 3); - let e: u64x2 = u64x2::new(6, 7); - let r: u64x2 = transmute(vmlal_u32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_dup_u16() { + let a: [u16; 13] = [0, 1, 1, 1, 3, 1, 4, 3, 5, 1, 6, 3, 7]; + let e: [u16x4; 3] = [u16x4::new(1, 1, 1, 1), u16x4::new(1, 1, 1, 1), u16x4::new(1, 1, 1, 1)]; + let r: [u16x4; 3] = transmute(vld3_dup_u16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_n_s16() { - let a: i32x4 = i32x4::new(0, 1, 2, 3); - let b: i16x4 = i16x4::new(2, 2, 2, 2); - let c: i16 = 3; - let e: i32x4 = i32x4::new(6, 7, 8, 9); - let r: i32x4 = transmute(vmlal_n_s16(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_dup_u32() { + let a: [u32; 7] = [0, 1, 1, 1, 3, 1, 4]; + let e: [u32x2; 3] = [u32x2::new(1, 1), u32x2::new(1, 1), u32x2::new(1, 1)]; + let r: [u32x2; 3] = transmute(vld3_dup_u32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_n_s32() { - let a: i64x2 = i64x2::new(0, 1); - let b: i32x2 = i32x2::new(2, 2); - let c: i32 = 3; - let e: i64x2 = i64x2::new(6, 7); - let r: i64x2 = transmute(vmlal_n_s32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3q_dup_u8() { + let a: [u8; 49] = [0, 1, 1, 1, 3, 1, 4, 3, 5, 1, 6, 3, 7, 4, 8, 5, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15, 8, 16, 9, 17, 6, 14, 7, 15, 8, 16, 9, 17, 6, 14, 7, 15, 8, 16, 9, 17]; + let e: [u8x16; 3] = [u8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), u8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), u8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)]; + let r: [u8x16; 3] = transmute(vld3q_dup_u8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_n_u16() { - let a: u32x4 = u32x4::new(0, 1, 2, 3); - let b: u16x4 = u16x4::new(2, 2, 2, 2); - let c: u16 = 3; - let e: u32x4 = u32x4::new(6, 7, 8, 9); - let r: u32x4 = transmute(vmlal_n_u16(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3q_dup_u16() { + let a: [u16; 25] = [0, 1, 1, 1, 3, 1, 4, 3, 5, 1, 6, 3, 7, 4, 8, 5, 9, 2, 10, 3, 11, 4, 12, 5, 13]; + let e: [u16x8; 3] = [u16x8::new(1, 1, 1, 1, 1, 1, 1, 1), u16x8::new(1, 1, 1, 1, 1, 1, 1, 1), u16x8::new(1, 1, 1, 1, 1, 1, 1, 1)]; + let r: [u16x8; 3] = transmute(vld3q_dup_u16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_n_u32() { - let a: u64x2 = u64x2::new(0, 1); - let b: u32x2 = u32x2::new(2, 2); - let c: u32 = 3; - let e: u64x2 = u64x2::new(6, 7); - let r: u64x2 = transmute(vmlal_n_u32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3q_dup_u32() { + let a: [u32; 13] = [0, 1, 1, 1, 3, 1, 4, 3, 5, 1, 6, 3, 7]; + let e: [u32x4; 3] = [u32x4::new(1, 1, 1, 1), u32x4::new(1, 1, 1, 1), u32x4::new(1, 1, 1, 1)]; + let r: [u32x4; 3] = transmute(vld3q_dup_u32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_lane_s16() { - let a: i32x4 = i32x4::new(0, 1, 2, 3); - let b: i16x4 = i16x4::new(2, 2, 2, 2); - let c: i16x4 = i16x4::new(0, 3, 0, 0); - let e: i32x4 = i32x4::new(6, 7, 8, 9); - let r: i32x4 = transmute(vmlal_lane_s16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_dup_p8() { + let a: [u8; 25] = [0, 1, 1, 1, 3, 1, 4, 3, 5, 1, 6, 3, 7, 4, 8, 5, 9, 2, 10, 3, 11, 4, 12, 5, 13]; + let e: [i8x8; 3] = [i8x8::new(1, 1, 1, 1, 1, 1, 1, 1), i8x8::new(1, 1, 1, 1, 1, 1, 1, 1), i8x8::new(1, 1, 1, 1, 1, 1, 1, 1)]; + let r: [i8x8; 3] = transmute(vld3_dup_p8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_laneq_s16() { - let a: i32x4 = i32x4::new(0, 1, 2, 3); - let b: i16x4 = i16x4::new(2, 2, 2, 2); - let c: i16x8 = i16x8::new(0, 3, 0, 0, 0, 0, 0, 0); - let e: i32x4 = i32x4::new(6, 7, 8, 9); - let r: i32x4 = transmute(vmlal_laneq_s16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_dup_p16() { + let a: [u16; 13] = [0, 1, 1, 1, 3, 1, 4, 3, 5, 1, 6, 3, 7]; + let e: [i16x4; 3] = [i16x4::new(1, 1, 1, 1), i16x4::new(1, 1, 1, 1), i16x4::new(1, 1, 1, 1)]; + let r: [i16x4; 3] = transmute(vld3_dup_p16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_lane_s32() { - let a: i64x2 = i64x2::new(0, 1); - let b: i32x2 = i32x2::new(2, 2); - let c: i32x2 = i32x2::new(0, 3); - let e: i64x2 = i64x2::new(6, 7); - let r: i64x2 = transmute(vmlal_lane_s32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3q_dup_p8() { + let a: [u8; 49] = [0, 1, 1, 1, 3, 1, 4, 3, 5, 1, 6, 3, 7, 4, 8, 5, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15, 8, 16, 9, 17, 6, 14, 7, 15, 8, 16, 9, 17, 6, 14, 7, 15, 8, 16, 9, 17]; + let e: [i8x16; 3] = [i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)]; + let r: [i8x16; 3] = transmute(vld3q_dup_p8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_laneq_s32() { - let a: i64x2 = i64x2::new(0, 1); - let b: i32x2 = i32x2::new(2, 2); - let c: i32x4 = i32x4::new(0, 3, 0, 0); - let e: i64x2 = i64x2::new(6, 7); - let r: i64x2 = transmute(vmlal_laneq_s32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3q_dup_p16() { + let a: [u16; 25] = [0, 1, 1, 1, 3, 1, 4, 3, 5, 1, 6, 3, 7, 4, 8, 5, 9, 2, 10, 3, 11, 4, 12, 5, 13]; + let e: [i16x8; 3] = [i16x8::new(1, 1, 1, 1, 1, 1, 1, 1), i16x8::new(1, 1, 1, 1, 1, 1, 1, 1), i16x8::new(1, 1, 1, 1, 1, 1, 1, 1)]; + let r: [i16x8; 3] = transmute(vld3q_dup_p16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_lane_u16() { - let a: u32x4 = u32x4::new(0, 1, 2, 3); - let b: u16x4 = u16x4::new(2, 2, 2, 2); - let c: u16x4 = u16x4::new(0, 3, 0, 0); - let e: u32x4 = u32x4::new(6, 7, 8, 9); - let r: u32x4 = transmute(vmlal_lane_u16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_dup_u64() { + let a: [u64; 4] = [0, 1, 1, 1]; + let e: [u64x1; 3] = [u64x1::new(1), u64x1::new(1), u64x1::new(1)]; + let r: [u64x1; 3] = transmute(vld3_dup_u64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_laneq_u16() { - let a: u32x4 = u32x4::new(0, 1, 2, 3); - let b: u16x4 = u16x4::new(2, 2, 2, 2); - let c: u16x8 = u16x8::new(0, 3, 0, 0, 0, 0, 0, 0); - let e: u32x4 = u32x4::new(6, 7, 8, 9); - let r: u32x4 = transmute(vmlal_laneq_u16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_dup_p64() { + let a: [u64; 4] = [0, 1, 1, 1]; + let e: [i64x1; 3] = [i64x1::new(1), i64x1::new(1), i64x1::new(1)]; + let r: [i64x1; 3] = transmute(vld3_dup_p64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_lane_u32() { - let a: u64x2 = u64x2::new(0, 1); - let b: u32x2 = u32x2::new(2, 2); - let c: u32x2 = u32x2::new(0, 3); - let e: u64x2 = u64x2::new(6, 7); - let r: u64x2 = transmute(vmlal_lane_u32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_dup_f32() { + let a: [f32; 7] = [0., 1., 1., 1., 3., 1., 4.]; + let e: [f32x2; 3] = [f32x2::new(1., 1.), f32x2::new(1., 1.), f32x2::new(1., 1.)]; + let r: [f32x2; 3] = transmute(vld3_dup_f32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlal_laneq_u32() { - let a: u64x2 = u64x2::new(0, 1); - let b: u32x2 = u32x2::new(2, 2); - let c: u32x4 = u32x4::new(0, 3, 0, 0); - let e: u64x2 = u64x2::new(6, 7); - let r: u64x2 = transmute(vmlal_laneq_u32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3q_dup_f32() { + let a: [f32; 13] = [0., 1., 1., 1., 3., 1., 4., 3., 5., 1., 4., 3., 5.]; + let e: [f32x4; 3] = [f32x4::new(1., 1., 1., 1.), f32x4::new(1., 1., 1., 1.), f32x4::new(1., 1., 1., 1.)]; + let r: [f32x4; 3] = transmute(vld3q_dup_f32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmls_s8() { - let a: i8x8 = i8x8::new(6, 7, 8, 9, 10, 11, 12, 13); - let b: i8x8 = i8x8::new(2, 2, 2, 2, 2, 2, 2, 2); - let c: i8x8 = i8x8::new(3, 3, 3, 3, 3, 3, 3, 3); - let e: i8x8 = i8x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let r: i8x8 = transmute(vmls_s8(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_lane_s8() { + let a: [i8; 25] = [0, 1, 2, 2, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [i8x8; 3] = [i8x8::new(0, 2, 2, 14, 2, 16, 17, 18), i8x8::new(2, 20, 21, 22, 23, 24, 25, 26), i8x8::new(11, 12, 13, 14, 15, 16, 17, 18)]; + let e: [i8x8; 3] = [i8x8::new(1, 2, 2, 14, 2, 16, 17, 18), i8x8::new(2, 20, 21, 22, 23, 24, 25, 26), i8x8::new(2, 12, 13, 14, 15, 16, 17, 18)]; + let r: [i8x8; 3] = transmute(vld3_lane_s8::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsq_s8() { - let a: i8x16 = i8x16::new(6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21); - let b: i8x16 = i8x16::new(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); - let c: i8x16 = i8x16::new(3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3); - let e: i8x16 = i8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - let r: i8x16 = transmute(vmlsq_s8(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_lane_s16() { + let a: [i16; 13] = [0, 1, 2, 2, 4, 5, 6, 7, 8, 1, 2, 3, 4]; + let b: [i16x4; 3] = [i16x4::new(0, 2, 2, 14), i16x4::new(2, 16, 17, 18), i16x4::new(2, 20, 21, 22)]; + let e: [i16x4; 3] = [i16x4::new(1, 2, 2, 14), i16x4::new(2, 16, 17, 18), i16x4::new(2, 20, 21, 22)]; + let r: [i16x4; 3] = transmute(vld3_lane_s16::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmls_s16() { - let a: i16x4 = i16x4::new(6, 7, 8, 9); - let b: i16x4 = i16x4::new(2, 2, 2, 2); - let c: i16x4 = i16x4::new(3, 3, 3, 3); - let e: i16x4 = i16x4::new(0, 1, 2, 3); - let r: i16x4 = transmute(vmls_s16(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_lane_s32() { + let a: [i32; 7] = [0, 1, 2, 2, 4, 5, 6]; + let b: [i32x2; 3] = [i32x2::new(0, 2), i32x2::new(2, 14), i32x2::new(2, 16)]; + let e: [i32x2; 3] = [i32x2::new(1, 2), i32x2::new(2, 14), i32x2::new(2, 16)]; + let r: [i32x2; 3] = transmute(vld3_lane_s32::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsq_s16() { - let a: i16x8 = i16x8::new(6, 7, 8, 9, 10, 11, 12, 13); - let b: i16x8 = i16x8::new(2, 2, 2, 2, 2, 2, 2, 2); - let c: i16x8 = i16x8::new(3, 3, 3, 3, 3, 3, 3, 3); - let e: i16x8 = i16x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let r: i16x8 = transmute(vmlsq_s16(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3q_lane_s16() { + let a: [i16; 25] = [0, 1, 2, 2, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [i16x8; 3] = [i16x8::new(0, 2, 2, 14, 2, 16, 17, 18), i16x8::new(2, 20, 21, 22, 23, 24, 25, 26), i16x8::new(11, 12, 13, 14, 15, 16, 17, 18)]; + let e: [i16x8; 3] = [i16x8::new(1, 2, 2, 14, 2, 16, 17, 18), i16x8::new(2, 20, 21, 22, 23, 24, 25, 26), i16x8::new(2, 12, 13, 14, 15, 16, 17, 18)]; + let r: [i16x8; 3] = transmute(vld3q_lane_s16::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmls_s32() { - let a: i32x2 = i32x2::new(6, 7); - let b: i32x2 = i32x2::new(2, 2); - let c: i32x2 = i32x2::new(3, 3); - let e: i32x2 = i32x2::new(0, 1); - let r: i32x2 = transmute(vmls_s32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3q_lane_s32() { + let a: [i32; 13] = [0, 1, 2, 2, 4, 5, 6, 7, 8, 1, 2, 3, 4]; + let b: [i32x4; 3] = [i32x4::new(0, 2, 2, 14), i32x4::new(2, 16, 17, 18), i32x4::new(2, 20, 21, 22)]; + let e: [i32x4; 3] = [i32x4::new(1, 2, 2, 14), i32x4::new(2, 16, 17, 18), i32x4::new(2, 20, 21, 22)]; + let r: [i32x4; 3] = transmute(vld3q_lane_s32::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsq_s32() { - let a: i32x4 = i32x4::new(6, 7, 8, 9); - let b: i32x4 = i32x4::new(2, 2, 2, 2); - let c: i32x4 = i32x4::new(3, 3, 3, 3); - let e: i32x4 = i32x4::new(0, 1, 2, 3); - let r: i32x4 = transmute(vmlsq_s32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_lane_u8() { + let a: [u8; 25] = [0, 1, 2, 2, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [u8x8; 3] = [u8x8::new(0, 2, 2, 14, 2, 16, 17, 18), u8x8::new(2, 20, 21, 22, 23, 24, 25, 26), u8x8::new(11, 12, 13, 14, 15, 16, 17, 18)]; + let e: [u8x8; 3] = [u8x8::new(1, 2, 2, 14, 2, 16, 17, 18), u8x8::new(2, 20, 21, 22, 23, 24, 25, 26), u8x8::new(2, 12, 13, 14, 15, 16, 17, 18)]; + let r: [u8x8; 3] = transmute(vld3_lane_u8::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmls_u8() { - let a: u8x8 = u8x8::new(6, 7, 8, 9, 10, 11, 12, 13); - let b: u8x8 = u8x8::new(2, 2, 2, 2, 2, 2, 2, 2); - let c: u8x8 = u8x8::new(3, 3, 3, 3, 3, 3, 3, 3); - let e: u8x8 = u8x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let r: u8x8 = transmute(vmls_u8(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_lane_u16() { + let a: [u16; 13] = [0, 1, 2, 2, 4, 5, 6, 7, 8, 1, 2, 3, 4]; + let b: [u16x4; 3] = [u16x4::new(0, 2, 2, 14), u16x4::new(2, 16, 17, 18), u16x4::new(2, 20, 21, 22)]; + let e: [u16x4; 3] = [u16x4::new(1, 2, 2, 14), u16x4::new(2, 16, 17, 18), u16x4::new(2, 20, 21, 22)]; + let r: [u16x4; 3] = transmute(vld3_lane_u16::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsq_u8() { - let a: u8x16 = u8x16::new(6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21); - let b: u8x16 = u8x16::new(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); - let c: u8x16 = u8x16::new(3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3); - let e: u8x16 = u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - let r: u8x16 = transmute(vmlsq_u8(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_lane_u32() { + let a: [u32; 7] = [0, 1, 2, 2, 4, 5, 6]; + let b: [u32x2; 3] = [u32x2::new(0, 2), u32x2::new(2, 14), u32x2::new(2, 16)]; + let e: [u32x2; 3] = [u32x2::new(1, 2), u32x2::new(2, 14), u32x2::new(2, 16)]; + let r: [u32x2; 3] = transmute(vld3_lane_u32::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmls_u16() { - let a: u16x4 = u16x4::new(6, 7, 8, 9); - let b: u16x4 = u16x4::new(2, 2, 2, 2); - let c: u16x4 = u16x4::new(3, 3, 3, 3); - let e: u16x4 = u16x4::new(0, 1, 2, 3); - let r: u16x4 = transmute(vmls_u16(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3q_lane_u16() { + let a: [u16; 25] = [0, 1, 2, 2, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [u16x8; 3] = [u16x8::new(0, 2, 2, 14, 2, 16, 17, 18), u16x8::new(2, 20, 21, 22, 23, 24, 25, 26), u16x8::new(11, 12, 13, 14, 15, 16, 17, 18)]; + let e: [u16x8; 3] = [u16x8::new(1, 2, 2, 14, 2, 16, 17, 18), u16x8::new(2, 20, 21, 22, 23, 24, 25, 26), u16x8::new(2, 12, 13, 14, 15, 16, 17, 18)]; + let r: [u16x8; 3] = transmute(vld3q_lane_u16::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsq_u16() { - let a: u16x8 = u16x8::new(6, 7, 8, 9, 10, 11, 12, 13); - let b: u16x8 = u16x8::new(2, 2, 2, 2, 2, 2, 2, 2); - let c: u16x8 = u16x8::new(3, 3, 3, 3, 3, 3, 3, 3); - let e: u16x8 = u16x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let r: u16x8 = transmute(vmlsq_u16(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3q_lane_u32() { + let a: [u32; 13] = [0, 1, 2, 2, 4, 5, 6, 7, 8, 1, 2, 3, 4]; + let b: [u32x4; 3] = [u32x4::new(0, 2, 2, 14), u32x4::new(2, 16, 17, 18), u32x4::new(2, 20, 21, 22)]; + let e: [u32x4; 3] = [u32x4::new(1, 2, 2, 14), u32x4::new(2, 16, 17, 18), u32x4::new(2, 20, 21, 22)]; + let r: [u32x4; 3] = transmute(vld3q_lane_u32::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmls_u32() { - let a: u32x2 = u32x2::new(6, 7); - let b: u32x2 = u32x2::new(2, 2); - let c: u32x2 = u32x2::new(3, 3); - let e: u32x2 = u32x2::new(0, 1); - let r: u32x2 = transmute(vmls_u32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_lane_p8() { + let a: [u8; 25] = [0, 1, 2, 2, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [i8x8; 3] = [i8x8::new(0, 2, 2, 14, 2, 16, 17, 18), i8x8::new(2, 20, 21, 22, 23, 24, 25, 26), i8x8::new(11, 12, 13, 14, 15, 16, 17, 18)]; + let e: [i8x8; 3] = [i8x8::new(1, 2, 2, 14, 2, 16, 17, 18), i8x8::new(2, 20, 21, 22, 23, 24, 25, 26), i8x8::new(2, 12, 13, 14, 15, 16, 17, 18)]; + let r: [i8x8; 3] = transmute(vld3_lane_p8::<0>(a[1..].as_ptr(), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld3_lane_p16() { + let a: [u16; 13] = [0, 1, 2, 2, 4, 5, 6, 7, 8, 1, 2, 3, 4]; + let b: [i16x4; 3] = [i16x4::new(0, 2, 2, 14), i16x4::new(2, 16, 17, 18), i16x4::new(2, 20, 21, 22)]; + let e: [i16x4; 3] = [i16x4::new(1, 2, 2, 14), i16x4::new(2, 16, 17, 18), i16x4::new(2, 20, 21, 22)]; + let r: [i16x4; 3] = transmute(vld3_lane_p16::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsq_u32() { - let a: u32x4 = u32x4::new(6, 7, 8, 9); - let b: u32x4 = u32x4::new(2, 2, 2, 2); - let c: u32x4 = u32x4::new(3, 3, 3, 3); - let e: u32x4 = u32x4::new(0, 1, 2, 3); - let r: u32x4 = transmute(vmlsq_u32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3q_lane_p16() { + let a: [u16; 25] = [0, 1, 2, 2, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [i16x8; 3] = [i16x8::new(0, 2, 2, 14, 2, 16, 17, 18), i16x8::new(2, 20, 21, 22, 23, 24, 25, 26), i16x8::new(11, 12, 13, 14, 15, 16, 17, 18)]; + let e: [i16x8; 3] = [i16x8::new(1, 2, 2, 14, 2, 16, 17, 18), i16x8::new(2, 20, 21, 22, 23, 24, 25, 26), i16x8::new(2, 12, 13, 14, 15, 16, 17, 18)]; + let r: [i16x8; 3] = transmute(vld3q_lane_p16::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmls_f32() { - let a: f32x2 = f32x2::new(6., 7.); - let b: f32x2 = f32x2::new(2., 2.); - let c: f32x2 = f32x2::new(3., 3.); - let e: f32x2 = f32x2::new(0., 1.); - let r: f32x2 = transmute(vmls_f32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3_lane_f32() { + let a: [f32; 7] = [0., 1., 2., 2., 4., 5., 6.]; + let b: [f32x2; 3] = [f32x2::new(0., 2.), f32x2::new(2., 14.), f32x2::new(9., 16.)]; + let e: [f32x2; 3] = [f32x2::new(1., 2.), f32x2::new(2., 14.), f32x2::new(2., 16.)]; + let r: [f32x2; 3] = transmute(vld3_lane_f32::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsq_f32() { - let a: f32x4 = f32x4::new(6., 7., 8., 9.); - let b: f32x4 = f32x4::new(2., 2., 2., 2.); - let c: f32x4 = f32x4::new(3., 3., 3., 3.); - let e: f32x4 = f32x4::new(0., 1., 2., 3.); - let r: f32x4 = transmute(vmlsq_f32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld3q_lane_f32() { + let a: [f32; 13] = [0., 1., 2., 2., 4., 5., 6., 7., 8., 5., 6., 7., 8.]; + let b: [f32x4; 3] = [f32x4::new(0., 2., 2., 14.), f32x4::new(9., 16., 17., 18.), f32x4::new(5., 6., 7., 8.)]; + let e: [f32x4; 3] = [f32x4::new(1., 2., 2., 14.), f32x4::new(2., 16., 17., 18.), f32x4::new(2., 6., 7., 8.)]; + let r: [f32x4; 3] = transmute(vld3q_lane_f32::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmls_n_s16() { - let a: i16x4 = i16x4::new(6, 7, 8, 9); - let b: i16x4 = i16x4::new(2, 2, 2, 2); - let c: i16 = 3; - let e: i16x4 = i16x4::new(0, 1, 2, 3); - let r: i16x4 = transmute(vmls_n_s16(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4_s8() { + let a: [i8; 33] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; + let e: [i8x8; 4] = [i8x8::new(1, 2, 2, 6, 2, 6, 6, 8), i8x8::new(2, 6, 6, 8, 6, 8, 8, 16), i8x8::new(2, 6, 6, 8, 6, 8, 8, 16), i8x8::new(6, 8, 8, 16, 8, 16, 16, 32)]; + let r: [i8x8; 4] = transmute(vld4_s8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsq_n_s16() { - let a: i16x8 = i16x8::new(6, 7, 8, 9, 10, 11, 12, 13); - let b: i16x8 = i16x8::new(2, 2, 2, 2, 2, 2, 2, 2); - let c: i16 = 3; - let e: i16x8 = i16x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let r: i16x8 = transmute(vmlsq_n_s16(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4_s16() { + let a: [i16; 17] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; + let e: [i16x4; 4] = [i16x4::new(1, 2, 2, 6), i16x4::new(2, 6, 6, 8), i16x4::new(2, 6, 6, 8), i16x4::new(6, 8, 8, 16)]; + let r: [i16x4; 4] = transmute(vld4_s16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmls_n_s32() { - let a: i32x2 = i32x2::new(6, 7); - let b: i32x2 = i32x2::new(2, 2); - let c: i32 = 3; - let e: i32x2 = i32x2::new(0, 1); - let r: i32x2 = transmute(vmls_n_s32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4_s32() { + let a: [i32; 9] = [0, 1, 2, 2, 6, 2, 6, 6, 8]; + let e: [i32x2; 4] = [i32x2::new(1, 2), i32x2::new(2, 6), i32x2::new(2, 6), i32x2::new(6, 8)]; + let r: [i32x2; 4] = transmute(vld4_s32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsq_n_s32() { - let a: i32x4 = i32x4::new(6, 7, 8, 9); - let b: i32x4 = i32x4::new(2, 2, 2, 2); - let c: i32 = 3; - let e: i32x4 = i32x4::new(0, 1, 2, 3); - let r: i32x4 = transmute(vmlsq_n_s32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4q_s8() { + let a: [i8; 65] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48, 6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64]; + let e: [i8x16; 4] = [i8x16::new(1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16), i8x16::new(2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32), i8x16::new(2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48), i8x16::new(6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64)]; + let r: [i8x16; 4] = transmute(vld4q_s8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmls_n_u16() { - let a: u16x4 = u16x4::new(6, 7, 8, 9); - let b: u16x4 = u16x4::new(2, 2, 2, 2); - let c: u16 = 3; - let e: u16x4 = u16x4::new(0, 1, 2, 3); - let r: u16x4 = transmute(vmls_n_u16(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4q_s16() { + let a: [i16; 33] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; + let e: [i16x8; 4] = [i16x8::new(1, 2, 2, 6, 2, 6, 6, 8), i16x8::new(2, 6, 6, 8, 6, 8, 8, 16), i16x8::new(2, 6, 6, 8, 6, 8, 8, 16), i16x8::new(6, 8, 8, 16, 8, 16, 16, 32)]; + let r: [i16x8; 4] = transmute(vld4q_s16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsq_n_u16() { - let a: u16x8 = u16x8::new(6, 7, 8, 9, 10, 11, 12, 13); - let b: u16x8 = u16x8::new(2, 2, 2, 2, 2, 2, 2, 2); - let c: u16 = 3; - let e: u16x8 = u16x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let r: u16x8 = transmute(vmlsq_n_u16(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4q_s32() { + let a: [i32; 17] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; + let e: [i32x4; 4] = [i32x4::new(1, 2, 2, 6), i32x4::new(2, 6, 6, 8), i32x4::new(2, 6, 6, 8), i32x4::new(6, 8, 8, 16)]; + let r: [i32x4; 4] = transmute(vld4q_s32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmls_n_u32() { - let a: u32x2 = u32x2::new(6, 7); - let b: u32x2 = u32x2::new(2, 2); - let c: u32 = 3; - let e: u32x2 = u32x2::new(0, 1); - let r: u32x2 = transmute(vmls_n_u32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4_s64() { + let a: [i64; 5] = [0, 1, 2, 2, 6]; + let e: [i64x1; 4] = [i64x1::new(1), i64x1::new(2), i64x1::new(2), i64x1::new(6)]; + let r: [i64x1; 4] = transmute(vld4_s64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsq_n_u32() { - let a: u32x4 = u32x4::new(6, 7, 8, 9); - let b: u32x4 = u32x4::new(2, 2, 2, 2); - let c: u32 = 3; - let e: u32x4 = u32x4::new(0, 1, 2, 3); - let r: u32x4 = transmute(vmlsq_n_u32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4_u8() { + let a: [u8; 33] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; + let e: [u8x8; 4] = [u8x8::new(1, 2, 2, 6, 2, 6, 6, 8), u8x8::new(2, 6, 6, 8, 6, 8, 8, 16), u8x8::new(2, 6, 6, 8, 6, 8, 8, 16), u8x8::new(6, 8, 8, 16, 8, 16, 16, 32)]; + let r: [u8x8; 4] = transmute(vld4_u8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmls_n_f32() { - let a: f32x2 = f32x2::new(6., 7.); - let b: f32x2 = f32x2::new(2., 2.); - let c: f32 = 3.; - let e: f32x2 = f32x2::new(0., 1.); - let r: f32x2 = transmute(vmls_n_f32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4_u16() { + let a: [u16; 17] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; + let e: [u16x4; 4] = [u16x4::new(1, 2, 2, 6), u16x4::new(2, 6, 6, 8), u16x4::new(2, 6, 6, 8), u16x4::new(6, 8, 8, 16)]; + let r: [u16x4; 4] = transmute(vld4_u16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsq_n_f32() { - let a: f32x4 = f32x4::new(6., 7., 8., 9.); - let b: f32x4 = f32x4::new(2., 2., 2., 2.); - let c: f32 = 3.; - let e: f32x4 = f32x4::new(0., 1., 2., 3.); - let r: f32x4 = transmute(vmlsq_n_f32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4_u32() { + let a: [u32; 9] = [0, 1, 2, 2, 6, 2, 6, 6, 8]; + let e: [u32x2; 4] = [u32x2::new(1, 2), u32x2::new(2, 6), u32x2::new(2, 6), u32x2::new(6, 8)]; + let r: [u32x2; 4] = transmute(vld4_u32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmls_lane_s16() { - let a: i16x4 = i16x4::new(6, 7, 8, 9); - let b: i16x4 = i16x4::new(2, 2, 2, 2); - let c: i16x4 = i16x4::new(0, 3, 0, 0); - let e: i16x4 = i16x4::new(0, 1, 2, 3); - let r: i16x4 = transmute(vmls_lane_s16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4q_u8() { + let a: [u8; 65] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48, 6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64]; + let e: [u8x16; 4] = [u8x16::new(1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16), u8x16::new(2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32), u8x16::new(2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48), u8x16::new(6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64)]; + let r: [u8x16; 4] = transmute(vld4q_u8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmls_laneq_s16() { - let a: i16x4 = i16x4::new(6, 7, 8, 9); - let b: i16x4 = i16x4::new(2, 2, 2, 2); - let c: i16x8 = i16x8::new(0, 3, 0, 0, 0, 0, 0, 0); - let e: i16x4 = i16x4::new(0, 1, 2, 3); - let r: i16x4 = transmute(vmls_laneq_s16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4q_u16() { + let a: [u16; 33] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; + let e: [u16x8; 4] = [u16x8::new(1, 2, 2, 6, 2, 6, 6, 8), u16x8::new(2, 6, 6, 8, 6, 8, 8, 16), u16x8::new(2, 6, 6, 8, 6, 8, 8, 16), u16x8::new(6, 8, 8, 16, 8, 16, 16, 32)]; + let r: [u16x8; 4] = transmute(vld4q_u16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsq_lane_s16() { - let a: i16x8 = i16x8::new(6, 7, 8, 9, 10, 11, 12, 13); - let b: i16x8 = i16x8::new(2, 2, 2, 2, 2, 2, 2, 2); - let c: i16x4 = i16x4::new(0, 3, 0, 0); - let e: i16x8 = i16x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let r: i16x8 = transmute(vmlsq_lane_s16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4q_u32() { + let a: [u32; 17] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; + let e: [u32x4; 4] = [u32x4::new(1, 2, 2, 6), u32x4::new(2, 6, 6, 8), u32x4::new(2, 6, 6, 8), u32x4::new(6, 8, 8, 16)]; + let r: [u32x4; 4] = transmute(vld4q_u32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsq_laneq_s16() { - let a: i16x8 = i16x8::new(6, 7, 8, 9, 10, 11, 12, 13); - let b: i16x8 = i16x8::new(2, 2, 2, 2, 2, 2, 2, 2); - let c: i16x8 = i16x8::new(0, 3, 0, 0, 0, 0, 0, 0); - let e: i16x8 = i16x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let r: i16x8 = transmute(vmlsq_laneq_s16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4_p8() { + let a: [u8; 33] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; + let e: [i8x8; 4] = [i8x8::new(1, 2, 2, 6, 2, 6, 6, 8), i8x8::new(2, 6, 6, 8, 6, 8, 8, 16), i8x8::new(2, 6, 6, 8, 6, 8, 8, 16), i8x8::new(6, 8, 8, 16, 8, 16, 16, 32)]; + let r: [i8x8; 4] = transmute(vld4_p8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmls_lane_s32() { - let a: i32x2 = i32x2::new(6, 7); - let b: i32x2 = i32x2::new(2, 2); - let c: i32x2 = i32x2::new(0, 3); - let e: i32x2 = i32x2::new(0, 1); - let r: i32x2 = transmute(vmls_lane_s32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4_p16() { + let a: [u16; 17] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; + let e: [i16x4; 4] = [i16x4::new(1, 2, 2, 6), i16x4::new(2, 6, 6, 8), i16x4::new(2, 6, 6, 8), i16x4::new(6, 8, 8, 16)]; + let r: [i16x4; 4] = transmute(vld4_p16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmls_laneq_s32() { - let a: i32x2 = i32x2::new(6, 7); - let b: i32x2 = i32x2::new(2, 2); - let c: i32x4 = i32x4::new(0, 3, 0, 0); - let e: i32x2 = i32x2::new(0, 1); - let r: i32x2 = transmute(vmls_laneq_s32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4q_p8() { + let a: [u8; 65] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48, 6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64]; + let e: [i8x16; 4] = [i8x16::new(1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16), i8x16::new(2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32), i8x16::new(2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48), i8x16::new(6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64)]; + let r: [i8x16; 4] = transmute(vld4q_p8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsq_lane_s32() { - let a: i32x4 = i32x4::new(6, 7, 8, 9); - let b: i32x4 = i32x4::new(2, 2, 2, 2); - let c: i32x2 = i32x2::new(0, 3); - let e: i32x4 = i32x4::new(0, 1, 2, 3); - let r: i32x4 = transmute(vmlsq_lane_s32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4q_p16() { + let a: [u16; 33] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; + let e: [i16x8; 4] = [i16x8::new(1, 2, 2, 6, 2, 6, 6, 8), i16x8::new(2, 6, 6, 8, 6, 8, 8, 16), i16x8::new(2, 6, 6, 8, 6, 8, 8, 16), i16x8::new(6, 8, 8, 16, 8, 16, 16, 32)]; + let r: [i16x8; 4] = transmute(vld4q_p16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsq_laneq_s32() { - let a: i32x4 = i32x4::new(6, 7, 8, 9); - let b: i32x4 = i32x4::new(2, 2, 2, 2); - let c: i32x4 = i32x4::new(0, 3, 0, 0); - let e: i32x4 = i32x4::new(0, 1, 2, 3); - let r: i32x4 = transmute(vmlsq_laneq_s32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4_u64() { + let a: [u64; 5] = [0, 1, 2, 2, 6]; + let e: [u64x1; 4] = [u64x1::new(1), u64x1::new(2), u64x1::new(2), u64x1::new(6)]; + let r: [u64x1; 4] = transmute(vld4_u64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmls_lane_u16() { - let a: u16x4 = u16x4::new(6, 7, 8, 9); - let b: u16x4 = u16x4::new(2, 2, 2, 2); - let c: u16x4 = u16x4::new(0, 3, 0, 0); - let e: u16x4 = u16x4::new(0, 1, 2, 3); - let r: u16x4 = transmute(vmls_lane_u16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4_p64() { + let a: [u64; 5] = [0, 1, 2, 2, 6]; + let e: [i64x1; 4] = [i64x1::new(1), i64x1::new(2), i64x1::new(2), i64x1::new(6)]; + let r: [i64x1; 4] = transmute(vld4_p64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmls_laneq_u16() { - let a: u16x4 = u16x4::new(6, 7, 8, 9); - let b: u16x4 = u16x4::new(2, 2, 2, 2); - let c: u16x8 = u16x8::new(0, 3, 0, 0, 0, 0, 0, 0); - let e: u16x4 = u16x4::new(0, 1, 2, 3); - let r: u16x4 = transmute(vmls_laneq_u16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4_f32() { + let a: [f32; 9] = [0., 1., 2., 2., 6., 2., 6., 6., 8.]; + let e: [f32x2; 4] = [f32x2::new(1., 2.), f32x2::new(2., 6.), f32x2::new(2., 6.), f32x2::new(6., 8.)]; + let r: [f32x2; 4] = transmute(vld4_f32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsq_lane_u16() { - let a: u16x8 = u16x8::new(6, 7, 8, 9, 10, 11, 12, 13); - let b: u16x8 = u16x8::new(2, 2, 2, 2, 2, 2, 2, 2); - let c: u16x4 = u16x4::new(0, 3, 0, 0); - let e: u16x8 = u16x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let r: u16x8 = transmute(vmlsq_lane_u16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4q_f32() { + let a: [f32; 17] = [0., 1., 2., 2., 6., 2., 6., 6., 8., 2., 6., 6., 8., 6., 8., 15., 16.]; + let e: [f32x4; 4] = [f32x4::new(1., 2., 2., 6.), f32x4::new(2., 6., 6., 8.), f32x4::new(2., 6., 6., 15.), f32x4::new(6., 8., 8., 16.)]; + let r: [f32x4; 4] = transmute(vld4q_f32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsq_laneq_u16() { - let a: u16x8 = u16x8::new(6, 7, 8, 9, 10, 11, 12, 13); - let b: u16x8 = u16x8::new(2, 2, 2, 2, 2, 2, 2, 2); - let c: u16x8 = u16x8::new(0, 3, 0, 0, 0, 0, 0, 0); - let e: u16x8 = u16x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let r: u16x8 = transmute(vmlsq_laneq_u16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4_dup_s8() { + let a: [i8; 33] = [0, 1, 1, 1, 1, 2, 4, 3, 5, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9]; + let e: [i8x8; 4] = [i8x8::new(1, 1, 1, 1, 1, 1, 1, 1), i8x8::new(1, 1, 1, 1, 1, 1, 1, 1), i8x8::new(1, 1, 1, 1, 1, 1, 1, 1), i8x8::new(1, 1, 1, 1, 1, 1, 1, 1)]; + let r: [i8x8; 4] = transmute(vld4_dup_s8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmls_lane_u32() { - let a: u32x2 = u32x2::new(6, 7); - let b: u32x2 = u32x2::new(2, 2); - let c: u32x2 = u32x2::new(0, 3); - let e: u32x2 = u32x2::new(0, 1); - let r: u32x2 = transmute(vmls_lane_u32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4_dup_s16() { + let a: [i16; 17] = [0, 1, 1, 1, 1, 2, 4, 3, 5, 8, 6, 3, 7, 4, 8, 5, 9]; + let e: [i16x4; 4] = [i16x4::new(1, 1, 1, 1), i16x4::new(1, 1, 1, 1), i16x4::new(1, 1, 1, 1), i16x4::new(1, 1, 1, 1)]; + let r: [i16x4; 4] = transmute(vld4_dup_s16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmls_laneq_u32() { - let a: u32x2 = u32x2::new(6, 7); - let b: u32x2 = u32x2::new(2, 2); - let c: u32x4 = u32x4::new(0, 3, 0, 0); - let e: u32x2 = u32x2::new(0, 1); - let r: u32x2 = transmute(vmls_laneq_u32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4_dup_s32() { + let a: [i32; 9] = [0, 1, 1, 1, 1, 2, 4, 3, 5]; + let e: [i32x2; 4] = [i32x2::new(1, 1), i32x2::new(1, 1), i32x2::new(1, 1), i32x2::new(1, 1)]; + let r: [i32x2; 4] = transmute(vld4_dup_s32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsq_lane_u32() { - let a: u32x4 = u32x4::new(6, 7, 8, 9); - let b: u32x4 = u32x4::new(2, 2, 2, 2); - let c: u32x2 = u32x2::new(0, 3); - let e: u32x4 = u32x4::new(0, 1, 2, 3); - let r: u32x4 = transmute(vmlsq_lane_u32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4q_dup_s8() { + let a: [i8; 65] = [0, 1, 1, 1, 1, 2, 4, 3, 5, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9]; + let e: [i8x16; 4] = [i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)]; + let r: [i8x16; 4] = transmute(vld4q_dup_s8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsq_laneq_u32() { - let a: u32x4 = u32x4::new(6, 7, 8, 9); - let b: u32x4 = u32x4::new(2, 2, 2, 2); - let c: u32x4 = u32x4::new(0, 3, 0, 0); - let e: u32x4 = u32x4::new(0, 1, 2, 3); - let r: u32x4 = transmute(vmlsq_laneq_u32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4q_dup_s16() { + let a: [i16; 33] = [0, 1, 1, 1, 1, 2, 4, 3, 5, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9]; + let e: [i16x8; 4] = [i16x8::new(1, 1, 1, 1, 1, 1, 1, 1), i16x8::new(1, 1, 1, 1, 1, 1, 1, 1), i16x8::new(1, 1, 1, 1, 1, 1, 1, 1), i16x8::new(1, 1, 1, 1, 1, 1, 1, 1)]; + let r: [i16x8; 4] = transmute(vld4q_dup_s16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmls_lane_f32() { - let a: f32x2 = f32x2::new(6., 7.); - let b: f32x2 = f32x2::new(2., 2.); - let c: f32x2 = f32x2::new(0., 3.); - let e: f32x2 = f32x2::new(0., 1.); - let r: f32x2 = transmute(vmls_lane_f32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4q_dup_s32() { + let a: [i32; 17] = [0, 1, 1, 1, 1, 2, 4, 3, 5, 8, 6, 3, 7, 4, 8, 5, 9]; + let e: [i32x4; 4] = [i32x4::new(1, 1, 1, 1), i32x4::new(1, 1, 1, 1), i32x4::new(1, 1, 1, 1), i32x4::new(1, 1, 1, 1)]; + let r: [i32x4; 4] = transmute(vld4q_dup_s32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmls_laneq_f32() { - let a: f32x2 = f32x2::new(6., 7.); - let b: f32x2 = f32x2::new(2., 2.); - let c: f32x4 = f32x4::new(0., 3., 0., 0.); - let e: f32x2 = f32x2::new(0., 1.); - let r: f32x2 = transmute(vmls_laneq_f32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4_dup_s64() { + let a: [i64; 5] = [0, 1, 1, 1, 1]; + let e: [i64x1; 4] = [i64x1::new(1), i64x1::new(1), i64x1::new(1), i64x1::new(1)]; + let r: [i64x1; 4] = transmute(vld4_dup_s64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsq_lane_f32() { - let a: f32x4 = f32x4::new(6., 7., 8., 9.); - let b: f32x4 = f32x4::new(2., 2., 2., 2.); - let c: f32x2 = f32x2::new(0., 3.); - let e: f32x4 = f32x4::new(0., 1., 2., 3.); - let r: f32x4 = transmute(vmlsq_lane_f32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4_dup_u8() { + let a: [u8; 33] = [0, 1, 1, 1, 1, 2, 4, 3, 5, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9]; + let e: [u8x8; 4] = [u8x8::new(1, 1, 1, 1, 1, 1, 1, 1), u8x8::new(1, 1, 1, 1, 1, 1, 1, 1), u8x8::new(1, 1, 1, 1, 1, 1, 1, 1), u8x8::new(1, 1, 1, 1, 1, 1, 1, 1)]; + let r: [u8x8; 4] = transmute(vld4_dup_u8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsq_laneq_f32() { - let a: f32x4 = f32x4::new(6., 7., 8., 9.); - let b: f32x4 = f32x4::new(2., 2., 2., 2.); - let c: f32x4 = f32x4::new(0., 3., 0., 0.); - let e: f32x4 = f32x4::new(0., 1., 2., 3.); - let r: f32x4 = transmute(vmlsq_laneq_f32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4_dup_u16() { + let a: [u16; 17] = [0, 1, 1, 1, 1, 2, 4, 3, 5, 8, 6, 3, 7, 4, 8, 5, 9]; + let e: [u16x4; 4] = [u16x4::new(1, 1, 1, 1), u16x4::new(1, 1, 1, 1), u16x4::new(1, 1, 1, 1), u16x4::new(1, 1, 1, 1)]; + let r: [u16x4; 4] = transmute(vld4_dup_u16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_s8() { - let a: i16x8 = i16x8::new(6, 7, 8, 9, 10, 11, 12, 13); - let b: i8x8 = i8x8::new(2, 2, 2, 2, 2, 2, 2, 2); - let c: i8x8 = i8x8::new(3, 3, 3, 3, 3, 3, 3, 3); - let e: i16x8 = i16x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let r: i16x8 = transmute(vmlsl_s8(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4_dup_u32() { + let a: [u32; 9] = [0, 1, 1, 1, 1, 2, 4, 3, 5]; + let e: [u32x2; 4] = [u32x2::new(1, 1), u32x2::new(1, 1), u32x2::new(1, 1), u32x2::new(1, 1)]; + let r: [u32x2; 4] = transmute(vld4_dup_u32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_s16() { - let a: i32x4 = i32x4::new(6, 7, 8, 9); - let b: i16x4 = i16x4::new(2, 2, 2, 2); - let c: i16x4 = i16x4::new(3, 3, 3, 3); - let e: i32x4 = i32x4::new(0, 1, 2, 3); - let r: i32x4 = transmute(vmlsl_s16(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4q_dup_u8() { + let a: [u8; 65] = [0, 1, 1, 1, 1, 2, 4, 3, 5, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9]; + let e: [u8x16; 4] = [u8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), u8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), u8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), u8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)]; + let r: [u8x16; 4] = transmute(vld4q_dup_u8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_s32() { - let a: i64x2 = i64x2::new(6, 7); - let b: i32x2 = i32x2::new(2, 2); - let c: i32x2 = i32x2::new(3, 3); - let e: i64x2 = i64x2::new(0, 1); - let r: i64x2 = transmute(vmlsl_s32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4q_dup_u16() { + let a: [u16; 33] = [0, 1, 1, 1, 1, 2, 4, 3, 5, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9]; + let e: [u16x8; 4] = [u16x8::new(1, 1, 1, 1, 1, 1, 1, 1), u16x8::new(1, 1, 1, 1, 1, 1, 1, 1), u16x8::new(1, 1, 1, 1, 1, 1, 1, 1), u16x8::new(1, 1, 1, 1, 1, 1, 1, 1)]; + let r: [u16x8; 4] = transmute(vld4q_dup_u16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_u8() { - let a: u16x8 = u16x8::new(6, 7, 8, 9, 10, 11, 12, 13); - let b: u8x8 = u8x8::new(2, 2, 2, 2, 2, 2, 2, 2); - let c: u8x8 = u8x8::new(3, 3, 3, 3, 3, 3, 3, 3); - let e: u16x8 = u16x8::new(0, 1, 2, 3, 4, 5, 6, 7); - let r: u16x8 = transmute(vmlsl_u8(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4q_dup_u32() { + let a: [u32; 17] = [0, 1, 1, 1, 1, 2, 4, 3, 5, 8, 6, 3, 7, 4, 8, 5, 9]; + let e: [u32x4; 4] = [u32x4::new(1, 1, 1, 1), u32x4::new(1, 1, 1, 1), u32x4::new(1, 1, 1, 1), u32x4::new(1, 1, 1, 1)]; + let r: [u32x4; 4] = transmute(vld4q_dup_u32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_u16() { - let a: u32x4 = u32x4::new(6, 7, 8, 9); - let b: u16x4 = u16x4::new(2, 2, 2, 2); - let c: u16x4 = u16x4::new(3, 3, 3, 3); - let e: u32x4 = u32x4::new(0, 1, 2, 3); - let r: u32x4 = transmute(vmlsl_u16(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4_dup_p8() { + let a: [u8; 33] = [0, 1, 1, 1, 1, 2, 4, 3, 5, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9]; + let e: [i8x8; 4] = [i8x8::new(1, 1, 1, 1, 1, 1, 1, 1), i8x8::new(1, 1, 1, 1, 1, 1, 1, 1), i8x8::new(1, 1, 1, 1, 1, 1, 1, 1), i8x8::new(1, 1, 1, 1, 1, 1, 1, 1)]; + let r: [i8x8; 4] = transmute(vld4_dup_p8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_u32() { - let a: u64x2 = u64x2::new(6, 7); - let b: u32x2 = u32x2::new(2, 2); - let c: u32x2 = u32x2::new(3, 3); - let e: u64x2 = u64x2::new(0, 1); - let r: u64x2 = transmute(vmlsl_u32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4_dup_p16() { + let a: [u16; 17] = [0, 1, 1, 1, 1, 2, 4, 3, 5, 8, 6, 3, 7, 4, 8, 5, 9]; + let e: [i16x4; 4] = [i16x4::new(1, 1, 1, 1), i16x4::new(1, 1, 1, 1), i16x4::new(1, 1, 1, 1), i16x4::new(1, 1, 1, 1)]; + let r: [i16x4; 4] = transmute(vld4_dup_p16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_n_s16() { - let a: i32x4 = i32x4::new(6, 7, 8, 9); - let b: i16x4 = i16x4::new(2, 2, 2, 2); - let c: i16 = 3; - let e: i32x4 = i32x4::new(0, 1, 2, 3); - let r: i32x4 = transmute(vmlsl_n_s16(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4q_dup_p8() { + let a: [u8; 65] = [0, 1, 1, 1, 1, 2, 4, 3, 5, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9]; + let e: [i8x16; 4] = [i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)]; + let r: [i8x16; 4] = transmute(vld4q_dup_p8(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_n_s32() { - let a: i64x2 = i64x2::new(6, 7); - let b: i32x2 = i32x2::new(2, 2); - let c: i32 = 3; - let e: i64x2 = i64x2::new(0, 1); - let r: i64x2 = transmute(vmlsl_n_s32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4q_dup_p16() { + let a: [u16; 33] = [0, 1, 1, 1, 1, 2, 4, 3, 5, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9]; + let e: [i16x8; 4] = [i16x8::new(1, 1, 1, 1, 1, 1, 1, 1), i16x8::new(1, 1, 1, 1, 1, 1, 1, 1), i16x8::new(1, 1, 1, 1, 1, 1, 1, 1), i16x8::new(1, 1, 1, 1, 1, 1, 1, 1)]; + let r: [i16x8; 4] = transmute(vld4q_dup_p16(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_n_u16() { - let a: u32x4 = u32x4::new(6, 7, 8, 9); - let b: u16x4 = u16x4::new(2, 2, 2, 2); - let c: u16 = 3; - let e: u32x4 = u32x4::new(0, 1, 2, 3); - let r: u32x4 = transmute(vmlsl_n_u16(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4_dup_u64() { + let a: [u64; 5] = [0, 1, 1, 1, 1]; + let e: [u64x1; 4] = [u64x1::new(1), u64x1::new(1), u64x1::new(1), u64x1::new(1)]; + let r: [u64x1; 4] = transmute(vld4_dup_u64(a[1..].as_ptr())); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld4_dup_p64() { + let a: [u64; 5] = [0, 1, 1, 1, 1]; + let e: [i64x1; 4] = [i64x1::new(1), i64x1::new(1), i64x1::new(1), i64x1::new(1)]; + let r: [i64x1; 4] = transmute(vld4_dup_p64(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_n_u32() { - let a: u64x2 = u64x2::new(6, 7); - let b: u32x2 = u32x2::new(2, 2); - let c: u32 = 3; - let e: u64x2 = u64x2::new(0, 1); - let r: u64x2 = transmute(vmlsl_n_u32(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4_dup_f32() { + let a: [f32; 9] = [0., 1., 1., 1., 1., 6., 4., 3., 5.]; + let e: [f32x2; 4] = [f32x2::new(1., 1.), f32x2::new(1., 1.), f32x2::new(1., 1.), f32x2::new(1., 1.)]; + let r: [f32x2; 4] = transmute(vld4_dup_f32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_lane_s16() { - let a: i32x4 = i32x4::new(6, 7, 8, 9); - let b: i16x4 = i16x4::new(2, 2, 2, 2); - let c: i16x4 = i16x4::new(0, 3, 0, 0); - let e: i32x4 = i32x4::new(0, 1, 2, 3); - let r: i32x4 = transmute(vmlsl_lane_s16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4q_dup_f32() { + let a: [f32; 17] = [0., 1., 1., 1., 1., 6., 4., 3., 5., 7., 4., 3., 5., 8., 4., 3., 5.]; + let e: [f32x4; 4] = [f32x4::new(1., 1., 1., 1.), f32x4::new(1., 1., 1., 1.), f32x4::new(1., 1., 1., 1.), f32x4::new(1., 1., 1., 1.)]; + let r: [f32x4; 4] = transmute(vld4q_dup_f32(a[1..].as_ptr())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_laneq_s16() { - let a: i32x4 = i32x4::new(6, 7, 8, 9); - let b: i16x4 = i16x4::new(2, 2, 2, 2); - let c: i16x8 = i16x8::new(0, 3, 0, 0, 0, 0, 0, 0); - let e: i32x4 = i32x4::new(0, 1, 2, 3); - let r: i32x4 = transmute(vmlsl_laneq_s16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4_lane_s8() { + let a: [i8; 33] = [0, 1, 2, 2, 2, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [i8x8; 4] = [i8x8::new(0, 2, 2, 2, 2, 16, 2, 18), i8x8::new(2, 20, 21, 22, 2, 24, 25, 26), i8x8::new(11, 12, 13, 14, 15, 16, 2, 18), i8x8::new(2, 20, 21, 22, 23, 24, 25, 26)]; + let e: [i8x8; 4] = [i8x8::new(1, 2, 2, 2, 2, 16, 2, 18), i8x8::new(2, 20, 21, 22, 2, 24, 25, 26), i8x8::new(2, 12, 13, 14, 15, 16, 2, 18), i8x8::new(2, 20, 21, 22, 23, 24, 25, 26)]; + let r: [i8x8; 4] = transmute(vld4_lane_s8::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_lane_s32() { - let a: i64x2 = i64x2::new(6, 7); - let b: i32x2 = i32x2::new(2, 2); - let c: i32x2 = i32x2::new(0, 3); - let e: i64x2 = i64x2::new(0, 1); - let r: i64x2 = transmute(vmlsl_lane_s32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4_lane_s16() { + let a: [i16; 17] = [0, 1, 2, 2, 2, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [i16x4; 4] = [i16x4::new(0, 2, 2, 2), i16x4::new(2, 16, 2, 18), i16x4::new(2, 20, 21, 22), i16x4::new(2, 24, 25, 26)]; + let e: [i16x4; 4] = [i16x4::new(1, 2, 2, 2), i16x4::new(2, 16, 2, 18), i16x4::new(2, 20, 21, 22), i16x4::new(2, 24, 25, 26)]; + let r: [i16x4; 4] = transmute(vld4_lane_s16::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_laneq_s32() { - let a: i64x2 = i64x2::new(6, 7); - let b: i32x2 = i32x2::new(2, 2); - let c: i32x4 = i32x4::new(0, 3, 0, 0); - let e: i64x2 = i64x2::new(0, 1); - let r: i64x2 = transmute(vmlsl_laneq_s32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4_lane_s32() { + let a: [i32; 9] = [0, 1, 2, 2, 2, 5, 6, 7, 8]; + let b: [i32x2; 4] = [i32x2::new(0, 2), i32x2::new(2, 2), i32x2::new(2, 16), i32x2::new(2, 18)]; + let e: [i32x2; 4] = [i32x2::new(1, 2), i32x2::new(2, 2), i32x2::new(2, 16), i32x2::new(2, 18)]; + let r: [i32x2; 4] = transmute(vld4_lane_s32::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_lane_u16() { - let a: u32x4 = u32x4::new(6, 7, 8, 9); - let b: u16x4 = u16x4::new(2, 2, 2, 2); - let c: u16x4 = u16x4::new(0, 3, 0, 0); - let e: u32x4 = u32x4::new(0, 1, 2, 3); - let r: u32x4 = transmute(vmlsl_lane_u16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4q_lane_s16() { + let a: [i16; 33] = [0, 1, 2, 2, 2, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [i16x8; 4] = [i16x8::new(0, 2, 2, 2, 2, 16, 2, 18), i16x8::new(2, 20, 21, 22, 2, 24, 25, 26), i16x8::new(11, 12, 13, 14, 15, 16, 2, 18), i16x8::new(2, 20, 21, 22, 23, 24, 25, 26)]; + let e: [i16x8; 4] = [i16x8::new(1, 2, 2, 2, 2, 16, 2, 18), i16x8::new(2, 20, 21, 22, 2, 24, 25, 26), i16x8::new(2, 12, 13, 14, 15, 16, 2, 18), i16x8::new(2, 20, 21, 22, 23, 24, 25, 26)]; + let r: [i16x8; 4] = transmute(vld4q_lane_s16::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_laneq_u16() { - let a: u32x4 = u32x4::new(6, 7, 8, 9); - let b: u16x4 = u16x4::new(2, 2, 2, 2); - let c: u16x8 = u16x8::new(0, 3, 0, 0, 0, 0, 0, 0); - let e: u32x4 = u32x4::new(0, 1, 2, 3); - let r: u32x4 = transmute(vmlsl_laneq_u16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4q_lane_s32() { + let a: [i32; 17] = [0, 1, 2, 2, 2, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [i32x4; 4] = [i32x4::new(0, 2, 2, 2), i32x4::new(2, 16, 2, 18), i32x4::new(2, 20, 21, 22), i32x4::new(2, 24, 25, 26)]; + let e: [i32x4; 4] = [i32x4::new(1, 2, 2, 2), i32x4::new(2, 16, 2, 18), i32x4::new(2, 20, 21, 22), i32x4::new(2, 24, 25, 26)]; + let r: [i32x4; 4] = transmute(vld4q_lane_s32::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_lane_u32() { - let a: u64x2 = u64x2::new(6, 7); - let b: u32x2 = u32x2::new(2, 2); - let c: u32x2 = u32x2::new(0, 3); - let e: u64x2 = u64x2::new(0, 1); - let r: u64x2 = transmute(vmlsl_lane_u32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4_lane_u8() { + let a: [u8; 33] = [0, 1, 2, 2, 2, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [u8x8; 4] = [u8x8::new(0, 2, 2, 2, 2, 16, 2, 18), u8x8::new(2, 20, 21, 22, 2, 24, 25, 26), u8x8::new(11, 12, 13, 14, 15, 16, 2, 18), u8x8::new(2, 20, 21, 22, 23, 24, 25, 26)]; + let e: [u8x8; 4] = [u8x8::new(1, 2, 2, 2, 2, 16, 2, 18), u8x8::new(2, 20, 21, 22, 2, 24, 25, 26), u8x8::new(2, 12, 13, 14, 15, 16, 2, 18), u8x8::new(2, 20, 21, 22, 23, 24, 25, 26)]; + let r: [u8x8; 4] = transmute(vld4_lane_u8::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmlsl_laneq_u32() { - let a: u64x2 = u64x2::new(6, 7); - let b: u32x2 = u32x2::new(2, 2); - let c: u32x4 = u32x4::new(0, 3, 0, 0); - let e: u64x2 = u64x2::new(0, 1); - let r: u64x2 = transmute(vmlsl_laneq_u32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vld4_lane_u16() { + let a: [u16; 17] = [0, 1, 2, 2, 2, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [u16x4; 4] = [u16x4::new(0, 2, 2, 2), u16x4::new(2, 16, 2, 18), u16x4::new(2, 20, 21, 22), u16x4::new(2, 24, 25, 26)]; + let e: [u16x4; 4] = [u16x4::new(1, 2, 2, 2), u16x4::new(2, 16, 2, 18), u16x4::new(2, 20, 21, 22), u16x4::new(2, 24, 25, 26)]; + let r: [u16x4; 4] = transmute(vld4_lane_u16::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vneg_s8() { - let a: i8x8 = i8x8::new(0, 1, -1, 2, -2, 3, -3, 4); - let e: i8x8 = i8x8::new(0, -1, 1, -2, 2, -3, 3, -4); - let r: i8x8 = transmute(vneg_s8(transmute(a))); + unsafe fn test_vld4_lane_u32() { + let a: [u32; 9] = [0, 1, 2, 2, 2, 5, 6, 7, 8]; + let b: [u32x2; 4] = [u32x2::new(0, 2), u32x2::new(2, 2), u32x2::new(2, 16), u32x2::new(2, 18)]; + let e: [u32x2; 4] = [u32x2::new(1, 2), u32x2::new(2, 2), u32x2::new(2, 16), u32x2::new(2, 18)]; + let r: [u32x2; 4] = transmute(vld4_lane_u32::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vnegq_s8() { - let a: i8x16 = i8x16::new(0, 1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, 7, -7, 8); - let e: i8x16 = i8x16::new(0, -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7, -8); - let r: i8x16 = transmute(vnegq_s8(transmute(a))); + unsafe fn test_vld4q_lane_u16() { + let a: [u16; 33] = [0, 1, 2, 2, 2, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [u16x8; 4] = [u16x8::new(0, 2, 2, 2, 2, 16, 2, 18), u16x8::new(2, 20, 21, 22, 2, 24, 25, 26), u16x8::new(11, 12, 13, 14, 15, 16, 2, 18), u16x8::new(2, 20, 21, 22, 23, 24, 25, 26)]; + let e: [u16x8; 4] = [u16x8::new(1, 2, 2, 2, 2, 16, 2, 18), u16x8::new(2, 20, 21, 22, 2, 24, 25, 26), u16x8::new(2, 12, 13, 14, 15, 16, 2, 18), u16x8::new(2, 20, 21, 22, 23, 24, 25, 26)]; + let r: [u16x8; 4] = transmute(vld4q_lane_u16::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vneg_s16() { - let a: i16x4 = i16x4::new(0, 1, -1, 2); - let e: i16x4 = i16x4::new(0, -1, 1, -2); - let r: i16x4 = transmute(vneg_s16(transmute(a))); + unsafe fn test_vld4q_lane_u32() { + let a: [u32; 17] = [0, 1, 2, 2, 2, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [u32x4; 4] = [u32x4::new(0, 2, 2, 2), u32x4::new(2, 16, 2, 18), u32x4::new(2, 20, 21, 22), u32x4::new(2, 24, 25, 26)]; + let e: [u32x4; 4] = [u32x4::new(1, 2, 2, 2), u32x4::new(2, 16, 2, 18), u32x4::new(2, 20, 21, 22), u32x4::new(2, 24, 25, 26)]; + let r: [u32x4; 4] = transmute(vld4q_lane_u32::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vnegq_s16() { - let a: i16x8 = i16x8::new(0, 1, -1, 2, -2, 3, -3, 4); - let e: i16x8 = i16x8::new(0, -1, 1, -2, 2, -3, 3, -4); - let r: i16x8 = transmute(vnegq_s16(transmute(a))); + unsafe fn test_vld4_lane_p8() { + let a: [u8; 33] = [0, 1, 2, 2, 2, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [i8x8; 4] = [i8x8::new(0, 2, 2, 2, 2, 16, 2, 18), i8x8::new(2, 20, 21, 22, 2, 24, 25, 26), i8x8::new(11, 12, 13, 14, 15, 16, 2, 18), i8x8::new(2, 20, 21, 22, 23, 24, 25, 26)]; + let e: [i8x8; 4] = [i8x8::new(1, 2, 2, 2, 2, 16, 2, 18), i8x8::new(2, 20, 21, 22, 2, 24, 25, 26), i8x8::new(2, 12, 13, 14, 15, 16, 2, 18), i8x8::new(2, 20, 21, 22, 23, 24, 25, 26)]; + let r: [i8x8; 4] = transmute(vld4_lane_p8::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vneg_s32() { - let a: i32x2 = i32x2::new(0, 1); - let e: i32x2 = i32x2::new(0, -1); - let r: i32x2 = transmute(vneg_s32(transmute(a))); + unsafe fn test_vld4_lane_p16() { + let a: [u16; 17] = [0, 1, 2, 2, 2, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [i16x4; 4] = [i16x4::new(0, 2, 2, 2), i16x4::new(2, 16, 2, 18), i16x4::new(2, 20, 21, 22), i16x4::new(2, 24, 25, 26)]; + let e: [i16x4; 4] = [i16x4::new(1, 2, 2, 2), i16x4::new(2, 16, 2, 18), i16x4::new(2, 20, 21, 22), i16x4::new(2, 24, 25, 26)]; + let r: [i16x4; 4] = transmute(vld4_lane_p16::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vnegq_s32() { - let a: i32x4 = i32x4::new(0, 1, -1, 2); - let e: i32x4 = i32x4::new(0, -1, 1, -2); - let r: i32x4 = transmute(vnegq_s32(transmute(a))); + unsafe fn test_vld4q_lane_p16() { + let a: [u16; 33] = [0, 1, 2, 2, 2, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]; + let b: [i16x8; 4] = [i16x8::new(0, 2, 2, 2, 2, 16, 2, 18), i16x8::new(2, 20, 21, 22, 2, 24, 25, 26), i16x8::new(11, 12, 13, 14, 15, 16, 2, 18), i16x8::new(2, 20, 21, 22, 23, 24, 25, 26)]; + let e: [i16x8; 4] = [i16x8::new(1, 2, 2, 2, 2, 16, 2, 18), i16x8::new(2, 20, 21, 22, 2, 24, 25, 26), i16x8::new(2, 12, 13, 14, 15, 16, 2, 18), i16x8::new(2, 20, 21, 22, 23, 24, 25, 26)]; + let r: [i16x8; 4] = transmute(vld4q_lane_p16::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vneg_f32() { - let a: f32x2 = f32x2::new(0., 1.); - let e: f32x2 = f32x2::new(0., -1.); - let r: f32x2 = transmute(vneg_f32(transmute(a))); + unsafe fn test_vld4_lane_f32() { + let a: [f32; 9] = [0., 1., 2., 2., 2., 5., 6., 7., 8.]; + let b: [f32x2; 4] = [f32x2::new(0., 2.), f32x2::new(2., 2.), f32x2::new(2., 16.), f32x2::new(2., 18.)]; + let e: [f32x2; 4] = [f32x2::new(1., 2.), f32x2::new(2., 2.), f32x2::new(2., 16.), f32x2::new(2., 18.)]; + let r: [f32x2; 4] = transmute(vld4_lane_f32::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vnegq_f32() { - let a: f32x4 = f32x4::new(0., 1., -1., 2.); - let e: f32x4 = f32x4::new(0., -1., 1., -2.); - let r: f32x4 = transmute(vnegq_f32(transmute(a))); + unsafe fn test_vld4q_lane_f32() { + let a: [f32; 17] = [0., 1., 2., 2., 2., 5., 6., 7., 8., 5., 6., 7., 8., 1., 4., 3., 5.]; + let b: [f32x4; 4] = [f32x4::new(0., 2., 2., 2.), f32x4::new(2., 16., 2., 18.), f32x4::new(5., 6., 7., 8.), f32x4::new(1., 4., 3., 5.)]; + let e: [f32x4; 4] = [f32x4::new(1., 2., 2., 2.), f32x4::new(2., 16., 2., 18.), f32x4::new(2., 6., 7., 8.), f32x4::new(2., 4., 3., 5.)]; + let r: [f32x4; 4] = transmute(vld4q_lane_f32::<0>(a[1..].as_ptr(), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqneg_s8() { - let a: i8x8 = i8x8::new(-128, 0, 1, -1, 2, -2, 3, -3); - let e: i8x8 = i8x8::new(0x7F, 0, -1, 1, -2, 2, -3, 3); - let r: i8x8 = transmute(vqneg_s8(transmute(a))); + unsafe fn test_vst1_lane_s8() { + let a: [i8; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let e: [i8; 8] = [1, 0, 0, 0, 0, 0, 0, 0]; + let mut r: [i8; 8] = [0i8; 8]; + vst1_lane_s8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqnegq_s8() { - let a: i8x16 = i8x16::new(-128, 0, 1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, 7, -7); - let e: i8x16 = i8x16::new(0x7F, 0, -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7); - let r: i8x16 = transmute(vqnegq_s8(transmute(a))); + unsafe fn test_vst1_lane_s16() { + let a: [i16; 5] = [0, 1, 2, 3, 4]; + let e: [i16; 4] = [1, 0, 0, 0]; + let mut r: [i16; 4] = [0i16; 4]; + vst1_lane_s16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqneg_s16() { - let a: i16x4 = i16x4::new(-32768, 0, 1, -1); - let e: i16x4 = i16x4::new(0x7F_FF, 0, -1, 1); - let r: i16x4 = transmute(vqneg_s16(transmute(a))); + unsafe fn test_vst1_lane_s32() { + let a: [i32; 3] = [0, 1, 2]; + let e: [i32; 2] = [1, 0]; + let mut r: [i32; 2] = [0i32; 2]; + vst1_lane_s32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqnegq_s16() { - let a: i16x8 = i16x8::new(-32768, 0, 1, -1, 2, -2, 3, -3); - let e: i16x8 = i16x8::new(0x7F_FF, 0, -1, 1, -2, 2, -3, 3); - let r: i16x8 = transmute(vqnegq_s16(transmute(a))); + unsafe fn test_vst1_lane_s64() { + let a: [i64; 2] = [0, 1]; + let e: [i64; 1] = [1]; + let mut r: [i64; 1] = [0i64; 1]; + vst1_lane_s64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqneg_s32() { - let a: i32x2 = i32x2::new(-2147483648, 0); - let e: i32x2 = i32x2::new(0x7F_FF_FF_FF, 0); - let r: i32x2 = transmute(vqneg_s32(transmute(a))); + unsafe fn test_vst1q_lane_s8() { + let a: [i8; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let e: [i8; 16] = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + let mut r: [i8; 16] = [0i8; 16]; + vst1q_lane_s8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqnegq_s32() { - let a: i32x4 = i32x4::new(-2147483648, 0, 1, -1); - let e: i32x4 = i32x4::new(0x7F_FF_FF_FF, 0, -1, 1); - let r: i32x4 = transmute(vqnegq_s32(transmute(a))); + unsafe fn test_vst1q_lane_s16() { + let a: [i16; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let e: [i16; 8] = [1, 0, 0, 0, 0, 0, 0, 0]; + let mut r: [i16; 8] = [0i16; 8]; + vst1q_lane_s16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqsub_u8() { - let a: u8x8 = u8x8::new(42, 42, 42, 42, 42, 42, 42, 42); - let b: u8x8 = u8x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let e: u8x8 = u8x8::new(41, 40, 39, 38, 37, 36, 35, 34); - let r: u8x8 = transmute(vqsub_u8(transmute(a), transmute(b))); + unsafe fn test_vst1q_lane_s32() { + let a: [i32; 5] = [0, 1, 2, 3, 4]; + let e: [i32; 4] = [1, 0, 0, 0]; + let mut r: [i32; 4] = [0i32; 4]; + vst1q_lane_s32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqsubq_u8() { - let a: u8x16 = u8x16::new(42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42); - let b: u8x16 = u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let e: u8x16 = u8x16::new(41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26); - let r: u8x16 = transmute(vqsubq_u8(transmute(a), transmute(b))); + unsafe fn test_vst1q_lane_s64() { + let a: [i64; 3] = [0, 1, 2]; + let e: [i64; 2] = [1, 0]; + let mut r: [i64; 2] = [0i64; 2]; + vst1q_lane_s64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqsub_u16() { - let a: u16x4 = u16x4::new(42, 42, 42, 42); - let b: u16x4 = u16x4::new(1, 2, 3, 4); - let e: u16x4 = u16x4::new(41, 40, 39, 38); - let r: u16x4 = transmute(vqsub_u16(transmute(a), transmute(b))); + unsafe fn test_vst1_lane_u8() { + let a: [u8; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let e: [u8; 8] = [1, 0, 0, 0, 0, 0, 0, 0]; + let mut r: [u8; 8] = [0u8; 8]; + vst1_lane_u8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqsubq_u16() { - let a: u16x8 = u16x8::new(42, 42, 42, 42, 42, 42, 42, 42); - let b: u16x8 = u16x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let e: u16x8 = u16x8::new(41, 40, 39, 38, 37, 36, 35, 34); - let r: u16x8 = transmute(vqsubq_u16(transmute(a), transmute(b))); + unsafe fn test_vst1_lane_u16() { + let a: [u16; 5] = [0, 1, 2, 3, 4]; + let e: [u16; 4] = [1, 0, 0, 0]; + let mut r: [u16; 4] = [0u16; 4]; + vst1_lane_u16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqsub_u32() { - let a: u32x2 = u32x2::new(42, 42); - let b: u32x2 = u32x2::new(1, 2); - let e: u32x2 = u32x2::new(41, 40); - let r: u32x2 = transmute(vqsub_u32(transmute(a), transmute(b))); + unsafe fn test_vst1_lane_u32() { + let a: [u32; 3] = [0, 1, 2]; + let e: [u32; 2] = [1, 0]; + let mut r: [u32; 2] = [0u32; 2]; + vst1_lane_u32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqsubq_u32() { - let a: u32x4 = u32x4::new(42, 42, 42, 42); - let b: u32x4 = u32x4::new(1, 2, 3, 4); - let e: u32x4 = u32x4::new(41, 40, 39, 38); - let r: u32x4 = transmute(vqsubq_u32(transmute(a), transmute(b))); + unsafe fn test_vst1_lane_u64() { + let a: [u64; 2] = [0, 1]; + let e: [u64; 1] = [1]; + let mut r: [u64; 1] = [0u64; 1]; + vst1_lane_u64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqsub_u64() { - let a: u64x1 = u64x1::new(42); - let b: u64x1 = u64x1::new(1); - let e: u64x1 = u64x1::new(41); - let r: u64x1 = transmute(vqsub_u64(transmute(a), transmute(b))); + unsafe fn test_vst1q_lane_u8() { + let a: [u8; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let e: [u8; 16] = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + let mut r: [u8; 16] = [0u8; 16]; + vst1q_lane_u8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqsubq_u64() { - let a: u64x2 = u64x2::new(42, 42); - let b: u64x2 = u64x2::new(1, 2); - let e: u64x2 = u64x2::new(41, 40); - let r: u64x2 = transmute(vqsubq_u64(transmute(a), transmute(b))); + unsafe fn test_vst1q_lane_u16() { + let a: [u16; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let e: [u16; 8] = [1, 0, 0, 0, 0, 0, 0, 0]; + let mut r: [u16; 8] = [0u16; 8]; + vst1q_lane_u16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqsub_s8() { - let a: i8x8 = i8x8::new(42, 42, 42, 42, 42, 42, 42, 42); - let b: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let e: i8x8 = i8x8::new(41, 40, 39, 38, 37, 36, 35, 34); - let r: i8x8 = transmute(vqsub_s8(transmute(a), transmute(b))); + unsafe fn test_vst1q_lane_u32() { + let a: [u32; 5] = [0, 1, 2, 3, 4]; + let e: [u32; 4] = [1, 0, 0, 0]; + let mut r: [u32; 4] = [0u32; 4]; + vst1q_lane_u32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqsubq_s8() { - let a: i8x16 = i8x16::new(42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42); - let b: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let e: i8x16 = i8x16::new(41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26); - let r: i8x16 = transmute(vqsubq_s8(transmute(a), transmute(b))); + unsafe fn test_vst1q_lane_u64() { + let a: [u64; 3] = [0, 1, 2]; + let e: [u64; 2] = [1, 0]; + let mut r: [u64; 2] = [0u64; 2]; + vst1q_lane_u64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqsub_s16() { - let a: i16x4 = i16x4::new(42, 42, 42, 42); - let b: i16x4 = i16x4::new(1, 2, 3, 4); - let e: i16x4 = i16x4::new(41, 40, 39, 38); - let r: i16x4 = transmute(vqsub_s16(transmute(a), transmute(b))); + unsafe fn test_vst1_lane_p8() { + let a: [u8; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let e: [u8; 8] = [1, 0, 0, 0, 0, 0, 0, 0]; + let mut r: [u8; 8] = [0u8; 8]; + vst1_lane_p8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqsubq_s16() { - let a: i16x8 = i16x8::new(42, 42, 42, 42, 42, 42, 42, 42); - let b: i16x8 = i16x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let e: i16x8 = i16x8::new(41, 40, 39, 38, 37, 36, 35, 34); - let r: i16x8 = transmute(vqsubq_s16(transmute(a), transmute(b))); + unsafe fn test_vst1_lane_p16() { + let a: [u16; 5] = [0, 1, 2, 3, 4]; + let e: [u16; 4] = [1, 0, 0, 0]; + let mut r: [u16; 4] = [0u16; 4]; + vst1_lane_p16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqsub_s32() { - let a: i32x2 = i32x2::new(42, 42); - let b: i32x2 = i32x2::new(1, 2); - let e: i32x2 = i32x2::new(41, 40); - let r: i32x2 = transmute(vqsub_s32(transmute(a), transmute(b))); + unsafe fn test_vst1q_lane_p8() { + let a: [u8; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let e: [u8; 16] = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + let mut r: [u8; 16] = [0u8; 16]; + vst1q_lane_p8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqsubq_s32() { - let a: i32x4 = i32x4::new(42, 42, 42, 42); - let b: i32x4 = i32x4::new(1, 2, 3, 4); - let e: i32x4 = i32x4::new(41, 40, 39, 38); - let r: i32x4 = transmute(vqsubq_s32(transmute(a), transmute(b))); + unsafe fn test_vst1q_lane_p16() { + let a: [u16; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let e: [u16; 8] = [1, 0, 0, 0, 0, 0, 0, 0]; + let mut r: [u16; 8] = [0u16; 8]; + vst1q_lane_p16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqsub_s64() { - let a: i64x1 = i64x1::new(42); - let b: i64x1 = i64x1::new(1); - let e: i64x1 = i64x1::new(41); - let r: i64x1 = transmute(vqsub_s64(transmute(a), transmute(b))); + unsafe fn test_vst1_lane_p64() { + let a: [u64; 2] = [0, 1]; + let e: [u64; 1] = [1]; + let mut r: [u64; 1] = [0u64; 1]; + vst1_lane_p64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqsubq_s64() { - let a: i64x2 = i64x2::new(42, 42); - let b: i64x2 = i64x2::new(1, 2); - let e: i64x2 = i64x2::new(41, 40); - let r: i64x2 = transmute(vqsubq_s64(transmute(a), transmute(b))); + unsafe fn test_vst1q_lane_p64() { + let a: [u64; 3] = [0, 1, 2]; + let e: [u64; 2] = [1, 0]; + let mut r: [u64; 2] = [0u64; 2]; + vst1q_lane_p64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vhadd_u8() { - let a: u8x8 = u8x8::new(42, 42, 42, 42, 42, 42, 42, 42); - let b: u8x8 = u8x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let e: u8x8 = u8x8::new(21, 22, 22, 23, 23, 24, 24, 25); - let r: u8x8 = transmute(vhadd_u8(transmute(a), transmute(b))); + unsafe fn test_vst1_lane_f32() { + let a: [f32; 3] = [0., 1., 2.]; + let e: [f32; 2] = [1., 0.]; + let mut r: [f32; 2] = [0f32; 2]; + vst1_lane_f32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vhaddq_u8() { - let a: u8x16 = u8x16::new(42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42); - let b: u8x16 = u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let e: u8x16 = u8x16::new(21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29); - let r: u8x16 = transmute(vhaddq_u8(transmute(a), transmute(b))); + unsafe fn test_vst1q_lane_f32() { + let a: [f32; 5] = [0., 1., 2., 3., 4.]; + let e: [f32; 4] = [1., 0., 0., 0.]; + let mut r: [f32; 4] = [0f32; 4]; + vst1q_lane_f32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vhadd_u16() { - let a: u16x4 = u16x4::new(42, 42, 42, 42); - let b: u16x4 = u16x4::new(1, 2, 3, 4); - let e: u16x4 = u16x4::new(21, 22, 22, 23); - let r: u16x4 = transmute(vhadd_u16(transmute(a), transmute(b))); + unsafe fn test_vst1_s8_x2() { + let a: [i8; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let e: [i8; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let mut r: [i8; 16] = [0i8; 16]; + vst1_s8_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vhaddq_u16() { - let a: u16x8 = u16x8::new(42, 42, 42, 42, 42, 42, 42, 42); - let b: u16x8 = u16x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let e: u16x8 = u16x8::new(21, 22, 22, 23, 23, 24, 24, 25); - let r: u16x8 = transmute(vhaddq_u16(transmute(a), transmute(b))); + unsafe fn test_vst1_s16_x2() { + let a: [i16; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let e: [i16; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; + let mut r: [i16; 8] = [0i16; 8]; + vst1_s16_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vhadd_u32() { - let a: u32x2 = u32x2::new(42, 42); - let b: u32x2 = u32x2::new(1, 2); - let e: u32x2 = u32x2::new(21, 22); - let r: u32x2 = transmute(vhadd_u32(transmute(a), transmute(b))); + unsafe fn test_vst1_s32_x2() { + let a: [i32; 5] = [0, 1, 2, 3, 4]; + let e: [i32; 4] = [1, 2, 3, 4]; + let mut r: [i32; 4] = [0i32; 4]; + vst1_s32_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vst1_s64_x2() { + let a: [i64; 3] = [0, 1, 2]; + let e: [i64; 2] = [1, 2]; + let mut r: [i64; 2] = [0i64; 2]; + vst1_s64_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vhaddq_u32() { - let a: u32x4 = u32x4::new(42, 42, 42, 42); - let b: u32x4 = u32x4::new(1, 2, 3, 4); - let e: u32x4 = u32x4::new(21, 22, 22, 23); - let r: u32x4 = transmute(vhaddq_u32(transmute(a), transmute(b))); + unsafe fn test_vst1q_s8_x2() { + let a: [i8; 33] = [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]; + let e: [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 mut r: [i8; 32] = [0i8; 32]; + vst1q_s8_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vhadd_s8() { - let a: i8x8 = i8x8::new(42, 42, 42, 42, 42, 42, 42, 42); - let b: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let e: i8x8 = i8x8::new(21, 22, 22, 23, 23, 24, 24, 25); - let r: i8x8 = transmute(vhadd_s8(transmute(a), transmute(b))); + unsafe fn test_vst1q_s16_x2() { + let a: [i16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let e: [i16; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let mut r: [i16; 16] = [0i16; 16]; + vst1q_s16_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vhaddq_s8() { - let a: i8x16 = i8x16::new(42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42); - let b: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let e: i8x16 = i8x16::new(21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29); - let r: i8x16 = transmute(vhaddq_s8(transmute(a), transmute(b))); + unsafe fn test_vst1q_s32_x2() { + let a: [i32; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let e: [i32; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; + let mut r: [i32; 8] = [0i32; 8]; + vst1q_s32_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vhadd_s16() { - let a: i16x4 = i16x4::new(42, 42, 42, 42); - let b: i16x4 = i16x4::new(1, 2, 3, 4); - let e: i16x4 = i16x4::new(21, 22, 22, 23); - let r: i16x4 = transmute(vhadd_s16(transmute(a), transmute(b))); + unsafe fn test_vst1q_s64_x2() { + let a: [i64; 5] = [0, 1, 2, 3, 4]; + let e: [i64; 4] = [1, 2, 3, 4]; + let mut r: [i64; 4] = [0i64; 4]; + vst1q_s64_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vhaddq_s16() { - let a: i16x8 = i16x8::new(42, 42, 42, 42, 42, 42, 42, 42); - let b: i16x8 = i16x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let e: i16x8 = i16x8::new(21, 22, 22, 23, 23, 24, 24, 25); - let r: i16x8 = transmute(vhaddq_s16(transmute(a), transmute(b))); + unsafe fn test_vst1_s8_x3() { + let a: [i8; 25] = [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]; + let e: [i8; 24] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]; + let mut r: [i8; 24] = [0i8; 24]; + vst1_s8_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vhadd_s32() { - let a: i32x2 = i32x2::new(42, 42); - let b: i32x2 = i32x2::new(1, 2); - let e: i32x2 = i32x2::new(21, 22); - let r: i32x2 = transmute(vhadd_s32(transmute(a), transmute(b))); + unsafe fn test_vst1_s16_x3() { + let a: [i16; 13] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + let e: [i16; 12] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + let mut r: [i16; 12] = [0i16; 12]; + vst1_s16_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vhaddq_s32() { - let a: i32x4 = i32x4::new(42, 42, 42, 42); - let b: i32x4 = i32x4::new(1, 2, 3, 4); - let e: i32x4 = i32x4::new(21, 22, 22, 23); - let r: i32x4 = transmute(vhaddq_s32(transmute(a), transmute(b))); + unsafe fn test_vst1_s32_x3() { + let a: [i32; 7] = [0, 1, 2, 3, 4, 5, 6]; + let e: [i32; 6] = [1, 2, 3, 4, 5, 6]; + let mut r: [i32; 6] = [0i32; 6]; + vst1_s32_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrhadd_u8() { - let a: u8x8 = u8x8::new(42, 42, 42, 42, 42, 42, 42, 42); - let b: u8x8 = u8x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let e: u8x8 = u8x8::new(22, 22, 23, 23, 24, 24, 25, 25); - let r: u8x8 = transmute(vrhadd_u8(transmute(a), transmute(b))); + unsafe fn test_vst1_s64_x3() { + let a: [i64; 4] = [0, 1, 2, 3]; + let e: [i64; 3] = [1, 2, 3]; + let mut r: [i64; 3] = [0i64; 3]; + vst1_s64_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrhaddq_u8() { - let a: u8x16 = u8x16::new(42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42); - let b: u8x16 = u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let e: u8x16 = u8x16::new(22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29); - let r: u8x16 = transmute(vrhaddq_u8(transmute(a), transmute(b))); + unsafe fn test_vst1q_s8_x3() { + let a: [i8; 49] = [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, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let e: [i8; 48] = [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, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let mut r: [i8; 48] = [0i8; 48]; + vst1q_s8_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrhadd_u16() { - let a: u16x4 = u16x4::new(42, 42, 42, 42); - let b: u16x4 = u16x4::new(1, 2, 3, 4); - let e: u16x4 = u16x4::new(22, 22, 23, 23); - let r: u16x4 = transmute(vrhadd_u16(transmute(a), transmute(b))); + unsafe fn test_vst1q_s16_x3() { + let a: [i16; 25] = [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]; + let e: [i16; 24] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]; + let mut r: [i16; 24] = [0i16; 24]; + vst1q_s16_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrhaddq_u16() { - let a: u16x8 = u16x8::new(42, 42, 42, 42, 42, 42, 42, 42); - let b: u16x8 = u16x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let e: u16x8 = u16x8::new(22, 22, 23, 23, 24, 24, 25, 25); - let r: u16x8 = transmute(vrhaddq_u16(transmute(a), transmute(b))); + unsafe fn test_vst1q_s32_x3() { + let a: [i32; 13] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + let e: [i32; 12] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + let mut r: [i32; 12] = [0i32; 12]; + vst1q_s32_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrhadd_u32() { - let a: u32x2 = u32x2::new(42, 42); - let b: u32x2 = u32x2::new(1, 2); - let e: u32x2 = u32x2::new(22, 22); - let r: u32x2 = transmute(vrhadd_u32(transmute(a), transmute(b))); + unsafe fn test_vst1q_s64_x3() { + let a: [i64; 7] = [0, 1, 2, 3, 4, 5, 6]; + let e: [i64; 6] = [1, 2, 3, 4, 5, 6]; + let mut r: [i64; 6] = [0i64; 6]; + vst1q_s64_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrhaddq_u32() { - let a: u32x4 = u32x4::new(42, 42, 42, 42); - let b: u32x4 = u32x4::new(1, 2, 3, 4); - let e: u32x4 = u32x4::new(22, 22, 23, 23); - let r: u32x4 = transmute(vrhaddq_u32(transmute(a), transmute(b))); + unsafe fn test_vst1_s8_x4() { + let a: [i8; 33] = [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]; + let e: [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 mut r: [i8; 32] = [0i8; 32]; + vst1_s8_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrhadd_s8() { - let a: i8x8 = i8x8::new(42, 42, 42, 42, 42, 42, 42, 42); - let b: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let e: i8x8 = i8x8::new(22, 22, 23, 23, 24, 24, 25, 25); - let r: i8x8 = transmute(vrhadd_s8(transmute(a), transmute(b))); + unsafe fn test_vst1_s16_x4() { + let a: [i16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let e: [i16; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let mut r: [i16; 16] = [0i16; 16]; + vst1_s16_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrhaddq_s8() { - let a: i8x16 = i8x16::new(42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42); - let b: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let e: i8x16 = i8x16::new(22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29); - let r: i8x16 = transmute(vrhaddq_s8(transmute(a), transmute(b))); + unsafe fn test_vst1_s32_x4() { + let a: [i32; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let e: [i32; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; + let mut r: [i32; 8] = [0i32; 8]; + vst1_s32_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrhadd_s16() { - let a: i16x4 = i16x4::new(42, 42, 42, 42); - let b: i16x4 = i16x4::new(1, 2, 3, 4); - let e: i16x4 = i16x4::new(22, 22, 23, 23); - let r: i16x4 = transmute(vrhadd_s16(transmute(a), transmute(b))); + unsafe fn test_vst1_s64_x4() { + let a: [i64; 5] = [0, 1, 2, 3, 4]; + let e: [i64; 4] = [1, 2, 3, 4]; + let mut r: [i64; 4] = [0i64; 4]; + vst1_s64_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrhaddq_s16() { - let a: i16x8 = i16x8::new(42, 42, 42, 42, 42, 42, 42, 42); - let b: i16x8 = i16x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let e: i16x8 = i16x8::new(22, 22, 23, 23, 24, 24, 25, 25); - let r: i16x8 = transmute(vrhaddq_s16(transmute(a), transmute(b))); + unsafe fn test_vst1q_s8_x4() { + let a: [i8; 65] = [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, 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 e: [i8; 64] = [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, 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 mut r: [i8; 64] = [0i8; 64]; + vst1q_s8_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrhadd_s32() { - let a: i32x2 = i32x2::new(42, 42); - let b: i32x2 = i32x2::new(1, 2); - let e: i32x2 = i32x2::new(22, 22); - let r: i32x2 = transmute(vrhadd_s32(transmute(a), transmute(b))); + unsafe fn test_vst1q_s16_x4() { + let a: [i16; 33] = [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]; + let e: [i16; 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 mut r: [i16; 32] = [0i16; 32]; + vst1q_s16_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrhaddq_s32() { - let a: i32x4 = i32x4::new(42, 42, 42, 42); - let b: i32x4 = i32x4::new(1, 2, 3, 4); - let e: i32x4 = i32x4::new(22, 22, 23, 23); - let r: i32x4 = transmute(vrhaddq_s32(transmute(a), transmute(b))); + unsafe fn test_vst1q_s32_x4() { + let a: [i32; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let e: [i32; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let mut r: [i32; 16] = [0i32; 16]; + vst1q_s32_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrndn_f32() { - let a: f32x2 = f32x2::new(-1.5, 0.5); - let e: f32x2 = f32x2::new(-2.0, 0.0); - let r: f32x2 = transmute(vrndn_f32(transmute(a))); + unsafe fn test_vst1q_s64_x4() { + let a: [i64; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let e: [i64; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; + let mut r: [i64; 8] = [0i64; 8]; + vst1q_s64_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrndnq_f32() { - let a: f32x4 = f32x4::new(-1.5, 0.5, 1.5, 2.5); - let e: f32x4 = f32x4::new(-2.0, 0.0, 2.0, 2.0); - let r: f32x4 = transmute(vrndnq_f32(transmute(a))); + unsafe fn test_vst1_u8_x2() { + let a: [u8; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let e: [u8; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let mut r: [u8; 16] = [0u8; 16]; + vst1_u8_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqadd_u8() { - let a: u8x8 = u8x8::new(42, 42, 42, 42, 42, 42, 42, 42); - let b: u8x8 = u8x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let e: u8x8 = u8x8::new(43, 44, 45, 46, 47, 48, 49, 50); - let r: u8x8 = transmute(vqadd_u8(transmute(a), transmute(b))); + unsafe fn test_vst1_u16_x2() { + let a: [u16; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let e: [u16; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; + let mut r: [u16; 8] = [0u16; 8]; + vst1_u16_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqaddq_u8() { - let a: u8x16 = u8x16::new(42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42); - let b: u8x16 = u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let e: u8x16 = u8x16::new(43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58); - let r: u8x16 = transmute(vqaddq_u8(transmute(a), transmute(b))); + unsafe fn test_vst1_u32_x2() { + let a: [u32; 5] = [0, 1, 2, 3, 4]; + let e: [u32; 4] = [1, 2, 3, 4]; + let mut r: [u32; 4] = [0u32; 4]; + vst1_u32_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqadd_u16() { - let a: u16x4 = u16x4::new(42, 42, 42, 42); - let b: u16x4 = u16x4::new(1, 2, 3, 4); - let e: u16x4 = u16x4::new(43, 44, 45, 46); - let r: u16x4 = transmute(vqadd_u16(transmute(a), transmute(b))); + unsafe fn test_vst1_u64_x2() { + let a: [u64; 3] = [0, 1, 2]; + let e: [u64; 2] = [1, 2]; + let mut r: [u64; 2] = [0u64; 2]; + vst1_u64_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqaddq_u16() { - let a: u16x8 = u16x8::new(42, 42, 42, 42, 42, 42, 42, 42); - let b: u16x8 = u16x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let e: u16x8 = u16x8::new(43, 44, 45, 46, 47, 48, 49, 50); - let r: u16x8 = transmute(vqaddq_u16(transmute(a), transmute(b))); + unsafe fn test_vst1q_u8_x2() { + let a: [u8; 33] = [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]; + let e: [u8; 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 mut r: [u8; 32] = [0u8; 32]; + vst1q_u8_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqadd_u32() { - let a: u32x2 = u32x2::new(42, 42); - let b: u32x2 = u32x2::new(1, 2); - let e: u32x2 = u32x2::new(43, 44); - let r: u32x2 = transmute(vqadd_u32(transmute(a), transmute(b))); + unsafe fn test_vst1q_u16_x2() { + let a: [u16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let e: [u16; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let mut r: [u16; 16] = [0u16; 16]; + vst1q_u16_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqaddq_u32() { - let a: u32x4 = u32x4::new(42, 42, 42, 42); - let b: u32x4 = u32x4::new(1, 2, 3, 4); - let e: u32x4 = u32x4::new(43, 44, 45, 46); - let r: u32x4 = transmute(vqaddq_u32(transmute(a), transmute(b))); + unsafe fn test_vst1q_u32_x2() { + let a: [u32; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let e: [u32; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; + let mut r: [u32; 8] = [0u32; 8]; + vst1q_u32_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqadd_u64() { - let a: u64x1 = u64x1::new(42); - let b: u64x1 = u64x1::new(1); - let e: u64x1 = u64x1::new(43); - let r: u64x1 = transmute(vqadd_u64(transmute(a), transmute(b))); + unsafe fn test_vst1q_u64_x2() { + let a: [u64; 5] = [0, 1, 2, 3, 4]; + let e: [u64; 4] = [1, 2, 3, 4]; + let mut r: [u64; 4] = [0u64; 4]; + vst1q_u64_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vst1_u8_x3() { + let a: [u8; 25] = [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]; + let e: [u8; 24] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]; + let mut r: [u8; 24] = [0u8; 24]; + vst1_u8_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqaddq_u64() { - let a: u64x2 = u64x2::new(42, 42); - let b: u64x2 = u64x2::new(1, 2); - let e: u64x2 = u64x2::new(43, 44); - let r: u64x2 = transmute(vqaddq_u64(transmute(a), transmute(b))); + unsafe fn test_vst1_u16_x3() { + let a: [u16; 13] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + let e: [u16; 12] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + let mut r: [u16; 12] = [0u16; 12]; + vst1_u16_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqadd_s8() { - let a: i8x8 = i8x8::new(42, 42, 42, 42, 42, 42, 42, 42); - let b: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let e: i8x8 = i8x8::new(43, 44, 45, 46, 47, 48, 49, 50); - let r: i8x8 = transmute(vqadd_s8(transmute(a), transmute(b))); + unsafe fn test_vst1_u32_x3() { + let a: [u32; 7] = [0, 1, 2, 3, 4, 5, 6]; + let e: [u32; 6] = [1, 2, 3, 4, 5, 6]; + let mut r: [u32; 6] = [0u32; 6]; + vst1_u32_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqaddq_s8() { - let a: i8x16 = i8x16::new(42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42); - let b: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let e: i8x16 = i8x16::new(43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58); - let r: i8x16 = transmute(vqaddq_s8(transmute(a), transmute(b))); + unsafe fn test_vst1_u64_x3() { + let a: [u64; 4] = [0, 1, 2, 3]; + let e: [u64; 3] = [1, 2, 3]; + let mut r: [u64; 3] = [0u64; 3]; + vst1_u64_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqadd_s16() { - let a: i16x4 = i16x4::new(42, 42, 42, 42); - let b: i16x4 = i16x4::new(1, 2, 3, 4); - let e: i16x4 = i16x4::new(43, 44, 45, 46); - let r: i16x4 = transmute(vqadd_s16(transmute(a), transmute(b))); + unsafe fn test_vst1q_u8_x3() { + let a: [u8; 49] = [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, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let e: [u8; 48] = [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, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let mut r: [u8; 48] = [0u8; 48]; + vst1q_u8_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqaddq_s16() { - let a: i16x8 = i16x8::new(42, 42, 42, 42, 42, 42, 42, 42); - let b: i16x8 = i16x8::new(1, 2, 3, 4, 5, 6, 7, 8); - let e: i16x8 = i16x8::new(43, 44, 45, 46, 47, 48, 49, 50); - let r: i16x8 = transmute(vqaddq_s16(transmute(a), transmute(b))); + unsafe fn test_vst1q_u16_x3() { + let a: [u16; 25] = [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]; + let e: [u16; 24] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]; + let mut r: [u16; 24] = [0u16; 24]; + vst1q_u16_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqadd_s32() { - let a: i32x2 = i32x2::new(42, 42); - let b: i32x2 = i32x2::new(1, 2); - let e: i32x2 = i32x2::new(43, 44); - let r: i32x2 = transmute(vqadd_s32(transmute(a), transmute(b))); + unsafe fn test_vst1q_u32_x3() { + let a: [u32; 13] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + let e: [u32; 12] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + let mut r: [u32; 12] = [0u32; 12]; + vst1q_u32_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqaddq_s32() { - let a: i32x4 = i32x4::new(42, 42, 42, 42); - let b: i32x4 = i32x4::new(1, 2, 3, 4); - let e: i32x4 = i32x4::new(43, 44, 45, 46); - let r: i32x4 = transmute(vqaddq_s32(transmute(a), transmute(b))); + unsafe fn test_vst1q_u64_x3() { + let a: [u64; 7] = [0, 1, 2, 3, 4, 5, 6]; + let e: [u64; 6] = [1, 2, 3, 4, 5, 6]; + let mut r: [u64; 6] = [0u64; 6]; + vst1q_u64_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqadd_s64() { - let a: i64x1 = i64x1::new(42); - let b: i64x1 = i64x1::new(1); - let e: i64x1 = i64x1::new(43); - let r: i64x1 = transmute(vqadd_s64(transmute(a), transmute(b))); + unsafe fn test_vst1_u8_x4() { + let a: [u8; 33] = [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]; + let e: [u8; 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 mut r: [u8; 32] = [0u8; 32]; + vst1_u8_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqaddq_s64() { - let a: i64x2 = i64x2::new(42, 42); - let b: i64x2 = i64x2::new(1, 2); - let e: i64x2 = i64x2::new(43, 44); - let r: i64x2 = transmute(vqaddq_s64(transmute(a), transmute(b))); + unsafe fn test_vst1_u16_x4() { + let a: [u16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let e: [u16; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let mut r: [u16; 16] = [0u16; 16]; + vst1_u16_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_s8_x2() { - let a: [i8; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let e: [i8x8; 2] = [i8x8::new(1, 2, 3, 4, 5, 6, 7, 8), i8x8::new(9, 10, 11, 12, 13, 14, 15, 16)]; - let r: [i8x8; 2] = transmute(vld1_s8_x2(a[1..].as_ptr())); + unsafe fn test_vst1_u32_x4() { + let a: [u32; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let e: [u32; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; + let mut r: [u32; 8] = [0u32; 8]; + vst1_u32_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_s16_x2() { - let a: [i16; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; - let e: [i16x4; 2] = [i16x4::new(1, 2, 3, 4), i16x4::new(5, 6, 7, 8)]; - let r: [i16x4; 2] = transmute(vld1_s16_x2(a[1..].as_ptr())); + unsafe fn test_vst1_u64_x4() { + let a: [u64; 5] = [0, 1, 2, 3, 4]; + let e: [u64; 4] = [1, 2, 3, 4]; + let mut r: [u64; 4] = [0u64; 4]; + vst1_u64_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_s32_x2() { - let a: [i32; 5] = [0, 1, 2, 3, 4]; - let e: [i32x2; 2] = [i32x2::new(1, 2), i32x2::new(3, 4)]; - let r: [i32x2; 2] = transmute(vld1_s32_x2(a[1..].as_ptr())); + unsafe fn test_vst1q_u8_x4() { + let a: [u8; 65] = [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, 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 e: [u8; 64] = [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, 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 mut r: [u8; 64] = [0u8; 64]; + vst1q_u8_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_s64_x2() { - let a: [i64; 3] = [0, 1, 2]; - let e: [i64x1; 2] = [i64x1::new(1), i64x1::new(2)]; - let r: [i64x1; 2] = transmute(vld1_s64_x2(a[1..].as_ptr())); + unsafe fn test_vst1q_u16_x4() { + let a: [u16; 33] = [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]; + let e: [u16; 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 mut r: [u16; 32] = [0u16; 32]; + vst1q_u16_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s8_x2() { - let a: [i8; 33] = [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]; - let e: [i8x16; 2] = [i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), i8x16::new(17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32)]; - let r: [i8x16; 2] = transmute(vld1q_s8_x2(a[1..].as_ptr())); + unsafe fn test_vst1q_u32_x4() { + let a: [u32; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let e: [u32; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let mut r: [u32; 16] = [0u32; 16]; + vst1q_u32_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s16_x2() { - let a: [i16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let e: [i16x8; 2] = [i16x8::new(1, 2, 3, 4, 5, 6, 7, 8), i16x8::new(9, 10, 11, 12, 13, 14, 15, 16)]; - let r: [i16x8; 2] = transmute(vld1q_s16_x2(a[1..].as_ptr())); + unsafe fn test_vst1q_u64_x4() { + let a: [u64; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let e: [u64; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; + let mut r: [u64; 8] = [0u64; 8]; + vst1q_u64_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s32_x2() { - let a: [i32; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; - let e: [i32x4; 2] = [i32x4::new(1, 2, 3, 4), i32x4::new(5, 6, 7, 8)]; - let r: [i32x4; 2] = transmute(vld1q_s32_x2(a[1..].as_ptr())); + unsafe fn test_vst1_p8_x2() { + let a: [u8; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let e: [u8; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let mut r: [u8; 16] = [0u8; 16]; + vst1_p8_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s64_x2() { - let a: [i64; 5] = [0, 1, 2, 3, 4]; - let e: [i64x2; 2] = [i64x2::new(1, 2), i64x2::new(3, 4)]; - let r: [i64x2; 2] = transmute(vld1q_s64_x2(a[1..].as_ptr())); + unsafe fn test_vst1_p8_x3() { + let a: [u8; 25] = [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]; + let e: [u8; 24] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]; + let mut r: [u8; 24] = [0u8; 24]; + vst1_p8_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_s8_x3() { - let a: [i8; 25] = [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]; - let e: [i8x8; 3] = [i8x8::new(1, 2, 3, 4, 5, 6, 7, 8), i8x8::new(9, 10, 11, 12, 13, 14, 15, 16), i8x8::new(17, 18, 19, 20, 21, 22, 23, 24)]; - let r: [i8x8; 3] = transmute(vld1_s8_x3(a[1..].as_ptr())); + unsafe fn test_vst1_p8_x4() { + let a: [u8; 33] = [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]; + let e: [u8; 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 mut r: [u8; 32] = [0u8; 32]; + vst1_p8_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_s16_x3() { - let a: [i16; 13] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; - let e: [i16x4; 3] = [i16x4::new(1, 2, 3, 4), i16x4::new(5, 6, 7, 8), i16x4::new(9, 10, 11, 12)]; - let r: [i16x4; 3] = transmute(vld1_s16_x3(a[1..].as_ptr())); + unsafe fn test_vst1q_p8_x2() { + let a: [u8; 33] = [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]; + let e: [u8; 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 mut r: [u8; 32] = [0u8; 32]; + vst1q_p8_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_s32_x3() { - let a: [i32; 7] = [0, 1, 2, 3, 4, 5, 6]; - let e: [i32x2; 3] = [i32x2::new(1, 2), i32x2::new(3, 4), i32x2::new(5, 6)]; - let r: [i32x2; 3] = transmute(vld1_s32_x3(a[1..].as_ptr())); + unsafe fn test_vst1q_p8_x3() { + let a: [u8; 49] = [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, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let e: [u8; 48] = [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, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let mut r: [u8; 48] = [0u8; 48]; + vst1q_p8_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_s64_x3() { - let a: [i64; 4] = [0, 1, 2, 3]; - let e: [i64x1; 3] = [i64x1::new(1), i64x1::new(2), i64x1::new(3)]; - let r: [i64x1; 3] = transmute(vld1_s64_x3(a[1..].as_ptr())); + unsafe fn test_vst1q_p8_x4() { + let a: [u8; 65] = [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, 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 e: [u8; 64] = [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, 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 mut r: [u8; 64] = [0u8; 64]; + vst1q_p8_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s8_x3() { - let a: [i8; 49] = [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, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let e: [i8x16; 3] = [i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), i8x16::new(17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32), i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)]; - let r: [i8x16; 3] = transmute(vld1q_s8_x3(a[1..].as_ptr())); + unsafe fn test_vst1_p16_x2() { + let a: [u16; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let e: [u16; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; + let mut r: [u16; 8] = [0u16; 8]; + vst1_p16_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s16_x3() { - let a: [i16; 25] = [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]; - let e: [i16x8; 3] = [i16x8::new(1, 2, 3, 4, 5, 6, 7, 8), i16x8::new(9, 10, 11, 12, 13, 14, 15, 16), i16x8::new(17, 18, 19, 20, 21, 22, 23, 24)]; - let r: [i16x8; 3] = transmute(vld1q_s16_x3(a[1..].as_ptr())); + unsafe fn test_vst1_p16_x3() { + let a: [u16; 13] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + let e: [u16; 12] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + let mut r: [u16; 12] = [0u16; 12]; + vst1_p16_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s32_x3() { - let a: [i32; 13] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; - let e: [i32x4; 3] = [i32x4::new(1, 2, 3, 4), i32x4::new(5, 6, 7, 8), i32x4::new(9, 10, 11, 12)]; - let r: [i32x4; 3] = transmute(vld1q_s32_x3(a[1..].as_ptr())); + unsafe fn test_vst1_p16_x4() { + let a: [u16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let e: [u16; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let mut r: [u16; 16] = [0u16; 16]; + vst1_p16_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s64_x3() { - let a: [i64; 7] = [0, 1, 2, 3, 4, 5, 6]; - let e: [i64x2; 3] = [i64x2::new(1, 2), i64x2::new(3, 4), i64x2::new(5, 6)]; - let r: [i64x2; 3] = transmute(vld1q_s64_x3(a[1..].as_ptr())); + unsafe fn test_vst1q_p16_x2() { + let a: [u16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let e: [u16; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let mut r: [u16; 16] = [0u16; 16]; + vst1q_p16_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_s8_x4() { - let a: [i8; 33] = [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]; - let e: [i8x8; 4] = [i8x8::new(1, 2, 3, 4, 5, 6, 7, 8), i8x8::new(9, 10, 11, 12, 13, 14, 15, 16), i8x8::new(17, 18, 19, 20, 21, 22, 23, 24), i8x8::new(25, 26, 27, 28, 29, 30, 31, 32)]; - let r: [i8x8; 4] = transmute(vld1_s8_x4(a[1..].as_ptr())); + unsafe fn test_vst1q_p16_x3() { + let a: [u16; 25] = [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]; + let e: [u16; 24] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]; + let mut r: [u16; 24] = [0u16; 24]; + vst1q_p16_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_s16_x4() { - let a: [i16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let e: [i16x4; 4] = [i16x4::new(1, 2, 3, 4), i16x4::new(5, 6, 7, 8), i16x4::new(9, 10, 11, 12), i16x4::new(13, 14, 15, 16)]; - let r: [i16x4; 4] = transmute(vld1_s16_x4(a[1..].as_ptr())); + unsafe fn test_vst1q_p16_x4() { + let a: [u16; 33] = [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]; + let e: [u16; 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 mut r: [u16; 32] = [0u16; 32]; + vst1q_p16_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_s32_x4() { - let a: [i32; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; - let e: [i32x2; 4] = [i32x2::new(1, 2), i32x2::new(3, 4), i32x2::new(5, 6), i32x2::new(7, 8)]; - let r: [i32x2; 4] = transmute(vld1_s32_x4(a[1..].as_ptr())); + unsafe fn test_vst1_p64_x2() { + let a: [u64; 3] = [0, 1, 2]; + let e: [u64; 2] = [1, 2]; + let mut r: [u64; 2] = [0u64; 2]; + vst1_p64_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_s64_x4() { - let a: [i64; 5] = [0, 1, 2, 3, 4]; - let e: [i64x1; 4] = [i64x1::new(1), i64x1::new(2), i64x1::new(3), i64x1::new(4)]; - let r: [i64x1; 4] = transmute(vld1_s64_x4(a[1..].as_ptr())); + unsafe fn test_vst1_p64_x3() { + let a: [u64; 4] = [0, 1, 2, 3]; + let e: [u64; 3] = [1, 2, 3]; + let mut r: [u64; 3] = [0u64; 3]; + vst1_p64_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s8_x4() { - let a: [i8; 65] = [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, 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 e: [i8x16; 4] = [i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), i8x16::new(17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32), i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), i8x16::new(17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32)]; - let r: [i8x16; 4] = transmute(vld1q_s8_x4(a[1..].as_ptr())); + unsafe fn test_vst1_p64_x4() { + let a: [u64; 5] = [0, 1, 2, 3, 4]; + let e: [u64; 4] = [1, 2, 3, 4]; + let mut r: [u64; 4] = [0u64; 4]; + vst1_p64_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s16_x4() { - let a: [i16; 33] = [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]; - let e: [i16x8; 4] = [i16x8::new(1, 2, 3, 4, 5, 6, 7, 8), i16x8::new(9, 10, 11, 12, 13, 14, 15, 16), i16x8::new(17, 18, 19, 20, 21, 22, 23, 24), i16x8::new(25, 26, 27, 28, 29, 30, 31, 32)]; - let r: [i16x8; 4] = transmute(vld1q_s16_x4(a[1..].as_ptr())); + unsafe fn test_vst1q_p64_x2() { + let a: [u64; 5] = [0, 1, 2, 3, 4]; + let e: [u64; 4] = [1, 2, 3, 4]; + let mut r: [u64; 4] = [0u64; 4]; + vst1q_p64_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s32_x4() { - let a: [i32; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let e: [i32x4; 4] = [i32x4::new(1, 2, 3, 4), i32x4::new(5, 6, 7, 8), i32x4::new(9, 10, 11, 12), i32x4::new(13, 14, 15, 16)]; - let r: [i32x4; 4] = transmute(vld1q_s32_x4(a[1..].as_ptr())); + unsafe fn test_vst1q_p64_x3() { + let a: [u64; 7] = [0, 1, 2, 3, 4, 5, 6]; + let e: [u64; 6] = [1, 2, 3, 4, 5, 6]; + let mut r: [u64; 6] = [0u64; 6]; + vst1q_p64_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s64_x4() { - let a: [i64; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; - let e: [i64x2; 4] = [i64x2::new(1, 2), i64x2::new(3, 4), i64x2::new(5, 6), i64x2::new(7, 8)]; - let r: [i64x2; 4] = transmute(vld1q_s64_x4(a[1..].as_ptr())); + unsafe fn test_vst1q_p64_x4() { + let a: [u64; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let e: [u64; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; + let mut r: [u64; 8] = [0u64; 8]; + vst1q_p64_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_u8_x2() { - let a: [u8; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let e: [u8x8; 2] = [u8x8::new(1, 2, 3, 4, 5, 6, 7, 8), u8x8::new(9, 10, 11, 12, 13, 14, 15, 16)]; - let r: [u8x8; 2] = transmute(vld1_u8_x2(a[1..].as_ptr())); + unsafe fn test_vst1_f32_x2() { + let a: [f32; 5] = [0., 1., 2., 3., 4.]; + let e: [f32; 4] = [1., 2., 3., 4.]; + let mut r: [f32; 4] = [0f32; 4]; + vst1_f32_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_u16_x2() { - let a: [u16; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; - let e: [u16x4; 2] = [u16x4::new(1, 2, 3, 4), u16x4::new(5, 6, 7, 8)]; - let r: [u16x4; 2] = transmute(vld1_u16_x2(a[1..].as_ptr())); + unsafe fn test_vst1q_f32_x2() { + let a: [f32; 9] = [0., 1., 2., 3., 4., 5., 6., 7., 8.]; + let e: [f32; 8] = [1., 2., 3., 4., 5., 6., 7., 8.]; + let mut r: [f32; 8] = [0f32; 8]; + vst1q_f32_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_u32_x2() { - let a: [u32; 5] = [0, 1, 2, 3, 4]; - let e: [u32x2; 2] = [u32x2::new(1, 2), u32x2::new(3, 4)]; - let r: [u32x2; 2] = transmute(vld1_u32_x2(a[1..].as_ptr())); + unsafe fn test_vst1_f32_x3() { + let a: [f32; 7] = [0., 1., 2., 3., 4., 5., 6.]; + let e: [f32; 6] = [1., 2., 3., 4., 5., 6.]; + let mut r: [f32; 6] = [0f32; 6]; + vst1_f32_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_u64_x2() { - let a: [u64; 3] = [0, 1, 2]; - let e: [u64x1; 2] = [u64x1::new(1), u64x1::new(2)]; - let r: [u64x1; 2] = transmute(vld1_u64_x2(a[1..].as_ptr())); + unsafe fn test_vst1q_f32_x3() { + let a: [f32; 13] = [0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; + let e: [f32; 12] = [1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; + let mut r: [f32; 12] = [0f32; 12]; + vst1q_f32_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u8_x2() { - let a: [u8; 33] = [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]; - let e: [u8x16; 2] = [u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), u8x16::new(17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32)]; - let r: [u8x16; 2] = transmute(vld1q_u8_x2(a[1..].as_ptr())); + unsafe fn test_vst1_f32_x4() { + let a: [f32; 9] = [0., 1., 2., 3., 4., 5., 6., 7., 8.]; + let e: [f32; 8] = [1., 2., 3., 4., 5., 6., 7., 8.]; + let mut r: [f32; 8] = [0f32; 8]; + vst1_f32_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u16_x2() { - let a: [u16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let e: [u16x8; 2] = [u16x8::new(1, 2, 3, 4, 5, 6, 7, 8), u16x8::new(9, 10, 11, 12, 13, 14, 15, 16)]; - let r: [u16x8; 2] = transmute(vld1q_u16_x2(a[1..].as_ptr())); + unsafe fn test_vst1q_f32_x4() { + let a: [f32; 17] = [0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16.]; + let e: [f32; 16] = [1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16.]; + let mut r: [f32; 16] = [0f32; 16]; + vst1q_f32_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u32_x2() { - let a: [u32; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; - let e: [u32x4; 2] = [u32x4::new(1, 2, 3, 4), u32x4::new(5, 6, 7, 8)]; - let r: [u32x4; 2] = transmute(vld1q_u32_x2(a[1..].as_ptr())); + unsafe fn test_vst2_s8() { + let a: [i8; 17] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9]; + let e: [i8; 16] = [1, 2, 2, 3, 2, 4, 3, 5, 2, 6, 3, 7, 4, 8, 5, 9]; + let mut r: [i8; 16] = [0i8; 16]; + vst2_s8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u64_x2() { - let a: [u64; 5] = [0, 1, 2, 3, 4]; - let e: [u64x2; 2] = [u64x2::new(1, 2), u64x2::new(3, 4)]; - let r: [u64x2; 2] = transmute(vld1q_u64_x2(a[1..].as_ptr())); + unsafe fn test_vst2_s16() { + let a: [i16; 9] = [0, 1, 2, 2, 3, 2, 3, 4, 5]; + let e: [i16; 8] = [1, 2, 2, 3, 2, 4, 3, 5]; + let mut r: [i16; 8] = [0i16; 8]; + vst2_s16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_u8_x3() { - let a: [u8; 25] = [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]; - let e: [u8x8; 3] = [u8x8::new(1, 2, 3, 4, 5, 6, 7, 8), u8x8::new(9, 10, 11, 12, 13, 14, 15, 16), u8x8::new(17, 18, 19, 20, 21, 22, 23, 24)]; - let r: [u8x8; 3] = transmute(vld1_u8_x3(a[1..].as_ptr())); + unsafe fn test_vst2_s32() { + let a: [i32; 5] = [0, 1, 2, 2, 3]; + let e: [i32; 4] = [1, 2, 2, 3]; + let mut r: [i32; 4] = [0i32; 4]; + vst2_s32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_u16_x3() { - let a: [u16; 13] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; - let e: [u16x4; 3] = [u16x4::new(1, 2, 3, 4), u16x4::new(5, 6, 7, 8), u16x4::new(9, 10, 11, 12)]; - let r: [u16x4; 3] = transmute(vld1_u16_x3(a[1..].as_ptr())); + unsafe fn test_vst2q_s8() { + let a: [i8; 33] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]; + let e: [i8; 32] = [1, 2, 2, 3, 2, 4, 3, 5, 2, 6, 3, 7, 4, 8, 5, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15, 8, 16, 9, 17]; + let mut r: [i8; 32] = [0i8; 32]; + vst2q_s8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_u32_x3() { - let a: [u32; 7] = [0, 1, 2, 3, 4, 5, 6]; - let e: [u32x2; 3] = [u32x2::new(1, 2), u32x2::new(3, 4), u32x2::new(5, 6)]; - let r: [u32x2; 3] = transmute(vld1_u32_x3(a[1..].as_ptr())); + unsafe fn test_vst2q_s16() { + let a: [i16; 17] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9]; + let e: [i16; 16] = [1, 2, 2, 3, 2, 4, 3, 5, 2, 6, 3, 7, 4, 8, 5, 9]; + let mut r: [i16; 16] = [0i16; 16]; + vst2q_s16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_u64_x3() { - let a: [u64; 4] = [0, 1, 2, 3]; - let e: [u64x1; 3] = [u64x1::new(1), u64x1::new(2), u64x1::new(3)]; - let r: [u64x1; 3] = transmute(vld1_u64_x3(a[1..].as_ptr())); + unsafe fn test_vst2q_s32() { + let a: [i32; 9] = [0, 1, 2, 2, 3, 2, 3, 4, 5]; + let e: [i32; 8] = [1, 2, 2, 3, 2, 4, 3, 5]; + let mut r: [i32; 8] = [0i32; 8]; + vst2q_s32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u8_x3() { - let a: [u8; 49] = [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, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let e: [u8x16; 3] = [u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), u8x16::new(17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32), u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)]; - let r: [u8x16; 3] = transmute(vld1q_u8_x3(a[1..].as_ptr())); + unsafe fn test_vst2_s64() { + let a: [i64; 3] = [0, 1, 2]; + let e: [i64; 2] = [1, 2]; + let mut r: [i64; 2] = [0i64; 2]; + vst2_s64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u16_x3() { - let a: [u16; 25] = [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]; - let e: [u16x8; 3] = [u16x8::new(1, 2, 3, 4, 5, 6, 7, 8), u16x8::new(9, 10, 11, 12, 13, 14, 15, 16), u16x8::new(17, 18, 19, 20, 21, 22, 23, 24)]; - let r: [u16x8; 3] = transmute(vld1q_u16_x3(a[1..].as_ptr())); + unsafe fn test_vst2_u8() { + let a: [u8; 17] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9]; + let e: [u8; 16] = [1, 2, 2, 3, 2, 4, 3, 5, 2, 6, 3, 7, 4, 8, 5, 9]; + let mut r: [u8; 16] = [0u8; 16]; + vst2_u8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u32_x3() { - let a: [u32; 13] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; - let e: [u32x4; 3] = [u32x4::new(1, 2, 3, 4), u32x4::new(5, 6, 7, 8), u32x4::new(9, 10, 11, 12)]; - let r: [u32x4; 3] = transmute(vld1q_u32_x3(a[1..].as_ptr())); + unsafe fn test_vst2_u16() { + let a: [u16; 9] = [0, 1, 2, 2, 3, 2, 3, 4, 5]; + let e: [u16; 8] = [1, 2, 2, 3, 2, 4, 3, 5]; + let mut r: [u16; 8] = [0u16; 8]; + vst2_u16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u64_x3() { - let a: [u64; 7] = [0, 1, 2, 3, 4, 5, 6]; - let e: [u64x2; 3] = [u64x2::new(1, 2), u64x2::new(3, 4), u64x2::new(5, 6)]; - let r: [u64x2; 3] = transmute(vld1q_u64_x3(a[1..].as_ptr())); + unsafe fn test_vst2_u32() { + let a: [u32; 5] = [0, 1, 2, 2, 3]; + let e: [u32; 4] = [1, 2, 2, 3]; + let mut r: [u32; 4] = [0u32; 4]; + vst2_u32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_u8_x4() { - let a: [u8; 33] = [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]; - let e: [u8x8; 4] = [u8x8::new(1, 2, 3, 4, 5, 6, 7, 8), u8x8::new(9, 10, 11, 12, 13, 14, 15, 16), u8x8::new(17, 18, 19, 20, 21, 22, 23, 24), u8x8::new(25, 26, 27, 28, 29, 30, 31, 32)]; - let r: [u8x8; 4] = transmute(vld1_u8_x4(a[1..].as_ptr())); + unsafe fn test_vst2q_u8() { + let a: [u8; 33] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]; + let e: [u8; 32] = [1, 2, 2, 3, 2, 4, 3, 5, 2, 6, 3, 7, 4, 8, 5, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15, 8, 16, 9, 17]; + let mut r: [u8; 32] = [0u8; 32]; + vst2q_u8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_u16_x4() { - let a: [u16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let e: [u16x4; 4] = [u16x4::new(1, 2, 3, 4), u16x4::new(5, 6, 7, 8), u16x4::new(9, 10, 11, 12), u16x4::new(13, 14, 15, 16)]; - let r: [u16x4; 4] = transmute(vld1_u16_x4(a[1..].as_ptr())); + unsafe fn test_vst2q_u16() { + let a: [u16; 17] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9]; + let e: [u16; 16] = [1, 2, 2, 3, 2, 4, 3, 5, 2, 6, 3, 7, 4, 8, 5, 9]; + let mut r: [u16; 16] = [0u16; 16]; + vst2q_u16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_u32_x4() { - let a: [u32; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; - let e: [u32x2; 4] = [u32x2::new(1, 2), u32x2::new(3, 4), u32x2::new(5, 6), u32x2::new(7, 8)]; - let r: [u32x2; 4] = transmute(vld1_u32_x4(a[1..].as_ptr())); + unsafe fn test_vst2q_u32() { + let a: [u32; 9] = [0, 1, 2, 2, 3, 2, 3, 4, 5]; + let e: [u32; 8] = [1, 2, 2, 3, 2, 4, 3, 5]; + let mut r: [u32; 8] = [0u32; 8]; + vst2q_u32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_u64_x4() { - let a: [u64; 5] = [0, 1, 2, 3, 4]; - let e: [u64x1; 4] = [u64x1::new(1), u64x1::new(2), u64x1::new(3), u64x1::new(4)]; - let r: [u64x1; 4] = transmute(vld1_u64_x4(a[1..].as_ptr())); + unsafe fn test_vst2_p8() { + let a: [u8; 17] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9]; + let e: [u8; 16] = [1, 2, 2, 3, 2, 4, 3, 5, 2, 6, 3, 7, 4, 8, 5, 9]; + let mut r: [u8; 16] = [0u8; 16]; + vst2_p8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u8_x4() { - let a: [u8; 65] = [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, 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 e: [u8x16; 4] = [u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), u8x16::new(17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32), u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), u8x16::new(17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32)]; - let r: [u8x16; 4] = transmute(vld1q_u8_x4(a[1..].as_ptr())); + unsafe fn test_vst2_p16() { + let a: [u16; 9] = [0, 1, 2, 2, 3, 2, 3, 4, 5]; + let e: [u16; 8] = [1, 2, 2, 3, 2, 4, 3, 5]; + let mut r: [u16; 8] = [0u16; 8]; + vst2_p16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u16_x4() { - let a: [u16; 33] = [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]; - let e: [u16x8; 4] = [u16x8::new(1, 2, 3, 4, 5, 6, 7, 8), u16x8::new(9, 10, 11, 12, 13, 14, 15, 16), u16x8::new(17, 18, 19, 20, 21, 22, 23, 24), u16x8::new(25, 26, 27, 28, 29, 30, 31, 32)]; - let r: [u16x8; 4] = transmute(vld1q_u16_x4(a[1..].as_ptr())); + unsafe fn test_vst2q_p8() { + let a: [u8; 33] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]; + let e: [u8; 32] = [1, 2, 2, 3, 2, 4, 3, 5, 2, 6, 3, 7, 4, 8, 5, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15, 8, 16, 9, 17]; + let mut r: [u8; 32] = [0u8; 32]; + vst2q_p8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u32_x4() { - let a: [u32; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let e: [u32x4; 4] = [u32x4::new(1, 2, 3, 4), u32x4::new(5, 6, 7, 8), u32x4::new(9, 10, 11, 12), u32x4::new(13, 14, 15, 16)]; - let r: [u32x4; 4] = transmute(vld1q_u32_x4(a[1..].as_ptr())); + unsafe fn test_vst2q_p16() { + let a: [u16; 17] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9]; + let e: [u16; 16] = [1, 2, 2, 3, 2, 4, 3, 5, 2, 6, 3, 7, 4, 8, 5, 9]; + let mut r: [u16; 16] = [0u16; 16]; + vst2q_p16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u64_x4() { - let a: [u64; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; - let e: [u64x2; 4] = [u64x2::new(1, 2), u64x2::new(3, 4), u64x2::new(5, 6), u64x2::new(7, 8)]; - let r: [u64x2; 4] = transmute(vld1q_u64_x4(a[1..].as_ptr())); + unsafe fn test_vst2_u64() { + let a: [u64; 3] = [0, 1, 2]; + let e: [u64; 2] = [1, 2]; + let mut r: [u64; 2] = [0u64; 2]; + vst2_u64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_p8_x2() { - let a: [u8; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let e: [i8x8; 2] = [i8x8::new(1, 2, 3, 4, 5, 6, 7, 8), i8x8::new(9, 10, 11, 12, 13, 14, 15, 16)]; - let r: [i8x8; 2] = transmute(vld1_p8_x2(a[1..].as_ptr())); + unsafe fn test_vst2_p64() { + let a: [u64; 3] = [0, 1, 2]; + let e: [u64; 2] = [1, 2]; + let mut r: [u64; 2] = [0u64; 2]; + vst2_p64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_p8_x3() { - let a: [u8; 25] = [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]; - let e: [i8x8; 3] = [i8x8::new(1, 2, 3, 4, 5, 6, 7, 8), i8x8::new(9, 10, 11, 12, 13, 14, 15, 16), i8x8::new(17, 18, 19, 20, 21, 22, 23, 24)]; - let r: [i8x8; 3] = transmute(vld1_p8_x3(a[1..].as_ptr())); + unsafe fn test_vst2_f32() { + let a: [f32; 5] = [0., 1., 2., 2., 3.]; + let e: [f32; 4] = [1., 2., 2., 3.]; + let mut r: [f32; 4] = [0f32; 4]; + vst2_f32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_p8_x4() { - let a: [u8; 33] = [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]; - let e: [i8x8; 4] = [i8x8::new(1, 2, 3, 4, 5, 6, 7, 8), i8x8::new(9, 10, 11, 12, 13, 14, 15, 16), i8x8::new(17, 18, 19, 20, 21, 22, 23, 24), i8x8::new(25, 26, 27, 28, 29, 30, 31, 32)]; - let r: [i8x8; 4] = transmute(vld1_p8_x4(a[1..].as_ptr())); + unsafe fn test_vst2q_f32() { + let a: [f32; 9] = [0., 1., 2., 2., 3., 2., 3., 4., 5.]; + let e: [f32; 8] = [1., 2., 2., 3., 2., 4., 3., 5.]; + let mut r: [f32; 8] = [0f32; 8]; + vst2q_f32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_p8_x2() { - let a: [u8; 33] = [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]; - let e: [i8x16; 2] = [i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), i8x16::new(17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32)]; - let r: [i8x16; 2] = transmute(vld1q_p8_x2(a[1..].as_ptr())); + unsafe fn test_vst2_lane_s8() { + let a: [i8; 17] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9]; + let e: [i8; 16] = [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + let mut r: [i8; 16] = [0i8; 16]; + vst2_lane_s8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_p8_x3() { - let a: [u8; 49] = [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, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let e: [i8x16; 3] = [i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), i8x16::new(17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32), i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)]; - let r: [i8x16; 3] = transmute(vld1q_p8_x3(a[1..].as_ptr())); + unsafe fn test_vst2_lane_s16() { + let a: [i16; 9] = [0, 1, 2, 2, 3, 2, 3, 4, 5]; + let e: [i16; 8] = [1, 2, 0, 0, 0, 0, 0, 0]; + let mut r: [i16; 8] = [0i16; 8]; + vst2_lane_s16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_p8_x4() { - let a: [u8; 65] = [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, 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 e: [i8x16; 4] = [i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), i8x16::new(17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32), i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), i8x16::new(17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32)]; - let r: [i8x16; 4] = transmute(vld1q_p8_x4(a[1..].as_ptr())); + unsafe fn test_vst2_lane_s32() { + let a: [i32; 5] = [0, 1, 2, 2, 3]; + let e: [i32; 4] = [1, 2, 0, 0]; + let mut r: [i32; 4] = [0i32; 4]; + vst2_lane_s32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_p16_x2() { - let a: [u16; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; - let e: [i16x4; 2] = [i16x4::new(1, 2, 3, 4), i16x4::new(5, 6, 7, 8)]; - let r: [i16x4; 2] = transmute(vld1_p16_x2(a[1..].as_ptr())); + unsafe fn test_vst2q_lane_s16() { + let a: [i16; 17] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9]; + let e: [i16; 16] = [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + let mut r: [i16; 16] = [0i16; 16]; + vst2q_lane_s16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_p16_x3() { - let a: [u16; 13] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; - let e: [i16x4; 3] = [i16x4::new(1, 2, 3, 4), i16x4::new(5, 6, 7, 8), i16x4::new(9, 10, 11, 12)]; - let r: [i16x4; 3] = transmute(vld1_p16_x3(a[1..].as_ptr())); + unsafe fn test_vst2q_lane_s32() { + let a: [i32; 9] = [0, 1, 2, 2, 3, 2, 3, 4, 5]; + let e: [i32; 8] = [1, 2, 0, 0, 0, 0, 0, 0]; + let mut r: [i32; 8] = [0i32; 8]; + vst2q_lane_s32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_p16_x4() { - let a: [u16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let e: [i16x4; 4] = [i16x4::new(1, 2, 3, 4), i16x4::new(5, 6, 7, 8), i16x4::new(9, 10, 11, 12), i16x4::new(13, 14, 15, 16)]; - let r: [i16x4; 4] = transmute(vld1_p16_x4(a[1..].as_ptr())); + unsafe fn test_vst2_lane_u8() { + let a: [u8; 17] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9]; + let e: [u8; 16] = [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + let mut r: [u8; 16] = [0u8; 16]; + vst2_lane_u8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_p16_x2() { - let a: [u16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let e: [i16x8; 2] = [i16x8::new(1, 2, 3, 4, 5, 6, 7, 8), i16x8::new(9, 10, 11, 12, 13, 14, 15, 16)]; - let r: [i16x8; 2] = transmute(vld1q_p16_x2(a[1..].as_ptr())); + unsafe fn test_vst2_lane_u16() { + let a: [u16; 9] = [0, 1, 2, 2, 3, 2, 3, 4, 5]; + let e: [u16; 8] = [1, 2, 0, 0, 0, 0, 0, 0]; + let mut r: [u16; 8] = [0u16; 8]; + vst2_lane_u16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_p16_x3() { - let a: [u16; 25] = [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]; - let e: [i16x8; 3] = [i16x8::new(1, 2, 3, 4, 5, 6, 7, 8), i16x8::new(9, 10, 11, 12, 13, 14, 15, 16), i16x8::new(17, 18, 19, 20, 21, 22, 23, 24)]; - let r: [i16x8; 3] = transmute(vld1q_p16_x3(a[1..].as_ptr())); + unsafe fn test_vst2_lane_u32() { + let a: [u32; 5] = [0, 1, 2, 2, 3]; + let e: [u32; 4] = [1, 2, 0, 0]; + let mut r: [u32; 4] = [0u32; 4]; + vst2_lane_u32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_p16_x4() { - let a: [u16; 33] = [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]; - let e: [i16x8; 4] = [i16x8::new(1, 2, 3, 4, 5, 6, 7, 8), i16x8::new(9, 10, 11, 12, 13, 14, 15, 16), i16x8::new(17, 18, 19, 20, 21, 22, 23, 24), i16x8::new(25, 26, 27, 28, 29, 30, 31, 32)]; - let r: [i16x8; 4] = transmute(vld1q_p16_x4(a[1..].as_ptr())); + unsafe fn test_vst2q_lane_u16() { + let a: [u16; 17] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9]; + let e: [u16; 16] = [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + let mut r: [u16; 16] = [0u16; 16]; + vst2q_lane_u16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_p64_x2() { - let a: [u64; 3] = [0, 1, 2]; - let e: [i64x1; 2] = [i64x1::new(1), i64x1::new(2)]; - let r: [i64x1; 2] = transmute(vld1_p64_x2(a[1..].as_ptr())); + unsafe fn test_vst2q_lane_u32() { + let a: [u32; 9] = [0, 1, 2, 2, 3, 2, 3, 4, 5]; + let e: [u32; 8] = [1, 2, 0, 0, 0, 0, 0, 0]; + let mut r: [u32; 8] = [0u32; 8]; + vst2q_lane_u32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_p64_x3() { - let a: [u64; 4] = [0, 1, 2, 3]; - let e: [i64x1; 3] = [i64x1::new(1), i64x1::new(2), i64x1::new(3)]; - let r: [i64x1; 3] = transmute(vld1_p64_x3(a[1..].as_ptr())); + unsafe fn test_vst2_lane_p8() { + let a: [u8; 17] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9]; + let e: [u8; 16] = [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + let mut r: [u8; 16] = [0u8; 16]; + vst2_lane_p8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_p64_x4() { - let a: [u64; 5] = [0, 1, 2, 3, 4]; - let e: [i64x1; 4] = [i64x1::new(1), i64x1::new(2), i64x1::new(3), i64x1::new(4)]; - let r: [i64x1; 4] = transmute(vld1_p64_x4(a[1..].as_ptr())); + unsafe fn test_vst2_lane_p16() { + let a: [u16; 9] = [0, 1, 2, 2, 3, 2, 3, 4, 5]; + let e: [u16; 8] = [1, 2, 0, 0, 0, 0, 0, 0]; + let mut r: [u16; 8] = [0u16; 8]; + vst2_lane_p16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_p64_x2() { - let a: [u64; 5] = [0, 1, 2, 3, 4]; - let e: [i64x2; 2] = [i64x2::new(1, 2), i64x2::new(3, 4)]; - let r: [i64x2; 2] = transmute(vld1q_p64_x2(a[1..].as_ptr())); + unsafe fn test_vst2q_lane_p16() { + let a: [u16; 17] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9]; + let e: [u16; 16] = [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + let mut r: [u16; 16] = [0u16; 16]; + vst2q_lane_p16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_p64_x3() { - let a: [u64; 7] = [0, 1, 2, 3, 4, 5, 6]; - let e: [i64x2; 3] = [i64x2::new(1, 2), i64x2::new(3, 4), i64x2::new(5, 6)]; - let r: [i64x2; 3] = transmute(vld1q_p64_x3(a[1..].as_ptr())); + unsafe fn test_vst2_lane_f32() { + let a: [f32; 5] = [0., 1., 2., 2., 3.]; + let e: [f32; 4] = [1., 2., 0., 0.]; + let mut r: [f32; 4] = [0f32; 4]; + vst2_lane_f32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_p64_x4() { - let a: [u64; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; - let e: [i64x2; 4] = [i64x2::new(1, 2), i64x2::new(3, 4), i64x2::new(5, 6), i64x2::new(7, 8)]; - let r: [i64x2; 4] = transmute(vld1q_p64_x4(a[1..].as_ptr())); + unsafe fn test_vst2q_lane_f32() { + let a: [f32; 9] = [0., 1., 2., 2., 3., 2., 3., 4., 5.]; + let e: [f32; 8] = [1., 2., 0., 0., 0., 0., 0., 0.]; + let mut r: [f32; 8] = [0f32; 8]; + vst2q_lane_f32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } - #[simd_test(enable = "neon")] - unsafe fn test_vld1_f32_x2() { - let a: [f32; 5] = [0., 1., 2., 3., 4.]; - let e: [f32x2; 2] = [f32x2::new(1., 2.), f32x2::new(3., 4.)]; - let r: [f32x2; 2] = transmute(vld1_f32_x2(a[1..].as_ptr())); + #[simd_test(enable = "neon")] + unsafe fn test_vst3_s8() { + let a: [i8; 25] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16]; + let e: [i8; 24] = [1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8, 2, 13, 13, 4, 14, 14, 7, 15, 15, 8, 16, 16]; + let mut r: [i8; 24] = [0i8; 24]; + vst3_s8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_f32_x2() { - let a: [f32; 9] = [0., 1., 2., 3., 4., 5., 6., 7., 8.]; - let e: [f32x4; 2] = [f32x4::new(1., 2., 3., 4.), f32x4::new(5., 6., 7., 8.)]; - let r: [f32x4; 2] = transmute(vld1q_f32_x2(a[1..].as_ptr())); + unsafe fn test_vst3_s16() { + let a: [i16; 13] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8]; + let e: [i16; 12] = [1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8]; + let mut r: [i16; 12] = [0i16; 12]; + vst3_s16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_f32_x3() { - let a: [f32; 7] = [0., 1., 2., 3., 4., 5., 6.]; - let e: [f32x2; 3] = [f32x2::new(1., 2.), f32x2::new(3., 4.), f32x2::new(5., 6.)]; - let r: [f32x2; 3] = transmute(vld1_f32_x3(a[1..].as_ptr())); + unsafe fn test_vst3_s32() { + let a: [i32; 7] = [0, 1, 2, 2, 4, 2, 4]; + let e: [i32; 6] = [1, 2, 2, 2, 4, 4]; + let mut r: [i32; 6] = [0i32; 6]; + vst3_s32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_f32_x3() { - let a: [f32; 13] = [0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; - let e: [f32x4; 3] = [f32x4::new(1., 2., 3., 4.), f32x4::new(5., 6., 7., 8.), f32x4::new(9., 10., 11., 12.)]; - let r: [f32x4; 3] = transmute(vld1q_f32_x3(a[1..].as_ptr())); + unsafe fn test_vst3q_s8() { + let a: [i8; 49] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16, 25, 26, 27, 28, 29, 30, 31, 32, 2, 4, 7, 8, 13, 14, 15, 16, 41, 42, 43, 44, 45, 46, 47, 48]; + let e: [i8; 48] = [1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8, 2, 13, 13, 4, 14, 14, 7, 15, 15, 8, 16, 16, 2, 25, 41, 4, 26, 42, 7, 27, 43, 8, 28, 44, 13, 29, 45, 14, 30, 46, 15, 31, 47, 16, 32, 48]; + let mut r: [i8; 48] = [0i8; 48]; + vst3q_s8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_f32_x4() { - let a: [f32; 9] = [0., 1., 2., 3., 4., 5., 6., 7., 8.]; - let e: [f32x2; 4] = [f32x2::new(1., 2.), f32x2::new(3., 4.), f32x2::new(5., 6.), f32x2::new(7., 8.)]; - let r: [f32x2; 4] = transmute(vld1_f32_x4(a[1..].as_ptr())); + unsafe fn test_vst3q_s16() { + let a: [i16; 25] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16]; + let e: [i16; 24] = [1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8, 2, 13, 13, 4, 14, 14, 7, 15, 15, 8, 16, 16]; + let mut r: [i16; 24] = [0i16; 24]; + vst3q_s16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_f32_x4() { - let a: [f32; 17] = [0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16.]; - let e: [f32x4; 4] = [f32x4::new(1., 2., 3., 4.), f32x4::new(5., 6., 7., 8.), f32x4::new(9., 10., 11., 12.), f32x4::new(13., 14., 15., 16.)]; - let r: [f32x4; 4] = transmute(vld1q_f32_x4(a[1..].as_ptr())); + unsafe fn test_vst3q_s32() { + let a: [i32; 13] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8]; + let e: [i32; 12] = [1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8]; + let mut r: [i32; 12] = [0i32; 12]; + vst3q_s32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_s8_x2() { - let a: [i8; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let e: [i8; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let mut r: [i8; 16] = [0i8; 16]; - vst1_s8_x2(r.as_mut_ptr(), vld1_s8_x2(a[1..].as_ptr())); + unsafe fn test_vst3_s64() { + let a: [i64; 4] = [0, 1, 2, 2]; + let e: [i64; 3] = [1, 2, 2]; + let mut r: [i64; 3] = [0i64; 3]; + vst3_s64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_s16_x2() { - let a: [i16; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; - let e: [i16; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; - let mut r: [i16; 8] = [0i16; 8]; - vst1_s16_x2(r.as_mut_ptr(), vld1_s16_x2(a[1..].as_ptr())); + unsafe fn test_vst3_u8() { + let a: [u8; 25] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16]; + let e: [u8; 24] = [1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8, 2, 13, 13, 4, 14, 14, 7, 15, 15, 8, 16, 16]; + let mut r: [u8; 24] = [0u8; 24]; + vst3_u8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_s32_x2() { - let a: [i32; 5] = [0, 1, 2, 3, 4]; - let e: [i32; 4] = [1, 2, 3, 4]; - let mut r: [i32; 4] = [0i32; 4]; - vst1_s32_x2(r.as_mut_ptr(), vld1_s32_x2(a[1..].as_ptr())); + unsafe fn test_vst3_u16() { + let a: [u16; 13] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8]; + let e: [u16; 12] = [1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8]; + let mut r: [u16; 12] = [0u16; 12]; + vst3_u16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_s64_x2() { - let a: [i64; 3] = [0, 1, 2]; - let e: [i64; 2] = [1, 2]; - let mut r: [i64; 2] = [0i64; 2]; - vst1_s64_x2(r.as_mut_ptr(), vld1_s64_x2(a[1..].as_ptr())); + unsafe fn test_vst3_u32() { + let a: [u32; 7] = [0, 1, 2, 2, 4, 2, 4]; + let e: [u32; 6] = [1, 2, 2, 2, 4, 4]; + let mut r: [u32; 6] = [0u32; 6]; + vst3_u32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_s8_x2() { - let a: [i8; 33] = [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]; - let e: [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 mut r: [i8; 32] = [0i8; 32]; - vst1q_s8_x2(r.as_mut_ptr(), vld1q_s8_x2(a[1..].as_ptr())); + unsafe fn test_vst3q_u8() { + let a: [u8; 49] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16, 25, 26, 27, 28, 29, 30, 31, 32, 2, 4, 7, 8, 13, 14, 15, 16, 41, 42, 43, 44, 45, 46, 47, 48]; + let e: [u8; 48] = [1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8, 2, 13, 13, 4, 14, 14, 7, 15, 15, 8, 16, 16, 2, 25, 41, 4, 26, 42, 7, 27, 43, 8, 28, 44, 13, 29, 45, 14, 30, 46, 15, 31, 47, 16, 32, 48]; + let mut r: [u8; 48] = [0u8; 48]; + vst3q_u8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_s16_x2() { - let a: [i16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let e: [i16; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let mut r: [i16; 16] = [0i16; 16]; - vst1q_s16_x2(r.as_mut_ptr(), vld1q_s16_x2(a[1..].as_ptr())); + unsafe fn test_vst3q_u16() { + let a: [u16; 25] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16]; + let e: [u16; 24] = [1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8, 2, 13, 13, 4, 14, 14, 7, 15, 15, 8, 16, 16]; + let mut r: [u16; 24] = [0u16; 24]; + vst3q_u16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_s32_x2() { - let a: [i32; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; - let e: [i32; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; - let mut r: [i32; 8] = [0i32; 8]; - vst1q_s32_x2(r.as_mut_ptr(), vld1q_s32_x2(a[1..].as_ptr())); + unsafe fn test_vst3q_u32() { + let a: [u32; 13] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8]; + let e: [u32; 12] = [1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8]; + let mut r: [u32; 12] = [0u32; 12]; + vst3q_u32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_s64_x2() { - let a: [i64; 5] = [0, 1, 2, 3, 4]; - let e: [i64; 4] = [1, 2, 3, 4]; - let mut r: [i64; 4] = [0i64; 4]; - vst1q_s64_x2(r.as_mut_ptr(), vld1q_s64_x2(a[1..].as_ptr())); + unsafe fn test_vst3_p8() { + let a: [u8; 25] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16]; + let e: [u8; 24] = [1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8, 2, 13, 13, 4, 14, 14, 7, 15, 15, 8, 16, 16]; + let mut r: [u8; 24] = [0u8; 24]; + vst3_p8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_s8_x3() { - let a: [i8; 25] = [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]; - let e: [i8; 24] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]; - let mut r: [i8; 24] = [0i8; 24]; - vst1_s8_x3(r.as_mut_ptr(), vld1_s8_x3(a[1..].as_ptr())); + unsafe fn test_vst3_p16() { + let a: [u16; 13] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8]; + let e: [u16; 12] = [1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8]; + let mut r: [u16; 12] = [0u16; 12]; + vst3_p16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_s16_x3() { - let a: [i16; 13] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; - let e: [i16; 12] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; - let mut r: [i16; 12] = [0i16; 12]; - vst1_s16_x3(r.as_mut_ptr(), vld1_s16_x3(a[1..].as_ptr())); + unsafe fn test_vst3q_p8() { + let a: [u8; 49] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16, 25, 26, 27, 28, 29, 30, 31, 32, 2, 4, 7, 8, 13, 14, 15, 16, 41, 42, 43, 44, 45, 46, 47, 48]; + let e: [u8; 48] = [1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8, 2, 13, 13, 4, 14, 14, 7, 15, 15, 8, 16, 16, 2, 25, 41, 4, 26, 42, 7, 27, 43, 8, 28, 44, 13, 29, 45, 14, 30, 46, 15, 31, 47, 16, 32, 48]; + let mut r: [u8; 48] = [0u8; 48]; + vst3q_p8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_s32_x3() { - let a: [i32; 7] = [0, 1, 2, 3, 4, 5, 6]; - let e: [i32; 6] = [1, 2, 3, 4, 5, 6]; - let mut r: [i32; 6] = [0i32; 6]; - vst1_s32_x3(r.as_mut_ptr(), vld1_s32_x3(a[1..].as_ptr())); + unsafe fn test_vst3q_p16() { + let a: [u16; 25] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16]; + let e: [u16; 24] = [1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8, 2, 13, 13, 4, 14, 14, 7, 15, 15, 8, 16, 16]; + let mut r: [u16; 24] = [0u16; 24]; + vst3q_p16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_s64_x3() { - let a: [i64; 4] = [0, 1, 2, 3]; - let e: [i64; 3] = [1, 2, 3]; - let mut r: [i64; 3] = [0i64; 3]; - vst1_s64_x3(r.as_mut_ptr(), vld1_s64_x3(a[1..].as_ptr())); + unsafe fn test_vst3_u64() { + let a: [u64; 4] = [0, 1, 2, 2]; + let e: [u64; 3] = [1, 2, 2]; + let mut r: [u64; 3] = [0u64; 3]; + vst3_u64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_s8_x3() { - let a: [i8; 49] = [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, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let e: [i8; 48] = [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, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let mut r: [i8; 48] = [0i8; 48]; - vst1q_s8_x3(r.as_mut_ptr(), vld1q_s8_x3(a[1..].as_ptr())); + unsafe fn test_vst3_p64() { + let a: [u64; 4] = [0, 1, 2, 2]; + let e: [u64; 3] = [1, 2, 2]; + let mut r: [u64; 3] = [0u64; 3]; + vst3_p64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_s16_x3() { - let a: [i16; 25] = [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]; - let e: [i16; 24] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]; - let mut r: [i16; 24] = [0i16; 24]; - vst1q_s16_x3(r.as_mut_ptr(), vld1q_s16_x3(a[1..].as_ptr())); + unsafe fn test_vst3_f32() { + let a: [f32; 7] = [0., 1., 2., 2., 4., 2., 4.]; + let e: [f32; 6] = [1., 2., 2., 2., 4., 4.]; + let mut r: [f32; 6] = [0f32; 6]; + vst3_f32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_s32_x3() { - let a: [i32; 13] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; - let e: [i32; 12] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; - let mut r: [i32; 12] = [0i32; 12]; - vst1q_s32_x3(r.as_mut_ptr(), vld1q_s32_x3(a[1..].as_ptr())); + unsafe fn test_vst3q_f32() { + let a: [f32; 13] = [0., 1., 2., 2., 4., 2., 4., 7., 8., 2., 4., 7., 8.]; + let e: [f32; 12] = [1., 2., 2., 2., 4., 4., 2., 7., 7., 4., 8., 8.]; + let mut r: [f32; 12] = [0f32; 12]; + vst3q_f32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_s64_x3() { - let a: [i64; 7] = [0, 1, 2, 3, 4, 5, 6]; - let e: [i64; 6] = [1, 2, 3, 4, 5, 6]; - let mut r: [i64; 6] = [0i64; 6]; - vst1q_s64_x3(r.as_mut_ptr(), vld1q_s64_x3(a[1..].as_ptr())); + unsafe fn test_vst3_lane_s8() { + let a: [i8; 25] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16]; + let e: [i8; 24] = [1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + let mut r: [i8; 24] = [0i8; 24]; + vst3_lane_s8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_s8_x4() { - let a: [i8; 33] = [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]; - let e: [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 mut r: [i8; 32] = [0i8; 32]; - vst1_s8_x4(r.as_mut_ptr(), vld1_s8_x4(a[1..].as_ptr())); + unsafe fn test_vst3_lane_s16() { + let a: [i16; 13] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8]; + let e: [i16; 12] = [1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + let mut r: [i16; 12] = [0i16; 12]; + vst3_lane_s16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_s16_x4() { - let a: [i16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let e: [i16; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let mut r: [i16; 16] = [0i16; 16]; - vst1_s16_x4(r.as_mut_ptr(), vld1_s16_x4(a[1..].as_ptr())); + unsafe fn test_vst3_lane_s32() { + let a: [i32; 7] = [0, 1, 2, 2, 4, 2, 4]; + let e: [i32; 6] = [1, 2, 2, 0, 0, 0]; + let mut r: [i32; 6] = [0i32; 6]; + vst3_lane_s32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_s32_x4() { - let a: [i32; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; - let e: [i32; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; - let mut r: [i32; 8] = [0i32; 8]; - vst1_s32_x4(r.as_mut_ptr(), vld1_s32_x4(a[1..].as_ptr())); + unsafe fn test_vst3q_lane_s16() { + let a: [i16; 25] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16]; + let e: [i16; 24] = [1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + let mut r: [i16; 24] = [0i16; 24]; + vst3q_lane_s16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_s64_x4() { - let a: [i64; 5] = [0, 1, 2, 3, 4]; - let e: [i64; 4] = [1, 2, 3, 4]; - let mut r: [i64; 4] = [0i64; 4]; - vst1_s64_x4(r.as_mut_ptr(), vld1_s64_x4(a[1..].as_ptr())); + unsafe fn test_vst3q_lane_s32() { + let a: [i32; 13] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8]; + let e: [i32; 12] = [1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + let mut r: [i32; 12] = [0i32; 12]; + vst3q_lane_s32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_s8_x4() { - let a: [i8; 65] = [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, 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 e: [i8; 64] = [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, 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 mut r: [i8; 64] = [0i8; 64]; - vst1q_s8_x4(r.as_mut_ptr(), vld1q_s8_x4(a[1..].as_ptr())); + unsafe fn test_vst3_lane_u8() { + let a: [u8; 25] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16]; + let e: [u8; 24] = [1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + let mut r: [u8; 24] = [0u8; 24]; + vst3_lane_u8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_s16_x4() { - let a: [i16; 33] = [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]; - let e: [i16; 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 mut r: [i16; 32] = [0i16; 32]; - vst1q_s16_x4(r.as_mut_ptr(), vld1q_s16_x4(a[1..].as_ptr())); + unsafe fn test_vst3_lane_u16() { + let a: [u16; 13] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8]; + let e: [u16; 12] = [1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + let mut r: [u16; 12] = [0u16; 12]; + vst3_lane_u16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_s32_x4() { - let a: [i32; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let e: [i32; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let mut r: [i32; 16] = [0i32; 16]; - vst1q_s32_x4(r.as_mut_ptr(), vld1q_s32_x4(a[1..].as_ptr())); + unsafe fn test_vst3_lane_u32() { + let a: [u32; 7] = [0, 1, 2, 2, 4, 2, 4]; + let e: [u32; 6] = [1, 2, 2, 0, 0, 0]; + let mut r: [u32; 6] = [0u32; 6]; + vst3_lane_u32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_s64_x4() { - let a: [i64; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; - let e: [i64; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; - let mut r: [i64; 8] = [0i64; 8]; - vst1q_s64_x4(r.as_mut_ptr(), vld1q_s64_x4(a[1..].as_ptr())); + unsafe fn test_vst3q_lane_u16() { + let a: [u16; 25] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16]; + let e: [u16; 24] = [1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + let mut r: [u16; 24] = [0u16; 24]; + vst3q_lane_u16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_u8_x2() { - let a: [u8; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let e: [u8; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let mut r: [u8; 16] = [0u8; 16]; - vst1_u8_x2(r.as_mut_ptr(), vld1_u8_x2(a[1..].as_ptr())); + unsafe fn test_vst3q_lane_u32() { + let a: [u32; 13] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8]; + let e: [u32; 12] = [1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + let mut r: [u32; 12] = [0u32; 12]; + vst3q_lane_u32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_u16_x2() { - let a: [u16; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; - let e: [u16; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; - let mut r: [u16; 8] = [0u16; 8]; - vst1_u16_x2(r.as_mut_ptr(), vld1_u16_x2(a[1..].as_ptr())); + unsafe fn test_vst3_lane_p8() { + let a: [u8; 25] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16]; + let e: [u8; 24] = [1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + let mut r: [u8; 24] = [0u8; 24]; + vst3_lane_p8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_u32_x2() { - let a: [u32; 5] = [0, 1, 2, 3, 4]; - let e: [u32; 4] = [1, 2, 3, 4]; - let mut r: [u32; 4] = [0u32; 4]; - vst1_u32_x2(r.as_mut_ptr(), vld1_u32_x2(a[1..].as_ptr())); + unsafe fn test_vst3_lane_p16() { + let a: [u16; 13] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8]; + let e: [u16; 12] = [1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + let mut r: [u16; 12] = [0u16; 12]; + vst3_lane_p16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_u64_x2() { - let a: [u64; 3] = [0, 1, 2]; - let e: [u64; 2] = [1, 2]; - let mut r: [u64; 2] = [0u64; 2]; - vst1_u64_x2(r.as_mut_ptr(), vld1_u64_x2(a[1..].as_ptr())); + unsafe fn test_vst3q_lane_p16() { + let a: [u16; 25] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16]; + let e: [u16; 24] = [1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + let mut r: [u16; 24] = [0u16; 24]; + vst3q_lane_p16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_u8_x2() { - let a: [u8; 33] = [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]; - let e: [u8; 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 mut r: [u8; 32] = [0u8; 32]; - vst1q_u8_x2(r.as_mut_ptr(), vld1q_u8_x2(a[1..].as_ptr())); + unsafe fn test_vst3_lane_f32() { + let a: [f32; 7] = [0., 1., 2., 2., 3., 2., 3.]; + let e: [f32; 6] = [1., 2., 2., 0., 0., 0.]; + let mut r: [f32; 6] = [0f32; 6]; + vst3_lane_f32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_u16_x2() { - let a: [u16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let e: [u16; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let mut r: [u16; 16] = [0u16; 16]; - vst1q_u16_x2(r.as_mut_ptr(), vld1q_u16_x2(a[1..].as_ptr())); + unsafe fn test_vst3q_lane_f32() { + let a: [f32; 13] = [0., 1., 2., 2., 3., 2., 3., 4., 5., 2., 3., 4., 5.]; + let e: [f32; 12] = [1., 2., 2., 0., 0., 0., 0., 0., 0., 0., 0., 0.]; + let mut r: [f32; 12] = [0f32; 12]; + vst3q_lane_f32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_u32_x2() { - let a: [u32; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; - let e: [u32; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; - let mut r: [u32; 8] = [0u32; 8]; - vst1q_u32_x2(r.as_mut_ptr(), vld1q_u32_x2(a[1..].as_ptr())); + unsafe fn test_vst4_s8() { + let a: [i8; 33] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; + let e: [i8; 32] = [1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; + let mut r: [i8; 32] = [0i8; 32]; + vst4_s8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_u64_x2() { - let a: [u64; 5] = [0, 1, 2, 3, 4]; - let e: [u64; 4] = [1, 2, 3, 4]; - let mut r: [u64; 4] = [0u64; 4]; - vst1q_u64_x2(r.as_mut_ptr(), vld1q_u64_x2(a[1..].as_ptr())); + unsafe fn test_vst4_s16() { + let a: [i16; 17] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; + let e: [i16; 16] = [1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; + let mut r: [i16; 16] = [0i16; 16]; + vst4_s16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_u8_x3() { - let a: [u8; 25] = [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]; - let e: [u8; 24] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]; - let mut r: [u8; 24] = [0u8; 24]; - vst1_u8_x3(r.as_mut_ptr(), vld1_u8_x3(a[1..].as_ptr())); + unsafe fn test_vst4_s32() { + let a: [i32; 9] = [0, 1, 2, 2, 6, 2, 6, 6, 8]; + let e: [i32; 8] = [1, 2, 2, 6, 2, 6, 6, 8]; + let mut r: [i32; 8] = [0i32; 8]; + vst4_s32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_u16_x3() { - let a: [u16; 13] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; - let e: [u16; 12] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; - let mut r: [u16; 12] = [0u16; 12]; - vst1_u16_x3(r.as_mut_ptr(), vld1_u16_x3(a[1..].as_ptr())); + unsafe fn test_vst4q_s8() { + let a: [i8; 65] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48, 6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64]; + let e: [i8; 64] = [1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48, 6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64]; + let mut r: [i8; 64] = [0i8; 64]; + vst4q_s8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_u32_x3() { - let a: [u32; 7] = [0, 1, 2, 3, 4, 5, 6]; - let e: [u32; 6] = [1, 2, 3, 4, 5, 6]; - let mut r: [u32; 6] = [0u32; 6]; - vst1_u32_x3(r.as_mut_ptr(), vld1_u32_x3(a[1..].as_ptr())); + unsafe fn test_vst4q_s16() { + let a: [i16; 33] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; + let e: [i16; 32] = [1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; + let mut r: [i16; 32] = [0i16; 32]; + vst4q_s16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_u64_x3() { - let a: [u64; 4] = [0, 1, 2, 3]; - let e: [u64; 3] = [1, 2, 3]; - let mut r: [u64; 3] = [0u64; 3]; - vst1_u64_x3(r.as_mut_ptr(), vld1_u64_x3(a[1..].as_ptr())); + unsafe fn test_vst4q_s32() { + let a: [i32; 17] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; + let e: [i32; 16] = [1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; + let mut r: [i32; 16] = [0i32; 16]; + vst4q_s32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_u8_x3() { - let a: [u8; 49] = [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, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let e: [u8; 48] = [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, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let mut r: [u8; 48] = [0u8; 48]; - vst1q_u8_x3(r.as_mut_ptr(), vld1q_u8_x3(a[1..].as_ptr())); + unsafe fn test_vst4_s64() { + let a: [i64; 5] = [0, 1, 2, 2, 6]; + let e: [i64; 4] = [1, 2, 2, 6]; + let mut r: [i64; 4] = [0i64; 4]; + vst4_s64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_u16_x3() { - let a: [u16; 25] = [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]; - let e: [u16; 24] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]; - let mut r: [u16; 24] = [0u16; 24]; - vst1q_u16_x3(r.as_mut_ptr(), vld1q_u16_x3(a[1..].as_ptr())); + unsafe fn test_vst4_u8() { + let a: [u8; 33] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; + let e: [u8; 32] = [1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; + let mut r: [u8; 32] = [0u8; 32]; + vst4_u8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_u32_x3() { - let a: [u32; 13] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; - let e: [u32; 12] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; - let mut r: [u32; 12] = [0u32; 12]; - vst1q_u32_x3(r.as_mut_ptr(), vld1q_u32_x3(a[1..].as_ptr())); + unsafe fn test_vst4_u16() { + let a: [u16; 17] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; + let e: [u16; 16] = [1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; + let mut r: [u16; 16] = [0u16; 16]; + vst4_u16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_u64_x3() { - let a: [u64; 7] = [0, 1, 2, 3, 4, 5, 6]; - let e: [u64; 6] = [1, 2, 3, 4, 5, 6]; - let mut r: [u64; 6] = [0u64; 6]; - vst1q_u64_x3(r.as_mut_ptr(), vld1q_u64_x3(a[1..].as_ptr())); + unsafe fn test_vst4_u32() { + let a: [u32; 9] = [0, 1, 2, 2, 6, 2, 6, 6, 8]; + let e: [u32; 8] = [1, 2, 2, 6, 2, 6, 6, 8]; + let mut r: [u32; 8] = [0u32; 8]; + vst4_u32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_u8_x4() { - let a: [u8; 33] = [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]; - let e: [u8; 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 mut r: [u8; 32] = [0u8; 32]; - vst1_u8_x4(r.as_mut_ptr(), vld1_u8_x4(a[1..].as_ptr())); + unsafe fn test_vst4q_u8() { + let a: [u8; 65] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48, 6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64]; + let e: [u8; 64] = [1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48, 6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64]; + let mut r: [u8; 64] = [0u8; 64]; + vst4q_u8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_u16_x4() { - let a: [u16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let e: [u16; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let mut r: [u16; 16] = [0u16; 16]; - vst1_u16_x4(r.as_mut_ptr(), vld1_u16_x4(a[1..].as_ptr())); + unsafe fn test_vst4q_u16() { + let a: [u16; 33] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; + let e: [u16; 32] = [1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; + let mut r: [u16; 32] = [0u16; 32]; + vst4q_u16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_u32_x4() { - let a: [u32; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; - let e: [u32; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; - let mut r: [u32; 8] = [0u32; 8]; - vst1_u32_x4(r.as_mut_ptr(), vld1_u32_x4(a[1..].as_ptr())); + unsafe fn test_vst4q_u32() { + let a: [u32; 17] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; + let e: [u32; 16] = [1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; + let mut r: [u32; 16] = [0u32; 16]; + vst4q_u32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_u64_x4() { - let a: [u64; 5] = [0, 1, 2, 3, 4]; - let e: [u64; 4] = [1, 2, 3, 4]; - let mut r: [u64; 4] = [0u64; 4]; - vst1_u64_x4(r.as_mut_ptr(), vld1_u64_x4(a[1..].as_ptr())); + unsafe fn test_vst4_p8() { + let a: [u8; 33] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; + let e: [u8; 32] = [1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; + let mut r: [u8; 32] = [0u8; 32]; + vst4_p8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_u8_x4() { - let a: [u8; 65] = [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, 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 e: [u8; 64] = [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, 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 mut r: [u8; 64] = [0u8; 64]; - vst1q_u8_x4(r.as_mut_ptr(), vld1q_u8_x4(a[1..].as_ptr())); + unsafe fn test_vst4_p16() { + let a: [u16; 17] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; + let e: [u16; 16] = [1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; + let mut r: [u16; 16] = [0u16; 16]; + vst4_p16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_u16_x4() { - let a: [u16; 33] = [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]; - let e: [u16; 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 mut r: [u16; 32] = [0u16; 32]; - vst1q_u16_x4(r.as_mut_ptr(), vld1q_u16_x4(a[1..].as_ptr())); + unsafe fn test_vst4q_p8() { + let a: [u8; 65] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48, 6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64]; + let e: [u8; 64] = [1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48, 6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64]; + let mut r: [u8; 64] = [0u8; 64]; + vst4q_p8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_u32_x4() { - let a: [u32; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let e: [u32; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let mut r: [u32; 16] = [0u32; 16]; - vst1q_u32_x4(r.as_mut_ptr(), vld1q_u32_x4(a[1..].as_ptr())); + unsafe fn test_vst4q_p16() { + let a: [u16; 33] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; + let e: [u16; 32] = [1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; + let mut r: [u16; 32] = [0u16; 32]; + vst4q_p16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_u64_x4() { - let a: [u64; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; - let e: [u64; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; - let mut r: [u64; 8] = [0u64; 8]; - vst1q_u64_x4(r.as_mut_ptr(), vld1q_u64_x4(a[1..].as_ptr())); + unsafe fn test_vst4_u64() { + let a: [u64; 5] = [0, 1, 2, 2, 6]; + let e: [u64; 4] = [1, 2, 2, 6]; + let mut r: [u64; 4] = [0u64; 4]; + vst4_u64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_p8_x2() { - let a: [u8; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let e: [u8; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let mut r: [u8; 16] = [0u8; 16]; - vst1_p8_x2(r.as_mut_ptr(), vld1_p8_x2(a[1..].as_ptr())); + unsafe fn test_vst4_p64() { + let a: [u64; 5] = [0, 1, 2, 2, 6]; + let e: [u64; 4] = [1, 2, 2, 6]; + let mut r: [u64; 4] = [0u64; 4]; + vst4_p64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_p8_x3() { - let a: [u8; 25] = [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]; - let e: [u8; 24] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]; - let mut r: [u8; 24] = [0u8; 24]; - vst1_p8_x3(r.as_mut_ptr(), vld1_p8_x3(a[1..].as_ptr())); + unsafe fn test_vst4_f32() { + let a: [f32; 9] = [0., 1., 2., 2., 6., 2., 6., 6., 8.]; + let e: [f32; 8] = [1., 2., 2., 6., 2., 6., 6., 8.]; + let mut r: [f32; 8] = [0f32; 8]; + vst4_f32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_p8_x4() { - let a: [u8; 33] = [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]; - let e: [u8; 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 mut r: [u8; 32] = [0u8; 32]; - vst1_p8_x4(r.as_mut_ptr(), vld1_p8_x4(a[1..].as_ptr())); + unsafe fn test_vst4q_f32() { + let a: [f32; 17] = [0., 1., 2., 2., 6., 2., 6., 6., 8., 2., 6., 6., 8., 6., 8., 8., 16.]; + let e: [f32; 16] = [1., 2., 2., 6., 2., 6., 6., 8., 2., 6., 6., 8., 6., 8., 8., 16.]; + let mut r: [f32; 16] = [0f32; 16]; + vst4q_f32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_p8_x2() { - let a: [u8; 33] = [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]; - let e: [u8; 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 mut r: [u8; 32] = [0u8; 32]; - vst1q_p8_x2(r.as_mut_ptr(), vld1q_p8_x2(a[1..].as_ptr())); + unsafe fn test_vst4_lane_s8() { + let a: [i8; 33] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; + let e: [i8; 32] = [1, 2, 2, 6, 0, 0, 0, 0, 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 mut r: [i8; 32] = [0i8; 32]; + vst4_lane_s8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_p8_x3() { - let a: [u8; 49] = [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, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let e: [u8; 48] = [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, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let mut r: [u8; 48] = [0u8; 48]; - vst1q_p8_x3(r.as_mut_ptr(), vld1q_p8_x3(a[1..].as_ptr())); + unsafe fn test_vst4_lane_s16() { + let a: [i16; 17] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; + let e: [i16; 16] = [1, 2, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + let mut r: [i16; 16] = [0i16; 16]; + vst4_lane_s16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_p8_x4() { - let a: [u8; 65] = [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, 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 e: [u8; 64] = [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, 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 mut r: [u8; 64] = [0u8; 64]; - vst1q_p8_x4(r.as_mut_ptr(), vld1q_p8_x4(a[1..].as_ptr())); + unsafe fn test_vst4_lane_s32() { + let a: [i32; 9] = [0, 1, 2, 2, 6, 2, 6, 6, 8]; + let e: [i32; 8] = [1, 2, 2, 6, 0, 0, 0, 0]; + let mut r: [i32; 8] = [0i32; 8]; + vst4_lane_s32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_p16_x2() { - let a: [u16; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; - let e: [u16; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; - let mut r: [u16; 8] = [0u16; 8]; - vst1_p16_x2(r.as_mut_ptr(), vld1_p16_x2(a[1..].as_ptr())); + unsafe fn test_vst4q_lane_s16() { + let a: [i16; 33] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; + let e: [i16; 32] = [1, 2, 2, 6, 0, 0, 0, 0, 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 mut r: [i16; 32] = [0i16; 32]; + vst4q_lane_s16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_p16_x3() { - let a: [u16; 13] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; - let e: [u16; 12] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; - let mut r: [u16; 12] = [0u16; 12]; - vst1_p16_x3(r.as_mut_ptr(), vld1_p16_x3(a[1..].as_ptr())); + unsafe fn test_vst4q_lane_s32() { + let a: [i32; 17] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; + let e: [i32; 16] = [1, 2, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + let mut r: [i32; 16] = [0i32; 16]; + vst4q_lane_s32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_p16_x4() { - let a: [u16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let e: [u16; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let mut r: [u16; 16] = [0u16; 16]; - vst1_p16_x4(r.as_mut_ptr(), vld1_p16_x4(a[1..].as_ptr())); + unsafe fn test_vst4_lane_u8() { + let a: [u8; 33] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; + let e: [u8; 32] = [1, 2, 2, 6, 0, 0, 0, 0, 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 mut r: [u8; 32] = [0u8; 32]; + vst4_lane_u8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_p16_x2() { - let a: [u16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - let e: [u16; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + unsafe fn test_vst4_lane_u16() { + let a: [u16; 17] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; + let e: [u16; 16] = [1, 2, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [u16; 16] = [0u16; 16]; - vst1q_p16_x2(r.as_mut_ptr(), vld1q_p16_x2(a[1..].as_ptr())); + vst4_lane_u16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_p16_x3() { - let a: [u16; 25] = [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]; - let e: [u16; 24] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]; - let mut r: [u16; 24] = [0u16; 24]; - vst1q_p16_x3(r.as_mut_ptr(), vld1q_p16_x3(a[1..].as_ptr())); + unsafe fn test_vst4_lane_u32() { + let a: [u32; 9] = [0, 1, 2, 2, 6, 2, 6, 6, 8]; + let e: [u32; 8] = [1, 2, 2, 6, 0, 0, 0, 0]; + let mut r: [u32; 8] = [0u32; 8]; + vst4_lane_u32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_p16_x4() { - let a: [u16; 33] = [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]; - let e: [u16; 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]; + unsafe fn test_vst4q_lane_u16() { + let a: [u16; 33] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; + let e: [u16; 32] = [1, 2, 2, 6, 0, 0, 0, 0, 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 mut r: [u16; 32] = [0u16; 32]; - vst1q_p16_x4(r.as_mut_ptr(), vld1q_p16_x4(a[1..].as_ptr())); + vst4q_lane_u16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_f32_x2() { - let a: [f32; 5] = [0., 1., 2., 3., 4.]; - let e: [f32; 4] = [1., 2., 3., 4.]; - let mut r: [f32; 4] = [0f32; 4]; - vst1_f32_x2(r.as_mut_ptr(), vld1_f32_x2(a[1..].as_ptr())); + unsafe fn test_vst4q_lane_u32() { + let a: [u32; 17] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; + let e: [u32; 16] = [1, 2, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + let mut r: [u32; 16] = [0u32; 16]; + vst4q_lane_u32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_f32_x2() { - let a: [f32; 9] = [0., 1., 2., 3., 4., 5., 6., 7., 8.]; - let e: [f32; 8] = [1., 2., 3., 4., 5., 6., 7., 8.]; - let mut r: [f32; 8] = [0f32; 8]; - vst1q_f32_x2(r.as_mut_ptr(), vld1q_f32_x2(a[1..].as_ptr())); + unsafe fn test_vst4_lane_p8() { + let a: [u8; 33] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; + let e: [u8; 32] = [1, 2, 2, 6, 0, 0, 0, 0, 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 mut r: [u8; 32] = [0u8; 32]; + vst4_lane_p8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_f32_x3() { - let a: [f32; 7] = [0., 1., 2., 3., 4., 5., 6.]; - let e: [f32; 6] = [1., 2., 3., 4., 5., 6.]; - let mut r: [f32; 6] = [0f32; 6]; - vst1_f32_x3(r.as_mut_ptr(), vld1_f32_x3(a[1..].as_ptr())); + unsafe fn test_vst4_lane_p16() { + let a: [u16; 17] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; + let e: [u16; 16] = [1, 2, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + let mut r: [u16; 16] = [0u16; 16]; + vst4_lane_p16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_f32_x3() { - let a: [f32; 13] = [0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; - let e: [f32; 12] = [1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; - let mut r: [f32; 12] = [0f32; 12]; - vst1q_f32_x3(r.as_mut_ptr(), vld1q_f32_x3(a[1..].as_ptr())); + unsafe fn test_vst4q_lane_p16() { + let a: [u16; 33] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; + let e: [u16; 32] = [1, 2, 2, 6, 0, 0, 0, 0, 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 mut r: [u16; 32] = [0u16; 32]; + vst4q_lane_p16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1_f32_x4() { - let a: [f32; 9] = [0., 1., 2., 3., 4., 5., 6., 7., 8.]; - let e: [f32; 8] = [1., 2., 3., 4., 5., 6., 7., 8.]; + unsafe fn test_vst4_lane_f32() { + let a: [f32; 9] = [0., 1., 2., 2., 6., 2., 6., 6., 8.]; + let e: [f32; 8] = [1., 2., 2., 6., 0., 0., 0., 0.]; let mut r: [f32; 8] = [0f32; 8]; - vst1_f32_x4(r.as_mut_ptr(), vld1_f32_x4(a[1..].as_ptr())); + vst4_lane_f32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_f32_x4() { - let a: [f32; 17] = [0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16.]; - let e: [f32; 16] = [1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16.]; + unsafe fn test_vst4q_lane_f32() { + let a: [f32; 17] = [0., 1., 2., 2., 6., 2., 6., 6., 8., 2., 6., 6., 8., 6., 8., 8., 16.]; + let e: [f32; 16] = [1., 2., 2., 6., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]; let mut r: [f32; 16] = [0f32; 16]; - vst1q_f32_x4(r.as_mut_ptr(), vld1q_f32_x4(a[1..].as_ptr())); + vst4q_lane_f32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); } @@ -23058,6 +33157,69 @@ mod test { assert_eq!(r, e); } + #[simd_test(enable = "neon")] + unsafe fn test_vadd_p8() { + let a: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let b: i8x8 = i8x8::new(1, 1, 1, 1, 1, 1, 1, 1); + let e: i8x8 = i8x8::new(0, 3, 2, 5, 4, 7, 6, 9); + let r: i8x8 = transmute(vadd_p8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vadd_p16() { + let a: i16x4 = i16x4::new(1, 2, 3, 4); + let b: i16x4 = i16x4::new(1, 1, 1, 1); + let e: i16x4 = i16x4::new(0, 3, 2, 5); + let r: i16x4 = transmute(vadd_p16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vaddq_p8() { + let a: i8x16 = i8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let b: i8x16 = i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); + let e: i8x16 = i8x16::new(0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14, 17); + let r: i8x16 = transmute(vaddq_p8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vaddq_p16() { + let a: i16x8 = i16x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let b: i16x8 = i16x8::new(1, 1, 1, 1, 1, 1, 1, 1); + let e: i16x8 = i16x8::new(0, 3, 2, 5, 4, 7, 6, 9); + let r: i16x8 = transmute(vaddq_p16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vadd_p64() { + let a: i64x1 = i64x1::new(1); + let b: i64x1 = i64x1::new(1); + let e: i64x1 = i64x1::new(0); + let r: i64x1 = transmute(vadd_p64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vaddq_p64() { + let a: i64x2 = i64x2::new(1, 2); + let b: i64x2 = i64x2::new(1, 1); + let e: i64x2 = i64x2::new(0, 3); + let r: i64x2 = transmute(vaddq_p64(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vaddq_p128() { + let a: p128 = 16; + let b: p128 = 1; + let e: p128 = 17; + let r: p128 = transmute(vaddq_p128(transmute(a), transmute(b))); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vsubhn_s16() { let a: i16x8 = i16x8::new(0x7F_FF, -32768, 1, 1, 0x7F_FF, -32768, 1, 1); @@ -23676,6 +33838,15 @@ mod test { assert_eq!(r, e); } + #[simd_test(enable = "neon")] + unsafe fn test_vpadd_f32() { + let a: f32x2 = f32x2::new(1., 2.); + let b: f32x2 = f32x2::new(3., 4.); + let e: f32x2 = f32x2::new(3., 7.); + let r: f32x2 = transmute(vpadd_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vqdmull_s16() { let a: i16x4 = i16x4::new(0, 1, 2, 3); @@ -23922,6 +34093,42 @@ mod test { assert_eq!(r, e); } + #[simd_test(enable = "neon")] + unsafe fn test_vqdmulhq_laneq_s16() { + let a: i16x8 = i16x8::new(0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF); + let b: i16x8 = i16x8::new(2, 1, 1, 1, 1, 1, 1, 1); + let e: i16x8 = i16x8::new(1, 1, 1, 1, 1, 1, 1, 1); + let r: i16x8 = transmute(vqdmulhq_laneq_s16::<0>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqdmulh_laneq_s16() { + let a: i16x4 = i16x4::new(0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF); + let b: i16x8 = i16x8::new(2, 1, 1, 1, 1, 1, 1, 1); + let e: i16x4 = i16x4::new(1, 1, 1, 1); + let r: i16x4 = transmute(vqdmulh_laneq_s16::<0>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqdmulhq_laneq_s32() { + let a: i32x4 = i32x4::new(0x7F_FF_FF_FF, 0x7F_FF_FF_FF, 0x7F_FF_FF_FF, 0x7F_FF_FF_FF); + let b: i32x4 = i32x4::new(2, 1, 1, 1); + let e: i32x4 = i32x4::new(1, 1, 1, 1); + let r: i32x4 = transmute(vqdmulhq_laneq_s32::<0>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqdmulh_laneq_s32() { + let a: i32x2 = i32x2::new(0x7F_FF_FF_FF, 0x7F_FF_FF_FF); + let b: i32x4 = i32x4::new(2, 1, 1, 1); + let e: i32x2 = i32x2::new(1, 1); + let r: i32x2 = transmute(vqdmulh_laneq_s32::<0>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vqmovn_s16() { let a: i16x8 = i16x8::new(0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF); @@ -24094,167 +34301,47 @@ mod test { } #[simd_test(enable = "neon")] - unsafe fn test_vqrdmulhq_laneq_s16() { - let a: i16x8 = i16x8::new(0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF); - let b: i16x8 = i16x8::new(0, 2, 0, 0, 0, 0, 0, 0); - let e: i16x8 = i16x8::new(2, 2, 2, 2, 2, 2, 2, 2); - let r: i16x8 = transmute(vqrdmulhq_laneq_s16::<1>(transmute(a), transmute(b))); - assert_eq!(r, e); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vqrdmulh_lane_s32() { - let a: i32x2 = i32x2::new(0x7F_FF_FF_FF, 0x7F_FF_FF_FF); - let b: i32x2 = i32x2::new(0, 2); - let e: i32x2 = i32x2::new(2, 2); - let r: i32x2 = transmute(vqrdmulh_lane_s32::<1>(transmute(a), transmute(b))); - assert_eq!(r, e); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vqrdmulh_laneq_s32() { - let a: i32x2 = i32x2::new(0x7F_FF_FF_FF, 0x7F_FF_FF_FF); - let b: i32x4 = i32x4::new(0, 2, 0, 0); - let e: i32x2 = i32x2::new(2, 2); - let r: i32x2 = transmute(vqrdmulh_laneq_s32::<1>(transmute(a), transmute(b))); - assert_eq!(r, e); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vqrdmulhq_lane_s32() { - let a: i32x4 = i32x4::new(0x7F_FF_FF_FF, 0x7F_FF_FF_FF, 0x7F_FF_FF_FF, 0x7F_FF_FF_FF); - let b: i32x2 = i32x2::new(0, 2); - let e: i32x4 = i32x4::new(2, 2, 2, 2); - let r: i32x4 = transmute(vqrdmulhq_lane_s32::<1>(transmute(a), transmute(b))); - assert_eq!(r, e); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vqrdmulhq_laneq_s32() { - let a: i32x4 = i32x4::new(0x7F_FF_FF_FF, 0x7F_FF_FF_FF, 0x7F_FF_FF_FF, 0x7F_FF_FF_FF); - let b: i32x4 = i32x4::new(0, 2, 0, 0); - let e: i32x4 = i32x4::new(2, 2, 2, 2); - let r: i32x4 = transmute(vqrdmulhq_laneq_s32::<1>(transmute(a), transmute(b))); - assert_eq!(r, e); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vqrdmlah_s16() { - let a: i16x4 = i16x4::new(1, 1, 1, 1); - let b: i16x4 = i16x4::new(0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF); - let c: i16x4 = i16x4::new(2, 2, 2, 2); - let e: i16x4 = i16x4::new(3, 3, 3, 3); - let r: i16x4 = transmute(vqrdmlah_s16(transmute(a), transmute(b), transmute(c))); - assert_eq!(r, e); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vqrdmlahq_s16() { - let a: i16x8 = i16x8::new(1, 1, 1, 1, 1, 1, 1, 1); - let b: i16x8 = i16x8::new(0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF); - let c: i16x8 = i16x8::new(2, 2, 2, 2, 2, 2, 2, 2); - let e: i16x8 = i16x8::new(3, 3, 3, 3, 3, 3, 3, 3); - let r: i16x8 = transmute(vqrdmlahq_s16(transmute(a), transmute(b), transmute(c))); - assert_eq!(r, e); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vqrdmlah_s32() { - let a: i32x2 = i32x2::new(1, 1); - let b: i32x2 = i32x2::new(0x7F_FF_FF_FF, 0x7F_FF_FF_FF); - let c: i32x2 = i32x2::new(2, 2); - let e: i32x2 = i32x2::new(3, 3); - let r: i32x2 = transmute(vqrdmlah_s32(transmute(a), transmute(b), transmute(c))); - assert_eq!(r, e); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vqrdmlahq_s32() { - let a: i32x4 = i32x4::new(1, 1, 1, 1); - let b: i32x4 = i32x4::new(0x7F_FF_FF_FF, 0x7F_FF_FF_FF, 0x7F_FF_FF_FF, 0x7F_FF_FF_FF); - let c: i32x4 = i32x4::new(2, 2, 2, 2); - let e: i32x4 = i32x4::new(3, 3, 3, 3); - let r: i32x4 = transmute(vqrdmlahq_s32(transmute(a), transmute(b), transmute(c))); - assert_eq!(r, e); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vqrdmlah_lane_s16() { - let a: i16x4 = i16x4::new(1, 1, 1, 1); - let b: i16x4 = i16x4::new(0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF); - let c: i16x4 = i16x4::new(0, 2, 0, 0); - let e: i16x4 = i16x4::new(3, 3, 3, 3); - let r: i16x4 = transmute(vqrdmlah_lane_s16::<1>(transmute(a), transmute(b), transmute(c))); - assert_eq!(r, e); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vqrdmlah_laneq_s16() { - let a: i16x4 = i16x4::new(1, 1, 1, 1); - let b: i16x4 = i16x4::new(0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF); - let c: i16x8 = i16x8::new(0, 2, 0, 0, 0, 0, 0, 0); - let e: i16x4 = i16x4::new(3, 3, 3, 3); - let r: i16x4 = transmute(vqrdmlah_laneq_s16::<1>(transmute(a), transmute(b), transmute(c))); - assert_eq!(r, e); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vqrdmlahq_lane_s16() { - let a: i16x8 = i16x8::new(1, 1, 1, 1, 1, 1, 1, 1); - let b: i16x8 = i16x8::new(0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF); - let c: i16x4 = i16x4::new(0, 2, 0, 0); - let e: i16x8 = i16x8::new(3, 3, 3, 3, 3, 3, 3, 3); - let r: i16x8 = transmute(vqrdmlahq_lane_s16::<1>(transmute(a), transmute(b), transmute(c))); - assert_eq!(r, e); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vqrdmlahq_laneq_s16() { - let a: i16x8 = i16x8::new(1, 1, 1, 1, 1, 1, 1, 1); - let b: i16x8 = i16x8::new(0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF); - let c: i16x8 = i16x8::new(0, 2, 0, 0, 0, 0, 0, 0); - let e: i16x8 = i16x8::new(3, 3, 3, 3, 3, 3, 3, 3); - let r: i16x8 = transmute(vqrdmlahq_laneq_s16::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vqrdmulhq_laneq_s16() { + let a: i16x8 = i16x8::new(0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF); + let b: i16x8 = i16x8::new(0, 2, 0, 0, 0, 0, 0, 0); + let e: i16x8 = i16x8::new(2, 2, 2, 2, 2, 2, 2, 2); + let r: i16x8 = transmute(vqrdmulhq_laneq_s16::<1>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqrdmlah_lane_s32() { - let a: i32x2 = i32x2::new(1, 1); - let b: i32x2 = i32x2::new(0x7F_FF_FF_FF, 0x7F_FF_FF_FF); - let c: i32x2 = i32x2::new(0, 2); - let e: i32x2 = i32x2::new(3, 3); - let r: i32x2 = transmute(vqrdmlah_lane_s32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vqrdmulh_lane_s32() { + let a: i32x2 = i32x2::new(0x7F_FF_FF_FF, 0x7F_FF_FF_FF); + let b: i32x2 = i32x2::new(0, 2); + let e: i32x2 = i32x2::new(2, 2); + let r: i32x2 = transmute(vqrdmulh_lane_s32::<1>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqrdmlah_laneq_s32() { - let a: i32x2 = i32x2::new(1, 1); - let b: i32x2 = i32x2::new(0x7F_FF_FF_FF, 0x7F_FF_FF_FF); - let c: i32x4 = i32x4::new(0, 2, 0, 0); - let e: i32x2 = i32x2::new(3, 3); - let r: i32x2 = transmute(vqrdmlah_laneq_s32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vqrdmulh_laneq_s32() { + let a: i32x2 = i32x2::new(0x7F_FF_FF_FF, 0x7F_FF_FF_FF); + let b: i32x4 = i32x4::new(0, 2, 0, 0); + let e: i32x2 = i32x2::new(2, 2); + let r: i32x2 = transmute(vqrdmulh_laneq_s32::<1>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqrdmlahq_lane_s32() { - let a: i32x4 = i32x4::new(1, 1, 1, 1); - let b: i32x4 = i32x4::new(0x7F_FF_FF_FF, 0x7F_FF_FF_FF, 0x7F_FF_FF_FF, 0x7F_FF_FF_FF); - let c: i32x2 = i32x2::new(0, 2); - let e: i32x4 = i32x4::new(3, 3, 3, 3); - let r: i32x4 = transmute(vqrdmlahq_lane_s32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vqrdmulhq_lane_s32() { + let a: i32x4 = i32x4::new(0x7F_FF_FF_FF, 0x7F_FF_FF_FF, 0x7F_FF_FF_FF, 0x7F_FF_FF_FF); + let b: i32x2 = i32x2::new(0, 2); + let e: i32x4 = i32x4::new(2, 2, 2, 2); + let r: i32x4 = transmute(vqrdmulhq_lane_s32::<1>(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqrdmlahq_laneq_s32() { - let a: i32x4 = i32x4::new(1, 1, 1, 1); - let b: i32x4 = i32x4::new(0x7F_FF_FF_FF, 0x7F_FF_FF_FF, 0x7F_FF_FF_FF, 0x7F_FF_FF_FF); - let c: i32x4 = i32x4::new(0, 2, 0, 0); - let e: i32x4 = i32x4::new(3, 3, 3, 3); - let r: i32x4 = transmute(vqrdmlahq_laneq_s32::<1>(transmute(a), transmute(b), transmute(c))); + unsafe fn test_vqrdmulhq_laneq_s32() { + let a: i32x4 = i32x4::new(0x7F_FF_FF_FF, 0x7F_FF_FF_FF, 0x7F_FF_FF_FF, 0x7F_FF_FF_FF); + let b: i32x4 = i32x4::new(0, 2, 0, 0); + let e: i32x4 = i32x4::new(2, 2, 2, 2); + let r: i32x4 = transmute(vqrdmulhq_laneq_s32::<1>(transmute(a), transmute(b))); assert_eq!(r, e); } @@ -24866,6 +34953,70 @@ mod test { assert_eq!(r, e); } + #[simd_test(enable = "neon")] + unsafe fn test_vqshlu_n_s8() { + let a: i8x8 = i8x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let e: u8x8 = u8x8::new(0, 4, 8, 12, 16, 20, 24, 28); + let r: u8x8 = transmute(vqshlu_n_s8::<2>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqshlu_n_s16() { + let a: i16x4 = i16x4::new(0, 1, 2, 3); + let e: u16x4 = u16x4::new(0, 4, 8, 12); + let r: u16x4 = transmute(vqshlu_n_s16::<2>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqshlu_n_s32() { + let a: i32x2 = i32x2::new(0, 1); + let e: u32x2 = u32x2::new(0, 4); + let r: u32x2 = transmute(vqshlu_n_s32::<2>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqshlu_n_s64() { + let a: i64x1 = i64x1::new(0); + let e: u64x1 = u64x1::new(0); + let r: u64x1 = transmute(vqshlu_n_s64::<2>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqshluq_n_s8() { + let a: i8x16 = i8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let e: u8x16 = u8x16::new(0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60); + let r: u8x16 = transmute(vqshluq_n_s8::<2>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqshluq_n_s16() { + let a: i16x8 = i16x8::new(0, 1, 2, 3, 4, 5, 6, 7); + let e: u16x8 = u16x8::new(0, 4, 8, 12, 16, 20, 24, 28); + let r: u16x8 = transmute(vqshluq_n_s16::<2>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqshluq_n_s32() { + let a: i32x4 = i32x4::new(0, 1, 2, 3); + let e: u32x4 = u32x4::new(0, 4, 8, 12); + let r: u32x4 = transmute(vqshluq_n_s32::<2>(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vqshluq_n_s64() { + let a: i64x2 = i64x2::new(0, 1); + let e: u64x2 = u64x2::new(0, 4); + let r: u64x2 = transmute(vqshluq_n_s64::<2>(transmute(a))); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vqshrn_n_s16() { let a: i16x8 = i16x8::new(0, 4, 8, 12, 16, 20, 24, 28); @@ -24954,6 +35105,40 @@ mod test { assert_eq!(r, e); } + #[simd_test(enable = "neon")] + unsafe fn test_vrsqrte_u32() { + let a: u32x2 = u32x2::new(1, 2); + let e: u32x2 = u32x2::new(4294967295, 4294967295); + let r: u32x2 = transmute(vrsqrte_u32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vrsqrteq_u32() { + let a: u32x4 = u32x4::new(1, 2, 3, 4); + let e: u32x4 = u32x4::new(4294967295, 4294967295, 4294967295, 4294967295); + let r: u32x4 = transmute(vrsqrteq_u32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vrsqrts_f32() { + let a: f32x2 = f32x2::new(1.0, 2.0); + let b: f32x2 = f32x2::new(1.0, 2.0); + let e: f32x2 = f32x2::new(1., -0.5); + let r: f32x2 = transmute(vrsqrts_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vrsqrtsq_f32() { + let a: f32x4 = f32x4::new(1.0, 2.0, 3.0, 4.0); + let b: f32x4 = f32x4::new(1.0, 2.0, 3.0, 4.0); + let e: f32x4 = f32x4::new(1., -0.5, -3.0, -6.5); + let r: f32x4 = transmute(vrsqrtsq_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vrecpe_f32() { let a: f32x2 = f32x2::new(4.0, 3.0); @@ -24970,6 +35155,40 @@ mod test { assert_eq!(r, e); } + #[simd_test(enable = "neon")] + unsafe fn test_vrecpe_u32() { + let a: u32x2 = u32x2::new(4, 3); + let e: u32x2 = u32x2::new(4294967295, 4294967295); + let r: u32x2 = transmute(vrecpe_u32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vrecpeq_u32() { + let a: u32x4 = u32x4::new(4, 3, 2, 1); + let e: u32x4 = u32x4::new(4294967295, 4294967295, 4294967295, 4294967295); + let r: u32x4 = transmute(vrecpeq_u32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vrecps_f32() { + let a: f32x2 = f32x2::new(4.0, 3.0); + let b: f32x2 = f32x2::new(4.0, 3.0); + let e: f32x2 = f32x2::new(-14., -7.); + let r: f32x2 = transmute(vrecps_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vrecpsq_f32() { + let a: f32x4 = f32x4::new(4.0, 3.0, 2.0, 1.0); + let b: f32x4 = f32x4::new(4.0, 3.0, 2.0, 1.0); + let e: f32x4 = f32x4::new(-14., -7., -2., 1.); + let r: f32x4 = transmute(vrecpsq_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vreinterpret_s8_u8() { let a: u8x8 = u8x8::new(0, 1, 2, 3, 4, 5, 6, 7); @@ -25530,6 +35749,62 @@ mod test { assert_eq!(r, e); } + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpret_s32_p64() { + let a: i64x1 = i64x1::new(0); + let e: i32x2 = i32x2::new(0, 0); + let r: i32x2 = transmute(vreinterpret_s32_p64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpret_u32_p64() { + let a: i64x1 = i64x1::new(0); + let e: u32x2 = u32x2::new(0, 0); + let r: u32x2 = transmute(vreinterpret_u32_p64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_s32_p64() { + let a: i64x2 = i64x2::new(0, 1); + let e: i32x4 = i32x4::new(0, 0, 1, 0); + let r: i32x4 = transmute(vreinterpretq_s32_p64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_u32_p64() { + let a: i64x2 = i64x2::new(0, 1); + let e: u32x4 = u32x4::new(0, 0, 1, 0); + let r: u32x4 = transmute(vreinterpretq_u32_p64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_s64_p128() { + let a: p128 = 0; + let e: i64x2 = i64x2::new(0, 0); + let r: i64x2 = transmute(vreinterpretq_s64_p128(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_u64_p128() { + let a: p128 = 0; + let e: u64x2 = u64x2::new(0, 0); + let r: u64x2 = transmute(vreinterpretq_u64_p128(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_p64_p128() { + let a: p128 = 0; + let e: i64x2 = i64x2::new(0, 0); + let r: i64x2 = transmute(vreinterpretq_p64_p128(transmute(a))); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vreinterpret_s16_p8() { let a: i8x8 = i8x8::new(0, 0, 1, 0, 2, 0, 3, 0); @@ -25834,6 +36109,62 @@ mod test { assert_eq!(r, e); } + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpret_p64_s32() { + let a: i32x2 = i32x2::new(0, 0); + let e: i64x1 = i64x1::new(0); + let r: i64x1 = transmute(vreinterpret_p64_s32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpret_p64_u32() { + let a: u32x2 = u32x2::new(0, 0); + let e: i64x1 = i64x1::new(0); + let r: i64x1 = transmute(vreinterpret_p64_u32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_p64_s32() { + let a: i32x4 = i32x4::new(0, 0, 1, 0); + let e: i64x2 = i64x2::new(0, 1); + let r: i64x2 = transmute(vreinterpretq_p64_s32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_p64_u32() { + let a: u32x4 = u32x4::new(0, 0, 1, 0); + let e: i64x2 = i64x2::new(0, 1); + let r: i64x2 = transmute(vreinterpretq_p64_u32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_p128_s64() { + let a: i64x2 = i64x2::new(0, 0); + let e: p128 = 0; + let r: p128 = transmute(vreinterpretq_p128_s64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_p128_u64() { + let a: u64x2 = u64x2::new(0, 0); + let e: p128 = 0; + let r: p128 = transmute(vreinterpretq_p128_u64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_p128_p64() { + let a: i64x2 = i64x2::new(0, 0); + let e: p128 = 0; + let r: p128 = transmute(vreinterpretq_p128_p64(transmute(a))); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vreinterpret_s8_s32() { let a: i32x2 = i32x2::new(0, 1); @@ -25979,50 +36310,114 @@ mod test { } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpret_p16_s64() { + unsafe fn test_vreinterpret_p16_s64() { + let a: i64x1 = i64x1::new(0); + let e: i16x4 = i16x4::new(0, 0, 0, 0); + let r: i16x4 = transmute(vreinterpret_p16_s64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpret_p16_u64() { + let a: u64x1 = u64x1::new(0); + let e: i16x4 = i16x4::new(0, 0, 0, 0); + let r: i16x4 = transmute(vreinterpret_p16_u64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_p8_s32() { + let a: i32x4 = i32x4::new(0, 1, 2, 3); + let e: i8x16 = i8x16::new(0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0); + let r: i8x16 = transmute(vreinterpretq_p8_s32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_p8_u32() { + let a: u32x4 = u32x4::new(0, 1, 2, 3); + let e: i8x16 = i8x16::new(0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0); + let r: i8x16 = transmute(vreinterpretq_p8_u32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_p16_s64() { + let a: i64x2 = i64x2::new(0, 1); + let e: i16x8 = i16x8::new(0, 0, 0, 0, 1, 0, 0, 0); + let r: i16x8 = transmute(vreinterpretq_p16_s64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_p16_u64() { + let a: u64x2 = u64x2::new(0, 1); + let e: i16x8 = i16x8::new(0, 0, 0, 0, 1, 0, 0, 0); + let r: i16x8 = transmute(vreinterpretq_p16_u64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpret_s16_p64() { + let a: i64x1 = i64x1::new(0); + let e: i16x4 = i16x4::new(0, 0, 0, 0); + let r: i16x4 = transmute(vreinterpret_s16_p64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpret_u16_p64() { let a: i64x1 = i64x1::new(0); - let e: i16x4 = i16x4::new(0, 0, 0, 0); - let r: i16x4 = transmute(vreinterpret_p16_s64(transmute(a))); + let e: u16x4 = u16x4::new(0, 0, 0, 0); + let r: u16x4 = transmute(vreinterpret_u16_p64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpret_p16_u64() { - let a: u64x1 = u64x1::new(0); + unsafe fn test_vreinterpret_p16_p64() { + let a: i64x1 = i64x1::new(0); let e: i16x4 = i16x4::new(0, 0, 0, 0); - let r: i16x4 = transmute(vreinterpret_p16_u64(transmute(a))); + let r: i16x4 = transmute(vreinterpret_p16_p64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpretq_p8_s32() { - let a: i32x4 = i32x4::new(0, 1, 2, 3); - let e: i8x16 = i8x16::new(0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0); - let r: i8x16 = transmute(vreinterpretq_p8_s32(transmute(a))); + unsafe fn test_vreinterpretq_s16_p64() { + let a: i64x2 = i64x2::new(0, 1); + let e: i16x8 = i16x8::new(0, 0, 0, 0, 1, 0, 0, 0); + let r: i16x8 = transmute(vreinterpretq_s16_p64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpretq_p8_u32() { - let a: u32x4 = u32x4::new(0, 1, 2, 3); - let e: i8x16 = i8x16::new(0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0); - let r: i8x16 = transmute(vreinterpretq_p8_u32(transmute(a))); + unsafe fn test_vreinterpretq_u16_p64() { + let a: i64x2 = i64x2::new(0, 1); + let e: u16x8 = u16x8::new(0, 0, 0, 0, 1, 0, 0, 0); + let r: u16x8 = transmute(vreinterpretq_u16_p64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpretq_p16_s64() { + unsafe fn test_vreinterpretq_p16_p64() { let a: i64x2 = i64x2::new(0, 1); let e: i16x8 = i16x8::new(0, 0, 0, 0, 1, 0, 0, 0); - let r: i16x8 = transmute(vreinterpretq_p16_s64(transmute(a))); + let r: i16x8 = transmute(vreinterpretq_p16_p64(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vreinterpretq_p16_u64() { - let a: u64x2 = u64x2::new(0, 1); - let e: i16x8 = i16x8::new(0, 0, 0, 0, 1, 0, 0, 0); - let r: i16x8 = transmute(vreinterpretq_p16_u64(transmute(a))); + unsafe fn test_vreinterpretq_s32_p128() { + let a: p128 = 0; + let e: i32x4 = i32x4::new(0, 0, 0, 0); + let r: i32x4 = transmute(vreinterpretq_s32_p128(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_u32_p128() { + let a: p128 = 0; + let e: u32x4 = u32x4::new(0, 0, 0, 0); + let r: u32x4 = transmute(vreinterpretq_u32_p128(transmute(a))); assert_eq!(r, e); } @@ -26218,6 +36613,70 @@ mod test { assert_eq!(r, e); } + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpret_p64_p16() { + let a: i16x4 = i16x4::new(0, 0, 0, 0); + let e: i64x1 = i64x1::new(0); + let r: i64x1 = transmute(vreinterpret_p64_p16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpret_p64_s16() { + let a: i16x4 = i16x4::new(0, 0, 0, 0); + let e: i64x1 = i64x1::new(0); + let r: i64x1 = transmute(vreinterpret_p64_s16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpret_p64_u16() { + let a: u16x4 = u16x4::new(0, 0, 0, 0); + let e: i64x1 = i64x1::new(0); + let r: i64x1 = transmute(vreinterpret_p64_u16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_p64_p16() { + let a: i16x8 = i16x8::new(0, 0, 0, 0, 1, 0, 0, 0); + let e: i64x2 = i64x2::new(0, 1); + let r: i64x2 = transmute(vreinterpretq_p64_p16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_p64_s16() { + let a: i16x8 = i16x8::new(0, 0, 0, 0, 1, 0, 0, 0); + let e: i64x2 = i64x2::new(0, 1); + let r: i64x2 = transmute(vreinterpretq_p64_s16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_p64_u16() { + let a: u16x8 = u16x8::new(0, 0, 0, 0, 1, 0, 0, 0); + let e: i64x2 = i64x2::new(0, 1); + let r: i64x2 = transmute(vreinterpretq_p64_u16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_p128_s32() { + let a: i32x4 = i32x4::new(0, 0, 0, 0); + let e: p128 = 0; + let r: p128 = transmute(vreinterpretq_p128_s32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_p128_u32() { + let a: u32x4 = u32x4::new(0, 0, 0, 0); + let e: p128 = 0; + let r: p128 = transmute(vreinterpretq_p128_u32(transmute(a))); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vreinterpret_s8_s64() { let a: i64x1 = i64x1::new(0); @@ -26314,6 +36773,78 @@ mod test { assert_eq!(r, e); } + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpret_s8_p64() { + let a: i64x1 = i64x1::new(0); + let e: i8x8 = i8x8::new(0, 0, 0, 0, 0, 0, 0, 0); + let r: i8x8 = transmute(vreinterpret_s8_p64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpret_u8_p64() { + let a: i64x1 = i64x1::new(0); + let e: u8x8 = u8x8::new(0, 0, 0, 0, 0, 0, 0, 0); + let r: u8x8 = transmute(vreinterpret_u8_p64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpret_p8_p64() { + let a: i64x1 = i64x1::new(0); + let e: i8x8 = i8x8::new(0, 0, 0, 0, 0, 0, 0, 0); + let r: i8x8 = transmute(vreinterpret_p8_p64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_s8_p64() { + let a: i64x2 = i64x2::new(0, 1); + let e: i8x16 = i8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0); + let r: i8x16 = transmute(vreinterpretq_s8_p64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_u8_p64() { + let a: i64x2 = i64x2::new(0, 1); + let e: u8x16 = u8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0); + let r: u8x16 = transmute(vreinterpretq_u8_p64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_p8_p64() { + let a: i64x2 = i64x2::new(0, 1); + let e: i8x16 = i8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0); + let r: i8x16 = transmute(vreinterpretq_p8_p64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_s16_p128() { + let a: p128 = 0; + let e: i16x8 = i16x8::new(0, 0, 0, 0, 0, 0, 0, 0); + let r: i16x8 = transmute(vreinterpretq_s16_p128(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_u16_p128() { + let a: p128 = 0; + let e: u16x8 = u16x8::new(0, 0, 0, 0, 0, 0, 0, 0); + let r: u16x8 = transmute(vreinterpretq_u16_p128(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_p16_p128() { + let a: p128 = 0; + let e: i16x8 = i16x8::new(0, 0, 0, 0, 0, 0, 0, 0); + let r: i16x8 = transmute(vreinterpretq_p16_p128(transmute(a))); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vreinterpret_s64_p8() { let a: i8x8 = i8x8::new(0, 0, 0, 0, 0, 0, 0, 0); @@ -26410,6 +36941,126 @@ mod test { assert_eq!(r, e); } + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpret_p64_p8() { + let a: i8x8 = i8x8::new(0, 0, 0, 0, 0, 0, 0, 0); + let e: i64x1 = i64x1::new(0); + let r: i64x1 = transmute(vreinterpret_p64_p8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpret_p64_s8() { + let a: i8x8 = i8x8::new(0, 0, 0, 0, 0, 0, 0, 0); + let e: i64x1 = i64x1::new(0); + let r: i64x1 = transmute(vreinterpret_p64_s8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpret_p64_u8() { + let a: u8x8 = u8x8::new(0, 0, 0, 0, 0, 0, 0, 0); + let e: i64x1 = i64x1::new(0); + let r: i64x1 = transmute(vreinterpret_p64_u8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_p64_p8() { + let a: i8x16 = i8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0); + let e: i64x2 = i64x2::new(0, 1); + let r: i64x2 = transmute(vreinterpretq_p64_p8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_p64_s8() { + let a: i8x16 = i8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0); + let e: i64x2 = i64x2::new(0, 1); + let r: i64x2 = transmute(vreinterpretq_p64_s8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_p64_u8() { + let a: u8x16 = u8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0); + let e: i64x2 = i64x2::new(0, 1); + let r: i64x2 = transmute(vreinterpretq_p64_u8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_p128_s16() { + let a: i16x8 = i16x8::new(0, 0, 0, 0, 0, 0, 0, 0); + let e: p128 = 0; + let r: p128 = transmute(vreinterpretq_p128_s16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_p128_u16() { + let a: u16x8 = u16x8::new(0, 0, 0, 0, 0, 0, 0, 0); + let e: p128 = 0; + let r: p128 = transmute(vreinterpretq_p128_u16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_p128_p16() { + let a: i16x8 = i16x8::new(0, 0, 0, 0, 0, 0, 0, 0); + let e: p128 = 0; + let r: p128 = transmute(vreinterpretq_p128_p16(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_p128_s8() { + let a: i8x16 = i8x16::new(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + let e: p128 = 1; + let r: p128 = transmute(vreinterpretq_p128_s8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_p128_u8() { + let a: u8x16 = u8x16::new(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + let e: p128 = 1; + let r: p128 = transmute(vreinterpretq_p128_u8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_p128_p8() { + let a: i8x16 = i8x16::new(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + let e: p128 = 1; + let r: p128 = transmute(vreinterpretq_p128_p8(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_s8_p128() { + let a: p128 = 1; + let e: i8x16 = i8x16::new(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + let r: i8x16 = transmute(vreinterpretq_s8_p128(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_u8_p128() { + let a: p128 = 1; + let e: u8x16 = u8x16::new(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + let r: u8x16 = transmute(vreinterpretq_u8_p128(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_p8_p128() { + let a: p128 = 1; + let e: i8x16 = i8x16::new(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + let r: i8x16 = transmute(vreinterpretq_p8_p128(transmute(a))); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vreinterpret_s8_f32() { let a: f32x2 = f32x2::new(0., 0.); @@ -26570,6 +37221,14 @@ mod test { assert_eq!(r, e); } + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_p128_f32() { + let a: f32x4 = f32x4::new(0., 0., 0., 0.); + let e: p128 = 0; + let r: p128 = transmute(vreinterpretq_p128_f32(transmute(a))); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vreinterpret_f32_s8() { let a: i8x8 = i8x8::new(0, 0, 0, 0, 0, 0, 0, 0); @@ -26730,6 +37389,14 @@ mod test { assert_eq!(r, e); } + #[simd_test(enable = "neon")] + unsafe fn test_vreinterpretq_f32_p128() { + let a: p128 = 0; + let e: f32x4 = f32x4::new(0., 0., 0., 0.); + let r: f32x4 = transmute(vreinterpretq_f32_p128(transmute(a))); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vrshl_s8() { let a: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); @@ -27159,38 +37826,92 @@ mod test { } #[simd_test(enable = "neon")] - unsafe fn test_vrsra_n_u32() { - let a: u32x2 = u32x2::new(1, 1); - let b: u32x2 = u32x2::new(4, 8); - let e: u32x2 = u32x2::new(2, 3); - let r: u32x2 = transmute(vrsra_n_u32::<2>(transmute(a), transmute(b))); + unsafe fn test_vrsra_n_u32() { + let a: u32x2 = u32x2::new(1, 1); + let b: u32x2 = u32x2::new(4, 8); + let e: u32x2 = u32x2::new(2, 3); + let r: u32x2 = transmute(vrsra_n_u32::<2>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vrsraq_n_u32() { + let a: u32x4 = u32x4::new(1, 1, 1, 1); + let b: u32x4 = u32x4::new(4, 8, 12, 16); + let e: u32x4 = u32x4::new(2, 3, 4, 5); + let r: u32x4 = transmute(vrsraq_n_u32::<2>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vrsra_n_u64() { + let a: u64x1 = u64x1::new(1); + let b: u64x1 = u64x1::new(4); + let e: u64x1 = u64x1::new(2); + let r: u64x1 = transmute(vrsra_n_u64::<2>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vrsraq_n_u64() { + let a: u64x2 = u64x2::new(1, 1); + let b: u64x2 = u64x2::new(4, 8); + let e: u64x2 = u64x2::new(2, 3); + let r: u64x2 = transmute(vrsraq_n_u64::<2>(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vrsubhn_s16() { + let a: i16x8 = i16x8::new(0x7F_FF, -32768, 0, 4, 5, 6, 7, 8); + let b: i16x8 = i16x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let e: i8x8 = i8x8::new(-128, -128, 0, 0, 0, 0, 0, 0); + let r: i8x8 = transmute(vrsubhn_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vrsubhn_s32() { + let a: i32x4 = i32x4::new(0x7F_FF_FF_FF, -2147483648, 0, 4); + let b: i32x4 = i32x4::new(1, 2, 3, 4); + let e: i16x4 = i16x4::new(-32768, -32768, 0, 0); + let r: i16x4 = transmute(vrsubhn_s32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrsraq_n_u32() { - let a: u32x4 = u32x4::new(1, 1, 1, 1); - let b: u32x4 = u32x4::new(4, 8, 12, 16); - let e: u32x4 = u32x4::new(2, 3, 4, 5); - let r: u32x4 = transmute(vrsraq_n_u32::<2>(transmute(a), transmute(b))); + unsafe fn test_vrsubhn_s64() { + let a: i64x2 = i64x2::new(0x7F_FF_FF_FF_FF_FF_FF_FF, -9223372036854775808); + let b: i64x2 = i64x2::new(1, 2); + let e: i32x2 = i32x2::new(-2147483648, -2147483648); + let r: i32x2 = transmute(vrsubhn_s64(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrsra_n_u64() { - let a: u64x1 = u64x1::new(1); - let b: u64x1 = u64x1::new(4); - let e: u64x1 = u64x1::new(2); - let r: u64x1 = transmute(vrsra_n_u64::<2>(transmute(a), transmute(b))); + unsafe fn test_vrsubhn_u16() { + let a: u16x8 = u16x8::new(0xFF_FF, 0, 3, 4, 5, 6, 7, 8); + let b: u16x8 = u16x8::new(1, 2, 3, 4, 5, 6, 7, 8); + let e: u8x8 = u8x8::new(0, 0, 0, 0, 0, 0, 0, 0); + let r: u8x8 = transmute(vrsubhn_u16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vrsraq_n_u64() { - let a: u64x2 = u64x2::new(1, 1); - let b: u64x2 = u64x2::new(4, 8); - let e: u64x2 = u64x2::new(2, 3); - let r: u64x2 = transmute(vrsraq_n_u64::<2>(transmute(a), transmute(b))); + unsafe fn test_vrsubhn_u32() { + let a: u32x4 = u32x4::new(0xFF_FF_FF_FF, 0, 3, 4); + let b: u32x4 = u32x4::new(1, 2, 3, 4); + let e: u16x4 = u16x4::new(0, 0, 0, 0); + let r: u16x4 = transmute(vrsubhn_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vrsubhn_u64() { + let a: u64x2 = u64x2::new(0xFF_FF_FF_FF_FF_FF_FF_FF, 0); + let b: u64x2 = u64x2::new(1, 2); + let e: u32x2 = u32x2::new(0, 0); + let r: u32x2 = transmute(vrsubhn_u64(transmute(a), transmute(b))); assert_eq!(r, e); } @@ -28050,6 +38771,492 @@ mod test { assert_eq!(r, e); } + #[simd_test(enable = "neon")] + unsafe fn test_vtrn_s8() { + let a: i8x8 = i8x8::new(0, 2, 2, 6, 2, 10, 6, 14); + let b: i8x8 = i8x8::new(1, 3, 3, 7, 3, 1, 7, 15); + let e: [i8; 16] = [0, 1, 2, 3, 2, 3, 6, 7, 2, 3, 6, 7, 10, 1, 14, 15]; + let r: [i8; 16] = transmute(vtrn_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtrn_s16() { + let a: i16x4 = i16x4::new(0, 2, 2, 6); + let b: i16x4 = i16x4::new(1, 3, 3, 7); + let e: [i16; 8] = [0, 1, 2, 3, 2, 3, 6, 7]; + let r: [i16; 8] = transmute(vtrn_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtrnq_s8() { + let a: i8x16 = i8x16::new(0, 2, 2, 6, 2, 10, 6, 14, 2, 18, 6, 22, 10, 26, 14, 30); + let b: i8x16 = i8x16::new(1, 3, 3, 7, 3, 1, 7, 15, 3, 19, 7, 23, 1, 27, 15, 31); + let e: [i8; 32] = [0, 1, 2, 3, 2, 3, 6, 7, 2, 3, 6, 7, 10, 1, 14, 15, 2, 3, 6, 7, 10, 1, 14, 15, 18, 19, 22, 23, 26, 27, 30, 31]; + let r: [i8; 32] = transmute(vtrnq_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtrnq_s16() { + let a: i16x8 = i16x8::new(0, 2, 2, 6, 2, 10, 6, 14); + let b: i16x8 = i16x8::new(1, 3, 3, 7, 3, 1, 7, 15); + let e: [i16; 16] = [0, 1, 2, 3, 2, 3, 6, 7, 2, 3, 6, 7, 10, 1, 14, 15]; + let r: [i16; 16] = transmute(vtrnq_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtrnq_s32() { + let a: i32x4 = i32x4::new(0, 2, 2, 6); + let b: i32x4 = i32x4::new(1, 3, 3, 7); + let e: [i32; 8] = [0, 1, 2, 3, 2, 3, 6, 7]; + let r: [i32; 8] = transmute(vtrnq_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtrn_u8() { + let a: u8x8 = u8x8::new(0, 2, 2, 6, 2, 10, 6, 14); + let b: u8x8 = u8x8::new(1, 3, 3, 7, 3, 1, 7, 15); + let e: [u8; 16] = [0, 1, 2, 3, 2, 3, 6, 7, 2, 3, 6, 7, 10, 1, 14, 15]; + let r: [u8; 16] = transmute(vtrn_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtrn_u16() { + let a: u16x4 = u16x4::new(0, 2, 2, 6); + let b: u16x4 = u16x4::new(1, 3, 3, 7); + let e: [u16; 8] = [0, 1, 2, 3, 2, 3, 6, 7]; + let r: [u16; 8] = transmute(vtrn_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtrnq_u8() { + let a: u8x16 = u8x16::new(0, 2, 2, 6, 2, 10, 6, 14, 2, 18, 6, 22, 10, 26, 14, 30); + let b: u8x16 = u8x16::new(1, 3, 3, 7, 3, 1, 7, 15, 3, 19, 7, 23, 1, 27, 15, 31); + let e: [u8; 32] = [0, 1, 2, 3, 2, 3, 6, 7, 2, 3, 6, 7, 10, 1, 14, 15, 2, 3, 6, 7, 10, 1, 14, 15, 18, 19, 22, 23, 26, 27, 30, 31]; + let r: [u8; 32] = transmute(vtrnq_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtrnq_u16() { + let a: u16x8 = u16x8::new(0, 2, 2, 6, 2, 10, 6, 14); + let b: u16x8 = u16x8::new(1, 3, 3, 7, 3, 1, 7, 15); + let e: [u16; 16] = [0, 1, 2, 3, 2, 3, 6, 7, 2, 3, 6, 7, 10, 1, 14, 15]; + let r: [u16; 16] = transmute(vtrnq_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtrnq_u32() { + let a: u32x4 = u32x4::new(0, 2, 2, 6); + let b: u32x4 = u32x4::new(1, 3, 3, 7); + let e: [u32; 8] = [0, 1, 2, 3, 2, 3, 6, 7]; + let r: [u32; 8] = transmute(vtrnq_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtrn_p8() { + let a: i8x8 = i8x8::new(0, 2, 2, 6, 2, 10, 6, 14); + let b: i8x8 = i8x8::new(1, 3, 3, 7, 3, 1, 7, 15); + let e: [u8; 16] = [0, 1, 2, 3, 2, 3, 6, 7, 2, 3, 6, 7, 10, 1, 14, 15]; + let r: [u8; 16] = transmute(vtrn_p8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtrn_p16() { + let a: i16x4 = i16x4::new(0, 2, 2, 6); + let b: i16x4 = i16x4::new(1, 3, 3, 7); + let e: [u16; 8] = [0, 1, 2, 3, 2, 3, 6, 7]; + let r: [u16; 8] = transmute(vtrn_p16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtrnq_p8() { + let a: i8x16 = i8x16::new(0, 2, 2, 6, 2, 10, 6, 14, 2, 18, 6, 22, 10, 26, 14, 30); + let b: i8x16 = i8x16::new(1, 3, 3, 7, 3, 1, 7, 15, 3, 19, 7, 23, 1, 27, 15, 31); + let e: [u8; 32] = [0, 1, 2, 3, 2, 3, 6, 7, 2, 3, 6, 7, 10, 1, 14, 15, 2, 3, 6, 7, 10, 1, 14, 15, 18, 19, 22, 23, 26, 27, 30, 31]; + let r: [u8; 32] = transmute(vtrnq_p8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtrnq_p16() { + let a: i16x8 = i16x8::new(0, 2, 2, 6, 2, 10, 6, 14); + let b: i16x8 = i16x8::new(1, 3, 3, 7, 3, 1, 7, 15); + let e: [u16; 16] = [0, 1, 2, 3, 2, 3, 6, 7, 2, 3, 6, 7, 10, 1, 14, 15]; + let r: [u16; 16] = transmute(vtrnq_p16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtrn_s32() { + let a: i32x2 = i32x2::new(0, 2); + let b: i32x2 = i32x2::new(1, 3); + let e: [i32; 4] = [0, 1, 2, 3]; + let r: [i32; 4] = transmute(vtrn_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtrn_u32() { + let a: u32x2 = u32x2::new(0, 2); + let b: u32x2 = u32x2::new(1, 3); + let e: [u32; 4] = [0, 1, 2, 3]; + let r: [u32; 4] = transmute(vtrn_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtrn_f32() { + let a: f32x2 = f32x2::new(0., 2.); + let b: f32x2 = f32x2::new(1., 3.); + let e: [f32; 4] = [0., 1., 2., 3.]; + let r: [f32; 4] = transmute(vtrn_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtrnq_f32() { + let a: f32x4 = f32x4::new(0., 2., 2., 6.); + let b: f32x4 = f32x4::new(1., 3., 3., 7.); + let e: [f32; 8] = [0., 1., 2., 3., 2., 3., 6., 7.]; + let r: [f32; 8] = transmute(vtrnq_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vzip_s8() { + let a: i8x8 = i8x8::new(0, 2, 4, 6, 8, 10, 12, 14); + let b: i8x8 = i8x8::new(1, 3, 5, 7, 9, 11, 13, 15); + let e: [i8; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + let r: [i8; 16] = transmute(vzip_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vzip_s16() { + let a: i16x4 = i16x4::new(0, 2, 4, 6); + let b: i16x4 = i16x4::new(1, 3, 5, 7); + let e: [i16; 8] = [0, 1, 2, 3, 4, 5, 6, 7]; + let r: [i16; 8] = transmute(vzip_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vzip_u8() { + let a: u8x8 = u8x8::new(0, 2, 4, 6, 8, 10, 12, 14); + let b: u8x8 = u8x8::new(1, 3, 5, 7, 9, 11, 13, 15); + let e: [u8; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + let r: [u8; 16] = transmute(vzip_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vzip_u16() { + let a: u16x4 = u16x4::new(0, 2, 4, 6); + let b: u16x4 = u16x4::new(1, 3, 5, 7); + let e: [u16; 8] = [0, 1, 2, 3, 4, 5, 6, 7]; + let r: [u16; 8] = transmute(vzip_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vzip_p8() { + let a: i8x8 = i8x8::new(0, 2, 4, 6, 8, 10, 12, 14); + let b: i8x8 = i8x8::new(1, 3, 5, 7, 9, 11, 13, 15); + let e: [u8; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + let r: [u8; 16] = transmute(vzip_p8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vzip_p16() { + let a: i16x4 = i16x4::new(0, 2, 4, 6); + let b: i16x4 = i16x4::new(1, 3, 5, 7); + let e: [u16; 8] = [0, 1, 2, 3, 4, 5, 6, 7]; + let r: [u16; 8] = transmute(vzip_p16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vzip_s32() { + let a: i32x2 = i32x2::new(0, 2); + let b: i32x2 = i32x2::new(1, 3); + let e: [i32; 4] = [0, 1, 2, 3]; + let r: [i32; 4] = transmute(vzip_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vzip_u32() { + let a: u32x2 = u32x2::new(0, 2); + let b: u32x2 = u32x2::new(1, 3); + let e: [u32; 4] = [0, 1, 2, 3]; + let r: [u32; 4] = transmute(vzip_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vzipq_s8() { + let a: i8x16 = i8x16::new(0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30); + let b: i8x16 = i8x16::new(1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31); + let e: [i8; 32] = [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: [i8; 32] = transmute(vzipq_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vzipq_s16() { + let a: i16x8 = i16x8::new(0, 2, 4, 6, 8, 10, 12, 14); + let b: i16x8 = i16x8::new(1, 3, 5, 7, 9, 11, 13, 15); + let e: [i16; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + let r: [i16; 16] = transmute(vzipq_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vzipq_s32() { + let a: i32x4 = i32x4::new(0, 2, 4, 6); + let b: i32x4 = i32x4::new(1, 3, 5, 7); + let e: [i32; 8] = [0, 1, 2, 3, 4, 5, 6, 7]; + let r: [i32; 8] = transmute(vzipq_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vzipq_u8() { + let a: u8x16 = u8x16::new(0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30); + let b: u8x16 = u8x16::new(1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31); + let e: [u8; 32] = [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: [u8; 32] = transmute(vzipq_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vzipq_u16() { + let a: u16x8 = u16x8::new(0, 2, 4, 6, 8, 10, 12, 14); + let b: u16x8 = u16x8::new(1, 3, 5, 7, 9, 11, 13, 15); + let e: [u16; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + let r: [u16; 16] = transmute(vzipq_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vzipq_u32() { + let a: u32x4 = u32x4::new(0, 2, 4, 6); + let b: u32x4 = u32x4::new(1, 3, 5, 7); + let e: [u32; 8] = [0, 1, 2, 3, 4, 5, 6, 7]; + let r: [u32; 8] = transmute(vzipq_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vzipq_p8() { + let a: i8x16 = i8x16::new(0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30); + let b: i8x16 = i8x16::new(1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31); + let e: [u8; 32] = [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: [u8; 32] = transmute(vzipq_p8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vzipq_p16() { + let a: i16x8 = i16x8::new(0, 2, 4, 6, 8, 10, 12, 14); + let b: i16x8 = i16x8::new(1, 3, 5, 7, 9, 11, 13, 15); + let e: [u16; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + let r: [u16; 16] = transmute(vzipq_p16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vzip_f32() { + let a: f32x2 = f32x2::new(1., 2.); + let b: f32x2 = f32x2::new(5., 6.); + let e: [f32; 4] = [1., 5., 2., 6.]; + let r: [f32; 4] = transmute(vzip_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vzipq_f32() { + let a: f32x4 = f32x4::new(1., 2., 3., 4.); + let b: f32x4 = f32x4::new(5., 6., 7., 8.); + let e: [f32; 8] = [1., 5., 2., 6., 3., 7., 4., 8.]; + let r: [f32; 8] = transmute(vzipq_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vuzp_s8() { + let a: i8x8 = i8x8::new(1, 2, 2, 3, 2, 3, 3, 8); + let b: i8x8 = i8x8::new(2, 3, 3, 8, 3, 15, 8, 16); + let e: [i8; 16] = [1, 2, 2, 3, 2, 3, 3, 8, 2, 3, 3, 8, 3, 8, 15, 16]; + let r: [i8; 16] = transmute(vuzp_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vuzp_s16() { + let a: i16x4 = i16x4::new(1, 2, 2, 3); + let b: i16x4 = i16x4::new(2, 3, 3, 8); + let e: [i16; 8] = [1, 2, 2, 3, 2, 3, 3, 8]; + let r: [i16; 8] = transmute(vuzp_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vuzpq_s8() { + let a: i8x16 = i8x16::new(1, 2, 2, 3, 2, 3, 3, 8, 2, 3, 3, 8, 3, 15, 8, 16); + let b: i8x16 = i8x16::new(2, 3, 3, 8, 3, 15, 8, 16, 3, 29, 8, 30, 15, 31, 16, 32); + let e: [i8; 32] = [1, 2, 2, 3, 2, 3, 3, 8, 2, 3, 3, 8, 3, 8, 15, 16, 2, 3, 3, 8, 3, 8, 15, 16, 3, 8, 15, 16, 29, 30, 31, 32]; + let r: [i8; 32] = transmute(vuzpq_s8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vuzpq_s16() { + let a: i16x8 = i16x8::new(1, 2, 2, 3, 2, 3, 3, 8); + let b: i16x8 = i16x8::new(2, 3, 3, 8, 3, 15, 8, 16); + let e: [i16; 16] = [1, 2, 2, 3, 2, 3, 3, 8, 2, 3, 3, 8, 3, 8, 15, 16]; + let r: [i16; 16] = transmute(vuzpq_s16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vuzpq_s32() { + let a: i32x4 = i32x4::new(1, 2, 2, 3); + let b: i32x4 = i32x4::new(2, 3, 3, 8); + let e: [i32; 8] = [1, 2, 2, 3, 2, 3, 3, 8]; + let r: [i32; 8] = transmute(vuzpq_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vuzp_u8() { + let a: u8x8 = u8x8::new(1, 2, 2, 3, 2, 3, 3, 8); + let b: u8x8 = u8x8::new(2, 3, 3, 8, 3, 15, 8, 16); + let e: [u8; 16] = [1, 2, 2, 3, 2, 3, 3, 8, 2, 3, 3, 8, 3, 8, 15, 16]; + let r: [u8; 16] = transmute(vuzp_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vuzp_u16() { + let a: u16x4 = u16x4::new(1, 2, 2, 3); + let b: u16x4 = u16x4::new(2, 3, 3, 8); + let e: [u16; 8] = [1, 2, 2, 3, 2, 3, 3, 8]; + let r: [u16; 8] = transmute(vuzp_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vuzpq_u8() { + let a: u8x16 = u8x16::new(1, 2, 2, 3, 2, 3, 3, 8, 2, 3, 3, 8, 3, 15, 8, 16); + let b: u8x16 = u8x16::new(2, 3, 3, 8, 3, 15, 8, 16, 3, 29, 8, 30, 15, 31, 16, 32); + let e: [u8; 32] = [1, 2, 2, 3, 2, 3, 3, 8, 2, 3, 3, 8, 3, 8, 15, 16, 2, 3, 3, 8, 3, 8, 15, 16, 3, 8, 15, 16, 29, 30, 31, 32]; + let r: [u8; 32] = transmute(vuzpq_u8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vuzpq_u16() { + let a: u16x8 = u16x8::new(1, 2, 2, 3, 2, 3, 3, 8); + let b: u16x8 = u16x8::new(2, 3, 3, 8, 3, 15, 8, 16); + let e: [u16; 16] = [1, 2, 2, 3, 2, 3, 3, 8, 2, 3, 3, 8, 3, 8, 15, 16]; + let r: [u16; 16] = transmute(vuzpq_u16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vuzpq_u32() { + let a: u32x4 = u32x4::new(1, 2, 2, 3); + let b: u32x4 = u32x4::new(2, 3, 3, 8); + let e: [u32; 8] = [1, 2, 2, 3, 2, 3, 3, 8]; + let r: [u32; 8] = transmute(vuzpq_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vuzp_p8() { + let a: i8x8 = i8x8::new(1, 2, 2, 3, 2, 3, 3, 8); + let b: i8x8 = i8x8::new(2, 3, 3, 8, 3, 15, 8, 16); + let e: [u8; 16] = [1, 2, 2, 3, 2, 3, 3, 8, 2, 3, 3, 8, 3, 8, 15, 16]; + let r: [u8; 16] = transmute(vuzp_p8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vuzp_p16() { + let a: i16x4 = i16x4::new(1, 2, 2, 3); + let b: i16x4 = i16x4::new(2, 3, 3, 8); + let e: [u16; 8] = [1, 2, 2, 3, 2, 3, 3, 8]; + let r: [u16; 8] = transmute(vuzp_p16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vuzpq_p8() { + let a: i8x16 = i8x16::new(1, 2, 2, 3, 2, 3, 3, 8, 2, 3, 3, 8, 3, 15, 8, 16); + let b: i8x16 = i8x16::new(2, 3, 3, 8, 3, 15, 8, 16, 3, 29, 8, 30, 15, 31, 16, 32); + let e: [u8; 32] = [1, 2, 2, 3, 2, 3, 3, 8, 2, 3, 3, 8, 3, 8, 15, 16, 2, 3, 3, 8, 3, 8, 15, 16, 3, 8, 15, 16, 29, 30, 31, 32]; + let r: [u8; 32] = transmute(vuzpq_p8(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vuzpq_p16() { + let a: i16x8 = i16x8::new(1, 2, 2, 3, 2, 3, 3, 8); + let b: i16x8 = i16x8::new(2, 3, 3, 8, 3, 15, 8, 16); + let e: [u16; 16] = [1, 2, 2, 3, 2, 3, 3, 8, 2, 3, 3, 8, 3, 8, 15, 16]; + let r: [u16; 16] = transmute(vuzpq_p16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vuzp_s32() { + let a: i32x2 = i32x2::new(1, 2); + let b: i32x2 = i32x2::new(2, 3); + let e: [i32; 4] = [1, 2, 2, 3]; + let r: [i32; 4] = transmute(vuzp_s32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vuzp_u32() { + let a: u32x2 = u32x2::new(1, 2); + let b: u32x2 = u32x2::new(2, 3); + let e: [u32; 4] = [1, 2, 2, 3]; + let r: [u32; 4] = transmute(vuzp_u32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vuzp_f32() { + let a: f32x2 = f32x2::new(1., 2.); + let b: f32x2 = f32x2::new(2., 6.); + let e: [f32; 4] = [1., 2., 2., 6.]; + let r: [f32; 4] = transmute(vuzp_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vuzpq_f32() { + let a: f32x4 = f32x4::new(1., 2., 2., 4.); + let b: f32x4 = f32x4::new(2., 6., 6., 8.); + let e: [f32; 8] = [1., 2., 2., 6., 2., 4., 6., 8.]; + let r: [f32; 8] = transmute(vuzpq_f32(transmute(a), transmute(b))); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vabal_u8() { let a: u16x8 = u16x8::new(1, 2, 3, 4, 5, 6, 7, 8); diff --git a/library/stdarch/crates/core_arch/src/arm_shared/neon/mod.rs b/library/stdarch/crates/core_arch/src/arm_shared/neon/mod.rs index d3f88abd9b..d348125a2a 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/neon/mod.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/neon/mod.rs @@ -83,43 +83,43 @@ types! { } /// ARM-specific type containing two `int8x8_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct int8x8x2_t(pub int8x8_t, pub int8x8_t); /// ARM-specific type containing three `int8x8_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct int8x8x3_t(pub int8x8_t, pub int8x8_t, pub int8x8_t); /// ARM-specific type containing four `int8x8_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct int8x8x4_t(pub int8x8_t, pub int8x8_t, pub int8x8_t, pub int8x8_t); /// ARM-specific type containing two `int8x16_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct int8x16x2_t(pub int8x16_t, pub int8x16_t); /// ARM-specific type containing three `int8x16_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct int8x16x3_t(pub int8x16_t, pub int8x16_t, pub int8x16_t); /// ARM-specific type containing four `int8x16_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct int8x16x4_t(pub int8x16_t, pub int8x16_t, pub int8x16_t, pub int8x16_t); /// ARM-specific type containing two `uint8x8_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct uint8x8x2_t(pub uint8x8_t, pub uint8x8_t); /// ARM-specific type containing three `uint8x8_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct uint8x8x3_t(pub uint8x8_t, pub uint8x8_t, pub uint8x8_t); /// ARM-specific type containing four `uint8x8_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct uint8x8x4_t(pub uint8x8_t, pub uint8x8_t, pub uint8x8_t, pub uint8x8_t); /// ARM-specific type containing two `uint8x16_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct uint8x16x2_t(pub uint8x16_t, pub uint8x16_t); /// ARM-specific type containing three `uint8x16_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct uint8x16x3_t(pub uint8x16_t, pub uint8x16_t, pub uint8x16_t); /// ARM-specific type containing four `uint8x16_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct uint8x16x4_t( pub uint8x16_t, pub uint8x16_t, @@ -128,23 +128,23 @@ pub struct uint8x16x4_t( ); /// ARM-specific type containing two `poly8x8_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct poly8x8x2_t(pub poly8x8_t, pub poly8x8_t); /// ARM-specific type containing three `poly8x8_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct poly8x8x3_t(pub poly8x8_t, pub poly8x8_t, pub poly8x8_t); /// ARM-specific type containing four `poly8x8_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct poly8x8x4_t(pub poly8x8_t, pub poly8x8_t, pub poly8x8_t, pub poly8x8_t); /// ARM-specific type containing two `poly8x16_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct poly8x16x2_t(pub poly8x16_t, pub poly8x16_t); /// ARM-specific type containing three `poly8x16_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct poly8x16x3_t(pub poly8x16_t, pub poly8x16_t, pub poly8x16_t); /// ARM-specific type containing four `poly8x16_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct poly8x16x4_t( pub poly8x16_t, pub poly8x16_t, @@ -153,33 +153,33 @@ pub struct poly8x16x4_t( ); /// ARM-specific type containing two `int16x4_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct int16x4x2_t(pub int16x4_t, pub int16x4_t); /// ARM-specific type containing three `int16x4_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct int16x4x3_t(pub int16x4_t, pub int16x4_t, pub int16x4_t); /// ARM-specific type containing four `int16x4_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct int16x4x4_t(pub int16x4_t, pub int16x4_t, pub int16x4_t, pub int16x4_t); /// ARM-specific type containing two `int16x8_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct int16x8x2_t(pub int16x8_t, pub int16x8_t); /// ARM-specific type containing three `int16x8_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct int16x8x3_t(pub int16x8_t, pub int16x8_t, pub int16x8_t); /// ARM-specific type containing four `int16x8_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct int16x8x4_t(pub int16x8_t, pub int16x8_t, pub int16x8_t, pub int16x8_t); /// ARM-specific type containing two `uint16x4_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct uint16x4x2_t(pub uint16x4_t, pub uint16x4_t); /// ARM-specific type containing three `uint16x4_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct uint16x4x3_t(pub uint16x4_t, pub uint16x4_t, pub uint16x4_t); /// ARM-specific type containing four `uint16x4_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct uint16x4x4_t( pub uint16x4_t, pub uint16x4_t, @@ -188,13 +188,13 @@ pub struct uint16x4x4_t( ); /// ARM-specific type containing two `uint16x8_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct uint16x8x2_t(pub uint16x8_t, pub uint16x8_t); /// ARM-specific type containing three `uint16x8_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct uint16x8x3_t(pub uint16x8_t, pub uint16x8_t, pub uint16x8_t); /// ARM-specific type containing four `uint16x8_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct uint16x8x4_t( pub uint16x8_t, pub uint16x8_t, @@ -203,13 +203,13 @@ pub struct uint16x8x4_t( ); /// ARM-specific type containing two `poly16x4_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct poly16x4x2_t(pub poly16x4_t, pub poly16x4_t); /// ARM-specific type containing three `poly16x4_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct poly16x4x3_t(pub poly16x4_t, pub poly16x4_t, pub poly16x4_t); /// ARM-specific type containing four `poly16x4_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct poly16x4x4_t( pub poly16x4_t, pub poly16x4_t, @@ -218,13 +218,13 @@ pub struct poly16x4x4_t( ); /// ARM-specific type containing two `poly16x8_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct poly16x8x2_t(pub poly16x8_t, pub poly16x8_t); /// ARM-specific type containing three `poly16x8_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct poly16x8x3_t(pub poly16x8_t, pub poly16x8_t, pub poly16x8_t); /// ARM-specific type containing four `poly16x8_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct poly16x8x4_t( pub poly16x8_t, pub poly16x8_t, @@ -233,33 +233,33 @@ pub struct poly16x8x4_t( ); /// ARM-specific type containing two `int32x2_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct int32x2x2_t(pub int32x2_t, pub int32x2_t); /// ARM-specific type containing three `int32x2_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct int32x2x3_t(pub int32x2_t, pub int32x2_t, pub int32x2_t); /// ARM-specific type containing four `int32x2_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct int32x2x4_t(pub int32x2_t, pub int32x2_t, pub int32x2_t, pub int32x2_t); /// ARM-specific type containing two `int32x4_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct int32x4x2_t(pub int32x4_t, pub int32x4_t); /// ARM-specific type containing three `int32x4_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct int32x4x3_t(pub int32x4_t, pub int32x4_t, pub int32x4_t); /// ARM-specific type containing four `int32x4_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct int32x4x4_t(pub int32x4_t, pub int32x4_t, pub int32x4_t, pub int32x4_t); /// ARM-specific type containing two `uint32x2_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct uint32x2x2_t(pub uint32x2_t, pub uint32x2_t); /// ARM-specific type containing three `uint32x2_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct uint32x2x3_t(pub uint32x2_t, pub uint32x2_t, pub uint32x2_t); /// ARM-specific type containing four `uint32x2_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct uint32x2x4_t( pub uint32x2_t, pub uint32x2_t, @@ -268,13 +268,13 @@ pub struct uint32x2x4_t( ); /// ARM-specific type containing two `uint32x4_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct uint32x4x2_t(pub uint32x4_t, pub uint32x4_t); /// ARM-specific type containing three `uint32x4_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct uint32x4x3_t(pub uint32x4_t, pub uint32x4_t, pub uint32x4_t); /// ARM-specific type containing four `uint32x4_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct uint32x4x4_t( pub uint32x4_t, pub uint32x4_t, @@ -283,13 +283,13 @@ pub struct uint32x4x4_t( ); /// ARM-specific type containing two `float32x2_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct float32x2x2_t(pub float32x2_t, pub float32x2_t); /// ARM-specific type containing three `float32x2_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct float32x2x3_t(pub float32x2_t, pub float32x2_t, pub float32x2_t); /// ARM-specific type containing four `float32x2_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct float32x2x4_t( pub float32x2_t, pub float32x2_t, @@ -298,13 +298,13 @@ pub struct float32x2x4_t( ); /// ARM-specific type containing two `float32x4_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct float32x4x2_t(pub float32x4_t, pub float32x4_t); /// ARM-specific type containing three `float32x4_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct float32x4x3_t(pub float32x4_t, pub float32x4_t, pub float32x4_t); /// ARM-specific type containing four `float32x4_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct float32x4x4_t( pub float32x4_t, pub float32x4_t, @@ -313,33 +313,33 @@ pub struct float32x4x4_t( ); /// ARM-specific type containing four `int64x1_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct int64x1x2_t(pub int64x1_t, pub int64x1_t); /// ARM-specific type containing four `int64x1_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct int64x1x3_t(pub int64x1_t, pub int64x1_t, pub int64x1_t); /// ARM-specific type containing four `int64x1_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct int64x1x4_t(pub int64x1_t, pub int64x1_t, pub int64x1_t, pub int64x1_t); /// ARM-specific type containing four `int64x2_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct int64x2x2_t(pub int64x2_t, pub int64x2_t); /// ARM-specific type containing four `int64x2_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct int64x2x3_t(pub int64x2_t, pub int64x2_t, pub int64x2_t); /// ARM-specific type containing four `int64x2_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct int64x2x4_t(pub int64x2_t, pub int64x2_t, pub int64x2_t, pub int64x2_t); /// ARM-specific type containing four `uint64x1_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct uint64x1x2_t(pub uint64x1_t, pub uint64x1_t); /// ARM-specific type containing four `uint64x1_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct uint64x1x3_t(pub uint64x1_t, pub uint64x1_t, pub uint64x1_t); /// ARM-specific type containing four `uint64x1_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct uint64x1x4_t( pub uint64x1_t, pub uint64x1_t, @@ -348,13 +348,13 @@ pub struct uint64x1x4_t( ); /// ARM-specific type containing four `uint64x2_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct uint64x2x2_t(pub uint64x2_t, pub uint64x2_t); /// ARM-specific type containing four `uint64x2_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct uint64x2x3_t(pub uint64x2_t, pub uint64x2_t, pub uint64x2_t); /// ARM-specific type containing four `uint64x2_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct uint64x2x4_t( pub uint64x2_t, pub uint64x2_t, @@ -363,13 +363,13 @@ pub struct uint64x2x4_t( ); /// ARM-specific type containing four `poly64x1_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct poly64x1x2_t(pub poly64x1_t, pub poly64x1_t); /// ARM-specific type containing four `poly64x1_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct poly64x1x3_t(pub poly64x1_t, pub poly64x1_t, pub poly64x1_t); /// ARM-specific type containing four `poly64x1_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct poly64x1x4_t( pub poly64x1_t, pub poly64x1_t, @@ -378,13 +378,13 @@ pub struct poly64x1x4_t( ); /// ARM-specific type containing four `poly64x2_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct poly64x2x2_t(pub poly64x2_t, pub poly64x2_t); /// ARM-specific type containing four `poly64x2_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct poly64x2x3_t(pub poly64x2_t, pub poly64x2_t, pub poly64x2_t); /// ARM-specific type containing four `poly64x2_t` vectors. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct poly64x2x4_t( pub poly64x2_t, pub poly64x2_t, @@ -478,9 +478,6 @@ extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vpadd.v8i8")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.addp.v8i8")] fn vpadd_s8_(a: int8x8_t, b: int8x8_t) -> int8x8_t; - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vpadd.v16i8")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.addp.v16i8")] - fn vpaddq_s8_(a: int8x16_t, b: int8x16_t) -> int8x16_t; #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vpaddls.v4i16.v8i8")] #[cfg_attr( @@ -3922,6 +3919,26 @@ unsafe fn vdup_n_f32_vfp4(value: f32) -> float32x2_t { float32x2_t(value, value) } +/// Load SIMD&FP register (immediate offset) +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vldrq_p128(a: *const p128) -> p128 { + *a +} + +/// Store SIMD&FP register (immediate offset) +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +pub unsafe fn vstrq_p128(a: *mut p128, b: p128) { + *a = b; +} + /// Duplicate vector element to vector or scalar #[inline] #[target_feature(enable = "neon")] @@ -4789,6 +4806,66 @@ pub unsafe fn vpadalq_u32(a: uint64x2_t, b: uint32x4_t) -> uint64x2_t { } } +/// 8-bit integer matrix multiply-accumulate +#[inline] +#[cfg_attr(not(bootstrap), target_feature(enable = "i8mm"))] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smmla))] +pub unsafe fn vmmlaq_s32(a: int32x4_t, b: int8x16_t, c: int8x16_t) -> int32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.smmla.v4i32.v16i8")] + #[cfg_attr( + target_arch = "aarch64", + link_name = "llvm.aarch64.neon.smmla.v4i32.v16i8" + )] + fn vmmlaq_s32_(a: int32x4_t, b: int8x16_t, c: int8x16_t) -> int32x4_t; + } + vmmlaq_s32_(a, b, c) +} + +/// 8-bit integer matrix multiply-accumulate +#[inline] +#[cfg_attr(not(bootstrap), target_feature(enable = "i8mm"))] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ummla))] +pub unsafe fn vmmlaq_u32(a: uint32x4_t, b: uint8x16_t, c: uint8x16_t) -> uint32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.ummla.v4i32.v16i8")] + #[cfg_attr( + target_arch = "aarch64", + link_name = "llvm.aarch64.neon.ummla.v4i32.v16i8" + )] + fn vmmlaq_u32_(a: uint32x4_t, b: uint8x16_t, c: uint8x16_t) -> uint32x4_t; + } + vmmlaq_u32_(a, b, c) +} + +/// Unsigned and signed 8-bit integer matrix multiply-accumulate +#[inline] +#[cfg_attr(not(bootstrap), target_feature(enable = "i8mm"))] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usmmla))] +pub unsafe fn vusmmlaq_s32(a: int32x4_t, b: uint8x16_t, c: int8x16_t) -> int32x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.usmmla.v4i32.v16i8")] + #[cfg_attr( + target_arch = "aarch64", + link_name = "llvm.aarch64.neon.usmmla.v4i32.v16i8" + )] + fn vusmmlaq_s32_(a: int32x4_t, b: uint8x16_t, c: int8x16_t) -> int32x4_t; + } + vusmmlaq_s32_(a, b, c) +} + #[cfg(test)] mod tests { use super::*; @@ -5817,6 +5894,23 @@ mod tests { assert_eq!(r, e); } + #[simd_test(enable = "neon")] + unsafe fn test_vldrq_p128() { + let v: [p128; 2] = [1, 2]; + let e: p128 = 2; + let r: p128 = vldrq_p128(v[1..].as_ptr()); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vstrq_p128() { + let v: [p128; 2] = [1, 2]; + let e: p128 = 2; + let mut r: p128 = 1; + vstrq_p128(&mut r, v[1]); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vmov_n_s8() { let v: i8 = 64; @@ -10334,6 +10428,35 @@ mod tests { let e: u16x8 = transmute(vrev64q_p16(transmute(a))); assert_eq!(r, e); } + #[simd_test(enable = "neon,i8mm")] + unsafe fn test_vmmlaq_s32() { + let a: i32x4 = i32x4::new(1, 3, 4, 9); + let b: i8x16 = i8x16::new(1, 21, 31, 14, 5, 6, 17, 8, 9, 13, 15, 12, 13, 19, 20, 16); + let c: i8x16 = i8x16::new(12, 22, 3, 4, 5, 56, 7, 8, 91, 10, 11, 15, 13, 14, 17, 16); + let e: i32x4 = i32x4::new(1, 2, 3, 4); + let r: i32x4 = transmute(vmmlaq_s32(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon,i8mm")] + unsafe fn test_vmmlaq_u32() { + let a: u32x4 = u32x4::new(1, 3, 4, 9); + let b: i8x16 = i8x16::new(1, 21, 31, 14, 5, 6, 17, 8, 9, 13, 15, 12, 13, 19, 20, 16); + let c: i8x16 = i8x16::new(12, 22, 3, 4, 5, 56, 7, 8, 91, 10, 11, 15, 13, 14, 17, 16); + let e: u32x4 = u32x4::new(1, 2, 3, 4); + let r: u32x4 = transmute(vmmlaq_u32(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon,i8mm")] + unsafe fn test_vusmmlaq_s32() { + let a: i32x4 = i32x4::new(1, 3, 4, 9); + let b: i8x16 = i8x16::new(1, 21, 31, 14, 5, 6, 17, 8, 9, 13, 15, 12, 13, 19, 20, 16); + let c: i8x16 = i8x16::new(12, 22, 3, 4, 5, 56, 7, 8, 91, 10, 11, 15, 13, 14, 17, 16); + let e: i32x4 = i32x4::new(1, 2, 3, 4); + let r: i32x4 = transmute(vusmmlaq_s32(transmute(a), transmute(b), transmute(c))); + assert_eq!(r, e); + } } #[cfg(all(test, target_arch = "arm", target_endian = "little"))] diff --git a/library/stdarch/crates/core_arch/src/arm_shared/neon/shift_and_insert_tests.rs b/library/stdarch/crates/core_arch/src/arm_shared/neon/shift_and_insert_tests.rs index 125659c105..ebb8b7b9ef 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/neon/shift_and_insert_tests.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/neon/shift_and_insert_tests.rs @@ -50,6 +50,8 @@ test_vsli!(test_vsli_n_p8, i8 => vsli_n_p8([3, 44, 127, 56, 0, 24, 97, 10], [127 test_vsli!(test_vsliq_n_p8, i8 => vsliq_n_p8([3, 44, 127, 56, 0, 24, 97, 10, 33, 1, 6, 39, 15, 101, 80, 1], [127, 14, 125, 77, 27, 8, 1, 110, 4, 92, 111, 32, 1, 4, 29, 99], 2)); test_vsli!(test_vsli_n_p16, i16 => vsli_n_p16([3304, 44, 2300, 546], [1208, 140, 1225, 707], 7)); test_vsli!(test_vsliq_n_p16, i16 => vsliq_n_p16([3304, 44, 2300, 20046, 0, 9924, 907, 1190], [1208, 140, 4225, 707, 2701, 804, 71, 2110], 14)); +test_vsli!(test_vsli_n_p64, i64 => vsli_n_p64([333333], [1028], 45)); +test_vsli!(test_vsliq_n_p64, i64 => vsliq_n_p64([333333, 52023], [1028, 99814], 33)); macro_rules! test_vsri { ($test_id:ident, $t:ty => $fn_id:ident ([$($a:expr),*], [$($b:expr),*], $n:expr)) => { @@ -87,3 +89,5 @@ test_vsri!(test_vsri_n_p8, i8 => vsri_n_p8([3, 44, 127, 56, 0, 24, 97, 10], [127 test_vsri!(test_vsriq_n_p8, i8 => vsriq_n_p8([3, 44, 127, 56, 0, 24, 97, 10, 33, 1, 6, 39, 15, 101, 80, 1], [127, 14, 125, 77, 27, 8, 1, 110, 4, 92, 111, 32, 1, 4, 29, 99], 2)); test_vsri!(test_vsri_n_p16, i16 => vsri_n_p16([3304, 44, 2300, 546], [1208, 140, 1225, 707], 7)); test_vsri!(test_vsriq_n_p16, i16 => vsriq_n_p16([3304, 44, 2300, 20046, 0, 9924, 907, 1190], [1208, 140, 4225, 707, 2701, 804, 71, 2110], 14)); +test_vsri!(test_vsri_n_p64, i64 => vsri_n_p64([333333], [1028], 45)); +test_vsri!(test_vsriq_n_p64, i64 => vsriq_n_p64([333333, 52023], [1028, 99814], 33)); diff --git a/library/stdarch/crates/core_arch/src/arm_shared/neon/store_tests.rs b/library/stdarch/crates/core_arch/src/arm_shared/neon/store_tests.rs index c1e355fd9a..cad660e877 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/neon/store_tests.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/neon/store_tests.rs @@ -339,6 +339,29 @@ unsafe fn test_vst1q_p16() { assert_eq!(vals[8], 8); } +#[simd_test(enable = "neon,aes")] +unsafe fn test_vst1_p64() { + let mut vals = [0_u64; 2]; + let a = u64x1::new(1); + + vst1_p64(vals[1..].as_mut_ptr(), transmute(a)); + + assert_eq!(vals[0], 0); + assert_eq!(vals[1], 1); +} + +#[simd_test(enable = "neon,aes")] +unsafe fn test_vst1q_p64() { + let mut vals = [0_u64; 3]; + let a = u64x2::new(1, 2); + + vst1q_p64(vals[1..].as_mut_ptr(), transmute(a)); + + assert_eq!(vals[0], 0); + assert_eq!(vals[1], 1); + assert_eq!(vals[2], 2); +} + #[simd_test(enable = "neon")] unsafe fn test_vst1_f32() { let mut vals = [0_f32; 3]; diff --git a/library/stdarch/crates/core_arch/src/lib.rs b/library/stdarch/crates/core_arch/src/lib.rs index a4c889365c..d43192b399 100644 --- a/library/stdarch/crates/core_arch/src/lib.rs +++ b/library/stdarch/crates/core_arch/src/lib.rs @@ -5,7 +5,6 @@ #![deny(rust_2018_idioms)] #![feature( asm, - const_panic, custom_inner_attributes, link_llvm_intrinsics, platform_intrinsics, @@ -34,7 +33,8 @@ f16c_target_feature, allow_internal_unstable, decl_macro, - bench_black_box + bench_black_box, + asm_const )] #![cfg_attr(test, feature(test, abi_vectorcall))] #![deny(clippy::missing_inline_in_public_items)] diff --git a/library/stdarch/crates/core_arch/src/mips/msa.rs b/library/stdarch/crates/core_arch/src/mips/msa.rs index 0ba0774313..85ed30d18e 100644 --- a/library/stdarch/crates/core_arch/src/mips/msa.rs +++ b/library/stdarch/crates/core_arch/src/mips/msa.rs @@ -498,8 +498,8 @@ extern "C" { fn msa_fexp2_w(a: v4f32, b: v4i32) -> v4f32; #[link_name = "llvm.mips.fexp2.d"] fn msa_fexp2_d(a: v2f64, b: v2i64) -> v2f64; - #[link_name = "llvm.mips.fexupl.w"] // FIXME: 16-bit floats + // #[link_name = "llvm.mips.fexupl.w"] // fn msa_fexupl_w(a: f16x8) -> v4f32; #[link_name = "llvm.mips.fexupl.d"] fn msa_fexupl_d(a: v4f32) -> v2f64; diff --git a/library/stdarch/crates/core_arch/src/mod.rs b/library/stdarch/crates/core_arch/src/mod.rs index 7812dc91f9..754336c7f6 100644 --- a/library/stdarch/crates/core_arch/src/mod.rs +++ b/library/stdarch/crates/core_arch/src/mod.rs @@ -162,6 +162,28 @@ pub mod arch { pub use crate::core_arch::wasm32::*; } + /// Platform-specific intrinsics for the `wasm64` platform. + /// + /// See the [module documentation](../index.html) for more details. + #[cfg(any(target_arch = "wasm64", doc))] + #[doc(cfg(target_arch = "wasm64"))] + #[unstable(feature = "simd_wasm64", issue = "90599")] + pub mod wasm64 { + #[unstable(feature = "simd_wasm64", issue = "90599")] + pub use crate::core_arch::wasm32::*; + } + + /// Platform-specific intrinsics for the `wasm` target family. + /// + /// See the [module documentation](../index.html) for more details. + #[cfg(any(target_family = "wasm", doc))] + #[doc(cfg(target_family = "wasm"))] + #[unstable(feature = "simd_wasm64", issue = "90599")] + pub mod wasm { + #[unstable(feature = "simd_wasm64", issue = "90599")] + pub use crate::core_arch::wasm32::*; + } + /// Platform-specific intrinsics for the `mips` platform. /// /// See the [module documentation](../index.html) for more details. @@ -229,8 +251,8 @@ mod aarch64; #[doc(cfg(any(target_arch = "arm")))] mod arm; -#[cfg(any(target_arch = "wasm32", doc))] -#[doc(cfg(target_arch = "wasm32"))] +#[cfg(any(target_family = "wasm", doc))] +#[doc(cfg(target_family = "wasm"))] mod wasm32; #[cfg(any(target_arch = "mips", target_arch = "mips64", doc))] diff --git a/library/stdarch/crates/core_arch/src/wasm32/memory.rs b/library/stdarch/crates/core_arch/src/wasm32/memory.rs index 4824bc6279..b5cf13e984 100644 --- a/library/stdarch/crates/core_arch/src/wasm32/memory.rs +++ b/library/stdarch/crates/core_arch/src/wasm32/memory.rs @@ -2,10 +2,10 @@ use stdarch_test::assert_instr; extern "C" { - #[link_name = "llvm.wasm.memory.grow.i32"] - fn llvm_memory_grow(mem: u32, pages: i32) -> i32; - #[link_name = "llvm.wasm.memory.size.i32"] - fn llvm_memory_size(mem: u32) -> i32; + #[link_name = "llvm.wasm.memory.grow"] + fn llvm_memory_grow(mem: u32, pages: usize) -> usize; + #[link_name = "llvm.wasm.memory.size"] + fn llvm_memory_size(mem: u32) -> usize; } /// Corresponding intrinsic to wasm's [`memory.size` instruction][instr] @@ -27,7 +27,7 @@ extern "C" { #[doc(alias("memory.size"))] pub fn memory_size() -> usize { static_assert!(MEM: u32 where MEM == 0); - unsafe { llvm_memory_size(MEM) as usize } + unsafe { llvm_memory_size(MEM) } } /// Corresponding intrinsic to wasm's [`memory.grow` instruction][instr] @@ -53,6 +53,6 @@ pub fn memory_size() -> usize { pub fn memory_grow(delta: usize) -> usize { unsafe { static_assert!(MEM: u32 where MEM == 0); - llvm_memory_grow(MEM, delta as i32) as isize as usize + llvm_memory_grow(MEM, delta) } } diff --git a/library/stdarch/crates/core_arch/src/x86/avx.rs b/library/stdarch/crates/core_arch/src/x86/avx.rs index 88d5c170df..8e0af72ca5 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx.rs @@ -2139,8 +2139,7 @@ pub unsafe fn _mm256_set_ps( _mm256_setr_ps(h, g, f, e, d, c, b, a) } -/// Sets packed 8-bit integers in returned vector with the supplied values in -/// reverse order. +/// Sets packed 8-bit integers in returned vector with the supplied values. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_set_epi8) #[inline] diff --git a/library/stdarch/crates/core_arch/src/x86/sse41.rs b/library/stdarch/crates/core_arch/src/x86/sse41.rs index 6e607d4832..a8fe97fc02 100644 --- a/library/stdarch/crates/core_arch/src/x86/sse41.rs +++ b/library/stdarch/crates/core_arch/src/x86/sse41.rs @@ -141,8 +141,31 @@ pub unsafe fn _mm_blend_ps(a: __m128, b: __m128) -> __m128 { } /// Extracts a single-precision (32-bit) floating-point element from `a`, -/// selected with `IMM8` -/// +/// selected with `IMM8`. The returned `i32` stores the float's bit-pattern, +/// and may be converted back to a floating point number via casting. +/// +/// # Example +/// ```rust +/// # #[cfg(target_arch = "x86")] +/// # use std::arch::x86::*; +/// # #[cfg(target_arch = "x86_64")] +/// # use std::arch::x86_64::*; +/// # fn main() { +/// # if is_x86_feature_detected!("sse4.1") { +/// # #[target_feature(enable = "sse4.1")] +/// # unsafe fn worker() { +/// let mut float_store = vec![1.0, 1.0, 2.0, 3.0]; +/// unsafe { +/// let simd_floats = _mm_set_ps(2.5, 5.0, 7.5, 10.0); +/// let x: i32 = _mm_extract_ps::<2>(simd_floats); +/// float_store.push(f32::from_bits(x as u32)); +/// } +/// assert_eq!(float_store, vec![1.0, 1.0, 2.0, 3.0, 5.0]); +/// # } +/// # unsafe { worker() } +/// # } +/// # } +/// ``` /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_extract_ps) #[inline] #[target_feature(enable = "sse4.1")] diff --git a/library/stdarch/crates/intrinsic-test/Cargo.toml b/library/stdarch/crates/intrinsic-test/Cargo.toml index 4cdf811e5c..5fde23c9eb 100644 --- a/library/stdarch/crates/intrinsic-test/Cargo.toml +++ b/library/stdarch/crates/intrinsic-test/Cargo.toml @@ -13,4 +13,5 @@ regex = "1.4.2" log = "0.4.11" pretty_env_logger = "0.4.0" rayon = "1.5.0" -diff = "0.1.12" \ No newline at end of file +diff = "0.1.12" +itertools = "0.10.1" \ No newline at end of file diff --git a/library/stdarch/crates/intrinsic-test/missing.txt b/library/stdarch/crates/intrinsic-test/missing.txt new file mode 100644 index 0000000000..fcc70935b6 --- /dev/null +++ b/library/stdarch/crates/intrinsic-test/missing.txt @@ -0,0 +1,115 @@ +vmmlaq_s32 +vmmlaq_u32 +vrnd32x_f64 +vrnd32xq_f64 +vrnd32z_f64 +vrnd32zq_f64 +vrnd64x_f64 +vrnd64z_f64 +vrnd64zq_f64 +vsm3partw1q_u32 +vsm3partw2q_u32 +vsm3tt1bq_u32 +vsm3tt2aq_u32 +vsm3tt2bq_u32 +vsm4ekeyq_u32 +vsm4eq_u32 +vsudot_lane_s32 +vsudot_laneq_s32 +vsudotq_lane_s32 +vsudotq_laneq_s32 +vusdot_lane_s32 +vusdot_laneq_s32 +vusdot_s32 +vusdotq_lane_s32 +vusdotq_laneq_s32 +vusdotq_s32 +vcls_u16 +vcls_u32 +vcls_u8 +vclsq_u16 +vclsq_u32 +vclsq_u8 +vcreate_s16 +vcreate_u16 +vpaddq_s64 +vpaddq_u64 +vqshlu_n_s16 +vqshlu_n_s32 +vqshlu_n_s64 +vqshlu_n_s8 +vqshlub_n_s8 +vqshlud_n_s64 +vqshluh_n_s16 +vqshluq_n_s16 +vqshluq_n_s32 +vqshluq_n_s64 +vqshluq_n_s8 +vqshlus_n_s32 +vrax1q_u64 +vreinterpretq_p128_f32 +vreinterpretq_p128_f64 +vreinterpretq_p128_p16 +vreinterpretq_p128_p8 +vreinterpretq_p128_s16 +vreinterpretq_p128_s32 +vreinterpretq_p128_s64 +vreinterpretq_p128_s8 +vreinterpretq_p128_u16 +vreinterpretq_p128_u32 +vreinterpretq_p128_u64 +vreinterpretq_p128_u8 +vrnd32x_f32 +vrnd32xq_f32 +vrnd32z_f32 +vrnd32zq_f32 +vrnd64x_f32 +vrnd64xq_f32 +vrnd64xq_f64 +vrnd64z_f32 +vrnd64zq_f32 +vsha512h2q_u64 +vsha512hq_u64 +vsha512su0q_u64 +vsha512su1q_u64 +vslid_n_s64 +vslid_n_u64 +vsm3ss1q_u32 +vsm3tt1aq_u32 +vsrid_n_s64 +vsrid_n_u64 +vusmmlaq_s32 +vxarq_u64 +vadd_p16 +vadd_p64 +vadd_p8 +vaddq_p16 +vaddq_p64 +vaddq_p8 +vbcaxq_s16 +vbcaxq_s32 +vbcaxq_s64 +vbcaxq_s8 +vbcaxq_u16 +vbcaxq_u32 +vbcaxq_u64 +vbcaxq_u8 +veor3q_s16 +veor3q_s32 +veor3q_s64 +veor3q_s8 +veor3q_u16 +veor3q_u32 +veor3q_u64 +veor3q_u8 +vshld_s64 +vshld_u64 +vcopyq_laneq_u8 +vcopyq_laneq_s8 +vcopyq_laneq_p8 +vcopyq_lane_u8 +vcopyq_lane_s8 +vcopyq_lane_p8 +vcopy_laneq_u8 +vcopy_laneq_s8 +vcopy_laneq_p8 diff --git a/library/stdarch/crates/intrinsic-test/neon-intrinsics.csv b/library/stdarch/crates/intrinsic-test/neon-intrinsics.csv deleted file mode 100644 index 438c6667f5..0000000000 --- a/library/stdarch/crates/intrinsic-test/neon-intrinsics.csv +++ /dev/null @@ -1,4356 +0,0 @@ -enabled,name,args,return,comment -FALSE,__crc32b,"a: u32, b: u8",u32,CRC32 checksum -FALSE,__crc32cb,"a: u32, b: u8",u32,CRC32 checksum -TRUE,__crc32cd,"a: u32, b: u64",u32,CRC32 checksum -FALSE,__crc32ch,"a: u32, b: u16",u32,CRC32 checksum -FALSE,__crc32cw,"a: u32, b: u32",u32,CRC32 checksum -TRUE,__crc32d,"a: u32, b: u64",u32,CRC32 checksum -FALSE,__crc32h,"a: u32, b: u16",u32,CRC32 checksum -FALSE,__crc32w,"a: u32, b: u32",u32,CRC32 checksum -TRUE,vaba_s16,"a: int16x4_t, b: int16x4_t, c: int16x4_t",int16x4_t,Signed absolute difference and accumulate -TRUE,vaba_s32,"a: int32x2_t, b: int32x2_t, c: int32x2_t",int32x2_t,Signed absolute difference and accumulate -TRUE,vaba_s8,"a: int8x8_t, b: int8x8_t, c: int8x8_t",int8x8_t,Signed absolute difference and accumulate -TRUE,vaba_u16,"a: uint16x4_t, b: uint16x4_t, c: uint16x4_t",uint16x4_t,Unsigned absolute difference and accumulate -TRUE,vaba_u32,"a: uint32x2_t, b: uint32x2_t, c: uint32x2_t",uint32x2_t,Unsigned absolute difference and accumulate -TRUE,vaba_u8,"a: uint8x8_t, b: uint8x8_t, c: uint8x8_t",uint8x8_t,Unsigned absolute difference and accumulate -TRUE,vabal_high_s16,"a: int32x4_t, b: int16x8_t, c: int16x8_t",int32x4_t,Signed absolute difference and accumulate long -TRUE,vabal_high_s32,"a: int64x2_t, b: int32x4_t, c: int32x4_t",int64x2_t,Signed absolute difference and accumulate long -TRUE,vabal_high_s8,"a: int16x8_t, b: int8x16_t, c: int8x16_t",int16x8_t,Signed absolute difference and accumulate long -TRUE,vabal_high_u16,"a: uint32x4_t, b: uint16x8_t, c: uint16x8_t",uint32x4_t,Unsigned absolute difference and accumulate long -TRUE,vabal_high_u32,"a: uint64x2_t, b: uint32x4_t, c: uint32x4_t",uint64x2_t,Unsigned absolute difference and accumulate long -TRUE,vabal_high_u8,"a: uint16x8_t, b: uint8x16_t, c: uint8x16_t",uint16x8_t,Unsigned absolute difference and accumulate long -TRUE,vabal_s16,"a: int32x4_t, b: int16x4_t, c: int16x4_t",int32x4_t,Signed absolute difference and accumulate long -TRUE,vabal_s32,"a: int64x2_t, b: int32x2_t, c: int32x2_t",int64x2_t,Signed absolute difference and accumulate long -TRUE,vabal_s8,"a: int16x8_t, b: int8x8_t, c: int8x8_t",int16x8_t,Signed absolute difference and accumulate long -TRUE,vabal_u16,"a: uint32x4_t, b: uint16x4_t, c: uint16x4_t",uint32x4_t,Unsigned absolute difference and accumulate long -TRUE,vabal_u32,"a: uint64x2_t, b: uint32x2_t, c: uint32x2_t",uint64x2_t,Unsigned absolute difference and accumulate long -TRUE,vabal_u8,"a: uint16x8_t, b: uint8x8_t, c: uint8x8_t",uint16x8_t,Unsigned absolute difference and accumulate long -TRUE,vabaq_s16,"a: int16x8_t, b: int16x8_t, c: int16x8_t",int16x8_t,Signed absolute difference and accumulate -TRUE,vabaq_s32,"a: int32x4_t, b: int32x4_t, c: int32x4_t",int32x4_t,Signed absolute difference and accumulate -TRUE,vabaq_s8,"a: int8x16_t, b: int8x16_t, c: int8x16_t",int8x16_t,Signed absolute difference and accumulate -TRUE,vabaq_u16,"a: uint16x8_t, b: uint16x8_t, c: uint16x8_t",uint16x8_t,Unsigned absolute difference and accumulate -TRUE,vabaq_u32,"a: uint32x4_t, b: uint32x4_t, c: uint32x4_t",uint32x4_t,Unsigned absolute difference and accumulate -TRUE,vabaq_u8,"a: uint8x16_t, b: uint8x16_t, c: uint8x16_t",uint8x16_t,Unsigned absolute difference and accumulate -FALSE,vabd_f16,"a: float16x4_t, b: float16x4_t",float16x4_t,Floating-point absolute difference -TRUE,vabd_f32,"a: float32x2_t, b: float32x2_t",float32x2_t,Floating-point absolute difference -TRUE,vabd_f64,"a: float64x1_t, b: float64x1_t",float64x1_t,Floating-point absolute difference -TRUE,vabd_s16,"a: int16x4_t, b: int16x4_t",int16x4_t,Signed absolute difference -TRUE,vabd_s32,"a: int32x2_t, b: int32x2_t",int32x2_t,Signed absolute difference -TRUE,vabd_s8,"a: int8x8_t, b: int8x8_t",int8x8_t,Signed absolute difference -TRUE,vabd_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4_t,Unsigned absolute difference -TRUE,vabd_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2_t,Unsigned absolute difference -TRUE,vabd_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,Unsigned absolute difference -FALSE,vabdd_f64,"a: float64_t, b: float64_t",float64_t,Floating-point absolute difference -FALSE,vabdh_f16,"a: float16_t, b: float16_t",float16_t,Floating-point absolute difference -TRUE,vabdl_high_s16,"a: int16x8_t, b: int16x8_t",int32x4_t,Signed absolute difference long -TRUE,vabdl_high_s32,"a: int32x4_t, b: int32x4_t",int64x2_t,Signed absolute difference long -TRUE,vabdl_high_s8,"a: int8x16_t, b: int8x16_t",int16x8_t,Signed absolute difference long -TRUE,vabdl_high_u16,"a: uint16x8_t, b: uint16x8_t",uint32x4_t,Unsigned absolute difference long -TRUE,vabdl_high_u32,"a: uint32x4_t, b: uint32x4_t",uint64x2_t,Unsigned absolute difference long -TRUE,vabdl_high_u8,"a: uint8x16_t, b: uint8x16_t",uint16x8_t,Unsigned absolute difference long -TRUE,vabdl_s16,"a: int16x4_t, b: int16x4_t",int32x4_t,Signed absolute difference long -TRUE,vabdl_s32,"a: int32x2_t, b: int32x2_t",int64x2_t,Signed absolute difference long -TRUE,vabdl_s8,"a: int8x8_t, b: int8x8_t",int16x8_t,Signed absolute difference long -TRUE,vabdl_u16,"a: uint16x4_t, b: uint16x4_t",uint32x4_t,Unsigned absolute difference long -TRUE,vabdl_u32,"a: uint32x2_t, b: uint32x2_t",uint64x2_t,Unsigned absolute difference long -TRUE,vabdl_u8,"a: uint8x8_t, b: uint8x8_t",uint16x8_t,Unsigned absolute difference long -FALSE,vabdq_f16,"a: float16x8_t, b: float16x8_t",float16x8_t,Floating-point absolute difference -TRUE,vabdq_f32,"a: float32x4_t, b: float32x4_t",float32x4_t,Floating-point absolute difference -TRUE,vabdq_f64,"a: float64x2_t, b: float64x2_t",float64x2_t,Floating-point absolute difference -TRUE,vabdq_s16,"a: int16x8_t, b: int16x8_t",int16x8_t,Signed absolute difference -TRUE,vabdq_s32,"a: int32x4_t, b: int32x4_t",int32x4_t,Signed absolute difference -TRUE,vabdq_s8,"a: int8x16_t, b: int8x16_t",int8x16_t,l -TRUE,vabdq_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8_t,Unsigned absolute difference -TRUE,vabdq_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,Unsigned absolute difference -TRUE,vabdq_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16_t,Unsigned absolute difference -FALSE,vabds_f32,"a: f32, b: f32",f32,Floating-point absolute difference -FALSE,vabs_f16,a: float16x4_t,float16x4_t,Floating-point absolute value -TRUE,vabs_f32,a: float32x2_t,float32x2_t,Floating-point absolute value -TRUE,vabs_f64,a: float64x1_t,float64x1_t,Floating-point absolute value -TRUE,vabs_s16,a: int16x4_t,int16x4_t,Absolute value -TRUE,vabs_s32,a: int32x2_t,int32x2_t,Absolute value -TRUE,vabs_s64,a: int64x1_t,int64x1_t,Absolute value -TRUE,vabs_s8,a: int8x8_t,int8x8_t,Absolute value -TRUE,vabsd_s64,a: i64,i64,Absolute value -FALSE,vabsh_f16,a: float16_t,float16_t,Floating-point absolute value -FALSE,vabsq_f16,a: float16x8_t,float16x8_t,Floating-point absolute value -TRUE,vabsq_f32,a: float32x4_t,float32x4_t,Floating-point absolute value -TRUE,vabsq_f64,a: float64x2_t,float64x2_t,Floating-point absolute value -TRUE,vabsq_s16,a: int16x8_t,int16x8_t,Absolute value -TRUE,vabsq_s32,a: int32x4_t,int32x4_t,Absolute value -TRUE,vabsq_s64,a: int64x2_t,int64x2_t,Absolute value -TRUE,vabsq_s8,a: int8x16_t,int8x16_t,Absolute value -FALSE,vadd_f16,"a: float16x4_t, b: float16x4_t",float16x4_t,Floating-point add -TRUE,vadd_f32,"a: float32x2_t, b: float32x2_t",float32x2_t,Floating-point add -TRUE,vadd_f64,"a: float64x1_t, b: float64x1_t",float64x1_t,Floating-point add -FALSE,vadd_p16,"a: poly16x4_t, b: poly16x4_t",poly16x4_t,Bitwise exclusive OR -FALSE,vadd_p64,"a: poly64x1_t, b: poly64x1_t",poly64x1_t,Bitwise exclusive OR -FALSE,vadd_p8,"a: poly8x8_t, b: poly8x8_t",poly8x8_t,Bitwise exclusive OR -TRUE,vadd_s16,"a: int16x4_t, b: int16x4_t",int16x4_t,Add -TRUE,vadd_s32,"a: int32x2_t, b: int32x2_t",int32x2_t,Add -TRUE,vadd_s64,"a: int64x1_t, b: int64x1_t",int64x1_t,Add -TRUE,vadd_s8,"a: int8x8_t, b: int8x8_t",int8x8_t,Add -TRUE,vadd_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4_t,Add -TRUE,vadd_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2_t,Add -TRUE,vadd_u64,"a: uint64x1_t, b: uint64x1_t",uint64x1_t,Add -TRUE,vadd_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,Add -TRUE,vaddd_s64,"a: i64, b: i64",i64,Add -TRUE,vaddd_u64,"a: u64, b: u64",u64,Add -FALSE,vaddh_f16,"a: float16_t, b: float16_t",float16_t,Floating-point add -TRUE,vaddhn_high_s16,"r: int8x8_t, a: int16x8_t, b: int16x8_t",int8x16_t,Add returning high narrow -TRUE,vaddhn_high_s32,"r: int16x4_t, a: int32x4_t, b: int32x4_t",int16x8_t,Add returning high narrow -TRUE,vaddhn_high_s64,"r: int32x2_t, a: int64x2_t, b: int64x2_t",int32x4_t,Add returning high narrow -TRUE,vaddhn_high_u16,"r: uint8x8_t, a: uint16x8_t, b: uint16x8_t",uint8x16_t,Add returning high narrow -TRUE,vaddhn_high_u32,"r: uint16x4_t, a: uint32x4_t, b: uint32x4_t",uint16x8_t,Add returning high narrow -TRUE,vaddhn_high_u64,"r: uint32x2_t, a: uint64x2_t, b: uint64x2_t",uint32x4_t,Add returning high narrow -TRUE,vaddhn_s16,"a: int16x8_t, b: int16x8_t",int8x8_t,Add returning high narrow -TRUE,vaddhn_s32,"a: int32x4_t, b: int32x4_t",int16x4_t,Add returning high narrow -TRUE,vaddhn_s64,"a: int64x2_t, b: int64x2_t",int32x2_t,Add returning high narrow -TRUE,vaddhn_u16,"a: uint16x8_t, b: uint16x8_t",uint8x8_t,Add returning high narrow -TRUE,vaddhn_u32,"a: uint32x4_t, b: uint32x4_t",uint16x4_t,Add returning high narrow -TRUE,vaddhn_u64,"a: uint64x2_t, b: uint64x2_t",uint32x2_t,Add returning high narrow -TRUE,vaddl_high_s16,"a: int16x8_t, b: int16x8_t",int32x4_t,Signed add long -TRUE,vaddl_high_s32,"a: int32x4_t, b: int32x4_t",int64x2_t,Signed add long -TRUE,vaddl_high_s8,"a: int8x16_t, b: int8x16_t",int16x8_t,Signed add long -TRUE,vaddl_high_u16,"a: uint16x8_t, b: uint16x8_t",uint32x4_t,Unsigned add long -TRUE,vaddl_high_u32,"a: uint32x4_t, b: uint32x4_t",uint64x2_t,Unsigned add long -TRUE,vaddl_high_u8,"a: uint8x16_t, b: uint8x16_t",uint16x8_t,Unsigned add long -TRUE,vaddl_s16,"a: int16x4_t, b: int16x4_t",int32x4_t,Signed add long -TRUE,vaddl_s32,"a: int32x2_t, b: int32x2_t",int64x2_t,Signed add long -TRUE,vaddl_s8,"a: int8x8_t, b: int8x8_t",int16x8_t,Signed add long -TRUE,vaddl_u16,"a: uint16x4_t, b: uint16x4_t",uint32x4_t,Unsigned add long -TRUE,vaddl_u32,"a: uint32x2_t, b: uint32x2_t",uint64x2_t,Unsigned add long -TRUE,vaddl_u8,"a: uint8x8_t, b: uint8x8_t",uint16x8_t,Unsigned add long -FALSE,vaddlv_s16,a: int16x4_t,i32,Signed add long across vector -FALSE,vaddlv_s32,a: int32x2_t,i64,Signed add long pairwise -FALSE,vaddlv_s8,a: int8x8_t,i16,Signed add long across vector -FALSE,vaddlv_u16,a: uint16x4_t,u32,Unsigned sum long across vector -FALSE,vaddlv_u32,a: uint32x2_t,u64,Unsigned add long pairwise -FALSE,vaddlv_u8,a: uint8x8_t,u16,Unsigned sum long across vector -FALSE,vaddlvq_s16,a: int16x8_t,i32,Signed add long across vector -FALSE,vaddlvq_s32,a: int32x4_t,i64,Signed add long across vector -FALSE,vaddlvq_s8,a: int8x16_t,i16,Signed add long across vector -FALSE,vaddlvq_u16,a: uint16x8_t,u32,Unsigned sum long across vector -FALSE,vaddlvq_u32,a: uint32x4_t,u64,Unsigned sum long across vector -FALSE,vaddlvq_u8,a: uint8x16_t,u16,Unsigned sum long across vector -FALSE,vaddq_f16,"a: float16x8_t, b: float16x8_t",float16x8_t,Floating-point add -TRUE,vaddq_f32,"a: float32x4_t, b: float32x4_t",float32x4_t,Floating-point add -TRUE,vaddq_f64,"a: float64x2_t, b: float64x2_t",float64x2_t,Floating-point add -FALSE,vaddq_p128,"a: poly128_t, b: poly128_t",poly128_t,Bitwise exclusive OR -FALSE,vaddq_p16,"a: poly16x8_t, b: poly16x8_t",poly16x8_t,Bitwise exclusive OR -FALSE,vaddq_p64,"a: poly64x2_t, b: poly64x2_t",poly64x2_t,Bitwise exclusive OR -FALSE,vaddq_p8,"a: poly8x16_t, b: poly8x16_t",poly8x16_t,Bitwise exclusive OR -TRUE,vaddq_s16,"a: int16x8_t, b: int16x8_t",int16x8_t,Add -TRUE,vaddq_s32,"a: int32x4_t, b: int32x4_t",int32x4_t,Add -TRUE,vaddq_s64,"a: int64x2_t, b: int64x2_t",int64x2_t,Add -TRUE,vaddq_s8,"a: int8x16_t, b: int8x16_t",int8x16_t,Add -TRUE,vaddq_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8_t,Add -TRUE,vaddq_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,Add -TRUE,vaddq_u64,"a: uint64x2_t, b: uint64x2_t",uint64x2_t,Add -TRUE,vaddq_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16_t,Add -FALSE,vaddv_f32,a: float32x2_t,f32,Floating-point add across vector -TRUE,vaddv_s16,a: int16x4_t,i16,Add across vector -TRUE,vaddv_s32,a: int32x2_t,i32,Add across vector -TRUE,vaddv_s8,a: int8x8_t,i8,Add across vector -TRUE,vaddv_u16,a: uint16x4_t,u16,Add across vector -TRUE,vaddv_u32,a: uint32x2_t,u32,Add across vector -TRUE,vaddv_u8,a: uint8x8_t,u8,Add across vector -FALSE,vaddvq_f32,a: float32x4_t,f32,Floating-point add across vector -FALSE,vaddvq_f64,a: float64x2_t,float64_t,Floating-point add across vector -TRUE,vaddvq_s16,a: int16x8_t,i16,Add across vector -TRUE,vaddvq_s32,a: int32x4_t,i32,Add across vector -TRUE,vaddvq_s64,a: int64x2_t,i64,Add across vector -TRUE,vaddvq_s8,a: int8x16_t,i8,Add across vector -TRUE,vaddvq_u16,a: uint16x8_t,u16,Add across vector -TRUE,vaddvq_u32,a: uint32x4_t,u32,Add across vector -TRUE,vaddvq_u64,a: uint64x2_t,u64,Add across vector -TRUE,vaddvq_u8,a: uint8x16_t,u8,Add across vector -TRUE,vaddw_high_s16,"a: int32x4_t, b: int16x8_t",int32x4_t,Signed add wide -TRUE,vaddw_high_s32,"a: int64x2_t, b: int32x4_t",int64x2_t,Signed add wide -TRUE,vaddw_high_s8,"a: int16x8_t, b: int8x16_t",int16x8_t,Signed add wide -TRUE,vaddw_high_u16,"a: uint32x4_t, b: uint16x8_t",uint32x4_t,Unsigned add wide -TRUE,vaddw_high_u32,"a: uint64x2_t, b: uint32x4_t",uint64x2_t,Unsigned add wide -TRUE,vaddw_high_u8,"a: uint16x8_t, b: uint8x16_t",uint16x8_t,Unsigned add wide -TRUE,vaddw_s16,"a: int32x4_t, b: int16x4_t",int32x4_t,Signed add wide -TRUE,vaddw_s32,"a: int64x2_t, b: int32x2_t",int64x2_t,Signed add wide -TRUE,vaddw_s8,"a: int16x8_t, b: int8x8_t",int16x8_t,Signed add wide -TRUE,vaddw_u16,"a: uint32x4_t, b: uint16x4_t",uint32x4_t,Unsigned add wide -TRUE,vaddw_u32,"a: uint64x2_t, b: uint32x2_t",uint64x2_t,Unsigned add wide -TRUE,vaddw_u8,"a: uint16x8_t, b: uint8x8_t",uint16x8_t,Unsigned add wide -TRUE,vaesdq_u8,"data: uint8x16_t, key: uint8x16_t",uint8x16_t,AES single round decryption -TRUE,vaeseq_u8,"data: uint8x16_t, key: uint8x16_t",uint8x16_t,AES single round encryption -TRUE,vaesimcq_u8,data: uint8x16_t,uint8x16_t,AES inverse mix columns -TRUE,vaesmcq_u8,data: uint8x16_t,uint8x16_t,AES mix columns -TRUE,vand_s16,"a: int16x4_t, b: int16x4_t",int16x4_t,Bitwise AND -TRUE,vand_s32,"a: int32x2_t, b: int32x2_t",int32x2_t,Bitwise AND -TRUE,vand_s64,"a: int64x1_t, b: int64x1_t",int64x1_t,Bitwise AND -TRUE,vand_s8,"a: int8x8_t, b: int8x8_t",int8x8_t,Bitwise AND -TRUE,vand_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4_t,Bitwise AND -TRUE,vand_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2_t,Bitwise AND -TRUE,vand_u64,"a: uint64x1_t, b: uint64x1_t",uint64x1_t,Bitwise AND -TRUE,vand_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,Bitwise AND -TRUE,vandq_s16,"a: int16x8_t, b: int16x8_t",int16x8_t,Bitwise AND -TRUE,vandq_s32,"a: int32x4_t, b: int32x4_t",int32x4_t,Bitwise AND -TRUE,vandq_s64,"a: int64x2_t, b: int64x2_t",int64x2_t,Bitwise AND -TRUE,vandq_s8,"a: int8x16_t, b: int8x16_t",int8x16_t,Bitwise AND -TRUE,vandq_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8_t,Bitwise AND -TRUE,vandq_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,Bitwise AND -TRUE,vandq_u64,"a: uint64x2_t, b: uint64x2_t",uint64x2_t,Bitwise AND -TRUE,vandq_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16_t,Bitwise AND -FALSE,vbcaxq_s16,"a: int16x8_t, b: int16x8_t, c: int16x8_t",int16x8_t,Bit clear and exclusive OR -FALSE,vbcaxq_s32,"a: int32x4_t, b: int32x4_t, c: int32x4_t",int32x4_t,Bit clear and exclusive OR -FALSE,vbcaxq_s64,"a: int64x2_t, b: int64x2_t, c: int64x2_t",int64x2_t,Bit clear and exclusive OR -FALSE,vbcaxq_s8,"a: int8x16_t, b: int8x16_t, c: int8x16_t",int8x16_t,Bit clear and exclusive OR -FALSE,vbcaxq_u16,"a: uint16x8_t, b: uint16x8_t, c: uint16x8_t",uint16x8_t,Bit clear and exclusive OR -FALSE,vbcaxq_u32,"a: uint32x4_t, b: uint32x4_t, c: uint32x4_t",uint32x4_t,Bit clear and exclusive OR -FALSE,vbcaxq_u64,"a: uint64x2_t, b: uint64x2_t, c: uint64x2_t",uint64x2_t,Bit clear and exclusive OR -FALSE,vbcaxq_u8,"a: uint8x16_t, b: uint8x16_t, c: uint8x16_t",uint8x16_t,Bit clear and exclusive OR -FALSE,vbfdot_f32,"r: float32x2_t, a: bfloat16x4_t, b: bfloat16x4_t",float32x2_t,Bfloat16 floating-point dot product -FALSE,vbfdot_lane_f32,"r: float32x2_t, a: bfloat16x4_t, b: bfloat16x4_t, lane: const int",float32x2_t,Bfloat16 floating-point dot product -FALSE,vbfdot_laneq_f32,"r: float32x2_t, a: bfloat16x4_t, b: bfloat16x8_t, lane: const int",float32x2_t,Bfloat16 floating-point dot product -FALSE,vbfdotq_f32,"r: float32x4_t, a: bfloat16x8_t, b: bfloat16x8_t",float32x4_t,Bfloat16 floating-point dot product -FALSE,vbfdotq_lane_f32,"r: float32x4_t, a: bfloat16x8_t, b: bfloat16x4_t, lane: const int",float32x4_t,Bfloat16 floating-point dot product -FALSE,vbfdotq_laneq_f32,"r: float32x4_t, a: bfloat16x8_t, b: bfloat16x8_t, lane: const int",float32x4_t,Bfloat16 floating-point dot product -FALSE,vbfmlalbq_f32,"r: float32x4_t, a: bfloat16x8_t, b: bfloat16x8_t",float32x4_t,Bfloat16 floating-point widening multiply-add long -FALSE,vbfmlalbq_lane_f32,"r: float32x4_t, a: bfloat16x8_t, b: bfloat16x4_t, lane: const int",float32x4_t,Bfloat16 floating-point widening multiply-add long -FALSE,vbfmlalbq_laneq_f32,"r: float32x4_t, a: bfloat16x8_t, b: bfloat16x8_t, lane: const int",float32x4_t,Bfloat16 floating-point widening multiply-add long -FALSE,vbfmlaltq_f32,"r: float32x4_t, a: bfloat16x8_t, b: bfloat16x8_t",float32x4_t,Bfloat16 floating-point widening multiply-add long -FALSE,vbfmlaltq_lane_f32,"r: float32x4_t, a: bfloat16x8_t, b: bfloat16x4_t, lane: const int",float32x4_t,Bfloat16 floating-point widening multiply-add long -FALSE,vbfmlaltq_laneq_f32,"r: float32x4_t, a: bfloat16x8_t, b: bfloat16x8_t, lane: const int",float32x4_t,Bfloat16 floating-point widening multiply-add long -FALSE,vbfmmlaq_f32,"r: float32x4_t, a: bfloat16x8_t, b: bfloat16x8_t",float32x4_t,Bfloat16 floating-point matrix multiply-accumulate into 2x2 matrix -TRUE,vbic_s16,"a: int16x4_t, b: int16x4_t",int16x4_t,"Bitwise bit clear (vector, immediate)" -TRUE,vbic_s32,"a: int32x2_t, b: int32x2_t",int32x2_t,"Bitwise bit clear (vector, immediate)" -TRUE,vbic_s64,"a: int64x1_t, b: int64x1_t",int64x1_t,"Bitwise bit clear (vector, immediate)" -TRUE,vbic_s8,"a: int8x8_t, b: int8x8_t",int8x8_t,"Bitwise bit clear (vector, immediate)" -TRUE,vbic_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4_t,"Bitwise bit clear (vector, immediate)" -TRUE,vbic_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2_t,"Bitwise bit clear (vector, immediate)" -TRUE,vbic_u64,"a: uint64x1_t, b: uint64x1_t",uint64x1_t,"Bitwise bit clear (vector, immediate)" -TRUE,vbic_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,"Bitwise bit clear (vector, immediate)" -TRUE,vbicq_s16,"a: int16x8_t, b: int16x8_t",int16x8_t,"Bitwise bit clear (vector, immediate)" -TRUE,vbicq_s32,"a: int32x4_t, b: int32x4_t",int32x4_t,"Bitwise bit clear (vector, immediate)" -TRUE,vbicq_s64,"a: int64x2_t, b: int64x2_t",int64x2_t,"Bitwise bit clear (vector, immediate)" -TRUE,vbicq_s8,"a: int8x16_t, b: int8x16_t",int8x16_t,"Bitwise bit clear (vector, immediate)" -TRUE,vbicq_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8_t,"Bitwise bit clear (vector, immediate)" -TRUE,vbicq_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,"Bitwise bit clear (vector, immediate)" -TRUE,vbicq_u64,"a: uint64x2_t, b: uint64x2_t",uint64x2_t,"Bitwise bit clear (vector, immediate)" -TRUE,vbicq_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16_t,"Bitwise bit clear (vector, immediate)" -FALSE,vbsl_f16,"a: uint16x4_t, b: float16x4_t, c: float16x4_t",float16x4_t,Bitwise select -TRUE,vbsl_f32,"a: uint32x2_t, b: float32x2_t, c: float32x2_t",float32x2_t,Bitwise select -TRUE,vbsl_f64,"a: uint64x1_t, b: float64x1_t, c: float64x1_t",float64x1_t,Bitwise select -TRUE,vbsl_p16,"a: uint16x4_t, b: poly16x4_t, c: poly16x4_t",poly16x4_t,Bitwise select -TRUE,vbsl_p64,"a: poly64x1_t, b: poly64x1_t, c: poly64x1_t",poly64x1_t,Bitwise select -TRUE,vbsl_p8,"a: uint8x8_t, b: poly8x8_t, c: poly8x8_t",poly8x8_t,Bitwise select -TRUE,vbsl_s16,"a: uint16x4_t, b: int16x4_t, c: int16x4_t",int16x4_t,Bitwise select -TRUE,vbsl_s32,"a: uint32x2_t, b: int32x2_t, c: int32x2_t",int32x2_t,Bitwise select -TRUE,vbsl_s64,"a: uint64x1_t, b: int64x1_t, c: int64x1_t",int64x1_t,Bitwise select -TRUE,vbsl_s8,"a: uint8x8_t, b: int8x8_t, c: int8x8_t",int8x8_t,Bitwise select -TRUE,vbsl_u16,"a: uint16x4_t, b: uint16x4_t, c: uint16x4_t",uint16x4_t,Bitwise select -TRUE,vbsl_u32,"a: uint32x2_t, b: uint32x2_t, c: uint32x2_t",uint32x2_t,Bitwise select -TRUE,vbsl_u64,"a: uint64x1_t, b: uint64x1_t, c: uint64x1_t",uint64x1_t,Bitwise select -TRUE,vbsl_u8,"a: uint8x8_t, b: uint8x8_t, c: uint8x8_t",uint8x8_t,Bitwise select -FALSE,vbslq_f16,"a: uint16x8_t, b: float16x8_t, c: float16x8_t",float16x8_t,Bitwise select -TRUE,vbslq_f32,"a: uint32x4_t, b: float32x4_t, c: float32x4_t",float32x4_t,Bitwise select -TRUE,vbslq_f64,"a: uint64x2_t, b: float64x2_t, c: float64x2_t",float64x2_t,Bitwise select -TRUE,vbslq_p16,"a: uint16x8_t, b: poly16x8_t, c: poly16x8_t",poly16x8_t,Bitwise select -TRUE,vbslq_p64,"a: poly64x2_t, b: poly64x2_t, c: poly64x2_t",poly64x2_t,Bitwise select -TRUE,vbslq_p8,"a: uint8x16_t, b: poly8x16_t, c: poly8x16_t",poly8x16_t,Bitwise select -TRUE,vbslq_s16,"a: uint16x8_t, b: int16x8_t, c: int16x8_t",int16x8_t,Bitwise select -TRUE,vbslq_s32,"a: uint32x4_t, b: int32x4_t, c: int32x4_t",int32x4_t,Bitwise select -TRUE,vbslq_s64,"a: uint64x2_t, b: int64x2_t, c: int64x2_t",int64x2_t,Bitwise select -TRUE,vbslq_s8,"a: uint8x16_t, b: int8x16_t, c: int8x16_t",int8x16_t,Bitwise select -TRUE,vbslq_u16,"a: uint16x8_t, b: uint16x8_t, c: uint16x8_t",uint16x8_t,Bitwise select -TRUE,vbslq_u32,"a: uint32x4_t, b: uint32x4_t, c: uint32x4_t",uint32x4_t,Bitwise select -TRUE,vbslq_u64,"a: uint64x2_t, b: uint64x2_t, c: uint64x2_t",uint64x2_t,Bitwise select -TRUE,vbslq_u8,"a: uint8x16_t, b: uint8x16_t, c: uint8x16_t",uint8x16_t,Bitwise select -FALSE,vcadd_rot270_f16,"a: float16x4_t, b: float16x4_t",float16x4_t,Floating-point complex add -FALSE,vcadd_rot270_f32,"a: float32x2_t, b: float32x2_t",float32x2_t,Floating-point complex add -FALSE,vcadd_rot90_f16,"a: float16x4_t, b: float16x4_t",float16x4_t,Floating-point complex add -FALSE,vcadd_rot90_f32,"a: float32x2_t, b: float32x2_t",float32x2_t,Floating-point complex add -FALSE,vcaddq_rot270_f16,"a: float16x8_t, b: float16x8_t",float16x8_t,Floating-point complex add -FALSE,vcaddq_rot270_f32,"a: float32x4_t, b: float32x4_t",float32x4_t,Floating-point complex add -FALSE,vcaddq_rot270_f64,"a: float64x2_t, b: float64x2_t",float64x2_t,Floating-point complex add -FALSE,vcaddq_rot90_f16,"a: float16x8_t, b: float16x8_t",float16x8_t,Floating-point complex add -FALSE,vcaddq_rot90_f32,"a: float32x4_t, b: float32x4_t",float32x4_t,Floating-point complex add -FALSE,vcaddq_rot90_f64,"a: float64x2_t, b: float64x2_t",float64x2_t,Floating-point complex add -FALSE,vcage_f16,"a: float16x4_t, b: float16x4_t",uint16x4_t,Floating-point absolute compare greater than or equal -TRUE,vcage_f32,"a: float32x2_t, b: float32x2_t",uint32x2_t,Floating-point absolute compare greater than or equal -TRUE,vcage_f64,"a: float64x1_t, b: float64x1_t",uint64x1_t,Floating-point absolute compare greater than or equal -FALSE,vcaged_f64,"a: float64_t, b: float64_t",u64,Floating-point absolute compare greater than or equal -FALSE,vcageh_f16,"a: float16_t, b: float16_t",u16,Floating-point absolute compare greater than or equal -FALSE,vcageq_f16,"a: float16x8_t, b: float16x8_t",uint16x8_t,Floating-point absolute compare greater than or equal -TRUE,vcageq_f32,"a: float32x4_t, b: float32x4_t",uint32x4_t,Floating-point absolute compare greater than or equal -TRUE,vcageq_f64,"a: float64x2_t, b: float64x2_t",uint64x2_t,Floating-point absolute compare greater than or equal -FALSE,vcages_f32,"a: f32, b: f32",u32,Floating-point absolute compare greater than or equal -FALSE,vcagt_f16,"a: float16x4_t, b: float16x4_t",uint16x4_t,Floating-point absolute compare greater than -TRUE,vcagt_f32,"a: float32x2_t, b: float32x2_t",uint32x2_t,Floating-point absolute compare greater than -TRUE,vcagt_f64,"a: float64x1_t, b: float64x1_t",uint64x1_t,Floating-point absolute compare greater than -FALSE,vcagtd_f64,"a: float64_t, b: float64_t",u64,Floating-point absolute compare greater than -FALSE,vcagth_f16,"a: float16_t, b: float16_t",u16,Floating-point absolute compare greater than -FALSE,vcagtq_f16,"a: float16x8_t, b: float16x8_t",uint16x8_t,Floating-point absolute compare greater than -TRUE,vcagtq_f32,"a: float32x4_t, b: float32x4_t",uint32x4_t,Floating-point absolute compare greater than -TRUE,vcagtq_f64,"a: float64x2_t, b: float64x2_t",uint64x2_t,Floating-point absolute compare greater than -FALSE,vcagts_f32,"a: f32, b: f32",u32,Floating-point absolute compare greater than -FALSE,vcale_f16,"a: float16x4_t, b: float16x4_t",uint16x4_t,Floating-point absolute compare less than or equal -TRUE,vcale_f32,"a: float32x2_t, b: float32x2_t",uint32x2_t,Floating-point absolute compare less than or equal -TRUE,vcale_f64,"a: float64x1_t, b: float64x1_t",uint64x1_t,Floating-point absolute compare less than or equal -FALSE,vcaled_f64,"a: float64_t, b: float64_t",u64,Floating-point absolute compare less than or equal -FALSE,vcaleh_f16,"a: float16_t, b: float16_t",u16,Floating-point absolute compare less than or equal -FALSE,vcaleq_f16,"a: float16x8_t, b: float16x8_t",uint16x8_t,Floating-point absolute compare less than or equal -TRUE,vcaleq_f32,"a: float32x4_t, b: float32x4_t",uint32x4_t,Floating-point absolute compare less than or equal -TRUE,vcaleq_f64,"a: float64x2_t, b: float64x2_t",uint64x2_t,Floating-point absolute compare less than or equal -FALSE,vcales_f32,"a: f32, b: f32",u32,Floating-point absolute compare less than or equal -FALSE,vcalt_f16,"a: float16x4_t, b: float16x4_t",uint16x4_t,Floating-point absolute compare less than -TRUE,vcalt_f32,"a: float32x2_t, b: float32x2_t",uint32x2_t,Floating-point absolute compare less than -TRUE,vcalt_f64,"a: float64x1_t, b: float64x1_t",uint64x1_t,Floating-point absolute compare less than -FALSE,vcaltd_f64,"a: float64_t, b: float64_t",u64,Floating-point absolute compare less than -FALSE,vcalth_f16,"a: float16_t, b: float16_t",u16,Floating-point absolute compare less than -FALSE,vcaltq_f16,"a: float16x8_t, b: float16x8_t",uint16x8_t,Floating-point absolute compare less than -TRUE,vcaltq_f32,"a: float32x4_t, b: float32x4_t",uint32x4_t,Floating-point absolute compare less than -TRUE,vcaltq_f64,"a: float64x2_t, b: float64x2_t",uint64x2_t,Floating-point absolute compare less than -FALSE,vcalts_f32,"a: f32, b: f32",u32,Floating-point absolute compare less than -FALSE,vceq_f16,"a: float16x4_t, b: float16x4_t",uint16x4_t,Floating-point compare equal -TRUE,vceq_f32,"a: float32x2_t, b: float32x2_t",uint32x2_t,Floating-point compare equal -TRUE,vceq_f64,"a: float64x1_t, b: float64x1_t",uint64x1_t,Floating-point compare equal -TRUE,vceq_p64,"a: poly64x1_t, b: poly64x1_t",uint64x1_t,Compare bitwise equal -FALSE,vceq_p8,"a: poly8x8_t, b: poly8x8_t",uint8x8_t,Compare bitwise equal -TRUE,vceq_s16,"a: int16x4_t, b: int16x4_t",uint16x4_t,Compare bitwise equal -TRUE,vceq_s32,"a: int32x2_t, b: int32x2_t",uint32x2_t,Compare bitwise equal -TRUE,vceq_s64,"a: int64x1_t, b: int64x1_t",uint64x1_t,Compare bitwise equal -TRUE,vceq_s8,"a: int8x8_t, b: int8x8_t",uint8x8_t,Compare bitwise equal -TRUE,vceq_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4_t,Compare bitwise equal -TRUE,vceq_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2_t,Compare bitwise equal -TRUE,vceq_u64,"a: uint64x1_t, b: uint64x1_t",uint64x1_t,Compare bitwise equal -TRUE,vceq_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,Compare bitwise equal -FALSE,vceqd_f64,"a: float64_t, b: float64_t",u64,Floating-point compare equal -FALSE,vceqd_s64,"a: i64, b: i64",u64,Compare bitwise equal -FALSE,vceqd_u64,"a: u64, b: u64",u64,Compare bitwise equal -FALSE,vceqh_f16,"a: float16_t, b: float16_t",u16,Floating-point compare equal -FALSE,vceqq_f16,"a: float16x8_t, b: float16x8_t",uint16x8_t,Floating-point compare equal -TRUE,vceqq_f32,"a: float32x4_t, b: float32x4_t",uint32x4_t,Floating-point compare equal -TRUE,vceqq_f64,"a: float64x2_t, b: float64x2_t",uint64x2_t,Floating-point compare equal -TRUE,vceqq_p64,"a: poly64x2_t, b: poly64x2_t",uint64x2_t,Compare bitwise equal -TRUE,vceqq_p8,"a: poly8x16_t, b: poly8x16_t",uint8x16_t,Compare bitwise equal -TRUE,vceqq_s16,"a: int16x8_t, b: int16x8_t",uint16x8_t,Compare bitwise equal -TRUE,vceqq_s32,"a: int32x4_t, b: int32x4_t",uint32x4_t,Compare bitwise equal -TRUE,vceqq_s64,"a: int64x2_t, b: int64x2_t",uint64x2_t,Compare bitwise equal -TRUE,vceqq_s8,"a: int8x16_t, b: int8x16_t",uint8x16_t,Compare bitwise equal -TRUE,vceqq_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8_t,Compare bitwise equal -TRUE,vceqq_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,Compare bitwise equal -TRUE,vceqq_u64,"a: uint64x2_t, b: uint64x2_t",uint64x2_t,Compare bitwise equal -TRUE,vceqq_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16_t,Compare bitwise equal -FALSE,vceqs_f32,"a: f32, b: f32",u32,Floating-point compare equal -FALSE,vceqz_f16,a: float16x4_t,uint16x4_t,Floating-point compare equal to zero -TRUE,vceqz_f32,a: float32x2_t,uint32x2_t,Floating-point compare equal to zero -TRUE,vceqz_f64,a: float64x1_t,uint64x1_t,Floating-point compare equal to zero -TRUE,vceqz_p64,a: poly64x1_t,uint64x1_t,Compare bitwise equal to zero -TRUE,vceqz_p8,a: poly8x8_t,uint8x8_t,Compare bitwise equal to zero -TRUE,vceqz_s16,a: int16x4_t,uint16x4_t,Compare bitwise equal to zero -TRUE,vceqz_s32,a: int32x2_t,uint32x2_t,Compare bitwise equal to zero -TRUE,vceqz_s64,a: int64x1_t,uint64x1_t,Compare bitwise equal to zero -TRUE,vceqz_s8,a: int8x8_t,uint8x8_t,Compare bitwise equal to zero -TRUE,vceqz_u16,a: uint16x4_t,uint16x4_t,Compare bitwise equal to zero -TRUE,vceqz_u32,a: uint32x2_t,uint32x2_t,Compare bitwise equal to zero -TRUE,vceqz_u64,a: uint64x1_t,uint64x1_t,Compare bitwise equal to zero -TRUE,vceqz_u8,a: uint8x8_t,uint8x8_t,Compare bitwise equal to zero -FALSE,vceqzd_f64,a: float64_t,u64,Floating-point compare equal to zero -FALSE,vceqzd_s64,a: i64,u64,Compare bitwise equal to zero -FALSE,vceqzd_u64,a: u64,u64,Compare bitwise equal to zero -FALSE,vceqzh_f16,a: float16_t,u16,Floating-point compare equal to zero -FALSE,vceqzq_f16,a: float16x8_t,uint16x8_t,Floating-point compare equal to zero -TRUE,vceqzq_f32,a: float32x4_t,uint32x4_t,Floating-point compare equal to zero -TRUE,vceqzq_f64,a: float64x2_t,uint64x2_t,Floating-point compare equal to zero -TRUE,vceqzq_p64,a: poly64x2_t,uint64x2_t,Compare bitwise equal to zero -TRUE,vceqzq_p8,a: poly8x16_t,uint8x16_t,Compare bitwise equal to zero -TRUE,vceqzq_s16,a: int16x8_t,uint16x8_t,Compare bitwise equal to zero -TRUE,vceqzq_s32,a: int32x4_t,uint32x4_t,Compare bitwise equal to zero -TRUE,vceqzq_s64,a: int64x2_t,uint64x2_t,Compare bitwise equal to zero -TRUE,vceqzq_s8,a: int8x16_t,uint8x16_t,Compare bitwise equal to zero -TRUE,vceqzq_u16,a: uint16x8_t,uint16x8_t,Compare bitwise equal to zero -TRUE,vceqzq_u32,a: uint32x4_t,uint32x4_t,Compare bitwise equal to zero -TRUE,vceqzq_u64,a: uint64x2_t,uint64x2_t,Compare bitwise equal to zero -TRUE,vceqzq_u8,a: uint8x16_t,uint8x16_t,Compare bitwise equal to zero -FALSE,vceqzs_f32,a: f32,u32,Floating-point compare equal to zero -FALSE,vcge_f16,"a: float16x4_t, b: float16x4_t",uint16x4_t,Floating-point compare greater than or equal -TRUE,vcge_f32,"a: float32x2_t, b: float32x2_t",uint32x2_t,Floating-point compare greater than or equal -TRUE,vcge_f64,"a: float64x1_t, b: float64x1_t",uint64x1_t,Floating-point compare greater than or equal -TRUE,vcge_s16,"a: int16x4_t, b: int16x4_t",uint16x4_t,Compare signed greater than or equal -TRUE,vcge_s32,"a: int32x2_t, b: int32x2_t",uint32x2_t,Compare signed greater than or equal -TRUE,vcge_s64,"a: int64x1_t, b: int64x1_t",uint64x1_t,Compare signed greater than or equal -TRUE,vcge_s8,"a: int8x8_t, b: int8x8_t",uint8x8_t,Compare signed greater than or equal -TRUE,vcge_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4_t,Compare unsigned higher or same -TRUE,vcge_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2_t,Compare unsigned higher or same -TRUE,vcge_u64,"a: uint64x1_t, b: uint64x1_t",uint64x1_t,Compare unsigned higher or same -TRUE,vcge_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,Compare unsigned higher or same -FALSE,vcged_f64,"a: float64_t, b: float64_t",u64,Floating-point compare greater than or equal -FALSE,vcged_s64,"a: i64, b: i64",u64,Compare signed greater than or equal -FALSE,vcged_u64,"a: u64, b: u64",u64,Compare unsigned higher or same -FALSE,vcgeh_f16,"a: float16_t, b: float16_t",u16,Floating-point compare greater than or equal -FALSE,vcgeq_f16,"a: float16x8_t, b: float16x8_t",uint16x8_t,Floating-point compare greater than or equal -TRUE,vcgeq_f32,"a: float32x4_t, b: float32x4_t",uint32x4_t,Floating-point compare greater than or equal -TRUE,vcgeq_f64,"a: float64x2_t, b: float64x2_t",uint64x2_t,Floating-point compare greater than or equal -TRUE,vcgeq_s16,"a: int16x8_t, b: int16x8_t",uint16x8_t,Compare signed greater than or equal -TRUE,vcgeq_s32,"a: int32x4_t, b: int32x4_t",uint32x4_t,Compare signed greater than or equal -TRUE,vcgeq_s64,"a: int64x2_t, b: int64x2_t",uint64x2_t,Compare signed greater than or equal -TRUE,vcgeq_s8,"a: int8x16_t, b: int8x16_t",uint8x16_t,Compare signed greater than or equal -TRUE,vcgeq_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8_t,Compare unsigned higher or same -TRUE,vcgeq_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,Compare unsigned higher or same -TRUE,vcgeq_u64,"a: uint64x2_t, b: uint64x2_t",uint64x2_t,Compare unsigned higher or same -TRUE,vcgeq_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16_t,Compare unsigned higher or same -FALSE,vcges_f32,"a: f32, b: f32",u32,Floating-point compare greater than or equal -FALSE,vcgez_f16,a: float16x4_t,uint16x4_t,Floating-point compare greater than or equal to zero -TRUE,vcgez_f32,a: float32x2_t,uint32x2_t,Floating-point compare greater than or equal to zero -TRUE,vcgez_f64,a: float64x1_t,uint64x1_t,Floating-point compare greater than or equal to zero -TRUE,vcgez_s16,a: int16x4_t,uint16x4_t,Compare signed greater than or equal to zero -TRUE,vcgez_s32,a: int32x2_t,uint32x2_t,Compare signed greater than or equal to zero -TRUE,vcgez_s64,a: int64x1_t,uint64x1_t,Compare signed greater than or equal to zero -TRUE,vcgez_s8,a: int8x8_t,uint8x8_t,Compare signed greater than or equal to zero -FALSE,vcgezd_f64,a: float64_t,u64,Floating-point compare greater than or equal to zero -FALSE,vcgezd_s64,a: i64,u64,Compare signed greater than or equal to zero -FALSE,vcgezh_f16,a: float16_t,u16,Floating-point compare greater than or equal to zero -FALSE,vcgezq_f16,a: float16x8_t,uint16x8_t,Floating-point compare greater than or equal to zero -TRUE,vcgezq_f32,a: float32x4_t,uint32x4_t,Floating-point compare greater than or equal to zero -TRUE,vcgezq_f64,a: float64x2_t,uint64x2_t,Floating-point compare greater than or equal to zero -TRUE,vcgezq_s16,a: int16x8_t,uint16x8_t,Compare signed greater than or equal to zero -TRUE,vcgezq_s32,a: int32x4_t,uint32x4_t,Compare signed greater than or equal to zero -TRUE,vcgezq_s64,a: int64x2_t,uint64x2_t,Compare signed greater than or equal to zero -TRUE,vcgezq_s8,a: int8x16_t,uint8x16_t,Compare signed greater than or equal to zero -FALSE,vcgezs_f32,a: f32,u32,Floating-point compare greater than or equal to zero -FALSE,vcgt_f16,"a: float16x4_t, b: float16x4_t",uint16x4_t,Floating-point compare greater than -TRUE,vcgt_f32,"a: float32x2_t, b: float32x2_t",uint32x2_t,Floating-point compare greater than -TRUE,vcgt_f64,"a: float64x1_t, b: float64x1_t",uint64x1_t,Floating-point compare greater than -TRUE,vcgt_s16,"a: int16x4_t, b: int16x4_t",uint16x4_t,Compare signed greater than -TRUE,vcgt_s32,"a: int32x2_t, b: int32x2_t",uint32x2_t,Compare signed greater than -TRUE,vcgt_s64,"a: int64x1_t, b: int64x1_t",uint64x1_t,Compare signed greater than -TRUE,vcgt_s8,"a: int8x8_t, b: int8x8_t",uint8x8_t,Compare signed greater than -TRUE,vcgt_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4_t,Compare unsigned higher -TRUE,vcgt_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2_t,Compare unsigned higher -TRUE,vcgt_u64,"a: uint64x1_t, b: uint64x1_t",uint64x1_t,Compare unsigned higher -TRUE,vcgt_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,Compare unsigned higher -FALSE,vcgtd_f64,"a: float64_t, b: float64_t",u64,Floating-point compare greater than -FALSE,vcgtd_s64,"a: i64, b: i64",u64,Compare signed greater than -FALSE,vcgtd_u64,"a: u64, b: u64",u64,Compare unsigned higher -FALSE,vcgth_f16,"a: float16_t, b: float16_t",u16,Floating-point compare greater than -FALSE,vcgtq_f16,"a: float16x8_t, b: float16x8_t",uint16x8_t,Floating-point compare greater than -TRUE,vcgtq_f32,"a: float32x4_t, b: float32x4_t",uint32x4_t,Floating-point compare greater than -TRUE,vcgtq_f64,"a: float64x2_t, b: float64x2_t",uint64x2_t,Floating-point compare greater than -TRUE,vcgtq_s16,"a: int16x8_t, b: int16x8_t",uint16x8_t,Compare signed greater than -TRUE,vcgtq_s32,"a: int32x4_t, b: int32x4_t",uint32x4_t,Compare signed greater than -TRUE,vcgtq_s64,"a: int64x2_t, b: int64x2_t",uint64x2_t,Compare signed greater than -TRUE,vcgtq_s8,"a: int8x16_t, b: int8x16_t",uint8x16_t,Compare signed greater than -TRUE,vcgtq_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8_t,Compare unsigned higher -TRUE,vcgtq_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,Compare unsigned higher -TRUE,vcgtq_u64,"a: uint64x2_t, b: uint64x2_t",uint64x2_t,Compare unsigned higher -TRUE,vcgtq_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16_t,Compare unsigned higher -FALSE,vcgts_f32,"a: f32, b: f32",u32,Floating-point compare greater than -FALSE,vcgtz_f16,a: float16x4_t,uint16x4_t,Floating-point compare greater than zero -TRUE,vcgtz_f32,a: float32x2_t,uint32x2_t,Floating-point compare greater than zero -TRUE,vcgtz_f64,a: float64x1_t,uint64x1_t,Floating-point compare greater than zero -TRUE,vcgtz_s16,a: int16x4_t,uint16x4_t,Compare signed greater than zero -TRUE,vcgtz_s32,a: int32x2_t,uint32x2_t,Compare signed greater than zero -TRUE,vcgtz_s64,a: int64x1_t,uint64x1_t,Compare signed greater than zero -TRUE,vcgtz_s8,a: int8x8_t,uint8x8_t,Compare signed greater than zero -FALSE,vcgtzd_f64,a: float64_t,u64,Floating-point compare greater than zero -FALSE,vcgtzd_s64,a: i64,u64,Compare signed greater than zero -FALSE,vcgtzh_f16,a: float16_t,u16,Floating-point compare greater than zero -FALSE,vcgtzq_f16,a: float16x8_t,uint16x8_t,Floating-point compare greater than zero -TRUE,vcgtzq_f32,a: float32x4_t,uint32x4_t,Floating-point compare greater than zero -TRUE,vcgtzq_f64,a: float64x2_t,uint64x2_t,Floating-point compare greater than zero -TRUE,vcgtzq_s16,a: int16x8_t,uint16x8_t,Compare signed greater than zero -TRUE,vcgtzq_s32,a: int32x4_t,uint32x4_t,Compare signed greater than zero -TRUE,vcgtzq_s64,a: int64x2_t,uint64x2_t,Compare signed greater than zero -TRUE,vcgtzq_s8,a: int8x16_t,uint8x16_t,Compare signed greater than zero -FALSE,vcgtzs_f32,a: f32,u32,Floating-point compare greater than zero -FALSE,vcle_f16,"a: float16x4_t, b: float16x4_t",uint16x4_t,Floating-point compare less than or equal -TRUE,vcle_f32,"a: float32x2_t, b: float32x2_t",uint32x2_t,Floating-point compare less than or equal -TRUE,vcle_f64,"a: float64x1_t, b: float64x1_t",uint64x1_t,Floating-point compare less than or equal -TRUE,vcle_s16,"a: int16x4_t, b: int16x4_t",uint16x4_t,Compare signed less than or equal -TRUE,vcle_s32,"a: int32x2_t, b: int32x2_t",uint32x2_t,Compare signed less than or equal -TRUE,vcle_s64,"a: int64x1_t, b: int64x1_t",uint64x1_t,Compare signed less than or equal -TRUE,vcle_s8,"a: int8x8_t, b: int8x8_t",uint8x8_t,Compare signed less than or equal -TRUE,vcle_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4_t,Compare unsigned less than or equal -TRUE,vcle_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2_t,Compare unsigned less than or equal -TRUE,vcle_u64,"a: uint64x1_t, b: uint64x1_t",uint64x1_t,Compare unsigned less than or equal -TRUE,vcle_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,Compare unsigned less than or equal -FALSE,vcled_f64,"a: float64_t, b: float64_t",u64,Floating-point compare less than or equal -FALSE,vcled_s64,"a: i64, b: i64",u64,Compare signed less than or equal -FALSE,vcled_u64,"a: u64, b: u64",u64,Compare unsigned less than or equal -FALSE,vcleh_f16,"a: float16_t, b: float16_t",u16,Floating-point compare less than or equal -FALSE,vcleq_f16,"a: float16x8_t, b: float16x8_t",uint16x8_t,Floating-point compare less than or equal -TRUE,vcleq_f32,"a: float32x4_t, b: float32x4_t",uint32x4_t,Floating-point compare less than or equal -TRUE,vcleq_f64,"a: float64x2_t, b: float64x2_t",uint64x2_t,Floating-point compare less than or equal -TRUE,vcleq_s16,"a: int16x8_t, b: int16x8_t",uint16x8_t,Compare signed less than or equal -TRUE,vcleq_s32,"a: int32x4_t, b: int32x4_t",uint32x4_t,Compare signed less than or equal -TRUE,vcleq_s64,"a: int64x2_t, b: int64x2_t",uint64x2_t,Compare signed less than or equal -TRUE,vcleq_s8,"a: int8x16_t, b: int8x16_t",uint8x16_t,Compare signed less than or equal -TRUE,vcleq_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8_t,Compare unsigned less than or equal -TRUE,vcleq_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,Compare unsigned less than or equal -TRUE,vcleq_u64,"a: uint64x2_t, b: uint64x2_t",uint64x2_t,Compare unsigned less than or equal -TRUE,vcleq_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16_t,Compare unsigned less than or equal -FALSE,vcles_f32,"a: f32, b: f32",u32,Floating-point compare less than or equal -FALSE,vclez_f16,a: float16x4_t,uint16x4_t,Floating-point compare less than or equal to zero -TRUE,vclez_f32,a: float32x2_t,uint32x2_t,Floating-point compare less than or equal to zero -TRUE,vclez_f64,a: float64x1_t,uint64x1_t,Floating-point compare less than or equal to zero -TRUE,vclez_s16,a: int16x4_t,uint16x4_t,Compare signed less than or equal to zero -TRUE,vclez_s32,a: int32x2_t,uint32x2_t,Compare signed less than or equal to zero -TRUE,vclez_s64,a: int64x1_t,uint64x1_t,Compare signed less than or equal to zero -TRUE,vclez_s8,a: int8x8_t,uint8x8_t,Compare signed less than or equal to zero -FALSE,vclezd_f64,a: float64_t,u64,Floating-point compare less than or equal to zero -FALSE,vclezd_s64,a: i64,u64,Compare signed less than or equal to zero -FALSE,vclezh_f16,a: float16_t,u16,Floating-point compare less than or equal to zero -FALSE,vclezq_f16,a: float16x8_t,uint16x8_t,Floating-point compare less than or equal to zero -TRUE,vclezq_f32,a: float32x4_t,uint32x4_t,Floating-point compare less than or equal to zero -TRUE,vclezq_f64,a: float64x2_t,uint64x2_t,Floating-point compare less than or equal to zero -TRUE,vclezq_s16,a: int16x8_t,uint16x8_t,Compare signed less than or equal to zero -TRUE,vclezq_s32,a: int32x4_t,uint32x4_t,Compare signed less than or equal to zero -TRUE,vclezq_s64,a: int64x2_t,uint64x2_t,Compare signed less than or equal to zero -TRUE,vclezq_s8,a: int8x16_t,uint8x16_t,Compare signed less than or equal to zero -FALSE,vclezs_f32,a: f32,u32,Floating-point compare less than or equal to zero -TRUE,vcls_s16,a: int16x4_t,int16x4_t,Count leading sign bits -TRUE,vcls_s32,a: int32x2_t,int32x2_t,Count leading sign bits -TRUE,vcls_s8,a: int8x8_t,int8x8_t,Count leading sign bits -TRUE,vclsq_s16,a: int16x8_t,int16x8_t,Count leading sign bits -TRUE,vclsq_s32,a: int32x4_t,int32x4_t,Count leading sign bits -TRUE,vclsq_s8,a: int8x16_t,int8x16_t,Count leading sign bits -FALSE,vclt_f16,"a: float16x4_t, b: float16x4_t",uint16x4_t,Floating-point compare less than -TRUE,vclt_f32,"a: float32x2_t, b: float32x2_t",uint32x2_t,Floating-point compare less than -TRUE,vclt_f64,"a: float64x1_t, b: float64x1_t",uint64x1_t,Floating-point compare less than -TRUE,vclt_s16,"a: int16x4_t, b: int16x4_t",uint16x4_t,Compare signed less than -TRUE,vclt_s32,"a: int32x2_t, b: int32x2_t",uint32x2_t,Compare signed less than -TRUE,vclt_s64,"a: int64x1_t, b: int64x1_t",uint64x1_t,Compare signed less than -TRUE,vclt_s8,"a: int8x8_t, b: int8x8_t",uint8x8_t,Compare signed less than -TRUE,vclt_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4_t,Compare unsigned less than -TRUE,vclt_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2_t,Compare unsigned less than -TRUE,vclt_u64,"a: uint64x1_t, b: uint64x1_t",uint64x1_t,Compare unsigned less than -TRUE,vclt_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,Compare unsigned less than -FALSE,vcltd_f64,"a: float64_t, b: float64_t",u64,Floating-point compare less than -FALSE,vcltd_s64,"a: i64, b: i64",u64,Compare signed less than -FALSE,vcltd_u64,"a: u64, b: u64",u64,Compare unsigned less than -FALSE,vclth_f16,"a: float16_t, b: float16_t",u16,Floating-point compare less than -FALSE,vcltq_f16,"a: float16x8_t, b: float16x8_t",uint16x8_t,Floating-point compare less than -TRUE,vcltq_f32,"a: float32x4_t, b: float32x4_t",uint32x4_t,Floating-point compare less than -TRUE,vcltq_f64,"a: float64x2_t, b: float64x2_t",uint64x2_t,Floating-point compare less than -TRUE,vcltq_s16,"a: int16x8_t, b: int16x8_t",uint16x8_t,Compare signed less than -TRUE,vcltq_s32,"a: int32x4_t, b: int32x4_t",uint32x4_t,Compare signed less than -TRUE,vcltq_s64,"a: int64x2_t, b: int64x2_t",uint64x2_t,Compare signed less than -TRUE,vcltq_s8,"a: int8x16_t, b: int8x16_t",uint8x16_t,Compare signed less than -TRUE,vcltq_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8_t,Compare unsigned less than -TRUE,vcltq_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,Compare unsigned less than -TRUE,vcltq_u64,"a: uint64x2_t, b: uint64x2_t",uint64x2_t,Compare unsigned less than -TRUE,vcltq_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16_t,Compare unsigned less than -FALSE,vclts_f32,"a: f32, b: f32",u32,Floating-point compare less than -FALSE,vcltz_f16,a: float16x4_t,uint16x4_t,Floating-point compare less than zero -TRUE,vcltz_f32,a: float32x2_t,uint32x2_t,Floating-point compare less than zero -TRUE,vcltz_f64,a: float64x1_t,uint64x1_t,Floating-point compare less than zero -TRUE,vcltz_s16,a: int16x4_t,uint16x4_t,Compare signed less than zero -TRUE,vcltz_s32,a: int32x2_t,uint32x2_t,Compare signed less than zero -TRUE,vcltz_s64,a: int64x1_t,uint64x1_t,Compare signed less than zero -TRUE,vcltz_s8,a: int8x8_t,uint8x8_t,Compare signed less than zero -FALSE,vcltzd_f64,a: float64_t,u64,Floating-point compare less than zero -FALSE,vcltzd_s64,a: i64,u64,Compare signed less than zero -FALSE,vcltzh_f16,a: float16_t,u16,Floating-point compare less than zero -FALSE,vcltzq_f16,a: float16x8_t,uint16x8_t,Floating-point compare less than zero -TRUE,vcltzq_f32,a: float32x4_t,uint32x4_t,Floating-point compare less than zero -TRUE,vcltzq_f64,a: float64x2_t,uint64x2_t,Floating-point compare less than zero -TRUE,vcltzq_s16,a: int16x8_t,uint16x8_t,Compare signed less than zero -TRUE,vcltzq_s32,a: int32x4_t,uint32x4_t,Compare signed less than zero -TRUE,vcltzq_s64,a: int64x2_t,uint64x2_t,Compare signed less than zero -TRUE,vcltzq_s8,a: int8x16_t,uint8x16_t,Compare signed less than zero -FALSE,vcltzs_f32,a: f32,u32,Floating-point compare less than zero -TRUE,vclz_s16,a: int16x4_t,int16x4_t,Count leading zero bits -TRUE,vclz_s32,a: int32x2_t,int32x2_t,Count leading zero bits -TRUE,vclz_s8,a: int8x8_t,int8x8_t,Count leading zero bits -TRUE,vclz_u16,a: uint16x4_t,uint16x4_t,Count leading zero bits -TRUE,vclz_u32,a: uint32x2_t,uint32x2_t,Count leading zero bits -TRUE,vclz_u8,a: uint8x8_t,uint8x8_t,Count leading zero bits -TRUE,vclzq_s16,a: int16x8_t,int16x8_t,Count leading zero bits -TRUE,vclzq_s32,a: int32x4_t,int32x4_t,Count leading zero bits -TRUE,vclzq_s8,a: int8x16_t,int8x16_t,Count leading zero bits -TRUE,vclzq_u16,a: uint16x8_t,uint16x8_t,Count leading zero bits -TRUE,vclzq_u32,a: uint32x4_t,uint32x4_t,Count leading zero bits -TRUE,vclzq_u8,a: uint8x16_t,uint8x16_t,Count leading zero bits -FALSE,vcmla_f16,"r: float16x4_t, a: float16x4_t, b: float16x4_t",float16x4_t,Floating-point complex multiply accumulate -FALSE,vcmla_f32,"r: float32x2_t, a: float32x2_t, b: float32x2_t",float32x2_t,Floating-point complex multiply accumulate -FALSE,vcmla_lane_f16,"r: float16x4_t, a: float16x4_t, b: float16x4_t, lane: const int",float16x4_t,Floating-point complex multiply accumulate -FALSE,vcmla_lane_f32,"r: float32x2_t, a: float32x2_t, b: float32x2_t, lane: const int",float32x2_t,Floating-point complex multiply accumulate -FALSE,vcmla_laneq_f16,"r: float16x4_t, a: float16x4_t, b: float16x8_t, lane: const int",float16x4_t,Floating-point complex multiply accumulate -FALSE,vcmla_laneq_f16,"r: float16x4_t, a: float16x4_t, b: float16x8_t, lane: const int",float16x4_t,Floating-point complex multiply accumulate -FALSE,vcmla_laneq_f32,"r: float32x2_t, a: float32x2_t, b: float32x4_t, lane: const int",float32x2_t,Floating-point complex multiply accumulate -FALSE,vcmla_rot180_f16,"r: float16x4_t, a: float16x4_t, b: float16x4_t",float16x4_t,Floating-point complex multiply accumulate -FALSE,vcmla_rot180_f32,"r: float32x2_t, a: float32x2_t, b: float32x2_t",float32x2_t,Floating-point complex multiply accumulate -FALSE,vcmla_rot180_lane_f16,"r: float16x4_t, a: float16x4_t, b: float16x4_t, lane: const int",float16x4_t,Floating-point complex multiply accumulate -FALSE,vcmla_rot180_lane_f32,"r: float32x2_t, a: float32x2_t, b: float32x2_t, lane: const int",float32x2_t,Floating-point complex multiply accumulate -FALSE,vcmla_rot180_laneq_f16,"r: float16x4_t, a: float16x4_t, b: float16x8_t, lane: const int",float16x4_t,Floating-point complex multiply accumulate -FALSE,vcmla_rot180_laneq_f16,"r: float16x4_t, a: float16x4_t, b: float16x8_t, lane: const int",float16x4_t,Floating-point complex multiply accumulate -FALSE,vcmla_rot180_laneq_f32,"r: float32x2_t, a: float32x2_t, b: float32x4_t, lane: const int",float32x2_t,Floating-point complex multiply accumulate -FALSE,vcmla_rot270_f16,"r: float16x4_t, a: float16x4_t, b: float16x4_t",float16x4_t,Floating-point complex multiply accumulate -FALSE,vcmla_rot270_f32,"r: float32x2_t, a: float32x2_t, b: float32x2_t",float32x2_t,Floating-point complex multiply accumulate -FALSE,vcmla_rot270_lane_f16,"r: float16x4_t, a: float16x4_t, b: float16x4_t, lane: const int",float16x4_t,Floating-point complex multiply accumulate -FALSE,vcmla_rot270_lane_f32,"r: float32x2_t, a: float32x2_t, b: float32x2_t, lane: const int",float32x2_t,Floating-point complex multiply accumulate -FALSE,vcmla_rot270_laneq_f16,"r: float16x4_t, a: float16x4_t, b: float16x8_t, lane: const int",float16x4_t,Floating-point complex multiply accumulate -FALSE,vcmla_rot270_laneq_f16,"r: float16x4_t, a: float16x4_t, b: float16x8_t, lane: const int",float16x4_t,Floating-point complex multiply accumulate -FALSE,vcmla_rot270_laneq_f32,"r: float32x2_t, a: float32x2_t, b: float32x4_t, lane: const int",float32x2_t,Floating-point complex multiply accumulate -FALSE,vcmla_rot90_f16,"r: float16x4_t, a: float16x4_t, b: float16x4_t",float16x4_t,Floating-point complex multiply accumulate -FALSE,vcmla_rot90_f32,"r: float32x2_t, a: float32x2_t, b: float32x2_t",float32x2_t,Floating-point complex multiply accumulate -FALSE,vcmla_rot90_lane_f16,"r: float16x4_t, a: float16x4_t, b: float16x4_t, lane: const int",float16x4_t,Floating-point complex multiply accumulate -FALSE,vcmla_rot90_lane_f32,"r: float32x2_t, a: float32x2_t, b: float32x2_t, lane: const int",float32x2_t,Floating-point complex multiply accumulate -FALSE,vcmla_rot90_laneq_f16,"r: float16x4_t, a: float16x4_t, b: float16x8_t, lane: const int",float16x4_t,Floating-point complex multiply accumulate -FALSE,vcmla_rot90_laneq_f16,"r: float16x4_t, a: float16x4_t, b: float16x8_t, lane: const int",float16x4_t,Floating-point complex multiply accumulate -FALSE,vcmla_rot90_laneq_f32,"r: float32x2_t, a: float32x2_t, b: float32x4_t, lane: const int",float32x2_t,Floating-point complex multiply accumulate -FALSE,vcmlaq_f16,"r: float16x8_t, a: float16x8_t, b: float16x8_t",float16x8_t,Floating-point complex multiply accumulate -FALSE,vcmlaq_f32,"r: float32x4_t, a: float32x4_t, b: float32x4_t",float32x4_t,Floating-point complex multiply accumulate -FALSE,vcmlaq_f64,"r: float64x2_t, a: float64x2_t, b: float64x2_t",float64x2_t,Floating-point complex multiply accumulate -FALSE,vcmlaq_lane_f16,"r: float16x8_t, a: float16x8_t, b: float16x4_t, lane: const int",float16x8_t,Floating-point complex multiply accumulate -FALSE,vcmlaq_lane_f32,"r: float32x4_t, a: float32x4_t, b: float32x2_t, lane: const int",float32x4_t,Floating-point complex multiply accumulate -FALSE,vcmlaq_laneq_f16,"r: float16x8_t, a: float16x8_t, b: float16x8_t, lane: const int",float16x8_t,Floating-point complex multiply accumulate -FALSE,vcmlaq_laneq_f32,"r: float32x4_t, a: float32x4_t, b: float32x4_t, lane: const int",float32x4_t,Floating-point complex multiply accumulate -FALSE,vcmlaq_rot180_f16,"r: float16x8_t, a: float16x8_t, b: float16x8_t",float16x8_t,Floating-point complex multiply accumulate -FALSE,vcmlaq_rot180_f32,"r: float32x4_t, a: float32x4_t, b: float32x4_t",float32x4_t,Floating-point complex multiply accumulate -FALSE,vcmlaq_rot180_f64,"r: float64x2_t, a: float64x2_t, b: float64x2_t",float64x2_t,Floating-point complex multiply accumulate -FALSE,vcmlaq_rot180_lane_f16,"r: float16x8_t, a: float16x8_t, b: float16x4_t, lane: const int",float16x8_t,Floating-point complex multiply accumulate -FALSE,vcmlaq_rot180_lane_f32,"r: float32x4_t, a: float32x4_t, b: float32x2_t, lane: const int",float32x4_t,Floating-point complex multiply accumulate -FALSE,vcmlaq_rot180_laneq_f16,"r: float16x8_t, a: float16x8_t, b: float16x8_t, lane: const int",float16x8_t,Floating-point complex multiply accumulate -FALSE,vcmlaq_rot180_laneq_f32,"r: float32x4_t, a: float32x4_t, b: float32x4_t, lane: const int",float32x4_t,Floating-point complex multiply accumulate -FALSE,vcmlaq_rot270_f16,"r: float16x8_t, a: float16x8_t, b: float16x8_t",float16x8_t,Floating-point complex multiply accumulate -FALSE,vcmlaq_rot270_f32,"r: float32x4_t, a: float32x4_t, b: float32x4_t",float32x4_t,Floating-point complex multiply accumulate -FALSE,vcmlaq_rot270_f64,"r: float64x2_t, a: float64x2_t, b: float64x2_t",float64x2_t,Floating-point complex multiply accumulate -FALSE,vcmlaq_rot270_lane_f16,"r: float16x8_t, a: float16x8_t, b: float16x4_t, lane: const int",float16x8_t,Floating-point complex multiply accumulate -FALSE,vcmlaq_rot270_lane_f32,"r: float32x4_t, a: float32x4_t, b: float32x2_t, lane: const int",float32x4_t,Floating-point complex multiply accumulate -FALSE,vcmlaq_rot270_laneq_f16,"r: float16x8_t, a: float16x8_t, b: float16x8_t, lane: const int",float16x8_t,Floating-point complex multiply accumulate -FALSE,vcmlaq_rot270_laneq_f32,"r: float32x4_t, a: float32x4_t, b: float32x4_t, lane: const int",float32x4_t,Floating-point complex multiply accumulate -FALSE,vcmlaq_rot90_f16,"r: float16x8_t, a: float16x8_t, b: float16x8_t",float16x8_t,Floating-point complex multiply accumulate -FALSE,vcmlaq_rot90_f32,"r: float32x4_t, a: float32x4_t, b: float32x4_t",float32x4_t,Floating-point complex multiply accumulate -FALSE,vcmlaq_rot90_f64,"r: float64x2_t, a: float64x2_t, b: float64x2_t",float64x2_t,Floating-point complex multiply accumulate -FALSE,vcmlaq_rot90_lane_f16,"r: float16x8_t, a: float16x8_t, b: float16x4_t, lane: const int",float16x8_t,Floating-point complex multiply accumulate -FALSE,vcmlaq_rot90_lane_f32,"r: float32x4_t, a: float32x4_t, b: float32x2_t, lane: const int",float32x4_t,Floating-point complex multiply accumulate -FALSE,vcmlaq_rot90_laneq_f16,"r: float16x8_t, a: float16x8_t, b: float16x8_t, lane: const int",float16x8_t,Floating-point complex multiply accumulate -FALSE,vcmlaq_rot90_laneq_f32,"r: float32x4_t, a: float32x4_t, b: float32x4_t, lane: const int",float32x4_t,Floating-point complex multiply accumulate -TRUE,vcnt_p8,a: poly8x8_t,poly8x8_t,Population count per byte -TRUE,vcnt_s8,a: int8x8_t,int8x8_t,Population count per byte -TRUE,vcnt_u8,a: uint8x8_t,uint8x8_t,Population count per byte -TRUE,vcntq_p8,a: poly8x16_t,poly8x16_t,Population count per byte -TRUE,vcntq_s8,a: int8x16_t,int8x16_t,Population count per byte -TRUE,vcntq_u8,a: uint8x16_t,uint8x16_t,Population count per byte -FALSE,vcombine_bf16,"low: bfloat16x4_t, high: bfloat16x4_t",bfloat16x8_t,Insert vector element from another vector element -FALSE,vcombine_f16,"low: float16x4_t, high: float16x4_t",float16x8_t,Join two smaller vectors into a single larger vector -TRUE,vcombine_f32,"low: float32x2_t, high: float32x2_t",float32x4_t,Join two smaller vectors into a single larger vector -TRUE,vcombine_f64,"low: float64x1_t, high: float64x1_t",float64x2_t,Join two smaller vectors into a single larger vector -TRUE,vcombine_p16,"low: poly16x4_t, high: poly16x4_t",poly16x8_t,Join two smaller vectors into a single larger vector -TRUE,vcombine_p64,"low: poly64x1_t, high: poly64x1_t",poly64x2_t,Join two smaller vectors into a single larger vector -TRUE,vcombine_p8,"low: poly8x8_t, high: poly8x8_t",poly8x16_t,Join two smaller vectors into a single larger vector -TRUE,vcombine_s16,"low: int16x4_t, high: int16x4_t",int16x8_t,Join two smaller vectors into a single larger vector -TRUE,vcombine_s32,"low: int32x2_t, high: int32x2_t",int32x4_t,Join two smaller vectors into a single larger vector -TRUE,vcombine_s64,"low: int64x1_t, high: int64x1_t",int64x2_t,Join two smaller vectors into a single larger vector -TRUE,vcombine_s8,"low: int8x8_t, high: int8x8_t",int8x16_t,Join two smaller vectors into a single larger vector -TRUE,vcombine_u16,"low: uint16x4_t, high: uint16x4_t",uint16x8_t,Join two smaller vectors into a single larger vector -TRUE,vcombine_u32,"low: uint32x2_t, high: uint32x2_t",uint32x4_t,Join two smaller vectors into a single larger vector -TRUE,vcombine_u64,"low: uint64x1_t, high: uint64x1_t",uint64x2_t,Join two smaller vectors into a single larger vector -TRUE,vcombine_u8,"low: uint8x8_t, high: uint8x8_t",uint8x16_t,Join two smaller vectors into a single larger vector -FALSE,vcopy_lane_bf16,"a: bfloat16x4_t, lane1: const int, b: bfloat16x4_t, lane2: const int",bfloat16x4_t,Insert vector element from another vector element -FALSE,vcopy_lane_f32,"a: float32x2_t, lane1: const int, b: float32x2_t, lane2: const int",float32x2_t,Insert vector element from another vector element -FALSE,vcopy_lane_f64,"a: float64x1_t, lane1: const int, b: float64x1_t, lane2: const int",float64x1_t,Duplicate vector element to vector or scalar -FALSE,vcopy_lane_p16,"a: poly16x4_t, lane1: const int, b: poly16x4_t, lane2: const int",poly16x4_t,Insert vector element from another vector element -FALSE,vcopy_lane_p64,"a: poly64x1_t, lane1: const int, b: poly64x1_t, lane2: const int",poly64x1_t,Duplicate vector element to vector or scalar -FALSE,vcopy_lane_p8,"a: poly8x8_t, lane1: const int, b: poly8x8_t, lane2: const int",poly8x8_t,Insert vector element from another vector element -FALSE,vcopy_lane_s16,"a: int16x4_t, lane1: const int, b: int16x4_t, lane2: const int",int16x4_t,Insert vector element from another vector element -FALSE,vcopy_lane_s32,"a: int32x2_t, lane1: const int, b: int32x2_t, lane2: const int",int32x2_t,Insert vector element from another vector element -FALSE,vcopy_lane_s64,"a: int64x1_t, lane1: const int, b: int64x1_t, lane2: const int",int64x1_t,Duplicate vector element to vector or scalar -FALSE,vcopy_lane_s8,"a: int8x8_t, lane1: const int, b: int8x8_t, lane2: const int",int8x8_t,Insert vector element from another vector element -FALSE,vcopy_lane_u16,"a: uint16x4_t, lane1: const int, b: uint16x4_t, lane2: const int",uint16x4_t,Insert vector element from another vector element -FALSE,vcopy_lane_u32,"a: uint32x2_t, lane1: const int, b: uint32x2_t, lane2: const int",uint32x2_t,Insert vector element from another vector element -FALSE,vcopy_lane_u64,"a: uint64x1_t, lane1: const int, b: uint64x1_t, lane2: const int",uint64x1_t,Duplicate vector element to vector or scalar -FALSE,vcopy_lane_u8,"a: uint8x8_t, lane1: const int, b: uint8x8_t, lane2: const int",uint8x8_t,Insert vector element from another vector element -FALSE,vcopy_laneq_bf16,"a: bfloat16x4_t, lane1: const int, b: bfloat16x8_t, lane2: const int",bfloat16x4_t,Insert vector element from another vector element -FALSE,vcopy_laneq_f32,"a: float32x2_t, lane1: const int, b: float32x4_t, lane2: const int",float32x2_t,Insert vector element from another vector element -FALSE,vcopy_laneq_f64,"a: float64x1_t, lane1: const int, b: float64x2_t, lane2: const int",float64x1_t,Duplicate vector element to vector or scalar -FALSE,vcopy_laneq_p16,"a: poly16x4_t, lane1: const int, b: poly16x8_t, lane2: const int",poly16x4_t,Insert vector element from another vector element -FALSE,vcopy_laneq_p64,"a: poly64x1_t, lane1: const int, b: poly64x2_t, lane2: const int",poly64x1_t,Duplicate vector element to vector or scalar -FALSE,vcopy_laneq_p8,"a: poly8x8_t, lane1: const int, b: poly8x16_t, lane2: const int",poly8x8_t,Insert vector element from another vector element -FALSE,vcopy_laneq_s16,"a: int16x4_t, lane1: const int, b: int16x8_t, lane2: const int",int16x4_t,Insert vector element from another vector element -FALSE,vcopy_laneq_s32,"a: int32x2_t, lane1: const int, b: int32x4_t, lane2: const int",int32x2_t,Insert vector element from another vector element -FALSE,vcopy_laneq_s64,"a: int64x1_t, lane1: const int, b: int64x2_t, lane2: const int",int64x1_t,Duplicate vector element to vector or scalar -FALSE,vcopy_laneq_s8,"a: int8x8_t, lane1: const int, b: int8x16_t, lane2: const int",int8x8_t,Insert vector element from another vector element -FALSE,vcopy_laneq_u16,"a: uint16x4_t, lane1: const int, b: uint16x8_t, lane2: const int",uint16x4_t,Insert vector element from another vector element -FALSE,vcopy_laneq_u32,"a: uint32x2_t, lane1: const int, b: uint32x4_t, lane2: const int",uint32x2_t,Insert vector element from another vector element -FALSE,vcopy_laneq_u64,"a: uint64x1_t, lane1: const int, b: uint64x2_t, lane2: const int",uint64x1_t,Duplicate vector element to vector or scalar -FALSE,vcopy_laneq_u8,"a: uint8x8_t, lane1: const int, b: uint8x16_t, lane2: const int",uint8x8_t,Insert vector element from another vector element -FALSE,vcopyq_lane_bf16,"a: bfloat16x8_t, lane1: const int, b: bfloat16x4_t, lane2: const int",bfloat16x8_t,Insert vector element from another vector element -FALSE,vcopyq_lane_f32,"a: float32x4_t, lane1: const int, b: float32x2_t, lane2: const int",float32x4_t,Insert vector element from another vector element -FALSE,vcopyq_lane_f64,"a: float64x2_t, lane1: const int, b: float64x1_t, lane2: const int",float64x2_t,Insert vector element from another vector element -FALSE,vcopyq_lane_p16,"a: poly16x8_t, lane1: const int, b: poly16x4_t, lane2: const int",poly16x8_t,Insert vector element from another vector element -FALSE,vcopyq_lane_p64,"a: poly64x2_t, lane1: const int, b: poly64x1_t, lane2: const int",poly64x2_t,Insert vector element from another vector element -FALSE,vcopyq_lane_p8,"a: poly8x16_t, lane1: const int, b: poly8x8_t, lane2: const int",poly8x16_t,Insert vector element from another vector element -FALSE,vcopyq_lane_s16,"a: int16x8_t, lane1: const int, b: int16x4_t, lane2: const int",int16x8_t,Insert vector element from another vector element -FALSE,vcopyq_lane_s32,"a: int32x4_t, lane1: const int, b: int32x2_t, lane2: const int",int32x4_t,Insert vector element from another vector element -FALSE,vcopyq_lane_s64,"a: int64x2_t, lane1: const int, b: int64x1_t, lane2: const int",int64x2_t,Insert vector element from another vector element -FALSE,vcopyq_lane_s8,"a: int8x16_t, lane1: const int, b: int8x8_t, lane2: const int",int8x16_t,Insert vector element from another vector element -FALSE,vcopyq_lane_u16,"a: uint16x8_t, lane1: const int, b: uint16x4_t, lane2: const int",uint16x8_t,Insert vector element from another vector element -FALSE,vcopyq_lane_u32,"a: uint32x4_t, lane1: const int, b: uint32x2_t, lane2: const int",uint32x4_t,Insert vector element from another vector element -FALSE,vcopyq_lane_u64,"a: uint64x2_t, lane1: const int, b: uint64x1_t, lane2: const int",uint64x2_t,Insert vector element from another vector element -FALSE,vcopyq_lane_u8,"a: uint8x16_t, lane1: const int, b: uint8x8_t, lane2: const int",uint8x16_t,Insert vector element from another vector element -FALSE,vcopyq_laneq_bf16,"a: bfloat16x8_t, lane1: const int, b: bfloat16x8_t, lane2: const int",bfloat16x8_t,Insert vector element from another vector element -FALSE,vcopyq_laneq_f32,"a: float32x4_t, lane1: const int, b: float32x4_t, lane2: const int",float32x4_t,Insert vector element from another vector element -FALSE,vcopyq_laneq_f64,"a: float64x2_t, lane1: const int, b: float64x2_t, lane2: const int",float64x2_t,Insert vector element from another vector element -FALSE,vcopyq_laneq_p16,"a: poly16x8_t, lane1: const int, b: poly16x8_t, lane2: const int",poly16x8_t,Insert vector element from another vector element -FALSE,vcopyq_laneq_p64,"a: poly64x2_t, lane1: const int, b: poly64x2_t, lane2: const int",poly64x2_t,Insert vector element from another vector element -FALSE,vcopyq_laneq_p8,"a: poly8x16_t, lane1: const int, b: poly8x16_t, lane2: const int",poly8x16_t,Insert vector element from another vector element -FALSE,vcopyq_laneq_s16,"a: int16x8_t, lane1: const int, b: int16x8_t, lane2: const int",int16x8_t,Insert vector element from another vector element -FALSE,vcopyq_laneq_s32,"a: int32x4_t, lane1: const int, b: int32x4_t, lane2: const int",int32x4_t,Insert vector element from another vector element -FALSE,vcopyq_laneq_s64,"a: int64x2_t, lane1: const int, b: int64x2_t, lane2: const int",int64x2_t,Insert vector element from another vector element -FALSE,vcopyq_laneq_s8,"a: int8x16_t, lane1: const int, b: int8x16_t, lane2: const int",int8x16_t,Insert vector element from another vector element -FALSE,vcopyq_laneq_u16,"a: uint16x8_t, lane1: const int, b: uint16x8_t, lane2: const int",uint16x8_t,Insert vector element from another vector element -FALSE,vcopyq_laneq_u32,"a: uint32x4_t, lane1: const int, b: uint32x4_t, lane2: const int",uint32x4_t,Insert vector element from another vector element -FALSE,vcopyq_laneq_u64,"a: uint64x2_t, lane1: const int, b: uint64x2_t, lane2: const int",uint64x2_t,Insert vector element from another vector element -FALSE,vcopyq_laneq_u8,"a: uint8x16_t, lane1: const int, b: uint8x16_t, lane2: const int",uint8x16_t,Insert vector element from another vector element -FALSE,vcreate_bf16,a: u64,bfloat16x4_t,Insert vector element from another vector element -FALSE,vcreate_f16,a: u64,float16x4_t,Insert vector element from another vector element -FALSE,vcreate_f32,a: u64,float32x2_t,Insert vector element from another vector element -FALSE,vcreate_f64,a: u64,float64x1_t,Insert vector element from another vector element -FALSE,vcreate_p16,a: u64,poly16x4_t,Insert vector element from another vector element -FALSE,vcreate_p64,a: u64,poly64x1_t,Insert vector element from another vector element -FALSE,vcreate_p8,a: u64,poly8x8_t,Insert vector element from another vector element -FALSE,vcreate_s16,a: u64,int16x4_t,Insert vector element from another vector element -FALSE,vcreate_s32,a: u64,int32x2_t,Insert vector element from another vector element -FALSE,vcreate_s64,a: u64,int64x1_t,Insert vector element from another vector element -FALSE,vcreate_s8,a: u64,int8x8_t,Insert vector element from another vector element -FALSE,vcreate_u16,a: u64,uint16x4_t,Insert vector element from another vector element -FALSE,vcreate_u32,a: u64,uint32x2_t,Insert vector element from another vector element -FALSE,vcreate_u64,a: u64,uint64x1_t,Insert vector element from another vector element -FALSE,vcreate_u8,a: u64,uint8x8_t,Insert vector element from another vector element -FALSE,vcvt_f16_f32,a: float32x4_t,float16x4_t,Floating-point convert to lower precision narrow -FALSE,vcvt_f16_s16,a: int16x4_t,float16x4_t,Signed fixed-point convert to floating-point -FALSE,vcvt_f16_u16,a: uint16x4_t,float16x4_t,Unsigned fixed-point convert to floating-point -FALSE,vcvt_f32_bf16,a: bfloat16x4_t,float32x4_t,Shift left long -FALSE,vcvt_f32_f16,a: float16x4_t,float32x4_t,Floating-point convert to higher precision long -TRUE,vcvt_f32_f64,a: float64x2_t,float32x2_t,Floating-point convert to lower precision narrow -FALSE,vcvt_f32_s32,a: int32x2_t,float32x2_t,Signed fixed-point convert to floating-point -FALSE,vcvt_f32_u32,a: uint32x2_t,float32x2_t,Unsigned fixed-point convert to floating-point -TRUE,vcvt_f64_f32,a: float32x2_t,float64x2_t,Floating-point convert to higher precision long -FALSE,vcvt_f64_s64,a: int64x1_t,float64x1_t,Signed fixed-point convert to floating-point -FALSE,vcvt_f64_u64,a: uint64x1_t,float64x1_t,Unsigned fixed-point convert to floating-point -FALSE,vcvt_high_bf16_f32,"inactive: bfloat16x4_t, a: float32x4_t",bfloat16x4_t,Floating-point convert from single-precision to bfloat16 format -FALSE,vcvt_high_f16_f32,"r: float16x4_t, a: float32x4_t",float16x8_t,Floating-point convert to lower precision narrow -FALSE,vcvt_high_f32_f16,a: float16x8_t,float32x4_t,Floating-point convert to higher precision long -TRUE,vcvt_high_f32_f64,"r: float32x2_t, a: float64x2_t",float32x4_t,Floating-point convert to lower precision narrow -TRUE,vcvt_high_f64_f32,a: float32x4_t,float64x2_t,Floating-point convert to higher precision long -FALSE,vcvt_low_bf16_f32,a: float32x4_t,bfloat16x4_t,Floating-point convert from single-precision to bfloat16 format -FALSE,vcvt_n_f16_s16,"a: int16x4_t, n: const int",float16x4_t,Signed fixed-point convert to floating-point -FALSE,vcvt_n_f16_u16,"a: uint16x4_t, n: const int",float16x4_t,Unsigned fixed-point convert to floating-point -FALSE,vcvt_n_f32_s32,"a: int32x2_t, n: const int",float32x2_t,Signed fixed-point convert to floating-point -FALSE,vcvt_n_f32_u32,"a: uint32x2_t, n: const int",float32x2_t,Unsigned fixed-point convert to floating-point -FALSE,vcvt_n_f64_s64,"a: int64x1_t, n: const int",float64x1_t,Signed fixed-point convert to floating-point -FALSE,vcvt_n_f64_u64,"a: uint64x1_t, n: const int",float64x1_t,Unsigned fixed-point convert to floating-point -FALSE,vcvt_n_s16_f16,"a: float16x4_t, n: const int",int16x4_t,"Floating-point convert to signed fixed-point, rounding toward zero" -FALSE,vcvt_n_s32_f32,"a: float32x2_t, n: const int",int32x2_t,"Floating-point convert to signed fixed-point, rounding toward zero" -FALSE,vcvt_n_s64_f64,"a: float64x1_t, n: const int",int64x1_t,"Floating-point convert to signed fixed-point, rounding toward zero" -FALSE,vcvt_n_u16_f16,"a: float16x4_t, n: const int",uint16x4_t,"Floating-point convert to unsigned fixed-point, rounding toward zero" -FALSE,vcvt_n_u32_f32,"a: float32x2_t, n: const int",uint32x2_t,"Floating-point convert to unsigned fixed-point, rounding toward zero" -FALSE,vcvt_n_u64_f64,"a: float64x1_t, n: const int",uint64x1_t,"Floating-point convert to unsigned fixed-point, rounding toward zero" -FALSE,vcvt_s16_f16,a: float16x4_t,int16x4_t,"Floating-point convert to signed fixed-point, rounding toward zero" -TRUE,vcvt_s32_f32,a: float32x2_t,int32x2_t,"Floating-point convert to signed fixed-point, rounding toward zero" -TRUE,vcvt_s64_f64,a: float64x1_t,int64x1_t,"Floating-point convert to signed fixed-point, rounding toward zero" -FALSE,vcvt_u16_f16,a: float16x4_t,uint16x4_t,"Floating-point convert to signed fixed-point, rounding toward zero" -TRUE,vcvt_u32_f32,a: float32x2_t,uint32x2_t,"Floating-point convert to unsigned fixed-point, rounding toward zero" -TRUE,vcvt_u64_f64,a: float64x1_t,uint64x1_t,"Floating-point convert to unsigned fixed-point, rounding toward zero" -FALSE,vcvta_s16_f16,a: float16x4_t,int16x4_t,"Floating-point convert to signed integer, rounding to nearest with ties to away" -TRUE,vcvta_s32_f32,a: float32x2_t,int32x2_t,"Floating-point convert to signed integer, rounding to nearest with ties to away" -TRUE,vcvta_s64_f64,a: float64x1_t,int64x1_t,"Floating-point convert to signed integer, rounding to nearest with ties to away" -FALSE,vcvta_u16_f16,a: float16x4_t,uint16x4_t,"Floating-point convert to unsigned integer, rounding to nearest with ties to away" -TRUE,vcvta_u32_f32,a: float32x2_t,uint32x2_t,"Floating-point convert to unsigned integer, rounding to nearest with ties to away" -TRUE,vcvta_u64_f64,a: float64x1_t,uint64x1_t,"Floating-point convert to unsigned integer, rounding to nearest with ties to away" -FALSE,vcvtad_s64_f64,a: float64_t,i64,"Floating-point convert to signed integer, rounding to nearest with ties to away" -FALSE,vcvtad_u64_f64,a: float64_t,u64,"Floating-point convert to unsigned integer, rounding to nearest with ties to away" -FALSE,vcvtah_f32_bf16,a: bfloat16_t,f32,Shift left -FALSE,vcvtah_s16_f16,a: float16_t,i16,"Floating-point convert to signed integer, rounding to nearest with ties to away" -FALSE,vcvtah_s32_f16,a: float16_t,i32,"Floating-point convert to signed integer, rounding to nearest with ties to away" -FALSE,vcvtah_s64_f16,a: float16_t,i64,"Floating-point convert to signed integer, rounding to nearest with ties to away" -FALSE,vcvtah_u16_f16,a: float16_t,u16,"Floating-point convert to unsigned integer, rounding to nearest with ties to away" -FALSE,vcvtah_u32_f16,a: float16_t,u32,"Floating-point convert to unsigned integer, rounding to nearest with ties to away" -FALSE,vcvtah_u64_f16,a: float16_t,u64,"Floating-point convert to unsigned integer, rounding to nearest with ties to away" -FALSE,vcvtaq_s16_f16,a: float16x8_t,int16x8_t,"Floating-point convert to signed integer, rounding to nearest with ties to away" -TRUE,vcvtaq_s32_f32,a: float32x4_t,int32x4_t,"Floating-point convert to signed integer, rounding to nearest with ties to away" -TRUE,vcvtaq_s64_f64,a: float64x2_t,int64x2_t,"Floating-point convert to signed integer, rounding to nearest with ties to away" -FALSE,vcvtaq_u16_f16,a: float16x8_t,uint16x8_t,"Floating-point convert to unsigned integer, rounding to nearest with ties to away" -TRUE,vcvtaq_u32_f32,a: float32x4_t,uint32x4_t,"Floating-point convert to unsigned integer, rounding to nearest with ties to away" -TRUE,vcvtaq_u64_f64,a: float64x2_t,uint64x2_t,"Floating-point convert to unsigned integer, rounding to nearest with ties to away" -FALSE,vcvtas_s32_f32,a: f32,i32,"Floating-point convert to signed integer, rounding to nearest with ties to away" -FALSE,vcvtas_u32_f32,a: f32,u32,"Floating-point convert to unsigned integer, rounding to nearest with ties to away" -FALSE,vcvtd_f64_s64,a: i64,float64_t,Signed fixed-point convert to floating-point -FALSE,vcvtd_f64_u64,a: u64,float64_t,Unsigned fixed-point convert to floating-point -FALSE,vcvtd_n_f64_s64,"a: i64, n: const int",float64_t,Signed fixed-point convert to floating-point -FALSE,vcvtd_n_f64_u64,"a: u64, n: const int",float64_t,Unsigned fixed-point convert to floating-point -FALSE,vcvtd_n_s64_f64,"a: float64_t, n: const int",i64,"Floating-point convert to signed fixed-point, rounding toward zero" -FALSE,vcvtd_n_u64_f64,"a: float64_t, n: const int",u64,"Floating-point convert to unsigned fixed-point, rounding toward zero" -FALSE,vcvtd_s64_f64,a: float64_t,i64,"Floating-point convert to signed fixed-point, rounding toward zero" -FALSE,vcvtd_u64_f64,a: float64_t,u64,"Floating-point convert to unsigned fixed-point, rounding toward zero" -FALSE,vcvth_bf16_f32,a: f32,bfloat16_t,Floating-point convert from single-precision to bfloat16 format -FALSE,vcvth_f16_s16,a: i16,float16_t,Signed fixed-point convert to floating-point -FALSE,vcvth_f16_s32,a: i32,float16_t,Signed fixed-point convert to floating-point -FALSE,vcvth_f16_s64,a: i64,float16_t,Signed fixed-point convert to floating-point -FALSE,vcvth_f16_u16,a: u16,float16_t,Unsigned fixed-point convert to floating-point -FALSE,vcvth_f16_u32,a: u32,float16_t,Unsigned fixed-point convert to floating-point -FALSE,vcvth_f16_u64,a: u64,float16_t,Unsigned fixed-point convert to floating-point -FALSE,vcvth_n_f16_s16,"a: i16, n: const int",float16_t,Signed fixed-point convert to floating-point -FALSE,vcvth_n_f16_s32,"a: i32, n: const int",float16_t,Signed fixed-point convert to floating-point -FALSE,vcvth_n_f16_s64,"a: i64, n: const int",float16_t,Signed fixed-point convert to floating-point -FALSE,vcvth_n_f16_u16,"a: u16, n: const int",float16_t,Unsigned fixed-point convert to floating-point -FALSE,vcvth_n_f16_u32,"a: u32, n: const int",float16_t,Unsigned fixed-point convert to floating-point -FALSE,vcvth_n_f16_u64,"a: u64, n: const int",float16_t,Unsigned fixed-point convert to floating-point -FALSE,vcvth_n_s16_f16,"a: float16_t, n: const int",i16,"Floating-point convert to signed fixed-point, rounding toward zero" -FALSE,vcvth_n_s32_f16,"a: float16_t, n: const int",i32,"Floating-point convert to signed fixed-point, rounding toward zero" -FALSE,vcvth_n_s64_f16,"a: float16_t, n: const int",i64,"Floating-point convert to signed fixed-point, rounding toward zero" -FALSE,vcvth_n_u16_f16,"a: float16_t, n: const int",u16,"Floating-point convert to unsigned fixed-point, rounding toward zero" -FALSE,vcvth_n_u32_f16,"a: float16_t, n: const int",u32,"Floating-point convert to unsigned fixed-point, rounding toward zero" -FALSE,vcvth_n_u64_f16,"a: float16_t, n: const int",u64,"Floating-point convert to unsigned fixed-point, rounding toward zero" -FALSE,vcvth_s16_f16,a: float16_t,i16,"Floating-point convert to signed fixed-point, rounding toward zero" -FALSE,vcvth_s32_f16,a: float16_t,i32,"Floating-point convert to signed fixed-point, rounding toward zero" -FALSE,vcvth_s64_f16,a: float16_t,i64,"Floating-point convert to signed fixed-point, rounding toward zero" -FALSE,vcvth_u16_f16,a: float16_t,u16,"Floating-point convert to unsigned fixed-point, rounding toward zero" -FALSE,vcvth_u32_f16,a: float16_t,u32,"Floating-point convert to unsigned fixed-point, rounding toward zero" -FALSE,vcvth_u64_f16,a: float16_t,u64,"Floating-point convert to unsigned fixed-point, rounding toward zero" -FALSE,vcvtm_s16_f16,a: float16x4_t,int16x4_t,"Floating-point convert to signed integer, rounding toward minus infinity" -TRUE,vcvtm_s32_f32,a: float32x2_t,int32x2_t,"Floating-point convert to signed integer, rounding toward minus infinity" -TRUE,vcvtm_s64_f64,a: float64x1_t,int64x1_t,"Floating-point convert to signed integer, rounding toward minus infinity" -FALSE,vcvtm_u16_f16,a: float16x4_t,uint16x4_t,"Floating-point convert to unsigned integer, rounding toward minus infinity" -TRUE,vcvtm_u32_f32,a: float32x2_t,uint32x2_t,"Floating-point convert to unsigned integer, rounding toward minus infinity" -TRUE,vcvtm_u64_f64,a: float64x1_t,uint64x1_t,"Floating-point convert to unsigned integer, rounding toward minus infinity" -FALSE,vcvtmd_s64_f64,a: float64_t,i64,"Floating-point convert to signed integer, rounding toward minus infinity" -FALSE,vcvtmd_u64_f64,a: float64_t,u64,"Floating-point convert to unsigned integer, rounding toward minus infinity" -FALSE,vcvtmh_s16_f16,a: float16_t,i16,"Floating-point convert to signed integer, rounding toward minus infinity" -FALSE,vcvtmh_s32_f16,a: float16_t,i32,"Floating-point convert to signed integer, rounding toward minus infinity" -FALSE,vcvtmh_s64_f16,a: float16_t,i64,"Floating-point convert to signed integer, rounding toward minus infinity" -FALSE,vcvtmh_u16_f16,a: float16_t,u16,"Floating-point convert to unsigned integer, rounding toward minus infinity" -FALSE,vcvtmh_u32_f16,a: float16_t,u32,"Floating-point convert to unsigned integer, rounding toward minus infinity" -FALSE,vcvtmh_u64_f16,a: float16_t,u64,"Floating-point convert to unsigned integer, rounding toward minus infinity" -FALSE,vcvtmq_s16_f16,a: float16x8_t,int16x8_t,"Floating-point convert to signed integer, rounding toward minus infinity" -TRUE,vcvtmq_s32_f32,a: float32x4_t,int32x4_t,"Floating-point convert to signed integer, rounding toward minus infinity" -TRUE,vcvtmq_s64_f64,a: float64x2_t,int64x2_t,"Floating-point convert to signed integer, rounding toward minus infinity" -FALSE,vcvtmq_u16_f16,a: float16x8_t,uint16x8_t,"Floating-point convert to unsigned integer, rounding toward minus infinity" -TRUE,vcvtmq_u32_f32,a: float32x4_t,uint32x4_t,"Floating-point convert to unsigned integer, rounding toward minus infinity" -TRUE,vcvtmq_u64_f64,a: float64x2_t,uint64x2_t,"Floating-point convert to unsigned integer, rounding toward minus infinity" -FALSE,vcvtms_s32_f32,a: f32,i32,"Floating-point convert to signed integer, rounding toward minus infinity" -FALSE,vcvtms_u32_f32,a: f32,u32,"Floating-point convert to unsigned integer, rounding toward minus infinity" -FALSE,vcvtn_s16_f16,a: float16x4_t,int16x4_t,"Floating-point convert to signed integer, rounding to nearest with ties to even" -TRUE,vcvtn_s32_f32,a: float32x2_t,int32x2_t,"Floating-point convert to signed integer, rounding to nearest with ties to even" -TRUE,vcvtn_s64_f64,a: float64x1_t,int64x1_t,"Floating-point convert to signed integer, rounding to nearest with ties to even" -FALSE,vcvtn_u16_f16,a: float16x4_t,uint16x4_t,"Floating-point convert to unsigned integer, rounding to nearest with ties to even" -TRUE,vcvtn_u32_f32,a: float32x2_t,uint32x2_t,"Floating-point convert to unsigned integer, rounding to nearest with ties to even" -TRUE,vcvtn_u64_f64,a: float64x1_t,uint64x1_t,"Floating-point convert to unsigned integer, rounding to nearest with ties to even" -FALSE,vcvtnd_s64_f64,a: float64_t,i64,"Floating-point convert to signed integer, rounding to nearest with ties to even" -FALSE,vcvtnd_u64_f64,a: float64_t,u64,"Floating-point convert to unsigned integer, rounding to nearest with ties to even" -FALSE,vcvtnh_s16_f16,a: float16_t,i16,"Floating-point convert to signed integer, rounding to nearest with ties to even" -FALSE,vcvtnh_s32_f16,a: float16_t,i32,"Floating-point convert to signed integer, rounding to nearest with ties to even" -FALSE,vcvtnh_s64_f16,a: float16_t,i64,"Floating-point convert to signed integer, rounding to nearest with ties to even" -FALSE,vcvtnh_u16_f16,a: float16_t,u16,"Floating-point convert to unsigned integer, rounding to nearest with ties to even" -FALSE,vcvtnh_u32_f16,a: float16_t,u32,"Floating-point convert to unsigned integer, rounding to nearest with ties to even" -FALSE,vcvtnh_u64_f16,a: float16_t,u64,"Floating-point convert to unsigned integer, rounding to nearest with ties to even" -FALSE,vcvtnq_s16_f16,a: float16x8_t,int16x8_t,"Floating-point convert to signed integer, rounding to nearest with ties to even" -TRUE,vcvtnq_s32_f32,a: float32x4_t,int32x4_t,"Floating-point convert to signed integer, rounding to nearest with ties to even" -TRUE,vcvtnq_s64_f64,a: float64x2_t,int64x2_t,"Floating-point convert to signed integer, rounding to nearest with ties to even" -FALSE,vcvtnq_u16_f16,a: float16x8_t,uint16x8_t,"Floating-point convert to unsigned integer, rounding to nearest with ties to even" -TRUE,vcvtnq_u32_f32,a: float32x4_t,uint32x4_t,"Floating-point convert to unsigned integer, rounding to nearest with ties to even" -TRUE,vcvtnq_u64_f64,a: float64x2_t,uint64x2_t,"Floating-point convert to unsigned integer, rounding to nearest with ties to even" -FALSE,vcvtns_s32_f32,a: f32,i32,"Floating-point convert to signed integer, rounding to nearest with ties to even" -FALSE,vcvtns_u32_f32,a: f32,u32,"Floating-point convert to unsigned integer, rounding to nearest with ties to even" -FALSE,vcvtp_s16_f16,a: float16x4_t,int16x4_t,"Floating-point convert to signed integer, rounding toward plus infinity" -TRUE,vcvtp_s32_f32,a: float32x2_t,int32x2_t,"Floating-point convert to signed integer, rounding toward plus infinity" -TRUE,vcvtp_s64_f64,a: float64x1_t,int64x1_t,"Floating-point convert to signed integer, rounding toward plus infinity" -FALSE,vcvtp_u16_f16,a: float16x4_t,uint16x4_t,"Floating-point convert to unsigned integer, rounding toward plus infinity" -TRUE,vcvtp_u32_f32,a: float32x2_t,uint32x2_t,"Floating-point convert to unsigned integer, rounding toward plus infinity" -TRUE,vcvtp_u64_f64,a: float64x1_t,uint64x1_t,"Floating-point convert to unsigned integer, rounding toward plus infinity" -FALSE,vcvtpd_s64_f64,a: float64_t,i64,"Floating-point convert to signed integer, rounding toward plus infinity" -FALSE,vcvtpd_u64_f64,a: float64_t,u64,"Floating-point convert to unsigned integer, rounding toward plus infinity" -FALSE,vcvtph_s16_f16,a: float16_t,i16,"Floating-point convert to signed integer, rounding toward plus infinity" -FALSE,vcvtph_s32_f16,a: float16_t,i32,"Floating-point convert to signed integer, rounding toward plus infinity" -FALSE,vcvtph_s64_f16,a: float16_t,i64,"Floating-point convert to signed integer, rounding toward plus infinity" -FALSE,vcvtph_u16_f16,a: float16_t,u16,"Floating-point convert to unsigned integer, rounding toward plus infinity" -FALSE,vcvtph_u32_f16,a: float16_t,u32,"Floating-point convert to unsigned integer, rounding toward plus infinity" -FALSE,vcvtph_u64_f16,a: float16_t,u64,"Floating-point convert to unsigned integer, rounding toward plus infinity" -FALSE,vcvtpq_s16_f16,a: float16x8_t,int16x8_t,"Floating-point convert to signed integer, rounding toward plus infinity" -TRUE,vcvtpq_s32_f32,a: float32x4_t,int32x4_t,"Floating-point convert to signed integer, rounding toward plus infinity" -TRUE,vcvtpq_s64_f64,a: float64x2_t,int64x2_t,"Floating-point convert to signed integer, rounding toward plus infinity" -FALSE,vcvtpq_u16_f16,a: float16x8_t,uint16x8_t,"Floating-point convert to unsigned integer, rounding toward plus infinity" -TRUE,vcvtpq_u32_f32,a: float32x4_t,uint32x4_t,"Floating-point convert to unsigned integer, rounding toward plus infinity" -TRUE,vcvtpq_u64_f64,a: float64x2_t,uint64x2_t,"Floating-point convert to unsigned integer, rounding toward plus infinity" -FALSE,vcvtps_s32_f32,a: f32,i32,"Floating-point convert to signed integer, rounding toward plus infinity" -FALSE,vcvtps_u32_f32,a: f32,u32,"Floating-point convert to unsigned integer, rounding toward plus infinity" -FALSE,vcvtq_f16_s16,a: int16x8_t,float16x8_t,Signed fixed-point convert to floating-point -FALSE,vcvtq_f16_u16,a: uint16x8_t,float16x8_t,Unsigned fixed-point convert to floating-point -FALSE,vcvtq_f32_s32,a: int32x4_t,float32x4_t,Signed fixed-point convert to floating-point -FALSE,vcvtq_f32_u32,a: uint32x4_t,float32x4_t,Unsigned fixed-point convert to floating-point -FALSE,vcvtq_f64_s64,a: int64x2_t,float64x2_t,Signed fixed-point convert to floating-point -FALSE,vcvtq_f64_u64,a: uint64x2_t,float64x2_t,Unsigned fixed-point convert to floating-point -FALSE,vcvtq_high_bf16_f32,"inactive: bfloat16x8_t, a: float32x4_t",bfloat16x8_t,Floating-point convert from single-precision to bfloat16 format -FALSE,vcvtq_high_f32_bf16,a: bfloat16x8_t,float32x4_t,Shift left long -FALSE,vcvtq_low_bf16_f32,a: float32x4_t,bfloat16x8_t,Floating-point convert from single-precision to bfloat16 format -FALSE,vcvtq_low_f32_bf16,a: bfloat16x8_t,float32x4_t,Shift left long -FALSE,vcvtq_n_f16_s16,"a: int16x8_t, n: const int",float16x8_t,Signed fixed-point convert to floating-point -FALSE,vcvtq_n_f16_u16,"a: uint16x8_t, n: const int",float16x8_t,Unsigned fixed-point convert to floating-point -FALSE,vcvtq_n_f32_s32,"a: int32x4_t, n: const int",float32x4_t,Signed fixed-point convert to floating-point -FALSE,vcvtq_n_f32_u32,"a: uint32x4_t, n: const int",float32x4_t,Unsigned fixed-point convert to floating-point -FALSE,vcvtq_n_f64_s64,"a: int64x2_t, n: const int",float64x2_t,Signed fixed-point convert to floating-point -FALSE,vcvtq_n_f64_u64,"a: uint64x2_t, n: const int",float64x2_t,Unsigned fixed-point convert to floating-point -FALSE,vcvtq_n_s16_f16,"a: float16x8_t, n: const int",int16x8_t,"Floating-point convert to signed fixed-point, rounding toward zero" -FALSE,vcvtq_n_s32_f32,"a: float32x4_t, n: const int",int32x4_t,"Floating-point convert to signed fixed-point, rounding toward zero" -FALSE,vcvtq_n_s64_f64,"a: float64x2_t, n: const int",int64x2_t,"Floating-point convert to signed fixed-point, rounding toward zero" -FALSE,vcvtq_n_u16_f16,"a: float16x8_t, n: const int",uint16x8_t,"Floating-point convert to unsigned fixed-point, rounding toward zero" -FALSE,vcvtq_n_u32_f32,"a: float32x4_t, n: const int",uint32x4_t,"Floating-point convert to unsigned fixed-point, rounding toward zero" -FALSE,vcvtq_n_u64_f64,"a: float64x2_t, n: const int",uint64x2_t,"Floating-point convert to unsigned fixed-point, rounding toward zero" -FALSE,vcvtq_s16_f16,a: float16x8_t,int16x8_t,"Floating-point convert to signed fixed-point, rounding toward zero" -TRUE,vcvtq_s32_f32,a: float32x4_t,int32x4_t,"Floating-point convert to signed fixed-point, rounding toward zero" -TRUE,vcvtq_s64_f64,a: float64x2_t,int64x2_t,"Floating-point convert to signed fixed-point, rounding toward zero" -FALSE,vcvtq_u16_f16,a: float16x8_t,uint16x8_t,"Floating-point convert to signed fixed-point, rounding toward zero" -TRUE,vcvtq_u32_f32,a: float32x4_t,uint32x4_t,"Floating-point convert to unsigned fixed-point, rounding toward zero" -TRUE,vcvtq_u64_f64,a: float64x2_t,uint64x2_t,"Floating-point convert to unsigned fixed-point, rounding toward zero" -FALSE,vcvts_f32_s32,a: i32,f32,Signed fixed-point convert to floating-point -FALSE,vcvts_f32_u32,a: u32,f32,Unsigned fixed-point convert to floating-point -FALSE,vcvts_n_f32_s32,"a: i32, n: const int",f32,Signed fixed-point convert to floating-point -FALSE,vcvts_n_f32_u32,"a: u32, n: const int",f32,Unsigned fixed-point convert to floating-point -FALSE,vcvts_n_s32_f32,"a: f32, n: const int",i32,"Floating-point convert to signed fixed-point, rounding toward zero" -FALSE,vcvts_n_u32_f32,"a: f32, n: const int",u32,"Floating-point convert to unsigned fixed-point, rounding toward zero" -FALSE,vcvts_s32_f32,a: f32,i32,"Floating-point convert to signed fixed-point, rounding toward zero" -FALSE,vcvts_u32_f32,a: f32,u32,"Floating-point convert to unsigned fixed-point, rounding toward zero" -TRUE,vcvtx_f32_f64,a: float64x2_t,float32x2_t,"Floating-point convert to lower precision narrow, rounding to odd" -TRUE,vcvtx_high_f32_f64,"r: float32x2_t, a: float64x2_t",float32x4_t,"Floating-point convert to lower precision narrow, rounding to odd" -FALSE,vcvtxd_f32_f64,a: float64_t,f32,"Floating-point convert to lower precision narrow, rounding to odd" -FALSE,vdiv_f16,"a: float16x4_t, b: float16x4_t",float16x4_t,Floating-point divide -TRUE,vdiv_f32,"a: float32x2_t, b: float32x2_t",float32x2_t,Floating-point divide -TRUE,vdiv_f64,"a: float64x1_t, b: float64x1_t",float64x1_t,Floating-point divide -FALSE,vdivh_f16,"a: float16_t, b: float16_t",float16_t,Floating-point divide -FALSE,vdivq_f16,"a: float16x8_t, b: float16x8_t",float16x8_t,Floating-point divide -TRUE,vdivq_f32,"a: float32x4_t, b: float32x4_t",float32x4_t,Floating-point divide -TRUE,vdivq_f64,"a: float64x2_t, b: float64x2_t",float64x2_t,Floating-point divide -FALSE,vdot_lane_s32,"r: int32x2_t, a: int8x8_t, b: int8x8_t, lane: const int",int32x2_t,Dot product signed arithmetic -FALSE,vdot_lane_u32,"r: uint32x2_t, a: uint8x8_t, b: uint8x8_t, lane: const int",uint32x2_t,Dot product unsigned arithmetic -FALSE,vdot_laneq_s32,"r: int32x2_t, a: int8x8_t, b: int8x16_t, lane: const int",int32x2_t,Dot product signed arithmetic -FALSE,vdot_laneq_u32,"r: uint32x2_t, a: uint8x8_t, b: uint8x16_t, lane: const int",uint32x2_t,Dot product unsigned arithmetic -FALSE,vdot_s32,"r: int32x2_t, a: int8x8_t, b: int8x8_t",int32x2_t,Dot product signed arithmetic -FALSE,vdot_u32,"r: uint32x2_t, a: uint8x8_t, b: uint8x8_t",uint32x2_t,Dot product unsigned arithmetic -FALSE,vdotq_lane_s32,"r: int32x4_t, a: int8x16_t, b: int8x8_t, lane: const int",int32x4_t,Dot product signed arithmetic -FALSE,vdotq_lane_u32,"r: uint32x4_t, a: uint8x16_t, b: uint8x8_t, lane: const int",uint32x4_t,Dot product unsigned arithmetic -FALSE,vdotq_laneq_s32,"r: int32x4_t, a: int8x16_t, b: int8x16_t, lane: const int",int32x4_t,Dot product signed arithmetic -FALSE,vdotq_laneq_u32,"r: uint32x4_t, a: uint8x16_t, b: uint8x16_t, lane: const int",uint32x4_t,Dot product unsigned arithmetic -FALSE,vdotq_s32,"r: int32x4_t, a: int8x16_t, b: int8x16_t",int32x4_t,Dot product signed arithmetic -FALSE,vdotq_u32,"r: uint32x4_t, a: uint8x16_t, b: uint8x16_t",uint32x4_t,Dot product unsigned arithmetic -FALSE,vdup_lane_bf16,"vec: bfloat16x4_t, lane: const int",bfloat16x4_t,Duplicate vector element to vector or scalar -FALSE,vdup_lane_f16,"vec: float16x4_t, lane: const int",float16x4_t,Set all vector lanes to the same value -TRUE,vdup_lane_f32,"vec: float32x2_t, lane: const int",float32x2_t,Set all vector lanes to the same value -TRUE,vdup_lane_f64,"vec: float64x1_t, lane: const int",float64x1_t,Set all vector lanes to the same value -TRUE,vdup_lane_p16,"vec: poly16x4_t, lane: const int",poly16x4_t,Set all vector lanes to the same value -TRUE,vdup_lane_p64,"vec: poly64x1_t, lane: const int",poly64x1_t,Set all vector lanes to the same value -TRUE,vdup_lane_p8,"vec: poly8x8_t, lane: const int",poly8x8_t,Set all vector lanes to the same value -TRUE,vdup_lane_s16,"vec: int16x4_t, lane: const int",int16x4_t,Set all vector lanes to the same value -TRUE,vdup_lane_s32,"vec: int32x2_t, lane: const int",int32x2_t,Set all vector lanes to the same value -TRUE,vdup_lane_s64,"vec: int64x1_t, lane: const int",int64x1_t,Set all vector lanes to the same value -TRUE,vdup_lane_s8,"vec: int8x8_t, lane: const int",int8x8_t,Set all vector lanes to the same value -TRUE,vdup_lane_u16,"vec: uint16x4_t, lane: const int",uint16x4_t,Set all vector lanes to the same value -TRUE,vdup_lane_u32,"vec: uint32x2_t, lane: const int",uint32x2_t,Set all vector lanes to the same value -TRUE,vdup_lane_u64,"vec: uint64x1_t, lane: const int",uint64x1_t,Set all vector lanes to the same value -TRUE,vdup_lane_u8,"vec: uint8x8_t, lane: const int",uint8x8_t,Set all vector lanes to the same value -FALSE,vdup_laneq_bf16,"vec: bfloat16x8_t, lane: const int",bfloat16x4_t,Duplicate vector element to vector or scalar -FALSE,vdup_laneq_f16,"vec: float16x8_t, lane: const int",float16x4_t,Set all vector lanes to the same value -TRUE,vdup_laneq_f32,"vec: float32x4_t, lane: const int",float32x2_t,Set all vector lanes to the same value -TRUE,vdup_laneq_f64,"vec: float64x2_t, lane: const int",float64x1_t,Set all vector lanes to the same value -TRUE,vdup_laneq_p16,"vec: poly16x8_t, lane: const int",poly16x4_t,Set all vector lanes to the same value -TRUE,vdup_laneq_p64,"vec: poly64x2_t, lane: const int",poly64x1_t,Set all vector lanes to the same value -TRUE,vdup_laneq_p8,"vec: poly8x16_t, lane: const int",poly8x8_t,Set all vector lanes to the same value -TRUE,vdup_laneq_s16,"vec: int16x8_t, lane: const int",int16x4_t,Set all vector lanes to the same value -TRUE,vdup_laneq_s32,"vec: int32x4_t, lane: const int",int32x2_t,Set all vector lanes to the same value -TRUE,vdup_laneq_s64,"vec: int64x2_t, lane: const int",int64x1_t,Set all vector lanes to the same value -TRUE,vdup_laneq_s8,"vec: int8x16_t, lane: const int",int8x8_t,Set all vector lanes to the same value -TRUE,vdup_laneq_u16,"vec: uint16x8_t, lane: const int",uint16x4_t,Set all vector lanes to the same value -TRUE,vdup_laneq_u32,"vec: uint32x4_t, lane: const int",uint32x2_t,Set all vector lanes to the same value -TRUE,vdup_laneq_u64,"vec: uint64x2_t, lane: const int",uint64x1_t,Set all vector lanes to the same value -TRUE,vdup_laneq_u8,"vec: uint8x16_t, lane: const int",uint8x8_t,Set all vector lanes to the same value -FALSE,vdup_n_bf16,value: bfloat16_t,bfloat16x4_t,Duplicate vector element to vector or scalar -FALSE,vdup_n_f16,value: float16_t,float16x4_t,Duplicate vector element to vector or scalar -TRUE,vdup_n_f32,value: f32,float32x2_t,Duplicate vector element to vector or scalar -TRUE,vdup_n_f64,value: float64_t,float64x1_t,Insert vector element from another vector element -TRUE,vdup_n_p16,value: poly16_t,poly16x4_t,Duplicate vector element to vector or scalar -TRUE,vdup_n_p64,value: poly64_t,poly64x1_t,Insert vector element from another vector element -TRUE,vdup_n_p8,value: poly8_t,poly8x8_t,Duplicate vector element to vector or scalar -TRUE,vdup_n_s16,value: i16,int16x4_t,Duplicate vector element to vector or scalar -TRUE,vdup_n_s32,value: i32,int32x2_t,Duplicate vector element to vector or scalar -TRUE,vdup_n_s64,value: i64,int64x1_t,Insert vector element from another vector element -TRUE,vdup_n_s8,value: i8,int8x8_t,Duplicate vector element to vector or scalar -TRUE,vdup_n_u16,value: u16,uint16x4_t,Duplicate vector element to vector or scalar -TRUE,vdup_n_u32,value: u32,uint32x2_t,Duplicate vector element to vector or scalar -TRUE,vdup_n_u64,value: u64,uint64x1_t,Insert vector element from another vector element -TRUE,vdup_n_u8,value: u8,uint8x8_t,Duplicate vector element to vector or scalar -TRUE,vdupb_lane_p8,"vec: poly8x8_t, lane: const int",poly8_t,Set all vector lanes to the same value -TRUE,vdupb_lane_s8,"vec: int8x8_t, lane: const int",i8,Set all vector lanes to the same value -TRUE,vdupb_lane_u8,"vec: uint8x8_t, lane: const int",u8,Set all vector lanes to the same value -TRUE,vdupb_laneq_p8,"vec: poly8x16_t, lane: const int",poly8_t,Set all vector lanes to the same value -TRUE,vdupb_laneq_s8,"vec: int8x16_t, lane: const int",i8,Set all vector lanes to the same value -TRUE,vdupb_laneq_u8,"vec: uint8x16_t, lane: const int",u8,Set all vector lanes to the same value -TRUE,vdupd_lane_f64,"vec: float64x1_t, lane: const int",float64_t,Set all vector lanes to the same value -TRUE,vdupd_lane_s64,"vec: int64x1_t, lane: const int",i64,Set all vector lanes to the same value -TRUE,vdupd_lane_u64,"vec: uint64x1_t, lane: const int",u64,Set all vector lanes to the same value -TRUE,vdupd_laneq_f64,"vec: float64x2_t, lane: const int",float64_t,Set all vector lanes to the same value -TRUE,vdupd_laneq_s64,"vec: int64x2_t, lane: const int",i64,Set all vector lanes to the same value -TRUE,vdupd_laneq_u64,"vec: uint64x2_t, lane: const int",u64,Set all vector lanes to the same value -FALSE,vduph_lane_bf16,"vec: bfloat16x4_t, lane: const int",bfloat16_t,Duplicate vector element to vector or scalar -FALSE,vduph_lane_f16,"vec: float16x4_t, lane: const int",float16_t,Set all vector lanes to the same value -TRUE,vduph_lane_p16,"vec: poly16x4_t, lane: const int",poly16_t,Set all vector lanes to the same value -TRUE,vduph_lane_s16,"vec: int16x4_t, lane: const int",i16,Set all vector lanes to the same value -TRUE,vduph_lane_u16,"vec: uint16x4_t, lane: const int",u16,Set all vector lanes to the same value -FALSE,vduph_laneq_bf16,"vec: bfloat16x8_t, lane: const int",bfloat16_t,Duplicate vector element to vector or scalar -FALSE,vduph_laneq_f16,"vec: float16x8_t, lane: const int",float16_t,Set all vector lanes to the same value -TRUE,vduph_laneq_p16,"vec: poly16x8_t, lane: const int",poly16_t,Set all vector lanes to the same value -TRUE,vduph_laneq_s16,"vec: int16x8_t, lane: const int",i16,Set all vector lanes to the same value -TRUE,vduph_laneq_u16,"vec: uint16x8_t, lane: const int",u16,Set all vector lanes to the same value -FALSE,vdupq_lane_bf16,"vec: bfloat16x4_t, lane: const int",bfloat16x8_t,Duplicate vector element to vector or scalar -FALSE,vdupq_lane_f16,"vec: float16x4_t, lane: const int",float16x8_t,Set all vector lanes to the same value -TRUE,vdupq_lane_f32,"vec: float32x2_t, lane: const int",float32x4_t,Set all vector lanes to the same value -TRUE,vdupq_lane_f64,"vec: float64x1_t, lane: const int",float64x2_t,Set all vector lanes to the same value -TRUE,vdupq_lane_p16,"vec: poly16x4_t, lane: const int",poly16x8_t,Set all vector lanes to the same value -TRUE,vdupq_lane_p64,"vec: poly64x1_t, lane: const int",poly64x2_t,Set all vector lanes to the same value -TRUE,vdupq_lane_p8,"vec: poly8x8_t, lane: const int",poly8x16_t,Set all vector lanes to the same value -TRUE,vdupq_lane_s16,"vec: int16x4_t, lane: const int",int16x8_t,Set all vector lanes to the same value -TRUE,vdupq_lane_s32,"vec: int32x2_t, lane: const int",int32x4_t,Set all vector lanes to the same value -TRUE,vdupq_lane_s64,"vec: int64x1_t, lane: const int",int64x2_t,Set all vector lanes to the same value -TRUE,vdupq_lane_s8,"vec: int8x8_t, lane: const int",int8x16_t,Set all vector lanes to the same value -TRUE,vdupq_lane_u16,"vec: uint16x4_t, lane: const int",uint16x8_t,Set all vector lanes to the same value -TRUE,vdupq_lane_u32,"vec: uint32x2_t, lane: const int",uint32x4_t,Set all vector lanes to the same value -TRUE,vdupq_lane_u64,"vec: uint64x1_t, lane: const int",uint64x2_t,Set all vector lanes to the same value -TRUE,vdupq_lane_u8,"vec: uint8x8_t, lane: const int",uint8x16_t,Set all vector lanes to the same value -FALSE,vdupq_laneq_bf16,"vec: bfloat16x8_t, lane: const int",bfloat16x8_t,Duplicate vector element to vector or scalar -FALSE,vdupq_laneq_f16,"vec: float16x8_t, lane: const int",float16x8_t,Set all vector lanes to the same value -TRUE,vdupq_laneq_f32,"vec: float32x4_t, lane: const int",float32x4_t,Set all vector lanes to the same value -TRUE,vdupq_laneq_f64,"vec: float64x2_t, lane: const int",float64x2_t,Set all vector lanes to the same value -TRUE,vdupq_laneq_p16,"vec: poly16x8_t, lane: const int",poly16x8_t,Set all vector lanes to the same value -TRUE,vdupq_laneq_p64,"vec: poly64x2_t, lane: const int",poly64x2_t,Set all vector lanes to the same value -TRUE,vdupq_laneq_p8,"vec: poly8x16_t, lane: const int",poly8x16_t,Set all vector lanes to the same value -TRUE,vdupq_laneq_s16,"vec: int16x8_t, lane: const int",int16x8_t,Set all vector lanes to the same value -TRUE,vdupq_laneq_s32,"vec: int32x4_t, lane: const int",int32x4_t,Set all vector lanes to the same value -TRUE,vdupq_laneq_s64,"vec: int64x2_t, lane: const int",int64x2_t,Set all vector lanes to the same value -TRUE,vdupq_laneq_s8,"vec: int8x16_t, lane: const int",int8x16_t,Set all vector lanes to the same value -TRUE,vdupq_laneq_u16,"vec: uint16x8_t, lane: const int",uint16x8_t,Set all vector lanes to the same value -TRUE,vdupq_laneq_u32,"vec: uint32x4_t, lane: const int",uint32x4_t,Set all vector lanes to the same value -TRUE,vdupq_laneq_u64,"vec: uint64x2_t, lane: const int",uint64x2_t,Set all vector lanes to the same value -TRUE,vdupq_laneq_u8,"vec: uint8x16_t, lane: const int",uint8x16_t,Set all vector lanes to the same value -FALSE,vdupq_n_bf16,value: bfloat16_t,bfloat16x8_t,Duplicate vector element to vector or scalar -FALSE,vdupq_n_f16,value: float16_t,float16x8_t,Duplicate vector element to vector or scalar -TRUE,vdupq_n_f32,value: f32,float32x4_t,Duplicate vector element to vector or scalar -TRUE,vdupq_n_f64,value: float64_t,float64x2_t,Duplicate vector element to vector or scalar -TRUE,vdupq_n_p16,value: poly16_t,poly16x8_t,Duplicate vector element to vector or scalar -TRUE,vdupq_n_p64,value: poly64_t,poly64x2_t,Duplicate vector element to vector or scalar -TRUE,vdupq_n_p8,value: poly8_t,poly8x16_t,Duplicate vector element to vector or scalar -TRUE,vdupq_n_s16,value: i16,int16x8_t,Duplicate vector element to vector or scalar -TRUE,vdupq_n_s32,value: i32,int32x4_t,Duplicate vector element to vector or scalar -TRUE,vdupq_n_s64,value: i64,int64x2_t,Duplicate vector element to vector or scalar -TRUE,vdupq_n_s8,value: i8,int8x16_t,Duplicate vector element to vector or scalar -TRUE,vdupq_n_u16,value: u16,uint16x8_t,Duplicate vector element to vector or scalar -TRUE,vdupq_n_u32,value: u32,uint32x4_t,Duplicate vector element to vector or scalar -TRUE,vdupq_n_u64,value: u64,uint64x2_t,Duplicate vector element to vector or scalar -TRUE,vdupq_n_u8,value: u8,uint8x16_t,Duplicate vector element to vector or scalar -TRUE,vdups_lane_f32,"vec: float32x2_t, lane: const int",f32,Set all vector lanes to the same value -TRUE,vdups_lane_s32,"vec: int32x2_t, lane: const int",i32,Set all vector lanes to the same value -TRUE,vdups_lane_u32,"vec: uint32x2_t, lane: const int",u32,Set all vector lanes to the same value -TRUE,vdups_laneq_f32,"vec: float32x4_t, lane: const int",f32,Set all vector lanes to the same value -TRUE,vdups_laneq_s32,"vec: int32x4_t, lane: const int",i32,Set all vector lanes to the same value -TRUE,vdups_laneq_u32,"vec: uint32x4_t, lane: const int",u32,Set all vector lanes to the same value -TRUE,veor_s16,"a: int16x4_t, b: int16x4_t",int16x4_t,Bitwise exclusive OR -TRUE,veor_s32,"a: int32x2_t, b: int32x2_t",int32x2_t,Bitwise exclusive OR -TRUE,veor_s64,"a: int64x1_t, b: int64x1_t",int64x1_t,Bitwise exclusive OR -TRUE,veor_s8,"a: int8x8_t, b: int8x8_t",int8x8_t,Bitwise exclusive OR -TRUE,veor_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4_t,Bitwise exclusive OR -TRUE,veor_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2_t,Bitwise exclusive OR -TRUE,veor_u64,"a: uint64x1_t, b: uint64x1_t",uint64x1_t,Bitwise exclusive OR -TRUE,veor_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,Bitwise exclusive OR -FALSE,veor3q_s16,"a: int16x8_t, b: int16x8_t, c: int16x8_t",int16x8_t,Three-way exclusive OR -FALSE,veor3q_s32,"a: int32x4_t, b: int32x4_t, c: int32x4_t",int32x4_t,Three-way exclusive OR -FALSE,veor3q_s64,"a: int64x2_t, b: int64x2_t, c: int64x2_t",int64x2_t,Three-way exclusive OR -FALSE,veor3q_s8,"a: int8x16_t, b: int8x16_t, c: int8x16_t",int8x16_t,Three-way exclusive OR -FALSE,veor3q_u16,"a: uint16x8_t, b: uint16x8_t, c: uint16x8_t",uint16x8_t,Three-way exclusive OR -FALSE,veor3q_u32,"a: uint32x4_t, b: uint32x4_t, c: uint32x4_t",uint32x4_t,Three-way exclusive OR -FALSE,veor3q_u64,"a: uint64x2_t, b: uint64x2_t, c: uint64x2_t",uint64x2_t,Three-way exclusive OR -FALSE,veor3q_u8,"a: uint8x16_t, b: uint8x16_t, c: uint8x16_t",uint8x16_t,Three-way exclusive OR -TRUE,veorq_s16,"a: int16x8_t, b: int16x8_t",int16x8_t,Bitwise exclusive OR -TRUE,veorq_s32,"a: int32x4_t, b: int32x4_t",int32x4_t,Bitwise exclusive OR -TRUE,veorq_s64,"a: int64x2_t, b: int64x2_t",int64x2_t,Bitwise exclusive OR -TRUE,veorq_s8,"a: int8x16_t, b: int8x16_t",int8x16_t,Bitwise exclusive OR -TRUE,veorq_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8_t,Bitwise exclusive OR -TRUE,veorq_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,Bitwise exclusive OR -TRUE,veorq_u64,"a: uint64x2_t, b: uint64x2_t",uint64x2_t,Bitwise exclusive OR -TRUE,veorq_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16_t,Bitwise exclusive OR -FALSE,vext_f16,"a: float16x4_t, b: float16x4_t, n: const int",float16x4_t,Extract vector from pair of vectors -TRUE,vext_f32,"a: float32x2_t, b: float32x2_t, n: const int",float32x2_t,Extract vector from pair of vectors -TRUE,vext_f64,"a: float64x1_t, b: float64x1_t, n: const int",float64x1_t,Extract vector from pair of vectors -TRUE,vext_p16,"a: poly16x4_t, b: poly16x4_t, n: const int",poly16x4_t,Extract vector from pair of vectors -TRUE,vext_p64,"a: poly64x1_t, b: poly64x1_t, n: const int",poly64x1_t,Extract vector from pair of vectors -TRUE,vext_p8,"a: poly8x8_t, b: poly8x8_t, n: const int",poly8x8_t,Extract vector from pair of vectors -TRUE,vext_s16,"a: int16x4_t, b: int16x4_t, n: const int",int16x4_t,Extract vector from pair of vectors -TRUE,vext_s32,"a: int32x2_t, b: int32x2_t, n: const int",int32x2_t,Extract vector from pair of vectors -TRUE,vext_s64,"a: int64x1_t, b: int64x1_t, n: const int",int64x1_t,Extract vector from pair of vectors -TRUE,vext_s8,"a: int8x8_t, b: int8x8_t, n: const int",int8x8_t,Extract vector from pair of vectors -TRUE,vext_u16,"a: uint16x4_t, b: uint16x4_t, n: const int",uint16x4_t,Extract vector from pair of vectors -TRUE,vext_u32,"a: uint32x2_t, b: uint32x2_t, n: const int",uint32x2_t,Extract vector from pair of vectors -TRUE,vext_u64,"a: uint64x1_t, b: uint64x1_t, n: const int",uint64x1_t,Extract vector from pair of vectors -TRUE,vext_u8,"a: uint8x8_t, b: uint8x8_t, n: const int",uint8x8_t,Extract vector from pair of vectors -FALSE,vextq_f16,"a: float16x8_t, b: float16x8_t, n: const int",float16x8_t,Extract vector from pair of vectors -TRUE,vextq_f32,"a: float32x4_t, b: float32x4_t, n: const int",float32x4_t,Extract vector from pair of vectors -TRUE,vextq_f64,"a: float64x2_t, b: float64x2_t, n: const int",float64x2_t,Extract vector from pair of vectors -TRUE,vextq_p16,"a: poly16x8_t, b: poly16x8_t, n: const int",poly16x8_t,Extract vector from pair of vectors -TRUE,vextq_p64,"a: poly64x2_t, b: poly64x2_t, n: const int",poly64x2_t,Extract vector from pair of vectors -TRUE,vextq_p8,"a: poly8x16_t, b: poly8x16_t, n: const int",poly8x16_t,Extract vector from pair of vectors -TRUE,vextq_s16,"a: int16x8_t, b: int16x8_t, n: const int",int16x8_t,Extract vector from pair of vectors -TRUE,vextq_s32,"a: int32x4_t, b: int32x4_t, n: const int",int32x4_t,Extract vector from pair of vectors -TRUE,vextq_s64,"a: int64x2_t, b: int64x2_t, n: const int",int64x2_t,Extract vector from pair of vectors -TRUE,vextq_s8,"a: int8x16_t, b: int8x16_t, n: const int",int8x16_t,Extract vector from pair of vectors -TRUE,vextq_u16,"a: uint16x8_t, b: uint16x8_t, n: const int",uint16x8_t,Extract vector from pair of vectors -TRUE,vextq_u32,"a: uint32x4_t, b: uint32x4_t, n: const int",uint32x4_t,Extract vector from pair of vectors -TRUE,vextq_u64,"a: uint64x2_t, b: uint64x2_t, n: const int",uint64x2_t,Extract vector from pair of vectors -TRUE,vextq_u8,"a: uint8x16_t, b: uint8x16_t, n: const int",uint8x16_t,Extract vector from pair of vectors -FALSE,vfma_f16,"a: float16x4_t, b: float16x4_t, c: float16x4_t",float16x4_t,Floating-point fused multiply-add to accumulator -TRUE,vfma_f32,"a: float32x2_t, b: float32x2_t, c: float32x2_t",float32x2_t,Floating-point fused multiply-add to accumulator -TRUE,vfma_f64,"a: float64x1_t, b: float64x1_t, c: float64x1_t",float64x1_t,Floating-point fused multiply-add -FALSE,vfma_lane_f16,"a: float16x4_t, b: float16x4_t, v: float16x4_t, lane: const int",float16x4_t,Floating-point fused multiply-add to accumulator -FALSE,vfma_lane_f32,"a: float32x2_t, b: float32x2_t, v: float32x2_t, lane: const int",float32x2_t,Floating-point fused multiply-add to accumulator -FALSE,vfma_lane_f64,"a: float64x1_t, b: float64x1_t, v: float64x1_t, lane: const int",float64x1_t,Floating-point fused multiply-add to accumulator -FALSE,vfma_laneq_f16,"a: float16x4_t, b: float16x4_t, v: float16x8_t, lane: const int",float16x4_t,Floating-point fused multiply-add to accumulator -FALSE,vfma_laneq_f32,"a: float32x2_t, b: float32x2_t, v: float32x4_t, lane: const int",float32x2_t,Floating-point fused multiply-add to accumulator -FALSE,vfma_laneq_f64,"a: float64x1_t, b: float64x1_t, v: float64x2_t, lane: const int",float64x1_t,Floating-point fused multiply-add to accumulator -FALSE,vfma_n_f16,"a: float16x4_t, b: float16x4_t, n: float16_t",float16x4_t,Floating-point fused multiply-add to accumulator -TRUE,vfma_n_f32,"a: float32x2_t, b: float32x2_t, n: f32",float32x2_t,Floating-point fused multiply-add to accumulator -TRUE,vfma_n_f64,"a: float64x1_t, b: float64x1_t, n: float64_t",float64x1_t,Floating-point fused multiply-add -FALSE,vfmad_lane_f64,"a: float64_t, b: float64_t, v: float64x1_t, lane: const int",float64_t,Floating-point fused multiply-add to accumulator -FALSE,vfmad_laneq_f64,"a: float64_t, b: float64_t, v: float64x2_t, lane: const int",float64_t,Floating-point fused multiply-add to accumulator -FALSE,vfmah_f16,"a: float16_t, b: float16_t, c: float16_t",float16_t,Floating-point fused multiply-add -FALSE,vfmah_lane_f16,"a: float16_t, b: float16_t, v: float16x4_t, lane: const int",float16_t,Floating-point fused multiply-add to accumulator -FALSE,vfmah_laneq_f16,"a: float16_t, b: float16_t, v: float16x8_t, lane: const int",float16_t,Floating-point fused multiply-add to accumulator -FALSE,vfmaq_f16,"a: float16x8_t, b: float16x8_t, c: float16x8_t",float16x8_t,Floating-point fused multiply-add to accumulator -TRUE,vfmaq_f32,"a: float32x4_t, b: float32x4_t, c: float32x4_t",float32x4_t,Floating-point fused multiply-add to accumulator -TRUE,vfmaq_f64,"a: float64x2_t, b: float64x2_t, c: float64x2_t",float64x2_t,Floating-point fused multiply-add to accumulator -FALSE,vfmaq_lane_f16,"a: float16x8_t, b: float16x8_t, v: float16x4_t, lane: const int",float16x8_t,Floating-point fused multiply-add to accumulator -FALSE,vfmaq_lane_f32,"a: float32x4_t, b: float32x4_t, v: float32x2_t, lane: const int",float32x4_t,Floating-point fused multiply-add to accumulator -FALSE,vfmaq_lane_f64,"a: float64x2_t, b: float64x2_t, v: float64x1_t, lane: const int",float64x2_t,Floating-point fused multiply-add to accumulator -FALSE,vfmaq_laneq_f16,"a: float16x8_t, b: float16x8_t, v: float16x8_t, lane: const int",float16x8_t,Floating-point fused multiply-add to accumulator -FALSE,vfmaq_laneq_f32,"a: float32x4_t, b: float32x4_t, v: float32x4_t, lane: const int",float32x4_t,Floating-point fused multiply-add to accumulator -FALSE,vfmaq_laneq_f64,"a: float64x2_t, b: float64x2_t, v: float64x2_t, lane: const int",float64x2_t,Floating-point fused multiply-add to accumulator -FALSE,vfmaq_n_f16,"a: float16x8_t, b: float16x8_t, n: float16_t",float16x8_t,Floating-point fused multiply-add to accumulator -TRUE,vfmaq_n_f32,"a: float32x4_t, b: float32x4_t, n: f32",float32x4_t,Floating-point fused multiply-add to accumulator -TRUE,vfmaq_n_f64,"a: float64x2_t, b: float64x2_t, n: float64_t",float64x2_t,Floating-point fused multiply-add to accumulator -FALSE,vfmas_lane_f32,"a: f32, b: f32, v: float32x2_t, lane: const int",f32,Floating-point fused multiply-add to accumulator -FALSE,vfmas_laneq_f32,"a: f32, b: f32, v: float32x4_t, lane: const int",f32,Floating-point fused multiply-add to accumulator -FALSE,vfmlal_high_f16,"r: float32x2_t, a: float16x4_t, b: float16x4_t",float32x2_t,Floating-point fused multiply-add long to accumulator -FALSE,vfmlal_lane_high_f16,"r: float32x2_t, a: float16x4_t, b: float16x4_t, lane: const int",float32x2_t,Floating-point fused multiply-add long to accumulator -FALSE,vfmlal_lane_low_f16,"r: float32x2_t, a: float16x4_t, b: float16x4_t, lane: const int",float32x2_t,Floating-point fused multiply-add long to accumulator -FALSE,vfmlal_laneq_high_f16,"r: float32x2_t, a: float16x4_t, b: float16x8_t, lane: const int",float32x2_t,Floating-point fused multiply-add long to accumulator -FALSE,vfmlal_laneq_low_f16,"r: float32x2_t, a: float16x4_t, b: float16x8_t, lane: const int",float32x2_t,Floating-point fused multiply-add long to accumulator -FALSE,vfmlal_low_f16,"r: float32x2_t, a: float16x4_t, b: float16x4_t",float32x2_t,Floating-point fused multiply-add long to accumulator -FALSE,vfmlalq_high_f16,"r: float32x4_t, a: float16x8_t, b: float16x8_t",float32x4_t,Floating-point fused multiply-add long to accumulator -FALSE,vfmlalq_lane_high_f16,"r: float32x4_t, a: float16x8_t, b: float16x4_t, lane: const int",float32x4_t,Floating-point fused multiply-add long to accumulator -FALSE,vfmlalq_lane_low_f16,"r: float32x4_t, a: float16x8_t, b: float16x4_t, lane: const int",float32x4_t,Floating-point fused multiply-add long to accumulator -FALSE,vfmlalq_laneq_high_f16,"r: float32x4_t, a: float16x8_t, b: float16x8_t, lane: const int",float32x4_t,Floating-point fused multiply-add long to accumulator -FALSE,vfmlalq_laneq_low_f16,"r: float32x4_t, a: float16x8_t, b: float16x8_t, lane: const int",float32x4_t,Floating-point fused multiply-add long to accumulator -FALSE,vfmlalq_low_f16,"r: float32x4_t, a: float16x8_t, b: float16x8_t",float32x4_t,Floating-point fused multiply-add long to accumulator -FALSE,vfmlsl_high_f16,"r: float32x2_t, a: float16x4_t, b: float16x4_t",float32x2_t,Floating-point fused multiply-subtract long from accumulator -FALSE,vfmlsl_lane_high_f16,"r: float32x2_t, a: float16x4_t, b: float16x4_t, lane: const int",float32x2_t,Floating-point fused multiply-subtract long from accumulator -FALSE,vfmlsl_lane_low_f16,"r: float32x2_t, a: float16x4_t, b: float16x4_t, lane: const int",float32x2_t,Floating-point fused multiply-subtract long from accumulator -FALSE,vfmlsl_laneq_high_f16,"r: float32x2_t, a: float16x4_t, b: float16x8_t, lane: const int",float32x2_t,Floating-point fused multiply-subtract long from accumulator -FALSE,vfmlsl_laneq_low_f16,"r: float32x2_t, a: float16x4_t, b: float16x8_t, lane: const int",float32x2_t,Floating-point fused multiply-subtract long from accumulator -FALSE,vfmlsl_low_f16,"r: float32x2_t, a: float16x4_t, b: float16x4_t",float32x2_t,Floating-point fused multiply-subtract long from accumulator -FALSE,vfmlslq_high_f16,"r: float32x4_t, a: float16x8_t, b: float16x8_t",float32x4_t,Floating-point fused multiply-subtract long from accumulator -FALSE,vfmlslq_lane_high_f16,"r: float32x4_t, a: float16x8_t, b: float16x4_t, lane: const int",float32x4_t,Floating-point fused multiply-subtract long from accumulator -FALSE,vfmlslq_lane_low_f16,"r: float32x4_t, a: float16x8_t, b: float16x4_t, lane: const int",float32x4_t,Floating-point fused multiply-subtract long from accumulator -FALSE,vfmlslq_laneq_high_f16,"r: float32x4_t, a: float16x8_t, b: float16x8_t, lane: const int",float32x4_t,Floating-point fused multiply-subtract long from accumulator -FALSE,vfmlslq_laneq_low_f16,"r: float32x4_t, a: float16x8_t, b: float16x8_t, lane: const int",float32x4_t,Floating-point fused multiply-subtract long from accumulator -FALSE,vfmlslq_low_f16,"r: float32x4_t, a: float16x8_t, b: float16x8_t",float32x4_t,Floating-point fused multiply-subtract long from accumulator -FALSE,vfms_f16,"a: float16x4_t, b: float16x4_t, c: float16x4_t",float16x4_t,Floating-point fused multiply-subtract from accumulator -FALSE,vfms_f32,"a: float32x2_t, b: float32x2_t, c: float32x2_t",float32x2_t,Floating-point fused multiply-subtract from accumulator -FALSE,vfms_f64,"a: float64x1_t, b: float64x1_t, c: float64x1_t",float64x1_t,Floating-point fused multiply-subtract -FALSE,vfms_lane_f16,"a: float16x4_t, b: float16x4_t, v: float16x4_t, lane: const int",float16x4_t,Floating-point fused multiply-subtract from accumulator -FALSE,vfms_lane_f32,"a: float32x2_t, b: float32x2_t, v: float32x2_t, lane: const int",float32x2_t,Floating-point fused multiply-subtract from accumulator -FALSE,vfms_lane_f64,"a: float64x1_t, b: float64x1_t, v: float64x1_t, lane: const int",float64x1_t,Floating-point fused multiply-subtract from accumulator -FALSE,vfms_laneq_f16,"a: float16x4_t, b: float16x4_t, v: float16x8_t, lane: const int",float16x4_t,Floating-point fused multiply-subtract from accumulator -FALSE,vfms_laneq_f32,"a: float32x2_t, b: float32x2_t, v: float32x4_t, lane: const int",float32x2_t,Floating-point fused multiply-subtract from accumulator -FALSE,vfms_laneq_f64,"a: float64x1_t, b: float64x1_t, v: float64x2_t, lane: const int",float64x1_t,Floating-point fused multiply-subtract from accumulator -FALSE,vfms_n_f16,"a: float16x4_t, b: float16x4_t, n: float16_t",float16x4_t,Floating-point fused multiply-subtract from accumulator -FALSE,vfms_n_f32,"a: float32x2_t, b: float32x2_t, n: f32",float32x2_t,Floating-point fused multiply-subtract from accumulator -FALSE,vfms_n_f64,"a: float64x1_t, b: float64x1_t, n: float64_t",float64x1_t,Floating-point fused multiply-subtract -FALSE,vfmsd_lane_f64,"a: float64_t, b: float64_t, v: float64x1_t, lane: const int",float64_t,Floating-point fused multiply-subtract from accumulator -FALSE,vfmsd_laneq_f64,"a: float64_t, b: float64_t, v: float64x2_t, lane: const int",float64_t,Floating-point fused multiply-subtract from accumulator -FALSE,vfmsh_f16,"a: float16_t, b: float16_t, c: float16_t",float16_t,Floating-point fused multiply-subtract -FALSE,vfmsh_lane_f16,"a: float16_t, b: float16_t, v: float16x4_t, lane: const int",float16_t,Floating-point fused multiply-subtract from accumulator -FALSE,vfmsh_laneq_f16,"a: float16_t, b: float16_t, v: float16x8_t, lane: const int",float16_t,Floating-point fused multiply-subtract from accumulator -FALSE,vfmsq_f16,"a: float16x8_t, b: float16x8_t, c: float16x8_t",float16x8_t,Floating-point fused multiply-subtract from accumulator -FALSE,vfmsq_f32,"a: float32x4_t, b: float32x4_t, c: float32x4_t",float32x4_t,Floating-point fused multiply-subtract from accumulator -FALSE,vfmsq_f64,"a: float64x2_t, b: float64x2_t, c: float64x2_t",float64x2_t,Floating-point fused multiply-subtract from accumulator -FALSE,vfmsq_lane_f16,"a: float16x8_t, b: float16x8_t, v: float16x4_t, lane: const int",float16x8_t,Floating-point fused multiply-subtract from accumulator -FALSE,vfmsq_lane_f32,"a: float32x4_t, b: float32x4_t, v: float32x2_t, lane: const int",float32x4_t,Floating-point fused multiply-subtract from accumulator -FALSE,vfmsq_lane_f64,"a: float64x2_t, b: float64x2_t, v: float64x1_t, lane: const int",float64x2_t,Floating-point fused multiply-subtract from accumulator -FALSE,vfmsq_laneq_f16,"a: float16x8_t, b: float16x8_t, v: float16x8_t, lane: const int",float16x8_t,Floating-point fused multiply-subtract from accumulator -FALSE,vfmsq_laneq_f32,"a: float32x4_t, b: float32x4_t, v: float32x4_t, lane: const int",float32x4_t,Floating-point fused multiply-subtract from accumulator -FALSE,vfmsq_laneq_f64,"a: float64x2_t, b: float64x2_t, v: float64x2_t, lane: const int",float64x2_t,Floating-point fused multiply-subtract from accumulator -FALSE,vfmsq_n_f16,"a: float16x8_t, b: float16x8_t, n: float16_t",float16x8_t,Floating-point fused multiply-subtract from accumulator -FALSE,vfmsq_n_f32,"a: float32x4_t, b: float32x4_t, n: f32",float32x4_t,Floating-point fused multiply-subtract from accumulator -FALSE,vfmsq_n_f64,"a: float64x2_t, b: float64x2_t, n: float64_t",float64x2_t,Floating-point fused multiply-subtract from accumulator -FALSE,vfmss_lane_f32,"a: f32, b: f32, v: float32x2_t, lane: const int",f32,Floating-point fused multiply-subtract from accumulator -FALSE,vfmss_laneq_f32,"a: f32, b: f32, v: float32x4_t, lane: const int",f32,Floating-point fused multiply-subtract from accumulator -FALSE,vget_high_bf16,a: bfloat16x8_t,bfloat16x4_t,Duplicate vector element to vector or scalar -FALSE,vget_high_f16,a: float16x8_t,float16x4_t,Duplicate vector element to vector or scalar -TRUE,vget_high_f32,a: float32x4_t,float32x2_t,Duplicate vector element to vector or scalar -TRUE,vget_high_f64,a: float64x2_t,float64x1_t,Duplicate vector element to vector or scalar -TRUE,vget_high_p16,a: poly16x8_t,poly16x4_t,Duplicate vector element to vector or scalar -TRUE,vget_high_p64,a: poly64x2_t,poly64x1_t,Duplicate vector element to vector or scalar -TRUE,vget_high_p8,a: poly8x16_t,poly8x8_t,Duplicate vector element to vector or scalar -TRUE,vget_high_s16,a: int16x8_t,int16x4_t,Duplicate vector element to vector or scalar -TRUE,vget_high_s32,a: int32x4_t,int32x2_t,Duplicate vector element to vector or scalar -TRUE,vget_high_s64,a: int64x2_t,int64x1_t,Duplicate vector element to vector or scalar -TRUE,vget_high_s8,a: int8x16_t,int8x8_t,Duplicate vector element to vector or scalar -TRUE,vget_high_u16,a: uint16x8_t,uint16x4_t,Duplicate vector element to vector or scalar -TRUE,vget_high_u32,a: uint32x4_t,uint32x2_t,Duplicate vector element to vector or scalar -TRUE,vget_high_u64,a: uint64x2_t,uint64x1_t,Duplicate vector element to vector or scalar -TRUE,vget_high_u8,a: uint8x16_t,uint8x8_t,Duplicate vector element to vector or scalar -FALSE,vget_lane_bf16,"v: bfloat16x4_t, lane: const int",bfloat16_t,Duplicate vector element to vector or scalar -FALSE,vget_lane_f16,"v: float16x4_t, lane: const int",float16_t,Duplicate vector element to vector or scalar -FALSE,vget_lane_f32,"v: float32x2_t, lane: const int",f32,Duplicate vector element to vector or scalar -FALSE,vget_lane_f64,"v: float64x1_t, lane: const int",float64_t,Duplicate vector element to vector or scalar -FALSE,vget_lane_p16,"v: poly16x4_t, lane: const int",poly16_t,Unsigned move vector element to general-purpose register -FALSE,vget_lane_p64,"v: poly64x1_t, lane: const int",poly64_t,Unsigned move vector element to general-purpose register -FALSE,vget_lane_p8,"v: poly8x8_t, lane: const int",poly8_t,Unsigned move vector element to general-purpose register -FALSE,vget_lane_s16,"v: int16x4_t, lane: const int",i16,Signed move vector element to general-purpose register -FALSE,vget_lane_s32,"v: int32x2_t, lane: const int",i32,Signed move vector element to general-purpose register -FALSE,vget_lane_s64,"v: int64x1_t, lane: const int",i64,Unsigned move vector element to general-purpose register -FALSE,vget_lane_s8,"v: int8x8_t, lane: const int",i8,Signed move vector element to general-purpose register -FALSE,vget_lane_u16,"v: uint16x4_t, lane: const int",u16,Unsigned move vector element to general-purpose register -FALSE,vget_lane_u32,"v: uint32x2_t, lane: const int",u32,Unsigned move vector element to general-purpose register -TRUE,vget_lane_u64,"v: uint64x1_t, lane: const int",u64,Unsigned move vector element to general-purpose register -TRUE,vget_lane_u8,"v: uint8x8_t, lane: const int",u8,Unsigned move vector element to general-purpose register -FALSE,vget_low_bf16,a: bfloat16x8_t,bfloat16x4_t,Duplicate vector element to vector or scalar -FALSE,vget_low_f16,a: float16x8_t,float16x4_t,Duplicate vector element to vector or scalar -TRUE,vget_low_f32,a: float32x4_t,float32x2_t,Duplicate vector element to vector or scalar -TRUE,vget_low_f64,a: float64x2_t,float64x1_t,Duplicate vector element to vector or scalar -TRUE,vget_low_p16,a: poly16x8_t,poly16x4_t,Duplicate vector element to vector or scalar -TRUE,vget_low_p64,a: poly64x2_t,poly64x1_t,Duplicate vector element to vector or scalar -TRUE,vget_low_p8,a: poly8x16_t,poly8x8_t,Duplicate vector element to vector or scalar -TRUE,vget_low_s16,a: int16x8_t,int16x4_t,Duplicate vector element to vector or scalar -TRUE,vget_low_s32,a: int32x4_t,int32x2_t,Duplicate vector element to vector or scalar -TRUE,vget_low_s64,a: int64x2_t,int64x1_t,Duplicate vector element to vector or scalar -TRUE,vget_low_s8,a: int8x16_t,int8x8_t,Duplicate vector element to vector or scalar -TRUE,vget_low_u16,a: uint16x8_t,uint16x4_t,Duplicate vector element to vector or scalar -TRUE,vget_low_u32,a: uint32x4_t,uint32x2_t,Duplicate vector element to vector or scalar -TRUE,vget_low_u64,a: uint64x2_t,uint64x1_t,Duplicate vector element to vector or scalar -TRUE,vget_low_u8,a: uint8x16_t,uint8x8_t,Duplicate vector element to vector or scalar -FALSE,vgetq_lane_bf16,"v: bfloat16x8_t, lane: const int",bfloat16_t,Duplicate vector element to vector or scalar -FALSE,vgetq_lane_f16,"v: float16x8_t, lane: const int",float16_t,Duplicate vector element to vector or scalar -FALSE,vgetq_lane_f32,"v: float32x4_t, lane: const int",f32,Duplicate vector element to vector or scalar -FALSE,vgetq_lane_f64,"v: float64x2_t, lane: const int",float64_t,Duplicate vector element to vector or scalar -FALSE,vgetq_lane_p16,"v: poly16x8_t, lane: const int",poly16_t,Unsigned move vector element to general-purpose register -FALSE,vgetq_lane_p64,"v: poly64x2_t, lane: const int",poly64_t,Unsigned move vector element to general-purpose register -FALSE,vgetq_lane_p8,"v: poly8x16_t, lane: const int",poly8_t,Unsigned move vector element to general-purpose register -FALSE,vgetq_lane_s16,"v: int16x8_t, lane: const int",i16,Signed move vector element to general-purpose register -FALSE,vgetq_lane_s32,"v: int32x4_t, lane: const int",i32,Signed move vector element to general-purpose register -FALSE,vgetq_lane_s64,"v: int64x2_t, lane: const int",i64,Unsigned move vector element to general-purpose register -FALSE,vgetq_lane_s8,"v: int8x16_t, lane: const int",i8,Signed move vector element to general-purpose register -TRUE,vgetq_lane_u16,"v: uint16x8_t, lane: const int",u16,Unsigned move vector element to general-purpose register -TRUE,vgetq_lane_u32,"v: uint32x4_t, lane: const int",u32,Unsigned move vector element to general-purpose register -TRUE,vgetq_lane_u64,"v: uint64x2_t, lane: const int",u64,Unsigned move vector element to general-purpose register -FALSE,vgetq_lane_u8,"v: uint8x16_t, lane: const int",u8,Unsigned move vector element to general-purpose register -TRUE,vhadd_s16,"a: int16x4_t, b: int16x4_t",int16x4_t,Signed halving add -TRUE,vhadd_s32,"a: int32x2_t, b: int32x2_t",int32x2_t,Signed halving add -TRUE,vhadd_s8,"a: int8x8_t, b: int8x8_t",int8x8_t,Signed halving add -TRUE,vhadd_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4_t,Unsigned halving add -TRUE,vhadd_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2_t,Unsigned halving add -TRUE,vhadd_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,Unsigned halving add -TRUE,vhaddq_s16,"a: int16x8_t, b: int16x8_t",int16x8_t,Signed halving add -TRUE,vhaddq_s32,"a: int32x4_t, b: int32x4_t",int32x4_t,Signed halving add -TRUE,vhaddq_s8,"a: int8x16_t, b: int8x16_t",int8x16_t,Signed halving add -TRUE,vhaddq_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8_t,Unsigned halving add -TRUE,vhaddq_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,Unsigned halving add -TRUE,vhaddq_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16_t,Unsigned halving add -TRUE,vhsub_s16,"a: int16x4_t, b: int16x4_t",int16x4_t,Signed halving subtract -TRUE,vhsub_s32,"a: int32x2_t, b: int32x2_t",int32x2_t,Signed halving subtract -TRUE,vhsub_s8,"a: int8x8_t, b: int8x8_t",int8x8_t,Signed halving subtract -TRUE,vhsub_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4_t,Unsigned halving subtract -TRUE,vhsub_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2_t,Unsigned halving subtract -TRUE,vhsub_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,Unsigned halving subtract -TRUE,vhsubq_s16,"a: int16x8_t, b: int16x8_t",int16x8_t,Signed halving subtract -TRUE,vhsubq_s32,"a: int32x4_t, b: int32x4_t",int32x4_t,Signed halving subtract -TRUE,vhsubq_s8,"a: int8x16_t, b: int8x16_t",int8x16_t,Signed halving subtract -TRUE,vhsubq_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8_t,Unsigned halving subtract -TRUE,vhsubq_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,Unsigned halving subtract -TRUE,vhsubq_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16_t,Unsigned halving subtract -FALSE,vld1_bf16,ptr: *const bfloat16_t,bfloat16x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_bf16_x2,ptr: *const bfloat16_t,bfloat16x4x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_bf16_x3,ptr: *const bfloat16_t,bfloat16x4x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_bf16_x4,ptr: *const bfloat16_t,bfloat16x4x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_dup_bf16,ptr: *const bfloat16_t,bfloat16x4_t,Load one single-element structure and replicate to all lanes (of one register) -FALSE,vld1_dup_f16,ptr: *const float16_t,float16x4_t,Load one single-element structure and replicate to all lanes (of one register) -FALSE,vld1_dup_f32,ptr: *const f32,float32x2_t,Load one single-element structure and replicate to all lanes (of one register) -FALSE,vld1_dup_f64,ptr: *const float64_t,float64x1_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_dup_p16,ptr: *const poly16_t,poly16x4_t,Load one single-element structure and replicate to all lanes (of one register) -FALSE,vld1_dup_p64,ptr: *const poly64_t,poly64x1_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_dup_p8,ptr: *const poly8_t,poly8x8_t,Load one single-element structure and replicate to all lanes (of one register) -FALSE,vld1_dup_s16,ptr: *const i16,int16x4_t,Load one single-element structure and replicate to all lanes (of one register) -FALSE,vld1_dup_s32,ptr: *const i32,int32x2_t,Load one single-element structure and replicate to all lanes (of one register) -FALSE,vld1_dup_s64,ptr: *const i64,int64x1_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_dup_s8,ptr: *const i8,int8x8_t,Load one single-element structure and replicate to all lanes (of one register) -FALSE,vld1_dup_u16,ptr: *const u16,uint16x4_t,Load one single-element structure and replicate to all lanes (of one register) -FALSE,vld1_dup_u32,ptr: *const u32,uint32x2_t,Load one single-element structure and replicate to all lanes (of one register) -FALSE,vld1_dup_u64,ptr: *const u64,uint64x1_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_dup_u8,ptr: *const u8,uint8x8_t,Load one single-element structure and replicate to all lanes (of one register) -FALSE,vld1_f16,ptr: *const float16_t,float16x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_f16_x2,ptr: *const float16_t,float16x4x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_f16_x3,ptr: *const float16_t,float16x4x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_f16_x4,ptr: *const float16_t,float16x4x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_f32,ptr: *const f32,float32x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_f32_x2,ptr: *const f32,float32x2x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_f32_x3,ptr: *const f32,float32x2x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_f32_x4,ptr: *const f32,float32x2x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_f64,ptr: *const float64_t,float64x1_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_f64_x2,ptr: *const float64_t,float64x1x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_f64_x3,ptr: *const float64_t,float64x1x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_f64_x4,ptr: *const float64_t,float64x1x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_lane_bf16,"ptr: *const bfloat16_t, src: bfloat16x4_t, lane: const int",bfloat16x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_lane_f16,"ptr: *const float16_t, src: float16x4_t, lane: const int",float16x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_lane_f32,"ptr: *const f32, src: float32x2_t, lane: const int",float32x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_lane_f64,"ptr: *const float64_t, src: float64x1_t, lane: const int",float64x1_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_lane_p16,"ptr: *const poly16_t, src: poly16x4_t, lane: const int",poly16x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_lane_p64,"ptr: *const poly64_t, src: poly64x1_t, lane: const int",poly64x1_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_lane_p8,"ptr: *const poly8_t, src: poly8x8_t, lane: const int",poly8x8_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_lane_s16,"ptr: *const i16, src: int16x4_t, lane: const int",int16x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_lane_s32,"ptr: *const i32, src: int32x2_t, lane: const int",int32x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_lane_s64,"ptr: *const i64, src: int64x1_t, lane: const int",int64x1_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_lane_s8,"ptr: *const i8, src: int8x8_t, lane: const int",int8x8_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_lane_u16,"ptr: *const u16, src: uint16x4_t, lane: const int",uint16x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_lane_u32,"ptr: *const u32, src: uint32x2_t, lane: const int",uint32x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_lane_u64,"ptr: *const u64, src: uint64x1_t, lane: const int",uint64x1_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_lane_u8,"ptr: *const u8, src: uint8x8_t, lane: const int",uint8x8_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_p16,ptr: *const poly16_t,poly16x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_p16_x2,ptr: *const poly16_t,poly16x4x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_p16_x3,ptr: *const poly16_t,poly16x4x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_p16_x4,ptr: *const poly16_t,poly16x4x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_p64,ptr: *const poly64_t,poly64x1_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_p64_x2,ptr: *const poly64_t,poly64x1x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_p64_x3,ptr: *const poly64_t,poly64x1x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_p64_x4,ptr: *const poly64_t,poly64x1x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_p8,ptr: *const poly8_t,poly8x8_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_p8_x2,ptr: *const poly8_t,poly8x8x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_p8_x3,ptr: *const poly8_t,poly8x8x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_p8_x4,ptr: *const poly8_t,poly8x8x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_s16,ptr: *const i16,int16x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_s16_x2,ptr: *const i16,int16x4x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_s16_x3,ptr: *const i16,int16x4x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_s16_x4,ptr: *const i16,int16x4x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_s32,ptr: *const i32,int32x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_s32_x2,ptr: *const i32,int32x2x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_s32_x3,ptr: *const i32,int32x2x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_s32_x4,ptr: *const i32,int32x2x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_s64,ptr: *const i64,int64x1_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_s64_x2,ptr: *const i64,int64x1x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_s64_x3,ptr: *const i64,int64x1x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_s64_x4,ptr: *const i64,int64x1x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_s8,ptr: *const i8,int8x8_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_s8_x2,ptr: *const i8,int8x8x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_s8_x3,ptr: *const i8,int8x8x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_s8_x4,ptr: *const i8,int8x8x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_u16,ptr: *const u16,uint16x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_u16_x2,ptr: *const u16,uint16x4x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_u16_x3,ptr: *const u16,uint16x4x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_u16_x4,ptr: *const u16,uint16x4x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_u32,ptr: *const u32,uint32x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_u32_x2,ptr: *const u32,uint32x2x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_u32_x3,ptr: *const u32,uint32x2x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_u32_x4,ptr: *const u32,uint32x2x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_u64,ptr: *const u64,uint64x1_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_u64_x2,ptr: *const u64,uint64x1x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_u64_x3,ptr: *const u64,uint64x1x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_u64_x4,ptr: *const u64,uint64x1x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_u8,ptr: *const u8,uint8x8_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_u8_x2,ptr: *const u8,uint8x8x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_u8_x3,ptr: *const u8,uint8x8x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1_u8_x4,ptr: *const u8,uint8x8x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_bf16,ptr: *const bfloat16_t,bfloat16x8_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_bf16_x2,ptr: *const bfloat16_t,bfloat16x8x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_bf16_x3,ptr: *const bfloat16_t,bfloat16x8x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_bf16_x4,ptr: *const bfloat16_t,bfloat16x8x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_dup_bf16,ptr: *const bfloat16_t,bfloat16x8_t,Load one single-element structure and replicate to all lanes (of one register) -FALSE,vld1q_dup_f16,ptr: *const float16_t,float16x8_t,Load one single-element structure and replicate to all lanes (of one register) -FALSE,vld1q_dup_f32,ptr: *const f32,float32x4_t,Load one single-element structure and replicate to all lanes (of one register) -FALSE,vld1q_dup_f64,ptr: *const float64_t,float64x2_t,Load one single-element structure and replicate to all lanes (of one register) -FALSE,vld1q_dup_p16,ptr: *const poly16_t,poly16x8_t,Load one single-element structure and replicate to all lanes (of one register) -FALSE,vld1q_dup_p64,ptr: *const poly64_t,poly64x2_t,Load one single-element structure and replicate to all lanes (of one register) -FALSE,vld1q_dup_p8,ptr: *const poly8_t,poly8x16_t,Load one single-element structure and replicate to all lanes (of one register) -FALSE,vld1q_dup_s16,ptr: *const i16,int16x8_t,Load one single-element structure and replicate to all lanes (of one register) -FALSE,vld1q_dup_s32,ptr: *const i32,int32x4_t,Load one single-element structure and replicate to all lanes (of one register) -FALSE,vld1q_dup_s64,ptr: *const i64,int64x2_t,Load one single-element structure and replicate to all lanes (of one register) -FALSE,vld1q_dup_s8,ptr: *const i8,int8x16_t,Load one single-element structure and replicate to all lanes (of one register) -FALSE,vld1q_dup_u16,ptr: *const u16,uint16x8_t,Load one single-element structure and replicate to all lanes (of one register) -FALSE,vld1q_dup_u32,ptr: *const u32,uint32x4_t,Load one single-element structure and replicate to all lanes (of one register) -FALSE,vld1q_dup_u64,ptr: *const u64,uint64x2_t,Load one single-element structure and replicate to all lanes (of one register) -FALSE,vld1q_dup_u8,ptr: *const u8,uint8x16_t,Load one single-element structure and replicate to all lanes (of one register) -FALSE,vld1q_f16,ptr: *const float16_t,float16x8_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_f16_x2,ptr: *const float16_t,float16x8x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_f16_x3,ptr: *const float16_t,float16x8x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_f16_x4,ptr: *const float16_t,float16x8x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_f32,ptr: *const f32,float32x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_f32_x2,ptr: *const f32,float32x4x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_f32_x3,ptr: *const f32,float32x4x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_f32_x4,ptr: *const f32,float32x4x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_f64,ptr: *const float64_t,float64x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_f64_x2,ptr: *const float64_t,float64x2x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_f64_x3,ptr: *const float64_t,float64x2x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_f64_x4,ptr: *const float64_t,float64x2x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_lane_bf16,"ptr: *const bfloat16_t, src: bfloat16x8_t, lane: const int",bfloat16x8_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_lane_f16,"ptr: *const float16_t, src: float16x8_t, lane: const int",float16x8_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_lane_f32,"ptr: *const f32, src: float32x4_t, lane: const int",float32x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_lane_f64,"ptr: *const float64_t, src: float64x2_t, lane: const int",float64x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_lane_p16,"ptr: *const poly16_t, src: poly16x8_t, lane: const int",poly16x8_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_lane_p64,"ptr: *const poly64_t, src: poly64x2_t, lane: const int",poly64x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_lane_p8,"ptr: *const poly8_t, src: poly8x16_t, lane: const int",poly8x16_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_lane_s16,"ptr: *const i16, src: int16x8_t, lane: const int",int16x8_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_lane_s32,"ptr: *const i32, src: int32x4_t, lane: const int",int32x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_lane_s64,"ptr: *const i64, src: int64x2_t, lane: const int",int64x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_lane_s8,"ptr: *const i8, src: int8x16_t, lane: const int",int8x16_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_lane_u16,"ptr: *const u16, src: uint16x8_t, lane: const int",uint16x8_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_lane_u32,"ptr: *const u32, src: uint32x4_t, lane: const int",uint32x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_lane_u64,"ptr: *const u64, src: uint64x2_t, lane: const int",uint64x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_lane_u8,"ptr: *const u8, src: uint8x16_t, lane: const int",uint8x16_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_p16,ptr: *const poly16_t,poly16x8_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_p16_x2,ptr: *const poly16_t,poly16x8x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_p16_x3,ptr: *const poly16_t,poly16x8x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_p16_x4,ptr: *const poly16_t,poly16x8x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_p64,ptr: *const poly64_t,poly64x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_p64_x2,ptr: *const poly64_t,poly64x2x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_p64_x3,ptr: *const poly64_t,poly64x2x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_p64_x4,ptr: *const poly64_t,poly64x2x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_p8,ptr: *const poly8_t,poly8x16_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_p8_x2,ptr: *const poly8_t,poly8x16x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_p8_x3,ptr: *const poly8_t,poly8x16x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_p8_x4,ptr: *const poly8_t,poly8x16x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_s16,ptr: *const i16,int16x8_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_s16_x2,ptr: *const i16,int16x8x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_s16_x3,ptr: *const i16,int16x8x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_s16_x4,ptr: *const i16,int16x8x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_s32,ptr: *const i32,int32x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_s32_x2,ptr: *const i32,int32x4x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_s32_x3,ptr: *const i32,int32x4x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_s32_x4,ptr: *const i32,int32x4x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_s64,ptr: *const i64,int64x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_s64_x2,ptr: *const i64,int64x2x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_s64_x3,ptr: *const i64,int64x2x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_s64_x4,ptr: *const i64,int64x2x4_t,"Load multiple single-element structures to one, two, three, or four registers" -TRUE,vld1q_s8,ptr: *const i8,int8x16_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_s8_x2,ptr: *const i8,int8x16x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_s8_x3,ptr: *const i8,int8x16x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_s8_x4,ptr: *const i8,int8x16x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_u16,ptr: *const u16,uint16x8_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_u16_x2,ptr: *const u16,uint16x8x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_u16_x3,ptr: *const u16,uint16x8x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_u16_x4,ptr: *const u16,uint16x8x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_u32,ptr: *const u32,uint32x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_u32_x2,ptr: *const u32,uint32x4x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_u32_x3,ptr: *const u32,uint32x4x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_u32_x4,ptr: *const u32,uint32x4x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_u64,ptr: *const u64,uint64x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_u64_x2,ptr: *const u64,uint64x2x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_u64_x3,ptr: *const u64,uint64x2x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_u64_x4,ptr: *const u64,uint64x2x4_t,"Load multiple single-element structures to one, two, three, or four registers" -TRUE,vld1q_u8,ptr: *const u8,uint8x16_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_u8_x2,ptr: *const u8,uint8x16x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_u8_x3,ptr: *const u8,uint8x16x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld1q_u8_x4,ptr: *const u8,uint8x16x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld2_bf16,ptr: *const bfloat16_t,bfloat16x4x2_t,Load multiple 2-element structures to two registers -FALSE,vld2_dup_bf16,ptr: *const bfloat16_t,bfloat16x4x2_t,Load single 2-element structure and replicate to all lanes of two registers -FALSE,vld2_dup_f16,ptr: *const float16_t,float16x4x2_t,Load single 2-element structure and replicate to all lanes of two registers -FALSE,vld2_dup_f32,ptr: *const f32,float32x2x2_t,Load single 2-element structure and replicate to all lanes of two registers -FALSE,vld2_dup_f64,ptr: *const float64_t,float64x1x2_t,Load single 2-element structure and replicate to all lanes of two registers -FALSE,vld2_dup_p16,ptr: *const poly16_t,poly16x4x2_t,Load single 2-element structure and replicate to all lanes of two registers -FALSE,vld2_dup_p64,ptr: *const poly64_t,poly64x1x2_t,Load single 2-element structure and replicate to all lanes of two registers -FALSE,vld2_dup_p8,ptr: *const poly8_t,poly8x8x2_t,Load single 2-element structure and replicate to all lanes of two registers -FALSE,vld2_dup_s16,ptr: *const i16,int16x4x2_t,Load single 2-element structure and replicate to all lanes of two registers -FALSE,vld2_dup_s32,ptr: *const i32,int32x2x2_t,Load single 2-element structure and replicate to all lanes of two registers -FALSE,vld2_dup_s64,ptr: *const i64,int64x1x2_t,Load single 2-element structure and replicate to all lanes of two registers -FALSE,vld2_dup_s8,ptr: *const i8,int8x8x2_t,Load single 2-element structure and replicate to all lanes of two registers -FALSE,vld2_dup_u16,ptr: *const u16,uint16x4x2_t,Load single 2-element structure and replicate to all lanes of two registers -FALSE,vld2_dup_u32,ptr: *const u32,uint32x2x2_t,Load single 2-element structure and replicate to all lanes of two registers -FALSE,vld2_dup_u64,ptr: *const u64,uint64x1x2_t,Load single 2-element structure and replicate to all lanes of two registers -FALSE,vld2_dup_u8,ptr: *const u8,uint8x8x2_t,Load single 2-element structure and replicate to all lanes of two registers -FALSE,vld2_f16,ptr: *const float16_t,float16x4x2_t,Load multiple 2-element structures to two registers -FALSE,vld2_f32,ptr: *const f32,float32x2x2_t,Load multiple 2-element structures to two registers -FALSE,vld2_f64,ptr: *const float64_t,float64x1x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld2_lane_bf16,"ptr: *const bfloat16_t, src: bfloat16x4x2_t, lane: const int",bfloat16x4x2_t,Load multiple 2-element structures to two registers -FALSE,vld2_lane_f16,"ptr: *const float16_t, src: float16x4x2_t, lane: const int",float16x4x2_t,Load multiple 2-element structures to two registers -FALSE,vld2_lane_f32,"ptr: *const f32, src: float32x2x2_t, lane: const int",float32x2x2_t,Load multiple 2-element structures to two registers -FALSE,vld2_lane_f64,"ptr: *const float64_t, src: float64x1x2_t, lane: const int",float64x1x2_t,Load multiple 2-element structures to two registers -FALSE,vld2_lane_p16,"ptr: *const poly16_t, src: poly16x4x2_t, lane: const int",poly16x4x2_t,Load multiple 2-element structures to two registers -FALSE,vld2_lane_p64,"ptr: *const poly64_t, src: poly64x1x2_t, lane: const int",poly64x1x2_t,Load multiple 2-element structures to two registers -FALSE,vld2_lane_p8,"ptr: *const poly8_t, src: poly8x8x2_t, lane: const int",poly8x8x2_t,Load multiple 2-element structures to two registers -FALSE,vld2_lane_s16,"ptr: *const i16, src: int16x4x2_t, lane: const int",int16x4x2_t,Load multiple 2-element structures to two registers -FALSE,vld2_lane_s32,"ptr: *const i32, src: int32x2x2_t, lane: const int",int32x2x2_t,Load multiple 2-element structures to two registers -FALSE,vld2_lane_s64,"ptr: *const i64, src: int64x1x2_t, lane: const int",int64x1x2_t,Load multiple 2-element structures to two registers -FALSE,vld2_lane_s8,"ptr: *const i8, src: int8x8x2_t, lane: const int",int8x8x2_t,Load multiple 2-element structures to two registers -FALSE,vld2_lane_u16,"ptr: *const u16, src: uint16x4x2_t, lane: const int",uint16x4x2_t,Load multiple 2-element structures to two registers -FALSE,vld2_lane_u32,"ptr: *const u32, src: uint32x2x2_t, lane: const int",uint32x2x2_t,Load multiple 2-element structures to two registers -FALSE,vld2_lane_u64,"ptr: *const u64, src: uint64x1x2_t, lane: const int",uint64x1x2_t,Load multiple 2-element structures to two registers -FALSE,vld2_lane_u8,"ptr: *const u8, src: uint8x8x2_t, lane: const int",uint8x8x2_t,Load multiple 2-element structures to two registers -FALSE,vld2_p16,ptr: *const poly16_t,poly16x4x2_t,Load multiple 2-element structures to two registers -FALSE,vld2_p64,ptr: *const poly64_t,poly64x1x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld2_p8,ptr: *const poly8_t,poly8x8x2_t,Load multiple 2-element structures to two registers -FALSE,vld2_s16,ptr: *const i16,int16x4x2_t,Load multiple 2-element structures to two registers -FALSE,vld2_s32,ptr: *const i32,int32x2x2_t,Load multiple 2-element structures to two registers -FALSE,vld2_s64,ptr: *const i64,int64x1x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld2_s8,ptr: *const i8,int8x8x2_t,Load multiple 2-element structures to two registers -FALSE,vld2_u16,ptr: *const u16,uint16x4x2_t,Load multiple 2-element structures to two registers -FALSE,vld2_u32,ptr: *const u32,uint32x2x2_t,Load multiple 2-element structures to two registers -FALSE,vld2_u64,ptr: *const u64,uint64x1x2_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld2_u8,ptr: *const u8,uint8x8x2_t,Load multiple 2-element structures to two registers -FALSE,vld2q_bf16,ptr: *const bfloat16_t,bfloat16x8x2_t,Load multiple 2-element structures to two registers -FALSE,vld2q_dup_bf16,ptr: *const bfloat16_t,bfloat16x8x2_t,Load single 2-element structure and replicate to all lanes of two registers -FALSE,vld2q_dup_f16,ptr: *const float16_t,float16x8x2_t,Load single 2-element structure and replicate to all lanes of two registers -FALSE,vld2q_dup_f32,ptr: *const f32,float32x4x2_t,Load single 2-element structure and replicate to all lanes of two registers -FALSE,vld2q_dup_f64,ptr: *const float64_t,float64x2x2_t,Load single 2-element structure and replicate to all lanes of two registers -FALSE,vld2q_dup_p16,ptr: *const poly16_t,poly16x8x2_t,Load single 2-element structure and replicate to all lanes of two registers -FALSE,vld2q_dup_p64,ptr: *const poly64_t,poly64x2x2_t,Load single 2-element structure and replicate to all lanes of two registers -FALSE,vld2q_dup_p8,ptr: *const poly8_t,poly8x16x2_t,Load single 2-element structure and replicate to all lanes of two registers -FALSE,vld2q_dup_s16,ptr: *const i16,int16x8x2_t,Load single 2-element structure and replicate to all lanes of two registers -FALSE,vld2q_dup_s32,ptr: *const i32,int32x4x2_t,Load single 2-element structure and replicate to all lanes of two registers -FALSE,vld2q_dup_s64,ptr: *const i64,int64x2x2_t,Load single 2-element structure and replicate to all lanes of two registers -FALSE,vld2q_dup_s8,ptr: *const i8,int8x16x2_t,Load single 2-element structure and replicate to all lanes of two registers -FALSE,vld2q_dup_u16,ptr: *const u16,uint16x8x2_t,Load single 2-element structure and replicate to all lanes of two registers -FALSE,vld2q_dup_u32,ptr: *const u32,uint32x4x2_t,Load single 2-element structure and replicate to all lanes of two registers -FALSE,vld2q_dup_u64,ptr: *const u64,uint64x2x2_t,Load single 2-element structure and replicate to all lanes of two registers -FALSE,vld2q_dup_u8,ptr: *const u8,uint8x16x2_t,Load single 2-element structure and replicate to all lanes of two registers -FALSE,vld2q_f16,ptr: *const float16_t,float16x8x2_t,Load multiple 2-element structures to two registers -FALSE,vld2q_f32,ptr: *const f32,float32x4x2_t,Load multiple 2-element structures to two registers -FALSE,vld2q_f64,ptr: *const float64_t,float64x2x2_t,Load multiple 2-element structures to two registers -FALSE,vld2q_lane_bf16,"ptr: *const bfloat16_t, src: bfloat16x8x2_t, lane: const int",bfloat16x8x2_t,Load multiple 2-element structures to two registers -FALSE,vld2q_lane_f16,"ptr: *const float16_t, src: float16x8x2_t, lane: const int",float16x8x2_t,Load multiple 2-element structures to two registers -FALSE,vld2q_lane_f32,"ptr: *const f32, src: float32x4x2_t, lane: const int",float32x4x2_t,Load multiple 2-element structures to two registers -FALSE,vld2q_lane_f64,"ptr: *const float64_t, src: float64x2x2_t, lane: const int",float64x2x2_t,Load multiple 2-element structures to two registers -FALSE,vld2q_lane_p16,"ptr: *const poly16_t, src: poly16x8x2_t, lane: const int",poly16x8x2_t,Load multiple 2-element structures to two registers -FALSE,vld2q_lane_p64,"ptr: *const poly64_t, src: poly64x2x2_t, lane: const int",poly64x2x2_t,Load multiple 2-element structures to two registers -FALSE,vld2q_lane_p8,"ptr: *const poly8_t, src: poly8x16x2_t, lane: const int",poly8x16x2_t,Load multiple 2-element structures to two registers -FALSE,vld2q_lane_s16,"ptr: *const i16, src: int16x8x2_t, lane: const int",int16x8x2_t,Load multiple 2-element structures to two registers -FALSE,vld2q_lane_s32,"ptr: *const i32, src: int32x4x2_t, lane: const int",int32x4x2_t,Load multiple 2-element structures to two registers -FALSE,vld2q_lane_s64,"ptr: *const i64, src: int64x2x2_t, lane: const int",int64x2x2_t,Load multiple 2-element structures to two registers -FALSE,vld2q_lane_s8,"ptr: *const i8, src: int8x16x2_t, lane: const int",int8x16x2_t,Load multiple 2-element structures to two registers -FALSE,vld2q_lane_u16,"ptr: *const u16, src: uint16x8x2_t, lane: const int",uint16x8x2_t,Load multiple 2-element structures to two registers -FALSE,vld2q_lane_u32,"ptr: *const u32, src: uint32x4x2_t, lane: const int",uint32x4x2_t,Load multiple 2-element structures to two registers -FALSE,vld2q_lane_u64,"ptr: *const u64, src: uint64x2x2_t, lane: const int",uint64x2x2_t,Load multiple 2-element structures to two registers -FALSE,vld2q_lane_u8,"ptr: *const u8, src: uint8x16x2_t, lane: const int",uint8x16x2_t,Load multiple 2-element structures to two registers -FALSE,vld2q_p16,ptr: *const poly16_t,poly16x8x2_t,Load multiple 2-element structures to two registers -FALSE,vld2q_p64,ptr: *const poly64_t,poly64x2x2_t,Load multiple 2-element structures to two registers -FALSE,vld2q_p8,ptr: *const poly8_t,poly8x16x2_t,Load multiple 2-element structures to two registers -FALSE,vld2q_s16,ptr: *const i16,int16x8x2_t,Load multiple 2-element structures to two registers -FALSE,vld2q_s32,ptr: *const i32,int32x4x2_t,Load multiple 2-element structures to two registers -FALSE,vld2q_s64,ptr: *const i64,int64x2x2_t,Load multiple 2-element structures to two registers -FALSE,vld2q_s8,ptr: *const i8,int8x16x2_t,Load multiple 2-element structures to two registers -FALSE,vld2q_u16,ptr: *const u16,uint16x8x2_t,Load multiple 2-element structures to two registers -FALSE,vld2q_u32,ptr: *const u32,uint32x4x2_t,Load multiple 2-element structures to two registers -FALSE,vld2q_u64,ptr: *const u64,uint64x2x2_t,Load multiple 2-element structures to two registers -FALSE,vld2q_u8,ptr: *const u8,uint8x16x2_t,Load multiple 2-element structures to two registers -FALSE,vld3_bf16,ptr: *const bfloat16_t,bfloat16x4x3_t,Load multiple 3-element structures to three registers -FALSE,vld3_dup_bf16,ptr: *const bfloat16_t,bfloat16x4x3_t,Load single 3-element structure and replicate to all lanes of three registers -FALSE,vld3_dup_f16,ptr: *const float16_t,float16x4x3_t,Load single 3-element structure and replicate to all lanes of three registers -FALSE,vld3_dup_f32,ptr: *const f32,float32x2x3_t,Load single 3-element structure and replicate to all lanes of three registers -FALSE,vld3_dup_f64,ptr: *const float64_t,float64x1x3_t,Load single 3-element structure and replicate to all lanes of three registers -FALSE,vld3_dup_p16,ptr: *const poly16_t,poly16x4x3_t,Load single 3-element structure and replicate to all lanes of three registers -FALSE,vld3_dup_p64,ptr: *const poly64_t,poly64x1x3_t,Load single 3-element structure and replicate to all lanes of three registers -FALSE,vld3_dup_p8,ptr: *const poly8_t,poly8x8x3_t,Load single 3-element structure and replicate to all lanes of three registers -FALSE,vld3_dup_s16,ptr: *const i16,int16x4x3_t,Load single 3-element structure and replicate to all lanes of three registers -FALSE,vld3_dup_s32,ptr: *const i32,int32x2x3_t,Load single 3-element structure and replicate to all lanes of three registers -FALSE,vld3_dup_s64,ptr: *const i64,int64x1x3_t,Load single 3-element structure and replicate to all lanes of three registers -FALSE,vld3_dup_s8,ptr: *const i8,int8x8x3_t,Load single 3-element structure and replicate to all lanes of three registers -FALSE,vld3_dup_u16,ptr: *const u16,uint16x4x3_t,Load single 3-element structure and replicate to all lanes of three registers -FALSE,vld3_dup_u32,ptr: *const u32,uint32x2x3_t,Load single 3-element structure and replicate to all lanes of three registers -FALSE,vld3_dup_u64,ptr: *const u64,uint64x1x3_t,Load single 3-element structure and replicate to all lanes of three registers -FALSE,vld3_dup_u8,ptr: *const u8,uint8x8x3_t,Load single 3-element structure and replicate to all lanes of three registers -FALSE,vld3_f16,ptr: *const float16_t,float16x4x3_t,Load multiple 3-element structures to three registers -FALSE,vld3_f32,ptr: *const f32,float32x2x3_t,Load multiple 3-element structures to three registers -FALSE,vld3_f64,ptr: *const float64_t,float64x1x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld3_lane_bf16,"ptr: *const bfloat16_t, src: bfloat16x4x3_t, lane: const int",bfloat16x4x3_t,Load multiple 3-element structures to three registers -FALSE,vld3_lane_f16,"ptr: *const float16_t, src: float16x4x3_t, lane: const int",float16x4x3_t,Load multiple 3-element structures to three registers -FALSE,vld3_lane_f32,"ptr: *const f32, src: float32x2x3_t, lane: const int",float32x2x3_t,Load multiple 3-element structures to three registers -FALSE,vld3_lane_f64,"ptr: *const float64_t, src: float64x1x3_t, lane: const int",float64x1x3_t,Load multiple 3-element structures to three registers -FALSE,vld3_lane_p16,"ptr: *const poly16_t, src: poly16x4x3_t, lane: const int",poly16x4x3_t,Load multiple 3-element structures to three registers -FALSE,vld3_lane_p64,"ptr: *const poly64_t, src: poly64x1x3_t, lane: const int",poly64x1x3_t,Load multiple 3-element structures to three registers -FALSE,vld3_lane_p8,"ptr: *const poly8_t, src: poly8x8x3_t, lane: const int",poly8x8x3_t,Load multiple 3-element structures to three registers -FALSE,vld3_lane_s16,"ptr: *const i16, src: int16x4x3_t, lane: const int",int16x4x3_t,Load multiple 3-element structures to three registers -FALSE,vld3_lane_s32,"ptr: *const i32, src: int32x2x3_t, lane: const int",int32x2x3_t,Load multiple 3-element structures to three registers -FALSE,vld3_lane_s64,"ptr: *const i64, src: int64x1x3_t, lane: const int",int64x1x3_t,Load multiple 3-element structures to three registers -FALSE,vld3_lane_s8,"ptr: *const i8, src: int8x8x3_t, lane: const int",int8x8x3_t,Load multiple 3-element structures to three registers -FALSE,vld3_lane_u16,"ptr: *const u16, src: uint16x4x3_t, lane: const int",uint16x4x3_t,Load multiple 3-element structures to three registers -FALSE,vld3_lane_u32,"ptr: *const u32, src: uint32x2x3_t, lane: const int",uint32x2x3_t,Load multiple 3-element structures to three registers -FALSE,vld3_lane_u64,"ptr: *const u64, src: uint64x1x3_t, lane: const int",uint64x1x3_t,Load multiple 3-element structures to three registers -FALSE,vld3_lane_u8,"ptr: *const u8, src: uint8x8x3_t, lane: const int",uint8x8x3_t,Load multiple 3-element structures to three registers -FALSE,vld3_p16,ptr: *const poly16_t,poly16x4x3_t,Load multiple 3-element structures to three registers -FALSE,vld3_p64,ptr: *const poly64_t,poly64x1x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld3_p8,ptr: *const poly8_t,poly8x8x3_t,Load multiple 3-element structures to three registers -FALSE,vld3_s16,ptr: *const i16,int16x4x3_t,Load multiple 3-element structures to three registers -FALSE,vld3_s32,ptr: *const i32,int32x2x3_t,Load multiple 3-element structures to three registers -FALSE,vld3_s64,ptr: *const i64,int64x1x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld3_s8,ptr: *const i8,int8x8x3_t,Load multiple 3-element structures to three registers -FALSE,vld3_u16,ptr: *const u16,uint16x4x3_t,Load multiple 3-element structures to three registers -FALSE,vld3_u32,ptr: *const u32,uint32x2x3_t,Load multiple 3-element structures to three registers -FALSE,vld3_u64,ptr: *const u64,uint64x1x3_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld3_u8,ptr: *const u8,uint8x8x3_t,Load multiple 3-element structures to three registers -FALSE,vld3q_bf16,ptr: *const bfloat16_t,bfloat16x8x3_t,Load multiple 3-element structures to three registers -FALSE,vld3q_dup_bf16,ptr: *const bfloat16_t,bfloat16x8x3_t,Load single 3-element structure and replicate to all lanes of three registers -FALSE,vld3q_dup_f16,ptr: *const float16_t,float16x8x3_t,Load single 3-element structure and replicate to all lanes of three registers -FALSE,vld3q_dup_f32,ptr: *const f32,float32x4x3_t,Load single 3-element structure and replicate to all lanes of three registers -FALSE,vld3q_dup_f64,ptr: *const float64_t,float64x2x3_t,Load single 3-element structure and replicate to all lanes of three registers -FALSE,vld3q_dup_p16,ptr: *const poly16_t,poly16x8x3_t,Load single 3-element structure and replicate to all lanes of three registers -FALSE,vld3q_dup_p64,ptr: *const poly64_t,poly64x2x3_t,Load single 3-element structure and replicate to all lanes of three registers -FALSE,vld3q_dup_p8,ptr: *const poly8_t,poly8x16x3_t,Load single 3-element structure and replicate to all lanes of three registers -FALSE,vld3q_dup_s16,ptr: *const i16,int16x8x3_t,Load single 3-element structure and replicate to all lanes of three registers -FALSE,vld3q_dup_s32,ptr: *const i32,int32x4x3_t,Load single 3-element structure and replicate to all lanes of three registers -FALSE,vld3q_dup_s64,ptr: *const i64,int64x2x3_t,Load single 3-element structure and replicate to all lanes of three registers -FALSE,vld3q_dup_s8,ptr: *const i8,int8x16x3_t,Load single 3-element structure and replicate to all lanes of three registers -FALSE,vld3q_dup_u16,ptr: *const u16,uint16x8x3_t,Load single 3-element structure and replicate to all lanes of three registers -FALSE,vld3q_dup_u32,ptr: *const u32,uint32x4x3_t,Load single 3-element structure and replicate to all lanes of three registers -FALSE,vld3q_dup_u64,ptr: *const u64,uint64x2x3_t,Load single 3-element structure and replicate to all lanes of three registers -FALSE,vld3q_dup_u8,ptr: *const u8,uint8x16x3_t,Load single 3-element structure and replicate to all lanes of three registers -FALSE,vld3q_f16,ptr: *const float16_t,float16x8x3_t,Load multiple 3-element structures to three registers -FALSE,vld3q_f32,ptr: *const f32,float32x4x3_t,Load multiple 3-element structures to three registers -FALSE,vld3q_f64,ptr: *const float64_t,float64x2x3_t,Load multiple 3-element structures to three registers -FALSE,vld3q_lane_bf16,"ptr: *const bfloat16_t, src: bfloat16x8x3_t, lane: const int",bfloat16x8x3_t,Load multiple 3-element structures to three registers -FALSE,vld3q_lane_f16,"ptr: *const float16_t, src: float16x8x3_t, lane: const int",float16x8x3_t,Load multiple 3-element structures to three registers -FALSE,vld3q_lane_f32,"ptr: *const f32, src: float32x4x3_t, lane: const int",float32x4x3_t,Load multiple 3-element structures to three registers -FALSE,vld3q_lane_f64,"ptr: *const float64_t, src: float64x2x3_t, lane: const int",float64x2x3_t,Load multiple 3-element structures to three registers -FALSE,vld3q_lane_p16,"ptr: *const poly16_t, src: poly16x8x3_t, lane: const int",poly16x8x3_t,Load multiple 3-element structures to three registers -FALSE,vld3q_lane_p64,"ptr: *const poly64_t, src: poly64x2x3_t, lane: const int",poly64x2x3_t,Load multiple 3-element structures to three registers -FALSE,vld3q_lane_p8,"ptr: *const poly8_t, src: poly8x16x3_t, lane: const int",poly8x16x3_t,Load multiple 3-element structures to three registers -FALSE,vld3q_lane_s16,"ptr: *const i16, src: int16x8x3_t, lane: const int",int16x8x3_t,Load multiple 3-element structures to three registers -FALSE,vld3q_lane_s32,"ptr: *const i32, src: int32x4x3_t, lane: const int",int32x4x3_t,Load multiple 3-element structures to three registers -FALSE,vld3q_lane_s64,"ptr: *const i64, src: int64x2x3_t, lane: const int",int64x2x3_t,Load multiple 3-element structures to three registers -FALSE,vld3q_lane_s8,"ptr: *const i8, src: int8x16x3_t, lane: const int",int8x16x3_t,Load multiple 3-element structures to three registers -FALSE,vld3q_lane_u16,"ptr: *const u16, src: uint16x8x3_t, lane: const int",uint16x8x3_t,Load multiple 3-element structures to three registers -FALSE,vld3q_lane_u32,"ptr: *const u32, src: uint32x4x3_t, lane: const int",uint32x4x3_t,Load multiple 3-element structures to three registers -FALSE,vld3q_lane_u64,"ptr: *const u64, src: uint64x2x3_t, lane: const int",uint64x2x3_t,Load multiple 3-element structures to three registers -FALSE,vld3q_lane_u8,"ptr: *const u8, src: uint8x16x3_t, lane: const int",uint8x16x3_t,Load multiple 3-element structures to three registers -FALSE,vld3q_p16,ptr: *const poly16_t,poly16x8x3_t,Load multiple 3-element structures to three registers -FALSE,vld3q_p64,ptr: *const poly64_t,poly64x2x3_t,Load multiple 3-element structures to three registers -FALSE,vld3q_p8,ptr: *const poly8_t,poly8x16x3_t,Load multiple 3-element structures to three registers -FALSE,vld3q_s16,ptr: *const i16,int16x8x3_t,Load multiple 3-element structures to three registers -FALSE,vld3q_s32,ptr: *const i32,int32x4x3_t,Load multiple 3-element structures to three registers -FALSE,vld3q_s64,ptr: *const i64,int64x2x3_t,Load multiple 3-element structures to three registers -FALSE,vld3q_s8,ptr: *const i8,int8x16x3_t,Load multiple 3-element structures to three registers -FALSE,vld3q_u16,ptr: *const u16,uint16x8x3_t,Load multiple 3-element structures to three registers -FALSE,vld3q_u32,ptr: *const u32,uint32x4x3_t,Load multiple 3-element structures to three registers -FALSE,vld3q_u64,ptr: *const u64,uint64x2x3_t,Load multiple 3-element structures to three registers -FALSE,vld3q_u8,ptr: *const u8,uint8x16x3_t,Load multiple 3-element structures to three registers -FALSE,vld4_bf16,ptr: *const bfloat16_t,bfloat16x4x4_t,Load multiple 4-element structures to four registers -FALSE,vld4_dup_bf16,ptr: *const bfloat16_t,bfloat16x4x4_t,Load single 4-element structure and replicate to all lanes of four registers -FALSE,vld4_dup_f16,ptr: *const float16_t,float16x4x4_t,Load single 4-element structure and replicate to all lanes of four registers -FALSE,vld4_dup_f32,ptr: *const f32,float32x2x4_t,Load single 4-element structure and replicate to all lanes of four registers -FALSE,vld4_dup_f64,ptr: *const float64_t,float64x1x4_t,Load single 4-element structure and replicate to all lanes of four registers -FALSE,vld4_dup_p16,ptr: *const poly16_t,poly16x4x4_t,Load single 4-element structure and replicate to all lanes of four registers -FALSE,vld4_dup_p64,ptr: *const poly64_t,poly64x1x4_t,Load single 4-element structure and replicate to all lanes of four registers -FALSE,vld4_dup_p8,ptr: *const poly8_t,poly8x8x4_t,Load single 4-element structure and replicate to all lanes of four registers -FALSE,vld4_dup_s16,ptr: *const i16,int16x4x4_t,Load single 4-element structure and replicate to all lanes of four registers -FALSE,vld4_dup_s32,ptr: *const i32,int32x2x4_t,Load single 4-element structure and replicate to all lanes of four registers -FALSE,vld4_dup_s64,ptr: *const i64,int64x1x4_t,Load single 4-element structure and replicate to all lanes of four registers -FALSE,vld4_dup_s8,ptr: *const i8,int8x8x4_t,Load single 4-element structure and replicate to all lanes of four registers -FALSE,vld4_dup_u16,ptr: *const u16,uint16x4x4_t,Load single 4-element structure and replicate to all lanes of four registers -FALSE,vld4_dup_u32,ptr: *const u32,uint32x2x4_t,Load single 4-element structure and replicate to all lanes of four registers -FALSE,vld4_dup_u64,ptr: *const u64,uint64x1x4_t,Load single 4-element structure and replicate to all lanes of four registers -FALSE,vld4_dup_u8,ptr: *const u8,uint8x8x4_t,Load single 4-element structure and replicate to all lanes of four registers -FALSE,vld4_f16,ptr: *const float16_t,float16x4x4_t,Load multiple 4-element structures to four registers -FALSE,vld4_f32,ptr: *const f32,float32x2x4_t,Load multiple 4-element structures to four registers -FALSE,vld4_f64,ptr: *const float64_t,float64x1x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld4_lane_bf16,"ptr: *const bfloat16_t, src: bfloat16x4x4_t, lane: const int",bfloat16x4x4_t,Load multiple 4-element structures to four registers -FALSE,vld4_lane_f16,"ptr: *const float16_t, src: float16x4x4_t, lane: const int",float16x4x4_t,Load multiple 4-element structures to four registers -FALSE,vld4_lane_f32,"ptr: *const f32, src: float32x2x4_t, lane: const int",float32x2x4_t,Load multiple 4-element structures to four registers -FALSE,vld4_lane_f64,"ptr: *const float64_t, src: float64x1x4_t, lane: const int",float64x1x4_t,Load multiple 4-element structures to four registers -FALSE,vld4_lane_p16,"ptr: *const poly16_t, src: poly16x4x4_t, lane: const int",poly16x4x4_t,Load multiple 4-element structures to four registers -FALSE,vld4_lane_p64,"ptr: *const poly64_t, src: poly64x1x4_t, lane: const int",poly64x1x4_t,Load multiple 4-element structures to four registers -FALSE,vld4_lane_p8,"ptr: *const poly8_t, src: poly8x8x4_t, lane: const int",poly8x8x4_t,Load multiple 4-element structures to four registers -FALSE,vld4_lane_s16,"ptr: *const i16, src: int16x4x4_t, lane: const int",int16x4x4_t,Load multiple 4-element structures to four registers -FALSE,vld4_lane_s32,"ptr: *const i32, src: int32x2x4_t, lane: const int",int32x2x4_t,Load multiple 4-element structures to four registers -FALSE,vld4_lane_s64,"ptr: *const i64, src: int64x1x4_t, lane: const int",int64x1x4_t,Load multiple 4-element structures to four registers -FALSE,vld4_lane_s8,"ptr: *const i8, src: int8x8x4_t, lane: const int",int8x8x4_t,Load multiple 4-element structures to four registers -FALSE,vld4_lane_u16,"ptr: *const u16, src: uint16x4x4_t, lane: const int",uint16x4x4_t,Load multiple 4-element structures to four registers -FALSE,vld4_lane_u32,"ptr: *const u32, src: uint32x2x4_t, lane: const int",uint32x2x4_t,Load multiple 4-element structures to four registers -FALSE,vld4_lane_u64,"ptr: *const u64, src: uint64x1x4_t, lane: const int",uint64x1x4_t,Load multiple 4-element structures to four registers -FALSE,vld4_lane_u8,"ptr: *const u8, src: uint8x8x4_t, lane: const int",uint8x8x4_t,Load multiple 4-element structures to four registers -FALSE,vld4_p16,ptr: *const poly16_t,poly16x4x4_t,Load multiple 4-element structures to four registers -FALSE,vld4_p64,ptr: *const poly64_t,poly64x1x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld4_p8,ptr: *const poly8_t,poly8x8x4_t,Load multiple 4-element structures to four registers -FALSE,vld4_s16,ptr: *const i16,int16x4x4_t,Load multiple 4-element structures to four registers -FALSE,vld4_s32,ptr: *const i32,int32x2x4_t,Load multiple 4-element structures to four registers -FALSE,vld4_s64,ptr: *const i64,int64x1x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld4_s8,ptr: *const i8,int8x8x4_t,Load multiple 4-element structures to four registers -FALSE,vld4_u16,ptr: *const u16,uint16x4x4_t,Load multiple 4-element structures to four registers -FALSE,vld4_u32,ptr: *const u32,uint32x2x4_t,Load multiple 4-element structures to four registers -FALSE,vld4_u64,ptr: *const u64,uint64x1x4_t,"Load multiple single-element structures to one, two, three, or four registers" -FALSE,vld4_u8,ptr: *const u8,uint8x8x4_t,Load multiple 4-element structures to four registers -FALSE,vld4q_bf16,ptr: *const bfloat16_t,bfloat16x8x4_t,Load multiple 4-element structures to four registers -FALSE,vld4q_dup_bf16,ptr: *const bfloat16_t,bfloat16x8x4_t,Load single 4-element structure and replicate to all lanes of four registers -FALSE,vld4q_dup_f16,ptr: *const float16_t,float16x8x4_t,Load single 4-element structure and replicate to all lanes of four registers -FALSE,vld4q_dup_f32,ptr: *const f32,float32x4x4_t,Load single 4-element structure and replicate to all lanes of four registers -FALSE,vld4q_dup_f64,ptr: *const float64_t,float64x2x4_t,Load single 4-element structure and replicate to all lanes of four registers -FALSE,vld4q_dup_p16,ptr: *const poly16_t,poly16x8x4_t,Load single 4-element structure and replicate to all lanes of four registers -FALSE,vld4q_dup_p64,ptr: *const poly64_t,poly64x2x4_t,Load single 4-element structure and replicate to all lanes of four registers -FALSE,vld4q_dup_p8,ptr: *const poly8_t,poly8x16x4_t,Load single 4-element structure and replicate to all lanes of four registers -FALSE,vld4q_dup_s16,ptr: *const i16,int16x8x4_t,Load single 4-element structure and replicate to all lanes of four registers -FALSE,vld4q_dup_s32,ptr: *const i32,int32x4x4_t,Load single 4-element structure and replicate to all lanes of four registers -FALSE,vld4q_dup_s64,ptr: *const i64,int64x2x4_t,Load single 4-element structure and replicate to all lanes of four registers -FALSE,vld4q_dup_s8,ptr: *const i8,int8x16x4_t,Load single 4-element structure and replicate to all lanes of four registers -FALSE,vld4q_dup_u16,ptr: *const u16,uint16x8x4_t,Load single 4-element structure and replicate to all lanes of four registers -FALSE,vld4q_dup_u32,ptr: *const u32,uint32x4x4_t,Load single 4-element structure and replicate to all lanes of four registers -FALSE,vld4q_dup_u64,ptr: *const u64,uint64x2x4_t,Load single 4-element structure and replicate to all lanes of four registers -FALSE,vld4q_dup_u8,ptr: *const u8,uint8x16x4_t,Load single 4-element structure and replicate to all lanes of four registers -FALSE,vld4q_f16,ptr: *const float16_t,float16x8x4_t,Load multiple 4-element structures to four registers -FALSE,vld4q_f32,ptr: *const f32,float32x4x4_t,Load multiple 4-element structures to four registers -FALSE,vld4q_f64,ptr: *const float64_t,float64x2x4_t,Load multiple 4-element structures to four registers -FALSE,vld4q_lane_bf16,"ptr: *const bfloat16_t, src: bfloat16x8x4_t, lane: const int",bfloat16x8x4_t,Load multiple 4-element structures to four registers -FALSE,vld4q_lane_f16,"ptr: *const float16_t, src: float16x8x4_t, lane: const int",float16x8x4_t,Load multiple 4-element structures to four registers -FALSE,vld4q_lane_f32,"ptr: *const f32, src: float32x4x4_t, lane: const int",float32x4x4_t,Load multiple 4-element structures to four registers -FALSE,vld4q_lane_f64,"ptr: *const float64_t, src: float64x2x4_t, lane: const int",float64x2x4_t,Load multiple 4-element structures to four registers -FALSE,vld4q_lane_p16,"ptr: *const poly16_t, src: poly16x8x4_t, lane: const int",poly16x8x4_t,Load multiple 4-element structures to four registers -FALSE,vld4q_lane_p64,"ptr: *const poly64_t, src: poly64x2x4_t, lane: const int",poly64x2x4_t,Load multiple 4-element structures to four registers -FALSE,vld4q_lane_p8,"ptr: *const poly8_t, src: poly8x16x4_t, lane: const int",poly8x16x4_t,Load multiple 4-element structures to four registers -FALSE,vld4q_lane_s16,"ptr: *const i16, src: int16x8x4_t, lane: const int",int16x8x4_t,Load multiple 4-element structures to four registers -FALSE,vld4q_lane_s32,"ptr: *const i32, src: int32x4x4_t, lane: const int",int32x4x4_t,Load multiple 4-element structures to four registers -FALSE,vld4q_lane_s64,"ptr: *const i64, src: int64x2x4_t, lane: const int",int64x2x4_t,Load multiple 4-element structures to four registers -FALSE,vld4q_lane_s8,"ptr: *const i8, src: int8x16x4_t, lane: const int",int8x16x4_t,Load multiple 4-element structures to four registers -FALSE,vld4q_lane_u16,"ptr: *const u16, src: uint16x8x4_t, lane: const int",uint16x8x4_t,Load multiple 4-element structures to four registers -FALSE,vld4q_lane_u32,"ptr: *const u32, src: uint32x4x4_t, lane: const int",uint32x4x4_t,Load multiple 4-element structures to four registers -FALSE,vld4q_lane_u64,"ptr: *const u64, src: uint64x2x4_t, lane: const int",uint64x2x4_t,Load multiple 4-element structures to four registers -FALSE,vld4q_lane_u8,"ptr: *const u8, src: uint8x16x4_t, lane: const int",uint8x16x4_t,Load multiple 4-element structures to four registers -FALSE,vld4q_p16,ptr: *const poly16_t,poly16x8x4_t,Load multiple 4-element structures to four registers -FALSE,vld4q_p64,ptr: *const poly64_t,poly64x2x4_t,Load multiple 4-element structures to four registers -FALSE,vld4q_p8,ptr: *const poly8_t,poly8x16x4_t,Load multiple 4-element structures to four registers -FALSE,vld4q_s16,ptr: *const i16,int16x8x4_t,Load multiple 4-element structures to four registers -FALSE,vld4q_s32,ptr: *const i32,int32x4x4_t,Load multiple 4-element structures to four registers -FALSE,vld4q_s64,ptr: *const i64,int64x2x4_t,Load multiple 4-element structures to four registers -FALSE,vld4q_s8,ptr: *const i8,int8x16x4_t,Load multiple 4-element structures to four registers -FALSE,vld4q_u16,ptr: *const u16,uint16x8x4_t,Load multiple 4-element structures to four registers -FALSE,vld4q_u32,ptr: *const u32,uint32x4x4_t,Load multiple 4-element structures to four registers -FALSE,vld4q_u64,ptr: *const u64,uint64x2x4_t,Load multiple 4-element structures to four registers -FALSE,vld4q_u8,ptr: *const u8,uint8x16x4_t,Load multiple 4-element structures to four registers -FALSE,vldrq_p128,ptr: *const poly128_t,poly128_t,Load SIMD&FP register (immediate offset) -FALSE,vmax_f16,"a: float16x4_t, b: float16x4_t",float16x4_t,Floating-point maximum -TRUE,vmax_f32,"a: float32x2_t, b: float32x2_t",float32x2_t,Floating-point maximum -TRUE,vmax_f64,"a: float64x1_t, b: float64x1_t",float64x1_t,Floating-point maximum -TRUE,vmax_s16,"a: int16x4_t, b: int16x4_t",int16x4_t,Signed maximum -TRUE,vmax_s32,"a: int32x2_t, b: int32x2_t",int32x2_t,Signed maximum -TRUE,vmax_s8,"a: int8x8_t, b: int8x8_t",int8x8_t,Signed maximum -TRUE,vmax_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4_t,Unsigned maximum -TRUE,vmax_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2_t,Unsigned maximum -TRUE,vmax_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,Unsigned maximum -FALSE,vmaxh_f16,"a: float16_t, b: float16_t",float16_t,Floating-point maximum -FALSE,vmaxnm_f16,"a: float16x4_t, b: float16x4_t",float16x4_t,Floating-point maximum number -TRUE,vmaxnm_f32,"a: float32x2_t, b: float32x2_t",float32x2_t,Floating-point maximum number -TRUE,vmaxnm_f64,"a: float64x1_t, b: float64x1_t",float64x1_t,Floating-point maximum number -FALSE,vmaxnmh_f16,"a: float16_t, b: float16_t",float16_t,Floating-point maximum number -FALSE,vmaxnmq_f16,"a: float16x8_t, b: float16x8_t",float16x8_t,Floating-point maximum number -TRUE,vmaxnmq_f32,"a: float32x4_t, b: float32x4_t",float32x4_t,Floating-point maximum number -TRUE,vmaxnmq_f64,"a: float64x2_t, b: float64x2_t",float64x2_t,Floating-point maximum number -FALSE,vmaxnmv_f16,a: float16x4_t,float16_t,Floating-point maximum number pairwise -FALSE,vmaxnmv_f32,a: float32x2_t,f32,Floating-point maximum number pairwise -FALSE,vmaxnmvq_f16,a: float16x8_t,float16_t,Floating-point maximum number pairwise -FALSE,vmaxnmvq_f32,a: float32x4_t,f32,Floating-point maximum number across vector -FALSE,vmaxnmvq_f64,a: float64x2_t,float64_t,Floating-point maximum number pairwise -FALSE,vmaxq_f16,"a: float16x8_t, b: float16x8_t",float16x8_t,Floating-point maximum -TRUE,vmaxq_f32,"a: float32x4_t, b: float32x4_t",float32x4_t,Floating-point maximum -TRUE,vmaxq_f64,"a: float64x2_t, b: float64x2_t",float64x2_t,Floating-point maximum -TRUE,vmaxq_s16,"a: int16x8_t, b: int16x8_t",int16x8_t,Signed maximum -TRUE,vmaxq_s32,"a: int32x4_t, b: int32x4_t",int32x4_t,Signed maximum -TRUE,vmaxq_s8,"a: int8x16_t, b: int8x16_t",int8x16_t,Signed maximum -TRUE,vmaxq_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8_t,Unsigned maximum -TRUE,vmaxq_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,Unsigned maximum -TRUE,vmaxq_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16_t,Unsigned maximum -FALSE,vmaxv_f16,a: float16x4_t,float16_t,Floating-point maximum pairwise -TRUE,vmaxv_f32,a: float32x2_t,f32,Floating-point maximum pairwise -TRUE,vmaxv_s16,a: int16x4_t,i16,Signed maximum across vector -TRUE,vmaxv_s32,a: int32x2_t,i32,Signed maximum pairwise -TRUE,vmaxv_s8,a: int8x8_t,i8,Signed maximum across vector -TRUE,vmaxv_u16,a: uint16x4_t,u16,Unsigned maximum across vector -TRUE,vmaxv_u32,a: uint32x2_t,u32,Unsigned maximum pairwise -TRUE,vmaxv_u8,a: uint8x8_t,u8,Unsigned maximum across vector -FALSE,vmaxvq_f16,a: float16x8_t,float16_t,Floating-point maximum pairwise -TRUE,vmaxvq_f32,a: float32x4_t,f32,Floating-point maximum across vector -TRUE,vmaxvq_f64,a: float64x2_t,float64_t,Floating-point maximum pairwise -TRUE,vmaxvq_s16,a: int16x8_t,i16,Signed maximum across vector -TRUE,vmaxvq_s32,a: int32x4_t,i32,Signed maximum across vector -TRUE,vmaxvq_s8,a: int8x16_t,i8,Signed maximum across vector -TRUE,vmaxvq_u16,a: uint16x8_t,u16,Unsigned maximum across vector -TRUE,vmaxvq_u32,a: uint32x4_t,u32,Unsigned maximum across vector -TRUE,vmaxvq_u8,a: uint8x16_t,u8,Unsigned maximum across vector -FALSE,vmin_f16,"a: float16x4_t, b: float16x4_t",float16x4_t,Floating-point minimum -TRUE,vmin_f32,"a: float32x2_t, b: float32x2_t",float32x2_t,Floating-point minimum -TRUE,vmin_f64,"a: float64x1_t, b: float64x1_t",float64x1_t,Floating-point minimum -TRUE,vmin_s16,"a: int16x4_t, b: int16x4_t",int16x4_t,Signed minimum -TRUE,vmin_s32,"a: int32x2_t, b: int32x2_t",int32x2_t,Signed minimum -TRUE,vmin_s8,"a: int8x8_t, b: int8x8_t",int8x8_t,Signed minimum -TRUE,vmin_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4_t,Unsigned minimum -TRUE,vmin_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2_t,Unsigned minimum -TRUE,vmin_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,Unsigned minimum -FALSE,vminh_f16,"a: float16_t, b: float16_t",float16_t,Floating-point minimum -FALSE,vminnm_f16,"a: float16x4_t, b: float16x4_t",float16x4_t,Floating-point minimum number -FALSE,vminnm_f32,"a: float32x2_t, b: float32x2_t",float32x2_t,Floating-point minimum number -FALSE,vminnm_f64,"a: float64x1_t, b: float64x1_t",float64x1_t,Floating-point minimum number -FALSE,vminnmh_f16,"a: float16_t, b: float16_t",float16_t,Floating-point minimum number -FALSE,vminnmq_f16,"a: float16x8_t, b: float16x8_t",float16x8_t,Floating-point minimum number -FALSE,vminnmq_f32,"a: float32x4_t, b: float32x4_t",float32x4_t,Floating-point minimum number -FALSE,vminnmq_f64,"a: float64x2_t, b: float64x2_t",float64x2_t,Floating-point minimum number -FALSE,vminnmv_f16,a: float16x4_t,float16_t,Floating-point minimum number pairwise -FALSE,vminnmv_f32,a: float32x2_t,f32,Floating-point minimum number pairwise -FALSE,vminnmvq_f16,a: float16x8_t,float16_t,Floating-point minimum number pairwise -FALSE,vminnmvq_f32,a: float32x4_t,f32,Floating-point minimum number across vector -FALSE,vminnmvq_f64,a: float64x2_t,float64_t,Floating-point minimum number pairwise -FALSE,vminq_f16,"a: float16x8_t, b: float16x8_t",float16x8_t,Floating-point minimum -TRUE,vminq_f32,"a: float32x4_t, b: float32x4_t",float32x4_t,Floating-point minimum -FALSE,vminq_f64,"a: float64x2_t, b: float64x2_t",float64x2_t,Floating-point minimum -TRUE,vminq_s16,"a: int16x8_t, b: int16x8_t",int16x8_t,Signed minimum -TRUE,vminq_s32,"a: int32x4_t, b: int32x4_t",int32x4_t,Signed minimum -TRUE,vminq_s8,"a: int8x16_t, b: int8x16_t",int8x16_t,Signed minimum -TRUE,vminq_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8_t,Unsigned minimum -TRUE,vminq_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,Unsigned minimum -TRUE,vminq_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16_t,Unsigned minimum -FALSE,vminv_f16,a: float16x4_t,float16_t,Floating-point minimum pairwise -TRUE,vminv_f32,a: float32x2_t,f32,Floating-point minimum pairwise -TRUE,vminv_s16,a: int16x4_t,i16,Signed minimum across vector -TRUE,vminv_s32,a: int32x2_t,i32,Signed minimum pairwise -TRUE,vminv_s8,a: int8x8_t,i8,Signed minimum across vector -TRUE,vminv_u16,a: uint16x4_t,u16,Unsigned minimum across vector -TRUE,vminv_u32,a: uint32x2_t,u32,Unsigned minimum pairwise -TRUE,vminv_u8,a: uint8x8_t,u8,Unsigned minimum across vector -FALSE,vminvq_f16,a: float16x8_t,float16_t,Floating-point minimum pairwise -TRUE,vminvq_f32,a: float32x4_t,f32,Floating-point minimum across vector -TRUE,vminvq_f64,a: float64x2_t,float64_t,Floating-point minimum pairwise -TRUE,vminvq_s16,a: int16x8_t,i16,Signed minimum across vector -TRUE,vminvq_s32,a: int32x4_t,i32,Signed minimum across vector -TRUE,vminvq_s8,a: int8x16_t,i8,Signed minimum across vector -TRUE,vminvq_u16,a: uint16x8_t,u16,Unsigned minimum across vector -TRUE,vminvq_u32,a: uint32x4_t,u32,Unsigned minimum across vector -TRUE,vminvq_u8,a: uint8x16_t,u8,Unsigned minimum across vector -TRUE,vmla_f32,"a: float32x2_t, b: float32x2_t, c: float32x2_t",float32x2_t,Floating-point multiply-add to accumulator -TRUE,vmla_f64,"a: float64x1_t, b: float64x1_t, c: float64x1_t",float64x1_t,Floating-point multiply-add to accumulator -FALSE,vmla_lane_f32,"a: float32x2_t, b: float32x2_t, v: float32x2_t, lane: const int",float32x2_t,Vector multiply accumulate with scalar -FALSE,vmla_lane_s16,"a: int16x4_t, b: int16x4_t, v: int16x4_t, lane: const int",int16x4_t,Vector multiply accumulate with scalar -FALSE,vmla_lane_s32,"a: int32x2_t, b: int32x2_t, v: int32x2_t, lane: const int",int32x2_t,Vector multiply accumulate with scalar -FALSE,vmla_lane_u16,"a: uint16x4_t, b: uint16x4_t, v: uint16x4_t, lane: const int",uint16x4_t,Vector multiply accumulate with scalar -FALSE,vmla_lane_u32,"a: uint32x2_t, b: uint32x2_t, v: uint32x2_t, lane: const int",uint32x2_t,Vector multiply accumulate with scalar -FALSE,vmla_laneq_f32,"a: float32x2_t, b: float32x2_t, v: float32x4_t, lane: const int",float32x2_t,Multiply-Add to accumulator -FALSE,vmla_laneq_s16,"a: int16x4_t, b: int16x4_t, v: int16x8_t, lane: const int",int16x4_t,Multiply-add to accumulator -FALSE,vmla_laneq_s32,"a: int32x2_t, b: int32x2_t, v: int32x4_t, lane: const int",int32x2_t,Multiply-add to accumulator -FALSE,vmla_laneq_u16,"a: uint16x4_t, b: uint16x4_t, v: uint16x8_t, lane: const int",uint16x4_t,Multiply-add to accumulator -FALSE,vmla_laneq_u32,"a: uint32x2_t, b: uint32x2_t, v: uint32x4_t, lane: const int",uint32x2_t,Multiply-add to accumulator -FALSE,vmla_n_f32,"a: float32x2_t, b: float32x2_t, c: f32",float32x2_t,Vector multiply accumulate with scalar -FALSE,vmla_n_s16,"a: int16x4_t, b: int16x4_t, c: i16",int16x4_t,Vector multiply accumulate with scalar -FALSE,vmla_n_s32,"a: int32x2_t, b: int32x2_t, c: i32",int32x2_t,Vector multiply accumulate with scalar -FALSE,vmla_n_u16,"a: uint16x4_t, b: uint16x4_t, c: u16",uint16x4_t,Vector multiply accumulate with scalar -FALSE,vmla_n_u32,"a: uint32x2_t, b: uint32x2_t, c: u32",uint32x2_t,Vector multiply accumulate with scalar -TRUE,vmla_s16,"a: int16x4_t, b: int16x4_t, c: int16x4_t",int16x4_t,Multiply-add to accumulator -TRUE,vmla_s32,"a: int32x2_t, b: int32x2_t, c: int32x2_t",int32x2_t,Multiply-add to accumulator -TRUE,vmla_s8,"a: int8x8_t, b: int8x8_t, c: int8x8_t",int8x8_t,Multiply-add to accumulator -TRUE,vmla_u16,"a: uint16x4_t, b: uint16x4_t, c: uint16x4_t",uint16x4_t,Multiply-add to accumulator -TRUE,vmla_u32,"a: uint32x2_t, b: uint32x2_t, c: uint32x2_t",uint32x2_t,Multiply-add to accumulator -TRUE,vmla_u8,"a: uint8x8_t, b: uint8x8_t, c: uint8x8_t",uint8x8_t,Multiply-add to accumulator -FALSE,vmlal_high_lane_s16,"a: int32x4_t, b: int16x8_t, v: int16x4_t, lane: const int",int32x4_t,Signed multiply-add long -FALSE,vmlal_high_lane_s32,"a: int64x2_t, b: int32x4_t, v: int32x2_t, lane: const int",int64x2_t,Signed multiply-add long -FALSE,vmlal_high_lane_u16,"a: uint32x4_t, b: uint16x8_t, v: uint16x4_t, lane: const int",uint32x4_t,Unsigned multiply-add long -FALSE,vmlal_high_lane_u32,"a: uint64x2_t, b: uint32x4_t, v: uint32x2_t, lane: const int",uint64x2_t,Unsigned multiply-add long -FALSE,vmlal_high_laneq_s16,"a: int32x4_t, b: int16x8_t, v: int16x8_t, lane: const int",int32x4_t,Signed multiply-add long -FALSE,vmlal_high_laneq_s32,"a: int64x2_t, b: int32x4_t, v: int32x4_t, lane: const int",int64x2_t,Signed multiply-add long -FALSE,vmlal_high_laneq_u16,"a: uint32x4_t, b: uint16x8_t, v: uint16x8_t, lane: const int",uint32x4_t,Unsigned multiply-add long -FALSE,vmlal_high_laneq_u32,"a: uint64x2_t, b: uint32x4_t, v: uint32x4_t, lane: const int",uint64x2_t,Unsigned multiply-add long -FALSE,vmlal_high_n_s16,"a: int32x4_t, b: int16x8_t, c: i16",int32x4_t,Signed multiply-add long -FALSE,vmlal_high_n_s32,"a: int64x2_t, b: int32x4_t, c: i32",int64x2_t,Signed multiply-add long -FALSE,vmlal_high_n_u16,"a: uint32x4_t, b: uint16x8_t, c: u16",uint32x4_t,Unsigned multiply-add long -FALSE,vmlal_high_n_u32,"a: uint64x2_t, b: uint32x4_t, c: u32",uint64x2_t,Unsigned multiply-add long -TRUE,vmlal_high_s16,"a: int32x4_t, b: int16x8_t, c: int16x8_t",int32x4_t,Signed multiply-add long -TRUE,vmlal_high_s32,"a: int64x2_t, b: int32x4_t, c: int32x4_t",int64x2_t,Signed multiply-add long -TRUE,vmlal_high_s8,"a: int16x8_t, b: int8x16_t, c: int8x16_t",int16x8_t,Signed multiply-add long -TRUE,vmlal_high_u16,"a: uint32x4_t, b: uint16x8_t, c: uint16x8_t",uint32x4_t,Unsigned multiply-add long -TRUE,vmlal_high_u32,"a: uint64x2_t, b: uint32x4_t, c: uint32x4_t",uint64x2_t,Unsigned multiply-add long -TRUE,vmlal_high_u8,"a: uint16x8_t, b: uint8x16_t, c: uint8x16_t",uint16x8_t,Unsigned multiply-add long -FALSE,vmlal_lane_s16,"a: int32x4_t, b: int16x4_t, v: int16x4_t, lane: const int",int32x4_t,Vector widening multiply accumulate with scalar -FALSE,vmlal_lane_s32,"a: int64x2_t, b: int32x2_t, v: int32x2_t, lane: const int",int64x2_t,Vector widening multiply accumulate with scalar -FALSE,vmlal_lane_u16,"a: uint32x4_t, b: uint16x4_t, v: uint16x4_t, lane: const int",uint32x4_t,Vector widening multiply accumulate with scalar -FALSE,vmlal_lane_u32,"a: uint64x2_t, b: uint32x2_t, v: uint32x2_t, lane: const int",uint64x2_t,Vector widening multiply accumulate with scalar -FALSE,vmlal_laneq_s16,"a: int32x4_t, b: int16x4_t, v: int16x8_t, lane: const int",int32x4_t,Signed multiply-add long -FALSE,vmlal_laneq_s32,"a: int64x2_t, b: int32x2_t, v: int32x4_t, lane: const int",int64x2_t,Signed multiply-add long -FALSE,vmlal_laneq_u16,"a: uint32x4_t, b: uint16x4_t, v: uint16x8_t, lane: const int",uint32x4_t,Unsigned multiply-add long -FALSE,vmlal_laneq_u32,"a: uint64x2_t, b: uint32x2_t, v: uint32x4_t, lane: const int",uint64x2_t,Unsigned multiply-add long -FALSE,vmlal_n_s16,"a: int32x4_t, b: int16x4_t, c: i16",int32x4_t,Vector widening multiply accumulate with scalar -FALSE,vmlal_n_s32,"a: int64x2_t, b: int32x2_t, c: i32",int64x2_t,Vector widening multiply accumulate with scalar -FALSE,vmlal_n_u16,"a: uint32x4_t, b: uint16x4_t, c: u16",uint32x4_t,Vector widening multiply accumulate with scalar -FALSE,vmlal_n_u32,"a: uint64x2_t, b: uint32x2_t, c: u32",uint64x2_t,Vector widening multiply accumulate with scalar -TRUE,vmlal_s16,"a: int32x4_t, b: int16x4_t, c: int16x4_t",int32x4_t,Signed multiply-add long -TRUE,vmlal_s32,"a: int64x2_t, b: int32x2_t, c: int32x2_t",int64x2_t,Signed multiply-add long -TRUE,vmlal_s8,"a: int16x8_t, b: int8x8_t, c: int8x8_t",int16x8_t,Signed multiply-add long -TRUE,vmlal_u16,"a: uint32x4_t, b: uint16x4_t, c: uint16x4_t",uint32x4_t,Unsigned multiply-add long -TRUE,vmlal_u32,"a: uint64x2_t, b: uint32x2_t, c: uint32x2_t",uint64x2_t,Unsigned multiply-add long -TRUE,vmlal_u8,"a: uint16x8_t, b: uint8x8_t, c: uint8x8_t",uint16x8_t,Unsigned multiply-add long -TRUE,vmlaq_f32,"a: float32x4_t, b: float32x4_t, c: float32x4_t",float32x4_t,Floating-point multiply-add to accumulator -TRUE,vmlaq_f64,"a: float64x2_t, b: float64x2_t, c: float64x2_t",float64x2_t,Floating-point multiply-add to accumulator -FALSE,vmlaq_lane_f32,"a: float32x4_t, b: float32x4_t, v: float32x2_t, lane: const int",float32x4_t,Vector multiply accumulate with scalar -FALSE,vmlaq_lane_s16,"a: int16x8_t, b: int16x8_t, v: int16x4_t, lane: const int",int16x8_t,Vector multiply accumulate with scalar -FALSE,vmlaq_lane_s32,"a: int32x4_t, b: int32x4_t, v: int32x2_t, lane: const int",int32x4_t,Vector multiply accumulate with scalar -FALSE,vmlaq_lane_u16,"a: uint16x8_t, b: uint16x8_t, v: uint16x4_t, lane: const int",uint16x8_t,Vector multiply accumulate with scalar -FALSE,vmlaq_lane_u32,"a: uint32x4_t, b: uint32x4_t, v: uint32x2_t, lane: const int",uint32x4_t,Vector multiply accumulate with scalar -FALSE,vmlaq_laneq_f32,"a: float32x4_t, b: float32x4_t, v: float32x4_t, lane: const int",float32x4_t,Multiply-Add to accumulator -FALSE,vmlaq_laneq_s16,"a: int16x8_t, b: int16x8_t, v: int16x8_t, lane: const int",int16x8_t,Multiply-add to accumulator -FALSE,vmlaq_laneq_s32,"a: int32x4_t, b: int32x4_t, v: int32x4_t, lane: const int",int32x4_t,Multiply-add to accumulator -FALSE,vmlaq_laneq_u16,"a: uint16x8_t, b: uint16x8_t, v: uint16x8_t, lane: const int",uint16x8_t,Multiply-add to accumulator -FALSE,vmlaq_laneq_u32,"a: uint32x4_t, b: uint32x4_t, v: uint32x4_t, lane: const int",uint32x4_t,Multiply-add to accumulator -FALSE,vmlaq_n_f32,"a: float32x4_t, b: float32x4_t, c: f32",float32x4_t,Vector multiply accumulate with scalar -FALSE,vmlaq_n_s16,"a: int16x8_t, b: int16x8_t, c: i16",int16x8_t,Vector multiply accumulate with scalar -FALSE,vmlaq_n_s32,"a: int32x4_t, b: int32x4_t, c: i32",int32x4_t,Vector multiply accumulate with scalar -FALSE,vmlaq_n_u16,"a: uint16x8_t, b: uint16x8_t, c: u16",uint16x8_t,Vector multiply accumulate with scalar -FALSE,vmlaq_n_u32,"a: uint32x4_t, b: uint32x4_t, c: u32",uint32x4_t,Vector multiply accumulate with scalar -TRUE,vmlaq_s16,"a: int16x8_t, b: int16x8_t, c: int16x8_t",int16x8_t,Multiply-add to accumulator -TRUE,vmlaq_s32,"a: int32x4_t, b: int32x4_t, c: int32x4_t",int32x4_t,Multiply-add to accumulator -TRUE,vmlaq_s8,"a: int8x16_t, b: int8x16_t, c: int8x16_t",int8x16_t,Multiply-add to accumulator -TRUE,vmlaq_u16,"a: uint16x8_t, b: uint16x8_t, c: uint16x8_t",uint16x8_t,Multiply-add to accumulator -TRUE,vmlaq_u32,"a: uint32x4_t, b: uint32x4_t, c: uint32x4_t",uint32x4_t,Multiply-add to accumulator -TRUE,vmlaq_u8,"a: uint8x16_t, b: uint8x16_t, c: uint8x16_t",uint8x16_t,Multiply-add to accumulator -TRUE,vmls_f32,"a: float32x2_t, b: float32x2_t, c: float32x2_t",float32x2_t,Multiply-subtract from accumulator -TRUE,vmls_f64,"a: float64x1_t, b: float64x1_t, c: float64x1_t",float64x1_t,Multiply-subtract from accumulator -FALSE,vmls_lane_f32,"a: float32x2_t, b: float32x2_t, v: float32x2_t, lane: const int",float32x2_t,Vector multiply subtract with scalar -FALSE,vmls_lane_s16,"a: int16x4_t, b: int16x4_t, v: int16x4_t, lane: const int",int16x4_t,Vector multiply subtract with scalar -FALSE,vmls_lane_s32,"a: int32x2_t, b: int32x2_t, v: int32x2_t, lane: const int",int32x2_t,Vector multiply subtract with scalar -FALSE,vmls_lane_u16,"a: uint16x4_t, b: uint16x4_t, v: uint16x4_t, lane: const int",uint16x4_t,Vector multiply subtract with scalar -FALSE,vmls_lane_u32,"a: uint32x2_t, b: uint32x2_t, v: uint32x2_t, lane: const int",uint32x2_t,Vector multiply subtract with scalar -FALSE,vmls_laneq_f32,"a: float32x2_t, b: float32x2_t, v: float32x4_t, lane: const int",float32x2_t,Multiply-subtract from accumulator -FALSE,vmls_laneq_s16,"a: int16x4_t, b: int16x4_t, v: int16x8_t, lane: const int",int16x4_t,Multiply-subtract from accumulator -FALSE,vmls_laneq_s32,"a: int32x2_t, b: int32x2_t, v: int32x4_t, lane: const int",int32x2_t,Multiply-subtract from accumulator -FALSE,vmls_laneq_u16,"a: uint16x4_t, b: uint16x4_t, v: uint16x8_t, lane: const int",uint16x4_t,Multiply-subtract from accumulator -FALSE,vmls_laneq_u32,"a: uint32x2_t, b: uint32x2_t, v: uint32x4_t, lane: const int",uint32x2_t,Multiply-subtract from accumulator -FALSE,vmls_n_f32,"a: float32x2_t, b: float32x2_t, c: f32",float32x2_t,Vector multiply subtract with scalar -FALSE,vmls_n_s16,"a: int16x4_t, b: int16x4_t, c: i16",int16x4_t,Vector multiply subtract with scalar -FALSE,vmls_n_s32,"a: int32x2_t, b: int32x2_t, c: i32",int32x2_t,Vector multiply subtract with scalar -FALSE,vmls_n_u16,"a: uint16x4_t, b: uint16x4_t, c: u16",uint16x4_t,Vector multiply subtract with scalar -FALSE,vmls_n_u32,"a: uint32x2_t, b: uint32x2_t, c: u32",uint32x2_t,Vector multiply subtract with scalar -TRUE,vmls_s16,"a: int16x4_t, b: int16x4_t, c: int16x4_t",int16x4_t,Multiply-subtract from accumulator -TRUE,vmls_s32,"a: int32x2_t, b: int32x2_t, c: int32x2_t",int32x2_t,Multiply-subtract from accumulator -TRUE,vmls_s8,"a: int8x8_t, b: int8x8_t, c: int8x8_t",int8x8_t,Multiply-subtract from accumulator -TRUE,vmls_u16,"a: uint16x4_t, b: uint16x4_t, c: uint16x4_t",uint16x4_t,Multiply-subtract from accumulator -TRUE,vmls_u32,"a: uint32x2_t, b: uint32x2_t, c: uint32x2_t",uint32x2_t,Multiply-subtract from accumulator -TRUE,vmls_u8,"a: uint8x8_t, b: uint8x8_t, c: uint8x8_t",uint8x8_t,Multiply-subtract from accumulator -FALSE,vmlsl_high_lane_s16,"a: int32x4_t, b: int16x8_t, v: int16x4_t, lane: const int",int32x4_t,Signed multiply-subtract long -FALSE,vmlsl_high_lane_s32,"a: int64x2_t, b: int32x4_t, v: int32x2_t, lane: const int",int64x2_t,Signed multiply-subtract long -FALSE,vmlsl_high_lane_u16,"a: uint32x4_t, b: uint16x8_t, v: uint16x4_t, lane: const int",uint32x4_t,Unsigned multiply-subtract long -FALSE,vmlsl_high_lane_u32,"a: uint64x2_t, b: uint32x4_t, v: uint32x2_t, lane: const int",uint64x2_t,Unsigned multiply-subtract long -FALSE,vmlsl_high_laneq_s16,"a: int32x4_t, b: int16x8_t, v: int16x8_t, lane: const int",int32x4_t,Signed multiply-subtract long -FALSE,vmlsl_high_laneq_s32,"a: int64x2_t, b: int32x4_t, v: int32x4_t, lane: const int",int64x2_t,Signed multiply-subtract long -FALSE,vmlsl_high_laneq_u16,"a: uint32x4_t, b: uint16x8_t, v: uint16x8_t, lane: const int",uint32x4_t,Unsigned multiply-subtract long -FALSE,vmlsl_high_laneq_u32,"a: uint64x2_t, b: uint32x4_t, v: uint32x4_t, lane: const int",uint64x2_t,Unsigned multiply-subtract long -FALSE,vmlsl_high_n_s16,"a: int32x4_t, b: int16x8_t, c: i16",int32x4_t,Signed multiply-subtract long -FALSE,vmlsl_high_n_s32,"a: int64x2_t, b: int32x4_t, c: i32",int64x2_t,Signed multiply-subtract long -FALSE,vmlsl_high_n_u16,"a: uint32x4_t, b: uint16x8_t, c: u16",uint32x4_t,Unsigned multiply-subtract long -FALSE,vmlsl_high_n_u32,"a: uint64x2_t, b: uint32x4_t, c: u32",uint64x2_t,Unsigned multiply-subtract long -TRUE,vmlsl_high_s16,"a: int32x4_t, b: int16x8_t, c: int16x8_t",int32x4_t,Signed multiply-subtract long -TRUE,vmlsl_high_s32,"a: int64x2_t, b: int32x4_t, c: int32x4_t",int64x2_t,Signed multiply-subtract long -TRUE,vmlsl_high_s8,"a: int16x8_t, b: int8x16_t, c: int8x16_t",int16x8_t,Signed multiply-subtract long -TRUE,vmlsl_high_u16,"a: uint32x4_t, b: uint16x8_t, c: uint16x8_t",uint32x4_t,Unsigned multiply-subtract long -TRUE,vmlsl_high_u32,"a: uint64x2_t, b: uint32x4_t, c: uint32x4_t",uint64x2_t,Unsigned multiply-subtract long -TRUE,vmlsl_high_u8,"a: uint16x8_t, b: uint8x16_t, c: uint8x16_t",uint16x8_t,Unsigned multiply-subtract long -FALSE,vmlsl_lane_s16,"a: int32x4_t, b: int16x4_t, v: int16x4_t, lane: const int",int32x4_t,Vector widening multiply subtract with scalar -FALSE,vmlsl_lane_s32,"a: int64x2_t, b: int32x2_t, v: int32x2_t, lane: const int",int64x2_t,Vector widening multiply subtract with scalar -FALSE,vmlsl_lane_u16,"a: uint32x4_t, b: uint16x4_t, v: uint16x4_t, lane: const int",uint32x4_t,Vector widening multiply subtract with scalar -FALSE,vmlsl_lane_u32,"a: uint64x2_t, b: uint32x2_t, v: uint32x2_t, lane: const int",uint64x2_t,Vector widening multiply subtract with scalar -FALSE,vmlsl_laneq_s16,"a: int32x4_t, b: int16x4_t, v: int16x8_t, lane: const int",int32x4_t,Signed multiply-subtract long -FALSE,vmlsl_laneq_s32,"a: int64x2_t, b: int32x2_t, v: int32x4_t, lane: const int",int64x2_t,Signed multiply-subtract long -FALSE,vmlsl_laneq_u16,"a: uint32x4_t, b: uint16x4_t, v: uint16x8_t, lane: const int",uint32x4_t,Unsigned multiply-subtract long -FALSE,vmlsl_laneq_u32,"a: uint64x2_t, b: uint32x2_t, v: uint32x4_t, lane: const int",uint64x2_t,Unsigned multiply-subtract long -FALSE,vmlsl_n_s16,"a: int32x4_t, b: int16x4_t, c: i16",int32x4_t,Vector widening multiply subtract with scalar -FALSE,vmlsl_n_s32,"a: int64x2_t, b: int32x2_t, c: i32",int64x2_t,Vector widening multiply subtract with scalar -FALSE,vmlsl_n_u16,"a: uint32x4_t, b: uint16x4_t, c: u16",uint32x4_t,Vector widening multiply subtract with scalar -FALSE,vmlsl_n_u32,"a: uint64x2_t, b: uint32x2_t, c: u32",uint64x2_t,Vector widening multiply subtract with scalar -TRUE,vmlsl_s16,"a: int32x4_t, b: int16x4_t, c: int16x4_t",int32x4_t,Signed multiply-subtract long -TRUE,vmlsl_s32,"a: int64x2_t, b: int32x2_t, c: int32x2_t",int64x2_t,Signed multiply-subtract long -TRUE,vmlsl_s8,"a: int16x8_t, b: int8x8_t, c: int8x8_t",int16x8_t,Signed multiply-subtract long -TRUE,vmlsl_u16,"a: uint32x4_t, b: uint16x4_t, c: uint16x4_t",uint32x4_t,Unsigned multiply-subtract long -TRUE,vmlsl_u32,"a: uint64x2_t, b: uint32x2_t, c: uint32x2_t",uint64x2_t,Unsigned multiply-subtract long -TRUE,vmlsl_u8,"a: uint16x8_t, b: uint8x8_t, c: uint8x8_t",uint16x8_t,Unsigned multiply-subtract long -TRUE,vmlsq_f32,"a: float32x4_t, b: float32x4_t, c: float32x4_t",float32x4_t,Multiply-subtract from accumulator -TRUE,vmlsq_f64,"a: float64x2_t, b: float64x2_t, c: float64x2_t",float64x2_t,Multiply-subtract from accumulator -FALSE,vmlsq_lane_f32,"a: float32x4_t, b: float32x4_t, v: float32x2_t, lane: const int",float32x4_t,Vector multiply subtract with scalar -FALSE,vmlsq_lane_s16,"a: int16x8_t, b: int16x8_t, v: int16x4_t, lane: const int",int16x8_t,Vector multiply subtract with scalar -FALSE,vmlsq_lane_s32,"a: int32x4_t, b: int32x4_t, v: int32x2_t, lane: const int",int32x4_t,Vector multiply subtract with scalar -FALSE,vmlsq_lane_u16,"a: uint16x8_t, b: uint16x8_t, v: uint16x4_t, lane: const int",uint16x8_t,Vector multiply subtract with scalar -FALSE,vmlsq_lane_u32,"a: uint32x4_t, b: uint32x4_t, v: uint32x2_t, lane: const int",uint32x4_t,Vector multiply subtract with scalar -FALSE,vmlsq_laneq_f32,"a: float32x4_t, b: float32x4_t, v: float32x4_t, lane: const int",float32x4_t,Multiply-subtract from accumulator -FALSE,vmlsq_laneq_s16,"a: int16x8_t, b: int16x8_t, v: int16x8_t, lane: const int",int16x8_t,Multiply-subtract from accumulator -FALSE,vmlsq_laneq_s32,"a: int32x4_t, b: int32x4_t, v: int32x4_t, lane: const int",int32x4_t,Multiply-subtract from accumulator -FALSE,vmlsq_laneq_u16,"a: uint16x8_t, b: uint16x8_t, v: uint16x8_t, lane: const int",uint16x8_t,Multiply-subtract from accumulator -FALSE,vmlsq_laneq_u32,"a: uint32x4_t, b: uint32x4_t, v: uint32x4_t, lane: const int",uint32x4_t,Multiply-subtract from accumulator -FALSE,vmlsq_n_f32,"a: float32x4_t, b: float32x4_t, c: f32",float32x4_t,Vector multiply subtract with scalar -FALSE,vmlsq_n_s16,"a: int16x8_t, b: int16x8_t, c: i16",int16x8_t,Vector multiply subtract with scalar -FALSE,vmlsq_n_s32,"a: int32x4_t, b: int32x4_t, c: i32",int32x4_t,Vector multiply subtract with scalar -FALSE,vmlsq_n_u16,"a: uint16x8_t, b: uint16x8_t, c: u16",uint16x8_t,Vector multiply subtract with scalar -FALSE,vmlsq_n_u32,"a: uint32x4_t, b: uint32x4_t, c: u32",uint32x4_t,Vector multiply subtract with scalar -TRUE,vmlsq_s16,"a: int16x8_t, b: int16x8_t, c: int16x8_t",int16x8_t,Multiply-subtract from accumulator -TRUE,vmlsq_s32,"a: int32x4_t, b: int32x4_t, c: int32x4_t",int32x4_t,Multiply-subtract from accumulator -TRUE,vmlsq_s8,"a: int8x16_t, b: int8x16_t, c: int8x16_t",int8x16_t,Multiply-subtract from accumulator -TRUE,vmlsq_u16,"a: uint16x8_t, b: uint16x8_t, c: uint16x8_t",uint16x8_t,Multiply-subtract from accumulator -TRUE,vmlsq_u32,"a: uint32x4_t, b: uint32x4_t, c: uint32x4_t",uint32x4_t,Multiply-subtract from accumulator -TRUE,vmlsq_u8,"a: uint8x16_t, b: uint8x16_t, c: uint8x16_t",uint8x16_t,Multiply-subtract from accumulator -FALSE,vmmlaq_s32,"r: int32x4_t, a: int8x16_t, b: int8x16_t",int32x4_t,Signed 8-bit integer matrix multiply-accumulate -FALSE,vmmlaq_u32,"r: uint32x4_t, a: uint8x16_t, b: uint8x16_t",uint32x4_t,Unsigned 8-bit integer matrix multiply-accumulate -FALSE,vmov_n_f16,value: float16_t,float16x4_t,Duplicate vector element to vector or scalar -TRUE,vmov_n_f32,value: f32,float32x2_t,Duplicate vector element to vector or scalar -TRUE,vmov_n_f64,value: float64_t,float64x1_t,Duplicate vector element to vector or scalar -TRUE,vmov_n_p16,value: poly16_t,poly16x4_t,Duplicate vector element to vector or scalar -TRUE,vmov_n_p8,value: poly8_t,poly8x8_t,Duplicate vector element to vector or scalar -TRUE,vmov_n_s16,value: i16,int16x4_t,Duplicate vector element to vector or scalar -TRUE,vmov_n_s32,value: i32,int32x2_t,Duplicate vector element to vector or scalar -TRUE,vmov_n_s64,value: i64,int64x1_t,Duplicate vector element to vector or scalar -TRUE,vmov_n_s8,value: i8,int8x8_t,Duplicate vector element to vector or scalar -TRUE,vmov_n_u16,value: u16,uint16x4_t,Duplicate vector element to vector or scalar -TRUE,vmov_n_u32,value: u32,uint32x2_t,Duplicate vector element to vector or scalar -TRUE,vmov_n_u64,value: u64,uint64x1_t,Duplicate vector element to vector or scalar -TRUE,vmov_n_u8,value: u8,uint8x8_t,Duplicate vector element to vector or scalar -FALSE,vmovl_high_s16,a: int16x8_t,int32x4_t,Vector move -FALSE,vmovl_high_s32,a: int32x4_t,int64x2_t,Vector move -FALSE,vmovl_high_s8,a: int8x16_t,int16x8_t,Vector move -FALSE,vmovl_high_u16,a: uint16x8_t,uint32x4_t,Vector move -FALSE,vmovl_high_u32,a: uint32x4_t,uint64x2_t,Vector move -FALSE,vmovl_high_u8,a: uint8x16_t,uint16x8_t,Vector move -TRUE,vmovl_s16,a: int16x4_t,int32x4_t,Vector move -TRUE,vmovl_s32,a: int32x2_t,int64x2_t,Vector move -TRUE,vmovl_s8,a: int8x8_t,int16x8_t,Vector move -TRUE,vmovl_u16,a: uint16x4_t,uint32x4_t,Vector move -TRUE,vmovl_u32,a: uint32x2_t,uint64x2_t,Vector move -TRUE,vmovl_u8,a: uint8x8_t,uint16x8_t,Vector move -TRUE,vmovn_high_s16,"r: int8x8_t, a: int16x8_t",int8x16_t,Extract narrow -TRUE,vmovn_high_s32,"r: int16x4_t, a: int32x4_t",int16x8_t,Extract narrow -TRUE,vmovn_high_s64,"r: int32x2_t, a: int64x2_t",int32x4_t,Extract narrow -TRUE,vmovn_high_u16,"r: uint8x8_t, a: uint16x8_t",uint8x16_t,Extract narrow -TRUE,vmovn_high_u32,"r: uint16x4_t, a: uint32x4_t",uint16x8_t,Extract narrow -TRUE,vmovn_high_u64,"r: uint32x2_t, a: uint64x2_t",uint32x4_t,Extract narrow -TRUE,vmovn_s16,a: int16x8_t,int8x8_t,Extract narrow -TRUE,vmovn_s32,a: int32x4_t,int16x4_t,Extract narrow -TRUE,vmovn_s64,a: int64x2_t,int32x2_t,Extract narrow -TRUE,vmovn_u16,a: uint16x8_t,uint8x8_t,Extract narrow -TRUE,vmovn_u32,a: uint32x4_t,uint16x4_t,Extract narrow -TRUE,vmovn_u64,a: uint64x2_t,uint32x2_t,Extract narrow -FALSE,vmovq_n_f16,value: float16_t,float16x8_t,Duplicate vector element to vector or scalar -TRUE,vmovq_n_f32,value: f32,float32x4_t,Duplicate vector element to vector or scalar -TRUE,vmovq_n_f64,value: float64_t,float64x2_t,Duplicate vector element to vector or scalar -TRUE,vmovq_n_p16,value: poly16_t,poly16x8_t,Duplicate vector element to vector or scalar -TRUE,vmovq_n_p8,value: poly8_t,poly8x16_t,Duplicate vector element to vector or scalar -TRUE,vmovq_n_s16,value: i16,int16x8_t,Duplicate vector element to vector or scalar -TRUE,vmovq_n_s32,value: i32,int32x4_t,Duplicate vector element to vector or scalar -TRUE,vmovq_n_s64,value: i64,int64x2_t,Duplicate vector element to vector or scalar -TRUE,vmovq_n_s8,value: i8,int8x16_t,Duplicate vector element to vector or scalar -TRUE,vmovq_n_u16,value: u16,uint16x8_t,Duplicate vector element to vector or scalar -TRUE,vmovq_n_u32,value: u32,uint32x4_t,Duplicate vector element to vector or scalar -TRUE,vmovq_n_u64,value: u64,uint64x2_t,Duplicate vector element to vector or scalar -TRUE,vmovq_n_u8,value: u8,uint8x16_t,Duplicate vector element to vector or scalar -FALSE,vmul_f16,"a: float16x4_t, b: float16x4_t",float16x4_t,Floating-point multiply -TRUE,vmul_f32,"a: float32x2_t, b: float32x2_t",float32x2_t,Floating-point multiply -TRUE,vmul_f64,"a: float64x1_t, b: float64x1_t",float64x1_t,Floating-point multiply -FALSE,vmul_lane_f16,"a: float16x4_t, v: float16x4_t, lane: const int",float16x4_t,Floating-point multiply -FALSE,vmul_lane_f32,"a: float32x2_t, v: float32x2_t, lane: const int",float32x2_t,Floating-point multiply -FALSE,vmul_lane_f64,"a: float64x1_t, v: float64x1_t, lane: const int",float64x1_t,Floating-point multiply -FALSE,vmul_lane_s16,"a: int16x4_t, v: int16x4_t, lane: const int",int16x4_t,Multiply -FALSE,vmul_lane_s32,"a: int32x2_t, v: int32x2_t, lane: const int",int32x2_t,Multiply -FALSE,vmul_lane_u16,"a: uint16x4_t, v: uint16x4_t, lane: const int",uint16x4_t,Multiply -FALSE,vmul_lane_u32,"a: uint32x2_t, v: uint32x2_t, lane: const int",uint32x2_t,Multiply -FALSE,vmul_laneq_f16,"a: float16x4_t, v: float16x8_t, lane: const int",float16x4_t,Floating-point multiply -FALSE,vmul_laneq_f32,"a: float32x2_t, v: float32x4_t, lane: const int",float32x2_t,Floating-point multiply -FALSE,vmul_laneq_f64,"a: float64x1_t, v: float64x2_t, lane: const int",float64x1_t,Floating-point multiply -FALSE,vmul_laneq_s16,"a: int16x4_t, v: int16x8_t, lane: const int",int16x4_t,Multiply -FALSE,vmul_laneq_s32,"a: int32x2_t, v: int32x4_t, lane: const int",int32x2_t,Multiply -FALSE,vmul_laneq_u16,"a: uint16x4_t, v: uint16x8_t, lane: const int",uint16x4_t,Multiply -FALSE,vmul_laneq_u32,"a: uint32x2_t, v: uint32x4_t, lane: const int",uint32x2_t,Multiply -FALSE,vmul_n_f16,"a: float16x4_t, n: float16_t",float16x4_t,Floating-point multiply -FALSE,vmul_n_f32,"a: float32x2_t, b: f32",float32x2_t,Vector multiply by scalar -FALSE,vmul_n_f64,"a: float64x1_t, b: float64_t",float64x1_t,Floating-point multiply -FALSE,vmul_n_s16,"a: int16x4_t, b: i16",int16x4_t,Vector multiply by scalar -FALSE,vmul_n_s32,"a: int32x2_t, b: i32",int32x2_t,Vector multiply by scalar -FALSE,vmul_n_u16,"a: uint16x4_t, b: u16",uint16x4_t,Vector multiply by scalar -FALSE,vmul_n_u32,"a: uint32x2_t, b: u32",uint32x2_t,Vector multiply by scalar -FALSE,vmul_p8,"a: poly8x8_t, b: poly8x8_t",poly8x8_t,Polynomial multiply -TRUE,vmul_s16,"a: int16x4_t, b: int16x4_t",int16x4_t,Multiply -TRUE,vmul_s32,"a: int32x2_t, b: int32x2_t",int32x2_t,Multiply -TRUE,vmul_s8,"a: int8x8_t, b: int8x8_t",int8x8_t,Multiply -TRUE,vmul_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4_t,Multiply -TRUE,vmul_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2_t,Multiply -TRUE,vmul_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,Multiply -FALSE,vmuld_lane_f64,"a: float64_t, v: float64x1_t, lane: const int",float64_t,Floating-point multiply -FALSE,vmuld_laneq_f64,"a: float64_t, v: float64x2_t, lane: const int",float64_t,Floating-point multiply -FALSE,vmulh_f16,"a: float16_t, b: float16_t",float16_t,Floating-point multiply -FALSE,vmulh_lane_f16,"a: float16_t, v: float16x4_t, lane: const int",float16_t,Floating-point multiply -FALSE,vmulh_laneq_f16,"a: float16_t, v: float16x8_t, lane: const int",float16_t,Floating-point multiply -FALSE,vmull_high_lane_s16,"a: int16x8_t, v: int16x4_t, lane: const int",int32x4_t,Signed multiply long -FALSE,vmull_high_lane_s32,"a: int32x4_t, v: int32x2_t, lane: const int",int64x2_t,Signed multiply long -FALSE,vmull_high_lane_u16,"a: uint16x8_t, v: uint16x4_t, lane: const int",uint32x4_t,Unsigned multiply long -FALSE,vmull_high_lane_u32,"a: uint32x4_t, v: uint32x2_t, lane: const int",uint64x2_t,Unsigned multiply long -FALSE,vmull_high_laneq_s16,"a: int16x8_t, v: int16x8_t, lane: const int",int32x4_t,Signed multiply long -FALSE,vmull_high_laneq_s32,"a: int32x4_t, v: int32x4_t, lane: const int",int64x2_t,Signed multiply long -FALSE,vmull_high_laneq_u16,"a: uint16x8_t, v: uint16x8_t, lane: const int",uint32x4_t,Unsigned multiply long -FALSE,vmull_high_laneq_u32,"a: uint32x4_t, v: uint32x4_t, lane: const int",uint64x2_t,Unsigned multiply long -FALSE,vmull_high_n_s16,"a: int16x8_t, b: i16",int32x4_t,Signed multiply long -FALSE,vmull_high_n_s32,"a: int32x4_t, b: i32",int64x2_t,Signed multiply long -FALSE,vmull_high_n_u16,"a: uint16x8_t, b: u16",uint32x4_t,Unsigned multiply long -FALSE,vmull_high_n_u32,"a: uint32x4_t, b: u32",uint64x2_t,Unsigned multiply long -FALSE,vmull_high_p64,"a: poly64x2_t, b: poly64x2_t",poly128_t,Polynomial multiply long -TRUE,vmull_high_p8,"a: poly8x16_t, b: poly8x16_t",poly16x8_t,Polynomial multiply long -TRUE,vmull_high_s16,"a: int16x8_t, b: int16x8_t",int32x4_t,Signed multiply long -TRUE,vmull_high_s32,"a: int32x4_t, b: int32x4_t",int64x2_t,Signed multiply long -TRUE,vmull_high_s8,"a: int8x16_t, b: int8x16_t",int16x8_t,Signed multiply long -TRUE,vmull_high_u16,"a: uint16x8_t, b: uint16x8_t",uint32x4_t,Unsigned multiply long -TRUE,vmull_high_u32,"a: uint32x4_t, b: uint32x4_t",uint64x2_t,Unsigned multiply long -TRUE,vmull_high_u8,"a: uint8x16_t, b: uint8x16_t",uint16x8_t,Unsigned multiply long -FALSE,vmull_lane_s16,"a: int16x4_t, v: int16x4_t, lane: const int",int32x4_t,Vector long multiply by scalar -FALSE,vmull_lane_s32,"a: int32x2_t, v: int32x2_t, lane: const int",int64x2_t,Vector long multiply by scalar -FALSE,vmull_lane_u16,"a: uint16x4_t, v: uint16x4_t, lane: const int",uint32x4_t,Vector long multiply by scalar -FALSE,vmull_lane_u32,"a: uint32x2_t, v: uint32x2_t, lane: const int",uint64x2_t,Vector long multiply by scalar -FALSE,vmull_laneq_s16,"a: int16x4_t, v: int16x8_t, lane: const int",int32x4_t,Signed multiply long -FALSE,vmull_laneq_s32,"a: int32x2_t, v: int32x4_t, lane: const int",int64x2_t,Signed multiply long -FALSE,vmull_laneq_u16,"a: uint16x4_t, v: uint16x8_t, lane: const int",uint32x4_t,Unsigned multiply long -FALSE,vmull_laneq_u32,"a: uint32x2_t, v: uint32x4_t, lane: const int",uint64x2_t,Unsigned multiply long -FALSE,vmull_n_s16,"a: int16x4_t, b: i16",int32x4_t,Vector long multiply with scalar -FALSE,vmull_n_s32,"a: int32x2_t, b: i32",int64x2_t,Vector long multiply with scalar -FALSE,vmull_n_u16,"a: uint16x4_t, b: u16",uint32x4_t,Vector long multiply with scalar -FALSE,vmull_n_u32,"a: uint32x2_t, b: u32",uint64x2_t,Vector long multiply with scalar -TRUE,vmull_p64,"a: poly64_t, b: poly64_t",poly128_t,Polynomial multiply long -TRUE,vmull_p8,"a: poly8x8_t, b: poly8x8_t",poly16x8_t,Polynomial multiply long -TRUE,vmull_s16,"a: int16x4_t, b: int16x4_t",int32x4_t,Signed multiply long -TRUE,vmull_s32,"a: int32x2_t, b: int32x2_t",int64x2_t,Signed multiply long -TRUE,vmull_s8,"a: int8x8_t, b: int8x8_t",int16x8_t,Signed multiply long -TRUE,vmull_u16,"a: uint16x4_t, b: uint16x4_t",uint32x4_t,Unsigned multiply long -TRUE,vmull_u32,"a: uint32x2_t, b: uint32x2_t",uint64x2_t,Unsigned multiply long -TRUE,vmull_u8,"a: uint8x8_t, b: uint8x8_t",uint16x8_t,Unsigned multiply long -FALSE,vmulq_f16,"a: float16x8_t, b: float16x8_t",float16x8_t,Floating-point multiply -TRUE,vmulq_f32,"a: float32x4_t, b: float32x4_t",float32x4_t,Floating-point multiply -TRUE,vmulq_f64,"a: float64x2_t, b: float64x2_t",float64x2_t,Floating-point multiply -FALSE,vmulq_lane_f16,"a: float16x8_t, v: float16x4_t, lane: const int",float16x8_t,Floating-point multiply -FALSE,vmulq_lane_f32,"a: float32x4_t, v: float32x2_t, lane: const int",float32x4_t,Floating-point multiply -FALSE,vmulq_lane_f64,"a: float64x2_t, v: float64x1_t, lane: const int",float64x2_t,Floating-point multiply -FALSE,vmulq_lane_s16,"a: int16x8_t, v: int16x4_t, lane: const int",int16x8_t,Multiply -FALSE,vmulq_lane_s32,"a: int32x4_t, v: int32x2_t, lane: const int",int32x4_t,Multiply -FALSE,vmulq_lane_u16,"a: uint16x8_t, v: uint16x4_t, lane: const int",uint16x8_t,Multiply -FALSE,vmulq_lane_u32,"a: uint32x4_t, v: uint32x2_t, lane: const int",uint32x4_t,Multiply -FALSE,vmulq_laneq_f16,"a: float16x8_t, v: float16x8_t, lane: const int",float16x8_t,Floating-point multiply -FALSE,vmulq_laneq_f32,"a: float32x4_t, v: float32x4_t, lane: const int",float32x4_t,Floating-point multiply -FALSE,vmulq_laneq_f64,"a: float64x2_t, v: float64x2_t, lane: const int",float64x2_t,Floating-point multiply -FALSE,vmulq_laneq_s16,"a: int16x8_t, v: int16x8_t, lane: const int",int16x8_t,Multiply -FALSE,vmulq_laneq_s32,"a: int32x4_t, v: int32x4_t, lane: const int",int32x4_t,Multiply -FALSE,vmulq_laneq_u16,"a: uint16x8_t, v: uint16x8_t, lane: const int",uint16x8_t,Multiply -FALSE,vmulq_laneq_u32,"a: uint32x4_t, v: uint32x4_t, lane: const int",uint32x4_t,Multiply -FALSE,vmulq_n_f16,"a: float16x8_t, n: float16_t",float16x8_t,Floating-point multiply -FALSE,vmulq_n_f32,"a: float32x4_t, b: f32",float32x4_t,Vector multiply by scalar -FALSE,vmulq_n_f64,"a: float64x2_t, b: float64_t",float64x2_t,Floating-point multiply -FALSE,vmulq_n_s16,"a: int16x8_t, b: i16",int16x8_t,Vector multiply by scalar -FALSE,vmulq_n_s32,"a: int32x4_t, b: i32",int32x4_t,Vector multiply by scalar -FALSE,vmulq_n_u16,"a: uint16x8_t, b: u16",uint16x8_t,Vector multiply by scalar -FALSE,vmulq_n_u32,"a: uint32x4_t, b: u32",uint32x4_t,Vector multiply by scalar -FALSE,vmulq_p8,"a: poly8x16_t, b: poly8x16_t",poly8x16_t,Polynomial multiply -TRUE,vmulq_s16,"a: int16x8_t, b: int16x8_t",int16x8_t,Multiply -TRUE,vmulq_s32,"a: int32x4_t, b: int32x4_t",int32x4_t,Multiply -TRUE,vmulq_s8,"a: int8x16_t, b: int8x16_t",int8x16_t,Multiply -TRUE,vmulq_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8_t,Multiply -TRUE,vmulq_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,Multiply -TRUE,vmulq_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16_t,Multiply -FALSE,vmuls_lane_f32,"a: f32, v: float32x2_t, lane: const int",f32,Floating-point multiply -FALSE,vmuls_laneq_f32,"a: f32, v: float32x4_t, lane: const int",f32,Floating-point multiply -FALSE,vmulx_f16,"a: float16x4_t, b: float16x4_t",float16x4_t,Floating-point multiply extended -FALSE,vmulx_f32,"a: float32x2_t, b: float32x2_t",float32x2_t,Floating-point multiply extended -FALSE,vmulx_f64,"a: float64x1_t, b: float64x1_t",float64x1_t,Floating-point multiply extended -FALSE,vmulx_lane_f16,"a: float16x4_t, v: float16x4_t, lane: const int",float16x4_t,Floating-point multiply extended -FALSE,vmulx_lane_f32,"a: float32x2_t, v: float32x2_t, lane: const int",float32x2_t,Floating-point multiply extended -FALSE,vmulx_lane_f64,"a: float64x1_t, v: float64x1_t, lane: const int",float64x1_t,Floating-point multiply extended -FALSE,vmulx_laneq_f16,"a: float16x4_t, v: float16x8_t, lane: const int",float16x4_t,Floating-point multiply extended -FALSE,vmulx_laneq_f32,"a: float32x2_t, v: float32x4_t, lane: const int",float32x2_t,Floating-point multiply extended -FALSE,vmulx_laneq_f64,"a: float64x1_t, v: float64x2_t, lane: const int",float64x1_t,Floating-point multiply extended -FALSE,vmulx_n_f16,"a: float16x4_t, n: float16_t",float16x4_t,Floating-point multiply extended -FALSE,vmulxd_f64,"a: float64_t, b: float64_t",float64_t,Floating-point multiply extended -FALSE,vmulxd_lane_f64,"a: float64_t, v: float64x1_t, lane: const int",float64_t,Floating-point multiply extended -FALSE,vmulxd_laneq_f64,"a: float64_t, v: float64x2_t, lane: const int",float64_t,Floating-point multiply extended -FALSE,vmulxh_f16,"a: float16_t, b: float16_t",float16_t,Floating-point multiply extended -FALSE,vmulxh_lane_f16,"a: float16_t, v: float16x4_t, lane: const int",float16_t,Floating-point multiply extended -FALSE,vmulxh_laneq_f16,"a: float16_t, v: float16x8_t, lane: const int",float16_t,Floating-point multiply extended -FALSE,vmulxq_f16,"a: float16x8_t, b: float16x8_t",float16x8_t,Floating-point multiply extended -FALSE,vmulxq_f32,"a: float32x4_t, b: float32x4_t",float32x4_t,Floating-point multiply extended -FALSE,vmulxq_f64,"a: float64x2_t, b: float64x2_t",float64x2_t,Floating-point multiply extended -FALSE,vmulxq_lane_f16,"a: float16x8_t, v: float16x4_t, lane: const int",float16x8_t,Floating-point multiply extended -FALSE,vmulxq_lane_f32,"a: float32x4_t, v: float32x2_t, lane: const int",float32x4_t,Floating-point multiply extended -FALSE,vmulxq_lane_f64,"a: float64x2_t, v: float64x1_t, lane: const int",float64x2_t,Floating-point multiply extended -FALSE,vmulxq_laneq_f16,"a: float16x8_t, v: float16x8_t, lane: const int",float16x8_t,Floating-point multiply extended -FALSE,vmulxq_laneq_f32,"a: float32x4_t, v: float32x4_t, lane: const int",float32x4_t,Floating-point multiply extended -FALSE,vmulxq_laneq_f64,"a: float64x2_t, v: float64x2_t, lane: const int",float64x2_t,Floating-point multiply extended -FALSE,vmulxq_n_f16,"a: float16x8_t, n: float16_t",float16x8_t,Floating-point multiply extended -FALSE,vmulxs_f32,"a: f32, b: f32",f32,Floating-point multiply extended -FALSE,vmulxs_lane_f32,"a: f32, v: float32x2_t, lane: const int",f32,Floating-point multiply extended -FALSE,vmulxs_laneq_f32,"a: f32, v: float32x4_t, lane: const int",f32,Floating-point multiply extended -TRUE,vmvn_p8,a: poly8x8_t,poly8x8_t,Bitwise NOT -TRUE,vmvn_s16,a: int16x4_t,int16x4_t,Bitwise NOT -TRUE,vmvn_s32,a: int32x2_t,int32x2_t,Bitwise NOT -TRUE,vmvn_s8,a: int8x8_t,int8x8_t,Bitwise NOT -TRUE,vmvn_u16,a: uint16x4_t,uint16x4_t,Bitwise NOT -TRUE,vmvn_u32,a: uint32x2_t,uint32x2_t,Bitwise NOT -TRUE,vmvn_u8,a: uint8x8_t,uint8x8_t,Bitwise NOT -TRUE,vmvnq_p8,a: poly8x16_t,poly8x16_t,Bitwise NOT -TRUE,vmvnq_s16,a: int16x8_t,int16x8_t,Bitwise NOT -TRUE,vmvnq_s32,a: int32x4_t,int32x4_t,Bitwise NOT -TRUE,vmvnq_s8,a: int8x16_t,int8x16_t,Bitwise NOT -TRUE,vmvnq_u16,a: uint16x8_t,uint16x8_t,Bitwise NOT -TRUE,vmvnq_u32,a: uint32x4_t,uint32x4_t,Bitwise NOT -TRUE,vmvnq_u8,a: uint8x16_t,uint8x16_t,Bitwise NOT -FALSE,vneg_f16,a: float16x4_t,float16x4_t,Floating-point negate -TRUE,vneg_f32,a: float32x2_t,float32x2_t,Floating-point negate -TRUE,vneg_f64,a: float64x1_t,float64x1_t,Floating-point negate -TRUE,vneg_s16,a: int16x4_t,int16x4_t,Negate -TRUE,vneg_s32,a: int32x2_t,int32x2_t,Negate -TRUE,vneg_s64,a: int64x1_t,int64x1_t,Negate -TRUE,vneg_s8,a: int8x8_t,int8x8_t,Negate -FALSE,vnegd_s64,a: i64,i64,Negate -FALSE,vnegh_f16,a: float16_t,float16_t,Floating-point negate -FALSE,vnegq_f16,a: float16x8_t,float16x8_t,Floating-point negate -TRUE,vnegq_f32,a: float32x4_t,float32x4_t,Floating-point negate -TRUE,vnegq_f64,a: float64x2_t,float64x2_t,Floating-point negate -TRUE,vnegq_s16,a: int16x8_t,int16x8_t,Negate -TRUE,vnegq_s32,a: int32x4_t,int32x4_t,Negate -TRUE,vnegq_s64,a: int64x2_t,int64x2_t,Negate -TRUE,vnegq_s8,a: int8x16_t,int8x16_t,Negate -TRUE,vorn_s16,"a: int16x4_t, b: int16x4_t",int16x4_t,Bitwise inclusive OR NOT -TRUE,vorn_s32,"a: int32x2_t, b: int32x2_t",int32x2_t,Bitwise inclusive OR NOT -TRUE,vorn_s64,"a: int64x1_t, b: int64x1_t",int64x1_t,Bitwise inclusive OR NOT -TRUE,vorn_s8,"a: int8x8_t, b: int8x8_t",int8x8_t,Bitwise inclusive OR NOT -TRUE,vorn_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4_t,Bitwise inclusive OR NOT -TRUE,vorn_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2_t,Bitwise inclusive OR NOT -TRUE,vorn_u64,"a: uint64x1_t, b: uint64x1_t",uint64x1_t,Bitwise inclusive OR NOT -TRUE,vorn_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,Bitwise inclusive OR NOT -TRUE,vornq_s16,"a: int16x8_t, b: int16x8_t",int16x8_t,Bitwise inclusive OR NOT -TRUE,vornq_s32,"a: int32x4_t, b: int32x4_t",int32x4_t,Bitwise inclusive OR NOT -TRUE,vornq_s64,"a: int64x2_t, b: int64x2_t",int64x2_t,Bitwise inclusive OR NOT -TRUE,vornq_s8,"a: int8x16_t, b: int8x16_t",int8x16_t,Bitwise inclusive OR NOT -TRUE,vornq_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8_t,Bitwise inclusive OR NOT -TRUE,vornq_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,Bitwise inclusive OR NOT -TRUE,vornq_u64,"a: uint64x2_t, b: uint64x2_t",uint64x2_t,Bitwise inclusive OR NOT -TRUE,vornq_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16_t,Bitwise inclusive OR NOT -TRUE,vorr_s16,"a: int16x4_t, b: int16x4_t",int16x4_t,"Bitwise inclusive OR (vector, immediate)" -TRUE,vorr_s32,"a: int32x2_t, b: int32x2_t",int32x2_t,"Bitwise inclusive OR (vector, immediate)" -TRUE,vorr_s64,"a: int64x1_t, b: int64x1_t",int64x1_t,"Bitwise inclusive OR (vector, immediate)" -TRUE,vorr_s8,"a: int8x8_t, b: int8x8_t",int8x8_t,"Bitwise inclusive OR (vector, immediate)" -TRUE,vorr_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4_t,"Bitwise inclusive OR (vector, immediate)" -TRUE,vorr_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2_t,"Bitwise inclusive OR (vector, immediate)" -TRUE,vorr_u64,"a: uint64x1_t, b: uint64x1_t",uint64x1_t,"Bitwise inclusive OR (vector, immediate)" -TRUE,vorr_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,"Bitwise inclusive OR (vector, immediate)" -TRUE,vorrq_s16,"a: int16x8_t, b: int16x8_t",int16x8_t,"Bitwise inclusive OR (vector, immediate)" -TRUE,vorrq_s32,"a: int32x4_t, b: int32x4_t",int32x4_t,"Bitwise inclusive OR (vector, immediate)" -TRUE,vorrq_s64,"a: int64x2_t, b: int64x2_t",int64x2_t,"Bitwise inclusive OR (vector, immediate)" -TRUE,vorrq_s8,"a: int8x16_t, b: int8x16_t",int8x16_t,"Bitwise inclusive OR (vector, immediate)" -TRUE,vorrq_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8_t,"Bitwise inclusive OR (vector, immediate)" -TRUE,vorrq_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,"Bitwise inclusive OR (vector, immediate)" -TRUE,vorrq_u64,"a: uint64x2_t, b: uint64x2_t",uint64x2_t,"Bitwise inclusive OR (vector, immediate)" -TRUE,vorrq_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16_t,"Bitwise inclusive OR (vector, immediate)" -TRUE,vpadal_s16,"a: int32x2_t, b: int16x4_t",int32x2_t,Signed add and accumulate long pairwise -TRUE,vpadal_s32,"a: int64x1_t, b: int32x2_t",int64x1_t,Signed add and accumulate long pairwise -TRUE,vpadal_s8,"a: int16x4_t, b: int8x8_t",int16x4_t,Signed add and accumulate long pairwise -FALSE,vpadal_u16,"a: uint32x2_t, b: uint16x4_t",uint32x2_t,Unsigned add and accumulate long pairwise -FALSE,vpadal_u32,"a: uint64x1_t, b: uint32x2_t",uint64x1_t,Unsigned add and accumulate long pairwise -FALSE,vpadal_u8,"a: uint16x4_t, b: uint8x8_t",uint16x4_t,Unsigned add and accumulate long pairwise -FALSE,vpadalq_s16,"a: int32x4_t, b: int16x8_t",int32x4_t,Signed add and accumulate long pairwise -FALSE,vpadalq_s32,"a: int64x2_t, b: int32x4_t",int64x2_t,Signed add and accumulate long pairwise -FALSE,vpadalq_s8,"a: int16x8_t, b: int8x16_t",int16x8_t,Signed add and accumulate long pairwise -FALSE,vpadalq_u16,"a: uint32x4_t, b: uint16x8_t",uint32x4_t,Unsigned add and accumulate long pairwise -FALSE,vpadalq_u32,"a: uint64x2_t, b: uint32x4_t",uint64x2_t,Unsigned add and accumulate long pairwise -FALSE,vpadalq_u8,"a: uint16x8_t, b: uint8x16_t",uint16x8_t,Unsigned add and accumulate long pairwise -FALSE,vpadd_f16,"a: float16x4_t, b: float16x4_t",float16x4_t,Floating-point add pairwise -FALSE,vpadd_f32,"a: float32x2_t, b: float32x2_t",float32x2_t,Floating-point add pairwise -TRUE,vpadd_s16,"a: int16x4_t, b: int16x4_t",int16x4_t,Add pairwise -TRUE,vpadd_s32,"a: int32x2_t, b: int32x2_t",int32x2_t,Add pairwise -TRUE,vpadd_s8,"a: int8x8_t, b: int8x8_t",int8x8_t,Add pairwise -TRUE,vpadd_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4_t,Add pairwise -TRUE,vpadd_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2_t,Add pairwise -TRUE,vpadd_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,Add pairwise -FALSE,vpaddd_f64,a: float64x2_t,float64_t,Floating-point add pairwise -TRUE,vpaddd_s64,a: int64x2_t,i64,Add pairwise -TRUE,vpaddd_u64,a: uint64x2_t,u64,Add pairwise -FALSE,vpaddl_s16,a: int16x4_t,int32x2_t,Signed add long pairwise -FALSE,vpaddl_s32,a: int32x2_t,int64x1_t,Signed add long pairwise -FALSE,vpaddl_s8,a: int8x8_t,int16x4_t,Signed add long pairwise -FALSE,vpaddl_u16,a: uint16x4_t,uint32x2_t,Unsigned add long pairwise -FALSE,vpaddl_u32,a: uint32x2_t,uint64x1_t,Unsigned add long pairwise -FALSE,vpaddl_u8,a: uint8x8_t,uint16x4_t,Unsigned add long pairwise -FALSE,vpaddlq_s16,a: int16x8_t,int32x4_t,Signed add long pairwise -FALSE,vpaddlq_s32,a: int32x4_t,int64x2_t,Signed add long pairwise -FALSE,vpaddlq_s8,a: int8x16_t,int16x8_t,Signed add long pairwise -FALSE,vpaddlq_u16,a: uint16x8_t,uint32x4_t,Unsigned add long pairwise -FALSE,vpaddlq_u32,a: uint32x4_t,uint64x2_t,Unsigned add long pairwise -FALSE,vpaddlq_u8,a: uint8x16_t,uint16x8_t,Unsigned add long pairwise -FALSE,vpaddq_f16,"a: float16x8_t, b: float16x8_t",float16x8_t,Floating-point add pairwise -FALSE,vpaddq_f32,"a: float32x4_t, b: float32x4_t",float32x4_t,Floating-point add pairwise -FALSE,vpaddq_f64,"a: float64x2_t, b: float64x2_t",float64x2_t,Floating-point add pairwise -TRUE,vpaddq_s16,"a: int16x8_t, b: int16x8_t",int16x8_t,Add pairwise -TRUE,vpaddq_s32,"a: int32x4_t, b: int32x4_t",int32x4_t,Add pairwise -FALSE,vpaddq_s64,"a: int64x2_t, b: int64x2_t",int64x2_t,Add pairwise -TRUE,vpaddq_s8,"a: int8x16_t, b: int8x16_t",int8x16_t,Add pairwise -TRUE,vpaddq_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8_t,Add pairwise -TRUE,vpaddq_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,Add pairwise -FALSE,vpaddq_u64,"a: uint64x2_t, b: uint64x2_t",uint64x2_t,Add pairwise -TRUE,vpaddq_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16_t,Add pairwise -FALSE,vpadds_f32,a: float32x2_t,f32,Floating-point add pairwise -FALSE,vpmax_f16,"a: float16x4_t, b: float16x4_t",float16x4_t,Floating-point maximum pairwise -TRUE,vpmax_f32,"a: float32x2_t, b: float32x2_t",float32x2_t,Floating-point maximum pairwise -TRUE,vpmax_s16,"a: int16x4_t, b: int16x4_t",int16x4_t,Signed maximum pairwise -TRUE,vpmax_s32,"a: int32x2_t, b: int32x2_t",int32x2_t,Signed maximum pairwise -TRUE,vpmax_s8,"a: int8x8_t, b: int8x8_t",int8x8_t,Signed maximum pairwise -TRUE,vpmax_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4_t,Unsigned maximum pairwise -TRUE,vpmax_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2_t,Unsigned maximum pairwise -TRUE,vpmax_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,Unsigned maximum pairwise -FALSE,vpmaxnm_f16,"a: float16x4_t, b: float16x4_t",float16x4_t,Floating-point maximum number pairwise -TRUE,vpmaxnm_f32,"a: float32x2_t, b: float32x2_t",float32x2_t,Floating-point maximum number pairwise -FALSE,vpmaxnmq_f16,"a: float16x8_t, b: float16x8_t",float16x8_t,Floating-point maximum number pairwise -TRUE,vpmaxnmq_f32,"a: float32x4_t, b: float32x4_t",float32x4_t,Floating-point maximum number pairwise -TRUE,vpmaxnmq_f64,"a: float64x2_t, b: float64x2_t",float64x2_t,Floating-point maximum number pairwise -FALSE,vpmaxnmqd_f64,a: float64x2_t,float64_t,Floating-point maximum number pairwise -FALSE,vpmaxnms_f32,a: float32x2_t,f32,Floating-point maximum number pairwise -FALSE,vpmaxq_f16,"a: float16x8_t, b: float16x8_t",float16x8_t,Floating-point maximum pairwise -TRUE,vpmaxq_f32,"a: float32x4_t, b: float32x4_t",float32x4_t,Floating-point maximum pairwise -TRUE,vpmaxq_f64,"a: float64x2_t, b: float64x2_t",float64x2_t,Floating-point maximum pairwise -TRUE,vpmaxq_s16,"a: int16x8_t, b: int16x8_t",int16x8_t,Signed maximum pairwise -TRUE,vpmaxq_s32,"a: int32x4_t, b: int32x4_t",int32x4_t,Signed maximum pairwise -TRUE,vpmaxq_s8,"a: int8x16_t, b: int8x16_t",int8x16_t,Signed maximum pairwise -TRUE,vpmaxq_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8_t,Unsigned maximum pairwise -TRUE,vpmaxq_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,Unsigned maximum pairwise -TRUE,vpmaxq_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16_t,Unsigned maximum pairwise -FALSE,vpmaxqd_f64,a: float64x2_t,float64_t,Floating-point maximum pairwise -FALSE,vpmaxs_f32,a: float32x2_t,f32,Floating-point maximum pairwise -FALSE,vpmin_f16,"a: float16x4_t, b: float16x4_t",float16x4_t,Floating-point minimum pairwise -TRUE,vpmin_f32,"a: float32x2_t, b: float32x2_t",float32x2_t,Floating-point minimum pairwise -TRUE,vpmin_s16,"a: int16x4_t, b: int16x4_t",int16x4_t,Signed minimum pairwise -TRUE,vpmin_s32,"a: int32x2_t, b: int32x2_t",int32x2_t,Signed minimum pairwise -TRUE,vpmin_s8,"a: int8x8_t, b: int8x8_t",int8x8_t,Signed minimum pairwise -TRUE,vpmin_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4_t,Unsigned minimum pairwise -TRUE,vpmin_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2_t,Unsigned minimum pairwise -TRUE,vpmin_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,Unsigned minimum pairwise -FALSE,vpminnm_f16,"a: float16x4_t, b: float16x4_t",float16x4_t,Floating-point minimum number pairwise -FALSE,vpminnm_f32,"a: float32x2_t, b: float32x2_t",float32x2_t,Floating-point minimum number pairwise -FALSE,vpminnmq_f16,"a: float16x8_t, b: float16x8_t",float16x8_t,Floating-point minimum number pairwise -FALSE,vpminnmq_f32,"a: float32x4_t, b: float32x4_t",float32x4_t,Floating-point minimum number pairwise -FALSE,vpminnmq_f64,"a: float64x2_t, b: float64x2_t",float64x2_t,Floating-point minimum number pairwise -FALSE,vpminnmqd_f64,a: float64x2_t,float64_t,Floating-point minimum number pairwise -FALSE,vpminnms_f32,a: float32x2_t,f32,Floating-point minimum number pairwise -FALSE,vpminq_f16,"a: float16x8_t, b: float16x8_t",float16x8_t,Floating-point minimum pairwise -TRUE,vpminq_f32,"a: float32x4_t, b: float32x4_t",float32x4_t,Floating-point minimum pairwise -TRUE,vpminq_f64,"a: float64x2_t, b: float64x2_t",float64x2_t,Floating-point minimum pairwise -TRUE,vpminq_s16,"a: int16x8_t, b: int16x8_t",int16x8_t,Signed minimum pairwise -TRUE,vpminq_s32,"a: int32x4_t, b: int32x4_t",int32x4_t,Signed minimum pairwise -TRUE,vpminq_s8,"a: int8x16_t, b: int8x16_t",int8x16_t,Signed minimum pairwise -TRUE,vpminq_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8_t,Unsigned minimum pairwise -TRUE,vpminq_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,Unsigned minimum pairwise -TRUE,vpminq_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16_t,Unsigned minimum pairwise -FALSE,vpminqd_f64,a: float64x2_t,float64_t,Floating-point minimum pairwise -FALSE,vpmins_f32,a: float32x2_t,f32,Floating-point minimum pairwise -TRUE,vqabs_s16,a: int16x4_t,int16x4_t,Signed saturating absolute value -TRUE,vqabs_s32,a: int32x2_t,int32x2_t,Signed saturating absolute value -TRUE,vqabs_s64,a: int64x1_t,int64x1_t,Signed saturating absolute value -TRUE,vqabs_s8,a: int8x8_t,int8x8_t,Signed saturating absolute value -FALSE,vqabsb_s8,a: i8,i8,Signed saturating absolute value -FALSE,vqabsd_s64,a: i64,i64,Signed saturating absolute value -FALSE,vqabsh_s16,a: i16,i16,Signed saturating absolute value -TRUE,vqabsq_s16,a: int16x8_t,int16x8_t,Signed saturating absolute value -TRUE,vqabsq_s32,a: int32x4_t,int32x4_t,Signed saturating absolute value -TRUE,vqabsq_s64,a: int64x2_t,int64x2_t,Signed saturating absolute value -TRUE,vqabsq_s8,a: int8x16_t,int8x16_t,Signed saturating absolute value -FALSE,vqabss_s32,a: i32,i32,Signed saturating absolute value -TRUE,vqadd_s16,"a: int16x4_t, b: int16x4_t",int16x4_t,Signed saturating add -TRUE,vqadd_s32,"a: int32x2_t, b: int32x2_t",int32x2_t,Signed saturating add -TRUE,vqadd_s64,"a: int64x1_t, b: int64x1_t",int64x1_t,Signed saturating add -TRUE,vqadd_s8,"a: int8x8_t, b: int8x8_t",int8x8_t,Signed saturating add -TRUE,vqadd_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4_t,Unsigned saturating add -TRUE,vqadd_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2_t,Unsigned saturating add -TRUE,vqadd_u64,"a: uint64x1_t, b: uint64x1_t",uint64x1_t,Unsigned saturating add -TRUE,vqadd_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,Unsigned saturating add -TRUE,vqaddb_s8,"a: i8, b: i8",i8,Signed saturating add -TRUE,vqaddb_u8,"a: u8, b: u8",u8,Unsigned saturating add -TRUE,vqaddd_s64,"a: i64, b: i64",i64,Signed saturating add -TRUE,vqaddd_u64,"a: u64, b: u64",u64,Unsigned saturating add -TRUE,vqaddh_s16,"a: i16, b: i16",i16,Signed saturating add -TRUE,vqaddh_u16,"a: u16, b: u16",u16,Unsigned saturating add -TRUE,vqaddq_s16,"a: int16x8_t, b: int16x8_t",int16x8_t,Signed saturating add -TRUE,vqaddq_s32,"a: int32x4_t, b: int32x4_t",int32x4_t,Signed saturating add -TRUE,vqaddq_s64,"a: int64x2_t, b: int64x2_t",int64x2_t,Signed saturating add -TRUE,vqaddq_s8,"a: int8x16_t, b: int8x16_t",int8x16_t,Signed saturating add -TRUE,vqaddq_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8_t,Unsigned saturating add -TRUE,vqaddq_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,Unsigned saturating add -TRUE,vqaddq_u64,"a: uint64x2_t, b: uint64x2_t",uint64x2_t,Unsigned saturating add -TRUE,vqaddq_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16_t,Unsigned saturating add -TRUE,vqadds_s32,"a: i32, b: i32",i32,Signed saturating add -TRUE,vqadds_u32,"a: u32, b: u32",u32,Unsigned saturating add -TRUE,vqdmlal_high_lane_s16,"a: int32x4_t, b: int16x8_t, v: int16x4_t, lane: const int",int32x4_t,Signed saturating doubling multiply-add long -TRUE,vqdmlal_high_lane_s32,"a: int64x2_t, b: int32x4_t, v: int32x2_t, lane: const int",int64x2_t,Signed saturating doubling multiply-add long -TRUE,vqdmlal_high_laneq_s16,"a: int32x4_t, b: int16x8_t, v: int16x8_t, lane: const int",int32x4_t,Signed saturating doubling multiply-add long -TRUE,vqdmlal_high_laneq_s32,"a: int64x2_t, b: int32x4_t, v: int32x4_t, lane: const int",int64x2_t,Signed saturating doubling multiply-add long -TRUE,vqdmlal_high_n_s16,"a: int32x4_t, b: int16x8_t, c: i16",int32x4_t,Signed saturating doubling multiply-add long -TRUE,vqdmlal_high_n_s32,"a: int64x2_t, b: int32x4_t, c: i32",int64x2_t,Signed saturating doubling multiply-add long -TRUE,vqdmlal_high_s16,"a: int32x4_t, b: int16x8_t, c: int16x8_t",int32x4_t,Signed saturating doubling multiply-add long -TRUE,vqdmlal_high_s32,"a: int64x2_t, b: int32x4_t, c: int32x4_t",int64x2_t,Signed saturating doubling multiply-add long -TRUE,vqdmlal_lane_s16,"a: int32x4_t, b: int16x4_t, v: int16x4_t, lane: const int",int32x4_t,Vector widening saturating doubling multiply accumulate with scalar -TRUE,vqdmlal_lane_s32,"a: int64x2_t, b: int32x2_t, v: int32x2_t, lane: const int",int64x2_t,Vector widening saturating doubling multiply accumulate with scalar -TRUE,vqdmlal_laneq_s16,"a: int32x4_t, b: int16x4_t, v: int16x8_t, lane: const int",int32x4_t,Signed saturating doubling multiply-add long -TRUE,vqdmlal_laneq_s32,"a: int64x2_t, b: int32x2_t, v: int32x4_t, lane: const int",int64x2_t,Signed saturating doubling multiply-add long -TRUE,vqdmlal_n_s16,"a: int32x4_t, b: int16x4_t, c: i16",int32x4_t,Vector widening saturating doubling multiply accumulate with scalar -TRUE,vqdmlal_n_s32,"a: int64x2_t, b: int32x2_t, c: i32",int64x2_t,Vector widening saturating doubling multiply accumulate with scalar -TRUE,vqdmlal_s16,"a: int32x4_t, b: int16x4_t, c: int16x4_t",int32x4_t,Signed saturating doubling multiply-add long -TRUE,vqdmlal_s32,"a: int64x2_t, b: int32x2_t, c: int32x2_t",int64x2_t,Signed saturating doubling multiply-add long -FALSE,vqdmlalh_lane_s16,"a: i32, b: i16, v: int16x4_t, lane: const int",i32,Signed saturating doubling multiply-add long -FALSE,vqdmlalh_laneq_s16,"a: i32, b: i16, v: int16x8_t, lane: const int",i32,Signed saturating doubling multiply-add long -FALSE,vqdmlalh_s16,"a: i32, b: i16, c: i16",i32,Signed saturating doubling multiply-add long -FALSE,vqdmlals_lane_s32,"a: i64, b: i32, v: int32x2_t, lane: const int",i64,Signed saturating doubling multiply-add long -FALSE,vqdmlals_laneq_s32,"a: i64, b: i32, v: int32x4_t, lane: const int",i64,Signed saturating doubling multiply-add long -FALSE,vqdmlals_s32,"a: i64, b: i32, c: i32",i64,Signed saturating doubling multiply-add long -TRUE,vqdmlsl_high_lane_s16,"a: int32x4_t, b: int16x8_t, v: int16x4_t, lane: const int",int32x4_t,Signed saturating doubling multiply-subtract long -TRUE,vqdmlsl_high_lane_s32,"a: int64x2_t, b: int32x4_t, v: int32x2_t, lane: const int",int64x2_t,Signed saturating doubling multiply-subtract long -TRUE,vqdmlsl_high_laneq_s16,"a: int32x4_t, b: int16x8_t, v: int16x8_t, lane: const int",int32x4_t,Signed saturating doubling multiply-subtract long -TRUE,vqdmlsl_high_laneq_s32,"a: int64x2_t, b: int32x4_t, v: int32x4_t, lane: const int",int64x2_t,Signed saturating doubling multiply-subtract long -TRUE,vqdmlsl_high_n_s16,"a: int32x4_t, b: int16x8_t, c: i16",int32x4_t,Signed saturating doubling multiply-subtract long -TRUE,vqdmlsl_high_n_s32,"a: int64x2_t, b: int32x4_t, c: i32",int64x2_t,Signed saturating doubling multiply-subtract long -TRUE,vqdmlsl_high_s16,"a: int32x4_t, b: int16x8_t, c: int16x8_t",int32x4_t,Signed saturating doubling multiply-subtract long -TRUE,vqdmlsl_high_s32,"a: int64x2_t, b: int32x4_t, c: int32x4_t",int64x2_t,Signed saturating doubling multiply-subtract long -TRUE,vqdmlsl_lane_s16,"a: int32x4_t, b: int16x4_t, v: int16x4_t, lane: const int",int32x4_t,Vector widening saturating doubling multiply subtract with scalar -TRUE,vqdmlsl_lane_s32,"a: int64x2_t, b: int32x2_t, v: int32x2_t, lane: const int",int64x2_t,Vector widening saturating doubling multiply subtract with scalar -TRUE,vqdmlsl_laneq_s16,"a: int32x4_t, b: int16x4_t, v: int16x8_t, lane: const int",int32x4_t,Signed saturating doubling multiply-subtract long -TRUE,vqdmlsl_laneq_s32,"a: int64x2_t, b: int32x2_t, v: int32x4_t, lane: const int",int64x2_t,Signed saturating doubling multiply-subtract long -TRUE,vqdmlsl_n_s16,"a: int32x4_t, b: int16x4_t, c: i16",int32x4_t,Vector widening saturating doubling multiply subtract with scalar -TRUE,vqdmlsl_n_s32,"a: int64x2_t, b: int32x2_t, c: i32",int64x2_t,Vector widening saturating doubling multiply subtract with scalar -TRUE,vqdmlsl_s16,"a: int32x4_t, b: int16x4_t, c: int16x4_t",int32x4_t,Signed saturating doubling multiply-subtract long -TRUE,vqdmlsl_s32,"a: int64x2_t, b: int32x2_t, c: int32x2_t",int64x2_t,Signed saturating doubling multiply-subtract long -FALSE,vqdmlslh_lane_s16,"a: i32, b: i16, v: int16x4_t, lane: const int",i32,Signed saturating doubling multiply-subtract long -FALSE,vqdmlslh_laneq_s16,"a: i32, b: i16, v: int16x8_t, lane: const int",i32,Signed saturating doubling multiply-subtract long -FALSE,vqdmlslh_s16,"a: i32, b: i16, c: i16",i32,Signed saturating doubling multiply-subtract long -FALSE,vqdmlsls_lane_s32,"a: i64, b: i32, v: int32x2_t, lane: const int",i64,Signed saturating doubling multiply-subtract long -FALSE,vqdmlsls_laneq_s32,"a: i64, b: i32, v: int32x4_t, lane: const int",i64,Signed saturating doubling multiply-subtract long -FALSE,vqdmlsls_s32,"a: i64, b: i32, c: i32",i64,Signed saturating doubling multiply-subtract long -FALSE,vqdmulh_lane_s16,"a: int16x4_t, v: int16x4_t, lane: const int",int16x4_t,Vector saturating doubling multiply high by scalar -FALSE,vqdmulh_lane_s32,"a: int32x2_t, v: int32x2_t, lane: const int",int32x2_t,Vector saturating doubling multiply high by scalar -FALSE,vqdmulh_laneq_s16,"a: int16x4_t, v: int16x8_t, lane: const int",int16x4_t,Signed saturating doubling multiply returning high half -FALSE,vqdmulh_laneq_s32,"a: int32x2_t, v: int32x4_t, lane: const int",int32x2_t,Signed saturating doubling multiply returning high half -TRUE,vqdmulh_n_s16,"a: int16x4_t, b: i16",int16x4_t,Vector saturating doubling multiply high with scalar -TRUE,vqdmulh_n_s32,"a: int32x2_t, b: i32",int32x2_t,Vector saturating doubling multiply high with scalar -TRUE,vqdmulh_s16,"a: int16x4_t, b: int16x4_t",int16x4_t,Signed saturating doubling multiply returning high half -TRUE,vqdmulh_s32,"a: int32x2_t, b: int32x2_t",int32x2_t,Signed saturating doubling multiply returning high half -TRUE,vqdmulhh_lane_s16,"a: i16, v: int16x4_t, lane: const int",i16,Signed saturating doubling multiply returning high half -TRUE,vqdmulhh_laneq_s16,"a: i16, v: int16x8_t, lane: const int",i16,Signed saturating doubling multiply returning high half -TRUE,vqdmulhh_s16,"a: i16, b: i16",i16,Signed saturating doubling multiply returning high half -FALSE,vqdmulhq_lane_s16,"a: int16x8_t, v: int16x4_t, lane: const int",int16x8_t,Vector saturating doubling multiply high by scalar -FALSE,vqdmulhq_lane_s32,"a: int32x4_t, v: int32x2_t, lane: const int",int32x4_t,Vector saturating doubling multiply high by scalar -FALSE,vqdmulhq_laneq_s16,"a: int16x8_t, v: int16x8_t, lane: const int",int16x8_t,Signed saturating doubling multiply returning high half -FALSE,vqdmulhq_laneq_s32,"a: int32x4_t, v: int32x4_t, lane: const int",int32x4_t,Signed saturating doubling multiply returning high half -FALSE,vqdmulhq_n_s16,"a: int16x8_t, b: i16",int16x8_t,Vector saturating doubling multiply high with scalar -FALSE,vqdmulhq_n_s32,"a: int32x4_t, b: i32",int32x4_t,Vector saturating doubling multiply high with scalar -FALSE,vqdmulhq_s16,"a: int16x8_t, b: int16x8_t",int16x8_t,Signed saturating doubling multiply returning high half -TRUE,vqdmulhq_s32,"a: int32x4_t, b: int32x4_t",int32x4_t,Signed saturating doubling multiply returning high half -TRUE,vqdmulhs_lane_s32,"a: i32, v: int32x2_t, lane: const int",i32,Signed saturating doubling multiply returning high half -TRUE,vqdmulhs_laneq_s32,"a: i32, v: int32x4_t, lane: const int",i32,Signed saturating doubling multiply returning high half -TRUE,vqdmulhs_s32,"a: i32, b: i32",i32,Signed saturating doubling multiply returning high half -TRUE,vqdmull_high_lane_s16,"a: int16x8_t, v: int16x4_t, lane: const int",int32x4_t,Signed saturating doubling multiply long -TRUE,vqdmull_high_lane_s32,"a: int32x4_t, v: int32x2_t, lane: const int",int64x2_t,Signed saturating doubling multiply long -TRUE,vqdmull_high_laneq_s16,"a: int16x8_t, v: int16x8_t, lane: const int",int32x4_t,Signed saturating doubling multiply long -TRUE,vqdmull_high_laneq_s32,"a: int32x4_t, v: int32x4_t, lane: const int",int64x2_t,Signed saturating doubling multiply long -TRUE,vqdmull_high_n_s16,"a: int16x8_t, b: i16",int32x4_t,Signed saturating doubling multiply long -TRUE,vqdmull_high_n_s32,"a: int32x4_t, b: i32",int64x2_t,Signed saturating doubling multiply long -TRUE,vqdmull_high_s16,"a: int16x8_t, b: int16x8_t",int32x4_t,Signed saturating doubling multiply long -TRUE,vqdmull_high_s32,"a: int32x4_t, b: int32x4_t",int64x2_t,Signed saturating doubling multiply long -TRUE,vqdmull_lane_s16,"a: int16x4_t, v: int16x4_t, lane: const int",int32x4_t,Vector saturating doubling long multiply by scalar -TRUE,vqdmull_lane_s32,"a: int32x2_t, v: int32x2_t, lane: const int",int64x2_t,Vector saturating doubling long multiply by scalar -TRUE,vqdmull_laneq_s16,"a: int16x4_t, v: int16x8_t, lane: const int",int32x4_t,Signed saturating doubling multiply long -TRUE,vqdmull_laneq_s32,"a: int32x2_t, v: int32x4_t, lane: const int",int64x2_t,Signed saturating doubling multiply long -TRUE,vqdmull_n_s16,"a: int16x4_t, b: i16",int32x4_t,Vector saturating doubling long multiply with scalar -TRUE,vqdmull_n_s32,"a: int32x2_t, b: i32",int64x2_t,Vector saturating doubling long multiply with scalar -TRUE,vqdmull_s16,"a: int16x4_t, b: int16x4_t",int32x4_t,Signed saturating doubling multiply long -TRUE,vqdmull_s32,"a: int32x2_t, b: int32x2_t",int64x2_t,Signed saturating doubling multiply long -TRUE,vqdmullh_lane_s16,"a: i16, v: int16x4_t, lane: const int",i32,Signed saturating doubling multiply long -TRUE,vqdmullh_laneq_s16,"a: i16, v: int16x8_t, lane: const int",i32,Signed saturating doubling multiply long -TRUE,vqdmullh_s16,"a: i16, b: i16",i32,Signed saturating doubling multiply long -TRUE,vqdmulls_lane_s32,"a: i32, v: int32x2_t, lane: const int",i64,Signed saturating doubling multiply long -TRUE,vqdmulls_laneq_s32,"a: i32, v: int32x4_t, lane: const int",i64,Signed saturating doubling multiply long -TRUE,vqdmulls_s32,"a: i32, b: i32",i64,Signed saturating doubling multiply long -FALSE,vqmovn_high_s16,"r: int8x8_t, a: int16x8_t",int8x16_t,Signed saturating extract narrow -FALSE,vqmovn_high_s32,"r: int16x4_t, a: int32x4_t",int16x8_t,Signed saturating extract narrow -FALSE,vqmovn_high_s64,"r: int32x2_t, a: int64x2_t",int32x4_t,Signed saturating extract narrow -FALSE,vqmovn_high_u16,"r: uint8x8_t, a: uint16x8_t",uint8x16_t,Unsigned saturating extract narrow -FALSE,vqmovn_high_u32,"r: uint16x4_t, a: uint32x4_t",uint16x8_t,Unsigned saturating extract narrow -FALSE,vqmovn_high_u64,"r: uint32x2_t, a: uint64x2_t",uint32x4_t,Unsigned saturating extract narrow -FALSE,vqmovn_s16,a: int16x8_t,int8x8_t,Signed saturating extract narrow -FALSE,vqmovn_s32,a: int32x4_t,int16x4_t,Signed saturating extract narrow -FALSE,vqmovn_s64,a: int64x2_t,int32x2_t,Signed saturating extract narrow -FALSE,vqmovn_u16,a: uint16x8_t,uint8x8_t,Unsigned saturating extract narrow -FALSE,vqmovn_u32,a: uint32x4_t,uint16x4_t,Unsigned saturating extract narrow -TRUE,vqmovn_u64,a: uint64x2_t,uint32x2_t,Unsigned saturating extract narrow -FALSE,vqmovnd_s64,a: i64,i32,Signed saturating extract narrow -FALSE,vqmovnd_u64,a: u64,u32,Unsigned saturating extract narrow -FALSE,vqmovnh_s16,a: i16,i8,Signed saturating extract narrow -FALSE,vqmovnh_u16,a: u16,u8,Unsigned saturating extract narrow -FALSE,vqmovns_s32,a: i32,i16,Signed saturating extract narrow -FALSE,vqmovns_u32,a: u32,u16,Unsigned saturating extract narrow -FALSE,vqmovun_high_s16,"r: uint8x8_t, a: int16x8_t",uint8x16_t,Signed saturating extract unsigned narrow -FALSE,vqmovun_high_s32,"r: uint16x4_t, a: int32x4_t",uint16x8_t,Signed saturating extract unsigned narrow -FALSE,vqmovun_high_s64,"r: uint32x2_t, a: int64x2_t",uint32x4_t,Signed saturating extract unsigned narrow -FALSE,vqmovun_s16,a: int16x8_t,uint8x8_t,Signed saturating extract unsigned narrow -FALSE,vqmovun_s32,a: int32x4_t,uint16x4_t,Signed saturating extract unsigned narrow -FALSE,vqmovun_s64,a: int64x2_t,uint32x2_t,Signed saturating extract unsigned narrow -FALSE,vqmovund_s64,a: i64,u32,Signed saturating extract unsigned narrow -FALSE,vqmovunh_s16,a: i16,u8,Signed saturating extract unsigned narrow -FALSE,vqmovuns_s32,a: i32,u16,Signed saturating extract unsigned narrow -TRUE,vqneg_s16,a: int16x4_t,int16x4_t,Signed saturating negate -TRUE,vqneg_s32,a: int32x2_t,int32x2_t,Signed saturating negate -TRUE,vqneg_s64,a: int64x1_t,int64x1_t,Signed saturating negate -TRUE,vqneg_s8,a: int8x8_t,int8x8_t,Signed saturating negate -FALSE,vqnegb_s8,a: i8,i8,Signed saturating negate -FALSE,vqnegd_s64,a: i64,i64,Signed saturating negate -FALSE,vqnegh_s16,a: i16,i16,Signed saturating negate -TRUE,vqnegq_s16,a: int16x8_t,int16x8_t,Signed saturating negate -TRUE,vqnegq_s32,a: int32x4_t,int32x4_t,Signed saturating negate -TRUE,vqnegq_s64,a: int64x2_t,int64x2_t,Signed saturating negate -TRUE,vqnegq_s8,a: int8x16_t,int8x16_t,Signed saturating negate -FALSE,vqnegs_s32,a: i32,i32,Signed saturating negate -FALSE,vqrdmlah_lane_s16,"a: int16x4_t, b: int16x4_t, v: int16x4_t, lane: const int",int16x4_t,Signed saturating rounding doubling multiply accumulate returning high half -FALSE,vqrdmlah_lane_s32,"a: int32x2_t, b: int32x2_t, v: int32x2_t, lane: const int",int32x2_t,Signed saturating rounding doubling multiply accumulate returning high half -FALSE,vqrdmlah_laneq_s16,"a: int16x4_t, b: int16x4_t, v: int16x8_t, lane: const int",int16x4_t,Signed saturating rounding doubling multiply accumulate returning high half -FALSE,vqrdmlah_laneq_s32,"a: int32x2_t, b: int32x2_t, v: int32x4_t, lane: const int",int32x2_t,Signed saturating rounding doubling multiply accumulate returning high half -FALSE,vqrdmlah_s16,"a: int16x4_t, b: int16x4_t, c: int16x4_t",int16x4_t,Signed saturating rounding doubling multiply accumulate returning high half -FALSE,vqrdmlah_s32,"a: int32x2_t, b: int32x2_t, c: int32x2_t",int32x2_t,Signed saturating rounding doubling multiply accumulate returning high half -FALSE,vqrdmlahh_lane_s16,"a: i16, b: i16, v: int16x4_t, lane: const int",i16,Signed saturating rounding doubling multiply accumulate returning high half -FALSE,vqrdmlahh_laneq_s16,"a: i16, b: i16, v: int16x8_t, lane: const int",i16,Signed saturating rounding doubling multiply accumulate returning high half -FALSE,vqrdmlahh_s16,"a: i16, b: i16, c: i16",i16,Signed saturating rounding doubling multiply subtract returning high half -FALSE,vqrdmlahq_lane_s16,"a: int16x8_t, b: int16x8_t, v: int16x4_t, lane: const int",int16x8_t,Signed saturating rounding doubling multiply accumulate returning high half -FALSE,vqrdmlahq_lane_s32,"a: int32x4_t, b: int32x4_t, v: int32x2_t, lane: const int",int32x4_t,Signed saturating rounding doubling multiply accumulate returning high half -FALSE,vqrdmlahq_laneq_s16,"a: int16x8_t, b: int16x8_t, v: int16x8_t, lane: const int",int16x8_t,Signed saturating rounding doubling multiply accumulate returning high half -FALSE,vqrdmlahq_laneq_s32,"a: int32x4_t, b: int32x4_t, v: int32x4_t, lane: const int",int32x4_t,Signed saturating rounding doubling multiply accumulate returning high half -FALSE,vqrdmlahq_s16,"a: int16x8_t, b: int16x8_t, c: int16x8_t",int16x8_t,Signed saturating rounding doubling multiply accumulate returning high half -FALSE,vqrdmlahq_s32,"a: int32x4_t, b: int32x4_t, c: int32x4_t",int32x4_t,Signed saturating rounding doubling multiply accumulate returning high half -FALSE,vqrdmlahs_lane_s32,"a: i32, b: i32, v: int32x4_t, lane: const int",i32,Signed saturating rounding doubling multiply accumulate returning high half -FALSE,vqrdmlahs_laneq_s32,"a: i32, b: i32, v: int32x8_t, lane: const int",i32,Signed saturating rounding doubling multiply accumulate returning high half -FALSE,vqrdmlahs_s32,"a: i32, b: i32, c: i32",i32,Signed saturating rounding doubling multiply subtract returning high half -FALSE,vqrdmlsh_lane_s16,"a: int16x4_t, b: int16x4_t, v: int16x4_t, lane: const int",int16x4_t,Signed saturating rounding doubling multiply subtract returning high half -FALSE,vqrdmlsh_lane_s32,"a: int32x2_t, b: int32x2_t, v: int32x2_t, lane: const int",int32x2_t,Signed saturating rounding doubling multiply subtract returning high half -FALSE,vqrdmlsh_laneq_s16,"a: int16x4_t, b: int16x4_t, v: int16x8_t, lane: const int",int16x4_t,Signed saturating rounding doubling multiply subtract returning high half -FALSE,vqrdmlsh_laneq_s32,"a: int32x2_t, b: int32x2_t, v: int32x4_t, lane: const int",int32x2_t,Signed saturating rounding doubling multiply subtract returning high half -FALSE,vqrdmlsh_s16,"a: int16x4_t, b: int16x4_t, c: int16x4_t",int16x4_t,Signed saturating rounding doubling multiply subtract returning high half -FALSE,vqrdmlsh_s32,"a: int32x2_t, b: int32x2_t, c: int32x2_t",int32x2_t,Signed saturating rounding doubling multiply subtract returning high half -FALSE,vqrdmlshh_lane_s16,"a: i16, b: i16, v: int16x4_t, lane: const int",i16,Signed saturating rounding doubling multiply subtract returning high half -FALSE,vqrdmlshh_laneq_s16,"a: i16, b: i16, v: int16x8_t, lane: const int",i16,Signed saturating rounding doubling multiply subtract returning high half -FALSE,vqrdmlshh_s16,"a: i16, b: i16, c: i16",i16,Signed saturating rounding doubling multiply subtract returning high half -FALSE,vqrdmlshq_lane_s16,"a: int16x8_t, b: int16x8_t, v: int16x4_t, lane: const int",int16x8_t,Signed saturating rounding doubling multiply subtract returning high half -FALSE,vqrdmlshq_lane_s32,"a: int32x4_t, b: int32x4_t, v: int32x2_t, lane: const int",int32x4_t,Signed saturating rounding doubling multiply subtract returning high half -FALSE,vqrdmlshq_laneq_s16,"a: int16x8_t, b: int16x8_t, v: int16x8_t, lane: const int",int16x8_t,Signed saturating rounding doubling multiply subtract returning high half -FALSE,vqrdmlshq_laneq_s32,"a: int32x4_t, b: int32x4_t, v: int32x4_t, lane: const int",int32x4_t,Signed saturating rounding doubling multiply subtract returning high half -FALSE,vqrdmlshq_s16,"a: int16x8_t, b: int16x8_t, c: int16x8_t",int16x8_t,Signed saturating rounding doubling multiply subtract returning high half -FALSE,vqrdmlshq_s32,"a: int32x4_t, b: int32x4_t, c: int32x4_t",int32x4_t,Signed saturating rounding doubling multiply subtract returning high half -FALSE,vqrdmlshs_lane_s32,"a: i32, b: i32, v: int32x4_t, lane: const int",i32,Signed saturating rounding doubling multiply subtract returning high half -FALSE,vqrdmlshs_laneq_s32,"a: i32, b: i32, v: int32x8_t, lane: const int",i32,Signed saturating rounding doubling multiply subtract returning high half -FALSE,vqrdmlshs_s32,"a: i32, b: i32, c: i32",i32,Signed saturating rounding doubling multiply subtract returning high half -FALSE,vqrdmulh_lane_s16,"a: int16x4_t, v: int16x4_t, lane: const int",int16x4_t,Vector rounding saturating doubling multiply high by scalar -FALSE,vqrdmulh_lane_s32,"a: int32x2_t, v: int32x2_t, lane: const int",int32x2_t,Vector rounding saturating doubling multiply high by scalar -FALSE,vqrdmulh_laneq_s16,"a: int16x4_t, v: int16x8_t, lane: const int",int16x4_t,Signed saturating rounding doubling multiply returning high half -FALSE,vqrdmulh_laneq_s32,"a: int32x2_t, v: int32x4_t, lane: const int",int32x2_t,Signed saturating rounding doubling multiply returning high half -FALSE,vqrdmulh_n_s16,"a: int16x4_t, b: i16",int16x4_t,Vector saturating rounding doubling multiply high with scalar -FALSE,vqrdmulh_n_s32,"a: int32x2_t, b: i32",int32x2_t,Vector saturating rounding doubling multiply high with scalar -FALSE,vqrdmulh_s16,"a: int16x4_t, b: int16x4_t",int16x4_t,Signed saturating rounding doubling multiply returning high half -FALSE,vqrdmulh_s32,"a: int32x2_t, b: int32x2_t",int32x2_t,Signed saturating rounding doubling multiply returning high half -FALSE,vqrdmulhh_lane_s16,"a: i16, v: int16x4_t, lane: const int",i16,Signed saturating rounding doubling multiply returning high half -FALSE,vqrdmulhh_laneq_s16,"a: i16, v: int16x8_t, lane: const int",i16,Signed saturating rounding doubling multiply returning high half -FALSE,vqrdmulhh_s16,"a: i16, b: i16",i16,Signed saturating rounding doubling multiply returning high half -FALSE,vqrdmulhq_lane_s16,"a: int16x8_t, v: int16x4_t, lane: const int",int16x8_t,Vector rounding saturating doubling multiply high by scalar -FALSE,vqrdmulhq_lane_s32,"a: int32x4_t, v: int32x2_t, lane: const int",int32x4_t,Vector rounding saturating doubling multiply high by scalar -FALSE,vqrdmulhq_laneq_s16,"a: int16x8_t, v: int16x8_t, lane: const int",int16x8_t,Signed saturating rounding doubling multiply returning high half -FALSE,vqrdmulhq_laneq_s32,"a: int32x4_t, v: int32x4_t, lane: const int",int32x4_t,Signed saturating rounding doubling multiply returning high half -FALSE,vqrdmulhq_n_s16,"a: int16x8_t, b: i16",int16x8_t,Vector saturating rounding doubling multiply high with scalar -FALSE,vqrdmulhq_n_s32,"a: int32x4_t, b: i32",int32x4_t,Vector saturating rounding doubling multiply high with scalar -FALSE,vqrdmulhq_s16,"a: int16x8_t, b: int16x8_t",int16x8_t,Signed saturating rounding doubling multiply returning high half -FALSE,vqrdmulhq_s32,"a: int32x4_t, b: int32x4_t",int32x4_t,Signed saturating rounding doubling multiply returning high half -FALSE,vqrdmulhs_lane_s32,"a: i32, v: int32x2_t, lane: const int",i32,Signed saturating rounding doubling multiply returning high half -FALSE,vqrdmulhs_laneq_s32,"a: i32, v: int32x4_t, lane: const int",i32,Signed saturating rounding doubling multiply returning high half -FALSE,vqrdmulhs_s32,"a: i32, b: i32",i32,Signed saturating rounding doubling multiply returning high half -TRUE,vqrshl_s16,"a: int16x4_t, b: int16x4_t",int16x4_t,Signed saturating rounding shift left -TRUE,vqrshl_s32,"a: int32x2_t, b: int32x2_t",int32x2_t,Signed saturating rounding shift left -TRUE,vqrshl_s64,"a: int64x1_t, b: int64x1_t",int64x1_t,Signed saturating rounding shift left -TRUE,vqrshl_s8,"a: int8x8_t, b: int8x8_t",int8x8_t,Signed saturating rounding shift left -TRUE,vqrshl_u16,"a: uint16x4_t, b: int16x4_t",uint16x4_t,Unsigned saturating rounding shift left -TRUE,vqrshl_u32,"a: uint32x2_t, b: int32x2_t",uint32x2_t,Unsigned saturating rounding shift left -TRUE,vqrshl_u64,"a: uint64x1_t, b: int64x1_t",uint64x1_t,Unsigned saturating rounding shift left -TRUE,vqrshl_u8,"a: uint8x8_t, b: int8x8_t",uint8x8_t,Unsigned saturating rounding shift left -TRUE,vqrshlb_s8,"a: i8, b: i8",i8,Signed saturating rounding shift left -TRUE,vqrshlb_u8,"a: u8, b: i8",u8,Unsigned saturating rounding shift left -TRUE,vqrshld_s64,"a: i64, b: i64",i64,Signed saturating rounding shift left -TRUE,vqrshld_u64,"a: u64, b: i64",u64,Unsigned saturating rounding shift left -TRUE,vqrshlh_s16,"a: i16, b: i16",i16,Signed saturating rounding shift left -TRUE,vqrshlh_u16,"a: u16, b: i16",u16,Unsigned saturating rounding shift left -TRUE,vqrshlq_s16,"a: int16x8_t, b: int16x8_t",int16x8_t,Signed saturating rounding shift left -TRUE,vqrshlq_s32,"a: int32x4_t, b: int32x4_t",int32x4_t,Signed saturating rounding shift left -TRUE,vqrshlq_s64,"a: int64x2_t, b: int64x2_t",int64x2_t,Signed saturating rounding shift left -TRUE,vqrshlq_s8,"a: int8x16_t, b: int8x16_t",int8x16_t,Signed saturating rounding shift left -TRUE,vqrshlq_u16,"a: uint16x8_t, b: int16x8_t",uint16x8_t,Unsigned saturating rounding shift left -TRUE,vqrshlq_u32,"a: uint32x4_t, b: int32x4_t",uint32x4_t,Unsigned saturating rounding shift left -TRUE,vqrshlq_u64,"a: uint64x2_t, b: int64x2_t",uint64x2_t,Unsigned saturating rounding shift left -TRUE,vqrshlq_u8,"a: uint8x16_t, b: int8x16_t",uint8x16_t,Unsigned saturating rounding shift left -TRUE,vqrshls_s32,"a: i32, b: i32",i32,Signed saturating rounding shift left -TRUE,vqrshls_u32,"a: u32, b: i32",u32,Unsigned saturating rounding shift left -TRUE,vqrshrn_high_n_s16,"r: int8x8_t, a: int16x8_t, n: const int",int8x16_t,Signed saturating rounded shift right narrow -TRUE,vqrshrn_high_n_s32,"r: int16x4_t, a: int32x4_t, n: const int",int16x8_t,Signed saturating rounded shift right narrow -TRUE,vqrshrn_high_n_s64,"r: int32x2_t, a: int64x2_t, n: const int",int32x4_t,Signed saturating rounded shift right narrow -TRUE,vqrshrn_high_n_u16,"r: uint8x8_t, a: uint16x8_t, n: const int",uint8x16_t,Unsigned saturating rounded shift right narrow -TRUE,vqrshrn_high_n_u32,"r: uint16x4_t, a: uint32x4_t, n: const int",uint16x8_t,Unsigned saturating rounded shift right narrow -TRUE,vqrshrn_high_n_u64,"r: uint32x2_t, a: uint64x2_t, n: const int",uint32x4_t,Unsigned saturating rounded shift right narrow -TRUE,vqrshrn_n_s16,"a: int16x8_t, n: const int",int8x8_t,Signed saturating rounded shift right narrow -TRUE,vqrshrn_n_s32,"a: int32x4_t, n: const int",int16x4_t,Signed saturating rounded shift right narrow -TRUE,vqrshrn_n_s64,"a: int64x2_t, n: const int",int32x2_t,Signed saturating rounded shift right narrow -TRUE,vqrshrn_n_u16,"a: uint16x8_t, n: const int",uint8x8_t,Unsigned saturating rounded shift right narrow -TRUE,vqrshrn_n_u32,"a: uint32x4_t, n: const int",uint16x4_t,Unsigned saturating rounded shift right narrow -TRUE,vqrshrn_n_u64,"a: uint64x2_t, n: const int",uint32x2_t,Unsigned saturating rounded shift right narrow -TRUE,vqrshrnd_n_s64,"a: i64, n: const int",i32,Signed saturating rounded shift right narrow -TRUE,vqrshrnd_n_u64,"a: u64, n: const int",u32,Unsigned saturating rounded shift right narrow -TRUE,vqrshrnh_n_s16,"a: i16, n: const int",i8,Signed saturating rounded shift right narrow -TRUE,vqrshrnh_n_u16,"a: u16, n: const int",u8,Unsigned saturating rounded shift right narrow -TRUE,vqrshrns_n_s32,"a: i32, n: const int",i16,Signed saturating rounded shift right narrow -TRUE,vqrshrns_n_u32,"a: u32, n: const int",u16,Unsigned saturating rounded shift right narrow -TRUE,vqrshrun_high_n_s16,"r: uint8x8_t, a: int16x8_t, n: const int",uint8x16_t,Signed saturating rounded shift right unsigned narrow -TRUE,vqrshrun_high_n_s32,"r: uint16x4_t, a: int32x4_t, n: const int",uint16x8_t,Signed saturating rounded shift right unsigned narrow -TRUE,vqrshrun_high_n_s64,"r: uint32x2_t, a: int64x2_t, n: const int",uint32x4_t,Signed saturating rounded shift right unsigned narrow -TRUE,vqrshrun_n_s16,"a: int16x8_t, n: const int",uint8x8_t,Signed saturating rounded shift right unsigned narrow -TRUE,vqrshrun_n_s32,"a: int32x4_t, n: const int",uint16x4_t,Signed saturating rounded shift right unsigned narrow -TRUE,vqrshrun_n_s64,"a: int64x2_t, n: const int",uint32x2_t,Signed saturating rounded shift right unsigned narrow -TRUE,vqrshrund_n_s64,"a: i64, n: const int",u32,Signed saturating rounded shift right unsigned narrow -TRUE,vqrshrunh_n_s16,"a: i16, n: const int",u8,Signed saturating rounded shift right unsigned narrow -TRUE,vqrshruns_n_s32,"a: i32, n: const int",u16,Signed saturating rounded shift right unsigned narrow -TRUE,vqshl_n_s16,"a: int16x4_t, n: const int",int16x4_t,Signed saturating shift left -TRUE,vqshl_n_s32,"a: int32x2_t, n: const int",int32x2_t,Signed saturating shift left -TRUE,vqshl_n_s64,"a: int64x1_t, n: const int",int64x1_t,Signed saturating shift left -TRUE,vqshl_n_s8,"a: int8x8_t, n: const int",int8x8_t,Signed saturating shift left -TRUE,vqshl_n_u16,"a: uint16x4_t, n: const int",uint16x4_t,Unsigned saturating shift left -TRUE,vqshl_n_u32,"a: uint32x2_t, n: const int",uint32x2_t,Unsigned saturating shift left -TRUE,vqshl_n_u64,"a: uint64x1_t, n: const int",uint64x1_t,Unsigned saturating shift left -TRUE,vqshl_n_u8,"a: uint8x8_t, n: const int",uint8x8_t,Unsigned saturating shift left -TRUE,vqshl_s16,"a: int16x4_t, b: int16x4_t",int16x4_t,Signed saturating shift left -TRUE,vqshl_s32,"a: int32x2_t, b: int32x2_t",int32x2_t,Signed saturating shift left -TRUE,vqshl_s64,"a: int64x1_t, b: int64x1_t",int64x1_t,Signed saturating shift left -TRUE,vqshl_s8,"a: int8x8_t, b: int8x8_t",int8x8_t,Signed saturating shift left -TRUE,vqshl_u16,"a: uint16x4_t, b: int16x4_t",uint16x4_t,Unsigned saturating shift left -TRUE,vqshl_u32,"a: uint32x2_t, b: int32x2_t",uint32x2_t,Unsigned saturating shift left -TRUE,vqshl_u64,"a: uint64x1_t, b: int64x1_t",uint64x1_t,Unsigned saturating shift left -TRUE,vqshl_u8,"a: uint8x8_t, b: int8x8_t",uint8x8_t,Unsigned saturating shift left -TRUE,vqshlb_n_s8,"a: i8, n: const int",i8,Signed saturating shift left -TRUE,vqshlb_n_u8,"a: u8, n: const int",u8,Unsigned saturating shift left -TRUE,vqshlb_s8,"a: i8, b: i8",i8,Signed saturating shift left -TRUE,vqshlb_u8,"a: u8, b: i8",u8,Unsigned saturating shift left -TRUE,vqshld_n_s64,"a: i64, n: const int",i64,Signed saturating shift left -TRUE,vqshld_n_u64,"a: u64, n: const int",u64,Unsigned saturating shift left -TRUE,vqshld_s64,"a: i64, b: i64",i64,Signed saturating shift left -TRUE,vqshld_u64,"a: u64, b: i64",u64,Unsigned saturating shift left -TRUE,vqshlh_n_s16,"a: i16, n: const int",i16,Signed saturating shift left -TRUE,vqshlh_n_u16,"a: u16, n: const int",u16,Unsigned saturating shift left -TRUE,vqshlh_s16,"a: i16, b: i16",i16,Signed saturating shift left -TRUE,vqshlh_u16,"a: u16, b: i16",u16,Unsigned saturating shift left -TRUE,vqshlq_n_s16,"a: int16x8_t, n: const int",int16x8_t,Signed saturating shift left -TRUE,vqshlq_n_s32,"a: int32x4_t, n: const int",int32x4_t,Signed saturating shift left -TRUE,vqshlq_n_s64,"a: int64x2_t, n: const int",int64x2_t,Signed saturating shift left -TRUE,vqshlq_n_s8,"a: int8x16_t, n: const int",int8x16_t,Signed saturating shift left -TRUE,vqshlq_n_u16,"a: uint16x8_t, n: const int",uint16x8_t,Unsigned saturating shift left -TRUE,vqshlq_n_u32,"a: uint32x4_t, n: const int",uint32x4_t,Unsigned saturating shift left -TRUE,vqshlq_n_u64,"a: uint64x2_t, n: const int",uint64x2_t,Unsigned saturating shift left -TRUE,vqshlq_n_u8,"a: uint8x16_t, n: const int",uint8x16_t,Unsigned saturating shift left -TRUE,vqshlq_s16,"a: int16x8_t, b: int16x8_t",int16x8_t,Signed saturating shift left -TRUE,vqshlq_s32,"a: int32x4_t, b: int32x4_t",int32x4_t,Signed saturating shift left -TRUE,vqshlq_s64,"a: int64x2_t, b: int64x2_t",int64x2_t,Signed saturating shift left -TRUE,vqshlq_s8,"a: int8x16_t, b: int8x16_t",int8x16_t,Signed saturating shift left -TRUE,vqshlq_u16,"a: uint16x8_t, b: int16x8_t",uint16x8_t,Unsigned saturating shift left -TRUE,vqshlq_u32,"a: uint32x4_t, b: int32x4_t",uint32x4_t,Unsigned saturating shift left -TRUE,vqshlq_u64,"a: uint64x2_t, b: int64x2_t",uint64x2_t,Unsigned saturating shift left -TRUE,vqshlq_u8,"a: uint8x16_t, b: int8x16_t",uint8x16_t,Unsigned saturating shift left -TRUE,vqshls_n_s32,"a: i32, n: const int",i32,Signed saturating shift left -TRUE,vqshls_n_u32,"a: u32, n: const int",u32,Unsigned saturating shift left -TRUE,vqshls_s32,"a: i32, b: i32",i32,Signed saturating shift left -TRUE,vqshls_u32,"a: u32, b: i32",u32,Unsigned saturating shift left -FALSE,vqshlu_n_s16,"a: int16x4_t, n: const int",uint16x4_t,Signed saturating shift left unsigned -FALSE,vqshlu_n_s32,"a: int32x2_t, n: const int",uint32x2_t,Signed saturating shift left unsigned -FALSE,vqshlu_n_s64,"a: int64x1_t, n: const int",uint64x1_t,Signed saturating shift left unsigned -FALSE,vqshlu_n_s8,"a: int8x8_t, n: const int",uint8x8_t,Signed saturating shift left unsigned -FALSE,vqshlub_n_s8,"a: i8, n: const int",u8,Signed saturating shift left unsigned -FALSE,vqshlud_n_s64,"a: i64, n: const int",u64,Signed saturating shift left unsigned -FALSE,vqshluh_n_s16,"a: i16, n: const int",u16,Signed saturating shift left unsigned -FALSE,vqshluq_n_s16,"a: int16x8_t, n: const int",uint16x8_t,Signed saturating shift left unsigned -FALSE,vqshluq_n_s32,"a: int32x4_t, n: const int",uint32x4_t,Signed saturating shift left unsigned -FALSE,vqshluq_n_s64,"a: int64x2_t, n: const int",uint64x2_t,Signed saturating shift left unsigned -FALSE,vqshluq_n_s8,"a: int8x16_t, n: const int",uint8x16_t,Signed saturating shift left unsigned -FALSE,vqshlus_n_s32,"a: i32, n: const int",u32,Signed saturating shift left unsigned -TRUE,vqshrn_high_n_s16,"r: int8x8_t, a: int16x8_t, n: const int",int8x16_t,Signed saturating shift right narrow -TRUE,vqshrn_high_n_s32,"r: int16x4_t, a: int32x4_t, n: const int",int16x8_t,Signed saturating shift right narrow -TRUE,vqshrn_high_n_s64,"r: int32x2_t, a: int64x2_t, n: const int",int32x4_t,Signed saturating shift right narrow -TRUE,vqshrn_high_n_u16,"r: uint8x8_t, a: uint16x8_t, n: const int",uint8x16_t,Unsigned saturating shift right narrow -TRUE,vqshrn_high_n_u32,"r: uint16x4_t, a: uint32x4_t, n: const int",uint16x8_t,Unsigned saturating shift right narrow -TRUE,vqshrn_high_n_u64,"r: uint32x2_t, a: uint64x2_t, n: const int",uint32x4_t,Unsigned saturating shift right narrow -TRUE,vqshrn_n_s16,"a: int16x8_t, n: const int",int8x8_t,Signed saturating shift right narrow -TRUE,vqshrn_n_s32,"a: int32x4_t, n: const int",int16x4_t,Signed saturating shift right narrow -TRUE,vqshrn_n_s64,"a: int64x2_t, n: const int",int32x2_t,Signed saturating shift right narrow -TRUE,vqshrn_n_u16,"a: uint16x8_t, n: const int",uint8x8_t,Unsigned saturating shift right narrow -TRUE,vqshrn_n_u32,"a: uint32x4_t, n: const int",uint16x4_t,Unsigned saturating shift right narrow -TRUE,vqshrn_n_u64,"a: uint64x2_t, n: const int",uint32x2_t,Unsigned saturating shift right narrow -TRUE,vqshrnd_n_s64,"a: i64, n: const int",i32,Signed saturating shift right narrow -TRUE,vqshrnd_n_u64,"a: u64, n: const int",u32,Unsigned saturating shift right narrow -TRUE,vqshrnh_n_s16,"a: i16, n: const int",i8,Signed saturating shift right narrow -TRUE,vqshrnh_n_u16,"a: u16, n: const int",u8,Unsigned saturating shift right narrow -TRUE,vqshrns_n_s32,"a: i32, n: const int",i16,Signed saturating shift right narrow -TRUE,vqshrns_n_u32,"a: u32, n: const int",u16,Unsigned saturating shift right narrow -TRUE,vqshrun_high_n_s16,"r: uint8x8_t, a: int16x8_t, n: const int",uint8x16_t,Signed saturating shift right unsigned narrow -TRUE,vqshrun_high_n_s32,"r: uint16x4_t, a: int32x4_t, n: const int",uint16x8_t,Signed saturating shift right unsigned narrow -TRUE,vqshrun_high_n_s64,"r: uint32x2_t, a: int64x2_t, n: const int",uint32x4_t,Signed saturating shift right unsigned narrow -TRUE,vqshrun_n_s16,"a: int16x8_t, n: const int",uint8x8_t,Signed saturating shift right unsigned narrow -TRUE,vqshrun_n_s32,"a: int32x4_t, n: const int",uint16x4_t,Signed saturating shift right unsigned narrow -TRUE,vqshrun_n_s64,"a: int64x2_t, n: const int",uint32x2_t,Signed saturating shift right unsigned narrow -TRUE,vqshrund_n_s64,"a: i64, n: const int",u32,Signed saturating shift right unsigned narrow -TRUE,vqshrunh_n_s16,"a: i16, n: const int",u8,Signed saturating shift right unsigned narrow -TRUE,vqshruns_n_s32,"a: i32, n: const int",u16,Signed saturating shift right unsigned narrow -TRUE,vqsub_s16,"a: int16x4_t, b: int16x4_t",int16x4_t,Signed saturating subtract -TRUE,vqsub_s32,"a: int32x2_t, b: int32x2_t",int32x2_t,Signed saturating subtract -TRUE,vqsub_s64,"a: int64x1_t, b: int64x1_t",int64x1_t,Signed saturating subtract -TRUE,vqsub_s8,"a: int8x8_t, b: int8x8_t",int8x8_t,Signed saturating subtract -TRUE,vqsub_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4_t,Unsigned saturating subtract -TRUE,vqsub_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2_t,Unsigned saturating subtract -TRUE,vqsub_u64,"a: uint64x1_t, b: uint64x1_t",uint64x1_t,Unsigned saturating subtract -TRUE,vqsub_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,Unsigned saturating subtract -TRUE,vqsubb_s8,"a: i8, b: i8",i8,Signed saturating subtract -TRUE,vqsubb_u8,"a: u8, b: u8",u8,Unsigned saturating subtract -TRUE,vqsubd_s64,"a: i64, b: i64",i64,Signed saturating subtract -TRUE,vqsubd_u64,"a: u64, b: u64",u64,Unsigned saturating subtract -TRUE,vqsubh_s16,"a: i16, b: i16",i16,Signed saturating subtract -TRUE,vqsubh_u16,"a: u16, b: u16",u16,Unsigned saturating subtract -TRUE,vqsubq_s16,"a: int16x8_t, b: int16x8_t",int16x8_t,Signed saturating subtract -TRUE,vqsubq_s32,"a: int32x4_t, b: int32x4_t",int32x4_t,Signed saturating subtract -TRUE,vqsubq_s64,"a: int64x2_t, b: int64x2_t",int64x2_t,Signed saturating subtract -TRUE,vqsubq_s8,"a: int8x16_t, b: int8x16_t",int8x16_t,Signed saturating subtract -TRUE,vqsubq_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8_t,Unsigned saturating subtract -TRUE,vqsubq_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,Unsigned saturating subtract -TRUE,vqsubq_u64,"a: uint64x2_t, b: uint64x2_t",uint64x2_t,Unsigned saturating subtract -TRUE,vqsubq_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16_t,Unsigned saturating subtract -TRUE,vqsubs_s32,"a: i32, b: i32",i32,Signed saturating subtract -TRUE,vqsubs_u32,"a: u32, b: u32",u32,Unsigned saturating subtract -TRUE,vqtbl1_p8,"t: poly8x16_t, idx: uint8x8_t",poly8x8_t,Table vector lookup -TRUE,vqtbl1_s8,"t: int8x16_t, idx: uint8x8_t",int8x8_t,Table vector lookup -TRUE,vqtbl1_u8,"t: uint8x16_t, idx: uint8x8_t",uint8x8_t,Table vector lookup -TRUE,vqtbl1q_p8,"t: poly8x16_t, idx: uint8x16_t",poly8x16_t,Table vector lookup -TRUE,vqtbl1q_s8,"t: int8x16_t, idx: uint8x16_t",int8x16_t,Table vector lookup -TRUE,vqtbl1q_u8,"t: uint8x16_t, idx: uint8x16_t",uint8x16_t,Table vector lookup -TRUE,vqtbl2_p8,"t: poly8x16x2_t, idx: uint8x8_t",poly8x8_t,Table vector lookup -TRUE,vqtbl2_s8,"t: int8x16x2_t, idx: uint8x8_t",int8x8_t,Table vector lookup -TRUE,vqtbl2_u8,"t: uint8x16x2_t, idx: uint8x8_t",uint8x8_t,Table vector lookup -TRUE,vqtbl2q_p8,"t: poly8x16x2_t, idx: uint8x16_t",poly8x16_t,Table vector lookup -TRUE,vqtbl2q_s8,"t: int8x16x2_t, idx: uint8x16_t",int8x16_t,Table vector lookup -TRUE,vqtbl2q_u8,"t: uint8x16x2_t, idx: uint8x16_t",uint8x16_t,Table vector lookup -TRUE,vqtbl3_p8,"t: poly8x16x3_t, idx: uint8x8_t",poly8x8_t,Table vector lookup -TRUE,vqtbl3_s8,"t: int8x16x3_t, idx: uint8x8_t",int8x8_t,Table vector lookup -TRUE,vqtbl3_u8,"t: uint8x16x3_t, idx: uint8x8_t",uint8x8_t,Table vector lookup -TRUE,vqtbl3q_p8,"t: poly8x16x3_t, idx: uint8x16_t",poly8x16_t,Table vector lookup -TRUE,vqtbl3q_s8,"t: int8x16x3_t, idx: uint8x16_t",int8x16_t,Table vector lookup -TRUE,vqtbl3q_u8,"t: uint8x16x3_t, idx: uint8x16_t",uint8x16_t,Table vector lookup -TRUE,vqtbl4_p8,"t: poly8x16x4_t, idx: uint8x8_t",poly8x8_t,Table vector lookup -TRUE,vqtbl4_s8,"t: int8x16x4_t, idx: uint8x8_t",int8x8_t,Table vector lookup -TRUE,vqtbl4_u8,"t: uint8x16x4_t, idx: uint8x8_t",uint8x8_t,Table vector lookup -TRUE,vqtbl4q_p8,"t: poly8x16x4_t, idx: uint8x16_t",poly8x16_t,Table vector lookup -TRUE,vqtbl4q_s8,"t: int8x16x4_t, idx: uint8x16_t",int8x16_t,Table vector lookup -TRUE,vqtbl4q_u8,"t: uint8x16x4_t, idx: uint8x16_t",uint8x16_t,Table vector lookup -TRUE,vqtbx1_p8,"a: poly8x8_t, t: poly8x16_t, idx: uint8x8_t",poly8x8_t,Table vector lookup extension -TRUE,vqtbx1_s8,"a: int8x8_t, t: int8x16_t, idx: uint8x8_t",int8x8_t,Table vector lookup extension -TRUE,vqtbx1_u8,"a: uint8x8_t, t: uint8x16_t, idx: uint8x8_t",uint8x8_t,Table vector lookup extension -TRUE,vqtbx1q_p8,"a: poly8x16_t, t: poly8x16_t, idx: uint8x16_t",poly8x16_t,Table vector lookup extension -TRUE,vqtbx1q_s8,"a: int8x16_t, t: int8x16_t, idx: uint8x16_t",int8x16_t,Table vector lookup extension -TRUE,vqtbx1q_u8,"a: uint8x16_t, t: uint8x16_t, idx: uint8x16_t",uint8x16_t,Table vector lookup extension -TRUE,vqtbx2_p8,"a: poly8x8_t, t: poly8x16x2_t, idx: uint8x8_t",poly8x8_t,Table vector lookup extension -TRUE,vqtbx2_s8,"a: int8x8_t, t: int8x16x2_t, idx: uint8x8_t",int8x8_t,Table vector lookup extension -TRUE,vqtbx2_u8,"a: uint8x8_t, t: uint8x16x2_t, idx: uint8x8_t",uint8x8_t,Table vector lookup extension -TRUE,vqtbx2q_p8,"a: poly8x16_t, t: poly8x16x2_t, idx: uint8x16_t",poly8x16_t,Table vector lookup extension -TRUE,vqtbx2q_s8,"a: int8x16_t, t: int8x16x2_t, idx: uint8x16_t",int8x16_t,Table vector lookup extension -TRUE,vqtbx2q_u8,"a: uint8x16_t, t: uint8x16x2_t, idx: uint8x16_t",uint8x16_t,Table vector lookup extension -TRUE,vqtbx3_p8,"a: poly8x8_t, t: poly8x16x3_t, idx: uint8x8_t",poly8x8_t,Table vector lookup extension -TRUE,vqtbx3_s8,"a: int8x8_t, t: int8x16x3_t, idx: uint8x8_t",int8x8_t,Table vector lookup extension -TRUE,vqtbx3_u8,"a: uint8x8_t, t: uint8x16x3_t, idx: uint8x8_t",uint8x8_t,Table vector lookup extension -TRUE,vqtbx3q_p8,"a: poly8x16_t, t: poly8x16x3_t, idx: uint8x16_t",poly8x16_t,Table vector lookup extension -TRUE,vqtbx3q_s8,"a: int8x16_t, t: int8x16x3_t, idx: uint8x16_t",int8x16_t,Table vector lookup extension -TRUE,vqtbx3q_u8,"a: uint8x16_t, t: uint8x16x3_t, idx: uint8x16_t",uint8x16_t,Table vector lookup extension -TRUE,vqtbx4_p8,"a: poly8x8_t, t: poly8x16x4_t, idx: uint8x8_t",poly8x8_t,Table vector lookup extension -TRUE,vqtbx4_s8,"a: int8x8_t, t: int8x16x4_t, idx: uint8x8_t",int8x8_t,Table vector lookup extension -TRUE,vqtbx4_u8,"a: uint8x8_t, t: uint8x16x4_t, idx: uint8x8_t",uint8x8_t,Table vector lookup extension -TRUE,vqtbx4q_p8,"a: poly8x16_t, t: poly8x16x4_t, idx: uint8x16_t",poly8x16_t,Table vector lookup extension -TRUE,vqtbx4q_s8,"a: int8x16_t, t: int8x16x4_t, idx: uint8x16_t",int8x16_t,Table vector lookup extension -TRUE,vqtbx4q_u8,"a: uint8x16_t, t: uint8x16x4_t, idx: uint8x16_t",uint8x16_t,Table vector lookup extension -FALSE,vraddhn_high_s16,"r: int8x8_t, a: int16x8_t, b: int16x8_t",int8x16_t,Rounding add returning high narrow -FALSE,vraddhn_high_s32,"r: int16x4_t, a: int32x4_t, b: int32x4_t",int16x8_t,Rounding add returning high narrow -FALSE,vraddhn_high_s64,"r: int32x2_t, a: int64x2_t, b: int64x2_t",int32x4_t,Rounding add returning high narrow -FALSE,vraddhn_high_u16,"r: uint8x8_t, a: uint16x8_t, b: uint16x8_t",uint8x16_t,Rounding add returning high narrow -FALSE,vraddhn_high_u32,"r: uint16x4_t, a: uint32x4_t, b: uint32x4_t",uint16x8_t,Rounding add returning high narrow -FALSE,vraddhn_high_u64,"r: uint32x2_t, a: uint64x2_t, b: uint64x2_t",uint32x4_t,Rounding add returning high narrow -FALSE,vraddhn_s16,"a: int16x8_t, b: int16x8_t",int8x8_t,Rounding add returning high narrow -FALSE,vraddhn_s32,"a: int32x4_t, b: int32x4_t",int16x4_t,Rounding add returning high narrow -FALSE,vraddhn_s64,"a: int64x2_t, b: int64x2_t",int32x2_t,Rounding add returning high narrow -FALSE,vraddhn_u16,"a: uint16x8_t, b: uint16x8_t",uint8x8_t,Rounding add returning high narrow -FALSE,vraddhn_u32,"a: uint32x4_t, b: uint32x4_t",uint16x4_t,Rounding add returning high narrow -FALSE,vraddhn_u64,"a: uint64x2_t, b: uint64x2_t",uint32x2_t,Rounding add returning high narrow -FALSE,vrax1q_u64,"a: uint64x2_t, b: uint64x2_t",uint64x2_t,Rotate and exclusive OR -TRUE,vrbit_p8,a: poly8x8_t,poly8x8_t,Reverse bit order -TRUE,vrbit_s8,a: int8x8_t,int8x8_t,Reverse bit order -TRUE,vrbit_u8,a: uint8x8_t,uint8x8_t,Reverse bit order -TRUE,vrbitq_p8,a: poly8x16_t,poly8x16_t,Reverse bit order -TRUE,vrbitq_s8,a: int8x16_t,int8x16_t,Reverse bit order -TRUE,vrbitq_u8,a: uint8x16_t,uint8x16_t,Reverse bit order -FALSE,vrecpe_f16,a: float16x4_t,float16x4_t,Floating-point reciprocal estimate -TRUE,vrecpe_f32,a: float32x2_t,float32x2_t,Floating-point reciprocal estimate -TRUE,vrecpe_f64,a: float64x1_t,float64x1_t,Floating-point reciprocal estimate -FALSE,vrecpe_u32,a: uint32x2_t,uint32x2_t,Unsigned reciprocal estimate -FALSE,vrecped_f64,a: float64_t,float64_t,Floating-point reciprocal estimate -FALSE,vrecpeh_f16,a: float16_t,float16_t,Floating-point reciprocal estimate -FALSE,vrecpeq_f16,a: float16x8_t,float16x8_t,Floating-point reciprocal estimate -TRUE,vrecpeq_f32,a: float32x4_t,float32x4_t,Floating-point reciprocal estimate -TRUE,vrecpeq_f64,a: float64x2_t,float64x2_t,Floating-point reciprocal estimate -FALSE,vrecpeq_u32,a: uint32x4_t,uint32x4_t,Unsigned reciprocal estimate -FALSE,vrecpes_f32,a: f32,f32,Floating-point reciprocal estimate -FALSE,vrecps_f16,"a: float16x4_t, b: float16x4_t",float16x4_t,Floating-point reciprocal step -FALSE,vrecps_f32,"a: float32x2_t, b: float32x2_t",float32x2_t,Floating-point reciprocal step -FALSE,vrecps_f64,"a: float64x1_t, b: float64x1_t",float64x1_t,Floating-point reciprocal step -FALSE,vrecpsd_f64,"a: float64_t, b: float64_t",float64_t,Floating-point reciprocal step -FALSE,vrecpsh_f16,"a: float16_t, b: float16_t",float16_t,Floating-point reciprocal step -FALSE,vrecpsq_f16,"a: float16x8_t, b: float16x8_t",float16x8_t,Floating-point reciprocal step -FALSE,vrecpsq_f32,"a: float32x4_t, b: float32x4_t",float32x4_t,Floating-point reciprocal step -FALSE,vrecpsq_f64,"a: float64x2_t, b: float64x2_t",float64x2_t,Floating-point reciprocal step -FALSE,vrecpss_f32,"a: f32, b: f32",f32,Floating-point reciprocal step -FALSE,vrecpxd_f64,a: float64_t,float64_t,Floating-point reciprocal exponent -FALSE,vrecpxh_f16,a: float16_t,float16_t,Floating-point reciprocal exponent -FALSE,vrecpxs_f32,a: f32,f32,Floating-point reciprocal exponent -FALSE,vreinterpret_bf16_f32,a: float32x2_t,bfloat16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_bf16_f64,a: float64x1_t,bfloat16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_bf16_p16,a: poly16x4_t,bfloat16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_bf16_p64,a: poly64x1_t,bfloat16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_bf16_p8,a: poly8x8_t,bfloat16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_bf16_s16,a: int16x4_t,bfloat16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_bf16_s32,a: int32x2_t,bfloat16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_bf16_s64,a: int64x1_t,bfloat16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_bf16_s8,a: int8x8_t,bfloat16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_bf16_u16,a: uint16x4_t,bfloat16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_bf16_u32,a: uint32x2_t,bfloat16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_bf16_u64,a: uint64x1_t,bfloat16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_bf16_u8,a: uint8x8_t,bfloat16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_f16_f32,a: float32x2_t,float16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_f16_f64,a: float64x1_t,float16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_f16_p16,a: poly16x4_t,float16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_f16_p64,a: poly64x1_t,float16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_f16_p8,a: poly8x8_t,float16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_f16_s16,a: int16x4_t,float16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_f16_s32,a: int32x2_t,float16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_f16_s64,a: int64x1_t,float16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_f16_s8,a: int8x8_t,float16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_f16_u16,a: uint16x4_t,float16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_f16_u32,a: uint32x2_t,float16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_f16_u64,a: uint64x1_t,float16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_f16_u8,a: uint8x8_t,float16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_f32_bf16,a: bfloat16x4_t,float32x2_t,Vector reinterpret cast operation -FALSE,vreinterpret_f32_f16,a: float16x4_t,float32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_f32_f64,a: float64x1_t,float32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_f32_p16,a: poly16x4_t,float32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_f32_p8,a: poly8x8_t,float32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_f32_s16,a: int16x4_t,float32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_f32_s32,a: int32x2_t,float32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_f32_s64,a: int64x1_t,float32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_f32_s8,a: int8x8_t,float32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_f32_u16,a: uint16x4_t,float32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_f32_u32,a: uint32x2_t,float32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_f32_u64,a: uint64x1_t,float32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_f32_u8,a: uint8x8_t,float32x2_t,Vector reinterpret cast operation -FALSE,vreinterpret_f64_bf16,a: bfloat16x4_t,float64x1_t,Vector reinterpret cast operation -FALSE,vreinterpret_f64_f16,a: float16x4_t,float64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_f64_f32,a: float32x2_t,float64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_f64_p16,a: poly16x4_t,float64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_f64_p64,a: poly64x1_t,float64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_f64_p8,a: poly8x8_t,float64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_f64_s16,a: int16x4_t,float64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_f64_s32,a: int32x2_t,float64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_f64_s64,a: int64x1_t,float64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_f64_s8,a: int8x8_t,float64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_f64_u16,a: uint16x4_t,float64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_f64_u32,a: uint32x2_t,float64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_f64_u64,a: uint64x1_t,float64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_f64_u8,a: uint8x8_t,float64x1_t,Vector reinterpret cast operation -FALSE,vreinterpret_p16_bf16,a: bfloat16x4_t,poly16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_p16_f16,a: float16x4_t,poly16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_p16_f32,a: float32x2_t,poly16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_p16_f64,a: float64x1_t,poly16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_p16_p64,a: poly64x1_t,poly16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_p16_p8,a: poly8x8_t,poly16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_p16_s16,a: int16x4_t,poly16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_p16_s32,a: int32x2_t,poly16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_p16_s64,a: int64x1_t,poly16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_p16_s8,a: int8x8_t,poly16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_p16_u16,a: uint16x4_t,poly16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_p16_u32,a: uint32x2_t,poly16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_p16_u64,a: uint64x1_t,poly16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_p16_u8,a: uint8x8_t,poly16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_p64_bf16,a: bfloat16x4_t,poly64x1_t,Vector reinterpret cast operation -FALSE,vreinterpret_p64_f16,a: float16x4_t,poly64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_p64_f32,a: float32x2_t,poly64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_p64_f64,a: float64x1_t,poly64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_p64_p16,a: poly16x4_t,poly64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_p64_p8,a: poly8x8_t,poly64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_p64_s16,a: int16x4_t,poly64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_p64_s32,a: int32x2_t,poly64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_p64_s8,a: int8x8_t,poly64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_p64_u16,a: uint16x4_t,poly64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_p64_u32,a: uint32x2_t,poly64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_p64_u64,a: uint64x1_t,poly64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_p64_u8,a: uint8x8_t,poly64x1_t,Vector reinterpret cast operation -FALSE,vreinterpret_p8_bf16,a: bfloat16x4_t,poly8x8_t,Vector reinterpret cast operation -FALSE,vreinterpret_p8_f16,a: float16x4_t,poly8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_p8_f32,a: float32x2_t,poly8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_p8_f64,a: float64x1_t,poly8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_p8_p16,a: poly16x4_t,poly8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_p8_p64,a: poly64x1_t,poly8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_p8_s16,a: int16x4_t,poly8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_p8_s32,a: int32x2_t,poly8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_p8_s64,a: int64x1_t,poly8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_p8_s8,a: int8x8_t,poly8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_p8_u16,a: uint16x4_t,poly8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_p8_u32,a: uint32x2_t,poly8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_p8_u64,a: uint64x1_t,poly8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_p8_u8,a: uint8x8_t,poly8x8_t,Vector reinterpret cast operation -FALSE,vreinterpret_s16_bf16,a: bfloat16x4_t,int16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_s16_f16,a: float16x4_t,int16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_s16_f32,a: float32x2_t,int16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_s16_f64,a: float64x1_t,int16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_s16_p16,a: poly16x4_t,int16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_s16_p64,a: poly64x1_t,int16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_s16_p8,a: poly8x8_t,int16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_s16_s32,a: int32x2_t,int16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_s16_s64,a: int64x1_t,int16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_s16_s8,a: int8x8_t,int16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_s16_u16,a: uint16x4_t,int16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_s16_u32,a: uint32x2_t,int16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_s16_u64,a: uint64x1_t,int16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_s16_u8,a: uint8x8_t,int16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_s32_bf16,a: bfloat16x4_t,int32x2_t,Vector reinterpret cast operation -FALSE,vreinterpret_s32_f16,a: float16x4_t,int32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_s32_f32,a: float32x2_t,int32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_s32_f64,a: float64x1_t,int32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_s32_p16,a: poly16x4_t,int32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_s32_p64,a: poly64x1_t,int32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_s32_p8,a: poly8x8_t,int32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_s32_s16,a: int16x4_t,int32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_s32_s64,a: int64x1_t,int32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_s32_s8,a: int8x8_t,int32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_s32_u16,a: uint16x4_t,int32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_s32_u32,a: uint32x2_t,int32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_s32_u64,a: uint64x1_t,int32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_s32_u8,a: uint8x8_t,int32x2_t,Vector reinterpret cast operation -FALSE,vreinterpret_s64_bf16,a: bfloat16x4_t,int64x1_t,Vector reinterpret cast operation -FALSE,vreinterpret_s64_f16,a: float16x4_t,int64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_s64_f32,a: float32x2_t,int64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_s64_f64,a: float64x1_t,int64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_s64_p16,a: poly16x4_t,int64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_s64_p64,a: poly64x1_t,int64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_s64_p8,a: poly8x8_t,int64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_s64_s16,a: int16x4_t,int64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_s64_s32,a: int32x2_t,int64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_s64_s8,a: int8x8_t,int64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_s64_u16,a: uint16x4_t,int64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_s64_u32,a: uint32x2_t,int64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_s64_u64,a: uint64x1_t,int64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_s64_u8,a: uint8x8_t,int64x1_t,Vector reinterpret cast operation -FALSE,vreinterpret_s8_bf16,a: bfloat16x4_t,int8x8_t,Vector reinterpret cast operation -FALSE,vreinterpret_s8_f16,a: float16x4_t,int8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_s8_f32,a: float32x2_t,int8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_s8_f64,a: float64x1_t,int8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_s8_p16,a: poly16x4_t,int8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_s8_p64,a: poly64x1_t,int8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_s8_p8,a: poly8x8_t,int8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_s8_s16,a: int16x4_t,int8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_s8_s32,a: int32x2_t,int8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_s8_s64,a: int64x1_t,int8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_s8_u16,a: uint16x4_t,int8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_s8_u32,a: uint32x2_t,int8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_s8_u64,a: uint64x1_t,int8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_s8_u8,a: uint8x8_t,int8x8_t,Vector reinterpret cast operation -FALSE,vreinterpret_u16_bf16,a: bfloat16x4_t,uint16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_u16_f16,a: float16x4_t,uint16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_u16_f32,a: float32x2_t,uint16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_u16_f64,a: float64x1_t,uint16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_u16_p16,a: poly16x4_t,uint16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_u16_p64,a: poly64x1_t,uint16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_u16_p8,a: poly8x8_t,uint16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_u16_s16,a: int16x4_t,uint16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_u16_s32,a: int32x2_t,uint16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_u16_s64,a: int64x1_t,uint16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_u16_s8,a: int8x8_t,uint16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_u16_u32,a: uint32x2_t,uint16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_u16_u64,a: uint64x1_t,uint16x4_t,Vector reinterpret cast operation -TRUE,vreinterpret_u16_u8,a: uint8x8_t,uint16x4_t,Vector reinterpret cast operation -FALSE,vreinterpret_u32_bf16,a: bfloat16x4_t,uint32x2_t,Vector reinterpret cast operation -FALSE,vreinterpret_u32_f16,a: float16x4_t,uint32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_u32_f32,a: float32x2_t,uint32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_u32_f64,a: float64x1_t,uint32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_u32_p16,a: poly16x4_t,uint32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_u32_p64,a: poly64x1_t,uint32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_u32_p8,a: poly8x8_t,uint32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_u32_s16,a: int16x4_t,uint32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_u32_s32,a: int32x2_t,uint32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_u32_s64,a: int64x1_t,uint32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_u32_s8,a: int8x8_t,uint32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_u32_u16,a: uint16x4_t,uint32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_u32_u64,a: uint64x1_t,uint32x2_t,Vector reinterpret cast operation -TRUE,vreinterpret_u32_u8,a: uint8x8_t,uint32x2_t,Vector reinterpret cast operation -FALSE,vreinterpret_u64_bf16,a: bfloat16x4_t,uint64x1_t,Vector reinterpret cast operation -FALSE,vreinterpret_u64_f16,a: float16x4_t,uint64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_u64_f32,a: float32x2_t,uint64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_u64_f64,a: float64x1_t,uint64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_u64_p16,a: poly16x4_t,uint64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_u64_p64,a: poly64x1_t,uint64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_u64_p8,a: poly8x8_t,uint64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_u64_s16,a: int16x4_t,uint64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_u64_s32,a: int32x2_t,uint64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_u64_s64,a: int64x1_t,uint64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_u64_s8,a: int8x8_t,uint64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_u64_u16,a: uint16x4_t,uint64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_u64_u32,a: uint32x2_t,uint64x1_t,Vector reinterpret cast operation -TRUE,vreinterpret_u64_u8,a: uint8x8_t,uint64x1_t,Vector reinterpret cast operation -FALSE,vreinterpret_u8_bf16,a: bfloat16x4_t,uint8x8_t,Vector reinterpret cast operation -FALSE,vreinterpret_u8_f16,a: float16x4_t,uint8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_u8_f32,a: float32x2_t,uint8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_u8_f64,a: float64x1_t,uint8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_u8_p16,a: poly16x4_t,uint8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_u8_p64,a: poly64x1_t,uint8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_u8_p8,a: poly8x8_t,uint8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_u8_s16,a: int16x4_t,uint8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_u8_s32,a: int32x2_t,uint8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_u8_s64,a: int64x1_t,uint8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_u8_s8,a: int8x8_t,uint8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_u8_u16,a: uint16x4_t,uint8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_u8_u32,a: uint32x2_t,uint8x8_t,Vector reinterpret cast operation -TRUE,vreinterpret_u8_u64,a: uint64x1_t,uint8x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_bf16_f32,a: float32x4_t,bfloat16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_bf16_f64,a: float64x2_t,bfloat16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_bf16_p128,a: poly128_t,bfloat16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_bf16_p16,a: poly16x8_t,bfloat16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_bf16_p64,a: poly64x2_t,bfloat16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_bf16_p8,a: poly8x16_t,bfloat16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_bf16_s16,a: int16x8_t,bfloat16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_bf16_s32,a: int32x4_t,bfloat16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_bf16_s64,a: int64x2_t,bfloat16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_bf16_s8,a: int8x16_t,bfloat16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_bf16_u16,a: uint16x8_t,bfloat16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_bf16_u32,a: uint32x4_t,bfloat16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_bf16_u64,a: uint64x2_t,bfloat16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_bf16_u8,a: uint8x16_t,bfloat16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_f16_f32,a: float32x4_t,float16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_f16_f64,a: float64x2_t,float16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_f16_p128,a: poly128_t,float16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_f16_p16,a: poly16x8_t,float16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_f16_p64,a: poly64x2_t,float16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_f16_p8,a: poly8x16_t,float16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_f16_s16,a: int16x8_t,float16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_f16_s32,a: int32x4_t,float16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_f16_s64,a: int64x2_t,float16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_f16_s8,a: int8x16_t,float16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_f16_u16,a: uint16x8_t,float16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_f16_u32,a: uint32x4_t,float16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_f16_u64,a: uint64x2_t,float16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_f16_u8,a: uint8x16_t,float16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_f32_bf16,a: bfloat16x8_t,float32x4_t,Vector reinterpret cast operation -FALSE,vreinterpretq_f32_f16,a: float16x8_t,float32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_f32_f64,a: float64x2_t,float32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_f32_p16,a: poly16x8_t,float32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_f32_p8,a: poly8x16_t,float32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_f32_s16,a: int16x8_t,float32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_f32_s32,a: int32x4_t,float32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_f32_s64,a: int64x2_t,float32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_f32_s8,a: int8x16_t,float32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_f32_u16,a: uint16x8_t,float32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_f32_u32,a: uint32x4_t,float32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_f32_u64,a: uint64x2_t,float32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_f32_u8,a: uint8x16_t,float32x4_t,Vector reinterpret cast operation -FALSE,vreinterpretq_f64_bf16,a: bfloat16x8_t,float64x2_t,Vector reinterpret cast operation -FALSE,vreinterpretq_f64_f16,a: float16x8_t,float64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_f64_f32,a: float32x4_t,float64x2_t,Vector reinterpret cast operation -FALSE,vreinterpretq_f64_p128,a: poly128_t,float64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_f64_p16,a: poly16x8_t,float64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_f64_p64,a: poly64x2_t,float64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_f64_p8,a: poly8x16_t,float64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_f64_s16,a: int16x8_t,float64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_f64_s32,a: int32x4_t,float64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_f64_s64,a: int64x2_t,float64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_f64_s8,a: int8x16_t,float64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_f64_u16,a: uint16x8_t,float64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_f64_u32,a: uint32x4_t,float64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_f64_u64,a: uint64x2_t,float64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_f64_u8,a: uint8x16_t,float64x2_t,Vector reinterpret cast operation -FALSE,vreinterpretq_p128_bf16,a: bfloat16x8_t,poly128_t,Vector reinterpret cast operation -FALSE,vreinterpretq_p128_f16,a: float16x8_t,poly128_t,Vector reinterpret cast operation -FALSE,vreinterpretq_p128_f32,a: float32x4_t,poly128_t,Vector reinterpret cast operation -FALSE,vreinterpretq_p128_f64,a: float64x2_t,poly128_t,Vector reinterpret cast operation -FALSE,vreinterpretq_p128_p16,a: poly16x8_t,poly128_t,Vector reinterpret cast operation -FALSE,vreinterpretq_p128_p8,a: poly8x16_t,poly128_t,Vector reinterpret cast operation -FALSE,vreinterpretq_p128_s16,a: int16x8_t,poly128_t,Vector reinterpret cast operation -FALSE,vreinterpretq_p128_s32,a: int32x4_t,poly128_t,Vector reinterpret cast operation -FALSE,vreinterpretq_p128_s64,a: int64x2_t,poly128_t,Vector reinterpret cast operation -FALSE,vreinterpretq_p128_s8,a: int8x16_t,poly128_t,Vector reinterpret cast operation -FALSE,vreinterpretq_p128_u16,a: uint16x8_t,poly128_t,Vector reinterpret cast operation -FALSE,vreinterpretq_p128_u32,a: uint32x4_t,poly128_t,Vector reinterpret cast operation -FALSE,vreinterpretq_p128_u64,a: uint64x2_t,poly128_t,Vector reinterpret cast operation -FALSE,vreinterpretq_p128_u8,a: uint8x16_t,poly128_t,Vector reinterpret cast operation -FALSE,vreinterpretq_p16_bf16,a: bfloat16x8_t,poly16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_p16_f16,a: float16x8_t,poly16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p16_f32,a: float32x4_t,poly16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p16_f64,a: float64x2_t,poly16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_p16_p128,a: poly128_t,poly16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p16_p64,a: poly64x2_t,poly16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p16_p8,a: poly8x16_t,poly16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p16_s16,a: int16x8_t,poly16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p16_s32,a: int32x4_t,poly16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p16_s64,a: int64x2_t,poly16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p16_s8,a: int8x16_t,poly16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p16_u16,a: uint16x8_t,poly16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p16_u32,a: uint32x4_t,poly16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p16_u64,a: uint64x2_t,poly16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p16_u8,a: uint8x16_t,poly16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_p64_bf16,a: bfloat16x8_t,poly64x2_t,Vector reinterpret cast operation -FALSE,vreinterpretq_p64_f16,a: float16x8_t,poly64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p64_f32,a: float32x4_t,poly64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p64_f64,a: float64x2_t,poly64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p64_p16,a: poly16x8_t,poly64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p64_p8,a: poly8x16_t,poly64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p64_s16,a: int16x8_t,poly64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p64_s32,a: int32x4_t,poly64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p64_s64,a: int64x2_t,poly64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p64_s8,a: int8x16_t,poly64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p64_u16,a: uint16x8_t,poly64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p64_u32,a: uint32x4_t,poly64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p64_u64,a: uint64x2_t,poly64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p64_u8,a: uint8x16_t,poly64x2_t,Vector reinterpret cast operation -FALSE,vreinterpretq_p8_bf16,a: bfloat16x8_t,poly8x16_t,Vector reinterpret cast operation -FALSE,vreinterpretq_p8_f16,a: float16x8_t,poly8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p8_f32,a: float32x4_t,poly8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p8_f64,a: float64x2_t,poly8x16_t,Vector reinterpret cast operation -FALSE,vreinterpretq_p8_p128,a: poly128_t,poly8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p8_p16,a: poly16x8_t,poly8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p8_p64,a: poly64x2_t,poly8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p8_s16,a: int16x8_t,poly8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p8_s32,a: int32x4_t,poly8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p8_s64,a: int64x2_t,poly8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p8_s8,a: int8x16_t,poly8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p8_u16,a: uint16x8_t,poly8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p8_u32,a: uint32x4_t,poly8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p8_u64,a: uint64x2_t,poly8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_p8_u8,a: uint8x16_t,poly8x16_t,Vector reinterpret cast operation -FALSE,vreinterpretq_s16_bf16,a: bfloat16x8_t,int16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_s16_f16,a: float16x8_t,int16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s16_f32,a: float32x4_t,int16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s16_f64,a: float64x2_t,int16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_s16_p128,a: poly128_t,int16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s16_p16,a: poly16x8_t,int16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s16_p64,a: poly64x2_t,int16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s16_p8,a: poly8x16_t,int16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s16_s32,a: int32x4_t,int16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s16_s64,a: int64x2_t,int16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s16_s8,a: int8x16_t,int16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s16_u16,a: uint16x8_t,int16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s16_u32,a: uint32x4_t,int16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s16_u64,a: uint64x2_t,int16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s16_u8,a: uint8x16_t,int16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_s32_bf16,a: bfloat16x8_t,int32x4_t,Vector reinterpret cast operation -FALSE,vreinterpretq_s32_f16,a: float16x8_t,int32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s32_f32,a: float32x4_t,int32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s32_f64,a: float64x2_t,int32x4_t,Vector reinterpret cast operation -FALSE,vreinterpretq_s32_p128,a: poly128_t,int32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s32_p16,a: poly16x8_t,int32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s32_p64,a: poly64x2_t,int32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s32_p8,a: poly8x16_t,int32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s32_s16,a: int16x8_t,int32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s32_s64,a: int64x2_t,int32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s32_s8,a: int8x16_t,int32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s32_u16,a: uint16x8_t,int32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s32_u32,a: uint32x4_t,int32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s32_u64,a: uint64x2_t,int32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s32_u8,a: uint8x16_t,int32x4_t,Vector reinterpret cast operation -FALSE,vreinterpretq_s64_bf16,a: bfloat16x8_t,int64x2_t,Vector reinterpret cast operation -FALSE,vreinterpretq_s64_f16,a: float16x8_t,int64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s64_f32,a: float32x4_t,int64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s64_f64,a: float64x2_t,int64x2_t,Vector reinterpret cast operation -FALSE,vreinterpretq_s64_p128,a: poly128_t,int64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s64_p16,a: poly16x8_t,int64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s64_p64,a: poly64x2_t,int64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s64_p8,a: poly8x16_t,int64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s64_s16,a: int16x8_t,int64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s64_s32,a: int32x4_t,int64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s64_s8,a: int8x16_t,int64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s64_u16,a: uint16x8_t,int64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s64_u32,a: uint32x4_t,int64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s64_u64,a: uint64x2_t,int64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s64_u8,a: uint8x16_t,int64x2_t,Vector reinterpret cast operation -FALSE,vreinterpretq_s8_bf16,a: bfloat16x8_t,int8x16_t,Vector reinterpret cast operation -FALSE,vreinterpretq_s8_f16,a: float16x8_t,int8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s8_f32,a: float32x4_t,int8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s8_f64,a: float64x2_t,int8x16_t,Vector reinterpret cast operation -FALSE,vreinterpretq_s8_p128,a: poly128_t,int8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s8_p16,a: poly16x8_t,int8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s8_p64,a: poly64x2_t,int8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s8_p8,a: poly8x16_t,int8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s8_s16,a: int16x8_t,int8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s8_s32,a: int32x4_t,int8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s8_s64,a: int64x2_t,int8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s8_u16,a: uint16x8_t,int8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s8_u32,a: uint32x4_t,int8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s8_u64,a: uint64x2_t,int8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_s8_u8,a: uint8x16_t,int8x16_t,Vector reinterpret cast operation -FALSE,vreinterpretq_u16_bf16,a: bfloat16x8_t,uint16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_u16_f16,a: float16x8_t,uint16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u16_f32,a: float32x4_t,uint16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u16_f64,a: float64x2_t,uint16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_u16_p128,a: poly128_t,uint16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u16_p16,a: poly16x8_t,uint16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u16_p64,a: poly64x2_t,uint16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u16_p8,a: poly8x16_t,uint16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u16_s16,a: int16x8_t,uint16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u16_s32,a: int32x4_t,uint16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u16_s64,a: int64x2_t,uint16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u16_s8,a: int8x16_t,uint16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u16_u32,a: uint32x4_t,uint16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u16_u64,a: uint64x2_t,uint16x8_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u16_u8,a: uint8x16_t,uint16x8_t,Vector reinterpret cast operation -FALSE,vreinterpretq_u32_bf16,a: bfloat16x8_t,uint32x4_t,Vector reinterpret cast operation -FALSE,vreinterpretq_u32_f16,a: float16x8_t,uint32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u32_f32,a: float32x4_t,uint32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u32_f64,a: float64x2_t,uint32x4_t,Vector reinterpret cast operation -FALSE,vreinterpretq_u32_p128,a: poly128_t,uint32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u32_p16,a: poly16x8_t,uint32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u32_p64,a: poly64x2_t,uint32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u32_p8,a: poly8x16_t,uint32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u32_s16,a: int16x8_t,uint32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u32_s32,a: int32x4_t,uint32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u32_s64,a: int64x2_t,uint32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u32_s8,a: int8x16_t,uint32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u32_u16,a: uint16x8_t,uint32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u32_u64,a: uint64x2_t,uint32x4_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u32_u8,a: uint8x16_t,uint32x4_t,Vector reinterpret cast operation -FALSE,vreinterpretq_u64_bf16,a: bfloat16x8_t,uint64x2_t,Vector reinterpret cast operation -FALSE,vreinterpretq_u64_f16,a: float16x8_t,uint64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u64_f32,a: float32x4_t,uint64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u64_f64,a: float64x2_t,uint64x2_t,Vector reinterpret cast operation -FALSE,vreinterpretq_u64_p128,a: poly128_t,uint64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u64_p16,a: poly16x8_t,uint64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u64_p64,a: poly64x2_t,uint64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u64_p8,a: poly8x16_t,uint64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u64_s16,a: int16x8_t,uint64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u64_s32,a: int32x4_t,uint64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u64_s64,a: int64x2_t,uint64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u64_s8,a: int8x16_t,uint64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u64_u16,a: uint16x8_t,uint64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u64_u32,a: uint32x4_t,uint64x2_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u64_u8,a: uint8x16_t,uint64x2_t,Vector reinterpret cast operation -FALSE,vreinterpretq_u8_bf16,a: bfloat16x8_t,uint8x16_t,Vector reinterpret cast operation -FALSE,vreinterpretq_u8_f16,a: float16x8_t,uint8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u8_f32,a: float32x4_t,uint8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u8_f64,a: float64x2_t,uint8x16_t,Vector reinterpret cast operation -FALSE,vreinterpretq_u8_p128,a: poly128_t,uint8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u8_p16,a: poly16x8_t,uint8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u8_p64,a: poly64x2_t,uint8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u8_p8,a: poly8x16_t,uint8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u8_s16,a: int16x8_t,uint8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u8_s32,a: int32x4_t,uint8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u8_s64,a: int64x2_t,uint8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u8_s8,a: int8x16_t,uint8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u8_u16,a: uint16x8_t,uint8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u8_u32,a: uint32x4_t,uint8x16_t,Vector reinterpret cast operation -TRUE,vreinterpretq_u8_u64,a: uint64x2_t,uint8x16_t,Vector reinterpret cast operation -TRUE,vrev16_p8,vec: poly8x8_t,poly8x8_t,Reverse elements in 16-bit halfwords -TRUE,vrev16_s8,vec: int8x8_t,int8x8_t,Reverse elements in 16-bit halfwords -TRUE,vrev16_u8,vec: uint8x8_t,uint8x8_t,Reverse elements in 16-bit halfwords -TRUE,vrev16q_p8,vec: poly8x16_t,poly8x16_t,Reverse elements in 16-bit halfwords -TRUE,vrev16q_s8,vec: int8x16_t,int8x16_t,Reverse elements in 16-bit halfwords -TRUE,vrev16q_u8,vec: uint8x16_t,uint8x16_t,Reverse elements in 16-bit halfwords -TRUE,vrev32_p16,vec: poly16x4_t,poly16x4_t,Reverse elements in 32-bit words -TRUE,vrev32_p8,vec: poly8x8_t,poly8x8_t,Reverse elements in 32-bit words -TRUE,vrev32_s16,vec: int16x4_t,int16x4_t,Reverse elements in 32-bit words -TRUE,vrev32_s8,vec: int8x8_t,int8x8_t,Reverse elements in 32-bit words -TRUE,vrev32_u16,vec: uint16x4_t,uint16x4_t,Reverse elements in 32-bit words -TRUE,vrev32_u8,vec: uint8x8_t,uint8x8_t,Reverse elements in 32-bit words -TRUE,vrev32q_p16,vec: poly16x8_t,poly16x8_t,Reverse elements in 32-bit words -TRUE,vrev32q_p8,vec: poly8x16_t,poly8x16_t,Reverse elements in 32-bit words -TRUE,vrev32q_s16,vec: int16x8_t,int16x8_t,Reverse elements in 32-bit words -TRUE,vrev32q_s8,vec: int8x16_t,int8x16_t,Reverse elements in 32-bit words -TRUE,vrev32q_u16,vec: uint16x8_t,uint16x8_t,Reverse elements in 32-bit words -TRUE,vrev32q_u8,vec: uint8x16_t,uint8x16_t,Reverse elements in 32-bit words -FALSE,vrev64_f16,vec: float16x4_t,float16x4_t,Reverse elements in 64-bit doublewords -TRUE,vrev64_f32,vec: float32x2_t,float32x2_t,Reverse elements in 64-bit doublewords -TRUE,vrev64_p16,vec: poly16x4_t,poly16x4_t,Reverse elements in 64-bit doublewords -TRUE,vrev64_p8,vec: poly8x8_t,poly8x8_t,Reverse elements in 64-bit doublewords -TRUE,vrev64_s16,vec: int16x4_t,int16x4_t,Reverse elements in 64-bit doublewords -TRUE,vrev64_s32,vec: int32x2_t,int32x2_t,Reverse elements in 64-bit doublewords -TRUE,vrev64_s8,vec: int8x8_t,int8x8_t,Reverse elements in 64-bit doublewords -TRUE,vrev64_u16,vec: uint16x4_t,uint16x4_t,Reverse elements in 64-bit doublewords -TRUE,vrev64_u32,vec: uint32x2_t,uint32x2_t,Reverse elements in 64-bit doublewords -TRUE,vrev64_u8,vec: uint8x8_t,uint8x8_t,Reverse elements in 64-bit doublewords -FALSE,vrev64q_f16,vec: float16x8_t,float16x8_t,Reverse elements in 64-bit doublewords -TRUE,vrev64q_f32,vec: float32x4_t,float32x4_t,Reverse elements in 64-bit doublewords -TRUE,vrev64q_p16,vec: poly16x8_t,poly16x8_t,Reverse elements in 64-bit doublewords -TRUE,vrev64q_p8,vec: poly8x16_t,poly8x16_t,Reverse elements in 64-bit doublewords -TRUE,vrev64q_s16,vec: int16x8_t,int16x8_t,Reverse elements in 64-bit doublewords -TRUE,vrev64q_s32,vec: int32x4_t,int32x4_t,Reverse elements in 64-bit doublewords -TRUE,vrev64q_s8,vec: int8x16_t,int8x16_t,Reverse elements in 64-bit doublewords -TRUE,vrev64q_u16,vec: uint16x8_t,uint16x8_t,Reverse elements in 64-bit doublewords -TRUE,vrev64q_u32,vec: uint32x4_t,uint32x4_t,Reverse elements in 64-bit doublewords -TRUE,vrev64q_u8,vec: uint8x16_t,uint8x16_t,Reverse elements in 64-bit doublewords -TRUE,vrhadd_s16,"a: int16x4_t, b: int16x4_t",int16x4_t,Signed rounding halving add -TRUE,vrhadd_s32,"a: int32x2_t, b: int32x2_t",int32x2_t,Signed rounding halving add -TRUE,vrhadd_s8,"a: int8x8_t, b: int8x8_t",int8x8_t,Signed rounding halving add -TRUE,vrhadd_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4_t,Unsigned rounding halving add -TRUE,vrhadd_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2_t,Unsigned rounding halving add -TRUE,vrhadd_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,Unsigned rounding halving add -TRUE,vrhaddq_s16,"a: int16x8_t, b: int16x8_t",int16x8_t,Signed rounding halving add -TRUE,vrhaddq_s32,"a: int32x4_t, b: int32x4_t",int32x4_t,Signed rounding halving add -TRUE,vrhaddq_s8,"a: int8x16_t, b: int8x16_t",int8x16_t,Signed rounding halving add -TRUE,vrhaddq_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8_t,Unsigned rounding halving add -TRUE,vrhaddq_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,Unsigned rounding halving add -TRUE,vrhaddq_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16_t,Unsigned rounding halving add -FALSE,vrnd_f16,a: float16x4_t,float16x4_t,"Floating-point round to integral, toward zero" -TRUE,vrnd_f32,a: float32x2_t,float32x2_t,"Floating-point round to integral, toward zero" -TRUE,vrnd_f64,a: float64x1_t,float64x1_t,"Floating-point round to integral, toward zero" -FALSE,vrnd32x_f32,a: float32x2_t,float32x2_t,"Floating-point round to 32-bit integer, using current rounding mode" -FALSE,vrnd32x_f64,a: float64x1_t,float64x1_t,"Floating-point round to 32-bit integer, using current rounding mode" -FALSE,vrnd32xq_f32,a: float32x4_t,float32x4_t,"Floating-point round to 32-bit integer, using current rounding mode" -FALSE,vrnd32xq_f64,a: float64x2_t,float64x2_t,"Floating-point round to 32-bit integer, using current rounding mode" -FALSE,vrnd32z_f32,a: float32x2_t,float32x2_t,Floating-point round to 32-bit integer toward zero -FALSE,vrnd32z_f64,a: float64x1_t,float64x1_t,Floating-point round to 32-bit integer toward zero -FALSE,vrnd32zq_f32,a: float32x4_t,float32x4_t,Floating-point round to 32-bit integer toward zero -FALSE,vrnd32zq_f64,a: float64x2_t,float64x2_t,Floating-point round to 32-bit integer toward zero -FALSE,vrnd64x_f32,a: float32x2_t,float32x2_t,"Floating-point round to 64-bit integer, using current rounding mode" -FALSE,vrnd64x_f64,a: float64x1_t,float64x1_t,"Floating-point round to 64-bit integer, using current rounding mode" -FALSE,vrnd64xq_f32,a: float32x4_t,float32x4_t,"Floating-point round to 64-bit integer, using current rounding mode" -FALSE,vrnd64xq_f64,a: float64x2_t,float64x2_t,"Floating-point round to 64-bit integer, using current rounding mode" -FALSE,vrnd64z_f32,a: float32x2_t,float32x2_t,Floating-point round to 64-bit integer toward zero -FALSE,vrnd64z_f64,a: float64x1_t,float64x1_t,Floating-point round to 64-bit integer toward zero -FALSE,vrnd64zq_f32,a: float32x4_t,float32x4_t,Floating-point round to 64-bit integer toward zero -FALSE,vrnd64zq_f64,a: float64x2_t,float64x2_t,Floating-point round to 64-bit integer toward zero -FALSE,vrnda_f16,a: float16x4_t,float16x4_t,"Floating-point round to integral, to nearest with ties to away" -TRUE,vrnda_f32,a: float32x2_t,float32x2_t,"Floating-point round to integral, to nearest with ties to away" -TRUE,vrnda_f64,a: float64x1_t,float64x1_t,"Floating-point round to integral, to nearest with ties to away" -FALSE,vrndah_f16,a: float16_t,float16_t,"Floating-point round to integral, to nearest with ties to away" -FALSE,vrndaq_f16,a: float16x8_t,float16x8_t,"Floating-point round to integral, to nearest with ties to away" -TRUE,vrndaq_f32,a: float32x4_t,float32x4_t,"Floating-point round to integral, to nearest with ties to away" -TRUE,vrndaq_f64,a: float64x2_t,float64x2_t,"Floating-point round to integral, to nearest with ties to away" -FALSE,vrndh_f16,a: float16_t,float16_t,"Floating-point round to integral, toward zero" -FALSE,vrndi_f16,a: float16x4_t,float16x4_t,"Floating-point round to integral, using current rounding mode" -TRUE,vrndi_f32,a: float32x2_t,float32x2_t,"Floating-point round to integral, using current rounding mode" -TRUE,vrndi_f64,a: float64x1_t,float64x1_t,"Floating-point round to integral, using current rounding mode" -FALSE,vrndih_f16,a: float16_t,float16_t,"Floating-point round to integral, using current rounding mode" -FALSE,vrndiq_f16,a: float16x8_t,float16x8_t,"Floating-point round to integral, using current rounding mode" -TRUE,vrndiq_f32,a: float32x4_t,float32x4_t,"Floating-point round to integral, using current rounding mode" -TRUE,vrndiq_f64,a: float64x2_t,float64x2_t,"Floating-point round to integral, using current rounding mode" -FALSE,vrndm_f16,a: float16x4_t,float16x4_t,"Floating-point round to integral, toward minus infinity" -TRUE,vrndm_f32,a: float32x2_t,float32x2_t,"Floating-point round to integral, toward minus infinity" -TRUE,vrndm_f64,a: float64x1_t,float64x1_t,"Floating-point round to integral, toward minus infinity" -FALSE,vrndmh_f16,a: float16_t,float16_t,"Floating-point round to integral, toward minus infinity" -FALSE,vrndmq_f16,a: float16x8_t,float16x8_t,"Floating-point round to integral, toward minus infinity" -TRUE,vrndmq_f32,a: float32x4_t,float32x4_t,"Floating-point round to integral, toward minus infinity" -TRUE,vrndmq_f64,a: float64x2_t,float64x2_t,"Floating-point round to integral, toward minus infinity" -FALSE,vrndn_f16,a: float16x4_t,float16x4_t,"Floating-point round to integral, to nearest with ties to even" -TRUE,vrndn_f32,a: float32x2_t,float32x2_t,"Floating-point round to integral, to nearest with ties to even" -TRUE,vrndn_f64,a: float64x1_t,float64x1_t,"Floating-point round to integral, to nearest with ties to even" -FALSE,vrndnh_f16,a: float16_t,float16_t,"Floating-point round to integral, to nearest with ties to even" -FALSE,vrndnq_f16,a: float16x8_t,float16x8_t,"Floating-point round to integral, to nearest with ties to even" -TRUE,vrndnq_f32,a: float32x4_t,float32x4_t,"Floating-point round to integral, to nearest with ties to even" -TRUE,vrndnq_f64,a: float64x2_t,float64x2_t,"Floating-point round to integral, to nearest with ties to even" -FALSE,vrndns_f32,a: f32,f32,"Floating-point round to integral, to nearest with ties to even" -FALSE,vrndp_f16,a: float16x4_t,float16x4_t,"Floating-point round to integral, toward plus infinity" -TRUE,vrndp_f32,a: float32x2_t,float32x2_t,"Floating-point round to integral, toward plus infinity" -TRUE,vrndp_f64,a: float64x1_t,float64x1_t,"Floating-point round to integral, toward plus infinity" -FALSE,vrndph_f16,a: float16_t,float16_t,"Floating-point round to integral, toward plus infinity" -FALSE,vrndpq_f16,a: float16x8_t,float16x8_t,"Floating-point round to integral, toward plus infinity" -TRUE,vrndpq_f32,a: float32x4_t,float32x4_t,"Floating-point round to integral, toward plus infinity" -TRUE,vrndpq_f64,a: float64x2_t,float64x2_t,"Floating-point round to integral, toward plus infinity" -FALSE,vrndq_f16,a: float16x8_t,float16x8_t,"Floating-point round to integral, toward zero" -TRUE,vrndq_f32,a: float32x4_t,float32x4_t,"Floating-point round to integral, toward zero" -TRUE,vrndq_f64,a: float64x2_t,float64x2_t,"Floating-point round to integral, toward zero" -FALSE,vrndx_f16,a: float16x4_t,float16x4_t,"Floating-point round to integral exact, using current rounding mode" -TRUE,vrndx_f32,a: float32x2_t,float32x2_t,"Floating-point round to integral exact, using current rounding mode" -TRUE,vrndx_f64,a: float64x1_t,float64x1_t,"Floating-point round to integral exact, using current rounding mode" -FALSE,vrndxh_f16,a: float16_t,float16_t,"Floating-point round to integral exact, using current rounding mode" -FALSE,vrndxq_f16,a: float16x8_t,float16x8_t,"Floating-point round to integral exact, using current rounding mode" -TRUE,vrndxq_f32,a: float32x4_t,float32x4_t,"Floating-point round to integral exact, using current rounding mode" -TRUE,vrndxq_f64,a: float64x2_t,float64x2_t,"Floating-point round to integral exact, using current rounding mode" -TRUE,vrshl_s16,"a: int16x4_t, b: int16x4_t",int16x4_t,Signed rounding shift left -TRUE,vrshl_s32,"a: int32x2_t, b: int32x2_t",int32x2_t,Signed rounding shift left -TRUE,vrshl_s64,"a: int64x1_t, b: int64x1_t",int64x1_t,Signed rounding shift left -TRUE,vrshl_s8,"a: int8x8_t, b: int8x8_t",int8x8_t,Signed rounding shift left -TRUE,vrshl_u16,"a: uint16x4_t, b: int16x4_t",uint16x4_t,Unsigned rounding shift left -TRUE,vrshl_u32,"a: uint32x2_t, b: int32x2_t",uint32x2_t,Unsigned rounding shift left -TRUE,vrshl_u64,"a: uint64x1_t, b: int64x1_t",uint64x1_t,Unsigned rounding shift left -TRUE,vrshl_u8,"a: uint8x8_t, b: int8x8_t",uint8x8_t,Unsigned rounding shift left -TRUE,vrshld_s64,"a: i64, b: i64",i64,Signed rounding shift left -TRUE,vrshld_u64,"a: u64, b: i64",u64,Unsigned rounding shift left -TRUE,vrshlq_s16,"a: int16x8_t, b: int16x8_t",int16x8_t,Signed rounding shift left -TRUE,vrshlq_s32,"a: int32x4_t, b: int32x4_t",int32x4_t,Signed rounding shift left -TRUE,vrshlq_s64,"a: int64x2_t, b: int64x2_t",int64x2_t,Signed rounding shift left -TRUE,vrshlq_s8,"a: int8x16_t, b: int8x16_t",int8x16_t,Signed rounding shift left -TRUE,vrshlq_u16,"a: uint16x8_t, b: int16x8_t",uint16x8_t,Unsigned rounding shift left -TRUE,vrshlq_u32,"a: uint32x4_t, b: int32x4_t",uint32x4_t,Unsigned rounding shift left -TRUE,vrshlq_u64,"a: uint64x2_t, b: int64x2_t",uint64x2_t,Unsigned rounding shift left -TRUE,vrshlq_u8,"a: uint8x16_t, b: int8x16_t",uint8x16_t,Unsigned rounding shift left -TRUE,vrshr_n_s16,"a: int16x4_t, n: const int",int16x4_t,Signed rounding shift right -TRUE,vrshr_n_s32,"a: int32x2_t, n: const int",int32x2_t,Signed rounding shift right -TRUE,vrshr_n_s64,"a: int64x1_t, n: const int",int64x1_t,Signed rounding shift right -TRUE,vrshr_n_s8,"a: int8x8_t, n: const int",int8x8_t,Signed rounding shift right -TRUE,vrshr_n_u16,"a: uint16x4_t, n: const int",uint16x4_t,Unsigned rounding shift right -TRUE,vrshr_n_u32,"a: uint32x2_t, n: const int",uint32x2_t,Unsigned rounding shift right -TRUE,vrshr_n_u64,"a: uint64x1_t, n: const int",uint64x1_t,Unsigned rounding shift right -TRUE,vrshr_n_u8,"a: uint8x8_t, n: const int",uint8x8_t,Unsigned rounding shift right -TRUE,vrshrd_n_s64,"a: i64, n: const int",i64,Signed rounding shift right -TRUE,vrshrd_n_u64,"a: u64, n: const int",u64,Unsigned rounding shift right -TRUE,vrshrn_high_n_s16,"r: int8x8_t, a: int16x8_t, n: const int",int8x16_t,Rounding shift right narrow -TRUE,vrshrn_high_n_s32,"r: int16x4_t, a: int32x4_t, n: const int",int16x8_t,Rounding shift right narrow -TRUE,vrshrn_high_n_s64,"r: int32x2_t, a: int64x2_t, n: const int",int32x4_t,Rounding shift right narrow -TRUE,vrshrn_high_n_u16,"r: uint8x8_t, a: uint16x8_t, n: const int",uint8x16_t,Rounding shift right narrow -TRUE,vrshrn_high_n_u32,"r: uint16x4_t, a: uint32x4_t, n: const int",uint16x8_t,Rounding shift right narrow -TRUE,vrshrn_high_n_u64,"r: uint32x2_t, a: uint64x2_t, n: const int",uint32x4_t,Rounding shift right narrow -TRUE,vrshrn_n_s16,"a: int16x8_t, n: const int",int8x8_t,Rounding shift right narrow -TRUE,vrshrn_n_s32,"a: int32x4_t, n: const int",int16x4_t,Rounding shift right narrow -TRUE,vrshrn_n_s64,"a: int64x2_t, n: const int",int32x2_t,Rounding shift right narrow -TRUE,vrshrn_n_u16,"a: uint16x8_t, n: const int",uint8x8_t,Rounding shift right narrow -TRUE,vrshrn_n_u32,"a: uint32x4_t, n: const int",uint16x4_t,Rounding shift right narrow -TRUE,vrshrn_n_u64,"a: uint64x2_t, n: const int",uint32x2_t,Rounding shift right narrow -TRUE,vrshrq_n_s16,"a: int16x8_t, n: const int",int16x8_t,Signed rounding shift right -TRUE,vrshrq_n_s32,"a: int32x4_t, n: const int",int32x4_t,Signed rounding shift right -TRUE,vrshrq_n_s64,"a: int64x2_t, n: const int",int64x2_t,Signed rounding shift right -TRUE,vrshrq_n_s8,"a: int8x16_t, n: const int",int8x16_t,Signed rounding shift right -TRUE,vrshrq_n_u16,"a: uint16x8_t, n: const int",uint16x8_t,Unsigned rounding shift right -TRUE,vrshrq_n_u32,"a: uint32x4_t, n: const int",uint32x4_t,Unsigned rounding shift right -TRUE,vrshrq_n_u64,"a: uint64x2_t, n: const int",uint64x2_t,Unsigned rounding shift right -TRUE,vrshrq_n_u8,"a: uint8x16_t, n: const int",uint8x16_t,Unsigned rounding shift right -FALSE,vrsqrte_f16,a: float16x4_t,float16x4_t,Floating-point reciprocal square root estimate -TRUE,vrsqrte_f32,a: float32x2_t,float32x2_t,Floating-point reciprocal square root estimate -FALSE,vrsqrte_f64,a: float64x1_t,float64x1_t,Floating-point reciprocal square root estimate -FALSE,vrsqrte_u32,a: uint32x2_t,uint32x2_t,Unsigned reciprocal square root estimate -FALSE,vrsqrted_f64,a: float64_t,float64_t,Floating-point reciprocal square root estimate -FALSE,vrsqrteh_f16,a: float16_t,float16_t,Floating-point reciprocal square root estimate -FALSE,vrsqrteq_f16,a: float16x8_t,float16x8_t,Floating-point reciprocal square root estimate -FALSE,vrsqrteq_f32,a: float32x4_t,float32x4_t,Floating-point reciprocal square root estimate -FALSE,vrsqrteq_f64,a: float64x2_t,float64x2_t,Floating-point reciprocal square root estimate -FALSE,vrsqrteq_u32,a: uint32x4_t,uint32x4_t,Unsigned reciprocal square root estimate -FALSE,vrsqrtes_f32,a: f32,f32,Floating-point reciprocal square root estimate -FALSE,vrsqrts_f16,"a: float16x4_t, b: float16x4_t",float16x4_t,Floating-point reciprocal square root step -FALSE,vrsqrts_f32,"a: float32x2_t, b: float32x2_t",float32x2_t,Floating-point reciprocal square root step -FALSE,vrsqrts_f64,"a: float64x1_t, b: float64x1_t",float64x1_t,Floating-point reciprocal square root step -FALSE,vrsqrtsd_f64,"a: float64_t, b: float64_t",float64_t,Floating-point reciprocal square root step -FALSE,vrsqrtsh_f16,"a: float16_t, b: float16_t",float16_t,Floating-point reciprocal square root step -FALSE,vrsqrtsq_f16,"a: float16x8_t, b: float16x8_t",float16x8_t,Floating-point reciprocal square root step -FALSE,vrsqrtsq_f32,"a: float32x4_t, b: float32x4_t",float32x4_t,Floating-point reciprocal square root step -FALSE,vrsqrtsq_f64,"a: float64x2_t, b: float64x2_t",float64x2_t,Floating-point reciprocal square root step -FALSE,vrsqrtss_f32,"a: f32, b: f32",f32,Floating-point reciprocal square root step -TRUE,vrsra_n_s16,"a: int16x4_t, b: int16x4_t, n: const int",int16x4_t,Signed rounding shift right and accumulate -TRUE,vrsra_n_s32,"a: int32x2_t, b: int32x2_t, n: const int",int32x2_t,Signed rounding shift right and accumulate -TRUE,vrsra_n_s64,"a: int64x1_t, b: int64x1_t, n: const int",int64x1_t,Signed rounding shift right and accumulate -TRUE,vrsra_n_s8,"a: int8x8_t, b: int8x8_t, n: const int",int8x8_t,Signed rounding shift right and accumulate -TRUE,vrsra_n_u16,"a: uint16x4_t, b: uint16x4_t, n: const int",uint16x4_t,Unsigned rounding shift right and accumulate -TRUE,vrsra_n_u32,"a: uint32x2_t, b: uint32x2_t, n: const int",uint32x2_t,Unsigned rounding shift right and accumulate -TRUE,vrsra_n_u64,"a: uint64x1_t, b: uint64x1_t, n: const int",uint64x1_t,Unsigned rounding shift right and accumulate -TRUE,vrsra_n_u8,"a: uint8x8_t, b: uint8x8_t, n: const int",uint8x8_t,Unsigned rounding shift right and accumulate -TRUE,vrsrad_n_s64,"a: i64, b: i64, n: const int",i64,Signed rounding shift right and accumulate -TRUE,vrsrad_n_u64,"a: u64, b: u64, n: const int",u64,Unsigned rounding shift right and accumulate -TRUE,vrsraq_n_s16,"a: int16x8_t, b: int16x8_t, n: const int",int16x8_t,Signed rounding shift right and accumulate -TRUE,vrsraq_n_s32,"a: int32x4_t, b: int32x4_t, n: const int",int32x4_t,Signed rounding shift right and accumulate -TRUE,vrsraq_n_s64,"a: int64x2_t, b: int64x2_t, n: const int",int64x2_t,Signed rounding shift right and accumulate -TRUE,vrsraq_n_s8,"a: int8x16_t, b: int8x16_t, n: const int",int8x16_t,Signed rounding shift right and accumulate -TRUE,vrsraq_n_u16,"a: uint16x8_t, b: uint16x8_t, n: const int",uint16x8_t,Unsigned rounding shift right and accumulate -TRUE,vrsraq_n_u32,"a: uint32x4_t, b: uint32x4_t, n: const int",uint32x4_t,Unsigned rounding shift right and accumulate -TRUE,vrsraq_n_u64,"a: uint64x2_t, b: uint64x2_t, n: const int",uint64x2_t,Unsigned rounding shift right and accumulate -TRUE,vrsraq_n_u8,"a: uint8x16_t, b: uint8x16_t, n: const int",uint8x16_t,Unsigned rounding shift right and accumulate -FALSE,vrsubhn_high_s16,"r: int8x8_t, a: int16x8_t, b: int16x8_t",int8x16_t,Rounding subtract returning high narrow -FALSE,vrsubhn_high_s32,"r: int16x4_t, a: int32x4_t, b: int32x4_t",int16x8_t,Rounding subtract returning high narrow -FALSE,vrsubhn_high_s64,"r: int32x2_t, a: int64x2_t, b: int64x2_t",int32x4_t,Rounding subtract returning high narrow -FALSE,vrsubhn_high_u16,"r: uint8x8_t, a: uint16x8_t, b: uint16x8_t",uint8x16_t,Rounding subtract returning high narrow -FALSE,vrsubhn_high_u32,"r: uint16x4_t, a: uint32x4_t, b: uint32x4_t",uint16x8_t,Rounding subtract returning high narrow -FALSE,vrsubhn_high_u64,"r: uint32x2_t, a: uint64x2_t, b: uint64x2_t",uint32x4_t,Rounding subtract returning high narrow -FALSE,vrsubhn_s16,"a: int16x8_t, b: int16x8_t",int8x8_t,Rounding subtract returning high narrow -FALSE,vrsubhn_s32,"a: int32x4_t, b: int32x4_t",int16x4_t,Rounding subtract returning high narrow -FALSE,vrsubhn_s64,"a: int64x2_t, b: int64x2_t",int32x2_t,Rounding subtract returning high narrow -FALSE,vrsubhn_u16,"a: uint16x8_t, b: uint16x8_t",uint8x8_t,Rounding subtract returning high narrow -FALSE,vrsubhn_u32,"a: uint32x4_t, b: uint32x4_t",uint16x4_t,Rounding subtract returning high narrow -FALSE,vrsubhn_u64,"a: uint64x2_t, b: uint64x2_t",uint32x2_t,Rounding subtract returning high narrow -FALSE,vset_lane_bf16,"a: bfloat16_t, v: bfloat16x4_t, lane: const int",bfloat16x4_t,Insert vector element from another vector element -FALSE,vset_lane_f16,"a: float16_t, v: float16x4_t, lane: const int",float16x4_t,Insert vector element from another vector element -FALSE,vset_lane_f32,"a: f32, v: float32x2_t, lane: const int",float32x2_t,Insert vector element from another vector element -FALSE,vset_lane_f64,"a: float64_t, v: float64x1_t, lane: const int",float64x1_t,Insert vector element from another vector element -FALSE,vset_lane_p16,"a: poly16_t, v: poly16x4_t, lane: const int",poly16x4_t,Insert vector element from another vector element -FALSE,vset_lane_p64,"a: poly64_t, v: poly64x1_t, lane: const int",poly64x1_t,Insert vector element from another vector element -FALSE,vset_lane_p8,"a: poly8_t, v: poly8x8_t, lane: const int",poly8x8_t,Insert vector element from another vector element -FALSE,vset_lane_s16,"a: i16, v: int16x4_t, lane: const int",int16x4_t,Insert vector element from another vector element -FALSE,vset_lane_s32,"a: i32, v: int32x2_t, lane: const int",int32x2_t,Insert vector element from another vector element -FALSE,vset_lane_s64,"a: i64, v: int64x1_t, lane: const int",int64x1_t,Insert vector element from another vector element -FALSE,vset_lane_s8,"a: i8, v: int8x8_t, lane: const int",int8x8_t,Insert vector element from another vector element -FALSE,vset_lane_u16,"a: u16, v: uint16x4_t, lane: const int",uint16x4_t,Insert vector element from another vector element -FALSE,vset_lane_u32,"a: u32, v: uint32x2_t, lane: const int",uint32x2_t,Insert vector element from another vector element -FALSE,vset_lane_u64,"a: u64, v: uint64x1_t, lane: const int",uint64x1_t,Insert vector element from another vector element -FALSE,vset_lane_u8,"a: u8, v: uint8x8_t, lane: const int",uint8x8_t,Insert vector element from another vector element -FALSE,vsetq_lane_bf16,"a: bfloat16_t, v: bfloat16x8_t, lane: const int",bfloat16x8_t,Insert vector element from another vector element -FALSE,vsetq_lane_f16,"a: float16_t, v: float16x8_t, lane: const int",float16x8_t,Insert vector element from another vector element -FALSE,vsetq_lane_f32,"a: f32, v: float32x4_t, lane: const int",float32x4_t,Insert vector element from another vector element -FALSE,vsetq_lane_f64,"a: float64_t, v: float64x2_t, lane: const int",float64x2_t,Insert vector element from another vector element -FALSE,vsetq_lane_p16,"a: poly16_t, v: poly16x8_t, lane: const int",poly16x8_t,Insert vector element from another vector element -FALSE,vsetq_lane_p64,"a: poly64_t, v: poly64x2_t, lane: const int",poly64x2_t,Insert vector element from another vector element -FALSE,vsetq_lane_p8,"a: poly8_t, v: poly8x16_t, lane: const int",poly8x16_t,Insert vector element from another vector element -FALSE,vsetq_lane_s16,"a: i16, v: int16x8_t, lane: const int",int16x8_t,Insert vector element from another vector element -FALSE,vsetq_lane_s32,"a: i32, v: int32x4_t, lane: const int",int32x4_t,Insert vector element from another vector element -FALSE,vsetq_lane_s64,"a: i64, v: int64x2_t, lane: const int",int64x2_t,Insert vector element from another vector element -FALSE,vsetq_lane_s8,"a: i8, v: int8x16_t, lane: const int",int8x16_t,Insert vector element from another vector element -FALSE,vsetq_lane_u16,"a: u16, v: uint16x8_t, lane: const int",uint16x8_t,Insert vector element from another vector element -FALSE,vsetq_lane_u32,"a: u32, v: uint32x4_t, lane: const int",uint32x4_t,Insert vector element from another vector element -FALSE,vsetq_lane_u64,"a: u64, v: uint64x2_t, lane: const int",uint64x2_t,Insert vector element from another vector element -FALSE,vsetq_lane_u8,"a: u8, v: uint8x16_t, lane: const int",uint8x16_t,Insert vector element from another vector element -TRUE,vsha1cq_u32,"hash_abcd: uint32x4_t, hash_e: u32, wk: uint32x4_t",uint32x4_t,SHA1 hash update (choose) -TRUE,vsha1h_u32,hash_e: u32,u32,SHA1 fixed rotate -TRUE,vsha1mq_u32,"hash_abcd: uint32x4_t, hash_e: u32, wk: uint32x4_t",uint32x4_t,SHA1 hash update (majority) -TRUE,vsha1pq_u32,"hash_abcd: uint32x4_t, hash_e: u32, wk: uint32x4_t",uint32x4_t,SHA1 hash update (parity) -TRUE,vsha1su0q_u32,"w0_3: uint32x4_t, w4_7: uint32x4_t, w8_11: uint32x4_t",uint32x4_t,SHA1 schedule update 0 -TRUE,vsha1su1q_u32,"tw0_3: uint32x4_t, w12_15: uint32x4_t",uint32x4_t,SHA1 schedule update 1 -TRUE,vsha256h2q_u32,"hash_efgh: uint32x4_t, hash_abcd: uint32x4_t, wk: uint32x4_t",uint32x4_t,SHA256 hash update (part 2) -TRUE,vsha256hq_u32,"hash_abcd: uint32x4_t, hash_efgh: uint32x4_t, wk: uint32x4_t",uint32x4_t,SHA256 hash update (part 1) -TRUE,vsha256su0q_u32,"w0_3: uint32x4_t, w4_7: uint32x4_t",uint32x4_t,SHA256 schedule update 0 -TRUE,vsha256su1q_u32,"tw0_3: uint32x4_t, w8_11: uint32x4_t, w12_15: uint32x4_t",uint32x4_t,SHA256 schedule update 1 -FALSE,vsha512h2q_u64,"sum_ab: uint64x2_t, hash_c_: uint64x2_t, hash_ab: uint64x2_t",uint64x2_t,SHA512 hash update part 2 -FALSE,vsha512hq_u64,"hash_ed: uint64x2_t, hash_gf: uint64x2_t, kwh_kwh2: uint64x2_t",uint64x2_t,SHA512 hash update part 1 -FALSE,vsha512su0q_u64,"w0_1: uint64x2_t, w2_: uint64x2_t",uint64x2_t,SHA512 schedule update 0 -FALSE,vsha512su1q_u64,"s01_s02: uint64x2_t, w14_15: uint64x2_t, w9_10: uint64x2_t",uint64x2_t,SHA512 schedule update 1 -TRUE,vshl_n_s16,"a: int16x4_t, n: const int",int16x4_t,Shift left -TRUE,vshl_n_s32,"a: int32x2_t, n: const int",int32x2_t,Shift left -TRUE,vshl_n_s64,"a: int64x1_t, n: const int",int64x1_t,Shift left -TRUE,vshl_n_s8,"a: int8x8_t, n: const int",int8x8_t,Shift left -TRUE,vshl_n_u16,"a: uint16x4_t, n: const int",uint16x4_t,Shift left -TRUE,vshl_n_u32,"a: uint32x2_t, n: const int",uint32x2_t,Shift left -TRUE,vshl_n_u64,"a: uint64x1_t, n: const int",uint64x1_t,Shift left -TRUE,vshl_n_u8,"a: uint8x8_t, n: const int",uint8x8_t,Shift left -TRUE,vshl_s16,"a: int16x4_t, b: int16x4_t",int16x4_t,Signed shift left -TRUE,vshl_s32,"a: int32x2_t, b: int32x2_t",int32x2_t,Signed shift left -TRUE,vshl_s64,"a: int64x1_t, b: int64x1_t",int64x1_t,Signed shift left -TRUE,vshl_s8,"a: int8x8_t, b: int8x8_t",int8x8_t,Signed shift left -TRUE,vshl_u16,"a: uint16x4_t, b: int16x4_t",uint16x4_t,Unsigned shift left -TRUE,vshl_u32,"a: uint32x2_t, b: int32x2_t",uint32x2_t,Unsigned shift left -TRUE,vshl_u64,"a: uint64x1_t, b: int64x1_t",uint64x1_t,Unsigned shift left -TRUE,vshl_u8,"a: uint8x8_t, b: int8x8_t",uint8x8_t,Unsigned shift left -TRUE,vshld_n_s64,"a: i64, n: const int",i64,Shift left -TRUE,vshld_n_u64,"a: u64, n: const int",u64,Shift left -TRUE,vshld_s64,"a: i64, b: i64",i64,Signed shift left -TRUE,vshld_u64,"a: u64, b: i64",u64,Unsigned shift left -TRUE,vshll_high_n_s16,"a: int16x8_t, n: const int",int32x4_t,Shift left long -TRUE,vshll_high_n_s16,"a: int16x8_t, n: const int",int32x4_t,Signed shift left long -TRUE,vshll_high_n_s32,"a: int32x4_t, n: const int",int64x2_t,Shift left long -TRUE,vshll_high_n_s32,"a: int32x4_t, n: const int",int64x2_t,Signed shift left long -TRUE,vshll_high_n_s8,"a: int8x16_t, n: const int",int16x8_t,Shift left long -TRUE,vshll_high_n_s8,"a: int8x16_t, n: const int",int16x8_t,Signed shift left long -TRUE,vshll_high_n_u16,"a: uint16x8_t, n: const int",uint32x4_t,Shift left long -TRUE,vshll_high_n_u16,"a: uint16x8_t, n: const int",uint32x4_t,Unsigned shift left long -TRUE,vshll_high_n_u32,"a: uint32x4_t, n: const int",uint64x2_t,Shift left long -TRUE,vshll_high_n_u32,"a: uint32x4_t, n: const int",uint64x2_t,Unsigned shift left long -TRUE,vshll_high_n_u8,"a: uint8x16_t, n: const int",uint16x8_t,Shift left long -TRUE,vshll_high_n_u8,"a: uint8x16_t, n: const int",uint16x8_t,Unsigned shift left long -TRUE,vshll_n_s16,"a: int16x4_t, n: const int",int32x4_t,Shift left long -TRUE,vshll_n_s16,"a: int16x4_t, n: const int",int32x4_t,Signed shift left long -TRUE,vshll_n_s32,"a: int32x2_t, n: const int",int64x2_t,Shift left long -TRUE,vshll_n_s32,"a: int32x2_t, n: const int",int64x2_t,Signed shift left long -TRUE,vshll_n_s8,"a: int8x8_t, n: const int",int16x8_t,Shift left long -TRUE,vshll_n_s8,"a: int8x8_t, n: const int",int16x8_t,Signed shift left long -TRUE,vshll_n_u16,"a: uint16x4_t, n: const int",uint32x4_t,Shift left long -TRUE,vshll_n_u16,"a: uint16x4_t, n: const int",uint32x4_t,Unsigned shift left long -TRUE,vshll_n_u32,"a: uint32x2_t, n: const int",uint64x2_t,Shift left long -TRUE,vshll_n_u32,"a: uint32x2_t, n: const int",uint64x2_t,Unsigned shift left long -TRUE,vshll_n_u8,"a: uint8x8_t, n: const int",uint16x8_t,Shift left long -TRUE,vshll_n_u8,"a: uint8x8_t, n: const int",uint16x8_t,Unsigned shift left long -TRUE,vshlq_n_s16,"a: int16x8_t, n: const int",int16x8_t,Shift left -TRUE,vshlq_n_s32,"a: int32x4_t, n: const int",int32x4_t,Shift left -TRUE,vshlq_n_s64,"a: int64x2_t, n: const int",int64x2_t,Shift left -TRUE,vshlq_n_s8,"a: int8x16_t, n: const int",int8x16_t,Shift left -TRUE,vshlq_n_u16,"a: uint16x8_t, n: const int",uint16x8_t,Shift left -TRUE,vshlq_n_u32,"a: uint32x4_t, n: const int",uint32x4_t,Shift left -TRUE,vshlq_n_u64,"a: uint64x2_t, n: const int",uint64x2_t,Shift left -TRUE,vshlq_n_u8,"a: uint8x16_t, n: const int",uint8x16_t,Shift left -TRUE,vshlq_s16,"a: int16x8_t, b: int16x8_t",int16x8_t,Signed shift left -TRUE,vshlq_s32,"a: int32x4_t, b: int32x4_t",int32x4_t,Signed shift left -TRUE,vshlq_s64,"a: int64x2_t, b: int64x2_t",int64x2_t,Signed shift left -TRUE,vshlq_s8,"a: int8x16_t, b: int8x16_t",int8x16_t,Signed shift left -TRUE,vshlq_u16,"a: uint16x8_t, b: int16x8_t",uint16x8_t,Unsigned shift left -TRUE,vshlq_u32,"a: uint32x4_t, b: int32x4_t",uint32x4_t,Unsigned shift left -TRUE,vshlq_u64,"a: uint64x2_t, b: int64x2_t",uint64x2_t,Unsigned shift left -TRUE,vshlq_u8,"a: uint8x16_t, b: int8x16_t",uint8x16_t,Unsigned shift left -TRUE,vshr_n_s16,"a: int16x4_t, n: const int",int16x4_t,Signed shift right -TRUE,vshr_n_s32,"a: int32x2_t, n: const int",int32x2_t,Signed shift right -TRUE,vshr_n_s64,"a: int64x1_t, n: const int",int64x1_t,Signed shift right -TRUE,vshr_n_s8,"a: int8x8_t, n: const int",int8x8_t,Signed shift right -TRUE,vshr_n_u16,"a: uint16x4_t, n: const int",uint16x4_t,Unsigned shift right -TRUE,vshr_n_u32,"a: uint32x2_t, n: const int",uint32x2_t,Unsigned shift right -TRUE,vshr_n_u64,"a: uint64x1_t, n: const int",uint64x1_t,Unsigned shift right -TRUE,vshr_n_u8,"a: uint8x8_t, n: const int",uint8x8_t,Unsigned shift right -TRUE,vshrd_n_s64,"a: i64, n: const int",i64,Signed shift right -TRUE,vshrd_n_u64,"a: u64, n: const int",u64,Unsigned shift right -TRUE,vshrn_high_n_s16,"r: int8x8_t, a: int16x8_t, n: const int",int8x16_t,Shift right narrow -TRUE,vshrn_high_n_s32,"r: int16x4_t, a: int32x4_t, n: const int",int16x8_t,Shift right narrow -TRUE,vshrn_high_n_s64,"r: int32x2_t, a: int64x2_t, n: const int",int32x4_t,Shift right narrow -TRUE,vshrn_high_n_u16,"r: uint8x8_t, a: uint16x8_t, n: const int",uint8x16_t,Shift right narrow -TRUE,vshrn_high_n_u32,"r: uint16x4_t, a: uint32x4_t, n: const int",uint16x8_t,Shift right narrow -TRUE,vshrn_high_n_u64,"r: uint32x2_t, a: uint64x2_t, n: const int",uint32x4_t,Shift right narrow -TRUE,vshrn_n_s16,"a: int16x8_t, n: const int",int8x8_t,Shift right narrow -TRUE,vshrn_n_s32,"a: int32x4_t, n: const int",int16x4_t,Shift right narrow -TRUE,vshrn_n_s64,"a: int64x2_t, n: const int",int32x2_t,Shift right narrow -TRUE,vshrn_n_u16,"a: uint16x8_t, n: const int",uint8x8_t,Shift right narrow -TRUE,vshrn_n_u32,"a: uint32x4_t, n: const int",uint16x4_t,Shift right narrow -TRUE,vshrn_n_u64,"a: uint64x2_t, n: const int",uint32x2_t,Shift right narrow -TRUE,vshrq_n_s16,"a: int16x8_t, n: const int",int16x8_t,Signed shift right -TRUE,vshrq_n_s32,"a: int32x4_t, n: const int",int32x4_t,Signed shift right -TRUE,vshrq_n_s64,"a: int64x2_t, n: const int",int64x2_t,Signed shift right -TRUE,vshrq_n_s8,"a: int8x16_t, n: const int",int8x16_t,Signed shift right -TRUE,vshrq_n_u16,"a: uint16x8_t, n: const int",uint16x8_t,Unsigned shift right -TRUE,vshrq_n_u32,"a: uint32x4_t, n: const int",uint32x4_t,Unsigned shift right -TRUE,vshrq_n_u64,"a: uint64x2_t, n: const int",uint64x2_t,Unsigned shift right -TRUE,vshrq_n_u8,"a: uint8x16_t, n: const int",uint8x16_t,Unsigned shift right -TRUE,vsli_n_p16,"a: poly16x4_t, b: poly16x4_t, n: const int",poly16x4_t,Shift left and insert -FALSE,vsli_n_p64,"a: poly64x1_t, b: poly64x1_t, n: const int",poly64x1_t,Shift left and insert -TRUE,vsli_n_p8,"a: poly8x8_t, b: poly8x8_t, n: const int",poly8x8_t,Shift left and insert -TRUE,vsli_n_s16,"a: int16x4_t, b: int16x4_t, n: const int",int16x4_t,Shift left and insert -TRUE,vsli_n_s32,"a: int32x2_t, b: int32x2_t, n: const int",int32x2_t,Shift left and insert -TRUE,vsli_n_s64,"a: int64x1_t, b: int64x1_t, n: const int",int64x1_t,Shift left and insert -TRUE,vsli_n_s8,"a: int8x8_t, b: int8x8_t, n: const int",int8x8_t,Shift left and insert -TRUE,vsli_n_u16,"a: uint16x4_t, b: uint16x4_t, n: const int",uint16x4_t,Shift left and insert -TRUE,vsli_n_u32,"a: uint32x2_t, b: uint32x2_t, n: const int",uint32x2_t,Shift left and insert -TRUE,vsli_n_u64,"a: uint64x1_t, b: uint64x1_t, n: const int",uint64x1_t,Shift left and insert -TRUE,vsli_n_u8,"a: uint8x8_t, b: uint8x8_t, n: const int",uint8x8_t,Shift left and insert -TRUE,vslid_n_s64,"a: i64, b: i64, n: const int",i64,Shift left and insert -TRUE,vslid_n_u64,"a: u64, b: u64, n: const int",u64,Shift left and insert -TRUE,vsliq_n_p16,"a: poly16x8_t, b: poly16x8_t, n: const int",poly16x8_t,Shift left and insert -FALSE,vsliq_n_p64,"a: poly64x2_t, b: poly64x2_t, n: const int",poly64x2_t,Shift left and insert -TRUE,vsliq_n_p8,"a: poly8x16_t, b: poly8x16_t, n: const int",poly8x16_t,Shift left and insert -TRUE,vsliq_n_s16,"a: int16x8_t, b: int16x8_t, n: const int",int16x8_t,Shift left and insert -TRUE,vsliq_n_s32,"a: int32x4_t, b: int32x4_t, n: const int",int32x4_t,Shift left and insert -TRUE,vsliq_n_s64,"a: int64x2_t, b: int64x2_t, n: const int",int64x2_t,Shift left and insert -TRUE,vsliq_n_s8,"a: int8x16_t, b: int8x16_t, n: const int",int8x16_t,Shift left and insert -TRUE,vsliq_n_u16,"a: uint16x8_t, b: uint16x8_t, n: const int",uint16x8_t,Shift left and insert -TRUE,vsliq_n_u32,"a: uint32x4_t, b: uint32x4_t, n: const int",uint32x4_t,Shift left and insert -TRUE,vsliq_n_u64,"a: uint64x2_t, b: uint64x2_t, n: const int",uint64x2_t,Shift left and insert -TRUE,vsliq_n_u8,"a: uint8x16_t, b: uint8x16_t, n: const int",uint8x16_t,Shift left and insert -FALSE,vsm3partw1q_u32,"a: uint32x4_t, b: uint32x4_t, c: uint32x4_t",uint32x4_t,SM3PARTW1 -FALSE,vsm3partw2q_u32,"a: uint32x4_t, b: uint32x4_t, c: uint32x4_t",uint32x4_t,SM3PARTW2 -FALSE,vsm3ss1q_u32,"a: uint32x4_t, b: uint32x4_t, c: uint32x4_t",uint32x4_t,SM3SS1 -FALSE,vsm3tt1aq_u32,"a: uint32x4_t, b: uint32x4_t, c: uint32x4_t, imm2: const int",uint32x4_t,SM3TT1A -FALSE,vsm3tt1bq_u32,"a: uint32x4_t, b: uint32x4_t, c: uint32x4_t, imm2: const int",uint32x4_t,SM3TT1B -FALSE,vsm3tt2aq_u32,"a: uint32x4_t, b: uint32x4_t, c: uint32x4_t, imm2: const int",uint32x4_t,SM3TT2A -FALSE,vsm3tt2bq_u32,"a: uint32x4_t, b: uint32x4_t, c: uint32x4_t, imm2: const int",uint32x4_t,SM3TT2B -FALSE,vsm4ekeyq_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,SM4 key -FALSE,vsm4eq_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,SM4 encode -FALSE,vsqadd_u16,"a: uint16x4_t, b: int16x4_t",uint16x4_t,Unsigned saturating accumulate of signed value -FALSE,vsqadd_u32,"a: uint32x2_t, b: int32x2_t",uint32x2_t,Unsigned saturating accumulate of signed value -FALSE,vsqadd_u64,"a: uint64x1_t, b: int64x1_t",uint64x1_t,Unsigned saturating accumulate of signed value -FALSE,vsqadd_u8,"a: uint8x8_t, b: int8x8_t",uint8x8_t,Unsigned saturating accumulate of signed value -FALSE,vsqaddb_u8,"a: u8, b: i8",u8,Unsigned saturating accumulate of signed value -FALSE,vsqaddd_u64,"a: u64, b: i64",u64,Unsigned saturating accumulate of signed value -FALSE,vsqaddh_u16,"a: u16, b: i16",u16,Unsigned saturating accumulate of signed value -FALSE,vsqaddq_u16,"a: uint16x8_t, b: int16x8_t",uint16x8_t,Unsigned saturating accumulate of signed value -FALSE,vsqaddq_u32,"a: uint32x4_t, b: int32x4_t",uint32x4_t,Unsigned saturating accumulate of signed value -FALSE,vsqaddq_u64,"a: uint64x2_t, b: int64x2_t",uint64x2_t,Unsigned saturating accumulate of signed value -FALSE,vsqaddq_u8,"a: uint8x16_t, b: int8x16_t",uint8x16_t,Unsigned saturating accumulate of signed value -FALSE,vsqadds_u32,"a: u32, b: i32",u32,Unsigned saturating accumulate of signed value -FALSE,vsqrt_f16,a: float16x4_t,float16x4_t,Floating-point square root -TRUE,vsqrt_f32,a: float32x2_t,float32x2_t,Floating-point square root -TRUE,vsqrt_f64,a: float64x1_t,float64x1_t,Floating-point square root -FALSE,vsqrth_f16,a: float16_t,float16_t,Floating-point square root -FALSE,vsqrtq_f16,a: float16x8_t,float16x8_t,Floating-point square root -TRUE,vsqrtq_f32,a: float32x4_t,float32x4_t,Floating-point square root -TRUE,vsqrtq_f64,a: float64x2_t,float64x2_t,Floating-point square root -TRUE,vsra_n_s16,"a: int16x4_t, b: int16x4_t, n: const int",int16x4_t,Signed shift right and accumulate -TRUE,vsra_n_s32,"a: int32x2_t, b: int32x2_t, n: const int",int32x2_t,Signed shift right and accumulate -TRUE,vsra_n_s64,"a: int64x1_t, b: int64x1_t, n: const int",int64x1_t,Signed shift right and accumulate -TRUE,vsra_n_s8,"a: int8x8_t, b: int8x8_t, n: const int",int8x8_t,Signed shift right and accumulate -TRUE,vsra_n_u16,"a: uint16x4_t, b: uint16x4_t, n: const int",uint16x4_t,Unsigned shift right and accumulate -TRUE,vsra_n_u32,"a: uint32x2_t, b: uint32x2_t, n: const int",uint32x2_t,Unsigned shift right and accumulate -TRUE,vsra_n_u64,"a: uint64x1_t, b: uint64x1_t, n: const int",uint64x1_t,Unsigned shift right and accumulate -TRUE,vsra_n_u8,"a: uint8x8_t, b: uint8x8_t, n: const int",uint8x8_t,Unsigned shift right and accumulate -TRUE,vsrad_n_s64,"a: i64, b: i64, n: const int",i64,Signed shift right and accumulate -TRUE,vsrad_n_u64,"a: u64, b: u64, n: const int",u64,Unsigned shift right and accumulate -TRUE,vsraq_n_s16,"a: int16x8_t, b: int16x8_t, n: const int",int16x8_t,Signed shift right and accumulate -TRUE,vsraq_n_s32,"a: int32x4_t, b: int32x4_t, n: const int",int32x4_t,Signed shift right and accumulate -TRUE,vsraq_n_s64,"a: int64x2_t, b: int64x2_t, n: const int",int64x2_t,Signed shift right and accumulate -TRUE,vsraq_n_s8,"a: int8x16_t, b: int8x16_t, n: const int",int8x16_t,Signed shift right and accumulate -TRUE,vsraq_n_u16,"a: uint16x8_t, b: uint16x8_t, n: const int",uint16x8_t,Unsigned shift right and accumulate -TRUE,vsraq_n_u32,"a: uint32x4_t, b: uint32x4_t, n: const int",uint32x4_t,Unsigned shift right and accumulate -TRUE,vsraq_n_u64,"a: uint64x2_t, b: uint64x2_t, n: const int",uint64x2_t,Unsigned shift right and accumulate -TRUE,vsraq_n_u8,"a: uint8x16_t, b: uint8x16_t, n: const int",uint8x16_t,Unsigned shift right and accumulate -TRUE,vsri_n_p16,"a: poly16x4_t, b: poly16x4_t, n: const int",poly16x4_t,Shift right and insert -FALSE,vsri_n_p64,"a: poly64x1_t, b: poly64x1_t, n: const int",poly64x1_t,Shift right and insert -TRUE,vsri_n_p8,"a: poly8x8_t, b: poly8x8_t, n: const int",poly8x8_t,Shift right and insert -TRUE,vsri_n_s16,"a: int16x4_t, b: int16x4_t, n: const int",int16x4_t,Shift right and insert -TRUE,vsri_n_s32,"a: int32x2_t, b: int32x2_t, n: const int",int32x2_t,Shift right and insert -TRUE,vsri_n_s64,"a: int64x1_t, b: int64x1_t, n: const int",int64x1_t,Shift right and insert -TRUE,vsri_n_s8,"a: int8x8_t, b: int8x8_t, n: const int",int8x8_t,Shift right and insert -TRUE,vsri_n_u16,"a: uint16x4_t, b: uint16x4_t, n: const int",uint16x4_t,Shift right and insert -TRUE,vsri_n_u32,"a: uint32x2_t, b: uint32x2_t, n: const int",uint32x2_t,Shift right and insert -TRUE,vsri_n_u64,"a: uint64x1_t, b: uint64x1_t, n: const int",uint64x1_t,Shift right and insert -TRUE,vsri_n_u8,"a: uint8x8_t, b: uint8x8_t, n: const int",uint8x8_t,Shift right and insert -TRUE,vsrid_n_s64,"a: i64, b: i64, n: const int",i64,Shift right and insert -TRUE,vsrid_n_u64,"a: u64, b: u64, n: const int",u64,Shift right and insert -TRUE,vsriq_n_p16,"a: poly16x8_t, b: poly16x8_t, n: const int",poly16x8_t,Shift right and insert -FALSE,vsriq_n_p64,"a: poly64x2_t, b: poly64x2_t, n: const int",poly64x2_t,Shift right and insert -TRUE,vsriq_n_p8,"a: poly8x16_t, b: poly8x16_t, n: const int",poly8x16_t,Shift right and insert -TRUE,vsriq_n_s16,"a: int16x8_t, b: int16x8_t, n: const int",int16x8_t,Shift right and insert -TRUE,vsriq_n_s32,"a: int32x4_t, b: int32x4_t, n: const int",int32x4_t,Shift right and insert -TRUE,vsriq_n_s64,"a: int64x2_t, b: int64x2_t, n: const int",int64x2_t,Shift right and insert -TRUE,vsriq_n_s8,"a: int8x16_t, b: int8x16_t, n: const int",int8x16_t,Shift right and insert -TRUE,vsriq_n_u16,"a: uint16x8_t, b: uint16x8_t, n: const int",uint16x8_t,Shift right and insert -TRUE,vsriq_n_u32,"a: uint32x4_t, b: uint32x4_t, n: const int",uint32x4_t,Shift right and insert -TRUE,vsriq_n_u64,"a: uint64x2_t, b: uint64x2_t, n: const int",uint64x2_t,Shift right and insert -TRUE,vsriq_n_u8,"a: uint8x16_t, b: uint8x16_t, n: const int",uint8x16_t,Shift right and insert -FALSE,vst1_bf16,"ptr: *mut bfloat16_t, val: bfloat16x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_bf16_x2,"ptr: *mut bfloat16_t, val: bfloat16x4x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_bf16_x3,"ptr: *mut bfloat16_t, val: bfloat16x4x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_bf16_x4,"ptr: *mut bfloat16_t, val: bfloat16x4x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_f16,"ptr: *mut float16_t, val: float16x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_f16_x2,"ptr: *mut float16_t, val: float16x4x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_f16_x3,"ptr: *mut float16_t, val: float16x4x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_f16_x4,"ptr: *mut float16_t, val: float16x4x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_f32,"ptr: *mut f32, val: float32x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_f32_x2,"ptr: *mut f32, val: float32x2x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_f32_x3,"ptr: *mut f32, val: float32x2x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_f32_x4,"ptr: *mut f32, val: float32x2x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_f64,"ptr: *mut float64_t, val: float64x1_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_f64_x2,"ptr: *mut float64_t, val: float64x1x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_f64_x3,"ptr: *mut float64_t, val: float64x1x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_f64_x4,"ptr: *mut float64_t, val: float64x1x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_lane_bf16,"ptr: *mut bfloat16_t, val: bfloat16x4_t, lane: const int",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_lane_f16,"ptr: *mut float16_t, val: float16x4_t, lane: const int",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_lane_f32,"ptr: *mut f32, val: float32x2_t, lane: const int",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_lane_f64,"ptr: *mut float64_t, val: float64x1_t, lane: const int",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_lane_p16,"ptr: *mut poly16_t, val: poly16x4_t, lane: const int",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_lane_p64,"ptr: *mut poly64_t, val: poly64x1_t, lane: const int",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_lane_p8,"ptr: *mut poly8_t, val: poly8x8_t, lane: const int",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_lane_s16,"ptr: *mut i16, val: int16x4_t, lane: const int",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_lane_s32,"ptr: *mut i32, val: int32x2_t, lane: const int",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_lane_s64,"ptr: *mut i64, val: int64x1_t, lane: const int",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_lane_s8,"ptr: *mut i8, val: int8x8_t, lane: const int",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_lane_u16,"ptr: *mut u16, val: uint16x4_t, lane: const int",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_lane_u32,"ptr: *mut u32, val: uint32x2_t, lane: const int",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_lane_u64,"ptr: *mut u64, val: uint64x1_t, lane: const int",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_lane_u8,"ptr: *mut u8, val: uint8x8_t, lane: const int",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_p16,"ptr: *mut poly16_t, val: poly16x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_p16_x2,"ptr: *mut poly16_t, val: poly16x4x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_p16_x3,"ptr: *mut poly16_t, val: poly16x4x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_p16_x4,"ptr: *mut poly16_t, val: poly16x4x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_p64,"ptr: *mut poly64_t, val: poly64x1_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_p64_x2,"ptr: *mut poly64_t, val: poly64x1x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_p64_x3,"ptr: *mut poly64_t, val: poly64x1x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_p64_x4,"ptr: *mut poly64_t, val: poly64x1x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_p8,"ptr: *mut poly8_t, val: poly8x8_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_p8_x2,"ptr: *mut poly8_t, val: poly8x8x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_p8_x3,"ptr: *mut poly8_t, val: poly8x8x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_p8_x4,"ptr: *mut poly8_t, val: poly8x8x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_s16,"ptr: *mut i16, val: int16x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_s16_x2,"ptr: *mut i16, val: int16x4x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_s16_x3,"ptr: *mut i16, val: int16x4x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_s16_x4,"ptr: *mut i16, val: int16x4x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_s32,"ptr: *mut i32, val: int32x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_s32_x2,"ptr: *mut i32, val: int32x2x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_s32_x3,"ptr: *mut i32, val: int32x2x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_s32_x4,"ptr: *mut i32, val: int32x2x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_s64,"ptr: *mut i64, val: int64x1_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_s64_x2,"ptr: *mut i64, val: int64x1x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_s64_x3,"ptr: *mut i64, val: int64x1x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_s64_x4,"ptr: *mut i64, val: int64x1x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_s8,"ptr: *mut i8, val: int8x8_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_s8_x2,"ptr: *mut i8, val: int8x8x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_s8_x3,"ptr: *mut i8, val: int8x8x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_s8_x4,"ptr: *mut i8, val: int8x8x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_u16,"ptr: *mut u16, val: uint16x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_u16_x2,"ptr: *mut u16, val: uint16x4x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_u16_x3,"ptr: *mut u16, val: uint16x4x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_u16_x4,"ptr: *mut u16, val: uint16x4x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_u32,"ptr: *mut u32, val: uint32x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_u32_x2,"ptr: *mut u32, val: uint32x2x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_u32_x3,"ptr: *mut u32, val: uint32x2x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_u32_x4,"ptr: *mut u32, val: uint32x2x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_u64,"ptr: *mut u64, val: uint64x1_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_u64_x2,"ptr: *mut u64, val: uint64x1x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_u64_x3,"ptr: *mut u64, val: uint64x1x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_u64_x4,"ptr: *mut u64, val: uint64x1x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_u8,"ptr: *mut u8, val: uint8x8_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_u8_x2,"ptr: *mut u8, val: uint8x8x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_u8_x3,"ptr: *mut u8, val: uint8x8x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1_u8_x4,"ptr: *mut u8, val: uint8x8x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_bf16,"ptr: *mut bfloat16_t, val: bfloat16x8_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_bf16_x2,"ptr: *mut bfloat16_t, val: bfloat16x8x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_bf16_x3,"ptr: *mut bfloat16_t, val: bfloat16x8x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_bf16_x4,"ptr: *mut bfloat16_t, val: bfloat16x8x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_f16,"ptr: *mut float16_t, val: float16x8_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_f16_x2,"ptr: *mut float16_t, val: float16x8x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_f16_x3,"ptr: *mut float16_t, val: float16x8x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_f16_x4,"ptr: *mut float16_t, val: float16x8x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_f32,"ptr: *mut f32, val: float32x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_f32_x2,"ptr: *mut f32, val: float32x4x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_f32_x3,"ptr: *mut f32, val: float32x4x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_f32_x4,"ptr: *mut f32, val: float32x4x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_f64,"ptr: *mut float64_t, val: float64x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_f64_x2,"ptr: *mut float64_t, val: float64x2x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_f64_x3,"ptr: *mut float64_t, val: float64x2x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_f64_x4,"ptr: *mut float64_t, val: float64x2x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_lane_bf16,"ptr: *mut bfloat16_t, val: bfloat16x8_t, lane: const int",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_lane_f16,"ptr: *mut float16_t, val: float16x8_t, lane: const int",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_lane_f32,"ptr: *mut f32, val: float32x4_t, lane: const int",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_lane_f64,"ptr: *mut float64_t, val: float64x2_t, lane: const int",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_lane_p16,"ptr: *mut poly16_t, val: poly16x8_t, lane: const int",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_lane_p64,"ptr: *mut poly64_t, val: poly64x2_t, lane: const int",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_lane_p8,"ptr: *mut poly8_t, val: poly8x16_t, lane: const int",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_lane_s16,"ptr: *mut i16, val: int16x8_t, lane: const int",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_lane_s32,"ptr: *mut i32, val: int32x4_t, lane: const int",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_lane_s64,"ptr: *mut i64, val: int64x2_t, lane: const int",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_lane_s8,"ptr: *mut i8, val: int8x16_t, lane: const int",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_lane_u16,"ptr: *mut u16, val: uint16x8_t, lane: const int",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_lane_u32,"ptr: *mut u32, val: uint32x4_t, lane: const int",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_lane_u64,"ptr: *mut u64, val: uint64x2_t, lane: const int",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_lane_u8,"ptr: *mut u8, val: uint8x16_t, lane: const int",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_p16,"ptr: *mut poly16_t, val: poly16x8_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_p16_x2,"ptr: *mut poly16_t, val: poly16x8x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_p16_x3,"ptr: *mut poly16_t, val: poly16x8x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_p16_x4,"ptr: *mut poly16_t, val: poly16x8x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_p64,"ptr: *mut poly64_t, val: poly64x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_p64_x2,"ptr: *mut poly64_t, val: poly64x2x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_p64_x3,"ptr: *mut poly64_t, val: poly64x2x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_p64_x4,"ptr: *mut poly64_t, val: poly64x2x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_p8,"ptr: *mut poly8_t, val: poly8x16_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_p8_x2,"ptr: *mut poly8_t, val: poly8x16x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_p8_x3,"ptr: *mut poly8_t, val: poly8x16x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_p8_x4,"ptr: *mut poly8_t, val: poly8x16x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_s16,"ptr: *mut i16, val: int16x8_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_s16_x2,"ptr: *mut i16, val: int16x8x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_s16_x3,"ptr: *mut i16, val: int16x8x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_s16_x4,"ptr: *mut i16, val: int16x8x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_s32,"ptr: *mut i32, val: int32x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_s32_x2,"ptr: *mut i32, val: int32x4x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_s32_x3,"ptr: *mut i32, val: int32x4x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_s32_x4,"ptr: *mut i32, val: int32x4x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_s64,"ptr: *mut i64, val: int64x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_s64_x2,"ptr: *mut i64, val: int64x2x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_s64_x3,"ptr: *mut i64, val: int64x2x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_s64_x4,"ptr: *mut i64, val: int64x2x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_s8,"ptr: *mut i8, val: int8x16_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_s8_x2,"ptr: *mut i8, val: int8x16x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_s8_x3,"ptr: *mut i8, val: int8x16x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_s8_x4,"ptr: *mut i8, val: int8x16x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_u16,"ptr: *mut u16, val: uint16x8_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_u16_x2,"ptr: *mut u16, val: uint16x8x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_u16_x3,"ptr: *mut u16, val: uint16x8x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_u16_x4,"ptr: *mut u16, val: uint16x8x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_u32,"ptr: *mut u32, val: uint32x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_u32_x2,"ptr: *mut u32, val: uint32x4x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_u32_x3,"ptr: *mut u32, val: uint32x4x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_u32_x4,"ptr: *mut u32, val: uint32x4x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_u64,"ptr: *mut u64, val: uint64x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_u64_x2,"ptr: *mut u64, val: uint64x2x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_u64_x3,"ptr: *mut u64, val: uint64x2x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_u64_x4,"ptr: *mut u64, val: uint64x2x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_u8,"ptr: *mut u8, val: uint8x16_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_u8_x2,"ptr: *mut u8, val: uint8x16x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_u8_x3,"ptr: *mut u8, val: uint8x16x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst1q_u8_x4,"ptr: *mut u8, val: uint8x16x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst2_bf16,"ptr: *mut bfloat16_t, val: bfloat16x4x2_t",void,Store multiple 2-element structures from two registers -FALSE,vst2_f16,"ptr: *mut float16_t, val: float16x4x2_t",void,Store multiple 2-element structures from two registers -FALSE,vst2_f32,"ptr: *mut f32, val: float32x2x2_t",void,Store multiple 2-element structures from two registers -FALSE,vst2_f64,"ptr: *mut float64_t, val: float64x1x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst2_lane_bf16,"ptr: *mut bfloat16_t, val: bfloat16x4x2_t, lane: const int",void,Store multiple 2-element structures from two registers -FALSE,vst2_lane_f16,"ptr: *mut float16_t, val: float16x4x2_t, lane: const int",void,Store multiple 2-element structures from two registers -FALSE,vst2_lane_f32,"ptr: *mut f32, val: float32x2x2_t, lane: const int",void,Store multiple 2-element structures from two registers -FALSE,vst2_lane_f64,"ptr: *mut float64_t, val: float64x1x2_t, lane: const int",void,Store multiple 2-element structures from two registers -FALSE,vst2_lane_p16,"ptr: *mut poly16_t, val: poly16x4x2_t, lane: const int",void,Store multiple 2-element structures from two registers -FALSE,vst2_lane_p64,"ptr: *mut poly64_t, val: poly64x1x2_t, lane: const int",void,Store multiple 2-element structures from two registers -FALSE,vst2_lane_p8,"ptr: *mut poly8_t, val: poly8x8x2_t, lane: const int",void,Store multiple 2-element structures from two registers -FALSE,vst2_lane_s16,"ptr: *mut i16, val: int16x4x2_t, lane: const int",void,Store multiple 2-element structures from two registers -FALSE,vst2_lane_s32,"ptr: *mut i32, val: int32x2x2_t, lane: const int",void,Store multiple 2-element structures from two registers -FALSE,vst2_lane_s64,"ptr: *mut i64, val: int64x1x2_t, lane: const int",void,Store multiple 2-element structures from two registers -FALSE,vst2_lane_s8,"ptr: *mut i8, val: int8x8x2_t, lane: const int",void,Store multiple 2-element structures from two registers -FALSE,vst2_lane_u16,"ptr: *mut u16, val: uint16x4x2_t, lane: const int",void,Store multiple 2-element structures from two registers -FALSE,vst2_lane_u32,"ptr: *mut u32, val: uint32x2x2_t, lane: const int",void,Store multiple 2-element structures from two registers -FALSE,vst2_lane_u64,"ptr: *mut u64, val: uint64x1x2_t, lane: const int",void,Store multiple 2-element structures from two registers -FALSE,vst2_lane_u8,"ptr: *mut u8, val: uint8x8x2_t, lane: const int",void,Store multiple 2-element structures from two registers -FALSE,vst2_p16,"ptr: *mut poly16_t, val: poly16x4x2_t",void,Store multiple 2-element structures from two registers -FALSE,vst2_p64,"ptr: *mut poly64_t, val: poly64x1x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst2_p8,"ptr: *mut poly8_t, val: poly8x8x2_t",void,Store multiple 2-element structures from two registers -FALSE,vst2_s16,"ptr: *mut i16, val: int16x4x2_t",void,Store multiple 2-element structures from two registers -FALSE,vst2_s32,"ptr: *mut i32, val: int32x2x2_t",void,Store multiple 2-element structures from two registers -FALSE,vst2_s64,"ptr: *mut i64, val: int64x1x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst2_s8,"ptr: *mut i8, val: int8x8x2_t",void,Store multiple 2-element structures from two registers -FALSE,vst2_u16,"ptr: *mut u16, val: uint16x4x2_t",void,Store multiple 2-element structures from two registers -FALSE,vst2_u32,"ptr: *mut u32, val: uint32x2x2_t",void,Store multiple 2-element structures from two registers -FALSE,vst2_u64,"ptr: *mut u64, val: uint64x1x2_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst2_u8,"ptr: *mut u8, val: uint8x8x2_t",void,Store multiple 2-element structures from two registers -FALSE,vst2q_bf16,"ptr: *mut bfloat16_t, val: bfloat16x8x2_t",void,Store multiple 2-element structures from two registers -FALSE,vst2q_f16,"ptr: *mut float16_t, val: float16x8x2_t",void,Store multiple 2-element structures from two registers -FALSE,vst2q_f32,"ptr: *mut f32, val: float32x4x2_t",void,Store multiple 2-element structures from two registers -FALSE,vst2q_f64,"ptr: *mut float64_t, val: float64x2x2_t",void,Store multiple 2-element structures from two registers -FALSE,vst2q_lane_bf16,"ptr: *mut bfloat16_t, val: bfloat16x8x2_t, lane: const int",void,Store multiple 2-element structures from two registers -FALSE,vst2q_lane_f16,"ptr: *mut float16_t, val: float16x8x2_t, lane: const int",void,Store multiple 2-element structures from two registers -FALSE,vst2q_lane_f32,"ptr: *mut f32, val: float32x4x2_t, lane: const int",void,Store multiple 2-element structures from two registers -FALSE,vst2q_lane_f64,"ptr: *mut float64_t, val: float64x2x2_t, lane: const int",void,Store multiple 2-element structures from two registers -FALSE,vst2q_lane_p16,"ptr: *mut poly16_t, val: poly16x8x2_t, lane: const int",void,Store multiple 2-element structures from two registers -FALSE,vst2q_lane_p64,"ptr: *mut poly64_t, val: poly64x2x2_t, lane: const int",void,Store multiple 2-element structures from two registers -FALSE,vst2q_lane_p8,"ptr: *mut poly8_t, val: poly8x16x2_t, lane: const int",void,Store multiple 2-element structures from two registers -FALSE,vst2q_lane_s16,"ptr: *mut i16, val: int16x8x2_t, lane: const int",void,Store multiple 2-element structures from two registers -FALSE,vst2q_lane_s32,"ptr: *mut i32, val: int32x4x2_t, lane: const int",void,Store multiple 2-element structures from two registers -FALSE,vst2q_lane_s64,"ptr: *mut i64, val: int64x2x2_t, lane: const int",void,Store multiple 2-element structures from two registers -FALSE,vst2q_lane_s8,"ptr: *mut i8, val: int8x16x2_t, lane: const int",void,Store multiple 2-element structures from two registers -FALSE,vst2q_lane_u16,"ptr: *mut u16, val: uint16x8x2_t, lane: const int",void,Store multiple 2-element structures from two registers -FALSE,vst2q_lane_u32,"ptr: *mut u32, val: uint32x4x2_t, lane: const int",void,Store multiple 2-element structures from two registers -FALSE,vst2q_lane_u64,"ptr: *mut u64, val: uint64x2x2_t, lane: const int",void,Store multiple 2-element structures from two registers -FALSE,vst2q_lane_u8,"ptr: *mut u8, val: uint8x16x2_t, lane: const int",void,Store multiple 2-element structures from two registers -FALSE,vst2q_p16,"ptr: *mut poly16_t, val: poly16x8x2_t",void,Store multiple 2-element structures from two registers -FALSE,vst2q_p64,"ptr: *mut poly64_t, val: poly64x2x2_t",void,Store multiple 2-element structures from two registers -FALSE,vst2q_p8,"ptr: *mut poly8_t, val: poly8x16x2_t",void,Store multiple 2-element structures from two registers -FALSE,vst2q_s16,"ptr: *mut i16, val: int16x8x2_t",void,Store multiple 2-element structures from two registers -FALSE,vst2q_s32,"ptr: *mut i32, val: int32x4x2_t",void,Store multiple 2-element structures from two registers -FALSE,vst2q_s64,"ptr: *mut i64, val: int64x2x2_t",void,Store multiple 2-element structures from two registers -FALSE,vst2q_s8,"ptr: *mut i8, val: int8x16x2_t",void,Store multiple 2-element structures from two registers -FALSE,vst2q_u16,"ptr: *mut u16, val: uint16x8x2_t",void,Store multiple 2-element structures from two registers -FALSE,vst2q_u32,"ptr: *mut u32, val: uint32x4x2_t",void,Store multiple 2-element structures from two registers -FALSE,vst2q_u64,"ptr: *mut u64, val: uint64x2x2_t",void,Store multiple 2-element structures from two registers -FALSE,vst2q_u8,"ptr: *mut u8, val: uint8x16x2_t",void,Store multiple 2-element structures from two registers -FALSE,vst3_bf16,"ptr: *mut bfloat16_t, val: bfloat16x4x3_t",void,Store multiple 3-element structures from three registers -FALSE,vst3_f16,"ptr: *mut float16_t, val: float16x4x3_t",void,Store multiple 3-element structures from three registers -FALSE,vst3_f32,"ptr: *mut f32, val: float32x2x3_t",void,Store multiple 3-element structures from three registers -FALSE,vst3_f64,"ptr: *mut float64_t, val: float64x1x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst3_lane_bf16,"ptr: *mut bfloat16_t, val: bfloat16x4x3_t, lane: const int",void,Store multiple 3-element structures from three registers -FALSE,vst3_lane_f16,"ptr: *mut float16_t, val: float16x4x3_t, lane: const int",void,Store multiple 3-element structures from three registers -FALSE,vst3_lane_f32,"ptr: *mut f32, val: float32x2x3_t, lane: const int",void,Store multiple 3-element structures from three registers -FALSE,vst3_lane_f64,"ptr: *mut float64_t, val: float64x1x3_t, lane: const int",void,Store multiple 3-element structures from three registers -FALSE,vst3_lane_p16,"ptr: *mut poly16_t, val: poly16x4x3_t, lane: const int",void,Store multiple 3-element structures from three registers -FALSE,vst3_lane_p64,"ptr: *mut poly64_t, val: poly64x1x3_t, lane: const int",void,Store multiple 3-element structures from three registers -FALSE,vst3_lane_p8,"ptr: *mut poly8_t, val: poly8x8x3_t, lane: const int",void,Store multiple 3-element structures from three registers -FALSE,vst3_lane_s16,"ptr: *mut i16, val: int16x4x3_t, lane: const int",void,Store multiple 3-element structures from three registers -FALSE,vst3_lane_s32,"ptr: *mut i32, val: int32x2x3_t, lane: const int",void,Store multiple 3-element structures from three registers -FALSE,vst3_lane_s64,"ptr: *mut i64, val: int64x1x3_t, lane: const int",void,Store multiple 3-element structures from three registers -FALSE,vst3_lane_s8,"ptr: *mut i8, val: int8x8x3_t, lane: const int",void,Store multiple 3-element structures from three registers -FALSE,vst3_lane_u16,"ptr: *mut u16, val: uint16x4x3_t, lane: const int",void,Store multiple 3-element structures from three registers -FALSE,vst3_lane_u32,"ptr: *mut u32, val: uint32x2x3_t, lane: const int",void,Store multiple 3-element structures from three registers -FALSE,vst3_lane_u64,"ptr: *mut u64, val: uint64x1x3_t, lane: const int",void,Store multiple 3-element structures from three registers -FALSE,vst3_lane_u8,"ptr: *mut u8, val: uint8x8x3_t, lane: const int",void,Store multiple 3-element structures from three registers -FALSE,vst3_p16,"ptr: *mut poly16_t, val: poly16x4x3_t",void,Store multiple 3-element structures from three registers -FALSE,vst3_p64,"ptr: *mut poly64_t, val: poly64x1x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst3_p8,"ptr: *mut poly8_t, val: poly8x8x3_t",void,Store multiple 3-element structures from three registers -FALSE,vst3_s16,"ptr: *mut i16, val: int16x4x3_t",void,Store multiple 3-element structures from three registers -FALSE,vst3_s32,"ptr: *mut i32, val: int32x2x3_t",void,Store multiple 3-element structures from three registers -FALSE,vst3_s64,"ptr: *mut i64, val: int64x1x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst3_s8,"ptr: *mut i8, val: int8x8x3_t",void,Store multiple 3-element structures from three registers -FALSE,vst3_u16,"ptr: *mut u16, val: uint16x4x3_t",void,Store multiple 3-element structures from three registers -FALSE,vst3_u32,"ptr: *mut u32, val: uint32x2x3_t",void,Store multiple 3-element structures from three registers -FALSE,vst3_u64,"ptr: *mut u64, val: uint64x1x3_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst3_u8,"ptr: *mut u8, val: uint8x8x3_t",void,Store multiple 3-element structures from three registers -FALSE,vst3q_bf16,"ptr: *mut bfloat16_t, val: bfloat16x8x3_t",void,Store multiple 3-element structures from three registers -FALSE,vst3q_f16,"ptr: *mut float16_t, val: float16x8x3_t",void,Store multiple 3-element structures from three registers -FALSE,vst3q_f32,"ptr: *mut f32, val: float32x4x3_t",void,Store multiple 3-element structures from three registers -FALSE,vst3q_f64,"ptr: *mut float64_t, val: float64x2x3_t",void,Store multiple 3-element structures from three registers -FALSE,vst3q_lane_bf16,"ptr: *mut bfloat16_t, val: bfloat16x8x3_t, lane: const int",void,Store multiple 3-element structures from three registers -FALSE,vst3q_lane_f16,"ptr: *mut float16_t, val: float16x8x3_t, lane: const int",void,Store multiple 3-element structures from three registers -FALSE,vst3q_lane_f32,"ptr: *mut f32, val: float32x4x3_t, lane: const int",void,Store multiple 3-element structures from three registers -FALSE,vst3q_lane_f64,"ptr: *mut float64_t, val: float64x2x3_t, lane: const int",void,Store multiple 3-element structures from three registers -FALSE,vst3q_lane_p16,"ptr: *mut poly16_t, val: poly16x8x3_t, lane: const int",void,Store multiple 3-element structures from three registers -FALSE,vst3q_lane_p64,"ptr: *mut poly64_t, val: poly64x2x3_t, lane: const int",void,Store multiple 3-element structures from three registers -FALSE,vst3q_lane_p8,"ptr: *mut poly8_t, val: poly8x16x3_t, lane: const int",void,Store multiple 3-element structures from three registers -FALSE,vst3q_lane_s16,"ptr: *mut i16, val: int16x8x3_t, lane: const int",void,Store multiple 3-element structures from three registers -FALSE,vst3q_lane_s32,"ptr: *mut i32, val: int32x4x3_t, lane: const int",void,Store multiple 3-element structures from three registers -FALSE,vst3q_lane_s64,"ptr: *mut i64, val: int64x2x3_t, lane: const int",void,Store multiple 3-element structures from three registers -FALSE,vst3q_lane_s8,"ptr: *mut i8, val: int8x16x3_t, lane: const int",void,Store multiple 3-element structures from three registers -FALSE,vst3q_lane_u16,"ptr: *mut u16, val: uint16x8x3_t, lane: const int",void,Store multiple 3-element structures from three registers -FALSE,vst3q_lane_u32,"ptr: *mut u32, val: uint32x4x3_t, lane: const int",void,Store multiple 3-element structures from three registers -FALSE,vst3q_lane_u64,"ptr: *mut u64, val: uint64x2x3_t, lane: const int",void,Store multiple 3-element structures from three registers -FALSE,vst3q_lane_u8,"ptr: *mut u8, val: uint8x16x3_t, lane: const int",void,Store multiple 3-element structures from three registers -FALSE,vst3q_p16,"ptr: *mut poly16_t, val: poly16x8x3_t",void,Store multiple 3-element structures from three registers -FALSE,vst3q_p64,"ptr: *mut poly64_t, val: poly64x2x3_t",void,Store multiple 3-element structures from three registers -FALSE,vst3q_p8,"ptr: *mut poly8_t, val: poly8x16x3_t",void,Store multiple 3-element structures from three registers -FALSE,vst3q_s16,"ptr: *mut i16, val: int16x8x3_t",void,Store multiple 3-element structures from three registers -FALSE,vst3q_s32,"ptr: *mut i32, val: int32x4x3_t",void,Store multiple 3-element structures from three registers -FALSE,vst3q_s64,"ptr: *mut i64, val: int64x2x3_t",void,Store multiple 3-element structures from three registers -FALSE,vst3q_s8,"ptr: *mut i8, val: int8x16x3_t",void,Store multiple 3-element structures from three registers -FALSE,vst3q_u16,"ptr: *mut u16, val: uint16x8x3_t",void,Store multiple 3-element structures from three registers -FALSE,vst3q_u32,"ptr: *mut u32, val: uint32x4x3_t",void,Store multiple 3-element structures from three registers -FALSE,vst3q_u64,"ptr: *mut u64, val: uint64x2x3_t",void,Store multiple 3-element structures from three registers -FALSE,vst3q_u8,"ptr: *mut u8, val: uint8x16x3_t",void,Store multiple 3-element structures from three registers -FALSE,vst4_bf16,"ptr: *mut bfloat16_t, val: bfloat16x4x4_t",void,Store multiple 4-element structures from four registers -FALSE,vst4_f16,"ptr: *mut float16_t, val: float16x4x4_t",void,Store multiple 4-element structures from four registers -FALSE,vst4_f32,"ptr: *mut f32, val: float32x2x4_t",void,Store multiple 4-element structures from four registers -FALSE,vst4_f64,"ptr: *mut float64_t, val: float64x1x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst4_lane_bf16,"ptr: *mut bfloat16_t, val: bfloat16x4x4_t, lane: const int",void,Store multiple 4-element structures from four registers -FALSE,vst4_lane_f16,"ptr: *mut float16_t, val: float16x4x4_t, lane: const int",void,Store multiple 4-element structures from four registers -FALSE,vst4_lane_f32,"ptr: *mut f32, val: float32x2x4_t, lane: const int",void,Store multiple 4-element structures from four registers -FALSE,vst4_lane_f64,"ptr: *mut float64_t, val: float64x1x4_t, lane: const int",void,Store multiple 4-element structures from four registers -FALSE,vst4_lane_p16,"ptr: *mut poly16_t, val: poly16x4x4_t, lane: const int",void,Store multiple 4-element structures from four registers -FALSE,vst4_lane_p64,"ptr: *mut poly64_t, val: poly64x1x4_t, lane: const int",void,Store multiple 4-element structures from four registers -FALSE,vst4_lane_p8,"ptr: *mut poly8_t, val: poly8x8x4_t, lane: const int",void,Store multiple 4-element structures from four registers -FALSE,vst4_lane_s16,"ptr: *mut i16, val: int16x4x4_t, lane: const int",void,Store multiple 4-element structures from four registers -FALSE,vst4_lane_s32,"ptr: *mut i32, val: int32x2x4_t, lane: const int",void,Store multiple 4-element structures from four registers -FALSE,vst4_lane_s64,"ptr: *mut i64, val: int64x1x4_t, lane: const int",void,Store multiple 4-element structures from four registers -FALSE,vst4_lane_s8,"ptr: *mut i8, val: int8x8x4_t, lane: const int",void,Store multiple 4-element structures from four registers -FALSE,vst4_lane_u16,"ptr: *mut u16, val: uint16x4x4_t, lane: const int",void,Store multiple 4-element structures from four registers -FALSE,vst4_lane_u32,"ptr: *mut u32, val: uint32x2x4_t, lane: const int",void,Store multiple 4-element structures from four registers -FALSE,vst4_lane_u64,"ptr: *mut u64, val: uint64x1x4_t, lane: const int",void,Store multiple 4-element structures from four registers -FALSE,vst4_lane_u8,"ptr: *mut u8, val: uint8x8x4_t, lane: const int",void,Store multiple 4-element structures from four registers -FALSE,vst4_p16,"ptr: *mut poly16_t, val: poly16x4x4_t",void,Store multiple 4-element structures from four registers -FALSE,vst4_p64,"ptr: *mut poly64_t, val: poly64x1x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst4_p8,"ptr: *mut poly8_t, val: poly8x8x4_t",void,Store multiple 4-element structures from four registers -FALSE,vst4_s16,"ptr: *mut i16, val: int16x4x4_t",void,Store multiple 4-element structures from four registers -FALSE,vst4_s32,"ptr: *mut i32, val: int32x2x4_t",void,Store multiple 4-element structures from four registers -FALSE,vst4_s64,"ptr: *mut i64, val: int64x1x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst4_s8,"ptr: *mut i8, val: int8x8x4_t",void,Store multiple 4-element structures from four registers -FALSE,vst4_u16,"ptr: *mut u16, val: uint16x4x4_t",void,Store multiple 4-element structures from four registers -FALSE,vst4_u32,"ptr: *mut u32, val: uint32x2x4_t",void,Store multiple 4-element structures from four registers -FALSE,vst4_u64,"ptr: *mut u64, val: uint64x1x4_t",void,"Store multiple single-element structures from one, two, three, or four registers" -FALSE,vst4_u8,"ptr: *mut u8, val: uint8x8x4_t",void,Store multiple 4-element structures from four registers -FALSE,vst4q_bf16,"ptr: *mut bfloat16_t, val: bfloat16x8x4_t",void,Store multiple 4-element structures from four registers -FALSE,vst4q_f16,"ptr: *mut float16_t, val: float16x8x4_t",void,Store multiple 4-element structures from four registers -FALSE,vst4q_f32,"ptr: *mut f32, val: float32x4x4_t",void,Store multiple 4-element structures from four registers -FALSE,vst4q_f64,"ptr: *mut float64_t, val: float64x2x4_t",void,Store multiple 4-element structures from four registers -FALSE,vst4q_lane_bf16,"ptr: *mut bfloat16_t, val: bfloat16x8x4_t, lane: const int",void,Store multiple 4-element structures from four registers -FALSE,vst4q_lane_f16,"ptr: *mut float16_t, val: float16x8x4_t, lane: const int",void,Store multiple 4-element structures from four registers -FALSE,vst4q_lane_f32,"ptr: *mut f32, val: float32x4x4_t, lane: const int",void,Store multiple 4-element structures from four registers -FALSE,vst4q_lane_f64,"ptr: *mut float64_t, val: float64x2x4_t, lane: const int",void,Store multiple 4-element structures from four registers -FALSE,vst4q_lane_p16,"ptr: *mut poly16_t, val: poly16x8x4_t, lane: const int",void,Store multiple 4-element structures from four registers -FALSE,vst4q_lane_p64,"ptr: *mut poly64_t, val: poly64x2x4_t, lane: const int",void,Store multiple 4-element structures from four registers -FALSE,vst4q_lane_p8,"ptr: *mut poly8_t, val: poly8x16x4_t, lane: const int",void,Store multiple 4-element structures from four registers -FALSE,vst4q_lane_s16,"ptr: *mut i16, val: int16x8x4_t, lane: const int",void,Store multiple 4-element structures from four registers -FALSE,vst4q_lane_s32,"ptr: *mut i32, val: int32x4x4_t, lane: const int",void,Store multiple 4-element structures from four registers -FALSE,vst4q_lane_s64,"ptr: *mut i64, val: int64x2x4_t, lane: const int",void,Store multiple 4-element structures from four registers -FALSE,vst4q_lane_s8,"ptr: *mut i8, val: int8x16x4_t, lane: const int",void,Store multiple 4-element structures from four registers -FALSE,vst4q_lane_u16,"ptr: *mut u16, val: uint16x8x4_t, lane: const int",void,Store multiple 4-element structures from four registers -FALSE,vst4q_lane_u32,"ptr: *mut u32, val: uint32x4x4_t, lane: const int",void,Store multiple 4-element structures from four registers -FALSE,vst4q_lane_u64,"ptr: *mut u64, val: uint64x2x4_t, lane: const int",void,Store multiple 4-element structures from four registers -FALSE,vst4q_lane_u8,"ptr: *mut u8, val: uint8x16x4_t, lane: const int",void,Store multiple 4-element structures from four registers -FALSE,vst4q_p16,"ptr: *mut poly16_t, val: poly16x8x4_t",void,Store multiple 4-element structures from four registers -FALSE,vst4q_p64,"ptr: *mut poly64_t, val: poly64x2x4_t",void,Store multiple 4-element structures from four registers -FALSE,vst4q_p8,"ptr: *mut poly8_t, val: poly8x16x4_t",void,Store multiple 4-element structures from four registers -FALSE,vst4q_s16,"ptr: *mut i16, val: int16x8x4_t",void,Store multiple 4-element structures from four registers -FALSE,vst4q_s32,"ptr: *mut i32, val: int32x4x4_t",void,Store multiple 4-element structures from four registers -FALSE,vst4q_s64,"ptr: *mut i64, val: int64x2x4_t",void,Store multiple 4-element structures from four registers -FALSE,vst4q_s8,"ptr: *mut i8, val: int8x16x4_t",void,Store multiple 4-element structures from four registers -FALSE,vst4q_u16,"ptr: *mut u16, val: uint16x8x4_t",void,Store multiple 4-element structures from four registers -FALSE,vst4q_u32,"ptr: *mut u32, val: uint32x4x4_t",void,Store multiple 4-element structures from four registers -FALSE,vst4q_u64,"ptr: *mut u64, val: uint64x2x4_t",void,Store multiple 4-element structures from four registers -FALSE,vst4q_u8,"ptr: *mut u8, val: uint8x16x4_t",void,Store multiple 4-element structures from four registers -FALSE,vstrq_p128,"ptr: *mut poly128_t, val: poly128_t",void,Store SIMD&FP register (immediate offset) -FALSE,vsub_f16,"a: float16x4_t, b: float16x4_t",float16x4_t,Floating-point subtract -TRUE,vsub_f32,"a: float32x2_t, b: float32x2_t",float32x2_t,Floating-point subtract -TRUE,vsub_f64,"a: float64x1_t, b: float64x1_t",float64x1_t,Floating-point subtract -TRUE,vsub_s16,"a: int16x4_t, b: int16x4_t",int16x4_t,Subtract -TRUE,vsub_s32,"a: int32x2_t, b: int32x2_t",int32x2_t,Subtract -TRUE,vsub_s64,"a: int64x1_t, b: int64x1_t",int64x1_t,Subtract -TRUE,vsub_s8,"a: int8x8_t, b: int8x8_t",int8x8_t,Subtract -TRUE,vsub_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4_t,Subtract -TRUE,vsub_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2_t,Subtract -TRUE,vsub_u64,"a: uint64x1_t, b: uint64x1_t",uint64x1_t,Subtract -TRUE,vsub_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,Subtract -FALSE,vsubd_s64,"a: i64, b: i64",i64,Subtract -FALSE,vsubd_u64,"a: u64, b: u64",u64,Subtract -FALSE,vsubh_f16,"a: float16_t, b: float16_t",float16_t,Floating-point subtract -TRUE,vsubhn_high_s16,"r: int8x8_t, a: int16x8_t, b: int16x8_t",int8x16_t,Subtract returning high narrow -TRUE,vsubhn_high_s32,"r: int16x4_t, a: int32x4_t, b: int32x4_t",int16x8_t,Subtract returning high narrow -TRUE,vsubhn_high_s64,"r: int32x2_t, a: int64x2_t, b: int64x2_t",int32x4_t,Subtract returning high narrow -TRUE,vsubhn_high_u16,"r: uint8x8_t, a: uint16x8_t, b: uint16x8_t",uint8x16_t,Subtract returning high narrow -TRUE,vsubhn_high_u32,"r: uint16x4_t, a: uint32x4_t, b: uint32x4_t",uint16x8_t,Subtract returning high narrow -TRUE,vsubhn_high_u64,"r: uint32x2_t, a: uint64x2_t, b: uint64x2_t",uint32x4_t,Subtract returning high narrow -TRUE,vsubhn_s16,"a: int16x8_t, b: int16x8_t",int8x8_t,Subtract returning high narrow -TRUE,vsubhn_s32,"a: int32x4_t, b: int32x4_t",int16x4_t,Subtract returning high narrow -TRUE,vsubhn_s64,"a: int64x2_t, b: int64x2_t",int32x2_t,Subtract returning high narrow -TRUE,vsubhn_u16,"a: uint16x8_t, b: uint16x8_t",uint8x8_t,Subtract returning high narrow -TRUE,vsubhn_u32,"a: uint32x4_t, b: uint32x4_t",uint16x4_t,Subtract returning high narrow -TRUE,vsubhn_u64,"a: uint64x2_t, b: uint64x2_t",uint32x2_t,Subtract returning high narrow -TRUE,vsubl_high_s16,"a: int16x8_t, b: int16x8_t",int32x4_t,Signed subtract long -TRUE,vsubl_high_s32,"a: int32x4_t, b: int32x4_t",int64x2_t,Signed subtract long -TRUE,vsubl_high_s8,"a: int8x16_t, b: int8x16_t",int16x8_t,Signed subtract long -TRUE,vsubl_high_u16,"a: uint16x8_t, b: uint16x8_t",uint32x4_t,Unsigned subtract long -TRUE,vsubl_high_u32,"a: uint32x4_t, b: uint32x4_t",uint64x2_t,Unsigned subtract long -TRUE,vsubl_high_u8,"a: uint8x16_t, b: uint8x16_t",uint16x8_t,Unsigned subtract long -TRUE,vsubl_s16,"a: int16x4_t, b: int16x4_t",int32x4_t,Signed subtract long -TRUE,vsubl_s32,"a: int32x2_t, b: int32x2_t",int64x2_t,Signed subtract long -TRUE,vsubl_s8,"a: int8x8_t, b: int8x8_t",int16x8_t,Signed subtract long -TRUE,vsubl_u16,"a: uint16x4_t, b: uint16x4_t",uint32x4_t,Unsigned subtract long -TRUE,vsubl_u32,"a: uint32x2_t, b: uint32x2_t",uint64x2_t,Unsigned subtract long -TRUE,vsubl_u8,"a: uint8x8_t, b: uint8x8_t",uint16x8_t,Unsigned subtract long -FALSE,vsubq_f16,"a: float16x8_t, b: float16x8_t",float16x8_t,Floating-point subtract -TRUE,vsubq_f32,"a: float32x4_t, b: float32x4_t",float32x4_t,Floating-point subtract -TRUE,vsubq_f64,"a: float64x2_t, b: float64x2_t",float64x2_t,Floating-point subtract -TRUE,vsubq_s16,"a: int16x8_t, b: int16x8_t",int16x8_t,Subtract -TRUE,vsubq_s32,"a: int32x4_t, b: int32x4_t",int32x4_t,Subtract -TRUE,vsubq_s64,"a: int64x2_t, b: int64x2_t",int64x2_t,Subtract -TRUE,vsubq_s8,"a: int8x16_t, b: int8x16_t",int8x16_t,Subtract -TRUE,vsubq_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8_t,Subtract -TRUE,vsubq_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,Subtract -TRUE,vsubq_u64,"a: uint64x2_t, b: uint64x2_t",uint64x2_t,Subtract -TRUE,vsubq_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16_t,Subtract -TRUE,vsubw_high_s16,"a: int32x4_t, b: int16x8_t",int32x4_t,Signed subtract wide -TRUE,vsubw_high_s32,"a: int64x2_t, b: int32x4_t",int64x2_t,Signed subtract wide -TRUE,vsubw_high_s8,"a: int16x8_t, b: int8x16_t",int16x8_t,Signed subtract wide -TRUE,vsubw_high_u16,"a: uint32x4_t, b: uint16x8_t",uint32x4_t,Unsigned subtract wide -TRUE,vsubw_high_u32,"a: uint64x2_t, b: uint32x4_t",uint64x2_t,Unsigned subtract wide -TRUE,vsubw_high_u8,"a: uint16x8_t, b: uint8x16_t",uint16x8_t,Unsigned subtract wide -TRUE,vsubw_s16,"a: int32x4_t, b: int16x4_t",int32x4_t,Signed subtract wide -TRUE,vsubw_s32,"a: int64x2_t, b: int32x2_t",int64x2_t,Signed subtract wide -TRUE,vsubw_s8,"a: int16x8_t, b: int8x8_t",int16x8_t,Signed subtract wide -TRUE,vsubw_u16,"a: uint32x4_t, b: uint16x4_t",uint32x4_t,Unsigned subtract wide -TRUE,vsubw_u32,"a: uint64x2_t, b: uint32x2_t",uint64x2_t,Unsigned subtract wide -TRUE,vsubw_u8,"a: uint16x8_t, b: uint8x8_t",uint16x8_t,Unsigned subtract wide -FALSE,vsudot_lane_s32,"r: int32x2_t, a: int8x8_t, b: uint8x8_t, lane: const int",int32x2_t,Dot product index form with signed and unsigned integers -FALSE,vsudot_laneq_s32,"r: int32x2_t, a: int8x8_t, b: uint8x16_t, lane: const int",int32x2_t,Dot product index form with signed and unsigned integers -FALSE,vsudotq_lane_s32,"r: int32x4_t, a: int8x16_t, b: uint8x8_t, lane: const int",int32x4_t,Dot product index form with signed and unsigned integers -FALSE,vsudotq_laneq_s32,"r: int32x4_t, a: int8x16_t, b: uint8x16_t, lane: const int",int32x4_t,Dot product index form with signed and unsigned integers -TRUE,vtbl1_p8,"a: poly8x8_t, b: uint8x8_t",poly8x8_t,Table vector lookup -TRUE,vtbl1_s8,"a: int8x8_t, b: int8x8_t",int8x8_t,Table vector lookup -TRUE,vtbl1_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,Table vector lookup -TRUE,vtbl2_p8,"a: poly8x8x2_t, b: uint8x8_t",poly8x8_t,Table vector lookup -TRUE,vtbl2_s8,"a: int8x8x2_t, b: int8x8_t",int8x8_t,Table vector lookup -TRUE,vtbl2_u8,"a: uint8x8x2_t, b: uint8x8_t",uint8x8_t,Table vector lookup -TRUE,vtbl3_p8,"a: poly8x8x3_t, b: uint8x8_t",poly8x8_t,Table vector lookup -TRUE,vtbl3_s8,"a: int8x8x3_t, b: int8x8_t",int8x8_t,Table vector lookup -TRUE,vtbl3_u8,"a: uint8x8x3_t, b: uint8x8_t",uint8x8_t,Table vector lookup -TRUE,vtbl4_p8,"a: poly8x8x4_t, b: uint8x8_t",poly8x8_t,Table vector lookup -TRUE,vtbl4_s8,"a: int8x8x4_t, b: int8x8_t",int8x8_t,Table vector lookup -TRUE,vtbl4_u8,"a: uint8x8x4_t, b: uint8x8_t",uint8x8_t,Table vector lookup -TRUE,vtbx1_p8,"a: poly8x8_t, b: poly8x8_t, c: uint8x8_t",poly8x8_t,Bitwise insert if false -TRUE,vtbx1_s8,"a: int8x8_t, b: int8x8_t, c: int8x8_t",int8x8_t,Bitwise insert if false -TRUE,vtbx1_u8,"a: uint8x8_t, b: uint8x8_t, c: uint8x8_t",uint8x8_t,Bitwise insert if false -TRUE,vtbx2_p8,"a: poly8x8_t, b: poly8x8x2_t, c: uint8x8_t",poly8x8_t,Table vector lookup extension -TRUE,vtbx2_s8,"a: int8x8_t, b: int8x8x2_t, c: int8x8_t",int8x8_t,Table vector lookup extension -TRUE,vtbx2_u8,"a: uint8x8_t, b: uint8x8x2_t, c: uint8x8_t",uint8x8_t,Table vector lookup extension -TRUE,vtbx3_p8,"a: poly8x8_t, b: poly8x8x3_t, c: uint8x8_t",poly8x8_t,Bitwise insert if false -TRUE,vtbx3_s8,"a: int8x8_t, b: int8x8x3_t, c: int8x8_t",int8x8_t,Bitwise insert if false -TRUE,vtbx3_u8,"a: uint8x8_t, b: uint8x8x3_t, c: uint8x8_t",uint8x8_t,Bitwise insert if false -TRUE,vtbx4_p8,"a: poly8x8_t, b: poly8x8x4_t, c: uint8x8_t",poly8x8_t,Table vector lookup extension -TRUE,vtbx4_s8,"a: int8x8_t, b: int8x8x4_t, c: int8x8_t",int8x8_t,Table vector lookup extension -TRUE,vtbx4_u8,"a: uint8x8_t, b: uint8x8x4_t, c: uint8x8_t",uint8x8_t,Table vector lookup extension -FALSE,vtrn_f16,"a: float16x4_t, b: float16x4_t",float16x4x2_t,Transpose elements -FALSE,vtrn_f32,"a: float32x2_t, b: float32x2_t",float32x2x2_t,Transpose elements -FALSE,vtrn_p16,"a: poly16x4_t, b: poly16x4_t",poly16x4x2_t,Transpose elements -FALSE,vtrn_p8,"a: poly8x8_t, b: poly8x8_t",poly8x8x2_t,Transpose elements -FALSE,vtrn_s16,"a: int16x4_t, b: int16x4_t",int16x4x2_t,Transpose elements -FALSE,vtrn_s32,"a: int32x2_t, b: int32x2_t",int32x2x2_t,Transpose elements -FALSE,vtrn_s8,"a: int8x8_t, b: int8x8_t",int8x8x2_t,Transpose elements -FALSE,vtrn_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4x2_t,Transpose elements -FALSE,vtrn_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2x2_t,Transpose elements -FALSE,vtrn_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8x2_t,Transpose elements -FALSE,vtrn1_f16,"a: float16x4_t, b: float16x4_t",float16x4_t,Transpose vectors -TRUE,vtrn1_f32,"a: float32x2_t, b: float32x2_t",float32x2_t,Transpose vectors -TRUE,vtrn1_p16,"a: poly16x4_t, b: poly16x4_t",poly16x4_t,Transpose vectors -TRUE,vtrn1_p8,"a: poly8x8_t, b: poly8x8_t",poly8x8_t,Transpose vectors -TRUE,vtrn1_s16,"a: int16x4_t, b: int16x4_t",int16x4_t,Transpose vectors -TRUE,vtrn1_s32,"a: int32x2_t, b: int32x2_t",int32x2_t,Transpose vectors -TRUE,vtrn1_s8,"a: int8x8_t, b: int8x8_t",int8x8_t,Transpose vectors -TRUE,vtrn1_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4_t,Transpose vectors -TRUE,vtrn1_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2_t,Transpose vectors -TRUE,vtrn1_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,Transpose vectors -FALSE,vtrn1q_f16,"a: float16x8_t, b: float16x8_t",float16x8_t,Transpose vectors -TRUE,vtrn1q_f32,"a: float32x4_t, b: float32x4_t",float32x4_t,Transpose vectors -TRUE,vtrn1q_f64,"a: float64x2_t, b: float64x2_t",float64x2_t,Transpose vectors -TRUE,vtrn1q_p16,"a: poly16x8_t, b: poly16x8_t",poly16x8_t,Transpose vectors -TRUE,vtrn1q_p64,"a: poly64x2_t, b: poly64x2_t",poly64x2_t,Transpose vectors -TRUE,vtrn1q_p8,"a: poly8x16_t, b: poly8x16_t",poly8x16_t,Transpose vectors -TRUE,vtrn1q_s16,"a: int16x8_t, b: int16x8_t",int16x8_t,Transpose vectors -TRUE,vtrn1q_s32,"a: int32x4_t, b: int32x4_t",int32x4_t,Transpose vectors -TRUE,vtrn1q_s64,"a: int64x2_t, b: int64x2_t",int64x2_t,Transpose vectors -TRUE,vtrn1q_s8,"a: int8x16_t, b: int8x16_t",int8x16_t,Transpose vectors -TRUE,vtrn1q_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8_t,Transpose vectors -TRUE,vtrn1q_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,Transpose vectors -TRUE,vtrn1q_u64,"a: uint64x2_t, b: uint64x2_t",uint64x2_t,Transpose vectors -TRUE,vtrn1q_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16_t,Transpose vectors -FALSE,vtrn2_f16,"a: float16x4_t, b: float16x4_t",float16x4_t,Transpose vectors -TRUE,vtrn2_f32,"a: float32x2_t, b: float32x2_t",float32x2_t,Transpose vectors -TRUE,vtrn2_p16,"a: poly16x4_t, b: poly16x4_t",poly16x4_t,Transpose vectors -TRUE,vtrn2_p8,"a: poly8x8_t, b: poly8x8_t",poly8x8_t,Transpose vectors -TRUE,vtrn2_s16,"a: int16x4_t, b: int16x4_t",int16x4_t,Transpose vectors -TRUE,vtrn2_s32,"a: int32x2_t, b: int32x2_t",int32x2_t,Transpose vectors -TRUE,vtrn2_s8,"a: int8x8_t, b: int8x8_t",int8x8_t,Transpose vectors -TRUE,vtrn2_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4_t,Transpose vectors -TRUE,vtrn2_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2_t,Transpose vectors -TRUE,vtrn2_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,Transpose vectors -FALSE,vtrn2q_f16,"a: float16x8_t, b: float16x8_t",float16x8_t,Transpose vectors -TRUE,vtrn2q_f32,"a: float32x4_t, b: float32x4_t",float32x4_t,Transpose vectors -TRUE,vtrn2q_f64,"a: float64x2_t, b: float64x2_t",float64x2_t,Transpose vectors -TRUE,vtrn2q_p16,"a: poly16x8_t, b: poly16x8_t",poly16x8_t,Transpose vectors -TRUE,vtrn2q_p64,"a: poly64x2_t, b: poly64x2_t",poly64x2_t,Transpose vectors -TRUE,vtrn2q_p8,"a: poly8x16_t, b: poly8x16_t",poly8x16_t,Transpose vectors -TRUE,vtrn2q_s16,"a: int16x8_t, b: int16x8_t",int16x8_t,Transpose vectors -TRUE,vtrn2q_s32,"a: int32x4_t, b: int32x4_t",int32x4_t,Transpose vectors -TRUE,vtrn2q_s64,"a: int64x2_t, b: int64x2_t",int64x2_t,Transpose vectors -TRUE,vtrn2q_s8,"a: int8x16_t, b: int8x16_t",int8x16_t,Transpose vectors -TRUE,vtrn2q_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8_t,Transpose vectors -TRUE,vtrn2q_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,Transpose vectors -TRUE,vtrn2q_u64,"a: uint64x2_t, b: uint64x2_t",uint64x2_t,Transpose vectors -TRUE,vtrn2q_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16_t,Transpose vectors -FALSE,vtrnq_f16,"a: float16x8_t, b: float16x8_t",float16x8x2_t,Transpose elements -FALSE,vtrnq_f32,"a: float32x4_t, b: float32x4_t",float32x4x2_t,Transpose elements -FALSE,vtrnq_p16,"a: poly16x8_t, b: poly16x8_t",poly16x8x2_t,Transpose elements -FALSE,vtrnq_p8,"a: poly8x16_t, b: poly8x16_t",poly8x16x2_t,Transpose elements -FALSE,vtrnq_s16,"a: int16x8_t, b: int16x8_t",int16x8x2_t,Transpose elements -FALSE,vtrnq_s32,"a: int32x4_t, b: int32x4_t",int32x4x2_t,Transpose elements -FALSE,vtrnq_s8,"a: int8x16_t, b: int8x16_t",int8x16x2_t,Transpose elements -FALSE,vtrnq_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8x2_t,Transpose elements -FALSE,vtrnq_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4x2_t,Transpose elements -FALSE,vtrnq_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16x2_t,Transpose elements -TRUE,vtst_p64,"a: poly64x1_t, b: poly64x1_t",uint64x1_t,Compare bitwise test bits nonzero -TRUE,vtst_p8,"a: poly8x8_t, b: poly8x8_t",uint8x8_t,Compare bitwise test bits nonzero -TRUE,vtst_s16,"a: int16x4_t, b: int16x4_t",uint16x4_t,Compare bitwise test bits nonzero -TRUE,vtst_s32,"a: int32x2_t, b: int32x2_t",uint32x2_t,Compare bitwise test bits nonzero -TRUE,vtst_s64,"a: int64x1_t, b: int64x1_t",uint64x1_t,Compare bitwise test bits nonzero -TRUE,vtst_s8,"a: int8x8_t, b: int8x8_t",uint8x8_t,Compare bitwise test bits nonzero -TRUE,vtst_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4_t,Compare bitwise test bits nonzero -TRUE,vtst_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2_t,Compare bitwise test bits nonzero -TRUE,vtst_u64,"a: uint64x1_t, b: uint64x1_t",uint64x1_t,Compare bitwise test bits nonzero -TRUE,vtst_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,Compare bitwise test bits nonzero -FALSE,vtstd_s64,"a: i64, b: i64",u64,Compare bitwise test bits nonzero -FALSE,vtstd_u64,"a: u64, b: u64",u64,Compare bitwise test bits nonzero -TRUE,vtstq_p64,"a: poly64x2_t, b: poly64x2_t",uint64x2_t,Compare bitwise test bits nonzero -TRUE,vtstq_p8,"a: poly8x16_t, b: poly8x16_t",uint8x16_t,Compare bitwise test bits nonzero -TRUE,vtstq_s16,"a: int16x8_t, b: int16x8_t",uint16x8_t,Compare bitwise test bits nonzero -TRUE,vtstq_s32,"a: int32x4_t, b: int32x4_t",uint32x4_t,Compare bitwise test bits nonzero -TRUE,vtstq_s64,"a: int64x2_t, b: int64x2_t",uint64x2_t,Compare bitwise test bits nonzero -TRUE,vtstq_s8,"a: int8x16_t, b: int8x16_t",uint8x16_t,Compare bitwise test bits nonzero -TRUE,vtstq_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8_t,Compare bitwise test bits nonzero -TRUE,vtstq_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,Compare bitwise test bits nonzero -TRUE,vtstq_u64,"a: uint64x2_t, b: uint64x2_t",uint64x2_t,Compare bitwise test bits nonzero -TRUE,vtstq_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16_t,Compare bitwise test bits nonzero -FALSE,vuqadd_s16,"a: int16x4_t, b: uint16x4_t",int16x4_t,Signed saturating accumulate of unsigned value -FALSE,vuqadd_s32,"a: int32x2_t, b: uint32x2_t",int32x2_t,Signed saturating accumulate of unsigned value -FALSE,vuqadd_s64,"a: int64x1_t, b: uint64x1_t",int64x1_t,Signed saturating accumulate of unsigned value -FALSE,vuqadd_s8,"a: int8x8_t, b: uint8x8_t",int8x8_t,Signed saturating accumulate of unsigned value -FALSE,vuqaddb_s8,"a: i8, b: u8",i8,Signed saturating accumulate of unsigned value -FALSE,vuqaddd_s64,"a: i64, b: u64",i64,Signed saturating accumulate of unsigned value -FALSE,vuqaddh_s16,"a: i16, b: u16",i16,Signed saturating accumulate of unsigned value -FALSE,vuqaddq_s16,"a: int16x8_t, b: uint16x8_t",int16x8_t,Signed saturating accumulate of unsigned value -FALSE,vuqaddq_s32,"a: int32x4_t, b: uint32x4_t",int32x4_t,Signed saturating accumulate of unsigned value -FALSE,vuqaddq_s64,"a: int64x2_t, b: uint64x2_t",int64x2_t,Signed saturating accumulate of unsigned value -FALSE,vuqaddq_s8,"a: int8x16_t, b: uint8x16_t",int8x16_t,Signed saturating accumulate of unsigned value -FALSE,vuqadds_s32,"a: i32, b: u32",i32,Signed saturating accumulate of unsigned value -FALSE,vusdot_lane_s32,"r: int32x2_t, a: uint8x8_t, b: int8x8_t, lane: const int",int32x2_t,Dot product vector form with unsigned and signed integers -FALSE,vusdot_laneq_s32,"r: int32x2_t, a: uint8x8_t, b: int8x16_t, lane: const int",int32x2_t,Dot product vector form with unsigned and signed integers -FALSE,vusdot_s32,"r: int32x2_t, a: uint8x8_t, b: int8x8_t",int32x2_t,Dot product vector form with unsigned and signed integers -FALSE,vusdotq_lane_s32,"r: int32x4_t, a: uint8x16_t, b: int8x8_t, lane: const int",int32x4_t,Dot product vector form with unsigned and signed integers -FALSE,vusdotq_laneq_s32,"r: int32x4_t, a: uint8x16_t, b: int8x16_t, lane: const int",int32x4_t,Dot product vector form with unsigned and signed integers -FALSE,vusdotq_s32,"r: int32x4_t, a: uint8x16_t, b: int8x16_t",int32x4_t,Dot product vector form with unsigned and signed integers -FALSE,vusmmlaq_s32,"r: int32x4_t, a: uint8x16_t, b: int8x16_t",int32x4_t,Unsigned and signed 8-bit integer matrix multiply-accumulate -FALSE,vuzp_f16,"a: float16x4_t, b: float16x4_t",float16x4x2_t,Unzip vectors -FALSE,vuzp_f32,"a: float32x2_t, b: float32x2_t",float32x2x2_t,Unzip vectors -FALSE,vuzp_p16,"a: poly16x4_t, b: poly16x4_t",poly16x4x2_t,Unzip vectors -FALSE,vuzp_p8,"a: poly8x8_t, b: poly8x8_t",poly8x8x2_t,Unzip vectors -FALSE,vuzp_s16,"a: int16x4_t, b: int16x4_t",int16x4x2_t,Unzip vectors -FALSE,vuzp_s32,"a: int32x2_t, b: int32x2_t",int32x2x2_t,Unzip vectors -FALSE,vuzp_s8,"a: int8x8_t, b: int8x8_t",int8x8x2_t,Unzip vectors -FALSE,vuzp_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4x2_t,Unzip vectors -FALSE,vuzp_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2x2_t,Unzip vectors -FALSE,vuzp_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8x2_t,Unzip vectors -FALSE,vuzp1_f16,"a: float16x4_t, b: float16x4_t",float16x4_t,Unzip vectors -TRUE,vuzp1_f32,"a: float32x2_t, b: float32x2_t",float32x2_t,Unzip vectors -FALSE,vuzp1_p16,"a: poly16x4_t, b: poly16x4_t",poly16x4_t,Unzip vectors -TRUE,vuzp1_p8,"a: poly8x8_t, b: poly8x8_t",poly8x8_t,Unzip vectors -TRUE,vuzp1_s16,"a: int16x4_t, b: int16x4_t",int16x4_t,Unzip vectors -TRUE,vuzp1_s32,"a: int32x2_t, b: int32x2_t",int32x2_t,Unzip vectors -TRUE,vuzp1_s8,"a: int8x8_t, b: int8x8_t",int8x8_t,Unzip vectors -TRUE,vuzp1_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4_t,Unzip vectors -TRUE,vuzp1_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2_t,Unzip vectors -TRUE,vuzp1_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,Unzip vectors -FALSE,vuzp1q_f16,"a: float16x8_t, b: float16x8_t",float16x8_t,Unzip vectors -TRUE,vuzp1q_f32,"a: float32x4_t, b: float32x4_t",float32x4_t,Unzip vectors -TRUE,vuzp1q_f64,"a: float64x2_t, b: float64x2_t",float64x2_t,Unzip vectors -FALSE,vuzp1q_p16,"a: poly16x8_t, b: poly16x8_t",poly16x8_t,Unzip vectors -TRUE,vuzp1q_p64,"a: poly64x2_t, b: poly64x2_t",poly64x2_t,Unzip vectors -FALSE,vuzp1q_p8,"a: poly8x16_t, b: poly8x16_t",poly8x16_t,Unzip vectors -TRUE,vuzp1q_s16,"a: int16x8_t, b: int16x8_t",int16x8_t,Unzip vectors -TRUE,vuzp1q_s32,"a: int32x4_t, b: int32x4_t",int32x4_t,Unzip vectors -TRUE,vuzp1q_s64,"a: int64x2_t, b: int64x2_t",int64x2_t,Unzip vectors -TRUE,vuzp1q_s8,"a: int8x16_t, b: int8x16_t",int8x16_t,Unzip vectors -TRUE,vuzp1q_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8_t,Unzip vectors -TRUE,vuzp1q_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,Unzip vectors -TRUE,vuzp1q_u64,"a: uint64x2_t, b: uint64x2_t",uint64x2_t,Unzip vectors -TRUE,vuzp1q_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16_t,Unzip vectors -FALSE,vuzp2_f16,"a: float16x4_t, b: float16x4_t",float16x4_t,Unzip vectors -TRUE,vuzp2_f32,"a: float32x2_t, b: float32x2_t",float32x2_t,Unzip vectors -FALSE,vuzp2_p16,"a: poly16x4_t, b: poly16x4_t",poly16x4_t,Unzip vectors -TRUE,vuzp2_p8,"a: poly8x8_t, b: poly8x8_t",poly8x8_t,Unzip vectors -TRUE,vuzp2_s16,"a: int16x4_t, b: int16x4_t",int16x4_t,Unzip vectors -TRUE,vuzp2_s32,"a: int32x2_t, b: int32x2_t",int32x2_t,Unzip vectors -TRUE,vuzp2_s8,"a: int8x8_t, b: int8x8_t",int8x8_t,Unzip vectors -TRUE,vuzp2_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4_t,Unzip vectors -TRUE,vuzp2_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2_t,Unzip vectors -TRUE,vuzp2_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,Unzip vectors -FALSE,vuzp2q_f16,"a: float16x8_t, b: float16x8_t",float16x8_t,Unzip vectors -TRUE,vuzp2q_f32,"a: float32x4_t, b: float32x4_t",float32x4_t,Unzip vectors -TRUE,vuzp2q_f64,"a: float64x2_t, b: float64x2_t",float64x2_t,Unzip vectors -FALSE,vuzp2q_p16,"a: poly16x8_t, b: poly16x8_t",poly16x8_t,Unzip vectors -TRUE,vuzp2q_p64,"a: poly64x2_t, b: poly64x2_t",poly64x2_t,Unzip vectors -FALSE,vuzp2q_p8,"a: poly8x16_t, b: poly8x16_t",poly8x16_t,Unzip vectors -TRUE,vuzp2q_s16,"a: int16x8_t, b: int16x8_t",int16x8_t,Unzip vectors -TRUE,vuzp2q_s32,"a: int32x4_t, b: int32x4_t",int32x4_t,Unzip vectors -TRUE,vuzp2q_s64,"a: int64x2_t, b: int64x2_t",int64x2_t,Unzip vectors -TRUE,vuzp2q_s8,"a: int8x16_t, b: int8x16_t",int8x16_t,Unzip vectors -TRUE,vuzp2q_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8_t,Unzip vectors -TRUE,vuzp2q_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,Unzip vectors -TRUE,vuzp2q_u64,"a: uint64x2_t, b: uint64x2_t",uint64x2_t,Unzip vectors -TRUE,vuzp2q_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16_t,Unzip vectors -FALSE,vuzpq_f16,"a: float16x8_t, b: float16x8_t",float16x8x2_t,Unzip vectors -FALSE,vuzpq_f32,"a: float32x4_t, b: float32x4_t",float32x4x2_t,Unzip vectors -FALSE,vuzpq_p16,"a: poly16x8_t, b: poly16x8_t",poly16x8x2_t,Unzip vectors -FALSE,vuzpq_p8,"a: poly8x16_t, b: poly8x16_t",poly8x16x2_t,Unzip vectors -FALSE,vuzpq_s16,"a: int16x8_t, b: int16x8_t",int16x8x2_t,Unzip vectors -FALSE,vuzpq_s32,"a: int32x4_t, b: int32x4_t",int32x4x2_t,Unzip vectors -FALSE,vuzpq_s8,"a: int8x16_t, b: int8x16_t",int8x16x2_t,Unzip vectors -FALSE,vuzpq_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8x2_t,Unzip vectors -FALSE,vuzpq_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4x2_t,Unzip vectors -FALSE,vuzpq_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16x2_t,Unzip vectors -FALSE,vxarq_u64,"a: uint64x2_t, b: uint64x2_t, imm6: const int",uint64x2_t,Exclusive OR and rotate -FALSE,vzip_f16,"a: float16x4_t, b: float16x4_t",float16x4x2_t,Zip vectors -FALSE,vzip_f32,"a: float32x2_t, b: float32x2_t",float32x2x2_t,Zip vectors -FALSE,vzip_p16,"a: poly16x4_t, b: poly16x4_t",poly16x4x2_t,Zip vectors -FALSE,vzip_p8,"a: poly8x8_t, b: poly8x8_t",poly8x8x2_t,Zip vectors -FALSE,vzip_s16,"a: int16x4_t, b: int16x4_t",int16x4x2_t,Zip vectors -FALSE,vzip_s32,"a: int32x2_t, b: int32x2_t",int32x2x2_t,Zip vectors -FALSE,vzip_s8,"a: int8x8_t, b: int8x8_t",int8x8x2_t,Zip vectors -FALSE,vzip_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4x2_t,Zip vectors -FALSE,vzip_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2x2_t,Zip vectors -FALSE,vzip_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8x2_t,Zip vectors -FALSE,vzip1_f16,"a: float16x4_t, b: float16x4_t",float16x4_t,Zip vectors -TRUE,vzip1_f32,"a: float32x2_t, b: float32x2_t",float32x2_t,Zip vectors -TRUE,vzip1_p16,"a: poly16x4_t, b: poly16x4_t",poly16x4_t,Zip vectors -TRUE,vzip1_p8,"a: poly8x8_t, b: poly8x8_t",poly8x8_t,Zip vectors -TRUE,vzip1_s16,"a: int16x4_t, b: int16x4_t",int16x4_t,Zip vectors -TRUE,vzip1_s32,"a: int32x2_t, b: int32x2_t",int32x2_t,Zip vectors -TRUE,vzip1_s8,"a: int8x8_t, b: int8x8_t",int8x8_t,Zip vectors -TRUE,vzip1_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4_t,Zip vectors -TRUE,vzip1_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2_t,Zip vectors -TRUE,vzip1_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,Zip vectors -FALSE,vzip1q_f16,"a: float16x8_t, b: float16x8_t",float16x8_t,Zip vectors -TRUE,vzip1q_f32,"a: float32x4_t, b: float32x4_t",float32x4_t,Zip vectors -TRUE,vzip1q_f64,"a: float64x2_t, b: float64x2_t",float64x2_t,Zip vectors -TRUE,vzip1q_p16,"a: poly16x8_t, b: poly16x8_t",poly16x8_t,Zip vectors -TRUE,vzip1q_p64,"a: poly64x2_t, b: poly64x2_t",poly64x2_t,Zip vectors -TRUE,vzip1q_p8,"a: poly8x16_t, b: poly8x16_t",poly8x16_t,Zip vectors -TRUE,vzip1q_s16,"a: int16x8_t, b: int16x8_t",int16x8_t,Zip vectors -TRUE,vzip1q_s32,"a: int32x4_t, b: int32x4_t",int32x4_t,Zip vectors -TRUE,vzip1q_s64,"a: int64x2_t, b: int64x2_t",int64x2_t,Zip vectors -TRUE,vzip1q_s8,"a: int8x16_t, b: int8x16_t",int8x16_t,Zip vectors -TRUE,vzip1q_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8_t,Zip vectors -TRUE,vzip1q_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,Zip vectors -TRUE,vzip1q_u64,"a: uint64x2_t, b: uint64x2_t",uint64x2_t,Zip vectors -TRUE,vzip1q_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16_t,Zip vectors -FALSE,vzip2_f16,"a: float16x4_t, b: float16x4_t",float16x4_t,Zip vectors -TRUE,vzip2_f32,"a: float32x2_t, b: float32x2_t",float32x2_t,Zip vectors -TRUE,vzip2_p16,"a: poly16x4_t, b: poly16x4_t",poly16x4_t,Zip vectors -TRUE,vzip2_p8,"a: poly8x8_t, b: poly8x8_t",poly8x8_t,Zip vectors -TRUE,vzip2_s16,"a: int16x4_t, b: int16x4_t",int16x4_t,Zip vectors -TRUE,vzip2_s32,"a: int32x2_t, b: int32x2_t",int32x2_t,Zip vectors -TRUE,vzip2_s8,"a: int8x8_t, b: int8x8_t",int8x8_t,Zip vectors -TRUE,vzip2_u16,"a: uint16x4_t, b: uint16x4_t",uint16x4_t,Zip vectors -TRUE,vzip2_u32,"a: uint32x2_t, b: uint32x2_t",uint32x2_t,Zip vectors -TRUE,vzip2_u8,"a: uint8x8_t, b: uint8x8_t",uint8x8_t,Zip vectors -FALSE,vzip2q_f16,"a: float16x8_t, b: float16x8_t",float16x8_t,Zip vectors -TRUE,vzip2q_f32,"a: float32x4_t, b: float32x4_t",float32x4_t,Zip vectors -TRUE,vzip2q_f64,"a: float64x2_t, b: float64x2_t",float64x2_t,Zip vectors -TRUE,vzip2q_p16,"a: poly16x8_t, b: poly16x8_t",poly16x8_t,Zip vectors -TRUE,vzip2q_p64,"a: poly64x2_t, b: poly64x2_t",poly64x2_t,Zip vectors -TRUE,vzip2q_p8,"a: poly8x16_t, b: poly8x16_t",poly8x16_t,Zip vectors -TRUE,vzip2q_s16,"a: int16x8_t, b: int16x8_t",int16x8_t,Zip vectors -TRUE,vzip2q_s32,"a: int32x4_t, b: int32x4_t",int32x4_t,Zip vectors -TRUE,vzip2q_s64,"a: int64x2_t, b: int64x2_t",int64x2_t,Zip vectors -TRUE,vzip2q_s8,"a: int8x16_t, b: int8x16_t",int8x16_t,Zip vectors -TRUE,vzip2q_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8_t,Zip vectors -TRUE,vzip2q_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4_t,Zip vectors -TRUE,vzip2q_u64,"a: uint64x2_t, b: uint64x2_t",uint64x2_t,Zip vectors -TRUE,vzip2q_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16_t,Zip vectors -FALSE,vzipq_f16,"a: float16x8_t, b: float16x8_t",float16x8x2_t,Zip vectors -FALSE,vzipq_f32,"a: float32x4_t, b: float32x4_t",float32x4x2_t,Zip vectors -FALSE,vzipq_p16,"a: poly16x8_t, b: poly16x8_t",poly16x8x2_t,Zip vectors -FALSE,vzipq_p8,"a: poly8x16_t, b: poly8x16_t",poly8x16x2_t,Zip vectors -FALSE,vzipq_s16,"a: int16x8_t, b: int16x8_t",int16x8x2_t,Zip vectors -FALSE,vzipq_s32,"a: int32x4_t, b: int32x4_t",int32x4x2_t,Zip vectors -FALSE,vzipq_s8,"a: int8x16_t, b: int8x16_t",int8x16x2_t,Zip vectors -FALSE,vzipq_u16,"a: uint16x8_t, b: uint16x8_t",uint16x8x2_t,Zip vectors -FALSE,vzipq_u32,"a: uint32x4_t, b: uint32x4_t",uint32x4x2_t,Zip vectors -FALSE,vzipq_u8,"a: uint8x16_t, b: uint8x16_t",uint8x16x2_t,Zip vectors \ No newline at end of file diff --git a/library/stdarch/crates/intrinsic-test/src/acle_csv_parser.rs b/library/stdarch/crates/intrinsic-test/src/acle_csv_parser.rs new file mode 100644 index 0000000000..f2179ff1d6 --- /dev/null +++ b/library/stdarch/crates/intrinsic-test/src/acle_csv_parser.rs @@ -0,0 +1,313 @@ +use itertools::Itertools; +use regex::Regex; +use serde::Deserialize; + +use crate::argument::{Argument, ArgumentList, Constraint}; +use crate::intrinsic::Intrinsic; +use crate::types::{IntrinsicType, TypeKind}; + +pub fn get_acle_intrinsics(filename: &str) -> Vec { + let data = std::fs::read_to_string(filename).expect("Failed to open ACLE intrinsics file"); + + let data = data + .lines() + .filter_map(|l| { + (!(l.starts_with("") || l.is_empty() || l.starts_with("
"))) + .then(|| l.replace("
\t", "")) + }) + .join("\n"); + + let mut csv_reader = csv::ReaderBuilder::new() + .delimiter(b'\t') + .from_reader(data.as_bytes()); + + let mut intrinsics: Vec = csv_reader + .deserialize() + .filter_map(|x: Result| x.ok().map(|i| i.into())) + .collect::>(); + + // Intrinsics such as vshll_n_s8 exist twice in the ACLE with different constraints. + intrinsics.sort_by(|a, b| a.name.cmp(&b.name)); + let (intrinsics, duplicates) = intrinsics.partition_dedup_by(|a, b| a.name == b.name); + for duplicate in duplicates { + let name = &duplicate.name; + let constraints = duplicate + .arguments + .args + .drain(..) + .filter(|a| a.has_constraint()); + let intrinsic = intrinsics.iter_mut().find(|i| &i.name == name).unwrap(); + + for mut constraint in constraints { + let real_constraint = intrinsic + .arguments + .args + .iter_mut() + .find(|a| a.name == constraint.name) + .unwrap(); + real_constraint + .constraints + .push(constraint.constraints.pop().unwrap()); + } + } + + intrinsics.to_vec() +} + +impl Into for ACLEIntrinsicLine { + fn into(self) -> Intrinsic { + let signature = self.intrinsic; + let (ret_ty, remaining) = signature.split_once(' ').unwrap(); + + let results = type_from_c(ret_ty) + .unwrap_or_else(|_| panic!("Failed to parse return type: {}", ret_ty)); + + let (name, args) = remaining.split_once('(').unwrap(); + let args = args.trim_end_matches(')'); + + // Typo in ACLE data + let args = args.replace("int16x8q_t", "int16x8_t"); + + let arg_prep = self.argument_preparation.as_str(); + let args = args + .split(',') + .enumerate() + .map(move |(idx, arg)| { + let arg = arg.trim(); + if arg.starts_with("__builtin_constant_p") { + handle_constraint(idx, arg, arg_prep) + } else { + from_c(idx, arg) + } + }) + .collect(); + let arguments = ArgumentList { args }; + + Intrinsic { + name: name.to_string(), + arguments, + results, + } + } +} + +fn handle_constraint(idx: usize, arg: &str, prep: &str) -> Argument { + let prep = prep.replace(' ', ""); + + let name = arg + .trim_start_matches("__builtin_constant_p") + .trim_start_matches(|ref c| c == &' ' || c == &'(') + .trim_end_matches(')') + .to_string(); + + let ty = IntrinsicType::Type { + constant: true, + kind: TypeKind::Int, + bit_len: Some(32), + simd_len: None, + vec_len: None, + }; + + let constraints = prep + .split(';') + .find_map(|p| handle_range_constraint(&name, p).or_else(|| handle_eq_constraint(&name, p))) + .map(|c| vec![c]) + .unwrap_or_default(); + + Argument { + pos: idx, + name, + ty, + constraints, + } +} + +fn handle_range_constraint(name: &str, data: &str) -> Option { + lazy_static! { + static ref RANGE_CONSTRAINT: Regex = + Regex::new(r#"([0-9]+)<=([[:alnum:]]+)<=([0-9]+)"#).unwrap(); + } + + let captures = RANGE_CONSTRAINT.captures(data)?; + if captures.get(2).map(|c| c.as_str() == name).unwrap_or(false) { + match (captures.get(1), captures.get(3)) { + (Some(start), Some(end)) => { + let start = start.as_str().parse::().unwrap(); + let end = end.as_str().parse::().unwrap() + 1; + Some(Constraint::Range(start..end)) + } + _ => panic!("Invalid constraint"), + } + } else { + None + } +} + +fn handle_eq_constraint(name: &str, data: &str) -> Option { + lazy_static! { + static ref EQ_CONSTRAINT: Regex = Regex::new(r#"([[:alnum:]]+)==([0-9]+)"#).unwrap(); + } + let captures = EQ_CONSTRAINT.captures(data)?; + if captures.get(1).map(|c| c.as_str() == name).unwrap_or(false) { + captures + .get(2) + .map(|c| Constraint::Equal(c.as_str().parse::().unwrap())) + } else { + None + } +} + +fn from_c(pos: usize, s: &str) -> Argument { + let name_index = s + .chars() + .rev() + .take_while(|c| c != &'*' && c != &' ') + .count(); + + let name_start = s.len() - name_index; + let name = s[name_start..].to_string(); + let s = s[..name_start].trim(); + + Argument { + pos, + name, + ty: type_from_c(s).unwrap_or_else(|_| panic!("Failed to parse type: {}", s)), + constraints: vec![], + } +} + +fn type_from_c(s: &str) -> Result { + const CONST_STR: &str = "const "; + + if let Some(s) = s.strip_suffix('*') { + let (s, constant) = if s.ends_with(CONST_STR) { + (&s[..s.len() - (CONST_STR.len() + 1)], true) + } else { + (s, false) + }; + + let s = s.trim_end(); + + Ok(IntrinsicType::Ptr { + constant, + child: Box::new(type_from_c(s)?), + }) + } else { + // [const ]TYPE[{bitlen}[x{simdlen}[x{vec_len}]]][_t] + + let (mut s, constant) = if let Some(s) = s.strip_prefix(CONST_STR) { + (s, true) + } else { + (s, false) + }; + s = s.strip_suffix("_t").unwrap_or(s); + + let mut parts = s.split('x'); // [[{bitlen}], [{simdlen}], [{vec_len}] ] + + let start = parts.next().ok_or("Impossible to parse type")?; + + if let Some(digit_start) = start.find(|c: char| c.is_ascii_digit()) { + let (arg_kind, bit_len) = start.split_at(digit_start); + + let arg_kind = arg_kind.parse::()?; + let bit_len = bit_len.parse::().map_err(|err| err.to_string())?; + + let simd_len = parts.next().map(|part| part.parse::().ok()).flatten(); + let vec_len = parts.next().map(|part| part.parse::().ok()).flatten(); + + Ok(IntrinsicType::Type { + constant, + kind: arg_kind, + bit_len: Some(bit_len), + simd_len, + vec_len, + }) + } else { + Ok(IntrinsicType::Type { + constant, + kind: start.parse::()?, + bit_len: None, + simd_len: None, + vec_len: None, + }) + } + } +} + +#[derive(Deserialize, Debug, PartialEq, Clone)] +struct ACLEIntrinsicLine { + #[serde(rename = "Intrinsic")] + intrinsic: String, + #[serde(rename = "Argument preparation")] + argument_preparation: String, + #[serde(rename = "AArch64 Instruction")] + aarch64_instruction: String, + #[serde(rename = "Result")] + result: String, + #[serde(rename = "Supported architectures")] + supported_architectures: String, +} + +#[cfg(test)] +mod test { + use super::*; + use crate::argument::Argument; + use crate::types::{IntrinsicType, TypeKind}; + + #[test] + fn parse_simd() { + let expected = Argument { + pos: 0, + name: "a".into(), + ty: IntrinsicType::Type { + constant: false, + kind: TypeKind::Int, + bit_len: Some(32), + simd_len: Some(4), + vec_len: None, + }, + constraints: vec![], + }; + let actual = from_c(0, "int32x4_t a"); + assert_eq!(expected, actual); + } + + #[test] + fn parse_simd_with_vec() { + let expected = Argument { + pos: 0, + name: "a".into(), + ty: IntrinsicType::Type { + constant: false, + kind: TypeKind::Int, + bit_len: Some(32), + simd_len: Some(4), + vec_len: Some(2), + }, + constraints: vec![], + }; + let actual = from_c(0, "int32x4x2_t a"); + assert_eq!(expected, actual); + } + + #[test] + fn test_ptr() { + let expected = Argument { + pos: 0, + name: "ptr".into(), + ty: crate::types::IntrinsicType::Ptr { + constant: true, + child: Box::new(IntrinsicType::Type { + constant: false, + kind: TypeKind::Int, + bit_len: Some(8), + simd_len: None, + vec_len: None, + }), + }, + constraints: vec![], + }; + let actual = from_c(0, "int8_t const *ptr"); + assert_eq!(expected, actual); + } +} diff --git a/library/stdarch/crates/intrinsic-test/src/argument.rs b/library/stdarch/crates/intrinsic-test/src/argument.rs index 96ed440ee7..9b02970f3f 100644 --- a/library/stdarch/crates/intrinsic-test/src/argument.rs +++ b/library/stdarch/crates/intrinsic-test/src/argument.rs @@ -1,4 +1,4 @@ -use serde::{Deserialize, Deserializer}; +use std::ops::Range; use crate::types::IntrinsicType; use crate::Language; @@ -12,18 +12,26 @@ pub struct Argument { pub name: String, /// The type of the argument. pub ty: IntrinsicType, + /// Any constraints that are on this argument + pub constraints: Vec, } -impl Argument { - /// Creates an argument from a Rust style signature i.e. `name: type` - fn from_rust(pos: usize, arg: &str) -> Result { - let mut parts = arg.split(':'); - let name = parts.next().unwrap().trim().to_string(); - let ty = IntrinsicType::from_rust(parts.next().unwrap().trim())?; +#[derive(Debug, PartialEq, Clone)] +pub enum Constraint { + Equal(i64), + Range(Range), +} - Ok(Self { pos, name, ty }) +impl Constraint { + pub fn to_range(&self) -> Range { + match self { + Constraint::Equal(eq) => *eq..*eq + 1, + Constraint::Range(range) => range.clone(), + } } +} +impl Argument { fn to_c_type(&self) -> String { self.ty.c_type() } @@ -35,6 +43,10 @@ impl Argument { pub fn is_ptr(&self) -> bool { self.ty.is_ptr() } + + pub fn has_constraint(&self) -> bool { + !self.constraints.is_empty() + } } #[derive(Debug, PartialEq, Clone)] @@ -43,19 +55,6 @@ pub struct ArgumentList { } impl ArgumentList { - /// Creates an argument list from a Rust function signature, the data for - /// this function should only be the arguments. - /// e.g. for `fn test(a: u32, b: u32) -> u32` data should just be `a: u32, b: u32` - fn from_rust_arguments(data: &str) -> Result { - let args = data - .split(',') - .enumerate() - .map(|(idx, arg)| Argument::from_rust(idx, arg)) - .collect::>()?; - - Ok(Self { args }) - } - /// Converts the argument list into the call paramters for a C function call. /// e.g. this would generate something like `a, &b, c` pub fn as_call_param_c(&self) -> String { @@ -76,6 +75,16 @@ impl ArgumentList { pub fn as_call_param_rust(&self) -> String { self.args .iter() + .filter(|a| !a.has_constraint()) + .map(|arg| arg.name.clone()) + .collect::>() + .join(", ") + } + + pub fn as_constraint_parameters_rust(&self) -> String { + self.args + .iter() + .filter(|a| a.has_constraint()) .map(|arg| arg.name.clone()) .collect::>() .join(", ") @@ -85,13 +94,15 @@ impl ArgumentList { /// e.g. `int32x2_t a = { 0x1, 0x2 };` pub fn init_random_values_c(&self, pass: usize) -> String { self.iter() - .map(|arg| { - format!( - "{ty} {name} = {{ {values} }};", - ty = arg.to_c_type(), - name = arg.name, - values = arg.ty.populate_random(pass, &Language::C) - ) + .filter_map(|arg| { + (!arg.has_constraint()).then(|| { + format!( + "{ty} {name} = {{ {values} }};", + ty = arg.to_c_type(), + name = arg.name, + values = arg.ty.populate_random(pass, &Language::C) + ) + }) }) .collect::>() .join("\n ") @@ -101,20 +112,22 @@ impl ArgumentList { /// e.g. `let a = transmute([0x1, 0x2]);` pub fn init_random_values_rust(&self, pass: usize) -> String { self.iter() - .map(|arg| { - if arg.is_simd() { - format!( - "let {name} = ::std::mem::transmute([{values}]);", - name = arg.name, - values = arg.ty.populate_random(pass, &Language::Rust), - ) - } else { - format!( - "let {name} = {value};", - name = arg.name, - value = arg.ty.populate_random(pass, &Language::Rust) - ) - } + .filter_map(|arg| { + (!arg.has_constraint()).then(|| { + if arg.is_simd() { + format!( + "let {name} = ::std::mem::transmute([{values}]);", + name = arg.name, + values = arg.ty.populate_random(pass, &Language::Rust), + ) + } else { + format!( + "let {name} = {value};", + name = arg.name, + value = arg.ty.populate_random(pass, &Language::Rust) + ) + } + }) }) .collect::>() .join("\n ") @@ -124,14 +137,3 @@ impl ArgumentList { self.args.iter() } } - -impl<'de> Deserialize<'de> for ArgumentList { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - use serde::de::Error; - let s = String::deserialize(deserializer)?; - Self::from_rust_arguments(&s).map_err(Error::custom) - } -} diff --git a/library/stdarch/crates/intrinsic-test/src/intrinsic.rs b/library/stdarch/crates/intrinsic-test/src/intrinsic.rs index 499cf7612c..447c6db0bc 100644 --- a/library/stdarch/crates/intrinsic-test/src/intrinsic.rs +++ b/library/stdarch/crates/intrinsic-test/src/intrinsic.rs @@ -1,33 +1,47 @@ use crate::types::{IntrinsicType, TypeKind}; use super::argument::ArgumentList; -use serde::de::Unexpected; -use serde::{de, Deserialize, Deserializer}; /// An intrinsic -#[derive(Deserialize, Debug, PartialEq, Clone)] +#[derive(Debug, PartialEq, Clone)] pub struct Intrinsic { - /// If the intrinsic should be tested. - #[serde(deserialize_with = "bool_from_string")] - pub enabled: bool, - /// The function name of this intrinsic. pub name: String, /// Any arguments for this intrinsinc. - #[serde(rename = "args")] pub arguments: ArgumentList, /// The return type of this intrinsic. - #[serde(rename = "return")] pub results: IntrinsicType, } impl Intrinsic { /// Generates a std::cout for the intrinsics results that will match the /// rust debug output format for the return type. - pub fn print_result_c(&self, index: usize) -> String { - let lanes = if self.results.num_lanes() > 1 { + pub fn print_result_c(&self, index: usize, additional: &str) -> String { + let lanes = if self.results.num_vectors() > 1 { + (0..self.results.num_vectors()) + .map(|vector| { + format!( + r#""{ty}(" << {lanes} << ")""#, + ty = self.results.c_single_vector_type(), + lanes = (0..self.results.num_lanes()) + .map(move |idx| -> std::string::String { + format!( + "{cast}{lane_fn}(__return_value.val[{vector}], {lane})", + cast = self.results.c_promotion(), + lane_fn = self.results.get_lane_function(), + lane = idx, + vector = vector, + ) + }) + .collect::>() + .join(r#" << ", " << "#) + ) + }) + .collect::>() + .join(r#" << ", " << "#) + } else if self.results.num_lanes() > 1 { (0..self.results.num_lanes()) .map(|idx| -> std::string::String { format!( @@ -55,7 +69,7 @@ impl Intrinsic { }; format!( - r#"std::cout << "Result {idx}: {ty}" << std::fixed << std::setprecision(150) << {lanes} << "{close}" << std::endl;"#, + r#"std::cout << "Result {additional}-{idx}: {ty}" << std::fixed << std::setprecision(150) << {lanes} << "{close}" << std::endl;"#, ty = if self.results.is_simd() { format!("{}(", self.results.c_type()) } else { @@ -63,26 +77,36 @@ impl Intrinsic { }, close = if self.results.is_simd() { ")" } else { "" }, lanes = lanes, + additional = additional, idx = index, ) } - pub fn generate_pass_rust(&self, index: usize) -> String { + pub fn generate_pass_rust(&self, index: usize, additional: &str) -> String { + let constraints = self.arguments.as_constraint_parameters_rust(); + let constraints = if !constraints.is_empty() { + format!("::<{}>", constraints) + } else { + constraints + }; + format!( r#" unsafe {{ {initialized_args} - let res = {intrinsic_call}({args}); - println!("Result {idx}: {{:.150?}}", res); + let res = {intrinsic_call}{const}({args}); + println!("Result {additional}-{idx}: {{:.150?}}", res); }}"#, initialized_args = self.arguments.init_random_values_rust(index), intrinsic_call = self.name, args = self.arguments.as_call_param_rust(), + additional = additional, idx = index, + const = constraints, ) } - pub fn generate_pass_c(&self, index: usize) -> String { + pub fn generate_pass_c(&self, index: usize, additional: &str) -> String { format!( r#" {{ {initialized_args} @@ -92,21 +116,7 @@ impl Intrinsic { initialized_args = self.arguments.init_random_values_c(index), intrinsic_call = self.name, args = self.arguments.as_call_param_c(), - print_result = self.print_result_c(index) + print_result = self.print_result_c(index, additional) ) } } - -fn bool_from_string<'de, D>(deserializer: D) -> Result -where - D: Deserializer<'de>, -{ - match String::deserialize(deserializer)?.to_uppercase().as_ref() { - "TRUE" => Ok(true), - "FALSE" => Ok(false), - other => Err(de::Error::invalid_value( - Unexpected::Str(other), - &"TRUE or FALSE", - )), - } -} diff --git a/library/stdarch/crates/intrinsic-test/src/main.rs b/library/stdarch/crates/intrinsic-test/src/main.rs index c5ff2b5487..9416456419 100644 --- a/library/stdarch/crates/intrinsic-test/src/main.rs +++ b/library/stdarch/crates/intrinsic-test/src/main.rs @@ -1,3 +1,4 @@ +#![feature(slice_partition_dedup)] #[macro_use] extern crate lazy_static; #[macro_use] @@ -9,9 +10,14 @@ use std::process::Command; use clap::{App, Arg}; use intrinsic::Intrinsic; +use itertools::Itertools; use rayon::prelude::*; use types::TypeKind; +use crate::acle_csv_parser::get_acle_intrinsics; +use crate::argument::Argument; + +mod acle_csv_parser; mod argument; mod intrinsic; mod types; @@ -23,7 +29,43 @@ pub enum Language { C, } +fn gen_code_c(intrinsic: &Intrinsic, constraints: &[&Argument], name: String) -> String { + if let Some((current, constraints)) = constraints.split_last() { + let range = current + .constraints + .iter() + .map(|c| c.to_range()) + .flat_map(|r| r.into_iter()); + + range + .map(|i| { + format!( + r#" {{ + {ty} {name} = {val}; +{pass} + }}"#, + name = current.name, + ty = current.ty.c_type(), + val = i, + pass = gen_code_c(intrinsic, constraints, format!("{}-{}", name, i)) + ) + }) + .collect() + } else { + (1..20) + .map(|idx| intrinsic.generate_pass_c(idx, &name)) + .collect::>() + .join("\n") + } +} + fn generate_c_program(header_files: &[&str], intrinsic: &Intrinsic) -> String { + let constraints = intrinsic + .arguments + .iter() + .filter(|i| i.has_constraint()) + .collect_vec(); + format!( r#"{header_files} #include @@ -57,29 +99,60 @@ int main(int argc, char **argv) {{ .map(|header| format!("#include <{}>", header)) .collect::>() .join("\n"), - passes = (1..20) - .map(|idx| intrinsic.generate_pass_c(idx)) - .collect::>() - .join("\n"), + passes = gen_code_c(intrinsic, constraints.as_slice(), Default::default()), ) } +fn gen_code_rust(intrinsic: &Intrinsic, constraints: &[&Argument], name: String) -> String { + if let Some((current, constraints)) = constraints.split_last() { + let range = current + .constraints + .iter() + .map(|c| c.to_range()) + .flat_map(|r| r.into_iter()); + + range + .map(|i| { + format!( + r#" {{ + const {name}: {ty} = {val}; +{pass} + }}"#, + name = current.name, + ty = current.ty.rust_type(), + val = i, + pass = gen_code_rust(intrinsic, constraints, format!("{}-{}", name, i)) + ) + }) + .collect() + } else { + (1..20) + .map(|idx| intrinsic.generate_pass_rust(idx, &name)) + .collect::>() + .join("\n") + } +} + fn generate_rust_program(intrinsic: &Intrinsic) -> String { + let constraints = intrinsic + .arguments + .iter() + .filter(|i| i.has_constraint()) + .collect_vec(); + format!( r#"#![feature(simd_ffi)] #![feature(link_llvm_intrinsics)] #![feature(stdsimd)] #![allow(overflowing_literals)] +#![allow(non_upper_case_globals)] use core_arch::arch::aarch64::*; fn main() {{ {passes} }} "#, - passes = (1..20) - .map(|idx| intrinsic.generate_pass_rust(idx)) - .collect::>() - .join("\n"), + passes = gen_code_rust(intrinsic, &constraints, Default::default()) ) } @@ -91,7 +164,7 @@ fn compile_c(c_filename: &str, intrinsic: &Intrinsic, compiler: &str) -> bool { .arg(format!( "{cpp} {cppflags} {arch_flags} -Wno-narrowing -O2 -target {target} -o c_programs/{intrinsic} {filename}", target = "aarch64-unknown-linux-gnu", - arch_flags = "-march=armv8-a+crypto+crc", + arch_flags = "-march=armv8.6-a+crypto+sha3+crc+dotprod", filename = c_filename, intrinsic = intrinsic.name, cpp = compiler, @@ -238,6 +311,12 @@ fn main() { .long("runner") .help("Run the C programs under emulation with this command"), ) + .arg( + Arg::with_name("SKIP") + .takes_value(true) + .long("skip") + .help("Filename for a list of intrinsics to skip (one per line)"), + ) .get_matches(); let filename = matches.value_of("INPUT").unwrap(); @@ -247,54 +326,32 @@ fn main() { let cpp_compiler = matches.value_of("CPPCOMPILER").unwrap(); let c_runner = matches.value_of("RUNNER").unwrap_or(""); - let mut csv_reader = csv::Reader::from_reader(std::fs::File::open(filename).unwrap()); - - let mut intrinsics = csv_reader - .deserialize() - .filter_map(|x| -> Option { - debug!("Processing {:#?}", x); - match x { - Ok(a) => Some(a), - e => { - error!("{:#?}", e); - None - } - } - }) - // Only perform the test for intrinsics that are enabled... - .filter(|i| i.enabled) + let skip = if let Some(filename) = matches.value_of("SKIP") { + let data = std::fs::read_to_string(&filename).expect("Failed to open file"); + data.lines().map(String::from).collect_vec() + } else { + Default::default() + }; + + let intrinsics = get_acle_intrinsics(filename); + + let mut intrinsics = intrinsics + .into_iter() // Not sure how we would compare intrinsic that returns void. .filter(|i| i.results.kind() != TypeKind::Void) .filter(|i| i.results.kind() != TypeKind::BFloat) .filter(|i| !(i.results.kind() == TypeKind::Float && i.results.inner_size() == 16)) + .filter(|i| !i.arguments.iter().any(|a| a.ty.kind() == TypeKind::BFloat)) .filter(|i| { - i.arguments - .iter() - .find(|a| a.ty.kind() == TypeKind::BFloat) - .is_none() - }) - .filter(|i| { - i.arguments + !i.arguments .iter() - .find(|a| a.ty.kind() == TypeKind::Float && a.ty.inner_size() == 16) - .is_none() + .any(|a| a.ty.kind() == TypeKind::Float && a.ty.inner_size() == 16) }) // Skip pointers for now, we would probably need to look at the return // type to work out how many elements we need to point to. - .filter(|i| i.arguments.iter().find(|a| a.is_ptr()).is_none()) - // intrinsics with a lane parameter have constraints, deal with them later. - .filter(|i| { - i.arguments - .iter() - .find(|a| a.name.starts_with("lane")) - .is_none() - }) - .filter(|i| i.arguments.iter().find(|a| a.name == "n").is_none()) - // clang-12 fails to compile this intrinsic due to an error. - // fatal error: error in backend: Cannot select: 0x2b99c30: i64 = AArch64ISD::VSHL Constant:i64<1>, Constant:i32<1> - // 0x2b9a520: i64 = Constant<1> - // 0x2b9a248: i32 = Constant<1> - .filter(|i| !["vshld_s64", "vshld_u64"].contains(&i.name.as_str())) + .filter(|i| !i.arguments.iter().any(|a| a.is_ptr())) + .filter(|i| !i.arguments.iter().any(|a| a.ty.inner_size() == 128)) + .filter(|i| !skip.contains(&i.name)) .collect::>(); intrinsics.dedup(); diff --git a/library/stdarch/crates/intrinsic-test/src/types.rs b/library/stdarch/crates/intrinsic-test/src/types.rs index cc5b68973b..89c9c95d5b 100644 --- a/library/stdarch/crates/intrinsic-test/src/types.rs +++ b/library/stdarch/crates/intrinsic-test/src/types.rs @@ -1,5 +1,3 @@ -use regex::Regex; -use serde::{Deserialize, Deserializer}; use std::fmt; use std::str::FromStr; @@ -131,6 +129,16 @@ impl IntrinsicType { } } + pub fn num_vectors(&self) -> u32 { + match *self { + IntrinsicType::Ptr { ref child, .. } => child.num_vectors(), + IntrinsicType::Type { + vec_len: Some(vl), .. + } => vl, + _ => 1, + } + } + /// Determine if the type is a simd type, this will treat a type such as /// `uint64x1` as simd. pub fn is_simd(&self) -> bool { @@ -152,107 +160,6 @@ impl IntrinsicType { } } - pub fn from_rust(ty: &str) -> Result { - lazy_static! { - static ref SIMD_TYPE: Regex = Regex::new(r#"([a-z]*)([0-9]*)x([0-9]*)_t"#).unwrap(); - static ref MULTI_SIMD_TYPE: Regex = - Regex::new(r#"([a-z]*)([0-9]*)x([0-9]*)x([0-9]*)_t"#).unwrap(); - static ref RUST_TYPE: Regex = Regex::new(r#"([iuf]|float|poly)([0-9]+)"#).unwrap(); - } - - debug!("Parsing type: {}", ty); - - if let Some(ty) = ty.strip_prefix('*') { - let (constant, ty) = if let Some(ty) = ty.strip_prefix("const") { - (true, ty.trim()) - } else if let Some(ty) = ty.strip_prefix("mut") { - (false, ty.trim()) - } else { - (false, ty) - }; - return Ok(Self::Ptr { - constant, - child: Box::new(Self::from_rust(ty)?), - }); - } - - let (constant, ty) = if let Some(ty) = ty.strip_prefix("const") { - (true, ty.trim()) - } else { - (false, ty) - }; - - if let Some(captures) = MULTI_SIMD_TYPE.captures(ty) { - let kind = captures - .get(1) - .map(|s| s.as_str().parse::().unwrap()) - .unwrap(); - let bit_len = captures.get(2).map(|s| s.as_str().parse::().unwrap()); - let simd_len = captures.get(3).map(|s| s.as_str().parse::().unwrap()); - let vec_len = captures.get(4).map(|s| s.as_str().parse::().unwrap()); - Ok(Self::Type { - constant, - kind, - bit_len, - simd_len, - vec_len, - }) - } else if let Some(captures) = SIMD_TYPE.captures(ty) { - let kind = captures - .get(1) - .map(|s| s.as_str().parse::().unwrap()) - .unwrap(); - let bit_len = captures.get(2).map(|s| s.as_str().parse::().unwrap()); - let simd_len = captures.get(3).map(|s| s.as_str().parse::().unwrap()); - - Ok(Self::Type { - constant, - kind, - bit_len, - simd_len, - vec_len: None, - }) - } else if let Some(captures) = RUST_TYPE.captures(ty) { - let kind = captures - .get(1) - .map(|s| match s.as_str() { - "i" => TypeKind::Int, - "u" => TypeKind::UInt, - "f" => TypeKind::Float, - "float" => TypeKind::Float, - "poly" => TypeKind::Poly, - a => panic!("Unexpected type: {} found", a), - }) - .unwrap(); - let bit_len = captures.get(2).map(|s| s.as_str().parse::().unwrap()); - Ok(Self::Type { - constant, - kind, - bit_len, - simd_len: None, - vec_len: None, - }) - } else { - match ty { - "int" => Ok(Self::Type { - constant, - kind: TypeKind::Int, - bit_len: Some(32), - simd_len: None, - vec_len: None, - }), - "void" => Ok(Self::Type { - constant: false, - kind: TypeKind::Void, - bit_len: None, - simd_len: None, - vec_len: None, - }), - _ => Err(format!("Failed to parse type: {}", ty)), - } - } - } - #[allow(unused)] fn c_scalar_type(&self) -> String { format!( @@ -305,6 +212,48 @@ impl IntrinsicType { } } + pub fn c_single_vector_type(&self) -> String { + match self { + IntrinsicType::Ptr { child, .. } => child.c_single_vector_type(), + IntrinsicType::Type { + kind, + bit_len: Some(bit_len), + simd_len: Some(simd_len), + vec_len: Some(_), + .. + } => format!("{}{}x{}_t", kind.c_prefix(), bit_len, simd_len), + _ => unreachable!("Shouldn't be called on this type"), + } + } + + pub fn rust_type(&self) -> String { + match self { + IntrinsicType::Ptr { child, .. } => child.c_type(), + IntrinsicType::Type { + kind, + bit_len: Some(bit_len), + simd_len: None, + vec_len: None, + .. + } => format!("{}{}", kind.rust_prefix(), bit_len), + IntrinsicType::Type { + kind, + bit_len: Some(bit_len), + simd_len: Some(simd_len), + vec_len: None, + .. + } => format!("{}{}x{}_t", kind.c_prefix(), bit_len, simd_len), + IntrinsicType::Type { + kind, + bit_len: Some(bit_len), + simd_len: Some(simd_len), + vec_len: Some(vec_len), + .. + } => format!("{}{}x{}x{}_t", kind.c_prefix(), bit_len, simd_len, vec_len), + _ => todo!("{:#?}", self), + } + } + /// Gets a cast for this type if needs promotion. /// This is required for 8 bit types due to printing as the 8 bit types use /// a char and when using that in `std::cout` it will print as a character, @@ -470,14 +419,3 @@ impl IntrinsicType { } } } - -impl<'de> Deserialize<'de> for IntrinsicType { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - use serde::de::Error; - let s = String::deserialize(deserializer)?; - Self::from_rust(&s).map_err(Error::custom) - } -} diff --git a/library/stdarch/crates/std_detect/src/detect/arch/arm.rs b/library/stdarch/crates/std_detect/src/detect/arch/arm.rs index d96514c844..9e7dda094f 100644 --- a/library/stdarch/crates/std_detect/src/detect/arch/arm.rs +++ b/library/stdarch/crates/std_detect/src/detect/arch/arm.rs @@ -22,4 +22,6 @@ features! { /// FEAT_AES (AES instructions) @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] sha2: "sha2"; /// FEAT_SHA1 & FEAT_SHA256 (SHA1 & SHA2-256 instructions) + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] i8mm: "i8mm"; + /// FEAT_I8MM } diff --git a/library/stdarch/crates/std_detect/src/detect/macros.rs b/library/stdarch/crates/std_detect/src/detect/macros.rs index a4af3d1c02..b83fe71c41 100644 --- a/library/stdarch/crates/std_detect/src/detect/macros.rs +++ b/library/stdarch/crates/std_detect/src/detect/macros.rs @@ -25,7 +25,7 @@ macro_rules! features { ($nort_feature) => { compile_error!( concat!( - stringify!(nort_feature), + stringify!($nort_feature), " feature cannot be detected at run-time" ) ) 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 388af2e304..ea5f595ec9 100644 --- a/library/stdarch/crates/std_detect/src/detect/os/x86.rs +++ b/library/stdarch/crates/std_detect/src/detect/os/x86.rs @@ -249,5 +249,25 @@ pub(crate) fn detect_features() -> cache::Initializer { } } + // Unfortunately, some Skylake chips erroneously report support for BMI1 and + // BMI2 without actual support. These chips don't support AVX, and it seems + // that all Intel chips with non-erroneous support BMI do (I didn't check + // other vendors), so we can disable these flags for chips that don't also + // report support for AVX. + // + // It's possible this will pessimize future chips that do support BMI and + // not AVX, but this seems minor compared to a hard crash you get when + // executing an unsupported instruction (to put it another way, it's safe + // for us to under-report CPU features, but not to over-report them). Still, + // to limit any impact this may have in the future, we only do this for + // Intel chips, as it's a bug only present in their chips. + // + // This bug is documented as `SKL052` in the errata section of this document: + // http://www.intel.com/content/dam/www/public/us/en/documents/specification-updates/desktop-6th-gen-core-family-spec-update.pdf + if vendor_id == *b"GenuineIntel" && !value.test(Feature::avx as u32) { + value.unset(Feature::bmi1 as u32); + value.unset(Feature::bmi2 as u32); + } + value } diff --git a/library/stdarch/crates/stdarch-gen/neon.spec b/library/stdarch/crates/stdarch-gen/neon.spec index a22dfe3dd4..729602f724 100644 --- a/library/stdarch/crates/stdarch-gen/neon.spec +++ b/library/stdarch/crates/stdarch-gen/neon.spec @@ -102,6 +102,20 @@ b = 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 validate 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F generate int*_t, uint*_t, int64x*_t, uint64x*_t +/// Three-way exclusive OR +name = veor3 +a = 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F +b = 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +c = 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +validate 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F +target = sha3 + +aarch64 = eor3 +link-aarch64 = llvm.aarch64.crypto.eor3s._EXT_ +generate int8x16_t, int16x8_t, int32x4_t, int64x2_t +link-aarch64 = llvm.aarch64.crypto.eor3u._EXT_ +generate uint8x16_t, uint16x8_t, uint32x4_t, uint64x2_t + //////////////////// // Absolute difference between the arguments //////////////////// @@ -140,6 +154,16 @@ link-arm = vabds._EXT_ link-aarch64 = fabd._EXT_ generate float*_t +/// Floating-point absolute difference +name = vabd +multi_fn = simd_extract, {vabd-in_ntt-noext, {vdup_n-in_ntt-noext, a}, {vdup_n-in_ntt-noext, b}}, 0 +a = 1.0 +b = 9.0 +validate 8.0 + +aarch64 = fabd +generate f32, f64 + //////////////////// // Absolute difference Long //////////////////// @@ -303,9 +327,28 @@ aarch64 = fcmeq generate float64x1_t:uint64x1_t, float64x2_t:uint64x2_t arm = vceq. -// we are missing float16x4_t:uint16x4_t, float16x8_t:uint16x8_t generate float32x2_t:uint32x2_t, float32x4_t:uint32x4_t +/// Compare bitwise equal +name = vceq +multi_fn = transmute, {vceq-in_ntt-noext, {transmute, a}, {transmute, b}} +a = 1 +b = 2 +validate 0 + +aarch64 = cmp +generate i64:u64, u64 + +/// Floating-point compare equal +name = vceq +multi_fn = simd_extract, {vceq-in_ntt-noext, {vdup_n-in_ntt-noext, a}, {vdup_n-in_ntt-noext, b}}, 0 +a = 1. +b = 2. +validate 0 + +aarch64 = fcmp +generate f32:u32, f64:u64 + /// Signed compare bitwise equal to zero name = vceqz fn = simd_eq @@ -336,6 +379,24 @@ validate TRUE, FALSE, FALSE, FALSE aarch64 = fcmeq generate float32x2_t:uint32x2_t, float32x4_t:uint32x4_t, float64x1_t:uint64x1_t, float64x2_t:uint64x2_t +/// Compare bitwise equal to zero +name = vceqz +multi_fn = transmute, {vceqz-in_ntt-noext, {transmute, a}} +a = 1 +validate 0 + +aarch64 = cmp +generate i64:u64, u64 + +/// Floating-point compare bitwise equal to zero +name = vceqz +multi_fn = simd_extract, {vceqz-in_ntt-noext, {vdup_n-in_ntt-noext, a}}, 0 +a = 1. +validate 0 + +aarch64 = fcmp +generate f32:u32, f64:u64 + /// Signed compare bitwise Test bits nonzero name = vtst multi_fn = simd_and, c:in_t, a, b @@ -368,6 +429,38 @@ generate uint64x*_t arm = vtst generate uint*_t +/// Compare bitwise test bits nonzero +name = vtst +multi_fn = transmute, {vtst-in_ntt-noext, {transmute, a}, {transmute, b}} +a = 0 +b = 0 +validate 0 + +aarch64 = tst +generate i64:i64:u64, u64 + +/// Signed saturating accumulate of unsigned value +name = vuqadd +out-suffix +a = 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4 +b = 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4 +validate 2, 4, 6, 8, 2, 4, 6, 8, 2, 4, 6, 8, 2, 4, 6, 8 + +aarch64 = suqadd +link-aarch64 = suqadd._EXT_ +generate i32:u32:i32, i64:u64:i64 + +/// Signed saturating accumulate of unsigned value +name = vuqadd +out-suffix +multi_fn = simd_extract, {vuqadd-out_ntt-noext, {vdup_n-out_ntt-noext, a}, {vdup_n-in_ntt-noext, b}}, 0 +a = 1 +b = 2 +validate 3 + +aarch64 = suqadd +generate i8:u8:i8, i16:u16:i16 + //////////////////// // Floating-point absolute value //////////////////// @@ -423,9 +516,28 @@ aarch64 = fcmgt generate float64x1_t:uint64x1_t, float64x2_t:uint64x2_t arm = vcgt.s -// we are missing float16x4_t:uint16x4_t, float16x8_t:uint16x8_t generate float32x2_t:uint32x2_t, float32x4_t:uint32x4_t +/// Compare greater than +name = vcgt +multi_fn = transmute, {vcgt-in_ntt-noext, {transmute, a}, {transmute, b}} +a = 1 +b = 2 +validate 0 + +aarch64 = cmp +generate i64:u64, u64 + +/// Floating-point compare greater than +name = vcgt +multi_fn = simd_extract, {vcgt-in_ntt-noext, {vdup_n-in_ntt-noext, a}, {vdup_n-in_ntt-noext, b}}, 0 +a = 1. +b = 2. +validate 0 + +aarch64 = fcmp +generate f32:u32, f64:u64 + //////////////////// // lesser then //////////////////// @@ -466,9 +578,28 @@ aarch64 = fcmgt generate float64x1_t:uint64x1_t, float64x2_t:uint64x2_t arm = vcgt.s -// we are missing float16x4_t:uint16x4_t, float16x8_t:uint16x8_t generate float32x2_t:uint32x2_t, float32x4_t:uint32x4_t +/// Compare less than +name = vclt +multi_fn = transmute, {vclt-in_ntt-noext, {transmute, a}, {transmute, b}} +a = 2 +b = 1 +validate 0 + +aarch64 = cmp +generate i64:u64, u64 + +/// Floating-point compare less than +name = vclt +multi_fn = simd_extract, {vclt-in_ntt-noext, {vdup_n-in_ntt-noext, a}, {vdup_n-in_ntt-noext, b}}, 0 +a = 2. +b = 1. +validate 0 + +aarch64 = fcmp +generate f32:u32, f64:u64 + //////////////////// // lesser then equals //////////////////// @@ -486,6 +617,26 @@ generate int64x1_t:uint64x1_t, int64x2_t:uint64x2_t arm = vcge.s generate int8x8_t:uint8x8_t, int8x16_t:uint8x16_t, int16x4_t:uint16x4_t, int16x8_t:uint16x8_t, int32x2_t:uint32x2_t, int32x4_t:uint32x4_t +/// Compare greater than or equal +name = vcge +multi_fn = transmute, {vcge-in_ntt-noext, {transmute, a}, {transmute, b}} +a = 1 +b = 2 +validate 0 + +aarch64 = cmp +generate i64:u64, u64 + +/// Floating-point compare greater than or equal +name = vcge +multi_fn = simd_extract, {vcge-in_ntt-noext, {vdup_n-in_ntt-noext, a}, {vdup_n-in_ntt-noext, b}}, 0 +a = 1. +b = 2. +validate 0 + +aarch64 = fcmp +generate f32:u32, f64:u64 + /// Compare unsigned less than or equal name = vcle fn = simd_le @@ -508,10 +659,29 @@ validate TRUE, TRUE, TRUE, TRUE, TRUE, TRUE aarch64 = fcmge generate float64x1_t:uint64x1_t, float64x2_t:uint64x2_t -// we are missing float16x4_t:uint16x4_t, float16x8_t:uint16x8_t arm = vcge.s generate float32x2_t:uint32x2_t, float32x4_t:uint32x4_t +/// Compare less than or equal +name = vcle +multi_fn = transmute, {vcle-in_ntt-noext, {transmute, a}, {transmute, b}} +a = 2 +b = 1 +validate 0 + +aarch64 = cmp +generate i64:u64, u64 + +/// Floating-point compare less than or equal +name = vcle +multi_fn = simd_extract, {vcle-in_ntt-noext, {vdup_n-in_ntt-noext, a}, {vdup_n-in_ntt-noext, b}}, 0 +a = 2. +b = 1. +validate 0 + +aarch64 = fcmp +generate f32:u32, f64:u64 + //////////////////// // greater then equals //////////////////// @@ -553,7 +723,6 @@ aarch64 = fcmge generate float64x1_t:uint64x1_t, float64x2_t:uint64x2_t arm = vcge.s -// we are missing float16x4_t:uint16x4_t, float16x8_t:uint16x8_t generate float32x2_t:uint32x2_t, float32x4_t:uint32x4_t /// Compare signed greater than or equal to zero @@ -576,6 +745,24 @@ validate FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE aarch64 = fcmge generate float32x2_t:uint32x2_t, float32x4_t:uint32x4_t, float64x1_t:uint64x1_t, float64x2_t:uint64x2_t +/// Compare signed greater than or equal to zero +name = vcgez +multi_fn = transmute, {vcgez-in_ntt-noext, {transmute, a}} +a = -1 +validate 0 + +aarch64 = eor +generate i64:u64 + +/// Floating-point compare greater than or equal to zero +name = vcgez +multi_fn = simd_extract, {vcgez-in_ntt-noext, {vdup_n-in_ntt-noext, a}}, 0 +a = -1. +validate 0 + +aarch64 = fcmp +generate f32:u32, f64:u64 + /// Compare signed greater than zero name = vcgtz fn = simd_gt @@ -596,6 +783,24 @@ validate FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE aarch64 = fcmgt generate float32x2_t:uint32x2_t, float32x4_t:uint32x4_t, float64x1_t:uint64x1_t, float64x2_t:uint64x2_t +/// Compare signed greater than zero +name = vcgtz +multi_fn = transmute, {vcgtz-in_ntt-noext, {transmute, a}} +a = -1 +validate 0 + +aarch64 = cmp +generate i64:u64 + +/// Floating-point compare greater than zero +name = vcgtz +multi_fn = simd_extract, {vcgtz-in_ntt-noext, {vdup_n-in_ntt-noext, a}}, 0 +a = -1. +validate 0 + +aarch64 = fcmp +generate f32:u32, f64:u64 + /// Compare signed less than or equal to zero name = vclez fn = simd_le @@ -616,6 +821,24 @@ validate TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE aarch64 = fcmle generate float32x2_t:uint32x2_t, float32x4_t:uint32x4_t, float64x1_t:uint64x1_t, float64x2_t:uint64x2_t +/// Compare less than or equal to zero +name = vclez +multi_fn = transmute, {vclez-in_ntt-noext, {transmute, a}} +a = 2 +validate 0 + +aarch64 = cmp +generate i64:u64 + +/// Floating-point compare less than or equal to zero +name = vclez +multi_fn = simd_extract, {vclez-in_ntt-noext, {vdup_n-in_ntt-noext, a}}, 0 +a = 2. +validate 0 + +aarch64 = fcmp +generate f32:u32, f64:u64 + /// Compare signed less than zero name = vcltz fn = simd_lt @@ -636,6 +859,24 @@ validate TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE aarch64 = fcmlt generate float32x2_t:uint32x2_t, float32x4_t:uint32x4_t, float64x1_t:uint64x1_t, float64x2_t:uint64x2_t +/// Compare less than zero +name = vcltz +multi_fn = transmute, {vcltz-in_ntt-noext, {transmute, a}} +a = 2 +validate 0 + +aarch64 = asr +generate i64:u64 + +/// Floating-point compare less than zero +name = vcltz +multi_fn = simd_extract, {vcltz-in_ntt-noext, {vdup_n-in_ntt-noext, a}}, 0 +a = 2. +validate 0 + +aarch64 = fcmp +generate f32:u32, f64:u64 + /// Count leading sign bits name = vcls a = MIN, -1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, MAX @@ -647,7 +888,17 @@ link-arm = vcls._EXT_ link-aarch64 = cls._EXT_ generate int*_t -/// Signed count leading sign bits +/// Count leading sign bits +name = vcls +multi_fn = transmute, {vcls-signed-noext, {transmute, a}} +a = MIN, MAX, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, MAX +validate BITS_M1, BITS_M1, BITS_M1, BITS_M1, BITS_M1, BITS_M1, BITS_M1, BITS_M1, BITS_M1, BITS_M1, BITS_M1, BITS_M1, BITS_M1, BITS_M1, BITS_M1, BITS_M1 + +arm = vcls +aarch64 = cls +generate uint*_t + +/// Count leading zero bits name = vclz multi_fn = self-signed-ext, a a = MIN, -1, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, MAX @@ -657,7 +908,7 @@ arm = vclz. aarch64 = clz generate int*_t -/// Unsigned count leading sign bits +/// Count leading zero bits name = vclz multi_fn = transmute, {self-signed-ext, transmute(a)} a = MIN, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, MAX @@ -671,11 +922,11 @@ generate uint*_t name = vcagt a = -1.2, 0.0, 1.2, 2.3, 3.4, 4.5, 5.6, 6.7 b = -1.1, 0.0, 1.1, 2.4, 3.3, 4.6, 5.5, 6.8 -validate TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE +validate !0, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE aarch64 = facgt link-aarch64 = facgt._EXT2_._EXT_ -generate float64x1_t:uint64x1_t, float64x2_t:uint64x2_t +generate float64x1_t:uint64x1_t, float64x2_t:uint64x2_t, f32:u32, f64:u64 arm = vacgt.s link-arm = vacgt._EXT2_._EXT_ @@ -685,11 +936,11 @@ generate float32x2_t:uint32x2_t, float32x4_t:uint32x4_t name = vcage a = -1.2, 0.0, 1.2, 2.3, 3.4, 4.5, 5.6, 6.7 b = -1.1, 0.0, 1.1, 2.4, 3.3, 4.6, 5.5, 6.8 -validate TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE +validate !0, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE aarch64 = facge link-aarch64 = facge._EXT2_._EXT_ -generate float64x1_t:uint64x1_t, float64x2_t:uint64x2_t +generate float64x1_t:uint64x1_t, float64x2_t:uint64x2_t, f32:u32, f64:u64 arm = vacge.s link-arm = vacge._EXT2_._EXT_ @@ -700,10 +951,10 @@ name = vcalt multi_fn = vcagt-self-noext, b, a a = -1.2, 0.0, 1.2, 2.3, 3.4, 4.5, 5.6, 6.7 b = -1.1, 0.0, 1.1, 2.4, 3.3, 4.6, 5.5, 6.8 -validate FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE +validate 0, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE aarch64 = facgt -generate float64x1_t:uint64x1_t, float64x2_t:uint64x2_t +generate float64x1_t:uint64x1_t, float64x2_t:uint64x2_t, f32:u32, f64:u64 arm = vacgt.s generate float32x2_t:uint32x2_t, float32x4_t:uint32x4_t @@ -713,10 +964,10 @@ name = vcale multi_fn = vcage-self-noext , b, a a = -1.2, 0.0, 1.2, 2.3, 3.4, 4.5, 5.6, 6.7 b = -1.1, 0.0, 1.1, 2.4, 3.3, 4.6, 5.5, 6.8 -validate FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE +validate 0, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE aarch64 = facge -generate float64x1_t:uint64x1_t, float64x2_t:uint64x2_t +generate float64x1_t:uint64x1_t, float64x2_t:uint64x2_t, f32:u32, f64:u64 arm = vacge.s generate float32x2_t:uint32x2_t, float32x4_t:uint32x4_t @@ -848,8 +1099,8 @@ validate 1, 0, 0, 0, 0, 0, 0, 0 aarch64 = nop arm = nop -generate u64:int8x8_t, u64:int16x4_t: u64:int32x2_t, u64:int64x1_t -generate u64:uint8x8_t, u64:uint16x4_t: u64:uint32x2_t, u64:uint64x1_t +generate u64:int8x8_t, u64:int16x4_t, u64:int32x2_t, u64:int64x1_t +generate u64:uint8x8_t, u64:uint16x4_t, u64:uint32x2_t, u64:uint64x1_t generate u64:poly8x8_t, u64:poly16x4_t target = aes generate u64:poly64x1_t @@ -936,6 +1187,16 @@ aarch64 = fcvtxn link-aarch64 = fcvtxn._EXT2_._EXT_ generate float64x2_t:float32x2_t +/// Floating-point convert to lower precision narrow, rounding to odd +name = vcvtx +double-suffixes +multi_fn = simd_extract, {vcvtx-_f32_f64-noext, {vdupq_n-in_ntt-noext, a}}, 0 +a = -1.0 +validate -1.0 + +aarch64 = fcvtxn +generate f64:f32 + /// Floating-point convert to lower precision narrow, rounding to odd name = vcvtx_high noq-double-suffixes @@ -1795,6 +2056,15 @@ generate int64x*_t arm = vneg.s generate int*_t +/// Negate +name = vneg +multi_fn = -a +a = 1 +validate -1 + +aarch64 = neg +generate i64 + /// Negate name = vneg fn = simd_neg @@ -1820,6 +2090,15 @@ generate int64x*_t arm = vqneg.s generate int*_t +/// Signed saturating negate +name = vqneg +multi_fn = simd_extract, {vqneg-in_ntt-noext, {vdup_n-in_ntt-noext, a}}, 0 +a = 1 +validate -1 + +aarch64 = sqneg +generate i8, i16, i32, i64 + /// Saturating subtract name = vqsub a = 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42 @@ -1954,6 +2233,15 @@ arm = vrintn link-arm = vrintn._EXT_ generate float*_t +/// Floating-point round to integral, to nearest with ties to even +name = vrndn +a = -1.5 +validate -2.0 + +aarch64 = frintn +link-aarch64 = llvm.roundeven._EXT_ +generate f32 + /// Floating-point round to integral, toward minus infinity name = vrndm a = -1.5, 0.5, 1.5, 2.5 @@ -2082,10 +2370,9 @@ generate *const p16:poly16x4x2_t, *const p16:poly16x4x3_t, *const p16:poly16x4x4 generate *const p16:poly16x8x2_t, *const p16:poly16x8x3_t, *const p16:poly16x8x4_t target = aes generate *const p64:poly64x1x2_t -arm = ldr +arm = nop generate *const p64:poly64x1x3_t, *const p64:poly64x1x4_t generate *const p64:poly64x2x2_t, *const p64:poly64x2x3_t, *const p64:poly64x2x4_t - /// Load multiple single-element structures to one, two, three, or four registers name = vld1 out-suffix @@ -2122,13 +2409,19 @@ out-nox a = 0, 1, 2, 2, 3, 2, 4, 3, 5, 2, 6, 3, 7, 4, 8, 5, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15, 8, 16, 9, 17 validate 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 load_fn +arm-aarch64-separate aarch64 = ld2 link-aarch64 = ld2._EXTv2_ +generate *const i64:int64x2x2_t + arm = vld2 link-arm = vld2._EXTpi82_ -//generate *const i8:int8x8x2_t, *const i16:int16x4x2_t, *const i32:int32x2x2_t, *const i64:int64x1x2_t -//generate *const i8:int8x16x2_t, *const i16:int16x8x2_t, *const i32:int32x4x2_t, *const i64:int64x2x2_t +generate *const i8:int8x8x2_t, *const i16:int16x4x2_t, *const i32:int32x2x2_t +generate *const i8:int8x16x2_t, *const i16:int16x8x2_t, *const i32:int32x4x2_t +arm = nop +aarch64 = nop +generate *const i64:int64x1x2_t /// Load multiple 2-element structures to two registers name = vld2 @@ -2139,10 +2432,21 @@ validate 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5, 6, 7, 8, 9, load_fn aarch64 = ld2 +generate *const u64:uint64x2x2_t +target = aes +generate *const p64:poly64x2x2_t + +target = default arm = vld2 -//generate *const u8:uint8x8x2_t, *const u16:uint16x4x2_t, *const u32:uint32x2x2_t, *const u64:uint64x1x2_t -//generate *const u8:uint8x16x2_t, *const u16:uint16x8x2_t, *const u32:uint32x4x2_t, *const u64:uint64x2x2_t -//generate *const p8:poly8x8x2_t, *const p16:poly16x4x2_t, *const p8:poly8x16x2_t, *const p16:poly16x8x2_t +generate *const u8:uint8x8x2_t, *const u16:uint16x4x2_t, *const u32:uint32x2x2_t +generate *const u8:uint8x16x2_t, *const u16:uint16x8x2_t, *const u32:uint32x4x2_t +generate *const p8:poly8x8x2_t, *const p16:poly16x4x2_t, *const p8:poly8x16x2_t, *const p16:poly16x8x2_t +arm = nop +aarch64 = nop +generate *const u64:uint64x1x2_t +target = aes +generate *const p64:poly64x1x2_t + /// Load multiple 2-element structures to two registers name = vld2 @@ -2150,14 +2454,17 @@ out-nox a = 0., 1., 2., 2., 3., 2., 4., 3., 5., 2., 6., 3., 7., 4., 8., 5., 9. validate 1., 2., 2., 3., 2., 3., 4., 5., 2., 3., 4., 5., 6., 7., 8., 9. load_fn +arm-aarch64-separate -aarch64 = ld2 +aarch64 = nop link-aarch64 = ld2._EXTv2_ -//generate *const f64:float64x1x2_t, *const f64:float64x2x2_t +generate *const f64:float64x1x2_t +aarch64 = ld2 +generate *const f64:float64x2x2_t arm = vld2 link-arm = vld2._EXTpi82_ -//generate *const f32:float32x2x2_t, *const f32:float32x4x2_t +generate *const f32:float32x2x2_t, *const f32:float32x4x2_t /// Load single 2-element structure and replicate to all lanes of two registers name = vld2 @@ -2165,13 +2472,18 @@ out-dup-nox a = 0, 1, 1, 2, 3, 1, 4, 3, 5, 1, 6, 3, 7, 4, 8, 5, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15, 8, 16, 9, 17 validate 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 load_fn +arm-aarch64-separate -arm = vld2dup -link-arm = vld2dup._EXTpi82_ aarch64 = ld2r link-aarch64 = ld2r._EXT2_ -//generate *const i8:int8x8x2_t, *const i16:int16x4x2_t, *const i32:int32x2x2_t, *const i64:int64x1x2_t -//generate *const i8:int8x16x2_t, *const i16:int16x8x2_t, *const i32:int32x4x2_t, *const i64:int64x2x2_t +generate *const i64:int64x2x2_t + +arm = vld2 +link-arm = vld2dup._EXTpi82_ +generate *const i8:int8x8x2_t, *const i16:int16x4x2_t, *const i32:int32x2x2_t +generate *const i8:int8x16x2_t, *const i16:int16x8x2_t, *const i32:int32x4x2_t +arm = nop +generate *const i64:int64x1x2_t /// Load single 2-element structure and replicate to all lanes of two registers name = vld2 @@ -2181,11 +2493,20 @@ a = 0, 1, 1, 2, 3, 1, 4, 3, 5, 1, 6, 3, 7, 4, 8, 5, 9, 2, 10, 3, 11, 4, 12, 5, 1 validate 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 load_fn -arm = vld2dup aarch64 = ld2r -//generate *const u8:uint8x8x2_t, *const u16:uint16x4x2_t, *const u32:uint32x2x2_t, *const u64:uint64x1x2_t -//generate *const u8:uint8x16x2_t, *const u16:uint16x8x2_t, *const u32:uint32x4x2_t, *const u64:uint64x2x2_t -//generate *const p8:poly8x8x2_t, *const p16:poly16x4x2_t, *const p8:poly8x16x2_t, *const p16:poly16x8x2_t +generate *const u64:uint64x2x2_t +target = aes +generate *const p64:poly64x2x2_t + +target = default +arm = vld2 +generate *const u8:uint8x8x2_t, *const u16:uint16x4x2_t, *const u32:uint32x2x2_t +generate *const u8:uint8x16x2_t, *const u16:uint16x8x2_t, *const u32:uint32x4x2_t +generate *const p8:poly8x8x2_t, *const p16:poly16x4x2_t, *const p8:poly8x16x2_t, *const p16:poly16x8x2_t +arm = nop +generate *const u64:uint64x1x2_t +target = aes +generate *const p64:poly64x1x2_t /// Load single 2-element structure and replicate to all lanes of two registers name = vld2 @@ -2193,14 +2514,15 @@ out-dup-nox a = 0., 1., 1., 2., 3., 1., 4., 3., 5. validate 1., 1., 1., 1., 1., 1., 1., 1. load_fn +arm-aarch64-separate aarch64 = ld2r link-aarch64 = ld2r._EXT2_ -//generate *const f64:float64x1x2_t, *const f64:float64x2x2_t +generate *const f64:float64x1x2_t, *const f64:float64x2x2_t -arm = vld2dup +arm = vld2 link-arm = vld2dup._EXTpi82_ -//generate *const f32:float32x2x2_t, *const f32:float32x4x2_t +generate *const f32:float32x2x2_t, *const f32:float32x4x2_t /// Load multiple 2-element structures to two registers name = vld2 @@ -2214,16 +2536,16 @@ validate 1, 2, 2, 14, 2, 16, 17, 18, 2, 20, 21, 22, 23, 24, 25, 26, 2, 12, 13, 1 load_fn arm-aarch64-separate -aarch64 = ld2lane +aarch64 = ld2 const-aarch64 = LANE link-aarch64 = ld2lane._EXTpi82_ -//generate *const i64:int64x1x2_t:int64x1x2_t, *const i64:int64x2x2_t:int64x2x2_t +generate *const i8:int8x16x2_t:int8x16x2_t, *const i64:int64x1x2_t:int64x1x2_t, *const i64:int64x2x2_t:int64x2x2_t -arm = vld2lane +arm = vld2 const-arm = LANE link-arm = vld2lane._EXTpi82_ -//generate *const i8:int8x8x2_t:int8x8x2_t, *const i16:int16x4x2_t:int16x4x2_t, *const i32:int32x2x2_t:int32x2x2_t -//generate *const i8:int8x16x2_t:int8x16x2_t, *const i16:int16x8x2_t:int16x8x2_t, *const i32:int32x4x2_t:int32x4x2_t +generate *const i8:int8x8x2_t:int8x8x2_t, *const i16:int16x4x2_t:int16x4x2_t, *const i32:int32x2x2_t:int32x2x2_t +generate *const i16:int16x8x2_t:int16x8x2_t, *const i32:int32x4x2_t:int32x4x2_t /// Load multiple 2-element structures to two registers name = vld2 @@ -2236,23 +2558,23 @@ b = 0, 2, 2, 14, 2, 16, 17, 18, 2, 20, 21, 22, 23, 24, 25, 26, 11, 12, 13, 14, 1 n = 0 validate 1, 2, 2, 14, 2, 16, 17, 18, 2, 20, 21, 22, 23, 24, 25, 26, 2, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 load_fn -arm-aarch64-separate -aarch64 = ld2lane +aarch64 = ld2 const-aarch64 = LANE target = aes -//generate *const p64:poly64x1x2_t:poly64x1x2_t, *const p64:poly64x2x2_t:poly64x2x2_t +generate *const p64:poly64x1x2_t:poly64x1x2_t, *const p64:poly64x2x2_t:poly64x2x2_t target = default -//generate *const u64:uint64x1x2_t:uint64x1x2_t, *const u64:uint64x2x2_t:uint64x2x2_t +generate *const u8:uint8x16x2_t:uint8x16x2_t, *const u64:uint64x1x2_t:uint64x1x2_t, *const u64:uint64x2x2_t:uint64x2x2_t +generate *const p8:poly8x16x2_t:poly8x16x2_t -arm = vld2lane +arm = vld2 const-arm = LANE -//generate *const u8:uint8x8x2_t:uint8x8x2_t, *const u16:uint16x4x2_t:uint16x4x2_t, *const u32:uint32x2x2_t:uint32x2x2_t -//generate *const u8:uint8x16x2_t:uint8x16x2_t, *const u16:uint16x8x2_t:uint16x8x2_t, *const u32:uint32x4x2_t:uint32x4x2_t -//generate *const p8:poly8x8x2_t:poly8x8x2_t, *const p16:poly16x4x2_t:poly16x4x2_t -//generate *const p8:poly8x16x2_t:poly8x16x2_t, *const p16:poly16x8x2_t:poly16x8x2_t +generate *const u8:uint8x8x2_t:uint8x8x2_t, *const u16:uint16x4x2_t:uint16x4x2_t, *const u32:uint32x2x2_t:uint32x2x2_t +generate *const u16:uint16x8x2_t:uint16x8x2_t, *const u32:uint32x4x2_t:uint32x4x2_t +generate *const p8:poly8x8x2_t:poly8x8x2_t, *const p16:poly16x4x2_t:poly16x4x2_t +generate *const p16:poly16x8x2_t:poly16x8x2_t /// Load multiple 2-element structures to two registers name = vld2 @@ -2266,39 +2588,459 @@ validate 1., 2., 2., 14., 2., 16., 17., 18. load_fn arm-aarch64-separate -aarch64 = ld2lane +aarch64 = ld2 const-aarch64 = LANE link-aarch64 = ld2lane._EXTpi82_ -//generate *const f64:float64x1x2_t:float64x1x2_t, *const f64:float64x2x2_t:float64x2x2_t +generate *const f64:float64x1x2_t:float64x1x2_t, *const f64:float64x2x2_t:float64x2x2_t -arm = vld2lane +arm = vld2 const-arm = LANE link-arm = vld2lane._EXTpi82_ -//generate *const f32:float32x2x2_t:float32x2x2_t, *const f32:float32x4x2_t:float32x4x2_t +generate *const f32:float32x2x2_t:float32x2x2_t, *const f32:float32x4x2_t:float32x4x2_t -/// Store multiple single-element structures from one, two, three, or four registers -name = vst1 -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, 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 -validate 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, 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 -store_fn +/// Load multiple 3-element structures to three registers +name = vld3 +out-nox +a = 0, 1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8, 2, 13, 13, 4, 14, 14, 7, 15, 15, 8, 16, 16, 2, 25, 41, 4, 26, 42, 7, 27, 43, 8, 28, 44, 13, 29, 45, 14, 30, 46, 15, 31, 47, 16, 32, 48 +validate 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16, 25, 26, 27, 28, 29, 30, 31, 32, 2, 4, 7, 8, 13, 14, 15, 16, 41, 42, 43, 44, 45, 46, 47, 48 +load_fn arm-aarch64-separate -aarch64 = st1 -link-aarch64 = st1x2._EXT3_ -arm = vst1 -link-arm = vst1x2._EXTr3_ -generate *mut i8:int8x8x2_t:void, *mut i16:int16x4x2_t:void, *mut i32:int32x2x2_t:void, *mut i64:int64x1x2_t:void -generate *mut i8:int8x16x2_t:void, *mut i16:int16x8x2_t:void, *mut i32:int32x4x2_t:void, *mut i64:int64x2x2_t:void +aarch64 = ld3 +link-aarch64 = ld3._EXTv2_ +generate *const i64:int64x2x3_t -link-aarch64 = st1x3._EXT3_ -link-arm = vst1x3._EXTr3_ -generate *mut i8:int8x8x3_t:void, *mut i16:int16x4x3_t:void, *mut i32:int32x2x3_t:void, *mut i64:int64x1x3_t:void -generate *mut i8:int8x16x3_t:void, *mut i16:int16x8x3_t:void, *mut i32:int32x4x3_t:void, *mut i64:int64x2x3_t:void +arm = vld3 +link-arm = vld3._EXTpi82_ +generate *const i8:int8x8x3_t, *const i16:int16x4x3_t, *const i32:int32x2x3_t +generate *const i8:int8x16x3_t, *const i16:int16x8x3_t, *const i32:int32x4x3_t +arm = nop +aarch64 = nop +generate *const i64:int64x1x3_t -link-aarch64 = st1x4._EXT3_ -link-arm = vst1x4._EXTr3_ -generate *mut i8:int8x8x4_t:void, *mut i16:int16x4x4_t:void, *mut i32:int32x2x4_t:void, *mut i64:int64x1x4_t:void -generate *mut i8:int8x16x4_t:void, *mut i16:int16x8x4_t:void, *mut i32:int32x4x4_t:void, *mut i64:int64x2x4_t:void +/// Load multiple 3-element structures to three registers +name = vld3 +out-nox +multi_fn = transmute, {vld3-outsignednox-noext, transmute(a)} +a = 0, 1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8, 2, 13, 13, 4, 14, 14, 7, 15, 15, 8, 16, 16, 2, 25, 41, 4, 26, 42, 7, 27, 43, 8, 28, 44, 13, 29, 45, 14, 30, 46, 15, 31, 47, 16, 32, 48 +validate 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16, 25, 26, 27, 28, 29, 30, 31, 32, 2, 4, 7, 8, 13, 14, 15, 16, 41, 42, 43, 44, 45, 46, 47, 48 +load_fn + +aarch64 = ld3 +generate *const u64:uint64x2x3_t +target = aes +generate *const p64:poly64x2x3_t + +target = default +arm = vld3 +generate *const u8:uint8x8x3_t, *const u16:uint16x4x3_t, *const u32:uint32x2x3_t +generate *const u8:uint8x16x3_t, *const u16:uint16x8x3_t, *const u32:uint32x4x3_t +generate *const p8:poly8x8x3_t, *const p16:poly16x4x3_t, *const p8:poly8x16x3_t, *const p16:poly16x8x3_t +arm = nop +aarch64 = nop +generate *const u64:uint64x1x3_t +target = aes +generate *const p64:poly64x1x3_t + +/// Load multiple 3-element structures to three registers +name = vld3 +out-nox +a = 0., 1., 2., 2., 2., 4., 4., 2., 7., 7., 4., 8., 8. +validate 1., 2., 2., 4., 2., 4., 7., 8., 2., 4., 7., 8. +load_fn +arm-aarch64-separate + +aarch64 = nop +link-aarch64 = ld3._EXTv2_ +generate *const f64:float64x1x3_t +aarch64 = ld3 +generate *const f64:float64x2x3_t + +arm = vld3 +link-arm = vld3._EXTpi82_ +generate *const f32:float32x2x3_t, *const f32:float32x4x3_t + +/// Load single 3-element structure and replicate to all lanes of three registers +name = vld3 +out-dup-nox +a = 0, 1, 1, 1, 3, 1, 4, 3, 5, 1, 6, 3, 7, 4, 8, 5, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15, 8, 16, 9, 17, 6, 14, 7, 15, 8, 16, 9, 17, 6, 14, 7, 15, 8, 16, 9, 17 +validate 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +load_fn +arm-aarch64-separate + +aarch64 = ld3r +link-aarch64 = ld3r._EXT2_ +generate *const i64:int64x2x3_t + +arm = vld3 +link-arm = vld3dup._EXTpi82_ +generate *const i8:int8x8x3_t, *const i16:int16x4x3_t, *const i32:int32x2x3_t +generate *const i8:int8x16x3_t, *const i16:int16x8x3_t, *const i32:int32x4x3_t +arm = nop +generate *const i64:int64x1x3_t + +/// Load single 3-element structure and replicate to all lanes of three registers +name = vld3 +out-dup-nox +multi_fn = transmute, {vld3-outsigneddupnox-noext, transmute(a)} +a = 0, 1, 1, 1, 3, 1, 4, 3, 5, 1, 6, 3, 7, 4, 8, 5, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15, 8, 16, 9, 17, 6, 14, 7, 15, 8, 16, 9, 17, 6, 14, 7, 15, 8, 16, 9, 17 +validate 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +load_fn + +aarch64 = ld3r +generate *const u64:uint64x2x3_t +target = aes +generate *const p64:poly64x2x3_t + +target = default +arm = vld3 +generate *const u8:uint8x8x3_t, *const u16:uint16x4x3_t, *const u32:uint32x2x3_t +generate *const u8:uint8x16x3_t, *const u16:uint16x8x3_t, *const u32:uint32x4x3_t +generate *const p8:poly8x8x3_t, *const p16:poly16x4x3_t, *const p8:poly8x16x3_t, *const p16:poly16x8x3_t +arm = nop +generate *const u64:uint64x1x3_t +target = aes +generate *const p64:poly64x1x3_t + +/// Load single 3-element structure and replicate to all lanes of three registers +name = vld3 +out-dup-nox +a = 0., 1., 1., 1., 3., 1., 4., 3., 5., 1., 4., 3., 5. +validate 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1. +load_fn +arm-aarch64-separate + +aarch64 = ld3r +link-aarch64 = ld3r._EXT2_ +generate *const f64:float64x1x3_t, *const f64:float64x2x3_t + +arm = vld3 +link-arm = vld3dup._EXTpi82_ +generate *const f32:float32x2x3_t, *const f32:float32x4x3_t + +/// Load multiple 3-element structures to two registers +name = vld3 +out-lane-nox +multi_fn = static_assert_imm-in_exp_len-LANE +constn = LANE +a = 0, 1, 2, 2, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 +b = 0, 2, 2, 14, 2, 16, 17, 18, 2, 20, 21, 22, 23, 24, 25, 26, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 +n = 0 +validate 1, 2, 2, 14, 2, 16, 17, 18, 2, 20, 21, 22, 23, 24, 25, 26, 2, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 2, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 +load_fn +arm-aarch64-separate + +aarch64 = ld3 +const-aarch64 = LANE +link-aarch64 = ld3lane._EXTpi82_ +generate *const i8:int8x16x3_t:int8x16x3_t, *const i64:int64x1x3_t:int64x1x3_t, *const i64:int64x2x3_t:int64x2x3_t + +arm = vld3 +const-arm = LANE +link-arm = vld3lane._EXTpi82_ +generate *const i8:int8x8x3_t:int8x8x3_t, *const i16:int16x4x3_t:int16x4x3_t, *const i32:int32x2x3_t:int32x2x3_t +generate *const i16:int16x8x3_t:int16x8x3_t, *const i32:int32x4x3_t:int32x4x3_t + +/// Load multiple 3-element structures to three registers +name = vld3 +out-lane-nox +multi_fn = static_assert_imm-in_exp_len-LANE +multi_fn = transmute, {vld3-outsignedlanenox-::, transmute(a), transmute(b)} +constn = LANE +a = 0, 1, 2, 2, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 +b = 0, 2, 2, 14, 2, 16, 17, 18, 2, 20, 21, 22, 23, 24, 25, 26, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 +n = 0 +validate 1, 2, 2, 14, 2, 16, 17, 18, 2, 20, 21, 22, 23, 24, 25, 26, 2, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 2, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 +load_fn + +aarch64 = ld3 +const-aarch64 = LANE +target = aes +generate *const p64:poly64x1x3_t:poly64x1x3_t, *const p64:poly64x2x3_t:poly64x2x3_t +target = default +generate *const p8:poly8x16x3_t:poly8x16x3_t, *const u8:uint8x16x3_t:uint8x16x3_t, *const u64:uint64x1x3_t:uint64x1x3_t, *const u64:uint64x2x3_t:uint64x2x3_t + +arm = vld3 +const-arm = LANE +generate *const u8:uint8x8x3_t:uint8x8x3_t, *const u16:uint16x4x3_t:uint16x4x3_t, *const u32:uint32x2x3_t:uint32x2x3_t +generate *const u16:uint16x8x3_t:uint16x8x3_t, *const u32:uint32x4x3_t:uint32x4x3_t +generate *const p8:poly8x8x3_t:poly8x8x3_t, *const p16:poly16x4x3_t:poly16x4x3_t +generate *const p16:poly16x8x3_t:poly16x8x3_t + +/// Load multiple 3-element structures to three registers +name = vld3 +out-lane-nox +multi_fn = static_assert_imm-in_exp_len-LANE +constn = LANE +a = 0., 1., 2., 2., 4., 5., 6., 7., 8., 5., 6., 7., 8. +b = 0., 2., 2., 14., 9., 16., 17., 18., 5., 6., 7., 8. +n = 0 +validate 1., 2., 2., 14., 2., 16., 17., 18., 2., 6., 7., 8. +load_fn +arm-aarch64-separate + +aarch64 = ld3 +const-aarch64 = LANE +link-aarch64 = ld3lane._EXTpi82_ +generate *const f64:float64x1x3_t:float64x1x3_t, *const f64:float64x2x3_t:float64x2x3_t + +arm = vld3 +const-arm = LANE +link-arm = vld3lane._EXTpi82_ +generate *const f32:float32x2x3_t:float32x2x3_t, *const f32:float32x4x3_t:float32x4x3_t + +/// Load multiple 4-element structures to four registers +name = vld4 +out-nox +a = 0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48, 6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64 +validate 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48, 6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64 +load_fn +arm-aarch64-separate + +aarch64 = ld4 +link-aarch64 = ld4._EXTv2_ +generate *const i64:int64x2x4_t + +arm = vld4 +link-arm = vld4._EXTpi82_ +generate *const i8:int8x8x4_t, *const i16:int16x4x4_t, *const i32:int32x2x4_t +generate *const i8:int8x16x4_t, *const i16:int16x8x4_t, *const i32:int32x4x4_t +aarch64 = nop +arm = nop +generate *const i64:int64x1x4_t + +/// Load multiple 4-element structures to four registers +name = vld4 +out-nox +multi_fn = transmute, {vld4-outsignednox-noext, transmute(a)} +a = 0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48, 6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64 +validate 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48, 6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64 +load_fn + +aarch64 = ld4 +generate *const u64:uint64x2x4_t +target = aes +generate *const p64:poly64x2x4_t + +target = default +arm = vld4 +generate *const u8:uint8x8x4_t, *const u16:uint16x4x4_t, *const u32:uint32x2x4_t +generate *const u8:uint8x16x4_t, *const u16:uint16x8x4_t, *const u32:uint32x4x4_t +generate *const p8:poly8x8x4_t, *const p16:poly16x4x4_t, *const p8:poly8x16x4_t, *const p16:poly16x8x4_t +aarch64 = nop +arm = nop +generate *const u64:uint64x1x4_t +target = aes +generate *const p64:poly64x1x4_t + +/// Load multiple 4-element structures to four registers +name = vld4 +out-nox +a = 0., 1., 2., 2., 6., 2., 6., 6., 8., 2., 6., 6., 8., 6., 8., 15., 16. +validate 1., 2., 2., 6., 2., 6., 6., 8., 2., 6., 6., 15., 6., 8., 8., 16. +load_fn +arm-aarch64-separate + +aarch64 = nop +link-aarch64 = ld4._EXTv2_ +generate *const f64:float64x1x4_t +aarch64 = ld4 +generate *const f64:float64x2x4_t + +arm = vld4 +link-arm = vld4._EXTpi82_ +generate *const f32:float32x2x4_t, *const f32:float32x4x4_t + +/// Load single 4-element structure and replicate to all lanes of four registers +name = vld4 +out-dup-nox +a = 0, 1, 1, 1, 1, 2, 4, 3, 5, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9 +validate 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +load_fn +arm-aarch64-separate + +aarch64 = ld4r +link-aarch64 = ld4r._EXT2_ +generate *const i64:int64x2x4_t + +arm = vld4 +link-arm = vld4dup._EXTpi82_ +generate *const i8:int8x8x4_t, *const i16:int16x4x4_t, *const i32:int32x2x4_t +generate *const i8:int8x16x4_t, *const i16:int16x8x4_t, *const i32:int32x4x4_t +arm = nop +generate *const i64:int64x1x4_t + +/// Load single 4-element structure and replicate to all lanes of four registers +name = vld4 +out-dup-nox +multi_fn = transmute, {vld4-outsigneddupnox-noext, transmute(a)} +a = 0, 1, 1, 1, 1, 2, 4, 3, 5, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9, 8, 6, 3, 7, 4, 8, 5, 9 +validate 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +load_fn + +aarch64 = ld4r +generate *const u64:uint64x2x4_t +target = aes +generate *const p64:poly64x2x4_t + +target = default +arm = vld4 +generate *const u8:uint8x8x4_t, *const u16:uint16x4x4_t, *const u32:uint32x2x4_t +generate *const u8:uint8x16x4_t, *const u16:uint16x8x4_t, *const u32:uint32x4x4_t +generate *const p8:poly8x8x4_t, *const p16:poly16x4x4_t, *const p8:poly8x16x4_t, *const p16:poly16x8x4_t +arm = nop +generate *const u64:uint64x1x4_t +target = aes +generate *const p64:poly64x1x4_t + +/// Load single 4-element structure and replicate to all lanes of four registers +name = vld4 +out-dup-nox +a = 0., 1., 1., 1., 1., 6., 4., 3., 5., 7., 4., 3., 5., 8., 4., 3., 5., 9., 4., 3., 5. +validate 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1. +load_fn +arm-aarch64-separate + +aarch64 = ld4r +link-aarch64 = ld4r._EXT2_ +generate *const f64:float64x1x4_t, *const f64:float64x2x4_t + +arm = vld4 +link-arm = vld4dup._EXTpi82_ +generate *const f32:float32x2x4_t, *const f32:float32x4x4_t + +/// Load multiple 4-element structures to four registers +name = vld4 +out-lane-nox +multi_fn = static_assert_imm-in_exp_len-LANE +constn = LANE +a = 0, 1, 2, 2, 2, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16 +b = 0, 2, 2, 2, 2, 16, 2, 18, 2, 20, 21, 22, 2, 24, 25, 26, 11, 12, 13, 14, 15, 16, 2, 18, 2, 20, 21, 22, 23, 24, 25, 26, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16 +n = 0 +validate 1, 2, 2, 2, 2, 16, 2, 18, 2, 20, 21, 22, 2, 24, 25, 26, 2, 12, 13, 14, 15, 16, 2, 18, 2, 20, 21, 22, 23, 24, 25, 26, 2, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 2, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16 +load_fn +arm-aarch64-separate + +aarch64 = ld4 +const-aarch64 = LANE +link-aarch64 = ld4lane._EXTpi82_ +generate *const i8:int8x16x4_t:int8x16x4_t, *const i64:int64x1x4_t:int64x1x4_t, *const i64:int64x2x4_t:int64x2x4_t + +arm = vld4 +const-arm = LANE +link-arm = vld4lane._EXTpi82_ +generate *const i8:int8x8x4_t:int8x8x4_t, *const i16:int16x4x4_t:int16x4x4_t, *const i32:int32x2x4_t:int32x2x4_t +generate *const i16:int16x8x4_t:int16x8x4_t, *const i32:int32x4x4_t:int32x4x4_t + +/// Load multiple 4-element structures to four registers +name = vld4 +out-lane-nox +multi_fn = static_assert_imm-in_exp_len-LANE +multi_fn = transmute, {vld4-outsignedlanenox-::, transmute(a), transmute(b)} +constn = LANE +a = 0, 1, 2, 2, 2, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16 +b = 0, 2, 2, 2, 2, 16, 2, 18, 2, 20, 21, 22, 2, 24, 25, 26, 11, 12, 13, 14, 15, 16, 2, 18, 2, 20, 21, 22, 23, 24, 25, 26, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16 +n = 0 +validate 1, 2, 2, 2, 2, 16, 2, 18, 2, 20, 21, 22, 2, 24, 25, 26, 2, 12, 13, 14, 15, 16, 2, 18, 2, 20, 21, 22, 23, 24, 25, 26, 2, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 2, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16 +load_fn + +aarch64 = ld4 +const-aarch64 = LANE +target = aes +generate *const p64:poly64x1x4_t:poly64x1x4_t, *const p64:poly64x2x4_t:poly64x2x4_t +target = default +generate *const p8:poly8x16x4_t:poly8x16x4_t, *const u8:uint8x16x4_t:uint8x16x4_t, *const u64:uint64x1x4_t:uint64x1x4_t, *const u64:uint64x2x4_t:uint64x2x4_t + +arm = vld4 +const-arm = LANE +generate *const u8:uint8x8x4_t:uint8x8x4_t, *const u16:uint16x4x4_t:uint16x4x4_t, *const u32:uint32x2x4_t:uint32x2x4_t +generate *const u16:uint16x8x4_t:uint16x8x4_t, *const u32:uint32x4x4_t:uint32x4x4_t +generate *const p8:poly8x8x4_t:poly8x8x4_t, *const p16:poly16x4x4_t:poly16x4x4_t +generate *const p16:poly16x8x4_t:poly16x8x4_t + +/// Load multiple 4-element structures to four registers +name = vld4 +out-lane-nox +multi_fn = static_assert_imm-in_exp_len-LANE +constn = LANE +a = 0., 1., 2., 2., 2., 5., 6., 7., 8., 5., 6., 7., 8., 1., 4., 3., 5. +b = 0., 2., 2., 2., 2., 16., 2., 18., 5., 6., 7., 8., 1., 4., 3., 5. +n = 0 +validate 1., 2., 2., 2., 2., 16., 2., 18., 2., 6., 7., 8., 2., 4., 3., 5. +load_fn +arm-aarch64-separate + +aarch64 = ld4 +const-aarch64 = LANE +link-aarch64 = ld4lane._EXTpi82_ +generate *const f64:float64x1x4_t:float64x1x4_t, *const f64:float64x2x4_t:float64x2x4_t + +arm = vld4 +const-arm = LANE +link-arm = vld4lane._EXTpi82_ +generate *const f32:float32x2x4_t:float32x2x4_t, *const f32:float32x4x4_t:float32x4x4_t + +/// Store multiple single-element structures from one, two, three, or four registers +name = vst1 +in1-lane-nox +multi_fn = static_assert_imm-in_exp_len-LANE +multi_fn = *a, {simd_extract, b, LANE as u32} +constn = LANE +a = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 +n = 0 +validate 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +store_fn + +aarch64 = nop +arm = nop +generate *mut i8:int8x8_t:void, *mut i16:int16x4_t:void, *mut i32:int32x2_t:void, *mut i64:int64x1_t:void +generate *mut i8:int8x16_t:void, *mut i16:int16x8_t:void, *mut i32:int32x4_t:void, *mut i64:int64x2_t:void +generate *mut u8:uint8x8_t:void, *mut u16:uint16x4_t:void, *mut u32:uint32x2_t:void, *mut u64:uint64x1_t:void +generate *mut u8:uint8x16_t:void, *mut u16:uint16x8_t:void, *mut u32:uint32x4_t:void, *mut u64:uint64x2_t:void +generate *mut p8:poly8x8_t:void, *mut p16:poly16x4_t:void, *mut p8:poly8x16_t:void, *mut p16:poly16x8_t:void +target = aes +generate *mut p64:poly64x1_t:void, *mut p64:poly64x2_t:void + +/// Store multiple single-element structures from one, two, three, or four registers +name = vst1 +in1-lane-nox +multi_fn = static_assert_imm-in_exp_len-LANE +multi_fn = *a, {simd_extract, b, LANE as u32} +constn = LANE +a = 0., 1., 2., 3., 4., 5., 6., 7., 8. +n = 0 +validate 1., 0., 0., 0., 0., 0., 0., 0. +store_fn + +aarch64 = nop +generate *mut f64:float64x1_t:void, *mut f64:float64x2_t:void + +arm = nop +generate *mut f32:float32x2_t:void, *mut f32:float32x4_t:void + +/// Store multiple single-element structures from one, two, three, or four registers +name = vst1 +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, 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 +validate 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, 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 +store_fn +arm-aarch64-separate + +aarch64 = st1 +link-aarch64 = st1x2._EXT3_ +arm = vst1 +link-arm = vst1x2._EXTr3_ +generate *mut i8:int8x8x2_t:void, *mut i16:int16x4x2_t:void, *mut i32:int32x2x2_t:void, *mut i64:int64x1x2_t:void +generate *mut i8:int8x16x2_t:void, *mut i16:int16x8x2_t:void, *mut i32:int32x4x2_t:void, *mut i64:int64x2x2_t:void + +link-aarch64 = st1x3._EXT3_ +link-arm = vst1x3._EXTr3_ +generate *mut i8:int8x8x3_t:void, *mut i16:int16x4x3_t:void, *mut i32:int32x2x3_t:void, *mut i64:int64x1x3_t:void +generate *mut i8:int8x16x3_t:void, *mut i16:int16x8x3_t:void, *mut i32:int32x4x3_t:void, *mut i64:int64x2x3_t:void + +link-aarch64 = st1x4._EXT3_ +link-arm = vst1x4._EXTr3_ +generate *mut i8:int8x8x4_t:void, *mut i16:int16x4x4_t:void, *mut i32:int32x2x4_t:void, *mut i64:int64x1x4_t:void +generate *mut i8:int8x16x4_t:void, *mut i16:int16x8x4_t:void, *mut i32:int32x4x4_t:void, *mut i64:int64x2x4_t:void /// Store multiple single-element structures to one, two, three, or four registers name = vst1 @@ -2319,6 +3061,11 @@ generate *mut p8:poly8x8x2_t:void, *mut p8:poly8x8x3_t:void, *mut p8:poly8x8x4_t generate *mut p8:poly8x16x2_t:void, *mut p8:poly8x16x3_t:void, *mut p8:poly8x16x4_t:void generate *mut p16:poly16x4x2_t:void, *mut p16:poly16x4x3_t:void, *mut p16:poly16x4x4_t:void generate *mut p16:poly16x8x2_t:void, *mut p16:poly16x8x3_t:void, *mut p16:poly16x8x4_t:void +target = aes +generate *mut p64:poly64x1x2_t:void +arm = nop +generate *mut p64:poly64x1x3_t:void, *mut p64:poly64x1x4_t:void +generate *mut p64:poly64x2x2_t:void, *mut p64:poly64x2x3_t:void, *mut p64:poly64x2x4_t:void /// Store multiple single-element structures to one, two, three, or four registers name = vst1 @@ -2350,6 +3097,409 @@ link-aarch64 = st1x4._EXT3_ link-arm = vst1x4._EXTr3_ generate *mut f32:float32x2x4_t:void, *mut f32:float32x4x4_t:void +/// Store multiple 2-element structures from two registers +name = vst2 +in1-nox +a = 0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 +validate 1, 2, 2, 3, 2, 4, 3, 5, 2, 6, 3, 7, 4, 8, 5, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15, 8, 16, 9, 17 +store_fn +arm-aarch64-separate + +aarch64 = st2 +link-aarch64 = st2._EXTpi8_ +generate *mut i64:int64x2x2_t:void + +arm = vst2 +link-arm = vst2._EXTpi8r_ +generate *mut i8:int8x8x2_t:void, *mut i16:int16x4x2_t:void, *mut i32:int32x2x2_t:void +generate *mut i8:int8x16x2_t:void, *mut i16:int16x8x2_t:void, *mut i32:int32x4x2_t:void +arm = nop +aarch64 = nop +generate *mut i64:int64x1x2_t:void + +/// Store multiple 2-element structures from two registers +name = vst2 +multi_fn = transmute, {vst2-in1signednox-noext, transmute(a), transmute(b)} +in1-nox +a = 0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 +validate 1, 2, 2, 3, 2, 4, 3, 5, 2, 6, 3, 7, 4, 8, 5, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15, 8, 16, 9, 17 +store_fn + +aarch64 = st2 +generate *mut u64:uint64x2x2_t:void +target = aes +generate *mut p64:poly64x2x2_t:void + +target = default +arm = vst2 +generate *mut u8:uint8x8x2_t:void, *mut u16:uint16x4x2_t:void, *mut u32:uint32x2x2_t:void +generate *mut u8:uint8x16x2_t:void, *mut u16:uint16x8x2_t:void, *mut u32:uint32x4x2_t:void +generate *mut p8:poly8x8x2_t:void, *mut p16:poly16x4x2_t:void, *mut p8:poly8x16x2_t:void, *mut p16:poly16x8x2_t:void +arm = nop +aarch64 = nop +generate *mut u64:uint64x1x2_t:void +target = aes +generate *mut p64:poly64x1x2_t:void + +/// Store multiple 2-element structures from two registers +name = vst2 +in1-nox +a = 0., 1., 2., 2., 3., 2., 3., 4., 5., 2., 3., 4., 5., 6., 7., 8., 9. +validate 1., 2., 2., 3., 2., 4., 3., 5., 2., 6., 3., 7., 4., 8., 5., 9. +store_fn +arm-aarch64-separate + +aarch64 = st1 +link-aarch64 = st2._EXTpi8_ +generate *mut f64:float64x1x2_t:void +aarch64 = st2 +generate *mut f64:float64x2x2_t:void + +arm = vst2 +link-arm = vst2._EXTpi8r_ +generate *mut f32:float32x2x2_t:void, *mut f32:float32x4x2_t:void + +/// Store multiple 2-element structures from two registers +name = vst2 +in1-lane-nox +constn = LANE +multi_fn = static_assert_imm-in_exp_len-LANE +a = 0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 +n = 0 +validate 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +store_fn +arm-aarch64-separate + +aarch64 = st2 +link-aarch64 = st2lane._EXTpi8_ +const-aarch64 = LANE +generate *mut i8:int8x16x2_t:void, *mut i64:int64x1x2_t:void, *mut i64:int64x2x2_t:void + +arm = vst2 +link-arm = vst2lane._EXTpi8r_ +const-arm = LANE +generate *mut i8:int8x8x2_t:void, *mut i16:int16x4x2_t:void, *mut i32:int32x2x2_t:void +generate *mut i16:int16x8x2_t:void, *mut i32:int32x4x2_t:void + +/// Store multiple 2-element structures from two registers +name = vst2 +in1-lane-nox +constn = LANE +multi_fn = static_assert_imm-in_exp_len-LANE +multi_fn = transmute, {vst2-in1signedlanenox-::, transmute(a), transmute(b)} +a = 0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 +n = 0 +validate 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +store_fn + +aarch64 = st2 +generate *mut u8:uint8x16x2_t:void, *mut u64:uint64x1x2_t:void, *mut u64:uint64x2x2_t:void, *mut p8:poly8x16x2_t:void +target = aes +generate *mut p64:poly64x1x2_t:void, *mut p64:poly64x2x2_t:void + +target = default +arm = vst2 +generate *mut u8:uint8x8x2_t:void, *mut u16:uint16x4x2_t:void, *mut u32:uint32x2x2_t:void +generate *mut u16:uint16x8x2_t:void, *mut u32:uint32x4x2_t:void +generate *mut p8:poly8x8x2_t:void, *mut p16:poly16x4x2_t:void, *mut p16:poly16x8x2_t:void + +/// Store multiple 2-element structures from two registers +name = vst2 +in1-lane-nox +constn = LANE +multi_fn = static_assert_imm-in_exp_len-LANE +a = 0., 1., 2., 2., 3., 2., 3., 4., 5., 2., 3., 4., 5., 6., 7., 8., 9. +n = 0 +validate 1., 2., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0. +store_fn +arm-aarch64-separate + +aarch64 = st2 +link-aarch64 = st2lane._EXTpi8_ +const-aarch64 = LANE +generate *mut f64:float64x1x2_t:void, *mut f64:float64x2x2_t:void + +arm = vst2 +link-arm = vst2lane._EXTpi8r_ +const-arm = LANE +generate *mut f32:float32x2x2_t:void, *mut f32:float32x4x2_t:void + +/// Store multiple 3-element structures from three registers +name = vst3 +in1-nox +a = 0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16, 25, 26, 27, 28, 29, 30, 31, 32, 2, 4, 7, 8, 13, 14, 15, 16, 41, 42, 43, 44, 45, 46, 47, 48 +validate 1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8, 2, 13, 13, 4, 14, 14, 7, 15, 15, 8, 16, 16, 2, 25, 41, 4, 26, 42, 7, 27, 43, 8, 28, 44, 13, 29, 45, 14, 30, 46, 15, 31, 47, 16, 32, 48 +store_fn +arm-aarch64-separate + +aarch64 = st3 +link-aarch64 = st3._EXTpi8_ +generate *mut i64:int64x2x3_t:void + +arm = vst3 +link-arm = vst3._EXTpi8r_ +generate *mut i8:int8x8x3_t:void, *mut i16:int16x4x3_t:void, *mut i32:int32x2x3_t:void +generate *mut i8:int8x16x3_t:void, *mut i16:int16x8x3_t:void, *mut i32:int32x4x3_t:void +arm = nop +aarch64 = nop +generate *mut i64:int64x1x3_t:void + +/// Store multiple 3-element structures from three registers +name = vst3 +multi_fn = transmute, {vst3-in1signednox-noext, transmute(a), transmute(b)} +in1-nox +a = 0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16, 25, 26, 27, 28, 29, 30, 31, 32, 2, 4, 7, 8, 13, 14, 15, 16, 41, 42, 43, 44, 45, 46, 47, 48 +validate 1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8, 2, 13, 13, 4, 14, 14, 7, 15, 15, 8, 16, 16, 2, 25, 41, 4, 26, 42, 7, 27, 43, 8, 28, 44, 13, 29, 45, 14, 30, 46, 15, 31, 47, 16, 32, 48 +store_fn + +aarch64 = st3 +generate *mut u64:uint64x2x3_t:void +target = aes +generate *mut p64:poly64x2x3_t:void + +target = default +arm = vst3 +generate *mut u8:uint8x8x3_t:void, *mut u16:uint16x4x3_t:void, *mut u32:uint32x2x3_t:void +generate *mut u8:uint8x16x3_t:void, *mut u16:uint16x8x3_t:void, *mut u32:uint32x4x3_t:void +generate *mut p8:poly8x8x3_t:void, *mut p16:poly16x4x3_t:void, *mut p8:poly8x16x3_t:void, *mut p16:poly16x8x3_t:void +arm = nop +aarch64 = nop +generate *mut u64:uint64x1x3_t:void +target = aes +generate *mut p64:poly64x1x3_t:void + +/// Store multiple 3-element structures from three registers +name = vst3 +in1-nox +a = 0., 1., 2., 2., 4., 2., 4., 7., 8., 2., 4., 7., 8., 13., 14., 15., 16 +validate 1., 2., 2., 2., 4., 4., 2., 7., 7., 4., 8., 8., 2., 13., 13., 4. +store_fn +arm-aarch64-separate + +aarch64 = nop +link-aarch64 = st3._EXTpi8_ +generate *mut f64:float64x1x3_t:void +aarch64 = st3 +generate *mut f64:float64x2x3_t:void + +arm = vst3 +link-arm = vst3._EXTpi8r_ +generate *mut f32:float32x2x3_t:void, *mut f32:float32x4x3_t:void + +/// Store multiple 3-element structures from three registers +name = vst3 +in1-lane-nox +constn = LANE +multi_fn = static_assert_imm-in_exp_len-LANE +a = 0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16, 25, 26, 27, 28, 29, 30, 31, 32, 2, 4, 7, 8, 13, 14, 15, 16, 41, 42, 43, 44, 45, 46, 47, 48 +n = 0 +validate 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +store_fn +arm-aarch64-separate + +aarch64 = st3 +link-aarch64 = st3lane._EXTpi8_ +const-aarch64 = LANE +generate *mut i8:int8x16x3_t:void, *mut i64:int64x1x3_t:void, *mut i64:int64x2x3_t:void + +arm = vst3 +link-arm = vst3lane._EXTpi8r_ +const-arm = LANE +generate *mut i8:int8x8x3_t:void, *mut i16:int16x4x3_t:void, *mut i32:int32x2x3_t:void +generate *mut i16:int16x8x3_t:void, *mut i32:int32x4x3_t:void + +/// Store multiple 3-element structures from three registers +name = vst3 +in1-lane-nox +constn = LANE +multi_fn = static_assert_imm-in_exp_len-LANE +multi_fn = transmute, {vst3-in1signedlanenox-::, transmute(a), transmute(b)} +a = 0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16, 25, 26, 27, 28, 29, 30, 31, 32, 2, 4, 7, 8, 13, 14, 15, 16, 41, 42, 43, 44, 45, 46, 47, 48 +n = 0 +validate 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +store_fn + +aarch64 = st3 +generate *mut u8:uint8x16x3_t:void, *mut u64:uint64x1x3_t:void, *mut u64:uint64x2x3_t:void, *mut p8:poly8x16x3_t:void +target = aes +generate *mut p64:poly64x1x3_t:void, *mut p64:poly64x2x3_t:void + +target = default +arm = vst3 +generate *mut u8:uint8x8x3_t:void, *mut u16:uint16x4x3_t:void, *mut u32:uint32x2x3_t:void +generate *mut u16:uint16x8x3_t:void, *mut u32:uint32x4x3_t:void +generate *mut p8:poly8x8x3_t:void, *mut p16:poly16x4x3_t:void, *mut p16:poly16x8x3_t:void + +/// Store multiple 3-element structures from three registers +name = vst3 +in1-lane-nox +constn = LANE +multi_fn = static_assert_imm-in_exp_len-LANE +a = 0., 1., 2., 2., 3., 2., 3., 4., 5., 2., 3., 4., 5., 6., 7., 8., 9. +n = 0 +validate 1., 2., 2., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0. +store_fn +arm-aarch64-separate + +aarch64 = st3 +link-aarch64 = st3lane._EXTpi8_ +const-aarch64 = LANE +generate *mut f64:float64x1x3_t:void, *mut f64:float64x2x3_t:void + +arm = vst3 +link-arm = vst3lane._EXTpi8r_ +const-arm = LANE +generate *mut f32:float32x2x3_t:void, *mut f32:float32x4x3_t:void + +/// Store multiple 4-element structures from four registers +name = vst4 +in1-nox +a = 0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48, 6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64 +validate 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48, 6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64 +store_fn +arm-aarch64-separate + +aarch64 = st4 +link-aarch64 = st4._EXTpi8_ +generate *mut i64:int64x2x4_t:void + +arm = vst4 +link-arm = vst4._EXTpi8r_ +generate *mut i8:int8x8x4_t:void, *mut i16:int16x4x4_t:void, *mut i32:int32x2x4_t:void +generate *mut i8:int8x16x4_t:void, *mut i16:int16x8x4_t:void, *mut i32:int32x4x4_t:void +arm = nop +aarch64 = nop +generate *mut i64:int64x1x4_t:void + +/// Store multiple 4-element structures from four registers +name = vst4 +multi_fn = transmute, {vst4-in1signednox-noext, transmute(a), transmute(b)} +in1-nox +a = 0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48, 6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64 +validate 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48, 6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64 +store_fn + +aarch64 = st4 +generate *mut u64:uint64x2x4_t:void +target = aes +generate *mut p64:poly64x2x4_t:void + +target = default +arm = vst4 +generate *mut u8:uint8x8x4_t:void, *mut u16:uint16x4x4_t:void, *mut u32:uint32x2x4_t:void +generate *mut u8:uint8x16x4_t:void, *mut u16:uint16x8x4_t:void, *mut u32:uint32x4x4_t:void +generate *mut p8:poly8x8x4_t:void, *mut p16:poly16x4x4_t:void, *mut p8:poly8x16x4_t:void, *mut p16:poly16x8x4_t:void +arm = nop +aarch64 = nop +generate *mut u64:uint64x1x4_t:void +target = aes +generate *mut p64:poly64x1x4_t:void + +/// Store multiple 4-element structures from four registers +name = vst4 +in1-nox +a = 0., 1., 2., 2., 6., 2., 6., 6., 8., 2., 6., 6., 8., 6., 8., 8., 16. +validate 1., 2., 2., 6., 2., 6., 6., 8., 2., 6., 6., 8., 6., 8., 8., 16. +store_fn +arm-aarch64-separate + +aarch64 = nop +link-aarch64 = st4._EXTpi8_ +generate *mut f64:float64x1x4_t:void +aarch64 = st4 +generate *mut f64:float64x2x4_t:void + +arm = vst4 +link-arm = vst4._EXTpi8r_ +generate *mut f32:float32x2x4_t:void, *mut f32:float32x4x4_t:void + +/// Store multiple 4-element structures from four registers +name = vst4 +in1-lane-nox +constn = LANE +multi_fn = static_assert_imm-in_exp_len-LANE +a = 0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48, 6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64 +n = 0 +validate 1, 2, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +store_fn +arm-aarch64-separate + +aarch64 = st4 +link-aarch64 = st4lane._EXTpi8_ +const-aarch64 = LANE +generate *mut i8:int8x16x4_t:void, *mut i64:int64x1x4_t:void, *mut i64:int64x2x4_t:void + +arm = vst4 +link-arm = vst4lane._EXTpi8r_ +const-arm = LANE +generate *mut i8:int8x8x4_t:void, *mut i16:int16x4x4_t:void, *mut i32:int32x2x4_t:void +generate *mut i16:int16x8x4_t:void, *mut i32:int32x4x4_t:void + +/// Store multiple 4-element structures from four registers +name = vst4 +in1-lane-nox +constn = LANE +multi_fn = static_assert_imm-in_exp_len-LANE +multi_fn = transmute, {vst4-in1signedlanenox-::, transmute(a), transmute(b)} +a = 0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48, 6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64 +n = 0 +validate 1, 2, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +store_fn + +aarch64 = st4 +generate *mut u8:uint8x16x4_t:void, *mut u64:uint64x1x4_t:void, *mut u64:uint64x2x4_t:void, *mut p8:poly8x16x4_t:void +target = aes +generate *mut p64:poly64x1x4_t:void, *mut p64:poly64x2x4_t:void + +target = default +arm = vst4 +generate *mut u8:uint8x8x4_t:void, *mut u16:uint16x4x4_t:void, *mut u32:uint32x2x4_t:void +generate *mut u16:uint16x8x4_t:void, *mut u32:uint32x4x4_t:void +generate *mut p8:poly8x8x4_t:void, *mut p16:poly16x4x4_t:void, *mut p16:poly16x8x4_t:void + +/// Store multiple 4-element structures from four registers +name = vst4 +in1-lane-nox +constn = LANE +multi_fn = static_assert_imm-in_exp_len-LANE +a = 0., 1., 2., 2., 6., 2., 6., 6., 8., 2., 6., 6., 8., 6., 8., 8., 16. +n = 0 +validate 1., 2., 2., 6., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0. +store_fn +arm-aarch64-separate + +aarch64 = st4 +link-aarch64 = st4lane._EXTpi8_ +const-aarch64 = LANE +generate *mut f64:float64x1x4_t:void, *mut f64:float64x2x4_t:void + +arm = vst4 +link-arm = vst4lane._EXTpi8r_ +const-arm = LANE +generate *mut f32:float32x2x4_t:void, *mut f32:float32x4x4_t:void + +/// Dot product index form with signed and unsigned integers +name = vsudot +out-lane-suffixes +constn = LANE +multi_fn = static_assert_imm-in2_dot-LANE +multi_fn = simd_shuffle-in_len-!, c:unsigned, c, c, {base-4-LANE} +multi_fn = vsudot-outlane-_, a, b, c +a = 1, 2, 1, 2 +b = 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 +c = 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 +n = 0 +validate 31, 72, 31, 72 +target = dotprod + +aarch64 = sudot +link-aarch64 = usdot._EXT2_._EXT4_:int32x2_t:int8x8_t:uint8x8_t:int32x2_t +// LLVM ERROR: Cannot select: intrinsic %llvm.aarch64.neon.usdot +//generate int32x2_t:int8x8_t:uint8x8_t:int32x2_t, int32x2_t:int8x8_t:uint8x16_t:int32x2_t +link-aarch64 = usdot._EXT2_._EXT4_:int32x4_t:int8x16_t:uint8x16_t:int32x4_t +// LLVM ERROR: Cannot select: intrinsic %llvm.aarch64.neon.usdot +//generate int32x4_t:int8x16_t:uint8x8_t:int32x4_t, int32x4_t:int8x16_t:uint8x16_t:int32x4_t + /// Multiply name = vmul a = 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2 @@ -2561,7 +3711,7 @@ target = aes aarch64 = pmull link-aarch64 = pmull64:p64:p64:p64:int8x16_t -// Because of the support status of llvm, vmull_p64 is currently only available on aarch64 +// Because of the support status of llvm, vmull_p64 is currently only available on arm // arm = vmull // link-arm = vmullp.v2i64:int64x1_t:int64x1_t:int64x1_t:int64x2_t generate p64:p64:p128 @@ -2903,6 +4053,58 @@ generate float64x*_t arm = vsub. generate float*_t +/// Subtract +name = vsub +multi_fn = a - b +a = 3 +b = 2 +validate 1 + +aarch64 = nop +generate i64, u64 + +/// Add +name = vadd +multi_fn = a + b +a = 1 +b = 2 +validate 3 + +aarch64 = nop +generate i64, u64 + +/// Bitwise exclusive OR +name = vadd +multi_fn = simd_xor, a, b +a = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 +b = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +validate 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14, 17 + +aarch64 = nop +arm = nop +generate poly8x8_t, poly16x4_t, poly8x16_t, poly16x8_t, poly64x1_t, poly64x2_t + +/// Bitwise exclusive OR +name = vaddq +no-q +multi_fn = a ^ b +a = 16 +b = 1 +validate 17 + +aarch64 = nop +arm = nop +generate p128 + +/// Floating-point add across vector +name = vaddv +a = 1., 2., 0., 0. +validate 3. + +aarch64 = faddp +link-aarch64 = faddv._EXT2_._EXT_ +generate float32x2_t:f32, float32x4_t:f32, float64x2_t:f64 + /// Signed Add Long across Vector name = vaddlv a = 1, 2, 3, 4 @@ -3245,6 +4447,210 @@ validate 6, 7 aarch64 = usubl generate uint32x4_t:uint32x4_t:uint64x2_t +/// Bit clear and exclusive OR +name = vbcax +a = 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 +b = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +c = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +validate 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14 +target = sha3 + +aarch64 = bcax +link-aarch64 = llvm.aarch64.crypto.bcaxs._EXT_ +generate int8x16_t, int16x8_t, int32x4_t, int64x2_t +link-aarch64 = llvm.aarch64.crypto.bcaxu._EXT_ +generate uint8x16_t, uint16x8_t, uint32x4_t, uint64x2_t + +/// Floating-point complex add +name = vcadd_rot270 +no-q +a = 1., -1., 1., -1. +b = -1., 1., -1., 1. +validate 2., 0., 2., 0. +target = fcma + +aarch64 = fcadd +link-aarch64 = vcadd.rot270._EXT_ +generate float32x2_t +name = vcaddq_rot270 +generate float32x4_t, float64x2_t + +/// Floating-point complex add +name = vcadd_rot90 +no-q +a = 1., -1., 1., -1. +b = -1., 1., -1., 1. +validate 0., -2., 0., -2. +target = fcma + +aarch64 = fcadd +link-aarch64 = vcadd.rot90._EXT_ +generate float32x2_t +name = vcaddq_rot90 +generate float32x4_t, float64x2_t + +/// Floating-point complex multiply accumulate +name = vcmla +a = 1., -1., 1., -1. +b = -1., 1., -1., 1. +c = 1., 1., -1., -1. +validate 0., -2., 2., 0. +target = fcma + +aarch64 = fcmla +link-aarch64 = vcmla.rot0._EXT_ +generate float32x2_t, float32x4_t, float64x2_t + +/// Floating-point complex multiply accumulate +name = vcmla_rot90 +rot-suffix +a = 1., 1., 1., 1. +b = 1., -1., 1., -1. +c = 1., 1., 1., 1. +validate 2., 0., 2., 0. +target = fcma + +aarch64 = fcmla +link-aarch64 = vcmla.rot90._EXT_ +generate float32x2_t, float32x4_t, float64x2_t + +/// Floating-point complex multiply accumulate +name = vcmla_rot180 +rot-suffix +a = 1., 1., 1., 1. +b = 1., -1., 1., -1. +c = 1., 1., 1., 1. +validate 0., 0., 0., 0. +target = fcma + +aarch64 = fcmla +link-aarch64 = vcmla.rot180._EXT_ +generate float32x2_t, float32x4_t, float64x2_t + +/// Floating-point complex multiply accumulate +name = vcmla_rot270 +rot-suffix +a = 1., 1., 1., 1. +b = 1., -1., 1., -1. +c = 1., 1., 1., 1. +validate 0., 2., 0., 2. +target = fcma + +aarch64 = fcmla +link-aarch64 = vcmla.rot270._EXT_ +generate float32x2_t, float32x4_t, float64x2_t + +/// Floating-point complex multiply accumulate +name = vcmla +in2-lane-suffixes +constn = LANE +multi_fn = static_assert_imm-in2_rot-LANE +multi_fn = simd_shuffle-out_len-!, c:out_t, c, c, {base-2-LANE} +multi_fn = vcmla-self-noext, a, b, c +a = 1., -1., 1., -1. +b = -1., 1., -1., 1. +c = 1., 1., -1., -1. +n = 0 +validate 0., -2., 0., -2. +target = fcma + +aarch64 = fcmla +generate float32x2_t, float32x2_t:float32x2_t:float32x4_t:float32x2_t +generate float32x4_t:float32x4_t:float32x2_t:float32x4_t, float32x4_t + +/// Floating-point complex multiply accumulate +name = vcmla_rot90 +rot-lane-suffixes +constn = LANE +multi_fn = static_assert_imm-in2_rot-LANE +multi_fn = simd_shuffle-out_len-!, c:out_t, c, c, {base-2-LANE} +multi_fn = vcmla_rot90-rot-noext, a, b, c +a = 1., -1., 1., -1. +b = -1., 1., -1., 1. +c = 1., 1., -1., -1. +n = 0 +validate 0., 0., 0., 0. +target = fcma + +aarch64 = fcmla +generate float32x2_t, float32x2_t:float32x2_t:float32x4_t:float32x2_t +generate float32x4_t:float32x4_t:float32x2_t:float32x4_t, float32x4_t + +/// Floating-point complex multiply accumulate +name = vcmla_rot180 +rot-lane-suffixes +constn = LANE +multi_fn = static_assert_imm-in2_rot-LANE +multi_fn = simd_shuffle-out_len-!, c:out_t, c, c, {base-2-LANE} +multi_fn = vcmla_rot180-rot-noext, a, b, c +a = 1., -1., 1., -1. +b = -1., 1., -1., 1. +c = 1., 1., -1., -1. +n = 0 +validate 2., 0., 2., 0. +target = fcma + +aarch64 = fcmla +generate float32x2_t, float32x2_t:float32x2_t:float32x4_t:float32x2_t +generate float32x4_t:float32x4_t:float32x2_t:float32x4_t, float32x4_t + +/// Floating-point complex multiply accumulate +name = vcmla_rot270 +rot-lane-suffixes +constn = LANE +multi_fn = static_assert_imm-in2_rot-LANE +multi_fn = simd_shuffle-out_len-!, c:out_t, c, c, {base-2-LANE} +multi_fn = vcmla_rot270-rot-noext, a, b, c +a = 1., -1., 1., -1. +b = -1., 1., -1., 1. +c = 1., 1., -1., -1. +n = 0 +validate 2., -2., 2., -2. +target = fcma + +aarch64 = fcmla +generate float32x2_t, float32x2_t:float32x2_t:float32x4_t:float32x2_t +generate float32x4_t:float32x4_t:float32x2_t:float32x4_t, float32x4_t + +/// Dot product arithmetic +name = vdot +out-suffix +a = 1, 2, 1, 2 +b = 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 +c = 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 +validate 31, 176, 31, 176 +target = dotprod + +aarch64 = sdot +link-aarch64 = sdot._EXT_._EXT3_ +generate int32x2_t:int8x8_t:int8x8_t:int32x2_t, int32x4_t:int8x16_t:int8x16_t:int32x4_t + +aarch64 = udot +link-aarch64 = udot._EXT_._EXT3_ +generate uint32x2_t:uint8x8_t:uint8x8_t:uint32x2_t, uint32x4_t:uint8x16_t:uint8x16_t:uint32x4_t + +/// Dot product arithmetic +name = vdot +out-lane-suffixes +constn = LANE +multi_fn = static_assert_imm-in2_dot-LANE +multi_fn = simd_shuffle-in_len-!, c:in_t, c, c, {base-4-LANE} +multi_fn = vdot-out-noext, a, b, c +a = 1, 2, 1, 2 +b = 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 +c = 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 +n = 0 +validate 31, 72, 31, 72 +target = dotprod + +aarch64 = sdot +generate int32x2_t:int8x8_t:int8x8_t:int32x2_t, int32x2_t:int8x8_t:int8x16_t:int32x2_t +generate int32x4_t:int8x16_t:int8x8_t:int32x4_t, int32x4_t:int8x16_t:int8x16_t:int32x4_t + +aarch64 = udot +generate uint32x2_t:uint8x8_t:uint8x8_t:uint32x2_t, uint32x2_t:uint8x8_t:uint8x16_t:uint32x2_t +generate uint32x4_t:uint8x16_t:uint8x8_t:uint32x4_t, uint32x4_t:uint8x16_t:uint8x16_t:uint32x4_t + /// Maximum (vector) name = vmax a = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 @@ -3296,6 +4702,17 @@ link-arm = vmaxnm._EXT_ link-aarch64 = fmaxnm._EXT_ generate float*_t +/// Floating-point maximum number across vector +name = vmaxnmv +a = 1., 2., 0., 1. +validate 2. + +aarch64 = fmaxnmp +link-aarch64 = fmaxnmv._EXT2_._EXT_ +generate float32x2_t:f32, float64x2_t:f64 +aarch64 = fmaxnmv +generate float32x4_t:f32 + /// Floating-point Maximum Number Pairwise (vector). name = vpmaxnm a = 1.0, 2.0 @@ -3314,6 +4731,30 @@ aarch64 = fmaxnmp link-aarch64 = fmaxnmp._EXT_ generate float32x4_t:float32x4_t:float32x4_t +/// Floating-point maximum number pairwise +name = vpmaxnm +out-suffix +a = 1., 2. +validate 2. + +aarch64 = fmaxnmp +link-aarch64 = fmaxnmv._EXT2_._EXT_ +generate float32x2_t:f32 +name = vpmaxnmq +generate float64x2_t:f64 + +/// Floating-point maximum pairwise +name = vpmax +out-suffix +a = 1., 2. +validate 2. + +aarch64 = fmaxp +link-aarch64 = fmaxv._EXT2_._EXT_ +generate float32x2_t:f32 +name = vpmaxq +generate float64x2_t:f64 + /// Minimum (vector) name = vmin a = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 @@ -3365,11 +4806,63 @@ link-arm = vminnm._EXT_ link-aarch64 = fminnm._EXT_ generate float*_t +/// Floating-point minimum number across vector +name = vminnmv +a = 1., 0., 2., 3. +validate 0. + +aarch64 = fminnmp +link-aarch64 = fminnmv._EXT2_._EXT_ +generate float32x2_t:f32, float64x2_t:f64 +aarch64 = fminnmv +generate float32x4_t:f32 + +/// Vector move +name = vmovl_high +no-q +multi_fn = simd_shuffle-out_len-!, a:half, a, a, {asc-halflen-halflen} +multi_fn = vmovl-noqself-noext, a +a = 1, 2, 3, 4, 3, 4, 5, 6, 3, 4, 5, 6, 7, 8, 9, 10 +validate 3, 4, 5, 6, 7, 8, 9, 10 + +aarch64 = sxtl2 +generate int8x16_t:int16x8_t, int16x8_t:int32x4_t, int32x4_t:int64x2_t + +aarch64 = uxtl2 +generate uint8x16_t:uint16x8_t, uint16x8_t:uint32x4_t, uint32x4_t:uint64x2_t + +/// Floating-point add pairwise +name = vpadd +a = 1., 2., 3., 4. +b = 3., 4., 5., 6. +validate 3., 7., 7., 11. + +aarch64 = faddp +link-aarch64 = faddp._EXT_ +generate float32x4_t, float64x2_t + +arm = vpadd +link-arm = vpadd._EXT_ +generate float32x2_t + +/// Floating-point add pairwise +name = vpadd +out-suffix +multi_fn = simd_extract, a1:out_t, a, 0 +multi_fn = simd_extract, a2:out_t, a, 1 +multi_fn = a1 + a2 +a = 1., 2. +validate 3. + +aarch64 = nop +generate float32x2_t:f32, float64x2_t:f64 + /// Floating-point Minimum Number Pairwise (vector). name = vpminnm a = 1.0, 2.0 b = 6.0, -3.0 validate 1.0, -3.0 + aarch64 = fminnmp link-aarch64 = fminnmp._EXT_ generate float32x2_t:float32x2_t:float32x2_t, float64x2_t:float64x2_t:float64x2_t @@ -3383,6 +4876,30 @@ aarch64 = fminnmp link-aarch64 = fminnmp._EXT_ generate float32x4_t:float32x4_t:float32x4_t +/// Floating-point minimum number pairwise +name = vpminnm +out-suffix +a = 1., 2. +validate 1. + +aarch64 = fminnmp +link-aarch64 = fminnmv._EXT2_._EXT_ +generate float32x2_t:f32 +name = vpminnmq +generate float64x2_t:f64 + +/// Floating-point minimum pairwise +name = vpmin +out-suffix +a = 1., 2. +validate 1. + +aarch64 = fminp +link-aarch64 = fminv._EXT2_._EXT_ +generate float32x2_t:f32 +name = vpminq +generate float64x2_t:f64 + /// Signed saturating doubling multiply long name = vqdmull a = 0, 1, 2, 3, 4, 5, 6, 7 @@ -3612,6 +5129,36 @@ validate 17, 22, 27, 32 aarch64 = sqdmlal2 generate int32x4_t:int16x8_t:int16x4_t:int32x4_t, int32x4_t:int16x8_t:int16x8_t:int32x4_t, int64x2_t: int32x4_t:int32x2_t:int64x2_t, int64x2_t:int32x4_t:int32x4_t:int64x2_t +/// Signed saturating doubling multiply-add long +name = vqdmlal +multi_fn = vqdmull-in_ntt-noext, x:out_long_ntt, {vdup_n-in_ntt-noext, b}, {vdup_n-in_ntt-noext, c} +multi_fn = vqadd-out-noext, a, {simd_extract, x, 0} +a = 1 +b = 1 +c = 2 +validate 5 + +aarch64 = sqdmull +generate i32:i16:i16:i32, i64:i32:i32:i64 + +/// Signed saturating doubling multiply-add long +name = vqdmlalh_lane +in2-suffix +constn = LANE +multi_fn = static_assert_imm-in2_exp_len-LANE +multi_fn = vqdmlal-self-noext, a, b, {simd_extract, c, LANE as u32} +a = 1 +b = 1 +c = 2, 1, 1, 1, 1, 1, 1, 1 +n = 0 +validate 5 + +aarch64 = sqdmlal +generate i32:i16:int16x4_t:i32, i32:i16:int16x8_t:i32 +name = vqdmlals_lane +aarch64 = sqdmull +generate i64:i32:int32x2_t:i64, i64:i32:int32x4_t:i64 + /// Signed saturating doubling multiply-subtract long name = vqdmlsl multi_fn = vqsub-out-noext, a, {vqdmull-self-noext, b, c} @@ -3694,6 +5241,36 @@ validate -1, -2, -3, -4 aarch64 = sqdmlsl2 generate int32x4_t:int16x8_t:int16x4_t:int32x4_t, int32x4_t:int16x8_t:int16x8_t:int32x4_t, int64x2_t: int32x4_t:int32x2_t:int64x2_t, int64x2_t:int32x4_t:int32x4_t:int64x2_t +/// Signed saturating doubling multiply-subtract long +name = vqdmlsl +multi_fn = vqdmull-in_ntt-noext, x:out_long_ntt, {vdup_n-in_ntt-noext, b}, {vdup_n-in_ntt-noext, c} +multi_fn = vqsub-out-noext, a, {simd_extract, x, 0} +a = 10 +b = 1 +c = 2 +validate 6 + +aarch64 = sqdmull +generate i32:i16:i16:i32, i64:i32:i32:i64 + +/// Signed saturating doubling multiply-subtract long +name = vqdmlslh_lane +in2-suffix +constn = LANE +multi_fn = static_assert_imm-in2_exp_len-LANE +multi_fn = vqdmlsl-self-noext, a, b, {simd_extract, c, LANE as u32} +a = 10 +b = 1 +c = 2, 1, 1, 1, 1, 1, 1, 1 +n = 0 +validate 6 + +aarch64 = sqdmlsl +generate i32:i16:int16x4_t:i32, i32:i16:int16x8_t:i32 +name = vqdmlsls_lane +aarch64 = sqdmull +generate i64:i32:int32x2_t:i64, i64:i32:int32x4_t:i64 + /// Signed saturating doubling multiply returning high half name = vqdmulh a = MAX, MAX, MAX, MAX, MAX, MAX, MAX, MAX @@ -3772,6 +5349,24 @@ validate 1 aarch64 = sqdmulh generate i32:int32x2_t:i32, i32:int32x4_t:i32 +/// Vector saturating doubling multiply high by scalar +name = vqdmulh +lane-suffixes +constn = LANE +multi_fn = static_assert_imm-in2_exp_len-LANE +multi_fn = vqdmulh-out-noext, a, {vdup-nout-noext, {simd_extract, b, LANE as u32}} +a = MAX, MAX, MAX, MAX, MAX, MAX, MAX, MAX +b = 2, 1, 1, 1, 1, 1, 1, 1 +n = 0 +validate 1, 1, 1, 1, 1, 1, 1, 1 + +aarch64 = sqdmulh +generate int16x4_t, int16x8_t:int16x4_t:int16x8_t +generate int32x2_t, int32x4_t:int32x2_t:int32x4_t +arm = vqdmulh +generate int16x8_t, int16x4_t:int16x8_t:int16x4_t +generate int32x4_t, int32x2_t:int32x4_t:int32x2_t + /// Signed saturating extract narrow name = vqmovn no-q @@ -3938,19 +5533,23 @@ b = MAX, MAX, MAX, MAX, MAX, MAX, MAX, MAX c = 2, 2, 2, 2, 2, 2, 2, 2 validate 3, 3, 3, 3, 3, 3, 3, 3 -aarch64 = sqrdmulh -arm = vqrdmulh +aarch64 = sqrdmlah +target = rdm generate int16x4_t, int16x8_t, int32x2_t, int32x4_t /// Signed saturating rounding doubling multiply accumulate returning high half name = vqrdmlah -multi_fn = vqadd-self-noext, a, {vqrdmulh-self-noext, b, c} +multi_fn = vdup_n-in_ntt-noext, a:in_ntt, a +multi_fn = vdup_n-in_ntt-noext, b:in_ntt, b +multi_fn = vdup_n-in_ntt-noext, c:in_ntt, c +multi_fn = simd_extract, {vqrdmlah-in_ntt-noext, a, b, c}, 0 a = 1 b = 1 c = 2 validate 1 -aarch64 = sqrdmulh +aarch64 = sqrdmlah +target = rdm generate i16, i32 /// Signed saturating rounding doubling multiply accumulate returning high half @@ -3965,8 +5564,8 @@ c = 0, 2, 0, 0, 0, 0, 0, 0 n = 1 validate 3, 3, 3, 3, 3, 3, 3, 3 -aarch64 = sqrdmulh -arm = vqrdmulh +aarch64 = sqrdmlah +target = rdm generate int16x4_t, int16x4_t:int16x4_t:int16x8_t:int16x4_t, int16x8_t:int16x8_t:int16x4_t:int16x8_t, int16x8_t generate int32x2_t, int32x2_t:int32x2_t:int32x4_t:int32x2_t, int32x4_t:int32x4_t:int32x2_t:int32x4_t, int32x4_t @@ -3975,14 +5574,15 @@ name = vqrdmlah in2-lane-suffixes constn = LANE multi_fn = static_assert_imm-in2_exp_len-LANE -multi_fn = vqadd-self-noext, a, {vqrdmulh-in2lane-::, b, c} +multi_fn = vqrdmlah-self-noext, a, b, {simd_extract, c, LANE as u32} a = 1 b = 1 c = 0, 2, 0, 0, 0, 0, 0, 0 n = 1 validate 1 -aarch64 = sqrdmulh +aarch64 = sqrdmlah +target = rdm generate i16:i16:int16x4_t:i16, i16:i16:int16x8_t:i16, i32:i32:int32x2_t:i32, i32:i32:int32x4_t:i32 /// Signed saturating rounding doubling multiply subtract returning high half @@ -4343,6 +5943,38 @@ validate 4 aarch64 = uqshl generate u8, u16, u32, u64 +/// Signed saturating shift left unsigned +name = vqshlu +n-suffix +constn = N +multi_fn = static_assert_imm-out_bits_exp_len-N +a = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +n = 2 +validate 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60 +arm-aarch64-separate + +aarch64 = sqshlu +link-aarch64 = sqshlu._EXT_ +const-aarch64 = {dup-in_len-N as ttn} +arm = vqshlu +link-arm = vqshiftsu._EXT_ +const-arm = N as ttn +generate int8x8_t:uint8x8_t, int16x4_t:uint16x4_t, int32x2_t:uint32x2_t, int64x1_t:uint64x1_t +generate int8x16_t:uint8x16_t, int16x8_t:uint16x8_t, int32x4_t:uint32x4_t, int64x2_t:uint64x2_t + +/// Signed saturating shift left unsigned +name = vqshlu +n-suffix +constn = N +multi_fn = static_assert_imm-out_bits_exp_len-N +multi_fn = simd_extract, {vqshlu_n-in_ntt-::, {vdup_n-in_ntt-noext, a}}, 0 +a = 1 +n = 2 +validate 4 + +aarch64 = sqshlu +generate i8:u8, i16:u16, i32:u32, i64:u64 + /// Signed saturating shift right narrow name = vqshrn noq-n-suffix @@ -4483,6 +6115,28 @@ validate 0, 1, 8, 9, 8, 9, 10, 11, 8, 9, 10, 11, 12, 13, 14, 15 aarch64 = sqshrun2 generate uint8x8_t:int16x8_t:uint8x16_t, uint16x4_t:int32x4_t:uint16x8_t, uint32x2_t:int64x2_t:uint32x4_t +/// Unsigned saturating accumulate of signed value +name = vsqadd +out-suffix +multi_fn = simd_extract, {vsqadd-out_ntt-noext, {vdup_n-out_ntt-noext, a}, {vdup_n-in_ntt-noext, b}}, 0 +a = 2 +b = 2 +validate 4 + +aarch64 = usqadd +generate u8:i8:u8, u16:i16:u16 + +/// Unsigned saturating accumulate of signed value +name = vsqadd +out-suffix +a = 2 +b = 2 +validate 4 + +aarch64 = usqadd +link-aarch64 = usqadd._EXT_ +generate u32:i32:u32, u64:i64:u64 + /// Calculates the square root of each lane. name = vsqrt fn = simd_fsqrt @@ -4499,10 +6153,35 @@ validate 0.998046875, 0.705078125, 0.576171875, 0.4990234375 aarch64 = frsqrte link-aarch64 = frsqrte._EXT_ -generate float64x*_t +generate float64x*_t, f32, f64 + +arm = vrsqrte +link-arm = vrsqrte._EXT_ +generate float*_t + +/// Unsigned reciprocal square root estimate +name = vrsqrte +a = 1, 2, 3, 4 +validate 4294967295, 4294967295, 4294967295, 4294967295 +aarch64 = ursqrte +link-aarch64 = ursqrte._EXT_ arm = vrsqrte link-arm = vrsqrte._EXT_ +generate uint32x2_t, uint32x4_t + +/// Floating-point reciprocal square root step +name = vrsqrts +a = 1.0, 2.0, 3.0, 4.0 +b = 1.0, 2.0, 3.0, 4.0 +validate 1., -0.5, -3.0, -6.5 + +aarch64 = frsqrts +link-aarch64 = frsqrts._EXT_ +generate float64x*_t, f32, f64 + +arm = vrsqrts +link-arm = vrsqrts._EXT_ generate float*_t /// Reciprocal estimate. @@ -4512,12 +6191,46 @@ validate 0.24951171875, 0.3330078125, 0.4990234375, 0.998046875 aarch64 = frecpe link-aarch64 = frecpe._EXT_ -generate float64x*_t +generate float64x*_t, f32, f64 arm = vrecpe link-arm = vrecpe._EXT_ generate float*_t +/// Unsigned reciprocal estimate +name = vrecpe +a = 4, 3, 2, 1 +validate 4294967295, 4294967295, 4294967295, 4294967295 + +aarch64 = urecpe +link-aarch64 = urecpe._EXT_ +arm = vrecpe +link-arm = vrecpe._EXT_ +generate uint32x2_t, uint32x4_t + +/// Floating-point reciprocal step +name = vrecps +a = 4.0, 3.0, 2.0, 1.0 +b = 4.0, 3.0, 2.0, 1.0 +validate -14., -7., -2., 1. + +aarch64 = frecps +link-aarch64 = frecps._EXT_ +generate float64x*_t, f32, f64 + +arm = vrecps +link-arm = vrecps._EXT_ +generate float*_t + +/// Floating-point reciprocal exponent +name = vrecpx +a = 4.0 +validate 0.5 + +aarch64 = frecpx +link-aarch64 = frecpx._EXT_ +generate f32, f64 + /// Vector reinterpret cast operation name = vreinterpret double-suffixes @@ -4545,9 +6258,6 @@ a = 0, 1, 2, 3, 4, 5, 6, 7 validate 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0 aarch64 = nop -generate poly64x1_t:int32x2_t, poly64x1_t:uint32x2_t -generate poly64x2_t:int32x4_t, poly64x2_t:uint32x4_t - arm = nop generate int16x4_t:int8x8_t, uint16x4_t:int8x8_t, poly16x4_t:int8x8_t, int32x2_t:int16x4_t, uint32x2_t:int16x4_t, int64x1_t:int32x2_t, uint64x1_t:int32x2_t generate int16x8_t:int8x16_t, uint16x8_t:int8x16_t, poly16x8_t:int8x16_t, int32x4_t:int16x8_t, uint32x4_t:int16x8_t, int64x2_t:int32x4_t, uint64x2_t:int32x4_t @@ -4555,6 +6265,10 @@ generate poly16x4_t:uint8x8_t, int16x4_t:uint8x8_t, uint16x4_t:uint8x8_t, int32x generate poly16x8_t:uint8x16_t, int16x8_t:uint8x16_t, uint16x8_t:uint8x16_t, int32x4_t:uint16x8_t, uint32x4_t:uint16x8_t, int64x2_t:uint32x4_t, uint64x2_t:uint32x4_t generate poly16x4_t:poly8x8_t, int16x4_t:poly8x8_t, uint16x4_t:poly8x8_t, int32x2_t:poly16x4_t, uint32x2_t:poly16x4_t generate poly16x8_t:poly8x16_t, int16x8_t:poly8x16_t, uint16x8_t:poly8x16_t, int32x4_t:poly16x8_t, uint32x4_t:poly16x8_t +target = aes +generate poly64x1_t:int32x2_t, poly64x1_t:uint32x2_t +generate poly64x2_t:int32x4_t, poly64x2_t:uint32x4_t +generate p128:int64x2_t, p128:uint64x2_t, p128:poly64x2_t /// Vector reinterpret cast operation name = vreinterpret @@ -4564,9 +6278,6 @@ a = 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0 validate 0, 1, 2, 3, 4, 5, 6, 7 aarch64 = nop -generate int32x2_t:poly64x1_t, uint32x2_t:poly64x1_t -generate int32x4_t:poly64x2_t, uint32x4_t:poly64x2_t - arm = nop generate poly8x8_t:int16x4_t, int8x8_t:int16x4_t, uint8x8_t:int16x4_t, poly16x4_t:int32x2_t, int16x4_t:int32x2_t, uint16x4_t:int32x2_t, int32x2_t:int64x1_t, uint32x2_t:int64x1_t generate poly8x16_t:int16x8_t, int8x16_t:int16x8_t, uint8x16_t:int16x8_t, poly16x8_t:int32x4_t, int16x8_t:int32x4_t, uint16x8_t:int32x4_t, int32x4_t:int64x2_t, uint32x4_t:int64x2_t @@ -4574,6 +6285,10 @@ generate poly8x8_t:uint16x4_t, int8x8_t:uint16x4_t, uint8x8_t:uint16x4_t, poly16 generate poly8x16_t:uint16x8_t, int8x16_t:uint16x8_t, uint8x16_t:uint16x8_t, poly16x8_t:uint32x4_t, int16x8_t:uint32x4_t, uint16x8_t:uint32x4_t, int32x4_t:uint64x2_t, uint32x4_t:uint64x2_t generate poly8x8_t:poly16x4_t, int8x8_t:poly16x4_t, uint8x8_t:poly16x4_t generate poly8x16_t:poly16x8_t, int8x16_t:poly16x8_t, uint8x16_t:poly16x8_t +target = aes +generate int32x2_t:poly64x1_t, uint32x2_t:poly64x1_t +generate int32x4_t:poly64x2_t, uint32x4_t:poly64x2_t +generate int64x2_t:p128, uint64x2_t:p128, poly64x2_t:p128 /// Vector reinterpret cast operation name = vreinterpret @@ -4583,9 +6298,6 @@ a = 0, 1, 2, 3 validate 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0 aarch64 = nop -generate poly64x1_t:int16x4_t, poly64x1_t:uint16x4_t, poly64x1_t:poly16x4_t -generate poly64x2_t:int16x8_t, poly64x2_t:uint16x8_t, poly64x2_t:poly16x8_t - arm = nop generate int32x2_t:int8x8_t, uint32x2_t:int8x8_t, int64x1_t:int16x4_t, uint64x1_t:int16x4_t generate int32x4_t:int8x16_t, uint32x4_t:int8x16_t, int64x2_t:int16x8_t, uint64x2_t:int16x8_t @@ -4593,6 +6305,10 @@ generate int32x2_t:uint8x8_t, uint32x2_t:uint8x8_t, int64x1_t:uint16x4_t, uint64 generate int32x4_t:uint8x16_t, uint32x4_t:uint8x16_t, int64x2_t:uint16x8_t, uint64x2_t:uint16x8_t generate int32x2_t:poly8x8_t, uint32x2_t:poly8x8_t, int64x1_t:poly16x4_t, uint64x1_t:poly16x4_t generate int32x4_t:poly8x16_t, uint32x4_t:poly8x16_t, int64x2_t:poly16x8_t, uint64x2_t:poly16x8_t +target = aes +generate poly64x1_t:int16x4_t, poly64x1_t:uint16x4_t, poly64x1_t:poly16x4_t +generate poly64x2_t:int16x8_t, poly64x2_t:uint16x8_t, poly64x2_t:poly16x8_t +generate p128:int32x4_t, p128:uint32x4_t /// Vector reinterpret cast operation name = vreinterpret @@ -4602,14 +6318,15 @@ a = 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0 validate 0, 1, 2, 3 aarch64 = nop -generate poly16x4_t:poly64x1_t, int16x4_t:poly64x1_t, uint16x4_t:poly64x1_t -generate poly16x8_t:poly64x2_t, int16x8_t:poly64x2_t, uint16x8_t:poly64x2_t - arm = nop generate poly8x8_t:int32x2_t, int8x8_t:int32x2_t, uint8x8_t:int32x2_t, poly16x4_t:int64x1_t, int16x4_t:int64x1_t, uint16x4_t:int64x1_t generate poly8x16_t:int32x4_t, int8x16_t:int32x4_t, uint8x16_t:int32x4_t, poly16x8_t:int64x2_t, int16x8_t:int64x2_t, uint16x8_t:int64x2_t generate poly8x8_t:uint32x2_t, int8x8_t:uint32x2_t, uint8x8_t:uint32x2_t, poly16x4_t:uint64x1_t, int16x4_t:uint64x1_t, uint16x4_t:uint64x1_t generate poly8x16_t:uint32x4_t, int8x16_t:uint32x4_t, uint8x16_t:uint32x4_t, poly16x8_t:uint64x2_t, int16x8_t:uint64x2_t, uint16x8_t:uint64x2_t +target = aes +generate poly16x4_t:poly64x1_t, int16x4_t:poly64x1_t, uint16x4_t:poly64x1_t +generate poly16x8_t:poly64x2_t, int16x8_t:poly64x2_t, uint16x8_t:poly64x2_t +generate int32x4_t:p128, uint32x4_t:p128 /// Vector reinterpret cast operation name = vreinterpret @@ -4619,12 +6336,13 @@ a = 0, 1 validate 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 aarch64 = nop -generate poly64x1_t:int8x8_t, poly64x1_t:uint8x8_t, poly64x1_t:poly8x8_t -generate poly64x2_t:int8x16_t, poly64x2_t:uint8x16_t, poly64x2_t:poly8x16_t - arm = nop generate int64x1_t:int8x8_t, uint64x1_t:int8x8_t, int64x1_t:uint8x8_t, uint64x1_t:uint8x8_t, int64x1_t:poly8x8_t, uint64x1_t:poly8x8_t generate int64x2_t:int8x16_t, uint64x2_t:int8x16_t, int64x2_t:uint8x16_t, uint64x2_t:uint8x16_t, int64x2_t:poly8x16_t, uint64x2_t:poly8x16_t +target = aes +generate poly64x1_t:int8x8_t, poly64x1_t:uint8x8_t, poly64x1_t:poly8x8_t +generate poly64x2_t:int8x16_t, poly64x2_t:uint8x16_t, poly64x2_t:poly8x16_t +generate p128:int16x8_t, p128:uint16x8_t, p128:poly16x8_t /// Vector reinterpret cast operation name = vreinterpret @@ -4634,12 +6352,37 @@ a = 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 validate 0, 1 aarch64 = nop +arm = nop +generate poly8x8_t:int64x1_t, int8x8_t:int64x1_t, uint8x8_t:int64x1_t, poly8x8_t:uint64x1_t, int8x8_t:uint64x1_t, uint8x8_t:uint64x1_t +generate poly8x16_t:int64x2_t, int8x16_t:int64x2_t, uint8x16_t:int64x2_t, poly8x16_t:uint64x2_t, int8x16_t:uint64x2_t, uint8x16_t:uint64x2_t +target = aes generate poly8x8_t:poly64x1_t, int8x8_t:poly64x1_t, uint8x8_t:poly64x1_t generate poly8x16_t:poly64x2_t, int8x16_t:poly64x2_t, uint8x16_t:poly64x2_t +generate int16x8_t:p128, uint16x8_t:p128, poly16x8_t:p128 + +/// Vector reinterpret cast operation +name = vreinterpret +double-suffixes +fn = transmute +a = 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +validate 1 +target = aes +aarch64 = nop arm = nop -generate poly8x8_t:int64x1_t, int8x8_t:int64x1_t, uint8x8_t:int64x1_t, poly8x8_t:uint64x1_t, int8x8_t:uint64x1_t, uint8x8_t:uint64x1_t -generate poly8x16_t:int64x2_t, int8x16_t:int64x2_t, uint8x16_t:int64x2_t, poly8x16_t:uint64x2_t, int8x16_t:uint64x2_t, uint8x16_t:uint64x2_t +generate int8x16_t:p128, uint8x16_t:p128, poly8x16_t:p128 + +/// Vector reinterpret cast operation +name = vreinterpret +double-suffixes +fn = transmute +a = 1 +validate 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +target = aes + +aarch64 = nop +arm = nop +generate p128:int8x16_t, p128:uint8x16_t, p128:poly8x16_t /// Vector reinterpret cast operation name = vreinterpret @@ -4655,6 +6398,7 @@ generate float64x1_t:uint8x8_t, float64x1_t:uint16x4_t, float64x1_t:uint32x2_t, generate float64x2_t:uint8x16_t, float64x2_t:uint16x8_t, float64x2_t:uint32x4_t, float64x2_t:uint64x2_t generate float64x1_t:poly8x8_t, float64x1_t:poly16x4_t, float32x2_t:poly64x1_t, float64x1_t:poly64x1_t generate float64x2_t:poly8x16_t, float64x2_t:poly16x8_t, float32x4_t:poly64x2_t, float64x2_t:poly64x2_t +generate float64x2_t:p128 arm = nop generate float32x2_t:int8x8_t, float32x2_t:int16x4_t, float32x2_t:int32x2_t, float32x2_t:int64x1_t @@ -4663,6 +6407,7 @@ generate float32x2_t:uint8x8_t, float32x2_t:uint16x4_t, float32x2_t:uint32x2_t, generate float32x4_t:uint8x16_t, float32x4_t:uint16x8_t, float32x4_t:uint32x4_t, float32x4_t:uint64x2_t generate float32x2_t:poly8x8_t, float32x2_t:poly16x4_t generate float32x4_t:poly8x16_t, float32x4_t:poly16x8_t +generate float32x4_t:p128 /// Vector reinterpret cast operation name = vreinterpret @@ -4678,6 +6423,7 @@ generate poly8x8_t:float64x1_t, uint16x4_t:float64x1_t, uint32x2_t:float64x1_t, generate poly8x16_t:float64x2_t, uint16x8_t:float64x2_t, uint32x4_t:float64x2_t, uint64x2_t:float64x2_t generate uint8x8_t:float64x1_t, poly16x4_t:float64x1_t, poly64x1_t:float64x1_t, poly64x1_t:float32x2_t generate uint8x16_t:float64x2_t, poly16x8_t:float64x2_t, poly64x2_t:float64x2_t, poly64x2_t:float32x4_t +generate p128:float64x2_t arm = nop generate int8x8_t:float32x2_t, int16x4_t:float32x2_t, int32x2_t:float32x2_t, int64x1_t:float32x2_t @@ -4686,6 +6432,7 @@ generate uint8x8_t:float32x2_t, uint16x4_t:float32x2_t, uint32x2_t:float32x2_t, generate uint8x16_t:float32x4_t, uint16x8_t:float32x4_t, uint32x4_t:float32x4_t, uint64x2_t:float32x4_t generate poly8x8_t:float32x2_t, poly16x4_t:float32x2_t generate poly8x16_t:float32x4_t, poly16x8_t:float32x4_t +generate p128:float32x4_t /// Vector reinterpret cast operation name = vreinterpret @@ -4890,6 +6637,45 @@ validate 2 aarch64 = ursra generate u64 +/// Rounding subtract returning high narrow +name = vrsubhn +no-q +a = MAX, MIN, 0, 4, 5, 6, 7, 8 +b = 1, 2, 3, 4, 5, 6, 7, 8 +validate MIN, MIN, 0, 0, 0, 0, 0, 0 + +aarch64 = rsubhn +link-aarch64 = rsubhn._EXT2_ +arm = vrsubhn +link-arm = vrsubhn._EXT2_ +generate int16x8_t:int16x8_t:int8x8_t, int32x4_t:int32x4_t:int16x4_t, int64x2_t:int64x2_t:int32x2_t + +/// Rounding subtract returning high narrow +name = vrsubhn +no-q +multi_fn = transmute, {vrsubhn-noqsigned-noext, {transmute, a}, {transmute, b}} +a = MAX, MIN, 3, 4, 5, 6, 7, 8 +b = 1, 2, 3, 4, 5, 6, 7, 8 +validate 0, 0, 0, 0, 0, 0, 0, 0 + +aarch64 = rsubhn +arm = vrsubhn +generate uint16x8_t:uint16x8_t:uint8x8_t, uint32x4_t:uint32x4_t:uint16x4_t, uint64x2_t:uint64x2_t:uint32x2_t + +/// Rounding subtract returning high narrow +name = vrsubhn_high +no-q +multi_fn = vrsubhn-noqself-noext, x:in_t0, b, c +multi_fn = simd_shuffle-out_len-!, a, x, {asc-0-out_len} +a = 1, 2, 0, 0, 0, 0, 0, 0 +b = 1, 2, 3, 4, 5, 6, 7, 8 +c = 1, 2, 3, 4, 5, 6, 7, 8 +validate 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + +aarch64 = rsubhn2 +generate int8x8_t:int16x8_t:int16x8_t:int8x16_t, int16x4_t:int32x4_t:int32x4_t:int16x8_t, int32x2_t:int64x2_t:int64x2_t:int32x4_t +generate uint8x8_t:uint16x8_t:uint16x8_t:uint8x16_t, uint16x4_t:uint32x4_t:uint32x4_t:uint16x8_t, uint32x2_t:uint64x2_t:uint64x2_t:uint32x4_t + /// Insert vector element from another vector element name = vset_lane constn = LANE @@ -5064,7 +6850,8 @@ name = vshr n-suffix constn = N multi_fn = static_assert-N-1-bits -multi_fn = simd_shr, a, {vdup-nself-noext, N.try_into().unwrap()} +multi_fn = fix_right_shift_imm-N-bits +multi_fn = simd_shr, a, {vdup-nself-noext, n.try_into().unwrap()} a = 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64 n = 2 validate 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 @@ -5135,6 +6922,194 @@ aarch64 = usra arm = vsra generate uint*_t, uint64x*_t +/// SM3PARTW1 +name = vsm3partw1 +a = 1, 2, 3, 4 +b = 1, 2, 3, 4 +c = 1, 2, 3, 4 +validate 2147549312, 3221323968, 131329, 2684362752 +target = sm4 + +aarch64 = sm3partw1 +link-aarch64 = llvm.aarch64.crypto.sm3partw1 +generate uint32x4_t + +/// SM3PARTW2 +name = vsm3partw2 +a = 1, 2, 3, 4 +b = 1, 2, 3, 4 +c = 1, 2, 3, 4 +validate 128, 256, 384, 1077977696 +target = sm4 + +aarch64 = sm3partw2 +link-aarch64 = llvm.aarch64.crypto.sm3partw2 +generate uint32x4_t + +/// SM3SS1 +name = vsm3ss1 +a = 1, 2, 3, 4 +b = 1, 2, 3, 4 +c = 1, 2, 3, 4 +validate 0, 0, 0, 2098176 +target = sm4 + +aarch64 = sm3ss1 +link-aarch64 = llvm.aarch64.crypto.sm3ss1 +generate uint32x4_t + +/// SM4 key +name = vsm4ekey +a = 1, 2, 3, 4 +b = 1, 2, 3, 4 +validate 1784948604, 136020997, 2940231695, 3789947679 +target = sm4 + +aarch64 = sm4ekey +link-aarch64 = llvm.aarch64.crypto.sm4ekey +generate uint32x4_t + +/// SM4 encode +name = vsm4e +a = 1, 2, 3, 4 +b = 1, 2, 3, 4 +validate 1093874472, 3616769504, 3878330411, 2765298765 +target = sm4 + +aarch64 = sm4e +link-aarch64 = llvm.aarch64.crypto.sm4e +generate uint32x4_t + +/// Rotate and exclusive OR +name = vrax1 +a = 1, 2 +b = 3, 4 +validate 7, 10 +target = sha3 + +aarch64 = rax1 +link-aarch64 = llvm.aarch64.crypto.rax1 +generate uint64x2_t + +/// SHA512 hash update part 1 +name = vsha512h +a = 1, 2 +b = 3, 4 +c = 5, 6 +validate 11189044327219203, 7177611956453380 +target = sha3 + +aarch64 = sha512h +link-aarch64 = llvm.aarch64.crypto.sha512h +generate uint64x2_t + +/// SHA512 hash update part 2 +name = vsha512h2 +a = 1, 2 +b = 3, 4 +c = 5, 6 +validate 5770237651009406214, 349133864969 +target = sha3 + +aarch64 = sha512h2 +link-aarch64 = llvm.aarch64.crypto.sha512h2 +generate uint64x2_t + +/// SHA512 schedule update 0 +name = vsha512su0 +a = 1, 2 +b = 3, 4 +validate 144115188075855874, 9439544818968559619 +target = sha3 + +aarch64 = sha512su0 +link-aarch64 = llvm.aarch64.crypto.sha512su0 +generate uint64x2_t + +/// SHA512 schedule update 1 +name = vsha512su1 +a = 1, 2 +b = 3, 4 +c = 5, 6 +validate 105553116266526, 140737488355368 +target = sha3 + +aarch64 = sha512su1 +link-aarch64 = llvm.aarch64.crypto.sha512su1 +generate uint64x2_t + +/// Floating-point round to 32-bit integer, using current rounding mode +name = vrnd32x +a = 1.1, 1.9, -1.7, -2.3 +validate 1.0, 2.0, -2.0, -2.0 +target = frintts + +aarch64 = frint32x +link-aarch64 = frint32x._EXT_ +generate float32x2_t, float32x4_t + +/// Floating-point round to 32-bit integer toward zero +name = vrnd32z +a = 1.1, 1.9, -1.7, -2.3 +validate 1.0, 1.0, -1.0, -2.0 +target = frintts + +aarch64 = frint32z +link-aarch64 = frint32z._EXT_ +generate float32x2_t, float32x4_t + +/// Floating-point round to 64-bit integer, using current rounding mode +name = vrnd64x +a = 1.1, 1.9, -1.7, -2.3 +validate 1.0, 2.0, -2.0, -2.0 +target = frintts + +aarch64 = frint64x +link-aarch64 = frint64x._EXT_ +generate float32x2_t, float32x4_t + +/// Floating-point round to 64-bit integer toward zero +name = vrnd64z +a = 1.1, 1.9, -1.7, -2.3 +validate 1.0, 1.0, -1.0, -2.0 +target = frintts + +aarch64 = frint64z +link-aarch64 = frint64z._EXT_ +generate float32x2_t, float32x4_t + +/// Transpose elements +name = vtrn +multi_fn = simd_shuffle-in_len-!, a1:in_t, a, b, {transpose-1-in_len} +multi_fn = simd_shuffle-in_len-!, b1:in_t, a, b, {transpose-2-in_len} +multi_fn = transmute, (a1, b1) +a = 0, 2, 2, 6, 2, 10, 6, 14, 2, 18, 6, 22, 10, 26, 14, 30 +b = 1, 3, 3, 7, 3, 1, 7, 15, 3, 19, 7, 23, 1, 27, 15, 31 +validate 0, 1, 2, 3, 2, 3, 6, 7, 2, 3, 6, 7, 10, 1, 14, 15, 2, 3, 6, 7, 10, 1, 14, 15, 18, 19, 22, 23, 26, 27, 30, 31 + +aarch64 = trn +arm = vtrn +generate int8x8_t:int8x8_t:int8x8x2_t, int16x4_t:int16x4_t:int16x4x2_t, int8x16_t:int8x16_t:int8x16x2_t, int16x8_t:int16x8_t:int16x8x2_t, int32x4_t:int32x4_t:int32x4x2_t +generate uint8x8_t:uint8x8_t:uint8x8x2_t, uint16x4_t:uint16x4_t:uint16x4x2_t, uint8x16_t:uint8x16_t:uint8x16x2_t, uint16x8_t:uint16x8_t:uint16x8x2_t, uint32x4_t:uint32x4_t:uint32x4x2_t +generate poly8x8_t:poly8x8_t:poly8x8x2_t, poly16x4_t:poly16x4_t:poly16x4x2_t, poly8x16_t:poly8x16_t:poly8x16x2_t, poly16x8_t:poly16x8_t:poly16x8x2_t +aarch64 = zip +generate int32x2_t:int32x2_t:int32x2x2_t, uint32x2_t:uint32x2_t:uint32x2x2_t + +/// Transpose elements +name = vtrn +multi_fn = simd_shuffle-in_len-!, a1:in_t, a, b, {transpose-1-in_len} +multi_fn = simd_shuffle-in_len-!, b1:in_t, a, b, {transpose-2-in_len} +multi_fn = transmute, (a1, b1) +a = 0., 2., 2., 6. +b = 1., 3., 3., 7. +validate 0., 1., 2., 3., 2., 3., 6., 7. + +aarch64 = zip +arm = vtrn +generate float32x2_t:float32x2_t:float32x2x2_t +aarch64 = trn +generate float32x4_t:float32x4_t:float32x4x2_t + /// Transpose vectors name = vtrn1 multi_fn = simd_shuffle-in_len-!, a, b, {transpose-1-in_len} @@ -5187,6 +7162,44 @@ generate float32x4_t aarch64 = zip2 generate float32x2_t, float64x2_t +/// Zip vectors +name = vzip +multi_fn = simd_shuffle-in_len-!, a0:in_t, a, b, {zip-1-in_len} +multi_fn = simd_shuffle-in_len-!, b0:in_t, a, b, {zip-2-in_len} +multi_fn = transmute, (a0, b0) +a = 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 +b = 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31 +validate 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 + +aarch64 = zip +arm = vzip +generate int8x8_t:int8x8_t:int8x8x2_t, int16x4_t:int16x4_t:int16x4x2_t +generate uint8x8_t:uint8x8_t:uint8x8x2_t, uint16x4_t:uint16x4_t:uint16x4x2_t +generate poly8x8_t:poly8x8_t:poly8x8x2_t, poly16x4_t:poly16x4_t:poly16x4x2_t +arm = vtrn +generate int32x2_t:int32x2_t:int32x2x2_t, uint32x2_t:uint32x2_t:uint32x2x2_t +aarch64 = ext +arm = vorr +generate int8x16_t:int8x16_t:int8x16x2_t, int16x8_t:int16x8_t:int16x8x2_t, int32x4_t:int32x4_t:int32x4x2_t +generate uint8x16_t:uint8x16_t:uint8x16x2_t, uint16x8_t:uint16x8_t:uint16x8x2_t, uint32x4_t:uint32x4_t:uint32x4x2_t +generate poly8x16_t:poly8x16_t:poly8x16x2_t, poly16x8_t:poly16x8_t:poly16x8x2_t + +/// Zip vectors +name = vzip +multi_fn = simd_shuffle-in_len-!, a0:in_t, a, b, {zip-1-in_len} +multi_fn = simd_shuffle-in_len-!, b0:in_t, a, b, {zip-2-in_len} +multi_fn = transmute, (a0, b0) +a = 1., 2., 3., 4. +b = 5., 6., 7., 8. +validate 1., 5., 2., 6., 3., 7., 4., 8. + +aarch64 = zip +arm = vtrn +generate float32x2_t:float32x2_t:float32x2x2_t +aarch64 = ext +arm = vorr +generate float32x4_t:float32x4_t:float32x4x2_t + /// Zip vectors name = vzip1 multi_fn = simd_shuffle-in_len-!, a, b, {zip-1-in_len} @@ -5227,6 +7240,40 @@ validate 8., 9., 10., 11., 12., 13., 14., 15. aarch64 = zip2 generate float32x2_t, float32x4_t, float64x2_t +/// Unzip vectors +name = vuzp +multi_fn = simd_shuffle-in_len-!, a0:in_t, a, b, {unzip-1-in_len} +multi_fn = simd_shuffle-in_len-!, b0:in_t, a, b, {unzip-2-in_len} +multi_fn = transmute, (a0, b0) +a = 1, 2, 2, 3, 2, 3, 3, 8, 2, 3, 3, 8, 3, 15, 8, 16 +b = 2, 3, 3, 8, 3, 15, 8, 16, 3, 29, 8, 30, 15, 31, 16, 32 +validate 1, 2, 2, 3, 2, 3, 3, 8, 2, 3, 3, 8, 3, 8, 15, 16, 2, 3, 3, 8, 3, 8, 15, 16, 3, 8, 15, 16, 29, 30, 31, 32 + +aarch64 = uzp +arm = vuzp +generate int8x8_t:int8x8_t:int8x8x2_t, int16x4_t:int16x4_t:int16x4x2_t, int8x16_t:int8x16_t:int8x16x2_t, int16x8_t:int16x8_t:int16x8x2_t, int32x4_t:int32x4_t:int32x4x2_t +generate uint8x8_t:uint8x8_t:uint8x8x2_t, uint16x4_t:uint16x4_t:uint16x4x2_t, uint8x16_t:uint8x16_t:uint8x16x2_t, uint16x8_t:uint16x8_t:uint16x8x2_t, uint32x4_t:uint32x4_t:uint32x4x2_t +generate poly8x8_t:poly8x8_t:poly8x8x2_t, poly16x4_t:poly16x4_t:poly16x4x2_t, poly8x16_t:poly8x16_t:poly8x16x2_t, poly16x8_t:poly16x8_t:poly16x8x2_t +aarch64 = zip +arm = vtrn +generate int32x2_t:int32x2_t:int32x2x2_t, uint32x2_t:uint32x2_t:uint32x2x2_t + +/// Unzip vectors +name = vuzp +multi_fn = simd_shuffle-in_len-!, a0:in_t, a, b, {unzip-1-in_len} +multi_fn = simd_shuffle-in_len-!, b0:in_t, a, b, {unzip-2-in_len} +multi_fn = transmute, (a0, b0) +a = 1., 2., 2., 4. +b = 2., 6., 6., 8. +validate 1., 2., 2., 6., 2., 4., 6., 8. + +aarch64 = zip +arm = vtrn +generate float32x2_t:float32x2_t:float32x2x2_t +aarch64 = uzp +arm = vuzp +generate float32x4_t:float32x4_t:float32x4x2_t + /// Unzip vectors name = vuzp1 multi_fn = simd_shuffle-in_len-!, a, b, {unzip-1-in_len} @@ -5458,3 +7505,49 @@ validate MAX, 7 aarch64 = sqabs link-aarch64 = sqabs._EXT_ generate int64x*_t + +/// Signed saturating absolute value +name = vqabs +multi_fn = simd_extract, {vqabs-in_ntt-noext, {vdup_n-in_ntt-noext, a}}, 0 +a = -7 +validate 7 + +aarch64 = sqabs +generate i8:i8, i16:i16 + +/// Signed saturating absolute value +name = vqabs +a = -7 +validate 7 + +aarch64 = sqabs +link-aarch64 = sqabs._EXT_ +generate i32:i32, i64:i64 + +/// Shift left and insert +name = vsli +n-suffix +constn = N +multi_fn = static_assert-N-0-63 +multi_fn = transmute, {vsli_n-in_ntt-::, transmute(a), transmute(b)} +a = 333 +b = 2042 +n = 2 +validate 8169 + +aarch64 = sli +generate i64, u64 + +/// Shift right and insert +name = vsri +n-suffix +constn = N +multi_fn = static_assert-N-1-bits +multi_fn = transmute, {vsri_n-in_ntt-::, transmute(a), transmute(b)} +a = 333 +b = 2042 +n = 2 +validate 510 + +aarch64 = sri +generate i64, u64 \ No newline at end of file diff --git a/library/stdarch/crates/stdarch-gen/src/main.rs b/library/stdarch/crates/stdarch-gen/src/main.rs index 35ed3308dc..2142e7a5a0 100644 --- a/library/stdarch/crates/stdarch-gen/src/main.rs +++ b/library/stdarch/crates/stdarch-gen/src/main.rs @@ -96,9 +96,9 @@ fn type_bits(t: &str) -> usize { } } -fn type_exp_len(t: &str) -> usize { +fn type_exp_len(t: &str, base_len: usize) -> usize { let t = type_to_sub_type(t); - let len = type_len(&t); + let len = type_len(&t) / base_len; match len { 1 => 0, 2 => 1, @@ -242,6 +242,7 @@ fn type_to_suffix(t: &str) -> &str { "f64" => "d_f64", "p8" => "b_p8", "p16" => "h_p16", + "p128" => "q_p128", _ => panic!("unknown type: {}", t), } } @@ -328,35 +329,48 @@ fn type_to_noq_n_suffix(t: &str) -> &str { } } -fn type_to_lane_suffixes<'a>(out_t: &'a str, in_t: &'a str) -> String { +fn type_to_lane_suffixes<'a>(out_t: &'a str, in_t: &'a str, re_to_out: bool) -> String { let mut str = String::new(); let suf = type_to_suffix(out_t); if !suf.starts_with("_") { str.push_str(&suf[0..1]); } str.push_str("_lane"); - str.push_str(type_to_suffix(in_t)); + if !re_to_out { + str.push_str(type_to_suffix(in_t)); + } else { + if type_to_suffix(in_t).starts_with("q") { + str.push_str("q"); + }; + let suf2 = type_to_noq_suffix(out_t); + str.push_str(suf2); + } str } -fn type_to_signed(t: &String) -> String { +fn type_to_rot_suffix(c_name: &str, suf: &str) -> String { + let ns: Vec<_> = c_name.split('_').collect(); + assert_eq!(ns.len(), 2); + if suf.starts_with("q") { + format!("{}q_{}{}", ns[0], ns[1], &suf[1..]) + } else { + format!("{}{}", c_name, suf) + } +} + +fn type_to_signed(t: &str) -> String { let s = t.replace("uint", "int"); let s = s.replace("poly", "int"); s } -fn type_to_unsigned(t: &str) -> &str { - match t { - "int8x8_t" | "uint8x8_t" | "poly8x8_t" => "uint8x8_t", - "int8x16_t" | "uint8x16_t" | "poly8x16_t" => "uint8x16_t", - "int16x4_t" | "uint16x4_t" | "poly16x4_t" => "uint16x4_t", - "int16x8_t" | "uint16x8_t" | "poly16x8_t" => "uint16x8_t", - "int32x2_t" | "uint32x2_t" => "uint32x2_t", - "int32x4_t" | "uint32x4_t" => "uint32x4_t", - "int64x1_t" | "uint64x1_t" | "poly64x1_t" => "uint64x1_t", - "int64x2_t" | "uint64x2_t" | "poly64x2_t" => "uint64x2_t", - _ => panic!("unknown type: {}", t), +fn type_to_unsigned(t: &str) -> String { + if t.contains("uint") { + return t.to_string(); } + let s = t.replace("int", "uint"); + let s = s.replace("poly", "uint"); + s } fn type_to_double_suffixes<'a>(out_t: &'a str, in_t: &'a str) -> String { @@ -411,6 +425,7 @@ fn type_to_noq_suffix(t: &str) -> &str { "poly8x8_t" | "poly8x16_t" => "_p8", "poly16x4_t" | "poly16x8_t" => "_p16", "poly64x1_t" | "poly64x2_t" | "p64" => "_p64", + "p128" => "_p128", _ => panic!("unknown type: {}", t), } } @@ -427,11 +442,16 @@ enum Suffix { OutSuffix, OutNSuffix, OutNox, + In1Nox, OutDupNox, OutLaneNox, + In1LaneNox, Lane, In2, In2Lane, + OutLane, + Rot, + RotLane, } #[derive(Clone, Copy)] @@ -441,6 +461,13 @@ enum TargetFeature { Vfp4, FPArmV8, AES, + FCMA, + Dotprod, + I8MM, + SHA3, + RDM, + SM4, + FTTS, } #[derive(Clone, Copy)] @@ -657,16 +684,30 @@ fn values(t: &str, vs: &[String]) -> String { } else if vs.len() == 1 && type_to_global_type(t) == "f64" { format!(": {} = {}", type_to_global_type(t), vs[0]) } else { - format!( - ": {} = {}::new({})", - type_to_global_type(t), - type_to_global_type(t), - vs.iter() - .map(|v| map_val(type_to_global_type(t), v)) - //.map(|v| format!("{}{}", v, type_to_native_type(t))) - .collect::>() - .join(", ") - ) + let s: Vec<_> = t.split('x').collect(); + if s.len() == 3 { + format!( + ": [{}; {}] = [{}]", + type_to_native_type(t), + type_len(t), + vs.iter() + .map(|v| map_val(type_to_global_type(t), v)) + //.map(|v| format!("{}{}", v, type_to_native_type(t))) + .collect::>() + .join(", ") + ) + } else { + format!( + ": {} = {}::new({})", + type_to_global_type(t), + type_to_global_type(t), + vs.iter() + .map(|v| map_val(type_to_global_type(t), v)) + //.map(|v| format!("{}{}", v, type_to_native_type(t))) + .collect::>() + .join(", ") + ) + } } } @@ -907,9 +948,27 @@ fn ext(s: &str, in_t: &[&str; 3], out_t: &str) -> String { s.replace("_EXT_", &type_to_ext(in_t[0], false, false, false)) .replace("_EXT2_", &type_to_ext(out_t, false, false, false)) .replace("_EXT3_", &type_to_ext(in_t[1], false, false, false)) + .replace("_EXT4_", &type_to_ext(in_t[2], false, false, false)) .replace("_EXTr3_", &type_to_ext(in_t[1], false, true, false)) .replace("_EXTv2_", &type_to_ext(out_t, true, false, false)) + .replace("_EXTpi8_", &type_to_ext(in_t[1], false, false, true)) .replace("_EXTpi82_", &type_to_ext(out_t, false, false, true)) + .replace("_EXTpi8r_", &type_to_ext(in_t[1], false, true, true)) +} + +fn is_vldx(name: &str) -> bool { + let s: Vec<_> = name.split('_').collect(); + &name[0..3] == "vld" + && name[3..4].parse::().unwrap() > 1 + && (s.last().unwrap().starts_with("s") || s.last().unwrap().starts_with("f")) +} + +fn is_vstx(name: &str) -> bool { + let s: Vec<_> = name.split('_').collect(); + s.len() == 2 + && &name[0..3] == "vst" + && name[3..4].parse::().unwrap() > 1 + && (s[1].starts_with("s") || s[1].starts_with("f")) } #[allow(clippy::too_many_arguments)] @@ -964,6 +1023,11 @@ fn gen_aarch64( current_name, type_to_suffix(&type_to_sub_type(out_t)) ), + In1Nox => format!( + "{}{}", + current_name, + type_to_suffix(&type_to_sub_type(in_t[1])) + ), OutDupNox => format!( "{}{}", current_name, @@ -974,9 +1038,29 @@ fn gen_aarch64( current_name, type_to_lane_suffix(&type_to_sub_type(out_t)) ), - Lane => format!("{}{}", current_name, type_to_lane_suffixes(out_t, in_t[1])), + In1LaneNox => format!( + "{}{}", + current_name, + type_to_lane_suffix(&type_to_sub_type(in_t[1])) + ), + Lane => format!( + "{}{}", + current_name, + type_to_lane_suffixes(out_t, in_t[1], false) + ), In2 => format!("{}{}", current_name, type_to_suffix(in_t[2])), - In2Lane => format!("{}{}", current_name, type_to_lane_suffixes(out_t, in_t[2])), + In2Lane => format!( + "{}{}", + current_name, + type_to_lane_suffixes(out_t, in_t[2], false) + ), + OutLane => format!( + "{}{}", + current_name, + type_to_lane_suffixes(out_t, in_t[2], true) + ), + Rot => type_to_rot_suffix(current_name, type_to_suffix(out_t)), + RotLane => type_to_rot_suffix(current_name, &type_to_lane_suffixes(out_t, in_t[2], false)), }; let current_target = match target { Default => "neon", @@ -984,6 +1068,13 @@ fn gen_aarch64( Vfp4 => "vfp4", FPArmV8 => "fp-armv8,v8", AES => "neon,aes", + FCMA => "neon,fcma", + Dotprod => "neon,dotprod", + I8MM => "neon,i8mm", + SHA3 => "neon,sha3", + RDM => "rdm", + SM4 => "neon,sm4", + FTTS => "neon,frintts", }; let current_fn = if let Some(current_fn) = current_fn.clone() { if link_aarch64.is_some() { @@ -1030,23 +1121,32 @@ fn gen_aarch64( }; let (ext_inputs, ext_output) = { if const_aarch64.is_some() { - if matches!(fn_type, Fntype::Load) { + if !matches!(fn_type, Fntype::Normal) { + let ptr_type = match fn_type { + Fntype::Load => "*const i8", + Fntype::Store => "*mut i8", + _ => panic!("unsupported fn type"), + }; let sub = type_to_sub_type(in_t[1]); ( match type_sub_len(in_t[1]) { - 1 => format!("a: {}, n: i64, ptr: *const i8", sub), - 2 => format!("a: {}, b: {}, n: i64, ptr: *const i8", sub, sub), + 1 => format!("a: {}, n: i64, ptr: {}", sub, ptr_type), + 2 => format!("a: {}, b: {}, n: i64, ptr: {}", sub, sub, ptr_type), 3 => format!( - "a: {}, b: {}, c: {}, n: i64, ptr: *const i8", - sub, sub, sub + "a: {}, b: {}, c: {}, n: i64, ptr: {}", + sub, sub, sub, ptr_type ), 4 => format!( - "a: {}, b: {}, c: {}, d: {}, n: i64, ptr: *const i8", - sub, sub, sub, sub + "a: {}, b: {}, c: {}, d: {}, n: i64, ptr: {}", + sub, sub, sub, sub, ptr_type ), _ => panic!("unsupported type: {}", in_t[1]), }, - format!(" -> {}", out_t), + if out_t != "void" { + format!(" -> {}", out_t) + } else { + String::new() + }, ) } else { ( @@ -1061,19 +1161,28 @@ fn gen_aarch64( } } else if matches!(fn_type, Fntype::Store) { let sub = type_to_sub_type(in_t[1]); - let native = type_to_native_type(in_t[1]); + let ptr_type = if is_vstx(&name) { + "i8".to_string() + } else { + type_to_native_type(in_t[1]) + }; + let subs = match type_sub_len(in_t[1]) { + 1 => format!("a: {}", sub), + 2 => format!("a: {}, b: {}", sub, sub), + 3 => format!("a: {}, b: {}, c: {}", sub, sub, sub), + 4 => format!("a: {}, b: {}, c: {}, d: {}", sub, sub, sub, sub), + _ => panic!("unsupported type: {}", in_t[1]), + }; + (format!("{}, ptr: *mut {}", subs, ptr_type), String::new()) + } else if is_vldx(&name) { + let ptr_type = if name.contains("dup") { + type_to_native_type(out_t) + } else { + type_to_sub_type(out_t) + }; ( - match type_sub_len(in_t[1]) { - 1 => format!("a: {}, ptr: *mut {}", sub, native), - 2 => format!("a: {}, b: {}, ptr: *mut {}", sub, sub, native), - 3 => format!("a: {}, b: {}, c: {}, ptr: *mut {}", sub, sub, sub, native), - 4 => format!( - "a: {}, b: {}, c: {}, d: {}, ptr: *mut {}", - sub, sub, sub, sub, native - ), - _ => panic!("unsupported type: {}", in_t[1]), - }, - String::new(), + format!("ptr: *const {}", ptr_type), + format!(" -> {}", out_t), ) } else { ( @@ -1185,7 +1294,7 @@ fn gen_aarch64( }; let call_params = { if let (Some(const_aarch64), Some(_)) = (const_aarch64, link_aarch64) { - if matches!(fn_type, Fntype::Load) { + if !matches!(fn_type, Fntype::Normal) { let subs = match type_sub_len(in_t[1]) { 1 => "b", 2 => "b.0, b.1", @@ -1195,7 +1304,7 @@ fn gen_aarch64( }; format!( r#"{} - {}{}({}, {} as i64, a as *const i8)"#, + {}{}({}, {} as i64, a.cast())"#, multi_calls, ext_c, current_fn, @@ -1217,14 +1326,17 @@ fn gen_aarch64( _ => String::new(), } } - } else if matches!(fn_type, Fntype::Store) { + } else if link_aarch64.is_some() && matches!(fn_type, Fntype::Store) { + let cast = if is_vstx(&name) { ".cast()" } else { "" }; match type_sub_len(in_t[1]) { - 1 => format!(r#"{}{}(b, a)"#, ext_c, current_fn), - 2 => format!(r#"{}{}(b.0, b.1, a)"#, ext_c, current_fn), - 3 => format!(r#"{}{}(b.0, b.1, b.2, a)"#, ext_c, current_fn), - 4 => format!(r#"{}{}(b.0, b.1, b.2, b.3, a)"#, ext_c, current_fn), + 1 => format!(r#"{}{}(b, a{})"#, ext_c, current_fn, cast), + 2 => format!(r#"{}{}(b.0, b.1, a{})"#, ext_c, current_fn, cast), + 3 => format!(r#"{}{}(b.0, b.1, b.2, a{})"#, ext_c, current_fn, cast), + 4 => format!(r#"{}{}(b.0, b.1, b.2, b.3, a{})"#, ext_c, current_fn, cast), _ => panic!("unsupported type: {}", in_t[1]), } + } else if link_aarch64.is_some() && is_vldx(&name) { + format!(r#"{}{}(a.cast())"#, ext_c, current_fn,) } else { let trans: [&str; 2] = if link_t[3] != out_t { ["transmute(", ")"] @@ -1273,6 +1385,13 @@ fn gen_aarch64( fn_decl, call_params ); + let test_target = match target { + I8MM => "neon,i8mm", + SM4 => "neon,sm4", + SHA3 => "neon,sha3", + FTTS => "neon,frintts", + _ => "neon", + }; let test = match fn_type { Fntype::Normal => gen_test( &name, @@ -1282,6 +1401,7 @@ fn gen_aarch64( [type_len(in_t[0]), type_len(in_t[1]), type_len(in_t[2])], type_len(out_t), para_num, + test_target, ), Fntype::Load => gen_load_test(&name, in_t, &out_t, current_tests, type_len(out_t)), Fntype::Store => gen_store_test(&name, in_t, &out_t, current_tests, type_len(in_t[1])), @@ -1406,7 +1526,7 @@ fn gen_store_test( unsafe fn test_{}() {{"#, name, ); - for (a, _, _, _, e) in current_tests { + for (a, _, _, constn, e) in current_tests { let a: Vec = a.iter().take(type_len + 1).cloned().collect(); let e: Vec = e.iter().take(type_len).cloned().collect(); let mut input = String::from("["); @@ -1425,12 +1545,15 @@ fn gen_store_test( output.push_str(&e[i]) } output.push_str("]"); + let const_n = constn + .as_deref() + .map_or(String::new(), |n| format!("::<{}>", n.to_string())); let t = format!( r#" let a: [{}; {}] = {}; let e: [{}; {}] = {}; let mut r: [{}; {}] = [0{}; {}]; - {}(r.as_mut_ptr(), {}(a[1..].as_ptr())); + {}{}(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); assert_eq!(r, e); "#, type_to_native_type(in_t[1]), @@ -1444,7 +1567,7 @@ fn gen_store_test( type_to_native_type(in_t[1]), type_len, name, - name.replace("st", "ld"), + const_n, ); test.push_str(&t); } @@ -1466,12 +1589,13 @@ fn gen_test( len_in: [usize; 3], len_out: usize, para_num: i32, + target: &str, ) -> String { let mut test = format!( r#" - #[simd_test(enable = "neon")] + #[simd_test(enable = "{}")] unsafe fn test_{}() {{"#, - name, + target, name, ); for (a, b, c, n, e) in current_tests { let a: Vec = a.iter().take(len_in[0]).cloned().collect(); @@ -1492,6 +1616,10 @@ fn gen_test( } else { String::new() }; + let r_type = match type_sub_len(out_t) { + 1 => type_to_global_type(out_t).to_string(), + _ => format!("[{}; {}]", type_to_native_type(out_t), type_len(out_t)), + }; let t = { match para_num { 1 => { @@ -1504,7 +1632,7 @@ fn gen_test( "#, values(in_t[0], &a), values(out_t, &e), - type_to_global_type(out_t), + r_type, name, const_value ) @@ -1521,7 +1649,7 @@ fn gen_test( values(in_t[0], &a), values(in_t[1], &b), values(out_t, &e), - type_to_global_type(out_t), + r_type, name, const_value ) @@ -1540,7 +1668,7 @@ fn gen_test( values(in_t[1], &b), values(in_t[2], &c), values(out_t, &e), - type_to_global_type(out_t), + r_type, name, const_value ) @@ -1613,6 +1741,11 @@ fn gen_arm( current_name, type_to_suffix(&type_to_sub_type(out_t)) ), + In1Nox => format!( + "{}{}", + current_name, + type_to_suffix(&type_to_sub_type(in_t[1])) + ), OutDupNox => format!( "{}{}", current_name, @@ -1623,9 +1756,29 @@ fn gen_arm( current_name, type_to_lane_suffix(&type_to_sub_type(out_t)) ), - Lane => format!("{}{}", current_name, type_to_lane_suffixes(out_t, in_t[1])), + In1LaneNox => format!( + "{}{}", + current_name, + type_to_lane_suffix(&type_to_sub_type(in_t[1])) + ), + Lane => format!( + "{}{}", + current_name, + type_to_lane_suffixes(out_t, in_t[1], false) + ), In2 => format!("{}{}", current_name, type_to_suffix(in_t[2])), - In2Lane => format!("{}{}", current_name, type_to_lane_suffixes(out_t, in_t[2])), + In2Lane => format!( + "{}{}", + current_name, + type_to_lane_suffixes(out_t, in_t[2], false) + ), + OutLane => format!( + "{}{}", + current_name, + type_to_lane_suffixes(out_t, in_t[2], true) + ), + Rot => type_to_rot_suffix(current_name, type_to_suffix(out_t)), + RotLane => type_to_rot_suffix(current_name, &type_to_lane_suffixes(out_t, in_t[2], false)), }; let current_aarch64 = current_aarch64 .clone() @@ -1636,6 +1789,13 @@ fn gen_arm( Vfp4 => "neon", FPArmV8 => "neon", AES => "neon,aes", + FCMA => "neon,fcma", + Dotprod => "neon,dotprod", + I8MM => "neon,i8mm", + SHA3 => "neon,sha3", + RDM => "rdm", + SM4 => "neon,sm4", + FTTS => "neon,frintts", }; let current_target_arm = match target { Default => "v7", @@ -1643,6 +1803,13 @@ fn gen_arm( Vfp4 => "vfp4", FPArmV8 => "fp-armv8,v8", AES => "aes,v8", + FCMA => "v8", // v8.3a + Dotprod => "v8", // v8.2a + I8MM => "v8,i8mm", + RDM => unreachable!(), + SM4 => unreachable!(), + SHA3 => unreachable!(), + FTTS => unreachable!(), }; let current_fn = if let Some(current_fn) = current_fn.clone() { if link_aarch64.is_some() || link_arm.is_some() { @@ -1752,7 +1919,12 @@ fn gen_arm( }; let (arm_ext_inputs, arm_ext_output) = { if let Some(const_arm) = const_arm { - if matches!(fn_type, Fntype::Load) { + if !matches!(fn_type, Fntype::Normal) { + let ptr_type = match fn_type { + Fntype::Load => "*const i8", + Fntype::Store => "*mut i8", + _ => panic!("unsupported fn type"), + }; let sub_type = type_to_sub_type(in_t[1]); let inputs = match type_sub_len(in_t[1]) { 1 => format!("a: {}", sub_type), @@ -1764,9 +1936,14 @@ fn gen_arm( ), _ => panic!("unknown type: {}", in_t[1]), }; + let out = if out_t == "void" { + String::new() + } else { + format!(" -> {}", out_t) + }; ( - format!("ptr: *const i8, {}, n: i32, size: i32", inputs), - String::new(), + format!("ptr: {}, {}, n: i32, size: i32", ptr_type, inputs), + out, ) } else { let (_, const_type) = if const_arm.contains(":") { @@ -1817,10 +1994,20 @@ fn gen_arm( ), _ => panic!("unknown type: {}", in_t[1]), }; + let (ptr_type, size) = if is_vstx(&name) { + ("i8".to_string(), ", size: i32") + } else { + (type_to_native_type(in_t[1]), "") + }; ( - format!("ptr: *mut {}, {}", type_to_native_type(in_t[1]), inputs), + format!("ptr: *mut {}, {}{}", ptr_type, inputs, size), String::new(), ) + } else if is_vldx(&name) { + ( + format!("ptr: *const i8, size: i32"), + format!(" -> {}", out_t), + ) } else { (String::new(), String::new()) } @@ -1835,8 +2022,13 @@ fn gen_arm( link_arm, current_fn, arm_ext_inputs, arm_ext_output, )); let (aarch64_ext_inputs, aarch64_ext_output) = { - if const_aarch64.is_some() { - if matches!(fn_type, Fntype::Load) { + if let Some(const_aarch64) = const_aarch64 { + if !matches!(fn_type, Fntype::Normal) { + let ptr_type = match fn_type { + Fntype::Load => "*const i8", + Fntype::Store => "*mut i8", + _ => panic!("unsupported fn type"), + }; let sub_type = type_to_sub_type(in_t[1]); let mut inputs = match type_sub_len(in_t[1]) { 1 => format!("a: {}", sub_type,), @@ -1848,8 +2040,26 @@ fn gen_arm( ), _ => panic!("unknown type: {}", in_t[1]), }; - inputs.push_str(&format!(", n: i64, ptr: *const i8")); - (inputs, format!(" -> {}", out_t)) + inputs.push_str(&format!(", n: i64, ptr: {}", ptr_type)); + let out = if out_t == "void" { + String::new() + } else { + format!(" -> {}", out_t) + }; + (inputs, out) + } else if const_aarch64.contains("dup-in_len-N as ttn") { + ( + match para_num { + 1 => format!("a: {}, n: {}", in_t[0], in_t[0]), + 2 => format!("a: {}, b: {}, n: {}", in_t[0], in_t[1], in_t[1]), + 3 => format!( + "a: {}, b: {}, c: {}, n: {}", + in_t[0], in_t[1], in_t[2], in_t[1] + ), + _ => unimplemented!("unknown para_num"), + }, + format!(" -> {}", out_t), + ) } else { ( match para_num { @@ -1886,8 +2096,23 @@ fn gen_arm( ), _ => panic!("unknown type: {}", in_t[1]), }; - inputs.push_str(&format!(", ptr: *mut {}", type_to_native_type(in_t[0]))); + let ptr_type = if is_vstx(&name) { + "i8".to_string() + } else { + type_to_native_type(in_t[1]) + }; + inputs.push_str(&format!(", ptr: *mut {}", ptr_type)); (inputs, String::new()) + } else if is_vldx(&name) { + let ptr_type = if name.contains("dup") { + type_to_native_type(out_t) + } else { + type_to_sub_type(out_t) + }; + ( + format!("ptr: *const {}", ptr_type), + format!(" -> {}", out_t), + ) } else { (String::new(), String::new()) } @@ -1962,7 +2187,7 @@ fn gen_arm( let function = if separate { let call_arm = { let arm_params = if let (Some(const_arm), Some(_)) = (const_arm, link_arm) { - if matches!(fn_type, Fntype::Load) { + if !matches!(fn_type, Fntype::Normal) { let subs = match type_sub_len(in_t[1]) { 1 => "b", 2 => "b.0, b.1", @@ -1971,7 +2196,7 @@ fn gen_arm( _ => "", }; format!( - "{}(a as *const i8, {}, {}, {})", + "{}(a.cast(), {}, {}, {})", current_fn, subs, constn.as_deref().unwrap(), @@ -2008,13 +2233,27 @@ fn gen_arm( _ => String::new(), } } else if matches!(fn_type, Fntype::Store) { + let (cast, size) = if is_vstx(&name) { + ( + ".cast()", + format!(", {}", type_bits(&type_to_sub_type(in_t[1])) / 8), + ) + } else { + ("", String::new()) + }; match type_sub_len(in_t[1]) { - 1 => format!("{}(a, b)", current_fn), - 2 => format!("{}(a, b.0, b.1)", current_fn), - 3 => format!("{}(a, b.0, b.1, b.2)", current_fn), - 4 => format!("{}(a, b.0, b.1, b.2, b.3)", current_fn), + 1 => format!("{}(a{}, b{})", current_fn, cast, size), + 2 => format!("{}(a{}, b.0, b.1{})", current_fn, cast, size), + 3 => format!("{}(a{}, b.0, b.1, b.2{})", current_fn, cast, size), + 4 => format!("{}(a{}, b.0, b.1, b.2, b.3{})", current_fn, cast, size), _ => String::new(), } + } else if link_arm.is_some() && is_vldx(&name) { + format!( + "{}(a as *const i8, {})", + current_fn, + type_bits(&type_to_sub_type(out_t)) / 8 + ) } else { String::new() }; @@ -2028,7 +2267,7 @@ fn gen_arm( let call_aarch64 = { let aarch64_params = if let (Some(const_aarch64), Some(_)) = (const_aarch64, link_aarch64) { - if matches!(fn_type, Fntype::Load) { + if !matches!(fn_type, Fntype::Normal) { let subs = match type_sub_len(in_t[1]) { 1 => "b", 2 => "b.0, b.1", @@ -2037,11 +2276,23 @@ fn gen_arm( _ => "", }; format!( - "{}({}, {} as i64, a as *const i8)", + "{}({}, {} as i64, a.cast())", current_fn, subs, constn.as_deref().unwrap() ) + } else if const_aarch64.contains("dup-in_len-N as ttn") { + let const_aarch64 = format!("N as {}", type_to_native_type(in_t[1])); + let mut cnt = String::from(in_t[1]); + cnt.push_str("("); + for i in 0..type_len(in_t[1]) { + if i != 0 { + cnt.push_str(", "); + } + cnt.push_str(&const_aarch64); + } + cnt.push_str(")"); + format!("{}(a, {})", current_fn, cnt) } else { match para_num { 1 => format!("{}(a, {})", current_fn, const_aarch64), @@ -2056,13 +2307,16 @@ fn gen_arm( _ => String::new(), } } else if matches!(fn_type, Fntype::Store) { + let cast = if is_vstx(&name) { ".cast()" } else { "" }; match type_sub_len(in_t[1]) { - 1 => format!("{}(b, a)", current_fn), - 2 => format!("{}(b.0, b.1, a)", current_fn), - 3 => format!("{}(b.0, b.1, b.2, a)", current_fn), - 4 => format!("{}(b.0, b.1, b.2, b.3, a)", current_fn), + 1 => format!("{}(b, a{})", current_fn, cast), + 2 => format!("{}(b.0, b.1, a{})", current_fn, cast), + 3 => format!("{}(b.0, b.1, b.2, a{})", current_fn, cast), + 4 => format!("{}(b.0, b.1, b.2, b.3, a{})", current_fn, cast), _ => String::new(), } + } else if link_aarch64.is_some() && is_vldx(&name) { + format!("{}(a.cast())", current_fn) } else { String::new() }; @@ -2156,6 +2410,13 @@ fn gen_arm( call, ) }; + let test_target = match target { + I8MM => "neon,i8mm", + SM4 => "neon,sm4", + SHA3 => "neon,sha3", + FTTS => "neon,frintts", + _ => "neon", + }; let test = match fn_type { Fntype::Normal => gen_test( &name, @@ -2165,6 +2426,7 @@ fn gen_arm( [type_len(in_t[0]), type_len(in_t[1]), type_len(in_t[2])], type_len(out_t), para_num, + test_target, ), Fntype::Load => gen_load_test(&name, in_t, &out_t, current_tests, type_len(out_t)), Fntype::Store => gen_store_test(&name, in_t, &out_t, current_tests, type_len(in_t[1])), @@ -2352,6 +2614,34 @@ fn get_call( }; return asc(start, len); } + if fn_name.starts_with("base") { + let fn_format: Vec<_> = fn_name.split('-').map(|v| v.to_string()).collect(); + assert_eq!(fn_format.len(), 3); + let mut s = format!(" [", &fn_format[2]); + let base_len = fn_format[1].parse::().unwrap(); + for i in 0..type_len(in_t[1]) / base_len { + for j in 0..base_len { + if i != 0 || j != 0 { + s.push_str(", "); + } + s.push_str(&format!("{} * {} as u32", base_len, &fn_format[2])); + if j != 0 { + s.push_str(&format!(" + {}", j)); + } + } + } + s.push_str("]"); + return s; + } + if fn_name.starts_with("as") { + let fn_format: Vec<_> = fn_name.split('-').map(|v| v.to_string()).collect(); + assert_eq!(fn_format.len(), 3); + let t = match &*fn_format[2] { + "in_ttn" => type_to_native_type(in_t[1]), + _ => String::new(), + }; + return format!("{} as {}", &fn_format[1], t); + } if fn_name.starts_with("ins") { let fn_format: Vec<_> = fn_name.split('-').map(|v| v.to_string()).collect(); let n = n.unwrap(); @@ -2384,13 +2674,15 @@ fn get_call( if fn_name.starts_with("static_assert_imm") { let fn_format: Vec<_> = fn_name.split('-').map(|v| v.to_string()).collect(); let len = match &*fn_format[1] { - "out_exp_len" => type_exp_len(out_t), + "out_exp_len" => type_exp_len(out_t, 1), "out_bits_exp_len" => type_bits_exp_len(out_t), - "in_exp_len" => type_exp_len(in_t[1]), + "in_exp_len" => type_exp_len(in_t[1], 1), "in_bits_exp_len" => type_bits_exp_len(in_t[1]), - "in0_exp_len" => type_exp_len(in_t[0]), - "in1_exp_len" => type_exp_len(in_t[1]), - "in2_exp_len" => type_exp_len(in_t[2]), + "in0_exp_len" => type_exp_len(in_t[0], 1), + "in1_exp_len" => type_exp_len(in_t[1], 1), + "in2_exp_len" => type_exp_len(in_t[2], 1), + "in2_rot" => type_exp_len(in_t[2], 2), + "in2_dot" => type_exp_len(in_t[2], 4), _ => 0, }; if len == 0 { @@ -2430,12 +2722,34 @@ fn get_call( ); } } + if fn_name.starts_with("fix_right_shift_imm") { + let fn_format: Vec<_> = fn_name.split('-').map(|v| v.to_string()).collect(); + let lim = if fn_format[2] == "bits" { + type_bits(in_t[1]).to_string() + } else { + fn_format[2].clone() + }; + let fixed = if in_t[1].starts_with('u') { + format!("return vdup{nself}(0);", nself = type_to_n_suffix(in_t[1])) + } else { + (lim.parse::().unwrap() - 1).to_string() + }; + + return format!( + r#"let {name}: i32 = if {const_name} == {upper} {{ {fixed} }} else {{ N }};"#, + name = fn_format[1].to_lowercase(), + const_name = fn_format[1], + upper = lim, + fixed = fixed, + ); + } + if fn_name.starts_with("matchn") { let fn_format: Vec<_> = fn_name.split('-').map(|v| v.to_string()).collect(); let len = match &*fn_format[1] { - "out_exp_len" => type_exp_len(out_t), - "in_exp_len" => type_exp_len(in_t[1]), - "in0_exp_len" => type_exp_len(in_t[0]), + "out_exp_len" => type_exp_len(out_t, 1), + "in_exp_len" => type_exp_len(in_t[1], 1), + "in0_exp_len" => type_exp_len(in_t[0], 1), _ => 0, }; let mut call = format!("match {} & 0b{} {{\n", &fn_format[2], "1".repeat(len)); @@ -2519,6 +2833,10 @@ fn get_call( re = Some((re_params[0].clone(), in_t[1].to_string())); } else if re_params[1] == "in_t" { re = Some((re_params[0].clone(), in_t[1].to_string())); + } else if re_params[1] == "signed" { + re = Some((re_params[0].clone(), type_to_signed(in_t[1]))); + } else if re_params[1] == "unsigned" { + re = Some((re_params[0].clone(), type_to_unsigned(in_t[1]))); } else if re_params[1] == "in_t0" { re = Some((re_params[0].clone(), in_t[0].to_string())); } else if re_params[1] == "in_t1" { @@ -2539,6 +2857,11 @@ fn get_call( )); } else if re_params[1] == "out_ntt" { re = Some((re_params[0].clone(), native_type_to_type(out_t).to_string())); + } else if re_params[1] == "out_long_ntt" { + re = Some(( + re_params[0].clone(), + native_type_to_long_type(out_t).to_string(), + )); } else { re = Some((re_params[0].clone(), re_params[1].clone())); } @@ -2566,6 +2889,12 @@ fn get_call( }); return format!(r#"[{}]"#, &half[..half.len() - 2]); } + if fn_name == "a - b" { + return fn_name; + } + if fn_name == "-a" { + return fn_name; + } if fn_name.contains('-') { let fn_format: Vec<_> = fn_name.split('-').map(|v| v.to_string()).collect(); assert_eq!(fn_format.len(), 3); @@ -2590,7 +2919,9 @@ fn get_call( } else if fn_format[1] == "in2" { fn_name.push_str(type_to_suffix(in_t[2])); } else if fn_format[1] == "in2lane" { - fn_name.push_str(&type_to_lane_suffixes(out_t, in_t[2])); + fn_name.push_str(&type_to_lane_suffixes(out_t, in_t[2], false)); + } else if fn_format[1] == "outlane" { + fn_name.push_str(&type_to_lane_suffixes(out_t, in_t[2], true)); } else if fn_format[1] == "signed" { fn_name.push_str(type_to_suffix(&type_to_signed(&String::from(in_t[1])))); } else if fn_format[1] == "outsigned" { @@ -2599,6 +2930,10 @@ fn get_call( fn_name.push_str(&type_to_suffix(&type_to_sub_type(&type_to_signed( &String::from(out_t), )))); + } else if fn_format[1] == "in1signednox" { + fn_name.push_str(&type_to_suffix(&type_to_sub_type(&type_to_signed( + &String::from(in_t[1]), + )))); } else if fn_format[1] == "outsigneddupnox" { fn_name.push_str(&type_to_dup_suffix(&type_to_sub_type(&type_to_signed( &String::from(out_t), @@ -2607,8 +2942,12 @@ fn get_call( fn_name.push_str(&type_to_lane_suffix(&type_to_sub_type(&type_to_signed( &String::from(out_t), )))); + } else if fn_format[1] == "in1signedlanenox" { + fn_name.push_str(&type_to_lane_suffix(&type_to_sub_type(&type_to_signed( + &String::from(in_t[1]), + )))); } else if fn_format[1] == "unsigned" { - fn_name.push_str(type_to_suffix(type_to_unsigned(in_t[1]))); + fn_name.push_str(type_to_suffix(&type_to_unsigned(in_t[1]))); } else if fn_format[1] == "doubleself" { fn_name.push_str(&type_to_double_suffixes(out_t, in_t[1])); } else if fn_format[1] == "noq_doubleself" { @@ -2636,6 +2975,8 @@ fn get_call( fn_name.push_str(type_to_suffix(native_type_to_type(in_t[1]))); } else if fn_format[1] == "out_ntt" { fn_name.push_str(type_to_suffix(native_type_to_type(out_t))); + } else if fn_format[1] == "rot" { + fn_name = type_to_rot_suffix(&fn_name, type_to_suffix(out_t)); } else { fn_name.push_str(&fn_format[1]); }; @@ -2672,6 +3013,8 @@ fn get_call( r#"let {}: {} = {}({});"#, re_name, re_type, fn_name, param_str ) + } else if fn_name.starts_with("*") { + format!(r#"{} = {};"#, fn_name, param_str) } else { format!(r#"{}({})"#, fn_name, param_str) }; @@ -2827,16 +3170,26 @@ mod test { suffix = OutSuffix; } else if line.starts_with("out-nox") { suffix = OutNox; + } else if line.starts_with("in1-nox") { + suffix = In1Nox; } else if line.starts_with("out-dup-nox") { suffix = OutDupNox; } else if line.starts_with("out-lane-nox") { suffix = OutLaneNox; + } else if line.starts_with("in1-lane-nox") { + suffix = In1LaneNox; } else if line.starts_with("lane-suffixes") { suffix = Lane; } else if line.starts_with("in2-suffix") { suffix = In2; } else if line.starts_with("in2-lane-suffixes") { suffix = In2Lane; + } else if line.starts_with("out-lane-suffixes") { + suffix = OutLane; + } else if line.starts_with("rot-suffix") { + suffix = Rot; + } else if line.starts_with("rot-lane-suffixes") { + suffix = RotLane; } else if line.starts_with("a = ") { a = line[4..].split(',').map(|v| v.trim().to_string()).collect(); } else if line.starts_with("b = ") { @@ -2871,6 +3224,13 @@ mod test { "vfp4" => Vfp4, "fp-armv8" => FPArmV8, "aes" => AES, + "fcma" => FCMA, + "dotprod" => Dotprod, + "i8mm" => I8MM, + "sha3" => SHA3, + "rdm" => RDM, + "sm4" => SM4, + "frintts" => FTTS, _ => Default, }, _ => Default, @@ -2975,20 +3335,22 @@ mod test { tests_aarch64.push('}'); tests_aarch64.push('\n'); - let arm_out_path: PathBuf = PathBuf::from(env::var("OUT_DIR").unwrap()) - .join("src") - .join("arm_shared") - .join("neon"); + let arm_out_path: PathBuf = + PathBuf::from(env::var("OUT_DIR").unwrap_or("crates/core_arch".to_string())) + .join("src") + .join("arm_shared") + .join("neon"); std::fs::create_dir_all(&arm_out_path)?; let mut file_arm = File::create(arm_out_path.join(ARM_OUT))?; file_arm.write_all(out_arm.as_bytes())?; file_arm.write_all(tests_arm.as_bytes())?; - let aarch64_out_path: PathBuf = PathBuf::from(env::var("OUT_DIR").unwrap()) - .join("src") - .join("aarch64") - .join("neon"); + let aarch64_out_path: PathBuf = + PathBuf::from(env::var("OUT_DIR").unwrap_or("crates/core_arch".to_string())) + .join("src") + .join("aarch64") + .join("neon"); std::fs::create_dir_all(&aarch64_out_path)?; let mut file_aarch = File::create(aarch64_out_path.join(AARCH64_OUT))?; diff --git a/library/stdarch/crates/stdarch-test/src/lib.rs b/library/stdarch/crates/stdarch-test/src/lib.rs index 15ff9595af..078736c66a 100644 --- a/library/stdarch/crates/stdarch-test/src/lib.rs +++ b/library/stdarch/crates/stdarch-test/src/lib.rs @@ -130,14 +130,27 @@ pub fn assert(shim_addr: usize, fnname: &str, expected: &str) { "usad8" | "vfma" | "vfms" => 27, "qadd8" | "qsub8" | "sadd8" | "sel" | "shadd8" | "shsub8" | "usub8" | "ssub8" => 29, // core_arch/src/arm_shared/simd32 + // vst1q_s64_x4_vst1 : #instructions = 22 >= 22 (limit) + "vld3" => 23, + // core_arch/src/arm_shared/simd32 + // vld4q_lane_u32_vld4 : #instructions = 31 >= 22 (limit) + "vld4" => 32, + // core_arch/src/arm_shared/simd32 // vst1q_s64_x4_vst1 : #instructions = 40 >= 22 (limit) "vst1" => 41, + // core_arch/src/arm_shared/simd32 + // vst4q_u32_vst4 : #instructions = 26 >= 22 (limit) + "vst4" => 27, // Temporary, currently the fptosi.sat and fptoui.sat LLVM // intrinsics emit unnecessary code on arm. This can be // removed once it has been addressed in LLVM. "fcvtzu" | "fcvtzs" | "vcvt" => 64, + // core_arch/src/arm_shared/simd32 + // vst1q_p64_x4_nop : #instructions = 33 >= 22 (limit) + "nop" if fnname.contains("vst1q_p64") => 34, + // Original limit was 20 instructions, but ARM DSP Intrinsics // are exactly 20 instructions long. So, bump the limit to 22 // instead of adding here a long list of exceptions. diff --git a/library/stdarch/crates/stdarch-verify/tests/arm.rs b/library/stdarch/crates/stdarch-verify/tests/arm.rs index 9047a08ef7..a170ea4e62 100644 --- a/library/stdarch/crates/stdarch-verify/tests/arm.rs +++ b/library/stdarch/crates/stdarch-verify/tests/arm.rs @@ -352,6 +352,8 @@ fn verify_all_signatures() { "vsliq_n_p8", "vsli_n_p16", "vsliq_n_p16", + "vsli_n_p64", + "vsliq_n_p64", "vsri_n_s8", "vsriq_n_s8", "vsri_n_s16", @@ -372,6 +374,8 @@ fn verify_all_signatures() { "vsriq_n_p8", "vsri_n_p16", "vsriq_n_p16", + "vsri_n_p64", + "vsriq_n_p64", "__smulbb", "__smultb", "__smulbt", @@ -450,6 +454,9 @@ fn verify_all_signatures() { "vreinterpret_p64_s64", "vreinterpret_f32_p64", "vreinterpretq_f32_p64", + "vreinterpretq_p64_p128", + "vreinterpretq_p128_p64", + "vreinterpretq_f32_p128", "vqrdmlahh_s16", "vqrdmlahs_s32", "vqrdmlahh_lane_s16", @@ -486,6 +493,107 @@ fn verify_all_signatures() { "vqrdmlsh_laneq_s32", "vqrdmlshq_lane_s32", "vqrdmlshq_laneq_s32", + "vcadd_rot270_f32", + "vcadd_rot90_f32", + "vcaddq_rot270_f32", + "vcaddq_rot270_f64", + "vcaddq_rot90_f32", + "vcaddq_rot90_f64", + "vcmla_f32", + "vcmlaq_f32", + "vcmlaq_f64", + "vcmla_rot90_f32", + "vcmlaq_rot90_f32", + "vcmlaq_rot90_f64", + "vcmla_rot180_f32", + "vcmlaq_rot180_f32", + "vcmlaq_rot180_f64", + "vcmla_rot270_f32", + "vcmlaq_rot270_f32", + "vcmlaq_rot270_f64", + "vcmla_lane_f32", + "vcmla_laneq_f32", + "vcmlaq_lane_f32", + "vcmlaq_laneq_f32", + "vcmla_rot90_lane_f32", + "vcmla_rot90_laneq_f32", + "vcmlaq_rot90_lane_f32", + "vcmlaq_rot90_laneq_f32", + "vcmla_rot180_lane_f32", + "vcmla_rot180_laneq_f32", + "vcmlaq_rot180_lane_f32", + "vcmlaq_rot180_laneq_f32", + "vcmla_rot270_lane_f32", + "vcmla_rot270_laneq_f32", + "vcmlaq_rot270_lane_f32", + "vcmlaq_rot270_laneq_f32", + "vdot_s32", + "vdot_u32", + "vdotq_s32", + "vdotq_u32", + "vdot_lane_s32", + "vdot_laneq_s32", + "vdotq_lane_s32", + "vdotq_laneq_s32", + "vdot_lane_u32", + "vdot_laneq_u32", + "vdotq_lane_u32", + "vdotq_laneq_u32", + "vbcaxq_s8", + "vbcaxq_s16", + "vbcaxq_s32", + "vbcaxq_s64", + "vbcaxq_u8", + "vbcaxq_u16", + "vbcaxq_u32", + "vbcaxq_u64", + "veor3q_s8", + "veor3q_s16", + "veor3q_s32", + "veor3q_s64", + "veor3q_u8", + "veor3q_u16", + "veor3q_u32", + "veor3q_u64", + "vadd_p8", + "vadd_p16", + "vadd_p64", + "vaddq_p8", + "vaddq_p16", + "vaddq_p64", + "vaddq_p128", + "vsm4ekeyq_u32", + "vsm4eq_u32", + "vmmlaq_s32", + "vmmlaq_u32", + "vusmmlaq_s32", + "vsm3partw1q_u32", + "vsm3partw2q_u32", + "vsm3ss1q_u32", + "vsm3tt1aq_u32", + "vsm3tt1bq_u32", + "vsm3tt2aq_u32", + "vsm3tt2bq_u32", + "vrax1q_u64", + "vxarq_u64", + "vsha512hq_u64", + "vsha512h2q_u64", + "vsha512su0q_u64", + "vsha512su1q_u64", + "vrnd32x_f32", + "vrnd32xq_f32", + "vrnd32z_f32", + "vrnd32zq_f32", + "vrnd64x_f32", + "vrnd64xq_f32", + "vrnd64z_f32", + "vrnd64zq_f32", + "vcls_u8", + "vcls_u16", + "vcls_u32", + "vclsq_u8", + "vclsq_u16", + "vclsq_u32", "__dbg", ]; let arm = match map.get(rust.name) { diff --git a/library/test/src/console.rs b/library/test/src/console.rs index 11c5ab48ed..9c261e8cc8 100644 --- a/library/test/src/console.rs +++ b/library/test/src/console.rs @@ -284,7 +284,7 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec) -> io::Resu // Prevent the usage of `Instant` in some cases: // - It's currently not supported for wasm targets. // - We disable it for miri because it's not available when isolation is enabled. - let is_instant_supported = !cfg!(target_arch = "wasm32") && !cfg!(miri); + let is_instant_supported = !cfg!(target_family = "wasm") && !cfg!(miri); let start_time = is_instant_supported.then(Instant::now); run_tests(opts, tests, |x| on_test_event(&x, &mut st, &mut *out))?; diff --git a/library/test/src/formatters/junit.rs b/library/test/src/formatters/junit.rs index e2aebee916..fa23cf2689 100644 --- a/library/test/src/formatters/junit.rs +++ b/library/test/src/formatters/junit.rs @@ -55,8 +55,8 @@ impl OutputFormatter for JunitFormatter { _stdout: &[u8], _state: &ConsoleTestState, ) -> io::Result<()> { - // Because the testsuit node holds some of the information as attributes, we can't write it - // until all of the tests has ran. Instead of writting every result as they come in, we add + // Because the testsuite node holds some of the information as attributes, we can't write it + // until all of the tests have finished. Instead of writing every result as they come in, we add // them to a Vec and write them all at once when run is complete. let duration = exec_time.map(|t| t.0).unwrap_or_default(); self.results.push((desc.clone(), result.clone(), duration)); diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 99d951d801..2516f3452b 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -470,7 +470,7 @@ pub fn run_test( // Emscripten can catch panics but other wasm targets cannot let ignore_because_no_process_support = desc.should_panic != ShouldPanic::No - && cfg!(target_arch = "wasm32") + && cfg!(target_family = "wasm") && !cfg!(target_os = "emscripten"); if force_ignore || desc.ignore || ignore_because_no_process_support { @@ -519,7 +519,7 @@ pub fn run_test( // If the platform is single-threaded we're just going to run // the test synchronously, regardless of the concurrency // level. - let supports_threads = !cfg!(target_os = "emscripten") && !cfg!(target_arch = "wasm32"); + let supports_threads = !cfg!(target_os = "emscripten") && !cfg!(target_family = "wasm"); if concurrency == Concurrent::Yes && supports_threads { let cfg = thread::Builder::new().name(name.as_slice().to_owned()); let mut runtest = Arc::new(Mutex::new(Some(runtest))); diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index e263780bf3..079626f0fe 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -5,7 +5,6 @@ #![feature(native_link_modifiers_bundle)] #![feature(nll)] #![feature(staged_api)] -#![feature(static_nobundle)] #![feature(c_unwind)] #![cfg_attr(not(target_env = "msvc"), feature(libc))] diff --git a/src/bootstrap/CHANGELOG.md b/src/bootstrap/CHANGELOG.md index 2f99e36aef..2bc7ffb0c5 100644 --- a/src/bootstrap/CHANGELOG.md +++ b/src/bootstrap/CHANGELOG.md @@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - `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) - Add options for enabling overflow checks, one for std (`overflow-checks-std`) and one for everything else (`overflow-checks`). Both default to false. +- Change the names for `dist` commmands to match the component they generate. [#90684](https://github.com/rust-lang/rust/pull/90684) ### Non-breaking changes diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index ac8bbfe102..ed53a98e9a 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -146,7 +146,7 @@ fn main() { } let is_test = args.iter().any(|a| a == "--test"); - if verbose > 1 { + if verbose > 2 { let rust_env_vars = env::vars().filter(|(k, _)| k.starts_with("RUST") || k.starts_with("CARGO")); let prefix = if is_test { "[RUSTC-SHIM] rustc --test" } else { "[RUSTC-SHIM] rustc" }; diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 0170be967e..22f2e405a1 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -492,10 +492,11 @@ class RustBuild(object): def downloading_llvm(self): opt = self.get_toml('download-ci-llvm', 'llvm') - # This is currently all tier 1 targets (since others may not have CI - # artifacts) + # This is currently all tier 1 targets and tier 2 targets with host tools + # (since others may not have CI artifacts) # https://doc.rust-lang.org/rustc/platform-support.html#tier-1 supported_platforms = [ + # tier 1 "aarch64-unknown-linux-gnu", "i686-pc-windows-gnu", "i686-pc-windows-msvc", @@ -504,6 +505,26 @@ class RustBuild(object): "x86_64-apple-darwin", "x86_64-pc-windows-gnu", "x86_64-pc-windows-msvc", + # tier 2 with host tools + "aarch64-apple-darwin", + "aarch64-pc-windows-msvc", + "aarch64-unknown-linux-musl", + "arm-unknown-linux-gnueabi", + "arm-unknown-linux-gnueabihf", + "armv7-unknown-linux-gnueabihf", + "mips-unknown-linux-gnu", + "mips64-unknown-linux-gnuabi64", + "mips64el-unknown-linux-gnuabi64", + "mipsel-unknown-linux-gnu", + "powerpc-unknown-linux-gnu", + "powerpc64-unknown-linux-gnu", + "powerpc64le-unknown-linux-gnu", + "riscv64gc-unknown-linux-gnu", + "s390x-unknown-linux-gnu", + "x86_64-unknown-freebsd", + "x86_64-unknown-illumos", + "x86_64-unknown-linux-musl", + "x86_64-unknown-netbsd", ] return opt == "true" \ or (opt == "if-available" and self.build in supported_platforms) @@ -959,7 +980,7 @@ class RustBuild(object): self.cargo())) args = [self.cargo(), "build", "--manifest-path", os.path.join(self.rust_root, "src/bootstrap/Cargo.toml")] - for _ in range(1, self.verbose): + for _ in range(0, self.verbose): args.append("--verbose") if self.use_locked_deps: args.append("--locked") @@ -1005,7 +1026,15 @@ class RustBuild(object): if self.git_version >= distutils.version.LooseVersion("2.11.0"): update_args.append("--progress") update_args.append(module) - run(update_args, cwd=self.rust_root, verbose=self.verbose, exception=True) + try: + run(update_args, cwd=self.rust_root, verbose=self.verbose, exception=True) + except RuntimeError: + print("Failed updating submodule. This is probably due to uncommitted local changes.") + print('Either stash the changes by running "git stash" within the submodule\'s') + print('directory, reset them by running "git reset --hard", or commit them.') + print("To reset all submodules' changes run", end=" ") + print('"git submodule foreach --recursive git reset --hard".') + raise SystemExit(1) run(["git", "reset", "-q", "--hard"], cwd=module_path, verbose=self.verbose) @@ -1090,17 +1119,22 @@ class RustBuild(object): raise Exception("{} not found".format(vendor_dir)) if self.use_vendored_sources: + config = ("[source.crates-io]\n" + "replace-with = 'vendored-sources'\n" + "registry = 'https://example.com'\n" + "\n" + "[source.vendored-sources]\n" + "directory = '{}/vendor'\n" + .format(self.rust_root)) if not os.path.exists('.cargo'): os.makedirs('.cargo') - with output('.cargo/config') as cargo_config: - cargo_config.write( - "[source.crates-io]\n" - "replace-with = 'vendored-sources'\n" - "registry = 'https://example.com'\n" - "\n" - "[source.vendored-sources]\n" - "directory = '{}/vendor'\n" - .format(self.rust_root)) + with output('.cargo/config') as cargo_config: + cargo_config.write(config) + else: + print('info: using vendored source, but .cargo/config is already present.') + print(' Reusing the current configuration file. But you may want to ' + 'configure vendoring like this:') + print(config) else: if os.path.exists('.cargo'): shutil.rmtree('.cargo') diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 6750f7a549..6ba1b1b603 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -482,6 +482,7 @@ impl<'a> Builder<'a> { doc::RustByExample, doc::RustcBook, doc::CargoBook, + doc::Clippy, doc::EmbeddedBook, doc::EditionGuide, ), @@ -972,8 +973,26 @@ impl<'a> Builder<'a> { } } - if self.config.rust_new_symbol_mangling { + let use_new_symbol_mangling = match self.config.rust_new_symbol_mangling { + Some(setting) => { + // If an explicit setting is given, use that + setting + } + None => { + if mode == Mode::Std { + // The standard library defaults to the legacy scheme + false + } else { + // The compiler and tools default to the new scheme + true + } + } + }; + + if use_new_symbol_mangling { rustflags.arg("-Zsymbol-mangling-version=v0"); + } else { + rustflags.arg("-Zsymbol-mangling-version=legacy"); } // FIXME: It might be better to use the same value for both `RUSTFLAGS` and `RUSTDOCFLAGS`, @@ -1483,7 +1502,7 @@ impl<'a> Builder<'a> { cargo.env("WINAPI_NO_BUNDLED_LIBRARIES", "1"); } - for _ in 1..self.verbosity { + for _ in 0..self.verbosity { cargo.arg("-v"); } diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index e9cc7662e6..007ca9f7f5 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -197,7 +197,7 @@ fn copy_self_contained_objects( t!(fs::create_dir_all(&libdir_self_contained)); let mut target_deps = vec![]; - // Copies the CRT objects. + // Copies the libc and CRT objects. // // rustc historically provides a more self-contained installation for musl targets // not requiring the presence of a native musl toolchain. For example, it can fall back @@ -208,7 +208,7 @@ fn copy_self_contained_objects( let srcdir = builder.musl_libdir(target).unwrap_or_else(|| { panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple) }); - for &obj in &["crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] { + for &obj in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] { copy_and_stamp( builder, &libdir_self_contained, @@ -235,7 +235,7 @@ fn copy_self_contained_objects( panic!("Target {:?} does not have a \"wasi-root\" key", target.triple) }) .join("lib/wasm32-wasi"); - for &obj in &["crt1-command.o", "crt1-reactor.o"] { + for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] { copy_and_stamp( builder, &libdir_self_contained, diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index e658d958d0..68e20f90b7 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -90,6 +90,7 @@ pub struct Config { // llvm codegen options pub llvm_skip_rebuild: bool, pub llvm_assertions: bool, + pub llvm_tests: bool, pub llvm_plugins: bool, pub llvm_optimize: bool, pub llvm_thin_lto: bool, @@ -140,7 +141,7 @@ pub struct Config { pub rust_verify_llvm_ir: bool, pub rust_thin_lto_import_instr_limit: Option, pub rust_remap_debuginfo: bool, - pub rust_new_symbol_mangling: bool, + pub rust_new_symbol_mangling: Option, pub rust_profile_use: Option, pub rust_profile_generate: Option, pub llvm_profile_use: Option, @@ -422,6 +423,7 @@ struct Llvm { thin_lto: Option, release_debuginfo: Option, assertions: Option, + tests: Option, plugins: Option, ccache: Option, version_check: Option, @@ -715,6 +717,7 @@ impl Config { // Store off these values as options because if they're not provided // we'll infer default values for them later let mut llvm_assertions = None; + let mut llvm_tests = None; let mut llvm_plugins = None; let mut debug = None; let mut debug_assertions = None; @@ -740,6 +743,7 @@ impl Config { } set(&mut config.ninja_in_file, llvm.ninja); llvm_assertions = llvm.assertions; + llvm_tests = llvm.tests; llvm_plugins = llvm.plugins; llvm_skip_rebuild = llvm_skip_rebuild.or(llvm.skip_rebuild); set(&mut config.llvm_optimize, llvm.optimize); @@ -765,10 +769,12 @@ impl Config { config.llvm_from_ci = match llvm.download_ci_llvm { Some(StringOrBool::String(s)) => { assert!(s == "if-available", "unknown option `{}` for download-ci-llvm", s); - // This is currently all tier 1 targets (since others may not have CI artifacts) + // This is currently all tier 1 targets and tier 2 targets with host tools + // (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 = [ + // tier 1 "aarch64-unknown-linux-gnu", "i686-pc-windows-gnu", "i686-pc-windows-msvc", @@ -777,6 +783,26 @@ impl Config { "x86_64-apple-darwin", "x86_64-pc-windows-gnu", "x86_64-pc-windows-msvc", + // tier 2 with host tools + "aarch64-apple-darwin", + "aarch64-pc-windows-msvc", + "aarch64-unknown-linux-musl", + "arm-unknown-linux-gnueabi", + "arm-unknown-linux-gnueabihf", + "armv7-unknown-linux-gnueabihf", + "mips-unknown-linux-gnu", + "mips64-unknown-linux-gnuabi64", + "mips64el-unknown-linux-gnuabi64", + "mipsel-unknown-linux-gnu", + "powerpc-unknown-linux-gnu", + "powerpc64-unknown-linux-gnu", + "powerpc64le-unknown-linux-gnu", + "riscv64gc-unknown-linux-gnu", + "s390x-unknown-linux-gnu", + "x86_64-unknown-freebsd", + "x86_64-unknown-illumos", + "x86_64-unknown-linux-musl", + "x86_64-unknown-netbsd", ]; supported_platforms.contains(&&*config.build.triple) } @@ -848,7 +874,7 @@ impl Config { config.rust_run_dsymutil = rust.run_dsymutil.unwrap_or(false); optimize = rust.optimize; ignore_git = rust.ignore_git; - set(&mut config.rust_new_symbol_mangling, rust.new_symbol_mangling); + config.rust_new_symbol_mangling = rust.new_symbol_mangling; set(&mut config.rust_optimize_tests, rust.optimize_tests); set(&mut config.codegen_tests, rust.codegen_tests); set(&mut config.rust_rpath, rust.rpath); @@ -969,6 +995,7 @@ impl Config { config.llvm_skip_rebuild = llvm_skip_rebuild.unwrap_or(false); config.llvm_assertions = llvm_assertions.unwrap_or(false); + config.llvm_tests = llvm_tests.unwrap_or(false); config.llvm_plugins = llvm_plugins.unwrap_or(false); config.rust_optimize = optimize.unwrap_or(true); diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index d4875cfe1b..09ea84a083 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -64,7 +64,7 @@ impl Step for Docs { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let default = run.builder.config.docs; - run.path("src/doc").default_condition(default) + run.path("rust-docs").default_condition(default) } fn make_run(run: RunConfig<'_>) { @@ -96,7 +96,8 @@ impl Step for RustcDocs { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path("src/librustc") + let builder = run.builder; + run.path("rustc-docs").default_condition(builder.config.compiler_docs) } fn make_run(run: RunConfig<'_>) { @@ -106,9 +107,6 @@ impl Step for RustcDocs { /// Builds the `rustc-docs` installer component. fn run(self, builder: &Builder<'_>) -> Option { let host = self.host; - if !builder.config.compiler_docs { - return None; - } builder.default_doc(&[]); let mut tarball = Tarball::new(builder, "rustc-docs", &host.triple); @@ -277,7 +275,7 @@ impl Step for Mingw { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.never() + run.path("rust-mingw") } fn make_run(run: RunConfig<'_>) { @@ -318,7 +316,7 @@ impl Step for Rustc { const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path("src/librustc") + run.path("rustc") } fn make_run(run: RunConfig<'_>) { @@ -574,7 +572,7 @@ impl Step for Std { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path("library/std") + run.path("rust-std") } fn make_run(run: RunConfig<'_>) { @@ -688,7 +686,7 @@ impl Step for Analysis { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let default = should_build_extended_tool(&run.builder, "analysis"); - run.path("analysis").default_condition(default) + run.path("rust-analysis").default_condition(default) } fn make_run(run: RunConfig<'_>) { @@ -823,7 +821,7 @@ impl Step for Src { const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path("src") + run.path("rust-src") } fn make_run(run: RunConfig<'_>) { @@ -876,7 +874,7 @@ impl Step for PlainSourceTarball { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; - run.path("src").default_condition(builder.config.rust_dist_src) + run.path("rustc-src").default_condition(builder.config.rust_dist_src) } fn make_run(run: RunConfig<'_>) { @@ -2122,7 +2120,7 @@ impl Step for BuildManifest { const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path("src/tools/build-manifest") + run.path("build-manifest") } fn make_run(run: RunConfig<'_>) { @@ -2154,7 +2152,7 @@ impl Step for ReproducibleArtifacts { const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path("reproducible") + run.path("reproducible-artifacts") } fn make_run(run: RunConfig<'_>) { diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 6f2470b706..f0f31c447b 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -529,7 +529,7 @@ impl Step for Rustc { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; - run.krate("rustc-main").path("compiler").default_condition(builder.config.docs) + run.krate("rustc-main").path("compiler").default_condition(builder.config.compiler_docs) } fn make_run(run: RunConfig<'_>) { @@ -560,11 +560,6 @@ impl Step for Rustc { }) .collect::>(); - if !builder.config.compiler_docs && !builder.was_invoked_explicitly::() { - builder.info("\tskipping - compiler/librustdoc docs disabled"); - return; - } - // This is the intended out directory for compiler documentation. let out = builder.compiler_doc_out(target); t!(fs::create_dir_all(&out)); @@ -674,7 +669,8 @@ macro_rules! tool_doc { const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.krate($should_run) + let builder = run.builder; + run.krate($should_run).default_condition(builder.config.compiler_docs) } fn make_run(run: RunConfig<'_>) { @@ -705,11 +701,6 @@ macro_rules! tool_doc { let compiler = builder.compiler(stage, builder.config.build); - if !builder.config.compiler_docs && !builder.was_invoked_explicitly::() { - builder.info("\tskipping - compiler/tool docs disabled"); - return; - } - // Build rustc docs so that we generate relative links. builder.ensure(Rustc { stage, target }); @@ -755,6 +746,7 @@ tool_doc!( "src/tools/rustfmt", ["rustfmt-nightly", "rustfmt-config_proc_macro"], ); +tool_doc!(Clippy, "clippy", "src/tools/clippy", ["clippy_utils"]); #[derive(Ord, PartialOrd, Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct ErrorIndex { diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 2d4e152789..1667dfc3f8 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -277,7 +277,6 @@ pub struct Build { struct Crate { name: Interned, deps: HashSet>, - id: String, path: PathBuf, } @@ -494,7 +493,7 @@ impl Build { // NOTE: The check for the empty directory is here because when running x.py the first time, // the submodule won't be checked out. Check it out now so we can build it. - if !channel::GitInfo::new(false, relative_path).is_git() && !dir_is_empty(&absolute_path) { + if !channel::GitInfo::new(false, &absolute_path).is_git() && !dir_is_empty(&absolute_path) { return; } diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs index a38391c7b8..65e229697d 100644 --- a/src/bootstrap/metadata.rs +++ b/src/bootstrap/metadata.rs @@ -14,7 +14,6 @@ struct Output { #[derive(Deserialize)] struct Package { - id: String, name: String, source: Option, manifest_path: String, @@ -50,7 +49,7 @@ pub fn build(build: &mut Build) { .filter(|dep| dep.source.is_none()) .map(|dep| INTERNER.intern_string(dep.name)) .collect(); - build.crates.insert(name, Crate { name, id: package.id, deps, path }); + build.crates.insert(name, Crate { name, deps, path }); } } } diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 27c9bb2504..37578e30f6 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -170,6 +170,7 @@ impl Step for Llvm { let assertions = if builder.config.llvm_assertions { "ON" } else { "OFF" }; let plugins = if builder.config.llvm_plugins { "ON" } else { "OFF" }; + let enable_tests = if builder.config.llvm_tests { "ON" } else { "OFF" }; cfg.out_dir(&out_dir) .profile(profile) @@ -180,7 +181,7 @@ impl Step for Llvm { .define("LLVM_INCLUDE_EXAMPLES", "OFF") .define("LLVM_INCLUDE_DOCS", "OFF") .define("LLVM_INCLUDE_BENCHMARKS", "OFF") - .define("LLVM_INCLUDE_TESTS", "OFF") + .define("LLVM_INCLUDE_TESTS", enable_tests) .define("LLVM_ENABLE_TERMINFO", "OFF") .define("LLVM_ENABLE_LIBEDIT", "OFF") .define("LLVM_ENABLE_BINDINGS", "OFF") @@ -377,11 +378,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 >= 10 { + if major >= 12 { return; } } - panic!("\n\nbad LLVM version: {}, need >=10.0\n\n", version) + panic!("\n\nbad LLVM version: {}, need >=12.0\n\n", version) } fn configure_cmake( diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 8594fa4226..cb1b0ebf8d 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -763,7 +763,7 @@ impl Step for RustdocJSStd { const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path("src/test/rustdoc-js-std") + run.suite_path("src/test/rustdoc-js-std") } fn make_run(run: RunConfig<'_>) { @@ -783,6 +783,17 @@ impl Step for RustdocJSStd { .arg(builder.doc_out(self.target)) .arg("--test-folder") .arg(builder.src.join("src/test/rustdoc-js-std")); + for path in &builder.paths { + if let Some(p) = + util::is_valid_test_suite_arg(path, "src/test/rustdoc-js-std", builder) + { + if !p.ends_with(".js") { + eprintln!("A non-js file was given: `{}`", path.display()); + panic!("Cannot run rustdoc-js-std tests"); + } + command.arg("--test-file").arg(path); + } + } builder.ensure(crate::doc::Std { target: self.target, stage: builder.top_stage }); builder.run(&mut command); } else { @@ -803,7 +814,7 @@ impl Step for RustdocJSNotStd { const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path("src/test/rustdoc-js") + run.suite_path("src/test/rustdoc-js") } fn make_run(run: RunConfig<'_>) { @@ -938,8 +949,12 @@ impl Step for RustdocGUI { .arg("--tests-folder") .arg(builder.build.src.join("src/test/rustdoc-gui")); for path in &builder.paths { - if let Some(name) = path.file_name().and_then(|f| f.to_str()) { - if name.ends_with(".goml") { + if let Some(p) = util::is_valid_test_suite_arg(path, "src/test/rustdoc-gui", builder) { + if !p.ends_with(".goml") { + eprintln!("A non-goml file was given: `{}`", path.display()); + panic!("Cannot run rustdoc-gui tests"); + } + if let Some(name) = path.file_name().and_then(|f| f.to_str()) { command.arg("--file").arg(name); } } @@ -1261,7 +1276,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the builder.ensure(native::TestHelpers { target: compiler.host }); // As well as the target, except for plain wasm32, which can't build it - if !target.contains("wasm32") || target.contains("emscripten") { + if !target.contains("wasm") || target.contains("emscripten") { builder.ensure(native::TestHelpers { target }); } @@ -1416,35 +1431,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the // Get test-args by striping suite path let mut test_args: Vec<&str> = paths .iter() - .map(|p| match p.strip_prefix(".") { - Ok(path) => path, - Err(_) => p, - }) - .filter(|p| p.starts_with(suite_path)) - .filter(|p| { - let exists = p.is_dir() || p.is_file(); - if !exists { - if let Some(p) = p.to_str() { - builder.info(&format!( - "Warning: Skipping \"{}\": not a regular file or directory", - p - )); - } - } - exists - }) - .filter_map(|p| { - // Since test suite paths are themselves directories, if we don't - // specify a directory or file, we'll get an empty string here - // (the result of the test suite directory without its suite prefix). - // Therefore, we need to filter these out, as only the first --test-args - // flag is respected, so providing an empty --test-args conflicts with - // any following it. - match p.strip_prefix(suite_path).ok().and_then(|p| p.to_str()) { - Some(s) if !s.is_empty() => Some(s), - _ => None, - } - }) + .filter_map(|p| util::is_valid_test_suite_arg(p, suite_path, builder)) .collect(); test_args.append(&mut builder.config.cmd.test_args()); diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index af6f4bb0e5..1317c3f983 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -286,7 +286,6 @@ macro_rules! bootstrap_tool { $name:ident, $path:expr, $tool_name:expr $(,is_external_tool = $external:expr)* $(,is_unstable_tool = $unstable:expr)* - $(,features = $features:expr)* ; )+) => { #[derive(Copy, PartialEq, Eq, Clone)] @@ -349,12 +348,7 @@ macro_rules! bootstrap_tool { } else { SourceType::InTree }, - extra_features: { - // FIXME(#60643): avoid this lint by using `_` - let mut _tmp = Vec::new(); - $(_tmp.extend($features);)* - _tmp - }, + extra_features: vec![], }).expect("expected to build -- essential tool") } } diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 112979b0be..57178aa382 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -310,3 +310,35 @@ pub fn use_host_linker(target: TargetSelection) -> bool { || target.contains("fuchsia") || target.contains("bpf")) } + +pub fn is_valid_test_suite_arg<'a, P: AsRef>( + path: &'a Path, + suite_path: P, + builder: &Builder<'_>, +) -> Option<&'a str> { + let suite_path = suite_path.as_ref(); + let path = match path.strip_prefix(".") { + Ok(p) => p, + Err(_) => path, + }; + if !path.starts_with(suite_path) { + return None; + } + let exists = path.is_dir() || path.is_file(); + if !exists { + if let Some(p) = path.to_str() { + builder.info(&format!("Warning: Skipping \"{}\": not a regular file or directory", p)); + } + return None; + } + // Since test suite paths are themselves directories, if we don't + // specify a directory or file, we'll get an empty string here + // (the result of the test suite directory without its suite prefix). + // Therefore, we need to filter these out, as only the first --test-args + // flag is respected, so providing an empty --test-args conflicts with + // any following it. + match path.strip_prefix(suite_path).ok().and_then(|p| p.to_str()) { + Some(s) if !s.is_empty() => Some(s), + _ => None, + } +} diff --git a/src/ci/docker/host-x86_64/disabled/asmjs/Dockerfile b/src/ci/docker/host-x86_64/disabled/asmjs/Dockerfile index e04f6409f5..07dcb9ea92 100644 --- a/src/ci/docker/host-x86_64/disabled/asmjs/Dockerfile +++ b/src/ci/docker/host-x86_64/disabled/asmjs/Dockerfile @@ -40,3 +40,4 @@ ENV SCRIPT python3 ../x.py --stage 2 test --host='' --target $TARGETS # running with assertions again is not useful ENV NO_DEBUG_ASSERTIONS=1 ENV NO_LLVM_ASSERTIONS=1 +ENV NO_OVERFLOW_CHECKS=1 diff --git a/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile index 1be3fecd88..61cc000dca 100644 --- a/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile @@ -8,6 +8,7 @@ RUN sh /scripts/crosstool-ng-1.24.sh WORKDIR /build +COPY scripts/musl-patch-configure.diff /build/ COPY scripts/musl-toolchain.sh /build/ # We need to mitigate rust-lang/rust#34978 when compiling musl itself as well RUN CFLAGS="-Wa,--compress-debug-sections=none -Wl,--compress-debug-sections=none" \ diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile index 5045234993..efc83c6cca 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile @@ -125,7 +125,7 @@ ENV RUST_CONFIGURE_ARGS \ ENV SCRIPT ../src/ci/pgo.sh python3 ../x.py dist \ --host $HOSTS --target $HOSTS \ --include-default-paths \ - src/tools/build-manifest + build-manifest ENV CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=clang # This is the only builder which will create source tarballs diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh index ed5edfec4e..562be752f8 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh @@ -4,7 +4,7 @@ set -ex source shared.sh -LLVM=llvmorg-12.0.1 +LLVM=llvmorg-13.0.0 mkdir llvm-project cd llvm-project 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 ea70771a57..ef49904b53 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 @@ -24,6 +24,7 @@ WORKDIR /build/ COPY scripts/cmake.sh /scripts/ RUN /scripts/cmake.sh +COPY scripts/musl-patch-configure.diff /build/ COPY scripts/musl-toolchain.sh /build/ # We need to mitigate rust-lang/rust#34978 when compiling musl itself as well RUN CFLAGS="-Wa,-mrelax-relocations=no -Wa,--compress-debug-sections=none -Wl,--compress-debug-sections=none" \ diff --git a/src/ci/docker/host-x86_64/test-various/Dockerfile b/src/ci/docker/host-x86_64/test-various/Dockerfile index ad0e8e9f92..4d554a2852 100644 --- a/src/ci/docker/host-x86_64/test-various/Dockerfile +++ b/src/ci/docker/host-x86_64/test-various/Dockerfile @@ -22,6 +22,7 @@ RUN curl -sL https://nodejs.org/dist/v15.14.0/node-v15.14.0-linux-x64.tar.xz | \ tar -xJ WORKDIR /build/ +COPY scripts/musl-patch-configure.diff /build/ COPY scripts/musl-toolchain.sh /build/ RUN bash musl-toolchain.sh x86_64 && rm -rf build WORKDIR / @@ -39,6 +40,7 @@ ENV RUST_CONFIGURE_ARGS \ # otherwise normally be. We already test libstd with debug assertions in lots of # other contexts as well ENV NO_DEBUG_ASSERTIONS=1 +ENV NO_OVERFLOW_CHECKS=1 ENV WASM_TARGETS=wasm32-unknown-unknown ENV WASM_SCRIPT python3 /checkout/x.py --stage 2 test --host='' --target $WASM_TARGETS \ diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-10/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-12/Dockerfile similarity index 93% rename from src/ci/docker/host-x86_64/x86_64-gnu-llvm-10/Dockerfile rename to src/ci/docker/host-x86_64/x86_64-gnu-llvm-12/Dockerfile index c34198708c..df1fbc29cf 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-10/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-12/Dockerfile @@ -1,5 +1,6 @@ -FROM ubuntu:18.04 +FROM ubuntu:20.04 +ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y --no-install-recommends \ g++ \ gcc-multilib \ @@ -13,8 +14,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ cmake \ sudo \ gdb \ - llvm-10-tools \ - llvm-10-dev \ + llvm-12-tools \ + llvm-12-dev \ libedit-dev \ libssl-dev \ pkg-config \ @@ -28,7 +29,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-10 \ + --llvm-root=/usr/lib/llvm-12 \ --enable-llvm-link-shared \ --set rust.thin-lto-import-instr-limit=10 diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile index adc970c66d..f71282a1b5 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile @@ -72,7 +72,7 @@ ENV PATH="/node-v14.4.0-linux-x64/bin:${PATH}" # https://github.com/puppeteer/puppeteer/issues/375 # # We also specify the version in case we need to update it to go around cache limitations. -RUN npm install -g browser-ui-test@0.4.3 --unsafe-perm=true +RUN npm install -g browser-ui-test@0.5.0 --unsafe-perm=true ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index 00e8666c54..93b4f435d4 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -71,8 +71,13 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then echo "Attempting to download $url" rm -f /tmp/rustci_docker_cache set +e - retry curl -y 30 -Y 10 --connect-timeout 30 -f -L -C - -o /tmp/rustci_docker_cache "$url" - loaded_images=$(docker load -i /tmp/rustci_docker_cache | sed 's/.* sha/sha/') + retry curl --max-time 600 -y 30 -Y 10 --connect-timeout 30 -f -L -C - \ + -o /tmp/rustci_docker_cache "$url" + echo "Loading images into docker" + # docker load sometimes hangs in the CI, so time out after 10 minutes with TERM, + # KILL after 12 minutes + loaded_images=$(/usr/bin/timeout -k 720 600 docker load -i /tmp/rustci_docker_cache \ + | sed 's/.* sha/sha/') set -e echo "Downloaded containers:\n$loaded_images" fi diff --git a/src/ci/docker/scripts/freebsd-toolchain.sh b/src/ci/docker/scripts/freebsd-toolchain.sh index 70c57e07fd..de6b52a5e0 100755 --- a/src/ci/docker/scripts/freebsd-toolchain.sh +++ b/src/ci/docker/scripts/freebsd-toolchain.sh @@ -53,7 +53,7 @@ files_to_extract=( for lib in c cxxrt gcc_s m thr util; do files_to_extract=("${files_to_extract[@]}" "./lib/lib${lib}.*" "./usr/lib/lib${lib}.*") done -for lib in c++ c_nonshared compiler_rt execinfo gcc pthread rt ssp_nonshared procstat; do +for lib in c++ c_nonshared compiler_rt execinfo gcc pthread rt ssp_nonshared procstat kvm; do files_to_extract=("${files_to_extract[@]}" "./usr/lib/lib${lib}.*") done diff --git a/src/ci/docker/scripts/musl-patch-configure.diff b/src/ci/docker/scripts/musl-patch-configure.diff new file mode 100644 index 0000000000..6e106b4504 --- /dev/null +++ b/src/ci/docker/scripts/musl-patch-configure.diff @@ -0,0 +1,13 @@ +diff --git a/configure b/configure +index 86801281..ed2f7998 100755 +--- a/configure ++++ b/configure +@@ -398,7 +398,7 @@ test "$debug" = yes && CFLAGS_AUTO=-g + # + printf "checking whether we should preprocess assembly to add debugging information... " + if fnmatch '-g*|*\ -g*' "$CFLAGS_AUTO $CFLAGS" && +- test -f "tools/add-cfi.$ARCH.awk" && ++ test -f "$srcdir/tools/add-cfi.$ARCH.awk" && + printf ".file 1 \"srcfile.s\"\n.line 1\n.cfi_startproc\n.cfi_endproc" | $CC -g -x assembler -c -o /dev/null 2>/dev/null - + then + ADD_CFI=yes diff --git a/src/ci/docker/scripts/musl-toolchain.sh b/src/ci/docker/scripts/musl-toolchain.sh index 59fc921ec2..3c17f316d1 100644 --- a/src/ci/docker/scripts/musl-toolchain.sh +++ b/src/ci/docker/scripts/musl-toolchain.sh @@ -38,13 +38,20 @@ shift # Ancient binutils versions don't understand debug symbols produced by more recent tools. # Apparently applying `-fPIC` everywhere allows them to link successfully. -export CFLAGS="-fPIC $CFLAGS" +# Enable debug info. If we don't do so, users can't debug into musl code, +# debuggers can't walk the stack, etc. Fixes #90103. +export CFLAGS="-fPIC -g1 $CFLAGS" git clone https://github.com/richfelker/musl-cross-make # -b v0.9.9 cd musl-cross-make # A few commits ahead of v0.9.9 to include the cowpatch fix: git checkout a54eb56f33f255dfca60be045f12a5cfaf5a72a9 +# Fix the cfi detection script in musl's configure so cfi is generated +# when debug info is asked for. +mkdir patches/musl-1.1.24 +cp ../musl-patch-configure.diff patches/musl-1.1.24/0001-fix-cfi-detection.diff + hide_output make -j$(nproc) TARGET=$TARGET MUSL_VER=1.1.24 LINUX_HEADERS_SITE=$LINUX_HEADERS_SITE hide_output make install TARGET=$TARGET MUSL_VER=1.1.24 LINUX_HEADERS_SITE=$LINUX_HEADERS_SITE OUTPUT=$OUTPUT diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index eb16cf3c76..96af401369 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -284,7 +284,7 @@ jobs: - name: mingw-check <<: *job-linux-xl - - name: x86_64-gnu-llvm-10 + - name: x86_64-gnu-llvm-12 <<: *job-linux-xl - name: x86_64-gnu-tools @@ -431,7 +431,7 @@ jobs: - name: x86_64-gnu-distcheck <<: *job-linux-xl - - name: x86_64-gnu-llvm-10 + - name: x86_64-gnu-llvm-12 env: RUST_BACKTRACE: 1 <<: *job-linux-xl @@ -448,14 +448,17 @@ jobs: # macOS Builders # #################### + # Only generate documentation for x86_64-apple-darwin, not other + # tier 2 targets produced by this builder. - name: dist-x86_64-apple env: - SCRIPT: ./x.py dist + SCRIPT: ./x.py dist --exclude rust-docs --exclude extended && ./x.py dist --target=x86_64-apple-darwin rust-docs && ./x.py dist extended RUST_CONFIGURE_ARGS: --host=x86_64-apple-darwin --target=x86_64-apple-darwin,aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.7 NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 + NO_OVERFLOW_CHECKS: 1 DIST_REQUIRE_ALL_TOOLS: 1 <<: *job-macos-xl @@ -467,6 +470,7 @@ jobs: MACOSX_DEPLOYMENT_TARGET: 10.7 NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 + NO_OVERFLOW_CHECKS: 1 <<: *job-macos-xl - name: x86_64-apple @@ -478,6 +482,7 @@ jobs: MACOSX_STD_DEPLOYMENT_TARGET: 10.7 NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 + NO_OVERFLOW_CHECKS: 1 <<: *job-macos-xl # This target only needs to support 11.0 and up as nothing else supports the hardware @@ -499,6 +504,7 @@ jobs: MACOSX_STD_DEPLOYMENT_TARGET: 11.0 NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 + NO_OVERFLOW_CHECKS: 1 DIST_REQUIRE_ALL_TOOLS: 1 # Corresponds to 16K page size # @@ -666,7 +672,9 @@ jobs: strategy: matrix: include: - - *dist-x86_64-linux + - &dist-x86_64-linux + name: dist-x86_64-linux + <<: *job-linux-xl master: name: master diff --git a/src/ci/pgo.sh b/src/ci/pgo.sh index e35e3e670c..29ef13a60f 100755 --- a/src/ci/pgo.sh +++ b/src/ci/pgo.sh @@ -4,9 +4,13 @@ set -euxo pipefail rm -rf /tmp/rustc-pgo +# We collect LLVM profiling information and rustc profiling information in +# separate phases. This increases build time -- though not by a huge amount -- +# but prevents any problems from arising due to different profiling runtimes +# being simultaneously linked in. + python3 ../x.py build --target=$PGO_HOST --host=$PGO_HOST \ --stage 2 library/std \ - --rust-profile-generate=/tmp/rustc-pgo \ --llvm-profile-generate # Profile libcore compilation in opt-level=0 and opt-level=3 @@ -15,6 +19,29 @@ RUSTC_BOOTSTRAP=1 ./build/$PGO_HOST/stage2/bin/rustc --edition=2018 \ RUSTC_BOOTSTRAP=1 ./build/$PGO_HOST/stage2/bin/rustc --edition=2018 \ --crate-type=lib -Copt-level=3 ../library/core/src/lib.rs +# Merge the profile data we gathered for LLVM +# Note that this uses the profdata from the clang we used to build LLVM, +# which likely has a different version than our in-tree clang. +/rustroot/bin/llvm-profdata \ + merge -o /tmp/llvm-pgo.profdata ./build/$PGO_HOST/llvm/build/profiles + +# Rustbuild currently doesn't support rebuilding LLVM when PGO options +# change (or any other llvm-related options); so just clear out the relevant +# directories ourselves. +rm -r ./build/$PGO_HOST/llvm ./build/$PGO_HOST/lld + +# Okay, LLVM profiling is done, switch to rustc PGO. + +python3 ../x.py build --target=$PGO_HOST --host=$PGO_HOST \ + --stage 2 library/std \ + --rust-profile-generate=/tmp/rustc-pgo + +# Profile libcore compilation in opt-level=0 and opt-level=3 +RUSTC_BOOTSTRAP=1 ./build/$PGO_HOST/stage2/bin/rustc --edition=2018 \ + --crate-type=lib ../library/core/src/lib.rs +RUSTC_BOOTSTRAP=1 ./build/$PGO_HOST/stage2/bin/rustc --edition=2018 \ + --crate-type=lib -Copt-level=3 ../library/core/src/lib.rs + cp -r /tmp/rustc-perf ./ chown -R $(whoami): ./rustc-perf cd rustc-perf @@ -46,18 +73,13 @@ cd /checkout/obj ./build/$PGO_HOST/llvm/bin/llvm-profdata \ merge -o /tmp/rustc-pgo.profdata /tmp/rustc-pgo -# Merge the profile data we gathered for LLVM -# Note that this uses the profdata from the clang we used to build LLVM, -# which likely has a different version than our in-tree clang. -/rustroot/bin/llvm-profdata \ - merge -o /tmp/llvm-pgo.profdata ./build/$PGO_HOST/llvm/build/profiles - # Rustbuild currently doesn't support rebuilding LLVM when PGO options # change (or any other llvm-related options); so just clear out the relevant # directories ourselves. rm -r ./build/$PGO_HOST/llvm ./build/$PGO_HOST/lld -# This produces the actual final set of artifacts. +# This produces the actual final set of artifacts, using both the LLVM and rustc +# collected profiling data. $@ \ --rust-profile-use=/tmp/rustc-pgo.profdata \ --llvm-profile-use=/tmp/llvm-pgo.profdata diff --git a/src/ci/run.sh b/src/ci/run.sh index b5019d83af..948445427d 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -43,7 +43,7 @@ else PYTHON="python2" fi -if ! isCI || isCiBranch auto || isCiBranch beta; then +if ! isCI || isCiBranch auto || isCiBranch beta || isCiBranch try; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.print-step-timings --enable-verbose-tests" fi @@ -89,6 +89,11 @@ else RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-debug-assertions" fi + # Same for overflow checks + if [ "$NO_OVERFLOW_CHECKS" = "" ]; then + RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-overflow-checks" + fi + # In general we always want to run tests with LLVM assertions enabled, but not # all platforms currently support that, so we have an option to disable. if [ "$NO_LLVM_ASSERTIONS" = "" ]; then @@ -112,7 +117,7 @@ datecheck() { echo -n " local time: " date echo -n " network time: " - curl -fs --head http://detectportal.firefox.com/success.txt | grep ^Date: \ + curl -fs --head http://ci-caches.rust-lang.org | grep ^Date: \ | sed 's/Date: //g' || true echo "== end clock drift check ==" } diff --git a/src/doc/book/2018-edition/src/SUMMARY.md b/src/doc/book/2018-edition/src/SUMMARY.md index 57a1916da4..db8991c003 100644 --- a/src/doc/book/2018-edition/src/SUMMARY.md +++ b/src/doc/book/2018-edition/src/SUMMARY.md @@ -48,7 +48,7 @@ - [Error Handling](ch09-00-error-handling.md) - [Unrecoverable Errors with `panic!`](ch09-01-unrecoverable-errors-with-panic.md) - [Recoverable Errors with `Result`](ch09-02-recoverable-errors-with-result.md) - - [To `panic!` or Not To `panic!`](ch09-03-to-panic-or-not-to-panic.md) + - [To `panic!` or Not to `panic!`](ch09-03-to-panic-or-not-to-panic.md) - [Generic Types, Traits, and Lifetimes](ch10-00-generics.md) - [Generic Data Types](ch10-01-syntax.md) diff --git a/src/doc/book/listings/ch09-error-handling/listing-09-10/Cargo.lock b/src/doc/book/listings/ch09-error-handling/listing-09-10/Cargo.lock index 0a2f222c21..1fa96b7974 100644 --- a/src/doc/book/listings/ch09-error-handling/listing-09-10/Cargo.lock +++ b/src/doc/book/listings/ch09-error-handling/listing-09-10/Cargo.lock @@ -1,83 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "getrandom" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "guessing_game" +name = "error-handling" version = "0.1.0" -dependencies = [ - "rand", -] -[[package]] -name = "libc" -version = "0.2.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" - -[[package]] -name = "ppv-lite86" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" - -[[package]] -name = "rand" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", - "rand_hc", -] - -[[package]] -name = "rand_chacha" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" diff --git a/src/doc/book/listings/ch09-error-handling/listing-09-10/Cargo.toml b/src/doc/book/listings/ch09-error-handling/listing-09-10/Cargo.toml index ca796231e8..1e678575c1 100644 --- a/src/doc/book/listings/ch09-error-handling/listing-09-10/Cargo.toml +++ b/src/doc/book/listings/ch09-error-handling/listing-09-10/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "guessing_game" +name = "error-handling" version = "0.1.0" edition = "2018" [dependencies] -rand = "0.8.3" diff --git a/src/doc/book/listings/ch09-error-handling/no-listing-06-question-mark-in-main/output.txt b/src/doc/book/listings/ch09-error-handling/listing-09-10/output.txt similarity index 100% rename from src/doc/book/listings/ch09-error-handling/no-listing-06-question-mark-in-main/output.txt rename to src/doc/book/listings/ch09-error-handling/listing-09-10/output.txt diff --git a/src/doc/book/listings/ch09-error-handling/listing-09-10/src/main.rs b/src/doc/book/listings/ch09-error-handling/listing-09-10/src/main.rs index 3375279461..8608dc13ff 100644 --- a/src/doc/book/listings/ch09-error-handling/listing-09-10/src/main.rs +++ b/src/doc/book/listings/ch09-error-handling/listing-09-10/src/main.rs @@ -1,55 +1,5 @@ -use rand::Rng; -use std::cmp::Ordering; -use std::io; - -// ANCHOR: here -pub struct Guess { - value: i32, -} - -impl Guess { - pub fn new(value: i32) -> Guess { - if value < 1 || value > 100 { - panic!("Guess value must be between 1 and 100, got {}.", value); - } - - Guess { value } - } - - pub fn value(&self) -> i32 { - self.value - } -} -// ANCHOR_END: here +use std::fs::File; fn main() { - println!("Guess the number!"); - - let secret_number = rand::thread_rng().gen_range(1..101); - - loop { - println!("Please input your guess."); - - let mut guess = String::new(); - - io::stdin() - .read_line(&mut guess) - .expect("Failed to read line"); - - let guess: i32 = match guess.trim().parse() { - Ok(num) => num, - Err(_) => continue, - }; - - let guess = Guess::new(guess); - - match guess.value().cmp(&secret_number) { - Ordering::Less => println!("Too small!"), - Ordering::Greater => println!("Too big!"), - Ordering::Equal => { - println!("You win!"); - break; - } - } - } + let f = File::open("hello.txt")?; } diff --git a/src/doc/book/listings/ch09-error-handling/no-listing-07-main-returning-result/Cargo.lock b/src/doc/book/listings/ch09-error-handling/listing-09-11/Cargo.lock similarity index 92% rename from src/doc/book/listings/ch09-error-handling/no-listing-07-main-returning-result/Cargo.lock rename to src/doc/book/listings/ch09-error-handling/listing-09-11/Cargo.lock index 1fa96b7974..7320ae6391 100644 --- a/src/doc/book/listings/ch09-error-handling/no-listing-07-main-returning-result/Cargo.lock +++ b/src/doc/book/listings/ch09-error-handling/listing-09-11/Cargo.lock @@ -1,6 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "error-handling" version = "0.1.0" - diff --git a/src/doc/book/listings/ch09-error-handling/no-listing-06-question-mark-in-main/Cargo.toml b/src/doc/book/listings/ch09-error-handling/listing-09-11/Cargo.toml similarity index 100% rename from src/doc/book/listings/ch09-error-handling/no-listing-06-question-mark-in-main/Cargo.toml rename to src/doc/book/listings/ch09-error-handling/listing-09-11/Cargo.toml diff --git a/src/doc/book/listings/ch09-error-handling/listing-09-11/src/main.rs b/src/doc/book/listings/ch09-error-handling/listing-09-11/src/main.rs new file mode 100644 index 0000000000..bd53227860 --- /dev/null +++ b/src/doc/book/listings/ch09-error-handling/listing-09-11/src/main.rs @@ -0,0 +1,15 @@ +// ANCHOR: here +fn last_char_of_first_line(text: &str) -> Option { + text.lines().next()?.chars().last() +} +// ANCHOR_END: here + +fn main() { + assert_eq!( + last_char_of_first_line("Hello, world\nHow are you today?"), + Some('d') + ); + + assert_eq!(last_char_of_first_line(""), None); + assert_eq!(last_char_of_first_line("\nhi"), None); +} diff --git a/src/doc/book/listings/ch09-error-handling/no-listing-06-question-mark-in-main/Cargo.lock b/src/doc/book/listings/ch09-error-handling/listing-09-12/Cargo.lock similarity index 100% rename from src/doc/book/listings/ch09-error-handling/no-listing-06-question-mark-in-main/Cargo.lock rename to src/doc/book/listings/ch09-error-handling/listing-09-12/Cargo.lock diff --git a/src/doc/book/listings/ch09-error-handling/no-listing-07-main-returning-result/Cargo.toml b/src/doc/book/listings/ch09-error-handling/listing-09-12/Cargo.toml similarity index 100% rename from src/doc/book/listings/ch09-error-handling/no-listing-07-main-returning-result/Cargo.toml rename to src/doc/book/listings/ch09-error-handling/listing-09-12/Cargo.toml diff --git a/src/doc/book/listings/ch09-error-handling/no-listing-07-main-returning-result/src/main.rs b/src/doc/book/listings/ch09-error-handling/listing-09-12/src/main.rs similarity index 100% rename from src/doc/book/listings/ch09-error-handling/no-listing-07-main-returning-result/src/main.rs rename to src/doc/book/listings/ch09-error-handling/listing-09-12/src/main.rs diff --git a/src/doc/book/listings/ch09-error-handling/listing-09-13/Cargo.lock b/src/doc/book/listings/ch09-error-handling/listing-09-13/Cargo.lock new file mode 100644 index 0000000000..0a2f222c21 --- /dev/null +++ b/src/doc/book/listings/ch09-error-handling/listing-09-13/Cargo.lock @@ -0,0 +1,83 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "getrandom" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "guessing_game" +version = "0.1.0" +dependencies = [ + "rand", +] + +[[package]] +name = "libc" +version = "0.2.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" + +[[package]] +name = "ppv-lite86" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" + +[[package]] +name = "rand" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" +dependencies = [ + "rand_core", +] + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" diff --git a/src/doc/book/listings/ch09-error-handling/listing-09-13/Cargo.toml b/src/doc/book/listings/ch09-error-handling/listing-09-13/Cargo.toml new file mode 100644 index 0000000000..ca796231e8 --- /dev/null +++ b/src/doc/book/listings/ch09-error-handling/listing-09-13/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "guessing_game" +version = "0.1.0" +edition = "2018" + +[dependencies] +rand = "0.8.3" diff --git a/src/doc/book/listings/ch09-error-handling/listing-09-13/src/main.rs b/src/doc/book/listings/ch09-error-handling/listing-09-13/src/main.rs new file mode 100644 index 0000000000..3375279461 --- /dev/null +++ b/src/doc/book/listings/ch09-error-handling/listing-09-13/src/main.rs @@ -0,0 +1,55 @@ +use rand::Rng; +use std::cmp::Ordering; +use std::io; + +// ANCHOR: here +pub struct Guess { + value: i32, +} + +impl Guess { + pub fn new(value: i32) -> Guess { + if value < 1 || value > 100 { + panic!("Guess value must be between 1 and 100, got {}.", value); + } + + Guess { value } + } + + pub fn value(&self) -> i32 { + self.value + } +} +// ANCHOR_END: here + +fn main() { + println!("Guess the number!"); + + let secret_number = rand::thread_rng().gen_range(1..101); + + loop { + println!("Please input your guess."); + + let mut guess = String::new(); + + io::stdin() + .read_line(&mut guess) + .expect("Failed to read line"); + + let guess: i32 = match guess.trim().parse() { + Ok(num) => num, + Err(_) => continue, + }; + + let guess = Guess::new(guess); + + match guess.value().cmp(&secret_number) { + Ordering::Less => println!("Too small!"), + Ordering::Greater => println!("Too big!"), + Ordering::Equal => { + println!("You win!"); + break; + } + } + } +} diff --git a/src/doc/book/listings/ch09-error-handling/no-listing-06-question-mark-in-main/src/main.rs b/src/doc/book/listings/ch09-error-handling/no-listing-06-question-mark-in-main/src/main.rs deleted file mode 100644 index 8608dc13ff..0000000000 --- a/src/doc/book/listings/ch09-error-handling/no-listing-06-question-mark-in-main/src/main.rs +++ /dev/null @@ -1,5 +0,0 @@ -use std::fs::File; - -fn main() { - let f = File::open("hello.txt")?; -} diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-11/src/main.rs b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-11/src/main.rs index 4a08d1a8d6..86b028108f 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-11/src/main.rs +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-11/src/main.rs @@ -1,10 +1,10 @@ -struct Point { - x: T, - y: U, +struct Point { + x: X1, + y: Y1, } -impl Point { - fn mixup(self, other: Point) -> Point { +impl Point { + fn mixup(self, other: Point) -> Point { Point { x: self.x, y: other.y, diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-12/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-12/Cargo.toml index 6681ba2326..a7adc3bc3c 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-12/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-12/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "chapter10" +name = "aggregator" version = "0.1.0" edition = "2018" diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-13/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-13/Cargo.toml index 6681ba2326..a7adc3bc3c 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-13/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-13/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "chapter10" +name = "aggregator" version = "0.1.0" edition = "2018" diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-14/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-14/Cargo.toml index 6681ba2326..a7adc3bc3c 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-14/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-14/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "chapter10" +name = "aggregator" version = "0.1.0" edition = "2018" diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/Cargo.lock b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/Cargo.lock index e8007a19be..2835471f04 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/Cargo.lock +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/Cargo.lock @@ -1,6 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] -name = "chapter10" +name = "aggregator" version = "0.1.0" - diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/Cargo.toml index 6681ba2326..a7adc3bc3c 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "chapter10" +name = "aggregator" version = "0.1.0" edition = "2018" diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/src/main.rs b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/src/main.rs index 466dc4d59a..0b51121d94 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/src/main.rs +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/src/main.rs @@ -1,7 +1,6 @@ -use chapter10::{self, Summary, Tweet}; +use aggregator::{Summary, Tweet}; fn main() { - // ANCHOR: here let tweet = Tweet { username: String::from("horse_ebooks"), content: String::from( @@ -12,5 +11,4 @@ fn main() { }; println!("1 new tweet: {}", tweet.summarize()); - // ANCHOR_END: here } diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-02-calling-default-impl/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-02-calling-default-impl/Cargo.toml index 6681ba2326..a7adc3bc3c 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-02-calling-default-impl/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-02-calling-default-impl/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "chapter10" +name = "aggregator" version = "0.1.0" edition = "2018" diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/Cargo.toml index 6681ba2326..a7adc3bc3c 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "chapter10" +name = "aggregator" version = "0.1.0" edition = "2018" diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-04-traits-as-parameters/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-04-traits-as-parameters/Cargo.toml index 6681ba2326..a7adc3bc3c 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-04-traits-as-parameters/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-04-traits-as-parameters/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "chapter10" +name = "aggregator" version = "0.1.0" edition = "2018" diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-05-returning-impl-trait/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-05-returning-impl-trait/Cargo.toml index 6681ba2326..a7adc3bc3c 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-05-returning-impl-trait/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-05-returning-impl-trait/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "chapter10" +name = "aggregator" version = "0.1.0" edition = "2018" diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-06-impl-trait-returns-one-type/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-06-impl-trait-returns-one-type/Cargo.toml index 6681ba2326..a7adc3bc3c 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-06-impl-trait-returns-one-type/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-06-impl-trait-returns-one-type/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "chapter10" +name = "aggregator" version = "0.1.0" edition = "2018" diff --git a/src/doc/book/nostarch/chapter02.md b/src/doc/book/nostarch/chapter02.md index c3b6584543..6381bbe805 100644 --- a/src/doc/book/nostarch/chapter02.md +++ b/src/doc/book/nostarch/chapter02.md @@ -6,8 +6,9 @@ Let’s jump into Rust by working through a hands-on project together! This chapter introduces you to a few common Rust concepts by showing you how to use them in a real program. You’ll learn about `let`, `match`, methods, associated -functions, using external crates, and more! The following chapters will explore -these ideas in more detail. In this chapter, you’ll practice the fundamentals. +functions, using external crates, and more! In the following chapters, we’ll +explore these ideas in more detail. In this chapter, you’ll practice the +fundamentals. We’ll implement a classic beginner programming problem: a guessing game. Here’s how it works: the program will generate a random integer between 1 and 100. It @@ -102,18 +103,26 @@ Listing 2-1: Code that gets a guess from the user and prints it This code contains a lot of information, so let’s go over it line by line. To obtain user input and then print the result as output, we need to bring the -`io` (input/output) library into scope. The `io` library comes from the -standard library (which is known as `std`): +`io` input/output library into scope. The `io` library comes from the +standard library, known as `std`: ``` use std::io; ``` -By default, Rust brings only a few types into the scope of every program in the -*prelude*. If a type you want to use isn’t in the prelude, you have to bring -that type into scope explicitly with a `use` statement. Using the `std::io` -library provides you with a number of useful features, including the ability to -accept user input. +By default, Rust has a few items defined in the standard library that it brings +into the scope of every program. This set is called the *prelude*, and you can +see everything in it at *https://doc.rust-lang.org/std/prelude/index.html*. + + + + +If a type you want to use isn’t in the prelude, you have to bring that type +into scope explicitly with a `use` statement. Using the `std::io` library +provides you with a number of useful features, including the ability to accept +user input. As you saw in Chapter 1, the `main` function is the entry point into the program: @@ -139,15 +148,14 @@ from the user. ### Storing Values with Variables -Next, we’ll create a place to store the user input, like this: +Next, we’ll create a *variable* to store the user input, like this: ``` let mut guess = String::new(); ``` Now the program is getting interesting! There’s a lot going on in this little -line. Notice that this is a `let` statement, which is used to create a -*variable*. Here’s another example: +line. We use the `let` statement to create the variable. Here’s another example: ``` let apples = 5; @@ -155,9 +163,8 @@ let apples = 5; This line creates a new variable named `apples` and binds it to the value 5. In Rust, variables are immutable by default. We’ll be discussing this concept in -detail in the “Variables and Mutability” section in Chapter 3. The following -example shows how to use `mut` before the variable name to make a variable -mutable: +detail in the “Variables and Mutability” section in Chapter 3. To make a +variable mutable, we add `mut` before the variable name: ``` let apples = 5; // immutable @@ -165,49 +172,57 @@ let mut bananas = 5; // mutable ``` > Note: The `//` syntax starts a comment that continues until the end of the -> line. Rust ignores everything in comments, which are discussed in more detail -> in Chapter 3. - -Let’s return to the guessing game program. You now know that `let mut guess` -will introduce a mutable variable named `guess`. On the other side of the equal -sign (`=`) is the value that `guess` is bound to, which is the result of -calling `String::new`, a function that returns a new instance of a `String`. -`String` is a string type provided by the standard library that is a growable, -UTF-8 encoded bit of text. - -The `::` syntax in the `::new` line indicates that `new` is an *associated -function* of the `String` type. An associated function is implemented on a -type, in this case `String`. - -This `new` function creates a new, empty string. You’ll find a `new` function -on many types, because it’s a common name for a function that makes a new value -of some kind. - -To summarize, the `let mut guess = String::new();` line has created a mutable +> line. Rust ignores everything in comments. We’ll discuss comments in more +> detail in Chapter 3. + +Returning to the guessing game program, you now know that `let mut guess` will +introduce a mutable variable named `guess`. The equal sign (`=`) tells Rust we +want to bind something to the variable now. On the right of the equals sign is +the value that `guess` is bound to, which is the result of calling +`String::new`, a function that returns a new instance of a `String`. `String` +is a string type provided by the standard library that is a growable, UTF-8 +encoded bit of text. + +The `::` syntax in the `::new` line indicates that `new` is an associated +function of the `String` type. An *associated function* is a function that’s +implemented on a type, in this case `String`. This `new` function creates a +new, empty string. You’ll find a `new` function on many types, because it’s a +common name for a function that makes a new value of some kind. + +In full, the `let mut guess = String::new();` line has created a mutable variable that is currently bound to a new, empty instance of a `String`. Whew! +### Receiving User Input + Recall that we included the input/output functionality from the standard library with `use std::io;` on the first line of the program. Now we’ll call -the `stdin` function from the `io` module: +the `stdin` function from the `io` module, which will allow us to handle user +input: ``` io::stdin() .read_line(&mut guess) ``` -If we hadn’t put the `use std::io` line at the beginning of the program, we -could have written this function call as `std::io::stdin`. The `stdin` function -returns an instance of `std::io::Stdin`, which is a type that represents a -handle to the standard input for your terminal. +If we hadn’t imported the `io` library with `use std::io` at the beginning of +the program, we could still use the function by writing this function call as +`std::io::stdin`. The `stdin` function returns an instance of `std::io::Stdin`, +which is a type that represents a handle to the standard input for your +terminal. + +Next, the line `.read_line(&mut guess)` calls the `read_line` method on the +standard input handle to get input from the user. We’re also passing `&mut +guess` as the argument to `read_line` to tell it what string to store the user +input in. The full job of `read_line` is to take whatever the user types into +standard input -The next part of the code, `.read_line(&mut guess)`, calls the `read_line` -method on the standard input handle to get input from the user. We’re also -passing one argument to `read_line`: `&mut guess`. + + -The job of `read_line` is to take whatever the user types into standard input -and append that into a string (without overwriting its contents), so it takes -that string as an argument. The string argument needs to be mutable so the -method can change the string’s content by adding the user input. +and append that into a string (without overwriting its contents), so we +therefore pass that string as an argument. The string argument needs to be +mutable so the method can change the string’s content. The `&` indicates that this argument is a *reference*, which gives you a way to let multiple parts of your code access one piece of data without needing to @@ -222,6 +237,13 @@ thoroughly.) ### Handling Potential Failure with the `Result` Type We’re still working on this line of code. Although we’re now discussing a third + + + line of text, it’s still part of a single logical line of code. The next part is this method: @@ -229,32 +251,38 @@ is this method: .expect("Failed to read line"); ``` -When you call a method with the `.method_name()` syntax, it’s often wise to -introduce a newline and other whitespace to help break up long lines. We could -have written this code as: +We could have written this code as: ``` io::stdin().read_line(&mut guess).expect("Failed to read line"); ``` -However, one long line is difficult to read, so it’s best to divide it. Now -let’s discuss what this line does. +However, one long line is difficult to read, so it’s best to divide it. It’s +often wise to introduce a newline and other whitespace to help break up long +lines when you call a method with the `.method_name()` syntax. Now let’s +discuss what this line does. + +As mentioned earlier, `read_line` puts whatever the user enters into the string +we pass to it, but it also returns a value—in this case, an `io::Result`. Rust +has a number of types named `Result` in its standard library: a generic +`Result` as well as specific versions for submodules, such as `io::Result`. The +`Result` types are *enumerations*, often referred to as *enums*, which can have +a fixed set of possibilites known as *variants*. Enums are often used with +`match`, a conditional that makes it convenient to execute different code based +on which variant an enum value is when the conditional is evaluated. -As mentioned earlier, `read_line` puts what the user types into the string -we’re passing it, but it also returns a value—in this case, an `io::Result`. -Rust has a number of types named `Result` in its standard library: a generic -`Result` as well as specific versions for submodules, such as `io::Result`. + + -The `Result` types are *enumerations*, often referred to as *enums*. An -enumeration is a type that can have a fixed set of values, and those values are -called the enum’s *variants*. Chapter 6 will cover enums in more detail. +Chapter 6 will cover enums in more detail. The purpose of these `Result` types +is to encode error-handling information. -For `Result`, the variants are `Ok` or `Err`. The `Ok` variant indicates the +`Result`’s variants are `Ok` or `Err`. The `Ok` variant indicates the operation was successful, and inside `Ok` is the successfully generated value. The `Err` variant means the operation failed, and `Err` contains information about how or why the operation failed. -The purpose of these `Result` types is to encode error-handling information. Values of the `Result` type, like values of any type, have methods defined on them. An instance of `io::Result` has an `expect` method that you can call. If this instance of `io::Result` is an `Err` value, `expect` will cause the @@ -263,8 +291,7 @@ program to crash and display the message that you passed as an argument to result of an error coming from the underlying operating system. If this instance of `io::Result` is an `Ok` value, `expect` will take the return value that `Ok` is holding and return just that value to you so you can use it. In -this case, that value is the number of bytes in what the user entered into -standard input. +this case, that value is the number of bytes in the user’s input. If you don’t call `expect`, the program will compile, but you’ll get a warning: @@ -280,31 +307,32 @@ warning: unused `Result` that must be used = note: `#[warn(unused_must_use)]` on by default = note: this `Result` may be an `Err` variant, which should be handled -warning: 1 warning emitted - +warning: `guessing_game` (bin "guessing_game") generated 1 warning Finished dev [unoptimized + debuginfo] target(s) in 0.59s ``` + + Rust warns that you haven’t used the `Result` value returned from `read_line`, indicating that the program hasn’t handled a possible error. The right way to suppress the warning is to actually write error handling, but -because you just want to crash this program when a problem occurs, you can use -`expect`. You’ll learn about recovering from errors in Chapter 9. +in our case we just want to crash this program when a problem occurs, so we can +use `expect`. You’ll learn about recovering from errors in Chapter 9. ### Printing Values with `println!` Placeholders Aside from the closing curly bracket, there’s only one more line to discuss in -the code added so far, which is the following: +the code so far: ``` println!("You guessed: {}", guess); ``` -This line prints the string we saved the user’s input in. The set of curly -brackets, `{}`, is a placeholder: think of `{}` as little crab pincers that -hold a value in place. You can print more than one value using curly brackets: -the first set of curly brackets holds the first value listed after the format +This line prints the string that now contains the user’s input. The `{}` set of +curly brackets is a placeholder: think of `{}` as little crab pincers that hold +a value in place. You can print more than one value using curly brackets: the +first set of curly brackets holds the first value listed after the format string, the second set holds the second value, and so on. Printing multiple values in one call to `println!` would look like this: @@ -339,24 +367,24 @@ keyboard and then printing it. Next, we need to generate a secret number that the user will try to guess. The secret number should be different every time so the game is fun to play more -than once. Let’s use a random number between 1 and 100 so the game isn’t too +than once. We’ll use a random number between 1 and 100 so the game isn’t too difficult. Rust doesn’t yet include random number functionality in its standard library. However, the Rust team does provide a `rand` crate at -*https://crates.io/crates/rand*. +*https://crates.io/crates/rand* with said functionality. ### Using a Crate to Get More Functionality Remember that a crate is a collection of Rust source code files. The project we’ve been building is a *binary crate*, which is an executable. The `rand` crate is a *library crate*, which contains code intended to be used in other -programs. +programs, and can’t be executed on its own. Cargo’s coordination of external crates is where Cargo really shines. Before we can write code that uses `rand`, we need to modify the *Cargo.toml* file to include the `rand` crate as a dependency. Open that file now and add the following line to the bottom beneath the `[dependencies]` section header that -Cargo created for you. Be sure to specify `rand` exactly as we have here, or -the code examples in this tutorial may not work. +Cargo created for you. Be sure to specify `rand` exactly as we have here, with +this version number, or the code examples in this tutorial may not work. Filename: Cargo.toml @@ -364,18 +392,25 @@ Filename: Cargo.toml rand = "0.8.3" ``` -In the *Cargo.toml* file, everything that follows a header is part of a section -that continues until another section starts. The `[dependencies]` section is -where you tell Cargo which external crates your project depends on and which -versions of those crates you require. In this case, we’ll specify the `rand` -crate with the semantic version specifier `0.8.3`. Cargo understands Semantic -Versioning (sometimes called *SemVer*), which is a standard for writing version -numbers. The number `0.8.3` is actually shorthand for `^0.8.3`, which means any -version that is at least `0.8.3` but below `0.9.0`. Cargo considers these -versions to have public APIs compatible with version `0.8.3`, and this -specification ensures you'll get the latest patch release that will still -compile with the code in this chapter. Any version `0.9.0` or greater is not -guaranteed to have the same API as what the following examples use. +In the *Cargo.toml* file, everything that follows a header is part of that +section that continues until another section starts. In `[dependencies]` you +tell Cargo which external crates your project depends on and which versions of +those crates you require. In this case, we specify the `rand` crate with the +semantic version specifier `0.8.3`. Cargo understands Semantic Versioning +(sometimes called *SemVer*), which is a standard for writing version numbers. +The number `0.8.3` is actually shorthand for `^0.8.3`, which means any version +that is at least `0.8.3` but below `0.9.0`. + + + + +Cargo considers these versions to have public APIs compatible with version +`0.8.3`, and this specification ensures you’ll get the latest patch release +that will still compile with the code in this chapter. Any version `0.9.0` or +greater is not guaranteed to have the same API as what the following examples +use. Now, without changing any of the code, let’s build the project, as shown in Listing 2-2. @@ -408,16 +443,16 @@ You may see different version numbers (but they will all be compatible with the code, thanks to SemVer!), different lines (depending on the operating system), and the lines may be in a different order. -Now that we have an external dependency, Cargo fetches the latest versions of -everything from the *registry*, which is a copy of data from Crates.io at -*https://crates.io/*. Crates.io is where people in the Rust ecosystem post -their open source Rust projects for others to use. +When we include an external dependency, Cargo fetches the latest versions of +everything that dependency needs from the *registry*, which is a copy of data +from Crates.io at *https://crates.io/*. Crates.io is where people in the Rust +ecosystem post their open source Rust projects for others to use. After updating the registry, Cargo checks the `[dependencies]` section and -downloads any crates you don’t have yet. In this case, although we only listed -`rand` as a dependency, Cargo also grabbed other crates that `rand` depends on -to work. After downloading the crates, Rust compiles them and then compiles the -project with the dependencies available. +downloads any crates listed that aren’t already downloaded. In this case, +although we only listed `rand` as a dependency, Cargo also grabbed other crates +that `rand` depends on to work. After downloading the crates, Rust compiles +them and then compiles the project with the dependencies available. If you immediately run `cargo build` again without making any changes, you won’t get any output aside from the `Finished` line. Cargo knows it has already @@ -437,20 +472,19 @@ $ cargo build These lines show Cargo only updates the build with your tiny change to the *src/main.rs* file. Your dependencies haven’t changed, so Cargo knows it can -reuse what it has already downloaded and compiled for those. It just rebuilds -your part of the code. +reuse what it has already downloaded and compiled for those. #### Ensuring Reproducible Builds with the *Cargo.lock* File Cargo has a mechanism that ensures you can rebuild the same artifact every time you or anyone else builds your code: Cargo will use only the versions of the -dependencies you specified until you indicate otherwise. For example, what -happens if next week version 0.8.4 of the `rand` crate comes out, and that -version contains an important bug fix, but it also contains a regression that -will break your code? +dependencies you specified until you indicate otherwise. For example, say that +next week version 0.8.4 of the `rand` crate comes out, and that version +contains an important bug fix, but it also contains a regression that will +break your code. To handle this, Rust creates the *Cargo.lock* file the first +time you run `cargo build`, so we now have this in the *guessing_game* +directory. -The answer to this problem is the *Cargo.lock* file, which was created the -first time you ran `cargo build` and is now in your *guessing_game* directory. When you build a project for the first time, Cargo figures out all the versions of the dependencies that fit the criteria and then writes them to the *Cargo.lock* file. When you build your project in the future, Cargo will @@ -462,14 +496,13 @@ file. #### Updating a Crate to Get a New Version -When you *do* want to update a crate, Cargo provides another command, `update`, +When you *do* want to update a crate, Cargo provides the command `update`, which will ignore the *Cargo.lock* file and figure out all the latest versions -that fit your specifications in *Cargo.toml*. If that works, Cargo will write -those versions to the *Cargo.lock* file. - -But by default, Cargo will only look for versions greater than `0.8.3` and less -than `0.9.0`. If the `rand` crate has released two new versions, `0.8.4` and -`0.9.0`, you would see the following if you ran `cargo update`: +that fit your specifications in *Cargo.toml*. Cargo will then write those +versions to the *Cargo.lock* file. Otherwise, by default, Cargo will only look +for versions greater than `0.8.3` and less than `0.9.0`. If the `rand` crate +has released the two new versions `0.8.4` and `0.9.0` you would see the +following if you ran `cargo update`: ``` $ cargo update @@ -477,11 +510,11 @@ $ cargo update Updating rand v0.8.3 -> v0.8.4 ``` -At this point, you would also notice a change in your *Cargo.lock* file noting -that the version of the `rand` crate you are now using is `0.8.4`. - -If you wanted to use `rand` version `0.9.0` or any version in the `0.9.x` -series, you’d have to update the *Cargo.toml* file to look like this instead: +Cargo ignores the `0.9.0` releaese. At this point, you would also notice a +change in your *Cargo.lock* file noting that the version of the `rand` crate +you are now using is `0.8.4`. To use `rand` version `0.9.0` or any version in +the `0.9.x` series, you’d have to update the *Cargo.toml* file to look like +this instead: ``` [dependencies] @@ -499,21 +532,27 @@ assembled from a number of packages. ### Generating a Random Number -Now that you’ve added the `rand` crate to *Cargo.toml*, let’s start using -`rand`. The next step is to update *src/main.rs*, as shown in Listing 2-3. +Let’s start using `rand` to generate a number to guess. The next step is to +update *src/main.rs*, as shown in Listing 2-3. + + + Filename: src/main.rs ``` use std::io; -use rand::Rng; +[1]use rand::Rng; fn main() { println!("Guess the number!"); - let secret_number = rand::thread_rng().gen_range(1..101); + [2] let secret_number = rand::thread_rng().gen_range(1..101); - println!("The secret number is: {}", secret_number); + [3] println!("The secret number is: {}", secret_number); println!("Please input your guess."); @@ -529,34 +568,43 @@ fn main() { Listing 2-3: Adding code to generate a random number -First, we add a `use` line: `use rand::Rng`. The `Rng` trait defines -methods that random number generators implement, and this trait must be in -scope for us to use those methods. Chapter 10 will cover traits in detail. - -Next, we’re adding two lines in the middle. The `rand::thread_rng` function -will give us the particular random number generator that we’re going to use: -one that is local to the current thread of execution and seeded by the -operating system. Then we call the `gen_range` method on the random number -generator. This method is defined by the `Rng` trait that we brought into scope -with the `use rand::Rng` statement. The `gen_range` method takes a range -expression as an argument and generates a random number in the range. The kind -of range expression we’re using here takes the form `start..end`. It’s -inclusive on the lower bound but exclusive on the upper bound, so we need to -specify `1..101` to request a number between 1 and 100. Alternatively, we could -pass the range `1..=100`, which is equivalent. + + + +First, we add the line `use rand::Rng` [1]. The `Rng` trait defines methods that random number generators implement, and this +trait must be in scope for us to use those methods. Chapter 10 will cover +traits in detail. + +Next, we’re adding two lines in the middle. In the first line [2], we call the +`rand::thread_rng` function that gives us the particular random number +generator that we’re going to use: one that is local to the current thread of +execution and seeded by the operating system. Then we call the `gen_range` +method on the random number generator. This method is defined by the `Rng` +trait that we brought into scope with the `use rand::Rng` statement. The +`gen_range` method takes a range expression as an argument and generates a +random number in the range. The kind of range expression we’re using here takes +the form `start..end` and is inclusive on the lower bound but exclusive on the +upper bound, so we need to specify `1..101` to request a number between 1 and +100. Alternatively, we could pass the range `1..=100`, which is equivalent. > Note: You won’t just know which traits to use and which methods and functions -> to call from a crate. Instructions for using a crate are in each crate’s -> documentation. Another neat feature of Cargo is that you can run the `cargo -> doc --open` command, which will build documentation provided by all of your +> to call from a crate, so each crate has documentation with instructions for +> using it. Another neat feature of Cargo is that running the `cargo +> doc --open` command will build documentation provided by all of your > dependencies locally and open it in your browser. If you’re interested in > other functionality in the `rand` crate, for example, run `cargo doc --open` > and click `rand` in the sidebar on the left. -The second line that we added to the middle of the code prints the secret -number. This is useful while we’re developing the program to be able to test -it, but we’ll delete it from the final version. It’s not much of a game if the -program prints the answer as soon as it starts! +The second new line [3] prints the secret number. This is useful while +we’re developing the program to be able to test it, but we’ll delete it from +the final version. It’s not much of a game if the program prints the answer as +soon as it starts! Try running the program a few times: @@ -594,7 +642,7 @@ Filename: src/main.rs ``` use rand::Rng; -use std::cmp::Ordering; +[1]use std::cmp::Ordering; use std::io; fn main() { @@ -602,7 +650,7 @@ fn main() { println!("You guessed: {}", guess); - match guess.cmp(&secret_number) { + match[2] guess.cmp(&secret_number)[3] { Ordering::Less => println!("Too small!"), Ordering::Greater => println!("Too big!"), Ordering::Equal => println!("You win!"), @@ -610,42 +658,40 @@ fn main() { } ``` -Listing 2-4: Handling the possible return values of -comparing two numbers +Listing 2-4: Handling the possible return values of comparing two numbers -The first new bit here is another `use` statement, bringing a type called -`std::cmp::Ordering` into scope from the standard library. Like `Result`, -`Ordering` is another enum, but the variants for `Ordering` are `Less`, -`Greater`, and `Equal`. These are the three outcomes that are possible when you -compare two values. +First we add another `use` statement [1], bringing a type called +`std::cmp::Ordering` into scope from the standard library. The `Ordering` type +is another enum and has the variants `Less`, `Greater`, and `Equal`. These are +the three outcomes that are possible when you compare two values. Then we add five new lines at the bottom that use the `Ordering` type. The -`cmp` method compares two values and can be called on anything that can be +`cmp` method [3] compares two values and can be called on anything that can be compared. It takes a reference to whatever you want to compare with: here it’s comparing the `guess` to the `secret_number`. Then it returns a variant of the `Ordering` enum we brought into scope with the `use` statement. We use a -`match` expression to decide what to do next based on which variant of +`match` expression [2] to decide what to do next based on which variant of `Ordering` was returned from the call to `cmp` with the values in `guess` and `secret_number`. -A `match` expression is made up of *arms*. An arm consists of a *pattern* and -the code that should be run if the value given to the beginning of the `match` -expression fits that arm’s pattern. Rust takes the value given to `match` and -looks through each arm’s pattern in turn. The `match` construct and patterns -are powerful features in Rust that let you express a variety of situations your -code might encounter and make sure that you handle them all. These features -will be covered in detail in Chapter 6 and Chapter 18, respectively. - -Let’s walk through an example of what would happen with the `match` expression -used here. Say that the user has guessed 50 and the randomly generated secret -number this time is 38. When the code compares 50 to 38, the `cmp` method will -return `Ordering::Greater`, because 50 is greater than 38. The `match` -expression gets the `Ordering::Greater` value and starts checking each arm’s -pattern. It looks at the first arm’s pattern, `Ordering::Less`, and sees that -the value `Ordering::Greater` does not match `Ordering::Less`, so it ignores -the code in that arm and moves to the next arm. The next arm’s pattern, -`Ordering::Greater`, *does* match `Ordering::Greater`! The associated code in -that arm will execute and print `Too big!` to the screen. The `match` +A `match` expression is made up of *arms*. An arm consists of a *pattern* to +match against, and the code that should be run if the value given to `match` +fits that arm’s pattern. Rust takes the value given to `match` and looks +through each arm’s pattern in turn. Patterns and the `match` construct are +powerful Rust features that let you express a variety of situations your code +might encounter and make sure that you handle them all. These features will be +covered in detail in Chapter 6 and Chapter 18, respectively. + +Let’s walk through an example with the `match` expression we use here. Say that +the user has guessed 50 and the randomly generated secret number this time is +38. When the code compares 50 to 38, the `cmp` method will return +`Ordering::Greater`, because 50 is greater than 38. The `match` expression gets +the `Ordering::Greater` value and starts checking each arm’s pattern. It looks +at the first arm’s pattern, `Ordering::Less`, and sees that the value +`Ordering::Greater` does not match `Ordering::Less`, so it ignores the code in +that arm and moves to the next arm. The next arm’s pattern is +`Ordering::Greater`, which *does* match `Ordering::Greater`! The associated +code in that arm will execute and print `Too big!` to the screen. The `match` expression ends because it has no need to look at the last arm in this scenario. However, the code in Listing 2-4 won’t compile yet. Let’s try it: @@ -661,29 +707,22 @@ error[E0308]: mismatched types | = note: expected reference `&String` found reference `&{integer}` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0308`. -error: could not compile `guessing_game` - -To learn more, run the command again with --verbose. ``` The core of the error states that there are *mismatched types*. Rust has a strong, static type system. However, it also has type inference. When we wrote `let mut guess = String::new()`, Rust was able to infer that `guess` should be a `String` and didn’t make us write the type. The `secret_number`, on the other -hand, is a number type. A few number types can have a value between 1 and 100: -`i32`, a 32-bit number; `u32`, an unsigned 32-bit number; `i64`, a 64-bit -number; as well as others. Rust defaults to an `i32`, which is the type of -`secret_number` unless you add type information elsewhere that would cause Rust -to infer a different numerical type. The reason for the error is that Rust -cannot compare a string and a number type. +hand, is a number type. A few of Rust’s number types can have a value between 1 +and 100: `i32`, a 32-bit number; `u32`, an unsigned 32-bit number; `i64`, a +64-bit number; as well as others. Unless otherwise speceified, Rust defaults to +an `i32`, which is the type of `secret_number` unless you add type information +elsewhere that would cause Rust to infer a different numerical type. The reason +for the error is that Rust cannot compare a string and a number type. Ultimately, we want to convert the `String` the program reads as input into a -real number type so we can compare it numerically to the secret number. We can -do that by adding another line to the `main` function body: +real number type so we can compare it numerically to the secret number. We do so +by adding this line to the `main` function body: Filename: src/main.rs @@ -707,30 +746,27 @@ Filename: src/main.rs } ``` -The line is: - -``` -let guess: u32 = guess.trim().parse().expect("Please type a number!"); -``` - We create a variable named `guess`. But wait, doesn’t the program already have -a variable named `guess`? It does, but Rust allows us to *shadow* the previous -value of `guess` with a new one. This feature is often used in situations in -which you want to convert a value from one type to another type. Shadowing lets -us reuse the `guess` variable name rather than forcing us to create two unique -variables, such as `guess_str` and `guess` for example. (Chapter 3 covers -shadowing in more detail.) - -We bind `guess` to the expression `guess.trim().parse()`. The `guess` in the -expression refers to the original `guess` that was a `String` with the input in -it. The `trim` method on a `String` instance will eliminate any whitespace at -the beginning and end. Although `u32` can contain only numerical characters, -the user must press enter to satisfy -`read_line`. When the user presses enter, a -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 (On Windows, pressing + +The user must press enter to satisfy `read_line` +and input their guess, which adds a newline character to the string. For +example, if the user types 5 and presses enter, `guess` looks like this: `5\n`. The `\n` +represents “newline”. (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`. @@ -745,7 +781,8 @@ comparison with `secret_number` means that Rust will infer that `secret_number` should be a `u32` as well. So now the comparison will be between two values of the same type! -The call to `parse` could easily cause an error. If, for example, the string +The `parse` method will only work on characters that can logically be converted +into numbers and so can easily cause errors. If, for example, the string contained `A👍%`, there would be no way to convert that to a number. Because it might fail, the `parse` method returns a `Result` type, much as the `read_line` method does (discussed earlier in “Handling Potential Failure with the `Result` @@ -781,7 +818,7 @@ Let’s change that by adding a loop! ## Allowing Multiple Guesses with Looping -The `loop` keyword creates an infinite loop. We’ll add that now to give users +The `loop` keyword creates an infinite loop. We’ll add a loop to give users more chances at guessing the number: Filename: src/main.rs @@ -805,17 +842,16 @@ Filename: src/main.rs } ``` -As you can see, we’ve moved everything into a loop from the guess input prompt -onward. Be sure to indent the lines inside the loop another four spaces each -and run the program again. Notice that there is a new problem because the -program is doing exactly what we told it to do: ask for another guess forever! -It doesn’t seem like the user can quit! +As you can see, we’ve moved everything from the guess input prompt onward into +a loop. Be sure to indent the lines inside the loop another four spaces each +and run the program again. The program will now ask for another guess forever, +which actually introduces a new problem. It doesn’t seem like the user can quit! The user could always interrupt the program by using the keyboard shortcut ctrl-c. But there’s another way to escape this insatiable monster, as mentioned in the `parse` discussion in “Comparing the Guess to the Secret Number”: if the user enters a non-number answer, the -program will crash. The user can take advantage of that in order to quit, as +program will crash. We can take advantage of that to allow the user to quit, as shown here: ``` @@ -843,9 +879,9 @@ thread 'main' panicked at 'Please type a number!: ParseIntError { kind: InvalidD note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace ``` -Typing `quit` actually quits the game, but so will any other non-number input. -However, this is suboptimal to say the least. We want the game to automatically -stop when the correct number is guessed. +Typing `quit` will quit the game, but as you’ll notice so will entering any +other non-number input. This is suboptimal to say the least; we want the game +to also stop when the correct number is guessed. ### Quitting After a Correct Guess @@ -901,11 +937,11 @@ Filename: src/main.rs Listing 2-5: Ignoring a non-number guess and asking for another guess instead of crashing the program -Switching from an `expect` call to a `match` expression is one way of moving -from crashing on an error to handling the error. Remember that `parse` returns -a `Result` type and `Result` is an enum that has the variants `Ok` or `Err`. -We’re using a `match` expression here, as we did with the `Ordering` result of -the `cmp` method. +We switch from an `expect` call to a `match` expression to move from crashing +on an error to handling the error. Remember that `parse` returns a `Result` +type and `Result` is an enum that has the variants `Ok` or `Err`. We’re using a +`match` expression here, as we did with the `Ordering` result of the `cmp` +method. If `parse` is able to successfully turn the string into a number, it will return an `Ok` value that contains the resulting number. That `Ok` value will diff --git a/src/doc/book/nostarch/chapter03.md b/src/doc/book/nostarch/chapter03.md index ba72a62466..2a00baffe4 100644 --- a/src/doc/book/nostarch/chapter03.md +++ b/src/doc/book/nostarch/chapter03.md @@ -37,7 +37,8 @@ that value. To illustrate this, let’s generate a new project called *variables in your *projects* directory by using `cargo new variables`. Then, in your new *variables* directory, open *src/main.rs* and replace its -code with the following code that won’t compile just yet: +code with the following code. This code won’t compile just yet, we'll first +examine the immutability error. Filename: src/main.rs @@ -70,7 +71,7 @@ error[E0384]: cannot assign twice to immutable variable `x` ``` This example shows how the compiler helps you find errors in your programs. -Even though compiler errors can be frustrating, they only mean your program +Compiler errors can be frustrating, but really they only mean your program isn’t safely doing what you want it to do yet; they do *not* mean that you’re not a good programmer! Experienced Rustaceans still get compiler errors. @@ -79,23 +80,21 @@ assign twice to immutable variable `x` ``, because you tried to assign a second value to the immutable `x` variable. It’s important that we get compile-time errors when we attempt to change a -value that we previously designated as immutable because this very situation -can lead to bugs. If one part of our code operates on the assumption that a -value will never change and another part of our code changes that value, it’s -possible that the first part of the code won’t do what it was designed to do. -The cause of this kind of bug can be difficult to track down after the fact, -especially when the second piece of code changes the value only *sometimes*. - -In Rust, the compiler guarantees that when you state that a value won’t change, -it really won’t change. That means that when you’re reading and writing code, -you don’t have to keep track of how and where a value might change. Your code -is thus easier to reason through. - -But mutability can be very useful. Variables are immutable only by default; as -you did in Chapter 2, you can make them mutable by adding `mut` in front of the -variable name. In addition to allowing this value to change, `mut` conveys -intent to future readers of the code by indicating that other parts of the code -will be changing this variable’s value. +value that’s designated as immutable because this very situation can lead to +bugs. If one part of our code operates on the assumption that a value will +never change and another part of our code changes that value, it’s possible +that the first part of the code won’t do what it was designed to do. The cause +of this kind of bug can be difficult to track down after the fact, especially +when the second piece of code changes the value only *sometimes*. The Rust +compiler guarantees that when you state a value won’t change, it really won’t +change, so you don’t have to keep track of it yourself. Your code is thus +easier to reason through. + +But mutability can be very useful, and can make code more convenient to write. +Variables are immutable only by default; as you did in Chapter 2, you can make +them mutable by adding `mut` in front of the variable name. Adding `mut` also +conveys intent to future readers of the code by indicating that other parts of +the code will be changing this variable’s value. For example, let’s change *src/main.rs* to the following: @@ -122,31 +121,26 @@ The value of x is: 6 ``` We’re allowed to change the value that `x` binds to from `5` to `6` when `mut` -is used. In some cases, you’ll want to make a variable mutable because it makes -the code more convenient to write than if it had only immutable variables. +is used. There are multiple trade-offs to consider in addition to the +prevention of bugs. For example, in cases where you’re using large data +structures, mutating an instance in place may be faster than copying and +returning newly allocated instances. With smaller data structures, creating new +instances and writing in a more functional programming style may be easier to +think through, so lower performance might be a worthwhile penalty for gaining +that clarity. -There are multiple trade-offs to consider in addition to the prevention of -bugs. For example, in cases where you’re using large data structures, mutating -an instance in place may be faster than copying and returning newly allocated -instances. With smaller data structures, creating new instances and writing in -a more functional programming style may be easier to think through, so lower -performance might be a worthwhile penalty for gaining that clarity. +### Constants -### Differences Between Variables and Constants - -Being unable to change the value of a variable might have reminded you of -another programming concept that most other languages have: *constants*. Like -immutable variables, constants are values that are bound to a name and are not -allowed to change, but there are a few differences between constants and -variables. +Like immutable variables, *constants* are values that are bound to a name and +are not allowed to change, but there are a few differences between constants +and variables. First, you aren’t allowed to use `mut` with constants. Constants aren’t just -immutable by default—they’re always immutable. - -You declare constants using the `const` keyword instead of the `let` keyword, -and the type of the value *must* be annotated. We’re about to cover types and -type annotations in the next section, “Data Types,” so don’t worry about the -details right now. Just know that you must always annotate the type. +immutable by default—they’re always immutable. You declare constants using the +`const` keyword instead of the `let` keyword, and the type of the value *must* +be annotated. We’re about to cover types and type annotations in the next +section, “Data Types,” so don’t worry about the details right now. Just know +that you must always annotate the type. Constants can be declared in any scope, including the global scope, which makes them useful for values that many parts of code need to know about. @@ -154,20 +148,20 @@ them useful for values that many parts of code need to know about. The last difference is that constants may be set only to a constant expression, not the result of a value that could only be computed at runtime. -Here’s an example of a constant declaration where the constant’s name is -`THREE_HOURS_IN_SECONDS` and its value is set to the result of multiplying 60 -(the number of seconds in a minute) by 60 (the number of minutes in an hour) by -3 (the number of hours we want to count in this program): +Here’s an example of a constant declaration: ``` const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 * 3; ``` -Rust’s naming convention for constants is to use all uppercase with underscores -between words. The compiler is able to evaluate a limited set of operations at -compile time, which lets us choose to write out this value in a way that’s -easier to understand and verify, rather than setting this constant to the value -10,800. See the Rust Reference’s section on constant evaluation at +The constant’s name is `THREE_HOURS_IN_SECONDS` and its value is set to the +result of multiplying 60 (the number of seconds in a minute) by 60 (the number +of minutes in an hour) by 3 (the number of hours we want to count in this +program). Rust’s naming convention for constants is to use all uppercase with +underscores between words. The compiler is able to evaluate a limited set of +operations at compile time, which lets us choose to write out this value in a +way that’s easier to understand and verify, rather than setting this constant +to the value 10,800. See the Rust Reference’s section on constant evaluation at *https://doc.rust-lang.org/reference/const_eval.html* for more information on what operations can be used when declaring constants. @@ -184,12 +178,12 @@ hardcoded value needed to be updated in the future. ### Shadowing -As you saw in the guessing game tutorial in the “Comparing the Guess to the -Secret Number” section in Chapter 2, you can declare a new variable with the -same name as a previous variable. Rustaceans say that the first variable is -*shadowed* by the second, which means that the second variable’s value is what -the program sees when the variable is used. We can shadow a variable by using -the same variable’s name and repeating the use of the `let` keyword as follows: +As you saw in the guessing game tutorial in Chapter 2, you can declare a new +variable with the same name as a previous variable. Rustaceans say that the +first variable is *shadowed* by the second, which means that the second +variable’s value is what the program sees when the variable is used. We can +shadow a variable by using the same variable’s name and repeating the use of +the `let` keyword as follows: Filename: src/main.rs @@ -230,23 +224,31 @@ using the `let` keyword. By using `let`, we can perform a few transformations on a value but have the variable be immutable after those transformations have been completed. + + + The other difference between `mut` and shadowing is that because we’re effectively creating a new variable when we use the `let` keyword again, we can change the type of the value but reuse the same name. For example, say our program asks a user to show how many spaces they want between some text by -inputting space characters, but we really want to store that input as a number: +inputting space characters, and then we want to store that input as a number: ``` let spaces = " "; let spaces = spaces.len(); ``` -This construct is allowed because the first `spaces` variable is a string type -and the second `spaces` variable, which is a brand-new variable that happens to -have the same name as the first one, is a number type. Shadowing thus spares us -from having to come up with different names, such as `spaces_str` and -`spaces_num`; instead, we can reuse the simpler `spaces` name. However, if we -try to use `mut` for this, as shown here, we’ll get a compile-time error: +The first `spaces` variable is a string type and the second `spaces` variable +is a number type. Shadowing thus spares us from having to come up with +different names, such as `spaces_str` and `spaces_num`; instead, we can reuse +the simpler `spaces` name. However, if we try to use `mut` for this, as shown +here, we’ll get a compile-time error: ``` let mut spaces = " "; @@ -313,9 +315,8 @@ An *integer* is a number without a fractional component. We used one integer type in Chapter 2, the `u32` type. This type declaration indicates that the value it’s associated with should be an unsigned integer (signed integer types start with `i`, instead of `u`) that takes up 32 bits of space. Table 3-1 shows -the built-in integer types in Rust. Each variant in the Signed and Unsigned -columns (for example, `i16`) can be used to declare the type of an integer -value. +the built-in integer types in Rust. We can use any of these variants to declare +the type of an integer value. Table 3-1: Integer Types in Rust @@ -343,9 +344,14 @@ Each signed variant can store numbers from -(2n - 1) to 2n - -128 to 127. Unsigned variants can store numbers from 0 to 2n - 1, so a `u8` can store numbers from 0 to 28 - 1, which equals 0 to 255. -Additionally, the `isize` and `usize` types depend on the kind of computer your -program is running on: 64 bits if you’re on a 64-bit architecture and 32 bits -if you’re on a 32-bit architecture. +Additionally, the `isize` and `usize` types depend on the architecture of the +computer your program is running on, which is denoted in the table as "arch": +64 bits if you’re on a 64-bit architecture and 32 bits if you’re on a 32-bit +architecture. + + + You can write integer literals in any of the forms shown in Table 3-2. Note that number literals that can be multiple numeric types allow a type suffix, @@ -370,15 +376,14 @@ some sort of collection. > ##### Integer Overflow > -> Let’s say you have a variable of type `u8` that can hold values between 0 and 255. -> If you try to change the variable to a value outside of that range, such -> as 256, *integer overflow* will occur. Rust has some interesting rules -> involving this behavior. When you’re compiling in debug mode, Rust includes -> checks for integer overflow that cause your program to *panic* at runtime if -> this behavior occurs. Rust uses the term panicking when a program exits with -> an error; we’ll discuss panics in more depth in the “Unrecoverable Errors -> with `panic!`” section in -> Chapter 9. +> Let’s say you have a variable of type `u8` that can hold values between 0 and +> 255. If you try to change the variable to a value outside of that range, such +> as 256, *integer overflow* will occur, which can result in one of two +> behaviors. When you’re compiling in debug mode, Rust includes checks for +> integer overflow that cause your program to *panic* at runtime if this +> behavior occurs. Rust uses the term panicking when a program exits with an +> error; we’ll discuss panics in more depth in the “Unrecoverable Errors with +> `panic!`” section in Chapter 9. > > When you’re compiling in release mode with the `--release` flag, Rust does > *not* include checks for integer overflow that cause panics. Instead, if @@ -390,7 +395,7 @@ some sort of collection. > have. Relying on integer overflow’s wrapping behavior is considered an error. > > To explicitly handle the possibility of overflow, you can use these families -> of methods that the standard library provides on primitive numeric types: +> of methods provided by the standard library for primitive numeric types: > > - Wrap in all modes with the `wrapping_*` methods, such as `wrapping_add` > - Return the `None` value if there is overflow with the `checked_*` methods @@ -405,7 +410,11 @@ Rust also has two primitive types for *floating-point numbers*, which are numbers with decimal points. Rust’s floating-point types are `f32` and `f64`, which are 32 bits and 64 bits in size, respectively. The default type is `f64` because on modern CPUs it’s roughly the same speed as `f32` but is capable of -more precision. +more precision. All floating-point types are signed. + + + Here’s an example that shows floating-point numbers in action: @@ -477,10 +486,8 @@ Flow” section. #### The Character Type -So far we’ve worked only with numbers, but Rust supports letters too. Rust’s -`char` type is the language’s most primitive alphabetic type, and the following -code shows one way to use it. (Note that `char` literals are specified with -single quotes, as opposed to string literals, which use double quotes.) +Rust’s `char` type is the language’s most primitive alphabetic type. Here's +some examples of declaring `char` values: Filename: src/main.rs @@ -492,14 +499,16 @@ fn main() { } ``` -Rust’s `char` type is four bytes in size and represents a Unicode Scalar Value, -which means it can represent a lot more than just ASCII. Accented letters; -Chinese, Japanese, and Korean characters; emoji; and zero-width spaces are all -valid `char` values in Rust. Unicode Scalar Values range from `U+0000` to -`U+D7FF` and `U+E000` to `U+10FFFF` inclusive. However, a “character” isn’t -really a concept in Unicode, so your human intuition for what a “character” is -may not match up with what a `char` is in Rust. We’ll discuss this topic in -detail in “Storing UTF-8 Encoded Text with Strings” in Chapter 8. +Note that we specify `char` literals with single quotes, as opposed to string +literals, which use double quotes. Rust’s `char` type is four bytes in size and +represents a Unicode Scalar Value, which means it can represent a lot more than +just ASCII. Accented letters; Chinese, Japanese, and Korean characters; emoji; +and zero-width spaces are all valid `char` values in Rust. Unicode Scalar +Values range from `U+0000` to `U+D7FF` and `U+E000` to `U+10FFFF` inclusive. +However, a “character” isn’t really a concept in Unicode, so your human +intuition for what a “character” is may not match up with what a `char` is in +Rust. We’ll discuss this topic in detail in “Storing UTF-8 Encoded Text with +Strings” in Chapter 8. ### Compound Types @@ -547,9 +556,8 @@ variables, `x`, `y`, and `z`. This is called *destructuring*, because it breaks the single tuple into three parts. Finally, the program prints the value of `y`, which is `6.4`. -In addition to destructuring through pattern matching, we can access a tuple -element directly by using a period (`.`) followed by the index of the value we -want to access. For example: +We can also access a tuple element directly by using a period (`.`) followed by +the index of the value we want to access. For example: Filename: src/main.rs @@ -565,7 +573,7 @@ fn main() { } ``` -This program creates a tuple, `x`, and then makes new variables for each +This program creates the tuple `x` and then makes new variables for each element by using their respective indices. As with most programming languages, the first index in a tuple is 0. @@ -577,12 +585,11 @@ return any other value. #### The Array Type Another way to have a collection of multiple values is with an *array*. Unlike -a tuple, every element of an array must have the same type. Arrays in Rust are -different from arrays in some other languages because arrays in Rust have a -fixed length, like tuples. +a tuple, every element of an array must have the same type. Unlike arrays in +some other languages, arrays in Rust have a fixed length. -In Rust, the values going into an array are written as a comma-separated list -inside square brackets: +We write the values in an array as a comma-separated list inside square +brackets: Filename: src/main.rs @@ -593,26 +600,34 @@ fn main() { ``` Arrays are useful when you want your data allocated on the stack rather than -the heap (we will discuss the stack and the heap more in Chapter 4) or when -you want to ensure you always have a fixed number of elements. An array isn’t -as flexible as the vector type, though. A vector is a similar collection type +the heap (we will discuss the stack and the heap more in Chapter 4) or when you +want to ensure you always have a fixed number of elements. An array isn’t as +flexible as the vector type, though. A vector is a similar collection type provided by the standard library that *is* allowed to grow or shrink in size. -If you’re unsure whether to use an array or a vector, you should probably use a -vector. Chapter 8 discusses vectors in more detail. +If you’re unsure whether to use an array or a vector, chances are you should +use a vector. Chapter 8 discusses vectors in more detail. -An example of when you might want to use an array rather than a vector is in a -program that needs to know the names of the months of the year. It’s very -unlikely that such a program will need to add or remove months, so you can use -an array because you know it will always contain 12 elements: +However, arrays are more useful when you know the number of elements will not +need to change. For example, if you were using the names of the month in a +program, you would probably use an array rather than a vector because you know +it will always contain 12 elements: ``` let months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; ``` -You would write an array’s type by using square brackets, and within the -brackets include the type of each element, a semicolon, and then the number of -elements in the array, like so: + + + +You write an array’s type using square brackets with the type of each element, +a semicolon, and then the number of elements in the array, like so: ``` let a: [i32; 5] = [1, 2, 3, 4, 5]; @@ -621,10 +636,9 @@ let a: [i32; 5] = [1, 2, 3, 4, 5]; Here, `i32` is the type of each element. After the semicolon, the number `5` indicates the array contains five elements. -Writing an array’s type this way looks similar to an alternative syntax for -initializing an array: if you want to create an array that contains the same -value for each element, you can specify the initial value, followed by a -semicolon, and then the length of the array in square brackets, as shown here: +You can also initialize an array to contain the same value for each element by +specifying the initial value, followed by a semicolon, and then the length of +the array in square brackets, as shown here: ``` let a = [3; 5]; @@ -657,9 +671,9 @@ get the value `2` from index `[1]` in the array. ##### Invalid Array Element Access -What happens if you try to access an element of an array that is past the end -of the array? Say you change the example to the following, which uses code -similar to the guessing game in Chapter 2 to get an array index from the user: +Let's see what happens if you try to access an element of an array that is past +the end of the array. Say you run this code, similar to the guessing game in +Chapter 2, to get an array index from the user: Filename: src/main.rs @@ -724,7 +738,7 @@ point of many programs. You’ve also seen the `fn` keyword, which allows you to declare new functions. Rust code uses *snake case* as the conventional style for function and variable -names. In snake case, all letters are lowercase and underscores separate words. +names, in which all letters are lowercase and underscores separate words. Here’s a program that contains an example function definition: Filename: src/main.rs @@ -741,9 +755,9 @@ fn another_function() { } ``` -Function definitions in Rust start with `fn` and have a set of parentheses -after the function name. The curly brackets tell the compiler where the -function body begins and ends. +We define a function in Rust by entering `fn` followed by a function name and a +set of parentheses. The curly brackets tell the compiler where the function +body begins and ends. We can call any function we’ve defined by entering its name followed by a set of parentheses. Because `another_function` is defined in the program, it can be @@ -769,18 +783,17 @@ The lines execute in the order in which they appear in the `main` function. First, the “Hello, world!” message prints, and then `another_function` is called and its message is printed. -### Function Parameters +### Parameters -Functions can also be defined to have *parameters*, which are special variables -that are part of a function’s signature. When a function has parameters, you -can provide it with concrete values for those parameters. Technically, the -concrete values are called *arguments*, but in casual conversation, people tend -to use the words *parameter* and *argument* interchangeably for either the -variables in a function’s definition or the concrete values passed in when you -call a function. +We can define functions to have *parameters*, which are special variables that +are part of a function’s signature. When a function has parameters, you can +provide it with concrete values for those parameters. Technically, the concrete +values are called *arguments*, but in casual conversation, people tend to use +the words *parameter* and *argument* interchangeably for either the variables +in a function’s definition or the concrete values passed in when you call a +function. -The following rewritten version of `another_function` shows what parameters -look like in Rust: +In this version of `another_function` we add a parameter: Filename: src/main.rs @@ -805,7 +818,7 @@ The value of x is: 5 ``` The declaration of `another_function` has one parameter named `x`. The type of -`x` is specified as `i32`. When `5` is passed to `another_function`, the +`x` is specified as `i32`. When we pass `5` in to `another_function`, the `println!` macro puts `5` where the pair of curly brackets were in the format string. @@ -814,8 +827,8 @@ a deliberate decision in Rust’s design: requiring type annotations in function definitions means the compiler almost never needs you to use them elsewhere in the code to figure out what type you mean. -When you want a function to have multiple parameters, separate the parameter -declarations with commas, like this: +When defining multiple parameters, separate the parameter declarations with +commas, like this: Filename: src/main.rs @@ -849,22 +862,22 @@ The measurement is: 5h Because we called the function with `5` as the value for `value` and `'h'` as the value for `unit_label`, the program output contains those values. -### Function Bodies Contain Statements and Expressions +### Statements and Expressions Function bodies are made up of a series of statements optionally ending in an -expression. So far, we’ve only covered functions without an ending expression, -but you have seen an expression as part of a statement. Because Rust is an -expression-based language, this is an important distinction to understand. -Other languages don’t have the same distinctions, so let’s look at what -statements and expressions are and how their differences affect the bodies of -functions. +expression. So far, the functions we've covered haven't included an ending +expression, but you have seen an expression as part of a statement. Because +Rust is an expression-based language, this is an important distinction to +understand. Other languages don’t have the same distinctions, so let’s look at +what statements and expressions are and how their differences affect the bodies +of functions. -We’ve actually already used statements and expressions. *Statements* are -instructions that perform some action and do not return a value. *Expressions* -evaluate to a resulting value. Let’s look at some examples. +*Statements* are instructions that perform some action and do not return a +value. *Expressions* evaluate to a resulting value. Let’s look at some examples. -Creating a variable and assigning a value to it with the `let` keyword is a -statement. In Listing 3-1, `let y = 6;` is a statement. +We’ve actually already used statements and expressions. Creating a variable and +assigning a value to it with the `let` keyword is a statement. In Listing 3-1, +`let y = 6;` is a statement. Filename: src/main.rs @@ -932,8 +945,8 @@ you’ll write in Rust. Consider a math operation, such as `5 + 6`, which is an expression that evaluates to the value `11`. Expressions can be part of statements: in Listing 3-1, the `6` in the statement `let y = 6;` is an expression that evaluates to the value `6`. Calling a function is an -expression. Calling a macro is an expression. The block that we use to create -new scopes, `{}`, is an expression, for example: +expression. Calling a macro is an expression. A new scope block created with +curly brackets is an expression, for example: Filename: src/main.rs @@ -960,10 +973,10 @@ This expression: ``` is a block that, in this case, evaluates to `4`. That value gets bound to `y` -as part of the `let` statement. Note the `x + 1` line without a semicolon at -the end, which is unlike most of the lines you’ve seen so far. Expressions do -not include ending semicolons. If you add a semicolon to the end of an -expression, you turn it into a statement, which will then not return a value. +as part of the `let` statement. Note that the `x + 1` line doesn't have a +semicolon at the end, unlike most of the lines you’ve seen so far. Expressions +do not include ending semicolons. If you add a semicolon to the end of an +expression, you turn it into a statement, and it will then not return a value. Keep this in mind as you explore function return values and expressions next. ### Functions with Return Values @@ -1078,9 +1091,9 @@ would fix the error. ## Comments All programmers strive to make their code easy to understand, but sometimes -extra explanation is warranted. In these cases, programmers leave notes, or -*comments*, in their source code that the compiler will ignore but people -reading the source code may find useful. +extra explanation is warranted. In these cases, programmers leave *comments* in +their source code that the compiler will ignore but people reading the source +code may find useful. Here’s a simple comment: @@ -1125,11 +1138,10 @@ discuss in the “Publishing a Crate to Crates.io” section of Chapter 14. ## Control Flow -Deciding whether or not to run some code depending on if a condition is true -and deciding to run some code repeatedly while a condition is true are basic -building blocks in most programming languages. The most common constructs that -let you control the flow of execution of Rust code are `if` expressions and -loops. +The ability to run some code depending on if a condition is true, or run some +code repeatedly while a condition is true, are basic building blocks in most +programming languages. The most common constructs that let you control the flow +of execution of Rust code are `if` expressions and loops. ### `if` Expressions @@ -1154,14 +1166,13 @@ fn main() { } ``` -All `if` expressions start with the keyword `if`, which is followed by a -condition. In this case, the condition checks whether or not the variable -`number` has a value less than 5. The block of code we want to execute if the -condition is true is placed immediately after the condition inside curly -brackets. Blocks of code associated with the conditions in `if` expressions are -sometimes called *arms*, just like the arms in `match` expressions that we -discussed in the “Comparing the Guess to the Secret Number” section of Chapter -2. +All `if` expressions start with the keyword `if`, followed by a condition. In +this case, the condition checks whether or not the variable `number` has a +value less than 5. We place block of code to execute if the condition is true +immediately after the condition inside curly brackets. Blocks of code +associated with the conditions in `if` expressions are sometimes called *arms*, +just like the arms in `match` expressions that we discussed in the “Comparing +the Guess to the Secret Number” section of Chapter 2. Optionally, we can also include an `else` expression, which we chose to do here, to give the program an alternative block of code to execute should @@ -1248,7 +1259,7 @@ Running this code will print `number was something other than zero`. #### Handling Multiple Conditions with `else if` -You can have multiple conditions by combining `if` and `else` in an `else if` +You can use multiple conditions by combining `if` and `else` in an `else if` expression. For example: Filename: src/main.rs @@ -1294,7 +1305,7 @@ Rust branching construct called `match` for these cases. #### Using `if` in a `let` Statement Because `if` is an expression, we can use it on the right side of a `let` -statement, as in Listing 3-2. +statement to assign the outcome to a variable, as in Listing 3-2. Filename: src/main.rs @@ -1359,18 +1370,18 @@ error[E0308]: `if` and `else` have incompatible types The expression in the `if` block evaluates to an integer, and the expression in the `else` block evaluates to a string. This won’t work because variables must -have a single type. Rust needs to know at compile time what type the `number` -variable is, definitively, so it can verify at compile time that its type is -valid everywhere we use `number`. Rust wouldn’t be able to do that if the type -of `number` was only determined at runtime; the compiler would be more complex -and would make fewer guarantees about the code if it had to keep track of -multiple hypothetical types for any variable. +have a single type, and Rust needs to know at compile time what type the +`number` variable is, definitively. Knowing the type of `number` lets the +compiler verify the type is valid everywhere we use `number`. Rust wouldn’t be +able to do that if the type of `number` was only determined at runtime; the +compiler would be more complex and would make fewer guarantees about the code +if it had to keep track of multiple hypothetical types for any variable. ### Repetition with Loops It’s often useful to execute a block of code more than once. For this task, -Rust provides several *loops*. A loop runs through the code inside the loop -body to the end and then starts immediately back at the beginning. To +Rust provides several *loops*, which will run through the code inside the loop +body to the end and then start immediately back at the beginning. To experiment with loops, let’s make a new project called *loops*. Rust has three kinds of loops: `loop`, `while`, and `for`. Let’s try each one. @@ -1394,8 +1405,8 @@ fn main() { ``` When we run this program, we’ll see `again!` printed over and over continuously -until we stop the program manually. Most terminals support a keyboard shortcut, -ctrl-c, to interrupt a program that is stuck in +until we stop the program manually. Most terminals support the keyboard shortcut +ctrl-c to interrupt a program that is stuck in a continual loop. Give it a try: ``` @@ -1415,19 +1426,19 @@ The symbol `^C` represents where you pressed ctrl-c depending on where the code was in the loop when it received the interrupt signal. -Fortunately, Rust provides a way to break out of a loop from code. You can +Fortunately, Rust also provides a way to break out of a loop using code. You can place the `break` keyword within the loop to tell the program when to stop executing the loop. Recall that we did this in the guessing game in the “Quitting After a Correct Guess” section of Chapter 2 to exit the program when the user won the game by guessing the correct number. -We also used `continue` in the guessing game. The `continue` keyword within a -loop tells the program to skip over any remaining code in this iteration of the -loop and go to the next iteration. +We also used `continue` in the guessing game, which in a loop tells the program +to skip over any remaining code in this iteration of the loop and go to the +next iteration. If you have loops within loops, `break` and `continue` apply to the innermost -loop at that point. You can optionally specify a *loop label* on a loop and -then use the label with `break` or `continue` to have those keywords applied to +loop at that point. You can optionally specify a *loop label* on a loop that we +can then use with `break` or `continue` to specify that those keywords apply to the labeled loop instead of the innermost loop. Here’s an example with two nested loops: @@ -1478,11 +1489,11 @@ End count = 2 #### Returning Values from Loops One of the uses of a `loop` is to retry an operation you know might fail, such -as checking whether a thread has completed its job. However, you might need to -pass the result of that operation to the rest of your code. To do this, you can -add the value you want returned after the `break` expression you use to stop -the loop; that value will be returned out of the loop so you can use it, as -shown here: +as checking whether a thread has completed its job. You might also need to pass +the result of that operation out of the loop to the rest of your code. To do +this, you can add the value you want returned after the `break` expression you +use to stop the loop; that value will be returned out of the loop so you can +use it, as shown here: ``` fn main() { @@ -1510,16 +1521,14 @@ print the value in `result`, which in this case is 20. #### Conditional Loops with `while` -It’s often useful for a program to evaluate a condition within a loop. While -the condition is true, the loop runs. When the condition ceases to be true, the -program calls `break`, stopping the loop. This loop type could be implemented -using a combination of `loop`, `if`, `else`, and `break`; you could try that -now in a program, if you’d like. - -However, this pattern is so common that Rust has a built-in language construct -for it, called a `while` loop. Listing 3-3 uses `while`: the program loops -three times, counting down each time, and then, after the loop, it prints -another message and exits. +A program will often need to evaluate a condition within a loop. While the +condition is true, the loop runs. When the condition ceases to be true, the +program calls `break`, stopping the loop. It's possible to implement behavior +like this using a combination of `loop`, `if`, `else`, and `break`; you could +try that now in a program, if you’d like. However, this pattern is so common +that Rust has a built-in language construct for it, called a `while` loop. In +Listing 3-3, we use `while` to loop the program three times, counting down each +time, and then, after the loop, print a message and exit. Filename: src/main.rs @@ -1545,8 +1554,9 @@ true, the code runs; otherwise, it exits the loop. #### Looping Through a Collection with `for` -You could use the `while` construct to loop over the elements of a collection, -such as an array. For example, let’s look at Listing 3-4. +You can choose to use the `while` construct to loop over the elements of a +collection, such as an array. For example, the loop in Listing 3-4 prints each +element in the array `a`. Filename: src/main.rs @@ -1586,9 +1596,11 @@ All five array values appear in the terminal, as expected. Even though `index` will reach a value of `5` at some point, the loop stops executing before trying to fetch a sixth value from the array. -But this approach is error prone; we could cause the program to panic if the -index value or test condition are incorrect. It’s also slow, because the -compiler adds runtime code to perform the conditional check of whether the +However, this approach is error prone; we could cause the program to panic if +the index value or test condition are incorrect. For example, if you changed +the definition of the `a` array to have four elements but forgot to update the +condition to `while index < 4`, the code would panic. It’s also slow, because +the compiler adds runtime code to perform the conditional check of whether the index is within the bounds of the array on every iteration through the loop. As a more concise alternative, you can use a `for` loop and execute some code @@ -1613,19 +1625,17 @@ importantly, we’ve now increased the safety of the code and eliminated the chance of bugs that might result from going beyond the end of the array or not going far enough and missing some items. -For example, in the code in Listing 3-4, if you changed the definition of the -`a` array to have four elements but forgot to update the condition to `while -index < 4`, the code would panic. Using the `for` loop, you wouldn’t need to -remember to change any other code if you changed the number of values in the -array. +Using the `for` loop, you wouldn’t need to remember to change any other code if +you changed the number of values in the array, as you would with the method +used in Listing 3-4. The safety and conciseness of `for` loops make them the most commonly used loop construct in Rust. Even in situations in which you want to run some code a certain number of times, as in the countdown example that used a `while` loop in Listing 3-3, most Rustaceans would use a `for` loop. The way to do that -would be to use a `Range`, which is a type provided by the standard library -that generates all numbers in sequence starting from one number and ending -before another number. +would be to use a `Range`, provided by the standard library, which generates +all numbers in sequence starting from one number and ending before another +number. Here’s what the countdown would look like using a `for` loop and another method we’ve not yet talked about, `rev`, to reverse the range: @@ -1646,8 +1656,8 @@ This code is a bit nicer, isn’t it? ## Summary You made it! That was a sizable chapter: you learned about variables, scalar -and compound data types, functions, comments, `if` expressions, and loops! If -you want to practice with the concepts discussed in this chapter, try building +and compound data types, functions, comments, `if` expressions, and loops! +To practice with the concepts discussed in this chapter, try building programs to do the following: * Convert temperatures between Fahrenheit and Celsius. diff --git a/src/doc/book/nostarch/chapter04.md b/src/doc/book/nostarch/chapter04.md index 24f55b1df6..8334bf1202 100644 --- a/src/doc/book/nostarch/chapter04.md +++ b/src/doc/book/nostarch/chapter04.md @@ -3,28 +3,29 @@ # Understanding Ownership -Ownership is Rust’s most unique feature, and it enables Rust to make memory -safety guarantees without needing a garbage collector. Therefore, it’s -important to understand how ownership works in Rust. In this chapter, we’ll -talk about ownership as well as several related features: borrowing, slices, -and how Rust lays data out in memory. +Ownership is Rust’s most unique feature and has deep implications for the rest +of the language. It enables Rust to make memory safety guarantees without +needing a garbage collector, so it’s important to understand how ownership +works. In this chapter, we’ll talk about ownership as well as several related +features: borrowing, slices, and how Rust lays data out in memory. ## What Is Ownership? -Rust’s central feature is *ownership*. Although the feature is straightforward -to explain, it has deep implications for the rest of the language. - +*Ownership* is a set of rules that governs how a Rust program manages memory. All programs have to manage the way they use a computer’s memory while running. -Some languages have garbage collection that constantly looks for no longer used +Some languages have garbage collection that constantly looks for no-longer used memory as the program runs; in other languages, the programmer must explicitly allocate and free the memory. Rust uses a third approach: memory is managed -through a system of ownership with a set of rules that the compiler checks at -compile time. None of the ownership features slow down your program while it’s +through a system of ownership with a set of rules that the compiler checks. If +any of the rules are violated, the program won’t compile. + + +None of the features of ownership will slow down your program while it’s running. Because ownership is a new concept for many programmers, it does take some time to get used to. The good news is that the more experienced you become with Rust -and the rules of the ownership system, the more you’ll be able to naturally +and the rules of the ownership system, the easier you’ll find it to naturally develop code that is safe and efficient. Keep at it! When you understand ownership, you’ll have a solid foundation for understanding @@ -34,44 +35,44 @@ strings. > ### The Stack and the Heap > -> In many programming languages, you don’t have to think about the stack and -> the heap very often. But in a systems programming language like Rust, whether -> a value is on the stack or the heap has more of an effect on how the language -> behaves and why you have to make certain decisions. Parts of ownership will -> be described in relation to the stack and the heap later in this chapter, so -> here is a brief explanation in preparation. -> -> Both the stack and the heap are parts of memory that are available to your -> code to use at runtime, but they are structured in different ways. The stack -> stores values in the order it gets them and removes the values in the -> opposite order. This is referred to as *last in, first out*. Think of a stack -> of plates: when you add more plates, you put them on top of the pile, and -> when you need a plate, you take one off the top. Adding or removing plates -> from the middle or bottom wouldn’t work as well! Adding data is called -> *pushing onto the stack*, and removing data is called *popping off the stack*. +> Many programming languages don’t require you to think about the stack and the +> heap very often. But in a systems programming language like Rust, whether a +> value is on the stack or the heap affects how the language behaves and why +> you have to make certain decisions. Parts of ownership will be described in +> relation to the stack and the heap later in this chapter, so here is a brief +> explanation in preparation. > -> All data stored on the stack must have a known, fixed size. Data with an -> unknown size at compile time or a size that might change must be stored on -> the heap instead. The heap is less organized: when you put data on the heap, -> you request a certain amount of space. The memory allocator finds an empty -> spot in the heap that is big enough, marks it as being in use, and returns a -> *pointer*, which is the address of that location. This process is called -> *allocating on the heap* and is sometimes abbreviated as just *allocating*. -> Pushing values onto the stack is not considered allocating. Because the -> pointer is a known, fixed size, you can store the pointer on the stack, but -> when you want the actual data, you must follow the pointer. +> Both the stack and the heap are parts of memory available to your code to use +> at runtime, but they are structured in different ways. The stack stores +> values in the order it gets them and removes the values in the opposite +> order. This is referred to as *last in, first out*. Think of a stack of +> plates: when you add more plates, you put them on top of the pile, and when +> you need a plate, you take one off the top. Adding or removing plates from +> the middle or bottom wouldn’t work as well! Adding data is called *pushing +> onto the stack*, and removing data is called *popping off the stack*. All +> data stored on the stack must have a known, fixed size. Data with an unknown +> size at compile time or a size that might change must be stored on the heap +> instead. > -> Think of being seated at a restaurant. When you enter, you state the number of -> people in your group, and the staff finds an empty table that fits everyone -> and leads you there. If someone in your group comes late, they can ask where -> you’ve been seated to find you. +> The heap is less organized: when you put data on the heap, you request a +> certain amount of space. The memory allocator finds an empty spot in the heap +> that is big enough, marks it as being in use, and returns a *pointer*, which +> is the address of that location. This process is called *allocating on the +> heap* and is sometimes abbreviated as just *allocating*. Pushing values onto +> the stack is not considered allocating. Because the pointer to the heap is a +> known, fixed size, you can store the pointer on the stack, but when you want +> the actual data, you must follow the pointer. Think of being seated at a +> restaurant. When you enter, you state the number of people in your group, and +> the staff finds an empty table that fits everyone and leads you there. If +> someone in your group comes late, they can ask where you’ve been seated to +> find you. > > Pushing to the stack is faster than allocating on the heap because the -> allocator never has to search for a place to store new data; that -> location is always at the top of the stack. Comparatively, allocating space -> on the heap requires more work, because the allocator must first find -> a big enough space to hold the data and then perform bookkeeping to prepare -> for the next allocation. +> allocator never has to search for a place to store new data; that location is +> always at the top of the stack. Comparatively, allocating space on the heap +> requires more work, because the allocator must first find a big enough space +> to hold the data and then perform bookkeeping to prepare for the next +> allocation. > > Accessing data in the heap is slower than accessing data on the stack because > you have to follow a pointer to get there. Contemporary processors are faster @@ -93,8 +94,8 @@ strings. > minimizing the amount of duplicate data on the heap, and cleaning up unused > data on the heap so you don’t run out of space are all problems that ownership > addresses. Once you understand ownership, you won’t need to think about the -> stack and the heap very often, but knowing that managing heap data is why -> ownership exists can help explain why it works the way it does. +> stack and the heap very often, but knowing that the main purpose of ownership +> is to manage heap data can help explain why it works the way it does. ### Ownership Rules @@ -107,16 +108,15 @@ work through the examples that illustrate them: ### Variable Scope -We’ve walked through an example of a Rust program already in Chapter 2. Now -that we’re past basic syntax, we won’t include all the `fn main() {` code in -examples, so if you’re following along, you’ll have to put the following +Now that we’re past basic Rust syntax, we won’t include all the `fn main() {` +code in examples, so if you’re following along, make sure to put the following examples inside a `main` function manually. As a result, our examples will be a bit more concise, letting us focus on the actual details rather than boilerplate code. As a first example of ownership, we’ll look at the *scope* of some variables. A -scope is the range within a program for which an item is valid. Let’s say we -have a variable that looks like this: +scope is the range within a program for which an item is valid. Take the +following variable: ``` let s = "hello"; @@ -124,15 +124,15 @@ let s = "hello"; The variable `s` refers to a string literal, where the value of the string is hardcoded into the text of our program. The variable is valid from the point at -which it’s declared until the end of the current *scope*. Listing 4-1 has -comments annotating where the variable `s` is valid. +which it’s declared until the end of the current *scope*. Listing 4-1 shows a +program with comments annotating where the variable `s` would be valid. ``` - { // s is not valid here, it’s not yet declared - let s = "hello"; // s is valid from this point forward +{ // s is not valid here, it’s not yet declared + let s = "hello"; // s is valid from this point forward. - // do stuff with s - } // this scope is now over, and s is no longer valid + // do stuff with s +} // this scope is now over, and s is no longer valid ``` Listing 4-1: A variable and the scope in which it is valid @@ -149,17 +149,18 @@ understanding by introducing the `String` type. ### The `String` Type To illustrate the rules of ownership, we need a data type that is more complex -than the ones we covered in the “Data Types” section of Chapter 3. The types +than those we covered in the “Data Types” section of Chapter 3. The types covered previously are all a known size, can be stored on the stack and popped off the stack when their scope is over, and can be quickly and trivially copied to make a new, independent instance if another part of code needs to use the same value in a different scope. But we want to look at data that is stored on -the heap and explore how Rust knows when to clean up that data. +the heap and explore how Rust knows when to clean up that data, and the +`String` type is a great example. -We’ll use `String` as the example here and concentrate on the parts of `String` -that relate to ownership. These aspects also apply to other complex data types, -whether they are provided by the standard library or created by you. We’ll -discuss `String` in more depth in Chapter 8. +We’ll concentrate on the parts of `String` that relate to ownership. These +aspects also apply to other complex data types, whether they are provided by +the standard library or created by you. We’ll discuss `String` in more depth in +Chapter 8. We’ve already seen string literals, where a string value is hardcoded into our program. String literals are convenient, but they aren’t suitable for every @@ -175,20 +176,20 @@ literal using the `from` function, like so: let s = String::from("hello"); ``` -The double colon (`::`) is an operator that allows us to namespace this -particular `from` function under the `String` type rather than using some sort -of name like `string_from`. We’ll discuss this syntax more in the “Method -Syntax” section of Chapter 5 and when we talk about namespacing with modules in -“Paths for Referring to an Item in the Module Tree” in Chapter 7. +The double colon `::` operator allows us to namespace this particular `from` +function under the `String` type rather than using some sort of name like +`string_from`. We’ll discuss this syntax more in the “Method Syntax” section of +Chapter 5 and when we talk about namespacing with modules in “Paths for +Referring to an Item in the Module Tree” in Chapter 7. This kind of string *can* be mutated: ``` - let mut s = String::from("hello"); +let mut s = String::from("hello"); - s.push_str(", world!"); // push_str() appends a literal to a String +s.push_str(", world!"); // push_str() appends a literal to a String - println!("{}", s); // This will print `hello, world!` +println!("{}", s); // This will print `hello, world!` ``` So, what’s the difference here? Why can `String` be mutated but literals @@ -216,25 +217,26 @@ requests the memory it needs. This is pretty much universal in programming languages. However, the second part is different. In languages with a *garbage collector -(GC)*, the GC keeps track and cleans up memory that isn’t being used anymore, -and we don’t need to think about it. Without a GC, it’s our responsibility to -identify when memory is no longer being used and call code to explicitly return -it, just as we did to request it. Doing this correctly has historically been a -difficult programming problem. If we forget, we’ll waste memory. If we do it -too early, we’ll have an invalid variable. If we do it twice, that’s a bug too. -We need to pair exactly one `allocate` with exactly one `free`. +(GC)*, the GC keeps track of and cleans up memory that isn’t being used +anymore, and we don’t need to think about it. In most languages without a GC, +it’s our responsibility to identify when memory is no longer being used and +call code to explicitly return it, just as we did to request it. Doing this +correctly has historically been a difficult programming problem. If we forget, +we’ll waste memory. If we do it too early, we’ll have an invalid variable. If +we do it twice, that’s a bug too. We need to pair exactly one `allocate` with +exactly one `free`. Rust takes a different path: the memory is automatically returned once the variable that owns it goes out of scope. Here’s a version of our scope example from Listing 4-1 using a `String` instead of a string literal: ``` - { - let s = String::from("hello"); // s is valid from this point forward +{ + let s = String::from("hello"); // s is valid from this point forward - // do stuff with s - } // this scope is now over, and s is no - // longer valid + // do stuff with s +} // this scope is now over, and s is no + // longer valid ``` There is a natural point at which we can return the memory our `String` needs @@ -278,9 +280,9 @@ Now let’s look at the `String` version: let s2 = s1; ``` -This looks very similar to the previous code, so we might assume that the way -it works would be the same: that is, the second line would make a copy of the -value in `s1` and bind it to `s2`. But this isn’t quite what happens. +This looks very similar, so we might assume that the way it works would be the +same: that is, the second line would make a copy of the value in `s1` and bind +it to `s2`. But this isn’t quite what happens. Take a look at Figure 4-1 to see what is happening to `String` under the covers. A `String` is made up of three parts, shown on the left: a pointer to @@ -290,7 +292,8 @@ heap that holds the contents. String in memory -Figure 4-1: Representation in memory of a `String` holding the value `"hello"` bound to `s1` +Figure 4-1: Representation in memory of a `String` holding the value `"hello"` +bound to `s1` The length is how much memory, in bytes, the contents of the `String` is currently using. The capacity is the total amount of memory, in bytes, that the @@ -305,7 +308,8 @@ representation in memory looks like Figure 4-2. s1 and s2 pointing to the same value -Figure 4-2: Representation in memory of the variable `s2` that has a copy of the pointer, length, and capacity of `s1` +Figure 4-2: Representation in memory of the variable `s2` that has a copy of +the pointer, length, and capacity of `s1` The representation does *not* look like Figure 4-3, which is what memory would look like if Rust instead copied the heap data as well. If Rust did this, the @@ -314,7 +318,8 @@ the data on the heap were large. s1 and s2 to two places -Figure 4-3: Another possibility for what `s2 = s1` might do if Rust copied the heap data as well +Figure 4-3: Another possibility for what `s2 = s1` might do if Rust copied the +heap data as well Earlier, we said that when a variable goes out of scope, Rust automatically calls the `drop` function and cleans up the heap memory for that variable. But @@ -324,25 +329,22 @@ same memory. This is known as a *double free* error and is one of the memory safety bugs we mentioned previously. Freeing memory twice can lead to memory corruption, which can potentially lead to security vulnerabilities. -To ensure memory safety, there’s one more detail to what happens in this -situation in Rust. After `let s2 = s1`, Rust considers `s1` to no longer be -valid. Therefore, Rust doesn’t need to free anything when `s1` goes out of -scope. Check out what happens when you try to use `s1` after `s2` is created; -it won’t work: +To ensure memory safety, after the line `let s2 = s1`, Rust considers `s1` as +no longer valid. Therefore, Rust doesn’t need to free anything when `s1` goes +out of scope. Check out what happens when you try to use `s1` after `s2` is +created; it won’t work: ``` - let s1 = String::from("hello"); - let s2 = s1; +let s1 = String::from("hello"); +let s2 = s1; - println!("{}, world!", s1); +println!("{}, world!", s1); ``` You’ll get an error like this because Rust prevents you from using the invalidated reference: ``` -$ cargo run - Compiling ownership v0.1.0 (file:///projects/ownership) error[E0382]: borrow of moved value: `s1` --> src/main.rs:5:28 | @@ -358,7 +360,7 @@ error[E0382]: borrow of moved value: `s1` If you’ve heard the terms *shallow copy* and *deep copy* while working with other languages, the concept of copying the pointer, length, and capacity without copying the data probably sounds like making a shallow copy. But -because Rust also invalidates the first variable, instead of being called a +because Rust also invalidates the first variable, instead of calling it a shallow copy, it’s known as a *move*. In this example, we would say that `s1` was *moved* into `s2`. So what actually happens is shown in Figure 4-4. @@ -383,10 +385,10 @@ programming languages, you’ve probably seen them before. Here’s an example of the `clone` method in action: ``` - let s1 = String::from("hello"); - let s2 = s1.clone(); +let s1 = String::from("hello"); +let s2 = s1.clone(); - println!("s1 = {}, s2 = {}", s1, s2); +println!("s1 = {}, s2 = {}", s1, s2); ``` This works just fine and explicitly produces the behavior shown in Figure 4-3, @@ -402,10 +404,10 @@ There’s another wrinkle we haven’t talked about yet. This code using integer part of which was shown in Listing 4-2 – works and is valid: ``` - let x = 5; - let y = x; +let x = 5; +let y = x; - println!("x = {}, y = {}", x, y); +println!("x = {}, y = {}", x, y); ``` But this code seems to contradict what we just learned: we don’t have a call to @@ -419,14 +421,20 @@ between deep and shallow copying here, so calling `clone` wouldn’t do anything different from the usual shallow copying and we can leave it out. Rust has a special annotation called the `Copy` trait that we can place on -types like integers that are stored on the stack (we’ll talk more about traits -in Chapter 10). If a type implements the `Copy` trait, an older variable is -still usable after assignment. Rust won’t let us annotate a type with the -`Copy` trait if the type, or any of its parts, has implemented the `Drop` -trait. If the type needs something special to happen when the value goes out of -scope and we add the `Copy` annotation to that type, we’ll get a compile-time -error. To learn about how to add the `Copy` annotation to your type to -implement the trait, see “Derivable Traits” in Appendix C. +types that are stored on the stack like integers are (we’ll talk more about +traits in Chapter 10). If a type implements the `Copy` trait, a variable is +still valid after assignment to another variable. + + +Rust won’t let us annotate a type with `Copy` if the type, or any of its parts, +has implemented the `Drop` trait. If the type needs something special to happen +when the value goes out of scope and we add the `Copy` annotation to that type, +we’ll get a compile-time error. To learn about how to add the `Copy` annotation +to your type to implement the trait, see “Derivable Traits” in Appendix C. So what types implement the `Copy` trait? You can check the documentation for the given type to be sure, but as a general rule, any group of simple scalar @@ -485,8 +493,9 @@ the ownership rules prevent you from doing so. ### Return Values and Scope -Returning values can also transfer ownership. Listing 4-4 is an example with -similar annotations to those in Listing 4-3. +Returning values can also transfer ownership. Listing 4-4 shows an example +of a function that returns some value, with similar annotations as those in +Listing 4-3. Filename: src/main.rs @@ -526,16 +535,16 @@ Listing 4-4: Transferring ownership of return values The ownership of a variable follows the same pattern every time: assigning a value to another variable moves it. When a variable that includes data on the -heap goes out of scope, the value will be cleaned up by `drop` unless the data -has been moved to be owned by another variable. +heap goes out of scope, the value will be cleaned up by `drop` unless ownership +of the data has been moved to another variable. -Taking ownership and then returning ownership with every function is a bit -tedious. What if we want to let a function use a value but not take ownership? -It’s quite annoying that anything we pass in also needs to be passed back if we -want to use it again, in addition to any data resulting from the body of the -function that we might want to return as well. +While this works, taking ownership and then returning ownership with every +function is a bit tedious. What if we want to let a function use a value but +not take ownership? It’s quite annoying that anything we pass in also needs to +be passed back if we want to use it again, in addition to any data resulting +from the body of the function that we might want to return as well. -It’s possible to return multiple values using a tuple, as shown in Listing 4-5. +Rust does let us return multiple values using a tuple, as shown in Listing 4-5. Filename: src/main.rs @@ -558,19 +567,24 @@ fn calculate_length(s: String) -> (String, usize) { Listing 4-5: Returning ownership of parameters But this is too much ceremony and a lot of work for a concept that should be -common. Luckily for us, Rust has a feature for this concept, called -*references*. +common. Luckily for us, Rust has a feature for using a value without +transferring ownership, called *references*. ## References and Borrowing The issue with the tuple code in Listing 4-5 is that we have to return the `String` to the calling function so we can still use the `String` after the call to `calculate_length`, because the `String` was moved into -`calculate_length`. - +`calculate_length`. Instead, we can provide a reference to the `String` value. +A *reference* is like a pointer in that it’s an address we can follow to access +data stored at that address that is owned by some other variable. Unlike a +pointer, a reference is guaranteed to point to a valid value of a particular +type. + + Here is how you would define and use a `calculate_length` function that has a -reference to an object as a parameter instead of taking ownership of the -value: +reference to an object as a parameter instead of taking ownership of the value: Filename: src/main.rs @@ -591,10 +605,8 @@ fn calculate_length(s: &String) -> usize { First, notice that all the tuple code in the variable declaration and the function return value is gone. Second, note that we pass `&s1` into `calculate_length` and, in its definition, we take `&String` rather than -`String`. - -These ampersands are *references*, and they allow you to refer to some value -without taking ownership of it. Figure 4-5 shows a diagram. +`String`. These ampersands represent *references*, and they allow you to refer +to some value without taking ownership of it. Figure 4-5 depicts this concept. &String s pointing at String s1 @@ -608,9 +620,9 @@ Figure 4-5: A diagram of `&String s` pointing at `String s1` Let’s take a closer look at the function call here: ``` - let s1 = String::from("hello"); +let s1 = String::from("hello"); - let len = calculate_length(&s1); +let len = calculate_length(&s1); ``` The `&s1` syntax lets us create a reference that *refers* to the value of `s1` @@ -628,14 +640,15 @@ fn calculate_length(s: &String) -> usize { // s is a reference to a String ``` The scope in which the variable `s` is valid is the same as any function -parameter’s scope, but we don’t drop what the reference points to when `s` -stops being used because we don’t have ownership. When functions have -references as parameters instead of the actual values, we won’t need to return -the values in order to give back ownership, because we never had ownership. +parameter’s scope, but the value pointed to by the reference is not dropped +when `s` stops being used because `s` doesn’t have ownership. When functions +have references as parameters instead of the actual values, we won’t need to +return the values in order to give back ownership, because we never had +ownership. We call the action of creating a reference *borrowing*. As in real life, if a person owns something, you can borrow it from them. When you’re done, you have -to give it back. +to give it back. You don’t own it. So what happens if we try to modify something we’re borrowing? Try the code in Listing 4-6. Spoiler alert: it doesn’t work! @@ -659,8 +672,6 @@ Listing 4-6: Attempting to modify a borrowed value Here’s the error: ``` -$ cargo run - Compiling ownership v0.1.0 (file:///projects/ownership) error[E0596]: cannot borrow `*some_string` as mutable, as it is behind a `&` reference --> src/main.rs:8:5 | @@ -675,7 +686,8 @@ allowed to modify something we have a reference to. ### Mutable References -We can fix the error in the code from Listing 4-6 with just a few small tweaks: +We can fix the code from Listing 4-6 to allow us to modify a borrowed value +with just a few small tweaks that use, instead, a *mutable reference*: Filename: src/main.rs @@ -691,14 +703,14 @@ fn change(some_string: &mut String) { } ``` -First, we had to change `s` to be `mut`. Then we had to create a mutable -reference with `&mut s` where we call the `change` function, and update the -function signature to accept a mutable reference with `some_string: &mut -String`. This makes it very clear that the `change` function will mutate the -value it borrows. +First, we change `s` to be `mut`. Then we create a mutable reference with `&mut +s` where we call the `change` function, and update the function signature to +accept a mutable reference with `some_string: &mut String`. This makes it very +clear that the `change` function will mutate the value it borrows. -But mutable references have one big restriction: you can have only one mutable -reference to a particular piece of data at a time. This code will fail: +Mutable references have one big restriction: you can have only one mutable +reference to a particular piece of data at a time. This code that attempts to +create two mutable references to `s` will fail: Filename: src/main.rs @@ -714,8 +726,6 @@ Filename: src/main.rs Here’s the error: ``` -$ cargo run - Compiling ownership v0.1.0 (file:///projects/ownership) error[E0499]: cannot borrow `s` as mutable more than once at a time --> src/main.rs:5:14 | @@ -737,11 +747,9 @@ in `r2` that borrows the same data as `r1`. The restriction preventing multiple mutable references to the same data at the same time allows for mutation but in a very controlled fashion. It’s something that new Rustaceans struggle with, because most languages let you mutate -whenever you’d like. - -The benefit of having this restriction is that Rust can prevent data races at -compile time. A *data race* is similar to a race condition and happens when -these three behaviors occur: +whenever you’d like. The benefit of having this restriction is that Rust can +prevent data races at compile time. A *data race* is similar to a race +condition and happens when these three behaviors occur: * Two or more pointers access the same data at the same time. * At least one of the pointers is being used to write to the data. @@ -749,39 +757,37 @@ these three behaviors occur: Data races cause undefined behavior and can be difficult to diagnose and fix when you’re trying to track them down at runtime; Rust prevents this problem -from happening because it won’t even compile code with data races! +by refusing to compile code with data races! As always, we can use curly brackets to create a new scope, allowing for multiple mutable references, just not *simultaneous* ones: ``` - let mut s = String::from("hello"); +let mut s = String::from("hello"); - { - let r1 = &mut s; - } // r1 goes out of scope here, so we can make a new reference with no problems. +{ + let r1 = &mut s; +} // r1 goes out of scope here, so we can make a new reference with no problems. - let r2 = &mut s; +let r2 = &mut s; ``` -A similar rule exists for combining mutable and immutable references. This code -results in an error: +Rust enforces a similar rule for combining mutable and immutable references. +This code results in an error: ``` - let mut s = String::from("hello"); +let mut s = String::from("hello"); - let r1 = &s; // no problem - let r2 = &s; // no problem - let r3 = &mut s; // BIG PROBLEM +let r1 = &s; // no problem +let r2 = &s; // no problem +let r3 = &mut s; // BIG PROBLEM - println!("{}, {}, and {}", r1, r2, r3); +println!("{}, {}, and {}", r1, r2, r3); ``` Here’s the error: ``` -$ cargo run - Compiling ownership v0.1.0 (file:///projects/ownership) error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immutable --> src/main.rs:6:14 | @@ -795,11 +801,15 @@ error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immuta | -- immutable borrow later used here ``` -Whew! We *also* cannot have a mutable reference while we have an immutable one. -Users of an immutable reference don’t expect the values to suddenly change out -from under them! However, multiple immutable references are okay because no one -who is just reading the data has the ability to affect anyone else’s reading of -the data. +Whew! We *also* cannot have a mutable reference while we have an immutable one +to the same value. + + +Users of an immutable reference don’t expect the value to suddenly change out +from under them! However, multiple immutable references are allowed because no +one who is just reading the data has the ability to affect anyone else’s +reading of the data. Note that a reference’s scope starts from where it is introduced and continues through the last time that reference is used. For instance, this code will @@ -807,22 +817,22 @@ compile because the last usage of the immutable references, the `println!`, occurs before the mutable reference is introduced: ``` - let mut s = String::from("hello"); +let mut s = String::from("hello"); - let r1 = &s; // no problem - let r2 = &s; // no problem - println!("{} and {}", r1, r2); - // variables r1 and r2 will not be used after this point +let r1 = &s; // no problem +let r2 = &s; // no problem +println!("{} and {}", r1, r2); +// variables r1 and r2 will not be used after this point - let r3 = &mut s; // no problem - println!("{}", r3); +let r3 = &mut s; // no problem +println!("{}", r3); ``` The scopes of the immutable references `r1` and `r2` end after the `println!` where they are last used, which is before the mutable reference `r3` is created. These scopes don’t overlap, so this code is allowed. The ability of the compiler to tell that a reference is no longer being used at a point before -the end of the scope is called Non-Lexical Lifetimes (NLL for short), and you +the end of the scope is called *Non-Lexical Lifetimes* (NLL for short), and you can read more about it in The Edition Guide at *https://doc.rust-lang.org/edition-guide/rust-2018/ownership-and-lifetimes/non-lexical-lifetimes.html*. @@ -834,14 +844,14 @@ have to track down why your data isn’t what you thought it was. ### Dangling References In languages with pointers, it’s easy to erroneously create a *dangling -pointer*, a pointer that references a location in memory that may have been -given to someone else, by freeing some memory while preserving a pointer to +pointer*--a pointer that references a location in memory that may have been +given to someone else--by freeing some memory while preserving a pointer to that memory. In Rust, by contrast, the compiler guarantees that references will never be dangling references: if you have a reference to some data, the compiler will ensure that the data will not go out of scope before the reference to the data does. -Let’s try to create a dangling reference, which Rust will prevent with a +Let’s try to create a dangling reference to see how Rust prevents them with a compile-time error: Filename: src/main.rs @@ -861,8 +871,6 @@ fn dangle() -> &String { Here’s the error: ``` -$ cargo run - Compiling ownership v0.1.0 (file:///projects/ownership) error[E0106]: missing lifetime specifier --> src/main.rs:5:16 | @@ -882,7 +890,7 @@ about lifetimes, the message does contain the key to why this code is a problem: ``` this function's return type contains a borrowed value, but there is no value -for it to be borrowed from. +for it to be borrowed from ``` Let’s take a closer look at exactly what’s happening at each stage of our @@ -930,39 +938,40 @@ Next, we’ll look at a different kind of reference: slices. ## The Slice Type -Another data type that does not have ownership is the *slice*. Slices let you -reference a contiguous sequence of elements in a collection rather than the -whole collection. +*Slices* let you reference a contiguous sequence of elements in a collection +rather than the whole collection. A slice is a kind of reference, so it does +not have ownership. Here’s a small programming problem: write a function that takes a string and returns the first word it finds in that string. If the function doesn’t find a space in the string, the whole string must be one word, so the entire string should be returned. -Let’s think about the signature of this function: +Let’s work through how we’d write the signature of this function without using +slices, to understand the problem that slices will solve: ``` fn first_word(s: &String) -> ? ``` -This function, `first_word`, has a `&String` as a parameter. We don’t want +The `first_word` function has a `&String` as a parameter. We don’t want ownership, so this is fine. But what should we return? We don’t really have a way to talk about *part* of a string. However, we could return the index of the -end of the word. Let’s try that, as shown in Listing 4-7. +end of the word, indicated by a space. Let’s try that, as shown in Listing 4-7. Filename: src/main.rs ``` fn first_word(s: &String) -> usize { - let bytes = s.as_bytes(); + [1] let bytes = s.as_bytes(); - for (i, &item) in bytes.iter().enumerate() { - if item == b' ' { + for (i, &item)[2] in bytes.iter()[3].enumerate() { + [4] if item == b' ' { return i; } } - s.len() + [5] s.len() } ``` @@ -971,18 +980,14 @@ Listing 4-7: The `first_word` function that returns a byte index value into the Because we need to go through the `String` element by element and check whether a value is a space, we’ll convert our `String` to an array of bytes using the -`as_bytes` method: - -``` - let bytes = s.as_bytes(); -``` - -Next, we create an iterator over the array of bytes using the `iter` method: - -``` - for (i, &item) in bytes.iter().enumerate() { -``` - +`as_bytes` method [1]. + + +Next, we create an iterator over the array of bytes using the `iter` method [3]. We’ll discuss iterators in more detail in Chapter 13. For now, know that `iter` is a method that returns each element in a collection and that `enumerate` wraps the result of `iter` and returns each element as part of a tuple instead. @@ -991,23 +996,14 @@ second element is a reference to the element. This is a bit more convenient than calculating the index ourselves. Because the `enumerate` method returns a tuple, we can use patterns to -destructure that tuple. We'll be discussing patterns more in Chapter 6. So in -the `for` loop, we specify a pattern that has `i` for the index in the tuple -and `&item` for the single byte in the tuple. Because we get a reference to the +destructure that tuple. We’ll be discussing patterns more in Chapter 6. In the +`for` loop, we specify a pattern that has `i` for the index in the tuple and +`&item` for the single byte in the tuple [2]. Because we get a reference to the element from `.iter().enumerate()`, we use `&` in the pattern. Inside the `for` loop, we search for the byte that represents the space by -using the byte literal syntax. If we find a space, we return the position. -Otherwise, we return the length of the string by using `s.len()`: - -``` - if item == b' ' { - return i; - } - } - - s.len() -``` +using the byte literal syntax [4]. If we find a space, we return the position. +Otherwise, we return the length of the string by using `s.len()` [5]. We now have a way to find out the index of the end of the first word in the string, but there’s a problem. We’re returning a `usize` on its own, but it’s @@ -1050,7 +1046,7 @@ fn second_word(s: &String) -> (usize, usize) { Now we’re tracking a starting *and* an ending index, and we have even more values that were calculated from data in a particular state but aren’t tied to -that state at all. We now have three unrelated variables floating around that +that state at all. We have three unrelated variables floating around that need to be kept in sync. Luckily, Rust has a solution to this problem: string slices. @@ -1066,18 +1062,15 @@ A *string slice* is a reference to part of a `String`, and it looks like this: let world = &s[6..11]; ``` -This is similar to taking a reference to the whole `String` but with the extra -`[0..5]` bit. Rather than a reference to the entire `String`, it’s a reference -to a portion of the `String`. - -We can create slices using a range within brackets by specifying -`[starting_index..ending_index]`, where `starting_index` is the first position -in the slice and `ending_index` is one more than the last position in the -slice. Internally, the slice data structure stores the starting position and -the length of the slice, which corresponds to `ending_index` minus -`starting_index`. So in the case of `let world = &s[6..11];`, `world` would be -a slice that contains a pointer to the byte at index 6 of `s` with a length -value of 5. +Rather than a reference to the entire `String`, `hello` is a reference to a +portion of the `String`, specified in the extra `[0..5]` bit. We create slices +using a range within brackets by specifying `[starting_index..ending_index]`, +where `starting_index` is the first position in the slice and `ending_index` is +one more than the last position in the slice. Internally, the slice data +structure stores the starting position and the length of the slice, which +corresponds to `ending_index` minus `starting_index`. So in the case of `let +world = &s[6..11];`, `world` would be a slice that contains a pointer to the +byte at index 6 of `s` with a length value of 5. Figure 4-6 shows this in a diagram. @@ -1187,9 +1180,8 @@ fn main() { Here’s the compiler error: ``` -$ cargo run - Compiling ownership v0.1.0 (file:///projects/ownership) -error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immutable +error[E0502]: cannot borrow `s` as mutable because it is also borrowed as +immutable --> src/main.rs:18:5 | 16 | let word = first_word(&s); diff --git a/src/doc/book/nostarch/chapter08.md b/src/doc/book/nostarch/chapter08.md new file mode 100644 index 0000000000..ed37b3c41e --- /dev/null +++ b/src/doc/book/nostarch/chapter08.md @@ -0,0 +1,1063 @@ + +[TOC] + +# Common Collections + +Rust’s standard library includes a number of very useful data structures called +*collections*. Most other data types represent one specific value, but +collections can contain multiple values. Unlike the built-in array and tuple +types, the data these collections point to is stored on the heap, which means +the amount of data does not need to be known at compile time and can grow or +shrink as the program runs. Each kind of collection has different capabilities +and costs, and choosing an appropriate one for your current situation is a +skill you’ll develop over time. In this chapter, we’ll discuss three +collections that are used very often in Rust programs: + +* A *vector* allows you to store a variable number of values next to each other. +* A *string* is a collection of characters. We’ve mentioned the `String` type + previously, but in this chapter we’ll talk about it in depth. +* A *hash map* allows you to associate a value with a particular key. It’s a + particular implementation of the more general data structure called a *map*. + +To learn about the other kinds of collections provided by the standard library, +see the documentation at *https://doc.rust-lang.org/std/collections/index.html*. + +We’ll discuss how to create and update vectors, strings, and hash maps, as well +as what makes each special. + +## Storing Lists of Values with Vectors + +The first collection type we’ll look at is `Vec`, also known as a *vector*. +Vectors allow you to store more than one value in a single data structure that +puts all the values next to each other in memory. Vectors can only store values +of the same type. They are useful when you have a list of items, such as the +lines of text in a file or the prices of items in a shopping cart. + +### Creating a New Vector + +To create a new, empty vector, we can call the `Vec::new` function, as shown in +Listing 8-1. + +``` +let v: Vec = Vec::new(); +``` + +Listing 8-1: Creating a new, empty vector to hold values of type `i32` + +Note that we added a type annotation here. Because we aren’t inserting any +values into this vector, Rust doesn’t know what kind of elements we intend to +store. This is an important point. Vectors are implemented using generics; +we’ll cover how to use generics with your own types in Chapter 10. For now, +know that the `Vec` type provided by the standard library can hold any type, +and when a specific vector holds a specific type, the type is specified within +angle brackets. In Listing 8-1, we’ve told Rust that the `Vec` in `v` will +hold elements of the `i32` type. + +In more realistic code, Rust can often infer the type of value you want to +store once you insert values, so you rarely need to do this type annotation. +It’s more common to create a `Vec` that has initial values, and Rust +provides the `vec!` macro for convenience. The macro will create a new vector +that holds the values you give it. Listing 8-2 creates a new `Vec` that +holds the values `1`, `2`, and `3`. The integer type is `i32` because that’s +the default integer type, as we discussed in the “Data Types” section of Chapter 3. + +``` +let v = vec![1, 2, 3]; +``` + +Listing 8-2: Creating a new vector containing values + +Because we’ve given initial `i32` values, Rust can infer that the type of `v` +is `Vec`, and the type annotation isn’t necessary. Next, we’ll look at how +to modify a vector. + +### Updating a Vector + +To create a vector and then add elements to it, we can use the `push` method, +as shown in Listing 8-3. + +``` +let mut v = Vec::new(); + +v.push(5); +v.push(6); +v.push(7); +v.push(8); +``` + +Listing 8-3: Using the `push` method to add values to a vector + +As with any variable, if we want to be able to change its value, we need to +make it mutable using the `mut` keyword, as discussed in Chapter 3. The numbers +we place inside are all of type `i32`, and Rust infers this from the data, so +we don’t need the `Vec` annotation. + +### Dropping a Vector Drops Its Elements + +Like any other `struct`, a vector is freed when it goes out of scope, as +annotated in Listing 8-4. + +``` +{ + let v = vec![1, 2, 3, 4]; + + // do stuff with v +} // <- v goes out of scope and is freed here +``` + +Listing 8-4: Showing where the vector and its elements are dropped + +When the vector gets dropped, all of its contents are also dropped, meaning +those integers it holds will be cleaned up. This may seem like a +straightforward point but can get a bit more complicated when you start to +introduce references to the elements of the vector. Let’s tackle that next! + +### Reading Elements of Vectors + +Now that you know how to create, update, and destroy vectors, knowing how to +read their contents is a good next step. There are two ways to reference a +value stored in a vector. In the examples, we’ve annotated the types of the +values that are returned from these functions for extra clarity. + +Listing 8-5 shows both methods of accessing a value in a vector, either with +indexing syntax or the `get` method. + +``` +let v = vec![1, 2, 3, 4, 5]; + +let third: &i32 = &v[2]; +println!("The third element is {}", third); + +match v.get(2) { + Some(third) => println!("The third element is {}", third), + None => println!("There is no third element."), +} +``` + +Listing 8-5: Using indexing syntax or the `get` method to access an item in a +vector + +Note two details here. First, we use the index value of `2` to get the third +element: vectors are indexed by number, starting at zero. Second, the two ways +to get the third element are by using `&` and `[]`, which gives us a reference, +or by using the `get` method with the index passed as an argument, which gives +us an `Option<&T>`. + +Rust has two ways to reference an element so you can choose how the program +behaves when you try to use an index value that the vector doesn’t have an +element for. As an example, let’s see what a program will do if it has a vector +that holds five elements and then tries to access an element at index 100, as +shown in Listing 8-6. + +``` +let v = vec![1, 2, 3, 4, 5]; + +let does_not_exist = &v[100]; +let does_not_exist = v.get(100); +``` + +Listing 8-6: Attempting to access the element at index 100 in a vector +containing five elements + +When we run this code, the first `[]` method will cause the program to panic +because it references a nonexistent element. This method is best used when you +want your program to crash if there’s an attempt to access an element past the +end of the vector. + +When the `get` method is passed an index that is outside the vector, it returns +`None` without panicking. You would use this method if accessing an element +beyond the range of the vector happens occasionally under normal circumstances. +Your code will then have logic to handle having either `Some(&element)` or +`None`, as discussed in Chapter 6. For example, the index could be coming from +a person entering a number. If they accidentally enter a number that’s too +large and the program gets a `None` value, you could tell the user how many +items are in the current vector and give them another chance to enter a valid +value. That would be more user-friendly than crashing the program due to a typo! + +When the program has a valid reference, the borrow checker enforces the +ownership and borrowing rules (covered in Chapter 4) to ensure this reference +and any other references to the contents of the vector remain valid. Recall the +rule that states you can’t have mutable and immutable references in the same +scope. That rule applies in Listing 8-7, where we hold an immutable reference to +the first element in a vector and try to add an element to the end, which won’t +work if we also try to refer to that element later in the function: + +``` +let mut v = vec![1, 2, 3, 4, 5]; + +let first = &v[0]; + +v.push(6); + +println!("The first element is: {}", first); +``` + +Listing 8-7: Attempting to add an element to a vector while holding a reference +to an item + +Compiling this code will result in this error: + +``` + --> src/main.rs:6:5 + | +4 | let first = &v[0]; + | - immutable borrow occurs here +5 | +6 | v.push(6); + | ^^^^^^^^^ mutable borrow occurs here +7 | +8 | println!("The first element is: {}", first); + | ----- immutable borrow later used here +``` + +The code in Listing 8-7 might look like it should work: why should a reference +to the first element care about what changes at the end of the vector? This +error is due to the way vectors work: adding a new element onto the end of the +vector might require allocating new memory and copying the old elements to the +new space, if there isn’t enough room to put all the elements next to each +other where the vector currently is. In that case, the reference to the first +element would be pointing to deallocated memory. The borrowing rules prevent +programs from ending up in that situation. + +> Note: For more on the implementation details of the `Vec` type, see “The +> Rustonomicon” at *https://doc.rust-lang.org/nomicon/vec/vec.html*. + +### Iterating over the Values in a Vector + +If we want to access each element in a vector in turn, we can iterate through +all of the elements rather than use indices to access one at a time. Listing +8-8 shows how to use a `for` loop to get immutable references to each element +in a vector of `i32` values and print them. + +``` +let v = vec![100, 32, 57]; +for i in &v { + println!("{}", i); +} +``` + +Listing 8-8: Printing each element in a vector by iterating over the elements +using a `for` loop + +We can also iterate over mutable references to each element in a mutable vector +in order to make changes to all the elements. The `for` loop in Listing 8-9 +will add `50` to each element. + +``` +let mut v = vec![100, 32, 57]; +for i in &mut v { + *i += 50; +} +``` + +Listing 8-9: Iterating over mutable references to elements in a vector + +To change the value that the mutable reference refers to, we have to use the +dereference operator (`*`) to get to the value in `i` before we can use the +`+=` operator. We’ll talk more about the dereference operator in the +“Following the Pointer to the Value with the Dereference Operator” +section of Chapter 15. + +### Using an Enum to Store Multiple Types + +At the beginning of this chapter, we said that vectors can only store values +that are the same type. This can be inconvenient; there are definitely use +cases for needing to store a list of items of different types. Fortunately, the +variants of an enum are defined under the same enum type, so when we need to +store elements of a different type in a vector, we can define and use an enum! + +For example, say we want to get values from a row in a spreadsheet in which +some of the columns in the row contain integers, some floating-point numbers, +and some strings. We can define an enum whose variants will hold the different +value types, and then all the enum variants will be considered the same type: +that of the enum. Then we can create a vector that holds that enum and so, +ultimately, holds different types. We’ve demonstrated this in Listing 8-10. + +``` +enum SpreadsheetCell { + Int(i32), + Float(f64), + Text(String), +} + +let row = vec![ + SpreadsheetCell::Int(3), + SpreadsheetCell::Text(String::from("blue")), + SpreadsheetCell::Float(10.12), +]; +``` + +Listing 8-10: Defining an `enum` to store values of different types in one +vector + +Rust needs to know what types will be in the vector at compile time so it knows +exactly how much memory on the heap will be needed to store each element. A +secondary advantage is that we can be explicit about what types are allowed in +this vector. If Rust allowed a vector to hold any type, there would be a chance +that one or more of the types would cause errors with the operations performed +on the elements of the vector. Using an enum plus a `match` expression means +that Rust will ensure at compile time that every possible case is handled, as +discussed in Chapter 6. + +When you’re writing a program, if you don’t know the exhaustive set of types +the program will get at runtime to store in a vector, the enum technique won’t +work. Instead, you can use a trait object, which we’ll cover in Chapter 17. + +Now that we’ve discussed some of the most common ways to use vectors, be sure +to review the API documentation for all the many useful methods defined on +`Vec` by the standard library. For example, in addition to `push`, a `pop` +method removes and returns the last element. Let’s move on to the next +collection type: `String`! + +## Storing UTF-8 Encoded Text with Strings + +We talked about strings in Chapter 4, but we’ll look at them in more depth now. +New Rustaceans commonly get stuck on strings for a combination of three +reasons: Rust’s propensity for exposing possible errors, strings being a more +complicated data structure than many programmers give them credit for, and +UTF-8. These factors combine in a way that can seem difficult when you’re +coming from other programming languages. + +It’s useful to discuss strings in the context of collections because strings +are implemented as a collection of bytes, plus some methods to provide useful +functionality when those bytes are interpreted as text. In this section, we’ll +talk about the operations on `String` that every collection type has, such as +creating, updating, and reading. We’ll also discuss the ways in which `String` +is different from the other collections, namely how indexing into a `String` is +complicated by the differences between how people and computers interpret +`String` data. + +### What Is a String? + +We’ll first define what we mean by the term *string*. Rust has only one string +type in the core language, which is the string slice `str` that is usually seen +in its borrowed form `&str`. In Chapter 4, we talked about *string slices*, +which are references to some UTF-8 encoded string data stored elsewhere. String +literals, for example, are stored in the program’s binary and are therefore +string slices. + +The `String` type, which is provided by Rust’s standard library rather than +coded into the core language, is a growable, mutable, owned, UTF-8 encoded +string type. When Rustaceans refer to “strings” in Rust, they usually mean the +`String` and the string slice `&str` types, not just one of those types. +Although this section is largely about `String`, both types are used heavily in +Rust’s standard library, and both `String` and string slices are UTF-8 encoded. + +Rust’s standard library also includes a number of other string types, such as +`OsString`, `OsStr`, `CString`, and `CStr`. Library crates can provide even +more options for storing string data. See how those names all end in `String` +or `Str`? They refer to owned and borrowed variants, just like the `String` and +`str` types you’ve seen previously. These string types can store text in +different encodings or be represented in memory in a different way, for +example. We won’t discuss these other string types in this chapter; see their +API documentation for more about how to use them and when each is appropriate. + +### Creating a New String + +Many of the same operations available with `Vec` are available with `String` +as well, starting with the `new` function to create a string, shown in Listing +8-11. + +``` +let mut s = String::new(); +``` + +Listing 8-11: Creating a new, empty `String` + +This line creates a new empty string called `s`, which we can then load data +into. Often, we’ll have some initial data that we want to start the string +with. For that, we use the `to_string` method, which is available on any type +that implements the `Display` trait, as string literals do. Listing 8-12 shows +two examples. + +``` +let data = "initial contents"; + +let s = data.to_string(); + +// the method also works on a literal directly: +let s = "initial contents".to_string(); +``` + +Listing 8-12: Using the `to_string` method to create a `String` from a string +literal + +This code creates a string containing `initial contents`. + +We can also use the function `String::from` to create a `String` from a string +literal. The code in Listing 8-13 is equivalent to the code from Listing 8-12 +that uses `to_string`. + +``` +let s = String::from("initial contents"); +``` + +Listing 8-13: Using the `String::from` function to create a `String` from a +string literal + +Because strings are used for so many things, we can use many different generic +APIs for strings, providing us with a lot of options. Some of them can seem +redundant, but they all have their place! In this case, `String::from` and +`to_string` do the same thing, so which you choose is a matter of style. + +Remember that strings are UTF-8 encoded, so we can include any properly encoded +data in them, as shown in Listing 8-14. + +``` +let hello = String::from("السلام عليكم"); +let hello = String::from("Dobrý den"); +let hello = String::from("Hello"); +let hello = String::from("שָׁלוֹם"); +let hello = String::from("नमस्ते"); +let hello = String::from("こんにちは"); +let hello = String::from("안녕하세요"); +let hello = String::from("你好"); +let hello = String::from("Olá"); +let hello = String::from("Здравствуйте"); +let hello = String::from("Hola"); +``` + +Listing 8-14: Storing greetings in different languages in strings + +All of these are valid `String` values. + +### Updating a String + +A `String` can grow in size and its contents can change, just like the contents +of a `Vec`, if you push more data into it. In addition, you can conveniently +use the `+` operator or the `format!` macro to concatenate `String` values. + +#### Appending to a String with `push_str` and `push` + +We can grow a `String` by using the `push_str` method to append a string slice, +as shown in Listing 8-15. + +``` +let mut s = String::from("foo"); +s.push_str("bar"); +``` + +Listing 8-15: Appending a string slice to a `String` using the `push_str` method + +After these two lines, `s` will contain `foobar`. The `push_str` method takes a +string slice because we don’t necessarily want to take ownership of the +parameter. For example, the code in Listing 8-16 shows that it would be +unfortunate if we weren’t able to use `s2` after appending its contents to `s1`. + +``` +let mut s1 = String::from("foo"); +let s2 = "bar"; +s1.push_str(s2); +println!("s2 is {}", s2); +``` + +Listing 8-16: Using a string slice after appending its contents to a `String` + +If the `push_str` method took ownership of `s2`, we wouldn’t be able to print +its value on the last line. However, this code works as we’d expect! + +The `push` method takes a single character as a parameter and adds it to the +`String`. Listing 8-17 shows code that adds the letter "l" to a `String` using +the `push` method. + +``` +let mut s = String::from("lo"); +s.push('l'); +``` + +Listing 8-17: Adding one character to a `String` value using `push` + +As a result of this code, `s` will contain `lol`. + +#### Concatenation with the `+` Operator or the `format!` Macro + +Often, you’ll want to combine two existing strings. One way is to use the `+` +operator, as shown in Listing 8-18. + +``` +let s1 = String::from("Hello, "); +let s2 = String::from("world!"); +let s3 = s1 + &s2; // note s1 has been moved here and can no longer be used +``` + +Listing 8-18: Using the `+` operator to combine two `String` values into a new +`String` value + +The string `s3` will contain `Hello, world!` as a result of this code. The +reason `s1` is no longer valid after the addition and the reason we used a +reference to `s2` has to do with the signature of the method that gets called +when we use the `+` operator. The `+` operator uses the `add` method, whose +signature looks something like this: + +``` +fn add(self, s: &str) -> String { +``` + +This isn’t the exact signature that’s in the standard library: in the standard +library, `add` is defined using generics. Here, we’re looking at the signature +of `add` with concrete types substituted for the generic ones, which is what +happens when we call this method with `String` values. We’ll discuss generics +in Chapter 10. This signature gives us the clues we need to understand the +tricky bits of the `+` operator. + +First, `s2` has an `&`, meaning that we’re adding a *reference* of the second +string to the first string because of the `s` parameter in the `add` function: +we can only add a `&str` to a `String`; we can’t add two `String` values +together. But wait—the type of `&s2` is `&String`, not `&str`, as specified in +the second parameter to `add`. So why does Listing 8-18 compile? + +The reason we’re able to use `&s2` in the call to `add` is that the compiler +can *coerce* the `&String` argument into a `&str`. When we call the `add` +method, Rust uses a *deref coercion*, which here turns `&s2` into `&s2[..]`. +We’ll discuss deref coercion in more depth in Chapter 15. Because `add` does +not take ownership of the `s` parameter, `s2` will still be a valid `String` +after this operation. + +Second, we can see in the signature that `add` takes ownership of `self`, +because `self` does *not* have an `&`. This means `s1` in Listing 8-18 will be +moved into the `add` call and no longer be valid after that. So although `let +s3 = s1 + &s2;` looks like it will copy both strings and create a new one, this +statement actually takes ownership of `s1`, appends a copy of the contents of +`s2`, and then returns ownership of the result. In other words, it looks like +it’s making a lot of copies but isn’t; the implementation is more efficient +than copying. + +If we need to concatenate multiple strings, the behavior of the `+` operator +gets unwieldy: + +``` +let s1 = String::from("tic"); +let s2 = String::from("tac"); +let s3 = String::from("toe"); + +let s = s1 + "-" + &s2 + "-" + &s3; +``` + +At this point, `s` will be `tic-tac-toe`. With all of the `+` and `"` +characters, it’s difficult to see what’s going on. For more complicated string +combining, we can use the `format!` macro: + +``` +let s1 = String::from("tic"); +let s2 = String::from("tac"); +let s3 = String::from("toe"); + +let s = format!("{}-{}-{}", s1, s2, s3); +``` + +This code also sets `s` to `tic-tac-toe`. The `format!` macro works in the same +way as `println!`, but instead of printing the output to the screen, it returns +a `String` with the contents. The version of the code using `format!` is much +easier to read, and the code generated by the `format!` macro uses references +so that this call doesn’t take ownership of any of its parameters. + +### Indexing into Strings + +In many other programming languages, accessing individual characters in a +string by referencing them by index is a valid and common operation. However, +if you try to access parts of a `String` using indexing syntax in Rust, you’ll +get an error. Consider the invalid code in Listing 8-19. + +``` +let s1 = String::from("hello"); +let h = s1[0]; +``` + +Listing 8-19: Attempting to use indexing syntax with a String + +This code will result in the following error: + +``` +error[E0277]: the type `String` cannot be indexed by `{integer}` + --> src/main.rs:3:13 + | +3 | let h = s1[0]; + | ^^^^^ `String` cannot be indexed by `{integer}` + | + = help: the trait `Index<{integer}>` is not implemented for `String` +``` + +The error and the note tell the story: Rust strings don’t support indexing. But +why not? To answer that question, we need to discuss how Rust stores strings in +memory. + +#### Internal Representation + +A `String` is a wrapper over a `Vec`. Let’s look at some of our properly +encoded UTF-8 example strings from Listing 8-14. First, this one: + +``` +let hello = String::from("Hola"); +``` + +In this case, `len` will be 4, which means the vector storing the string “Hola” +is 4 bytes long. Each of these letters takes 1 byte when encoded in UTF-8. But +what about the following line? (Note that this string begins with the capital +Cyrillic letter Ze, not the Arabic number 3.) + +``` +let hello = String::from("Здравствуйте"); +``` + +Asked how long the string is, you might say 12. However, Rust’s answer is 24: +that’s the number of bytes it takes to encode “Здравствуйте” in UTF-8, because +each Unicode scalar value in that string takes 2 bytes of storage. Therefore, +an index into the string’s bytes will not always correlate to a valid Unicode +scalar value. To demonstrate, consider this invalid Rust code: + +``` +let hello = "Здравствуйте"; +let answer = &hello[0]; +``` + +What should the value of `answer` be? Should it be `З`, the first letter? When +encoded in UTF-8, the first byte of `З` is `208` and the second is `151`, so +`answer` should in fact be `208`, but `208` is not a valid character on its +own. Returning `208` is likely not what a user would want if they asked for the +first letter of this string; however, that’s the only data that Rust has at +byte index 0. Users generally don’t want the byte value returned, even if the +string contains only Latin letters: if `&"hello"[0]` were valid code that +returned the byte value, it would return `104`, not `h`. To avoid returning an +unexpected value and causing bugs that might not be discovered immediately, +Rust doesn’t compile this code at all and prevents misunderstandings early in +the development process. + +#### Bytes and Scalar Values and Grapheme Clusters! Oh My! + +Another point about UTF-8 is that there are actually three relevant ways to +look at strings from Rust’s perspective: as bytes, scalar values, and grapheme +clusters (the closest thing to what we would call *letters*). + +If we look at the Hindi word “नमस्ते” written in the Devanagari script, it is +stored as a vector of `u8` values that looks like this: + +``` +[224, 164, 168, 224, 164, 174, 224, 164, 184, 224, 165, 141, 224, 164, 164, +224, 165, 135] +``` + +That’s 18 bytes and is how computers ultimately store this data. If we look at +them as Unicode scalar values, which are what Rust’s `char` type is, those +bytes look like this: + +``` +['न', 'म', 'स', '्', 'त', 'े'] +``` + +There are six `char` values here, but the fourth and sixth are not letters: +they’re diacritics that don’t make sense on their own. Finally, if we look at +them as grapheme clusters, we’d get what a person would call the four letters +that make up the Hindi word: + +``` +["न", "म", "स्", "ते"] +``` + +Rust provides different ways of interpreting the raw string data that computers +store so that each program can choose the interpretation it needs, no matter +what human language the data is in. + +A final reason Rust doesn’t allow us to index into a `String` to get a +character is that indexing operations are expected to always take constant time +(O(1)). But it isn’t possible to guarantee that performance with a `String`, +because Rust would have to walk through the contents from the beginning to the +index to determine how many valid characters there were. + +### Slicing Strings + +Indexing into a string is often a bad idea because it’s not clear what the +return type of the string-indexing operation should be: a byte value, a +character, a grapheme cluster, or a string slice. Therefore, Rust asks you to +be more specific if you really need to use indices to create string slices. To +be more specific in your indexing and indicate that you want a string slice, +rather than indexing using `[]` with a single number, you can use `[]` with a +range to create a string slice containing particular bytes: + +``` +let hello = "Здравствуйте"; + +let s = &hello[0..4]; +``` + +Here, `s` will be a `&str` that contains the first 4 bytes of the string. +Earlier, we mentioned that each of these characters was 2 bytes, which means +`s` will be `Зд`. + +What would happen if we used `&hello[0..1]`? The answer: Rust would panic at +runtime in the same way as if an invalid index were accessed in a vector: + +``` +thread 'main' panicked at 'byte index 1 is not a char boundary; it is inside 'З' (bytes 0..2) of `Здравствуйте`', src/main.rs:4:14 +``` + +You should use ranges to create string slices with caution, because doing so +can crash your program. + +### Methods for Iterating Over Strings + +Fortunately, you can access elements in a string in other ways. + +If you need to perform operations on individual Unicode scalar values, the best +way to do so is to use the `chars` method. Calling `chars` on “नमस्ते” separates +out and returns six values of type `char`, and you can iterate over the result +to access each element: + +``` +for c in "नमस्ते".chars() { + println!("{}", c); +} +``` + +This code will print the following: + +``` +न +म +स +् +त +े +``` + +The `bytes` method returns each raw byte, which might be appropriate for your +domain: + +``` +for b in "नमस्ते".bytes() { + println!("{}", b); +} +``` + +This code will print the 18 bytes that make up this `String`: + +``` +224 +164 +// --snip-- +165 +135 +``` + +But be sure to remember that valid Unicode scalar values may be made up of more +than 1 byte. + +Getting grapheme clusters from strings is complex, so this functionality is not +provided by the standard library. Crates are available on crates.io if this is +the functionality you need. + +### Strings Are Not So Simple + +To summarize, strings are complicated. Different programming languages make +different choices about how to present this complexity to the programmer. Rust +has chosen to make the correct handling of `String` data the default behavior +for all Rust programs, which means programmers have to put more thought into +handling UTF-8 data upfront. This trade-off exposes more of the complexity of +strings than is apparent in other programming languages, but it prevents you +from having to handle errors involving non-ASCII characters later in your +development life cycle. + +Let’s switch to something a bit less complex: hash maps! + +## Storing Keys with Associated Values in Hash Maps + +The last of our common collections is the *hash map*. The type `HashMap` +stores a mapping of keys of type `K` to values of type `V`. It does this via a +*hashing function*, which determines how it places these keys and values into +memory. Many programming languages support this kind of data structure, but +they often use a different name, such as hash, map, object, hash table, +dictionary, or associative array, just to name a few. + +Hash maps are useful when you want to look up data not by using an index, as +you can with vectors, but by using a key that can be of any type. For example, +in a game, you could keep track of each team’s score in a hash map in which +each key is a team’s name and the values are each team’s score. Given a team +name, you can retrieve its score. + +We’ll go over the basic API of hash maps in this section, but many more goodies +are hiding in the functions defined on `HashMap` by the standard library. +As always, check the standard library documentation for more information. + +### Creating a New Hash Map + +You can create an empty hash map with `new` and add elements with `insert`. In +Listing 8-20, we’re keeping track of the scores of two teams whose names are +Blue and Yellow. The Blue team starts with 10 points, and the Yellow team +starts with 50. + +``` +use std::collections::HashMap; + +let mut scores = HashMap::new(); + +scores.insert(String::from("Blue"), 10); +scores.insert(String::from("Yellow"), 50); +``` + +Listing 8-20: Creating a new hash map and inserting some keys and values + +Note that we need to first `use` the `HashMap` from the collections portion of +the standard library. Of our three common collections, this one is the least +often used, so it’s not included in the features brought into scope +automatically in the prelude. Hash maps also have less support from the +standard library; there’s no built-in macro to construct them, for example. + +Just like vectors, hash maps store their data on the heap. This `HashMap` has +keys of type `String` and values of type `i32`. Like vectors, hash maps are +homogeneous: all of the keys must have the same type, and all of the values +must have the same type. + +Another way of constructing a hash map is by using iterators and the `collect` +method on a vector of tuples, where each tuple consists of a key and its value. +We’ll be going into more detail about iterators and their associated methods in +the ”Processing a Series of Items with Iterators” section of Chapter +13. The `collect` method gathers data into a number +of collection types, including `HashMap`. For example, if we had the team names +and initial scores in two separate vectors, we could use the `zip` method to +create an iterator of tuples where “Blue” is paired with 10, and so forth. Then +we could use the `collect` method to turn that iterator of tuples into a hash +map, as shown in Listing 8-21. + +``` +use std::collections::HashMap; + +let teams = vec![String::from("Blue"), String::from("Yellow")]; +let initial_scores = vec![10, 50]; + +let mut scores: HashMap<_, _> = + teams.into_iter().zip(initial_scores.into_iter()).collect(); +``` + +Listing 8-21: Creating a hash map from a list of teams and a list of scores + +The type annotation `HashMap<_, _>` is needed here because it’s possible to +`collect` into many different data structures and Rust doesn’t know which you +want unless you specify. For the parameters for the key and value types, +however, we use underscores, and Rust can infer the types that the hash map +contains based on the types of the data in the vectors. In Listing 8-21, the +key type will be `String` and the value type will be `i32`, just as the types +were in Listing 8-20. + +### Hash Maps and Ownership + +For types that implement the `Copy` trait, like `i32`, the values are copied +into the hash map. For owned values like `String`, the values will be moved and +the hash map will be the owner of those values, as demonstrated in Listing 8-22. + +``` +use std::collections::HashMap; + +let field_name = String::from("Favorite color"); +let field_value = String::from("Blue"); + +let mut map = HashMap::new(); +map.insert(field_name, field_value); +// field_name and field_value are invalid at this point, try using them and +// see what compiler error you get! +``` + +Listing 8-22: Showing that keys and values are owned by the hash map once +they’re inserted + +We aren’t able to use the variables `field_name` and `field_value` after +they’ve been moved into the hash map with the call to `insert`. + +If we insert references to values into the hash map, the values won’t be moved +into the hash map. The values that the references point to must be valid for at +least as long as the hash map is valid. We’ll talk more about these issues in +the “Validating References with Lifetimes” section in Chapter 10. + +### Accessing Values in a Hash Map + +We can get a value out of the hash map by providing its key to the `get` +method, as shown in Listing 8-23. + +``` +use std::collections::HashMap; + +let mut scores = HashMap::new(); + +scores.insert(String::from("Blue"), 10); +scores.insert(String::from("Yellow"), 50); + +let team_name = String::from("Blue"); +let score = scores.get(&team_name); +``` + +Listing 8-23: Accessing the score for the Blue team stored in the hash map + +Here, `score` will have the value that’s associated with the Blue team, and the +result will be `Some(&10)`. The result is wrapped in `Some` because `get` +returns an `Option<&V>`; if there’s no value for that key in the hash map, +`get` will return `None`. The program will need to handle the `Option` in one +of the ways that we covered in Chapter 6. + +We can iterate over each key/value pair in a hash map in a similar manner as we +do with vectors, using a `for` loop: + +``` +use std::collections::HashMap; + +let mut scores = HashMap::new(); + +scores.insert(String::from("Blue"), 10); +scores.insert(String::from("Yellow"), 50); + +for (key, value) in &scores { + println!("{}: {}", key, value); +} +``` + +This code will print each pair in an arbitrary order: + +``` +Yellow: 50 +Blue: 10 +``` + +### Updating a Hash Map + +Although the number of keys and values is growable, each key can only have one +value associated with it at a time. When you want to change the data in a hash +map, you have to decide how to handle the case when a key already has a value +assigned. You could replace the old value with the new value, completely +disregarding the old value. You could keep the old value and ignore the new +value, only adding the new value if the key *doesn’t* already have a value. Or +you could combine the old value and the new value. Let’s look at how to do each +of these! + +#### Overwriting a Value + +If we insert a key and a value into a hash map and then insert that same key +with a different value, the value associated with that key will be replaced. +Even though the code in Listing 8-24 calls `insert` twice, the hash map will +only contain one key/value pair because we’re inserting the value for the Blue +team’s key both times. + +``` +use std::collections::HashMap; + +let mut scores = HashMap::new(); + +scores.insert(String::from("Blue"), 10); +scores.insert(String::from("Blue"), 25); + +println!("{:?}", scores); +``` + +Listing 8-24: Replacing a value stored with a particular key + +This code will print `{"Blue": 25}`. The original value of `10` has been +overwritten. + +#### Only Inserting a Value If the Key Has No Value + +It’s common to check whether a particular key has a value and, if it doesn’t, +insert a value for it. Hash maps have a special API for this called `entry` +that takes the key you want to check as a parameter. The return value of the +`entry` method is an enum called `Entry` that represents a value that might or +might not exist. Let’s say we want to check whether the key for the Yellow team +has a value associated with it. If it doesn’t, we want to insert the value 50, +and the same for the Blue team. Using the `entry` API, the code looks like +Listing 8-25. + +``` +use std::collections::HashMap; + +let mut scores = HashMap::new(); +scores.insert(String::from("Blue"), 10); + +scores.entry(String::from("Yellow")).or_insert(50); +scores.entry(String::from("Blue")).or_insert(50); + +println!("{:?}", scores); +``` + +Listing 8-25: Using the `entry` method to only insert if the key does not +already have a value + +The `or_insert` method on `Entry` is defined to return a mutable reference to +the value for the corresponding `Entry` key if that key exists, and if not, +inserts the parameter as the new value for this key and returns a mutable +reference to the new value. This technique is much cleaner than writing the +logic ourselves and, in addition, plays more nicely with the borrow checker. + +Running the code in Listing 8-25 will print `{"Yellow": 50, "Blue": 10}`. The +first call to `entry` will insert the key for the Yellow team with the value +50 because the Yellow team doesn’t have a value already. The second call to +`entry` will not change the hash map because the Blue team already has the +value 10. + +#### Updating a Value Based on the Old Value + +Another common use case for hash maps is to look up a key’s value and then +update it based on the old value. For instance, Listing 8-26 shows code that +counts how many times each word appears in some text. We use a hash map with +the words as keys and increment the value to keep track of how many times we’ve +seen that word. If it’s the first time we’ve seen a word, we’ll first insert +the value 0. + +``` +use std::collections::HashMap; + +let text = "hello world wonderful world"; + +let mut map = HashMap::new(); + +for word in text.split_whitespace() { + let count = map.entry(word).or_insert(0); + *count += 1; +} + +println!("{:?}", map); +``` + +Listing 8-26: Counting occurrences of words using a hash map that stores words +and counts + +This code will print `{"world": 2, "hello": 1, "wonderful": 1}`. The +`split_whitespace` method iterates over sub-slices, separated by whitespace, of +the value in `text`. The `or_insert` method returns a mutable reference (`&mut +V`) to the value for the specified key. Here we store that mutable reference in +the `count` variable, so in order to assign to that value, we must first +dereference `count` using the asterisk (`*`). The mutable reference goes out of +scope at the end of the `for` loop, so all of these changes are safe and +allowed by the borrowing rules. + +### Hashing Functions + +By default, `HashMap` uses a hashing function called SipHash that can provide +resistance to Denial of Service (DoS) attacks involving hash tables. This is +not the fastest hashing algorithm available, but the trade-off for better +security that comes with the drop in performance is worth it. If you profile +your code and find that the default hash function is too slow for your +purposes, you can switch to another function by specifying a different +*hasher*. A hasher is a type that implements the `BuildHasher` trait. We’ll +talk about traits and how to implement them in Chapter 10. You don’t +necessarily have to implement your own hasher from scratch; crates.io has +libraries shared by other Rust users that provide hashers implementing many +common hashing algorithms. + +## Summary + +Vectors, strings, and hash maps will provide a large amount of functionality +necessary in programs when you need to store, access, and modify data. Here are +some exercises you should now be equipped to solve: + +* Given a list of integers, use a vector and return the median (when sorted, + the value in the middle position) and mode (the value that occurs most often; + a hash map will be helpful here) of the list. +* Convert strings to pig latin. The first consonant of each word is moved to + the end of the word and “ay” is added, so “first” becomes “irst-fay.” Words + that start with a vowel have “hay” added to the end instead (“apple” becomes + “apple-hay”). Keep in mind the details about UTF-8 encoding! +* Using a hash map and vectors, create a text interface to allow a user to add + employee names to a department in a company. For example, “Add Sally to + Engineering” or “Add Amir to Sales.” Then let the user retrieve a list of all + people in a department or all people in the company by department, sorted + alphabetically. + +The standard library API documentation describes methods that vectors, strings, +and hash maps have that will be helpful for these exercises! + +We’re getting into more complex programs in which operations can fail, so, it’s +a perfect time to discuss error handling. We’ll do that next! diff --git a/src/doc/book/nostarch/chapter09.md b/src/doc/book/nostarch/chapter09.md new file mode 100644 index 0000000000..c3c4e057ba --- /dev/null +++ b/src/doc/book/nostarch/chapter09.md @@ -0,0 +1,1042 @@ + +[TOC] + +# Error Handling + +Rust’s commitment to reliability extends to error handling. Errors are a fact +of life in software, so Rust has a number of features for handling situations +in which something goes wrong. In many cases, Rust requires you to acknowledge +the possibility of an error and take some action before your code will compile. +This requirement makes your program more robust by ensuring that you’ll +discover errors and handle them appropriately before you’ve deployed your code +to production! + +Rust groups errors into two major categories: *recoverable* and *unrecoverable* +errors. For a recoverable error, such as a file not found error, it’s +reasonable to report the problem to the user and retry the operation. +Unrecoverable errors are always symptoms of bugs, like trying to access a +location beyond the end of an array. + +Most languages don’t distinguish between these two kinds of errors and handle +both in the same way, using mechanisms such as exceptions. Rust doesn’t have +exceptions. Instead, it has the type `Result` for recoverable errors and +the `panic!` macro that stops execution when the program encounters an +unrecoverable error. This chapter covers calling `panic!` first and then talks +about returning `Result` values. Additionally, we’ll explore +considerations when deciding whether to try to recover from an error or to stop +execution. + +## Unrecoverable Errors with `panic!` + +Sometimes, bad things happen in your code, and there’s nothing you can do about +it. In these cases, Rust has the `panic!` macro. When the `panic!` macro +executes, your program will print a failure message, unwind and clean up the +stack, and then quit. This most commonly occurs when a bug of some kind has +been detected and it’s not clear to the programmer how to handle the error. + +> ### Unwinding the Stack or Aborting in Response to a Panic +> +> By default, when a panic occurs, the program starts *unwinding*, which +> means Rust walks back up the stack and cleans up the data from each function +> it encounters. But this walking back and cleanup is a lot of work. The +> alternative is to immediately *abort*, which ends the program without +> cleaning up. Memory that the program was using will then need to be cleaned +> up by the operating system. If in your project you need to make the resulting +> binary as small as possible, you can switch from unwinding to aborting upon a +> panic by adding `panic = 'abort'` to the appropriate `[profile]` sections in +> your *Cargo.toml* file. For example, if you want to abort on panic in release +> mode, add this: +> +> ```toml +> profile.release +> panic = 'abort' +> ``` + +Let’s try calling `panic!` in a simple program: + +Filename: src/main.rs + +``` +fn main() { + panic!("crash and burn"); +} +``` + +When you run the program, you’ll see something like this: + +``` +thread 'main' panicked at 'crash and burn', src/main.rs:2:5 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +``` + +The call to `panic!` causes the error message contained in the last two lines. +The first line shows our panic message and the place in our source code where +the panic occurred: *src/main.rs:2:5* indicates that it’s the second line, +fifth character of our *src/main.rs* file. + +In this case, the line indicated is part of our code, and if we go to that +line, we see the `panic!` macro call. In other cases, the `panic!` call might +be in code that our code calls, and the filename and line number reported by +the error message will be someone else’s code where the `panic!` macro is +called, not the line of our code that eventually led to the `panic!` call. We +can use the backtrace of the functions the `panic!` call came from to figure +out the part of our code that is causing the problem. We’ll discuss what a +backtrace is in more detail next. + +### Using a `panic!` Backtrace + +Let’s look at another example to see what it’s like when a `panic!` call comes +from a library because of a bug in our code instead of from our code calling +the macro directly. Listing 9-1 has some code that attempts to access an +element by index in a vector. + +Filename: src/main.rs + +``` +fn main() { + let v = vec![1, 2, 3]; + + v[99]; +} +``` + +Listing 9-1: Attempting to access an element beyond the end of a vector, which +will cause a call to `panic!` + +Here, we’re attempting to access the 100th element of our vector (which is at +index 99 because indexing starts at zero), but it has only 3 elements. In this +situation, Rust will panic. Using `[]` is supposed to return an element, but if +you pass an invalid index, there’s no element that Rust could return here that +would be correct. + +In C, attempting to read beyond the end of a data structure is undefined +behavior. You might get whatever is at the location in memory that would +correspond to that element in the data structure, even though the memory +doesn’t belong to that structure. This is called a *buffer overread* and can +lead to security vulnerabilities if an attacker is able to manipulate the index +in such a way as to read data they shouldn’t be allowed to that is stored after +the data structure. + +To protect your program from this sort of vulnerability, if you try to read an +element at an index that doesn’t exist, Rust will stop execution and refuse to +continue. Let’s try it and see: + +``` +thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 99', src/main.rs:4:5 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +``` + +This error points at line 4 of our `main.rs` where we attempt to access index +99. The next note line tells us that we can set the `RUST_BACKTRACE` +environment variable to get a backtrace of exactly what happened to cause the +error. A *backtrace* is a list of all the functions that have been called to +get to this point. Backtraces in Rust work as they do in other languages: the +key to reading the backtrace is to start from the top and read until you see +files you wrote. That’s the spot where the problem originated. The lines above +the lines mentioning your files are code that your code called; the lines below +are code that called your code. These lines might include core Rust code, +standard library code, or crates that you’re using. Let’s try getting a +backtrace by setting the `RUST_BACKTRACE` environment variable to any value +except 0. Listing 9-2 shows output similar to what you’ll see. + +``` +$ RUST_BACKTRACE=1 cargo run +thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 99', src/main.rs:4:5 +stack backtrace: + 0: rust_begin_unwind + at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/panicking.rs:483 + 1: core::panicking::panic_fmt + at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/panicking.rs:85 + 2: core::panicking::panic_bounds_check + at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/panicking.rs:62 + 3: >::index + at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/slice/index.rs:255 + 4: core::slice::index:: for [T]>::index + at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/slice/index.rs:15 + 5: as core::ops::index::Index>::index + at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/alloc/src/vec.rs:1982 + 6: panic::main + at ./src/main.rs:4 + 7: core::ops::function::FnOnce::call_once + at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/ops/function.rs:227 +note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. +``` + +Listing 9-2: The backtrace generated by a call to `panic!` displayed when the +environment variable `RUST_BACKTRACE` is set + +That’s a lot of output! The exact output you see might be different depending +on your operating system and Rust version. In order to get backtraces with this +information, debug symbols must be enabled. Debug symbols are enabled by +default when using `cargo build` or `cargo run` without the `--release` flag, +as we have here. + +In the output in Listing 9-2, line 6 of the backtrace points to the line in +our project that’s causing the problem: line 4 of *src/main.rs*. If we don’t +want our program to panic, the location pointed to by the first line mentioning +a file we wrote is where we should start investigating. In Listing 9-1, where +we deliberately wrote code that would panic in order to demonstrate how to use +backtraces, the way to fix the panic is to not request an element at index 99 +from a vector that only contains 3 items. When your code panics in the future, +you’ll need to figure out what action the code is taking with what values to +cause the panic and what the code should do instead. + +We’ll come back to `panic!` and when we should and should not use `panic!` to +handle error conditions in the “To `panic!` or Not to `panic!`” section later +in this chapter. Next, we’ll look at how to recover from an error using +`Result`. + +## Recoverable Errors with `Result` + +Most errors aren’t serious enough to require the program to stop entirely. +Sometimes, when a function fails, it’s for a reason that you can easily +interpret and respond to. For example, if you try to open a file and that +operation fails because the file doesn’t exist, you might want to create the +file instead of terminating the process. + +Recall from “Handling Potential Failure with the `Result` Type” in Chapter 2 +that the `Result` enum is defined as having two variants, `Ok` and `Err`, as +follows: + +``` +enum Result { + Ok(T), + Err(E), +} +``` + +The `T` and `E` are generic type parameters: we’ll discuss generics in more +detail in Chapter 10. What you need to know right now is that `T` represents +the type of the value that will be returned in a success case within the `Ok` +variant, and `E` represents the type of the error that will be returned in a +failure case within the `Err` variant. Because `Result` has these generic type +parameters, we can use the `Result` type and the functions that the standard +library has defined on it in many different situations where the successful +value and error value we want to return may differ. + +Let’s call a function that returns a `Result` value because the function could +fail. In Listing 9-3 we try to open a file. + +Filename: src/main.rs + +``` +use std::fs::File; + +fn main() { + let f = File::open("hello.txt"); +} +``` + +Listing 9-3: Opening a file + +How do we know `File::open` returns a `Result`? We could look at the standard +library API documentation, or we could ask the compiler! If we give `f` a type +annotation that we know is *not* the return type of the function and then try +to compile the code, the compiler will tell us that the types don’t match. The +error message will then tell us what the type of `f` *is*. Let’s try it! We +know that the return type of `File::open` isn’t of type `u32`, so let’s change +the `let f` statement to this: + +``` + let f: u32 = File::open("hello.txt"); +``` + +Attempting to compile now gives us the following output: + +``` +error[E0308]: mismatched types + --> src/main.rs:4:18 + | +4 | let f: u32 = File::open("hello.txt"); + | --- ^^^^^^^^^^^^^^^^^^^^^^^ expected `u32`, found enum `Result` + | | + | expected due to this + | + = note: expected type `u32` + found enum `Result` +``` + +This tells us the return type of the `File::open` function is a `Result`. +The generic parameter `T` has been filled in here with the type of the success +value, `std::fs::File`, which is a file handle. The type of `E` used in the +error value is `std::io::Error`. + +This return type means the call to `File::open` might succeed and return a file +handle that we can read from or write to. The function call also might fail: +for example, the file might not exist, or we might not have permission to +access the file. The `File::open` function needs to have a way to tell us +whether it succeeded or failed and at the same time give us either the file +handle or error information. This information is exactly what the `Result` enum +conveys. + +In the case where `File::open` succeeds, the value in the variable `f` will be +an instance of `Ok` that contains a file handle. In the case where it fails, +the value in `f` will be an instance of `Err` that contains more information +about the kind of error that happened. + +We need to add to the code in Listing 9-3 to take different actions depending +on the value `File::open` returns. Listing 9-4 shows one way to handle the +`Result` using a basic tool, the `match` expression that we discussed in +Chapter 6. + +Filename: src/main.rs + +``` +use std::fs::File; + +fn main() { + let f = File::open("hello.txt"); + + let f = match f { + Ok(file) => file, + Err(error) => panic!("Problem opening the file: {:?}", error), + }; +} +``` + +Listing 9-4: Using a `match` expression to handle the `Result` variants that +might be returned + +Note that, like the `Option` enum, the `Result` enum and its variants have been +brought into scope by the prelude, so we don’t need to specify `Result::` +before the `Ok` and `Err` variants in the `match` arms. + +Here we tell Rust that when the result is `Ok`, return the inner `file` value +out of the `Ok` variant, and we then assign that file handle value to the +variable `f`. After the `match`, we can use the file handle for reading or +writing. + +The other arm of the `match` handles the case where we get an `Err` value from +`File::open`. In this example, we’ve chosen to call the `panic!` macro. If +there’s no file named *hello.txt* in our current directory and we run this +code, we’ll see the following output from the `panic!` macro: + +``` +thread 'main' panicked at 'Problem opening the file: Os { code: 2, kind: NotFound, message: "No such file or directory" }', src/main.rs:8:23 +``` + +As usual, this output tells us exactly what has gone wrong. + +### Matching on Different Errors + +The code in Listing 9-4 will `panic!` no matter why `File::open` failed. What +we want to do instead is take different actions for different failure reasons: +if `File::open` failed because the file doesn’t exist, we want to create the +file and return the handle to the new file. If `File::open` failed for any +other reason—for example, because we didn’t have permission to open the file—we +still want the code to `panic!` in the same way as it did in Listing 9-4. Look +at Listing 9-5, which adds an inner `match` expression. + +Filename: src/main.rs + +``` +use std::fs::File; +use std::io::ErrorKind; + +fn main() { + let f = File::open("hello.txt"); + + let f = match f { + Ok(file) => file, + Err(error) => match error.kind() { + ErrorKind::NotFound => match File::create("hello.txt") { + Ok(fc) => fc, + Err(e) => panic!("Problem creating the file: {:?}", e), + }, + other_error => { + panic!("Problem opening the file: {:?}", other_error) + } + }, + }; +} +``` + +Listing 9-5: Handling different kinds of errors in different ways + +The type of the value that `File::open` returns inside the `Err` variant is +`io::Error`, which is a struct provided by the standard library. This struct +has a method `kind` that we can call to get an `io::ErrorKind` value. The enum +`io::ErrorKind` is provided by the standard library and has variants +representing the different kinds of errors that might result from an `io` +operation. The variant we want to use is `ErrorKind::NotFound`, which indicates +the file we’re trying to open doesn’t exist yet. So we match on `f`, but we +also have an inner match on `error.kind()`. + +The condition we want to check in the inner match is whether the value returned +by `error.kind()` is the `NotFound` variant of the `ErrorKind` enum. If it is, +we try to create the file with `File::create`. However, because `File::create` +could also fail, we need a second arm in the inner `match` expression. When the +file can’t be created, a different error message is printed. The second arm of +the outer `match` stays the same, so the program panics on any error besides +the missing file error. + +That’s a lot of `match`! The `match` expression is very useful but also very +much a primitive. In Chapter 13, you’ll learn about closures; the `Result` type has many methods that accept a closure and are implemented using +`match` expressions. Using those methods will make your code more concise. A +more seasoned Rustacean might write this code instead of Listing 9-5: + +``` +use std::fs::File; +use std::io::ErrorKind; + +fn main() { + let f = File::open("hello.txt").unwrap_or_else(|error| { + if error.kind() == ErrorKind::NotFound { + File::create("hello.txt").unwrap_or_else(|error| { + panic!("Problem creating the file: {:?}", error); + }) + } else { + panic!("Problem opening the file: {:?}", error); + } + }); +} +``` + +Although this code has the same behavior as Listing 9-5, it doesn’t contain any +`match` expressions and is cleaner to read. Come back to this example after +you’ve read Chapter 13, and look up the `unwrap_or_else` method in the standard +library documentation. Many more of these methods can clean up huge nested +`match` expressions when you’re dealing with errors. + +### Shortcuts for Panic on Error: `unwrap` and `expect` + +Using `match` works well enough, but it can be a bit verbose and doesn’t always +communicate intent well. The `Result` type has many helper methods +defined on it to do various tasks. One of those methods, called `unwrap`, is a +shortcut method that is implemented just like the `match` expression we wrote in +Listing 9-4. If the `Result` value is the `Ok` variant, `unwrap` will return +the value inside the `Ok`. If the `Result` is the `Err` variant, `unwrap` will +call the `panic!` macro for us. Here is an example of `unwrap` in action: + +Filename: src/main.rs + +``` +use std::fs::File; + +fn main() { + let f = File::open("hello.txt").unwrap(); +} +``` + +If we run this code without a *hello.txt* file, we’ll see an error message from +the `panic!` call that the `unwrap` method makes: + +``` +thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error { +repr: Os { code: 2, message: "No such file or directory" } }', +src/libcore/result.rs:906:4 +``` + +Another method, `expect`, which is similar to `unwrap`, lets us also choose the +`panic!` error message. Using `expect` instead of `unwrap` and providing good +error messages can convey your intent and make tracking down the source of a +panic easier. The syntax of `expect` looks like this: + +Filename: src/main.rs + +``` +use std::fs::File; + +fn main() { + let f = File::open("hello.txt").expect("Failed to open hello.txt"); +} +``` + +We use `expect` in the same way as `unwrap`: to return the file handle or call +the `panic!` macro. The error message used by `expect` in its call to `panic!` +will be the parameter that we pass to `expect`, rather than the default +`panic!` message that `unwrap` uses. Here’s what it looks like: + +``` +thread 'main' panicked at 'Failed to open hello.txt: Error { repr: Os { code: +2, message: "No such file or directory" } }', src/libcore/result.rs:906:4 +``` + +Because this error message starts with the text we specified, `Failed to open +hello.txt`, it will be easier to find where in the code this error message is +coming from. If we use `unwrap` in multiple places, it can take more time to +figure out exactly which `unwrap` is causing the panic because all `unwrap` +calls that panic print the same message. + +### Propagating Errors + +When you’re writing a function whose implementation calls something that might +fail, instead of handling the error within this function, you can return the +error to the calling code so that it can decide what to do. This is known as +*propagating* the error and gives more control to the calling code, where there +might be more information or logic that dictates how the error should be +handled than what you have available in the context of your code. + +For example, Listing 9-6 shows a function that reads a username from a file. If +the file doesn’t exist or can’t be read, this function will return those errors +to the code that called this function. + +Filename: src/main.rs + +``` +use std::fs::File; +use std::io::{self, Read}; + +fn read_username_from_file() -> Result { + let f = File::open("hello.txt"); + + let mut f = match f { + Ok(file) => file, + Err(e) => return Err(e), + }; + + let mut s = String::new(); + + match f.read_to_string(&mut s) { + Ok(_) => Ok(s), + Err(e) => Err(e), + } +} +``` + +Listing 9-6: A function that returns errors to the calling code using `match` + +This function can be written in a much shorter way, but we’re going to start by +doing a lot of it manually in order to explore error handling; at the end, +we’ll show the shorter way. Let’s look at the return type of the function first: +`Result`. This means the function is returning a value of +the type `Result` where the generic parameter `T` has been filled in +with the concrete type `String` and the generic type `E` has been filled in +with the concrete type `io::Error`. If this function succeeds without any +problems, the code that calls this function will receive an `Ok` value that +holds a `String`—the username that this function read from the file. If this +function encounters any problems, the code that calls this function will +receive an `Err` value that holds an instance of `io::Error` that contains +more information about what the problems were. We chose `io::Error` as the +return type of this function because that happens to be the type of the error +value returned from both of the operations we’re calling in this function’s +body that might fail: the `File::open` function and the `read_to_string` +method. + +The body of the function starts by calling the `File::open` function. Then we +handle the `Result` value with a `match` similar to the `match` in Listing 9-4. +If `File::open` succeeds, the file handle in the pattern variable `file` +becomes the value in the mutable variable `f` and the function continues. In +the `Err` case, instead of calling `panic!`, we use the `return` keyword to +return early out of the function entirely and pass the error value from +`File::open`, now in the pattern variable `e`, back to the calling code as this +function’s error value. + +So if we have a file handle in `f`, the function then creates a new `String` in +variable `s` and calls the `read_to_string` method on the file handle in `f` to +read the contents of the file into `s`. The `read_to_string` method also +returns a `Result` because it might fail, even though `File::open` succeeded. +So we need another `match` to handle that `Result`: if `read_to_string` +succeeds, then our function has succeeded, and we return the username from the +file that’s now in `s` wrapped in an `Ok`. If `read_to_string` fails, we return +the error value in the same way that we returned the error value in the `match` +that handled the return value of `File::open`. However, we don’t need to +explicitly say `return`, because this is the last expression in the function. + +The code that calls this code will then handle getting either an `Ok` value +that contains a username or an `Err` value that contains an `io::Error`. We +don’t know what the calling code will do with those values. If the calling code +gets an `Err` value, it could call `panic!` and crash the program, use a +default username, or look up the username from somewhere other than a file, for +example. We don’t have enough information on what the calling code is actually +trying to do, so we propagate all the success or error information upward for +it to handle appropriately. + +This pattern of propagating errors is so common in Rust that Rust provides the +question mark operator `?` to make this easier. + +#### A Shortcut for Propagating Errors: the `?` Operator + +Listing 9-7 shows an implementation of `read_username_from_file` that has the +same functionality as it had in Listing 9-6, but this implementation uses the +`?` operator. + +Filename: src/main.rs + +``` +use std::fs::File; +use std::io; +use std::io::Read; + +fn read_username_from_file() -> Result { + let mut f = File::open("hello.txt")?; + let mut s = String::new(); + f.read_to_string(&mut s)?; + Ok(s) +} +``` + +Listing 9-7: A function that returns errors to the calling code using the `?` +operator + +The `?` placed after a `Result` value is defined to work in almost the same way +as the `match` expressions we defined to handle the `Result` values in Listing +9-6. If the value of the `Result` is an `Ok`, the value inside the `Ok` will +get returned from this expression, and the program will continue. If the value +is an `Err`, the `Err` will be returned from the whole function as if we had +used the `return` keyword so the error value gets propagated to the calling +code. + +There is a difference between what the `match` expression from Listing 9-6 does +and what the `?` operator does: error values that have the `?` operator called +on them go through the `from` function, defined in the `From` trait in the +standard library, which is used to convert errors from one type into another. +When the `?` operator calls the `from` function, the error type received is +converted into the error type defined in the return type of the current +function. This is useful when a function returns one error type to represent +all the ways a function might fail, even if parts might fail for many different +reasons. As long as there’s an `impl From for ReturnedError` to +define the conversion in the trait’s `from` function, the `?` operator takes +care of calling the `from` function automatically. + +In the context of Listing 9-7, the `?` at the end of the `File::open` call will +return the value inside an `Ok` to the variable `f`. If an error occurs, the +`?` operator will return early out of the whole function and give any `Err` +value to the calling code. The same thing applies to the `?` at the end of the +`read_to_string` call. + +The `?` operator eliminates a lot of boilerplate and makes this function’s +implementation simpler. We could even shorten this code further by chaining +method calls immediately after the `?`, as shown in Listing 9-8. + +Filename: src/main.rs + +``` +use std::fs::File; +use std::io; +use std::io::Read; + +fn read_username_from_file() -> Result { + let mut s = String::new(); + + File::open("hello.txt")?.read_to_string(&mut s)?; + + Ok(s) +} +``` + +Listing 9-8: Chaining method calls after the `?` operator + +We’ve moved the creation of the new `String` in `s` to the beginning of the +function; that part hasn’t changed. Instead of creating a variable `f`, we’ve +chained the call to `read_to_string` directly onto the result of +`File::open("hello.txt")?`. We still have a `?` at the end of the +`read_to_string` call, and we still return an `Ok` value containing the +username in `s` when both `File::open` and `read_to_string` succeed rather than +returning errors. The functionality is again the same as in Listing 9-6 and +Listing 9-7; this is just a different, more ergonomic way to write it. + +Speaking of different ways to write this function, Listing 9-9 shows that +there’s a way to make this even shorter. + +Filename: src/main.rs + +``` +use std::fs; +use std::io; + +fn read_username_from_file() -> Result { + fs::read_to_string("hello.txt") +} +``` + +Listing 9-9: Using `fs::read_to_string` instead of opening and then reading the +file + +Reading a file into a string is a fairly common operation, so Rust provides the +convenient `fs::read_to_string` function that opens the file, creates a new +`String`, reads the contents of the file, puts the contents into that `String`, +and returns it. Of course, using `fs::read_to_string` doesn’t give us the +opportunity to explain all the error handling, so we did it the longer way +first. + +#### Where The `?` Operator Can Be Used + +The `?` operator can only be used in functions that have a return type +compatible with the value the `?` is used on. This is because the `?` operator +is defined to perform an early return of a value out of the function, in the +same manner as the `match` expression we defined in Listing 9-6 did. In Listing +9-6, the `match` was using a `Result` value, and the early return arm returned +an `Err(e)` value. The return type of the function has to be a `Result` to be +compatible with this `return`. + +In Listing 9-10, let’s look at the error we’ll get if we use the `?` operator +in a `main` function with a return type of `()`: + +``` +use std::fs::File; + +fn main() { + let f = File::open("hello.txt")?; +} +``` + +Listing 9-10: Attempting to use the `?` in the `main` function that returns +`()` won’t compile + +This code opens a file, which might fail. The `?` operator follows the `Result` +value returned by `File::open`, but this `main` function has the return type of +`()`, not `Result`. When we compile this code, we get the following error +message: + +``` +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> src/main.rs:4:36 + | +3 | / fn main() { +4 | | let f = File::open("hello.txt")?; + | | ^ cannot use the `?` operator in a function that returns `()` +5 | | } + | |_- this function should return `Result` or `Option` to accept `?` + | +``` + +This error points out that we’re only allowed to use the `?` operator in a +function that returns `Result`, `Option`, or another type that implements +`FromResidual`. To fix this error, you have two choices. One technique is to +change the return type of your function to be `Result` if you have no +restrictions preventing that. The other technique is to use a `match` or one of +the `Result` methods to handle the `Result` in whatever way is +appropriate. + +The error message also mentioned that `?` can be used with `Option` values +as well. As with using `?` on `Result`, you can only use `?` on `Option` in a +function that returns an `Option`. The behavior of the `?` operator when called +on an `Option` is similar to its behavior when called on a `Result`: +if the value is `None`, the `None` will be returned early from the function at +that point. If the value is `Some`, the value inside the `Some` is the +resulting value of the expression and the function continues. Listing 9-11 has +an example of a function that finds the last character of the first line in the +given text: + +``` +fn last_char_of_first_line(text: &str) -> Option { + text.lines().next()?.chars().last() +} +``` + +Listing 9-11: Using the `?` operator on an `Option` value + +This function returns `Option` because it might find a character at this +position, or there might be no character there. This code takes the `text` +string slice argument and calls the `lines` method on it, which returns an +iterator over the lines in the string. Because this function wants to examine +the first line, it calls `next` on the iterator to get the first value from the +iterator. If `text` is the empty string, this call to `next` will return +`None`, and here we can use `?` to stop and return `None` from +`last_char_of_first_line` if that is the case. If `text` is not the empty +string, `next` will return a `Some` value containing a string slice of the +first line in `text`. + +The `?` extracts the string slice, and we can call `chars` on that string slice +to get an iterator of the characters in this string slice. We’re interested in +the last character in this first line, so we call `last` to return the last +item in the iterator over the characters. This is an `Option` because the first +line might be the empty string, if `text` starts with a blank line but has +characters on other lines, as in `"\nhi"`. However, if there is a last +character on the first line, it will be returned in the `Some` variant. The `?` +operator in the middle gives us a concise way to express this logic, and this +function can be implemented in one line. If we couldn’t use the `?` operator on +`Option`, we’d have to implement this logic using more method calls or a +`match` expression. + +Note that you can use the `?` operator on a `Result` in a function that returns +`Result`, and you can use the `?` operator on an `Option` in a function that +returns `Option`, but you can’t mix and match. The `?` operator won’t +automatically convert a `Result` to an `Option` or vice versa; in those cases, +there are methods like the `ok` method on `Result` or the `ok_or` method on +`Option` that will do the conversion explicitly. + +So far, all the `main` functions we’ve used return `()`. The `main` function is +special because it’s the entry and exit point of executable programs, and there +are restrictions on what its return type can be for the programs to behave as +expected. Executables written in C return integers when they exit, and Rust +executables follow this convention as well: programs that exit successfully +return the integer `0`, and programs that error return some integer other than +`0`. When `main` returns `()`, Rust executables will return `0` if `main` +returns and a nonzero value if the program panics before reaching the end of +`main`. + +Another return type `main` can have is `Result<(), E>`. Listing 9-12 has the +code from Listing 9-10 but we’ve changed the return type of `main` to be +`Result<(), Box>` and added a return value `Ok(())` to the end. This +code will now compile: + +``` +use std::error::Error; +use std::fs::File; + +fn main() -> Result<(), Box> { + let f = File::open("hello.txt")?; + + Ok(()) +} +``` + +Listing 9-12: Changing `main` to return `Result<(), E>` allows the use of the +`?` operator on `Result` values + +The `Box` type is called a trait object, which we’ll talk about in +the “Using Trait Objects that Allow for Values of Different Types” section in +Chapter 17. For now, you can read `Box` to mean “any kind of error.” +Using `?` on a `Result` value in a `main` function with this return type is +allowed, because now an `Err` value can be returned early. When a `main` +function returns a `Result<(), E>`, the executable will exit with a value of +`0` if `main` returns `Ok(())` and will exit with a nonzero value if `main` +returns an `Err` value. + +The types that `main` may return are those that implement the +`std::process::Termination` trait. As of this writing, the `Termination` trait +is an unstable feature only available in Nightly Rust, so you can’t yet +implement it for your own types in Stable Rust, but you might be able to +someday! + +Now that we’ve discussed the details of calling `panic!` or returning `Result`, +let’s return to the topic of how to decide which is appropriate to use in which +cases. + +## To `panic!` or Not to `panic!` + +So how do you decide when you should call `panic!` and when you should return +`Result`? When code panics, there’s no way to recover. You could call `panic!` +for any error situation, whether there’s a possible way to recover or not, but +then you’re making the decision on behalf of the code calling your code that a +situation is unrecoverable. When you choose to return a `Result` value, you +give the calling code options rather than making the decision for it. The +calling code could choose to attempt to recover in a way that’s appropriate for +its situation, or it could decide that an `Err` value in this case is +unrecoverable, so it can call `panic!` and turn your recoverable error into an +unrecoverable one. Therefore, returning `Result` is a good default choice when +you’re defining a function that might fail. + +In rare situations, it’s more appropriate to write code that panics instead of +returning a `Result`. Let’s explore why it’s appropriate to panic in examples, +prototype code, and tests. Then we’ll discuss situations in which the compiler +can’t tell that failure is impossible, but you as a human can. The chapter will +conclude with some general guidelines on how to decide whether to panic in +library code. + +### Examples, Prototype Code, and Tests + +When you’re writing an example to illustrate some concept, having robust +error-handling code in the example as well can make the example less clear. In +examples, it’s understood that a call to a method like `unwrap` that could +panic is meant as a placeholder for the way you’d want your application to +handle errors, which can differ based on what the rest of your code is doing. + +Similarly, the `unwrap` and `expect` methods are very handy when prototyping, +before you’re ready to decide how to handle errors. They leave clear markers in +your code for when you’re ready to make your program more robust. + +If a method call fails in a test, you’d want the whole test to fail, even if +that method isn’t the functionality under test. Because `panic!` is how a test +is marked as a failure, calling `unwrap` or `expect` is exactly what should +happen. + +### Cases in Which You Have More Information Than the Compiler + +It would also be appropriate to call `unwrap` when you have some other logic +that ensures the `Result` will have an `Ok` value, but the logic isn’t +something the compiler understands. You’ll still have a `Result` value that you +need to handle: whatever operation you’re calling still has the possibility of +failing in general, even though it’s logically impossible in your particular +situation. If you can ensure by manually inspecting the code that you’ll never +have an `Err` variant, it’s perfectly acceptable to call `unwrap`. Here’s an +example: + +``` +use std::net::IpAddr; + +let home: IpAddr = "127.0.0.1".parse().unwrap(); +``` + +We’re creating an `IpAddr` instance by parsing a hardcoded string. We can see +that `127.0.0.1` is a valid IP address, so it’s acceptable to use `unwrap` +here. However, having a hardcoded, valid string doesn’t change the return type +of the `parse` method: we still get a `Result` value, and the compiler will +still make us handle the `Result` as if the `Err` variant is a possibility +because the compiler isn’t smart enough to see that this string is always a +valid IP address. If the IP address string came from a user rather than being +hardcoded into the program and therefore *did* have a possibility of failure, +we’d definitely want to handle the `Result` in a more robust way instead. + +### Guidelines for Error Handling + +It’s advisable to have your code panic when it’s possible that your code +could end up in a bad state. In this context, a *bad state* is when some +assumption, guarantee, contract, or invariant has been broken, such as when +invalid values, contradictory values, or missing values are passed to your +code—plus one or more of the following: + +* The bad state is something that is unexpected, as opposed to something that + will likely happen occasionally, like a user entering data in the wrong + format. +* Your code after this point needs to rely on not being in this bad state, + rather than checking for the problem at every step. +* There’s not a good way to encode this information in the types you use. We’ll + work through an example of what we mean in the “Encoding States and Behavior + as Types” section of Chapter 17. + +If someone calls your code and passes in values that don’t make sense, the best +choice might be to call `panic!` and alert the person using your library to the +bug in their code so they can fix it during development. Similarly, `panic!` is +often appropriate if you’re calling external code that is out of your control +and it returns an invalid state that you have no way of fixing. + +However, when failure is expected, it’s more appropriate to return a `Result` +than to make a `panic!` call. Examples include a parser being given malformed +data or an HTTP request returning a status that indicates you have hit a rate +limit. In these cases, returning a `Result` indicates that failure is an +expected possibility that the calling code must decide how to handle. + +When your code performs operations on values, your code should verify the +values are valid first and panic if the values aren’t valid. This is mostly for +safety reasons: attempting to operate on invalid data can expose your code to +vulnerabilities. This is the main reason the standard library will call +`panic!` if you attempt an out-of-bounds memory access: trying to access memory +that doesn’t belong to the current data structure is a common security problem. +Functions often have *contracts*: their behavior is only guaranteed if the +inputs meet particular requirements. Panicking when the contract is violated +makes sense because a contract violation always indicates a caller-side bug and +it’s not a kind of error you want the calling code to have to explicitly +handle. In fact, there’s no reasonable way for calling code to recover; the +calling *programmers* need to fix the code. Contracts for a function, +especially when a violation will cause a panic, should be explained in the API +documentation for the function. + +However, having lots of error checks in all of your functions would be verbose +and annoying. Fortunately, you can use Rust’s type system (and thus the type +checking the compiler does) to do many of the checks for you. If your function +has a particular type as a parameter, you can proceed with your code’s logic +knowing that the compiler has already ensured you have a valid value. For +example, if you have a type rather than an `Option`, your program expects to +have *something* rather than *nothing*. Your code then doesn’t have to handle +two cases for the `Some` and `None` variants: it will only have one case for +definitely having a value. Code trying to pass nothing to your function won’t +even compile, so your function doesn’t have to check for that case at runtime. +Another example is using an unsigned integer type such as `u32`, which ensures +the parameter is never negative. + +### Creating Custom Types for Validation + +Let’s take the idea of using Rust’s type system to ensure we have a valid value +one step further and look at creating a custom type for validation. Recall the +guessing game in Chapter 2 in which our code asked the user to guess a number +between 1 and 100. We never validated that the user’s guess was between those +numbers before checking it against our secret number; we only validated that +the guess was positive. In this case, the consequences were not very dire: our +output of “Too high” or “Too low” would still be correct. But it would be a +useful enhancement to guide the user toward valid guesses and have different +behavior when a user guesses a number that’s out of range versus when a user +types, for example, letters instead. + +One way to do this would be to parse the guess as an `i32` instead of only a +`u32` to allow potentially negative numbers, and then add a check for the +number being in range, like so: + +``` +loop { + // --snip-- + + let guess: i32 = match guess.trim().parse() { + Ok(num) => num, + Err(_) => continue, + }; + + if guess < 1 || guess > 100 { + println!("The secret number will be between 1 and 100."); + continue; + } + + match guess.cmp(&secret_number) { + // --snip-- +} +``` + +The `if` expression checks whether our value is out of range, tells the user +about the problem, and calls `continue` to start the next iteration of the loop +and ask for another guess. After the `if` expression, we can proceed with the +comparisons between `guess` and the secret number knowing that `guess` is +between 1 and 100. + +However, this is not an ideal solution: if it was absolutely critical that the +program only operated on values between 1 and 100, and it had many functions +with this requirement, having a check like this in every function would be +tedious (and might impact performance). + +Instead, we can make a new type and put the validations in a function to create +an instance of the type rather than repeating the validations everywhere. That +way, it’s safe for functions to use the new type in their signatures and +confidently use the values they receive. Listing 9-13 shows one way to define a +`Guess` type that will only create an instance of `Guess` if the `new` function +receives a value between 1 and 100. + +``` +pub struct Guess { + value: i32, +} + +impl Guess { + pub fn new(value: i32) -> Guess { + if value < 1 || value > 100 { + panic!("Guess value must be between 1 and 100, got {}.", value); + } + + Guess { value } + } + + pub fn value(&self) -> i32 { + self.value + } +} +``` + +Listing 9-13: A `Guess` type that will only continue with values between 1 and +100 + +First, we define a struct named `Guess` that has a field named `value` that +holds an `i32`. This is where the number will be stored. + +Then we implement an associated function named `new` on `Guess` that creates +instances of `Guess` values. The `new` function is defined to have one +parameter named `value` of type `i32` and to return a `Guess`. The code in the +body of the `new` function tests `value` to make sure it’s between 1 and 100. +If `value` doesn’t pass this test, we make a `panic!` call, which will alert +the programmer who is writing the calling code that they have a bug they need +to fix, because creating a `Guess` with a `value` outside this range would +violate the contract that `Guess::new` is relying on. The conditions in which +`Guess::new` might panic should be discussed in its public-facing API +documentation; we’ll cover documentation conventions indicating the possibility +of a `panic!` in the API documentation that you create in Chapter 14. If +`value` does pass the test, we create a new `Guess` with its `value` field set +to the `value` parameter and return the `Guess`. + +Next, we implement a method named `value` that borrows `self`, doesn’t have any +other parameters, and returns an `i32`. This kind of method is sometimes called +a *getter*, because its purpose is to get some data from its fields and return +it. This public method is necessary because the `value` field of the `Guess` +struct is private. It’s important that the `value` field be private so code +using the `Guess` struct is not allowed to set `value` directly: code outside +the module *must* use the `Guess::new` function to create an instance of +`Guess`, thereby ensuring there’s no way for a `Guess` to have a `value` that +hasn’t been checked by the conditions in the `Guess::new` function. + +A function that has a parameter or returns only numbers between 1 and 100 could +then declare in its signature that it takes or returns a `Guess` rather than an +`i32` and wouldn’t need to do any additional checks in its body. + +## Summary + +Rust’s error handling features are designed to help you write more robust code. +The `panic!` macro signals that your program is in a state it can’t handle and +lets you tell the process to stop instead of trying to proceed with invalid or +incorrect values. The `Result` enum uses Rust’s type system to indicate that +operations might fail in a way that your code could recover from. You can use +`Result` to tell code that calls your code that it needs to handle potential +success or failure as well. Using `panic!` and `Result` in the appropriate +situations will make your code more reliable in the face of inevitable problems. + +Now that you’ve seen useful ways that the standard library uses generics with +the `Option` and `Result` enums, we’ll talk about how generics work and how you +can use them in your code. diff --git a/src/doc/book/nostarch/chapter10.md b/src/doc/book/nostarch/chapter10.md new file mode 100644 index 0000000000..b259636914 --- /dev/null +++ b/src/doc/book/nostarch/chapter10.md @@ -0,0 +1,2042 @@ + +[TOC] + +# Generic Types, Traits, and Lifetimes + +Every programming language has tools for effectively handling the duplication +of concepts. In Rust, one such tool is *generics*. Generics are abstract +stand-ins for concrete types or other properties. When we’re writing code, we +can express the behavior of generics or how they relate to other generics +without knowing what will be in their place when compiling and running the code. + +Similar to the way a function takes parameters with unknown values to run the +same code on multiple concrete values, functions can take parameters of some +generic type instead of a concrete type, like `i32` or `String`. In fact, we’ve +already used generics in Chapter 6 with `Option`, Chapter 8 with `Vec` +and `HashMap`, and Chapter 9 with `Result`. In this chapter, you’ll +explore how to define your own types, functions, and methods with generics! + +First, we’ll review how to extract a function to reduce code duplication. Next, +we’ll use the same technique to make a generic function from two functions that +differ only in the types of their parameters. We’ll also explain how to use +generic types in struct and enum definitions. + +Then you’ll learn how to use *traits* to define behavior in a generic way. You +can combine traits with generic types to constrain a generic type to only +those types that have a particular behavior, as opposed to just any type. + +Finally, we’ll discuss *lifetimes*, a variety of generics that give the +compiler information about how references relate to each other. Lifetimes allow +us to borrow values in many situations while still enabling the compiler to +check that the references are valid. + +## Removing Duplication by Extracting a Function + +Before diving into generics syntax, let’s first look at how to remove +duplication that doesn’t involve generic types by extracting a function. Then +we’ll apply this technique to extract a generic function! In the same way that +you recognize duplicated code to extract into a function, you’ll start to +recognize duplicated code that can use generics. + +Consider a short program that finds the largest number in a list, as shown in +Listing 10-1. + +Filename: src/main.rs + +``` +fn main() { + let number_list = vec![34, 50, 25, 100, 65]; + + let mut largest = number_list[0]; + + for number in number_list { + if number > largest { + largest = number; + } + } + + println!("The largest number is {}", largest); +} +``` + +Listing 10-1: Code to find the largest number in a list of numbers + +This code stores a list of integers in the variable `number_list` and places +the first number in the list in a variable named `largest`. Then it iterates +through all the numbers in the list, and if the current number is greater than +the number stored in `largest`, it replaces the number in that variable. +However, if the current number is less than or equal to the largest number seen +so far, the variable doesn’t change, and the code moves on to the next number +in the list. After considering all the numbers in the list, `largest` should +hold the largest number, which in this case is 100. + +To find the largest number in two different lists of numbers, we can duplicate +the code in Listing 10-1 and use the same logic at two different places in the +program, as shown in Listing 10-2. + +Filename: src/main.rs + +``` +fn main() { + let number_list = vec![34, 50, 25, 100, 65]; + + let mut largest = number_list[0]; + + for number in number_list { + if number > largest { + largest = number; + } + } + + println!("The largest number is {}", largest); + + let number_list = vec![102, 34, 6000, 89, 54, 2, 43, 8]; + + let mut largest = number_list[0]; + + for number in number_list { + if number > largest { + largest = number; + } + } + + println!("The largest number is {}", largest); +} +``` + +Listing 10-2: Code to find the largest number in *two* lists of numbers + +Although this code works, duplicating code is tedious and error prone. We also +have to update the code in multiple places when we want to change it. + +To eliminate this duplication, we can create an abstraction by defining a +function that operates on any list of integers given to it in a parameter. This +solution makes our code clearer and lets us express the concept of finding the +largest number in a list abstractly. + +In Listing 10-3, we extracted the code that finds the largest number into a +function named `largest`. Unlike the code in Listing 10-1, which can find the +largest number in only one particular list, this program can find the largest +number in two different lists. + +Filename: src/main.rs + +``` +fn largest(list: &[i32]) -> i32 { + let mut largest = list[0]; + + for &item in list { + if item > largest { + largest = item; + } + } + + largest +} + +fn main() { + let number_list = vec![34, 50, 25, 100, 65]; + + let result = largest(&number_list); + println!("The largest number is {}", result); + + let number_list = vec![102, 34, 6000, 89, 54, 2, 43, 8]; + + let result = largest(&number_list); + println!("The largest number is {}", result); +} +``` + +Listing 10-3: Abstracted code to find the largest number in two lists + +The `largest` function has a parameter called `list`, which represents any +concrete slice of `i32` values that we might pass into the function. As a +result, when we call the function, the code runs on the specific values that we +pass in. Don’t worry about the syntax of the `for` loop for now. We aren’t +referencing a reference to an `i32` here; we’re pattern matching and +destructuring each `&i32` that the `for` loop gets so that `item` will be an +`i32` inside the loop body. We’ll cover pattern matching in detail in Chapter +18. + +In sum, here are the steps we took to change the code from Listing 10-2 to +Listing 10-3: + +1. Identify duplicate code. +2. Extract the duplicate code into the body of the function and specify the + inputs and return values of that code in the function signature. +3. Update the two instances of duplicated code to call the function instead. + +Next, we’ll use these same steps with generics to reduce code duplication in +different ways. In the same way that the function body can operate on an +abstract `list` instead of specific values, generics allow code to operate on +abstract types. + +For example, say we had two functions: one that finds the largest item in a +slice of `i32` values and one that finds the largest item in a slice of `char` +values. How would we eliminate that duplication? Let’s find out! + +## Generic Data Types + +We can use generics to create definitions for items like function signatures or +structs, which we can then use with many different concrete data types. Let’s +first look at how to define functions, structs, enums, and methods using +generics. Then we’ll discuss how generics affect code performance. + +### In Function Definitions + +When defining a function that uses generics, we place the generics in the +signature of the function where we would usually specify the data types of the +parameters and return value. Doing so makes our code more flexible and provides +more functionality to callers of our function while preventing code duplication. + +Continuing with our `largest` function, Listing 10-4 shows two functions that +both find the largest value in a slice. + +Filename: src/main.rs + +``` +fn largest_i32(list: &[i32]) -> i32 { + let mut largest = list[0]; + + for &item in list { + if item > largest { + largest = item; + } + } + + largest +} + +fn largest_char(list: &[char]) -> char { + let mut largest = list[0]; + + for &item in list { + if item > largest { + largest = item; + } + } + + largest +} + +fn main() { + let number_list = vec![34, 50, 25, 100, 65]; + + let result = largest_i32(&number_list); + println!("The largest number is {}", result); + + let char_list = vec!['y', 'm', 'a', 'q']; + + let result = largest_char(&char_list); + println!("The largest char is {}", result); +} +``` + +Listing 10-4: Two functions that differ only in their names and the types in +their signatures + +The `largest_i32` function is the one we extracted in Listing 10-3 that finds +the largest `i32` in a slice. The `largest_char` function finds the largest +`char` in a slice. The function bodies have the same code, so let’s eliminate +the duplication by introducing a generic type parameter in a single function. + +To parameterize the types in the new function we’ll define, we need to name the +type parameter, just as we do for the value parameters to a function. You can +use any identifier as a type parameter name. But we’ll use `T` because, by +convention, parameter names in Rust are short, often just a letter, and Rust’s +type-naming convention is CamelCase. Short for “type,” `T` is the default +choice of most Rust programmers. + +When we use a parameter in the body of the function, we have to declare the +parameter name in the signature so the compiler knows what that name means. +Similarly, when we use a type parameter name in a function signature, we have +to declare the type parameter name before we use it. To define the generic +`largest` function, place type name declarations inside angle brackets, `<>`, +between the name of the function and the parameter list, like this: + +``` +fn largest(list: &[T]) -> T { +``` + +We read this definition as: the function `largest` is generic over some type +`T`. This function has one parameter named `list`, which is a slice of values +of type `T`. The `largest` function will return a value of the +same type `T`. + +Listing 10-5 shows the combined `largest` function definition using the generic +data type in its signature. The listing also shows how we can call the function +with either a slice of `i32` values or `char` values. Note that this code won’t +compile yet, but we’ll fix it later in this chapter. + +Filename: src/main.rs + +``` +fn largest(list: &[T]) -> T { + let mut largest = list[0]; + + for &item in list { + if item > largest { + largest = item; + } + } + + largest +} + +fn main() { + let number_list = vec![34, 50, 25, 100, 65]; + + let result = largest(&number_list); + println!("The largest number is {}", result); + + let char_list = vec!['y', 'm', 'a', 'q']; + + let result = largest(&char_list); + println!("The largest char is {}", result); +} +``` + +Listing 10-5: A definition of the `largest` function that uses generic type +parameters but doesn’t compile yet + +If we compile this code right now, we’ll get this error: + +``` +error[E0369]: binary operation `>` cannot be applied to type `T` + --> src/main.rs:5:17 + | +5 | if item > largest { + | ---- ^ ------- T + | | + | T + | +help: consider restricting type parameter `T` + | +1 | fn largest(list: &[T]) -> T { + | ^^^^^^^^^^^^^^^^^^^^^^ +``` + +The note mentions `std::cmp::PartialOrd`, which is a *trait*. We’ll talk about +traits in the next section. For now, this error states that the body of +`largest` won’t work for all possible types that `T` could be. Because we want +to compare values of type `T` in the body, we can only use types whose values +can be ordered. To enable comparisons, the standard library has the +`std::cmp::PartialOrd` trait that you can implement on types (see Appendix C +for more on this trait). You’ll learn how to specify that a generic type has a +particular trait in the “Traits as Parameters” section, but let’s first explore +other ways of using generic type parameters. + +### In Struct Definitions + +We can also define structs to use a generic type parameter in one or more +fields using the `<>` syntax. Listing 10-6 shows how to define a `Point` +struct to hold `x` and `y` coordinate values of any type. + +Filename: src/main.rs + +``` +struct Point { + x: T, + y: T, +} + +fn main() { + let integer = Point { x: 5, y: 10 }; + let float = Point { x: 1.0, y: 4.0 }; +} +``` + +Listing 10-6: A `Point` struct that holds `x` and `y` values of type `T` + +The syntax for using generics in struct definitions is similar to that used in +function definitions. First, we declare the name of the type parameter inside +angle brackets just after the name of the struct. Then we can use the generic +type in the struct definition where we would otherwise specify concrete data +types. + +Note that because we’ve used only one generic type to define `Point`, this +definition says that the `Point` struct is generic over some type `T`, and +the fields `x` and `y` are *both* that same type, whatever that type may be. If +we create an instance of a `Point` that has values of different types, as in +Listing 10-7, our code won’t compile. + +Filename: src/main.rs + +``` +struct Point { + x: T, + y: T, +} + +fn main() { + let wont_work = Point { x: 5, y: 4.0 }; +} +``` + +Listing 10-7: The fields `x` and `y` must be the same type because both have +the same generic data type `T`. + +In this example, when we assign the integer value 5 to `x`, we let the +compiler know that the generic type `T` will be an integer for this instance of +`Point`. Then when we specify 4.0 for `y`, which we’ve defined to have the +same type as `x`, we’ll get a type mismatch error like this: + +``` +error[E0308]: mismatched types + --> src/main.rs:7:38 + | +7 | let wont_work = Point { x: 5, y: 4.0 }; + | ^^^ expected integer, found floating-point number +``` + +To define a `Point` struct where `x` and `y` are both generics but could have +different types, we can use multiple generic type parameters. For example, in +Listing 10-8, we can change the definition of `Point` to be generic over types +`T` and `U` where `x` is of type `T` and `y` is of type `U`. + +Filename: src/main.rs + +``` +struct Point { + x: T, + y: U, +} + +fn main() { + let both_integer = Point { x: 5, y: 10 }; + let both_float = Point { x: 1.0, y: 4.0 }; + let integer_and_float = Point { x: 5, y: 4.0 }; +} +``` + +Listing 10-8: A `Point` generic over two types so that `x` and `y` can be +values of different types + +Now all the instances of `Point` shown are allowed! You can use as many generic +type parameters in a definition as you want, but using more than a few makes +your code hard to read. When you need lots of generic types in your code, it +could indicate that your code needs restructuring into smaller pieces. + +### In Enum Definitions + +As we did with structs, we can define enums to hold generic data types in their +variants. Let’s take another look at the `Option` enum that the standard +library provides, which we used in Chapter 6: + +``` +enum Option { + Some(T), + None, +} +``` + +This definition should now make more sense to you. As you can see, `Option` +is an enum that is generic over type `T` and has two variants: `Some`, which +holds one value of type `T`, and a `None` variant that doesn’t hold any value. +By using the `Option` enum, we can express the abstract concept of having an +optional value, and because `Option` is generic, we can use this abstraction +no matter what the type of the optional value is. + +Enums can use multiple generic types as well. The definition of the `Result` +enum that we used in Chapter 9 is one example: + +``` +enum Result { + Ok(T), + Err(E), +} +``` + +The `Result` enum is generic over two types, `T` and `E`, and has two variants: +`Ok`, which holds a value of type `T`, and `Err`, which holds a value of type +`E`. This definition makes it convenient to use the `Result` enum anywhere we +have an operation that might succeed (return a value of some type `T`) or fail +(return an error of some type `E`). In fact, this is what we used to open a +file in Listing 9-3, where `T` was filled in with the type `std::fs::File` when +the file was opened successfully and `E` was filled in with the type +`std::io::Error` when there were problems opening the file. + +When you recognize situations in your code with multiple struct or enum +definitions that differ only in the types of the values they hold, you can +avoid duplication by using generic types instead. + +### In Method Definitions + +We can implement methods on structs and enums (as we did in Chapter 5) and use +generic types in their definitions, too. Listing 10-9 shows the `Point` +struct we defined in Listing 10-6 with a method named `x` implemented on it. + +Filename: src/main.rs + +``` +struct Point { + x: T, + y: T, +} + +impl Point { + fn x(&self) -> &T { + &self.x + } +} + +fn main() { + let p = Point { x: 5, y: 10 }; + + println!("p.x = {}", p.x()); +} +``` + +Listing 10-9: Implementing a method named `x` on the `Point` struct that +will return a reference to the `x` field of type `T` + +Here, we’ve defined a method named `x` on `Point` that returns a reference +to the data in the field `x`. + +Note that we have to declare `T` just after `impl` so we can use it to specify +that we’re implementing methods on the type `Point`. By declaring `T` as a +generic type after `impl`, Rust can identify that the type in the angle +brackets in `Point` is a generic type rather than a concrete type. Because this +is declaring the generic again, we could have chosen a different name for the +generic parameter than the generic parameter declared in the struct definition, +but using the same name is conventional. Methods written within an `impl` that +declares the generic type will be defined on any instance of the type, no +matter what concrete type ends up substituting for the generic type. + +The other option we have is defining methods on the type with some constraint +on the generic type. We could, for example, implement methods only on +`Point` instances rather than on `Point` instances with any generic +type. In Listing 10-10 we use the concrete type `f32`, meaning we don’t declare +any types after `impl`. + +Filename: src/main.rs + +``` +impl Point { + fn distance_from_origin(&self) -> f32 { + (self.x.powi(2) + self.y.powi(2)).sqrt() + } +} +``` + +Listing 10-10: An `impl` block that only applies to a struct with a particular +concrete type for the generic type parameter `T` + +This code means the type `Point` will have a method named +`distance_from_origin` and other instances of `Point` where `T` is not of +type `f32` will not have this method defined. The method measures how far our +point is from the point at coordinates (0.0, 0.0) and uses mathematical +operations that are available only for floating point types. + +Generic type parameters in a struct definition aren’t always the same as those +you use in that struct’s method signatures. Listing 10-11 uses the generic +types `X1` and `Y1` for the `Point` struct and `X2` `Y2` for the `mixup` method +signature to make the example clearer. The method creates a new `Point` +instance with the `x` value from the `self` `Point` (of type `X1`) and the `y` +value from the passed-in `Point` (of type `Y2`). + +Filename: src/main.rs + +``` +struct Point { + x: X1, + y: Y1, +} + +impl Point { + fn mixup(self, other: Point) -> Point { + Point { + x: self.x, + y: other.y, + } + } +} + +fn main() { + let p1 = Point { x: 5, y: 10.4 }; + let p2 = Point { x: "Hello", y: 'c' }; + + let p3 = p1.mixup(p2); + + println!("p3.x = {}, p3.y = {}", p3.x, p3.y); +} +``` + +Listing 10-11: A method that uses different generic types from its struct’s +definition + +In `main`, we’ve defined a `Point` that has an `i32` for `x` (with value `5`) +and an `f64` for `y` (with value `10.4`). The `p2` variable is a `Point` struct +that has a string slice for `x` (with value `"Hello"`) and a `char` for `y` +(with value `c`). Calling `mixup` on `p1` with the argument `p2` gives us `p3`, +which will have an `i32` for `x`, because `x` came from `p1`. The `p3` variable +will have a `char` for `y`, because `y` came from `p2`. The `println!` macro +call will print `p3.x = 5, p3.y = c`. + +The purpose of this example is to demonstrate a situation in which some generic +parameters are declared with `impl` and some are declared with the method +definition. Here, the generic parameters `X1` and `Y1` are declared after +`impl` because they go with the struct definition. The generic parameters `X2` +and `Y2` are declared after `fn mixup`, because they’re only relevant to the +method. + +### Performance of Code Using Generics + +You might be wondering whether there is a runtime cost when you’re using +generic type parameters. The good news is that Rust implements generics in such +a way that your code doesn’t run any slower using generic types than it would +with concrete types. + +Rust accomplishes this by performing monomorphization of the code that is using +generics at compile time. *Monomorphization* is the process of turning generic +code into specific code by filling in the concrete types that are used when +compiled. + +In this process, the compiler does the opposite of the steps we used to create +the generic function in Listing 10-5: the compiler looks at all the places +where generic code is called and generates code for the concrete types the +generic code is called with. + +Let’s look at how this works with an example that uses the standard library’s +`Option` enum: + +``` +let integer = Some(5); +let float = Some(5.0); +``` + +When Rust compiles this code, it performs monomorphization. During that +process, the compiler reads the values that have been used in `Option` +instances and identifies two kinds of `Option`: one is `i32` and the other +is `f64`. As such, it expands the generic definition of `Option` into +`Option_i32` and `Option_f64`, thereby replacing the generic definition with +the specific ones. + +The monomorphized version of the code looks like the following. The generic +`Option` is replaced with the specific definitions created by the compiler: + +Filename: src/main.rs + +``` +enum Option_i32 { + Some(i32), + None, +} + +enum Option_f64 { + Some(f64), + None, +} + +fn main() { + let integer = Option_i32::Some(5); + let float = Option_f64::Some(5.0); +} +``` + +Because Rust compiles generic code into code that specifies the type in each +instance, we pay no runtime cost for using generics. When the code runs, it +performs just as it would if we had duplicated each definition by hand. The +process of monomorphization makes Rust’s generics extremely efficient at +runtime. + +## Traits: Defining Shared Behavior + +A *trait* tells the Rust compiler about functionality a particular type has and +can share with other types. We can use traits to define shared behavior in an +abstract way. We can use trait bounds to specify that a generic type can be any +type that has certain behavior. + +> Note: Traits are similar to a feature often called *interfaces* in other +> languages, although with some differences. + +### Defining a Trait + +A type’s behavior consists of the methods we can call on that type. Different +types share the same behavior if we can call the same methods on all of those +types. Trait definitions are a way to group method signatures together to +define a set of behaviors necessary to accomplish some purpose. + +For example, let’s say we have multiple structs that hold various kinds and +amounts of text: a `NewsArticle` struct that holds a news story filed in a +particular location and a `Tweet` that can have at most 280 characters along +with metadata that indicates whether it was a new tweet, a retweet, or a reply +to another tweet. + +We want to make a media aggregator library crate named `aggregator` that can +display summaries of data that might be stored in a `NewsArticle` or `Tweet` +instance. To do this, we need a summary from each type, and we’ll request +that summary by calling a `summarize` method on an instance. Listing 10-12 +shows the definition of a public `Summary` trait that expresses this behavior. + +Filename: src/lib.rs + +``` +pub trait Summary { + fn summarize(&self) -> String; +} +``` + +Listing 10-12: A `Summary` trait that consists of the behavior provided by a +`summarize` method + +Here, we declare a trait using the `trait` keyword and then the trait’s name, +which is `Summary` in this case. We’ve also declared the trait as `pub` so that +crates depending on this crate can make use of this trait too, as we’ll see in +a few examples. Inside the curly brackets, we declare the method signatures +that describe the behaviors of the types that implement this trait, which in +this case is `fn summarize(&self) -> String`. + +After the method signature, instead of providing an implementation within curly +brackets, we use a semicolon. Each type implementing this trait must provide +its own custom behavior for the body of the method. The compiler will enforce +that any type that has the `Summary` trait will have the method `summarize` +defined with this signature exactly. + +A trait can have multiple methods in its body: the method signatures are listed +one per line and each line ends in a semicolon. + +### Implementing a Trait on a Type + +Now that we’ve defined the desired signatures of the `Summary` trait’s methods, +we can implement it on the types in our media aggregator. Listing 10-13 shows +an implementation of the `Summary` trait on the `NewsArticle` struct that uses +the headline, the author, and the location to create the return value of +`summarize`. For the `Tweet` struct, we define `summarize` as the username +followed by the entire text of the tweet, assuming that tweet content is +already limited to 280 characters. + +Filename: src/lib.rs + +``` +pub struct NewsArticle { + pub headline: String, + pub location: String, + pub author: String, + pub content: String, +} + +impl Summary for NewsArticle { + fn summarize(&self) -> String { + format!("{}, by {} ({})", self.headline, self.author, self.location) + } +} + +pub struct Tweet { + pub username: String, + pub content: String, + pub reply: bool, + pub retweet: bool, +} + +impl Summary for Tweet { + fn summarize(&self) -> String { + format!("{}: {}", self.username, self.content) + } +} +``` + +Listing 10-13: Implementing the `Summary` trait on the `NewsArticle` and +`Tweet` types + +Implementing a trait on a type is similar to implementing regular methods. The +difference is that after `impl`, we put the trait name that we want to +implement, then use the `for` keyword, and then specify the name of the type we +want to implement the trait for. Within the `impl` block, we put the method +signatures that the trait definition has defined. Instead of adding a semicolon +after each signature, we use curly brackets and fill in the method body with +the specific behavior that we want the methods of the trait to have for the +particular type. + +Now that the library has implemented the `Summary` trait on `NewsArticle` and +`Tweet`, users of the crate can call the trait methods on instances of +`NewsArticle` and `Tweet` in the same way we call regular methods. The only +difference is that the trait has to be brought into scope as well as the types +to get the additional trait methods. Here’s an example of how a binary crate +could use our `aggregator` library crate: + +``` +use aggregator::{Summary, Tweet}; + +fn main() { + let tweet = Tweet { + username: String::from("horse_ebooks"), + content: String::from( + "of course, as you probably already know, people", + ), + reply: false, + retweet: false, + }; + + println!("1 new tweet: {}", tweet.summarize()); +} +``` + +This code prints `1 new tweet: horse_ebooks: of course, as you probably already +know, people`. + +Other crates that depend on the `aggregator` crate can also bring the `Summary` +trait into scope to implement the trait on their own types. One restriction to +note with trait implementations is that we can implement a trait on a type only +if at least one of the trait or the type is local to our crate. For example, we +can implement standard library traits like `Display` on a custom type like +`Tweet` as part of our `aggregator` crate functionality, because the type +`Tweet` is local to our `aggregator` crate. We can also implement `Summary` on +`Vec` in our `aggregator` crate, because the trait `Summary` is local to our +`aggregator` crate. + +But we can’t implement external traits on external types. For example, we can’t +implement the `Display` trait on `Vec` within our `aggregator` crate, +because `Display` and `Vec` are defined in the standard library and aren’t +local to our `aggregator` crate. This restriction is part of a property of +programs called *coherence*, and more specifically the *orphan rule*, so named +because the parent type is not present. This rule ensures that other people’s +code can’t break your code and vice versa. Without the rule, two crates could +implement the same trait for the same type, and Rust wouldn’t know which +implementation to use. + +### Default Implementations + +Sometimes it’s useful to have default behavior for some or all of the methods +in a trait instead of requiring implementations for all methods on every type. +Then, as we implement the trait on a particular type, we can keep or override +each method’s default behavior. + +Listing 10-14 shows how to specify a default string for the `summarize` method +of the `Summary` trait instead of only defining the method signature, as we did +in Listing 10-12. + +Filename: src/lib.rs + +``` +pub trait Summary { + fn summarize(&self) -> String { + String::from("(Read more...)") + } +} +``` + +Listing 10-14: Definition of a `Summary` trait with a default implementation of +the `summarize` method + +To use a default implementation to summarize instances of `NewsArticle` instead +of defining a custom implementation, we specify an empty `impl` block with +`impl Summary for NewsArticle {}`. + +Even though we’re no longer defining the `summarize` method on `NewsArticle` +directly, we’ve provided a default implementation and specified that +`NewsArticle` implements the `Summary` trait. As a result, we can still call +the `summarize` method on an instance of `NewsArticle`, like this: + +``` +let article = NewsArticle { + headline: String::from("Penguins win the Stanley Cup Championship!"), + location: String::from("Pittsburgh, PA, USA"), + author: String::from("Iceburgh"), + content: String::from( + "The Pittsburgh Penguins once again are the best \ + hockey team in the NHL.", + ), +}; + +println!("New article available! {}", article.summarize()); +``` + +This code prints `New article available! (Read more...)`. + +Creating a default implementation for `summarize` doesn’t require us to change +anything about the implementation of `Summary` on `Tweet` in Listing 10-13. The +reason is that the syntax for overriding a default implementation is the same +as the syntax for implementing a trait method that doesn’t have a default +implementation. + +Default implementations can call other methods in the same trait, even if those +other methods don’t have a default implementation. In this way, a trait can +provide a lot of useful functionality and only require implementors to specify +a small part of it. For example, we could define the `Summary` trait to have a +`summarize_author` method whose implementation is required, and then define a +`summarize` method that has a default implementation that calls the +`summarize_author` method: + +``` +pub trait Summary { + fn summarize_author(&self) -> String; + + fn summarize(&self) -> String { + format!("(Read more from {}...)", self.summarize_author()) + } +} +``` + +To use this version of `Summary`, we only need to define `summarize_author` +when we implement the trait on a type: + +``` +impl Summary for Tweet { + fn summarize_author(&self) -> String { + format!("@{}", self.username) + } +} +``` + +After we define `summarize_author`, we can call `summarize` on instances of the +`Tweet` struct, and the default implementation of `summarize` will call the +definition of `summarize_author` that we’ve provided. Because we’ve implemented +`summarize_author`, the `Summary` trait has given us the behavior of the +`summarize` method without requiring us to write any more code. + +``` +let tweet = Tweet { + username: String::from("horse_ebooks"), + content: String::from( + "of course, as you probably already know, people", + ), + reply: false, + retweet: false, +}; + +println!("1 new tweet: {}", tweet.summarize()); +``` + +This code prints `1 new tweet: (Read more from @horse_ebooks...)`. + +Note that it isn’t possible to call the default implementation from an +overriding implementation of that same method. + +### Traits as Parameters + +Now that you know how to define and implement traits, we can explore how to use +traits to define functions that accept many different types. + +For example, in Listing 10-13, we implemented the `Summary` trait on the +`NewsArticle` and `Tweet` types. We can define a `notify` function that calls +the `summarize` method on its `item` parameter, which is of some type that +implements the `Summary` trait. To do this, we can use the `impl Trait` +syntax, like this: + +``` +pub fn notify(item: &impl Summary) { + println!("Breaking news! {}", item.summarize()); +} +``` + +Instead of a concrete type for the `item` parameter, we specify the `impl` +keyword and the trait name. This parameter accepts any type that implements the +specified trait. In the body of `notify`, we can call any methods on `item` +that come from the `Summary` trait, such as `summarize`. We can call `notify` +and pass in any instance of `NewsArticle` or `Tweet`. Code that calls the +function with any other type, such as a `String` or an `i32`, won’t compile +because those types don’t implement `Summary`. + +#### Trait Bound Syntax + +The `impl Trait` syntax works for straightforward cases but is actually +syntax sugar for a longer form, which is called a *trait bound*; it looks like +this: + +``` +pub fn notify(item: &T) { + println!("Breaking news! {}", item.summarize()); +} +``` + +This longer form is equivalent to the example in the previous section but is +more verbose. We place trait bounds with the declaration of the generic type +parameter after a colon and inside angle brackets. + +The `impl Trait` syntax is convenient and makes for more concise code in simple +cases. The trait bound syntax can express more complexity in other cases. For +example, we can have two parameters that implement `Summary`. Using the `impl +Trait` syntax looks like this: + +``` +pub fn notify(item1: &impl Summary, item2: &impl Summary) { +``` + +If we wanted this function to allow `item1` and `item2` to have different +types, using `impl Trait` would be appropriate (as long as both types implement +`Summary`). If we wanted to force both parameters to have the same type, that’s +only possible to express using a trait bound, like this: + +``` +pub fn notify(item1: &T, item2: &T) { +``` + +The generic type `T` specified as the type of the `item1` and `item2` +parameters constrains the function such that the concrete type of the value +passed as an argument for `item1` and `item2` must be the same. + +#### Specifying Multiple Trait Bounds with the `+` Syntax + +We can also specify more than one trait bound. Say we wanted `notify` to use +display formatting on `item` as well as the `summarize` method: we specify in +the `notify` definition that `item` must implement both `Display` and +`Summary`. We can do so using the `+` syntax: + +``` +pub fn notify(item: &(impl Summary + Display)) { +``` + +The `+` syntax is also valid with trait bounds on generic types: + +``` +pub fn notify(item: &T) { +``` + +With the two trait bounds specified, the body of `notify` can call `summarize` +and use `{}` to format `item`. + +#### Clearer Trait Bounds with `where` Clauses + +Using too many trait bounds has its downsides. Each generic has its own trait +bounds, so functions with multiple generic type parameters can contain lots of +trait bound information between the function’s name and its parameter list, +making the function signature hard to read. For this reason, Rust has alternate +syntax for specifying trait bounds inside a `where` clause after the function +signature. So instead of writing this: + +``` +fn some_function(t: &T, u: &U) -> i32 { +``` + +we can use a `where` clause, like this: + +``` +fn some_function(t: &T, u: &U) -> i32 + where T: Display + Clone, + U: Clone + Debug +{ +``` + +This function’s signature is less cluttered: the function name, parameter list, +and return type are close together, similar to a function without lots of trait +bounds. + +### Returning Types that Implement Traits + +We can also use the `impl Trait` syntax in the return position to return a +value of some type that implements a trait, as shown here: + +``` +fn returns_summarizable() -> impl Summary { + Tweet { + username: String::from("horse_ebooks"), + content: String::from( + "of course, as you probably already know, people", + ), + reply: false, + retweet: false, + } +} +``` + +By using `impl Summary` for the return type, we specify that the +`returns_summarizable` function returns some type that implements the `Summary` +trait without naming the concrete type. In this case, `returns_summarizable` +returns a `Tweet`, but the code calling this function doesn’t know that. + +The ability to return a type that is only specified by the trait it implements +is especially useful in the context of closures and iterators, which we cover +in Chapter 13. Closures and iterators create types that only the compiler knows +or types that are very long to specify. The `impl Trait` syntax lets you +concisely specify that a function returns some type that implements the +`Iterator` trait without needing to write out a very long type. + +However, you can only use `impl Trait` if you’re returning a single type. For +example, this code that returns either a `NewsArticle` or a `Tweet` with the +return type specified as `impl Summary` wouldn’t work: + +``` +fn returns_summarizable(switch: bool) -> impl Summary { + if switch { + NewsArticle { + headline: String::from( + "Penguins win the Stanley Cup Championship!", + ), + location: String::from("Pittsburgh, PA, USA"), + author: String::from("Iceburgh"), + content: String::from( + "The Pittsburgh Penguins once again are the best \ + hockey team in the NHL.", + ), + } + } else { + Tweet { + username: String::from("horse_ebooks"), + content: String::from( + "of course, as you probably already know, people", + ), + reply: false, + retweet: false, + } + } +} +``` + +Returning either a `NewsArticle` or a `Tweet` isn’t allowed due to restrictions +around how the `impl Trait` syntax is implemented in the compiler. We’ll cover +how to write a function with this behavior in the “Using Trait Objects That +Allow for Values of Different +Types” section of Chapter 17. + +### Fixing the `largest` Function with Trait Bounds + +Now that you know how to specify the behavior you want to use using the generic +type parameter’s bounds, let’s return to Listing 10-5 to fix the definition of +the `largest` function that uses a generic type parameter! Last time we tried +to run that code, we received this error: + +``` +error[E0369]: binary operation `>` cannot be applied to type `T` + --> src/main.rs:5:17 + | +5 | if item > largest { + | ---- ^ ------- T + | | + | T + | +help: consider restricting type parameter `T` + | +1 | fn largest(list: &[T]) -> T { + | ^^^^^^^^^^^^^^^^^^^^^^ +``` + +In the body of `largest` we wanted to compare two values of type `T` using the +greater than (`>`) operator. Because that operator is defined as a default +method on the standard library trait `std::cmp::PartialOrd`, we need to specify +`PartialOrd` in the trait bounds for `T` so the `largest` function can work on +slices of any type that we can compare. We don’t need to bring `PartialOrd` +into scope because it’s in the prelude. Change the signature of `largest` to +look like this: + +``` +fn largest(list: &[T]) -> T { +``` + +This time when we compile the code, we get a different set of errors: + +``` +error[E0508]: cannot move out of type `[T]`, a non-copy slice + --> src/main.rs:2:23 + | +2 | let mut largest = list[0]; + | ^^^^^^^ + | | + | cannot move out of here + | move occurs because `list[_]` has type `T`, which does not implement the `Copy` trait + | help: consider borrowing here: `&list[0]` + +error[E0507]: cannot move out of a shared reference + --> src/main.rs:4:18 + | +4 | for &item in list { + | ----- ^^^^ + | || + | |data moved here + | |move occurs because `item` has type `T`, which does not implement the `Copy` trait + | help: consider removing the `&`: `item` +``` + +The key line in this error is `cannot move out of type [T], a non-copy slice`. +With our non-generic versions of the `largest` function, we were only trying to +find the largest `i32` or `char`. As discussed in the “Stack-Only Data: Copy” +section in Chapter 4, types like `i32` and `char` that have a known size can be +stored on the stack, so they implement the `Copy` trait. But when we made the +`largest` function generic, it became possible for the `list` parameter to have +types in it that don’t implement the `Copy` trait. Consequently, we wouldn’t be +able to move the value out of `list[0]` and into the `largest` variable, +resulting in this error. + +To call this code with only those types that implement the `Copy` trait, we can +add `Copy` to the trait bounds of `T`! Listing 10-15 shows the complete code of +a generic `largest` function that will compile as long as the types of the +values in the slice that we pass into the function implement the `PartialOrd` +*and* `Copy` traits, like `i32` and `char` do. + +Filename: src/main.rs + +``` +fn largest(list: &[T]) -> T { + let mut largest = list[0]; + + for &item in list { + if item > largest { + largest = item; + } + } + + largest +} + +fn main() { + let number_list = vec![34, 50, 25, 100, 65]; + + let result = largest(&number_list); + println!("The largest number is {}", result); + + let char_list = vec!['y', 'm', 'a', 'q']; + + let result = largest(&char_list); + println!("The largest char is {}", result); +} +``` + +Listing 10-15: A working definition of the `largest` function that works on any +generic type that implements the `PartialOrd` and `Copy` traits + +If we don’t want to restrict the `largest` function to the types that implement +the `Copy` trait, we could specify that `T` has the trait bound `Clone` instead +of `Copy`. Then we could clone each value in the slice when we want the +`largest` function to have ownership. Using the `clone` function means we’re +potentially making more heap allocations in the case of types that own heap +data like `String`, and heap allocations can be slow if we’re working with +large amounts of data. + +Another way we could implement `largest` is for the function to return a +reference to a `T` value in the slice. If we change the return type to `&T` +instead of `T`, thereby changing the body of the function to return a +reference, we wouldn’t need the `Clone` or `Copy` trait bounds and we could +avoid heap allocations. Try implementing these alternate solutions on your own! +If you get stuck with errors having to do with lifetimes, keep reading: the +“Validating References with Lifetimes” section coming up will explain, but +lifetimes aren’t required to solve these challenges. + +### Using Trait Bounds to Conditionally Implement Methods + +By using a trait bound with an `impl` block that uses generic type parameters, +we can implement methods conditionally for types that implement the specified +traits. For example, the type `Pair` in Listing 10-16 always implements the +`new` function to return a new instance of `Pair` (recall from the ”Defining +Methods” section of Chapter 5 that `Self` is a type alias for the type of the +`impl` block, which in this case is `Pair`). But in the next `impl` block, +`Pair` only implements the `cmp_display` method if its inner type `T` +implements the `PartialOrd` trait that enables comparison *and* the `Display` +trait that enables printing. + +Filename: src/lib.rs + +``` +use std::fmt::Display; + +struct Pair { + x: T, + y: T, +} + +impl Pair { + fn new(x: T, y: T) -> Self { + Self { x, y } + } +} + +impl Pair { + fn cmp_display(&self) { + if self.x >= self.y { + println!("The largest member is x = {}", self.x); + } else { + println!("The largest member is y = {}", self.y); + } + } +} +``` + +Listing 10-16: Conditionally implement methods on a generic type depending on +trait bounds + +We can also conditionally implement a trait for any type that implements +another trait. Implementations of a trait on any type that satisfies the trait +bounds are called *blanket implementations* and are extensively used in the +Rust standard library. For example, the standard library implements the +`ToString` trait on any type that implements the `Display` trait. The `impl` +block in the standard library looks similar to this code: + +``` +impl ToString for T { + // --snip-- +} +``` + +Because the standard library has this blanket implementation, we can call the +`to_string` method defined by the `ToString` trait on any type that implements +the `Display` trait. For example, we can turn integers into their corresponding +`String` values like this because integers implement `Display`: + +``` +let s = 3.to_string(); +``` + +Blanket implementations appear in the documentation for the trait in the +“Implementors” section. + +Traits and trait bounds let us write code that uses generic type parameters to +reduce duplication but also specify to the compiler that we want the generic +type to have particular behavior. The compiler can then use the trait bound +information to check that all the concrete types used with our code provide the +correct behavior. In dynamically typed languages, we would get an error at +runtime if we called a method on a type which didn’t define the method. But Rust +moves these errors to compile time so we’re forced to fix the problems before +our code is even able to run. Additionally, we don’t have to write code that +checks for behavior at runtime because we’ve already checked at compile time. +Doing so improves performance without having to give up the flexibility of +generics. + +Another kind of generic that we’ve already been using is called *lifetimes*. +Rather than ensuring that a type has the behavior we want, lifetimes ensure +that references are valid as long as we need them to be. Let’s look at how +lifetimes do that. + +## Validating References with Lifetimes + +One detail we didn’t discuss in the “References and Borrowing” section in +Chapter 4 is that every reference in Rust has a *lifetime*, which is the scope +for which that reference is valid. Most of the time, lifetimes are implicit and +inferred, just like most of the time, types are inferred. We must annotate +types when multiple types are possible. In a similar way, we must annotate +lifetimes when the lifetimes of references could be related in a few different +ways. Rust requires us to annotate the relationships using generic lifetime +parameters to ensure the actual references used at runtime will definitely be +valid. + +Annotating lifetimes is not even a concept most other programming languages +have, so this is going to feel unfamiliar. Although we won’t cover lifetimes in +their entirety in this chapter, we’ll discuss common ways you might encounter +lifetime syntax so you can get introduced to the concept. + +### Preventing Dangling References with Lifetimes + +The main aim of lifetimes is to prevent dangling references, which cause a +program to reference data other than the data it’s intended to reference. +Consider the program in Listing 10-17, which has an outer scope and an inner +scope. + +``` +{ + let r; + + { + let x = 5; + r = &x; + } + + println!("r: {}", r); +} +``` + +Listing 10-17: An attempt to use a reference whose value has gone out of scope + +> Note: The examples in Listings 10-17, 10-18, and 10-24 declare variables +> without giving them an initial value, so the variable name exists in the +> outer scope. At first glance, this might appear to be in conflict with Rust’s +> having no null values. However, if we try to use a variable before giving it +> a value, we’ll get a compile-time error, which shows that Rust indeed does +> not allow null values. + +The outer scope declares a variable named `r` with no initial value, and the +inner scope declares a variable named `x` with the initial value of 5. Inside +the inner scope, we attempt to set the value of `r` as a reference to `x`. Then +the inner scope ends, and we attempt to print the value in `r`. This code won’t +compile because the value `r` is referring to has gone out of scope before we +try to use it. Here is the error message: + +``` +error[E0597]: `x` does not live long enough + --> src/main.rs:7:17 + | +7 | r = &x; + | ^^ borrowed value does not live long enough +8 | } + | - `x` dropped here while still borrowed +9 | +10 | println!("r: {}", r); + | - borrow later used here +``` + +The variable `x` doesn’t “live long enough.” The reason is that `x` will be out +of scope when the inner scope ends on line 7. But `r` is still valid for the +outer scope; because its scope is larger, we say that it “lives longer.” If +Rust allowed this code to work, `r` would be referencing memory that was +deallocated when `x` went out of scope, and anything we tried to do with `r` +wouldn’t work correctly. So how does Rust determine that this code is invalid? +It uses a borrow checker. + +### The Borrow Checker + +The Rust compiler has a *borrow checker* that compares scopes to determine +whether all borrows are valid. Listing 10-18 shows the same code as Listing +10-17 but with annotations showing the lifetimes of the variables. + +``` +{ + let r; // ---------+-- 'a + // | + { // | + let x = 5; // -+-- 'b | + r = &x; // | | + } // -+ | + // | + println!("r: {}", r); // | +} // ---------+ +``` + +Listing 10-18: Annotations of the lifetimes of `r` and `x`, named `'a` and +`'b`, respectively + +Here, we’ve annotated the lifetime of `r` with `'a` and the lifetime of `x` +with `'b`. As you can see, the inner `'b` block is much smaller than the outer +`'a` lifetime block. At compile time, Rust compares the size of the two +lifetimes and sees that `r` has a lifetime of `'a` but that it refers to memory +with a lifetime of `'b`. The program is rejected because `'b` is shorter than +`'a`: the subject of the reference doesn’t live as long as the reference. + +Listing 10-19 fixes the code so it doesn’t have a dangling reference and +compiles without any errors. + +``` +{ + let x = 5; // ----------+-- 'b + // | + let r = &x; // --+-- 'a | + // | | + println!("r: {}", r); // | | + // --+ | +} // ----------+ +``` + +Listing 10-19: A valid reference because the data has a longer lifetime than +the reference + +Here, `x` has the lifetime `'b`, which in this case is larger than `'a`. This +means `r` can reference `x` because Rust knows that the reference in `r` will +always be valid while `x` is valid. + +Now that you know where the lifetimes of references are and how Rust analyzes +lifetimes to ensure references will always be valid, let’s explore generic +lifetimes of parameters and return values in the context of functions. + +### Generic Lifetimes in Functions + +Let’s write a function that returns the longer of two string slices. This +function will take two string slices and return a string slice. After we’ve +implemented the `longest` function, the code in Listing 10-20 should print `The +longest string is abcd`. + +Filename: src/main.rs + +``` +fn main() { + let string1 = String::from("abcd"); + let string2 = "xyz"; + + let result = longest(string1.as_str(), string2); + println!("The longest string is {}", result); +} +``` + +Listing 10-20: A `main` function that calls the `longest` function to find the +longer of two string slices + +Note that we want the function to take string slices, which are references, +because we don’t want the `longest` function to take ownership of its +parameters. Refer to the “String Slices as +Parameters” section in Chapter 4 +for more discussion about why the parameters we use in Listing 10-20 are the +ones we want. + +If we try to implement the `longest` function as shown in Listing 10-21, it +won’t compile. + +Filename: src/main.rs + +``` +fn longest(x: &str, y: &str) -> &str { + if x.len() > y.len() { + x + } else { + y + } +} +``` + +Listing 10-21: An implementation of the `longest` function that returns the +longer of two string slices but does not yet compile + +Instead, we get the following error that talks about lifetimes: + +``` +error[E0106]: missing lifetime specifier + --> src/main.rs:9:33 + | +9 | fn longest(x: &str, y: &str) -> &str { + | ---- ---- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y` +help: consider introducing a named lifetime parameter + | +9 | fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { + | ^^^^ ^^^^^^^ ^^^^^^^ ^^^ +``` + +The help text reveals that the return type needs a generic lifetime parameter +on it because Rust can’t tell whether the reference being returned refers to +`x` or `y`. Actually, we don’t know either, because the `if` block in the body +of this function returns a reference to `x` and the `else` block returns a +reference to `y`! + +When we’re defining this function, we don’t know the concrete values that will +be passed into this function, so we don’t know whether the `if` case or the +`else` case will execute. We also don’t know the concrete lifetimes of the +references that will be passed in, so we can’t look at the scopes as we did in +Listings 10-18 and 10-19 to determine whether the reference we return will +always be valid. The borrow checker can’t determine this either, because it +doesn’t know how the lifetimes of `x` and `y` relate to the lifetime of the +return value. To fix this error, we’ll add generic lifetime parameters that +define the relationship between the references so the borrow checker can +perform its analysis. + +### Lifetime Annotation Syntax + +Lifetime annotations don’t change how long any of the references live. Just +as functions can accept any type when the signature specifies a generic type +parameter, functions can accept references with any lifetime by specifying a +generic lifetime parameter. Lifetime annotations describe the relationships of +the lifetimes of multiple references to each other without affecting the +lifetimes. + +Lifetime annotations have a slightly unusual syntax: the names of lifetime +parameters must start with an apostrophe (`'`) and are usually all lowercase and +very short, like generic types. Most people use the name `'a`. We place +lifetime parameter annotations after the `&` of a reference, using a space to +separate the annotation from the reference’s type. + +Here are some examples: a reference to an `i32` without a lifetime parameter, a +reference to an `i32` that has a lifetime parameter named `'a`, and a mutable +reference to an `i32` that also has the lifetime `'a`. + +``` +&i32 // a reference +&'a i32 // a reference with an explicit lifetime +&'a mut i32 // a mutable reference with an explicit lifetime +``` + +One lifetime annotation by itself doesn’t have much meaning, because the +annotations are meant to tell Rust how generic lifetime parameters of multiple +references relate to each other. For example, let’s say we have a function with +the parameter `first` that is a reference to an `i32` with lifetime `'a`. The +function also has another parameter named `second` that is another reference to +an `i32` that also has the lifetime `'a`. The lifetime annotations indicate +that the references `first` and `second` must both live as long as that generic +lifetime. + +### Lifetime Annotations in Function Signatures + +Now let’s examine lifetime annotations in the context of the `longest` +function. As with generic type parameters, we need to declare generic lifetime +parameters inside angle brackets between the function name and the parameter +list. The constraint we want to express in this signature is that the lifetimes +of both of the parameters and the lifetime of the returned reference are +related such that the returned reference will be valid as long as both the +parameters are. We’ll name the lifetime `'a` and then add it to each reference, +as shown in Listing 10-22. + +Filename: src/main.rs + +``` +fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { + if x.len() > y.len() { + x + } else { + y + } +} +``` + +Listing 10-22: The `longest` function definition specifying that all the +references in the signature must have the same lifetime `'a` + +This code should compile and produce the result we want when we use it with the +`main` function in Listing 10-20. + +The function signature now tells Rust that for some lifetime `'a`, the function +takes two parameters, both of which are string slices that live at least as +long as lifetime `'a`. The function signature also tells Rust that the string +slice returned from the function will live at least as long as lifetime `'a`. +In practice, it means that the lifetime of the reference returned by the +`longest` function is the same as the smaller of the lifetimes of the +references passed in. These relationships are what we want Rust to use when +analyzing this code. + +Remember, when we specify the lifetime parameters in this function signature, +we’re not changing the lifetimes of any values passed in or returned. Rather, +we’re specifying that the borrow checker should reject any values that don’t +adhere to these constraints. Note that the `longest` function doesn’t need to +know exactly how long `x` and `y` will live, only that some scope can be +substituted for `'a` that will satisfy this signature. + +When annotating lifetimes in functions, the annotations go in the function +signature, not in the function body. The lifetime annotations become part of +the contract of the function, much like the types in the signature are. Having +function signatures contain the lifetime contract means the analysis the Rust +compiler does can be simpler. If there’s a problem with the way a function is +annotated or the way it is called, the compiler errors can point to the part of +our code and the constraints more precisely. If, instead, the Rust compiler +made more inferences about what we intended the relationships of the lifetimes +to be, the compiler might only be able to point to a use of our code many steps +away from the cause of the problem. + +When we pass concrete references to `longest`, the concrete lifetime that is +substituted for `'a` is the part of the scope of `x` that overlaps with the +scope of `y`. In other words, the generic lifetime `'a` will get the concrete +lifetime that is equal to the smaller of the lifetimes of `x` and `y`. Because +we’ve annotated the returned reference with the same lifetime parameter `'a`, +the returned reference will also be valid for the length of the smaller of the +lifetimes of `x` and `y`. + +Let’s look at how the lifetime annotations restrict the `longest` function by +passing in references that have different concrete lifetimes. Listing 10-23 is +a straightforward example. + +Filename: src/main.rs + +``` +fn main() { + let string1 = String::from("long string is long"); + + { + let string2 = String::from("xyz"); + let result = longest(string1.as_str(), string2.as_str()); + println!("The longest string is {}", result); + } +} +``` + +Listing 10-23: Using the `longest` function with references to `String` values +that have different concrete lifetimes + +In this example, `string1` is valid until the end of the outer scope, `string2` +is valid until the end of the inner scope, and `result` references something +that is valid until the end of the inner scope. Run this code, and you’ll see +that the borrow checker approves of this code; it will compile and print `The +longest string is long string is long`. + +Next, let’s try an example that shows that the lifetime of the reference in +`result` must be the smaller lifetime of the two arguments. We’ll move the +declaration of the `result` variable outside the inner scope but leave the +assignment of the value to the `result` variable inside the scope with +`string2`. Then we’ll move the `println!` that uses `result` outside the inner +scope, after the inner scope has ended. The code in Listing 10-24 will not +compile. + +Filename: src/main.rs + +``` +fn main() { + let string1 = String::from("long string is long"); + let result; + { + let string2 = String::from("xyz"); + result = longest(string1.as_str(), string2.as_str()); + } + println!("The longest string is {}", result); +} +``` + +Listing 10-24: Attempting to use `result` after `string2` has gone out of scope + +When we try to compile this code, we’ll get this error: + +``` +error[E0597]: `string2` does not live long enough + --> src/main.rs:6:44 + | +6 | result = longest(string1.as_str(), string2.as_str()); + | ^^^^^^^ borrowed value does not live long enough +7 | } + | - `string2` dropped here while still borrowed +8 | println!("The longest string is {}", result); + | ------ borrow later used here +``` + +The error shows that for `result` to be valid for the `println!` statement, +`string2` would need to be valid until the end of the outer scope. Rust knows +this because we annotated the lifetimes of the function parameters and return +values using the same lifetime parameter `'a`. + +As humans, we can look at this code and see that `string1` is longer than +`string2` and therefore `result` will contain a reference to `string1`. +Because `string1` has not gone out of scope yet, a reference to `string1` will +still be valid for the `println!` statement. However, the compiler can’t see +that the reference is valid in this case. We’ve told Rust that the lifetime of +the reference returned by the `longest` function is the same as the smaller of +the lifetimes of the references passed in. Therefore, the borrow checker +disallows the code in Listing 10-24 as possibly having an invalid reference. + +Try designing more experiments that vary the values and lifetimes of the +references passed in to the `longest` function and how the returned reference +is used. Make hypotheses about whether or not your experiments will pass the +borrow checker before you compile; then check to see if you’re right! + +### Thinking in Terms of Lifetimes + +The way in which you need to specify lifetime parameters depends on what your +function is doing. For example, if we changed the implementation of the +`longest` function to always return the first parameter rather than the longest +string slice, we wouldn’t need to specify a lifetime on the `y` parameter. The +following code will compile: + +Filename: src/main.rs + +``` +fn longest<'a>(x: &'a str, y: &str) -> &'a str { + x +} +``` + +In this example, we’ve specified a lifetime parameter `'a` for the parameter +`x` and the return type, but not for the parameter `y`, because the lifetime of +`y` does not have any relationship with the lifetime of `x` or the return value. + +When returning a reference from a function, the lifetime parameter for the +return type needs to match the lifetime parameter for one of the parameters. If +the reference returned does *not* refer to one of the parameters, it must refer +to a value created within this function, which would be a dangling reference +because the value will go out of scope at the end of the function. Consider +this attempted implementation of the `longest` function that won’t compile: + +Filename: src/main.rs + +``` +fn longest<'a>(x: &str, y: &str) -> &'a str { + let result = String::from("really long string"); + result.as_str() +} +``` + +Here, even though we’ve specified a lifetime parameter `'a` for the return +type, this implementation will fail to compile because the return value +lifetime is not related to the lifetime of the parameters at all. Here is the +error message we get: + +``` +error[E0515]: cannot return value referencing local variable `result` + --> src/main.rs:11:5 + | +11 | result.as_str() + | ------^^^^^^^^^ + | | + | returns a value referencing data owned by the current function + | `result` is borrowed here +``` + +The problem is that `result` goes out of scope and gets cleaned up at the end +of the `longest` function. We’re also trying to return a reference to `result` +from the function. There is no way we can specify lifetime parameters that +would change the dangling reference, and Rust won’t let us create a dangling +reference. In this case, the best fix would be to return an owned data type +rather than a reference so the calling function is then responsible for +cleaning up the value. + +Ultimately, lifetime syntax is about connecting the lifetimes of various +parameters and return values of functions. Once they’re connected, Rust has +enough information to allow memory-safe operations and disallow operations that +would create dangling pointers or otherwise violate memory safety. + +### Lifetime Annotations in Struct Definitions + +So far, we’ve only defined structs to hold owned types. It’s possible for +structs to hold references, but in that case we would need to add a lifetime +annotation on every reference in the struct’s definition. Listing 10-25 has a +struct named `ImportantExcerpt` that holds a string slice. + +Filename: src/main.rs + +``` +struct ImportantExcerpt<'a> { + part: &'a str, +} + +fn main() { + let novel = String::from("Call me Ishmael. Some years ago..."); + let first_sentence = novel.split('.').next().expect("Could not find a '.'"); + let i = ImportantExcerpt { + part: first_sentence, + }; +} +``` + +Listing 10-25: A struct that holds a reference, so its definition needs a +lifetime annotation + +This struct has one field, `part`, that holds a string slice, which is a +reference. As with generic data types, we declare the name of the generic +lifetime parameter inside angle brackets after the name of the struct so we can +use the lifetime parameter in the body of the struct definition. This +annotation means an instance of `ImportantExcerpt` can’t outlive the reference +it holds in its `part` field. + +The `main` function here creates an instance of the `ImportantExcerpt` struct +that holds a reference to the first sentence of the `String` owned by the +variable `novel`. The data in `novel` exists before the `ImportantExcerpt` +instance is created. In addition, `novel` doesn’t go out of scope until after +the `ImportantExcerpt` goes out of scope, so the reference in the +`ImportantExcerpt` instance is valid. + +### Lifetime Elision + +You’ve learned that every reference has a lifetime and that you need to specify +lifetime parameters for functions or structs that use references. However, in +Chapter 4 we had a function in Listing 4-9, which is shown again in Listing +10-26, that compiled without lifetime annotations. + +Filename: src/lib.rs + +``` +fn first_word(s: &str) -> &str { + let bytes = s.as_bytes(); + + for (i, &item) in bytes.iter().enumerate() { + if item == b' ' { + return &s[0..i]; + } + } + + &s[..] +} +``` + +Listing 10-26: A function we defined in Listing 4-9 that compiled without +lifetime annotations, even though the parameter and return type are references + +The reason this function compiles without lifetime annotations is historical: +in early versions (pre-1.0) of Rust, this code wouldn’t have compiled because +every reference needed an explicit lifetime. At that time, the function +signature would have been written like this: + +``` +fn first_word<'a>(s: &'a str) -> &'a str { +``` + +After writing a lot of Rust code, the Rust team found that Rust programmers +were entering the same lifetime annotations over and over in particular +situations. These situations were predictable and followed a few deterministic +patterns. The developers programmed these patterns into the compiler’s code so +the borrow checker could infer the lifetimes in these situations and wouldn’t +need explicit annotations. + +This piece of Rust history is relevant because it’s possible that more +deterministic patterns will emerge and be added to the compiler. In the future, +even fewer lifetime annotations might be required. + +The patterns programmed into Rust’s analysis of references are called the +*lifetime elision rules*. These aren’t rules for programmers to follow; they’re +a set of particular cases that the compiler will consider, and if your code +fits these cases, you don’t need to write the lifetimes explicitly. + +The elision rules don’t provide full inference. If Rust deterministically +applies the rules but there is still ambiguity as to what lifetimes the +references have, the compiler won’t guess what the lifetime of the remaining +references should be. In this case, instead of guessing, the compiler will give +you an error that you can resolve by adding the lifetime annotations that +specify how the references relate to each other. + +Lifetimes on function or method parameters are called *input lifetimes*, and +lifetimes on return values are called *output lifetimes*. + +The compiler uses three rules to figure out what lifetimes references have when +there aren’t explicit annotations. The first rule applies to input lifetimes, +and the second and third rules apply to output lifetimes. If the compiler gets +to the end of the three rules and there are still references for which it can’t +figure out lifetimes, the compiler will stop with an error. These rules apply +to `fn` definitions as well as `impl` blocks. + +The first rule is that each parameter that is a reference gets its own lifetime +parameter. In other words, a function with one parameter gets one lifetime +parameter: `fn foo<'a>(x: &'a i32)`; a function with two parameters gets two +separate lifetime parameters: `fn foo<'a, 'b>(x: &'a i32, y: &'b i32)`; and so +on. + +The second rule is if there is exactly one input lifetime parameter, that +lifetime is assigned to all output lifetime parameters: `fn foo<'a>(x: &'a i32) +-> &'a i32`. + +The third rule is if there are multiple input lifetime parameters, but one of +them is `&self` or `&mut self` because this is a method, the lifetime of `self` +is assigned to all output lifetime parameters. This third rule makes methods +much nicer to read and write because fewer symbols are necessary. + +Let’s pretend we’re the compiler. We’ll apply these rules to figure out what +the lifetimes of the references in the signature of the `first_word` function +in Listing 10-26 are. The signature starts without any lifetimes associated +with the references: + +``` +fn first_word(s: &str) -> &str { +``` + +Then the compiler applies the first rule, which specifies that each parameter +gets its own lifetime. We’ll call it `'a` as usual, so now the signature is +this: + +``` +fn first_word<'a>(s: &'a str) -> &str { +``` + +The second rule applies because there is exactly one input lifetime. The second +rule specifies that the lifetime of the one input parameter gets assigned to +the output lifetime, so the signature is now this: + +``` +fn first_word<'a>(s: &'a str) -> &'a str { +``` + +Now all the references in this function signature have lifetimes, and the +compiler can continue its analysis without needing the programmer to annotate +the lifetimes in this function signature. + +Let’s look at another example, this time using the `longest` function that had +no lifetime parameters when we started working with it in Listing 10-21: + +``` +fn longest(x: &str, y: &str) -> &str { +``` + +Let’s apply the first rule: each parameter gets its own lifetime. This time we +have two parameters instead of one, so we have two lifetimes: + +``` +fn longest<'a, 'b>(x: &'a str, y: &'b str) -> &str { +``` + +You can see that the second rule doesn’t apply because there is more than one +input lifetime. The third rule doesn’t apply either, because `longest` is a +function rather than a method, so none of the parameters are `self`. After +working through all three rules, we still haven’t figured out what the return +type’s lifetime is. This is why we got an error trying to compile the code in +Listing 10-21: the compiler worked through the lifetime elision rules but still +couldn’t figure out all the lifetimes of the references in the signature. + +Because the third rule really only applies in method signatures, we’ll look at +lifetimes in that context next to see why the third rule means we don’t have to +annotate lifetimes in method signatures very often. + +### Lifetime Annotations in Method Definitions + +When we implement methods on a struct with lifetimes, we use the same syntax as +that of generic type parameters shown in Listing 10-11. Where we declare and +use the lifetime parameters depends on whether they’re related to the struct +fields or the method parameters and return values. + +Lifetime names for struct fields always need to be declared after the `impl` +keyword and then used after the struct’s name, because those lifetimes are part +of the struct’s type. + +In method signatures inside the `impl` block, references might be tied to the +lifetime of references in the struct’s fields, or they might be independent. In +addition, the lifetime elision rules often make it so that lifetime annotations +aren’t necessary in method signatures. Let’s look at some examples using the +struct named `ImportantExcerpt` that we defined in Listing 10-25. + +First, we’ll use a method named `level` whose only parameter is a reference to +`self` and whose return value is an `i32`, which is not a reference to anything: + +``` +impl<'a> ImportantExcerpt<'a> { + fn level(&self) -> i32 { + 3 + } +} +``` + +The lifetime parameter declaration after `impl` and its use after the type name +are required, but we’re not required to annotate the lifetime of the reference +to `self` because of the first elision rule. + +Here is an example where the third lifetime elision rule applies: + +``` +impl<'a> ImportantExcerpt<'a> { + fn announce_and_return_part(&self, announcement: &str) -> &str { + println!("Attention please: {}", announcement); + self.part + } +} +``` + +There are two input lifetimes, so Rust applies the first lifetime elision rule +and gives both `&self` and `announcement` their own lifetimes. Then, because +one of the parameters is `&self`, the return type gets the lifetime of `&self`, +and all lifetimes have been accounted for. + +### The Static Lifetime + +One special lifetime we need to discuss is `'static`, which means that this +reference *can* live for the entire duration of the program. All string +literals have the `'static` lifetime, which we can annotate as follows: + +``` +let s: &'static str = "I have a static lifetime."; +``` + +The text of this string is stored directly in the program’s binary, which +is always available. Therefore, the lifetime of all string literals is +`'static`. + +You might see suggestions to use the `'static` lifetime in error messages. But +before specifying `'static` as the lifetime for a reference, think about +whether the reference you have actually lives the entire lifetime of your +program or not. You might consider whether you want it to live that long, even +if it could. Most of the time, the problem results from attempting to create a +dangling reference or a mismatch of the available lifetimes. In such cases, the +solution is fixing those problems, not specifying the `'static` lifetime. + +## Generic Type Parameters, Trait Bounds, and Lifetimes Together + +Let’s briefly look at the syntax of specifying generic type parameters, trait +bounds, and lifetimes all in one function! + +``` +use std::fmt::Display; + +fn longest_with_an_announcement<'a, T>( + x: &'a str, + y: &'a str, + ann: T, +) -> &'a str +where + T: Display, +{ + println!("Announcement! {}", ann); + if x.len() > y.len() { + x + } else { + y + } +} +``` + +This is the `longest` function from Listing 10-22 that returns the longer of +two string slices. But now it has an extra parameter named `ann` of the generic +type `T`, which can be filled in by any type that implements the `Display` +trait as specified by the `where` clause. This extra parameter will be printed +using `{}`, which is why the `Display` trait bound is necessary. Because +lifetimes are a type of generic, the declarations of the lifetime parameter +`'a` and the generic type parameter `T` go in the same list inside the angle +brackets after the function name. + +## Summary + +We covered a lot in this chapter! Now that you know about generic type +parameters, traits and trait bounds, and generic lifetime parameters, you’re +ready to write code without repetition that works in many different situations. +Generic type parameters let you apply the code to different types. Traits and +trait bounds ensure that even though the types are generic, they’ll have the +behavior the code needs. You learned how to use lifetime annotations to ensure +that this flexible code won’t have any dangling references. And all of this +analysis happens at compile time, which doesn’t affect runtime performance! + +Believe it or not, there is much more to learn on the topics we discussed in +this chapter: Chapter 17 discusses trait objects, which are another way to use +traits. There are also more complex scenarios involving lifetime annotations +that you will only need in very advanced scenarios; for those, you should read +the Rust Reference at *https://doc.rust-lang.org/reference/trait-bounds.html*. +But next, you’ll learn how to write tests in Rust so you can make sure your +code is working the way it should. diff --git a/src/doc/book/redirects/const-and-static.md b/src/doc/book/redirects/const-and-static.md index 3d09f37dc9..b87bdd3831 100644 --- a/src/doc/book/redirects/const-and-static.md +++ b/src/doc/book/redirects/const-and-static.md @@ -14,7 +14,7 @@ static HELLO_WORLD: &str = "Hello, world!"; --- You can find the latest version about constants -[here](ch03-01-variables-and-mutability.html#differences-between-variables-and-constants), +[here](ch03-01-variables-and-mutability.html#constants), and about statics [here](ch19-01-unsafe-rust.html#accessing-or-modifying-a-mutable-static-variable). diff --git a/src/doc/book/second-edition/src/SUMMARY.md b/src/doc/book/second-edition/src/SUMMARY.md index 1ca086328c..37d703d8ea 100644 --- a/src/doc/book/second-edition/src/SUMMARY.md +++ b/src/doc/book/second-edition/src/SUMMARY.md @@ -49,7 +49,7 @@ - [Error Handling](ch09-00-error-handling.md) - [Unrecoverable Errors with `panic!`](ch09-01-unrecoverable-errors-with-panic.md) - [Recoverable Errors with `Result`](ch09-02-recoverable-errors-with-result.md) - - [To `panic!` or Not To `panic!`](ch09-03-to-panic-or-not-to-panic.md) + - [To `panic!` or Not to `panic!`](ch09-03-to-panic-or-not-to-panic.md) - [Generic Types, Traits, and Lifetimes](ch10-00-generics.md) - [Generic Data Types](ch10-01-syntax.md) diff --git a/src/doc/book/src/SUMMARY.md b/src/doc/book/src/SUMMARY.md index a9b8feb00a..22c11ca78b 100644 --- a/src/doc/book/src/SUMMARY.md +++ b/src/doc/book/src/SUMMARY.md @@ -52,7 +52,7 @@ - [Error Handling](ch09-00-error-handling.md) - [Unrecoverable Errors with `panic!`](ch09-01-unrecoverable-errors-with-panic.md) - [Recoverable Errors with `Result`](ch09-02-recoverable-errors-with-result.md) - - [To `panic!` or Not To `panic!`](ch09-03-to-panic-or-not-to-panic.md) + - [To `panic!` or Not to `panic!`](ch09-03-to-panic-or-not-to-panic.md) - [Generic Types, Traits, and Lifetimes](ch10-00-generics.md) - [Generic Data Types](ch10-01-syntax.md) diff --git a/src/doc/book/src/appendix-06-translation.md b/src/doc/book/src/appendix-06-translation.md index d95ea675e0..af7d614106 100644 --- a/src/doc/book/src/appendix-06-translation.md +++ b/src/doc/book/src/appendix-06-translation.md @@ -17,7 +17,6 @@ For resources in languages other than English. Most are still in progress; see - [日本語](https://github.com/rust-lang-ja/book-ja) - [Français](https://github.com/Jimskapt/rust-book-fr) - [Polski](https://github.com/paytchoo/book-pl) -- [עברית](https://github.com/idanmel/rust-book-heb) - [Cebuano](https://github.com/agentzero1/book) - [Tagalog](https://github.com/josephace135/book) - [Esperanto](https://github.com/psychoslave/Rust-libro) diff --git a/src/doc/book/src/ch01-01-installation.md b/src/doc/book/src/ch01-01-installation.md index 1e3a75df53..bbb24fa963 100644 --- a/src/doc/book/src/ch01-01-installation.md +++ b/src/doc/book/src/ch01-01-installation.md @@ -5,9 +5,9 @@ command line tool for managing Rust versions and associated tools. You’ll need an internet connection for the download. > Note: If you prefer not to use `rustup` for some reason, please see the -> [Other Rust Installation Methods page][install] for more options. +> [Other Rust Installation Methods page][otherinstall] for more options. -[install]: https://forge.rust-lang.org/infra/other-installation-methods.html +[otherinstall]: https://forge.rust-lang.org/infra/other-installation-methods.html The following steps install the latest stable version of the Rust compiler. Rust’s stability guarantees ensure that all the examples in the book that @@ -54,7 +54,7 @@ $ xcode-select --install ``` Linux users should generally install GCC or Clang, according to their -distribution's documentation. For example, if you use Ubuntu, you can install +distribution’s documentation. For example, if you use Ubuntu, you can install the `build-essential` package. ### Installing `rustup` on Windows @@ -64,7 +64,7 @@ the instructions for installing Rust. At some point in the installation, you’l receive a message explaining that you’ll also need the C++ build tools for Visual Studio 2013 or later. The easiest way to acquire the build tools is to install [Build Tools for Visual Studio 2019][visualstudio]. When asked which -workloads to install make sure "C++ build tools" is selected and that the +workloads to install make sure “C++ build tools” is selected and that the Windows 10 SDK and the English language pack components are included. [install]: https://www.rust-lang.org/tools/install diff --git a/src/doc/book/src/ch01-02-hello-world.md b/src/doc/book/src/ch01-02-hello-world.md index 98ba880715..e390768b9c 100644 --- a/src/doc/book/src/ch01-02-hello-world.md +++ b/src/doc/book/src/ch01-02-hello-world.md @@ -126,7 +126,7 @@ Second, `println!` calls a Rust macro. If it called a function instead, it would be entered as `println` (without the `!`). We’ll discuss Rust macros in more detail in Chapter 19. For now, you just need to know that using a `!` means that you’re calling a macro instead of a normal function, and that macros -don't always follow the same rules as functions. +don’t always follow the same rules as functions. Third, you see the `"Hello, world!"` string. We pass this string as an argument to `println!`, and the string is printed to the screen. 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 761dc218a9..234f7a3540 100644 --- a/src/doc/book/src/ch02-00-guessing-game-tutorial.md +++ b/src/doc/book/src/ch02-00-guessing-game-tutorial.md @@ -3,8 +3,9 @@ Let’s jump into Rust by working through a hands-on project together! This chapter introduces you to a few common Rust concepts by showing you how to use them in a real program. You’ll learn about `let`, `match`, methods, associated -functions, using external crates, and more! The following chapters will explore -these ideas in more detail. In this chapter, you’ll practice the fundamentals. +functions, using external crates, and more! In the following chapters, we’ll +explore these ideas in more detail. In this chapter, you’ll practice the +fundamentals. We’ll implement a classic beginner programming problem: a guessing game. Here’s how it works: the program will generate a random integer between 1 and 100. It @@ -74,20 +75,21 @@ prints it This code contains a lot of information, so let’s go over it line by line. To obtain user input and then print the result as output, we need to bring the -`io` (input/output) library into scope. The `io` library comes from the -standard library (which is known as `std`): +`io` input/output library into scope. The `io` library comes from the +standard library, known as `std`: ```rust,ignore {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:io}} ``` -By default, Rust brings only a few types into the scope of every program in -[the *prelude*][prelude]. If a type you want to use isn’t in the -prelude, you have to bring that type into scope explicitly with a `use` -statement. Using the `std::io` library provides you with a number of useful -features, including the ability to accept user input. +By default, Rust has a few items defined in the standard library that it brings +into the scope of every program. This set is called the *prelude*, and you can +see everything in it [in the standard library documentation][prelude]. -[prelude]: ../std/prelude/index.html +If a type you want to use isn’t in the prelude, you have to bring that type +into scope explicitly with a `use` statement. Using the `std::io` library +provides you with a number of useful features, including the ability to accept +user input. As you saw in Chapter 1, the `main` function is the entry point into the program: @@ -111,15 +113,14 @@ from the user. ### Storing Values with Variables -Next, we’ll create a place to store the user input, like this: +Next, we’ll create a *variable* to store the user input, like this: ```rust,ignore {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:string}} ``` Now the program is getting interesting! There’s a lot going on in this little -line. Notice that this is a `let` statement, which is used to create a -*variable*. Here’s another example: +line. We use the `let` statement to create the variable. Here’s another example: ```rust,ignore let apples = 5; @@ -128,8 +129,8 @@ let apples = 5; This line creates a new variable named `apples` and binds it to the value 5. In Rust, variables are immutable by default. We’ll be discussing this concept in detail in the [“Variables and Mutability”][variables-and-mutability] section in Chapter 3. The following example shows how to use `mut` before -the variable name to make a variable mutable: +--> section in Chapter 3. To make a variable mutable, we add `mut` before the +variable name: ```rust,ignore let apples = 5; // immutable @@ -137,55 +138,51 @@ let mut bananas = 5; // mutable ``` > Note: The `//` syntax starts a comment that continues until the end of the -> line. Rust ignores everything in comments, which are discussed in more detail -> in Chapter 3. - -Let’s return to the guessing game program. You now know that `let mut guess` -will introduce a mutable variable named `guess`. On the other side of the equal -sign (`=`) is the value that `guess` is bound to, which is the result of -calling `String::new`, a function that returns a new instance of a `String`. +> line. Rust ignores everything in comments. We’ll discuss comments in more +> detail in [Chapter 3][comments]. + +Returning to the guessing game program, you now know that `let mut guess` will +introduce a mutable variable named `guess`. The equal sign (`=`) tells Rust we +want to bind something to the variable now. On the right of the equals sign is +the value that `guess` is bound to, which is the result of calling +`String::new`, a function that returns a new instance of a `String`. [`String`][string] is a string type provided by the standard library that is a growable, UTF-8 encoded bit of text. -[string]: ../std/string/struct.String.html - -The `::` syntax in the `::new` line indicates that `new` is an *associated -function* of the `String` type. An associated function is implemented on a -type, in this case `String`. +The `::` syntax in the `::new` line indicates that `new` is an associated +function of the `String` type. An *associated function* is a function that’s +implemented on a type, in this case `String`. This `new` function creates a +new, empty string. You’ll find a `new` function on many types, because it’s a +common name for a function that makes a new value of some kind. -This `new` function creates a new, empty string. You’ll find a `new` function -on many types, because it’s a common name for a function that makes a new value -of some kind. - -To summarize, the `let mut guess = String::new();` line has created a mutable +In full, the `let mut guess = String::new();` line has created a mutable variable that is currently bound to a new, empty instance of a `String`. Whew! +### Receiving User Input + Recall that we included the input/output functionality from the standard library with `use std::io;` on the first line of the program. Now we’ll call -the `stdin` function from the `io` module: +the `stdin` function from the `io` module, which will allow us to handle user +input: ```rust,ignore {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:read}} ``` -If we hadn’t put the `use std::io` line at the beginning of the program, we -could have written this function call as `std::io::stdin`. The `stdin` function -returns an instance of [`std::io::Stdin`][iostdin], which is a -type that represents a handle to the standard input for your terminal. +If we hadn’t imported the `io` library with `use std::io` at the beginning of +the program, we could still use the function by writing this function call as +`std::io::stdin`. The `stdin` function returns an instance of +[`std::io::Stdin`][iostdin], which is a type that represents a +handle to the standard input for your terminal. -[iostdin]: ../std/io/struct.Stdin.html - -The next part of the code, `.read_line(&mut guess)`, calls the -[`read_line`][read_line] method on the standard input handle to -get input from the user. We’re also passing one argument to `read_line`: `&mut -guess`. - -[read_line]: ../std/io/struct.Stdin.html#method.read_line - -The job of `read_line` is to take whatever the user types into standard input -and append that into a string (without overwriting its contents), so it takes -that string as an argument. The string argument needs to be mutable so the -method can change the string’s content by adding the user input. +Next, the line `.read_line(&mut guess)` calls the [`read_line`][read_line] method on the standard input handle to get input from the user. +We’re also passing `&mut guess` as the argument to `read_line` to tell it what +string to store the user input in. The full job of `read_line` is to take +whatever the user types into standard input and append that into a string +(without overwriting its contents), so we therefore pass that string as an +argument. The string argument needs to be mutable so the method can change the +string’s content. The `&` indicates that this argument is a *reference*, which gives you a way to let multiple parts of your code access one piece of data without needing to @@ -207,39 +204,35 @@ is this method: {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:expect}} ``` -When you call a method with the `.method_name()` syntax, it’s often wise to -introduce a newline and other whitespace to help break up long lines. We could -have written this code as: +We could have written this code as: ```rust,ignore io::stdin().read_line(&mut guess).expect("Failed to read line"); ``` -However, one long line is difficult to read, so it’s best to divide it. Now -let’s discuss what this line does. +However, one long line is difficult to read, so it’s best to divide it. It’s +often wise to introduce a newline and other whitespace to help break up long +lines when you call a method with the `.method_name()` syntax. Now let’s +discuss what this line does. -As mentioned earlier, `read_line` puts what the user types into the string -we’re passing it, but it also returns a value—in this case, an +As mentioned earlier, `read_line` puts whatever the user enters into the string +we pass to it, but it also returns a value—in this case, an [`io::Result`][ioresult]. Rust has a number of types named `Result` in its standard library: a generic [`Result`][result] -as well as specific versions for submodules, such as `io::Result`. +as well as specific versions for submodules, such as `io::Result`. The `Result` +types are [*enumerations*][enums], often referred to as *enums*, +which can have a fixed set of possibilites known as *variants*. Enums are often +used with `match`, a conditional that makes it convenient to execute different +code based on which variant an enum value is when the conditional is evaluated. -[ioresult]: ../std/io/type.Result.html -[result]: ../std/result/enum.Result.html +Chapter 6 will cover enums in more detail. The purpose of these `Result` types +is to encode error-handling information. -The `Result` types are [*enumerations*][enums], often referred -to as *enums*. An enumeration is a type that can have a fixed set of values, -and those values are called the enum’s *variants*. Chapter 6 will cover enums -in more detail. +`Result`’s variants are `Ok` or `Err`. The `Ok` variant indicates the operation +was successful, and inside `Ok` is the successfully generated value. The `Err` +variant means the operation failed, and `Err` contains information about how or +why the operation failed. -[enums]: ch06-00-enums.html - -For `Result`, the variants are `Ok` or `Err`. The `Ok` variant indicates the -operation was successful, and inside `Ok` is the successfully generated value. -The `Err` variant means the operation failed, and `Err` contains information -about how or why the operation failed. - -The purpose of these `Result` types is to encode error-handling information. Values of the `Result` type, like values of any type, have methods defined on them. An instance of `io::Result` has an [`expect` method][expect] that you can call. If this instance of `io::Result` is an `Err` value, @@ -248,10 +241,7 @@ passed as an argument to `expect`. If the `read_line` method returns an `Err`, it would likely be the result of an error coming from the underlying operating system. If this instance of `io::Result` is an `Ok` value, `expect` will take the return value that `Ok` is holding and return just that value to you so you -can use it. In this case, that value is the number of bytes in what the user -entered into standard input. - -[expect]: ../std/result/enum.Result.html#method.expect +can use it. In this case, that value is the number of bytes in the user’s input. If you don’t call `expect`, the program will compile, but you’ll get a warning: @@ -263,22 +253,23 @@ Rust warns that you haven’t used the `Result` value returned from `read_line`, indicating that the program hasn’t handled a possible error. The right way to suppress the warning is to actually write error handling, but -because you just want to crash this program when a problem occurs, you can use -`expect`. You’ll learn about recovering from errors in Chapter 9. +in our case we just want to crash this program when a problem occurs, so we can +use `expect`. You’ll learn about recovering from errors in [Chapter +9][recover]. ### Printing Values with `println!` Placeholders Aside from the closing curly bracket, there’s only one more line to discuss in -the code added so far, which is the following: +the code so far: ```rust,ignore {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:print_guess}} ``` -This line prints the string we saved the user’s input in. The set of curly -brackets, `{}`, is a placeholder: think of `{}` as little crab pincers that -hold a value in place. You can print more than one value using curly brackets: -the first set of curly brackets holds the first value listed after the format +This line prints the string that now contains the user’s input. The `{}` set of +curly brackets is a placeholder: think of `{}` as little crab pincers that hold +a value in place. You can print more than one value using curly brackets: the +first set of curly brackets holds the first value listed after the format string, the second set holds the second value, and so on. Printing multiple values in one call to `println!` would look like this: @@ -319,25 +310,24 @@ keyboard and then printing it. Next, we need to generate a secret number that the user will try to guess. The secret number should be different every time so the game is fun to play more -than once. Let’s use a random number between 1 and 100 so the game isn’t too +than once. We’ll use a random number between 1 and 100 so the game isn’t too difficult. Rust doesn’t yet include random number functionality in its standard -library. However, the Rust team does provide a [`rand` crate][randcrate]. - -[randcrate]: https://crates.io/crates/rand +library. However, the Rust team does provide a [`rand` crate][randcrate] with +said functionality. ### Using a Crate to Get More Functionality Remember that a crate is a collection of Rust source code files. The project we’ve been building is a *binary crate*, which is an executable. The `rand` crate is a *library crate*, which contains code intended to be used in other -programs. +programs, and can’t be executed on its own. Cargo’s coordination of external crates is where Cargo really shines. Before we can write code that uses `rand`, we need to modify the *Cargo.toml* file to include the `rand` crate as a dependency. Open that file now and add the following line to the bottom beneath the `[dependencies]` section header that -Cargo created for you. Be sure to specify `rand` exactly as we have here, or -the code examples in this tutorial may not work. +Cargo created for you. Be sure to specify `rand` exactly as we have here, with +this version number, or the code examples in this tutorial may not work. (sometimes called *SemVer*), which is a standard for writing version numbers. The number `0.8.3` is actually shorthand for `^0.8.3`, which means any version that is at least `0.8.3` but below `0.9.0`. Cargo considers these versions to have public APIs compatible with -version `0.8.3`, and this specification ensures you'll get the latest patch +version `0.8.3`, and this specification ensures you’ll get the latest patch release that will still compile with the code in this chapter. Any version `0.9.0` or greater is not guaranteed to have the same API as what the following examples use. -[semver]: http://semver.org - Now, without changing any of the code, let’s build the project, as shown in Listing 2-2. @@ -399,22 +387,20 @@ $ cargo build Listing 2-2: The output from running `cargo build` after adding the rand crate as a dependency -You may see different version numbers (but they will all be compatible with -the code, thanks to SemVer!), different lines (depending on the operating -system), and the lines may be in a different order. +You may see different version numbers (but they will all be compatible with the +code, thanks to SemVer!), different lines (depending on the operating system), +and the lines may be in a different order. -Now that we have an external dependency, Cargo fetches the latest versions of -everything from the *registry*, which is a copy of data from -[Crates.io][cratesio]. Crates.io is where people in the Rust ecosystem post -their open source Rust projects for others to use. - -[cratesio]: https://crates.io/ +When we include an external dependency, Cargo fetches the latest versions of +everything that dependency needs from the *registry*, which is a copy of data +from [Crates.io][cratesio]. Crates.io is where people in the Rust ecosystem +post their open source Rust projects for others to use. After updating the registry, Cargo checks the `[dependencies]` section and -downloads any crates you don’t have yet. In this case, although we only listed -`rand` as a dependency, Cargo also grabbed other crates that `rand` depends on -to work. After downloading the crates, Rust compiles them and then compiles the -project with the dependencies available. +downloads any crates listed that aren’t already downloaded. In this case, +although we only listed `rand` as a dependency, Cargo also grabbed other crates +that `rand` depends on to work. After downloading the crates, Rust compiles +them and then compiles the project with the dependencies available. If you immediately run `cargo build` again without making any changes, you won’t get any output aside from the `Finished` line. Cargo knows it has already @@ -439,20 +425,19 @@ $ cargo build These lines show Cargo only updates the build with your tiny change to the *src/main.rs* file. Your dependencies haven’t changed, so Cargo knows it can -reuse what it has already downloaded and compiled for those. It just rebuilds -your part of the code. +reuse what it has already downloaded and compiled for those. #### Ensuring Reproducible Builds with the *Cargo.lock* File Cargo has a mechanism that ensures you can rebuild the same artifact every time you or anyone else builds your code: Cargo will use only the versions of the -dependencies you specified until you indicate otherwise. For example, what -happens if next week version 0.8.4 of the `rand` crate comes out, and that -version contains an important bug fix, but it also contains a regression that -will break your code? +dependencies you specified until you indicate otherwise. For example, say that +next week version 0.8.4 of the `rand` crate comes out, and that version +contains an important bug fix, but it also contains a regression that will +break your code. To handle this, Rust creates the *Cargo.lock* file the first +time you run `cargo build`, so we now have this in the *guessing_game* +directory. -The answer to this problem is the *Cargo.lock* file, which was created the -first time you ran `cargo build` and is now in your *guessing_game* directory. When you build a project for the first time, Cargo figures out all the versions of the dependencies that fit the criteria and then writes them to the *Cargo.lock* file. When you build your project in the future, Cargo will @@ -464,14 +449,13 @@ file. #### Updating a Crate to Get a New Version -When you *do* want to update a crate, Cargo provides another command, `update`, +When you *do* want to update a crate, Cargo provides the command `update`, which will ignore the *Cargo.lock* file and figure out all the latest versions -that fit your specifications in *Cargo.toml*. If that works, Cargo will write -those versions to the *Cargo.lock* file. - -But by default, Cargo will only look for versions greater than `0.8.3` and less -than `0.9.0`. If the `rand` crate has released two new versions, `0.8.4` and -`0.9.0`, you would see the following if you ran `cargo update`: +that fit your specifications in *Cargo.toml*. Cargo will then write those +versions to the *Cargo.lock* file. Otherwise, by default, Cargo will only look +for versions greater than `0.8.3` and less than `0.9.0`. If the `rand` crate +has released the two new versions `0.8.4` and `0.9.0` you would see the +following if you ran `cargo update`: : if the user enters a non-number answer, the program will crash. The -user can take advantage of that in order to quit, as shown here: +ignore -->: if the user enters a non-number answer, the program will crash. We +can take advantage of that to allow the user to quit, as shown here: so don’t worry about the details right now. Just know that you must always -annotate the type. +immutable by default—they’re always immutable. You declare constants using the +`const` keyword instead of the `let` keyword, and the type of the value *must* +be annotated. We’re about to cover types and type annotations in the next +section, [“Data Types,”][data-types] so don’t worry about the +details right now. Just know that you must always annotate the type. Constants can be declared in any scope, including the global scope, which makes them useful for values that many parts of code need to know about. @@ -104,21 +97,22 @@ them useful for values that many parts of code need to know about. The last difference is that constants may be set only to a constant expression, not the result of a value that could only be computed at runtime. -Here’s an example of a constant declaration where the constant’s name is -`THREE_HOURS_IN_SECONDS` and its value is set to the result of multiplying 60 -(the number of seconds in a minute) by 60 (the number of minutes in an hour) by -3 (the number of hours we want to count in this program): +Here’s an example of a constant declaration: ```rust const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 * 3; ``` -Rust’s naming convention for constants is to use all uppercase with underscores -between words. The compiler is able to evaluate a limited set of operations at -compile time, which lets us choose to write out this value in a way that’s -easier to understand and verify, rather than setting this constant to the value -10,800. See the [Rust Reference’s section on constant evaluation][const-eval] -for more information on what operations can be used when declaring constants. +The constant’s name is `THREE_HOURS_IN_SECONDS` and its value is set to the +result of multiplying 60 (the number of seconds in a minute) by 60 (the number +of minutes in an hour) by 3 (the number of hours we want to count in this +program). Rust’s naming convention for constants is to use all uppercase with +underscores between words. The compiler is able to evaluate a limited set of +operations at compile time, which lets us choose to write out this value in a +way that’s easier to understand and verify, rather than setting this constant +to the value 10,800. See the [Rust Reference’s section on constant +evaluation][const-eval] for more information on what operations can be used +when declaring constants. Constants are valid for the entire time a program runs, within the scope they were declared in. This property makes constants useful for values in your @@ -133,13 +127,13 @@ hardcoded value needed to be updated in the future. ### Shadowing -As you saw in the guessing game tutorial in the [“Comparing the Guess to the -Secret Number”][comparing-the-guess-to-the-secret-number] -section in Chapter 2, you can declare a new variable with the same name as a -previous variable. Rustaceans say that the first variable is *shadowed* by the -second, which means that the second variable’s value is what the program sees when the -variable is used. We can shadow a variable by using the same variable’s name -and repeating the use of the `let` keyword as follows: +As you saw in the guessing game tutorial in [Chapter +2][comparing-the-guess-to-the-secret-number], you can declare a +new variable with the same name as a previous variable. Rustaceans say that the +first variable is *shadowed* by the second, which means that the second +variable’s value is what the program sees when the variable is used. We can +shadow a variable by using the same variable’s name and repeating the use of +the `let` keyword as follows: Filename: src/main.rs @@ -168,18 +162,17 @@ The other difference between `mut` and shadowing is that because we’re effectively creating a new variable when we use the `let` keyword again, we can change the type of the value but reuse the same name. For example, say our program asks a user to show how many spaces they want between some text by -inputting space characters, but we really want to store that input as a number: +inputting space characters, and then we want to store that input as a number: ```rust {{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-04-shadowing-can-change-types/src/main.rs:here}} ``` -This construct is allowed because the first `spaces` variable is a string type -and the second `spaces` variable, which is a brand-new variable that happens to -have the same name as the first one, is a number type. Shadowing thus spares us -from having to come up with different names, such as `spaces_str` and -`spaces_num`; instead, we can reuse the simpler `spaces` name. However, if we -try to use `mut` for this, as shown here, we’ll get a compile-time error: +The first `spaces` variable is a string type and the second `spaces` variable +is a number type. Shadowing thus spares us from having to come up with +different names, such as `spaces_str` and `spaces_num`; instead, we can reuse +the simpler `spaces` name. However, if we try to use `mut` for this, as shown +here, we’ll get a compile-time error: ```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-05-mut-cant-change-types/src/main.rs:here}} diff --git a/src/doc/book/src/ch03-02-data-types.md b/src/doc/book/src/ch03-02-data-types.md index 453e9e5b2c..e8b61838d7 100644 --- a/src/doc/book/src/ch03-02-data-types.md +++ b/src/doc/book/src/ch03-02-data-types.md @@ -38,9 +38,8 @@ An *integer* is a number without a fractional component. We used one integer type in Chapter 2, the `u32` type. This type declaration indicates that the value it’s associated with should be an unsigned integer (signed integer types start with `i`, instead of `u`) that takes up 32 bits of space. Table 3-1 shows -the built-in integer types in Rust. Each variant in the Signed and Unsigned -columns (for example, `i16`) can be used to declare the type of an integer -value. +the built-in integer types in Rust. We can use any of these variants to declare +the type of an integer value. Table 3-1: Integer Types in Rust @@ -70,9 +69,10 @@ Each signed variant can store numbers from -(2n - 1) to 2n - -128 to 127. Unsigned variants can store numbers from 0 to 2n - 1, so a `u8` can store numbers from 0 to 28 - 1, which equals 0 to 255. -Additionally, the `isize` and `usize` types depend on the kind of computer your -program is running on: 64 bits if you’re on a 64-bit architecture and 32 bits -if you’re on a 32-bit architecture. +Additionally, the `isize` and `usize` types depend on the architecture of the +computer your program is running on, which is denoted in the table as “arch”: +64 bits if you’re on a 64-bit architecture and 32 bits if you’re on a 32-bit +architecture. You can write integer literals in any of the forms shown in Table 3-2. Note that number literals that can be multiple numeric types allow a type suffix, @@ -97,15 +97,15 @@ some sort of collection. > ##### Integer Overflow > -> Let’s say you have a variable of type `u8` that can hold values between 0 and 255. -> If you try to change the variable to a value outside of that range, such -> as 256, *integer overflow* will occur. Rust has some interesting rules -> involving this behavior. When you’re compiling in debug mode, Rust includes -> checks for integer overflow that cause your program to *panic* at runtime if -> this behavior occurs. Rust uses the term panicking when a program exits with -> an error; we’ll discuss panics in more depth in the [“Unrecoverable Errors -> with `panic!`”][unrecoverable-errors-with-panic] section in -> Chapter 9. +> Let’s say you have a variable of type `u8` that can hold values between 0 and +> 255. If you try to change the variable to a value outside of that range, such +> as 256, *integer overflow* will occur, which can result in one of two +> behaviors. When you’re compiling in debug mode, Rust includes checks for +> integer overflow that cause your program to *panic* at runtime if this +> behavior occurs. Rust uses the term panicking when a program exits with an +> error; we’ll discuss panics in more depth in the [“Unrecoverable Errors with +> `panic!`”][unrecoverable-errors-with-panic] section in Chapter +> 9. > > When you’re compiling in release mode with the `--release` flag, Rust does > *not* include checks for integer overflow that cause panics. Instead, if @@ -117,7 +117,7 @@ some sort of collection. > have. Relying on integer overflow’s wrapping behavior is considered an error. > > To explicitly handle the possibility of overflow, you can use these families -> of methods that the standard library provides on primitive numeric types: +> of methods provided by the standard library for primitive numeric types: > > - Wrap in all modes with the `wrapping_*` methods, such as `wrapping_add` > - Return the `None` value if there is overflow with the `checked_*` methods @@ -132,7 +132,7 @@ Rust also has two primitive types for *floating-point numbers*, which are numbers with decimal points. Rust’s floating-point types are `f32` and `f64`, which are 32 bits and 64 bits in size, respectively. The default type is `f64` because on modern CPUs it’s roughly the same speed as `f32` but is capable of -more precision. +more precision. All floating-point types are signed. Here’s an example that shows floating-point numbers in action: @@ -180,10 +180,8 @@ Flow”][control-flow] section. #### The Character Type -So far we’ve worked only with numbers, but Rust supports letters too. Rust’s -`char` type is the language’s most primitive alphabetic type, and the following -code shows one way to use it. (Note that `char` literals are specified with -single quotes, as opposed to string literals, which use double quotes.) +Rust’s `char` type is the language’s most primitive alphabetic type. Here’s +some examples of declaring `char` values: Filename: src/main.rs @@ -191,15 +189,16 @@ single quotes, as opposed to string literals, which use double quotes.) {{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-09-char/src/main.rs}} ``` -Rust’s `char` type is four bytes in size and represents a Unicode Scalar Value, -which means it can represent a lot more than just ASCII. Accented letters; -Chinese, Japanese, and Korean characters; emoji; and zero-width spaces are all -valid `char` values in Rust. Unicode Scalar Values range from `U+0000` to -`U+D7FF` and `U+E000` to `U+10FFFF` inclusive. However, a “character” isn’t -really a concept in Unicode, so your human intuition for what a “character” is -may not match up with what a `char` is in Rust. We’ll discuss this topic in -detail in [“Storing UTF-8 Encoded Text with Strings”][strings] -in Chapter 8. +Note that we specify `char` literals with single quotes, as opposed to string +literals, which use double quotes. Rust’s `char` type is four bytes in size and +represents a Unicode Scalar Value, which means it can represent a lot more than +just ASCII. Accented letters; Chinese, Japanese, and Korean characters; emoji; +and zero-width spaces are all valid `char` values in Rust. Unicode Scalar +Values range from `U+0000` to `U+D7FF` and `U+E000` to `U+10FFFF` inclusive. +However, a “character” isn’t really a concept in Unicode, so your human +intuition for what a “character” is may not match up with what a `char` is in +Rust. We’ll discuss this topic in detail in [“Storing UTF-8 Encoded Text with +Strings”][strings] in Chapter 8. ### Compound Types @@ -239,9 +238,8 @@ variables, `x`, `y`, and `z`. This is called *destructuring*, because it breaks the single tuple into three parts. Finally, the program prints the value of `y`, which is `6.4`. -In addition to destructuring through pattern matching, we can access a tuple -element directly by using a period (`.`) followed by the index of the value we -want to access. For example: +We can also access a tuple element directly by using a period (`.`) followed by +the index of the value we want to access. For example: Filename: src/main.rs @@ -249,7 +247,7 @@ want to access. For example: {{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-12-tuple-indexing/src/main.rs}} ``` -This program creates a tuple, `x`, and then makes new variables for each +This program creates the tuple `x` and then makes new variables for each element by using their respective indices. As with most programming languages, the first index in a tuple is 0. @@ -261,12 +259,11 @@ return any other value. #### The Array Type Another way to have a collection of multiple values is with an *array*. Unlike -a tuple, every element of an array must have the same type. Arrays in Rust are -different from arrays in some other languages because arrays in Rust have a -fixed length, like tuples. +a tuple, every element of an array must have the same type. Unlike arrays in +some other languages, arrays in Rust have a fixed length. -In Rust, the values going into an array are written as a comma-separated list -inside square brackets: +We write the values in an array as a comma-separated list inside square +brackets: Filename: src/main.rs @@ -275,26 +272,26 @@ inside square brackets: ``` Arrays are useful when you want your data allocated on the stack rather than -the heap (we will discuss the stack and the heap more in Chapter 4) or when -you want to ensure you always have a fixed number of elements. An array isn’t -as flexible as the vector type, though. A vector is a similar collection type -provided by the standard library that *is* allowed to grow or shrink in size. -If you’re unsure whether to use an array or a vector, you should probably use a -vector. Chapter 8 discusses vectors in more detail. - -An example of when you might want to use an array rather than a vector is in a -program that needs to know the names of the months of the year. It’s very -unlikely that such a program will need to add or remove months, so you can use -an array because you know it will always contain 12 elements: +the heap (we will discuss the stack and the heap more in [Chapter +4][stack-and-heap]) or when you want to ensure you always have a +fixed number of elements. An array isn’t as flexible as the vector type, +though. A vector is a similar collection type provided by the standard library +that *is* allowed to grow or shrink in size. If you’re unsure whether to use an +array or a vector, chances are you should use a vector. [Chapter +8][vectors] discusses vectors in more detail. + +However, arrays are more useful when you know the number of elements will not +need to change. For example, if you were using the names of the month in a +program, you would probably use an array rather than a vector because you know +it will always contain 12 elements: ```rust let months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; ``` -You would write an array’s type by using square brackets, and within the -brackets include the type of each element, a semicolon, and then the number of -elements in the array, like so: +You write an array’s type using square brackets with the type of each element, +a semicolon, and then the number of elements in the array, like so: ```rust let a: [i32; 5] = [1, 2, 3, 4, 5]; @@ -303,10 +300,9 @@ let a: [i32; 5] = [1, 2, 3, 4, 5]; Here, `i32` is the type of each element. After the semicolon, the number `5` indicates the array contains five elements. -Writing an array’s type this way looks similar to an alternative syntax for -initializing an array: if you want to create an array that contains the same -value for each element, you can specify the initial value, followed by a -semicolon, and then the length of the array in square brackets, as shown here: +You can also initialize an array to contain the same value for each element by +specifying the initial value, followed by a semicolon, and then the length of +the array in square brackets, as shown here: ```rust let a = [3; 5]; @@ -334,9 +330,9 @@ get the value `2` from index `[1]` in the array. ##### Invalid Array Element Access -What happens if you try to access an element of an array that is past the end -of the array? Say you change the example to the following, which uses code -similar to the guessing game in Chapter 2 to get an array index from the user: +Let’s see what happens if you try to access an element of an array that is past +the end of the array. Say you run this code, similar to the guessing game in +Chapter 2, to get an array index from the user: Filename: src/main.rs @@ -379,6 +375,8 @@ continuing. Chapter 9 discusses more of Rust’s error handling. ch02-00-guessing-game-tutorial.html#comparing-the-guess-to-the-secret-number [control-flow]: ch03-05-control-flow.html#control-flow [strings]: ch08-02-strings.html#storing-utf-8-encoded-text-with-strings +[stack-and-heap]: ch04-01-what-is-ownership.html#the-stack-and-the-heap +[vectors]: ch08-01-vectors.html [unrecoverable-errors-with-panic]: ch09-01-unrecoverable-errors-with-panic.html [wrapping]: ../std/num/struct.Wrapping.html [appendix_b]: appendix-02-operators.md diff --git a/src/doc/book/src/ch03-03-how-functions-work.md b/src/doc/book/src/ch03-03-how-functions-work.md index d51b4a6a58..76aa243ab2 100644 --- a/src/doc/book/src/ch03-03-how-functions-work.md +++ b/src/doc/book/src/ch03-03-how-functions-work.md @@ -6,7 +6,7 @@ point of many programs. You’ve also seen the `fn` keyword, which allows you to declare new functions. Rust code uses *snake case* as the conventional style for function and variable -names. In snake case, all letters are lowercase and underscores separate words. +names, in which all letters are lowercase and underscores separate words. Here’s a program that contains an example function definition: Filename: src/main.rs @@ -15,9 +15,9 @@ Here’s a program that contains an example function definition: {{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-16-functions/src/main.rs}} ``` -Function definitions in Rust start with `fn` and have a set of parentheses -after the function name. The curly brackets tell the compiler where the -function body begins and ends. +We define a function in Rust by entering `fn` followed by a function name and a +set of parentheses. The curly brackets tell the compiler where the function +body begins and ends. We can call any function we’ve defined by entering its name followed by a set of parentheses. Because `another_function` is defined in the program, it can be @@ -38,18 +38,17 @@ The lines execute in the order in which they appear in the `main` function. First, the “Hello, world!” message prints, and then `another_function` is called and its message is printed. -### Function Parameters +### Parameters -Functions can also be defined to have *parameters*, which are special variables -that are part of a function’s signature. When a function has parameters, you -can provide it with concrete values for those parameters. Technically, the -concrete values are called *arguments*, but in casual conversation, people tend -to use the words *parameter* and *argument* interchangeably for either the -variables in a function’s definition or the concrete values passed in when you -call a function. +We can define functions to have *parameters*, which are special variables that +are part of a function’s signature. When a function has parameters, you can +provide it with concrete values for those parameters. Technically, the concrete +values are called *arguments*, but in casual conversation, people tend to use +the words *parameter* and *argument* interchangeably for either the variables +in a function’s definition or the concrete values passed in when you call a +function. -The following rewritten version of `another_function` shows what parameters -look like in Rust: +In this version of `another_function` we add a parameter: Filename: src/main.rs @@ -64,7 +63,7 @@ Try running this program; you should get the following output: ``` The declaration of `another_function` has one parameter named `x`. The type of -`x` is specified as `i32`. When `5` is passed to `another_function`, the +`x` is specified as `i32`. When we pass `5` in to `another_function`, the `println!` macro puts `5` where the pair of curly brackets were in the format string. @@ -73,8 +72,8 @@ a deliberate decision in Rust’s design: requiring type annotations in function definitions means the compiler almost never needs you to use them elsewhere in the code to figure out what type you mean. -When you want a function to have multiple parameters, separate the parameter -declarations with commas, like this: +When defining multiple parameters, separate the parameter declarations with +commas, like this: Filename: src/main.rs @@ -98,22 +97,22 @@ run`: Because we called the function with `5` as the value for `value` and `'h'` as the value for `unit_label`, the program output contains those values. -### Function Bodies Contain Statements and Expressions +### Statements and Expressions Function bodies are made up of a series of statements optionally ending in an -expression. So far, we’ve only covered functions without an ending expression, -but you have seen an expression as part of a statement. Because Rust is an -expression-based language, this is an important distinction to understand. -Other languages don’t have the same distinctions, so let’s look at what -statements and expressions are and how their differences affect the bodies of -functions. +expression. So far, the functions we’ve covered haven’t included an ending +expression, but you have seen an expression as part of a statement. Because +Rust is an expression-based language, this is an important distinction to +understand. Other languages don’t have the same distinctions, so let’s look at +what statements and expressions are and how their differences affect the bodies +of functions. -We’ve actually already used statements and expressions. *Statements* are -instructions that perform some action and do not return a value. *Expressions* -evaluate to a resulting value. Let’s look at some examples. +*Statements* are instructions that perform some action and do not return a +value. *Expressions* evaluate to a resulting value. Let’s look at some examples. -Creating a variable and assigning a value to it with the `let` keyword is a -statement. In Listing 3-1, `let y = 6;` is a statement. +We’ve actually already used statements and expressions. Creating a variable and +assigning a value to it with the `let` keyword is a statement. In Listing 3-1, +`let y = 6;` is a statement. Filename: src/main.rs @@ -152,8 +151,8 @@ you’ll write in Rust. Consider a math operation, such as `5 + 6`, which is an expression that evaluates to the value `11`. Expressions can be part of statements: in Listing 3-1, the `6` in the statement `let y = 6;` is an expression that evaluates to the value `6`. Calling a function is an -expression. Calling a macro is an expression. The block that we use to create -new scopes, `{}`, is an expression, for example: +expression. Calling a macro is an expression. A new scope block created with +curly brackets is an expression, for example: Filename: src/main.rs @@ -171,10 +170,10 @@ This expression: ``` is a block that, in this case, evaluates to `4`. That value gets bound to `y` -as part of the `let` statement. Note the `x + 1` line without a semicolon at -the end, which is unlike most of the lines you’ve seen so far. Expressions do -not include ending semicolons. If you add a semicolon to the end of an -expression, you turn it into a statement, which will then not return a value. +as part of the `let` statement. Note that the `x + 1` line doesn’t have a +semicolon at the end, unlike most of the lines you’ve seen so far. Expressions +do not include ending semicolons. If you add a semicolon to the end of an +expression, you turn it into a statement, and it will then not return a value. Keep this in mind as you explore function return values and expressions next. ### Functions with Return Values diff --git a/src/doc/book/src/ch03-04-comments.md b/src/doc/book/src/ch03-04-comments.md index 6a3f8efd46..6af0ce175c 100644 --- a/src/doc/book/src/ch03-04-comments.md +++ b/src/doc/book/src/ch03-04-comments.md @@ -1,9 +1,9 @@ ## Comments All programmers strive to make their code easy to understand, but sometimes -extra explanation is warranted. In these cases, programmers leave notes, or -*comments*, in their source code that the compiler will ignore but people -reading the source code may find useful. +extra explanation is warranted. In these cases, programmers leave *comments* in +their source code that the compiler will ignore but people reading the source +code may find useful. Here’s a simple comment: diff --git a/src/doc/book/src/ch03-05-control-flow.md b/src/doc/book/src/ch03-05-control-flow.md index 8d0b840504..f75d6071a7 100644 --- a/src/doc/book/src/ch03-05-control-flow.md +++ b/src/doc/book/src/ch03-05-control-flow.md @@ -1,10 +1,9 @@ ## Control Flow -Deciding whether or not to run some code depending on if a condition is true -and deciding to run some code repeatedly while a condition is true are basic -building blocks in most programming languages. The most common constructs that -let you control the flow of execution of Rust code are `if` expressions and -loops. +The ability to run some code depending on if a condition is true, or run some +code repeatedly while a condition is true, are basic building blocks in most +programming languages. The most common constructs that let you control the flow +of execution of Rust code are `if` expressions and loops. ### `if` Expressions @@ -21,15 +20,14 @@ the `if` expression. In the *src/main.rs* file, input the following: {{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-26-if-true/src/main.rs}} ``` -All `if` expressions start with the keyword `if`, which is followed by a -condition. In this case, the condition checks whether or not the variable -`number` has a value less than 5. The block of code we want to execute if the -condition is true is placed immediately after the condition inside curly -brackets. Blocks of code associated with the conditions in `if` expressions are -sometimes called *arms*, just like the arms in `match` expressions that we -discussed in the [“Comparing the Guess to the Secret -Number”][comparing-the-guess-to-the-secret-number] section of -Chapter 2. +All `if` expressions start with the keyword `if`, followed by a condition. In +this case, the condition checks whether or not the variable `number` has a +value less than 5. We place block of code to execute if the condition is true +immediately after the condition inside curly brackets. Blocks of code +associated with the conditions in `if` expressions are sometimes called *arms*, +just like the arms in `match` expressions that we discussed in the [“Comparing +the Guess to the Secret Number”][comparing-the-guess-to-the-secret-number] section of Chapter 2. Optionally, we can also include an `else` expression, which we chose to do here, to give the program an alternative block of code to execute should @@ -90,7 +88,7 @@ Running this code will print `number was something other than zero`. #### Handling Multiple Conditions with `else if` -You can have multiple conditions by combining `if` and `else` in an `else if` +You can use multiple conditions by combining `if` and `else` in an `else if` expression. For example: Filename: src/main.rs @@ -120,7 +118,7 @@ Rust branching construct called `match` for these cases. #### Using `if` in a `let` Statement Because `if` is an expression, we can use it on the right side of a `let` -statement, as in Listing 3-2. +statement to assign the outcome to a variable, as in Listing 3-2. Filename: src/main.rs @@ -162,18 +160,18 @@ find the problem in the program: The expression in the `if` block evaluates to an integer, and the expression in the `else` block evaluates to a string. This won’t work because variables must -have a single type. Rust needs to know at compile time what type the `number` -variable is, definitively, so it can verify at compile time that its type is -valid everywhere we use `number`. Rust wouldn’t be able to do that if the type -of `number` was only determined at runtime; the compiler would be more complex -and would make fewer guarantees about the code if it had to keep track of -multiple hypothetical types for any variable. +have a single type, and Rust needs to know at compile time what type the +`number` variable is, definitively. Knowing the type of `number` lets the +compiler verify the type is valid everywhere we use `number`. Rust wouldn’t be +able to do that if the type of `number` was only determined at runtime; the +compiler would be more complex and would make fewer guarantees about the code +if it had to keep track of multiple hypothetical types for any variable. ### Repetition with Loops It’s often useful to execute a block of code more than once. For this task, -Rust provides several *loops*. A loop runs through the code inside the loop -body to the end and then starts immediately back at the beginning. To +Rust provides several *loops*, which will run through the code inside the loop +body to the end and then start immediately back at the beginning. To experiment with loops, let’s make a new project called *loops*. Rust has three kinds of loops: `loop`, `while`, and `for`. Let’s try each one. @@ -193,8 +191,8 @@ like this: ``` When we run this program, we’ll see `again!` printed over and over continuously -until we stop the program manually. Most terminals support a keyboard shortcut, -ctrl-c, to interrupt a program that is stuck in +until we stop the program manually. Most terminals support the keyboard shortcut +ctrl-c to interrupt a program that is stuck in a continual loop. Give it a try: section of Chapter 2 to exit the program when the user won the game by guessing the correct number. -We also used `continue` in the guessing game. The `continue` keyword within a -loop tells the program to skip over any remaining code in this iteration of the -loop and go to the next iteration. +We also used `continue` in the guessing game, which in a loop tells the program +to skip over any remaining code in this iteration of the loop and go to the +next iteration. If you have loops within loops, `break` and `continue` apply to the innermost -loop at that point. You can optionally specify a *loop label* on a loop and -then use the label with `break` or `continue` to have those keywords applied to +loop at that point. You can optionally specify a *loop label* on a loop that we +can then use with `break` or `continue` to specify that those keywords apply to the labeled loop instead of the innermost loop. Here’s an example with two nested loops: @@ -253,11 +251,11 @@ doesn’t specify a label will exit the inner loop only. The `break #### Returning Values from Loops One of the uses of a `loop` is to retry an operation you know might fail, such -as checking whether a thread has completed its job. However, you might need to -pass the result of that operation to the rest of your code. To do this, you can -add the value you want returned after the `break` expression you use to stop -the loop; that value will be returned out of the loop so you can use it, as -shown here: +as checking whether a thread has completed its job. You might also need to pass +the result of that operation out of the loop to the rest of your code. To do +this, you can add the value you want returned after the `break` expression you +use to stop the loop; that value will be returned out of the loop so you can +use it, as shown here: ```rust {{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-33-return-value-from-loop/src/main.rs}} @@ -273,16 +271,14 @@ print the value in `result`, which in this case is 20. #### Conditional Loops with `while` -It’s often useful for a program to evaluate a condition within a loop. While -the condition is true, the loop runs. When the condition ceases to be true, the -program calls `break`, stopping the loop. This loop type could be implemented -using a combination of `loop`, `if`, `else`, and `break`; you could try that -now in a program, if you’d like. - -However, this pattern is so common that Rust has a built-in language construct -for it, called a `while` loop. Listing 3-3 uses `while`: the program loops -three times, counting down each time, and then, after the loop, it prints -another message and exits. +A program will often need to evaluate a condition within a loop. While the +condition is true, the loop runs. When the condition ceases to be true, the +program calls `break`, stopping the loop. It’s possible to implement behavior +like this using a combination of `loop`, `if`, `else`, and `break`; you could +try that now in a program, if you’d like. However, this pattern is so common +that Rust has a built-in language construct for it, called a `while` loop. In +Listing 3-3, we use `while` to loop the program three times, counting down each +time, and then, after the loop, print a message and exit. Filename: src/main.rs @@ -299,8 +295,9 @@ true, the code runs; otherwise, it exits the loop. #### Looping Through a Collection with `for` -You could use the `while` construct to loop over the elements of a collection, -such as an array. For example, let’s look at Listing 3-4. +You can choose to use the `while` construct to loop over the elements of a +collection, such as an array. For example, the loop in Listing 3-4 prints each +element in the array `a`. Filename: src/main.rs @@ -324,9 +321,11 @@ All five array values appear in the terminal, as expected. Even though `index` will reach a value of `5` at some point, the loop stops executing before trying to fetch a sixth value from the array. -But this approach is error prone; we could cause the program to panic if the -index value or test condition are incorrect. It’s also slow, because the -compiler adds runtime code to perform the conditional check of whether the +However, this approach is error prone; we could cause the program to panic if +the index value or test condition are incorrect. For example, if you changed +the definition of the `a` array to have four elements but forgot to update the +condition to `while index < 4`, the code would panic. It’s also slow, because +the compiler adds runtime code to perform the conditional check of whether the index is within the bounds of the array on every iteration through the loop. As a more concise alternative, you can use a `for` loop and execute some code @@ -346,19 +345,17 @@ importantly, we’ve now increased the safety of the code and eliminated the chance of bugs that might result from going beyond the end of the array or not going far enough and missing some items. -For example, in the code in Listing 3-4, if you changed the definition of the -`a` array to have four elements but forgot to update the condition to `while -index < 4`, the code would panic. Using the `for` loop, you wouldn’t need to -remember to change any other code if you changed the number of values in the -array. +Using the `for` loop, you wouldn’t need to remember to change any other code if +you changed the number of values in the array, as you would with the method +used in Listing 3-4. -The safety and conciseness of `for` loops makes them the most commonly used -loop construct in Rust. Even in situations in which you want to run some code -a certain number of times, as in the countdown example that used a `while` loop +The safety and conciseness of `for` loops make them the most commonly used loop +construct in Rust. Even in situations in which you want to run some code a +certain number of times, as in the countdown example that used a `while` loop in Listing 3-3, most Rustaceans would use a `for` loop. The way to do that -would be to use a `Range`, which is a type provided by the standard library -that generates all numbers in sequence starting from one number and ending -before another number. +would be to use a `Range`, provided by the standard library, which generates +all numbers in sequence starting from one number and ending before another +number. Here’s what the countdown would look like using a `for` loop and another method we’ve not yet talked about, `rev`, to reverse the range: @@ -374,8 +371,8 @@ This code is a bit nicer, isn’t it? ## Summary You made it! That was a sizable chapter: you learned about variables, scalar -and compound data types, functions, comments, `if` expressions, and loops! If -you want to practice with the concepts discussed in this chapter, try building +and compound data types, functions, comments, `if` expressions, and loops! +To practice with the concepts discussed in this chapter, try building programs to do the following: * Convert temperatures between Fahrenheit and Celsius. diff --git a/src/doc/book/src/ch04-00-understanding-ownership.md b/src/doc/book/src/ch04-00-understanding-ownership.md index a58d673964..52eda6a12f 100644 --- a/src/doc/book/src/ch04-00-understanding-ownership.md +++ b/src/doc/book/src/ch04-00-understanding-ownership.md @@ -1,7 +1,7 @@ # Understanding Ownership -Ownership is Rust’s most unique feature, and it enables Rust to make memory -safety guarantees without needing a garbage collector. Therefore, it’s -important to understand how ownership works in Rust. In this chapter, we’ll -talk about ownership as well as several related features: borrowing, slices, -and how Rust lays data out in memory. +Ownership is Rust’s most unique feature and has deep implications for the rest +of the language. It enables Rust to make memory safety guarantees without +needing a garbage collector, so it’s important to understand how ownership +works. In this chapter, we’ll talk about ownership as well as several related +features: borrowing, slices, and how Rust lays data out in memory. diff --git a/src/doc/book/src/ch04-01-what-is-ownership.md b/src/doc/book/src/ch04-01-what-is-ownership.md index a2d3acd62f..3efbf4a851 100644 --- a/src/doc/book/src/ch04-01-what-is-ownership.md +++ b/src/doc/book/src/ch04-01-what-is-ownership.md @@ -1,19 +1,17 @@ ## What Is Ownership? -Rust’s central feature is *ownership*. Although the feature is straightforward -to explain, it has deep implications for the rest of the language. - +*Ownership* is a set of rules that governs how a Rust program manages memory. All programs have to manage the way they use a computer’s memory while running. -Some languages have garbage collection that constantly looks for no longer used +Some languages have garbage collection that constantly looks for no-longer used memory as the program runs; in other languages, the programmer must explicitly allocate and free the memory. Rust uses a third approach: memory is managed -through a system of ownership with a set of rules that the compiler checks at -compile time. None of the ownership features slow down your program while it’s -running. +through a system of ownership with a set of rules that the compiler checks. If +any of the rules are violated, the program won’t compile. None of the features +of ownership will slow down your program while it’s running. Because ownership is a new concept for many programmers, it does take some time to get used to. The good news is that the more experienced you become with Rust -and the rules of the ownership system, the more you’ll be able to naturally +and the rules of the ownership system, the easier you’ll find it to naturally develop code that is safe and efficient. Keep at it! When you understand ownership, you’ll have a solid foundation for understanding @@ -23,44 +21,44 @@ strings. > ### The Stack and the Heap > -> In many programming languages, you don’t have to think about the stack and -> the heap very often. But in a systems programming language like Rust, whether -> a value is on the stack or the heap has more of an effect on how the language -> behaves and why you have to make certain decisions. Parts of ownership will -> be described in relation to the stack and the heap later in this chapter, so -> here is a brief explanation in preparation. -> -> Both the stack and the heap are parts of memory that are available to your -> code to use at runtime, but they are structured in different ways. The stack -> stores values in the order it gets them and removes the values in the -> opposite order. This is referred to as *last in, first out*. Think of a stack -> of plates: when you add more plates, you put them on top of the pile, and -> when you need a plate, you take one off the top. Adding or removing plates -> from the middle or bottom wouldn’t work as well! Adding data is called -> *pushing onto the stack*, and removing data is called *popping off the stack*. +> Many programming languages don’t require you to think about the stack and the +> heap very often. But in a systems programming language like Rust, whether a +> value is on the stack or the heap affects how the language behaves and why +> you have to make certain decisions. Parts of ownership will be described in +> relation to the stack and the heap later in this chapter, so here is a brief +> explanation in preparation. > -> All data stored on the stack must have a known, fixed size. Data with an -> unknown size at compile time or a size that might change must be stored on -> the heap instead. The heap is less organized: when you put data on the heap, -> you request a certain amount of space. The memory allocator finds an empty -> spot in the heap that is big enough, marks it as being in use, and returns a -> *pointer*, which is the address of that location. This process is called -> *allocating on the heap* and is sometimes abbreviated as just *allocating*. -> Pushing values onto the stack is not considered allocating. Because the -> pointer is a known, fixed size, you can store the pointer on the stack, but -> when you want the actual data, you must follow the pointer. +> Both the stack and the heap are parts of memory available to your code to use +> at runtime, but they are structured in different ways. The stack stores +> values in the order it gets them and removes the values in the opposite +> order. This is referred to as *last in, first out*. Think of a stack of +> plates: when you add more plates, you put them on top of the pile, and when +> you need a plate, you take one off the top. Adding or removing plates from +> the middle or bottom wouldn’t work as well! Adding data is called *pushing +> onto the stack*, and removing data is called *popping off the stack*. All +> data stored on the stack must have a known, fixed size. Data with an unknown +> size at compile time or a size that might change must be stored on the heap +> instead. > -> Think of being seated at a restaurant. When you enter, you state the number of -> people in your group, and the staff finds an empty table that fits everyone -> and leads you there. If someone in your group comes late, they can ask where -> you’ve been seated to find you. +> The heap is less organized: when you put data on the heap, you request a +> certain amount of space. The memory allocator finds an empty spot in the heap +> that is big enough, marks it as being in use, and returns a *pointer*, which +> is the address of that location. This process is called *allocating on the +> heap* and is sometimes abbreviated as just *allocating*. Pushing values onto +> the stack is not considered allocating. Because the pointer to the heap is a +> known, fixed size, you can store the pointer on the stack, but when you want +> the actual data, you must follow the pointer. Think of being seated at a +> restaurant. When you enter, you state the number of people in your group, and +> the staff finds an empty table that fits everyone and leads you there. If +> someone in your group comes late, they can ask where you’ve been seated to +> find you. > > Pushing to the stack is faster than allocating on the heap because the -> allocator never has to search for a place to store new data; that -> location is always at the top of the stack. Comparatively, allocating space -> on the heap requires more work, because the allocator must first find -> a big enough space to hold the data and then perform bookkeeping to prepare -> for the next allocation. +> allocator never has to search for a place to store new data; that location is +> always at the top of the stack. Comparatively, allocating space on the heap +> requires more work, because the allocator must first find a big enough space +> to hold the data and then perform bookkeeping to prepare for the next +> allocation. > > Accessing data in the heap is slower than accessing data on the stack because > you have to follow a pointer to get there. Contemporary processors are faster @@ -82,8 +80,8 @@ strings. > minimizing the amount of duplicate data on the heap, and cleaning up unused > data on the heap so you don’t run out of space are all problems that ownership > addresses. Once you understand ownership, you won’t need to think about the -> stack and the heap very often, but knowing that managing heap data is why -> ownership exists can help explain why it works the way it does. +> stack and the heap very often, but knowing that the main purpose of ownership +> is to manage heap data can help explain why it works the way it does. ### Ownership Rules @@ -96,16 +94,15 @@ work through the examples that illustrate them: ### Variable Scope -We’ve walked through an example of a Rust program already in Chapter 2. Now -that we’re past basic syntax, we won’t include all the `fn main() {` code in -examples, so if you’re following along, you’ll have to put the following +Now that we’re past basic Rust syntax, we won’t include all the `fn main() {` +code in examples, so if you’re following along, make sure to put the following examples inside a `main` function manually. As a result, our examples will be a bit more concise, letting us focus on the actual details rather than boilerplate code. As a first example of ownership, we’ll look at the *scope* of some variables. A -scope is the range within a program for which an item is valid. Let’s say we -have a variable that looks like this: +scope is the range within a program for which an item is valid. Take the +following variable: ```rust let s = "hello"; @@ -113,8 +110,8 @@ let s = "hello"; The variable `s` refers to a string literal, where the value of the string is hardcoded into the text of our program. The variable is valid from the point at -which it’s declared until the end of the current *scope*. Listing 4-1 has -comments annotating where the variable `s` is valid. +which it’s declared until the end of the current *scope*. Listing 4-1 shows a +program with comments annotating where the variable `s` would be valid. ```rust {{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-01/src/main.rs:here}} @@ -135,18 +132,18 @@ understanding by introducing the `String` type. ### The `String` Type To illustrate the rules of ownership, we need a data type that is more complex -than the ones we covered in the [“Data Types”][data-types] -section of Chapter 3. The types covered previously are all a known size, can be -stored on the stack and popped off the stack when their scope is over, and can -be quickly and trivially copied to make a new, independent instance if another +than those we covered in the [“Data Types”][data-types] section +of Chapter 3. The types covered previously are all a known size, can be stored +on the stack and popped off the stack when their scope is over, and can be +quickly and trivially copied to make a new, independent instance if another part of code needs to use the same value in a different scope. But we want to look at data that is stored on the heap and explore how Rust knows when to -clean up that data. +clean up that data, and the `String` type is a great example. -We’ll use `String` as the example here and concentrate on the parts of `String` -that relate to ownership. These aspects also apply to other complex data types, -whether they are provided by the standard library or created by you. We’ll -discuss `String` in more depth in Chapter 8. +We’ll concentrate on the parts of `String` that relate to ownership. These +aspects also apply to other complex data types, whether they are provided by +the standard library or created by you. We’ll discuss `String` in more depth in +[Chapter 8][ch8]. We’ve already seen string literals, where a string value is hardcoded into our program. String literals are convenient, but they aren’t suitable for every @@ -162,9 +159,9 @@ literal using the `from` function, like so: let s = String::from("hello"); ``` -The double colon (`::`) is an operator that allows us to namespace this -particular `from` function under the `String` type rather than using some sort -of name like `string_from`. We’ll discuss this syntax more in the [“Method +The double colon `::` operator allows us to namespace this particular `from` +function under the `String` type rather than using some sort of name like +`string_from`. We’ll discuss this syntax more in the [“Method Syntax”][method-syntax] section of Chapter 5 and when we talk about namespacing with modules in [“Paths for Referring to an Item in the Module Tree”][paths-module-tree] in Chapter 7. @@ -200,13 +197,14 @@ requests the memory it needs. This is pretty much universal in programming languages. However, the second part is different. In languages with a *garbage collector -(GC)*, the GC keeps track and cleans up memory that isn’t being used anymore, -and we don’t need to think about it. Without a GC, it’s our responsibility to -identify when memory is no longer being used and call code to explicitly return -it, just as we did to request it. Doing this correctly has historically been a -difficult programming problem. If we forget, we’ll waste memory. If we do it -too early, we’ll have an invalid variable. If we do it twice, that’s a bug too. -We need to pair exactly one `allocate` with exactly one `free`. +(GC)*, the GC keeps track of and cleans up memory that isn’t being used +anymore, and we don’t need to think about it. In most languages without a GC, +it’s our responsibility to identify when memory is no longer being used and +call code to explicitly return it, just as we did to request it. Doing this +correctly has historically been a difficult programming problem. If we forget, +we’ll waste memory. If we do it too early, we’ll have an invalid variable. If +we do it twice, that’s a bug too. We need to pair exactly one `allocate` with +exactly one `free`. Rust takes a different path: the memory is automatically returned once the variable that owns it goes out of scope. Here’s a version of our scope example @@ -257,9 +255,9 @@ Now let’s look at the `String` version: {{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-03-string-move/src/main.rs:here}} ``` -This looks very similar to the previous code, so we might assume that the way -it works would be the same: that is, the second line would make a copy of the -value in `s1` and bind it to `s2`. But this isn’t quite what happens. +This looks very similar, so we might assume that the way it works would be the +same: that is, the second line would make a copy of the value in `s1` and bind +it to `s2`. But this isn’t quite what happens. Take a look at Figure 4-1 to see what is happening to `String` under the covers. A `String` is made up of three parts, shown on the left: a pointer to @@ -306,11 +304,10 @@ same memory. This is known as a *double free* error and is one of the memory safety bugs we mentioned previously. Freeing memory twice can lead to memory corruption, which can potentially lead to security vulnerabilities. -To ensure memory safety, there’s one more detail to what happens in this -situation in Rust. After `let s2 = s1`, Rust considers `s1` to no longer be -valid. Therefore, Rust doesn’t need to free anything when `s1` goes out of -scope. Check out what happens when you try to use `s1` after `s2` is created; -it won’t work: +To ensure memory safety, after the line `let s2 = s1`, Rust considers `s1` as +no longer valid. Therefore, Rust doesn’t need to free anything when `s1` goes +out of scope. Check out what happens when you try to use `s1` after `s2` is +created; it won’t work: ```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/src/main.rs:here}} @@ -326,7 +323,7 @@ invalidated reference: If you’ve heard the terms *shallow copy* and *deep copy* while working with other languages, the concept of copying the pointer, length, and capacity without copying the data probably sounds like making a shallow copy. But -because Rust also invalidates the first variable, instead of being called a +because Rust also invalidates the first variable, instead of calling it a shallow copy, it’s known as a *move*. In this example, we would say that `s1` was *moved* into `s2`. So what actually happens is shown in Figure 4-4. @@ -382,10 +379,10 @@ between deep and shallow copying here, so calling `clone` wouldn’t do anything different from the usual shallow copying and we can leave it out. Rust has a special annotation called the `Copy` trait that we can place on -types like integers that are stored on the stack (we’ll talk more about traits -in Chapter 10). If a type implements the `Copy` trait, an older variable is -still usable after assignment. Rust won’t let us annotate a type with the -`Copy` trait if the type, or any of its parts, has implemented the `Drop` +types that are stored on the stack like integers are (we’ll talk more about +traits in Chapter 10). If a type implements the `Copy` trait, a variable is +still valid after assignment to another variable. Rust won’t let us annotate a +type with `Copy` if the type, or any of its parts, has implemented the `Drop` trait. If the type needs something special to happen when the value goes out of scope and we add the `Copy` annotation to that type, we’ll get a compile-time error. To learn about how to add the `Copy` annotation to your type to @@ -428,8 +425,9 @@ the ownership rules prevent you from doing so. ### Return Values and Scope -Returning values can also transfer ownership. Listing 4-4 is an example with -similar annotations to those in Listing 4-3. +Returning values can also transfer ownership. Listing 4-4 shows an example +of a function that returns some value, with similar annotations as those in +Listing 4-3. Filename: src/main.rs @@ -442,16 +440,16 @@ values The ownership of a variable follows the same pattern every time: assigning a value to another variable moves it. When a variable that includes data on the -heap goes out of scope, the value will be cleaned up by `drop` unless the data -has been moved to be owned by another variable. +heap goes out of scope, the value will be cleaned up by `drop` unless ownership +of the data has been moved to another variable. -Taking ownership and then returning ownership with every function is a bit -tedious. What if we want to let a function use a value but not take ownership? -It’s quite annoying that anything we pass in also needs to be passed back if we -want to use it again, in addition to any data resulting from the body of the -function that we might want to return as well. +While this works, taking ownership and then returning ownership with every +function is a bit tedious. What if we want to let a function use a value but +not take ownership? It’s quite annoying that anything we pass in also needs to +be passed back if we want to use it again, in addition to any data resulting +from the body of the function that we might want to return as well. -It’s possible to return multiple values using a tuple, as shown in Listing 4-5. +Rust does let us return multiple values using a tuple, as shown in Listing 4-5. Filename: src/main.rs @@ -462,10 +460,11 @@ It’s possible to return multiple values using a tuple, as shown in Listing 4-5 Listing 4-5: Returning ownership of parameters But this is too much ceremony and a lot of work for a concept that should be -common. Luckily for us, Rust has a feature for this concept, called -*references*. +common. Luckily for us, Rust has a feature for using a value without +transferring ownership, called *references*. [data-types]: ch03-02-data-types.html#data-types +[ch8]: ch08-02-strings.html [derivable-traits]: appendix-03-derivable-traits.html [method-syntax]: ch05-03-method-syntax.html#method-syntax [paths-module-tree]: ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html diff --git a/src/doc/book/src/ch04-02-references-and-borrowing.md b/src/doc/book/src/ch04-02-references-and-borrowing.md index ccb0cf05aa..82b7a7b31d 100644 --- a/src/doc/book/src/ch04-02-references-and-borrowing.md +++ b/src/doc/book/src/ch04-02-references-and-borrowing.md @@ -3,10 +3,12 @@ The issue with the tuple code in Listing 4-5 is that we have to return the `String` to the calling function so we can still use the `String` after the call to `calculate_length`, because the `String` was moved into -`calculate_length`. - -Here is how you would define and use a `calculate_length` function that has a -reference to an object as a parameter instead of taking ownership of the +`calculate_length`. Instead, we can provide a reference to the `String` value. +A *reference* is like a pointer in that it’s an address we can follow to access +data stored at that address that is owned by some other variable. Unlike a +pointer, a reference is guaranteed to point to a valid value of a particular +type. Here is how you would define and use a `calculate_length` function that +has a reference to an object as a parameter instead of taking ownership of the value: Filename: src/main.rs @@ -18,10 +20,8 @@ value: First, notice that all the tuple code in the variable declaration and the function return value is gone. Second, note that we pass `&s1` into `calculate_length` and, in its definition, we take `&String` rather than -`String`. - -These ampersands are *references*, and they allow you to refer to some value -without taking ownership of it. Figure 4-5 shows a diagram. +`String`. These ampersands represent *references*, and they allow you to refer +to some value without taking ownership of it. Figure 4-5 depicts this concept. &String s pointing at String s1 @@ -51,14 +51,15 @@ the parameter `s` is a reference. Let’s add some explanatory annotations: ``` The scope in which the variable `s` is valid is the same as any function -parameter’s scope, but we don’t drop what the reference points to when `s` -stops being used because we don’t have ownership. When functions have -references as parameters instead of the actual values, we won’t need to return -the values in order to give back ownership, because we never had ownership. +parameter’s scope, but the value pointed to by the reference is not dropped +when `s` stops being used because `s` doesn’t have ownership. When functions +have references as parameters instead of the actual values, we won’t need to +return the values in order to give back ownership, because we never had +ownership. We call the action of creating a reference *borrowing*. As in real life, if a person owns something, you can borrow it from them. When you’re done, you have -to give it back. +to give it back. You don’t own it. So what happens if we try to modify something we’re borrowing? Try the code in Listing 4-6. Spoiler alert: it doesn’t work! @@ -82,7 +83,8 @@ allowed to modify something we have a reference to. ### Mutable References -We can fix the error in the code from Listing 4-6 with just a few small tweaks: +We can fix the code from Listing 4-6 to allow us to modify a borrowed value +with just a few small tweaks that use, instead, a *mutable reference*: Filename: src/main.rs @@ -90,14 +92,14 @@ We can fix the error in the code from Listing 4-6 with just a few small tweaks: {{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-09-fixes-listing-04-06/src/main.rs}} ``` -First, we had to change `s` to be `mut`. Then we had to create a mutable -reference with `&mut s` where we call the `change` function, and update the -function signature to accept a mutable reference with `some_string: &mut -String`. This makes it very clear that the `change` function will mutate the -value it borrows. +First, we change `s` to be `mut`. Then we create a mutable reference with `&mut +s` where we call the `change` function, and update the function signature to +accept a mutable reference with `some_string: &mut String`. This makes it very +clear that the `change` function will mutate the value it borrows. -But mutable references have one big restriction: you can have only one mutable -reference to a particular piece of data at a time. This code will fail: +Mutable references have one big restriction: you can have only one mutable +reference to a particular piece of data at a time. This code that attempts to +create two mutable references to `s` will fail: Filename: src/main.rs @@ -120,11 +122,9 @@ in `r2` that borrows the same data as `r1`. The restriction preventing multiple mutable references to the same data at the same time allows for mutation but in a very controlled fashion. It’s something that new Rustaceans struggle with, because most languages let you mutate -whenever you’d like. - -The benefit of having this restriction is that Rust can prevent data races at -compile time. A *data race* is similar to a race condition and happens when -these three behaviors occur: +whenever you’d like. The benefit of having this restriction is that Rust can +prevent data races at compile time. A *data race* is similar to a race +condition and happens when these three behaviors occur: * Two or more pointers access the same data at the same time. * At least one of the pointers is being used to write to the data. @@ -132,7 +132,7 @@ these three behaviors occur: Data races cause undefined behavior and can be difficult to diagnose and fix when you’re trying to track them down at runtime; Rust prevents this problem -from happening because it won’t even compile code with data races! +by refusing to compile code with data races! As always, we can use curly brackets to create a new scope, allowing for multiple mutable references, just not *simultaneous* ones: @@ -141,8 +141,8 @@ multiple mutable references, just not *simultaneous* ones: {{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-11-muts-in-separate-scopes/src/main.rs:here}} ``` -A similar rule exists for combining mutable and immutable references. This code -results in an error: +Rust enforces a similar rule for combining mutable and immutable references. +This code results in an error: ```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/src/main.rs:here}} @@ -154,11 +154,11 @@ Here’s the error: {{#include ../listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/output.txt}} ``` -Whew! We *also* cannot have a mutable reference while we have an immutable one. -Users of an immutable reference don’t expect the values to suddenly change out -from under them! However, multiple immutable references are okay because no one -who is just reading the data has the ability to affect anyone else’s reading of -the data. +Whew! We *also* cannot have a mutable reference while we have an immutable one +to the same value. Users of an immutable reference don’t expect the value to +suddenly change out from under them! However, multiple immutable references are +allowed because no one who is just reading the data has the ability to affect +anyone else’s reading of the data. Note that a reference’s scope starts from where it is introduced and continues through the last time that reference is used. For instance, this code will @@ -173,7 +173,7 @@ The scopes of the immutable references `r1` and `r2` end after the `println!` where they are last used, which is before the mutable reference `r3` is created. These scopes don’t overlap, so this code is allowed. The ability of the compiler to tell that a reference is no longer being used at a point before -the end of the scope is called Non-Lexical Lifetimes (NLL for short), and you +the end of the scope is called *Non-Lexical Lifetimes* (NLL for short), and you can read more about it in [The Edition Guide][nll]. Even though borrowing errors may be frustrating at times, remember that it’s @@ -184,14 +184,14 @@ have to track down why your data isn’t what you thought it was. ### Dangling References In languages with pointers, it’s easy to erroneously create a *dangling -pointer*, a pointer that references a location in memory that may have been -given to someone else, by freeing some memory while preserving a pointer to +pointer*--a pointer that references a location in memory that may have been +given to someone else--by freeing some memory while preserving a pointer to that memory. In Rust, by contrast, the compiler guarantees that references will never be dangling references: if you have a reference to some data, the compiler will ensure that the data will not go out of scope before the reference to the data does. -Let’s try to create a dangling reference, which Rust will prevent with a +Let’s try to create a dangling reference to see how Rust prevents them with a compile-time error: Filename: src/main.rs @@ -212,7 +212,7 @@ about lifetimes, the message does contain the key to why this code is a problem: ```text this function's return type contains a borrowed value, but there is no value -for it to be borrowed from. +for it to be borrowed from ``` Let’s take a closer look at exactly what’s happening at each stage of our diff --git a/src/doc/book/src/ch04-03-slices.md b/src/doc/book/src/ch04-03-slices.md index 68f147295d..fe7bd6a155 100644 --- a/src/doc/book/src/ch04-03-slices.md +++ b/src/doc/book/src/ch04-03-slices.md @@ -1,24 +1,25 @@ ## The Slice Type -Another data type that does not have ownership is the *slice*. Slices let you -reference a contiguous sequence of elements in a collection rather than the -whole collection. +*Slices* let you reference a contiguous sequence of elements in a collection +rather than the whole collection. A slice is a kind of reference, so it does +not have ownership. Here’s a small programming problem: write a function that takes a string and returns the first word it finds in that string. If the function doesn’t find a space in the string, the whole string must be one word, so the entire string should be returned. -Let’s think about the signature of this function: +Let’s work through how we’d write the signature of this function without using +slices, to understand the problem that slices will solve: ```rust,ignore fn first_word(s: &String) -> ? ``` -This function, `first_word`, has a `&String` as a parameter. We don’t want +The `first_word` function has a `&String` as a parameter. We don’t want ownership, so this is fine. But what should we return? We don’t really have a way to talk about *part* of a string. However, we could return the index of the -end of the word. Let’s try that, as shown in Listing 4-7. +end of the word, indicated by a space. Let’s try that, as shown in Listing 4-7. Filename: src/main.rs @@ -43,18 +44,19 @@ Next, we create an iterator over the array of bytes using the `iter` method: {{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-07/src/main.rs:iter}} ``` -We’ll discuss iterators in more detail in Chapter 13. For now, know that `iter` -is a method that returns each element in a collection and that `enumerate` -wraps the result of `iter` and returns each element as part of a tuple instead. -The first element of the tuple returned from `enumerate` is the index, and the -second element is a reference to the element. This is a bit more convenient -than calculating the index ourselves. +We’ll discuss iterators in more detail in [Chapter 13][ch13]. +For now, know that `iter` is a method that returns each element in a collection +and that `enumerate` wraps the result of `iter` and returns each element as +part of a tuple instead. The first element of the tuple returned from +`enumerate` is the index, and the second element is a reference to the element. +This is a bit more convenient than calculating the index ourselves. Because the `enumerate` method returns a tuple, we can use patterns to -destructure that tuple. We'll be discussing patterns more in Chapter 6. So in -the `for` loop, we specify a pattern that has `i` for the index in the tuple -and `&item` for the single byte in the tuple. Because we get a reference to the -element from `.iter().enumerate()`, we use `&` in the pattern. +destructure that tuple. We’ll be discussing patterns more in [Chapter +6][ch6]. In the `for` loop, we specify a pattern that has `i` +for the index in the tuple and `&item` for the single byte in the tuple. +Because we get a reference to the element from `.iter().enumerate()`, we use +`&` in the pattern. Inside the `for` loop, we search for the byte that represents the space by using the byte literal syntax. If we find a space, we return the position. @@ -96,7 +98,7 @@ fn second_word(s: &String) -> (usize, usize) { Now we’re tracking a starting *and* an ending index, and we have even more values that were calculated from data in a particular state but aren’t tied to -that state at all. We now have three unrelated variables floating around that +that state at all. We have three unrelated variables floating around that need to be kept in sync. Luckily, Rust has a solution to this problem: string slices. @@ -109,18 +111,15 @@ A *string slice* is a reference to part of a `String`, and it looks like this: {{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-17-slice/src/main.rs:here}} ``` -This is similar to taking a reference to the whole `String` but with the extra -`[0..5]` bit. Rather than a reference to the entire `String`, it’s a reference -to a portion of the `String`. - -We can create slices using a range within brackets by specifying -`[starting_index..ending_index]`, where `starting_index` is the first position -in the slice and `ending_index` is one more than the last position in the -slice. Internally, the slice data structure stores the starting position and -the length of the slice, which corresponds to `ending_index` minus -`starting_index`. So in the case of `let world = &s[6..11];`, `world` would be -a slice that contains a pointer to the byte at index 6 of `s` with a length -value of 5. +Rather than a reference to the entire `String`, `hello` is a reference to a +portion of the `String`, specified in the extra `[0..5]` bit. We create slices +using a range within brackets by specifying `[starting_index..ending_index]`, +where `starting_index` is the first position in the slice and `ending_index` is +one more than the last position in the slice. Internally, the slice data +structure stores the starting position and the length of the slice, which +corresponds to `ending_index` minus `starting_index`. So in the case of `let +world = &s[6..11];`, `world` would be a slice that contains a pointer to the +byte at index 6 of `s` with a length value of 5. Figure 4-6 shows this in a diagram. @@ -309,5 +308,7 @@ Ownership affects how lots of other parts of Rust work, so we’ll talk about these concepts further throughout the rest of the book. Let’s move on to Chapter 5 and look at grouping pieces of data together in a `struct`. +[ch13]: ch13-02-iterators.html +[ch6]: ch06-02-match.html#patterns-that-bind-to-values [strings]: ch08-02-strings.html#storing-utf-8-encoded-text-with-strings [deref-coercions]: ch15-02-deref.html#implicit-deref-coercions-with-functions-and-methods diff --git a/src/doc/book/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md b/src/doc/book/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md index fc3980e468..0879b9066d 100644 --- a/src/doc/book/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md +++ b/src/doc/book/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md @@ -97,7 +97,7 @@ see and do everything in the restaurant in which they operate. Rust chose to have the module system function this way so that hiding inner implementation details is the default. That way, you know which parts of the inner code you can change without breaking outer code. But you can expose inner -parts of child modules' code to outer ancestor modules by using the `pub` +parts of child modules’ code to outer ancestor modules by using the `pub` keyword to make an item public. ### Exposing Paths with the `pub` Keyword diff --git a/src/doc/book/src/ch08-01-vectors.md b/src/doc/book/src/ch08-01-vectors.md index 934eff4360..c629cc5aab 100644 --- a/src/doc/book/src/ch08-01-vectors.md +++ b/src/doc/book/src/ch08-01-vectors.md @@ -193,7 +193,7 @@ elements in a vector To change the value that the mutable reference refers to, we have to use the dereference operator (`*`) to get to the value in `i` before we can use the `+=` operator. We’ll talk more about the dereference operator in the -[“Following the Pointer to the Value with the Dereference Operator”][deref] +[“Following the Pointer to the Value with the Dereference Operator”][deref] section of Chapter 15. ### Using an Enum to Store Multiple Types @@ -232,12 +232,12 @@ the program will get at runtime to store in a vector, the enum technique won’t work. Instead, you can use a trait object, which we’ll cover in Chapter 17. Now that we’ve discussed some of the most common ways to use vectors, be sure -to review [the API documentation][vec-api] for all the many useful methods defined on -`Vec` by the standard library. For example, in addition to `push`, a `pop` -method removes and returns the last element. Let’s move on to the next -collection type: `String`! +to review [the API documentation][vec-api] for all the many +useful methods defined on `Vec` by the standard library. For example, in +addition to `push`, a `pop` method removes and returns the last element. Let’s +move on to the next collection type: `String`! [data-types]: ch03-02-data-types.html#data-types -[nomicon]: ../nomicon/vec.html +[nomicon]: ../nomicon/vec/vec.html [vec-api]: ../std/vec/struct.Vec.html [deref]: ch15-02-deref.html#following-the-pointer-to-the-value-with-the-dereference-operator diff --git a/src/doc/book/src/ch08-02-strings.md b/src/doc/book/src/ch08-02-strings.md index 9daefa91aa..03b006d9b8 100644 --- a/src/doc/book/src/ch08-02-strings.md +++ b/src/doc/book/src/ch08-02-strings.md @@ -130,7 +130,7 @@ If the `push_str` method took ownership of `s2`, we wouldn’t be able to print its value on the last line. However, this code works as we’d expect! The `push` method takes a single character as a parameter and adds it to the -`String`. Listing 8-17 shows code that adds the letter "l" to a `String` using +`String`. Listing 8-17 shows code that adds the letter “l” to a `String` using the `push` method. ```rust @@ -400,7 +400,8 @@ than 1 byte. Getting grapheme clusters from strings is complex, so this functionality is not provided by the standard library. Crates are available on -[crates.io](https://crates.io/) if this is the functionality you need. +[crates.io](https://crates.io/) if this is the functionality you +need. ### Strings Are Not So Simple diff --git a/src/doc/book/src/ch08-03-hash-maps.md b/src/doc/book/src/ch08-03-hash-maps.md index 2708f11790..ba77b79fd7 100644 --- a/src/doc/book/src/ch08-03-hash-maps.md +++ b/src/doc/book/src/ch08-03-hash-maps.md @@ -199,25 +199,28 @@ the value 0. map that stores words and counts This code will print `{"world": 2, "hello": 1, "wonderful": 1}`. The -`or_insert` method actually returns a mutable reference (`&mut V`) to the value -for this key. Here we store that mutable reference in the `count` variable, so -in order to assign to that value, we must first dereference `count` using the -asterisk (`*`). The mutable reference goes out of scope at the end of the `for` -loop, so all of these changes are safe and allowed by the borrowing rules. +`split_whitespace` method iterates over sub-slices, separated by whitespace, of +the value in `text`. The `or_insert` method returns a mutable reference (`&mut +V`) to the value for the specified key. Here we store that mutable reference in +the `count` variable, so in order to assign to that value, we must first +dereference `count` using the asterisk (`*`). The mutable reference goes out of +scope at the end of the `for` loop, so all of these changes are safe and +allowed by the borrowing rules. ### Hashing Functions By default, `HashMap` uses a hashing function called SipHash that can provide -resistance to Denial of Service (DoS) attacks involving hash tables[^siphash]. This -is not the fastest hashing algorithm available, but the trade-off for better -security that comes with the drop in performance is worth it. If you profile -your code and find that the default hash function is too slow for your -purposes, you can switch to another function by specifying a different -*hasher*. A hasher is a type that implements the `BuildHasher` trait. We’ll -talk about traits and how to implement them in Chapter 10. You don’t -necessarily have to implement your own hasher from scratch; -[crates.io](https://crates.io/) has libraries shared by other Rust users that -provide hashers implementing many common hashing algorithms. +resistance to Denial of Service (DoS) attacks involving hash +tables[^siphash]. This is not the fastest hashing algorithm +available, but the trade-off for better security that comes with the drop in +performance is worth it. If you profile your code and find that the default +hash function is too slow for your purposes, you can switch to another function +by specifying a different *hasher*. A hasher is a type that implements the +`BuildHasher` trait. We’ll talk about traits and how to implement them in +Chapter 10. You don’t necessarily have to implement your own hasher from +scratch; [crates.io](https://crates.io/) has libraries shared by +other Rust users that provide hashers implementing many common hashing +algorithms. [^siphash]: [https://en.wikipedia.org/wiki/SipHash](https://en.wikipedia.org/wiki/SipHash) @@ -227,9 +230,9 @@ Vectors, strings, and hash maps will provide a large amount of functionality necessary in programs when you need to store, access, and modify data. Here are some exercises you should now be equipped to solve: -* Given a list of integers, use a vector and return the mean (the average - value), median (when sorted, the value in the middle position), and mode (the - value that occurs most often; a hash map will be helpful here) of the list. +* Given a list of integers, use a vector and return the median (when sorted, + the value in the middle position) and mode (the value that occurs most often; + a hash map will be helpful here) of the list. * Convert strings to pig latin. The first consonant of each word is moved to the end of the word and “ay” is added, so “first” becomes “irst-fay.” Words that start with a vowel have “hay” added to the end instead (“apple” becomes diff --git a/src/doc/book/src/ch09-02-recoverable-errors-with-result.md b/src/doc/book/src/ch09-02-recoverable-errors-with-result.md index ba8168dbee..7f5a97e76d 100644 --- a/src/doc/book/src/ch09-02-recoverable-errors-with-result.md +++ b/src/doc/book/src/ch09-02-recoverable-errors-with-result.md @@ -260,22 +260,24 @@ body that might fail: the `File::open` function and the `read_to_string` method. The body of the function starts by calling the `File::open` function. Then we -handle the `Result` value returned with a `match` similar to the `match` in -Listing 9-4, only instead of calling `panic!` in the `Err` case, we return -early from this function and pass the error value from `File::open` back to the -calling code as this function’s error value. If `File::open` succeeds, we store -the file handle in the variable `f` and continue. - -Then we create a new `String` in variable `s` and call the `read_to_string` -method on the file handle in `f` to read the contents of the file into `s`. The -`read_to_string` method also returns a `Result` because it might fail, even -though `File::open` succeeded. So we need another `match` to handle that -`Result`: if `read_to_string` succeeds, then our function has succeeded, and we -return the username from the file that’s now in `s` wrapped in an `Ok`. If -`read_to_string` fails, we return the error value in the same way that we -returned the error value in the `match` that handled the return value of -`File::open`. However, we don’t need to explicitly say `return`, because this -is the last expression in the function. +handle the `Result` value with a `match` similar to the `match` in Listing 9-4. +If `File::open` succeeds, the file handle in the pattern variable `file` +becomes the value in the mutable variable `f` and the function continues. In +the `Err` case, instead of calling `panic!`, we use the `return` keyword to +return early out of the function entirely and pass the error value from +`File::open`, now in the pattern variable `e`, back to the calling code as this +function’s error value. + +So if we have a file handle in `f`, the function then creates a new `String` in +variable `s` and calls the `read_to_string` method on the file handle in `f` to +read the contents of the file into `s`. The `read_to_string` method also +returns a `Result` because it might fail, even though `File::open` succeeded. +So we need another `match` to handle that `Result`: if `read_to_string` +succeeds, then our function has succeeded, and we return the username from the +file that’s now in `s` wrapped in an `Ok`. If `read_to_string` fails, we return +the error value in the same way that we returned the error value in the `match` +that handled the return value of `File::open`. However, we don’t need to +explicitly say `return`, because this is the last expression in the function. The code that calls this code will then handle getting either an `Ok` value that contains a username or an `Err` value that contains an `io::Error`. We @@ -322,11 +324,11 @@ on them go through the `from` function, defined in the `From` trait in the standard library, which is used to convert errors from one type into another. When the `?` operator calls the `from` function, the error type received is converted into the error type defined in the return type of the current -function. This is useful when a function returns one error type to represent all -the ways a function might fail, even if parts might fail for many different -reasons. As long as each error type implements the `from` function to define how -to convert itself to the returned error type, the `?` operator takes care of the -conversion automatically. +function. This is useful when a function returns one error type to represent +all the ways a function might fail, even if parts might fail for many different +reasons. As long as there’s an `impl From for ReturnedError` to +define the conversion in the trait’s `from` function, the `?` operator takes +care of calling the `from` function automatically. In the context of Listing 9-7, the `?` at the end of the `File::open` call will return the value inside an `Ok` to the variable `f`. If an error occurs, the @@ -383,53 +385,130 @@ and returns it. Of course, using `fs::read_to_string` doesn’t give us the opportunity to explain all the error handling, so we did it the longer way first. -#### The `?` Operator Can Be Used in Functions That Return `Result` +#### Where The `?` Operator Can Be Used -The `?` operator can be used in functions that have a return type of -`Result`, because it is defined to work in the same way as the `match` -expression we defined in Listing 9-6. The part of the `match` that requires a -return type of `Result` is `return Err(e)`, so the return type of the function -has to be a `Result` to be compatible with this `return`. +The `?` operator can only be used in functions that have a return type +compatible with the value the `?` is used on. This is because the `?` operator +is defined to perform an early return of a value out of the function, in the +same manner as the `match` expression we defined in Listing 9-6 did. In Listing +9-6, the `match` was using a `Result` value, and the early return arm returned +an `Err(e)` value. The return type of the function has to be a `Result` to be +compatible with this `return`. -Let’s look at what happens if we use the `?` operator in the `main` function, -which you’ll recall has a return type of `()`: +In Listing 9-10, let’s look at the error we’ll get if we use the `?` operator +in a `main` function with a return type of `()`: ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch09-error-handling/no-listing-06-question-mark-in-main/src/main.rs}} +{{#rustdoc_include ../listings/ch09-error-handling/listing-09-10/src/main.rs}} ``` -When we compile this code, we get the following error message: +Listing 9-10: Attempting to use the `?` in the `main` +function that returns `()` won’t compile + +This code opens a file, which might fail. The `?` operator follows the `Result` +value returned by `File::open`, but this `main` function has the return type of +`()`, not `Result`. When we compile this code, we get the following error +message: ```console -{{#include ../listings/ch09-error-handling/no-listing-06-question-mark-in-main/output.txt}} +{{#include ../listings/ch09-error-handling/listing-09-10/output.txt}} ``` This error points out that we’re only allowed to use the `?` operator in a -function that returns `Result` or `Option` or another type that implements -`std::ops::Try`. When you’re writing code in a function -that doesn’t return one of these types, and you want to use `?` when you call other -functions that return `Result`, you have two choices to fix this problem. -One technique is to change the return type of your function to be `Result` if you have no restrictions preventing that. The other technique is to use -a `match` or one of the `Result` methods to handle the `Result` in -whatever way is appropriate. - -The `main` function is special, and there are restrictions on what its return -type must be. One valid return type for main is `()`, and conveniently, another -valid return type is `Result`, as shown here: +function that returns `Result`, `Option`, or another type that implements +`FromResidual`. To fix this error, you have two choices. One technique is to +change the return type of your function to be `Result` if you have no +restrictions preventing that. The other technique is to use a `match` or one of +the `Result` methods to handle the `Result` in whatever way is +appropriate. + +The error message also mentioned that `?` can be used with `Option` values +as well. As with using `?` on `Result`, you can only use `?` on `Option` in a +function that returns an `Option`. The behavior of the `?` operator when called +on an `Option` is similar to its behavior when called on a `Result`: +if the value is `None`, the `None` will be returned early from the function at +that point. If the value is `Some`, the value inside the `Some` is the +resulting value of the expression and the function continues. Listing 9-11 has +an example of a function that finds the last character of the first line in the +given text: + +```rust +{{#rustdoc_include ../listings/ch09-error-handling/listing-09-11/src/main.rs:here}} +``` + +Listing 9-11: Using the `?` operator on an `Option` +value + +This function returns `Option` because it might find a character at this +position, or there might be no character there. This code takes the `text` +string slice argument and calls the `lines` method on it, which returns an +iterator over the lines in the string. Because this function wants to examine +the first line, it calls `next` on the iterator to get the first value from the +iterator. If `text` is the empty string, this call to `next` will return +`None`, and here we can use `?` to stop and return `None` from +`last_char_of_first_line` if that is the case. If `text` is not the empty +string, `next` will return a `Some` value containing a string slice of the +first line in `text`. + +The `?` extracts the string slice, and we can call `chars` on that string slice +to get an iterator of the characters in this string slice. We’re interested in +the last character in this first line, so we call `last` to return the last +item in the iterator over the characters. This is an `Option` because the first +line might be the empty string, if `text` starts with a blank line but has +characters on other lines, as in `"\nhi"`. However, if there is a last +character on the first line, it will be returned in the `Some` variant. The `?` +operator in the middle gives us a concise way to express this logic, and this +function can be implemented in one line. If we couldn’t use the `?` operator on +`Option`, we’d have to implement this logic using more method calls or a +`match` expression. + +Note that you can use the `?` operator on a `Result` in a function that returns +`Result`, and you can use the `?` operator on an `Option` in a function that +returns `Option`, but you can’t mix and match. The `?` operator won’t +automatically convert a `Result` to an `Option` or vice versa; in those cases, +there are methods like the `ok` method on `Result` or the `ok_or` method on +`Option` that will do the conversion explicitly. + +So far, all the `main` functions we’ve used return `()`. The `main` function is +special because it’s the entry and exit point of executable programs, and there +are restrictions on what its return type can be for the programs to behave as +expected. Executables written in C return integers when they exit, and Rust +executables follow this convention as well: programs that exit successfully +return the integer `0`, and programs that error return some integer other than +`0`. When `main` returns `()`, Rust executables will return `0` if `main` +returns and a nonzero value if the program panics before reaching the end of +`main`. + +Another return type `main` can have is `Result<(), E>`. Listing 9-12 has the +code from Listing 9-10 but we’ve changed the return type of `main` to be +`Result<(), Box>` and added a return value `Ok(())` to the end. This +code will now compile: ```rust,ignore -{{#rustdoc_include ../listings/ch09-error-handling/no-listing-07-main-returning-result/src/main.rs}} +{{#rustdoc_include ../listings/ch09-error-handling/listing-09-12/src/main.rs}} ``` +Listing 9-12: Changing `main` to return `Result<(), E>` +allows the use of the `?` operator on `Result` values + The `Box` type is called a trait object, which we’ll talk about in the [“Using Trait Objects that Allow for Values of Different Types”][trait-objects] section in Chapter 17. For now, you can -read `Box` to mean “any kind of error.” Using `?` in a `main` -function with this return type is allowed. +read `Box` to mean “any kind of error.” Using `?` on a `Result` +value in a `main` function with this return type is allowed, because now an +`Err` value can be returned early. When a `main` function returns a `Result<(), +E>`, the executable will exit with a value of `0` if `main` returns `Ok(())` +and will exit with a nonzero value if `main` returns an `Err` value. + +The types that `main` may return are those that implement [the +`std::process::Termination` trait][termination]. As of this +writing, the `Termination` trait is an unstable feature only available in +Nightly Rust, so you can’t yet implement it for your own types in Stable Rust, +but you might be able to someday! Now that we’ve discussed the details of calling `panic!` or returning `Result`, let’s return to the topic of how to decide which is appropriate to use in which cases. [trait-objects]: ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types +[termination]: ../std/process/trait.Termination.html diff --git a/src/doc/book/src/ch09-03-to-panic-or-not-to-panic.md b/src/doc/book/src/ch09-03-to-panic-or-not-to-panic.md index e5af81d0eb..92decf4066 100644 --- a/src/doc/book/src/ch09-03-to-panic-or-not-to-panic.md +++ b/src/doc/book/src/ch09-03-to-panic-or-not-to-panic.md @@ -69,9 +69,14 @@ assumption, guarantee, contract, or invariant has been broken, such as when invalid values, contradictory values, or missing values are passed to your code—plus one or more of the following: -* The bad state is not something that’s *expected* to happen occasionally. -* Your code after this point needs to rely on not being in this bad state. -* There’s not a good way to encode this information in the types you use. +* The bad state is something that is unexpected, as opposed to something that + will likely happen occasionally, like a user entering data in the wrong + format. +* Your code after this point needs to rely on not being in this bad state, + rather than checking for the problem at every step. +* There’s not a good way to encode this information in the types you use. We’ll + work through an example of what we mean in the [“Encoding States and Behavior + as Types”][encoding] section of Chapter 17. If someone calls your code and passes in values that don’t make sense, the best choice might be to call `panic!` and alert the person using your library to the @@ -148,7 +153,7 @@ tedious (and might impact performance). Instead, we can make a new type and put the validations in a function to create an instance of the type rather than repeating the validations everywhere. That way, it’s safe for functions to use the new type in their signatures and -confidently use the values they receive. Listing 9-10 shows one way to define a +confidently use the values they receive. Listing 9-13 shows one way to define a `Guess` type that will only create an instance of `Guess` if the `new` function receives a value between 1 and 100. @@ -158,10 +163,10 @@ experimentation purposes, but don't want to include it for rustdoc testing purposes. --> ```rust -{{#include ../listings/ch09-error-handling/listing-09-10/src/main.rs:here}} +{{#include ../listings/ch09-error-handling/listing-09-13/src/main.rs:here}} ``` -Listing 9-10: A `Guess` type that will only continue with +Listing 9-13: A `Guess` type that will only continue with values between 1 and 100 First, we define a struct named `Guess` that has a field named `value` that @@ -209,3 +214,5 @@ situations will make your code more reliable in the face of inevitable problems. Now that you’ve seen useful ways that the standard library uses generics with the `Option` and `Result` enums, we’ll talk about how generics work and how you can use them in your code. + +[encoding]: ch17-03-oo-design-patterns.html#encoding-states-and-behavior-as-types diff --git a/src/doc/book/src/ch10-00-generics.md b/src/doc/book/src/ch10-00-generics.md index c0375a12ba..14f46ad708 100644 --- a/src/doc/book/src/ch10-00-generics.md +++ b/src/doc/book/src/ch10-00-generics.md @@ -94,10 +94,10 @@ in two lists The `largest` function has a parameter called `list`, which represents any concrete slice of `i32` values that we might pass into the function. As a result, when we call the function, the code runs on the specific values that we -pass in. Don't worry about the syntax of the `for` loop for now. We aren't -referencing a reference to an `i32` here; we're pattern matching and +pass in. Don’t worry about the syntax of the `for` loop for now. We aren’t +referencing a reference to an `i32` here; we’re pattern matching and destructuring each `&i32` that the `for` loop gets so that `item` will be an -`i32` inside the loop body. We'll cover pattern matching in detail in [Chapter +`i32` inside the loop body. We’ll cover pattern matching in detail in [Chapter 18][ch18]. In sum, here are the steps we took to change the code from Listing 10-2 to diff --git a/src/doc/book/src/ch10-01-syntax.md b/src/doc/book/src/ch10-01-syntax.md index 0eb8b56892..e3b3a6c5b6 100644 --- a/src/doc/book/src/ch10-01-syntax.md +++ b/src/doc/book/src/ch10-01-syntax.md @@ -210,13 +210,20 @@ Here, we’ve defined a method named `x` on `Point` that returns a reference to the data in the field `x`. Note that we have to declare `T` just after `impl` so we can use it to specify -that we’re implementing methods on the type `Point`. By declaring `T` as a +that we’re implementing methods on the type `Point`. By declaring `T` as a generic type after `impl`, Rust can identify that the type in the angle -brackets in `Point` is a generic type rather than a concrete type. - -We could, for example, implement methods only on `Point` instances rather -than on `Point` instances with any generic type. In Listing 10-10 we use the -concrete type `f32`, meaning we don’t declare any types after `impl`. +brackets in `Point` is a generic type rather than a concrete type. Because this +is declaring the generic again, we could have chosen a different name for the +generic parameter than the generic parameter declared in the struct definition, +but using the same name is conventional. Methods written within an `impl` that +declares the generic type will be defined on any instance of the type, no +matter what concrete type ends up substituting for the generic type. + +The other option we have is defining methods on the type with some constraint +on the generic type. We could, for example, implement methods only on +`Point` instances rather than on `Point` instances with any generic +type. In Listing 10-10 we use the concrete type `f32`, meaning we don’t declare +any types after `impl`. Filename: src/main.rs @@ -234,12 +241,11 @@ point is from the point at coordinates (0.0, 0.0) and uses mathematical operations that are available only for floating point types. Generic type parameters in a struct definition aren’t always the same as those -you use in that struct’s method signatures. For example, Listing 10-11 defines -the method `mixup` on the `Point` struct from Listing 10-8. The method -takes another `Point` as a parameter, which might have different types from the -`self` `Point` we’re calling `mixup` on. The method creates a new `Point` -instance with the `x` value from the `self` `Point` (of type `T`) and the `y` -value from the passed-in `Point` (of type `W`). +you use in that struct’s method signatures. Listing 10-11 uses the generic +types `X1` and `Y1` for the `Point` struct and `X2` `Y2` for the `mixup` method +signature to make the example clearer. The method creates a new `Point` +instance with the `x` value from the `self` `Point` (of type `X1`) and the `y` +value from the passed-in `Point` (of type `Y2`). Filename: src/main.rs @@ -260,9 +266,10 @@ call will print `p3.x = 5, p3.y = c`. The purpose of this example is to demonstrate a situation in which some generic parameters are declared with `impl` and some are declared with the method -definition. Here, the generic parameters `T` and `U` are declared after `impl`, -because they go with the struct definition. The generic parameters `V` and `W` -are declared after `fn mixup`, because they’re only relevant to the method. +definition. Here, the generic parameters `X1` and `Y1` are declared after +`impl` because they go with the struct definition. The generic parameters `X2` +and `Y2` are declared after `fn mixup`, because they’re only relevant to the +method. ### Performance of Code Using Generics diff --git a/src/doc/book/src/ch10-02-traits.md b/src/doc/book/src/ch10-02-traits.md index 083b767f59..98dedde148 100644 --- a/src/doc/book/src/ch10-02-traits.md +++ b/src/doc/book/src/ch10-02-traits.md @@ -21,11 +21,11 @@ particular location and a `Tweet` that can have at most 280 characters along with metadata that indicates whether it was a new tweet, a retweet, or a reply to another tweet. -We want to make a media aggregator library that can display summaries of data -that might be stored in a `NewsArticle` or `Tweet` instance. To do this, we -need a summary from each type, and we need to request that summary by calling a -`summarize` method on an instance. Listing 10-12 shows the definition of a -`Summary` trait that expresses this behavior. +We want to make a media aggregator library crate named `aggregator` that can +display summaries of data that might be stored in a `NewsArticle` or `Tweet` +instance. To do this, we need a summary from each type, and we’ll request +that summary by calling a `summarize` method on an instance. Listing 10-12 +shows the definition of a public `Summary` trait that expresses this behavior. Filename: src/lib.rs @@ -37,9 +37,11 @@ need a summary from each type, and we need to request that summary by calling a behavior provided by a `summarize` method Here, we declare a trait using the `trait` keyword and then the trait’s name, -which is `Summary` in this case. Inside the curly brackets, we declare the -method signatures that describe the behaviors of the types that implement this -trait, which in this case is `fn summarize(&self) -> String`. +which is `Summary` in this case. We’ve also declared the trait as `pub` so that +crates depending on this crate can make use of this trait too, as we’ll see in +a few examples. Inside the curly brackets, we declare the method signatures +that describe the behaviors of the types that implement this trait, which in +this case is `fn summarize(&self) -> String`. After the method signature, instead of providing an implementation within curly brackets, we use a semicolon. Each type implementing this trait must provide @@ -52,10 +54,10 @@ one per line and each line ends in a semicolon. ### Implementing a Trait on a Type -Now that we’ve defined the desired behavior using the `Summary` trait, we can -implement it on the types in our media aggregator. Listing 10-13 shows an -implementation of the `Summary` trait on the `NewsArticle` struct that uses the -headline, the author, and the location to create the return value of +Now that we’ve defined the desired signatures of the `Summary` trait’s methods, +we can implement it on the types in our media aggregator. Listing 10-13 shows +an implementation of the `Summary` trait on the `NewsArticle` struct that uses +the headline, the author, and the location to create the return value of `summarize`. For the `Tweet` struct, we define `summarize` as the username followed by the entire text of the tweet, assuming that tweet content is already limited to 280 characters. @@ -78,34 +80,29 @@ after each signature, we use curly brackets and fill in the method body with the specific behavior that we want the methods of the trait to have for the particular type. -After implementing the trait, we can call the methods on instances of -`NewsArticle` and `Tweet` in the same way we call regular methods, like this: +Now that the library has implemented the `Summary` trait on `NewsArticle` and +`Tweet`, users of the crate can call the trait methods on instances of +`NewsArticle` and `Tweet` in the same way we call regular methods. The only +difference is that the trait has to be brought into scope as well as the types +to get the additional trait methods. Here’s an example of how a binary crate +could use our `aggregator` library crate: ```rust,ignore -{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/src/main.rs:here}} +{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/src/main.rs}} ``` This code prints `1 new tweet: horse_ebooks: of course, as you probably already know, people`. -Note that because we defined the `Summary` trait and the `NewsArticle` and -`Tweet` types in the same *lib.rs* in Listing 10-13, they’re all in the same -scope. Let’s say this *lib.rs* is for a crate we’ve called `aggregator` and -someone else wants to use our crate’s functionality to implement the `Summary` -trait on a struct defined within their library’s scope. They would need to -bring the trait into their scope first. They would do so by specifying `use -aggregator::Summary;`, which then would enable them to implement `Summary` for -their type. The `Summary` trait would also need to be a public trait for -another crate to implement it, which it is because we put the `pub` keyword -before `trait` in Listing 10-12. - -One restriction to note with trait implementations is that we can implement a -trait on a type only if either the trait or the type is local to our crate. -For example, we can implement standard library traits like `Display` on a -custom type like `Tweet` as part of our `aggregator` crate functionality, -because the type `Tweet` is local to our `aggregator` crate. We can also -implement `Summary` on `Vec` in our `aggregator` crate, because the -trait `Summary` is local to our `aggregator` crate. +Other crates that depend on the `aggregator` crate can also bring the `Summary` +trait into scope to implement the trait on their own types. One restriction to +note with trait implementations is that we can implement a trait on a type only +if at least one of the trait or the type is local to our crate. For example, we +can implement standard library traits like `Display` on a custom type like +`Tweet` as part of our `aggregator` crate functionality, because the type +`Tweet` is local to our `aggregator` crate. We can also implement `Summary` on +`Vec` in our `aggregator` crate, because the trait `Summary` is local to our +`aggregator` crate. But we can’t implement external traits on external types. For example, we can’t implement the `Display` trait on `Vec` within our `aggregator` crate, @@ -406,16 +403,19 @@ reference, we wouldn’t need the `Clone` or `Copy` trait bounds and we could avoid heap allocations. Try implementing these alternate solutions on your own! If you get stuck with errors having to do with lifetimes, keep reading: the “Validating References with Lifetimes” section coming up will explain, but -lifetimes aren't required to solve these challenges. +lifetimes aren’t required to solve these challenges. ### Using Trait Bounds to Conditionally Implement Methods By using a trait bound with an `impl` block that uses generic type parameters, we can implement methods conditionally for types that implement the specified traits. For example, the type `Pair` in Listing 10-16 always implements the -`new` function. But `Pair` only implements the `cmp_display` method if its -inner type `T` implements the `PartialOrd` trait that enables comparison *and* -the `Display` trait that enables printing. +`new` function to return a new instance of `Pair` (recall from the +[”Defining Methods”][methods] section of Chapter 5 that `Self` +is a type alias for the type of the `impl` block, which in this case is +`Pair`). But in the next `impl` block, `Pair` only implements the +`cmp_display` method if its inner type `T` implements the `PartialOrd` trait +that enables comparison *and* the `Display` trait that enables printing. Filename: src/lib.rs @@ -472,3 +472,4 @@ lifetimes do that. ch04-01-what-is-ownership.html#stack-only-data-copy [using-trait-objects-that-allow-for-values-of-different-types]: ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types +[methods]: ch05-03-method-syntax.html#defining-methods diff --git a/src/doc/book/src/ch10-03-lifetime-syntax.md b/src/doc/book/src/ch10-03-lifetime-syntax.md index 6cec3799e1..1746ca1fd6 100644 --- a/src/doc/book/src/ch10-03-lifetime-syntax.md +++ b/src/doc/book/src/ch10-03-lifetime-syntax.md @@ -11,11 +11,10 @@ ways. Rust requires us to annotate the relationships using generic lifetime parameters to ensure the actual references used at runtime will definitely be valid. -The concept of lifetimes is somewhat different from tools in other programming -languages, arguably making lifetimes Rust’s most distinctive feature. Although -we won’t cover lifetimes in their entirety in this chapter, we’ll discuss -common ways you might encounter lifetime syntax so you can become familiar with -the concepts. +Annotating lifetimes is not even a concept most other programming languages +have, so this is going to feel unfamiliar. Although we won’t cover lifetimes in +their entirety in this chapter, we’ll discuss common ways you might encounter +lifetime syntax so you can get introduced to the concept. ### Preventing Dangling References with Lifetimes @@ -193,10 +192,11 @@ lifetime. Now let’s examine lifetime annotations in the context of the `longest` function. As with generic type parameters, we need to declare generic lifetime parameters inside angle brackets between the function name and the parameter -list. The constraint we want to express in this signature is that all the -references in the parameters and the return value must have the same lifetime. -We’ll name the lifetime `'a` and then add it to each reference, as shown in -Listing 10-22. +list. The constraint we want to express in this signature is that the lifetimes +of both of the parameters and the lifetime of the returned reference are +related such that the returned reference will be valid as long as both the +parameters are. We’ll name the lifetime `'a` and then add it to each reference, +as shown in Listing 10-22. Filename: src/main.rs @@ -217,7 +217,9 @@ long as lifetime `'a`. The function signature also tells Rust that the string slice returned from the function will live at least as long as lifetime `'a`. In practice, it means that the lifetime of the reference returned by the `longest` function is the same as the smaller of the lifetimes of the -references passed in. These constraints are what we want Rust to enforce. +references passed in. These relationships are what we want Rust to use when +analyzing this code. + Remember, when we specify the lifetime parameters in this function signature, we’re not changing the lifetimes of any values passed in or returned. Rather, we’re specifying that the borrow checker should reject any values that don’t @@ -226,12 +228,15 @@ know exactly how long `x` and `y` will live, only that some scope can be substituted for `'a` that will satisfy this signature. When annotating lifetimes in functions, the annotations go in the function -signature, not in the function body. Rust can analyze the code within the -function without any help. However, when a function has references to or from -code outside that function, it becomes almost impossible for Rust to figure out -the lifetimes of the parameters or return values on its own. The lifetimes -might be different each time the function is called. This is why we need to -annotate the lifetimes manually. +signature, not in the function body. The lifetime annotations become part of +the contract of the function, much like the types in the signature are. Having +function signatures contain the lifetime contract means the analysis the Rust +compiler does can be simpler. If there’s a problem with the way a function is +annotated or the way it is called, the compiler errors can point to the part of +our code and the constraints more precisely. If, instead, the Rust compiler +made more inferences about what we intended the relationships of the lifetimes +to be, the compiler might only be able to point to a use of our code many steps +away from the cause of the problem. When we pass concrete references to `longest`, the concrete lifetime that is substituted for `'a` is the part of the scope of `x` that overlaps with the @@ -588,10 +593,10 @@ This is the `longest` function from Listing 10-22 that returns the longer of two string slices. But now it has an extra parameter named `ann` of the generic type `T`, which can be filled in by any type that implements the `Display` trait as specified by the `where` clause. This extra parameter will be printed -before the function compares the lengths of the string slices, which is why the -`Display` trait bound is necessary. Because lifetimes are a type of generic, -the declarations of the lifetime parameter `'a` and the generic type parameter -`T` go in the same list inside the angle brackets after the function name. +using `{}`, which is why the `Display` trait bound is necessary. Because +lifetimes are a type of generic, the declarations of the lifetime parameter +`'a` and the generic type parameter `T` go in the same list inside the angle +brackets after the function name. ## Summary diff --git a/src/doc/book/src/ch11-01-writing-tests.md b/src/doc/book/src/ch11-01-writing-tests.md index c2d001bd0d..0c41f4a1c1 100644 --- a/src/doc/book/src/ch11-01-writing-tests.md +++ b/src/doc/book/src/ch11-01-writing-tests.md @@ -406,7 +406,7 @@ debug what happened instead of what we were expecting to happen. In addition to checking that our code returns the correct values we expect, it’s also important to check that our code handles error conditions as we expect. For example, consider the `Guess` type that we created in Chapter 9, -Listing 9-10. Other code that uses `Guess` depends on the guarantee that `Guess` +Listing 9-13. Other code that uses `Guess` depends on the guarantee that `Guess` instances will contain only values between 1 and 100. We can write a test that ensures that attempting to create a `Guess` instance with a value outside that range panics. diff --git a/src/doc/book/src/ch12-03-improving-error-handling-and-modularity.md b/src/doc/book/src/ch12-03-improving-error-handling-and-modularity.md index 32f0e571e9..b8a91623f7 100644 --- a/src/doc/book/src/ch12-03-improving-error-handling-and-modularity.md +++ b/src/doc/book/src/ch12-03-improving-error-handling-and-modularity.md @@ -247,7 +247,7 @@ arguments again to see what the error looks like now: This output is better: we now have a reasonable error message. However, we also have extraneous information we don’t want to give to our users. Perhaps using -the technique we used in Listing 9-10 isn’t the best to use here: a call to +the technique we used in Listing 9-13 isn’t the best to use here: a call to `panic!` is more appropriate for a programming problem than a usage problem, [as discussed in Chapter 9][ch9-error-guidelines]. Instead, we can use the other technique you learned about in Chapter 9—[returning a diff --git a/src/doc/book/src/ch12-05-working-with-environment-variables.md b/src/doc/book/src/ch12-05-working-with-environment-variables.md index 6554df4dfa..3ce6b6736f 100644 --- a/src/doc/book/src/ch12-05-working-with-environment-variables.md +++ b/src/doc/book/src/ch12-05-working-with-environment-variables.md @@ -61,9 +61,9 @@ First, we lowercase the `query` string and store it in a shadowed variable with the same name. Calling `to_lowercase` on the query is necessary so no matter whether the user’s query is `"rust"`, `"RUST"`, `"Rust"`, or `"rUsT"`, we’ll treat the query as if it were `"rust"` and be insensitive to the case. While -`to_lowercase` will handle basic Unicode, it won't be 100% accurate. If we were -writing a real application, we'd want to do a bit more work here, but this section -is about environment variables, not Unicode, so we'll leave it at that here. +`to_lowercase` will handle basic Unicode, it won’t be 100% accurate. If we were +writing a real application, we’d want to do a bit more work here, but this section +is about environment variables, not Unicode, so we’ll leave it at that here. Note that `query` is now a `String` rather than a string slice, because calling `to_lowercase` creates new data rather than referencing existing data. Say the @@ -157,7 +157,7 @@ the word “to” in all lowercase: Looks like that still works! Now, let’s run the program with `CASE_INSENSITIVE` set to `1` but with the same query `to`. -If you're using PowerShell, you will need to set the environment +If you’re using PowerShell, you will need to set the environment variable and run the program as separate commands: ```console diff --git a/src/doc/book/src/ch15-06-reference-cycles.md b/src/doc/book/src/ch15-06-reference-cycles.md index 7094c6556c..2b70c9fa44 100644 --- a/src/doc/book/src/ch15-06-reference-cycles.md +++ b/src/doc/book/src/ch15-06-reference-cycles.md @@ -70,7 +70,7 @@ variable `b`, which decreases the reference count of the `Rc` instance from 2 to 1. The memory that `Rc` has on the heap won’t be dropped at this point, because its reference count is 1, not 0. Then Rust drops `a`, which decreases the reference count of the `a` `Rc` instance from 2 to 1 as -well. This instance's memory can’t be dropped either, because the other +well. This instance’s memory can’t be dropped either, because the other `Rc` instance still refers to it. The memory allocated to the list will remain uncollected forever. To visualize this reference cycle, we’ve created a diagram in Figure 15-4. diff --git a/src/doc/book/src/ch17-03-oo-design-patterns.md b/src/doc/book/src/ch17-03-oo-design-patterns.md index 4944e96079..0232e17001 100644 --- a/src/doc/book/src/ch17-03-oo-design-patterns.md +++ b/src/doc/book/src/ch17-03-oo-design-patterns.md @@ -435,7 +435,7 @@ But we also have to make some small changes to `main`. The `request_review` and `approve` methods return new instances rather than modifying the struct they’re called on, so we need to add more `let post =` shadowing assignments to save the returned instances. We also can’t have the assertions about the draft and -pending review post’s contents be empty strings, nor do we need them: we can’t +pending review posts’ contents be empty strings, nor do we need them: we can’t compile code that tries to use the content of posts in those states any longer. The updated code in `main` is shown in Listing 17-21: diff --git a/src/doc/book/src/ch19-01-unsafe-rust.md b/src/doc/book/src/ch19-01-unsafe-rust.md index 4eb5f3af98..322bc4a8b5 100644 --- a/src/doc/book/src/ch19-01-unsafe-rust.md +++ b/src/doc/book/src/ch19-01-unsafe-rust.md @@ -455,7 +455,7 @@ annotation makes it easier to track down the source of problems when they occur. [dangling-references]: ch04-02-references-and-borrowing.html#dangling-references [differences-between-variables-and-constants]: -ch03-01-variables-and-mutability.html#differences-between-variables-and-constants +ch03-01-variables-and-mutability.html#constants [extensible-concurrency-with-the-sync-and-send-traits]: ch16-04-extensible-concurrency-sync-and-send.html#extensible-concurrency-with-the-sync-and-send-traits [the-slice-type]: ch04-03-slices.html#the-slice-type diff --git a/src/doc/book/src/ch19-06-macros.md b/src/doc/book/src/ch19-06-macros.md index fe2605fd81..49e71c705d 100644 --- a/src/doc/book/src/ch19-06-macros.md +++ b/src/doc/book/src/ch19-06-macros.md @@ -280,7 +280,7 @@ in a moment, so we need to add them as dependencies. Add the following to the Filename: hello_macro_derive/Cargo.toml ```toml -{{#include ../listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/Cargo.toml:7:12}} +{{#include ../listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/Cargo.toml:6:12}} ``` To start defining the procedural macro, place the code in Listing 19-31 into diff --git a/src/doc/book/src/ch20-01-single-threaded.md b/src/doc/book/src/ch20-01-single-threaded.md index e0b017263c..0e1b55e352 100644 --- a/src/doc/book/src/ch20-01-single-threaded.md +++ b/src/doc/book/src/ch20-01-single-threaded.md @@ -48,7 +48,7 @@ Using `TcpListener`, we can listen for TCP connections at the address `127.0.0.1:7878`. In the address, the section before the colon is an IP address representing your computer (this is the same on every computer and doesn’t represent the authors’ computer specifically), and `7878` is the port. We’ve -chosen this port for two reasons: HTTP isn't normally accepted on this port, and +chosen this port for two reasons: HTTP isn’t normally accepted on this port, and 7878 is *rust* typed on a telephone. The `bind` function in this scenario works like the `new` function in that it diff --git a/src/doc/book/tools/convert-quotes.sh b/src/doc/book/tools/convert-quotes.sh index 86435b5494..8508e97021 100755 --- a/src/doc/book/tools/convert-quotes.sh +++ b/src/doc/book/tools/convert-quotes.sh @@ -2,7 +2,7 @@ set -eu -mkdir -p tmp +mkdir -p tmp/src rm -rf tmp/*.md for f in src/${1:-""}*.md diff --git a/src/doc/edition-guide/src/rust-2021/default-cargo-resolver.md b/src/doc/edition-guide/src/rust-2021/default-cargo-resolver.md index 542f5c5da2..9abc5a6089 100644 --- a/src/doc/edition-guide/src/rust-2021/default-cargo-resolver.md +++ b/src/doc/edition-guide/src/rust-2021/default-cargo-resolver.md @@ -173,7 +173,7 @@ bstr v0.2.16 ``` This snippet of output shows that the project `foo` depends on `bar` with the "default" feature. -Then, `bar` depends on `bstr` as a build-dependency with the "default" feature +Then, `bar` depends on `bstr` as a build-dependency with the "default" feature. We can further see that `bstr`'s "default" feature enables "unicode" (among other features). [`cargo tree`]: ../../cargo/commands/cargo-tree.html diff --git a/src/doc/edition-guide/src/rust-2021/disjoint-capture-in-closures.md b/src/doc/edition-guide/src/rust-2021/disjoint-capture-in-closures.md index 4b1d832c17..25da6d71c0 100644 --- a/src/doc/edition-guide/src/rust-2021/disjoint-capture-in-closures.md +++ b/src/doc/edition-guide/src/rust-2021/disjoint-capture-in-closures.md @@ -132,14 +132,14 @@ In most cases, dropping values at different times just affects when memory is fr Closures automatically implement the following traits based on what values they capture: -- [`Clone`]: if all captured values are [`Clone`]. +- [`Clone`]: if all captured values are `Clone`. - [Auto traits] like [`Send`], [`Sync`], and [`UnwindSafe`]: if all captured values implement the given trait. [auto traits]: https://doc.rust-lang.org/nightly/reference/special-types-and-traits.html#auto-traits [`clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html [`send`]: https://doc.rust-lang.org/std/marker/trait.Send.html [`sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html -[`unwindsafe`]: https://doc.rust-lang.org/std/marker/trait.UnwindSafe.html +[`unwindsafe`]: https://doc.rust-lang.org/std/panic/trait.UnwindSafe.html In Rust 2021, since different values are being captured, this can affect what traits a closure will implement. The migration lints test each closure to see whether it would have implemented a given trait before and whether it still implements it now; if they find that a trait used to be implemented but no longer is, then "dummy lets" are inserted. diff --git a/src/doc/edition-guide/src/rust-2021/prelude.md b/src/doc/edition-guide/src/rust-2021/prelude.md index 13f9c3347d..be1fbf111e 100644 --- a/src/doc/edition-guide/src/rust-2021/prelude.md +++ b/src/doc/edition-guide/src/rust-2021/prelude.md @@ -75,7 +75,7 @@ We can fix this by using fully qualified syntax: ```rust,ignore fn main() { // Now it is clear which trait method we're referring to - as MyTrait>::from_iter(None); + as MyTrait<()>>::from_iter(None); } ``` diff --git a/src/doc/embedded-book/src/SUMMARY.md b/src/doc/embedded-book/src/SUMMARY.md index 4cbdcd1bde..f62fa63333 100644 --- a/src/doc/embedded-book/src/SUMMARY.md +++ b/src/doc/embedded-book/src/SUMMARY.md @@ -53,6 +53,7 @@ more information and coordination - [A little Rust with your C](./interoperability/rust-with-c.md) - [Unsorted topics](./unsorted/index.md) - [Optimizations: The speed size tradeoff](./unsorted/speed-vs-size.md) + - [Performing Math Functionality](./unsorted/math.md) --- diff --git a/src/doc/embedded-book/src/peripherals/borrowck.md b/src/doc/embedded-book/src/peripherals/borrowck.md index d389fc7a69..fb817b2d9f 100644 --- a/src/doc/embedded-book/src/peripherals/borrowck.md +++ b/src/doc/embedded-book/src/peripherals/borrowck.md @@ -16,4 +16,4 @@ The last two of these rules sound suspiciously similar to what the Borrow Checke Imagine if we could pass around ownership of these peripherals, or offer immutable or mutable references to them? -Well, we can, but for the Borrow Checker, we need to have exactly one instance of each peripheral, so Rust can handle this correctly. Well, luckliy in the hardware, there is only one instance of any given peripheral, but how can we expose that in the structure of our code? +Well, we can, but for the Borrow Checker, we need to have exactly one instance of each peripheral, so Rust can handle this correctly. Well, luckily in the hardware, there is only one instance of any given peripheral, but how can we expose that in the structure of our code? diff --git a/src/doc/embedded-book/src/unsorted/math.md b/src/doc/embedded-book/src/unsorted/math.md new file mode 100644 index 0000000000..91271710ee --- /dev/null +++ b/src/doc/embedded-book/src/unsorted/math.md @@ -0,0 +1,75 @@ +# Performing math functionality with `#[no_std]` + +If you want to perform math related functionality like calculating the squareroot or +the exponential of a number and you have the full standard library available, your code +might look like this: + +```rs +//! Some mathematical functions with standard support available + +fn main() { + let float: f32 = 4.82832; + let floored_float = float.floor(); + + let sqrt_of_four = floored_float.sqrt(); + + let sinus_of_four = floored_float.sin(); + + let exponential_of_four = floored_float.exp(); + println!("Floored test float {} to {}", float, floored_float); + println!("The square root of {} is {}", floored_float, sqrt_of_four); + println!("The sinus of four is {}", sinus_of_four); + println!( + "The exponential of four to the base e is {}", + exponential_of_four + ) +} +``` + +Without standard library support, these functions are not available. +An external crate like [`libm`](https://crates.io/crates/libm) can be used instead. The example code +would then look like this: + +```rs +#![no_main] +#![no_std] + +use panic_halt as _; + +use cortex_m_rt::entry; +use cortex_m_semihosting::{debug, hprintln}; +use libm::{exp, floorf, sin, sqrtf}; + +#[entry] +fn main() -> ! { + let float = 4.82832; + let floored_float = floorf(float); + + let sqrt_of_four = sqrtf(floored_float); + + let sinus_of_four = sin(floored_float.into()); + + let exponential_of_four = exp(floored_float.into()); + hprintln!("Floored test float {} to {}", float, floored_float).unwrap(); + hprintln!("The square root of {} is {}", floored_float, sqrt_of_four).unwrap(); + hprintln!("The sinus of four is {}", sinus_of_four).unwrap(); + hprintln!( + "The exponential of four to the base e is {}", + exponential_of_four + ) + .unwrap(); + // exit QEMU + // NOTE do not run this on hardware; it can corrupt OpenOCD state + // debug::exit(debug::EXIT_SUCCESS); + + loop {} +} +``` + +If you need to perform more complex operations like DSP signal processing or advanced linear +algebra on your MCU, the following crates might help you + +- [CMSIS DSP library binding](https://github.com/jacobrosenthal/cmsis-dsp-sys) +- [`micromath`](https://github.com/tarcieri/micromath) +- [`microfft`](https://crates.io/crates/microfft) +- [`nalgebra`](https://github.com/dimforge/nalgebra) diff --git a/src/doc/nomicon/src/arc-mutex/arc-layout.md b/src/doc/nomicon/src/arc-mutex/arc-layout.md index 3dae2cd25b..fabfdca310 100644 --- a/src/doc/nomicon/src/arc-mutex/arc-layout.md +++ b/src/doc/nomicon/src/arc-mutex/arc-layout.md @@ -47,7 +47,7 @@ all the details on variance and drop check. To fix the first problem, we can use `NonNull`. Note that `NonNull` is a wrapper around a raw pointer that declares that: -* We are variant over `T` +* We are covariant over `T` * Our pointer is never null To fix the second problem, we can include a `PhantomData` marker containing an diff --git a/src/doc/nomicon/src/ffi.md b/src/doc/nomicon/src/ffi.md index 825be5aa88..3f41187a34 100644 --- a/src/doc/nomicon/src/ffi.md +++ b/src/doc/nomicon/src/ffi.md @@ -240,6 +240,74 @@ the release of these resources (especially in the case of panic). For more about destructors, see the [Drop trait](../std/ops/trait.Drop.html). +## Calling Rust code from C + +You may wish to compile Rust code in a way so that it can be called from C. +This is fairly easy, but requires a few things. + +### Rust side + +First, we assume you have a lib crate named as `rust_from_c`. +`lib.rs` should have Rust code as following: + +```rust +#[no_mangle] +pub extern "C" fn hello_from_rust() { + println!("Hello from Rust!"); +} +# fn main() {} +``` + +The `extern "C"` makes this function adhere to the C calling convention, as discussed above in "[Foreign Calling Conventions]". +The `no_mangle` attribute turns off Rust's name mangling, so that it has a well defined symbol to link to. + +Then, to compile Rust code as a shared library that can be called from C, add the following to your `Cargo.toml`: + +```toml +[lib] +crate-type = ["cdylib"] +``` + +(NOTE: We could also use the `staticlib` crate type but it needs to tweak some linking flags.) + +Run `cargo build` and you're ready to go on the Rust side. + +[Foreign Calling Conventions]: ffi.md#foreign-calling-conventions + +### C side + +We'll create a C file to call the `hello_from_rust` function and compile it by `gcc`. + +C file should look like: + +```c +int main() { + hello_from_rust(); + return 0; +} +``` + +We name the file as `call_rust.c` and place it on the crate root. +Run the following to compile: + +```sh +gcc call_rust.c -o call_rust -lrust_from_c -L./target/debug +``` + +`-l` and `-L` tell gcc to find our Rust library. + +Finally, we can call Rust code from C with `LD_LIBRARY_PATH` specified: + +```sh +$ LD_LIBRARY_PATH=./target/debug ./call_rust +Hello from Rust! +``` + +That's it! +For more realistic example, check the [`cbindgen`]. + +[`cbindgen`]: https://github.com/eqrion/cbindgen + ## Callbacks from C code to Rust functions Some external libraries require the usage of callbacks to report back their @@ -648,24 +716,6 @@ void register(void (*f)(int (*)(int), int)) { No `transmute` required! -## Calling Rust code from C - -You may wish to compile Rust code in a way so that it can be called from C. This is -fairly easy, but requires a few things: - -```rust -#[no_mangle] -pub extern "C" fn hello_rust() -> *const u8 { - "Hello, world!\0".as_ptr() -} -# fn main() {} -``` - -The `extern "C"` makes this function adhere to the C calling convention, as -discussed above in "[Foreign Calling -Conventions](ffi.html#foreign-calling-conventions)". The `no_mangle` -attribute turns off Rust's name mangling, so that it is easier to link to. - ## FFI and panics It’s important to be mindful of `panic!`s when working with FFI. A `panic!` diff --git a/src/doc/nomicon/src/phantom-data.md b/src/doc/nomicon/src/phantom-data.md index 68ddb8f06f..a5e88bbab3 100644 --- a/src/doc/nomicon/src/phantom-data.md +++ b/src/doc/nomicon/src/phantom-data.md @@ -39,7 +39,7 @@ struct Iter<'a, T: 'a> { } ``` -and that's it. The lifetime will be bounded, and your iterator will be variant +and that's it. The lifetime will be bounded, and your iterator will be covariant over `'a` and `T`. Everything Just Works. Another important example is Vec, which is (approximately) defined as follows: diff --git a/src/doc/nomicon/src/safe-unsafe-meaning.md b/src/doc/nomicon/src/safe-unsafe-meaning.md index 6f55622e26..f7cd68cf27 100644 --- a/src/doc/nomicon/src/safe-unsafe-meaning.md +++ b/src/doc/nomicon/src/safe-unsafe-meaning.md @@ -63,7 +63,7 @@ of Safe Rust, the *soundness property*: The design of the safe/unsafe split means that there is an asymmetric trust relationship between Safe and Unsafe Rust. Safe Rust inherently has to trust that any Unsafe Rust it touches has been written correctly. -On the other hand, Unsafe Rust has to be very careful about trusting Safe Rust. +On the other hand, Unsafe Rust cannot trust Safe Rust without care. As an example, Rust has the [`PartialOrd`] and [`Ord`] traits to differentiate between types which can "just" be compared, and those that provide a "total" diff --git a/src/doc/nomicon/src/subtyping.md b/src/doc/nomicon/src/subtyping.md index 1d892e6cfc..c944c1e803 100644 --- a/src/doc/nomicon/src/subtyping.md +++ b/src/doc/nomicon/src/subtyping.md @@ -443,7 +443,7 @@ struct MyType<'a, 'b, A: 'a, B: 'b, C, D, E, F, G, H, In, Out, Mixed> { f: Vec, // covariant over F g: Cell, // invariant over G - h1: H, // would also be variant over H except... + h1: H, // would also be covariant over H except... h2: Cell, // invariant over H, because invariance wins all conflicts i: fn(In) -> Out, // contravariant over In, covariant over Out diff --git a/src/doc/nomicon/src/what-unsafe-does.md b/src/doc/nomicon/src/what-unsafe-does.md index 6a3c79f3e7..64694ee4d5 100644 --- a/src/doc/nomicon/src/what-unsafe-does.md +++ b/src/doc/nomicon/src/what-unsafe-does.md @@ -48,7 +48,7 @@ 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 pointer value and the size of the pointee type. As a consequence, if the span is -empty, "dangling" is the same as "non-null". Note that slices and strings point +empty, "dangling" is the same as "null". Note that slices and strings point to their entire range, so it's important that the length metadata is never too large (in particular, allocations and therefore slices and strings cannot be bigger than `isize::MAX` bytes). If for some reason this is too cumbersome, diff --git a/src/doc/reference/src/const_eval.md b/src/doc/reference/src/const_eval.md index 4874a73724..93d2fe8b65 100644 --- a/src/doc/reference/src/const_eval.md +++ b/src/doc/reference/src/const_eval.md @@ -93,7 +93,6 @@ Notable features that const contexts have, but const fn haven't are: * generic bounds on generic parameters beyond `Sized` * comparing raw pointers * union field access -* [`transmute`] invocations. Conversely, the following are possible in a const function, but not in a const context: @@ -143,6 +142,5 @@ Conversely, the following are possible in a const function, but not in a const c [statics]: items/static-items.md [struct]: expressions/struct-expr.md [tuple expressions]: expressions/tuple-expr.md -[`transmute`]: ../std/mem/fn.transmute.html [while]: expressions/loop-expr.md#predicate-loops [`while let`]: expressions/loop-expr.md#predicate-pattern-loops diff --git a/src/doc/reference/src/crates-and-source-files.md b/src/doc/reference/src/crates-and-source-files.md index fe1d214f66..494e4543e4 100644 --- a/src/doc/reference/src/crates-and-source-files.md +++ b/src/doc/reference/src/crates-and-source-files.md @@ -132,7 +132,7 @@ name of the crate with the [_MetaNameValueStr_] syntax. ``` The crate name must not be empty, and must only contain [Unicode alphanumeric] -or `-` (U+002D) characters. +or `_` (U+005F) characters. [^phase-distinction]: This distinction would also exist in an interpreter. Static checks like syntactic analysis, type checking, and lints should diff --git a/src/doc/reference/src/special-types-and-traits.md b/src/doc/reference/src/special-types-and-traits.md index 6d054aae2c..4bb4e65993 100644 --- a/src/doc/reference/src/special-types-and-traits.md +++ b/src/doc/reference/src/special-types-and-traits.md @@ -67,13 +67,10 @@ For unions, this means all variants have to be `Copy`. `Copy` is implemented by the compiler for -* [Numeric types] -* `char`, `bool`, and [`!`] * [Tuples] of `Copy` types -* [Arrays] of `Copy` types -* [Shared references] -* [Raw pointers] -* [Function pointers] and [function item types] +* [Function pointers] +* [Function items] +* [Closures] that capture no values or that only capture values of `Copy` types ## `Clone` @@ -83,7 +80,6 @@ types: * Types with a built-in `Copy` implementation (see above) * [Tuples] of `Clone` types -* [Arrays] of `Clone` types ## `Send` @@ -168,21 +164,18 @@ These implicit `Sized` bounds may be relaxed by using the special `?Sized` bound [drop check]: ../nomicon/dropck.html [dynamically sized type]: dynamically-sized-types.md [Function pointers]: types/function-pointer.md -[function item types]: types/function-item.md +[Function items]: types/function-item.md [implementation items]: items/implementations.md [indexing expressions]: expressions/array-expr.md#array-and-slice-indexing-expressions [interior mutability]: interior-mutability.md -[Numeric types]: types/numeric.md [Methods]: items/associated-items.md#associated-functions-and-methods [method resolution]: expressions/method-call-expr.md [operators]: expressions/operator-expr.md [orphan rules]: items/implementations.md#trait-implementation-coherence -[Raw pointers]: types/pointer.md#raw-pointers-const-and-mut [`static` items]: items/static-items.md -[Shared references]: types/pointer.md#shared-references- [the standard library]: ../std/index.html [trait object]: types/trait-object.md [Tuples]: types/tuple.md [Type parameters]: types/parameters.md [variance]: subtyping.md#variance -[`!`]: types/never.md +[Closures]: types/closure.md diff --git a/src/doc/reference/src/tokens.md b/src/doc/reference/src/tokens.md index 8cdf6dd577..1c14a1819f 100644 --- a/src/doc/reference/src/tokens.md +++ b/src/doc/reference/src/tokens.md @@ -235,7 +235,7 @@ r##"foo #"# bar"##; // foo #"# bar > > BYTE_ESCAPE :\ >       `\x` HEX_DIGIT HEX_DIGIT\ ->    | `\n` | `\r` | `\t` | `\\` | `\0` +>    | `\n` | `\r` | `\t` | `\\` | `\0` | `\'` | `\"` A _byte literal_ is a single ASCII character (in the `U+0000` to `U+007F` range) or a single _escape_ preceded by the characters `U+0062` (`b`) and diff --git a/src/doc/reference/style-check/Cargo.toml b/src/doc/reference/style-check/Cargo.toml index ec56dbaf0b..d592f65d04 100644 --- a/src/doc/reference/style-check/Cargo.toml +++ b/src/doc/reference/style-check/Cargo.toml @@ -2,7 +2,7 @@ name = "style-check" version = "0.1.0" authors = ["steveklabnik "] -edition = "2018" +edition = "2021" [dependencies] pulldown-cmark = "0.8" 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 b07adecf6b..cd4e3e6202 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 @@ -1,6 +1,6 @@ # Testcase: linked-list -A common use for `enums` is to create a linked-list: +A common way to implement a linked-list is via `enums`: ```rust,editable use crate::List::*; 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 508cff2314..f7813b4d36 100644 --- a/src/doc/rust-by-example/src/custom_types/structs.md +++ b/src/doc/rust-by-example/src/custom_types/structs.md @@ -89,7 +89,7 @@ fn main() { 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 + returns a `Rectangle` with its top left corner on the point, and a width and height corresponding to the `f32`. ### See also diff --git a/src/doc/rust-by-example/src/testing/dev_dependencies.md b/src/doc/rust-by-example/src/testing/dev_dependencies.md index 3d4ccde556..0899845eec 100644 --- a/src/doc/rust-by-example/src/testing/dev_dependencies.md +++ b/src/doc/rust-by-example/src/testing/dev_dependencies.md @@ -5,23 +5,18 @@ or benchmarks) only. Such dependencies are added to `Cargo.toml` in the `[dev-dependencies]` section. These dependencies are not propagated to other packages which depend on this package. -One such example is using a crate that extends standard `assert!` macros. +One such example is [`pretty_assertions`](https://docs.rs/pretty_assertions/1.0.0/pretty_assertions/index.html), which extends standard `assert_eq!` and `assert_ne!` macros, to provide colorful diff. File `Cargo.toml`: ```toml # standard crate data is left out [dev-dependencies] -pretty_assertions = "0.4.0" +pretty_assertions = "1" ``` File `src/lib.rs`: ```rust,ignore -// externing crate for test-only use -#[cfg(test)] -#[macro_use] -extern crate pretty_assertions; - pub fn add(a: i32, b: i32) -> i32 { a + b } @@ -29,6 +24,7 @@ pub fn add(a: i32, b: i32) -> i32 { #[cfg(test)] mod tests { use super::*; + use pretty_assertions::assert_eq; // crate for test-only use. Cannot be used in non-test code. #[test] fn test_add() { diff --git a/src/doc/rust-by-example/src/trait/impl_trait.md b/src/doc/rust-by-example/src/trait/impl_trait.md index f429d9adf7..e738be4a35 100644 --- a/src/doc/rust-by-example/src/trait/impl_trait.md +++ b/src/doc/rust-by-example/src/trait/impl_trait.md @@ -1,5 +1,56 @@ # `impl Trait` +`impl Trait` can be used in two locations: + +1. as an argument type +2. as a return type + +## As an argument type + +If your function is generic over a trait but you don't mind the specific type, you can simplify the function declaration using `impl Trait` as the type of the argument. + +For example, consider the following code: + +```rust,editable +fn parse_csv_document(src: R) -> std::io::Result>> { + src.lines() + .map(|line| { + // For each line in the source + line.map(|line| { + // If the line was read successfully, process it, if not, return the error + line.split(',') // Split the line separated by commas + .map(|entry| String::from(entry.trim())) // Remove leading and trailing whitespace + .collect() // Collect all strings in a row into a Vec + }) + }) + .collect() // Collect all lines into a Vec> +} +``` + +`parse_csv_document` is generic, allowing it to take any type which implements BufRead, such as `BufReader` or `[u8]`, +but it's not important what type `R` is, and `R` is only used to declare the type of `src`, so the function can also be written an + +```rust,editable +fn parse_csv_document(src: impl std::io::BufRead) -> std::io::Result>> { + src.lines() + .map(|line| { + // For each line in the source + line.map(|line| { + // If the line was read successfully, process it, if not, return the error + line.split(',') // Split the line separated by commas + .map(|entry| String::from(entry.trim())) // Remove leading and trailing whitespace + .collect() // Collect all strings in a row into a Vec + }) + }) + .collect() // Collect all lines into a Vec> +} +``` + +Note that using `impl Trait` as an argument type means that you cannot explicitly state what form of the function you use, i.e. `parse_csv_document::(std::io::empty())` will not work with the second example + + +## As a return type + If your function returns a type that implements `MyTrait`, you can write its return type as `-> impl MyTrait`. This can help simplify your type signatures quite a lot! 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 c787da0712..b808876a42 100644 --- a/src/doc/rustc-dev-guide/.github/workflows/date-check.yml +++ b/src/doc/rustc-dev-guide/.github/workflows/date-check.yml @@ -17,6 +17,10 @@ jobs: - name: Checkout repo uses: actions/checkout@v2 + - name: Ensure Rust is up-to-date + run: | + rustup update stable + - name: Run `date-check` working-directory: ci/date-check run: | diff --git a/src/doc/rustc-dev-guide/ci/date-check/Cargo.toml b/src/doc/rustc-dev-guide/ci/date-check/Cargo.toml index 95251fb123..472529511d 100644 --- a/src/doc/rustc-dev-guide/ci/date-check/Cargo.toml +++ b/src/doc/rustc-dev-guide/ci/date-check/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "date-check" version = "0.1.0" -authors = ["Camelid "] -edition = "2018" +authors = ["Noah Lev "] +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index b7b6d8bd14..411387ab63 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -116,6 +116,7 @@ - [Opaque Types](./opaque-types-type-alias-impl-trait.md) - [Pattern and Exhaustiveness Checking](./pat-exhaustive-checking.md) - [MIR dataflow](./mir/dataflow.md) +- [Drop elaboration](./mir/drop-elaboration.md) - [The borrow checker](./borrow_check.md) - [Tracking moves and initialization](./borrow_check/moves_and_initialization.md) - [Move paths](./borrow_check/moves_and_initialization/move_paths.md) diff --git a/src/doc/rustc-dev-guide/src/about-this-guide.md b/src/doc/rustc-dev-guide/src/about-this-guide.md index 3fa397ae40..e015302c05 100644 --- a/src/doc/rustc-dev-guide/src/about-this-guide.md +++ b/src/doc/rustc-dev-guide/src/about-this-guide.md @@ -1,26 +1,27 @@ # About this guide -This guide is meant to help document how rustc – the Rust compiler – -works, as well as to help new contributors get involved in rustc -development. +This guide is meant to help document how rustc – the Rust compiler – works, +as well as to help new contributors get involved in rustc development. There are seven parts to this guide: -1. [Building and debugging `rustc`][p1]: Contains information that should be - useful no matter how you are contributing, about building, debugging, - profiling, etc. -2. [Contributing to `rustc`][p2]: Contains information that should be useful - no matter how you are contributing, about procedures for contribution, using git - and Github, stabilizing features, etc. -3. [High-Level Compiler Architecture][p3]: Discusses the high-level - architecture of the compiler and stages of the compile process. -4. [Source Code Representation][p4]: Describes the process of taking raw source code from the user and - transforming it into various forms that the compiler can work with easily. -5. [Analysis][p5]: discusses the analyses that the compiler uses to check various - properties of the code and inform later stages of the compile process (e.g., type checking). +1. [Building and debugging `rustc`][p1]: + Contains information that should be useful no matter how you are contributing, + about building, debugging, profiling, etc. +2. [Contributing to `rustc`][p2]: + Contains information that should be useful no matter how you are contributing, + about procedures for contribution, using git and Github, stabilizing features, etc. +3. [High-Level Compiler Architecture][p3]: + Discusses the high-level architecture of the compiler and stages of the compile process. +4. [Source Code Representation][p4]: + Describes the process of taking raw source code from the user + and transforming it into various forms that the compiler can work with easily. +5. [Analysis][p5]: + discusses the analyses that the compiler uses to check various properties of the code + and inform later stages of the compile process (e.g., type checking). 6. [From MIR to Binaries][p6]: How linked executable machine code is generated. -7. [Appendices][p7] at the end with useful reference information. There are a - few of these with different information, including a glossary. +7. [Appendices][p7] at the end with useful reference information. + There are a few of these with different information, including a glossary. [p1]: ./getting-started.md [p2]: ./contributing.md @@ -32,25 +33,26 @@ There are seven parts to this guide: ### Constant change -Keep in mind that `rustc` is a real production-quality product, being worked upon continuously by a -sizeable set of contributors. +Keep in mind that `rustc` is a real production-quality product, +being worked upon continuously by a sizeable set of contributors. As such, it has its fair share of codebase churn and technical debt. -In addition, many of the ideas discussed throughout this guide are idealized designs that are not -fully realized yet. +In addition, many of the ideas discussed throughout this guide are idealized designs +that are not fully realized yet. All this makes keeping this guide completely up to date on everything very hard! -The Guide itself is of course open-source as well, and the sources can be found at the -[GitHub repository]. -If you find any mistakes in the guide, please file an issue about it, or even better, open a PR with -a correction! +The Guide itself is of course open-source as well, +and the sources can be found at the [GitHub repository]. +If you find any mistakes in the guide, please file an issue about it. +Even better, open a PR with a correction! -If you do contribute to the guide, please see the corresponding -[subsection on writing documentation in this guide]. +If you do contribute to the guide, +please see the corresponding [subsection on writing documentation in this guide]. [subsection on writing documentation in this guide]: contributing.md#contributing-to-rustc-dev-guide -> “‘All conditioned things are impermanent’ — when one sees this with wisdom, one turns away from -> suffering.” _The Dhammapada, verse 277_ +> “‘All conditioned things are impermanent’ — +> when one sees this with wisdom, one turns away from suffering.” +> _The Dhammapada, verse 277_ ## Other places to find information diff --git a/src/doc/rustc-dev-guide/src/appendix/glossary.md b/src/doc/rustc-dev-guide/src/appendix/glossary.md index 6b3ec41966..4eba27fce2 100644 --- a/src/doc/rustc-dev-guide/src/appendix/glossary.md +++ b/src/doc/rustc-dev-guide/src/appendix/glossary.md @@ -87,7 +87,7 @@ Term | Meaning uninhabited type   | A type which has _no_ values. This is not the same as a ZST, which has exactly 1 value. An example of an uninhabited type is `enum Foo {}`, which has no variants, and so, can never be created. The compiler can treat code that deals with uninhabited types as dead code, since there is no such value to be manipulated. `!` (the never type) is an uninhabited type. Uninhabited types are also called "empty types". upvar   | A variable captured by a closure from outside the closure. variance   | Determines how changes to a generic type/lifetime parameter affect subtyping; for example, if `T` is a subtype of `U`, then `Vec` is a subtype `Vec` because `Vec` is *covariant* in its generic parameter. See [the background chapter](./background.md#variance) for a more general explanation. See the [variance chapter](../variance.md) for an explanation of how type checking handles variance. -variant index   | In an enum, identifies a variant by assigning them indices starting at 0. This is purely internal and not to be confused with the ["discrimiant"](#discriminant) which can be overwritten by the user (e.g. `enum Bool { True = 42, False = 0 }`). +variant index   | In an enum, identifies a variant by assigning them indices starting at 0. This is purely internal and not to be confused with the ["discriminant"](#discriminant) which can be overwritten by the user (e.g. `enum Bool { True = 42, False = 0 }`). wide pointer   | A pointer with additional metadata. See "fat pointer" for more. ZST   | Zero-Sized Type. A type whose values have size 0 bytes. Since `2^0 = 1`, such types can have exactly one value. For example, `()` (unit) is a ZST. `struct Foo;` is also a ZST. The compiler can do some nice optimizations around ZSTs. diff --git a/src/doc/rustc-dev-guide/src/backend/implicit-caller-location.md b/src/doc/rustc-dev-guide/src/backend/implicit-caller-location.md index 02eea5bab6..21554f5a40 100644 --- a/src/doc/rustc-dev-guide/src/backend/implicit-caller-location.md +++ b/src/doc/rustc-dev-guide/src/backend/implicit-caller-location.md @@ -269,13 +269,13 @@ to the author and reviewers. [attrs-flags]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/middle/codegen_fn_attrs/struct.CodegenFnAttrFlags.html#associatedconstant.TRACK_CALLER [`ReifyShim`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.InstanceDef.html#variant.ReifyShim [`Location`]: https://doc.rust-lang.org/core/panic/struct.Location.html -[const-find-closest]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/interpret/struct.InterpCx.html#method.find_closest_untracked_caller_location +[const-find-closest]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_const_eval/interpret/struct.InterpCx.html#method.find_closest_untracked_caller_location [requires-location]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.InstanceDef.html#method.requires_caller_location -[alloc-location]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/interpret/struct.InterpCx.html#method.alloc_caller_location +[alloc-location]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_const_eval/interpret/struct.InterpCx.html#method.alloc_caller_location [fcx-location]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/mir/struct.FunctionCx.html#structfield.caller_location [const-location-query]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html#method.const_caller_location -[location-memory-kind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/interpret/enum.MemoryKind.html#variant.CallerLocation -[const-frame]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/interpret/struct.Frame.html -[const-stack]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/interpret/struct.InterpCx.html#structfield.stack +[location-memory-kind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_const_eval/interpret/enum.MemoryKind.html#variant.CallerLocation +[const-frame]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_const_eval/interpret/struct.Frame.html +[const-stack]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_const_eval/interpret/struct.InterpCx.html#structfield.stack [fcx-get]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/mir/struct.FunctionCx.html#method.get_caller_location -[frame-instance]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/interpret/struct.Frame.html#structfield.instance +[frame-instance]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_const_eval/interpret/struct.Frame.html#structfield.instance diff --git a/src/doc/rustc-dev-guide/src/backend/monomorph.md b/src/doc/rustc-dev-guide/src/backend/monomorph.md index 0457c18412..a2918b6082 100644 --- a/src/doc/rustc-dev-guide/src/backend/monomorph.md +++ b/src/doc/rustc-dev-guide/src/backend/monomorph.md @@ -49,7 +49,7 @@ for them. Collector will also add things like statics to that list. See [the collector rustdocs][collect] for more info. -[collect]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/monomorphize/collector/index.html +[collect]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_monomorphize/collector/index.html The monomorphization collector is run just before MIR lowering and codegen. [`rustc_codegen_ssa::base::codegen_crate`][codegen1] calls the @@ -71,14 +71,14 @@ or more modules in Crate B. | - | - | | Non-generic function | Crate A function doesn't appear in any codegen units of Crate B | | Non-generic `#[inline]` function | Crate A function appears with in a single CGU of Crate B, and exists even after post-inlining stage| -| Generic function | Regardless of inlining, all monoporphized (specialized) functions
from Crate A appear within a single codegen unit for Crate B.
The codegen unit exists even after the post inlining stage.| +| Generic function | Regardless of inlining, all monomorphized (specialized) functions
from Crate A appear within a single codegen unit for Crate B.
The codegen unit exists even after the post inlining stage.| | Generic `#[inline]` function | - same - | For more details about the partitioner read the module level [documentation]. -[mono]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/monomorphize/partitioning/fn.collect_and_partition_mono_items.html +[mono]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_monomorphize/partitioning/fn.collect_and_partition_mono_items.html [codegen1]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/base/fn.codegen_crate.html -[documentation]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/monomorphize/partitioning/index.html +[documentation]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_monomorphize/partitioning/index.html ## Polymorphization @@ -90,7 +90,7 @@ In addition to MIR optimizations, rustc attempts to determine when fewer copies of functions are necessary and avoid making those copies - known as "polymorphization". When a function-like item is found during monomorphization collection, the -[`rustc_mir::monomorphize::polymorphize::unused_generic_params`][polymorph] +[`rustc_mir_monomorphize::polymorphize::unused_generic_params`][polymorph] query is invoked, which traverses the MIR of the item to determine on which generic parameters the item might not need duplicated. @@ -149,7 +149,7 @@ More details on polymorphization are available in the implementation. [miropt]: ../mir/optimizations.md -[polymorph]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/monomorphize/polymorphize/fn.unused_generic_params.html +[polymorph]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_monomorphize/polymorphize/fn.unused_generic_params.html [inst]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/instance/struct.Instance.html [inst_polymorph]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/instance/struct.Instance.html#method.polymorphize [thesis]: https://davidtw.co/media/masters_dissertation.pdf 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 1a6fa033a9..0de0767b6d 100644 --- a/src/doc/rustc-dev-guide/src/backend/updating-llvm.md +++ b/src/doc/rustc-dev-guide/src/backend/updating-llvm.md @@ -102,7 +102,7 @@ through each in detail. with updated LLVM bindings. Note that you should use `#ifdef` and such to ensure that the bindings still compile on older LLVM versions. - Note that `profile = "compiler"` and other defaults set by `x.py setup` + Note that `profile = "compiler"` and other defaults set by `./x.py setup` download LLVM from CI instead of building it from source. You should disable this temporarily to make sure your changes are being used, by setting ```toml diff --git a/src/doc/rustc-dev-guide/src/borrow_check.md b/src/doc/rustc-dev-guide/src/borrow_check.md index 7e076edf37..8e2bb752ae 100644 --- a/src/doc/rustc-dev-guide/src/borrow_check.md +++ b/src/doc/rustc-dev-guide/src/borrow_check.md @@ -27,11 +27,11 @@ HIR. Doing borrow checking on MIR has several advantages: ### Major phases of the borrow checker The borrow checker source is found in -[the `rustc_mir::borrow_check` module][b_c]. The main entry point is +[the `rustc_borrow_ck` crate][b_c]. The main entry point is the [`mir_borrowck`] query. -[b_c]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/index.html -[`mir_borrowck`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/fn.mir_borrowck.html +[b_c]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/index.html +[`mir_borrowck`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/fn.mir_borrowck.html - We first create a **local copy** of the MIR. In the coming steps, we will modify this copy in place to modify the types and things to @@ -56,4 +56,4 @@ the [`mir_borrowck`] query. require an error to be reported. Doing this check requires the results of all the previous analyses. -[`replace_regions_in_mir`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/fn.replace_regions_in_mir.html +[`replace_regions_in_mir`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/nll/fn.replace_regions_in_mir.html diff --git a/src/doc/rustc-dev-guide/src/borrow_check/moves_and_initialization/move_paths.md b/src/doc/rustc-dev-guide/src/borrow_check/moves_and_initialization/move_paths.md index e38b923cf3..4afec42f83 100644 --- a/src/doc/rustc-dev-guide/src/borrow_check/moves_and_initialization/move_paths.md +++ b/src/doc/rustc-dev-guide/src/borrow_check/moves_and_initialization/move_paths.md @@ -29,7 +29,7 @@ paths roughly correspond to the concept of a [`Place`] from MIR, but they are indexed in ways that enable us to do move analysis more efficiently. -[`MovePath`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/dataflow/move_paths/struct.MovePath.html +[`MovePath`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_dataflow/move_paths/struct.MovePath.html [`Place`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.Place.html ## Move path indices @@ -45,9 +45,9 @@ access the [`MovePath::place`] field like so: move_data.move_paths[mpi].place ``` -[move_paths]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/dataflow/move_paths/struct.MoveData.html#structfield.move_paths -[`MovePath::place`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/dataflow/move_paths/struct.MovePath.html#structfield.place -[`MovePathIndex`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/dataflow/move_paths/struct.MovePathIndex.html +[move_paths]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_dataflow/move_paths/struct.MoveData.html#structfield.move_paths +[`MovePath::place`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_dataflow/move_paths/struct.MovePath.html#structfield.place +[`MovePathIndex`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_dataflow/move_paths/struct.MovePathIndex.html ## Building move paths @@ -60,8 +60,8 @@ corresponding [`MovePathIndex`]. It also records when/where that particular move path is moved/initialized, but we'll get to that in a later section. -[`Gatherer`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/dataflow/move_paths/builder/struct.Gatherer.html -[`MoveData::gather_moves`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/dataflow/move_paths/struct.MoveData.html#method.gather_moves +[`Gatherer`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_dataflow/move_paths/builder/struct.Gatherer.html +[`MoveData::gather_moves`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_dataflow/move_paths/struct.MoveData.html#method.gather_moves ### Illegal move paths @@ -82,7 +82,7 @@ those just discussed, the function returns an `Err`. This in turn means we don't have to bother tracking whether those places are initialized (which lowers overhead). -[`move_path_for`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/dataflow/move_paths/builder/struct.Gatherer.html#method.move_path_for +[`move_path_for`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_dataflow/move_paths/builder/struct.Gatherer.html#method.move_path_for ## Looking up a move-path @@ -90,9 +90,9 @@ If you have a [`Place`] and you would like to convert it to a [`MovePathIndex`], can do that using the [`MovePathLookup`] structure found in the [`rev_lookup`] field of [`MoveData`]. There are two different methods: -[`MoveData`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/dataflow/move_paths/struct.MoveData.html -[`MovePathLookup`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/dataflow/move_paths/struct.MovePathLookup.html -[`rev_lookup`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/dataflow/move_paths/struct.MoveData.html#structfield.rev_lookup +[`MoveData`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_dataflow/move_paths/struct.MoveData.html +[`MovePathLookup`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_dataflow/move_paths/struct.MovePathLookup.html +[`rev_lookup`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_dataflow/move_paths/struct.MoveData.html#structfield.rev_lookup - [`find_local`], which takes a [`mir::Local`] representing a local variable. This is the easier method, because we **always** create a @@ -105,10 +105,10 @@ of [`MoveData`]. There are two different methods: that exists (e.g., for `foo[1]`, it might return just the path for `foo`). -[`find`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/dataflow/move_paths/struct.MovePathLookup.html#method.find -[`find_local`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/dataflow/move_paths/struct.MovePathLookup.html#method.find_local +[`find`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_dataflow/move_paths/struct.MovePathLookup.html#method.find +[`find_local`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_dataflow/move_paths/struct.MovePathLookup.html#method.find_local [`mir::Local`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.Local.html -[`LookupResult`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/dataflow/move_paths/enum.LookupResult.html +[`LookupResult`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_dataflow/move_paths/enum.LookupResult.html ## Cross-references @@ -126,4 +126,4 @@ whether a move-path (e.g., `a.b`) or any child of that move-path (e.g.,`a.b.c`) matches a given predicate. [`Place`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.Place.html -[`find_in_move_path_or_its_descendants`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/dataflow/move_paths/struct.MoveData.html#method.find_in_move_path_or_its_descendants +[`find_in_move_path_or_its_descendants`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_dataflow/move_paths/struct.MoveData.html#method.find_in_move_path_or_its_descendants diff --git a/src/doc/rustc-dev-guide/src/borrow_check/region_inference.md b/src/doc/rustc-dev-guide/src/borrow_check/region_inference.md index e14bc41579..cfb32bf07f 100644 --- a/src/doc/rustc-dev-guide/src/borrow_check/region_inference.md +++ b/src/doc/rustc-dev-guide/src/borrow_check/region_inference.md @@ -5,7 +5,7 @@ The MIR-based region checking code is located in [the `rustc_mir::borrow_check` module][nll]. -[nll]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/index.html +[nll]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/index.html The MIR-based region analysis consists of two major functions: @@ -38,10 +38,10 @@ The MIR-based region analysis consists of two major functions: [cp]: ./region_inference/constraint_propagation.md [fvb]: ../appendix/background.md#free-vs-bound -[`replace_regions_in_mir`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/fn.replace_regions_in_mir.html -[`compute_regions`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/fn.compute_regions.html -[`RegionInferenceContext`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/region_infer/struct.RegionInferenceContext.html -[`solve`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/region_infer/struct.RegionInferenceContext.html#method.solve +[`replace_regions_in_mir`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/nll/fn.replace_regions_in_mir.html +[`compute_regions`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/nll/fn.compute_regions.html +[`RegionInferenceContext`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/region_infer/struct.RegionInferenceContext.html +[`solve`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/region_infer/struct.RegionInferenceContext.html#method.solve [NLL RFC]: https://rust-lang.github.io/rfcs/2094-nll.html [MIR type checker]: ./type_check.md @@ -68,7 +68,7 @@ the moment. TODO: write about _how_ these regions are computed. -[`UniversalRegions`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/universal_regions/struct.UniversalRegions.html +[`UniversalRegions`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/universal_regions/struct.UniversalRegions.html
@@ -115,7 +115,7 @@ common sorts of constraints are: 2. Liveness constraints. Each region needs to be live at points where it can be used. These constraints are collected by [`generate_constraints`]. -[`generate_constraints`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/constraint_generation/fn.generate_constraints.html +[`generate_constraints`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/constraint_generation/fn.generate_constraints.html ## Inference Overview @@ -219,13 +219,13 @@ Here are some of the fields of the struct: - [`closure_bounds_mapping`]: used for propagating region constraints from closures back out to the creator of the closure. -[`constraints`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/region_infer/struct.RegionInferenceContext.html#structfield.constraints -[`liveness_constraints`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/region_infer/struct.RegionInferenceContext.html#structfield.liveness_constraints +[`constraints`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/region_infer/struct.RegionInferenceContext.html#structfield.constraints +[`liveness_constraints`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/region_infer/struct.RegionInferenceContext.html#structfield.liveness_constraints [`location`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.Location.html -[`universal_regions`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/region_infer/struct.RegionInferenceContext.html#structfield.universal_regions -[`universal_region_relations`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/region_infer/struct.RegionInferenceContext.html#structfield.universal_region_relations -[`type_tests`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/region_infer/struct.RegionInferenceContext.html#structfield.type_tests -[`closure_bounds_mapping`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/region_infer/struct.RegionInferenceContext.html#structfield.closure_bounds_mapping +[`universal_regions`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/region_infer/struct.RegionInferenceContext.html#structfield.universal_regions +[`universal_region_relations`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/region_infer/struct.RegionInferenceContext.html#structfield.universal_region_relations +[`type_tests`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/region_infer/struct.RegionInferenceContext.html#structfield.type_tests +[`closure_bounds_mapping`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/region_infer/struct.RegionInferenceContext.html#structfield.closure_bounds_mapping TODO: should we discuss any of the others fields? What about the SCCs? @@ -234,6 +234,6 @@ inference. This is done by calling the [`solve`] method on the context. This is where we call [`propagate_constraints`] and then check the resulting type tests and universal regions, as discussed above. -[`propagate_constraints`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/region_infer/struct.RegionInferenceContext.html#method.propagate_constraints -[`check_type_tests`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/region_infer/struct.RegionInferenceContext.html#method.check_type_tests -[`check_universal_regions`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/region_infer/struct.RegionInferenceContext.html#method.check_universal_regions +[`propagate_constraints`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/region_infer/struct.RegionInferenceContext.html#method.propagate_constraints +[`check_type_tests`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/region_infer/struct.RegionInferenceContext.html#method.check_type_tests +[`check_universal_regions`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/region_infer/struct.RegionInferenceContext.html#method.check_universal_regions diff --git a/src/doc/rustc-dev-guide/src/borrow_check/region_inference/constraint_propagation.md b/src/doc/rustc-dev-guide/src/borrow_check/region_inference/constraint_propagation.md index f0a7f73535..4c30d25e04 100644 --- a/src/doc/rustc-dev-guide/src/borrow_check/region_inference/constraint_propagation.md +++ b/src/doc/rustc-dev-guide/src/borrow_check/region_inference/constraint_propagation.md @@ -12,7 +12,7 @@ on one at a time (each of them is fairly independent from the others): - outlives constraints (`R1: R2`), which arise from subtyping; - [member constraints][m_c] (`member R_m of [R_c...]`), which arise from impl Trait. -[`propagate_constraints`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/region_infer/struct.RegionInferenceContext.html#method.propagate_constraints +[`propagate_constraints`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/region_infer/struct.RegionInferenceContext.html#method.propagate_constraints [m_c]: ./member_constraints.md In this chapter, we'll explain the "heart" of constraint propagation, @@ -70,8 +70,8 @@ though; instead, we store a (sparse) bitset per region variable (of type [`LivenessValues`]). This way we only need a single bit for each liveness constraint. -[`liveness_constraints`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/region_infer/struct.RegionInferenceContext.html#structfield.liveness_constraints -[`LivenessValues`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/region_infer/values/struct.LivenessValues.html +[`liveness_constraints`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/region_infer/struct.RegionInferenceContext.html#structfield.liveness_constraints +[`LivenessValues`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/region_infer/values/struct.LivenessValues.html One thing that is worth mentioning: All lifetime parameters are always considered to be live over the entire function body. This is because @@ -114,9 +114,9 @@ induces an edge `'a -> 'b`. This conversion happens in the [`RegionInferenceContext::new`] function that creates the inference context. -[`OutlivesConstraintSet`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/constraints/struct.OutlivesConstraintSet.html -[graph-fn]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/constraints/struct.OutlivesConstraintSet.html#method.graph -[`RegionInferenceContext::new`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/region_infer/struct.RegionInferenceContext.html#method.new +[`OutlivesConstraintSet`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/constraints/struct.OutlivesConstraintSet.html +[graph-fn]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/constraints/struct.OutlivesConstraintSet.html#method.graph +[`RegionInferenceContext::new`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/region_infer/struct.RegionInferenceContext.html#method.new When using a graph representation, we can detect regions that must be equal by looking for cycles. That is, if you have a constraint like @@ -148,8 +148,8 @@ of fields are defined in terms of SCCs. For example, the of a specific region `'a` then, we first figure out the SCC that the region is a part of, and then find the value of that SCC. -[`constraint_sccs`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/region_infer/struct.RegionInferenceContext.html#structfield.constraint_sccs -[`scc_values`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/region_infer/struct.RegionInferenceContext.html#structfield.scc_values +[`constraint_sccs`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/region_infer/struct.RegionInferenceContext.html#structfield.constraint_sccs +[`scc_values`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/region_infer/struct.RegionInferenceContext.html#structfield.scc_values When we compute SCCs, we not only figure out which regions are a member of each SCC, we also figure out the edges between them. So for example diff --git a/src/doc/rustc-dev-guide/src/borrow_check/region_inference/lifetime_parameters.md b/src/doc/rustc-dev-guide/src/borrow_check/region_inference/lifetime_parameters.md index c65b8ce5a5..2dbbc0c1e2 100644 --- a/src/doc/rustc-dev-guide/src/borrow_check/region_inference/lifetime_parameters.md +++ b/src/doc/rustc-dev-guide/src/borrow_check/region_inference/lifetime_parameters.md @@ -31,9 +31,9 @@ relationships to one another. So if you have e.g. `where 'a: 'b`, then the [`UniversalRegionRelations`] struct would track that `'a: 'b` is known to hold (which could be tested with the [`outlives`] function. -[`UniversalRegions`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/universal_regions/struct.UniversalRegions.html -[`UniversalRegionRelations`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/type_check/free_region_relations/struct.UniversalRegionRelations.html -[`outlives`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/type_check/free_region_relations/struct.UniversalRegionRelations.html#method.outlives +[`UniversalRegions`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/universal_regions/struct.UniversalRegions.html +[`UniversalRegionRelations`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/type_check/free_region_relations/struct.UniversalRegionRelations.html +[`outlives`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/type_check/free_region_relations/struct.UniversalRegionRelations.html#method.outlives ## Everything is a region variable @@ -58,7 +58,7 @@ type). These subdivisions are not important for the topics discussed here, but become important when we consider [closure constraint propagation](./closure_constraints.html), so we discuss them there. -[`RegionClassification`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/universal_regions/enum.RegionClassification.html#variant.Local +[`RegionClassification`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/universal_regions/enum.RegionClassification.html#variant.Local ## Universal lifetimes as the elements of a region's value @@ -88,7 +88,7 @@ liveness constraint (i.e., `'a` must extend until the end of itself). In the code, these liveness constraints are setup in [`init_free_and_bound_regions`]. -[`init_free_and_bound_regions`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/region_infer/struct.RegionInferenceContext.html#method.init_free_and_bound_regions +[`init_free_and_bound_regions`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/region_infer/struct.RegionInferenceContext.html#method.init_free_and_bound_regions ## Propagating outlives constraints for universal regions @@ -124,4 +124,4 @@ not, as in our example, that is an error. This check is done in the universal regions, inspects their final value, and tests against the declared [`UniversalRegionRelations`]. -[`check_universal_regions`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/region_infer/struct.RegionInferenceContext.html#method.check_universal_regions +[`check_universal_regions`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/region_infer/struct.RegionInferenceContext.html#method.check_universal_regions diff --git a/src/doc/rustc-dev-guide/src/borrow_check/type_check.md b/src/doc/rustc-dev-guide/src/borrow_check/type_check.md index 0db895619e..1485f2ae87 100644 --- a/src/doc/rustc-dev-guide/src/borrow_check/type_check.md +++ b/src/doc/rustc-dev-guide/src/borrow_check/type_check.md @@ -1,7 +1,7 @@ # The MIR type-check A key component of the borrow check is the -[MIR type-check](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/type_check/index.html). +[MIR type-check](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/type_check/index.html). This check walks the MIR and does a complete "type check" -- the same kind you might find in any other language. In the process of doing this type-check, we also uncover the region constraints that apply to diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping.md b/src/doc/rustc-dev-guide/src/building/bootstrapping.md index 876c565abb..fc1ad6c000 100644 --- a/src/doc/rustc-dev-guide/src/building/bootstrapping.md +++ b/src/doc/rustc-dev-guide/src/building/bootstrapping.md @@ -2,11 +2,8 @@ -This subchapter is about the bootstrapping process. -## What is bootstrapping? How does it work? - -[Bootstrapping] is the process of using a compiler to compile itself. +[*Bootstrapping*][boot] is the process of using a compiler to compile itself. More accurately, it means using an older compiler to compile a newer version of the same compiler. @@ -21,45 +18,53 @@ rustc, then uses it to compile the new compiler. ## Stages of bootstrapping -Compiling `rustc` is done in stages: - -- **Stage 0:** the stage0 compiler is usually (you can configure `x.py` to use - something else) the current _beta_ `rustc` compiler and its associated dynamic - libraries (which `x.py` will download for you). This stage0 compiler is then - used only to compile `rustbuild`, `std`, and `rustc`. When compiling - `rustc`, this stage0 compiler uses the freshly compiled `std`. - There are two concepts at play here: a compiler (with its set of dependencies) - and its 'target' or 'object' libraries (`std` and `rustc`). - Both are staged, but in a staggered manner. -- **Stage 1:** the code in your clone (for new version) is then - compiled with the stage0 compiler to produce the stage1 compiler. - However, it was built with an older compiler (stage0), so to - optimize the stage1 compiler we go to the next stage. - - In theory, the stage1 compiler is functionally identical to the - stage2 compiler, but in practice there are subtle differences. In - particular, the stage1 compiler itself was built by stage0 and - hence not by the source in your working directory: this means that - the symbol names used in the compiler source may not match the - symbol names that would have been made by the stage1 compiler. This is - important when using dynamic linking and the lack of ABI compatibility - between versions. This primarily manifests when tests try to link with any - of the `rustc_*` crates or use the (now deprecated) plugin infrastructure. - These tests are marked with `ignore-stage1`. -- **Stage 2:** we rebuild our stage1 compiler with itself to produce - the stage2 compiler (i.e. it builds itself) to have all the _latest - optimizations_. (By default, we copy the stage1 libraries for use by - the stage2 compiler, since they ought to be identical.) -- _(Optional)_ **Stage 3**: to sanity check our new compiler, we - can build the libraries with the stage2 compiler. The result ought - to be identical to before, unless something has broken. - -The `stage2` compiler is the one distributed with `rustup` and all other -install methods. However, it takes a very long time to build because one must -first build the new compiler with an older compiler and then use that to -build the new compiler with itself. For development, you usually only want -the `stage1` compiler: `x.py build library/std`. - -### Default stages +Compiling `rustc` is done in stages. + +### Stage 0 + +The stage0 compiler is usually the current _beta_ `rustc` compiler +and its associated dynamic libraries, +which `x.py` will download for you. +(You can also configure `x.py` to use something else.) + +The stage0 compiler is then used only to compile `rustbuild`, `std`, and `rustc`. +When compiling `rustc`, the stage0 compiler uses the freshly compiled `std`. +There are two concepts at play here: +a compiler (with its set of dependencies) +and its 'target' or 'object' libraries (`std` and `rustc`). +Both are staged, but in a staggered manner. + +### Stage 1 + +The rustc source code is then compiled with the stage0 compiler to produce the stage1 compiler. + +### Stage 2 + +We then rebuild our stage1 compiler with itself to produce the stage2 compiler. + +In theory, the stage1 compiler is functionally identical to the stage2 compiler, +but in practice there are subtle differences. +In particular, the stage1 compiler itself was built by stage0 +and hence not by the source in your working directory. +This means that the symbol names used in the compiler source +may not match the symbol names that would have been made by the stage1 compiler, +which can cause problems for dynamic libraries and tests. + +The `stage2` compiler is the one distributed with `rustup` and all other install methods. +However, it takes a very long time to build +because one must first build the new compiler with an older compiler +and then use that to build the new compiler with itself. +For development, you usually only want the `stage1` compiler, +which you can build with `./x.py build library/std`. +See [Building the Compiler](/building/how-to-build-and-run.html#building-the-compiler). + +### Stage 3 + +Stage 3 is optional. To sanity check our new compiler, we +can build the libraries with the stage2 compiler. The result ought +to be identical to before, unless something has broken. + +### Building the stages `x.py` tries to be helpful and pick the stage you most likely meant for each subcommand. These defaults are as follows: @@ -96,7 +101,7 @@ _break the stability guarantees_ of rust: Allow using `#![feature(...)]` with a compiler that's not nightly. This should never be used except when bootstrapping the compiler. -[Bootstrapping]: https://en.wikipedia.org/wiki/Bootstrapping_(compilers) +[boot]: https://en.wikipedia.org/wiki/Bootstrapping_(compilers) [intrinsics]: ../appendix/glossary.md#intrinsic [ocaml-compiler]: https://github.com/rust-lang/rust/tree/ef75860a0a72f79f97216f8aaa5b388d98da6480/src/boot @@ -132,9 +137,10 @@ contribution [here][bootstrap-build]. This is a detailed look into the separate bootstrap stages. The convention `x.py` uses is that: + - A `--stage N` flag means to run the stage N compiler (`stageN/rustc`). - A "stage N artifact" is a build artifact that is _produced_ by the stage N compiler. -- The "stage (N+1) compiler" is assembled from "stage N artifacts". This +- The stage N+1 compiler is assembled from stage N *artifacts*. This process is called _uplifting_. #### Build artifacts @@ -149,51 +155,35 @@ Build artifacts include, but are not limited to: [rlib]: ../serialization.md -#### Assembling the compiler - -There is a separate step between building the compiler and making it possible -to run. This step is called _assembling_ or _uplifting_ the compiler. It copies -all the necessary build artifacts from `build/stageN-sysroot` to -`build/stage(N+1)`, which allows you to use `build/stage(N+1)` as a [toolchain] -with `rustup toolchain link`. - -There is [no way to trigger this step on its own][#73519], but `x.py` will -perform it automatically any time you build with stage N+1. - -[toolchain]: https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html#creating-a-rustup-toolchain -[#73519]: https://github.com/rust-lang/rust/issues/73519 - #### Examples -- `x.py build --stage 0` means to build with the beta `rustc`. -- `x.py doc --stage 0` means to document using the beta `rustdoc`. -- `x.py test --stage 0 library/std` means to run tests on the standard library +- `./x.py build --stage 0` means to build with the beta `rustc`. +- `./x.py doc --stage 0` means to document using the beta `rustdoc`. +- `./x.py test --stage 0 library/std` means to run tests on the standard library without building `rustc` from source ('build with stage 0, then test the artifacts'). If you're working on the standard library, this is normally the test command you want. -- `x.py test src/test/ui` means to build the stage 1 compiler and run +- `./x.py test src/test/ui` means to build the stage 1 compiler and run `compiletest` on it. If you're working on the compiler, this is normally the test command you want. #### Examples of what *not* to do -- `x.py test --stage 0 src/test/ui` is not meaningful: it runs tests on the +- `./x.py test --stage 0 src/test/ui` is not meaningful: it runs tests on the _beta_ compiler and doesn't build `rustc` from source. Use `test src/test/ui` instead, which builds stage 1 from source. -- `x.py test --stage 0 compiler/rustc` builds the compiler but runs no tests: +- `./x.py test --stage 0 compiler/rustc` builds the compiler but runs no tests: it's running `cargo test -p rustc`, but cargo doesn't understand Rust's tests. You shouldn't need to use this, use `test` instead (without arguments). -- `x.py build --stage 0 compiler/rustc` builds the compiler, but does - not [assemble] it. Use `x.py build library/std` instead, which puts the - compiler in `stage1/rustc`. - -[assemble]: #assembling-the-compiler - -### Building vs. Running +- `./x.py build --stage 0 compiler/rustc` builds the compiler, but does not build + libstd or even libcore. Most of the time, you'll want `./x.py build + library/std` instead, which allows compiling programs without needing to define + lang items. +### Building vs. running Note that `build --stage N compiler/rustc` **does not** build the stage N compiler: -instead it builds the stage _N+1_ compiler _using_ the stage N compiler. +instead it builds the stage N+1 compiler _using_ the stage N compiler. In short, _stage 0 uses the stage0 compiler to create stage0 artifacts which will later be uplifted to be the stage1 compiler_. @@ -201,8 +191,8 @@ will later be uplifted to be the stage1 compiler_. In each stage, two major steps are performed: 1. `std` is compiled by the stage N compiler. -2. That `std` is linked to programs built by the stage N compiler, including - the stage N artifacts (stage (N+1) compiler). +2. That `std` is linked to programs built by the stage N compiler, + including the stage N artifacts (stage N+1 compiler). This is somewhat intuitive if one thinks of the stage N artifacts as "just" another program we are building with the stage N compiler: @@ -217,8 +207,6 @@ Keep in mind this diagram is a simplification, i.e. `rustdoc` can be built at different stages, the process is a bit different when passing flags such as `--keep-stage`, or if there are non-host targets. -The stage 2 compiler is what is shipped to end-users. - ### Stages and `std` Note that there are two `std` libraries in play here: @@ -241,10 +229,12 @@ recompiling that `std`. `--keep-stage` simply assumes the previous compile is fine and copies those artifacts into the appropriate place, skipping the cargo invocation. -### Cross-compiling +### Cross-compiling rustc + +*Cross-compiling* is the process of compiling code that will run on another archicture. +For instance, you might want to build an ARM version of rustc using an x86 machine. +Building stage2 `std` is different when you are cross-compiling. -Building stage2 `std` is different depending on whether you are cross-compiling or not -(see in the table how stage2 only builds non-host `std` targets). This is because `x.py` uses a trick: if `HOST` and `TARGET` are the same, it will reuse stage1 `std` for stage2! This is sound because stage1 `std` was compiled with the stage1 compiler, i.e. a compiler using the source code @@ -254,6 +244,8 @@ to the `std` that `stage2/rustc` would compile. However, when cross-compiling, stage1 `std` will only run on the host. So the stage2 compiler has to recompile `std` for the target. +(See in the table how stage2 only builds non-host `std` targets). + ### Why does only libstd use `cfg(bootstrap)`? The `rustc` generated by the stage0 compiler is linked to the freshly-built @@ -356,7 +348,7 @@ You can find more discussion about sysroots in: [rustdoc PR]: https://github.com/rust-lang/rust/pull/76728 -### Directories and artifacts generated by x.py +### Directories and artifacts generated by `x.py` The following tables indicate the outputs of various stage actions: diff --git a/src/doc/rustc-dev-guide/src/building/build-install-distribution-artifacts.md b/src/doc/rustc-dev-guide/src/building/build-install-distribution-artifacts.md index 7430ffb9b8..4ec3f958a0 100644 --- a/src/doc/rustc-dev-guide/src/building/build-install-distribution-artifacts.md +++ b/src/doc/rustc-dev-guide/src/building/build-install-distribution-artifacts.md @@ -18,7 +18,7 @@ test that it works on your target system. You’ll want to run this command: Note: If you are testing out a modification to a compiler, you might want to use it to compile some project. - Usually, you do not want to use ./x.py install for testing. + Usually, you do not want to use `./x.py install` for testing. Rather, you should create a toolchain as discussed in [here][create-rustup-toolchain]. diff --git a/src/doc/rustc-dev-guide/src/building/compiler-documenting.md b/src/doc/rustc-dev-guide/src/building/compiler-documenting.md index af3cd7ce28..0efe2fce61 100644 --- a/src/doc/rustc-dev-guide/src/building/compiler-documenting.md +++ b/src/doc/rustc-dev-guide/src/building/compiler-documenting.md @@ -4,7 +4,7 @@ You might want to build documentation of the various components available like the standard library. There’s two ways to go about this. You can run rustdoc directly on the file to make sure the HTML is correct, which is fast. Alternatively, you can build the documentation -as part of the build process through x.py. Both are viable methods +as part of the build process through `x.py`. Both are viable methods since documentation is more about the content. ## Document everything 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 49c2e8b664..981bb6e50e 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,7 +20,7 @@ cd rust ## Create a `config.toml` -To start, run `x.py setup`. This will create a `config.toml` with reasonable defaults. +To start, run `./x.py setup`. This will create a `config.toml` with reasonable defaults. You may also want to change some of the following settings (and possibly others, such as `llvm.ccache`): diff --git a/src/doc/rustc-dev-guide/src/building/new-target.md b/src/doc/rustc-dev-guide/src/building/new-target.md index 9687541388..b5fc2cb0ad 100644 --- a/src/doc/rustc-dev-guide/src/building/new-target.md +++ b/src/doc/rustc-dev-guide/src/building/new-target.md @@ -8,7 +8,7 @@ relevant to your desired goal. For very new targets, you may need to use a different fork of LLVM than what is currently shipped with Rust. In that case, navigate to -the `src/llvm-project` git submodule (you might need to run `x.py +the `src/llvm-project` git submodule (you might need to run `./x.py check` at least once so the submodule is updated), check out the appropriate commit for your fork, then commit that new submodule reference in the main Rust repository. diff --git a/src/doc/rustc-dev-guide/src/building/suggested.md b/src/doc/rustc-dev-guide/src/building/suggested.md index 24e25f5d05..bae98aa041 100644 --- a/src/doc/rustc-dev-guide/src/building/suggested.md +++ b/src/doc/rustc-dev-guide/src/building/suggested.md @@ -8,13 +8,13 @@ to make your life easier. CI will automatically fail your build if it doesn't pass `tidy`, our internal tool for ensuring code quality. If you'd like, you can install a [Git hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) -that will automatically run `x.py test tidy --bless` on each commit, to ensure +that will automatically run `./x.py test tidy --bless` on each commit, to ensure your code is up to par. If you decide later that this behavior is undesirable, you can delete the `pre-commit` file in `.git/hooks`. A prebuilt git hook lives at [`src/etc/pre-commit.sh`](https://github.com/rust-lang/rust/blob/master/src/etc/pre-commit.sh) which can be copied into your `.git/hooks` folder as `pre-commit` (without the `.sh` extension!). -You can also install the hook as a step of running `x.py setup`! +You can also install the hook as a step of running `./x.py setup`! ## Configuring `rust-analyzer` for `rustc` @@ -32,7 +32,7 @@ you can write: July 2021, we lint against direct declarations without the use of the macro today (although this may change in the future, as the macro is somewhat unwieldy to add new fields to, like all macros). -Lint declarations don't carry any "state" - they are merely global identifers and descriptions of +Lint declarations don't carry any "state" - they are merely global identifiers and descriptions of lints. We assert at runtime that they are not registered twice (by lint name). Lint passes are the meat of any lint. Notably, there is not a one-to-one relationship between diff --git a/src/doc/rustc-dev-guide/src/early-late-bound.md b/src/doc/rustc-dev-guide/src/early-late-bound.md index 4178a4af05..29b2136b4c 100644 --- a/src/doc/rustc-dev-guide/src/early-late-bound.md +++ b/src/doc/rustc-dev-guide/src/early-late-bound.md @@ -24,7 +24,7 @@ of type `for fn(T)`, we would need a single function pointer that can be used for a parameter of any type, but in Rust we generate customized code for each parameter type. -One consequence of this asymmetry is a weird split in how we represesent some +One consequence of this asymmetry is a weird split in how we represent some generic types: _early-_ and _late-_ bound parameters. Basically, if we cannot represent a type (e.g. a universally quantified type), we have to bind it _early_ so that the unrepresentable type is never around. diff --git a/src/doc/rustc-dev-guide/src/getting-started.md b/src/doc/rustc-dev-guide/src/getting-started.md index abc084c2be..f8273d631f 100644 --- a/src/doc/rustc-dev-guide/src/getting-started.md +++ b/src/doc/rustc-dev-guide/src/getting-started.md @@ -128,13 +128,13 @@ this chapter for more info][config]. In the top level of the repo: ```sh -$ x.py setup +$ ./x.py setup ``` -This will walk you through an interactive setup for x.py that looks like this: +This will walk you through an interactive setup for `x.py` that looks like this: ``` -$ x.py setup +$ ./x.py setup Welcome to the Rust project! What do you want to do with x.py? a) Contribute to the standard library b) Contribute to the compiler @@ -150,13 +150,13 @@ To get started, try one of the following commands: For more suggestions, see https://rustc-dev-guide.rust-lang.org/building/suggested.html ``` -Note that by default, `x.py setup` will use CI-built LLVM if available for your +Note that by default, `./x.py setup` will use CI-built LLVM if available for your platform so that you don't need to build LLVM in addition to building the compiler. In some circumstances, such as when updating the version of LLVM used by `rustc`, you may want to temporarily disable this feature. See the ["Updating LLVM" section] for more. -If you want to download LLVM from CI without running `x.py setup`, you can set +If you want to download LLVM from CI without running `./x.py setup`, you can set the `download-ci-llvm` option to `true` in your `config.toml`: ```toml @@ -166,7 +166,7 @@ download-ci-llvm = true ["Updating LLVM" section]: https://rustc-dev-guide.rust-lang.org/backend/updating-llvm.html?highlight=download-ci-llvm#feature-updates -### x.py Intro +### `x.py` Intro `rustc` is a _bootstrapping_ compiler, which means that it is written in Rust and thus needs to be compiled by itself. So where do you @@ -177,7 +177,7 @@ to build a new compiler. Then, we use that compiler to build itself. Thus, [boot]: ./building/bootstrapping.md -We have a special tool `./x.py` that drives this process. It is used for +We have a special tool `x.py` that drives this process. It is used for building the compiler, the standard libraries, and `rustdoc`. It is also used for driving CI and building the final release artifacts. @@ -195,14 +195,14 @@ should still read the rest of the section: | Command | When to use it | | --- | --- | -| `x.py check` | Quick check to see if things compile; [rust-analyzer can run this automatically for you][rust-analyzer] | -| `x.py build --stage 0 [library/std]` | Build only the standard library, without building the compiler | -| `x.py build library/std` | Build just the 1st stage of the compiler, along with the standard library; this is faster than building stage 2 and usually good enough | -| `x.py build --keep-stage 1 library/std` | Build the 1st stage of the compiler and skips rebuilding the standard library; this is useful after you've done an ordinary stage1 build to skip compilation time, but it can cause weird problems. (Just do a regular build to resolve.) | -| `x.py test [--keep-stage 1]` | Run the test suite using the stage1 compiler | -| `x.py test --bless [--keep-stage 1]` | Run the test suite using the stage1 compiler _and_ update expected test output. | -| `x.py build --stage 2 compiler/rustc` | Do a full 2-stage build. You almost never want to do this. | -| `x.py test --stage 2` | Do a full 2-stage build and run all tests. You almost never want to do this. | +| `./x.py check` | Quick check to see if things compile; [rust-analyzer can run this automatically for you][rust-analyzer] | +| `./x.py build --stage 0 [library/std]` | Build only the standard library, without building the compiler | +| `./x.py build library/std` | Build just the 1st stage of the compiler, along with the standard library; this is faster than building stage 2 and usually good enough | +| `./x.py build --keep-stage 1 library/std` | Build the 1st stage of the compiler and skips rebuilding the standard library; this is useful after you've done an ordinary stage1 build to skip compilation time, but it can cause weird problems. (Just do a regular build to resolve.) | +| `./x.py test [--keep-stage 1]` | Run the test suite using the stage1 compiler | +| `./x.py test --bless [--keep-stage 1]` | Run the test suite using the stage1 compiler _and_ update expected test output. | +| `./x.py build --stage 2 compiler/rustc` | Do a full 2-stage build. You almost never want to do this. | +| `./x.py test --stage 2` | Do a full 2-stage build and run all tests. You almost never want to do this. | To do a full 2-stage build of the whole compiler, you should run this (after updating `config.toml` as mentioned above): @@ -231,7 +231,7 @@ For most contributions, you only need to build stage 1, which saves a lot of tim ``` This will take a while, especially the first time. Be wary of accidentally -touching or formatting the compiler, as `./x.py` will try to recompile it. +touching or formatting the compiler, as `x.py` will try to recompile it. **NOTE**: The `--keep-stage 1` will _assume_ that the stage 0 standard library does not need to be rebuilt, which is usually true, which will save some time. diff --git a/src/doc/rustc-dev-guide/src/git.md b/src/doc/rustc-dev-guide/src/git.md index ac03a3c0f7..e9588fd597 100644 --- a/src/doc/rustc-dev-guide/src/git.md +++ b/src/doc/rustc-dev-guide/src/git.md @@ -158,7 +158,7 @@ These changes are not changes to files: they are changes to submodules (more on this [later](#git-submodules)). To get rid of those, run `git submodule update` (or run any `x.py` command, which will automatically update the submodules). Note that there is (as of July 2021) a [bug][#77620] if you use -worktrees, submodules, and x.py in a commit hook. If you run into an error +worktrees, submodules, and `x.py` in a commit hook. If you run into an error like: ``` @@ -408,7 +408,7 @@ nothing to commit, working tree clean ``` As far as git is concerned, you are no longer in the `rust` repo, but in the `miri` repo. -You will notice that we are in "detatched HEAD" state, i.e. not on a branch but on a +You will notice that we are in "detached HEAD" state, i.e. not on a branch but on a particular commit. This is because, like any dependency, we want to be able to control which version to use. diff --git a/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md b/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md index 7d3c0fe360..4a0f53bfa1 100644 --- a/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md +++ b/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md @@ -130,7 +130,7 @@ The `InstrumentCoverage` MIR pass is documented in [more detail below][instrument-coverage-pass-details]. [mir-passes]: mir/passes.md -[mir-instrument-coverage]: https://github.com/rust-lang/rust/tree/master/compiler/rustc_mir/src/transform/coverage +[mir-instrument-coverage]: https://github.com/rust-lang/rust/tree/master/compiler/rustc_mir_transform/src/coverage [code-region]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/coverage/struct.CodeRegion.html [counter-coverage-kind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/coverage/enum.CoverageKind.html#variant.Counter [expression-coverage-kind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/coverage/enum.CoverageKind.html#variant.Expression @@ -358,13 +358,13 @@ example, `A + (B - C)` might represent an `Expression` count computed from three other counters, `A`, `B`, and `C`, but computing that value requires an intermediate expression for `B - C`. -[instrumentor]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/coverage/struct.Instrumentor.html -[coverage-graph]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/coverage/graph/struct.CoverageGraph.html -[inject-counters]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/coverage/struct.Instrumentor.html#method.inject_counters -[bcb]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/coverage/graph/struct.BasicCoverageBlock.html -[debug]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/coverage/debug -[generate-coverage-spans]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/coverage/spans/struct.CoverageSpans.html#method.generate_coverage_spans -[make-bcb-counters]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/coverage/counters/struct.BcbCounters.html#method.make_bcb_counters +[instrumentor]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/struct.Instrumentor.html +[coverage-graph]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/graph/struct.CoverageGraph.html +[inject-counters]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/struct.Instrumentor.html#method.inject_counters +[bcb]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/graph/struct.BasicCoverageBlock.html +[debug]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/debug +[generate-coverage-spans]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/spans/struct.CoverageSpans.html#method.generate_coverage_spans +[make-bcb-counters]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/counters/struct.BcbCounters.html#method.make_bcb_counters ### The `CoverageGraph` @@ -453,7 +453,7 @@ The nodes contain information in sections: its `BasicCoverageBlockData`). 2. The first content section shows the assigned `Counter` or `Expression` for each contiguous section of code. (There may be more than one `Expression` - incremented by the same `Counter` for discontiguous sections of code + incremented by the same `Counter` for noncontiguous sections of code representing the same sequential actions.) Note the code is represented by the line and column ranges (for example: `52:28-52:33`, representing the original source line 52, for columns 28-33). These are followed by the MIR @@ -472,11 +472,11 @@ function--[`bcb_from_bb()`][bcb-from-bb]--to look up a `BasicCoverageBlock` from [directed-graph]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_data_structures/graph/trait.DirectedGraph.html [graph-traits]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_data_structures/graph/index.html#traits [mir-dev-guide]: mir/index.md -[compute-basic-coverage-blocks]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/coverage/graph/struct.CoverageGraph.html#method.compute_basic_coverage_blocks -[simplify-cfg]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/simplify/struct.SimplifyCfg.html +[compute-basic-coverage-blocks]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/graph/struct.CoverageGraph.html#method.compute_basic_coverage_blocks +[simplify-cfg]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/simplify/struct.SimplifyCfg.html [rust-lang/rust#78544]: https://github.com/rust-lang/rust/issues/78544 [mir-debugging]: mir/debugging.md -[bcb-from-bb]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/coverage/graph/struct.CoverageGraph.html#method.bcb_from_bb +[bcb-from-bb]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/graph/struct.CoverageGraph.html#method.bcb_from_bb ### `CoverageSpans` @@ -521,9 +521,9 @@ MIR `Statement`s and `Terminator`s contributing to the `CoverageSpan`, and their individual `Span`s (which should be encapsulated within the code region of the refined `CoverageSpan`) -[coverage-spans]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/coverage/spans/struct.CoverageSpans.html -[coverage-span]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/coverage/spans/struct.CoverageSpan.html -[to-refined-spans]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/coverage/spans/struct.CoverageSpans.html#method.to_refined_spans +[coverage-spans]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/spans/struct.CoverageSpans.html +[coverage-span]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/spans/struct.CoverageSpan.html +[to-refined-spans]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/spans/struct.CoverageSpans.html#method.to_refined_spans ### `make_bcb_counters()` @@ -586,8 +586,8 @@ of `Counter` vs. `Expression` also depends on the order of counter assignments, and whether a BCB or incoming edge counter already has its `Counter` or `Expression`. -[bcb-counters]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/coverage/counters/struct.BcbCounters.html -[traverse-coverage-graph-with-loops]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/coverage/graph/struct.TraverseCoverageGraphWithLoops.html +[bcb-counters]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/counters/struct.BcbCounters.html +[traverse-coverage-graph-with-loops]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/graph/struct.TraverseCoverageGraphWithLoops.html ### Injecting counters into a MIR `BasicBlock` @@ -616,9 +616,9 @@ still must be injected because they contribute to other `Expression`s. Finally, edge's with a `CoverageKind::Counter` require a new `BasicBlock`, so the counter is only incremented when traversing the branch edge. -[inject-coverage-span-counters]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/coverage/struct.Instrumentor.html#method.inject_coverage_span_counters -[inject-indirect-counters]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/coverage/struct.Instrumentor.html#method.inject_indirect_counters -[inject-intermediate-expression]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/coverage/fn.inject_intermediate_expression.html +[inject-coverage-span-counters]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/struct.Instrumentor.html#method.inject_coverage_span_counters +[inject-indirect-counters]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/struct.Instrumentor.html#method.inject_indirect_counters +[inject-intermediate-expression]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/fn.inject_intermediate_expression.html ### Additional Debugging Support @@ -627,4 +627,4 @@ See the for a detailed description of the debug output, logging, and configuration options available to developers working on the `InstrumentCoverage` pass. -[coverage-debugging]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/coverage/debug/index.html +[coverage-debugging]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/debug/index.html diff --git a/src/doc/rustc-dev-guide/src/macro-expansion.md b/src/doc/rustc-dev-guide/src/macro-expansion.md index ce82852832..2f42ad9b9e 100644 --- a/src/doc/rustc-dev-guide/src/macro-expansion.md +++ b/src/doc/rustc-dev-guide/src/macro-expansion.md @@ -585,7 +585,7 @@ syntactic sugar and are allowed to be in namespaces. ## Procedural Macros -Precedural macros are also expanded during parsing, as mentioned above. +Procedural macros are also expanded during parsing, as mentioned above. However, they use a rather different mechanism. Rather than having a parser in the compiler, procedural macros are implemented as custom, third-party crates. The compiler will compile the proc macro crate and specially annotated diff --git a/src/doc/rustc-dev-guide/src/mir/dataflow.md b/src/doc/rustc-dev-guide/src/mir/dataflow.md index 61277846ba..0e626d97c6 100644 --- a/src/doc/rustc-dev-guide/src/mir/dataflow.md +++ b/src/doc/rustc-dev-guide/src/mir/dataflow.md @@ -218,17 +218,17 @@ the example below: ["gen-kill" problems]: https://en.wikipedia.org/wiki/Data-flow_analysis#Bit_vector_problems [*Static Program Analysis*]: https://cs.au.dk/~amoeller/spa/ [Debugging MIR]: ./debugging.html -[`AnalysisDomain`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/dataflow/trait.AnalysisDomain.html -[`Analysis`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/dataflow/trait.Analysis.html -[`Engine`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/dataflow/struct.Engine.html -[`GenKillAnalysis`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/dataflow/trait.GenKillAnalysis.html -[`JoinSemiLattice`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/dataflow/lattice/trait.JoinSemiLattice.html -[`NAME`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/dataflow/trait.AnalysisDomain.html#associatedconstant.NAME -[`ResultsCursor`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/dataflow/struct.ResultsCursor.html -[`ResultsVisitor`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/dataflow/trait.ResultsVisitor.html -[`apply_call_return_effect`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/dataflow/trait.Analysis.html#tymethod.apply_call_return_effect -[`into_engine`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/dataflow/trait.Analysis.html#method.into_engine -[`lattice`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/dataflow/lattice/index.html +[`AnalysisDomain`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_dataflow/trait.AnalysisDomain.html +[`Analysis`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_dataflow/trait.Analysis.html +[`Engine`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_dataflow/struct.Engine.html +[`GenKillAnalysis`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_dataflow/trait.GenKillAnalysis.html +[`JoinSemiLattice`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_dataflow/lattice/trait.JoinSemiLattice.html +[`NAME`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_dataflow/trait.AnalysisDomain.html#associatedconstant.NAME +[`ResultsCursor`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_dataflow/struct.ResultsCursor.html +[`ResultsVisitor`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_dataflow/trait.ResultsVisitor.html +[`apply_call_return_effect`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_dataflow/trait.Analysis.html#tymethod.apply_call_return_effect +[`into_engine`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_dataflow/trait.Analysis.html#method.into_engine +[`lattice`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_dataflow/lattice/index.html [goethe]: https://www.youtube.com/watch?v=NVBQSR_HdL0&list=PL_sGR8T76Y58l3Gck3ZwIIHLWEmXrOLV_&index=2 [lattice]: https://en.wikipedia.org/wiki/Lattice_(order) [wiki]: https://en.wikipedia.org/wiki/Data-flow_analysis#Basic_principles diff --git a/src/doc/rustc-dev-guide/src/mir/debugging.md b/src/doc/rustc-dev-guide/src/mir/debugging.md index b7182fa900..3da17785bb 100644 --- a/src/doc/rustc-dev-guide/src/mir/debugging.md +++ b/src/doc/rustc-dev-guide/src/mir/debugging.md @@ -12,7 +12,7 @@ control-flow graph spans associated with MIR elements (including mouse-over actions to reveal elements obscured by overlaps, and tooltips to view the MIR statements). This flag takes an optional value: `statement` (the default), `terminator`, or -`block`, to generate span highlights with different levels of granulatity. +`block`, to generate span highlights with different levels of granularity. `-Z dump-mir=F` is a handy compiler options that will let you view the MIR for each function at each stage of compilation. `-Z dump-mir` takes a **filter** `F` @@ -60,7 +60,7 @@ will select for things that reference *both* `main` and the pass > ls mir_dump rustc.main.000-000.CleanEndRegions.after.mir rustc.main.000-000.CleanEndRegions.before.mir ``` - + Filters can also have `|` parts to combine multiple sets of `&`-filters. For example `main & CleanEndRegions | main & NoLandingPads` will select *either* `main` and `CleanEndRegions` *or* diff --git a/src/doc/rustc-dev-guide/src/mir/drop-elaboration.md b/src/doc/rustc-dev-guide/src/mir/drop-elaboration.md new file mode 100644 index 0000000000..20b92cc45a --- /dev/null +++ b/src/doc/rustc-dev-guide/src/mir/drop-elaboration.md @@ -0,0 +1,195 @@ +# Drop elaboration + + + +## Dynamic drops + +According to the [reference][reference-drop]: + +> When an initialized variable or temporary goes out of scope, its destructor +> is run, or it is dropped. Assignment also runs the destructor of its +> left-hand operand, if it's initialized. If a variable has been partially +> initialized, only its initialized fields are dropped. + +When building the MIR, the `Drop` and `DropAndReplace` terminators represent +places where drops may occur. However, in this phase, the presence of these +terminators does not guarantee that a destructor will run. That's because the +target of a drop may be uninitialized (usually because it has been moved from) +before the terminator is reached. In general, we cannot know at compile-time whether a +variable is initialized. + +```rust +let mut y = vec![]; + +{ + let x = vec![1, 2, 3]; + if std::process::id() % 2 == 0 { + y = x; // conditionally move `x` into `y` + } +} // `x` goes out of scope here. Should it be dropped? +``` + +In these cases, we need to keep track of whether a variable is initialized +*dynamically*. The rules are laid out in detail in [RFC 320: Non-zeroing +dynamic drops][RFC 320]. + +## Drop obligations + +From the RFC: + +> When a local variable becomes initialized, it establishes a set of "drop +> obligations": a set of structural paths (e.g. a local `a`, or a path to a +> field `b.f.y`) that need to be dropped. +> +> The drop obligations for a local variable x of struct-type `T` are computed +> from analyzing the structure of `T`. If `T` itself implements `Drop`, then `x` is a +> drop obligation. If `T` does not implement `Drop`, then the set of drop +> obligations is the union of the drop obligations of the fields of `T`. + +When a structural path is moved from (and thus becomes uninitialized), any drop +obligations for that path or its descendants (`path.f`, `path.f.g.h`, etc.) are +released. Types with `Drop` implementations do not permit moves from individual +fields, so there is no need to track initializedness through them. + +When a local variable goes out of scope (`Drop`), or when a structural path is +overwritten via assignment (`DropAndReplace`), we check for any drop +obligations for that variable or path. Unless that obligation has been +released by this point, its associated `Drop` implementation will be called. +For `enum` types, only fields corresponding to the "active" variant need to be +dropped. When processing drop obligations for such types, we first check the +discriminant to determine the active variant. All drop obligations for variants +besides the active one are ignored. + +Here are a few interesting types to help illustrate these rules: + +```rust +struct NoDrop(u8); // No `Drop` impl. No fields with `Drop` impls. + +struct NeedsDrop(Vec); // No `Drop` impl but has fields with `Drop` impls. + +struct ThinVec(*const u8); // Custom `Drop` impl. Individual fields cannot be moved from. + +impl Drop for ThinVec { + fn drop(&mut self) { /* ... */ } +} + +enum MaybeDrop { + Yes(NeedsDrop), + No(NoDrop), +} +``` + +## Drop elaboration + +One valid model for these rules is to keep a boolean flag (a "drop flag") for +every structural path that is used at any point in the function. This flag is +set when its path is initialized and is cleared when the path is moved from. +When a `Drop` occurs, we check the flags for every obligation associated with +the target of the `Drop` and call the associated `Drop` impl for those that are +still applicable. + +This process—transforming the newly built MIR with its imprecise `Drop` and +`DropAndReplace` terminators into one with drop flags—is known as drop +elaboration. When a MIR statement causes a variable to become initialized (or +uninitialized), drop elaboration inserts code that sets (or clears) the drop +flag for that variable. It wraps `Drop` terminators in conditionals that check +the newly inserted drop flags. + +Drop elaboration also splits `DropAndReplace` terminators into a `Drop` of the +target and a write of the newly dropped place. This is somewhat unrelated to what +we've discussed above. + +Once this is complete, `Drop` terminators in the MIR correspond to a call to +the "drop glue" or "drop shim" for the type of the dropped place. The drop +glue for a type calls the `Drop` impl for that type (if one exists), and then +recursively calls the drop glue for all fields of that type. + +## Drop elaboration in `rustc` + +The approach described above is more expensive than necessary. One can imagine +a few optimizations: + +- Only paths that are the target of a `Drop` (or have the target as a prefix) + need drop flags. +- Some variables are known to initialized (or uninitialized) when they are + dropped. These do not need drop flags. +- If a set of paths are only dropped or moved from via a shared prefix, those + paths can share a single drop flag. + +A subset of these are implemented in `rustc`. + +In the compiler, drop elaboration is split across several modules. The pass +itself is defined [here][drops-transform], but the [main logic][drops] is +defined elsewhere since it is also used to build [drop shims][drops-shim]. + +Drop elaboration designates each `Drop` in the newly built MIR as one of four +kinds: + +- `Static`, the target is always initialized. +- `Dead`, the target is always **un**initialized. +- `Conditional`, the target is either wholly initialized or wholly + uninitialized. It is not partly initialized. +- `Open`, the target may be partly initialized. + +For this, it uses a pair of dataflow analyses, `MaybeInitializedPlaces` and +`MaybeUninitializedPlaces`. If a place is in one but not the other, then the +initializedness of the target is known at compile-time (`Dead` or `Static`). +In this case, drop elaboration does not add a flag for the target. It simply +removes (`Dead`) or preserves (`Static`) the `Drop` terminator. + +For `Conditional` drops, we know that the initializedness of the variable as a +whole is the same as the initializedness of its fields. Therefore, once we +generate a drop flag for the target of that drop, it's safe to call the drop +glue for that target. + +### `Open` drops + +`Open` drops are the most complex, since we need to break down a single `Drop` +terminator into several different ones, one for each field of the target whose +type has drop glue (`Ty::needs_drop`). We cannot call the drop glue for the +target itself because that requires all fields of the target to be initialized. +Remember, variables whose type has a custom `Drop` impl do not allow `Open` +drops because their fields cannot be moved from. + +This is accomplished by recursively categorizing each field as `Dead`, +`Static`, `Conditional` or `Open`. Fields whose type does not have drop glue +are automatically `Dead` and need not be considered during the recursion. When +we reach a field whose kind is not `Open`, we handle it as we did above. If the +field is also `Open`, the recursion continues. + +It's worth noting how we handle `Open` drops of enums. Inside drop elaboration, +each variant of the enum is treated like a field, with the invariant that only +one of those "variant fields" can be initialized at any given time. In the +general case, we do not know which variant is the active one, so we will have +to call the drop glue for the enum (which checks the discriminant) or check the +discriminant ourselves as part of an elaborated `Open` drop. However, in +certain cases (within a `match` arm, for example) we do know which variant of +an enum is active. This information is encoded in the `MaybeInitializedPlaces` +and `MaybeUninitializedPlaces` dataflow analyses by marking all places +corresponding to inactive variants as uninitialized. + +### Cleanup paths + +TODO: Discuss drop elaboration and unwinding. + +## Aside: drop elaboration and const-eval + +In Rust, functions that are eligible for evaluation at compile-time must be +marked explicitly using the `const` keyword. This includes implementations of +the `Drop` trait, which may or may not be `const`. Code that is eligible for +compile-time evaluation may only call `const` functions, so any calls to +non-const `Drop` implementations in such code must be forbidden. + +A call to a `Drop` impl is encoded as a `Drop` terminator in the MIR. However, +as we discussed above, a `Drop` terminator in newly built MIR does not +necessarily result in a call to `Drop::drop`. The drop target may be +uninitialized at that point. This means that checking for non-const `Drop`s on +the newly built MIR can result in spurious errors. Instead, we wait until after +drop elaboration runs, which eliminates `Dead` drops (ones where the target is +known to be uninitialized) to run these checks. + +[RFC 320]: https://rust-lang.github.io/rfcs/0320-nonzeroing-dynamic-drop.html +[reference-drop]: https://doc.rust-lang.org/reference/destructors.html +[drops]: https://github.com/rust-lang/rust/blob/master/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +[drops-shim]: https://github.com/rust-lang/rust/blob/master/compiler/rustc_mir_transform/src/shim.rs +[drops-transform]: https://github.com/rust-lang/rust/blob/master/compiler/rustc_mir_dataflow/src/elaborate_drops.rs diff --git a/src/doc/rustc-dev-guide/src/mir/index.md b/src/doc/rustc-dev-guide/src/mir/index.md index 306d2abfd2..0c00928c0c 100644 --- a/src/doc/rustc-dev-guide/src/mir/index.md +++ b/src/doc/rustc-dev-guide/src/mir/index.md @@ -18,7 +18,9 @@ graphs and desugaring), you may enjoy the ## Introduction to MIR MIR is defined in the [`compiler/rustc_middle/src/mir/`][mir] module, but much of the code -that manipulates it is found in [`compiler/rustc_mir`][mirmanip]. +that manipulates it is found in [`compiler/rustc_mir_build`][mirmanip_build], +[`compiler/rustc_mir_transform`][mirmanip_transform], and +[`compiler/rustc_mir_dataflow`][mirmanip_dataflow]. [RFC 1211]: https://rust-lang.github.io/rfcs/1211-mir.html @@ -52,7 +54,7 @@ This section introduces the key concepts of MIR, summarized here: - **Operands:** the arguments to an rvalue, which can either be a constant (like `22`) or a place (like `_1`). -You can get a feeling for how MIR is structed by translating simple +You can get a feeling for how MIR is constructed by translating simple programs into MIR and reading the pretty printed output. In fact, the playground makes this easy, since it supplies a MIR button that will show you the MIR for your program. Try putting this program into play @@ -258,7 +260,9 @@ See the const-eval WG's [docs on promotion](https://github.com/rust-lang/const-e [mir]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/index.html -[mirmanip]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/index.html +[mirmanip_build]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_build/index.html +[mirmanip_transform]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/index.html +[mirmanip_dataflow]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_dataflow/index.html [`Body`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.Body.html [newtype'd]: ../appendix/glossary.html#newtype [basicblocks]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.Body.html#structfield.basic_blocks diff --git a/src/doc/rustc-dev-guide/src/mir/optimizations.md b/src/doc/rustc-dev-guide/src/mir/optimizations.md index 50e06960ed..9ecf4e0d30 100644 --- a/src/doc/rustc-dev-guide/src/mir/optimizations.md +++ b/src/doc/rustc-dev-guide/src/mir/optimizations.md @@ -21,7 +21,7 @@ for a given [`DefId`][defid]. This query makes sure that the borrow checker has run and that some validation has occurred. Then, it [steals][steal] the MIR, optimizes it, and returns the improved MIR. -[optmir]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/fn.optimized_mir.html +[optmir]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/fn.optimized_mir.html [query]: https://rustc-dev-guide.rust-lang.org/query.html [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 @@ -42,7 +42,7 @@ optimizes it, and returns the improved MIR. 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`]. +4. Implement a new optimization in [`compiler/rustc_mir_transform/src`]. The fastest and easiest way to do this is to 1. pick a small optimization (such as [`no_landing_pads`]) and copy it @@ -71,9 +71,10 @@ 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 +[`compiler/rustc_mir_transform/src`]: https://github.com/rust-lang/rust/tree/master/compiler/rustc_mir_transform/src + +[`no_landing_pads`]: https://github.com/rust-lang/rust/blob/master/compiler/rustc_mir_transform/src/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 @@ -81,11 +82,11 @@ The list of passes run and the order in which they are run is defined by the [`run_optimization_passes`][rop] function. It contains an array of passes to run. Each pass in the array is a struct that implements the [`MirPass`] trait. The array is an array of `&dyn MirPass` trait objects. Typically, a pass is -implemented in its own submodule of the [`rustc_mir::transform`][trans] module. +implemented in its own module of the [`rustc_mir_transform`][trans] crate. -[rop]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/fn.run_optimization_passes.html -[`MirPass`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/trait.MirPass.html -[trans]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/index.html +[rop]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/fn.run_optimization_passes.html +[`MirPass`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/trait.MirPass.html +[trans]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/index.html Some examples of passes are: - `CleanupNonCodegenStatements`: remove some of the info that is only needed for @@ -94,7 +95,7 @@ Some examples of passes are: You can see the ["Implementors" section of the `MirPass` rustdocs][impl] for more examples. -[impl]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/trait.MirPass.html#implementors +[impl]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/trait.MirPass.html#implementors [constprop]: https://en.wikipedia.org/wiki/Constant_folding#Constant_propagation ## MIR optimization levels diff --git a/src/doc/rustc-dev-guide/src/mir/passes.md b/src/doc/rustc-dev-guide/src/mir/passes.md index b847584b1b..5528b77624 100644 --- a/src/doc/rustc-dev-guide/src/mir/passes.md +++ b/src/doc/rustc-dev-guide/src/mir/passes.md @@ -27,7 +27,7 @@ where we want to access the MIR for type checking or other purposes: A `MirPass` is some bit of code that processes the MIR, typically – but not always – transforming it along the way somehow. For example, it might perform an optimization. The `MirPass` trait itself is found -in [the `rustc_mir::transform` module][mirtransform], and it +in [the `rustc_mir_transform` crate][mirtransform], and it basically consists of one method, `run_pass`, that simply gets an `&mut Mir` (along with the tcx and some information about where it came from). The MIR is therefore modified in place (which helps to @@ -96,6 +96,7 @@ This mechanism is a bit dodgy. There is a discussion of more elegant alternatives in [rust-lang/rust#41710]. [rust-lang/rust#41710]: https://github.com/rust-lang/rust/issues/41710 -[mirtransform]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/ -[`NoLandingPads`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/no_landing_pads/struct.NoLandingPads.html +[mirtransform]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/ + +[`NoLandingPads`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/no_landing_pads/struct.NoLandingPads.html [MIR visitor]: ./visitor.html diff --git a/src/doc/rustc-dev-guide/src/mir/visitor.md b/src/doc/rustc-dev-guide/src/mir/visitor.md index c80462b953..5c21d5304a 100644 --- a/src/doc/rustc-dev-guide/src/mir/visitor.md +++ b/src/doc/rustc-dev-guide/src/mir/visitor.md @@ -41,7 +41,8 @@ A very simple example of a visitor can be found in [`NoLandingPads`]. That visitor doesn't even require any state: it just visits all terminators and removes their `unwind` successors. -[`NoLandingPads`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/no_landing_pads/struct.NoLandingPads.html + +[`NoLandingPads`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/no_landing_pads/struct.NoLandingPads.html ## Traversal diff --git a/src/doc/rustc-dev-guide/src/miri.md b/src/doc/rustc-dev-guide/src/miri.md index c19ba64012..dd54f65483 100644 --- a/src/doc/rustc-dev-guide/src/miri.md +++ b/src/doc/rustc-dev-guide/src/miri.md @@ -100,11 +100,11 @@ further queries need to be executed in order to get at something as simple as a Future evaluations of the same constants will not actually invoke Miri, but just use the cached result. -[`Operand`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/interpret/enum.Operand.html -[`Immediate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/interpret/enum.Immediate.html +[`Operand`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_const_eval/interpret/enum.Operand.html +[`Immediate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_const_eval/interpret/enum.Immediate.html [`ConstValue`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/enum.ConstValue.html [`Scalar`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/enum.Scalar.html -[`op_to_const`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/const_eval/eval_queries/fn.op_to_const.html +[`op_to_const`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_const_eval/const_eval/eval_queries/fn.op_to_const.html ## Datastructures @@ -119,7 +119,7 @@ allocation. These allocations can be accessed via the methods on see [the next section](#memory) for more on that. If you are expecting a numeric result, you can use `eval_usize` (panics on -anything that can't be representad as a `u64`) or `try_eval_usize` which results +anything that can't be represented as a `u64`) or `try_eval_usize` which results in an `Option` yielding the `Scalar` if possible. ## Memory @@ -183,7 +183,7 @@ needed to support circular statics, where we need to have a `Pointer` to a `static` for which we cannot yet have an `Allocation` as we do not know the bytes of its value. -[`Memory`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/interpret/struct.Memory.html +[`Memory`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_const_eval/interpret/struct.Memory.html [`Allocation`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/struct.Allocation.html [`Pointer`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/struct.Pointer.html [`GlobalAlloc`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/enum.GlobalAlloc.html @@ -209,7 +209,7 @@ values. Although the main entry point to constant evaluation is the `tcx.const_eval_*` functions, there are additional functions in -[rustc_mir/src/const_eval.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/const_eval/index.html) +[rustc_const_eval/src/const_eval](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_const_eval/index.html) that allow accessing the fields of a `ConstValue` (`ByRef` or otherwise). You should never have to access an `Allocation` directly except for translating it to the compilation target (at the moment just LLVM). @@ -220,7 +220,7 @@ function with no arguments, except that constants do not allow local (named) variables at the time of writing this guide. A stack frame is defined by the `Frame` type in -[rustc_mir/src/interpret/eval_context.rs](https://github.com/rust-lang/rust/blob/master/compiler/rustc_mir/src/interpret/eval_context.rs) +[rustc_const_eval/src/interpret/eval_context.rs](https://github.com/rust-lang/rust/blob/master/compiler/rustc_const_eval/src/interpret/eval_context.rs) and contains all the local variables memory (`None` at the start of evaluation). Each frame refers to the evaluation of either the root constant or subsequent calls to `const fn`. The @@ -232,7 +232,7 @@ The frames are just a `Vec`, there's no way to actually refer to a memory that can be referred to are `Allocation`s. Miri now calls the `step` method (in -[rustc_mir/src/interpret/step.rs](https://github.com/rust-lang/rust/blob/master/compiler/rustc_mir/src/interpret/step.rs) +[rustc_const_eval/src/interpret/step.rs](https://github.com/rust-lang/rust/blob/master/compiler/rustc_const_eval/src/interpret/step.rs) ) until it either returns an error or has no further statements to execute. Each statement will now initialize or modify the locals or the virtual memory referred to by a local. This might require evaluating other constants or diff --git a/src/doc/rustc-dev-guide/src/overview.md b/src/doc/rustc-dev-guide/src/overview.md index 26b291d35f..5c88722ef3 100644 --- a/src/doc/rustc-dev-guide/src/overview.md +++ b/src/doc/rustc-dev-guide/src/overview.md @@ -262,7 +262,7 @@ Moreover, the compiler wasn't originally built to use a query system; the query system has been retrofitted into the compiler, so parts of it are not query-fied yet. Also, LLVM isn't our code, so that isn't querified either. The plan is to eventually query-fy all of the steps listed in the previous section, -but as of February 2021, only the steps between HIR and +but as of November 2021, only the steps between HIR and LLVM IR are query-fied. That is, lexing, parsing, name resolution, and macro expansion are done all at once for the whole program. @@ -373,15 +373,15 @@ For more details on bootstrapping, see - The Mid Level Intermediate Representation (MIR) - Guide: [The MIR (Mid level IR)](https://rustc-dev-guide.rust-lang.org/mir/index.html) - Definition: [`rustc_middle/src/mir`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/index.html) - - Definition of source that manipulates the MIR: [`rustc_mir`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/index.html) + - Definition of sources that manipulates the MIR: [`rustc_mir_build`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_build/index.html), [`rustc_mir_dataflow`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_dataflow/index.html), [`rustc_mir_transform`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/index.html) - The Borrow Checker - Guide: [MIR Borrow Check](https://rustc-dev-guide.rust-lang.org/borrow_check.html) - - Definition: [`rustc_mir/borrow_check`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/index.html) - - Main entry point: [`mir_borrowck` query](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/fn.mir_borrowck.html) + - Definition: [`rustc_borrowck`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/index.html) + - Main entry point: [`mir_borrowck` query](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/fn.mir_borrowck.html) - MIR Optimizations - Guide: [MIR Optimizations](https://rustc-dev-guide.rust-lang.org/mir/optimizations.html) - - Definition: [`rustc_mir/transform`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/index.html) - - Main entry point: [`optimized_mir` query](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/fn.optimized_mir.html) + - Definition: [`rustc_mir_transform`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/index.html) + - Main entry point: [`optimized_mir` query](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/fn.optimized_mir.html) - Code Generation - Guide: [Code Generation](https://rustc-dev-guide.rust-lang.org/backend/codegen.html) - Generating Machine Code from LLVM IR with LLVM - **TODO: reference?** diff --git a/src/doc/rustc-dev-guide/src/profiling.md b/src/doc/rustc-dev-guide/src/profiling.md index ca0fee6d57..fd7014224d 100644 --- a/src/doc/rustc-dev-guide/src/profiling.md +++ b/src/doc/rustc-dev-guide/src/profiling.md @@ -5,7 +5,10 @@ This section talks about how to profile the compiler and find out where it spend Depending on what you're trying to measure, there are several different approaches: - If you want to see if a PR improves or regresses compiler performance: - - The [rustc-perf](https://github.com/rust-lang/rustc-perf) project makes this easy and can be triggered to run on a PR via the `@rustc-perf` bot. + - The [rustc-perf](https://github.com/rust-lang/rustc-perf) project makes this easy and can be triggered to run on a PR via the `@rust-timer` bot. + The `@bors try @rust-timer queue` command, in a comment on the PR, will queue a try build and a + benchmarking run. + Note: you need `try` privileges to be able to do this. More details are available in the [perf collector documentation](https://github.com/rust-lang/rustc-perf/blob/master/collector/README.md). - If you want a medium-to-high level overview of where `rustc` is spending its time: - The `-Z self-profile` flag and [measureme](https://github.com/rust-lang/measureme) tools offer a query-based approach to profiling. @@ -41,7 +44,7 @@ extension in LLVM bitcode format. Example usage: ``` cargo install cargo-llvm-lines -# On a normal crate you could now run `cargo llvm-lines`, but x.py isn't normal :P +# On a normal crate you could now run `cargo llvm-lines`, but `x.py` isn't normal :P # Do a clean before every run, to not mix in the results from previous runs. ./x.py clean @@ -85,7 +88,7 @@ Example output for the compiler: 326903 (0.7%) 642 (0.0%) rustc_query_system::query::plumbing::try_execute_query ``` -Since this doesn't seem to work with incremental compilation or `x.py check`, +Since this doesn't seem to work with incremental compilation or `./x.py check`, you will be compiling rustc _a lot_. I recommend changing a few settings in `config.toml` to make it bearable: ``` diff --git a/src/doc/rustc-dev-guide/src/profiling/with_perf.md b/src/doc/rustc-dev-guide/src/profiling/with_perf.md index b383ec542b..af30b47325 100644 --- a/src/doc/rustc-dev-guide/src/profiling/with_perf.md +++ b/src/doc/rustc-dev-guide/src/profiling/with_perf.md @@ -253,7 +253,7 @@ the regular expression matched. ### Example: Where does MIR borrowck spend its time? -Often we want to do a more "explorational" queries. Like, we know that +Often we want to do more "explorational" queries. Like, we know that MIR borrowck is 29% of the time, but where does that time get spent? For that, the `--tree-callees` option is often the best tool. You usually also want to give `--tree-min-percent` or @@ -268,14 +268,14 @@ Percentage : 43% Tree | matched `{do_mir_borrowck}` (43% total, 0% self) -: | rustc_mir::borrow_check::nll::compute_regions (20% total, 0% self) -: : | rustc_mir::borrow_check::nll::type_check::type_check_internal (13% total, 0% self) +: | rustc_borrowck::nll::compute_regions (20% total, 0% self) +: : | rustc_borrowck::nll::type_check::type_check_internal (13% total, 0% self) : : : | core::ops::function::FnOnce::call_once (5% total, 0% self) -: : : : | rustc_mir::borrow_check::nll::type_check::liveness::generate (5% total, 3% self) -: : : | as rustc::mir::visit::Visitor<'tcx>>::visit_mir (3% total, 0% self) +: : : : | rustc_borrowck::nll::type_check::liveness::generate (5% total, 3% self) +: : : | as rustc::mir::visit::Visitor<'tcx>>::visit_mir (3% total, 0% self) : | rustc::mir::visit::Visitor::visit_mir (8% total, 6% self) -: | as rustc_mir::dataflow::DataflowResultsConsumer<'cx, 'tcx>>::visit_statement_entry (5% total, 0% self) -: | rustc_mir::dataflow::do_dataflow (3% total, 0% self) +: | as rustc_mir_dataflow::DataflowResultsConsumer<'cx, 'tcx>>::visit_statement_entry (5% total, 0% self) +: | rustc_mir_dataflow::do_dataflow (3% total, 0% self) ``` What happens with `--tree-callees` is that @@ -319,10 +319,10 @@ Percentage : 100% Tree | matched `{do_mir_borrowck}` (100% total, 0% self) -: | rustc_mir::borrow_check::nll::compute_regions (47% total, 0% self) [...] +: | rustc_borrowck::nll::compute_regions (47% total, 0% self) [...] : | rustc::mir::visit::Visitor::visit_mir (19% total, 15% self) [...] -: | as rustc_mir::dataflow::DataflowResultsConsumer<'cx, 'tcx>>::visit_statement_entry (13% total, 0% self) [...] -: | rustc_mir::dataflow::do_dataflow (8% total, 1% self) [...] +: | as rustc_mir_dataflow::DataflowResultsConsumer<'cx, 'tcx>>::visit_statement_entry (13% total, 0% self) [...] +: | rustc_mir_dataflow::do_dataflow (8% total, 1% self) [...] ``` Here you see that `compute_regions` came up as "47% total" — that diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals.md b/src/doc/rustc-dev-guide/src/rustdoc-internals.md index 112a5dcab7..0d7459b1d3 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc-internals.md +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals.md @@ -66,7 +66,7 @@ these passes, please let us know!) [44136]: https://github.com/rust-lang/rust/issues/44136 -Here is the list of passes as of February 2021: +Here is the list of passes as of October 2021: - `calculate-doc-coverage` calculates information used for the `--show-coverage` flag. diff --git a/src/doc/rustc-dev-guide/src/sanitizers.md b/src/doc/rustc-dev-guide/src/sanitizers.md index 49183d6d5e..a088d62eda 100644 --- a/src/doc/rustc-dev-guide/src/sanitizers.md +++ b/src/doc/rustc-dev-guide/src/sanitizers.md @@ -5,6 +5,8 @@ The rustc compiler contains support for following sanitizers: * [AddressSanitizer][clang-asan] a faster memory error detector. Can detect out-of-bounds access to heap, stack, and globals, use after free, use after return, double free, invalid free, memory leaks. +* [ControlFlowIntegrity][clang-cfi] LLVM Control Flow Integrity (CFI) provides + forward-edge control flow protection. * [Hardware-assisted AddressSanitizer][clang-hwasan] a tool similar to AddressSanitizer but based on partial hardware assistance. * [LeakSanitizer][clang-lsan] a run-time memory leak detector. @@ -14,15 +16,16 @@ The rustc compiler contains support for following sanitizers: ## How to use the sanitizers? To enable a sanitizer compile with `-Z sanitizer=...` option, where value is one -of `address`, `hwaddress`, `leak`, `memory` or `thread`. For more details on how -to use sanitizers please refer to the sanitizer flag in [the unstable +of `address`, `cfi`, `hwaddress`, `leak`, `memory` or `thread`. For more details +on how to use sanitizers please refer to the sanitizer flag in [the unstable book](https://doc.rust-lang.org/unstable-book/). ## How are sanitizers implemented in rustc? -The implementation of sanitizers relies almost entirely on LLVM. The rustc is -an integration point for LLVM compile time instrumentation passes and runtime -libraries. Highlight of the most important aspects of the implementation: +The implementation of sanitizers (except CFI) relies almost entirely on LLVM. +The rustc is an integration point for LLVM compile time instrumentation passes +and runtime libraries. Highlight of the most important aspects of the +implementation: * The sanitizer runtime libraries are part of the [compiler-rt] project, and [will be built][sanitizer-build] on [supported targets][sanitizer-targets] @@ -104,12 +107,14 @@ To enable a sanitizer on a new target which is already supported by LLVM: * [Sanitizers project page](https://github.com/google/sanitizers/wiki/) * [AddressSanitizer in Clang][clang-asan] +* [ControlFlowIntegrity in Clang][clang-cfi] * [Hardware-assisted AddressSanitizer][clang-hwasan] * [LeakSanitizer in Clang][clang-lsan] * [MemorySanitizer in Clang][clang-msan] * [ThreadSanitizer in Clang][clang-tsan] [clang-asan]: https://clang.llvm.org/docs/AddressSanitizer.html +[clang-cfi]: https://clang.llvm.org/docs/ControlFlowIntegrity.html [clang-hwasan]: https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html [clang-lsan]: https://clang.llvm.org/docs/LeakSanitizer.html [clang-msan]: https://clang.llvm.org/docs/MemorySanitizer.html diff --git a/src/doc/rustc-dev-guide/src/tests/adding.md b/src/doc/rustc-dev-guide/src/tests/adding.md index d1b19516f6..34bd6f20ee 100644 --- a/src/doc/rustc-dev-guide/src/tests/adding.md +++ b/src/doc/rustc-dev-guide/src/tests/adding.md @@ -43,7 +43,6 @@ rough heuristics: message is not relevant to the test. These should have an [error number] (`E0XXX`) in the code block to make sure it's the correct error. - For most other things, [a `ui` (or `ui-fulldeps`) test](#ui) is to be preferred: - - [`ui`](#ui) tests subsume both `run-pass`, `compile-fail`, and `parse-fail` tests - in the case of warnings or errors, `ui` tests capture the full output, which makes it easier to review but also helps prevent "hidden" regressions in the output diff --git a/src/doc/rustc-dev-guide/src/tests/intro.md b/src/doc/rustc-dev-guide/src/tests/intro.md index 6419133455..25c1d059c1 100644 --- a/src/doc/rustc-dev-guide/src/tests/intro.md +++ b/src/doc/rustc-dev-guide/src/tests/intro.md @@ -3,7 +3,7 @@ The Rust project runs a wide variety of different tests, orchestrated by -the build system (`x.py test`). The main test harness for testing the +the build system (`./x.py test`). The main test harness for testing the compiler itself is a tool called compiletest (located in the [`src/tools/compiletest`] directory). This section gives a brief overview of how the testing framework is setup, and then gets into some @@ -126,8 +126,7 @@ essence, it runs `./x.py test` after building for each of them. The integration bot [bors] is used for coordinating merges to the master branch. When a PR is approved, it goes into a [queue] where merges are tested one at a -time on a wide set of platforms using GitHub Actions (as of January 2021, over 50 different configurations). Due to the limit on the +time on a wide set of platforms using GitHub Actions. Due to the limit on the number of parallel jobs, we run CI under the [rust-lang-ci] organization except for PRs. Most platforms only run the build steps, some run a restricted set of tests, only a subset run the full suite of tests (see Rust's [platform tiers]). diff --git a/src/doc/rustc-dev-guide/src/tests/running.md b/src/doc/rustc-dev-guide/src/tests/running.md index 34a44f9c24..2e1ce0a910 100644 --- a/src/doc/rustc-dev-guide/src/tests/running.md +++ b/src/doc/rustc-dev-guide/src/tests/running.md @@ -49,7 +49,7 @@ with the debuginfo test suite: ``` If you only need to test a specific subdirectory of tests for any -given test suite, you can pass that directory to `x.py test`: +given test suite, you can pass that directory to `./x.py test`: ```bash ./x.py test src/test/ui/const-generics @@ -186,8 +186,17 @@ To run the UI test suite in NLL mode, one would use the following: ./x.py test src/test/ui --compare-mode=nll ``` -Other examples of compare-modes are "noopt", "migrate", and -[revisions](./adding.html#revisions). +The possible compare modes are: + +* nll - currently nll is implemented in migrate mode, this option runs with true nll. +* polonius +* chalk +* split-dwarf +* split-dwarf-single + +Note that compare modes are separate to [revisions](./adding.html#revisions). +All revisions are tested when running `./x.py test src/test/ui`, +however compare-modes must be manually run individually via the `--compare-mode` flag. ## Running tests manually diff --git a/src/doc/rustc-dev-guide/src/tracing.md b/src/doc/rustc-dev-guide/src/tracing.md index 422d94c538..63d68e5412 100644 --- a/src/doc/rustc-dev-guide/src/tracing.md +++ b/src/doc/rustc-dev-guide/src/tracing.md @@ -176,7 +176,7 @@ here. There is no perfect balance to hit here, and is left to the reviewer's discretion to decide whether to let you leave `debug!` statements in or whether to ask you to remove them before merging. -It may be preferrable to use `trace!` over `debug!` for very noisy logs. +It may be preferable to use `trace!` over `debug!` for very noisy logs. A loosely followed convention is to use `#[instrument(level = "debug")]` ([also see the attribute's documentation](https://docs.rs/tracing-attributes/0.1.17/tracing_attributes/attr.instrument.html)) @@ -201,4 +201,4 @@ This means that you should not put anything too expensive or likely to crash there - that would annoy anyone who wants to use logging for that module. No-one will know it until someone tries to use logging to find *another* bug. -[`tracing`]: https://docs.rs/tracing \ No newline at end of file +[`tracing`]: https://docs.rs/tracing diff --git a/src/doc/rustc-dev-guide/src/ty.md b/src/doc/rustc-dev-guide/src/ty.md index 9ee2ccfe2d..87d653a745 100644 --- a/src/doc/rustc-dev-guide/src/ty.md +++ b/src/doc/rustc-dev-guide/src/ty.md @@ -312,7 +312,7 @@ delaying a redundant span bug. Recall that we represent a generic struct with `(AdtDef, substs)`. So why bother with this scheme? -Well, the alternate way we could have choosen to represent types would be to always create a new, +Well, the alternate way we could have chosen to represent types would be to always create a new, fully-substituted form of the `AdtDef` where all the types are already substituted. This seems like less of a hassle. However, the `(AdtDef, substs)` scheme has some advantages over this. diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 8c41835183..69a0304d41 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -15,6 +15,8 @@ - [Platform Support](platform-support.md) - [aarch64-apple-ios-sim](platform-support/aarch64-apple-ios-sim.md) - [\*-kmc-solid_\*](platform-support/kmc-solid.md) + - [x86_64-unknown-none](platform-support/x86_64-unknown-none.md) + - [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md) - [Target Tier Policy](target-tier-policy.md) - [Targets](targets/index.md) - [Built-in Targets](targets/built-in.md) diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index 4f8c4c66f8..0201b88417 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -525,6 +525,22 @@ platforms. Possible values are: Note that `packed` and `unpacked` are gated behind `-Z unstable-options` on non-macOS platforms at this time. +## strip + +The option `-C strip=val` controls stripping of debuginfo and similar auxiliary +data from binaries during linking. + +Supported values for this option are: + +- `none` - debuginfo and symbols (if they exist) are copied to the produced + binary or separate files depending on the target (e.g. `.pdb` files in case + of MSVC). +- `debuginfo` - debuginfo sections and debuginfo symbols from the symbol table + section are stripped at link time and are not copied to the produced binary + or separate files. +- `symbols` - same as `debuginfo`, but the rest of the symbol table section is + stripped as well if the linker supports it. + ## target-cpu This instructs `rustc` to generate code specifically for a particular processor. diff --git a/src/doc/rustc/src/exploit-mitigations.md b/src/doc/rustc/src/exploit-mitigations.md index 70df5170b2..fa38dd54d6 100644 --- a/src/doc/rustc/src/exploit-mitigations.md +++ b/src/doc/rustc/src/exploit-mitigations.md @@ -123,9 +123,9 @@ equivalent. Forward-edge control flow protection - No + Yes - + Nightly @@ -465,24 +465,27 @@ implementations such as [LLVM ControlFlowIntegrity commercially available [grsecurity/PaX Reuse Attack Protector (RAP)](https://grsecurity.net/rap_faq). -The Rust compiler does not support forward-edge control flow protection on -Linux6. There is work currently ongoing to add support -for the [sanitizers](https://github.com/google/sanitizers)[40], which may or -may not include support for LLVM CFI. +The Rust compiler supports forward-edge control flow protection on nightly +builds[40]-[41] 6. ```text -$ readelf -s target/release/hello-rust | grep __cfi_init +$ readelf -s -W target/debug/rust-cfi | grep "\.cfi" + 12: 0000000000005170 46 FUNC LOCAL DEFAULT 14 _RNvCsjaOHoaNjor6_8rust_cfi7add_one.cfi + 15: 00000000000051a0 16 FUNC LOCAL DEFAULT 14 _RNvCsjaOHoaNjor6_8rust_cfi7add_two.cfi + 17: 0000000000005270 396 FUNC LOCAL DEFAULT 14 _RNvCsjaOHoaNjor6_8rust_cfi4main.cfi +... ``` -Fig. 15. Checking if LLVM CFI is enabled for a given binary. +Fig. 15. Checking if LLVM CFI is enabled for a given binary[41]. -The presence of the `__cfi_init` symbol (and references to `__cfi_check`) -indicates that LLVM CFI (i.e., forward-edge control flow protection) is -enabled for a given binary. Conversely, the absence of the `__cfi_init` -symbol (and references to `__cfi_check`) indicates that LLVM CFI is not -enabled for a given binary (see Fig. 15). +The presence of symbols suffixed with ".cfi" or the `__cfi_init` symbol (and +references to `__cfi_check`) indicates that LLVM CFI (i.e., forward-edge control +flow protection) is enabled for a given binary. Conversely, the absence of +symbols suffixed with ".cfi" or the `__cfi_init` symbol (and references to +`__cfi_check`) indicates that LLVM CFI is not enabled for a given binary (see +Fig. 15). -6\. It supports Control Flow Guard (CFG) on Windows (see +6\. It also supports Control Flow Guard (CFG) on Windows (see ). ↩ @@ -689,5 +692,8 @@ defaults (unrelated to `READ_IMPLIES_EXEC`). 39. A. Crichton. “Remove the alloc\_jemalloc crate #55238.” GitHub. . -40. J. Aparicio. 2017. “Tracking issue for sanitizer support #39699.” - . +40. R. de C Valle. “Tracking Issue for LLVM Control Flow Integrity (CFI) Support + for Rust #89653.” GitHub. . + +41. “ControlFlowIntegrity.” The Rust Unstable Book. + . diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index bbeab598f2..4da3491c58 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -276,7 +276,7 @@ target | std | host | notes `thumbv7a-pc-windows-msvc` | ? | | `thumbv7a-uwp-windows-msvc` | ✓ | | `thumbv7neon-unknown-linux-musleabihf` | ? | | Thumb2-mode ARMv7a Linux with NEON, MUSL -`wasm64-unknown-unknown` | * | | WebAssembly +[`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? | | WebAssembly `x86_64-apple-ios-macabi` | ✓ | | Apple Catalyst on x86_64 `x86_64-apple-tvos` | * | | x86 64-bit tvOS `x86_64-pc-windows-msvc` | ✓ | | 64-bit Windows XP support @@ -285,6 +285,7 @@ target | std | host | notes `x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku `x86_64-unknown-hermit` | ? | | `x86_64-unknown-l4re-uclibc` | ? | | +[`x86_64-unknown-none`](platform-support/x86_64-unknown-none.md) | * | | Freestanding/bare-metal x86_64, softfloat `x86_64-unknown-none-hermitkernel` | ? | | HermitCore kernel `x86_64-unknown-none-linuxkernel` | * | | Linux kernel modules `x86_64-unknown-openbsd` | ✓ | ✓ | 64-bit OpenBSD diff --git a/src/doc/rustc/src/platform-support/wasm64-unknown-unknown.md b/src/doc/rustc/src/platform-support/wasm64-unknown-unknown.md new file mode 100644 index 0000000000..021b904deb --- /dev/null +++ b/src/doc/rustc/src/platform-support/wasm64-unknown-unknown.md @@ -0,0 +1,101 @@ +# `wasm64-unknown-unknown` + +**Tier: 3** + +WebAssembly target which uses 64-bit memories, relying on the [memory64] +WebAssembly proposal. + +[memory64]: https://github.com/webassembly/memory64 + +## Target maintainers + +- Alex Crichton, https://github.com/alexcrichton + +## Requirements + +This target is cross-compiled. The target supports `std` in the same manner as +the `wasm32-unknown-unknown` target which is to say that it comes with the +standard library but many I/O functions such as `std::fs` and `std::net` will +simply return error. Additionally I/O operations like `println!` don't actually +do anything and the prints aren't routed anywhere. This is the same as the +`wasm32-unknown-unknown` target. This target comes by default with an allocator, +currently [dlmalloc] which is [ported to rust][dlmalloc-rs]. + +[dlmalloc]: http://gee.cs.oswego.edu/dl/html/malloc.html +[dlmalloc-rs]: https://github.com/alexcrichton/dlmalloc-rs + +The difference of this target with `wasm32-unknown-unknown` is that it's +compiled for 64-bit memories instead of 32-bit memories. This means that `usize` +is 8-bytes large as well as pointers. The tradeoff, though, is that the maximum +memory size is now the full 64-bit address space instead of the 4GB as limited +by the 32-bit address space for `wasm32-unknown-unknown`. + +This target is not a stable target. The [memory64] WebAssembly proposal is stil +in-progress and not standardized. This means that there are not many engines +which implement the `memory64` feature and if they do they're likely behind a +flag, for example: + +* Nodejs - `--experimental-wasm-memory64` +* Wasmtime - `--wasm-features memory64` + +Also note that at this time the `wasm64-unknown-unknown` target assumes the +presence of other merged wasm proposals such as (with their LLVM feature flags): + +* [Bulk memory] - `+bulk-memory` +* Mutable imported globals - `+mutable-globals` +* [Sign-extending operations] - `+sign-ext` +* [Non-trapping fp-to-int operations] - `+nontrapping-fptoint` + +[Bulk memory]: https://github.com/WebAssembly/spec/blob/main/proposals/bulk-memory-operations/Overview.md +[Sign-extending operations]: https://github.com/WebAssembly/spec/blob/main/proposals/sign-extension-ops/Overview.md +[Non-trapping fp-to-int operations]: https://github.com/WebAssembly/spec/blob/main/proposals/nontrapping-float-to-int-conversion/Overview.md + +The `wasm64-unknown-unknown` target intends to match the default Clang targets +for its `"C"` ABI, which is likely to be the same as Clang's +`wasm32-unknown-unknown` largely. + +> **Note**: due to the relatively early-days nature of this target when working +> with this target you may encounter LLVM bugs. If an assertion hit or a bug is +> found it's recommended to open an issue either with rust-lang/rust or ideally +> with LLVM itself. + +This target does not support `panic=unwind` at this time. + +## Building the target + +You can build Rust with support for the target by adding it to the `target` +list in `config.toml`, and the target also requires `lld` to be built to work. + +```toml +[build] +target = ["wasm64-unknown-unknown"] + +[rust] +lld = true +``` + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for this target. To compile for +this target, you will either need to build Rust with the target enabled (see +"Building the target" above), or build your own copy of `std` by using +`build-std` or similar. + +Note that the following `cfg` directives are set for `wasm64-unknown-unknown`: + +* `cfg(target_arch = "wasm64")` +* `cfg(target_family = "wasm")` + +## Testing + +Currently testing is not well supported for `wasm64-unknown-unknown` and the +Rust project doesn't run any tests for this target. Testing support sort of +works but without `println!` it's not the most exciting tests to run. + +## Cross-compilation toolchains and C code + +Compiling Rust code with C code for `wasm64-unknown-unknown` is theoretically +possible, but there are no known toolchains to do this at this time. At the time +of this writing there is no known "libc" for wasm that works with +`wasm64-unknown-unknown`, which means that mixing C & Rust with this target +effectively cannot be done. diff --git a/src/doc/rustc/src/platform-support/x86_64-unknown-none.md b/src/doc/rustc/src/platform-support/x86_64-unknown-none.md new file mode 100644 index 0000000000..afcc48003b --- /dev/null +++ b/src/doc/rustc/src/platform-support/x86_64-unknown-none.md @@ -0,0 +1,76 @@ +# `x86_64-unknown-none` + +**Tier: 3** + +Freestanding/bare-metal x86-64 binaries in ELF format: firmware, kernels, etc. + +## Target maintainers + +- Harald Hoyer `harald@profian.com`, https://github.com/haraldh +- Mike Leany, https://github.com/mikeleany + +## Requirements + +This target is cross-compiled. There is no support for `std`. There is no +default allocator, but it's possible to use `alloc` by supplying an allocator. + +By default, Rust code generated for this target does not use any vector or +floating-point registers (e.g. SSE, AVX). This allows the generated code to run +in environments, such as kernels, which may need to avoid the use of such +registers or which may have special considerations about the use of such +registers (e.g. saving and restoring them to avoid breaking userspace code +using the same registers). You can change code generation to use additional CPU +features via the `-C target-feature=` codegen options to rustc, or via the +`#[target_feature]` mechanism within Rust code. + +By default, code generated with this target should run on any `x86_64` +hardware; enabling additional target features may raise this baseline. + +Code generated with this target will use the `kernel` code model by default. +You can change this using the `-C code-model=` option to rustc. + +On `x86_64-unknown-none`, `extern "C"` uses the [standard System V calling +convention](https://gitlab.com/x86-psABIs/x86-64-ABI), without red zones. + +This target generated binaries in the ELF format. Any alternate formats or +special considerations for binary layout will require linker options or linker +scripts. + +## Building the target + +You can build Rust with support for the target by adding it to the `target` +list in `config.toml`: + +```toml +[build] +build-stage = 1 +target = ["x86_64-unknown-none"] +``` + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for this target. To compile for +this target, you will either need to build Rust with the target enabled (see +"Building the target" above), or build your own copy of `core` by using +`build-std` or similar. + +## Testing + +As `x86_64-unknown-none` supports a variety of different environments and does +not support `std`, this target does not support running the Rust testsuite. + +## Cross-compilation toolchains and C code + +If you want to compile C code along with Rust (such as for Rust crates with C +dependencies), you will need an appropriate `x86_64` toolchain. + +Rust *may* be able to use an `x86_64-linux-gnu-` toolchain with appropriate +standalone flags to build for this toolchain (depending on the assumptions of +that toolchain, see below), or you may wish to use a separate +`x86_64-unknown-none` (or `x86_64-elf-`) toolchain. + +On some `x86_64` hosts that use ELF binaries, you *may* be able to use the host +C toolchain, if it does not introduce assumptions about the host environment +that don't match the expectations of a standalone environment. Otherwise, you +may need a separate toolchain for standalone/freestanding development, just as +when cross-compiling from a non-`x86_64` platform. diff --git a/src/doc/rustdoc/src/SUMMARY.md b/src/doc/rustdoc/src/SUMMARY.md index 3fa91bb51f..eb18185945 100644 --- a/src/doc/rustdoc/src/SUMMARY.md +++ b/src/doc/rustdoc/src/SUMMARY.md @@ -1,6 +1,7 @@ # The Rustdoc Book - [What is rustdoc?](what-is-rustdoc.md) +- [How to read rustdoc output](how-to-read-rustdoc.md) - [How to write documentation](how-to-write-documentation.md) - [What to include (and exclude)](what-to-include.md) - [Command-line arguments](command-line-arguments.md) diff --git a/src/doc/rustdoc/src/documentation-tests.md b/src/doc/rustdoc/src/documentation-tests.md index 70900a0bab..6be53fb4cf 100644 --- a/src/doc/rustdoc/src/documentation-tests.md +++ b/src/doc/rustdoc/src/documentation-tests.md @@ -261,6 +261,16 @@ conversion, so type inference fails because the type is not unique. Please note that you must write the `(())` in one sequence without intermediate whitespace so that `rustdoc` understands you want an implicit `Result`-returning function. +## Showing warnings in doctests + +You can show warnings in doctests by running `rustdoc --test --test-args=--show-output` +(or, if you're using cargo, `cargo test --doc -- --show-output`). +By default, this will still hide `unused` warnings, since so many examples use private functions; +you can add `#![warn(unused)]` to the top of your example if you want to see unused variables or dead code warnings. +You can also use [`#![doc(test(attr(warn(unused))))]`][test-attr] in the crate root to enable warnings globally. + +[test-attr]: ./the-doc-attribute.md#testattr + ## Documenting macros Here’s an example of documenting a macro: diff --git a/src/doc/rustdoc/src/how-to-read-rustdoc.md b/src/doc/rustdoc/src/how-to-read-rustdoc.md new file mode 100644 index 0000000000..99724d859e --- /dev/null +++ b/src/doc/rustdoc/src/how-to-read-rustdoc.md @@ -0,0 +1,107 @@ +# How to read rustdoc output + +Rustdoc's HTML output includes a friendly and useful navigation interface which +makes it easier for users to navigate and understand your code. +This chapter covers the major features of that interface, +and is a great starting point for documentation authors and users alike. + +## Structure + +The `rustdoc` output is divided into three sections. +Along the left side of each page is a quick navigation bar, +which shows contextual information about the current entry. +The rest of the page is taken up by the search interface at the top +and the documentation for the current item below that. + +## The Item Documentation + +The majority of the screen is taken up with the documentation text for the item +currently being viewed. +At the top is some at-a-glance info and controls: + +- the type and name of the item, + such as "Struct `std::time::Duration`", +- a button to copy the item's path to the clipboard, + which is a clipboard item +- a button to collapse or expand the top-level documentation for that item + (`[+]` or `[-]`), +- a link to the source code (`[src]`), + if [configured](the-doc-attribute.html#html_no_source), + and present (the source may not be available if + the documentation was created with `cargo doc --no-deps`), +- and the version in which the item became stable, + if it's a stable item in the standard library. + +Below this is the main documentation for the item, +including a definition or function signature if appropriate, +followed by a list of fields or variants for Rust types. +Finally, the page lists associated functions and trait implementations, +including automatic and blanket implementations that `rustdoc` knows about. + +### Navigation + +Subheadings, variants, fields, and many other things in this documentation +are anchors and can be clicked on and deep-linked to, +which is a great way to communicate exactly what you're talking about. +The typograpical character "§" appears next to lines with anchors on them +when hovered or given keyboard focus. + +## The Navigation Bar + +For example, when looking at documentation for the crate root, +it shows all the crates documented in the documentation bundle, +and quick links to the modules, structs, traits, functions, and macros available +from the current crate. +At the top, it displays a [configurable logo](the-doc-attribute.html#html_logo_url) +alongside the current crate's name and version, +or the current item whose documentation is being displayed. + +## The Theme Picker and Search Interface + +When viewing `rustdoc`'s output in a browser with JavaScript enabled, +a dynamic interface appears at the top of the page. +To the left is the theme picker, denoted with a paint-brush icon, +and the search interface, help screen, and options appear to the right of that. + +### The Theme Picker + +Clicking on the theme picker provides a list of themes - +by default `ayu`, `light`, and `dark` - +which are available for viewing. + +### The Search Interface + +Typing in the search bar instantly searches the available documentation for +the string entered with a fuzzy matching algorithm that is tolerant of minor +typos. + +By default, the search results give are "In Names", +meaning that the fuzzy match is made against the names of items. +Matching names are shown on the left, and the first few words of their +descriptions are given on the right. +By clicking an item, you will navigate to its particular documentation. + +There are two other sets of results, shown as tabs in the search results pane. +"In Parameters" shows matches for the string in the types of parameters to +functions, and "In Return Types" shows matches in the return types of functions. +Both are very useful when looking for a function whose name you can't quite +bring to mind when you know the type you have or want. + +When typing in the search bar, you can prefix your search term with a type +followed by a colon (such as `mod:`) to restrict the results to just that +kind of item. (The available items are listed in the help popup.) + +### Shortcuts + +Pressing `S` while focused elsewhere on the page will move focus to the +search bar, and pressing `?` shows the help screen, +which includes all these shortcuts and more. +Pressing `T` focuses the theme picker. + +When the search results are focused, +the left and right arrows move between tabs and the up and down arrows move +among the results. +Pressing the enter or return key opens the highlighted result. + +When looking at the documentation for an item, the plus and minus keys expand +and collapse all sections in the document. diff --git a/src/doc/rustdoc/src/the-doc-attribute.md b/src/doc/rustdoc/src/the-doc-attribute.md index b17ea7cd8f..a75b6d3893 100644 --- a/src/doc/rustdoc/src/the-doc-attribute.md +++ b/src/doc/rustdoc/src/the-doc-attribute.md @@ -153,7 +153,9 @@ example, if you want your doctests to fail if they produce any warnings, you cou These forms of the `#[doc]` attribute are used on individual items, to control how they are documented. -## `#[doc(no_inline)]`/`#[doc(inline)]` +### `inline` and `no_inline` + + These attributes are used on `use` statements, and control where the documentation shows up. For example, consider this Rust code: @@ -219,7 +221,56 @@ Now we'll have a `Re-exports` line, and `Bar` will not link to anywhere. One special case: In Rust 2018 and later, if you `pub use` one of your dependencies, `rustdoc` will not eagerly inline it as a module unless you add `#[doc(inline)]`. -## `#[doc(hidden)]` +### `hidden` + + Any item annotated with `#[doc(hidden)]` will not appear in the documentation, unless the `strip-hidden` pass is removed. + +### `alias` + +This attribute adds an alias in the search index. + +Let's take an example: + +```rust,no_run +#[doc(alias = "TheAlias")] +pub struct SomeType; +``` + +So now, if you enter "TheAlias" in the search, it'll display `SomeType`. +Of course, if you enter `SomeType` it'll return `SomeType` as expected! + +#### FFI example + +This doc attribute is especially useful when writing bindings for a C library. +For example, let's say we have a C function that looks like this: + +```c +int lib_name_do_something(Obj *obj); +``` + +It takes a pointer to an `Obj` type and returns an integer. In Rust, it might +be written like this: + +```ignore (using non-existing ffi types) +pub struct Obj { + inner: *mut ffi::Obj, +} + +impl Obj { + pub fn do_something(&mut self) -> i32 { + unsafe { ffi::lib_name_do_something(self.inner) } + } +} +``` + +The function has been turned into a method to make it more convenient to use. +However, if you want to look for the Rust equivalent of `lib_name_do_something`, +you have no way to do so. + +To get around this limitation, we just add `#[doc(alias = "lib_name_do_something")]` +on the `do_something` method and then it's all good! +Users can now look for `lib_name_do_something` in our crate directly and find +`Obj::do_something`. diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 9179599764..0210402154 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -134,9 +134,28 @@ Book][unstable-masked] and [its tracking issue][issue-masked]. ## Document primitives +This is for Rust compiler internal use only. + Since primitive types are defined in the compiler, there's no place to attach documentation -attributes. The `#[doc(primitive)]` attribute is used by the standard library to provide a way to generate -documentation for primitive types, and requires `#![feature(doc_primitive)]` to enable. +attributes. The `#[doc(primitive)]` attribute is used by the standard library to provide a way +to generate documentation for primitive types, and requires `#![feature(rustdoc_internals)]` to +enable. + +## Document keywords + +This is for Rust compiler internal use only. + +Rust keywords are documented in the standard library (look for `match` for example). + +To do so, the `#[doc(keyword = "...")]` attribute is used. Example: + +```rust +#![feature(rustdoc_internals)] + +/// Some documentation about the keyword. +#[doc(keyword = "keyword")] +mod empty_mod {} +``` ## Unstable command-line arguments @@ -238,22 +257,6 @@ all these files are linked from every page, changing where they are can be cumbe specially cache them. This flag will rename all these files in the output to include the suffix in the filename. For example, `light.css` would become `light-suf.css` with the above command. -### `--display-doctest-warnings`: display warnings when documenting or running documentation tests - -Using this flag looks like this: - -```bash -$ rustdoc src/lib.rs -Z unstable-options --display-doctest-warnings -$ rustdoc --test src/lib.rs -Z unstable-options --display-doctest-warnings -``` - -The intent behind this flag is to allow the user to see warnings that occur within their library or -their documentation tests, which are usually suppressed. However, [due to a -bug][issue-display-warnings], this flag doesn't 100% work as intended. See the linked issue for -details. - -[issue-display-warnings]: https://github.com/rust-lang/rust/issues/41574 - ### `--extern-html-root-url`: control how rustdoc links to non-local crates Using this flag looks like this: @@ -330,6 +333,18 @@ Using this flag looks like this: $ rustdoc src/lib.rs -Z unstable-options --show-coverage ``` +It generates something like this: + +```bash ++-------------------------------------+------------+------------+------------+------------+ +| File | Documented | Percentage | Examples | Percentage | ++-------------------------------------+------------+------------+------------+------------+ +| lib.rs | 4 | 100.0% | 1 | 25.0% | ++-------------------------------------+------------+------------+------------+------------+ +| Total | 4 | 100.0% | 1 | 25.0% | ++-------------------------------------+------------+------------+------------+------------+ +``` + If you want to determine how many items in your crate are documented, pass this flag to rustdoc. When it receives this flag, it will count the public items in your crate that have documentation, and print out the counts and a percentage instead of generating docs. @@ -349,12 +364,21 @@ Some methodology notes about what rustdoc counts in this metric: Public items that are not documented can be seen with the built-in `missing_docs` lint. Private items that are not documented can be seen with Clippy's `missing_docs_in_private_items` lint. -### `-w`/`--output-format`: output format +Calculating code examples follows these rules: -When using -[`--show-coverage`](https://doc.rust-lang.org/nightly/rustdoc/unstable-features.html#--show-coverage-get-statistics-about-code-documentation-coverage), -passing `--output-format json` will display the coverage information in JSON format. For example, -here is the JSON for a file with one documented item and one undocumented item: +1. These items aren't accounted by default: + * struct/union field + * enum variant + * constant + * static + * typedef +2. If one of the previously listed items has a code example, then it'll be counted. + +#### JSON output + +When using `--output-format json` with this option, it will display the coverage information in +JSON format. For example, here is the JSON for a file with one documented item and one +undocumented item: ```rust /// This item has documentation @@ -369,10 +393,16 @@ pub fn no_documentation() {} Note that the third item is the crate root, which in this case is undocumented. -When not using `--show-coverage`, `--output-format json` emits documentation in the experimental +### `-w`/`--output-format`: output format + +`--output-format json` emits documentation in the experimental [JSON format](https://github.com/rust-lang/rfcs/pull/2963). `--output-format html` has no effect, and is also accepted on stable toolchains. +It can also be used with `--show-coverage`. Take a look at its +[documentation](#--show-coverage-get-statistics-about-code-documentation-coverage) for more +information. + ### `--enable-per-target-ignores`: allow `ignore-foo` style filters for doctests Using this flag looks like this: @@ -423,35 +453,26 @@ $ rustdoc src/lib.rs -Z unstable-options --runtool valgrind Another use case would be to run a test inside an emulator, or through a Virtual Machine. -### `--show-coverage`: get statistics about code documentation coverage +### `--with-examples`: include examples of uses of items as documentation -This option allows you to get a nice overview over your code documentation coverage, including both -doc-comments and code examples in the doc-comments. Example: +This option, combined with `--scrape-examples-target-crate` and +`--scrape-examples-output-path`, is used to implement the functionality in [RFC +#3123](https://github.com/rust-lang/rfcs/pull/3123). Uses of an item (currently +functions / call-sites) are found in a crate and its reverse-dependencies, and +then the uses are included as documentation for that item. This feature is +intended to be used via `cargo doc --scrape-examples`, but the rustdoc-only +workflow looks like: ```bash -$ rustdoc src/lib.rs -Z unstable-options --show-coverage -+-------------------------------------+------------+------------+------------+------------+ -| File | Documented | Percentage | Examples | Percentage | -+-------------------------------------+------------+------------+------------+------------+ -| lib.rs | 4 | 100.0% | 1 | 25.0% | -+-------------------------------------+------------+------------+------------+------------+ -| Total | 4 | 100.0% | 1 | 25.0% | -+-------------------------------------+------------+------------+------------+------------+ -``` - -You can also use this option with the `--output-format` one: - -```bash -$ rustdoc src/lib.rs -Z unstable-options --show-coverage --output-format json -{"lib.rs":{"total":4,"with_docs":4,"total_examples":4,"with_examples":1}} +$ rustdoc examples/ex.rs -Z unstable-options \ + --extern foobar=target/deps/libfoobar.rmeta \ + --scrape-examples-target-crate foobar \ + --scrape-examples-output-path output.calls +$ rustdoc src/lib.rs -Z unstable-options --with-examples output.calls ``` -Calculating code examples follows these rules: - -1. These items aren't accounted by default: - * struct/union field - * enum variant - * constant - * static - * typedef -2. If one of the previously listed items has a code example, then it'll be counted. +First, the library must be checked to generate an `rmeta`. Then a +reverse-dependency like `examples/ex.rs` is given to rustdoc with the target +crate being documented (`foobar`) and a path to output the calls +(`output.calls`). Then, the generated calls file can be passed via +`--with-examples` to the subsequent documentation of `foobar`. diff --git a/src/doc/unstable-book/src/compiler-flags/location-detail.md b/src/doc/unstable-book/src/compiler-flags/location-detail.md new file mode 100644 index 0000000000..08d937cc28 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/location-detail.md @@ -0,0 +1,43 @@ +# `location-detail` + +The tracking issue for this feature is: [#70580](https://github.com/rust-lang/rust/issues/70580). + +------------------------ + +Option `-Z location-detail=val` controls what location details are tracked when +using `caller_location`. This allows users to control what location details +are printed as part of panic messages, by allowing them to exclude any combination +of filenames, line numbers, and column numbers. This option is intended to provide +users with a way to mitigate the size impact of `#[track_caller]`. + +This option supports a comma separated list of location details to be included. Valid options +within this list are: + +- `file` - the filename of the panic will be included in the panic output +- `line` - the source line of the panic will be included in the panic output +- `column` - the source column of the panic will be included in the panic output + +Any combination of these three options are supported. If this option is not specified, +all three are included by default. + +An example of a panic output when using `-Z location-detail=line`: +```text +panicked at 'Process blink had a fault', :323:0 +``` + +The code size savings from this option are two-fold. First, the `&'static str` values +for each path to a file containing a panic are removed from the binary. For projects +with deep directory structures and many files with panics, this can add up. This category +of savings can only be realized by excluding filenames from the panic output. Second, +savings can be realized by allowing multiple panics to be fused into a single panicking +branch. It is often the case that within a single file, multiple panics with the same +panic message exist -- e.g. two calls to `Option::unwrap()` in a single line, or +two calls to `Result::expect()` on adjacent lines. If column and line information +are included in the `Location` struct passed to the panic handler, these branches cannot +be fused, as the output is different depending on which panic occurs. However if line +and column information is identical for all panics, these branches can be fused, which +can lead to substantial code size savings, especially for small embedded binaries with +many panics. + +The savings from this option are amplified when combined with the use of `-Zbuild-std`, as +otherwise paths for panics within the standard library are still included in your binary. diff --git a/src/doc/unstable-book/src/compiler-flags/no-unique-section-names.md b/src/doc/unstable-book/src/compiler-flags/no-unique-section-names.md new file mode 100644 index 0000000000..5c1c7cda70 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/no-unique-section-names.md @@ -0,0 +1,9 @@ +# `no-unique-section-names` + +------------------------ + +This flag currently applies only to ELF-based targets using the LLVM codegen backend. It prevents the generation of unique ELF section names for each separate code and data item when `-Z function-sections` is also in use, which is the default for most targets. This option can reduce the size of object files, and depending on the linker, the final ELF binary as well. + +For example, a function `func` will by default generate a code section called `.text.func`. Normally this is fine because the linker will merge all those `.text.*` sections into a single one in the binary. However, starting with [LLVM 12](https://github.com/llvm/llvm-project/commit/ee5d1a04), the backend will also generate unique section names for exception handling, so you would see a section name of `.gcc_except_table.func` in the object file and potentially in the final ELF binary, which could add significant bloat to programs that contain many functions. + +This flag instructs LLVM to use the same `.text` and `.gcc_except_table` section name for each function, and it is analogous to Clang's `-fno-unique-section-names` option. diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md index 29a267053b..b3dbc9a995 100644 --- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md +++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md @@ -1,19 +1,24 @@ # `sanitizer` -The tracking issue for this feature is: [#39699](https://github.com/rust-lang/rust/issues/39699). +The tracking issues for this feature are: + +* [#39699](https://github.com/rust-lang/rust/issues/39699). +* [#89653](https://github.com/rust-lang/rust/issues/89653). ------------------------ This feature allows for use of one of following sanitizers: * [AddressSanitizer][clang-asan] a fast memory error detector. +* [ControlFlowIntegrity][clang-cfi] LLVM Control Flow Integrity (CFI) provides + forward-edge control flow protection. * [HWAddressSanitizer][clang-hwasan] a memory error detector similar to AddressSanitizer, but based on partial hardware assistance. * [LeakSanitizer][clang-lsan] a run-time memory leak detector. * [MemorySanitizer][clang-msan] a detector of uninitialized reads. * [ThreadSanitizer][clang-tsan] a fast data race detector. -To enable a sanitizer compile with `-Zsanitizer=address`, +To enable a sanitizer compile with `-Zsanitizer=address`,`-Zsanitizer=cfi`, `-Zsanitizer=hwaddress`, `-Zsanitizer=leak`, `-Zsanitizer=memory` or `-Zsanitizer=thread`. @@ -177,6 +182,176 @@ Shadow byte legend (one shadow byte represents 8 application bytes): ==39249==ABORTING ``` +# ControlFlowIntegrity + +The LLVM Control Flow Integrity (CFI) support in the Rust compiler initially +provides forward-edge control flow protection for Rust-compiled code only by +aggregating function pointers in groups identified by their number of arguments. + +Forward-edge control flow protection for C or C++ and Rust -compiled code "mixed +binaries" (i.e., for when C or C++ and Rust -compiled code share the same +virtual address space) will be provided in later work by defining and using +compatible type identifiers (see Type metadata in the design document in the +tracking issue [#89653](https://github.com/rust-lang/rust/issues/89653)). + +LLVM CFI can be enabled with -Zsanitizer=cfi and requires LTO (i.e., -Clto). + +## Example + +```text +#![feature(asm, naked_functions)] + +use std::mem; + +fn add_one(x: i32) -> i32 { + x + 1 +} + +#[naked] +pub extern "C" fn add_two(x: i32) { + // x + 2 preceeded by a landing pad/nop block + unsafe { + asm!( + " + nop + nop + nop + nop + nop + nop + nop + nop + nop + lea rax, [rdi+2] + ret + ", + options(noreturn) + ); + } +} + +fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 { + f(arg) + f(arg) +} + +fn main() { + let answer = do_twice(add_one, 5); + + println!("The answer is: {}", answer); + + println!("With CFI enabled, you should not see the next answer"); + let f: fn(i32) -> i32 = unsafe { + // Offsets 0-8 make it land in the landing pad/nop block, and offsets 1-8 are + // invalid branch/call destinations (i.e., within the body of the function). + mem::transmute::<*const u8, fn(i32) -> i32>((add_two as *const u8).offset(5)) + }; + let next_answer = do_twice(f, 5); + + println!("The next answer is: {}", next_answer); +} +``` +Fig. 1. Modified example from the [Advanced Functions and +Closures][rust-book-ch19-05] chapter of the [The Rust Programming +Language][rust-book] book. + +[//]: # (FIXME: Replace with output from cargo using nightly when #89652 is merged) + +```shell +$ rustc rust_cfi.rs -o rust_cfi +$ ./rust_cfi +The answer is: 12 +With CFI enabled, you should not see the next answer +The next answer is: 14 +$ +``` +Fig. 2. Build and execution of the modified example with LLVM CFI disabled. + +[//]: # (FIXME: Replace with output from cargo using nightly when #89652 is merged) + +```shell +$ rustc -Clto -Zsanitizer=cfi rust_cfi.rs -o rust_cfi +$ ./rust_cfi +The answer is: 12 +With CFI enabled, you should not see the next answer +Illegal instruction +$ +``` +Fig. 3. Build and execution of the modified example with LLVM CFI enabled. + +When LLVM CFI is enabled, if there are any attempts to change/hijack control +flow using an indirect branch/call to an invalid destination, the execution is +terminated (see Fig. 3). + +```rust +use std::mem; + +fn add_one(x: i32) -> i32 { + x + 1 +} + +fn add_two(x: i32, _y: i32) -> i32 { + x + 2 +} + +fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 { + f(arg) + f(arg) +} + +fn main() { + let answer = do_twice(add_one, 5); + + println!("The answer is: {}", answer); + + println!("With CFI enabled, you should not see the next answer"); + let f: fn(i32) -> i32 = + unsafe { mem::transmute::<*const u8, fn(i32) -> i32>(add_two as *const u8) }; + let next_answer = do_twice(f, 5); + + println!("The next answer is: {}", next_answer); +} +``` +Fig. 4. Another modified example from the [Advanced Functions and +Closures][rust-book-ch19-05] chapter of the [The Rust Programming +Language][rust-book] book. + +[//]: # (FIXME: Replace with output from cargo using nightly when #89652 is merged) + +```shell +$ rustc rust_cfi.rs -o rust_cfi +$ ./rust_cfi +The answer is: 12 +With CFI enabled, you should not see the next answer +The next answer is: 14 +$ +``` +Fig. 5. Build and execution of the modified example with LLVM CFI disabled. + +[//]: # (FIXME: Replace with output from cargo using nightly when #89652 is merged) + +```shell +$ rustc -Clto -Zsanitizer=cfi rust_cfi.rs -o rust_cfi +$ ./rust_cfi +The answer is: 12 +With CFI enabled, you should not see the next answer +Illegal instruction +$ +``` +Fig. 6. Build and execution of the modified example with LLVM CFI enabled. + +When LLVM CFI is enabled, if there are any attempts to change/hijack control +flow using an indirect branch/call to a function with different number of +arguments than intended/passed in the call/branch site, the execution is also +terminated (see Fig. 6). + +Forward-edge control flow protection not only by aggregating function pointers +in groups identified by their number of arguments, but also their argument +types, will also be provided in later work by defining and using compatible type +identifiers (see Type metadata in the design document in the tracking +issue [#89653](https://github.com/rust-lang/rust/issues/89653)). + +[rust-book-ch19-05]: https://doc.rust-lang.org/book/ch19-05-advanced-functions-and-closures.html +[rust-book]: https://doc.rust-lang.org/book/title-page.html + # HWAddressSanitizer HWAddressSanitizer is a newer variant of AddressSanitizer that consumes much @@ -404,12 +579,14 @@ Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PAT * [Sanitizers project page](https://github.com/google/sanitizers/wiki/) * [AddressSanitizer in Clang][clang-asan] +* [ControlFlowIntegrity in Clang][clang-cfi] * [HWAddressSanitizer in Clang][clang-hwasan] * [LeakSanitizer in Clang][clang-lsan] * [MemorySanitizer in Clang][clang-msan] * [ThreadSanitizer in Clang][clang-tsan] [clang-asan]: https://clang.llvm.org/docs/AddressSanitizer.html +[clang-cfi]: https://clang.llvm.org/docs/ControlFlowIntegrity.html [clang-hwasan]: https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html [clang-lsan]: https://clang.llvm.org/docs/LeakSanitizer.html [clang-msan]: https://clang.llvm.org/docs/MemorySanitizer.html diff --git a/src/doc/unstable-book/src/compiler-flags/strip.md b/src/doc/unstable-book/src/compiler-flags/strip.md deleted file mode 100644 index 52cb98113c..0000000000 --- a/src/doc/unstable-book/src/compiler-flags/strip.md +++ /dev/null @@ -1,17 +0,0 @@ -# `strip` - -The tracking issue for this feature is: [#72110](https://github.com/rust-lang/rust/issues/72110). - ------------------------- - -Option `-Z strip=val` controls stripping of debuginfo and similar auxiliary data from binaries -during linking. - -Supported values for this option are: - -- `none` - debuginfo and symbols (if they exist) are copied to the produced binary or separate files -depending on the target (e.g. `.pdb` files in case of MSVC). -- `debuginfo` - debuginfo sections and debuginfo symbols from the symbol table section -are stripped at link time and are not copied to the produced binary or separate files. -- `symbols` - same as `debuginfo`, but the rest of the symbol table section is stripped as well -if the linker supports it. diff --git a/src/doc/unstable-book/src/compiler-flags/temps-dir.md b/src/doc/unstable-book/src/compiler-flags/temps-dir.md new file mode 100644 index 0000000000..e25011f711 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/temps-dir.md @@ -0,0 +1,10 @@ +# `temps-dir` + +-------------------- + +The `-Ztemps-dir` compiler flag specifies the directory to write the +intermediate files in. If not set, the output directory is used. This option is +useful if you are running more than one instance of `rustc` (e.g. with different +`--crate-type` settings), and you need to make sure they are not overwriting +each other's intermediate files. No files are kept unless `-C save-temps=yes` is +also set. diff --git a/src/doc/unstable-book/src/language-features/inline-const-pat.md b/src/doc/unstable-book/src/language-features/inline-const-pat.md new file mode 100644 index 0000000000..5f0f7547a0 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/inline-const-pat.md @@ -0,0 +1,24 @@ +# `inline_const_pat` + +The tracking issue for this feature is: [#76001] + +See also [`inline_const`](inline-const.md) + +------ + +This feature allows you to use inline constant expressions in pattern position: + +```rust +#![feature(inline_const_pat)] + +const fn one() -> i32 { 1 } + +let some_int = 3; +match some_int { + const { 1 + 2 } => println!("Matched 1 + 2"), + const { one() } => println!("Matched const fn returning 1"), + _ => println!("Didn't match anything :("), +} +``` + +[#76001]: https://github.com/rust-lang/rust/issues/76001 diff --git a/src/doc/unstable-book/src/language-features/inline-const.md b/src/doc/unstable-book/src/language-features/inline-const.md index 00e1c79ca3..7be70eed6c 100644 --- a/src/doc/unstable-book/src/language-features/inline-const.md +++ b/src/doc/unstable-book/src/language-features/inline-const.md @@ -2,6 +2,8 @@ The tracking issue for this feature is: [#76001] +See also [`inline_const_pat`](inline-const-pat.md) + ------ This feature allows you to use inline constant expressions. For example, you can @@ -27,19 +29,4 @@ fn main() { } ``` -You can also use inline constant expressions in patterns: - -```rust -#![feature(inline_const)] - -const fn one() -> i32 { 1 } - -let some_int = 3; -match some_int { - const { 1 + 2 } => println!("Matched 1 + 2"), - const { one() } => println!("Matched const fn returning 1"), - _ => println!("Didn't match anything :("), -} -``` - [#76001]: https://github.com/rust-lang/rust/issues/76001 diff --git a/src/doc/unstable-book/src/language-features/type-changing-struct-update.md b/src/doc/unstable-book/src/language-features/type-changing-struct-update.md new file mode 100644 index 0000000000..9909cf35b5 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/type-changing-struct-update.md @@ -0,0 +1,33 @@ +# `type_changing_struct_update` + +The tracking issue for this feature is: [#86555] + +[#86555]: https://github.com/rust-lang/rust/issues/86555 + +------------------------ + +This implements [RFC2528]. When turned on, you can create instances of the same struct +that have different generic type or lifetime parameters. + +[RFC2528]: https://github.com/rust-lang/rfcs/blob/master/text/2528-type-changing-struct-update-syntax.md + +```rust +#![allow(unused_variables, dead_code)] +#![feature(type_changing_struct_update)] + +fn main () { + struct Foo { + field1: T, + field2: U, + } + + let base: Foo = Foo { + field1: String::from("hello"), + field2: 1234, + }; + let updated: Foo = Foo { + field1: 3.14, + ..base + }; +} +``` diff --git a/src/doc/unstable-book/src/library-features/asm.md b/src/doc/unstable-book/src/library-features/asm.md index 5a2cef2487..fac55b9788 100644 --- a/src/doc/unstable-book/src/library-features/asm.md +++ b/src/doc/unstable-book/src/library-features/asm.md @@ -66,7 +66,7 @@ assert_eq!(x, 5); This will write the value `5` into the `u64` variable `x`. You can see that the string literal we use to specify instructions is actually a template string. It is governed by the same rules as Rust [format strings][format-syntax]. -The arguments that are inserted into the template however look a bit different then you may +The arguments that are inserted into the template however look a bit different than you may be familiar with. First we need to specify if the variable is an input or an output of the inline assembly. In this case it is an output. We declared this by writing `out`. We also need to specify in what kind of register the assembly expects the variable. @@ -106,7 +106,7 @@ code. Second, we can see that inputs are declared by writing `in` instead of `out`. Third, one of our operands has a type we haven't seen yet, `const`. -This tells the compiler to expand this argument to value directly inside the assembly template. +This tells the compiler to expand this argument to a value directly inside the assembly template. This is only possible for constants and literals. Fourth, we can see that we can specify an argument number, or name as in any format string. @@ -257,7 +257,7 @@ unsafe { } println!( - "L1 Cache: {}", + "L0 Cache: {}", ((ebx >> 22) + 1) * (((ebx >> 12) & 0x3ff) + 1) * ((ebx & 0xfff) + 1) * (ecx + 1) ); ``` @@ -319,7 +319,7 @@ fn call_foo(arg: i32) -> i32 { Note that the `fn` or `static` item does not need to be public or `#[no_mangle]`: the compiler will automatically insert the appropriate mangled symbol name into the assembly code. -By default, `asm!` assumes that any register not specified as an output will have its contents preserved by the assembly code. The [`clobber_abi`](#abi-clobbers) argument to `asm!` tells the compiler to automatically insert the necessary clobber operands according to the given calling convention ABI: any register which is not fully preserved in that ABI will be treated as clobbered. +By default, `asm!` assumes that any register not specified as an output will have its contents preserved by the assembly code. The [`clobber_abi`](#abi-clobbers) argument to `asm!` tells the compiler to automatically insert the necessary clobber operands according to the given calling convention ABI: any register which is not fully preserved in that ABI will be treated as clobbered. Multiple `clobber_abi` arguments may be provided and all clobbers from all specified ABIs will be inserted. ## Register template modifiers @@ -453,10 +453,10 @@ reg_spec := / "" operand_expr := expr / "_" / expr "=>" expr / expr "=>" "_" reg_operand := dir_spec "(" reg_spec ")" operand_expr operand := reg_operand / "const" const_expr / "sym" path -clobber_abi := "clobber_abi(" ")" +clobber_abi := "clobber_abi(" *["," ] [","] ")" option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn" / "nostack" / "att_syntax" / "raw" options := "options(" option *["," option] [","] ")" -asm := "asm!(" format_string *("," format_string) *("," [ident "="] operand) ["," clobber_abi] *("," options) [","] ")" +asm := "asm!(" format_string *("," format_string) *("," [ident "="] operand) *("," clobber_abi) *("," options) [","] ")" ``` Inline assembly is currently supported on the following architectures: @@ -562,9 +562,12 @@ Here is the list of currently supported register classes: | AArch64 | `vreg` | `v[0-31]` | `w` | | AArch64 | `vreg_low16` | `v[0-15]` | `x` | | AArch64 | `preg` | `p[0-15]`, `ffr` | Only clobbers | -| ARM | `reg` | `r[0-12]`, `r14` | `r` | -| ARM (Thumb) | `reg_thumb` | `r[0-r7]` | `l` | +| ARM (ARM) | `reg` | `r[0-12]`, `r14` | `r` | +| ARM (Thumb2) | `reg` | `r[0-12]`, `r14` | `r` | +| ARM (Thumb1) | `reg` | `r[0-7]` | `r` | | ARM (ARM) | `reg_thumb` | `r[0-r12]`, `r14` | `l` | +| ARM (Thumb2) | `reg_thumb` | `r[0-7]` | `l` | +| ARM (Thumb1) | `reg_thumb` | `r[0-7]` | `l` | | ARM | `sreg` | `s[0-31]` | `t` | | ARM | `sreg_low16` | `s[0-15]` | `x` | | ARM | `dreg` | `d[0-31]` | `w` | @@ -799,6 +802,8 @@ As stated in the previous section, passing an input value smaller than the regis The `clobber_abi` keyword can be used to apply a default set of clobbers to an `asm` block. This will automatically insert the necessary clobber constraints as needed for calling a function with a particular calling convention: if the calling convention does not fully preserve the value of a register across a call then a `lateout("reg") _` is implicitly added to the operands list. +`clobber_abi` may be specified any number of times. It will insert a clobber for all unique registers in the union of all specified calling conventions. + Generic register class outputs are disallowed by the compiler when `clobber_abi` is used: all outputs must specify an explicit register. Explicit register outputs have precedence over the implicit clobbers inserted by `clobber_abi`: a clobber will only be inserted for a register if that register is not used as an output. The following ABIs can be used with `clobber_abi`: @@ -885,5 +890,7 @@ 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. +- On x86, inline assembly must not end with an instruction prefix (such as `LOCK`) that would apply to instructions generated by the compiler. + - The compiler is currently unable to detect this due to the way inline assembly is compiled, but may catch and reject this in the future. > **Note**: As a general rule, the flags covered by `preserves_flags` are those which are *not* preserved when performing a function call. diff --git a/src/doc/unstable-book/src/library-features/format-args-capture.md b/src/doc/unstable-book/src/library-features/format-args-capture.md deleted file mode 100644 index 64b1b3d81b..0000000000 --- a/src/doc/unstable-book/src/library-features/format-args-capture.md +++ /dev/null @@ -1,47 +0,0 @@ -# `format_args_capture` - -The tracking issue for this feature is: [#67984] - -[#67984]: https://github.com/rust-lang/rust/issues/67984 - ------------------------- - -Enables `format_args!` (and macros which use `format_args!` in their implementation, such -as `format!`, `print!` and `panic!`) to capture variables from the surrounding scope. -This avoids the need to pass named parameters when the binding in question -already exists in scope. - -```rust -#![feature(format_args_capture)] - -let (person, species, name) = ("Charlie Brown", "dog", "Snoopy"); - -// captures named argument `person` -print!("Hello {person}"); - -// captures named arguments `species` and `name` -format!("The {species}'s name is {name}."); -``` - -This also works for formatting parameters such as width and precision: - -```rust -#![feature(format_args_capture)] - -let precision = 2; -let s = format!("{:.precision$}", 1.324223); - -assert_eq!(&s, "1.32"); -``` - -A non-exhaustive list of macros which benefit from this functionality include: -- `format!` -- `print!` and `println!` -- `eprint!` and `eprintln!` -- `write!` and `writeln!` -- `panic!` -- `unreachable!` -- `unimplemented!` -- `todo!` -- `assert!` and similar -- macros in many thirdparty crates, such as `log` diff --git a/src/doc/unstable-book/src/library-features/global-asm.md b/src/doc/unstable-book/src/library-features/global-asm.md index 146d17b463..3f8e165841 100644 --- a/src/doc/unstable-book/src/library-features/global-asm.md +++ b/src/doc/unstable-book/src/library-features/global-asm.md @@ -75,7 +75,7 @@ are concatenated into one or assembled separately. constants defined in Rust to be used in assembly code: ```rust,no_run -#![feature(global_asm)] +#![feature(global_asm, asm_const)] # #[cfg(any(target_arch="x86", target_arch="x86_64"))] # mod x86 { const C: i32 = 1234; @@ -96,7 +96,7 @@ override this by adding `options(att_syntax)` at the end of the macro arguments list: ```rust,no_run -#![feature(global_asm)] +#![feature(global_asm, asm_const)] # #[cfg(any(target_arch="x86", target_arch="x86_64"))] # mod x86 { global_asm!("movl ${}, %ecx", const 5, options(att_syntax)); diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 945b2a8e9a..268905bcb5 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -10,7 +10,7 @@ path = "lib.rs" arrayvec = { version = "0.7", default-features = false } pulldown-cmark = { version = "0.8", default-features = false } minifier = "0.0.41" -rayon = { version = "0.3.0", package = "rustc-rayon" } +rayon = "1.3.1" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" smallvec = "1.6.1" diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index f9d1666977..2ccf17387d 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -76,17 +76,17 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { new_generics }); - let negative_polarity; + let polarity; let new_generics = match result { AutoTraitResult::PositiveImpl(new_generics) => { - negative_polarity = false; + polarity = ty::ImplPolarity::Positive; if discard_positive_impl { return None; } new_generics } AutoTraitResult::NegativeImpl => { - negative_polarity = true; + polarity = ty::ImplPolarity::Negative; // For negative impls, we use the generic params, but *not* the predicates, // from the original type. Otherwise, the displayed impl appears to be a @@ -115,15 +115,13 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { visibility: Inherited, def_id: ItemId::Auto { trait_: trait_def_id, for_: item_def_id }, kind: box ImplItem(Impl { - span: Span::dummy(), unsafety: hir::Unsafety::Normal, generics: new_generics, trait_: Some(trait_ref.clean(self.cx)), for_: ty.clean(self.cx), items: Vec::new(), - negative_polarity, - synthetic: true, - blanket_impl: None, + polarity, + kind: ImplKind::Auto, }), cfg: None, }) @@ -136,7 +134,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { let f = auto_trait::AutoTraitFinder::new(tcx); debug!("get_auto_trait_impls({:?})", ty); - let auto_traits: Vec<_> = self.cx.auto_traits.iter().cloned().collect(); + let auto_traits: Vec<_> = self.cx.auto_traits.iter().copied().collect(); let mut auto_traits: Vec = auto_traits .into_iter() .filter_map(|trait_def_id| { @@ -193,8 +191,8 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { // to its smaller and larger regions. Note that 'larger' regions correspond // to sub-regions in Rust code (e.g., in 'a: 'b, 'a is the larger region). for constraint in regions.constraints.keys() { - match constraint { - &Constraint::VarSubVar(r1, r2) => { + match *constraint { + Constraint::VarSubVar(r1, r2) => { { let deps1 = vid_map.entry(RegionTarget::RegionVid(r1)).or_default(); deps1.larger.insert(RegionTarget::RegionVid(r2)); @@ -203,15 +201,15 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { let deps2 = vid_map.entry(RegionTarget::RegionVid(r2)).or_default(); deps2.smaller.insert(RegionTarget::RegionVid(r1)); } - &Constraint::RegSubVar(region, vid) => { + Constraint::RegSubVar(region, vid) => { let deps = vid_map.entry(RegionTarget::RegionVid(vid)).or_default(); deps.smaller.insert(RegionTarget::Region(region)); } - &Constraint::VarSubReg(vid, region) => { + Constraint::VarSubReg(vid, region) => { let deps = vid_map.entry(RegionTarget::RegionVid(vid)).or_default(); deps.larger.insert(RegionTarget::Region(region)); } - &Constraint::RegSubReg(r1, r2) => { + Constraint::RegSubReg(r1, r2) => { // The constraint is already in the form that we want, so we're done with it // Desired order is 'larger, smaller', so flip then if region_name(r1) != region_name(r2) { @@ -513,8 +511,8 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { // as we want to combine them with any 'Output' qpaths // later - let is_fn = match &mut b { - &mut GenericBound::TraitBound(ref mut p, _) => { + let is_fn = match b { + GenericBound::TraitBound(ref mut p, _) => { // Insert regions into the for_generics hash map first, to ensure // that we don't end up with duplicate bounds (e.g., for<'b, 'b>) for_generics.extend(p.generic_params.clone()); @@ -576,7 +574,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { rhs, }); continue; // If something other than a Fn ends up - // with parenthesis, leave it alone + // with parentheses, leave it alone } } @@ -699,8 +697,8 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { } fn region_name(region: Region<'_>) -> Option { - match region { - &ty::ReEarlyBound(r) => Some(r.name), + match *region { + ty::ReEarlyBound(r) => Some(r.name), _ => None, } } @@ -717,8 +715,8 @@ impl<'a, 'tcx> TypeFolder<'tcx> for RegionReplacer<'a, 'tcx> { } fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - (match r { - &ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned(), + (match *r { + ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned(), _ => None, }) .unwrap_or_else(|| r.super_fold_with(self)) diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 843dda324d..f44589f606 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -106,7 +106,6 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { visibility: Inherited, def_id: ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id }, kind: box ImplItem(Impl { - span: Span::new(self.cx.tcx.def_span(impl_def_id)), unsafety: hir::Unsafety::Normal, generics: ( self.cx.tcx.generics_of(impl_def_id), @@ -122,11 +121,10 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { .tcx .associated_items(impl_def_id) .in_definition_order() - .collect::>() - .clean(self.cx), - negative_polarity: false, - synthetic: false, - blanket_impl: Some(box trait_ref.self_ty().clean(self.cx)), + .map(|x| x.clean(self.cx)) + .collect::>(), + polarity: ty::ImplPolarity::Positive, + kind: ImplKind::Blanket(box trait_ref.self_ty().clean(self.cx)), }), cfg: None, }); diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index e11b802a09..d4bf93bb40 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -15,7 +15,7 @@ use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Symbol}; use crate::clean::{ - self, utils, Attributes, AttributesExt, GetDefId, ItemId, NestedAttributesExt, Type, + self, utils, Attributes, AttributesExt, ImplKind, ItemId, NestedAttributesExt, Type, }; use crate::core::DocContext; use crate::formats::item_type::ItemType; @@ -229,6 +229,7 @@ fn build_external_function(cx: &mut DocContext<'_>, did: DefId) -> clean::Functi let asyncness = cx.tcx.asyncness(did); let predicates = cx.tcx.predicates_of(did); let (generics, decl) = clean::enter_impl_trait(cx, |cx| { + // NOTE: generics need to be cleaned before the decl! ((cx.tcx.generics_of(did), predicates).clean(cx), (did, sig).clean(cx)) }); clean::Function { @@ -244,7 +245,7 @@ fn build_enum(cx: &mut DocContext<'_>, did: DefId) -> clean::Enum { clean::Enum { generics: (cx.tcx.generics_of(did), predicates).clean(cx), variants_stripped: false, - variants: cx.tcx.adt_def(did).variants.clean(cx), + variants: cx.tcx.adt_def(did).variants.iter().map(|v| v.clean(cx)).collect(), } } @@ -255,7 +256,7 @@ fn build_struct(cx: &mut DocContext<'_>, did: DefId) -> clean::Struct { clean::Struct { struct_type: variant.ctor_kind, generics: (cx.tcx.generics_of(did), predicates).clean(cx), - fields: variant.fields.clean(cx), + fields: variant.fields.iter().map(|x| x.clean(cx)).collect(), fields_stripped: false, } } @@ -264,11 +265,9 @@ fn build_union(cx: &mut DocContext<'_>, did: DefId) -> clean::Union { let predicates = cx.tcx.explicit_predicates_of(did); let variant = cx.tcx.adt_def(did).non_enum_variant(); - clean::Union { - generics: (cx.tcx.generics_of(did), predicates).clean(cx), - fields: variant.fields.clean(cx), - fields_stripped: false, - } + let generics = (cx.tcx.generics_of(did), predicates).clean(cx); + let fields = variant.fields.iter().map(|x| x.clean(cx)).collect(); + clean::Union { generics, fields, fields_stripped: false } } fn build_type_alias(cx: &mut DocContext<'_>, did: DefId) -> clean::Typedef { @@ -325,7 +324,7 @@ fn merge_attrs( } } -/// Builds a specific implementation of a type. The `did` could be a type method or trait method. +/// Inline an `impl`, inherent or of a trait. The `did` must be for an `impl`. crate fn build_impl( cx: &mut DocContext<'_>, parent_module: impl Into>, @@ -337,6 +336,8 @@ crate fn build_impl( return; } + let _prof_timer = cx.tcx.sess.prof.generic_activity("build_extern_trait_impl"); + let tcx = cx.tcx; let associated_trait = tcx.impl_trait_ref(did); @@ -376,7 +377,7 @@ crate fn build_impl( // Only inline impl if the implementing type is // reachable in rustdoc generated documentation if !did.is_local() { - if let Some(did) = for_.def_id() { + if let Some(did) = for_.def_id(&cx.cache) { if !cx.cache.access_levels.is_public(did) { return; } @@ -435,7 +436,7 @@ crate fn build_impl( tcx.associated_items(did) .in_definition_order() .filter_map(|item| { - if associated_trait.is_some() || item.vis == ty::Visibility::Public { + if associated_trait.is_some() || item.vis.is_public() { Some(item.clean(cx)) } else { None @@ -446,7 +447,7 @@ crate fn build_impl( ), }; let polarity = tcx.impl_polarity(did); - let trait_ = associated_trait.clean(cx); + let trait_ = associated_trait.map(|t| t.clean(cx)); if trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() { super::build_deref_target_impls(cx, &trait_items, ret); } @@ -464,7 +465,7 @@ crate fn build_impl( } while let Some(ty) = stack.pop() { - if let Some(did) = ty.def_id() { + if let Some(did) = ty.def_id(&cx.cache) { if tcx.get_attrs(did).lists(sym::doc).has_word(sym::hidden) { return; } @@ -481,20 +482,22 @@ crate fn build_impl( let (merged_attrs, cfg) = merge_attrs(cx, parent_module.into(), load_attrs(cx, did), attrs); trace!("merged_attrs={:?}", merged_attrs); - trace!("build_impl: impl {:?} for {:?}", trait_.as_ref().map(|t| t.def_id()), for_.def_id()); + trace!( + "build_impl: impl {:?} for {:?}", + trait_.as_ref().map(|t| t.def_id()), + for_.def_id(&cx.cache) + ); 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, trait_, for_, items: trait_items, - negative_polarity: polarity.clean(cx), - synthetic: false, - blanket_impl: None, + polarity, + kind: ImplKind::Normal, }), box merged_attrs, cx, @@ -513,7 +516,7 @@ fn build_module( // two namespaces, so the target may be listed twice. Make sure we only // visit each node at most once. for &item in cx.tcx.item_children(did).iter() { - if item.vis == ty::Visibility::Public { + if item.vis.is_public() { let res = item.res.expect_non_local(); if let Some(def_id) = res.mod_def_id() { if did == def_id || !visited.insert(def_id) { @@ -590,14 +593,9 @@ fn build_macro( match CStore::from_tcx(cx.tcx).load_macro_untracked(def_id, cx.sess()) { LoadedMacro::MacroDef(item_def, _) => { if let ast::ItemKind::MacroDef(ref def) = item_def.kind { + let vis = cx.tcx.visibility(import_def_id.unwrap_or(def_id)).clean(cx); clean::MacroItem(clean::Macro { - source: utils::display_macro_source( - cx, - name, - def, - def_id, - cx.tcx.visibility(import_def_id.unwrap_or(def_id)), - ), + source: utils::display_macro_source(cx, name, def, def_id, vis), }) } else { unreachable!() diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 9d102d6878..4e1dabd05b 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -16,7 +16,6 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; -use rustc_index::vec::{Idx, IndexVec}; use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData}; use rustc_middle::middle::resolve_lifetime as rl; use rustc_middle::ty::fold::TypeFolder; @@ -34,59 +33,22 @@ use std::assert_matches::assert_matches; use std::collections::hash_map::Entry; use std::default::Default; use std::hash::Hash; -use std::rc::Rc; use std::{mem, vec}; use crate::core::{self, DocContext, ImplTraitParam}; -use crate::doctree; use crate::formats::item_type::ItemType; +use crate::visit_ast::Module as DocModule; use utils::*; -crate use utils::{get_auto_trait_and_blanket_impls, krate, register_res}; - -crate use self::types::FnRetTy::*; -crate use self::types::ItemKind::*; -crate use self::types::SelfTy::*; -crate use self::types::Type::*; -crate use self::types::Visibility::{Inherited, Public}; crate use self::types::*; +crate use self::utils::{get_auto_trait_and_blanket_impls, krate, register_res}; crate trait Clean { fn clean(&self, cx: &mut DocContext<'_>) -> T; } -impl, U> Clean> for [T] { - fn clean(&self, cx: &mut DocContext<'_>) -> Vec { - self.iter().map(|x| x.clean(cx)).collect() - } -} - -impl, U, V: Idx> Clean> for IndexVec { - fn clean(&self, cx: &mut DocContext<'_>) -> IndexVec { - self.iter().map(|x| x.clean(cx)).collect() - } -} - -impl, U> Clean for &T { - fn clean(&self, cx: &mut DocContext<'_>) -> U { - (**self).clean(cx) - } -} - -impl, U> Clean for Rc { - fn clean(&self, cx: &mut DocContext<'_>) -> U { - (**self).clean(cx) - } -} - -impl, U> Clean> for Option { - fn clean(&self, cx: &mut DocContext<'_>) -> Option { - self.as_ref().map(|v| v.clean(cx)) - } -} - -impl Clean for doctree::Module<'_> { +impl Clean for DocModule<'_> { fn clean(&self, cx: &mut DocContext<'_>) -> Item { let mut items: Vec = vec![]; items.extend(self.foreigns.iter().map(|x| x.clean(cx))); @@ -141,7 +103,10 @@ impl Clean for hir::GenericBound<'_> { }; GenericBound::TraitBound( - PolyTrait { trait_: (trait_ref, &*bindings).clean(cx), generic_params: vec![] }, + PolyTrait { + trait_: (trait_ref, &bindings[..]).clean(cx), + generic_params: vec![], + }, hir::TraitBoundModifier::None, ) } @@ -216,17 +181,15 @@ impl<'tcx> Clean for ty::PolyTraitRef<'tcx> { impl Clean for hir::Lifetime { fn clean(&self, cx: &mut DocContext<'_>) -> Lifetime { let def = cx.tcx.named_region(self.hir_id); - match def { - Some( - rl::Region::EarlyBound(_, node_id, _) - | rl::Region::LateBound(_, _, node_id, _) - | rl::Region::Free(_, node_id), - ) => { - if let Some(lt) = cx.lt_substs.get(&node_id).cloned() { - return lt; - } + if let Some( + rl::Region::EarlyBound(_, node_id, _) + | rl::Region::LateBound(_, _, node_id, _) + | rl::Region::Free(_, node_id), + ) = def + { + if let Some(lt) = cx.substs.get(&node_id).and_then(|p| p.as_lt()).cloned() { + return lt; } - _ => {} } Lifetime(self.name.ident().name) } @@ -289,14 +252,14 @@ impl Clean for hir::WherePredicate<'_> { .collect(); WherePredicate::BoundPredicate { ty: wbp.bounded_ty.clean(cx), - bounds: wbp.bounds.clean(cx), + bounds: wbp.bounds.iter().map(|x| x.clean(cx)).collect(), bound_params, } } hir::WherePredicate::RegionPredicate(ref wrp) => WherePredicate::RegionPredicate { lifetime: wrp.lifetime.clean(cx), - bounds: wrp.bounds.clean(cx), + bounds: wrp.bounds.iter().map(|x| x.clean(cx)).collect(), }, hir::WherePredicate::EqPredicate(ref wrp) => { @@ -385,7 +348,7 @@ impl<'tcx> Clean for ty::ProjectionTy<'tcx> { let self_type = self.self_ty().clean(cx); Type::QPath { name: cx.tcx.associated_item(self.item_def_id).ident.name, - self_def_id: self_type.def_id(), + self_def_id: self_type.def_id(&cx.cache), self_type: box self_type, trait_, } @@ -421,7 +384,7 @@ impl Clean for ty::GenericParamDef { GenericParamDefKind::Type { did: self.def_id, bounds: vec![], // These are filled in from the where-clauses. - default, + default: default.map(Box::new), synthetic, }, ) @@ -430,9 +393,9 @@ impl Clean for ty::GenericParamDef { self.name, GenericParamDefKind::Const { did: self.def_id, - ty: cx.tcx.type_of(self.def_id).clean(cx), + ty: Box::new(cx.tcx.type_of(self.def_id).clean(cx)), default: match has_default { - true => Some(cx.tcx.const_param_default(self.def_id).to_string()), + true => Some(Box::new(cx.tcx.const_param_default(self.def_id).to_string())), false => None, }, }, @@ -461,8 +424,8 @@ impl Clean for hir::GenericParam<'_> { self.name.ident().name, GenericParamDefKind::Type { did: cx.tcx.hir().local_def_id(self.hir_id).to_def_id(), - bounds: self.bounds.clean(cx), - default: default.clean(cx), + bounds: self.bounds.iter().map(|x| x.clean(cx)).collect(), + default: default.map(|t| t.clean(cx)).map(Box::new), synthetic, }, ), @@ -470,10 +433,10 @@ impl Clean for hir::GenericParam<'_> { self.name.ident().name, GenericParamDefKind::Const { did: cx.tcx.hir().local_def_id(self.hir_id).to_def_id(), - ty: ty.clean(cx), + ty: Box::new(ty.clean(cx)), default: default.map(|ct| { let def_id = cx.tcx.hir().local_def_id(ct.hir_id); - ty::Const::from_anon_const(cx.tcx, def_id).to_string() + Box::new(ty::Const::from_anon_const(cx.tcx, def_id).to_string()) }), }, ), @@ -490,9 +453,7 @@ impl Clean for hir::Generics<'_> { // scans them first. fn is_impl_trait(param: &hir::GenericParam<'_>) -> bool { match param.kind { - hir::GenericParamKind::Type { synthetic, .. } => { - synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) - } + hir::GenericParamKind::Type { synthetic, .. } => synthetic, _ => false, } } @@ -532,8 +493,10 @@ impl Clean for hir::Generics<'_> { } params.extend(impl_trait_params); - let mut generics = - Generics { params, where_predicates: self.where_clause.predicates.clean(cx) }; + let mut generics = Generics { + params, + where_predicates: self.where_clause.predicates.iter().map(|x| x.clean(cx)).collect(), + }; // Some duplicates are generated for ?Sized bounds between type params and where // predicates. The point in here is to move the bounds definitions from type params @@ -589,7 +552,7 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, ty::GenericPredicates<'tcx assert_eq!(param.index, 0); return None; } - if synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) { + if synthetic { impl_trait.insert(param.index.into(), vec![]); return None; } @@ -793,8 +756,13 @@ fn clean_fn_or_proc_macro( impl<'a> Clean for (&'a hir::FnSig<'a>, &'a hir::Generics<'a>, hir::BodyId) { fn clean(&self, cx: &mut DocContext<'_>) -> Function { - let (generics, decl) = - enter_impl_trait(cx, |cx| (self.1.clean(cx), (&*self.0.decl, self.2).clean(cx))); + let (generics, decl) = enter_impl_trait(cx, |cx| { + // NOTE: generics must be cleaned before args + let generics = self.1.clean(cx); + let args = (self.0.decl.inputs, self.2).clean(cx); + let decl = clean_fn_decl_with_args(cx, self.0.decl, args); + (generics, decl) + }); Function { decl, generics, header: self.0.header } } } @@ -828,7 +796,7 @@ impl<'a> Clean for (&'a [hir::Ty<'a>], hir::BodyId) { .iter() .enumerate() .map(|(i, ty)| Argument { - name: name_from_pat(&body.params[i].pat), + name: name_from_pat(body.params[i].pat), type_: ty.clean(cx), }) .collect(), @@ -836,17 +804,12 @@ impl<'a> Clean for (&'a [hir::Ty<'a>], hir::BodyId) { } } -impl<'a, A: Copy> Clean for (&'a hir::FnDecl<'a>, A) -where - (&'a [hir::Ty<'a>], A): Clean, -{ - fn clean(&self, cx: &mut DocContext<'_>) -> FnDecl { - FnDecl { - inputs: (self.0.inputs, self.1).clean(cx), - output: self.0.output.clean(cx), - c_variadic: self.0.c_variadic, - } - } +fn clean_fn_decl_with_args( + cx: &mut DocContext<'_>, + decl: &hir::FnDecl<'_>, + args: Arguments, +) -> FnDecl { + FnDecl { inputs: args, output: decl.output.clean(cx), c_variadic: decl.c_variadic } } impl<'tcx> Clean for (DefId, ty::PolyFnSig<'tcx>) { @@ -902,7 +865,7 @@ impl Clean for hir::PolyTraitRef<'_> { fn clean(&self, cx: &mut DocContext<'_>) -> PolyTrait { PolyTrait { trait_: self.trait_ref.clean(cx), - generic_params: self.bound_generic_params.clean(cx), + generic_params: self.bound_generic_params.iter().map(|x| x.clean(cx)).collect(), } } } @@ -924,9 +887,13 @@ impl Clean for hir::TraitItem<'_> { } MethodItem(m, None) } - hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(ref names)) => { + hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(names)) => { let (generics, decl) = enter_impl_trait(cx, |cx| { - (self.generics.clean(cx), (&*sig.decl, &names[..]).clean(cx)) + // NOTE: generics must be cleaned before args + let generics = self.generics.clean(cx); + let args = (sig.decl.inputs, names).clean(cx); + let decl = clean_fn_decl_with_args(cx, sig.decl, args); + (generics, decl) }); let mut t = Function { header: sig.header, decl, generics }; if t.header.constness == hir::Constness::Const @@ -936,8 +903,10 @@ impl Clean for hir::TraitItem<'_> { } TyMethodItem(t) } - hir::TraitItemKind::Type(ref bounds, ref default) => { - AssocTypeItem(bounds.clean(cx), default.clean(cx)) + hir::TraitItemKind::Type(bounds, ref default) => { + let bounds = bounds.iter().map(|x| x.clean(cx)).collect(); + let default = default.map(|t| t.clean(cx)); + AssocTypeItem(bounds, default) } }; let what_rustc_thinks = @@ -1129,7 +1098,7 @@ impl Clean for ty::AssocItem { None }; - AssocTypeItem(bounds, ty.clean(cx)) + AssocTypeItem(bounds, ty.map(|t| t.clean(cx))) } else { // FIXME: when could this happen? Associated items in inherent impls? let type_ = tcx.type_of(self.def_id).clean(cx); @@ -1150,7 +1119,6 @@ impl Clean for ty::AssocItem { } fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type { - use rustc_hir::GenericParamCount; let hir::Ty { hir_id: _, span, ref kind } = *hir_ty; let qpath = match kind { hir::TyKind::Path(qpath) => qpath, @@ -1160,7 +1128,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type { match qpath { hir::QPath::Resolved(None, ref path) => { if let Res::Def(DefKind::TyParam, did) = path.res { - if let Some(new_ty) = cx.ty_substs.get(&did).cloned() { + if let Some(new_ty) = cx.substs.get(&did).and_then(|p| p.as_ty()).cloned() { return new_ty; } if let Some(bounds) = cx.impl_trait_bounds.remove(&did.into()) { @@ -1168,99 +1136,14 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type { } } - let mut alias = None; - if let Res::Def(DefKind::TyAlias, def_id) = path.res { - // Substitute private type aliases - if let Some(def_id) = def_id.as_local() { - let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id); - if !cx.cache.access_levels.is_exported(def_id.to_def_id()) { - alias = Some(&cx.tcx.hir().expect_item(hir_id).kind); - } - } - }; - - if let Some(&hir::ItemKind::TyAlias(ref ty, ref generics)) = alias { - let provided_params = &path.segments.last().expect("segments were empty"); - let mut ty_substs = FxHashMap::default(); - let mut lt_substs = FxHashMap::default(); - let mut ct_substs = FxHashMap::default(); - let generic_args = provided_params.args(); - { - let mut indices: GenericParamCount = Default::default(); - for param in generics.params.iter() { - match param.kind { - hir::GenericParamKind::Lifetime { .. } => { - let mut j = 0; - let lifetime = generic_args.args.iter().find_map(|arg| match arg { - hir::GenericArg::Lifetime(lt) => { - if indices.lifetimes == j { - return Some(lt); - } - j += 1; - None - } - _ => None, - }); - if let Some(lt) = lifetime.cloned() { - let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id); - let cleaned = if !lt.is_elided() { - lt.clean(cx) - } else { - self::types::Lifetime::elided() - }; - lt_substs.insert(lt_def_id.to_def_id(), cleaned); - } - indices.lifetimes += 1; - } - hir::GenericParamKind::Type { ref default, .. } => { - let ty_param_def_id = cx.tcx.hir().local_def_id(param.hir_id); - let mut j = 0; - let type_ = generic_args.args.iter().find_map(|arg| match arg { - hir::GenericArg::Type(ty) => { - if indices.types == j { - return Some(ty); - } - j += 1; - None - } - _ => None, - }); - if let Some(ty) = type_ { - ty_substs.insert(ty_param_def_id.to_def_id(), ty.clean(cx)); - } else if let Some(default) = *default { - ty_substs - .insert(ty_param_def_id.to_def_id(), default.clean(cx)); - } - indices.types += 1; - } - hir::GenericParamKind::Const { .. } => { - let const_param_def_id = cx.tcx.hir().local_def_id(param.hir_id); - let mut j = 0; - let const_ = generic_args.args.iter().find_map(|arg| match arg { - hir::GenericArg::Const(ct) => { - if indices.consts == j { - return Some(ct); - } - j += 1; - None - } - _ => None, - }); - if let Some(ct) = const_ { - ct_substs.insert(const_param_def_id.to_def_id(), ct.clean(cx)); - } - // FIXME(const_generics_defaults) - indices.consts += 1; - } - } - } - } - return cx.enter_alias(ty_substs, lt_substs, ct_substs, |cx| ty.clean(cx)); + if let Some(expanded) = maybe_expand_private_type_alias(cx, path) { + expanded + } else { + let path = path.clean(cx); + resolve_type(cx, path) } - let path = path.clean(cx); - resolve_type(cx, path) } - hir::QPath::Resolved(Some(ref qself), ref p) => { + hir::QPath::Resolved(Some(ref qself), p) => { // Try to normalize `::T` to a type let ty = hir_ty_to_ty(cx.tcx, hir_ty); if let Some(normalized_value) = normalize(cx, ty) { @@ -1271,7 +1154,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type { let trait_def = cx.tcx.associated_item(p.res.def_id()).container.id(); let trait_ = self::Path { res: Res::Def(DefKind::Trait, trait_def), - segments: trait_segments.clean(cx), + segments: trait_segments.iter().map(|x| x.clean(cx)).collect(), }; register_res(cx, trait_.res); Type::QPath { @@ -1281,7 +1164,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type { trait_, } } - hir::QPath::TypeRelative(ref qself, ref segment) => { + hir::QPath::TypeRelative(ref qself, segment) => { let ty = hir_ty_to_ty(cx.tcx, hir_ty); let res = match ty.kind() { ty::Projection(proj) => Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id), @@ -1302,6 +1185,94 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type { } } +fn maybe_expand_private_type_alias(cx: &mut DocContext<'_>, path: &hir::Path<'_>) -> Option { + let Res::Def(DefKind::TyAlias, def_id) = path.res else { return None }; + // Substitute private type aliases + let Some(def_id) = def_id.as_local() else { return None }; + let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id); + let alias = if !cx.cache.access_levels.is_exported(def_id.to_def_id()) { + &cx.tcx.hir().expect_item(hir_id).kind + } else { + return None; + }; + let hir::ItemKind::TyAlias(ty, generics) = alias else { return None }; + + let provided_params = &path.segments.last().expect("segments were empty"); + let mut substs = FxHashMap::default(); + let generic_args = provided_params.args(); + + let mut indices: hir::GenericParamCount = Default::default(); + for param in generics.params.iter() { + match param.kind { + hir::GenericParamKind::Lifetime { .. } => { + let mut j = 0; + let lifetime = generic_args.args.iter().find_map(|arg| match arg { + hir::GenericArg::Lifetime(lt) => { + if indices.lifetimes == j { + return Some(lt); + } + j += 1; + None + } + _ => None, + }); + if let Some(lt) = lifetime.cloned() { + let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id); + let cleaned = if !lt.is_elided() { + lt.clean(cx) + } else { + self::types::Lifetime::elided() + }; + substs.insert(lt_def_id.to_def_id(), SubstParam::Lifetime(cleaned)); + } + indices.lifetimes += 1; + } + hir::GenericParamKind::Type { ref default, .. } => { + let ty_param_def_id = cx.tcx.hir().local_def_id(param.hir_id); + let mut j = 0; + let type_ = generic_args.args.iter().find_map(|arg| match arg { + hir::GenericArg::Type(ty) => { + if indices.types == j { + return Some(ty); + } + j += 1; + None + } + _ => None, + }); + if let Some(ty) = type_ { + substs.insert(ty_param_def_id.to_def_id(), SubstParam::Type(ty.clean(cx))); + } else if let Some(default) = *default { + substs.insert(ty_param_def_id.to_def_id(), SubstParam::Type(default.clean(cx))); + } + indices.types += 1; + } + hir::GenericParamKind::Const { .. } => { + let const_param_def_id = cx.tcx.hir().local_def_id(param.hir_id); + let mut j = 0; + let const_ = generic_args.args.iter().find_map(|arg| match arg { + hir::GenericArg::Const(ct) => { + if indices.consts == j { + return Some(ct); + } + j += 1; + None + } + _ => None, + }); + if let Some(ct) = const_ { + substs + .insert(const_param_def_id.to_def_id(), SubstParam::Constant(ct.clean(cx))); + } + // FIXME(const_generics_defaults) + indices.consts += 1; + } + } + } + + Some(cx.enter_alias(substs, |cx| ty.clean(cx))) +} + impl Clean for hir::Ty<'_> { fn clean(&self, cx: &mut DocContext<'_>) -> Type { use rustc_hir::*; @@ -1337,17 +1308,17 @@ impl Clean for hir::Ty<'_> { let length = print_const(cx, ct.eval(cx.tcx, param_env)); Array(box ty.clean(cx), length) } - TyKind::Tup(ref tys) => Tuple(tys.clean(cx)), + TyKind::Tup(tys) => Tuple(tys.iter().map(|x| x.clean(cx)).collect()), TyKind::OpaqueDef(item_id, _) => { let item = cx.tcx.hir().item(item_id); if let hir::ItemKind::OpaqueTy(ref ty) = item.kind { - ImplTrait(ty.bounds.clean(cx)) + ImplTrait(ty.bounds.iter().map(|x| x.clean(cx)).collect()) } else { unreachable!() } } - TyKind::Path(_) => clean_qpath(&self, cx), - TyKind::TraitObject(ref bounds, ref lifetime, _) => { + TyKind::Path(_) => clean_qpath(self, cx), + TyKind::TraitObject(bounds, ref lifetime, _) => { let bounds = bounds.iter().map(|bound| bound.clean(cx)).collect(); let lifetime = if !lifetime.is_elided() { Some(lifetime.clean(cx)) } else { None }; DynTrait(bounds, lifetime) @@ -1434,14 +1405,14 @@ impl<'tcx> Clean for Ty<'tcx> { }; inline::record_extern_fqn(cx, did, kind); let path = external_path(cx, did, false, vec![], substs); - ResolvedPath { path, did } + Type::Path { path } } ty::Foreign(did) => { inline::record_extern_fqn(cx, did, ItemType::ForeignType); let path = external_path(cx, did, false, vec![], InternalSubsts::empty()); - ResolvedPath { path, did } + Type::Path { path } } - ty::Dynamic(ref obj, ref reg) => { + ty::Dynamic(obj, ref reg) => { // HACK: pick the first `did` as the `did` of the trait object. Someone // might want to implement "native" support for marker-trait-only // trait objects. @@ -1481,9 +1452,7 @@ impl<'tcx> Clean for Ty<'tcx> { DynTrait(bounds, lifetime) } - ty::Tuple(ref t) => { - Tuple(t.iter().map(|t| t.expect_ty()).collect::>().clean(cx)) - } + ty::Tuple(t) => Tuple(t.iter().map(|t| t.expect_ty().clean(cx)).collect()), ty::Projection(ref data) => data.clean(cx), @@ -1590,45 +1559,37 @@ impl<'tcx> Clean for ty::Const<'tcx> { impl Clean for hir::FieldDef<'_> { fn clean(&self, cx: &mut DocContext<'_>) -> Item { - let what_rustc_thinks = Item::from_hir_id_and_parts( - self.hir_id, - Some(self.ident.name), - StructFieldItem(self.ty.clean(cx)), - cx, - ); - // Don't show `pub` for fields on enum variants; they are always public - Item { visibility: self.vis.clean(cx), ..what_rustc_thinks } + let def_id = cx.tcx.hir().local_def_id(self.hir_id).to_def_id(); + clean_field(def_id, self.ident.name, self.ty.clean(cx), cx) } } impl Clean for ty::FieldDef { fn clean(&self, cx: &mut DocContext<'_>) -> Item { - let what_rustc_thinks = Item::from_def_id_and_parts( - self.did, - Some(self.ident.name), - StructFieldItem(cx.tcx.type_of(self.did).clean(cx)), - cx, - ); - // Don't show `pub` for fields on enum variants; they are always public - Item { visibility: self.vis.clean(cx), ..what_rustc_thinks } + clean_field(self.did, self.ident.name, cx.tcx.type_of(self.did).clean(cx), cx) } } -impl Clean for hir::Visibility<'_> { - fn clean(&self, cx: &mut DocContext<'_>) -> Visibility { - match self.node { - hir::VisibilityKind::Public => Visibility::Public, - hir::VisibilityKind::Inherited => Visibility::Inherited, - hir::VisibilityKind::Crate(_) => { - let krate = DefId::local(CRATE_DEF_INDEX); - Visibility::Restricted(krate) - } - hir::VisibilityKind::Restricted { ref path, .. } => { - let path = path.clean(cx); - let did = register_res(cx, path.res); - Visibility::Restricted(did) - } - } +fn clean_field(def_id: DefId, name: Symbol, ty: Type, cx: &mut DocContext<'_>) -> Item { + let what_rustc_thinks = + Item::from_def_id_and_parts(def_id, Some(name), StructFieldItem(ty), cx); + if is_field_vis_inherited(cx.tcx, def_id) { + // Variant fields inherit their enum's visibility. + Item { visibility: Visibility::Inherited, ..what_rustc_thinks } + } else { + what_rustc_thinks + } +} + +fn is_field_vis_inherited(tcx: TyCtxt<'_>, def_id: DefId) -> bool { + let parent = tcx + .parent(def_id) + .expect("is_field_vis_inherited can only be called on struct or variant fields"); + match tcx.def_kind(parent) { + DefKind::Struct | DefKind::Union => false, + DefKind::Variant => true, + // FIXME: what about DefKind::Ctor? + parent_kind => panic!("unexpected parent kind: {:?}", parent_kind), } } @@ -1639,8 +1600,7 @@ impl Clean for ty::Visibility { // NOTE: this is not quite right: `ty` uses `Invisible` to mean 'private', // while rustdoc really does mean inherited. That means that for enum variants, such as // `pub enum E { V }`, `V` will be marked as `Public` by `ty`, but as `Inherited` by rustdoc. - // This is the main reason `impl Clean for hir::Visibility` still exists; various parts of clean - // override `tcx.visibility` explicitly to make sure this distinction is captured. + // Various parts of clean override `tcx.visibility` explicitly to make sure this distinction is captured. ty::Visibility::Invisible => Visibility::Inherited, ty::Visibility::Restricted(module) => Visibility::Restricted(module), } @@ -1667,39 +1627,18 @@ impl Clean for ty::VariantDef { fn clean(&self, cx: &mut DocContext<'_>) -> Item { let kind = match self.ctor_kind { CtorKind::Const => Variant::CLike, - CtorKind::Fn => Variant::Tuple( - self.fields - .iter() - .map(|field| { - let name = Some(field.ident.name); - let kind = StructFieldItem(cx.tcx.type_of(field.did).clean(cx)); - let what_rustc_thinks = - Item::from_def_id_and_parts(field.did, name, kind, cx); - // don't show `pub` for fields, which are always public - Item { visibility: Visibility::Inherited, ..what_rustc_thinks } - }) - .collect(), - ), + CtorKind::Fn => { + Variant::Tuple(self.fields.iter().map(|field| field.clean(cx)).collect()) + } CtorKind::Fictive => Variant::Struct(VariantStruct { struct_type: CtorKind::Fictive, fields_stripped: false, - fields: self - .fields - .iter() - .map(|field| { - let name = Some(field.ident.name); - let kind = StructFieldItem(cx.tcx.type_of(field.did).clean(cx)); - let what_rustc_thinks = - Item::from_def_id_and_parts(field.did, name, kind, cx); - // don't show `pub` for fields, which are always public - Item { visibility: Visibility::Inherited, ..what_rustc_thinks } - }) - .collect(), + fields: self.fields.iter().map(|field| field.clean(cx)).collect(), }), }; let what_rustc_thinks = Item::from_def_id_and_parts(self.def_id, Some(self.ident.name), VariantItem(kind), cx); - // don't show `pub` for fields, which are always public + // don't show `pub` for variants, which always inherit visibility Item { visibility: Inherited, ..what_rustc_thinks } } } @@ -1716,7 +1655,7 @@ impl Clean for hir::VariantData<'_> { impl Clean for hir::Path<'_> { fn clean(&self, cx: &mut DocContext<'_>) -> Path { - Path { res: self.res, segments: self.segments.clean(cx) } + Path { res: self.res, segments: self.segments.iter().map(|x| x.clean(cx)).collect() } } } @@ -1726,24 +1665,24 @@ impl Clean for hir::GenericArgs<'_> { let output = self.bindings[0].ty().clean(cx); let output = if output != Type::Tuple(Vec::new()) { Some(Box::new(output)) } else { None }; - GenericArgs::Parenthesized { inputs: self.inputs().clean(cx), output } + let inputs = self.inputs().iter().map(|x| x.clean(cx)).collect(); + GenericArgs::Parenthesized { inputs, output } } else { - GenericArgs::AngleBracketed { - args: self - .args - .iter() - .map(|arg| match arg { - hir::GenericArg::Lifetime(lt) if !lt.is_elided() => { - GenericArg::Lifetime(lt.clean(cx)) - } - hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()), - hir::GenericArg::Type(ty) => GenericArg::Type(ty.clean(cx)), - hir::GenericArg::Const(ct) => GenericArg::Const(Box::new(ct.clean(cx))), - hir::GenericArg::Infer(_inf) => GenericArg::Infer, - }) - .collect(), - bindings: self.bindings.clean(cx), - } + let args = self + .args + .iter() + .map(|arg| match arg { + hir::GenericArg::Lifetime(lt) if !lt.is_elided() => { + GenericArg::Lifetime(lt.clean(cx)) + } + hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()), + hir::GenericArg::Type(ty) => GenericArg::Type(ty.clean(cx)), + hir::GenericArg::Const(ct) => GenericArg::Const(Box::new(ct.clean(cx))), + hir::GenericArg::Infer(_inf) => GenericArg::Infer, + }) + .collect(); + let bindings = self.bindings.iter().map(|x| x.clean(cx)).collect(); + GenericArgs::AngleBracketed { args, bindings } } } } @@ -1757,7 +1696,11 @@ impl Clean for hir::PathSegment<'_> { impl Clean for hir::BareFnTy<'_> { fn clean(&self, cx: &mut DocContext<'_>) -> BareFunctionDecl { let (generic_params, decl) = enter_impl_trait(cx, |cx| { - (self.generic_params.clean(cx), (&*self.decl, self.param_names).clean(cx)) + // NOTE: generics must be cleaned before args + let generic_params = self.generic_params.iter().map(|x| x.clean(cx)).collect(); + let args = (self.decl.inputs, self.param_names).clean(cx); + let decl = clean_fn_decl_with_args(cx, self.decl, args); + (generic_params, decl) }); BareFunctionDecl { unsafety: self.unsafety, abi: self.abi, decl, generic_params } } @@ -1780,7 +1723,7 @@ impl Clean> for (&hir::Item<'_>, Option) { kind: ConstantKind::Local { body: body_id, def_id }, }), ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy { - bounds: ty.bounds.clean(cx), + bounds: ty.bounds.iter().map(|x| x.clean(cx)).collect(), generics: ty.generics.clean(cx), }), ItemKind::TyAlias(hir_ty, ref generics) => { @@ -1802,17 +1745,17 @@ impl Clean> for (&hir::Item<'_>, Option) { }), ItemKind::TraitAlias(ref generics, bounds) => TraitAliasItem(TraitAlias { generics: generics.clean(cx), - bounds: bounds.clean(cx), + bounds: bounds.iter().map(|x| x.clean(cx)).collect(), }), ItemKind::Union(ref variant_data, ref generics) => UnionItem(Union { generics: generics.clean(cx), - fields: variant_data.fields().clean(cx), + fields: variant_data.fields().iter().map(|x| x.clean(cx)).collect(), fields_stripped: false, }), ItemKind::Struct(ref variant_data, ref generics) => StructItem(Struct { struct_type: CtorKind::from_hir(variant_data), generics: generics.clean(cx), - fields: variant_data.fields().clean(cx), + fields: variant_data.fields().iter().map(|x| x.clean(cx)).collect(), fields_stripped: false, }), ItemKind::Impl(ref impl_) => return clean_impl(impl_, item.hir_id(), cx), @@ -1820,10 +1763,13 @@ impl Clean> for (&hir::Item<'_>, Option) { ItemKind::Fn(ref sig, ref generics, body_id) => { clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx) } - ItemKind::Macro(ref macro_def) => MacroItem(Macro { - source: display_macro_source(cx, name, ¯o_def, def_id, &item.vis), - }), - ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref item_ids) => { + ItemKind::Macro(ref macro_def) => { + let ty_vis = cx.tcx.visibility(def_id).clean(cx); + MacroItem(Macro { + source: display_macro_source(cx, name, macro_def, def_id, ty_vis), + }) + } + ItemKind::Trait(is_auto, unsafety, ref generics, bounds, item_ids) => { let items = item_ids .iter() .map(|ti| cx.tcx.hir().trait_item(ti.id).clean(cx)) @@ -1832,7 +1778,7 @@ impl Clean> for (&hir::Item<'_>, Option) { unsafety, items, generics: generics.clean(cx), - bounds: bounds.clean(cx), + bounds: bounds.iter().map(|x| x.clean(cx)).collect(), is_auto: is_auto.clean(cx), }) } @@ -1860,22 +1806,10 @@ impl Clean for hir::Variant<'_> { } } -impl Clean for ty::ImplPolarity { - /// Returns whether the impl has negative polarity. - fn clean(&self, _: &mut DocContext<'_>) -> bool { - match self { - &ty::ImplPolarity::Positive | - // FIXME: do we want to do something else here? - &ty::ImplPolarity::Reservation => false, - &ty::ImplPolarity::Negative => true, - } - } -} - fn clean_impl(impl_: &hir::Impl<'_>, hir_id: hir::HirId, cx: &mut DocContext<'_>) -> Vec { let tcx = cx.tcx; let mut ret = Vec::new(); - let trait_ = impl_.of_trait.clean(cx); + let trait_ = impl_.of_trait.as_ref().map(|t| t.clean(cx)); let items = impl_.items.iter().map(|ii| tcx.hir().impl_item(ii.id).clean(cx)).collect::>(); let def_id = tcx.hir().local_def_id(hir_id); @@ -1887,21 +1821,19 @@ fn clean_impl(impl_: &hir::Impl<'_>, hir_id: hir::HirId, cx: &mut DocContext<'_> } let for_ = impl_.self_ty.clean(cx); - let type_alias = for_.def_id().and_then(|did| match tcx.def_kind(did) { + let type_alias = for_.def_id(&cx.cache).and_then(|did| match tcx.def_kind(did) { DefKind::TyAlias => Some(tcx.type_of(did).clean(cx)), _ => None, }); 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), trait_, for_, items, - negative_polarity: tcx.impl_polarity(def_id).clean(cx), - synthetic: false, - blanket_impl: None, + polarity: tcx.impl_polarity(def_id), + kind: ImplKind::Normal, }); Item::from_hir_id_and_parts(hir_id, None, kind, cx) }; @@ -1923,7 +1855,8 @@ fn clean_extern_crate( // this is the ID of the crate itself let crate_def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX }; let attrs = cx.tcx.hir().attrs(krate.hir_id()); - let please_inline = krate.vis.node.is_pub() + let ty_vis = cx.tcx.visibility(krate.def_id); + let please_inline = ty_vis.is_public() && attrs.iter().any(|a| { a.has_name(sym::doc) && match a.meta_item_list() { @@ -1955,7 +1888,7 @@ fn clean_extern_crate( name: Some(name), attrs: box attrs.clean(cx), def_id: crate_def_id.into(), - visibility: krate.vis.clean(cx), + visibility: ty_vis.clean(cx), kind: box ExternCrateItem { src: orig_name }, cfg: attrs.cfg(cx.tcx, &cx.cache.hidden_cfg), }] @@ -1975,9 +1908,24 @@ fn clean_use_statement( return Vec::new(); } + let visibility = cx.tcx.visibility(import.def_id); let attrs = cx.tcx.hir().attrs(import.hir_id()); let inline_attr = attrs.lists(sym::doc).get_word_attr(sym::inline); - let pub_underscore = import.vis.node.is_pub() && name == kw::Underscore; + let pub_underscore = visibility.is_public() && name == kw::Underscore; + let current_mod = cx.tcx.parent_module_from_def_id(import.def_id); + + // The parent of the module in which this import resides. This + // is the same as `current_mod` if that's already the top + // level module. + let parent_mod = cx.tcx.parent_module_from_def_id(current_mod); + + // This checks if the import can be seen from a higher level module. + // In other words, it checks if the visibility is the equivalent of + // `pub(super)` or higher. If the current module is the top level + // module, there isn't really a parent module, which makes the results + // meaningless. In this case, we make sure the answer is `false`. + let is_visible_from_parent_mod = visibility.is_accessible_from(parent_mod.to_def_id(), cx.tcx) + && !current_mod.is_top_level_module(); if pub_underscore { if let Some(ref inline) = inline_attr { @@ -1996,8 +1944,8 @@ fn clean_use_statement( // forcefully don't inline if this is not public or if the // #[doc(no_inline)] attribute is present. // Don't inline doc(hidden) imports so they can be stripped at a later stage. - let mut denied = !(import.vis.node.is_pub() - || (cx.render_options.document_private && import.vis.node.is_pub_restricted())) + let mut denied = !(visibility.is_public() + || (cx.render_options.document_private && is_visible_from_parent_mod)) || pub_underscore || attrs.iter().any(|a| { a.has_name(sym::doc) @@ -2062,12 +2010,17 @@ fn clean_use_statement( impl Clean for (&hir::ForeignItem<'_>, Option) { fn clean(&self, cx: &mut DocContext<'_>) -> Item { let (item, renamed) = self; - cx.with_param_env(item.def_id.to_def_id(), |cx| { + let def_id = item.def_id.to_def_id(); + cx.with_param_env(def_id, |cx| { let kind = match item.kind { - hir::ForeignItemKind::Fn(ref decl, ref names, ref generics) => { + hir::ForeignItemKind::Fn(decl, names, ref generics) => { let abi = cx.tcx.hir().get_foreign_abi(item.hir_id()); let (generics, decl) = enter_impl_trait(cx, |cx| { - (generics.clean(cx), (&**decl, &names[..]).clean(cx)) + // NOTE: generics must be cleaned before args + let generics = generics.clean(cx); + let args = (decl.inputs, names).clean(cx); + let decl = clean_fn_decl_with_args(cx, decl, args); + (generics, decl) }); ForeignFunctionItem(Function { decl, @@ -2112,7 +2065,7 @@ impl Clean for hir::TypeBindingKind<'_> { hir::TypeBindingKind::Equality { ref ty } => { TypeBindingKind::Equality { ty: ty.clean(cx) } } - hir::TypeBindingKind::Constraint { ref bounds } => { + hir::TypeBindingKind::Constraint { bounds } => { TypeBindingKind::Constraint { bounds: bounds.iter().map(|b| b.clean(cx)).collect() } } } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 153435367a..37acf68def 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -34,7 +34,6 @@ use rustc_target::spec::abi::Abi; use crate::clean::cfg::Cfg; use crate::clean::external_path; 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; @@ -43,10 +42,14 @@ use crate::formats::item_type::ItemType; use crate::html::render::cache::ExternalLocation; use crate::html::render::Context; -use self::FnRetTy::*; -use self::ItemKind::*; -use self::SelfTy::*; -use self::Type::*; +crate use self::FnRetTy::*; +crate use self::ItemKind::*; +crate use self::SelfTy::*; +crate use self::Type::{ + Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive, QPath, + RawPointer, Slice, Tuple, +}; +crate use self::Visibility::{Inherited, Public}; crate type ItemIdSet = FxHashSet; @@ -113,18 +116,30 @@ impl From for ItemId { } } +/// The crate currently being documented. #[derive(Clone, Debug)] crate struct Crate { - crate name: Symbol, - crate src: FileName, crate module: Item, - crate externs: Vec, crate primitives: ThinVec<(DefId, PrimitiveType)>, /// Only here so that they can be filtered through the rustdoc passes. crate external_traits: Rc>>, crate collapsed: bool, } +// `Crate` is frequently moved by-value. Make sure it doesn't unintentionally get bigger. +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] +rustc_data_structures::static_assert_size!(Crate, 80); + +impl Crate { + crate fn name(&self, tcx: TyCtxt<'_>) -> Symbol { + ExternalCrate::LOCAL.name(tcx) + } + + crate fn src(&self, tcx: TyCtxt<'_>) -> FileName { + ExternalCrate::LOCAL.src(tcx) + } +} + /// This struct is used to wrap additional information added by rustdoc on a `trait` item. #[derive(Clone, Debug)] crate struct TraitWithExtraInfo { @@ -138,6 +153,8 @@ crate struct ExternalCrate { } impl ExternalCrate { + const LOCAL: Self = Self { crate_num: LOCAL_CRATE }; + #[inline] crate fn def_id(&self) -> DefId { DefId { krate: self.crate_num, index: CRATE_DEF_INDEX } @@ -204,7 +221,7 @@ impl ExternalCrate { .filter_map(|a| a.value_str()) .map(to_remote) .next() - .or(extern_url.map(to_remote)) // NOTE: only matters if `extern_url_takes_precedence` is false + .or_else(|| extern_url.map(to_remote)) // NOTE: only matters if `extern_url_takes_precedence` is false .unwrap_or(Unknown) // Well, at least we tried. } @@ -238,8 +255,8 @@ impl ExternalCrate { 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() => + hir::ItemKind::Use(path, hir::UseKind::Single) + if tcx.visibility(id.def_id).is_public() => { as_keyword(path.res.expect_non_local()) .map(|(_, prim)| (id.def_id.to_def_id(), prim)) @@ -304,8 +321,8 @@ impl ExternalCrate { 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() => + hir::ItemKind::Use(path, hir::UseKind::Single) + if tcx.visibility(id.def_id).is_public() => { as_primitive(path.res.expect_non_local()).map(|(_, prim)| { // Pretend the primitive is local. @@ -376,12 +393,19 @@ impl Item { ItemKind::StrippedItem(k) => k, _ => &*self.kind, }; - if let ItemKind::ModuleItem(Module { span, .. }) | ItemKind::ImplItem(Impl { span, .. }) = - kind - { - *span - } else { - self.def_id.as_def_id().map(|did| rustc_span(did, tcx)).unwrap_or_else(|| Span::dummy()) + match kind { + ItemKind::ModuleItem(Module { span, .. }) => *span, + ItemKind::ImplItem(Impl { kind: ImplKind::Auto, .. }) => Span::dummy(), + ItemKind::ImplItem(Impl { kind: ImplKind::Blanket(_), .. }) => { + if let ItemId::Blanket { impl_id, .. } = self.def_id { + rustc_span(impl_id, tcx) + } else { + panic!("blanket impl item has non-blanket ID") + } + } + _ => { + self.def_id.as_def_id().map(|did| rustc_span(did, tcx)).unwrap_or_else(Span::dummy) + } } } @@ -562,7 +586,7 @@ impl Item { } crate fn stability_class(&self, tcx: TyCtxt<'_>) -> Option { - self.stability(tcx).as_ref().and_then(|ref s| { + self.stability(tcx).as_ref().and_then(|s| { let mut classes = Vec::with_capacity(2); if s.level.is_unstable() { @@ -823,9 +847,9 @@ impl AttributesExt for [ast::Attribute] { // #[doc(cfg(...))] if let Some(cfg_mi) = item .meta_item() - .and_then(|item| rustc_expand::config::parse_cfg(&item, sess)) + .and_then(|item| rustc_expand::config::parse_cfg(item, sess)) { - match Cfg::parse(&cfg_mi) { + match Cfg::parse(cfg_mi) { Ok(new_cfg) => cfg &= new_cfg, Err(e) => sess.span_err(e.span, e.msg), } @@ -884,7 +908,6 @@ impl + IntoIterator FromIterator<&'a DocFragment> for String { T: IntoIterator, { iter.into_iter().fold(String::new(), |mut acc, frag| { - add_doc_fragment(&mut acc, &frag); + add_doc_fragment(&mut acc, frag); acc }) } @@ -1005,7 +1032,6 @@ impl Attributes { additional_attrs: Option<(&[ast::Attribute], DefId)>, ) -> Attributes { let mut doc_strings: Vec = vec![]; - let mut doc_line = 0; fn update_need_backline(doc_strings: &mut Vec) { if let Some(prev) = doc_strings.last_mut() { @@ -1023,10 +1049,7 @@ impl Attributes { DocFragmentKind::RawDoc }; - let line = doc_line; - doc_line += value.as_str().lines().count(); let frag = DocFragment { - line, span: attr.span, doc: value, kind, @@ -1064,12 +1087,12 @@ impl Attributes { let ori = iter.next()?; let mut out = String::new(); - add_doc_fragment(&mut out, &ori); - while let Some(new_frag) = iter.next() { + add_doc_fragment(&mut out, ori); + for new_frag in iter { if new_frag.kind != ori.kind || new_frag.parent_module != ori.parent_module { break; } - add_doc_fragment(&mut out, &new_frag); + add_doc_fragment(&mut out, new_frag); } if out.is_empty() { None } else { Some(out) } } @@ -1082,7 +1105,7 @@ impl Attributes { for new_frag in self.doc_strings.iter() { let out = ret.entry(new_frag.parent_module).or_default(); - add_doc_fragment(out, &new_frag); + add_doc_fragment(out, new_frag); } ret } @@ -1093,7 +1116,7 @@ impl Attributes { if self.doc_strings.is_empty() { None } else { Some(self.doc_strings.iter().collect()) } } - crate fn get_doc_aliases(&self) -> Box<[String]> { + crate fn get_doc_aliases(&self) -> Box<[Symbol]> { let mut aliases = FxHashSet::default(); for attr in self.other_attrs.lists(sym::doc).filter(|a| a.has_name(sym::alias)) { @@ -1101,16 +1124,16 @@ impl Attributes { for l in values { match l.literal().unwrap().kind { ast::LitKind::Str(s, _) => { - aliases.insert(s.as_str().to_string()); + aliases.insert(s); } _ => unreachable!(), } } } else { - aliases.insert(attr.value_str().map(|s| s.to_string()).unwrap()); + aliases.insert(attr.value_str().unwrap()); } } - aliases.into_iter().collect::>().into() + aliases.into_iter().collect::>().into() } } @@ -1216,20 +1239,9 @@ impl WherePredicate { #[derive(Clone, PartialEq, Eq, Debug, Hash)] crate enum GenericParamDefKind { - Lifetime { - outlives: Vec, - }, - Type { - did: DefId, - bounds: Vec, - default: Option, - synthetic: Option, - }, - Const { - did: DefId, - ty: Type, - default: Option, - }, + Lifetime { outlives: Vec }, + Type { did: DefId, bounds: Vec, default: Option>, synthetic: bool }, + Const { did: DefId, ty: Box, default: Option> }, } impl GenericParamDefKind { @@ -1242,8 +1254,8 @@ impl GenericParamDefKind { // any embedded types, but `get_type` seems to be the wrong name for that. crate fn get_type(&self) -> Option { match self { - GenericParamDefKind::Type { default, .. } => default.clone(), - GenericParamDefKind::Const { ty, .. } => Some(ty.clone()), + GenericParamDefKind::Type { default, .. } => default.as_deref().cloned(), + GenericParamDefKind::Const { ty, .. } => Some((&**ty).clone()), GenericParamDefKind::Lifetime { .. } => None, } } @@ -1255,11 +1267,15 @@ crate struct GenericParamDef { crate kind: GenericParamDefKind, } +// `GenericParamDef` is used in many places. Make sure it doesn't unintentionally get bigger. +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] +rustc_data_structures::static_assert_size!(GenericParamDef, 56); + impl GenericParamDef { crate fn is_synthetic_type_param(&self) -> bool { match self.kind { GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false, - GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(), + GenericParamDefKind::Type { synthetic, .. } => synthetic, } } @@ -1369,17 +1385,10 @@ crate enum FnRetTy { DefaultReturn, } -impl GetDefId for FnRetTy { - fn def_id(&self) -> Option { - match *self { - Return(ref ty) => ty.def_id(), - DefaultReturn => None, - } - } - - fn def_id_full(&self, cache: &Cache) -> Option { - match *self { - Return(ref ty) => ty.def_id_full(cache), +impl FnRetTy { + crate fn as_return(&self) -> Option<&Type> { + match self { + Return(ret) => Some(ret), DefaultReturn => None, } } @@ -1412,8 +1421,9 @@ crate struct PolyTrait { crate enum Type { /// A named type, which could be a trait. /// - /// This is mostly Rustdoc's version of [`hir::Path`]. It has to be different because Rustdoc's [`PathSegment`] can contain cleaned generics. - ResolvedPath { path: Path, did: DefId }, + /// This is mostly Rustdoc's version of [`hir::Path`]. + /// It has to be different because Rustdoc's [`PathSegment`] can contain cleaned generics. + Path { path: Path }, /// A `dyn Trait` object: `dyn for<'a> Trait<'a> + Send + 'static` DynTrait(Vec, Option), /// A type parameter. @@ -1453,33 +1463,9 @@ crate enum Type { ImplTrait(Vec), } -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`]. - /// Use [`Self::def_id_full`] if you want to include primitives. - /// - /// [`clean`]: crate::clean - /// [`clean::Type`]: crate::clean::Type - // FIXME: get rid of this function and always use `def_id_full` - fn def_id(&self) -> Option; - - /// Use this method to get the [DefId] of a [clean] AST node, including [PrimitiveType]s. - /// - /// See [`Self::def_id`] for more. - /// - /// [clean]: crate::clean - fn def_id_full(&self, cache: &Cache) -> Option; -} - -impl GetDefId for Option { - fn def_id(&self) -> Option { - self.as_ref().and_then(|d| d.def_id()) - } - - fn def_id_full(&self, cache: &Cache) -> Option { - self.as_ref().and_then(|d| d.def_id_full(cache)) - } -} +// `Type` is used a lot. Make sure it doesn't unintentionally get bigger. +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] +rustc_data_structures::static_assert_size!(Type, 72); impl Type { crate fn primitive_type(&self) -> Option { @@ -1503,7 +1489,7 @@ impl Type { /// Checks if this is a `T::Name` path for an associated type. crate fn is_assoc_ty(&self) -> bool { match self { - ResolvedPath { path, .. } => path.is_assoc_ty(), + Type::Path { path, .. } => path.is_assoc_ty(), _ => false, } } @@ -1517,7 +1503,7 @@ impl Type { crate fn generics(&self) -> Option> { match self { - ResolvedPath { path, .. } => path.generics(), + Type::Path { path, .. } => path.generics(), _ => None, } } @@ -1540,7 +1526,7 @@ impl Type { fn inner_def_id(&self, cache: Option<&Cache>) -> Option { let t: PrimitiveType = match *self { - ResolvedPath { did, .. } => return Some(did), + Type::Path { ref path } => return Some(path.def_id()), DynTrait(ref bounds, _) => return Some(bounds[0].trait_.def_id()), Primitive(p) => return cache.and_then(|c| c.primitive_locations.get(&p).cloned()), BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference, @@ -1559,17 +1545,27 @@ impl Type { QPath { ref self_type, .. } => return self_type.inner_def_id(cache), Generic(_) | Infer | ImplTrait(_) => return None, }; - cache.and_then(|c| Primitive(t).def_id_full(c)) + cache.and_then(|c| Primitive(t).def_id(c)) } -} -impl GetDefId for Type { - fn def_id(&self) -> Option { - self.inner_def_id(None) + /// Use this method to get the [DefId] of a [clean] AST node, including [PrimitiveType]s. + /// + /// See [`Self::def_id_no_primitives`] for more. + /// + /// [clean]: crate::clean + crate fn def_id(&self, cache: &Cache) -> Option { + self.inner_def_id(Some(cache)) } - fn def_id_full(&self, cache: &Cache) -> Option { - self.inner_def_id(Some(cache)) + /// Use this method to get the [`DefId`] of a [`clean`] AST node. + /// This will return [`None`] when called on a primitive [`clean::Type`]. + /// Use [`Self::def_id`] if you want to include primitives. + /// + /// [`clean`]: crate::clean + /// [`clean::Type`]: crate::clean::Type + // FIXME: get rid of this function and always use `def_id` + crate fn def_id_no_primitives(&self) -> Option { + self.inner_def_id(None) } } @@ -2087,16 +2083,6 @@ crate struct Typedef { crate item_type: Option, } -impl GetDefId for Typedef { - fn def_id(&self) -> Option { - self.type_.def_id() - } - - fn def_id_full(&self, cache: &Cache) -> Option { - self.type_.def_id_full(cache) - } -} - #[derive(Clone, Debug)] crate struct OpaqueTy { crate bounds: Vec, @@ -2177,15 +2163,13 @@ impl Constant { #[derive(Clone, Debug)] crate struct Impl { - crate span: Span, crate unsafety: hir::Unsafety, crate generics: Generics, crate trait_: Option, crate for_: Type, crate items: Vec, - crate negative_polarity: bool, - crate synthetic: bool, - crate blanket_impl: Option>, + crate polarity: ty::ImplPolarity, + crate kind: ImplKind, } impl Impl { @@ -2198,6 +2182,30 @@ impl Impl { } } +#[derive(Clone, Debug)] +crate enum ImplKind { + Normal, + Auto, + Blanket(Box), +} + +impl ImplKind { + crate fn is_auto(&self) -> bool { + matches!(self, ImplKind::Auto) + } + + crate fn is_blanket(&self) -> bool { + matches!(self, ImplKind::Blanket(_)) + } + + crate fn as_blanket_ty(&self) -> Option<&Type> { + match self { + ImplKind::Blanket(ty) => Some(ty), + _ => None, + } + } +} + #[derive(Clone, Debug)] crate struct Import { crate kind: ImportKind, @@ -2262,3 +2270,32 @@ impl TypeBinding { } } } + +/// The type, lifetime, or constant that a private type alias's parameter should be +/// replaced with when expanding a use of that type alias. +/// +/// For example: +/// +/// ``` +/// type PrivAlias = Vec; +/// +/// pub fn public_fn() -> PrivAlias { vec![] } +/// ``` +/// +/// `public_fn`'s docs will show it as returning `Vec`, since `PrivAlias` is private. +/// [`SubstParam`] is used to record that `T` should be mapped to `i32`. +crate enum SubstParam { + Type(Type), + Lifetime(Lifetime), + Constant(Constant), +} + +impl SubstParam { + crate fn as_ty(&self) -> Option<&Type> { + if let Self::Type(ty) = self { Some(ty) } else { None } + } + + crate fn as_lt(&self) -> Option<&Lifetime> { + if let Self::Lifetime(lt) = self { Some(lt) } else { None } + } +} diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index de43daff6f..38f53d7e0b 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -2,11 +2,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, Path, PathSegment, Primitive, PrimitiveType, ResolvedPath, Type, - TypeBinding, Visibility, + ItemKind, Lifetime, Path, PathSegment, Primitive, PrimitiveType, Type, TypeBinding, Visibility, }; use crate::core::DocContext; use crate::formats::item_type::ItemType; +use crate::visit_lib::LibEmbargoVisitor; use rustc_ast as ast; use rustc_ast::tokenstream::TokenTree; @@ -24,17 +24,12 @@ use std::mem; mod tests; crate fn krate(cx: &mut DocContext<'_>) -> Crate { - use crate::visit_lib::LibEmbargoVisitor; - let module = crate::visit_ast::RustdocVisitor::new(cx).visit(); - let mut externs = Vec::new(); - for &cnum in cx.tcx.crates(()).iter() { - externs.push(ExternalCrate { crate_num: cnum }); + for &cnum in cx.tcx.crates(()) { // Analyze doc-reachability for extern items LibEmbargoVisitor::new(cx).visit_lib(cnum); } - externs.sort_unstable_by_key(|e| e.crate_num); // Clean the crate, translating the entire librustc_ast AST to one that is // understood by rustdoc. @@ -57,8 +52,6 @@ crate fn krate(cx: &mut DocContext<'_>) -> Crate { } let local_crate = ExternalCrate { crate_num: LOCAL_CRATE }; - let src = local_crate.src(cx.tcx); - let name = local_crate.name(cx.tcx); let primitives = local_crate.primitives(cx.tcx); let keywords = local_crate.keywords(cx.tcx); { @@ -79,15 +72,7 @@ crate fn krate(cx: &mut DocContext<'_>) -> Crate { })); } - Crate { - name, - src, - module, - externs, - primitives, - external_traits: cx.external_traits.clone(), - collapsed: false, - } + Crate { module, primitives, external_traits: cx.external_traits.clone(), collapsed: false } } fn external_generic_args( @@ -171,8 +156,8 @@ crate fn strip_path_generics(path: Path) -> Path { crate fn qpath_to_string(p: &hir::QPath<'_>) -> String { let segments = match *p { - hir::QPath::Resolved(_, ref path) => &path.segments, - hir::QPath::TypeRelative(_, ref segment) => return segment.ident.to_string(), + hir::QPath::Resolved(_, path) => &path.segments, + hir::QPath::TypeRelative(_, segment) => return segment.ident.to_string(), hir::QPath::LangItem(lang_item, ..) => return lang_item.name().to_string(), }; @@ -201,7 +186,8 @@ crate fn build_deref_target_impls(cx: &mut DocContext<'_>, items: &[Item], ret: for &did in prim.impls(tcx).iter().filter(|did| !did.is_local()) { inline::build_impl(cx, None, did, None, ret); } - } else if let ResolvedPath { did, .. } = *target { + } else if let Type::Path { path } = target { + let did = path.def_id(); if !did.is_local() { inline::build_impls(cx, None, did, None, ret); } @@ -217,15 +203,15 @@ crate fn name_from_pat(p: &hir::Pat<'_>) -> Symbol { PatKind::Wild | PatKind::Struct(..) => return kw::Underscore, PatKind::Binding(_, _, ident, _) => return ident.name, PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p), - PatKind::Or(ref pats) => { + PatKind::Or(pats) => { pats.iter().map(|p| name_from_pat(p).to_string()).collect::>().join(" | ") } - PatKind::Tuple(ref elts, _) => format!( + PatKind::Tuple(elts, _) => format!( "({})", elts.iter().map(|p| name_from_pat(p).to_string()).collect::>().join(", ") ), - PatKind::Box(ref p) => return name_from_pat(&**p), - PatKind::Ref(ref p, _) => return name_from_pat(&**p), + PatKind::Box(p) => return name_from_pat(&*p), + PatKind::Ref(p, _) => return name_from_pat(&*p), PatKind::Lit(..) => { warn!( "tried to get argument name from PatKind::Lit, which is silly in function arguments" @@ -233,7 +219,7 @@ crate fn name_from_pat(p: &hir::Pat<'_>) -> Symbol { return Symbol::intern("()"); } PatKind::Range(..) => return kw::Underscore, - PatKind::Slice(ref begin, ref mid, ref end) => { + PatKind::Slice(begin, ref mid, end) => { let begin = begin.iter().map(|p| name_from_pat(p).to_string()); let mid = mid.as_ref().map(|p| format!("..{}", name_from_pat(&**p))).into_iter(); let end = end.iter().map(|p| name_from_pat(p).to_string()); @@ -374,8 +360,8 @@ crate fn resolve_type(cx: &mut DocContext<'_>, path: Path) -> Type { Res::SelfTy(..) if path.segments.len() == 1 => Generic(kw::SelfUpper), Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => Generic(path.segments[0].name), _ => { - let did = register_res(cx, path.res); - ResolvedPath { path, did } + let _ = register_res(cx, path.res); + Type::Path { path } } } } @@ -407,20 +393,12 @@ crate fn register_res(cx: &mut DocContext<'_>, res: Res) -> DefId { debug!("register_res({:?})", res); let (did, kind) = match res { - Res::Def(DefKind::AssocTy | DefKind::AssocFn | DefKind::AssocConst, i) => { - // associated items are documented, but on the page of their parent - (cx.tcx.parent(i).unwrap(), ItemType::Trait) - } - Res::Def(DefKind::Variant, i) => { - // variant items are documented, but on the page of their parent - (cx.tcx.parent(i).expect("cannot get parent def id"), ItemType::Enum) - } - // Each of these have their own page. + // These should be added to the cache using `record_extern_fqn`. Res::Def( kind @ - (Fn | TyAlias | Enum | Trait | Struct | Union | Mod | ForeignTy | Const | Static - | Macro(..) | TraitAlias), + (AssocTy | AssocFn | AssocConst | Variant | Fn | TyAlias | Enum | Trait | Struct + | Union | Mod | ForeignTy | Const | Static | Macro(..) | TraitAlias), i, ) => (i, kind.into()), // This is part of a trait definition; document the trait. @@ -435,8 +413,9 @@ crate fn register_res(cx: &mut DocContext<'_>, res: Res) -> DefId { | Res::NonMacroAttr(_) | Res::Err => return res.def_id(), Res::Def( - TyParam | ConstParam | Ctor(..) | ExternCrate | Use | ForeignMod | AnonConst | OpaqueTy - | Field | LifetimeParam | GlobalAsm | Impl | Closure | Generator, + TyParam | ConstParam | Ctor(..) | ExternCrate | Use | ForeignMod | AnonConst + | InlineConst | OpaqueTy | Field | LifetimeParam | GlobalAsm | Impl | Closure + | Generator, id, ) => return id, }; @@ -507,7 +486,7 @@ crate fn has_doc_flag(attrs: ty::Attributes<'_>, flag: Symbol) -> bool { /// so that the channel is consistent. /// /// Set by `bootstrap::Builder::doc_rust_lang_org_channel` in order to keep tests passing on beta/stable. -crate const DOC_RUST_LANG_ORG_CHANNEL: &'static str = env!("DOC_RUST_LANG_ORG_CHANNEL"); +crate const DOC_RUST_LANG_ORG_CHANNEL: &str = env!("DOC_RUST_LANG_ORG_CHANNEL"); /// Render a sequence of macro arms in a format suitable for displaying to the user /// as part of an item declaration. @@ -533,7 +512,7 @@ pub(super) fn display_macro_source( name: Symbol, def: &ast::MacroDef, def_id: DefId, - vis: impl Clean, + vis: Visibility, ) -> String { let tts: Vec<_> = def.body.inner_tokens().into_trees().collect(); // Extract the spans of all matchers. They represent the "interface" of the macro. @@ -542,8 +521,6 @@ pub(super) fn display_macro_source( if def.macro_rules { format!("macro_rules! {} {{\n{}}}", name, render_macro_arms(matchers, ";")) } else { - let vis = vis.clean(cx); - if matchers.len() <= 1 { format!( "{}macro {}{} {{\n ...\n}}", diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index ac440a3951..7c23117cce 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -25,6 +25,7 @@ use crate::html::render::StylePath; use crate::html::static_files; use crate::opts; use crate::passes::{self, Condition, DefaultPassOption}; +use crate::scrape_examples::{AllCallLocations, ScrapeExamplesOptions}; use crate::theme; #[derive(Clone, Copy, PartialEq, Eq, Debug)] @@ -135,9 +136,6 @@ crate struct Options { /// /// Be aware: This option can come both from the CLI and from crate attributes! crate manual_passes: Vec, - /// Whether to display warnings during doc generation or while gathering doctests. By default, - /// all non-rustdoc-specific lints are allowed when generating docs. - crate display_doctest_warnings: bool, /// Whether to run the `calculate-doc-coverage` pass, which counts the number of public items /// with and without documentation. crate show_coverage: bool, @@ -158,6 +156,10 @@ crate struct Options { crate json_unused_externs: bool, /// Whether to skip capturing stdout and stderr of tests. crate nocapture: bool, + + /// Configuration for scraping examples from the current crate. If this option is Some(..) then + /// the compiler will scrape examples and not generate documentation. + crate scrape_examples_options: Option, } impl fmt::Debug for Options { @@ -192,7 +194,6 @@ impl fmt::Debug for Options { .field("persist_doctests", &self.persist_doctests) .field("default_passes", &self.default_passes) .field("manual_passes", &self.manual_passes) - .field("display_doctest_warnings", &self.display_doctest_warnings) .field("show_coverage", &self.show_coverage) .field("crate_version", &self.crate_version) .field("render_options", &self.render_options) @@ -202,6 +203,7 @@ impl fmt::Debug for Options { .field("run_check", &self.run_check) .field("no_run", &self.no_run) .field("nocapture", &self.nocapture) + .field("scrape_examples_options", &self.scrape_examples_options) .finish() } } @@ -280,6 +282,7 @@ crate struct RenderOptions { crate emit: Vec, /// If `true`, HTML source pages will generate links for items to their definition. crate generate_link_to_definition: bool, + crate call_locations: AllCallLocations, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -314,13 +317,13 @@ impl Options { /// been printed, returns `Err` with the exit code. crate fn from_matches(matches: &getopts::Matches) -> Result { // Check for unstable options. - nightly_options::check_nightly_options(&matches, &opts()); + nightly_options::check_nightly_options(matches, &opts()); if matches.opt_present("h") || matches.opt_present("help") { crate::usage("rustdoc"); return Err(0); } else if matches.opt_present("version") { - rustc_driver::version("rustdoc", &matches); + rustc_driver::version("rustdoc", matches); return Err(0); } @@ -356,10 +359,10 @@ impl Options { return Err(0); } - let color = config::parse_color(&matches); + let color = config::parse_color(matches); let config::JsonConfig { json_rendered, json_unused_externs, .. } = - config::parse_json(&matches); - let error_format = config::parse_error_format(&matches, color, json_rendered); + config::parse_json(matches); + let error_format = config::parse_error_format(matches, color, json_rendered); let codegen_options = CodegenOptions::build(matches, error_format); let debugging_opts = DebuggingOptions::build(matches, error_format); @@ -367,7 +370,7 @@ impl Options { let diag = new_handler(error_format, None, &debugging_opts); // check for deprecated options - check_deprecated_options(&matches, &diag); + check_deprecated_options(matches, &diag); let mut emit = Vec::new(); for list in matches.opt_strs("emit") { @@ -433,8 +436,8 @@ impl Options { .iter() .map(|s| SearchPath::from_cli_opt(s, error_format)) .collect(); - let externs = parse_externs(&matches, &debugging_opts, error_format); - let extern_html_root_urls = match parse_extern_html_roots(&matches) { + let externs = parse_externs(matches, &debugging_opts, error_format); + let extern_html_root_urls = match parse_extern_html_roots(matches) { Ok(ex) => ex, Err(err) => { diag.struct_err(err).emit(); @@ -553,7 +556,7 @@ impl Options { } } - let edition = config::parse_crate_edition(&matches); + let edition = config::parse_crate_edition(matches); let mut id_map = html::markdown::IdMap::new(); let external_html = match ExternalHtml::load( @@ -562,7 +565,7 @@ impl Options { &matches.opt_strs("html-after-content"), &matches.opt_strs("markdown-before-content"), &matches.opt_strs("markdown-after-content"), - nightly_options::match_is_nightly_build(&matches), + nightly_options::match_is_nightly_build(matches), &diag, &mut id_map, edition, @@ -632,7 +635,6 @@ impl Options { let proc_macro_crate = crate_types.contains(&CrateType::ProcMacro); let playground_url = matches.opt_str("playground-url"); let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from); - let display_doctest_warnings = matches.opt_present("display-doctest-warnings"); let sort_modules_alphabetically = !matches.opt_present("sort-modules-by-appearance"); let resource_suffix = matches.opt_str("resource-suffix").unwrap_or_default(); let enable_minification = !matches.opt_present("disable-minification"); @@ -671,6 +673,10 @@ impl Options { return Err(1); } + let scrape_examples_options = ScrapeExamplesOptions::new(&matches, &diag)?; + let with_examples = matches.opt_strs("with-examples"); + let call_locations = crate::scrape_examples::load_call_locations(with_examples, &diag)?; + let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format); Ok(Options { @@ -696,7 +702,6 @@ impl Options { test_args, default_passes, manual_passes, - display_doctest_warnings, show_coverage, crate_version, test_run_directory, @@ -737,10 +742,12 @@ impl Options { ), emit, generate_link_to_definition, + call_locations, }, crate_name, output_format, json_unused_externs, + scrape_examples_options, }) } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 0c79d37a6d..c58310947d 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -56,14 +56,10 @@ crate struct DocContext<'tcx> { /// Used while populating `external_traits` to ensure we don't process the same trait twice at /// the same time. crate active_extern_traits: FxHashSet, - // The current set of type and lifetime substitutions, + // The current set of parameter substitutions, // for expanding type aliases at the HIR level: - /// Table `DefId` of type parameter -> substituted type - crate ty_substs: FxHashMap, - /// Table `DefId` of lifetime parameter -> substituted lifetime - crate lt_substs: FxHashMap, - /// Table `DefId` of const parameter -> substituted const - crate ct_substs: FxHashMap, + /// Table `DefId` of type, lifetime, or const parameter -> substituted type, lifetime, or const + crate substs: FxHashMap, /// Table synthetic type parameter for `impl Trait` in argument position -> bounds crate impl_trait_bounds: FxHashMap>, /// Auto-trait or blanket impls processed so far, as `(self_ty, trait_def_id)`. @@ -87,7 +83,7 @@ crate struct DocContext<'tcx> { impl<'tcx> DocContext<'tcx> { crate fn sess(&self) -> &'tcx Session { - &self.tcx.sess + self.tcx.sess } crate fn with_param_env T>(&mut self, def_id: DefId, f: F) -> T { @@ -106,25 +102,13 @@ impl<'tcx> DocContext<'tcx> { /// Call the closure with the given parameters set as /// the substitutions for a type alias' RHS. - crate fn enter_alias( - &mut self, - ty_substs: FxHashMap, - lt_substs: FxHashMap, - ct_substs: FxHashMap, - f: F, - ) -> R + crate fn enter_alias(&mut self, substs: FxHashMap, f: F) -> R where F: FnOnce(&mut Self) -> R, { - let (old_tys, old_lts, old_cts) = ( - mem::replace(&mut self.ty_substs, ty_substs), - mem::replace(&mut self.lt_substs, lt_substs), - mem::replace(&mut self.ct_substs, ct_substs), - ); + let old_substs = mem::replace(&mut self.substs, substs); let r = f(self); - self.ty_substs = old_tys; - self.lt_substs = old_lts; - self.ct_substs = old_cts; + self.substs = old_substs; r } @@ -283,9 +267,9 @@ crate fn create_config( // Closures' tables come from their outermost function, // as they are part of the same "inference environment". // This avoids emitting errors for the parent twice (see similar code in `typeck_with_fallback`) - let outer_def_id = tcx.closure_base_def_id(def_id.to_def_id()).expect_local(); - if outer_def_id != def_id { - return tcx.typeck(outer_def_id); + let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id()).expect_local(); + if typeck_root_def_id != def_id { + return tcx.typeck(typeck_root_def_id); } let hir = tcx.hir(); @@ -382,9 +366,7 @@ crate fn run_global_ctxt( param_env: ParamEnv::empty(), external_traits: Default::default(), active_extern_traits: Default::default(), - ty_substs: Default::default(), - lt_substs: Default::default(), - ct_substs: Default::default(), + substs: Default::default(), impl_trait_bounds: Default::default(), generated_synthetics: Default::default(), auto_traits: tcx @@ -496,7 +478,7 @@ crate fn run_global_ctxt( _ => continue, }; for name in value.as_str().split_whitespace() { - let span = attr.name_value_literal_span().unwrap_or(attr.span()); + let span = attr.name_value_literal_span().unwrap_or_else(|| attr.span()); manual_passes.extend(parse_pass(name, Some(span))); } } @@ -518,20 +500,20 @@ crate fn run_global_ctxt( }; if run { debug!("running pass {}", p.pass.name); - krate = ctxt.tcx.sess.time(p.pass.name, || (p.pass.run)(krate, &mut ctxt)); + krate = tcx.sess.time(p.pass.name, || (p.pass.run)(krate, &mut ctxt)); } } - ctxt.sess().abort_if_errors(); + if tcx.sess.diagnostic().has_errors_or_lint_errors() { + rustc_errors::FatalError.raise(); + } - let render_options = ctxt.render_options; - let mut cache = ctxt.cache; - krate = tcx.sess.time("create_format_cache", || cache.populate(krate, tcx, &render_options)); + krate = tcx.sess.time("create_format_cache", || Cache::populate(&mut ctxt, krate)); // The main crate doc comments are always collapsed. krate.collapsed = true; - (krate, render_options, cache) + (krate, ctxt.render_options, ctxt.cache) } /// Due to , diff --git a/src/librustdoc/docfs.rs b/src/librustdoc/docfs.rs index a5fab1b3d4..d59273db08 100644 --- a/src/librustdoc/docfs.rs +++ b/src/librustdoc/docfs.rs @@ -15,15 +15,6 @@ use std::path::{Path, PathBuf}; use std::string::ToString; use std::sync::mpsc::Sender; -macro_rules! try_err { - ($e:expr, $file:expr) => { - match $e { - Ok(e) => e, - Err(e) => return Err(E::new(e, $file)), - } - }; -} - crate trait PathError { fn new>(e: S, path: P) -> Self where @@ -75,7 +66,7 @@ impl DocFS { }); }); } else { - try_err!(fs::write(&path, contents), path); + fs::write(&path, contents).map_err(|e| E::new(e, path))?; } Ok(()) } diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 9e64d200b4..56ccdfae1d 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -1,7 +1,7 @@ use rustc_ast as ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; -use rustc_errors::{ColorConfig, ErrorReported}; +use rustc_errors::{ColorConfig, ErrorReported, FatalError}; use rustc_hir as hir; use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::intravisit; @@ -38,9 +38,6 @@ use crate::passes::span_of_attrs; crate struct TestOptions { /// Whether to disable the default `extern crate my_crate;` when creating doctests. crate no_crate_inject: bool, - /// Whether to emit compilation warnings when compiling doctests. Setting this will suppress - /// the default `#![allow(unused)]`. - crate display_doctest_warnings: bool, /// Additional crate-level attributes to add to doctests. crate attrs: Vec, } @@ -65,6 +62,8 @@ crate fn run(options: Options) -> Result<(), ErrorReported> { } }); + debug!(?lint_opts); + let crate_types = if options.proc_macro_crate { vec![CrateType::ProcMacro] } else { vec![CrateType::Rlib] }; @@ -72,8 +71,8 @@ crate fn run(options: Options) -> Result<(), ErrorReported> { maybe_sysroot: options.maybe_sysroot.clone(), search_paths: options.libs.clone(), crate_types, - lint_opts: if !options.display_doctest_warnings { lint_opts } else { vec![] }, - lint_cap: Some(options.lint_cap.unwrap_or_else(|| lint::Forbid)), + lint_opts, + lint_cap: Some(options.lint_cap.unwrap_or(lint::Forbid)), cg: options.codegen_options.clone(), externs: options.externs.clone(), unstable_features: options.render_options.unstable_features, @@ -106,7 +105,6 @@ crate fn run(options: Options) -> Result<(), ErrorReported> { }; let test_args = options.test_args.clone(); - let display_doctest_warnings = options.display_doctest_warnings; let nocapture = options.nocapture; let externs = options.externs.clone(); let json_unused_externs = options.json_unused_externs; @@ -118,8 +116,7 @@ crate fn run(options: Options) -> Result<(), ErrorReported> { let collector = global_ctxt.enter(|tcx| { let crate_attrs = tcx.hir().attrs(CRATE_HIR_ID); - let mut opts = scrape_test_config(crate_attrs); - opts.display_doctest_warnings |= options.display_doctest_warnings; + let opts = scrape_test_config(crate_attrs); let enable_per_target_ignores = options.enable_per_target_ignores; let mut collector = Collector::new( tcx.crate_name(LOCAL_CRATE), @@ -149,7 +146,9 @@ crate fn run(options: Options) -> Result<(), ErrorReported> { collector }); - compiler.session().abort_if_errors(); + if compiler.session().diagnostic().has_errors_or_lint_errors() { + FatalError.raise(); + } let unused_extern_reports = collector.unused_extern_reports.clone(); let compiling_test_count = collector.compiling_test_count.load(Ordering::SeqCst); @@ -163,7 +162,7 @@ crate fn run(options: Options) -> Result<(), ErrorReported> { Err(ErrorReported) => return Err(ErrorReported), }; - run_tests(test_args, nocapture, display_doctest_warnings, tests); + run_tests(test_args, nocapture, tests); // Collect and warn about unused externs, but only if we've gotten // reports for each doctest @@ -176,7 +175,7 @@ crate fn run(options: Options) -> Result<(), ErrorReported> { .iter() .map(|uexts| uexts.unused_extern_names.iter().collect::>()) .fold(extern_names, |uextsa, uextsb| { - uextsa.intersection(&uextsb).map(|v| *v).collect::>() + uextsa.intersection(&uextsb).copied().collect::>() }) .iter() .map(|v| (*v).clone()) @@ -206,29 +205,19 @@ crate fn run(options: Options) -> Result<(), ErrorReported> { Ok(()) } -crate fn run_tests( - mut test_args: Vec, - nocapture: bool, - display_doctest_warnings: bool, - tests: Vec, -) { +crate fn run_tests(mut test_args: Vec, nocapture: bool, tests: Vec) { test_args.insert(0, "rustdoctest".to_string()); if nocapture { test_args.push("--nocapture".to_string()); } - test::test_main( - &test_args, - tests, - Some(test::Options::new().display_output(display_doctest_warnings)), - ); + test::test_main(&test_args, tests, None); } // Look for `#![doc(test(no_crate_inject))]`, used by crates in the std facade. fn scrape_test_config(attrs: &[ast::Attribute]) -> TestOptions { use rustc_ast_pretty::pprust; - let mut opts = - TestOptions { no_crate_inject: false, display_doctest_warnings: false, attrs: Vec::new() }; + let mut opts = TestOptions { no_crate_inject: false, attrs: Vec::new() }; let test_attrs: Vec<_> = attrs .iter() @@ -423,7 +412,7 @@ fn run_test( // 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 { + if !out_lines.is_empty() { out_lines.push(""); } @@ -508,7 +497,7 @@ crate fn make_test( let mut prog = String::new(); let mut supports_color = false; - if opts.attrs.is_empty() && !opts.display_doctest_warnings { + if opts.attrs.is_empty() { // If there aren't any attributes supplied by #![doc(test(attr(...)))], then allow some // lints that are commonly triggered in doctests. The crate-level test attributes are // commonly used to make tests fail in case they trigger warnings, so having this there in @@ -611,6 +600,10 @@ crate fn make_test( break; } } + + // The supplied slice is only used for diagnostics, + // which are swallowed here anyway. + parser.maybe_consume_incorrect_semicolon(&[]); } // Reset errors so that they won't be reported as compiler bugs when dropping the @@ -1124,7 +1117,7 @@ impl<'a, 'hir, 'tcx> HirCollector<'a, 'hir, 'tcx> { let mut attrs = Attributes::from_ast(ast_attrs, None); if let Some(ref cfg) = ast_attrs.cfg(self.tcx, &FxHashSet::default()) { - if !cfg.matches(&self.sess.parse_sess, Some(&self.sess.features_untracked())) { + if !cfg.matches(&self.sess.parse_sess, Some(self.sess.features_untracked())) { return; } } diff --git a/src/librustdoc/doctest/tests.rs b/src/librustdoc/doctest/tests.rs index 1851708096..099609d0f9 100644 --- a/src/librustdoc/doctest/tests.rs +++ b/src/librustdoc/doctest/tests.rs @@ -52,8 +52,7 @@ assert_eq!(2+2, 4); fn make_test_no_crate_inject() { // Even if you do use the crate within the test, setting `opts.no_crate_inject` will skip // adding it anyway. - let opts = - TestOptions { no_crate_inject: true, display_doctest_warnings: false, attrs: vec![] }; + let opts = TestOptions { no_crate_inject: true, attrs: vec![] }; let input = "use asdf::qwop; assert_eq!(2+2, 4);"; let expected = "#![allow(unused)] @@ -215,20 +214,6 @@ assert_eq!(2+2, 4);" assert_eq!((output, len), (expected, 1)); } -#[test] -fn make_test_display_doctest_warnings() { - // If the user is asking to display doctest warnings, suppress the default `allow(unused)`. - let mut opts = TestOptions::default(); - opts.display_doctest_warnings = true; - let input = "assert_eq!(2+2, 4);"; - let expected = "fn main() { -assert_eq!(2+2, 4); -}" - .to_string(); - let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION, None); - assert_eq!((output, len), (expected, 1)); -} - #[test] fn make_test_issues_21299_33731() { let opts = TestOptions::default(); diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs deleted file mode 100644 index 8f1e8f277c..0000000000 --- a/src/librustdoc/doctree.rs +++ /dev/null @@ -1,27 +0,0 @@ -//! This module is used to store stuff from Rust's AST in a more convenient -//! manner (and with prettier names) before cleaning. -use rustc_middle::ty::TyCtxt; -use rustc_span::{self, Span, Symbol}; - -use rustc_hir as hir; - -#[derive(Debug)] -crate struct Module<'hir> { - crate name: Symbol, - crate where_inner: Span, - crate mods: Vec>, - crate id: hir::HirId, - // (item, renamed) - crate items: Vec<(&'hir hir::Item<'hir>, Option)>, - crate foreigns: Vec<(&'hir hir::ForeignItem<'hir>, Option)>, -} - -impl Module<'hir> { - crate fn new(name: Symbol, id: hir::HirId, where_inner: Span) -> Module<'hir> { - Module { name, id, where_inner, mods: Vec::new(), items: Vec::new(), foreigns: Vec::new() } - } - - crate fn where_outer(&self, tcx: TyCtxt<'_>) -> Span { - tcx.hir().span(self.id) - } -} diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs index 302fc5a677..6ed911b8d2 100644 --- a/src/librustdoc/externalfiles.rs +++ b/src/librustdoc/externalfiles.rs @@ -8,13 +8,13 @@ use serde::Serialize; #[derive(Clone, Debug, Serialize)] crate struct ExternalHtml { - /// Content that will be included inline in the section of a + /// Content that will be included inline in the `` section of a /// rendered Markdown file or generated documentation crate in_header: String, - /// Content that will be included inline between and the content of + /// Content that will be included inline between `` and the content of /// a rendered Markdown file or generated documentation crate before_content: String, - /// Content that will be included inline between the content and of + /// Content that will be included inline between the content and `` of /// a rendered Markdown file or generated documentation crate after_content: String, } diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index f84850c0fe..cd0f44e569 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -20,22 +20,28 @@ crate trait DocFolder: Sized { StructItem(mut i) => { let num_fields = i.fields.len(); i.fields = i.fields.into_iter().filter_map(|x| self.fold_item(x)).collect(); - i.fields_stripped |= - num_fields != i.fields.len() || i.fields.iter().any(|f| f.is_stripped()); + if !i.fields_stripped { + i.fields_stripped = + num_fields != i.fields.len() || i.fields.iter().any(|f| f.is_stripped()); + } StructItem(i) } UnionItem(mut i) => { let num_fields = i.fields.len(); i.fields = i.fields.into_iter().filter_map(|x| self.fold_item(x)).collect(); - i.fields_stripped |= - num_fields != i.fields.len() || i.fields.iter().any(|f| f.is_stripped()); + if !i.fields_stripped { + i.fields_stripped = + num_fields != i.fields.len() || i.fields.iter().any(|f| f.is_stripped()); + } UnionItem(i) } EnumItem(mut i) => { let num_variants = i.variants.len(); i.variants = i.variants.into_iter().filter_map(|x| self.fold_item(x)).collect(); - i.variants_stripped |= - num_variants != i.variants.len() || i.variants.iter().any(|f| f.is_stripped()); + if !i.variants_stripped { + i.variants_stripped = num_variants != i.variants.len() + || i.variants.iter().any(|f| f.is_stripped()); + } EnumItem(i) } TraitItem(mut i) => { @@ -46,24 +52,42 @@ crate trait DocFolder: Sized { i.items = i.items.into_iter().filter_map(|x| self.fold_item(x)).collect(); ImplItem(i) } - VariantItem(i) => { - let i2 = i.clone(); // this clone is small - match i { - Variant::Struct(mut j) => { - let num_fields = j.fields.len(); - j.fields = j.fields.into_iter().filter_map(|x| self.fold_item(x)).collect(); - j.fields_stripped |= num_fields != j.fields.len() + VariantItem(i) => match i { + Variant::Struct(mut j) => { + let num_fields = j.fields.len(); + j.fields = j.fields.into_iter().filter_map(|x| self.fold_item(x)).collect(); + if !j.fields_stripped { + j.fields_stripped = num_fields != j.fields.len() || j.fields.iter().any(|f| f.is_stripped()); - VariantItem(Variant::Struct(j)) - } - Variant::Tuple(fields) => { - let fields = fields.into_iter().filter_map(|x| self.fold_item(x)).collect(); - VariantItem(Variant::Tuple(fields)) } - _ => VariantItem(i2), + VariantItem(Variant::Struct(j)) } - } - x => x, + Variant::Tuple(fields) => { + let fields = fields.into_iter().filter_map(|x| self.fold_item(x)).collect(); + VariantItem(Variant::Tuple(fields)) + } + Variant::CLike => VariantItem(Variant::CLike), + }, + ExternCrateItem { src: _ } + | ImportItem(_) + | FunctionItem(_) + | TypedefItem(_, _) + | OpaqueTyItem(_) + | StaticItem(_) + | ConstantItem(_) + | TraitAliasItem(_) + | TyMethodItem(_) + | MethodItem(_, _) + | StructFieldItem(_) + | ForeignFunctionItem(_) + | ForeignStaticItem(_) + | ForeignTypeItem + | MacroItem(_) + | ProcMacroItem(_) + | PrimitiveItem(_) + | AssocConstItem(_, _) + | AssocTypeItem(_, _) + | KeywordItem(_) => kind, } } @@ -86,14 +110,12 @@ crate trait DocFolder: Sized { fn fold_crate(&mut self, mut c: Crate) -> Crate { c.module = self.fold_item(c.module).unwrap(); - { - let external_traits = { std::mem::take(&mut *c.external_traits.borrow_mut()) }; - for (k, mut v) in external_traits { - v.trait_.items = - v.trait_.items.into_iter().filter_map(|i| self.fold_item(i)).collect(); - c.external_traits.borrow_mut().insert(k, v); - } + let external_traits = { std::mem::take(&mut *c.external_traits.borrow_mut()) }; + for (k, mut v) in external_traits { + v.trait_.items = v.trait_.items.into_iter().filter_map(|i| self.fold_item(i)).collect(); + c.external_traits.borrow_mut().insert(k, v); } + c } } diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 8b883ffaaf..d3831450e1 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -6,8 +6,8 @@ use rustc_middle::middle::privacy::AccessLevels; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::sym; -use crate::clean::{self, GetDefId, ItemId, PrimitiveType}; -use crate::config::RenderOptions; +use crate::clean::{self, ExternalCrate, ItemId, PrimitiveType}; +use crate::core::DocContext; use crate::fold::DocFolder; use crate::formats::item_type::ItemType; use crate::formats::Impl; @@ -27,7 +27,7 @@ use crate::html::render::IndexItem; #[derive(Default)] crate struct Cache { /// Maps a type ID to all known implementations for that type. This is only - /// recognized for intra-crate `ResolvedPath` types, and is used to print + /// recognized for intra-crate [`clean::Type::Path`]s, and is used to print /// out extra documentation on the page of an enum/struct. /// /// The values of the map are a list of implementations and documentation @@ -136,46 +136,47 @@ impl Cache { /// Populates the `Cache` with more data. The returned `Crate` will be missing some data that was /// in `krate` due to the data being moved into the `Cache`. - crate fn populate( - &mut self, - mut krate: clean::Crate, - tcx: TyCtxt<'_>, - render_options: &RenderOptions, - ) -> clean::Crate { + crate fn populate(cx: &mut DocContext<'_>, mut krate: clean::Crate) -> clean::Crate { + let tcx = cx.tcx; + // Crawl the crate to build various caches used for the output - debug!(?self.crate_version); - self.traits = krate.external_traits.take(); - let RenderOptions { extern_html_root_takes_precedence, output: dst, .. } = render_options; + debug!(?cx.cache.crate_version); + cx.cache.traits = krate.external_traits.take(); // 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 &e in &krate.externs { + for &crate_num in cx.tcx.crates(()) { + let e = ExternalCrate { crate_num }; + let name = e.name(tcx); + let render_options = &cx.render_options; let extern_url = render_options.extern_html_root_urls.get(&*name.as_str()).map(|u| &**u); - let location = e.location(extern_url, *extern_html_root_takes_precedence, dst, tcx); - self.extern_locations.insert(e.crate_num, location); - self.external_paths.insert(e.def_id(), (vec![name.to_string()], ItemType::Module)); + let extern_url_takes_precedence = render_options.extern_html_root_takes_precedence; + let dst = &render_options.output; + let location = e.location(extern_url, extern_url_takes_precedence, dst, tcx); + cx.cache.extern_locations.insert(e.crate_num, location); + cx.cache.external_paths.insert(e.def_id(), (vec![name.to_string()], ItemType::Module)); } // FIXME: avoid this clone (requires implementing Default manually) - self.primitive_locations = PrimitiveType::primitive_locations(tcx).clone(); - for (prim, &def_id) in &self.primitive_locations { + cx.cache.primitive_locations = PrimitiveType::primitive_locations(tcx).clone(); + for (prim, &def_id) in &cx.cache.primitive_locations { let crate_name = tcx.crate_name(def_id.krate); // Recall that we only allow primitive modules to be at the root-level of the crate. // If that restriction is ever lifted, this will have to include the relative paths instead. - self.external_paths.insert( + cx.cache.external_paths.insert( def_id, (vec![crate_name.to_string(), prim.as_sym().to_string()], ItemType::Primitive), ); } - krate = CacheBuilder { tcx, cache: self }.fold_crate(krate); + krate = CacheBuilder { tcx, cache: &mut cx.cache }.fold_crate(krate); - for (trait_did, dids, impl_) in self.orphan_trait_impls.drain(..) { - if self.traits.contains_key(&trait_did) { + for (trait_did, dids, impl_) in cx.cache.orphan_trait_impls.drain(..) { + if cx.cache.traits.contains_key(&trait_did) { for did in dids { - self.impls.entry(did).or_default().push(impl_.clone()); + cx.cache.impls.entry(did).or_default().push(impl_.clone()); } } } @@ -206,7 +207,9 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { || i.trait_ .as_ref() .map_or(false, |t| self.cache.masked_crates.contains(&t.def_id().krate)) - || i.for_.def_id().map_or(false, |d| self.cache.masked_crates.contains(&d.krate)) + || i.for_ + .def_id(self.cache) + .map_or(false, |d| self.cache.masked_crates.contains(&d.krate)) { return None; } @@ -226,7 +229,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { // Collect all the implementors of traits. if let clean::ImplItem(ref i) = *item.kind { if let Some(trait_) = &i.trait_ { - if i.blanket_impl.is_none() { + if !i.kind.is_blanket() { self.cache .implementors .entry(trait_.def_id()) @@ -292,7 +295,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { // inserted later on when serializing the search-index. if item.def_id.index().map_or(false, |idx| idx != CRATE_DEF_INDEX) { let desc = item.doc_value().map_or_else(String::new, |x| { - short_markdown_summary(&x.as_str(), &item.link_names(&self.cache)) + short_markdown_summary(x.as_str(), &item.link_names(self.cache)) }); self.cache.search_index.push(IndexItem { ty: item.type_(), @@ -301,7 +304,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { desc, parent, parent_idx: None, - search_type: get_index_search_type(&item, self.tcx), + search_type: get_index_search_type(&item, self.tcx, self.cache), aliases: item.attrs.get_doc_aliases(), }); } @@ -398,8 +401,8 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { clean::ImplItem(ref i) => { self.cache.parent_is_trait_impl = i.trait_.is_some(); match i.for_ { - clean::ResolvedPath { did, .. } => { - self.cache.parent_stack.push(did); + clean::Type::Path { ref path } => { + self.cache.parent_stack.push(path.def_id()); true } clean::DynTrait(ref bounds, _) @@ -433,9 +436,9 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { // Note: matching twice to restrict the lifetime of the `i` borrow. let mut dids = FxHashSet::default(); match i.for_ { - clean::ResolvedPath { did, .. } - | clean::BorrowedRef { type_: box clean::ResolvedPath { did, .. }, .. } => { - dids.insert(did); + clean::Type::Path { ref path } + | clean::BorrowedRef { type_: box clean::Type::Path { ref path }, .. } => { + dids.insert(path.def_id()); } clean::DynTrait(ref bounds, _) | clean::BorrowedRef { type_: box clean::DynTrait(ref bounds, _), .. } => { @@ -454,7 +457,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { if let Some(generics) = i.trait_.as_ref().and_then(|t| t.generics()) { for bound in generics { - if let Some(did) = bound.def_id() { + if let Some(did) = bound.def_id(self.cache) { dids.insert(did); } } @@ -462,7 +465,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { let impl_item = Impl { impl_item: item }; if impl_item.trait_did().map_or(true, |d| self.cache.traits.contains_key(&d)) { for did in dids { - self.cache.impls.entry(did).or_insert(vec![]).push(impl_item.clone()); + self.cache.impls.entry(did).or_insert_with(Vec::new).push(impl_item.clone()); } } else { let trait_did = impl_item.trait_did().expect("no trait did"); diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs index 955de57dc0..3979d29b67 100644 --- a/src/librustdoc/formats/item_type.rs +++ b/src/librustdoc/formats/item_type.rs @@ -48,6 +48,7 @@ crate enum ItemType { ProcAttribute = 23, ProcDerive = 24, TraitAlias = 25, + Generic = 26, } impl Serialize for ItemType { @@ -133,6 +134,7 @@ impl From for ItemType { | DefKind::Use | DefKind::ForeignMod | DefKind::AnonConst + | DefKind::InlineConst | DefKind::OpaqueTy | DefKind::Field | DefKind::LifetimeParam @@ -173,6 +175,7 @@ impl ItemType { ItemType::ProcAttribute => "attr", ItemType::ProcDerive => "derive", ItemType::TraitAlias => "traitalias", + ItemType::Generic => "generic", } } } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index f2751947c7..34742fac0e 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -13,7 +13,10 @@ use rustc_attr::{ConstStability, StabilityLevel}; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; +use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; +use rustc_middle::ty; +use rustc_middle::ty::DefIdTree; use rustc_middle::ty::TyCtxt; use rustc_span::def_id::CRATE_DEF_INDEX; use rustc_target::spec::abi::Abi; @@ -501,7 +504,16 @@ crate fn href_with_root_path( cx: &Context<'_>, root_path: Option<&str>, ) -> Result<(String, ItemType, Vec), HrefError> { - let cache = &cx.cache(); + let tcx = cx.tcx(); + let def_kind = tcx.def_kind(did); + let did = match def_kind { + DefKind::AssocTy | DefKind::AssocFn | DefKind::AssocConst | DefKind::Variant => { + // documented on their parent's page + tcx.parent(did).unwrap() + } + _ => did, + }; + 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] } @@ -595,9 +607,8 @@ crate fn href_relative_parts<'a>(fqp: &'a [String], relative_to_fqp: &'a [String } } -/// 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<'a, 'cx: 'a>( +/// Used to render a [`clean::Path`]. +fn resolved_path<'cx>( w: &mut fmt::Formatter<'_>, did: DefId, path: &clean::Path, @@ -696,7 +707,7 @@ fn primitive_link( /// Helper to render type parameters fn tybounds<'a, 'tcx: 'a>( - bounds: &'a Vec, + bounds: &'a [clean::PolyTrait], lt: &'a Option, cx: &'a Context<'tcx>, ) -> impl fmt::Display + 'a + Captures<'tcx> { @@ -750,8 +761,9 @@ fn fmt_type<'cx>( match *t { clean::Generic(name) => write!(f, "{}", name), - clean::ResolvedPath { did, ref path } => { + clean::Type::Path { ref path } => { // Paths like `T::Output` and `Self::Output` should be rendered with all segments. + let did = path.def_id(); resolved_path(f, did, path, path.is_assoc_ty(), use_absolute, cx) } clean::DynTrait(ref bounds, ref lt) => { @@ -886,7 +898,7 @@ fn fmt_type<'cx>( if bounds.len() > 1 || trait_lt.is_some() => { write!(f, "{}{}{}(", amp, lt, m)?; - fmt_type(&ty, f, use_absolute, cx)?; + fmt_type(ty, f, use_absolute, cx)?; write!(f, ")") } clean::Generic(..) => { @@ -896,11 +908,11 @@ fn fmt_type<'cx>( &format!("{}{}{}", amp, lt, m), cx, )?; - fmt_type(&ty, f, use_absolute, cx) + fmt_type(ty, f, use_absolute, cx) } _ => { write!(f, "{}{}{}", amp, lt, m)?; - fmt_type(&ty, f, use_absolute, cx) + fmt_type(ty, f, use_absolute, cx) } } } @@ -990,14 +1002,15 @@ impl clean::Impl { } if let Some(ref ty) = self.trait_ { - if self.negative_polarity { - write!(f, "!")?; + match self.polarity { + ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => {} + ty::ImplPolarity::Negative => write!(f, "!")?, } fmt::Display::fmt(&ty.print(cx), f)?; write!(f, " for ")?; } - if let Some(ref ty) = self.blanket_impl { + if let Some(ref ty) = self.kind.as_blanket_ty() { fmt_type(ty, f, use_absolute, cx)?; } else { fmt_type(&self.for_, f, use_absolute, cx)?; diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 8ed6996287..688860f94e 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -12,6 +12,7 @@ use crate::html::render::Context; use std::collections::VecDeque; use std::fmt::{Display, Write}; +use rustc_data_structures::fx::FxHashMap; use rustc_lexer::{LiteralKind, TokenKind}; use rustc_span::edition::Edition; use rustc_span::symbol::Symbol; @@ -30,6 +31,10 @@ crate struct ContextInfo<'a, 'b, 'c> { crate root_path: &'c str, } +/// Decorations are represented as a map from CSS class to vector of character ranges. +/// Each range will be wrapped in a span with that class. +crate struct DecorationInfo(crate FxHashMap<&'static str, Vec<(u32, u32)>>); + /// Highlights `src`, returning the HTML output. crate fn render_with_highlighting( src: &str, @@ -40,6 +45,7 @@ crate fn render_with_highlighting( edition: Edition, extra_content: Option, context_info: Option>, + decoration_info: Option, ) { debug!("highlighting: ================\n{}\n==============", src); if let Some((edition_info, class)) = tooltip { @@ -56,7 +62,7 @@ crate fn render_with_highlighting( } write_header(out, class, extra_content); - write_code(out, &src, edition, context_info); + write_code(out, src, edition, context_info, decoration_info); write_footer(out, playground_button); } @@ -89,17 +95,23 @@ fn write_code( src: &str, edition: Edition, context_info: Option>, + decoration_info: Option, ) { // This replace allows to fix how the code source with DOS backline characters is displayed. let src = src.replace("\r\n", "\n"); - Classifier::new(&src, edition, context_info.as_ref().map(|c| c.file_span).unwrap_or(DUMMY_SP)) - .highlight(&mut |highlight| { - match highlight { - Highlight::Token { text, class } => string(out, Escape(text), class, &context_info), - Highlight::EnterSpan { class } => enter_span(out, class), - Highlight::ExitSpan => exit_span(out), - }; - }); + Classifier::new( + &src, + edition, + context_info.as_ref().map(|c| c.file_span).unwrap_or(DUMMY_SP), + decoration_info, + ) + .highlight(&mut |highlight| { + match highlight { + Highlight::Token { text, class } => string(out, Escape(text), class, &context_info), + Highlight::EnterSpan { class } => enter_span(out, class), + Highlight::ExitSpan => exit_span(out), + }; + }); } fn write_footer(out: &mut Buffer, playground_button: Option<&str>) { @@ -127,6 +139,7 @@ enum Class { PreludeTy, PreludeVal, QuestionMark, + Decoration(&'static str), } impl Class { @@ -150,6 +163,7 @@ impl Class { Class::PreludeTy => "prelude-ty", Class::PreludeVal => "prelude-val", Class::QuestionMark => "question-mark", + Class::Decoration(kind) => kind, } } @@ -248,6 +262,30 @@ impl Iterator for PeekIter<'a> { } } +/// Custom spans inserted into the source. Eg --scrape-examples uses this to highlight function calls +struct Decorations { + starts: Vec<(u32, &'static str)>, + ends: Vec, +} + +impl Decorations { + fn new(info: DecorationInfo) -> Self { + // Extract tuples (start, end, kind) into separate sequences of (start, kind) and (end). + let (mut starts, mut ends): (Vec<_>, Vec<_>) = info + .0 + .into_iter() + .map(|(kind, ranges)| ranges.into_iter().map(move |(lo, hi)| ((lo, kind), hi))) + .flatten() + .unzip(); + + // Sort the sequences in document order. + starts.sort_by_key(|(lo, _)| *lo); + ends.sort(); + + Decorations { starts, ends } + } +} + /// Processes program tokens, classifying strings of text by highlighting /// category (`Class`). struct Classifier<'a> { @@ -259,13 +297,20 @@ struct Classifier<'a> { byte_pos: u32, file_span: Span, src: &'a str, + decorations: Option, } impl<'a> Classifier<'a> { /// Takes as argument the source code to HTML-ify, the rust edition to use and the source code /// file span which will be used later on by the `span_correspondance_map`. - fn new(src: &str, edition: Edition, file_span: Span) -> Classifier<'_> { + fn new( + src: &str, + edition: Edition, + file_span: Span, + decoration_info: Option, + ) -> Classifier<'_> { let tokens = PeekIter::new(TokenIter { src }); + let decorations = decoration_info.map(Decorations::new); Classifier { tokens, in_attribute: false, @@ -275,6 +320,7 @@ impl<'a> Classifier<'a> { byte_pos: 0, file_span, src, + decorations, } } @@ -356,6 +402,19 @@ impl<'a> Classifier<'a> { /// token is used. fn highlight(mut self, sink: &mut dyn FnMut(Highlight<'a>)) { loop { + if let Some(decs) = self.decorations.as_mut() { + let byte_pos = self.byte_pos; + let n_starts = decs.starts.iter().filter(|(i, _)| byte_pos >= *i).count(); + for (_, kind) in decs.starts.drain(0..n_starts) { + sink(Highlight::EnterSpan { class: Class::Decoration(kind) }); + } + + let n_ends = decs.ends.iter().filter(|i| byte_pos >= **i).count(); + for _ in decs.ends.drain(0..n_ends) { + sink(Highlight::ExitSpan); + } + } + if self .tokens .peek() @@ -416,22 +475,37 @@ impl<'a> Classifier<'a> { // Assume that '&' or '*' is the reference or dereference operator // or a reference or pointer type. Unless, of course, it looks like // a logical and or a multiplication operator: `&&` or `* `. - TokenKind::Star => match self.peek() { - Some(TokenKind::Whitespace) => Class::Op, + TokenKind::Star => match self.tokens.peek() { + Some((TokenKind::Whitespace, _)) => Class::Op, + Some((TokenKind::Ident, "mut")) => { + self.next(); + sink(Highlight::Token { text: "*mut", class: Some(Class::RefKeyWord) }); + return; + } + Some((TokenKind::Ident, "const")) => { + self.next(); + sink(Highlight::Token { text: "*const", class: Some(Class::RefKeyWord) }); + return; + } _ => Class::RefKeyWord, }, - TokenKind::And => match lookahead { - Some(TokenKind::And) => { + TokenKind::And => match self.tokens.peek() { + Some((TokenKind::And, _)) => { self.next(); sink(Highlight::Token { text: "&&", class: Some(Class::Op) }); return; } - Some(TokenKind::Eq) => { + Some((TokenKind::Eq, _)) => { self.next(); sink(Highlight::Token { text: "&=", class: Some(Class::Op) }); return; } - Some(TokenKind::Whitespace) => Class::Op, + Some((TokenKind::Whitespace, _)) => Class::Op, + Some((TokenKind::Ident, "mut")) => { + self.next(); + sink(Highlight::Token { text: "&mut", class: Some(Class::RefKeyWord) }); + return; + } _ => Class::RefKeyWord, }, @@ -558,7 +632,7 @@ impl<'a> Classifier<'a> { }, Some(c) => c, }, - TokenKind::RawIdent | TokenKind::UnknownPrefix => { + TokenKind::RawIdent | TokenKind::UnknownPrefix | TokenKind::InvalidIdent => { Class::Ident(self.new_span(before, text)) } TokenKind::Lifetime { .. } => Class::Lifetime, @@ -657,7 +731,7 @@ fn string( // https://github.com/rust-lang/rust/blob/60f1a2fc4b535ead9c85ce085fdce49b1b097531/src/librustdoc/html/render/context.rs#L315-L338 match href { LinkFromSrc::Local(span) => context - .href_from_span(*span) + .href_from_span(*span, true) .map(|s| format!("{}{}", context_info.root_path, s)), LinkFromSrc::External(def_id) => { format::href_with_root_path(*def_id, context, Some(context_info.root_path)) @@ -665,7 +739,7 @@ fn string( .map(|(url, _, _)| url) } LinkFromSrc::Primitive(prim) => format::href_with_root_path( - PrimitiveType::primitive_locations(context.tcx())[&prim], + PrimitiveType::primitive_locations(context.tcx())[prim], context, Some(context_info.root_path), ) diff --git a/src/librustdoc/html/highlight/fixtures/decorations.html b/src/librustdoc/html/highlight/fixtures/decorations.html new file mode 100644 index 0000000000..45f567880c --- /dev/null +++ b/src/librustdoc/html/highlight/fixtures/decorations.html @@ -0,0 +1,2 @@ +let x = 1; +let y = 2; \ No newline at end of file diff --git a/src/librustdoc/html/highlight/fixtures/sample.html b/src/librustdoc/html/highlight/fixtures/sample.html index 22e650af7e..b117a12e39 100644 --- a/src/librustdoc/html/highlight/fixtures/sample.html +++ b/src/librustdoc/html/highlight/fixtures/sample.html @@ -15,11 +15,11 @@ #[cfg(target_os = "linux")] fn main() -> () { let foo = true && false || true; - let _: *const () = 0; + let _: *const () = 0; let _ = &foo; let _ = &&foo; let _ = *foo; - mac!(foo, &mut bar); + mac!(foo, &mut bar); assert!(self.length < N && index <= self.length); ::std::env::var("gateau").is_ok(); #[rustfmt::skip] diff --git a/src/librustdoc/html/highlight/tests.rs b/src/librustdoc/html/highlight/tests.rs index 450bbfea1e..1fea7e983b 100644 --- a/src/librustdoc/html/highlight/tests.rs +++ b/src/librustdoc/html/highlight/tests.rs @@ -1,6 +1,7 @@ -use super::write_code; +use super::{write_code, DecorationInfo}; use crate::html::format::Buffer; use expect_test::expect_file; +use rustc_data_structures::fx::FxHashMap; use rustc_span::create_default_session_globals_then; use rustc_span::edition::Edition; @@ -22,7 +23,7 @@ fn test_html_highlighting() { let src = include_str!("fixtures/sample.rs"); let html = { let mut out = Buffer::new(); - write_code(&mut out, src, Edition::Edition2018, None); + write_code(&mut out, src, Edition::Edition2018, None, None); format!("{}
{}
\n", STYLE, out.into_inner()) }; expect_file!["fixtures/sample.html"].assert_eq(&html); @@ -36,7 +37,7 @@ fn test_dos_backline() { println!(\"foo\");\r\n\ }\r\n"; let mut html = Buffer::new(); - write_code(&mut html, src, Edition::Edition2018, None); + write_code(&mut html, src, Edition::Edition2018, None, None); expect_file!["fixtures/dos_line.html"].assert_eq(&html.into_inner()); }); } @@ -50,7 +51,7 @@ let x = super::b::foo; let y = Self::whatever;"; let mut html = Buffer::new(); - write_code(&mut html, src, Edition::Edition2018, None); + write_code(&mut html, src, Edition::Edition2018, None, None); expect_file!["fixtures/highlight.html"].assert_eq(&html.into_inner()); }); } @@ -60,7 +61,21 @@ fn test_union_highlighting() { create_default_session_globals_then(|| { let src = include_str!("fixtures/union.rs"); let mut html = Buffer::new(); - write_code(&mut html, src, Edition::Edition2018, None); + write_code(&mut html, src, Edition::Edition2018, None, None); expect_file!["fixtures/union.html"].assert_eq(&html.into_inner()); }); } + +#[test] +fn test_decorations() { + create_default_session_globals_then(|| { + let src = "let x = 1; +let y = 2;"; + let mut decorations = FxHashMap::default(); + decorations.insert("example", vec![(0, 10)]); + + let mut html = Buffer::new(); + write_code(&mut html, src, Edition::Edition2018, None, Some(DecorationInfo(decorations))); + expect_file!["fixtures/decorations.html"].assert_eq(&html.into_inner()); + }); +} diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 6ed603c96b..71d7cc1a09 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -22,6 +22,8 @@ crate struct Layout { /// If false, the `select` element to have search filtering by crates on rendered docs /// won't be generated. crate generate_search_filter: bool, + /// If true, then scrape-examples.js will be included in the output HTML file + crate scrape_examples_extension: bool, } #[derive(Serialize)] @@ -66,10 +68,8 @@ crate fn render( let krate_with_trailing_slash = ensure_trailing_slash(&layout.krate).to_string(); let style_files = style_files .iter() - .filter_map(|t| { - if let Some(stem) = t.path.file_stem() { Some((stem, t.disabled)) } else { None } - }) - .filter_map(|t| if let Some(path) = t.0.to_str() { Some((path, t.1)) } else { None }) + .filter_map(|t| t.path.file_stem().map(|stem| (stem, t.disabled))) + .filter_map(|t| t.0.to_str().map(|path| (path, t.1))) .map(|t| { format!( r#""#, diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index c46439b851..d811c85ea5 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -178,7 +178,7 @@ fn map_line(s: &str) -> Line<'_> { Line::Shown(Cow::Owned(s.replacen("##", "#", 1))) } else if let Some(stripped) = trimmed.strip_prefix("# ") { // # text - Line::Hidden(&stripped) + Line::Hidden(stripped) } else if trimmed == "#" { // We cannot handle '#text' because it could be #[attr]. Line::Hidden("") @@ -258,7 +258,7 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> { let parse_result = match kind { CodeBlockKind::Fenced(ref lang) => { let parse_result = - LangString::parse_without_check(&lang, self.check_error_codes, false); + LangString::parse_without_check(lang, self.check_error_codes, false); if !parse_result.rust { return Some(Event::Html( format!( @@ -360,6 +360,7 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> { edition, None, None, + None, ); Some(Event::Html(s.into_inner().into())) } @@ -655,7 +656,7 @@ impl<'a, I> Footnotes<'a, I> { } fn get_entry(&mut self, key: &str) -> &mut (Vec>, u16) { - let new_id = self.footnotes.keys().count() + 1; + let new_id = self.footnotes.len() + 1; let key = key.to_owned(); self.footnotes.entry(key).or_insert((Vec::new(), new_id as u16)) } @@ -668,7 +669,7 @@ impl<'a, I: Iterator>> Iterator for Footnotes<'a, I> { loop { match self.inner.next() { Some((Event::FootnoteReference(ref reference), range)) => { - let entry = self.get_entry(&reference); + let entry = self.get_entry(reference); let reference = format!( "{0}", (*entry).1 @@ -903,7 +904,7 @@ impl LangString { string .split(|c| c == ',' || c == ' ' || c == '\t') .map(str::trim) - .map(|token| if token.chars().next() == Some('.') { &token[1..] } else { token }) + .map(|token| token.strip_prefix('.').unwrap_or(token)) .filter(|token| !token.is_empty()) } @@ -973,7 +974,10 @@ impl LangString { } x if extra.is_some() => { let s = x.to_lowercase(); - match if s == "compile-fail" || s == "compile_fail" || s == "compilefail" { + if let Some((flag, help)) = if s == "compile-fail" + || s == "compile_fail" + || s == "compilefail" + { Some(( "compile_fail", "the code block will either not be tested if not marked as a rust one \ @@ -1006,15 +1010,12 @@ impl LangString { } else { None } { - Some((flag, help)) => { - if let Some(ref extra) = extra { - extra.error_invalid_codeblock_attr( - &format!("unknown attribute `{}`. Did you mean `{}`?", x, flag), - help, - ); - } + if let Some(extra) = extra { + extra.error_invalid_codeblock_attr( + &format!("unknown attribute `{}`. Did you mean `{}`?", x, flag), + help, + ); } - None => {} } seen_other_tags = true; } @@ -1050,13 +1051,10 @@ impl Markdown<'_> { return String::new(); } let mut replacer = |broken_link: BrokenLink<'_>| { - if let Some(link) = - links.iter().find(|link| &*link.original_text == broken_link.reference) - { - Some((link.href.as_str().into(), link.new_text.as_str().into())) - } else { - None - } + links + .iter() + .find(|link| &*link.original_text == broken_link.reference) + .map(|link| (link.href.as_str().into(), link.new_text.as_str().into())) }; let p = Parser::new_with_broken_link_callback(md, main_body_opts(), Some(&mut replacer)); @@ -1134,13 +1132,10 @@ impl MarkdownSummaryLine<'_> { } let mut replacer = |broken_link: BrokenLink<'_>| { - if let Some(link) = - links.iter().find(|link| &*link.original_text == broken_link.reference) - { - Some((link.href.as_str().into(), link.new_text.as_str().into())) - } else { - None - } + links + .iter() + .find(|link| &*link.original_text == broken_link.reference) + .map(|link| (link.href.as_str().into(), link.new_text.as_str().into())) }; let p = Parser::new_with_broken_link_callback(md, summary_opts(), Some(&mut replacer)); @@ -1171,13 +1166,10 @@ fn markdown_summary_with_limit( } let mut replacer = |broken_link: BrokenLink<'_>| { - if let Some(link) = - link_names.iter().find(|link| &*link.original_text == broken_link.reference) - { - Some((link.href.as_str().into(), link.new_text.as_str().into())) - } else { - None - } + link_names + .iter() + .find(|link| &*link.original_text == broken_link.reference) + .map(|link| (link.href.as_str().into(), link.new_text.as_str().into())) }; let p = Parser::new_with_broken_link_callback(md, summary_opts(), Some(&mut replacer)); @@ -1412,7 +1404,7 @@ crate fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec { // The ending of the offset goes too far sometime so we reduce it by one in // these cases. - if offset.end > offset.start && md.get(offset.end..=offset.end) == Some(&"\n") { + if offset.end > offset.start && md.get(offset.end..=offset.end) == Some("\n") { ( LangString::default(), offset.start, diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index 9c05c80d55..d12667c9e5 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -1,14 +1,13 @@ +use std::collections::hash_map::Entry; use std::collections::BTreeMap; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashMap; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::Symbol; use serde::ser::{Serialize, SerializeStruct, Serializer}; use crate::clean; -use crate::clean::types::{ - FnDecl, FnRetTy, GenericBound, Generics, GetDefId, Type, WherePredicate, -}; +use crate::clean::types::{FnDecl, FnRetTy, GenericBound, Generics, Type, WherePredicate}; use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; use crate::html::markdown::short_markdown_summary; @@ -27,7 +26,6 @@ crate enum ExternalLocation { /// Builds the search index from the collected metadata crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt<'tcx>) -> String { let mut defid_to_pathid = FxHashMap::default(); - let mut crate_items = Vec::with_capacity(cache.search_index.len()); let mut crate_paths = vec![]; // Attach all orphan items to the type's definition if the type @@ -36,7 +34,7 @@ crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt< if let Some(&(ref fqp, _)) = cache.paths.get(&did) { let desc = item .doc_value() - .map_or_else(String::new, |s| short_markdown_summary(&s, &item.link_names(&cache))); + .map_or_else(String::new, |s| short_markdown_summary(&s, &item.link_names(cache))); cache.search_index.push(IndexItem { ty: item.type_(), name: item.name.unwrap().to_string(), @@ -44,7 +42,7 @@ crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt< desc, parent: Some(did), parent_idx: None, - search_type: get_index_search_type(&item, tcx), + search_type: get_index_search_type(item, tcx, cache), aliases: item.attrs.get_doc_aliases(), }); } @@ -53,7 +51,7 @@ crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt< let crate_doc = krate .module .doc_value() - .map_or_else(String::new, |s| short_markdown_summary(&s, &krate.module.link_names(&cache))); + .map_or_else(String::new, |s| short_markdown_summary(&s, &krate.module.link_names(cache))); let Cache { ref mut search_index, ref paths, .. } = *cache; @@ -72,41 +70,44 @@ crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt< // Set up alias indexes. for (i, item) in search_index.iter().enumerate() { for alias in &item.aliases[..] { - aliases.entry(alias.to_lowercase()).or_insert(Vec::new()).push(i); + aliases.entry(alias.as_str().to_lowercase()).or_default().push(i); } } // Reduce `DefId` in paths into smaller sequential numbers, // and prune the paths that do not appear in the index. - let mut lastpath = String::new(); + let mut lastpath = ""; let mut lastpathid = 0usize; - for item in search_index { - item.parent_idx = item.parent.and_then(|defid| { - if defid_to_pathid.contains_key(&defid) { - defid_to_pathid.get(&defid).copied() - } else { - let pathid = lastpathid; - defid_to_pathid.insert(defid, pathid); - lastpathid += 1; + let crate_items: Vec<&IndexItem> = search_index + .iter_mut() + .map(|item| { + item.parent_idx = item.parent.and_then(|defid| match defid_to_pathid.entry(defid) { + Entry::Occupied(entry) => Some(*entry.get()), + Entry::Vacant(entry) => { + let pathid = lastpathid; + entry.insert(pathid); + lastpathid += 1; - if let Some(&(ref fqp, short)) = paths.get(&defid) { - crate_paths.push((short, fqp.last().unwrap().clone())); - Some(pathid) - } else { - None + if let Some(&(ref fqp, short)) = paths.get(&defid) { + crate_paths.push((short, fqp.last().unwrap().clone())); + Some(pathid) + } else { + None + } } + }); + + // Omit the parent path if it is same to that of the prior item. + if lastpath == &item.path { + item.path.clear(); + } else { + lastpath = &item.path; } - }); - // Omit the parent path if it is same to that of the prior item. - if lastpath == item.path { - item.path.clear(); - } else { - lastpath = item.path.clone(); - } - crate_items.push(&*item); - } + &*item + }) + .collect(); struct CrateData<'a> { doc: String, @@ -174,7 +175,7 @@ crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt< // Collect the index into a string format!( r#""{}":{}"#, - krate.name, + krate.name(tcx), serde_json::to_string(&CrateData { doc: crate_doc, items: crate_items, @@ -193,39 +194,31 @@ crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt< crate fn get_index_search_type<'tcx>( item: &clean::Item, tcx: TyCtxt<'tcx>, + cache: &Cache, ) -> Option { - let (all_types, ret_types) = match *item.kind { - clean::FunctionItem(ref f) => get_all_types(&f.generics, &f.decl, tcx), - clean::MethodItem(ref m, _) => get_all_types(&m.generics, &m.decl, tcx), - clean::TyMethodItem(ref m) => get_all_types(&m.generics, &m.decl, tcx), + let (mut inputs, mut output) = match *item.kind { + clean::FunctionItem(ref f) => get_all_types(&f.generics, &f.decl, tcx, cache), + clean::MethodItem(ref m, _) => get_all_types(&m.generics, &m.decl, tcx, cache), + clean::TyMethodItem(ref m) => get_all_types(&m.generics, &m.decl, tcx, cache), _ => return None, }; - let inputs = all_types - .iter() - .map(|(ty, kind)| TypeWithKind::from((get_index_type(&ty), *kind))) - .filter(|a| a.ty.name.is_some()) - .collect(); - let output = ret_types - .iter() - .map(|(ty, kind)| TypeWithKind::from((get_index_type(&ty), *kind))) - .filter(|a| a.ty.name.is_some()) - .collect::>(); - let output = if output.is_empty() { None } else { Some(output) }; + inputs.retain(|a| a.ty.name.is_some()); + output.retain(|a| a.ty.name.is_some()); Some(IndexItemFunctionType { inputs, output }) } -fn get_index_type(clean_type: &clean::Type) -> RenderType { +fn get_index_type(clean_type: &clean::Type, generics: Vec) -> RenderType { RenderType { name: get_index_type_name(clean_type, true).map(|s| s.as_str().to_ascii_lowercase()), - generics: get_generics(clean_type), + generics: if generics.is_empty() { None } else { Some(generics) }, } } fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option { match *clean_type { - clean::ResolvedPath { ref path, .. } => { + clean::Type::Path { ref path, .. } => { let path_segment = path.segments.last().unwrap(); Some(path_segment.name) } @@ -248,59 +241,109 @@ fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option } } -/// Return a list of generic parameters for use in the search index. -/// -/// This function replaces bounds with types, so that `T where T: Debug` just becomes `Debug`. -/// It does return duplicates, and that's intentional, since search queries like `Result` -/// are supposed to match only results where both parameters are `usize`. -fn get_generics(clean_type: &clean::Type) -> Option> { - clean_type.generics().and_then(|types| { - let r = types - .iter() - .filter_map(|t| { - get_index_type_name(t, false).map(|name| name.as_str().to_ascii_lowercase()) - }) - .collect::>(); - if r.is_empty() { None } else { Some(r) } - }) -} - /// The point of this function is to replace bounds with types. /// /// i.e. `[T, U]` when you have the following bounds: `T: Display, U: Option` will return -/// `[Display, Option]` (we just returns the list of the types, we don't care about the -/// wrapped types in here). +/// `[Display, Option]`. If a type parameter has no trait bound, it is discarded. +/// +/// Important note: It goes through generics recursively. So if you have +/// `T: Option>`, it'll go into `Option` and then into `Result`. crate fn get_real_types<'tcx>( generics: &Generics, arg: &Type, tcx: TyCtxt<'tcx>, - recurse: i32, - res: &mut FxHashSet<(Type, ItemType)>, -) -> usize { - fn insert(res: &mut FxHashSet<(Type, ItemType)>, tcx: TyCtxt<'_>, ty: Type) -> usize { - if let Some(kind) = ty.def_id().map(|did| tcx.def_kind(did).into()) { - res.insert((ty, kind)); - 1 + recurse: usize, + res: &mut Vec, + cache: &Cache, +) { + fn insert_ty( + res: &mut Vec, + tcx: TyCtxt<'_>, + ty: Type, + mut generics: Vec, + _cache: &Cache, + ) { + let is_full_generic = ty.is_full_generic(); + + if is_full_generic { + if generics.is_empty() { + // This is a type parameter with no trait bounds (for example: `T` in + // `fn f(p: T)`, so not useful for the rustdoc search because we would end up + // with an empty type with an empty name. Let's just discard it. + return; + } else if generics.len() == 1 { + // In this case, no need to go through an intermediate state if the type parameter + // contains only one trait bound. + // + // For example: + // + // `fn foo(r: Option) {}` + // + // In this case, it would contain: + // + // ``` + // [{ + // name: "option", + // generics: [{ + // name: "", + // generics: [ + // name: "Display", + // generics: [] + // }] + // }] + // }] + // ``` + // + // After removing the intermediate (unnecessary) type parameter, it'll become: + // + // ``` + // [{ + // name: "option", + // generics: [{ + // name: "Display", + // generics: [] + // }] + // }] + // ``` + // + // To be noted that it can work if there is ONLY ONE trait bound, otherwise we still + // need to keep it as is! + res.push(generics.pop().unwrap()); + return; + } + } + let mut index_ty = get_index_type(&ty, generics); + if index_ty.name.as_ref().map(|s| s.is_empty()).unwrap_or(true) { + return; + } + if is_full_generic { + // We remove the name of the full generic because we have no use for it. + index_ty.name = Some(String::new()); + res.push(TypeWithKind::from((index_ty, ItemType::Generic))); + } else if let Some(kind) = ty.def_id_no_primitives().map(|did| tcx.def_kind(did).into()) { + res.push(TypeWithKind::from((index_ty, kind))); } else if ty.is_primitive() { // This is a primitive, let's store it as such. - res.insert((ty, ItemType::Primitive)); - 1 - } else { - 0 + res.push(TypeWithKind::from((index_ty, ItemType::Primitive))); } } if recurse >= 10 { // FIXME: remove this whole recurse thing when the recursion bug is fixed - return 0; + return; } - let mut nb_added = 0; - if let &Type::Generic(arg_s) = arg { + // If this argument is a type parameter and not a trait bound or a type, we need to look + // for its bounds. + if let Type::Generic(arg_s) = *arg { + // First we check if the bounds are in a `where` predicate... if let Some(where_pred) = generics.where_predicates.iter().find(|g| match g { - WherePredicate::BoundPredicate { ty, .. } => ty.def_id() == arg.def_id(), + WherePredicate::BoundPredicate { ty, .. } => { + ty.def_id_no_primitives() == arg.def_id_no_primitives() + } _ => false, }) { + let mut ty_generics = Vec::new(); let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]); for bound in bounds.iter() { if let GenericBound::TraitBound(poly_trait, _) = bound { @@ -309,41 +352,45 @@ crate fn get_real_types<'tcx>( continue; } if let Some(ty) = x.get_type() { - let adds = get_real_types(generics, &ty, tcx, recurse + 1, res); - nb_added += adds; - if adds == 0 && !ty.is_full_generic() { - nb_added += insert(res, tcx, ty); - } + get_real_types( + generics, + &ty, + tcx, + recurse + 1, + &mut ty_generics, + cache, + ); } } } } + insert_ty(res, tcx, arg.clone(), ty_generics, cache); } + // Otherwise we check if the trait bounds are "inlined" like `T: Option`... if let Some(bound) = generics.params.iter().find(|g| g.is_type() && g.name == arg_s) { + let mut ty_generics = Vec::new(); for bound in bound.get_bounds().unwrap_or(&[]) { if let Some(path) = bound.get_trait_path() { - let ty = Type::ResolvedPath { did: path.def_id(), path }; - let adds = get_real_types(generics, &ty, tcx, recurse + 1, res); - nb_added += adds; - if adds == 0 && !ty.is_full_generic() { - nb_added += insert(res, tcx, ty); - } + let ty = Type::Path { path }; + get_real_types(generics, &ty, tcx, recurse + 1, &mut ty_generics, cache); } } + insert_ty(res, tcx, arg.clone(), ty_generics, cache); } } else { - nb_added += insert(res, tcx, arg.clone()); - if let Some(gens) = arg.generics() { - for gen in gens.iter() { - if gen.is_full_generic() { - nb_added += get_real_types(generics, gen, tcx, recurse + 1, res); - } else { - nb_added += insert(res, tcx, (*gen).clone()); - } + // This is not a type parameter. So for example if we have `T, U: Option`, and we're + // looking at `Option`, we enter this "else" condition, otherwise if it's `T`, we don't. + // + // So in here, we can add it directly and look for its own type parameters (so for `Option`, + // we will look for them but not for `T`). + let mut ty_generics = Vec::new(); + if let Some(arg_generics) = arg.generics() { + for gen in arg_generics.iter() { + get_real_types(generics, gen, tcx, recurse + 1, &mut ty_generics, cache); } } + insert_ty(res, tcx, arg.clone(), ty_generics, cache); } - nb_added } /// Return the full list of types when bounds have been resolved. @@ -354,35 +401,38 @@ crate fn get_all_types<'tcx>( generics: &Generics, decl: &FnDecl, tcx: TyCtxt<'tcx>, -) -> (Vec<(Type, ItemType)>, Vec<(Type, ItemType)>) { - let mut all_types = FxHashSet::default(); + cache: &Cache, +) -> (Vec, Vec) { + let mut all_types = Vec::new(); for arg in decl.inputs.values.iter() { if arg.type_.is_self_type() { continue; } - let mut args = FxHashSet::default(); - get_real_types(generics, &arg.type_, tcx, 0, &mut args); + let mut args = Vec::new(); + get_real_types(generics, &arg.type_, tcx, 0, &mut args, cache); if !args.is_empty() { all_types.extend(args); } else { - if let Some(kind) = arg.type_.def_id().map(|did| tcx.def_kind(did).into()) { - all_types.insert((arg.type_.clone(), kind)); + if let Some(kind) = arg.type_.def_id_no_primitives().map(|did| tcx.def_kind(did).into()) + { + all_types.push(TypeWithKind::from((get_index_type(&arg.type_, vec![]), kind))); } } } - let ret_types = match decl.output { + let mut ret_types = Vec::new(); + match decl.output { FnRetTy::Return(ref return_type) => { - let mut ret = FxHashSet::default(); - get_real_types(generics, &return_type, tcx, 0, &mut ret); - if ret.is_empty() { - if let Some(kind) = return_type.def_id().map(|did| tcx.def_kind(did).into()) { - ret.insert((return_type.clone(), kind)); + get_real_types(generics, return_type, tcx, 0, &mut ret_types, cache); + if ret_types.is_empty() { + if let Some(kind) = + return_type.def_id_no_primitives().map(|did| tcx.def_kind(did).into()) + { + ret_types.push(TypeWithKind::from((get_index_type(return_type, vec![]), kind))); } } - ret.into_iter().collect() } - _ => Vec::new(), + _ => {} }; - (all_types.into_iter().collect(), ret_types) + (all_types, ret_types) } diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 011d3cfcf7..069862efde 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -6,7 +6,7 @@ use std::rc::Rc; use std::sync::mpsc::{channel, Receiver}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_hir::def_id::LOCAL_CRATE; +use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_span::edition::Edition; @@ -22,8 +22,7 @@ use super::{ BASIC_KEYWORDS, }; -use crate::clean; -use crate::clean::ExternalCrate; +use crate::clean::{self, ExternalCrate}; use crate::config::RenderOptions; use crate::docfs::{DocFS, PathError}; use crate::error::Error; @@ -34,6 +33,8 @@ use crate::html::escape::Escape; use crate::html::format::Buffer; use crate::html::markdown::{self, plain_text_summary, ErrorCodes, IdMap}; use crate::html::{layout, sources}; +use crate::scrape_examples::AllCallLocations; +use crate::try_err; /// Major driving force in all rustdoc rendering. This contains information /// about where in the tree-like hierarchy rendering is occurring and controls @@ -53,6 +54,9 @@ crate struct Context<'tcx> { /// real location of an item. This is used to allow external links to /// publicly reused items to redirect to the right location. pub(super) render_redirect_pages: bool, + /// Tracks section IDs for `Deref` targets so they match in both the main + /// body and the sidebar. + pub(super) deref_id_map: RefCell>, /// The map used to ensure all generated 'id=' attributes are unique. pub(super) id_map: RefCell, /// Shared mutable state. @@ -69,7 +73,7 @@ crate struct Context<'tcx> { // `Context` is cloned a lot, so we don't want the size to grow unexpectedly. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Context<'_>, 104); +rustc_data_structures::static_assert_size!(Context<'_>, 144); /// Shared mutable state used in [`Context`] and elsewhere. crate struct SharedContext<'tcx> { @@ -123,6 +127,8 @@ crate struct SharedContext<'tcx> { crate span_correspondance_map: FxHashMap, /// The [`Cache`] used during rendering. crate cache: Cache, + + crate call_locations: AllCallLocations, } impl SharedContext<'_> { @@ -157,7 +163,7 @@ impl<'tcx> Context<'tcx> { } pub(super) fn sess(&self) -> &'tcx Session { - &self.shared.tcx.sess + self.shared.tcx.sess } pub(super) fn derive_id(&self, id: String) -> String { @@ -185,7 +191,7 @@ impl<'tcx> Context<'tcx> { }; title.push_str(" - Rust"); let tyname = it.type_(); - let desc = it.doc_value().as_ref().map(|doc| plain_text_summary(&doc)); + let desc = it.doc_value().as_ref().map(|doc| plain_text_summary(doc)); let desc = if let Some(desc) = desc { desc } else if it.is_crate() { @@ -291,10 +297,10 @@ impl<'tcx> Context<'tcx> { /// may happen, for example, with externally inlined items where the source /// of their crate documentation isn't known. pub(super) fn src_href(&self, item: &clean::Item) -> Option { - self.href_from_span(item.span(self.tcx())) + self.href_from_span(item.span(self.tcx()), true) } - crate fn href_from_span(&self, span: clean::Span) -> Option { + crate fn href_from_span(&self, span: clean::Span, with_lines: bool) -> Option { if span.is_dummy() { return None; } @@ -341,16 +347,26 @@ impl<'tcx> Context<'tcx> { (&*symbol, &path) }; - let loline = span.lo(self.sess()).line; - let hiline = span.hi(self.sess()).line; - let lines = - if loline == hiline { loline.to_string() } else { format!("{}-{}", loline, hiline) }; + let anchor = if with_lines { + let loline = span.lo(self.sess()).line; + let hiline = span.hi(self.sess()).line; + format!( + "#{}", + if loline == hiline { + loline.to_string() + } else { + format!("{}-{}", loline, hiline) + } + ) + } else { + "".to_string() + }; Some(format!( - "{root}src/{krate}/{path}#{lines}", + "{root}src/{krate}/{path}{anchor}", root = Escape(&root), krate = krate, path = path, - lines = lines + anchor = anchor )) } } @@ -388,10 +404,11 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { generate_redirect_map, show_type_layout, generate_link_to_definition, + call_locations, .. } = options; - let src_root = match krate.src { + let src_root = match krate.src(tcx) { FileName::Real(ref p) => match p.local_path_if_available().parent() { Some(p) => p.to_path_buf(), None => PathBuf::new(), @@ -402,16 +419,17 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { let mut playground = None; if let Some(url) = playground_url { playground = - Some(markdown::Playground { crate_name: Some(krate.name.to_string()), url }); + Some(markdown::Playground { crate_name: Some(krate.name(tcx).to_string()), url }); } let mut layout = layout::Layout { logo: String::new(), favicon: String::new(), external_html, default_settings, - krate: krate.name.to_string(), + krate: krate.name(tcx).to_string(), css_file_extension: extension_css, generate_search_filter, + scrape_examples_extension: !call_locations.is_empty(), }; let mut issue_tracker_base_url = None; let mut include_sources = true; @@ -429,7 +447,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { } (sym::html_playground_url, Some(s)) => { playground = Some(markdown::Playground { - crate_name: Some(krate.name.to_string()), + crate_name: Some(krate.name(tcx).to_string()), url: s.to_string(), }); } @@ -443,9 +461,9 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { } } - let (mut krate, local_sources, matches) = collect_spans_and_sources( + let (local_sources, matches) = collect_spans_and_sources( tcx, - krate, + &krate, &src_root, include_sources, generate_link_to_definition, @@ -474,6 +492,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { templates, span_correspondance_map: matches, cache, + call_locations, }; // Add the default themes to the `Vec` of stylepaths @@ -497,12 +516,13 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { dst, render_redirect_pages: false, id_map: RefCell::new(id_map), + deref_id_map: RefCell::new(FxHashMap::default()), shared: Rc::new(scx), include_sources, }; if emit_crate { - krate = sources::render(&mut cx, krate)?; + sources::render(&mut cx, &krate)?; } // Build our search index @@ -520,6 +540,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { current: self.current.clone(), dst: self.dst.clone(), render_redirect_pages: self.render_redirect_pages, + deref_id_map: RefCell::new(FxHashMap::default()), id_map: RefCell::new(IdMap::new()), shared: Rc::clone(&self.shared), include_sources: self.include_sources, diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 2898da1cbf..20a200f048 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -34,30 +34,36 @@ mod span_map; mod templates; mod write_shared; -crate use context::*; -crate use span_map::{collect_spans_and_sources, LinkFromSrc}; +crate use self::context::*; +crate use self::span_map::{collect_spans_and_sources, LinkFromSrc}; use std::collections::VecDeque; use std::default::Default; use std::fmt; +use std::fs; +use std::iter::Peekable; use std::path::PathBuf; use std::str; use std::string::ToString; use rustc_ast_pretty::pprust; use rustc_attr::{ConstStability, Deprecation, StabilityLevel}; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir as hir; use rustc_hir::def::CtorKind; use rustc_hir::def_id::DefId; use rustc_hir::Mutability; use rustc_middle::middle::stability; +use rustc_middle::ty; use rustc_middle::ty::TyCtxt; -use rustc_span::symbol::{kw, sym, Symbol}; +use rustc_span::{ + symbol::{kw, sym, Symbol}, + BytePos, FileName, RealFileName, +}; use serde::ser::SerializeSeq; use serde::{Serialize, Serializer}; -use crate::clean::{self, GetDefId, ItemId, RenderedLink, SelfTy}; +use crate::clean::{self, ItemId, RenderedLink, SelfTy}; use crate::docfs::PathError; use crate::error::Error; use crate::formats::cache::Cache; @@ -68,7 +74,11 @@ use crate::html::format::{ href, print_abi_with_space, print_constness_with_space, print_default_space, print_generic_bounds, print_where_clause, Buffer, HrefError, PrintWithSpace, }; +use crate::html::highlight; use crate::html::markdown::{HeadingOffset, Markdown, MarkdownHtml, MarkdownSummaryLine}; +use crate::html::sources; +use crate::scrape_examples::{CallData, CallLocation}; +use crate::try_none; /// A pair of name and its optional document. crate type NameDoc = (String, Option); @@ -93,21 +103,21 @@ crate struct IndexItem { crate parent: Option, crate parent_idx: Option, crate search_type: Option, - crate aliases: Box<[String]>, + crate aliases: Box<[Symbol]>, } /// A type used for the search index. #[derive(Debug)] crate struct RenderType { name: Option, - generics: Option>, + generics: Option>, } /// Full type of functions/methods in the search index. #[derive(Debug)] crate struct IndexItemFunctionType { inputs: Vec, - output: Option>, + output: Vec, } impl Serialize for IndexItemFunctionType { @@ -116,21 +126,16 @@ impl Serialize for IndexItemFunctionType { S: Serializer, { // If we couldn't figure out a type, just write `null`. - let mut iter = self.inputs.iter(); - if match self.output { - Some(ref output) => iter.chain(output.iter()).any(|ref i| i.ty.name.is_none()), - None => iter.any(|ref i| i.ty.name.is_none()), - } { + let has_missing = self.inputs.iter().chain(self.output.iter()).any(|i| i.ty.name.is_none()); + if has_missing { serializer.serialize_none() } else { let mut seq = serializer.serialize_seq(None)?; seq.serialize_element(&self.inputs)?; - if let Some(output) = &self.output { - if output.len() > 1 { - seq.serialize_element(&output)?; - } else { - seq.serialize_element(&output[0])?; - } + match self.output.as_slice() { + [] => {} + [one] => seq.serialize_element(one)?, + all => seq.serialize_element(all)?, } seq.end() } @@ -585,6 +590,14 @@ fn document_full_inner( render_markdown(w, cx, &s, item.links(cx), heading_offset); } } + + let kind = match &*item.kind { + clean::ItemKind::StrippedItem(box kind) | kind => kind, + }; + + if let clean::ItemKind::FunctionItem(..) | clean::ItemKind::MethodItem(..) = kind { + render_call_locations(w, cx, item); + } } /// Add extra information about an item such as: @@ -669,7 +682,7 @@ fn short_item_info( // Render unstable items. But don't render "rustc_private" crates (internal compiler crates). // Those crates are permanently unstable so it makes no sense to render "unstable" everywhere. - if let Some((StabilityLevel::Unstable { reason, issue, .. }, feature)) = item + if let Some((StabilityLevel::Unstable { reason: _, issue, .. }, feature)) = item .stability(cx.tcx()) .as_ref() .filter(|stab| stab.feature != sym::rustc_private) @@ -689,22 +702,6 @@ fn short_item_info( message.push_str(&format!(" ({})", feature)); - if let Some(unstable_reason) = reason { - let mut ids = cx.id_map.borrow_mut(); - message = format!( - "
{}{}
", - message, - MarkdownHtml( - &unstable_reason.as_str(), - &mut ids, - error_codes, - cx.shared.edition(), - &cx.shared.playground, - ) - .into_string() - ); - } - extra_info.push(format!("
{}
", message)); } @@ -890,7 +887,7 @@ fn render_assoc_item( AssocItemLink::GotoSource(did, provided_methods) => { // We're creating a link from an impl-item to the corresponding // trait-item and need to map the anchored type accordingly. - let ty = if provided_methods.contains(&name) { + let ty = if provided_methods.contains(name) { ItemType::Method } else { ItemType::TyMethod @@ -949,7 +946,7 @@ fn render_assoc_item( name = name, generics = g.print(cx), decl = d.full_print(header_len, indent, header.asyncness, cx), - notable_traits = notable_traits_decl(&d, cx), + notable_traits = notable_traits_decl(d, cx), where_clause = print_where_clause(g, cx, indent, end_newline), ) } @@ -992,7 +989,7 @@ fn attributes(it: &clean::Item) -> Vec { .iter() .filter_map(|attr| { if ALLOWED_ATTRIBUTES.contains(&attr.name_or_empty()) { - Some(pprust::attribute_to_string(&attr).replace("\n", "").replace(" ", " ")) + Some(pprust::attribute_to_string(attr).replace("\n", "").replace(" ", " ")) } else { None } @@ -1025,7 +1022,7 @@ enum AssocItemLink<'a> { impl<'a> AssocItemLink<'a> { fn anchor(&self, id: &'a str) -> Self { match *self { - AssocItemLink::Anchor(_) => AssocItemLink::Anchor(Some(&id)), + AssocItemLink::Anchor(_) => AssocItemLink::Anchor(Some(id)), ref other => *other, } } @@ -1037,6 +1034,19 @@ fn render_assoc_items( containing_item: &clean::Item, it: DefId, what: AssocItemRender<'_>, +) { + let mut derefs = FxHashSet::default(); + derefs.insert(it); + render_assoc_items_inner(w, cx, containing_item, it, what, &mut derefs) +} + +fn render_assoc_items_inner( + w: &mut Buffer, + cx: &Context<'_>, + containing_item: &clean::Item, + it: DefId, + what: AssocItemRender<'_>, + derefs: &mut FxHashSet, ) { info!("Documenting associated items of {:?}", containing_item.name); let cache = cx.cache(); @@ -1046,9 +1056,10 @@ fn render_assoc_items( }; let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none()); if !non_trait.is_empty() { + let mut tmp_buf = Buffer::empty_from(w); let render_mode = match what { AssocItemRender::All => { - w.write_str( + tmp_buf.write_str( "

\ Implementations\

", @@ -1056,21 +1067,28 @@ fn render_assoc_items( RenderMode::Normal } AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => { + let id = + cx.derive_id(small_url_encode(format!("deref-methods-{:#}", type_.print(cx)))); + if let Some(def_id) = type_.def_id(cx.cache()) { + cx.deref_id_map.borrow_mut().insert(def_id, id.clone()); + } write!( - w, - "

\ + tmp_buf, + "

\ Methods from {trait_}<Target = {type_}>\ - \ + \

", + id = id, trait_ = trait_.print(cx), type_ = type_.print(cx), ); RenderMode::ForDeref { mut_: deref_mut_ } } }; + let mut impls_buf = Buffer::empty_from(w); for i in &non_trait { render_impl( - w, + &mut impls_buf, cx, i, containing_item, @@ -1087,24 +1105,33 @@ fn render_assoc_items( }, ); } + if !impls_buf.is_empty() { + w.push_buffer(tmp_buf); + w.push_buffer(impls_buf); + } } - if let AssocItemRender::DerefFor { .. } = what { - return; - } + if !traits.is_empty() { let deref_impl = traits.iter().find(|t| t.trait_did() == cx.tcx().lang_items().deref_trait()); if let Some(impl_) = deref_impl { let has_deref_mut = traits.iter().any(|t| t.trait_did() == cx.tcx().lang_items().deref_mut_trait()); - render_deref_methods(w, cx, impl_, containing_item, has_deref_mut); + render_deref_methods(w, cx, impl_, containing_item, has_deref_mut, derefs); + } + + // If we were already one level into rendering deref methods, we don't want to render + // anything after recursing into any further deref methods above. + if let AssocItemRender::DerefFor { .. } = what { + return; } + let (synthetic, concrete): (Vec<&&Impl>, Vec<&&Impl>) = - traits.iter().partition(|t| t.inner_impl().synthetic); + traits.iter().partition(|t| t.inner_impl().kind.is_auto()); let (blanket_impl, concrete): (Vec<&&Impl>, _) = - concrete.into_iter().partition(|t| t.inner_impl().blanket_impl.is_some()); + concrete.into_iter().partition(|t| t.inner_impl().kind.is_blanket()); - let mut impls = Buffer::empty_from(&w); + let mut impls = Buffer::empty_from(w); render_impls(cx, &mut impls, &concrete, containing_item); let impls = impls.into_inner(); if !impls.is_empty() { @@ -1150,6 +1177,7 @@ fn render_deref_methods( impl_: &Impl, container_item: &clean::Item, deref_mut: bool, + derefs: &mut FxHashSet, ) { let cache = cx.cache(); let deref_type = impl_.inner_impl().trait_.as_ref().unwrap(); @@ -1168,19 +1196,19 @@ fn render_deref_methods( debug!("Render deref methods for {:#?}, target {:#?}", impl_.inner_impl().for_, target); let what = AssocItemRender::DerefFor { trait_: deref_type, type_: real_target, deref_mut_: deref_mut }; - if let Some(did) = target.def_id_full(cache) { - if let Some(type_did) = impl_.inner_impl().for_.def_id_full(cache) { + if let Some(did) = target.def_id(cache) { + if let Some(type_did) = impl_.inner_impl().for_.def_id(cache) { // `impl Deref for S` - if did == type_did { + if did == type_did || !derefs.insert(did) { // Avoid infinite cycles return; } } - render_assoc_items(w, cx, container_item, did, what); + render_assoc_items_inner(w, cx, container_item, did, what, derefs); } else { if let Some(prim) = target.primitive_type() { if let Some(&did) = cache.primitive_locations.get(&prim) { - render_assoc_items(w, cx, container_item, did, what); + render_assoc_items_inner(w, cx, container_item, did, what, derefs); } } } @@ -1199,8 +1227,8 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) -> | SelfTy::SelfExplicit(clean::BorrowedRef { mutability, .. }) => { (mutability == Mutability::Mut, false, false) } - SelfTy::SelfExplicit(clean::ResolvedPath { did, .. }) => { - (false, Some(did) == tcx.lang_items().owned_box(), false) + SelfTy::SelfExplicit(clean::Type::Path { path }) => { + (false, Some(path.def_id()) == tcx.lang_items().owned_box(), false) } SelfTy::SelfValue => (false, false, true), _ => (false, false, false), @@ -1215,7 +1243,7 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) -> fn notable_traits_decl(decl: &clean::FnDecl, cx: &Context<'_>) -> String { let mut out = Buffer::html(); - if let Some(did) = decl.output.def_id_full(cx.cache()) { + if let Some(did) = decl.output.as_return().and_then(|t| t.def_id(cx.cache())) { if let Some(impls) = cx.cache().impls.get(&did) { for i in impls { let impl_ = i.inner_impl(); @@ -1317,7 +1345,7 @@ fn render_impl( && match render_mode { RenderMode::Normal => true, RenderMode::ForDeref { mut_: deref_mut_ } => { - should_render_item(&item, deref_mut_, cx.tcx()) + should_render_item(item, deref_mut_, cx.tcx()) } }; @@ -1550,7 +1578,7 @@ fn render_impl( &mut impl_items, cx, &t.trait_, - &i.inner_impl(), + i.inner_impl(), &i.impl_item, parent, render_mode, @@ -1970,7 +1998,9 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) { if let Some(impl_) = v.iter().find(|i| i.trait_did() == cx.tcx().lang_items().deref_trait()) { - sidebar_deref_methods(cx, out, impl_, v); + let mut derefs = FxHashSet::default(); + derefs.insert(did); + sidebar_deref_methods(cx, out, impl_, v, &mut derefs); } let format_impls = |impls: Vec<&Impl>| { @@ -1983,12 +2013,12 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) { let i_display = format!("{:#}", i.print(cx)); let out = Escape(&i_display); let encoded = small_url_encode(format!("{:#}", i.print(cx))); - let generated = format!( - "{}{}", - encoded, - if it.inner_impl().negative_polarity { "!" } else { "" }, - out - ); + let prefix = match it.inner_impl().polarity { + ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "", + ty::ImplPolarity::Negative => "!", + }; + let generated = + format!("{}{}", encoded, prefix, out); if links.insert(generated.clone()) { Some(generated) } else { None } } else { None @@ -2008,10 +2038,9 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) { }; let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) = - v.iter().partition::, _>(|i| i.inner_impl().synthetic); - let (blanket_impl, concrete): (Vec<&Impl>, Vec<&Impl>) = concrete - .into_iter() - .partition::, _>(|i| i.inner_impl().blanket_impl.is_some()); + v.iter().partition::, _>(|i| i.inner_impl().kind.is_auto()); + let (blanket_impl, concrete): (Vec<&Impl>, Vec<&Impl>) = + concrete.into_iter().partition::, _>(|i| i.inner_impl().kind.is_blanket()); let concrete_format = format_impls(concrete); let synthetic_format = format_impls(synthetic); @@ -2044,7 +2073,13 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) { } } -fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &Vec) { +fn sidebar_deref_methods( + cx: &Context<'_>, + out: &mut Buffer, + impl_: &Impl, + v: &[Impl], + derefs: &mut FxHashSet, +) { let c = cx.cache(); debug!("found Deref: {:?}", impl_); @@ -2058,10 +2093,10 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V }) { debug!("found target, real_target: {:?} {:?}", target, real_target); - if let Some(did) = target.def_id_full(c) { - if let Some(type_did) = impl_.inner_impl().for_.def_id_full(c) { + if let Some(did) = target.def_id(c) { + if let Some(type_did) = impl_.inner_impl().for_.def_id(c) { // `impl Deref for S` - if did == type_did { + if did == type_did || !derefs.insert(did) { // Avoid infinite cycles return; } @@ -2069,7 +2104,7 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V } let deref_mut = v.iter().any(|i| i.trait_did() == cx.tcx().lang_items().deref_mut_trait()); let inner_impl = target - .def_id_full(c) + .def_id(c) .or_else(|| { target.primitive_type().and_then(|prim| c.primitive_locations.get(&prim).cloned()) }) @@ -2085,9 +2120,17 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V }) .collect::>(); if !ret.is_empty() { + let map; + let id = if let Some(target_def_id) = real_target.def_id(c) { + map = cx.deref_id_map.borrow(); + map.get(&target_def_id).expect("Deref section without derived id") + } else { + "deref-methods" + }; write!( out, - "

Methods from {}<Target={}>

", + "

Methods from {}<Target={}>

", + id, Escape(&format!("{:#}", impl_.inner_impl().trait_.as_ref().unwrap().print(cx))), Escape(&format!("{:#}", real_target.print(cx))), ); @@ -2100,6 +2143,21 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V out.push_str(""); } } + + // Recurse into any further impls that might exist for `target` + if let Some(target_did) = target.def_id(c) { + if let Some(target_impls) = c.impls.get(&target_did) { + if let Some(target_deref_impl) = target_impls.iter().find(|i| { + i.inner_impl() + .trait_ + .as_ref() + .map(|t| Some(t.def_id()) == cx.tcx().lang_items().deref_trait()) + .unwrap_or(false) + }) { + sidebar_deref_methods(cx, out, target_deref_impl, target_impls, derefs); + } + } + } } } @@ -2143,16 +2201,14 @@ fn get_id_for_impl_on_foreign_type( fn extract_for_impl_name(item: &clean::Item, cx: &Context<'_>) -> Option<(String, String)> { match *item.kind { clean::ItemKind::ImplItem(ref i) => { - if let Some(ref trait_) = i.trait_ { + i.trait_.as_ref().map(|trait_| { // Alternative format produces no URLs, // so this parameter does nothing. - Some(( + ( format!("{:#}", i.for_.print(cx)), get_id_for_impl_on_foreign_type(&i.for_, trait_, cx), - )) - } else { - None - } + ) + }) } _ => None, } @@ -2232,10 +2288,7 @@ fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean let mut res = implementors .iter() .filter(|i| { - i.inner_impl() - .for_ - .def_id_full(cache) - .map_or(false, |d| !cache.paths.contains_key(&d)) + i.inner_impl().for_.def_id(cache).map_or(false, |d| !cache.paths.contains_key(&d)) }) .filter_map(|i| extract_for_impl_name(&i.impl_item, cx)) .collect::>(); @@ -2327,9 +2380,10 @@ fn sidebar_enum(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, e: &clean: let mut variants = e .variants .iter() - .filter_map(|v| match v.name { - Some(ref name) => Some(format!("{name}", name = name)), - _ => None, + .filter_map(|v| { + v.name + .as_ref() + .map(|name| format!("{name}", name = name)) }) .collect::>(); if !variants.is_empty() { @@ -2375,6 +2429,7 @@ fn item_ty_to_strs(ty: ItemType) -> (&'static str, &'static str) { ItemType::ProcAttribute => ("attributes", "Attribute Macros"), ItemType::ProcDerive => ("derives", "Derive Macros"), ItemType::TraitAlias => ("trait-aliases", "Trait aliases"), + ItemType::Generic => unreachable!(), } } @@ -2465,7 +2520,7 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec { } match ty { - clean::Type::ResolvedPath { did, .. } => process_path(did), + clean::Type::Path { path } => process_path(path.def_id()), clean::Type::Tuple(tys) => { work.extend(tys.into_iter()); } @@ -2490,3 +2545,228 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec { } out } + +const MAX_FULL_EXAMPLES: usize = 5; +const NUM_VISIBLE_LINES: usize = 10; + +/// Generates the HTML for example call locations generated via the --scrape-examples flag. +fn render_call_locations(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item) { + let tcx = cx.tcx(); + let def_id = item.def_id.expect_def_id(); + let key = tcx.def_path_hash(def_id); + let call_locations = match cx.shared.call_locations.get(&key) { + Some(call_locations) => call_locations, + _ => { + return; + } + }; + + // Generate a unique ID so users can link to this section for a given method + let id = cx.id_map.borrow_mut().derive("scraped-examples"); + write!( + w, + "
\ + \ +
\ + Examples found in repository\ +
", + id = id + ); + + // Create a URL to a particular location in a reverse-dependency's source file + let link_to_loc = |call_data: &CallData, loc: &CallLocation| -> (String, String) { + let (line_lo, line_hi) = loc.call_expr.line_span; + let (anchor, title) = if line_lo == line_hi { + ((line_lo + 1).to_string(), format!("line {}", line_lo + 1)) + } else { + ( + format!("{}-{}", line_lo + 1, line_hi + 1), + format!("lines {}-{}", line_lo + 1, line_hi + 1), + ) + }; + let url = format!("{}{}#{}", cx.root_path(), call_data.url, anchor); + (url, title) + }; + + // Generate the HTML for a single example, being the title and code block + let write_example = |w: &mut Buffer, (path, call_data): (&PathBuf, &CallData)| -> bool { + let contents = match fs::read_to_string(&path) { + Ok(contents) => contents, + Err(err) => { + let span = item.span(tcx).inner(); + tcx.sess + .span_err(span, &format!("failed to read file {}: {}", path.display(), err)); + return false; + } + }; + + // To reduce file sizes, we only want to embed the source code needed to understand the example, not + // the entire file. So we find the smallest byte range that covers all items enclosing examples. + assert!(!call_data.locations.is_empty()); + let min_loc = + call_data.locations.iter().min_by_key(|loc| loc.enclosing_item.byte_span.0).unwrap(); + let byte_min = min_loc.enclosing_item.byte_span.0; + let line_min = min_loc.enclosing_item.line_span.0; + let max_loc = + call_data.locations.iter().max_by_key(|loc| loc.enclosing_item.byte_span.1).unwrap(); + let byte_max = max_loc.enclosing_item.byte_span.1; + let line_max = max_loc.enclosing_item.line_span.1; + + // The output code is limited to that byte range. + let contents_subset = &contents[(byte_min as usize)..(byte_max as usize)]; + + // The call locations need to be updated to reflect that the size of the program has changed. + // Specifically, the ranges are all subtracted by `byte_min` since that's the new zero point. + let (mut byte_ranges, line_ranges): (Vec<_>, Vec<_>) = call_data + .locations + .iter() + .map(|loc| { + let (byte_lo, byte_hi) = loc.call_expr.byte_span; + let (line_lo, line_hi) = loc.call_expr.line_span; + let byte_range = (byte_lo - byte_min, byte_hi - byte_min); + let line_range = (line_lo - line_min, line_hi - line_min); + let (line_url, line_title) = link_to_loc(call_data, loc); + + (byte_range, (line_range, line_url, line_title)) + }) + .unzip(); + + let (_, init_url, init_title) = &line_ranges[0]; + let needs_expansion = line_max - line_min > NUM_VISIBLE_LINES; + let locations_encoded = serde_json::to_string(&line_ranges).unwrap(); + + write!( + w, + "
\ +
\ + {name} ({title})\ +
\ +
", + expanded_cls = if needs_expansion { "" } else { "expanded" }, + name = call_data.display_name, + url = init_url, + title = init_title, + // The locations are encoded as a data attribute, so they can be read + // later by the JS for interactions. + locations = Escape(&locations_encoded) + ); + + if line_ranges.len() > 1 { + write!(w, r#" "#); + } + + if needs_expansion { + write!(w, r#""#); + } + + // Look for the example file in the source map if it exists, otherwise return a dummy span + let file_span = (|| { + let source_map = tcx.sess.source_map(); + let crate_src = tcx.sess.local_crate_source_file.as_ref()?; + let abs_crate_src = crate_src.canonicalize().ok()?; + let crate_root = abs_crate_src.parent()?.parent()?; + let rel_path = path.strip_prefix(crate_root).ok()?; + let files = source_map.files(); + let file = files.iter().find(|file| match &file.name { + FileName::Real(RealFileName::LocalPath(other_path)) => rel_path == other_path, + _ => false, + })?; + Some(rustc_span::Span::with_root_ctxt( + file.start_pos + BytePos(byte_min), + file.start_pos + BytePos(byte_max), + )) + })() + .unwrap_or(rustc_span::DUMMY_SP); + + // The root path is the inverse of Context::current + let root_path = vec!["../"; cx.current.len() - 1].join(""); + + let mut decoration_info = FxHashMap::default(); + decoration_info.insert("highlight focus", vec![byte_ranges.remove(0)]); + decoration_info.insert("highlight", byte_ranges); + + sources::print_src( + w, + contents_subset, + call_data.edition, + file_span, + cx, + &root_path, + Some(highlight::DecorationInfo(decoration_info)), + sources::SourceContext::Embedded { offset: line_min }, + ); + write!(w, "
"); + + true + }; + + // The call locations are output in sequence, so that sequence needs to be determined. + // Ideally the most "relevant" examples would be shown first, but there's no general algorithm + // for determining relevance. Instead, we prefer the smallest examples being likely the easiest to + // understand at a glance. + let ordered_locations = { + let sort_criterion = |(_, call_data): &(_, &CallData)| { + // Use the first location because that's what the user will see initially + let (lo, hi) = call_data.locations[0].enclosing_item.byte_span; + hi - lo + }; + + let mut locs = call_locations.into_iter().collect::>(); + locs.sort_by_key(sort_criterion); + locs + }; + + let mut it = ordered_locations.into_iter().peekable(); + + // An example may fail to write if its source can't be read for some reason, so this method + // continues iterating until a write suceeds + let write_and_skip_failure = |w: &mut Buffer, it: &mut Peekable<_>| { + while let Some(example) = it.next() { + if write_example(&mut *w, example) { + break; + } + } + }; + + // Write just one example that's visible by default in the method's description. + write_and_skip_failure(w, &mut it); + + // Then add the remaining examples in a hidden section. + if it.peek().is_some() { + write!( + w, + "
\ + \ + More examples\ + \ +
\ +
\ +
" + ); + + // Only generate inline code for MAX_FULL_EXAMPLES number of examples. Otherwise we could + // make the page arbitrarily huge! + for _ in 0..MAX_FULL_EXAMPLES { + write_and_skip_failure(w, &mut it); + } + + // For the remaining examples, generate a
    containing links to the source files. + if it.peek().is_some() { + write!(w, r#""); + } + + write!(w, "
"); + } + + write!(w, "
"); +} diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 739ea35dc3..1bdd6cbc1c 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -21,7 +21,7 @@ use super::{ render_impl, render_stability_since_raw, write_srclink, AssocItemLink, Context, ImplRenderingParameters, }; -use crate::clean::{self, GetDefId}; +use crate::clean; use crate::formats::item_type::ItemType; use crate::formats::{AssocItemRender, Impl, RenderMode}; use crate::html::escape::Escape; @@ -34,10 +34,10 @@ use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine}; use serde::Serialize; -const ITEM_TABLE_OPEN: &'static str = "
"; -const ITEM_TABLE_CLOSE: &'static str = "
"; -const ITEM_TABLE_ROW_OPEN: &'static str = "
"; -const ITEM_TABLE_ROW_CLOSE: &'static str = "
"; +const ITEM_TABLE_OPEN: &str = "
"; +const ITEM_TABLE_CLOSE: &str = "
"; +const ITEM_TABLE_ROW_OPEN: &str = "
"; +const ITEM_TABLE_ROW_CLOSE: &str = "
"; // A component in a `use` path, like `string` in std::string::ToString #[derive(Serialize)] @@ -296,7 +296,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl let (short, name) = item_ty_to_strs(myty.unwrap()); write!( w, - "

\ + "

\ {name}\

\n{}", ITEM_TABLE_OPEN, @@ -482,24 +482,26 @@ fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean:: + name.as_str().len() + generics_len; - wrap_item(w, "fn", |w| { - render_attributes_in_pre(w, it, ""); - w.reserve(header_len); - write!( - w, - "{vis}{constness}{asyncness}{unsafety}{abi}fn \ - {name}{generics}{decl}{notable_traits}{where_clause}", - vis = vis, - constness = constness, - asyncness = asyncness, - unsafety = unsafety, - abi = abi, - name = name, - generics = f.generics.print(cx), - where_clause = print_where_clause(&f.generics, cx, 0, true), - decl = f.decl.full_print(header_len, 0, f.header.asyncness, cx), - notable_traits = notable_traits_decl(&f.decl, cx), - ); + wrap_into_docblock(w, |w| { + wrap_item(w, "fn", |w| { + render_attributes_in_pre(w, it, ""); + w.reserve(header_len); + write!( + w, + "{vis}{constness}{asyncness}{unsafety}{abi}fn \ + {name}{generics}{decl}{notable_traits}{where_clause}", + vis = vis, + constness = constness, + asyncness = asyncness, + unsafety = unsafety, + abi = abi, + name = name, + generics = f.generics.print(cx), + where_clause = print_where_clause(&f.generics, cx, 0, true), + decl = f.decl.full_print(header_len, 0, f.header.asyncness, cx), + notable_traits = notable_traits_decl(&f.decl, cx), + ); + }); }); document(w, cx, it, None, HeadingOffset::H2) } @@ -725,10 +727,11 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra let mut implementor_dups: FxHashMap = FxHashMap::default(); for implementor in implementors { match implementor.inner_impl().for_ { - clean::ResolvedPath { ref path, did, .. } - | clean::BorrowedRef { - type_: box clean::ResolvedPath { ref path, did, .. }, .. - } if !path.is_assoc_ty() => { + clean::Type::Path { ref path } + | clean::BorrowedRef { type_: box clean::Type::Path { ref path }, .. } + if !path.is_assoc_ty() => + { + let did = path.def_id(); let &mut (prev_did, ref mut has_duplicates) = implementor_dups.entry(path.last()).or_insert((did, false)); if prev_did != did { @@ -740,11 +743,11 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra } let (local, foreign) = implementors.iter().partition::, _>(|i| { - i.inner_impl().for_.def_id_full(cache).map_or(true, |d| cache.paths.contains_key(&d)) + i.inner_impl().for_.def_id(cache).map_or(true, |d| cache.paths.contains_key(&d)) }); let (mut synthetic, mut concrete): (Vec<&&Impl>, Vec<&&Impl>) = - local.iter().partition(|i| i.inner_impl().synthetic); + local.iter().partition(|i| i.inner_impl().kind.is_auto()); synthetic.sort_by(|a, b| compare_impl(a, b, cx)); concrete.sort_by(|a, b| compare_impl(a, b, cx)); @@ -759,7 +762,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra render_impl( w, cx, - &implementor, + implementor, it, assoc_link, RenderMode::Normal, @@ -844,16 +847,18 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra } fn item_trait_alias(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::TraitAlias) { - wrap_item(w, "trait-alias", |w| { - render_attributes_in_pre(w, it, ""); - write!( - w, - "trait {}{}{} = {};", - it.name.as_ref().unwrap(), - t.generics.print(cx), - print_where_clause(&t.generics, cx, 0, true), - bounds(&t.bounds, true, cx) - ); + wrap_into_docblock(w, |w| { + wrap_item(w, "trait-alias", |w| { + render_attributes_in_pre(w, it, ""); + write!( + w, + "trait {}{}{} = {};", + it.name.as_ref().unwrap(), + t.generics.print(cx), + print_where_clause(&t.generics, cx, 0, true), + bounds(&t.bounds, true, cx) + ); + }); }); document(w, cx, it, None, HeadingOffset::H2); @@ -866,16 +871,18 @@ fn item_trait_alias(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clea } fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::OpaqueTy) { - wrap_item(w, "opaque", |w| { - render_attributes_in_pre(w, it, ""); - write!( - w, - "type {}{}{where_clause} = impl {bounds};", - it.name.as_ref().unwrap(), - t.generics.print(cx), - where_clause = print_where_clause(&t.generics, cx, 0, true), - bounds = bounds(&t.bounds, false, cx), - ); + wrap_into_docblock(w, |w| { + wrap_item(w, "opaque", |w| { + render_attributes_in_pre(w, it, ""); + write!( + w, + "type {}{}{where_clause} = impl {bounds};", + it.name.as_ref().unwrap(), + t.generics.print(cx), + where_clause = print_where_clause(&t.generics, cx, 0, true), + bounds = bounds(&t.bounds, false, cx), + ); + }); }); document(w, cx, it, None, HeadingOffset::H2); @@ -894,20 +901,37 @@ fn item_typedef( t: &clean::Typedef, is_associated: bool, ) { - wrap_item(w, "typedef", |w| { - render_attributes_in_pre(w, it, ""); - if !is_associated { - write!(w, "{}", it.visibility.print_with_space(it.def_id, cx)); - } - write!( - w, - "type {}{}{where_clause} = {type_};", - it.name.as_ref().unwrap(), - t.generics.print(cx), - where_clause = print_where_clause(&t.generics, cx, 0, true), - type_ = t.type_.print(cx), - ); - }); + fn write_content( + w: &mut Buffer, + cx: &Context<'_>, + it: &clean::Item, + t: &clean::Typedef, + is_associated: bool, + ) { + wrap_item(w, "typedef", |w| { + render_attributes_in_pre(w, it, ""); + if !is_associated { + write!(w, "{}", it.visibility.print_with_space(it.def_id, cx)); + } + write!( + w, + "type {}{}{where_clause} = {type_};", + it.name.as_ref().unwrap(), + t.generics.print(cx), + where_clause = print_where_clause(&t.generics, cx, 0, true), + type_ = t.type_.print(cx), + ); + }); + } + + // If this is an associated typedef, we don't want to wrap it into a docblock. + if is_associated { + write_content(w, cx, it, t, is_associated); + } else { + wrap_into_docblock(w, |w| { + write_content(w, cx, it, t, is_associated); + }); + } document(w, cx, it, None, HeadingOffset::H2); @@ -1057,7 +1081,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum cx.derive_id(format!("{}.{}", ItemType::Variant, variant.name.as_ref().unwrap())); write!( w, - "
\ + "

\ \ {name}", id = id, @@ -1070,9 +1094,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum } w.write_str(""); render_stability_since(w, variant, it, cx.tcx()); - w.write_str("

"); - document(w, cx, variant, Some(it), HeadingOffset::H3); - document_non_exhaustive(w, variant); + w.write_str(""); use crate::clean::Variant; if let Some((extra, fields)) = match *variant.kind { @@ -1086,12 +1108,8 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum variant.name.as_ref().unwrap() )); write!(w, "
", id = variant_id); - write!( - w, - "

{extra}Fields of {name}

", - extra = extra, - name = variant.name.as_ref().unwrap(), - ); + write!(w, "

{extra}Fields

", extra = extra,); + document_non_exhaustive(w, variant); for field in fields { match *field.kind { clean::StrippedItem(box clean::StructFieldItem(_)) => {} @@ -1103,7 +1121,8 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum )); write!( w, - "\ + "
\ + \ \ {f}: {t}\ ", @@ -1111,13 +1130,16 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum f = field.name.as_ref().unwrap(), t = ty.print(cx) ); - document(w, cx, field, Some(variant), HeadingOffset::H4); + document(w, cx, field, Some(variant), HeadingOffset::H5); + write!(w, "
"); } _ => unreachable!(), } } - w.write_str("
"); + w.write_str(""); } + + document(w, cx, variant, Some(it), HeadingOffset::H4); } } let def_id = it.def_id.expect_def_id(); @@ -1136,38 +1158,41 @@ fn item_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Mac it.span(cx.tcx()).inner().edition(), None, None, + None, ); }); document(w, cx, it, None, HeadingOffset::H2) } fn item_proc_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, m: &clean::ProcMacro) { - let name = it.name.as_ref().expect("proc-macros always have names"); - match m.kind { - MacroKind::Bang => { - wrap_item(w, "macro", |w| { - write!(w, "{}!() {{ /* proc-macro */ }}", name); - }); - } - MacroKind::Attr => { - wrap_item(w, "attr", |w| { - write!(w, "#[{}]", name); - }); - } - MacroKind::Derive => { - wrap_item(w, "derive", |w| { - write!(w, "#[derive({})]", name); - if !m.helpers.is_empty() { - w.push_str("\n{\n"); - w.push_str(" // Attributes available to this derive:\n"); - for attr in &m.helpers { - writeln!(w, " #[{}]", attr); + wrap_into_docblock(w, |w| { + let name = it.name.as_ref().expect("proc-macros always have names"); + match m.kind { + MacroKind::Bang => { + wrap_item(w, "macro", |w| { + write!(w, "{}!() {{ /* proc-macro */ }}", name); + }); + } + MacroKind::Attr => { + wrap_item(w, "attr", |w| { + write!(w, "#[{}]", name); + }); + } + MacroKind::Derive => { + wrap_item(w, "derive", |w| { + write!(w, "#[derive({})]", name); + if !m.helpers.is_empty() { + w.push_str("\n{\n"); + w.push_str(" // Attributes available to this derive:\n"); + for attr in &m.helpers { + writeln!(w, " #[{}]", attr); + } + w.push_str("}\n"); } - w.push_str("}\n"); - } - }); + }); + } } - } + }); document(w, cx, it, None, HeadingOffset::H2) } @@ -1177,38 +1202,40 @@ fn item_primitive(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) { } fn item_constant(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, c: &clean::Constant) { - wrap_item(w, "const", |w| { - render_attributes_in_code(w, it); + wrap_into_docblock(w, |w| { + wrap_item(w, "const", |w| { + render_attributes_in_code(w, it); - write!( - w, - "{vis}const {name}: {typ}", - vis = it.visibility.print_with_space(it.def_id, cx), - name = it.name.as_ref().unwrap(), - typ = c.type_.print(cx), - ); + write!( + w, + "{vis}const {name}: {typ}", + vis = it.visibility.print_with_space(it.def_id, cx), + name = it.name.as_ref().unwrap(), + typ = c.type_.print(cx), + ); - let value = c.value(cx.tcx()); - let is_literal = c.is_literal(cx.tcx()); - let expr = c.expr(cx.tcx()); - if value.is_some() || is_literal { - write!(w, " = {expr};", expr = Escape(&expr)); - } else { - w.write_str(";"); - } + let value = c.value(cx.tcx()); + let is_literal = c.is_literal(cx.tcx()); + let expr = c.expr(cx.tcx()); + if value.is_some() || is_literal { + write!(w, " = {expr};", expr = Escape(&expr)); + } else { + w.write_str(";"); + } - if !is_literal { - if let Some(value) = &value { - let value_lowercase = value.to_lowercase(); - let expr_lowercase = expr.to_lowercase(); + if !is_literal { + if let Some(value) = &value { + let value_lowercase = value.to_lowercase(); + let expr_lowercase = expr.to_lowercase(); - if value_lowercase != expr_lowercase - && value_lowercase.trim_end_matches("i32") != expr_lowercase - { - write!(w, " // {value}", value = Escape(value)); + if value_lowercase != expr_lowercase + && value_lowercase.trim_end_matches("i32") != expr_lowercase + { + write!(w, " // {value}", value = Escape(value)); + } } } - } + }); }); document(w, cx, it, None, HeadingOffset::H2) @@ -1268,30 +1295,34 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St } fn item_static(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Static) { - wrap_item(w, "static", |w| { - render_attributes_in_code(w, it); - write!( - w, - "{vis}static {mutability}{name}: {typ}", - vis = it.visibility.print_with_space(it.def_id, cx), - mutability = s.mutability.print_with_space(), - name = it.name.as_ref().unwrap(), - typ = s.type_.print(cx) - ); + wrap_into_docblock(w, |w| { + wrap_item(w, "static", |w| { + render_attributes_in_code(w, it); + write!( + w, + "{vis}static {mutability}{name}: {typ}", + vis = it.visibility.print_with_space(it.def_id, cx), + mutability = s.mutability.print_with_space(), + name = it.name.as_ref().unwrap(), + typ = s.type_.print(cx) + ); + }); }); document(w, cx, it, None, HeadingOffset::H2) } fn item_foreign_type(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) { - wrap_item(w, "foreigntype", |w| { - w.write_str("extern {\n"); - render_attributes_in_code(w, it); - write!( - w, - " {}type {};\n}}", - it.visibility.print_with_space(it.def_id, cx), - it.name.as_ref().unwrap(), - ); + wrap_into_docblock(w, |w| { + wrap_item(w, "foreigntype", |w| { + w.write_str("extern {\n"); + render_attributes_in_code(w, it); + write!( + w, + " {}type {};\n}}", + it.visibility.print_with_space(it.def_id, cx), + it.name.as_ref().unwrap(), + ); + }); }); document(w, cx, it, None, HeadingOffset::H2); @@ -1374,7 +1405,7 @@ fn wrap_into_docblock(w: &mut Buffer, f: F) where F: FnOnce(&mut Buffer), { - w.write_str("
"); + w.write_str("
"); f(w); w.write_str("
") } @@ -1422,8 +1453,8 @@ fn render_implementor( // If there's already another implementor that has the same abridged name, use the // full path, for example in `std::iter::ExactSizeIterator` let use_absolute = match implementor.inner_impl().for_ { - clean::ResolvedPath { ref path, .. } - | clean::BorrowedRef { type_: box clean::ResolvedPath { ref path, .. }, .. } + clean::Type::Path { ref path, .. } + | clean::BorrowedRef { type_: box clean::Type::Path { ref path, .. }, .. } if !path.is_assoc_ty() => { implementor_dups[&path.last()].1 @@ -1465,7 +1496,7 @@ fn render_union( ); if let Some(g) = g { write!(w, "{}", g.print(cx)); - write!(w, "{}", print_where_clause(&g, cx, 0, true)); + write!(w, "{}", print_where_clause(g, cx, 0, true)); } write!(w, " {{\n{}", tab); diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs index d517f3ac0e..7803a77972 100644 --- a/src/librustdoc/html/render/span_map.rs +++ b/src/librustdoc/html/render/span_map.rs @@ -37,21 +37,21 @@ crate enum LinkFromSrc { /// only keep the `lo` and `hi`. crate fn collect_spans_and_sources( tcx: TyCtxt<'_>, - krate: clean::Crate, + krate: &clean::Crate, src_root: &Path, include_sources: bool, generate_link_to_definition: bool, -) -> (clean::Crate, FxHashMap, FxHashMap) { +) -> (FxHashMap, FxHashMap) { let mut visitor = SpanMapVisitor { tcx, matches: FxHashMap::default() }; if include_sources { if generate_link_to_definition { tcx.hir().walk_toplevel_module(&mut visitor); } - let (krate, sources) = sources::collect_local_sources(tcx, src_root, krate); - (krate, sources, visitor.matches) + let sources = sources::collect_local_sources(tcx, src_root, &krate); + (sources, visitor.matches) } else { - (krate, Default::default(), Default::default()) + (Default::default(), Default::default()) } } @@ -105,7 +105,7 @@ impl Visitor<'tcx> for SpanMapVisitor<'tcx> { } for bound in p.bounds { if let Some(trait_ref) = bound.trait_ref() { - self.handle_path(&trait_ref.path, None); + self.handle_path(trait_ref.path, None); } } } @@ -121,42 +121,33 @@ impl Visitor<'tcx> for SpanMapVisitor<'tcx> { if !span.overlaps(m.inner) { // Now that we confirmed it's a file import, we want to get the span for the module // name only and not all the "mod foo;". - if let Some(node) = self.tcx.hir().find(id) { - match node { - Node::Item(item) => { - self.matches - .insert(item.ident.span, LinkFromSrc::Local(clean::Span::new(m.inner))); - } - _ => {} - } + if let Some(Node::Item(item)) = self.tcx.hir().find(id) { + self.matches.insert(item.ident.span, LinkFromSrc::Local(clean::Span::new(m.inner))); } } intravisit::walk_mod(self, m, id); } fn visit_expr(&mut self, expr: &'tcx rustc_hir::Expr<'tcx>) { - match expr.kind { - ExprKind::MethodCall(segment, method_span, _, _) => { - if let Some(hir_id) = segment.hir_id { - let hir = self.tcx.hir(); - let body_id = hir.enclosing_body_owner(hir_id); - let typeck_results = self.tcx.sess.with_disabled_diagnostic(|| { - self.tcx.typeck_body( - hir.maybe_body_owned_by(body_id).expect("a body which isn't a body"), - ) - }); - if let Some(def_id) = typeck_results.type_dependent_def_id(expr.hir_id) { - self.matches.insert( - method_span, - match hir.span_if_local(def_id) { - Some(span) => LinkFromSrc::Local(clean::Span::new(span)), - None => LinkFromSrc::External(def_id), - }, - ); - } + if let ExprKind::MethodCall(segment, method_span, _, _) = expr.kind { + if let Some(hir_id) = segment.hir_id { + let hir = self.tcx.hir(); + let body_id = hir.enclosing_body_owner(hir_id); + let typeck_results = self.tcx.sess.with_disabled_diagnostic(|| { + self.tcx.typeck_body( + hir.maybe_body_owned_by(body_id).expect("a body which isn't a body"), + ) + }); + if let Some(def_id) = typeck_results.type_dependent_def_id(expr.hir_id) { + self.matches.insert( + method_span, + match hir.span_if_local(def_id) { + Some(span) => LinkFromSrc::Local(clean::Span::new(span)), + None => LinkFromSrc::External(def_id), + }, + ); } } - _ => {} } intravisit::walk_expr(self, expr); } diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index e4c2556118..2d3b249067 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -17,6 +17,7 @@ use crate::config::{EmitType, RenderOptions}; use crate::docfs::PathError; use crate::error::Error; use crate::html::{layout, static_files}; +use crate::{try_err, try_none}; static FILES_UNVERSIONED: Lazy> = Lazy::new(|| { map! { @@ -39,9 +40,9 @@ static FILES_UNVERSIONED: Lazy> = Lazy::new(|| { "SourceCodePro-Semibold.ttf.woff" => static_files::source_code_pro::SEMIBOLD, "SourceCodePro-It.ttf.woff" => static_files::source_code_pro::ITALIC, "SourceCodePro-LICENSE.txt" => static_files::source_code_pro::LICENSE, - "noto-sans-kr-regular.woff2" => static_files::noto_sans_kr::REGULAR2, - "noto-sans-kr-regular.woff" => static_files::noto_sans_kr::REGULAR, - "noto-sans-kr-LICENSE.txt" => static_files::noto_sans_kr::LICENSE, + "NanumBarunGothic.ttf.woff2" => static_files::nanum_barun_gothic::REGULAR2, + "NanumBarunGothic.ttf.woff" => static_files::nanum_barun_gothic::REGULAR, + "NanumBarunGothic-LICENSE.txt" => static_files::nanum_barun_gothic::LICENSE, "LICENSE-MIT.txt" => static_files::LICENSE_MIT, "LICENSE-APACHE.txt" => static_files::LICENSE_APACHE, "COPYRIGHT.txt" => static_files::COPYRIGHT, @@ -128,7 +129,7 @@ impl Context<'_> { ) -> Result<(), Error> { if minify { let contents = contents.as_ref(); - let contents = if resource.extension() == Some(&OsStr::new("css")) { + let contents = if resource.extension() == Some(OsStr::new("css")) { minifier::css::minify(contents).map_err(|e| { Error::new(format!("failed to minify CSS file: {}", e), resource.path(self)) })? @@ -304,6 +305,15 @@ pub(super) fn write_shared( )?; } + if cx.shared.layout.scrape_examples_extension { + cx.write_minify( + SharedResource::InvocationSpecific { basename: "scrape-examples.js" }, + static_files::SCRAPE_EXAMPLES_JS, + options.enable_minification, + &options.emit, + )?; + } + if let Some(ref css) = cx.shared.layout.css_file_extension { let buffer = try_err!(fs::read_to_string(css), css); // This varies based on the invocation, so it can't go through the write_minify wrapper. @@ -446,10 +456,10 @@ pub(super) fn write_shared( let dst = cx.dst.join(&format!("source-files{}.js", cx.shared.resource_suffix)); let make_sources = || { let (mut all_sources, _krates) = - try_err!(collect(&dst, &krate.name.as_str(), "sourcesIndex"), &dst); + try_err!(collect(&dst, &krate.name(cx.tcx()).as_str(), "sourcesIndex"), &dst); all_sources.push(format!( "sourcesIndex[\"{}\"] = {};", - &krate.name, + &krate.name(cx.tcx()), hierarchy.to_json_string() )); all_sources.sort(); @@ -464,9 +474,10 @@ pub(super) fn write_shared( // Update the search index and crate list. let dst = cx.dst.join(&format!("search-index{}.js", cx.shared.resource_suffix)); - let (mut all_indexes, mut krates) = try_err!(collect_json(&dst, &krate.name.as_str()), &dst); + let (mut all_indexes, mut krates) = + try_err!(collect_json(&dst, &krate.name(cx.tcx()).as_str()), &dst); all_indexes.push(search_index); - krates.push(krate.name.to_string()); + krates.push(krate.name(cx.tcx()).to_string()); krates.sort(); // Sort the indexes by crate so the file will be generated identically even @@ -574,7 +585,7 @@ pub(super) fn write_shared( } else { Some(Implementor { text: imp.inner_impl().print(false, cx).to_string(), - synthetic: imp.inner_impl().synthetic, + synthetic: imp.inner_impl().kind.is_auto(), types: collect_paths_for_type(imp.inner_impl().for_.clone(), cache), }) } @@ -590,7 +601,7 @@ pub(super) fn write_shared( let implementors = format!( r#"implementors["{}"] = {};"#, - krate.name, + krate.name(cx.tcx()), serde_json::to_string(&implementors).unwrap() ); @@ -602,7 +613,7 @@ pub(super) fn write_shared( mydst.push(&format!("{}.{}.js", remote_item_type, remote_path[remote_path.len() - 1])); let (mut all_implementors, _) = - try_err!(collect(&mydst, &krate.name.as_str(), "implementors"), &mydst); + try_err!(collect(&mydst, &krate.name(cx.tcx()).as_str(), "implementors"), &mydst); all_implementors.push(implementors); // Sort the implementors by crate so the file will be generated // identically even with rustdoc running in parallel. diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index 71c64231a2..c8e93374e6 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -1,11 +1,11 @@ use crate::clean; use crate::docfs::PathError; use crate::error::Error; -use crate::fold::DocFolder; use crate::html::format::Buffer; use crate::html::highlight; use crate::html::layout; use crate::html::render::{Context, BASIC_KEYWORDS}; +use crate::visit::DocVisitor; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::ty::TyCtxt; @@ -16,23 +16,25 @@ use std::ffi::OsStr; use std::fs; use std::path::{Component, Path, PathBuf}; -crate fn render(cx: &mut Context<'_>, krate: clean::Crate) -> Result { +crate fn render(cx: &mut Context<'_>, krate: &clean::Crate) -> Result<(), Error> { info!("emitting source files"); - let dst = cx.dst.join("src").join(&*krate.name.as_str()); + + let dst = cx.dst.join("src").join(&*krate.name(cx.tcx()).as_str()); cx.shared.ensure_dir(&dst)?; - let mut folder = SourceCollector { dst, cx, emitted_local_sources: FxHashSet::default() }; - Ok(folder.fold_crate(krate)) + + let mut collector = SourceCollector { dst, cx, emitted_local_sources: FxHashSet::default() }; + collector.visit_crate(krate); + Ok(()) } crate fn collect_local_sources<'tcx>( tcx: TyCtxt<'tcx>, src_root: &Path, - krate: clean::Crate, -) -> (clean::Crate, FxHashMap) { + krate: &clean::Crate, +) -> FxHashMap { let mut lsc = LocalSourcesCollector { tcx, local_sources: FxHashMap::default(), src_root }; - - let krate = lsc.fold_crate(krate); - (krate, lsc.local_sources) + lsc.visit_crate(krate); + lsc.local_sources } struct LocalSourcesCollector<'a, 'tcx> { @@ -42,7 +44,7 @@ struct LocalSourcesCollector<'a, 'tcx> { } fn is_real_and_local(span: clean::Span, sess: &Session) -> bool { - span.filename(sess).is_real() && span.cnum(sess) == LOCAL_CRATE + span.cnum(sess) == LOCAL_CRATE && span.filename(sess).is_real() } impl LocalSourcesCollector<'_, '_> { @@ -54,12 +56,13 @@ impl LocalSourcesCollector<'_, '_> { return; } let filename = span.filename(sess); - let p = match filename { - FileName::Real(ref file) => match file.local_path() { - Some(p) => p.to_path_buf(), - _ => return, - }, - _ => return, + let p = if let FileName::Real(file) = filename { + match file.into_local_path() { + Some(p) => p, + None => return, + } + } else { + return; }; if self.local_sources.contains_key(&*p) { // We've already emitted this source @@ -67,7 +70,7 @@ impl LocalSourcesCollector<'_, '_> { } let mut href = String::new(); - clean_path(&self.src_root, &p, false, |component| { + clean_path(self.src_root, &p, false, |component| { href.push_str(&component.to_string_lossy()); href.push('/'); }); @@ -79,13 +82,11 @@ impl LocalSourcesCollector<'_, '_> { } } -impl DocFolder for LocalSourcesCollector<'_, '_> { - fn fold_item(&mut self, item: clean::Item) -> Option { - self.add_local_source(&item); +impl DocVisitor for LocalSourcesCollector<'_, '_> { + fn visit_item(&mut self, item: &clean::Item) { + self.add_local_source(item); - // FIXME: if `include_sources` isn't set and DocFolder didn't require consuming the crate by value, - // we could return None here without having to walk the rest of the crate. - Some(self.fold_item_recur(item)) + self.visit_item_recur(item) } } @@ -98,8 +99,12 @@ struct SourceCollector<'a, 'tcx> { emitted_local_sources: FxHashSet, } -impl DocFolder for SourceCollector<'_, '_> { - fn fold_item(&mut self, item: clean::Item) -> Option { +impl DocVisitor for SourceCollector<'_, '_> { + fn visit_item(&mut self, item: &clean::Item) { + if !self.cx.include_sources { + return; + } + let tcx = self.cx.tcx(); let span = item.span(tcx); let sess = tcx.sess; @@ -107,7 +112,7 @@ impl DocFolder for SourceCollector<'_, '_> { // If we're not rendering sources, there's nothing to do. // If we're including source files, and we haven't seen this file yet, // then we need to render it out to the filesystem. - if self.cx.include_sources && is_real_and_local(span, sess) { + if is_real_and_local(span, sess) { let filename = span.filename(sess); let span = span.inner(); let pos = sess.source_map().lookup_source_file(span.lo()); @@ -132,9 +137,8 @@ impl DocFolder for SourceCollector<'_, '_> { } }; } - // FIXME: if `include_sources` isn't set and DocFolder didn't require consuming the crate by value, - // we could return None here without having to walk the rest of the crate. - Some(self.fold_item_recur(item)) + + self.visit_item_recur(item) } } @@ -168,7 +172,7 @@ impl SourceCollector<'_, 'tcx> { }; // Remove the utf-8 BOM if any - let contents = if contents.starts_with('\u{feff}') { &contents[3..] } else { &contents }; + let contents = contents.strip_prefix('\u{feff}').unwrap_or(&contents); // Create the intermediate directories let mut cur = self.dst.clone(); @@ -204,7 +208,16 @@ impl SourceCollector<'_, 'tcx> { &page, "", |buf: &mut _| { - print_src(buf, contents, self.cx.shared.edition(), file_span, &self.cx, &root_path) + print_src( + buf, + contents, + self.cx.shared.edition(), + file_span, + self.cx, + &root_path, + None, + SourceContext::Standalone, + ) }, &self.cx.shared.style_files, ); @@ -241,15 +254,22 @@ where } } +crate enum SourceContext { + Standalone, + Embedded { offset: usize }, +} + /// Wrapper struct to render the source code of a file. This will do things like /// adding line numbers to the left-hand side. -fn print_src( +crate fn print_src( buf: &mut Buffer, s: &str, edition: Edition, file_span: rustc_span::Span, context: &Context<'_>, root_path: &str, + decoration_info: Option, + source_context: SourceContext, ) { let lines = s.lines().count(); let mut line_numbers = Buffer::empty_from(buf); @@ -261,7 +281,14 @@ fn print_src( } line_numbers.write_str("
");
     for i in 1..=lines {
-        writeln!(line_numbers, "{0:1$}", i, cols);
+        match source_context {
+            SourceContext::Standalone => {
+                writeln!(line_numbers, "{0:1$}", i, cols)
+            }
+            SourceContext::Embedded { offset } => {
+                writeln!(line_numbers, "{0:1$}", i + offset, cols)
+            }
+        }
     }
     line_numbers.write_str("
"); highlight::render_with_highlighting( @@ -273,5 +300,6 @@ fn print_src( edition, Some(line_numbers), Some(highlight::ContextInfo { context, file_span, root_path }), + decoration_info, ); } diff --git a/src/librustdoc/html/static/css/noscript.css b/src/librustdoc/html/static/css/noscript.css index 0a196edd53..37ea7b0003 100644 --- a/src/librustdoc/html/static/css/noscript.css +++ b/src/librustdoc/html/static/css/noscript.css @@ -13,3 +13,12 @@ rules. /* It requires JS to work so no need to display it in this case. */ display: none; } + +.sub { + /* The search bar and related controls don't work without JS */ + display: none; +} + +#theme-picker { + display: none; +} diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 11c54876de..479b5210f9 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -77,11 +77,11 @@ /* Avoid using legacy CJK serif fonts in Windows like Batang. */ @font-face { - font-family: 'Noto Sans KR'; - src: url("noto-sans-kr-regular.woff2") format("woff2"), - url("noto-sans-kr-regular.woff") format("woff"); + font-family: 'NanumBarunGothic'; + src: url("NanumBarunGothic.ttf.woff2") format("woff2"), + url("NanumBarunGothic.ttf.woff") format("woff"); font-display: swap; - unicode-range: U+AC00-D7AF, U+3130-318F, U+1100-11FF, U+A960-A97F, U+D7B0-D7FF; + unicode-range: U+AC00-D7AF, U+1100-11FF, U+3130-318F, U+A960-A97F, U+D7B0-D7FF; } * { @@ -108,7 +108,7 @@ html { /* General structure and fonts */ body { - font: 16px/1.4 "Source Serif 4", "Noto Sans KR", serif; + font: 16px/1.4 "Source Serif 4", NanumBarunGothic, serif; margin: 0; position: relative; padding: 10px 15px 20px 15px; @@ -129,9 +129,14 @@ h3 { } h1, h2, h3, h4, h5, h6 { font-weight: 500; +} +h1, h2, h3, h4 { margin: 20px 0 15px 0; padding-bottom: 6px; } +.docblock h3, .docblock h4, h5, h6 { + margin: 15px 0 5px 0; +} h1.fqn { display: flex; border-bottom: 1px dashed; @@ -144,13 +149,26 @@ h1.fqn { h1.fqn > .in-band > a:hover { text-decoration: underline; } -h2, h3, h4 { +/* The only headings that get underlines are: + Markdown-generated headings within the top-doc + Rustdoc-generated h2 section headings (e.g. "Implementations", "Required Methods", etc) + Underlines elsewhere in the documentation break up visual flow and tend to invert + section hierarchies. */ +h2, +.top-doc h3, +.top-doc h4, +.sidebar .others h3 { border-bottom: 1px solid; } -h3.code-header, h4.code-header { +h3.code-header { + font-size: 1.1em; +} +h4.code-header { font-size: 1em; +} +h3.code-header, h4.code-header { font-weight: 600; - border: none; + border-bottom-style: none; padding: 0; margin: 0; } @@ -169,12 +187,6 @@ h3.code-header, h4.code-header { margin-bottom: 10px; position: relative; } -.impl, .method.trait-impl, -.type.trait-impl, -.associatedconstant.trait-impl, -.associatedtype.trait-impl { - padding-left: 15px; -} div.impl-items > div { padding-left: 0; @@ -187,12 +199,11 @@ h1, h2, h3, h4, h5, h6, div.item-list .out-of-band, span.since, #source-sidebar, #sidebar-toggle, details.rustdoc-toggle > summary::before, -details.undocumented > summary::before, div.impl-items > div:not(.docblock):not(.item-info), .content ul.crate a.crate, a.srclink, /* This selector is for the items listed in the "all items" page. */ #main > ul.docblock > li > a { - font-family: "Fira Sans", Arial, sans-serif; + font-family: "Fira Sans", Arial, NanumBarunGothic, sans-serif; } .content ul.crate a.crate { @@ -254,7 +265,10 @@ code, pre, a.test-arrow, .code-header { pre { padding: 14px; } -.type-decl pre { +.docblock.item-decl { + margin-left: 0; +} +.item-decl pre { overflow-x: auto; } @@ -288,7 +302,11 @@ nav.sub { left: 0; top: 0; bottom: 0; - overflow: auto; + overflow-y: scroll; +} + +.rustdoc.source .sidebar { + overflow-y: auto; } /* Improve the scrollbar display on firefox */ @@ -459,6 +477,11 @@ nav.sub { overflow-x: auto; } +.rustdoc:not(.source) .example-wrap > pre.line-numbers { + width: auto; + overflow-x: visible; +} + .rustdoc .example-wrap > pre { margin: 0; } @@ -502,14 +525,12 @@ nav.sub { white-space: pre-wrap; } -.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5, .docblock h6 { - border-bottom: 1px solid; -} - .top-doc .docblock h2 { font-size: 1.3em; } .top-doc .docblock h3 { font-size: 1.15em; } .top-doc .docblock h4, -.top-doc .docblock h5, +.top-doc .docblock h5 { + font-size: 1.1em; +} .top-doc .docblock h6 { font-size: 1em; } @@ -522,7 +543,7 @@ nav.sub { position: relative; } -.docblock > * { +.docblock > :not(.information) { max-width: 100%; overflow-x: auto; } @@ -550,6 +571,7 @@ nav.sub { flex-grow: 1; margin: 0px; padding: 0px; + overflow-wrap: anywhere; } .in-band > code, .in-band > .code-header { @@ -662,13 +684,6 @@ nav.sub { left: -19px; } -.content .impl-items .method, .content .impl-items > .type, .impl-items > .associatedconstant, -.impl-items > .associatedtype, .content .impl-items details > summary > .type, -.impl-items details > summary > .associatedconstant, -.impl-items details > summary > .associatedtype { - margin-left: 20px; -} - .content .impl-items .docblock, .content .impl-items .item-info { margin-bottom: .6em; } @@ -739,7 +754,7 @@ a { .anchor { display: none; position: absolute; - left: 0; + left: -0.5em; background: none !important; } .anchor.field { @@ -953,8 +968,6 @@ body.blur > :not(#help) { display: table; } .stab { - border-width: 1px; - border-style: solid; padding: 3px; margin-bottom: 5px; font-size: 90%; @@ -965,7 +978,7 @@ body.blur > :not(#help) { } .stab .emoji { - font-size: 1.5em; + font-size: 1.2em; } /* Black one-pixel outline around emoji shapes */ @@ -1067,10 +1080,6 @@ a.test-arrow:hover{ text-decoration: none; } -.section-header a { - color: inherit; -} - .code-attribute { font-weight: 300; } @@ -1090,25 +1099,28 @@ a.test-arrow:hover{ margin-right: 5px; } -.sub-variant, .sub-variant > h3 { - margin-top: 0px !important; - padding-top: 1px; +h3.variant { + font-weight: 600; + font-size: 1.1em; + margin-bottom: 10px; + border-bottom: none; } -#main .sub-variant > h3 { - font-size: 15px; - margin-left: 25px; - margin-bottom: 5px; +.sub-variant h4 { + font-size: 1em; + font-weight: 400; + border-bottom: none; + margin-top: 0; + margin-bottom: 0; } -.sub-variant > div { - margin-left: 20px; - margin-bottom: 10px; +.sub-variant { + margin-left: 24px; + margin-bottom: 40px; } -.sub-variant > div > span { - display: block; - position: relative; +.sub-variant > .sub-variant-field { + margin-left: 24px; } .toggle-label { @@ -1117,15 +1129,17 @@ a.test-arrow:hover{ margin-top: 3px; } -.docblock > .section-header:first-child { +.top-doc .docblock > .section-header:first-child { margin-left: 15px; - margin-top: 0; } - -.docblock > .section-header:first-child:hover > a:before { +.top-doc .docblock > .section-header:first-child:hover > a:before { left: -10px; } +.docblock > .section-header:first-child { + margin-top: 0; +} + :target > code, :target > .code-header { opacity: 1; } @@ -1508,13 +1522,11 @@ details.rustdoc-toggle > summary.hideme { cursor: pointer; } -details.rustdoc-toggle > summary, details.undocumented > summary { +details.rustdoc-toggle > summary { list-style: none; } details.rustdoc-toggle > summary::-webkit-details-marker, -details.rustdoc-toggle > summary::marker, -details.undocumented > summary::-webkit-details-marker, -details.undocumented > summary::marker { +details.rustdoc-toggle > summary::marker { display: none; } @@ -1572,14 +1584,13 @@ details.rustdoc-toggle > summary.hideme::before { details.rustdoc-toggle > summary:not(.hideme)::before { position: absolute; - left: -23px; + left: -24px; top: 3px; } -.impl-items > details.rustdoc-toggle > summary:not(.hideme)::before, -.undocumented > details.rustdoc-toggle > summary:not(.hideme)::before { +.impl-items > details.rustdoc-toggle > summary:not(.hideme)::before { position: absolute; - left: -2px; + left: -24px; } /* When a "hideme" summary is open and the "Expand description" or "Show @@ -1591,7 +1602,7 @@ details.rustdoc-toggle[open] > summary.hideme { position: absolute; } -details.rustdoc-toggle, details.undocumented { +details.rustdoc-toggle { position: relative; } @@ -1614,31 +1625,6 @@ details.rustdoc-toggle[open] > summary.hideme::after { content: "Collapse"; } -details.undocumented > summary::before { - padding-left: 17px; - height: max(17px, 1.1em); - background-repeat: no-repeat; - background-position: top left; - content: "Show hidden undocumented items"; - cursor: pointer; - font-size: 16px; - font-weight: 300; - opacity: .5; -} - -details.undocumented > summary:focus::before, -details.undocumented > summary:hover::before { - opacity: 1; -} - -details.undocumented[open] > summary::before { - padding-left: 17px; - height: max(17px, 1.1em); - background-repeat: no-repeat - background-position: top left; - content: "Hide undocumented items"; -} - /* Media Queries */ @media (min-width: 701px) { @@ -1973,3 +1959,166 @@ details.undocumented[open] > summary::before { overflow-wrap: anywhere; } } + + +/* Begin: styles for --scrape-examples feature */ + +.scraped-example-title { + font-family: 'Fira Sans'; +} + +.scraped-example:not(.expanded) .code-wrapper pre.line-numbers { + overflow: hidden; + max-height: 240px; +} + +.scraped-example:not(.expanded) .code-wrapper .example-wrap pre.rust { + overflow-y: hidden; + max-height: 240px; + padding-bottom: 0; +} + +.scraped-example .code-wrapper .prev { + position: absolute; + top: 0.25em; + right: 2.25em; + z-index: 100; + cursor: pointer; +} + +.scraped-example .code-wrapper .next { + position: absolute; + top: 0.25em; + right: 1.25em; + z-index: 100; + cursor: pointer; +} + +.scraped-example .code-wrapper .expand { + position: absolute; + top: 0.25em; + right: 0.25em; + z-index: 100; + cursor: pointer; +} + +.scraped-example .code-wrapper { + position: relative; + display: flex; + flex-direction: row; + flex-wrap: wrap; + width: 100%; +} + +.scraped-example:not(.expanded) .code-wrapper:before { + content: " "; + width: 100%; + height: 5px; + position: absolute; + z-index: 100; + top: 0; + background: linear-gradient(to bottom, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0)); +} + +.scraped-example:not(.expanded) .code-wrapper:after { + content: " "; + width: 100%; + height: 5px; + position: absolute; + z-index: 100; + bottom: 0; + background: linear-gradient(to top, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0)); +} + +.scraped-example:not(.expanded) .code-wrapper { + overflow: hidden; + max-height: 240px; +} + +.scraped-example .code-wrapper .line-numbers { + margin: 0; + padding: 14px 0; +} + +.scraped-example .code-wrapper .line-numbers span { + padding: 0 14px; +} + +.scraped-example .code-wrapper .example-wrap { + flex: 1; + overflow-x: auto; + overflow-y: hidden; + margin-bottom: 0; +} + +.scraped-example .code-wrapper .example-wrap pre.rust { + overflow-x: inherit; + width: inherit; + overflow-y: hidden; +} + +.scraped-example .example-wrap .rust span.highlight { + background: #fcffd6; +} + +.scraped-example .example-wrap .rust span.highlight.focus { + background: #f6fdb0; +} + +.more-examples-toggle { + margin-top: 10px; +} + +.more-examples-toggle summary { + color: #999; + font-family: 'Fira Sans'; +} + +.more-scraped-examples { + margin-left: 25px; + display: flex; + flex-direction: row; + width: calc(100% - 25px); +} + +.more-scraped-examples-inner { + /* 20px is width of toggle-line + toggle-line-inner */ + width: calc(100% - 20px); +} + +.toggle-line { + align-self: stretch; + margin-right: 10px; + margin-top: 5px; + padding: 0 4px; + cursor: pointer; +} + +.toggle-line:hover .toggle-line-inner { + background: #aaa; +} + +.toggle-line-inner { + min-width: 2px; + background: #ddd; + height: 100%; +} + +.more-scraped-examples .scraped-example { + margin-bottom: 20px; +} + +.more-scraped-examples .scraped-example:last-child { + margin-bottom: 0; +} + +.example-links a { + margin-top: 20px; + font-family: 'Fira Sans'; +} + +.example-links ul { + margin-bottom: 0; +} + +/* End: styles for --scrape-examples feature */ diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index 0fd6462a8f..532bc0e351 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -70,11 +70,11 @@ pre, .rustdoc.source .example-wrap { /* Improve the scrollbar display on firefox */ * { - scrollbar-color: #5c6773 transparent; + scrollbar-color: #5c6773 #24292f; } .sidebar { - scrollbar-color: #5c6773 transparent; + scrollbar-color: #5c6773 #24292f; } /* Improve the scrollbar display on webkit-based browsers */ @@ -214,18 +214,25 @@ nav.main .separator { border: 1px solid #5c6773; } a { + color: #39AFD7; +} +a.srclink, +a#toggle-all-docs, +a.anchor, +.small-section-header a, +#source-sidebar a, +pre.rust a, +.sidebar a, +.in-band a { color: #c5c5c5; } +.search-results a { + color: #0096cf; +} body.source .example-wrap pre.rust a { background: #333; } -.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow), -.docblock-short a:not(.srclink):not(.test-arrow), .item-info a, -#help a { - color: #39AFD7; -} - details.rustdoc-toggle > summary.hideme > span, details.rustdoc-toggle > summary::before, details.undocumented > summary::before { @@ -255,10 +262,6 @@ details.undocumented > summary::before { box-shadow: 0 0 0 1px #148099,0 0 0 2px transparent; } -.search-input:disabled { - background-color: #3e3e3e; -} - .module-item .stab, .import-item .stab { color: #000; @@ -613,3 +616,22 @@ div.files > .selected { input:checked + .slider { background-color: #ffb454 !important; } + +.scraped-example .example-wrap .rust span.highlight { + background: rgb(91, 59, 1); +} +.scraped-example .example-wrap .rust span.highlight.focus { + background: rgb(124, 75, 15); +} +.scraped-example:not(.expanded) .code-wrapper:before { + background: linear-gradient(to bottom, rgba(15, 20, 25, 1), rgba(15, 20, 25, 0)); +} +.scraped-example:not(.expanded) .code-wrapper:after { + background: linear-gradient(to top, rgba(15, 20, 25, 1), rgba(15, 20, 25, 0)); +} +.toggle-line-inner { + background: #616161; +} +.toggle-line:hover .toggle-line-inner { + background: ##898989; +} diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index d863701dd7..56ed8a2006 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -44,7 +44,7 @@ pre, .rustdoc.source .example-wrap { scrollbar-color: rgb(64, 65, 67) #717171; } .sidebar { - scrollbar-color: rgba(32,34,37,.6) transparent; + scrollbar-color: rgba(32,34,37,.6) #5a5a5a; } /* Improve the scrollbar display on webkit-based browsers */ @@ -174,22 +174,29 @@ nav.main .current { nav.main .separator { border-color: #eee; } + a { - color: #ddd; + color: #D2991D; } -body.source .example-wrap pre.rust a { - background: #333; +a.srclink, +a#toggle-all-docs, +a.anchor, +.small-section-header a, +#source-sidebar a, +pre.rust a, +.sidebar a, +.in-band a { + color: #ddd; } - -.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow), -.docblock-short a:not(.srclink):not(.test-arrow), .item-info a, -#help a { - color: #D2991D; +.search-results a { + color: #ddd; } - a.test-arrow { color: #dedede; } +body.source .example-wrap pre.rust a { + background: #333; +} details.rustdoc-toggle > summary.hideme > span, details.rustdoc-toggle > summary::before, @@ -219,10 +226,6 @@ details.undocumented > summary::before { border-color: #008dfd; } -.search-input:disabled { - background-color: #c5c4c4; -} - #crate-search + .search-input:focus { box-shadow: 0 0 8px 4px #078dd8; } @@ -485,3 +488,22 @@ div.files > .selected { .setting-line > .title { border-bottom-color: #ddd; } + +.scraped-example .example-wrap .rust span.highlight { + background: rgb(91, 59, 1); +} +.scraped-example .example-wrap .rust span.highlight.focus { + background: rgb(124, 75, 15); +} +.scraped-example:not(.expanded) .code-wrapper:before { + background: linear-gradient(to bottom, rgba(53, 53, 53, 1), rgba(53, 53, 53, 0)); +} +.scraped-example:not(.expanded) .code-wrapper:after { + background: linear-gradient(to top, rgba(53, 53, 53, 1), rgba(53, 53, 53, 0)); +} +.toggle-line-inner { + background: #616161; +} +.toggle-line:hover .toggle-line-inner { + background: ##898989; +} diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index 28d2e99a3d..d636141918 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -169,22 +169,29 @@ nav.main .current { nav.main .separator { border: 1px solid #000; } + a { - color: #000; + color: #3873AD; } -body.source .example-wrap pre.rust a { - background: #eee; +a.srclink, +a#toggle-all-docs, +a.anchor, +.small-section-header a, +#source-sidebar a, +pre.rust a, +.sidebar a, +.in-band a { + color: #000; } - -.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow), -.docblock-short a:not(.srclink):not(.test-arrow), .item-info a, -#help a { - color: #3873AD; +.search-results a { + color: initial; } - a.test-arrow { color: #f5f5f5; } +body.source .example-wrap pre.rust a { + background: #eee; +} details.rustdoc-toggle > summary.hideme > span, details.rustdoc-toggle > summary::before, @@ -209,10 +216,6 @@ details.undocumented > summary::before { border-color: #66afe9; } -.search-input:disabled { - background-color: #e6e6e6; -} - #crate-search + .search-input:focus { box-shadow: 0 0 8px #078dd8; } diff --git a/src/librustdoc/html/static/fonts/NanumBarunGothic-LICENSE.txt b/src/librustdoc/html/static/fonts/NanumBarunGothic-LICENSE.txt new file mode 100644 index 0000000000..0bf46682b5 --- /dev/null +++ b/src/librustdoc/html/static/fonts/NanumBarunGothic-LICENSE.txt @@ -0,0 +1,99 @@ +Copyright (c) 2010, NAVER Corporation (https://www.navercorp.com/), + +with Reserved Font Name Nanum, Naver Nanum, NanumGothic, Naver NanumGothic, +NanumMyeongjo, Naver NanumMyeongjo, NanumBrush, Naver NanumBrush, NanumPen, +Naver NanumPen, Naver NanumGothicEco, NanumGothicEco, Naver NanumMyeongjoEco, +NanumMyeongjoEco, Naver NanumGothicLight, NanumGothicLight, NanumBarunGothic, +Naver NanumBarunGothic, NanumSquareRound, NanumBarunPen, MaruBuri + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/src/librustdoc/html/static/fonts/NanumBarunGothic.ttf.woff b/src/librustdoc/html/static/fonts/NanumBarunGothic.ttf.woff new file mode 100644 index 0000000000000000000000000000000000000000..fb063e8fb7dc5435c591560e257903a35f76ee6a GIT binary patch literal 677868 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⋘6;xf~32d$0yk&7>f75=aNfY{aX;P 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ȫt(PxR${=poRw4*a?_M2*akmH!V-Xt0A{c`H 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�mPX# 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�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

xz5_8aF@(pQs@zgto+ItjS_s2^}<|M=lFQ2 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,qWUc(1+qXDfx7@=bp~~)(TqS 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 Psah$GwaNdR#Q^{S={DW} literal 0 HcmV?d00001 diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index e396fd9d28..c9fa72cbaa 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -263,7 +263,9 @@ function hideThemeButtonState() { search_input.placeholder = searchState.input.origPlaceholder; }); - search_input.removeAttribute('disabled'); + if (search_input.value != '') { + loadSearch(); + } // `crates{version}.js` should always be loaded before this script, so we can use it // safely. @@ -564,6 +566,7 @@ function hideThemeButtonState() { // delayed sidebar rendering. window.initSidebarItems = function(items) { var sidebar = document.getElementsByClassName("sidebar-elems")[0]; + var others; var current = window.sidebarCurrent; function addSidebarCrates(crates) { @@ -592,7 +595,7 @@ function hideThemeButtonState() { li.appendChild(link); ul.appendChild(li); } - sidebar.appendChild(div); + others.appendChild(div); } function block(shortty, longty) { @@ -633,10 +636,14 @@ function hideThemeButtonState() { ul.appendChild(li); } div.appendChild(ul); - sidebar.appendChild(div); + others.appendChild(div); } if (sidebar) { + others = document.createElement("div"); + others.className = "others"; + sidebar.appendChild(others); + var isModule = hasClass(document.body, "mod"); if (!isModule) { block("primitive", "Primitive Types"); @@ -879,6 +886,14 @@ function hideThemeButtonState() { } }); + onEachLazy(document.querySelectorAll(".rustdoc-toggle > summary:not(.hideme)"), function(el) { + el.addEventListener("click", function(e) { + if (e.target.tagName != "SUMMARY" && e.target.tagName != "A") { + e.preventDefault(); + } + }); + }); + onEachLazy(document.getElementsByClassName("notable-traits"), function(e) { e.onclick = function() { this.getElementsByClassName('notable-traits-tooltiptext')[0] diff --git a/src/librustdoc/html/static/js/scrape-examples.js b/src/librustdoc/html/static/js/scrape-examples.js new file mode 100644 index 0000000000..664b187e33 --- /dev/null +++ b/src/librustdoc/html/static/js/scrape-examples.js @@ -0,0 +1,86 @@ +/* global addClass, hasClass, removeClass, onEach */ + +(function () { + // Scroll code block to put the given code location in the middle of the viewer + function scrollToLoc(elt, loc) { + var wrapper = elt.querySelector(".code-wrapper"); + var halfHeight = wrapper.offsetHeight / 2; + var lines = elt.querySelector('.line-numbers'); + var offsetMid = (lines.children[loc[0]].offsetTop + + lines.children[loc[1]].offsetTop) / 2; + var scrollOffset = offsetMid - halfHeight; + lines.scrollTo(0, scrollOffset); + elt.querySelector(".rust").scrollTo(0, scrollOffset); + } + + function updateScrapedExample(example) { + var locs = JSON.parse(example.attributes.getNamedItem("data-locs").textContent); + var locIndex = 0; + var highlights = example.querySelectorAll('.highlight'); + var link = example.querySelector('.scraped-example-title a'); + + if (locs.length > 1) { + // Toggle through list of examples in a given file + var onChangeLoc = function(changeIndex) { + removeClass(highlights[locIndex], 'focus'); + changeIndex(); + scrollToLoc(example, locs[locIndex][0]); + addClass(highlights[locIndex], 'focus'); + + var url = locs[locIndex][1]; + var title = locs[locIndex][2]; + + link.href = url; + link.innerHTML = title; + }; + + example.querySelector('.prev') + .addEventListener('click', function() { + onChangeLoc(function() { + locIndex = (locIndex - 1 + locs.length) % locs.length; + }); + }); + + example.querySelector('.next') + .addEventListener('click', function() { + onChangeLoc(function() { + locIndex = (locIndex + 1) % locs.length; + }); + }); + } + + var expandButton = example.querySelector('.expand'); + if (expandButton) { + expandButton.addEventListener('click', function () { + if (hasClass(example, "expanded")) { + removeClass(example, "expanded"); + scrollToLoc(example, locs[0][0]); + } else { + addClass(example, "expanded"); + } + }); + } + + // Start with the first example in view + scrollToLoc(example, locs[0][0]); + } + + var firstExamples = document.querySelectorAll('.scraped-example-list > .scraped-example'); + onEach(firstExamples, updateScrapedExample); + onEach(document.querySelectorAll('.more-examples-toggle'), function(toggle) { + // Allow users to click the left border of the

section to close it, + // since the section can be large and finding the [+] button is annoying. + toggle.querySelector('.toggle-line').addEventListener('click', function() { + toggle.open = false; + }); + + var moreExamples = toggle.querySelectorAll('.scraped-example'); + toggle.querySelector('summary').addEventListener('click', function() { + // Wrapping in setTimeout ensures the update happens after the elements are actually + // visible. This is necessary since updateScrapedExample calls scrollToLoc which + // depends on offsetHeight, a property that requires an element to be visible to + // compute correctly. + setTimeout(function() { onEach(moreExamples, updateScrapedExample); }); + }, {once: true}); + }); +})(); diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 5eb545f758..c2ea54abd2 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -299,10 +299,10 @@ window.initSearch = function(rawSearchIndex) { var elems = Object.create(null); var elength = obj[GENERICS_DATA].length; for (var x = 0; x < elength; ++x) { - if (!elems[obj[GENERICS_DATA][x]]) { - elems[obj[GENERICS_DATA][x]] = 0; + if (!elems[obj[GENERICS_DATA][x][NAME]]) { + elems[obj[GENERICS_DATA][x][NAME]] = 0; } - elems[obj[GENERICS_DATA][x]] += 1; + elems[obj[GENERICS_DATA][x][NAME]] += 1; } var total = 0; var done = 0; @@ -345,6 +345,7 @@ window.initSearch = function(rawSearchIndex) { // Check for type name and type generics (if any). function checkType(obj, val, literalSearch) { var lev_distance = MAX_LEV_DISTANCE + 1; + var tmp_lev = MAX_LEV_DISTANCE + 1; var len, x, firstGeneric; if (obj[NAME] === val.name) { if (literalSearch) { @@ -354,10 +355,10 @@ window.initSearch = function(rawSearchIndex) { var elems = Object.create(null); len = obj[GENERICS_DATA].length; for (x = 0; x < len; ++x) { - if (!elems[obj[GENERICS_DATA][x]]) { - elems[obj[GENERICS_DATA][x]] = 0; + if (!elems[obj[GENERICS_DATA][x][NAME]]) { + elems[obj[GENERICS_DATA][x][NAME]] = 0; } - elems[obj[GENERICS_DATA][x]] += 1; + elems[obj[GENERICS_DATA][x][NAME]] += 1; } var allFound = true; @@ -382,7 +383,7 @@ window.initSearch = function(rawSearchIndex) { // 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); + tmp_lev = checkGenerics(obj, val); if (tmp_lev <= MAX_LEV_DISTANCE) { return tmp_lev; } @@ -392,8 +393,8 @@ window.initSearch = function(rawSearchIndex) { if ((!val.generics || val.generics.length === 0) && obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) { return obj[GENERICS_DATA].some( - function(name) { - return name === val.name; + function(gen) { + return gen[NAME] === val.name; }); } return false; @@ -404,17 +405,27 @@ window.initSearch = function(rawSearchIndex) { // 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) { + } + 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); + tmp_lev = Math.min(levenshtein(obj[GENERICS_DATA][x][NAME], val.name), tmp_lev); + } + if (tmp_lev !== 0) { + // If we didn't find a good enough result, we go check inside the generics of + // the generics. + for (x = 0; x < olength && tmp_lev !== 0; ++x) { + tmp_lev = Math.min( + checkType(obj[GENERICS_DATA][x], val, literalSearch), + tmp_lev + ); + } } } // 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; + return Math.min(lev_distance, tmp_lev) + 1; } function findArg(obj, val, literalSearch, typeFilter) { diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs index 924e3f1d29..56c5399d07 100644 --- a/src/librustdoc/html/static_files.rs +++ b/src/librustdoc/html/static_files.rs @@ -35,6 +35,10 @@ crate static SETTINGS_JS: &str = include_str!("static/js/settings.js"); /// Storage, used to store documentation settings. crate static STORAGE_JS: &str = include_str!("static/js/storage.js"); +/// The file contents of `scraped-examples.js`, which contains functionality related to the +/// --scrape-examples flag that inserts automatically-found examples of usages of items. +crate static SCRAPE_EXAMPLES_JS: &str = include_str!("static/js/scrape-examples.js"); + /// The file contents of `brush.svg`, the icon used for the theme-switch button. crate static BRUSH_SVG: &[u8] = include_bytes!("static/images/brush.svg"); @@ -156,15 +160,35 @@ crate mod source_code_pro { crate static LICENSE: &[u8] = include_bytes!("static/fonts/SourceCodePro-LICENSE.txt"); } -crate mod noto_sans_kr { - /// The file `noto-sans-kr.woff`, the Regular variant of the Noto Sans KR font. - crate static REGULAR: &[u8] = include_bytes!("static/fonts/noto-sans-kr-regular.woff"); - - /// The file `noto-sans-kr.woff2`, the Regular variant of the Noto Sans KR font. - crate static REGULAR2: &[u8] = include_bytes!("static/fonts/noto-sans-kr-regular.woff2"); - - /// The file `noto-sans-kr-LICENSE.txt`, the license text of the Noto Sans KR font. - crate static LICENSE: &[u8] = include_bytes!("static/fonts/noto-sans-kr-LICENSE.txt"); +/// Files related to the Nanum Barun Gothic font. +/// +/// These files are used to avoid some legacy CJK serif fonts in Windows. +/// +/// Note that the Noto Sans KR font, which was used previously but was not very readable on Windows, +/// has been replaced by the Nanum Barun Gothic font. This is due to Windows' implementation of font +/// rendering that distorts OpenType fonts too much. +/// +/// The font files were generated with these commands: +/// +/// ```sh +/// pyftsubset NanumBarunGothic.ttf \ +/// --unicodes=U+AC00-D7AF,U+1100-11FF,U+3130-318F,U+A960-A97F,U+D7B0-D7FF \ +/// --output-file=NanumBarunGothic.ttf.woff --flavor=woff +/// ``` +/// ```sh +/// pyftsubset NanumBarunGothic.ttf \ +/// --unicodes=U+AC00-D7AF,U+1100-11FF,U+3130-318F,U+A960-A97F,U+D7B0-D7FF \ +/// --output-file=NanumBarunGothic.ttf.woff2 --flavor=woff2 +/// ``` +crate mod nanum_barun_gothic { + /// The file `NanumBarunGothic.ttf.woff`, the Regular variant of the Nanum Barun Gothic font. + crate static REGULAR: &[u8] = include_bytes!("static/fonts/NanumBarunGothic.ttf.woff"); + + /// The file `NanumBarunGothic.ttf.woff2`, the Regular variant of the Nanum Barun Gothic font. + crate static REGULAR2: &[u8] = include_bytes!("static/fonts/NanumBarunGothic.ttf.woff2"); + + /// The file `NanumBarunGothic-LICENSE.txt`, the license text of the Nanum Barun Gothic font. + crate static LICENSE: &[u8] = include_bytes!("static/fonts/NanumBarunGothic-LICENSE.txt"); } /// Files related to the sidebar in rustdoc sources. diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html index 38dc3b30e7..cf57d4cf3a 100644 --- a/src/librustdoc/html/templates/page.html +++ b/src/librustdoc/html/templates/page.html @@ -20,6 +20,16 @@ > {#- -#} {#- -#} {#- -#} + {#- -#} + {%- for script in page.static_extra_scripts -%} + {#- -#} + {% endfor %} + {%- if layout.scrape_examples_extension -%} + {#- -#} + {%- endif -%} + {%- for script in page.extra_scripts -%} + {#- -#} + {% endfor %}

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

- {#- -#} - {%- for script in page.static_extra_scripts -%} - {#- -#} - {% endfor %} - {%- for script in page.extra_scripts -%} - {#- -#} - {% endfor %} {#- -#} {#- -#} diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 4098f17db8..7fc295747f 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -9,7 +9,7 @@ use std::fmt; use rustc_ast::ast; use rustc_hir::{def::CtorKind, def_id::DefId}; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{self, TyCtxt}; use rustc_span::def_id::CRATE_DEF_INDEX; use rustc_span::Pos; @@ -330,10 +330,10 @@ impl FromWithTcx for GenericParamDefKind { }, Type { did: _, bounds, default, synthetic: _ } => GenericParamDefKind::Type { bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(), - default: default.map(|x| x.into_tcx(tcx)), + default: default.map(|x| (*x).into_tcx(tcx)), }, Const { did: _, ty, default } => { - GenericParamDefKind::Const { ty: ty.into_tcx(tcx), default } + GenericParamDefKind::Const { ty: (*ty).into_tcx(tcx), default: default.map(|x| *x) } } } } @@ -365,8 +365,7 @@ impl FromWithTcx for GenericBound { match bound { TraitBound(clean::PolyTrait { trait_, generic_params }, modifier) => { // FIXME: should `trait_` be a clean::Path equivalent in JSON? - let trait_ = - clean::ResolvedPath { did: trait_.def_id(), path: trait_ }.into_tcx(tcx); + let trait_ = clean::Type::Path { path: trait_ }.into_tcx(tcx); GenericBound::TraitBound { trait_, generic_params: generic_params.into_iter().map(|x| x.into_tcx(tcx)).collect(), @@ -389,11 +388,15 @@ crate fn from_trait_bound_modifier(modifier: rustc_hir::TraitBoundModifier) -> T impl FromWithTcx for Type { fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self { - use clean::Type::*; + use clean::Type::{ + Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive, + QPath, RawPointer, Slice, Tuple, + }; + match ty { - ResolvedPath { path, did } => Type::ResolvedPath { + clean::Type::Path { path } => Type::ResolvedPath { name: path.whole_name(), - id: from_item_id(did.into()), + id: from_item_id(path.def_id().into()), args: path.segments.last().map(|args| Box::new(args.clone().args.into_tcx(tcx))), param_names: Vec::new(), }, @@ -412,7 +415,7 @@ impl FromWithTcx for Type { .map(|t| { clean::GenericBound::TraitBound(t, rustc_hir::TraitBoundModifier::None) }) - .chain(lt.into_iter().map(|lt| clean::GenericBound::Outlives(lt))) + .chain(lt.map(clean::GenericBound::Outlives)) .map(|bound| bound.into_tcx(tcx)) .collect(), } @@ -436,7 +439,7 @@ impl FromWithTcx for Type { }, QPath { name, self_type, trait_, .. } => { // FIXME: should `trait_` be a clean::Path equivalent in JSON? - let trait_ = ResolvedPath { did: trait_.def_id(), path: trait_ }.into_tcx(tcx); + let trait_ = clean::Type::Path { path: trait_ }.into_tcx(tcx); Type::QualifiedPath { name: name.to_string(), self_type: Box::new((*self_type).into_tcx(tcx)), @@ -500,22 +503,19 @@ impl FromWithTcx for Trait { impl FromWithTcx for Impl { fn from_tcx(impl_: clean::Impl, tcx: TyCtxt<'_>) -> Self { let provided_trait_methods = impl_.provided_trait_methods(tcx); - let clean::Impl { - unsafety, - generics, - trait_, - for_, - items, - negative_polarity, - synthetic, - blanket_impl, - span: _span, - } = impl_; + let clean::Impl { unsafety, generics, trait_, for_, items, polarity, kind } = impl_; // FIXME: should `trait_` be a clean::Path equivalent in JSON? - let trait_ = trait_.map(|path| { - let did = path.def_id(); - clean::ResolvedPath { path, did }.into_tcx(tcx) - }); + let trait_ = trait_.map(|path| clean::Type::Path { path }.into_tcx(tcx)); + // FIXME: use something like ImplKind in JSON? + let (synthetic, blanket_impl) = match kind { + clean::ImplKind::Normal => (false, None), + clean::ImplKind::Auto => (true, None), + clean::ImplKind::Blanket(ty) => (false, Some(*ty)), + }; + let negative_polarity = match polarity { + ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => false, + ty::ImplPolarity::Negative => true, + }; Impl { is_unsafe: unsafety == rustc_hir::Unsafety::Unsafe, generics: generics.into_tcx(tcx), @@ -528,7 +528,7 @@ impl FromWithTcx for Impl { items: ids(items), negative: negative_polarity, synthetic, - blanket_impl: blanket_impl.map(|x| (*x).into_tcx(tcx)), + blanket_impl: blanket_impl.map(|x| x.into_tcx(tcx)), } } } @@ -697,6 +697,7 @@ impl FromWithTcx for ItemKind { TraitAlias => ItemKind::TraitAlias, ProcAttribute => ItemKind::ProcAttribute, ProcDerive => ItemKind::ProcDerive, + Generic => unreachable!(), } } } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index dc7dc45136..b6311abb5c 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -9,6 +9,7 @@ #![feature(control_flow_enum)] #![feature(box_syntax)] #![feature(in_band_lifetimes)] +#![feature(let_else)] #![feature(nll)] #![feature(test)] #![feature(crate_visibility_modifier)] @@ -48,11 +49,13 @@ extern crate rustc_interface; extern crate rustc_lexer; extern crate rustc_lint; extern crate rustc_lint_defs; +extern crate rustc_macros; extern crate rustc_metadata; extern crate rustc_middle; extern crate rustc_parse; extern crate rustc_passes; extern crate rustc_resolve; +extern crate rustc_serialize; extern crate rustc_session; extern crate rustc_span; extern crate rustc_target; @@ -101,17 +104,13 @@ macro_rules! map { }} } -#[macro_use] -mod externalfiles; - mod clean; mod config; mod core; mod docfs; -mod doctree; -#[macro_use] -mod error; mod doctest; +mod error; +mod externalfiles; mod fold; mod formats; // used by the error-index generator, so it needs to be public @@ -120,7 +119,9 @@ mod json; crate mod lint; mod markdown; mod passes; +mod scrape_examples; mod theme; +mod visit; mod visit_ast; mod visit_lib; @@ -619,6 +620,30 @@ fn opts() -> Vec { "Make the identifiers in the HTML source code pages navigable", ) }), + unstable("scrape-examples-output-path", |o| { + o.optopt( + "", + "scrape-examples-output-path", + "", + "collect function call information and output at the given path", + ) + }), + unstable("scrape-examples-target-crate", |o| { + o.optmulti( + "", + "scrape-examples-target-crate", + "", + "collect function call information for functions from the target crate", + ) + }), + unstable("with-examples", |o| { + o.optmulti( + "", + "with-examples", + "", + "path to function call information (for displaying examples in the documentation)", + ) + }), ] } @@ -733,6 +758,7 @@ fn main_options(options: config::Options) -> MainResult { let externs = options.externs.clone(); let manual_passes = options.manual_passes.clone(); let render_options = options.render_options.clone(); + let scrape_examples_options = options.scrape_examples_options.clone(); let config = core::create_config(options); interface::create_compiler_and_run(config, |compiler| { @@ -750,7 +776,7 @@ fn main_options(options: config::Options) -> MainResult { // current architecture. let resolver = core::create_resolver(externs, queries, sess); - if sess.has_errors() { + if sess.diagnostic().has_errors_or_lint_errors() { sess.fatal("Compilation failed, aborting rustdoc"); } @@ -769,6 +795,10 @@ fn main_options(options: config::Options) -> MainResult { }); info!("finished with rustc"); + if let Some(options) = scrape_examples_options { + return scrape_examples::run(krate, render_opts, cache, tcx, options); + } + cache.crate_version = crate_version; if show_coverage { diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 47b24d40ed..abb4bec5ca 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -131,7 +131,6 @@ crate fn test(options: Options) -> Result<(), String> { .map_err(|err| format!("{}: {}", options.input.display(), err))?; let mut opts = TestOptions::default(); opts.no_crate_inject = true; - opts.display_doctest_warnings = options.display_doctest_warnings; let mut collector = Collector::new( Symbol::intern(&options.input.display().to_string()), options.clone(), @@ -146,11 +145,6 @@ crate fn test(options: Options) -> Result<(), String> { find_testable_code(&input_str, &mut collector, codes, options.enable_per_target_ignores, None); - crate::doctest::run_tests( - options.test_args, - options.nocapture, - options.display_doctest_warnings, - collector.tests, - ); + crate::doctest::run_tests(options.test_args, options.nocapture, collector.tests); Ok(()) } diff --git a/src/librustdoc/passes/bare_urls.rs b/src/librustdoc/passes/bare_urls.rs index 37faa67429..4e146a07d1 100644 --- a/src/librustdoc/passes/bare_urls.rs +++ b/src/librustdoc/passes/bare_urls.rs @@ -1,8 +1,8 @@ use super::Pass; use crate::clean::*; use crate::core::DocContext; -use crate::fold::DocFolder; use crate::html::markdown::main_body_opts; +use crate::visit::DocVisitor; use core::ops::Range; use pulldown_cmark::{Event, Parser, Tag}; use regex::Regex; @@ -39,7 +39,7 @@ impl<'a, 'tcx> BareUrlsLinter<'a, 'tcx> { ) { 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) { + for match_ in URL_REGEX.find_iter(text) { let url = match_.as_str(); let url_range = match_.range(); f( @@ -53,16 +53,17 @@ impl<'a, 'tcx> BareUrlsLinter<'a, 'tcx> { } crate fn check_bare_urls(krate: Crate, cx: &mut DocContext<'_>) -> Crate { - BareUrlsLinter { cx }.fold_crate(krate) + BareUrlsLinter { cx }.visit_crate(&krate); + krate } -impl<'a, 'tcx> DocFolder for BareUrlsLinter<'a, 'tcx> { - fn fold_item(&mut self, item: Item) -> Option { +impl<'a, 'tcx> DocVisitor for BareUrlsLinter<'a, 'tcx> { + fn visit_item(&mut self, item: &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)); + return; } }; let dox = item.attrs.collapsed_doc_value().unwrap_or_default(); @@ -106,6 +107,6 @@ impl<'a, 'tcx> DocFolder for BareUrlsLinter<'a, 'tcx> { } } - Some(self.fold_item_recur(item)) + self.visit_item_recur(item) } } diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index 5e3bd41b85..85542ebd9a 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -1,9 +1,9 @@ use crate::clean; use crate::core::DocContext; -use crate::fold::{self, DocFolder}; use crate::html::markdown::{find_testable_code, ErrorCodes}; use crate::passes::check_doc_test_visibility::{should_have_doc_example, Tests}; use crate::passes::Pass; +use crate::visit::DocVisitor; use rustc_hir as hir; use rustc_lint::builtin::MISSING_DOCS; use rustc_middle::lint::LintLevelSource; @@ -23,7 +23,7 @@ crate const CALCULATE_DOC_COVERAGE: Pass = Pass { fn calculate_doc_coverage(krate: clean::Crate, ctx: &mut DocContext<'_>) -> clean::Crate { let mut calc = CoverageCalculator { items: Default::default(), ctx }; - let krate = calc.fold_crate(krate); + calc.visit_crate(&krate); calc.print_results(); @@ -182,17 +182,18 @@ impl<'a, 'b> CoverageCalculator<'a, 'b> { } } -impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> { - fn fold_item(&mut self, i: clean::Item) -> Option { +impl<'a, 'b> DocVisitor for CoverageCalculator<'a, 'b> { + fn visit_item(&mut self, i: &clean::Item) { + if !i.def_id.is_local() { + // non-local items are skipped because they can be out of the users control, + // especially in the case of trait impls, which rustdoc eagerly inlines + return; + } + match *i.kind { - _ if !i.def_id.is_local() => { - // non-local items are skipped because they can be out of the users control, - // especially in the case of trait impls, which rustdoc eagerly inlines - return Some(i); - } clean::StrippedItem(..) => { // don't count items in stripped modules - return Some(i); + return; } // docs on `use` and `extern crate` statements are not displayed, so they're not // worth counting @@ -269,6 +270,6 @@ impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> { } } - Some(self.fold_item_recur(i)) + self.visit_item_recur(i) } } diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs index d2b3c5239c..fd2ab0dc97 100644 --- a/src/librustdoc/passes/check_code_block_syntax.rs +++ b/src/librustdoc/passes/check_code_block_syntax.rs @@ -8,9 +8,9 @@ use rustc_span::{hygiene::AstPass, ExpnData, ExpnKind, FileName, InnerSpan, DUMM use crate::clean; use crate::core::DocContext; -use crate::fold::DocFolder; use crate::html::markdown::{self, RustCodeBlock}; use crate::passes::Pass; +use crate::visit::DocVisitor; crate const CHECK_CODE_BLOCK_SYNTAX: Pass = Pass { name: "check-code-block-syntax", @@ -19,7 +19,8 @@ crate const CHECK_CODE_BLOCK_SYNTAX: Pass = Pass { }; crate fn check_code_block_syntax(krate: clean::Crate, cx: &mut DocContext<'_>) -> clean::Crate { - SyntaxChecker { cx }.fold_crate(krate) + SyntaxChecker { cx }.visit_crate(&krate); + krate } struct SyntaxChecker<'a, 'tcx> { @@ -36,7 +37,7 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> { let source = dox[code_block.code].to_owned(); let sess = ParseSess::with_span_handler(handler, sm); - let edition = code_block.lang_string.edition.unwrap_or(self.cx.tcx.sess.edition()); + let edition = code_block.lang_string.edition.unwrap_or_else(|| self.cx.tcx.sess.edition()); let expn_data = ExpnData::default( ExpnKind::AstPass(AstPass::TestHarness), DUMMY_SP, @@ -77,7 +78,7 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> { // The span and whether it is precise or not. let (sp, precise_span) = match super::source_span_for_markdown_range( self.cx.tcx, - &dox, + dox, &code_block.range, &item.attrs, ) { @@ -123,7 +124,7 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> { // FIXME(#67563): Provide more context for these errors by displaying the spans inline. for message in buffer.messages.iter() { - diag.note(&message); + diag.note(message); } diag.emit(); @@ -141,8 +142,8 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> { } } -impl<'a, 'tcx> DocFolder for SyntaxChecker<'a, 'tcx> { - fn fold_item(&mut self, item: clean::Item) -> Option { +impl<'a, 'tcx> DocVisitor for SyntaxChecker<'a, 'tcx> { + fn visit_item(&mut self, item: &clean::Item) { if let Some(dox) = &item.attrs.collapsed_doc_value() { let sp = item.attr_span(self.cx.tcx); let extra = crate::html::markdown::ExtraInfo::new_did( @@ -150,12 +151,12 @@ impl<'a, 'tcx> DocFolder for SyntaxChecker<'a, 'tcx> { item.def_id.expect_def_id(), sp, ); - for code_block in markdown::rust_code_blocks(&dox, &extra) { - self.check_rust_syntax(&item, &dox, code_block); + for code_block in markdown::rust_code_blocks(dox, &extra) { + self.check_rust_syntax(&item, dox, code_block); } } - Some(self.fold_item_recur(item)) + self.visit_item_recur(item) } } diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs index 1f7d605423..7d3010cf33 100644 --- a/src/librustdoc/passes/check_doc_test_visibility.rs +++ b/src/librustdoc/passes/check_doc_test_visibility.rs @@ -7,8 +7,8 @@ use super::Pass; use crate::clean; use crate::clean::*; use crate::core::DocContext; -use crate::fold::DocFolder; use crate::html::markdown::{find_testable_code, ErrorCodes, Ignore, LangString}; +use crate::visit::DocVisitor; use crate::visit_ast::inherits_doc_hidden; use rustc_hir as hir; use rustc_middle::lint::LintLevelSource; @@ -27,17 +27,17 @@ struct DocTestVisibilityLinter<'a, 'tcx> { crate fn check_doc_test_visibility(krate: Crate, cx: &mut DocContext<'_>) -> Crate { let mut coll = DocTestVisibilityLinter { cx }; - - coll.fold_crate(krate) + coll.visit_crate(&krate); + krate } -impl<'a, 'tcx> DocFolder for DocTestVisibilityLinter<'a, 'tcx> { - fn fold_item(&mut self, item: Item) -> Option { +impl<'a, 'tcx> DocVisitor for DocTestVisibilityLinter<'a, 'tcx> { + fn visit_item(&mut self, item: &Item) { let dox = item.attrs.collapsed_doc_value().unwrap_or_else(String::new); look_for_tests(self.cx, &dox, &item); - Some(self.fold_item_recur(item)) + self.visit_item_recur(item) } } @@ -115,10 +115,10 @@ crate fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) { let mut tests = Tests { found_tests: 0 }; - find_testable_code(&dox, &mut tests, ErrorCodes::No, false, None); + find_testable_code(dox, &mut tests, ErrorCodes::No, false, None); if tests.found_tests == 0 && cx.tcx.sess.is_nightly_build() { - if should_have_doc_example(cx, &item) { + if should_have_doc_example(cx, item) { debug!("reporting error for {:?} (hir_id={:?})", item, hir_id); let sp = item.attr_span(cx.tcx); cx.tcx.struct_span_lint_hir( diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 318c897bcb..4e5812d7f8 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -32,10 +32,10 @@ use std::ops::Range; use crate::clean::{self, utils::find_nearest_parent_module, Crate, Item, ItemLink, PrimitiveType}; use crate::core::DocContext; -use crate::fold::DocFolder; use crate::html::markdown::{markdown_links, MarkdownLink}; use crate::lint::{BROKEN_INTRA_DOC_LINKS, PRIVATE_INTRA_DOC_LINKS}; use crate::passes::Pass; +use crate::visit::DocVisitor; mod early; crate use early::load_intra_link_crates; @@ -47,13 +47,14 @@ crate const COLLECT_INTRA_DOC_LINKS: Pass = Pass { }; fn collect_intra_doc_links(krate: Crate, cx: &mut DocContext<'_>) -> Crate { - LinkCollector { + let mut collector = LinkCollector { cx, mod_ids: Vec::new(), kind_side_channel: Cell::new(None), visited_links: FxHashMap::default(), - } - .fold_crate(krate) + }; + collector.visit_crate(&krate); + krate } /// Top-level errors emitted by this pass. @@ -289,7 +290,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { ) -> Result<(Res, Option), ErrorKind<'path>> { let tcx = self.cx.tcx; let no_res = || ResolutionFailure::NotResolved { - module_id: module_id, + module_id, partial_res: None, unresolved: path_str.into(), }; @@ -437,7 +438,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { fn resolve_path(&self, path_str: &str, ns: Namespace, module_id: DefId) -> Option { let result = self.cx.enter_resolver(|resolver| { resolver - .resolve_str_path_error(DUMMY_SP, &path_str, ns, module_id) + .resolve_str_path_error(DUMMY_SP, path_str, ns, module_id) .and_then(|(_, res)| res.try_into()) }); debug!("{} resolved to {:?} in namespace {:?}", path_str, result, ns); @@ -543,7 +544,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { ty::Uint(uty) => Res::Primitive(uty.into()), ty::Float(fty) => Res::Primitive(fty.into()), ty::Str => Res::Primitive(Str), - ty::Tuple(ref tys) if tys.is_empty() => Res::Primitive(Unit), + ty::Tuple(tys) if tys.is_empty() => Res::Primitive(Unit), ty::Tuple(_) => Res::Primitive(Tuple), ty::Array(..) => Res::Primitive(Array), ty::Slice(_) => Res::Primitive(Slice), @@ -816,8 +817,8 @@ fn is_derive_trait_collision(ns: &PerNS DocFolder for LinkCollector<'a, 'tcx> { - fn fold_item(&mut self, item: Item) -> Option { +impl<'a, 'tcx> DocVisitor for LinkCollector<'a, 'tcx> { + fn visit_item(&mut self, item: &Item) { use rustc_middle::ty::DefIdTree; let parent_node = @@ -911,17 +912,16 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { } } - Some(if item.is_mod() { + if item.is_mod() { if !inner_docs { self.mod_ids.push(item.def_id.expect_def_id()); } - let ret = self.fold_item_recur(item); + self.visit_item_recur(item); self.mod_ids.pop(); - ret } else { - self.fold_item_recur(item) - }) + self.visit_item_recur(item) + } } } @@ -978,13 +978,13 @@ fn preprocess_link<'a>( } // Parse and strip the disambiguator from the link, if present. - let (disambiguator, path_str, link_text) = match Disambiguator::from_str(&link) { + let (disambiguator, path_str, link_text) = match Disambiguator::from_str(link) { Ok(Some((d, path, link_text))) => (Some(d), path.trim(), link_text.trim()), Ok(None) => (None, link.trim(), link.trim()), Err((err_msg, relative_range)) => { // Only report error if we would not have ignored this link. See issue #83859. if !should_ignore_link_with_disambiguators(link) { - let no_backticks_range = range_between_backticks(&ori_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))); @@ -1000,7 +1000,7 @@ fn preprocess_link<'a>( // Strip generics from the path. let path_str = if path_str.contains(['<', '>'].as_slice()) { - match strip_generics_from_path(&path_str) { + match strip_generics_from_path(path_str) { Ok(path) => path, Err(err_kind) => { debug!("link has malformed generics: {}", path_str); @@ -1228,7 +1228,7 @@ impl LinkCollector<'_, '_> { if self.cx.tcx.privacy_access_levels(()).is_exported(src_id) && !self.cx.tcx.privacy_access_levels(()).is_exported(dst_id) { - privacy_error(self.cx, &diag_info, &path_str); + privacy_error(self.cx, &diag_info, path_str); } } @@ -1766,8 +1766,8 @@ fn report_diagnostic( let span = super::source_span_for_markdown_range(tcx, dox, link_range, &item.attrs).map(|sp| { - if dox.bytes().nth(link_range.start) == Some(b'`') - && dox.bytes().nth(link_range.end - 1) == Some(b'`') + if dox.as_bytes().get(link_range.start) == Some(&b'`') + && dox.as_bytes().get(link_range.end - 1) == Some(&b'`') { sp.with_lo(sp.lo() + BytePos(1)).with_hi(sp.hi() - BytePos(1)) } else { @@ -1868,8 +1868,7 @@ fn resolution_failure( }; name = start; for ns in [TypeNS, ValueNS, MacroNS] { - if let Some(res) = - collector.check_full_res(ns, &start, module_id, &None) + if let Some(res) = collector.check_full_res(ns, start, module_id, &None) { debug!("found partial_res={:?}", res); *partial_res = Some(res); @@ -1938,7 +1937,8 @@ fn resolution_failure( | Use | LifetimeParam | Ctor(_, _) - | AnonConst => { + | AnonConst + | InlineConst => { let note = assoc_item_not_allowed(res); if let Some(span) = sp { diag.span_label(span, ¬e); diff --git a/src/librustdoc/passes/collect_intra_doc_links/early.rs b/src/librustdoc/passes/collect_intra_doc_links/early.rs index d5148fed5c..4cebf741e2 100644 --- a/src/librustdoc/passes/collect_intra_doc_links/early.rs +++ b/src/librustdoc/passes/collect_intra_doc_links/early.rs @@ -35,7 +35,7 @@ impl IntraLinkCrateLoader { let attrs = crate::clean::Attributes::from_ast(attrs, None); for (parent_module, doc) in attrs.collapsed_doc_value_by_module_level() { debug!(?doc); - for link in markdown_links(&doc.as_str()) { + for link in markdown_links(doc.as_str()) { debug!(?link.link); let path_str = if let Some(Ok(x)) = preprocess_link(&link) { x.path_str @@ -47,7 +47,7 @@ impl IntraLinkCrateLoader { span, &path_str, TypeNS, - parent_module.unwrap_or(self.current_mod.to_def_id()), + parent_module.unwrap_or_else(|| self.current_mod.to_def_id()), ); }); } diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 319dd7b42b..8524f872ca 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -1,9 +1,10 @@ use super::Pass; use crate::clean::*; use crate::core::DocContext; -use crate::fold::DocFolder; +use crate::visit::DocVisitor; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_hir::def_id::DefId; use rustc_middle::ty::DefIdTree; use rustc_span::symbol::sym; @@ -13,17 +14,18 @@ crate const COLLECT_TRAIT_IMPLS: Pass = Pass { description: "retrieves trait impls for items in the crate", }; -crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate { - let (mut krate, synth_impls) = cx.sess().time("collect_synthetic_impls", || { +crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate { + let synth_impls = cx.sess().time("collect_synthetic_impls", || { let mut synth = SyntheticImplCollector { cx, impls: Vec::new() }; - (synth.fold_crate(krate), synth.impls) + synth.visit_crate(&krate); + synth.impls }); let prims: FxHashSet = krate.primitives.iter().map(|p| p.1).collect(); let crate_items = { let mut coll = ItemCollector::new(); - krate = cx.sess().time("collect_items_for_trait_impls", || coll.fold_crate(krate)); + cx.sess().time("collect_items_for_trait_impls", || coll.visit_crate(&krate)); coll.items }; @@ -31,9 +33,7 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate { for &cnum in cx.tcx.crates(()).iter() { for &(did, _) in cx.tcx.all_trait_implementations(cnum).iter() { - cx.tcx.sess.prof.generic_activity("build_extern_trait_impl").run(|| { - inline::build_impl(cx, None, did, None, &mut new_items); - }); + inline::build_impl(cx, None, did, None, &mut new_items); } } @@ -53,12 +53,36 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate { } let mut cleaner = BadImplStripper { prims, items: crate_items }; + let mut type_did_to_deref_target: FxHashMap = FxHashMap::default(); + + // Follow all `Deref` targets of included items and recursively add them as valid + fn add_deref_target( + cx: &DocContext<'_>, + map: &FxHashMap, + cleaner: &mut BadImplStripper, + type_did: DefId, + ) { + if let Some(target) = map.get(&type_did) { + debug!("add_deref_target: type {:?}, target {:?}", type_did, target); + if let Some(target_prim) = target.primitive_type() { + cleaner.prims.insert(target_prim); + } else if let Some(target_did) = target.def_id(&cx.cache) { + // `impl Deref for S` + if target_did == type_did { + // Avoid infinite cycles + return; + } + cleaner.items.insert(target_did.into()); + add_deref_target(cx, map, cleaner, target_did); + } + } + } // scan through included items ahead of time to splice in Deref targets to the "valid" sets for it in &new_items { if let ImplItem(Impl { ref for_, ref trait_, ref items, .. }) = *it.kind { - if cleaner.keep_impl(for_) - && trait_.as_ref().map(|t| t.def_id()) == cx.tcx.lang_items().deref_trait() + if trait_.as_ref().map(|t| t.def_id()) == cx.tcx.lang_items().deref_trait() + && cleaner.keep_impl(for_, true) { let target = items .iter() @@ -70,20 +94,30 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate { if let Some(prim) = target.primitive_type() { cleaner.prims.insert(prim); - } else if let Some(did) = target.def_id() { + } else if let Some(did) = target.def_id(&cx.cache) { cleaner.items.insert(did.into()); } + if let Some(for_did) = for_.def_id_no_primitives() { + if type_did_to_deref_target.insert(for_did, target).is_none() { + // Since only the `DefId` portion of the `Type` instances is known to be same for both the + // `Deref` target type and the impl for type positions, this map of types is keyed by + // `DefId` and for convenience uses a special cleaner that accepts `DefId`s directly. + if cleaner.keep_impl_with_def_id(for_did.into()) { + add_deref_target(cx, &type_did_to_deref_target, &mut cleaner, for_did); + } + } + } } } } new_items.retain(|it| { - if let ImplItem(Impl { ref for_, ref trait_, ref blanket_impl, .. }) = *it.kind { - cleaner.keep_impl(for_) - || trait_ - .as_ref() - .map_or(false, |t| cleaner.keep_impl_with_def_id(t.def_id().into())) - || blanket_impl.is_some() + if let ImplItem(Impl { ref for_, ref trait_, ref kind, .. }) = *it.kind { + cleaner.keep_impl( + for_, + trait_.as_ref().map(|t| t.def_id()) == cx.tcx.lang_items().deref_trait(), + ) || trait_.as_ref().map_or(false, |t| cleaner.keep_impl_with_def_id(t.def_id().into())) + || kind.is_blanket() } else { true } @@ -120,14 +154,13 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate { } } - let items = if let ModuleItem(Module { ref mut items, .. }) = *krate.module.kind { - items + if let ModuleItem(Module { items, .. }) = &mut *krate.module.kind { + items.extend(synth_impls); + items.extend(new_items); } else { panic!("collect-trait-impls can't run"); }; - items.extend(synth_impls); - items.extend(new_items); krate } @@ -136,8 +169,8 @@ struct SyntheticImplCollector<'a, 'tcx> { impls: Vec, } -impl<'a, 'tcx> DocFolder for SyntheticImplCollector<'a, 'tcx> { - fn fold_item(&mut self, i: Item) -> Option { +impl<'a, 'tcx> DocVisitor for SyntheticImplCollector<'a, 'tcx> { + fn visit_item(&mut self, i: &Item) { if i.is_struct() || i.is_enum() || i.is_union() { // FIXME(eddyb) is this `doc(hidden)` check needed? if !self @@ -152,7 +185,7 @@ impl<'a, 'tcx> DocFolder for SyntheticImplCollector<'a, 'tcx> { } } - Some(self.fold_item_recur(i)) + self.visit_item_recur(i) } } @@ -167,11 +200,11 @@ impl ItemCollector { } } -impl DocFolder for ItemCollector { - fn fold_item(&mut self, i: Item) -> Option { +impl DocVisitor for ItemCollector { + fn visit_item(&mut self, i: &Item) { self.items.insert(i.def_id); - Some(self.fold_item_recur(i)) + self.visit_item_recur(i) } } @@ -181,14 +214,14 @@ struct BadImplStripper { } impl BadImplStripper { - fn keep_impl(&self, ty: &Type) -> bool { + fn keep_impl(&self, ty: &Type, is_deref: bool) -> bool { if let Generic(_) = ty { // keep impls made on generics true } else if let Some(prim) = ty.primitive_type() { self.prims.contains(&prim) - } else if let Some(did) = ty.def_id() { - self.keep_impl_with_def_id(did.into()) + } else if let Some(did) = ty.def_id_no_primitives() { + is_deref || self.keep_impl_with_def_id(did.into()) } else { false } diff --git a/src/librustdoc/passes/html_tags.rs b/src/librustdoc/passes/html_tags.rs index a3fde92d76..56b222d893 100644 --- a/src/librustdoc/passes/html_tags.rs +++ b/src/librustdoc/passes/html_tags.rs @@ -1,11 +1,13 @@ use super::Pass; use crate::clean::*; use crate::core::DocContext; -use crate::fold::DocFolder; use crate::html::markdown::main_body_opts; -use core::ops::Range; +use crate::visit::DocVisitor; + use pulldown_cmark::{Event, Parser, Tag}; + use std::iter::Peekable; +use std::ops::Range; use std::str::CharIndices; crate const CHECK_INVALID_HTML_TAGS: Pass = Pass { @@ -19,13 +21,11 @@ struct InvalidHtmlTagsLinter<'a, 'tcx> { } crate fn check_invalid_html_tags(krate: Crate, cx: &mut DocContext<'_>) -> Crate { - if !cx.tcx.sess.is_nightly_build() { - krate - } else { + if cx.tcx.sess.is_nightly_build() { let mut coll = InvalidHtmlTagsLinter { cx }; - - coll.fold_crate(krate) + coll.visit_crate(&krate); } + krate } const ALLOWED_UNCLOSED: &[&str] = &[ @@ -165,14 +165,14 @@ fn extract_tags( } } -impl<'a, 'tcx> DocFolder for InvalidHtmlTagsLinter<'a, 'tcx> { - fn fold_item(&mut self, item: Item) -> Option { +impl<'a, 'tcx> DocVisitor for InvalidHtmlTagsLinter<'a, 'tcx> { + fn visit_item(&mut self, item: &Item) { let tcx = self.cx.tcx; let hir_id = match DocContext::as_local_hir_id(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)); + return; } }; let dox = item.attrs.collapsed_doc_value().unwrap_or_default(); @@ -217,6 +217,6 @@ impl<'a, 'tcx> DocFolder for InvalidHtmlTagsLinter<'a, 'tcx> { } } - Some(self.fold_item_recur(item)) + self.visit_item_recur(item) } } diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index 8b1fd662f8..74a9a2da06 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -2,7 +2,7 @@ use rustc_hir::def_id::DefId; use rustc_middle::middle::privacy::AccessLevels; use std::mem; -use crate::clean::{self, GetDefId, Item, ItemIdSet}; +use crate::clean::{self, Item, ItemIdSet}; use crate::fold::{strip_item, DocFolder}; crate struct Stripper<'a> { @@ -127,7 +127,7 @@ impl<'a> DocFolder for ImplStripper<'a> { if imp.trait_.is_none() && imp.items.is_empty() { return None; } - if let Some(did) = imp.for_.def_id() { + if let Some(did) = imp.for_.def_id_no_primitives() { if did.is_local() && !imp.for_.is_assoc_ty() && !self.retained.contains(&did.into()) { debug!("ImplStripper: impl item for stripped type; removing"); @@ -142,7 +142,7 @@ impl<'a> DocFolder for ImplStripper<'a> { } if let Some(generics) = imp.trait_.as_ref().and_then(|t| t.generics()) { for typaram in generics { - if let Some(did) = typaram.def_id() { + if let Some(did) = typaram.def_id_no_primitives() { if did.is_local() && !self.retained.contains(&did.into()) { debug!( "ImplStripper: stripped item in trait's generics; removing impl" diff --git a/src/librustdoc/passes/unindent_comments.rs b/src/librustdoc/passes/unindent_comments.rs index da2eda7364..97f4f941e0 100644 --- a/src/librustdoc/passes/unindent_comments.rs +++ b/src/librustdoc/passes/unindent_comments.rs @@ -1,5 +1,7 @@ use std::cmp; +use rustc_span::symbol::kw; + use crate::clean::{self, DocFragment, DocFragmentKind, Item}; use crate::core::DocContext; use crate::fold::{self, DocFolder}; @@ -87,7 +89,7 @@ fn unindent_fragments(docs: &mut Vec) { }; for fragment in docs { - if fragment.doc.as_str().lines().count() == 0 { + if fragment.doc == kw::Empty { continue; } diff --git a/src/librustdoc/passes/unindent_comments/tests.rs b/src/librustdoc/passes/unindent_comments/tests.rs index 82d1afac5e..daec04e11c 100644 --- a/src/librustdoc/passes/unindent_comments/tests.rs +++ b/src/librustdoc/passes/unindent_comments/tests.rs @@ -5,7 +5,6 @@ use rustc_span::symbol::Symbol; fn create_doc_fragment(s: &str) -> Vec { vec![DocFragment { - line: 0, span: DUMMY_SP, parent_module: None, doc: Symbol::intern(s), diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs new file mode 100644 index 0000000000..10b6fdf87f --- /dev/null +++ b/src/librustdoc/scrape_examples.rs @@ -0,0 +1,305 @@ +//! This module analyzes crates to find call sites that can serve as examples in the documentation. + +use crate::clean; +use crate::config; +use crate::formats; +use crate::formats::renderer::FormatRenderer; +use crate::html::render::Context; + +use rustc_data_structures::fx::FxHashMap; +use rustc_hir::{ + self as hir, + intravisit::{self, Visitor}, +}; +use rustc_interface::interface; +use rustc_macros::{Decodable, Encodable}; +use rustc_middle::hir::map::Map; +use rustc_middle::ty::{self, TyCtxt}; +use rustc_serialize::{ + opaque::{Decoder, FileEncoder}, + Decodable, Encodable, +}; +use rustc_session::getopts; +use rustc_span::{ + def_id::{CrateNum, DefPathHash, LOCAL_CRATE}, + edition::Edition, + BytePos, FileName, SourceFile, +}; + +use std::fs; +use std::path::PathBuf; + +#[derive(Debug, Clone)] +crate struct ScrapeExamplesOptions { + output_path: PathBuf, + target_crates: Vec, +} + +impl ScrapeExamplesOptions { + crate fn new( + matches: &getopts::Matches, + diag: &rustc_errors::Handler, + ) -> Result, i32> { + let output_path = matches.opt_str("scrape-examples-output-path"); + let target_crates = matches.opt_strs("scrape-examples-target-crate"); + match (output_path, !target_crates.is_empty()) { + (Some(output_path), true) => Ok(Some(ScrapeExamplesOptions { + output_path: PathBuf::from(output_path), + target_crates, + })), + (Some(_), false) | (None, true) => { + diag.err("must use --scrape-examples-output-path and --scrape-examples-target-crate together"); + Err(1) + } + (None, false) => Ok(None), + } + } +} + +#[derive(Encodable, Decodable, Debug, Clone)] +crate struct SyntaxRange { + crate byte_span: (u32, u32), + crate line_span: (usize, usize), +} + +impl SyntaxRange { + fn new(span: rustc_span::Span, file: &SourceFile) -> Self { + let get_pos = |bytepos: BytePos| file.original_relative_byte_pos(bytepos).0; + let get_line = |bytepos: BytePos| file.lookup_line(bytepos).unwrap(); + + SyntaxRange { + byte_span: (get_pos(span.lo()), get_pos(span.hi())), + line_span: (get_line(span.lo()), get_line(span.hi())), + } + } +} + +#[derive(Encodable, Decodable, Debug, Clone)] +crate struct CallLocation { + crate call_expr: SyntaxRange, + crate enclosing_item: SyntaxRange, +} + +impl CallLocation { + fn new( + expr_span: rustc_span::Span, + enclosing_item_span: rustc_span::Span, + source_file: &SourceFile, + ) -> Self { + CallLocation { + call_expr: SyntaxRange::new(expr_span, source_file), + enclosing_item: SyntaxRange::new(enclosing_item_span, source_file), + } + } +} + +#[derive(Encodable, Decodable, Debug, Clone)] +crate struct CallData { + crate locations: Vec, + crate url: String, + crate display_name: String, + crate edition: Edition, +} + +crate type FnCallLocations = FxHashMap; +crate type AllCallLocations = FxHashMap; + +/// Visitor for traversing a crate and finding instances of function calls. +struct FindCalls<'a, 'tcx> { + tcx: TyCtxt<'tcx>, + map: Map<'tcx>, + cx: Context<'tcx>, + target_crates: Vec, + calls: &'a mut AllCallLocations, +} + +impl<'a, 'tcx> Visitor<'tcx> for FindCalls<'a, 'tcx> +where + 'tcx: 'a, +{ + type Map = Map<'tcx>; + + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { + intravisit::NestedVisitorMap::OnlyBodies(self.map) + } + + fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) { + intravisit::walk_expr(self, ex); + + let tcx = self.tcx; + + // If we visit an item that contains an expression outside a function body, + // then we need to exit before calling typeck (which will panic). See + // test/run-make/rustdoc-scrape-examples-invalid-expr for an example. + let hir = tcx.hir(); + let owner = hir.local_def_id_to_hir_id(ex.hir_id.owner); + if hir.maybe_body_owned_by(owner).is_none() { + return; + } + + // Get type of function if expression is a function call + let (ty, span) = match ex.kind { + hir::ExprKind::Call(f, _) => { + let types = tcx.typeck(ex.hir_id.owner); + + if let Some(ty) = types.node_type_opt(f.hir_id) { + (ty, ex.span) + } else { + trace!("node_type_opt({}) = None", f.hir_id); + return; + } + } + hir::ExprKind::MethodCall(_, _, _, span) => { + let types = tcx.typeck(ex.hir_id.owner); + let def_id = if let Some(def_id) = types.type_dependent_def_id(ex.hir_id) { + def_id + } else { + trace!("type_dependent_def_id({}) = None", ex.hir_id); + return; + }; + (tcx.type_of(def_id), span) + } + _ => { + return; + } + }; + + // If this span comes from a macro expansion, then the source code may not actually show + // a use of the given item, so it would be a poor example. Hence, we skip all uses in macros. + if span.from_expansion() { + trace!("Rejecting expr from macro: {:?}", span); + return; + } + + // If the enclosing item has a span coming from a proc macro, then we also don't want to include + // the example. + let enclosing_item_span = tcx.hir().span_with_body(tcx.hir().get_parent_item(ex.hir_id)); + if enclosing_item_span.from_expansion() { + trace!("Rejecting expr ({:?}) from macro item: {:?}", span, enclosing_item_span); + return; + } + + assert!( + enclosing_item_span.contains(span), + "Attempted to scrape call at [{:?}] whose enclosing item [{:?}] doesn't contain the span of the call.", + span, + enclosing_item_span + ); + + // Save call site if the function resolves to a concrete definition + if let ty::FnDef(def_id, _) = ty.kind() { + if self.target_crates.iter().all(|krate| *krate != def_id.krate) { + trace!("Rejecting expr from crate not being documented: {:?}", span); + return; + } + + let file = tcx.sess.source_map().lookup_char_pos(span.lo()).file; + let file_path = match file.name.clone() { + FileName::Real(real_filename) => real_filename.into_local_path(), + _ => None, + }; + + if let Some(file_path) = file_path { + let abs_path = fs::canonicalize(file_path.clone()).unwrap(); + let cx = &self.cx; + let mk_call_data = || { + let clean_span = crate::clean::types::Span::new(span); + let url = cx.href_from_span(clean_span, false).unwrap(); + let display_name = file_path.display().to_string(); + let edition = span.edition(); + CallData { locations: Vec::new(), url, display_name, edition } + }; + + let fn_key = tcx.def_path_hash(*def_id); + let fn_entries = self.calls.entry(fn_key).or_default(); + + trace!("Including expr: {:?}", span); + let location = CallLocation::new(span, enclosing_item_span, &file); + fn_entries.entry(abs_path).or_insert_with(mk_call_data).locations.push(location); + } + } + } +} + +crate fn run( + krate: clean::Crate, + renderopts: config::RenderOptions, + cache: formats::cache::Cache, + tcx: TyCtxt<'_>, + options: ScrapeExamplesOptions, +) -> interface::Result<()> { + let inner = move || -> Result<(), String> { + // Generates source files for examples + let (cx, _) = Context::init(krate, renderopts, cache, tcx).map_err(|e| e.to_string())?; + + // Collect CrateIds corresponding to provided target crates + // If two different versions of the crate in the dependency tree, then examples will be collcted from both. + let all_crates = tcx + .crates(()) + .iter() + .chain([&LOCAL_CRATE]) + .map(|crate_num| (crate_num, tcx.crate_name(*crate_num))) + .collect::>(); + let target_crates = options + .target_crates + .into_iter() + .map(|target| all_crates.iter().filter(move |(_, name)| name.as_str() == target)) + .flatten() + .map(|(crate_num, _)| **crate_num) + .collect::>(); + + debug!("All crates in TyCtxt: {:?}", all_crates); + debug!("Scrape examples target_crates: {:?}", target_crates); + + // Run call-finder on all items + let mut calls = FxHashMap::default(); + let mut finder = FindCalls { calls: &mut calls, tcx, map: tcx.hir(), cx, target_crates }; + tcx.hir().visit_all_item_likes(&mut finder.as_deep_visitor()); + + // Sort call locations within a given file in document order + for fn_calls in calls.values_mut() { + for file_calls in fn_calls.values_mut() { + file_calls.locations.sort_by_key(|loc| loc.call_expr.byte_span.0); + } + } + + // Save output to provided path + let mut encoder = FileEncoder::new(options.output_path).map_err(|e| e.to_string())?; + calls.encode(&mut encoder).map_err(|e| e.to_string())?; + encoder.flush().map_err(|e| e.to_string())?; + + Ok(()) + }; + + if let Err(e) = inner() { + tcx.sess.fatal(&e); + } + + Ok(()) +} + +// Note: the Handler must be passed in explicitly because sess isn't available while parsing options +crate fn load_call_locations( + with_examples: Vec, + diag: &rustc_errors::Handler, +) -> Result { + let inner = || { + let mut all_calls: AllCallLocations = FxHashMap::default(); + for path in with_examples { + let bytes = fs::read(&path).map_err(|e| format!("{} (for path {})", e, path))?; + let mut decoder = Decoder::new(&bytes, 0); + let calls = AllCallLocations::decode(&mut decoder)?; + + for (function, fn_calls) in calls.into_iter() { + all_calls.entry(function).or_default().extend(fn_calls.into_iter()); + } + } + + Ok(all_calls) + }; + + inner().map_err(|e: String| { + diag.err(&format!("failed to load examples: {}", e)); + 1 + }) +} diff --git a/src/librustdoc/visit.rs b/src/librustdoc/visit.rs new file mode 100644 index 0000000000..df4d1558eb --- /dev/null +++ b/src/librustdoc/visit.rs @@ -0,0 +1,71 @@ +use crate::clean::*; + +crate trait DocVisitor: Sized { + fn visit_item(&mut self, item: &Item) { + self.visit_item_recur(item) + } + + /// don't override! + fn visit_inner_recur(&mut self, kind: &ItemKind) { + match kind { + StrippedItem(..) => unreachable!(), + ModuleItem(i) => { + self.visit_mod(i); + return; + } + StructItem(i) => i.fields.iter().for_each(|x| self.visit_item(x)), + UnionItem(i) => i.fields.iter().for_each(|x| self.visit_item(x)), + EnumItem(i) => i.variants.iter().for_each(|x| self.visit_item(x)), + TraitItem(i) => i.items.iter().for_each(|x| self.visit_item(x)), + ImplItem(i) => i.items.iter().for_each(|x| self.visit_item(x)), + VariantItem(i) => match i { + Variant::Struct(j) => j.fields.iter().for_each(|x| self.visit_item(x)), + Variant::Tuple(fields) => fields.iter().for_each(|x| self.visit_item(x)), + Variant::CLike => {} + }, + ExternCrateItem { src: _ } + | ImportItem(_) + | FunctionItem(_) + | TypedefItem(_, _) + | OpaqueTyItem(_) + | StaticItem(_) + | ConstantItem(_) + | TraitAliasItem(_) + | TyMethodItem(_) + | MethodItem(_, _) + | StructFieldItem(_) + | ForeignFunctionItem(_) + | ForeignStaticItem(_) + | ForeignTypeItem + | MacroItem(_) + | ProcMacroItem(_) + | PrimitiveItem(_) + | AssocConstItem(_, _) + | AssocTypeItem(_, _) + | KeywordItem(_) => {} + } + } + + /// don't override! + fn visit_item_recur(&mut self, item: &Item) { + match &*item.kind { + StrippedItem(i) => self.visit_inner_recur(i), + _ => self.visit_inner_recur(&item.kind), + } + } + + fn visit_mod(&mut self, m: &Module) { + m.items.iter().for_each(|i| self.visit_item(i)) + } + + fn visit_crate(&mut self, c: &Crate) { + self.visit_item(&c.module); + + // FIXME: make this a simple by-ref for loop once external_traits is cleaned up + let external_traits = { std::mem::take(&mut *c.external_traits.borrow_mut()) }; + for (k, v) in external_traits { + v.trait_.items.iter().for_each(|i| self.visit_item(i)); + c.external_traits.borrow_mut().insert(k, v); + } + } +} diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 3e853456fa..379de080ff 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -9,16 +9,37 @@ use rustc_hir::Node; use rustc_hir::CRATE_HIR_ID; use rustc_middle::middle::privacy::AccessLevel; use rustc_middle::ty::TyCtxt; -use rustc_span; use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE}; -use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Symbol}; +use rustc_span::Span; use std::mem; use crate::clean::{self, cfg::Cfg, AttributesExt, NestedAttributesExt}; use crate::core; -use crate::doctree::*; + +/// This module is used to store stuff from Rust's AST in a more convenient +/// manner (and with prettier names) before cleaning. +#[derive(Debug)] +crate struct Module<'hir> { + crate name: Symbol, + crate where_inner: Span, + crate mods: Vec>, + crate id: hir::HirId, + // (item, renamed) + crate items: Vec<(&'hir hir::Item<'hir>, Option)>, + crate foreigns: Vec<(&'hir hir::ForeignItem<'hir>, Option)>, +} + +impl Module<'hir> { + crate fn new(name: Symbol, id: hir::HirId, where_inner: Span) -> Module<'hir> { + Module { name, id, where_inner, mods: Vec::new(), items: Vec::new(), foreigns: Vec::new() } + } + + crate fn where_outer(&self, tcx: TyCtxt<'_>) -> Span { + tcx.hir().span(self.id) + } +} // FIXME: Should this be replaced with tcx.def_path_str? fn def_id_to_path(tcx: TyCtxt<'_>, did: DefId) -> Vec { @@ -73,9 +94,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } crate fn visit(mut self) -> Module<'tcx> { - let span = self.cx.tcx.def_span(CRATE_DEF_ID); let mut top_level_module = self.visit_mod_contents( - &Spanned { span, node: hir::VisibilityKind::Public }, hir::CRATE_HIR_ID, self.cx.tcx.hir().root_module(), self.cx.tcx.crate_name(LOCAL_CRATE), @@ -135,15 +154,15 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { fn visit_mod_contents( &mut self, - vis: &hir::Visibility<'_>, id: hir::HirId, m: &'tcx hir::Mod<'tcx>, name: Symbol, ) -> Module<'tcx> { let mut om = Module::new(name, id, m.inner); + let def_id = self.cx.tcx.hir().local_def_id(id).to_def_id(); // Keep track of if there were any private modules in the path. let orig_inside_public_path = self.inside_public_path; - self.inside_public_path &= vis.node.is_pub(); + self.inside_public_path &= self.cx.tcx.visibility(def_id).is_public(); for &i in m.item_ids { let item = self.cx.tcx.hir().item(i); self.visit_item(item, None, &mut om); @@ -260,7 +279,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { let name = renamed.unwrap_or(item.ident.name); let def_id = item.def_id.to_def_id(); - let is_pub = item.vis.node.is_pub() || self.cx.tcx.has_attr(def_id, sym::macro_export); + let is_pub = self.cx.tcx.visibility(def_id).is_public(); if is_pub { self.store_path(item.def_id.to_def_id()); @@ -277,7 +296,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { _ if self.inlining && !is_pub => {} hir::ItemKind::GlobalAsm(..) => {} hir::ItemKind::Use(_, hir::UseKind::ListStem) => {} - hir::ItemKind::Use(ref path, kind) => { + hir::ItemKind::Use(path, kind) => { let is_glob = kind == hir::UseKind::Glob; // Struct and variant constructors and proc macro stubs always show up alongside @@ -333,7 +352,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } } hir::ItemKind::Mod(ref m) => { - om.mods.push(self.visit_mod_contents(&item.vis, item.hir_id(), m, name)); + om.mods.push(self.visit_mod_contents(item.hir_id(), m, name)); } hir::ItemKind::Fn(..) | hir::ItemKind::ExternCrate(..) @@ -369,7 +388,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { om: &mut Module<'tcx>, ) { // If inlining we only want to include public functions. - if !self.inlining || item.vis.node.is_pub() { + if !self.inlining || self.cx.tcx.visibility(item.def_id).is_public() { om.foreigns.push((item, renamed)); } } diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs index 3e98ba08fb..791f7ff437 100644 --- a/src/librustdoc/visit_lib.rs +++ b/src/librustdoc/visit_lib.rs @@ -2,7 +2,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX}; use rustc_middle::middle::privacy::{AccessLevel, AccessLevels}; -use rustc_middle::ty::{TyCtxt, Visibility}; +use rustc_middle::ty::TyCtxt; use rustc_span::symbol::sym; use crate::clean::{AttributesExt, NestedAttributesExt}; @@ -59,7 +59,7 @@ impl<'a, 'tcx> LibEmbargoVisitor<'a, 'tcx> { for item in self.tcx.item_children(def_id).iter() { if let Some(def_id) = item.res.opt_def_id() { if self.tcx.def_key(def_id).parent.map_or(false, |d| d == def_id.index) - || item.vis == Visibility::Public + || item.vis.is_public() { self.visit_item(item.res); } @@ -70,7 +70,7 @@ impl<'a, 'tcx> LibEmbargoVisitor<'a, 'tcx> { fn visit_item(&mut self, res: Res) { let def_id = res.def_id(); let vis = self.tcx.visibility(def_id); - let inherited_item_level = if vis == Visibility::Public { self.prev_level } else { None }; + let inherited_item_level = if vis.is_public() { self.prev_level } else { None }; let item_level = self.update(def_id, inherited_item_level); diff --git a/src/stage0.json b/src/stage0.json index 4bff2a98e0..bead05f821 100644 --- a/src/stage0.json +++ b/src/stage0.json @@ -2,290 +2,290 @@ "__comment": "Generated by `./x.py run src/tools/bump-stage0`. Run that command again to update the bootstrap compiler.", "dist_server": "https://static.rust-lang.org", "compiler": { - "date": "2021-11-01", - "version": "1.56.1" + "date": "2021-12-02", + "version": "1.57.0" }, "rustfmt": null, "checksums_sha256": { - "dist/2021-11-01/cargo-1.56.1-aarch64-apple-darwin.tar.gz": "6ed30275214e956ee10b03db87b0b4297948fd102d39896cece01669555047ef", - "dist/2021-11-01/cargo-1.56.1-aarch64-apple-darwin.tar.xz": "f2e184a62e6b112fce2f6dd0d707c60a84addc29f774cdebcfded663ae81291a", - "dist/2021-11-01/cargo-1.56.1-aarch64-pc-windows-msvc.tar.gz": "8eaaf29bf6012ac99732c9fdeff3d23763620ed30b4fee9b9dac1406b8f3dfbb", - "dist/2021-11-01/cargo-1.56.1-aarch64-pc-windows-msvc.tar.xz": "b230a5d81ce5157de3b6df264fe5d9e74c91ab3de2a27a14e9588016f92ca48b", - "dist/2021-11-01/cargo-1.56.1-aarch64-unknown-linux-gnu.tar.gz": "9aa557436b0cf2a2f4f0d6c4aed5b95062c0637a4a94c000522402e59db1c93a", - "dist/2021-11-01/cargo-1.56.1-aarch64-unknown-linux-gnu.tar.xz": "3d263eb1871b5d6ca4b198b9611925923e9353e1f5c2becf8c7b784298e88743", - "dist/2021-11-01/cargo-1.56.1-aarch64-unknown-linux-musl.tar.gz": "313f095df71bdd7cab5934641990cbcf325acdfefdcdf9d7a4a8aa950fc655d6", - "dist/2021-11-01/cargo-1.56.1-aarch64-unknown-linux-musl.tar.xz": "27f73d4ddcad9cddcc2fd25d194e26fefafbc9c6a98a14e0617b0fa63413f8b9", - "dist/2021-11-01/cargo-1.56.1-arm-unknown-linux-gnueabi.tar.gz": "c6f4190231a062acc7371a14de52dab33dbf3a3a96be50069892cef6318e4b8e", - "dist/2021-11-01/cargo-1.56.1-arm-unknown-linux-gnueabi.tar.xz": "09e69dd23cbf00ed599487eb94e6556c8fd4a28177427fe56ea4c549a94d3122", - "dist/2021-11-01/cargo-1.56.1-arm-unknown-linux-gnueabihf.tar.gz": "fe444ee7d5d3e8777507e3d671e252465295df8552367d69e4d163de6b1ef4b0", - "dist/2021-11-01/cargo-1.56.1-arm-unknown-linux-gnueabihf.tar.xz": "01ce6ec7c0666e91d2be48d25ee1dfd56f05c01f85eaa2c1464dc055fe064e35", - "dist/2021-11-01/cargo-1.56.1-armv7-unknown-linux-gnueabihf.tar.gz": "61b4686b778d1eb118e23d40d79b9da248dbff93a1edc0f64a920f8ba195be59", - "dist/2021-11-01/cargo-1.56.1-armv7-unknown-linux-gnueabihf.tar.xz": "151c96c9cb7c13bec2f2de9c949d494cae3d72bf4f59951b74d905ca03df891a", - "dist/2021-11-01/cargo-1.56.1-i686-pc-windows-gnu.tar.gz": "7e184de74b95ff456eb8aba5bbb98ac21d60b13d7977b292a7824c85c3a7ac53", - "dist/2021-11-01/cargo-1.56.1-i686-pc-windows-gnu.tar.xz": "a91f12926e7646b0fd307e8ddf9a5049d58f6fa81ad3745ff91bca3778871581", - "dist/2021-11-01/cargo-1.56.1-i686-pc-windows-msvc.tar.gz": "6d11253bac7a2b067da40de7bafcb538f6e49b8729d2999716bce4d5701a478b", - "dist/2021-11-01/cargo-1.56.1-i686-pc-windows-msvc.tar.xz": "fb0b06ac6641649b9f19aa07efa19e731e2d316376f98dbcf7e43b7b8204eb4a", - "dist/2021-11-01/cargo-1.56.1-i686-unknown-linux-gnu.tar.gz": "1142c1b8a29d17794d5d2682de93a6c0807d09047dd1462af4d613e0fe63269b", - "dist/2021-11-01/cargo-1.56.1-i686-unknown-linux-gnu.tar.xz": "0a09556948da5ac0041df581a2f16d80c61bcef6d22cc9b26b4d8c64859cfd84", - "dist/2021-11-01/cargo-1.56.1-mips-unknown-linux-gnu.tar.gz": "dc29f524d3879a5eec09684d97469e853aecb6b02281000b4d72efd886f05edb", - "dist/2021-11-01/cargo-1.56.1-mips-unknown-linux-gnu.tar.xz": "32c269755f0e1160f47b80cefa05ac7b77cd3639776d0bb9757d21effdb74456", - "dist/2021-11-01/cargo-1.56.1-mips64-unknown-linux-gnuabi64.tar.gz": "96be8e56ad31c6d35d90c51d54086939ebe03613779c5e643724b6583777b6cf", - "dist/2021-11-01/cargo-1.56.1-mips64-unknown-linux-gnuabi64.tar.xz": "ec1ffacc30cd0ced255fc65272aab1f9870fb376b751f7e10f60f494508d3a61", - "dist/2021-11-01/cargo-1.56.1-mips64el-unknown-linux-gnuabi64.tar.gz": "cd187465cb3d330c98399f6e79665720a3a44b80f1580a8e9525bee6bdc5ce1a", - "dist/2021-11-01/cargo-1.56.1-mips64el-unknown-linux-gnuabi64.tar.xz": "bfe618804ac9e72cc59b7130a7e945633b1cef99cfe148b64e97dc823ab4d0eb", - "dist/2021-11-01/cargo-1.56.1-mipsel-unknown-linux-gnu.tar.gz": "61550d9a5c3a4ec784a1cf152292d514037064941a59bdf402aa725ad48d0992", - "dist/2021-11-01/cargo-1.56.1-mipsel-unknown-linux-gnu.tar.xz": "75bc41bcbe867dba7ae47ee82ded3a24ef53a1589cb413a58603368c735f21d5", - "dist/2021-11-01/cargo-1.56.1-powerpc-unknown-linux-gnu.tar.gz": "537518dd84100d727bfd7cf41fa390de05645ecf7369517cbe519ba9c8c71d5f", - "dist/2021-11-01/cargo-1.56.1-powerpc-unknown-linux-gnu.tar.xz": "89da39892488aca3c0931a81b2cd94cc99c23635b0926d38ca64ad64a097bdd6", - "dist/2021-11-01/cargo-1.56.1-powerpc64-unknown-linux-gnu.tar.gz": "68005d4d5588c9aa9a1fe813ae866b551ea7dff6857956f360d272fad617a27b", - "dist/2021-11-01/cargo-1.56.1-powerpc64-unknown-linux-gnu.tar.xz": "b1be5b5e52bececa56be33b5df3c4c6c14b72de6621c2eabaabcdd5e86c928df", - "dist/2021-11-01/cargo-1.56.1-powerpc64le-unknown-linux-gnu.tar.gz": "2806e83799c007b607d007950e283aac6982d5ecc134f4b26e2600d476aab8a1", - "dist/2021-11-01/cargo-1.56.1-powerpc64le-unknown-linux-gnu.tar.xz": "06be63ee1aec76307a3de1b79f3627e70dec642969682ad8013ce43079e49d57", - "dist/2021-11-01/cargo-1.56.1-riscv64gc-unknown-linux-gnu.tar.gz": "4740f2ed48e2be09be50f3b4c9fefc509b4bbcc17f0dd59892656b7bff2edce0", - "dist/2021-11-01/cargo-1.56.1-riscv64gc-unknown-linux-gnu.tar.xz": "84b760d148bfdb8c9858ed087df7101af707b466a6c850abce377866e4879d0e", - "dist/2021-11-01/cargo-1.56.1-s390x-unknown-linux-gnu.tar.gz": "2600d8d1f031413904978b8aed652af2a2b5a022700ef60aede3ff8580ec8ee8", - "dist/2021-11-01/cargo-1.56.1-s390x-unknown-linux-gnu.tar.xz": "534c6f28fe9e96ff8b2f42cf64ca294fef3174b15d819cf0616336642226a09e", - "dist/2021-11-01/cargo-1.56.1-x86_64-apple-darwin.tar.gz": "cd60c32d0bb0ed59508df96bebb83cf6f85accb9908fb5d63ca95c983a190cf3", - "dist/2021-11-01/cargo-1.56.1-x86_64-apple-darwin.tar.xz": "46840c92c510b1bcfffb0ea7f0c0ee649a54ec0308965a2f3e154ae9d1780f29", - "dist/2021-11-01/cargo-1.56.1-x86_64-pc-windows-gnu.tar.gz": "78f20b3a746b4b2b700dc82710311d56f95e51dc08e979707bab59d35a69fb5d", - "dist/2021-11-01/cargo-1.56.1-x86_64-pc-windows-gnu.tar.xz": "dd1b4f61fb5bb3c0aa4a2886041d20dbea5bd920a65ca77559101713225b1eb6", - "dist/2021-11-01/cargo-1.56.1-x86_64-pc-windows-msvc.tar.gz": "0606835d9c41137552ee63f339c5df1a2ed6f722c871f9fc5cb92b02c7372373", - "dist/2021-11-01/cargo-1.56.1-x86_64-pc-windows-msvc.tar.xz": "264281bfee9fee1fabde6805a9bf916ca24337a7bb130a34b6a5fe1ed2fc42c2", - "dist/2021-11-01/cargo-1.56.1-x86_64-unknown-freebsd.tar.gz": "a1656603049a4612cdf44179ac7ccdb3c342f0b152cb114f61a228d321b0f384", - "dist/2021-11-01/cargo-1.56.1-x86_64-unknown-freebsd.tar.xz": "c987fc8c70bd4c92f753a51a14ce49dbe666a8dc209df681562575efcfe7921b", - "dist/2021-11-01/cargo-1.56.1-x86_64-unknown-illumos.tar.gz": "292ed7f6efa78cf93f91aed38508da1d0ef192f4cdba5fa37d9e739ed0d78a88", - "dist/2021-11-01/cargo-1.56.1-x86_64-unknown-illumos.tar.xz": "a3854cdba97226d7ce123eb4c3e9d9ba8c9b480bdcd54978909ec57ea0431b3f", - "dist/2021-11-01/cargo-1.56.1-x86_64-unknown-linux-gnu.tar.gz": "c896c033bb1f430c4e200ae8af0f74d792e4909a458086b9597f076e1dcc2ab2", - "dist/2021-11-01/cargo-1.56.1-x86_64-unknown-linux-gnu.tar.xz": "dfed65a50e2b58b6807c1fb6f8afa7abd5c3b22c682d505721d615823687c708", - "dist/2021-11-01/cargo-1.56.1-x86_64-unknown-linux-musl.tar.gz": "4ecdd39695d9e09c3f4efffff61d67451cd41f28f09155485ac7dcc8f7a65a26", - "dist/2021-11-01/cargo-1.56.1-x86_64-unknown-linux-musl.tar.xz": "ceb8e3e273ade68766b526a7d076fc8ebfb19c2b2d4946f789bcf2597d06f83a", - "dist/2021-11-01/cargo-1.56.1-x86_64-unknown-netbsd.tar.gz": "4c458fbe9121fdd9e01cee4129249b1abf86301c0f441f7e78e8a6ba554d8cfc", - "dist/2021-11-01/cargo-1.56.1-x86_64-unknown-netbsd.tar.xz": "24148a57a64aeb2fdf84044728e138a53353d08fadfd3136771f355ea52eb7e0", - "dist/2021-11-01/rust-std-1.56.1-aarch64-apple-darwin.tar.gz": "59fcdb16c264fce206a1a59261fc576f547fa0a807d3370b542ab25261ae5158", - "dist/2021-11-01/rust-std-1.56.1-aarch64-apple-darwin.tar.xz": "733d5855a4b4158778e4eab50229a96cfdd492cfa8cf1877bfe7c9a242d523cd", - "dist/2021-11-01/rust-std-1.56.1-aarch64-apple-ios-sim.tar.gz": "eca6dc2d6ab37ed2ea58d408c9f0496ed2cca03b49c3d748fdcc41640fee2225", - "dist/2021-11-01/rust-std-1.56.1-aarch64-apple-ios-sim.tar.xz": "be91d88dd4ea439cc16d2affb90ec7d88436562938e77f39993899e87f1e0173", - "dist/2021-11-01/rust-std-1.56.1-aarch64-apple-ios.tar.gz": "2032f94869f69bf03c0f01c82e84ef174c827d333feab7823e75b408b8124648", - "dist/2021-11-01/rust-std-1.56.1-aarch64-apple-ios.tar.xz": "13b883914ba238f697a75cd14044e87dc2617cd2bee09de8840dcb7a84636778", - "dist/2021-11-01/rust-std-1.56.1-aarch64-fuchsia.tar.gz": "04f82af2f37cb003f5e4dbd48499f1e8e25c610f11c72ed8bc24388a90ef14bd", - "dist/2021-11-01/rust-std-1.56.1-aarch64-fuchsia.tar.xz": "ffba901f4ff822ca9b1c474840cb38ecc4aad83a4e755cdb780372eb534838e7", - "dist/2021-11-01/rust-std-1.56.1-aarch64-linux-android.tar.gz": "b340fff6db68427472ab654773b1b5537d6b6b6e135490c914f9d5928b34c6db", - "dist/2021-11-01/rust-std-1.56.1-aarch64-linux-android.tar.xz": "2ac95848896317aed41583d779641342ca411440efb72cc132497848ccfb6b13", - "dist/2021-11-01/rust-std-1.56.1-aarch64-pc-windows-msvc.tar.gz": "51a6feee2170a5c73bd1ac866b8337ffac310488ca541b663b791308db7eb20f", - "dist/2021-11-01/rust-std-1.56.1-aarch64-pc-windows-msvc.tar.xz": "71b75f9124241a2b8c90238374c7e5b05bd47bb8dcaa72214f02836a5c621233", - "dist/2021-11-01/rust-std-1.56.1-aarch64-unknown-linux-gnu.tar.gz": "d577c25879cf160ec1a04d5101971dd684f9b4f87b3cb463a7521b676dc3df89", - "dist/2021-11-01/rust-std-1.56.1-aarch64-unknown-linux-gnu.tar.xz": "a83416d15354e4dfa1c1e4a756282c6be7169679f2b04eca82ed34e2116b93f0", - "dist/2021-11-01/rust-std-1.56.1-aarch64-unknown-linux-musl.tar.gz": "444d5cb43bb82322562afe54c249c3d85b5b1cf215fcd0cfdabd2e657fcda687", - "dist/2021-11-01/rust-std-1.56.1-aarch64-unknown-linux-musl.tar.xz": "50603cfa6332846ee1a7e9c0440f976b57b49d1800a2504ef0be1fb484646bbc", - "dist/2021-11-01/rust-std-1.56.1-aarch64-unknown-none-softfloat.tar.gz": "0bf6e201e77c0ca2261398853cfd882a391dfd62dda2a8321b3d43e131dd0334", - "dist/2021-11-01/rust-std-1.56.1-aarch64-unknown-none-softfloat.tar.xz": "02b4e72a8d4f4125acf4bee59854ddc937d7fbe38b0436bb780b8326edd4bb97", - "dist/2021-11-01/rust-std-1.56.1-aarch64-unknown-none.tar.gz": "45c7d49e25675a1e520e952b91b965122610c4a2a7f1c59964005470073dae23", - "dist/2021-11-01/rust-std-1.56.1-aarch64-unknown-none.tar.xz": "d23e31946836a59f074ed0b24c79913e87fc61cf0ef6cb27077ea51d4768ef69", - "dist/2021-11-01/rust-std-1.56.1-arm-linux-androideabi.tar.gz": "a687eea48c20a2f377f84e42d547e67532d393ac6278740a097519a6f3c490d3", - "dist/2021-11-01/rust-std-1.56.1-arm-linux-androideabi.tar.xz": "01396ddd5ab1d8b1a7a3f13734d7c83558cd67a745e77c53bda2c81face56d4f", - "dist/2021-11-01/rust-std-1.56.1-arm-unknown-linux-gnueabi.tar.gz": "13a618ef5ee18e00b76d5891fcd1886f1fdb042ca81962dae30df6c535d42bef", - "dist/2021-11-01/rust-std-1.56.1-arm-unknown-linux-gnueabi.tar.xz": "3a7d1b12b961ecee610b89258260b0c596b81cc0e9444b9b651669844f6f056d", - "dist/2021-11-01/rust-std-1.56.1-arm-unknown-linux-gnueabihf.tar.gz": "01963e591bfbe7e33e2b264984005320e0ac0c5849a23bb897613de38bef9abd", - "dist/2021-11-01/rust-std-1.56.1-arm-unknown-linux-gnueabihf.tar.xz": "ee5dda5e1901379a617a1070152890b463b117267aeabd8dd9cdcfece826eccb", - "dist/2021-11-01/rust-std-1.56.1-arm-unknown-linux-musleabi.tar.gz": "c09983c442b5307b3564c406bad2f306153d07fff6acc7584265b36714e7cb01", - "dist/2021-11-01/rust-std-1.56.1-arm-unknown-linux-musleabi.tar.xz": "eac145da4edd6200a304f50bcde86eb6ecc62418b20f1ce618a65031f15f99a6", - "dist/2021-11-01/rust-std-1.56.1-arm-unknown-linux-musleabihf.tar.gz": "9410faa13d85080b4d338b4e16b03c2fbadaa97f7463392196cb0ffa69cc3ad9", - "dist/2021-11-01/rust-std-1.56.1-arm-unknown-linux-musleabihf.tar.xz": "6211547d48e961344024226a0dbad40d97d458f497fe4c54f4768cd7c76d4307", - "dist/2021-11-01/rust-std-1.56.1-armebv7r-none-eabi.tar.gz": "dec378a0e599a7d20a489b4de0713e21bb9153f444d1892fbc195579b2aa4a72", - "dist/2021-11-01/rust-std-1.56.1-armebv7r-none-eabi.tar.xz": "84d3d03676bdde599df1759268cb055476529623c0124ca0b97b0d4cc6462739", - "dist/2021-11-01/rust-std-1.56.1-armebv7r-none-eabihf.tar.gz": "3fae86e0e86440dce288575ab6ed311841cfeec0f7e9ba62ad5f8e1968ede580", - "dist/2021-11-01/rust-std-1.56.1-armebv7r-none-eabihf.tar.xz": "3f135a57508fd61d8652995737cb520808aebbf4e11b2105836064f8164f69d1", - "dist/2021-11-01/rust-std-1.56.1-armv5te-unknown-linux-gnueabi.tar.gz": "ce240263fee9de563727e4feb5c6ee038c837189b3fa93d2d2f5b4ec7077f42e", - "dist/2021-11-01/rust-std-1.56.1-armv5te-unknown-linux-gnueabi.tar.xz": "5a85910a68c80976af123cf31229eaf70028298da8f4f212e832b004c4ef405b", - "dist/2021-11-01/rust-std-1.56.1-armv5te-unknown-linux-musleabi.tar.gz": "e3aa96cd1ec07512575b6daf74677fefee766a18de678a0a77f44614f606c1a7", - "dist/2021-11-01/rust-std-1.56.1-armv5te-unknown-linux-musleabi.tar.xz": "9f375a46531a66b670e55df432cc5cebcdf7e7647ab7fd61814560ff3a115ba3", - "dist/2021-11-01/rust-std-1.56.1-armv7-linux-androideabi.tar.gz": "197477edffa06dae19c461cabe57ee45c20b7e4c3850094671209fec9438acd1", - "dist/2021-11-01/rust-std-1.56.1-armv7-linux-androideabi.tar.xz": "187a79c99463128a7533d092042a0376dd7866cbc8ba15567cc5c188e8145933", - "dist/2021-11-01/rust-std-1.56.1-armv7-unknown-linux-gnueabi.tar.gz": "5e2adde15b1177814137f7f93ca6392ecb4dc44bf82f05ca3cc8abd24a8072be", - "dist/2021-11-01/rust-std-1.56.1-armv7-unknown-linux-gnueabi.tar.xz": "0c6fb440c8dc219093674fa685bf08432ca7d2f1bad2e724a344a718571d90c0", - "dist/2021-11-01/rust-std-1.56.1-armv7-unknown-linux-gnueabihf.tar.gz": "cedd08ec5f94e7b6348befde00e42a8e1e5981586762be8d264b34e1f7de9818", - "dist/2021-11-01/rust-std-1.56.1-armv7-unknown-linux-gnueabihf.tar.xz": "d4eeeae7cd711372c3ccde1b943d1b6e1055918c59a637bba7f5fe3cd2aede4a", - "dist/2021-11-01/rust-std-1.56.1-armv7-unknown-linux-musleabi.tar.gz": "3c7dd1cac570038cc95fc1edcd8b965dd19447bdcf29782fb7745d64f98ce7da", - "dist/2021-11-01/rust-std-1.56.1-armv7-unknown-linux-musleabi.tar.xz": "d485fa9a545d3ad20dc96c8665a06f436447b841cff68db34c156bcd28186351", - "dist/2021-11-01/rust-std-1.56.1-armv7-unknown-linux-musleabihf.tar.gz": "21a6f072752c57c5692d36fce19e45cfd3704a22e263c4c31963587d085c7530", - "dist/2021-11-01/rust-std-1.56.1-armv7-unknown-linux-musleabihf.tar.xz": "406276fb537b0e26957b5c3274c01d59f80ee12b2dda1c035dc45df6435cc5a0", - "dist/2021-11-01/rust-std-1.56.1-armv7a-none-eabi.tar.gz": "c8dafb090c29ae58fc991003303b49e80d2657dc0e256016953b72430fadd88c", - "dist/2021-11-01/rust-std-1.56.1-armv7a-none-eabi.tar.xz": "cfc2089bacf64e8d937d1b1e7dfe0d608e3d01ad5832bb66cab315998b2ba200", - "dist/2021-11-01/rust-std-1.56.1-armv7r-none-eabi.tar.gz": "75dcae3d8d31ab06646f11504c533ef3386c22717ecab4ea90f5087a3a480067", - "dist/2021-11-01/rust-std-1.56.1-armv7r-none-eabi.tar.xz": "a647b0717acaf54abd60912e08a9c7e1ec9e09463692f3da6f9e1567305c49c3", - "dist/2021-11-01/rust-std-1.56.1-armv7r-none-eabihf.tar.gz": "4cef8deef36d9ec3a27cc12d2aef0918da581748622b9b6f15bdad4c27c47ba7", - "dist/2021-11-01/rust-std-1.56.1-armv7r-none-eabihf.tar.xz": "a09b855ff61abc5522199aee787adcbf7d3a08b750d61c2a3e1a443c9b3334cb", - "dist/2021-11-01/rust-std-1.56.1-asmjs-unknown-emscripten.tar.gz": "5912086ddf103ab831cd478b3ecbbdaba97a4d0b3287aaeeb6b5ccbcfde6f21e", - "dist/2021-11-01/rust-std-1.56.1-asmjs-unknown-emscripten.tar.xz": "dae15590f62445c8c45f46de98ee03782701eb0ce70572af7e7978926626c2ed", - "dist/2021-11-01/rust-std-1.56.1-i586-pc-windows-msvc.tar.gz": "18ac156546ec8c997356596268bf64b7f0fcaa71dd58ba2262d4a54d3bc8c058", - "dist/2021-11-01/rust-std-1.56.1-i586-pc-windows-msvc.tar.xz": "454dd3fdc3432774c137753f514f063c87e05b185eda5c20f289b9acdaa4869a", - "dist/2021-11-01/rust-std-1.56.1-i586-unknown-linux-gnu.tar.gz": "9aa048d2bc7e97e1c4a648d43e856050ce41ef9c53d684aae18faf0284e5193a", - "dist/2021-11-01/rust-std-1.56.1-i586-unknown-linux-gnu.tar.xz": "3979068f4785080db04437bd080402d6c472b87828ec6de32b2b7003cb3326df", - "dist/2021-11-01/rust-std-1.56.1-i586-unknown-linux-musl.tar.gz": "77aa024712e5e4cd1e96b996c0105c3d57cf3c7719b76b63b460482d658b929c", - "dist/2021-11-01/rust-std-1.56.1-i586-unknown-linux-musl.tar.xz": "2e449ac494d1455e6cef943b498e0551e9fc16db1da5dffd01aec9d53cb7cdca", - "dist/2021-11-01/rust-std-1.56.1-i686-linux-android.tar.gz": "ef735709105b89782d9f6948f01ee739b4ab62e8d879ed207d0dcf1ed90c0fe4", - "dist/2021-11-01/rust-std-1.56.1-i686-linux-android.tar.xz": "0ec3b10470da960da6907ea7390e3a2abbca95876e684d51fc751c598cf87969", - "dist/2021-11-01/rust-std-1.56.1-i686-pc-windows-gnu.tar.gz": "f7bb9af44b2407b46d4c98a0ff335c7d05fedc7fdbb2b32a224ce004211f90f1", - "dist/2021-11-01/rust-std-1.56.1-i686-pc-windows-gnu.tar.xz": "840ef76c8b462f7434be2c2fd2677b78e5659098c85becf40490ddfc1bfb4e2d", - "dist/2021-11-01/rust-std-1.56.1-i686-pc-windows-msvc.tar.gz": "c2108cca173656766b8743d41b5c0c0c20c6c4855b0a022c749bc70a231c42ce", - "dist/2021-11-01/rust-std-1.56.1-i686-pc-windows-msvc.tar.xz": "d6807c920f6cd448ea4a4f87bf1d6f1402ff7b5b6d98c7196a8719541e26593a", - "dist/2021-11-01/rust-std-1.56.1-i686-unknown-freebsd.tar.gz": "db427a44cca63c9811ee7af6774356a29c49b6056b9f6057cba4d0955991e7da", - "dist/2021-11-01/rust-std-1.56.1-i686-unknown-freebsd.tar.xz": "257b4669776a4b6b16c04e02ffad81704c001edaf3c73bbbb3954aee33821572", - "dist/2021-11-01/rust-std-1.56.1-i686-unknown-linux-gnu.tar.gz": "daff2db4e3d42916094a59b7c4eef169030b1fe0050c3cf882e7e293279298bd", - "dist/2021-11-01/rust-std-1.56.1-i686-unknown-linux-gnu.tar.xz": "616c78507a68439355116d45353c0bd07f1356d4021406b72a47a2f3f833996f", - "dist/2021-11-01/rust-std-1.56.1-i686-unknown-linux-musl.tar.gz": "67578ed8b2e2625e09d8f0c23f34feb28b9be847cfabdc53e778ede8a3b38511", - "dist/2021-11-01/rust-std-1.56.1-i686-unknown-linux-musl.tar.xz": "c1e56f99785ad3bd84ca723c0e65ca578aa0734ddfe5e0d4f252bda9fbfcc445", - "dist/2021-11-01/rust-std-1.56.1-mips-unknown-linux-gnu.tar.gz": "3ed4c2c3975ac4296b016910df2bf129dfafca30d6a9fda68f6fa1a3f22a0a23", - "dist/2021-11-01/rust-std-1.56.1-mips-unknown-linux-gnu.tar.xz": "c13790eae5d9a7e76e0406161c19cae3249dc096b6fcf33934954a928c724649", - "dist/2021-11-01/rust-std-1.56.1-mips-unknown-linux-musl.tar.gz": "e87448e5561c4325fcd11d2cf47a002c43b339ead6cfa73ea14687e2a4b6114b", - "dist/2021-11-01/rust-std-1.56.1-mips-unknown-linux-musl.tar.xz": "003619386c44b45e6f3274c8bbbdc5598727d0e69b1e7bb01e6e86e9527490d7", - "dist/2021-11-01/rust-std-1.56.1-mips64-unknown-linux-gnuabi64.tar.gz": "f4bca093a787bbcfc88bdb2a1b19e8ec05cd34b34fadc28557eed2651178d7b5", - "dist/2021-11-01/rust-std-1.56.1-mips64-unknown-linux-gnuabi64.tar.xz": "c036d1b576f8c8f1026ea972712da7c89e7fdeee6e193050f0a7ceadf660e031", - "dist/2021-11-01/rust-std-1.56.1-mips64-unknown-linux-muslabi64.tar.gz": "ba9b96c5541745083d222e4d261c60c68612373d467113840c4b3fe5bd0d76ac", - "dist/2021-11-01/rust-std-1.56.1-mips64-unknown-linux-muslabi64.tar.xz": "318f663f00add6af66fe5601ce4813d4b667a3e64b2680e384907739fc6577d8", - "dist/2021-11-01/rust-std-1.56.1-mips64el-unknown-linux-gnuabi64.tar.gz": "e5946fcda6275b53568cf7564ffaff9b738ab3e098e9497abd7483c5083b1920", - "dist/2021-11-01/rust-std-1.56.1-mips64el-unknown-linux-gnuabi64.tar.xz": "f56f5dcd7e96d7986ad7e32eee6be6e84ce3172dbbe1d2af15e677226e0d518d", - "dist/2021-11-01/rust-std-1.56.1-mips64el-unknown-linux-muslabi64.tar.gz": "bf53a5a55a3f31e7a5f4ce5220cbe75f9ead277d96de89ef01929c932cfe39ea", - "dist/2021-11-01/rust-std-1.56.1-mips64el-unknown-linux-muslabi64.tar.xz": "46af98067623584b355e8e542dc3283543ec51f1ab7b83ec2acbb878b27dd34d", - "dist/2021-11-01/rust-std-1.56.1-mipsel-unknown-linux-gnu.tar.gz": "739bf07f42374a1e272cdd0639311c65897e230bed3336b217f616b7479ae905", - "dist/2021-11-01/rust-std-1.56.1-mipsel-unknown-linux-gnu.tar.xz": "b08ed2c414fda72493f6409b1a9b4505179a531ffeb157c20581474f7f1c7c15", - "dist/2021-11-01/rust-std-1.56.1-mipsel-unknown-linux-musl.tar.gz": "c6907e51847bbe1aa527375a4ad8ff1c1747d2b86ba05677960c047f3a3918c9", - "dist/2021-11-01/rust-std-1.56.1-mipsel-unknown-linux-musl.tar.xz": "851461985a31ca5f5879db3a6a86ee651e3e7f3b7214e0bcfdb7aadabd1276fe", - "dist/2021-11-01/rust-std-1.56.1-nvptx64-nvidia-cuda.tar.gz": "464903fbec2740f996ff0507bbeac45231cdc031397d5620d73090dcd4c48d2d", - "dist/2021-11-01/rust-std-1.56.1-nvptx64-nvidia-cuda.tar.xz": "fde4334b448ffcef5588aab776545e552b757612dcec25a4761f5992c30ae5ff", - "dist/2021-11-01/rust-std-1.56.1-powerpc-unknown-linux-gnu.tar.gz": "11d753855c461d220222824a5d4bdb31424251ff447e38657a7ad348d95908f5", - "dist/2021-11-01/rust-std-1.56.1-powerpc-unknown-linux-gnu.tar.xz": "0c1de91436fbe52ed9388f8d0bab4931a3fa19160e283361afd79acd5ef9ca7c", - "dist/2021-11-01/rust-std-1.56.1-powerpc64-unknown-linux-gnu.tar.gz": "b1a4ea580685fa9e4332f774e94d25d80713692d5e0c4659a01534bd479c8ae7", - "dist/2021-11-01/rust-std-1.56.1-powerpc64-unknown-linux-gnu.tar.xz": "1d74331e02088997cadd3c534aa1da4b34fdf0587b64770788e6efe08dd63dba", - "dist/2021-11-01/rust-std-1.56.1-powerpc64le-unknown-linux-gnu.tar.gz": "d9c8b33f38d6acd73529e3658f8044316144e9a5a8a79eba66747f64d99c256e", - "dist/2021-11-01/rust-std-1.56.1-powerpc64le-unknown-linux-gnu.tar.xz": "0bda1a2e91c9a471e907bd34b75859c1b152e03f1509344a927fba214c4c5bc6", - "dist/2021-11-01/rust-std-1.56.1-riscv32i-unknown-none-elf.tar.gz": "140c35c4f7502690e0065411ede32cdc3a1e7e40003a985db5e746cb2e69d1c6", - "dist/2021-11-01/rust-std-1.56.1-riscv32i-unknown-none-elf.tar.xz": "b044c51563843b4d7f970a31b0ddd7d5f4a15bc2818762021b8fcaef2ae9c740", - "dist/2021-11-01/rust-std-1.56.1-riscv32imac-unknown-none-elf.tar.gz": "adecc46de4ba90d4d71cfd441a566138d8fcb1dcf028faa8e4e7eaad3a5d56dc", - "dist/2021-11-01/rust-std-1.56.1-riscv32imac-unknown-none-elf.tar.xz": "4fc9d42a749deb606a76a36a6cd1dc4df3cc6ec46378fe230b704f7f5a7e3e14", - "dist/2021-11-01/rust-std-1.56.1-riscv32imc-unknown-none-elf.tar.gz": "517c934d61cc96264b37f2fe08b9e12b8d5d1c700940dc4622ccea7a3472e154", - "dist/2021-11-01/rust-std-1.56.1-riscv32imc-unknown-none-elf.tar.xz": "2d040592fec1de79ccca2e2dc18089886ab69884a82ea014b6cbe458c3e3277d", - "dist/2021-11-01/rust-std-1.56.1-riscv64gc-unknown-linux-gnu.tar.gz": "76e04d6afa8ae6e983ea7f0aeb98594e0ff228e0872f388d3de806bb7c3519b9", - "dist/2021-11-01/rust-std-1.56.1-riscv64gc-unknown-linux-gnu.tar.xz": "fe5b7b7a14588101a09cf4d9bbe421ae8b071231a791f96ace22b9eaa5875756", - "dist/2021-11-01/rust-std-1.56.1-riscv64gc-unknown-none-elf.tar.gz": "b6c3049fcb6b559176cb4f4c75a4ca01cad61b972e500c7485e58918ed8ddc0e", - "dist/2021-11-01/rust-std-1.56.1-riscv64gc-unknown-none-elf.tar.xz": "649fe72f7d519dda2410e60f7e61ce1ffd692a102a35f05402a842231afa63dc", - "dist/2021-11-01/rust-std-1.56.1-riscv64imac-unknown-none-elf.tar.gz": "fcf27d893b5bdd08b55481b85a8990d893b408abddd9b57dda6c19aa95bc8c80", - "dist/2021-11-01/rust-std-1.56.1-riscv64imac-unknown-none-elf.tar.xz": "ff302ff438f710eb75633ed7426ed050e8e0c7edaee84eafb6fabba6c72a1cd5", - "dist/2021-11-01/rust-std-1.56.1-s390x-unknown-linux-gnu.tar.gz": "531f7a2f22df9e91cf6efc01b3d0b58e3b96afbc93090a1716cdcbc904cc3dcf", - "dist/2021-11-01/rust-std-1.56.1-s390x-unknown-linux-gnu.tar.xz": "c3526a691da0a2877225727f60798130dcb2ff00bcf97f0a5b391ccb85eb092e", - "dist/2021-11-01/rust-std-1.56.1-sparc64-unknown-linux-gnu.tar.gz": "cab263b4634f82b2d47bb806570ee9c8798e737ea84e555ef98d5f746e0d24fb", - "dist/2021-11-01/rust-std-1.56.1-sparc64-unknown-linux-gnu.tar.xz": "b607cc4a489d40ecbee50a926ebe49fba4e1ab25528be0d43b182d6245f3369c", - "dist/2021-11-01/rust-std-1.56.1-sparcv9-sun-solaris.tar.gz": "06da09aede77790c98a0a87aca4f1b4fef76cb14037a554d585a6b023b84c4f2", - "dist/2021-11-01/rust-std-1.56.1-sparcv9-sun-solaris.tar.xz": "aa9110244da119b3611836ff8ed4d2e12361925118d4b0692cde1acf39cbd444", - "dist/2021-11-01/rust-std-1.56.1-thumbv6m-none-eabi.tar.gz": "375e97ad8f5895ead09798f666377c50833bd3443614de2abf05929d5599fee8", - "dist/2021-11-01/rust-std-1.56.1-thumbv6m-none-eabi.tar.xz": "591dfff0d8bc3e2a699975e8145cf420f0637f9c5b4862f7a3f68c531b608e71", - "dist/2021-11-01/rust-std-1.56.1-thumbv7em-none-eabi.tar.gz": "7081fa371997641bb8b3f1b1850efe41daebb27e9ec13a8dfad0eac8161c8fdd", - "dist/2021-11-01/rust-std-1.56.1-thumbv7em-none-eabi.tar.xz": "0516f076e3ddb9aa8380ecf4baf607a39b0ab2c9184ecdc5c29d71b328a0c7bd", - "dist/2021-11-01/rust-std-1.56.1-thumbv7em-none-eabihf.tar.gz": "dc0f66f3065565f664fe70e907303b6c5f031e999cf8313c6a02975517b96b0a", - "dist/2021-11-01/rust-std-1.56.1-thumbv7em-none-eabihf.tar.xz": "ca2cc134e2b3698764b4ba71d979709fb7f689030c3468de62c087c079f8ec5c", - "dist/2021-11-01/rust-std-1.56.1-thumbv7m-none-eabi.tar.gz": "8d10efbaa6ea8002e164d199ded6262a65259291cbef60c43fe5e06eeae2a104", - "dist/2021-11-01/rust-std-1.56.1-thumbv7m-none-eabi.tar.xz": "833dffcdc9fde44a935a3ba6f2157ae54daf96932109f879602c4bdaf5e4b772", - "dist/2021-11-01/rust-std-1.56.1-thumbv7neon-linux-androideabi.tar.gz": "04c2b78fc9e8bce32ae501e7218f1f327051da8f2c345b9efd624efd4bc1f494", - "dist/2021-11-01/rust-std-1.56.1-thumbv7neon-linux-androideabi.tar.xz": "fe3830203073eec0e4631ed4f7d2292fb86751d222833ca92815ae56200d1c10", - "dist/2021-11-01/rust-std-1.56.1-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "9604c64703da0795ccd8e44970beace05e7c97612b060d0b36d15ce0feb64dd4", - "dist/2021-11-01/rust-std-1.56.1-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "73f20b47af9f9c13dae8955a6118e990c2ae060b81a428cd56d093f064b0944b", - "dist/2021-11-01/rust-std-1.56.1-thumbv8m.base-none-eabi.tar.gz": "27c9783e294f51a25f1de9a79b24ba057c462bd340cc07e4785be1e644bdb242", - "dist/2021-11-01/rust-std-1.56.1-thumbv8m.base-none-eabi.tar.xz": "64a4bf70b1ab301a5f0e9b5e7b1c632a3e53c9519512df5553a50e6d2cde0d2b", - "dist/2021-11-01/rust-std-1.56.1-thumbv8m.main-none-eabi.tar.gz": "21eb29cd9597cbd5b52ebdb48a01ac8e38bb675c9ecb7f9c928b3a2b73c65a58", - "dist/2021-11-01/rust-std-1.56.1-thumbv8m.main-none-eabi.tar.xz": "77c3fe1b10fcf7c630371ab6064a7300b1befea2cbc2e20c5c7defee0acde15a", - "dist/2021-11-01/rust-std-1.56.1-thumbv8m.main-none-eabihf.tar.gz": "5c2cd41b5047f83f3c1d67b8454fc43e42203493e003db9cf0aae150e5d4d32d", - "dist/2021-11-01/rust-std-1.56.1-thumbv8m.main-none-eabihf.tar.xz": "b84061540ca71fad799ff9398fbf6b5874dcbb8adbd478729d5be1abf9e7de35", - "dist/2021-11-01/rust-std-1.56.1-wasm32-unknown-emscripten.tar.gz": "f318d3bf38ce83e3f3531114ba59af31c853cbdb5720d8804ae77970e40048dc", - "dist/2021-11-01/rust-std-1.56.1-wasm32-unknown-emscripten.tar.xz": "7f437a469dd0adcb9041b1cb0413a4f7e80531b67dc88347001a9096632a0ab8", - "dist/2021-11-01/rust-std-1.56.1-wasm32-unknown-unknown.tar.gz": "4e62beca963a5b8c98913dd10abc493126675a0a35c2817afdf6975a49cc1bce", - "dist/2021-11-01/rust-std-1.56.1-wasm32-unknown-unknown.tar.xz": "4ad9c1d9eb00c2dc569f6e2b5ca5acd715db02db3456af08ba61d00f40e3a0fd", - "dist/2021-11-01/rust-std-1.56.1-wasm32-wasi.tar.gz": "a7eaf9bf238671f7a54afe00cd76dbb354933e525ab5bceb10d156a2bc414dd7", - "dist/2021-11-01/rust-std-1.56.1-wasm32-wasi.tar.xz": "c5ae515041a447a94de4d7f9559f82e70fcc7b48571bfb26d9866dcb2fa5cfa6", - "dist/2021-11-01/rust-std-1.56.1-x86_64-apple-darwin.tar.gz": "a1cedfaea1508bf3bfc8a77d82d15c693b41e70e56fad930d24f21f0bce5052a", - "dist/2021-11-01/rust-std-1.56.1-x86_64-apple-darwin.tar.xz": "5e58c2ecb19b09dd56637bd21813fd76778aee2be3104d324b62bc6c4ec3c46d", - "dist/2021-11-01/rust-std-1.56.1-x86_64-apple-ios.tar.gz": "68fec8fd73357d2da75027eed38858cbe64e174a59bc0aeea133aa74f554bcac", - "dist/2021-11-01/rust-std-1.56.1-x86_64-apple-ios.tar.xz": "dea687c9e1c33351d03fb8fe3f0141c56f9e0965938d4e16566a662197719ecb", - "dist/2021-11-01/rust-std-1.56.1-x86_64-fortanix-unknown-sgx.tar.gz": "c5e30e097b86df00c90149cc221c450b5a687608d489537b1808a72ac720ef98", - "dist/2021-11-01/rust-std-1.56.1-x86_64-fortanix-unknown-sgx.tar.xz": "ca51c524f939eb8cdb73421e9dd9cc1640e3ff5e89fa453bdfde7d0a07c760cf", - "dist/2021-11-01/rust-std-1.56.1-x86_64-fuchsia.tar.gz": "ae37eaf74470b57448fc03bd199d558cc9e00bafc9c41cef16eb89bdda786b9e", - "dist/2021-11-01/rust-std-1.56.1-x86_64-fuchsia.tar.xz": "0e2de360c1066f78d5d9a405dafe934f204728968f4103cae68e826ba5122c46", - "dist/2021-11-01/rust-std-1.56.1-x86_64-linux-android.tar.gz": "9bd1ef68894d68c4d33a0344ddf2ccce2469e4c9a5ced235459e33f76e789063", - "dist/2021-11-01/rust-std-1.56.1-x86_64-linux-android.tar.xz": "272d6eaef8259ea9fd4b51e84976135f885a04314feffedaad18b84828b479f0", - "dist/2021-11-01/rust-std-1.56.1-x86_64-pc-solaris.tar.gz": "f8718bba856c0569ac14ae99cc83206617161f68a1f775163962385145c437f8", - "dist/2021-11-01/rust-std-1.56.1-x86_64-pc-solaris.tar.xz": "1fa68f6aec421592e23fee0d0b2c203417f0bc9444b2aa9e690c76d806242ec1", - "dist/2021-11-01/rust-std-1.56.1-x86_64-pc-windows-gnu.tar.gz": "8c5d425d2882a93827850672a70bfc2e643cae425aaffa9dafa6808fcd4bc798", - "dist/2021-11-01/rust-std-1.56.1-x86_64-pc-windows-gnu.tar.xz": "3cefe2bdf19d8edbc4bb124c541770b200cf5f19f2129c9cdf1e1361dbaa9b1a", - "dist/2021-11-01/rust-std-1.56.1-x86_64-pc-windows-msvc.tar.gz": "ace5ea90e70b9d035b28b405175d52e1796fb1bb36cfbdead1048ff00e9ec1fe", - "dist/2021-11-01/rust-std-1.56.1-x86_64-pc-windows-msvc.tar.xz": "064e4e9a030057c20e398c2f4c46e6e5e2d3b493b5e677c2e5e32fe77d1ecfb2", - "dist/2021-11-01/rust-std-1.56.1-x86_64-sun-solaris.tar.gz": "4c7182fffa8f7ef456c01babdb50b64fd608fe7c6ec28909d34b2d508a1bc85a", - "dist/2021-11-01/rust-std-1.56.1-x86_64-sun-solaris.tar.xz": "46f1b3f6c440d0549c6187b92aa89afe03dd3dc2ccb378a085205544496fafdd", - "dist/2021-11-01/rust-std-1.56.1-x86_64-unknown-freebsd.tar.gz": "1382799af56e1ec48cf3971f84122c9d445996422055b822d9d6226a31a20737", - "dist/2021-11-01/rust-std-1.56.1-x86_64-unknown-freebsd.tar.xz": "8ae63f5c03a8d8a60be62dc536672b6ae8e5259837cf2a543f1c4c30d4cbb5e6", - "dist/2021-11-01/rust-std-1.56.1-x86_64-unknown-illumos.tar.gz": "171b2e2600d091aa2e3c9bdf4c8336f29582c42dc894341418fef83e22141599", - "dist/2021-11-01/rust-std-1.56.1-x86_64-unknown-illumos.tar.xz": "d7b3fdda726a014434a3944b7e1136cc6e97a34cd223f8a9fc08e79e14e01b1b", - "dist/2021-11-01/rust-std-1.56.1-x86_64-unknown-linux-gnu.tar.gz": "afd959b295e17640d1e94648278a944dc5f349ebdd9e59e2404729db0810c531", - "dist/2021-11-01/rust-std-1.56.1-x86_64-unknown-linux-gnu.tar.xz": "b01011cbb5503c456ecc6a557a38e099994b8497df545c661ce8fd48c5beadc6", - "dist/2021-11-01/rust-std-1.56.1-x86_64-unknown-linux-gnux32.tar.gz": "059c7db359dbcffb77f236fd59ed757478f7a817d715eb5554f53309dfa13109", - "dist/2021-11-01/rust-std-1.56.1-x86_64-unknown-linux-gnux32.tar.xz": "338ae41e07c6e07fa929cff76d957f806bd3276a1a54140041ac720a4bb1d2fd", - "dist/2021-11-01/rust-std-1.56.1-x86_64-unknown-linux-musl.tar.gz": "88bfd0dce45d4321b0781550a300f90da5344dda20744219b6b23072b6cb03af", - "dist/2021-11-01/rust-std-1.56.1-x86_64-unknown-linux-musl.tar.xz": "055c5f8676712d8b86c3685d857d45bc0757594cb59f04dce4949a91df99635c", - "dist/2021-11-01/rust-std-1.56.1-x86_64-unknown-netbsd.tar.gz": "76eeb1ae5d876c8cbda6994806892597e48fa49adc01ed47228961c5508daa22", - "dist/2021-11-01/rust-std-1.56.1-x86_64-unknown-netbsd.tar.xz": "a4adabe39a73919957235629a9df3beb61353e829442f6e44f1c605fe5cddae3", - "dist/2021-11-01/rust-std-1.56.1-x86_64-unknown-redox.tar.gz": "ddfead63d5d9c4ee589684068156edf00ad50bbe680f1e000e821b2279a753d6", - "dist/2021-11-01/rust-std-1.56.1-x86_64-unknown-redox.tar.xz": "a50ea76404efc7fc49ac79ecf9ad4962bd914c52061687fee5b343e25e71a215", - "dist/2021-11-01/rustc-1.56.1-aarch64-apple-darwin.tar.gz": "fcb2c2e46e3cc7e7cba3abbb78ba87131aea56770145f8d97944b675a491312a", - "dist/2021-11-01/rustc-1.56.1-aarch64-apple-darwin.tar.xz": "b68f42d3d5ef3c88ac21f5958149a25bacc4144c69a5d6b04ed3d05530265817", - "dist/2021-11-01/rustc-1.56.1-aarch64-pc-windows-msvc.tar.gz": "c02a963a7635e2971c500125fcd3c3f2f5fad87262007af1456fc520c866e60c", - "dist/2021-11-01/rustc-1.56.1-aarch64-pc-windows-msvc.tar.xz": "d715013ab58c18219cb735861484e1d728a50f36370ac6c635f2f771d51b64fe", - "dist/2021-11-01/rustc-1.56.1-aarch64-unknown-linux-gnu.tar.gz": "9e7461908d0b3e6f4bbb158b71d85e536c186fe571c9960f8ef4300328b25a11", - "dist/2021-11-01/rustc-1.56.1-aarch64-unknown-linux-gnu.tar.xz": "77aec6a8c5f3d33941c79a48cda3bb08878c23dd1947dc027dfe5c4da41305b3", - "dist/2021-11-01/rustc-1.56.1-aarch64-unknown-linux-musl.tar.gz": "1e913b7f39d0f478c48ff9b9dd6a05dfe67a6ad58e478509cafb20e106512965", - "dist/2021-11-01/rustc-1.56.1-aarch64-unknown-linux-musl.tar.xz": "d8e7e6b9a9f07b9a9f3c080d9fd2ab93684776b8e0434bb06c147ce626adef05", - "dist/2021-11-01/rustc-1.56.1-arm-unknown-linux-gnueabi.tar.gz": "509796815de3cde667a1c253d9255e4fd9af13c835ffefaf11c853edc75b0c77", - "dist/2021-11-01/rustc-1.56.1-arm-unknown-linux-gnueabi.tar.xz": "4030921274328ce7e3fcc2a7aed19d09d28831eb4d426200a5749bd698c51589", - "dist/2021-11-01/rustc-1.56.1-arm-unknown-linux-gnueabihf.tar.gz": "3d542c8c14c5f103ba8a8a685a22a7658efdff1ca06adc99a6639b20fbda0abd", - "dist/2021-11-01/rustc-1.56.1-arm-unknown-linux-gnueabihf.tar.xz": "2507cdd49bd7f5c07d4b351b933d172bd92f53718569bb2fc7de506cd1750dab", - "dist/2021-11-01/rustc-1.56.1-armv7-unknown-linux-gnueabihf.tar.gz": "bbbe46c312c9355c1689d4dbce1c8291d9827a91ae69eea7754f789dcdccc37c", - "dist/2021-11-01/rustc-1.56.1-armv7-unknown-linux-gnueabihf.tar.xz": "6ca09ce8d5170162135817da08866a7d0afbb68bea46220882cea68c5a3d35df", - "dist/2021-11-01/rustc-1.56.1-i686-pc-windows-gnu.tar.gz": "81ab13668fc09e79a9a50bd2dc264063aa0a02be81608bee34a0c0bd1cb00645", - "dist/2021-11-01/rustc-1.56.1-i686-pc-windows-gnu.tar.xz": "dd7353dd36878caee807fafd8f88f74519107e0e69812190f86df9a84c1ebb43", - "dist/2021-11-01/rustc-1.56.1-i686-pc-windows-msvc.tar.gz": "2a7356c843eca8619b18d01e22f498879a2b3d6f3a30a620c989a1941bd4bf05", - "dist/2021-11-01/rustc-1.56.1-i686-pc-windows-msvc.tar.xz": "88344ed564c825f06d5a2666cb0be330d55855ecf887d287479ccaf50b50fea2", - "dist/2021-11-01/rustc-1.56.1-i686-unknown-linux-gnu.tar.gz": "a6ce2439963fd848199347fb75b323f9d1b7e1a6fa5b1d02cd741322a582ad65", - "dist/2021-11-01/rustc-1.56.1-i686-unknown-linux-gnu.tar.xz": "ac97b1887881d3703635d1118977d53b54d24a24899d79e3b1a13c92adbcb317", - "dist/2021-11-01/rustc-1.56.1-mips-unknown-linux-gnu.tar.gz": "33523515ad417544a50a9339702a5227a41debefdd06708897aeff7936c617e2", - "dist/2021-11-01/rustc-1.56.1-mips-unknown-linux-gnu.tar.xz": "02d46cabdbfe64a2ccb7fed78097352b8ec6d98a1912c8a319ca9474da7260bf", - "dist/2021-11-01/rustc-1.56.1-mips64-unknown-linux-gnuabi64.tar.gz": "3446859f0028eab1289602d3f020e4f98356d6881639264de658d87763844a46", - "dist/2021-11-01/rustc-1.56.1-mips64-unknown-linux-gnuabi64.tar.xz": "11a5eff326595db4ed8f4c3e642a4d3cdbdc226a68044d55f077873dcb67ca05", - "dist/2021-11-01/rustc-1.56.1-mips64el-unknown-linux-gnuabi64.tar.gz": "0c582b3bd06c04d0de33124c6096d61cac65cae159fbc39e7fd84b595075d1cb", - "dist/2021-11-01/rustc-1.56.1-mips64el-unknown-linux-gnuabi64.tar.xz": "06fd3d739d074f44f08bcc308d2b4866cc8f347043ebfc61044fb6a515f214a1", - "dist/2021-11-01/rustc-1.56.1-mipsel-unknown-linux-gnu.tar.gz": "91e59e111fb5a10abdcfb1d65881b8159e514216da3076433a64fd5bb29eb2e8", - "dist/2021-11-01/rustc-1.56.1-mipsel-unknown-linux-gnu.tar.xz": "357f728b7c592f8b994641eeed9b7c732bf2cb2bea34a06a60bfa1c8c2dc1bc0", - "dist/2021-11-01/rustc-1.56.1-powerpc-unknown-linux-gnu.tar.gz": "10306ea9eee418341d2c6160b4f4135f5d921acaaf5bee9687f85297f9750539", - "dist/2021-11-01/rustc-1.56.1-powerpc-unknown-linux-gnu.tar.xz": "3837b4377cad3e539f8679d8c420423fe9a5015b83fc8a697c49cfaf8edee4ce", - "dist/2021-11-01/rustc-1.56.1-powerpc64-unknown-linux-gnu.tar.gz": "e0ff6e79744753642b0b7eec91ec9d4769c26563e7ef6b5ae2b3b1b8ba221eec", - "dist/2021-11-01/rustc-1.56.1-powerpc64-unknown-linux-gnu.tar.xz": "07e8078e131aac48ecc68b7dbf82061cd1cbcc6764016464f5535b4eb4b95ae4", - "dist/2021-11-01/rustc-1.56.1-powerpc64le-unknown-linux-gnu.tar.gz": "0517345c67aa77eef9a7facffd28d679655e9d453892d61bfc9d8c09ff8e9dce", - "dist/2021-11-01/rustc-1.56.1-powerpc64le-unknown-linux-gnu.tar.xz": "96c6accf1829ebaeedddb3998e53d10439d9e566970b3f8c89c4026421e75277", - "dist/2021-11-01/rustc-1.56.1-riscv64gc-unknown-linux-gnu.tar.gz": "8ec8ae0c1ea281d99eb83f93bfc8e38d8c6ffac20d5b18004e3d2bbeaa362f1b", - "dist/2021-11-01/rustc-1.56.1-riscv64gc-unknown-linux-gnu.tar.xz": "a14b25c11f929ecc6e6aee3ce2a608d054f5349453304f3fb41e020d8fcf0ab1", - "dist/2021-11-01/rustc-1.56.1-s390x-unknown-linux-gnu.tar.gz": "6bdd92400c1f150009215fd5122c6ac9f1b5ed59a055e8268169115313f792ed", - "dist/2021-11-01/rustc-1.56.1-s390x-unknown-linux-gnu.tar.xz": "0b6edfc6aeb8d390afdc1ee18a921fd2ea7bdbdb9c7e1a6ed61d4198db9cdb8f", - "dist/2021-11-01/rustc-1.56.1-x86_64-apple-darwin.tar.gz": "876b9ed13a71ada3c00878c6006d837b852973cba84419753445c8a8a76efe00", - "dist/2021-11-01/rustc-1.56.1-x86_64-apple-darwin.tar.xz": "aa7f98ef0cbf1cd3e983d8240474d381c800e25c33522532abf03fb960c065d6", - "dist/2021-11-01/rustc-1.56.1-x86_64-pc-windows-gnu.tar.gz": "c901b2ea9d6cc460b4e726ea0acf97a604cd50594f57470d10e848eed7cc557d", - "dist/2021-11-01/rustc-1.56.1-x86_64-pc-windows-gnu.tar.xz": "8c6add5c7068ff8d958292e17efb76c4064373d45283bf68075fee1220317435", - "dist/2021-11-01/rustc-1.56.1-x86_64-pc-windows-msvc.tar.gz": "709fa5ad9723e233025ab0cd142b628cd8a4bb8d11fcdbb97a779d78a60604e5", - "dist/2021-11-01/rustc-1.56.1-x86_64-pc-windows-msvc.tar.xz": "68970f47f8eb37b683521c97ce1e9fc711bb526a8474c8950b798fb5f5482412", - "dist/2021-11-01/rustc-1.56.1-x86_64-unknown-freebsd.tar.gz": "b6a440bf5c3b1e4930effc07c6e50bf03cc44c0465f0c379d626b800f4971700", - "dist/2021-11-01/rustc-1.56.1-x86_64-unknown-freebsd.tar.xz": "630a2d54a614c7d2b2f57f83c8d36c9b037299b42233e267bfedb05ef178de28", - "dist/2021-11-01/rustc-1.56.1-x86_64-unknown-illumos.tar.gz": "4dbb2778c2210c4f02a8e4b8088b087f0b1141adbe466e82197f23cdbc839573", - "dist/2021-11-01/rustc-1.56.1-x86_64-unknown-illumos.tar.xz": "b9eb72e9f112c691000daabe4e4ba1964d21e6fb8e0dd2c1d5595b6bb542c609", - "dist/2021-11-01/rustc-1.56.1-x86_64-unknown-linux-gnu.tar.gz": "d09557a497a4f3b0726cae4c8e193843e403c80615f25f6ef740c79d7e4c122b", - "dist/2021-11-01/rustc-1.56.1-x86_64-unknown-linux-gnu.tar.xz": "a7001d1218b62d377cab15522d1b1c376b073c05f7d0ff32cf278871a5eeda3d", - "dist/2021-11-01/rustc-1.56.1-x86_64-unknown-linux-musl.tar.gz": "b49ef5d9d8a2c49e48dda8bf08fc5a95ac87095a8895df9dbce0ecfb1a97c70a", - "dist/2021-11-01/rustc-1.56.1-x86_64-unknown-linux-musl.tar.xz": "1b1f83b69502240ea66a45426bb1ba3a7c1291b05c31b59a28ac0551933e1210", - "dist/2021-11-01/rustc-1.56.1-x86_64-unknown-netbsd.tar.gz": "a79a181ea75bd0ed282cff60c42b4abad1126f7ea62f46c5f648866cb1a2815f", - "dist/2021-11-01/rustc-1.56.1-x86_64-unknown-netbsd.tar.xz": "58ab590c0421689b4bbe7f41918a508e3640d68e9ad98798d810a12dc16d8780" + "dist/2021-12-02/cargo-1.57.0-aarch64-apple-darwin.tar.gz": "2171ecf2c18fadd90588252aa294272aeb740f065772076ef36d04b1b4bfcc4e", + "dist/2021-12-02/cargo-1.57.0-aarch64-apple-darwin.tar.xz": "7314e53b73811913f63556860789d8a337b44bb240c485f3fab7d95f0e220b03", + "dist/2021-12-02/cargo-1.57.0-aarch64-pc-windows-msvc.tar.gz": "6025c78e9a8ca66c602315ce4f41f6531f038e32069a4a6994ab85cb8d7b0f33", + "dist/2021-12-02/cargo-1.57.0-aarch64-pc-windows-msvc.tar.xz": "5ba6ebf1b17b4273bd22cf433b98a2839a8e873e90065fe744a420fb537aac78", + "dist/2021-12-02/cargo-1.57.0-aarch64-unknown-linux-gnu.tar.gz": "8c046fc59feb1d670757b6de30990e346faa4b2ff49cd42f6d5f6a2b92a1ad6c", + "dist/2021-12-02/cargo-1.57.0-aarch64-unknown-linux-gnu.tar.xz": "6d11cd94618d80cda273eeeae7285980445f61a49ebacc616777b482a41cbf3f", + "dist/2021-12-02/cargo-1.57.0-aarch64-unknown-linux-musl.tar.gz": "87f7b1fb2b1a270336fbeac0ed2ea2ceda1fde26467f133e059907b57ad2bdb6", + "dist/2021-12-02/cargo-1.57.0-aarch64-unknown-linux-musl.tar.xz": "2f336c14418dbd117df136f99fc7c89459ee3553e8951473be138fa562483516", + "dist/2021-12-02/cargo-1.57.0-arm-unknown-linux-gnueabi.tar.gz": "d6efa8b3ccaa679b7637c8c36ac4772d35c2ba6517ddaabe59fb2823a7d9bb29", + "dist/2021-12-02/cargo-1.57.0-arm-unknown-linux-gnueabi.tar.xz": "2da3bff82818bf1ad1fdc09f335247a9261355fac587c272ee15655eb85b4575", + "dist/2021-12-02/cargo-1.57.0-arm-unknown-linux-gnueabihf.tar.gz": "4d1a1f8bc824020321560636dcc2989cce1114739c6d0c3864d8ff371cb7e85d", + "dist/2021-12-02/cargo-1.57.0-arm-unknown-linux-gnueabihf.tar.xz": "08df39d99604e9c5456d972c36792cee31b6882c7e471935298a5e4870dce4ab", + "dist/2021-12-02/cargo-1.57.0-armv7-unknown-linux-gnueabihf.tar.gz": "16a1c7390dd13ae03e85948ceffe33b1592c08999764e871adbd3f23b6d2f626", + "dist/2021-12-02/cargo-1.57.0-armv7-unknown-linux-gnueabihf.tar.xz": "70341859c855780b62e52cfe13e88ad6d1b2f895012043ab7e56a1bc3bcd4cd5", + "dist/2021-12-02/cargo-1.57.0-i686-pc-windows-gnu.tar.gz": "7beff47d0d6143d492755622207fa5f2c07683cae4a5dd5ed43f0ec4b60b99df", + "dist/2021-12-02/cargo-1.57.0-i686-pc-windows-gnu.tar.xz": "41572472f4047b6729b450def5812a0e8e54497ce50a98900138807a5167b6cc", + "dist/2021-12-02/cargo-1.57.0-i686-pc-windows-msvc.tar.gz": "4ccc3d6e5a8138824521e74087d1c03800413c6b0fff7e7ba5def756ed440508", + "dist/2021-12-02/cargo-1.57.0-i686-pc-windows-msvc.tar.xz": "474b1d047a1b12e34ca4a099a2040abc15c2dd98904905110e546e52d0f80f83", + "dist/2021-12-02/cargo-1.57.0-i686-unknown-linux-gnu.tar.gz": "ac2f436f87f04d40cfff9dbc7a0554c387dfc1ec1ff5e5a9425b7203b0528fc5", + "dist/2021-12-02/cargo-1.57.0-i686-unknown-linux-gnu.tar.xz": "9898a1fae2647f930fa14b9c160a1d22e67ccc70ac0d2d8f79ef1ffcf8d89af7", + "dist/2021-12-02/cargo-1.57.0-mips-unknown-linux-gnu.tar.gz": "f5618dbb97f9ee4c2472a53bd8b1ef08043c88a0c62675bf33677b458ad9564d", + "dist/2021-12-02/cargo-1.57.0-mips-unknown-linux-gnu.tar.xz": "270aac785bda2d4b282408abbb2286d655f938c98eb6106fc8408b5488560ab3", + "dist/2021-12-02/cargo-1.57.0-mips64-unknown-linux-gnuabi64.tar.gz": "33f8488593b2857dd23fe086c843860fdb752f76bd8fc64a617f69120766f423", + "dist/2021-12-02/cargo-1.57.0-mips64-unknown-linux-gnuabi64.tar.xz": "f28e02a67825da0f73259d7d26efa6f5fc827bb934cafd1ce4bfab24663ba481", + "dist/2021-12-02/cargo-1.57.0-mips64el-unknown-linux-gnuabi64.tar.gz": "761aafc99ae980eae6fe2836b68336ffb033b9de1ffe19fc4fcef503a59b0c42", + "dist/2021-12-02/cargo-1.57.0-mips64el-unknown-linux-gnuabi64.tar.xz": "2ea76ffa445788afd669155457bc8ca67a1a50ed205e74d6474ef2451875ab49", + "dist/2021-12-02/cargo-1.57.0-mipsel-unknown-linux-gnu.tar.gz": "f6655da10fe674ae065754415d658669b3b6d26a9b0a0b762385cbba56a141db", + "dist/2021-12-02/cargo-1.57.0-mipsel-unknown-linux-gnu.tar.xz": "834bd30b33936467aecd144845f7381fb7cca218a74e40ae2bf7ba1811f8557f", + "dist/2021-12-02/cargo-1.57.0-powerpc-unknown-linux-gnu.tar.gz": "7910ee91986543b88e84adc0593639a5b8a9343d95dbf5071153c1fd295c90dd", + "dist/2021-12-02/cargo-1.57.0-powerpc-unknown-linux-gnu.tar.xz": "e896f396d6fceed389c5c145e2b5edfa45e0102368f6544e3acae6219f766c09", + "dist/2021-12-02/cargo-1.57.0-powerpc64-unknown-linux-gnu.tar.gz": "36d41f2f2f0ecb9f00543c57637df138bfb27838ab98440407839dfeeb90c2cd", + "dist/2021-12-02/cargo-1.57.0-powerpc64-unknown-linux-gnu.tar.xz": "6af98fff5db1ce7c16cc7bdc1f10141c8a9e4d06175ed74a2cd6b256a15e5d95", + "dist/2021-12-02/cargo-1.57.0-powerpc64le-unknown-linux-gnu.tar.gz": "96c6cd0392f5d2acd2a5f198217cd8c015857f659c257913f5c439f33a55ed4c", + "dist/2021-12-02/cargo-1.57.0-powerpc64le-unknown-linux-gnu.tar.xz": "599cf1b5a8cdbf76d591621bc9222aefa60e2f5fd378ae71c4dcf4514c47122e", + "dist/2021-12-02/cargo-1.57.0-riscv64gc-unknown-linux-gnu.tar.gz": "0ff569ea422cd18c6cf9e6bdf9df0768592e7bfc9c26b9084d715ea9c72d2bef", + "dist/2021-12-02/cargo-1.57.0-riscv64gc-unknown-linux-gnu.tar.xz": "217d10841ff9460db242e35827e89b86c6869f604db52983ff672c959716af3b", + "dist/2021-12-02/cargo-1.57.0-s390x-unknown-linux-gnu.tar.gz": "c38bca25c81a15b499227e740a6fdfc68af97d3c584bec2f4df3f1eabb5aa512", + "dist/2021-12-02/cargo-1.57.0-s390x-unknown-linux-gnu.tar.xz": "bf1317db77e6929c0ff53818e5e5681ee795c006647d4bebb24205e8a4859528", + "dist/2021-12-02/cargo-1.57.0-x86_64-apple-darwin.tar.gz": "26129f0e3ecd42e730f62d9c693e1a89aedfe6b7c8108cf970b2f1ed51900fb8", + "dist/2021-12-02/cargo-1.57.0-x86_64-apple-darwin.tar.xz": "019e0387ec5db129d1370311fa85024af5e0eb9bce4a79216148fb579027b7b1", + "dist/2021-12-02/cargo-1.57.0-x86_64-pc-windows-gnu.tar.gz": "9e32217053d290b860aad03f31c5ee29b797fc05def8144dbb7106fa7c21d10a", + "dist/2021-12-02/cargo-1.57.0-x86_64-pc-windows-gnu.tar.xz": "5512f953572e0eb29ac01436d63d8741957eb65e0183324c140bbd920e7f9ca5", + "dist/2021-12-02/cargo-1.57.0-x86_64-pc-windows-msvc.tar.gz": "23f4562605316f0c9002bb30d0e635f96577db9002052ef2f78b63e747b6b2cd", + "dist/2021-12-02/cargo-1.57.0-x86_64-pc-windows-msvc.tar.xz": "a68b853b7dac161472952958f0b4c81352473956982eb9391635624429a9758b", + "dist/2021-12-02/cargo-1.57.0-x86_64-unknown-freebsd.tar.gz": "c14839639299fce4e448629950c28de61fcfdd0393f9a751958c5c6d9c6d2ba7", + "dist/2021-12-02/cargo-1.57.0-x86_64-unknown-freebsd.tar.xz": "84bbe73e1806b459d310d3f213f5d7e80758e69d5549b417ce4ef7615d19ec7a", + "dist/2021-12-02/cargo-1.57.0-x86_64-unknown-illumos.tar.gz": "09276f2b97f3c79e408f480be3d5123e25c438eb99440507f240a40f96c2e25d", + "dist/2021-12-02/cargo-1.57.0-x86_64-unknown-illumos.tar.xz": "d6e48f5f5f604869ad685ce81a11e6e37f57b984c79051e0d898c9d7d1ba7903", + "dist/2021-12-02/cargo-1.57.0-x86_64-unknown-linux-gnu.tar.gz": "2b341034e4c30bede47a432751935549a28e40b566a1fd4b59c824ccd0a26ff6", + "dist/2021-12-02/cargo-1.57.0-x86_64-unknown-linux-gnu.tar.xz": "ed2013713ae742895af5df8d91c5430ba9ba3c781e3bc7f3471b220cc06d565d", + "dist/2021-12-02/cargo-1.57.0-x86_64-unknown-linux-musl.tar.gz": "0f14c6bb7c413c3be2db1917eb0109b7563bff0ba02a03d30089004811d87f2f", + "dist/2021-12-02/cargo-1.57.0-x86_64-unknown-linux-musl.tar.xz": "0d8564d0348843d6c08d98990d9eac50b7b7ab790f89d514b4f45079e786d932", + "dist/2021-12-02/cargo-1.57.0-x86_64-unknown-netbsd.tar.gz": "683d3c3b680db1f68fc3662eca8b9f28b49abe0a94e681cd334863cafdd82927", + "dist/2021-12-02/cargo-1.57.0-x86_64-unknown-netbsd.tar.xz": "9928892ba85981078744a414fc22cddc7bfe686dc0f0de3b63ecaecab6a43b9a", + "dist/2021-12-02/rust-std-1.57.0-aarch64-apple-darwin.tar.gz": "3b442d3f546524aef4fe8483c5ddcec1c5dbd52216d98aabc066883db31088d8", + "dist/2021-12-02/rust-std-1.57.0-aarch64-apple-darwin.tar.xz": "1636ae0aa61c0d64bbcaf424d0a18b4f1e604b538ffdf86d710beeb1e36ffbf4", + "dist/2021-12-02/rust-std-1.57.0-aarch64-apple-ios-sim.tar.gz": "9f02f66495ea99a1963bd62a4875d2184d7961a2e99d87c30026463db7b47763", + "dist/2021-12-02/rust-std-1.57.0-aarch64-apple-ios-sim.tar.xz": "eaa23999e342f0494f1e0a099c30ae890d27472e647b8d4b30d4aa78c4449647", + "dist/2021-12-02/rust-std-1.57.0-aarch64-apple-ios.tar.gz": "18a0aad4b8915f1c30addeb9dc8ac7383f5be79acf0a6b965131542e7495285a", + "dist/2021-12-02/rust-std-1.57.0-aarch64-apple-ios.tar.xz": "531e8daa9483b8e6e7427361c7e3bc51b4ce61ea0df426f7f8689d324f787396", + "dist/2021-12-02/rust-std-1.57.0-aarch64-fuchsia.tar.gz": "8fe58448f37ec82289c0a5fde05c4e4f65673769b859878bf33eb98d2f0691ae", + "dist/2021-12-02/rust-std-1.57.0-aarch64-fuchsia.tar.xz": "1ef319a03173131f30509cc987e7831ae888de9695807954afe97db210052c8b", + "dist/2021-12-02/rust-std-1.57.0-aarch64-linux-android.tar.gz": "18ec2075e582ec33a6fe2d2099b7f6036658364ab1e276d018fbafdb6719d1e8", + "dist/2021-12-02/rust-std-1.57.0-aarch64-linux-android.tar.xz": "0b7545897710a7504ee750696068518b06b300c7deb7ecb73abf71bccbaae8bc", + "dist/2021-12-02/rust-std-1.57.0-aarch64-pc-windows-msvc.tar.gz": "a6e59bce55b55dc969e2d49e17d439e6de8db0674b93f2bc4a5c99303f4f20f9", + "dist/2021-12-02/rust-std-1.57.0-aarch64-pc-windows-msvc.tar.xz": "ab519f2a14bae0e97e441faa7f87f8b7c705a2d4401bea061cb0e15116a5a96c", + "dist/2021-12-02/rust-std-1.57.0-aarch64-unknown-linux-gnu.tar.gz": "4c70901d1cbddec9ea99fbd62b20f454d30e1ffbb48a21169ac823b3f02a1fbc", + "dist/2021-12-02/rust-std-1.57.0-aarch64-unknown-linux-gnu.tar.xz": "3618da916a0f92f241cf1d67d04bb57835b303cf2047b57dc2f2487b89a4fc1f", + "dist/2021-12-02/rust-std-1.57.0-aarch64-unknown-linux-musl.tar.gz": "4f0c6533186b8fb596ee11b49bd6c9ffb76be59eb8bbdf26f25a47d297666c02", + "dist/2021-12-02/rust-std-1.57.0-aarch64-unknown-linux-musl.tar.xz": "a955bb0d7b8c6fc67f89af6e4eba4aa700debe7b040c5e19cbb9e2eb57c234af", + "dist/2021-12-02/rust-std-1.57.0-aarch64-unknown-none-softfloat.tar.gz": "b862bd4f0343ab208ce22b6f6a61484b49d4901c1bf15376084dce8f6b3281bc", + "dist/2021-12-02/rust-std-1.57.0-aarch64-unknown-none-softfloat.tar.xz": "87c00a21b346f30fb2c043f465df941e43b9540f932ab632823908e703d65607", + "dist/2021-12-02/rust-std-1.57.0-aarch64-unknown-none.tar.gz": "9b3f99dc749675c22167397fd0a8168b359c33faefcc1dd81b120a83aa279f94", + "dist/2021-12-02/rust-std-1.57.0-aarch64-unknown-none.tar.xz": "994d8e9015ce454782d79fea174005d752ea39969841f9bb6759557186e25097", + "dist/2021-12-02/rust-std-1.57.0-arm-linux-androideabi.tar.gz": "51eadd4c8b0d725013e1f4a35db0fe0728ce17330738b5145f902d66655f9276", + "dist/2021-12-02/rust-std-1.57.0-arm-linux-androideabi.tar.xz": "a85597cec6a6ac4b3941b7faf3bd720b3510b810a9e9953e46e046a4695ed555", + "dist/2021-12-02/rust-std-1.57.0-arm-unknown-linux-gnueabi.tar.gz": "976ca4b8feef5e455734ee121f947719c32e1a3bea273e186c110bfb2c129c5b", + "dist/2021-12-02/rust-std-1.57.0-arm-unknown-linux-gnueabi.tar.xz": "511e041c31f0eba4fe1468167953b390b590ed7fecc5021fce27d53a01156128", + "dist/2021-12-02/rust-std-1.57.0-arm-unknown-linux-gnueabihf.tar.gz": "5d64eaa7af15fc79de39f12ba354ef8c9bb6d5728350c66d7252ba25c64aa205", + "dist/2021-12-02/rust-std-1.57.0-arm-unknown-linux-gnueabihf.tar.xz": "c01e395b23bfdf4b194b7f18b8cb770349545870076828be12271aebc697eeec", + "dist/2021-12-02/rust-std-1.57.0-arm-unknown-linux-musleabi.tar.gz": "86b71d79357d0de0a21a05752de20760113414d29026b7d2b6afb6a505f38508", + "dist/2021-12-02/rust-std-1.57.0-arm-unknown-linux-musleabi.tar.xz": "3692765f05178dcfe7397e7d50acb9da4623f20c33c36a042b1cf5f2c34f5f20", + "dist/2021-12-02/rust-std-1.57.0-arm-unknown-linux-musleabihf.tar.gz": "2671c3750fe76936c1ca66207338eead86bdefe86aa5fc1d6abd770832da3afe", + "dist/2021-12-02/rust-std-1.57.0-arm-unknown-linux-musleabihf.tar.xz": "4b728d19db0ac4ba8501b2b8674d9b1da923fa4470a795b8a4e19b858f251642", + "dist/2021-12-02/rust-std-1.57.0-armebv7r-none-eabi.tar.gz": "c700f1c43c6e518ee2631a7e29728374b6ecbde8a99d53f4834586db702f6a8c", + "dist/2021-12-02/rust-std-1.57.0-armebv7r-none-eabi.tar.xz": "e1e529d92893f6ae1ec16b794dc0781cfbc28a1e0544e569f84a273accdc8875", + "dist/2021-12-02/rust-std-1.57.0-armebv7r-none-eabihf.tar.gz": "cb347fd42f69feabde938a5da11ec82593dee9d224a4c0f3fb22d2418ee5b5fe", + "dist/2021-12-02/rust-std-1.57.0-armebv7r-none-eabihf.tar.xz": "6438c44447bb28507fdf16b0de631c05b374c7b103f93123bb2e34804ade6989", + "dist/2021-12-02/rust-std-1.57.0-armv5te-unknown-linux-gnueabi.tar.gz": "2d2eaaa29093306eb65ce7011456e5b4fa5e2f262697b72d25d804403a8ff632", + "dist/2021-12-02/rust-std-1.57.0-armv5te-unknown-linux-gnueabi.tar.xz": "a54a9d4758c7e12de338b44821af82ec106794d9fef61cb45dc723148aebf696", + "dist/2021-12-02/rust-std-1.57.0-armv5te-unknown-linux-musleabi.tar.gz": "3f29dbb27b75626fc5ab0d31a932c60126e1c696c191ac444910889cf65208cf", + "dist/2021-12-02/rust-std-1.57.0-armv5te-unknown-linux-musleabi.tar.xz": "afd19d7791af063d9d4daf6ff479f95ad579d9e9b2cd7c0bc147ecb1a8bf0508", + "dist/2021-12-02/rust-std-1.57.0-armv7-linux-androideabi.tar.gz": "0d4e0fda7eaf077e880118a858016e20b8844c4636ac053d2b2bde7d41cecebe", + "dist/2021-12-02/rust-std-1.57.0-armv7-linux-androideabi.tar.xz": "7793c95b4488e4b29843af7f6058f184961d2ab427da00a244c8d02c55821939", + "dist/2021-12-02/rust-std-1.57.0-armv7-unknown-linux-gnueabi.tar.gz": "0b52dd17e0a4005bff9f9815c48c5f10b54fd05d3e4c5247125e2a01b6dbf72e", + "dist/2021-12-02/rust-std-1.57.0-armv7-unknown-linux-gnueabi.tar.xz": "7e88d917a2c7c32bdd7d2e159af67d1b2aae3b6022d7cfca6d76b9fce8cde68b", + "dist/2021-12-02/rust-std-1.57.0-armv7-unknown-linux-gnueabihf.tar.gz": "39b170358cf76c6dc284cf2c99439338871b79f5d0417f3342d48694c392121d", + "dist/2021-12-02/rust-std-1.57.0-armv7-unknown-linux-gnueabihf.tar.xz": "4811caac5c61fced4e1b8690196cc4bc853acf4378ca93d6d1a391360bbccb28", + "dist/2021-12-02/rust-std-1.57.0-armv7-unknown-linux-musleabi.tar.gz": "c35382193ad3303e6367e7a145ef9b3f6d2bd21eb7345b6ce6d844055d135def", + "dist/2021-12-02/rust-std-1.57.0-armv7-unknown-linux-musleabi.tar.xz": "461248b8b8b9ed376b4dd7ea025cb26ff2c2f439c75486f8a2d8783229cae3ec", + "dist/2021-12-02/rust-std-1.57.0-armv7-unknown-linux-musleabihf.tar.gz": "0c3917cb3e166fc1f3dbb945893199a12e578df32f02c70c9bce1cda7d968c1a", + "dist/2021-12-02/rust-std-1.57.0-armv7-unknown-linux-musleabihf.tar.xz": "efef9a9cbf7d6d6f62dd2c24b409e1fca6d65bcda460b3cd99dab3cfb78448bd", + "dist/2021-12-02/rust-std-1.57.0-armv7a-none-eabi.tar.gz": "ba83df0fbf8d13f001c285a23a2637b4726bab5fdcb6dfb2287f9fda77166a09", + "dist/2021-12-02/rust-std-1.57.0-armv7a-none-eabi.tar.xz": "d18bcfede5e1f915c3b687de6b2063191a8f11c5f3c8a0004630acd40fb71be0", + "dist/2021-12-02/rust-std-1.57.0-armv7r-none-eabi.tar.gz": "7597495f42b7b123713bf9e1bfe273ff9757a406ade15d2d3bee4c408b6da18d", + "dist/2021-12-02/rust-std-1.57.0-armv7r-none-eabi.tar.xz": "b986d23b49502c81f5453847c684992869ceae667f5f0abebfe05f1e236df91a", + "dist/2021-12-02/rust-std-1.57.0-armv7r-none-eabihf.tar.gz": "192c828d0d4ead6963329ec748df97f3e76f7caea1a655b1b28533836940dcd7", + "dist/2021-12-02/rust-std-1.57.0-armv7r-none-eabihf.tar.xz": "4e9320254db1d59ae9a627a61cd30fba3c8a3475390cac94b573c84a2a42ab85", + "dist/2021-12-02/rust-std-1.57.0-asmjs-unknown-emscripten.tar.gz": "3d66b82d7d459fd7192f05d065294f24bdc3758d87e3186b4dfb1672b4ae2605", + "dist/2021-12-02/rust-std-1.57.0-asmjs-unknown-emscripten.tar.xz": "3f703927486f9289026eafe4961c0ea5d05f5513e529333ad9aaa1164a2374d3", + "dist/2021-12-02/rust-std-1.57.0-i586-pc-windows-msvc.tar.gz": "5a408b484d6964c2aa1edc49df3bf0999dc3ddb02ea113759c87360cd1b5c897", + "dist/2021-12-02/rust-std-1.57.0-i586-pc-windows-msvc.tar.xz": "573edf9a4d0d793b597bf57fdf599433051ce0a8e211af09d3328b87e0ddacf1", + "dist/2021-12-02/rust-std-1.57.0-i586-unknown-linux-gnu.tar.gz": "1c8b04c71789fff9617885ad0fda22ee727b32c33b0bc61e5fdd7f80c918ece2", + "dist/2021-12-02/rust-std-1.57.0-i586-unknown-linux-gnu.tar.xz": "d304d411c16ea9d87d8014bca0f1cfb5a10e21db92738c351ae07f4719fafa62", + "dist/2021-12-02/rust-std-1.57.0-i586-unknown-linux-musl.tar.gz": "bf6a9c0fb523ddcbf5ec8299df06c0ca0adffc75f9425f222c32b5f3f3a8bc19", + "dist/2021-12-02/rust-std-1.57.0-i586-unknown-linux-musl.tar.xz": "e130c859458587c7dec97126235f48e4b383d2873b0fabc20aceee5df8ddc166", + "dist/2021-12-02/rust-std-1.57.0-i686-linux-android.tar.gz": "e5363a02847bb81938ba884ef7db750e0db48fabdcb3d271bb72dcb7d38910c4", + "dist/2021-12-02/rust-std-1.57.0-i686-linux-android.tar.xz": "7a048e8d1d0a0dda46b31316b5d30296cfa192bbb05916676c23ea5fce49e081", + "dist/2021-12-02/rust-std-1.57.0-i686-pc-windows-gnu.tar.gz": "64f0ac032b06aaa3036dbfa1eaf514edc458614736ae3ade0c88705eb7f4794d", + "dist/2021-12-02/rust-std-1.57.0-i686-pc-windows-gnu.tar.xz": "477acfdfc556a33e445510a8900792fe769a3306911470ce51f302e2f763ff46", + "dist/2021-12-02/rust-std-1.57.0-i686-pc-windows-msvc.tar.gz": "d8e66ae6a97a3470129646cb0f0961cb7fc4a6466514a8aad94b339f7f4996fe", + "dist/2021-12-02/rust-std-1.57.0-i686-pc-windows-msvc.tar.xz": "2ca8798eb9e3bb0f3c4a02cf5d17e4a3f0f4f2a3807585e165f30889cae39e0d", + "dist/2021-12-02/rust-std-1.57.0-i686-unknown-freebsd.tar.gz": "675aa73e634267aee38aaa184b6eb2c82ed7a995434a638ff42058d2c3e33b80", + "dist/2021-12-02/rust-std-1.57.0-i686-unknown-freebsd.tar.xz": "bd6d80eb66b6b0d578cec7e5d33a3713d3b63fc55f9a91f81132260f7b3d3f7d", + "dist/2021-12-02/rust-std-1.57.0-i686-unknown-linux-gnu.tar.gz": "6fb3eb0e9f401d568a3da52c7cd26dadfcd6f1ebd4bc25075b5a092e51e230c9", + "dist/2021-12-02/rust-std-1.57.0-i686-unknown-linux-gnu.tar.xz": "586e7fd521a058cbf4778abb67d7d078dd4820d356351d0b6a719e21d00966db", + "dist/2021-12-02/rust-std-1.57.0-i686-unknown-linux-musl.tar.gz": "5149f9eb32be782d49bc107a29aef4c063f2bc11a3f3b0d2a396f75b3ec4e7db", + "dist/2021-12-02/rust-std-1.57.0-i686-unknown-linux-musl.tar.xz": "1e57cc16c47cf89b44edbd869764c95c2289a55a63b3ea770ca0a69a20cea1e5", + "dist/2021-12-02/rust-std-1.57.0-mips-unknown-linux-gnu.tar.gz": "f4c3dadfdf03b5261a1eba2ccf382f99ef6f6177a4ee2d9f19174df6f2d81db4", + "dist/2021-12-02/rust-std-1.57.0-mips-unknown-linux-gnu.tar.xz": "a0a9a48e8896d7ea7831eb5e3bdcd971bdb02ba499bf954816a032510120fbea", + "dist/2021-12-02/rust-std-1.57.0-mips-unknown-linux-musl.tar.gz": "6bff4945b0abe605a45789a4567bee04f82cb8416b28fcd0aefc958c03102857", + "dist/2021-12-02/rust-std-1.57.0-mips-unknown-linux-musl.tar.xz": "cfed1422612946371da4a6cd6061c514a8ab75240c8ce3a362c2f46ae0f716b2", + "dist/2021-12-02/rust-std-1.57.0-mips64-unknown-linux-gnuabi64.tar.gz": "cde2b742b8e781a2da80b8ad81ac0f9fc646b3dbecbb4d77378999a705c33bf3", + "dist/2021-12-02/rust-std-1.57.0-mips64-unknown-linux-gnuabi64.tar.xz": "47f3f0777c438e51bbc23caf1e08195bcead9fb6f954585a4d07bc18ddbfefcf", + "dist/2021-12-02/rust-std-1.57.0-mips64-unknown-linux-muslabi64.tar.gz": "62612851267bc5559220f9329ea097b175eb310c9428efccd0702d6c3fb2e9eb", + "dist/2021-12-02/rust-std-1.57.0-mips64-unknown-linux-muslabi64.tar.xz": "e003a634f6a32a4a0ac41d0259530a018cb1f2ec5cde663ef8b834fa40901040", + "dist/2021-12-02/rust-std-1.57.0-mips64el-unknown-linux-gnuabi64.tar.gz": "c023ad3ebf8fcb3b8420932496034f19ce72b85279981d27c52dcdec7c172597", + "dist/2021-12-02/rust-std-1.57.0-mips64el-unknown-linux-gnuabi64.tar.xz": "52add79ae3b02a7bfc30d0a7639736251e6b41950ba32718b64daa0c0c7be46b", + "dist/2021-12-02/rust-std-1.57.0-mips64el-unknown-linux-muslabi64.tar.gz": "5ab4cc2cb17246fc2deedef0d10fb59ac2b7ba25dab15172a7073fe3f57a34cd", + "dist/2021-12-02/rust-std-1.57.0-mips64el-unknown-linux-muslabi64.tar.xz": "95cd2cbb25c72dd0c4abda05dabf4d0492a36156514ec7d58f88cb5671c707ca", + "dist/2021-12-02/rust-std-1.57.0-mipsel-unknown-linux-gnu.tar.gz": "c10e699fc22f673d8c91a4aad3e4e78ca60f91485936a093595f0ea90b5399c1", + "dist/2021-12-02/rust-std-1.57.0-mipsel-unknown-linux-gnu.tar.xz": "a5704f504bb182d6c327c513eb7feeecb366474ba0dfa28ee8fe8851f64c6f4d", + "dist/2021-12-02/rust-std-1.57.0-mipsel-unknown-linux-musl.tar.gz": "e939962334657e209ff0f693a2f0cef6f045cb9fa1f8648255370c6321eed889", + "dist/2021-12-02/rust-std-1.57.0-mipsel-unknown-linux-musl.tar.xz": "cafa0e02cebe1fb3ec227299e43e2e384e257fbcc7dcd5f5d6b14ac627ada27e", + "dist/2021-12-02/rust-std-1.57.0-nvptx64-nvidia-cuda.tar.gz": "360a5b1fd8c6bdfd7111503399172d9b9322f5271605dd3a2700e660e4f91e06", + "dist/2021-12-02/rust-std-1.57.0-nvptx64-nvidia-cuda.tar.xz": "19af6eb695f19a01048501c9f46c1ca37bef0f0fc3445b5048bd18566ff27108", + "dist/2021-12-02/rust-std-1.57.0-powerpc-unknown-linux-gnu.tar.gz": "dc70b13f3cd8bf6eab0d619a5e0113b071b070d06cb0bacec0e0632e09a3c5cc", + "dist/2021-12-02/rust-std-1.57.0-powerpc-unknown-linux-gnu.tar.xz": "bc117ce5f0c81d2e14ea2d1832c0e908b1153caf49f295a9d28af2128f5fae44", + "dist/2021-12-02/rust-std-1.57.0-powerpc64-unknown-linux-gnu.tar.gz": "ec90746fd488670dad0a3e2108e7180e77c85269387294114b5aceb14d6deea2", + "dist/2021-12-02/rust-std-1.57.0-powerpc64-unknown-linux-gnu.tar.xz": "e594147fcc269120ad808a57e967b320a51e16860b60642c435c37808cb5f7c5", + "dist/2021-12-02/rust-std-1.57.0-powerpc64le-unknown-linux-gnu.tar.gz": "a1a25ca8e035ca656075275e9ba1a2e757e43a6308245ce6119250b727fec8a3", + "dist/2021-12-02/rust-std-1.57.0-powerpc64le-unknown-linux-gnu.tar.xz": "fc07eb3e9f3d227428cc5b53ca868e3de375bc198ce4dce7b87a9246e6fec81a", + "dist/2021-12-02/rust-std-1.57.0-riscv32i-unknown-none-elf.tar.gz": "3c09939614d0056a5710584b9ff423096a8780e06c7db768db6535ab29ccb112", + "dist/2021-12-02/rust-std-1.57.0-riscv32i-unknown-none-elf.tar.xz": "1f31bbf7e136f1b5e1fac8ef99885e4baf32e75cee4025fd2782f6f169fe897d", + "dist/2021-12-02/rust-std-1.57.0-riscv32imac-unknown-none-elf.tar.gz": "b60f28167adbb3c86dff41d125a9821620501f5adfd9729958754cb5cb9092de", + "dist/2021-12-02/rust-std-1.57.0-riscv32imac-unknown-none-elf.tar.xz": "bcf36bbe11a46b0d531d1784570be5fb99a87e155589e1ea44d9636d7ad8ccfd", + "dist/2021-12-02/rust-std-1.57.0-riscv32imc-unknown-none-elf.tar.gz": "dea58baa24bd47a2037c93385d759d5a78c6c961dc5dcc1b92745c5796f8200c", + "dist/2021-12-02/rust-std-1.57.0-riscv32imc-unknown-none-elf.tar.xz": "1e4c9a6d4771c2510b0456b062b22ccb2d4a7578660fcfb2047aa8f2af0c03b4", + "dist/2021-12-02/rust-std-1.57.0-riscv64gc-unknown-linux-gnu.tar.gz": "ab549d4b6ac630abb96e2739f36f2165816efdd0bbba5982a827953886ab2531", + "dist/2021-12-02/rust-std-1.57.0-riscv64gc-unknown-linux-gnu.tar.xz": "de1b7198e4b5ce25dee89e671fa1b82a160f51f044831f9c96ec8c54ad9058db", + "dist/2021-12-02/rust-std-1.57.0-riscv64gc-unknown-none-elf.tar.gz": "331b526f8c6fa8906c3d9583fc67714ea94033507df07a100584ee8d9e4bebdb", + "dist/2021-12-02/rust-std-1.57.0-riscv64gc-unknown-none-elf.tar.xz": "7ded683ce09b0d586c42dc5be38fc842087af3abfd9369242fdd990ca43a831d", + "dist/2021-12-02/rust-std-1.57.0-riscv64imac-unknown-none-elf.tar.gz": "7451a6f45ed929d87d9be98327c106de919b08bf3eb4dac7f46112f937dbddfe", + "dist/2021-12-02/rust-std-1.57.0-riscv64imac-unknown-none-elf.tar.xz": "4bf072008958f5780c15fa4256d9417c010adf027eb7fd69d7bd028870f66d9b", + "dist/2021-12-02/rust-std-1.57.0-s390x-unknown-linux-gnu.tar.gz": "ede206caadda3c42de0476ebe0ff08dfcfb0704fabbd7b85d4827a37ecfb97bf", + "dist/2021-12-02/rust-std-1.57.0-s390x-unknown-linux-gnu.tar.xz": "383088afba88c89a7c5978ff57e9b4a07fcbd0dfc2789a84fa48eeab1360f31d", + "dist/2021-12-02/rust-std-1.57.0-sparc64-unknown-linux-gnu.tar.gz": "1f2328032ab7b0dc49eec2406f97e5afcd34d757333df46c6be4742069005132", + "dist/2021-12-02/rust-std-1.57.0-sparc64-unknown-linux-gnu.tar.xz": "8c7cd8d8d86d7fd5791fec6dd6b044bcdc0a00b5c2ce73a3374e14e7c0874eb2", + "dist/2021-12-02/rust-std-1.57.0-sparcv9-sun-solaris.tar.gz": "7d5a72307185b7e7adaea750aff1391f3f191f421c8bd756b4c0ab244106b764", + "dist/2021-12-02/rust-std-1.57.0-sparcv9-sun-solaris.tar.xz": "95d1a1a2ecf1b0d00606f4b2b32f1a44749943369a2c0643845199f87889e87e", + "dist/2021-12-02/rust-std-1.57.0-thumbv6m-none-eabi.tar.gz": "895a140a1bb5d8f021efb00d7e45a673e359f734beed4412374e64141dd3f012", + "dist/2021-12-02/rust-std-1.57.0-thumbv6m-none-eabi.tar.xz": "3b557d45b30d7180c5ca5f9bf820dfdb6b9e005415dc299647066253886b3164", + "dist/2021-12-02/rust-std-1.57.0-thumbv7em-none-eabi.tar.gz": "5ac6070a3f1f12718196917b6f803f39310743b520a36877321974555f43caaf", + "dist/2021-12-02/rust-std-1.57.0-thumbv7em-none-eabi.tar.xz": "21564f2af596ab2363d7124d00c96f42090f8c3c32759754dd07c378abee8695", + "dist/2021-12-02/rust-std-1.57.0-thumbv7em-none-eabihf.tar.gz": "6c0f075987837378c61fa32432bd887cde184a9a3dab0e5a1d5a0c240832ce16", + "dist/2021-12-02/rust-std-1.57.0-thumbv7em-none-eabihf.tar.xz": "917e79b81cfce328a4fc79555d83d2738772162f12ef78075080e3c8ee5d1039", + "dist/2021-12-02/rust-std-1.57.0-thumbv7m-none-eabi.tar.gz": "7913445ac379e6c437d552158b91e9dbe0a4425b5b153c18693cab9bc97d57f0", + "dist/2021-12-02/rust-std-1.57.0-thumbv7m-none-eabi.tar.xz": "b41555485bbaadf5692dfe4ab383d778b3c4dcea16ba97c4655cb4fe94eab626", + "dist/2021-12-02/rust-std-1.57.0-thumbv7neon-linux-androideabi.tar.gz": "70e1223aae258d20519662f4b53a294ebfac3deead841848b16254784dc93460", + "dist/2021-12-02/rust-std-1.57.0-thumbv7neon-linux-androideabi.tar.xz": "77ba420114fb2e1c23c4dd0d4e3e6a56ad12f7007374e4703dc8aa4810f3a429", + "dist/2021-12-02/rust-std-1.57.0-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "03e596499c02298a6633afaf942a6efc2358730bdf1bed71fa2a23e6d45466af", + "dist/2021-12-02/rust-std-1.57.0-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "2a09bfd05423b873eae26b24dadcf12a21168a58bf6ef633a6a94a9b5d156655", + "dist/2021-12-02/rust-std-1.57.0-thumbv8m.base-none-eabi.tar.gz": "0ed674d4d67e55866b9f2c484f82e7a8163a1b785b8956c555d10e39f25297d4", + "dist/2021-12-02/rust-std-1.57.0-thumbv8m.base-none-eabi.tar.xz": "78ca5bbf44c39e4374b93bf9a96d834f25f6020dc2a01a4ff572b98305d52deb", + "dist/2021-12-02/rust-std-1.57.0-thumbv8m.main-none-eabi.tar.gz": "873346f11c6ceaa36f049ba86ce0b9f2deb083ca68c2eaa8e9460c9eacd1bbb9", + "dist/2021-12-02/rust-std-1.57.0-thumbv8m.main-none-eabi.tar.xz": "866006b3f773ae2112007abc6a62a593fc706c9c59ca0d7893da230d8249d68c", + "dist/2021-12-02/rust-std-1.57.0-thumbv8m.main-none-eabihf.tar.gz": "069642f1a7ddc0afc152c261998b2f7bacd6869e9c0430a43e6fe5aa898a877c", + "dist/2021-12-02/rust-std-1.57.0-thumbv8m.main-none-eabihf.tar.xz": "f4c3d7c46af7b454efde4d9aec20c025f37f1fd5c147d19dac2e5ae715fb3e5b", + "dist/2021-12-02/rust-std-1.57.0-wasm32-unknown-emscripten.tar.gz": "dfdda9d9e1db3457d2b5cb6855f13b12663657968a501ca78f72646bf2dd3e35", + "dist/2021-12-02/rust-std-1.57.0-wasm32-unknown-emscripten.tar.xz": "8a0b2339eca0c8b04c5027eafa88bba0cc56dc3d0c0f368abd4c45283ced058e", + "dist/2021-12-02/rust-std-1.57.0-wasm32-unknown-unknown.tar.gz": "3e0525d9e16f1a58e847080f2d3c02e275c2d5563b7980311e39382bb6c8441d", + "dist/2021-12-02/rust-std-1.57.0-wasm32-unknown-unknown.tar.xz": "c5ceafae74f43ae31ca21f9523eee317e298d77b2ef94515a27676941f6271b7", + "dist/2021-12-02/rust-std-1.57.0-wasm32-wasi.tar.gz": "391d814379cf117e927e5deb17bf44e964adee4f5f7208eaee1ddc8927da1fbc", + "dist/2021-12-02/rust-std-1.57.0-wasm32-wasi.tar.xz": "93395034223068ea82efc61c6c32d040a7db13a5c0682608507261ef408c2cb5", + "dist/2021-12-02/rust-std-1.57.0-x86_64-apple-darwin.tar.gz": "c1eb892ddb50ebeed288b7aa8171ad46d62362bb26b2d82d2b463dfd45606dc2", + "dist/2021-12-02/rust-std-1.57.0-x86_64-apple-darwin.tar.xz": "46c2c8fd6aeffbfb62bc03ba913d65b37dfdb328405e2b75a540b6f68e1031c2", + "dist/2021-12-02/rust-std-1.57.0-x86_64-apple-ios.tar.gz": "cdceb2a0f711f6468ce283682657f58d4f9b5827c0c33742a23b49b87215db48", + "dist/2021-12-02/rust-std-1.57.0-x86_64-apple-ios.tar.xz": "48b87e3fca806c5d4bf81a8fd497586e60d7119f3a791b52ba2330ee300760bf", + "dist/2021-12-02/rust-std-1.57.0-x86_64-fortanix-unknown-sgx.tar.gz": "58daead170094bd8e8665893e34faf4d36a3c38f2b52afa4019bc505e758776c", + "dist/2021-12-02/rust-std-1.57.0-x86_64-fortanix-unknown-sgx.tar.xz": "a727e141b1a97374b9f5f061444e8676a2de7f2e35070489344f3d0835a9491c", + "dist/2021-12-02/rust-std-1.57.0-x86_64-fuchsia.tar.gz": "ad8a9604f32c053297e799b441dda4bd5877ca80bd52fbc6e2206fefaf712972", + "dist/2021-12-02/rust-std-1.57.0-x86_64-fuchsia.tar.xz": "8fa84dfb89a3a1296082d6151bb17c9612bbd77f48e17c96635e6833a4998181", + "dist/2021-12-02/rust-std-1.57.0-x86_64-linux-android.tar.gz": "6df583d2d3a4178ef33576d1a54f8c1015654ab2067027b730af2dfd4a4c0673", + "dist/2021-12-02/rust-std-1.57.0-x86_64-linux-android.tar.xz": "cae6f687655c98cd477ddad92afd09967bd4e900d79ee1507a9b44420015d4dd", + "dist/2021-12-02/rust-std-1.57.0-x86_64-pc-solaris.tar.gz": "fc24cd91eeafda198345daf072ce944c2ff8b834593edd3931ce8173cf78cc89", + "dist/2021-12-02/rust-std-1.57.0-x86_64-pc-solaris.tar.xz": "e43dc328232d527e81f9c040942c84405b791e3e8a260c2b9931a5809c37c247", + "dist/2021-12-02/rust-std-1.57.0-x86_64-pc-windows-gnu.tar.gz": "75c910899ed36a90b155e3a01c21b863000675867efc56f2b68c44edd4b7e18c", + "dist/2021-12-02/rust-std-1.57.0-x86_64-pc-windows-gnu.tar.xz": "478b3cd0ade0076998c72b84d2b74c6ec94b6ebbf37630bbd30803deb8651fc8", + "dist/2021-12-02/rust-std-1.57.0-x86_64-pc-windows-msvc.tar.gz": "c3984148c561297f804238f6f1e4dd06302c6b3465d3744074016bc23a9f078b", + "dist/2021-12-02/rust-std-1.57.0-x86_64-pc-windows-msvc.tar.xz": "f6a7512ed0bb31885c3b98ce195f2fa314e02cca71c6a3c1c5d1601d0f44df66", + "dist/2021-12-02/rust-std-1.57.0-x86_64-sun-solaris.tar.gz": "4f4ca11be9f93b8e02cc893b8d7471514e5f912839f78c527fbd8af75655ae44", + "dist/2021-12-02/rust-std-1.57.0-x86_64-sun-solaris.tar.xz": "8bebddb4e4c5fe216d12c8de0935e0e5d250a161b10eff95585975af032360c7", + "dist/2021-12-02/rust-std-1.57.0-x86_64-unknown-freebsd.tar.gz": "1528a4bc7e3ba42da164bcc7b952dfa73048333c5b9254ce2d03db6bab6081e8", + "dist/2021-12-02/rust-std-1.57.0-x86_64-unknown-freebsd.tar.xz": "d8279054e722e03794c2499c5ebb25e99df372f81e98dc986d62a76884baf422", + "dist/2021-12-02/rust-std-1.57.0-x86_64-unknown-illumos.tar.gz": "e979839efd104341fb07bd24a55632c08a8f2dddd8d2bb5a77ddd9d16bad27a4", + "dist/2021-12-02/rust-std-1.57.0-x86_64-unknown-illumos.tar.xz": "72125364192f1a1d1ac226f94fff593bb7d3418ee867d58f0fdd98a1fc18f8ea", + "dist/2021-12-02/rust-std-1.57.0-x86_64-unknown-linux-gnu.tar.gz": "9140ad6f46a903345d4297a987ccaf37b9c5ca594cd6fd5a27d0be482116fe7f", + "dist/2021-12-02/rust-std-1.57.0-x86_64-unknown-linux-gnu.tar.xz": "ccdc72d06c90841b7227ec3630337881eeda3da5fbe87328d2e9d705f6f8016c", + "dist/2021-12-02/rust-std-1.57.0-x86_64-unknown-linux-gnux32.tar.gz": "49368deaa5fa15b9fe6cd5edf0b6f1543ebee27647ee01990e3d550d20ebbd1a", + "dist/2021-12-02/rust-std-1.57.0-x86_64-unknown-linux-gnux32.tar.xz": "ab9ec3a431881a5721c5ad33848a5886c4479cf30ee70471546cc4f008fc3952", + "dist/2021-12-02/rust-std-1.57.0-x86_64-unknown-linux-musl.tar.gz": "e59345c7ba6bde5e1d2950b846c097511998d5897c63a7cea078ece4b8507f5b", + "dist/2021-12-02/rust-std-1.57.0-x86_64-unknown-linux-musl.tar.xz": "818213a6444503ed6adf0231d3c71de990d4c26926c62e8c602bb7e2d636fb94", + "dist/2021-12-02/rust-std-1.57.0-x86_64-unknown-netbsd.tar.gz": "a0ee6f716f2fd2903124f228240c2020524867558ca5af606d8730eab7c6148b", + "dist/2021-12-02/rust-std-1.57.0-x86_64-unknown-netbsd.tar.xz": "bfaf5271fb701ec9f28f555b98335bfe767f56e5f913c2c191fcc05ba5da3904", + "dist/2021-12-02/rust-std-1.57.0-x86_64-unknown-redox.tar.gz": "3cd9e3edfee39f24b7faf731ee0483dca40ea63d84eb8402ed8929302b9b3152", + "dist/2021-12-02/rust-std-1.57.0-x86_64-unknown-redox.tar.xz": "9983ee185f505c3ba81b63a0ab64596bd681b4d40471b1adbf57e513557541b1", + "dist/2021-12-02/rustc-1.57.0-aarch64-apple-darwin.tar.gz": "cfd28be33d8669c85dc177775de6c4aa94289bba7cc65b90cbd2d9cd5486c860", + "dist/2021-12-02/rustc-1.57.0-aarch64-apple-darwin.tar.xz": "edd8bcd6e75a0161a6f63fabafaa32d918b60b49b0eea34c560f3e12bf5b9c82", + "dist/2021-12-02/rustc-1.57.0-aarch64-pc-windows-msvc.tar.gz": "c0a31058e2f6854920fc676cd941635a2ef020ebfbefd1a137045bba9efe746f", + "dist/2021-12-02/rustc-1.57.0-aarch64-pc-windows-msvc.tar.xz": "dc30485ad50e3c6c28b5ee34b71169ddd8fff44a57355dbc13cff4217221101d", + "dist/2021-12-02/rustc-1.57.0-aarch64-unknown-linux-gnu.tar.gz": "91f1e29387fc53430592985b0620c8587e4aacc8ac582de4ef96c45c9ae930d4", + "dist/2021-12-02/rustc-1.57.0-aarch64-unknown-linux-gnu.tar.xz": "f26811e48d03c56c125de03d389e1ae7c6df36990953c1670c6a5676bc12d4cb", + "dist/2021-12-02/rustc-1.57.0-aarch64-unknown-linux-musl.tar.gz": "e5289c930ed72c08310108f543deafc319c27389523c6c6905fa35283e9ab725", + "dist/2021-12-02/rustc-1.57.0-aarch64-unknown-linux-musl.tar.xz": "28e78badf85819eed0099b7dd32a18c1d790f004f137f4df534ced59eaf3c9cd", + "dist/2021-12-02/rustc-1.57.0-arm-unknown-linux-gnueabi.tar.gz": "db328c9cff0d47e15c5fcdfd462d62433457a077a2e531a7b488c44572912f1e", + "dist/2021-12-02/rustc-1.57.0-arm-unknown-linux-gnueabi.tar.xz": "99a432a6d7f8b7ca963e100dbba1f11a561af2342aa6a3f457ccfeb65331198c", + "dist/2021-12-02/rustc-1.57.0-arm-unknown-linux-gnueabihf.tar.gz": "14ca5b876d92c1311be7cfbd38e25eb0945be98c9d8f2dd491702c3c4bb9d8c3", + "dist/2021-12-02/rustc-1.57.0-arm-unknown-linux-gnueabihf.tar.xz": "89d70adfecab36ed29a89024d064bc8cd277148733c25740a4dc965183c851f1", + "dist/2021-12-02/rustc-1.57.0-armv7-unknown-linux-gnueabihf.tar.gz": "f7293a081f9ad5afc45ef31e35fac1390705b6ad7b0aff7018fb6f1c2ff4cb5a", + "dist/2021-12-02/rustc-1.57.0-armv7-unknown-linux-gnueabihf.tar.xz": "7bced082d257b4e3c0548401b9b45b95b1d2c1343f69700558f2726024205a5c", + "dist/2021-12-02/rustc-1.57.0-i686-pc-windows-gnu.tar.gz": "636d2fb28290333f4202446e28212219c74e129e4b0097c822b5d13f5959468d", + "dist/2021-12-02/rustc-1.57.0-i686-pc-windows-gnu.tar.xz": "2bec8a429b1d0b7a408ff390df8ef57e52b2f29d3b6490bfe61f8d06409a88b0", + "dist/2021-12-02/rustc-1.57.0-i686-pc-windows-msvc.tar.gz": "9de242ba0a4ea36d0da6d80344082fdea48058a7410be450a1ae00aee72beed3", + "dist/2021-12-02/rustc-1.57.0-i686-pc-windows-msvc.tar.xz": "5d9a358399d47231ec69ae6a010051fc839a998a4cd0b5c305f6a24e0248a249", + "dist/2021-12-02/rustc-1.57.0-i686-unknown-linux-gnu.tar.gz": "356a12b32b951cdb71f34b5c75e7a32f331148bf3fae81106d3ed070fd598f93", + "dist/2021-12-02/rustc-1.57.0-i686-unknown-linux-gnu.tar.xz": "9bade3fcd246b0ad6859fcf5d0a80d3eb833e5410efa3a5552c241865562461e", + "dist/2021-12-02/rustc-1.57.0-mips-unknown-linux-gnu.tar.gz": "867c34ab51473ae359c61e1ef9bb77976bf8704d63c40901027445613a83de7b", + "dist/2021-12-02/rustc-1.57.0-mips-unknown-linux-gnu.tar.xz": "05f3784b21404438531a57e4ef258037c7404a5690dae09eeb8a831577da406b", + "dist/2021-12-02/rustc-1.57.0-mips64-unknown-linux-gnuabi64.tar.gz": "eaf93359f5cb62beca4e6b56ea7dc0d307c717043f69b688c34d435b5fd97a9a", + "dist/2021-12-02/rustc-1.57.0-mips64-unknown-linux-gnuabi64.tar.xz": "4254ed8cb6174815d815fd40b99bb1a6d0cd4bb6821de14c0f4c495ddc83b4ce", + "dist/2021-12-02/rustc-1.57.0-mips64el-unknown-linux-gnuabi64.tar.gz": "6e3a4a06da13635b7e206174928c4866c1abc47d63c2b3baa6b2292bedcdc2dc", + "dist/2021-12-02/rustc-1.57.0-mips64el-unknown-linux-gnuabi64.tar.xz": "fe99e2a589c786e71b0de91eee232e0131eea95b11898bc40bc0d919109201ac", + "dist/2021-12-02/rustc-1.57.0-mipsel-unknown-linux-gnu.tar.gz": "053f607bd8673958954279fb8dfefa8913075d921fd0e6ca8d10b7422a102316", + "dist/2021-12-02/rustc-1.57.0-mipsel-unknown-linux-gnu.tar.xz": "235d4118997cefe61798b9978cb2f0769a1c1a62138e3d06b4f30452e2444e8b", + "dist/2021-12-02/rustc-1.57.0-powerpc-unknown-linux-gnu.tar.gz": "5124e6bd5660a76e1b774b92420255b6b861183ab389ce0490553f2cf1f7b29a", + "dist/2021-12-02/rustc-1.57.0-powerpc-unknown-linux-gnu.tar.xz": "a1d7611b2d39224ba9a915009ae2a6639def42767370f50effd57770b3eb2150", + "dist/2021-12-02/rustc-1.57.0-powerpc64-unknown-linux-gnu.tar.gz": "125adb3abb4a7224f67bf58468a12e548a89c8bac56b42fb5885da6ff9a04a1a", + "dist/2021-12-02/rustc-1.57.0-powerpc64-unknown-linux-gnu.tar.xz": "da903d498146e0831e2982269e20b095d520a4a3b7dd40a22248e2336ec97c53", + "dist/2021-12-02/rustc-1.57.0-powerpc64le-unknown-linux-gnu.tar.gz": "348a1b74687c5f67105c26480c37a68b02346ca1dd08b885ca5c752a103155b1", + "dist/2021-12-02/rustc-1.57.0-powerpc64le-unknown-linux-gnu.tar.xz": "f43cb99109c3438c77c7079cdce4673df3320e310158e0b4d949c1babc4300fc", + "dist/2021-12-02/rustc-1.57.0-riscv64gc-unknown-linux-gnu.tar.gz": "f7665fef2c04189de9d3c7659efd9d49551289dac7a48d2343b895dc34d81d27", + "dist/2021-12-02/rustc-1.57.0-riscv64gc-unknown-linux-gnu.tar.xz": "0976cc48088979c27c2c94214a3d2cf558e67fd5470f99439369c4f053c34aaa", + "dist/2021-12-02/rustc-1.57.0-s390x-unknown-linux-gnu.tar.gz": "352ee9cdadddbb1a0c3e95429ddb75273baac03ddc8f79af5d98477c81b22560", + "dist/2021-12-02/rustc-1.57.0-s390x-unknown-linux-gnu.tar.xz": "6032b1ddc822c0a064ca2bf981164c3cafac947d148ae806373e4117884b43aa", + "dist/2021-12-02/rustc-1.57.0-x86_64-apple-darwin.tar.gz": "4417eea141bb915f39305cf2d812579f503422fa2e712eddf11427ce91c48294", + "dist/2021-12-02/rustc-1.57.0-x86_64-apple-darwin.tar.xz": "07d8a849bbe6f5e12946061d6dc007733b953c3c29f02c8393e1606136ea0c87", + "dist/2021-12-02/rustc-1.57.0-x86_64-pc-windows-gnu.tar.gz": "539c6515a9bbb0bcfad00a4956b68d418a10ef807fbb30f7dd2488f9155e4b3d", + "dist/2021-12-02/rustc-1.57.0-x86_64-pc-windows-gnu.tar.xz": "9234f3b39709a3a0bedd8df311947e283851fe1e6f7c1118b72dedfde05c7642", + "dist/2021-12-02/rustc-1.57.0-x86_64-pc-windows-msvc.tar.gz": "073bbc3f8f71fb20bf6c7bd2e4cf6e2758c8ee6f08d3eef51a615d5b5b8a516b", + "dist/2021-12-02/rustc-1.57.0-x86_64-pc-windows-msvc.tar.xz": "c2c163a386ff840fece2cb08bfcd7a8f962c114e719768dbcd3a6b6f44a4c458", + "dist/2021-12-02/rustc-1.57.0-x86_64-unknown-freebsd.tar.gz": "ef9af581c88b5d52f3b91f8781fbea77426364ac035bb7cb274f41fa3bf60706", + "dist/2021-12-02/rustc-1.57.0-x86_64-unknown-freebsd.tar.xz": "83a0431e38c40699d7ffae7729fead5a9f4a1193ed38bb6768f6b4ab14e8c34b", + "dist/2021-12-02/rustc-1.57.0-x86_64-unknown-illumos.tar.gz": "62b30e3cda4530e8fc07fb0dd9b1c58e314f7ebfb31f863455e4682d6941ef69", + "dist/2021-12-02/rustc-1.57.0-x86_64-unknown-illumos.tar.xz": "7ed262c5c4151caed07ea96d5ddd5cca4dc555b7439135d2e06f4f2c866f488d", + "dist/2021-12-02/rustc-1.57.0-x86_64-unknown-linux-gnu.tar.gz": "92257646cd85b7c03520c838920851c879845ed8dfd2b339d2ebb4480ee4d4d3", + "dist/2021-12-02/rustc-1.57.0-x86_64-unknown-linux-gnu.tar.xz": "c42f40c5279a3a9d539cae93dbcab9d333777ad9a60a5b9f1086b874ef63db86", + "dist/2021-12-02/rustc-1.57.0-x86_64-unknown-linux-musl.tar.gz": "49ff02cdc94bd8732c2969b06006773311c8e41c188a9cef627b37eefb0b73d7", + "dist/2021-12-02/rustc-1.57.0-x86_64-unknown-linux-musl.tar.xz": "5b04e0e0bbf140f7c49baa6280114c28f59f6de50481bdd45074eebf629c174c", + "dist/2021-12-02/rustc-1.57.0-x86_64-unknown-netbsd.tar.gz": "cd39b7c7a8880a2d1ee67a5366cb4999dc9a9d28cbed3a0a003f468cb15ef1c1", + "dist/2021-12-02/rustc-1.57.0-x86_64-unknown-netbsd.tar.xz": "a6720d4b5340801c23bf021e514133ac0882a1830484e7d78e469e292622144a" } } diff --git a/src/test/assembly/asm/aarch64-modifiers.rs b/src/test/assembly/asm/aarch64-modifiers.rs index d4a44b1739..5196aa9fa1 100644 --- a/src/test/assembly/asm/aarch64-modifiers.rs +++ b/src/test/assembly/asm/aarch64-modifiers.rs @@ -1,4 +1,3 @@ -// 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-outline-atomics.rs b/src/test/assembly/asm/aarch64-outline-atomics.rs index 42cef9bb67..c2ec4e911b 100644 --- a/src/test/assembly/asm/aarch64-outline-atomics.rs +++ b/src/test/assembly/asm/aarch64-outline-atomics.rs @@ -1,4 +1,3 @@ -// min-llvm-version: 12.0 // 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 aa25562d32..04b5f4aed9 100644 --- a/src/test/assembly/asm/aarch64-types.rs +++ b/src/test/assembly/asm/aarch64-types.rs @@ -1,9 +1,8 @@ -// min-llvm-version: 10.0.1 // assembly-output: emit-asm // compile-flags: --target aarch64-unknown-linux-gnu // needs-llvm-components: aarch64 -#![feature(no_core, lang_items, rustc_attrs, repr_simd)] +#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] diff --git a/src/test/assembly/asm/arm-modifiers.rs b/src/test/assembly/asm/arm-modifiers.rs index bb6cc1c987..a6985a3bf5 100644 --- a/src/test/assembly/asm/arm-modifiers.rs +++ b/src/test/assembly/asm/arm-modifiers.rs @@ -1,4 +1,3 @@ -// 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 b16fde571a..0c57b1fc47 100644 --- a/src/test/assembly/asm/arm-types.rs +++ b/src/test/assembly/asm/arm-types.rs @@ -1,10 +1,9 @@ -// min-llvm-version: 10.0.1 // assembly-output: emit-asm // compile-flags: --target armv7-unknown-linux-gnueabihf // compile-flags: -C target-feature=+neon // needs-llvm-components: arm -#![feature(no_core, lang_items, rustc_attrs, repr_simd)] +#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] diff --git a/src/test/assembly/asm/bpf-types.rs b/src/test/assembly/asm/bpf-types.rs index 7271ef1128..3428d93fb1 100644 --- a/src/test/assembly/asm/bpf-types.rs +++ b/src/test/assembly/asm/bpf-types.rs @@ -3,7 +3,7 @@ // compile-flags: --target bpfel-unknown-none -C target_feature=+alu32 // needs-llvm-components: bpf -#![feature(no_core, lang_items, rustc_attrs, repr_simd)] +#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym, asm_experimental_arch)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] diff --git a/src/test/assembly/asm/global_asm.rs b/src/test/assembly/asm/global_asm.rs index 3a7f2fa1ef..7e48c386ab 100644 --- a/src/test/assembly/asm/global_asm.rs +++ b/src/test/assembly/asm/global_asm.rs @@ -1,9 +1,8 @@ -// min-llvm-version: 10.0.1 // only-x86_64 // assembly-output: emit-asm // compile-flags: -C llvm-args=--x86-asm-syntax=intel -#![feature(asm, global_asm)] +#![feature(global_asm, asm_const)] #![crate_type = "rlib"] // CHECK: mov eax, eax diff --git a/src/test/assembly/asm/hexagon-types.rs b/src/test/assembly/asm/hexagon-types.rs index 40352cdb4c..de310c7848 100644 --- a/src/test/assembly/asm/hexagon-types.rs +++ b/src/test/assembly/asm/hexagon-types.rs @@ -1,9 +1,8 @@ -// min-llvm-version: 10.0.1 // assembly-output: emit-asm // compile-flags: --target hexagon-unknown-linux-musl // needs-llvm-components: hexagon -#![feature(no_core, lang_items, rustc_attrs, repr_simd)] +#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym, asm_experimental_arch)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] diff --git a/src/test/assembly/asm/mips-types.rs b/src/test/assembly/asm/mips-types.rs index 9ec7ba83c4..04bf49a40e 100644 --- a/src/test/assembly/asm/mips-types.rs +++ b/src/test/assembly/asm/mips-types.rs @@ -1,4 +1,3 @@ -// min-llvm-version: 10.0.1 // revisions: mips32 mips64 // assembly-output: emit-asm //[mips32] compile-flags: --target mips-unknown-linux-gnu @@ -6,7 +5,7 @@ //[mips64] compile-flags: --target mips64-unknown-linux-gnuabi64 //[mips64] needs-llvm-components: mips -#![feature(no_core, lang_items, rustc_attrs, repr_simd)] +#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym, asm_experimental_arch)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] diff --git a/src/test/assembly/asm/nvptx-types.rs b/src/test/assembly/asm/nvptx-types.rs index 75b6371fb7..3ebd5b4b89 100644 --- a/src/test/assembly/asm/nvptx-types.rs +++ b/src/test/assembly/asm/nvptx-types.rs @@ -1,10 +1,9 @@ -// min-llvm-version: 10.0.1 // assembly-output: emit-asm // compile-flags: --target nvptx64-nvidia-cuda // compile-flags: --crate-type cdylib // needs-llvm-components: nvptx -#![feature(no_core, lang_items, rustc_attrs)] +#![feature(no_core, lang_items, rustc_attrs, asm_sym, asm_experimental_arch)] #![no_core] #[rustc_builtin_macro] diff --git a/src/test/assembly/asm/powerpc-types.rs b/src/test/assembly/asm/powerpc-types.rs index 55ca8ee836..b8859c07e1 100644 --- a/src/test/assembly/asm/powerpc-types.rs +++ b/src/test/assembly/asm/powerpc-types.rs @@ -1,4 +1,4 @@ -// min-llvm-version: 10.0.1 +// min-llvm-version: 12.0.1 // revisions: powerpc powerpc64 // assembly-output: emit-asm //[powerpc] compile-flags: --target powerpc-unknown-linux-gnu @@ -6,7 +6,7 @@ //[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu //[powerpc64] needs-llvm-components: powerpc -#![feature(no_core, lang_items, rustc_attrs, repr_simd)] +#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym, asm_experimental_arch)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] diff --git a/src/test/assembly/asm/riscv-types.rs b/src/test/assembly/asm/riscv-types.rs index e62a6197b9..0f9f61bd6d 100644 --- a/src/test/assembly/asm/riscv-types.rs +++ b/src/test/assembly/asm/riscv-types.rs @@ -1,4 +1,3 @@ -// min-llvm-version: 10.0.1 // revisions: riscv64 riscv32 // assembly-output: emit-asm //[riscv64] compile-flags: --target riscv64imac-unknown-none-elf @@ -6,9 +5,8 @@ //[riscv32] compile-flags: --target riscv32imac-unknown-none-elf //[riscv32] needs-llvm-components: riscv // compile-flags: -C target-feature=+d -// min-system-llvm-version: 12.0 -#![feature(no_core, lang_items, rustc_attrs)] +#![feature(no_core, lang_items, rustc_attrs, asm_sym)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register)] diff --git a/src/test/assembly/asm/s390x-types.rs b/src/test/assembly/asm/s390x-types.rs index 69d9cab23c..6a12902a04 100644 --- a/src/test/assembly/asm/s390x-types.rs +++ b/src/test/assembly/asm/s390x-types.rs @@ -1,10 +1,9 @@ -// min-llvm-version: 10.0.1 // revisions: s390x // assembly-output: emit-asm //[s390x] compile-flags: --target s390x-unknown-linux-gnu //[s390x] needs-llvm-components: systemz -#![feature(no_core, lang_items, rustc_attrs, repr_simd)] +#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym, asm_experimental_arch)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] diff --git a/src/test/assembly/asm/wasm-types.rs b/src/test/assembly/asm/wasm-types.rs index a071a850c2..3aa128c46a 100644 --- a/src/test/assembly/asm/wasm-types.rs +++ b/src/test/assembly/asm/wasm-types.rs @@ -1,10 +1,9 @@ -// min-llvm-version: 10.0.1 // assembly-output: emit-asm // compile-flags: --target wasm32-unknown-unknown // compile-flags: --crate-type cdylib // needs-llvm-components: webassembly -#![feature(no_core, lang_items, rustc_attrs)] +#![feature(no_core, lang_items, rustc_attrs, asm_sym, asm_experimental_arch)] #![no_core] #[rustc_builtin_macro] diff --git a/src/test/assembly/asm/x86-modifiers.rs b/src/test/assembly/asm/x86-modifiers.rs index c926fd7b3f..574fdf12cd 100644 --- a/src/test/assembly/asm/x86-modifiers.rs +++ b/src/test/assembly/asm/x86-modifiers.rs @@ -1,4 +1,3 @@ -// 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 d25f3a0377..e871535cfd 100644 --- a/src/test/assembly/asm/x86-types.rs +++ b/src/test/assembly/asm/x86-types.rs @@ -1,4 +1,3 @@ -// min-llvm-version: 10.0.1 // revisions: x86_64 i686 // assembly-output: emit-asm //[x86_64] compile-flags: --target x86_64-unknown-linux-gnu @@ -8,7 +7,7 @@ // compile-flags: -C llvm-args=--x86-asm-syntax=intel // compile-flags: -C target-feature=+avx512bw -#![feature(no_core, lang_items, rustc_attrs, repr_simd)] +#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] diff --git a/src/test/assembly/stack-protector/stack-protector-heuristics-effect.rs b/src/test/assembly/stack-protector/stack-protector-heuristics-effect.rs new file mode 100644 index 0000000000..530326ab74 --- /dev/null +++ b/src/test/assembly/stack-protector/stack-protector-heuristics-effect.rs @@ -0,0 +1,396 @@ +// revisions: all strong basic none missing +// assembly-output: emit-asm +// ignore-macos slightly different policy on stack protection of arrays +// ignore-windows stack check code uses different function names +// ignore-nvptx64 stack protector is not supported +// [all] compile-flags: -Z stack-protector=all +// [strong] compile-flags: -Z stack-protector=strong +// [basic] compile-flags: -Z stack-protector=basic +// [none] compile-flags: -Z stack-protector=none +// compile-flags: -C opt-level=2 -Z merge-functions=disabled + +#![crate_type = "lib"] + +#![allow(incomplete_features)] + +#![feature(unsized_locals, unsized_fn_params)] + + +// CHECK-LABEL: emptyfn: +#[no_mangle] +pub fn emptyfn() { + // all: __stack_chk_fail + // strong-NOT: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +// CHECK-LABEL: array_char +#[no_mangle] +pub fn array_char(f: fn(*const char)) { + let a = ['c'; 1]; + let b = ['d'; 3]; + let c = ['e'; 15]; + + f(&a as *const _); + f(&b as *const _); + f(&c as *const _); + + // Any type of local array variable leads to stack protection with the + // "strong" heuristic. The 'basic' heuristic only adds stack protection to + // functions with local array variables of a byte-sized type, however. Since + // 'char' is 4 bytes in Rust, this function is not protected by the 'basic' + // heuristic + // + // (This test *also* takes the address of the local stack variables. We + // cannot know that this isn't what triggers the `strong` heuristic. + // However, the test strategy of passing the address of a stack array to an + // external function is sufficient to trigger the `basic` heuristic (see + // test `array_u8_large()`). Since the `basic` heuristic only checks for the + // presence of stack-local array variables, we can be confident that this + // test also captures this part of the `strong` heuristic specification.) + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +// CHECK-LABEL: array_u8_1 +#[no_mangle] +pub fn array_u8_1(f: fn(*const u8)) { + let a = [0u8; 1]; + f(&a as *const _); + + // The 'strong' heuristic adds stack protection to functions with local + // array variables regardless of their size. + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +// CHECK-LABEL: array_u8_small: +#[no_mangle] +pub fn array_u8_small(f: fn(*const u8)) { + let a = [0u8; 2]; + let b = [0u8; 8]; + f(&a as *const _); + f(&b as *const _); + + // Small arrays do not lead to stack protection by the 'basic' heuristic. + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +// CHECK-LABEL: array_u8_large: +#[no_mangle] +pub fn array_u8_large(f: fn(*const u8)) { + let a = [0u8; 9]; + f(&a as *const _); + + // Since `a` is a byte array with size greater than 8, the basic heuristic + // will also protect this function. + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +#[derive(Copy, Clone)] +pub struct ByteSizedNewtype(u8); + +// CHECK-LABEL: array_bytesizednewtype_9: +#[no_mangle] +pub fn array_bytesizednewtype_9(f: fn(*const ByteSizedNewtype)) { + let a = [ByteSizedNewtype(0); 9]; + f(&a as *const _); + + // Since `a` is a byte array in the LLVM output, the basic heuristic will + // also protect this function. + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +// CHECK-LABEL: local_var_addr_used_indirectly +#[no_mangle] +pub fn local_var_addr_used_indirectly(f: fn(bool)) { + let a = 5; + let a_addr = &a as *const _ as usize; + f(a_addr & 0x10 == 0); + + // This function takes the address of a local variable taken. Although this + // address is never used as a way to refer to stack memory, the `strong` + // heuristic adds stack smash protection. This is also the case in C++: + // ``` + // cat << EOF | clang++ -O2 -fstack-protector-strong -S -x c++ - -o - | grep stack_chk + // #include + // void f(void (*g)(bool)) { + // int32_t x; + // g((reinterpret_cast(&x) & 0x10U) == 0); + // } + // EOF + // ``` + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + + +// CHECK-LABEL: local_string_addr_taken +#[no_mangle] +pub fn local_string_addr_taken(f: fn(&String)) { + let x = String::new(); + f(&x); + + // Taking the address of the local variable `x` leads to stack smash + // protection with the `strong` heuristic, but not with the `basic` + // heuristic. It does not matter that the reference is not mut. + // + // An interesting note is that a similar function in C++ *would* be + // protected by the `basic` heuristic, because `std::string` has a char + // array internally as a small object optimization: + // ``` + // cat < + // void f(void (*g)(const std::string&)) { + // std::string x; + // g(x); + // } + // EOF + // ``` + // + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +pub trait SelfByRef { + fn f(&self) -> i32; +} + +impl SelfByRef for i32 { + fn f(&self) -> i32 { + return self + 1; + } +} + +// CHECK-LABEL: local_var_addr_taken_used_locally_only +#[no_mangle] +pub fn local_var_addr_taken_used_locally_only(factory: fn() -> i32, sink: fn(i32)) { + let x = factory(); + let g = x.f(); + sink(g); + + // Even though the local variable conceptually has its address taken, as + // it's passed by reference to the trait function, the use of the reference + // is easily inlined. There is therefore no stack smash protection even with + // the `strong` heuristic. + + // all: __stack_chk_fail + // strong-NOT: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +pub struct Gigastruct { + does: u64, + not: u64, + have: u64, + array: u64, + members: u64 +} + +// CHECK-LABEL: local_large_var_moved +#[no_mangle] +pub fn local_large_var_moved(f: fn(Gigastruct)) { + let x = Gigastruct { does: 0, not: 1, have: 2, array: 3, members: 4 }; + f(x); + + // Even though the local variable conceptually doesn't have its address + // taken, it's so large that the "move" is implemented with a reference to a + // stack-local variable in the ABI. Consequently, this function *is* + // protected by the `strong` heuristic. This is also the case for + // rvalue-references in C++, regardless of struct size: + // ``` + // cat < + // #include + // void f(void (*g)(uint64_t&&)) { + // uint64_t x; + // g(std::move(x)); + // } + // EOF + // ``` + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +// CHECK-LABEL: local_large_var_cloned +#[no_mangle] +pub fn local_large_var_cloned(f: fn(Gigastruct)) { + f(Gigastruct { does: 0, not: 1, have: 2, array: 3, members: 4 }); + + // A new instance of `Gigastruct` is passed to `f()`, without any apparent + // connection to this stack frame. Still, since instances of `Gigastruct` + // are sufficiently large, it is allocated in the caller stack frame and + // passed as a pointer. As such, this function is *also* protected by the + // `strong` heuristic, just like `local_large_var_moved`. This is also the + // case for pass-by-value of sufficiently large structs in C++: + // ``` + // cat < + // #include + // struct Gigastruct { uint64_t a, b, c, d, e; }; + // void f(void (*g)(Gigastruct)) { + // g(Gigastruct{}); + // } + // EOF + // ``` + + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + + +extern "C" { + // A call to an external `alloca` function is *not* recognized as an + // `alloca(3)` operation. This function is a compiler built-in, as the + // man page explains. Clang translates it to an LLVM `alloca` + // instruction with a count argument, which is also what the LLVM stack + // protector heuristics looks for. The man page for `alloca(3)` details + // a way to avoid using the compiler built-in: pass a -std=c11 + // argument, *and* don't include . Though this leads to an + // external alloca() function being called, it doesn't lead to stack + // protection being included. It even fails with a linker error + // "undefined reference to `alloca'". Example: + // ``` + // cat< + // void * alloca(size_t); + // void f(void (*g)(void*)) { + // void * p = alloca(10); + // g(p); + // } + // int main() { return 0; } + // EOF + // ``` + // The following tests demonstrate that calls to an external `alloca` + // function in Rust also doesn't trigger stack protection. + + fn alloca(size: usize) -> *mut (); +} + +// CHECK-LABEL: alloca_small_compile_time_constant_arg +#[no_mangle] +pub fn alloca_small_compile_time_constant_arg(f: fn(*mut ())) { + f(unsafe { alloca(8) }); + + // all: __stack_chk_fail + // strong-NOT: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +// CHECK-LABEL: alloca_large_compile_time_constant_arg +#[no_mangle] +pub fn alloca_large_compile_time_constant_arg(f: fn(*mut ())) { + f(unsafe { alloca(9) }); + + // all: __stack_chk_fail + // strong-NOT: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + + +// CHECK-LABEL: alloca_dynamic_arg +#[no_mangle] +pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) { + f(unsafe { alloca(n) }); + + // all: __stack_chk_fail + // strong-NOT: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +// The question then is: in what ways can Rust code generate array-`alloca` +// LLVM instructions? This appears to only be generated by +// rustc_codegen_ssa::traits::Builder::array_alloca() through +// rustc_codegen_ssa::mir::operand::OperandValue::store_unsized(). FWICT +// this is support for the "unsized locals" unstable feature: +// https://doc.rust-lang.org/unstable-book/language-features/unsized-locals.html. + + +// CHECK-LABEL: unsized_fn_param +#[no_mangle] +pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) { + let n = if l { 1 } else { 2 }; + f(*Box::<[u8]>::from(&s[0..n])); // slice-copy with Box::from + + // Even though slices are conceptually passed by-value both into this + // function and into `f()`, this is implemented with pass-by-reference + // using a suitably constructed fat-pointer (as if the functions + // accepted &[u8]). This function therefore doesn't need dynamic array + // alloca, and is therefore not protected by the `strong` or `basic` + // heuristics. + + + // all: __stack_chk_fail + // strong-NOT: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +// CHECK-LABEL: unsized_local +#[no_mangle] +pub fn unsized_local(s: &[u8], l: bool, f: fn(&mut [u8])) { + let n = if l { 1 } else { 2 }; + let mut a: [u8] = *Box::<[u8]>::from(&s[0..n]); // slice-copy with Box::from + f(&mut a); + + // This function allocates a slice as a local variable in its stack + // frame. Since the size is not a compile-time constant, an array + // alloca is required, and the function is protected by both the + // `strong` and `basic` heuristic. + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} diff --git a/src/test/assembly/stack-protector/stack-protector-target-support.rs b/src/test/assembly/stack-protector/stack-protector-target-support.rs new file mode 100644 index 0000000000..5ba46d082e --- /dev/null +++ b/src/test/assembly/stack-protector/stack-protector-target-support.rs @@ -0,0 +1,286 @@ +// Test that stack smash protection code is emitted for all tier1 and tier2 +// targets, with the exception of nvptx64-nvidia-cuda +// +// revisions: r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15 r16 r17 r18 r19 r20 r21 r22 r23 +// revisions: r24 r25 r26 r27 r28 r29 r30 r31 r32 r33 r34 r35 r36 r37 r38 r39 r40 r41 r42 r43 r44 +// revisions: r45 r46 r47 r48 r49 r50 r51 r52 r53 r54 r55 r56 r57 r58 r59 r60 r61 r62 r63 r64 r65 +// revisions: r66 r67 r68 r69 r70 r71 r72 r73 r74 r75 r76 r77 r78 r79 r80 r81 r82 r83 r84 +// assembly-output: emit-asm +// [r1] compile-flags: --target aarch64-unknown-linux-gnu +// [r1] needs-llvm-components: aarch64 +// [r2] compile-flags: --target i686-pc-windows-gnu +// [r2] needs-llvm-components: x86 +// [r3] compile-flags: --target i686-pc-windows-msvc +// [r3] needs-llvm-components: x86 +// [r4] compile-flags: --target i686-unknown-linux-gnu +// [r4] needs-llvm-components: x86 +// [r5] compile-flags: --target x86_64-apple-darwin +// [r5] needs-llvm-components: x86 +// [r6] compile-flags: --target x86_64-pc-windows-gnu +// [r6] needs-llvm-components: x86 +// [r7] compile-flags: --target x86_64-pc-windows-msvc +// [r7] needs-llvm-components: x86 +// [r8] compile-flags: --target x86_64-unknown-linux-gnu +// [r8] needs-llvm-components: x86 +// [r9] compile-flags: --target aarch64-apple-darwin +// [r9] needs-llvm-components: aarch64 +// [r10] compile-flags: --target aarch64-apple-ios +// [r10] needs-llvm-components: aarch64 +// [r11] compile-flags: --target aarch64-fuchsia +// [r11] needs-llvm-components: aarch64 +// [r12] compile-flags: --target aarch64-linux-android +// [r12] needs-llvm-components: aarch64 +// [r13] compile-flags: --target aarch64-pc-windows-msvc +// [r13] needs-llvm-components: aarch64 +// [r14] compile-flags: --target aarch64-unknown-linux-musl +// [r14] needs-llvm-components: aarch64 +// [r15] compile-flags: --target aarch64-unknown-none +// [r15] needs-llvm-components: aarch64 +// [r16] compile-flags: --target aarch64-unknown-none-softfloat +// [r16] needs-llvm-components: aarch64 +// [r17] compile-flags: --target arm-linux-androideabi +// [r17] needs-llvm-components: arm +// [r18] compile-flags: --target arm-unknown-linux-gnueabi +// [r18] needs-llvm-components: arm +// [r19] compile-flags: --target arm-unknown-linux-gnueabihf +// [r19] needs-llvm-components: arm +// [r20] compile-flags: --target arm-unknown-linux-musleabi +// [r20] needs-llvm-components: arm +// [r21] compile-flags: --target arm-unknown-linux-musleabihf +// [r21] needs-llvm-components: arm +// [r22] compile-flags: --target armebv7r-none-eabi +// [r22] needs-llvm-components: arm +// [r23] compile-flags: --target armebv7r-none-eabihf +// [r23] needs-llvm-components: arm +// [r24] compile-flags: --target armv5te-unknown-linux-gnueabi +// [r24] needs-llvm-components: arm +// [r25] compile-flags: --target armv5te-unknown-linux-musleabi +// [r25] needs-llvm-components: arm +// [r26] compile-flags: --target armv7-linux-androideabi +// [r26] needs-llvm-components: arm +// [r27] compile-flags: --target armv7a-none-eabi +// [r27] needs-llvm-components: arm +// [r28] compile-flags: --target armv7r-none-eabi +// [r28] needs-llvm-components: arm +// [r29] compile-flags: --target armv7r-none-eabihf +// [r29] needs-llvm-components: arm +// [r30] compile-flags: --target armv7-unknown-linux-gnueabi +// [r30] needs-llvm-components: arm +// [r31] compile-flags: --target armv7-unknown-linux-gnueabihf +// [r31] needs-llvm-components: arm +// [r32] compile-flags: --target armv7-unknown-linux-musleabi +// [r32] needs-llvm-components: arm +// [r33] compile-flags: --target armv7-unknown-linux-musleabihf +// [r33] needs-llvm-components: arm +// [r34] compile-flags: --target asmjs-unknown-emscripten +// [r34] needs-llvm-components: webassembly +// [r35] compile-flags: --target i586-pc-windows-msvc +// [r35] needs-llvm-components: x86 +// [r36] compile-flags: --target i586-unknown-linux-gnu +// [r36] needs-llvm-components: x86 +// [r37] compile-flags: --target i586-unknown-linux-musl +// [r37] needs-llvm-components: x86 +// [r38] compile-flags: --target i686-linux-android +// [r38] needs-llvm-components: x86 +// [r39] compile-flags: --target i686-unknown-freebsd +// [r39] needs-llvm-components: x86 +// [r40] compile-flags: --target i686-unknown-linux-musl +// [r40] needs-llvm-components: x86 +// [r41] compile-flags: --target mips-unknown-linux-gnu +// [r41] needs-llvm-components: mips +// [r42] compile-flags: --target mips-unknown-linux-musl +// [r42] needs-llvm-components: mips +// [r43] compile-flags: --target mips64-unknown-linux-gnuabi64 +// [r43] needs-llvm-components: mips +// [r44] compile-flags: --target mips64-unknown-linux-muslabi64 +// [r44] needs-llvm-components: mips +// [r45] compile-flags: --target mips64el-unknown-linux-gnuabi64 +// [r45] needs-llvm-components: mips +// [r46] compile-flags: --target mips64el-unknown-linux-muslabi64 +// [r46] needs-llvm-components: mips +// [r47] compile-flags: --target mipsel-unknown-linux-gnu +// [r47] needs-llvm-components: mips +// [r48] compile-flags: --target mipsel-unknown-linux-musl +// [r48] needs-llvm-components: mips +// [r49] compile-flags: --target nvptx64-nvidia-cuda +// [r49] needs-llvm-components: nvptx +// [r50] compile-flags: --target powerpc-unknown-linux-gnu +// [r50] needs-llvm-components: powerpc +// [r51] compile-flags: --target powerpc64-unknown-linux-gnu +// [r51] needs-llvm-components: powerpc +// [r52] compile-flags: --target powerpc64le-unknown-linux-gnu +// [r52] needs-llvm-components: powerpc +// [r53] compile-flags: --target riscv32i-unknown-none-elf +// [r53] needs-llvm-components: riscv +// [r54] compile-flags: --target riscv32imac-unknown-none-elf +// [r54] needs-llvm-components: riscv +// [r55] compile-flags:--target riscv32imc-unknown-none-elf +// [r55] needs-llvm-components: riscv +// [r56] compile-flags:--target riscv64gc-unknown-linux-gnu +// [r56] needs-llvm-components: riscv +// [r57] compile-flags:--target riscv64gc-unknown-none-elf +// [r57] needs-llvm-components: riscv +// [r58] compile-flags:--target riscv64imac-unknown-none-elf +// [r58] needs-llvm-components: riscv +// [r59] compile-flags:--target s390x-unknown-linux-gnu +// [r59] needs-llvm-components: systemz +// [r60] compile-flags:--target sparc64-unknown-linux-gnu +// [r60] needs-llvm-components: sparc +// [r61] compile-flags:--target sparcv9-sun-solaris +// [r61] needs-llvm-components: sparc +// [r62] compile-flags:--target thumbv6m-none-eabi +// [r62] needs-llvm-components: arm +// [r63] compile-flags:--target thumbv7em-none-eabi +// [r63] needs-llvm-components: arm +// [r64] compile-flags:--target thumbv7em-none-eabihf +// [r64] needs-llvm-components: arm +// [r65] compile-flags:--target thumbv7m-none-eabi +// [r65] needs-llvm-components: arm +// [r66] compile-flags:--target thumbv7neon-linux-androideabi +// [r66] needs-llvm-components: arm +// [r67] compile-flags:--target thumbv7neon-unknown-linux-gnueabihf +// [r67] needs-llvm-components: arm +// [r68] compile-flags:--target thumbv8m.base-none-eabi +// [r68] needs-llvm-components: arm +// [r69] compile-flags:--target thumbv8m.main-none-eabi +// [r69] needs-llvm-components: arm +// [r70] compile-flags:--target thumbv8m.main-none-eabihf +// [r70] needs-llvm-components: arm +// [r71] compile-flags:--target wasm32-unknown-emscripten +// [r71] needs-llvm-components: webassembly +// [r72] compile-flags:--target wasm32-unknown-unknown +// [r72] needs-llvm-components: webassembly +// [r73] compile-flags:--target wasm32-wasi +// [r73] needs-llvm-components: webassembly +// [r74] compile-flags:--target x86_64-apple-ios +// [r74] needs-llvm-components: x86 +// [r75] compile-flags:--target x86_64-fortanix-unknown-sgx +// [r75] needs-llvm-components: x86 +// [r75] min-llvm-version: 11.0.0 +// [r76] compile-flags:--target x86_64-fuchsia +// [r76] needs-llvm-components: x86 +// [r77] compile-flags:--target x86_64-linux-android +// [r77] needs-llvm-components: x86 +// [r78] compile-flags:--target x86_64-sun-solaris +// [r78] needs-llvm-components: x86 +// [r79] compile-flags:--target x86_64-unknown-freebsd +// [r79] needs-llvm-components: x86 +// [r80] compile-flags:--target x86_64-unknown-illumos +// [r80] needs-llvm-components: x86 +// [r81] compile-flags:--target x86_64-unknown-linux-gnux32 +// [r81] needs-llvm-components: x86 +// [r82] compile-flags:--target x86_64-unknown-linux-musl +// [r82] needs-llvm-components: x86 +// [r83] compile-flags:--target x86_64-unknown-netbsd +// [r83] needs-llvm-components: x86 +// [r84] compile-flags: --target x86_64-unknown-redox +// [r84] needs-llvm-components: x86 +// compile-flags: -Z stack-protector=all +// compile-flags: -C opt-level=2 + +#![crate_type = "lib"] + +#![feature(no_core, lang_items)] +#![crate_type = "lib"] +#![no_core] + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +#[no_mangle] +pub fn foo() { + // CHECK: foo{{:|()}} + + // MSVC does the stack checking within a stack-check function: + // r3: calll @__security_check_cookie + // r7: callq __security_check_cookie + // r13: bl __security_check_cookie + // r35: calll @__security_check_cookie + + // cuda doesn't support stack-smash protection + // r49-NOT: __security_check_cookie + // r49-NOT: __stack_chk_fail + + // Other targets do stack checking within the function, and call a failure function on error + // r1: __stack_chk_fail + // r2: __stack_chk_fail + // r4: __stack_chk_fail + // r5: __stack_chk_fail + // r6: __stack_chk_fail + // r8: __stack_chk_fail + // r9: __stack_chk_fail + // r10: __stack_chk_fail + // r11: __stack_chk_fail + // r12: __stack_chk_fail + // r14: __stack_chk_fail + // r15: __stack_chk_fail + // r16: __stack_chk_fail + // r17: __stack_chk_fail + // r18: __stack_chk_fail + // r19: __stack_chk_fail + // r20: __stack_chk_fail + // r21: __stack_chk_fail + // r22: __stack_chk_fail + // r23: __stack_chk_fail + // r24: __stack_chk_fail + // r25: __stack_chk_fail + // r26: __stack_chk_fail + // r27: __stack_chk_fail + // r28: __stack_chk_fail + // r29: __stack_chk_fail + // r30: __stack_chk_fail + // r31: __stack_chk_fail + // r32: __stack_chk_fail + // r33: __stack_chk_fail + // r34: __stack_chk_fail + // r36: __stack_chk_fail + // r37: __stack_chk_fail + // r38: __stack_chk_fail + // r39: __stack_chk_fail + // r40: __stack_chk_fail + // r41: __stack_chk_fail + // r42: __stack_chk_fail + // r43: __stack_chk_fail + // r44: __stack_chk_fail + // r45: __stack_chk_fail + // r46: __stack_chk_fail + // r47: __stack_chk_fail + // r48: __stack_chk_fail + // r50: __stack_chk_fail + // r51: __stack_chk_fail + // r52: __stack_chk_fail + // r53: __stack_chk_fail + // r54: __stack_chk_fail + // r55: __stack_chk_fail + // r56: __stack_chk_fail + // r57: __stack_chk_fail + // r58: __stack_chk_fail + // r59: __stack_chk_fail + // r60: __stack_chk_fail + // r61: __stack_chk_fail + // r62: __stack_chk_fail + // r63: __stack_chk_fail + // r64: __stack_chk_fail + // r65: __stack_chk_fail + // r66: __stack_chk_fail + // r67: __stack_chk_fail + // r68: __stack_chk_fail + // r69: __stack_chk_fail + // r70: __stack_chk_fail + // r71: __stack_chk_fail + // r72: __stack_chk_fail + // r73: __stack_chk_fail + // r74: __stack_chk_fail + // r75: __stack_chk_fail + // r76: __stack_chk_fail + // r77: __stack_chk_fail + // r78: __stack_chk_fail + // r79: __stack_chk_fail + // r80: __stack_chk_fail + // r81: __stack_chk_fail + // r82: __stack_chk_fail + // r83: __stack_chk_fail + // r84: __stack_chk_fail +} diff --git a/src/test/assembly/static-relocation-model.rs b/src/test/assembly/static-relocation-model.rs index b331d45668..6c41e0b78f 100644 --- a/src/test/assembly/static-relocation-model.rs +++ b/src/test/assembly/static-relocation-model.rs @@ -1,4 +1,3 @@ -// min-llvm-version: 12.0.0 // revisions: x64 A64 ppc64le // assembly-output: emit-asm // [x64] compile-flags: --target x86_64-unknown-linux-gnu -Crelocation-model=static diff --git a/src/test/codegen-units/item-collection/implicit-panic-call.rs b/src/test/codegen-units/item-collection/implicit-panic-call.rs new file mode 100644 index 0000000000..abec7ad50a --- /dev/null +++ b/src/test/codegen-units/item-collection/implicit-panic-call.rs @@ -0,0 +1,58 @@ +// compile-flags:-Zprint-mono-items=lazy + +// rust-lang/rust#90405 +// Ensure implicit panic calls are collected + +#![feature(lang_items)] +#![feature(no_core)] +#![crate_type = "lib"] +#![no_core] +#![no_std] + +#[lang = "panic_location"] +struct Location<'a> { + _file: &'a str, + _line: u32, + _col: u32, +} + +#[lang = "panic"] +#[inline] +#[track_caller] +fn panic(_: &'static str) -> ! { + loop {} +} + +#[lang = "sized"] +trait Sized {} + +#[lang = "copy"] +trait Copy {} + +#[lang = "freeze"] +trait Freeze {} + +impl Copy for i32 {} + +#[lang = "div"] +trait Div { + type Output; + fn div(self, rhs: Rhs) -> Self::Output; +} + +impl Div for i32 { + type Output = i32; + fn div(self, rhs: i32) -> i32 { + self / rhs + } +} + +#[allow(unconditional_panic)] +pub fn foo() { + // This implicitly generates a panic call. + let _ = 1 / 0; +} + +//~ MONO_ITEM fn foo +//~ MONO_ITEM fn ::div +//~ MONO_ITEM fn panic diff --git a/src/test/codegen/alloc-optimisation.rs b/src/test/codegen/alloc-optimisation.rs index aee93b93e3..c3ffaeb954 100644 --- a/src/test/codegen/alloc-optimisation.rs +++ b/src/test/codegen/alloc-optimisation.rs @@ -1,6 +1,5 @@ // // no-system-llvm -// min-llvm-version: 10.0.1 // compile-flags: -O #![crate_type="lib"] diff --git a/src/test/codegen/array-clone.rs b/src/test/codegen/array-clone.rs new file mode 100644 index 0000000000..0d42963bcd --- /dev/null +++ b/src/test/codegen/array-clone.rs @@ -0,0 +1,15 @@ +// compile-flags: -O + +#![crate_type = "lib"] + +// CHECK-LABEL: @array_clone +#[no_mangle] +pub fn array_clone(a: &[u8; 2]) -> [u8; 2] { + // CHECK-NOT: getelementptr + // CHECK-NOT: load i8 + // CHECK-NOT: zext + // CHECK-NOT: shl + // CHECK: load i16 + // CHECK-NEXT: ret i16 + a.clone() +} diff --git a/src/test/codegen/asm-powerpc-clobbers.rs b/src/test/codegen/asm-powerpc-clobbers.rs index 91a82c6012..10b20ba6be 100644 --- a/src/test/codegen/asm-powerpc-clobbers.rs +++ b/src/test/codegen/asm-powerpc-clobbers.rs @@ -1,4 +1,3 @@ -// min-llvm-version: 10.0.1 // revisions: powerpc powerpc64 powerpc64le //[powerpc] compile-flags: --target powerpc-unknown-linux-gnu //[powerpc] needs-llvm-components: powerpc @@ -8,7 +7,7 @@ //[powerpc64le] needs-llvm-components: powerpc #![crate_type = "rlib"] -#![feature(no_core, rustc_attrs, lang_items)] +#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)] #![no_core] #[lang = "sized"] diff --git a/src/test/codegen/binary-search-index-no-bound-check.rs b/src/test/codegen/binary-search-index-no-bound-check.rs index 110d1d5562..2deabcaa6c 100644 --- a/src/test/codegen/binary-search-index-no-bound-check.rs +++ b/src/test/codegen/binary-search-index-no-bound-check.rs @@ -1,4 +1,3 @@ -// min-llvm-version: 11.0.0 // compile-flags: -O // ignore-debug: the debug assertions get in the way #![crate_type = "lib"] diff --git a/src/test/codegen/enum-bounds-check-derived-idx.rs b/src/test/codegen/enum-bounds-check-derived-idx.rs index 7e3773b6a3..aa66c2ed08 100644 --- a/src/test/codegen/enum-bounds-check-derived-idx.rs +++ b/src/test/codegen/enum-bounds-check-derived-idx.rs @@ -1,7 +1,6 @@ // This test checks an optimization that is not guaranteed to work. This test case should not block // a future LLVM update. // compile-flags: -O -// min-llvm-version: 11.0 #![crate_type = "lib"] diff --git a/src/test/codegen/enum-bounds-check-issue-13926.rs b/src/test/codegen/enum-bounds-check-issue-13926.rs index ad029f0fa7..b26945bc54 100644 --- a/src/test/codegen/enum-bounds-check-issue-13926.rs +++ b/src/test/codegen/enum-bounds-check-issue-13926.rs @@ -1,7 +1,6 @@ // This test checks an optimization that is not guaranteed to work. This test case should not block // a future LLVM update. // compile-flags: -O -// min-llvm-version: 11.0 #![crate_type = "lib"] diff --git a/src/test/codegen/enum-bounds-check-issue-82871.rs b/src/test/codegen/enum-bounds-check-issue-82871.rs index e779e2ef27..a1fa1387d9 100644 --- a/src/test/codegen/enum-bounds-check-issue-82871.rs +++ b/src/test/codegen/enum-bounds-check-issue-82871.rs @@ -1,5 +1,4 @@ // compile-flags: -O -// min-llvm-version: 11.0 #![crate_type = "lib"] diff --git a/src/test/codegen/function-arguments.rs b/src/test/codegen/function-arguments.rs index f936f90960..3e10e227e5 100644 --- a/src/test/codegen/function-arguments.rs +++ b/src/test/codegen/function-arguments.rs @@ -1,6 +1,4 @@ // compile-flags: -O -C no-prepopulate-passes -// -// min-system-llvm-version: 12.0 #![crate_type = "lib"] #![feature(rustc_attrs)] diff --git a/src/test/codegen/issue-27130.rs b/src/test/codegen/issue-27130.rs index 7ae78782ff..e5ee94e1f4 100644 --- a/src/test/codegen/issue-27130.rs +++ b/src/test/codegen/issue-27130.rs @@ -1,5 +1,4 @@ // compile-flags: -O -// min-llvm-version: 11.0 #![crate_type = "lib"] diff --git a/src/test/codegen/issue-73031.rs b/src/test/codegen/issue-73031.rs index 6ba4d707f4..a09c4bcfbe 100644 --- a/src/test/codegen/issue-73031.rs +++ b/src/test/codegen/issue-73031.rs @@ -1,4 +1,3 @@ -// min-llvm-version: 12.0.0 // compile-flags: -O #![crate_type = "lib"] diff --git a/src/test/codegen/issue-73396-bounds-check-after-position.rs b/src/test/codegen/issue-73396-bounds-check-after-position.rs index e5f3ae45c0..8d07a67a1b 100644 --- a/src/test/codegen/issue-73396-bounds-check-after-position.rs +++ b/src/test/codegen/issue-73396-bounds-check-after-position.rs @@ -1,4 +1,3 @@ -// min-llvm-version: 11.0.0 // compile-flags: -O // ignore-debug: the debug assertions get in the way #![crate_type = "lib"] diff --git a/src/test/codegen/issue-73827-bounds-check-index-in-subexpr.rs b/src/test/codegen/issue-73827-bounds-check-index-in-subexpr.rs index d07eaa75b7..1ad05906e2 100644 --- a/src/test/codegen/issue-73827-bounds-check-index-in-subexpr.rs +++ b/src/test/codegen/issue-73827-bounds-check-index-in-subexpr.rs @@ -1,7 +1,6 @@ // This test checks that bounds checks are elided when // index is part of a (x | y) < C style condition -// min-llvm-version: 11.0.0 // compile-flags: -O #![crate_type = "lib"] diff --git a/src/test/codegen/issue-75525-bounds-checks.rs b/src/test/codegen/issue-75525-bounds-checks.rs index a03c63c1d0..2d363d8f73 100644 --- a/src/test/codegen/issue-75525-bounds-checks.rs +++ b/src/test/codegen/issue-75525-bounds-checks.rs @@ -1,6 +1,5 @@ // Regression test for #75525, verifies that no bounds checks are generated. -// min-llvm-version: 12.0.0 // compile-flags: -O #![crate_type = "lib"] diff --git a/src/test/codegen/issue-75546.rs b/src/test/codegen/issue-75546.rs index 49e4d4c7ec..470a9e0409 100644 --- a/src/test/codegen/issue-75546.rs +++ b/src/test/codegen/issue-75546.rs @@ -1,4 +1,3 @@ -// min-llvm-version: 12.0.0 // compile-flags: -O #![crate_type = "lib"] diff --git a/src/test/codegen/issue-77812.rs b/src/test/codegen/issue-77812.rs index 95042579ad..4cc8241454 100644 --- a/src/test/codegen/issue-77812.rs +++ b/src/test/codegen/issue-77812.rs @@ -1,4 +1,3 @@ -// min-llvm-version: 12.0.0 // compile-flags: -O #![crate_type = "lib"] diff --git a/src/test/codegen/non-terminate/infinite-loop-1.rs b/src/test/codegen/non-terminate/infinite-loop-1.rs index 8f9a53d19d..fa9c66b47c 100644 --- a/src/test/codegen/non-terminate/infinite-loop-1.rs +++ b/src/test/codegen/non-terminate/infinite-loop-1.rs @@ -1,4 +1,3 @@ -// min-llvm-version: 12.0 // compile-flags: -C opt-level=3 #![crate_type = "lib"] diff --git a/src/test/codegen/non-terminate/infinite-loop-2.rs b/src/test/codegen/non-terminate/infinite-loop-2.rs index a4c76de1e3..81d62ab33d 100644 --- a/src/test/codegen/non-terminate/infinite-loop-2.rs +++ b/src/test/codegen/non-terminate/infinite-loop-2.rs @@ -1,4 +1,3 @@ -// min-llvm-version: 12.0 // compile-flags: -C opt-level=3 #![crate_type = "lib"] diff --git a/src/test/codegen/non-terminate/infinite-recursion.rs b/src/test/codegen/non-terminate/infinite-recursion.rs index ccb22afbc7..6d1f2d4bf8 100644 --- a/src/test/codegen/non-terminate/infinite-recursion.rs +++ b/src/test/codegen/non-terminate/infinite-recursion.rs @@ -1,4 +1,3 @@ -// min-llvm-version: 12.0 // compile-flags: -C opt-level=3 #![crate_type = "lib"] diff --git a/src/test/codegen/non-terminate/nonempty-infinite-loop.rs b/src/test/codegen/non-terminate/nonempty-infinite-loop.rs index 896b7e8721..5e25e04fc2 100644 --- a/src/test/codegen/non-terminate/nonempty-infinite-loop.rs +++ b/src/test/codegen/non-terminate/nonempty-infinite-loop.rs @@ -1,4 +1,3 @@ -// min-llvm-version: 12.0 // compile-flags: -C opt-level=3 #![crate_type = "lib"] diff --git a/src/test/codegen/repr-transparent-aggregates-1.rs b/src/test/codegen/repr-transparent-aggregates-1.rs index 3017adb443..a61dad218c 100644 --- a/src/test/codegen/repr-transparent-aggregates-1.rs +++ b/src/test/codegen/repr-transparent-aggregates-1.rs @@ -1,7 +1,6 @@ // compile-flags: -C no-prepopulate-passes // -// min-system-llvm-version: 12.0 // ignore-arm // ignore-aarch64 // ignore-mips diff --git a/src/test/codegen/repr-transparent-aggregates-2.rs b/src/test/codegen/repr-transparent-aggregates-2.rs index 429d760b4a..b68e8e9ebe 100644 --- a/src/test/codegen/repr-transparent-aggregates-2.rs +++ b/src/test/codegen/repr-transparent-aggregates-2.rs @@ -1,7 +1,6 @@ // compile-flags: -C no-prepopulate-passes // -// min-system-llvm-version: 12.0 // ignore-aarch64 // ignore-emscripten // ignore-mips64 diff --git a/src/test/codegen/repr-transparent-aggregates-3.rs b/src/test/codegen/repr-transparent-aggregates-3.rs index 21176ac0e7..0db17e6b13 100644 --- a/src/test/codegen/repr-transparent-aggregates-3.rs +++ b/src/test/codegen/repr-transparent-aggregates-3.rs @@ -1,7 +1,6 @@ // compile-flags: -C no-prepopulate-passes // -// min-system-llvm-version: 12.0 // only-mips64 // See repr-transparent.rs diff --git a/src/test/codegen/sanitizer_cfi_add_canonical_jump_tables_flag.rs b/src/test/codegen/sanitizer_cfi_add_canonical_jump_tables_flag.rs new file mode 100644 index 0000000000..68f8180886 --- /dev/null +++ b/src/test/codegen/sanitizer_cfi_add_canonical_jump_tables_flag.rs @@ -0,0 +1,14 @@ +// Verifies that "CFI Canonical Jump Tables" module flag is added. +// +// ignore-windows +// needs-sanitizer-cfi +// only-aarch64 +// only-x86_64 +// compile-flags: -Clto -Zsanitizer=cfi + +#![crate_type="lib"] + +pub fn foo() { +} + +// CHECK: !{{[0-9]+}} = !{i32 2, !"CFI Canonical Jump Tables", i32 1} diff --git a/src/test/codegen/sanitizer_cfi_emit_type_checks.rs b/src/test/codegen/sanitizer_cfi_emit_type_checks.rs new file mode 100644 index 0000000000..9ed0422cef --- /dev/null +++ b/src/test/codegen/sanitizer_cfi_emit_type_checks.rs @@ -0,0 +1,24 @@ +// Verifies that pointer type membership tests for indirect calls are emitted. +// +// ignore-windows +// needs-sanitizer-cfi +// only-aarch64 +// only-x86_64 +// compile-flags: -Clto -Cno-prepopulate-passes -Zsanitizer=cfi + +#![crate_type="lib"] + +pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 { + // CHECK-LABEL: define{{.*}}foo{{.*}}!type !{{[0-9]+}} + // CHECK: start: + // CHECK-NEXT: %0 = bitcast i32 (i32)* %f to i8* + // CHECK-NEXT: %1 = call i1 @llvm.type.test(i8* %0, metadata !"{{[[:print:]]+}}") + // CHECK-NEXT: br i1 %1, label %type_test.pass, label %type_test.fail + // CHECK: type_test.pass: + // CHECK-NEXT: %2 = call i32 %f(i32 %arg) + // CHECK-NEXT: br label %bb1 + // CHECK: type_test.fail: + // CHECK-NEXT: call void @llvm.trap() + // CHECK-NEXT: unreachable + f(arg) +} diff --git a/src/test/codegen/sanitizer_cfi_emit_type_metadata.rs b/src/test/codegen/sanitizer_cfi_emit_type_metadata.rs new file mode 100644 index 0000000000..96fced47e7 --- /dev/null +++ b/src/test/codegen/sanitizer_cfi_emit_type_metadata.rs @@ -0,0 +1,31 @@ +// Verifies that type metadata for functions are emitted. +// +// ignore-windows +// needs-sanitizer-cfi +// only-aarch64 +// only-x86_64 +// compile-flags: -Clto -Cno-prepopulate-passes -Zsanitizer=cfi + +#![crate_type="lib"] + +pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 { + // CHECK-LABEL: define{{.*}}foo{{.*}}!type !{{[0-9]+}} + // CHECK: %1 = call i1 @llvm.type.test(i8* %0, metadata !"typeid1") + f(arg) +} + +pub fn bar(f: fn(i32, i32) -> i32, arg1: i32, arg2: i32) -> i32 { + // CHECK-LABEL: define{{.*}}bar{{.*}}!type !{{[0-9]+}} + // CHECK: %1 = call i1 @llvm.type.test(i8* %0, metadata !"typeid2") + f(arg1, arg2) +} + +pub fn baz(f: fn(i32, i32, i32) -> i32, arg1: i32, arg2: i32, arg3: i32) -> i32 { + // CHECK-LABEL: define{{.*}}baz{{.*}}!type !{{[0-9]+}} + // CHECK: %1 = call i1 @llvm.type.test(i8* %0, metadata !"typeid3") + f(arg1, arg2, arg3) +} + +// CHECK: !{{[0-9]+}} = !{i64 0, !"typeid2"} +// CHECK: !{{[0-9]+}} = !{i64 0, !"typeid3"} +// CHECK: !{{[0-9]+}} = !{i64 0, !"typeid4"} diff --git a/src/test/codegen/slice-reverse.rs b/src/test/codegen/slice-reverse.rs new file mode 100644 index 0000000000..e50b22f3ac --- /dev/null +++ b/src/test/codegen/slice-reverse.rs @@ -0,0 +1,27 @@ +// compile-flags: -O +// only-x86_64 +// ignore-debug: the debug assertions in from_raw_parts get in the way + +#![crate_type = "lib"] + +// CHECK-LABEL: @slice_reverse_u8 +#[no_mangle] +pub fn slice_reverse_u8(slice: &mut [u8]) { + // CHECK-NOT: panic_bounds_check + // CHECK-NOT: slice_end_index_len_fail + // CHECK: shufflevector <{{[0-9]+}} x i8> + // CHECK-NOT: panic_bounds_check + // CHECK-NOT: slice_end_index_len_fail + slice.reverse(); +} + +// CHECK-LABEL: @slice_reverse_i32 +#[no_mangle] +pub fn slice_reverse_i32(slice: &mut [i32]) { + // CHECK-NOT: panic_bounds_check + // CHECK-NOT: slice_end_index_len_fail + // CHECK: shufflevector <{{[0-9]+}} x i32> + // CHECK-NOT: panic_bounds_check + // CHECK-NOT: slice_end_index_len_fail + slice.reverse(); +} diff --git a/src/test/codegen/src-hash-algorithm/src-hash-algorithm-sha256.rs b/src/test/codegen/src-hash-algorithm/src-hash-algorithm-sha256.rs index eaa9eafa1e..dc7db8e237 100644 --- a/src/test/codegen/src-hash-algorithm/src-hash-algorithm-sha256.rs +++ b/src/test/codegen/src-hash-algorithm/src-hash-algorithm-sha256.rs @@ -1,5 +1,4 @@ // compile-flags: -g -Z src-hash-algorithm=sha256 -// min-llvm-version: 11.0 #![crate_type = "lib"] diff --git a/src/test/codegen/stack-protector.rs b/src/test/codegen/stack-protector.rs new file mode 100644 index 0000000000..a24e6f1e4f --- /dev/null +++ b/src/test/codegen/stack-protector.rs @@ -0,0 +1,34 @@ +// revisions: all strong basic none +// ignore-nvptx64 stack protector not supported +// [all] compile-flags: -Z stack-protector=all +// [strong] compile-flags: -Z stack-protector=strong +// [basic] compile-flags: -Z stack-protector=basic + +#![crate_type = "lib"] + +#[no_mangle] +pub fn foo() { + // CHECK: @foo() unnamed_addr #0 + + // all-NOT: attributes #0 = { {{.*}} sspstrong {{.*}} } + // all-NOT: attributes #0 = { {{.*}} ssp {{.*}} } + // all: attributes #0 = { {{.*}} sspreq {{.*}} } + // all-NOT: attributes #0 = { {{.*}} sspstrong {{.*}} } + // all-NOT: attributes #0 = { {{.*}} ssp {{.*}} } + + // strong-NOT: attributes #0 = { {{.*}} sspreq {{.*}} } + // strong-NOT: attributes #0 = { {{.*}} ssp {{.*}} } + // strong: attributes #0 = { {{.*}} sspstrong {{.*}} } + // strong-NOT: attributes #0 = { {{.*}} sspreq {{.*}} } + // strong-NOT: attributes #0 = { {{.*}} ssp {{.*}} } + + // basic-NOT: attributes #0 = { {{.*}} sspreq {{.*}} } + // basic-NOT: attributes #0 = { {{.*}} sspstrong {{.*}} } + // basic: attributes #0 = { {{.*}} ssp {{.*}} } + // basic-NOT: attributes #0 = { {{.*}} sspreq {{.*}} } + // basic-NOT: attributes #0 = { {{.*}} sspstrong {{.*}} } + + // none-NOT: attributes #0 = { {{.*}} sspreq {{.*}} } + // none-NOT: attributes #0 = { {{.*}} sspstrong {{.*}} } + // none-NOT: attributes #0 = { {{.*}} ssp {{.*}} } +} diff --git a/src/test/codegen/vec-in-place.rs b/src/test/codegen/vec-in-place.rs index 72ed7492be..a656c9e6f6 100644 --- a/src/test/codegen/vec-in-place.rs +++ b/src/test/codegen/vec-in-place.rs @@ -1,6 +1,5 @@ // 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) diff --git a/src/test/codegen/wasm_casts_trapping.rs b/src/test/codegen/wasm_casts_trapping.rs index baf130a879..eb06c4975b 100644 --- a/src/test/codegen/wasm_casts_trapping.rs +++ b/src/test/codegen/wasm_casts_trapping.rs @@ -1,6 +1,5 @@ // only-wasm32 // compile-flags: -C target-feature=-nontrapping-fptoint -// min-llvm-version: 12.0 #![crate_type = "lib"] // CHECK-LABEL: @cast_f64_i64 diff --git a/src/test/incremental/auxiliary/rustc-rust-log-aux.rs b/src/test/incremental/auxiliary/rustc-rust-log-aux.rs new file mode 100644 index 0000000000..a361373dc1 --- /dev/null +++ b/src/test/incremental/auxiliary/rustc-rust-log-aux.rs @@ -0,0 +1,8 @@ +// rustc-env:RUSTC_LOG=debug +#[cfg(rpass1)] +pub fn foo() {} + +#[cfg(rpass2)] +pub fn foo() { + println!(); +} diff --git a/src/test/incremental/hashes/for_loops.rs b/src/test/incremental/hashes/for_loops.rs index 5a944d28a0..d3687d5b90 100644 --- a/src/test/incremental/hashes/for_loops.rs +++ b/src/test/incremental/hashes/for_loops.rs @@ -83,7 +83,7 @@ pub fn change_iteration_variable_pattern() { #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck, promoted_mir")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_iteration_variable_pattern() { let mut _x = 0; @@ -108,7 +108,7 @@ pub fn change_iterable() { #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, promoted_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, promoted_mir, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, promoted_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_iterable() { let mut _x = 0; @@ -237,7 +237,7 @@ pub fn add_loop_label_to_continue() { #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn add_loop_label_to_continue() { let mut _x = 0; diff --git a/src/test/incremental/hashes/trait_defs.rs b/src/test/incremental/hashes/trait_defs.rs index 9cbd110d68..b72ec404f6 100644 --- a/src/test/incremental/hashes/trait_defs.rs +++ b/src/test/incremental/hashes/trait_defs.rs @@ -33,7 +33,7 @@ trait TraitVisibility { } #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub trait TraitVisibility { } @@ -46,7 +46,7 @@ trait TraitUnsafety { } #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] unsafe trait TraitUnsafety { } @@ -60,7 +60,7 @@ trait TraitAddMethod { #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,associated_item_def_ids,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub trait TraitAddMethod { fn method(); diff --git a/src/test/incremental/issue-85360-eval-obligation-ice.rs b/src/test/incremental/issue-85360-eval-obligation-ice.rs new file mode 100644 index 0000000000..1796c9d197 --- /dev/null +++ b/src/test/incremental/issue-85360-eval-obligation-ice.rs @@ -0,0 +1,118 @@ +// revisions:cfail1 cfail2 +//[cfail1] compile-flags: --crate-type=lib --edition=2021 -Zassert-incr-state=not-loaded +//[cfail2] compile-flags: --crate-type=lib --edition=2021 -Zassert-incr-state=loaded +// build-pass + +use core::any::Any; +use core::marker::PhantomData; + +struct DerefWrap(T); + +impl core::ops::Deref for DerefWrap { + type Target = T; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +struct Storage { + phantom: PhantomData<(T, D)>, +} + +type ReadStorage = Storage>>; + +pub trait Component { + type Storage; +} + +struct VecStorage; + +struct Pos; + +impl Component for Pos { + type Storage = VecStorage; +} + +struct GenericComp { + _t: T, +} + +impl Component for GenericComp { + type Storage = VecStorage; +} +struct ReadData { + pos_interpdata: ReadStorage>, +} + +trait System { + type SystemData; + + fn run(data: Self::SystemData, any: Box); +} + +struct Sys; + +impl System for Sys { + type SystemData = (ReadData, ReadStorage); + + fn run((data, pos): Self::SystemData, any: Box) { + > as SystemData>::setup(any); + + ParJoin::par_join((&pos, &data.pos_interpdata)); + } +} + +trait ParJoin { + fn par_join(self) + where + Self: Sized, + { + } +} + +impl<'a, T, D> ParJoin for &'a Storage +where + T: Component, + D: core::ops::Deref>, + T::Storage: Sync, +{ +} + +impl ParJoin for (A, B) +where + A: ParJoin, + B: ParJoin, +{ +} + +pub trait SystemData { + fn setup(any: Box); +} + +impl SystemData for ReadStorage +where + T: Component, +{ + fn setup(any: Box) { + let storage: &MaskedStorage = any.downcast_ref().unwrap(); + + >>::cast(&storage); + } +} + +pub struct MaskedStorage { + _inner: T::Storage, +} + +pub unsafe trait CastFrom { + fn cast(t: &T) -> &Self; +} + +unsafe impl CastFrom for dyn Any +where + T: Any + 'static, +{ + fn cast(t: &T) -> &Self { + t + } +} diff --git a/src/test/incremental/link_order/auxiliary/my_lib.rs b/src/test/incremental/link_order/auxiliary/my_lib.rs index 57cde5f7c6..1e7d823050 100644 --- a/src/test/incremental/link_order/auxiliary/my_lib.rs +++ b/src/test/incremental/link_order/auxiliary/my_lib.rs @@ -1,3 +1,3 @@ // no-prefer-dynamic -//[cfail1] compile-flags: -lbar -lfoo --crate-type lib -//[cfail2] compile-flags: -lfoo -lbar --crate-type lib +//[cfail1] compile-flags: -lbar -lfoo --crate-type lib -Zassert-incr-state=not-loaded +//[cfail2] compile-flags: -lfoo -lbar --crate-type lib -Zassert-incr-state=not-loaded diff --git a/src/test/incremental/rustc-rust-log.rs b/src/test/incremental/rustc-rust-log.rs new file mode 100644 index 0000000000..566f0d96d9 --- /dev/null +++ b/src/test/incremental/rustc-rust-log.rs @@ -0,0 +1,16 @@ +// revisions: rpass1 rpass2 +// This test is just checking that we won't ICE if logging is turned +// on; don't bother trying to compare that (copious) output. +// +// dont-check-compiler-stdout +// dont-check-compiler-stderr +// aux-build: rustc-rust-log-aux.rs +// rustc-env:RUSTC_LOG=debug + +#[cfg(rpass1)] +fn main() {} + +#[cfg(rpass2)] +fn main() { + println!(); +} diff --git a/src/test/incremental/struct_change_field_name.rs b/src/test/incremental/struct_change_field_name.rs index 7498d0305e..a7c79e9d75 100644 --- a/src/test/incremental/struct_change_field_name.rs +++ b/src/test/incremental/struct_change_field_name.rs @@ -3,6 +3,7 @@ // revisions:rpass1 cfail2 // compile-flags: -Z query-dep-graph +// [cfail2] compile-flags: -Z query-dep-graph -Z assert-incr-state=loaded #![feature(rustc_attrs)] diff --git a/src/test/mir-opt/inline/inline_generator.main.Inline.diff b/src/test/mir-opt/inline/inline_generator.main.Inline.diff index 9035b46f4c..29243c9aa7 100644 --- a/src/test/mir-opt/inline/inline_generator.main.Inline.diff +++ b/src/test/mir-opt/inline/inline_generator.main.Inline.diff @@ -3,10 +3,10 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/inline-generator.rs:8:11: 8:11 - let _1: std::ops::GeneratorState< as std::ops::Generator>::Yield, as std::ops::Generator>::Return>; // in scope 0 at $DIR/inline-generator.rs:9:9: 9:11 - let mut _2: std::pin::Pin<&mut impl std::ops::Generator>; // in scope 0 at $DIR/inline-generator.rs:9:14: 9:32 - let mut _3: &mut impl std::ops::Generator; // in scope 0 at $DIR/inline-generator.rs:9:23: 9:31 - let mut _4: impl std::ops::Generator; // in scope 0 at $DIR/inline-generator.rs:9:28: 9:31 + let _1: std::ops::GeneratorState; // in scope 0 at $DIR/inline-generator.rs:9:9: 9:11 + let mut _2: std::pin::Pin<&mut [generator@$DIR/inline-generator.rs:15:5: 15:41]>; // in scope 0 at $DIR/inline-generator.rs:9:14: 9:32 + let mut _3: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41]; // in scope 0 at $DIR/inline-generator.rs:9:23: 9:31 + let mut _4: [generator@$DIR/inline-generator.rs:15:5: 15:41]; // in scope 0 at $DIR/inline-generator.rs:9:28: 9:31 + let mut _7: bool; // in scope 0 at $DIR/inline-generator.rs:9:14: 9:46 scope 1 { debug _r => _1; // in scope 1 at $DIR/inline-generator.rs:9:9: 9:11 diff --git a/src/test/mir-opt/inline/issue-78442.rs b/src/test/mir-opt/inline/issue-78442.rs new file mode 100644 index 0000000000..aa8ede2df9 --- /dev/null +++ b/src/test/mir-opt/inline/issue-78442.rs @@ -0,0 +1,20 @@ +// compile-flags: -Z mir-opt-level=3 -Z inline-mir +// ignore-wasm32-bare compiled with panic=abort by default +#![crate_type = "lib"] + +// EMIT_MIR issue_78442.bar.RevealAll.diff +// EMIT_MIR issue_78442.bar.Inline.diff +pub fn bar

( + // Error won't happen if "bar" is not generic + _baz: P, +) { + hide_foo()(); +} + +fn hide_foo() -> impl Fn() { + // Error won't happen if "iterate" hasn't impl Trait or has generics + foo +} + +fn foo() { // Error won't happen if "foo" isn't used in "iterate" or has generics +} diff --git a/src/test/mir-opt/inline/issue_78442.bar.Inline.diff b/src/test/mir-opt/inline/issue_78442.bar.Inline.diff new file mode 100644 index 0000000000..045bc720ca --- /dev/null +++ b/src/test/mir-opt/inline/issue_78442.bar.Inline.diff @@ -0,0 +1,67 @@ +- // MIR for `bar` before Inline ++ // MIR for `bar` after Inline + + fn bar(_1: P) -> () { + debug _baz => _1; // in scope 0 at $DIR/issue-78442.rs:9:5: 9:9 + let mut _0: (); // return place in scope 0 at $DIR/issue-78442.rs:10:3: 10:3 + let _2: (); // in scope 0 at $DIR/issue-78442.rs:11:5: 11:17 + let mut _3: &fn() {foo}; // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15 + let _4: fn() {foo}; // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15 + let mut _5: (); // in scope 0 at $DIR/issue-78442.rs:11:5: 11:17 ++ scope 1 (inlined >::call - shim(fn() {foo})) { // at $DIR/issue-78442.rs:11:5: 11:17 ++ } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 + StorageLive(_3); // scope 0 at $DIR/issue-78442.rs:11:5: 11:15 + StorageLive(_4); // scope 0 at $DIR/issue-78442.rs:11:5: 11:15 +- _4 = hide_foo() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:15 ++ _4 = hide_foo() -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:15 + // mir::Constant + // + span: $DIR/issue-78442.rs:11:5: 11:13 + // + literal: Const { ty: fn() -> impl Fn() {hide_foo}, val: Value(Scalar()) } + } + + bb1: { + _3 = &_4; // scope 0 at $DIR/issue-78442.rs:11:5: 11:15 + StorageLive(_5); // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 +- _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 +- // mir::Constant +- // + span: $DIR/issue-78442.rs:11:5: 11:15 +- // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r impl Fn(), ()) -> >::Output {>::call}, val: Value(Scalar()) } ++ _2 = move (*_3)() -> [return: bb5, unwind: bb3]; // scope 1 at $DIR/issue-78442.rs:11:5: 11:17 + } + + bb2: { +- StorageDead(_5); // scope 0 at $DIR/issue-78442.rs:11:16: 11:17 +- StorageDead(_3); // scope 0 at $DIR/issue-78442.rs:11:16: 11:17 +- StorageDead(_4); // scope 0 at $DIR/issue-78442.rs:11:17: 11:18 +- StorageDead(_2); // scope 0 at $DIR/issue-78442.rs:11:17: 11:18 +- _0 = const (); // scope 0 at $DIR/issue-78442.rs:10:3: 12:2 +- drop(_1) -> [return: bb3, unwind: bb5]; // scope 0 at $DIR/issue-78442.rs:12:1: 12:2 ++ return; // scope 0 at $DIR/issue-78442.rs:12:2: 12:2 + } + +- bb3: { +- return; // scope 0 at $DIR/issue-78442.rs:12:2: 12:2 ++ bb3 (cleanup): { ++ drop(_1) -> bb4; // scope 0 at $DIR/issue-78442.rs:12:1: 12:2 + } + + bb4 (cleanup): { +- drop(_1) -> bb5; // scope 0 at $DIR/issue-78442.rs:12:1: 12:2 ++ resume; // scope 0 at $DIR/issue-78442.rs:7:1: 12:2 + } + +- bb5 (cleanup): { +- resume; // scope 0 at $DIR/issue-78442.rs:7:1: 12:2 ++ bb5: { ++ StorageDead(_5); // scope 0 at $DIR/issue-78442.rs:11:16: 11:17 ++ StorageDead(_3); // scope 0 at $DIR/issue-78442.rs:11:16: 11:17 ++ StorageDead(_4); // scope 0 at $DIR/issue-78442.rs:11:17: 11:18 ++ StorageDead(_2); // scope 0 at $DIR/issue-78442.rs:11:17: 11:18 ++ _0 = const (); // scope 0 at $DIR/issue-78442.rs:10:3: 12:2 ++ drop(_1) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:12:1: 12:2 + } + } + diff --git a/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff b/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff new file mode 100644 index 0000000000..3190db5228 --- /dev/null +++ b/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff @@ -0,0 +1,55 @@ +- // MIR for `bar` before RevealAll ++ // MIR for `bar` after RevealAll + + fn bar(_1: P) -> () { + debug _baz => _1; // in scope 0 at $DIR/issue-78442.rs:9:5: 9:9 + let mut _0: (); // return place in scope 0 at $DIR/issue-78442.rs:10:3: 10:3 + let _2: (); // in scope 0 at $DIR/issue-78442.rs:11:5: 11:17 +- let mut _3: &impl Fn(); // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15 +- let _4: impl Fn(); // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15 ++ let mut _3: &fn() {foo}; // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15 ++ let _4: fn() {foo}; // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15 + let mut _5: (); // in scope 0 at $DIR/issue-78442.rs:11:5: 11:17 + + bb0: { + StorageLive(_2); // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 + StorageLive(_3); // scope 0 at $DIR/issue-78442.rs:11:5: 11:15 + StorageLive(_4); // scope 0 at $DIR/issue-78442.rs:11:5: 11:15 + _4 = hide_foo() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:15 + // mir::Constant + // + span: $DIR/issue-78442.rs:11:5: 11:13 + // + literal: Const { ty: fn() -> impl Fn() {hide_foo}, val: Value(Scalar()) } + } + + bb1: { + _3 = &_4; // scope 0 at $DIR/issue-78442.rs:11:5: 11:15 + StorageLive(_5); // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 + nop; // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 + _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 + // mir::Constant + // + span: $DIR/issue-78442.rs:11:5: 11:15 + // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r impl Fn(), ()) -> >::Output {>::call}, val: Value(Scalar()) } + } + + bb2: { + StorageDead(_5); // scope 0 at $DIR/issue-78442.rs:11:16: 11:17 + StorageDead(_3); // scope 0 at $DIR/issue-78442.rs:11:16: 11:17 + StorageDead(_4); // scope 0 at $DIR/issue-78442.rs:11:17: 11:18 + StorageDead(_2); // scope 0 at $DIR/issue-78442.rs:11:17: 11:18 + _0 = const (); // scope 0 at $DIR/issue-78442.rs:10:3: 12:2 + drop(_1) -> [return: bb3, unwind: bb5]; // scope 0 at $DIR/issue-78442.rs:12:1: 12:2 + } + + bb3: { + return; // scope 0 at $DIR/issue-78442.rs:12:2: 12:2 + } + + bb4 (cleanup): { + drop(_1) -> bb5; // scope 0 at $DIR/issue-78442.rs:12:1: 12:2 + } + + bb5 (cleanup): { + resume; // scope 0 at $DIR/issue-78442.rs:7:1: 12:2 + } + } + diff --git a/src/test/mir-opt/issue-78192.rs b/src/test/mir-opt/issue-78192.rs index 906d094f72..39f665402b 100644 --- a/src/test/mir-opt/issue-78192.rs +++ b/src/test/mir-opt/issue-78192.rs @@ -1,4 +1,4 @@ -// EMIT_MIR issue_78192.f.InstCombine.diff +// compile-flags: -Zmir-opt-level=1 -Zinline-mir pub fn f(a: &T) -> *const T { let b: &*const T = &(a as *const T); *b @@ -7,3 +7,5 @@ pub fn f(a: &T) -> *const T { fn main() { f(&2); } + +// EMIT_MIR issue_78192.f.InstCombine.diff diff --git a/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff b/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff index 02f6e55a9a..2dfc94f218 100644 --- a/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff +++ b/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff @@ -7,39 +7,29 @@ let mut _2: std::ops::Range; // in scope 0 at $DIR/remove_storage_markers.rs:8:14: 8:19 let mut _3: std::ops::Range; // in scope 0 at $DIR/remove_storage_markers.rs:8:14: 8:19 let mut _5: (); // in scope 0 at $DIR/remove_storage_markers.rs:6:1: 11:2 - let _7: (); // in scope 0 at $DIR/remove_storage_markers.rs:8:14: 8:19 - let mut _8: std::option::Option; // in scope 0 at $DIR/remove_storage_markers.rs:8:14: 8:19 + let _6: (); // in scope 0 at $DIR/remove_storage_markers.rs:8:14: 8:19 + let mut _7: std::option::Option; // in scope 0 at $DIR/remove_storage_markers.rs:8:14: 8:19 + let mut _8: &mut std::ops::Range; // in scope 0 at $DIR/remove_storage_markers.rs:8:14: 8:19 let mut _9: &mut std::ops::Range; // in scope 0 at $DIR/remove_storage_markers.rs:8:14: 8:19 - let mut _10: &mut std::ops::Range; // in scope 0 at $DIR/remove_storage_markers.rs:8:14: 8:19 - let mut _11: isize; // in scope 0 at $DIR/remove_storage_markers.rs:8:9: 8:10 - let mut _13: i32; // in scope 0 at $DIR/remove_storage_markers.rs:8:9: 8:10 - let mut _14: !; // in scope 0 at $DIR/remove_storage_markers.rs:8:5: 10:6 - let _16: (); // in scope 0 at $DIR/remove_storage_markers.rs:8:20: 10:6 - let mut _17: i32; // in scope 0 at $DIR/remove_storage_markers.rs:9:16: 9:17 + let mut _10: isize; // in scope 0 at $DIR/remove_storage_markers.rs:8:5: 10:6 + let mut _11: !; // in scope 0 at $DIR/remove_storage_markers.rs:8:5: 10:6 + let mut _13: i32; // in scope 0 at $DIR/remove_storage_markers.rs:9:16: 9:17 scope 1 { debug sum => _1; // in scope 1 at $DIR/remove_storage_markers.rs:7:9: 7:16 let mut _4: std::ops::Range; // in scope 1 at $DIR/remove_storage_markers.rs:8:14: 8:19 scope 2 { debug iter => _4; // in scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19 - let mut _6: i32; // in scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19 + let _12: i32; // in scope 2 at $DIR/remove_storage_markers.rs:8:9: 8:10 scope 3 { - debug __next => _6; // in scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19 - let _12: i32; // in scope 3 at $DIR/remove_storage_markers.rs:8:9: 8:10 - let _15: i32; // in scope 3 at $DIR/remove_storage_markers.rs:8:9: 8:10 - scope 4 { - debug val => _12; // in scope 4 at $DIR/remove_storage_markers.rs:8:9: 8:10 - } - scope 5 { - debug i => _15; // in scope 5 at $DIR/remove_storage_markers.rs:8:9: 8:10 - } - scope 7 (inlined iter::range::>::next) { // at $DIR/remove_storage_markers.rs:8:14: 8:19 - debug self => _9; // in scope 7 at $DIR/remove_storage_markers.rs:8:14: 8:19 - let mut _18: &mut std::ops::Range; // in scope 7 at $DIR/remove_storage_markers.rs:8:14: 8:19 - } + debug i => _12; // in scope 3 at $DIR/remove_storage_markers.rs:8:9: 8:10 + } + scope 5 (inlined iter::range::>::next) { // at $DIR/remove_storage_markers.rs:8:14: 8:19 + debug self => _8; // in scope 5 at $DIR/remove_storage_markers.rs:8:14: 8:19 + let mut _14: &mut std::ops::Range; // in scope 5 at $DIR/remove_storage_markers.rs:8:14: 8:19 } } - scope 6 (inlined as IntoIterator>::into_iter) { // at $DIR/remove_storage_markers.rs:8:14: 8:19 - debug self => _3; // in scope 6 at $DIR/remove_storage_markers.rs:8:14: 8:19 + scope 4 (inlined as IntoIterator>::into_iter) { // at $DIR/remove_storage_markers.rs:8:14: 8:19 + debug self => _3; // in scope 4 at $DIR/remove_storage_markers.rs:8:14: 8:19 } } @@ -50,7 +40,7 @@ - StorageLive(_3); // scope 1 at $DIR/remove_storage_markers.rs:8:14: 8:19 (_3.0: i32) = const 0_i32; // scope 1 at $DIR/remove_storage_markers.rs:8:14: 8:19 (_3.1: i32) = const 10_i32; // scope 1 at $DIR/remove_storage_markers.rs:8:14: 8:19 - _2 = move _3; // scope 6 at $DIR/remove_storage_markers.rs:8:14: 8:19 + _2 = move _3; // scope 4 at $DIR/remove_storage_markers.rs:8:14: 8:19 - StorageDead(_3); // scope 1 at $DIR/remove_storage_markers.rs:8:18: 8:19 - StorageLive(_4); // scope 1 at $DIR/remove_storage_markers.rs:8:14: 8:19 _4 = move _2; // scope 1 at $DIR/remove_storage_markers.rs:8:14: 8:19 @@ -59,64 +49,51 @@ bb1: { - StorageLive(_6); // scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19 -- StorageLive(_7); // scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19 -- StorageLive(_8); // scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19 -- StorageLive(_9); // scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19 -- StorageLive(_10); // scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19 - _10 = &mut _4; // scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19 - _9 = &mut (*_10); // scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19 -- StorageLive(_18); // scope 7 at $DIR/remove_storage_markers.rs:8:14: 8:19 - _18 = &mut (*_9); // scope 7 at $DIR/remove_storage_markers.rs:8:14: 8:19 - _8 = as iter::range::RangeIteratorImpl>::spec_next(move _18) -> bb4; // scope 7 at $DIR/remove_storage_markers.rs:8:14: 8:19 +- StorageLive(_7); // scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19 +- StorageLive(_8); // scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19 +- StorageLive(_9); // scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19 + _9 = &mut _4; // scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19 + _8 = &mut (*_9); // scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19 +- StorageLive(_14); // scope 5 at $DIR/remove_storage_markers.rs:8:14: 8:19 + _14 = &mut (*_8); // scope 5 at $DIR/remove_storage_markers.rs:8:14: 8:19 + _7 = as iter::range::RangeIteratorImpl>::spec_next(move _14) -> bb4; // scope 5 at $DIR/remove_storage_markers.rs:8:14: 8:19 // mir::Constant // + span: $DIR/remove_storage_markers.rs:8:14: 8:19 // + literal: Const { ty: for<'r> fn(&'r mut std::ops::Range) -> std::option::Option< as std::iter::range::RangeIteratorImpl>::Item> { as std::iter::range::RangeIteratorImpl>::spec_next}, val: Value(Scalar()) } } bb2: { - _0 = const (); // scope 3 at $DIR/remove_storage_markers.rs:8:5: 10:6 -- StorageDead(_10); // scope 3 at $DIR/remove_storage_markers.rs:8:18: 8:19 -- StorageDead(_8); // scope 3 at $DIR/remove_storage_markers.rs:8:18: 8:19 -- StorageDead(_7); // scope 3 at $DIR/remove_storage_markers.rs:8:18: 8:19 +- StorageLive(_12); // scope 2 at $DIR/remove_storage_markers.rs:8:9: 8:10 + _12 = ((_7 as Some).0: i32); // scope 2 at $DIR/remove_storage_markers.rs:8:9: 8:10 +- StorageLive(_13); // scope 3 at $DIR/remove_storage_markers.rs:9:16: 9:17 + _13 = _12; // scope 3 at $DIR/remove_storage_markers.rs:9:16: 9:17 + _1 = Add(_1, move _13); // scope 3 at $DIR/remove_storage_markers.rs:9:9: 9:17 +- StorageDead(_13); // scope 3 at $DIR/remove_storage_markers.rs:9:16: 9:17 + _6 = const (); // scope 3 at $DIR/remove_storage_markers.rs:8:20: 10:6 +- StorageDead(_12); // scope 2 at $DIR/remove_storage_markers.rs:10:5: 10:6 +- StorageDead(_9); // scope 2 at $DIR/remove_storage_markers.rs:10:5: 10:6 +- StorageDead(_7); // scope 2 at $DIR/remove_storage_markers.rs:10:5: 10:6 - StorageDead(_6); // scope 2 at $DIR/remove_storage_markers.rs:10:5: 10:6 -- StorageDead(_4); // scope 1 at $DIR/remove_storage_markers.rs:10:5: 10:6 -- StorageDead(_2); // scope 1 at $DIR/remove_storage_markers.rs:10:5: 10:6 -- StorageDead(_1); // scope 0 at $DIR/remove_storage_markers.rs:11:1: 11:2 - return; // scope 0 at $DIR/remove_storage_markers.rs:11:2: 11:2 + _5 = const (); // scope 2 at $DIR/remove_storage_markers.rs:8:5: 10:6 + goto -> bb1; // scope 2 at $DIR/remove_storage_markers.rs:8:5: 10:6 } bb3: { -- StorageLive(_12); // scope 3 at $DIR/remove_storage_markers.rs:8:9: 8:10 - _12 = ((_8 as Some).0: i32); // scope 3 at $DIR/remove_storage_markers.rs:8:9: 8:10 -- StorageLive(_13); // scope 4 at $DIR/remove_storage_markers.rs:8:9: 8:10 - _13 = _12; // scope 4 at $DIR/remove_storage_markers.rs:8:9: 8:10 - _6 = move _13; // scope 4 at $DIR/remove_storage_markers.rs:8:9: 8:10 - _7 = const (); // scope 4 at $DIR/remove_storage_markers.rs:8:9: 8:10 -- StorageDead(_13); // scope 4 at $DIR/remove_storage_markers.rs:8:9: 8:10 -- StorageDead(_12); // scope 3 at $DIR/remove_storage_markers.rs:8:9: 8:10 -- StorageDead(_10); // scope 3 at $DIR/remove_storage_markers.rs:8:18: 8:19 -- StorageDead(_8); // scope 3 at $DIR/remove_storage_markers.rs:8:18: 8:19 -- StorageDead(_7); // scope 3 at $DIR/remove_storage_markers.rs:8:18: 8:19 -- StorageLive(_15); // scope 3 at $DIR/remove_storage_markers.rs:8:9: 8:10 - _15 = _6; // scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19 -- StorageLive(_16); // scope 5 at $DIR/remove_storage_markers.rs:8:20: 10:6 -- StorageLive(_17); // scope 5 at $DIR/remove_storage_markers.rs:9:16: 9:17 - _17 = _15; // scope 5 at $DIR/remove_storage_markers.rs:9:16: 9:17 - _1 = Add(_1, move _17); // scope 5 at $DIR/remove_storage_markers.rs:9:9: 9:17 -- StorageDead(_17); // scope 5 at $DIR/remove_storage_markers.rs:9:16: 9:17 - _16 = const (); // scope 5 at $DIR/remove_storage_markers.rs:8:20: 10:6 -- StorageDead(_16); // scope 5 at $DIR/remove_storage_markers.rs:10:5: 10:6 - _5 = const (); // scope 2 at $DIR/remove_storage_markers.rs:8:5: 10:6 -- StorageDead(_15); // scope 3 at $DIR/remove_storage_markers.rs:10:5: 10:6 + _0 = const (); // scope 2 at $DIR/remove_storage_markers.rs:8:5: 10:6 +- StorageDead(_9); // scope 2 at $DIR/remove_storage_markers.rs:10:5: 10:6 +- StorageDead(_7); // scope 2 at $DIR/remove_storage_markers.rs:10:5: 10:6 - StorageDead(_6); // scope 2 at $DIR/remove_storage_markers.rs:10:5: 10:6 - goto -> bb1; // scope 2 at $DIR/remove_storage_markers.rs:8:5: 10:6 +- StorageDead(_4); // scope 1 at $DIR/remove_storage_markers.rs:10:5: 10:6 +- StorageDead(_2); // scope 1 at $DIR/remove_storage_markers.rs:10:5: 10:6 +- StorageDead(_1); // scope 0 at $DIR/remove_storage_markers.rs:11:1: 11:2 + return; // scope 0 at $DIR/remove_storage_markers.rs:11:2: 11:2 } bb4: { -- StorageDead(_18); // scope 7 at $DIR/remove_storage_markers.rs:8:14: 8:19 -- StorageDead(_9); // scope 3 at $DIR/remove_storage_markers.rs:8:18: 8:19 - _11 = discriminant(_8); // scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19 - switchInt(move _11) -> [0_isize: bb2, otherwise: bb3]; // scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19 +- StorageDead(_14); // scope 5 at $DIR/remove_storage_markers.rs:8:14: 8:19 +- StorageDead(_8); // scope 2 at $DIR/remove_storage_markers.rs:8:18: 8:19 + _10 = discriminant(_7); // scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19 + switchInt(move _10) -> [0_isize: bb3, otherwise: bb2]; // scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19 } } diff --git a/src/test/pretty/dollar-crate.pp b/src/test/pretty/dollar-crate.pp index f4be3c1c63..84eda08d20 100644 --- a/src/test/pretty/dollar-crate.pp +++ b/src/test/pretty/dollar-crate.pp @@ -12,7 +12,7 @@ fn main() { { ::std::io::_print(::core::fmt::Arguments::new_v1(&["rust\n"], &match () { - () => [], + _args => [], })); }; } diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp index 199aee0562..529daab903 100644 --- a/src/test/pretty/issue-4264.pp +++ b/src/test/pretty/issue-4264.pp @@ -45,7 +45,7 @@ pub fn bar() ({ as ()) { - () + _args => ([] as diff --git a/src/test/run-make-fulldeps/coverage-llvmir/Makefile b/src/test/run-make-fulldeps/coverage-llvmir/Makefile index 1ff1ffcc4b..8722d9e10d 100644 --- a/src/test/run-make-fulldeps/coverage-llvmir/Makefile +++ b/src/test/run-make-fulldeps/coverage-llvmir/Makefile @@ -1,5 +1,4 @@ # needs-profiler-support -# min-llvm-version: 11.0 -include ../coverage/coverage_tools.mk diff --git a/src/test/run-make-fulldeps/coverage-reports/Makefile b/src/test/run-make-fulldeps/coverage-reports/Makefile index 78fbf811f1..4adf02bee0 100644 --- a/src/test/run-make-fulldeps/coverage-reports/Makefile +++ b/src/test/run-make-fulldeps/coverage-reports/Makefile @@ -1,6 +1,5 @@ # needs-profiler-support # ignore-windows-gnu -# min-llvm-version: 11.0 # FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works # properly. Since we only have GCC on the CI ignore the test for now. 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 index 28e0f1953e..1c64ead9f2 100644 --- 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 @@ -5,7 +5,6 @@ 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; @@ -17,7 +16,6 @@ 16| 0| x = 3; 17| | } 18| 11| for _ in 0..10 { - ^10 19| 10| match is_true { 20| 0| false => { 21| 0| x = 1; @@ -29,7 +27,6 @@ 27| 0| x = 3; 28| | } 29| 11| for _ in 0..10 { - ^10 30| 10| match is_true { 31| 10| true => { 32| 10| x = 1; @@ -41,14 +38,12 @@ 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; 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 31d3ddea8d..6f5d1544fa 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 @@ -40,7 +40,8 @@ 39| 30|} 40| | 41| 6|fn display(xs: &[T]) { - 42| 18| for x in xs { + 42| 24| for x in xs { + ^18 43| 18| print!("{}", x); 44| 18| } 45| 6| println!(); 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 5d572db7cc..b7ad79a248 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 @@ -17,7 +17,8 @@ 16| 0| } else { 17| 0| } 18| | - 19| 10| for i in 0..10 { + 19| 11| for i in 0..10 { + ^10 20| 10| if true { 21| 10| if false { 22| 0| while true {} @@ -43,7 +44,8 @@ 41| 1| write!(f, "cool")?; ^0 42| | } - 43| 10| for i in 0..10 { + 43| 11| for i in 0..10 { + ^10 44| 10| if false { 45| 0| } else { 46| 10| if false { diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.simple_match.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.simple_match.txt index 81b4c090a4..b929821311 100644 --- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.simple_match.txt +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.simple_match.txt @@ -13,7 +13,7 @@ ^0 13| | 14| | for - 15| 2| _ + 15| | _ 16| | in 17| 3| 0..2 18| | { 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 9fca52451e..0ad0180b76 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 @@ -14,7 +14,7 @@ 14| 1| countdown = 10 15| | ; 16| | for - 17| 6| _ + 17| | _ 18| | in 19| 6| 0..10 20| | { @@ -64,7 +64,7 @@ 63| 1| countdown = 10 64| | ; 65| | for - 66| 6| _ + 66| | _ 67| | in 68| 6| 0..10 69| | { diff --git a/src/test/run-make-fulldeps/foreign-exceptions/foo.rs b/src/test/run-make-fulldeps/foreign-exceptions/foo.rs index c279cf7e8b..dd3b7c76f2 100644 --- a/src/test/run-make-fulldeps/foreign-exceptions/foo.rs +++ b/src/test/run-make-fulldeps/foreign-exceptions/foo.rs @@ -2,8 +2,6 @@ // are caught by catch_unwind. Also tests that Rust panics can unwind through // C++ code. -// For linking libstdc++ on MinGW -#![cfg_attr(all(windows, target_env = "gnu"), feature(static_nobundle))] #![feature(c_unwind)] use std::panic::{catch_unwind, AssertUnwindSafe}; diff --git a/src/test/run-make-fulldeps/invalid-library/Makefile b/src/test/run-make-fulldeps/invalid-library/Makefile index c75713c3ee..de463a3301 100644 --- a/src/test/run-make-fulldeps/invalid-library/Makefile +++ b/src/test/run-make-fulldeps/invalid-library/Makefile @@ -3,4 +3,4 @@ all: touch $(TMPDIR)/lib.rmeta $(AR) crus $(TMPDIR)/libfoo-ffffffff-1.0.rlib $(TMPDIR)/lib.rmeta - $(RUSTC) foo.rs 2>&1 | $(CGREP) "can't find crate for" + $(RUSTC) foo.rs 2>&1 | $(CGREP) "found invalid metadata" diff --git a/src/test/run-make-fulldeps/obtain-borrowck/driver.rs b/src/test/run-make-fulldeps/obtain-borrowck/driver.rs index a288b90d79..86e6d9e756 100644 --- a/src/test/run-make-fulldeps/obtain-borrowck/driver.rs +++ b/src/test/run-make-fulldeps/obtain-borrowck/driver.rs @@ -25,7 +25,7 @@ use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_interface::interface::Compiler; use rustc_interface::{Config, Queries}; use rustc_middle::ty::query::query_values::mir_borrowck; -use rustc_middle::ty::query::Providers; +use rustc_middle::ty::query::{ExternProviders, Providers}; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::Session; use std::cell::RefCell; @@ -87,9 +87,8 @@ impl rustc_driver::Callbacks for CompilerCalls { } } -fn override_queries(_session: &Session, local: &mut Providers, external: &mut Providers) { +fn override_queries(_session: &Session, local: &mut Providers, _external: &mut ExternProviders) { local.mir_borrowck = mir_borrowck; - external.mir_borrowck = mir_borrowck; } // Since mir_borrowck does not have access to any other state, we need to use a diff --git a/src/test/run-make-fulldeps/print-cfg/Makefile b/src/test/run-make-fulldeps/print-cfg/Makefile index 013bf3baca..5472baae3f 100644 --- a/src/test/run-make-fulldeps/print-cfg/Makefile +++ b/src/test/run-make-fulldeps/print-cfg/Makefile @@ -1,3 +1,5 @@ +# needs-llvm-components: x86 arm + -include ../tools.mk all: default diff --git a/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/Makefile b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/Makefile new file mode 100644 index 0000000000..4934e875da --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/Makefile @@ -0,0 +1,18 @@ +-include ../../run-make-fulldeps/tools.mk + +OUTPUT_DIR := "$(TMPDIR)/rustdoc" +DYLIB_NAME := $(shell echo | $(RUSTC) --crate-name foobar_macro --crate-type dylib --print file-names -) + +all: + $(RUSTC) src/proc.rs --crate-name foobar_macro --edition=2021 --crate-type proc-macro --emit=dep-info,link + + $(RUSTC) src/lib.rs --crate-name foobar --edition=2021 --crate-type lib --emit=dep-info,link + + $(RUSTDOC) examples/ex.rs --crate-name ex --crate-type bin --output $(OUTPUT_DIR) \ + --extern foobar=$(TMPDIR)/libfoobar.rlib --extern foobar_macro=$(TMPDIR)/$(DYLIB_NAME) \ + -Z unstable-options --scrape-examples-output-path $(TMPDIR)/ex.calls --scrape-examples-target-crate foobar + + $(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --output $(OUTPUT_DIR) \ + -Z unstable-options --with-examples $(TMPDIR)/ex.calls + + $(HTMLDOCCK) $(OUTPUT_DIR) src/lib.rs diff --git a/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/examples/ex.rs b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/examples/ex.rs new file mode 100644 index 0000000000..4d8c8b30e3 --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/examples/ex.rs @@ -0,0 +1,27 @@ +extern crate foobar; +extern crate foobar_macro; + +use foobar::*; +use foobar_macro::*; + +a_proc_macro!(); // no + +#[an_attr_macro] +fn a() { + f(); // no +} + +#[an_attr_macro(with_span)] +fn b() { + f(); // yes +} + +fn c() { + a_rules_macro!(f()); // yes +} + +fn d() { + a_rules_macro!(()); // no +} + +fn main(){} diff --git a/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/lib.rs b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/lib.rs new file mode 100644 index 0000000000..bac3970a4d --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/lib.rs @@ -0,0 +1,12 @@ +// Scraped example should only include line numbers for items b and c in ex.rs +// @!has foobar/fn.f.html '//*[@class="line-numbers"]' '14' +// @has foobar/fn.f.html '//*[@class="line-numbers"]' '15' +// @has foobar/fn.f.html '//*[@class="line-numbers"]' '21' +// @!has foobar/fn.f.html '//*[@class="line-numbers"]' '22' + +pub fn f() {} + +#[macro_export] +macro_rules! a_rules_macro { + ($e:expr) => { ($e, foobar::f()); } +} diff --git a/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/proc.rs b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/proc.rs new file mode 100644 index 0000000000..46e518fdf6 --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/proc.rs @@ -0,0 +1,39 @@ +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +pub fn a_proc_macro(_item: TokenStream) -> TokenStream { + "fn ex() { foobar::f(); }".parse().unwrap() +} + +// inserts foobar::f() to the end of the function +#[proc_macro_attribute] +pub fn an_attr_macro(attr: TokenStream, item: TokenStream) -> TokenStream { + let new_call: TokenStream = "foobar::f();".parse().unwrap(); + + let mut tokens = item.into_iter(); + + let fn_tok = tokens.next().unwrap(); + let ident_tok = tokens.next().unwrap(); + let args_tok = tokens.next().unwrap(); + let body = match tokens.next().unwrap() { + TokenTree::Group(g) => { + let new_g = Group::new(g.delimiter(), new_call); + let mut outer_g = Group::new( + g.delimiter(), + [TokenTree::Group(g.clone()), TokenTree::Group(new_g)].into_iter().collect(), + ); + + if attr.to_string() == "with_span" { + outer_g.set_span(g.span()); + } + + TokenTree::Group(outer_g) + } + _ => unreachable!(), + }; + + let tokens = vec![fn_tok, ident_tok, args_tok, body].into_iter().collect::(); + + tokens +} diff --git a/src/test/run-make-fulldeps/split-debuginfo/Makefile b/src/test/run-make-fulldeps/split-debuginfo/Makefile index c89f2ae834..e8e62efe01 100644 --- a/src/test/run-make-fulldeps/split-debuginfo/Makefile +++ b/src/test/run-make-fulldeps/split-debuginfo/Makefile @@ -1,7 +1,5 @@ -include ../tools.mk -# min-llvm-version: 11.0 - all: off packed unpacked ifeq ($(UNAME),Darwin) diff --git a/src/test/run-make-fulldeps/split-dwarf/Makefile b/src/test/run-make-fulldeps/split-dwarf/Makefile index f56b4168b2..ef61ff0450 100644 --- a/src/test/run-make-fulldeps/split-dwarf/Makefile +++ b/src/test/run-make-fulldeps/split-dwarf/Makefile @@ -1,7 +1,6 @@ -include ../tools.mk # only-linux -# min-llvm-version: 11.0 all: $(RUSTC) -Z unstable-options -C split-debuginfo=packed -C debuginfo=2 foo.rs -g diff --git a/src/test/run-make-fulldeps/tools.mk b/src/test/run-make-fulldeps/tools.mk index 3934c4725f..9655d09df0 100644 --- a/src/test/run-make-fulldeps/tools.mk +++ b/src/test/run-make-fulldeps/tools.mk @@ -117,10 +117,10 @@ else # that it is compiled with the expectation that pthreads is dynamically # linked as a DLL and will fail to link with a statically linked libpthread. # - # So we end up with the following hack: we link use static-nobundle to only + # So we end up with the following hack: we link use static:-bundle to only # link the parts of libstdc++ that we actually use, which doesn't include # the dependency on the pthreads DLL. - EXTRARSCXXFLAGS := -l static-nobundle=stdc++ + EXTRARSCXXFLAGS := -l static:-bundle=stdc++ -Z unstable-options endif else ifeq ($(UNAME),Darwin) diff --git a/src/test/run-make/invalid-so/Makefile b/src/test/run-make/invalid-so/Makefile new file mode 100644 index 0000000000..5b82ecd207 --- /dev/null +++ b/src/test/run-make/invalid-so/Makefile @@ -0,0 +1,7 @@ +include ../../run-make-fulldeps/tools.mk + +DYLIB_NAME := $(shell echo | $(RUSTC) --crate-name foo --crate-type dylib --print file-names -) + +all: + echo >> $(TMPDIR)/$(DYLIB_NAME) + $(RUSTC) --crate-type lib --extern foo=$(TMPDIR)/$(DYLIB_NAME) bar.rs 2>&1 | $(CGREP) 'invalid metadata files for crate `foo`' diff --git a/src/test/run-make/invalid-so/bar.rs b/src/test/run-make/invalid-so/bar.rs new file mode 100644 index 0000000000..49af74e1b7 --- /dev/null +++ b/src/test/run-make/invalid-so/bar.rs @@ -0,0 +1 @@ +extern crate foo; diff --git a/src/test/run-make/issue-10971-temps-dir/Makefile b/src/test/run-make/issue-10971-temps-dir/Makefile new file mode 100644 index 0000000000..5ce2719260 --- /dev/null +++ b/src/test/run-make/issue-10971-temps-dir/Makefile @@ -0,0 +1,10 @@ +-include ../../run-make-fulldeps/tools.mk + +# Regression test for issue #10971 +# Running two invocations in parallel would overwrite each other's temp files. + +all: + touch $(TMPDIR)/lib.rs + + $(RUSTC) --crate-type=lib -Z temps-dir=$(TMPDIR)/temp1 $(TMPDIR)/lib.rs & \ + $(RUSTC) --crate-type=staticlib -Z temps-dir=$(TMPDIR)/temp2 $(TMPDIR)/lib.rs diff --git a/src/test/run-make/issue-36710/foo.rs b/src/test/run-make/issue-36710/foo.rs index 845844f427..f30a35e27c 100644 --- a/src/test/run-make/issue-36710/foo.rs +++ b/src/test/run-make/issue-36710/foo.rs @@ -1,8 +1,5 @@ // Tests that linking to C++ code with global destructors works. -// For linking libstdc++ on MinGW -#![cfg_attr(all(windows, target_env = "gnu"), feature(static_nobundle))] - extern "C" { fn get() -> u32; } diff --git a/src/test/run-make/rustdoc-scrape-examples-invalid-expr/Makefile b/src/test/run-make/rustdoc-scrape-examples-invalid-expr/Makefile new file mode 100644 index 0000000000..dce8b83eef --- /dev/null +++ b/src/test/run-make/rustdoc-scrape-examples-invalid-expr/Makefile @@ -0,0 +1,5 @@ +deps := ex + +-include ../rustdoc-scrape-examples-multiple/scrape.mk + +all: scrape diff --git a/src/test/run-make/rustdoc-scrape-examples-invalid-expr/examples/ex.rs b/src/test/run-make/rustdoc-scrape-examples-invalid-expr/examples/ex.rs new file mode 100644 index 0000000000..b342b5b0aa --- /dev/null +++ b/src/test/run-make/rustdoc-scrape-examples-invalid-expr/examples/ex.rs @@ -0,0 +1,2 @@ +pub struct Foo([usize; foobar::f()]); +fn main() {} diff --git a/src/test/run-make/rustdoc-scrape-examples-invalid-expr/src/lib.rs b/src/test/run-make/rustdoc-scrape-examples-invalid-expr/src/lib.rs new file mode 100644 index 0000000000..c30c99dec6 --- /dev/null +++ b/src/test/run-make/rustdoc-scrape-examples-invalid-expr/src/lib.rs @@ -0,0 +1 @@ +pub const fn f() -> usize { 5 } diff --git a/src/test/run-make/rustdoc-scrape-examples-multiple/Makefile b/src/test/run-make/rustdoc-scrape-examples-multiple/Makefile new file mode 100644 index 0000000000..897805e440 --- /dev/null +++ b/src/test/run-make/rustdoc-scrape-examples-multiple/Makefile @@ -0,0 +1,5 @@ +deps := ex ex2 + +-include ./scrape.mk + +all: scrape diff --git a/src/test/run-make/rustdoc-scrape-examples-multiple/examples/ex.rs b/src/test/run-make/rustdoc-scrape-examples-multiple/examples/ex.rs new file mode 100644 index 0000000000..01b730c614 --- /dev/null +++ b/src/test/run-make/rustdoc-scrape-examples-multiple/examples/ex.rs @@ -0,0 +1,4 @@ +fn main() { + foobar::ok(); + foobar::ok(); +} diff --git a/src/test/run-make/rustdoc-scrape-examples-multiple/examples/ex2.rs b/src/test/run-make/rustdoc-scrape-examples-multiple/examples/ex2.rs new file mode 100644 index 0000000000..f83cf2f270 --- /dev/null +++ b/src/test/run-make/rustdoc-scrape-examples-multiple/examples/ex2.rs @@ -0,0 +1,3 @@ +fn main() { + foobar::ok(); +} diff --git a/src/test/run-make/rustdoc-scrape-examples-multiple/scrape.mk b/src/test/run-make/rustdoc-scrape-examples-multiple/scrape.mk new file mode 100644 index 0000000000..1fa1fae1a0 --- /dev/null +++ b/src/test/run-make/rustdoc-scrape-examples-multiple/scrape.mk @@ -0,0 +1,20 @@ +-include ../../run-make-fulldeps/tools.mk + +OUTPUT_DIR := "$(TMPDIR)/rustdoc" + +$(TMPDIR)/%.calls: $(TMPDIR)/libfoobar.rmeta + $(RUSTDOC) examples/$*.rs --crate-name $* --crate-type bin --output $(OUTPUT_DIR) \ + --extern foobar=$(TMPDIR)/libfoobar.rmeta \ + -Z unstable-options \ + --scrape-examples-output-path $@ \ + --scrape-examples-target-crate foobar + +$(TMPDIR)/lib%.rmeta: src/lib.rs + $(RUSTC) src/lib.rs --crate-name $* --crate-type lib --emit=metadata + +scrape: $(foreach d,$(deps),$(TMPDIR)/$(d).calls) + $(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --output $(OUTPUT_DIR) \ + -Z unstable-options \ + $(foreach d,$(deps),--with-examples $(TMPDIR)/$(d).calls) + + $(HTMLDOCCK) $(OUTPUT_DIR) src/lib.rs diff --git a/src/test/run-make/rustdoc-scrape-examples-multiple/src/lib.rs b/src/test/run-make/rustdoc-scrape-examples-multiple/src/lib.rs new file mode 100644 index 0000000000..bdfeda92d7 --- /dev/null +++ b/src/test/run-make/rustdoc-scrape-examples-multiple/src/lib.rs @@ -0,0 +1,6 @@ +// @has foobar/fn.ok.html '//*[@class="docblock scraped-example-list"]//*[@class="prev"]' '' +// @has foobar/fn.ok.html '//*[@class="more-scraped-examples"]' '' +// @has src/ex/ex.rs.html +// @has foobar/fn.ok.html '//a[@href="../src/ex/ex.rs.html#2"]' '' + +pub fn ok() {} diff --git a/src/test/run-make/rustdoc-scrape-examples-ordering/Makefile b/src/test/run-make/rustdoc-scrape-examples-ordering/Makefile new file mode 100644 index 0000000000..339d539bfd --- /dev/null +++ b/src/test/run-make/rustdoc-scrape-examples-ordering/Makefile @@ -0,0 +1,5 @@ +deps := ex1 ex2 + +-include ../rustdoc-scrape-examples-multiple/scrape.mk + +all: scrape diff --git a/src/test/run-make/rustdoc-scrape-examples-ordering/examples/ex1.rs b/src/test/run-make/rustdoc-scrape-examples-ordering/examples/ex1.rs new file mode 100644 index 0000000000..05c18007b0 --- /dev/null +++ b/src/test/run-make/rustdoc-scrape-examples-ordering/examples/ex1.rs @@ -0,0 +1,11 @@ +fn main() { + foobar::ok(0); + + // this is a + + // .. + + // BIG + + // item +} diff --git a/src/test/run-make/rustdoc-scrape-examples-ordering/examples/ex2.rs b/src/test/run-make/rustdoc-scrape-examples-ordering/examples/ex2.rs new file mode 100644 index 0000000000..de21d9061f --- /dev/null +++ b/src/test/run-make/rustdoc-scrape-examples-ordering/examples/ex2.rs @@ -0,0 +1,8 @@ +fn main() { + foobar::ok(1); + // small item +} + +fn f() { + foobar::ok(2); +} diff --git a/src/test/run-make/rustdoc-scrape-examples-ordering/src/lib.rs b/src/test/run-make/rustdoc-scrape-examples-ordering/src/lib.rs new file mode 100644 index 0000000000..5afffffdf9 --- /dev/null +++ b/src/test/run-make/rustdoc-scrape-examples-ordering/src/lib.rs @@ -0,0 +1,7 @@ +// @has foobar/fn.ok.html '//*[@class="docblock scraped-example-list"]' 'ex2' +// @has foobar/fn.ok.html '//*[@class="more-scraped-examples"]' 'ex1' +// @has foobar/fn.ok.html '//*[@class="highlight focus"]' '1' +// @has foobar/fn.ok.html '//*[@class="highlight"]' '2' +// @has foobar/fn.ok.html '//*[@class="highlight focus"]' '0' + +pub fn ok(_x: i32) {} diff --git a/src/test/run-make/rustdoc-scrape-examples-remap/Makefile b/src/test/run-make/rustdoc-scrape-examples-remap/Makefile new file mode 100644 index 0000000000..dce8b83eef --- /dev/null +++ b/src/test/run-make/rustdoc-scrape-examples-remap/Makefile @@ -0,0 +1,5 @@ +deps := ex + +-include ../rustdoc-scrape-examples-multiple/scrape.mk + +all: scrape diff --git a/src/test/run-make/rustdoc-scrape-examples-remap/examples/ex.rs b/src/test/run-make/rustdoc-scrape-examples-remap/examples/ex.rs new file mode 100644 index 0000000000..1438fdba70 --- /dev/null +++ b/src/test/run-make/rustdoc-scrape-examples-remap/examples/ex.rs @@ -0,0 +1,4 @@ +fn main() { + foobar::b::foo(); + foobar::c::foo(); +} diff --git a/src/test/run-make/rustdoc-scrape-examples-remap/src/a.rs b/src/test/run-make/rustdoc-scrape-examples-remap/src/a.rs new file mode 100644 index 0000000000..b76b4321d6 --- /dev/null +++ b/src/test/run-make/rustdoc-scrape-examples-remap/src/a.rs @@ -0,0 +1 @@ +pub fn foo() {} diff --git a/src/test/run-make/rustdoc-scrape-examples-remap/src/lib.rs b/src/test/run-make/rustdoc-scrape-examples-remap/src/lib.rs new file mode 100644 index 0000000000..f525a4270d --- /dev/null +++ b/src/test/run-make/rustdoc-scrape-examples-remap/src/lib.rs @@ -0,0 +1,8 @@ +// @has foobar/b/fn.foo.html '//*[@class="scraped-example expanded"]' 'ex.rs' +// @has foobar/c/fn.foo.html '//*[@class="scraped-example expanded"]' 'ex.rs' + +#[path = "a.rs"] +pub mod b; + +#[path = "a.rs"] +pub mod c; diff --git a/src/test/rustdoc-gui/anchor-navigable.goml b/src/test/rustdoc-gui/anchor-navigable.goml new file mode 100644 index 0000000000..424c312233 --- /dev/null +++ b/src/test/rustdoc-gui/anchor-navigable.goml @@ -0,0 +1,11 @@ +// The `impl Foo` heading underneath `Implementations` has a § +// anchor to its left (used for linking to that heading). The anchor only shows +// up when hovering the `impl Foo`. This test ensures there's no gap between the +// anchor and the `impl Foo`. If there were a gap, this would cause an annoying +// problem: you hover `impl Foo` to see the anchor, then when you move your +// mouse to the left, the anchor disappears before you reach it. +goto: file://|DOC_PATH|/test_docs/struct.Foo.html +// We check that ".item-info" is bigger than its content. +move-cursor-to: ".impl" +assert-property: (".impl > a.anchor", {"offsetWidth": "9"}) +assert-css: (".impl > a.anchor", {"left": "-8px"}) diff --git a/src/test/rustdoc-gui/anchors.goml b/src/test/rustdoc-gui/anchors.goml new file mode 100644 index 0000000000..8910cbbbb2 --- /dev/null +++ b/src/test/rustdoc-gui/anchors.goml @@ -0,0 +1,74 @@ +// This test is to ensure that the anchors (`§`) have the expected color and position. +goto: file://|DOC_PATH|/test_docs/struct.HeavilyDocumentedStruct.html +show-text: true + +// This is needed to ensure that the text color is computed. +show-text: true + +// Set the theme to light. +local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"} +// We reload the page so the local storage settings are being used. +reload: + +assert-css: ("#toggle-all-docs", {"color": "rgb(0, 0, 0)"}) +assert-css: (".fqn .in-band a:nth-of-type(1)", {"color": "rgb(0, 0, 0)"}) +assert-css: (".fqn .in-band a:nth-of-type(2)", {"color": "rgb(173, 68, 142)"}) +assert-css: (".srclink", {"color": "rgb(0, 0, 0)"}) +assert-css: (".srclink", {"color": "rgb(0, 0, 0)"}) + +assert-css: ("#top-doc-prose-title", {"color": "rgb(0, 0, 0)"}) + +assert-css: (".sidebar a", {"color": "rgb(0, 0, 0)"}) +assert-css: (".in-band a", {"color": "rgb(0, 0, 0)"}) + +// We move the cursor over the "Implementations" title so the anchor is displayed. +move-cursor-to: "h2#implementations" +assert-css: ("h2#implementations a.anchor", {"color": "rgb(0, 0, 0)"}) + +// Same thing with the impl block title. +move-cursor-to: "#impl" +assert-css: ("#impl a.anchor", {"color": "rgb(0, 0, 0)"}) + +// Now we check the positions: only the first heading of the top doc comment should +// have a different position. +move-cursor-to: ".top-doc .docblock .section-header:first-child" +assert-css: ( + ".top-doc .docblock .section-header:first-child > a::before", + {"left": "-10px", "padding-right": "10px"} +) +// We also check that the heading itself has a different indent. +assert-css: (".top-doc .docblock .section-header:first-child", {"margin-left": "15px"}) + +move-cursor-to: ".top-doc .docblock .section-header:not(:first-child)" +assert-css: ( + ".top-doc .docblock .section-header:not(:first-child) > a::before", + {"left": "-25px", "padding-right": "10px"} +) +assert-css: (".top-doc .docblock .section-header:not(:first-child)", {"margin-left": "0px"}) + +// Now let's check some other docblock headings... +// First the impl block docs. +move-cursor-to: "#title-for-struct-impl-doc" +assert-css: ( + "#title-for-struct-impl-doc > a::before", + {"left": "-25px", "padding-right": "10px"} +) +assert-css: ("#title-for-struct-impl-doc", {"margin-left": "0px"}) +// Now a method docs. +move-cursor-to: "#title-for-struct-impl-item-doc" +assert-css: ( + "#title-for-struct-impl-item-doc > a::before", + {"left": "-25px", "padding-right": "10px"} +) +assert-css: ("#title-for-struct-impl-item-doc", {"margin-left": "0px"}) + +// Finally, we want to ensure that if the first element of the doc block isn't a heading, +// if there is a heading afterwards, it won't have the indent. +goto: file://|DOC_PATH|/test_docs/enum.WhoLetTheDogOut.html + +move-cursor-to: ".top-doc .docblock .section-header" +assert-css: ( + ".top-doc .docblock .section-header > a::before", + {"left": "-25px", "padding-right": "10px"} +) +assert-css: (".top-doc .docblock .section-header", {"margin-left": "0px"}) diff --git a/src/test/rustdoc-gui/basic.goml b/src/test/rustdoc-gui/basic.goml index 44fcec3393..239e51a912 100644 --- a/src/test/rustdoc-gui/basic.goml +++ b/src/test/rustdoc-gui/basic.goml @@ -1,4 +1,4 @@ goto: file://|DOC_PATH|/test_docs/index.html assert: ("#functions") goto: ./struct.Foo.html -assert: ("div.type-decl") +assert: ("div.item-decl") diff --git a/src/test/rustdoc-gui/check-code-blocks-margin.goml b/src/test/rustdoc-gui/check-code-blocks-margin.goml new file mode 100644 index 0000000000..2de4768285 --- /dev/null +++ b/src/test/rustdoc-gui/check-code-blocks-margin.goml @@ -0,0 +1,6 @@ +// This test ensures that the docblock elements have the appropriate left margin. +goto: file://|DOC_PATH|/test_docs/fn.foo.html +// The top docblock elements shouldn't have left margin... +assert-css: ("#main .docblock.item-decl", {"margin-left": "0px"}) +// ... but all the others should! +assert-css: ("#main .docblock:not(.item-decl)", {"margin-left": "24px"}) diff --git a/src/test/rustdoc-gui/docblock-code-block-line-number.goml b/src/test/rustdoc-gui/docblock-code-block-line-number.goml new file mode 100644 index 0000000000..7e6607b55e --- /dev/null +++ b/src/test/rustdoc-gui/docblock-code-block-line-number.goml @@ -0,0 +1,22 @@ +// Checks that the setting "line numbers" is working as expected. +goto: file://|DOC_PATH|/test_docs/fn.foo.html + +// We check that without this setting, there is no line number displayed. +assert-false: "pre.line-number" + +// We now set the setting to show the line numbers on code examples. +local-storage: {"rustdoc-line-numbers": "true" } +// We reload to make the line numbers appear. +reload: + +// We wait for them to be added into the DOM by the JS... +wait-for: "pre.line-number" +// If the test didn't fail, it means that it was found! +// Let's now check some CSS properties... +assert-css: ("pre.line-number", { + "margin": "0px", + "padding": "13px 8px", + "text-align": "right" +}) +// The first code block has two lines so let's check its `

` elements lists both of them.
+assert-text: ("pre.line-number", "1\n2")
diff --git a/src/test/rustdoc-gui/font-weight.goml b/src/test/rustdoc-gui/font-weight.goml
index d8411511c5..0459fd4b9c 100644
--- a/src/test/rustdoc-gui/font-weight.goml
+++ b/src/test/rustdoc-gui/font-weight.goml
@@ -1,6 +1,6 @@
 goto: file://|DOC_PATH|/lib2/struct.Foo.html
 // This test checks that the font weight is correctly applied.
-assert-css: ("//*[@class='docblock type-decl']//a[text()='Alias']", {"font-weight": "400"})
+assert-css: ("//*[@class='docblock item-decl']//a[text()='Alias']", {"font-weight": "400"})
 assert-css: ("//*[@class='structfield small-section-header']//a[text()='Alias']", {"font-weight": "400"})
 assert-css: ("#method\.a_method > .code-header", {"font-weight": "600"})
 assert-css: ("#associatedtype\.X > .code-header", {"font-weight": "600"})
@@ -16,7 +16,7 @@ goto: file://|DOC_PATH|/lib2/trait.Trait.html
 
 // This is a complex selector, so here's how it works:
 //
-// * //*[@class='docblock type-decl'] — selects element of any tag with classes docblock and type-decl
+// * //*[@class='docblock item-decl'] — selects element of any tag with classes docblock and item-decl
 // * /pre[@class='rust trait'] — selects immediate child with tag pre and classes rust and trait
 // * /code — selects immediate child with tag code
 // * /a[@class='constant'] — selects immediate child with tag a and class constant
@@ -25,8 +25,8 @@ goto: file://|DOC_PATH|/lib2/trait.Trait.html
 //
 // This uses '/parent::*' as a proxy for the style of the text node.
 // We can't just select the '' because intermediate tags could be added.
-assert-count: ("//*[@class='docblock type-decl']/pre[@class='rust trait']/code/a[@class='constant']//text()/parent::*", 1)
-assert-css: ("//*[@class='docblock type-decl']/pre[@class='rust trait']/code/a[@class='constant']//text()/parent::*", {"font-weight": "400"})
+assert-count: ("//*[@class='docblock item-decl']/pre[@class='rust trait']/code/a[@class='constant']//text()/parent::*", 1)
+assert-css: ("//*[@class='docblock item-decl']/pre[@class='rust trait']/code/a[@class='constant']//text()/parent::*", {"font-weight": "400"})
 
 assert-count: (".methods .type", 1)
 assert-css: (".methods .type", {"font-weight": "600"})
diff --git a/src/test/rustdoc-gui/header-size.goml b/src/test/rustdoc-gui/header-size.goml
deleted file mode 100644
index 4f45367fc7..0000000000
--- a/src/test/rustdoc-gui/header-size.goml
+++ /dev/null
@@ -1,99 +0,0 @@
-// This test check that headers (a) have the correct heading level, and (b) are the right size.
-// The sizes may change as design changes, but try to make sure a lower header is never bigger than
-// its parent headers.
-// Most of these sizes are set in CSS in `em` units, so here's a conversion chart based on our
-// default 16px font size:
-// 24px    1.5em
-// 22.4px  1.4em
-// 20.8px  1.3em
-// 18.4px  1.15em
-// 17.6px  1.1em
-// 16px    1em
-// 15.2px  0.95em  
-goto: file://|DOC_PATH|/test_docs/struct.HeavilyDocumentedStruct.html
-
-assert-css: ("h1.fqn", {"font-size": "24px"})
-
-assert-css: ("h2#top-doc-prose-title", {"font-size": "20.8px"})
-assert-css: ("h3#top-doc-prose-sub-heading", {"font-size": "18.4px"})
-assert-css: ("h4#top-doc-prose-sub-sub-heading", {"font-size": "16px"})
-
-assert-css: ("h2#fields", {"font-size": "22.4px"})
-assert-css: ("h3#title-for-field", {"font-size": "20.8px"})
-assert-css: ("h4#sub-heading-for-field", {"font-size": "16px"})
-
-assert-css: ("h2#implementations", {"font-size": "22.4px"})
-
-assert-css: ("#impl > h3.code-header", {"font-size": "16px"})
-assert-css: ("#method\.do_nothing > h4.code-header", {"font-size": "16px"})
-
-assert-css: ("h4#title-for-struct-impl-doc", {"font-size": "16px"})
-assert-css: ("h5#sub-heading-for-struct-impl-doc", {"font-size": "16px"})
-assert-css: ("h6#sub-sub-heading-for-struct-impl-doc", {"font-size": "15.2px"})
-
-assert-css: ("h5#title-for-struct-impl-item-doc", {"font-size": "16px"})
-assert-css: ("h6#sub-heading-for-struct-impl-item-doc", {"font-size": "15.2px"})
-assert-css: ("h6#sub-sub-heading-for-struct-impl-item-doc", {"font-size": "15.2px"})
-
-goto: file://|DOC_PATH|/test_docs/enum.HeavilyDocumentedEnum.html
-
-assert-css: ("h1.fqn", {"font-size": "24px"})
-
-assert-css: ("h2#top-doc-prose-title", {"font-size": "20.8px"})
-assert-css: ("h3#top-doc-prose-sub-heading", {"font-size": "18.4px"})
-assert-css: ("h4#top-doc-prose-sub-sub-heading", {"font-size": "16px"})
-
-assert-css: ("h2#variants", {"font-size": "22.4px"})
-
-assert-css: ("h3#none-prose-title", {"font-size": "20.8px"})
-assert-css: ("h4#none-prose-sub-heading", {"font-size": "16px"})
-
-assert-css: ("h3#wrapped-prose-title", {"font-size": "20.8px"})
-assert-css: ("h4#wrapped-prose-sub-heading", {"font-size": "16px"})
-
-assert-css: ("h4#wrapped0-prose-title", {"font-size": "16px"})
-assert-css: ("h5#wrapped0-prose-sub-heading", {"font-size": "16px"})
-
-assert-css: ("h4#structy-prose-title", {"font-size": "16px"})
-assert-css: ("h5#structy-prose-sub-heading", {"font-size": "16px"})
-
-assert-css: ("h2#implementations", {"font-size": "22.4px"})
-
-assert-css: ("#impl > h3.code-header", {"font-size": "16px"})
-assert-css: ("#method\.do_nothing > h4.code-header", {"font-size": "16px"})
-
-assert-css: ("h4#title-for-enum-impl-doc", {"font-size": "16px"})
-assert-css: ("h5#sub-heading-for-enum-impl-doc", {"font-size": "16px"})
-assert-css: ("h6#sub-sub-heading-for-enum-impl-doc", {"font-size": "15.2px"})
-
-assert-css: ("h5#title-for-enum-impl-item-doc", {"font-size": "16px"})
-assert-css: ("h6#sub-heading-for-enum-impl-item-doc", {"font-size": "15.2px"})
-assert-css: ("h6#sub-sub-heading-for-enum-impl-item-doc", {"font-size": "15.2px"})
-
-goto: file://|DOC_PATH|/test_docs/union.HeavilyDocumentedUnion.html
-
-assert-css: ("h1.fqn", {"font-size": "24px"})
-
-assert-css: ("h2#top-doc-prose-title", {"font-size": "20.8px"})
-assert-css: ("h3#top-doc-prose-sub-heading", {"font-size": "18.4px"})
-
-assert-css: ("h2#fields", {"font-size": "22.4px"})
-
-assert-css: ("h3#title-for-union-variant", {"font-size": "20.8px"})
-assert-css: ("h4#sub-heading-for-union-variant", {"font-size": "16px"})
-
-assert-css: ("h2#implementations", {"font-size": "22.4px"})
-
-assert-css: ("#impl > h3.code-header", {"font-size": "16px"})
-assert-css: ("h4#title-for-union-impl-doc", {"font-size": "16px"})
-assert-css: ("h5#sub-heading-for-union-impl-doc", {"font-size": "16px"})
-
-assert-css: ("h5#title-for-union-impl-item-doc", {"font-size": "16px"})
-assert-css: ("h6#sub-heading-for-union-impl-item-doc", {"font-size": "15.2px"})
-
-goto: file://|DOC_PATH|/test_docs/macro.heavily_documented_macro.html
-
-assert-css: ("h1.fqn", {"font-size": "24px"})
-
-assert-css: ("h2#top-doc-prose-title", {"font-size": "20.8px"})
-assert-css: ("h3#top-doc-prose-sub-heading", {"font-size": "18.4px"})
diff --git a/src/test/rustdoc-gui/headers-color.goml b/src/test/rustdoc-gui/headers-color.goml
index b5be31bd2c..03b10e3f78 100644
--- a/src/test/rustdoc-gui/headers-color.goml
+++ b/src/test/rustdoc-gui/headers-color.goml
@@ -17,6 +17,12 @@ assert-css: ("#impl", {"color": "rgb(197, 197, 197)", "background-color": "rgba(
 goto: file://|DOC_PATH|/test_docs/struct.Foo.html#method.must_use
 assert-css: ("#method\.must_use", {"color": "rgb(197, 197, 197)", "background-color": "rgba(255, 236, 164, 0.06)"}, ALL)
 
+goto: file://|DOC_PATH|/test_docs/index.html
+assert-css: (".small-section-header a", {"color": "rgb(197, 197, 197)"}, ALL)
+
+goto: file://|DOC_PATH|/test_docs/struct.HeavilyDocumentedStruct.html
+assert-css: (".section-header a", {"color": "rgb(57, 175, 215)"}, ALL)
+
 // Dark theme
 local-storage: {"rustdoc-theme": "dark", "rustdoc-preferred-dark-theme": "dark", "rustdoc-use-system-theme": "false"}
 goto: file://|DOC_PATH|/test_docs/struct.Foo.html
@@ -30,6 +36,12 @@ assert-css: ("#impl", {"color": "rgb(221, 221, 221)", "background-color": "rgb(7
 goto: file://|DOC_PATH|/test_docs/struct.Foo.html#method.must_use
 assert-css: ("#method\.must_use", {"color": "rgb(221, 221, 221)", "background-color": "rgb(73, 74, 61)"}, ALL)
 
+goto: file://|DOC_PATH|/test_docs/index.html
+assert-css: (".small-section-header a", {"color": "rgb(221, 221, 221)"}, ALL)
+
+goto: file://|DOC_PATH|/test_docs/struct.HeavilyDocumentedStruct.html
+assert-css: (".section-header a", {"color": "rgb(210, 153, 29)"}, ALL)
+
 // Light theme
 local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"}
 reload:
@@ -44,3 +56,9 @@ assert-css: ("#impl", {"color": "rgb(0, 0, 0)", "background-color": "rgb(253, 25
 
 goto: file://|DOC_PATH|/test_docs/struct.Foo.html#method.must_use
 assert-css: ("#method\.must_use", {"color": "rgb(0, 0, 0)", "background-color": "rgb(253, 255, 211)"}, ALL)
+
+goto: file://|DOC_PATH|/test_docs/index.html
+assert-css: (".small-section-header a", {"color": "rgb(0, 0, 0)"}, ALL)
+
+goto: file://|DOC_PATH|/test_docs/struct.HeavilyDocumentedStruct.html
+assert-css: (".section-header a", {"color": "rgb(56, 115, 173)"}, ALL)
diff --git a/src/test/rustdoc-gui/headings.goml b/src/test/rustdoc-gui/headings.goml
new file mode 100644
index 0000000000..87c512468e
--- /dev/null
+++ b/src/test/rustdoc-gui/headings.goml
@@ -0,0 +1,156 @@
+// This test checks that headers (a) have the correct heading level, (b) are the right size,
+// and (c) have the correct underlining (or absence of underlining).
+// The sizes may change as design changes, but try to make sure a lower header is never bigger than
+// its parent headers. Also make sure lower headers don't have underlines when their parents lack
+// an underline.
+// Most of these sizes are set in CSS in `em` units, so here's a conversion chart based on our
+// default 16px font size:
+// 24px    1.5em
+// 22.4px  1.4em
+// 20.8px  1.3em
+// 18.4px  1.15em
+// 17.6px  1.1em
+// 16px    1em
+// 15.2px  0.95em  
+goto: file://|DOC_PATH|/test_docs/struct.HeavilyDocumentedStruct.html
+
+assert-css: ("h1.fqn", {"font-size": "24px"})
+assert-css: ("h1.fqn", {"border-bottom-width": "1px"})
+
+assert-css: ("h2#top-doc-prose-title", {"font-size": "20.8px"})
+assert-css: ("h2#top-doc-prose-title", {"border-bottom-width": "1px"})
+assert-css: ("h3#top-doc-prose-sub-heading", {"font-size": "18.4px"})
+assert-css: ("h3#top-doc-prose-sub-heading", {"border-bottom-width": "1px"})
+assert-css: ("h4#top-doc-prose-sub-sub-heading", {"font-size": "17.6px"})
+assert-css: ("h4#top-doc-prose-sub-sub-heading", {"border-bottom-width": "1px"})
+
+assert-css: ("h2#fields", {"font-size": "22.4px"})
+assert-css: ("h2#fields", {"border-bottom-width": "1px"})
+assert-css: ("h3#title-for-field", {"font-size": "20.8px"})
+assert-css: ("h3#title-for-field", {"border-bottom-width": "0px"})
+assert-css: ("h4#sub-heading-for-field", {"font-size": "16px"})
+assert-css: ("h4#sub-heading-for-field", {"border-bottom-width": "0px"})
+
+assert-css: ("h2#implementations", {"font-size": "22.4px"})
+assert-css: ("h2#implementations", {"border-bottom-width": "1px"})
+
+assert-css: ("#impl > h3.code-header", {"font-size": "17.6px"})
+assert-css: ("#impl > h3.code-header", {"border-bottom-width": "0px"})
+assert-css: ("#method\.do_nothing > h4.code-header", {"font-size": "16px"})
+assert-css: ("#method\.do_nothing > h4.code-header", {"border-bottom-width": "0px"})
+
+assert-css: ("h4#title-for-struct-impl-doc", {"font-size": "16px"})
+assert-css: ("h4#title-for-struct-impl-doc", {"border-bottom-width": "0px"})
+assert-css: ("h5#sub-heading-for-struct-impl-doc", {"font-size": "16px"})
+assert-css: ("h5#sub-heading-for-struct-impl-doc", {"border-bottom-width": "0px"})
+assert-css: ("h6#sub-sub-heading-for-struct-impl-doc", {"font-size": "15.2px"})
+assert-css: ("h6#sub-sub-heading-for-struct-impl-doc", {"border-bottom-width": "0px"})
+
+assert-css: ("h5#title-for-struct-impl-item-doc", {"font-size": "16px"})
+assert-css: ("h5#title-for-struct-impl-item-doc", {"border-bottom-width": "0px"})
+assert-css: ("h6#sub-heading-for-struct-impl-item-doc", {"font-size": "15.2px"})
+assert-css: ("h6#sub-heading-for-struct-impl-item-doc", {"border-bottom-width": "0px"})
+assert-css: ("h6#sub-sub-heading-for-struct-impl-item-doc", {"font-size": "15.2px"})
+
+goto: file://|DOC_PATH|/test_docs/enum.HeavilyDocumentedEnum.html
+
+assert-css: ("h1.fqn", {"font-size": "24px"})
+assert-css: ("h1.fqn", {"border-bottom-width": "1px"})
+
+assert-css: ("h2#top-doc-prose-title", {"font-size": "20.8px"})
+assert-css: ("h2#top-doc-prose-title", {"border-bottom-width": "1px"})
+assert-css: ("h3#top-doc-prose-sub-heading", {"font-size": "18.4px"})
+assert-css: ("h3#top-doc-prose-sub-heading", {"border-bottom-width": "1px"})
+assert-css: ("h4#top-doc-prose-sub-sub-heading", {"font-size": "17.6px"})
+assert-css: ("h4#top-doc-prose-sub-sub-heading", {"border-bottom-width": "1px"})
+
+assert-css: ("h2#variants", {"font-size": "22.4px"})
+assert-css: ("h2#variants", {"border-bottom-width": "1px"})
+
+assert-css: ("h4#none-prose-title", {"font-size": "16px"})
+assert-css: ("h4#none-prose-title", {"border-bottom-width": "0px"})
+assert-css: ("h5#none-prose-sub-heading", {"font-size": "16px"})
+assert-css: ("h5#none-prose-sub-heading", {"border-bottom-width": "0px"})
+
+assert-css: ("h4#wrapped-prose-title", {"font-size": "16px"})
+assert-css: ("h4#wrapped-prose-title", {"border-bottom-width": "0px"})
+assert-css: ("h5#wrapped-prose-sub-heading", {"font-size": "16px"})
+assert-css: ("h5#wrapped-prose-sub-heading", {"border-bottom-width": "0px"})
+
+assert-css: ("h5#wrapped0-prose-title", {"font-size": "16px"})
+assert-css: ("h5#wrapped0-prose-title", {"border-bottom-width": "0px"})
+assert-css: ("h6#wrapped0-prose-sub-heading", {"font-size": "15.2px"})
+assert-css: ("h6#wrapped0-prose-sub-heading", {"border-bottom-width": "0px"})
+
+assert-css: ("h5#structy-prose-title", {"font-size": "16px"})
+assert-css: ("h5#structy-prose-title", {"border-bottom-width": "0px"})
+assert-css: ("h6#structy-prose-sub-heading", {"font-size": "15.2px"})
+assert-css: ("h6#structy-prose-sub-heading", {"border-bottom-width": "0px"})
+
+assert-css: ("h2#implementations", {"font-size": "22.4px"})
+assert-css: ("h2#implementations", {"border-bottom-width": "1px"})
+
+assert-css: ("#impl > h3.code-header", {"font-size": "17.6px"})
+assert-css: ("#impl > h3.code-header", {"border-bottom-width": "0px"})
+assert-css: ("#method\.do_nothing > h4.code-header", {"font-size": "16px"})
+assert-css: ("#method\.do_nothing > h4.code-header", {"border-bottom-width": "0px"})
+
+assert-css: ("h4#title-for-enum-impl-doc", {"font-size": "16px"})
+assert-css: ("h4#title-for-enum-impl-doc", {"border-bottom-width": "0px"})
+assert-css: ("h5#sub-heading-for-enum-impl-doc", {"font-size": "16px"})
+assert-css: ("h5#sub-heading-for-enum-impl-doc", {"border-bottom-width": "0px"})
+assert-css: ("h6#sub-sub-heading-for-enum-impl-doc", {"font-size": "15.2px"})
+assert-css: ("h6#sub-sub-heading-for-enum-impl-doc", {"border-bottom-width": "0px"})
+
+assert-css: ("h5#title-for-enum-impl-item-doc", {"font-size": "16px"})
+assert-css: ("h5#title-for-enum-impl-item-doc", {"border-bottom-width": "0px"})
+assert-css: ("h6#sub-heading-for-enum-impl-item-doc", {"font-size": "15.2px"})
+assert-css: ("h6#sub-heading-for-enum-impl-item-doc", {"border-bottom-width": "0px"})
+assert-css: ("h6#sub-sub-heading-for-enum-impl-item-doc", {"font-size": "15.2px"})
+assert-css: ("h6#sub-sub-heading-for-enum-impl-item-doc", {"border-bottom-width": "0px"})
+
+assert-text: (".sidebar .others h3", "Modules")
+assert-css: (".sidebar .others h3", {"border-bottom-width": "1px"}, ALL)
+
+goto: file://|DOC_PATH|/test_docs/union.HeavilyDocumentedUnion.html
+
+assert-css: ("h1.fqn", {"font-size": "24px"})
+assert-css: ("h1.fqn", {"border-bottom-width": "1px"})
+
+assert-css: ("h2#top-doc-prose-title", {"font-size": "20.8px"})
+assert-css: ("h2#top-doc-prose-title", {"border-bottom-width": "1px"})
+assert-css: ("h3#top-doc-prose-sub-heading", {"font-size": "18.4px"})
+assert-css: ("h3#top-doc-prose-sub-heading", {"border-bottom-width": "1px"})
+
+assert-css: ("h2#fields", {"font-size": "22.4px"})
+assert-css: ("h2#fields", {"border-bottom-width": "1px"})
+
+assert-css: ("h3#title-for-union-variant", {"font-size": "20.8px"})
+assert-css: ("h3#title-for-union-variant", {"border-bottom-width": "0px"})
+assert-css: ("h4#sub-heading-for-union-variant", {"font-size": "16px"})
+assert-css: ("h4#sub-heading-for-union-variant", {"border-bottom-width": "0px"})
+
+assert-css: ("h2#implementations", {"font-size": "22.4px"})
+assert-css: ("h2#implementations", {"border-bottom-width": "1px"})
+
+assert-css: ("#impl > h3.code-header", {"font-size": "17.6px"})
+assert-css: ("#impl > h3.code-header", {"border-bottom-width": "0px"})
+assert-css: ("h4#title-for-union-impl-doc", {"font-size": "16px"})
+assert-css: ("h4#title-for-union-impl-doc", {"border-bottom-width": "0px"})
+assert-css: ("h5#sub-heading-for-union-impl-doc", {"font-size": "16px"})
+assert-css: ("h5#sub-heading-for-union-impl-doc", {"border-bottom-width": "0px"})
+
+assert-css: ("h5#title-for-union-impl-item-doc", {"font-size": "16px"})
+assert-css: ("h5#title-for-union-impl-item-doc", {"border-bottom-width": "0px"})
+assert-css: ("h6#sub-heading-for-union-impl-item-doc", {"font-size": "15.2px"})
+assert-css: ("h6#sub-heading-for-union-impl-item-doc", {"border-bottom-width": "0px"})
+
+goto: file://|DOC_PATH|/test_docs/macro.heavily_documented_macro.html
+
+assert-css: ("h1.fqn", {"font-size": "24px"})
+assert-css: ("h1.fqn", {"border-bottom-width": "1px"})
+
+assert-css: ("h2#top-doc-prose-title", {"font-size": "20.8px"})
+assert-css: ("h2#top-doc-prose-title", {"border-bottom-width": "1px"})
+assert-css: ("h3#top-doc-prose-sub-heading", {"font-size": "18.4px"})
+assert-css: ("h3#top-doc-prose-sub-heading", {"border-bottom-width": "1px"})
diff --git a/src/test/rustdoc-gui/item-info-width.goml b/src/test/rustdoc-gui/item-info-width.goml
index 44b79e6091..cdc00d3411 100644
--- a/src/test/rustdoc-gui/item-info-width.goml
+++ b/src/test/rustdoc-gui/item-info-width.goml
@@ -4,4 +4,4 @@ goto: file://|DOC_PATH|/lib2/struct.Foo.html
 size: (1100, 800)
 // We check that ".item-info" is bigger than its content.
 assert-css: (".item-info", {"width": "807px"})
-assert-css: (".item-info .stab", {"width": "343px"})
+assert-css: (".item-info .stab", {"width": "341px"})
diff --git a/src/test/rustdoc-gui/javascript-disabled.goml b/src/test/rustdoc-gui/javascript-disabled.goml
new file mode 100644
index 0000000000..1693f7b645
--- /dev/null
+++ b/src/test/rustdoc-gui/javascript-disabled.goml
@@ -0,0 +1,6 @@
+// When JavaScript is disabled, we hide the search bar, because it
+// can't be used without JS.
+javascript: false
+
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html
+assert-css: (".sub", {"display": "none"})
diff --git a/src/test/rustdoc-gui/module-items-font.goml b/src/test/rustdoc-gui/module-items-font.goml
index ab595d2801..0316172ee1 100644
--- a/src/test/rustdoc-gui/module-items-font.goml
+++ b/src/test/rustdoc-gui/module-items-font.goml
@@ -1,23 +1,23 @@
 // This test checks that the correct font is used on module items (in index.html pages).
 goto: file://|DOC_PATH|/test_docs/index.html
-assert-css: (".item-table .module-item a", {"font-family": '"Fira Sans", Arial, sans-serif'}, ALL)
-assert-css: (".item-table .docblock-short", {"font-family": '"Source Serif 4", "Noto Sans KR", serif'}, ALL)
+assert-css: (".item-table .module-item a", {"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'}, ALL)
+assert-css: (".item-table .docblock-short", {"font-family": '"Source Serif 4", NanumBarunGothic, serif'}, ALL)
 
 // modules
-assert-css: ("#modules + .item-table .item-left a", {"font-family": '"Fira Sans", Arial, sans-serif'})
-assert-css: ("#modules + .item-table .item-right.docblock-short", {"font-family": '"Source Serif 4", "Noto Sans KR", serif'})
+assert-css: ("#modules + .item-table .item-left a", {"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'})
+assert-css: ("#modules + .item-table .item-right.docblock-short", {"font-family": '"Source Serif 4", NanumBarunGothic, serif'})
 // structs
-assert-css: ("#structs + .item-table .item-left a", {"font-family": '"Fira Sans", Arial, sans-serif'})
-assert-css: ("#structs + .item-table .item-right.docblock-short", {"font-family": '"Source Serif 4", "Noto Sans KR", serif'})
+assert-css: ("#structs + .item-table .item-left a", {"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'})
+assert-css: ("#structs + .item-table .item-right.docblock-short", {"font-family": '"Source Serif 4", NanumBarunGothic, serif'})
 // enums
-assert-css: ("#enums + .item-table .item-left a", {"font-family": '"Fira Sans", Arial, sans-serif'})
-assert-css: ("#enums + .item-table .item-right.docblock-short", {"font-family": '"Source Serif 4", "Noto Sans KR", serif'})
+assert-css: ("#enums + .item-table .item-left a", {"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'})
+assert-css: ("#enums + .item-table .item-right.docblock-short", {"font-family": '"Source Serif 4", NanumBarunGothic, serif'})
 // traits
-assert-css: ("#traits + .item-table .item-left a", {"font-family": '"Fira Sans", Arial, sans-serif'})
-assert-css: ("#traits + .item-table .item-right.docblock-short", {"font-family": '"Source Serif 4", "Noto Sans KR", serif'})
+assert-css: ("#traits + .item-table .item-left a", {"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'})
+assert-css: ("#traits + .item-table .item-right.docblock-short", {"font-family": '"Source Serif 4", NanumBarunGothic, serif'})
 // functions
-assert-css: ("#functions + .item-table .item-left a", {"font-family": '"Fira Sans", Arial, sans-serif'})
-assert-css: ("#functions + .item-table .item-right.docblock-short", {"font-family": '"Source Serif 4", "Noto Sans KR", serif'})
+assert-css: ("#functions + .item-table .item-left a", {"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'})
+assert-css: ("#functions + .item-table .item-right.docblock-short", {"font-family": '"Source Serif 4", NanumBarunGothic, serif'})
 // keywords
-assert-css: ("#keywords + .item-table .item-left a", {"font-family": '"Fira Sans", Arial, sans-serif'})
-assert-css: ("#keywords + .item-table .item-right.docblock-short", {"font-family": '"Source Serif 4", "Noto Sans KR", serif'})
+assert-css: ("#keywords + .item-table .item-left a", {"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'})
+assert-css: ("#keywords + .item-table .item-right.docblock-short", {"font-family": '"Source Serif 4", NanumBarunGothic, serif'})
diff --git a/src/test/rustdoc-gui/overflow-tooltip-information.goml b/src/test/rustdoc-gui/overflow-tooltip-information.goml
new file mode 100644
index 0000000000..7ef85a4c44
--- /dev/null
+++ b/src/test/rustdoc-gui/overflow-tooltip-information.goml
@@ -0,0 +1,8 @@
+// The goal of this test is to ensure that the tooltip `.information` class doesn't
+// have overflow and max-width CSS rules set because they create a bug in firefox on
+// mac. For more information: https://github.com/rust-lang/rust/issues/89185
+goto: file://|DOC_PATH|/test_docs/fn.foo.html
+assert-css: (".docblock > .information", {
+    "overflow-x": "visible",
+    "max-width": "none"
+}, ALL)
diff --git a/src/test/rustdoc-gui/search-filter.goml b/src/test/rustdoc-gui/search-filter.goml
index a098dbd9f1..7a8f8ca531 100644
--- a/src/test/rustdoc-gui/search-filter.goml
+++ b/src/test/rustdoc-gui/search-filter.goml
@@ -1,9 +1,11 @@
 goto: file://|DOC_PATH|/test_docs/index.html
+show-text: true
 write: (".search-input", "test")
 // Waiting for the search results to appear...
 wait-for: "#titles"
 assert-text: ("#results .externcrate", "test_docs")
-text: (".search-input", "")
+
+goto: file://|DOC_PATH|/test_docs/index.html
 // We now want to change the crate filter.
 click: "#crate-search"
 // We select "lib2" option then press enter to change the filter.
diff --git a/src/test/rustdoc-gui/sidebar-macro-reexport.goml b/src/test/rustdoc-gui/sidebar-macro-reexport.goml
new file mode 100644
index 0000000000..a3a62fe544
--- /dev/null
+++ b/src/test/rustdoc-gui/sidebar-macro-reexport.goml
@@ -0,0 +1,5 @@
+// This test ensures that the reexport of a macro doesn't make the original macro
+// displayed twice in the sidebar.
+goto: file://|DOC_PATH|/test_docs/macro.repro.html
+wait-for: ".sidebar-elems .macro .macro"
+assert-count: ("//*[@class='sidebar-elems']//*[@class='block macro']//a[text()='repro']", 1)
diff --git a/src/test/rustdoc-gui/sidebar.goml b/src/test/rustdoc-gui/sidebar.goml
index eacc9f6c15..f9c707f81e 100644
--- a/src/test/rustdoc-gui/sidebar.goml
+++ b/src/test/rustdoc-gui/sidebar.goml
@@ -4,17 +4,17 @@ assert-text: (".sidebar > .location", "Crate test_docs")
 assert-count: (".sidebar .location", 1)
 assert-text: (".sidebar-elems > #all-types", "See all test_docs's items")
 // We check that we have the crates list and that the "current" on is "test_docs".
-assert-text: (".sidebar-elems > .crate > ul > li > a.current", "test_docs")
+assert-text: (".sidebar-elems .crate > ul > li > a.current", "test_docs")
 // And we're also supposed to have the list of items in the current module.
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(1)", "Modules")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(2)", "Macros")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(3)", "Structs")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(4)", "Enums")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(5)", "Traits")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(6)", "Functions")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(7)", "Type Definitions")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(8)", "Unions")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(9)", "Keywords")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(1)", "Modules")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(2)", "Macros")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(3)", "Structs")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(4)", "Enums")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(5)", "Traits")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(6)", "Functions")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(7)", "Type Definitions")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(8)", "Unions")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(9)", "Keywords")
 assert-text: ("#structs + .item-table .item-left > a", "Foo")
 click: "#structs + .item-table .item-left > a"
 
@@ -24,13 +24,13 @@ assert-count: (".sidebar .location", 2)
 assert-false: ".sidebar-elems > .crate"
 // We now go back to the crate page to click on the "lib2" crate link.
 goto: file://|DOC_PATH|/test_docs/index.html
-click: ".sidebar-elems > .crate > ul > li:first-child > a"
+click: ".sidebar-elems .crate > ul > li:first-child > a"
 
 // PAGE: lib2/index.html
 goto: file://|DOC_PATH|/lib2/index.html
 assert-text: (".sidebar > .location", "Crate lib2")
 // We check that we have the crates list and that the "current" on is now "lib2".
-assert-text: (".sidebar-elems > .crate > ul > li > a.current", "lib2")
+assert-text: (".sidebar-elems .crate > ul > li > a.current", "lib2")
 // We now go to the "foobar" function page.
 assert-text: (".sidebar-elems > .items > ul > li:nth-child(1)", "Modules")
 assert-text: (".sidebar-elems > .items > ul > li:nth-child(2)", "Structs")
@@ -57,6 +57,6 @@ assert-false: ".sidebar-elems > .crate"
 goto: ./sub_module/sub_sub_module/index.html
 assert-text: (".sidebar > .location", "Module sub_sub_module")
 // We check that we don't have the crate list.
-assert-false: ".sidebar-elems > .crate"
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(1)", "Functions")
+assert-false: ".sidebar-elems .crate"
+assert-text: (".sidebar-elems .items > ul > li:nth-child(1)", "Functions")
 assert-text: ("#functions + .item-table .item-left > a", "foo")
diff --git a/src/test/rustdoc-gui/src/lib2/lib.rs b/src/test/rustdoc-gui/src/lib2/lib.rs
index d5835b78d2..79354ec874 100644
--- a/src/test/rustdoc-gui/src/lib2/lib.rs
+++ b/src/test/rustdoc-gui/src/lib2/lib.rs
@@ -22,6 +22,8 @@ pub struct Foo {
 }
 
 impl Foo {
+    /// Some documentation
+    /// # A Heading
     pub fn a_method(&self) {}
 }
 
@@ -84,3 +86,20 @@ pub mod summary_table {
     /// | content | content |
     pub struct Foo;
 }
+
+pub mod too_long {
+pub type ReallyLongTypeNameLongLongLong = Option *const u8>;
+
+pub const ReallyLongTypeNameLongLongLongConstBecauseWhyNotAConstRightGigaGigaSupraLong: u32 = 0;
+
+pub struct SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName {
+    pub a: u32,
+}
+
+impl SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName {
+    /// ```
+    /// let x = SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName { a: 0 };
+    /// ```
+        pub fn foo(&self) {}
+    }
+}
diff --git a/src/test/rustdoc-gui/src/test_docs/lib.rs b/src/test/rustdoc-gui/src/test_docs/lib.rs
index 89871952c1..9b37703dde 100644
--- a/src/test/rustdoc-gui/src/test_docs/lib.rs
+++ b/src/test/rustdoc-gui/src/test_docs/lib.rs
@@ -2,7 +2,7 @@
 //! documentation generated so we can test each different features.
 
 #![crate_name = "test_docs"]
-#![feature(doc_keyword)]
+#![feature(rustdoc_internals)]
 #![feature(doc_cfg)]
 
 use std::convert::AsRef;
@@ -12,6 +12,7 @@ use std::fmt;
 ///
 /// ```
 /// println!("nothing fancy");
+/// println!("but with two lines!");
 /// ```
 ///
 /// A failing to compile one:
@@ -46,6 +47,8 @@ impl AsRef for Foo {
 }
 
 /// Just a normal enum.
+///
+/// # title!
 #[doc(alias = "ThisIsAnAlias")]
 pub enum WhoLetTheDogOut {
     /// Woof!
@@ -124,6 +127,13 @@ pub mod huge_amount_of_consts {
 /// Very long code text `hereIgoWithLongTextBecauseWhyNotAndWhyWouldntI`.
 pub mod long_code_block {}
 
+#[macro_export]
+macro_rules! repro {
+    () => {};
+}
+
+pub use crate::repro as repro2;
+
 /// # Top-doc Prose title
 ///
 /// Text below title.
diff --git a/src/test/rustdoc-gui/toggle-click-deadspace.goml b/src/test/rustdoc-gui/toggle-click-deadspace.goml
new file mode 100644
index 0000000000..7bc3c56315
--- /dev/null
+++ b/src/test/rustdoc-gui/toggle-click-deadspace.goml
@@ -0,0 +1,12 @@
+// This test ensures that clicking on a method summary, but not on the "[-]",
+// doesn't toggle the 
. +goto: file://|DOC_PATH|/lib2/struct.Foo.html +assert-attribute: (".impl-items .rustdoc-toggle", {"open": ""}) +click: "h4.code-header" // This is the position of "pub" in "pub fn a_method" +assert-attribute: (".impl-items .rustdoc-toggle", {"open": ""}) +click: ".impl-items .rustdoc-toggle summary::before" // This is the position of "[-]" next to that pub fn. +assert-attribute-false: (".impl-items .rustdoc-toggle", {"open": ""}) + +// Click the "Trait" part of "impl Trait" and verify it navigates. +click: "#impl-Trait h3 a:first-of-type" +assert-text: (".fqn .in-band", "Trait lib2::Trait") diff --git a/src/test/rustdoc-gui/type-declation-overflow.goml b/src/test/rustdoc-gui/type-declation-overflow.goml index 0a316e220a..63ab867fb1 100644 --- a/src/test/rustdoc-gui/type-declation-overflow.goml +++ b/src/test/rustdoc-gui/type-declation-overflow.goml @@ -1,8 +1,25 @@ -// This test ensures that the type declaration content overflow is handled inside the
 directly.
+// This test ensures that the items declaration content overflow is handled inside the 
 directly.
 goto: file://|DOC_PATH|/lib2/long_trait/trait.ALongNameBecauseItHelpsTestingTheCurrentProblem.html
 // We set a fixed size so there is no chance of "random" resize.
 size: (1100, 800)
 // Logically, the  scroll width should be the width of the window.
 assert-property: ("body", {"scrollWidth": "1100"})
 // However, since there is overflow in the type declaration, its scroll width is bigger.
-assert-property: (".type-decl pre", {"scrollWidth": "1324"})
+assert-property: (".item-decl pre", {"scrollWidth": "1324"})
+
+// We now make the same check on type declaration...
+goto: file://|DOC_PATH|/lib2/too_long/type.ReallyLongTypeNameLongLongLong.html
+assert-property: ("body", {"scrollWidth": "1100"})
+// We now check that the section width hasn't grown because of it.
+assert-property: ("#main", {"scrollWidth": "840"})
+// And now checking that it has scrollable content.
+assert-property: (".item-decl pre", {"scrollWidth": "1103"})
+
+// ... and constant.
+// On a sidenote, it also checks that the (very) long title isn't changing the docblock width.
+goto: file://|DOC_PATH|/lib2/too_long/constant.ReallyLongTypeNameLongLongLongConstBecauseWhyNotAConstRightGigaGigaSupraLong.html
+assert-property: ("body", {"scrollWidth": "1100"})
+// We now check that the section width hasn't grown because of it.
+assert-property: ("#main", {"scrollWidth": "840"})
+// And now checking that it has scrollable content.
+assert-property: (".item-decl pre", {"scrollWidth": "950"})
diff --git a/src/test/rustdoc-js/generics.js b/src/test/rustdoc-js/generics.js
index 49a80ae236..63a9ad5381 100644
--- a/src/test/rustdoc-js/generics.js
+++ b/src/test/rustdoc-js/generics.js
@@ -1,10 +1,12 @@
 // exact-check
 
 const QUERY = [
-  '"R

"', - '"P"', - 'P', - '"ExtraCreditStructMulti"', + '"R

"', + '"P"', + 'P', + '"ExtraCreditStructMulti"', + 'TraitCat', + 'TraitDog', ]; const EXPECTED = [ @@ -30,9 +32,11 @@ const EXPECTED = [ { 'returned': [ { 'path': 'generics', 'name': 'alef' }, + { 'path': 'generics', 'name': 'bet' }, ], 'in_args': [ { 'path': 'generics', 'name': 'alpha' }, + { 'path': 'generics', 'name': 'beta' }, ], }, { @@ -41,4 +45,14 @@ const EXPECTED = [ ], 'returned': [], }, + { + 'in_args': [ + { 'path': 'generics', 'name': 'gamma' }, + ], + }, + { + 'in_args': [ + { 'path': 'generics', 'name': 'gamma' }, + ], + }, ]; diff --git a/src/test/rustdoc-js/generics.rs b/src/test/rustdoc-js/generics.rs index a0dc086e9f..5e11a6d601 100644 --- a/src/test/rustdoc-js/generics.rs +++ b/src/test/rustdoc-js/generics.rs @@ -19,3 +19,8 @@ pub fn extracreditlabhomework( pub fn redherringmatchforextracredit( _param: ExtraCreditStructMulti ) { loop {} } + +pub trait TraitCat {} +pub trait TraitDog {} + +pub fn gamma(t: T) {} diff --git a/src/test/rustdoc-json/primitive.rs b/src/test/rustdoc-json/primitive.rs index 3a7d6d18c1..b84c2f7c6a 100644 --- a/src/test/rustdoc-json/primitive.rs +++ b/src/test/rustdoc-json/primitive.rs @@ -1,6 +1,6 @@ // edition:2018 -#![feature(doc_primitive)] +#![feature(rustdoc_internals)] #[doc(primitive = "usize")] mod usize {} diff --git a/src/test/rustdoc-ui/auxiliary/empty-fn.rs b/src/test/rustdoc-ui/auxiliary/empty-fn.rs new file mode 100644 index 0000000000..877810f15d --- /dev/null +++ b/src/test/rustdoc-ui/auxiliary/empty-fn.rs @@ -0,0 +1,3 @@ +// no-prefer-dynamic +#![crate_type = "lib"] +pub fn empty() {} diff --git a/src/test/rustdoc-ui/coverage/exotic.rs b/src/test/rustdoc-ui/coverage/exotic.rs index 18f2014d9e..72b70d6980 100644 --- a/src/test/rustdoc-ui/coverage/exotic.rs +++ b/src/test/rustdoc-ui/coverage/exotic.rs @@ -1,8 +1,7 @@ // compile-flags:-Z unstable-options --show-coverage // check-pass -#![feature(doc_keyword)] -#![feature(doc_primitive)] +#![feature(rustdoc_internals)] //! the features only used in std also have entries in the table, so make sure those get pulled out //! properly as well diff --git a/src/test/rustdoc-ui/display-output.rs b/src/test/rustdoc-ui/display-output.rs index 5e390029dc..30b32c511b 100644 --- a/src/test/rustdoc-ui/display-output.rs +++ b/src/test/rustdoc-ui/display-output.rs @@ -1,9 +1,15 @@ +// Test that `--show-output` has an effect and `allow(unused)` can be overriden. + // check-pass -// compile-flags:-Zunstable-options --display-doctest-warnings --test +// edition:2018 +// compile-flags:--test --test-args=--show-output // normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR" // normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" /// ``` +/// #![warn(unused)] /// let x = 12; +/// +/// fn foo(x: &std::fmt::Display) {} /// ``` pub fn foo() {} diff --git a/src/test/rustdoc-ui/display-output.stdout b/src/test/rustdoc-ui/display-output.stdout index 00467b9359..f76dec1c85 100644 --- a/src/test/rustdoc-ui/display-output.stdout +++ b/src/test/rustdoc-ui/display-output.stdout @@ -1,24 +1,58 @@ running 1 test -test $DIR/display-output.rs - foo (line 6) ... ok +test $DIR/display-output.rs - foo (line 9) ... ok successes: ----- $DIR/display-output.rs - foo (line 6) stdout ---- +---- $DIR/display-output.rs - foo (line 9) stdout ---- +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/display-output.rs:13:12 + | +LL | fn foo(x: &std::fmt::Display) {} + | ^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn std::fmt::Display` + | + = note: `#[warn(bare_trait_objects)]` on by default + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see + warning: unused variable: `x` - --> $DIR/display-output.rs:7:5 + --> $DIR/display-output.rs:11:5 | LL | let x = 12; | ^ help: if this is intentional, prefix it with an underscore: `_x` | - = note: `#[warn(unused_variables)]` on by default +note: the lint level is defined here + --> $DIR/display-output.rs:9:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` + +warning: unused variable: `x` + --> $DIR/display-output.rs:13:8 + | +LL | fn foo(x: &std::fmt::Display) {} + | ^ help: if this is intentional, prefix it with an underscore: `_x` + +warning: function is never used: `foo` + --> $DIR/display-output.rs:13:4 + | +LL | fn foo(x: &std::fmt::Display) {} + | ^^^ + | +note: the lint level is defined here + --> $DIR/display-output.rs:9:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(dead_code)]` implied by `#[warn(unused)]` -warning: 1 warning emitted +warning: 4 warnings emitted successes: - $DIR/display-output.rs - foo (line 6) + $DIR/display-output.rs - foo (line 9) test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME diff --git a/src/test/rustdoc-ui/doc-without-codeblock.rs b/src/test/rustdoc-ui/doc-without-codeblock.rs index 6812a45415..315fca1958 100644 --- a/src/test/rustdoc-ui/doc-without-codeblock.rs +++ b/src/test/rustdoc-ui/doc-without-codeblock.rs @@ -11,3 +11,12 @@ pub mod foo { //~^ ERROR missing code example in this documentation pub fn bar() {} } + +// This impl is here to ensure the lint isn't emitted for foreign traits implementations. +impl std::ops::Neg for Foo { + type Output = Self; + + fn neg(self) -> Self::Output { + Self + } +} diff --git a/src/test/rustdoc-ui/doc-without-codeblock.stderr b/src/test/rustdoc-ui/doc-without-codeblock.stderr index aac537e978..1c13804416 100644 --- a/src/test/rustdoc-ui/doc-without-codeblock.stderr +++ b/src/test/rustdoc-ui/doc-without-codeblock.stderr @@ -6,7 +6,7 @@ LL | | LL | | /// Some docs. LL | | ... | -LL | | pub fn bar() {} +LL | | } LL | | } | |_^ | diff --git a/src/test/rustdoc-ui/failed-doctest-extra-semicolon-on-item.rs b/src/test/rustdoc-ui/failed-doctest-extra-semicolon-on-item.rs new file mode 100644 index 0000000000..16d737106e --- /dev/null +++ b/src/test/rustdoc-ui/failed-doctest-extra-semicolon-on-item.rs @@ -0,0 +1,18 @@ +// FIXME: if/when the output of the test harness can be tested on its own, this test should be +// adapted to use that, and that normalize line can go away + +// compile-flags:--test +// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR" +// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" +// failure-status: 101 + +/// +/// +/// ```rust +/// struct S {}; // unexpected semicolon after struct def +/// +/// fn main() { +/// assert_eq!(0, 1); +/// } +/// ``` +mod m {} diff --git a/src/test/rustdoc-ui/failed-doctest-extra-semicolon-on-item.stdout b/src/test/rustdoc-ui/failed-doctest-extra-semicolon-on-item.stdout new file mode 100644 index 0000000000..61468b6c74 --- /dev/null +++ b/src/test/rustdoc-ui/failed-doctest-extra-semicolon-on-item.stdout @@ -0,0 +1,24 @@ + +running 1 test +test $DIR/failed-doctest-extra-semicolon-on-item.rs - m (line 11) ... FAILED + +failures: + +---- $DIR/failed-doctest-extra-semicolon-on-item.rs - m (line 11) stdout ---- +error: expected item, found `;` + --> $DIR/failed-doctest-extra-semicolon-on-item.rs:12:12 + | +LL | struct S {}; // unexpected semicolon after struct def + | ^ help: remove this semicolon + | + = help: braced struct declarations are not followed by a semicolon + +error: aborting due to previous error + +Couldn't compile the test. + +failures: + $DIR/failed-doctest-extra-semicolon-on-item.rs - m (line 11) + +test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/src/test/rustdoc-ui/invalid-doc-attr.stderr b/src/test/rustdoc-ui/invalid-doc-attr.stderr index 595ece2ea7..55006b2087 100644 --- a/src/test/rustdoc-ui/invalid-doc-attr.stderr +++ b/src/test/rustdoc-ui/invalid-doc-attr.stderr @@ -29,7 +29,7 @@ LL | pub fn foo() {} | = warning: this was previously accepted 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: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#docno_inlinedocinline for more information + = note: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline for more information error: this attribute can only be applied at the crate level --> $DIR/invalid-doc-attr.rs:15:12 @@ -72,7 +72,7 @@ LL | pub fn 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 #82730 - = note: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#docno_inlinedocinline for more information + = note: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline for more information error: aborting due to 6 previous errors diff --git a/src/test/rustdoc-ui/invalid-keyword.rs b/src/test/rustdoc-ui/invalid-keyword.rs index ce2abc69bb..2d70471c85 100644 --- a/src/test/rustdoc-ui/invalid-keyword.rs +++ b/src/test/rustdoc-ui/invalid-keyword.rs @@ -1,4 +1,4 @@ -#![feature(doc_keyword)] +#![feature(rustdoc_internals)] #[doc(keyword = "foo df")] //~ ERROR mod foo {} diff --git a/src/test/rustdoc-ui/issue-91134.rs b/src/test/rustdoc-ui/issue-91134.rs new file mode 100644 index 0000000000..d2ff3a2522 --- /dev/null +++ b/src/test/rustdoc-ui/issue-91134.rs @@ -0,0 +1,14 @@ +// compile-flags: --test --crate-name=empty_fn --extern=empty_fn --test-args=--test-threads=1 +// aux-build:empty-fn.rs +// check-pass +// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR" +// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" +// edition:2021 + +/// +/// +/// ``` +/// extern crate empty_fn; +/// empty_fn::empty(); +/// ``` +pub struct Something; diff --git a/src/test/rustdoc-ui/issue-91134.stdout b/src/test/rustdoc-ui/issue-91134.stdout new file mode 100644 index 0000000000..084062743d --- /dev/null +++ b/src/test/rustdoc-ui/issue-91134.stdout @@ -0,0 +1,6 @@ + +running 1 test +test $DIR/issue-91134.rs - Something (line 10) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/src/test/rustdoc-ui/recursive-deref-ice.rs b/src/test/rustdoc-ui/recursive-deref-ice.rs new file mode 100644 index 0000000000..c44fd27f40 --- /dev/null +++ b/src/test/rustdoc-ui/recursive-deref-ice.rs @@ -0,0 +1,19 @@ +// check-pass + +// ICE found in https://github.com/rust-lang/rust/issues/83123 + +pub struct Attribute; + +pub struct Map<'hir> {} +impl<'hir> Map<'hir> { + pub fn attrs(&self) -> &'hir [Attribute] { &[] } +} + +pub struct List(T); + +impl std::ops::Deref for List { + type Target = [T]; + fn deref(&self) -> &[T] { + &[] + } +} diff --git a/src/test/rustdoc-ui/scrape-examples-ice.rs b/src/test/rustdoc-ui/scrape-examples-ice.rs new file mode 100644 index 0000000000..a6138add52 --- /dev/null +++ b/src/test/rustdoc-ui/scrape-examples-ice.rs @@ -0,0 +1,4 @@ +// compile-flags: -Z unstable-options --scrape-examples-output-path t.calls --scrape-examples-target-crate foobar +// check-pass +#![no_std] +use core as _; diff --git a/src/test/rustdoc-ui/scrape-examples-wrong-options-1.rs b/src/test/rustdoc-ui/scrape-examples-wrong-options-1.rs new file mode 100644 index 0000000000..a1f005c32e --- /dev/null +++ b/src/test/rustdoc-ui/scrape-examples-wrong-options-1.rs @@ -0,0 +1 @@ +// compile-flags: -Z unstable-options --scrape-examples-target-crate foobar diff --git a/src/test/rustdoc-ui/scrape-examples-wrong-options-1.stderr b/src/test/rustdoc-ui/scrape-examples-wrong-options-1.stderr new file mode 100644 index 0000000000..eb8e9f7996 --- /dev/null +++ b/src/test/rustdoc-ui/scrape-examples-wrong-options-1.stderr @@ -0,0 +1,2 @@ +error: must use --scrape-examples-output-path and --scrape-examples-target-crate together + diff --git a/src/test/rustdoc-ui/scrape-examples-wrong-options-2.rs b/src/test/rustdoc-ui/scrape-examples-wrong-options-2.rs new file mode 100644 index 0000000000..4aacec7f09 --- /dev/null +++ b/src/test/rustdoc-ui/scrape-examples-wrong-options-2.rs @@ -0,0 +1 @@ +// compile-flags: -Z unstable-options --scrape-examples-output-path ex.calls diff --git a/src/test/rustdoc-ui/scrape-examples-wrong-options-2.stderr b/src/test/rustdoc-ui/scrape-examples-wrong-options-2.stderr new file mode 100644 index 0000000000..eb8e9f7996 --- /dev/null +++ b/src/test/rustdoc-ui/scrape-examples-wrong-options-2.stderr @@ -0,0 +1,2 @@ +error: must use --scrape-examples-output-path and --scrape-examples-target-crate together + diff --git a/src/test/rustdoc/attributes.rs b/src/test/rustdoc/attributes.rs index 6a588fbd56..1c7f4b7241 100644 --- a/src/test/rustdoc/attributes.rs +++ b/src/test/rustdoc/attributes.rs @@ -8,6 +8,6 @@ pub extern "C" fn f() {} #[export_name = "bar"] pub extern "C" fn g() {} -// @has foo/struct.Repr.html '//*[@class="docblock type-decl"]' '#[repr(C, align(8))]' +// @has foo/struct.Repr.html '//*[@class="docblock item-decl"]' '#[repr(C, align(8))]' #[repr(C, align(8))] pub struct Repr; diff --git a/src/test/rustdoc/auxiliary/reexports.rs b/src/test/rustdoc/auxiliary/reexports.rs index e04b786a86..4336993a36 100644 --- a/src/test/rustdoc/auxiliary/reexports.rs +++ b/src/test/rustdoc/auxiliary/reexports.rs @@ -4,39 +4,63 @@ pub macro addr_of($place:expr) { &raw const $place } +pub macro addr_of_crate($place:expr) { + &raw const $place +} + +pub macro addr_of_super($place:expr) { + &raw const $place +} + pub macro addr_of_self($place:expr) { &raw const $place } -pub macro addr_of_crate($place:expr) { +pub macro addr_of_local($place:expr) { &raw const $place } pub struct Foo; -pub struct FooSelf; pub struct FooCrate; +pub struct FooSuper; +pub struct FooSelf; +pub struct FooLocal; pub enum Bar { Foo, } -pub enum BarSelf { Foo, } pub enum BarCrate { Foo, } +pub enum BarSuper { Foo, } +pub enum BarSelf { Foo, } +pub enum BarLocal { Foo, } pub fn foo() {} -pub fn foo_self() {} pub fn foo_crate() {} +pub fn foo_super() {} +pub fn foo_self() {} +pub fn foo_local() {} pub type Type = i32; -pub type TypeSelf = i32; pub type TypeCrate = i32; +pub type TypeSuper = i32; +pub type TypeSelf = i32; +pub type TypeLocal = i32; pub union Union { a: i8, b: i8, } +pub union UnionCrate { + a: i8, + b: i8, +} +pub union UnionSuper { + a: i8, + b: i8, +} pub union UnionSelf { a: i8, b: i8, } -pub union UnionCrate { +pub union UnionLocal { a: i8, b: i8, } diff --git a/src/test/rustdoc/deref-recursive-pathbuf.rs b/src/test/rustdoc/deref-recursive-pathbuf.rs new file mode 100644 index 0000000000..9ab338ca9b --- /dev/null +++ b/src/test/rustdoc/deref-recursive-pathbuf.rs @@ -0,0 +1,25 @@ +// #26207: Show all methods reachable via Deref impls, recursing through multiple dereferencing +// levels and across multiple crates. +// For `Deref` on non-foreign types, look at `deref-recursive.rs`. + +// @has 'foo/struct.Foo.html' +// @has '-' '//*[@id="deref-methods-PathBuf"]' 'Methods from Deref' +// @has '-' '//*[@class="impl-items"]//*[@id="method.as_path"]' 'pub fn as_path(&self)' +// @has '-' '//*[@id="deref-methods-Path"]' 'Methods from Deref' +// @has '-' '//*[@class="impl-items"]//*[@id="method.exists"]' 'pub fn exists(&self)' +// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-PathBuf"]' 'Methods from Deref' +// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.as_path"]' 'as_path' +// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-Path"]' 'Methods from Deref' +// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.exists"]' 'exists' + +#![crate_name = "foo"] + +use std::ops::Deref; +use std::path::PathBuf; + +pub struct Foo(PathBuf); + +impl Deref for Foo { + type Target = PathBuf; + fn deref(&self) -> &PathBuf { &self.0 } +} diff --git a/src/test/rustdoc/deref-recursive.rs b/src/test/rustdoc/deref-recursive.rs new file mode 100644 index 0000000000..c07e048b06 --- /dev/null +++ b/src/test/rustdoc/deref-recursive.rs @@ -0,0 +1,41 @@ +// #26207: Show all methods reachable via Deref impls, recursing through multiple dereferencing +// levels if needed. +// For `Deref` on foreign types, look at `deref-recursive-pathbuf.rs`. + +// @has 'foo/struct.Foo.html' +// @has '-' '//*[@id="deref-methods-Bar"]' 'Methods from Deref' +// @has '-' '//*[@class="impl-items"]//*[@id="method.bar"]' 'pub fn bar(&self)' +// @has '-' '//*[@id="deref-methods-Baz"]' 'Methods from Deref' +// @has '-' '//*[@class="impl-items"]//*[@id="method.baz"]' 'pub fn baz(&self)' +// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-Bar"]' 'Methods from Deref' +// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.bar"]' 'bar' +// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-Baz"]' 'Methods from Deref' +// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.baz"]' 'baz' + +#![crate_name = "foo"] + +use std::ops::Deref; + +pub struct Foo(Bar); +pub struct Bar(Baz); +pub struct Baz; + +impl Deref for Foo { + type Target = Bar; + fn deref(&self) -> &Bar { &self.0 } +} + +impl Deref for Bar { + type Target = Baz; + fn deref(&self) -> &Baz { &self.0 } +} + +impl Bar { + /// This appears under `Foo` methods + pub fn bar(&self) {} +} + +impl Baz { + /// This should also appear in `Foo` methods when recursing + pub fn baz(&self) {} +} diff --git a/src/test/rustdoc/deref-typedef.rs b/src/test/rustdoc/deref-typedef.rs index d42ff384b2..ad7a96c5da 100644 --- a/src/test/rustdoc/deref-typedef.rs +++ b/src/test/rustdoc/deref-typedef.rs @@ -1,12 +1,12 @@ #![crate_name = "foo"] // @has 'foo/struct.Bar.html' -// @has '-' '//*[@id="deref-methods"]' 'Methods from Deref' +// @has '-' '//*[@id="deref-methods-FooJ"]' 'Methods from Deref' // @has '-' '//*[@class="impl-items"]//*[@id="method.foo_a"]' 'pub fn foo_a(&self)' // @has '-' '//*[@class="impl-items"]//*[@id="method.foo_b"]' 'pub fn foo_b(&self)' // @has '-' '//*[@class="impl-items"]//*[@id="method.foo_c"]' 'pub fn foo_c(&self)' // @has '-' '//*[@class="impl-items"]//*[@id="method.foo_j"]' 'pub fn foo_j(&self)' -// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods"]' 'Methods from Deref' +// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-FooJ"]' 'Methods from Deref' // @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_a"]' 'foo_a' // @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_b"]' 'foo_b' // @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_c"]' 'foo_c' diff --git a/src/test/rustdoc/enum-headings.rs b/src/test/rustdoc/enum-headings.rs new file mode 100644 index 0000000000..2e5c34391c --- /dev/null +++ b/src/test/rustdoc/enum-headings.rs @@ -0,0 +1,40 @@ +#![crate_name = "foo"] +// @has foo/enum.Token.html +/// A token! +/// # First +/// Some following text... +// @has - '//h2[@id="first"]' "First" +pub enum Token { + /// A declaration! + /// # Variant-First + /// Some following text... + // @has - '//h4[@id="variant-first"]' "Variant-First" + Declaration { + /// A version! + /// # Variant-Field-First + /// Some following text... + // @has - '//h5[@id="variant-field-first"]' "Variant-Field-First" + version: String, + }, + /// A Zoople! + /// # Variant-First + Zoople( + // @has - '//h5[@id="variant-tuple-field-first"]' "Variant-Tuple-Field-First" + /// Zoople's first variant! + /// # Variant-Tuple-Field-First + /// Some following text... + usize, + ), + /// Unfinished business! + /// # Non-Exhaustive-First + /// Some following text... + // @has - '//h4[@id="non-exhaustive-first"]' "Non-Exhaustive-First" + #[non_exhaustive] + Unfinished { + /// This is x. + /// # X-First + /// Some following text... + // @has - '//h5[@id="x-first"]' "X-First" + x: usize, + }, +} diff --git a/src/test/rustdoc/include_str_cut.rs b/src/test/rustdoc/include_str_cut.rs new file mode 100644 index 0000000000..cbc1ba8db7 --- /dev/null +++ b/src/test/rustdoc/include_str_cut.rs @@ -0,0 +1,7 @@ +#![crate_name = "foo"] +#![no_std] + +// @has 'foo/fn.foo.html' +// @has - '//*[@class="docblock"]' 'inc2 x' +#[doc = include_str!("short-line.md")] +pub fn foo() {} diff --git a/src/test/rustdoc/issue-32374.rs b/src/test/rustdoc/issue-32374.rs index 4e92ae49a2..7654a56152 100644 --- a/src/test/rustdoc/issue-32374.rs +++ b/src/test/rustdoc/issue-32374.rs @@ -1,7 +1,6 @@ #![feature(staged_api)] #![doc(issue_tracker_base_url = "https://issue_url/")] - -#![unstable(feature="test", issue = "32374")] +#![unstable(feature = "test", issue = "32374")] // @matches issue_32374/index.html '//*[@class="item-left unstable deprecated module-item"]/span[@class="stab deprecated"]' \ // 'Deprecated' @@ -23,12 +22,6 @@ pub struct T; // '👎 Deprecated since 1.0.0: deprecated' // @has issue_32374/struct.U.html '//*[@class="stab unstable"]' \ // '🔬 This is a nightly-only experimental API. (test #32374)' -// @has issue_32374/struct.U.html '//details' \ -// '🔬 This is a nightly-only experimental API. (test #32374)' -// @has issue_32374/struct.U.html '//summary' \ -// '🔬 This is a nightly-only experimental API. (test #32374)' -// @has issue_32374/struct.U.html '//details/p' \ -// 'unstable' #[rustc_deprecated(since = "1.0.0", reason = "deprecated")] #[unstable(feature = "test", issue = "32374", reason = "unstable")] pub struct U; diff --git a/src/test/rustdoc/keyword.rs b/src/test/rustdoc/keyword.rs index 652517c5c9..16f7cac5f5 100644 --- a/src/test/rustdoc/keyword.rs +++ b/src/test/rustdoc/keyword.rs @@ -1,6 +1,6 @@ #![crate_name = "foo"] -#![feature(doc_keyword)] +#![feature(rustdoc_internals)] // @has foo/index.html '//h2[@id="keywords"]' 'Keywords' // @has foo/index.html '//a[@href="keyword.match.html"]' 'match' diff --git a/src/test/rustdoc/mixing-doc-comments-and-attrs.rs b/src/test/rustdoc/mixing-doc-comments-and-attrs.rs new file mode 100644 index 0000000000..c26d3a3198 --- /dev/null +++ b/src/test/rustdoc/mixing-doc-comments-and-attrs.rs @@ -0,0 +1,26 @@ +#![crate_name = "foo"] + +// @has 'foo/struct.S1.html' +// @count - '//details[@class="rustdoc-toggle top-doc"]/div[@class="docblock"]/p' \ +// 1 +// @has - '//details[@class="rustdoc-toggle top-doc"]/div[@class="docblock"]/p[1]' \ +// 'Hello world! Goodbye! Hello again!' + +#[doc = "Hello world!\n\n"] +/// Goodbye! +#[doc = " Hello again!\n"] +pub struct S1; + +// @has 'foo/struct.S2.html' +// @count - '//details[@class="rustdoc-toggle top-doc"]/div[@class="docblock"]/p' \ +// 2 +// @has - '//details[@class="rustdoc-toggle top-doc"]/div[@class="docblock"]/p[1]' \ +// 'Hello world!' +// @has - '//details[@class="rustdoc-toggle top-doc"]/div[@class="docblock"]/p[2]' \ +// 'Goodbye! Hello again!' + +/// Hello world! +/// +#[doc = "Goodbye!"] +/// Hello again! +pub struct S2; diff --git a/src/test/rustdoc/recursive-deref-sidebar.rs b/src/test/rustdoc/recursive-deref-sidebar.rs index fcb636ade8..65a7debc25 100644 --- a/src/test/rustdoc/recursive-deref-sidebar.rs +++ b/src/test/rustdoc/recursive-deref-sidebar.rs @@ -15,7 +15,7 @@ impl Deref for A { fn deref(&self) -> &B { todo!() } } -// @!has recursive_deref_sidebar/struct.A.html '//div[@class="sidebar-links"]' 'foo_c' +// @has recursive_deref_sidebar/struct.A.html '//div[@class="sidebar-links"]' 'foo_c' impl Deref for B { type Target = C; fn deref(&self) -> &C { todo!() } diff --git a/src/test/rustdoc/recursive-deref.rs b/src/test/rustdoc/recursive-deref.rs index 3d17bce472..a7504fbccf 100644 --- a/src/test/rustdoc/recursive-deref.rs +++ b/src/test/rustdoc/recursive-deref.rs @@ -1,9 +1,16 @@ use std::ops::Deref; +// Cyclic deref with the parent (which is not the top parent). pub struct A; pub struct B; +pub struct C; + +impl C { + pub fn c(&self) {} +} // @has recursive_deref/struct.A.html '//h3[@class="code-header in-band"]' 'impl Deref for A' +// @has '-' '//*[@class="impl-items"]//*[@id="method.c"]' 'pub fn c(&self)' impl Deref for A { type Target = B; @@ -13,8 +20,99 @@ impl Deref for A { } // @has recursive_deref/struct.B.html '//h3[@class="code-header in-band"]' 'impl Deref for B' +// @has '-' '//*[@class="impl-items"]//*[@id="method.c"]' 'pub fn c(&self)' impl Deref for B { - type Target = A; + type Target = C; + + fn deref(&self) -> &Self::Target { + panic!() + } +} + +// @has recursive_deref/struct.C.html '//h3[@class="code-header in-band"]' 'impl Deref for C' +impl Deref for C { + type Target = B; + + fn deref(&self) -> &Self::Target { + panic!() + } +} + +// Cyclic deref with the grand-parent (which is not the top parent). +pub struct D; +pub struct E; +pub struct F; +pub struct G; + +impl G { + // There is no "self" parameter so it shouldn't be listed! + pub fn g() {} +} + +// @has recursive_deref/struct.D.html '//h3[@class="code-header in-band"]' 'impl Deref for D' +// We also check that `G::g` method isn't rendered because there is no `self` argument. +// @!has '-' '//*[@id="deref-methods-G"]' +impl Deref for D { + type Target = E; + + fn deref(&self) -> &Self::Target { + panic!() + } +} + +// @has recursive_deref/struct.E.html '//h3[@class="code-header in-band"]' 'impl Deref for E' +// We also check that `G::g` method isn't rendered because there is no `self` argument. +// @!has '-' '//*[@id="deref-methods-G"]' +impl Deref for E { + type Target = F; + + fn deref(&self) -> &Self::Target { + panic!() + } +} + +// @has recursive_deref/struct.F.html '//h3[@class="code-header in-band"]' 'impl Deref for F' +// We also check that `G::g` method isn't rendered because there is no `self` argument. +// @!has '-' '//*[@id="deref-methods-G"]' +impl Deref for F { + type Target = G; + + fn deref(&self) -> &Self::Target { + panic!() + } +} + +// @has recursive_deref/struct.G.html '//h3[@class="code-header in-band"]' 'impl Deref for G' +impl Deref for G { + type Target = E; + + fn deref(&self) -> &Self::Target { + panic!() + } +} + +// Cyclic deref with top parent. +pub struct H; +pub struct I; + +impl I { + // There is no "self" parameter so it shouldn't be listed! + pub fn i() {} +} + +// @has recursive_deref/struct.H.html '//h3[@class="code-header in-band"]' 'impl Deref for H' +// @!has '-' '//*[@id="deref-methods-I"]' +impl Deref for H { + type Target = I; + + fn deref(&self) -> &Self::Target { + panic!() + } +} + +// @has recursive_deref/struct.I.html '//h3[@class="code-header in-band"]' 'impl Deref for I' +impl Deref for I { + type Target = H; fn deref(&self) -> &Self::Target { panic!() diff --git a/src/test/rustdoc/reexports-priv.rs b/src/test/rustdoc/reexports-priv.rs index ff7424033a..95f7418074 100644 --- a/src/test/rustdoc/reexports-priv.rs +++ b/src/test/rustdoc/reexports-priv.rs @@ -5,49 +5,131 @@ extern crate reexports; -// @has 'foo/macro.addr_of.html' '//*[@class="docblock type-decl"]' 'pub macro addr_of($place : expr) {' +// @has 'foo/macro.addr_of.html' '//*[@class="docblock item-decl"]' 'pub macro addr_of($place : expr) {' pub use reexports::addr_of; -// @has 'foo/macro.addr_of_crate.html' '//*[@class="docblock type-decl"]' 'pub(crate) macro addr_of_crate($place : expr) {' +// @!has 'foo/macro.addr_of_crate.html' pub(crate) use reexports::addr_of_crate; -// @has 'foo/macro.addr_of_self.html' '//*[@class="docblock type-decl"]' 'pub(crate) macro addr_of_self($place : expr) {' +// @!has 'foo/macro.addr_of_self.html' pub(self) use reexports::addr_of_self; +// @!has 'foo/macro.addr_of_local.html' +use reexports::addr_of_local; -// @has 'foo/struct.Foo.html' '//*[@class="docblock type-decl"]' 'pub struct Foo;' +// @has 'foo/struct.Foo.html' '//*[@class="docblock item-decl"]' 'pub struct Foo;' pub use reexports::Foo; -// @has 'foo/struct.FooCrate.html' '//*[@class="docblock type-decl"]' 'pub(crate) struct FooCrate;' +// @!has 'foo/struct.FooCrate.html' pub(crate) use reexports::FooCrate; -// @has 'foo/struct.FooSelf.html' '//*[@class="docblock type-decl"]' 'pub(crate) struct FooSelf;' +// @!has 'foo/struct.FooSelf.html' pub(self) use reexports::FooSelf; +// @!has 'foo/struct.FooLocal.html' +use reexports::FooLocal; -// @has 'foo/enum.Bar.html' '//*[@class="docblock type-decl"]' 'pub enum Bar {' +// @has 'foo/enum.Bar.html' '//*[@class="docblock item-decl"]' 'pub enum Bar {' pub use reexports::Bar; -// @has 'foo/enum.BarCrate.html' '//*[@class="docblock type-decl"]' 'pub(crate) enum BarCrate {' +// @!has 'foo/enum.BarCrate.html' pub(crate) use reexports::BarCrate; -// @has 'foo/enum.BarSelf.html' '//*[@class="docblock type-decl"]' 'pub(crate) enum BarSelf {' +// @!has 'foo/enum.BarSelf.html' pub(self) use reexports::BarSelf; +// @!has 'foo/enum.BarLocal.html' +use reexports::BarLocal; // @has 'foo/fn.foo.html' '//*[@class="rust fn"]' 'pub fn foo()' pub use reexports::foo; -// @has 'foo/fn.foo_crate.html' '//*[@class="rust fn"]' 'pub(crate) fn foo_crate()' +// @!has 'foo/fn.foo_crate.html' pub(crate) use reexports::foo_crate; -// @has 'foo/fn.foo_self.html' '//*[@class="rust fn"]' 'pub(crate) fn foo_self()' +// @!has 'foo/fn.foo_self.html' pub(self) use reexports::foo_self; +// @!has 'foo/fn.foo_local.html' +use reexports::foo_local; // @has 'foo/type.Type.html' '//*[@class="rust typedef"]' 'pub type Type =' pub use reexports::Type; -// @has 'foo/type.TypeCrate.html' '//*[@class="rust typedef"]' 'pub(crate) type TypeCrate =' +// @!has 'foo/type.TypeCrate.html' pub(crate) use reexports::TypeCrate; -// @has 'foo/type.TypeSelf.html' '//*[@class="rust typedef"]' 'pub(crate) type TypeSelf =' +// @!has 'foo/type.TypeSelf.html' pub(self) use reexports::TypeSelf; +// @!has 'foo/type.TypeLocal.html' +use reexports::TypeLocal; -// @has 'foo/union.Union.html' '//*[@class="docblock type-decl"]' 'pub union Union {' +// @has 'foo/union.Union.html' '//*[@class="docblock item-decl"]' 'pub union Union {' pub use reexports::Union; -// @has 'foo/union.UnionCrate.html' '//*[@class="docblock type-decl"]' 'pub(crate) union UnionCrate {' +// @!has 'foo/union.UnionCrate.html' pub(crate) use reexports::UnionCrate; -// @has 'foo/union.UnionSelf.html' '//*[@class="docblock type-decl"]' 'pub(crate) union UnionSelf {' +// @!has 'foo/union.UnionSelf.html' pub(self) use reexports::UnionSelf; +// @!has 'foo/union.UnionLocal.html' +use reexports::UnionLocal; -pub mod foo { - // @!has 'foo/foo/union.Union.html' - use crate::reexports::Union; +pub mod outer { + pub mod inner { + // @has 'foo/outer/inner/macro.addr_of.html' '//*[@class="docblock item-decl"]' 'pub macro addr_of($place : expr) {' + pub use reexports::addr_of; + // @has 'foo/outer/inner/macro.addr_of_crate.html' '//*[@class="docblock item-decl"]' 'pub(crate) macro addr_of_crate($place : expr) {' + pub(crate) use reexports::addr_of_crate; + // @has 'foo/outer/inner/macro.addr_of_super.html' '//*[@class="docblock item-decl"]' 'pub(in outer) macro addr_of_super($place : expr) {' + pub(super) use reexports::addr_of_super; + // @!has 'foo/outer/inner/macro.addr_of_self.html' + pub(self) use reexports::addr_of_self; + // @!has 'foo/outer/inner/macro.addr_of_local.html' + use reexports::addr_of_local; + + // @has 'foo/outer/inner/struct.Foo.html' '//*[@class="docblock item-decl"]' 'pub struct Foo;' + pub use reexports::Foo; + // @has 'foo/outer/inner/struct.FooCrate.html' '//*[@class="docblock item-decl"]' 'pub(crate) struct FooCrate;' + pub(crate) use reexports::FooCrate; + // @has 'foo/outer/inner/struct.FooSuper.html' '//*[@class="docblock item-decl"]' 'pub(in outer) struct FooSuper;' + pub(super) use reexports::FooSuper; + // @!has 'foo/outer/inner/struct.FooSelf.html' + pub(self) use reexports::FooSelf; + // @!has 'foo/outer/inner/struct.FooLocal.html' + use reexports::FooLocal; + + // @has 'foo/outer/inner/enum.Bar.html' '//*[@class="docblock item-decl"]' 'pub enum Bar {' + pub use reexports::Bar; + // @has 'foo/outer/inner/enum.BarCrate.html' '//*[@class="docblock item-decl"]' 'pub(crate) enum BarCrate {' + pub(crate) use reexports::BarCrate; + // @has 'foo/outer/inner/enum.BarSuper.html' '//*[@class="docblock item-decl"]' 'pub(in outer) enum BarSuper {' + pub(super) use reexports::BarSuper; + // @!has 'foo/outer/inner/enum.BarSelf.html' + pub(self) use reexports::BarSelf; + // @!has 'foo/outer/inner/enum.BarLocal.html' + use reexports::BarLocal; + + // @has 'foo/outer/inner/fn.foo.html' '//*[@class="rust fn"]' 'pub fn foo()' + pub use reexports::foo; + // @has 'foo/outer/inner/fn.foo_crate.html' '//*[@class="rust fn"]' 'pub(crate) fn foo_crate()' + pub(crate) use reexports::foo_crate; + // @has 'foo/outer/inner/fn.foo_super.html' '//*[@class="rust fn"]' 'pub(in outer) fn foo_super()' + pub(super) use::reexports::foo_super; + // @!has 'foo/outer/inner/fn.foo_self.html' + pub(self) use reexports::foo_self; + // @!has 'foo/outer/inner/fn.foo_local.html' + use reexports::foo_local; + + // @has 'foo/outer/inner/type.Type.html' '//*[@class="rust typedef"]' 'pub type Type =' + pub use reexports::Type; + // @has 'foo/outer/inner/type.TypeCrate.html' '//*[@class="rust typedef"]' 'pub(crate) type TypeCrate =' + pub(crate) use reexports::TypeCrate; + // @has 'foo/outer/inner/type.TypeSuper.html' '//*[@class="rust typedef"]' 'pub(in outer) type TypeSuper =' + pub(super) use reexports::TypeSuper; + // @!has 'foo/outer/inner/type.TypeSelf.html' + pub(self) use reexports::TypeSelf; + // @!has 'foo/outer/inner/type.TypeLocal.html' + use reexports::TypeLocal; + + // @has 'foo/outer/inner/union.Union.html' '//*[@class="docblock item-decl"]' 'pub union Union {' + pub use reexports::Union; + // @has 'foo/outer/inner/union.UnionCrate.html' '//*[@class="docblock item-decl"]' 'pub(crate) union UnionCrate {' + pub(crate) use reexports::UnionCrate; + // @has 'foo/outer/inner/union.UnionSuper.html' '//*[@class="docblock item-decl"]' 'pub(in outer) union UnionSuper {' + pub(super) use reexports::UnionSuper; + // @!has 'foo/outer/inner/union.UnionSelf.html' + pub(self) use reexports::UnionSelf; + // @!has 'foo/outer/inner/union.UnionLocal.html' + use reexports::UnionLocal; + } +} + +mod re_re_exports { + // @!has 'foo/re_re_exports/union.Union.html' + use crate::reexports::Union; } diff --git a/src/test/rustdoc/reexports.rs b/src/test/rustdoc/reexports.rs index ab4c5bc743..3b31530847 100644 --- a/src/test/rustdoc/reexports.rs +++ b/src/test/rustdoc/reexports.rs @@ -4,26 +4,32 @@ extern crate reexports; -// @has 'foo/macro.addr_of.html' '//*[@class="docblock type-decl"]' 'pub macro addr_of($place : expr) {' +// @has 'foo/macro.addr_of.html' '//*[@class="docblock item-decl"]' 'pub macro addr_of($place : expr) {' pub use reexports::addr_of; // @!has 'foo/macro.addr_of_crate.html' pub(crate) use reexports::addr_of_crate; // @!has 'foo/macro.addr_of_self.html' pub(self) use reexports::addr_of_self; +// @!has 'foo/macro.addr_of_local.html' +use reexports::addr_of_local; -// @has 'foo/struct.Foo.html' '//*[@class="docblock type-decl"]' 'pub struct Foo;' +// @has 'foo/struct.Foo.html' '//*[@class="docblock item-decl"]' 'pub struct Foo;' pub use reexports::Foo; // @!has 'foo/struct.FooCrate.html' pub(crate) use reexports::FooCrate; // @!has 'foo/struct.FooSelf.html' pub(self) use reexports::FooSelf; +// @!has 'foo/struct.FooLocal.html' +use reexports::FooLocal; -// @has 'foo/enum.Bar.html' '//*[@class="docblock type-decl"]' 'pub enum Bar {' +// @has 'foo/enum.Bar.html' '//*[@class="docblock item-decl"]' 'pub enum Bar {' pub use reexports::Bar; // @!has 'foo/enum.BarCrate.html' pub(crate) use reexports::BarCrate; // @!has 'foo/enum.BarSelf.html' pub(self) use reexports::BarSelf; +// @!has 'foo/enum.BarLocal.html' +use reexports::BarLocal; // @has 'foo/fn.foo.html' '//*[@class="rust fn"]' 'pub fn foo()' pub use reexports::foo; @@ -31,6 +37,8 @@ pub use reexports::foo; pub(crate) use reexports::foo_crate; // @!has 'foo/fn.foo_self.html' pub(self) use reexports::foo_self; +// @!has 'foo/fn.foo_local.html' +use reexports::foo_local; // @has 'foo/type.Type.html' '//*[@class="rust typedef"]' 'pub type Type =' pub use reexports::Type; @@ -38,10 +46,84 @@ pub use reexports::Type; pub(crate) use reexports::TypeCrate; // @!has 'foo/type.TypeSelf.html' pub(self) use reexports::TypeSelf; +// @!has 'foo/type.TypeLocal.html' +use reexports::TypeLocal; -// @has 'foo/union.Union.html' '//*[@class="docblock type-decl"]' 'pub union Union {' +// @has 'foo/union.Union.html' '//*[@class="docblock item-decl"]' 'pub union Union {' pub use reexports::Union; // @!has 'foo/union.UnionCrate.html' pub(crate) use reexports::UnionCrate; // @!has 'foo/union.UnionSelf.html' pub(self) use reexports::UnionSelf; +// @!has 'foo/union.UnionLocal.html' +use reexports::UnionLocal; + +pub mod outer { + pub mod inner { + // @has 'foo/outer/inner/macro.addr_of.html' '//*[@class="docblock item-decl"]' 'pub macro addr_of($place : expr) {' + pub use reexports::addr_of; + // @!has 'foo/outer/inner/macro.addr_of_crate.html' + pub(crate) use reexports::addr_of_crate; + // @!has 'foo/outer/inner/macro.addr_of_super.html' + pub(super) use reexports::addr_of_super; + // @!has 'foo/outer/inner/macro.addr_of_self.html' + pub(self) use reexports::addr_of_self; + // @!has 'foo/outer/inner/macro.addr_of_local.html' + use reexports::addr_of_local; + + // @has 'foo/outer/inner/struct.Foo.html' '//*[@class="docblock item-decl"]' 'pub struct Foo;' + pub use reexports::Foo; + // @!has 'foo/outer/inner/struct.FooCrate.html' + pub(crate) use reexports::FooCrate; + // @!has 'foo/outer/inner/struct.FooSuper.html' + pub(super) use reexports::FooSuper; + // @!has 'foo/outer/inner/struct.FooSelf.html' + pub(self) use reexports::FooSelf; + // @!has 'foo/outer/inner/struct.FooLocal.html' + use reexports::FooLocal; + + // @has 'foo/outer/inner/enum.Bar.html' '//*[@class="docblock item-decl"]' 'pub enum Bar {' + pub use reexports::Bar; + // @!has 'foo/outer/inner/enum.BarCrate.html' + pub(crate) use reexports::BarCrate; + // @!has 'foo/outer/inner/enum.BarSuper.html' + pub(super) use reexports::BarSuper; + // @!has 'foo/outer/inner/enum.BarSelf.html' + pub(self) use reexports::BarSelf; + // @!has 'foo/outer/inner/enum.BarLocal.html' + use reexports::BarLocal; + + // @has 'foo/outer/inner/fn.foo.html' '//*[@class="rust fn"]' 'pub fn foo()' + pub use reexports::foo; + // @!has 'foo/outer/inner/fn.foo_crate.html' + pub(crate) use reexports::foo_crate; + // @!has 'foo/outer/inner/fn.foo_super.html' + pub(super) use::reexports::foo_super; + // @!has 'foo/outer/inner/fn.foo_self.html' + pub(self) use reexports::foo_self; + // @!has 'foo/outer/inner/fn.foo_local.html' + use reexports::foo_local; + + // @has 'foo/outer/inner/type.Type.html' '//*[@class="rust typedef"]' 'pub type Type =' + pub use reexports::Type; + // @!has 'foo/outer/inner/type.TypeCrate.html' + pub(crate) use reexports::TypeCrate; + // @!has 'foo/outer/inner/type.TypeSuper.html' + pub(super) use reexports::TypeSuper; + // @!has 'foo/outer/inner/type.TypeSelf.html' + pub(self) use reexports::TypeSelf; + // @!has 'foo/outer/inner/type.TypeLocal.html' + use reexports::TypeLocal; + + // @has 'foo/outer/inner/union.Union.html' '//*[@class="docblock item-decl"]' 'pub union Union {' + pub use reexports::Union; + // @!has 'foo/outer/inner/union.UnionCrate.html' + pub(crate) use reexports::UnionCrate; + // @!has 'foo/outer/inner/union.UnionSuper.html' + pub(super) use reexports::UnionSuper; + // @!has 'foo/outer/inner/union.UnionSelf.html' + pub(self) use reexports::UnionSelf; + // @!has 'foo/outer/inner/union.UnionLocal.html' + use reexports::UnionLocal; + } +} diff --git a/src/test/rustdoc/short-line.md b/src/test/rustdoc/short-line.md new file mode 100644 index 0000000000..eff713baac --- /dev/null +++ b/src/test/rustdoc/short-line.md @@ -0,0 +1,2 @@ +inc2 +x diff --git a/src/test/rustdoc/tab_title.rs b/src/test/rustdoc/tab_title.rs index 7dce6092de..0cc4f147e1 100644 --- a/src/test/rustdoc/tab_title.rs +++ b/src/test/rustdoc/tab_title.rs @@ -1,5 +1,5 @@ #![crate_name = "foo"] -#![feature(doc_keyword)] +#![feature(rustdoc_internals)] // tests for the html element diff --git a/src/test/rustdoc/toggle-item-contents.rs b/src/test/rustdoc/toggle-item-contents.rs index ae871e79d7..937646987d 100644 --- a/src/test/rustdoc/toggle-item-contents.rs +++ b/src/test/rustdoc/toggle-item-contents.rs @@ -55,7 +55,7 @@ pub union Union { // @has 'toggle_item_contents/struct.PrivStruct.html' // @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 0 -// @has - '//div[@class="docblock type-decl"]' 'fields omitted' +// @has - '//div[@class="docblock item-decl"]' 'fields omitted' pub struct PrivStruct { a: usize, b: usize, diff --git a/src/test/rustdoc/trait_alias.rs b/src/test/rustdoc/trait_alias.rs index 6cd4a1a0af..c9fccf5a77 100644 --- a/src/test/rustdoc/trait_alias.rs +++ b/src/test/rustdoc/trait_alias.rs @@ -13,11 +13,14 @@ use std::fmt::Debug; // @has foo/index.html '//a[@class="traitalias"]' 'Alias2' // @has foo/index.html '//a[@class="traitalias"]' 'Foo' -// @has foo/traitalias.CopyAlias.html '//section[@id="main"]/pre' 'trait CopyAlias = Copy;' +// @has foo/traitalias.CopyAlias.html +// @has - '//section[@id="main"]/div[@class="docblock item-decl"]/pre' 'trait CopyAlias = Copy;' pub trait CopyAlias = Copy; -// @has foo/traitalias.Alias2.html '//section[@id="main"]/pre' 'trait Alias2 = Copy + Debug;' +// @has foo/traitalias.Alias2.html +// @has - '//section[@id="main"]/div[@class="docblock item-decl"]/pre' 'trait Alias2 = Copy + Debug;' pub trait Alias2 = Copy + Debug; -// @has foo/traitalias.Foo.html '//section[@id="main"]/pre' 'trait Foo<T> = Into<T> + Debug;' +// @has foo/traitalias.Foo.html +// @has - '//section[@id="main"]/div[@class="docblock item-decl"]/pre' 'trait Foo<T> = Into<T> + Debug;' pub trait Foo<T> = Into<T> + Debug; // @has foo/fn.bar.html '//a[@href="traitalias.Alias2.html"]' 'Alias2' pub fn bar<T>() where T: Alias2 {} diff --git a/src/test/rustdoc/tuple-struct-fields-doc.rs b/src/test/rustdoc/tuple-struct-fields-doc.rs index f3d8e39ea2..139c5b4391 100644 --- a/src/test/rustdoc/tuple-struct-fields-doc.rs +++ b/src/test/rustdoc/tuple-struct-fields-doc.rs @@ -20,10 +20,10 @@ pub struct Foo( // @has foo/enum.Bar.html // @has - '//pre[@class="rust enum"]' 'BarVariant(String),' -// @matches - '//*[@id="variant.BarVariant.fields"]/h3' '^Tuple Fields of BarVariant$' +// @matches - '//*[@id="variant.BarVariant.fields"]/h4' '^Tuple Fields$' // @has - '//*[@id="variant.BarVariant.field.0"]' '0: String' // @has - '//*[@id="variant.BarVariant.fields"]//*[@class="docblock"]' 'Hello docs' -// @matches - '//*[@id="variant.FooVariant.fields"]/h3' '^Fields of FooVariant$' +// @matches - '//*[@id="variant.FooVariant.fields"]/h4' '^Fields$' pub enum Bar { BarVariant( /// Hello docs diff --git a/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.rs b/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.rs index 053712a4b4..7783dc40fc 100644 --- a/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.rs +++ b/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.rs @@ -1,7 +1,7 @@ // compile-flags: -Z unstable-options #![feature(rustc_private)] -#![feature(doc_keyword)] +#![feature(rustdoc_internals)] #![crate_type = "lib"] diff --git a/src/test/ui-fulldeps/lint-tool-test.rs b/src/test/ui-fulldeps/lint-tool-test.rs index f92bcd213b..0d04eb6fcf 100644 --- a/src/test/ui-fulldeps/lint-tool-test.rs +++ b/src/test/ui-fulldeps/lint-tool-test.rs @@ -10,10 +10,12 @@ //~^ WARNING lint name `test_lint` is deprecated and may not have an effect in the future //~| WARNING lint name `test_lint` is deprecated and may not have an effect in the future //~| WARNING lint name `test_lint` is deprecated and may not have an effect in the future +//~| WARNING lint name `test_lint` is deprecated and may not have an effect in the future #![deny(clippy_group)] //~^ WARNING lint name `clippy_group` is deprecated and may not have an effect in the future //~| WARNING lint name `clippy_group` is deprecated and may not have an effect in the future //~| WARNING lint name `clippy_group` is deprecated and may not have an effect in the future +//~| WARNING lint name `clippy_group` is deprecated and may not have an effect in the future fn lintme() { } //~ ERROR item is named 'lintme' @@ -30,6 +32,7 @@ pub fn main() { //~^ WARNING lint name `test_group` is deprecated and may not have an effect in the future //~| WARNING lint name `test_group` is deprecated and may not have an effect in the future //~| WARNING lint name `test_group` is deprecated and may not have an effect in the future +//~| WARNING lint name `test_group` is deprecated and may not have an effect in the future #[deny(this_lint_does_not_exist)] //~ WARNING unknown lint: `this_lint_does_not_exist` fn hello() { fn lintmetoo() { } diff --git a/src/test/ui-fulldeps/lint-tool-test.stderr b/src/test/ui-fulldeps/lint-tool-test.stderr index 2260477a91..0f76384ed5 100644 --- a/src/test/ui-fulldeps/lint-tool-test.stderr +++ b/src/test/ui-fulldeps/lint-tool-test.stderr @@ -7,19 +7,19 @@ LL | #![cfg_attr(foo, warn(test_lint))] = note: `#[warn(renamed_and_removed_lints)]` on by default warning: lint name `clippy_group` is deprecated and may not have an effect in the future. - --> $DIR/lint-tool-test.rs:13:9 + --> $DIR/lint-tool-test.rs:14:9 | LL | #![deny(clippy_group)] | ^^^^^^^^^^^^ help: change it to: `clippy::group` warning: lint name `test_group` is deprecated and may not have an effect in the future. - --> $DIR/lint-tool-test.rs:29:9 + --> $DIR/lint-tool-test.rs:31:9 | LL | #[allow(test_group)] | ^^^^^^^^^^ help: change it to: `clippy::test_group` warning: unknown lint: `this_lint_does_not_exist` - --> $DIR/lint-tool-test.rs:33:8 + --> $DIR/lint-tool-test.rs:36:8 | LL | #[deny(this_lint_does_not_exist)] | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -33,13 +33,13 @@ LL | #![cfg_attr(foo, warn(test_lint))] | ^^^^^^^^^ help: change it to: `clippy::test_lint` warning: lint name `clippy_group` is deprecated and may not have an effect in the future. - --> $DIR/lint-tool-test.rs:13:9 + --> $DIR/lint-tool-test.rs:14:9 | LL | #![deny(clippy_group)] | ^^^^^^^^^^^^ help: change it to: `clippy::group` warning: lint name `test_group` is deprecated and may not have an effect in the future. - --> $DIR/lint-tool-test.rs:29:9 + --> $DIR/lint-tool-test.rs:31:9 | LL | #[allow(test_group)] | ^^^^^^^^^^ help: change it to: `clippy::test_group` @@ -59,42 +59,60 @@ LL | #![cfg_attr(foo, warn(test_lint))] | ^^^^^^^^^ help: change it to: `clippy::test_lint` warning: lint name `clippy_group` is deprecated and may not have an effect in the future. - --> $DIR/lint-tool-test.rs:13:9 + --> $DIR/lint-tool-test.rs:14:9 | LL | #![deny(clippy_group)] | ^^^^^^^^^^^^ help: change it to: `clippy::group` error: item is named 'lintme' - --> $DIR/lint-tool-test.rs:18:1 + --> $DIR/lint-tool-test.rs:20:1 | LL | fn lintme() { } | ^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/lint-tool-test.rs:13:9 + --> $DIR/lint-tool-test.rs:14:9 | LL | #![deny(clippy_group)] | ^^^^^^^^^^^^ = note: `#[deny(clippy::test_lint)]` implied by `#[deny(clippy::group)]` error: item is named 'lintmetoo' - --> $DIR/lint-tool-test.rs:26:5 + --> $DIR/lint-tool-test.rs:28:5 | LL | fn lintmetoo() { } | ^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/lint-tool-test.rs:13:9 + --> $DIR/lint-tool-test.rs:14:9 | LL | #![deny(clippy_group)] | ^^^^^^^^^^^^ = note: `#[deny(clippy::test_group)]` implied by `#[deny(clippy::group)]` warning: lint name `test_group` is deprecated and may not have an effect in the future. - --> $DIR/lint-tool-test.rs:29:9 + --> $DIR/lint-tool-test.rs:31:9 | LL | #[allow(test_group)] | ^^^^^^^^^^ help: change it to: `clippy::test_group` -error: aborting due to 2 previous errors; 11 warnings emitted +warning: lint name `test_lint` is deprecated and may not have an effect in the future. + --> $DIR/lint-tool-test.rs:9:23 + | +LL | #![cfg_attr(foo, warn(test_lint))] + | ^^^^^^^^^ help: change it to: `clippy::test_lint` + +warning: lint name `clippy_group` is deprecated and may not have an effect in the future. + --> $DIR/lint-tool-test.rs:14:9 + | +LL | #![deny(clippy_group)] + | ^^^^^^^^^^^^ help: change it to: `clippy::group` + +warning: lint name `test_group` is deprecated and may not have an effect in the future. + --> $DIR/lint-tool-test.rs:31:9 + | +LL | #[allow(test_group)] + | ^^^^^^^^^^ help: change it to: `clippy::test_group` + +error: aborting due to 2 previous errors; 14 warnings emitted diff --git a/src/test/ui/c-stack-returning-int64.rs b/src/test/ui/abi/c-stack-returning-int64.rs similarity index 100% rename from src/test/ui/c-stack-returning-int64.rs rename to src/test/ui/abi/c-stack-returning-int64.rs diff --git a/src/test/ui/abi/stack-protector.rs b/src/test/ui/abi/stack-protector.rs new file mode 100644 index 0000000000..24bd2e2194 --- /dev/null +++ b/src/test/ui/abi/stack-protector.rs @@ -0,0 +1,99 @@ +// run-pass +// only-x86_64-unknown-linux-gnu +// revisions: ssp no-ssp +// [ssp] compile-flags: -Z stack-protector=all +// compile-flags: -C opt-level=2 +// compile-flags: -g + +use std::env; +use std::process::{Command, ExitStatus}; + +fn main() { + if env::args().len() == 1 { + // The test is initially run without arguments. Start the process again, + // this time *with* an argument; in this configuration, the test program + // will deliberately smash the stack. + let cur_argv0 = env::current_exe().unwrap(); + let mut child = Command::new(&cur_argv0); + child.arg("stacksmash"); + + if cfg!(ssp) { + assert_stack_smash_prevented(&mut child); + } else { + assert_stack_smashed(&mut child); + } + } else { + vulnerable_function(); + // If we return here the test is broken: it should either have called + // malicious_code() which terminates the process, or be caught by the + // stack check which also terminates the process. + panic!("TEST BUG: stack smash unsuccessful"); + } +} + +// Avoid inlining to make sure the return address is pushed to stack. +#[inline(never)] +fn vulnerable_function() { + let mut x = 5usize; + let stackaddr = &mut x as *mut usize; + let bad_code_ptr = malicious_code as usize; + // Overwrite the on-stack return address with the address of `malicious_code()`, + // thereby jumping to that function when returning from `vulnerable_function()`. + unsafe { fill(stackaddr, bad_code_ptr, 20); } +} + +// Use an uninlined function with its own stack frame to make sure that we don't +// clobber e.g. the counter or address local variable. +#[inline(never)] +unsafe fn fill(addr: *mut usize, val: usize, count: usize) { + let mut addr = addr; + for _ in 0..count { + *addr = val; + addr = addr.add(1); + } +} + +// We jump to malicious_code() having wreaked havoc with the previous stack +// frame and not setting up a new one. This function is therefore constrained, +// e.g. both println!() and std::process::exit() segfaults if called. We +// therefore keep the amount of work to a minimum by calling POSIX functions +// directly. +// The function is un-inlined just to make it possible to set a breakpoint here. +#[inline(never)] +fn malicious_code() { + let msg = [112u8, 119u8, 110u8, 101u8, 100u8, 33u8, 0u8]; // "pwned!\0" ascii + unsafe { + write(1, &msg as *const u8, msg.len()); + _exit(0); + } +} +extern "C" { + fn write(fd: i32, buf: *const u8, count: usize) -> isize; + fn _exit(status: i32) -> !; +} + + +fn assert_stack_smash_prevented(cmd: &mut Command) { + let (status, stdout, stderr) = run(cmd); + assert!(!status.success()); + assert!(stdout.is_empty()); + assert!(stderr.contains("stack smashing detected")); +} + +fn assert_stack_smashed(cmd: &mut Command) { + let (status, stdout, stderr) = run(cmd); + assert!(status.success()); + assert!(stdout.contains("pwned!")); + assert!(stderr.is_empty()); +} + + +fn run(cmd: &mut Command) -> (ExitStatus, String, String) { + let output = cmd.output().unwrap(); + let stdout = String::from_utf8_lossy(&output.stdout); + let stderr = String::from_utf8_lossy(&output.stderr); + println!("status: {}", output.status); + println!("stdout: {}", stdout); + println!("stderr: {}", stderr); + (output.status, stdout.to_string(), stderr.to_string()) +} diff --git a/src/test/ui/abi/unsupported.aarch64.stderr b/src/test/ui/abi/unsupported.aarch64.stderr index 225d49e05a..a948947dbd 100644 --- a/src/test/ui/abi/unsupported.aarch64.stderr +++ b/src/test/ui/abi/unsupported.aarch64.stderr @@ -40,25 +40,22 @@ error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target LL | extern "x86-interrupt" fn x86() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target +error[E0570]: `"thiscall"` is not a supported ABI for the current target --> $DIR/unsupported.rs:43:1 | -LL | extern "stdcall" fn stdcall() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(unsupported_calling_conventions)]` on by default - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678> +LL | extern "thiscall" fn thiscall() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:50:1 + --> $DIR/unsupported.rs:47:1 | -LL | extern "thiscall" fn thiscall() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | extern "stdcall" fn stdcall() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = note: `#[warn(unsupported_calling_conventions)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678> -error: aborting due to 7 previous errors; 2 warnings emitted +error: aborting due to 8 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0570`. diff --git a/src/test/ui/abi/unsupported.arm.stderr b/src/test/ui/abi/unsupported.arm.stderr index b050ee0aa3..297354c282 100644 --- a/src/test/ui/abi/unsupported.arm.stderr +++ b/src/test/ui/abi/unsupported.arm.stderr @@ -34,25 +34,22 @@ error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target LL | extern "x86-interrupt" fn x86() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target +error[E0570]: `"thiscall"` is not a supported ABI for the current target --> $DIR/unsupported.rs:43:1 | -LL | extern "stdcall" fn stdcall() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(unsupported_calling_conventions)]` on by default - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678> +LL | extern "thiscall" fn thiscall() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:50:1 + --> $DIR/unsupported.rs:47:1 | -LL | extern "thiscall" fn thiscall() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | extern "stdcall" fn stdcall() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = note: `#[warn(unsupported_calling_conventions)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678> -error: aborting due to 6 previous errors; 2 warnings emitted +error: aborting due to 7 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0570`. diff --git a/src/test/ui/abi/unsupported.rs b/src/test/ui/abi/unsupported.rs index 9319eac8d3..6427a5695c 100644 --- a/src/test/ui/abi/unsupported.rs +++ b/src/test/ui/abi/unsupported.rs @@ -40,14 +40,11 @@ extern "avr-interrupt" fn avr() {} extern "x86-interrupt" fn x86() {} //[aarch64]~^ ERROR is not a supported ABI //[arm]~^^ ERROR is not a supported ABI -extern "stdcall" fn stdcall() {} -//[x64]~^ WARN use of calling convention not supported -//[x64]~^^ WARN this was previously accepted -//[aarch64]~^^^ WARN use of calling convention not supported -//[aarch64]~^^^^ WARN this was previously accepted -//[arm]~^^^^^ WARN use of calling convention not supported -//[arm]~^^^^^^ WARN this was previously accepted extern "thiscall" fn thiscall() {} +//[x64]~^ ERROR is not a supported ABI +//[aarch64]~^^ ERROR is not a supported ABI +//[arm]~^^^ ERROR is not a supported ABI +extern "stdcall" fn stdcall() {} //[x64]~^ WARN use of calling convention not supported //[x64]~^^ WARN this was previously accepted //[aarch64]~^^^ WARN use of calling convention not supported diff --git a/src/test/ui/abi/unsupported.x64.stderr b/src/test/ui/abi/unsupported.x64.stderr index f2f5268332..49b88cd3fa 100644 --- a/src/test/ui/abi/unsupported.x64.stderr +++ b/src/test/ui/abi/unsupported.x64.stderr @@ -34,25 +34,22 @@ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target LL | extern "avr-interrupt" fn avr() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target +error[E0570]: `"thiscall"` is not a supported ABI for the current target --> $DIR/unsupported.rs:43:1 | -LL | extern "stdcall" fn stdcall() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(unsupported_calling_conventions)]` on by default - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678> +LL | extern "thiscall" fn thiscall() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:50:1 + --> $DIR/unsupported.rs:47:1 | -LL | extern "thiscall" fn thiscall() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | extern "stdcall" fn stdcall() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = note: `#[warn(unsupported_calling_conventions)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678> -error: aborting due to 6 previous errors; 2 warnings emitted +error: aborting due to 7 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0570`. diff --git a/src/test/ui/x86stdcall.rs b/src/test/ui/abi/x86stdcall.rs similarity index 89% rename from src/test/ui/x86stdcall.rs rename to src/test/ui/abi/x86stdcall.rs index 2bf4cfc500..868923e593 100644 --- a/src/test/ui/x86stdcall.rs +++ b/src/test/ui/abi/x86stdcall.rs @@ -28,10 +28,11 @@ pub fn main() { target_os = "emscripten", target_os = "freebsd", target_os = "fuchsia", + target_os = "illumos", target_os = "linux", target_os = "macos", target_os = "netbsd", target_os = "openbsd", - target_os = "vxworks", - target_os = "solaris"))] + target_os = "solaris", + target_os = "vxworks"))] pub fn main() { } diff --git a/src/test/ui/x86stdcall2.rs b/src/test/ui/abi/x86stdcall2.rs similarity index 100% rename from src/test/ui/x86stdcall2.rs rename to src/test/ui/abi/x86stdcall2.rs diff --git a/src/test/ui/default-alloc-error-hook.rs b/src/test/ui/alloc-error/default-alloc-error-hook.rs similarity index 100% rename from src/test/ui/default-alloc-error-hook.rs rename to src/test/ui/alloc-error/default-alloc-error-hook.rs diff --git a/src/test/ui/alloca-from-derived-tydesc.rs b/src/test/ui/alloca-from-derived-tydesc.rs deleted file mode 100644 index c7f7fbad43..0000000000 --- a/src/test/ui/alloca-from-derived-tydesc.rs +++ /dev/null @@ -1,15 +0,0 @@ -// run-pass - -#![allow(non_camel_case_types)] -#![allow(dead_code)] - - -// pretty-expanded FIXME #23616 - -enum option<T> { some(T), none, } - -struct R<T> {v: Vec<option<T>> } - -fn f<T>() -> Vec<T> { return Vec::new(); } - -pub fn main() { let mut r: R<isize> = R {v: Vec::new()}; r.v = f(); } diff --git a/src/test/ui/allocator/not-an-allocator.stderr b/src/test/ui/allocator/not-an-allocator.stderr index 628b48a45d..e7a9ce94af 100644 --- a/src/test/ui/allocator/not-an-allocator.stderr +++ b/src/test/ui/allocator/not-an-allocator.stderr @@ -6,11 +6,6 @@ LL | #[global_allocator] LL | static A: usize = 0; | ^^^^^^^^^^^^^^^^^^^^ the trait `GlobalAlloc` is not implemented for `usize` | -note: required by `std::alloc::GlobalAlloc::alloc` - --> $SRC_DIR/core/src/alloc/global.rs:LL:COL - | -LL | unsafe fn alloc(&self, layout: Layout) -> *mut u8; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied @@ -21,11 +16,6 @@ LL | #[global_allocator] LL | static A: usize = 0; | ^^^^^^^^^^^^^^^^^^^^ the trait `GlobalAlloc` is not implemented for `usize` | -note: required by `std::alloc::GlobalAlloc::dealloc` - --> $SRC_DIR/core/src/alloc/global.rs:LL:COL - | -LL | unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied @@ -36,11 +26,6 @@ LL | #[global_allocator] LL | static A: usize = 0; | ^^^^^^^^^^^^^^^^^^^^ the trait `GlobalAlloc` is not implemented for `usize` | -note: required by `std::alloc::GlobalAlloc::realloc` - --> $SRC_DIR/core/src/alloc/global.rs:LL:COL - | -LL | unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied @@ -51,11 +36,6 @@ LL | #[global_allocator] LL | static A: usize = 0; | ^^^^^^^^^^^^^^^^^^^^ the trait `GlobalAlloc` is not implemented for `usize` | -note: required by `std::alloc::GlobalAlloc::alloc_zeroed` - --> $SRC_DIR/core/src/alloc/global.rs:LL:COL - | -LL | unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/src/test/ui/argument-passing.rs b/src/test/ui/argument-passing.rs deleted file mode 100644 index 74759a4a6b..0000000000 --- a/src/test/ui/argument-passing.rs +++ /dev/null @@ -1,25 +0,0 @@ -// run-pass - -struct X { - x: isize -} - -fn f1(a: &mut X, b: &mut isize, c: isize) -> isize { - let r = a.x + *b + c; - a.x = 0; - *b = 10; - return r; -} - -fn f2<F>(a: isize, f: F) -> isize where F: FnOnce(isize) { f(1); return a; } - -pub fn main() { - let mut a = X {x: 1}; - let mut b = 2; - let c = 3; - assert_eq!(f1(&mut a, &mut b, c), 6); - assert_eq!(a.x, 0); - assert_eq!(b, 10); - assert_eq!(f2(a.x, |_| a.x = 50), 0); - assert_eq!(a.x, 50); -} diff --git a/src/test/ui/byte-literals.rs b/src/test/ui/array-slice-vec/byte-literals.rs similarity index 100% rename from src/test/ui/byte-literals.rs rename to src/test/ui/array-slice-vec/byte-literals.rs diff --git a/src/test/ui/mut-vstore-expr.rs b/src/test/ui/array-slice-vec/mut-vstore-expr.rs similarity index 100% rename from src/test/ui/mut-vstore-expr.rs rename to src/test/ui/array-slice-vec/mut-vstore-expr.rs diff --git a/src/test/ui/asm/aarch64/bad-reg.rs b/src/test/ui/asm/aarch64/bad-reg.rs index 22d0499a1c..4d7a7fd31f 100644 --- a/src/test/ui/asm/aarch64/bad-reg.rs +++ b/src/test/ui/asm/aarch64/bad-reg.rs @@ -1,7 +1,7 @@ // only-aarch64 // compile-flags: -C target-feature=+fp -#![feature(asm)] +#![feature(asm, asm_const, asm_sym)] fn main() { let mut foo = 0; diff --git a/src/test/ui/asm/aarch64/const.rs b/src/test/ui/asm/aarch64/const.rs index 906dcb0eba..49fe48600c 100644 --- a/src/test/ui/asm/aarch64/const.rs +++ b/src/test/ui/asm/aarch64/const.rs @@ -1,10 +1,9 @@ -// min-llvm-version: 10.0.1 // only-aarch64 // run-pass // revisions: mirunsafeck thirunsafeck // [thirunsafeck]compile-flags: -Z thir-unsafeck -#![feature(asm, global_asm)] +#![feature(asm, global_asm, asm_const)] fn const_generic<const X: usize>() -> usize { unsafe { diff --git a/src/test/ui/asm/aarch64/parse-error.rs b/src/test/ui/asm/aarch64/parse-error.rs index faa5e37b78..bc0aed8fe5 100644 --- a/src/test/ui/asm/aarch64/parse-error.rs +++ b/src/test/ui/asm/aarch64/parse-error.rs @@ -1,6 +1,6 @@ // only-aarch64 -#![feature(asm, global_asm)] +#![feature(asm, global_asm, asm_const)] fn main() { let mut foo = 0; @@ -40,9 +40,9 @@ fn main() { asm!("", clobber_abi(foo)); //~^ ERROR expected string literal asm!("", clobber_abi("C" foo)); - //~^ ERROR expected `)`, found `foo` + //~^ ERROR expected one of `)` or `,`, found `foo` asm!("", clobber_abi("C", foo)); - //~^ ERROR expected `)`, found `,` + //~^ ERROR expected string literal asm!("{}", clobber_abi("C"), const foo); //~^ ERROR arguments are not allowed after clobber_abi //~^^ ERROR attempt to use a non-constant value in a constant @@ -50,8 +50,6 @@ fn main() { //~^ ERROR clobber_abi is not allowed after options asm!("{}", options(), clobber_abi("C"), const foo); //~^ ERROR clobber_abi is not allowed after options - asm!("", clobber_abi("C"), clobber_abi("C")); - //~^ ERROR clobber_abi specified multiple times asm!("{a}", a = const foo, a = const bar); //~^ ERROR duplicate argument named `a` //~^^ ERROR argument never used @@ -110,9 +108,9 @@ global_asm!("{}", options(), const FOO); global_asm!("", clobber_abi(FOO)); //~^ ERROR expected string literal global_asm!("", clobber_abi("C" FOO)); -//~^ ERROR expected `)`, found `FOO` +//~^ ERROR expected one of `)` or `,`, found `FOO` global_asm!("", clobber_abi("C", FOO)); -//~^ ERROR expected `)`, found `,` +//~^ ERROR expected string literal global_asm!("{}", clobber_abi("C"), const FOO); //~^ ERROR arguments are not allowed after clobber_abi //~^^ ERROR `clobber_abi` cannot be used with `global_asm!` @@ -120,8 +118,6 @@ global_asm!("", options(), clobber_abi("C")); //~^ ERROR clobber_abi is not allowed after options global_asm!("{}", options(), clobber_abi("C"), const FOO); //~^ ERROR clobber_abi is not allowed after options -global_asm!("", clobber_abi("C"), clobber_abi("C")); -//~^ ERROR clobber_abi specified multiple times global_asm!("{a}", a = const FOO, a = const BAR); //~^ ERROR duplicate argument named `a` //~^^ ERROR argument never used diff --git a/src/test/ui/asm/aarch64/parse-error.stderr b/src/test/ui/asm/aarch64/parse-error.stderr index 6f318c9b9c..3d88cef5c7 100644 --- a/src/test/ui/asm/aarch64/parse-error.stderr +++ b/src/test/ui/asm/aarch64/parse-error.stderr @@ -96,17 +96,17 @@ error: expected string literal LL | asm!("", clobber_abi(foo)); | ^^^ not a string literal -error: expected `)`, found `foo` +error: expected one of `)` or `,`, found `foo` --> $DIR/parse-error.rs:42:34 | LL | asm!("", clobber_abi("C" foo)); - | ^^^ expected `)` + | ^^^ expected one of `)` or `,` -error: expected `)`, found `,` - --> $DIR/parse-error.rs:44:33 +error: expected string literal + --> $DIR/parse-error.rs:44:35 | LL | asm!("", clobber_abi("C", foo)); - | ^ expected `)` + | ^^^ not a string literal error: arguments are not allowed after clobber_abi --> $DIR/parse-error.rs:46:38 @@ -132,16 +132,8 @@ LL | asm!("{}", options(), clobber_abi("C"), const foo); | | | options -error: clobber_abi specified multiple times - --> $DIR/parse-error.rs:53:36 - | -LL | asm!("", clobber_abi("C"), clobber_abi("C")); - | ---------------- ^^^^^^^^^^^^^^^^ - | | - | clobber_abi previously specified here - error: duplicate argument named `a` - --> $DIR/parse-error.rs:55:36 + --> $DIR/parse-error.rs:53:36 | LL | asm!("{a}", a = const foo, a = const bar); | ------------- ^^^^^^^^^^^^^ duplicate argument @@ -149,7 +141,7 @@ LL | asm!("{a}", a = const foo, a = const bar); | previously here error: argument never used - --> $DIR/parse-error.rs:55:36 + --> $DIR/parse-error.rs:53:36 | LL | asm!("{a}", a = const foo, a = const bar); | ^^^^^^^^^^^^^ argument never used @@ -157,13 +149,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:60:18 + --> $DIR/parse-error.rs:58:18 | LL | asm!("", a = in("x0") foo); | ^^^^^^^^^^^^^^^^ error: named arguments cannot follow explicit register arguments - --> $DIR/parse-error.rs:62:35 + --> $DIR/parse-error.rs:60:35 | LL | asm!("{a}", in("x0") foo, a = const bar); | ------------ ^^^^^^^^^^^^^ named argument @@ -171,7 +163,7 @@ LL | asm!("{a}", in("x0") foo, a = const bar); | explicit register argument error: named arguments cannot follow explicit register arguments - --> $DIR/parse-error.rs:65:35 + --> $DIR/parse-error.rs:63:35 | LL | asm!("{a}", in("x0") foo, a = const bar); | ------------ ^^^^^^^^^^^^^ named argument @@ -179,7 +171,7 @@ LL | asm!("{a}", in("x0") foo, a = const bar); | explicit register argument error: positional arguments cannot follow named arguments or explicit register arguments - --> $DIR/parse-error.rs:68:35 + --> $DIR/parse-error.rs:66:35 | LL | asm!("{1}", in("x0") foo, const bar); | ------------ ^^^^^^^^^ positional argument @@ -187,19 +179,19 @@ LL | asm!("{1}", in("x0") foo, const bar); | explicit register argument error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `""` - --> $DIR/parse-error.rs:71:29 + --> $DIR/parse-error.rs:69:29 | LL | asm!("", options(), ""); | ^^ expected one of 9 possible tokens error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `"{}"` - --> $DIR/parse-error.rs:73:33 + --> $DIR/parse-error.rs:71:33 | LL | asm!("{}", in(reg) foo, "{}", out(reg) foo); | ^^^^ expected one of 9 possible tokens error: asm template must be a string literal - --> $DIR/parse-error.rs:75:14 + --> $DIR/parse-error.rs:73:14 | LL | asm!(format!("{{{}}}", 0), in(reg) foo); | ^^^^^^^^^^^^^^^^^^^^ @@ -207,7 +199,7 @@ LL | asm!(format!("{{{}}}", 0), in(reg) foo); = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) error: asm template must be a string literal - --> $DIR/parse-error.rs:77:21 + --> $DIR/parse-error.rs:75:21 | LL | asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar); | ^^^^^^^^^^^^^^^^^^^^ @@ -215,79 +207,79 @@ LL | asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar); = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) error: _ cannot be used for input operands - --> $DIR/parse-error.rs:79:28 + --> $DIR/parse-error.rs:77:28 | LL | asm!("{}", in(reg) _); | ^ error: _ cannot be used for input operands - --> $DIR/parse-error.rs:81:31 + --> $DIR/parse-error.rs:79:31 | LL | asm!("{}", inout(reg) _); | ^ error: _ cannot be used for input operands - --> $DIR/parse-error.rs:83:35 + --> $DIR/parse-error.rs:81:35 | LL | asm!("{}", inlateout(reg) _); | ^ error: requires at least a template string argument - --> $DIR/parse-error.rs:90:1 + --> $DIR/parse-error.rs:88:1 | LL | global_asm!(); | ^^^^^^^^^^^^^ error: asm template must be a string literal - --> $DIR/parse-error.rs:92:13 + --> $DIR/parse-error.rs:90:13 | LL | global_asm!(FOO); | ^^^ error: expected token: `,` - --> $DIR/parse-error.rs:94:18 + --> $DIR/parse-error.rs:92:18 | LL | global_asm!("{}" FOO); | ^^^ expected `,` error: expected operand, options, or additional template string - --> $DIR/parse-error.rs:96:19 + --> $DIR/parse-error.rs:94:19 | LL | global_asm!("{}", FOO); | ^^^ expected operand, options, or additional template string error: expected expression, found end of macro arguments - --> $DIR/parse-error.rs:98:24 + --> $DIR/parse-error.rs:96:24 | LL | global_asm!("{}", const); | ^ expected expression error: expected one of `,`, `.`, `?`, or an operator, found `FOO` - --> $DIR/parse-error.rs:100:30 + --> $DIR/parse-error.rs:98:30 | LL | global_asm!("{}", const(reg) FOO); | ^^^ expected one of `,`, `.`, `?`, or an operator error: expected one of `)`, `att_syntax`, or `raw`, found `FOO` - --> $DIR/parse-error.rs:102:25 + --> $DIR/parse-error.rs:100:25 | LL | global_asm!("", options(FOO)); | ^^^ expected one of `)`, `att_syntax`, or `raw` error: expected one of `)`, `att_syntax`, or `raw`, found `nomem` - --> $DIR/parse-error.rs:104:25 + --> $DIR/parse-error.rs:102:25 | LL | global_asm!("", options(nomem FOO)); | ^^^^^ expected one of `)`, `att_syntax`, or `raw` error: expected one of `)`, `att_syntax`, or `raw`, found `nomem` - --> $DIR/parse-error.rs:106:25 + --> $DIR/parse-error.rs:104:25 | LL | global_asm!("", options(nomem, FOO)); | ^^^^^ expected one of `)`, `att_syntax`, or `raw` error: arguments are not allowed after options - --> $DIR/parse-error.rs:108:30 + --> $DIR/parse-error.rs:106:30 | LL | global_asm!("{}", options(), const FOO); | --------- ^^^^^^^^^ argument @@ -295,25 +287,25 @@ LL | global_asm!("{}", options(), const FOO); | previous options error: expected string literal - --> $DIR/parse-error.rs:110:29 + --> $DIR/parse-error.rs:108:29 | LL | global_asm!("", clobber_abi(FOO)); | ^^^ not a string literal -error: expected `)`, found `FOO` - --> $DIR/parse-error.rs:112:33 +error: expected one of `)` or `,`, found `FOO` + --> $DIR/parse-error.rs:110:33 | LL | global_asm!("", clobber_abi("C" FOO)); - | ^^^ expected `)` + | ^^^ expected one of `)` or `,` -error: expected `)`, found `,` - --> $DIR/parse-error.rs:114:32 +error: expected string literal + --> $DIR/parse-error.rs:112:34 | LL | global_asm!("", clobber_abi("C", FOO)); - | ^ expected `)` + | ^^^ not a string literal error: arguments are not allowed after clobber_abi - --> $DIR/parse-error.rs:116:37 + --> $DIR/parse-error.rs:114:37 | LL | global_asm!("{}", clobber_abi("C"), const FOO); | ---------------- ^^^^^^^^^ argument @@ -321,13 +313,13 @@ LL | global_asm!("{}", clobber_abi("C"), const FOO); | clobber_abi error: `clobber_abi` cannot be used with `global_asm!` - --> $DIR/parse-error.rs:116:19 + --> $DIR/parse-error.rs:114:19 | LL | global_asm!("{}", clobber_abi("C"), const FOO); | ^^^^^^^^^^^^^^^^ error: clobber_abi is not allowed after options - --> $DIR/parse-error.rs:119:28 + --> $DIR/parse-error.rs:117:28 | LL | global_asm!("", options(), clobber_abi("C")); | --------- ^^^^^^^^^^^^^^^^ @@ -335,23 +327,15 @@ LL | global_asm!("", options(), clobber_abi("C")); | options error: clobber_abi is not allowed after options - --> $DIR/parse-error.rs:121:30 + --> $DIR/parse-error.rs:119:30 | LL | global_asm!("{}", options(), clobber_abi("C"), const FOO); | --------- ^^^^^^^^^^^^^^^^ | | | options -error: clobber_abi specified multiple times - --> $DIR/parse-error.rs:123:35 - | -LL | global_asm!("", clobber_abi("C"), clobber_abi("C")); - | ---------------- ^^^^^^^^^^^^^^^^ - | | - | clobber_abi previously specified here - error: duplicate argument named `a` - --> $DIR/parse-error.rs:125:35 + --> $DIR/parse-error.rs:121:35 | LL | global_asm!("{a}", a = const FOO, a = const BAR); | ------------- ^^^^^^^^^^^^^ duplicate argument @@ -359,7 +343,7 @@ LL | global_asm!("{a}", a = const FOO, a = const BAR); | previously here error: argument never used - --> $DIR/parse-error.rs:125:35 + --> $DIR/parse-error.rs:121:35 | LL | global_asm!("{a}", a = const FOO, a = const BAR); | ^^^^^^^^^^^^^ argument never used @@ -367,19 +351,19 @@ LL | global_asm!("{a}", a = const FOO, a = const BAR); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"` error: expected one of `clobber_abi`, `const`, or `options`, found `""` - --> $DIR/parse-error.rs:128:28 + --> $DIR/parse-error.rs:124:28 | LL | global_asm!("", options(), ""); | ^^ expected one of `clobber_abi`, `const`, or `options` error: expected one of `clobber_abi`, `const`, or `options`, found `"{}"` - --> $DIR/parse-error.rs:130:30 + --> $DIR/parse-error.rs:126:30 | LL | global_asm!("{}", const FOO, "{}", const FOO); | ^^^^ expected one of `clobber_abi`, `const`, or `options` error: asm template must be a string literal - --> $DIR/parse-error.rs:132:13 + --> $DIR/parse-error.rs:128:13 | LL | global_asm!(format!("{{{}}}", 0), const FOO); | ^^^^^^^^^^^^^^^^^^^^ @@ -387,7 +371,7 @@ LL | global_asm!(format!("{{{}}}", 0), const FOO); = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) error: asm template must be a string literal - --> $DIR/parse-error.rs:134:20 + --> $DIR/parse-error.rs:130:20 | LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR); | ^^^^^^^^^^^^^^^^^^^^ @@ -413,7 +397,7 @@ LL | asm!("{}", clobber_abi("C"), const foo); | ^^^ non-constant value error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:55:31 + --> $DIR/parse-error.rs:53:31 | LL | let mut foo = 0; | ---------- help: consider using `const` instead of `let`: `const foo` @@ -422,7 +406,7 @@ 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:55:46 + --> $DIR/parse-error.rs:53:46 | LL | let mut bar = 0; | ---------- help: consider using `const` instead of `let`: `const bar` @@ -431,7 +415,7 @@ 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:62:45 + --> $DIR/parse-error.rs:60:45 | LL | let mut bar = 0; | ---------- help: consider using `const` instead of `let`: `const bar` @@ -440,7 +424,7 @@ LL | asm!("{a}", in("x0") foo, a = const bar); | ^^^ non-constant value error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:65:45 + --> $DIR/parse-error.rs:63:45 | LL | let mut bar = 0; | ---------- help: consider using `const` instead of `let`: `const bar` @@ -449,7 +433,7 @@ LL | asm!("{a}", in("x0") foo, a = const bar); | ^^^ non-constant value error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:68:41 + --> $DIR/parse-error.rs:66:41 | LL | let mut bar = 0; | ---------- help: consider using `const` instead of `let`: `const bar` @@ -457,6 +441,6 @@ LL | let mut bar = 0; LL | asm!("{1}", in("x0") foo, const bar); | ^^^ non-constant value -error: aborting due to 66 previous errors +error: aborting due to 64 previous errors For more information about this error, try `rustc --explain E0435`. diff --git a/src/test/ui/asm/aarch64/srcloc.rs b/src/test/ui/asm/aarch64/srcloc.rs index 58feb52653..143ed18240 100644 --- a/src/test/ui/asm/aarch64/srcloc.rs +++ b/src/test/ui/asm/aarch64/srcloc.rs @@ -1,4 +1,3 @@ -// min-llvm-version: 10.0.1 // only-aarch64 // build-fail // compile-flags: -Ccodegen-units=1 diff --git a/src/test/ui/asm/aarch64/srcloc.stderr b/src/test/ui/asm/aarch64/srcloc.stderr index 96dab1bce0..f03fbf28d3 100644 --- a/src/test/ui/asm/aarch64/srcloc.stderr +++ b/src/test/ui/asm/aarch64/srcloc.stderr @@ -1,5 +1,5 @@ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:11:15 + --> $DIR/srcloc.rs:10:15 | LL | asm!("invalid_instruction"); | ^ @@ -11,7 +11,7 @@ LL | invalid_instruction | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:15:13 + --> $DIR/srcloc.rs:14:13 | LL | invalid_instruction | ^ @@ -23,7 +23,7 @@ LL | invalid_instruction | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:20:13 + --> $DIR/srcloc.rs:19:13 | LL | invalid_instruction | ^ @@ -35,7 +35,7 @@ LL | invalid_instruction | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:26:13 + --> $DIR/srcloc.rs:25:13 | LL | invalid_instruction | ^ @@ -47,7 +47,7 @@ LL | invalid_instruction | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:33:13 + --> $DIR/srcloc.rs:32:13 | LL | invalid_instruction | ^ @@ -59,7 +59,7 @@ LL | invalid_instruction | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:38:14 + --> $DIR/srcloc.rs:37:14 | LL | asm!(concat!("invalid", "_", "instruction")); | ^ @@ -71,7 +71,7 @@ LL | invalid_instruction | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:42:14 + --> $DIR/srcloc.rs:41:14 | LL | "invalid_instruction", | ^ @@ -83,7 +83,7 @@ LL | invalid_instruction | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:48:14 + --> $DIR/srcloc.rs:47:14 | LL | "invalid_instruction", | ^ @@ -95,7 +95,7 @@ LL | invalid_instruction | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:55:14 + --> $DIR/srcloc.rs:54:14 | LL | "invalid_instruction", | ^ @@ -107,7 +107,7 @@ LL | invalid_instruction | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:62:13 + --> $DIR/srcloc.rs:61:13 | LL | concat!("invalid", "_", "instruction"), | ^ @@ -119,7 +119,7 @@ LL | invalid_instruction | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:69:13 + --> $DIR/srcloc.rs:68:13 | LL | concat!("invalid", "_", "instruction"), | ^ @@ -131,7 +131,7 @@ LL | invalid_instruction | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:76:14 + --> $DIR/srcloc.rs:75:14 | LL | "invalid_instruction1", | ^ @@ -143,7 +143,7 @@ LL | invalid_instruction1 | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:77:14 + --> $DIR/srcloc.rs:76:14 | LL | "invalid_instruction2", | ^ @@ -155,7 +155,7 @@ LL | invalid_instruction2 | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:83:13 + --> $DIR/srcloc.rs:82:13 | LL | concat!( | ^ @@ -167,7 +167,7 @@ LL | invalid_instruction1 | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:83:13 + --> $DIR/srcloc.rs:82:13 | LL | concat!( | ^ @@ -179,7 +179,7 @@ LL | invalid_instruction2 | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:92:13 + --> $DIR/srcloc.rs:91:13 | LL | concat!( | ^ @@ -191,7 +191,7 @@ LL | invalid_instruction1 | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:92:13 + --> $DIR/srcloc.rs:91:13 | LL | concat!( | ^ @@ -203,7 +203,7 @@ LL | invalid_instruction2 | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:96:13 + --> $DIR/srcloc.rs:95:13 | LL | concat!( | ^ @@ -215,7 +215,7 @@ LL | invalid_instruction3 | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:96:13 + --> $DIR/srcloc.rs:95:13 | LL | concat!( | ^ @@ -227,7 +227,7 @@ LL | invalid_instruction4 | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:107:13 + --> $DIR/srcloc.rs:106:13 | LL | concat!( | ^ @@ -239,7 +239,7 @@ LL | invalid_instruction1 | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:107:13 + --> $DIR/srcloc.rs:106:13 | LL | concat!( | ^ @@ -251,7 +251,7 @@ LL | invalid_instruction2 | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:111:13 + --> $DIR/srcloc.rs:110:13 | LL | concat!( | ^ @@ -263,7 +263,7 @@ LL | invalid_instruction3 | ^ error: unrecognized instruction mnemonic - --> $DIR/srcloc.rs:111:13 + --> $DIR/srcloc.rs:110:13 | LL | concat!( | ^ diff --git a/src/test/ui/asm/aarch64/sym.rs b/src/test/ui/asm/aarch64/sym.rs index 6fd1192eec..b0dd143a0a 100644 --- a/src/test/ui/asm/aarch64/sym.rs +++ b/src/test/ui/asm/aarch64/sym.rs @@ -1,9 +1,8 @@ -// min-llvm-version: 10.0.1 // only-aarch64 // only-linux // run-pass -#![feature(asm, thread_local)] +#![feature(asm, thread_local, asm_sym)] extern "C" fn f1() -> i32 { 111 @@ -76,5 +75,7 @@ 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(); + }) + .join() + .unwrap(); } diff --git a/src/test/ui/asm/aarch64/type-check-2.rs b/src/test/ui/asm/aarch64/type-check-2.rs index cf25dcb930..e1e8a91dda 100644 --- a/src/test/ui/asm/aarch64/type-check-2.rs +++ b/src/test/ui/asm/aarch64/type-check-2.rs @@ -1,6 +1,6 @@ // only-aarch64 -#![feature(asm, repr_simd, never_type)] +#![feature(asm, repr_simd, never_type, asm_sym)] #[repr(simd)] #[derive(Clone, Copy)] diff --git a/src/test/ui/asm/aarch64/type-check-3.rs b/src/test/ui/asm/aarch64/type-check-3.rs index d0d5954ca4..fc1831a520 100644 --- a/src/test/ui/asm/aarch64/type-check-3.rs +++ b/src/test/ui/asm/aarch64/type-check-3.rs @@ -1,13 +1,13 @@ // only-aarch64 // compile-flags: -C target-feature=+neon -#![feature(asm, global_asm, repr_simd, stdsimd)] +#![feature(asm, global_asm, repr_simd, stdsimd, asm_const)] use std::arch::aarch64::float64x2_t; #[repr(simd)] #[derive(Copy, Clone)] -struct Simd256bit(f64, f64,f64, f64); +struct Simd256bit(f64, f64, f64, f64); fn main() { let f64x2: float64x2_t = unsafe { std::mem::transmute(0i128) }; @@ -42,7 +42,6 @@ fn main() { asm!("{:b}", in(vreg) 0u64); asm!("{:d}", in(vreg_low16) f64x2); - // Template modifier suggestions for sub-registers asm!("{}", in(reg) 0u8); diff --git a/src/test/ui/asm/aarch64/type-check-3.stderr b/src/test/ui/asm/aarch64/type-check-3.stderr index c31a62ae79..ed9d3147b9 100644 --- a/src/test/ui/asm/aarch64/type-check-3.stderr +++ b/src/test/ui/asm/aarch64/type-check-3.stderr @@ -1,5 +1,5 @@ warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:48:15 + --> $DIR/type-check-3.rs:47:15 | LL | asm!("{}", in(reg) 0u8); | ^^ --- for this argument @@ -9,7 +9,7 @@ LL | asm!("{}", in(reg) 0u8); = help: or use the `x` modifier to keep the default formatting of `x0` warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:50:15 + --> $DIR/type-check-3.rs:49:15 | LL | asm!("{}", in(reg) 0u16); | ^^ ---- for this argument @@ -18,7 +18,7 @@ LL | asm!("{}", in(reg) 0u16); = help: or use the `x` modifier to keep the default formatting of `x0` warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:52:15 + --> $DIR/type-check-3.rs:51:15 | LL | asm!("{}", in(reg) 0i32); | ^^ ---- for this argument @@ -27,7 +27,7 @@ LL | asm!("{}", in(reg) 0i32); = help: or use the `x` modifier to keep the default formatting of `x0` warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:54:15 + --> $DIR/type-check-3.rs:53:15 | LL | asm!("{}", in(reg) 0f32); | ^^ ---- for this argument @@ -36,7 +36,7 @@ LL | asm!("{}", in(reg) 0f32); = help: or use the `x` modifier to keep the default formatting of `x0` warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:57:15 + --> $DIR/type-check-3.rs:56:15 | LL | asm!("{}", in(vreg) 0i16); | ^^ ---- for this argument @@ -45,7 +45,7 @@ LL | asm!("{}", in(vreg) 0i16); = help: or use the `v` modifier to keep the default formatting of `v0` warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:59:15 + --> $DIR/type-check-3.rs:58:15 | LL | asm!("{}", in(vreg) 0f32); | ^^ ---- for this argument @@ -54,7 +54,7 @@ LL | asm!("{}", in(vreg) 0f32); = help: or use the `v` modifier to keep the default formatting of `v0` warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:61:15 + --> $DIR/type-check-3.rs:60:15 | LL | asm!("{}", in(vreg) 0f64); | ^^ ---- for this argument @@ -63,7 +63,7 @@ LL | asm!("{}", in(vreg) 0f64); = help: or use the `v` modifier to keep the default formatting of `v0` warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:63:15 + --> $DIR/type-check-3.rs:62:15 | LL | asm!("{}", in(vreg_low16) 0f64); | ^^ ---- for this argument @@ -72,7 +72,7 @@ LL | asm!("{}", in(vreg_low16) 0f64); = help: or use the `v` modifier to keep the default formatting of `v0` warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:66:15 + --> $DIR/type-check-3.rs:65:15 | LL | asm!("{0} {0}", in(reg) 0i16); | ^^^ ^^^ ---- for this argument @@ -81,7 +81,7 @@ LL | asm!("{0} {0}", in(reg) 0i16); = help: or use the `x` modifier to keep the default formatting of `x0` warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:68:15 + --> $DIR/type-check-3.rs:67:15 | LL | asm!("{0} {0:x}", in(reg) 0i16); | ^^^ ---- for this argument @@ -90,7 +90,7 @@ LL | asm!("{0} {0:x}", in(reg) 0i16); = help: or use the `x` modifier to keep the default formatting of `x0` error: type `i128` cannot be used with this register class - --> $DIR/type-check-3.rs:73:28 + --> $DIR/type-check-3.rs:72:28 | LL | asm!("{}", in(reg) 0i128); | ^^^^^ @@ -98,7 +98,7 @@ LL | asm!("{}", in(reg) 0i128); = note: register class `reg` supports these types: i8, i16, i32, i64, f32, f64 error: type `float64x2_t` cannot be used with this register class - --> $DIR/type-check-3.rs:75:28 + --> $DIR/type-check-3.rs:74:28 | LL | asm!("{}", in(reg) f64x2); | ^^^^^ @@ -106,7 +106,7 @@ LL | asm!("{}", in(reg) f64x2); = note: register class `reg` supports these types: i8, i16, i32, i64, f32, f64 error: type `Simd256bit` cannot be used with this register class - --> $DIR/type-check-3.rs:77:29 + --> $DIR/type-check-3.rs:76:29 | LL | asm!("{}", in(vreg) f64x4); | ^^^^^ @@ -114,7 +114,7 @@ LL | asm!("{}", in(vreg) f64x4); = note: register class `vreg` supports these types: i8, i16, i32, i64, f32, f64, i8x8, i16x4, i32x2, i64x1, f32x2, f64x1, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2 error: incompatible types for asm inout argument - --> $DIR/type-check-3.rs:88:33 + --> $DIR/type-check-3.rs:87:33 | LL | asm!("{:x}", inout(reg) 0u32 => val_f32); | ^^^^ ^^^^^^^ type `f32` @@ -124,7 +124,7 @@ LL | asm!("{:x}", inout(reg) 0u32 => val_f32); = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size error: incompatible types for asm inout argument - --> $DIR/type-check-3.rs:90:33 + --> $DIR/type-check-3.rs:89:33 | LL | asm!("{:x}", inout(reg) 0u32 => val_ptr); | ^^^^ ^^^^^^^ type `*mut u8` @@ -134,7 +134,7 @@ LL | asm!("{:x}", inout(reg) 0u32 => val_ptr); = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size error: incompatible types for asm inout argument - --> $DIR/type-check-3.rs:92:33 + --> $DIR/type-check-3.rs:91:33 | LL | asm!("{:x}", inout(reg) main => val_u32); | ^^^^ ^^^^^^^ type `u32` @@ -144,7 +144,7 @@ LL | asm!("{:x}", inout(reg) main => val_u32); = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size error[E0013]: constants cannot refer to statics - --> $DIR/type-check-3.rs:108:25 + --> $DIR/type-check-3.rs:107:25 | LL | global_asm!("{}", const S); | ^ @@ -152,7 +152,7 @@ LL | global_asm!("{}", const S); = help: consider extracting the value of the `static` to a `const`, and referring to that error[E0013]: constants cannot refer to statics - --> $DIR/type-check-3.rs:111:35 + --> $DIR/type-check-3.rs:110:35 | LL | global_asm!("{}", const const_foo(S)); | ^ @@ -160,7 +160,7 @@ LL | global_asm!("{}", const const_foo(S)); = help: consider extracting the value of the `static` to a `const`, and referring to that error[E0013]: constants cannot refer to statics - --> $DIR/type-check-3.rs:114:35 + --> $DIR/type-check-3.rs:113:35 | LL | global_asm!("{}", const const_bar(S)); | ^ diff --git a/src/test/ui/asm/bad-template.rs b/src/test/ui/asm/bad-template.rs index fca77e7aa7..b062c45e6e 100644 --- a/src/test/ui/asm/bad-template.rs +++ b/src/test/ui/asm/bad-template.rs @@ -10,7 +10,7 @@ // [aarch64_thirunsafeck] needs-llvm-components: aarch64 // [aarch64_mirunsafeck] needs-llvm-components: aarch64 -#![feature(no_core, lang_items, rustc_attrs)] +#![feature(no_core, lang_items, rustc_attrs, asm_const)] #![no_core] #[rustc_builtin_macro] diff --git a/src/test/ui/asm/issue-89305.rs b/src/test/ui/asm/issue-89305.rs index bdcf3f305e..a4b22e2102 100644 --- a/src/test/ui/asm/issue-89305.rs +++ b/src/test/ui/asm/issue-89305.rs @@ -2,6 +2,7 @@ // as both unused and possibly-uninitialized. // check-pass +// needs-asm-support #![feature(asm)] #![warn(unused)] diff --git a/src/test/ui/asm/issue-89305.stderr b/src/test/ui/asm/issue-89305.stderr index 9cc127b44d..3fb1526183 100644 --- a/src/test/ui/asm/issue-89305.stderr +++ b/src/test/ui/asm/issue-89305.stderr @@ -1,11 +1,11 @@ warning: unused variable: `x` - --> $DIR/issue-89305.rs:11:13 + --> $DIR/issue-89305.rs:12:13 | LL | let x: () = asm!("nop"); | ^ help: if this is intentional, prefix it with an underscore: `_x` | note: the lint level is defined here - --> $DIR/issue-89305.rs:7:9 + --> $DIR/issue-89305.rs:8:9 | LL | #![warn(unused)] | ^^^^^^ diff --git a/src/test/ui/asm/naked-functions.rs b/src/test/ui/asm/naked-functions.rs index 803311d423..7154ce26ef 100644 --- a/src/test/ui/asm/naked-functions.rs +++ b/src/test/ui/asm/naked-functions.rs @@ -7,11 +7,15 @@ #![feature(llvm_asm)] #![feature(naked_functions)] #![feature(or_patterns)] +#![feature(asm_const, asm_sym)] #![crate_type = "lib"] #![allow(deprecated)] // llvm_asm! #[repr(C)] -pub struct P { x: u8, y: u16 } +pub struct P { + x: u8, + y: u16, +} #[naked] pub unsafe extern "C" fn patterns( @@ -143,21 +147,27 @@ pub unsafe fn default_abi() { } #[naked] -pub unsafe extern "Rust" fn rust_abi() { +pub unsafe fn rust_abi() { //~^ WARN Rust ABI is unsupported in naked functions asm!("", options(noreturn)); } #[naked] pub extern "C" fn valid_a<T>() -> T { - unsafe { asm!("", options(noreturn)); } + unsafe { + asm!("", options(noreturn)); + } } #[naked] pub extern "C" fn valid_b() { - unsafe { { { - asm!("", options(noreturn)); ; ; ; - } ; } ; } + unsafe { + { + { + asm!("", options(noreturn)); + }; + }; + } } #[naked] diff --git a/src/test/ui/asm/naked-functions.stderr b/src/test/ui/asm/naked-functions.stderr index 465db634aa..e4ddb97ca2 100644 --- a/src/test/ui/asm/naked-functions.stderr +++ b/src/test/ui/asm/naked-functions.stderr @@ -1,35 +1,35 @@ error: asm with the `pure` option must have at least one output - --> $DIR/naked-functions.rs:131:14 + --> $DIR/naked-functions.rs:135:14 | LL | asm!("", options(readonly, nostack), options(pure)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ error: patterns not allowed in naked function parameters - --> $DIR/naked-functions.rs:18:5 + --> $DIR/naked-functions.rs:22:5 | LL | mut a: u32, | ^^^^^ error: patterns not allowed in naked function parameters - --> $DIR/naked-functions.rs:20:5 + --> $DIR/naked-functions.rs:24:5 | LL | &b: &i32, | ^^ error: patterns not allowed in naked function parameters - --> $DIR/naked-functions.rs:22:6 + --> $DIR/naked-functions.rs:26:6 | LL | (None | Some(_)): Option<std::ptr::NonNull<u8>>, | ^^^^^^^^^^^^^^ error: patterns not allowed in naked function parameters - --> $DIR/naked-functions.rs:24:5 + --> $DIR/naked-functions.rs:28:5 | LL | P { x, y }: P, | ^^^^^^^^^^ error: referencing function parameters is not allowed in naked functions - --> $DIR/naked-functions.rs:34:5 + --> $DIR/naked-functions.rs:38:5 | LL | a + 1 | ^ @@ -37,7 +37,7 @@ LL | a + 1 = help: follow the calling convention in asm block to use parameters warning: naked functions must contain a single asm block - --> $DIR/naked-functions.rs:31:1 + --> $DIR/naked-functions.rs:35:1 | LL | / pub unsafe extern "C" fn inc(a: u32) -> u32 { LL | | @@ -53,7 +53,7 @@ LL | | } = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408> error: referencing function parameters is not allowed in naked functions - --> $DIR/naked-functions.rs:40:31 + --> $DIR/naked-functions.rs:44:31 | LL | asm!("/* {0} */", in(reg) a, options(noreturn)); | ^ @@ -61,7 +61,7 @@ LL | asm!("/* {0} */", in(reg) a, options(noreturn)); = help: follow the calling convention in asm block to use parameters warning: only `const` and `sym` operands are supported in naked functions - --> $DIR/naked-functions.rs:40:23 + --> $DIR/naked-functions.rs:44:23 | LL | asm!("/* {0} */", in(reg) a, options(noreturn)); | ^^^^^^^^^ @@ -70,7 +70,7 @@ LL | asm!("/* {0} */", in(reg) a, options(noreturn)); = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408> warning: naked functions must contain a single asm block - --> $DIR/naked-functions.rs:47:1 + --> $DIR/naked-functions.rs:51:1 | LL | / pub unsafe extern "C" fn inc_closure(a: u32) -> u32 { LL | | @@ -84,7 +84,7 @@ LL | | } = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408> warning: only `const` and `sym` operands are supported in naked functions - --> $DIR/naked-functions.rs:67:10 + --> $DIR/naked-functions.rs:71:10 | LL | in(reg) a, | ^^^^^^^^^ @@ -102,7 +102,7 @@ LL | out(reg) e, = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408> warning: asm in naked functions must use `noreturn` option - --> $DIR/naked-functions.rs:64:5 + --> $DIR/naked-functions.rs:68:5 | LL | / asm!("/* {0} {1} {2} {3} {4} {5} {6} */", LL | | @@ -117,7 +117,7 @@ LL | | ); = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408> warning: naked functions must contain a single asm block - --> $DIR/naked-functions.rs:54:1 + --> $DIR/naked-functions.rs:58:1 | LL | / pub unsafe extern "C" fn unsupported_operands() { LL | | @@ -141,7 +141,7 @@ LL | | } = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408> warning: naked functions must contain a single asm block - --> $DIR/naked-functions.rs:80:1 + --> $DIR/naked-functions.rs:84:1 | LL | / pub extern "C" fn missing_assembly() { LL | | @@ -153,7 +153,7 @@ LL | | } = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408> warning: asm in naked functions must use `noreturn` option - --> $DIR/naked-functions.rs:89:5 + --> $DIR/naked-functions.rs:93:5 | LL | asm!(""); | ^^^^^^^^ @@ -162,7 +162,7 @@ LL | asm!(""); = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408> warning: asm in naked functions must use `noreturn` option - --> $DIR/naked-functions.rs:92:5 + --> $DIR/naked-functions.rs:96:5 | LL | asm!(""); | ^^^^^^^^ @@ -171,7 +171,7 @@ LL | asm!(""); = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408> warning: asm in naked functions must use `noreturn` option - --> $DIR/naked-functions.rs:95:5 + --> $DIR/naked-functions.rs:99:5 | LL | asm!(""); | ^^^^^^^^ @@ -180,7 +180,7 @@ LL | asm!(""); = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408> warning: naked functions must contain a single asm block - --> $DIR/naked-functions.rs:86:1 + --> $DIR/naked-functions.rs:90:1 | LL | / pub extern "C" fn too_many_asm_blocks() { LL | | @@ -202,7 +202,7 @@ LL | | } = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408> error: referencing function parameters is not allowed in naked functions - --> $DIR/naked-functions.rs:106:11 + --> $DIR/naked-functions.rs:110:11 | LL | *&y | ^ @@ -210,7 +210,7 @@ LL | *&y = help: follow the calling convention in asm block to use parameters warning: naked functions must contain a single asm block - --> $DIR/naked-functions.rs:103:5 + --> $DIR/naked-functions.rs:107:5 | LL | / pub extern "C" fn inner(y: usize) -> usize { LL | | @@ -225,7 +225,7 @@ LL | | } = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408> warning: the LLVM-style inline assembly is unsupported in naked functions - --> $DIR/naked-functions.rs:116:5 + --> $DIR/naked-functions.rs:120:5 | LL | llvm_asm!(""); | ^^^^^^^^^^^^^ @@ -236,7 +236,7 @@ LL | llvm_asm!(""); = note: this warning originates in the macro `llvm_asm` (in Nightly builds, run with -Z macro-backtrace for more info) warning: naked functions must contain a single asm block - --> $DIR/naked-functions.rs:113:1 + --> $DIR/naked-functions.rs:117:1 | LL | / unsafe extern "C" fn llvm() -> ! { LL | | @@ -252,7 +252,7 @@ LL | | } = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408> warning: asm options unsupported in naked functions: `nomem`, `preserves_flags` - --> $DIR/naked-functions.rs:124:5 + --> $DIR/naked-functions.rs:128:5 | LL | asm!("", options(nomem, preserves_flags, noreturn)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -261,7 +261,7 @@ LL | asm!("", options(nomem, preserves_flags, noreturn)); = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408> warning: asm options unsupported in naked functions: `nostack`, `pure`, `readonly` - --> $DIR/naked-functions.rs:131:5 + --> $DIR/naked-functions.rs:135:5 | LL | asm!("", options(readonly, nostack), options(pure)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -270,7 +270,7 @@ LL | asm!("", options(readonly, nostack), options(pure)); = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408> warning: asm in naked functions must use `noreturn` option - --> $DIR/naked-functions.rs:131:5 + --> $DIR/naked-functions.rs:135:5 | LL | asm!("", options(readonly, nostack), options(pure)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -279,7 +279,7 @@ LL | asm!("", options(readonly, nostack), options(pure)); = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408> warning: Rust ABI is unsupported in naked functions - --> $DIR/naked-functions.rs:140:15 + --> $DIR/naked-functions.rs:144:15 | LL | pub unsafe fn default_abi() { | ^^^^^^^^^^^ @@ -287,13 +287,13 @@ LL | pub unsafe fn default_abi() { = note: `#[warn(undefined_naked_function_abi)]` on by default warning: Rust ABI is unsupported in naked functions - --> $DIR/naked-functions.rs:146:29 + --> $DIR/naked-functions.rs:150:15 | -LL | pub unsafe extern "Rust" fn rust_abi() { - | ^^^^^^^^ +LL | pub unsafe fn rust_abi() { + | ^^^^^^^^ warning: naked functions cannot be inlined - --> $DIR/naked-functions.rs:180:1 + --> $DIR/naked-functions.rs:190:1 | LL | #[inline] | ^^^^^^^^^ @@ -302,7 +302,7 @@ LL | #[inline] = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408> warning: naked functions cannot be inlined - --> $DIR/naked-functions.rs:188:1 + --> $DIR/naked-functions.rs:198:1 | LL | #[inline(always)] | ^^^^^^^^^^^^^^^^^ @@ -311,7 +311,7 @@ LL | #[inline(always)] = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408> warning: naked functions cannot be inlined - --> $DIR/naked-functions.rs:196:1 + --> $DIR/naked-functions.rs:206:1 | LL | #[inline(never)] | ^^^^^^^^^^^^^^^^ @@ -320,7 +320,7 @@ LL | #[inline(never)] = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408> warning: naked functions cannot be inlined - --> $DIR/naked-functions.rs:204:1 + --> $DIR/naked-functions.rs:214:1 | LL | #[inline] | ^^^^^^^^^ @@ -329,7 +329,7 @@ LL | #[inline] = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408> warning: naked functions cannot be inlined - --> $DIR/naked-functions.rs:207:1 + --> $DIR/naked-functions.rs:217:1 | LL | #[inline(always)] | ^^^^^^^^^^^^^^^^^ @@ -338,7 +338,7 @@ LL | #[inline(always)] = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408> warning: naked functions cannot be inlined - --> $DIR/naked-functions.rs:210:1 + --> $DIR/naked-functions.rs:220:1 | LL | #[inline(never)] | ^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/asm/named-asm-labels.rs b/src/test/ui/asm/named-asm-labels.rs index 82c47945a7..c87188e46a 100644 --- a/src/test/ui/asm/named-asm-labels.rs +++ b/src/test/ui/asm/named-asm-labels.rs @@ -11,7 +11,7 @@ // which causes less readable LLVM errors and in the worst cases causes ICEs // or segfaults based on system dependent behavior and codegen flags. -#![feature(asm, global_asm, naked_functions)] +#![feature(asm, global_asm, naked_functions, asm_const)] #[no_mangle] pub static FOO: usize = 42; diff --git a/src/test/ui/asm/type-check-1.rs b/src/test/ui/asm/type-check-1.rs index bbbe798d15..1e463107b1 100644 --- a/src/test/ui/asm/type-check-1.rs +++ b/src/test/ui/asm/type-check-1.rs @@ -3,7 +3,7 @@ // ignore-spirv // ignore-wasm32 -#![feature(asm, global_asm)] +#![feature(asm, global_asm, asm_const)] fn main() { unsafe { diff --git a/src/test/ui/asm/x86_64/bad-clobber-abi.rs b/src/test/ui/asm/x86_64/bad-clobber-abi.rs new file mode 100644 index 0000000000..f4ca033048 --- /dev/null +++ b/src/test/ui/asm/x86_64/bad-clobber-abi.rs @@ -0,0 +1,32 @@ +// needs-asm-support +// only-x86_64 + +// checks various modes of failure for the `clobber_abi` argument (after parsing) + +#![feature(asm)] + +fn main() { + unsafe { + asm!("", clobber_abi("C")); + asm!("", clobber_abi("foo")); + //~^ ERROR invalid ABI for `clobber_abi` + asm!("", clobber_abi("C", "foo")); + //~^ ERROR invalid ABI for `clobber_abi` + asm!("", clobber_abi("C", "C")); + //~^ ERROR `C` ABI specified multiple times + asm!("", clobber_abi("win64", "sysv64")); + asm!("", clobber_abi("win64", "efiapi")); + //~^ ERROR `win64` ABI specified multiple times + asm!("", clobber_abi("C", "foo", "C")); + //~^ ERROR invalid ABI for `clobber_abi` + //~| ERROR `C` ABI specified multiple times + asm!("", clobber_abi("win64", "foo", "efiapi")); + //~^ ERROR invalid ABI for `clobber_abi` + //~| ERROR `win64` ABI specified multiple times + asm!("", clobber_abi("C"), clobber_abi("C")); + //~^ ERROR `C` ABI specified multiple times + asm!("", clobber_abi("win64"), clobber_abi("sysv64")); + asm!("", clobber_abi("win64"), clobber_abi("efiapi")); + //~^ ERROR `win64` ABI specified multiple times + } +} diff --git a/src/test/ui/asm/x86_64/bad-clobber-abi.stderr b/src/test/ui/asm/x86_64/bad-clobber-abi.stderr new file mode 100644 index 0000000000..46e91a3951 --- /dev/null +++ b/src/test/ui/asm/x86_64/bad-clobber-abi.stderr @@ -0,0 +1,88 @@ +error: invalid ABI for `clobber_abi` + --> $DIR/bad-clobber-abi.rs:11:18 + | +LL | asm!("", clobber_abi("foo")); + | ^^^^^^^^^^^^^^^^^^ + | + = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64` + +error: invalid ABI for `clobber_abi` + --> $DIR/bad-clobber-abi.rs:13:35 + | +LL | asm!("", clobber_abi("C", "foo")); + | ^^^^^ + | + = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64` + +error: `C` ABI specified multiple times + --> $DIR/bad-clobber-abi.rs:15:35 + | +LL | asm!("", clobber_abi("C", "C")); + | --- ^^^ + | | + | previously specified here + +error: `win64` ABI specified multiple times + --> $DIR/bad-clobber-abi.rs:18:39 + | +LL | asm!("", clobber_abi("win64", "efiapi")); + | ------- ^^^^^^^^ + | | + | previously specified here + | + = note: these ABIs are equivalent on the current target + +error: invalid ABI for `clobber_abi` + --> $DIR/bad-clobber-abi.rs:20:35 + | +LL | asm!("", clobber_abi("C", "foo", "C")); + | ^^^^^ + | + = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64` + +error: `C` ABI specified multiple times + --> $DIR/bad-clobber-abi.rs:20:42 + | +LL | asm!("", clobber_abi("C", "foo", "C")); + | --- ^^^ + | | + | previously specified here + +error: invalid ABI for `clobber_abi` + --> $DIR/bad-clobber-abi.rs:23:39 + | +LL | asm!("", clobber_abi("win64", "foo", "efiapi")); + | ^^^^^ + | + = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64` + +error: `win64` ABI specified multiple times + --> $DIR/bad-clobber-abi.rs:23:46 + | +LL | asm!("", clobber_abi("win64", "foo", "efiapi")); + | ------- ^^^^^^^^ + | | + | previously specified here + | + = note: these ABIs are equivalent on the current target + +error: `C` ABI specified multiple times + --> $DIR/bad-clobber-abi.rs:26:36 + | +LL | asm!("", clobber_abi("C"), clobber_abi("C")); + | ---------------- ^^^^^^^^^^^^^^^^ + | | + | previously specified here + +error: `win64` ABI specified multiple times + --> $DIR/bad-clobber-abi.rs:29:40 + | +LL | asm!("", clobber_abi("win64"), clobber_abi("efiapi")); + | -------------------- ^^^^^^^^^^^^^^^^^^^^^ + | | + | previously specified here + | + = note: these ABIs are equivalent on the current target + +error: aborting due to 10 previous errors + diff --git a/src/test/ui/asm/x86_64/bad-options.rs b/src/test/ui/asm/x86_64/bad-options.rs index dc61d1612e..3facc87641 100644 --- a/src/test/ui/asm/x86_64/bad-options.rs +++ b/src/test/ui/asm/x86_64/bad-options.rs @@ -21,6 +21,9 @@ fn main() { //~^ ERROR invalid ABI for `clobber_abi` asm!("{}", out(reg) foo, clobber_abi("C")); //~^ ERROR asm with `clobber_abi` must specify explicit registers for outputs + asm!("{}", out(reg) foo, clobber_abi("C"), clobber_abi("C")); + //~^ ERROR asm with `clobber_abi` must specify explicit registers for outputs + //~| ERROR `C` ABI specified multiple times asm!("", out("eax") foo, clobber_abi("C")); } } diff --git a/src/test/ui/asm/x86_64/bad-options.stderr b/src/test/ui/asm/x86_64/bad-options.stderr index 8cfd450ab0..e2351840ee 100644 --- a/src/test/ui/asm/x86_64/bad-options.stderr +++ b/src/test/ui/asm/x86_64/bad-options.stderr @@ -36,38 +36,47 @@ LL | asm!("{}", out(reg) foo, clobber_abi("C")); | | | generic outputs +error: asm with `clobber_abi` must specify explicit registers for outputs + --> $DIR/bad-options.rs:24:20 + | +LL | asm!("{}", out(reg) foo, clobber_abi("C"), clobber_abi("C")); + | ^^^^^^^^^^^^ ---------------- ---------------- clobber_abi + | | | + | | clobber_abi + | generic outputs + error: expected one of `)`, `att_syntax`, or `raw`, found `nomem` - --> $DIR/bad-options.rs:28:25 + --> $DIR/bad-options.rs:31:25 | LL | global_asm!("", options(nomem)); | ^^^^^ expected one of `)`, `att_syntax`, or `raw` error: expected one of `)`, `att_syntax`, or `raw`, found `readonly` - --> $DIR/bad-options.rs:30:25 + --> $DIR/bad-options.rs:33:25 | LL | global_asm!("", options(readonly)); | ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw` error: expected one of `)`, `att_syntax`, or `raw`, found `noreturn` - --> $DIR/bad-options.rs:32:25 + --> $DIR/bad-options.rs:35:25 | LL | global_asm!("", options(noreturn)); | ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw` error: expected one of `)`, `att_syntax`, or `raw`, found `pure` - --> $DIR/bad-options.rs:34:25 + --> $DIR/bad-options.rs:37:25 | LL | global_asm!("", options(pure)); | ^^^^ expected one of `)`, `att_syntax`, or `raw` error: expected one of `)`, `att_syntax`, or `raw`, found `nostack` - --> $DIR/bad-options.rs:36:25 + --> $DIR/bad-options.rs:39:25 | LL | global_asm!("", options(nostack)); | ^^^^^^^ expected one of `)`, `att_syntax`, or `raw` error: expected one of `)`, `att_syntax`, or `raw`, found `preserves_flags` - --> $DIR/bad-options.rs:38:25 + --> $DIR/bad-options.rs:41:25 | LL | global_asm!("", options(preserves_flags)); | ^^^^^^^^^^^^^^^ expected one of `)`, `att_syntax`, or `raw` @@ -80,5 +89,13 @@ LL | asm!("", clobber_abi("foo")); | = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64` -error: aborting due to 13 previous errors +error: `C` ABI specified multiple times + --> $DIR/bad-options.rs:24:52 + | +LL | asm!("{}", out(reg) foo, clobber_abi("C"), clobber_abi("C")); + | ---------------- ^^^^^^^^^^^^^^^^ + | | + | previously specified here + +error: aborting due to 15 previous errors diff --git a/src/test/ui/asm/x86_64/bad-reg.rs b/src/test/ui/asm/x86_64/bad-reg.rs index 91d0f8c33f..ba4e95db46 100644 --- a/src/test/ui/asm/x86_64/bad-reg.rs +++ b/src/test/ui/asm/x86_64/bad-reg.rs @@ -1,7 +1,7 @@ // only-x86_64 // compile-flags: -C target-feature=+avx2 -#![feature(asm)] +#![feature(asm, asm_const, asm_sym)] fn main() { let mut foo = 0; diff --git a/src/test/ui/asm/x86_64/const.rs b/src/test/ui/asm/x86_64/const.rs index d4de9abb8c..c1e4cdbb92 100644 --- a/src/test/ui/asm/x86_64/const.rs +++ b/src/test/ui/asm/x86_64/const.rs @@ -1,10 +1,9 @@ -// min-llvm-version: 10.0.1 // only-x86_64 // run-pass // revisions: mirunsafeck thirunsafeck // [thirunsafeck]compile-flags: -Z thir-unsafeck -#![feature(asm, global_asm)] +#![feature(asm, global_asm, asm_const)] fn const_generic<const X: usize>() -> usize { unsafe { diff --git a/src/test/ui/asm/x86_64/issue-89875.rs b/src/test/ui/asm/x86_64/issue-89875.rs new file mode 100644 index 0000000000..9b2b21bbda --- /dev/null +++ b/src/test/ui/asm/x86_64/issue-89875.rs @@ -0,0 +1,14 @@ +// build-pass +// only-x86_64 + +#![feature(asm, target_feature_11)] + +#[target_feature(enable = "avx")] +fn main() { + unsafe { + asm!( + "/* {} */", + out(ymm_reg) _, + ); + } +} diff --git a/src/test/ui/asm/x86_64/multiple-clobber-abi.rs b/src/test/ui/asm/x86_64/multiple-clobber-abi.rs new file mode 100644 index 0000000000..a573d672d0 --- /dev/null +++ b/src/test/ui/asm/x86_64/multiple-clobber-abi.rs @@ -0,0 +1,33 @@ +// run-pass +// needs-asm-support +// only-x86_64 + +// Checks that multiple clobber_abi options can be used + +#![feature(asm, asm_sym)] + +extern "sysv64" fn foo(x: i32) -> i32 { + x + 16 +} + +extern "win64" fn bar(x: i32) -> i32 { + x / 2 +} + +fn main() { + let x = 8; + let y: i32; + // call `foo` with `x` as the input, and then `bar` with the output of `foo` + // and output that to `y` + unsafe { + asm!( + "call {}; mov rcx, rax; call {}", + sym foo, + sym bar, + in("rdi") x, + out("rax") y, + clobber_abi("sysv64", "win64"), + ); + } + assert_eq!((x, y), (8, 12)); +} diff --git a/src/test/ui/asm/x86_64/parse-error.rs b/src/test/ui/asm/x86_64/parse-error.rs index fa14c52cf0..1d6545f1b5 100644 --- a/src/test/ui/asm/x86_64/parse-error.rs +++ b/src/test/ui/asm/x86_64/parse-error.rs @@ -1,6 +1,6 @@ // only-x86_64 -#![feature(asm, global_asm)] +#![feature(asm, global_asm, asm_const)] fn main() { let mut foo = 0; @@ -37,12 +37,14 @@ fn main() { asm!("{}", options(), const foo); //~^ ERROR arguments are not allowed after options //~^^ ERROR attempt to use a non-constant value in a constant + asm!("", clobber_abi()); + //~^ ERROR at least one abi must be provided asm!("", clobber_abi(foo)); //~^ ERROR expected string literal asm!("", clobber_abi("C" foo)); - //~^ ERROR expected `)`, found `foo` + //~^ ERROR expected one of `)` or `,`, found `foo` asm!("", clobber_abi("C", foo)); - //~^ ERROR expected `)`, found `,` + //~^ ERROR expected string literal asm!("{}", clobber_abi("C"), const foo); //~^ ERROR arguments are not allowed after clobber_abi //~^^ ERROR attempt to use a non-constant value in a constant @@ -50,8 +52,6 @@ fn main() { //~^ ERROR clobber_abi is not allowed after options asm!("{}", options(), clobber_abi("C"), const foo); //~^ ERROR clobber_abi is not allowed after options - asm!("", clobber_abi("C"), clobber_abi("C")); - //~^ ERROR clobber_abi specified multiple times asm!("{a}", a = const foo, a = const bar); //~^ ERROR duplicate argument named `a` //~^^ ERROR argument never used @@ -110,9 +110,9 @@ global_asm!("{}", options(), const FOO); global_asm!("", clobber_abi(FOO)); //~^ ERROR expected string literal global_asm!("", clobber_abi("C" FOO)); -//~^ ERROR expected `)`, found `FOO` +//~^ ERROR expected one of `)` or `,`, found `FOO` global_asm!("", clobber_abi("C", FOO)); -//~^ ERROR expected `)`, found `,` +//~^ ERROR expected string literal global_asm!("{}", clobber_abi("C"), const FOO); //~^ ERROR arguments are not allowed after clobber_abi //~^^ ERROR `clobber_abi` cannot be used with `global_asm!` @@ -121,7 +121,7 @@ global_asm!("", options(), clobber_abi("C")); global_asm!("{}", options(), clobber_abi("C"), const FOO); //~^ ERROR clobber_abi is not allowed after options global_asm!("", clobber_abi("C"), clobber_abi("C")); -//~^ ERROR clobber_abi specified multiple times +//~^ ERROR `clobber_abi` cannot be used with `global_asm!` global_asm!("{a}", a = const FOO, a = const BAR); //~^ ERROR duplicate argument named `a` //~^^ ERROR argument never used diff --git a/src/test/ui/asm/x86_64/parse-error.stderr b/src/test/ui/asm/x86_64/parse-error.stderr index 91a6baa4af..018df9826c 100644 --- a/src/test/ui/asm/x86_64/parse-error.stderr +++ b/src/test/ui/asm/x86_64/parse-error.stderr @@ -90,26 +90,32 @@ LL | asm!("{}", options(), const foo); | | | previous options -error: expected string literal +error: at least one abi must be provided as an argument to `clobber_abi` --> $DIR/parse-error.rs:40:30 | +LL | asm!("", clobber_abi()); + | ^ + +error: expected string literal + --> $DIR/parse-error.rs:42:30 + | LL | asm!("", clobber_abi(foo)); | ^^^ not a string literal -error: expected `)`, found `foo` - --> $DIR/parse-error.rs:42:34 +error: expected one of `)` or `,`, found `foo` + --> $DIR/parse-error.rs:44:34 | LL | asm!("", clobber_abi("C" foo)); - | ^^^ expected `)` + | ^^^ expected one of `)` or `,` -error: expected `)`, found `,` - --> $DIR/parse-error.rs:44:33 +error: expected string literal + --> $DIR/parse-error.rs:46:35 | LL | asm!("", clobber_abi("C", foo)); - | ^ expected `)` + | ^^^ not a string literal error: arguments are not allowed after clobber_abi - --> $DIR/parse-error.rs:46:38 + --> $DIR/parse-error.rs:48:38 | LL | asm!("{}", clobber_abi("C"), const foo); | ---------------- ^^^^^^^^^ argument @@ -117,7 +123,7 @@ LL | asm!("{}", clobber_abi("C"), const foo); | clobber_abi error: clobber_abi is not allowed after options - --> $DIR/parse-error.rs:49:29 + --> $DIR/parse-error.rs:51:29 | LL | asm!("", options(), clobber_abi("C")); | --------- ^^^^^^^^^^^^^^^^ @@ -125,21 +131,13 @@ LL | asm!("", options(), clobber_abi("C")); | options error: clobber_abi is not allowed after options - --> $DIR/parse-error.rs:51:31 + --> $DIR/parse-error.rs:53:31 | LL | asm!("{}", options(), clobber_abi("C"), const foo); | --------- ^^^^^^^^^^^^^^^^ | | | options -error: clobber_abi specified multiple times - --> $DIR/parse-error.rs:53:36 - | -LL | asm!("", clobber_abi("C"), clobber_abi("C")); - | ---------------- ^^^^^^^^^^^^^^^^ - | | - | clobber_abi previously specified here - error: duplicate argument named `a` --> $DIR/parse-error.rs:55:36 | @@ -300,17 +298,17 @@ error: expected string literal LL | global_asm!("", clobber_abi(FOO)); | ^^^ not a string literal -error: expected `)`, found `FOO` +error: expected one of `)` or `,`, found `FOO` --> $DIR/parse-error.rs:112:33 | LL | global_asm!("", clobber_abi("C" FOO)); - | ^^^ expected `)` + | ^^^ expected one of `)` or `,` -error: expected `)`, found `,` - --> $DIR/parse-error.rs:114:32 +error: expected string literal + --> $DIR/parse-error.rs:114:34 | LL | global_asm!("", clobber_abi("C", FOO)); - | ^ expected `)` + | ^^^ not a string literal error: arguments are not allowed after clobber_abi --> $DIR/parse-error.rs:116:37 @@ -342,13 +340,11 @@ LL | global_asm!("{}", options(), clobber_abi("C"), const FOO); | | | options -error: clobber_abi specified multiple times - --> $DIR/parse-error.rs:123:35 +error: `clobber_abi` cannot be used with `global_asm!` + --> $DIR/parse-error.rs:123:17 | LL | global_asm!("", clobber_abi("C"), clobber_abi("C")); - | ---------------- ^^^^^^^^^^^^^^^^ - | | - | clobber_abi previously specified here + | ^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ error: duplicate argument named `a` --> $DIR/parse-error.rs:125:35 @@ -404,7 +400,7 @@ LL | asm!("{}", options(), const foo); | ^^^ non-constant value error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:46:44 + --> $DIR/parse-error.rs:48:44 | LL | let mut foo = 0; | ---------- help: consider using `const` instead of `let`: `const foo` diff --git a/src/test/ui/asm/x86_64/srcloc.rs b/src/test/ui/asm/x86_64/srcloc.rs index ed8cefc58b..c4ccfb8016 100644 --- a/src/test/ui/asm/x86_64/srcloc.rs +++ b/src/test/ui/asm/x86_64/srcloc.rs @@ -1,4 +1,3 @@ -// min-llvm-version: 10.0.1 // only-x86_64 // build-fail // compile-flags: -Ccodegen-units=1 diff --git a/src/test/ui/asm/x86_64/srcloc.stderr b/src/test/ui/asm/x86_64/srcloc.stderr index b62c894828..7789465729 100644 --- a/src/test/ui/asm/x86_64/srcloc.stderr +++ b/src/test/ui/asm/x86_64/srcloc.stderr @@ -1,5 +1,5 @@ error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:11:15 + --> $DIR/srcloc.rs:10:15 | LL | asm!("invalid_instruction"); | ^ @@ -11,7 +11,7 @@ LL | invalid_instruction | ^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:15:13 + --> $DIR/srcloc.rs:14:13 | LL | invalid_instruction | ^ @@ -23,7 +23,7 @@ LL | invalid_instruction | ^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:20:13 + --> $DIR/srcloc.rs:19:13 | LL | invalid_instruction | ^ @@ -35,7 +35,7 @@ LL | invalid_instruction | ^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:26:13 + --> $DIR/srcloc.rs:25:13 | LL | invalid_instruction | ^ @@ -47,7 +47,7 @@ LL | invalid_instruction | ^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:33:13 + --> $DIR/srcloc.rs:32:13 | LL | invalid_instruction | ^ @@ -59,7 +59,7 @@ LL | invalid_instruction | ^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:38:14 + --> $DIR/srcloc.rs:37:14 | LL | asm!(concat!("invalid", "_", "instruction")); | ^ @@ -71,7 +71,7 @@ LL | invalid_instruction | ^^^^^^^^^^^^^^^^^^^ warning: scale factor without index register is ignored - --> $DIR/srcloc.rs:41:15 + --> $DIR/srcloc.rs:40:15 | LL | asm!("movaps %xmm3, (%esi, 2)", options(att_syntax)); | ^ @@ -83,7 +83,7 @@ LL | movaps %xmm3, (%esi, 2) | ^ error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:45:14 + --> $DIR/srcloc.rs:44:14 | LL | "invalid_instruction", | ^ @@ -95,7 +95,7 @@ LL | invalid_instruction | ^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:51:14 + --> $DIR/srcloc.rs:50:14 | LL | "invalid_instruction", | ^ @@ -107,7 +107,7 @@ LL | invalid_instruction | ^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:58:14 + --> $DIR/srcloc.rs:57:14 | LL | "invalid_instruction", | ^ @@ -119,7 +119,7 @@ LL | invalid_instruction | ^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:65:13 + --> $DIR/srcloc.rs:64:13 | LL | concat!("invalid", "_", "instruction"), | ^ @@ -131,7 +131,7 @@ LL | invalid_instruction | ^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction' - --> $DIR/srcloc.rs:72:13 + --> $DIR/srcloc.rs:71:13 | LL | concat!("invalid", "_", "instruction"), | ^ @@ -143,7 +143,7 @@ LL | invalid_instruction | ^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction1' - --> $DIR/srcloc.rs:79:14 + --> $DIR/srcloc.rs:78:14 | LL | "invalid_instruction1", | ^ @@ -155,7 +155,7 @@ LL | invalid_instruction1 | ^^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction2' - --> $DIR/srcloc.rs:80:14 + --> $DIR/srcloc.rs:79:14 | LL | "invalid_instruction2", | ^ @@ -167,7 +167,7 @@ LL | invalid_instruction2 | ^^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction1' - --> $DIR/srcloc.rs:86:13 + --> $DIR/srcloc.rs:85:13 | LL | concat!( | ^ @@ -179,7 +179,7 @@ LL | invalid_instruction1 | ^^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction2' - --> $DIR/srcloc.rs:86:13 + --> $DIR/srcloc.rs:85:13 | LL | concat!( | ^ @@ -191,7 +191,7 @@ LL | invalid_instruction2 | ^^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction1' - --> $DIR/srcloc.rs:95:13 + --> $DIR/srcloc.rs:94:13 | LL | concat!( | ^ @@ -203,7 +203,7 @@ LL | invalid_instruction1 | ^^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction2' - --> $DIR/srcloc.rs:95:13 + --> $DIR/srcloc.rs:94:13 | LL | concat!( | ^ @@ -215,7 +215,7 @@ LL | invalid_instruction2 | ^^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction3' - --> $DIR/srcloc.rs:99:13 + --> $DIR/srcloc.rs:98:13 | LL | concat!( | ^ @@ -227,7 +227,7 @@ LL | invalid_instruction3 | ^^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction4' - --> $DIR/srcloc.rs:99:13 + --> $DIR/srcloc.rs:98:13 | LL | concat!( | ^ @@ -239,7 +239,7 @@ LL | invalid_instruction4 | ^^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction1' - --> $DIR/srcloc.rs:110:13 + --> $DIR/srcloc.rs:109:13 | LL | concat!( | ^ @@ -251,7 +251,7 @@ LL | invalid_instruction1 | ^^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction2' - --> $DIR/srcloc.rs:110:13 + --> $DIR/srcloc.rs:109:13 | LL | concat!( | ^ @@ -263,7 +263,7 @@ LL | invalid_instruction2 | ^^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction3' - --> $DIR/srcloc.rs:114:13 + --> $DIR/srcloc.rs:113:13 | LL | concat!( | ^ @@ -275,7 +275,7 @@ LL | invalid_instruction3 | ^^^^^^^^^^^^^^^^^^^^ error: invalid instruction mnemonic 'invalid_instruction4' - --> $DIR/srcloc.rs:114:13 + --> $DIR/srcloc.rs:113:13 | LL | concat!( | ^ diff --git a/src/test/ui/asm/x86_64/sym.rs b/src/test/ui/asm/x86_64/sym.rs index 634ef010e6..958dbbdd37 100644 --- a/src/test/ui/asm/x86_64/sym.rs +++ b/src/test/ui/asm/x86_64/sym.rs @@ -1,9 +1,9 @@ -// min-llvm-version: 10.0.1 +// min-llvm-version: 12.0.1 // only-x86_64 // only-linux // run-pass -#![feature(asm, thread_local)] +#![feature(asm, thread_local, asm_sym)] extern "C" fn f1() -> i32 { 111 @@ -76,5 +76,7 @@ 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(); + }) + .join() + .unwrap(); } diff --git a/src/test/ui/asm/x86_64/type-check-2.rs b/src/test/ui/asm/x86_64/type-check-2.rs index 2311f86d34..94aadcf09f 100644 --- a/src/test/ui/asm/x86_64/type-check-2.rs +++ b/src/test/ui/asm/x86_64/type-check-2.rs @@ -1,6 +1,6 @@ // only-x86_64 -#![feature(asm, repr_simd, never_type)] +#![feature(asm, repr_simd, never_type, asm_sym)] #[repr(simd)] struct SimdNonCopy(f32, f32, f32, f32); diff --git a/src/test/ui/asm/x86_64/type-check-3.rs b/src/test/ui/asm/x86_64/type-check-3.rs index c2c1885ff1..83674cf820 100644 --- a/src/test/ui/asm/x86_64/type-check-3.rs +++ b/src/test/ui/asm/x86_64/type-check-3.rs @@ -1,7 +1,7 @@ // only-x86_64 // compile-flags: -C target-feature=+avx512f -#![feature(asm, global_asm)] +#![feature(asm, global_asm, asm_const)] use std::arch::x86_64::{_mm256_setzero_ps, _mm_setzero_ps}; diff --git a/src/test/ui/associated-consts/associated-const-array-len.stderr b/src/test/ui/associated-consts/associated-const-array-len.stderr index ff56d112c8..86c62e7b7f 100644 --- a/src/test/ui/associated-consts/associated-const-array-len.stderr +++ b/src/test/ui/associated-consts/associated-const-array-len.stderr @@ -3,12 +3,6 @@ error[E0277]: the trait bound `i32: Foo` is not satisfied | LL | const X: [i32; <i32 as Foo>::ID] = [0, 1, 2]; | ^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32` - | -note: required by `Foo::ID` - --> $DIR/associated-const-array-len.rs:2:5 - | -LL | const ID: usize; - | ^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-consts/issue-63496.stderr b/src/test/ui/associated-consts/issue-63496.stderr index cea56cd594..db39fd762c 100644 --- a/src/test/ui/associated-consts/issue-63496.stderr +++ b/src/test/ui/associated-consts/issue-63496.stderr @@ -9,11 +9,6 @@ LL | fn f() -> ([u8; A::C], [u8; A::C]); | = note: cannot satisfy `_: A` = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl` -note: required by `A::C` - --> $DIR/issue-63496.rs:2:5 - | -LL | const C: usize; - | ^^^^^^^^^^^^^^^ error[E0283]: type annotations needed --> $DIR/issue-63496.rs:4:33 @@ -26,11 +21,6 @@ LL | fn f() -> ([u8; A::C], [u8; A::C]); | = note: cannot satisfy `_: A` = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl` -note: required by `A::C` - --> $DIR/issue-63496.rs:2:5 - | -LL | const C: usize; - | ^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-item/issue-48027.stderr b/src/test/ui/associated-item/issue-48027.stderr index 7b158f1d75..9ae25a8c22 100644 --- a/src/test/ui/associated-item/issue-48027.stderr +++ b/src/test/ui/associated-item/issue-48027.stderr @@ -9,11 +9,6 @@ LL | fn return_n(&self) -> [u8; Bar::X]; | = note: cannot satisfy `_: Bar` = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl` -note: required by `Bar::X` - --> $DIR/issue-48027.rs:2:5 - | -LL | const X: usize; - | ^^^^^^^^^^^^^^^ error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/issue-48027.rs:6:6 diff --git a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr index 57aacf67e0..4ecae471ec 100644 --- a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr +++ b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr @@ -5,13 +5,6 @@ LL | type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8 | ^^^^ `<<Self as Case1>::C as Iterator>::Item` cannot be sent between threads safely | = help: the trait `Send` is not implemented for `<<Self as Case1>::C as Iterator>::Item` -note: required by a bound in `Send` - --> $SRC_DIR/core/src/marker.rs:LL:COL - | -LL | / pub unsafe auto trait Send { -LL | | // empty. -LL | | } - | |_^ required by this bound in `Send` help: consider further restricting the associated type | LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Send { @@ -24,17 +17,6 @@ LL | type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `<<Self as Case1>::C as Iterator>::Item` is not an iterator | = help: the trait `Iterator` is not implemented for `<<Self as Case1>::C as Iterator>::Item` -note: required by a bound in `Iterator` - --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL - | -LL | / pub trait Iterator { -LL | | /// The type of the elements being iterated over. -LL | | #[stable(feature = "rust1", since = "1.0.0")] -LL | | type Item; -... | -LL | | } -LL | | } - | |_^ required by this bound in `Iterator` help: consider further restricting the associated type | LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Iterator { @@ -47,17 +29,6 @@ LL | type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8 | ^^^^ `<<Self as Case1>::C as Iterator>::Item` cannot be shared between threads safely | = help: the trait `Sync` is not implemented for `<<Self as Case1>::C as Iterator>::Item` -note: required by a bound in `Sync` - --> $SRC_DIR/core/src/marker.rs:LL:COL - | -LL | / pub unsafe auto trait Sync { -LL | | // FIXME(estebank): once support to add notes in `rustc_on_unimplemented` -LL | | // lands in beta, and it has been extended to check whether a closure is -LL | | // anywhere in the requirement chain, extend it as such (#48534): -... | -LL | | // Empty -LL | | } - | |_^ required by this bound in `Sync` help: consider further restricting the associated type | LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Sync { diff --git a/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr b/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr index 4da5a2cbd4..4e2313bd4e 100644 --- a/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr +++ b/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr @@ -5,17 +5,6 @@ LL | type A: Iterator<Item: Debug>; | ^^^^^ `<<Self as Case1>::A as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = help: the trait `Debug` is not implemented for `<<Self as Case1>::A as Iterator>::Item` -note: required by a bound in `Debug` - --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL - | -LL | / pub trait Debug { -LL | | /// Formats the value using the given formatter. -LL | | /// -LL | | /// # Examples -... | -LL | | fn fmt(&self, f: &mut Formatter<'_>) -> Result; -LL | | } - | |_^ required by this bound in `Debug` help: consider further restricting the associated type | LL | trait Case1 where <<Self as Case1>::A as Iterator>::Item: Debug { @@ -27,17 +16,6 @@ error[E0277]: the trait bound `<<Self as Foo>::Out as Baz>::Assoc: Default` is n LL | pub trait Foo { type Out: Baz<Assoc: Default>; } | ^^^^^^^ the trait `Default` is not implemented for `<<Self as Foo>::Out as Baz>::Assoc` | -note: required by a bound in `Default` - --> $SRC_DIR/core/src/default.rs:LL:COL - | -LL | / pub trait Default: Sized { -LL | | /// Returns the "default value" for a type. -LL | | /// -LL | | /// Default values are often some kind of initial value, identity value, or anything else that -... | -LL | | fn default() -> Self; -LL | | } - | |_^ required by this bound in `Default` help: consider further restricting the associated type | LL | pub trait Foo where <<Self as Foo>::Out as Baz>::Assoc: Default { type Out: Baz<Assoc: Default>; } diff --git a/src/test/ui/associated-item-long-paths.rs b/src/test/ui/associated-types/associated-item-long-paths.rs similarity index 100% rename from src/test/ui/associated-item-long-paths.rs rename to src/test/ui/associated-types/associated-item-long-paths.rs diff --git a/src/test/ui/associated-types/associated-types-bound-failure.stderr b/src/test/ui/associated-types/associated-types-bound-failure.stderr index e66c6b35ca..3eda22796e 100644 --- a/src/test/ui/associated-types/associated-types-bound-failure.stderr +++ b/src/test/ui/associated-types/associated-types-bound-failure.stderr @@ -6,11 +6,6 @@ LL | ToInt::to_int(&g.get()) | | | required by a bound introduced by this call | -note: required by `ToInt::to_int` - --> $DIR/associated-types-bound-failure.rs:6:5 - | -LL | fn to_int(&self) -> isize; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider further restricting the associated type | LL | where G : GetToInt, <G as GetToInt>::R: ToInt diff --git a/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr b/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr index 92c963a9ef..6552c8be78 100644 --- a/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr +++ b/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr @@ -4,11 +4,6 @@ error[E0277]: the trait bound `Self: Get` is not satisfied LL | fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {} | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` | -note: required by a bound in `Get` - --> $DIR/associated-types-for-unimpl-trait.rs:4:1 - | -LL | trait Get { - | ^^^^^^^^^ required by this bound in `Get` help: consider further restricting `Self` | LL | fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) where Self: Get {} diff --git a/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr b/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr index 509d548c69..b2ee1b5e6d 100644 --- a/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr +++ b/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr @@ -4,11 +4,6 @@ error[E0277]: the trait bound `T: Get` is not satisfied LL | fn uhoh<T>(foo: <T as Get>::Value) {} | ^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T` | -note: required by a bound in `Get` - --> $DIR/associated-types-no-suitable-bound.rs:1:1 - | -LL | trait Get { - | ^^^^^^^^^ required by this bound in `Get` help: consider restricting type parameter `T` | LL | fn uhoh<T: Get>(foo: <T as Get>::Value) {} diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr b/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr index 1cb9ac8fde..2e40dbd065 100644 --- a/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr +++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr @@ -4,11 +4,6 @@ error[E0277]: the trait bound `Self: Get` is not satisfied LL | fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {} | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` | -note: required by a bound in `Get` - --> $DIR/associated-types-no-suitable-supertrait-2.rs:12:1 - | -LL | trait Get { - | ^^^^^^^^^ required by this bound in `Get` help: consider further restricting `Self` | LL | fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) where Self: Get {} diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr index e3185fbe93..da79c7ac77 100644 --- a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr +++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr @@ -4,11 +4,6 @@ error[E0277]: the trait bound `Self: Get` is not satisfied LL | fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {} | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` | -note: required by a bound in `Get` - --> $DIR/associated-types-no-suitable-supertrait.rs:12:1 - | -LL | trait Get { - | ^^^^^^^^^ required by this bound in `Get` help: consider further restricting `Self` | LL | fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) where Self: Get {} @@ -19,12 +14,6 @@ error[E0277]: the trait bound `(T, U): Get` is not satisfied | LL | fn uhoh<U:Get>(&self, foo: U, bar: <(T, U) as Get>::Value) {} | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `(T, U)` - | -note: required by a bound in `Get` - --> $DIR/associated-types-no-suitable-supertrait.rs:12:1 - | -LL | trait Get { - | ^^^^^^^^^ required by this bound in `Get` error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-types/associated-types-path-2.rs b/src/test/ui/associated-types/associated-types-path-2.rs index 912dedfdce..c993e1d272 100644 --- a/src/test/ui/associated-types/associated-types-path-2.rs +++ b/src/test/ui/associated-types/associated-types-path-2.rs @@ -28,11 +28,13 @@ pub fn f1_int_uint() { pub fn f1_uint_uint() { f1(2u32, 4u32); //~^ ERROR `u32: Foo` is not satisfied + //~| ERROR `u32: Foo` is not satisfied } pub fn f1_uint_int() { f1(2u32, 4i32); //~^ ERROR `u32: Foo` is not satisfied + //~| ERROR `u32: Foo` is not satisfied } pub fn f2_int() { diff --git a/src/test/ui/associated-types/associated-types-path-2.stderr b/src/test/ui/associated-types/associated-types-path-2.stderr index 15a5245d54..b3bb58f781 100644 --- a/src/test/ui/associated-types/associated-types-path-2.stderr +++ b/src/test/ui/associated-types/associated-types-path-2.stderr @@ -10,12 +10,10 @@ LL | f1(2i32, 4u32); | ~~~ error[E0277]: the trait bound `u32: Foo` is not satisfied - --> $DIR/associated-types-path-2.rs:29:14 + --> $DIR/associated-types-path-2.rs:29:5 | LL | f1(2u32, 4u32); - | -- ^^^^ the trait `Foo` is not implemented for `u32` - | | - | required by a bound introduced by this call + | ^^ the trait `Foo` is not implemented for `u32` | note: required by a bound in `f1` --> $DIR/associated-types-path-2.rs:13:14 @@ -24,10 +22,16 @@ LL | pub fn f1<T: Foo>(a: T, x: T::A) {} | ^^^ required by this bound in `f1` error[E0277]: the trait bound `u32: Foo` is not satisfied - --> $DIR/associated-types-path-2.rs:34:14 + --> $DIR/associated-types-path-2.rs:29:14 + | +LL | f1(2u32, 4u32); + | ^^^^ the trait `Foo` is not implemented for `u32` + +error[E0277]: the trait bound `u32: Foo` is not satisfied + --> $DIR/associated-types-path-2.rs:35:8 | LL | f1(2u32, 4i32); - | -- ^^^^ the trait `Foo` is not implemented for `u32` + | -- ^^^^ the trait `Foo` is not implemented for `u32` | | | required by a bound introduced by this call | @@ -37,8 +41,14 @@ note: required by a bound in `f1` LL | pub fn f1<T: Foo>(a: T, x: T::A) {} | ^^^ required by this bound in `f1` +error[E0277]: the trait bound `u32: Foo` is not satisfied + --> $DIR/associated-types-path-2.rs:35:14 + | +LL | f1(2u32, 4i32); + | ^^^^ the trait `Foo` is not implemented for `u32` + error[E0308]: mismatched types - --> $DIR/associated-types-path-2.rs:39:18 + --> $DIR/associated-types-path-2.rs:41:18 | LL | let _: i32 = f2(2i32); | --- ^^^^^^^^ expected `i32`, found `u32` @@ -50,7 +60,7 @@ help: you can convert a `u32` to an `i32` and panic if the converted value doesn LL | let _: i32 = f2(2i32).try_into().unwrap(); | ++++++++++++++++++++ -error: aborting due to 4 previous errors +error: aborting due to 6 previous errors Some errors have detailed explanations: E0277, E0308. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr index 09ec0e1161..2e67c21940 100644 --- a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr +++ b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr @@ -4,11 +4,6 @@ error[E0277]: the trait bound `Self: Get` is not satisfied LL | fn okay<U:Get>(&self, foo: U, bar: <Self as Get>::Value); | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` | -note: required by a bound in `Get` - --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:5:1 - | -LL | trait Get { - | ^^^^^^^^^ required by this bound in `Get` help: consider further restricting `Self` | LL | fn okay<U:Get>(&self, foo: U, bar: <Self as Get>::Value) where Self: Get; diff --git a/src/test/ui/associated-types/associated-types-unconstrained.stderr b/src/test/ui/associated-types/associated-types-unconstrained.stderr index 5f4b65bd13..60ec23cf65 100644 --- a/src/test/ui/associated-types/associated-types-unconstrained.stderr +++ b/src/test/ui/associated-types/associated-types-unconstrained.stderr @@ -5,11 +5,6 @@ LL | let x: isize = Foo::bar(); | ^^^^^^^^ cannot infer type | = note: cannot satisfy `_: Foo` -note: required by `Foo::bar` - --> $DIR/associated-types-unconstrained.rs:5:5 - | -LL | fn bar() -> isize; - | ^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/default-associated-types.rs b/src/test/ui/associated-types/default-associated-types.rs similarity index 100% rename from src/test/ui/default-associated-types.rs rename to src/test/ui/associated-types/default-associated-types.rs diff --git a/src/test/ui/issues/issue-22066.rs b/src/test/ui/associated-types/issue-22066.rs similarity index 100% rename from src/test/ui/issues/issue-22066.rs rename to src/test/ui/associated-types/issue-22066.rs diff --git a/src/test/ui/issues/issue-22828.rs b/src/test/ui/associated-types/issue-22828.rs similarity index 100% rename from src/test/ui/issues/issue-22828.rs rename to src/test/ui/associated-types/issue-22828.rs diff --git a/src/test/ui/issues/issue-28871.rs b/src/test/ui/associated-types/issue-28871.rs similarity index 100% rename from src/test/ui/issues/issue-28871.rs rename to src/test/ui/associated-types/issue-28871.rs diff --git a/src/test/ui/associated-types/issue-44153.stderr b/src/test/ui/associated-types/issue-44153.stderr index 7bf36d5e91..54f6556c08 100644 --- a/src/test/ui/associated-types/issue-44153.stderr +++ b/src/test/ui/associated-types/issue-44153.stderr @@ -9,11 +9,6 @@ note: required because of the requirements on the impl of `Visit` for `()` | LL | impl<'a> Visit for () where | ^^^^^ ^^ -note: required by `Visit::visit` - --> $DIR/issue-44153.rs:6:5 - | -LL | fn visit() {} - | ^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-47139-1.rs b/src/test/ui/associated-types/issue-47139-1.rs similarity index 100% rename from src/test/ui/issues/issue-47139-1.rs rename to src/test/ui/associated-types/issue-47139-1.rs diff --git a/src/test/ui/issues/issue-54467.rs b/src/test/ui/associated-types/issue-54467.rs similarity index 100% rename from src/test/ui/issues/issue-54467.rs rename to src/test/ui/associated-types/issue-54467.rs diff --git a/src/test/ui/associated-types/issue-87261.rs b/src/test/ui/associated-types/issue-87261.rs index a70f771e48..aae562ae72 100644 --- a/src/test/ui/associated-types/issue-87261.rs +++ b/src/test/ui/associated-types/issue-87261.rs @@ -83,17 +83,17 @@ fn main() { //~^ ERROR type mismatch resolving `<impl DerivedTrait as Trait>::Associated == ()` accepts_trait(returns_opaque_foo()); - //~^ ERROR type mismatch resolving `<impl Trait+Foo as Trait>::Associated == ()` + //~^ ERROR type mismatch resolving `<impl Foo + Trait as Trait>::Associated == ()` accepts_trait(returns_opaque_derived_foo()); - //~^ ERROR type mismatch resolving `<impl DerivedTrait+Foo as Trait>::Associated == ()` + //~^ ERROR type mismatch resolving `<impl Foo + DerivedTrait as Trait>::Associated == ()` accepts_generic_trait(returns_opaque_generic()); //~^ ERROR type mismatch resolving `<impl GenericTrait<()> as GenericTrait<()>>::Associated == ()` accepts_generic_trait(returns_opaque_generic_foo()); - //~^ ERROR type mismatch resolving `<impl GenericTrait<()>+Foo as GenericTrait<()>>::Associated == ()` + //~^ ERROR type mismatch resolving `<impl Foo + GenericTrait<()> as GenericTrait<()>>::Associated == ()` accepts_generic_trait(returns_opaque_generic_duplicate()); - //~^ ERROR type mismatch resolving `<impl GenericTrait<()>+GenericTrait<u8> as GenericTrait<()>>::Associated == ()` + //~^ ERROR type mismatch resolving `<impl GenericTrait<u8> + GenericTrait<()> as GenericTrait<()>>::Associated == ()` } diff --git a/src/test/ui/associated-types/issue-87261.stderr b/src/test/ui/associated-types/issue-87261.stderr index b85d64b86a..c00b48abc1 100644 --- a/src/test/ui/associated-types/issue-87261.stderr +++ b/src/test/ui/associated-types/issue-87261.stderr @@ -160,7 +160,7 @@ help: consider constraining the associated type `<impl DerivedTrait as Trait>::A LL | fn returns_opaque_derived() -> impl DerivedTrait<Associated = ()> + 'static { | +++++++++++++++++ -error[E0271]: type mismatch resolving `<impl Trait+Foo as Trait>::Associated == ()` +error[E0271]: type mismatch resolving `<impl Foo + Trait as Trait>::Associated == ()` --> $DIR/issue-87261.rs:85:5 | LL | fn returns_opaque_foo() -> impl Trait + Foo { @@ -170,18 +170,18 @@ LL | accepts_trait(returns_opaque_foo()); | ^^^^^^^^^^^^^ expected `()`, found associated type | = note: expected unit type `()` - found associated type `<impl Trait+Foo as Trait>::Associated` + found associated type `<impl Foo + Trait as Trait>::Associated` note: required by a bound in `accepts_trait` --> $DIR/issue-87261.rs:43:27 | LL | fn accepts_trait<T: Trait<Associated = ()>>(_: T) {} | ^^^^^^^^^^^^^^^ required by this bound in `accepts_trait` -help: consider constraining the associated type `<impl Trait+Foo as Trait>::Associated` to `()` +help: consider constraining the associated type `<impl Foo + Trait as Trait>::Associated` to `()` | LL | fn returns_opaque_foo() -> impl Trait<Associated = ()> + Foo { | +++++++++++++++++ -error[E0271]: type mismatch resolving `<impl DerivedTrait+Foo as Trait>::Associated == ()` +error[E0271]: type mismatch resolving `<impl Foo + DerivedTrait as Trait>::Associated == ()` --> $DIR/issue-87261.rs:88:5 | LL | fn returns_opaque_derived_foo() -> impl DerivedTrait + Foo { @@ -191,8 +191,8 @@ LL | accepts_trait(returns_opaque_derived_foo()); | ^^^^^^^^^^^^^ expected `()`, found associated type | = note: expected unit type `()` - found associated type `<impl DerivedTrait+Foo as Trait>::Associated` - = help: consider constraining the associated type `<impl DerivedTrait+Foo as Trait>::Associated` to `()` + found associated type `<impl Foo + DerivedTrait as Trait>::Associated` + = help: consider constraining the associated type `<impl Foo + DerivedTrait as Trait>::Associated` to `()` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html note: required by a bound in `accepts_trait` --> $DIR/issue-87261.rs:43:27 @@ -221,7 +221,7 @@ help: consider constraining the associated type `<impl GenericTrait<()> as Gener LL | fn returns_opaque_generic() -> impl GenericTrait<(), Associated = ()> + 'static { | +++++++++++++++++ -error[E0271]: type mismatch resolving `<impl GenericTrait<()>+Foo as GenericTrait<()>>::Associated == ()` +error[E0271]: type mismatch resolving `<impl Foo + GenericTrait<()> as GenericTrait<()>>::Associated == ()` --> $DIR/issue-87261.rs:94:5 | LL | fn returns_opaque_generic_foo() -> impl GenericTrait<()> + Foo { @@ -231,18 +231,18 @@ LL | accepts_generic_trait(returns_opaque_generic_foo()); | ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type | = note: expected unit type `()` - found associated type `<impl GenericTrait<()>+Foo as GenericTrait<()>>::Associated` + found associated type `<impl Foo + GenericTrait<()> as GenericTrait<()>>::Associated` note: required by a bound in `accepts_generic_trait` --> $DIR/issue-87261.rs:44:46 | LL | fn accepts_generic_trait<T: GenericTrait<(), Associated = ()>>(_: T) {} | ^^^^^^^^^^^^^^^ required by this bound in `accepts_generic_trait` -help: consider constraining the associated type `<impl GenericTrait<()>+Foo as GenericTrait<()>>::Associated` to `()` +help: consider constraining the associated type `<impl Foo + GenericTrait<()> as GenericTrait<()>>::Associated` to `()` | LL | fn returns_opaque_generic_foo() -> impl GenericTrait<(), Associated = ()> + Foo { | +++++++++++++++++ -error[E0271]: type mismatch resolving `<impl GenericTrait<()>+GenericTrait<u8> as GenericTrait<()>>::Associated == ()` +error[E0271]: type mismatch resolving `<impl GenericTrait<u8> + GenericTrait<()> as GenericTrait<()>>::Associated == ()` --> $DIR/issue-87261.rs:97:5 | LL | fn returns_opaque_generic_duplicate() -> impl GenericTrait<()> + GenericTrait<u8> { @@ -252,8 +252,8 @@ LL | accepts_generic_trait(returns_opaque_generic_duplicate()); | ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type | = note: expected unit type `()` - found associated type `<impl GenericTrait<()>+GenericTrait<u8> as GenericTrait<()>>::Associated` - = help: consider constraining the associated type `<impl GenericTrait<()>+GenericTrait<u8> as GenericTrait<()>>::Associated` to `()` + found associated type `<impl GenericTrait<u8> + GenericTrait<()> as GenericTrait<()>>::Associated` + = help: consider constraining the associated type `<impl GenericTrait<u8> + GenericTrait<()> as GenericTrait<()>>::Associated` to `()` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html note: required by a bound in `accepts_generic_trait` --> $DIR/issue-87261.rs:44:46 diff --git a/src/test/ui/substs-ppaux.normal.stderr b/src/test/ui/associated-types/substs-ppaux.normal.stderr similarity index 94% rename from src/test/ui/substs-ppaux.normal.stderr rename to src/test/ui/associated-types/substs-ppaux.normal.stderr index 97caa833d2..085c56870b 100644 --- a/src/test/ui/substs-ppaux.normal.stderr +++ b/src/test/ui/associated-types/substs-ppaux.normal.stderr @@ -82,11 +82,6 @@ note: required because of the requirements on the impl of `Foo<'_, '_, u8>` for | LL | impl<'a,'b,T,S> Foo<'a, 'b, S> for T {} | ^^^^^^^^^^^^^^ ^ -note: required by a bound in `Foo::bar` - --> $DIR/substs-ppaux.rs:7:30 - | -LL | fn bar<'a, T>() where T: 'a {} - | ^^ required by this bound in `Foo::bar` error: aborting due to 5 previous errors diff --git a/src/test/ui/substs-ppaux.rs b/src/test/ui/associated-types/substs-ppaux.rs similarity index 100% rename from src/test/ui/substs-ppaux.rs rename to src/test/ui/associated-types/substs-ppaux.rs diff --git a/src/test/ui/substs-ppaux.verbose.stderr b/src/test/ui/associated-types/substs-ppaux.verbose.stderr similarity index 94% rename from src/test/ui/substs-ppaux.verbose.stderr rename to src/test/ui/associated-types/substs-ppaux.verbose.stderr index 5829073c26..b831f3b7a7 100644 --- a/src/test/ui/substs-ppaux.verbose.stderr +++ b/src/test/ui/associated-types/substs-ppaux.verbose.stderr @@ -82,11 +82,6 @@ note: required because of the requirements on the impl of `Foo<'_#0r, '_#1r, u8> | LL | impl<'a,'b,T,S> Foo<'a, 'b, S> for T {} | ^^^^^^^^^^^^^^ ^ -note: required by a bound in `Foo::bar` - --> $DIR/substs-ppaux.rs:7:30 - | -LL | fn bar<'a, T>() where T: 'a {} - | ^^ required by this bound in `Foo::bar` error: aborting due to 5 previous errors diff --git a/src/test/ui/async-await/async-block-control-flow-static-semantics.rs b/src/test/ui/async-await/async-block-control-flow-static-semantics.rs index 5bc7069ff8..e383276720 100644 --- a/src/test/ui/async-await/async-block-control-flow-static-semantics.rs +++ b/src/test/ui/async-await/async-block-control-flow-static-semantics.rs @@ -15,16 +15,16 @@ fn return_targets_async_block_not_fn() -> u8 { return 0u8; }; let _: &dyn Future<Output = ()> = █ - //~^ ERROR type mismatch resolving `<impl Future as Future>::Output == ()` + //~^ ERROR type mismatch } async fn return_targets_async_block_not_async_fn() -> u8 { - //~^ ERROR mismatched types + //~^ ERROR mismatched types [E0308] let block = async { return 0u8; }; let _: &dyn Future<Output = ()> = █ - //~^ ERROR type mismatch resolving `<impl Future as Future>::Output == ()` + //~^ ERROR type mismatch resolving `<impl Future<Output = [async output]> as Future>::Output == ()` } fn no_break_in_async_block() { diff --git a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr index 919904ce3b..fe864c65b7 100644 --- a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr +++ b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr @@ -31,7 +31,7 @@ LL | | LL | | } | |_^ expected `u8`, found `()` -error[E0271]: type mismatch resolving `<impl Future as Future>::Output == ()` +error[E0271]: type mismatch resolving `<impl Future<Output = [async output]> as Future>::Output == ()` --> $DIR/async-block-control-flow-static-semantics.rs:26:39 | LL | let _: &dyn Future<Output = ()> = █ @@ -47,7 +47,7 @@ LL | fn return_targets_async_block_not_fn() -> u8 { | | | implicitly returns `()` as its body has no tail or `return` expression -error[E0271]: type mismatch resolving `<impl Future as Future>::Output == ()` +error[E0271]: type mismatch resolving `<impl Future<Output = [async output]> as Future>::Output == ()` --> $DIR/async-block-control-flow-static-semantics.rs:17:39 | LL | let _: &dyn Future<Output = ()> = █ diff --git a/src/test/ui/async-await/async-fn-nonsend.stderr b/src/test/ui/async-await/async-fn-nonsend.stderr index d509ff3598..bf7ab148e2 100644 --- a/src/test/ui/async-await/async-fn-nonsend.stderr +++ b/src/test/ui/async-await/async-fn-nonsend.stderr @@ -1,10 +1,10 @@ error: future cannot be sent between threads safely - --> $DIR/async-fn-nonsend.rs:49:5 + --> $DIR/async-fn-nonsend.rs:49:17 | LL | assert_send(local_dropped_before_await()); - | ^^^^^^^^^^^ future returned by `local_dropped_before_await` is not `Send` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `local_dropped_before_await` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` + = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>` note: future is not `Send` as this value is used across an await --> $DIR/async-fn-nonsend.rs:24:5 | @@ -22,12 +22,12 @@ LL | fn assert_send(_: impl Send) {} | ^^^^ required by this bound in `assert_send` error: future cannot be sent between threads safely - --> $DIR/async-fn-nonsend.rs:51:5 + --> $DIR/async-fn-nonsend.rs:51:17 | LL | assert_send(non_send_temporary_in_match()); - | ^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` + = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>` note: future is not `Send` as this value is used across an await --> $DIR/async-fn-nonsend.rs:33:20 | @@ -45,10 +45,10 @@ LL | fn assert_send(_: impl Send) {} | ^^^^ required by this bound in `assert_send` error: future cannot be sent between threads safely - --> $DIR/async-fn-nonsend.rs:53:5 + --> $DIR/async-fn-nonsend.rs:53:17 | LL | assert_send(non_sync_with_method_call()); - | ^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send` | = help: the trait `Send` is not implemented for `dyn std::fmt::Write` note: future is not `Send` as this value is used across an await diff --git a/src/test/ui/async-await/dont-suggest-missing-await.stderr b/src/test/ui/async-await/dont-suggest-missing-await.stderr index 76bbad26c8..289a567209 100644 --- a/src/test/ui/async-await/dont-suggest-missing-await.stderr +++ b/src/test/ui/async-await/dont-suggest-missing-await.stderr @@ -10,7 +10,7 @@ note: while checking the return type of the `async fn` LL | async fn make_u32() -> u32 { | ^^^ checked the `Output` of this `async fn`, found opaque type = note: expected type `u32` - found opaque type `impl Future` + found opaque type `impl Future<Output = u32>` help: consider `await`ing on the `Future` | LL | take_u32(x.await) diff --git a/src/test/ui/async-await/generator-desc.stderr b/src/test/ui/async-await/generator-desc.stderr index d75e927696..4a45d8d2a9 100644 --- a/src/test/ui/async-await/generator-desc.stderr +++ b/src/test/ui/async-await/generator-desc.stderr @@ -25,8 +25,8 @@ note: while checking the return type of the `async fn` | LL | async fn two() {} | ^ checked the `Output` of this `async fn`, found opaque type - = note: expected opaque type `impl Future` (opaque type at <$DIR/generator-desc.rs:5:16>) - found opaque type `impl Future` (opaque type at <$DIR/generator-desc.rs:6:16>) + = note: expected opaque type `impl Future<Output = ()>` (opaque type at <$DIR/generator-desc.rs:5:16>) + found opaque type `impl Future<Output = ()>` (opaque type at <$DIR/generator-desc.rs:6:16>) = help: consider `await`ing on both `Future`s = note: distinct uses of `impl Trait` result in different opaque types @@ -46,8 +46,8 @@ LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return> | the expected opaque type | the found opaque type | - = note: expected opaque type `impl Future` (`async` closure body) - found opaque type `impl Future` (`async` closure body) + = note: expected opaque type `impl Future<Output = [async output]>` (`async` closure body) + found opaque type `impl Future<Output = [async output]>` (`async` closure body) error: aborting due to 3 previous errors diff --git a/src/test/ui/parser/incorrect-move-async-order-issue-79694.fixed b/src/test/ui/async-await/incorrect-move-async-order-issue-79694.fixed similarity index 100% rename from src/test/ui/parser/incorrect-move-async-order-issue-79694.fixed rename to src/test/ui/async-await/incorrect-move-async-order-issue-79694.fixed diff --git a/src/test/ui/parser/incorrect-move-async-order-issue-79694.rs b/src/test/ui/async-await/incorrect-move-async-order-issue-79694.rs similarity index 100% rename from src/test/ui/parser/incorrect-move-async-order-issue-79694.rs rename to src/test/ui/async-await/incorrect-move-async-order-issue-79694.rs diff --git a/src/test/ui/parser/incorrect-move-async-order-issue-79694.stderr b/src/test/ui/async-await/incorrect-move-async-order-issue-79694.stderr similarity index 100% rename from src/test/ui/parser/incorrect-move-async-order-issue-79694.stderr rename to src/test/ui/async-await/incorrect-move-async-order-issue-79694.stderr diff --git a/src/test/ui/async-await/issue-61076.rs b/src/test/ui/async-await/issue-61076.rs index 220f0774e2..a94136cfea 100644 --- a/src/test/ui/async-await/issue-61076.rs +++ b/src/test/ui/async-await/issue-61076.rs @@ -40,14 +40,12 @@ async fn foo() -> Result<(), ()> { async fn bar() -> Result<(), ()> { foo()?; //~ ERROR the `?` operator can only be applied to values that implement `Try` - //~^ NOTE the `?` operator cannot be applied to type `impl Future` - //~| HELP the trait `Try` is not implemented for `impl Future` - //~| NOTE required by `branch` + //~^ NOTE the `?` operator cannot be applied to type `impl Future<Output = Result<(), ()>>` + //~| HELP the trait `Try` is not implemented for `impl Future<Output = Result<(), ()>>` //~| HELP consider `await`ing on the `Future` //~| NOTE in this expansion of desugaring of operator `?` //~| NOTE in this expansion of desugaring of operator `?` //~| NOTE in this expansion of desugaring of operator `?` - //~| NOTE in this expansion of desugaring of operator `?` Ok(()) } @@ -67,12 +65,10 @@ async fn baz() -> Result<(), ()> { t?; //~ ERROR the `?` operator can only be applied to values that implement `Try` //~^ NOTE the `?` operator cannot be applied to type `T` //~| HELP the trait `Try` is not implemented for `T` - //~| NOTE required by `branch` //~| HELP consider `await`ing on the `Future` //~| NOTE in this expansion of desugaring of operator `?` //~| NOTE in this expansion of desugaring of operator `?` //~| NOTE in this expansion of desugaring of operator `?` - //~| NOTE in this expansion of desugaring of operator `?` let _: i32 = tuple().0; //~ ERROR no field `0` @@ -84,7 +80,7 @@ async fn baz() -> Result<(), ()> { //~| NOTE field not available in `impl Future` struct_().method(); //~ ERROR no method named - //~^ NOTE method not found in `impl Future` + //~^ NOTE method not found in `impl Future<Output = Struct>` //~| HELP consider `await`ing on the `Future` Ok(()) } @@ -93,7 +89,7 @@ async fn match_() { match tuple() { //~ HELP consider `await`ing on the `Future` Tuple(_) => {} //~ ERROR mismatched types //~^ NOTE expected opaque type, found struct `Tuple` - //~| NOTE expected opaque type `impl Future` + //~| NOTE expected opaque type `impl Future<Output = Tuple>` } } diff --git a/src/test/ui/async-await/issue-61076.stderr b/src/test/ui/async-await/issue-61076.stderr index 60b5bfa53d..65c0bc695b 100644 --- a/src/test/ui/async-await/issue-61076.stderr +++ b/src/test/ui/async-await/issue-61076.stderr @@ -2,38 +2,28 @@ error[E0277]: the `?` operator can only be applied to values that implement `Try --> $DIR/issue-61076.rs:42:5 | LL | foo()?; - | ^^^^^^ the `?` operator cannot be applied to type `impl Future` + | ^^^^^^ the `?` operator cannot be applied to type `impl Future<Output = Result<(), ()>>` | - = help: the trait `Try` is not implemented for `impl Future` -note: required by `branch` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn branch(self) -> ControlFlow<Self::Residual, Self::Output>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: the trait `Try` is not implemented for `impl Future<Output = Result<(), ()>>` help: consider `await`ing on the `Future` | LL | foo().await?; | ++++++ error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/issue-61076.rs:67:5 + --> $DIR/issue-61076.rs:65:5 | LL | t?; | ^^ the `?` operator cannot be applied to type `T` | = help: the trait `Try` is not implemented for `T` -note: required by `branch` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn branch(self) -> ControlFlow<Self::Residual, Self::Output>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `await`ing on the `Future` | LL | t.await?; | ++++++ -error[E0609]: no field `0` on type `impl Future` - --> $DIR/issue-61076.rs:78:26 +error[E0609]: no field `0` on type `impl Future<Output = Tuple>` + --> $DIR/issue-61076.rs:74:26 | LL | let _: i32 = tuple().0; | ^ field not available in `impl Future`, but it is available in its `Output` @@ -43,8 +33,8 @@ help: consider `await`ing on the `Future` and access the field of its `Output` LL | let _: i32 = tuple().await.0; | ++++++ -error[E0609]: no field `a` on type `impl Future` - --> $DIR/issue-61076.rs:82:28 +error[E0609]: no field `a` on type `impl Future<Output = Struct>` + --> $DIR/issue-61076.rs:78:28 | LL | let _: i32 = struct_().a; | ^ field not available in `impl Future`, but it is available in its `Output` @@ -54,11 +44,11 @@ help: consider `await`ing on the `Future` and access the field of its `Output` LL | let _: i32 = struct_().await.a; | ++++++ -error[E0599]: no method named `method` found for opaque type `impl Future` in the current scope - --> $DIR/issue-61076.rs:86:15 +error[E0599]: no method named `method` found for opaque type `impl Future<Output = Struct>` in the current scope + --> $DIR/issue-61076.rs:82:15 | LL | struct_().method(); - | ^^^^^^ method not found in `impl Future` + | ^^^^^^ method not found in `impl Future<Output = Struct>` | help: consider `await`ing on the `Future` and calling the method on its `Output` | @@ -66,17 +56,17 @@ LL | struct_().await.method(); | ++++++ error[E0308]: mismatched types - --> $DIR/issue-61076.rs:94:9 + --> $DIR/issue-61076.rs:90:9 | LL | Tuple(_) => {} | ^^^^^^^^ expected opaque type, found struct `Tuple` | note: while checking the return type of the `async fn` - --> $DIR/issue-61076.rs:58:21 + --> $DIR/issue-61076.rs:56:21 | LL | async fn tuple() -> Tuple { | ^^^^^ checked the `Output` of this `async fn`, expected opaque type - = note: expected opaque type `impl Future` + = note: expected opaque type `impl Future<Output = Tuple>` found struct `Tuple` help: consider `await`ing on the `Future` | diff --git a/src/test/ui/async-await/issue-64130-1-sync.stderr b/src/test/ui/async-await/issue-64130-1-sync.stderr index 69c7ff4745..010611fae4 100644 --- a/src/test/ui/async-await/issue-64130-1-sync.stderr +++ b/src/test/ui/async-await/issue-64130-1-sync.stderr @@ -1,10 +1,10 @@ error: future cannot be shared between threads safely - --> $DIR/issue-64130-1-sync.rs:21:5 + --> $DIR/issue-64130-1-sync.rs:21:13 | LL | is_sync(bar()); - | ^^^^^^^ future returned by `bar` is not `Sync` + | ^^^^^ future returned by `bar` is not `Sync` | - = help: within `impl Future`, the trait `Sync` is not implemented for `Foo` + = help: within `impl Future<Output = ()>`, the trait `Sync` is not implemented for `Foo` note: future is not `Sync` as this value is used across an await --> $DIR/issue-64130-1-sync.rs:15:5 | diff --git a/src/test/ui/async-await/issue-64130-2-send.stderr b/src/test/ui/async-await/issue-64130-2-send.stderr index 933e929684..bb598b5359 100644 --- a/src/test/ui/async-await/issue-64130-2-send.stderr +++ b/src/test/ui/async-await/issue-64130-2-send.stderr @@ -1,10 +1,10 @@ error: future cannot be sent between threads safely - --> $DIR/issue-64130-2-send.rs:21:5 + --> $DIR/issue-64130-2-send.rs:21:13 | LL | is_send(bar()); - | ^^^^^^^ future returned by `bar` is not `Send` + | ^^^^^ future returned by `bar` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `Foo` + = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Foo` note: future is not `Send` as this value is used across an await --> $DIR/issue-64130-2-send.rs:15:5 | diff --git a/src/test/ui/async-await/issue-64130-3-other.rs b/src/test/ui/async-await/issue-64130-3-other.rs index 7f2e3db6d6..52801c35ba 100644 --- a/src/test/ui/async-await/issue-64130-3-other.rs +++ b/src/test/ui/async-await/issue-64130-3-other.rs @@ -5,22 +5,22 @@ // This tests the the unspecialized async-await-specific error when futures don't implement an // auto trait (which is not Send or Sync) due to some type that was captured. -auto trait Qux { } +auto trait Qux {} struct Foo; impl !Qux for Foo {} -fn is_qux<T: Qux>(t: T) { } +fn is_qux<T: Qux>(t: T) {} async fn bar() { let x = Foo; baz().await; } -async fn baz() { } +async fn baz() {} fn main() { is_qux(bar()); - //~^ ERROR the trait bound `Foo: Qux` is not satisfied in `impl Future` + //~^ ERROR the trait bound `Foo: Qux` is not satisfied in `impl Future<Output = ()>` } diff --git a/src/test/ui/async-await/issue-64130-3-other.stderr b/src/test/ui/async-await/issue-64130-3-other.stderr index ec0fdd4a55..4de7929e18 100644 --- a/src/test/ui/async-await/issue-64130-3-other.stderr +++ b/src/test/ui/async-await/issue-64130-3-other.stderr @@ -1,11 +1,11 @@ -error[E0277]: the trait bound `Foo: Qux` is not satisfied in `impl Future` - --> $DIR/issue-64130-3-other.rs:24:5 +error[E0277]: the trait bound `Foo: Qux` is not satisfied in `impl Future<Output = ()>` + --> $DIR/issue-64130-3-other.rs:24:12 | LL | async fn bar() { - | - within this `impl Future` + | - within this `impl Future<Output = ()>` ... LL | is_qux(bar()); - | ^^^^^^ within `impl Future`, the trait `Qux` is not implemented for `Foo` + | ^^^^^ within `impl Future<Output = ()>`, the trait `Qux` is not implemented for `Foo` | note: future does not implement `Qux` as this value is used across an await --> $DIR/issue-64130-3-other.rs:18:5 @@ -19,7 +19,7 @@ LL | } note: required by a bound in `is_qux` --> $DIR/issue-64130-3-other.rs:14:14 | -LL | fn is_qux<T: Qux>(t: T) { } +LL | fn is_qux<T: Qux>(t: T) {} | ^^^ required by this bound in `is_qux` error: aborting due to previous error diff --git a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr index 81e026dc54..8eedb35973 100644 --- a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr +++ b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr @@ -1,10 +1,10 @@ error: future cannot be sent between threads safely - --> $DIR/issue-64130-non-send-future-diags.rs:23:5 + --> $DIR/issue-64130-non-send-future-diags.rs:23:13 | LL | is_send(foo()); - | ^^^^^^^ future returned by `foo` is not `Send` + | ^^^^^ future returned by `foo` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, u32>` + = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `MutexGuard<'_, u32>` note: future is not `Send` as this value is used across an await --> $DIR/issue-64130-non-send-future-diags.rs:17:5 | diff --git a/src/test/ui/async-await/issue-67252-unnamed-future.stderr b/src/test/ui/async-await/issue-67252-unnamed-future.stderr index d046e2a056..b61694ad53 100644 --- a/src/test/ui/async-await/issue-67252-unnamed-future.stderr +++ b/src/test/ui/async-await/issue-67252-unnamed-future.stderr @@ -4,7 +4,7 @@ error: future cannot be sent between threads safely LL | spawn(async { | ^^^^^ future created by async block is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `*mut ()` + = help: within `impl Future<Output = [async output]>`, the trait `Send` is not implemented for `*mut ()` note: future is not `Send` as this value is used across an await --> $DIR/issue-67252-unnamed-future.rs:20:9 | diff --git a/src/test/ui/async-await/issue-68112.stderr b/src/test/ui/async-await/issue-68112.stderr index 6b8e49a21a..a8c2ebe12f 100644 --- a/src/test/ui/async-await/issue-68112.stderr +++ b/src/test/ui/async-await/issue-68112.stderr @@ -9,7 +9,7 @@ note: future is not `Send` as it awaits another future which is not `Send` --> $DIR/issue-68112.rs:31:17 | LL | let _ = non_send_fut.await; - | ^^^^^^^^^^^^ await occurs here on type `impl Future`, which is not `Send` + | ^^^^^^^^^^^^ await occurs here on type `impl Future<Output = Arc<RefCell<i32>>>`, which is not `Send` note: required by a bound in `require_send` --> $DIR/issue-68112.rs:11:25 | @@ -27,7 +27,7 @@ note: future is not `Send` as it awaits another future which is not `Send` --> $DIR/issue-68112.rs:40:17 | LL | let _ = make_non_send_future1().await; - | ^^^^^^^^^^^^^^^^^^^^^^^ await occurs here on type `impl Future`, which is not `Send` + | ^^^^^^^^^^^^^^^^^^^^^^^ await occurs here on type `impl Future<Output = Arc<RefCell<i32>>>`, which is not `Send` note: required by a bound in `require_send` --> $DIR/issue-68112.rs:11:25 | @@ -44,13 +44,13 @@ LL | require_send(send_fut); = note: required because of the requirements on the impl of `Send` for `Arc<RefCell<i32>>` = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:47:31: 47:36]` = note: required because it appears within the type `from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:47:31: 47:36]>` - = note: required because it appears within the type `impl Future` - = note: required because it appears within the type `impl Future` - = note: required because it appears within the type `impl Future` - = note: required because it appears within the type `{ResumeTy, impl Future, (), i32, Ready<i32>}` + = note: required because it appears within the type `impl Future<Output = [async output]>` + = note: required because it appears within the type `impl Future<Output = Arc<RefCell<i32>>>` + = note: required because it appears within the type `impl Future<Output = Arc<RefCell<i32>>>` + = note: required because it appears within the type `{ResumeTy, impl Future<Output = Arc<RefCell<i32>>>, (), i32, Ready<i32>}` = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:55:26: 59:6]` = note: required because it appears within the type `from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:55:26: 59:6]>` - = note: required because it appears within the type `impl Future` + = note: required because it appears within the type `impl Future<Output = [async output]>` note: required by a bound in `require_send` --> $DIR/issue-68112.rs:11:25 | diff --git a/src/test/ui/async-await/issue-70594.stderr b/src/test/ui/async-await/issue-70594.stderr index e20e2e8f6b..eb24040404 100644 --- a/src/test/ui/async-await/issue-70594.stderr +++ b/src/test/ui/async-await/issue-70594.stderr @@ -25,11 +25,6 @@ LL | [1; ().await]; | ^^^^^^^^ `()` is not a future | = help: the trait `Future` is not implemented for `()` -note: required by `poll` - --> $SRC_DIR/core/src/future/future.rs:LL:COL - | -LL | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/async-await/issue-71137.stderr b/src/test/ui/async-await/issue-71137.stderr index c9a2d7587b..dddea12162 100644 --- a/src/test/ui/async-await/issue-71137.stderr +++ b/src/test/ui/async-await/issue-71137.stderr @@ -1,10 +1,10 @@ error: future cannot be sent between threads safely - --> $DIR/issue-71137.rs:22:3 + --> $DIR/issue-71137.rs:22:14 | LL | fake_spawn(wrong_mutex()); - | ^^^^^^^^^^ future returned by `wrong_mutex` is not `Send` + | ^^^^^^^^^^^^^ future returned by `wrong_mutex` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, i32>` + = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `MutexGuard<'_, i32>` note: future is not `Send` as this value is used across an await --> $DIR/issue-71137.rs:14:5 | diff --git a/src/test/ui/issues/issue-73541-1.rs b/src/test/ui/async-await/issue-73541-1.rs similarity index 100% rename from src/test/ui/issues/issue-73541-1.rs rename to src/test/ui/async-await/issue-73541-1.rs diff --git a/src/test/ui/issues/issue-73541-1.stderr b/src/test/ui/async-await/issue-73541-1.stderr similarity index 100% rename from src/test/ui/issues/issue-73541-1.stderr rename to src/test/ui/async-await/issue-73541-1.stderr diff --git a/src/test/ui/async-await/issue-74497-lifetime-in-opaque.stderr b/src/test/ui/async-await/issue-74497-lifetime-in-opaque.stderr index 89fe1abb36..4427014ae3 100644 --- a/src/test/ui/async-await/issue-74497-lifetime-in-opaque.stderr +++ b/src/test/ui/async-await/issue-74497-lifetime-in-opaque.stderr @@ -4,7 +4,7 @@ error: lifetime may not live long enough LL | let _ = foo(|x| bar(x)); | -- ^^^^^^ returning this value requires that `'1` must outlive `'2` | || - | |return type of closure `impl Future` contains a lifetime `'2` + | |return type of closure `impl Future<Output = ()>` contains a lifetime `'2` | has type `&'1 u8` error: aborting due to previous error diff --git a/src/test/ui/async-await/issue-84841.stderr b/src/test/ui/async-await/issue-84841.stderr index e28ba74eb6..1e22373ba6 100644 --- a/src/test/ui/async-await/issue-84841.stderr +++ b/src/test/ui/async-await/issue-84841.stderr @@ -2,14 +2,9 @@ error[E0277]: the `?` operator can only be applied to values that implement `Try --> $DIR/issue-84841.rs:9:5 | LL | test()?; - | ^^^^^^^ the `?` operator cannot be applied to type `impl Future` + | ^^^^^^^ the `?` operator cannot be applied to type `impl Future<Output = ()>` | - = help: the trait `Try` is not implemented for `impl Future` -note: required by `branch` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn branch(self) -> ControlFlow<Self::Residual, Self::Output>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: the trait `Try` is not implemented for `impl Future<Output = ()>` error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `FromResidual`) --> $DIR/issue-84841.rs:9:11 @@ -25,11 +20,6 @@ LL | | } | |_- this function should return `Result` or `Option` to accept `?` | = help: the trait `FromResidual<_>` is not implemented for `()` -note: required by `from_residual` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn from_residual(residual: R) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/async-await/issues/issue-62009-1.stderr b/src/test/ui/async-await/issues/issue-62009-1.stderr index 946b8d19e6..e2ea72a1e6 100644 --- a/src/test/ui/async-await/issues/issue-62009-1.stderr +++ b/src/test/ui/async-await/issues/issue-62009-1.stderr @@ -34,11 +34,6 @@ LL | (|_| 2333).await; | ^^^^^^^^^^^^^^^^ `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]` is not a future | = help: the trait `Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]` -note: required by `poll` - --> $SRC_DIR/core/src/future/future.rs:LL:COL - | -LL | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr index 666ef851ad..6ebefbebe5 100644 --- a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr +++ b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr @@ -4,7 +4,7 @@ error: future cannot be sent between threads safely LL | assert_send(async { | ^^^^^^^^^^^ future created by async block is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `*const u8` + = help: within `impl Future<Output = [async output]>`, the trait `Send` is not implemented for `*const u8` note: future is not `Send` as this value is used across an await --> $DIR/issue-65436-raw-ptr-not-send.rs:14:9 | diff --git a/src/test/ui/async-await/issues/issue-67893.rs b/src/test/ui/async-await/issues/issue-67893.rs index f34ce8081c..8b53408d75 100644 --- a/src/test/ui/async-await/issues/issue-67893.rs +++ b/src/test/ui/async-await/issues/issue-67893.rs @@ -7,5 +7,5 @@ fn g(_: impl Send) {} fn main() { g(issue_67893::run()) - //~^ ERROR: `MutexGuard<'_, ()>` cannot be sent between threads safely + //~^ ERROR generator cannot be sent between threads safely } diff --git a/src/test/ui/async-await/issues/issue-67893.stderr b/src/test/ui/async-await/issues/issue-67893.stderr index c4b55e6ec2..0aa0d5d7cc 100644 --- a/src/test/ui/async-await/issues/issue-67893.stderr +++ b/src/test/ui/async-await/issues/issue-67893.stderr @@ -1,20 +1,10 @@ -error[E0277]: `MutexGuard<'_, ()>` cannot be sent between threads safely - --> $DIR/issue-67893.rs:9:5 +error: generator cannot be sent between threads safely + --> $DIR/issue-67893.rs:9:7 | LL | g(issue_67893::run()) - | ^ `MutexGuard<'_, ()>` cannot be sent between threads safely + | ^^^^^^^^^^^^^^^^^^ generator is not `Send` | - ::: $DIR/auxiliary/issue_67893.rs:7:20 - | -LL | pub async fn run() { - | - within this `impl Future` - | - = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, ()>` - = note: required because it appears within the type `for<'r, 's, 't0, 't1, 't2, 't3> {ResumeTy, Arc<Mutex<()>>, &'r Mutex<()>, Result<MutexGuard<'s, ()>, PoisonError<MutexGuard<'t0, ()>>>, &'t1 MutexGuard<'t2, ()>, MutexGuard<'t3, ()>, (), impl Future}` - = note: required because it appears within the type `[static generator@run::{closure#0}]` - = note: required because it appears within the type `from_generator::GenFuture<[static generator@run::{closure#0}]>` - = note: required because it appears within the type `impl Future` - = note: required because it appears within the type `impl Future` + = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `MutexGuard<'_, ()>` note: required by a bound in `g` --> $DIR/issue-67893.rs:6:14 | @@ -23,4 +13,3 @@ LL | fn g(_: impl Send) {} error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr index b6841da1f0..9b0018d890 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr +++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr @@ -1,13 +1,31 @@ error: lifetime may not live long enough - --> $DIR/ret-impl-trait-one.rs:10:65 + --> $DIR/ret-impl-trait-one.rs:10:85 + | +LL | async fn async_ret_impl_trait3<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b { + | ________________________________--__--_______________________________________________^ + | | | | + | | | lifetime `'b` defined here + | | lifetime `'a` defined here +LL | | +LL | | (a, b) +LL | | } + | |_^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ret-impl-trait-one.rs:16:65 | LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> { - | -- -- ^^^^^^^^^^^^^^ opaque type requires that `'b` must outlive `'a` - | | | - | | lifetime `'b` defined here - | lifetime `'a` defined here + | -- ^^^^^^^^^^^^^^ + | | + | hidden type `(&'a u8, &'b u8)` captures the lifetime `'b` as defined here + | +help: to declare that the `impl Trait` captures 'b, you can add an explicit `'b` lifetime bound | - = help: consider adding the following bound: `'b: 'a` +LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b { + | ++++ -error: aborting due to previous error +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs index 7e084217c2..4f32489014 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs +++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs @@ -6,9 +6,15 @@ trait Trait<'a> { } impl<T> Trait<'_> for T { } +// Fails to recognize that both 'a and 'b are mentioned and should thus be accepted +async fn async_ret_impl_trait3<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b { + //~^ ERROR lifetime mismatch + (a, b) +} + // Only `'a` permitted in return type, not `'b`. async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> { - //~^ ERROR lifetime mismatch + //~^ ERROR captures lifetime that does not appear in bounds (a, b) } diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr index 8e28605721..bcd96367e2 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr +++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr @@ -1,13 +1,27 @@ error[E0623]: lifetime mismatch --> $DIR/ret-impl-trait-one.rs:10:65 | +LL | async fn async_ret_impl_trait3<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b { + | ------ ^^^^^^^^^^^^^^^^^^^ + | | | + | | ...but data from `a` is held across an await point here + | | this `async fn` implicitly returns an `impl Future<Output = impl Trait<'a> + 'b>` + | this parameter and the returned future are declared with different lifetimes... + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ret-impl-trait-one.rs:16:65 + | LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> { - | ------ ^^^^^^^^^^^^^^ - | | | - | | ...but data from `b` is held across an await point here - | | this `async fn` implicitly returns an `impl Future<Output = impl Trait<'a>>` - | this parameter and the returned future are declared with different lifetimes... + | -- ^^^^^^^^^^^^^^ + | | + | hidden type `(&'a u8, &'b u8)` captures the lifetime `'b` as defined here + | +help: to declare that the `impl Trait` captures 'b, you can add an explicit `'b` lifetime bound + | +LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b { + | ++++ -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0623`. +Some errors have detailed explanations: E0623, E0700. +For more information about an error, try `rustc --explain E0623`. 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 index 8c581ff222..83d1a02c87 100644 --- a/src/test/ui/async-await/pin-needed-to-poll-2.stderr +++ b/src/test/ui/async-await/pin-needed-to-poll-2.stderr @@ -1,8 +1,10 @@ error[E0277]: `PhantomPinned` cannot be unpinned - --> $DIR/pin-needed-to-poll-2.rs:43:9 + --> $DIR/pin-needed-to-poll-2.rs:43:18 | LL | Pin::new(&mut self.sleep).poll(cx) - | ^^^^^^^^ within `Sleep`, the trait `Unpin` is not implemented for `PhantomPinned` + | -------- ^^^^^^^^^^^^^^^ within `Sleep`, the trait `Unpin` is not implemented for `PhantomPinned` + | | + | required by a bound introduced by this call | = note: consider using `Box::pin` note: required because it appears within the type `Sleep` @@ -10,11 +12,11 @@ note: required because it appears within the type `Sleep` | LL | struct Sleep(std::marker::PhantomPinned); | ^^^^^ -note: required by `Pin::<P>::new` +note: required by a bound in `Pin::<P>::new` --> $SRC_DIR/core/src/pin.rs:LL:COL | -LL | pub const fn new(pointer: P) -> Pin<P> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl<P: Deref<Target: Unpin>> Pin<P> { + | ^^^^^ required by this bound in `Pin::<P>::new` error: aborting due to previous error diff --git a/src/test/ui/async-await/suggest-missing-await-closure.stderr b/src/test/ui/async-await/suggest-missing-await-closure.stderr index 630ae4b539..d951c8ed09 100644 --- a/src/test/ui/async-await/suggest-missing-await-closure.stderr +++ b/src/test/ui/async-await/suggest-missing-await-closure.stderr @@ -10,7 +10,7 @@ note: while checking the return type of the `async fn` LL | async fn make_u32() -> u32 { | ^^^ checked the `Output` of this `async fn`, found opaque type = note: expected type `u32` - found opaque type `impl Future` + found opaque type `impl Future<Output = u32>` help: consider `await`ing on the `Future` | LL | take_u32(x.await) diff --git a/src/test/ui/async-await/suggest-missing-await.rs b/src/test/ui/async-await/suggest-missing-await.rs index 352a88ac10..c7c5b51e73 100644 --- a/src/test/ui/async-await/suggest-missing-await.rs +++ b/src/test/ui/async-await/suggest-missing-await.rs @@ -26,4 +26,49 @@ async fn suggest_await_in_async_fn_return() { //~| SUGGESTION .await } +#[allow(unused)] +async fn suggest_await_on_if() { + let _x = if true { + dummy() + //~^ HELP consider `await`ing on the `Future` + } else { + dummy().await + //~^ ERROR `if` and `else` have incompatible types [E0308] + }; +} + +#[allow(unused)] +async fn suggest_await_on_previous_match_arms() { + let _x = match 0usize { + 0 => dummy(), //~ HELP consider `await`ing on the `Future` + 1 => dummy(), + 2 => dummy().await, + //~^ `match` arms have incompatible types [E0308] + }; +} + +#[allow(unused)] +async fn suggest_await_on_match_expr() { + let _x = match dummy() { //~ HELP consider `await`ing on the `Future` + () => {} //~ ERROR mismatched types [E0308] + }; +} + +async fn dummy_result() -> Result<(), ()> { + Ok(()) +} + +#[allow(unused)] +async fn suggest_await_in_generic_pattern() { + match dummy_result() { + //~^ HELP consider `await`ing on the `Future` + //~| HELP consider `await`ing on the `Future` + //~| SUGGESTION .await + Ok(_) => {} + //~^ ERROR mismatched types [E0308] + Err(_) => {} + //~^ ERROR mismatched types [E0308] + } +} + fn main() {} diff --git a/src/test/ui/async-await/suggest-missing-await.stderr b/src/test/ui/async-await/suggest-missing-await.stderr index 08868a0465..3cca9616a3 100644 --- a/src/test/ui/async-await/suggest-missing-await.stderr +++ b/src/test/ui/async-await/suggest-missing-await.stderr @@ -10,7 +10,7 @@ note: while checking the return type of the `async fn` LL | async fn make_u32() -> u32 { | ^^^ checked the `Output` of this `async fn`, found opaque type = note: expected type `u32` - found opaque type `impl Future` + found opaque type `impl Future<Output = u32>` help: consider `await`ing on the `Future` | LL | take_u32(x.await) @@ -28,7 +28,7 @@ note: while checking the return type of the `async fn` LL | async fn dummy() {} | ^ checked the `Output` of this `async fn`, found opaque type = note: expected unit type `()` - found opaque type `impl Future` + found opaque type `impl Future<Output = ()>` help: consider `await`ing on the `Future` | LL | dummy().await @@ -38,6 +38,110 @@ help: consider using a semicolon here LL | dummy(); | + -error: aborting due to 2 previous errors +error[E0308]: `if` and `else` have incompatible types + --> $DIR/suggest-missing-await.rs:35:9 + | +LL | let _x = if true { + | ______________- +LL | | dummy() + | | ------- expected because of this +LL | | +LL | | } else { +LL | | dummy().await + | | ^^^^^^^^^^^^^ expected opaque type, found `()` +LL | | +LL | | }; + | |_____- `if` and `else` have incompatible types + | + = note: expected type `impl Future<Output = ()>` + found unit type `()` +help: consider `await`ing on the `Future` + | +LL | dummy().await + | ++++++ + +error[E0308]: `match` arms have incompatible types + --> $DIR/suggest-missing-await.rs:45:14 + | +LL | let _x = match 0usize { + | ______________- +LL | | 0 => dummy(), + | | ------- this is found to be of type `impl Future<Output = ()>` +LL | | 1 => dummy(), + | | ------- this is found to be of type `impl Future<Output = ()>` +LL | | 2 => dummy().await, + | | ^^^^^^^^^^^^^ expected opaque type, found `()` +LL | | +LL | | }; + | |_____- `match` arms have incompatible types + | +note: while checking the return type of the `async fn` + --> $DIR/suggest-missing-await.rs:18:18 + | +LL | async fn dummy() {} + | ^ checked the `Output` of this `async fn`, expected opaque type + = note: expected opaque type `impl Future<Output = ()>` + found unit type `()` +help: consider `await`ing on the `Future` + | +LL ~ 0 => dummy().await, +LL ~ 1 => dummy().await, + | + +error[E0308]: mismatched types + --> $DIR/suggest-missing-await.rs:53:9 + | +LL | () => {} + | ^^ expected opaque type, found `()` + | +note: while checking the return type of the `async fn` + --> $DIR/suggest-missing-await.rs:18:18 + | +LL | async fn dummy() {} + | ^ checked the `Output` of this `async fn`, expected opaque type + = note: expected opaque type `impl Future<Output = ()>` + found unit type `()` +help: consider `await`ing on the `Future` + | +LL | let _x = match dummy().await { + | ++++++ + +error[E0308]: mismatched types + --> $DIR/suggest-missing-await.rs:67:9 + | +LL | Ok(_) => {} + | ^^^^^ expected opaque type, found enum `Result` + | +note: while checking the return type of the `async fn` + --> $DIR/suggest-missing-await.rs:57:28 + | +LL | async fn dummy_result() -> Result<(), ()> { + | ^^^^^^^^^^^^^^ checked the `Output` of this `async fn`, expected opaque type + = note: expected opaque type `impl Future<Output = Result<(), ()>>` + found enum `Result<_, _>` +help: consider `await`ing on the `Future` + | +LL | match dummy_result().await { + | ++++++ + +error[E0308]: mismatched types + --> $DIR/suggest-missing-await.rs:69:9 + | +LL | Err(_) => {} + | ^^^^^^ expected opaque type, found enum `Result` + | +note: while checking the return type of the `async fn` + --> $DIR/suggest-missing-await.rs:57:28 + | +LL | async fn dummy_result() -> Result<(), ()> { + | ^^^^^^^^^^^^^^ checked the `Output` of this `async fn`, expected opaque type + = note: expected opaque type `impl Future<Output = Result<(), ()>>` + found enum `Result<_, _>` +help: consider `await`ing on the `Future` + | +LL | match dummy_result().await { + | ++++++ + +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/async-await/try-on-option-in-async.stderr b/src/test/ui/async-await/try-on-option-in-async.stderr index e8bb4aca9a..a55850d76c 100644 --- a/src/test/ui/async-await/try-on-option-in-async.stderr +++ b/src/test/ui/async-await/try-on-option-in-async.stderr @@ -11,11 +11,6 @@ LL | | } | |_____- this function should return `Result` or `Option` to accept `?` | = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `{integer}` -note: required by `from_residual` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn from_residual(residual: R) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used in an async closure that returns `Result` or `Option` (or another type that implements `FromResidual`) --> $DIR/try-on-option-in-async.rs:17:10 @@ -30,11 +25,6 @@ LL | | }; | |_____- this function should return `Result` or `Option` to accept `?` | = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32` -note: required by `from_residual` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn from_residual(residual: R) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `FromResidual`) --> $DIR/try-on-option-in-async.rs:26:6 @@ -49,11 +39,6 @@ LL | | } | |_- this function should return `Result` or `Option` to accept `?` | = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32` -note: required by `from_residual` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn from_residual(residual: R) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/attr-eq-token-tree.rs b/src/test/ui/attributes/attr-eq-token-tree.rs similarity index 100% rename from src/test/ui/attr-eq-token-tree.rs rename to src/test/ui/attributes/attr-eq-token-tree.rs diff --git a/src/test/ui/attr-eq-token-tree.stderr b/src/test/ui/attributes/attr-eq-token-tree.stderr similarity index 100% rename from src/test/ui/attr-eq-token-tree.stderr rename to src/test/ui/attributes/attr-eq-token-tree.stderr diff --git a/src/test/ui/attributes/invalid-doc-attr.stderr b/src/test/ui/attributes/invalid-doc-attr.stderr index 595ece2ea7..55006b2087 100644 --- a/src/test/ui/attributes/invalid-doc-attr.stderr +++ b/src/test/ui/attributes/invalid-doc-attr.stderr @@ -29,7 +29,7 @@ LL | pub fn foo() {} | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730> - = note: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#docno_inlinedocinline for more information + = note: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline for more information error: this attribute can only be applied at the crate level --> $DIR/invalid-doc-attr.rs:15:12 @@ -72,7 +72,7 @@ LL | pub fn 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 #82730 <https://github.com/rust-lang/rust/issues/82730> - = note: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#docno_inlinedocinline for more information + = note: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline for more information error: aborting due to 6 previous errors diff --git a/src/test/ui/issues/issue-40962.rs b/src/test/ui/attributes/issue-40962.rs similarity index 100% rename from src/test/ui/issues/issue-40962.rs rename to src/test/ui/attributes/issue-40962.rs diff --git a/src/test/ui/attributes/issue-90873.rs b/src/test/ui/attributes/issue-90873.rs new file mode 100644 index 0000000000..76708ea983 --- /dev/null +++ b/src/test/ui/attributes/issue-90873.rs @@ -0,0 +1,9 @@ +#![u=||{static d=||1;}] +//~^ unexpected token +//~| cannot find attribute `u` in this scope +//~| `main` function not found in crate `issue_90873` +//~| missing type for `static` item + +#![a={impl std::ops::Neg for i8 {}}] +//~^ ERROR unexpected token +//~| ERROR cannot find attribute `a` in this scope diff --git a/src/test/ui/attributes/issue-90873.stderr b/src/test/ui/attributes/issue-90873.stderr new file mode 100644 index 0000000000..d466157f04 --- /dev/null +++ b/src/test/ui/attributes/issue-90873.stderr @@ -0,0 +1,50 @@ +error: unexpected token: `|| + { + static d: _ = || 1; + }` + --> $DIR/issue-90873.rs:1:6 + | +LL | #![u=||{static d=||1;}] + | ^^^^^^^^^^^^^^^^^ + +error: unexpected token: `{ + impl std::ops::Neg for i8 { } + }` + --> $DIR/issue-90873.rs:7:6 + | +LL | #![a={impl std::ops::Neg for i8 {}}] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: cannot find attribute `u` in this scope + --> $DIR/issue-90873.rs:1:4 + | +LL | #![u=||{static d=||1;}] + | ^ + +error: cannot find attribute `a` in this scope + --> $DIR/issue-90873.rs:7:4 + | +LL | #![a={impl std::ops::Neg for i8 {}}] + | ^ + +error[E0601]: `main` function not found in crate `issue_90873` + --> $DIR/issue-90873.rs:1:1 + | +LL | / #![u=||{static d=||1;}] +LL | | +LL | | +LL | | +LL | | +LL | | +LL | | #![a={impl std::ops::Neg for i8 {}}] + | |____________________________________^ consider adding a `main` function to `$DIR/issue-90873.rs` + +error: missing type for `static` item + --> $DIR/issue-90873.rs:1:16 + | +LL | #![u=||{static d=||1;}] + | ^ help: provide a type for the item: `d: <type>` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/attributes/key-value-expansion.stderr b/src/test/ui/attributes/key-value-expansion.stderr index ef59381f5f..878afb3921 100644 --- a/src/test/ui/attributes/key-value-expansion.stderr +++ b/src/test/ui/attributes/key-value-expansion.stderr @@ -16,15 +16,15 @@ LL | bug!(); = note: this error originates in the macro `bug` (in Nightly builds, run with -Z macro-backtrace for more info) error: unexpected token: `{ - let res = - ::alloc::fmt::format(::core::fmt::Arguments::new_v1(&[""], - &match (&"u8",) { - (arg0,) => - [::core::fmt::ArgumentV1::new(arg0, - ::core::fmt::Display::fmt)], - })); - res -}.as_str()` + let res = + ::alloc::fmt::format(::core::fmt::Arguments::new_v1(&[""], + &match (&"u8",) { + _args => + [::core::fmt::ArgumentV1::new(_args.0, + ::core::fmt::Display::fmt)], + })); + res + }.as_str()` --> $DIR/key-value-expansion.rs:48:23 | LL | doc_comment! {format!("{coor}", coor = stringify!($t1)).as_str()} diff --git a/src/test/ui/suffixed-literal-meta.rs b/src/test/ui/attributes/suffixed-literal-meta.rs similarity index 100% rename from src/test/ui/suffixed-literal-meta.rs rename to src/test/ui/attributes/suffixed-literal-meta.rs diff --git a/src/test/ui/suffixed-literal-meta.stderr b/src/test/ui/attributes/suffixed-literal-meta.stderr similarity index 100% rename from src/test/ui/suffixed-literal-meta.stderr rename to src/test/ui/attributes/suffixed-literal-meta.stderr diff --git a/src/test/ui/tool_attributes.rs b/src/test/ui/attributes/tool_attributes.rs similarity index 100% rename from src/test/ui/tool_attributes.rs rename to src/test/ui/attributes/tool_attributes.rs diff --git a/src/test/ui/unrestricted-attribute-tokens.rs b/src/test/ui/attributes/unrestricted-attribute-tokens.rs similarity index 100% rename from src/test/ui/unrestricted-attribute-tokens.rs rename to src/test/ui/attributes/unrestricted-attribute-tokens.rs diff --git a/src/test/ui/augmented-assignments-feature-gate.rs b/src/test/ui/augmented-assignments-feature-gate.rs deleted file mode 100644 index 8e686796fe..0000000000 --- a/src/test/ui/augmented-assignments-feature-gate.rs +++ /dev/null @@ -1,15 +0,0 @@ -// run-pass - -use std::ops::AddAssign; - -struct Int(i32); - -impl AddAssign<i32> for Int { - fn add_assign(&mut self, _: i32) { - } -} - -fn main() { - let mut x = Int(0); - x += 1; -} diff --git a/src/test/ui/binding/ambiguity-item.stderr b/src/test/ui/binding/ambiguity-item.stderr index 615193c0d0..f362013964 100644 --- a/src/test/ui/binding/ambiguity-item.stderr +++ b/src/test/ui/binding/ambiguity-item.stderr @@ -1,9 +1,10 @@ -error[E0659]: `f` is ambiguous (glob import vs glob import in the same module) +error[E0659]: `f` is ambiguous --> $DIR/ambiguity-item.rs:14:13 | LL | let v = f; | ^ ambiguous name | + = note: ambiguous because of multiple glob imports of a name in the same module note: `f` could refer to the function imported here --> $DIR/ambiguity-item.rs:6:5 | @@ -17,12 +18,13 @@ LL | use n::*; // OK, no conflict with `use m::*;` | ^^^^ = help: consider adding an explicit import of `f` to disambiguate -error[E0659]: `f` is ambiguous (glob import vs glob import in the same module) +error[E0659]: `f` is ambiguous --> $DIR/ambiguity-item.rs:16:9 | LL | f => {} | ^ ambiguous name | + = note: ambiguous because of multiple glob imports of a name in the same module note: `f` could refer to the function imported here --> $DIR/ambiguity-item.rs:6:5 | diff --git a/src/test/ui/operator-multidispatch.rs b/src/test/ui/binop/operator-multidispatch.rs similarity index 100% rename from src/test/ui/operator-multidispatch.rs rename to src/test/ui/binop/operator-multidispatch.rs diff --git a/src/test/ui/operator-overloading.rs b/src/test/ui/binop/operator-overloading.rs similarity index 100% rename from src/test/ui/operator-overloading.rs rename to src/test/ui/binop/operator-overloading.rs diff --git a/src/test/ui/placement-syntax.rs b/src/test/ui/binop/placement-syntax.rs similarity index 100% rename from src/test/ui/placement-syntax.rs rename to src/test/ui/binop/placement-syntax.rs diff --git a/src/test/ui/placement-syntax.stderr b/src/test/ui/binop/placement-syntax.stderr similarity index 100% rename from src/test/ui/placement-syntax.stderr rename to src/test/ui/binop/placement-syntax.stderr diff --git a/src/test/ui/shift-various-bad-types.rs b/src/test/ui/binop/shift-various-bad-types.rs similarity index 100% rename from src/test/ui/shift-various-bad-types.rs rename to src/test/ui/binop/shift-various-bad-types.rs diff --git a/src/test/ui/shift-various-bad-types.stderr b/src/test/ui/binop/shift-various-bad-types.stderr similarity index 100% rename from src/test/ui/shift-various-bad-types.stderr rename to src/test/ui/binop/shift-various-bad-types.stderr diff --git a/src/test/ui/structured-compare.rs b/src/test/ui/binop/structured-compare.rs similarity index 100% rename from src/test/ui/structured-compare.rs rename to src/test/ui/binop/structured-compare.rs diff --git a/src/test/ui/access-mode-in-closures.rs b/src/test/ui/borrowck/access-mode-in-closures.rs similarity index 100% rename from src/test/ui/access-mode-in-closures.rs rename to src/test/ui/borrowck/access-mode-in-closures.rs diff --git a/src/test/ui/access-mode-in-closures.stderr b/src/test/ui/borrowck/access-mode-in-closures.stderr similarity index 100% rename from src/test/ui/access-mode-in-closures.stderr rename to src/test/ui/borrowck/access-mode-in-closures.stderr diff --git a/src/test/ui/immut-function-arguments.rs b/src/test/ui/borrowck/immut-function-arguments.rs similarity index 100% rename from src/test/ui/immut-function-arguments.rs rename to src/test/ui/borrowck/immut-function-arguments.rs diff --git a/src/test/ui/immut-function-arguments.stderr b/src/test/ui/borrowck/immut-function-arguments.stderr similarity index 100% rename from src/test/ui/immut-function-arguments.stderr rename to src/test/ui/borrowck/immut-function-arguments.stderr diff --git a/src/test/ui/issues/issue-46095.rs b/src/test/ui/borrowck/issue-46095.rs similarity index 100% rename from src/test/ui/issues/issue-46095.rs rename to src/test/ui/borrowck/issue-46095.rs diff --git a/src/test/ui/borrowck/issue-80772.rs b/src/test/ui/borrowck/issue-80772.rs new file mode 100644 index 0000000000..1b8caa3f8a --- /dev/null +++ b/src/test/ui/borrowck/issue-80772.rs @@ -0,0 +1,21 @@ +// check-pass + +trait SomeTrait {} + +pub struct Exhibit { + constant: usize, + factory: fn(&usize) -> Box<dyn SomeTrait>, +} + +pub const A_CONSTANT: &[Exhibit] = &[ + Exhibit { + constant: 1, + factory: |_| unimplemented!(), + }, + Exhibit { + constant: "Hello world".len(), + factory: |_| unimplemented!(), + }, +]; + +fn main() {} diff --git a/src/test/ui/borrowck/issue-91206.rs b/src/test/ui/borrowck/issue-91206.rs new file mode 100644 index 0000000000..3b1fbf4b69 --- /dev/null +++ b/src/test/ui/borrowck/issue-91206.rs @@ -0,0 +1,15 @@ +struct TestClient; + +impl TestClient { + fn get_inner_ref(&self) -> &Vec<usize> { + todo!() + } +} + +fn main() { + let client = TestClient; + let inner = client.get_inner_ref(); + //~^ HELP consider changing this to be a mutable reference + inner.clear(); + //~^ ERROR cannot borrow `*inner` as mutable, as it is behind a `&` reference [E0596] +} diff --git a/src/test/ui/borrowck/issue-91206.stderr b/src/test/ui/borrowck/issue-91206.stderr new file mode 100644 index 0000000000..535d247452 --- /dev/null +++ b/src/test/ui/borrowck/issue-91206.stderr @@ -0,0 +1,12 @@ +error[E0596]: cannot borrow `*inner` as mutable, as it is behind a `&` reference + --> $DIR/issue-91206.rs:13:5 + | +LL | let inner = client.get_inner_ref(); + | ----- help: consider changing this to be a mutable reference: `&mut Vec<usize>` +LL | +LL | inner.clear(); + | ^^^^^^^^^^^^^ `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/kindck-implicit-close-over-mut-var.rs b/src/test/ui/borrowck/kindck-implicit-close-over-mut-var.rs similarity index 100% rename from src/test/ui/kindck-implicit-close-over-mut-var.rs rename to src/test/ui/borrowck/kindck-implicit-close-over-mut-var.rs diff --git a/src/test/ui/lazy-init.rs b/src/test/ui/borrowck/lazy-init.rs similarity index 100% rename from src/test/ui/lazy-init.rs rename to src/test/ui/borrowck/lazy-init.rs diff --git a/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr index 536fd43ef7..1e3b071ef9 100644 --- a/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr +++ b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr @@ -64,13 +64,13 @@ LL | fn wrong_bound2(self, b: Inv, c: Inv, d: Inv) { | ^ lifetimes do not match method in trait error[E0276]: impl has stricter requirements than trait - --> $DIR/regions-bound-missing-bound-in-impl.rs:49:5 + --> $DIR/regions-bound-missing-bound-in-impl.rs:49:26 | LL | fn another_bound<'x: 'a>(self, x: Inv<'x>, y: Inv<'t>); | ------------------------------------------------------- definition of `another_bound` from trait ... LL | fn another_bound<'x: 't>(self, x: Inv<'x>, y: Inv<'t>) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `'x: 't` + | ^^ impl has extra requirement `'x: 't` error: aborting due to 6 previous errors diff --git a/src/test/ui/borrowck/return-local-binding-from-desugaring.rs b/src/test/ui/borrowck/return-local-binding-from-desugaring.rs index b2dcd54ec2..c6643edf5a 100644 --- a/src/test/ui/borrowck/return-local-binding-from-desugaring.rs +++ b/src/test/ui/borrowck/return-local-binding-from-desugaring.rs @@ -27,7 +27,7 @@ where let key = f(x); result.entry(key).or_insert(Vec::new()).push(x); } - result //~ ERROR cannot return value referencing local binding + result //~ ERROR cannot return value referencing temporary value } fn main() {} diff --git a/src/test/ui/borrowck/return-local-binding-from-desugaring.stderr b/src/test/ui/borrowck/return-local-binding-from-desugaring.stderr index 293dbe6281..9f952542e1 100644 --- a/src/test/ui/borrowck/return-local-binding-from-desugaring.stderr +++ b/src/test/ui/borrowck/return-local-binding-from-desugaring.stderr @@ -1,8 +1,8 @@ -error[E0515]: cannot return value referencing local binding +error[E0515]: cannot return value referencing temporary value --> $DIR/return-local-binding-from-desugaring.rs:30:5 | LL | for ref x in xs { - | -- local binding introduced here + | -- temporary value created here ... LL | result | ^^^^^^ returns a value referencing data owned by the current function diff --git a/src/test/ui/box/into-boxed-slice-fail.stderr b/src/test/ui/box/into-boxed-slice-fail.stderr index 2f1dec9d20..de654fdc1a 100644 --- a/src/test/ui/box/into-boxed-slice-fail.stderr +++ b/src/test/ui/box/into-boxed-slice-fail.stderr @@ -7,11 +7,11 @@ LL | let _ = Box::into_boxed_slice(boxed_slice); | required by a bound introduced by this call | = help: the trait `Sized` is not implemented for `[u8]` -note: required by `Box::<T, A>::into_boxed_slice` +note: required by a bound in `Box::<T, A>::into_boxed_slice` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL | -LL | pub fn into_boxed_slice(boxed: Self) -> Box<[T], A> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl<T, A: Allocator> Box<T, A> { + | ^ required by this bound in `Box::<T, A>::into_boxed_slice` error[E0277]: the size for values of type `[u8]` cannot be known at compilation time --> $DIR/into-boxed-slice-fail.rs:7:13 @@ -31,11 +31,11 @@ LL | let _ = Box::into_boxed_slice(boxed_trait); | required by a bound introduced by this call | = help: the trait `Sized` is not implemented for `dyn Debug` -note: required by `Box::<T, A>::into_boxed_slice` +note: required by a bound in `Box::<T, A>::into_boxed_slice` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL | -LL | pub fn into_boxed_slice(boxed: Self) -> Box<[T], A> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl<T, A: Allocator> Box<T, A> { + | ^ required by this bound in `Box::<T, A>::into_boxed_slice` error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time --> $DIR/into-boxed-slice-fail.rs:11:13 diff --git a/src/test/ui/new-box-syntax.rs b/src/test/ui/box/new-box-syntax.rs similarity index 100% rename from src/test/ui/new-box-syntax.rs rename to src/test/ui/box/new-box-syntax.rs diff --git a/src/test/ui/new-box.rs b/src/test/ui/box/new-box.rs similarity index 100% rename from src/test/ui/new-box.rs rename to src/test/ui/box/new-box.rs diff --git a/src/test/ui/builtin-clone-unwind.rs b/src/test/ui/builtin-clone-unwind.rs index 339bcfa106..2caedb649a 100644 --- a/src/test/ui/builtin-clone-unwind.rs +++ b/src/test/ui/builtin-clone-unwind.rs @@ -53,7 +53,7 @@ fn main() { ].clone(); }); - assert!(result.is_err()); + assert!(child.is_err()); assert_eq!( 1, Rc::strong_count(&counter) diff --git a/src/test/ui/issues/issue-32201.rs b/src/test/ui/c-variadic/issue-32201.rs similarity index 100% rename from src/test/ui/issues/issue-32201.rs rename to src/test/ui/c-variadic/issue-32201.rs diff --git a/src/test/ui/issues/issue-32201.stderr b/src/test/ui/c-variadic/issue-32201.stderr similarity index 100% rename from src/test/ui/issues/issue-32201.stderr rename to src/test/ui/c-variadic/issue-32201.stderr diff --git a/src/test/ui/cast/casts-differing-anon.stderr b/src/test/ui/cast/casts-differing-anon.stderr index a30e9b35f5..f9abfb5225 100644 --- a/src/test/ui/cast/casts-differing-anon.stderr +++ b/src/test/ui/cast/casts-differing-anon.stderr @@ -1,4 +1,4 @@ -error[E0606]: casting `*mut impl Debug+?Sized` as `*mut impl Debug+?Sized` is invalid +error[E0606]: casting `*mut impl Debug + ?Sized` as `*mut impl Debug + ?Sized` is invalid --> $DIR/casts-differing-anon.rs:21:13 | LL | b_raw = f_raw as *mut _; diff --git a/src/test/ui/codegen-object-shim.rs b/src/test/ui/cast/codegen-object-shim.rs similarity index 100% rename from src/test/ui/codegen-object-shim.rs rename to src/test/ui/cast/codegen-object-shim.rs diff --git a/src/test/ui/supported-cast.rs b/src/test/ui/cast/supported-cast.rs similarity index 100% rename from src/test/ui/supported-cast.rs rename to src/test/ui/cast/supported-cast.rs diff --git a/src/test/ui/cfg/cfg-target-family.rs b/src/test/ui/cfg/cfg-target-family.rs index 90a59fab8e..5182cdc894 100644 --- a/src/test/ui/cfg/cfg-target-family.rs +++ b/src/test/ui/cfg/cfg-target-family.rs @@ -4,13 +4,10 @@ // pretty-expanded FIXME #23616 #[cfg(target_family = "windows")] -pub fn main() { -} +pub fn main() {} #[cfg(target_family = "unix")] -pub fn main() { -} +pub fn main() {} -#[cfg(target_family="wasm")] -pub fn main() { -} +#[cfg(all(target_family = "wasm", not(target_os = "emscripten")))] +pub fn main() {} diff --git a/src/test/ui/crt-static-off-works.rs b/src/test/ui/cfg/crt-static-off-works.rs similarity index 100% rename from src/test/ui/crt-static-off-works.rs rename to src/test/ui/cfg/crt-static-off-works.rs diff --git a/src/test/ui/crt-static-on-works.rs b/src/test/ui/cfg/crt-static-on-works.rs similarity index 100% rename from src/test/ui/crt-static-on-works.rs rename to src/test/ui/cfg/crt-static-on-works.rs diff --git a/src/test/ui/expanded-cfg.rs b/src/test/ui/cfg/expanded-cfg.rs similarity index 100% rename from src/test/ui/expanded-cfg.rs rename to src/test/ui/cfg/expanded-cfg.rs diff --git a/src/test/ui/chalkify/builtin-copy-clone.rs b/src/test/ui/chalkify/builtin-copy-clone.rs index d403514b55..4323e87b08 100644 --- a/src/test/ui/chalkify/builtin-copy-clone.rs +++ b/src/test/ui/chalkify/builtin-copy-clone.rs @@ -23,11 +23,12 @@ fn test_copy_clone<T: Copy + Clone>(arg: T) { fn foo() { } fn main() { + // FIXME: add closures when they're considered WF test_copy_clone(foo); let f: fn() = foo; test_copy_clone(f); - // FIXME: add closures when they're considered WF - test_copy_clone([1; 56]); + // FIXME(#86252): reinstate array test after chalk upgrade + //test_copy_clone([1; 56]); test_copy_clone((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)); test_copy_clone((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, true, 'a', 1.1)); test_copy_clone(()); diff --git a/src/test/ui/chalkify/type_wf.stderr b/src/test/ui/chalkify/type_wf.stderr index ebd885a7d3..57902efa20 100644 --- a/src/test/ui/chalkify/type_wf.stderr +++ b/src/test/ui/chalkify/type_wf.stderr @@ -7,11 +7,11 @@ LL | let s = S { = help: the following implementations were found: <Option<T> as Foo> <i32 as Foo> -note: required by `S` - --> $DIR/type_wf.rs:6:1 +note: required by a bound in `S` + --> $DIR/type_wf.rs:6:13 | LL | struct S<T: Foo> { - | ^^^^^^^^^^^^^^^^ + | ^^^ required by this bound in `S` error: aborting due to previous error diff --git a/src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.nll.stderr b/src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.nll.stderr index e7d9664ec5..af3810e91a 100644 --- a/src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.nll.stderr +++ b/src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.nll.stderr @@ -1,11 +1,18 @@ -error[E0621]: explicit lifetime required in the type of `x` +error[E0521]: borrowed data escapes outside of function --> $DIR/closure-bounds-static-cant-capture-borrowed.rs:5:5 | +LL | fn foo(x: &()) { + | - - let's call the lifetime of this reference `'1` + | | + | `x` is a reference that is only valid in the function body LL | / bar(|| { LL | | LL | | let _ = x; LL | | }) - | |______^ lifetime `'static` required + | | ^ + | | | + | |______`x` escapes the function body here + | argument requires that `'1` must outlive `'static` error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function --> $DIR/closure-bounds-static-cant-capture-borrowed.rs:5:9 @@ -31,5 +38,5 @@ LL | bar(move || { error: aborting due to 2 previous errors -Some errors have detailed explanations: E0373, E0621. +Some errors have detailed explanations: E0373, E0521. For more information about an error, try `rustc --explain E0373`. diff --git a/src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.rs b/src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.rs index 4fa5d54431..cbdc8b7dee 100644 --- a/src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.rs +++ b/src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.rs @@ -3,7 +3,7 @@ fn bar<F>(blk: F) where F: FnOnce() + 'static { fn foo(x: &()) { bar(|| { - //~^ ERROR explicit lifetime required in the type of `x` [E0621] + //~^ ERROR `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement [E0759] let _ = x; }) } diff --git a/src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr b/src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr index a9add6184f..d761abdfc6 100644 --- a/src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr +++ b/src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr @@ -1,9 +1,21 @@ -error[E0621]: explicit lifetime required in the type of `x` +error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/closure-bounds-static-cant-capture-borrowed.rs:5:9 + | +LL | fn foo(x: &()) { + | --- this data with an anonymous lifetime `'_`... +LL | bar(|| { + | _________^ +LL | | +LL | | let _ = x; +LL | | }) + | |_____^ ...is captured here... + | +note: ...and is required to live as long as `'static` here --> $DIR/closure-bounds-static-cant-capture-borrowed.rs:5:5 | LL | bar(|| { - | ^^^ lifetime `'static` required + | ^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0621`. +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/closure-expected.rs b/src/test/ui/closures/closure-expected.rs similarity index 100% rename from src/test/ui/closure-expected.rs rename to src/test/ui/closures/closure-expected.rs diff --git a/src/test/ui/closure-expected.stderr b/src/test/ui/closures/closure-expected.stderr similarity index 67% rename from src/test/ui/closure-expected.stderr rename to src/test/ui/closures/closure-expected.stderr index d4f2307804..8b38d5ff45 100644 --- a/src/test/ui/closure-expected.stderr +++ b/src/test/ui/closures/closure-expected.stderr @@ -8,6 +8,11 @@ LL | let y = x.or_else(4); | = help: the trait `FnOnce<()>` is not implemented for `{integer}` = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }` +note: required by a bound in `Option::<T>::or_else` + --> $SRC_DIR/core/src/option.rs:LL:COL + | +LL | pub fn or_else<F: FnOnce() -> Option<T>>(self, f: F) -> Option<T> { + | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Option::<T>::or_else` error: aborting due to previous error diff --git a/src/test/ui/closure_promotion.rs b/src/test/ui/closures/closure_promotion.rs similarity index 100% rename from src/test/ui/closure_promotion.rs rename to src/test/ui/closures/closure_promotion.rs diff --git a/src/test/ui/closures/coerce-unsafe-to-closure.stderr b/src/test/ui/closures/coerce-unsafe-to-closure.stderr index 4a47e05491..24db272534 100644 --- a/src/test/ui/closures/coerce-unsafe-to-closure.stderr +++ b/src/test/ui/closures/coerce-unsafe-to-closure.stderr @@ -7,6 +7,11 @@ LL | let x: Option<&[u8]> = Some("foo").map(std::mem::transmute); | required by a bound introduced by this call | = help: the trait `FnOnce<(&str,)>` is not implemented for `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` +note: required by a bound in `Option::<T>::map` + --> $SRC_DIR/core/src/option.rs:LL:COL + | +LL | pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> { + | ^^^^^^^^^^^^^^ required by this bound in `Option::<T>::map` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-10398.rs b/src/test/ui/closures/issue-10398.rs similarity index 100% rename from src/test/ui/issues/issue-10398.rs rename to src/test/ui/closures/issue-10398.rs diff --git a/src/test/ui/issues/issue-10398.stderr b/src/test/ui/closures/issue-10398.stderr similarity index 100% rename from src/test/ui/issues/issue-10398.stderr rename to src/test/ui/closures/issue-10398.stderr diff --git a/src/test/ui/issues/issue-42463.rs b/src/test/ui/closures/issue-42463.rs similarity index 100% rename from src/test/ui/issues/issue-42463.rs rename to src/test/ui/closures/issue-42463.rs diff --git a/src/test/ui/once-move-out-on-heap.rs b/src/test/ui/closures/once-move-out-on-heap.rs similarity index 100% rename from src/test/ui/once-move-out-on-heap.rs rename to src/test/ui/closures/once-move-out-on-heap.rs diff --git a/src/test/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr b/src/test/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr index d9479002b6..ee394d64a1 100644 --- a/src/test/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr +++ b/src/test/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr @@ -9,7 +9,7 @@ LL | let c1 : () = c; | expected due to this | = note: expected unit type `()` - found closure `[mod1::f<T>::{closure#0} closure_substs=(unavailable)]` + found closure `[mod1::f<T>::{closure#0} closure_substs=(unavailable) substs=[T, _#22t, extern "rust-call" fn(()), _#23t]]` help: use parentheses to call this closure | LL | let c1 : () = c(); diff --git a/src/test/ui/closures/print/closure-print-generic-verbose-2.stderr b/src/test/ui/closures/print/closure-print-generic-verbose-2.stderr index 880e38df2d..11b9fa7e40 100644 --- a/src/test/ui/closures/print/closure-print-generic-verbose-2.stderr +++ b/src/test/ui/closures/print/closure-print-generic-verbose-2.stderr @@ -9,7 +9,7 @@ LL | let c1 : () = c; | expected due to this | = note: expected unit type `()` - found closure `[f<T>::{closure#0} closure_substs=(unavailable)]` + found closure `[f<T>::{closure#0} closure_substs=(unavailable) substs=[T, _#22t, extern "rust-call" fn(()), _#23t]]` help: use parentheses to call this closure | LL | let c1 : () = c(); diff --git a/src/test/ui/closures/print/closure-print-verbose.stderr b/src/test/ui/closures/print/closure-print-verbose.stderr index d19b07acbf..083717b333 100644 --- a/src/test/ui/closures/print/closure-print-verbose.stderr +++ b/src/test/ui/closures/print/closure-print-verbose.stderr @@ -7,7 +7,7 @@ LL | let foo: fn(u8) -> u8 = |v: u8| { a += v; a }; | expected due to this | = note: expected fn pointer `fn(u8) -> u8` - found closure `[main::{closure#0} closure_substs=(unavailable)]` + found closure `[main::{closure#0} closure_substs=(unavailable) substs=[i8, extern "rust-call" fn((u8,)) -> u8, _#6t]]` note: closures can only be coerced to `fn` types if they do not capture any variables --> $DIR/closure-print-verbose.rs:10:39 | diff --git a/src/test/ui/semistatement-in-lambda.rs b/src/test/ui/closures/semistatement-in-lambda.rs similarity index 100% rename from src/test/ui/semistatement-in-lambda.rs rename to src/test/ui/closures/semistatement-in-lambda.rs diff --git a/src/test/ui/thir-unsafeck-issue-85871.rs b/src/test/ui/closures/thir-unsafeck-issue-85871.rs similarity index 100% rename from src/test/ui/thir-unsafeck-issue-85871.rs rename to src/test/ui/closures/thir-unsafeck-issue-85871.rs diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.rs b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.rs index 9697146d5c..d5c67af2b4 100644 --- a/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.rs +++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.rs @@ -1,7 +1,6 @@ // build-fail // compile-flags: --target thumbv8m.main-none-eabi --crate-type lib // needs-llvm-components: arm -// min-llvm-version: 11.0 #![feature(abi_c_cmse_nonsecure_call, no_core, lang_items, intrinsics)] #![no_core] #[lang="sized"] diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.stderr b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.stderr index c906418407..3723007878 100644 --- a/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.stderr +++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.stderr @@ -1,5 +1,4 @@ error: <unknown>:0:0: in function test i32 (i32, i32, i32, i32, i32): call to non-secure function would require passing arguments on stack - error: aborting due to previous error diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs index 74321fdfdd..9a1b0a38d5 100644 --- a/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs +++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs @@ -1,7 +1,6 @@ // build-fail // compile-flags: --target thumbv8m.main-none-eabi --crate-type lib // needs-llvm-components: arm -// min-llvm-version: 11.0 #![feature(cmse_nonsecure_entry, no_core, lang_items)] #![no_core] #[lang="sized"] diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.stderr b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.stderr index d9956acbe7..1054c26651 100644 --- a/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.stderr +++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.stderr @@ -1,5 +1,4 @@ error: <unknown>:0:0: in function entry_function i32 (i32, i32, i32, i32, i32): secure entry function requires arguments on stack - error: aborting due to previous error diff --git a/src/test/ui/auxiliary/llvm_pr32379.rs b/src/test/ui/codegen/auxiliary/llvm_pr32379.rs similarity index 100% rename from src/test/ui/auxiliary/llvm_pr32379.rs rename to src/test/ui/codegen/auxiliary/llvm_pr32379.rs diff --git a/src/test/ui/init-large-type.rs b/src/test/ui/codegen/init-large-type.rs similarity index 100% rename from src/test/ui/init-large-type.rs rename to src/test/ui/codegen/init-large-type.rs diff --git a/src/test/ui/llvm-pr32379.rs b/src/test/ui/codegen/llvm-pr32379.rs similarity index 100% rename from src/test/ui/llvm-pr32379.rs rename to src/test/ui/codegen/llvm-pr32379.rs diff --git a/src/test/ui/issues/auxiliary/issue-39823.rs b/src/test/ui/coercion/auxiliary/issue-39823.rs similarity index 100% rename from src/test/ui/issues/auxiliary/issue-39823.rs rename to src/test/ui/coercion/auxiliary/issue-39823.rs diff --git a/src/test/ui/issues/issue-14589.rs b/src/test/ui/coercion/issue-14589.rs similarity index 100% rename from src/test/ui/issues/issue-14589.rs rename to src/test/ui/coercion/issue-14589.rs diff --git a/src/test/ui/issues/issue-39823.rs b/src/test/ui/coercion/issue-39823.rs similarity index 100% rename from src/test/ui/issues/issue-39823.rs rename to src/test/ui/coercion/issue-39823.rs diff --git a/src/test/ui/issues/issue-73886.rs b/src/test/ui/coercion/issue-73886.rs similarity index 100% rename from src/test/ui/issues/issue-73886.rs rename to src/test/ui/coercion/issue-73886.rs diff --git a/src/test/ui/issues/issue-73886.stderr b/src/test/ui/coercion/issue-73886.stderr similarity index 100% rename from src/test/ui/issues/issue-73886.stderr rename to src/test/ui/coercion/issue-73886.stderr diff --git a/src/test/ui/retslot-cast.rs b/src/test/ui/coercion/retslot-cast.rs similarity index 100% rename from src/test/ui/retslot-cast.rs rename to src/test/ui/coercion/retslot-cast.rs diff --git a/src/test/ui/retslot-cast.stderr b/src/test/ui/coercion/retslot-cast.stderr similarity index 100% rename from src/test/ui/retslot-cast.stderr rename to src/test/ui/coercion/retslot-cast.stderr diff --git a/src/test/ui/unsafe-coercion.rs b/src/test/ui/coercion/unsafe-coercion.rs similarity index 100% rename from src/test/ui/unsafe-coercion.rs rename to src/test/ui/coercion/unsafe-coercion.rs diff --git a/src/test/ui/coherence/auxiliary/error_lib.rs b/src/test/ui/coherence/auxiliary/error_lib.rs new file mode 100644 index 0000000000..43806cb995 --- /dev/null +++ b/src/test/ui/coherence/auxiliary/error_lib.rs @@ -0,0 +1,5 @@ +#![crate_type = "lib"] +#![feature(negative_impls)] + +pub trait Error {} +impl !Error for &str {} diff --git a/src/test/ui/coherence/coherence-cross-crate-conflict.rs b/src/test/ui/coherence/coherence-cross-crate-conflict.rs index 648e290a4b..588630957c 100644 --- a/src/test/ui/coherence/coherence-cross-crate-conflict.rs +++ b/src/test/ui/coherence/coherence-cross-crate-conflict.rs @@ -6,9 +6,7 @@ extern crate trait_impl_conflict; use trait_impl_conflict::Foo; -impl<A> Foo for A { - //~^ ERROR E0119 - //~| ERROR E0210 +impl<A> Foo for A { //~ ERROR E0210 } fn main() { diff --git a/src/test/ui/coherence/coherence-cross-crate-conflict.stderr b/src/test/ui/coherence/coherence-cross-crate-conflict.stderr index d0d86c72ff..3d253d56a4 100644 --- a/src/test/ui/coherence/coherence-cross-crate-conflict.stderr +++ b/src/test/ui/coherence/coherence-cross-crate-conflict.stderr @@ -1,12 +1,3 @@ -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 { - | ^^^^^^^^^^^^^^^^^ - | - = note: conflicting implementation in crate `trait_impl_conflict`: - - impl Foo for isize; - error[E0210]: type parameter `A` must be used as the type parameter for some local type (e.g., `MyStruct<A>`) --> $DIR/coherence-cross-crate-conflict.rs:9:6 | @@ -16,7 +7,6 @@ LL | impl<A> Foo for A { = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local = note: only traits defined in the current crate can be implemented for a type parameter -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0119, E0210. -For more information about an error, try `rustc --explain E0119`. +For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr index c364c707ff..9128914807 100644 --- a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr +++ b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr @@ -1,15 +1,3 @@ -error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1` - --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1 - | -LL | impl !Marker1 for dyn Object + Marker2 { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1` - -error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2` - --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:17:1 - | -LL | impl !Marker2 for dyn Object + Marker2 { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2` - error[E0117]: only traits defined in the current crate can be implemented for arbitrary types --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:23:1 | @@ -33,6 +21,18 @@ error[E0321]: cross-crate traits with a default impl, like `Send`, can only be i LL | impl !Send for dyn Object + Marker2 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type +error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1` + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1 + | +LL | impl !Marker1 for dyn Object + Marker2 { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1` + +error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2` + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:17:1 + | +LL | impl !Marker2 for dyn Object + Marker2 { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2` + error: aborting due to 5 previous errors Some errors have detailed explanations: E0117, E0321, E0371. diff --git a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr index b80429794f..056198374a 100644 --- a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr +++ b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr @@ -1,15 +1,3 @@ -error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1` - --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:15:1 - | -LL | impl Marker1 for dyn Object + Marker2 { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1` - -error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2` - --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:17:1 - | -LL | impl Marker2 for dyn Object + Marker2 { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2` - error[E0117]: only traits defined in the current crate can be implemented for arbitrary types --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:23:1 | @@ -33,6 +21,18 @@ error[E0321]: cross-crate traits with a default impl, like `Send`, can only be i LL | unsafe impl Send for dyn Object + Marker2 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type +error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1` + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:15:1 + | +LL | impl Marker1 for dyn Object + Marker2 { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1` + +error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2` + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:17:1 + | +LL | impl Marker2 for dyn Object + Marker2 { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2` + error: aborting due to 5 previous errors Some errors have detailed explanations: E0117, E0321, E0371. diff --git a/src/test/ui/coherence/coherence-impls-copy.rs b/src/test/ui/coherence/coherence-impls-copy.rs index a86ca0e5ea..4204fecc37 100644 --- a/src/test/ui/coherence/coherence-impls-copy.rs +++ b/src/test/ui/coherence/coherence-impls-copy.rs @@ -3,8 +3,7 @@ use std::marker::Copy; impl Copy for i32 {} -//~^ ERROR E0119 -//~| ERROR E0117 +//~^ ERROR E0117 enum TestE { A } @@ -32,7 +31,6 @@ impl Copy for [MyType] {} //~^ ERROR E0206 //~| ERROR E0117 impl Copy for &'static [NotSync] {} -//~^ ERROR E0119 -//~| ERROR E0117 +//~^ ERROR E0117 fn main() { } diff --git a/src/test/ui/coherence/coherence-impls-copy.stderr b/src/test/ui/coherence/coherence-impls-copy.stderr index 2ac0706d72..a7d6968a29 100644 --- a/src/test/ui/coherence/coherence-impls-copy.stderr +++ b/src/test/ui/coherence/coherence-impls-copy.stderr @@ -1,50 +1,3 @@ -error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `i32` - --> $DIR/coherence-impls-copy.rs:5:1 - | -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` - --> $DIR/coherence-impls-copy.rs:29:1 - | -LL | impl Copy for &'static NotSync {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: conflicting implementation in crate `core`: - - impl<T> Copy for &T - where T: ?Sized; - -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] {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: conflicting implementation in crate `core`: - - impl<T> Copy for &T - where T: ?Sized; - -error[E0206]: the trait `Copy` may not be implemented for this type - --> $DIR/coherence-impls-copy.rs:22:15 - | -LL | impl Copy for &'static mut MyType {} - | ^^^^^^^^^^^^^^^^^^^ type is not a structure or enumeration - -error[E0206]: the trait `Copy` may not be implemented for this type - --> $DIR/coherence-impls-copy.rs:26:15 - | -LL | impl Copy for (MyType, MyType) {} - | ^^^^^^^^^^^^^^^^ type is not a structure or enumeration - -error[E0206]: the trait `Copy` may not be implemented for this type - --> $DIR/coherence-impls-copy.rs:31:15 - | -LL | impl Copy for [MyType] {} - | ^^^^^^^^ type is not a structure or enumeration - error[E0117]: only traits defined in the current crate can be implemented for arbitrary types --> $DIR/coherence-impls-copy.rs:5:1 | @@ -57,7 +10,7 @@ LL | impl Copy for i32 {} = note: define and implement a trait or new type instead error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/coherence-impls-copy.rs:26:1 + --> $DIR/coherence-impls-copy.rs:25:1 | LL | impl Copy for (MyType, MyType) {} | ^^^^^^^^^^^^^^---------------- @@ -68,7 +21,7 @@ LL | impl Copy for (MyType, MyType) {} = note: define and implement a trait or new type instead error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/coherence-impls-copy.rs:31:1 + --> $DIR/coherence-impls-copy.rs:30:1 | LL | impl Copy for [MyType] {} | ^^^^^^^^^^^^^^-------- @@ -79,7 +32,7 @@ LL | impl Copy for [MyType] {} = note: define and implement a trait or new type instead error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/coherence-impls-copy.rs:34:1 + --> $DIR/coherence-impls-copy.rs:33:1 | LL | impl Copy for &'static [NotSync] {} | ^^^^^^^^^^^^^^------------------ @@ -89,7 +42,35 @@ LL | impl Copy for &'static [NotSync] {} | = note: define and implement a trait or new type instead -error: aborting due to 10 previous errors +error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `&NotSync` + --> $DIR/coherence-impls-copy.rs:28:1 + | +LL | impl Copy for &'static NotSync {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: conflicting implementation in crate `core`: + - impl<T> Copy for &T + where T: ?Sized; + +error[E0206]: the trait `Copy` may not be implemented for this type + --> $DIR/coherence-impls-copy.rs:21:15 + | +LL | impl Copy for &'static mut MyType {} + | ^^^^^^^^^^^^^^^^^^^ type is not a structure or enumeration + +error[E0206]: the trait `Copy` may not be implemented for this type + --> $DIR/coherence-impls-copy.rs:25:15 + | +LL | impl Copy for (MyType, MyType) {} + | ^^^^^^^^^^^^^^^^ type is not a structure or enumeration + +error[E0206]: the trait `Copy` may not be implemented for this type + --> $DIR/coherence-impls-copy.rs:30:15 + | +LL | impl Copy for [MyType] {} + | ^^^^^^^^ type is not a structure or enumeration + +error: aborting due to 8 previous errors Some errors have detailed explanations: E0117, E0119, E0206. For more information about an error, try `rustc --explain E0117`. diff --git a/src/test/ui/coherence/coherence-impls-send.rs b/src/test/ui/coherence/coherence-impls-send.rs index e00cb9a7c5..b7b57c602b 100644 --- a/src/test/ui/coherence/coherence-impls-send.rs +++ b/src/test/ui/coherence/coherence-impls-send.rs @@ -23,7 +23,6 @@ unsafe impl Send for [MyType] {} //~^ ERROR E0117 unsafe impl Send for &'static [NotSync] {} -//~^ ERROR conflicting implementations of trait -//~| ERROR only traits defined in the current crate +//~^ ERROR only traits defined in the current crate fn main() {} diff --git a/src/test/ui/coherence/coherence-impls-send.stderr b/src/test/ui/coherence/coherence-impls-send.stderr index 46e9e7e986..dd1fd1b0dc 100644 --- a/src/test/ui/coherence/coherence-impls-send.stderr +++ b/src/test/ui/coherence/coherence-impls-send.stderr @@ -1,14 +1,3 @@ -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] {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: conflicting implementation in crate `core`: - - impl<T> Send for &T - where T: Sync, T: ?Sized; - = note: upstream crates may add a new impl of trait `std::marker::Sync` for type `[NotSync]` in future versions - error[E0117]: only traits defined in the current crate can be implemented for arbitrary types --> $DIR/coherence-impls-send.rs:16:1 | @@ -48,7 +37,7 @@ LL | unsafe impl Send for &'static [NotSync] {} | = note: define and implement a trait or new type instead -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0117, E0119, E0321. +Some errors have detailed explanations: E0117, E0321. For more information about an error, try `rustc --explain E0117`. diff --git a/src/test/ui/coherence/coherence-impls-sized.stderr b/src/test/ui/coherence/coherence-impls-sized.stderr index 3b0a9fc60a..9cf5ed38c9 100644 --- a/src/test/ui/coherence/coherence-impls-sized.stderr +++ b/src/test/ui/coherence/coherence-impls-sized.stderr @@ -1,3 +1,36 @@ +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence-impls-sized.rs:20:1 + | +LL | impl Sized for (MyType, MyType) {} + | ^^^^^^^^^^^^^^^---------------- + | | | + | | this is not defined in the current crate because tuples are always foreign + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence-impls-sized.rs:27:1 + | +LL | impl Sized for [MyType] {} + | ^^^^^^^^^^^^^^^-------- + | | | + | | this is not defined in the current crate because slices are always foreign + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence-impls-sized.rs:31:1 + | +LL | impl Sized for &'static [NotSync] {} + | ^^^^^^^^^^^^^^^------------------ + | | | + | | this is not defined in the current crate because slices are always foreign + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + error[E0322]: explicit impls for the `Sized` trait are not permitted --> $DIR/coherence-impls-sized.rs:14:1 | @@ -34,39 +67,6 @@ error[E0322]: explicit impls for the `Sized` trait are not permitted LL | impl Sized for &'static [NotSync] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of 'Sized' not allowed -error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/coherence-impls-sized.rs:20:1 - | -LL | impl Sized for (MyType, MyType) {} - | ^^^^^^^^^^^^^^^---------------- - | | | - | | this is not defined in the current crate because tuples are always foreign - | impl doesn't use only types from inside the current crate - | - = note: define and implement a trait or new type instead - -error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/coherence-impls-sized.rs:27:1 - | -LL | impl Sized for [MyType] {} - | ^^^^^^^^^^^^^^^-------- - | | | - | | this is not defined in the current crate because slices are always foreign - | impl doesn't use only types from inside the current crate - | - = note: define and implement a trait or new type instead - -error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/coherence-impls-sized.rs:31:1 - | -LL | impl Sized for &'static [NotSync] {} - | ^^^^^^^^^^^^^^^------------------ - | | | - | | this is not defined in the current crate because slices are always foreign - | impl doesn't use only types from inside the current crate - | - = note: define and implement a trait or new type instead - error: aborting due to 9 previous errors Some errors have detailed explanations: E0117, E0322. diff --git a/src/test/ui/coherence/coherence-orphan.stderr b/src/test/ui/coherence/coherence-orphan.stderr index 52d2cc88cb..051a519ee1 100644 --- a/src/test/ui/coherence/coherence-orphan.stderr +++ b/src/test/ui/coherence/coherence-orphan.stderr @@ -1,22 +1,22 @@ error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/coherence-orphan.rs:10:1 + --> $DIR/coherence-orphan.rs:17:1 | -LL | impl TheTrait<usize> for isize { } - | ^^^^^---------------^^^^^----- - | | | | - | | | `isize` is not defined in the current crate - | | `usize` is not defined in the current crate +LL | impl !Send for Vec<isize> { } + | ^^^^^^^^^^^^^^^---------- + | | | + | | `Vec` is not defined in the current crate | impl doesn't use only types from inside the current crate | = note: define and implement a trait or new type instead error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/coherence-orphan.rs:17:1 + --> $DIR/coherence-orphan.rs:10:1 | -LL | impl !Send for Vec<isize> { } - | ^^^^^^^^^^^^^^^---------- - | | | - | | `Vec` is not defined in the current crate +LL | impl TheTrait<usize> for isize { } + | ^^^^^---------------^^^^^----- + | | | | + | | | `isize` is not defined in the current crate + | | `usize` is not defined in the current crate | impl doesn't use only types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/src/test/ui/coherence/coherence-overlap-negate-alias-strict.rs b/src/test/ui/coherence/coherence-overlap-negate-alias-strict.rs new file mode 100644 index 0000000000..16ace450b0 --- /dev/null +++ b/src/test/ui/coherence/coherence-overlap-negate-alias-strict.rs @@ -0,0 +1,19 @@ +#![feature(negative_impls)] +#![feature(rustc_attrs)] +#![feature(trait_alias)] + +trait A {} +trait B {} +trait AB = A + B; + +impl !A for u32 {} + +trait C {} +#[rustc_strict_coherence] +impl<T: AB> C for T {} +#[rustc_strict_coherence] +impl C for u32 {} +//~^ ERROR: conflicting implementations of trait `C` for type `u32` [E0119] +// FIXME this should work, we should implement an `assemble_neg_candidates` fn + +fn main() {} diff --git a/src/test/ui/coherence/coherence-overlap-negate-alias-strict.stderr b/src/test/ui/coherence/coherence-overlap-negate-alias-strict.stderr new file mode 100644 index 0000000000..5e43622311 --- /dev/null +++ b/src/test/ui/coherence/coherence-overlap-negate-alias-strict.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `C` for type `u32` + --> $DIR/coherence-overlap-negate-alias-strict.rs:15:1 + | +LL | impl<T: AB> C for T {} + | ------------------- first implementation here +LL | #[rustc_strict_coherence] +LL | impl C for u32 {} + | ^^^^^^^^^^^^^^ conflicting implementation for `u32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/coherence/coherence-overlap-negate-not-use-feature-gate.rs b/src/test/ui/coherence/coherence-overlap-negate-not-use-feature-gate.rs new file mode 100644 index 0000000000..a067736f63 --- /dev/null +++ b/src/test/ui/coherence/coherence-overlap-negate-not-use-feature-gate.rs @@ -0,0 +1,8 @@ +use std::ops::DerefMut; + +trait Foo {} +impl<T: DerefMut> Foo for T {} +impl<U> Foo for &U {} +//~^ ERROR: conflicting implementations of trait `Foo` for type `&_` [E0119] + +fn main() {} diff --git a/src/test/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr b/src/test/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr new file mode 100644 index 0000000000..4b55001ecc --- /dev/null +++ b/src/test/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr @@ -0,0 +1,11 @@ +error[E0119]: conflicting implementations of trait `Foo` for type `&_` + --> $DIR/coherence-overlap-negate-not-use-feature-gate.rs:5:1 + | +LL | impl<T: DerefMut> Foo for T {} + | --------------------------- first implementation here +LL | impl<U> Foo for &U {} + | ^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/coherence/coherence-overlap-negate-strict.rs b/src/test/ui/coherence/coherence-overlap-negate-strict.rs new file mode 100644 index 0000000000..b3ae9a7bf7 --- /dev/null +++ b/src/test/ui/coherence/coherence-overlap-negate-strict.rs @@ -0,0 +1,18 @@ +// check-pass + +#![feature(negative_impls)] +#![feature(rustc_attrs)] +#![feature(trait_alias)] + +trait A {} +trait B {} + +impl !A for u32 {} + +trait C {} +#[rustc_strict_coherence] +impl<T: A + B> C for T {} +#[rustc_strict_coherence] +impl C for u32 {} + +fn main() {} diff --git a/src/test/ui/coherence/coherence-overlap-negate-use-feature-gate.rs b/src/test/ui/coherence/coherence-overlap-negate-use-feature-gate.rs new file mode 100644 index 0000000000..e024eae981 --- /dev/null +++ b/src/test/ui/coherence/coherence-overlap-negate-use-feature-gate.rs @@ -0,0 +1,11 @@ +// check-pass + +#![feature(negative_impls)] + +use std::ops::DerefMut; + +trait Foo {} +impl<T: DerefMut> Foo for T {} +impl<U> Foo for &U {} + +fn main() {} diff --git a/src/test/ui/coherence/coherence-overlap-negative-trait.rs b/src/test/ui/coherence/coherence-overlap-negative-trait.rs new file mode 100644 index 0000000000..ab65163bea --- /dev/null +++ b/src/test/ui/coherence/coherence-overlap-negative-trait.rs @@ -0,0 +1,16 @@ +// check-pass +// aux-build:error_lib.rs +// +// Check that if we promise to not impl what would overlap it doesn't actually overlap + +#![feature(negative_impls)] + +extern crate error_lib as lib; +use lib::Error; + +trait From<T> {} + +impl From<&str> for Box<dyn Error> {} +impl<E> From<E> for Box<dyn Error> where E: Error {} + +fn main() {} diff --git a/src/test/ui/coherence/coherence-overlap-trait-alias.rs b/src/test/ui/coherence/coherence-overlap-trait-alias.rs new file mode 100644 index 0000000000..45b2f08630 --- /dev/null +++ b/src/test/ui/coherence/coherence-overlap-trait-alias.rs @@ -0,0 +1,20 @@ +#![feature(rustc_attrs)] +#![feature(trait_alias)] + +trait A {} +trait B {} +trait AB = A + B; + +impl A for u32 {} +impl B for u32 {} + +trait C {} +#[rustc_strict_coherence] +impl<T: AB> C for T {} +#[rustc_strict_coherence] +impl C for u32 {} +//~^ ERROR +// FIXME it's giving an ungreat error but unsure if we care given that it's using an internal rustc +// attribute and an artificial code path for testing purposes + +fn main() {} diff --git a/src/test/ui/coherence/coherence-overlap-trait-alias.stderr b/src/test/ui/coherence/coherence-overlap-trait-alias.stderr new file mode 100644 index 0000000000..5b389f24bf --- /dev/null +++ b/src/test/ui/coherence/coherence-overlap-trait-alias.stderr @@ -0,0 +1,18 @@ +error[E0283]: type annotations needed + --> $DIR/coherence-overlap-trait-alias.rs:15:6 + | +LL | impl C for u32 {} + | ^ cannot infer type for type `u32` + | +note: multiple `impl`s satisfying `u32: C` found + --> $DIR/coherence-overlap-trait-alias.rs:13:1 + | +LL | impl<T: AB> C for T {} + | ^^^^^^^^^^^^^^^^^^^ +LL | #[rustc_strict_coherence] +LL | impl C for u32 {} + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/src/test/ui/compare-method/issue-90444.rs b/src/test/ui/compare-method/issue-90444.rs new file mode 100644 index 0000000000..6c287d9a70 --- /dev/null +++ b/src/test/ui/compare-method/issue-90444.rs @@ -0,0 +1,17 @@ +pub struct A; +impl From<fn((), (), &())> for A { + fn from(_: fn((), (), &mut ())) -> Self { + //~^ error: method `from` has an incompatible type for trait + loop {} + } +} + +pub struct B; +impl From<fn((), (), u32)> for B { + fn from(_: fn((), (), u64)) -> Self { + //~^ error: method `from` has an incompatible type for trait + loop {} + } +} + +fn main() {} diff --git a/src/test/ui/compare-method/issue-90444.stderr b/src/test/ui/compare-method/issue-90444.stderr new file mode 100644 index 0000000000..84bbec0623 --- /dev/null +++ b/src/test/ui/compare-method/issue-90444.stderr @@ -0,0 +1,27 @@ +error[E0053]: method `from` has an incompatible type for trait + --> $DIR/issue-90444.rs:3:16 + | +LL | fn from(_: fn((), (), &mut ())) -> Self { + | ^^^^^^^^^^^^^^^^^^^ + | | + | types differ in mutability + | help: change the parameter type to match the trait: `for<'r> fn((), (), &'r ())` + | + = note: expected fn pointer `fn(for<'r> fn((), (), &'r ())) -> A` + found fn pointer `fn(for<'r> fn((), (), &'r mut ())) -> A` + +error[E0053]: method `from` has an incompatible type for trait + --> $DIR/issue-90444.rs:11:16 + | +LL | fn from(_: fn((), (), u64)) -> Self { + | ^^^^^^^^^^^^^^^ + | | + | expected `u32`, found `u64` + | help: change the parameter type to match the trait: `fn((), (), u32)` + | + = note: expected fn pointer `fn(fn((), (), u32)) -> B` + found fn pointer `fn(fn((), (), u64)) -> B` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0053`. diff --git a/src/test/ui/compare-method/proj-outlives-region.stderr b/src/test/ui/compare-method/proj-outlives-region.stderr index e5f5c5ed20..797a816793 100644 --- a/src/test/ui/compare-method/proj-outlives-region.stderr +++ b/src/test/ui/compare-method/proj-outlives-region.stderr @@ -1,11 +1,11 @@ error[E0276]: impl has stricter requirements than trait - --> $DIR/proj-outlives-region.rs:9:5 + --> $DIR/proj-outlives-region.rs:9:23 | LL | fn foo() where T: 'a; | --------------------- definition of `foo` from trait ... LL | fn foo() where U: 'a { } - | ^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `U: 'a` + | ^^ impl has extra requirement `U: 'a` error: aborting due to previous error diff --git a/src/test/ui/compare-method/region-extra-2.stderr b/src/test/ui/compare-method/region-extra-2.stderr index 420d99c15e..f01d7f4710 100644 --- a/src/test/ui/compare-method/region-extra-2.stderr +++ b/src/test/ui/compare-method/region-extra-2.stderr @@ -1,11 +1,11 @@ error[E0276]: impl has stricter requirements than trait - --> $DIR/region-extra-2.rs:9:5 + --> $DIR/region-extra-2.rs:9:53 | LL | fn renew<'b: 'a>(self) -> &'b mut [T]; | -------------------------------------- definition of `renew` from trait ... LL | fn renew<'b: 'a>(self) -> &'b mut [T] where 'a: 'b { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `'a: 'b` + | ^^ impl has extra requirement `'a: 'b` error: aborting due to previous error diff --git a/src/test/ui/compare-method/region-extra.stderr b/src/test/ui/compare-method/region-extra.stderr index 5a584c7d6e..4a3af65e90 100644 --- a/src/test/ui/compare-method/region-extra.stderr +++ b/src/test/ui/compare-method/region-extra.stderr @@ -1,11 +1,11 @@ error[E0276]: impl has stricter requirements than trait - --> $DIR/region-extra.rs:9:5 + --> $DIR/region-extra.rs:9:24 | LL | fn foo(); | --------- definition of `foo` from trait ... LL | fn foo() where 'a: 'b { } - | ^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `'a: 'b` + | ^^ impl has extra requirement `'a: 'b` error: aborting due to previous error diff --git a/src/test/ui/compare-method/region-unrelated.stderr b/src/test/ui/compare-method/region-unrelated.stderr index fd3576ddcf..f7ae6f9443 100644 --- a/src/test/ui/compare-method/region-unrelated.stderr +++ b/src/test/ui/compare-method/region-unrelated.stderr @@ -1,11 +1,11 @@ error[E0276]: impl has stricter requirements than trait - --> $DIR/region-unrelated.rs:9:5 + --> $DIR/region-unrelated.rs:9:23 | LL | fn foo() where T: 'a; | --------------------- definition of `foo` from trait ... LL | fn foo() where V: 'a { } - | ^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `V: 'a` + | ^^ impl has extra requirement `V: 'a` error: aborting due to previous error diff --git a/src/test/ui/compare-method/trait-bound-on-type-parameter.stderr b/src/test/ui/compare-method/trait-bound-on-type-parameter.stderr index 83a2ae6068..ce6885c154 100644 --- a/src/test/ui/compare-method/trait-bound-on-type-parameter.stderr +++ b/src/test/ui/compare-method/trait-bound-on-type-parameter.stderr @@ -1,11 +1,11 @@ error[E0276]: impl has stricter requirements than trait - --> $DIR/trait-bound-on-type-parameter.rs:15:5 + --> $DIR/trait-bound-on-type-parameter.rs:15:13 | LL | fn b<C,D>(&self, x: C) -> C; | ---------------------------- definition of `b` from trait ... LL | fn b<F: Sync, G>(&self, _x: F) -> F { panic!() } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `F: Sync` + | ^^^^ impl has extra requirement `F: Sync` error: aborting due to previous error diff --git a/src/test/ui/compare-method/traits-misc-mismatch-1.stderr b/src/test/ui/compare-method/traits-misc-mismatch-1.stderr index da94fc6584..805c04536c 100644 --- a/src/test/ui/compare-method/traits-misc-mismatch-1.stderr +++ b/src/test/ui/compare-method/traits-misc-mismatch-1.stderr @@ -1,65 +1,65 @@ error[E0276]: impl has stricter requirements than trait - --> $DIR/traits-misc-mismatch-1.rs:27:5 + --> $DIR/traits-misc-mismatch-1.rs:27:26 | LL | fn test_error1_fn<T: Eq>(&self); | -------------------------------- definition of `test_error1_fn` from trait ... LL | fn test_error1_fn<T: Ord>(&self) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: Ord` + | ^^^ impl has extra requirement `T: Ord` error[E0276]: impl has stricter requirements than trait - --> $DIR/traits-misc-mismatch-1.rs:31:5 + --> $DIR/traits-misc-mismatch-1.rs:31:31 | LL | fn test_error2_fn<T: Eq + Ord>(&self); | -------------------------------------- definition of `test_error2_fn` from trait ... LL | fn test_error2_fn<T: Eq + B>(&self) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: B` + | ^ impl has extra requirement `T: B` error[E0276]: impl has stricter requirements than trait - --> $DIR/traits-misc-mismatch-1.rs:35:5 + --> $DIR/traits-misc-mismatch-1.rs:35:26 | LL | fn test_error3_fn<T: Eq + Ord>(&self); | -------------------------------------- definition of `test_error3_fn` from trait ... LL | fn test_error3_fn<T: B + Eq>(&self) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: B` + | ^ impl has extra requirement `T: B` error[E0276]: impl has stricter requirements than trait - --> $DIR/traits-misc-mismatch-1.rs:45:5 + --> $DIR/traits-misc-mismatch-1.rs:45:26 | LL | fn test_error5_fn<T: A>(&self); | ------------------------------- definition of `test_error5_fn` from trait ... LL | fn test_error5_fn<T: B>(&self) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: B` + | ^ impl has extra requirement `T: B` error[E0276]: impl has stricter requirements than trait - --> $DIR/traits-misc-mismatch-1.rs:51:5 + --> $DIR/traits-misc-mismatch-1.rs:51:30 | LL | fn test_error7_fn<T: A>(&self); | ------------------------------- definition of `test_error7_fn` from trait ... LL | fn test_error7_fn<T: A + Eq>(&self) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: Eq` + | ^^ impl has extra requirement `T: Eq` error[E0276]: impl has stricter requirements than trait - --> $DIR/traits-misc-mismatch-1.rs:54:5 + --> $DIR/traits-misc-mismatch-1.rs:54:26 | LL | fn test_error8_fn<T: B>(&self); | ------------------------------- definition of `test_error8_fn` from trait ... LL | fn test_error8_fn<T: C>(&self) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: C` + | ^ impl has extra requirement `T: C` error[E0276]: impl has stricter requirements than trait - --> $DIR/traits-misc-mismatch-1.rs:67:5 + --> $DIR/traits-misc-mismatch-1.rs:67:18 | LL | fn method<G:Getter<isize>>(&self); | ---------------------------------- definition of `method` from trait ... LL | fn method<G: Getter<usize>>(&self) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `G: Getter<usize>` + | ^^^^^^^^^^^^^ impl has extra requirement `G: Getter<usize>` error: aborting due to 7 previous errors diff --git a/src/test/ui/compare-method/traits-misc-mismatch-2.stderr b/src/test/ui/compare-method/traits-misc-mismatch-2.stderr index acf94ad32b..36bb764d40 100644 --- a/src/test/ui/compare-method/traits-misc-mismatch-2.stderr +++ b/src/test/ui/compare-method/traits-misc-mismatch-2.stderr @@ -1,11 +1,11 @@ error[E0276]: impl has stricter requirements than trait - --> $DIR/traits-misc-mismatch-2.rs:13:5 + --> $DIR/traits-misc-mismatch-2.rs:13:18 | LL | fn zip<B, U: Iterator<U>>(self, other: U) -> ZipIterator<Self, U>; | ------------------------------------------------------------------ definition of `zip` from trait ... LL | fn zip<B, U: Iterator<B>>(self, other: U) -> ZipIterator<T, U> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `U: Iterator<B>` + | ^^^^^^^^^^^ impl has extra requirement `U: Iterator<B>` error: aborting due to previous error diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-7.rs b/src/test/ui/conditional-compilation/cfg-arg-invalid-7.rs new file mode 100644 index 0000000000..149142f63a --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-7.rs @@ -0,0 +1,5 @@ +// Regression test for issue #89358. + +// compile-flags: --cfg a" +// error-pattern: unterminated double quote string +// error-pattern: this error occurred on the command line diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-7.stderr b/src/test/ui/conditional-compilation/cfg-arg-invalid-7.stderr new file mode 100644 index 0000000000..919709c847 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-7.stderr @@ -0,0 +1,4 @@ +error[E0765]: unterminated double quote string + | + = note: this error occurred on the command line: `--cfg=a"` + diff --git a/src/test/ui/issues/issue-34028.rs b/src/test/ui/conditional-compilation/issue-34028.rs similarity index 100% rename from src/test/ui/issues/issue-34028.rs rename to src/test/ui/conditional-compilation/issue-34028.rs diff --git a/src/test/ui/auxiliary/legacy-const-generics.rs b/src/test/ui/const-generics/auxiliary/legacy-const-generics.rs similarity index 100% rename from src/test/ui/auxiliary/legacy-const-generics.rs rename to src/test/ui/const-generics/auxiliary/legacy-const-generics.rs diff --git a/src/test/ui/const-generics/defaults/default-annotation.rs b/src/test/ui/const-generics/defaults/default-annotation.rs index 2b41dbb588..5517bf8ac5 100644 --- a/src/test/ui/const-generics/defaults/default-annotation.rs +++ b/src/test/ui/const-generics/defaults/default-annotation.rs @@ -2,7 +2,7 @@ #![feature(staged_api)] #![feature(const_generics_defaults)] #![allow(incomplete_features)] -// FIXME(const_generics): It seems like we aren't testing the right thing here, +// FIXME(const_generics_defaults): It seems like we aren't testing the right thing here, // I would assume that we want the attributes to apply to the const parameter defaults // themselves. #![stable(feature = "const_default_test", since="none")] diff --git a/src/test/ui/const-generics/defaults/doesnt_infer.rs b/src/test/ui/const-generics/defaults/doesnt_infer.rs new file mode 100644 index 0000000000..c7f14e47a9 --- /dev/null +++ b/src/test/ui/const-generics/defaults/doesnt_infer.rs @@ -0,0 +1,15 @@ +#![feature(const_generics_defaults)] + +// test that defaulted const params are not used to help type inference + +struct Foo<const N: u32 = 2>; + +impl<const N: u32> Foo<N> { + fn foo() -> Self { loop {} } +} + +fn main() { + let foo = Foo::<1>::foo(); + let foo = Foo::foo(); + //~^ error: type annotations needed for `Foo<{_: u32}>` +} diff --git a/src/test/ui/const-generics/defaults/doesnt_infer.stderr b/src/test/ui/const-generics/defaults/doesnt_infer.stderr new file mode 100644 index 0000000000..b57975e26f --- /dev/null +++ b/src/test/ui/const-generics/defaults/doesnt_infer.stderr @@ -0,0 +1,11 @@ +error[E0282]: type annotations needed for `Foo<{_: u32}>` + --> $DIR/doesnt_infer.rs:13:15 + | +LL | let foo = Foo::foo(); + | --- ^^^^^^^^ cannot infer the value of const parameter `N` + | | + | consider giving `foo` the explicit type `Foo<{_: u32}>`, 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/const-generics/defaults/rp_impl_trait.rs b/src/test/ui/const-generics/defaults/rp_impl_trait.rs new file mode 100644 index 0000000000..1447ebe534 --- /dev/null +++ b/src/test/ui/const-generics/defaults/rp_impl_trait.rs @@ -0,0 +1,31 @@ +// run-pass +#![feature(const_generics_defaults)] + +struct Uwu<const N: u32 = 1, const M: u32 = N>; + +trait Trait {} +impl<const N: u32> Trait for Uwu<N> {} + +fn rawr<const N: u32>() -> impl Trait { + Uwu::<N> +} + +trait Traitor<const N: u8 = 1, const M: u8 = N> { } + +impl<const N: u8> Traitor<N> for u32 {} +impl Traitor<1, 1> for u64 {} + +fn uwu<const N: u8>() -> impl Traitor<N> { + 1_u32 +} + +fn owo() -> impl Traitor { + 1_u64 +} + +fn main() { + rawr::<3>(); + rawr::<7>(); + uwu::<{ u8::MAX }>(); + owo(); +} diff --git a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.rs b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.rs new file mode 100644 index 0000000000..c989fc8338 --- /dev/null +++ b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.rs @@ -0,0 +1,33 @@ +#![feature(const_generics_defaults)] + +struct Uwu<const N: u32 = 1, const M: u32 = N>; + +trait Trait {} +impl<const N: u32> Trait for Uwu<N> {} + +fn rawr() -> impl Trait { + //~^ error: the trait bound `Uwu<10_u32, 12_u32>: Trait` is not satisfied + Uwu::<10, 12> +} + +trait Traitor<const N: u8 = 1, const M: u8 = N> { } + +impl<const N: u8> Traitor<N, 2> for u32 {} +impl Traitor<1, 2> for u64 {} + + +fn uwu<const N: u8>() -> impl Traitor<N> { + //~^ error: the trait bound `u32: Traitor<N, N>` is not satisfied + 1_u32 +} + +fn owo() -> impl Traitor { + //~^ error: the trait bound `u64: Traitor<1_u8, 1_u8>` is not satisfied + 1_u64 +} + +fn main() { + rawr(); + uwu(); + owo(); +} diff --git a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr new file mode 100644 index 0000000000..cf28932177 --- /dev/null +++ b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr @@ -0,0 +1,30 @@ +error[E0277]: the trait bound `Uwu<10_u32, 12_u32>: Trait` is not satisfied + --> $DIR/rp_impl_trait_fail.rs:8:14 + | +LL | fn rawr() -> impl Trait { + | ^^^^^^^^^^ the trait `Trait` is not implemented for `Uwu<10_u32, 12_u32>` + | + = help: the following implementations were found: + <Uwu<N> as Trait> + +error[E0277]: the trait bound `u32: Traitor<N, N>` is not satisfied + --> $DIR/rp_impl_trait_fail.rs:19:26 + | +LL | fn uwu<const N: u8>() -> impl Traitor<N> { + | ^^^^^^^^^^^^^^^ the trait `Traitor<N, N>` is not implemented for `u32` + | + = help: the following implementations were found: + <u32 as Traitor<N, 2_u8>> + +error[E0277]: the trait bound `u64: Traitor<1_u8, 1_u8>` is not satisfied + --> $DIR/rp_impl_trait_fail.rs:24:13 + | +LL | fn owo() -> impl Traitor { + | ^^^^^^^^^^^^ the trait `Traitor<1_u8, 1_u8>` is not implemented for `u64` + | + = help: the following implementations were found: + <u64 as Traitor<1_u8, 2_u8>> + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/defaults/trait_objects.rs b/src/test/ui/const-generics/defaults/trait_objects.rs new file mode 100644 index 0000000000..e36f23fadb --- /dev/null +++ b/src/test/ui/const-generics/defaults/trait_objects.rs @@ -0,0 +1,45 @@ +// run-pass +#![feature(const_generics_defaults)] + +trait Trait<const N: u8 = 12> { + fn uwu(&self) -> u8 { + N + } +} + +impl Trait for u32 {} + +impl Trait<12> for u64 { + fn uwu(&self) -> u8 { + *self as u8 + } +} + +fn foo(arg: &dyn Trait) -> u8 { + arg.uwu() +} + +trait Traitor<const N: u8 = 1, const M: u8 = N> { + fn owo(&self) -> u8 { + M + } +} + +impl Traitor<2> for bool { } +impl Traitor for u8 { + fn owo(&self) -> u8 { + *self + } +} + +fn bar<const N: u8>(arg: &dyn Traitor<N>) -> u8 { + arg.owo() +} + +fn main() { + assert_eq!(foo(&10_u32), 12); + assert_eq!(foo(&3_u64), 3); + + assert_eq!(bar(&true), 2); + assert_eq!(bar(&1_u8), 1); +} diff --git a/src/test/ui/const-generics/defaults/trait_objects_fail.rs b/src/test/ui/const-generics/defaults/trait_objects_fail.rs new file mode 100644 index 0000000000..09e4265a7a --- /dev/null +++ b/src/test/ui/const-generics/defaults/trait_objects_fail.rs @@ -0,0 +1,32 @@ +#![feature(const_generics_defaults)] + +trait Trait<const N: u8 = 12> { + fn uwu(&self) -> u8 { + N + } +} + +impl Trait<2> for u32 {} + +fn foo(arg: &dyn Trait) -> u8 { + arg.uwu() +} + +trait Traitor<const N: u8 = 1, const M: u8 = N> { + fn owo(&self) -> u8 { + M + } +} + +impl Traitor<2, 3> for bool { } + +fn bar<const N: u8>(arg: &dyn Traitor<N>) -> u8 { + arg.owo() +} + +fn main() { + foo(&10_u32); + //~^ error: the trait bound `u32: Trait` is not satisfied + bar(&true); + //~^ error: the trait bound `bool: Traitor<{_: u8}, {_: u8}>` is not satisfied +} diff --git a/src/test/ui/const-generics/defaults/trait_objects_fail.stderr b/src/test/ui/const-generics/defaults/trait_objects_fail.stderr new file mode 100644 index 0000000000..b097c8cd4b --- /dev/null +++ b/src/test/ui/const-generics/defaults/trait_objects_fail.stderr @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `u32: Trait` is not satisfied + --> $DIR/trait_objects_fail.rs:28:9 + | +LL | foo(&10_u32); + | --- ^^^^^^^ the trait `Trait` is not implemented for `u32` + | | + | required by a bound introduced by this call + | + = help: the following implementations were found: + <u32 as Trait<2_u8>> + = note: required for the cast to the object type `dyn Trait` + +error[E0277]: the trait bound `bool: Traitor<{_: u8}, {_: u8}>` is not satisfied + --> $DIR/trait_objects_fail.rs:30:9 + | +LL | bar(&true); + | --- ^^^^^ the trait `Traitor<{_: u8}, {_: u8}>` is not implemented for `bool` + | | + | required by a bound introduced by this call + | + = help: the following implementations were found: + <bool as Traitor<2_u8, 3_u8>> + = note: required for the cast to the object type `dyn Traitor<{_: u8}, {_: u8}>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/defaults/wfness.rs b/src/test/ui/const-generics/defaults/wfness.rs new file mode 100644 index 0000000000..c171f292fd --- /dev/null +++ b/src/test/ui/const-generics/defaults/wfness.rs @@ -0,0 +1,21 @@ +#![feature(const_generics_defaults)] + +struct Ooopsies<const N: u8 = { u8::MAX + 1 }>; +//~^ error: evaluation of constant value failed + +trait Trait<const N: u8> {} +impl Trait<3> for () {} +struct WhereClause<const N: u8 = 2> where (): Trait<N>; +//~^ error: the trait bound `(): Trait<2_u8>` is not satisfied + +trait Traitor<T, const N: u8> {} +struct WhereClauseTooGeneric<T = u32, const N: u8 = 2>(T) where (): Traitor<T, N>; + +// no error on struct def +struct DependentDefaultWfness<const N: u8 = 1, T = WhereClause<N>>(T); +fn foo() -> DependentDefaultWfness { + //~^ error: the trait bound `(): Trait<1_u8>` is not satisfied + loop {} +} + +fn main() {} diff --git a/src/test/ui/const-generics/defaults/wfness.stderr b/src/test/ui/const-generics/defaults/wfness.stderr new file mode 100644 index 0000000000..2d400f9bbf --- /dev/null +++ b/src/test/ui/const-generics/defaults/wfness.stderr @@ -0,0 +1,33 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/wfness.rs:3:33 + | +LL | struct Ooopsies<const N: u8 = { u8::MAX + 1 }>; + | ^^^^^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow + +error[E0277]: the trait bound `(): Trait<2_u8>` is not satisfied + --> $DIR/wfness.rs:8:47 + | +LL | struct WhereClause<const N: u8 = 2> where (): Trait<N>; + | ^^^^^^^^ the trait `Trait<2_u8>` is not implemented for `()` + | + = help: the following implementations were found: + <() as Trait<3_u8>> + +error[E0277]: the trait bound `(): Trait<1_u8>` is not satisfied + --> $DIR/wfness.rs:16:13 + | +LL | fn foo() -> DependentDefaultWfness { + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<1_u8>` is not implemented for `()` + | + = help: the following implementations were found: + <() as Trait<3_u8>> +note: required by a bound in `WhereClause` + --> $DIR/wfness.rs:8:47 + | +LL | struct WhereClause<const N: u8 = 2> where (): Trait<N>; + | ^^^^^^^^ required by this bound in `WhereClause` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0080, E0277. +For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/const-generics/defaults/wrong-order.rs b/src/test/ui/const-generics/defaults/wrong-order.rs index 33564a4844..94e7367b1f 100644 --- a/src/test/ui/const-generics/defaults/wrong-order.rs +++ b/src/test/ui/const-generics/defaults/wrong-order.rs @@ -5,4 +5,7 @@ struct A<T = u32, const N: usize> { arg: T, } +struct Foo<const N: u8 = 3, T>(T); +//~^ error: generic parameters with a default must be trailing + fn main() {} diff --git a/src/test/ui/const-generics/defaults/wrong-order.stderr b/src/test/ui/const-generics/defaults/wrong-order.stderr index 47a2c6f3f4..143ce5c4fe 100644 --- a/src/test/ui/const-generics/defaults/wrong-order.stderr +++ b/src/test/ui/const-generics/defaults/wrong-order.stderr @@ -4,5 +4,11 @@ error: generic parameters with a default must be trailing LL | struct A<T = u32, const N: usize> { | ^ -error: aborting due to previous error +error: generic parameters with a default must be trailing + --> $DIR/wrong-order.rs:8:18 + | +LL | struct Foo<const N: u8 = 3, T>(T); + | ^ + +error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr b/src/test/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr index 09986f623f..68ce61bd4a 100644 --- a/src/test/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr +++ b/src/test/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr @@ -3,12 +3,6 @@ error[E0277]: the trait bound `[Adt; _]: Foo` is not satisfied | LL | <[Adt; std::mem::size_of::<Self::Assoc>()] as Foo>::bar() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `[Adt; _]` - | -note: required by `Foo::bar` - --> $DIR/dont-evaluate-array-len-on-err-1.rs:19:5 - | -LL | fn bar() {} - | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/const-generics/exhaustive-value.stderr b/src/test/ui/const-generics/exhaustive-value.stderr index 0c6aced4bc..1a8f4abf52 100644 --- a/src/test/ui/const-generics/exhaustive-value.stderr +++ b/src/test/ui/const-generics/exhaustive-value.stderr @@ -10,11 +10,6 @@ LL | <() as Foo<N>>::test() <() as Foo<101_u8>> <() as Foo<102_u8>> and 252 others -note: required by `Foo::test` - --> $DIR/exhaustive-value.rs:2:5 - | -LL | fn test() {} - | ^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr index 3c7a740e84..02dce4f7a9 100644 --- a/src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr @@ -41,11 +41,6 @@ LL | IsLessOrEqual<I, 8>: True, | ^^^^ cannot infer type for struct `IsLessOrEqual<I, 8_u32>` | = note: cannot satisfy `IsLessOrEqual<I, 8_u32>: True` -note: required by a bound in `True` - --> $DIR/issue-72787.rs:8:1 - | -LL | pub trait True {} - | ^^^^^^^^^^^^^^ required by this bound in `True` error[E0283]: type annotations needed --> $DIR/issue-72787.rs:21:26 @@ -54,11 +49,6 @@ LL | IsLessOrEqual<I, 8>: True, | ^^^^ cannot infer type for struct `IsLessOrEqual<I, 8_u32>` | = note: cannot satisfy `IsLessOrEqual<I, 8_u32>: True` -note: required by a bound in `True` - --> $DIR/issue-72787.rs:8:1 - | -LL | pub trait True {} - | ^^^^^^^^^^^^^^ required by this bound in `True` error: aborting due to 6 previous errors diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-83765.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-83765.stderr index ef785bf07e..0332e82fe0 100644 --- a/src/test/ui/const-generics/generic_const_exprs/issue-83765.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/issue-83765.stderr @@ -14,6 +14,11 @@ LL | self.reference.size() | ^^^^ | = help: try adding a `where` bound using this expression: `where [(); Self::DIM]:` +note: required by a bound in `TensorSize::size` + --> $DIR/issue-83765.rs:9:31 + | +LL | fn size(&self) -> [usize; Self::DIM]; + | ^^^^^^^^^ required by this bound in `TensorSize::size` error[E0308]: mismatched types --> $DIR/issue-83765.rs:32:9 diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-85848.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-85848.stderr index e51db35925..4202cbae7e 100644 --- a/src/test/ui/const-generics/generic_const_exprs/issue-85848.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/issue-85848.stderr @@ -1,8 +1,10 @@ error[E0277]: the trait bound `(): _Contains<&C>` is not satisfied - --> $DIR/issue-85848.rs:24:5 + --> $DIR/issue-85848.rs:24:29 | LL | writes_to_specific_path(&cap); - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `_Contains<&C>` is not implemented for `()` + | ----------------------- ^^^^ the trait `_Contains<&C>` is not implemented for `()` + | | + | required by a bound introduced by this call | note: required because of the requirements on the impl of `Contains<(), true>` for `&C` --> $DIR/issue-85848.rs:21:12 @@ -21,10 +23,12 @@ LL | fn writes_to_specific_path<C: Delegates<()>>(cap: &C) {} | ^^^^^^^^^^^^^ required by this bound in `writes_to_specific_path` error: unconstrained generic constant - --> $DIR/issue-85848.rs:24:5 + --> $DIR/issue-85848.rs:24:29 | LL | writes_to_specific_path(&cap); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ----------------------- ^^^^ + | | + | required by a bound introduced by this call | = help: try adding a `where` bound using this expression: `where [(); { contains::<T, U>() }]:` note: required because of the requirements on the impl of `Contains<(), true>` for `&C` diff --git a/src/test/ui/const-generics/impl-trait-with-const-arguments.stderr b/src/test/ui/const-generics/impl-trait-with-const-arguments.stderr index 6268a564b0..87e4ad5004 100644 --- a/src/test/ui/const-generics/impl-trait-with-const-arguments.stderr +++ b/src/test/ui/const-generics/impl-trait-with-const-arguments.stderr @@ -3,6 +3,9 @@ error[E0632]: cannot provide explicit generic arguments when `impl Trait` is use | LL | assert_eq!(f::<4usize>(Usizable), 20usize); | ^^^^^^ explicit generic argument not allowed + | + = note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information + = help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable error: aborting due to previous error diff --git a/src/test/ui/const-generics/invariant.nll.stderr b/src/test/ui/const-generics/invariant.nll.stderr new file mode 100644 index 0000000000..ce0fad1047 --- /dev/null +++ b/src/test/ui/const-generics/invariant.nll.stderr @@ -0,0 +1,26 @@ +warning: conflicting implementations of trait `SadBee` for type `for<'a> fn(&'a ())` + --> $DIR/invariant.rs:14:1 + | +LL | impl SadBee for for<'a> fn(&'a ()) { + | ---------------------------------- first implementation here +... +LL | impl SadBee for fn(&'static ()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a> fn(&'a ())` + | + = note: `#[warn(coherence_leak_check)]` 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 #56105 <https://github.com/rust-lang/rust/issues/56105> + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details + +error[E0308]: mismatched types + --> $DIR/invariant.rs:27:5 + | +LL | v + | ^ one type is more general than the other + | + = note: expected reference `&Foo<fn(&())>` + found reference `&Foo<for<'a> fn(&'a ())>` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/invariant.rs b/src/test/ui/const-generics/invariant.rs new file mode 100644 index 0000000000..ee191b65c2 --- /dev/null +++ b/src/test/ui/const-generics/invariant.rs @@ -0,0 +1,33 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +use std::marker::PhantomData; + +trait SadBee { + const ASSOC: usize; +} +// fn(&'static ())` is a supertype of `for<'a> fn(&'a ())` while +// we allow two different impls for these types, leading +// to different const eval results. +impl SadBee for for<'a> fn(&'a ()) { + const ASSOC: usize = 0; +} +impl SadBee for fn(&'static ()) { + //~^ WARNING conflicting implementations of trait + //~| WARNING this was previously accepted + const ASSOC: usize = 100; +} + +struct Foo<T: SadBee>([u8; <T as SadBee>::ASSOC], PhantomData<T>) +where + [(); <T as SadBee>::ASSOC]: ; + +fn covariant( + v: &'static Foo<for<'a> fn(&'a ())> +) -> &'static Foo<fn(&'static ())> { + v //~ ERROR mismatched types +} + +fn main() { + let y = covariant(&Foo([], PhantomData)); + println!("{:?}", y.0); +} diff --git a/src/test/ui/const-generics/invariant.stderr b/src/test/ui/const-generics/invariant.stderr new file mode 100644 index 0000000000..318c885e6a --- /dev/null +++ b/src/test/ui/const-generics/invariant.stderr @@ -0,0 +1,26 @@ +warning: conflicting implementations of trait `SadBee` for type `for<'a> fn(&'a ())` + --> $DIR/invariant.rs:14:1 + | +LL | impl SadBee for for<'a> fn(&'a ()) { + | ---------------------------------- first implementation here +... +LL | impl SadBee for fn(&'static ()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a> fn(&'a ())` + | + = note: `#[warn(coherence_leak_check)]` 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 #56105 <https://github.com/rust-lang/rust/issues/56105> + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details + +error[E0308]: mismatched types + --> $DIR/invariant.rs:27:5 + | +LL | v + | ^ one type is more general than the other + | + = note: expected reference `&'static Foo<fn(&'static ())>` + found reference `&'static Foo<for<'a> fn(&'a ())>` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/issues/issue-67185-2.rs b/src/test/ui/const-generics/issues/issue-67185-2.rs index c1a04e2014..18bb6f6bc1 100644 --- a/src/test/ui/const-generics/issues/issue-67185-2.rs +++ b/src/test/ui/const-generics/issues/issue-67185-2.rs @@ -9,11 +9,10 @@ trait Bar {} impl Bar for [u16; 4] {} impl Bar for [[u16; 3]; 3] {} -trait Foo //~ ERROR the trait bound `[u16; 3]: Bar` is not satisfied [E0277] - //~^ ERROR the trait bound `[[u16; 3]; 2]: Bar` is not satisfied [E0277] - where - [<u8 as Baz>::Quaks; 2]: Bar, - <u8 as Baz>::Quaks: Bar, +trait Foo +where + [<u8 as Baz>::Quaks; 2]: Bar, //~ ERROR the trait bound `[[u16; 3]; 2]: Bar` is not satisfied [E0277] + <u8 as Baz>::Quaks: Bar, //~ ERROR the trait bound `[u16; 3]: Bar` is not satisfied [E0277] { } diff --git a/src/test/ui/const-generics/issues/issue-67185-2.stderr b/src/test/ui/const-generics/issues/issue-67185-2.stderr index 7167bea94b..89aa3d395e 100644 --- a/src/test/ui/const-generics/issues/issue-67185-2.stderr +++ b/src/test/ui/const-generics/issues/issue-67185-2.stderr @@ -1,14 +1,8 @@ error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:12:1 + --> $DIR/issue-67185-2.rs:15:5 | -LL | / trait Foo -LL | | -LL | | where -LL | | [<u8 as Baz>::Quaks; 2]: Bar, -LL | | <u8 as Baz>::Quaks: Bar, -LL | | { -LL | | } - | |_^ the trait `Bar` is not implemented for `[u16; 3]` +LL | <u8 as Baz>::Quaks: Bar, + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `[u16; 3]` | = help: the following implementations were found: <[[u16; 3]; 3] as Bar> @@ -17,16 +11,10 @@ LL | | } = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:12:1 + --> $DIR/issue-67185-2.rs:14:5 | -LL | / trait Foo -LL | | -LL | | where -LL | | [<u8 as Baz>::Quaks; 2]: Bar, -LL | | <u8 as Baz>::Quaks: Bar, -LL | | { -LL | | } - | |_^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` +LL | [<u8 as Baz>::Quaks; 2]: Bar, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` | = help: the following implementations were found: <[[u16; 3]; 3] as Bar> @@ -35,7 +23,7 @@ LL | | } = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:22:6 + --> $DIR/issue-67185-2.rs:21:6 | LL | impl Foo for FooImpl {} | ^^^ the trait `Bar` is not implemented for `[u16; 3]` @@ -44,16 +32,16 @@ LL | impl Foo for FooImpl {} <[[u16; 3]; 3] as Bar> <[u16; 4] as Bar> note: required by a bound in `Foo` - --> $DIR/issue-67185-2.rs:16:29 + --> $DIR/issue-67185-2.rs:15:25 | LL | trait Foo | --- required by a bound in this ... -LL | <u8 as Baz>::Quaks: Bar, - | ^^^ required by this bound in `Foo` +LL | <u8 as Baz>::Quaks: Bar, + | ^^^ required by this bound in `Foo` error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:22:6 + --> $DIR/issue-67185-2.rs:21:6 | LL | impl Foo for FooImpl {} | ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` @@ -62,16 +50,16 @@ LL | impl Foo for FooImpl {} <[[u16; 3]; 3] as Bar> <[u16; 4] as Bar> note: required by a bound in `Foo` - --> $DIR/issue-67185-2.rs:15:34 + --> $DIR/issue-67185-2.rs:14:30 | LL | trait Foo | --- required by a bound in this -... -LL | [<u8 as Baz>::Quaks; 2]: Bar, - | ^^^ required by this bound in `Foo` +LL | where +LL | [<u8 as Baz>::Quaks; 2]: Bar, + | ^^^ required by this bound in `Foo` error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:26:14 + --> $DIR/issue-67185-2.rs:25:14 | LL | fn f(_: impl Foo) {} | ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` @@ -80,16 +68,16 @@ LL | fn f(_: impl Foo) {} <[[u16; 3]; 3] as Bar> <[u16; 4] as Bar> note: required by a bound in `Foo` - --> $DIR/issue-67185-2.rs:15:34 + --> $DIR/issue-67185-2.rs:14:30 | LL | trait Foo | --- required by a bound in this -... -LL | [<u8 as Baz>::Quaks; 2]: Bar, - | ^^^ required by this bound in `Foo` +LL | where +LL | [<u8 as Baz>::Quaks; 2]: Bar, + | ^^^ required by this bound in `Foo` error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:26:14 + --> $DIR/issue-67185-2.rs:25:14 | LL | fn f(_: impl Foo) {} | ^^^ the trait `Bar` is not implemented for `[u16; 3]` @@ -98,13 +86,13 @@ LL | fn f(_: impl Foo) {} <[[u16; 3]; 3] as Bar> <[u16; 4] as Bar> note: required by a bound in `Foo` - --> $DIR/issue-67185-2.rs:16:29 + --> $DIR/issue-67185-2.rs:15:25 | LL | trait Foo | --- required by a bound in this ... -LL | <u8 as Baz>::Quaks: Bar, - | ^^^ required by this bound in `Foo` +LL | <u8 as Baz>::Quaks: Bar, + | ^^^ required by this bound in `Foo` error: aborting due to 6 previous errors diff --git a/src/test/ui/const-generics/issues/issue-67375.full.stderr b/src/test/ui/const-generics/issues/issue-67375.full.stderr index 0f0e339655..0cf69879a5 100644 --- a/src/test/ui/const-generics/issues/issue-67375.full.stderr +++ b/src/test/ui/const-generics/issues/issue-67375.full.stderr @@ -8,15 +8,5 @@ LL | inner: [(); { [|_: &T| {}; 0].len() }], | = help: consider moving this anonymous constant into a `const` function -error[E0392]: parameter `T` is never used - --> $DIR/issue-67375.rs:5:12 - | -LL | struct Bug<T> { - | ^ unused parameter - | - = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `T` to be a const parameter, use `const T: usize` instead - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0392`. diff --git a/src/test/ui/const-generics/issues/issue-67375.rs b/src/test/ui/const-generics/issues/issue-67375.rs index b5b842a15a..8b4b276bae 100644 --- a/src/test/ui/const-generics/issues/issue-67375.rs +++ b/src/test/ui/const-generics/issues/issue-67375.rs @@ -3,7 +3,7 @@ #![cfg_attr(full, feature(generic_const_exprs))] struct Bug<T> { - //~^ ERROR parameter `T` is never used + //[min]~^ ERROR parameter `T` is never used inner: [(); { [|_: &T| {}; 0].len() }], //[min]~^ ERROR generic parameters may not be used in const operations //[full]~^^ ERROR overly complex generic constant diff --git a/src/test/ui/const-generics/issues/issue-67945-1.full.stderr b/src/test/ui/const-generics/issues/issue-67945-1.full.stderr index 1edc7828ca..8e18fcdffa 100644 --- a/src/test/ui/const-generics/issues/issue-67945-1.full.stderr +++ b/src/test/ui/const-generics/issues/issue-67945-1.full.stderr @@ -12,16 +12,6 @@ LL | let x: S = MaybeUninit::uninit(); = note: expected type parameter `S` found union `MaybeUninit<_>` -error[E0392]: parameter `S` is never used - --> $DIR/issue-67945-1.rs:7:12 - | -LL | struct Bug<S> { - | ^ unused parameter - | - = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `S` to be a const parameter, use `const S: usize` instead - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0308, E0392. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/issues/issue-67945-1.rs b/src/test/ui/const-generics/issues/issue-67945-1.rs index 7b7e842863..99f88bc8e1 100644 --- a/src/test/ui/const-generics/issues/issue-67945-1.rs +++ b/src/test/ui/const-generics/issues/issue-67945-1.rs @@ -5,7 +5,7 @@ use std::mem::MaybeUninit; struct Bug<S> { - //~^ ERROR parameter `S` is never used + //[min]~^ ERROR parameter `S` is never used A: [(); { let x: S = MaybeUninit::uninit(); //[min]~^ ERROR generic parameters may not be used in const operations diff --git a/src/test/ui/const-generics/issues/issue-88997.rs b/src/test/ui/const-generics/issues/issue-88997.rs new file mode 100644 index 0000000000..7666a51410 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-88997.rs @@ -0,0 +1,14 @@ +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +struct ConstAssert<const COND: bool>; +trait True {} +impl True for ConstAssert<true> {} + +struct Range<T: PartialOrd, const MIN: T, const MAX: T>(T) +//~^ ERROR the type of const parameters must not depend on other generic parameters +//~| ERROR the type of const parameters must not depend on other generic parameters +where + ConstAssert<{ MIN <= MAX }>: True; + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-88997.stderr b/src/test/ui/const-generics/issues/issue-88997.stderr new file mode 100644 index 0000000000..505ba0da23 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-88997.stderr @@ -0,0 +1,15 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/issue-88997.rs:8:40 + | +LL | struct Range<T: PartialOrd, const MIN: T, const MAX: T>(T) + | ^ the type must not depend on the parameter `T` + +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/issue-88997.rs:8:54 + | +LL | struct Range<T: PartialOrd, const MIN: T, const MAX: T>(T) + | ^ the type must not depend on the parameter `T` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0770`. diff --git a/src/test/ui/const-generics/issues/issue-89304.rs b/src/test/ui/const-generics/issues/issue-89304.rs new file mode 100644 index 0000000000..d544d637cc --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-89304.rs @@ -0,0 +1,20 @@ +// check-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct GenericStruct<const T: usize> { val: i64 } + +impl<const T: usize> From<GenericStruct<T>> for GenericStruct<{T + 1}> { + fn from(other: GenericStruct<T>) -> Self { + Self { val: other.val } + } +} + +impl<const T: usize> From<GenericStruct<{T + 1}>> for GenericStruct<T> { + fn from(other: GenericStruct<{T + 1}>) -> Self { + Self { val: other.val } + } +} + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-90364.rs b/src/test/ui/const-generics/issues/issue-90364.rs new file mode 100644 index 0000000000..b11b07b502 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-90364.rs @@ -0,0 +1,9 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub struct Foo<T, const H: T>(T) +//~^ ERROR the type of const parameters must not depend on other generic parameters +where + [(); 1]:; + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-90364.stderr b/src/test/ui/const-generics/issues/issue-90364.stderr new file mode 100644 index 0000000000..e85bd136ef --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-90364.stderr @@ -0,0 +1,9 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/issue-90364.rs:4:28 + | +LL | pub struct Foo<T, const H: T>(T) + | ^ the type must not depend on the parameter `T` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0770`. diff --git a/src/test/ui/legacy-const-generics-bad.rs b/src/test/ui/const-generics/legacy-const-generics-bad.rs similarity index 100% rename from src/test/ui/legacy-const-generics-bad.rs rename to src/test/ui/const-generics/legacy-const-generics-bad.rs diff --git a/src/test/ui/legacy-const-generics-bad.stderr b/src/test/ui/const-generics/legacy-const-generics-bad.stderr similarity index 100% rename from src/test/ui/legacy-const-generics-bad.stderr rename to src/test/ui/const-generics/legacy-const-generics-bad.stderr diff --git a/src/test/ui/legacy-const-generics.rs b/src/test/ui/const-generics/legacy-const-generics.rs similarity index 100% rename from src/test/ui/legacy-const-generics.rs rename to src/test/ui/const-generics/legacy-const-generics.rs 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 index 382dd0ee5a..486a298a9f 100644 --- a/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr +++ b/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr @@ -6,13 +6,11 @@ LL | let _ = A; | = help: the following implementations were found: <A<7_usize> as Bar<N>> -note: required by `A` - --> $DIR/unused-substs-1.rs:7:1 +note: required by a bound in `A` + --> $DIR/unused-substs-1.rs:9:11 | -LL | / struct A<const N: usize> -LL | | where -LL | | A<N>: Bar<N>; - | |_________________^ +LL | A<N>: Bar<N>; + | ^^^^^^ required by this bound in `A` error: aborting due to previous error diff --git a/src/test/ui/consts/closure-structural-match-issue-90013.rs b/src/test/ui/consts/closure-structural-match-issue-90013.rs new file mode 100644 index 0000000000..1952ddb941 --- /dev/null +++ b/src/test/ui/consts/closure-structural-match-issue-90013.rs @@ -0,0 +1,7 @@ +// Regression test for issue 90013. +// check-pass +#![feature(inline_const)] + +fn main() { + const { || {} }; +} diff --git a/src/test/ui/consts/const-blocks/fn-call-in-const.rs b/src/test/ui/consts/const-blocks/fn-call-in-const.rs index 7936af75d8..20496f6271 100644 --- a/src/test/ui/consts/const-blocks/fn-call-in-const.rs +++ b/src/test/ui/consts/const-blocks/fn-call-in-const.rs @@ -1,7 +1,7 @@ // run-pass #![feature(inline_const)] -#![allow(unused, incomplete_features)] +#![allow(unused)] // Some type that is not copyable. struct Bar; diff --git a/src/test/ui/consts/const-deref-ptr.rs b/src/test/ui/consts/const-deref-ptr.rs index b5f603bb47..4aca75e3a1 100644 --- a/src/test/ui/consts/const-deref-ptr.rs +++ b/src/test/ui/consts/const-deref-ptr.rs @@ -1,7 +1,7 @@ -// Check that you can't dereference raw pointers in constants. +// Check that you can't dereference invalid raw pointers in constants. fn main() { static C: u64 = unsafe {*(0xdeadbeef as *const u64)}; - //~^ ERROR dereferencing raw pointers in statics is unstable + //~^ ERROR could not evaluate static initializer println!("{}", C); } diff --git a/src/test/ui/consts/const-deref-ptr.stderr b/src/test/ui/consts/const-deref-ptr.stderr index 61fcb52431..316843889c 100644 --- a/src/test/ui/consts/const-deref-ptr.stderr +++ b/src/test/ui/consts/const-deref-ptr.stderr @@ -1,12 +1,9 @@ -error[E0658]: dereferencing raw pointers in statics is unstable +error[E0080]: could not evaluate static initializer --> $DIR/const-deref-ptr.rs:4:29 | LL | static C: u64 = unsafe {*(0xdeadbeef as *const u64)}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #51911 <https://github.com/rust-lang/rust/issues/51911> for more information - = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 0xdeadbeef is not a valid pointer error: aborting due to previous error -For more information about this error, try `rustc --explain E0658`. +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-err.rs b/src/test/ui/consts/const-err.rs index 031f2121a1..a8633fd87b 100644 --- a/src/test/ui/consts/const-err.rs +++ b/src/test/ui/consts/const-err.rs @@ -1,5 +1,5 @@ // build-fail -// compile-flags: -Zforce-overflow-checks=on +// compile-flags: -C overflow-checks=on #![allow(arithmetic_overflow)] #![warn(const_err)] diff --git a/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs b/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs deleted file mode 100644 index 037c6f9f7e..0000000000 --- a/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs +++ /dev/null @@ -1,19 +0,0 @@ -// New test for #53818: modifying static memory at compile-time is not allowed. -// The test should never compile successfully - -#![feature(const_raw_ptr_deref, const_mut_refs)] - -use std::cell::UnsafeCell; - -struct Foo(UnsafeCell<u32>); - -unsafe impl Send for Foo {} -unsafe impl Sync for Foo {} - -static FOO: Foo = Foo(UnsafeCell::new(42)); - -static BAR: () = unsafe { - *FOO.0.get() = 5; //~ ERROR -}; - -fn main() {} diff --git a/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr b/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr deleted file mode 100644 index 296a6bf542..0000000000 --- a/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0080]: could not evaluate static initializer - --> $DIR/assign-to-static-within-other-static-2.rs:16:5 - | -LL | *FOO.0.get() = 5; - | ^^^^^^^^^^^^^^^^ modifying a static's initial value from another static's initializer - -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/assign-to-static-within-other-static.rs b/src/test/ui/consts/const-eval/assign-to-static-within-other-static.rs index 648caae30b..ecf97223f6 100644 --- a/src/test/ui/consts/const-eval/assign-to-static-within-other-static.rs +++ b/src/test/ui/consts/const-eval/assign-to-static-within-other-static.rs @@ -1,8 +1,6 @@ // New test for #53818: modifying static memory at compile-time is not allowed. // The test should never compile successfully -#![feature(const_raw_ptr_deref)] - use std::cell::UnsafeCell; static mut FOO: u32 = 42; diff --git a/src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr b/src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr index bf5e476d80..4b6784acfc 100644 --- a/src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr +++ b/src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr @@ -1,5 +1,5 @@ error[E0080]: could not evaluate static initializer - --> $DIR/assign-to-static-within-other-static.rs:10:5 + --> $DIR/assign-to-static-within-other-static.rs:8:5 | LL | FOO = 5; | ^^^^^^^ modifying a static's initial value from another static's initializer diff --git a/src/test/ui/consts/const-eval/const_panic_stability.e2018.stderr b/src/test/ui/consts/const-eval/const_panic_stability.e2018.stderr new file mode 100644 index 0000000000..94cf64fff1 --- /dev/null +++ b/src/test/ui/consts/const-eval/const_panic_stability.e2018.stderr @@ -0,0 +1,16 @@ +warning: panic message is not a string literal + --> $DIR/const_panic_stability.rs:14:12 + | +LL | panic!({ "foo" }); + | ^^^^^^^^^ + | + = note: `#[warn(non_fmt_panics)]` on by default + = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> +help: add a "{}" format string to Display the message + | +LL | panic!("{}", { "foo" }); + | +++++ + +warning: 1 warning emitted + diff --git a/src/test/ui/consts/const-eval/const_panic_stability.e2021.stderr b/src/test/ui/consts/const-eval/const_panic_stability.e2021.stderr new file mode 100644 index 0000000000..9e8179181f --- /dev/null +++ b/src/test/ui/consts/const-eval/const_panic_stability.e2021.stderr @@ -0,0 +1,13 @@ +error: format argument must be a string literal + --> $DIR/const_panic_stability.rs:14:12 + | +LL | panic!({ "foo" }); + | ^^^^^^^^^ + | +help: you might be missing a string literal to format with + | +LL | panic!("{}", { "foo" }); + | +++++ + +error: aborting due to previous error + diff --git a/src/test/ui/consts/const-eval/const_panic_stability.rs b/src/test/ui/consts/const-eval/const_panic_stability.rs new file mode 100644 index 0000000000..1aee6f27e2 --- /dev/null +++ b/src/test/ui/consts/const-eval/const_panic_stability.rs @@ -0,0 +1,17 @@ +// revisions: e2018 e2021 +//[e2018] edition:2018 +//[e2021] edition:2021 +//[e2018] check-pass +#![crate_type = "lib"] +#![stable(feature = "foo", since = "1.0.0")] +#![feature(staged_api)] + +#[stable(feature = "foo", since = "1.0.0")] +#[rustc_const_stable(feature = "foo", since = "1.0.0")] +const fn foo() { + assert!(false); + assert!(false, "foo"); + panic!({ "foo" }); + //[e2018]~^ WARNING panic message is not a string literal + //[e2021]~^^ ERROR format argument must be a string literal +} diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops2.rs b/src/test/ui/consts/const-eval/const_raw_ptr_ops2.rs index 11f6a58be3..c3f8b9f31e 100644 --- a/src/test/ui/consts/const-eval/const_raw_ptr_ops2.rs +++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops2.rs @@ -1,5 +1,3 @@ -#![feature(const_raw_ptr_deref)] - fn main() {} // fine diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops2.stderr b/src/test/ui/consts/const-eval/const_raw_ptr_ops2.stderr index ca32900773..44fa437806 100644 --- a/src/test/ui/consts/const-eval/const_raw_ptr_ops2.stderr +++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops2.stderr @@ -1,11 +1,11 @@ error[E0080]: evaluation of constant value failed - --> $DIR/const_raw_ptr_ops2.rs:9:26 + --> $DIR/const_raw_ptr_ops2.rs:7:26 | LL | const Z2: i32 = unsafe { *(42 as *const i32) }; | ^^^^^^^^^^^^^^^^^^^ 0x2a is not a valid pointer error[E0080]: evaluation of constant value failed - --> $DIR/const_raw_ptr_ops2.rs:11:26 + --> $DIR/const_raw_ptr_ops2.rs:9:26 | LL | const Z3: i32 = unsafe { *(44 as *const i32) }; | ^^^^^^^^^^^^^^^^^^^ 0x2c is not a valid pointer diff --git a/src/test/ui/consts/const-eval/dangling.rs b/src/test/ui/consts/const-eval/dangling.rs index 610531c7b4..4fcf879218 100644 --- a/src/test/ui/consts/const-eval/dangling.rs +++ b/src/test/ui/consts/const-eval/dangling.rs @@ -1,5 +1,3 @@ -#![feature(const_raw_ptr_deref)] - use std::mem; // Make sure we error with the right kind of error on a too large slice. diff --git a/src/test/ui/consts/const-eval/dangling.stderr b/src/test/ui/consts/const-eval/dangling.stderr index 5665a9c3e0..92d70573d9 100644 --- a/src/test/ui/consts/const-eval/dangling.stderr +++ b/src/test/ui/consts/const-eval/dangling.stderr @@ -1,5 +1,5 @@ error[E0080]: evaluation of constant value failed - --> $DIR/dangling.rs:8:16 + --> $DIR/dangling.rs:6:16 | LL | let _val = &*slice; | ^^^^^^^ invalid metadata in wide pointer: slice is bigger than largest supported object diff --git a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.rs b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.rs index 4df541eeeb..1a1d9a6d54 100644 --- a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.rs +++ b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.rs @@ -1,6 +1,5 @@ #![feature(core_intrinsics)] #![feature(const_heap)] -#![feature(const_raw_ptr_deref)] #![feature(const_mut_refs)] use std::intrinsics; diff --git a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr index 327e291120..74fb65ca1a 100644 --- a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr +++ b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr @@ -1,14 +1,14 @@ error[E0080]: evaluation of constant value failed - --> $DIR/alloc_intrinsic_errors.rs:10:17 + --> $DIR/alloc_intrinsic_errors.rs:9:17 | LL | const FOO: i32 = foo(); - | ----- inside `FOO` at $DIR/alloc_intrinsic_errors.rs:7:18 + | ----- inside `FOO` at $DIR/alloc_intrinsic_errors.rs:6:18 ... LL | let _ = intrinsics::const_allocate(4, 3) as * mut i32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | align has to be a power of 2, `3` is not a power of 2 - | inside `foo` at $DIR/alloc_intrinsic_errors.rs:10:17 + | inside `foo` at $DIR/alloc_intrinsic_errors.rs:9:17 error: aborting due to previous error diff --git a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_nontransient.rs b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_nontransient.rs index de7fb65f68..0a8fc7bcaa 100644 --- a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_nontransient.rs +++ b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_nontransient.rs @@ -1,7 +1,6 @@ // run-pass #![feature(core_intrinsics)] #![feature(const_heap)] -#![feature(const_raw_ptr_deref)] #![feature(const_mut_refs)] use std::intrinsics; diff --git a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.rs b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.rs index e6ef9974aa..f746f27000 100644 --- a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.rs +++ b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.rs @@ -1,6 +1,5 @@ #![feature(core_intrinsics)] #![feature(const_heap)] -#![feature(const_raw_ptr_deref)] #![feature(const_mut_refs)] use std::intrinsics; diff --git a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.stderr b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.stderr index 08679350d6..adaa4716f1 100644 --- a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.stderr +++ b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.stderr @@ -1,5 +1,5 @@ error: untyped pointers are not allowed in constant - --> $DIR/alloc_intrinsic_nontransient_fail.rs:7:1 + --> $DIR/alloc_intrinsic_nontransient_fail.rs:6:1 | LL | const FOO: *const i32 = foo(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_transient.rs b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_transient.rs index c55cd32d26..92193bb33e 100644 --- a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_transient.rs +++ b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_transient.rs @@ -1,7 +1,6 @@ // run-pass #![feature(core_intrinsics)] #![feature(const_heap)] -#![feature(const_raw_ptr_deref)] #![feature(const_mut_refs)] use std::intrinsics; diff --git a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr index c11fea8533..597703de01 100644 --- a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr +++ b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/alloc_intrinsic_uninit.rs:9:1 + --> $DIR/alloc_intrinsic_uninit.rs:8:1 | LL | const BAR: &i32 = unsafe { &*(intrinsics::const_allocate(4, 4) as *mut i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes 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 index 58d24dc2e8..08fbb67b37 100644 --- 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 @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/alloc_intrinsic_uninit.rs:9:1 + --> $DIR/alloc_intrinsic_uninit.rs:8:1 | LL | const BAR: &i32 = unsafe { &*(intrinsics::const_allocate(4, 4) as *mut i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes 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 63a3fd4e09..b53c9ac7a2 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 @@ -2,7 +2,6 @@ // compile-test #![feature(core_intrinsics)] #![feature(const_heap)] -#![feature(const_raw_ptr_deref)] #![feature(const_mut_refs)] use std::intrinsics; diff --git a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs index 625f7670bc..77871c394b 100644 --- a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs +++ b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs @@ -1,6 +1,5 @@ #![feature(core_intrinsics)] #![feature(const_heap)] -#![feature(const_raw_ptr_deref)] #![feature(const_mut_refs)] use std::intrinsics; diff --git a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr index ee84f8e54f..8f4fea96c5 100644 --- a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr +++ b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr @@ -1,5 +1,5 @@ error: untyped pointers are not allowed in constant - --> $DIR/alloc_intrinsic_untyped.rs:7:1 + --> $DIR/alloc_intrinsic_untyped.rs:6:1 | LL | const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/consts/const-eval/issue-84957-const-str-as-bytes.rs b/src/test/ui/consts/const-eval/issue-84957-const-str-as-bytes.rs new file mode 100644 index 0000000000..7e235c4911 --- /dev/null +++ b/src/test/ui/consts/const-eval/issue-84957-const-str-as-bytes.rs @@ -0,0 +1,28 @@ +// build-pass + +trait Foo {} + +struct Bar { + bytes: &'static [u8], + func: fn(&Box<dyn Foo>), +} +fn example(_: &Box<dyn Foo>) {} + +const BARS: &[Bar] = &[ + Bar { + bytes: "0".as_bytes(), + func: example, + }, + Bar { + bytes: "0".as_bytes(), + func: example, + }, +]; + +fn main() { + let x = todo!(); + + for bar in BARS { + (bar.func)(&x); + } +} diff --git a/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs b/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs index 481e046946..b6b74e67d2 100644 --- a/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs +++ b/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs @@ -1,7 +1,7 @@ // New test for #53818: modifying static memory at compile-time is not allowed. // The test should never compile successfully -#![feature(const_raw_ptr_deref)] +#![feature(const_mut_refs)] use std::cell::UnsafeCell; @@ -14,7 +14,7 @@ static FOO: Foo = Foo(UnsafeCell::new(42)); static BAR: () = unsafe { *FOO.0.get() = 5; - //~^ mutation through a reference + //~^ ERROR could not evaluate static initializer }; fn main() { diff --git a/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr b/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr index 38282c0e30..d127d1d455 100644 --- a/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr +++ b/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr @@ -1,12 +1,9 @@ -error[E0658]: mutation through a reference is not allowed in statics +error[E0080]: could not evaluate static initializer --> $DIR/mod-static-with-const-fn.rs:16:5 | LL | *FOO.0.get() = 5; - | ^^^^^^^^^^^^^^^^ - | - = 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 + | ^^^^^^^^^^^^^^^^ modifying a static's initial value from another static's initializer error: aborting due to previous error -For more information about this error, try `rustc --explain E0658`. +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/partial_ptr_overwrite.rs b/src/test/ui/consts/const-eval/partial_ptr_overwrite.rs index 5371f9f174..07bca7d64f 100644 --- a/src/test/ui/consts/const-eval/partial_ptr_overwrite.rs +++ b/src/test/ui/consts/const-eval/partial_ptr_overwrite.rs @@ -1,5 +1,5 @@ // Test for the behavior described in <https://github.com/rust-lang/rust/issues/87184>. -#![feature(const_mut_refs, const_raw_ptr_deref)] +#![feature(const_mut_refs)] const PARTIAL_OVERWRITE: () = { let mut p = &42; diff --git a/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs index c7d84303fe..1800b0a978 100644 --- a/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs +++ b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs @@ -1,5 +1,3 @@ -#![feature(const_raw_ptr_deref)] - fn main() { let x: &'static bool = &(42 as *const i32 == 43 as *const i32); //~^ ERROR temporary value dropped while borrowed diff --git a/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.stderr b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.stderr index 7f2e489918..8ac60da386 100644 --- a/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.stderr +++ b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.stderr @@ -1,5 +1,5 @@ error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_raw_ptr_ops.rs:4:29 + --> $DIR/promoted_raw_ptr_ops.rs:2:29 | LL | let x: &'static bool = &(42 as *const i32 == 43 as *const i32); | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use @@ -10,7 +10,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_raw_ptr_ops.rs:6:30 + --> $DIR/promoted_raw_ptr_ops.rs:4:30 | LL | let y: &'static usize = &(&1 as *const i32 as usize + 1); | -------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use @@ -21,7 +21,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_raw_ptr_ops.rs:8:28 + --> $DIR/promoted_raw_ptr_ops.rs:6:28 | LL | let z: &'static i32 = &(unsafe { *(42 as *const i32) }); | ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use @@ -32,7 +32,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_raw_ptr_ops.rs:10:29 + --> $DIR/promoted_raw_ptr_ops.rs:8:29 | LL | let a: &'static bool = &(main as fn() == main as fn()); | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use 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 cae8fcf106..a1d6c5e51b 100644 --- a/src/test/ui/consts/const-eval/simd/insert_extract.rs +++ b/src/test/ui/consts/const-eval/simd/insert_extract.rs @@ -7,7 +7,9 @@ #[repr(simd)] struct i8x1(i8); #[repr(simd)] struct u16x2(u16, u16); -#[repr(simd)] struct f32x4(f32, f32, f32, f32); +// Make some of them array types to ensure those also work. +#[repr(simd)] struct i8x1_arr([i8; 1]); +#[repr(simd)] struct f32x4([f32; 4]); extern "platform-intrinsic" { #[rustc_const_stable(feature = "foo", since = "1.3.37")] @@ -25,6 +27,14 @@ fn main() { assert_eq!(X0, 42); assert_eq!(Y0, 42); } + { + const U: i8x1_arr = i8x1_arr([13]); + const V: i8x1_arr = unsafe { simd_insert(U, 0_u32, 42_i8) }; + const X0: i8 = V.0[0]; + const Y0: i8 = unsafe { simd_extract(V, 0) }; + assert_eq!(X0, 42); + assert_eq!(Y0, 42); + } { const U: u16x2 = u16x2(13, 14); const V: u16x2 = unsafe { simd_insert(U, 1_u32, 42_u16) }; @@ -38,12 +48,12 @@ fn main() { assert_eq!(Y1, 42); } { - const U: f32x4 = f32x4(13., 14., 15., 16.); + const U: f32x4 = f32x4([13., 14., 15., 16.]); const V: f32x4 = unsafe { simd_insert(U, 1_u32, 42_f32) }; - const X0: f32 = V.0; - const X1: f32 = V.1; - const X2: f32 = V.2; - const X3: f32 = V.3; + const X0: f32 = V.0[0]; + const X1: f32 = V.0[1]; + const X2: f32 = V.0[2]; + const X3: f32 = V.0[3]; const Y0: f32 = unsafe { simd_extract(V, 0) }; const Y1: f32 = unsafe { simd_extract(V, 1) }; const Y2: f32 = unsafe { simd_extract(V, 2) }; 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 f35f3c5e8e..a7d329f125 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,6 +1,5 @@ #![feature(const_mut_refs)] #![feature(raw_ref_op)] -#![feature(const_raw_ptr_deref)] const NULL: *mut i32 = std::ptr::null_mut(); const A: *const i32 = &4; 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 fb43ce2131..3a9ce79f10 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:11:21 + --> $DIR/mut_ref_in_final.rs:10:21 | LL | const B: *mut i32 = &mut 4; | ^^^^^^ error[E0716]: temporary value dropped while borrowed - --> $DIR/mut_ref_in_final.rs:17:40 + --> $DIR/mut_ref_in_final.rs:16: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:20:42 + --> $DIR/mut_ref_in_final.rs:19: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:35:65 + --> $DIR/mut_ref_in_final.rs:34: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:38:67 + --> $DIR/mut_ref_in_final.rs:37: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:41:71 + --> $DIR/mut_ref_in_final.rs:40: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 24d7bc4914..e0704e24a2 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,6 +1,5 @@ #![feature(const_mut_refs)] #![feature(raw_ref_op)] -#![feature(const_raw_ptr_deref)] // This file checks that our dynamic checks catch things that the static checks miss. // We do not have static checks for these, because we do not look into function bodies. 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 b3fcd6a7fe..7d6716787a 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,17 +1,17 @@ error[E0080]: evaluation of constant value failed - --> $DIR/mut_ref_in_final_dynamic_check.rs:14:10 + --> $DIR/mut_ref_in_final_dynamic_check.rs:13:10 | LL | Some(&mut *(42 as *mut i32)) | ^^^^^^^^^^^^^^^^^^^^^^ | | | 0x2a is not a valid pointer - | inside `helper` at $DIR/mut_ref_in_final_dynamic_check.rs:14:10 + | inside `helper` at $DIR/mut_ref_in_final_dynamic_check.rs:13:10 ... LL | const A: Option<&mut i32> = helper(); - | -------- inside `A` at $DIR/mut_ref_in_final_dynamic_check.rs:19:29 + | -------- inside `A` at $DIR/mut_ref_in_final_dynamic_check.rs:18:29 error: encountered dangling pointer in final constant - --> $DIR/mut_ref_in_final_dynamic_check.rs:26:1 + --> $DIR/mut_ref_in_final_dynamic_check.rs:25:1 | LL | const B: Option<&mut i32> = helper2(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/consts/const-suggest-feature.rs b/src/test/ui/consts/const-suggest-feature.rs index d11b91edb8..d76d01a3d5 100644 --- a/src/test/ui/consts/const-suggest-feature.rs +++ b/src/test/ui/consts/const-suggest-feature.rs @@ -1,7 +1,7 @@ const WRITE: () = unsafe { *std::ptr::null_mut() = 0; - //~^ ERROR dereferencing raw pointers in constants is unstable - //~| HELP add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable + //~^ ERROR dereferencing raw mutable pointers in constants is unstable + //~| HELP add `#![feature(const_mut_refs)]` to the crate attributes to enable }; fn main() {} diff --git a/src/test/ui/consts/const-suggest-feature.stderr b/src/test/ui/consts/const-suggest-feature.stderr index 1ccc3d754f..3bc1eacf32 100644 --- a/src/test/ui/consts/const-suggest-feature.stderr +++ b/src/test/ui/consts/const-suggest-feature.stderr @@ -1,11 +1,11 @@ -error[E0658]: dereferencing raw pointers in constants is unstable +error[E0658]: dereferencing raw mutable pointers in constants is unstable --> $DIR/const-suggest-feature.rs:2:5 | LL | *std::ptr::null_mut() = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #51911 <https://github.com/rust-lang/rust/issues/51911> for more information - = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable + = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable error: aborting due to previous error diff --git a/src/test/ui/consts/const_discriminant.rs b/src/test/ui/consts/const_discriminant.rs index a47f6af029..f623c5101f 100644 --- a/src/test/ui/consts/const_discriminant.rs +++ b/src/test/ui/consts/const_discriminant.rs @@ -25,6 +25,13 @@ enum SingleVariant { const TEST_V: Discriminant<SingleVariant> = discriminant(&SingleVariant::V); +pub const TEST_VOID: () = { + // This is UB, but CTFE does not check validity so it does not detect this. + // This is a regression test for https://github.com/rust-lang/rust/issues/89765. + unsafe { std::mem::discriminant(&*(&() as *const () as *const Void)); }; +}; + + fn main() { assert_eq!(TEST_A, TEST_A_OTHER); assert_eq!(TEST_A, discriminant(black_box(&Test::A(17)))); diff --git a/src/test/ui/eval-enum.rs b/src/test/ui/consts/eval-enum.rs similarity index 100% rename from src/test/ui/eval-enum.rs rename to src/test/ui/consts/eval-enum.rs diff --git a/src/test/ui/eval-enum.stderr b/src/test/ui/consts/eval-enum.stderr similarity index 100% rename from src/test/ui/eval-enum.stderr rename to src/test/ui/consts/eval-enum.stderr diff --git a/src/test/ui/consts/inline_asm.rs b/src/test/ui/consts/inline_asm.rs index fa9542f93a..b46ca6ba6d 100644 --- a/src/test/ui/consts/inline_asm.rs +++ b/src/test/ui/consts/inline_asm.rs @@ -1,3 +1,5 @@ +// needs-asm-support + #![feature(asm)] const _: () = unsafe { asm!("nop") }; diff --git a/src/test/ui/consts/inline_asm.stderr b/src/test/ui/consts/inline_asm.stderr index f38044a290..65a828d118 100644 --- a/src/test/ui/consts/inline_asm.stderr +++ b/src/test/ui/consts/inline_asm.stderr @@ -1,5 +1,5 @@ error[E0015]: inline assembly is not allowed in constants - --> $DIR/inline_asm.rs:3:24 + --> $DIR/inline_asm.rs:5:24 | LL | const _: () = unsafe { asm!("nop") }; | ^^^^^^^^^^^ diff --git a/src/test/ui/consts/int_ptr_for_zst_slices.rs b/src/test/ui/consts/int_ptr_for_zst_slices.rs index 34dafd00d2..34e5bb322b 100644 --- a/src/test/ui/consts/int_ptr_for_zst_slices.rs +++ b/src/test/ui/consts/int_ptr_for_zst_slices.rs @@ -1,6 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) - -#![feature(const_raw_ptr_deref)] +// check-pass const FOO: &str = unsafe { &*(1_usize as *const [u8; 0] as *const [u8] as *const str) }; diff --git a/src/test/ui/issues/issue-13902.rs b/src/test/ui/consts/issue-13902.rs similarity index 100% rename from src/test/ui/issues/issue-13902.rs rename to src/test/ui/consts/issue-13902.rs diff --git a/src/test/ui/issues/issue-17074.rs b/src/test/ui/consts/issue-17074.rs similarity index 100% rename from src/test/ui/issues/issue-17074.rs rename to src/test/ui/consts/issue-17074.rs diff --git a/src/test/ui/issues/issue-18294.rs b/src/test/ui/consts/issue-18294.rs similarity index 100% rename from src/test/ui/issues/issue-18294.rs rename to src/test/ui/consts/issue-18294.rs diff --git a/src/test/ui/issues/issue-18294.stderr b/src/test/ui/consts/issue-18294.stderr similarity index 100% rename from src/test/ui/issues/issue-18294.stderr rename to src/test/ui/consts/issue-18294.stderr diff --git a/src/test/ui/issues/issue-23968-const-not-overflow.rs b/src/test/ui/consts/issue-23968-const-not-overflow.rs similarity index 100% rename from src/test/ui/issues/issue-23968-const-not-overflow.rs rename to src/test/ui/consts/issue-23968-const-not-overflow.rs diff --git a/src/test/ui/issues/issue-37550.rs b/src/test/ui/consts/issue-37550-1.rs similarity index 100% rename from src/test/ui/issues/issue-37550.rs rename to src/test/ui/consts/issue-37550-1.rs diff --git a/src/test/ui/issues/issue-37550.stderr b/src/test/ui/consts/issue-37550-1.stderr similarity index 92% rename from src/test/ui/issues/issue-37550.stderr rename to src/test/ui/consts/issue-37550-1.stderr index 54b60df70f..f66d706787 100644 --- a/src/test/ui/issues/issue-37550.stderr +++ b/src/test/ui/consts/issue-37550-1.stderr @@ -1,5 +1,5 @@ error[E0658]: function pointers cannot appear in constant functions - --> $DIR/issue-37550.rs:3:9 + --> $DIR/issue-37550-1.rs:3:9 | LL | let x = || t; | ^ diff --git a/src/test/ui/issues/issue-37991.rs b/src/test/ui/consts/issue-37991.rs similarity index 100% rename from src/test/ui/issues/issue-37991.rs rename to src/test/ui/consts/issue-37991.rs diff --git a/src/test/ui/consts/issue-90878-2.rs b/src/test/ui/consts/issue-90878-2.rs new file mode 100644 index 0000000000..ac5640646a --- /dev/null +++ b/src/test/ui/consts/issue-90878-2.rs @@ -0,0 +1,10 @@ + #![l=|x|[b;x ]] //~ ERROR unexpected token: `|x| [b; x]` +//~^ ERROR cannot find attribute `l` in this scope + +// notice the space at the start, +// we can't attach any attributes to this file because it needs to be at the start + +// this example has been slightly modified (adding ]] at the end), so that it actually works here +// it still produces the same issue though + +fn main() {} diff --git a/src/test/ui/consts/issue-90878-2.stderr b/src/test/ui/consts/issue-90878-2.stderr new file mode 100644 index 0000000000..4ccce36eed --- /dev/null +++ b/src/test/ui/consts/issue-90878-2.stderr @@ -0,0 +1,14 @@ +error: unexpected token: `|x| [b; x]` + --> $DIR/issue-90878-2.rs:1:7 + | +LL | #![l=|x|[b;x ]] + | ^^^^^^^^^ + +error: cannot find attribute `l` in this scope + --> $DIR/issue-90878-2.rs:1:5 + | +LL | #![l=|x|[b;x ]] + | ^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/consts/issue-90878-3.rs b/src/test/ui/consts/issue-90878-3.rs new file mode 100644 index 0000000000..0e36646eb4 --- /dev/null +++ b/src/test/ui/consts/issue-90878-3.rs @@ -0,0 +1,6 @@ + +fn main() { + |x: usize| [0; x]; //~ ERROR attempt to use a non-constant value in a constant [E0435] + // (note the newline before "fn") +} +// ignore-tidy-leading-newlines diff --git a/src/test/ui/consts/issue-90878-3.stderr b/src/test/ui/consts/issue-90878-3.stderr new file mode 100644 index 0000000000..1bcc0eb378 --- /dev/null +++ b/src/test/ui/consts/issue-90878-3.stderr @@ -0,0 +1,11 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/issue-90878-3.rs:3:20 + | +LL | |x: usize| [0; x]; + | - ^ + | | + | this would need to be a `const` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0435`. diff --git a/src/test/ui/consts/issue-90878.rs b/src/test/ui/consts/issue-90878.rs new file mode 100644 index 0000000000..43f6fe5f38 --- /dev/null +++ b/src/test/ui/consts/issue-90878.rs @@ -0,0 +1,4 @@ + fn main() { + |x: usize| [0; x]; //~ ERROR attempt to use a non-constant value in a constant [E0435] + // (note the space before "fn") +} diff --git a/src/test/ui/consts/issue-90878.stderr b/src/test/ui/consts/issue-90878.stderr new file mode 100644 index 0000000000..c038fc622d --- /dev/null +++ b/src/test/ui/consts/issue-90878.stderr @@ -0,0 +1,11 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/issue-90878.rs:2:20 + | +LL | |x: usize| [0; x]; + | - ^ + | | + | this would need to be a `const` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0435`. diff --git a/src/test/ui/consts/issue-miri-1910.rs b/src/test/ui/consts/issue-miri-1910.rs new file mode 100644 index 0000000000..20efa145db --- /dev/null +++ b/src/test/ui/consts/issue-miri-1910.rs @@ -0,0 +1,12 @@ +// error-pattern unable to turn pointer into raw bytes +#![feature(const_ptr_read)] +#![feature(const_ptr_offset)] + +const C: () = unsafe { + let foo = Some(&42 as *const i32); + let one_and_a_half_pointers = std::mem::size_of::<*const i32>()/2*3; + (&foo as *const _ as *const u8).add(one_and_a_half_pointers).read(); +}; + +fn main() { +} diff --git a/src/test/ui/consts/issue-miri-1910.stderr b/src/test/ui/consts/issue-miri-1910.stderr new file mode 100644 index 0000000000..e2f4ef6358 --- /dev/null +++ b/src/test/ui/consts/issue-miri-1910.stderr @@ -0,0 +1,26 @@ +error: any use of this value will cause an error + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL + | +LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | unable to turn pointer into raw bytes + | inside `std::ptr::read::<u8>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL + | inside `ptr::const_ptr::<impl *const u8>::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | inside `C` at $DIR/issue-miri-1910.rs:8:5 + | + ::: $DIR/issue-miri-1910.rs:5:1 + | +LL | / const C: () = unsafe { +LL | | let foo = Some(&42 as *const i32); +LL | | let one_and_a_half_pointers = std::mem::size_of::<*const i32>()/2*3; +LL | | (&foo as *const _ as *const u8).add(one_and_a_half_pointers).read(); +LL | | }; + | |__- + | + = note: `#[deny(const_err)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> + +error: aborting due to previous error + diff --git a/src/test/ui/consts/min_const_fn/allow_raw_ptr_dereference_const_fn.rs b/src/test/ui/consts/min_const_fn/allow_raw_ptr_dereference_const_fn.rs index f4279e6b82..d221157556 100644 --- a/src/test/ui/consts/min_const_fn/allow_raw_ptr_dereference_const_fn.rs +++ b/src/test/ui/consts/min_const_fn/allow_raw_ptr_dereference_const_fn.rs @@ -1,5 +1,4 @@ // check-pass -#![feature(const_raw_ptr_deref)] use std::ptr; diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs index 719a7a9172..a6e1788bb7 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs +++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs @@ -1,10 +1,10 @@ const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } } -//~^ dereferencing raw pointers in constant functions +//~^ dereferencing raw mutable pointers in constant functions const unsafe fn bad_const_unsafe_deref_raw(x: *mut usize) -> usize { *x } -//~^ dereferencing raw pointers in constant functions +//~^ dereferencing raw mutable pointers in constant functions const unsafe fn bad_const_unsafe_deref_raw_ref(x: *mut usize) -> &'static usize { &*x } -//~^ dereferencing raw pointers in constant functions +//~^ dereferencing raw mutable pointers in constant functions fn main() {} diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr index 86ff4721c2..820b6433f3 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr @@ -1,29 +1,29 @@ -error[E0658]: dereferencing raw pointers in constant functions is unstable +error[E0658]: dereferencing raw mutable pointers in constant functions is unstable --> $DIR/min_const_fn_unsafe_bad.rs:1:77 | LL | const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } } | ^^^ | - = note: see issue #51911 <https://github.com/rust-lang/rust/issues/51911> for more information - = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable + = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable -error[E0658]: dereferencing raw pointers in constant functions is unstable +error[E0658]: dereferencing raw mutable pointers in constant functions is unstable --> $DIR/min_const_fn_unsafe_bad.rs:4:70 | LL | const unsafe fn bad_const_unsafe_deref_raw(x: *mut usize) -> usize { *x } | ^^ | - = note: see issue #51911 <https://github.com/rust-lang/rust/issues/51911> for more information - = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable + = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable -error[E0658]: dereferencing raw pointers in constant functions is unstable +error[E0658]: dereferencing raw mutable pointers in constant functions is unstable --> $DIR/min_const_fn_unsafe_bad.rs:7:83 | LL | const unsafe fn bad_const_unsafe_deref_raw_ref(x: *mut usize) -> &'static usize { &*x } | ^^^ | - = note: see issue #51911 <https://github.com/rust-lang/rust/issues/51911> for more information - = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable + = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable error: aborting due to 3 previous errors diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr index e5cd86b3d6..c48f59fe84 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr @@ -33,11 +33,6 @@ help: skipping check that does not even have a feature gate | LL | unsafe { *(&FOO as *const _ as *const usize) } | ^^^ -help: skipping check for `const_raw_ptr_deref` feature - --> $DIR/const_refers_to_static.rs:18:14 - | -LL | unsafe { *(&FOO as *const _ as *const usize) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate --> $DIR/const_refers_to_static.rs:22:32 | diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static2.32bit.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static2.32bit.stderr index 1a6ed0f43b..039b466ee0 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static2.32bit.stderr +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static2.32bit.stderr @@ -35,11 +35,6 @@ help: skipping check that does not even have a feature gate | 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 - | -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:21:6 | 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 index 4f268dd905..e0e2ec31ef 100644 --- 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 @@ -35,11 +35,6 @@ help: skipping check that does not even have a feature gate | 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 - | -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:21:6 | diff --git a/src/test/ui/consts/non-const-value-in-const.rs b/src/test/ui/consts/non-const-value-in-const.rs new file mode 100644 index 0000000000..1a20b1e09d --- /dev/null +++ b/src/test/ui/consts/non-const-value-in-const.rs @@ -0,0 +1,7 @@ +fn main() { + let x = 5; + const Y: i32 = x; //~ ERROR attempt to use a non-constant value in a constant [E0435] + + let x = 5; + let _ = [0; x]; //~ ERROR attempt to use a non-constant value in a constant [E0435] +} diff --git a/src/test/ui/consts/non-const-value-in-const.stderr b/src/test/ui/consts/non-const-value-in-const.stderr new file mode 100644 index 0000000000..0ce4b4b705 --- /dev/null +++ b/src/test/ui/consts/non-const-value-in-const.stderr @@ -0,0 +1,20 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/non-const-value-in-const.rs:3:20 + | +LL | const Y: i32 = x; + | ------- ^ non-constant value + | | + | help: consider using `let` instead of `const`: `let Y` + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/non-const-value-in-const.rs:6:17 + | +LL | let x = 5; + | ----- help: consider using `const` instead of `let`: `const x` +... +LL | let _ = [0; x]; + | ^ non-constant value + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0435`. diff --git a/src/test/ui/consts/offset_from.rs b/src/test/ui/consts/offset_from.rs index 8d501e0d95..4c9b1c1571 100644 --- a/src/test/ui/consts/offset_from.rs +++ b/src/test/ui/consts/offset_from.rs @@ -1,6 +1,5 @@ // run-pass -#![feature(const_raw_ptr_deref)] #![feature(const_ptr_offset_from)] struct Struct { diff --git a/src/test/ui/consts/offset_from_ub.rs b/src/test/ui/consts/offset_from_ub.rs index 4b55c299b5..cbc88bc4d9 100644 --- a/src/test/ui/consts/offset_from_ub.rs +++ b/src/test/ui/consts/offset_from_ub.rs @@ -1,4 +1,3 @@ -#![feature(const_raw_ptr_deref)] #![feature(const_ptr_offset_from)] #![feature(core_intrinsics)] diff --git a/src/test/ui/consts/offset_from_ub.stderr b/src/test/ui/consts/offset_from_ub.stderr index 2478ff081d..ffd6ad58c3 100644 --- a/src/test/ui/consts/offset_from_ub.stderr +++ b/src/test/ui/consts/offset_from_ub.stderr @@ -1,5 +1,5 @@ error[E0080]: evaluation of constant value failed - --> $DIR/offset_from_ub.rs:18:27 + --> $DIR/offset_from_ub.rs:17:27 | LL | let offset = unsafe { ptr_offset_from(field_ptr, base_ptr) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ptr_offset_from cannot compute offset of pointers into different allocations. @@ -13,25 +13,25 @@ LL | unsafe { intrinsics::ptr_offset_from(self, origin) } | 0x2a is not a valid pointer | inside `ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - ::: $DIR/offset_from_ub.rs:24:14 + ::: $DIR/offset_from_ub.rs:23:14 | LL | unsafe { (42 as *const u8).offset_from(&5u8) as usize } - | ----------------------------------- inside `NOT_PTR` at $DIR/offset_from_ub.rs:24:14 + | ----------------------------------- inside `NOT_PTR` at $DIR/offset_from_ub.rs:23:14 error[E0080]: evaluation of constant value failed - --> $DIR/offset_from_ub.rs:31:14 + --> $DIR/offset_from_ub.rs:30:14 | LL | unsafe { ptr_offset_from(field_ptr, base_ptr as *const u16) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ exact_div: 1_isize cannot be divided by 2_isize without remainder error[E0080]: evaluation of constant value failed - --> $DIR/offset_from_ub.rs:37:14 + --> $DIR/offset_from_ub.rs:36:14 | LL | unsafe { ptr_offset_from(ptr, ptr) } | ^^^^^^^^^^^^^^^^^^^^^^^^^ null pointer is not a valid pointer for this operation error[E0080]: evaluation of constant value failed - --> $DIR/offset_from_ub.rs:44:14 + --> $DIR/offset_from_ub.rs:43:14 | LL | unsafe { ptr_offset_from(ptr2, ptr1) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 0x10 is not a valid pointer diff --git a/src/test/ui/consts/precise-drop-with-promoted.rs b/src/test/ui/consts/precise-drop-with-promoted.rs new file mode 100644 index 0000000000..6f2317a5a2 --- /dev/null +++ b/src/test/ui/consts/precise-drop-with-promoted.rs @@ -0,0 +1,9 @@ +// Regression test for issue #89938. +// check-pass +// compile-flags: --crate-type=lib +#![feature(const_precise_live_drops)] + +pub const fn f() { + let _: Option<String> = None; + let _: &'static Option<String> = &None; +} diff --git a/src/test/ui/consts/promote-not.rs b/src/test/ui/consts/promote-not.rs index 9992653224..6830b23cfa 100644 --- a/src/test/ui/consts/promote-not.rs +++ b/src/test/ui/consts/promote-not.rs @@ -39,6 +39,8 @@ const TEST_INTERIOR_MUT: () = { let _val: &'static _ = &(Cell::new(1), 2).1; //~ ERROR temporary value dropped while borrowed }; +const TEST_DROP: String = String::new(); + fn main() { // We must not promote things with interior mutability. Not even if we "project it away". let _val: &'static _ = &(Cell::new(1), 2).0; //~ ERROR temporary value dropped while borrowed @@ -50,4 +52,17 @@ fn main() { let _val: &'static _ = &(1%0); //~ ERROR temporary value dropped while borrowed let _val: &'static _ = &(1%(1-1)); //~ ERROR temporary value dropped while borrowed let _val: &'static _ = &([1,2,3][4]+1); //~ ERROR temporary value dropped while borrowed + + // No promotion of temporaries that need to be dropped. + let _val: &'static _ = &TEST_DROP; + //~^ ERROR temporary value dropped while borrowed + let _val: &'static _ = &&TEST_DROP; + //~^ ERROR temporary value dropped while borrowed + //~| ERROR temporary value dropped while borrowed + let _val: &'static _ = &(&TEST_DROP,); + //~^ ERROR temporary value dropped while borrowed + //~| ERROR temporary value dropped while borrowed + let _val: &'static _ = &[&TEST_DROP; 1]; + //~^ ERROR temporary value dropped while borrowed + //~| ERROR temporary value dropped while borrowed } diff --git a/src/test/ui/consts/promote-not.stderr b/src/test/ui/consts/promote-not.stderr index 932109bd86..0d0b0f9c68 100644 --- a/src/test/ui/consts/promote-not.stderr +++ b/src/test/ui/consts/promote-not.stderr @@ -59,7 +59,7 @@ LL | }; | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:44:29 + --> $DIR/promote-not.rs:46:29 | LL | let _val: &'static _ = &(Cell::new(1), 2).0; | ---------- ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use @@ -70,7 +70,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:45:29 + --> $DIR/promote-not.rs:47:29 | LL | let _val: &'static _ = &(Cell::new(1), 2).1; | ---------- ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use @@ -81,7 +81,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:48:29 + --> $DIR/promote-not.rs:50:29 | LL | let _val: &'static _ = &(1/0); | ---------- ^^^^^ creates a temporary which is freed while still in use @@ -92,7 +92,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:49:29 + --> $DIR/promote-not.rs:51:29 | LL | let _val: &'static _ = &(1/(1-1)); | ---------- ^^^^^^^^^ creates a temporary which is freed while still in use @@ -103,7 +103,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:50:29 + --> $DIR/promote-not.rs:52:29 | LL | let _val: &'static _ = &(1%0); | ---------- ^^^^^ creates a temporary which is freed while still in use @@ -114,26 +114,102 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:51:29 + --> $DIR/promote-not.rs:53:29 | LL | let _val: &'static _ = &(1%(1-1)); | ---------- ^^^^^^^^^ creates a temporary which is freed while still in use | | | type annotation requires that borrow lasts for `'static` -LL | let _val: &'static _ = &([1,2,3][4]+1); +... LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:52:29 + --> $DIR/promote-not.rs:54:29 | LL | let _val: &'static _ = &([1,2,3][4]+1); | ---------- ^^^^^^^^^^^^^^ creates a temporary which is freed while still in use | | | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-not.rs:57:29 + | +LL | let _val: &'static _ = &TEST_DROP; + | ---------- ^^^^^^^^^ creates a temporary which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-not.rs:59:29 + | +LL | let _val: &'static _ = &&TEST_DROP; + | ---------- ^^^^^^^^^^ creates a temporary which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-not.rs:59:30 + | +LL | let _val: &'static _ = &&TEST_DROP; + | ---------- ^^^^^^^^^ creates a temporary which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-not.rs:62:29 + | +LL | let _val: &'static _ = &(&TEST_DROP,); + | ---------- ^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... LL | } | - temporary value is freed at the end of this statement -error: aborting due to 13 previous errors +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-not.rs:62:31 + | +LL | let _val: &'static _ = &(&TEST_DROP,); + | ---------- ^^^^^^^^^ creates a temporary which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-not.rs:65:29 + | +LL | let _val: &'static _ = &[&TEST_DROP; 1]; + | ---------- ^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-not.rs:65:31 + | +LL | let _val: &'static _ = &[&TEST_DROP; 1]; + | ---------- ^^^^^^^^^ - temporary value is freed at the end of this statement + | | | + | | creates a temporary which is freed while still in use + | type annotation requires that borrow lasts for `'static` + +error: aborting due to 20 previous errors For more information about this error, try `rustc --explain E0716`. diff --git a/src/test/ui/consts/promoted-const-drop.rs b/src/test/ui/consts/promoted-const-drop.rs new file mode 100644 index 0000000000..c896c011ab --- /dev/null +++ b/src/test/ui/consts/promoted-const-drop.rs @@ -0,0 +1,15 @@ +#![feature(const_trait_impl)] +#![feature(const_mut_refs)] + +struct A(); + +impl const Drop for A { + fn drop(&mut self) {} +} + +const C: A = A(); + +fn main() { + let _: &'static A = &A(); //~ ERROR temporary value dropped while borrowed + let _: &'static [A] = &[C]; //~ ERROR temporary value dropped while borrowed +} diff --git a/src/test/ui/consts/promoted-const-drop.stderr b/src/test/ui/consts/promoted-const-drop.stderr new file mode 100644 index 0000000000..184ba0ea3b --- /dev/null +++ b/src/test/ui/consts/promoted-const-drop.stderr @@ -0,0 +1,24 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted-const-drop.rs:13:26 + | +LL | let _: &'static A = &A(); + | ---------- ^^^ creates a temporary which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | let _: &'static [A] = &[C]; +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted-const-drop.rs:14:28 + | +LL | let _: &'static [A] = &[C]; + | ------------ ^^^ creates a temporary which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0716`. diff --git a/src/test/ui/consts/promoted-storage.rs b/src/test/ui/consts/promoted-storage.rs new file mode 100644 index 0000000000..52ef685e8f --- /dev/null +++ b/src/test/ui/consts/promoted-storage.rs @@ -0,0 +1,20 @@ +// Check that storage statements reset local qualification. +// check-pass +use std::cell::Cell; + +const C: Option<Cell<u32>> = { + let mut c = None; + let mut i = 0; + while i == 0 { + let mut x = None; + c = x; + x = Some(Cell::new(0)); + let _ = x; + i += 1; + } + c +}; + +fn main() { + let _: &'static _ = &C; +} diff --git a/src/test/ui/consts/ptr_comparisons.rs b/src/test/ui/consts/ptr_comparisons.rs index 971b7c3cb1..8161c7af96 100644 --- a/src/test/ui/consts/ptr_comparisons.rs +++ b/src/test/ui/consts/ptr_comparisons.rs @@ -8,7 +8,6 @@ core_intrinsics, const_raw_ptr_comparison, const_ptr_offset, - const_raw_ptr_deref )] const FOO: &usize = &42; diff --git a/src/test/ui/consts/ptr_comparisons.stderr b/src/test/ui/consts/ptr_comparisons.stderr index 48cd5da213..cfec25a719 100644 --- a/src/test/ui/consts/ptr_comparisons.stderr +++ b/src/test/ui/consts/ptr_comparisons.stderr @@ -7,19 +7,19 @@ LL | unsafe { intrinsics::offset(self, count) } | pointer arithmetic failed: alloc3 has size $WORD, so pointer to $TWO_WORDS bytes starting at offset 0 is out-of-bounds | inside `ptr::const_ptr::<impl *const usize>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - ::: $DIR/ptr_comparisons.rs:60:34 + ::: $DIR/ptr_comparisons.rs:59:34 | LL | const _: *const usize = unsafe { (FOO as *const usize).offset(2) }; - | ------------------------------- inside `_` at $DIR/ptr_comparisons.rs:60:34 + | ------------------------------- inside `_` at $DIR/ptr_comparisons.rs:59:34 error[E0080]: evaluation of constant value failed - --> $DIR/ptr_comparisons.rs:63:33 + --> $DIR/ptr_comparisons.rs:62:33 | LL | unsafe { std::ptr::addr_of!((*(FOO as *const usize as *const [u8; 1000]))[999]) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: alloc3 has size $WORD, so pointer to 1000 bytes starting at offset 0 is out-of-bounds error: any use of this value will cause an error - --> $DIR/ptr_comparisons.rs:67:27 + --> $DIR/ptr_comparisons.rs:66:27 | LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 }; | --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -31,7 +31,7 @@ LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + = 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/ptr_comparisons.rs:72:27 + --> $DIR/ptr_comparisons.rs:71:27 | LL | const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4 }; | --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- diff --git a/src/test/ui/consts/qualif-indirect-mutation-fail.rs b/src/test/ui/consts/qualif-indirect-mutation-fail.rs new file mode 100644 index 0000000000..f74a25a346 --- /dev/null +++ b/src/test/ui/consts/qualif-indirect-mutation-fail.rs @@ -0,0 +1,64 @@ +// compile-flags: --crate-type=lib +#![feature(const_mut_refs)] +#![feature(const_precise_live_drops)] +#![feature(const_swap)] +#![feature(raw_ref_op)] + +// Mutable borrow of a field with drop impl. +pub const fn f() { + let mut a: (u32, Option<String>) = (0, None); //~ ERROR destructors cannot be evaluated + let _ = &mut a.1; +} + +// Mutable borrow of a type with drop impl. +pub const A1: () = { + let mut x = None; //~ ERROR destructors cannot be evaluated + let mut y = Some(String::new()); + let a = &mut x; + let b = &mut y; + std::mem::swap(a, b); + std::mem::forget(y); +}; + +// Mutable borrow of a type with drop impl. +pub const A2: () = { + let mut x = None; + let mut y = Some(String::new()); + let a = &mut x; + let b = &mut y; + std::mem::swap(a, b); + std::mem::forget(y); + let _z = x; //~ ERROR destructors cannot be evaluated +}; + +// Shared borrow of a type that might be !Freeze and Drop. +pub const fn g1<T>() { + let x: Option<T> = None; //~ ERROR destructors cannot be evaluated + let _ = x.is_some(); +} + +// Shared borrow of a type that might be !Freeze and Drop. +pub const fn g2<T>() { + let x: Option<T> = None; + let _ = x.is_some(); + let _y = x; //~ ERROR destructors cannot be evaluated +} + +// Mutable raw reference to a Drop type. +pub const fn address_of_mut() { + let mut x: Option<String> = None; //~ ERROR destructors cannot be evaluated + &raw mut x; + + let mut y: Option<String> = None; //~ ERROR destructors cannot be evaluated + std::ptr::addr_of_mut!(y); +} + +// Const raw reference to a Drop type. Conservatively assumed to allow mutation +// until resolution of https://github.com/rust-lang/rust/issues/56604. +pub const fn address_of_const() { + let x: Option<String> = None; //~ ERROR destructors cannot be evaluated + &raw const x; + + let y: Option<String> = None; //~ ERROR destructors cannot be evaluated + std::ptr::addr_of!(y); +} diff --git a/src/test/ui/consts/qualif-indirect-mutation-fail.stderr b/src/test/ui/consts/qualif-indirect-mutation-fail.stderr new file mode 100644 index 0000000000..713df12b7a --- /dev/null +++ b/src/test/ui/consts/qualif-indirect-mutation-fail.stderr @@ -0,0 +1,57 @@ +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/qualif-indirect-mutation-fail.rs:9:9 + | +LL | let mut a: (u32, Option<String>) = (0, None); + | ^^^^^ constant functions cannot evaluate destructors + +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/qualif-indirect-mutation-fail.rs:15:9 + | +LL | let mut x = None; + | ^^^^^ constants cannot evaluate destructors + +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/qualif-indirect-mutation-fail.rs:31:9 + | +LL | let _z = x; + | ^^ constants cannot evaluate destructors + +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/qualif-indirect-mutation-fail.rs:36:9 + | +LL | let x: Option<T> = None; + | ^ constant functions cannot evaluate destructors + +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/qualif-indirect-mutation-fail.rs:44:9 + | +LL | let _y = x; + | ^^ constant functions cannot evaluate destructors + +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/qualif-indirect-mutation-fail.rs:52:9 + | +LL | let mut y: Option<String> = None; + | ^^^^^ constant functions cannot evaluate destructors + +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/qualif-indirect-mutation-fail.rs:49:9 + | +LL | let mut x: Option<String> = None; + | ^^^^^ constant functions cannot evaluate destructors + +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/qualif-indirect-mutation-fail.rs:62:9 + | +LL | let y: Option<String> = None; + | ^ constant functions cannot evaluate destructors + +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/qualif-indirect-mutation-fail.rs:59:9 + | +LL | let x: Option<String> = None; + | ^ constant functions cannot evaluate destructors + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0493`. diff --git a/src/test/ui/consts/qualif-indirect-mutation-pass.rs b/src/test/ui/consts/qualif-indirect-mutation-pass.rs new file mode 100644 index 0000000000..06af6a03b8 --- /dev/null +++ b/src/test/ui/consts/qualif-indirect-mutation-pass.rs @@ -0,0 +1,24 @@ +// compile-flags: --crate-type=lib +// check-pass +#![feature(const_mut_refs)] +#![feature(const_precise_live_drops)] + +// Mutable reference allows only mutation of !Drop place. +pub const fn f() { + let mut x: (Option<String>, u32) = (None, 0); + let mut a = 10; + *(&mut a) = 11; + x.1 = a; +} + +// Mutable reference allows only mutation of !Drop place. +pub const fn g() { + let mut a: (u32, Option<String>) = (0, None); + let _ = &mut a.0; +} + +// Shared reference does not allow for mutation. +pub const fn h() { + let x: Option<String> = None; + let _ = &x; +} diff --git a/src/test/ui/consts/qualif-union.rs b/src/test/ui/consts/qualif-union.rs new file mode 100644 index 0000000000..2054b5b89e --- /dev/null +++ b/src/test/ui/consts/qualif-union.rs @@ -0,0 +1,32 @@ +// Checks that unions use type based qualification. Regression test for issue #90268. +#![feature(untagged_unions)] +use std::cell::Cell; + +union U { i: u32, c: Cell<u32> } + +const C1: Cell<u32> = { + unsafe { U { c: Cell::new(0) }.c } +}; + +const C2: Cell<u32> = { + unsafe { U { i : 0 }.c } +}; + +const C3: Cell<u32> = { + let mut u = U { i: 0 }; + u.i = 1; + unsafe { u.c } +}; + +const C4: U = U { i: 0 }; + +const C5: [U; 1] = [U {i : 0}; 1]; + +fn main() { + // Interior mutability should prevent promotion. + let _: &'static _ = &C1; //~ ERROR temporary value dropped while borrowed + let _: &'static _ = &C2; //~ ERROR temporary value dropped while borrowed + let _: &'static _ = &C3; //~ ERROR temporary value dropped while borrowed + let _: &'static _ = &C4; //~ ERROR temporary value dropped while borrowed + let _: &'static _ = &C5; //~ ERROR temporary value dropped while borrowed +} diff --git a/src/test/ui/consts/qualif-union.stderr b/src/test/ui/consts/qualif-union.stderr new file mode 100644 index 0000000000..fda8ad4a3b --- /dev/null +++ b/src/test/ui/consts/qualif-union.stderr @@ -0,0 +1,57 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/qualif-union.rs:27:26 + | +LL | let _: &'static _ = &C1; + | ---------- ^^ creates a temporary which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/qualif-union.rs:28:26 + | +LL | let _: &'static _ = &C2; + | ---------- ^^ creates a temporary which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/qualif-union.rs:29:26 + | +LL | let _: &'static _ = &C3; + | ---------- ^^ creates a temporary which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/qualif-union.rs:30:26 + | +LL | let _: &'static _ = &C4; + | ---------- ^^ creates a temporary which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | let _: &'static _ = &C5; +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/qualif-union.rs:31:26 + | +LL | let _: &'static _ = &C5; + | ---------- ^^ creates a temporary which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0716`. diff --git a/src/test/ui/consts/validate_never_arrays.rs b/src/test/ui/consts/validate_never_arrays.rs index 1990fb0739..a02e386c66 100644 --- a/src/test/ui/consts/validate_never_arrays.rs +++ b/src/test/ui/consts/validate_never_arrays.rs @@ -1,5 +1,5 @@ // stderr-per-bitwidth -#![feature(const_raw_ptr_deref, never_type)] +#![feature(never_type)] const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; //~ ERROR undefined behavior const _: &[!; 0] = unsafe { &*(1_usize as *const [!; 0]) }; // ok diff --git a/src/test/ui/consts/write_to_mut_ref_dest.mut_refs.stderr b/src/test/ui/consts/write_to_mut_ref_dest.mut_refs.stderr deleted file mode 100644 index 3ee5090746..0000000000 --- a/src/test/ui/consts/write_to_mut_ref_dest.mut_refs.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: dereferencing raw pointers in constants is unstable - --> $DIR/write_to_mut_ref_dest.rs:11:18 - | -LL | unsafe { *b = 5; } - | ^^^^^^ - | - = note: see issue #51911 <https://github.com/rust-lang/rust/issues/51911> for more information - = help: add `#![feature(const_raw_ptr_deref)]` 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/write_to_mut_ref_dest.rs b/src/test/ui/consts/write_to_mut_ref_dest.rs index d35df330bb..484ec42443 100644 --- a/src/test/ui/consts/write_to_mut_ref_dest.rs +++ b/src/test/ui/consts/write_to_mut_ref_dest.rs @@ -1,4 +1,5 @@ // revisions: stock mut_refs +//[mut_refs] check-pass #![cfg_attr(mut_refs, feature(const_mut_refs))] @@ -8,7 +9,7 @@ const FOO: &u32 = { let mut a = 42; { let b: *mut u32 = &mut a; //[stock]~ ERROR mutable references are not allowed in constants - unsafe { *b = 5; } //~ ERROR dereferencing raw pointers in constants + unsafe { *b = 5; } //[stock]~ ERROR dereferencing raw mutable pointers in constants } &{a} }; diff --git a/src/test/ui/consts/write_to_mut_ref_dest.stock.stderr b/src/test/ui/consts/write_to_mut_ref_dest.stock.stderr index 2b6d1d3267..bb10592760 100644 --- a/src/test/ui/consts/write_to_mut_ref_dest.stock.stderr +++ b/src/test/ui/consts/write_to_mut_ref_dest.stock.stderr @@ -1,5 +1,5 @@ error[E0658]: mutable references are not allowed in constants - --> $DIR/write_to_mut_ref_dest.rs:10:27 + --> $DIR/write_to_mut_ref_dest.rs:11:27 | LL | let b: *mut u32 = &mut a; | ^^^^^^ @@ -7,14 +7,14 @@ LL | let b: *mut u32 = &mut a; = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable -error[E0658]: dereferencing raw pointers in constants is unstable - --> $DIR/write_to_mut_ref_dest.rs:11:18 +error[E0658]: dereferencing raw mutable pointers in constants is unstable + --> $DIR/write_to_mut_ref_dest.rs:12:18 | LL | unsafe { *b = 5; } | ^^^^^^ | - = note: see issue #51911 <https://github.com/rust-lang/rust/issues/51911> for more information - = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable + = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable error: aborting due to 2 previous errors diff --git a/vendor/gimli/rustfmt.toml b/src/test/ui/crate-loading/auxiliary/libfoo.rlib similarity index 100% rename from vendor/gimli/rustfmt.toml rename to src/test/ui/crate-loading/auxiliary/libfoo.rlib diff --git a/src/test/ui/crate-loading/invalid-rlib.rs b/src/test/ui/crate-loading/invalid-rlib.rs new file mode 100644 index 0000000000..77c29090a3 --- /dev/null +++ b/src/test/ui/crate-loading/invalid-rlib.rs @@ -0,0 +1,8 @@ +// compile-flags: --crate-type lib --extern foo={{src-base}}/crate-loading/auxiliary/libfoo.rlib +// normalize-stderr-test: "failed to mmap file '.*auxiliary/libfoo.rlib':.*" -> "failed to mmap file 'auxiliary/libfoo.rlib'" +// don't emit warn logging, it's basically the same as the errors and it's annoying to normalize +// rustc-env:RUSTC_LOG=error +// edition:2018 +#![no_std] +use ::foo; //~ ERROR invalid metadata files for crate `foo` +//~| NOTE failed to mmap file diff --git a/src/test/ui/crate-loading/invalid-rlib.stderr b/src/test/ui/crate-loading/invalid-rlib.stderr new file mode 100644 index 0000000000..b2c79f742f --- /dev/null +++ b/src/test/ui/crate-loading/invalid-rlib.stderr @@ -0,0 +1,11 @@ +error[E0786]: found invalid metadata files for crate `foo` + --> $DIR/invalid-rlib.rs:7:7 + | +LL | use ::foo; + | ^^^ + | + = note: failed to mmap file 'auxiliary/libfoo.rlib' + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0786`. diff --git a/src/test/ui/cross/cross-fn-cache-hole.rs b/src/test/ui/cross/cross-fn-cache-hole.rs index 249c6474c9..c38a5001ac 100644 --- a/src/test/ui/cross/cross-fn-cache-hole.rs +++ b/src/test/ui/cross/cross-fn-cache-hole.rs @@ -12,8 +12,8 @@ trait Bar<X> { } // We don't always check where clauses for sanity, but in this case // wfcheck does report an error here: -fn vacuous<A>() //~ ERROR the trait bound `i32: Bar<u32>` is not satisfied - where i32: Foo<u32, A> +fn vacuous<A>() + where i32: Foo<u32, A> //~ ERROR the trait bound `i32: Bar<u32>` is not satisfied { // ... the original intention was to check that we don't use that // vacuous where clause (which could never be satisfied) to accept diff --git a/src/test/ui/cross/cross-fn-cache-hole.stderr b/src/test/ui/cross/cross-fn-cache-hole.stderr index 0d325bb7ec..7e15562b08 100644 --- a/src/test/ui/cross/cross-fn-cache-hole.stderr +++ b/src/test/ui/cross/cross-fn-cache-hole.stderr @@ -1,14 +1,8 @@ error[E0277]: the trait bound `i32: Bar<u32>` is not satisfied - --> $DIR/cross-fn-cache-hole.rs:15:1 + --> $DIR/cross-fn-cache-hole.rs:16:11 | -LL | / fn vacuous<A>() -LL | | where i32: Foo<u32, A> -LL | | { -LL | | // ... the original intention was to check that we don't use that -... | -LL | | require::<i32, u32>(); -LL | | } - | |_^ the trait `Bar<u32>` is not implemented for `i32` +LL | where i32: Foo<u32, A> + | ^^^^^^^^^^^^^^^^ the trait `Bar<u32>` is not implemented for `i32` | = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable diff --git a/src/test/ui/deprecation/deprecation-lint.rs b/src/test/ui/deprecation/deprecation-lint.rs index 35e42a6857..9bde2ca194 100644 --- a/src/test/ui/deprecation/deprecation-lint.rs +++ b/src/test/ui/deprecation/deprecation-lint.rs @@ -278,6 +278,7 @@ mod this_crate { let _ = nested::DeprecatedStruct { //~^ ERROR use of deprecated struct `this_crate::nested::DeprecatedStruct`: text i: 0 //~ ERROR use of deprecated field `this_crate::nested::DeprecatedStruct::i`: text + //~| ERROR field `i` of struct `this_crate::nested::DeprecatedStruct` is private }; let _ = nested::DeprecatedUnitStruct; //~ ERROR use of deprecated unit struct `this_crate::nested::DeprecatedUnitStruct`: text diff --git a/src/test/ui/deprecation/deprecation-lint.stderr b/src/test/ui/deprecation/deprecation-lint.stderr index 20af4f62e6..5d716fa625 100644 --- a/src/test/ui/deprecation/deprecation-lint.stderr +++ b/src/test/ui/deprecation/deprecation-lint.stderr @@ -257,97 +257,97 @@ LL | let _ = nested::DeprecatedStruct { | ^^^^^^^^^^^^^^^^ error: use of deprecated unit struct `this_crate::nested::DeprecatedUnitStruct`: text - --> $DIR/deprecation-lint.rs:283:25 + --> $DIR/deprecation-lint.rs:284:25 | LL | let _ = nested::DeprecatedUnitStruct; | ^^^^^^^^^^^^^^^^^^^^ error: use of deprecated unit variant `this_crate::nested::Enum::DeprecatedVariant`: text - --> $DIR/deprecation-lint.rs:285:31 + --> $DIR/deprecation-lint.rs:286:31 | LL | ... let _ = nested::Enum::DeprecatedVariant; | ^^^^^^^^^^^^^^^^^ error: use of deprecated tuple struct `this_crate::nested::DeprecatedTupleStruct`: text - --> $DIR/deprecation-lint.rs:287:25 + --> $DIR/deprecation-lint.rs:288:25 | LL | ... let _ = nested::DeprecatedTupleStruct (1); | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:292:16 + --> $DIR/deprecation-lint.rs:293:16 | LL | Trait::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:294:25 + --> $DIR/deprecation-lint.rs:295:25 | LL | <Foo as Trait>::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:296:16 + --> $DIR/deprecation-lint.rs:297:16 | LL | Trait::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:298:25 + --> $DIR/deprecation-lint.rs:299:25 | LL | ... <Foo as Trait>::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated function `this_crate::test_fn_closure_body::{closure#0}::bar` - --> $DIR/deprecation-lint.rs:316:13 + --> $DIR/deprecation-lint.rs:317:13 | LL | bar(); | ^^^ error: use of deprecated trait `this_crate::DeprecatedTrait`: text - --> $DIR/deprecation-lint.rs:335:10 + --> $DIR/deprecation-lint.rs:336:10 | LL | impl DeprecatedTrait for S { } | ^^^^^^^^^^^^^^^ error: use of deprecated trait `this_crate::DeprecatedTrait`: text - --> $DIR/deprecation-lint.rs:337:24 + --> $DIR/deprecation-lint.rs:338:24 | LL | trait LocalTrait : DeprecatedTrait { } | ^^^^^^^^^^^^^^^ error: use of deprecated struct `this_crate2::Deprecated`: text - --> $DIR/deprecation-lint.rs:389:17 + --> $DIR/deprecation-lint.rs:390:17 | LL | let x = Deprecated { | ^^^^^^^^^^ error: use of deprecated struct `this_crate2::Deprecated`: text - --> $DIR/deprecation-lint.rs:398:13 + --> $DIR/deprecation-lint.rs:399:13 | LL | let Deprecated { | ^^^^^^^^^^ error: use of deprecated struct `this_crate2::Deprecated`: text - --> $DIR/deprecation-lint.rs:404:13 + --> $DIR/deprecation-lint.rs:405:13 | LL | let Deprecated | ^^^^^^^^^^ error: use of deprecated tuple struct `this_crate2::Deprecated2`: text - --> $DIR/deprecation-lint.rs:409:17 + --> $DIR/deprecation-lint.rs:410:17 | LL | let x = Deprecated2(1, 2, 3); | ^^^^^^^^^^^ error: use of deprecated tuple struct `this_crate2::Deprecated2`: text - --> $DIR/deprecation-lint.rs:419:13 + --> $DIR/deprecation-lint.rs:420:13 | LL | let Deprecated2 | ^^^^^^^^^^^ error: use of deprecated tuple struct `this_crate2::Deprecated2`: text - --> $DIR/deprecation-lint.rs:428:13 + --> $DIR/deprecation-lint.rs:429:13 | LL | let Deprecated2 | ^^^^^^^^^^^ @@ -617,124 +617,131 @@ LL | i: 0 | ^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:291:13 + --> $DIR/deprecation-lint.rs:292:13 | LL | foo.trait_deprecated(); | ^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:293:16 + --> $DIR/deprecation-lint.rs:294:16 | LL | <Foo>::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:295:13 + --> $DIR/deprecation-lint.rs:296:13 | LL | foo.trait_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:297:16 + --> $DIR/deprecation-lint.rs:298:16 | LL | <Foo>::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:302:13 + --> $DIR/deprecation-lint.rs:303:13 | LL | foo.trait_deprecated(); | ^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:303:13 + --> $DIR/deprecation-lint.rs:304:13 | LL | foo.trait_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated field `this_crate2::Stable::override2`: text - --> $DIR/deprecation-lint.rs:362:13 + --> $DIR/deprecation-lint.rs:363:13 | LL | override2: 3, | ^^^^^^^^^^^^ error: use of deprecated field `this_crate2::Stable::override2`: text - --> $DIR/deprecation-lint.rs:366:17 + --> $DIR/deprecation-lint.rs:367:17 | LL | let _ = x.override2; | ^^^^^^^^^^^ error: use of deprecated field `this_crate2::Stable::override2`: text - --> $DIR/deprecation-lint.rs:370:13 + --> $DIR/deprecation-lint.rs:371:13 | LL | override2: _ | ^^^^^^^^^^^^ error: use of deprecated field `this_crate2::Stable2::2`: text - --> $DIR/deprecation-lint.rs:378:17 + --> $DIR/deprecation-lint.rs:379:17 | LL | let _ = x.2; | ^^^ error: use of deprecated field `this_crate2::Stable2::2`: text - --> $DIR/deprecation-lint.rs:383:20 + --> $DIR/deprecation-lint.rs:384:20 | LL | _) | ^ error: use of deprecated field `this_crate2::Deprecated::inherit`: text - --> $DIR/deprecation-lint.rs:391:13 + --> $DIR/deprecation-lint.rs:392:13 | LL | inherit: 1, | ^^^^^^^^^^ error: use of deprecated field `this_crate2::Deprecated::inherit`: text - --> $DIR/deprecation-lint.rs:395:17 + --> $DIR/deprecation-lint.rs:396:17 | LL | let _ = x.inherit; | ^^^^^^^^^ error: use of deprecated field `this_crate2::Deprecated::inherit`: text - --> $DIR/deprecation-lint.rs:400:13 + --> $DIR/deprecation-lint.rs:401:13 | LL | inherit: _, | ^^^^^^^^^^ error: use of deprecated field `this_crate2::Deprecated2::0`: text - --> $DIR/deprecation-lint.rs:412:17 + --> $DIR/deprecation-lint.rs:413:17 | LL | let _ = x.0; | ^^^ error: use of deprecated field `this_crate2::Deprecated2::1`: text - --> $DIR/deprecation-lint.rs:414:17 + --> $DIR/deprecation-lint.rs:415:17 | LL | let _ = x.1; | ^^^ error: use of deprecated field `this_crate2::Deprecated2::2`: text - --> $DIR/deprecation-lint.rs:416:17 + --> $DIR/deprecation-lint.rs:417:17 | LL | let _ = x.2; | ^^^ error: use of deprecated field `this_crate2::Deprecated2::0`: text - --> $DIR/deprecation-lint.rs:421:14 + --> $DIR/deprecation-lint.rs:422:14 | LL | (_, | ^ error: use of deprecated field `this_crate2::Deprecated2::1`: text - --> $DIR/deprecation-lint.rs:423:14 + --> $DIR/deprecation-lint.rs:424:14 | LL | _, | ^ error: use of deprecated field `this_crate2::Deprecated2::2`: text - --> $DIR/deprecation-lint.rs:425:14 + --> $DIR/deprecation-lint.rs:426:14 | LL | _) | ^ -error: aborting due to 122 previous errors +error[E0451]: field `i` of struct `this_crate::nested::DeprecatedStruct` is private + --> $DIR/deprecation-lint.rs:280:13 + | +LL | i: 0 + | ^^^^ private field + +error: aborting due to 123 previous errors +For more information about this error, try `rustc --explain E0451`. diff --git a/src/test/ui/deprecation/invalid-literal.stderr b/src/test/ui/deprecation/invalid-literal.stderr index f15be95db1..b56eedeb80 100644 --- a/src/test/ui/deprecation/invalid-literal.stderr +++ b/src/test/ui/deprecation/invalid-literal.stderr @@ -6,12 +6,12 @@ LL | #[deprecated = b"test"] | help: the following are the possible correct uses | -LL | #[deprecated] - | ~~~~~~~~~~~~~ -LL | #[deprecated(/*opt*/ since = "version", /*opt*/ note = "reason")] - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LL | #[deprecated = "reason"] | ~~~~~~~~~~~~~~~~~~~~~~~~ +LL | #[deprecated(/*opt*/ since = "version", /*opt*/ note = "reason")] + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | #[deprecated] + | ~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/try-macro-suggestion.rs b/src/test/ui/deprecation/try-macro-suggestion.rs similarity index 100% rename from src/test/ui/try-macro-suggestion.rs rename to src/test/ui/deprecation/try-macro-suggestion.rs diff --git a/src/test/ui/try-macro-suggestion.stderr b/src/test/ui/deprecation/try-macro-suggestion.stderr similarity index 100% rename from src/test/ui/try-macro-suggestion.stderr rename to src/test/ui/deprecation/try-macro-suggestion.stderr 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 1080f94773..45a906a394 100644 --- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr +++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr @@ -13,12 +13,16 @@ LL | struct NotClone; LL | Bar::<NotClone> { x: 1 }.clone(); | ^^^^^ method cannot be called on `Bar<NotClone>` due to unsatisfied trait bounds | - = note: the following trait bounds were not satisfied: - `NotClone: Clone` - which is required by `Bar<NotClone>: Clone` +note: the following trait bounds were not satisfied because of the requirements of the implementation of `Clone` for `_`: + `NotClone: Clone` + --> $DIR/derive-assoc-type-not-impl.rs:6:10 + | +LL | #[derive(Clone)] + | ^^^^^ = 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: candidate #1: `Clone` + = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `NotClone` with `#[derive(Clone)]` | LL | #[derive(Clone)] diff --git a/src/test/ui/derives/derives-span-Clone-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-Clone-enum-struct-variant.stderr index c5bc50e407..cc874576cb 100644 --- a/src/test/ui/derives/derives-span-Clone-enum-struct-variant.stderr +++ b/src/test/ui/derives/derives-span-Clone-enum-struct-variant.stderr @@ -7,11 +7,6 @@ LL | #[derive(Clone)] LL | x: Error | ^^^^^^^^ the trait `Clone` is not implemented for `Error` | -note: required by `clone` - --> $SRC_DIR/core/src/clone.rs:LL:COL - | -LL | fn clone(&self) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-Clone-enum.stderr b/src/test/ui/derives/derives-span-Clone-enum.stderr index a6dc818eb6..a4870635de 100644 --- a/src/test/ui/derives/derives-span-Clone-enum.stderr +++ b/src/test/ui/derives/derives-span-Clone-enum.stderr @@ -7,11 +7,6 @@ LL | #[derive(Clone)] LL | Error | ^^^^^ the trait `Clone` is not implemented for `Error` | -note: required by `clone` - --> $SRC_DIR/core/src/clone.rs:LL:COL - | -LL | fn clone(&self) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-Clone-struct.stderr b/src/test/ui/derives/derives-span-Clone-struct.stderr index cf7b9ec276..4507eeccc3 100644 --- a/src/test/ui/derives/derives-span-Clone-struct.stderr +++ b/src/test/ui/derives/derives-span-Clone-struct.stderr @@ -7,11 +7,6 @@ LL | struct Struct { LL | x: Error | ^^^^^^^^ the trait `Clone` is not implemented for `Error` | -note: required by `clone` - --> $SRC_DIR/core/src/clone.rs:LL:COL - | -LL | fn clone(&self) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-Clone-tuple-struct.stderr b/src/test/ui/derives/derives-span-Clone-tuple-struct.stderr index 80733d6273..a79be7f574 100644 --- a/src/test/ui/derives/derives-span-Clone-tuple-struct.stderr +++ b/src/test/ui/derives/derives-span-Clone-tuple-struct.stderr @@ -7,11 +7,6 @@ LL | struct Struct( LL | Error | ^^^^^ the trait `Clone` is not implemented for `Error` | -note: required by `clone` - --> $SRC_DIR/core/src/clone.rs:LL:COL - | -LL | fn clone(&self) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-Default-struct.stderr b/src/test/ui/derives/derives-span-Default-struct.stderr index c60b6ac456..dd2cfaf89b 100644 --- a/src/test/ui/derives/derives-span-Default-struct.stderr +++ b/src/test/ui/derives/derives-span-Default-struct.stderr @@ -7,11 +7,6 @@ LL | struct Struct { LL | x: Error | ^^^^^^^^ the trait `Default` is not implemented for `Error` | -note: required by `std::default::Default::default` - --> $SRC_DIR/core/src/default.rs:LL:COL - | -LL | fn default() -> Self; - | ^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-Default-tuple-struct.stderr b/src/test/ui/derives/derives-span-Default-tuple-struct.stderr index ed342f539d..0674d635d3 100644 --- a/src/test/ui/derives/derives-span-Default-tuple-struct.stderr +++ b/src/test/ui/derives/derives-span-Default-tuple-struct.stderr @@ -7,11 +7,6 @@ LL | struct Struct( LL | Error | ^^^^^ the trait `Default` is not implemented for `Error` | -note: required by `std::default::Default::default` - --> $SRC_DIR/core/src/default.rs:LL:COL - | -LL | fn default() -> Self; - | ^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-Hash-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-Hash-enum-struct-variant.stderr index 47c7f1c2c3..7f24be959f 100644 --- a/src/test/ui/derives/derives-span-Hash-enum-struct-variant.stderr +++ b/src/test/ui/derives/derives-span-Hash-enum-struct-variant.stderr @@ -7,11 +7,6 @@ LL | #[derive(Hash)] LL | x: Error | ^^^^^^^^ the trait `Hash` is not implemented for `Error` | -note: required by a bound in `std::hash::Hash::hash` - --> $SRC_DIR/core/src/hash/mod.rs:LL:COL - | -LL | fn hash<H: Hasher>(&self, state: &mut H); - | ^ required by this bound in `std::hash::Hash::hash` = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-Hash-enum.stderr b/src/test/ui/derives/derives-span-Hash-enum.stderr index 92f084b58e..ae2921a16b 100644 --- a/src/test/ui/derives/derives-span-Hash-enum.stderr +++ b/src/test/ui/derives/derives-span-Hash-enum.stderr @@ -7,11 +7,6 @@ LL | #[derive(Hash)] LL | Error | ^^^^^ the trait `Hash` is not implemented for `Error` | -note: required by a bound in `std::hash::Hash::hash` - --> $SRC_DIR/core/src/hash/mod.rs:LL:COL - | -LL | fn hash<H: Hasher>(&self, state: &mut H); - | ^ required by this bound in `std::hash::Hash::hash` = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-Hash-struct.stderr b/src/test/ui/derives/derives-span-Hash-struct.stderr index c57cebe04e..37b3af702a 100644 --- a/src/test/ui/derives/derives-span-Hash-struct.stderr +++ b/src/test/ui/derives/derives-span-Hash-struct.stderr @@ -7,11 +7,6 @@ LL | struct Struct { LL | x: Error | ^^^^^^^^ the trait `Hash` is not implemented for `Error` | -note: required by a bound in `std::hash::Hash::hash` - --> $SRC_DIR/core/src/hash/mod.rs:LL:COL - | -LL | fn hash<H: Hasher>(&self, state: &mut H); - | ^ required by this bound in `std::hash::Hash::hash` = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-Hash-tuple-struct.stderr b/src/test/ui/derives/derives-span-Hash-tuple-struct.stderr index 200937f0c9..18624667d2 100644 --- a/src/test/ui/derives/derives-span-Hash-tuple-struct.stderr +++ b/src/test/ui/derives/derives-span-Hash-tuple-struct.stderr @@ -7,11 +7,6 @@ LL | struct Struct( LL | Error | ^^^^^ the trait `Hash` is not implemented for `Error` | -note: required by a bound in `std::hash::Hash::hash` - --> $SRC_DIR/core/src/hash/mod.rs:LL:COL - | -LL | fn hash<H: Hasher>(&self, state: &mut H); - | ^ required by this bound in `std::hash::Hash::hash` = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-Ord-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-Ord-enum-struct-variant.stderr index 1e1cd715e6..b52c5a0d6a 100644 --- a/src/test/ui/derives/derives-span-Ord-enum-struct-variant.stderr +++ b/src/test/ui/derives/derives-span-Ord-enum-struct-variant.stderr @@ -7,11 +7,6 @@ LL | #[derive(Ord,Eq,PartialOrd,PartialEq)] LL | x: Error | ^^^^^^^^ the trait `Ord` is not implemented for `Error` | -note: required by `std::cmp::Ord::cmp` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - | -LL | fn cmp(&self, other: &Self) -> Ordering; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-Ord-enum.stderr b/src/test/ui/derives/derives-span-Ord-enum.stderr index 43abe9a954..2ea0496ea0 100644 --- a/src/test/ui/derives/derives-span-Ord-enum.stderr +++ b/src/test/ui/derives/derives-span-Ord-enum.stderr @@ -7,11 +7,6 @@ LL | #[derive(Ord,Eq,PartialOrd,PartialEq)] LL | Error | ^^^^^ the trait `Ord` is not implemented for `Error` | -note: required by `std::cmp::Ord::cmp` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - | -LL | fn cmp(&self, other: &Self) -> Ordering; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-Ord-struct.stderr b/src/test/ui/derives/derives-span-Ord-struct.stderr index 44f6bab08c..52cf0cf8cd 100644 --- a/src/test/ui/derives/derives-span-Ord-struct.stderr +++ b/src/test/ui/derives/derives-span-Ord-struct.stderr @@ -7,11 +7,6 @@ LL | struct Struct { LL | x: Error | ^^^^^^^^ the trait `Ord` is not implemented for `Error` | -note: required by `std::cmp::Ord::cmp` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - | -LL | fn cmp(&self, other: &Self) -> Ordering; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-Ord-tuple-struct.stderr b/src/test/ui/derives/derives-span-Ord-tuple-struct.stderr index e604018245..ecdf8d8cb5 100644 --- a/src/test/ui/derives/derives-span-Ord-tuple-struct.stderr +++ b/src/test/ui/derives/derives-span-Ord-tuple-struct.stderr @@ -7,11 +7,6 @@ LL | struct Struct( LL | Error | ^^^^^ the trait `Ord` is not implemented for `Error` | -note: required by `std::cmp::Ord::cmp` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - | -LL | fn cmp(&self, other: &Self) -> Ordering; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr index 9a716048e2..fc8eb1ebfd 100644 --- a/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr +++ b/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr @@ -8,11 +8,6 @@ LL | x: Error | ^^^^^^^^ no implementation for `Error < Error` and `Error > Error` | = help: the trait `PartialOrd` is not implemented for `Error` -note: required by `std::cmp::PartialOrd::partial_cmp` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - | -LL | fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-PartialOrd-enum.stderr b/src/test/ui/derives/derives-span-PartialOrd-enum.stderr index c726d33eab..38053495a0 100644 --- a/src/test/ui/derives/derives-span-PartialOrd-enum.stderr +++ b/src/test/ui/derives/derives-span-PartialOrd-enum.stderr @@ -8,11 +8,6 @@ LL | Error | ^^^^^ no implementation for `Error < Error` and `Error > Error` | = help: the trait `PartialOrd` is not implemented for `Error` -note: required by `std::cmp::PartialOrd::partial_cmp` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - | -LL | fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-PartialOrd-struct.stderr b/src/test/ui/derives/derives-span-PartialOrd-struct.stderr index a56c163ca7..1c07b98f98 100644 --- a/src/test/ui/derives/derives-span-PartialOrd-struct.stderr +++ b/src/test/ui/derives/derives-span-PartialOrd-struct.stderr @@ -8,11 +8,6 @@ LL | x: Error | ^^^^^^^^ no implementation for `Error < Error` and `Error > Error` | = help: the trait `PartialOrd` is not implemented for `Error` -note: required by `std::cmp::PartialOrd::partial_cmp` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - | -LL | fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.stderr b/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.stderr index 7a0a52e582..bf01252b07 100644 --- a/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.stderr +++ b/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.stderr @@ -8,11 +8,6 @@ LL | Error | ^^^^^ no implementation for `Error < Error` and `Error > Error` | = help: the trait `PartialOrd` is not implemented for `Error` -note: required by `std::cmp::PartialOrd::partial_cmp` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - | -LL | fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/deriving-copyclone.stderr b/src/test/ui/derives/deriving-copyclone.stderr index 1d0554ad04..13097edf0a 100644 --- a/src/test/ui/derives/deriving-copyclone.stderr +++ b/src/test/ui/derives/deriving-copyclone.stderr @@ -1,4 +1,4 @@ -error[E0277]: the trait bound `C: Copy` is not satisfied +error[E0277]: the trait bound `B<C>: Copy` is not satisfied --> $DIR/deriving-copyclone.rs:31:13 | LL | is_copy(B { a: 1, b: C }); @@ -22,7 +22,7 @@ help: consider borrowing here LL | is_copy(&B { a: 1, b: C }); | + -error[E0277]: the trait bound `C: Clone` is not satisfied +error[E0277]: the trait bound `B<C>: Clone` is not satisfied --> $DIR/deriving-copyclone.rs:32:14 | LL | is_clone(B { a: 1, b: C }); @@ -46,7 +46,7 @@ help: consider borrowing here LL | is_clone(&B { a: 1, b: C }); | + -error[E0277]: the trait bound `D: Copy` is not satisfied +error[E0277]: the trait bound `B<D>: Copy` is not satisfied --> $DIR/deriving-copyclone.rs:35:13 | LL | is_copy(B { a: 1, b: D }); diff --git a/src/test/ui/derives/deriving-no-inner-impl-error-message.stderr b/src/test/ui/derives/deriving-no-inner-impl-error-message.stderr index e322db97fa..d64b4509b2 100644 --- a/src/test/ui/derives/deriving-no-inner-impl-error-message.stderr +++ b/src/test/ui/derives/deriving-no-inner-impl-error-message.stderr @@ -47,11 +47,6 @@ LL | struct C { LL | x: NoCloneOrEq | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `NoCloneOrEq` | -note: required by `clone` - --> $SRC_DIR/core/src/clone.rs:LL:COL - | -LL | fn clone(&self) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/src/test/ui/issues/issue-19358.rs b/src/test/ui/deriving/issue-19358.rs similarity index 100% rename from src/test/ui/issues/issue-19358.rs rename to src/test/ui/deriving/issue-19358.rs diff --git a/src/test/ui/issues/issue-58319.rs b/src/test/ui/deriving/issue-58319.rs similarity index 100% rename from src/test/ui/issues/issue-58319.rs rename to src/test/ui/deriving/issue-58319.rs diff --git a/src/test/ui/did_you_mean/compatible-variants.rs b/src/test/ui/did_you_mean/compatible-variants.rs new file mode 100644 index 0000000000..fb6b6a5673 --- /dev/null +++ b/src/test/ui/did_you_mean/compatible-variants.rs @@ -0,0 +1,43 @@ +enum Hey<A, B> { + A(A), + B(B), +} + +fn f() {} + +fn a() -> Option<()> { + while false { + //~^ ERROR mismatched types + f(); + } + //~^ HELP try adding an expression +} + +fn b() -> Result<(), ()> { + f() + //~^ ERROR mismatched types + //~| HELP try adding an expression +} + +fn main() { + let _: Option<()> = while false {}; + //~^ ERROR mismatched types + //~| HELP try wrapping + let _: Option<()> = { + while false {} + //~^ ERROR mismatched types + //~| HELP try adding an expression + }; + let _: Result<i32, i32> = 1; + //~^ ERROR mismatched types + //~| HELP try wrapping + let _: Option<i32> = 1; + //~^ ERROR mismatched types + //~| HELP try wrapping + let _: Hey<i32, i32> = 1; + //~^ ERROR mismatched types + //~| HELP try wrapping + let _: Hey<i32, bool> = false; + //~^ ERROR mismatched types + //~| HELP try wrapping +} diff --git a/src/test/ui/did_you_mean/compatible-variants.stderr b/src/test/ui/did_you_mean/compatible-variants.stderr new file mode 100644 index 0000000000..e77949687f --- /dev/null +++ b/src/test/ui/did_you_mean/compatible-variants.stderr @@ -0,0 +1,137 @@ +error[E0308]: mismatched types + --> $DIR/compatible-variants.rs:9:5 + | +LL | fn a() -> Option<()> { + | ---------- expected `Option<()>` because of return type +LL | / while false { +LL | | +LL | | f(); +LL | | } + | |_____^ expected enum `Option`, found `()` + | + = note: expected enum `Option<()>` + found unit type `()` +help: try adding an expression at the end of the block + | +LL ~ } +LL + None + | +LL ~ } +LL + Some(()) + | + +error[E0308]: mismatched types + --> $DIR/compatible-variants.rs:17:5 + | +LL | fn b() -> Result<(), ()> { + | -------------- expected `Result<(), ()>` because of return type +LL | f() + | ^^^ expected enum `Result`, found `()` + | + = note: expected enum `Result<(), ()>` + found unit type `()` +help: try adding an expression at the end of the block + | +LL ~ f(); +LL + Ok(()) + | + +error[E0308]: mismatched types + --> $DIR/compatible-variants.rs:23:25 + | +LL | let _: Option<()> = while false {}; + | ---------- ^^^^^^^^^^^^^^ expected enum `Option`, found `()` + | | + | expected due to this + | + = note: expected enum `Option<()>` + found unit type `()` +help: try wrapping the expression in `Some` + | +LL | let _: Option<()> = Some(while false {}); + | +++++ + + +error[E0308]: mismatched types + --> $DIR/compatible-variants.rs:27:9 + | +LL | while false {} + | ^^^^^^^^^^^^^^ expected enum `Option`, found `()` + | + = note: expected enum `Option<()>` + found unit type `()` +help: try adding an expression at the end of the block + | +LL ~ while false {} +LL + None + | +LL ~ while false {} +LL + Some(()) + | + +error[E0308]: mismatched types + --> $DIR/compatible-variants.rs:31:31 + | +LL | let _: Result<i32, i32> = 1; + | ---------------- ^ expected enum `Result`, found integer + | | + | expected due to this + | + = note: expected enum `Result<i32, i32>` + found type `{integer}` +help: try wrapping the expression in a variant of `Result` + | +LL | let _: Result<i32, i32> = Ok(1); + | +++ + +LL | let _: Result<i32, i32> = Err(1); + | ++++ + + +error[E0308]: mismatched types + --> $DIR/compatible-variants.rs:34:26 + | +LL | let _: Option<i32> = 1; + | ----------- ^ expected enum `Option`, found integer + | | + | expected due to this + | + = note: expected enum `Option<i32>` + found type `{integer}` +help: try wrapping the expression in `Some` + | +LL | let _: Option<i32> = Some(1); + | +++++ + + +error[E0308]: mismatched types + --> $DIR/compatible-variants.rs:37:28 + | +LL | let _: Hey<i32, i32> = 1; + | ------------- ^ expected enum `Hey`, found integer + | | + | expected due to this + | + = note: expected enum `Hey<i32, i32>` + found type `{integer}` +help: try wrapping the expression in a variant of `Hey` + | +LL | let _: Hey<i32, i32> = Hey::A(1); + | +++++++ + +LL | let _: Hey<i32, i32> = Hey::B(1); + | +++++++ + + +error[E0308]: mismatched types + --> $DIR/compatible-variants.rs:40:29 + | +LL | let _: Hey<i32, bool> = false; + | -------------- ^^^^^ expected enum `Hey`, found `bool` + | | + | expected due to this + | + = note: expected enum `Hey<i32, bool>` + found type `bool` +help: try wrapping the expression in `Hey::B` + | +LL | let _: Hey<i32, bool> = Hey::B(false); + | +++++++ + + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr index c7458916c5..5381a717dc 100644 --- a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr +++ b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr @@ -12,11 +12,6 @@ LL | Foo::<i32>::bar(&1i8); <i8 as Foo<u32>> <i8 as Foo<u64>> <i8 as Foo<u8>> -note: required by `Foo::bar` - --> $DIR/issue-39802-show-5-trait-impls.rs:2:5 - | -LL | fn bar(&self){} - | ^^^^^^^^^^^^^ error[E0277]: the trait bound `u8: Foo<i32>` is not satisfied --> $DIR/issue-39802-show-5-trait-impls.rs:25:21 @@ -31,11 +26,6 @@ LL | Foo::<i32>::bar(&1u8); <u8 as Foo<u16>> <u8 as Foo<u32>> <u8 as Foo<u64>> -note: required by `Foo::bar` - --> $DIR/issue-39802-show-5-trait-impls.rs:2:5 - | -LL | fn bar(&self){} - | ^^^^^^^^^^^^^ error[E0277]: the trait bound `bool: Foo<i32>` is not satisfied --> $DIR/issue-39802-show-5-trait-impls.rs:26:21 @@ -51,11 +41,6 @@ LL | Foo::<i32>::bar(&true); <bool as Foo<u16>> <bool as Foo<u32>> and 2 others -note: required by `Foo::bar` - --> $DIR/issue-39802-show-5-trait-impls.rs:2:5 - | -LL | fn bar(&self){} - | ^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/did_you_mean/issue-42764.rs b/src/test/ui/did_you_mean/issue-42764.rs index 700f8128a9..6da640b2b7 100644 --- a/src/test/ui/did_you_mean/issue-42764.rs +++ b/src/test/ui/did_you_mean/issue-42764.rs @@ -10,7 +10,7 @@ fn main() { let n: usize = 42; this_function_expects_a_double_option(n); //~^ ERROR mismatched types - //~| HELP try using a variant of the expected enum + //~| HELP try wrapping the expression in a variant of `DoubleOption` } diff --git a/src/test/ui/did_you_mean/issue-42764.stderr b/src/test/ui/did_you_mean/issue-42764.stderr index b339ce5ce8..dbe46704b9 100644 --- a/src/test/ui/did_you_mean/issue-42764.stderr +++ b/src/test/ui/did_you_mean/issue-42764.stderr @@ -6,12 +6,12 @@ LL | this_function_expects_a_double_option(n); | = note: expected enum `DoubleOption<_>` found type `usize` -help: try using a variant of the expected enum +help: try wrapping the expression in a variant of `DoubleOption` | LL | this_function_expects_a_double_option(DoubleOption::FirstSome(n)); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++++++ + LL | this_function_expects_a_double_option(DoubleOption::AlternativeSome(n)); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++++++++++++ + error[E0308]: mismatched types --> $DIR/issue-42764.rs:27:33 diff --git a/src/test/ui/auxiliary/inline_dtor.rs b/src/test/ui/drop/auxiliary/inline_dtor.rs similarity index 100% rename from src/test/ui/auxiliary/inline_dtor.rs rename to src/test/ui/drop/auxiliary/inline_dtor.rs diff --git a/src/test/ui/issues/issue-35546.rs b/src/test/ui/drop/issue-35546.rs similarity index 100% rename from src/test/ui/issues/issue-35546.rs rename to src/test/ui/drop/issue-35546.rs diff --git a/src/test/ui/drop/issue-90752-raw-ptr-shenanigans.rs b/src/test/ui/drop/issue-90752-raw-ptr-shenanigans.rs new file mode 100644 index 0000000000..4e67b35949 --- /dev/null +++ b/src/test/ui/drop/issue-90752-raw-ptr-shenanigans.rs @@ -0,0 +1,41 @@ +// run-pass + +use std::cell::RefCell; + +struct S<'a>(i32, &'a RefCell<Vec<i32>>); + +impl<'a> Drop for S<'a> { + fn drop(&mut self) { + self.1.borrow_mut().push(self.0); + } +} + +fn test(drops: &RefCell<Vec<i32>>) { + let mut foo = None; + let pfoo: *mut _ = &mut foo; + + match foo { + None => (), + _ => return, + } + + // Both S(0) and S(1) should be dropped, but aren't. + unsafe { *pfoo = Some((S(0, drops), S(1, drops))); } + + match foo { + Some((_x, _)) => {} + _ => {} + } +} + +fn main() { + let drops = RefCell::new(Vec::new()); + test(&drops); + + // Ideally, we want this... + //assert_eq!(*drops.borrow(), &[0, 1]); + + // But the delayed access through the raw pointer confuses drop elaboration, + // causing S(1) to be leaked. + assert_eq!(*drops.borrow(), &[0]); +} diff --git a/src/test/ui/drop/issue-90752.rs b/src/test/ui/drop/issue-90752.rs new file mode 100644 index 0000000000..4395e45e77 --- /dev/null +++ b/src/test/ui/drop/issue-90752.rs @@ -0,0 +1,32 @@ +// run-pass + +use std::cell::RefCell; + +struct S<'a>(i32, &'a RefCell<Vec<i32>>); + +impl<'a> Drop for S<'a> { + fn drop(&mut self) { + self.1.borrow_mut().push(self.0); + } +} + +fn test(drops: &RefCell<Vec<i32>>) { + let mut foo = None; + match foo { + None => (), + _ => return, + } + + *(&mut foo) = Some((S(0, drops), S(1, drops))); // Both S(0) and S(1) should be dropped + + match foo { + Some((_x, _)) => {} + _ => {} + } +} + +fn main() { + let drops = RefCell::new(Vec::new()); + test(&drops); + assert_eq!(*drops.borrow(), &[0, 1]); +} diff --git a/src/test/ui/terminate-in-initializer.rs b/src/test/ui/drop/terminate-in-initializer.rs similarity index 100% rename from src/test/ui/terminate-in-initializer.rs rename to src/test/ui/drop/terminate-in-initializer.rs diff --git a/src/test/ui/use_inline_dtor.rs b/src/test/ui/drop/use_inline_dtor.rs similarity index 100% rename from src/test/ui/use_inline_dtor.rs rename to src/test/ui/drop/use_inline_dtor.rs diff --git a/src/test/ui/cleanup-arm-conditional.rs b/src/test/ui/dropck/cleanup-arm-conditional.rs similarity index 100% rename from src/test/ui/cleanup-arm-conditional.rs rename to src/test/ui/dropck/cleanup-arm-conditional.rs diff --git a/src/test/ui/dropck/drop-on-non-struct.stderr b/src/test/ui/dropck/drop-on-non-struct.stderr index 3991c44f2e..e52728f378 100644 --- a/src/test/ui/dropck/drop-on-non-struct.stderr +++ b/src/test/ui/dropck/drop-on-non-struct.stderr @@ -4,12 +4,6 @@ error[E0412]: cannot find type `Nonexistent` in this scope LL | impl Drop for Nonexistent { | ^^^^^^^^^^^ not found in this scope -error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions - --> $DIR/drop-on-non-struct.rs:1:19 - | -LL | impl<'a> Drop for &'a mut isize { - | ^^^^^^^^^^^^^ must be a struct, enum, or union - error[E0117]: only traits defined in the current crate can be implemented for arbitrary types --> $DIR/drop-on-non-struct.rs:1:1 | @@ -21,6 +15,12 @@ LL | impl<'a> Drop for &'a mut isize { | = note: define and implement a trait or new type instead +error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions + --> $DIR/drop-on-non-struct.rs:1:19 + | +LL | impl<'a> Drop for &'a mut isize { + | ^^^^^^^^^^^^^ must be a struct, enum, or union + error: aborting due to 3 previous errors Some errors have detailed explanations: E0117, E0120, E0412. diff --git a/src/test/ui/issues/issue-28498-ugeh-with-passed-to-fn.rs b/src/test/ui/dropck/issue-28498-ugeh-with-passed-to-fn.rs similarity index 100% rename from src/test/ui/issues/issue-28498-ugeh-with-passed-to-fn.rs rename to src/test/ui/dropck/issue-28498-ugeh-with-passed-to-fn.rs diff --git a/src/test/ui/dst/dst-bad-assign-3.stderr b/src/test/ui/dst/dst-bad-assign-3.stderr index 04e4623353..b326dbbbc1 100644 --- a/src/test/ui/dst/dst-bad-assign-3.stderr +++ b/src/test/ui/dst/dst-bad-assign-3.stderr @@ -2,7 +2,9 @@ error[E0308]: mismatched types --> $DIR/dst-bad-assign-3.rs:33:12 | LL | f5.2 = Bar1 {f: 36}; - | ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1` + | ---- ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1` + | | + | expected due to the type of this binding | = note: expected trait object `dyn ToBar` found struct `Bar1` diff --git a/src/test/ui/dst/dst-bad-assign.stderr b/src/test/ui/dst/dst-bad-assign.stderr index f87a34c6d3..614f213875 100644 --- a/src/test/ui/dst/dst-bad-assign.stderr +++ b/src/test/ui/dst/dst-bad-assign.stderr @@ -2,7 +2,9 @@ error[E0308]: mismatched types --> $DIR/dst-bad-assign.rs:35:14 | LL | f5.ptr = Bar1 {f: 36}; - | ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1` + | ------ ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1` + | | + | expected due to the type of this binding | = note: expected trait object `dyn ToBar` found struct `Bar1` diff --git a/src/test/ui/editions/dyn-trait-sugg-2021.stderr b/src/test/ui/editions/dyn-trait-sugg-2021.stderr index f6e9fa96a1..a7119b073a 100644 --- a/src/test/ui/editions/dyn-trait-sugg-2021.stderr +++ b/src/test/ui/editions/dyn-trait-sugg-2021.stderr @@ -1,4 +1,4 @@ -error[E0783]: trait objects without an explicit `dyn` are deprecated +error[E0782]: trait objects without an explicit `dyn` are deprecated --> $DIR/dyn-trait-sugg-2021.rs:10:5 | LL | Foo::hi(123); @@ -6,4 +6,4 @@ LL | Foo::hi(123); error: aborting due to previous error -For more information about this error, try `rustc --explain E0783`. +For more information about this error, try `rustc --explain E0782`. diff --git a/src/test/ui/edition-keywords-2015-2015.rs b/src/test/ui/editions/edition-keywords-2015-2015.rs similarity index 100% rename from src/test/ui/edition-keywords-2015-2015.rs rename to src/test/ui/editions/edition-keywords-2015-2015.rs diff --git a/src/test/ui/edition-keywords-2015-2018.rs b/src/test/ui/editions/edition-keywords-2015-2018.rs similarity index 100% rename from src/test/ui/edition-keywords-2015-2018.rs rename to src/test/ui/editions/edition-keywords-2015-2018.rs diff --git a/src/test/ui/edition-keywords-2018-2015.rs b/src/test/ui/editions/edition-keywords-2018-2015.rs similarity index 100% rename from src/test/ui/edition-keywords-2018-2015.rs rename to src/test/ui/editions/edition-keywords-2018-2015.rs diff --git a/src/test/ui/edition-keywords-2018-2018.rs b/src/test/ui/editions/edition-keywords-2018-2018.rs similarity index 100% rename from src/test/ui/edition-keywords-2018-2018.rs rename to src/test/ui/editions/edition-keywords-2018-2018.rs diff --git a/src/test/ui/epoch-gate-feature.rs b/src/test/ui/editions/epoch-gate-feature.rs similarity index 100% rename from src/test/ui/epoch-gate-feature.rs rename to src/test/ui/editions/epoch-gate-feature.rs diff --git a/src/test/ui/empty/empty-attributes.rs b/src/test/ui/empty/empty-attributes.rs new file mode 100644 index 0000000000..7e9b05587b --- /dev/null +++ b/src/test/ui/empty/empty-attributes.rs @@ -0,0 +1,14 @@ +#![deny(unused_attributes)] +#![allow()] //~ ERROR unused attribute +#![warn()] //~ ERROR unused attribute +#![deny()] //~ ERROR unused attribute +#![forbid()] //~ ERROR unused attribute +#![feature()] //~ ERROR unused attribute + +#[repr()] //~ ERROR unused attribute +pub struct S; + +#[target_feature()] //~ ERROR unused attribute +pub unsafe fn foo() {} + +fn main() {} diff --git a/src/test/ui/empty/empty-attributes.stderr b/src/test/ui/empty/empty-attributes.stderr new file mode 100644 index 0000000000..e0798e4f0c --- /dev/null +++ b/src/test/ui/empty/empty-attributes.stderr @@ -0,0 +1,63 @@ +error: unused attribute + --> $DIR/empty-attributes.rs:8:1 + | +LL | #[repr()] + | ^^^^^^^^^ help: remove this attribute + | +note: the lint level is defined here + --> $DIR/empty-attributes.rs:1:9 + | +LL | #![deny(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + = note: attribute `repr` with an empty list has no effect + +error: unused attribute + --> $DIR/empty-attributes.rs:11:1 + | +LL | #[target_feature()] + | ^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | + = note: attribute `target_feature` with an empty list has no effect + +error: unused attribute + --> $DIR/empty-attributes.rs:2:1 + | +LL | #![allow()] + | ^^^^^^^^^^^ help: remove this attribute + | + = note: attribute `allow` with an empty list has no effect + +error: unused attribute + --> $DIR/empty-attributes.rs:3:1 + | +LL | #![warn()] + | ^^^^^^^^^^ help: remove this attribute + | + = note: attribute `warn` with an empty list has no effect + +error: unused attribute + --> $DIR/empty-attributes.rs:4:1 + | +LL | #![deny()] + | ^^^^^^^^^^ help: remove this attribute + | + = note: attribute `deny` with an empty list has no effect + +error: unused attribute + --> $DIR/empty-attributes.rs:5:1 + | +LL | #![forbid()] + | ^^^^^^^^^^^^ help: remove this attribute + | + = note: attribute `forbid` with an empty list has no effect + +error: unused attribute + --> $DIR/empty-attributes.rs:6:1 + | +LL | #![feature()] + | ^^^^^^^^^^^^^ help: remove this attribute + | + = note: attribute `feature` with an empty list has no effect + +error: aborting due to 7 previous errors + diff --git a/src/test/ui/empty/empty-struct-unit-expr.stderr b/src/test/ui/empty/empty-struct-unit-expr.stderr index 1023950639..81651c5bf6 100644 --- a/src/test/ui/empty/empty-struct-unit-expr.stderr +++ b/src/test/ui/empty/empty-struct-unit-expr.stderr @@ -20,10 +20,11 @@ LL | let e4 = E::Empty4(); | | | call expression requires function | -help: `E::Empty4` is a unit variant, you need to write it without the parenthesis +help: `E::Empty4` is a unit variant, you need to write it without the parentheses | -LL | let e4 = E::Empty4; - | ~~~~~~~~~ +LL - let e4 = E::Empty4(); +LL + let e4 = E::Empty4; + | error[E0618]: expected function, found `empty_struct::XEmpty2` --> $DIR/empty-struct-unit-expr.rs:18:15 @@ -41,10 +42,11 @@ LL | let xe4 = XE::XEmpty4(); | | | call expression requires function | -help: `XE::XEmpty4` is a unit variant, you need to write it without the parenthesis +help: `XE::XEmpty4` is a unit variant, you need to write it without the parentheses | -LL | let xe4 = XE::XEmpty4; - | ~~~~~~~~~~~ +LL - let xe4 = XE::XEmpty4(); +LL + let xe4 = XE::XEmpty4; + | error: aborting due to 4 previous errors diff --git a/src/test/ui/entry-point/imported_main_conflict.rs b/src/test/ui/entry-point/imported_main_conflict.rs index 2839688f34..e8c70b0651 100644 --- a/src/test/ui/entry-point/imported_main_conflict.rs +++ b/src/test/ui/entry-point/imported_main_conflict.rs @@ -1,5 +1,5 @@ #![feature(imported_main)] -//~^ ERROR `main` is ambiguous (glob import vs glob import in the same module) +//~^ ERROR `main` is ambiguous mod m1 { pub(crate) fn main() {} } mod m2 { pub(crate) fn main() {} } diff --git a/src/test/ui/entry-point/imported_main_conflict.stderr b/src/test/ui/entry-point/imported_main_conflict.stderr index 36cb98d94e..8fadd0e19b 100644 --- a/src/test/ui/entry-point/imported_main_conflict.stderr +++ b/src/test/ui/entry-point/imported_main_conflict.stderr @@ -1,5 +1,6 @@ -error[E0659]: `main` is ambiguous (glob import vs glob import in the same module) +error[E0659]: `main` is ambiguous | + = note: ambiguous because of multiple glob imports of a name in the same module note: `main` could refer to the function imported here --> $DIR/imported_main_conflict.rs:6:5 | 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 index 6aa170fdfd..c731c32832 100644 --- 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 @@ -21,7 +21,7 @@ LL | type MainFn = impl Fn(); LL | pub const BAR: MainFn = bar; | ^^^ expected opaque type, found fn item | - = note: expected opaque type `impl Fn<()>` + = note: expected opaque type `impl Fn()` found fn item `fn() {bar}` error: could not find defining uses diff --git a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs index f2270602d8..22c5332c92 100644 --- a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs +++ b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs @@ -1,5 +1,5 @@ // run-pass -#![feature(arbitrary_enum_discriminant, const_raw_ptr_deref, test)] +#![feature(arbitrary_enum_discriminant, test)] extern crate test; diff --git a/src/test/ui/issues/issue-51582.rs b/src/test/ui/enum-discriminant/issue-51582.rs similarity index 100% rename from src/test/ui/issues/issue-51582.rs rename to src/test/ui/enum-discriminant/issue-51582.rs diff --git a/src/test/ui/issues/issue-42747.rs b/src/test/ui/enum/issue-42747.rs similarity index 100% rename from src/test/ui/issues/issue-42747.rs rename to src/test/ui/enum/issue-42747.rs diff --git a/src/test/ui/error-codes/E0070.rs b/src/test/ui/error-codes/E0070.rs index ab956d8109..3aae0c9ff6 100644 --- a/src/test/ui/error-codes/E0070.rs +++ b/src/test/ui/error-codes/E0070.rs @@ -6,7 +6,6 @@ fn some_function() { SOME_CONST = 14; //~ ERROR E0070 1 = 3; //~ ERROR E0070 some_other_func() = 4; //~ ERROR E0070 - //~^ ERROR E0308 } fn main() { diff --git a/src/test/ui/error-codes/E0070.stderr b/src/test/ui/error-codes/E0070.stderr index e24d498e35..8868bc257a 100644 --- a/src/test/ui/error-codes/E0070.stderr +++ b/src/test/ui/error-codes/E0070.stderr @@ -22,13 +22,6 @@ LL | some_other_func() = 4; | | | cannot assign to this expression -error[E0308]: mismatched types - --> $DIR/E0070.rs:8:25 - | -LL | some_other_func() = 4; - | ^ expected `()`, found integer - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0070, E0308. -For more information about an error, try `rustc --explain E0070`. +For more information about this error, try `rustc --explain E0070`. diff --git a/src/test/ui/error-codes/E0117.stderr b/src/test/ui/error-codes/E0117.stderr index b48a1d8e50..cdbafff2a2 100644 --- a/src/test/ui/error-codes/E0117.stderr +++ b/src/test/ui/error-codes/E0117.stderr @@ -1,9 +1,3 @@ -error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions - --> $DIR/E0117.rs:1:15 - | -LL | impl Drop for u32 {} - | ^^^ must be a struct, enum, or union - error[E0117]: only traits defined in the current crate can be implemented for arbitrary types --> $DIR/E0117.rs:1:1 | @@ -15,6 +9,12 @@ LL | impl Drop for u32 {} | = note: define and implement a trait or new type instead +error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions + --> $DIR/E0117.rs:1:15 + | +LL | impl Drop for u32 {} + | ^^^ must be a struct, enum, or union + error: aborting due to 2 previous errors Some errors have detailed explanations: E0117, E0120. diff --git a/src/test/ui/error-codes/E0206.rs b/src/test/ui/error-codes/E0206.rs index bace046758..0f3d427ce1 100644 --- a/src/test/ui/error-codes/E0206.rs +++ b/src/test/ui/error-codes/E0206.rs @@ -1,9 +1,3 @@ -type Foo = [u8; 256]; - -impl Copy for Foo { } -//~^ ERROR the trait `Copy` may not be implemented for this type -//~| ERROR only traits defined in the current crate can be implemented for arbitrary types - #[derive(Copy, Clone)] struct Bar; diff --git a/src/test/ui/error-codes/E0206.stderr b/src/test/ui/error-codes/E0206.stderr index e4ad4ffb45..57ae2647d3 100644 --- a/src/test/ui/error-codes/E0206.stderr +++ b/src/test/ui/error-codes/E0206.stderr @@ -1,27 +1,9 @@ error[E0206]: the trait `Copy` may not be implemented for this type - --> $DIR/E0206.rs:3:15 - | -LL | impl Copy for Foo { } - | ^^^ type is not a structure or enumeration - -error[E0206]: the trait `Copy` may not be implemented for this type - --> $DIR/E0206.rs:10:15 + --> $DIR/E0206.rs:4:15 | LL | impl Copy for &'static mut Bar { } | ^^^^^^^^^^^^^^^^ type is not a structure or enumeration -error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/E0206.rs:3:1 - | -LL | impl Copy for Foo { } - | ^^^^^^^^^^^^^^--- - | | | - | | this is not defined in the current crate because arrays are always foreign - | impl doesn't use only types from inside the current crate - | - = note: define and implement a trait or new type instead - -error: aborting due to 3 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0117, E0206. -For more information about an error, try `rustc --explain E0117`. +For more information about this error, try `rustc --explain E0206`. diff --git a/src/test/ui/error-codes/E0275.stderr b/src/test/ui/error-codes/E0275.stderr index e13f0961a1..dfffbb182a 100644 --- a/src/test/ui/error-codes/E0275.stderr +++ b/src/test/ui/error-codes/E0275.stderr @@ -12,11 +12,6 @@ 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>` -note: required by a bound in `Foo` - --> $DIR/E0275.rs:1:1 - | -LL | trait Foo {} - | ^^^^^^^^^ required by this bound in `Foo` error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0276.stderr b/src/test/ui/error-codes/E0276.stderr index 8857e1646e..1013f041bb 100644 --- a/src/test/ui/error-codes/E0276.stderr +++ b/src/test/ui/error-codes/E0276.stderr @@ -1,11 +1,11 @@ error[E0276]: impl has stricter requirements than trait - --> $DIR/E0276.rs:6:5 + --> $DIR/E0276.rs:6:30 | LL | fn foo<T>(x: T); | ---------------- definition of `foo` from trait ... LL | fn foo<T>(x: T) where T: Copy {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: Copy` + | ^^^^ impl has extra requirement `T: Copy` error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0283.stderr b/src/test/ui/error-codes/E0283.stderr index b6078e3023..7dcfe96b35 100644 --- a/src/test/ui/error-codes/E0283.stderr +++ b/src/test/ui/error-codes/E0283.stderr @@ -5,11 +5,6 @@ LL | let cont: u32 = Generator::create(); | ^^^^^^^^^^^^^^^^^ cannot infer type | = note: cannot satisfy `_: Generator` -note: required by `Generator::create` - --> $DIR/E0283.rs:2:5 - | -LL | fn create() -> u32; - | ^^^^^^^^^^^^^^^^^^^ error[E0283]: type annotations needed --> $DIR/E0283.rs:35:24 @@ -21,7 +16,14 @@ LL | let bar = foo_impl.into() * 1u32; | this method call resolves to `T` | help: use the fully qualified path for the potential candidate: `<Impl as Into<u32>>::into(foo_impl)` | - = note: cannot satisfy `Impl: Into<_>` +note: multiple `impl`s satisfying `Impl: Into<_>` found + --> $DIR/E0283.rs:17:1 + | +LL | impl Into<u32> for Impl { + | ^^^^^^^^^^^^^^^^^^^^^^^ + = note: and another `impl` found in the `core` crate: + - impl<T, U> Into<U> for T + where U: From<T>; error: aborting due to 2 previous errors diff --git a/src/test/ui/error-codes/E0365.rs b/src/test/ui/error-codes/E0365.rs index f12ff96bb8..464109247c 100644 --- a/src/test/ui/error-codes/E0365.rs +++ b/src/test/ui/error-codes/E0365.rs @@ -3,6 +3,6 @@ mod foo { } pub use foo as foo2; -//~^ ERROR `foo` is private, and cannot be re-exported [E0365] +//~^ ERROR `foo` is only public within the crate, and cannot be re-exported outside [E0365] fn main() {} diff --git a/src/test/ui/error-codes/E0365.stderr b/src/test/ui/error-codes/E0365.stderr index c8fc59f8ba..5bfcf1394d 100644 --- a/src/test/ui/error-codes/E0365.stderr +++ b/src/test/ui/error-codes/E0365.stderr @@ -1,8 +1,8 @@ -error[E0365]: `foo` is private, and cannot be re-exported +error[E0365]: `foo` is only public within the crate, and cannot be re-exported outside --> $DIR/E0365.rs:5:9 | LL | pub use foo as foo2; - | ^^^^^^^^^^^ re-export of private `foo` + | ^^^^^^^^^^^ re-export of crate public `foo` | = note: consider declaring type or module `foo` with `pub` diff --git a/src/test/ui/error-codes/E0396-fixed.rs b/src/test/ui/error-codes/E0396-fixed.rs index 654b21f05b..fe20da1a8e 100644 --- a/src/test/ui/error-codes/E0396-fixed.rs +++ b/src/test/ui/error-codes/E0396-fixed.rs @@ -1,6 +1,6 @@ -#![feature(const_raw_ptr_deref)] +#![feature(const_mut_refs)] -const REG_ADDR: *const u8 = 0x5f3759df as *const u8; +const REG_ADDR: *mut u8 = 0x5f3759df as *mut u8; const VALUE: u8 = unsafe { *REG_ADDR }; //~^ ERROR evaluation of constant value failed diff --git a/src/test/ui/error-codes/E0396.rs b/src/test/ui/error-codes/E0396.rs index 58ed3c2c72..4415b70e75 100644 --- a/src/test/ui/error-codes/E0396.rs +++ b/src/test/ui/error-codes/E0396.rs @@ -1,19 +1,17 @@ -// gate-test-const_raw_ptr_deref - -const REG_ADDR: *const u8 = 0x5f3759df as *const u8; +const REG_ADDR: *mut u8 = 0x5f3759df as *mut u8; const VALUE: u8 = unsafe { *REG_ADDR }; -//~^ ERROR dereferencing raw pointers in constants is unstable +//~^ ERROR dereferencing raw mutable pointers in constants is unstable const unsafe fn unreachable() -> ! { use std::convert::Infallible; - const INFALLIBLE: *const Infallible = [].as_ptr(); + const INFALLIBLE: *mut Infallible = &[] as *const [Infallible] as *const _ as _; match *INFALLIBLE {} - //~^ ERROR dereferencing raw pointers in constant functions is unstable + //~^ ERROR dereferencing raw mutable pointers in constant functions is unstable const BAD: () = unsafe { match *INFALLIBLE {} }; - //~^ ERROR dereferencing raw pointers in constants is unstable + //~^ ERROR dereferencing raw mutable pointers in constants is unstable } fn main() { diff --git a/src/test/ui/error-codes/E0396.stderr b/src/test/ui/error-codes/E0396.stderr index 20dad1b983..8c87f40674 100644 --- a/src/test/ui/error-codes/E0396.stderr +++ b/src/test/ui/error-codes/E0396.stderr @@ -1,29 +1,29 @@ -error[E0658]: dereferencing raw pointers in constants is unstable - --> $DIR/E0396.rs:5:28 +error[E0658]: dereferencing raw mutable pointers in constants is unstable + --> $DIR/E0396.rs:3:28 | LL | const VALUE: u8 = unsafe { *REG_ADDR }; | ^^^^^^^^^ | - = note: see issue #51911 <https://github.com/rust-lang/rust/issues/51911> for more information - = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable + = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable -error[E0658]: dereferencing raw pointers in constant functions is unstable - --> $DIR/E0396.rs:12:11 +error[E0658]: dereferencing raw mutable pointers in constant functions is unstable + --> $DIR/E0396.rs:10:11 | LL | match *INFALLIBLE {} | ^^^^^^^^^^^ | - = note: see issue #51911 <https://github.com/rust-lang/rust/issues/51911> for more information - = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable + = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable -error[E0658]: dereferencing raw pointers in constants is unstable - --> $DIR/E0396.rs:15:36 +error[E0658]: dereferencing raw mutable pointers in constants is unstable + --> $DIR/E0396.rs:13:36 | LL | const BAD: () = unsafe { match *INFALLIBLE {} }; | ^^^^^^^^^^^ | - = note: see issue #51911 <https://github.com/rust-lang/rust/issues/51911> for more information - = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable + = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable error: aborting due to 3 previous errors diff --git a/src/test/ui/error-codes/E0618.stderr b/src/test/ui/error-codes/E0618.stderr index 19a1a8e20c..a3a90968df 100644 --- a/src/test/ui/error-codes/E0618.stderr +++ b/src/test/ui/error-codes/E0618.stderr @@ -9,10 +9,11 @@ LL | X::Entry(); | | | call expression requires function | -help: `X::Entry` is a unit variant, you need to write it without the parenthesis +help: `X::Entry` is a unit variant, you need to write it without the parentheses | -LL | X::Entry; - | ~~~~~~~~ +LL - X::Entry(); +LL + X::Entry; + | error[E0618]: expected function, found `i32` --> $DIR/E0618.rs:9:5 diff --git a/src/test/ui/error-codes/E0637.rs b/src/test/ui/error-codes/E0637.rs index b4888d4af6..382ce3ed01 100644 --- a/src/test/ui/error-codes/E0637.rs +++ b/src/test/ui/error-codes/E0637.rs @@ -1,9 +1,17 @@ -struct Foo<'a: '_>(&'a u8); //~ ERROR cannot be used here -fn foo<'a: '_>(_: &'a u8) {} //~ ERROR cannot be used here +fn underscore_lifetime<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str { + //~^ ERROR: `'_` cannot be used here [E0637] + //~| ERROR: missing lifetime specifier + if str1.len() > str2.len() { + str1 + } else { + str2 + } +} -struct Bar<'a>(&'a u8); -impl<'a: '_> Bar<'a> { //~ ERROR cannot be used here - fn bar() {} +fn and_without_explicit_lifetime<T>() +where + T: Into<&u32>, //~ ERROR: `&` without an explicit lifetime name cannot be used here [E0637] +{ } fn main() {} diff --git a/src/test/ui/error-codes/E0637.stderr b/src/test/ui/error-codes/E0637.stderr index d19ebfd15a..87aaba65a7 100644 --- a/src/test/ui/error-codes/E0637.stderr +++ b/src/test/ui/error-codes/E0637.stderr @@ -1,21 +1,28 @@ error[E0637]: `'_` cannot be used here - --> $DIR/E0637.rs:1:16 + --> $DIR/E0637.rs:1:24 | -LL | struct Foo<'a: '_>(&'a u8); - | ^^ `'_` is a reserved lifetime name +LL | fn underscore_lifetime<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str { + | ^^ `'_` is a reserved lifetime name -error[E0637]: `'_` cannot be used here - --> $DIR/E0637.rs:2:12 +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/E0637.rs:13:13 | -LL | fn foo<'a: '_>(_: &'a u8) {} - | ^^ `'_` is a reserved lifetime name +LL | T: Into<&u32>, + | ^ explicit lifetime name needed here -error[E0637]: `'_` cannot be used here - --> $DIR/E0637.rs:5:10 +error[E0106]: missing lifetime specifier + --> $DIR/E0637.rs:1:62 + | +LL | fn underscore_lifetime<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str { + | ------- ------- ^^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `str1` or `str2` +help: consider introducing a named lifetime parameter | -LL | impl<'a: '_> Bar<'a> { - | ^^ `'_` is a reserved lifetime name +LL | fn underscore_lifetime<'a, '_>(str1: &'a str, str2: &'a str) -> &'a str { + | +++ ~~ ~~ ~~ error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0637`. +Some errors have detailed explanations: E0106, E0637. +For more information about an error, try `rustc --explain E0106`. diff --git a/src/test/ui/error-codes/E0659.stderr b/src/test/ui/error-codes/E0659.stderr index 2f01f54c2d..b0c73c636c 100644 --- a/src/test/ui/error-codes/E0659.stderr +++ b/src/test/ui/error-codes/E0659.stderr @@ -1,9 +1,10 @@ -error[E0659]: `foo` is ambiguous (glob import vs glob import in the same module) +error[E0659]: `foo` is ambiguous --> $DIR/E0659.rs:15:15 | LL | collider::foo(); | ^^^ ambiguous name | + = note: ambiguous because of multiple glob imports of a name in the same module note: `foo` could refer to the function imported here --> $DIR/E0659.rs:10:13 | diff --git a/src/test/ui/error-codes/e0119/complex-impl.rs b/src/test/ui/error-codes/e0119/complex-impl.rs index 7dbf93ada5..9149e4ce58 100644 --- a/src/test/ui/error-codes/e0119/complex-impl.rs +++ b/src/test/ui/error-codes/e0119/complex-impl.rs @@ -7,6 +7,5 @@ use complex_impl_support::{External, M}; struct Q; impl<R> External for (Q, R) {} //~ ERROR only traits defined -//~^ ERROR conflicting implementations of trait fn main() {} diff --git a/src/test/ui/error-codes/e0119/complex-impl.stderr b/src/test/ui/error-codes/e0119/complex-impl.stderr index 6a1a502749..654073eec2 100644 --- a/src/test/ui/error-codes/e0119/complex-impl.stderr +++ b/src/test/ui/error-codes/e0119/complex-impl.stderr @@ -1,13 +1,3 @@ -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) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: conflicting implementation in crate `complex_impl_support`: - - impl<'a, 'b, 'c, T, U, V, W> External for (T, M<'a, 'b, 'c, Box<U>, V, W>) - where <U as FnOnce<(T,)>>::Output == V, <V as Iterator>::Item == T, 'b: 'a, T: 'a, U: 'static, U: FnOnce<(T,)>, V: Iterator, V: Clone, W: Add, <W as Add>::Output: Copy; - error[E0117]: only traits defined in the current crate can be implemented for arbitrary types --> $DIR/complex-impl.rs:9:1 | @@ -19,7 +9,6 @@ LL | impl<R> External for (Q, R) {} | = note: define and implement a trait or new type instead -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0117, E0119. -For more information about an error, try `rustc --explain E0117`. +For more information about this error, try `rustc --explain E0117`. diff --git a/src/test/ui/error-codes/e0119/issue-28981.rs b/src/test/ui/error-codes/e0119/issue-28981.rs index c31b212b25..5fb7e9a991 100644 --- a/src/test/ui/error-codes/e0119/issue-28981.rs +++ b/src/test/ui/error-codes/e0119/issue-28981.rs @@ -3,6 +3,5 @@ use std::ops::Deref; struct Foo; impl<Foo> Deref for Foo { } //~ ERROR must be used -//~^ ERROR conflicting implementations fn main() {} diff --git a/src/test/ui/error-codes/e0119/issue-28981.stderr b/src/test/ui/error-codes/e0119/issue-28981.stderr index 56e8e1eb54..97b570bc7a 100644 --- a/src/test/ui/error-codes/e0119/issue-28981.stderr +++ b/src/test/ui/error-codes/e0119/issue-28981.stderr @@ -1,13 +1,3 @@ -error[E0119]: conflicting implementations of trait `std::ops::Deref` for type `&_` - --> $DIR/issue-28981.rs:5:1 - | -LL | impl<Foo> Deref for Foo { } - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: conflicting implementation in crate `core`: - - impl<T> Deref for &T - where T: ?Sized; - error[E0210]: type parameter `Foo` must be used as the type parameter for some local type (e.g., `MyStruct<Foo>`) --> $DIR/issue-28981.rs:5:6 | @@ -17,7 +7,6 @@ LL | impl<Foo> Deref for Foo { } = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local = note: only traits defined in the current crate can be implemented for a type parameter -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0119, E0210. -For more information about an error, try `rustc --explain E0119`. +For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/estr-uniq.rs b/src/test/ui/estr-uniq.rs deleted file mode 100644 index 1d0a427395..0000000000 --- a/src/test/ui/estr-uniq.rs +++ /dev/null @@ -1,15 +0,0 @@ -// run-pass - -#![allow(unused_assignments)] -#![allow(unknown_lints)] - -#![allow(dead_assignment)] - -pub fn main() { - let x : String = "hello".to_string(); - let _y : String = "there".to_string(); - let mut z = "thing".to_string(); - z = x; - assert_eq!(z.as_bytes()[0], ('h' as u8)); - assert_eq!(z.as_bytes()[4], ('o' as u8)); -} diff --git a/src/test/ui/export-import.rs b/src/test/ui/export-import.rs deleted file mode 100644 index 3f54363606..0000000000 --- a/src/test/ui/export-import.rs +++ /dev/null @@ -1,11 +0,0 @@ -use m::unexported; -//~^ ERROR: is private - -mod m { - pub fn exported() { } - - fn unexported() { } -} - - -fn main() { unexported(); } diff --git a/src/test/ui/export-import.stderr b/src/test/ui/export-import.stderr deleted file mode 100644 index 753424c7f8..0000000000 --- a/src/test/ui/export-import.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0603]: function `unexported` is private - --> $DIR/export-import.rs:1:8 - | -LL | use m::unexported; - | ^^^^^^^^^^ private function - | -note: the function `unexported` is defined here - --> $DIR/export-import.rs:7:5 - | -LL | fn unexported() { } - | ^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0603`. diff --git a/src/test/ui/export-non-interference2.rs b/src/test/ui/export-non-interference2.rs deleted file mode 100644 index 6d18b03891..0000000000 --- a/src/test/ui/export-non-interference2.rs +++ /dev/null @@ -1,11 +0,0 @@ -// run-pass - -mod foo { - pub mod bar { - pub fn y() { super::super::foo::x(); } - } - - pub fn x() { println!("x"); } -} - -pub fn main() { self::foo::bar::y(); } diff --git a/src/test/ui/export-non-interference3.rs b/src/test/ui/export-non-interference3.rs deleted file mode 100644 index 0d6b6369f9..0000000000 --- a/src/test/ui/export-non-interference3.rs +++ /dev/null @@ -1,11 +0,0 @@ -// run-pass - -pub mod foo { - pub fn x() { ::bar::x(); } -} - -pub mod bar { - pub fn x() { println!("x"); } -} - -pub fn main() { foo::x(); } diff --git a/src/test/ui/export.rs b/src/test/ui/export.rs deleted file mode 100644 index 73ceec6803..0000000000 --- a/src/test/ui/export.rs +++ /dev/null @@ -1,10 +0,0 @@ -mod foo { - pub fn x(y: isize) { log(debug, y); } - //~^ ERROR cannot find function `log` in this scope - //~| ERROR cannot find value `debug` in this scope - fn z(y: isize) { log(debug, y); } - //~^ ERROR cannot find function `log` in this scope - //~| ERROR cannot find value `debug` in this scope -} - -fn main() { foo::z(10); } //~ ERROR function `z` is private diff --git a/src/test/ui/export.stderr b/src/test/ui/export.stderr deleted file mode 100644 index 23c29b31c6..0000000000 --- a/src/test/ui/export.stderr +++ /dev/null @@ -1,40 +0,0 @@ -error[E0425]: cannot find function `log` in this scope - --> $DIR/export.rs:2:26 - | -LL | pub fn x(y: isize) { log(debug, y); } - | ^^^ not found in this scope - -error[E0425]: cannot find value `debug` in this scope - --> $DIR/export.rs:2:30 - | -LL | pub fn x(y: isize) { log(debug, y); } - | ^^^^^ not found in this scope - -error[E0425]: cannot find function `log` in this scope - --> $DIR/export.rs:5:22 - | -LL | fn z(y: isize) { log(debug, y); } - | ^^^ not found in this scope - -error[E0425]: cannot find value `debug` in this scope - --> $DIR/export.rs:5:26 - | -LL | fn z(y: isize) { log(debug, y); } - | ^^^^^ not found in this scope - -error[E0603]: function `z` is private - --> $DIR/export.rs:10:18 - | -LL | fn main() { foo::z(10); } - | ^ private function - | -note: the function `z` is defined here - --> $DIR/export.rs:5:5 - | -LL | fn z(y: isize) { log(debug, y); } - | ^^^^^^^^^^^^^^ - -error: aborting due to 5 previous errors - -Some errors have detailed explanations: E0425, E0603. -For more information about an error, try `rustc --explain E0425`. diff --git a/src/test/ui/export2.rs b/src/test/ui/export2.rs deleted file mode 100644 index 64ebeddffa..0000000000 --- a/src/test/ui/export2.rs +++ /dev/null @@ -1,11 +0,0 @@ -mod foo { - pub fn x() { bar::x(); } //~ ERROR failed to resolve: use of undeclared crate or module `bar` -} - -mod bar { - fn x() { println!("x"); } - - pub fn y() { } -} - -fn main() { foo::x(); } diff --git a/src/test/ui/export2.stderr b/src/test/ui/export2.stderr deleted file mode 100644 index 7cf47d0764..0000000000 --- a/src/test/ui/export2.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0433]: failed to resolve: use of undeclared crate or module `bar` - --> $DIR/export2.rs:2:18 - | -LL | pub fn x() { bar::x(); } - | ^^^ use of undeclared crate or module `bar` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/expr-block-slot.rs b/src/test/ui/expr-block-slot.rs deleted file mode 100644 index 54bcbb328b..0000000000 --- a/src/test/ui/expr-block-slot.rs +++ /dev/null @@ -1,13 +0,0 @@ -// run-pass -// Regression test for issue #377 - - -struct A { a: isize } -struct V { v: isize } - -pub fn main() { - let a = { let b = A {a: 3}; b }; - assert_eq!(a.a, 3); - let c = { let d = V {v: 3}; d }; - assert_eq!(c.v, 3); -} diff --git a/src/test/ui/expr-block-unique.rs b/src/test/ui/expr-block-unique.rs deleted file mode 100644 index 5fa11ad128..0000000000 --- a/src/test/ui/expr-block-unique.rs +++ /dev/null @@ -1,4 +0,0 @@ -// run-pass -#![allow(unused_braces)] - -pub fn main() { let x: Box<_> = { Box::new(100) }; assert_eq!(*x, 100); } diff --git a/src/test/ui/expr-if.rs b/src/test/ui/expr/if/expr-if.rs similarity index 100% rename from src/test/ui/expr-if.rs rename to src/test/ui/expr/if/expr-if.rs diff --git a/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr b/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr index 14d28b5964..53924e24e4 100644 --- a/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr +++ b/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr @@ -20,6 +20,11 @@ LL | | }); | |_____^ expected an `FnOnce<({integer},)>` closure, found `Option<_>` | = help: the trait `FnOnce<({integer},)>` is not implemented for `Option<_>` +note: required by a bound in `Option::<T>::and_then` + --> $SRC_DIR/core/src/option.rs:LL:COL + | +LL | pub fn and_then<U, F: FnOnce(T) -> Option<U>>(self, f: F) -> Option<U> { + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Option::<T>::and_then` error: aborting due to 2 previous errors diff --git a/src/test/ui/auxiliary/no-mangle-associated-fn.rs b/src/test/ui/extern/auxiliary/no-mangle-associated-fn.rs similarity index 100% rename from src/test/ui/auxiliary/no-mangle-associated-fn.rs rename to src/test/ui/extern/auxiliary/no-mangle-associated-fn.rs diff --git a/src/test/ui/auxiliary/reexport-should-still-link.rs b/src/test/ui/extern/auxiliary/reexport-should-still-link.rs similarity index 100% rename from src/test/ui/auxiliary/reexport-should-still-link.rs rename to src/test/ui/extern/auxiliary/reexport-should-still-link.rs diff --git a/src/test/ui/extern/extern-methods.rs b/src/test/ui/extern/extern-methods.rs index 3909b5301a..22792c1136 100644 --- a/src/test/ui/extern/extern-methods.rs +++ b/src/test/ui/extern/extern-methods.rs @@ -1,5 +1,5 @@ // run-pass -// only-i686 +// only-x86 trait A { extern "fastcall" fn test1(i: i32); diff --git a/src/test/ui/extern/extern-thiscall.rs b/src/test/ui/extern/extern-thiscall.rs index 8ce94aa71a..717df57ec4 100644 --- a/src/test/ui/extern/extern-thiscall.rs +++ b/src/test/ui/extern/extern-thiscall.rs @@ -1,5 +1,5 @@ // run-pass -// only-i686 +// only-x86 #![feature(abi_thiscall)] diff --git a/src/test/ui/extern/extern-vectorcall.rs b/src/test/ui/extern/extern-vectorcall.rs index f625eb0890..a283573c9f 100644 --- a/src/test/ui/extern/extern-vectorcall.rs +++ b/src/test/ui/extern/extern-vectorcall.rs @@ -1,7 +1,7 @@ // run-pass // revisions: x64 x32 // [x64]only-x86_64 -// [x32]only-i686 +// [x32]only-x86 #![feature(abi_vectorcall)] diff --git a/src/test/ui/issues/issue-28324.mir.stderr b/src/test/ui/extern/issue-28324.mir.stderr similarity index 100% rename from src/test/ui/issues/issue-28324.mir.stderr rename to src/test/ui/extern/issue-28324.mir.stderr diff --git a/src/test/ui/issues/issue-28324.rs b/src/test/ui/extern/issue-28324.rs similarity index 100% rename from src/test/ui/issues/issue-28324.rs rename to src/test/ui/extern/issue-28324.rs diff --git a/src/test/ui/issues/issue-28324.thir.stderr b/src/test/ui/extern/issue-28324.thir.stderr similarity index 100% rename from src/test/ui/issues/issue-28324.thir.stderr rename to src/test/ui/extern/issue-28324.thir.stderr diff --git a/src/test/ui/no-mangle-associated-fn.rs b/src/test/ui/extern/no-mangle-associated-fn.rs similarity index 100% rename from src/test/ui/no-mangle-associated-fn.rs rename to src/test/ui/extern/no-mangle-associated-fn.rs diff --git a/src/test/ui/feature-gates/feature-gate-asm_const.rs b/src/test/ui/feature-gates/feature-gate-asm_const.rs new file mode 100644 index 0000000000..c152b54c66 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-asm_const.rs @@ -0,0 +1,10 @@ +// only-x86_64 + +#![feature(asm)] + +fn main() { + unsafe { + asm!("mov eax, {}", const 123); + //~^ ERROR const operands for inline assembly are unstable + } +} diff --git a/src/test/ui/feature-gates/feature-gate-asm_const.stderr b/src/test/ui/feature-gates/feature-gate-asm_const.stderr new file mode 100644 index 0000000000..2851a9b0ae --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-asm_const.stderr @@ -0,0 +1,12 @@ +error[E0658]: const operands for inline assembly are unstable + --> $DIR/feature-gate-asm_const.rs:7:29 + | +LL | asm!("mov eax, {}", const 123); + | ^^^^^^^^^ + | + = note: see issue #72016 <https://github.com/rust-lang/rust/issues/72016> for more information + = help: add `#![feature(asm_const)]` 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-asm_experimental_arch.rs b/src/test/ui/feature-gates/feature-gate-asm_experimental_arch.rs new file mode 100644 index 0000000000..53e2a4d132 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-asm_experimental_arch.rs @@ -0,0 +1,21 @@ +// compile-flags: --target mips-unknown-linux-gnu +// needs-llvm-components: mips + +#![feature(no_core, lang_items, rustc_attrs)] +#![crate_type = "rlib"] +#![no_core] + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +unsafe fn main() { + asm!(""); + //~^ ERROR inline assembly is not stable yet on this architecture +} diff --git a/src/test/ui/feature-gates/feature-gate-asm_experimental_arch.stderr b/src/test/ui/feature-gates/feature-gate-asm_experimental_arch.stderr new file mode 100644 index 0000000000..1b4188ae1a --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-asm_experimental_arch.stderr @@ -0,0 +1,12 @@ +error[E0658]: inline assembly is not stable yet on this architecture + --> $DIR/feature-gate-asm_experimental_arch.rs:19:5 + | +LL | asm!(""); + | ^^^^^^^^ + | + = note: see issue #72016 <https://github.com/rust-lang/rust/issues/72016> for more information + = help: add `#![feature(asm_experimental_arch)]` 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-asm_sym.rs b/src/test/ui/feature-gates/feature-gate-asm_sym.rs new file mode 100644 index 0000000000..d89c7dd0ef --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-asm_sym.rs @@ -0,0 +1,10 @@ +// only-x86_64 + +#![feature(asm)] + +fn main() { + unsafe { + asm!("mov eax, {}", sym main); + //~^ ERROR sym operands for inline assembly are unstable + } +} diff --git a/src/test/ui/feature-gates/feature-gate-asm_sym.stderr b/src/test/ui/feature-gates/feature-gate-asm_sym.stderr new file mode 100644 index 0000000000..99b61b829f --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-asm_sym.stderr @@ -0,0 +1,12 @@ +error[E0658]: sym operands for inline assembly are unstable + --> $DIR/feature-gate-asm_sym.rs:7:29 + | +LL | asm!("mov eax, {}", sym main); + | ^^^^^^^^ + | + = note: see issue #72016 <https://github.com/rust-lang/rust/issues/72016> for more information + = help: add `#![feature(asm_sym)]` 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-associated_type_bounds.stderr b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr index 8df5fbcc7e..8c5d72d7ef 100644 --- a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr +++ b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr @@ -139,13 +139,6 @@ error[E0277]: the trait bound `<<Self as _Tr3>::A as Iterator>::Item: Copy` is n LL | type A: Iterator<Item: Copy>; | ^^^^ the trait `Copy` is not implemented for `<<Self as _Tr3>::A as Iterator>::Item` | -note: required by a bound in `Copy` - --> $SRC_DIR/core/src/marker.rs:LL:COL - | -LL | / pub trait Copy: Clone { -LL | | // Empty. -LL | | } - | |_^ required by this bound in `Copy` help: consider further restricting the associated type | LL | trait _Tr3 where <<Self as _Tr3>::A as Iterator>::Item: Copy { diff --git a/src/test/ui/feature-gates/feature-gate-doc_keyword.rs b/src/test/ui/feature-gates/feature-gate-doc_keyword.rs deleted file mode 100644 index 4bb9a40deb..0000000000 --- a/src/test/ui/feature-gates/feature-gate-doc_keyword.rs +++ /dev/null @@ -1,5 +0,0 @@ -#[doc(keyword = "match")] //~ ERROR: `#[doc(keyword)]` is experimental -/// wonderful -mod foo{} - -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-doc_keyword.stderr b/src/test/ui/feature-gates/feature-gate-doc_keyword.stderr deleted file mode 100644 index c5dc7d537f..0000000000 --- a/src/test/ui/feature-gates/feature-gate-doc_keyword.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: `#[doc(keyword)]` is experimental - --> $DIR/feature-gate-doc_keyword.rs:1:1 - | -LL | #[doc(keyword = "match")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #51315 <https://github.com/rust-lang/rust/issues/51315> for more information - = help: add `#![feature(doc_keyword)]` 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-inline_const_pat.rs b/src/test/ui/feature-gates/feature-gate-inline_const_pat.rs new file mode 100644 index 0000000000..3d0df289fb --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-inline_const_pat.rs @@ -0,0 +1,4 @@ +fn main() { + let const { () } = (); + //~^ ERROR inline-const in pattern position is experimental [E0658] +} diff --git a/src/test/ui/feature-gates/feature-gate-inline_const_pat.stderr b/src/test/ui/feature-gates/feature-gate-inline_const_pat.stderr new file mode 100644 index 0000000000..ca533d8505 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-inline_const_pat.stderr @@ -0,0 +1,12 @@ +error[E0658]: inline-const in pattern position is experimental + --> $DIR/feature-gate-inline_const_pat.rs:2:9 + | +LL | let const { () } = (); + | ^^^^^ + | + = note: see issue #76001 <https://github.com/rust-lang/rust/issues/76001> for more information + = help: add `#![feature(inline_const_pat)]` 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-relaxed_struct_unsize.rs b/src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.rs deleted file mode 100644 index 0cfd0a0b97..0000000000 --- a/src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.rs +++ /dev/null @@ -1,10 +0,0 @@ -// Test that we allow unsizing even if there is an unchanged param in the -// field getting unsized. -struct A<T, U: ?Sized + 'static>(T, B<T, U>); -struct B<T, U: ?Sized>(T, U); - -fn main() { - let x: A<[u32; 1], [u32; 1]> = A([0; 1], B([0; 1], [0; 1])); - let y: &A<[u32; 1], [u32]> = &x; //~ ERROR mismatched types - assert_eq!(y.1.1.len(), 1); -} diff --git a/src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.stderr b/src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.stderr deleted file mode 100644 index f62def4772..0000000000 --- a/src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/feature-gate-relaxed_struct_unsize.rs:8:34 - | -LL | let y: &A<[u32; 1], [u32]> = &x; - | ------------------- ^^ expected slice `[u32]`, found array `[u32; 1]` - | | - | expected due to this - | - = note: expected reference `&A<[u32; 1], [u32]>` - found reference `&A<[u32; 1], [u32; 1]>` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/feature-gates/feature-gate-rustdoc_internals.rs b/src/test/ui/feature-gates/feature-gate-rustdoc_internals.rs new file mode 100644 index 0000000000..d2ff4f6200 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-rustdoc_internals.rs @@ -0,0 +1,5 @@ +#[doc(keyword = "match")] //~ ERROR: `#[doc(keyword)]` is meant for internal use only +/// wonderful +mod foo {} + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-rustdoc_internals.stderr b/src/test/ui/feature-gates/feature-gate-rustdoc_internals.stderr new file mode 100644 index 0000000000..e96461ac38 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-rustdoc_internals.stderr @@ -0,0 +1,12 @@ +error[E0658]: `#[doc(keyword)]` is meant for internal use only + --> $DIR/feature-gate-rustdoc_internals.rs:1:1 + | +LL | #[doc(keyword = "match")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #90418 <https://github.com/rust-lang/rust/issues/90418> for more information + = help: add `#![feature(rustdoc_internals)]` 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-trivial_bounds.stderr b/src/test/ui/feature-gates/feature-gate-trivial_bounds.stderr index 78904b383f..28c49c33bf 100644 --- a/src/test/ui/feature-gates/feature-gate-trivial_bounds.stderr +++ b/src/test/ui/feature-gates/feature-gate-trivial_bounds.stderr @@ -1,87 +1,71 @@ error[E0277]: the trait bound `i32: Foo` is not satisfied - --> $DIR/feature-gate-trivial_bounds.rs:10:1 + --> $DIR/feature-gate-trivial_bounds.rs:10:14 | LL | enum E where i32: Foo { V } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32` + | ^^^^^^^^ the trait `Foo` is not implemented for `i32` | = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `i32: Foo` is not satisfied - --> $DIR/feature-gate-trivial_bounds.rs:12:1 + --> $DIR/feature-gate-trivial_bounds.rs:12:16 | LL | struct S where i32: Foo; - | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32` + | ^^^^^^^^ the trait `Foo` is not implemented for `i32` | = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `i32: Foo` is not satisfied - --> $DIR/feature-gate-trivial_bounds.rs:14:1 + --> $DIR/feature-gate-trivial_bounds.rs:14:15 | LL | trait T where i32: Foo {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32` + | ^^^^^^^^ the trait `Foo` is not implemented for `i32` | = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `i32: Foo` is not satisfied - --> $DIR/feature-gate-trivial_bounds.rs:16:1 + --> $DIR/feature-gate-trivial_bounds.rs:16:15 | LL | union U where i32: Foo { f: i32 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32` + | ^^^^^^^^ the trait `Foo` is not implemented for `i32` | = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `i32: Foo` is not satisfied - --> $DIR/feature-gate-trivial_bounds.rs:20:1 + --> $DIR/feature-gate-trivial_bounds.rs:20:23 | -LL | / impl Foo for () where i32: Foo { -LL | | fn test(&self) { -LL | | 3i32.test(); -LL | | Foo::test(&4i32); -LL | | generic_function(5i32); -LL | | } -LL | | } - | |_^ the trait `Foo` is not implemented for `i32` +LL | impl Foo for () where i32: Foo { + | ^^^^^^^^ the trait `Foo` is not implemented for `i32` | = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `i32: Foo` is not satisfied - --> $DIR/feature-gate-trivial_bounds.rs:28:1 + --> $DIR/feature-gate-trivial_bounds.rs:28:14 | -LL | / fn f() where i32: Foo -LL | | { -LL | | let s = S; -LL | | 3i32.test(); -LL | | Foo::test(&4i32); -LL | | generic_function(5i32); -LL | | } - | |_^ the trait `Foo` is not implemented for `i32` +LL | fn f() where i32: Foo + | ^^^^^^^^ the trait `Foo` is not implemented for `i32` | = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `String: Neg` is not satisfied - --> $DIR/feature-gate-trivial_bounds.rs:36:1 + --> $DIR/feature-gate-trivial_bounds.rs:36:38 | -LL | / fn use_op(s: String) -> String where String: ::std::ops::Neg<Output=String> { -LL | | -s -LL | | } - | |_^ the trait `Neg` is not implemented for `String` +LL | fn use_op(s: String) -> String where String: ::std::ops::Neg<Output=String> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Neg` is not implemented for `String` | = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: `i32` is not an iterator - --> $DIR/feature-gate-trivial_bounds.rs:40:1 + --> $DIR/feature-gate-trivial_bounds.rs:40:20 | -LL | / fn use_for() where i32: Iterator { -LL | | for _ in 2i32 {} -LL | | } - | |_^ `i32` is not an iterator +LL | fn use_for() where i32: Iterator { + | ^^^^^^^^^^^^^ `i32` is not an iterator | = help: the trait `Iterator` is not implemented for `i32` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` @@ -89,22 +73,20 @@ LL | | } = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/feature-gate-trivial_bounds.rs:52:1 + --> $DIR/feature-gate-trivial_bounds.rs:52:32 | LL | struct TwoStrs(str, str) where str: Sized; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | ^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time - --> $DIR/feature-gate-trivial_bounds.rs:55:1 + --> $DIR/feature-gate-trivial_bounds.rs:55:26 | -LL | / fn unsized_local() where Dst<dyn A>: Sized { -LL | | let x: Dst<dyn A> = *(Box::new(Dst { x: 1 }) as Box<Dst<dyn A>>); -LL | | } - | |_^ doesn't have a size known at compile-time +LL | fn unsized_local() where Dst<dyn A>: Sized { + | ^^^^^^^^^^^^^^^^^ 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)>` @@ -116,12 +98,10 @@ LL | struct Dst<X: ?Sized> { = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/feature-gate-trivial_bounds.rs:59:1 + --> $DIR/feature-gate-trivial_bounds.rs:59:30 | -LL | / fn return_str() -> str where str: Sized { -LL | | *"Sized".to_string().into_boxed_str() -LL | | } - | |_^ doesn't have a size known at compile-time +LL | fn return_str() -> str where str: Sized { + | ^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` = help: see issue #48214 diff --git a/src/test/ui/feature-gates/feature-gate-untagged_unions.stderr b/src/test/ui/feature-gates/feature-gate-untagged_unions.stderr index ed973871b3..0967cb7ba8 100644 --- a/src/test/ui/feature-gates/feature-gate-untagged_unions.stderr +++ b/src/test/ui/feature-gates/feature-gate-untagged_unions.stderr @@ -13,11 +13,10 @@ error[E0740]: unions may not contain fields that need dropping LL | a: String, | ^^^^^^^^^ | -note: `std::mem::ManuallyDrop` can be used to wrap the type - --> $DIR/feature-gate-untagged_unions.rs:16:5 +help: wrap the type with `std::mem::ManuallyDrop` and ensure it is manually dropped | -LL | a: String, - | ^^^^^^^^^ +LL | a: std::mem::ManuallyDrop<String>, + | +++++++++++++++++++++++ + error[E0740]: unions may not contain fields that need dropping --> $DIR/feature-gate-untagged_unions.rs:24:5 @@ -25,11 +24,10 @@ error[E0740]: unions may not contain fields that need dropping LL | a: T, | ^^^^ | -note: `std::mem::ManuallyDrop` can be used to wrap the type - --> $DIR/feature-gate-untagged_unions.rs:24:5 +help: wrap the type with `std::mem::ManuallyDrop` and ensure it is manually dropped | -LL | a: T, - | ^^^^ +LL | a: std::mem::ManuallyDrop<T>, + | +++++++++++++++++++++++ + error: aborting due to 3 previous errors diff --git a/src/test/ui/gated-bad-feature.rs b/src/test/ui/feature-gates/gated-bad-feature.rs similarity index 100% rename from src/test/ui/gated-bad-feature.rs rename to src/test/ui/feature-gates/gated-bad-feature.rs diff --git a/src/test/ui/gated-bad-feature.stderr b/src/test/ui/feature-gates/gated-bad-feature.stderr similarity index 100% rename from src/test/ui/gated-bad-feature.stderr rename to src/test/ui/feature-gates/gated-bad-feature.stderr 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 44abe160f8..1fe133ac2b 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 @@ -134,4 +134,27 @@ mod start { //~^ ERROR: `start` attribute can only be used on functions } +#[repr(C)] +//~^ ERROR: attribute should be applied to a struct, enum, or union +mod repr { +//~^ NOTE not a struct, enum, or union + mod inner { #![repr(C)] } + //~^ ERROR: attribute should be applied to a struct, enum, or union + //~| NOTE not a struct, enum, or union + + #[repr(C)] fn f() { } + //~^ ERROR: attribute should be applied to a struct, enum, or union + //~| NOTE not a struct, enum, or union + + struct S; + + #[repr(C)] type T = S; + //~^ ERROR: attribute should be applied to a struct, enum, or union + //~| NOTE not a struct, enum, or union + + #[repr(C)] impl S { } + //~^ ERROR: attribute should be applied to a struct, enum, or union + //~| NOTE not a struct, enum, or union +} + fn main() {} 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 aed1312155..9e2e2d4137 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 @@ -91,6 +91,21 @@ LL | | } LL | | } | |_- not a free function, impl method or static +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:137:8 + | +LL | #[repr(C)] + | ^ +LL | +LL | / mod repr { +LL | | +LL | | mod inner { #![repr(C)] } +LL | | +... | +LL | | +LL | | } + | |_- not a struct, enum, or union + error: attribute should be applied to an `extern crate` item --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:25:1 | @@ -235,7 +250,31 @@ error: attribute should be applied to a free function, impl method or static LL | #[export_name = "2200"] fn bar() {} | ^^^^^^^^^^^^^^^^^^^^^^^ ----------- not a free function, impl method or static -error: aborting due to 34 previous errors +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:141:25 + | +LL | mod inner { #![repr(C)] } + | --------------------^---- not a struct, enum, or union + +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:145:12 + | +LL | #[repr(C)] fn f() { } + | ^ ---------- not a struct, enum, or union + +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:151:12 + | +LL | #[repr(C)] type T = S; + | ^ ----------- not a struct, enum, or union + +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:155:12 + | +LL | #[repr(C)] impl S { } + | ^ ---------- not a struct, enum, or union + +error: aborting due to 39 previous errors -Some errors have detailed explanations: E0518, E0658. -For more information about an error, try `rustc --explain E0518`. +Some errors have detailed explanations: E0517, E0518, E0658. +For more information about an error, try `rustc --explain E0517`. 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 97fa775967..1ddf8508cc 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 @@ -245,19 +245,6 @@ mod bench { impl S { } } -#[repr()] -mod repr { - mod inner { #![repr()] } - - #[repr()] fn f() { } - - struct S; - - #[repr()] type T = S; - - #[repr()] impl S { } -} - #[path = "3800"] mod path { mod inner { #![path="3800"] } 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 214584f47e..b98374bfa8 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 @@ -173,7 +173,7 @@ LL | #[deny(x5100)] impl S { } | ^^^^^ warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:412:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:399:17 | LL | mod inner { #![macro_escape] } | ^^^^^^^^^^^^^^^^ @@ -181,7 +181,7 @@ 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:409:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:396:1 | LL | #[macro_escape] | ^^^^^^^^^^^^^^^ @@ -213,13 +213,13 @@ LL | #![warn(unused_attributes, unknown_lints)] | ^^^^^^^^^^^^^^^^^ warning: `#[automatically_derived]` only has an effect on items - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:278:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:265:1 | LL | #[automatically_derived] | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:296:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:283:1 | LL | #[no_mangle] | ^^^^^^^^^^^^ @@ -236,31 +236,31 @@ 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: `#[should_panic]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:336:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:323:1 | LL | #[should_panic] | ^^^^^^^^^^^^^^^ warning: `#[ignore]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:354:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:341:1 | LL | #[ignore] | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:389:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:376:1 | LL | #[reexport_test_harness_main = "2900"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:429:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:416:1 | LL | #[no_std] | ^^^^^^^^^ warning: attribute should be applied to a function - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:465:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:452:1 | LL | #[cold] | ^^^^^^^ @@ -277,7 +277,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:494:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:481:1 | LL | #[link_name = "1900"] | ^^^^^^^^^^^^^^^^^^^^^ @@ -294,7 +294,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:533:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:520:1 | LL | #[link_section = "1800"] | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -311,37 +311,37 @@ 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: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:624:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:611: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:643:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:630: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:662:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:649: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:682:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:669: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:714:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:701: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:733:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:720:1 | LL | #[type_length_limit="0100"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -443,55 +443,55 @@ LL | #[macro_export] impl S { } | ^^^^^^^^^^^^^^^ warning: `#[path]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:265:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:252:5 | LL | #[path = "3800"] fn f() { } | ^^^^^^^^^^^^^^^^ warning: `#[path]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:268:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:255:5 | LL | #[path = "3800"] struct S; | ^^^^^^^^^^^^^^^^ warning: `#[path]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:271:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:258:5 | LL | #[path = "3800"] type T = S; | ^^^^^^^^^^^^^^^^ warning: `#[path]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:274:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:261:5 | LL | #[path = "3800"] impl S { } | ^^^^^^^^^^^^^^^^ warning: `#[automatically_derived]` only has an effect on items - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:281:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:268:17 | LL | mod inner { #![automatically_derived] } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[automatically_derived]` only has an effect on items - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:284:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:271:5 | LL | #[automatically_derived] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[automatically_derived]` only has an effect on items - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:287:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:274:5 | LL | #[automatically_derived] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[automatically_derived]` only has an effect on items - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:290:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:277:5 | LL | #[automatically_derived] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:301:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:288:17 | LL | mod inner { #![no_mangle] } | ------------^^^^^^^^^^^^^-- not a free function, impl method or static @@ -499,7 +499,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 free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:308:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:295:5 | LL | #[no_mangle] struct S; | ^^^^^^^^^^^^ --------- not a free function, impl method or static @@ -507,7 +507,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 free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:313:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:300:5 | LL | #[no_mangle] type T = S; | ^^^^^^^^^^^^ ----------- not a free function, impl method or static @@ -515,7 +515,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 free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:318:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:305:5 | LL | #[no_mangle] impl S { } | ^^^^^^^^^^^^ ---------- not a free function, impl method or static @@ -523,7 +523,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 free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:324:9 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:311:9 | LL | #[no_mangle] fn foo(); | ^^^^^^^^^^^^ --------- not a free function, impl method or static @@ -531,7 +531,7 @@ LL | #[no_mangle] fn foo(); = 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 free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:329:9 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:316:9 | LL | #[no_mangle] fn bar() {} | ^^^^^^^^^^^^ ----------- not a free function, impl method or static @@ -539,163 +539,163 @@ LL | #[no_mangle] fn bar() {} = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[should_panic]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:339:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:326:17 | LL | mod inner { #![should_panic] } | ^^^^^^^^^^^^^^^^ warning: `#[should_panic]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:344:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:331:5 | LL | #[should_panic] struct S; | ^^^^^^^^^^^^^^^ warning: `#[should_panic]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:347:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:334:5 | LL | #[should_panic] type T = S; | ^^^^^^^^^^^^^^^ warning: `#[should_panic]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:350:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:337:5 | LL | #[should_panic] impl S { } | ^^^^^^^^^^^^^^^ warning: `#[ignore]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:357:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:344:17 | LL | mod inner { #![ignore] } | ^^^^^^^^^^ warning: `#[ignore]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:362:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:349:5 | LL | #[ignore] struct S; | ^^^^^^^^^ warning: `#[ignore]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:365:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:352:5 | LL | #[ignore] type T = S; | ^^^^^^^^^ warning: `#[ignore]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:368:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:355:5 | LL | #[ignore] impl S { } | ^^^^^^^^^ warning: `#[no_implicit_prelude]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:376:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:363:5 | LL | #[no_implicit_prelude] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: `#[no_implicit_prelude]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:379:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:366:5 | LL | #[no_implicit_prelude] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: `#[no_implicit_prelude]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:382:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:369:5 | LL | #[no_implicit_prelude] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: `#[no_implicit_prelude]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:385:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:372:5 | LL | #[no_implicit_prelude] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:392:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:379:17 | LL | mod inner { #![reexport_test_harness_main="2900"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:395:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:382:5 | LL | #[reexport_test_harness_main = "2900"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:398:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:385:5 | LL | #[reexport_test_harness_main = "2900"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:401:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:388:5 | LL | #[reexport_test_harness_main = "2900"] 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:404:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:391:5 | LL | #[reexport_test_harness_main = "2900"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[macro_escape]` only has an effect on `extern crate` and modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:416:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:403:5 | LL | #[macro_escape] fn f() { } | ^^^^^^^^^^^^^^^ warning: `#[macro_escape]` only has an effect on `extern crate` and modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:419:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:406:5 | LL | #[macro_escape] struct S; | ^^^^^^^^^^^^^^^ warning: `#[macro_escape]` only has an effect on `extern crate` and modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:422:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:409:5 | LL | #[macro_escape] type T = S; | ^^^^^^^^^^^^^^^ warning: `#[macro_escape]` only has an effect on `extern crate` and modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:425:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:412:5 | LL | #[macro_escape] impl S { } | ^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:432:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:419:17 | LL | mod inner { #![no_std] } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:435:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:422: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:438:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:425: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:441:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:428: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:444:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:431:5 | LL | #[no_std] impl S { } | ^^^^^^^^^ warning: attribute should be applied to a function - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:471:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:458:17 | LL | mod inner { #![cold] } | ------------^^^^^^^^-- not a function @@ -703,7 +703,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:478:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:465:5 | LL | #[cold] struct S; | ^^^^^^^ --------- not a function @@ -711,7 +711,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:483:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:470:5 | LL | #[cold] type T = S; | ^^^^^^^ ----------- not a function @@ -719,7 +719,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:488:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:475:5 | LL | #[cold] impl S { } | ^^^^^^^ ---------- not a function @@ -727,7 +727,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:500:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:487:5 | LL | #[link_name = "1900"] | ^^^^^^^^^^^^^^^^^^^^^ @@ -737,13 +737,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:500:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:487:5 | LL | #[link_name = "1900"] | ^^^^^^^^^^^^^^^^^^^^^ warning: attribute should be applied to a foreign function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:507:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:494:17 | LL | mod inner { #![link_name="1900"] } | ------------^^^^^^^^^^^^^^^^^^^^-- not a foreign function or static @@ -751,7 +751,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:512:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:499:5 | LL | #[link_name = "1900"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^ ---------- not a foreign function or static @@ -759,7 +759,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:517:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:504:5 | LL | #[link_name = "1900"] struct S; | ^^^^^^^^^^^^^^^^^^^^^ --------- not a foreign function or static @@ -767,7 +767,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:522:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:509:5 | LL | #[link_name = "1900"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^ ----------- not a foreign function or static @@ -775,7 +775,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:527:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:514:5 | LL | #[link_name = "1900"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^ ---------- not a foreign function or static @@ -783,7 +783,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:539:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:526:17 | LL | mod inner { #![link_section="1800"] } | ------------^^^^^^^^^^^^^^^^^^^^^^^-- not a function or static @@ -791,7 +791,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:546:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:533:5 | LL | #[link_section = "1800"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^ --------- not a function or static @@ -799,7 +799,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:551:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:538:5 | LL | #[link_section = "1800"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^ ----------- not a function or static @@ -807,7 +807,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:556:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:543:5 | LL | #[link_section = "1800"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^ ---------- not a function or static @@ -815,181 +815,181 @@ 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: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:627:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:614:17 | LL | mod inner { #![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:630:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:617: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:633:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:620: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:636:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:623: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:639:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:626:5 | LL | #[crate_name = "0900"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:646:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:633:17 | LL | mod inner { #![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:649:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:636: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:652:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:639: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:655:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:642: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:658:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:645:5 | LL | #[crate_type = "0800"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:665:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:652:17 | LL | mod inner { #![feature(x0600)] } | ^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:668:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:655: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:671:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:658: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:674:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:661: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:677:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:664:5 | LL | #[feature(x0600)] impl S { } | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:685:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:672:17 | LL | mod inner { #![no_main] } | ^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:675: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:691:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:678: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:694:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:681: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:697:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:684:5 | LL | #[no_main] impl S { } | ^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:717:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:704:17 | LL | mod inner { #![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:720:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:707: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:723:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:710: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:726:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:713: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:729:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:716:5 | LL | #[recursion_limit="0200"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:736:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:723:17 | LL | mod inner { #![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:739:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:726: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:742:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:729: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:745:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:732: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:748:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:735:5 | LL | #[type_length_limit="0100"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-macro_use.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-macro_use.stderr index c0d2df3753..9a12851f20 100644 --- a/src/test/ui/feature-gates/issue-43106-gating-of-macro_use.stderr +++ b/src/test/ui/feature-gates/issue-43106-gating-of-macro_use.stderr @@ -24,10 +24,10 @@ LL | #[macro_use = "2700"] struct S; | help: the following are the possible correct uses | -LL | #[macro_use] struct S; - | ~~~~~~~~~~~~ LL | #[macro_use(name1, name2, ...)] struct S; | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | #[macro_use] struct S; + | ~~~~~~~~~~~~ error: aborting due to 4 previous errors diff --git a/src/test/ui/stable-features.rs b/src/test/ui/feature-gates/stable-features.rs similarity index 100% rename from src/test/ui/stable-features.rs rename to src/test/ui/feature-gates/stable-features.rs diff --git a/src/test/ui/stable-features.stderr b/src/test/ui/feature-gates/stable-features.stderr similarity index 100% rename from src/test/ui/stable-features.stderr rename to src/test/ui/feature-gates/stable-features.stderr diff --git a/src/test/ui/fmt/feature-gate-format-args-capture.rs b/src/test/ui/fmt/feature-gate-format-args-capture.rs deleted file mode 100644 index 21af916109..0000000000 --- a/src/test/ui/fmt/feature-gate-format-args-capture.rs +++ /dev/null @@ -1,6 +0,0 @@ -fn main() { - format!("{foo}"); //~ ERROR: there is no argument named `foo` - - // panic! doesn't hit format_args! unless there are two or more arguments. - panic!("{foo} {bar}", bar=1); //~ ERROR: there is no argument named `foo` -} diff --git a/src/test/ui/fmt/feature-gate-format-args-capture.stderr b/src/test/ui/fmt/feature-gate-format-args-capture.stderr deleted file mode 100644 index f08f1651cb..0000000000 --- a/src/test/ui/fmt/feature-gate-format-args-capture.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: there is no argument named `foo` - --> $DIR/feature-gate-format-args-capture.rs:2:14 - | -LL | format!("{foo}"); - | ^^^^^ - | - = help: if you intended to capture `foo` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes - -error: there is no argument named `foo` - --> $DIR/feature-gate-format-args-capture.rs:5:13 - | -LL | panic!("{foo} {bar}", bar=1); - | ^^^^^ - | - = help: if you intended to capture `foo` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/fmt/format-args-capture-macro-hygiene.rs b/src/test/ui/fmt/format-args-capture-macro-hygiene.rs index 6ca7dcc216..fdbd93836e 100644 --- a/src/test/ui/fmt/format-args-capture-macro-hygiene.rs +++ b/src/test/ui/fmt/format-args-capture-macro-hygiene.rs @@ -1,5 +1,3 @@ -#![feature(format_args_capture)] - fn main() { format!(concat!("{foo}")); //~ ERROR: there is no argument named `foo` format!(concat!("{ba", "r} {}"), 1); //~ ERROR: there is no argument named `bar` diff --git a/src/test/ui/fmt/format-args-capture-macro-hygiene.stderr b/src/test/ui/fmt/format-args-capture-macro-hygiene.stderr index 33cd89ad5a..9423e8c819 100644 --- a/src/test/ui/fmt/format-args-capture-macro-hygiene.stderr +++ b/src/test/ui/fmt/format-args-capture-macro-hygiene.stderr @@ -1,5 +1,5 @@ error: there is no argument named `foo` - --> $DIR/format-args-capture-macro-hygiene.rs:4:13 + --> $DIR/format-args-capture-macro-hygiene.rs:2:13 | LL | format!(concat!("{foo}")); | ^^^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | format!(concat!("{foo}")); = note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info) error: there is no argument named `bar` - --> $DIR/format-args-capture-macro-hygiene.rs:5:13 + --> $DIR/format-args-capture-macro-hygiene.rs:3:13 | LL | format!(concat!("{ba", "r} {}"), 1); | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/fmt/format-args-capture-missing-variables.rs b/src/test/ui/fmt/format-args-capture-missing-variables.rs index 3a4b6144b0..46fc083cb7 100644 --- a/src/test/ui/fmt/format-args-capture-missing-variables.rs +++ b/src/test/ui/fmt/format-args-capture-missing-variables.rs @@ -1,5 +1,3 @@ -#![feature(format_args_capture)] - fn main() { format!("{} {foo} {} {bar} {}", 1, 2, 3); //~^ ERROR: cannot find value `foo` in this scope diff --git a/src/test/ui/fmt/format-args-capture-missing-variables.stderr b/src/test/ui/fmt/format-args-capture-missing-variables.stderr index ec2faa4185..d53c206003 100644 --- a/src/test/ui/fmt/format-args-capture-missing-variables.stderr +++ b/src/test/ui/fmt/format-args-capture-missing-variables.stderr @@ -1,5 +1,5 @@ error: named argument never used - --> $DIR/format-args-capture-missing-variables.rs:10:51 + --> $DIR/format-args-capture-missing-variables.rs:8:51 | LL | format!("{valuea} {valueb}", valuea=5, valuec=7); | ------------------- ^ named argument never used @@ -7,37 +7,37 @@ LL | format!("{valuea} {valueb}", valuea=5, valuec=7); | formatting specifier missing error[E0425]: cannot find value `foo` in this scope - --> $DIR/format-args-capture-missing-variables.rs:4:17 + --> $DIR/format-args-capture-missing-variables.rs:2:17 | LL | format!("{} {foo} {} {bar} {}", 1, 2, 3); | ^^^^^ not found in this scope error[E0425]: cannot find value `bar` in this scope - --> $DIR/format-args-capture-missing-variables.rs:4:26 + --> $DIR/format-args-capture-missing-variables.rs:2:26 | LL | format!("{} {foo} {} {bar} {}", 1, 2, 3); | ^^^^^ not found in this scope error[E0425]: cannot find value `foo` in this scope - --> $DIR/format-args-capture-missing-variables.rs:8:14 + --> $DIR/format-args-capture-missing-variables.rs:6:14 | LL | format!("{foo}"); | ^^^^^ not found in this scope error[E0425]: cannot find value `valueb` in this scope - --> $DIR/format-args-capture-missing-variables.rs:10:23 + --> $DIR/format-args-capture-missing-variables.rs:8:23 | LL | format!("{valuea} {valueb}", valuea=5, valuec=7); | ^^^^^^^^ not found in this scope error[E0425]: cannot find value `foo` in this scope - --> $DIR/format-args-capture-missing-variables.rs:16:9 + --> $DIR/format-args-capture-missing-variables.rs:14:9 | LL | {foo} | ^^^^^ not found in this scope error[E0425]: cannot find value `foo` in this scope - --> $DIR/format-args-capture-missing-variables.rs:21:13 + --> $DIR/format-args-capture-missing-variables.rs:19:13 | LL | panic!("{foo} {bar}", bar=1); | ^^^^^ not found in this scope diff --git a/src/test/ui/fmt/format-args-capture.rs b/src/test/ui/fmt/format-args-capture.rs index b30e9a47a1..e830a5bc9c 100644 --- a/src/test/ui/fmt/format-args-capture.rs +++ b/src/test/ui/fmt/format-args-capture.rs @@ -1,5 +1,4 @@ // run-pass -#![feature(format_args_capture)] #![feature(cfg_panic)] fn main() { diff --git a/src/test/ui/fmt/ifmt-bad-arg.rs b/src/test/ui/fmt/ifmt-bad-arg.rs index a0b0a8fb98..b3e54ed32a 100644 --- a/src/test/ui/fmt/ifmt-bad-arg.rs +++ b/src/test/ui/fmt/ifmt-bad-arg.rs @@ -25,10 +25,10 @@ fn main() { //~^ ERROR: invalid reference to positional arguments 3, 4 and 5 (there are 3 arguments) format!("{} {foo} {} {bar} {}", 1, 2, 3); - //~^ ERROR: there is no argument named `foo` - //~^^ ERROR: there is no argument named `bar` + //~^ ERROR: cannot find value `foo` in this scope + //~^^ ERROR: cannot find value `bar` in this scope - format!("{foo}"); //~ ERROR: no argument named `foo` + format!("{foo}"); //~ ERROR: cannot find value `foo` in this scope format!("", 1, 2); //~ ERROR: multiple unused formatting arguments format!("{}", 1, 2); //~ ERROR: argument never used format!("{1}", 1, 2); //~ ERROR: argument never used @@ -43,7 +43,7 @@ fn main() { // bad named arguments, #35082 format!("{valuea} {valueb}", valuea=5, valuec=7); - //~^ ERROR there is no argument named `valueb` + //~^ ERROR cannot find value `valueb` in this scope //~^^ ERROR named argument never used // bad syntax of the format string @@ -60,7 +60,7 @@ fn main() { {foo} "##); - //~^^^ ERROR: there is no argument named `foo` + //~^^^ ERROR: cannot find value `foo` in this scope // bad syntax in format string with multiple newlines, #53836 format!("first number: {} diff --git a/src/test/ui/fmt/ifmt-bad-arg.stderr b/src/test/ui/fmt/ifmt-bad-arg.stderr index f4c84e22fa..acc4e95f5b 100644 --- a/src/test/ui/fmt/ifmt-bad-arg.stderr +++ b/src/test/ui/fmt/ifmt-bad-arg.stderr @@ -58,30 +58,6 @@ LL | format!("{name} {value} {} {} {} {} {} {}", 0, name=1, value=2); | = note: positional arguments are zero-based -error: there is no argument named `foo` - --> $DIR/ifmt-bad-arg.rs:27:17 - | -LL | format!("{} {foo} {} {bar} {}", 1, 2, 3); - | ^^^^^ - | - = help: if you intended to capture `foo` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes - -error: there is no argument named `bar` - --> $DIR/ifmt-bad-arg.rs:27:26 - | -LL | format!("{} {foo} {} {bar} {}", 1, 2, 3); - | ^^^^^ - | - = help: if you intended to capture `bar` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes - -error: there is no argument named `foo` - --> $DIR/ifmt-bad-arg.rs:31:14 - | -LL | format!("{foo}"); - | ^^^^^ - | - = help: if you intended to capture `foo` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes - error: multiple unused formatting arguments --> $DIR/ifmt-bad-arg.rs:32:17 | @@ -156,14 +132,6 @@ LL | format!("{foo} {} {}", foo=1, 2); | | | named argument -error: there is no argument named `valueb` - --> $DIR/ifmt-bad-arg.rs:45:23 - | -LL | format!("{valuea} {valueb}", valuea=5, valuec=7); - | ^^^^^^^^ - | - = help: if you intended to capture `valueb` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes - error: named argument never used --> $DIR/ifmt-bad-arg.rs:45:51 | @@ -208,14 +176,6 @@ LL | format!("foo %s baz", "bar"); | = note: printf formatting not supported; see the documentation for `std::fmt` -error: there is no argument named `foo` - --> $DIR/ifmt-bad-arg.rs:60:9 - | -LL | {foo} - | ^^^^^ - | - = help: if you intended to capture `foo` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes - error: invalid format string: expected `'}'`, found `'t'` --> $DIR/ifmt-bad-arg.rs:75:1 | @@ -302,6 +262,36 @@ LL | println!("{:.*}"); = note: positional arguments are zero-based = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html +error[E0425]: cannot find value `foo` in this scope + --> $DIR/ifmt-bad-arg.rs:27:17 + | +LL | format!("{} {foo} {} {bar} {}", 1, 2, 3); + | ^^^^^ not found in this scope + +error[E0425]: cannot find value `bar` in this scope + --> $DIR/ifmt-bad-arg.rs:27:26 + | +LL | format!("{} {foo} {} {bar} {}", 1, 2, 3); + | ^^^^^ not found in this scope + +error[E0425]: cannot find value `foo` in this scope + --> $DIR/ifmt-bad-arg.rs:31:14 + | +LL | format!("{foo}"); + | ^^^^^ not found in this scope + +error[E0425]: cannot find value `valueb` in this scope + --> $DIR/ifmt-bad-arg.rs:45:23 + | +LL | format!("{valuea} {valueb}", valuea=5, valuec=7); + | ^^^^^^^^ not found in this scope + +error[E0425]: cannot find value `foo` in this scope + --> $DIR/ifmt-bad-arg.rs:60:9 + | +LL | {foo} + | ^^^^^ not found in this scope + error[E0308]: mismatched types --> $DIR/ifmt-bad-arg.rs:78:32 | @@ -324,4 +314,5 @@ LL | println!("{} {:07$.*} {}", 1, 3.2, 4); error: aborting due to 36 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0308, E0425. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/fmt/ifmt-unimpl.stderr b/src/test/ui/fmt/ifmt-unimpl.stderr index 0a68c24b60..bee165437c 100644 --- a/src/test/ui/fmt/ifmt-unimpl.stderr +++ b/src/test/ui/fmt/ifmt-unimpl.stderr @@ -5,11 +5,6 @@ LL | format!("{:X}", "3"); | ^^^ the trait `UpperHex` is not implemented for `str` | = note: required because of the requirements on the impl of `UpperHex` for `&str` -note: required by `std::fmt::UpperHex::fmt` - --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL - | -LL | fn fmt(&self, f: &mut Formatter<'_>) -> Result; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `$crate::__export::format_args` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/expr-fn.rs b/src/test/ui/fn/expr-fn.rs similarity index 100% rename from src/test/ui/expr-fn.rs rename to src/test/ui/fn/expr-fn.rs diff --git a/src/test/ui/fun-call-variants.rs b/src/test/ui/fn/fun-call-variants.rs similarity index 100% rename from src/test/ui/fun-call-variants.rs rename to src/test/ui/fn/fun-call-variants.rs diff --git a/src/test/ui/nested-function-names-issue-8587.rs b/src/test/ui/fn/nested-function-names-issue-8587.rs similarity index 100% rename from src/test/ui/nested-function-names-issue-8587.rs rename to src/test/ui/fn/nested-function-names-issue-8587.rs diff --git a/src/test/ui/break-outside-loop.rs b/src/test/ui/for-loop-while/break-outside-loop.rs similarity index 100% rename from src/test/ui/break-outside-loop.rs rename to src/test/ui/for-loop-while/break-outside-loop.rs diff --git a/src/test/ui/break-outside-loop.stderr b/src/test/ui/for-loop-while/break-outside-loop.stderr similarity index 100% rename from src/test/ui/break-outside-loop.stderr rename to src/test/ui/for-loop-while/break-outside-loop.stderr diff --git a/src/test/ui/break-while-condition.rs b/src/test/ui/for-loop-while/break-while-condition.rs similarity index 100% rename from src/test/ui/break-while-condition.rs rename to src/test/ui/for-loop-while/break-while-condition.rs diff --git a/src/test/ui/break-while-condition.stderr b/src/test/ui/for-loop-while/break-while-condition.stderr similarity index 100% rename from src/test/ui/break-while-condition.stderr rename to src/test/ui/for-loop-while/break-while-condition.stderr diff --git a/src/test/ui/issues/issue-51345.rs b/src/test/ui/for-loop-while/issue-51345.rs similarity index 100% rename from src/test/ui/issues/issue-51345.rs rename to src/test/ui/for-loop-while/issue-51345.rs diff --git a/src/test/ui/long-while.rs b/src/test/ui/for-loop-while/long-while.rs similarity index 100% rename from src/test/ui/long-while.rs rename to src/test/ui/for-loop-while/long-while.rs diff --git a/src/test/ui/while-let.rs b/src/test/ui/for-loop-while/while-let-2.rs similarity index 100% rename from src/test/ui/while-let.rs rename to src/test/ui/for-loop-while/while-let-2.rs diff --git a/src/test/ui/while-let.stderr b/src/test/ui/for-loop-while/while-let-2.stderr similarity index 93% rename from src/test/ui/while-let.stderr rename to src/test/ui/for-loop-while/while-let-2.stderr index c5e2fd92f0..cb1abd4357 100644 --- a/src/test/ui/while-let.stderr +++ b/src/test/ui/for-loop-while/while-let-2.stderr @@ -1,5 +1,5 @@ warning: irrefutable `while let` pattern - --> $DIR/while-let.rs:7:19 + --> $DIR/while-let-2.rs:7:19 | LL | while let $p = $e $b | ^^^ @@ -15,7 +15,7 @@ LL | | }); = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) warning: irrefutable `while let` pattern - --> $DIR/while-let.rs:7:19 + --> $DIR/while-let-2.rs:7:19 | LL | while let $p = $e $b | ^^^ @@ -30,7 +30,7 @@ LL | | }); = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) warning: irrefutable `while let` pattern - --> $DIR/while-let.rs:27:11 + --> $DIR/while-let-2.rs:27:11 | LL | while let _a = 1 { | ^^^^^^^^^^ diff --git a/src/test/ui/for/for-c-in-str.rs b/src/test/ui/for/for-c-in-str.rs index 97a4ea53af..86a1c1a34e 100644 --- a/src/test/ui/for/for-c-in-str.rs +++ b/src/test/ui/for/for-c-in-str.rs @@ -6,8 +6,6 @@ fn main() { //~| NOTE `&str` is not an iterator //~| HELP the trait `Iterator` is not implemented for `&str` //~| NOTE required because of the requirements on the impl of `IntoIterator` for `&str` - //~| NOTE required by `into_iter` - //~| NOTE in this expansion of desugaring of `for` loop //~| NOTE in this expansion of desugaring of `for` loop //~| NOTE in this expansion of desugaring of `for` loop //~| NOTE in this expansion of desugaring of `for` loop diff --git a/src/test/ui/for/for-c-in-str.stderr b/src/test/ui/for/for-c-in-str.stderr index 7eac8c9c5a..07ddc8ea78 100644 --- a/src/test/ui/for/for-c-in-str.stderr +++ b/src/test/ui/for/for-c-in-str.stderr @@ -6,11 +6,6 @@ LL | for c in "asdf" { | = help: the trait `Iterator` is not implemented for `&str` = note: required because of the requirements on the impl of `IntoIterator` for `&str` -note: required by `into_iter` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/for/for-loop-bogosity.stderr b/src/test/ui/for/for-loop-bogosity.stderr index 288243325c..0bdd75b355 100644 --- a/src/test/ui/for/for-loop-bogosity.stderr +++ b/src/test/ui/for/for-loop-bogosity.stderr @@ -6,11 +6,6 @@ LL | for x in bogus { | = help: the trait `Iterator` is not implemented for `MyStruct` = note: required because of the requirements on the impl of `IntoIterator` for `MyStruct` -note: required by `into_iter` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/for/for-loop-unconstrained-element-type.stderr b/src/test/ui/for/for-loop-unconstrained-element-type.stderr index 0672014a92..580b135ac2 100644 --- a/src/test/ui/for/for-loop-unconstrained-element-type.stderr +++ b/src/test/ui/for/for-loop-unconstrained-element-type.stderr @@ -1,8 +1,10 @@ error[E0282]: type annotations needed - --> $DIR/for-loop-unconstrained-element-type.rs:8:14 + --> $DIR/for-loop-unconstrained-element-type.rs:8:9 | LL | for i in Vec::new() { } - | ^^^^^^^^^^ the element type for this iterator is not specified + | ^ ---------- the element type for this iterator is not specified + | | + | cannot infer type error: aborting due to previous error diff --git a/src/test/ui/nil-decl-in-foreign.rs b/src/test/ui/foreign/nil-decl-in-foreign.rs similarity index 100% rename from src/test/ui/nil-decl-in-foreign.rs rename to src/test/ui/foreign/nil-decl-in-foreign.rs diff --git a/src/test/ui/fully-qualified-type/fully-qualified-type-name1.rs b/src/test/ui/fully-qualified-type/fully-qualified-type-name1.rs index 1c6b9805b5..229c174daa 100644 --- a/src/test/ui/fully-qualified-type/fully-qualified-type-name1.rs +++ b/src/test/ui/fully-qualified-type/fully-qualified-type-name1.rs @@ -1,10 +1,10 @@ // Test that we use fully-qualified type names in error messages. fn main() { - let x: Option<usize>; + let x: //~ NOTE expected due to the type of this binding + Option<usize>; //~ NOTE expected due to this type x = 5; //~^ ERROR mismatched types - //~| expected enum `Option<usize>` - //~| found type `{integer}` - //~| expected enum `Option`, found integer + //~| NOTE expected enum `Option<usize>` + //~| NOTE expected enum `Option`, found integer } diff --git a/src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr b/src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr index b5018b47b7..4750c5ccdf 100644 --- a/src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr +++ b/src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr @@ -1,14 +1,19 @@ error[E0308]: mismatched types - --> $DIR/fully-qualified-type-name1.rs:5:9 + --> $DIR/fully-qualified-type-name1.rs:6:9 | +LL | let x: + | - expected due to the type of this binding +LL | Option<usize>; + | ------------- expected due to this type LL | x = 5; - | ^ - | | - | expected enum `Option`, found integer - | help: try using a variant of the expected enum: `Some(5)` + | ^ expected enum `Option`, found integer | = note: expected enum `Option<usize>` found type `{integer}` +help: try wrapping the expression in `Some` + | +LL | x = Some(5); + | +++++ + error: aborting due to previous error diff --git a/src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr b/src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr index b9574e3975..778b13f24c 100644 --- a/src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr +++ b/src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr @@ -4,13 +4,14 @@ error[E0308]: mismatched types LL | fn bar(x: usize) -> Option<usize> { | ------------- expected `Option<usize>` because of return type LL | return x; - | ^ - | | - | expected enum `Option`, found `usize` - | help: try using a variant of the expected enum: `Some(x)` + | ^ expected enum `Option`, found `usize` | = note: expected enum `Option<usize>` found type `usize` +help: try wrapping the expression in `Some` + | +LL | return Some(x); + | +++++ + error: aborting due to previous error diff --git a/src/test/ui/function-pointer/function-pointer-comparison-issue-54685.rs b/src/test/ui/function-pointer/function-pointer-comparison-issue-54685.rs index a036d10e63..855749c14b 100644 --- a/src/test/ui/function-pointer/function-pointer-comparison-issue-54685.rs +++ b/src/test/ui/function-pointer/function-pointer-comparison-issue-54685.rs @@ -1,4 +1,3 @@ -// min-llvm-version: 12.0 // compile-flags: -C opt-level=3 // run-pass diff --git a/src/test/ui/generator/generator-region-requirements.nll.stderr b/src/test/ui/generator/generator-region-requirements.nll.stderr new file mode 100644 index 0000000000..b4530cfda2 --- /dev/null +++ b/src/test/ui/generator/generator-region-requirements.nll.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/generator-region-requirements.rs:13:51 + | +LL | fn dangle(x: &mut i32) -> &'static mut i32 { + | - let's call the lifetime of this reference `'1` +... +LL | GeneratorState::Complete(c) => return c, + | ^ returning this value requires that `'1` must outlive `'static` + +error: aborting due to previous error + diff --git a/src/test/ui/generator/generator-region-requirements.rs b/src/test/ui/generator/generator-region-requirements.rs index 5f0a6bb09b..cec68509a6 100644 --- a/src/test/ui/generator/generator-region-requirements.rs +++ b/src/test/ui/generator/generator-region-requirements.rs @@ -6,11 +6,11 @@ fn dangle(x: &mut i32) -> &'static mut i32 { let mut g = || { yield; x + //~^ ERROR `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement [E0759] }; loop { match Pin::new(&mut g).resume(()) { GeneratorState::Complete(c) => return c, - //~^ ERROR explicit lifetime required GeneratorState::Yielded(_) => (), } } diff --git a/src/test/ui/generator/generator-region-requirements.stderr b/src/test/ui/generator/generator-region-requirements.stderr index de90a599e7..b6b9db2242 100644 --- a/src/test/ui/generator/generator-region-requirements.stderr +++ b/src/test/ui/generator/generator-region-requirements.stderr @@ -1,9 +1,15 @@ -error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/generator-region-requirements.rs:12:51 +error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/generator-region-requirements.rs:8:9 | +LL | fn dangle(x: &mut i32) -> &'static mut i32 { + | -------- this data with an anonymous lifetime `'_`... +... +LL | x + | ^ ...is captured here... +... LL | GeneratorState::Complete(c) => return c, - | ^ lifetime `'static` required + | - ...and is required to live as long as `'static` here error: aborting due to previous error -For more information about this error, try `rustc --explain E0621`. +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/generator/issue-68112.stderr b/src/test/ui/generator/issue-68112.stderr index c3fc8dd8f9..a7d7a73254 100644 --- a/src/test/ui/generator/issue-68112.stderr +++ b/src/test/ui/generator/issue-68112.stderr @@ -9,7 +9,7 @@ note: generator is not `Send` as this value is used across a yield --> $DIR/issue-68112.rs:31:9 | LL | let _non_send_gen = make_non_send_generator(); - | ------------- has type `impl Generator` which is not `Send` + | ------------- has type `impl Generator<Return = Arc<RefCell<i32>>>` which is not `Send` LL | yield; | ^^^^^ yield occurs here, with `_non_send_gen` maybe used later LL | }; @@ -29,9 +29,9 @@ LL | require_send(send_gen); = help: the trait `Sync` is not implemented for `RefCell<i32>` = note: required because of the requirements on the impl of `Send` for `Arc<RefCell<i32>>` = note: required because it appears within the type `[generator@$DIR/issue-68112.rs:38:5: 41:6]` - = note: required because it appears within the type `impl Generator` - = note: required because it appears within the type `impl Generator` - = note: required because it appears within the type `{impl Generator, ()}` + = note: required because it appears within the type `impl Generator<Return = Arc<RefCell<i32>>>` + = note: required because it appears within the type `impl Generator<Return = Arc<RefCell<i32>>>` + = note: required because it appears within the type `{impl Generator<Return = Arc<RefCell<i32>>>, ()}` = note: required because it appears within the type `[generator@$DIR/issue-68112.rs:48:20: 51:6]` note: required by a bound in `require_send` --> $DIR/issue-68112.rs:22:25 diff --git a/src/test/ui/generator/yield-outside-generator-issue-78653.stderr b/src/test/ui/generator/yield-outside-generator-issue-78653.stderr index dff743bc35..ee1afbe5b5 100644 --- a/src/test/ui/generator/yield-outside-generator-issue-78653.stderr +++ b/src/test/ui/generator/yield-outside-generator-issue-78653.stderr @@ -13,11 +13,6 @@ LL | yield || for i in 0 { } = help: the trait `Iterator` is not implemented for `{integer}` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required because of the requirements on the impl of `IntoIterator` for `{integer}` -note: required by `into_iter` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/generic-associated-types/collections-project-default.rs b/src/test/ui/generic-associated-types/collections-project-default.rs index 0944bf110c..5b94cdee7c 100644 --- a/src/test/ui/generic-associated-types/collections-project-default.rs +++ b/src/test/ui/generic-associated-types/collections-project-default.rs @@ -8,7 +8,7 @@ // check that we don't normalize with trait defaults. trait Collection<T> { - type Iter<'iter>: Iterator<Item=&'iter T> where T: 'iter; + type Iter<'iter>: Iterator<Item=&'iter T> where T: 'iter, Self: 'iter; type Family: CollectionFamily; // Test associated type defaults with parameters type Sibling<U>: Collection<U> = diff --git a/src/test/ui/generic-associated-types/collections.rs b/src/test/ui/generic-associated-types/collections.rs index f14c6dac1b..b0f2fb3f56 100644 --- a/src/test/ui/generic-associated-types/collections.rs +++ b/src/test/ui/generic-associated-types/collections.rs @@ -8,7 +8,7 @@ // run-pass trait Collection<T> { - type Iter<'iter>: Iterator<Item=&'iter T> where T: 'iter; + type Iter<'iter>: Iterator<Item=&'iter T> where T: 'iter, Self: 'iter; type Family: CollectionFamily; // Test associated type defaults with parameters type Sibling<U>: Collection<U> = diff --git a/src/test/ui/generic-associated-types/generic-associated-type-bounds.rs b/src/test/ui/generic-associated-types/generic-associated-type-bounds.rs index 5d3a3a8935..d7c4dbda26 100644 --- a/src/test/ui/generic-associated-types/generic-associated-type-bounds.rs +++ b/src/test/ui/generic-associated-types/generic-associated-type-bounds.rs @@ -3,7 +3,7 @@ #![feature(generic_associated_types)] pub trait X { - type Y<'a>; + type Y<'a> where Self: 'a; fn m(&self) -> Self::Y<'_>; } diff --git a/src/test/ui/generic-associated-types/impl_bounds.stderr b/src/test/ui/generic-associated-types/impl_bounds.stderr index f47b5f81e2..1c8a1f09af 100644 --- a/src/test/ui/generic-associated-types/impl_bounds.stderr +++ b/src/test/ui/generic-associated-types/impl_bounds.stderr @@ -59,10 +59,10 @@ LL | impl<T: std::marker::Copy> Foo for Fooy<T> { | +++++++++++++++++++ error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/impl_bounds.rs:22:5 + --> $DIR/impl_bounds.rs:22:24 | LL | fn d() where Self: Copy {} - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` + | ^^^^ the trait `Copy` is not implemented for `T` | note: required because of the requirements on the impl of `Copy` for `Fooy<T>` --> $DIR/impl_bounds.rs:11:10 diff --git a/src/test/ui/generic-associated-types/issue-70303.rs b/src/test/ui/generic-associated-types/issue-70303.rs index d238f53bde..568996e1a1 100644 --- a/src/test/ui/generic-associated-types/issue-70303.rs +++ b/src/test/ui/generic-associated-types/issue-70303.rs @@ -3,7 +3,7 @@ #![feature(generic_associated_types)] trait Document { - type Cursor<'a>: DocCursor<'a>; + type Cursor<'a>: DocCursor<'a> where Self: 'a; fn cursor(&self) -> Self::Cursor<'_>; } diff --git a/src/test/ui/generic-associated-types/issue-76535.rs b/src/test/ui/generic-associated-types/issue-76535.rs index 1dad856d5a..20c6924afa 100644 --- a/src/test/ui/generic-associated-types/issue-76535.rs +++ b/src/test/ui/generic-associated-types/issue-76535.rs @@ -3,7 +3,7 @@ pub trait SubTrait {} pub trait SuperTrait { - type SubType<'a>: SubTrait; + type SubType<'a>: SubTrait where Self: 'a; fn get_sub<'a>(&'a mut self) -> Self::SubType<'a>; } diff --git a/src/test/ui/generic-associated-types/issue-76535.stderr b/src/test/ui/generic-associated-types/issue-76535.stderr index 0a7eb5dde6..64eeec1b2f 100644 --- a/src/test/ui/generic-associated-types/issue-76535.stderr +++ b/src/test/ui/generic-associated-types/issue-76535.stderr @@ -7,7 +7,7 @@ LL | let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruc note: associated type defined here, with 1 lifetime parameter: `'a` --> $DIR/issue-76535.rs:6:10 | -LL | type SubType<'a>: SubTrait; +LL | type SubType<'a>: SubTrait where Self: 'a; | ^^^^^^^ -- help: add missing lifetime argument | @@ -25,7 +25,7 @@ note: for a trait to be "object safe" it needs to allow building a vtable to all | LL | pub trait SuperTrait { | ---------- this trait cannot be made into an object... -LL | type SubType<'a>: SubTrait; +LL | type SubType<'a>: SubTrait where Self: 'a; | ^^^^^^^ ...because it contains the generic associated type `SubType` = help: consider moving `SubType` to another trait @@ -40,7 +40,7 @@ note: for a trait to be "object safe" it needs to allow building a vtable to all | LL | pub trait SuperTrait { | ---------- this trait cannot be made into an object... -LL | type SubType<'a>: SubTrait; +LL | type SubType<'a>: SubTrait where Self: 'a; | ^^^^^^^ ...because it contains the generic associated type `SubType` = help: consider moving `SubType` to another trait = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn SuperTrait<SubType = SubStruct<'_>>>>` for `Box<SuperStruct>` diff --git a/src/test/ui/generic-associated-types/issue-79422.rs b/src/test/ui/generic-associated-types/issue-79422.rs index 7f0ac34835..47ef38ff45 100644 --- a/src/test/ui/generic-associated-types/issue-79422.rs +++ b/src/test/ui/generic-associated-types/issue-79422.rs @@ -17,12 +17,12 @@ impl<'a, T> RefCont<'a, T> for Box<T> { } trait MapLike<K, V> { - type VRefCont<'a>: RefCont<'a, V>; + type VRefCont<'a>: RefCont<'a, V> where Self: 'a; fn get<'a>(&'a self, key: &K) -> Option<Self::VRefCont<'a>>; } impl<K: Ord, V: 'static> MapLike<K, V> for std::collections::BTreeMap<K, V> { - type VRefCont<'a> = &'a V; + type VRefCont<'a> where Self: 'a = &'a V; fn get<'a>(&'a self, key: &K) -> Option<&'a V> { std::collections::BTreeMap::get(self, key) } diff --git a/src/test/ui/generic-associated-types/issue-79422.stderr b/src/test/ui/generic-associated-types/issue-79422.stderr index b6f856a97e..8b6f9b866e 100644 --- a/src/test/ui/generic-associated-types/issue-79422.stderr +++ b/src/test/ui/generic-associated-types/issue-79422.stderr @@ -7,7 +7,7 @@ LL | as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>; note: associated type defined here, with 1 lifetime parameter: `'a` --> $DIR/issue-79422.rs:20:10 | -LL | type VRefCont<'a>: RefCont<'a, V>; +LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; | ^^^^^^^^ -- help: add missing lifetime argument | @@ -25,7 +25,7 @@ note: for a trait to be "object safe" it needs to allow building a vtable to all | LL | trait MapLike<K, V> { | ------- this trait cannot be made into an object... -LL | type VRefCont<'a>: RefCont<'a, V>; +LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; | ^^^^^^^^ ...because it contains the generic associated type `VRefCont` = help: consider moving `VRefCont` to another trait @@ -40,7 +40,7 @@ note: for a trait to be "object safe" it needs to allow building a vtable to all | LL | trait MapLike<K, V> { | ------- this trait cannot be made into an object... -LL | type VRefCont<'a>: RefCont<'a, V>; +LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; | ^^^^^^^^ ...because it contains the generic associated type `VRefCont` = help: consider moving `VRefCont` to another trait = 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>>` diff --git a/src/test/ui/generic-associated-types/issue-85921.rs b/src/test/ui/generic-associated-types/issue-85921.rs new file mode 100644 index 0000000000..df59f497d7 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-85921.rs @@ -0,0 +1,19 @@ +// check-pass + +#![feature(generic_associated_types)] + +trait Trait { + type Assoc<'a>; + + fn with_assoc(f: impl FnOnce(Self::Assoc<'_>)); +} + +impl Trait for () { + type Assoc<'a> = i32; + + fn with_assoc(f: impl FnOnce(Self::Assoc<'_>)) { + f(5i32) + } +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-86483.stderr b/src/test/ui/generic-associated-types/issue-86483.stderr index d6978794e1..2f29cd5d9e 100644 --- a/src/test/ui/generic-associated-types/issue-86483.stderr +++ b/src/test/ui/generic-associated-types/issue-86483.stderr @@ -11,8 +11,9 @@ LL | | { ... | LL | | LL | | } - | |_^ ...so that the type `T` will meet its required lifetime bounds... + | |_^ | + = note: ...so that the type `T` will meet its required lifetime bounds... note: ...that is required by this bound --> $DIR/issue-86483.rs:7:16 | diff --git a/src/test/ui/generic-associated-types/issue-86787.rs b/src/test/ui/generic-associated-types/issue-86787.rs index f1f05ea662..0f62f83e25 100644 --- a/src/test/ui/generic-associated-types/issue-86787.rs +++ b/src/test/ui/generic-associated-types/issue-86787.rs @@ -9,6 +9,7 @@ enum Either<L, R> { pub trait HasChildrenOf { type T; type TRef<'a>; + //~^ Missing required bounds fn ref_children<'a>(&'a self) -> Vec<Self::TRef<'a>>; fn take_children(self) -> Vec<Self::T>; @@ -20,9 +21,9 @@ where Right: HasChildrenOf, { type T = Either<Left::T, Right::T>; + // We used to error below because the where clause doesn't match the trait. + // Now, we error early on the trait itself. type TRef<'a> - //~^ `impl` associated type signature - //~^^ `impl` associated type signature where <Left as HasChildrenOf>::T: 'a, <Right as HasChildrenOf>::T: 'a diff --git a/src/test/ui/generic-associated-types/issue-86787.stderr b/src/test/ui/generic-associated-types/issue-86787.stderr index 648eff77d7..87dcd875de 100644 --- a/src/test/ui/generic-associated-types/issue-86787.stderr +++ b/src/test/ui/generic-associated-types/issue-86787.stderr @@ -1,32 +1,10 @@ -error: `impl` associated type signature for `TRef` doesn't match `trait` associated type signature - --> $DIR/issue-86787.rs:23:5 +error: Missing required bounds on TRef + --> $DIR/issue-86787.rs:11:5 | -LL | type TRef<'a>; - | -------------- expected -... -LL | / type TRef<'a> -LL | | -LL | | -LL | | where -LL | | <Left as HasChildrenOf>::T: 'a, -LL | | <Right as HasChildrenOf>::T: 'a -LL | | = Either<&'a Left::T, &'a Right::T>; - | |________________________________________^ found +LL | type TRef<'a>; + | ^^^^^^^^^^^^^- + | | + | help: add the required where clauses: `where Self: 'a` -error: `impl` associated type signature for `TRef` doesn't match `trait` associated type signature - --> $DIR/issue-86787.rs:23:5 - | -LL | type TRef<'a>; - | -------------- expected -... -LL | / type TRef<'a> -LL | | -LL | | -LL | | where -LL | | <Left as HasChildrenOf>::T: 'a, -LL | | <Right as HasChildrenOf>::T: 'a -LL | | = Either<&'a Left::T, &'a Right::T>; - | |________________________________________^ found - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/issue-87258_a.rs b/src/test/ui/generic-associated-types/issue-87258_a.rs new file mode 100644 index 0000000000..d9d17751fa --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-87258_a.rs @@ -0,0 +1,24 @@ +#![feature(type_alias_impl_trait)] +#![feature(generic_associated_types)] + +// See https://github.com/rust-lang/rust/issues/87258#issuecomment-883293367 + +trait Trait1 {} + +struct Struct<'b>(&'b ()); + +impl<'d> Trait1 for Struct<'d> {} + +pub trait Trait2 { + type FooFuture<'a>: Trait1; + fn foo<'a>() -> Self::FooFuture<'a>; +} + +impl<'c, S: Trait2> Trait2 for &'c mut S { + type FooFuture<'a> = impl Trait1; + fn foo<'a>() -> Self::FooFuture<'a> { //~ ERROR + Struct(unimplemented!()) + } +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-87258_a.stderr b/src/test/ui/generic-associated-types/issue-87258_a.stderr new file mode 100644 index 0000000000..93513a4563 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-87258_a.stderr @@ -0,0 +1,11 @@ +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/issue-87258_a.rs:19:21 + | +LL | fn foo<'a>() -> Self::FooFuture<'a> { + | ^^^^^^^^^^^^^^^^^^^ + | + = note: hidden type `Struct<'_>` captures lifetime '_#7r + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/generic-associated-types/issue-87258_b.rs b/src/test/ui/generic-associated-types/issue-87258_b.rs new file mode 100644 index 0000000000..b29a978f51 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-87258_b.rs @@ -0,0 +1,26 @@ +#![feature(type_alias_impl_trait)] +#![feature(generic_associated_types)] + +// See https://github.com/rust-lang/rust/issues/87258#issuecomment-883293367 + +trait Trait1 {} + +struct Struct<'b>(&'b ()); + +impl<'d> Trait1 for Struct<'d> {} + +pub trait Trait2 { + type FooFuture<'a>: Trait1; + fn foo<'a>() -> Self::FooFuture<'a>; +} + +type Helper<'xenon, 'yttrium, KABOOM: Trait2> = impl Trait1; + +impl<'c, S: Trait2> Trait2 for &'c mut S { + type FooFuture<'a> = Helper<'c, 'a, S>; + fn foo<'a>() -> Self::FooFuture<'a> { //~ ERROR + Struct(unimplemented!()) + } +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-87258_b.stderr b/src/test/ui/generic-associated-types/issue-87258_b.stderr new file mode 100644 index 0000000000..e077a42340 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-87258_b.stderr @@ -0,0 +1,11 @@ +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/issue-87258_b.rs:21:21 + | +LL | fn foo<'a>() -> Self::FooFuture<'a> { + | ^^^^^^^^^^^^^^^^^^^ + | + = note: hidden type `Struct<'_>` captures lifetime '_#7r + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/generic-associated-types/issue-88287.rs b/src/test/ui/generic-associated-types/issue-88287.rs index 2e65af594a..df5586ed42 100644 --- a/src/test/ui/generic-associated-types/issue-88287.rs +++ b/src/test/ui/generic-associated-types/issue-88287.rs @@ -13,7 +13,8 @@ trait SearchableResource<Criteria> { trait SearchableResourceExt<Criteria>: SearchableResource<Criteria> { type Future<'f, A: 'f + ?Sized, B: 'f>: Future<Output = Result<Vec<A::SearchResult>, ()>> + 'f where - A: SearchableResource<B>; + A: SearchableResource<B>, + Self: 'f; fn search<'c>(&'c self, client: &'c ()) -> Self::Future<'c, Self, Criteria>; } @@ -29,6 +30,7 @@ where type Future<'f, A, B: 'f> where A: SearchableResource<B> + ?Sized + 'f, + Self: 'f, = SearchFutureTy<'f, A, B>; fn search<'c>(&'c self, _client: &'c ()) -> Self::Future<'c, Self, Criteria> { diff --git a/src/test/ui/generic-associated-types/issue-88360.rs b/src/test/ui/generic-associated-types/issue-88360.rs index 06af3f5ec9..8ee98201ab 100644 --- a/src/test/ui/generic-associated-types/issue-88360.rs +++ b/src/test/ui/generic-associated-types/issue-88360.rs @@ -1,13 +1,14 @@ #![feature(generic_associated_types)] trait GatTrait { - type Gat<'a>; + type Gat<'a> where Self: 'a; fn test(&self) -> Self::Gat<'_>; } trait SuperTrait<T> where + Self: 'static, for<'a> Self: GatTrait<Gat<'a> = &'a T>, { fn copy(&self) -> Self::Gat<'_> where T: Copy { diff --git a/src/test/ui/generic-associated-types/issue-88360.stderr b/src/test/ui/generic-associated-types/issue-88360.stderr index cfbf3aaa4e..5f769d799f 100644 --- a/src/test/ui/generic-associated-types/issue-88360.stderr +++ b/src/test/ui/generic-associated-types/issue-88360.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-88360.rs:14:9 + --> $DIR/issue-88360.rs:15:9 | LL | trait SuperTrait<T> | - this type parameter diff --git a/src/test/ui/generic-associated-types/issue-88459.rs b/src/test/ui/generic-associated-types/issue-88459.rs new file mode 100644 index 0000000000..3b26a18015 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-88459.rs @@ -0,0 +1,19 @@ +// check-pass + +#![feature(generic_associated_types)] + +trait Trait { + type Assoc<'a>; +} + +fn f<T: Trait>(_: T, _: impl Fn(T::Assoc<'_>)) {} + +struct Type; + +impl Trait for Type { + type Assoc<'a> = (); +} + +fn main() { + f(Type, |_|()); +} diff --git a/src/test/ui/generic-associated-types/issue-88595.rs b/src/test/ui/generic-associated-types/issue-88595.rs new file mode 100644 index 0000000000..e397390783 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-88595.rs @@ -0,0 +1,24 @@ +#![feature(generic_associated_types)] +#![feature(type_alias_impl_trait)] + +fn main() {} + +trait A<'a> { + type B<'b>: Clone + // FIXME(generic_associated_types): Remove one of the below bounds + // https://github.com/rust-lang/rust/pull/90678#discussion_r744976085 + where + 'a: 'b, Self: 'a, Self: 'b; + + fn a(&'a self) -> Self::B<'a>; +} + +struct C; + +impl<'a> A<'a> for C { + type B<'b> = impl Clone; + //~^ ERROR: lifetime bound not satisfied + //~| ERROR: could not find defining uses + + fn a(&'a self) -> Self::B<'a> {} //~ ERROR: non-defining opaque type use in defining scope +} diff --git a/src/test/ui/generic-associated-types/issue-88595.stderr b/src/test/ui/generic-associated-types/issue-88595.stderr new file mode 100644 index 0000000000..1948f82d0c --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-88595.stderr @@ -0,0 +1,40 @@ +error[E0478]: lifetime bound not satisfied + --> $DIR/issue-88595.rs:19:5 + | +LL | type B<'b> = impl Clone; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: lifetime parameter instantiated with the lifetime `'a` as defined here + --> $DIR/issue-88595.rs:18:6 + | +LL | impl<'a> A<'a> for C { + | ^^ +note: but lifetime parameter must outlive the lifetime `'b` as defined here + --> $DIR/issue-88595.rs:19:12 + | +LL | type B<'b> = impl Clone; + | ^^ + +error: non-defining opaque type use in defining scope + --> $DIR/issue-88595.rs:23:23 + | +LL | fn a(&'a self) -> Self::B<'a> {} + | ^^^^^^^^^^^ + | +note: lifetime used multiple times + --> $DIR/issue-88595.rs:18:6 + | +LL | impl<'a> A<'a> for C { + | ^^ +LL | type B<'b> = impl Clone; + | ^^ + +error: could not find defining uses + --> $DIR/issue-88595.rs:19:18 + | +LL | type B<'b> = impl Clone; + | ^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0478`. diff --git a/src/test/ui/generic-associated-types/issue-90014.rs b/src/test/ui/generic-associated-types/issue-90014.rs new file mode 100644 index 0000000000..f110b06938 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-90014.rs @@ -0,0 +1,22 @@ +// edition:2018 + +#![feature(generic_associated_types)] +#![feature(type_alias_impl_trait)] + +use std::future::Future; + +trait MakeFut { + type Fut<'a> where Self: 'a; + fn make_fut<'a>(&'a self) -> Self::Fut<'a>; +} + +impl MakeFut for &'_ mut () { + type Fut<'a> = impl Future<Output = ()>; + //~^ ERROR: the type `&mut ()` does not fulfill the required lifetime + + fn make_fut<'a>(&'a self) -> Self::Fut<'a> { + async { () } + } +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-90014.stderr b/src/test/ui/generic-associated-types/issue-90014.stderr new file mode 100644 index 0000000000..125d817e35 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-90014.stderr @@ -0,0 +1,15 @@ +error[E0477]: the type `&mut ()` does not fulfill the required lifetime + --> $DIR/issue-90014.rs:14:5 + | +LL | type Fut<'a> = impl Future<Output = ()>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: type must outlive the lifetime `'a` as defined here + --> $DIR/issue-90014.rs:14:14 + | +LL | type Fut<'a> = impl Future<Output = ()>; + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0477`. diff --git a/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs b/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs index 6db249221b..8b6f7c41a7 100644 --- a/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs +++ b/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs @@ -12,6 +12,7 @@ trait M { } impl<T: X<Y<i32> = i32>> M for T {} +//~^ NOTE the following trait bounds were not satisfied struct S; //~^ NOTE method `f` not found for this @@ -26,7 +27,6 @@ fn f(a: S) { a.f(); //~^ ERROR the method `f` exists for struct `S`, but its trait bounds were not satisfied //~| NOTE method cannot be called on `S` due to unsatisfied trait bounds - //~| NOTE the following trait bounds were not satisfied: } fn main() {} diff --git a/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr b/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr index 8af9fbed87..3eeb9540e7 100644 --- a/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr +++ b/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr @@ -1,5 +1,5 @@ error[E0599]: the method `f` exists for struct `S`, but its trait bounds were not satisfied - --> $DIR/method-unsatified-assoc-type-predicate.rs:26:7 + --> $DIR/method-unsatified-assoc-type-predicate.rs:27:7 | LL | struct S; | --------- @@ -11,9 +11,12 @@ LL | struct S; LL | a.f(); | ^ method cannot be called on `S` due to unsatisfied trait bounds | - = note: the following trait bounds were not satisfied: - `<S as X>::Y<i32> = i32` - which is required by `S: M` +note: the following trait bounds were not satisfied because of the requirements of the implementation of `M` for `_`: + `<S as X>::Y<i32> = i32` + --> $DIR/method-unsatified-assoc-type-predicate.rs:14:26 + | +LL | impl<T: X<Y<i32> = i32>> M for T {} + | ^ ^ error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.nll.stderr b/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.nll.stderr new file mode 100644 index 0000000000..4620aa34e8 --- /dev/null +++ b/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.nll.stderr @@ -0,0 +1,26 @@ +error: lifetime may not live long enough + --> $DIR/projection-type-lifetime-mismatch.rs:17:5 + | +LL | fn f(x: &impl for<'a> X<Y<'a> = &'a ()>) -> &'static () { + | - let's call the lifetime of this reference `'1` +LL | x.m() + | ^^^^^ returning this value requires that `'1` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/projection-type-lifetime-mismatch.rs:22:5 + | +LL | fn g<T: for<'a> X<Y<'a> = &'a ()>>(x: &T) -> &'static () { + | - let's call the lifetime of this reference `'1` +LL | x.m() + | ^^^^^ returning this value requires that `'1` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/projection-type-lifetime-mismatch.rs:27:5 + | +LL | fn h(x: &()) -> &'static () { + | - let's call the lifetime of this reference `'1` +LL | x.m() + | ^^^^^ returning this value requires that `'1` must outlive `'static` + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.rs b/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.rs index b976ee3261..9b04fe2332 100644 --- a/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.rs +++ b/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.rs @@ -1,7 +1,7 @@ #![feature(generic_associated_types)] pub trait X { - type Y<'a>; + type Y<'a> where Self: 'a; fn m(&self) -> Self::Y<'_>; } @@ -15,17 +15,17 @@ impl X for () { fn f(x: &impl for<'a> X<Y<'a> = &'a ()>) -> &'static () { x.m() - //~^ ERROR explicit lifetime required + //~^ ERROR `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement [E0759] } fn g<T: for<'a> X<Y<'a> = &'a ()>>(x: &T) -> &'static () { x.m() - //~^ ERROR explicit lifetime required + //~^ ERROR `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement [E0759] } fn h(x: &()) -> &'static () { x.m() - //~^ ERROR explicit lifetime required + //~^ ERROR `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement [E0759] } fn main() { diff --git a/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.stderr b/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.stderr index 315bef16c5..1ffd205652 100644 --- a/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.stderr +++ b/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.stderr @@ -1,21 +1,27 @@ -error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/projection-type-lifetime-mismatch.rs:17:5 +error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/projection-type-lifetime-mismatch.rs:17:7 | +LL | fn f(x: &impl for<'a> X<Y<'a> = &'a ()>) -> &'static () { + | ------------------------------- this data with an anonymous lifetime `'_`... LL | x.m() - | ^^^^^ lifetime `'static` required + | --^-- ...is captured and required to live as long as `'static` here -error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/projection-type-lifetime-mismatch.rs:22:5 +error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/projection-type-lifetime-mismatch.rs:22:7 | +LL | fn g<T: for<'a> X<Y<'a> = &'a ()>>(x: &T) -> &'static () { + | -- this data with an anonymous lifetime `'_`... LL | x.m() - | ^^^^^ lifetime `'static` required + | --^-- ...is captured and required to live as long as `'static` here -error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/projection-type-lifetime-mismatch.rs:27:5 +error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/projection-type-lifetime-mismatch.rs:27:7 | +LL | fn h(x: &()) -> &'static () { + | --- this data with an anonymous lifetime `'_`... LL | x.m() - | ^^^^^ lifetime `'static` required + | --^-- ...is captured and required to live as long as `'static` here error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0621`. +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/generic-associated-types/self-outlives-lint.rs b/src/test/ui/generic-associated-types/self-outlives-lint.rs new file mode 100644 index 0000000000..af90d15885 --- /dev/null +++ b/src/test/ui/generic-associated-types/self-outlives-lint.rs @@ -0,0 +1,173 @@ +#![feature(generic_associated_types)] + +// check-fail + +use std::fmt::Debug; + +// We have a `&'a self`, so we need a `Self: 'a` +trait Iterable { + type Item<'x>; + //~^ Missing required bounds + fn iter<'a>(&'a self) -> Self::Item<'a>; +} + +/* +impl<T> Iterable for T { + type Item<'a> = &'a T; + fn iter<'a>(&'a self) -> Self::Item<'a> { + self + } +} +*/ + +// We have a `&'a T`, so we need a `T: 'x` +trait Deserializer<T> { + type Out<'x>; + //~^ Missing required bounds + fn deserialize<'a>(&self, input: &'a T) -> Self::Out<'a>; +} + +/* +impl<T> Deserializer<T> for () { + type Out<'a> = &'a T; + fn deserialize<'a>(&self, input: &'a T) -> Self::Out<'a> { input } +} +*/ + +// We have a `&'b T` and a `'b: 'a`, so it is implied that `T: 'a`. Therefore, we need a `T: 'x` +trait Deserializer2<T> { + type Out<'x>; + //~^ Missing required bounds + fn deserialize2<'a, 'b: 'a>(&self, input1: &'b T) -> Self::Out<'a>; +} + +// We have a `&'a T` and a `&'b U`, so we need a `T: 'x` and a `U: 'y` +trait Deserializer3<T, U> { + type Out<'x, 'y>; + //~^ Missing required bounds + fn deserialize2<'a, 'b>(&self, input: &'a T, input2: &'b U) -> Self::Out<'a, 'b>; +} + +// `T` is a param on the function, so it can't be named by the associated type +trait Deserializer4 { + type Out<'x>; + fn deserialize<'a, T>(&self, input: &'a T) -> Self::Out<'a>; +} + +struct Wrap<T>(T); + +// We pass `Wrap<T>` and we see `&'z Wrap<T>`, so we require `D: 'x` +trait Des { + type Out<'x, D>; + //~^ Missing required bounds + fn des<'z, T>(&self, data: &'z Wrap<T>) -> Self::Out<'z, Wrap<T>>; +} +/* +impl Des for () { + type Out<'x, D> = &'x D; // Not okay + fn des<'a, T>(&self, data: &'a Wrap<T>) -> Self::Out<'a, Wrap<T>> { + data + } +} +*/ + +// We have `T` and `'z` as GAT substs. Because of `&'z Wrap<T>`, there is an +// implied bound that `T: 'z`, so we require `D: 'x` +trait Des2 { + type Out<'x, D>; + //~^ Missing required bounds + fn des<'z, T>(&self, data: &'z Wrap<T>) -> Self::Out<'z, T>; +} +/* +impl Des2 for () { + type Out<'x, D> = &'x D; + fn des<'a, T>(&self, data: &'a Wrap<T>) -> Self::Out<'a, T> { + &data.0 + } +} +*/ + +// We see `&'z T`, so we require `D: 'x` +trait Des3 { + type Out<'x, D>; + //~^ Missing required bounds + fn des<'z, T>(&self, data: &'z T) -> Self::Out<'z, T>; +} +/* +impl Des3 for () { + type Out<'x, D> = &'x D; + fn des<'a, T>(&self, data: &'a T) -> Self::Out<'a, T> { + data + } +} +*/ + +// Similar case to before, except with GAT. +trait NoGat<'a> { + type Bar; + fn method(&'a self) -> Self::Bar; +} + +// Lifetime is not on function; except `Self: 'a` +// FIXME: we require two bounds (`where Self: 'a, Self: 'b`) when we should only require one +trait TraitLifetime<'a> { + type Bar<'b>; + //~^ Missing required bounds + fn method(&'a self) -> Self::Bar<'a>; +} + +// Like above, but we have a where clause that can prove what we want +// FIXME: we require two bounds (`where Self: 'a, Self: 'b`) when we should only require one +trait TraitLifetimeWhere<'a> where Self: 'a { + type Bar<'b>; + //~^ Missing required bounds + fn method(&'a self) -> Self::Bar<'a>; +} + +// Explicit bound instead of implicit; we want to still error +trait ExplicitBound { + type Bar<'b>; + //~^ Missing required bounds + fn method<'b>(&self, token: &'b ()) -> Self::Bar<'b> where Self: 'b; +} + +// The use of the GAT here is not in the return, we don't want to error +trait NotInReturn { + type Bar<'b>; + fn method<'b>(&'b self) where Self::Bar<'b>: Debug; +} + +// We obviously error for `Iterator`, but we should also error for `Item` +trait IterableTwo { + type Item<'a>; + type Iterator<'a>: Iterator<Item = Self::Item<'a>>; + //~^ Missing required bounds + fn iter<'a>(&'a self) -> Self::Iterator<'a>; +} + +// We also should report region outlives clauses +trait RegionOutlives { + type Bar<'a, 'b>; + //~^ Missing required bounds + fn foo<'x, 'y>(&self, input: &'x &'y ()) -> Self::Bar<'x, 'y>; +} + +/* +impl Foo for () { + type Bar<'a, 'b> = &'a &'b (); + fn foo<'x, 'y>(&self, input: &'x &'y ()) -> Self::Bar<'x, 'y> { + input + } +} +*/ + +// If there are multiple methods that return the GAT, require a set of clauses +// that can be satisfied by *all* methods +trait MultipleMethods { + type Bar<'me>; + + fn gimme<'a>(&'a self) -> Self::Bar<'a>; + fn gimme_default(&self) -> Self::Bar<'static>; +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/self-outlives-lint.stderr b/src/test/ui/generic-associated-types/self-outlives-lint.stderr new file mode 100644 index 0000000000..bf85780f69 --- /dev/null +++ b/src/test/ui/generic-associated-types/self-outlives-lint.stderr @@ -0,0 +1,98 @@ +error: Missing required bounds on Item + --> $DIR/self-outlives-lint.rs:9:5 + | +LL | type Item<'x>; + | ^^^^^^^^^^^^^- + | | + | help: add the required where clauses: `where Self: 'x` + +error: Missing required bounds on Out + --> $DIR/self-outlives-lint.rs:25:5 + | +LL | type Out<'x>; + | ^^^^^^^^^^^^- + | | + | help: add the required where clauses: `where T: 'x` + +error: Missing required bounds on Out + --> $DIR/self-outlives-lint.rs:39:5 + | +LL | type Out<'x>; + | ^^^^^^^^^^^^- + | | + | help: add the required where clauses: `where T: 'x` + +error: Missing required bounds on Out + --> $DIR/self-outlives-lint.rs:46:5 + | +LL | type Out<'x, 'y>; + | ^^^^^^^^^^^^^^^^- + | | + | help: add the required where clauses: `where T: 'x, U: 'y` + +error: Missing required bounds on Out + --> $DIR/self-outlives-lint.rs:61:5 + | +LL | type Out<'x, D>; + | ^^^^^^^^^^^^^^^- + | | + | help: add the required where clauses: `where D: 'x` + +error: Missing required bounds on Out + --> $DIR/self-outlives-lint.rs:77:5 + | +LL | type Out<'x, D>; + | ^^^^^^^^^^^^^^^- + | | + | help: add the required where clauses: `where D: 'x` + +error: Missing required bounds on Out + --> $DIR/self-outlives-lint.rs:92:5 + | +LL | type Out<'x, D>; + | ^^^^^^^^^^^^^^^- + | | + | help: add the required where clauses: `where D: 'x` + +error: Missing required bounds on Bar + --> $DIR/self-outlives-lint.rs:114:5 + | +LL | type Bar<'b>; + | ^^^^^^^^^^^^- + | | + | help: add the required where clauses: `where Self: 'a, Self: 'b` + +error: Missing required bounds on Bar + --> $DIR/self-outlives-lint.rs:122:5 + | +LL | type Bar<'b>; + | ^^^^^^^^^^^^- + | | + | help: add the required where clauses: `where Self: 'a, Self: 'b` + +error: Missing required bounds on Bar + --> $DIR/self-outlives-lint.rs:129:5 + | +LL | type Bar<'b>; + | ^^^^^^^^^^^^- + | | + | help: add the required where clauses: `where Self: 'b` + +error: Missing required bounds on Iterator + --> $DIR/self-outlives-lint.rs:143:5 + | +LL | type Iterator<'a>: Iterator<Item = Self::Item<'a>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: add the required where clauses: `where Self: 'a` + +error: Missing required bounds on Bar + --> $DIR/self-outlives-lint.rs:150:5 + | +LL | type Bar<'a, 'b>; + | ^^^^^^^^^^^^^^^^- + | | + | help: add the required where clauses: `where 'a: 'b` + +error: aborting due to 12 previous errors + diff --git a/src/test/ui/generic-associated-types/streaming_iterator.rs b/src/test/ui/generic-associated-types/streaming_iterator.rs index 2feff9f4c6..f83d4d7b68 100644 --- a/src/test/ui/generic-associated-types/streaming_iterator.rs +++ b/src/test/ui/generic-associated-types/streaming_iterator.rs @@ -5,12 +5,12 @@ use std::fmt::Display; trait StreamingIterator { - type Item<'a>; + type Item<'a> where Self: 'a; // Applying the lifetime parameter `'a` to `Self::Item` inside the trait. fn next<'a>(&'a mut self) -> Option<Self::Item<'a>>; } -struct Foo<T: StreamingIterator> { +struct Foo<T: StreamingIterator + 'static> { // Applying a concrete lifetime to the constructor outside the trait. bar: <T as StreamingIterator>::Item<'static>, } @@ -30,7 +30,7 @@ struct StreamEnumerate<I> { } impl<I: StreamingIterator> StreamingIterator for StreamEnumerate<I> { - type Item<'a> = (usize, I::Item<'a>); + type Item<'a> where Self: 'a = (usize, I::Item<'a>); fn next<'a>(&'a mut self) -> Option<Self::Item<'a>> { match self.iter.next() { None => None, @@ -44,7 +44,7 @@ impl<I: StreamingIterator> StreamingIterator for StreamEnumerate<I> { } impl<I: Iterator> StreamingIterator for I { - type Item<'a> = <I as Iterator>::Item; + type Item<'a> where Self: 'a = <I as Iterator>::Item; fn next(&mut self) -> Option<<I as StreamingIterator>::Item<'_>> { Iterator::next(self) } diff --git a/src/test/ui/generic-associated-types/variance_constraints.rs b/src/test/ui/generic-associated-types/variance_constraints.rs index 7bc250ee87..7d0f7638ac 100644 --- a/src/test/ui/generic-associated-types/variance_constraints.rs +++ b/src/test/ui/generic-associated-types/variance_constraints.rs @@ -3,7 +3,7 @@ #![feature(generic_associated_types)] trait A { - type B<'a>; + type B<'a> where Self: 'a; fn make_b<'a>(&'a self) -> Self::B<'a>; } diff --git a/src/test/ui/autobind.rs b/src/test/ui/generics/autobind.rs similarity index 100% rename from src/test/ui/autobind.rs rename to src/test/ui/generics/autobind.rs diff --git a/src/test/ui/issues/issue-1112.rs b/src/test/ui/generics/issue-1112.rs similarity index 100% rename from src/test/ui/issues/issue-1112.rs rename to src/test/ui/generics/issue-1112.rs diff --git a/src/test/ui/issues/issue-333.rs b/src/test/ui/generics/issue-333.rs similarity index 100% rename from src/test/ui/issues/issue-333.rs rename to src/test/ui/generics/issue-333.rs diff --git a/src/test/ui/issues/issue-59508-1.rs b/src/test/ui/generics/issue-59508-1.rs similarity index 100% rename from src/test/ui/issues/issue-59508-1.rs rename to src/test/ui/generics/issue-59508-1.rs diff --git a/src/test/ui/issues/issue-59508-1.stderr b/src/test/ui/generics/issue-59508-1.stderr similarity index 100% rename from src/test/ui/issues/issue-59508-1.stderr rename to src/test/ui/generics/issue-59508-1.stderr diff --git a/src/test/ui/issues/issue-59508.fixed b/src/test/ui/generics/issue-59508.fixed similarity index 100% rename from src/test/ui/issues/issue-59508.fixed rename to src/test/ui/generics/issue-59508.fixed diff --git a/src/test/ui/issues/issue-59508.rs b/src/test/ui/generics/issue-59508.rs similarity index 100% rename from src/test/ui/issues/issue-59508.rs rename to src/test/ui/generics/issue-59508.rs diff --git a/src/test/ui/issues/issue-59508.stderr b/src/test/ui/generics/issue-59508.stderr similarity index 100% rename from src/test/ui/issues/issue-59508.stderr rename to src/test/ui/generics/issue-59508.stderr diff --git a/src/test/ui/lifetime-before-type-params.rs b/src/test/ui/generics/lifetime-before-type-params.rs similarity index 100% rename from src/test/ui/lifetime-before-type-params.rs rename to src/test/ui/generics/lifetime-before-type-params.rs diff --git a/src/test/ui/lifetime-before-type-params.stderr b/src/test/ui/generics/lifetime-before-type-params.stderr similarity index 100% rename from src/test/ui/lifetime-before-type-params.stderr rename to src/test/ui/generics/lifetime-before-type-params.stderr diff --git a/src/test/ui/type-params-in-for-each.rs b/src/test/ui/generics/type-params-in-for-each.rs similarity index 100% rename from src/test/ui/type-params-in-for-each.rs rename to src/test/ui/generics/type-params-in-for-each.rs diff --git a/src/test/ui/half-open-range-patterns/range_pat_interactions0.rs b/src/test/ui/half-open-range-patterns/range_pat_interactions0.rs index 4f478a6988..8f745e8104 100644 --- a/src/test/ui/half-open-range-patterns/range_pat_interactions0.rs +++ b/src/test/ui/half-open-range-patterns/range_pat_interactions0.rs @@ -2,7 +2,7 @@ #![allow(incomplete_features)] #![feature(exclusive_range_pattern)] #![feature(half_open_range_patterns)] -#![feature(inline_const)] +#![feature(inline_const_pat)] fn main() { let mut if_lettable = vec![]; diff --git a/src/test/ui/half-open-range-patterns/range_pat_interactions3.rs b/src/test/ui/half-open-range-patterns/range_pat_interactions3.rs index 0afb512605..41c7e46dfc 100644 --- a/src/test/ui/half-open-range-patterns/range_pat_interactions3.rs +++ b/src/test/ui/half-open-range-patterns/range_pat_interactions3.rs @@ -12,7 +12,7 @@ fn main() { y @ (0..5 | 6) => or_two.push(y), //~^ exclusive range pattern syntax is experimental y @ 0..const { 5 + 1 } => assert_eq!(y, 5), - //~^ inline-const is experimental + //~^ inline-const in pattern position is experimental //~| exclusive range pattern syntax is experimental y @ -5.. => range_from.push(y), y @ ..-7 => assert_eq!(y, -8), diff --git a/src/test/ui/half-open-range-patterns/range_pat_interactions3.stderr b/src/test/ui/half-open-range-patterns/range_pat_interactions3.stderr index 8278e7cc6c..5e36996a46 100644 --- a/src/test/ui/half-open-range-patterns/range_pat_interactions3.stderr +++ b/src/test/ui/half-open-range-patterns/range_pat_interactions3.stderr @@ -7,14 +7,14 @@ LL | y @ ..-7 => assert_eq!(y, -8), = note: see issue #67264 <https://github.com/rust-lang/rust/issues/67264> for more information = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable -error[E0658]: inline-const is experimental +error[E0658]: inline-const in pattern position is experimental --> $DIR/range_pat_interactions3.rs:14:20 | LL | y @ 0..const { 5 + 1 } => assert_eq!(y, 5), | ^^^^^ | = note: see issue #76001 <https://github.com/rust-lang/rust/issues/76001> for more information - = help: add `#![feature(inline_const)]` to the crate attributes to enable + = help: add `#![feature(inline_const_pat)]` to the crate attributes to enable error[E0658]: exclusive range pattern syntax is experimental --> $DIR/range_pat_interactions3.rs:10:17 diff --git a/src/test/ui/hello2021.rs b/src/test/ui/hello2021.rs index 738f151b0f..134d8af5bf 100644 --- a/src/test/ui/hello2021.rs +++ b/src/test/ui/hello2021.rs @@ -1,6 +1,5 @@ // run-pass // edition:2021 -// compile-flags: -Zunstable-options fn main() { println!("hello, 2021"); diff --git a/src/test/ui/issues/issue-60283.rs b/src/test/ui/higher-rank-trait-bounds/issue-60283.rs similarity index 100% rename from src/test/ui/issues/issue-60283.rs rename to src/test/ui/higher-rank-trait-bounds/issue-60283.rs diff --git a/src/test/ui/issues/issue-60283.stderr b/src/test/ui/higher-rank-trait-bounds/issue-60283.stderr similarity index 100% rename from src/test/ui/issues/issue-60283.stderr rename to src/test/ui/higher-rank-trait-bounds/issue-60283.stderr diff --git a/src/test/ui/issues/issue-44005.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-44005.rs similarity index 95% rename from src/test/ui/issues/issue-44005.rs rename to src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-44005.rs index ab3b92142c..f255eac0c4 100644 --- a/src/test/ui/issues/issue-44005.rs +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-44005.rs @@ -1,3 +1,5 @@ +// check-pass + pub trait Foo<'a> { type Bar; fn foo(&'a self) -> Self::Bar; @@ -24,7 +26,6 @@ pub fn catalyst(x: &i32) { pub fn broken<F: Fn(&i32)>(x: &i32, f: F) { uncallable(x, |y| f(y)); - //~^ type mismatch } fn main() {} diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-56556.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-56556.rs new file mode 100644 index 0000000000..768d1c3661 --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-56556.rs @@ -0,0 +1,13 @@ +// check-pass + +fn foo<T>(t: T) -> usize +where + for<'a> &'a T: IntoIterator, + for<'a> <&'a T as IntoIterator>::IntoIter: ExactSizeIterator, +{ + t.into_iter().len() +} + +fn main() { + foo::<Vec<u32>>(vec![]); +} diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs index 24ac566f9d..7c3c72e04c 100644 --- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs @@ -77,7 +77,7 @@ where P: Execute + 'static { } fn main() { - task(annotate( //~ type mismatch + task(annotate( //~^ the size //~^^ the trait bound Annotate::<RefMutFamily<usize>>::new(), diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr index b13226fef6..01b14660b6 100644 --- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr @@ -1,29 +1,3 @@ -error[E0631]: type mismatch in closure arguments - --> $DIR/issue-62529-1.rs:80:10 - | -LL | task(annotate( - | _____----_^ - | | | - | | required by a bound introduced by this call -LL | | -LL | | -LL | | Annotate::<RefMutFamily<usize>>::new(), -LL | | |value: &mut usize| { - | | ------------------- found signature of `for<'r> fn(&'r mut usize) -> _` -LL | | *value = 2; -LL | | } -LL | | )); - | |_____^ expected signature of `for<'r> fn(<RefMutFamily<usize> as FamilyLt<'r>>::Out) -> _` - | -note: required by a bound in `annotate` - --> $DIR/issue-62529-1.rs:44:8 - | -LL | fn annotate<F, Q>(_q: Annotate<Q>, func: F) -> impl Execute + 'static - | -------- required by a bound in this -LL | where -LL | F: for<'r> FnOnce(<<Q as Inject>::I as FamilyLt<'r>>::Out) + 'static, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `annotate` - error[E0277]: the size for values of type `impl Execute` cannot be known at compilation time --> $DIR/issue-62529-1.rs:80:10 | @@ -73,7 +47,6 @@ LL | fn task<P>(processor: P) -> Task LL | where P: Execute + 'static { | ^^^^^^^ required by this bound in `task` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0277, E0631. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs index 87d1a250f7..3ced40230f 100644 --- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs @@ -1,3 +1,5 @@ +// check-pass + pub trait MyTrait<'a> { type Output: 'a; fn gimme_value(&self) -> Self::Output; @@ -23,7 +25,7 @@ where fn main() { let struc = MyStruct; - meow(struc, |foo| { //~ type mismatch + meow(struc, |foo| { println!("{:?}", foo); }) } diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.stderr deleted file mode 100644 index efc956888e..0000000000 --- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0631]: type mismatch in closure arguments - --> $DIR/issue-70120.rs:26:5 - | -LL | meow(struc, |foo| { - | ^^^^ ----- found signature of `for<'r> fn(&'r usize) -> _` - | | - | expected signature of `for<'any2> fn(<MyStruct as MyTrait<'any2>>::Output) -> _` - | -note: required by a bound in `meow` - --> $DIR/issue-70120.rs:18:8 - | -LL | fn meow<T, F>(t: T, f: F) - | ---- required by a bound in this -... -LL | F: for<'any2> Fn(<T as MyTrait<'any2>>::Output), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `meow` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.migrate.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.migrate.stderr new file mode 100644 index 0000000000..119cec1fa9 --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.migrate.stderr @@ -0,0 +1,92 @@ +error: implementation of `Parser` is not general enough + --> $DIR/issue-71955.rs:52:5 + | +LL | foo(bar, "string", |s| s.len() == 5); + | ^^^ implementation of `Parser` is not general enough + | + = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1` + +error: implementation of `Parser` is not general enough + --> $DIR/issue-71955.rs:52:5 + | +LL | foo(bar, "string", |s| s.len() == 5); + | ^^^ implementation of `Parser` is not general enough + | + = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1` + +error: implementation of `Parser` is not general enough + --> $DIR/issue-71955.rs:52:5 + | +LL | foo(bar, "string", |s| s.len() == 5); + | ^^^ implementation of `Parser` is not general enough + | + = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1` + +error: implementation of `Parser` is not general enough + --> $DIR/issue-71955.rs:52:5 + | +LL | foo(bar, "string", |s| s.len() == 5); + | ^^^ implementation of `Parser` is not general enough + | + = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1` + +error: implementation of `Parser` is not general enough + --> $DIR/issue-71955.rs:52:5 + | +LL | foo(bar, "string", |s| s.len() == 5); + | ^^^ implementation of `Parser` is not general enough + | + = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1` + +error: implementation of `Parser` is not general enough + --> $DIR/issue-71955.rs:58:5 + | +LL | foo(baz, "string", |s| s.0.len() == 5); + | ^^^ implementation of `Parser` is not general enough + | + = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1` + +error: implementation of `Parser` is not general enough + --> $DIR/issue-71955.rs:58:5 + | +LL | foo(baz, "string", |s| s.0.len() == 5); + | ^^^ implementation of `Parser` is not general enough + | + = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1` + +error: implementation of `Parser` is not general enough + --> $DIR/issue-71955.rs:58:5 + | +LL | foo(baz, "string", |s| s.0.len() == 5); + | ^^^ implementation of `Parser` is not general enough + | + = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1` + +error: implementation of `Parser` is not general enough + --> $DIR/issue-71955.rs:58:5 + | +LL | foo(baz, "string", |s| s.0.len() == 5); + | ^^^ implementation of `Parser` is not general enough + | + = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1` + +error: implementation of `Parser` is not general enough + --> $DIR/issue-71955.rs:58:5 + | +LL | foo(baz, "string", |s| s.0.len() == 5); + | ^^^ implementation of `Parser` is not general enough + | + = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1` + +error: aborting due to 10 previous errors + diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.nll.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.nll.stderr new file mode 100644 index 0000000000..69ab446bc7 --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.nll.stderr @@ -0,0 +1,8 @@ +error: fatal error triggered by #[rustc_error] + --> $DIR/issue-71955.rs:42:1 + | +LL | fn main() { + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs new file mode 100644 index 0000000000..95e3b3d4e1 --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs @@ -0,0 +1,64 @@ +// ignore-compare-mode-nll +// revisions: migrate nll +// [nll]compile-flags: -Zborrowck=mir +// check-fail + +#![feature(rustc_attrs)] + +trait Parser<'s> { + type Output; + + fn call(&self, input: &'s str) -> (&'s str, Self::Output); +} + +impl<'s, F, T> Parser<'s> for F +where F: Fn(&'s str) -> (&'s str, T) { + type Output = T; + fn call(&self, input: &'s str) -> (&'s str, T) { + self(input) + } +} + +fn foo<F1, F2>( + f1: F1, + base: &'static str, + f2: F2 +) +where + F1: for<'a> Parser<'a>, + F2: FnOnce(&<F1 as Parser>::Output) -> bool +{ + let s: String = base.to_owned(); + let str_ref = s.as_ref(); + let (remaining, produced) = f1.call(str_ref); + assert!(f2(&produced)); + assert_eq!(remaining.len(), 0); +} + +struct Wrapper<'a>(&'a str); + +// Because nll currently succeeds and migrate doesn't +#[rustc_error] +fn main() { + //[nll]~^ fatal + fn bar<'a>(s: &'a str) -> (&'a str, &'a str) { + (&s[..1], &s[..]) + } + + fn baz<'a>(s: &'a str) -> (&'a str, Wrapper<'a>) { + (&s[..1], Wrapper(&s[..])) + } + + foo(bar, "string", |s| s.len() == 5); + //[migrate]~^ ERROR implementation of `Parser` is not general enough + //[migrate]~| ERROR implementation of `Parser` is not general enough + //[migrate]~| ERROR implementation of `Parser` is not general enough + //[migrate]~| ERROR implementation of `Parser` is not general enough + //[migrate]~| ERROR implementation of `Parser` is not general enough + foo(baz, "string", |s| s.0.len() == 5); + //[migrate]~^ ERROR implementation of `Parser` is not general enough + //[migrate]~| ERROR implementation of `Parser` is not general enough + //[migrate]~| ERROR implementation of `Parser` is not general enough + //[migrate]~| ERROR implementation of `Parser` is not general enough + //[migrate]~| ERROR implementation of `Parser` is not general enough +} diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-74261.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-74261.rs new file mode 100644 index 0000000000..93ccb42684 --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-74261.rs @@ -0,0 +1,30 @@ +// check-pass + +use std::marker::PhantomData; + +trait A<'a> { + type B; + fn b(self) -> Self::B; +} + +struct T; +struct S<'a>(PhantomData<&'a ()>); + +impl<'a> A<'a> for T { + type B = S<'a>; + fn b(self) -> Self::B { + S(PhantomData) + } +} + +fn s<TT, F>(t: TT, f: F) +where + TT: for<'a> A<'a>, + F: for<'a> FnOnce(<TT as A<'a>>::B) +{ + f(t.b()); +} + +fn main() { + s(T, |_| {}); +} diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-76956.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-76956.rs new file mode 100644 index 0000000000..583470080a --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-76956.rs @@ -0,0 +1,15 @@ +// check-pass + +use std::ops::Deref; + +struct Data { + boxed: Box<&'static i32> +} + +impl Data { + fn use_data(&self, user: impl for <'a> FnOnce(<Box<&'a i32> as Deref>::Target)) { + user(*self.boxed) + } +} + +fn main() {} diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90612.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90612.rs new file mode 100644 index 0000000000..e150ecfe9a --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90612.rs @@ -0,0 +1,43 @@ +// check-pass + +#![feature(generic_associated_types)] + +use std::marker::PhantomData; + +trait Family: Sized { + type Item<'a>; + + fn apply_all<F>(&self, f: F) + where + F: FamilyItemFn<Self> { } +} + +struct Array<T>(PhantomData<T>); + +impl<T: 'static> Family for Array<T> { + type Item<'a> = &'a T; +} + +trait FamilyItemFn<T: Family> { + fn apply(&self, item: T::Item<'_>); +} + +impl<T, F> FamilyItemFn<T> for F +where + T: Family, + for<'a> F: Fn(T::Item<'a>) +{ + fn apply(&self, item: T::Item<'_>) { + (*self)(item); + } +} + +fn process<T: 'static>(array: Array<T>) { + // Works + array.apply_all(|x: &T| { }); + + // ICE: NoSolution + array.apply_all(|x: <Array<T> as Family>::Item<'_>| { }); +} + +fn main() {} diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90638.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90638.rs new file mode 100644 index 0000000000..18b7f38348 --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90638.rs @@ -0,0 +1,37 @@ +//check-pass + +#![feature(generic_associated_types)] + +trait Yokeable<'a>: 'static { + type Output: 'a; +} + +trait IsCovariant<'a> {} + +struct Yoke<Y: for<'a> Yokeable<'a>> { + data: Y, +} + +impl<Y: for<'a> Yokeable<'a>> Yoke<Y> { + fn project<Y2: for<'a> Yokeable<'a>>(&self, _f: for<'a> fn(<Y as Yokeable<'a>>::Output, &'a ()) + -> <Y2 as Yokeable<'a>>::Output) -> Yoke<Y2> { + + unimplemented!() + } +} + +fn _upcast<Y>(x: Yoke<Y>) -> Yoke<Box<dyn IsCovariant<'static> + 'static>> where + Y: for<'a> Yokeable<'a>, + for<'a> <Y as Yokeable<'a>>::Output: IsCovariant<'a> + { + x.project(|data, _| { + Box::new(data) + }) +} + + +impl<'a> Yokeable<'a> for Box<dyn IsCovariant<'static> + 'static> { + type Output = Box<dyn IsCovariant<'a> + 'a>; +} + +fn main() {} diff --git a/src/test/ui/hrtb/issue-30786.migrate.stderr b/src/test/ui/hrtb/issue-30786.migrate.stderr index a769872d83..a497c6257d 100644 --- a/src/test/ui/hrtb/issue-30786.migrate.stderr +++ b/src/test/ui/hrtb/issue-30786.migrate.stderr @@ -10,13 +10,14 @@ LL | pub struct Map<S, F> { LL | let filter = map.filterx(|x: &_| true); | ^^^^^^^ method cannot be called on `Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>` due to unsatisfied trait bounds | - = note: the following trait bounds were not satisfied: - `&'a mut Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: Stream` - which is required by `Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: StreamExt` - `&'a mut &Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: Stream` - which is required by `&Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: StreamExt` - `&'a mut &mut Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: Stream` - which is required by `&mut Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: StreamExt` +note: the following trait bounds were not satisfied because of the requirements of the implementation of `StreamExt` for `_`: + `&'a mut Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: Stream` + `&'a mut &Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: Stream` + `&'a mut &mut Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: Stream` + --> $DIR/issue-30786.rs:106:9 + | +LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {} + | ^^^^^^^^^ ^ error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>`, but its trait bounds were not satisfied --> $DIR/issue-30786.rs:141:24 @@ -30,13 +31,14 @@ LL | pub struct Filter<S, F> { LL | let count = filter.countx(); | ^^^^^^ method cannot be called on `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>` due to unsatisfied trait bounds | - = note: the following trait bounds were not satisfied: - `&'a mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` - which is required by `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt` - `&'a mut &Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` - which is required by `&Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt` - `&'a mut &mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` - which is required by `&mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt` +note: the following trait bounds were not satisfied because of the requirements of the implementation of `StreamExt` for `_`: + `&'a mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` + `&'a mut &Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` + `&'a mut &mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` + --> $DIR/issue-30786.rs:106:9 + | +LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {} + | ^^^^^^^^^ ^ error: aborting due to 2 previous errors diff --git a/src/test/ui/hrtb/issue-30786.nll.stderr b/src/test/ui/hrtb/issue-30786.nll.stderr index a769872d83..a497c6257d 100644 --- a/src/test/ui/hrtb/issue-30786.nll.stderr +++ b/src/test/ui/hrtb/issue-30786.nll.stderr @@ -10,13 +10,14 @@ LL | pub struct Map<S, F> { LL | let filter = map.filterx(|x: &_| true); | ^^^^^^^ method cannot be called on `Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>` due to unsatisfied trait bounds | - = note: the following trait bounds were not satisfied: - `&'a mut Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: Stream` - which is required by `Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: StreamExt` - `&'a mut &Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: Stream` - which is required by `&Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: StreamExt` - `&'a mut &mut Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: Stream` - which is required by `&mut Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: StreamExt` +note: the following trait bounds were not satisfied because of the requirements of the implementation of `StreamExt` for `_`: + `&'a mut Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: Stream` + `&'a mut &Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: Stream` + `&'a mut &mut Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: Stream` + --> $DIR/issue-30786.rs:106:9 + | +LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {} + | ^^^^^^^^^ ^ error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>`, but its trait bounds were not satisfied --> $DIR/issue-30786.rs:141:24 @@ -30,13 +31,14 @@ LL | pub struct Filter<S, F> { LL | let count = filter.countx(); | ^^^^^^ method cannot be called on `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>` due to unsatisfied trait bounds | - = note: the following trait bounds were not satisfied: - `&'a mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` - which is required by `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt` - `&'a mut &Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` - which is required by `&Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt` - `&'a mut &mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` - which is required by `&mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt` +note: the following trait bounds were not satisfied because of the requirements of the implementation of `StreamExt` for `_`: + `&'a mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` + `&'a mut &Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` + `&'a mut &mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` + --> $DIR/issue-30786.rs:106:9 + | +LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {} + | ^^^^^^^^^ ^ error: aborting due to 2 previous errors diff --git a/src/test/ui/hrtb/issue-62203-hrtb-ice.rs b/src/test/ui/hrtb/issue-62203-hrtb-ice.rs index 454d7e5e9c..80f099ce3c 100644 --- a/src/test/ui/hrtb/issue-62203-hrtb-ice.rs +++ b/src/test/ui/hrtb/issue-62203-hrtb-ice.rs @@ -37,8 +37,8 @@ trait Ty<'a> { fn main() { let v = Unit2.m( //~^ ERROR type mismatch - //~| ERROR type mismatch L { + //~^ ERROR type mismatch f : |x| { drop(x); Unit4 } }); } diff --git a/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr b/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr index 97f53bc70e..5db17cb1bf 100644 --- a/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr +++ b/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr @@ -2,24 +2,46 @@ error[E0271]: type mismatch resolving `for<'r> <L<[closure@$DIR/issue-62203-hrtb --> $DIR/issue-62203-hrtb-ice.rs:38:19 | LL | let v = Unit2.m( - | ^ expected struct `Unit4`, found associated type + | ^ expected associated type, found struct `Unit4` | - = note: expected struct `Unit4` - found associated type `<_ as Ty<'_>>::V` - = help: consider constraining the associated type `<_ as Ty<'_>>::V` to `Unit4` + = note: expected associated type `<_ as Ty<'_>>::V` + found struct `Unit4` + = help: consider constraining the associated type `<_ as Ty<'_>>::V` to `Unit4` or calling a method that returns `<_ as Ty<'_>>::V` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html +note: required by a bound in `T1::m` + --> $DIR/issue-62203-hrtb-ice.rs:27:51 + | +LL | fn m<'a, B: Ty<'a>, F>(&self, f: F) -> Unit1 + | - required by a bound in this +LL | where +LL | F: for<'r> T0<'r, (<Self as Ty<'r>>::V,), O = <B as Ty<'r>>::V>, + | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m` error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39] as FnOnce<((&'r u8,),)>>::Output == Unit3` - --> $DIR/issue-62203-hrtb-ice.rs:38:19 + --> $DIR/issue-62203-hrtb-ice.rs:40:9 | -LL | let v = Unit2.m( - | ^ expected struct `Unit4`, found struct `Unit3` +LL | let v = Unit2.m( + | - required by a bound introduced by this call +LL | +LL | / L { +LL | | +LL | | f : |x| { drop(x); Unit4 } +LL | | }); + | |_________^ expected struct `Unit3`, found struct `Unit4` | note: required because of the requirements on the impl of `for<'r> T0<'r, (&'r u8,)>` 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> | ^^^^^^^^^ ^^^^ +note: required by a bound in `T1::m` + --> $DIR/issue-62203-hrtb-ice.rs:27:12 + | +LL | fn m<'a, B: Ty<'a>, F>(&self, f: F) -> Unit1 + | - required by a bound in this +LL | where +LL | F: for<'r> T0<'r, (<Self as Ty<'r>>::V,), O = <B as Ty<'r>>::V>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m` error: aborting due to 2 previous errors diff --git a/src/test/ui/hrtb/issue-90177.rs b/src/test/ui/hrtb/issue-90177.rs new file mode 100644 index 0000000000..b151a9d3ab --- /dev/null +++ b/src/test/ui/hrtb/issue-90177.rs @@ -0,0 +1,32 @@ +// check-pass + +trait Base<'f> { + type Assoc; + + fn do_something(&self); +} + +trait ForAnyLifetime: for<'f> Base<'f> {} + +impl<T> ForAnyLifetime for T where T: for<'f> Base<'f> {} + +trait CanBeDynamic: ForAnyLifetime + for<'f> Base<'f, Assoc = ()> {} + +fn foo(a: &dyn CanBeDynamic) { + a.do_something(); +} + +struct S; + +impl<'a> Base<'a> for S { + type Assoc = (); + + fn do_something(&self) {} +} + +impl CanBeDynamic for S {} + +fn main() { + let s = S; + foo(&s); +} diff --git a/src/test/ui/hygiene/auxiliary/fields.rs b/src/test/ui/hygiene/auxiliary/fields.rs new file mode 100644 index 0000000000..733d11a9e8 --- /dev/null +++ b/src/test/ui/hygiene/auxiliary/fields.rs @@ -0,0 +1,73 @@ +#![feature(decl_macro)] + +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum Field { + RootCtxt, + MacroCtxt, +} + +#[rustfmt::skip] +macro x( + $macro_name:ident, + $macro2_name:ident, + $type_name:ident, + $field_name:ident, + $const_name:ident +) { + #[derive(Copy, Clone)] + pub struct $type_name { + pub field: Field, + pub $field_name: Field, + } + + pub const $const_name: $type_name = + $type_name { field: Field::MacroCtxt, $field_name: Field::RootCtxt }; + + #[macro_export] + macro_rules! $macro_name { + (check_fields_of $e:expr) => {{ + let e = $e; + assert_eq!(e.field, Field::MacroCtxt); + assert_eq!(e.$field_name, Field::RootCtxt); + }}; + (check_fields) => {{ + assert_eq!($const_name.field, Field::MacroCtxt); + assert_eq!($const_name.$field_name, Field::RootCtxt); + }}; + (construct) => { + $type_name { field: Field::MacroCtxt, $field_name: Field::RootCtxt } + }; + } + + pub macro $macro2_name { + (check_fields_of $e:expr) => {{ + let e = $e; + assert_eq!(e.field, Field::MacroCtxt); + assert_eq!(e.$field_name, Field::RootCtxt); + }}, + (check_fields) => {{ + assert_eq!($const_name.field, Field::MacroCtxt); + assert_eq!($const_name.$field_name, Field::RootCtxt); + }}, + (construct) => { + $type_name { field: Field::MacroCtxt, $field_name: Field::RootCtxt } + } + } +} + +x!(test_fields, test_fields2, MyStruct, field, MY_CONST); + +pub fn check_fields(s: MyStruct) { + test_fields!(check_fields_of s); +} + +pub fn check_fields_local() { + test_fields!(check_fields); + test_fields2!(check_fields); + + let s1 = test_fields!(construct); + test_fields!(check_fields_of s1); + + let s2 = test_fields2!(construct); + test_fields2!(check_fields_of s2); +} diff --git a/src/test/ui/hygiene/auxiliary/methods.rs b/src/test/ui/hygiene/auxiliary/methods.rs new file mode 100644 index 0000000000..23b9c61cfc --- /dev/null +++ b/src/test/ui/hygiene/auxiliary/methods.rs @@ -0,0 +1,160 @@ +#![feature(decl_macro)] + +#[derive(PartialEq, Eq, Debug)] +pub enum Method { + DefaultMacroCtxt, + DefaultRootCtxt, + OverrideMacroCtxt, + OverrideRootCtxt, +} + +#[rustfmt::skip] +macro x($macro_name:ident, $macro2_name:ident, $trait_name:ident, $method_name:ident) { + pub trait $trait_name { + fn method(&self) -> Method { + Method::DefaultMacroCtxt + } + + fn $method_name(&self) -> Method { + Method::DefaultRootCtxt + } + } + + impl $trait_name for () {} + impl $trait_name for bool { + fn method(&self) -> Method { + Method::OverrideMacroCtxt + } + + fn $method_name(&self) -> Method { + Method::OverrideRootCtxt + } + } + + #[macro_export] + macro_rules! $macro_name { + (check_resolutions) => { + assert_eq!(().method(), Method::DefaultMacroCtxt); + assert_eq!($trait_name::method(&()), Method::DefaultMacroCtxt); + assert_eq!(().$method_name(), Method::DefaultRootCtxt); + assert_eq!($trait_name::$method_name(&()), Method::DefaultRootCtxt); + + assert_eq!(false.method(), Method::OverrideMacroCtxt); + assert_eq!($trait_name::method(&false), Method::OverrideMacroCtxt); + assert_eq!(false.$method_name(), Method::OverrideRootCtxt); + assert_eq!($trait_name::$method_name(&false), Method::OverrideRootCtxt); + + assert_eq!('a'.method(), Method::DefaultMacroCtxt); + assert_eq!($trait_name::method(&'a'), Method::DefaultMacroCtxt); + assert_eq!('a'.$method_name(), Method::DefaultRootCtxt); + assert_eq!($trait_name::$method_name(&'a'), Method::DefaultRootCtxt); + + assert_eq!(1i32.method(), Method::OverrideMacroCtxt); + assert_eq!($trait_name::method(&1i32), Method::OverrideMacroCtxt); + assert_eq!(1i32.$method_name(), Method::OverrideRootCtxt); + assert_eq!($trait_name::$method_name(&1i32), Method::OverrideRootCtxt); + + assert_eq!(1i64.method(), Method::OverrideMacroCtxt); + assert_eq!($trait_name::method(&1i64), Method::OverrideMacroCtxt); + assert_eq!(1i64.$method_name(), Method::OverrideRootCtxt); + assert_eq!($trait_name::$method_name(&1i64), Method::OverrideRootCtxt); + }; + (assert_no_override $v:expr) => { + assert_eq!($v.method(), Method::DefaultMacroCtxt); + assert_eq!($trait_name::method(&$v), Method::DefaultMacroCtxt); + assert_eq!($v.$method_name(), Method::DefaultRootCtxt); + assert_eq!($trait_name::$method_name(&$v), Method::DefaultRootCtxt); + }; + (assert_override $v:expr) => { + assert_eq!($v.method(), Method::OverrideMacroCtxt); + assert_eq!($trait_name::method(&$v), Method::OverrideMacroCtxt); + assert_eq!($v.$method_name(), Method::OverrideRootCtxt); + assert_eq!($trait_name::$method_name(&$v), Method::OverrideRootCtxt); + }; + (impl for $t:ty) => { + impl $trait_name for $t { + fn method(&self) -> Method { + Method::OverrideMacroCtxt + } + + fn $method_name(&self) -> Method { + Method::OverrideRootCtxt + } + } + }; + } + + pub macro $macro2_name { + (check_resolutions) => { + assert_eq!(().method(), Method::DefaultMacroCtxt); + assert_eq!($trait_name::method(&()), Method::DefaultMacroCtxt); + assert_eq!(().$method_name(), Method::DefaultRootCtxt); + assert_eq!($trait_name::$method_name(&()), Method::DefaultRootCtxt); + + assert_eq!(false.method(), Method::OverrideMacroCtxt); + assert_eq!($trait_name::method(&false), Method::OverrideMacroCtxt); + assert_eq!(false.$method_name(), Method::OverrideRootCtxt); + assert_eq!($trait_name::$method_name(&false), Method::OverrideRootCtxt); + + assert_eq!('a'.method(), Method::DefaultMacroCtxt); + assert_eq!($trait_name::method(&'a'), Method::DefaultMacroCtxt); + assert_eq!('a'.$method_name(), Method::DefaultRootCtxt); + assert_eq!($trait_name::$method_name(&'a'), Method::DefaultRootCtxt); + + assert_eq!(1i32.method(), Method::OverrideMacroCtxt); + assert_eq!($trait_name::method(&1i32), Method::OverrideMacroCtxt); + assert_eq!(1i32.$method_name(), Method::OverrideRootCtxt); + assert_eq!($trait_name::$method_name(&1i32), Method::OverrideRootCtxt); + + assert_eq!(1i64.method(), Method::OverrideMacroCtxt); + assert_eq!($trait_name::method(&1i64), Method::OverrideMacroCtxt); + assert_eq!(1i64.$method_name(), Method::OverrideRootCtxt); + assert_eq!($trait_name::$method_name(&1i64), Method::OverrideRootCtxt); + }, + (assert_no_override $v:expr) => { + assert_eq!($v.method(), Method::DefaultMacroCtxt); + assert_eq!($trait_name::method(&$v), Method::DefaultMacroCtxt); + assert_eq!($v.$method_name(), Method::DefaultRootCtxt); + assert_eq!($trait_name::$method_name(&$v), Method::DefaultRootCtxt); + }, + (assert_override $v:expr) => { + assert_eq!($v.method(), Method::OverrideMacroCtxt); + assert_eq!($trait_name::method(&$v), Method::OverrideMacroCtxt); + assert_eq!($v.$method_name(), Method::OverrideRootCtxt); + assert_eq!($trait_name::$method_name(&$v), Method::OverrideRootCtxt); + }, + (impl for $t:ty) => { + impl $trait_name for $t { + fn method(&self) -> Method { + Method::OverrideMacroCtxt + } + + fn $method_name(&self) -> Method { + Method::OverrideRootCtxt + } + } + } + } +} + +x!(test_trait, test_trait2, MyTrait, method); + +impl MyTrait for char {} +test_trait!(impl for i32); +test_trait2!(impl for i64); + +pub fn check_crate_local() { + test_trait!(check_resolutions); + test_trait2!(check_resolutions); +} + +// Check that any comparison of idents at monomorphization time is correct +pub fn check_crate_local_generic<T: MyTrait, U: MyTrait>(t: T, u: U) { + test_trait!(check_resolutions); + test_trait2!(check_resolutions); + + test_trait!(assert_no_override t); + test_trait2!(assert_no_override t); + test_trait!(assert_override u); + test_trait2!(assert_override u); +} diff --git a/src/test/ui/hygiene/auxiliary/pub_hygiene.rs b/src/test/ui/hygiene/auxiliary/pub_hygiene.rs new file mode 100644 index 0000000000..47e76a629c --- /dev/null +++ b/src/test/ui/hygiene/auxiliary/pub_hygiene.rs @@ -0,0 +1,7 @@ +#![feature(decl_macro)] + +macro x() { + pub struct MyStruct; +} + +x!(); diff --git a/src/test/ui/hygiene/auxiliary/use_by_macro.rs b/src/test/ui/hygiene/auxiliary/use_by_macro.rs new file mode 100644 index 0000000000..791cf03589 --- /dev/null +++ b/src/test/ui/hygiene/auxiliary/use_by_macro.rs @@ -0,0 +1,15 @@ +#![feature(decl_macro)] + +macro x($macro_name:ident) { + #[macro_export] + macro_rules! $macro_name { + (define) => { + pub struct MyStruct; + }; + (create) => { + MyStruct {} + }; + } +} + +x!(my_struct); diff --git a/src/test/ui/hygiene/auxiliary/variants.rs b/src/test/ui/hygiene/auxiliary/variants.rs new file mode 100644 index 0000000000..dbfcce17d4 --- /dev/null +++ b/src/test/ui/hygiene/auxiliary/variants.rs @@ -0,0 +1,36 @@ +#![feature(decl_macro)] + +#[rustfmt::skip] +macro x($macro_name:ident, $macro2_name:ident, $type_name:ident, $variant_name:ident) { + #[repr(u8)] + pub enum $type_name { + Variant = 0, + $variant_name = 1, + } + + #[macro_export] + macro_rules! $macro_name { + () => {{ + assert_eq!($type_name::Variant as u8, 0); + assert_eq!($type_name::$variant_name as u8, 1); + assert_eq!(<$type_name>::Variant as u8, 0); + assert_eq!(<$type_name>::$variant_name as u8, 1); + }}; + } + + pub macro $macro2_name { + () => {{ + assert_eq!($type_name::Variant as u8, 0); + assert_eq!($type_name::$variant_name as u8, 1); + assert_eq!(<$type_name>::Variant as u8, 0); + assert_eq!(<$type_name>::$variant_name as u8, 1); + }}, + } +} + +x!(test_variants, test_variants2, MyEnum, Variant); + +pub fn check_variants() { + test_variants!(); + test_variants2!(); +} diff --git a/src/test/ui/hygiene/cross-crate-define-and-use.rs b/src/test/ui/hygiene/cross-crate-define-and-use.rs new file mode 100644 index 0000000000..94f1adff62 --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-define-and-use.rs @@ -0,0 +1,19 @@ +// Check that a marco from another crate can define an item in one expansion +// and use it from another, without it being visible to everyone. +// This requires that the definition of `my_struct` preserves the hygiene +// information for the tokens in its definition. + +// check-pass +// aux-build:use_by_macro.rs + +#![feature(type_name_of_val)] +extern crate use_by_macro; + +use use_by_macro::*; + +enum MyStruct {} +my_struct!(define); + +fn main() { + let x = my_struct!(create); +} diff --git a/src/test/ui/hygiene/cross-crate-fields.rs b/src/test/ui/hygiene/cross-crate-fields.rs new file mode 100644 index 0000000000..1bcd64573a --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-fields.rs @@ -0,0 +1,24 @@ +// Test that fields on a struct defined in another crate are resolved correctly +// their names differ only in `SyntaxContext`. + +// run-pass +// aux-build:fields.rs + +extern crate fields; + +use fields::*; + +fn main() { + check_fields_local(); + + test_fields!(check_fields); + test_fields2!(check_fields); + + let s1 = test_fields!(construct); + check_fields(s1); + test_fields!(check_fields_of s1); + + let s2 = test_fields2!(construct); + check_fields(s2); + test_fields2!(check_fields_of s2); +} diff --git a/src/test/ui/hygiene/cross-crate-glob-hygiene.rs b/src/test/ui/hygiene/cross-crate-glob-hygiene.rs new file mode 100644 index 0000000000..de5576682a --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-glob-hygiene.rs @@ -0,0 +1,23 @@ +// Check that globs cannot import hygienic identifiers from a macro expansion +// in another crate. `my_struct` is a `macro_rules` macro, so the struct it +// defines is only not imported because `my_struct` is defined by a macros 2.0 +// macro. + +// aux-build:use_by_macro.rs + +extern crate use_by_macro; + +use use_by_macro::*; + +mod m { + use use_by_macro::*; + + my_struct!(define); +} + +use m::*; + +fn main() { + let x = my_struct!(create); + //~^ ERROR cannot find struct, variant or union type `MyStruct` in this scope +} diff --git a/src/test/ui/hygiene/cross-crate-glob-hygiene.stderr b/src/test/ui/hygiene/cross-crate-glob-hygiene.stderr new file mode 100644 index 0000000000..7369e77d07 --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-glob-hygiene.stderr @@ -0,0 +1,11 @@ +error[E0422]: cannot find struct, variant or union type `MyStruct` in this scope + --> $DIR/cross-crate-glob-hygiene.rs:21:13 + | +LL | let x = my_struct!(create); + | ^^^^^^^^^^^^^^^^^^ not found in this scope + | + = note: this error originates in the macro `my_struct` (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 E0422`. diff --git a/src/test/ui/hygiene/cross-crate-methods.rs b/src/test/ui/hygiene/cross-crate-methods.rs new file mode 100644 index 0000000000..0e6f57c33f --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-methods.rs @@ -0,0 +1,33 @@ +// Test that methods defined in another crate are resolved correctly their +// names differ only in `SyntaxContext`. This also checks that any name +// resolution done when monomorphizing is correct. + +// run-pass +// aux-build:methods.rs + +extern crate methods; + +use methods::*; + +struct A; +struct B; +struct C; + +impl MyTrait for A {} +test_trait!(impl for B); +test_trait2!(impl for C); + +fn main() { + check_crate_local(); + check_crate_local_generic(A, B); + check_crate_local_generic(A, C); + + test_trait!(check_resolutions); + test_trait2!(check_resolutions); + test_trait!(assert_no_override A); + test_trait2!(assert_no_override A); + test_trait!(assert_override B); + test_trait2!(assert_override B); + test_trait!(assert_override C); + test_trait2!(assert_override C); +} diff --git a/src/test/ui/hygiene/cross-crate-name-collision.rs b/src/test/ui/hygiene/cross-crate-name-collision.rs new file mode 100644 index 0000000000..8f118782f2 --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-name-collision.rs @@ -0,0 +1,12 @@ +// Check that two items defined in another crate that have identifiers that +// only differ by `SyntaxContext` do not cause name collisions when imported +// in another crate. + +// check-pass +// aux-build:needs_hygiene.rs + +extern crate needs_hygiene; + +use needs_hygiene::*; + +fn main() {} diff --git a/src/test/ui/hygiene/cross-crate-name-hiding-2.rs b/src/test/ui/hygiene/cross-crate-name-hiding-2.rs new file mode 100644 index 0000000000..3eacd775c9 --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-name-hiding-2.rs @@ -0,0 +1,15 @@ +// Check that an identifier from a 2.0 macro in another crate cannot be +// resolved with an identifier that's not from a macro expansion. + +// aux-build:use_by_macro.rs + +extern crate use_by_macro; + +use use_by_macro::*; + +my_struct!(define); + +fn main() { + let x = MyStruct {}; + //~^ ERROR cannot find struct, variant or union type `MyStruct` in this scope +} diff --git a/src/test/ui/hygiene/cross-crate-name-hiding-2.stderr b/src/test/ui/hygiene/cross-crate-name-hiding-2.stderr new file mode 100644 index 0000000000..46314cdd5a --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-name-hiding-2.stderr @@ -0,0 +1,9 @@ +error[E0422]: cannot find struct, variant or union type `MyStruct` in this scope + --> $DIR/cross-crate-name-hiding-2.rs:13:13 + | +LL | let x = MyStruct {}; + | ^^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0422`. diff --git a/src/test/ui/hygiene/cross-crate-name-hiding.rs b/src/test/ui/hygiene/cross-crate-name-hiding.rs new file mode 100644 index 0000000000..dd76ecc576 --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-name-hiding.rs @@ -0,0 +1,13 @@ +// Check that an item defined by a 2.0 macro in another crate cannot be used in +// another crate. + +// aux-build:pub_hygiene.rs + +extern crate pub_hygiene; + +use pub_hygiene::*; + +fn main() { + let x = MyStruct {}; + //~^ ERROR cannot find struct, variant or union type `MyStruct` in this scope +} diff --git a/src/test/ui/hygiene/cross-crate-name-hiding.stderr b/src/test/ui/hygiene/cross-crate-name-hiding.stderr new file mode 100644 index 0000000000..f8840c8f85 --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-name-hiding.stderr @@ -0,0 +1,9 @@ +error[E0422]: cannot find struct, variant or union type `MyStruct` in this scope + --> $DIR/cross-crate-name-hiding.rs:11:13 + | +LL | let x = MyStruct {}; + | ^^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0422`. diff --git a/src/test/ui/hygiene/cross-crate-redefine.rs b/src/test/ui/hygiene/cross-crate-redefine.rs new file mode 100644 index 0000000000..3cb06b4bad --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-redefine.rs @@ -0,0 +1,14 @@ +// Check that items with identical `SyntaxContext` conflict even when that +// context involves a mark from another crate. + +// aux-build:use_by_macro.rs + +extern crate use_by_macro; + +use use_by_macro::*; + +my_struct!(define); +//~^ ERROR the name `MyStruct` is defined multiple times +my_struct!(define); + +fn main() {} diff --git a/src/test/ui/hygiene/cross-crate-redefine.stderr b/src/test/ui/hygiene/cross-crate-redefine.stderr new file mode 100644 index 0000000000..4f1419de42 --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-redefine.stderr @@ -0,0 +1,15 @@ +error[E0428]: the name `MyStruct` is defined multiple times + --> $DIR/cross-crate-redefine.rs:10:1 + | +LL | my_struct!(define); + | ^^^^^^^^^^^^^^^^^^ `MyStruct` redefined here +LL | +LL | my_struct!(define); + | ------------------ previous definition of the type `MyStruct` here + | + = note: `MyStruct` must be defined only once in the type namespace of this module + = note: this error originates in the macro `my_struct` (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 E0428`. diff --git a/src/test/ui/hygiene/cross-crate-variants.rs b/src/test/ui/hygiene/cross-crate-variants.rs new file mode 100644 index 0000000000..efc73a21f1 --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-variants.rs @@ -0,0 +1,18 @@ +// Test that variants of an enum defined in another crate are resolved +// correctly when their names differ only in `SyntaxContext`. + +// run-pass +// aux-build:variants.rs + +extern crate variants; + +use variants::*; + +fn main() { + check_variants(); + + test_variants!(); + test_variants2!(); + + assert_eq!(MyEnum::Variant as u8, 1); +} diff --git a/src/test/ui/hygiene/cross_crate_hygiene.rs b/src/test/ui/hygiene/cross_crate_hygiene.rs deleted file mode 100644 index 75742960b7..0000000000 --- a/src/test/ui/hygiene/cross_crate_hygiene.rs +++ /dev/null @@ -1,8 +0,0 @@ -// check-pass -// aux-build:needs_hygiene.rs - -extern crate needs_hygiene; - -use needs_hygiene::*; - -fn main() {} diff --git a/src/test/ui/lambda-var-hygiene.rs b/src/test/ui/hygiene/lambda-var-hygiene.rs similarity index 100% rename from src/test/ui/lambda-var-hygiene.rs rename to src/test/ui/hygiene/lambda-var-hygiene.rs diff --git a/src/test/ui/hygiene/rustc-macro-transparency.stderr b/src/test/ui/hygiene/rustc-macro-transparency.stderr index ef650b75b5..e4c1c8ad29 100644 --- a/src/test/ui/hygiene/rustc-macro-transparency.stderr +++ b/src/test/ui/hygiene/rustc-macro-transparency.stderr @@ -2,11 +2,14 @@ error[E0425]: cannot find value `Opaque` in this scope --> $DIR/rustc-macro-transparency.rs:26:5 | LL | Opaque; - | ^^^^^^ help: a local variable with a similar name exists (notice the capitalization): `opaque` + | ^^^^^^ not found in this scope error[E0423]: expected value, found macro `semitransparent` --> $DIR/rustc-macro-transparency.rs:29:5 | +LL | struct SemiTransparent; + | ----------------------- similarly named unit struct `SemiTransparent` defined here +... LL | semitransparent; | ^^^^^^^^^^^^^^^ not a value | @@ -14,10 +17,17 @@ help: use `!` to invoke the macro | LL | semitransparent!; | + +help: a unit struct with a similar name exists + | +LL | SemiTransparent; + | ~~~~~~~~~~~~~~~ error[E0423]: expected value, found macro `opaque` --> $DIR/rustc-macro-transparency.rs:30:5 | +LL | struct Opaque; + | -------------- similarly named unit struct `Opaque` defined here +... LL | opaque; | ^^^^^^ not a value | @@ -25,6 +35,10 @@ help: use `!` to invoke the macro | LL | opaque!; | + +help: a unit struct with a similar name exists + | +LL | Opaque; + | ~~~~~~ error: aborting due to 3 previous errors diff --git a/src/test/ui/thread-local-not-in-prelude.rs b/src/test/ui/hygiene/thread-local-not-in-prelude.rs similarity index 100% rename from src/test/ui/thread-local-not-in-prelude.rs rename to src/test/ui/hygiene/thread-local-not-in-prelude.rs diff --git a/src/test/ui/impl-trait/auto-trait-leak2.stderr b/src/test/ui/impl-trait/auto-trait-leak2.stderr index 5a8e503601..37ae3c6802 100644 --- a/src/test/ui/impl-trait/auto-trait-leak2.stderr +++ b/src/test/ui/impl-trait/auto-trait-leak2.stderr @@ -1,15 +1,17 @@ error[E0277]: `Rc<Cell<i32>>` cannot be sent between threads safely - --> $DIR/auto-trait-leak2.rs:13:5 + --> $DIR/auto-trait-leak2.rs:13:10 | LL | fn before() -> impl Fn(i32) { - | ------------ within this `impl Fn<(i32,)>` + | ------------ within this `impl Fn(i32)` ... LL | send(before()); - | ^^^^ `Rc<Cell<i32>>` cannot be sent between threads safely + | ---- ^^^^^^^^ `Rc<Cell<i32>>` cannot be sent between threads safely + | | + | required by a bound introduced by this call | - = help: within `impl Fn<(i32,)>`, the trait `Send` is not implemented for `Rc<Cell<i32>>` + = help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc<Cell<i32>>` = note: required because it appears within the type `[closure@$DIR/auto-trait-leak2.rs:7:5: 7:22]` - = note: required because it appears within the type `impl Fn<(i32,)>` + = note: required because it appears within the type `impl Fn(i32)` note: required by a bound in `send` --> $DIR/auto-trait-leak2.rs:10:12 | @@ -17,17 +19,19 @@ LL | fn send<T: Send>(_: T) {} | ^^^^ required by this bound in `send` error[E0277]: `Rc<Cell<i32>>` cannot be sent between threads safely - --> $DIR/auto-trait-leak2.rs:16:5 + --> $DIR/auto-trait-leak2.rs:16:10 | LL | send(after()); - | ^^^^ `Rc<Cell<i32>>` cannot be sent between threads safely + | ---- ^^^^^^^ `Rc<Cell<i32>>` cannot be sent between threads safely + | | + | required by a bound introduced by this call ... LL | fn after() -> impl Fn(i32) { - | ------------ within this `impl Fn<(i32,)>` + | ------------ within this `impl Fn(i32)` | - = help: within `impl Fn<(i32,)>`, the trait `Send` is not implemented for `Rc<Cell<i32>>` + = help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc<Cell<i32>>` = note: required because it appears within the type `[closure@$DIR/auto-trait-leak2.rs:24:5: 24:22]` - = note: required because it appears within the type `impl Fn<(i32,)>` + = note: required because it appears within the type `impl Fn(i32)` note: required by a bound in `send` --> $DIR/auto-trait-leak2.rs:10:12 | diff --git a/src/test/ui/impl-trait/equality.rs b/src/test/ui/impl-trait/equality.rs index 828b5aac89..9610618ca1 100644 --- a/src/test/ui/impl-trait/equality.rs +++ b/src/test/ui/impl-trait/equality.rs @@ -17,7 +17,7 @@ fn two(x: bool) -> impl Foo { //~| expected `i32`, found `u32` } -fn sum_to(n: u32) -> impl Foo { +fn sum_to(n: u32) -> impl Foo { //~ ERROR type annotations needed if n == 0 { 0 } else { diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr index 536a4726c6..d9819484a9 100644 --- a/src/test/ui/impl-trait/equality.stderr +++ b/src/test/ui/impl-trait/equality.stderr @@ -34,7 +34,22 @@ LL | n + sum_to(n - 1) | = help: the trait `Add<impl Foo>` is not implemented for `u32` -error: aborting due to 2 previous errors; 1 warning emitted +error[E0283]: type annotations needed + --> $DIR/equality.rs:20:22 + | +LL | fn sum_to(n: u32) -> impl Foo { + | ^^^^^^^^ cannot infer type for type `{integer}` + | + = note: multiple `impl`s satisfying `{integer}: ToString` found in the `alloc` crate: + - impl ToString for i8; + - impl ToString for u8; +note: required because of the requirements on the impl of `Foo` for `{integer}` + --> $DIR/equality.rs:5:26 + | +LL | impl<T: Copy + ToString> Foo for T {} + | ^^^ ^ + +error: aborting due to 3 previous errors; 1 warning emitted -Some errors have detailed explanations: E0277, E0308. +Some errors have detailed explanations: E0277, E0283, E0308. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/feature-gate.stderr b/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/feature-gate.stderr index 6adc4e6b23..a25c85faf4 100644 --- a/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/feature-gate.stderr +++ b/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/feature-gate.stderr @@ -3,6 +3,9 @@ error[E0632]: cannot provide explicit generic arguments when `impl Trait` is use | LL | foo::<str>("".to_string()); | ^^^ explicit generic argument not allowed + | + = note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information + = help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable error: aborting due to previous error diff --git a/src/test/ui/impl-trait/impl-trait-in-macro.stderr b/src/test/ui/impl-trait/impl-trait-in-macro.stderr index b5f9986ce4..7cfbe3447b 100644 --- a/src/test/ui/impl-trait/impl-trait-in-macro.stderr +++ b/src/test/ui/impl-trait/impl-trait-in-macro.stderr @@ -7,6 +7,8 @@ LL | ($($tr:tt)*) => { impl $($tr)* }; | expected type parameter | found type parameter ... +LL | let mut a = x; + | - expected due to this value LL | a = y; | ^ expected type parameter `impl Debug`, found a different type parameter `impl Debug` | diff --git a/src/test/ui/issues/issue-49579.rs b/src/test/ui/impl-trait/issue-49579.rs similarity index 100% rename from src/test/ui/issues/issue-49579.rs rename to src/test/ui/impl-trait/issue-49579.rs diff --git a/src/test/ui/issues/issue-49685.rs b/src/test/ui/impl-trait/issue-49685.rs similarity index 100% rename from src/test/ui/issues/issue-49685.rs rename to src/test/ui/impl-trait/issue-49685.rs diff --git a/src/test/ui/issues/issue-51185.rs b/src/test/ui/impl-trait/issue-51185.rs similarity index 100% rename from src/test/ui/issues/issue-51185.rs rename to src/test/ui/impl-trait/issue-51185.rs diff --git a/src/test/ui/impl-trait/issue-55872-1.stderr b/src/test/ui/impl-trait/issue-55872-1.stderr index e772445a56..2d1142fd0c 100644 --- a/src/test/ui/impl-trait/issue-55872-1.stderr +++ b/src/test/ui/impl-trait/issue-55872-1.stderr @@ -1,11 +1,11 @@ error[E0276]: impl has stricter requirements than trait - --> $DIR/issue-55872-1.rs:12:5 + --> $DIR/issue-55872-1.rs:12:15 | LL | fn foo<T>() -> Self::E; | ----------------------- definition of `foo` from trait ... LL | fn foo<T: Default>() -> Self::E { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: Default` + | ^^^^^^^ impl has extra requirement `T: Default` error[E0277]: the trait bound `S: Copy` is not satisfied in `(S, T)` --> $DIR/issue-55872-1.rs:12:29 diff --git a/src/test/ui/impl-trait/issue-55872-2.rs b/src/test/ui/impl-trait/issue-55872-2.rs index 9546d01ac5..a519397806 100644 --- a/src/test/ui/impl-trait/issue-55872-2.rs +++ b/src/test/ui/impl-trait/issue-55872-2.rs @@ -13,7 +13,7 @@ impl<S> Bar for S { type E = impl std::marker::Copy; fn foo<T>() -> Self::E { //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - //~| ERROR the trait bound `impl Future: Copy` is not satisfied [E0277] + //~| ERROR the trait bound `impl Future<Output = [async output]>: Copy` is not satisfied async {} } } diff --git a/src/test/ui/impl-trait/issue-55872-2.stderr b/src/test/ui/impl-trait/issue-55872-2.stderr index 31b8fbd299..97545ba3d1 100644 --- a/src/test/ui/impl-trait/issue-55872-2.stderr +++ b/src/test/ui/impl-trait/issue-55872-2.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `impl Future: Copy` is not satisfied +error[E0277]: the trait bound `impl Future<Output = [async output]>: Copy` is not satisfied --> $DIR/issue-55872-2.rs:14:20 | LL | fn foo<T>() -> Self::E { - | ^^^^^^^ the trait `Copy` is not implemented for `impl Future` + | ^^^^^^^ the trait `Copy` is not implemented for `impl Future<Output = [async output]>` 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:14:28 diff --git a/src/test/ui/impl-trait/issue-72911.stderr b/src/test/ui/impl-trait/issue-72911.stderr index 17748ae427..e57fbf104d 100644 --- a/src/test/ui/impl-trait/issue-72911.stderr +++ b/src/test/ui/impl-trait/issue-72911.stderr @@ -19,14 +19,14 @@ LL | LL | lint_files().flat_map(|f| gather_from_file(&f)) | ----------------------------------------------- | | - | returning here with type `FlatMap<impl Iterator, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>` - | returning here with type `FlatMap<impl Iterator, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>` + | returning here with type `FlatMap<impl Iterator<Item = [type error]>, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>` + | returning here with type `FlatMap<impl Iterator<Item = [type error]>, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>` ... LL | fn gather_from_file(dir_entry: &foo::MissingItem) -> impl Iterator<Item = Lint> { - | -------------------------- returning this opaque type `FlatMap<impl Iterator, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>` + | -------------------------- returning this opaque type `FlatMap<impl Iterator<Item = [type error]>, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>` ... LL | fn lint_files() -> impl Iterator<Item = foo::MissingItem> { - | -------------------------------------- returning this opaque type `FlatMap<impl Iterator, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>` + | -------------------------------------- returning this opaque type `FlatMap<impl Iterator<Item = [type error]>, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>` error: aborting due to 3 previous errors diff --git a/src/test/ui/impl-trait/issue-87450.stderr b/src/test/ui/impl-trait/issue-87450.stderr index 83eb33efc6..5019e544bd 100644 --- a/src/test/ui/impl-trait/issue-87450.stderr +++ b/src/test/ui/impl-trait/issue-87450.stderr @@ -17,10 +17,10 @@ LL | fn foo() -> impl Fn() { | ^^^^^^^^^ recursive opaque type ... LL | wrap(wrap(wrap(wrap(wrap(wrap(wrap(foo()))))))) - | ----------------------------------------------- returning here with type `impl Fn<()>` + | ----------------------------------------------- returning here with type `impl Fn()` ... LL | fn wrap(f: impl Fn()) -> impl Fn() { - | --------- returning this opaque type `impl Fn<()>` + | --------- returning this opaque type `impl Fn()` error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/impl-trait/issues/issue-78722.stderr b/src/test/ui/impl-trait/issues/issue-78722.stderr index 5e432e7649..130678de23 100644 --- a/src/test/ui/impl-trait/issues/issue-78722.stderr +++ b/src/test/ui/impl-trait/issues/issue-78722.stderr @@ -14,8 +14,8 @@ LL | let f: F = async { 1 }; LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return> | ------------------------------- the found opaque type | - = note: expected opaque type `impl Future` (opaque type at <$DIR/issue-78722.rs:5:10>) - found opaque type `impl Future` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>) + = note: expected opaque type `impl Future<Output = u8>` + found opaque type `impl Future<Output = [async output]>` = note: distinct uses of `impl Trait` result in different opaque types error: aborting due to previous error diff --git a/src/test/ui/impl-trait/issues/universal-issue-48703.stderr b/src/test/ui/impl-trait/issues/universal-issue-48703.stderr index 6800b37b5b..90c252537e 100644 --- a/src/test/ui/impl-trait/issues/universal-issue-48703.stderr +++ b/src/test/ui/impl-trait/issues/universal-issue-48703.stderr @@ -3,6 +3,9 @@ error[E0632]: cannot provide explicit generic arguments when `impl Trait` is use | LL | foo::<String>('a'); | ^^^^^^ explicit generic argument not allowed + | + = note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information + = help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable error: aborting due to previous error diff --git a/src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.stderr b/src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.stderr index db66d46109..84b98f71f4 100644 --- a/src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.stderr +++ b/src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.stderr @@ -5,6 +5,9 @@ LL | evt.handle_event::<TestEvent, fn(TestEvent)>(|_evt| { | ^^^^^^^^^ ^^^^^^^^^^^^^ explicit generic argument not allowed | | | explicit generic argument not allowed + | + = note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information + = help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable error: aborting due to previous error diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.nll.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.nll.stderr deleted file mode 100644 index bfe656c7e2..0000000000 --- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.nll.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/ordinary-bounds-unrelated.rs:16:74 - | -LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> - | -- ^^^^^^^^^^^^^^^^^^ - | | - | hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here - | -help: to declare that the `impl Trait` captures 'b, you can add an explicit `'b` lifetime bound - | -LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> + 'b - | ++++ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr index a6bc8fec28..bfe656c7e2 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr @@ -2,13 +2,14 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea --> $DIR/ordinary-bounds-unrelated.rs:16:74 | LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> - | ^^^^^^^^^^^^^^^^^^ + | -- ^^^^^^^^^^^^^^^^^^ + | | + | hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here | -note: hidden type `Ordinary<'_>` captures lifetime smaller than the function body - --> $DIR/ordinary-bounds-unrelated.rs:16:74 +help: to declare that the `impl Trait` captures 'b, you can add an explicit `'b` lifetime bound | -LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> - | ^^^^^^^^^^^^^^^^^^ +LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> + 'b + | ++++ error: aborting due to previous error diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.nll.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.nll.stderr deleted file mode 100644 index 75c2dd8e9d..0000000000 --- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.nll.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/ordinary-bounds-unsuited.rs:18:62 - | -LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> - | -- ^^^^^^^^^^^^^^^^^^ - | | - | hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here - | -help: to declare that the `impl Trait` captures 'b, you can add an explicit `'b` lifetime bound - | -LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> + 'b - | ++++ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr index a219e74741..75c2dd8e9d 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr @@ -2,13 +2,14 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea --> $DIR/ordinary-bounds-unsuited.rs:18:62 | LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> - | ^^^^^^^^^^^^^^^^^^ + | -- ^^^^^^^^^^^^^^^^^^ + | | + | hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here | -note: hidden type `Ordinary<'_>` captures lifetime smaller than the function body - --> $DIR/ordinary-bounds-unsuited.rs:18:62 +help: to declare that the `impl Trait` captures 'b, you can add an explicit `'b` lifetime bound | -LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> - | ^^^^^^^^^^^^^^^^^^ +LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> + 'b + | ++++ error: aborting due to previous error diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr index 812093e6e7..eaf341248a 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr @@ -1,31 +1,31 @@ -error: lifetime may not live long enough +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds --> $DIR/must_outlive_least_region_or_bound.rs:3:23 | LL | fn elided(x: &i32) -> impl Copy { x } - | - ^^^^^^^^^ opaque type requires that `'1` must outlive `'static` + | ---- ^^^^^^^^^ | | - | let's call the lifetime of this reference `'1` + | hidden type `&i32` captures the anonymous lifetime defined here | -help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound +help: to declare that the `impl Trait` captures '_, you can add an explicit `'_` lifetime bound | LL | fn elided(x: &i32) -> impl Copy + '_ { x } | ++++ -error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:5:32 +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/must_outlive_least_region_or_bound.rs:6:32 | LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } - | -- ^^^^^^^^^ opaque type requires that `'a` must outlive `'static` + | -- ^^^^^^^^^ | | - | lifetime `'a` defined here + | hidden type `&'a i32` captures the lifetime `'a` as defined here | -help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a bound +help: to declare that the `impl Trait` captures 'a, you can add an explicit `'a` lifetime bound | LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } | ++++ error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:7:46 + --> $DIR/must_outlive_least_region_or_bound.rs:9:46 | LL | fn elided2(x: &i32) -> impl Copy + 'static { x } | - ^ returning this value requires that `'1` must outlive `'static` @@ -35,7 +35,7 @@ LL | fn elided2(x: &i32) -> impl Copy + 'static { x } = help: consider replacing `'1` with `'static` error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:9:55 + --> $DIR/must_outlive_least_region_or_bound.rs:11:55 | LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } | -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static` @@ -43,7 +43,7 @@ LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } = help: consider replacing `'a` with `'static` error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/must_outlive_least_region_or_bound.rs:11:41 + --> $DIR/must_outlive_least_region_or_bound.rs:13:41 | LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x } | ---- ^ lifetime `'a` required @@ -51,33 +51,36 @@ LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x } | help: add explicit lifetime `'a` to the type of `x`: `&'a i32` error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:22:24 + --> $DIR/must_outlive_least_region_or_bound.rs:24:55 | LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) } - | - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ opaque type requires that `'1` must outlive `'static` + | - ^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static` | | | let's call the lifetime of this reference `'1` error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:28:69 + --> $DIR/must_outlive_least_region_or_bound.rs:29:69 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static` | = help: consider replacing `'a` with `'static` -error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:32:61 +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/must_outlive_least_region_or_bound.rs:33:61 | LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) { - | -- -- lifetime `'b` defined here ^^^^^^^^^^^^^^^^ opaque type requires that `'b` must outlive `'a` - | | - | lifetime `'a` defined here + | -- ^^^^^^^^^^^^^^^^ + | | + | hidden type `[closure@$DIR/must_outlive_least_region_or_bound.rs:35:5: 35:31]` captures the lifetime `'b` as defined here + | +help: to declare that the `impl Trait` captures 'b, you can add an explicit `'b` lifetime bound | - = help: consider adding the following bound: `'b: 'a` +LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) + 'b { + | ++++ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:37:51 + --> $DIR/must_outlive_least_region_or_bound.rs:38:51 | LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static { | ^^^^^^^^^^^^^^^^^^^^ @@ -86,5 +89,5 @@ LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static { error: aborting due to 9 previous errors -Some errors have detailed explanations: E0310, E0621. +Some errors have detailed explanations: E0310, E0621, E0700. For more information about an error, try `rustc --explain E0310`. diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs index 51f488e45a..69d2843ff3 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs @@ -1,8 +1,10 @@ use std::fmt::Debug; -fn elided(x: &i32) -> impl Copy { x } //~ ERROR E0759 +fn elided(x: &i32) -> impl Copy { x } +//~^ ERROR: captures lifetime that does not appear in bounds -fn explicit<'a>(x: &'a i32) -> impl Copy { x } //~ ERROR E0759 +fn explicit<'a>(x: &'a i32) -> impl Copy { x } +//~^ ERROR: captures lifetime that does not appear in bounds fn elided2(x: &i32) -> impl Copy + 'static { x } //~ ERROR E0759 @@ -20,7 +22,6 @@ fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) } //~ ERROR E0759 fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) } //~ ERROR E0759 fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) } //~ ERROR E0759 -//~^ ERROR E0759 trait LifetimeTrait<'a> {} impl<'a> LifetimeTrait<'a> for &'a i32 {} @@ -30,7 +31,7 @@ fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } //~ ERRO // Tests that a closure type containing 'b cannot be returned from a type where // only 'a was expected. fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) { - //~^ ERROR lifetime mismatch + //~^ ERROR: captures lifetime that does not appear in bounds move |_| println!("{}", y) } diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index 81ba89b0e0..d65dea7adc 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -1,41 +1,31 @@ -error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement - --> $DIR/must_outlive_least_region_or_bound.rs:3:35 +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/must_outlive_least_region_or_bound.rs:3:23 | LL | fn elided(x: &i32) -> impl Copy { x } - | ---- ^ ...is captured here... + | ---- ^^^^^^^^^ | | - | this data with an anonymous lifetime `'_`... - | -note: ...and is required to live as long as `'static` here - --> $DIR/must_outlive_least_region_or_bound.rs:3:23 + | hidden type `&i32` captures the anonymous lifetime defined here | -LL | fn elided(x: &i32) -> impl Copy { x } - | ^^^^^^^^^ -help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'_` lifetime bound +help: to declare that the `impl Trait` captures '_, you can add an explicit `'_` lifetime bound | LL | fn elided(x: &i32) -> impl Copy + '_ { x } | ++++ -error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement - --> $DIR/must_outlive_least_region_or_bound.rs:5:44 +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/must_outlive_least_region_or_bound.rs:6:32 | LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } - | ------- ^ ...is captured here... - | | - | this data with lifetime `'a`... + | -- ^^^^^^^^^ + | | + | hidden type `&'a i32` captures the lifetime `'a` as defined here | -note: ...and is required to live as long as `'static` here - --> $DIR/must_outlive_least_region_or_bound.rs:5:32 - | -LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } - | ^^^^^^^^^ -help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'a` lifetime bound +help: to declare that the `impl Trait` captures 'a, you can add an explicit `'a` lifetime bound | LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } | ++++ error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement - --> $DIR/must_outlive_least_region_or_bound.rs:7:46 + --> $DIR/must_outlive_least_region_or_bound.rs:9:46 | LL | fn elided2(x: &i32) -> impl Copy + 'static { x } | ---- ^ ...is captured here... @@ -43,7 +33,7 @@ LL | fn elided2(x: &i32) -> impl Copy + 'static { x } | this data with an anonymous lifetime `'_`... | note: ...and is required to live as long as `'static` here - --> $DIR/must_outlive_least_region_or_bound.rs:7:24 + --> $DIR/must_outlive_least_region_or_bound.rs:9:24 | LL | fn elided2(x: &i32) -> impl Copy + 'static { x } | ^^^^^^^^^^^^^^^^^^^ @@ -57,7 +47,7 @@ LL | fn elided2(x: &'static i32) -> impl Copy + 'static { x } | ~~~~~~~~~~~~ error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement - --> $DIR/must_outlive_least_region_or_bound.rs:9:55 + --> $DIR/must_outlive_least_region_or_bound.rs:11:55 | LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } | ------- ^ ...is captured here... @@ -65,7 +55,7 @@ LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } | this data with lifetime `'a`... | note: ...and is required to live as long as `'static` here - --> $DIR/must_outlive_least_region_or_bound.rs:9:33 + --> $DIR/must_outlive_least_region_or_bound.rs:11:33 | LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } | ^^^^^^^^^^^^^^^^^^^ @@ -79,7 +69,7 @@ LL | fn explicit2<'a>(x: &'static i32) -> impl Copy + 'static { x } | ~~~~~~~~~~~~ error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/must_outlive_least_region_or_bound.rs:11:24 + --> $DIR/must_outlive_least_region_or_bound.rs:13:24 | LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x } | ---- ^^^^^^^^^^^^^^ lifetime `'a` required @@ -87,7 +77,7 @@ LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x } | help: add explicit lifetime `'a` to the type of `x`: `&'a i32` error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement - --> $DIR/must_outlive_least_region_or_bound.rs:22:65 + --> $DIR/must_outlive_least_region_or_bound.rs:24:65 | LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) } | ---- this data with an anonymous lifetime `'_`... ^ ...is captured here, requiring it to live as long as `'static` @@ -101,34 +91,14 @@ help: to declare that the `impl Trait` captures data from argument `x`, you can LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug + '_) { (Box::new(x), x) } | ++++ -error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement - --> $DIR/must_outlive_least_region_or_bound.rs:22:69 - | -LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) } - | ---- this data with an anonymous lifetime `'_`... ^ ...is captured here... - | -note: ...and is required to live as long as `'static` here - --> $DIR/must_outlive_least_region_or_bound.rs:22:41 - | -LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) } - | ^^^^^^^^^^ -help: to declare that the trait object captures data from argument `x`, you can add an explicit `'_` lifetime bound - | -LL | fn elided5(x: &i32) -> (Box<dyn Debug + '_>, impl Debug) { (Box::new(x), x) } - | ++++ -help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'_` lifetime bound - | -LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug + '_) { (Box::new(x), x) } - | ++++ - error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement - --> $DIR/must_outlive_least_region_or_bound.rs:28:69 + --> $DIR/must_outlive_least_region_or_bound.rs:29:69 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | ------- this data with lifetime `'a`... ^ ...is captured here... | note: ...and is required to live as long as `'static` here - --> $DIR/must_outlive_least_region_or_bound.rs:28:34 + --> $DIR/must_outlive_least_region_or_bound.rs:29:34 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -141,17 +111,21 @@ help: alternatively, add an explicit `'static` bound to this reference LL | fn with_bound<'a>(x: &'static i32) -> impl LifetimeTrait<'a> + 'static { x } | ~~~~~~~~~~~~ -error[E0623]: lifetime mismatch - --> $DIR/must_outlive_least_region_or_bound.rs:32:61 +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/must_outlive_least_region_or_bound.rs:33:61 | LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) { - | ------- ^^^^^^^^^^^^^^^^ - | | | - | | ...but data from `y` is returned here - | this parameter and the return type are declared with different lifetimes... + | -- ^^^^^^^^^^^^^^^^ + | | + | hidden type `[closure@$DIR/must_outlive_least_region_or_bound.rs:35:5: 35:31]` captures the lifetime `'b` as defined here + | +help: to declare that the `impl Trait` captures 'b, you can add an explicit `'b` lifetime bound + | +LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) + 'b { + | ++++ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:37:51 + --> $DIR/must_outlive_least_region_or_bound.rs:38:51 | LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static { | -- ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds @@ -159,7 +133,7 @@ LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static { | help: consider adding an explicit lifetime bound...: `T: 'static +` error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement - --> $DIR/must_outlive_least_region_or_bound.rs:14:50 + --> $DIR/must_outlive_least_region_or_bound.rs:16:50 | LL | fn elided3(x: &i32) -> Box<dyn Debug> { Box::new(x) } | ---- ^ ...is captured here, requiring it to live as long as `'static` @@ -172,7 +146,7 @@ LL | fn elided3(x: &i32) -> Box<dyn Debug + '_> { Box::new(x) } | ++++ error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement - --> $DIR/must_outlive_least_region_or_bound.rs:16:59 + --> $DIR/must_outlive_least_region_or_bound.rs:18:59 | LL | fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug> { Box::new(x) } | ------- ^ ...is captured here, requiring it to live as long as `'static` @@ -185,7 +159,7 @@ LL | fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug + 'a> { Box::new(x) } | ++++ error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement - --> $DIR/must_outlive_least_region_or_bound.rs:18:60 + --> $DIR/must_outlive_least_region_or_bound.rs:20:60 | LL | fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) } | ---- ^ ...is captured here, requiring it to live as long as `'static` @@ -202,7 +176,7 @@ LL | fn elided4(x: &'static i32) -> Box<dyn Debug + 'static> { Box::new(x) } | ~~~~~~~~~~~~ error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement - --> $DIR/must_outlive_least_region_or_bound.rs:20:69 + --> $DIR/must_outlive_least_region_or_bound.rs:22:69 | LL | fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) } | ------- this data with lifetime `'a`... ^ ...is captured here, requiring it to live as long as `'static` @@ -216,7 +190,7 @@ help: alternatively, add an explicit `'static` bound to this reference LL | fn explicit4<'a>(x: &'static i32) -> Box<dyn Debug + 'static> { Box::new(x) } | ~~~~~~~~~~~~ -error: aborting due to 14 previous errors +error: aborting due to 13 previous errors -Some errors have detailed explanations: E0310, E0621, E0623, E0759. +Some errors have detailed explanations: E0310, E0621, E0700, E0759. For more information about an error, try `rustc --explain E0310`. 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 30afc8646d..c8ebed3bfd 100644 --- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr +++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr @@ -9,12 +9,12 @@ help: the following traits are implemented but not in scope; perhaps add a `use` | LL | use foo::Bar; | +LL | use no_method_suggested_traits::Reexported; + | LL | use no_method_suggested_traits::foo::PubPub; | LL | use no_method_suggested_traits::qux::PrivPub; | -LL | use no_method_suggested_traits::Reexported; - | error[E0599]: no method named `method` found for struct `Rc<&mut Box<&u32>>` in the current scope --> $DIR/no-method-suggested-traits.rs:26:44 @@ -27,12 +27,12 @@ help: the following traits are implemented but not in scope; perhaps add a `use` | LL | use foo::Bar; | +LL | use no_method_suggested_traits::Reexported; + | LL | use no_method_suggested_traits::foo::PubPub; | LL | use no_method_suggested_traits::qux::PrivPub; | -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 diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr deleted file mode 100644 index a3aeff50ee..0000000000 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr +++ /dev/null @@ -1,28 +0,0 @@ -error: lifetime may not live long enough - --> $DIR/static-return-lifetime-infered.rs:6:35 - | -LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> { - | - ^^^^^^^^^^^^^^^^^^^^^^^ 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 iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ { - | ++++ - -error: lifetime may not live long enough - --> $DIR/static-return-lifetime-infered.rs:9:37 - | -LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> { - | -- ^^^^^^^^^^^^^^^^^^^^^^^ opaque type requires that `'a` must outlive `'static` - | | - | lifetime `'a` defined here - | -help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a bound - | -LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a { - | ++++ - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.rs b/src/test/ui/impl-trait/static-return-lifetime-infered.rs index 518c52f5de..d792c6eafb 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.rs +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.rs @@ -4,10 +4,14 @@ struct A { impl A { fn iter_values_anon(&self) -> impl Iterator<Item=u32> { - self.x.iter().map(|a| a.0) //~ ERROR E0759 + //~^ ERROR: captures lifetime that does not appear in bounds + //~| ERROR: captures lifetime that does not appear in bounds + self.x.iter().map(|a| a.0) } fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> { - self.x.iter().map(|a| a.0) //~ ERROR E0759 + //~^ ERROR: captures lifetime that does not appear in bounds + //~| ERROR: captures lifetime that does not appear in bounds + self.x.iter().map(|a| a.0) } } diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr index ebd0b6a128..0d68f8c825 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr @@ -1,43 +1,55 @@ -error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement - --> $DIR/static-return-lifetime-infered.rs:7:16 +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/static-return-lifetime-infered.rs:6:35 | LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> { - | ----- this data with an anonymous lifetime `'_`... -LL | self.x.iter().map(|a| a.0) - | ------ ^^^^ - | | - | ...is captured here... + | ----- ^^^^^^^^^^^^^^^^^^^^^^^ + | | + | hidden type `Map<std::slice::Iter<'_, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:9:27: 9:34]>` captures the anonymous lifetime defined here + | +help: to declare that the `impl Trait` captures '_, you can add an explicit `'_` lifetime bound | -note: ...and is required to live as long as `'static` here +LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ { + | ++++ + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds --> $DIR/static-return-lifetime-infered.rs:6:35 | LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> { - | ^^^^^^^^^^^^^^^^^^^^^^^ -help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound + | ----- ^^^^^^^^^^^^^^^^^^^^^^^ + | | + | hidden type `Map<std::slice::Iter<'_, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:9:27: 9:34]>` captures the anonymous lifetime defined here + | +help: to declare that the `impl Trait` captures '_, you can add an explicit `'_` lifetime bound | LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ { | ++++ -error[E0759]: `self` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement - --> $DIR/static-return-lifetime-infered.rs:10:16 +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/static-return-lifetime-infered.rs:11:37 | LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> { - | -------- this data with lifetime `'a`... -LL | self.x.iter().map(|a| a.0) - | ------ ^^^^ - | | - | ...is captured here... + | -- ^^^^^^^^^^^^^^^^^^^^^^^ + | | + | hidden type `Map<std::slice::Iter<'a, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:14:27: 14:34]>` captures the lifetime `'a` as defined here | -note: ...and is required to live as long as `'static` here - --> $DIR/static-return-lifetime-infered.rs:9:37 +help: to declare that the `impl Trait` captures 'a, you can add an explicit `'a` lifetime bound + | +LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a { + | ++++ + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/static-return-lifetime-infered.rs:11:37 | LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> { - | ^^^^^^^^^^^^^^^^^^^^^^^ -help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'a` lifetime bound + | -- ^^^^^^^^^^^^^^^^^^^^^^^ + | | + | hidden type `Map<std::slice::Iter<'a, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:14:27: 14:34]>` captures the lifetime `'a` as defined here + | +help: to declare that the `impl Trait` captures 'a, you can add an explicit `'a` lifetime bound | LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a { | ++++ -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0759`. +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/impl-trait/universal-two-impl-traits.stderr b/src/test/ui/impl-trait/universal-two-impl-traits.stderr index 7c120235fd..ab8a53d0db 100644 --- a/src/test/ui/impl-trait/universal-two-impl-traits.stderr +++ b/src/test/ui/impl-trait/universal-two-impl-traits.stderr @@ -6,6 +6,7 @@ LL | fn foo(x: impl Debug, y: impl Debug) -> String { | | | expected type parameter LL | let mut a = x; + | - expected due to this value LL | a = y; | ^ expected type parameter `impl Debug`, found a different type parameter `impl Debug` | diff --git a/src/test/ui/impl-trait/where-allowed.rs b/src/test/ui/impl-trait/where-allowed.rs index 4605e76ac9..35fb42d621 100644 --- a/src/test/ui/impl-trait/where-allowed.rs +++ b/src/test/ui/impl-trait/where-allowed.rs @@ -235,6 +235,7 @@ 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 method return types +//~| ERROR no nominal type found // Disallowed fn in_method_generic_param_default<T = impl Debug>(_: T) {} diff --git a/src/test/ui/impl-trait/where-allowed.stderr b/src/test/ui/impl-trait/where-allowed.stderr index 7f11d30dba..236cf449e8 100644 --- a/src/test/ui/impl-trait/where-allowed.stderr +++ b/src/test/ui/impl-trait/where-allowed.stderr @@ -272,19 +272,19 @@ LL | impl <T = impl Debug> T {} | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and method return types - --> $DIR/where-allowed.rs:240:40 + --> $DIR/where-allowed.rs:241:40 | LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {} | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and method return types - --> $DIR/where-allowed.rs:246:29 + --> $DIR/where-allowed.rs:247:29 | LL | let _in_local_variable: impl Fn() = || {}; | ^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and method return types - --> $DIR/where-allowed.rs:248:46 + --> $DIR/where-allowed.rs:249:46 | LL | let _in_return_in_local_variable = || -> impl Fn() { || {} }; | ^^^^^^^^^ @@ -300,7 +300,7 @@ LL | impl <T = impl Debug> T {} = 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 - --> $DIR/where-allowed.rs:240:36 + --> $DIR/where-allowed.rs:241:36 | LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {} | ^ @@ -308,7 +308,15 @@ LL | fn in_method_generic_param_default<T = impl Debug>(_: 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: aborting due to 48 previous errors +error[E0118]: no nominal type found for inherent implementation + --> $DIR/where-allowed.rs:234:23 + | +LL | impl <T = impl Debug> T {} + | ^ impl requires a nominal type + | + = note: either implement a trait on it or create a newtype to wrap it instead + +error: aborting due to 49 previous errors -Some errors have detailed explanations: E0562, E0658, E0666. -For more information about an error, try `rustc --explain E0562`. +Some errors have detailed explanations: E0118, E0562, E0658, E0666. +For more information about an error, try `rustc --explain E0118`. diff --git a/src/test/ui/absolute-paths-in-nested-use-groups.rs b/src/test/ui/imports/absolute-paths-in-nested-use-groups.rs similarity index 100% rename from src/test/ui/absolute-paths-in-nested-use-groups.rs rename to src/test/ui/imports/absolute-paths-in-nested-use-groups.rs diff --git a/src/test/ui/absolute-paths-in-nested-use-groups.stderr b/src/test/ui/imports/absolute-paths-in-nested-use-groups.stderr similarity index 100% rename from src/test/ui/absolute-paths-in-nested-use-groups.stderr rename to src/test/ui/imports/absolute-paths-in-nested-use-groups.stderr diff --git a/src/test/ui/imports/duplicate.stderr b/src/test/ui/imports/duplicate.stderr index 0dbcb5f1de..997a2741b3 100644 --- a/src/test/ui/imports/duplicate.stderr +++ b/src/test/ui/imports/duplicate.stderr @@ -8,12 +8,13 @@ LL | use a::foo; | = note: `foo` must be defined only once in the value namespace of this module -error[E0659]: `foo` is ambiguous (glob import vs glob import in the same module) +error[E0659]: `foo` is ambiguous --> $DIR/duplicate.rs:46:15 | LL | use self::foo::bar; | ^^^ ambiguous name | + = note: ambiguous because of multiple glob imports of a name in the same module note: `foo` could refer to the module imported here --> $DIR/duplicate.rs:43:9 | @@ -27,12 +28,13 @@ LL | use self::m2::*; | ^^^^^^^^^^^ = help: consider adding an explicit import of `foo` to disambiguate -error[E0659]: `foo` is ambiguous (glob import vs glob import in the same module) +error[E0659]: `foo` is ambiguous --> $DIR/duplicate.rs:35:8 | LL | f::foo(); | ^^^ ambiguous name | + = note: ambiguous because of multiple glob imports of a name in the same module note: `foo` could refer to the function imported here --> $DIR/duplicate.rs:24:13 | @@ -46,12 +48,13 @@ LL | pub use b::*; | ^^^^ = help: consider adding an explicit import of `foo` to disambiguate -error[E0659]: `foo` is ambiguous (glob import vs glob import in the same module) +error[E0659]: `foo` is ambiguous --> $DIR/duplicate.rs:49:9 | LL | foo::bar(); | ^^^ ambiguous name | + = note: ambiguous because of multiple glob imports of a name in the same module note: `foo` could refer to the module imported here --> $DIR/duplicate.rs:43:9 | diff --git a/src/test/ui/export-multi.rs b/src/test/ui/imports/export-multi.rs similarity index 100% rename from src/test/ui/export-multi.rs rename to src/test/ui/imports/export-multi.rs diff --git a/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr b/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr index 472824b84f..c31c884038 100644 --- a/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr +++ b/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr @@ -9,12 +9,13 @@ LL | define_other_core!(); | = note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0659]: `Vec` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) +error[E0659]: `Vec` is ambiguous --> $DIR/extern-prelude-extern-crate-restricted-shadowing.rs:13:9 | LL | Vec::panic!(); | ^^^ ambiguous name | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution note: `Vec` could refer to the crate imported here --> $DIR/extern-prelude-extern-crate-restricted-shadowing.rs:5:9 | diff --git a/src/test/ui/glob-cycles.rs b/src/test/ui/imports/glob-cycles.rs similarity index 100% rename from src/test/ui/glob-cycles.rs rename to src/test/ui/imports/glob-cycles.rs diff --git a/src/test/ui/imports/glob-shadowing.stderr b/src/test/ui/imports/glob-shadowing.stderr index 4ef446f93c..aff2eff68a 100644 --- a/src/test/ui/imports/glob-shadowing.stderr +++ b/src/test/ui/imports/glob-shadowing.stderr @@ -1,9 +1,10 @@ -error[E0659]: `env` is ambiguous (glob import vs any other name from outer scope during import/macro resolution) +error[E0659]: `env` is ambiguous --> $DIR/glob-shadowing.rs:11:17 | LL | let x = env!("PATH"); | ^^^ ambiguous name | + = note: ambiguous because of a conflict between a name from a glob import and an outer scope during import or macro resolution = note: `env` could refer to a macro from prelude note: `env` could also refer to the macro imported here --> $DIR/glob-shadowing.rs:9:9 @@ -13,12 +14,13 @@ LL | use m::*; = help: consider adding an explicit import of `env` to disambiguate = help: or use `self::env` to refer to this macro unambiguously -error[E0659]: `env` is ambiguous (glob import vs any other name from outer scope during import/macro resolution) +error[E0659]: `env` is ambiguous --> $DIR/glob-shadowing.rs:19:21 | LL | let x = env!("PATH"); | ^^^ ambiguous name | + = note: ambiguous because of a conflict between a name from a glob import and an outer scope during import or macro resolution = note: `env` could refer to a macro from prelude note: `env` could also refer to the macro imported here --> $DIR/glob-shadowing.rs:17:13 @@ -27,12 +29,13 @@ LL | use m::*; | ^^^^ = help: consider adding an explicit import of `env` to disambiguate -error[E0659]: `fenv` is ambiguous (glob import vs any other name from outer scope during import/macro resolution) +error[E0659]: `fenv` is ambiguous --> $DIR/glob-shadowing.rs:29:21 | LL | let x = fenv!(); | ^^^^ ambiguous name | + = note: ambiguous because of a conflict between a name from a glob import and an outer scope during import or macro resolution note: `fenv` could refer to the macro imported here --> $DIR/glob-shadowing.rs:27:13 | diff --git a/src/test/ui/imports/issue-53269.stderr b/src/test/ui/imports/issue-53269.stderr index bbec2aae82..a0e7bf8b61 100644 --- a/src/test/ui/imports/issue-53269.stderr +++ b/src/test/ui/imports/issue-53269.stderr @@ -4,12 +4,13 @@ error[E0432]: unresolved import `nonexistent_module` LL | use nonexistent_module::mac; | ^^^^^^^^^^^^^^^^^^ maybe a missing crate `nonexistent_module`? -error[E0659]: `mac` is ambiguous (`macro_rules` vs non-`macro_rules` from other module) +error[E0659]: `mac` is ambiguous --> $DIR/issue-53269.rs:8:5 | LL | mac!(); | ^^^ ambiguous name | + = note: ambiguous because of a conflict between a `macro_rules` name and a non-`macro_rules` name from another module note: `mac` could refer to the macro defined here --> $DIR/issue-53269.rs:3:1 | diff --git a/src/test/ui/imports/issue-55884-1.stderr b/src/test/ui/imports/issue-55884-1.stderr index a7a7cc8879..c38166ddea 100644 --- a/src/test/ui/imports/issue-55884-1.stderr +++ b/src/test/ui/imports/issue-55884-1.stderr @@ -1,9 +1,10 @@ -error[E0659]: `S` is ambiguous (glob import vs glob import in the same module) +error[E0659]: `S` is ambiguous --> $DIR/issue-55884-1.rs:19:12 | LL | use m::S; | ^ ambiguous name | + = note: ambiguous because of multiple glob imports of a name in the same module note: `S` could refer to the struct imported here --> $DIR/issue-55884-1.rs:14:13 | diff --git a/src/test/ui/imports/issue-56125.stderr b/src/test/ui/imports/issue-56125.stderr index d78cc52303..2e4ba86237 100644 --- a/src/test/ui/imports/issue-56125.stderr +++ b/src/test/ui/imports/issue-56125.stderr @@ -4,12 +4,13 @@ error[E0432]: unresolved import `empty::issue_56125` LL | use empty::issue_56125; | ^^^^^^^^^^^^^^^^^^ no `issue_56125` in `m3::empty` -error[E0659]: `issue_56125` is ambiguous (name vs any other name during import resolution) +error[E0659]: `issue_56125` is ambiguous --> $DIR/issue-56125.rs:6:9 | LL | use issue_56125::last_segment::*; | ^^^^^^^^^^^ ambiguous name | + = note: ambiguous because of multiple potential import sources = note: `issue_56125` could refer to a crate passed with `--extern` = help: use `::issue_56125` to refer to this crate unambiguously note: `issue_56125` could also refer to the module imported here @@ -19,12 +20,13 @@ LL | use issue_56125::last_segment::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: use `self::issue_56125` to refer to this module unambiguously -error[E0659]: `issue_56125` is ambiguous (name vs any other name during import resolution) +error[E0659]: `issue_56125` is ambiguous --> $DIR/issue-56125.rs:11:9 | LL | use issue_56125::non_last_segment::non_last_segment::*; | ^^^^^^^^^^^ ambiguous name | + = note: ambiguous because of multiple potential import sources = note: `issue_56125` could refer to a crate passed with `--extern` = help: use `::issue_56125` to refer to this crate unambiguously note: `issue_56125` could also refer to the module imported here @@ -34,12 +36,13 @@ LL | use issue_56125::non_last_segment::non_last_segment::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: use `self::issue_56125` to refer to this module unambiguously -error[E0659]: `issue_56125` is ambiguous (name vs any other name during import resolution) +error[E0659]: `issue_56125` is ambiguous --> $DIR/issue-56125.rs:18:9 | LL | use issue_56125::*; | ^^^^^^^^^^^ ambiguous name | + = note: ambiguous because of multiple potential import sources = note: `issue_56125` could refer to a crate passed with `--extern` = help: use `::issue_56125` to refer to this crate unambiguously note: `issue_56125` could also refer to the module imported here diff --git a/src/test/ui/imports/issue-57539.stderr b/src/test/ui/imports/issue-57539.stderr index 174088e8f6..1a3ca4edac 100644 --- a/src/test/ui/imports/issue-57539.stderr +++ b/src/test/ui/imports/issue-57539.stderr @@ -1,9 +1,10 @@ -error[E0659]: `core` is ambiguous (name vs any other name during import resolution) +error[E0659]: `core` is ambiguous --> $DIR/issue-57539.rs:4:9 | LL | use core; | ^^^^ ambiguous name | + = note: ambiguous because of multiple potential import sources = note: `core` could refer to a built-in crate = help: use `::core` to refer to this crate unambiguously note: `core` could also refer to the module imported here diff --git a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr index f809698fe1..c048d2ea20 100644 --- a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr +++ b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr @@ -1,9 +1,10 @@ -error[E0659]: `exported` is ambiguous (glob import vs macro-expanded name in the same module during import/macro resolution) +error[E0659]: `exported` is ambiguous --> $DIR/local-modularized-tricky-fail-1.rs:28:1 | LL | exported!(); | ^^^^^^^^ ambiguous name | + = note: ambiguous because of a conflict between a name from a glob import and a macro-expanded name in the same module during import or macro resolution note: `exported` could refer to the macro defined here --> $DIR/local-modularized-tricky-fail-1.rs:5:5 | @@ -22,12 +23,13 @@ LL | use inner1::*; = help: consider adding an explicit import of `exported` to disambiguate = note: this error originates in the macro `define_exported` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0659]: `exported` is ambiguous (glob import vs macro-expanded name in the same module during import/macro resolution) +error[E0659]: `exported` is ambiguous --> $DIR/local-modularized-tricky-fail-1.rs:28:1 | LL | exported!(); | ^^^^^^^^ ambiguous name | + = note: ambiguous because of a conflict between a name from a glob import and a macro-expanded name in the same module during import or macro resolution note: `exported` could refer to the macro defined here --> $DIR/local-modularized-tricky-fail-1.rs:5:5 | @@ -46,12 +48,13 @@ LL | use inner1::*; = help: consider adding an explicit import of `exported` to disambiguate = note: this error originates in the macro `define_exported` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0659]: `panic` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) +error[E0659]: `panic` is ambiguous --> $DIR/local-modularized-tricky-fail-1.rs:36:5 | LL | panic!(); | ^^^^^ ambiguous name | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution = note: `panic` could refer to a macro from prelude note: `panic` could also refer to the macro defined here --> $DIR/local-modularized-tricky-fail-1.rs:11:5 @@ -66,12 +69,13 @@ LL | define_panic!(); = help: use `crate::panic` to refer to this macro unambiguously = note: this error originates in the macro `define_panic` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0659]: `include` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) +error[E0659]: `include` is ambiguous --> $DIR/local-modularized-tricky-fail-1.rs:47:1 | LL | include!(); | ^^^^^^^ ambiguous name | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution = note: `include` could refer to a macro from prelude note: `include` could also refer to the macro defined here --> $DIR/local-modularized-tricky-fail-1.rs:17:5 diff --git a/src/test/ui/imports/macro-paths.stderr b/src/test/ui/imports/macro-paths.stderr index a5b9000827..5f113ce2be 100644 --- a/src/test/ui/imports/macro-paths.stderr +++ b/src/test/ui/imports/macro-paths.stderr @@ -1,9 +1,10 @@ -error[E0659]: `bar` is ambiguous (glob import vs macro-expanded name in the same module during import/macro resolution) +error[E0659]: `bar` is ambiguous --> $DIR/macro-paths.rs:13:5 | LL | bar::m! { | ^^^ ambiguous name | + = note: ambiguous because of a conflict between a name from a glob import and a macro-expanded name in the same module during import or macro resolution note: `bar` could refer to the module defined here --> $DIR/macro-paths.rs:14:9 | @@ -16,12 +17,13 @@ LL | use foo::*; | ^^^^^^ = help: consider adding an explicit import of `bar` to disambiguate -error[E0659]: `baz` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) +error[E0659]: `baz` is ambiguous --> $DIR/macro-paths.rs:23:5 | LL | baz::m! { | ^^^ ambiguous name | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution note: `baz` could refer to the module defined here --> $DIR/macro-paths.rs:24:9 | diff --git a/src/test/ui/imports/macros.stderr b/src/test/ui/imports/macros.stderr index 27b34fe0c0..110548d1d6 100644 --- a/src/test/ui/imports/macros.stderr +++ b/src/test/ui/imports/macros.stderr @@ -1,9 +1,10 @@ -error[E0659]: `m` is ambiguous (glob import vs macro-expanded name in the same module during import/macro resolution) +error[E0659]: `m` is ambiguous --> $DIR/macros.rs:16:5 | LL | m! { | ^ ambiguous name | + = note: ambiguous because of a conflict between a name from a glob import and a macro-expanded name in the same module during import or macro resolution note: `m` could refer to the macro imported here --> $DIR/macros.rs:18:13 | @@ -16,12 +17,13 @@ LL | use two_macros::*; | ^^^^^^^^^^^^^ = help: consider adding an explicit import of `m` to disambiguate -error[E0659]: `m` is ambiguous (glob import vs macro-expanded name in the same module during import/macro resolution) +error[E0659]: `m` is ambiguous --> $DIR/macros.rs:16:5 | LL | m! { | ^ ambiguous name | + = note: ambiguous because of a conflict between a name from a glob import and a macro-expanded name in the same module during import or macro resolution note: `m` could refer to the macro imported here --> $DIR/macros.rs:18:13 | @@ -34,12 +36,13 @@ LL | use two_macros::*; | ^^^^^^^^^^^^^ = help: consider adding an explicit import of `m` to disambiguate -error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) +error[E0659]: `m` is ambiguous --> $DIR/macros.rs:30:9 | LL | m! { | ^ ambiguous name | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution note: `m` could refer to the macro imported here --> $DIR/macros.rs:31:17 | diff --git a/src/test/ui/no-std-inject.rs b/src/test/ui/imports/no-std-inject.rs similarity index 100% rename from src/test/ui/no-std-inject.rs rename to src/test/ui/imports/no-std-inject.rs diff --git a/src/test/ui/no-std-inject.stderr b/src/test/ui/imports/no-std-inject.stderr similarity index 100% rename from src/test/ui/no-std-inject.stderr rename to src/test/ui/imports/no-std-inject.stderr diff --git a/src/test/ui/reexport-star.rs b/src/test/ui/imports/reexport-star.rs similarity index 100% rename from src/test/ui/reexport-star.rs rename to src/test/ui/imports/reexport-star.rs diff --git a/src/test/ui/imports/rfc-1560-warning-cycle.stderr b/src/test/ui/imports/rfc-1560-warning-cycle.stderr index d79c719d82..fd7e99165b 100644 --- a/src/test/ui/imports/rfc-1560-warning-cycle.stderr +++ b/src/test/ui/imports/rfc-1560-warning-cycle.stderr @@ -1,9 +1,10 @@ -error[E0659]: `Foo` is ambiguous (glob import vs glob import in the same module) +error[E0659]: `Foo` is ambiguous --> $DIR/rfc-1560-warning-cycle.rs:9:17 | LL | fn f(_: Foo) {} | ^^^ ambiguous name | + = note: ambiguous because of multiple glob imports of a name in the same module note: `Foo` could refer to the struct imported here --> $DIR/rfc-1560-warning-cycle.rs:7:13 | diff --git a/src/test/ui/imports/shadow_builtin_macros.stderr b/src/test/ui/imports/shadow_builtin_macros.stderr index 2fcbb2a045..6ffb31c20e 100644 --- a/src/test/ui/imports/shadow_builtin_macros.stderr +++ b/src/test/ui/imports/shadow_builtin_macros.stderr @@ -1,9 +1,10 @@ -error[E0659]: `panic` is ambiguous (glob import vs any other name from outer scope during import/macro resolution) +error[E0659]: `panic` is ambiguous --> $DIR/shadow_builtin_macros.rs:15:14 | LL | fn f() { panic!(); } | ^^^^^ ambiguous name | + = note: ambiguous because of a conflict between a name from a glob import and an outer scope during import or macro resolution = note: `panic` could refer to a macro from prelude note: `panic` could also refer to the macro imported here --> $DIR/shadow_builtin_macros.rs:14:9 @@ -13,12 +14,13 @@ LL | use foo::*; = help: consider adding an explicit import of `panic` to disambiguate = help: or use `self::panic` to refer to this macro unambiguously -error[E0659]: `panic` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) +error[E0659]: `panic` is ambiguous --> $DIR/shadow_builtin_macros.rs:33:5 | LL | panic!(); | ^^^^^ ambiguous name | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution = note: `panic` could refer to a macro from prelude note: `panic` could also refer to the macro defined here --> $DIR/shadow_builtin_macros.rs:30:9 @@ -30,12 +32,13 @@ LL | m!(); | ---- in this macro invocation = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0659]: `n` is ambiguous (glob import vs any other name from outer scope during import/macro resolution) +error[E0659]: `n` is ambiguous --> $DIR/shadow_builtin_macros.rs:49:5 | LL | n!(); | ^ ambiguous name | + = note: ambiguous because of a conflict between a name from a glob import and an outer scope during import or macro resolution note: `n` could refer to the macro imported here --> $DIR/shadow_builtin_macros.rs:48:9 | @@ -49,12 +52,13 @@ note: `n` could also refer to the macro imported here LL | #[macro_use(n)] | ^ -error[E0659]: `panic` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) +error[E0659]: `panic` is ambiguous --> $DIR/shadow_builtin_macros.rs:20:14 | LL | fn f() { panic!(); } | ^^^^^ ambiguous name | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution = note: `panic` could refer to a macro from prelude note: `panic` could also refer to the macro imported here --> $DIR/shadow_builtin_macros.rs:19:26 diff --git a/src/test/ui/use-mod.rs b/src/test/ui/imports/use-mod.rs similarity index 100% rename from src/test/ui/use-mod.rs rename to src/test/ui/imports/use-mod.rs diff --git a/src/test/ui/in-band-lifetimes.rs b/src/test/ui/in-band-lifetimes/in-band-lifetimes.rs similarity index 100% rename from src/test/ui/in-band-lifetimes.rs rename to src/test/ui/in-band-lifetimes/in-band-lifetimes.rs diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr index b15efd6c77..0546b6b51b 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr @@ -2,15 +2,15 @@ error: `impl` item signature doesn't match `trait` item signature --> $DIR/mismatched_trait_impl-2.rs:8:5 | LL | fn deref(&self) -> &dyn Trait { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&Struct) -> &dyn Trait` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 Struct) -> &'1 (dyn Trait + '1)` | ::: $SRC_DIR/core/src/ops/deref.rs:LL:COL | LL | fn deref(&self) -> &Self::Target; - | --------------------------------- expected `fn(&Struct) -> &(dyn Trait + 'static)` + | --------------------------------- expected `fn(&'1 Struct) -> &'1 (dyn Trait + 'static)` | - = note: expected `fn(&Struct) -> &(dyn Trait + 'static)` - found `fn(&Struct) -> &dyn Trait` + = note: expected `fn(&'1 Struct) -> &'1 (dyn Trait + 'static)` + found `fn(&'1 Struct) -> &'1 (dyn Trait + '1)` = 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 diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr index 149c2aeb95..c7a90c57ad 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr @@ -2,13 +2,13 @@ error: `impl` item signature doesn't match `trait` item signature --> $DIR/mismatched_trait_impl.rs:9:5 | LL | fn foo(&self, x: &'a u32, y: &u32) -> &'a u32; - | ---------------------------------------------- expected `fn(&i32, &'a u32, &u32) -> &'a u32` + | ---------------------------------------------- expected `fn(&'1 i32, &'a u32, &'2 u32) -> &'a u32` ... LL | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&i32, &u32, &u32) -> &u32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 i32, &'2 u32, &'3 u32) -> &'3 u32` | - = note: expected `fn(&i32, &'a u32, &u32) -> &'a u32` - found `fn(&i32, &u32, &u32) -> &u32` + = note: expected `fn(&'1 i32, &'a u32, &'2 u32) -> &'a u32` + found `fn(&'1 i32, &'2 u32, &'3 u32) -> &'3 u32` = 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 diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr index 9a0bd82785..84e5339122 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr @@ -2,13 +2,13 @@ error: `impl` item signature doesn't match `trait` item signature --> $DIR/mismatched_trait_impl.rs:9:5 | LL | fn foo(&self, x: &'a u32, y: &u32) -> &'a u32; - | ---------------------------------------------- expected `fn(&i32, &'a u32, &u32) -> &'a u32` + | ---------------------------------------------- expected `fn(&'1 i32, &'a u32, &'2 u32) -> &'a u32` ... LL | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&i32, &u32, &u32) -> &u32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 i32, &'2 u32, &'3 u32) -> &'3 u32` | - = note: expected `fn(&i32, &'a u32, &u32) -> &'a u32` - found `fn(&i32, &u32, &u32) -> &u32` + = note: expected `fn(&'1 i32, &'a u32, &'2 u32) -> &'a u32` + found `fn(&'1 i32, &'2 u32, &'3 u32) -> &'3 u32` = 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 diff --git a/src/test/ui/inference/auxiliary/inference_unstable_iterator.rs b/src/test/ui/inference/auxiliary/inference_unstable_iterator.rs index 91fc398f74..04bc0b1a8a 100644 --- a/src/test/ui/inference/auxiliary/inference_unstable_iterator.rs +++ b/src/test/ui/inference/auxiliary/inference_unstable_iterator.rs @@ -1,4 +1,5 @@ #![feature(staged_api)] +#![feature(arbitrary_self_types)] #![stable(feature = "ipu_iterator", since = "1.0.0")] @@ -8,6 +9,22 @@ pub trait IpuIterator { fn ipu_flatten(&self) -> u32 { 0 } + + #[unstable(feature = "ipu_flatten", issue = "99999")] + fn ipu_by_value_vs_by_ref(self) -> u32 where Self: Sized { + 0 + } + + #[unstable(feature = "ipu_flatten", issue = "99999")] + fn ipu_by_ref_vs_by_ref_mut(&self) -> u32 { + 0 + } + + #[unstable(feature = "ipu_flatten", issue = "99999")] + fn ipu_by_mut_ptr_vs_by_const_ptr(self: *mut Self) -> u32 { + 0 + } + #[unstable(feature = "assoc_const_ipu_iter", issue = "99999")] const C: i32; } diff --git a/src/test/ui/inference/auxiliary/inference_unstable_itertools.rs b/src/test/ui/inference/auxiliary/inference_unstable_itertools.rs index e00adda5c3..fa1efbcfef 100644 --- a/src/test/ui/inference/auxiliary/inference_unstable_itertools.rs +++ b/src/test/ui/inference/auxiliary/inference_unstable_itertools.rs @@ -1,8 +1,22 @@ +#![feature(arbitrary_self_types)] + pub trait IpuItertools { fn ipu_flatten(&self) -> u32 { 1 } + fn ipu_by_value_vs_by_ref(&self) -> u32 { + 1 + } + + fn ipu_by_ref_vs_by_ref_mut(&mut self) -> u32 { + 1 + } + + fn ipu_by_mut_ptr_vs_by_const_ptr(self: *const Self) -> u32 { + 1 + } + const C: i32; } diff --git a/src/test/ui/inference/inference_unstable.rs b/src/test/ui/inference/inference_unstable.rs index 86bb62b8a5..daf0cf042c 100644 --- a/src/test/ui/inference/inference_unstable.rs +++ b/src/test/ui/inference/inference_unstable.rs @@ -15,6 +15,15 @@ use inference_unstable_itertools::IpuItertools; fn main() { assert_eq!('x'.ipu_flatten(), 1); //~^ WARN an associated function with this name may be added to the standard library in the future +//~| WARN once this associated item is added to the standard library, the ambiguity may cause an + assert_eq!('x'.ipu_by_value_vs_by_ref(), 1); +//~^ WARN an associated function with this name may be added to the standard library in the future +//~| WARN once this associated item is added to the standard library, the ambiguity may cause an + assert_eq!('x'.ipu_by_ref_vs_by_ref_mut(), 1); +//~^ WARN an associated function with this name may be added to the standard library in the future +//~| WARN once this associated item is added to the standard library, the ambiguity may cause an + assert_eq!((&mut 'x' as *mut char).ipu_by_mut_ptr_vs_by_const_ptr(), 1); +//~^ WARN an associated function with this name may be added to the standard library in the future //~| WARN once this associated item is added to the standard library, the ambiguity may cause an assert_eq!(char::C, 1); //~^ WARN an associated constant with this name may be added to the standard library in the future diff --git a/src/test/ui/inference/inference_unstable.stderr b/src/test/ui/inference/inference_unstable.stderr index 2c282e610b..df7a09686b 100644 --- a/src/test/ui/inference/inference_unstable.stderr +++ b/src/test/ui/inference/inference_unstable.stderr @@ -10,8 +10,41 @@ LL | assert_eq!('x'.ipu_flatten(), 1); = help: call with fully qualified syntax `inference_unstable_itertools::IpuItertools::ipu_flatten(...)` to keep using the current method = help: add `#![feature(ipu_flatten)]` to the crate attributes to enable `inference_unstable_iterator::IpuIterator::ipu_flatten` +warning: an associated function with this name may be added to the standard library in the future + --> $DIR/inference_unstable.rs:19:20 + | +LL | assert_eq!('x'.ipu_by_value_vs_by_ref(), 1); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: once this associated item is added to the standard library, the ambiguity may cause an error or change in behavior! + = note: for more information, see issue #48919 <https://github.com/rust-lang/rust/issues/48919> + = help: call with fully qualified syntax `inference_unstable_itertools::IpuItertools::ipu_by_value_vs_by_ref(...)` to keep using the current method + = help: add `#![feature(ipu_flatten)]` to the crate attributes to enable `inference_unstable_iterator::IpuIterator::ipu_by_value_vs_by_ref` + +warning: an associated function with this name may be added to the standard library in the future + --> $DIR/inference_unstable.rs:22:20 + | +LL | assert_eq!('x'.ipu_by_ref_vs_by_ref_mut(), 1); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: once this associated item is added to the standard library, the ambiguity may cause an error or change in behavior! + = note: for more information, see issue #48919 <https://github.com/rust-lang/rust/issues/48919> + = help: call with fully qualified syntax `inference_unstable_itertools::IpuItertools::ipu_by_ref_vs_by_ref_mut(...)` to keep using the current method + = help: add `#![feature(ipu_flatten)]` to the crate attributes to enable `inference_unstable_iterator::IpuIterator::ipu_by_ref_vs_by_ref_mut` + +warning: an associated function with this name may be added to the standard library in the future + --> $DIR/inference_unstable.rs:25:40 + | +LL | assert_eq!((&mut 'x' as *mut char).ipu_by_mut_ptr_vs_by_const_ptr(), 1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: once this associated item is added to the standard library, the ambiguity may cause an error or change in behavior! + = note: for more information, see issue #48919 <https://github.com/rust-lang/rust/issues/48919> + = help: call with fully qualified syntax `inference_unstable_itertools::IpuItertools::ipu_by_mut_ptr_vs_by_const_ptr(...)` to keep using the current method + = help: add `#![feature(ipu_flatten)]` to the crate attributes to enable `inference_unstable_iterator::IpuIterator::ipu_by_mut_ptr_vs_by_const_ptr` + warning: an associated constant with this name may be added to the standard library in the future - --> $DIR/inference_unstable.rs:19:16 + --> $DIR/inference_unstable.rs:28:16 | LL | assert_eq!(char::C, 1); | ^^^^^^^ help: use the fully qualified path to the associated const: `<char as IpuItertools>::C` @@ -20,5 +53,5 @@ LL | assert_eq!(char::C, 1); = note: for more information, see issue #48919 <https://github.com/rust-lang/rust/issues/48919> = help: add `#![feature(assoc_const_ipu_iter)]` to the crate attributes to enable `inference_unstable_iterator::IpuIterator::C` -warning: 2 warnings emitted +warning: 5 warnings emitted diff --git a/src/test/ui/inference/issue-71732.stderr b/src/test/ui/inference/issue-71732.stderr index 17fad57138..0369196c91 100644 --- a/src/test/ui/inference/issue-71732.stderr +++ b/src/test/ui/inference/issue-71732.stderr @@ -6,7 +6,19 @@ LL | .get(&"key".into()) | | | cannot infer type for type parameter `Q` declared on the associated function `get` | - = note: cannot satisfy `String: Borrow<_>` + = note: multiple `impl`s satisfying `String: Borrow<_>` found in the following crates: `alloc`, `core`: + - impl Borrow<str> for String; + - impl<T> Borrow<T> for T + where T: ?Sized; +note: required by a bound in `HashMap::<K, V, S>::get` + --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL + | +LL | K: Borrow<Q>, + | ^^^^^^^^^ required by this bound in `HashMap::<K, V, S>::get` +help: consider specifying the type argument in the function call + | +LL | .get::<Q>(&"key".into()) + | +++++ error: aborting due to previous error diff --git a/src/test/ui/inference/issue-72616.stderr b/src/test/ui/inference/issue-72616.stderr index 3c9d864c42..0077c73474 100644 --- a/src/test/ui/inference/issue-72616.stderr +++ b/src/test/ui/inference/issue-72616.stderr @@ -6,7 +6,11 @@ LL | if String::from("a") == "a".try_into().unwrap() {} | | | cannot infer type | - = note: cannot satisfy `String: PartialEq<_>` + = note: multiple `impl`s satisfying `String: PartialEq<_>` found in the `alloc` crate: + - impl PartialEq for String; + - impl<'a, 'b> PartialEq<&'a str> for String; + - impl<'a, 'b> PartialEq<Cow<'a, str>> for String; + - impl<'a, 'b> PartialEq<str> for String; error: aborting due to previous error diff --git a/src/test/ui/lub-glb-with-unbound-infer-var.rs b/src/test/ui/inference/lub-glb-with-unbound-infer-var.rs similarity index 100% rename from src/test/ui/lub-glb-with-unbound-infer-var.rs rename to src/test/ui/inference/lub-glb-with-unbound-infer-var.rs diff --git a/src/test/ui/newlambdas-ret-infer.rs b/src/test/ui/inference/newlambdas-ret-infer.rs similarity index 100% rename from src/test/ui/newlambdas-ret-infer.rs rename to src/test/ui/inference/newlambdas-ret-infer.rs diff --git a/src/test/ui/newlambdas-ret-infer2.rs b/src/test/ui/inference/newlambdas-ret-infer2.rs similarity index 100% rename from src/test/ui/newlambdas-ret-infer2.rs rename to src/test/ui/inference/newlambdas-ret-infer2.rs diff --git a/src/test/ui/question-mark-type-infer.rs b/src/test/ui/inference/question-mark-type-infer.rs similarity index 100% rename from src/test/ui/question-mark-type-infer.rs rename to src/test/ui/inference/question-mark-type-infer.rs diff --git a/src/test/ui/question-mark-type-infer.stderr b/src/test/ui/inference/question-mark-type-infer.stderr similarity index 100% rename from src/test/ui/question-mark-type-infer.stderr rename to src/test/ui/inference/question-mark-type-infer.stderr diff --git a/src/test/ui/range-type-infer.rs b/src/test/ui/inference/range-type-infer.rs similarity index 100% rename from src/test/ui/range-type-infer.rs rename to src/test/ui/inference/range-type-infer.rs diff --git a/src/test/ui/simple-infer.rs b/src/test/ui/inference/simple-infer.rs similarity index 100% rename from src/test/ui/simple-infer.rs rename to src/test/ui/inference/simple-infer.rs diff --git a/src/test/ui/tutorial-suffix-inference-test.rs b/src/test/ui/inference/tutorial-suffix-inference-test.rs similarity index 100% rename from src/test/ui/tutorial-suffix-inference-test.rs rename to src/test/ui/inference/tutorial-suffix-inference-test.rs diff --git a/src/test/ui/tutorial-suffix-inference-test.stderr b/src/test/ui/inference/tutorial-suffix-inference-test.stderr similarity index 100% rename from src/test/ui/tutorial-suffix-inference-test.stderr rename to src/test/ui/inference/tutorial-suffix-inference-test.stderr diff --git a/src/test/ui/type-infer-generalize-ty-var.rs b/src/test/ui/inference/type-infer-generalize-ty-var.rs similarity index 100% rename from src/test/ui/type-infer-generalize-ty-var.rs rename to src/test/ui/inference/type-infer-generalize-ty-var.rs diff --git a/src/test/ui/inline-const/const-expr-array-init.rs b/src/test/ui/inline-const/const-expr-array-init.rs index 8bb5dab1fa..8a92cdbc0f 100644 --- a/src/test/ui/inline-const/const-expr-array-init.rs +++ b/src/test/ui/inline-const/const-expr-array-init.rs @@ -1,6 +1,5 @@ // build-pass -#![allow(incomplete_features)] #![feature(inline_const)] use std::cell::Cell; diff --git a/src/test/ui/inline-const/const-expr-basic.rs b/src/test/ui/inline-const/const-expr-basic.rs index 9254c96a1e..dac46fe25e 100644 --- a/src/test/ui/inline-const/const-expr-basic.rs +++ b/src/test/ui/inline-const/const-expr-basic.rs @@ -1,7 +1,7 @@ // run-pass -#![allow(incomplete_features)] #![feature(inline_const)] + fn foo() -> i32 { const { let x = 5 + 10; diff --git a/src/test/ui/inline-const/const-expr-inference.rs b/src/test/ui/inline-const/const-expr-inference.rs new file mode 100644 index 0000000000..0d5892a74d --- /dev/null +++ b/src/test/ui/inline-const/const-expr-inference.rs @@ -0,0 +1,11 @@ +// check-pass + +#![feature(inline_const)] + +pub fn todo<T>() -> T { + const { todo!() } +} + +fn main() { + let _: usize = const { 0 }; +} diff --git a/src/test/ui/inline-const/const-expr-lifetime-err.rs b/src/test/ui/inline-const/const-expr-lifetime-err.rs new file mode 100644 index 0000000000..0a032a7338 --- /dev/null +++ b/src/test/ui/inline-const/const-expr-lifetime-err.rs @@ -0,0 +1,29 @@ +#![feature(const_mut_refs)] +#![feature(inline_const)] + +use std::marker::PhantomData; + +#[derive(PartialEq, Eq)] +pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>); + +impl<'a, T: ?Sized> InvariantRef<'a, T> { + pub const fn new(r: &'a T) -> Self { + InvariantRef(r, PhantomData) + } +} + +impl<'a> InvariantRef<'a, ()> { + pub const NEW: Self = InvariantRef::new(&()); +} + +fn equate<T>(x: T, y: T){} + +fn foo<'a>() { + let y = (); + equate(InvariantRef::new(&y), const { InvariantRef::<'a>::NEW }); + //~^ ERROR `y` does not live long enough [E0597] +} + +fn main() { + foo(); +} diff --git a/src/test/ui/inline-const/const-expr-lifetime-err.stderr b/src/test/ui/inline-const/const-expr-lifetime-err.stderr new file mode 100644 index 0000000000..a23f7c9a79 --- /dev/null +++ b/src/test/ui/inline-const/const-expr-lifetime-err.stderr @@ -0,0 +1,18 @@ +error[E0597]: `y` does not live long enough + --> $DIR/const-expr-lifetime-err.rs:23:30 + | +LL | fn foo<'a>() { + | -- lifetime `'a` defined here +LL | let y = (); +LL | equate(InvariantRef::new(&y), const { InvariantRef::<'a>::NEW }); + | ------------------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `y` is borrowed for `'a` +LL | +LL | } + | - `y` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/inline-const/const-expr-lifetime.rs b/src/test/ui/inline-const/const-expr-lifetime.rs new file mode 100644 index 0000000000..d883deb284 --- /dev/null +++ b/src/test/ui/inline-const/const-expr-lifetime.rs @@ -0,0 +1,35 @@ +// run-pass + +#![feature(const_mut_refs)] +#![feature(inline_const)] + +use std::marker::PhantomData; + +// rust-lang/rust#78174: ICE: "cannot convert ReErased to a region vid" +fn issue_78174() { + let foo = const { "foo" }; + assert_eq!(foo, "foo"); +} + +pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>); + +impl<'a, T: ?Sized> InvariantRef<'a, T> { + pub const fn new(r: &'a T) -> Self { + InvariantRef(r, PhantomData) + } +} + +fn get_invariant_ref<'a>() -> InvariantRef<'a, ()> { + const { InvariantRef::<'a, ()>::new(&()) } +} + +fn get_invariant_ref2<'a>() -> InvariantRef<'a, ()> { + // Try some type inference + const { InvariantRef::new(&()) } +} + +fn main() { + issue_78174(); + get_invariant_ref(); + get_invariant_ref2(); +} diff --git a/src/test/ui/inline-const/const-expr-macro.rs b/src/test/ui/inline-const/const-expr-macro.rs index 66b5857175..041f3e15a2 100644 --- a/src/test/ui/inline-const/const-expr-macro.rs +++ b/src/test/ui/inline-const/const-expr-macro.rs @@ -1,7 +1,7 @@ // run-pass -#![allow(incomplete_features)] #![feature(inline_const)] + macro_rules! do_const_block{ ($val:block) => { const $val } } diff --git a/src/test/ui/inline-const/const-expr-reference.rs b/src/test/ui/inline-const/const-expr-reference.rs index 747f14e4bd..a54d879f69 100644 --- a/src/test/ui/inline-const/const-expr-reference.rs +++ b/src/test/ui/inline-const/const-expr-reference.rs @@ -1,6 +1,5 @@ // run-pass -#![allow(incomplete_features)] #![feature(inline_const)] const fn bar() -> i32 { diff --git a/src/test/ui/inline-const/const-match-pat-generic.rs b/src/test/ui/inline-const/const-match-pat-generic.rs index 61680d653d..4486411698 100644 --- a/src/test/ui/inline-const/const-match-pat-generic.rs +++ b/src/test/ui/inline-const/const-match-pat-generic.rs @@ -1,5 +1,5 @@ #![allow(incomplete_features)] -#![feature(inline_const)] +#![feature(inline_const_pat)] // rust-lang/rust#82518: ICE with inline-const in match referencing const-generic parameter diff --git a/src/test/ui/inline-const/const-match-pat-inference.rs b/src/test/ui/inline-const/const-match-pat-inference.rs new file mode 100644 index 0000000000..d83ae6e983 --- /dev/null +++ b/src/test/ui/inline-const/const-match-pat-inference.rs @@ -0,0 +1,12 @@ +// check-pass + +#![feature(inline_const_pat)] +#![allow(incomplete_features)] + +fn main() { + match 1u64 { + 0 => (), + const { 0 + 1 } => (), + const { 2 - 1 } ..= const { u64::MAX } => (), + } +} diff --git a/src/test/ui/inline-const/const-match-pat-lifetime-err.rs b/src/test/ui/inline-const/const-match-pat-lifetime-err.rs new file mode 100644 index 0000000000..436b8037f3 --- /dev/null +++ b/src/test/ui/inline-const/const-match-pat-lifetime-err.rs @@ -0,0 +1,34 @@ +// ignore-test + +#![allow(incomplete_features)] +#![feature(const_mut_refs)] +#![feature(inline_const_pat)] + +use std::marker::PhantomData; + +#[derive(PartialEq, Eq)] +pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>); + +impl<'a, T: ?Sized> InvariantRef<'a, T> { + pub const fn new(r: &'a T) -> Self { + InvariantRef(r, PhantomData) + } +} + +impl<'a> InvariantRef<'a, ()> { + pub const NEW: Self = InvariantRef::new(&()); +} + +fn match_invariant_ref<'a>() { + let y = (); + match InvariantRef::new(&y) { + //~^ ERROR `y` does not live long enough [E0597] + // FIXME(nbdd0121): This should give the same error as `InvariantRef::<'a>::NEW` (without + // const block) + const { InvariantRef::<'a>::NEW } => (), + } +} + +fn main() { + match_invariant_ref(); +} diff --git a/src/test/ui/inline-const/const-match-pat-lifetime.rs b/src/test/ui/inline-const/const-match-pat-lifetime.rs new file mode 100644 index 0000000000..6d943bbcc0 --- /dev/null +++ b/src/test/ui/inline-const/const-match-pat-lifetime.rs @@ -0,0 +1,37 @@ +// run-pass + +#![allow(incomplete_features)] +#![feature(const_mut_refs)] +#![feature(inline_const)] +#![feature(inline_const_pat)] + +use std::marker::PhantomData; + +// rust-lang/rust#78174: ICE: "cannot convert ReErased to a region vid" +fn issue_78174() { + match "foo" { + const { concat!("fo", "o") } => (), + _ => unreachable!(), + } +} + +#[derive(PartialEq, Eq)] +pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>); + +impl<'a, T: ?Sized> InvariantRef<'a, T> { + pub const fn new(r: &'a T) -> Self { + InvariantRef(r, PhantomData) + } +} + +fn match_invariant_ref<'a>() { + match const { InvariantRef::<'a, _>::new(&()) } { + const { InvariantRef::<'a, ()>::new(&()) } => { + } + } +} + +fn main() { + issue_78174(); + match_invariant_ref(); +} diff --git a/src/test/ui/inline-const/const-match-pat-range.rs b/src/test/ui/inline-const/const-match-pat-range.rs index eefe43a1a2..7dc8c11355 100644 --- a/src/test/ui/inline-const/const-match-pat-range.rs +++ b/src/test/ui/inline-const/const-match-pat-range.rs @@ -1,7 +1,7 @@ // build-pass #![allow(incomplete_features)] -#![feature(inline_const, half_open_range_patterns, exclusive_range_pattern)] +#![feature(inline_const_pat, half_open_range_patterns, exclusive_range_pattern)] fn main() { const N: u32 = 10; let x: u32 = 3; diff --git a/src/test/ui/inline-const/const-match-pat.rs b/src/test/ui/inline-const/const-match-pat.rs index c0dc90d971..2f55e16b35 100644 --- a/src/test/ui/inline-const/const-match-pat.rs +++ b/src/test/ui/inline-const/const-match-pat.rs @@ -1,7 +1,7 @@ // run-pass #![allow(incomplete_features)] -#![feature(inline_const)] +#![feature(inline_const_pat)] const MMIO_BIT1: u8 = 4; const MMIO_BIT2: u8 = 5; diff --git a/src/test/ui/integral-variable-unification-error.rs b/src/test/ui/integral-variable-unification-error.rs index 5200b4a829..8d1621321e 100644 --- a/src/test/ui/integral-variable-unification-error.rs +++ b/src/test/ui/integral-variable-unification-error.rs @@ -1,6 +1,8 @@ fn main() { - let mut x = 2; + let mut x //~ NOTE expected due to the type of this binding + = + 2; //~ NOTE expected due to this value x = 5.0; //~^ ERROR mismatched types - //~| expected integer, found floating-point number + //~| NOTE expected integer, found floating-point number } diff --git a/src/test/ui/integral-variable-unification-error.stderr b/src/test/ui/integral-variable-unification-error.stderr index b49bff1b0d..f77c265a2a 100644 --- a/src/test/ui/integral-variable-unification-error.stderr +++ b/src/test/ui/integral-variable-unification-error.stderr @@ -1,6 +1,11 @@ error[E0308]: mismatched types - --> $DIR/integral-variable-unification-error.rs:3:9 + --> $DIR/integral-variable-unification-error.rs:5:9 | +LL | let mut x + | ----- expected due to the type of this binding +LL | = +LL | 2; + | - expected due to this value LL | x = 5.0; | ^^^ expected integer, found floating-point number diff --git a/src/test/ui/intrinsics/const-eval-select-bad.rs b/src/test/ui/intrinsics/const-eval-select-bad.rs index 8fbdc0c39c..a3171187e6 100644 --- a/src/test/ui/intrinsics/const-eval-select-bad.rs +++ b/src/test/ui/intrinsics/const-eval-select-bad.rs @@ -7,6 +7,7 @@ const fn not_fn_items() { //~^ ERROR expected a `FnOnce<()>` closure const_eval_select((), 42, 0xDEADBEEF); //~^ ERROR expected a `FnOnce<()>` closure + //~| ERROR expected a `FnOnce<()>` closure } const fn foo(n: i32) -> i32 { diff --git a/src/test/ui/intrinsics/const-eval-select-bad.stderr b/src/test/ui/intrinsics/const-eval-select-bad.stderr index 78647e9213..5e1ab584d8 100644 --- a/src/test/ui/intrinsics/const-eval-select-bad.stderr +++ b/src/test/ui/intrinsics/const-eval-select-bad.stderr @@ -1,8 +1,8 @@ error[E0277]: expected a `FnOnce<()>` closure, found `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:32]` - --> $DIR/const-eval-select-bad.rs:6:34 + --> $DIR/const-eval-select-bad.rs:6:27 | LL | const_eval_select((), || {}, || {}); - | ----------------- ^^^^^ expected an `FnOnce<()>` closure, found `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:32]` + | ----------------- ^^^^^ expected an `FnOnce<()>` closure, found `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:32]` | | | required by a bound introduced by this call | @@ -15,10 +15,10 @@ LL | F: ~const FnOnce<ARG, Output = RET>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select` error[E0277]: expected a `FnOnce<()>` closure, found `{integer}` - --> $DIR/const-eval-select-bad.rs:8:31 + --> $DIR/const-eval-select-bad.rs:8:27 | LL | const_eval_select((), 42, 0xDEADBEEF); - | ----------------- ^^^^^^^^^^ expected an `FnOnce<()>` closure, found `{integer}` + | ----------------- ^^ expected an `FnOnce<()>` closure, found `{integer}` | | | required by a bound introduced by this call | @@ -30,8 +30,24 @@ note: required by a bound in `const_eval_select` LL | F: ~const FnOnce<ARG, Output = RET>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select` +error[E0277]: expected a `FnOnce<()>` closure, found `{integer}` + --> $DIR/const-eval-select-bad.rs:8:31 + | +LL | const_eval_select((), 42, 0xDEADBEEF); + | ----------------- ^^^^^^^^^^ expected an `FnOnce<()>` closure, found `{integer}` + | | + | required by a bound introduced by this call + | + = help: the trait `FnOnce<()>` is not implemented for `{integer}` + = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }` +note: required by a bound in `const_eval_select` + --> $SRC_DIR/core/src/intrinsics.rs:LL:COL + | +LL | G: FnOnce<ARG, Output = RET> + ~const Drop, + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select` + error[E0271]: type mismatch resolving `<fn(i32) -> bool {bar} as FnOnce<(i32,)>>::Output == i32` - --> $DIR/const-eval-select-bad.rs:27:5 + --> $DIR/const-eval-select-bad.rs:28:5 | LL | const_eval_select((1,), foo, bar); | ^^^^^^^^^^^^^^^^^ expected `i32`, found `bool` @@ -43,13 +59,13 @@ LL | G: FnOnce<ARG, Output = RET> + ~const Drop, | ^^^^^^^^^^^^ required by this bound in `const_eval_select` error[E0631]: type mismatch in function arguments - --> $DIR/const-eval-select-bad.rs:32:37 + --> $DIR/const-eval-select-bad.rs:33:32 | LL | const fn foo(n: i32) -> i32 { | --------------------------- found signature of `fn(i32) -> _` ... LL | const_eval_select((true,), foo, baz); - | ----------------- ^^^ expected signature of `fn(bool) -> _` + | ----------------- ^^^ expected signature of `fn(bool) -> _` | | | required by a bound introduced by this call | @@ -59,7 +75,7 @@ note: required by a bound in `const_eval_select` LL | F: ~const FnOnce<ARG, Output = RET>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select` -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0271, E0277, E0631. For more information about an error, try `rustc --explain E0271`. diff --git a/src/test/ui/intrinsics/intrinsic-alignment.rs b/src/test/ui/intrinsics/intrinsic-alignment.rs index 5a27ea8783..6007eba8c0 100644 --- a/src/test/ui/intrinsics/intrinsic-alignment.rs +++ b/src/test/ui/intrinsics/intrinsic-alignment.rs @@ -15,6 +15,7 @@ mod rusti { target_os = "emscripten", target_os = "freebsd", target_os = "fuchsia", + target_os = "illumos", target_os = "linux", target_os = "macos", target_os = "netbsd", diff --git a/src/test/ui/issues/issue-13407.rs b/src/test/ui/issues/issue-13407.rs index fa53d55f5b..7ea81ffb59 100644 --- a/src/test/ui/issues/issue-13407.rs +++ b/src/test/ui/issues/issue-13407.rs @@ -5,6 +5,5 @@ mod A { fn main() { A::C = 1; //~^ ERROR: invalid left-hand side of assignment - //~| ERROR: mismatched types //~| ERROR: struct `C` is private } diff --git a/src/test/ui/issues/issue-13407.stderr b/src/test/ui/issues/issue-13407.stderr index 4df1813a71..54b6c640d9 100644 --- a/src/test/ui/issues/issue-13407.stderr +++ b/src/test/ui/issues/issue-13407.stderr @@ -18,13 +18,7 @@ LL | A::C = 1; | | | cannot assign to this expression -error[E0308]: mismatched types - --> $DIR/issue-13407.rs:6:12 - | -LL | A::C = 1; - | ^ expected struct `C`, found integer - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0070, E0308, E0603. +Some errors have detailed explanations: E0070, E0603. For more information about an error, try `rustc --explain E0070`. diff --git a/src/test/ui/issues/issue-14853.stderr b/src/test/ui/issues/issue-14853.stderr index 6fc1055049..2adcf55eca 100644 --- a/src/test/ui/issues/issue-14853.stderr +++ b/src/test/ui/issues/issue-14853.stderr @@ -1,11 +1,11 @@ error[E0276]: impl has stricter requirements than trait - --> $DIR/issue-14853.rs:12:5 + --> $DIR/issue-14853.rs:12:15 | LL | fn yay<T: Debug>(_: Option<Self>, thing: &[T]); | ----------------------------------------------- definition of `yay` from trait ... LL | fn yay<T: Str>(_:Option<X>, thing: &[T]) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: Str` + | ^^^ impl has extra requirement `T: Str` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-17651.stderr b/src/test/ui/issues/issue-17651.stderr index 214477f6c6..efaaeeda2f 100644 --- a/src/test/ui/issues/issue-17651.stderr +++ b/src/test/ui/issues/issue-17651.stderr @@ -7,11 +7,11 @@ LL | (|| Box::new(*(&[0][..])))(); | required by a bound introduced by this call | = help: the trait `Sized` is not implemented for `[{integer}]` -note: required by `Box::<T>::new` +note: required by a bound in `Box::<T>::new` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL | -LL | pub fn new(x: T) -> Self { - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl<T> Box<T> { + | ^ required by this bound in `Box::<T>::new` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-18611.stderr b/src/test/ui/issues/issue-18611.stderr index b702196abd..bd18d46223 100644 --- a/src/test/ui/issues/issue-18611.stderr +++ b/src/test/ui/issues/issue-18611.stderr @@ -3,12 +3,6 @@ error[E0277]: the trait bound `isize: HasState` is not satisfied | LL | fn add_state(op: <isize as HasState>::State) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasState` is not implemented for `isize` - | -note: required by a bound in `HasState` - --> $DIR/issue-18611.rs:5:1 - | -LL | trait HasState { - | ^^^^^^^^^^^^^^ required by this bound in `HasState` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-18937.rs b/src/test/ui/issues/issue-18937.rs index ab4c9c736d..af85e5b2b0 100644 --- a/src/test/ui/issues/issue-18937.rs +++ b/src/test/ui/issues/issue-18937.rs @@ -16,8 +16,8 @@ trait A<'a> { } impl<'a> A<'a> for B { - fn foo<F>(&mut self, f: F) //~ ERROR impl has stricter - where F: fmt::Debug + 'static, + fn foo<F>(&mut self, f: F) + where F: fmt::Debug + 'static, //~ ERROR impl has stricter { self.list.push(Box::new(f)); } diff --git a/src/test/ui/issues/issue-18937.stderr b/src/test/ui/issues/issue-18937.stderr index ac302caecc..5e2ba0ef4f 100644 --- a/src/test/ui/issues/issue-18937.stderr +++ b/src/test/ui/issues/issue-18937.stderr @@ -1,17 +1,13 @@ error[E0276]: impl has stricter requirements than trait - --> $DIR/issue-18937.rs:19:5 + --> $DIR/issue-18937.rs:20:31 | LL | / fn foo<F>(&mut self, f: F) LL | | where F: fmt::Debug + 'a, LL | | Self: Sized; | |__________________________- definition of `foo` from trait ... -LL | / fn foo<F>(&mut self, f: F) -LL | | where F: fmt::Debug + 'static, -LL | | { -LL | | self.list.push(Box::new(f)); -LL | | } - | |_____^ impl has extra requirement `F: 'static` +LL | where F: fmt::Debug + 'static, + | ^^^^^^^ impl has extra requirement `F: 'static` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-20162.stderr b/src/test/ui/issues/issue-20162.stderr index ef1eb2ea6c..6848c3f0d8 100644 --- a/src/test/ui/issues/issue-20162.stderr +++ b/src/test/ui/issues/issue-20162.stderr @@ -3,6 +3,12 @@ error[E0277]: the trait bound `X: Ord` is not satisfied | LL | b.sort(); | ^^^^ the trait `Ord` is not implemented for `X` + | +note: required by a bound in `slice::<impl [T]>::sort` + --> $SRC_DIR/alloc/src/slice.rs:LL:COL + | +LL | T: Ord, + | ^^^ required by this bound in `slice::<impl [T]>::sort` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-20261.stderr b/src/test/ui/issues/issue-20261.stderr index c6c3f32dfe..6330364c92 100644 --- a/src/test/ui/issues/issue-20261.stderr +++ b/src/test/ui/issues/issue-20261.stderr @@ -1,8 +1,8 @@ -error[E0282]: type annotations needed for `&(_,)` +error[E0282]: type annotations needed for `(_,)` --> $DIR/issue-20261.rs:4:11 | LL | for (ref i,) in [].iter() { - | --------- the element type for this iterator is not specified + | --------- this method call resolves to `std::slice::Iter<'_, T>` LL | i.clone(); | ^^^^^ cannot infer type | diff --git a/src/test/ui/issues/issue-20413.stderr b/src/test/ui/issues/issue-20413.stderr index 9135c5ac36..2935214140 100644 --- a/src/test/ui/issues/issue-20413.stderr +++ b/src/test/ui/issues/issue-20413.stderr @@ -21,11 +21,6 @@ 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>` -note: required by a bound in `Foo` - --> $DIR/issue-20413.rs:1:1 - | -LL | trait Foo { - | ^^^^^^^^^ required by this bound in `Foo` error[E0275]: overflow evaluating the requirement `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<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>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo` --> $DIR/issue-20413.rs:8:36 @@ -41,11 +36,6 @@ 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>` -note: required by a bound in `Foo` - --> $DIR/issue-20413.rs:1:1 - | -LL | trait Foo { - | ^^^^^^^^^ required by this bound in `Foo` error[E0275]: overflow evaluating the requirement `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<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>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Baz` --> $DIR/issue-20413.rs:28:42 @@ -66,11 +56,6 @@ 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>` -note: required by a bound in `Baz` - --> $DIR/issue-20413.rs:20:1 - | -LL | trait Baz { - | ^^^^^^^^^ required by this bound in `Baz` error[E0275]: overflow evaluating the requirement `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<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>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Baz` --> $DIR/issue-20413.rs:28:42 @@ -91,11 +76,6 @@ 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>` -note: required by a bound in `Baz` - --> $DIR/issue-20413.rs:20:1 - | -LL | trait Baz { - | ^^^^^^^^^ required by this bound in `Baz` error[E0275]: overflow evaluating the requirement `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<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>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Bar` --> $DIR/issue-20413.rs:36:42 @@ -116,11 +96,6 @@ 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>` -note: required by a bound in `Bar` - --> $DIR/issue-20413.rs:16:1 - | -LL | trait Bar { - | ^^^^^^^^^ required by this bound in `Bar` error[E0275]: overflow evaluating the requirement `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<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>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Bar` --> $DIR/issue-20413.rs:36:42 @@ -141,11 +116,6 @@ 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>` -note: required by a bound in `Bar` - --> $DIR/issue-20413.rs:16:1 - | -LL | trait Bar { - | ^^^^^^^^^ required by this bound in `Bar` error: aborting due to 7 previous errors diff --git a/src/test/ui/issues/issue-20605.stderr b/src/test/ui/issues/issue-20605.stderr index 5a67aead75..41eefe3f8e 100644 --- a/src/test/ui/issues/issue-20605.stderr +++ b/src/test/ui/issues/issue-20605.stderr @@ -6,11 +6,6 @@ LL | for item in *things { *item = 0 } | = note: the trait bound `dyn Iterator<Item = &'a mut u8>: IntoIterator` is not satisfied = note: required because of the requirements on the impl of `IntoIterator` for `dyn Iterator<Item = &'a mut u8>` -note: required by `into_iter` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider mutably borrowing here | LL | for item in &mut *things { *item = 0 } diff --git a/src/test/ui/issues/issue-21160.stderr b/src/test/ui/issues/issue-21160.stderr index 92742b5061..300c1272ef 100644 --- a/src/test/ui/issues/issue-21160.stderr +++ b/src/test/ui/issues/issue-21160.stderr @@ -6,11 +6,6 @@ LL | #[derive(Hash)] LL | struct Foo(Bar); | ^^^ the trait `Hash` is not implemented for `Bar` | -note: required by a bound in `std::hash::Hash::hash` - --> $SRC_DIR/core/src/hash/mod.rs:LL:COL - | -LL | fn hash<H: Hasher>(&self, state: &mut H); - | ^ required by this bound in `std::hash::Hash::hash` = note: this error originates in the derive macro `Hash` (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-21974.stderr b/src/test/ui/issues/issue-21974.stderr index 3b6663513b..dfabde9abc 100644 --- a/src/test/ui/issues/issue-21974.stderr +++ b/src/test/ui/issues/issue-21974.stderr @@ -5,11 +5,6 @@ LL | where &'a T : Foo, | ^^^ cannot infer type for reference `&'a T` | = note: cannot satisfy `&'a T: Foo` -note: required by a bound in `Foo` - --> $DIR/issue-21974.rs:6:1 - | -LL | trait Foo { - | ^^^^^^^^^ required by this bound in `Foo` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-22933-2.stderr b/src/test/ui/issues/issue-22933-2.stderr index 584b05ec44..0bfbf53848 100644 --- a/src/test/ui/issues/issue-22933-2.stderr +++ b/src/test/ui/issues/issue-22933-2.stderr @@ -5,7 +5,10 @@ LL | enum Delicious { | -------------- variant or associated item `PIE` not found here ... LL | ApplePie = Delicious::Apple as isize | Delicious::PIE as isize, - | ^^^ variant or associated item not found in `Delicious` + | ^^^ + | | + | variant or associated item not found in `Delicious` + | help: there is a variant with a similar name: `Pie` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-23966.stderr b/src/test/ui/issues/issue-23966.stderr index 9c87ee6104..ae8233d5c7 100644 --- a/src/test/ui/issues/issue-23966.stderr +++ b/src/test/ui/issues/issue-23966.stderr @@ -7,6 +7,11 @@ LL | "".chars().fold(|_, _| (), ()); | required by a bound introduced by this call | = help: the trait `FnMut<(_, char)>` is not implemented for `()` +note: required by a bound in `fold` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | F: FnMut(B, Self::Item) -> B, + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `fold` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-24424.stderr b/src/test/ui/issues/issue-24424.stderr index 4896006b64..fa59da852f 100644 --- a/src/test/ui/issues/issue-24424.stderr +++ b/src/test/ui/issues/issue-24424.stderr @@ -5,11 +5,6 @@ LL | impl <'l0, 'l1, T0> Trait1<'l0, T0> for bool where T0 : Trait0<'l0>, T0 : T | ^^^^^^^^^^^ cannot infer type for type parameter `T0` | = note: cannot satisfy `T0: Trait0<'l0>` -note: required by a bound in `Trait0` - --> $DIR/issue-24424.rs:2:1 - | -LL | trait Trait0<'l0> {} - | ^^^^^^^^^^^^^^^^^ required by this bound in `Trait0` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-2444.rs b/src/test/ui/issues/issue-2444.rs deleted file mode 100644 index ac0d0506a3..0000000000 --- a/src/test/ui/issues/issue-2444.rs +++ /dev/null @@ -1,17 +0,0 @@ -// run-fail -// error-pattern:explicit panic -// ignore-emscripten no processes - -use std::sync::Arc; - -enum Err<T> { - Errr(Arc<T>), -} - -fn foo() -> Err<isize> { - panic!(); -} - -fn main() { - let _f = foo(); -} diff --git a/src/test/ui/issues/issue-2748-b.rs b/src/test/ui/issues/issue-2748-b.rs deleted file mode 100644 index 8df735ac88..0000000000 --- a/src/test/ui/issues/issue-2748-b.rs +++ /dev/null @@ -1,11 +0,0 @@ -// run-pass - -fn thing<'r>(x: &'r [isize]) -> &'r [isize] { x } - -pub fn main() { - let x = &[1,2,3]; - let y = x; - let z = thing(x); - assert_eq!(z[2], x[2]); - assert_eq!(z[1], y[1]); -} diff --git a/src/test/ui/issues/issue-28098.stderr b/src/test/ui/issues/issue-28098.stderr index 6a74f4ed48..3beb992924 100644 --- a/src/test/ui/issues/issue-28098.stderr +++ b/src/test/ui/issues/issue-28098.stderr @@ -7,11 +7,6 @@ LL | let _ = Iterator::next(&mut ()); | required by a bound introduced by this call | = help: the trait `Iterator` is not implemented for `()` -note: required by `std::iter::Iterator::next` - --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL - | -LL | fn next(&mut self) -> Option<Self::Item>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `bool` is not an iterator --> $DIR/issue-28098.rs:6:14 @@ -21,11 +16,6 @@ LL | for _ in false {} | = help: the trait `Iterator` is not implemented for `bool` = note: required because of the requirements on the impl of `IntoIterator` for `bool` -note: required by `into_iter` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `()` is not an iterator --> $DIR/issue-28098.rs:9:28 @@ -36,11 +26,6 @@ LL | let _ = Iterator::next(&mut ()); | required by a bound introduced by this call | = help: the trait `Iterator` is not implemented for `()` -note: required by `std::iter::Iterator::next` - --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL - | -LL | fn next(&mut self) -> Option<Self::Item>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `()` is not an iterator --> $DIR/issue-28098.rs:2:13 @@ -59,11 +44,6 @@ LL | let _ = Iterator::next(&mut ()); | required by a bound introduced by this call | = help: the trait `Iterator` is not implemented for `()` -note: required by `std::iter::Iterator::next` - --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL - | -LL | fn next(&mut self) -> Option<Self::Item>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `()` is not an iterator --> $DIR/issue-28098.rs:22:28 @@ -74,11 +54,6 @@ LL | let _ = Iterator::next(&mut ()); | required by a bound introduced by this call | = help: the trait `Iterator` is not implemented for `()` -note: required by `std::iter::Iterator::next` - --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL - | -LL | fn next(&mut self) -> Option<Self::Item>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `bool` is not an iterator --> $DIR/issue-28098.rs:25:14 @@ -88,11 +63,6 @@ LL | for _ in false {} | = help: the trait `Iterator` is not implemented for `bool` = note: required because of the requirements on the impl of `IntoIterator` for `bool` -note: required by `into_iter` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `()` is not an iterator --> $DIR/issue-28098.rs:18:13 diff --git a/src/test/ui/issues/issue-29147.stderr b/src/test/ui/issues/issue-29147.stderr index f00d5d32bb..5570e887ed 100644 --- a/src/test/ui/issues/issue-29147.stderr +++ b/src/test/ui/issues/issue-29147.stderr @@ -4,12 +4,13 @@ error[E0283]: type annotations needed LL | let _ = <S5<_>>::xxx; | ^^^^^^^^^^^^ cannot infer type for struct `S5<_>` | - = note: cannot satisfy `S5<_>: Foo` -note: required by `Foo::xxx` - --> $DIR/issue-29147.rs:10:13 +note: multiple `impl`s satisfying `S5<_>: Foo` found + --> $DIR/issue-29147.rs:17:1 | -LL | trait Foo { fn xxx(&self); } - | ^^^^^^^^^^^^^^ +LL | impl Foo for S5<u32> { fn xxx(&self) {} } + | ^^^^^^^^^^^^^^^^^^^^ +LL | impl Foo for S5<u64> { fn xxx(&self) {} } + | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-2951.stderr b/src/test/ui/issues/issue-2951.stderr index b966b33938..538bbe2f50 100644 --- a/src/test/ui/issues/issue-2951.stderr +++ b/src/test/ui/issues/issue-2951.stderr @@ -6,6 +6,7 @@ LL | fn foo<T, U>(x: T, y: U) { | | | expected type parameter LL | let mut xx = x; + | - expected due to this value LL | xx = y; | ^ expected type parameter `T`, found type parameter `U` | diff --git a/src/test/ui/issues/issue-31173.rs b/src/test/ui/issues/issue-31173.rs index 40475426cf..48061ae54a 100644 --- a/src/test/ui/issues/issue-31173.rs +++ b/src/test/ui/issues/issue-31173.rs @@ -9,8 +9,6 @@ pub fn get_tok(it: &mut IntoIter<u8>) { }) .cloned() //~^ ERROR type mismatch resolving - //~| expected type `u8` - //~| found reference `&_` .collect(); //~ ERROR the method } diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index 8b7871ce31..982b6118ce 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -2,13 +2,18 @@ error[E0271]: type mismatch resolving `<TakeWhile<&mut std::vec::IntoIter<u8>, [ --> $DIR/issue-31173.rs:10:10 | LL | .cloned() - | ^^^^^^ expected `u8`, found reference + | ^^^^^^ expected reference, found `u8` | - = note: expected type `u8` - found reference `&_` + = note: expected reference `&_` + found type `u8` +note: required by a bound in `cloned` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | Self: Sized + Iterator<Item = &'a T>, + | ^^^^^^^^^^^^ required by this bound in `cloned` error[E0599]: the method `collect` exists for struct `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6]>>`, but its trait bounds were not satisfied - --> $DIR/issue-31173.rs:14:10 + --> $DIR/issue-31173.rs:12:10 | LL | .collect(); | ^^^^^^^ method cannot be called on `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6]>>` due to unsatisfied trait bounds diff --git a/src/test/ui/issues/issue-31299.rs b/src/test/ui/issues/issue-31299.rs index abed18d81f..d93ffcb226 100644 --- a/src/test/ui/issues/issue-31299.rs +++ b/src/test/ui/issues/issue-31299.rs @@ -29,6 +29,7 @@ struct PtrBack<T: Front>(Vec<T::Back>); struct M(PtrBack<Vec<M>>); +#[allow(unused_must_use)] fn main() { std::mem::size_of::<M>(); } diff --git a/src/test/ui/issues/issue-3211.rs b/src/test/ui/issues/issue-3211.rs deleted file mode 100644 index 49dd4fa736..0000000000 --- a/src/test/ui/issues/issue-3211.rs +++ /dev/null @@ -1,7 +0,0 @@ -// run-pass -pub fn main() { - let mut x = 0; - for _ in 0..4096 { x += 1; } - assert_eq!(x, 4096); - println!("x = {}", x); -} diff --git a/src/test/ui/issues/issue-32709.stderr b/src/test/ui/issues/issue-32709.stderr index bc7eb0688e..b4c3f148e3 100644 --- a/src/test/ui/issues/issue-32709.stderr +++ b/src/test/ui/issues/issue-32709.stderr @@ -8,11 +8,6 @@ LL | Err(5)?; | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait = note: required because of the requirements on the impl of `FromResidual<Result<Infallible, {integer}>>` for `Result<i32, ()>` -note: required by `from_residual` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn from_residual(residual: R) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-33941.rs b/src/test/ui/issues/issue-33941.rs index 4fb805b37e..ccaa633485 100644 --- a/src/test/ui/issues/issue-33941.rs +++ b/src/test/ui/issues/issue-33941.rs @@ -3,5 +3,4 @@ use std::collections::HashMap; fn main() { for _ in HashMap::new().iter().cloned() {} //~ ERROR type mismatch //~^ ERROR type mismatch - //~| ERROR type mismatch } diff --git a/src/test/ui/issues/issue-33941.stderr b/src/test/ui/issues/issue-33941.stderr index d588214f50..eb98a3a29a 100644 --- a/src/test/ui/issues/issue-33941.stderr +++ b/src/test/ui/issues/issue-33941.stderr @@ -2,26 +2,15 @@ error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, --> $DIR/issue-33941.rs:4:36 | LL | for _ in HashMap::new().iter().cloned() {} - | ^^^^^^ expected tuple, found reference - | - = note: expected tuple `(&_, &_)` - found reference `&_` - -error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, _> as Iterator>::Item == &_` - --> $DIR/issue-33941.rs:4:14 - | -LL | for _ in HashMap::new().iter().cloned() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found tuple + | ^^^^^^ expected reference, found tuple | = 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` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL +note: required by a bound in `cloned` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Self: Sized + Iterator<Item = &'a T>, + | ^^^^^^^^^^^^ required by this bound in `cloned` error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, _> as Iterator>::Item == &_` --> $DIR/issue-33941.rs:4:14 @@ -32,12 +21,8 @@ LL | for _ in HashMap::new().iter().cloned() {} = note: expected reference `&_` found tuple `(&_, &_)` = note: required because of the requirements on the impl of `Iterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` -note: required by `std::iter::Iterator::next` - --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL - | -LL | fn next(&mut self) -> Option<Self::Item>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: required because of the requirements on the impl of `IntoIterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/issues/issue-34229.stderr b/src/test/ui/issues/issue-34229.stderr index fba75de8cc..71e02f2fd8 100644 --- a/src/test/ui/issues/issue-34229.stderr +++ b/src/test/ui/issues/issue-34229.stderr @@ -7,11 +7,6 @@ LL | #[derive(PartialEq, PartialOrd)] struct Nope(Comparable); | in this derive macro expansion | = help: the trait `PartialOrd` is not implemented for `Comparable` -note: required by `std::cmp::PartialOrd::partial_cmp` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - | -LL | fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/issues/issue-34334.stderr b/src/test/ui/issues/issue-34334.stderr index acb44ce2c3..49d6709a86 100644 --- a/src/test/ui/issues/issue-34334.stderr +++ b/src/test/ui/issues/issue-34334.stderr @@ -14,6 +14,11 @@ LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_rece | ^^^^^^^ value of type `Vec<(u32, _, _)>` cannot be built from `std::iter::Iterator<Item=()>` | = help: the trait `FromIterator<()>` is not implemented for `Vec<(u32, _, _)>` +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | fn collect<B: FromIterator<Self::Item>>(self) -> B + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-39970.stderr b/src/test/ui/issues/issue-39970.stderr index f609e47e81..ffcac1f470 100644 --- a/src/test/ui/issues/issue-39970.stderr +++ b/src/test/ui/issues/issue-39970.stderr @@ -9,11 +9,6 @@ note: required because of the requirements on the impl of `Visit` for `()` | LL | impl Visit for () where | ^^^^^ ^^ -note: required by `Visit::visit` - --> $DIR/issue-39970.rs:6:5 - | -LL | fn visit() {} - | ^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-40827.stderr b/src/test/ui/issues/issue-40827.stderr index 3b2d232e61..11c23e5b65 100644 --- a/src/test/ui/issues/issue-40827.stderr +++ b/src/test/ui/issues/issue-40827.stderr @@ -1,8 +1,10 @@ error[E0277]: `Rc<Foo>` cannot be shared between threads safely - --> $DIR/issue-40827.rs:14:5 + --> $DIR/issue-40827.rs:14:7 | LL | f(Foo(Arc::new(Bar::B(None)))); - | ^ `Rc<Foo>` cannot be shared between threads safely + | - ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Rc<Foo>` cannot be shared between threads safely + | | + | required by a bound introduced by this call | = help: within `Bar`, the trait `Sync` is not implemented for `Rc<Foo>` note: required because it appears within the type `Bar` @@ -23,10 +25,12 @@ LL | fn f<T: Send>(_: T) {} | ^^^^ required by this bound in `f` error[E0277]: `Rc<Foo>` cannot be sent between threads safely - --> $DIR/issue-40827.rs:14:5 + --> $DIR/issue-40827.rs:14:7 | LL | f(Foo(Arc::new(Bar::B(None)))); - | ^ `Rc<Foo>` cannot be sent between threads safely + | - ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Rc<Foo>` cannot be sent between threads safely + | | + | required by a bound introduced by this call | = help: within `Bar`, the trait `Send` is not implemented for `Rc<Foo>` note: required because it appears within the type `Bar` diff --git a/src/test/ui/issues/issue-41974.rs b/src/test/ui/issues/issue-41974.rs index 7875b432d7..10c363479a 100644 --- a/src/test/ui/issues/issue-41974.rs +++ b/src/test/ui/issues/issue-41974.rs @@ -4,9 +4,9 @@ struct Flags; trait A { } -impl<T> Drop for T where T: A { //~ ERROR E0119 - //~^ ERROR E0120 - //~| ERROR E0210 +impl<T> Drop for T where T: A { + //~^ ERROR E0120 + //~| ERROR E0210 fn drop(&mut self) { } } diff --git a/src/test/ui/issues/issue-41974.stderr b/src/test/ui/issues/issue-41974.stderr index 11d77857d6..fcbb401402 100644 --- a/src/test/ui/issues/issue-41974.stderr +++ b/src/test/ui/issues/issue-41974.stderr @@ -1,13 +1,11 @@ -error[E0119]: conflicting implementations of trait `std::ops::Drop` for type `std::boxed::Box<_, _>` - --> $DIR/issue-41974.rs:7:1 +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`) + --> $DIR/issue-41974.rs:7:6 | LL | impl<T> Drop for T where T: A { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^ type parameter `T` must be used as the type parameter for some local type | - = note: conflicting implementation in crate `alloc`: - - impl<T, A> Drop for Box<T, A> - where A: Allocator, T: ?Sized; - = note: downstream crates may implement trait `A` for type `std::boxed::Box<_, _>` + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions --> $DIR/issue-41974.rs:7:18 @@ -15,16 +13,7 @@ error[E0120]: the `Drop` trait may only be implemented for structs, enums, and u LL | impl<T> Drop for T where T: A { | ^ must be a struct, enum, or union -error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`) - --> $DIR/issue-41974.rs:7:6 - | -LL | impl<T> Drop for T where T: A { - | ^ type parameter `T` must be used as the type parameter for some local type - | - = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local - = note: only traits defined in the current crate can be implemented for a type parameter - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0119, E0120, E0210. -For more information about an error, try `rustc --explain E0119`. +Some errors have detailed explanations: E0120, E0210. +For more information about an error, try `rustc --explain E0120`. diff --git a/src/test/ui/issues/issue-44005.stderr b/src/test/ui/issues/issue-44005.stderr deleted file mode 100644 index 307e444e69..0000000000 --- a/src/test/ui/issues/issue-44005.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0631]: type mismatch in closure arguments - --> $DIR/issue-44005.rs:26:5 - | -LL | uncallable(x, |y| f(y)); - | ^^^^^^^^^^ -------- found signature of `for<'r> fn(&'r i32) -> _` - | | - | expected signature of `for<'a> fn(<&i32 as Foo<'a>>::Bar) -> _` - | -note: required by a bound in `uncallable` - --> $DIR/issue-44005.rs:16:8 - | -LL | pub fn uncallable<T, F>(x: T, f: F) - | ---------- required by a bound in this -... -LL | F: for<'a> Fn(<T as Foo<'a>>::Bar), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `uncallable` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/issues/issue-4401.rs b/src/test/ui/issues/issue-4401.rs deleted file mode 100644 index fef73fbe1f..0000000000 --- a/src/test/ui/issues/issue-4401.rs +++ /dev/null @@ -1,7 +0,0 @@ -// run-pass -pub fn main() { - let mut count = 0; - for _ in 0..999_999 { count += 1; } - assert_eq!(count, 999_999); - println!("{}", count); -} diff --git a/src/test/ui/issues/issue-46983.nll.stderr b/src/test/ui/issues/issue-46983.nll.stderr new file mode 100644 index 0000000000..38a219bbd7 --- /dev/null +++ b/src/test/ui/issues/issue-46983.nll.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/issue-46983.rs:2:5 + | +LL | fn foo(x: &u32) -> &'static u32 { + | - let's call the lifetime of this reference `'1` +LL | &*x + | ^^^ returning this value requires that `'1` must outlive `'static` + +error: aborting due to previous error + diff --git a/src/test/ui/issues/issue-46983.rs b/src/test/ui/issues/issue-46983.rs index c1fd7729bd..87ed892894 100644 --- a/src/test/ui/issues/issue-46983.rs +++ b/src/test/ui/issues/issue-46983.rs @@ -1,6 +1,6 @@ fn foo(x: &u32) -> &'static u32 { &*x - //~^ ERROR explicit lifetime required in the type of `x` [E0621] + //~^ ERROR `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement [E0759] } fn main() {} diff --git a/src/test/ui/issues/issue-46983.stderr b/src/test/ui/issues/issue-46983.stderr index d328329eda..77fb130f51 100644 --- a/src/test/ui/issues/issue-46983.stderr +++ b/src/test/ui/issues/issue-46983.stderr @@ -1,9 +1,11 @@ -error[E0621]: explicit lifetime required in the type of `x` +error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement --> $DIR/issue-46983.rs:2:5 | +LL | fn foo(x: &u32) -> &'static u32 { + | ---- this data with an anonymous lifetime `'_`... LL | &*x - | ^^^ lifetime `'static` required + | ^^^ ...is captured and required to live as long as `'static` here error: aborting due to previous error -For more information about this error, try `rustc --explain E0621`. +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/issues/issue-47706-trait.stderr b/src/test/ui/issues/issue-47706-trait.stderr index 2e542644b7..eb0c80f8f0 100644 --- a/src/test/ui/issues/issue-47706-trait.stderr +++ b/src/test/ui/issues/issue-47706-trait.stderr @@ -7,6 +7,12 @@ LL | None::<()>.map(Self::f); | --- ^^^^^^^ expected function that takes a single 0-tuple as argument | | | required by a bound introduced by this call + | +note: required by a bound in `Option::<T>::map` + --> $SRC_DIR/core/src/option.rs:LL:COL + | +LL | pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> { + | ^^^^^^^^^^^^^^ required by this bound in `Option::<T>::map` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-47706.stderr b/src/test/ui/issues/issue-47706.stderr index acf7626c63..237b2b9e79 100644 --- a/src/test/ui/issues/issue-47706.stderr +++ b/src/test/ui/issues/issue-47706.stderr @@ -8,6 +8,12 @@ LL | self.foo.map(Foo::new) | --- ^^^^^^^^ expected function that takes 1 argument | | | required by a bound introduced by this call + | +note: required by a bound in `Option::<T>::map` + --> $SRC_DIR/core/src/option.rs:LL:COL + | +LL | pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> { + | ^^^^^^^^^^^^^^ required by this bound in `Option::<T>::map` error[E0593]: function is expected to take 0 arguments, but it takes 1 argument --> $DIR/issue-47706.rs:27:9 diff --git a/src/test/ui/issues/issue-50993.rs b/src/test/ui/issues/issue-50993.rs deleted file mode 100644 index e6a9451a06..0000000000 --- a/src/test/ui/issues/issue-50993.rs +++ /dev/null @@ -1,9 +0,0 @@ -// compile-flags: --crate-type dylib --target thumbv7em-none-eabihf -// needs-llvm-components: arm -// build-pass -// error-pattern: dropping unsupported crate type `dylib` for target `thumbv7em-none-eabihf` - -#![feature(no_core)] - -#![no_std] -#![no_core] diff --git a/src/test/ui/issues/issue-50993.stderr b/src/test/ui/issues/issue-50993.stderr deleted file mode 100644 index 45cbfef070..0000000000 --- a/src/test/ui/issues/issue-50993.stderr +++ /dev/null @@ -1,4 +0,0 @@ -warning: dropping unsupported crate type `dylib` for target `thumbv7em-none-eabihf` - -warning: 1 warning emitted - diff --git a/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr b/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr index 0f61e03c3b..15d2ef3fce 100644 --- a/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr +++ b/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr @@ -12,10 +12,10 @@ help: try removing this `?` LL - missing_discourses()? LL + missing_discourses() | -help: try using a variant of the expected enum +help: try wrapping the expression in `Ok` | LL | Ok(missing_discourses()?) - | + | +++ + error: aborting due to previous error diff --git a/src/test/ui/issues/issue-53348.rs b/src/test/ui/issues/issue-53348.rs index 65f4656b02..d2f8c77c0c 100644 --- a/src/test/ui/issues/issue-53348.rs +++ b/src/test/ui/issues/issue-53348.rs @@ -5,7 +5,7 @@ fn main() { v.into_iter().map(|s|s.to_owned()).collect::<Vec<_>>(); - let mut a = String::new(); + let mut a = String::new(); //~ NOTE expected due to this value for i in v { a = *i.to_string(); //~^ ERROR mismatched types diff --git a/src/test/ui/issues/issue-53348.stderr b/src/test/ui/issues/issue-53348.stderr index 8f50026124..71d9f5b3db 100644 --- a/src/test/ui/issues/issue-53348.stderr +++ b/src/test/ui/issues/issue-53348.stderr @@ -1,6 +1,9 @@ error[E0308]: mismatched types --> $DIR/issue-53348.rs:10:13 | +LL | let mut a = String::new(); + | ------------- expected due to this value +LL | for i in v { LL | a = *i.to_string(); | ^^^^^^^^^^^^^^ expected struct `String`, found `str` diff --git a/src/test/ui/issues/issue-5358-1.stderr b/src/test/ui/issues/issue-5358-1.stderr index 314d1fddbd..d1bc279c75 100644 --- a/src/test/ui/issues/issue-5358-1.stderr +++ b/src/test/ui/issues/issue-5358-1.stderr @@ -8,6 +8,10 @@ LL | Either::Right(_) => {} | = note: expected struct `S` found enum `Either<_, _>` +help: you might have meant to use field `0` whose type is `Either<usize, usize>` + | +LL | match S(Either::Left(5)).0 { + | ~~~~~~~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-54954.stderr b/src/test/ui/issues/issue-54954.stderr index df76a98555..efe2ef504a 100644 --- a/src/test/ui/issues/issue-54954.stderr +++ b/src/test/ui/issues/issue-54954.stderr @@ -11,11 +11,6 @@ LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type | = note: cannot satisfy `_: Tt` -note: required by a bound in `Tt::const_val` - --> $DIR/issue-54954.rs:5:24 - | -LL | const fn const_val<T: Sized>() -> usize { - | ^ required by this bound in `Tt::const_val` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-58022.stderr b/src/test/ui/issues/issue-58022.stderr index a1715bd99e..0128b70e21 100644 --- a/src/test/ui/issues/issue-58022.stderr +++ b/src/test/ui/issues/issue-58022.stderr @@ -15,11 +15,6 @@ LL | fn new(slice: &[u8; Foo::SIZE]) -> Self; | = note: cannot satisfy `_: Foo` = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl` -note: required by `Foo::SIZE` - --> $DIR/issue-58022.rs:2:5 - | -LL | const SIZE: usize; - | ^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-59494.rs b/src/test/ui/issues/issue-59494.rs index 06b8eb777c..a53e28f724 100644 --- a/src/test/ui/issues/issue-59494.rs +++ b/src/test/ui/issues/issue-59494.rs @@ -19,5 +19,5 @@ fn main() { let g = |(a, _)| a; let t7 = |env| |a| |b| t7p(f, g)(((env, a), b)); let t8 = t8n(t7, t7p(f, g)); - //~^ ERROR: expected a `Fn<(_,)>` closure, found `impl Fn<(((_, _), _),)> + //~^ ERROR: expected a `Fn<(_,)>` closure, found `impl Fn(((_, _), _))` [E0277] } diff --git a/src/test/ui/issues/issue-59494.stderr b/src/test/ui/issues/issue-59494.stderr index 9b7fe1ef78..a9284535e4 100644 --- a/src/test/ui/issues/issue-59494.stderr +++ b/src/test/ui/issues/issue-59494.stderr @@ -1,12 +1,12 @@ -error[E0277]: expected a `Fn<(_,)>` closure, found `impl Fn<(((_, _), _),)>` +error[E0277]: expected a `Fn<(_,)>` closure, found `impl Fn(((_, _), _))` --> $DIR/issue-59494.rs:21:22 | LL | let t8 = t8n(t7, t7p(f, g)); - | --- ^^^^^^^^^ expected an `Fn<(_,)>` closure, found `impl Fn<(((_, _), _),)>` + | --- ^^^^^^^^^ expected an `Fn<(_,)>` closure, found `impl Fn(((_, _), _))` | | | required by a bound introduced by this call | - = help: the trait `Fn<(_,)>` is not implemented for `impl Fn<(((_, _), _),)>` + = help: the trait `Fn<(_,)>` is not implemented for `impl Fn(((_, _), _))` note: required by a bound in `t8n` --> $DIR/issue-59494.rs:5:45 | diff --git a/src/test/ui/issues/issue-66353.stderr b/src/test/ui/issues/issue-66353.stderr index 282e236d3d..3356180974 100644 --- a/src/test/ui/issues/issue-66353.stderr +++ b/src/test/ui/issues/issue-66353.stderr @@ -11,12 +11,6 @@ LL | _Func::< <() as _A>::AssocT >::func(()); | ----------------------------------- ^^ the trait `_Func<_>` is not implemented for `()` | | | required by a bound introduced by this call - | -note: required by `_Func::func` - --> $DIR/issue-66353.rs:4:5 - | -LL | fn func(_: Self); - | ^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr index a08531000b..6a96709cba 100644 --- a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr +++ b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr @@ -5,6 +5,11 @@ LL | let x2: Vec<f64> = x1.into_iter().collect(); | ^^^^^^^ value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>` | = help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>` +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | fn collect<B: FromIterator<Self::Item>>(self) -> B + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect` error[E0277]: a value of type `Vec<f64>` cannot be built from an iterator over elements of type `&f64` --> $DIR/issue-66923-show-error-for-correct-call.rs:12:29 @@ -13,6 +18,11 @@ LL | let x3 = x1.into_iter().collect::<Vec<f64>>(); | ^^^^^^^ value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>` | = help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>` +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | fn collect<B: FromIterator<Self::Item>>(self) -> B + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect` error: aborting due to 2 previous errors 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 e04dec24e4..6e030f1cc4 100644 --- a/src/test/ui/issues/issue-69225-SCEVAddExpr-wrap-flag.rs +++ b/src/test/ui/issues/issue-69225-SCEVAddExpr-wrap-flag.rs @@ -1,6 +1,5 @@ // 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-69455.rs b/src/test/ui/issues/issue-69455.rs index f1935ae253..a53aadcfad 100644 --- a/src/test/ui/issues/issue-69455.rs +++ b/src/test/ui/issues/issue-69455.rs @@ -27,4 +27,5 @@ impl Test<u64> for u64 { fn main() { let xs: Vec<u64> = vec![1, 2, 3]; println!("{}", 23u64.test(xs.iter().sum())); //~ ERROR: type annotations needed + //~^ ERROR type annotations needed } diff --git a/src/test/ui/issues/issue-69455.stderr b/src/test/ui/issues/issue-69455.stderr index 430bbcabf8..da84a6b52d 100644 --- a/src/test/ui/issues/issue-69455.stderr +++ b/src/test/ui/issues/issue-69455.stderr @@ -4,6 +4,26 @@ error[E0284]: type annotations needed: cannot satisfy `<u64 as Test<_>>::Output LL | println!("{}", 23u64.test(xs.iter().sum())); | ^^^^ cannot satisfy `<u64 as Test<_>>::Output == _` -error: aborting due to previous error +error[E0283]: type annotations needed + --> $DIR/issue-69455.rs:29:26 + | +LL | println!("{}", 23u64.test(xs.iter().sum())); + | ^^^^ cannot infer type for type parameter `Rhs` declared on the trait `Test` + | +note: multiple `impl`s satisfying `u64: Test<_>` found + --> $DIR/issue-69455.rs:11:1 + | +LL | impl Test<u32> for u64 { + | ^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Test<u64> for u64 { + | ^^^^^^^^^^^^^^^^^^^^^^ +help: consider specifying the type argument in the method call + | +LL | println!("{}", 23u64.test(xs.iter().sum::<S>())); + | +++++ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0284`. +Some errors have detailed explanations: E0283, E0284. +For more information about an error, try `rustc --explain E0283`. diff --git a/src/test/ui/issues/issue-69683.rs b/src/test/ui/issues/issue-69683.rs index cc7f1fa0f5..7a76e9ef20 100644 --- a/src/test/ui/issues/issue-69683.rs +++ b/src/test/ui/issues/issue-69683.rs @@ -28,5 +28,6 @@ fn main() { let b: [u8; 3] = [0u8; 3]; 0u16.foo(b); //~ ERROR type annotations needed + //~^ ERROR type annotations needed //<u16 as Foo<[(); 3]>>::foo(0u16, b); } diff --git a/src/test/ui/issues/issue-69683.stderr b/src/test/ui/issues/issue-69683.stderr index 776370331a..b53923eec1 100644 --- a/src/test/ui/issues/issue-69683.stderr +++ b/src/test/ui/issues/issue-69683.stderr @@ -4,6 +4,30 @@ error[E0284]: type annotations needed: cannot satisfy `<u8 as Element<_>>::Array LL | 0u16.foo(b); | ^^^ cannot satisfy `<u8 as Element<_>>::Array == [u8; 3]` -error: aborting due to previous error +error[E0283]: type annotations needed + --> $DIR/issue-69683.rs:30:10 + | +LL | 0u16.foo(b); + | ^^^ cannot infer type for type parameter `I` declared on the trait `Foo` + | +note: multiple `impl`s satisfying `u8: Element<_>` found + --> $DIR/issue-69683.rs:5:1 + | +LL | impl<T> Element<()> for T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl<T: Element<S>, S> Element<[S; 3]> for T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `Foo::foo` + --> $DIR/issue-69683.rs:15:9 + | +LL | u8: Element<I>, + | ^^^^^^^^^^ required by this bound in `Foo::foo` +LL | { +LL | fn foo(self, x: <u8 as Element<I>>::Array); + | --- required by a bound in this + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0284`. +Some errors have detailed explanations: E0283, E0284. +For more information about an error, try `rustc --explain E0283`. diff --git a/src/test/ui/issues/issue-7246.rs b/src/test/ui/issues/issue-7246.rs index bf2794eb63..7b16fa024f 100644 --- a/src/test/ui/issues/issue-7246.rs +++ b/src/test/ui/issues/issue-7246.rs @@ -5,6 +5,7 @@ use std::ptr; pub unsafe fn g() { return; if *ptr::null() {}; //~ ERROR unreachable + //~| WARNING dereferencing a null pointer } pub fn main() {} diff --git a/src/test/ui/issues/issue-7246.stderr b/src/test/ui/issues/issue-7246.stderr index bb0221ecb8..a9bf2bf763 100644 --- a/src/test/ui/issues/issue-7246.stderr +++ b/src/test/ui/issues/issue-7246.stderr @@ -12,5 +12,13 @@ note: the lint level is defined here LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +warning: dereferencing a null pointer + --> $DIR/issue-7246.rs:7:8 + | +LL | if *ptr::null() {}; + | ^^^^^^^^^^^^ this code causes undefined behavior when executed + | + = note: `#[warn(deref_nullptr)]` on by default + +error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/issues/issue-72690.rs b/src/test/ui/issues/issue-72690.rs index 4edbd9ca15..916a7832c6 100644 --- a/src/test/ui/issues/issue-72690.rs +++ b/src/test/ui/issues/issue-72690.rs @@ -5,10 +5,13 @@ fn no_err() { fn err() { String::from("x".as_ref()); //~ ERROR type annotations needed + //~^ ERROR type annotations needed } fn arg_pat_closure_err() { |x| String::from("x".as_ref()); //~ ERROR type annotations needed + //~^ ERROR type annotations needed + //~| ERROR type annotations needed } fn local_pat_closure_err() { @@ -17,12 +20,14 @@ fn local_pat_closure_err() { fn err_first_arg_pat() { String::from("x".as_ref()); //~ ERROR type annotations needed + //~^ ERROR type annotations needed |x: String| x; } fn err_second_arg_pat() { |x: String| x; String::from("x".as_ref()); //~ ERROR type annotations needed + //~^ ERROR type annotations needed } fn err_mid_arg_pat() { @@ -31,6 +36,7 @@ fn err_mid_arg_pat() { |x: String| x; |x: String| x; String::from("x".as_ref()); //~ ERROR type annotations needed + //~^ ERROR type annotations needed |x: String| x; |x: String| x; |x: String| x; @@ -39,12 +45,14 @@ fn err_mid_arg_pat() { fn err_first_local_pat() { String::from("x".as_ref()); //~ ERROR type annotations needed + //~^ ERROR type annotations needed let _ = String::from("x"); } fn err_second_local_pat() { let _ = String::from("x"); String::from("x".as_ref()); //~ ERROR type annotations needed + //~^ ERROR type annotations needed } fn err_mid_local_pat() { @@ -53,6 +61,7 @@ fn err_mid_local_pat() { let _ = String::from("x"); let _ = String::from("x"); String::from("x".as_ref()); //~ ERROR type annotations needed + //~^ ERROR type annotations needed let _ = String::from("x"); let _ = String::from("x"); let _ = String::from("x"); diff --git a/src/test/ui/issues/issue-72690.stderr b/src/test/ui/issues/issue-72690.stderr index af3459a7d2..629ccea257 100644 --- a/src/test/ui/issues/issue-72690.stderr +++ b/src/test/ui/issues/issue-72690.stderr @@ -4,108 +4,221 @@ error[E0283]: type annotations needed LL | String::from("x".as_ref()); | ^^^^^^^^^^^^ cannot infer type for reference `&_` | - = note: cannot satisfy `String: From<&_>` -note: required by `from` - --> $SRC_DIR/core/src/convert/mod.rs:LL:COL + = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate: + - impl<> From<&String> for String; + - impl<> From<&str> for String; + +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:7:22 | -LL | fn from(_: T) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | String::from("x".as_ref()); + | ----^^^^^^-- + | | | + | | cannot infer type for type parameter `T` declared on the trait `AsRef` + | this method call resolves to `&T` + | + = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef<OsStr> for str; + - impl AsRef<Path> for str; + - impl AsRef<[u8]> for str; + - impl AsRef<str> for str; error[E0282]: type annotations needed - --> $DIR/issue-72690.rs:11:6 + --> $DIR/issue-72690.rs:12:6 | LL | |x| String::from("x".as_ref()); | ^ consider giving this closure parameter a type +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:12:9 + | +LL | |x| String::from("x".as_ref()); + | ^^^^^^^^^^^^ cannot infer type for reference `&_` + | + = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate: + - impl<> From<&String> for String; + - impl<> From<&str> for String; + +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:12:26 + | +LL | |x| String::from("x".as_ref()); + | ----^^^^^^-- + | | | + | | cannot infer type for type parameter `T` declared on the trait `AsRef` + | this method call resolves to `&T` + | + = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef<OsStr> for str; + - impl AsRef<Path> for str; + - impl AsRef<[u8]> for str; + - impl AsRef<str> for str; + error[E0283]: type annotations needed for `&T` - --> $DIR/issue-72690.rs:15:17 + --> $DIR/issue-72690.rs:18:17 | LL | let _ = "x".as_ref(); | - ^^^^^^ cannot infer type for type parameter `T` declared on the trait `AsRef` | | | consider giving this pattern the explicit type `&T`, where the type parameter `T` is specified | - = note: cannot satisfy `str: AsRef<_>` + = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef<OsStr> for str; + - impl AsRef<Path> for str; + - impl AsRef<[u8]> for str; + - impl AsRef<str> for str; error[E0283]: type annotations needed - --> $DIR/issue-72690.rs:19:5 + --> $DIR/issue-72690.rs:22:5 | LL | String::from("x".as_ref()); | ^^^^^^^^^^^^ cannot infer type for reference `&_` | - = note: cannot satisfy `String: From<&_>` -note: required by `from` - --> $SRC_DIR/core/src/convert/mod.rs:LL:COL + = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate: + - impl<> From<&String> for String; + - impl<> From<&str> for String; + +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:22:22 | -LL | fn from(_: T) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | String::from("x".as_ref()); + | ----^^^^^^-- + | | | + | | cannot infer type for type parameter `T` declared on the trait `AsRef` + | this method call resolves to `&T` + | + = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef<OsStr> for str; + - impl AsRef<Path> for str; + - impl AsRef<[u8]> for str; + - impl AsRef<str> for str; error[E0283]: type annotations needed - --> $DIR/issue-72690.rs:25:5 + --> $DIR/issue-72690.rs:29:5 | LL | String::from("x".as_ref()); | ^^^^^^^^^^^^ cannot infer type for reference `&_` | - = note: cannot satisfy `String: From<&_>` -note: required by `from` - --> $SRC_DIR/core/src/convert/mod.rs:LL:COL + = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate: + - impl<> From<&String> for String; + - impl<> From<&str> for String; + +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:29:22 | -LL | fn from(_: T) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | String::from("x".as_ref()); + | ----^^^^^^-- + | | | + | | cannot infer type for type parameter `T` declared on the trait `AsRef` + | this method call resolves to `&T` + | + = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef<OsStr> for str; + - impl AsRef<Path> for str; + - impl AsRef<[u8]> for str; + - impl AsRef<str> for str; error[E0283]: type annotations needed - --> $DIR/issue-72690.rs:33:5 + --> $DIR/issue-72690.rs:38:5 | LL | String::from("x".as_ref()); | ^^^^^^^^^^^^ cannot infer type for reference `&_` | - = note: cannot satisfy `String: From<&_>` -note: required by `from` - --> $SRC_DIR/core/src/convert/mod.rs:LL:COL + = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate: + - impl<> From<&String> for String; + - impl<> From<&str> for String; + +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:38:22 | -LL | fn from(_: T) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | String::from("x".as_ref()); + | ----^^^^^^-- + | | | + | | cannot infer type for type parameter `T` declared on the trait `AsRef` + | this method call resolves to `&T` + | + = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef<OsStr> for str; + - impl AsRef<Path> for str; + - impl AsRef<[u8]> for str; + - impl AsRef<str> for str; error[E0283]: type annotations needed - --> $DIR/issue-72690.rs:41:5 + --> $DIR/issue-72690.rs:47:5 | LL | String::from("x".as_ref()); | ^^^^^^^^^^^^ cannot infer type for reference `&_` | - = note: cannot satisfy `String: From<&_>` -note: required by `from` - --> $SRC_DIR/core/src/convert/mod.rs:LL:COL + = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate: + - impl<> From<&String> for String; + - impl<> From<&str> for String; + +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:47:22 | -LL | fn from(_: T) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | String::from("x".as_ref()); + | ----^^^^^^-- + | | | + | | cannot infer type for type parameter `T` declared on the trait `AsRef` + | this method call resolves to `&T` + | + = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef<OsStr> for str; + - impl AsRef<Path> for str; + - impl AsRef<[u8]> for str; + - impl AsRef<str> for str; error[E0283]: type annotations needed - --> $DIR/issue-72690.rs:47:5 + --> $DIR/issue-72690.rs:54:5 | LL | String::from("x".as_ref()); | ^^^^^^^^^^^^ cannot infer type for reference `&_` | - = note: cannot satisfy `String: From<&_>` -note: required by `from` - --> $SRC_DIR/core/src/convert/mod.rs:LL:COL + = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate: + - impl<> From<&String> for String; + - impl<> From<&str> for String; + +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:54:22 | -LL | fn from(_: T) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | String::from("x".as_ref()); + | ----^^^^^^-- + | | | + | | cannot infer type for type parameter `T` declared on the trait `AsRef` + | this method call resolves to `&T` + | + = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef<OsStr> for str; + - impl AsRef<Path> for str; + - impl AsRef<[u8]> for str; + - impl AsRef<str> for str; error[E0283]: type annotations needed - --> $DIR/issue-72690.rs:55:5 + --> $DIR/issue-72690.rs:63:5 | LL | String::from("x".as_ref()); | ^^^^^^^^^^^^ cannot infer type for reference `&_` | - = note: cannot satisfy `String: From<&_>` -note: required by `from` - --> $SRC_DIR/core/src/convert/mod.rs:LL:COL + = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate: + - impl<> From<&String> for String; + - impl<> From<&str> for String; + +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:63:22 | -LL | fn from(_: T) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | String::from("x".as_ref()); + | ----^^^^^^-- + | | | + | | cannot infer type for type parameter `T` declared on the trait `AsRef` + | this method call resolves to `&T` + | + = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef<OsStr> for str; + - impl AsRef<Path> for str; + - impl AsRef<[u8]> for str; + - impl AsRef<str> for str; -error: aborting due to 9 previous errors +error: aborting due to 18 previous errors Some errors have detailed explanations: E0282, E0283. For more information about an error, try `rustc --explain E0282`. diff --git a/src/test/ui/issues/issue-73427.stderr b/src/test/ui/issues/issue-73427.stderr index 54df7fccaa..59bb98a340 100644 --- a/src/test/ui/issues/issue-73427.stderr +++ b/src/test/ui/issues/issue-73427.stderr @@ -120,10 +120,10 @@ LL | | } | |_^ help: try to construct one of the enum's variants | -LL | let x = A::TupleWithFields(3); - | ~~~~~~~~~~~~~~~~~~ LL | let x = A::Tuple(3); | ~~~~~~~~ +LL | let x = A::TupleWithFields(3); + | ~~~~~~~~~~~~~~~~~~ error[E0532]: expected tuple struct or tuple variant, found enum `A` --> $DIR/issue-73427.rs:42:12 @@ -145,10 +145,10 @@ LL | | } | |_^ help: try to match against one of the enum's variants | -LL | if let A::TupleWithFields(3) = x { } - | ~~~~~~~~~~~~~~~~~~ LL | if let A::Tuple(3) = x { } | ~~~~~~~~ +LL | if let A::TupleWithFields(3) = x { } + | ~~~~~~~~~~~~~~~~~~ error: aborting due to 6 previous errors diff --git a/src/test/ui/issues/issue-77218.rs b/src/test/ui/issues/issue-77218.rs deleted file mode 100644 index a6a2401795..0000000000 --- a/src/test/ui/issues/issue-77218.rs +++ /dev/null @@ -1,11 +0,0 @@ -fn main() { - let value = [7u8]; - while Some(0) = value.get(0) { //~ ERROR destructuring assignments are unstable - //~| ERROR invalid left-hand side of assignment - //~| ERROR mismatched types - //~| ERROR mismatched types - - // FIXME The following diagnostic should also be emitted - // HELP you might have meant to use pattern matching - } -} diff --git a/src/test/ui/issues/issue-77218.stderr b/src/test/ui/issues/issue-77218.stderr deleted file mode 100644 index ce70c0111b..0000000000 --- a/src/test/ui/issues/issue-77218.stderr +++ /dev/null @@ -1,40 +0,0 @@ -error[E0658]: destructuring assignments are unstable - --> $DIR/issue-77218.rs:3:19 - | -LL | while Some(0) = value.get(0) { - | ------- ^ - | | - | cannot assign to this expression - | - = note: see issue #71126 <https://github.com/rust-lang/rust/issues/71126> for more information - = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable - -error[E0070]: invalid left-hand side of assignment - --> $DIR/issue-77218.rs:3:19 - | -LL | while Some(0) = value.get(0) { - | - ^ - | | - | cannot assign to this expression - -error[E0308]: mismatched types - --> $DIR/issue-77218.rs:3:16 - | -LL | while Some(0) = value.get(0) { - | ^ expected integer, found `&u8` - | -help: consider dereferencing the borrow - | -LL | while Some(*0) = value.get(0) { - | + - -error[E0308]: mismatched types - --> $DIR/issue-77218.rs:3:11 - | -LL | while Some(0) = value.get(0) { - | ^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()` - -error: aborting due to 4 previous errors - -Some errors have detailed explanations: E0070, E0308, E0658. -For more information about an error, try `rustc --explain E0070`. diff --git a/src/test/ui/issues/issue-77218/issue-77218-2.fixed b/src/test/ui/issues/issue-77218/issue-77218-2.fixed new file mode 100644 index 0000000000..06487fe088 --- /dev/null +++ b/src/test/ui/issues/issue-77218/issue-77218-2.fixed @@ -0,0 +1,7 @@ +// run-rustfix +#![feature(destructuring_assignment)] +fn main() { + let value = [7u8]; + while let Some(0) = value.get(0) { //~ ERROR invalid left-hand side of assignment + } +} diff --git a/src/test/ui/issues/issue-77218/issue-77218-2.rs b/src/test/ui/issues/issue-77218/issue-77218-2.rs new file mode 100644 index 0000000000..e19cec08e4 --- /dev/null +++ b/src/test/ui/issues/issue-77218/issue-77218-2.rs @@ -0,0 +1,7 @@ +// run-rustfix +#![feature(destructuring_assignment)] +fn main() { + let value = [7u8]; + while Some(0) = value.get(0) { //~ ERROR invalid left-hand side of assignment + } +} diff --git a/src/test/ui/issues/issue-77218/issue-77218-2.stderr b/src/test/ui/issues/issue-77218/issue-77218-2.stderr new file mode 100644 index 0000000000..8d9eb2219d --- /dev/null +++ b/src/test/ui/issues/issue-77218/issue-77218-2.stderr @@ -0,0 +1,16 @@ +error[E0070]: invalid left-hand side of assignment + --> $DIR/issue-77218-2.rs:5:19 + | +LL | while Some(0) = value.get(0) { + | - ^ + | | + | cannot assign to this expression + | +help: you might have meant to use pattern destructuring + | +LL | while let Some(0) = value.get(0) { + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0070`. diff --git a/src/test/ui/issues/issue-77218/issue-77218.fixed b/src/test/ui/issues/issue-77218/issue-77218.fixed new file mode 100644 index 0000000000..4ea5110902 --- /dev/null +++ b/src/test/ui/issues/issue-77218/issue-77218.fixed @@ -0,0 +1,6 @@ +// run-rustfix +fn main() { + let value = [7u8]; + while let Some(0) = value.get(0) { //~ ERROR destructuring assignments are unstable + } +} diff --git a/src/test/ui/issues/issue-77218/issue-77218.rs b/src/test/ui/issues/issue-77218/issue-77218.rs new file mode 100644 index 0000000000..0f3c12f563 --- /dev/null +++ b/src/test/ui/issues/issue-77218/issue-77218.rs @@ -0,0 +1,6 @@ +// run-rustfix +fn main() { + let value = [7u8]; + while Some(0) = value.get(0) { //~ ERROR destructuring assignments are unstable + } +} diff --git a/src/test/ui/issues/issue-77218/issue-77218.stderr b/src/test/ui/issues/issue-77218/issue-77218.stderr new file mode 100644 index 0000000000..54f49609a4 --- /dev/null +++ b/src/test/ui/issues/issue-77218/issue-77218.stderr @@ -0,0 +1,18 @@ +error[E0658]: destructuring assignments are unstable + --> $DIR/issue-77218.rs:4:19 + | +LL | while Some(0) = value.get(0) { + | ------- ^ + | | + | cannot assign to this expression + | + = note: see issue #71126 <https://github.com/rust-lang/rust/issues/71126> for more information + = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable +help: you might have meant to use pattern destructuring + | +LL | while let Some(0) = value.get(0) { + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/issues/issue-811.rs b/src/test/ui/issues/issue-811.rs deleted file mode 100644 index f929d38881..0000000000 --- a/src/test/ui/issues/issue-811.rs +++ /dev/null @@ -1,26 +0,0 @@ -// run-fail -// error-pattern:quux -// ignore-emscripten no processes - -use std::marker::PhantomData; - -fn test00_start(ch: Chan<isize>, message: isize) { - send(ch, message); -} - -type TaskId = isize; -type PortId = isize; - -struct Chan<T> { - task: TaskId, - port: PortId, - marker: PhantomData<*mut T>, -} - -fn send<T: Send>(_ch: Chan<T>, _data: T) { - panic!(); -} - -fn main() { - panic!("quux"); -} diff --git a/src/test/ui/iterators/integral.stderr b/src/test/ui/iterators/integral.stderr index 60b2cbfdf4..5e2744bab9 100644 --- a/src/test/ui/iterators/integral.stderr +++ b/src/test/ui/iterators/integral.stderr @@ -7,11 +7,6 @@ LL | for _ in 42 {} = help: the trait `Iterator` is not implemented for `{integer}` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required because of the requirements on the impl of `IntoIterator` for `{integer}` -note: required by `into_iter` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `u8` is not an iterator --> $DIR/integral.rs:4:14 @@ -22,11 +17,6 @@ LL | for _ in 42 as u8 {} = help: the trait `Iterator` is not implemented for `u8` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required because of the requirements on the impl of `IntoIterator` for `u8` -note: required by `into_iter` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `i8` is not an iterator --> $DIR/integral.rs:6:14 @@ -37,11 +27,6 @@ LL | for _ in 42 as i8 {} = help: the trait `Iterator` is not implemented for `i8` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required because of the requirements on the impl of `IntoIterator` for `i8` -note: required by `into_iter` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `u16` is not an iterator --> $DIR/integral.rs:8:14 @@ -52,11 +37,6 @@ LL | for _ in 42 as u16 {} = help: the trait `Iterator` is not implemented for `u16` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required because of the requirements on the impl of `IntoIterator` for `u16` -note: required by `into_iter` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `i16` is not an iterator --> $DIR/integral.rs:10:14 @@ -67,11 +47,6 @@ LL | for _ in 42 as i16 {} = help: the trait `Iterator` is not implemented for `i16` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required because of the requirements on the impl of `IntoIterator` for `i16` -note: required by `into_iter` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `u32` is not an iterator --> $DIR/integral.rs:12:14 @@ -82,11 +57,6 @@ LL | for _ in 42 as u32 {} = help: the trait `Iterator` is not implemented for `u32` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required because of the requirements on the impl of `IntoIterator` for `u32` -note: required by `into_iter` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `i32` is not an iterator --> $DIR/integral.rs:14:14 @@ -97,11 +67,6 @@ LL | for _ in 42 as i32 {} = help: the trait `Iterator` is not implemented for `i32` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required because of the requirements on the impl of `IntoIterator` for `i32` -note: required by `into_iter` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `u64` is not an iterator --> $DIR/integral.rs:16:14 @@ -112,11 +77,6 @@ LL | for _ in 42 as u64 {} = help: the trait `Iterator` is not implemented for `u64` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required because of the requirements on the impl of `IntoIterator` for `u64` -note: required by `into_iter` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `i64` is not an iterator --> $DIR/integral.rs:18:14 @@ -127,11 +87,6 @@ LL | for _ in 42 as i64 {} = help: the trait `Iterator` is not implemented for `i64` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required because of the requirements on the impl of `IntoIterator` for `i64` -note: required by `into_iter` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `usize` is not an iterator --> $DIR/integral.rs:20:14 @@ -142,11 +97,6 @@ LL | for _ in 42 as usize {} = help: the trait `Iterator` is not implemented for `usize` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required because of the requirements on the impl of `IntoIterator` for `usize` -note: required by `into_iter` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `isize` is not an iterator --> $DIR/integral.rs:22:14 @@ -157,11 +107,6 @@ LL | for _ in 42 as isize {} = help: the trait `Iterator` is not implemented for `isize` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required because of the requirements on the impl of `IntoIterator` for `isize` -note: required by `into_iter` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `{float}` is not an iterator --> $DIR/integral.rs:24:14 @@ -171,11 +116,6 @@ LL | for _ in 42.0 {} | = help: the trait `Iterator` is not implemented for `{float}` = note: required because of the requirements on the impl of `IntoIterator` for `{float}` -note: required by `into_iter` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 12 previous errors diff --git a/src/test/ui/iterators/into-iter-on-arrays-2021.rs b/src/test/ui/iterators/into-iter-on-arrays-2021.rs index ec54ed0051..158317efe4 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-2021.rs +++ b/src/test/ui/iterators/into-iter-on-arrays-2021.rs @@ -1,6 +1,5 @@ // check-pass // edition:2021 -// compile-flags: -Zunstable-options use std::array::IntoIter; use std::ops::Deref; diff --git a/src/test/ui/iterators/ranges.stderr b/src/test/ui/iterators/ranges.stderr index fdc33862c0..440a8960a4 100644 --- a/src/test/ui/iterators/ranges.stderr +++ b/src/test/ui/iterators/ranges.stderr @@ -7,11 +7,6 @@ LL | for _ in ..10 {} = help: the trait `Iterator` is not implemented for `RangeTo<{integer}>` = note: `..end` is a `RangeTo`, which cannot be iterated on; you might have meant to have a bounded `Range`: `0..end` = note: required because of the requirements on the impl of `IntoIterator` for `RangeTo<{integer}>` -note: required by `into_iter` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `RangeToInclusive<{integer}>` is not an iterator --> $DIR/ranges.rs:4:14 @@ -22,11 +17,6 @@ LL | for _ in ..=10 {} = help: the trait `Iterator` is not implemented for `RangeToInclusive<{integer}>` = note: `..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant to have a bounded `RangeInclusive`: `0..=end` = note: required because of the requirements on the impl of `IntoIterator` for `RangeToInclusive<{integer}>` -note: required by `into_iter` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/iterators/rsplit-clone.rs b/src/test/ui/iterators/rsplit-clone.rs new file mode 100644 index 0000000000..911da74295 --- /dev/null +++ b/src/test/ui/iterators/rsplit-clone.rs @@ -0,0 +1,11 @@ +// check-pass + +// RSplit<T, P> previously required T: Clone in order to be Clone + +struct NotClone; + +fn main() { + let elements = [NotClone, NotClone, NotClone]; + let rsplit = elements.rsplit(|_| false); + rsplit.clone(); +} diff --git a/src/test/ui/iterators/string.stderr b/src/test/ui/iterators/string.stderr index f7089be277..d9c40fe1ba 100644 --- a/src/test/ui/iterators/string.stderr +++ b/src/test/ui/iterators/string.stderr @@ -6,11 +6,6 @@ LL | for _ in "".to_owned() {} | = help: the trait `Iterator` is not implemented for `String` = note: required because of the requirements on the impl of `IntoIterator` for `String` -note: required by `into_iter` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `&str` is not an iterator --> $DIR/string.rs:4:14 @@ -20,11 +15,6 @@ LL | for _ in "" {} | = help: the trait `Iterator` is not implemented for `&str` = note: required because of the requirements on the impl of `IntoIterator` for `&str` -note: required by `into_iter` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/keyword-changes-2012-07-31.rs b/src/test/ui/keyword-changes-2012-07-31.rs deleted file mode 100644 index 1b38527ec2..0000000000 --- a/src/test/ui/keyword-changes-2012-07-31.rs +++ /dev/null @@ -1,20 +0,0 @@ -// run-pass - -#![allow(dead_code)] -// return -> return -// mod -> module -// match -> match - -// pretty-expanded FIXME #23616 - -pub fn main() { -} - -mod foo { -} - -fn bar() -> isize { - match 0 { - _ => { 0 } - } -} diff --git a/src/test/ui/issues/issue-19660.rs b/src/test/ui/lang-items/issue-19660.rs similarity index 100% rename from src/test/ui/issues/issue-19660.rs rename to src/test/ui/lang-items/issue-19660.rs diff --git a/src/test/ui/issues/issue-19660.stderr b/src/test/ui/lang-items/issue-19660.stderr similarity index 100% rename from src/test/ui/issues/issue-19660.stderr rename to src/test/ui/lang-items/issue-19660.stderr diff --git a/src/test/ui/issues/issue-31076.rs b/src/test/ui/lang-items/issue-31076.rs similarity index 100% rename from src/test/ui/issues/issue-31076.rs rename to src/test/ui/lang-items/issue-31076.rs diff --git a/src/test/ui/issues/issue-31076.stderr b/src/test/ui/lang-items/issue-31076.stderr similarity index 100% rename from src/test/ui/issues/issue-31076.stderr rename to src/test/ui/lang-items/issue-31076.stderr diff --git a/src/test/ui/lang-items/issue-87573.rs b/src/test/ui/lang-items/issue-87573.rs new file mode 100644 index 0000000000..aeb0c245a7 --- /dev/null +++ b/src/test/ui/lang-items/issue-87573.rs @@ -0,0 +1,28 @@ +// Regression test for #87573, ensures that duplicate lang items or invalid generics +// for lang items doesn't cause ICE. + +#![feature(no_core, lang_items)] +#![no_core] +#![crate_type = "lib"] + +pub static STATIC_BOOL: bool = true; + +#[lang = "sized"] +trait Sized {} + +#[lang = "copy"] +trait Copy {} + +#[lang = "sync"] +trait Sync {} +impl Sync for bool {} + +#[lang = "drop_in_place"] +//~^ ERROR: `drop_in_place` language item must be applied to a function with at least 1 generic argument +fn drop_fn() { + while false {} +} + +#[lang = "start"] +//~^ ERROR: `start` language item must be applied to a function with 1 generic argument +fn start(){} diff --git a/src/test/ui/lang-items/issue-87573.stderr b/src/test/ui/lang-items/issue-87573.stderr new file mode 100644 index 0000000000..25560cfa0e --- /dev/null +++ b/src/test/ui/lang-items/issue-87573.stderr @@ -0,0 +1,21 @@ +error[E0718]: `drop_in_place` language item must be applied to a function with at least 1 generic argument + --> $DIR/issue-87573.rs:20:1 + | +LL | #[lang = "drop_in_place"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | fn drop_fn() { + | - this function has 0 generic arguments + +error[E0718]: `start` language item must be applied to a function with 1 generic argument + --> $DIR/issue-87573.rs:26:1 + | +LL | #[lang = "start"] + | ^^^^^^^^^^^^^^^^^ +LL | +LL | fn start(){} + | - this function has 0 generic arguments + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0718`. diff --git a/src/test/ui/no_owned_box_lang_item.rs b/src/test/ui/lang-items/no_owned_box_lang_item.rs similarity index 100% rename from src/test/ui/no_owned_box_lang_item.rs rename to src/test/ui/lang-items/no_owned_box_lang_item.rs diff --git a/src/test/ui/no_owned_box_lang_item.stderr b/src/test/ui/lang-items/no_owned_box_lang_item.stderr similarity index 100% rename from src/test/ui/no_owned_box_lang_item.stderr rename to src/test/ui/lang-items/no_owned_box_lang_item.stderr diff --git a/src/test/ui/required-lang-item.rs b/src/test/ui/lang-items/required-lang-item.rs similarity index 100% rename from src/test/ui/required-lang-item.rs rename to src/test/ui/lang-items/required-lang-item.rs diff --git a/src/test/ui/required-lang-item.stderr b/src/test/ui/lang-items/required-lang-item.stderr similarity index 100% rename from src/test/ui/required-lang-item.stderr rename to src/test/ui/lang-items/required-lang-item.stderr diff --git a/src/test/ui/layout/debug.stderr b/src/test/ui/layout/debug.stderr index 1a371c6b17..418f780d62 100644 --- a/src/test/ui/layout/debug.stderr +++ b/src/test/ui/layout/debug.stderr @@ -1,345 +1,345 @@ error: layout_of(E) = Layout { - fields: Arbitrary { - offsets: [ - Size { - raw: 0, - }, - ], - memory_index: [ - 0, - ], - }, - variants: Multiple { - tag: Scalar { - value: Int( - I32, - false, - ), - valid_range: 0..=0, - }, - tag_encoding: Direct, - tag_field: 0, - variants: [ - Layout { - fields: Arbitrary { - offsets: [], - memory_index: [], - }, - variants: Single { - index: 0, - }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, - pref: $PREF_ALIGN, - }, - size: Size { - raw: 4, - }, - }, - Layout { - fields: Arbitrary { - offsets: [ - Size { - raw: 4, - }, - Size { - raw: 4, - }, - Size { - raw: 8, - }, - ], - memory_index: [ - 0, - 1, - 2, - ], - }, - variants: Single { - index: 1, - }, - abi: Uninhabited, - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, - pref: $PREF_ALIGN, - }, - size: Size { - raw: 12, - }, - }, - ], - }, - abi: Aggregate { - sized: true, - }, - largest_niche: Some( - Niche { - offset: Size { - raw: 0, - }, - scalar: Scalar { - value: Int( - I32, - false, - ), - valid_range: 0..=0, - }, - }, - ), - align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, - pref: $PREF_ALIGN, - }, - size: Size { - raw: 12, - }, -} + fields: Arbitrary { + offsets: [ + Size { + raw: 0, + }, + ], + memory_index: [ + 0, + ], + }, + variants: Multiple { + tag: Scalar { + value: Int( + I32, + false, + ), + valid_range: 0..=0, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + variants: Single { + index: 0, + }, + abi: Aggregate { + sized: true, + }, + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align { + pow2: 0, + }, + pref: $PREF_ALIGN, + }, + size: Size { + raw: 4, + }, + }, + Layout { + fields: Arbitrary { + offsets: [ + Size { + raw: 4, + }, + Size { + raw: 4, + }, + Size { + raw: 8, + }, + ], + memory_index: [ + 0, + 1, + 2, + ], + }, + variants: Single { + index: 1, + }, + abi: Uninhabited, + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align { + pow2: 2, + }, + pref: $PREF_ALIGN, + }, + size: Size { + raw: 12, + }, + }, + ], + }, + abi: Aggregate { + sized: true, + }, + largest_niche: Some( + Niche { + offset: Size { + raw: 0, + }, + scalar: Scalar { + value: Int( + I32, + false, + ), + valid_range: 0..=0, + }, + }, + ), + align: AbiAndPrefAlign { + abi: Align { + pow2: 2, + }, + pref: $PREF_ALIGN, + }, + size: Size { + raw: 12, + }, + } --> $DIR/debug.rs:6:1 | LL | enum E { Foo, Bar(!, i32, i32) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: layout_of(S) = Layout { - fields: Arbitrary { - offsets: [ - Size { - raw: 0, - }, - Size { - raw: 0, - }, - Size { - raw: 4, - }, - ], - memory_index: [ - 1, - 0, - 2, - ], - }, - variants: Single { - index: 0, - }, - abi: ScalarPair( - Scalar { - value: Int( - I32, - true, - ), - valid_range: 0..=4294967295, - }, - Scalar { - value: Int( - I32, - true, - ), - valid_range: 0..=4294967295, - }, - ), - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, - pref: $PREF_ALIGN, - }, - size: Size { - raw: 8, - }, -} + fields: Arbitrary { + offsets: [ + Size { + raw: 0, + }, + Size { + raw: 0, + }, + Size { + raw: 4, + }, + ], + memory_index: [ + 1, + 0, + 2, + ], + }, + variants: Single { + index: 0, + }, + abi: ScalarPair( + Scalar { + value: Int( + I32, + true, + ), + valid_range: 0..=4294967295, + }, + Scalar { + value: Int( + I32, + true, + ), + valid_range: 0..=4294967295, + }, + ), + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align { + pow2: 2, + }, + pref: $PREF_ALIGN, + }, + size: Size { + raw: 8, + }, + } --> $DIR/debug.rs:9:1 | LL | struct S { f1: i32, f2: (), f3: i32 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: layout_of(U) = Layout { - fields: Union( - 2, - ), - variants: Single { - index: 0, - }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, - pref: $PREF_ALIGN, - }, - size: Size { - raw: 8, - }, -} + fields: Union( + 2, + ), + variants: Single { + index: 0, + }, + abi: Aggregate { + sized: true, + }, + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align { + pow2: 2, + }, + pref: $PREF_ALIGN, + }, + size: Size { + raw: 8, + }, + } --> $DIR/debug.rs:12:1 | LL | union U { f1: (i32, i32), f3: i32 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: layout_of(std::result::Result<i32, i32>) = Layout { - fields: Arbitrary { - offsets: [ - Size { - raw: 0, - }, - ], - memory_index: [ - 0, - ], - }, - variants: Multiple { - tag: Scalar { - value: Int( - I32, - false, - ), - valid_range: 0..=1, - }, - tag_encoding: Direct, - tag_field: 0, - variants: [ - Layout { - fields: Arbitrary { - offsets: [ - Size { - raw: 4, - }, - ], - memory_index: [ - 0, - ], - }, - variants: Single { - index: 0, - }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, - pref: $PREF_ALIGN, - }, - size: Size { - raw: 8, - }, - }, - Layout { - fields: Arbitrary { - offsets: [ - Size { - raw: 4, - }, - ], - memory_index: [ - 0, - ], - }, - variants: Single { - index: 1, - }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, - pref: $PREF_ALIGN, - }, - size: Size { - raw: 8, - }, - }, - ], - }, - abi: ScalarPair( - Scalar { - value: Int( - I32, - false, - ), - valid_range: 0..=1, - }, - Scalar { - value: Int( - I32, - true, - ), - valid_range: 0..=4294967295, - }, - ), - largest_niche: Some( - Niche { - offset: Size { - raw: 0, - }, - scalar: Scalar { - value: Int( - I32, - false, - ), - valid_range: 0..=1, - }, - }, - ), - align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, - pref: $PREF_ALIGN, - }, - size: Size { - raw: 8, - }, -} + fields: Arbitrary { + offsets: [ + Size { + raw: 0, + }, + ], + memory_index: [ + 0, + ], + }, + variants: Multiple { + tag: Scalar { + value: Int( + I32, + false, + ), + valid_range: 0..=1, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + fields: Arbitrary { + offsets: [ + Size { + raw: 4, + }, + ], + memory_index: [ + 0, + ], + }, + variants: Single { + index: 0, + }, + abi: Aggregate { + sized: true, + }, + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align { + pow2: 2, + }, + pref: $PREF_ALIGN, + }, + size: Size { + raw: 8, + }, + }, + Layout { + fields: Arbitrary { + offsets: [ + Size { + raw: 4, + }, + ], + memory_index: [ + 0, + ], + }, + variants: Single { + index: 1, + }, + abi: Aggregate { + sized: true, + }, + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align { + pow2: 2, + }, + pref: $PREF_ALIGN, + }, + size: Size { + raw: 8, + }, + }, + ], + }, + abi: ScalarPair( + Scalar { + value: Int( + I32, + false, + ), + valid_range: 0..=1, + }, + Scalar { + value: Int( + I32, + true, + ), + valid_range: 0..=4294967295, + }, + ), + largest_niche: Some( + Niche { + offset: Size { + raw: 0, + }, + scalar: Scalar { + value: Int( + I32, + false, + ), + valid_range: 0..=1, + }, + }, + ), + align: AbiAndPrefAlign { + abi: Align { + pow2: 2, + }, + pref: $PREF_ALIGN, + }, + size: Size { + raw: 8, + }, + } --> $DIR/debug.rs:15:1 | LL | type Test = Result<i32, i32>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: layout_of(i32) = Layout { - fields: Primitive, - variants: Single { - index: 0, - }, - abi: Scalar( - Scalar { - value: Int( - I32, - true, - ), - valid_range: 0..=4294967295, - }, - ), - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, - pref: $PREF_ALIGN, - }, - size: Size { - raw: 4, - }, -} + fields: Primitive, + variants: Single { + index: 0, + }, + abi: Scalar( + Scalar { + value: Int( + I32, + true, + ), + valid_range: 0..=4294967295, + }, + ), + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align { + pow2: 2, + }, + pref: $PREF_ALIGN, + }, + size: Size { + raw: 4, + }, + } --> $DIR/debug.rs:18:1 | LL | type T = impl std::fmt::Debug; diff --git a/src/test/ui/layout/hexagon-enum.stderr b/src/test/ui/layout/hexagon-enum.stderr index d4676a5afb..39b23cb4b5 100644 --- a/src/test/ui/layout/hexagon-enum.stderr +++ b/src/test/ui/layout/hexagon-enum.stderr @@ -1,438 +1,438 @@ error: layout_of(A) = Layout { - fields: Arbitrary { - offsets: [ - Size { - raw: 0, - }, - ], - memory_index: [ - 0, - ], - }, - variants: Multiple { - tag: Scalar { - value: Int( - I8, - false, - ), - valid_range: 0..=0, - }, - tag_encoding: Direct, - tag_field: 0, - variants: [ - Layout { - fields: Arbitrary { - offsets: [], - memory_index: [], - }, - variants: Single { - index: 0, - }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, - pref: Align { - pow2: 0, - }, - }, - size: Size { - raw: 1, - }, - }, - ], - }, - abi: Scalar( - Scalar { - value: Int( - I8, - false, - ), - valid_range: 0..=0, - }, - ), - largest_niche: Some( - Niche { - offset: Size { - raw: 0, - }, - scalar: Scalar { - value: Int( - I8, - false, - ), - valid_range: 0..=0, - }, - }, - ), - align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, - pref: Align { - pow2: 0, - }, - }, - size: Size { - raw: 1, - }, -} + fields: Arbitrary { + offsets: [ + Size { + raw: 0, + }, + ], + memory_index: [ + 0, + ], + }, + variants: Multiple { + tag: Scalar { + value: Int( + I8, + false, + ), + valid_range: 0..=0, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + variants: Single { + index: 0, + }, + abi: Aggregate { + sized: true, + }, + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align { + pow2: 0, + }, + pref: Align { + pow2: 0, + }, + }, + size: Size { + raw: 1, + }, + }, + ], + }, + abi: Scalar( + Scalar { + value: Int( + I8, + false, + ), + valid_range: 0..=0, + }, + ), + largest_niche: Some( + Niche { + offset: Size { + raw: 0, + }, + scalar: Scalar { + value: Int( + I8, + false, + ), + valid_range: 0..=0, + }, + }, + ), + align: AbiAndPrefAlign { + abi: Align { + pow2: 0, + }, + pref: Align { + pow2: 0, + }, + }, + size: Size { + raw: 1, + }, + } --> $DIR/hexagon-enum.rs:16:1 | LL | enum A { Apple } | ^^^^^^^^^^^^^^^^ error: layout_of(B) = Layout { - fields: Arbitrary { - offsets: [ - Size { - raw: 0, - }, - ], - memory_index: [ - 0, - ], - }, - variants: Multiple { - tag: Scalar { - value: Int( - I8, - false, - ), - valid_range: 255..=255, - }, - tag_encoding: Direct, - tag_field: 0, - variants: [ - Layout { - fields: Arbitrary { - offsets: [], - memory_index: [], - }, - variants: Single { - index: 0, - }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, - pref: Align { - pow2: 0, - }, - }, - size: Size { - raw: 1, - }, - }, - ], - }, - abi: Scalar( - Scalar { - value: Int( - I8, - false, - ), - valid_range: 255..=255, - }, - ), - largest_niche: Some( - Niche { - offset: Size { - raw: 0, - }, - scalar: Scalar { - value: Int( - I8, - false, - ), - valid_range: 255..=255, - }, - }, - ), - align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, - pref: Align { - pow2: 0, - }, - }, - size: Size { - raw: 1, - }, -} + fields: Arbitrary { + offsets: [ + Size { + raw: 0, + }, + ], + memory_index: [ + 0, + ], + }, + variants: Multiple { + tag: Scalar { + value: Int( + I8, + false, + ), + valid_range: 255..=255, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + variants: Single { + index: 0, + }, + abi: Aggregate { + sized: true, + }, + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align { + pow2: 0, + }, + pref: Align { + pow2: 0, + }, + }, + size: Size { + raw: 1, + }, + }, + ], + }, + abi: Scalar( + Scalar { + value: Int( + I8, + false, + ), + valid_range: 255..=255, + }, + ), + largest_niche: Some( + Niche { + offset: Size { + raw: 0, + }, + scalar: Scalar { + value: Int( + I8, + false, + ), + valid_range: 255..=255, + }, + }, + ), + align: AbiAndPrefAlign { + abi: Align { + pow2: 0, + }, + pref: Align { + pow2: 0, + }, + }, + size: Size { + raw: 1, + }, + } --> $DIR/hexagon-enum.rs:20:1 | LL | enum B { Banana = 255, } | ^^^^^^^^^^^^^^^^^^^^^^^^ error: layout_of(C) = Layout { - fields: Arbitrary { - offsets: [ - Size { - raw: 0, - }, - ], - memory_index: [ - 0, - ], - }, - variants: Multiple { - tag: Scalar { - value: Int( - I16, - false, - ), - valid_range: 256..=256, - }, - tag_encoding: Direct, - tag_field: 0, - variants: [ - Layout { - fields: Arbitrary { - offsets: [], - memory_index: [], - }, - variants: Single { - index: 0, - }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align { - pow2: 1, - }, - pref: Align { - pow2: 1, - }, - }, - size: Size { - raw: 2, - }, - }, - ], - }, - abi: Scalar( - Scalar { - value: Int( - I16, - false, - ), - valid_range: 256..=256, - }, - ), - largest_niche: Some( - Niche { - offset: Size { - raw: 0, - }, - scalar: Scalar { - value: Int( - I16, - false, - ), - valid_range: 256..=256, - }, - }, - ), - align: AbiAndPrefAlign { - abi: Align { - pow2: 1, - }, - pref: Align { - pow2: 1, - }, - }, - size: Size { - raw: 2, - }, -} + fields: Arbitrary { + offsets: [ + Size { + raw: 0, + }, + ], + memory_index: [ + 0, + ], + }, + variants: Multiple { + tag: Scalar { + value: Int( + I16, + false, + ), + valid_range: 256..=256, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + variants: Single { + index: 0, + }, + abi: Aggregate { + sized: true, + }, + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align { + pow2: 1, + }, + pref: Align { + pow2: 1, + }, + }, + size: Size { + raw: 2, + }, + }, + ], + }, + abi: Scalar( + Scalar { + value: Int( + I16, + false, + ), + valid_range: 256..=256, + }, + ), + largest_niche: Some( + Niche { + offset: Size { + raw: 0, + }, + scalar: Scalar { + value: Int( + I16, + false, + ), + valid_range: 256..=256, + }, + }, + ), + align: AbiAndPrefAlign { + abi: Align { + pow2: 1, + }, + pref: Align { + pow2: 1, + }, + }, + size: Size { + raw: 2, + }, + } --> $DIR/hexagon-enum.rs:24:1 | LL | enum C { Chaenomeles = 256, } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: layout_of(P) = Layout { - fields: Arbitrary { - offsets: [ - Size { - raw: 0, - }, - ], - memory_index: [ - 0, - ], - }, - variants: Multiple { - tag: Scalar { - value: Int( - I32, - false, - ), - valid_range: 268435456..=268435456, - }, - tag_encoding: Direct, - tag_field: 0, - variants: [ - Layout { - fields: Arbitrary { - offsets: [], - memory_index: [], - }, - variants: Single { - index: 0, - }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, - pref: Align { - pow2: 2, - }, - }, - size: Size { - raw: 4, - }, - }, - ], - }, - abi: Scalar( - Scalar { - value: Int( - I32, - false, - ), - valid_range: 268435456..=268435456, - }, - ), - largest_niche: Some( - Niche { - offset: Size { - raw: 0, - }, - scalar: Scalar { - value: Int( - I32, - false, - ), - valid_range: 268435456..=268435456, - }, - }, - ), - align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, - pref: Align { - pow2: 2, - }, - }, - size: Size { - raw: 4, - }, -} + fields: Arbitrary { + offsets: [ + Size { + raw: 0, + }, + ], + memory_index: [ + 0, + ], + }, + variants: Multiple { + tag: Scalar { + value: Int( + I32, + false, + ), + valid_range: 268435456..=268435456, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + variants: Single { + index: 0, + }, + abi: Aggregate { + sized: true, + }, + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align { + pow2: 2, + }, + pref: Align { + pow2: 2, + }, + }, + size: Size { + raw: 4, + }, + }, + ], + }, + abi: Scalar( + Scalar { + value: Int( + I32, + false, + ), + valid_range: 268435456..=268435456, + }, + ), + largest_niche: Some( + Niche { + offset: Size { + raw: 0, + }, + scalar: Scalar { + value: Int( + I32, + false, + ), + valid_range: 268435456..=268435456, + }, + }, + ), + align: AbiAndPrefAlign { + abi: Align { + pow2: 2, + }, + pref: Align { + pow2: 2, + }, + }, + size: Size { + raw: 4, + }, + } --> $DIR/hexagon-enum.rs:28:1 | LL | enum P { Peach = 0x1000_0000isize, } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: layout_of(T) = Layout { - fields: Arbitrary { - offsets: [ - Size { - raw: 0, - }, - ], - memory_index: [ - 0, - ], - }, - variants: Multiple { - tag: Scalar { - value: Int( - I32, - true, - ), - valid_range: 2164260864..=2164260864, - }, - tag_encoding: Direct, - tag_field: 0, - variants: [ - Layout { - fields: Arbitrary { - offsets: [], - memory_index: [], - }, - variants: Single { - index: 0, - }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, - pref: Align { - pow2: 2, - }, - }, - size: Size { - raw: 4, - }, - }, - ], - }, - abi: Scalar( - Scalar { - value: Int( - I32, - true, - ), - valid_range: 2164260864..=2164260864, - }, - ), - largest_niche: Some( - Niche { - offset: Size { - raw: 0, - }, - scalar: Scalar { - value: Int( - I32, - true, - ), - valid_range: 2164260864..=2164260864, - }, - }, - ), - align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, - pref: Align { - pow2: 2, - }, - }, - size: Size { - raw: 4, - }, -} + fields: Arbitrary { + offsets: [ + Size { + raw: 0, + }, + ], + memory_index: [ + 0, + ], + }, + variants: Multiple { + tag: Scalar { + value: Int( + I32, + true, + ), + valid_range: 2164260864..=2164260864, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + variants: Single { + index: 0, + }, + abi: Aggregate { + sized: true, + }, + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align { + pow2: 2, + }, + pref: Align { + pow2: 2, + }, + }, + size: Size { + raw: 4, + }, + }, + ], + }, + abi: Scalar( + Scalar { + value: Int( + I32, + true, + ), + valid_range: 2164260864..=2164260864, + }, + ), + largest_niche: Some( + Niche { + offset: Size { + raw: 0, + }, + scalar: Scalar { + value: Int( + I32, + true, + ), + valid_range: 2164260864..=2164260864, + }, + }, + ), + align: AbiAndPrefAlign { + abi: Align { + pow2: 2, + }, + pref: Align { + pow2: 2, + }, + }, + size: Size { + raw: 4, + }, + } --> $DIR/hexagon-enum.rs:34:1 | LL | enum T { Tangerine = TANGERINE as isize } diff --git a/src/test/ui/layout/thumb-enum.stderr b/src/test/ui/layout/thumb-enum.stderr index 898a61b904..144ab02792 100644 --- a/src/test/ui/layout/thumb-enum.stderr +++ b/src/test/ui/layout/thumb-enum.stderr @@ -1,438 +1,438 @@ error: layout_of(A) = Layout { - fields: Arbitrary { - offsets: [ - Size { - raw: 0, - }, - ], - memory_index: [ - 0, - ], - }, - variants: Multiple { - tag: Scalar { - value: Int( - I8, - false, - ), - valid_range: 0..=0, - }, - tag_encoding: Direct, - tag_field: 0, - variants: [ - Layout { - fields: Arbitrary { - offsets: [], - memory_index: [], - }, - variants: Single { - index: 0, - }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, - pref: Align { - pow2: 2, - }, - }, - size: Size { - raw: 1, - }, - }, - ], - }, - abi: Scalar( - Scalar { - value: Int( - I8, - false, - ), - valid_range: 0..=0, - }, - ), - largest_niche: Some( - Niche { - offset: Size { - raw: 0, - }, - scalar: Scalar { - value: Int( - I8, - false, - ), - valid_range: 0..=0, - }, - }, - ), - align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, - pref: Align { - pow2: 2, - }, - }, - size: Size { - raw: 1, - }, -} + fields: Arbitrary { + offsets: [ + Size { + raw: 0, + }, + ], + memory_index: [ + 0, + ], + }, + variants: Multiple { + tag: Scalar { + value: Int( + I8, + false, + ), + valid_range: 0..=0, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + variants: Single { + index: 0, + }, + abi: Aggregate { + sized: true, + }, + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align { + pow2: 0, + }, + pref: Align { + pow2: 2, + }, + }, + size: Size { + raw: 1, + }, + }, + ], + }, + abi: Scalar( + Scalar { + value: Int( + I8, + false, + ), + valid_range: 0..=0, + }, + ), + largest_niche: Some( + Niche { + offset: Size { + raw: 0, + }, + scalar: Scalar { + value: Int( + I8, + false, + ), + valid_range: 0..=0, + }, + }, + ), + align: AbiAndPrefAlign { + abi: Align { + pow2: 0, + }, + pref: Align { + pow2: 2, + }, + }, + size: Size { + raw: 1, + }, + } --> $DIR/thumb-enum.rs:16:1 | LL | enum A { Apple } | ^^^^^^^^^^^^^^^^ error: layout_of(B) = Layout { - fields: Arbitrary { - offsets: [ - Size { - raw: 0, - }, - ], - memory_index: [ - 0, - ], - }, - variants: Multiple { - tag: Scalar { - value: Int( - I8, - false, - ), - valid_range: 255..=255, - }, - tag_encoding: Direct, - tag_field: 0, - variants: [ - Layout { - fields: Arbitrary { - offsets: [], - memory_index: [], - }, - variants: Single { - index: 0, - }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, - pref: Align { - pow2: 2, - }, - }, - size: Size { - raw: 1, - }, - }, - ], - }, - abi: Scalar( - Scalar { - value: Int( - I8, - false, - ), - valid_range: 255..=255, - }, - ), - largest_niche: Some( - Niche { - offset: Size { - raw: 0, - }, - scalar: Scalar { - value: Int( - I8, - false, - ), - valid_range: 255..=255, - }, - }, - ), - align: AbiAndPrefAlign { - abi: Align { - pow2: 0, - }, - pref: Align { - pow2: 2, - }, - }, - size: Size { - raw: 1, - }, -} + fields: Arbitrary { + offsets: [ + Size { + raw: 0, + }, + ], + memory_index: [ + 0, + ], + }, + variants: Multiple { + tag: Scalar { + value: Int( + I8, + false, + ), + valid_range: 255..=255, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + variants: Single { + index: 0, + }, + abi: Aggregate { + sized: true, + }, + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align { + pow2: 0, + }, + pref: Align { + pow2: 2, + }, + }, + size: Size { + raw: 1, + }, + }, + ], + }, + abi: Scalar( + Scalar { + value: Int( + I8, + false, + ), + valid_range: 255..=255, + }, + ), + largest_niche: Some( + Niche { + offset: Size { + raw: 0, + }, + scalar: Scalar { + value: Int( + I8, + false, + ), + valid_range: 255..=255, + }, + }, + ), + align: AbiAndPrefAlign { + abi: Align { + pow2: 0, + }, + pref: Align { + pow2: 2, + }, + }, + size: Size { + raw: 1, + }, + } --> $DIR/thumb-enum.rs:20:1 | LL | enum B { Banana = 255, } | ^^^^^^^^^^^^^^^^^^^^^^^^ error: layout_of(C) = Layout { - fields: Arbitrary { - offsets: [ - Size { - raw: 0, - }, - ], - memory_index: [ - 0, - ], - }, - variants: Multiple { - tag: Scalar { - value: Int( - I16, - false, - ), - valid_range: 256..=256, - }, - tag_encoding: Direct, - tag_field: 0, - variants: [ - Layout { - fields: Arbitrary { - offsets: [], - memory_index: [], - }, - variants: Single { - index: 0, - }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align { - pow2: 1, - }, - pref: Align { - pow2: 2, - }, - }, - size: Size { - raw: 2, - }, - }, - ], - }, - abi: Scalar( - Scalar { - value: Int( - I16, - false, - ), - valid_range: 256..=256, - }, - ), - largest_niche: Some( - Niche { - offset: Size { - raw: 0, - }, - scalar: Scalar { - value: Int( - I16, - false, - ), - valid_range: 256..=256, - }, - }, - ), - align: AbiAndPrefAlign { - abi: Align { - pow2: 1, - }, - pref: Align { - pow2: 2, - }, - }, - size: Size { - raw: 2, - }, -} + fields: Arbitrary { + offsets: [ + Size { + raw: 0, + }, + ], + memory_index: [ + 0, + ], + }, + variants: Multiple { + tag: Scalar { + value: Int( + I16, + false, + ), + valid_range: 256..=256, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + variants: Single { + index: 0, + }, + abi: Aggregate { + sized: true, + }, + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align { + pow2: 1, + }, + pref: Align { + pow2: 2, + }, + }, + size: Size { + raw: 2, + }, + }, + ], + }, + abi: Scalar( + Scalar { + value: Int( + I16, + false, + ), + valid_range: 256..=256, + }, + ), + largest_niche: Some( + Niche { + offset: Size { + raw: 0, + }, + scalar: Scalar { + value: Int( + I16, + false, + ), + valid_range: 256..=256, + }, + }, + ), + align: AbiAndPrefAlign { + abi: Align { + pow2: 1, + }, + pref: Align { + pow2: 2, + }, + }, + size: Size { + raw: 2, + }, + } --> $DIR/thumb-enum.rs:24:1 | LL | enum C { Chaenomeles = 256, } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: layout_of(P) = Layout { - fields: Arbitrary { - offsets: [ - Size { - raw: 0, - }, - ], - memory_index: [ - 0, - ], - }, - variants: Multiple { - tag: Scalar { - value: Int( - I32, - false, - ), - valid_range: 268435456..=268435456, - }, - tag_encoding: Direct, - tag_field: 0, - variants: [ - Layout { - fields: Arbitrary { - offsets: [], - memory_index: [], - }, - variants: Single { - index: 0, - }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, - pref: Align { - pow2: 2, - }, - }, - size: Size { - raw: 4, - }, - }, - ], - }, - abi: Scalar( - Scalar { - value: Int( - I32, - false, - ), - valid_range: 268435456..=268435456, - }, - ), - largest_niche: Some( - Niche { - offset: Size { - raw: 0, - }, - scalar: Scalar { - value: Int( - I32, - false, - ), - valid_range: 268435456..=268435456, - }, - }, - ), - align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, - pref: Align { - pow2: 2, - }, - }, - size: Size { - raw: 4, - }, -} + fields: Arbitrary { + offsets: [ + Size { + raw: 0, + }, + ], + memory_index: [ + 0, + ], + }, + variants: Multiple { + tag: Scalar { + value: Int( + I32, + false, + ), + valid_range: 268435456..=268435456, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + variants: Single { + index: 0, + }, + abi: Aggregate { + sized: true, + }, + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align { + pow2: 2, + }, + pref: Align { + pow2: 2, + }, + }, + size: Size { + raw: 4, + }, + }, + ], + }, + abi: Scalar( + Scalar { + value: Int( + I32, + false, + ), + valid_range: 268435456..=268435456, + }, + ), + largest_niche: Some( + Niche { + offset: Size { + raw: 0, + }, + scalar: Scalar { + value: Int( + I32, + false, + ), + valid_range: 268435456..=268435456, + }, + }, + ), + align: AbiAndPrefAlign { + abi: Align { + pow2: 2, + }, + pref: Align { + pow2: 2, + }, + }, + size: Size { + raw: 4, + }, + } --> $DIR/thumb-enum.rs:28:1 | LL | enum P { Peach = 0x1000_0000isize, } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: layout_of(T) = Layout { - fields: Arbitrary { - offsets: [ - Size { - raw: 0, - }, - ], - memory_index: [ - 0, - ], - }, - variants: Multiple { - tag: Scalar { - value: Int( - I32, - true, - ), - valid_range: 2164260864..=2164260864, - }, - tag_encoding: Direct, - tag_field: 0, - variants: [ - Layout { - fields: Arbitrary { - offsets: [], - memory_index: [], - }, - variants: Single { - index: 0, - }, - abi: Aggregate { - sized: true, - }, - largest_niche: None, - align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, - pref: Align { - pow2: 2, - }, - }, - size: Size { - raw: 4, - }, - }, - ], - }, - abi: Scalar( - Scalar { - value: Int( - I32, - true, - ), - valid_range: 2164260864..=2164260864, - }, - ), - largest_niche: Some( - Niche { - offset: Size { - raw: 0, - }, - scalar: Scalar { - value: Int( - I32, - true, - ), - valid_range: 2164260864..=2164260864, - }, - }, - ), - align: AbiAndPrefAlign { - abi: Align { - pow2: 2, - }, - pref: Align { - pow2: 2, - }, - }, - size: Size { - raw: 4, - }, -} + fields: Arbitrary { + offsets: [ + Size { + raw: 0, + }, + ], + memory_index: [ + 0, + ], + }, + variants: Multiple { + tag: Scalar { + value: Int( + I32, + true, + ), + valid_range: 2164260864..=2164260864, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + variants: Single { + index: 0, + }, + abi: Aggregate { + sized: true, + }, + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align { + pow2: 2, + }, + pref: Align { + pow2: 2, + }, + }, + size: Size { + raw: 4, + }, + }, + ], + }, + abi: Scalar( + Scalar { + value: Int( + I32, + true, + ), + valid_range: 2164260864..=2164260864, + }, + ), + largest_niche: Some( + Niche { + offset: Size { + raw: 0, + }, + scalar: Scalar { + value: Int( + I32, + true, + ), + valid_range: 2164260864..=2164260864, + }, + }, + ), + align: AbiAndPrefAlign { + abi: Align { + pow2: 2, + }, + pref: Align { + pow2: 2, + }, + }, + size: Size { + raw: 4, + }, + } --> $DIR/thumb-enum.rs:34:1 | LL | enum T { Tangerine = TANGERINE as isize } diff --git a/src/test/ui/leak-unique-as-tydesc.rs b/src/test/ui/leak-unique-as-tydesc.rs deleted file mode 100644 index 322f726156..0000000000 --- a/src/test/ui/leak-unique-as-tydesc.rs +++ /dev/null @@ -1,9 +0,0 @@ -// run-pass -// pretty-expanded FIXME #23616 - -fn leaky<T>(_t: T) { } - -pub fn main() { - let x = Box::new(10); - leaky::<Box<isize>>(x); -} diff --git a/src/test/ui/let-else/issue-89960.rs b/src/test/ui/let-else/issue-89960.rs new file mode 100644 index 0000000000..8fd55adbfd --- /dev/null +++ b/src/test/ui/let-else/issue-89960.rs @@ -0,0 +1,7 @@ +#![feature(let_else)] + +fn main() { + // FIXME: more precise diagnostics + let Some(ref mut meow) = Some(()) else { return }; + //~^ ERROR: cannot borrow value as mutable, as `val` is not declared as mutable +} diff --git a/src/test/ui/let-else/issue-89960.stderr b/src/test/ui/let-else/issue-89960.stderr new file mode 100644 index 0000000000..697f04d6d2 --- /dev/null +++ b/src/test/ui/let-else/issue-89960.stderr @@ -0,0 +1,12 @@ +error[E0596]: cannot borrow value as mutable, as `val` is not declared as mutable + --> $DIR/issue-89960.rs:5:14 + | +LL | let Some(ref mut meow) = Some(()) else { return }; + | ---------^^^^^^^^^^^^----------------------------- + | | | + | | cannot borrow as mutable + | help: consider changing this to be mutable: `mut val` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/let-else/let-else-bool-binop-init.stderr b/src/test/ui/let-else/let-else-bool-binop-init.stderr index 6551e24cc8..edee657624 100644 --- a/src/test/ui/let-else/let-else-bool-binop-init.stderr +++ b/src/test/ui/let-else/let-else-bool-binop-init.stderr @@ -4,7 +4,7 @@ error: a `&&` expression cannot be directly assigned in `let...else` LL | let true = true && false else { return }; | ^^^^^^^^^^^^^ | -help: wrap the expression in parenthesis +help: wrap the expression in parentheses | LL | let true = (true && false) else { return }; | + + @@ -15,7 +15,7 @@ error: a `||` expression cannot be directly assigned in `let...else` LL | let true = true || false else { return }; | ^^^^^^^^^^^^^ | -help: wrap the expression in parenthesis +help: wrap the expression in parentheses | LL | let true = (true || false) else { return }; | + + diff --git a/src/test/ui/let-else/let-else-brace-before-else.stderr b/src/test/ui/let-else/let-else-brace-before-else.stderr index eac029c848..51051bbd4d 100644 --- a/src/test/ui/let-else/let-else-brace-before-else.stderr +++ b/src/test/ui/let-else/let-else-brace-before-else.stderr @@ -4,7 +4,7 @@ error: right curly brace `}` before `else` in a `let...else` statement not allow LL | let Some(1) = { Some(1) } else { | ^ | -help: try wrapping the expression in parenthesis +help: try wrapping the expression in parentheses | LL | let Some(1) = ({ Some(1) }) else { | + + @@ -15,7 +15,7 @@ error: right curly brace `}` before `else` in a `let...else` statement not allow LL | let Some(1) = loop { break Some(1) } else { | ^ | -help: try wrapping the expression in parenthesis +help: try wrapping the expression in parentheses | LL | let Some(1) = (loop { break Some(1) }) else { | + + @@ -26,7 +26,7 @@ error: right curly brace `}` before `else` in a `let...else` statement not allow LL | let 2 = 1 + match 1 { n => n } else { | ^ | -help: try wrapping the expression in parenthesis +help: try wrapping the expression in parentheses | LL | let 2 = 1 + (match 1 { n => n }) else { | + + @@ -37,7 +37,7 @@ error: right curly brace `}` before `else` in a `let...else` statement not allow LL | let Some(1) = unsafe { unsafe_fn() } else { | ^ | -help: try wrapping the expression in parenthesis +help: try wrapping the expression in parentheses | LL | let Some(1) = (unsafe { unsafe_fn() }) else { | + + diff --git a/src/test/ui/let-else/let-else-if.rs b/src/test/ui/let-else/let-else-if.rs new file mode 100644 index 0000000000..c3a17330d6 --- /dev/null +++ b/src/test/ui/let-else/let-else-if.rs @@ -0,0 +1,10 @@ +#![feature(let_else)] + +fn main() { + let Some(_) = Some(()) else if true { + //~^ ERROR conditional `else if` is not supported for `let...else` + return; + } else { + return; + }; +} diff --git a/src/test/ui/let-else/let-else-if.stderr b/src/test/ui/let-else/let-else-if.stderr new file mode 100644 index 0000000000..38c739fd85 --- /dev/null +++ b/src/test/ui/let-else/let-else-if.stderr @@ -0,0 +1,18 @@ +error: conditional `else if` is not supported for `let...else` + --> $DIR/let-else-if.rs:4:33 + | +LL | let Some(_) = Some(()) else if true { + | ^^ expected `{` + | +help: try placing this code inside a block + | +LL ~ let Some(_) = Some(()) else { if true { +LL + +LL + return; +LL + } else { +LL + return; +LL ~ } }; + | + +error: aborting due to previous error + diff --git a/src/test/ui/parser/lex-bad-binary-literal.rs b/src/test/ui/lexer/lex-bad-binary-literal.rs similarity index 100% rename from src/test/ui/parser/lex-bad-binary-literal.rs rename to src/test/ui/lexer/lex-bad-binary-literal.rs diff --git a/src/test/ui/parser/lex-bad-binary-literal.stderr b/src/test/ui/lexer/lex-bad-binary-literal.stderr similarity index 100% rename from src/test/ui/parser/lex-bad-binary-literal.stderr rename to src/test/ui/lexer/lex-bad-binary-literal.stderr diff --git a/src/test/ui/parser/lex-bad-char-literals-1.rs b/src/test/ui/lexer/lex-bad-char-literals-1.rs similarity index 100% rename from src/test/ui/parser/lex-bad-char-literals-1.rs rename to src/test/ui/lexer/lex-bad-char-literals-1.rs diff --git a/src/test/ui/parser/lex-bad-char-literals-1.stderr b/src/test/ui/lexer/lex-bad-char-literals-1.stderr similarity index 100% rename from src/test/ui/parser/lex-bad-char-literals-1.stderr rename to src/test/ui/lexer/lex-bad-char-literals-1.stderr diff --git a/src/test/ui/parser/lex-bad-char-literals-2.rs b/src/test/ui/lexer/lex-bad-char-literals-2.rs similarity index 100% rename from src/test/ui/parser/lex-bad-char-literals-2.rs rename to src/test/ui/lexer/lex-bad-char-literals-2.rs diff --git a/src/test/ui/parser/lex-bad-char-literals-2.stderr b/src/test/ui/lexer/lex-bad-char-literals-2.stderr similarity index 100% rename from src/test/ui/parser/lex-bad-char-literals-2.stderr rename to src/test/ui/lexer/lex-bad-char-literals-2.stderr diff --git a/src/test/ui/parser/lex-bad-char-literals-3.rs b/src/test/ui/lexer/lex-bad-char-literals-3.rs similarity index 100% rename from src/test/ui/parser/lex-bad-char-literals-3.rs rename to src/test/ui/lexer/lex-bad-char-literals-3.rs diff --git a/src/test/ui/parser/lex-bad-char-literals-3.stderr b/src/test/ui/lexer/lex-bad-char-literals-3.stderr similarity index 100% rename from src/test/ui/parser/lex-bad-char-literals-3.stderr rename to src/test/ui/lexer/lex-bad-char-literals-3.stderr diff --git a/src/test/ui/parser/lex-bad-char-literals-4.rs b/src/test/ui/lexer/lex-bad-char-literals-4.rs similarity index 100% rename from src/test/ui/parser/lex-bad-char-literals-4.rs rename to src/test/ui/lexer/lex-bad-char-literals-4.rs diff --git a/src/test/ui/parser/lex-bad-char-literals-4.stderr b/src/test/ui/lexer/lex-bad-char-literals-4.stderr similarity index 100% rename from src/test/ui/parser/lex-bad-char-literals-4.stderr rename to src/test/ui/lexer/lex-bad-char-literals-4.stderr diff --git a/src/test/ui/parser/lex-bad-char-literals-5.rs b/src/test/ui/lexer/lex-bad-char-literals-5.rs similarity index 100% rename from src/test/ui/parser/lex-bad-char-literals-5.rs rename to src/test/ui/lexer/lex-bad-char-literals-5.rs diff --git a/src/test/ui/parser/lex-bad-char-literals-5.stderr b/src/test/ui/lexer/lex-bad-char-literals-5.stderr similarity index 100% rename from src/test/ui/parser/lex-bad-char-literals-5.stderr rename to src/test/ui/lexer/lex-bad-char-literals-5.stderr diff --git a/src/test/ui/parser/lex-bad-char-literals-6.rs b/src/test/ui/lexer/lex-bad-char-literals-6.rs similarity index 100% rename from src/test/ui/parser/lex-bad-char-literals-6.rs rename to src/test/ui/lexer/lex-bad-char-literals-6.rs diff --git a/src/test/ui/parser/lex-bad-char-literals-6.stderr b/src/test/ui/lexer/lex-bad-char-literals-6.stderr similarity index 100% rename from src/test/ui/parser/lex-bad-char-literals-6.stderr rename to src/test/ui/lexer/lex-bad-char-literals-6.stderr diff --git a/src/test/ui/parser/lex-bad-char-literals-7.rs b/src/test/ui/lexer/lex-bad-char-literals-7.rs similarity index 100% rename from src/test/ui/parser/lex-bad-char-literals-7.rs rename to src/test/ui/lexer/lex-bad-char-literals-7.rs diff --git a/src/test/ui/parser/lex-bad-char-literals-7.stderr b/src/test/ui/lexer/lex-bad-char-literals-7.stderr similarity index 100% rename from src/test/ui/parser/lex-bad-char-literals-7.stderr rename to src/test/ui/lexer/lex-bad-char-literals-7.stderr diff --git a/src/test/ui/parser/lex-bad-numeric-literals.rs b/src/test/ui/lexer/lex-bad-numeric-literals.rs similarity index 100% rename from src/test/ui/parser/lex-bad-numeric-literals.rs rename to src/test/ui/lexer/lex-bad-numeric-literals.rs diff --git a/src/test/ui/parser/lex-bad-numeric-literals.stderr b/src/test/ui/lexer/lex-bad-numeric-literals.stderr similarity index 100% rename from src/test/ui/parser/lex-bad-numeric-literals.stderr rename to src/test/ui/lexer/lex-bad-numeric-literals.stderr diff --git a/src/test/ui/parser/lex-bad-octal-literal.rs b/src/test/ui/lexer/lex-bad-octal-literal.rs similarity index 100% rename from src/test/ui/parser/lex-bad-octal-literal.rs rename to src/test/ui/lexer/lex-bad-octal-literal.rs diff --git a/src/test/ui/parser/lex-bad-octal-literal.stderr b/src/test/ui/lexer/lex-bad-octal-literal.stderr similarity index 100% rename from src/test/ui/parser/lex-bad-octal-literal.stderr rename to src/test/ui/lexer/lex-bad-octal-literal.stderr diff --git a/src/test/ui/parser/lex-bad-token.rs b/src/test/ui/lexer/lex-bad-token.rs similarity index 100% rename from src/test/ui/parser/lex-bad-token.rs rename to src/test/ui/lexer/lex-bad-token.rs diff --git a/src/test/ui/parser/lex-bad-token.stderr b/src/test/ui/lexer/lex-bad-token.stderr similarity index 100% rename from src/test/ui/parser/lex-bad-token.stderr rename to src/test/ui/lexer/lex-bad-token.stderr diff --git a/src/test/ui/parser/lex-bare-cr-nondoc-comment.rs b/src/test/ui/lexer/lex-bare-cr-nondoc-comment.rs similarity index 100% rename from src/test/ui/parser/lex-bare-cr-nondoc-comment.rs rename to src/test/ui/lexer/lex-bare-cr-nondoc-comment.rs diff --git a/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.rs b/src/test/ui/lexer/lex-bare-cr-string-literal-doc-comment.rs similarity index 100% rename from src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.rs rename to src/test/ui/lexer/lex-bare-cr-string-literal-doc-comment.rs diff --git a/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.stderr b/src/test/ui/lexer/lex-bare-cr-string-literal-doc-comment.stderr similarity index 100% rename from src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.stderr rename to src/test/ui/lexer/lex-bare-cr-string-literal-doc-comment.stderr diff --git a/src/test/ui/parser/lex-stray-backslash.rs b/src/test/ui/lexer/lex-stray-backslash.rs similarity index 100% rename from src/test/ui/parser/lex-stray-backslash.rs rename to src/test/ui/lexer/lex-stray-backslash.rs diff --git a/src/test/ui/parser/lex-stray-backslash.stderr b/src/test/ui/lexer/lex-stray-backslash.stderr similarity index 100% rename from src/test/ui/parser/lex-stray-backslash.stderr rename to src/test/ui/lexer/lex-stray-backslash.stderr diff --git a/src/test/ui/parser/lexer-crlf-line-endings-string-literal-doc-comment.rs b/src/test/ui/lexer/lexer-crlf-line-endings-string-literal-doc-comment.rs similarity index 100% rename from src/test/ui/parser/lexer-crlf-line-endings-string-literal-doc-comment.rs rename to src/test/ui/lexer/lexer-crlf-line-endings-string-literal-doc-comment.rs diff --git a/src/test/ui/issues/issue-26638.rs b/src/test/ui/lifetimes/issue-26638.rs similarity index 100% rename from src/test/ui/issues/issue-26638.rs rename to src/test/ui/lifetimes/issue-26638.rs diff --git a/src/test/ui/issues/issue-26638.stderr b/src/test/ui/lifetimes/issue-26638.stderr similarity index 100% rename from src/test/ui/issues/issue-26638.stderr rename to src/test/ui/lifetimes/issue-26638.stderr diff --git a/src/test/ui/lifetimes/issue-34979.stderr b/src/test/ui/lifetimes/issue-34979.stderr index b76d71a3d4..1b97f8d818 100644 --- a/src/test/ui/lifetimes/issue-34979.stderr +++ b/src/test/ui/lifetimes/issue-34979.stderr @@ -5,11 +5,6 @@ LL | &'a (): Foo, | ^^^ cannot infer type for reference `&'a ()` | = note: cannot satisfy `&'a (): Foo` -note: required by a bound in `Foo` - --> $DIR/issue-34979.rs:1:1 - | -LL | trait Foo {} - | ^^^^^^^^^ required by this bound in `Foo` error: aborting due to previous error diff --git a/src/test/ui/lifetimes/issue-90170-elision-mismatch.fixed b/src/test/ui/lifetimes/issue-90170-elision-mismatch.fixed new file mode 100644 index 0000000000..0bc889ee72 --- /dev/null +++ b/src/test/ui/lifetimes/issue-90170-elision-mismatch.fixed @@ -0,0 +1,9 @@ +// run-rustfix + +pub fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } //~ ERROR lifetime mismatch + +pub fn foo2<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } //~ ERROR lifetime mismatch + +pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } //~ ERROR lifetime mismatch + +fn main() {} diff --git a/src/test/ui/lifetimes/issue-90170-elision-mismatch.nll.stderr b/src/test/ui/lifetimes/issue-90170-elision-mismatch.nll.stderr new file mode 100644 index 0000000000..a5bc7450bb --- /dev/null +++ b/src/test/ui/lifetimes/issue-90170-elision-mismatch.nll.stderr @@ -0,0 +1,29 @@ +error: lifetime may not live long enough + --> $DIR/issue-90170-elision-mismatch.rs:3:40 + | +LL | pub fn foo(x: &mut Vec<&u8>, y: &u8) { x.push(y); } + | - - ^^^^^^^^^ argument requires that `'1` must outlive `'2` + | | | + | | let's call the lifetime of this reference `'1` + | let's call the lifetime of this reference `'2` + +error: lifetime may not live long enough + --> $DIR/issue-90170-elision-mismatch.rs:5:44 + | +LL | pub fn foo2(x: &mut Vec<&'_ u8>, y: &u8) { x.push(y); } + | - - ^^^^^^^^^ argument requires that `'1` must outlive `'2` + | | | + | | let's call the lifetime of this reference `'1` + | let's call the lifetime of this reference `'2` + +error: lifetime may not live long enough + --> $DIR/issue-90170-elision-mismatch.rs:7:63 + | +LL | pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&u8>, y: &u8) { x.push(y); } + | - - ^^^^^^^^^ argument requires that `'1` must outlive `'2` + | | | + | | let's call the lifetime of this reference `'1` + | let's call the lifetime of this reference `'2` + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/lifetimes/issue-90170-elision-mismatch.rs b/src/test/ui/lifetimes/issue-90170-elision-mismatch.rs new file mode 100644 index 0000000000..1d6573c00a --- /dev/null +++ b/src/test/ui/lifetimes/issue-90170-elision-mismatch.rs @@ -0,0 +1,9 @@ +// run-rustfix + +pub fn foo(x: &mut Vec<&u8>, y: &u8) { x.push(y); } //~ ERROR lifetime mismatch + +pub fn foo2(x: &mut Vec<&'_ u8>, y: &u8) { x.push(y); } //~ ERROR lifetime mismatch + +pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&u8>, y: &u8) { x.push(y); } //~ ERROR lifetime mismatch + +fn main() {} diff --git a/src/test/ui/lifetimes/issue-90170-elision-mismatch.stderr b/src/test/ui/lifetimes/issue-90170-elision-mismatch.stderr new file mode 100644 index 0000000000..7fa092ca22 --- /dev/null +++ b/src/test/ui/lifetimes/issue-90170-elision-mismatch.stderr @@ -0,0 +1,45 @@ +error[E0623]: lifetime mismatch + --> $DIR/issue-90170-elision-mismatch.rs:3:47 + | +LL | pub fn foo(x: &mut Vec<&u8>, y: &u8) { x.push(y); } + | --- --- ^ ...but data from `y` flows into `x` here + | | + | these two types are declared with different lifetimes... + | + = note: each elided lifetime in input position becomes a distinct lifetime +help: consider introducing a named lifetime parameter + | +LL | pub fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } + | ++++ ++ ++ + +error[E0623]: lifetime mismatch + --> $DIR/issue-90170-elision-mismatch.rs:5:51 + | +LL | pub fn foo2(x: &mut Vec<&'_ u8>, y: &u8) { x.push(y); } + | ------ --- ^ ...but data from `y` flows into `x` here + | | + | these two types are declared with different lifetimes... + | + = note: each elided lifetime in input position becomes a distinct lifetime +help: consider introducing a named lifetime parameter + | +LL | pub fn foo2<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } + | ++++ ~~ ++ + +error[E0623]: lifetime mismatch + --> $DIR/issue-90170-elision-mismatch.rs:7:70 + | +LL | pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&u8>, y: &u8) { x.push(y); } + | --- --- ^ ...but data from `y` flows into `x` here + | | + | these two types are declared with different lifetimes... + | + = note: each elided lifetime in input position becomes a distinct lifetime +help: consider introducing a named lifetime parameter + | +LL | pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } + | ++ ++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/lifetimes/issue-90600-expected-return-static-indirect.nll.stderr b/src/test/ui/lifetimes/issue-90600-expected-return-static-indirect.nll.stderr new file mode 100644 index 0000000000..99e1e7217b --- /dev/null +++ b/src/test/ui/lifetimes/issue-90600-expected-return-static-indirect.nll.stderr @@ -0,0 +1,24 @@ +error[E0597]: `foo` does not live long enough + --> $DIR/issue-90600-expected-return-static-indirect.rs:7:32 + | +LL | let refcell = RefCell::new(&mut foo); + | ^^^^^^^^ borrowed value does not live long enough +LL | +LL | let read = &refcell as &RefCell<dyn Read>; + | -------- cast requires that `foo` is borrowed for `'static` +... +LL | } + | - `foo` dropped here while still borrowed + +error: lifetime may not live long enough + --> $DIR/issue-90600-expected-return-static-indirect.rs:9:16 + | +LL | fn inner(mut foo: &[u8]) { + | - let's call the lifetime of this reference `'1` +... +LL | let read = &refcell as &RefCell<dyn Read>; + | ^^^^^^^^ cast requires that `'1` must outlive `'static` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/lifetimes/issue-90600-expected-return-static-indirect.rs b/src/test/ui/lifetimes/issue-90600-expected-return-static-indirect.rs new file mode 100644 index 0000000000..39996bbf43 --- /dev/null +++ b/src/test/ui/lifetimes/issue-90600-expected-return-static-indirect.rs @@ -0,0 +1,14 @@ +use std::cell::RefCell; +use std::io::Read; + +fn main() {} + +fn inner(mut foo: &[u8]) { + let refcell = RefCell::new(&mut foo); + //~^ ERROR `foo` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement [E0759] + let read = &refcell as &RefCell<dyn Read>; + + read_thing(read); +} + +fn read_thing(refcell: &RefCell<dyn Read>) {} diff --git a/src/test/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr b/src/test/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr new file mode 100644 index 0000000000..3f65d3af72 --- /dev/null +++ b/src/test/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr @@ -0,0 +1,14 @@ +error[E0759]: `foo` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/issue-90600-expected-return-static-indirect.rs:7:32 + | +LL | fn inner(mut foo: &[u8]) { + | ----- this data with an anonymous lifetime `'_`... +LL | let refcell = RefCell::new(&mut foo); + | ^^^^^^^^ ...is captured here... +... +LL | read_thing(read); + | ---- ...and is required to live as long as `'static` here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr index 0aff80c6fb..5c79363677 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr @@ -5,6 +5,12 @@ LL | fn foo(&mut (ref mut v, w): &mut (&u8, &u8), x: &u8) { | --- --- these two types are declared with different lifetimes... LL | *v = x; | ^ ...but data from `x` flows here + | + = note: each elided lifetime in input position becomes a distinct lifetime +help: consider introducing a named lifetime parameter + | +LL | fn foo<'a>(&mut (ref mut v, w): &mut (&'a u8, &u8), x: &'a u8) { + | ++++ ++ ++ error: aborting due to previous error diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr index 2e5ff6782d..1a7b4fca1b 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr @@ -5,6 +5,12 @@ LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) { | --- --- these two types are declared with different lifetimes... LL | z.push((x,y)); | ^ ...but data flows into `z` here + | + = note: each elided lifetime in input position becomes a distinct lifetime +help: consider introducing a named lifetime parameter + | +LL | fn foo<'a>(z: &mut Vec<(&'a u8,&u8)>, (x, y): (&'a u8, &u8)) { + | ++++ ++ ++ error[E0623]: lifetime mismatch --> $DIR/ex3-both-anon-regions-3.rs:2:15 @@ -13,6 +19,12 @@ LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) { | --- --- these two types are declared with different lifetimes... LL | z.push((x,y)); | ^ ...but data flows into `z` here + | + = note: each elided lifetime in input position becomes a distinct lifetime +help: consider introducing a named lifetime parameter + | +LL | fn foo<'a>(z: &mut Vec<(&u8,&'a u8)>, (x, y): (&u8, &'a u8)) { + | ++++ ++ ++ error: aborting due to 2 previous errors diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr index d2cc3dba6a..6ed3528bb9 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr @@ -5,6 +5,12 @@ LL | fn foo(x:fn(&u8, &u8), y: Vec<&u8>, z: &u8) { | --- --- these two types are declared with different lifetimes... LL | y.push(z); | ^ ...but data from `z` flows into `y` here + | + = note: each elided lifetime in input position becomes a distinct lifetime +help: consider introducing a named lifetime parameter + | +LL | fn foo<'a>(x:fn(&u8, &u8), y: Vec<&'a u8>, z: &'a u8) { + | ++++ ++ ++ error: aborting due to previous error diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr index 2acc4eaf60..ede1631db2 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr @@ -5,6 +5,12 @@ LL | fn foo(x:Box<dyn Fn(&u8, &u8)> , y: Vec<&u8>, z: &u8) { | --- --- these two types are declared with different lifetimes... LL | y.push(z); | ^ ...but data from `z` flows into `y` here + | + = note: each elided lifetime in input position becomes a distinct lifetime +help: consider introducing a named lifetime parameter + | +LL | fn foo<'a>(x:Box<dyn Fn(&'a u8, &'a u8)> , y: Vec<&u8>, z: &u8) { + | ++++ ++ ++ error: aborting due to previous error diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr index b278482767..cf405c0de3 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr @@ -5,6 +5,12 @@ LL | fn foo(x: &mut Vec<&u8>, y: &u8) { | --- --- these two types are declared with different lifetimes... LL | x.push(y); | ^ ...but data from `y` flows into `x` here + | + = note: each elided lifetime in input position becomes a distinct lifetime +help: consider introducing a named lifetime parameter + | +LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { + | ++++ ++ ++ error: aborting due to previous error diff --git a/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr index 060e695440..3040a8512c 100644 --- a/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr +++ b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr @@ -2,13 +2,13 @@ error: `impl` item signature doesn't match `trait` item signature --> $DIR/lifetime-mismatch-between-trait-and-impl.rs:6:5 | LL | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32; - | ------------------------------------------- expected `fn(&i32, &'a i32) -> &'a i32` + | ------------------------------------------- expected `fn(&'1 i32, &'a i32) -> &'a i32` ... LL | fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&i32, &i32) -> &i32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 i32, &'1 i32) -> &'1 i32` | - = note: expected `fn(&i32, &'a i32) -> &'a i32` - found `fn(&i32, &i32) -> &i32` + = note: expected `fn(&'1 i32, &'a i32) -> &'a i32` + found `fn(&'1 i32, &'1 i32) -> &'1 i32` = 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 diff --git a/src/test/ui/auxiliary/link-cfg-works-transitive-dylib.rs b/src/test/ui/linkage-attr/auxiliary/link-cfg-works-transitive-dylib.rs similarity index 100% rename from src/test/ui/auxiliary/link-cfg-works-transitive-dylib.rs rename to src/test/ui/linkage-attr/auxiliary/link-cfg-works-transitive-dylib.rs diff --git a/src/test/ui/auxiliary/link-cfg-works-transitive-rlib.rs b/src/test/ui/linkage-attr/auxiliary/link-cfg-works-transitive-rlib.rs similarity index 100% rename from src/test/ui/auxiliary/link-cfg-works-transitive-rlib.rs rename to src/test/ui/linkage-attr/auxiliary/link-cfg-works-transitive-rlib.rs diff --git a/src/test/ui/auxiliary/linkage1.rs b/src/test/ui/linkage-attr/auxiliary/linkage1.rs similarity index 100% rename from src/test/ui/auxiliary/linkage1.rs rename to src/test/ui/linkage-attr/auxiliary/linkage1.rs diff --git a/src/test/ui/link-cfg-works.rs b/src/test/ui/linkage-attr/link-cfg-works.rs similarity index 100% rename from src/test/ui/link-cfg-works.rs rename to src/test/ui/linkage-attr/link-cfg-works.rs diff --git a/src/test/ui/linkage1.rs b/src/test/ui/linkage-attr/linkage1.rs similarity index 100% rename from src/test/ui/linkage1.rs rename to src/test/ui/linkage-attr/linkage1.rs diff --git a/src/test/ui/lint/crate_level_only_lint.rs b/src/test/ui/lint/crate_level_only_lint.rs index 38c5487183..d9673faa21 100644 --- a/src/test/ui/lint/crate_level_only_lint.rs +++ b/src/test/ui/lint/crate_level_only_lint.rs @@ -4,10 +4,12 @@ mod foo { #![allow(uncommon_codepoints)] //~^ ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] //~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] +//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] #[allow(uncommon_codepoints)] //~^ ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] //~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] +//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] const BAR: f64 = 0.000001; } @@ -15,5 +17,6 @@ const BAR: f64 = 0.000001; #[allow(uncommon_codepoints)] //~^ ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] //~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] +//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] fn main() { } diff --git a/src/test/ui/lint/crate_level_only_lint.stderr b/src/test/ui/lint/crate_level_only_lint.stderr index 83bea0412f..8fb06df2a4 100644 --- a/src/test/ui/lint/crate_level_only_lint.stderr +++ b/src/test/ui/lint/crate_level_only_lint.stderr @@ -11,13 +11,13 @@ LL | #![deny(uncommon_codepoints, unused_attributes)] | ^^^^^^^^^^^^^^^^^ error: allow(uncommon_codepoints) is ignored unless specified at crate level - --> $DIR/crate_level_only_lint.rs:8:9 + --> $DIR/crate_level_only_lint.rs:9:9 | LL | #[allow(uncommon_codepoints)] | ^^^^^^^^^^^^^^^^^^^ error: allow(uncommon_codepoints) is ignored unless specified at crate level - --> $DIR/crate_level_only_lint.rs:15:9 + --> $DIR/crate_level_only_lint.rs:17:9 | LL | #[allow(uncommon_codepoints)] | ^^^^^^^^^^^^^^^^^^^ @@ -29,16 +29,34 @@ LL | #![allow(uncommon_codepoints)] | ^^^^^^^^^^^^^^^^^^^ error: allow(uncommon_codepoints) is ignored unless specified at crate level - --> $DIR/crate_level_only_lint.rs:8:9 + --> $DIR/crate_level_only_lint.rs:9:9 | LL | #[allow(uncommon_codepoints)] | ^^^^^^^^^^^^^^^^^^^ error: allow(uncommon_codepoints) is ignored unless specified at crate level - --> $DIR/crate_level_only_lint.rs:15:9 + --> $DIR/crate_level_only_lint.rs:17:9 | LL | #[allow(uncommon_codepoints)] | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to 6 previous errors +error: allow(uncommon_codepoints) is ignored unless specified at crate level + --> $DIR/crate_level_only_lint.rs:4:10 + | +LL | #![allow(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + +error: allow(uncommon_codepoints) is ignored unless specified at crate level + --> $DIR/crate_level_only_lint.rs:9:9 + | +LL | #[allow(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + +error: allow(uncommon_codepoints) is ignored unless specified at crate level + --> $DIR/crate_level_only_lint.rs:17:9 + | +LL | #[allow(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 9 previous errors diff --git a/src/test/ui/lint/dead-code/anon-const-in-pat.rs b/src/test/ui/lint/dead-code/anon-const-in-pat.rs index 4c6211a279..d3e39c0de6 100644 --- a/src/test/ui/lint/dead-code/anon-const-in-pat.rs +++ b/src/test/ui/lint/dead-code/anon-const-in-pat.rs @@ -1,5 +1,5 @@ // check-pass -#![feature(inline_const)] +#![feature(inline_const_pat)] #![allow(incomplete_features)] #![deny(dead_code)] diff --git a/src/test/ui/lint/forbid-group-group-2.rs b/src/test/ui/lint/forbid-group-group-2.rs index 7d8a398181..b12fd72da7 100644 --- a/src/test/ui/lint/forbid-group-group-2.rs +++ b/src/test/ui/lint/forbid-group-group-2.rs @@ -17,4 +17,10 @@ //~| WARNING previously accepted by the compiler //~| ERROR incompatible with previous //~| WARNING previously accepted by the compiler +//~| ERROR incompatible with previous +//~| WARNING previously accepted by the compiler +//~| ERROR incompatible with previous +//~| WARNING previously accepted by the compiler +//~| ERROR incompatible with previous +//~| WARNING previously accepted by the compiler fn main() {} diff --git a/src/test/ui/lint/forbid-group-group-2.stderr b/src/test/ui/lint/forbid-group-group-2.stderr index d8c09e6526..214e949c11 100644 --- a/src/test/ui/lint/forbid-group-group-2.stderr +++ b/src/test/ui/lint/forbid-group-group-2.stderr @@ -75,5 +75,41 @@ LL | #[allow(nonstandard_style)] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> -error: aborting due to 6 previous errors +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> + +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> + +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> + +error: aborting due to 9 previous errors diff --git a/src/test/ui/lint/force-warn/allowed-cli-deny-by-default-lint.rs b/src/test/ui/lint/force-warn/allowed-cli-deny-by-default-lint.rs index 3fab914839..3a3d81176d 100644 --- a/src/test/ui/lint/force-warn/allowed-cli-deny-by-default-lint.rs +++ b/src/test/ui/lint/force-warn/allowed-cli-deny-by-default-lint.rs @@ -1,6 +1,6 @@ // --force-warn $LINT causes $LINT (which is deny-by-default) to warn // despite $LINT being allowed on command line -// compile-flags: -A const_err --force-warn const_err -Zunstable-options +// compile-flags: -A const_err --force-warn const_err // check-pass const C: i32 = 1 / 0; diff --git a/src/test/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.rs b/src/test/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.rs index 4eb05b538b..9736027452 100644 --- a/src/test/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.rs +++ b/src/test/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.rs @@ -1,6 +1,6 @@ // --force-warn $LINT_GROUP causes $LINT (which is warn-by-default) to warn // despite $LINT being allowed on command line -// compile-flags: -A bare-trait-objects --force-warn rust-2018-idioms -Zunstable-options +// compile-flags: -A bare-trait-objects --force-warn rust-2018-idioms // check-pass pub trait SomeTrait {} diff --git a/src/test/ui/lint/force-warn/warn-by-default-lint-two-modules.rs b/src/test/ui/lint/force-warn/warn-by-default-lint-two-modules.rs index d2cb3417be..267e7b45f0 100644 --- a/src/test/ui/lint/force-warn/warn-by-default-lint-two-modules.rs +++ b/src/test/ui/lint/force-warn/warn-by-default-lint-two-modules.rs @@ -1,6 +1,6 @@ // --force-warn $LINT causes $LINT (which is warn-by-default) to warn // despite being allowed in one submodule (but not the other) -// compile-flags: --force-warn dead_code -Zunstable-options +// compile-flags: --force-warn dead_code // check-pass mod one { diff --git a/src/test/ui/lint/force-warn/warnings-lint-group.rs b/src/test/ui/lint/force-warn/warnings-lint-group.rs index fa25a1f8a8..d1d4f5602f 100644 --- a/src/test/ui/lint/force-warn/warnings-lint-group.rs +++ b/src/test/ui/lint/force-warn/warnings-lint-group.rs @@ -1,5 +1,5 @@ // --force-warn warnings is an error -// compile-flags: --force-warn warnings -Zunstable-options +// compile-flags: --force-warn warnings // error-pattern: `warnings` lint group is not supported fn main() {} diff --git a/src/test/ui/lint/force-warn/warnings-lint-group.stderr b/src/test/ui/lint/force-warn/warnings-lint-group.stderr index 03f5788b52..1faeed3370 100644 --- a/src/test/ui/lint/force-warn/warnings-lint-group.stderr +++ b/src/test/ui/lint/force-warn/warnings-lint-group.stderr @@ -2,8 +2,6 @@ error[E0602]: `warnings` lint group is not supported with ´--force-warn´ error[E0602]: `warnings` lint group is not supported with ´--force-warn´ -error[E0602]: `warnings` lint group is not supported with ´--force-warn´ - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0602`. diff --git a/src/test/ui/issues/issue-14837.rs b/src/test/ui/lint/issue-14837.rs similarity index 100% rename from src/test/ui/issues/issue-14837.rs rename to src/test/ui/lint/issue-14837.rs diff --git a/src/test/ui/issues/issue-57410-1.rs b/src/test/ui/lint/issue-57410-1.rs similarity index 100% rename from src/test/ui/issues/issue-57410-1.rs rename to src/test/ui/lint/issue-57410-1.rs diff --git a/src/test/ui/issues/issue-63364.rs b/src/test/ui/lint/issue-63364.rs similarity index 100% rename from src/test/ui/issues/issue-63364.rs rename to src/test/ui/lint/issue-63364.rs diff --git a/src/test/ui/issues/issue-63364.stderr b/src/test/ui/lint/issue-63364.stderr similarity index 100% rename from src/test/ui/issues/issue-63364.stderr rename to src/test/ui/lint/issue-63364.stderr diff --git a/src/test/ui/lint-cap.rs b/src/test/ui/lint/lint-cap.rs similarity index 100% rename from src/test/ui/lint-cap.rs rename to src/test/ui/lint/lint-cap.rs diff --git a/src/test/ui/lint/lint-ctypes-73251-2.rs b/src/test/ui/lint/lint-ctypes-73251-2.rs index 79effd054b..717ca4986f 100644 --- a/src/test/ui/lint/lint-ctypes-73251-2.rs +++ b/src/test/ui/lint/lint-ctypes-73251-2.rs @@ -33,7 +33,7 @@ fn use_of_b() -> AliasB { } extern "C" { - pub fn lint_me() -> <AliasB as TraitB>::Assoc; //~ ERROR: uses type `impl TraitA` + pub fn lint_me() -> <AliasB as TraitB>::Assoc; //~ ERROR: uses type `impl TraitA<Assoc = u32>` } fn main() {} diff --git a/src/test/ui/lint/lint-ctypes-73251-2.stderr b/src/test/ui/lint/lint-ctypes-73251-2.stderr index 94ee95d422..d7e10db441 100644 --- a/src/test/ui/lint/lint-ctypes-73251-2.stderr +++ b/src/test/ui/lint/lint-ctypes-73251-2.stderr @@ -1,4 +1,4 @@ -error: `extern` block uses type `impl TraitA`, which is not FFI-safe +error: `extern` block uses type `impl TraitA<Assoc = u32>`, which is not FFI-safe --> $DIR/lint-ctypes-73251-2.rs:36:25 | LL | pub fn lint_me() -> <AliasB as TraitB>::Assoc; diff --git a/src/test/ui/lint/lint-forbid-internal-unsafe.rs b/src/test/ui/lint/lint-forbid-internal-unsafe.rs index b08fbf6f84..3ee55ba96b 100644 --- a/src/test/ui/lint/lint-forbid-internal-unsafe.rs +++ b/src/test/ui/lint/lint-forbid-internal-unsafe.rs @@ -13,4 +13,5 @@ macro_rules! evil { fn main() { println!("{}", evil!(*(0 as *const u8))); + //~^ WARNING dereferencing a null pointer } diff --git a/src/test/ui/lint/lint-forbid-internal-unsafe.stderr b/src/test/ui/lint/lint-forbid-internal-unsafe.stderr index e31c003985..ba425ceb44 100644 --- a/src/test/ui/lint/lint-forbid-internal-unsafe.stderr +++ b/src/test/ui/lint/lint-forbid-internal-unsafe.stderr @@ -10,5 +10,13 @@ note: the lint level is defined here LL | #![forbid(unsafe_code)] | ^^^^^^^^^^^ -error: aborting due to previous error +warning: dereferencing a null pointer + --> $DIR/lint-forbid-internal-unsafe.rs:15:26 + | +LL | println!("{}", evil!(*(0 as *const u8))); + | ^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + | + = note: `#[warn(deref_nullptr)]` on by default + +error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/lint/opaque-ty-ffi-unsafe.rs b/src/test/ui/lint/opaque-ty-ffi-unsafe.rs index fadb747195..3a62b6a21a 100644 --- a/src/test/ui/lint/opaque-ty-ffi-unsafe.rs +++ b/src/test/ui/lint/opaque-ty-ffi-unsafe.rs @@ -9,7 +9,7 @@ pub fn ret_closure() -> A { extern "C" { pub fn a(_: A); - //~^ ERROR `extern` block uses type `impl Fn<()>`, which is not FFI-safe + //~^ ERROR `extern` block uses type `impl Fn()`, which is not FFI-safe [improper_ctypes] } fn main() {} diff --git a/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr b/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr index 9d46f6d936..5afbef778b 100644 --- a/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr +++ b/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr @@ -1,4 +1,4 @@ -error: `extern` block uses type `impl Fn<()>`, which is not FFI-safe +error: `extern` block uses type `impl Fn()`, which is not FFI-safe --> $DIR/opaque-ty-ffi-unsafe.rs:11:17 | LL | pub fn a(_: A); 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 81a3427a10..ed8e7ddddc 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,6 +1,7 @@ #![deny(uncommon_codepoints)] const µ: f64 = 0.000001; //~ ERROR identifier contains uncommon Unicode codepoints +//~| WARNING should have an upper case name fn dijkstra() {} //~ 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 d435282a6e..0533da0306 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 @@ -11,16 +11,24 @@ LL | #![deny(uncommon_codepoints)] | ^^^^^^^^^^^^^^^^^^^ error: identifier contains uncommon Unicode codepoints - --> $DIR/lint-uncommon-codepoints.rs:5:4 + --> $DIR/lint-uncommon-codepoints.rs:6:4 | LL | fn dijkstra() {} | ^^^^^^^ error: identifier contains uncommon Unicode codepoints - --> $DIR/lint-uncommon-codepoints.rs:8:9 + --> $DIR/lint-uncommon-codepoints.rs:9:9 | LL | let ㇻㇲㇳ = "rust"; | ^^^^^^ -error: aborting due to 3 previous errors +warning: constant `µ` should have an upper case name + --> $DIR/lint-uncommon-codepoints.rs:3:7 + | +LL | const µ: f64 = 0.000001; + | ^ help: convert the identifier to upper case: `Μ` + | + = note: `#[warn(non_upper_case_globals)]` on by default + +error: aborting due to 3 previous errors; 1 warning emitted diff --git a/src/test/ui/test-allow-dead-extern-static-no-warning.rs b/src/test/ui/lint/test-allow-dead-extern-static-no-warning.rs similarity index 100% rename from src/test/ui/test-allow-dead-extern-static-no-warning.rs rename to src/test/ui/lint/test-allow-dead-extern-static-no-warning.rs diff --git a/src/test/ui/unnecessary-extern-crate.rs b/src/test/ui/lint/unnecessary-extern-crate.rs similarity index 100% rename from src/test/ui/unnecessary-extern-crate.rs rename to src/test/ui/lint/unnecessary-extern-crate.rs diff --git a/src/test/ui/unnecessary-extern-crate.stderr b/src/test/ui/lint/unnecessary-extern-crate.stderr similarity index 100% rename from src/test/ui/unnecessary-extern-crate.stderr rename to src/test/ui/lint/unnecessary-extern-crate.stderr diff --git a/src/test/ui/lint/unused/issue-70041.stderr b/src/test/ui/lint/unused/issue-70041.stderr index ecd618eae8..b2e6d1aeb3 100644 --- a/src/test/ui/lint/unused/issue-70041.stderr +++ b/src/test/ui/lint/unused/issue-70041.stderr @@ -1,11 +1,8 @@ -warning: unused macro definition - --> $DIR/issue-70041.rs:4:1 +warning: unused macro definition: `regex` + --> $DIR/issue-70041.rs:4:14 | -LL | / macro_rules! regex { -LL | | -LL | | () => {}; -LL | | } - | |_^ +LL | macro_rules! regex { + | ^^^^^ | = note: `#[warn(unused_macros)]` on by default diff --git a/src/test/ui/lint/unused/unused-async.rs b/src/test/ui/lint/unused/unused-async.rs new file mode 100644 index 0000000000..7d17af1157 --- /dev/null +++ b/src/test/ui/lint/unused/unused-async.rs @@ -0,0 +1,43 @@ +// edition:2018 +// run-pass +#![allow(dead_code)] + +#[must_use] +//~^ WARNING `must_use` +async fn test() -> i32 { + 1 +} + + +struct Wowee {} + +impl Wowee { + #[must_use] + //~^ WARNING `must_use` + async fn test_method() -> i32 { + 1 + } +} + +/* FIXME(guswynn) update this test when async-fn-in-traits works +trait Doer { + #[must_use] + async fn test_trait_method() -> i32; + WARNING must_use + async fn test_other_trait() -> i32; +} + +impl Doer for Wowee { + async fn test_trait_method() -> i32 { + 1 + } + #[must_use] + async fn test_other_trait() -> i32 { + WARNING must_use + 1 + } +} +*/ + +fn main() { +} diff --git a/src/test/ui/lint/unused/unused-async.stderr b/src/test/ui/lint/unused/unused-async.stderr new file mode 100644 index 0000000000..6bbc9e2bf0 --- /dev/null +++ b/src/test/ui/lint/unused/unused-async.stderr @@ -0,0 +1,26 @@ +warning: `must_use` attribute on `async` functions applies to the anonymous `Future` returned by the function, not the value within + --> $DIR/unused-async.rs:5:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ +LL | +LL | / async fn test() -> i32 { +LL | | 1 +LL | | } + | |_- this attribute does nothing, the `Future`s returned by async functions are already `must_use` + | + = note: `#[warn(unused_attributes)]` on by default + +warning: `must_use` attribute on `async` functions applies to the anonymous `Future` returned by the function, not the value within + --> $DIR/unused-async.rs:15:5 + | +LL | #[must_use] + | ^^^^^^^^^^^ +LL | +LL | / async fn test_method() -> i32 { +LL | | 1 +LL | | } + | |_____- this attribute does nothing, the `Future`s returned by async functions are already `must_use` + +warning: 2 warnings emitted + diff --git a/src/test/ui/lint/unused/unused-attr-duplicate.rs b/src/test/ui/lint/unused/unused-attr-duplicate.rs new file mode 100644 index 0000000000..074d5a92ad --- /dev/null +++ b/src/test/ui/lint/unused/unused-attr-duplicate.rs @@ -0,0 +1,108 @@ +// Tests for repeating attribute warnings. +// aux-build:lint_unused_extern_crate.rs +// compile-flags:--test +// Not tested due to extra requirements: +// - panic_handler: needs extra setup +// - target_feature: platform-specific +// - link_section: platform-specific +// - proc_macro, proc_macro_derive, proc_macro_attribute: needs to be a +// proc-macro, and have special handling for mixing. +// - unstable attributes (not going to bother) +// - no_main: extra setup +#![deny(unused_attributes)] +#![crate_name = "unused_attr_duplicate"] +#![crate_name = "unused_attr_duplicate2"] //~ ERROR unused attribute +//~^ WARN this was previously accepted +#![crate_type = "bin"] +#![crate_type = "rlib"] //~ ERROR unused attribute +//~^ WARN this was previously accepted +#![recursion_limit = "128"] +#![recursion_limit = "256"] //~ ERROR unused attribute +//~^ WARN this was previously accepted +#![type_length_limit = "1048576"] +#![type_length_limit = "1"] //~ ERROR unused attribute +//~^ WARN this was previously accepted +#![no_std] +#![no_std] //~ ERROR unused attribute +#![no_implicit_prelude] +#![no_implicit_prelude] //~ ERROR unused attribute +#![windows_subsystem = "console"] +#![windows_subsystem = "windows"] //~ ERROR unused attribute +//~^ WARN this was previously accepted +#![no_builtins] +#![no_builtins] //~ ERROR unused attribute + +#[no_link] +#[no_link] //~ ERROR unused attribute +extern crate lint_unused_extern_crate; + +#[macro_use] +#[macro_use] //~ ERROR unused attribute +pub mod m { + #[macro_export] + #[macro_export] //~ ERROR unused attribute + macro_rules! foo { + () => {}; + } +} + +#[path = "auxiliary/lint_unused_extern_crate.rs"] +#[path = "bar.rs"] //~ ERROR unused attribute +//~^ WARN this was previously accepted +pub mod from_path; + +#[test] +#[ignore] +#[ignore = "some text"] //~ ERROR unused attribute +#[should_panic] +#[should_panic(expected = "values don't match")] //~ ERROR unused attribute +//~^ WARN this was previously accepted +fn t1() {} + +#[must_use] +#[must_use = "some message"] //~ ERROR unused attribute +//~^ WARN this was previously accepted +// No warnings for #[repr], would require more logic. +#[repr(C)] +#[repr(C)] +#[non_exhaustive] +#[non_exhaustive] //~ ERROR unused attribute +pub struct X; + +#[automatically_derived] +#[automatically_derived] //~ ERROR unused attribute +impl X {} + +#[inline(always)] +#[inline(never)] //~ ERROR unused attribute +//~^ WARN this was previously accepted +#[cold] +#[cold] //~ ERROR unused attribute +#[track_caller] +#[track_caller] //~ ERROR unused attribute +pub fn xyz() {} + +// No warnings for #[link], would require more logic. +#[link(name = "rust_test_helpers", kind = "static")] +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + #[link_name = "this_does_not_exist"] //~ ERROR unused attribute + //~^ WARN this was previously accepted + #[link_name = "rust_dbg_extern_identity_u32"] + pub fn name_in_rust(v: u32) -> u32; +} + +#[export_name = "exported_symbol_name"] //~ ERROR unused attribute +//~^ WARN this was previously accepted +#[export_name = "exported_symbol_name2"] +pub fn export_test() {} + +#[no_mangle] +#[no_mangle] //~ ERROR unused attribute +pub fn no_mangle_test() {} + +#[used] +#[used] //~ ERROR unused attribute +static FOO: u32 = 0; + +fn main() {} diff --git a/src/test/ui/lint/unused/unused-attr-duplicate.stderr b/src/test/ui/lint/unused/unused-attr-duplicate.stderr new file mode 100644 index 0000000000..d4305add0a --- /dev/null +++ b/src/test/ui/lint/unused/unused-attr-duplicate.stderr @@ -0,0 +1,306 @@ +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:36:1 + | +LL | #[no_link] + | ^^^^^^^^^^ help: remove this attribute + | +note: the lint level is defined here + --> $DIR/unused-attr-duplicate.rs:12:9 + | +LL | #![deny(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:35:1 + | +LL | #[no_link] + | ^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:40:1 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:39:1 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:50:1 + | +LL | #[path = "bar.rs"] + | ^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:49:1 + | +LL | #[path = "auxiliary/lint_unused_extern_crate.rs"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:56:1 + | +LL | #[ignore = "some text"] + | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:55:1 + | +LL | #[ignore] + | ^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:58:1 + | +LL | #[should_panic(expected = "values don't match")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:57:1 + | +LL | #[should_panic] + | ^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:63:1 + | +LL | #[must_use = "some message"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:62:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:69:1 + | +LL | #[non_exhaustive] + | ^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:68:1 + | +LL | #[non_exhaustive] + | ^^^^^^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:73:1 + | +LL | #[automatically_derived] + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:72:1 + | +LL | #[automatically_derived] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:77:1 + | +LL | #[inline(never)] + | ^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:76:1 + | +LL | #[inline(always)] + | ^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:80:1 + | +LL | #[cold] + | ^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:79:1 + | +LL | #[cold] + | ^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:82:1 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:81:1 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:95:1 + | +LL | #[export_name = "exported_symbol_name"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:97:1 + | +LL | #[export_name = "exported_symbol_name2"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:101:1 + | +LL | #[no_mangle] + | ^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:100:1 + | +LL | #[no_mangle] + | ^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:105:1 + | +LL | #[used] + | ^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:104:1 + | +LL | #[used] + | ^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:89:5 + | +LL | #[link_name = "this_does_not_exist"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:91:5 + | +LL | #[link_name = "rust_dbg_extern_identity_u32"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:14:1 + | +LL | #![crate_name = "unused_attr_duplicate2"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:13:1 + | +LL | #![crate_name = "unused_attr_duplicate"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:17:1 + | +LL | #![crate_type = "rlib"] + | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:16:1 + | +LL | #![crate_type = "bin"] + | ^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:20:1 + | +LL | #![recursion_limit = "256"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:19:1 + | +LL | #![recursion_limit = "128"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:23:1 + | +LL | #![type_length_limit = "1"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:22:1 + | +LL | #![type_length_limit = "1048576"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:26:1 + | +LL | #![no_std] + | ^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:25:1 + | +LL | #![no_std] + | ^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:28:1 + | +LL | #![no_implicit_prelude] + | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:27:1 + | +LL | #![no_implicit_prelude] + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:30:1 + | +LL | #![windows_subsystem = "windows"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:29:1 + | +LL | #![windows_subsystem = "console"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:33:1 + | +LL | #![no_builtins] + | ^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:32:1 + | +LL | #![no_builtins] + | ^^^^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:43:5 + | +LL | #[macro_export] + | ^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:42:5 + | +LL | #[macro_export] + | ^^^^^^^^^^^^^^^ + +error: aborting due to 24 previous errors + diff --git a/src/test/ui/lint/unused/unused-macro-rules.stderr b/src/test/ui/lint/unused/unused-macro-rules.stderr index 6812a1d8f6..59db35b411 100644 --- a/src/test/ui/lint/unused/unused-macro-rules.stderr +++ b/src/test/ui/lint/unused/unused-macro-rules.stderr @@ -1,10 +1,8 @@ -error: unused macro definition - --> $DIR/unused-macro-rules.rs:4:1 +error: unused macro definition: `unused` + --> $DIR/unused-macro-rules.rs:4:14 | -LL | / macro_rules! unused { -LL | | () => {}; -LL | | } - | |_^ +LL | macro_rules! unused { + | ^^^^^^ | note: the lint level is defined here --> $DIR/unused-macro-rules.rs:1:9 @@ -12,26 +10,17 @@ note: the lint level is defined here LL | #![deny(unused_macros)] | ^^^^^^^^^^^^^ -error: unused macro definition - --> $DIR/unused-macro-rules.rs:11:9 +error: unused macro definition: `m` + --> $DIR/unused-macro-rules.rs:11:22 | -LL | / macro_rules! m { -LL | | () => {}; -LL | | } - | |_________^ -... -LL | create_macro!(); - | --------------- in this macro invocation - | - = note: this error originates in the macro `create_macro` (in Nightly builds, run with -Z macro-backtrace for more info) +LL | macro_rules! m { + | ^ -error: unused macro definition - --> $DIR/unused-macro-rules.rs:24:5 +error: unused macro definition: `unused` + --> $DIR/unused-macro-rules.rs:24:18 | -LL | / macro_rules! unused { -LL | | () => {}; -LL | | } - | |_____^ +LL | macro_rules! unused { + | ^^^^^^ | note: the lint level is defined here --> $DIR/unused-macro-rules.rs:23:12 diff --git a/src/test/ui/lint/unused/unused-macro.stderr b/src/test/ui/lint/unused/unused-macro.stderr index f5eb76179b..1a73279ed6 100644 --- a/src/test/ui/lint/unused/unused-macro.stderr +++ b/src/test/ui/lint/unused/unused-macro.stderr @@ -1,10 +1,8 @@ -error: unused macro definition - --> $DIR/unused-macro.rs:5:1 +error: unused macro definition: `unused` + --> $DIR/unused-macro.rs:5:7 | -LL | / macro unused { -LL | | () => {} -LL | | } - | |_^ +LL | macro unused { + | ^^^^^^ | note: the lint level is defined here --> $DIR/unused-macro.rs:2:9 @@ -12,13 +10,11 @@ note: the lint level is defined here LL | #![deny(unused_macros)] | ^^^^^^^^^^^^^ -error: unused macro definition - --> $DIR/unused-macro.rs:15:5 +error: unused macro definition: `unused` + --> $DIR/unused-macro.rs:15:11 | -LL | / macro unused { -LL | | () => {} -LL | | } - | |_____^ +LL | macro unused { + | ^^^^^^ | note: the lint level is defined here --> $DIR/unused-macro.rs:14:12 @@ -26,13 +22,11 @@ note: the lint level is defined here LL | #[deny(unused_macros)] | ^^^^^^^^^^^^^ -error: unused macro definition - --> $DIR/unused-macro.rs:21:5 +error: unused macro definition: `unused` + --> $DIR/unused-macro.rs:21:22 | -LL | / pub(crate) macro unused { -LL | | () => {} -LL | | } - | |_____^ +LL | pub(crate) macro unused { + | ^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/lint/unused_parens_json_suggestion.fixed b/src/test/ui/lint/unused_parens_json_suggestion.fixed index 15ee19755b..c400454046 100644 --- a/src/test/ui/lint/unused_parens_json_suggestion.fixed +++ b/src/test/ui/lint/unused_parens_json_suggestion.fixed @@ -1,4 +1,4 @@ -// compile-flags: --error-format json -Zunstable-options +// compile-flags: --error-format json // run-rustfix // The output for humans should just highlight the whole span without showing diff --git a/src/test/ui/lint/unused_parens_json_suggestion.rs b/src/test/ui/lint/unused_parens_json_suggestion.rs index d72df21e09..962c8bdd7d 100644 --- a/src/test/ui/lint/unused_parens_json_suggestion.rs +++ b/src/test/ui/lint/unused_parens_json_suggestion.rs @@ -1,4 +1,4 @@ -// compile-flags: --error-format json -Zunstable-options +// compile-flags: --error-format json // run-rustfix // The output for humans should just highlight the whole span without showing diff --git a/src/test/ui/lint/unused_parens_json_suggestion.stderr b/src/test/ui/lint/unused_parens_json_suggestion.stderr index 498c25d2e1..169fb82402 100644 --- a/src/test/ui/lint/unused_parens_json_suggestion.stderr +++ b/src/test/ui/lint/unused_parens_json_suggestion.stderr @@ -1,4 +1,4 @@ -{"message":"unnecessary parentheses around assigned value","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":596,"byte_end":597,"line_start":16,"line_end":16,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3)); +{"message":"unnecessary parentheses around assigned value","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":577,"byte_end":578,"line_start":16,"line_end":16,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3)); --> $DIR/unused_parens_json_suggestion.rs:16:14 | LL | let _a = (1 / (2 + 3)); diff --git a/src/test/ui/lint/unused_parens_remove_json_suggestion.fixed b/src/test/ui/lint/unused_parens_remove_json_suggestion.fixed index 1d891d328d..8a57cd5738 100644 --- a/src/test/ui/lint/unused_parens_remove_json_suggestion.fixed +++ b/src/test/ui/lint/unused_parens_remove_json_suggestion.fixed @@ -1,4 +1,4 @@ -// compile-flags: --error-format json -Zunstable-options +// compile-flags: --error-format json // run-rustfix // The output for humans should just highlight the whole span without showing diff --git a/src/test/ui/lint/unused_parens_remove_json_suggestion.rs b/src/test/ui/lint/unused_parens_remove_json_suggestion.rs index 494cd18450..952332d54e 100644 --- a/src/test/ui/lint/unused_parens_remove_json_suggestion.rs +++ b/src/test/ui/lint/unused_parens_remove_json_suggestion.rs @@ -1,4 +1,4 @@ -// compile-flags: --error-format json -Zunstable-options +// compile-flags: --error-format json // run-rustfix // The output for humans should just highlight the whole span without showing diff --git a/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr b/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr index 08291b10fc..43367aaa91 100644 --- a/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr +++ b/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr @@ -1,4 +1,4 @@ -{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":500,"byte_end":501,"line_start":17,"line_end":17,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (_b) { +{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":481,"byte_end":482,"line_start":17,"line_end":17,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (_b) { --> $DIR/unused_parens_remove_json_suggestion.rs:17:8 | LL | if (_b) { @@ -16,7 +16,7 @@ LL + if _b { | "} -{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":631,"byte_end":632,"line_start":28,"line_end":28,"column_start":7,"column_end":8,"is_primary":true,"text":[{"text":" if(c) { +{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":612,"byte_end":613,"line_start":28,"line_end":28,"column_start":7,"column_end":8,"is_primary":true,"text":[{"text":" if(c) { --> $DIR/unused_parens_remove_json_suggestion.rs:28:7 | LL | if(c) { @@ -29,7 +29,7 @@ LL + if c { | "} -{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":711,"byte_end":712,"line_start":32,"line_end":32,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (c){ +{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":692,"byte_end":693,"line_start":32,"line_end":32,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (c){ --> $DIR/unused_parens_remove_json_suggestion.rs:32:8 | LL | if (c){ @@ -42,7 +42,7 @@ LL + if c { | "} -{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":793,"byte_end":794,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":807,"byte_end":808,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":793,"byte_end":794,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":807,"byte_end":808,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition +{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":774,"byte_end":775,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":788,"byte_end":789,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":774,"byte_end":775,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":788,"byte_end":789,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition --> $DIR/unused_parens_remove_json_suggestion.rs:36:11 | LL | while (false && true){ @@ -55,7 +55,7 @@ LL + while false && true { | "} -{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":821,"byte_end":822,"line_start":37,"line_end":37,"column_start":12,"column_end":13,"is_primary":true,"text":[{"text":" if (c) { +{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":802,"byte_end":803,"line_start":37,"line_end":37,"column_start":12,"column_end":13,"is_primary":true,"text":[{"text":" if (c) { --> $DIR/unused_parens_remove_json_suggestion.rs:37:12 | LL | if (c) { @@ -68,7 +68,7 @@ LL + if c { | "} -{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":918,"byte_end":919,"line_start":43,"line_end":43,"column_start":10,"column_end":11,"is_primary":true,"text":[{"text":" while(true && false) { +{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":899,"byte_end":900,"line_start":43,"line_end":43,"column_start":10,"column_end":11,"is_primary":true,"text":[{"text":" while(true && false) { --> $DIR/unused_parens_remove_json_suggestion.rs:43:10 | LL | while(true && false) { @@ -81,7 +81,7 @@ LL + while true && false { | "} -{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":987,"byte_end":988,"line_start":44,"line_end":44,"column_start":18,"column_end":19,"is_primary":true,"text":[{"text":" for _ in (0 .. 3){ +{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":968,"byte_end":969,"line_start":44,"line_end":44,"column_start":18,"column_end":19,"is_primary":true,"text":[{"text":" for _ in (0 .. 3){ --> $DIR/unused_parens_remove_json_suggestion.rs:44:18 | LL | for _ in (0 .. 3){ @@ -94,7 +94,7 @@ LL + for _ in 0 .. 3 { | "} -{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1088,"byte_end":1089,"line_start":49,"line_end":49,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" for _ in (0 .. 3) { +{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1069,"byte_end":1070,"line_start":49,"line_end":49,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" for _ in (0 .. 3) { --> $DIR/unused_parens_remove_json_suggestion.rs:49:14 | LL | for _ in (0 .. 3) { @@ -107,7 +107,7 @@ LL + for _ in 0 .. 3 { | "} -{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1147,"byte_end":1148,"line_start":50,"line_end":50,"column_start":15,"column_end":16,"is_primary":true,"text":[{"text":" while (true && false) { +{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1128,"byte_end":1129,"line_start":50,"line_end":50,"column_start":15,"column_end":16,"is_primary":true,"text":[{"text":" while (true && false) { --> $DIR/unused_parens_remove_json_suggestion.rs:50:15 | LL | while (true && false) { diff --git a/src/test/ui/warn-ctypes-inhibit.rs b/src/test/ui/lint/warn-ctypes-inhibit.rs similarity index 100% rename from src/test/ui/warn-ctypes-inhibit.rs rename to src/test/ui/lint/warn-ctypes-inhibit.rs diff --git a/src/test/ui/warn-path-statement.rs b/src/test/ui/lint/warn-path-statement.rs similarity index 100% rename from src/test/ui/warn-path-statement.rs rename to src/test/ui/lint/warn-path-statement.rs diff --git a/src/test/ui/warn-path-statement.stderr b/src/test/ui/lint/warn-path-statement.stderr similarity index 100% rename from src/test/ui/warn-path-statement.stderr rename to src/test/ui/lint/warn-path-statement.stderr diff --git a/src/test/ui/liveness-assign-imm-local-after-ret.rs b/src/test/ui/liveness/liveness-assign-imm-local-after-ret.rs similarity index 100% rename from src/test/ui/liveness-assign-imm-local-after-ret.rs rename to src/test/ui/liveness/liveness-assign-imm-local-after-ret.rs diff --git a/src/test/ui/issues/issue-23458.rs b/src/test/ui/llvm-asm/issue-23458.rs similarity index 100% rename from src/test/ui/issues/issue-23458.rs rename to src/test/ui/llvm-asm/issue-23458.rs diff --git a/src/test/ui/issues/issue-23458.stderr b/src/test/ui/llvm-asm/issue-23458.stderr similarity index 100% rename from src/test/ui/issues/issue-23458.stderr rename to src/test/ui/llvm-asm/issue-23458.stderr diff --git a/src/test/ui/issues/issue-37366.rs b/src/test/ui/llvm-asm/issue-37366.rs similarity index 100% rename from src/test/ui/issues/issue-37366.rs rename to src/test/ui/llvm-asm/issue-37366.rs diff --git a/src/test/ui/issues/issue-53787-inline-assembler-macro.rs b/src/test/ui/llvm-asm/issue-53787-inline-assembler-macro.rs similarity index 100% rename from src/test/ui/issues/issue-53787-inline-assembler-macro.rs rename to src/test/ui/llvm-asm/issue-53787-inline-assembler-macro.rs diff --git a/src/test/ui/issues/issue-53787-inline-assembler-macro.stderr b/src/test/ui/llvm-asm/issue-53787-inline-assembler-macro.stderr similarity index 100% rename from src/test/ui/issues/issue-53787-inline-assembler-macro.stderr rename to src/test/ui/llvm-asm/issue-53787-inline-assembler-macro.stderr diff --git a/src/test/ui/thinlto/all-crates.rs b/src/test/ui/lto/all-crates.rs similarity index 100% rename from src/test/ui/thinlto/all-crates.rs rename to src/test/ui/lto/all-crates.rs diff --git a/src/test/ui/auxiliary/debuginfo-lto-aux.rs b/src/test/ui/lto/auxiliary/debuginfo-lto-aux.rs similarity index 100% rename from src/test/ui/auxiliary/debuginfo-lto-aux.rs rename to src/test/ui/lto/auxiliary/debuginfo-lto-aux.rs diff --git a/src/test/ui/thinlto/auxiliary/dylib.rs b/src/test/ui/lto/auxiliary/dylib.rs similarity index 100% rename from src/test/ui/thinlto/auxiliary/dylib.rs rename to src/test/ui/lto/auxiliary/dylib.rs diff --git a/src/test/ui/auxiliary/lto-duplicate-symbols1.rs b/src/test/ui/lto/auxiliary/lto-duplicate-symbols1.rs similarity index 100% rename from src/test/ui/auxiliary/lto-duplicate-symbols1.rs rename to src/test/ui/lto/auxiliary/lto-duplicate-symbols1.rs diff --git a/src/test/ui/auxiliary/lto-duplicate-symbols2.rs b/src/test/ui/lto/auxiliary/lto-duplicate-symbols2.rs similarity index 100% rename from src/test/ui/auxiliary/lto-duplicate-symbols2.rs rename to src/test/ui/lto/auxiliary/lto-duplicate-symbols2.rs diff --git a/src/test/ui/auxiliary/lto-rustc-loads-linker-plugin.rs b/src/test/ui/lto/auxiliary/lto-rustc-loads-linker-plugin.rs similarity index 100% rename from src/test/ui/auxiliary/lto-rustc-loads-linker-plugin.rs rename to src/test/ui/lto/auxiliary/lto-rustc-loads-linker-plugin.rs diff --git a/src/test/ui/thinlto/auxiliary/msvc-imp-present.rs b/src/test/ui/lto/auxiliary/msvc-imp-present.rs similarity index 100% rename from src/test/ui/thinlto/auxiliary/msvc-imp-present.rs rename to src/test/ui/lto/auxiliary/msvc-imp-present.rs diff --git a/src/test/ui/thinlto/auxiliary/thin-lto-inlines-aux.rs b/src/test/ui/lto/auxiliary/thin-lto-inlines-aux.rs similarity index 100% rename from src/test/ui/thinlto/auxiliary/thin-lto-inlines-aux.rs rename to src/test/ui/lto/auxiliary/thin-lto-inlines-aux.rs diff --git a/src/test/ui/debuginfo-lto.rs b/src/test/ui/lto/debuginfo-lto.rs similarity index 100% rename from src/test/ui/debuginfo-lto.rs rename to src/test/ui/lto/debuginfo-lto.rs diff --git a/src/test/ui/thinlto/dylib-works.rs b/src/test/ui/lto/dylib-works.rs similarity index 100% rename from src/test/ui/thinlto/dylib-works.rs rename to src/test/ui/lto/dylib-works.rs diff --git a/src/test/ui/fat-lto.rs b/src/test/ui/lto/fat-lto.rs similarity index 100% rename from src/test/ui/fat-lto.rs rename to src/test/ui/lto/fat-lto.rs diff --git a/src/test/ui/lto-and-no-bitcode-in-rlib.rs b/src/test/ui/lto/lto-and-no-bitcode-in-rlib.rs similarity index 100% rename from src/test/ui/lto-and-no-bitcode-in-rlib.rs rename to src/test/ui/lto/lto-and-no-bitcode-in-rlib.rs diff --git a/src/test/ui/lto-and-no-bitcode-in-rlib.stderr b/src/test/ui/lto/lto-and-no-bitcode-in-rlib.stderr similarity index 100% rename from src/test/ui/lto-and-no-bitcode-in-rlib.stderr rename to src/test/ui/lto/lto-and-no-bitcode-in-rlib.stderr diff --git a/src/test/ui/lto-duplicate-symbols.rs b/src/test/ui/lto/lto-duplicate-symbols.rs similarity index 100% rename from src/test/ui/lto-duplicate-symbols.rs rename to src/test/ui/lto/lto-duplicate-symbols.rs diff --git a/src/test/ui/lto-duplicate-symbols.stderr b/src/test/ui/lto/lto-duplicate-symbols.stderr similarity index 100% rename from src/test/ui/lto-duplicate-symbols.stderr rename to src/test/ui/lto/lto-duplicate-symbols.stderr diff --git a/src/test/ui/lto-many-codegen-units.rs b/src/test/ui/lto/lto-many-codegen-units.rs similarity index 100% rename from src/test/ui/lto-many-codegen-units.rs rename to src/test/ui/lto/lto-many-codegen-units.rs diff --git a/src/test/ui/lto-opt-level-s.rs b/src/test/ui/lto/lto-opt-level-s.rs similarity index 100% rename from src/test/ui/lto-opt-level-s.rs rename to src/test/ui/lto/lto-opt-level-s.rs diff --git a/src/test/ui/lto-opt-level-z.rs b/src/test/ui/lto/lto-opt-level-z.rs similarity index 100% rename from src/test/ui/lto-opt-level-z.rs rename to src/test/ui/lto/lto-opt-level-z.rs diff --git a/src/test/ui/lto-rustc-loads-linker-plugin.rs b/src/test/ui/lto/lto-rustc-loads-linker-plugin.rs similarity index 100% rename from src/test/ui/lto-rustc-loads-linker-plugin.rs rename to src/test/ui/lto/lto-rustc-loads-linker-plugin.rs diff --git a/src/test/ui/lto-still-runs-thread-dtors.rs b/src/test/ui/lto/lto-still-runs-thread-dtors.rs similarity index 100% rename from src/test/ui/lto-still-runs-thread-dtors.rs rename to src/test/ui/lto/lto-still-runs-thread-dtors.rs diff --git a/src/test/ui/lto-thin-rustc-loads-linker-plugin.rs b/src/test/ui/lto/lto-thin-rustc-loads-linker-plugin.rs similarity index 100% rename from src/test/ui/lto-thin-rustc-loads-linker-plugin.rs rename to src/test/ui/lto/lto-thin-rustc-loads-linker-plugin.rs diff --git a/src/test/ui/thinlto/msvc-imp-present.rs b/src/test/ui/lto/msvc-imp-present.rs similarity index 100% rename from src/test/ui/thinlto/msvc-imp-present.rs rename to src/test/ui/lto/msvc-imp-present.rs diff --git a/src/test/ui/thin-lto-global-allocator.rs b/src/test/ui/lto/thin-lto-global-allocator.rs similarity index 100% rename from src/test/ui/thin-lto-global-allocator.rs rename to src/test/ui/lto/thin-lto-global-allocator.rs diff --git a/src/test/ui/thinlto/thin-lto-inlines.rs b/src/test/ui/lto/thin-lto-inlines.rs similarity index 100% rename from src/test/ui/thinlto/thin-lto-inlines.rs rename to src/test/ui/lto/thin-lto-inlines.rs diff --git a/src/test/ui/thinlto/thin-lto-inlines2.rs b/src/test/ui/lto/thin-lto-inlines2.rs similarity index 100% rename from src/test/ui/thinlto/thin-lto-inlines2.rs rename to src/test/ui/lto/thin-lto-inlines2.rs diff --git a/src/test/ui/thinlto/weak-works.rs b/src/test/ui/lto/weak-works.rs similarity index 100% rename from src/test/ui/thinlto/weak-works.rs rename to src/test/ui/lto/weak-works.rs diff --git a/src/test/ui/macros/ambiguity-legacy-vs-modern.stderr b/src/test/ui/macros/ambiguity-legacy-vs-modern.stderr index d9a0a9f005..330aa6acf3 100644 --- a/src/test/ui/macros/ambiguity-legacy-vs-modern.stderr +++ b/src/test/ui/macros/ambiguity-legacy-vs-modern.stderr @@ -1,9 +1,10 @@ -error[E0659]: `m` is ambiguous (`macro_rules` vs non-`macro_rules` from other module) +error[E0659]: `m` is ambiguous --> $DIR/ambiguity-legacy-vs-modern.rs:31:9 | LL | m!() | ^ ambiguous name | + = note: ambiguous because of a conflict between a `macro_rules` name and a non-`macro_rules` name from another module note: `m` could refer to the macro defined here --> $DIR/ambiguity-legacy-vs-modern.rs:26:5 | @@ -15,12 +16,13 @@ note: `m` could also refer to the macro defined here LL | macro m() { 0 } | ^^^^^^^^^^^^^^^ -error[E0659]: `m` is ambiguous (`macro_rules` vs non-`macro_rules` from other module) +error[E0659]: `m` is ambiguous --> $DIR/ambiguity-legacy-vs-modern.rs:43:5 | LL | m!() | ^ ambiguous name | + = note: ambiguous because of a conflict between a `macro_rules` name and a non-`macro_rules` name from another module note: `m` could refer to the macro defined here --> $DIR/ambiguity-legacy-vs-modern.rs:40:9 | diff --git a/src/test/ui/issues/auxiliary/issue-19163.rs b/src/test/ui/macros/auxiliary/issue-19163.rs similarity index 100% rename from src/test/ui/issues/auxiliary/issue-19163.rs rename to src/test/ui/macros/auxiliary/issue-19163.rs diff --git a/src/test/ui/auxiliary/proc_macro_def.rs b/src/test/ui/macros/auxiliary/proc_macro_def.rs similarity index 100% rename from src/test/ui/auxiliary/proc_macro_def.rs rename to src/test/ui/macros/auxiliary/proc_macro_def.rs diff --git a/src/test/ui/concat.rs b/src/test/ui/macros/concat.rs similarity index 100% rename from src/test/ui/concat.rs rename to src/test/ui/macros/concat.rs diff --git a/src/test/ui/concat.stderr b/src/test/ui/macros/concat.stderr similarity index 100% rename from src/test/ui/concat.stderr rename to src/test/ui/macros/concat.stderr diff --git a/src/test/ui/include-single-expr-helper-1.rs b/src/test/ui/macros/include-single-expr-helper-1.rs similarity index 100% rename from src/test/ui/include-single-expr-helper-1.rs rename to src/test/ui/macros/include-single-expr-helper-1.rs diff --git a/src/test/ui/include-single-expr-helper.rs b/src/test/ui/macros/include-single-expr-helper.rs similarity index 100% rename from src/test/ui/include-single-expr-helper.rs rename to src/test/ui/macros/include-single-expr-helper.rs diff --git a/src/test/ui/include-single-expr.rs b/src/test/ui/macros/include-single-expr.rs similarity index 100% rename from src/test/ui/include-single-expr.rs rename to src/test/ui/macros/include-single-expr.rs diff --git a/src/test/ui/include-single-expr.stderr b/src/test/ui/macros/include-single-expr.stderr similarity index 100% rename from src/test/ui/include-single-expr.stderr rename to src/test/ui/macros/include-single-expr.stderr diff --git a/src/test/ui/issues/issue-16098.rs b/src/test/ui/macros/issue-16098.rs similarity index 100% rename from src/test/ui/issues/issue-16098.rs rename to src/test/ui/macros/issue-16098.rs diff --git a/src/test/ui/issues/issue-16098.stderr b/src/test/ui/macros/issue-16098.stderr similarity index 100% rename from src/test/ui/issues/issue-16098.stderr rename to src/test/ui/macros/issue-16098.stderr diff --git a/src/test/ui/issues/issue-19163.rs b/src/test/ui/macros/issue-19163.rs similarity index 100% rename from src/test/ui/issues/issue-19163.rs rename to src/test/ui/macros/issue-19163.rs diff --git a/src/test/ui/issues/issue-19163.stderr b/src/test/ui/macros/issue-19163.stderr similarity index 100% rename from src/test/ui/issues/issue-19163.stderr rename to src/test/ui/macros/issue-19163.stderr diff --git a/src/test/ui/issues/issue-21356.rs b/src/test/ui/macros/issue-21356.rs similarity index 100% rename from src/test/ui/issues/issue-21356.rs rename to src/test/ui/macros/issue-21356.rs diff --git a/src/test/ui/issues/issue-21356.stderr b/src/test/ui/macros/issue-21356.stderr similarity index 100% rename from src/test/ui/issues/issue-21356.stderr rename to src/test/ui/macros/issue-21356.stderr diff --git a/src/test/ui/issues/issue-22463.rs b/src/test/ui/macros/issue-22463.rs similarity index 100% rename from src/test/ui/issues/issue-22463.rs rename to src/test/ui/macros/issue-22463.rs diff --git a/src/test/ui/issues/issue-29084.rs b/src/test/ui/macros/issue-29084.rs similarity index 100% rename from src/test/ui/issues/issue-29084.rs rename to src/test/ui/macros/issue-29084.rs diff --git a/src/test/ui/issues/issue-29084.stderr b/src/test/ui/macros/issue-29084.stderr similarity index 100% rename from src/test/ui/issues/issue-29084.stderr rename to src/test/ui/macros/issue-29084.stderr diff --git a/src/test/ui/issues/issue-34171.rs b/src/test/ui/macros/issue-34171.rs similarity index 100% rename from src/test/ui/issues/issue-34171.rs rename to src/test/ui/macros/issue-34171.rs diff --git a/src/test/ui/issues/issue-37175.rs b/src/test/ui/macros/issue-37175.rs similarity index 100% rename from src/test/ui/issues/issue-37175.rs rename to src/test/ui/macros/issue-37175.rs diff --git a/src/test/ui/issues/issue-39388.rs b/src/test/ui/macros/issue-39388.rs similarity index 100% rename from src/test/ui/issues/issue-39388.rs rename to src/test/ui/macros/issue-39388.rs diff --git a/src/test/ui/issues/issue-39388.stderr b/src/test/ui/macros/issue-39388.stderr similarity index 100% rename from src/test/ui/issues/issue-39388.stderr rename to src/test/ui/macros/issue-39388.stderr diff --git a/src/test/ui/issues/issue-40770.rs b/src/test/ui/macros/issue-40770.rs similarity index 100% rename from src/test/ui/issues/issue-40770.rs rename to src/test/ui/macros/issue-40770.rs diff --git a/src/test/ui/issues/issue-57597.rs b/src/test/ui/macros/issue-57597.rs similarity index 100% rename from src/test/ui/issues/issue-57597.rs rename to src/test/ui/macros/issue-57597.rs diff --git a/src/test/ui/issues/issue-57597.stderr b/src/test/ui/macros/issue-57597.stderr similarity index 100% rename from src/test/ui/issues/issue-57597.stderr rename to src/test/ui/macros/issue-57597.stderr diff --git a/src/test/ui/issues/issue-6596-1.rs b/src/test/ui/macros/issue-6596-1.rs similarity index 100% rename from src/test/ui/issues/issue-6596-1.rs rename to src/test/ui/macros/issue-6596-1.rs diff --git a/src/test/ui/issues/issue-6596-1.stderr b/src/test/ui/macros/issue-6596-1.stderr similarity index 100% rename from src/test/ui/issues/issue-6596-1.stderr rename to src/test/ui/macros/issue-6596-1.stderr diff --git a/src/test/ui/issues/issue-86865.rs b/src/test/ui/macros/issue-86865.rs similarity index 100% rename from src/test/ui/issues/issue-86865.rs rename to src/test/ui/macros/issue-86865.rs diff --git a/src/test/ui/issues/issue-86865.stderr b/src/test/ui/macros/issue-86865.stderr similarity index 100% rename from src/test/ui/issues/issue-86865.stderr rename to src/test/ui/macros/issue-86865.stderr diff --git a/src/test/ui/macros/macro-path-prelude-shadowing.stderr b/src/test/ui/macros/macro-path-prelude-shadowing.stderr index 7bbb8eddb7..4a864c2e92 100644 --- a/src/test/ui/macros/macro-path-prelude-shadowing.stderr +++ b/src/test/ui/macros/macro-path-prelude-shadowing.stderr @@ -1,9 +1,10 @@ -error[E0659]: `std` is ambiguous (glob import vs any other name from outer scope during import/macro resolution) +error[E0659]: `std` is ambiguous --> $DIR/macro-path-prelude-shadowing.rs:29:9 | LL | std::panic!(); | ^^^ ambiguous name | + = note: ambiguous because of a conflict between a name from a glob import and an outer scope during import or macro resolution = note: `std` could refer to a built-in crate note: `std` could also refer to the module imported here --> $DIR/macro-path-prelude-shadowing.rs:27:9 diff --git a/src/test/ui/macros/macro-shadowing.stderr b/src/test/ui/macros/macro-shadowing.stderr index 58224b7073..a052b43ac1 100644 --- a/src/test/ui/macros/macro-shadowing.stderr +++ b/src/test/ui/macros/macro-shadowing.stderr @@ -10,12 +10,13 @@ LL | m1!(); = note: macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560) = note: this error originates in the macro `m1` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0659]: `foo` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) +error[E0659]: `foo` is ambiguous --> $DIR/macro-shadowing.rs:17:1 | LL | foo!(); | ^^^ ambiguous name | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution note: `foo` could refer to the macro defined here --> $DIR/macro-shadowing.rs:10:5 | diff --git a/src/test/ui/macros/macro-use-all-and-none.stderr b/src/test/ui/macros/macro-use-all-and-none.stderr index bdee5f4d87..6de7ffb2f6 100644 --- a/src/test/ui/macros/macro-use-all-and-none.stderr +++ b/src/test/ui/macros/macro-use-all-and-none.stderr @@ -2,13 +2,14 @@ warning: unused attribute --> $DIR/macro-use-all-and-none.rs:7:1 | LL | #[macro_use()] - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ help: remove this attribute | note: the lint level is defined here --> $DIR/macro-use-all-and-none.rs:4:9 | LL | #![warn(unused_attributes)] | ^^^^^^^^^^^^^^^^^ + = note: attribute `macro_use` with an empty list has no effect warning: 1 warning emitted diff --git a/src/test/ui/malformed_macro_lhs.rs b/src/test/ui/macros/malformed_macro_lhs.rs similarity index 100% rename from src/test/ui/malformed_macro_lhs.rs rename to src/test/ui/macros/malformed_macro_lhs.rs diff --git a/src/test/ui/malformed_macro_lhs.stderr b/src/test/ui/macros/malformed_macro_lhs.stderr similarity index 100% rename from src/test/ui/malformed_macro_lhs.stderr rename to src/test/ui/macros/malformed_macro_lhs.stderr diff --git a/src/test/ui/macros/missing-bang-in-decl.fixed b/src/test/ui/macros/missing-bang-in-decl.fixed new file mode 100644 index 0000000000..b1aa3298bf --- /dev/null +++ b/src/test/ui/macros/missing-bang-in-decl.fixed @@ -0,0 +1,16 @@ +// run-rustfix + +#![allow(unused_macros)] + +macro_rules! foo { + //~^ ERROR expected `!` after `macro_rules` + () => {}; +} + +macro_rules! bar { + //~^ ERROR expected `!` after `macro_rules` + //~^^ ERROR macro names aren't followed by a `!` + () => {}; +} + +fn main() {} diff --git a/src/test/ui/macros/missing-bang-in-decl.rs b/src/test/ui/macros/missing-bang-in-decl.rs new file mode 100644 index 0000000000..8393f15fc5 --- /dev/null +++ b/src/test/ui/macros/missing-bang-in-decl.rs @@ -0,0 +1,16 @@ +// run-rustfix + +#![allow(unused_macros)] + +macro_rules foo { + //~^ ERROR expected `!` after `macro_rules` + () => {}; +} + +macro_rules bar! { + //~^ ERROR expected `!` after `macro_rules` + //~^^ ERROR macro names aren't followed by a `!` + () => {}; +} + +fn main() {} diff --git a/src/test/ui/macros/missing-bang-in-decl.stderr b/src/test/ui/macros/missing-bang-in-decl.stderr new file mode 100644 index 0000000000..dfabafb0a7 --- /dev/null +++ b/src/test/ui/macros/missing-bang-in-decl.stderr @@ -0,0 +1,20 @@ +error: expected `!` after `macro_rules` + --> $DIR/missing-bang-in-decl.rs:5:1 + | +LL | macro_rules foo { + | ^^^^^^^^^^^ help: add a `!`: `macro_rules!` + +error: expected `!` after `macro_rules` + --> $DIR/missing-bang-in-decl.rs:10:1 + | +LL | macro_rules bar! { + | ^^^^^^^^^^^ help: add a `!`: `macro_rules!` + +error: macro names aren't followed by a `!` + --> $DIR/missing-bang-in-decl.rs:10:16 + | +LL | macro_rules bar! { + | ^ help: remove the `!` + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/no-std-macros.rs b/src/test/ui/macros/no-std-macros.rs similarity index 100% rename from src/test/ui/no-std-macros.rs rename to src/test/ui/macros/no-std-macros.rs diff --git a/src/test/ui/macros/out-of-order-shadowing.stderr b/src/test/ui/macros/out-of-order-shadowing.stderr index 6b11916707..dedefac5c4 100644 --- a/src/test/ui/macros/out-of-order-shadowing.stderr +++ b/src/test/ui/macros/out-of-order-shadowing.stderr @@ -1,9 +1,10 @@ -error[E0659]: `bar` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) +error[E0659]: `bar` is ambiguous --> $DIR/out-of-order-shadowing.rs:5:1 | LL | bar!(); | ^^^ ambiguous name | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution note: `bar` could refer to the macro defined here --> $DIR/out-of-order-shadowing.rs:4:1 | diff --git a/src/test/ui/proc_macro.rs b/src/test/ui/macros/proc_macro.rs similarity index 100% rename from src/test/ui/proc_macro.rs rename to src/test/ui/macros/proc_macro.rs diff --git a/src/test/ui/macros/restricted-shadowing-legacy.stderr b/src/test/ui/macros/restricted-shadowing-legacy.stderr index 4912166883..99b27a5cab 100644 --- a/src/test/ui/macros/restricted-shadowing-legacy.stderr +++ b/src/test/ui/macros/restricted-shadowing-legacy.stderr @@ -1,4 +1,4 @@ -error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) +error[E0659]: `m` is ambiguous --> $DIR/restricted-shadowing-legacy.rs:101:13 | LL | m!(); @@ -7,6 +7,7 @@ LL | m!(); LL | include!(); | ---------- in this macro invocation | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 | @@ -25,7 +26,7 @@ LL | include!(); | ---------- in this macro invocation = note: this error originates in the macro `gen_gen_inner_invoc` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) +error[E0659]: `m` is ambiguous --> $DIR/restricted-shadowing-legacy.rs:139:42 | LL | macro_rules! gen_invoc { () => { m!() } } @@ -34,6 +35,7 @@ LL | macro_rules! gen_invoc { () => { m!() } } LL | include!(); | ---------- in this macro invocation | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 | @@ -52,7 +54,7 @@ LL | include!(); | ---------- in this macro invocation = note: this error originates in the macro `gen_invoc` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) +error[E0659]: `m` is ambiguous --> $DIR/restricted-shadowing-legacy.rs:148:9 | LL | m!(); @@ -61,6 +63,7 @@ LL | m!(); LL | include!(); | ---------- in this macro invocation | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 | @@ -79,7 +82,7 @@ LL | include!(); | ---------- in this macro invocation = note: this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) +error[E0659]: `m` is ambiguous --> $DIR/restricted-shadowing-legacy.rs:164:9 | LL | m!(); @@ -88,6 +91,7 @@ LL | m!(); LL | include!(); | ---------- in this macro invocation | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 | @@ -106,7 +110,7 @@ LL | include!(); | ---------- in this macro invocation = note: this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) +error[E0659]: `m` is ambiguous --> $DIR/restricted-shadowing-legacy.rs:180:13 | LL | m!(); @@ -115,6 +119,7 @@ LL | m!(); LL | include!(); | ---------- in this macro invocation | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 | @@ -133,7 +138,7 @@ LL | include!(); | ---------- in this macro invocation = note: this error originates in the macro `gen_gen_inner_invoc` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) +error[E0659]: `m` is ambiguous --> $DIR/restricted-shadowing-legacy.rs:218:42 | LL | macro_rules! gen_invoc { () => { m!() } } @@ -142,6 +147,7 @@ LL | macro_rules! gen_invoc { () => { m!() } } LL | include!(); | ---------- in this macro invocation | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 | @@ -160,7 +166,7 @@ LL | include!(); | ---------- in this macro invocation = note: this error originates in the macro `gen_invoc` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) +error[E0659]: `m` is ambiguous --> $DIR/restricted-shadowing-legacy.rs:232:9 | LL | m!(); @@ -169,6 +175,7 @@ LL | m!(); LL | include!(); | ---------- in this macro invocation | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 | @@ -187,7 +194,7 @@ LL | include!(); | ---------- in this macro invocation = note: this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) +error[E0659]: `m` is ambiguous --> $DIR/restricted-shadowing-legacy.rs:262:42 | LL | macro_rules! gen_invoc { () => { m!() } } @@ -196,6 +203,7 @@ LL | macro_rules! gen_invoc { () => { m!() } } LL | include!(); | ---------- in this macro invocation | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 | diff --git a/src/test/ui/macros/restricted-shadowing-modern.stderr b/src/test/ui/macros/restricted-shadowing-modern.stderr index 62639eeb11..b169e63132 100644 --- a/src/test/ui/macros/restricted-shadowing-modern.stderr +++ b/src/test/ui/macros/restricted-shadowing-modern.stderr @@ -1,4 +1,4 @@ -error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) +error[E0659]: `m` is ambiguous --> $DIR/restricted-shadowing-modern.rs:104:17 | LL | m!(); @@ -7,6 +7,7 @@ LL | m!(); LL | include!(); | ---------- in this macro invocation | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-modern.rs:91:9 | @@ -25,7 +26,7 @@ LL | include!(); | ---------- in this macro invocation = note: this error originates in the macro `gen_gen_inner_invoc` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) +error[E0659]: `m` is ambiguous --> $DIR/restricted-shadowing-modern.rs:147:33 | LL | macro gen_invoc() { m!() } @@ -34,6 +35,7 @@ LL | macro gen_invoc() { m!() } LL | include!(); | ---------- in this macro invocation | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-modern.rs:91:9 | @@ -52,7 +54,7 @@ LL | include!(); | ---------- in this macro invocation = note: this error originates in the macro `gen_invoc` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) +error[E0659]: `m` is ambiguous --> $DIR/restricted-shadowing-modern.rs:156:13 | LL | m!(); @@ -61,6 +63,7 @@ LL | m!(); LL | include!(); | ---------- in this macro invocation | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-modern.rs:91:9 | @@ -79,7 +82,7 @@ LL | include!(); | ---------- in this macro invocation = note: this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) +error[E0659]: `m` is ambiguous --> $DIR/restricted-shadowing-modern.rs:172:13 | LL | m!(); @@ -88,6 +91,7 @@ LL | m!(); LL | include!(); | ---------- in this macro invocation | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-modern.rs:91:9 | @@ -106,7 +110,7 @@ LL | include!(); | ---------- in this macro invocation = note: this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) +error[E0659]: `m` is ambiguous --> $DIR/restricted-shadowing-modern.rs:190:17 | LL | m!(); @@ -115,6 +119,7 @@ LL | m!(); LL | include!(); | ---------- in this macro invocation | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-modern.rs:91:9 | @@ -133,7 +138,7 @@ LL | include!(); | ---------- in this macro invocation = note: this error originates in the macro `gen_gen_inner_invoc` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) +error[E0659]: `m` is ambiguous --> $DIR/restricted-shadowing-modern.rs:233:33 | LL | macro gen_invoc() { m!() } @@ -142,6 +147,7 @@ LL | macro gen_invoc() { m!() } LL | include!(); | ---------- in this macro invocation | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-modern.rs:91:9 | diff --git a/src/test/ui/trace_macros-format.rs b/src/test/ui/macros/trace_macros-format.rs similarity index 100% rename from src/test/ui/trace_macros-format.rs rename to src/test/ui/macros/trace_macros-format.rs diff --git a/src/test/ui/trace_macros-format.stderr b/src/test/ui/macros/trace_macros-format.stderr similarity index 100% rename from src/test/ui/trace_macros-format.stderr rename to src/test/ui/macros/trace_macros-format.stderr diff --git a/src/test/ui/overlap-doesnt-conflict-with-specialization.rs b/src/test/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.rs similarity index 100% rename from src/test/ui/overlap-doesnt-conflict-with-specialization.rs rename to src/test/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.rs diff --git a/src/test/ui/overlap-doesnt-conflict-with-specialization.stderr b/src/test/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.stderr similarity index 100% rename from src/test/ui/overlap-doesnt-conflict-with-specialization.stderr rename to src/test/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.stderr diff --git a/src/test/ui/overlap-permitted-for-annotated-marker-traits.rs b/src/test/ui/marker_trait_attr/overlap-permitted-for-annotated-marker-traits.rs similarity index 100% rename from src/test/ui/overlap-permitted-for-annotated-marker-traits.rs rename to src/test/ui/marker_trait_attr/overlap-permitted-for-annotated-marker-traits.rs diff --git a/src/test/ui/marker_trait_attr/region-overlap.stderr b/src/test/ui/marker_trait_attr/region-overlap.stderr index e4a94d56f1..2eeab801e3 100644 --- a/src/test/ui/marker_trait_attr/region-overlap.stderr +++ b/src/test/ui/marker_trait_attr/region-overlap.stderr @@ -4,12 +4,13 @@ error[E0283]: type annotations needed LL | impl<'a> A for (&'static (), &'a ()) {} | ^ cannot infer type for tuple `(&'static (), &'a ())` | - = note: cannot satisfy `(&'static (), &'a ()): A` -note: required by a bound in `A` - --> $DIR/region-overlap.rs:4:1 +note: multiple `impl`s satisfying `(&'static (), &'a ()): A` found + --> $DIR/region-overlap.rs:5:1 | -LL | trait A {} - | ^^^^^^^ required by this bound in `A` +LL | impl<'a> A for (&'static (), &'a ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl<'a> A for (&'a (), &'static ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0283]: type annotations needed --> $DIR/region-overlap.rs:6:10 @@ -17,12 +18,13 @@ error[E0283]: type annotations needed LL | impl<'a> A for (&'a (), &'static ()) {} | ^ cannot infer type for tuple `(&'a (), &'static ())` | - = note: cannot satisfy `(&'a (), &'static ()): A` -note: required by a bound in `A` - --> $DIR/region-overlap.rs:4:1 +note: multiple `impl`s satisfying `(&'a (), &'static ()): A` found + --> $DIR/region-overlap.rs:5:1 | -LL | trait A {} - | ^^^^^^^ required by this bound in `A` +LL | impl<'a> A for (&'static (), &'a ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl<'a> A for (&'a (), &'static ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-11940.rs b/src/test/ui/match/issue-11940.rs similarity index 100% rename from src/test/ui/issues/issue-11940.rs rename to src/test/ui/match/issue-11940.rs diff --git a/src/test/ui/issues/issue-18060.rs b/src/test/ui/match/issue-18060.rs similarity index 100% rename from src/test/ui/issues/issue-18060.rs rename to src/test/ui/match/issue-18060.rs diff --git a/src/test/ui/issues/issue-26251.rs b/src/test/ui/match/issue-26251.rs similarity index 100% rename from src/test/ui/issues/issue-26251.rs rename to src/test/ui/match/issue-26251.rs diff --git a/src/test/ui/issues/issue-26996.rs b/src/test/ui/match/issue-26996.rs similarity index 100% rename from src/test/ui/issues/issue-26996.rs rename to src/test/ui/match/issue-26996.rs diff --git a/src/test/ui/issues/issue-42679.rs b/src/test/ui/match/issue-42679.rs similarity index 100% rename from src/test/ui/issues/issue-42679.rs rename to src/test/ui/match/issue-42679.rs diff --git a/src/test/ui/match/issue-91058.rs b/src/test/ui/match/issue-91058.rs new file mode 100644 index 0000000000..4845937d54 --- /dev/null +++ b/src/test/ui/match/issue-91058.rs @@ -0,0 +1,11 @@ +struct S(()); + +fn main() { + let array = [S(())]; + + match array { + [()] => {} + //~^ ERROR mismatched types [E0308] + _ => {} + } +} diff --git a/src/test/ui/match/issue-91058.stderr b/src/test/ui/match/issue-91058.stderr new file mode 100644 index 0000000000..ec1d7e21fa --- /dev/null +++ b/src/test/ui/match/issue-91058.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/issue-91058.rs:7:10 + | +LL | match array { + | ----- this expression has type `[S; 1]` +LL | [()] => {} + | ^^ expected struct `S`, found `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/match-on-negative-integer-ranges.rs b/src/test/ui/match/match-on-negative-integer-ranges.rs similarity index 100% rename from src/test/ui/match-on-negative-integer-ranges.rs rename to src/test/ui/match/match-on-negative-integer-ranges.rs diff --git a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.rs b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.rs index 49fe7d1324..7b2fc34e1a 100644 --- a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.rs +++ b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.rs @@ -23,7 +23,7 @@ fn m1() { // we couldn't infer the type of the vector just based on calling foo()... let mut x = Vec::new(); //~^ ERROR type annotations needed - x.foo(); + x.foo(); //~ ERROR type annotations needed } fn m2() { diff --git a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr index 4b494c9611..f33672433d 100644 --- a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr +++ b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr @@ -6,6 +6,21 @@ LL | let mut x = Vec::new(); | | | consider giving `x` the explicit type `Vec<T>`, where the type parameter `T` is specified +error[E0283]: type annotations needed + --> $DIR/method-ambig-one-trait-unknown-int-type.rs:26:7 + | +LL | x.foo(); + | ^^^ cannot infer type for struct `Vec<_>` + | +note: multiple `impl`s satisfying `Vec<_>: Foo` found + --> $DIR/method-ambig-one-trait-unknown-int-type.rs:9:1 + | +LL | impl Foo for Vec<usize> { + | ^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Foo for Vec<isize> { + | ^^^^^^^^^^^^^^^^^^^^^^^ + error[E0308]: mismatched types --> $DIR/method-ambig-one-trait-unknown-int-type.rs:33:20 | @@ -19,7 +34,7 @@ help: you can convert an `isize` to a `usize` and panic if the converted value d LL | let y: usize = x.foo().try_into().unwrap(); | ++++++++++++++++++++ -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0282, E0308. +Some errors have detailed explanations: E0282, E0283, E0308. For more information about an error, try `rustc --explain E0282`. diff --git a/src/test/ui/mir-dataflow/indirect-mutation-offset.rs b/src/test/ui/mir-dataflow/indirect-mutation-offset.rs deleted file mode 100644 index 374a9f75a1..0000000000 --- a/src/test/ui/mir-dataflow/indirect-mutation-offset.rs +++ /dev/null @@ -1,48 +0,0 @@ -// compile-flags: -Zunleash-the-miri-inside-of-you - -// This test demonstrates a shortcoming of the `MaybeMutBorrowedLocals` analysis. It does not -// handle code that takes a reference to one field of a struct, then use pointer arithmetic to -// transform it to another field of that same struct that may have interior mutability. For now, -// this is UB, but this may change in the future. See [rust-lang/unsafe-code-guidelines#134]. -// -// [rust-lang/unsafe-code-guidelines#134]: https://github.com/rust-lang/unsafe-code-guidelines/issues/134 - -#![feature(core_intrinsics, rustc_attrs, const_raw_ptr_deref)] - -use std::cell::UnsafeCell; -use std::intrinsics::rustc_peek; - -#[repr(C)] -struct PartialInteriorMut { - zst: [i32; 0], - cell: UnsafeCell<i32>, -} - -#[rustc_mir(rustc_peek_indirectly_mutable,stop_after_dataflow)] -const BOO: i32 = { - let x = PartialInteriorMut { - zst: [], - cell: UnsafeCell::new(0), - }; - - let p_zst: *const _ = &x.zst ; // Doesn't cause `x` to get marked as indirectly mutable. - - let rmut_cell = unsafe { - // Take advantage of the fact that `zst` and `cell` are at the same location in memory. - // This trick would work with any size type if miri implemented `ptr::offset`. - let p_cell = p_zst as *const UnsafeCell<i32>; - - let pmut_cell = (*p_cell).get(); - &mut *pmut_cell - }; - - *rmut_cell = 42; // Mutates `x` indirectly even though `x` is not marked indirectly mutable!!! - let val = *rmut_cell; - rustc_peek(x); //~ ERROR rustc_peek: bit not set - - val -}; - -fn main() { - println!("{}", BOO); -} diff --git a/src/test/ui/mir-dataflow/indirect-mutation-offset.stderr b/src/test/ui/mir-dataflow/indirect-mutation-offset.stderr deleted file mode 100644 index 1d5287c15a..0000000000 --- a/src/test/ui/mir-dataflow/indirect-mutation-offset.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: rustc_peek: bit not set - --> $DIR/indirect-mutation-offset.rs:41:5 - | -LL | rustc_peek(x); - | ^^^^^^^^^^^^^ - -error: stop_after_dataflow ended compilation - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/issue-73914.rs b/src/test/ui/mir/issue-73914.rs similarity index 100% rename from src/test/ui/issue-73914.rs rename to src/test/ui/mir/issue-73914.rs diff --git a/src/test/ui/issues/issue-74739.rs b/src/test/ui/mir/issue-74739.rs similarity index 100% rename from src/test/ui/issues/issue-74739.rs rename to src/test/ui/mir/issue-74739.rs diff --git a/src/test/ui/mir/mir_overflow_off.rs b/src/test/ui/mir/mir_overflow_off.rs index 922ec36e53..0098584dd2 100644 --- a/src/test/ui/mir/mir_overflow_off.rs +++ b/src/test/ui/mir/mir_overflow_off.rs @@ -1,5 +1,5 @@ // run-pass -// compile-flags: -Z force-overflow-checks=off +// compile-flags: -C overflow-checks=off // Test that with MIR codegen, overflow checks can be // turned off, even when they're from core::ops::*. diff --git a/src/test/ui/mismatched_types/abridged.stderr b/src/test/ui/mismatched_types/abridged.stderr index db4e858929..ff1a836c9a 100644 --- a/src/test/ui/mismatched_types/abridged.stderr +++ b/src/test/ui/mismatched_types/abridged.stderr @@ -26,13 +26,14 @@ error[E0308]: mismatched types LL | fn b() -> Option<Foo> { | ----------- expected `Option<Foo>` because of return type LL | Foo { bar: 1 } - | ^^^^^^^^^^^^^^ - | | - | expected enum `Option`, found struct `Foo` - | help: try using a variant of the expected enum: `Some(Foo { bar: 1 })` + | ^^^^^^^^^^^^^^ expected enum `Option`, found struct `Foo` | = note: expected enum `Option<Foo>` found struct `Foo` +help: try wrapping the expression in `Some` + | +LL | Some(Foo { bar: 1 }) + | +++++ + error[E0308]: mismatched types --> $DIR/abridged.rs:28:5 @@ -40,13 +41,14 @@ error[E0308]: mismatched types LL | fn c() -> Result<Foo, Bar> { | ---------------- expected `Result<Foo, Bar>` because of return type LL | Foo { bar: 1 } - | ^^^^^^^^^^^^^^ - | | - | expected enum `Result`, found struct `Foo` - | help: try using a variant of the expected enum: `Ok(Foo { bar: 1 })` + | ^^^^^^^^^^^^^^ expected enum `Result`, found struct `Foo` | = note: expected enum `Result<Foo, Bar>` found struct `Foo` +help: try wrapping the expression in `Ok` + | +LL | Ok(Foo { bar: 1 }) + | +++ + error[E0308]: mismatched types --> $DIR/abridged.rs:39:5 diff --git a/src/test/ui/assignment-operator-unimplemented.rs b/src/test/ui/mismatched_types/assignment-operator-unimplemented.rs similarity index 100% rename from src/test/ui/assignment-operator-unimplemented.rs rename to src/test/ui/mismatched_types/assignment-operator-unimplemented.rs diff --git a/src/test/ui/assignment-operator-unimplemented.stderr b/src/test/ui/mismatched_types/assignment-operator-unimplemented.stderr similarity index 100% rename from src/test/ui/assignment-operator-unimplemented.stderr rename to src/test/ui/mismatched_types/assignment-operator-unimplemented.stderr diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr index e8fcf80e94..fed47e0f17 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count.stderr @@ -125,6 +125,12 @@ LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(foo); ... LL | fn foo() {} | -------- takes 0 arguments + | +note: required by a bound in `map` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | F: FnMut(Self::Item) -> B, + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map` error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 3 distinct arguments --> $DIR/closure-arg-count.rs:27:57 @@ -135,6 +141,12 @@ LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(bar); | --- ^^^ expected closure that takes a single 2-tuple as argument | | | required by a bound introduced by this call + | +note: required by a bound in `map` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | F: FnMut(Self::Item) -> B, + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map` error[E0593]: function is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments --> $DIR/closure-arg-count.rs:29:57 @@ -146,6 +158,12 @@ LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(qux); ... LL | fn qux(x: usize, y: usize) {} | -------------------------- takes 2 distinct arguments + | +note: required by a bound in `map` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | F: FnMut(Self::Item) -> B, + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map` error[E0593]: function is expected to take 1 argument, but it takes 2 arguments --> $DIR/closure-arg-count.rs:32:45 @@ -154,6 +172,12 @@ LL | let _it = vec![1, 2, 3].into_iter().map(usize::checked_add); | --- ^^^^^^^^^^^^^^^^^^ expected function that takes 1 argument | | | required by a bound introduced by this call + | +note: required by a bound in `map` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | F: FnMut(Self::Item) -> B, + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map` error[E0593]: function is expected to take 0 arguments, but it takes 1 argument --> $DIR/closure-arg-count.rs:35:10 diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.nll.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.nll.stderr index 6ed91b20ab..1f46229cb5 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.nll.stderr +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.nll.stderr @@ -5,6 +5,12 @@ LL | a.iter().map(|_: (u32, u32)| 45); | ^^^ ------------------ found signature of `fn((u32, u32)) -> _` | | | expected signature of `fn(&(u32, u32)) -> _` + | +note: required by a bound in `map` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | F: FnMut(Self::Item) -> B, + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map` error[E0631]: type mismatch in closure arguments --> $DIR/closure-arg-type-mismatch.rs:4:14 @@ -13,6 +19,12 @@ LL | a.iter().map(|_: &(u16, u16)| 45); | ^^^ ------------------- found signature of `for<'r> fn(&'r (u16, u16)) -> _` | | | expected signature of `fn(&(u32, u32)) -> _` + | +note: required by a bound in `map` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | F: FnMut(Self::Item) -> B, + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map` error[E0631]: type mismatch in closure arguments --> $DIR/closure-arg-type-mismatch.rs:5:14 @@ -21,6 +33,12 @@ LL | a.iter().map(|_: (u16, u16)| 45); | ^^^ ------------------ found signature of `fn((u16, u16)) -> _` | | | expected signature of `fn(&(u32, u32)) -> _` + | +note: required by a bound in `map` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | F: FnMut(Self::Item) -> B, + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map` error: aborting due to 3 previous errors diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr index 0ec282dac4..f34ac35c75 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -5,6 +5,12 @@ LL | a.iter().map(|_: (u32, u32)| 45); | ^^^ ------------------ found signature of `fn((u32, u32)) -> _` | | | expected signature of `fn(&(u32, u32)) -> _` + | +note: required by a bound in `map` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | F: FnMut(Self::Item) -> B, + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map` error[E0631]: type mismatch in closure arguments --> $DIR/closure-arg-type-mismatch.rs:4:14 @@ -13,6 +19,12 @@ LL | a.iter().map(|_: &(u16, u16)| 45); | ^^^ ------------------- found signature of `for<'r> fn(&'r (u16, u16)) -> _` | | | expected signature of `fn(&(u32, u32)) -> _` + | +note: required by a bound in `map` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | F: FnMut(Self::Item) -> B, + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map` error[E0631]: type mismatch in closure arguments --> $DIR/closure-arg-type-mismatch.rs:5:14 @@ -21,6 +33,12 @@ LL | a.iter().map(|_: (u16, u16)| 45); | ^^^ ------------------ found signature of `fn((u16, u16)) -> _` | | | expected signature of `fn(&(u32, u32)) -> _` + | +note: required by a bound in `map` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | F: FnMut(Self::Item) -> B, + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map` error[E0308]: mismatched types --> $DIR/closure-arg-type-mismatch.rs:10:5 diff --git a/src/test/ui/float-literal-inference-restrictions.rs b/src/test/ui/mismatched_types/float-literal-inference-restrictions.rs similarity index 100% rename from src/test/ui/float-literal-inference-restrictions.rs rename to src/test/ui/mismatched_types/float-literal-inference-restrictions.rs diff --git a/src/test/ui/float-literal-inference-restrictions.stderr b/src/test/ui/mismatched_types/float-literal-inference-restrictions.stderr similarity index 100% rename from src/test/ui/float-literal-inference-restrictions.stderr rename to src/test/ui/mismatched_types/float-literal-inference-restrictions.stderr diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index 67e8ee2283..a8bcdf5efe 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -5,6 +5,12 @@ LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); | ^^^^^^ -------------- found signature of `for<'r> fn(&'r str) -> _` | | | expected signature of `for<'r> fn(&'r &str) -> _` + | +note: required by a bound in `filter` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | P: FnMut(&Self::Item) -> bool, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `filter` error[E0599]: the method `count` exists for struct `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>`, but its trait bounds were not satisfied --> $DIR/issue-36053-2.rs:7:55 diff --git a/src/test/ui/mismatched_types/issue-75361-mismatched-impl.stderr b/src/test/ui/mismatched_types/issue-75361-mismatched-impl.stderr index 9867addaf3..2a2c23c942 100644 --- a/src/test/ui/mismatched_types/issue-75361-mismatched-impl.stderr +++ b/src/test/ui/mismatched_types/issue-75361-mismatched-impl.stderr @@ -2,13 +2,13 @@ error: `impl` item signature doesn't match `trait` item signature --> $DIR/issue-75361-mismatched-impl.rs:18:3 | LL | fn adjacent_edges(&self) -> Box<dyn MyTrait<Item = &Self::EdgeType>>; - | --------------------------------------------------------------------- expected `fn(&T) -> Box<(dyn MyTrait<Item = &T> + 'static)>` + | --------------------------------------------------------------------- expected `fn(&'1 T) -> Box<(dyn MyTrait<Item = &'1 T> + 'static)>` ... LL | fn adjacent_edges(&self) -> Box<dyn MyTrait<Item = &Self::EdgeType> + '_> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&T) -> Box<dyn MyTrait<Item = &T>>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 T) -> Box<(dyn MyTrait<Item = &'1 T> + '1)>` | - = note: expected `fn(&T) -> Box<(dyn MyTrait<Item = &T> + 'static)>` - found `fn(&T) -> Box<dyn MyTrait<Item = &T>>` + = note: expected `fn(&'1 T) -> Box<(dyn MyTrait<Item = &'1 T> + 'static)>` + found `fn(&'1 T) -> Box<(dyn MyTrait<Item = &'1 T> + '1)>` help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` --> $DIR/issue-75361-mismatched-impl.rs:12:55 | diff --git a/src/test/ui/mismatched_types/issue-84976.stderr b/src/test/ui/mismatched_types/issue-84976.stderr index 0c27e17294..f8f2b1f0f5 100644 --- a/src/test/ui/mismatched_types/issue-84976.stderr +++ b/src/test/ui/mismatched_types/issue-84976.stderr @@ -7,6 +7,9 @@ LL | length = { foo(&length) }; error[E0308]: mismatched types --> $DIR/issue-84976.rs:17:14 | +LL | let mut length = 0; + | - expected due to this value +... LL | length = foo(&length); | ^^^^^^^^^^^^ expected `u32`, found `i32` @@ -19,6 +22,9 @@ LL | float_length = { bar(&float_length) }; error[E0308]: mismatched types --> $DIR/issue-84976.rs:23:20 | +LL | let mut float_length = 0.0; + | --- expected due to this value +... LL | float_length = bar(&float_length); | ^^^^^^^^^^^^^^^^^^ expected `f32`, found `f64` diff --git a/src/test/ui/issues/auxiliary/issue-69725.rs b/src/test/ui/missing-trait-bounds/auxiliary/issue-69725.rs similarity index 100% rename from src/test/ui/issues/auxiliary/issue-69725.rs rename to src/test/ui/missing-trait-bounds/auxiliary/issue-69725.rs diff --git a/src/test/ui/missing-trait-bounds/issue-35677.fixed b/src/test/ui/missing-trait-bounds/issue-35677.fixed new file mode 100644 index 0000000000..08174d8d8d --- /dev/null +++ b/src/test/ui/missing-trait-bounds/issue-35677.fixed @@ -0,0 +1,11 @@ +// run-rustfix +#![allow(dead_code)] +use std::collections::HashSet; +use std::hash::Hash; + +fn is_subset<T>(this: &HashSet<T>, other: &HashSet<T>) -> bool where T: Eq, T: Hash { + this.is_subset(other) + //~^ ERROR the method +} + +fn main() {} diff --git a/src/test/ui/issues/issue-35677.rs b/src/test/ui/missing-trait-bounds/issue-35677.rs similarity index 74% rename from src/test/ui/issues/issue-35677.rs rename to src/test/ui/missing-trait-bounds/issue-35677.rs index 15d1397906..2cb394386b 100644 --- a/src/test/ui/issues/issue-35677.rs +++ b/src/test/ui/missing-trait-bounds/issue-35677.rs @@ -1,4 +1,7 @@ +// run-rustfix +#![allow(dead_code)] use std::collections::HashSet; +use std::hash::Hash; fn is_subset<T>(this: &HashSet<T>, other: &HashSet<T>) -> bool { this.is_subset(other) diff --git a/src/test/ui/issues/issue-35677.stderr b/src/test/ui/missing-trait-bounds/issue-35677.stderr similarity index 61% rename from src/test/ui/issues/issue-35677.stderr rename to src/test/ui/missing-trait-bounds/issue-35677.stderr index ab59e5d1ac..a2201b946a 100644 --- a/src/test/ui/issues/issue-35677.stderr +++ b/src/test/ui/missing-trait-bounds/issue-35677.stderr @@ -1,5 +1,5 @@ error[E0599]: the method `is_subset` exists for reference `&HashSet<T>`, but its trait bounds were not satisfied - --> $DIR/issue-35677.rs:4:10 + --> $DIR/issue-35677.rs:7:10 | LL | this.is_subset(other) | ^^^^^^^^^ method cannot be called on `&HashSet<T>` due to unsatisfied trait bounds @@ -7,6 +7,10 @@ LL | this.is_subset(other) = note: the following trait bounds were not satisfied: `T: Eq` `T: Hash` +help: consider restricting the type parameters to satisfy the trait bounds + | +LL | fn is_subset<T>(this: &HashSet<T>, other: &HashSet<T>) -> bool where T: Eq, T: Hash { + | ++++++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/missing-trait-bounds/issue-69725.fixed b/src/test/ui/missing-trait-bounds/issue-69725.fixed new file mode 100644 index 0000000000..d57badcfd8 --- /dev/null +++ b/src/test/ui/missing-trait-bounds/issue-69725.fixed @@ -0,0 +1,13 @@ +// run-rustfix +// aux-build:issue-69725.rs +#![allow(dead_code)] + +extern crate issue_69725; +use issue_69725::Struct; + +fn crash<A>() where A: Clone { + let _ = Struct::<A>::new().clone(); + //~^ ERROR: the method +} + +fn main() {} diff --git a/src/test/ui/issues/issue-69725.rs b/src/test/ui/missing-trait-bounds/issue-69725.rs similarity index 83% rename from src/test/ui/issues/issue-69725.rs rename to src/test/ui/missing-trait-bounds/issue-69725.rs index 7c77293945..9c88969c5c 100644 --- a/src/test/ui/issues/issue-69725.rs +++ b/src/test/ui/missing-trait-bounds/issue-69725.rs @@ -1,4 +1,6 @@ +// run-rustfix // aux-build:issue-69725.rs +#![allow(dead_code)] extern crate issue_69725; use issue_69725::Struct; diff --git a/src/test/ui/issues/issue-69725.stderr b/src/test/ui/missing-trait-bounds/issue-69725.stderr similarity index 78% rename from src/test/ui/issues/issue-69725.stderr rename to src/test/ui/missing-trait-bounds/issue-69725.stderr index b1ba89f6cb..6395bca300 100644 --- a/src/test/ui/issues/issue-69725.stderr +++ b/src/test/ui/missing-trait-bounds/issue-69725.stderr @@ -1,5 +1,5 @@ error[E0599]: the method `clone` exists for struct `Struct<A>`, but its trait bounds were not satisfied - --> $DIR/issue-69725.rs:7:32 + --> $DIR/issue-69725.rs:9:32 | LL | let _ = Struct::<A>::new().clone(); | ^^^^^ method cannot be called on `Struct<A>` due to unsatisfied trait bounds @@ -12,6 +12,10 @@ LL | pub struct Struct<A>(A); = note: the following trait bounds were not satisfied: `A: Clone` which is required by `Struct<A>: Clone` +help: consider restricting the type parameter to satisfy the trait bound + | +LL | fn crash<A>() where A: Clone { + | ++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/suggestions/missing-trait-bound-for-op.fixed b/src/test/ui/missing-trait-bounds/missing-trait-bound-for-op.fixed similarity index 100% rename from src/test/ui/suggestions/missing-trait-bound-for-op.fixed rename to src/test/ui/missing-trait-bounds/missing-trait-bound-for-op.fixed diff --git a/src/test/ui/suggestions/missing-trait-bound-for-op.rs b/src/test/ui/missing-trait-bounds/missing-trait-bound-for-op.rs similarity index 100% rename from src/test/ui/suggestions/missing-trait-bound-for-op.rs rename to src/test/ui/missing-trait-bounds/missing-trait-bound-for-op.rs diff --git a/src/test/ui/suggestions/missing-trait-bound-for-op.stderr b/src/test/ui/missing-trait-bounds/missing-trait-bound-for-op.stderr similarity index 100% rename from src/test/ui/suggestions/missing-trait-bound-for-op.stderr rename to src/test/ui/missing-trait-bounds/missing-trait-bound-for-op.stderr diff --git a/src/test/ui/suggestions/missing-trait-bounds-for-method-call.rs b/src/test/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.rs similarity index 100% rename from src/test/ui/suggestions/missing-trait-bounds-for-method-call.rs rename to src/test/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.rs diff --git a/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr b/src/test/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.stderr similarity index 100% rename from src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr rename to src/test/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.stderr diff --git a/src/test/ui/modules/issue-56411.rs b/src/test/ui/modules/issue-56411.rs index 163651a7ef..0a20f5fe98 100644 --- a/src/test/ui/modules/issue-56411.rs +++ b/src/test/ui/modules/issue-56411.rs @@ -5,7 +5,7 @@ macro_rules! import { mod $name; pub use self::$name; //~^ ERROR the name `issue_56411_aux` is defined multiple times - //~| ERROR `issue_56411_aux` is private, and cannot be re-exported + //~| ERROR `issue_56411_aux` is only public within the crate, and cannot be re-exported outside )* } diff --git a/src/test/ui/modules/issue-56411.stderr b/src/test/ui/modules/issue-56411.stderr index 5ab4542b04..6732a8a3d7 100644 --- a/src/test/ui/modules/issue-56411.stderr +++ b/src/test/ui/modules/issue-56411.stderr @@ -15,11 +15,11 @@ LL | import!(("issue-56411-aux.rs", issue_56411_aux)); = note: `issue_56411_aux` must be defined only once in the type namespace of this module = note: this error originates in the macro `import` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0365]: `issue_56411_aux` is private, and cannot be re-exported +error[E0365]: `issue_56411_aux` is only public within the crate, and cannot be re-exported outside --> $DIR/issue-56411.rs:6:21 | LL | pub use self::$name; - | ^^^^^^^^^^^ re-export of private `issue_56411_aux` + | ^^^^^^^^^^^ re-export of crate public `issue_56411_aux` ... LL | import!(("issue-56411-aux.rs", issue_56411_aux)); | ------------------------------------------------ in this macro invocation diff --git a/src/test/ui/moves/move-of-addr-of-mut.rs b/src/test/ui/moves/move-of-addr-of-mut.rs new file mode 100644 index 0000000000..f2f64e43cd --- /dev/null +++ b/src/test/ui/moves/move-of-addr-of-mut.rs @@ -0,0 +1,12 @@ +// Ensure that taking a mutable raw ptr to an uninitialized variable does not change its +// initializedness. + +struct S; + +fn main() { + let mut x: S; + std::ptr::addr_of_mut!(x); //~ borrow of + + let y = x; // Should error here if `addr_of_mut` is ever allowed on uninitialized variables + drop(y); +} diff --git a/src/test/ui/moves/move-of-addr-of-mut.stderr b/src/test/ui/moves/move-of-addr-of-mut.stderr new file mode 100644 index 0000000000..ce8fb02831 --- /dev/null +++ b/src/test/ui/moves/move-of-addr-of-mut.stderr @@ -0,0 +1,11 @@ +error[E0381]: borrow of possibly-uninitialized variable: `x` + --> $DIR/move-of-addr-of-mut.rs:8:5 + | +LL | std::ptr::addr_of_mut!(x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `x` + | + = note: this error originates in the macro `std::ptr::addr_of_mut` (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 E0381`. diff --git a/src/test/ui/mut/mutable-enum-indirect.stderr b/src/test/ui/mut/mutable-enum-indirect.stderr index 8ec478cd63..9e1f4e1fe4 100644 --- a/src/test/ui/mut/mutable-enum-indirect.stderr +++ b/src/test/ui/mut/mutable-enum-indirect.stderr @@ -1,8 +1,10 @@ error[E0277]: `NoSync` cannot be shared between threads safely - --> $DIR/mutable-enum-indirect.rs:17:5 + --> $DIR/mutable-enum-indirect.rs:17:9 | LL | bar(&x); - | ^^^ `NoSync` cannot be shared between threads safely + | --- ^^ `NoSync` cannot be shared between threads safely + | | + | required by a bound introduced by this call | = help: within `&Foo`, the trait `Sync` is not implemented for `NoSync` note: required because it appears within the type `Foo` diff --git a/src/test/ui/negative.rs b/src/test/ui/negative.rs deleted file mode 100644 index 9601e9118a..0000000000 --- a/src/test/ui/negative.rs +++ /dev/null @@ -1,8 +0,0 @@ -// run-pass - -pub fn main() { - match -5 { - -5 => {} - _ => { panic!() } - } -} diff --git a/src/test/ui/diverging-tuple-parts-39485.rs b/src/test/ui/never_type/diverging-tuple-parts-39485.rs similarity index 100% rename from src/test/ui/diverging-tuple-parts-39485.rs rename to src/test/ui/never_type/diverging-tuple-parts-39485.rs diff --git a/src/test/ui/diverging-tuple-parts-39485.stderr b/src/test/ui/never_type/diverging-tuple-parts-39485.stderr similarity index 100% rename from src/test/ui/diverging-tuple-parts-39485.stderr rename to src/test/ui/never_type/diverging-tuple-parts-39485.stderr diff --git a/src/test/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr b/src/test/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr index 614cdff1f8..a14253e384 100644 --- a/src/test/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr +++ b/src/test/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr @@ -6,11 +6,6 @@ LL | <E as From<_>>::from(never); | = help: the following implementations were found: <E as From<!>> -note: required by `from` - --> $SRC_DIR/core/src/convert/mod.rs:LL:COL - | -LL | fn from(_: T) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/newtype-temporary.rs b/src/test/ui/newtype-temporary.rs deleted file mode 100644 index 8ee75b2fef..0000000000 --- a/src/test/ui/newtype-temporary.rs +++ /dev/null @@ -1,12 +0,0 @@ -// run-pass - -#[derive(PartialEq, Debug)] -struct Foo(usize); - -fn foo() -> Foo { - Foo(42) -} - -pub fn main() { - assert_eq!(foo(), Foo(42)); -} diff --git a/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs index ac2943fc3a..c8f226f523 100644 --- a/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs +++ b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs @@ -7,7 +7,7 @@ fn foo(x: &u32) -> &'static u32 { &*x - //~^ ERROR explicit lifetime required in the type of `x` + //~^ ERROR lifetime may not live long enough } fn main() { } diff --git a/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr index 4c302d935d..7034492cee 100644 --- a/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr +++ b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr @@ -1,9 +1,10 @@ -error[E0621]: explicit lifetime required in the type of `x` +error: lifetime may not live long enough --> $DIR/region-lbr-anon-does-not-outlive-static.rs:9:5 | +LL | fn foo(x: &u32) -> &'static u32 { + | - let's call the lifetime of this reference `'1` LL | &*x - | ^^^ lifetime `ReStatic` required + | ^^^ returning this value requires that `'1` must outlive `'static` error: aborting due to previous error -For more information about this error, try `rustc --explain E0621`. diff --git a/src/test/ui/nll/dont-print-desugared.stderr b/src/test/ui/nll/dont-print-desugared.stderr index 88773def8b..fad6121cbc 100644 --- a/src/test/ui/nll/dont-print-desugared.stderr +++ b/src/test/ui/nll/dont-print-desugared.stderr @@ -2,7 +2,7 @@ error[E0596]: cannot borrow data in a `&` reference as mutable --> $DIR/dont-print-desugared.rs:4:10 | LL | for &ref mut x in s {} - | ^^^^^^^^^ cannot borrow as mutable through `&` reference + | ^^^^^^^^^ cannot borrow as mutable error[E0597]: `y` does not live long enough --> $DIR/dont-print-desugared.rs:17:16 diff --git a/src/test/ui/nll/guarantor-issue-46974.rs b/src/test/ui/nll/guarantor-issue-46974.rs index d0af468cff..87ed0e642e 100644 --- a/src/test/ui/nll/guarantor-issue-46974.rs +++ b/src/test/ui/nll/guarantor-issue-46974.rs @@ -12,7 +12,7 @@ fn foo(s: &mut (i32,)) -> i32 { fn bar(s: &Box<(i32,)>) -> &'static i32 { // FIXME(#46983): error message should be better - &s.0 //~ ERROR explicit lifetime required in the type of `s` [E0621] + &s.0 //~ ERROR lifetime may not live long enough } fn main() { diff --git a/src/test/ui/nll/guarantor-issue-46974.stderr b/src/test/ui/nll/guarantor-issue-46974.stderr index eabc3105c0..8245aadf82 100644 --- a/src/test/ui/nll/guarantor-issue-46974.stderr +++ b/src/test/ui/nll/guarantor-issue-46974.stderr @@ -9,13 +9,15 @@ LL | *s = (2,); LL | *x | -- borrow later used here -error[E0621]: explicit lifetime required in the type of `s` +error: lifetime may not live long enough --> $DIR/guarantor-issue-46974.rs:15:5 | +LL | fn bar(s: &Box<(i32,)>) -> &'static i32 { + | - let's call the lifetime of this reference `'1` +LL | // FIXME(#46983): error message should be better LL | &s.0 - | ^^^^ lifetime `'static` required + | ^^^^ returning this value requires that `'1` must outlive `'static` error: aborting due to 2 previous errors -Some errors have detailed explanations: E0506, E0621. -For more information about an error, try `rustc --explain E0506`. +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/nll/issue-53773.stderr b/src/test/ui/nll/issue-53773.stderr index 11cd423295..90cba2a145 100644 --- a/src/test/ui/nll/issue-53773.stderr +++ b/src/test/ui/nll/issue-53773.stderr @@ -2,12 +2,10 @@ error[E0713]: borrow may still be in use when destructor runs --> $DIR/issue-53773.rs:41:22 | LL | members.push(child.raw); - | ^^^^^^^^^ + | -------------^^^^^^^^^- borrow later used here LL | LL | } | - here, drop of `child` needs exclusive access to `*child.raw`, because the type `C<'_>` implements the `Drop` trait -LL | members.len(); - | ------------- borrow later used here | = note: consider using a `let` binding to create a longer lived value diff --git a/src/test/ui/nll/issue-73159-rpit-static.rs b/src/test/ui/nll/issue-73159-rpit-static.rs index a5455a3f9e..e29ba09b36 100644 --- a/src/test/ui/nll/issue-73159-rpit-static.rs +++ b/src/test/ui/nll/issue-73159-rpit-static.rs @@ -6,7 +6,8 @@ struct Foo<'a>(&'a [u8]); impl<'a> Foo<'a> { - fn make_it(&self) -> impl Iterator<Item = u8> { //~ ERROR lifetime may not live + fn make_it(&self) -> impl Iterator<Item = u8> { + //~^ ERROR: captures lifetime that does not appear in bounds self.0.iter().copied() } } diff --git a/src/test/ui/nll/issue-73159-rpit-static.stderr b/src/test/ui/nll/issue-73159-rpit-static.stderr index 60b1552701..6c7cd0c825 100644 --- a/src/test/ui/nll/issue-73159-rpit-static.stderr +++ b/src/test/ui/nll/issue-73159-rpit-static.stderr @@ -1,10 +1,11 @@ -error: lifetime may not live long enough +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds --> $DIR/issue-73159-rpit-static.rs:9:26 | LL | impl<'a> Foo<'a> { - | -- lifetime `'a` defined here + | -- hidden type `Copied<std::slice::Iter<'a, u8>>` captures the lifetime `'a` as defined here LL | fn make_it(&self) -> impl Iterator<Item = u8> { - | ^^^^^^^^^^^^^^^^^^^^^^^^ opaque type requires that `'a` must outlive `'static` + | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/nll/issue-78561.rs b/src/test/ui/nll/issue-78561.rs new file mode 100644 index 0000000000..55147fcd1b --- /dev/null +++ b/src/test/ui/nll/issue-78561.rs @@ -0,0 +1,23 @@ +// check-pass +#![feature(type_alias_impl_trait)] + +pub trait Trait { + type A; + + fn f() -> Self::A; +} + +pub trait Tr2<'a, 'b> {} + +pub struct A<T>(T); +pub trait Tr { + type B; +} + +impl<'a, 'b, T: Tr<B = dyn Tr2<'a, 'b>>> Trait for A<T> { + type A = impl core::fmt::Debug; + + fn f() -> Self::A {} +} + +fn main() {} diff --git a/src/test/ui/lub-if.nll.stderr b/src/test/ui/nll/lub-if.nll.stderr similarity index 100% rename from src/test/ui/lub-if.nll.stderr rename to src/test/ui/nll/lub-if.nll.stderr diff --git a/src/test/ui/lub-if.rs b/src/test/ui/nll/lub-if.rs similarity index 100% rename from src/test/ui/lub-if.rs rename to src/test/ui/nll/lub-if.rs diff --git a/src/test/ui/lub-if.stderr b/src/test/ui/nll/lub-if.stderr similarity index 100% rename from src/test/ui/lub-if.stderr rename to src/test/ui/nll/lub-if.stderr diff --git a/src/test/ui/lub-match.nll.stderr b/src/test/ui/nll/lub-match.nll.stderr similarity index 100% rename from src/test/ui/lub-match.nll.stderr rename to src/test/ui/nll/lub-match.nll.stderr diff --git a/src/test/ui/lub-match.rs b/src/test/ui/nll/lub-match.rs similarity index 100% rename from src/test/ui/lub-match.rs rename to src/test/ui/nll/lub-match.rs diff --git a/src/test/ui/lub-match.stderr b/src/test/ui/nll/lub-match.stderr similarity index 100% rename from src/test/ui/lub-match.stderr rename to src/test/ui/nll/lub-match.stderr diff --git a/src/test/ui/ref-suggestion.rs b/src/test/ui/nll/ref-suggestion.rs similarity index 100% rename from src/test/ui/ref-suggestion.rs rename to src/test/ui/nll/ref-suggestion.rs diff --git a/src/test/ui/ref-suggestion.stderr b/src/test/ui/nll/ref-suggestion.stderr similarity index 100% rename from src/test/ui/ref-suggestion.stderr rename to src/test/ui/nll/ref-suggestion.stderr diff --git a/src/test/ui/nll/ty-outlives/impl-trait-captures.rs b/src/test/ui/nll/ty-outlives/impl-trait-captures.rs index bcdf643c0b..8af23aad72 100644 --- a/src/test/ui/nll/ty-outlives/impl-trait-captures.rs +++ b/src/test/ui/nll/ty-outlives/impl-trait-captures.rs @@ -8,7 +8,7 @@ trait Foo<'a> { impl<'a, T> Foo<'a> for T { } fn foo<'a, T>(x: &T) -> impl Foo<'a> { -//~^ ERROR explicit lifetime required in the type of `x` [E0621] +//~^ ERROR captures lifetime that does not appear in bounds x } diff --git a/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr index d05fc79396..21d1eea54e 100644 --- a/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr +++ b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr @@ -1,14 +1,16 @@ -error[E0621]: explicit lifetime required in the type of `x` +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds --> $DIR/impl-trait-captures.rs:10:25 | LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> { - | ^^^^^^^^^^^^ lifetime `ReEarlyBound(0, 'a)` required + | -- ^^^^^^^^^^^^ + | | + | hidden type `&ReFree(DefId(0:8 ~ impl_trait_captures[e9f4]::foo), BrAnon(0)) T` captures the anonymous lifetime defined here | -help: add explicit lifetime `ReEarlyBound(0, 'a)` to the type of `x` +help: to declare that the `impl Trait` captures ReFree(DefId(0:8 ~ impl_trait_captures[e9f4]::foo), BrAnon(0)), you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[e9f4]::foo), BrAnon(0))` lifetime bound | -LL | fn foo<'a, T>(x: &ReEarlyBound(0, 'a) T) -> impl Foo<'a> { - | ~~~~~~~~~~~~~~~~~~~~~~ +LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + ReFree(DefId(0:8 ~ impl_trait_captures[e9f4]::foo), BrAnon(0)) { + | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ error: aborting due to previous error -For more information about this error, try `rustc --explain E0621`. +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/no_send-enum.stderr b/src/test/ui/no_send-enum.stderr index 814f347382..b5a14b551d 100644 --- a/src/test/ui/no_send-enum.stderr +++ b/src/test/ui/no_send-enum.stderr @@ -1,8 +1,10 @@ error[E0277]: `NoSend` cannot be sent between threads safely - --> $DIR/no_send-enum.rs:16:5 + --> $DIR/no_send-enum.rs:16:9 | LL | bar(x); - | ^^^ `NoSend` cannot be sent between threads safely + | --- ^ `NoSend` cannot be sent between threads safely + | | + | required by a bound introduced by this call | = help: within `Foo`, the trait `Send` is not implemented for `NoSend` note: required because it appears within the type `Foo` diff --git a/src/test/ui/no_share-enum.stderr b/src/test/ui/no_share-enum.stderr index ad837863be..5b453e0da3 100644 --- a/src/test/ui/no_share-enum.stderr +++ b/src/test/ui/no_share-enum.stderr @@ -1,8 +1,10 @@ error[E0277]: `NoSync` cannot be shared between threads safely - --> $DIR/no_share-enum.rs:14:5 + --> $DIR/no_share-enum.rs:14:9 | LL | bar(x); - | ^^^ `NoSync` cannot be shared between threads safely + | --- ^ `NoSync` cannot be shared between threads safely + | | + | required by a bound introduced by this call | = help: within `Foo`, the trait `Sync` is not implemented for `NoSync` note: required because it appears within the type `Foo` diff --git a/src/test/ui/non-legacy-modes.rs b/src/test/ui/non-legacy-modes.rs deleted file mode 100644 index 38c83e00a6..0000000000 --- a/src/test/ui/non-legacy-modes.rs +++ /dev/null @@ -1,22 +0,0 @@ -// run-pass - -struct X { - repr: isize -} - -fn apply<T, F>(x: T, f: F) where F: FnOnce(T) { - f(x); -} - -fn check_int(x: isize) { - assert_eq!(x, 22); -} - -fn check_struct(x: X) { - check_int(x.repr); -} - -pub fn main() { - apply(22, check_int); - apply(X {repr: 22}, check_struct); -} diff --git a/src/test/ui/numbers-arithmetic/int-abs-overflow.rs b/src/test/ui/numbers-arithmetic/int-abs-overflow.rs index 10ec3f0c66..9c6dff7e1a 100644 --- a/src/test/ui/numbers-arithmetic/int-abs-overflow.rs +++ b/src/test/ui/numbers-arithmetic/int-abs-overflow.rs @@ -1,5 +1,5 @@ // run-pass -// compile-flags: -Z force-overflow-checks=on +// compile-flags: -C overflow-checks=on // ignore-emscripten no threads support use std::thread; diff --git a/src/test/ui/unary-minus-suffix-inference.rs b/src/test/ui/numbers-arithmetic/unary-minus-suffix-inference.rs similarity index 100% rename from src/test/ui/unary-minus-suffix-inference.rs rename to src/test/ui/numbers-arithmetic/unary-minus-suffix-inference.rs diff --git a/src/test/ui/integer-literal-suffix-inference.rs b/src/test/ui/numeric/integer-literal-suffix-inference.rs similarity index 100% rename from src/test/ui/integer-literal-suffix-inference.rs rename to src/test/ui/numeric/integer-literal-suffix-inference.rs diff --git a/src/test/ui/integer-literal-suffix-inference.stderr b/src/test/ui/numeric/integer-literal-suffix-inference.stderr similarity index 100% rename from src/test/ui/integer-literal-suffix-inference.stderr rename to src/test/ui/numeric/integer-literal-suffix-inference.stderr diff --git a/src/test/ui/object-lifetime-default-default-to-static.rs b/src/test/ui/object-lifetime/object-lifetime-default-default-to-static.rs similarity index 100% rename from src/test/ui/object-lifetime-default-default-to-static.rs rename to src/test/ui/object-lifetime/object-lifetime-default-default-to-static.rs diff --git a/src/test/ui/structs-enums/object-lifetime-default-from-ref-struct.rs b/src/test/ui/object-lifetime/object-lifetime-default-from-ref-struct.rs similarity index 100% rename from src/test/ui/structs-enums/object-lifetime-default-from-ref-struct.rs rename to src/test/ui/object-lifetime/object-lifetime-default-from-ref-struct.rs diff --git a/src/test/ui/object-lifetime-default-from-rptr-box.rs b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box.rs similarity index 100% rename from src/test/ui/object-lifetime-default-from-rptr-box.rs rename to src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box.rs diff --git a/src/test/ui/object-lifetime-default-from-rptr-mut.rs b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-mut.rs similarity index 100% rename from src/test/ui/object-lifetime-default-from-rptr-mut.rs rename to src/test/ui/object-lifetime/object-lifetime-default-from-rptr-mut.rs diff --git a/src/test/ui/structs-enums/object-lifetime-default-from-rptr-struct.rs b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct.rs similarity index 100% rename from src/test/ui/structs-enums/object-lifetime-default-from-rptr-struct.rs rename to src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct.rs diff --git a/src/test/ui/object-lifetime-default-from-rptr.rs b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr.rs similarity index 100% rename from src/test/ui/object-lifetime-default-from-rptr.rs rename to src/test/ui/object-lifetime/object-lifetime-default-from-rptr.rs diff --git a/src/test/ui/object-lifetime-default-inferred.rs b/src/test/ui/object-lifetime/object-lifetime-default-inferred.rs similarity index 100% rename from src/test/ui/object-lifetime-default-inferred.rs rename to src/test/ui/object-lifetime/object-lifetime-default-inferred.rs diff --git a/src/test/ui/on-unimplemented/bad-annotation.stderr b/src/test/ui/on-unimplemented/bad-annotation.stderr index ac0cf0f1f0..a8d3c8680f 100644 --- a/src/test/ui/on-unimplemented/bad-annotation.stderr +++ b/src/test/ui/on-unimplemented/bad-annotation.stderr @@ -6,10 +6,10 @@ LL | #[rustc_on_unimplemented] | help: the following are the possible correct uses | -LL | #[rustc_on_unimplemented(/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...")] - | LL | #[rustc_on_unimplemented = "message"] | +LL | #[rustc_on_unimplemented(/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...")] + | error[E0230]: there is no parameter `C` on trait `BadAnnotation2` --> $DIR/bad-annotation.rs:22:1 diff --git a/src/test/ui/on-unimplemented/multiple-impls.stderr b/src/test/ui/on-unimplemented/multiple-impls.stderr index a3658f2242..76aa128e24 100644 --- a/src/test/ui/on-unimplemented/multiple-impls.stderr +++ b/src/test/ui/on-unimplemented/multiple-impls.stderr @@ -7,11 +7,6 @@ LL | Index::index(&[] as &[i32], 2u32); | required by a bound introduced by this call | = help: the trait `Index<u32>` is not implemented for `[i32]` -note: required by `Index::index` - --> $DIR/multiple-impls.rs:12:5 - | -LL | fn index(&self, index: Idx) -> &Self::Output; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied --> $DIR/multiple-impls.rs:36:18 @@ -22,11 +17,6 @@ LL | Index::index(&[] as &[i32], Foo(2u32)); | required by a bound introduced by this call | = help: the trait `Index<Foo<u32>>` is not implemented for `[i32]` -note: required by `Index::index` - --> $DIR/multiple-impls.rs:12:5 - | -LL | fn index(&self, index: Idx) -> &Self::Output; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied --> $DIR/multiple-impls.rs:39:18 @@ -37,11 +27,6 @@ LL | Index::index(&[] as &[i32], Bar(2u32)); | required by a bound introduced by this call | = help: the trait `Index<Bar<u32>>` is not implemented for `[i32]` -note: required by `Index::index` - --> $DIR/multiple-impls.rs:12:5 - | -LL | fn index(&self, index: Idx) -> &Self::Output; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied --> $DIR/multiple-impls.rs:33:5 diff --git a/src/test/ui/on-unimplemented/on-impl.stderr b/src/test/ui/on-unimplemented/on-impl.stderr index 18eca06ba6..940763fae5 100644 --- a/src/test/ui/on-unimplemented/on-impl.stderr +++ b/src/test/ui/on-unimplemented/on-impl.stderr @@ -7,11 +7,6 @@ LL | Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32); | required by a bound introduced by this call | = help: the trait `Index<u32>` is not implemented for `[i32]` -note: required by `Index::index` - --> $DIR/on-impl.rs:9:5 - | -LL | fn index(&self, index: Idx) -> &Self::Output; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied --> $DIR/on-impl.rs:22:5 diff --git a/src/test/ui/output-type-mismatch.stderr b/src/test/ui/output-type-mismatch.stderr index 533bd87c9c..4507a4df62 100644 --- a/src/test/ui/output-type-mismatch.stderr +++ b/src/test/ui/output-type-mismatch.stderr @@ -2,7 +2,9 @@ error[E0308]: mismatched types --> $DIR/output-type-mismatch.rs:5:31 | LL | fn main() { let i: isize; i = f(); } - | ^^^ expected `isize`, found `()` + | ----- ^^^ expected `isize`, found `()` + | | + | expected due to this type error: aborting due to previous error diff --git a/src/test/ui/fixup-deref-mut.rs b/src/test/ui/overloaded/fixup-deref-mut.rs similarity index 100% rename from src/test/ui/fixup-deref-mut.rs rename to src/test/ui/overloaded/fixup-deref-mut.rs diff --git a/src/test/ui/overloaded-calls-nontuple.rs b/src/test/ui/overloaded/overloaded-calls-nontuple.rs similarity index 100% rename from src/test/ui/overloaded-calls-nontuple.rs rename to src/test/ui/overloaded/overloaded-calls-nontuple.rs diff --git a/src/test/ui/overloaded-calls-nontuple.stderr b/src/test/ui/overloaded/overloaded-calls-nontuple.stderr similarity index 100% rename from src/test/ui/overloaded-calls-nontuple.stderr rename to src/test/ui/overloaded/overloaded-calls-nontuple.stderr diff --git a/src/test/ui/issues/issue-45152.rs b/src/test/ui/packed/issue-46152.rs similarity index 100% rename from src/test/ui/issues/issue-45152.rs rename to src/test/ui/packed/issue-46152.rs diff --git a/src/test/ui/panics/location-detail-panic-no-column.rs b/src/test/ui/panics/location-detail-panic-no-column.rs new file mode 100644 index 0000000000..673e638ca0 --- /dev/null +++ b/src/test/ui/panics/location-detail-panic-no-column.rs @@ -0,0 +1,7 @@ +// run-fail +// check-run-results +// compile-flags: -Zlocation-detail=line,file + +fn main() { + panic!("column-redacted"); +} diff --git a/src/test/ui/panics/location-detail-panic-no-column.run.stderr b/src/test/ui/panics/location-detail-panic-no-column.run.stderr new file mode 100644 index 0000000000..9f35623fba --- /dev/null +++ b/src/test/ui/panics/location-detail-panic-no-column.run.stderr @@ -0,0 +1,2 @@ +thread 'main' panicked at 'column-redacted', $DIR/location-detail-panic-no-column.rs:6:0 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/src/test/ui/panics/location-detail-panic-no-file.rs b/src/test/ui/panics/location-detail-panic-no-file.rs new file mode 100644 index 0000000000..0e5d52cfd1 --- /dev/null +++ b/src/test/ui/panics/location-detail-panic-no-file.rs @@ -0,0 +1,7 @@ +// run-fail +// check-run-results +// compile-flags: -Zlocation-detail=line,column + +fn main() { + panic!("file-redacted"); +} diff --git a/src/test/ui/panics/location-detail-panic-no-file.run.stderr b/src/test/ui/panics/location-detail-panic-no-file.run.stderr new file mode 100644 index 0000000000..1e07e3a07a --- /dev/null +++ b/src/test/ui/panics/location-detail-panic-no-file.run.stderr @@ -0,0 +1,2 @@ +thread 'main' panicked at 'file-redacted', <redacted>:6:5 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/src/test/ui/panics/location-detail-panic-no-line.rs b/src/test/ui/panics/location-detail-panic-no-line.rs new file mode 100644 index 0000000000..57f6d0ebcb --- /dev/null +++ b/src/test/ui/panics/location-detail-panic-no-line.rs @@ -0,0 +1,7 @@ +// run-fail +// check-run-results +// compile-flags: -Zlocation-detail=file,column + +fn main() { + panic!("line-redacted"); +} diff --git a/src/test/ui/panics/location-detail-panic-no-line.run.stderr b/src/test/ui/panics/location-detail-panic-no-line.run.stderr new file mode 100644 index 0000000000..cc3f1624c4 --- /dev/null +++ b/src/test/ui/panics/location-detail-panic-no-line.run.stderr @@ -0,0 +1,2 @@ +thread 'main' panicked at 'line-redacted', $DIR/location-detail-panic-no-line.rs:0:5 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/src/test/ui/panics/location-detail-unwrap-no-file.rs b/src/test/ui/panics/location-detail-unwrap-no-file.rs new file mode 100644 index 0000000000..d7f96f058e --- /dev/null +++ b/src/test/ui/panics/location-detail-unwrap-no-file.rs @@ -0,0 +1,8 @@ +// run-fail +// check-run-results +// compile-flags: -Zlocation-detail=line,column + +fn main() { + let opt: Option<u32> = None; + opt.unwrap(); +} diff --git a/src/test/ui/panics/location-detail-unwrap-no-file.run.stderr b/src/test/ui/panics/location-detail-unwrap-no-file.run.stderr new file mode 100644 index 0000000000..f8f84b5c49 --- /dev/null +++ b/src/test/ui/panics/location-detail-unwrap-no-file.run.stderr @@ -0,0 +1,2 @@ +thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', <redacted>:7:9 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/src/test/ui/paren-free.rs b/src/test/ui/paren-free.rs deleted file mode 100644 index 8e8bb8800e..0000000000 --- a/src/test/ui/paren-free.rs +++ /dev/null @@ -1,7 +0,0 @@ -// run-pass - -pub fn main() { - let x = true; - if x { let mut i = 10; while i > 0 { i -= 1; } } - match x { true => { println!("right"); } false => { println!("wrong"); } } -} diff --git a/src/test/ui/attribute-with-no-generics-in-parameter-list.rs b/src/test/ui/parser/attribute-with-no-generics-in-parameter-list.rs similarity index 100% rename from src/test/ui/attribute-with-no-generics-in-parameter-list.rs rename to src/test/ui/parser/attribute-with-no-generics-in-parameter-list.rs diff --git a/src/test/ui/attribute-with-no-generics-in-parameter-list.stderr b/src/test/ui/parser/attribute-with-no-generics-in-parameter-list.stderr similarity index 100% rename from src/test/ui/attribute-with-no-generics-in-parameter-list.stderr rename to src/test/ui/parser/attribute-with-no-generics-in-parameter-list.stderr diff --git a/src/test/ui/bastion-of-the-turbofish.rs b/src/test/ui/parser/bastion-of-the-turbofish.rs similarity index 100% rename from src/test/ui/bastion-of-the-turbofish.rs rename to src/test/ui/parser/bastion-of-the-turbofish.rs diff --git a/src/test/ui/parser/char/whitespace-character-literal.rs b/src/test/ui/parser/char/whitespace-character-literal.rs new file mode 100644 index 0000000000..de5e09204b --- /dev/null +++ b/src/test/ui/parser/char/whitespace-character-literal.rs @@ -0,0 +1,10 @@ +// This tests that the error generated when a character literal has multiple +// characters in it contains a note about non-printing characters. + +fn main() { + let _hair_space_around = ' x​'; + //~^ ERROR: character literal may only contain one codepoint + //~| NOTE: there are non-printing characters, the full sequence is `\u{200a}x\u{200b}` + //~| HELP: consider removing the non-printing characters + //~| SUGGESTION: x +} diff --git a/src/test/ui/parser/char/whitespace-character-literal.stderr b/src/test/ui/parser/char/whitespace-character-literal.stderr new file mode 100644 index 0000000000..d73de41a80 --- /dev/null +++ b/src/test/ui/parser/char/whitespace-character-literal.stderr @@ -0,0 +1,16 @@ +error: character literal may only contain one codepoint + --> $DIR/whitespace-character-literal.rs:5:30 + | +LL | let _hair_space_around = ' x​'; + | ^--^ + | | + | help: consider removing the non-printing characters: `x` + | +note: there are non-printing characters, the full sequence is `\u{200a}x\u{200b}` + --> $DIR/whitespace-character-literal.rs:5:31 + | +LL | let _hair_space_around = ' x​'; + | ^^ + +error: aborting due to previous error + diff --git a/src/test/ui/parser/const-param-decl-on-type-instead-of-impl.rs b/src/test/ui/parser/const-param-decl-on-type-instead-of-impl.rs new file mode 100644 index 0000000000..53e3c6f960 --- /dev/null +++ b/src/test/ui/parser/const-param-decl-on-type-instead-of-impl.rs @@ -0,0 +1,15 @@ +struct NInts<const N: usize>([u8; N]); +impl NInts<const N: usize> {} //~ ERROR unexpected `const` parameter declaration + +fn main() { + let _: () = 42; //~ ERROR mismatched types +} + +fn banana(a: <T<const N: usize>>::BAR) {} +//~^ ERROR unexpected `const` parameter declaration +//~| ERROR cannot find type `T` in this scope +fn chaenomeles() { + path::path::Struct::<const N: usize>() + //~^ ERROR unexpected `const` parameter declaration + //~| ERROR failed to resolve: use of undeclared crate or module `path` +} diff --git a/src/test/ui/parser/const-param-decl-on-type-instead-of-impl.stderr b/src/test/ui/parser/const-param-decl-on-type-instead-of-impl.stderr new file mode 100644 index 0000000000..96885d11ee --- /dev/null +++ b/src/test/ui/parser/const-param-decl-on-type-instead-of-impl.stderr @@ -0,0 +1,47 @@ +error: unexpected `const` parameter declaration + --> $DIR/const-param-decl-on-type-instead-of-impl.rs:2:12 + | +LL | impl NInts<const N: usize> {} + | ^^^^^^^^^^^^^^ expected a `const` expression, not a parameter declaration + | +help: `const` parameters must be declared for the `impl` + | +LL | impl<const N: usize> NInts<N> {} + | ++++++++++++++++ ~ + +error: unexpected `const` parameter declaration + --> $DIR/const-param-decl-on-type-instead-of-impl.rs:8:17 + | +LL | fn banana(a: <T<const N: usize>>::BAR) {} + | ^^^^^^^^^^^^^^ expected a `const` expression, not a parameter declaration + +error: unexpected `const` parameter declaration + --> $DIR/const-param-decl-on-type-instead-of-impl.rs:12:26 + | +LL | path::path::Struct::<const N: usize>() + | ^^^^^^^^^^^^^^ expected a `const` expression, not a parameter declaration + +error[E0433]: failed to resolve: use of undeclared crate or module `path` + --> $DIR/const-param-decl-on-type-instead-of-impl.rs:12:5 + | +LL | path::path::Struct::<const N: usize>() + | ^^^^ use of undeclared crate or module `path` + +error[E0412]: cannot find type `T` in this scope + --> $DIR/const-param-decl-on-type-instead-of-impl.rs:8:15 + | +LL | fn banana(a: <T<const N: usize>>::BAR) {} + | ^ not found in this scope + +error[E0308]: mismatched types + --> $DIR/const-param-decl-on-type-instead-of-impl.rs:5:17 + | +LL | let _: () = 42; + | -- ^^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0308, E0412, E0433. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/dyn-trait-compatibility.rs b/src/test/ui/parser/dyn-trait-compatibility.rs similarity index 100% rename from src/test/ui/dyn-trait-compatibility.rs rename to src/test/ui/parser/dyn-trait-compatibility.rs diff --git a/src/test/ui/dyn-trait-compatibility.stderr b/src/test/ui/parser/dyn-trait-compatibility.stderr similarity index 100% rename from src/test/ui/dyn-trait-compatibility.stderr rename to src/test/ui/parser/dyn-trait-compatibility.stderr diff --git a/src/test/ui/parser/emoji-identifiers.rs b/src/test/ui/parser/emoji-identifiers.rs new file mode 100644 index 0000000000..ef18939bbb --- /dev/null +++ b/src/test/ui/parser/emoji-identifiers.rs @@ -0,0 +1,16 @@ +struct ABig👩‍👩‍👧‍👧Family; //~ ERROR identifiers cannot contain emoji +struct 👀; //~ ERROR identifiers cannot contain emoji +impl 👀 { + fn full_of_✨() -> 👀 { //~ ERROR identifiers cannot contain emoji + 👀 + } +} +fn i_like_to_😅_a_lot() -> 👀 { //~ ERROR identifiers cannot contain emoji + 👀::full_of✨() //~ ERROR no function or associated item named `full_of✨` found for struct `👀` + //~^ ERROR identifiers cannot contain emoji +} +fn main() { + let _ = i_like_to_😄_a_lot() ➖ 4; //~ ERROR cannot find function `i_like_to_😄_a_lot` in this scope + //~^ ERROR identifiers cannot contain emoji + //~| ERROR unknown start of token: \u{2796} +} diff --git a/src/test/ui/parser/emoji-identifiers.stderr b/src/test/ui/parser/emoji-identifiers.stderr new file mode 100644 index 0000000000..5f9263c4c1 --- /dev/null +++ b/src/test/ui/parser/emoji-identifiers.stderr @@ -0,0 +1,83 @@ +error: unknown start of token: \u{2796} + --> $DIR/emoji-identifiers.rs:13:33 + | +LL | let _ = i_like_to_😄_a_lot() ➖ 4; + | ^^ + | +help: Unicode character '➖' (Heavy Minus Sign) looks like '-' (Minus/Hyphen), but it is not + | +LL | let _ = i_like_to_😄_a_lot() - 4; + | ~ + +error[E0425]: cannot find function `i_like_to_😄_a_lot` in this scope + --> $DIR/emoji-identifiers.rs:13:13 + | +LL | fn i_like_to_😅_a_lot() -> 👀 { + | ----------------------------- similarly named function `i_like_to_😅_a_lot` defined here +... +LL | let _ = i_like_to_😄_a_lot() ➖ 4; + | ^^^^^^^^^^^^^^^^^^ help: a function with a similar name exists: `i_like_to_😅_a_lot` + +error: identifiers cannot contain emoji: `ABig👩👩👧👧Family` + --> $DIR/emoji-identifiers.rs:1:8 + | +LL | struct ABig👩👩👧👧Family; + | ^^^^^^^^^^^^^^^^^^ + +error: identifiers cannot contain emoji: `👀` + --> $DIR/emoji-identifiers.rs:2:8 + | +LL | struct 👀; + | ^^ +LL | impl 👀 { + | ^^ +LL | fn full_of_✨() -> 👀 { + | ^^ +LL | 👀 + | ^^ +... +LL | fn i_like_to_😅_a_lot() -> 👀 { + | ^^ +LL | 👀::full_of✨() + | ^^ + +error: identifiers cannot contain emoji: `full_of_✨` + --> $DIR/emoji-identifiers.rs:4:8 + | +LL | fn full_of_✨() -> 👀 { + | ^^^^^^^^^^ + +error: identifiers cannot contain emoji: `i_like_to_😅_a_lot` + --> $DIR/emoji-identifiers.rs:8:4 + | +LL | fn i_like_to_😅_a_lot() -> 👀 { + | ^^^^^^^^^^^^^^^^^^ + +error: identifiers cannot contain emoji: `full_of✨` + --> $DIR/emoji-identifiers.rs:9:8 + | +LL | 👀::full_of✨() + | ^^^^^^^^^ + +error: identifiers cannot contain emoji: `i_like_to_😄_a_lot` + --> $DIR/emoji-identifiers.rs:13:13 + | +LL | let _ = i_like_to_😄_a_lot() ➖ 4; + | ^^^^^^^^^^^^^^^^^^ + +error[E0599]: no function or associated item named `full_of✨` found for struct `👀` in the current scope + --> $DIR/emoji-identifiers.rs:9:8 + | +LL | struct 👀; + | ---------- function or associated item `full_of✨` not found for this +... +LL | 👀::full_of✨() + | ^^^^^^^^^ + | | + | function or associated item not found in `👀` + | help: there is an associated function with a similar name: `full_of_✨` + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0425, E0599. +For more information about an error, try `rustc --explain E0425`. diff --git a/src/test/ui/parser/fn-header-semantic-fail.stderr b/src/test/ui/parser/fn-header-semantic-fail.stderr index 0adfa5b47a..75c60a0ea2 100644 --- a/src/test/ui/parser/fn-header-semantic-fail.stderr +++ b/src/test/ui/parser/fn-header-semantic-fail.stderr @@ -194,7 +194,7 @@ LL | async fn ft1() {} | = note: while checking the return type of the `async fn` = note: expected fn pointer `fn()` - found fn pointer `fn() -> impl Future` + found fn pointer `fn() -> impl Future<Output = ()>` error[E0053]: method `ft5` has an incompatible type for trait --> $DIR/fn-header-semantic-fail.rs:33:48 @@ -210,7 +210,7 @@ LL | const async unsafe extern "C" fn ft5() {} | = note: while checking the return type of the `async fn` = note: expected fn pointer `unsafe extern "C" fn()` - found fn pointer `unsafe extern "C" fn() -> impl Future` + found fn pointer `unsafe extern "C" fn() -> impl Future<Output = ()>` error: aborting due to 20 previous errors diff --git a/src/test/ui/parser/issue-90728.rs b/src/test/ui/parser/issue-90728.rs new file mode 100644 index 0000000000..d6a898361c --- /dev/null +++ b/src/test/ui/parser/issue-90728.rs @@ -0,0 +1,6 @@ +fn main() { + a.5.2E+ + //~^ ERROR: unexpected token: `5.2E+` + //~| ERROR: expected one of `.`, `;`, `?`, `}`, or an operator, found `5.2E+` + //~| ERROR: expected at least one digit in exponent +} diff --git a/src/test/ui/parser/issue-90728.stderr b/src/test/ui/parser/issue-90728.stderr new file mode 100644 index 0000000000..b55c460306 --- /dev/null +++ b/src/test/ui/parser/issue-90728.stderr @@ -0,0 +1,20 @@ +error: expected at least one digit in exponent + --> $DIR/issue-90728.rs:2:7 + | +LL | a.5.2E+ + | ^^^^^ + +error: unexpected token: `5.2E+` + --> $DIR/issue-90728.rs:2:7 + | +LL | a.5.2E+ + | ^^^^^ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `5.2E+` + --> $DIR/issue-90728.rs:2:7 + | +LL | a.5.2E+ + | ^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/parser/auxiliary/issue-21146-inc.rs b/src/test/ui/parser/issues/auxiliary/issue-21146-inc.rs similarity index 100% rename from src/test/ui/parser/auxiliary/issue-21146-inc.rs rename to src/test/ui/parser/issues/auxiliary/issue-21146-inc.rs diff --git a/src/test/ui/parser/issues/auxiliary/issue-89971-outer-attr-following-inner-attr-ice.rs b/src/test/ui/parser/issues/auxiliary/issue-89971-outer-attr-following-inner-attr-ice.rs new file mode 100644 index 0000000000..e5604b816b --- /dev/null +++ b/src/test/ui/parser/issues/auxiliary/issue-89971-outer-attr-following-inner-attr-ice.rs @@ -0,0 +1,13 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(ICE)] +pub fn derive(_: TokenStream) -> TokenStream { + r#"#[allow(missing_docs)] struct X { }"#.parse().unwrap() +} diff --git a/src/test/ui/parser/issue-10392-2.fixed b/src/test/ui/parser/issues/issue-10392-2.fixed similarity index 100% rename from src/test/ui/parser/issue-10392-2.fixed rename to src/test/ui/parser/issues/issue-10392-2.fixed diff --git a/src/test/ui/parser/issue-10392-2.rs b/src/test/ui/parser/issues/issue-10392-2.rs similarity index 100% rename from src/test/ui/parser/issue-10392-2.rs rename to src/test/ui/parser/issues/issue-10392-2.rs diff --git a/src/test/ui/parser/issue-10392-2.stderr b/src/test/ui/parser/issues/issue-10392-2.stderr similarity index 100% rename from src/test/ui/parser/issue-10392-2.stderr rename to src/test/ui/parser/issues/issue-10392-2.stderr diff --git a/src/test/ui/parser/issue-10392.rs b/src/test/ui/parser/issues/issue-10392.rs similarity index 100% rename from src/test/ui/parser/issue-10392.rs rename to src/test/ui/parser/issues/issue-10392.rs diff --git a/src/test/ui/parser/issue-10392.stderr b/src/test/ui/parser/issues/issue-10392.stderr similarity index 100% rename from src/test/ui/parser/issue-10392.stderr rename to src/test/ui/parser/issues/issue-10392.stderr diff --git a/src/test/ui/parser/issue-10636-1.rs b/src/test/ui/parser/issues/issue-10636-1.rs similarity index 100% rename from src/test/ui/parser/issue-10636-1.rs rename to src/test/ui/parser/issues/issue-10636-1.rs diff --git a/src/test/ui/parser/issue-10636-1.stderr b/src/test/ui/parser/issues/issue-10636-1.stderr similarity index 100% rename from src/test/ui/parser/issue-10636-1.stderr rename to src/test/ui/parser/issues/issue-10636-1.stderr diff --git a/src/test/ui/parser/issue-10636-2.rs b/src/test/ui/parser/issues/issue-10636-2.rs similarity index 100% rename from src/test/ui/parser/issue-10636-2.rs rename to src/test/ui/parser/issues/issue-10636-2.rs diff --git a/src/test/ui/parser/issue-10636-2.stderr b/src/test/ui/parser/issues/issue-10636-2.stderr similarity index 100% rename from src/test/ui/parser/issue-10636-2.stderr rename to src/test/ui/parser/issues/issue-10636-2.stderr diff --git a/src/test/ui/issues/issue-13483.rs b/src/test/ui/parser/issues/issue-13483.rs similarity index 100% rename from src/test/ui/issues/issue-13483.rs rename to src/test/ui/parser/issues/issue-13483.rs diff --git a/src/test/ui/issues/issue-13483.stderr b/src/test/ui/parser/issues/issue-13483.stderr similarity index 100% rename from src/test/ui/issues/issue-13483.stderr rename to src/test/ui/parser/issues/issue-13483.stderr diff --git a/src/test/ui/parser/issue-14303-enum.rs b/src/test/ui/parser/issues/issue-14303-enum.rs similarity index 100% rename from src/test/ui/parser/issue-14303-enum.rs rename to src/test/ui/parser/issues/issue-14303-enum.rs diff --git a/src/test/ui/parser/issue-14303-enum.stderr b/src/test/ui/parser/issues/issue-14303-enum.stderr similarity index 100% rename from src/test/ui/parser/issue-14303-enum.stderr rename to src/test/ui/parser/issues/issue-14303-enum.stderr diff --git a/src/test/ui/parser/issue-14303-fn-def.rs b/src/test/ui/parser/issues/issue-14303-fn-def.rs similarity index 100% rename from src/test/ui/parser/issue-14303-fn-def.rs rename to src/test/ui/parser/issues/issue-14303-fn-def.rs diff --git a/src/test/ui/parser/issue-14303-fn-def.stderr b/src/test/ui/parser/issues/issue-14303-fn-def.stderr similarity index 100% rename from src/test/ui/parser/issue-14303-fn-def.stderr rename to src/test/ui/parser/issues/issue-14303-fn-def.stderr diff --git a/src/test/ui/parser/issue-14303-fncall.full.stderr b/src/test/ui/parser/issues/issue-14303-fncall.full.stderr similarity index 100% rename from src/test/ui/parser/issue-14303-fncall.full.stderr rename to src/test/ui/parser/issues/issue-14303-fncall.full.stderr diff --git a/src/test/ui/parser/issue-14303-fncall.generic_arg.stderr b/src/test/ui/parser/issues/issue-14303-fncall.generic_arg.stderr similarity index 100% rename from src/test/ui/parser/issue-14303-fncall.generic_arg.stderr rename to src/test/ui/parser/issues/issue-14303-fncall.generic_arg.stderr diff --git a/src/test/ui/parser/issue-14303-fncall.rs b/src/test/ui/parser/issues/issue-14303-fncall.rs similarity index 100% rename from src/test/ui/parser/issue-14303-fncall.rs rename to src/test/ui/parser/issues/issue-14303-fncall.rs diff --git a/src/test/ui/parser/issue-14303-impl.rs b/src/test/ui/parser/issues/issue-14303-impl.rs similarity index 100% rename from src/test/ui/parser/issue-14303-impl.rs rename to src/test/ui/parser/issues/issue-14303-impl.rs diff --git a/src/test/ui/parser/issue-14303-impl.stderr b/src/test/ui/parser/issues/issue-14303-impl.stderr similarity index 100% rename from src/test/ui/parser/issue-14303-impl.stderr rename to src/test/ui/parser/issues/issue-14303-impl.stderr diff --git a/src/test/ui/parser/issue-14303-path.rs b/src/test/ui/parser/issues/issue-14303-path.rs similarity index 100% rename from src/test/ui/parser/issue-14303-path.rs rename to src/test/ui/parser/issues/issue-14303-path.rs diff --git a/src/test/ui/parser/issue-14303-path.stderr b/src/test/ui/parser/issues/issue-14303-path.stderr similarity index 100% rename from src/test/ui/parser/issue-14303-path.stderr rename to src/test/ui/parser/issues/issue-14303-path.stderr diff --git a/src/test/ui/parser/issue-14303-struct.rs b/src/test/ui/parser/issues/issue-14303-struct.rs similarity index 100% rename from src/test/ui/parser/issue-14303-struct.rs rename to src/test/ui/parser/issues/issue-14303-struct.rs diff --git a/src/test/ui/parser/issue-14303-struct.stderr b/src/test/ui/parser/issues/issue-14303-struct.stderr similarity index 100% rename from src/test/ui/parser/issue-14303-struct.stderr rename to src/test/ui/parser/issues/issue-14303-struct.stderr diff --git a/src/test/ui/parser/issue-14303-trait.rs b/src/test/ui/parser/issues/issue-14303-trait.rs similarity index 100% rename from src/test/ui/parser/issue-14303-trait.rs rename to src/test/ui/parser/issues/issue-14303-trait.rs diff --git a/src/test/ui/parser/issue-14303-trait.stderr b/src/test/ui/parser/issues/issue-14303-trait.stderr similarity index 100% rename from src/test/ui/parser/issue-14303-trait.stderr rename to src/test/ui/parser/issues/issue-14303-trait.stderr diff --git a/src/test/ui/parser/issue-15914.rs b/src/test/ui/parser/issues/issue-15914.rs similarity index 100% rename from src/test/ui/parser/issue-15914.rs rename to src/test/ui/parser/issues/issue-15914.rs diff --git a/src/test/ui/parser/issue-15914.stderr b/src/test/ui/parser/issues/issue-15914.stderr similarity index 100% rename from src/test/ui/parser/issue-15914.stderr rename to src/test/ui/parser/issues/issue-15914.stderr diff --git a/src/test/ui/parser/issue-15980.rs b/src/test/ui/parser/issues/issue-15980.rs similarity index 100% rename from src/test/ui/parser/issue-15980.rs rename to src/test/ui/parser/issues/issue-15980.rs diff --git a/src/test/ui/parser/issue-15980.stderr b/src/test/ui/parser/issues/issue-15980.stderr similarity index 100% rename from src/test/ui/parser/issue-15980.stderr rename to src/test/ui/parser/issues/issue-15980.stderr diff --git a/src/test/ui/parser/issue-1655.rs b/src/test/ui/parser/issues/issue-1655.rs similarity index 100% rename from src/test/ui/parser/issue-1655.rs rename to src/test/ui/parser/issues/issue-1655.rs diff --git a/src/test/ui/parser/issue-1655.stderr b/src/test/ui/parser/issues/issue-1655.stderr similarity index 100% rename from src/test/ui/parser/issue-1655.stderr rename to src/test/ui/parser/issues/issue-1655.stderr diff --git a/src/test/ui/parser/issue-17383.rs b/src/test/ui/parser/issues/issue-17383.rs similarity index 100% rename from src/test/ui/parser/issue-17383.rs rename to src/test/ui/parser/issues/issue-17383.rs diff --git a/src/test/ui/parser/issue-17383.stderr b/src/test/ui/parser/issues/issue-17383.stderr similarity index 100% rename from src/test/ui/parser/issue-17383.stderr rename to src/test/ui/parser/issues/issue-17383.stderr diff --git a/src/test/ui/parser/issue-17718-const-mut.rs b/src/test/ui/parser/issues/issue-17718-const-mut.rs similarity index 100% rename from src/test/ui/parser/issue-17718-const-mut.rs rename to src/test/ui/parser/issues/issue-17718-const-mut.rs diff --git a/src/test/ui/parser/issue-17718-const-mut.stderr b/src/test/ui/parser/issues/issue-17718-const-mut.stderr similarity index 100% rename from src/test/ui/parser/issue-17718-const-mut.stderr rename to src/test/ui/parser/issues/issue-17718-const-mut.stderr diff --git a/src/test/ui/parser/issue-17904-2.rs b/src/test/ui/parser/issues/issue-17904-2.rs similarity index 100% rename from src/test/ui/parser/issue-17904-2.rs rename to src/test/ui/parser/issues/issue-17904-2.rs diff --git a/src/test/ui/parser/issue-17904-2.stderr b/src/test/ui/parser/issues/issue-17904-2.stderr similarity index 100% rename from src/test/ui/parser/issue-17904-2.stderr rename to src/test/ui/parser/issues/issue-17904-2.stderr diff --git a/src/test/ui/parser/issue-17904.rs b/src/test/ui/parser/issues/issue-17904.rs similarity index 100% rename from src/test/ui/parser/issue-17904.rs rename to src/test/ui/parser/issues/issue-17904.rs diff --git a/src/test/ui/parser/issue-17904.stderr b/src/test/ui/parser/issues/issue-17904.stderr similarity index 100% rename from src/test/ui/parser/issue-17904.stderr rename to src/test/ui/parser/issues/issue-17904.stderr diff --git a/src/test/ui/parser/issue-1802-1.rs b/src/test/ui/parser/issues/issue-1802-1.rs similarity index 100% rename from src/test/ui/parser/issue-1802-1.rs rename to src/test/ui/parser/issues/issue-1802-1.rs diff --git a/src/test/ui/parser/issue-1802-1.stderr b/src/test/ui/parser/issues/issue-1802-1.stderr similarity index 100% rename from src/test/ui/parser/issue-1802-1.stderr rename to src/test/ui/parser/issues/issue-1802-1.stderr diff --git a/src/test/ui/parser/issue-1802-2.rs b/src/test/ui/parser/issues/issue-1802-2.rs similarity index 100% rename from src/test/ui/parser/issue-1802-2.rs rename to src/test/ui/parser/issues/issue-1802-2.rs diff --git a/src/test/ui/parser/issue-1802-2.stderr b/src/test/ui/parser/issues/issue-1802-2.stderr similarity index 100% rename from src/test/ui/parser/issue-1802-2.stderr rename to src/test/ui/parser/issues/issue-1802-2.stderr diff --git a/src/test/ui/parser/issue-19096.rs b/src/test/ui/parser/issues/issue-19096.rs similarity index 100% rename from src/test/ui/parser/issue-19096.rs rename to src/test/ui/parser/issues/issue-19096.rs diff --git a/src/test/ui/parser/issue-19096.stderr b/src/test/ui/parser/issues/issue-19096.stderr similarity index 100% rename from src/test/ui/parser/issue-19096.stderr rename to src/test/ui/parser/issues/issue-19096.stderr diff --git a/src/test/ui/parser/issue-19398.rs b/src/test/ui/parser/issues/issue-19398.rs similarity index 100% rename from src/test/ui/parser/issue-19398.rs rename to src/test/ui/parser/issues/issue-19398.rs diff --git a/src/test/ui/parser/issue-19398.stderr b/src/test/ui/parser/issues/issue-19398.stderr similarity index 100% rename from src/test/ui/parser/issue-19398.stderr rename to src/test/ui/parser/issues/issue-19398.stderr diff --git a/src/test/ui/parser/issue-20616-1.rs b/src/test/ui/parser/issues/issue-20616-1.rs similarity index 100% rename from src/test/ui/parser/issue-20616-1.rs rename to src/test/ui/parser/issues/issue-20616-1.rs diff --git a/src/test/ui/parser/issue-20616-1.stderr b/src/test/ui/parser/issues/issue-20616-1.stderr similarity index 100% rename from src/test/ui/parser/issue-20616-1.stderr rename to src/test/ui/parser/issues/issue-20616-1.stderr diff --git a/src/test/ui/parser/issue-20616-2.rs b/src/test/ui/parser/issues/issue-20616-2.rs similarity index 100% rename from src/test/ui/parser/issue-20616-2.rs rename to src/test/ui/parser/issues/issue-20616-2.rs diff --git a/src/test/ui/parser/issue-20616-2.stderr b/src/test/ui/parser/issues/issue-20616-2.stderr similarity index 100% rename from src/test/ui/parser/issue-20616-2.stderr rename to src/test/ui/parser/issues/issue-20616-2.stderr diff --git a/src/test/ui/parser/issue-20616-3.rs b/src/test/ui/parser/issues/issue-20616-3.rs similarity index 100% rename from src/test/ui/parser/issue-20616-3.rs rename to src/test/ui/parser/issues/issue-20616-3.rs diff --git a/src/test/ui/parser/issue-20616-3.stderr b/src/test/ui/parser/issues/issue-20616-3.stderr similarity index 100% rename from src/test/ui/parser/issue-20616-3.stderr rename to src/test/ui/parser/issues/issue-20616-3.stderr diff --git a/src/test/ui/issues/issue-20616-4.rs b/src/test/ui/parser/issues/issue-20616-4.rs similarity index 100% rename from src/test/ui/issues/issue-20616-4.rs rename to src/test/ui/parser/issues/issue-20616-4.rs diff --git a/src/test/ui/issues/issue-20616-4.stderr b/src/test/ui/parser/issues/issue-20616-4.stderr similarity index 100% rename from src/test/ui/issues/issue-20616-4.stderr rename to src/test/ui/parser/issues/issue-20616-4.stderr diff --git a/src/test/ui/issues/issue-20616-5.rs b/src/test/ui/parser/issues/issue-20616-5.rs similarity index 100% rename from src/test/ui/issues/issue-20616-5.rs rename to src/test/ui/parser/issues/issue-20616-5.rs diff --git a/src/test/ui/issues/issue-20616-5.stderr b/src/test/ui/parser/issues/issue-20616-5.stderr similarity index 100% rename from src/test/ui/issues/issue-20616-5.stderr rename to src/test/ui/parser/issues/issue-20616-5.stderr diff --git a/src/test/ui/issues/issue-20616-6.rs b/src/test/ui/parser/issues/issue-20616-6.rs similarity index 100% rename from src/test/ui/issues/issue-20616-6.rs rename to src/test/ui/parser/issues/issue-20616-6.rs diff --git a/src/test/ui/issues/issue-20616-6.stderr b/src/test/ui/parser/issues/issue-20616-6.stderr similarity index 100% rename from src/test/ui/issues/issue-20616-6.stderr rename to src/test/ui/parser/issues/issue-20616-6.stderr diff --git a/src/test/ui/issues/issue-20616-7.rs b/src/test/ui/parser/issues/issue-20616-7.rs similarity index 100% rename from src/test/ui/issues/issue-20616-7.rs rename to src/test/ui/parser/issues/issue-20616-7.rs diff --git a/src/test/ui/issues/issue-20616-7.stderr b/src/test/ui/parser/issues/issue-20616-7.stderr similarity index 100% rename from src/test/ui/issues/issue-20616-7.stderr rename to src/test/ui/parser/issues/issue-20616-7.stderr diff --git a/src/test/ui/parser/issue-20616-8.rs b/src/test/ui/parser/issues/issue-20616-8.rs similarity index 100% rename from src/test/ui/parser/issue-20616-8.rs rename to src/test/ui/parser/issues/issue-20616-8.rs diff --git a/src/test/ui/parser/issue-20616-8.stderr b/src/test/ui/parser/issues/issue-20616-8.stderr similarity index 100% rename from src/test/ui/parser/issue-20616-8.stderr rename to src/test/ui/parser/issues/issue-20616-8.stderr diff --git a/src/test/ui/parser/issue-20616-9.rs b/src/test/ui/parser/issues/issue-20616-9.rs similarity index 100% rename from src/test/ui/parser/issue-20616-9.rs rename to src/test/ui/parser/issues/issue-20616-9.rs diff --git a/src/test/ui/parser/issue-20616-9.stderr b/src/test/ui/parser/issues/issue-20616-9.stderr similarity index 100% rename from src/test/ui/parser/issue-20616-9.stderr rename to src/test/ui/parser/issues/issue-20616-9.stderr diff --git a/src/test/ui/parser/issue-20711-2.rs b/src/test/ui/parser/issues/issue-20711-2.rs similarity index 100% rename from src/test/ui/parser/issue-20711-2.rs rename to src/test/ui/parser/issues/issue-20711-2.rs diff --git a/src/test/ui/parser/issue-20711-2.stderr b/src/test/ui/parser/issues/issue-20711-2.stderr similarity index 100% rename from src/test/ui/parser/issue-20711-2.stderr rename to src/test/ui/parser/issues/issue-20711-2.stderr diff --git a/src/test/ui/parser/issue-20711.rs b/src/test/ui/parser/issues/issue-20711.rs similarity index 100% rename from src/test/ui/parser/issue-20711.rs rename to src/test/ui/parser/issues/issue-20711.rs diff --git a/src/test/ui/parser/issue-20711.stderr b/src/test/ui/parser/issues/issue-20711.stderr similarity index 100% rename from src/test/ui/parser/issue-20711.stderr rename to src/test/ui/parser/issues/issue-20711.stderr diff --git a/src/test/ui/parser/issue-21146.rs b/src/test/ui/parser/issues/issue-21146.rs similarity index 100% rename from src/test/ui/parser/issue-21146.rs rename to src/test/ui/parser/issues/issue-21146.rs diff --git a/src/test/ui/parser/issue-21146.stderr b/src/test/ui/parser/issues/issue-21146.stderr similarity index 100% rename from src/test/ui/parser/issue-21146.stderr rename to src/test/ui/parser/issues/issue-21146.stderr diff --git a/src/test/ui/parser/issue-21153.rs b/src/test/ui/parser/issues/issue-21153.rs similarity index 100% rename from src/test/ui/parser/issue-21153.rs rename to src/test/ui/parser/issues/issue-21153.rs diff --git a/src/test/ui/parser/issue-21153.stderr b/src/test/ui/parser/issues/issue-21153.stderr similarity index 100% rename from src/test/ui/parser/issue-21153.stderr rename to src/test/ui/parser/issues/issue-21153.stderr diff --git a/src/test/ui/issues/issue-21475.rs b/src/test/ui/parser/issues/issue-21475.rs similarity index 100% rename from src/test/ui/issues/issue-21475.rs rename to src/test/ui/parser/issues/issue-21475.rs diff --git a/src/test/ui/parser/issue-22647.rs b/src/test/ui/parser/issues/issue-22647.rs similarity index 100% rename from src/test/ui/parser/issue-22647.rs rename to src/test/ui/parser/issues/issue-22647.rs diff --git a/src/test/ui/parser/issue-22647.stderr b/src/test/ui/parser/issues/issue-22647.stderr similarity index 100% rename from src/test/ui/parser/issue-22647.stderr rename to src/test/ui/parser/issues/issue-22647.stderr diff --git a/src/test/ui/parser/issue-22712.rs b/src/test/ui/parser/issues/issue-22712.rs similarity index 100% rename from src/test/ui/parser/issue-22712.rs rename to src/test/ui/parser/issues/issue-22712.rs diff --git a/src/test/ui/parser/issue-22712.stderr b/src/test/ui/parser/issues/issue-22712.stderr similarity index 100% rename from src/test/ui/parser/issue-22712.stderr rename to src/test/ui/parser/issues/issue-22712.stderr diff --git a/src/test/ui/parser/issue-2354-1.rs b/src/test/ui/parser/issues/issue-2354-1.rs similarity index 100% rename from src/test/ui/parser/issue-2354-1.rs rename to src/test/ui/parser/issues/issue-2354-1.rs diff --git a/src/test/ui/parser/issue-2354-1.stderr b/src/test/ui/parser/issues/issue-2354-1.stderr similarity index 100% rename from src/test/ui/parser/issue-2354-1.stderr rename to src/test/ui/parser/issues/issue-2354-1.stderr diff --git a/src/test/ui/parser/issue-2354.rs b/src/test/ui/parser/issues/issue-2354.rs similarity index 100% rename from src/test/ui/parser/issue-2354.rs rename to src/test/ui/parser/issues/issue-2354.rs diff --git a/src/test/ui/parser/issue-2354.stderr b/src/test/ui/parser/issues/issue-2354.stderr similarity index 100% rename from src/test/ui/parser/issue-2354.stderr rename to src/test/ui/parser/issues/issue-2354.stderr diff --git a/src/test/ui/parser/issue-23620-invalid-escapes.rs b/src/test/ui/parser/issues/issue-23620-invalid-escapes.rs similarity index 100% rename from src/test/ui/parser/issue-23620-invalid-escapes.rs rename to src/test/ui/parser/issues/issue-23620-invalid-escapes.rs diff --git a/src/test/ui/parser/issue-23620-invalid-escapes.stderr b/src/test/ui/parser/issues/issue-23620-invalid-escapes.stderr similarity index 100% rename from src/test/ui/parser/issue-23620-invalid-escapes.stderr rename to src/test/ui/parser/issues/issue-23620-invalid-escapes.stderr diff --git a/src/test/ui/parser/issue-24197.rs b/src/test/ui/parser/issues/issue-24197.rs similarity index 100% rename from src/test/ui/parser/issue-24197.rs rename to src/test/ui/parser/issues/issue-24197.rs diff --git a/src/test/ui/parser/issue-24197.stderr b/src/test/ui/parser/issues/issue-24197.stderr similarity index 100% rename from src/test/ui/parser/issue-24197.stderr rename to src/test/ui/parser/issues/issue-24197.stderr diff --git a/src/test/ui/parser/issue-24375.rs b/src/test/ui/parser/issues/issue-24375.rs similarity index 100% rename from src/test/ui/parser/issue-24375.rs rename to src/test/ui/parser/issues/issue-24375.rs diff --git a/src/test/ui/parser/issue-24375.stderr b/src/test/ui/parser/issues/issue-24375.stderr similarity index 100% rename from src/test/ui/parser/issue-24375.stderr rename to src/test/ui/parser/issues/issue-24375.stderr diff --git a/src/test/ui/parser/issue-24780.rs b/src/test/ui/parser/issues/issue-24780.rs similarity index 100% rename from src/test/ui/parser/issue-24780.rs rename to src/test/ui/parser/issues/issue-24780.rs diff --git a/src/test/ui/parser/issue-24780.stderr b/src/test/ui/parser/issues/issue-24780.stderr similarity index 100% rename from src/test/ui/parser/issue-24780.stderr rename to src/test/ui/parser/issues/issue-24780.stderr diff --git a/src/test/ui/parser/issue-27255.rs b/src/test/ui/parser/issues/issue-27255.rs similarity index 100% rename from src/test/ui/parser/issue-27255.rs rename to src/test/ui/parser/issues/issue-27255.rs diff --git a/src/test/ui/parser/issue-27255.stderr b/src/test/ui/parser/issues/issue-27255.stderr similarity index 100% rename from src/test/ui/parser/issue-27255.stderr rename to src/test/ui/parser/issues/issue-27255.stderr diff --git a/src/test/ui/parser/issue-30318.fixed b/src/test/ui/parser/issues/issue-30318.fixed similarity index 100% rename from src/test/ui/parser/issue-30318.fixed rename to src/test/ui/parser/issues/issue-30318.fixed diff --git a/src/test/ui/parser/issue-30318.rs b/src/test/ui/parser/issues/issue-30318.rs similarity index 100% rename from src/test/ui/parser/issue-30318.rs rename to src/test/ui/parser/issues/issue-30318.rs diff --git a/src/test/ui/parser/issue-30318.stderr b/src/test/ui/parser/issues/issue-30318.stderr similarity index 100% rename from src/test/ui/parser/issue-30318.stderr rename to src/test/ui/parser/issues/issue-30318.stderr diff --git a/src/test/ui/parser/issue-3036.fixed b/src/test/ui/parser/issues/issue-3036.fixed similarity index 100% rename from src/test/ui/parser/issue-3036.fixed rename to src/test/ui/parser/issues/issue-3036.fixed diff --git a/src/test/ui/parser/issue-3036.rs b/src/test/ui/parser/issues/issue-3036.rs similarity index 100% rename from src/test/ui/parser/issue-3036.rs rename to src/test/ui/parser/issues/issue-3036.rs diff --git a/src/test/ui/parser/issue-3036.stderr b/src/test/ui/parser/issues/issue-3036.stderr similarity index 100% rename from src/test/ui/parser/issue-3036.stderr rename to src/test/ui/parser/issues/issue-3036.stderr diff --git a/src/test/ui/issues/issue-31804.rs b/src/test/ui/parser/issues/issue-31804.rs similarity index 100% rename from src/test/ui/issues/issue-31804.rs rename to src/test/ui/parser/issues/issue-31804.rs diff --git a/src/test/ui/issues/issue-31804.stderr b/src/test/ui/parser/issues/issue-31804.stderr similarity index 100% rename from src/test/ui/issues/issue-31804.stderr rename to src/test/ui/parser/issues/issue-31804.stderr diff --git a/src/test/ui/parser/issue-32214.rs b/src/test/ui/parser/issues/issue-32214.rs similarity index 100% rename from src/test/ui/parser/issue-32214.rs rename to src/test/ui/parser/issues/issue-32214.rs diff --git a/src/test/ui/parser/issue-32214.stderr b/src/test/ui/parser/issues/issue-32214.stderr similarity index 100% rename from src/test/ui/parser/issue-32214.stderr rename to src/test/ui/parser/issues/issue-32214.stderr diff --git a/src/test/ui/parser/issue-32446.rs b/src/test/ui/parser/issues/issue-32446.rs similarity index 100% rename from src/test/ui/parser/issue-32446.rs rename to src/test/ui/parser/issues/issue-32446.rs diff --git a/src/test/ui/parser/issue-32446.stderr b/src/test/ui/parser/issues/issue-32446.stderr similarity index 100% rename from src/test/ui/parser/issue-32446.stderr rename to src/test/ui/parser/issues/issue-32446.stderr diff --git a/src/test/ui/parser/issue-32501.rs b/src/test/ui/parser/issues/issue-32501.rs similarity index 100% rename from src/test/ui/parser/issue-32501.rs rename to src/test/ui/parser/issues/issue-32501.rs diff --git a/src/test/ui/parser/issue-32501.stderr b/src/test/ui/parser/issues/issue-32501.stderr similarity index 100% rename from src/test/ui/parser/issue-32501.stderr rename to src/test/ui/parser/issues/issue-32501.stderr diff --git a/src/test/ui/parser/issue-32505.rs b/src/test/ui/parser/issues/issue-32505.rs similarity index 100% rename from src/test/ui/parser/issue-32505.rs rename to src/test/ui/parser/issues/issue-32505.rs diff --git a/src/test/ui/parser/issue-32505.stderr b/src/test/ui/parser/issues/issue-32505.stderr similarity index 100% rename from src/test/ui/parser/issue-32505.stderr rename to src/test/ui/parser/issues/issue-32505.stderr diff --git a/src/test/ui/parser/issue-33262.rs b/src/test/ui/parser/issues/issue-33262.rs similarity index 100% rename from src/test/ui/parser/issue-33262.rs rename to src/test/ui/parser/issues/issue-33262.rs diff --git a/src/test/ui/parser/issue-33262.stderr b/src/test/ui/parser/issues/issue-33262.stderr similarity index 100% rename from src/test/ui/parser/issue-33262.stderr rename to src/test/ui/parser/issues/issue-33262.stderr diff --git a/src/test/ui/parser/issue-33413.rs b/src/test/ui/parser/issues/issue-33413.rs similarity index 100% rename from src/test/ui/parser/issue-33413.rs rename to src/test/ui/parser/issues/issue-33413.rs diff --git a/src/test/ui/parser/issue-33413.stderr b/src/test/ui/parser/issues/issue-33413.stderr similarity index 100% rename from src/test/ui/parser/issue-33413.stderr rename to src/test/ui/parser/issues/issue-33413.stderr diff --git a/src/test/ui/parser/issue-33418.fixed b/src/test/ui/parser/issues/issue-33418.fixed similarity index 100% rename from src/test/ui/parser/issue-33418.fixed rename to src/test/ui/parser/issues/issue-33418.fixed diff --git a/src/test/ui/parser/issue-33418.rs b/src/test/ui/parser/issues/issue-33418.rs similarity index 100% rename from src/test/ui/parser/issue-33418.rs rename to src/test/ui/parser/issues/issue-33418.rs diff --git a/src/test/ui/parser/issue-33418.stderr b/src/test/ui/parser/issues/issue-33418.stderr similarity index 100% rename from src/test/ui/parser/issue-33418.stderr rename to src/test/ui/parser/issues/issue-33418.stderr diff --git a/src/test/ui/parser/issue-33455.rs b/src/test/ui/parser/issues/issue-33455.rs similarity index 100% rename from src/test/ui/parser/issue-33455.rs rename to src/test/ui/parser/issues/issue-33455.rs diff --git a/src/test/ui/parser/issue-33455.stderr b/src/test/ui/parser/issues/issue-33455.stderr similarity index 100% rename from src/test/ui/parser/issue-33455.stderr rename to src/test/ui/parser/issues/issue-33455.stderr diff --git a/src/test/ui/parser/issue-34222-1.rs b/src/test/ui/parser/issues/issue-34222-1.rs similarity index 100% rename from src/test/ui/parser/issue-34222-1.rs rename to src/test/ui/parser/issues/issue-34222-1.rs diff --git a/src/test/ui/parser/issue-34222-1.stderr b/src/test/ui/parser/issues/issue-34222-1.stderr similarity index 100% rename from src/test/ui/parser/issue-34222-1.stderr rename to src/test/ui/parser/issues/issue-34222-1.stderr diff --git a/src/test/ui/issues/issue-34255-1.rs b/src/test/ui/parser/issues/issue-34255-1.rs similarity index 100% rename from src/test/ui/issues/issue-34255-1.rs rename to src/test/ui/parser/issues/issue-34255-1.rs diff --git a/src/test/ui/issues/issue-34255-1.stderr b/src/test/ui/parser/issues/issue-34255-1.stderr similarity index 100% rename from src/test/ui/issues/issue-34255-1.stderr rename to src/test/ui/parser/issues/issue-34255-1.stderr diff --git a/src/test/ui/parser/issue-35813-postfix-after-cast.rs b/src/test/ui/parser/issues/issue-35813-postfix-after-cast.rs similarity index 100% rename from src/test/ui/parser/issue-35813-postfix-after-cast.rs rename to src/test/ui/parser/issues/issue-35813-postfix-after-cast.rs diff --git a/src/test/ui/parser/issue-35813-postfix-after-cast.stderr b/src/test/ui/parser/issues/issue-35813-postfix-after-cast.stderr similarity index 100% rename from src/test/ui/parser/issue-35813-postfix-after-cast.stderr rename to src/test/ui/parser/issues/issue-35813-postfix-after-cast.stderr diff --git a/src/test/ui/parser/issue-41155.rs b/src/test/ui/parser/issues/issue-41155.rs similarity index 100% rename from src/test/ui/parser/issue-41155.rs rename to src/test/ui/parser/issues/issue-41155.rs diff --git a/src/test/ui/parser/issue-41155.stderr b/src/test/ui/parser/issues/issue-41155.stderr similarity index 100% rename from src/test/ui/parser/issue-41155.stderr rename to src/test/ui/parser/issues/issue-41155.stderr diff --git a/src/test/ui/parser/issue-43196.rs b/src/test/ui/parser/issues/issue-43196.rs similarity index 100% rename from src/test/ui/parser/issue-43196.rs rename to src/test/ui/parser/issues/issue-43196.rs diff --git a/src/test/ui/parser/issue-43196.stderr b/src/test/ui/parser/issues/issue-43196.stderr similarity index 100% rename from src/test/ui/parser/issue-43196.stderr rename to src/test/ui/parser/issues/issue-43196.stderr diff --git a/src/test/ui/parser/issue-43692.rs b/src/test/ui/parser/issues/issue-43692.rs similarity index 100% rename from src/test/ui/parser/issue-43692.rs rename to src/test/ui/parser/issues/issue-43692.rs diff --git a/src/test/ui/parser/issue-43692.stderr b/src/test/ui/parser/issues/issue-43692.stderr similarity index 100% rename from src/test/ui/parser/issue-43692.stderr rename to src/test/ui/parser/issues/issue-43692.stderr diff --git a/src/test/ui/parser/issue-44021.rs b/src/test/ui/parser/issues/issue-44021.rs similarity index 100% rename from src/test/ui/parser/issue-44021.rs rename to src/test/ui/parser/issues/issue-44021.rs diff --git a/src/test/ui/parser/issue-44021.stderr b/src/test/ui/parser/issues/issue-44021.stderr similarity index 100% rename from src/test/ui/parser/issue-44021.stderr rename to src/test/ui/parser/issues/issue-44021.stderr diff --git a/src/test/ui/parser/issue-44406.rs b/src/test/ui/parser/issues/issue-44406.rs similarity index 100% rename from src/test/ui/parser/issue-44406.rs rename to src/test/ui/parser/issues/issue-44406.rs diff --git a/src/test/ui/parser/issue-44406.stderr b/src/test/ui/parser/issues/issue-44406.stderr similarity index 100% rename from src/test/ui/parser/issue-44406.stderr rename to src/test/ui/parser/issues/issue-44406.stderr diff --git a/src/test/ui/parser/issue-45296.rs b/src/test/ui/parser/issues/issue-45296.rs similarity index 100% rename from src/test/ui/parser/issue-45296.rs rename to src/test/ui/parser/issues/issue-45296.rs diff --git a/src/test/ui/parser/issue-45296.stderr b/src/test/ui/parser/issues/issue-45296.stderr similarity index 100% rename from src/test/ui/parser/issue-45296.stderr rename to src/test/ui/parser/issues/issue-45296.stderr diff --git a/src/test/ui/parser/issue-46186.fixed b/src/test/ui/parser/issues/issue-46186.fixed similarity index 100% rename from src/test/ui/parser/issue-46186.fixed rename to src/test/ui/parser/issues/issue-46186.fixed diff --git a/src/test/ui/parser/issue-46186.rs b/src/test/ui/parser/issues/issue-46186.rs similarity index 100% rename from src/test/ui/parser/issue-46186.rs rename to src/test/ui/parser/issues/issue-46186.rs diff --git a/src/test/ui/parser/issue-46186.stderr b/src/test/ui/parser/issues/issue-46186.stderr similarity index 100% rename from src/test/ui/parser/issue-46186.stderr rename to src/test/ui/parser/issues/issue-46186.stderr diff --git a/src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs b/src/test/ui/parser/issues/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs similarity index 100% rename from src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs rename to src/test/ui/parser/issues/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs diff --git a/src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.stderr b/src/test/ui/parser/issues/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.stderr similarity index 100% rename from src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.stderr rename to src/test/ui/parser/issues/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.stderr diff --git a/src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items.rs b/src/test/ui/parser/issues/issue-48137-macros-cannot-interpolate-impl-items.rs similarity index 100% rename from src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items.rs rename to src/test/ui/parser/issues/issue-48137-macros-cannot-interpolate-impl-items.rs diff --git a/src/test/ui/parser/issue-48508-aux.rs b/src/test/ui/parser/issues/issue-48508-aux.rs similarity index 100% rename from src/test/ui/parser/issue-48508-aux.rs rename to src/test/ui/parser/issues/issue-48508-aux.rs diff --git a/src/test/ui/parser/issue-48508.rs b/src/test/ui/parser/issues/issue-48508.rs similarity index 100% rename from src/test/ui/parser/issue-48508.rs rename to src/test/ui/parser/issues/issue-48508.rs diff --git a/src/test/ui/parser/issue-48636.fixed b/src/test/ui/parser/issues/issue-48636.fixed similarity index 100% rename from src/test/ui/parser/issue-48636.fixed rename to src/test/ui/parser/issues/issue-48636.fixed diff --git a/src/test/ui/parser/issue-48636.rs b/src/test/ui/parser/issues/issue-48636.rs similarity index 100% rename from src/test/ui/parser/issue-48636.rs rename to src/test/ui/parser/issues/issue-48636.rs diff --git a/src/test/ui/parser/issue-48636.stderr b/src/test/ui/parser/issues/issue-48636.stderr similarity index 100% rename from src/test/ui/parser/issue-48636.stderr rename to src/test/ui/parser/issues/issue-48636.stderr diff --git a/src/test/ui/issues/issue-49040.rs b/src/test/ui/parser/issues/issue-49040.rs similarity index 100% rename from src/test/ui/issues/issue-49040.rs rename to src/test/ui/parser/issues/issue-49040.rs diff --git a/src/test/ui/issues/issue-49040.stderr b/src/test/ui/parser/issues/issue-49040.stderr similarity index 100% rename from src/test/ui/issues/issue-49040.stderr rename to src/test/ui/parser/issues/issue-49040.stderr diff --git a/src/test/ui/parser/issue-51602.rs b/src/test/ui/parser/issues/issue-51602.rs similarity index 100% rename from src/test/ui/parser/issue-51602.rs rename to src/test/ui/parser/issues/issue-51602.rs diff --git a/src/test/ui/parser/issue-51602.stderr b/src/test/ui/parser/issues/issue-51602.stderr similarity index 100% rename from src/test/ui/parser/issue-51602.stderr rename to src/test/ui/parser/issues/issue-51602.stderr diff --git a/src/test/ui/parser/issue-52496.rs b/src/test/ui/parser/issues/issue-52496.rs similarity index 100% rename from src/test/ui/parser/issue-52496.rs rename to src/test/ui/parser/issues/issue-52496.rs diff --git a/src/test/ui/parser/issue-52496.stderr b/src/test/ui/parser/issues/issue-52496.stderr similarity index 100% rename from src/test/ui/parser/issue-52496.stderr rename to src/test/ui/parser/issues/issue-52496.stderr diff --git a/src/test/ui/parser/issue-54521-1.rs b/src/test/ui/parser/issues/issue-54521-1.rs similarity index 100% rename from src/test/ui/parser/issue-54521-1.rs rename to src/test/ui/parser/issues/issue-54521-1.rs diff --git a/src/test/ui/parser/issue-54521-2.fixed b/src/test/ui/parser/issues/issue-54521-2.fixed similarity index 100% rename from src/test/ui/parser/issue-54521-2.fixed rename to src/test/ui/parser/issues/issue-54521-2.fixed diff --git a/src/test/ui/parser/issue-54521-2.rs b/src/test/ui/parser/issues/issue-54521-2.rs similarity index 100% rename from src/test/ui/parser/issue-54521-2.rs rename to src/test/ui/parser/issues/issue-54521-2.rs diff --git a/src/test/ui/parser/issue-54521-2.stderr b/src/test/ui/parser/issues/issue-54521-2.stderr similarity index 100% rename from src/test/ui/parser/issue-54521-2.stderr rename to src/test/ui/parser/issues/issue-54521-2.stderr diff --git a/src/test/ui/parser/issue-54521-3.fixed b/src/test/ui/parser/issues/issue-54521-3.fixed similarity index 100% rename from src/test/ui/parser/issue-54521-3.fixed rename to src/test/ui/parser/issues/issue-54521-3.fixed diff --git a/src/test/ui/parser/issue-54521-3.rs b/src/test/ui/parser/issues/issue-54521-3.rs similarity index 100% rename from src/test/ui/parser/issue-54521-3.rs rename to src/test/ui/parser/issues/issue-54521-3.rs diff --git a/src/test/ui/parser/issue-54521-3.stderr b/src/test/ui/parser/issues/issue-54521-3.stderr similarity index 100% rename from src/test/ui/parser/issue-54521-3.stderr rename to src/test/ui/parser/issues/issue-54521-3.stderr diff --git a/src/test/ui/parser/issue-5544-a.rs b/src/test/ui/parser/issues/issue-5544-a.rs similarity index 100% rename from src/test/ui/parser/issue-5544-a.rs rename to src/test/ui/parser/issues/issue-5544-a.rs diff --git a/src/test/ui/parser/issue-5544-a.stderr b/src/test/ui/parser/issues/issue-5544-a.stderr similarity index 100% rename from src/test/ui/parser/issue-5544-a.stderr rename to src/test/ui/parser/issues/issue-5544-a.stderr diff --git a/src/test/ui/parser/issue-5544-b.rs b/src/test/ui/parser/issues/issue-5544-b.rs similarity index 100% rename from src/test/ui/parser/issue-5544-b.rs rename to src/test/ui/parser/issues/issue-5544-b.rs diff --git a/src/test/ui/parser/issue-5544-b.stderr b/src/test/ui/parser/issues/issue-5544-b.stderr similarity index 100% rename from src/test/ui/parser/issue-5544-b.stderr rename to src/test/ui/parser/issues/issue-5544-b.stderr diff --git a/src/test/ui/issues/issue-56031.rs b/src/test/ui/parser/issues/issue-56031.rs similarity index 100% rename from src/test/ui/issues/issue-56031.rs rename to src/test/ui/parser/issues/issue-56031.rs diff --git a/src/test/ui/issues/issue-56031.stderr b/src/test/ui/parser/issues/issue-56031.stderr similarity index 100% rename from src/test/ui/issues/issue-56031.stderr rename to src/test/ui/parser/issues/issue-56031.stderr diff --git a/src/test/ui/parser/issue-57198.rs b/src/test/ui/parser/issues/issue-57198.rs similarity index 100% rename from src/test/ui/parser/issue-57198.rs rename to src/test/ui/parser/issues/issue-57198.rs diff --git a/src/test/ui/parser/issue-57198.stderr b/src/test/ui/parser/issues/issue-57198.stderr similarity index 100% rename from src/test/ui/parser/issue-57198.stderr rename to src/test/ui/parser/issues/issue-57198.stderr diff --git a/src/test/ui/parser/issue-57684.fixed b/src/test/ui/parser/issues/issue-57684.fixed similarity index 100% rename from src/test/ui/parser/issue-57684.fixed rename to src/test/ui/parser/issues/issue-57684.fixed diff --git a/src/test/ui/parser/issue-57684.rs b/src/test/ui/parser/issues/issue-57684.rs similarity index 100% rename from src/test/ui/parser/issue-57684.rs rename to src/test/ui/parser/issues/issue-57684.rs diff --git a/src/test/ui/parser/issue-57684.stderr b/src/test/ui/parser/issues/issue-57684.stderr similarity index 100% rename from src/test/ui/parser/issue-57684.stderr rename to src/test/ui/parser/issues/issue-57684.stderr diff --git a/src/test/ui/parser/issue-57819.fixed b/src/test/ui/parser/issues/issue-57819.fixed similarity index 100% rename from src/test/ui/parser/issue-57819.fixed rename to src/test/ui/parser/issues/issue-57819.fixed diff --git a/src/test/ui/parser/issue-57819.rs b/src/test/ui/parser/issues/issue-57819.rs similarity index 100% rename from src/test/ui/parser/issue-57819.rs rename to src/test/ui/parser/issues/issue-57819.rs diff --git a/src/test/ui/parser/issue-57819.stderr b/src/test/ui/parser/issues/issue-57819.stderr similarity index 100% rename from src/test/ui/parser/issue-57819.stderr rename to src/test/ui/parser/issues/issue-57819.stderr diff --git a/src/test/ui/parser/issue-5806.rs b/src/test/ui/parser/issues/issue-5806.rs similarity index 100% rename from src/test/ui/parser/issue-5806.rs rename to src/test/ui/parser/issues/issue-5806.rs diff --git a/src/test/ui/parser/issue-5806.stderr b/src/test/ui/parser/issues/issue-5806.stderr similarity index 100% rename from src/test/ui/parser/issue-5806.stderr rename to src/test/ui/parser/issues/issue-5806.stderr diff --git a/src/test/ui/parser/issue-58094-missing-right-square-bracket.rs b/src/test/ui/parser/issues/issue-58094-missing-right-square-bracket.rs similarity index 100% rename from src/test/ui/parser/issue-58094-missing-right-square-bracket.rs rename to src/test/ui/parser/issues/issue-58094-missing-right-square-bracket.rs diff --git a/src/test/ui/parser/issue-58094-missing-right-square-bracket.stderr b/src/test/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr similarity index 100% rename from src/test/ui/parser/issue-58094-missing-right-square-bracket.stderr rename to src/test/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr diff --git a/src/test/ui/parser/issue-58856-1.rs b/src/test/ui/parser/issues/issue-58856-1.rs similarity index 100% rename from src/test/ui/parser/issue-58856-1.rs rename to src/test/ui/parser/issues/issue-58856-1.rs diff --git a/src/test/ui/parser/issue-58856-1.stderr b/src/test/ui/parser/issues/issue-58856-1.stderr similarity index 100% rename from src/test/ui/parser/issue-58856-1.stderr rename to src/test/ui/parser/issues/issue-58856-1.stderr diff --git a/src/test/ui/parser/issue-58856-2.rs b/src/test/ui/parser/issues/issue-58856-2.rs similarity index 100% rename from src/test/ui/parser/issue-58856-2.rs rename to src/test/ui/parser/issues/issue-58856-2.rs diff --git a/src/test/ui/parser/issue-58856-2.stderr b/src/test/ui/parser/issues/issue-58856-2.stderr similarity index 100% rename from src/test/ui/parser/issue-58856-2.stderr rename to src/test/ui/parser/issues/issue-58856-2.stderr diff --git a/src/test/ui/parser/issue-59418.rs b/src/test/ui/parser/issues/issue-59418.rs similarity index 100% rename from src/test/ui/parser/issue-59418.rs rename to src/test/ui/parser/issues/issue-59418.rs diff --git a/src/test/ui/parser/issue-59418.stderr b/src/test/ui/parser/issues/issue-59418.stderr similarity index 100% rename from src/test/ui/parser/issue-59418.stderr rename to src/test/ui/parser/issues/issue-59418.stderr diff --git a/src/test/ui/parser/issue-60075.rs b/src/test/ui/parser/issues/issue-60075.rs similarity index 100% rename from src/test/ui/parser/issue-60075.rs rename to src/test/ui/parser/issues/issue-60075.rs diff --git a/src/test/ui/parser/issue-60075.stderr b/src/test/ui/parser/issues/issue-60075.stderr similarity index 100% rename from src/test/ui/parser/issue-60075.stderr rename to src/test/ui/parser/issues/issue-60075.stderr diff --git a/src/test/ui/parser/issue-62524.rs b/src/test/ui/parser/issues/issue-62524.rs similarity index 100% rename from src/test/ui/parser/issue-62524.rs rename to src/test/ui/parser/issues/issue-62524.rs diff --git a/src/test/ui/parser/issue-62524.stderr b/src/test/ui/parser/issues/issue-62524.stderr similarity index 100% rename from src/test/ui/parser/issue-62524.stderr rename to src/test/ui/parser/issues/issue-62524.stderr diff --git a/src/test/ui/parser/issue-62546.rs b/src/test/ui/parser/issues/issue-62546.rs similarity index 100% rename from src/test/ui/parser/issue-62546.rs rename to src/test/ui/parser/issues/issue-62546.rs diff --git a/src/test/ui/parser/issue-62546.stderr b/src/test/ui/parser/issues/issue-62546.stderr similarity index 100% rename from src/test/ui/parser/issue-62546.stderr rename to src/test/ui/parser/issues/issue-62546.stderr diff --git a/src/test/ui/parser/issue-62554.rs b/src/test/ui/parser/issues/issue-62554.rs similarity index 100% rename from src/test/ui/parser/issue-62554.rs rename to src/test/ui/parser/issues/issue-62554.rs diff --git a/src/test/ui/parser/issue-62554.stderr b/src/test/ui/parser/issues/issue-62554.stderr similarity index 100% rename from src/test/ui/parser/issue-62554.stderr rename to src/test/ui/parser/issues/issue-62554.stderr diff --git a/src/test/ui/parser/issue-62660.rs b/src/test/ui/parser/issues/issue-62660.rs similarity index 100% rename from src/test/ui/parser/issue-62660.rs rename to src/test/ui/parser/issues/issue-62660.rs diff --git a/src/test/ui/parser/issue-62660.stderr b/src/test/ui/parser/issues/issue-62660.stderr similarity index 100% rename from src/test/ui/parser/issue-62660.stderr rename to src/test/ui/parser/issues/issue-62660.stderr diff --git a/src/test/ui/parser/issue-62881.rs b/src/test/ui/parser/issues/issue-62881.rs similarity index 100% rename from src/test/ui/parser/issue-62881.rs rename to src/test/ui/parser/issues/issue-62881.rs diff --git a/src/test/ui/parser/issue-62881.stderr b/src/test/ui/parser/issues/issue-62881.stderr similarity index 100% rename from src/test/ui/parser/issue-62881.stderr rename to src/test/ui/parser/issues/issue-62881.stderr diff --git a/src/test/ui/parser/issue-62894.rs b/src/test/ui/parser/issues/issue-62894.rs similarity index 100% rename from src/test/ui/parser/issue-62894.rs rename to src/test/ui/parser/issues/issue-62894.rs diff --git a/src/test/ui/parser/issue-62894.stderr b/src/test/ui/parser/issues/issue-62894.stderr similarity index 100% rename from src/test/ui/parser/issue-62894.stderr rename to src/test/ui/parser/issues/issue-62894.stderr diff --git a/src/test/ui/parser/issue-62895.rs b/src/test/ui/parser/issues/issue-62895.rs similarity index 100% rename from src/test/ui/parser/issue-62895.rs rename to src/test/ui/parser/issues/issue-62895.rs diff --git a/src/test/ui/parser/issue-62895.stderr b/src/test/ui/parser/issues/issue-62895.stderr similarity index 100% rename from src/test/ui/parser/issue-62895.stderr rename to src/test/ui/parser/issues/issue-62895.stderr diff --git a/src/test/ui/parser/issue-62913.rs b/src/test/ui/parser/issues/issue-62913.rs similarity index 100% rename from src/test/ui/parser/issue-62913.rs rename to src/test/ui/parser/issues/issue-62913.rs diff --git a/src/test/ui/parser/issue-62913.stderr b/src/test/ui/parser/issues/issue-62913.stderr similarity index 100% rename from src/test/ui/parser/issue-62913.stderr rename to src/test/ui/parser/issues/issue-62913.stderr diff --git a/src/test/ui/parser/issue-62973.rs b/src/test/ui/parser/issues/issue-62973.rs similarity index 100% rename from src/test/ui/parser/issue-62973.rs rename to src/test/ui/parser/issues/issue-62973.rs diff --git a/src/test/ui/parser/issue-62973.stderr b/src/test/ui/parser/issues/issue-62973.stderr similarity index 100% rename from src/test/ui/parser/issue-62973.stderr rename to src/test/ui/parser/issues/issue-62973.stderr diff --git a/src/test/ui/parser/issue-63115-range-pat-interpolated.rs b/src/test/ui/parser/issues/issue-63115-range-pat-interpolated.rs similarity index 100% rename from src/test/ui/parser/issue-63115-range-pat-interpolated.rs rename to src/test/ui/parser/issues/issue-63115-range-pat-interpolated.rs diff --git a/src/test/ui/parser/issue-63116.rs b/src/test/ui/parser/issues/issue-63116.rs similarity index 100% rename from src/test/ui/parser/issue-63116.rs rename to src/test/ui/parser/issues/issue-63116.rs diff --git a/src/test/ui/parser/issue-63116.stderr b/src/test/ui/parser/issues/issue-63116.stderr similarity index 100% rename from src/test/ui/parser/issue-63116.stderr rename to src/test/ui/parser/issues/issue-63116.stderr diff --git a/src/test/ui/parser/issue-63135.rs b/src/test/ui/parser/issues/issue-63135.rs similarity index 100% rename from src/test/ui/parser/issue-63135.rs rename to src/test/ui/parser/issues/issue-63135.rs diff --git a/src/test/ui/parser/issue-63135.stderr b/src/test/ui/parser/issues/issue-63135.stderr similarity index 100% rename from src/test/ui/parser/issue-63135.stderr rename to src/test/ui/parser/issues/issue-63135.stderr diff --git a/src/test/ui/parser/issue-64732.rs b/src/test/ui/parser/issues/issue-64732.rs similarity index 100% rename from src/test/ui/parser/issue-64732.rs rename to src/test/ui/parser/issues/issue-64732.rs diff --git a/src/test/ui/parser/issue-64732.stderr b/src/test/ui/parser/issues/issue-64732.stderr similarity index 100% rename from src/test/ui/parser/issue-64732.stderr rename to src/test/ui/parser/issues/issue-64732.stderr diff --git a/src/test/ui/parser/issue-65041-empty-vis-matcher-in-enum.rs b/src/test/ui/parser/issues/issue-65041-empty-vis-matcher-in-enum.rs similarity index 100% rename from src/test/ui/parser/issue-65041-empty-vis-matcher-in-enum.rs rename to src/test/ui/parser/issues/issue-65041-empty-vis-matcher-in-enum.rs diff --git a/src/test/ui/parser/issue-65041-empty-vis-matcher-in-trait.rs b/src/test/ui/parser/issues/issue-65041-empty-vis-matcher-in-trait.rs similarity index 100% rename from src/test/ui/parser/issue-65041-empty-vis-matcher-in-trait.rs rename to src/test/ui/parser/issues/issue-65041-empty-vis-matcher-in-trait.rs diff --git a/src/test/ui/parser/issue-65122-mac-invoc-in-mut-patterns.rs b/src/test/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.rs similarity index 100% rename from src/test/ui/parser/issue-65122-mac-invoc-in-mut-patterns.rs rename to src/test/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.rs diff --git a/src/test/ui/parser/issue-65122-mac-invoc-in-mut-patterns.stderr b/src/test/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.stderr similarity index 100% rename from src/test/ui/parser/issue-65122-mac-invoc-in-mut-patterns.stderr rename to src/test/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.stderr diff --git a/src/test/ui/parser/issue-65257-invalid-var-decl-recovery.rs b/src/test/ui/parser/issues/issue-65257-invalid-var-decl-recovery.rs similarity index 100% rename from src/test/ui/parser/issue-65257-invalid-var-decl-recovery.rs rename to src/test/ui/parser/issues/issue-65257-invalid-var-decl-recovery.rs diff --git a/src/test/ui/parser/issue-65257-invalid-var-decl-recovery.stderr b/src/test/ui/parser/issues/issue-65257-invalid-var-decl-recovery.stderr similarity index 100% rename from src/test/ui/parser/issue-65257-invalid-var-decl-recovery.stderr rename to src/test/ui/parser/issues/issue-65257-invalid-var-decl-recovery.stderr diff --git a/src/test/ui/parser/issue-65846-rollback-gating-failing-matcher.rs b/src/test/ui/parser/issues/issue-65846-rollback-gating-failing-matcher.rs similarity index 100% rename from src/test/ui/parser/issue-65846-rollback-gating-failing-matcher.rs rename to src/test/ui/parser/issues/issue-65846-rollback-gating-failing-matcher.rs diff --git a/src/test/ui/parser/issue-6610.rs b/src/test/ui/parser/issues/issue-6610.rs similarity index 100% rename from src/test/ui/parser/issue-6610.rs rename to src/test/ui/parser/issues/issue-6610.rs diff --git a/src/test/ui/parser/issue-6610.stderr b/src/test/ui/parser/issues/issue-6610.stderr similarity index 100% rename from src/test/ui/parser/issue-6610.stderr rename to src/test/ui/parser/issues/issue-6610.stderr diff --git a/src/test/ui/parser/issue-66357-unexpected-unreachable.rs b/src/test/ui/parser/issues/issue-66357-unexpected-unreachable.rs similarity index 100% rename from src/test/ui/parser/issue-66357-unexpected-unreachable.rs rename to src/test/ui/parser/issues/issue-66357-unexpected-unreachable.rs diff --git a/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr b/src/test/ui/parser/issues/issue-66357-unexpected-unreachable.stderr similarity index 100% rename from src/test/ui/parser/issue-66357-unexpected-unreachable.stderr rename to src/test/ui/parser/issues/issue-66357-unexpected-unreachable.stderr diff --git a/src/test/ui/parser/issue-66473.rs b/src/test/ui/parser/issues/issue-66473.rs similarity index 100% rename from src/test/ui/parser/issue-66473.rs rename to src/test/ui/parser/issues/issue-66473.rs diff --git a/src/test/ui/parser/issue-66473.stderr b/src/test/ui/parser/issues/issue-66473.stderr similarity index 100% rename from src/test/ui/parser/issue-66473.stderr rename to src/test/ui/parser/issues/issue-66473.stderr diff --git a/src/test/ui/parser/issue-67146-negative-outlives-bound-syntactic-fail.fixed b/src/test/ui/parser/issues/issue-67146-negative-outlives-bound-syntactic-fail.fixed similarity index 100% rename from src/test/ui/parser/issue-67146-negative-outlives-bound-syntactic-fail.fixed rename to src/test/ui/parser/issues/issue-67146-negative-outlives-bound-syntactic-fail.fixed diff --git a/src/test/ui/parser/issue-67146-negative-outlives-bound-syntactic-fail.rs b/src/test/ui/parser/issues/issue-67146-negative-outlives-bound-syntactic-fail.rs similarity index 100% rename from src/test/ui/parser/issue-67146-negative-outlives-bound-syntactic-fail.rs rename to src/test/ui/parser/issues/issue-67146-negative-outlives-bound-syntactic-fail.rs diff --git a/src/test/ui/parser/issue-67146-negative-outlives-bound-syntactic-fail.stderr b/src/test/ui/parser/issues/issue-67146-negative-outlives-bound-syntactic-fail.stderr similarity index 100% rename from src/test/ui/parser/issue-67146-negative-outlives-bound-syntactic-fail.stderr rename to src/test/ui/parser/issues/issue-67146-negative-outlives-bound-syntactic-fail.stderr diff --git a/src/test/ui/parser/issue-67377-invalid-syntax-in-enum-discriminant.rs b/src/test/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.rs similarity index 100% rename from src/test/ui/parser/issue-67377-invalid-syntax-in-enum-discriminant.rs rename to src/test/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.rs diff --git a/src/test/ui/parser/issue-67377-invalid-syntax-in-enum-discriminant.stderr b/src/test/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr similarity index 100% rename from src/test/ui/parser/issue-67377-invalid-syntax-in-enum-discriminant.stderr rename to src/test/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr diff --git a/src/test/ui/parser/issue-68000-unicode-ident-after-missing-comma.rs b/src/test/ui/parser/issues/issue-68000-unicode-ident-after-missing-comma.rs similarity index 100% rename from src/test/ui/parser/issue-68000-unicode-ident-after-missing-comma.rs rename to src/test/ui/parser/issues/issue-68000-unicode-ident-after-missing-comma.rs diff --git a/src/test/ui/parser/issue-68000-unicode-ident-after-missing-comma.stderr b/src/test/ui/parser/issues/issue-68000-unicode-ident-after-missing-comma.stderr similarity index 100% rename from src/test/ui/parser/issue-68000-unicode-ident-after-missing-comma.stderr rename to src/test/ui/parser/issues/issue-68000-unicode-ident-after-missing-comma.stderr diff --git a/src/test/ui/parser/issue-68629.rs b/src/test/ui/parser/issues/issue-68629.rs similarity index 100% rename from src/test/ui/parser/issue-68629.rs rename to src/test/ui/parser/issues/issue-68629.rs diff --git a/src/test/ui/parser/issue-68629.stderr b/src/test/ui/parser/issues/issue-68629.stderr similarity index 100% rename from src/test/ui/parser/issue-68629.stderr rename to src/test/ui/parser/issues/issue-68629.stderr diff --git a/src/test/ui/parser/issue-68730.rs b/src/test/ui/parser/issues/issue-68730.rs similarity index 100% rename from src/test/ui/parser/issue-68730.rs rename to src/test/ui/parser/issues/issue-68730.rs diff --git a/src/test/ui/parser/issue-68730.stderr b/src/test/ui/parser/issues/issue-68730.stderr similarity index 100% rename from src/test/ui/parser/issue-68730.stderr rename to src/test/ui/parser/issues/issue-68730.stderr diff --git a/src/test/ui/parser/issue-68788-in-trait-item-propagation.rs b/src/test/ui/parser/issues/issue-68788-in-trait-item-propagation.rs similarity index 100% rename from src/test/ui/parser/issue-68788-in-trait-item-propagation.rs rename to src/test/ui/parser/issues/issue-68788-in-trait-item-propagation.rs diff --git a/src/test/ui/parser/issue-68890-2.rs b/src/test/ui/parser/issues/issue-68890-2.rs similarity index 100% rename from src/test/ui/parser/issue-68890-2.rs rename to src/test/ui/parser/issues/issue-68890-2.rs diff --git a/src/test/ui/parser/issue-68890-2.stderr b/src/test/ui/parser/issues/issue-68890-2.stderr similarity index 100% rename from src/test/ui/parser/issue-68890-2.stderr rename to src/test/ui/parser/issues/issue-68890-2.stderr diff --git a/src/test/ui/parser/issue-68890.rs b/src/test/ui/parser/issues/issue-68890.rs similarity index 100% rename from src/test/ui/parser/issue-68890.rs rename to src/test/ui/parser/issues/issue-68890.rs diff --git a/src/test/ui/parser/issue-68890.stderr b/src/test/ui/parser/issues/issue-68890.stderr similarity index 100% rename from src/test/ui/parser/issue-68890.stderr rename to src/test/ui/parser/issues/issue-68890.stderr diff --git a/src/test/ui/parser/issue-70050-ntliteral-accepts-negated-lit.rs b/src/test/ui/parser/issues/issue-70050-ntliteral-accepts-negated-lit.rs similarity index 100% rename from src/test/ui/parser/issue-70050-ntliteral-accepts-negated-lit.rs rename to src/test/ui/parser/issues/issue-70050-ntliteral-accepts-negated-lit.rs diff --git a/src/test/ui/parser/issue-70388-recover-dotdotdot-rest-pat.rs b/src/test/ui/parser/issues/issue-70388-recover-dotdotdot-rest-pat.rs similarity index 100% rename from src/test/ui/parser/issue-70388-recover-dotdotdot-rest-pat.rs rename to src/test/ui/parser/issues/issue-70388-recover-dotdotdot-rest-pat.rs diff --git a/src/test/ui/parser/issue-70388-recover-dotdotdot-rest-pat.stderr b/src/test/ui/parser/issues/issue-70388-recover-dotdotdot-rest-pat.stderr similarity index 100% rename from src/test/ui/parser/issue-70388-recover-dotdotdot-rest-pat.stderr rename to src/test/ui/parser/issues/issue-70388-recover-dotdotdot-rest-pat.stderr diff --git a/src/test/ui/parser/issue-70388-without-witness.fixed b/src/test/ui/parser/issues/issue-70388-without-witness.fixed similarity index 100% rename from src/test/ui/parser/issue-70388-without-witness.fixed rename to src/test/ui/parser/issues/issue-70388-without-witness.fixed diff --git a/src/test/ui/parser/issue-70388-without-witness.rs b/src/test/ui/parser/issues/issue-70388-without-witness.rs similarity index 100% rename from src/test/ui/parser/issue-70388-without-witness.rs rename to src/test/ui/parser/issues/issue-70388-without-witness.rs diff --git a/src/test/ui/parser/issue-70388-without-witness.stderr b/src/test/ui/parser/issues/issue-70388-without-witness.stderr similarity index 100% rename from src/test/ui/parser/issue-70388-without-witness.stderr rename to src/test/ui/parser/issues/issue-70388-without-witness.stderr diff --git a/src/test/ui/parser/issue-70549-resolve-after-recovered-self-ctor.rs b/src/test/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.rs similarity index 100% rename from src/test/ui/parser/issue-70549-resolve-after-recovered-self-ctor.rs rename to src/test/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.rs diff --git a/src/test/ui/parser/issue-70549-resolve-after-recovered-self-ctor.stderr b/src/test/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.stderr similarity index 100% rename from src/test/ui/parser/issue-70549-resolve-after-recovered-self-ctor.stderr rename to src/test/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.stderr diff --git a/src/test/ui/parser/issue-70552-ascription-in-parens-after-call.rs b/src/test/ui/parser/issues/issue-70552-ascription-in-parens-after-call.rs similarity index 100% rename from src/test/ui/parser/issue-70552-ascription-in-parens-after-call.rs rename to src/test/ui/parser/issues/issue-70552-ascription-in-parens-after-call.rs diff --git a/src/test/ui/parser/issue-70552-ascription-in-parens-after-call.stderr b/src/test/ui/parser/issues/issue-70552-ascription-in-parens-after-call.stderr similarity index 100% rename from src/test/ui/parser/issue-70552-ascription-in-parens-after-call.stderr rename to src/test/ui/parser/issues/issue-70552-ascription-in-parens-after-call.stderr diff --git a/src/test/ui/parser/issue-70583-block-is-empty-1.rs b/src/test/ui/parser/issues/issue-70583-block-is-empty-1.rs similarity index 100% rename from src/test/ui/parser/issue-70583-block-is-empty-1.rs rename to src/test/ui/parser/issues/issue-70583-block-is-empty-1.rs diff --git a/src/test/ui/parser/issue-70583-block-is-empty-1.stderr b/src/test/ui/parser/issues/issue-70583-block-is-empty-1.stderr similarity index 100% rename from src/test/ui/parser/issue-70583-block-is-empty-1.stderr rename to src/test/ui/parser/issues/issue-70583-block-is-empty-1.stderr diff --git a/src/test/ui/parser/issue-70583-block-is-empty-2.rs b/src/test/ui/parser/issues/issue-70583-block-is-empty-2.rs similarity index 100% rename from src/test/ui/parser/issue-70583-block-is-empty-2.rs rename to src/test/ui/parser/issues/issue-70583-block-is-empty-2.rs diff --git a/src/test/ui/parser/issue-70583-block-is-empty-2.stderr b/src/test/ui/parser/issues/issue-70583-block-is-empty-2.stderr similarity index 100% rename from src/test/ui/parser/issue-70583-block-is-empty-2.stderr rename to src/test/ui/parser/issues/issue-70583-block-is-empty-2.stderr diff --git a/src/test/ui/parser/issue-7222.rs b/src/test/ui/parser/issues/issue-7222.rs similarity index 100% rename from src/test/ui/parser/issue-7222.rs rename to src/test/ui/parser/issues/issue-7222.rs diff --git a/src/test/ui/parser/issue-72253.rs b/src/test/ui/parser/issues/issue-72253.rs similarity index 100% rename from src/test/ui/parser/issue-72253.rs rename to src/test/ui/parser/issues/issue-72253.rs diff --git a/src/test/ui/parser/issue-72253.stderr b/src/test/ui/parser/issues/issue-72253.stderr similarity index 100% rename from src/test/ui/parser/issue-72253.stderr rename to src/test/ui/parser/issues/issue-72253.stderr diff --git a/src/test/ui/parser/issue-72373.rs b/src/test/ui/parser/issues/issue-72373.rs similarity index 100% rename from src/test/ui/parser/issue-72373.rs rename to src/test/ui/parser/issues/issue-72373.rs diff --git a/src/test/ui/parser/issue-72373.stderr b/src/test/ui/parser/issues/issue-72373.stderr similarity index 100% rename from src/test/ui/parser/issue-72373.stderr rename to src/test/ui/parser/issues/issue-72373.stderr diff --git a/src/test/ui/parser/issue-73568-lifetime-after-mut.rs b/src/test/ui/parser/issues/issue-73568-lifetime-after-mut.rs similarity index 100% rename from src/test/ui/parser/issue-73568-lifetime-after-mut.rs rename to src/test/ui/parser/issues/issue-73568-lifetime-after-mut.rs diff --git a/src/test/ui/parser/issue-73568-lifetime-after-mut.stderr b/src/test/ui/parser/issues/issue-73568-lifetime-after-mut.stderr similarity index 100% rename from src/test/ui/parser/issue-73568-lifetime-after-mut.stderr rename to src/test/ui/parser/issues/issue-73568-lifetime-after-mut.stderr diff --git a/src/test/ui/parser/issue-75599.rs b/src/test/ui/parser/issues/issue-75599.rs similarity index 100% rename from src/test/ui/parser/issue-75599.rs rename to src/test/ui/parser/issues/issue-75599.rs diff --git a/src/test/ui/parser/issue-76437-async.rs b/src/test/ui/parser/issues/issue-76437-async.rs similarity index 100% rename from src/test/ui/parser/issue-76437-async.rs rename to src/test/ui/parser/issues/issue-76437-async.rs diff --git a/src/test/ui/parser/issue-76437-async.stderr b/src/test/ui/parser/issues/issue-76437-async.stderr similarity index 100% rename from src/test/ui/parser/issue-76437-async.stderr rename to src/test/ui/parser/issues/issue-76437-async.stderr diff --git a/src/test/ui/parser/issue-76437-const-async-unsafe.rs b/src/test/ui/parser/issues/issue-76437-const-async-unsafe.rs similarity index 100% rename from src/test/ui/parser/issue-76437-const-async-unsafe.rs rename to src/test/ui/parser/issues/issue-76437-const-async-unsafe.rs diff --git a/src/test/ui/parser/issue-76437-const-async-unsafe.stderr b/src/test/ui/parser/issues/issue-76437-const-async-unsafe.stderr similarity index 100% rename from src/test/ui/parser/issue-76437-const-async-unsafe.stderr rename to src/test/ui/parser/issues/issue-76437-const-async-unsafe.stderr diff --git a/src/test/ui/parser/issue-76437-const-async.rs b/src/test/ui/parser/issues/issue-76437-const-async.rs similarity index 100% rename from src/test/ui/parser/issue-76437-const-async.rs rename to src/test/ui/parser/issues/issue-76437-const-async.rs diff --git a/src/test/ui/parser/issue-76437-const-async.stderr b/src/test/ui/parser/issues/issue-76437-const-async.stderr similarity index 100% rename from src/test/ui/parser/issue-76437-const-async.stderr rename to src/test/ui/parser/issues/issue-76437-const-async.stderr diff --git a/src/test/ui/parser/issue-76437-const.rs b/src/test/ui/parser/issues/issue-76437-const.rs similarity index 100% rename from src/test/ui/parser/issue-76437-const.rs rename to src/test/ui/parser/issues/issue-76437-const.rs diff --git a/src/test/ui/parser/issue-76437-const.stderr b/src/test/ui/parser/issues/issue-76437-const.stderr similarity index 100% rename from src/test/ui/parser/issue-76437-const.stderr rename to src/test/ui/parser/issues/issue-76437-const.stderr diff --git a/src/test/ui/parser/issue-76437-pub-crate-unsafe.rs b/src/test/ui/parser/issues/issue-76437-pub-crate-unsafe.rs similarity index 100% rename from src/test/ui/parser/issue-76437-pub-crate-unsafe.rs rename to src/test/ui/parser/issues/issue-76437-pub-crate-unsafe.rs diff --git a/src/test/ui/parser/issue-76437-pub-crate-unsafe.stderr b/src/test/ui/parser/issues/issue-76437-pub-crate-unsafe.stderr similarity index 100% rename from src/test/ui/parser/issue-76437-pub-crate-unsafe.stderr rename to src/test/ui/parser/issues/issue-76437-pub-crate-unsafe.stderr diff --git a/src/test/ui/parser/issue-76437-unsafe.rs b/src/test/ui/parser/issues/issue-76437-unsafe.rs similarity index 100% rename from src/test/ui/parser/issue-76437-unsafe.rs rename to src/test/ui/parser/issues/issue-76437-unsafe.rs diff --git a/src/test/ui/parser/issue-76437-unsafe.stderr b/src/test/ui/parser/issues/issue-76437-unsafe.stderr similarity index 100% rename from src/test/ui/parser/issue-76437-unsafe.stderr rename to src/test/ui/parser/issues/issue-76437-unsafe.stderr diff --git a/src/test/ui/parser/issue-76597.fixed b/src/test/ui/parser/issues/issue-76597.fixed similarity index 100% rename from src/test/ui/parser/issue-76597.fixed rename to src/test/ui/parser/issues/issue-76597.fixed diff --git a/src/test/ui/parser/issue-76597.rs b/src/test/ui/parser/issues/issue-76597.rs similarity index 100% rename from src/test/ui/parser/issue-76597.rs rename to src/test/ui/parser/issues/issue-76597.rs diff --git a/src/test/ui/parser/issue-76597.stderr b/src/test/ui/parser/issues/issue-76597.stderr similarity index 100% rename from src/test/ui/parser/issue-76597.stderr rename to src/test/ui/parser/issues/issue-76597.stderr diff --git a/src/test/ui/parser/issue-7970b.rs b/src/test/ui/parser/issues/issue-7970b.rs similarity index 100% rename from src/test/ui/parser/issue-7970b.rs rename to src/test/ui/parser/issues/issue-7970b.rs diff --git a/src/test/ui/parser/issue-7970b.stderr b/src/test/ui/parser/issues/issue-7970b.stderr similarity index 100% rename from src/test/ui/parser/issue-7970b.stderr rename to src/test/ui/parser/issues/issue-7970b.stderr diff --git a/src/test/ui/parser/issue-81806.rs b/src/test/ui/parser/issues/issue-81806.rs similarity index 100% rename from src/test/ui/parser/issue-81806.rs rename to src/test/ui/parser/issues/issue-81806.rs diff --git a/src/test/ui/parser/issue-81806.stderr b/src/test/ui/parser/issues/issue-81806.stderr similarity index 100% rename from src/test/ui/parser/issue-81806.stderr rename to src/test/ui/parser/issues/issue-81806.stderr diff --git a/src/test/ui/issue-83639.rs b/src/test/ui/parser/issues/issue-83639.rs similarity index 100% rename from src/test/ui/issue-83639.rs rename to src/test/ui/parser/issues/issue-83639.rs diff --git a/src/test/ui/issue-83639.stderr b/src/test/ui/parser/issues/issue-83639.stderr similarity index 100% rename from src/test/ui/issue-83639.stderr rename to src/test/ui/parser/issues/issue-83639.stderr diff --git a/src/test/ui/parser/issue-84104.rs b/src/test/ui/parser/issues/issue-84104.rs similarity index 100% rename from src/test/ui/parser/issue-84104.rs rename to src/test/ui/parser/issues/issue-84104.rs diff --git a/src/test/ui/parser/issue-84104.stderr b/src/test/ui/parser/issues/issue-84104.stderr similarity index 100% rename from src/test/ui/parser/issue-84104.stderr rename to src/test/ui/parser/issues/issue-84104.stderr diff --git a/src/test/ui/parser/issue-84117.rs b/src/test/ui/parser/issues/issue-84117.rs similarity index 100% rename from src/test/ui/parser/issue-84117.rs rename to src/test/ui/parser/issues/issue-84117.rs diff --git a/src/test/ui/parser/issue-84117.stderr b/src/test/ui/parser/issues/issue-84117.stderr similarity index 100% rename from src/test/ui/parser/issue-84117.stderr rename to src/test/ui/parser/issues/issue-84117.stderr diff --git a/src/test/ui/parser/issue-84148-1.rs b/src/test/ui/parser/issues/issue-84148-1.rs similarity index 100% rename from src/test/ui/parser/issue-84148-1.rs rename to src/test/ui/parser/issues/issue-84148-1.rs diff --git a/src/test/ui/parser/issue-84148-1.stderr b/src/test/ui/parser/issues/issue-84148-1.stderr similarity index 100% rename from src/test/ui/parser/issue-84148-1.stderr rename to src/test/ui/parser/issues/issue-84148-1.stderr diff --git a/src/test/ui/parser/issue-84148-2.rs b/src/test/ui/parser/issues/issue-84148-2.rs similarity index 100% rename from src/test/ui/parser/issue-84148-2.rs rename to src/test/ui/parser/issues/issue-84148-2.rs diff --git a/src/test/ui/parser/issue-84148-2.stderr b/src/test/ui/parser/issues/issue-84148-2.stderr similarity index 100% rename from src/test/ui/parser/issue-84148-2.stderr rename to src/test/ui/parser/issues/issue-84148-2.stderr diff --git a/src/test/ui/parser/issue-8537.rs b/src/test/ui/parser/issues/issue-8537.rs similarity index 100% rename from src/test/ui/parser/issue-8537.rs rename to src/test/ui/parser/issues/issue-8537.rs diff --git a/src/test/ui/parser/issue-8537.stderr b/src/test/ui/parser/issues/issue-8537.stderr similarity index 100% rename from src/test/ui/parser/issue-8537.stderr rename to src/test/ui/parser/issues/issue-8537.stderr diff --git a/src/test/ui/parser/issue-86895.rs b/src/test/ui/parser/issues/issue-86895.rs similarity index 100% rename from src/test/ui/parser/issue-86895.rs rename to src/test/ui/parser/issues/issue-86895.rs diff --git a/src/test/ui/parser/issue-86895.stderr b/src/test/ui/parser/issues/issue-86895.stderr similarity index 100% rename from src/test/ui/parser/issue-86895.stderr rename to src/test/ui/parser/issues/issue-86895.stderr diff --git a/src/test/ui/parser/issue-87086-colon-path-sep.rs b/src/test/ui/parser/issues/issue-87086-colon-path-sep.rs similarity index 100% rename from src/test/ui/parser/issue-87086-colon-path-sep.rs rename to src/test/ui/parser/issues/issue-87086-colon-path-sep.rs diff --git a/src/test/ui/parser/issue-87086-colon-path-sep.stderr b/src/test/ui/parser/issues/issue-87086-colon-path-sep.stderr similarity index 100% rename from src/test/ui/parser/issue-87086-colon-path-sep.stderr rename to src/test/ui/parser/issues/issue-87086-colon-path-sep.stderr diff --git a/src/test/ui/parser/issue-87197-missing-semicolon.fixed b/src/test/ui/parser/issues/issue-87197-missing-semicolon.fixed similarity index 100% rename from src/test/ui/parser/issue-87197-missing-semicolon.fixed rename to src/test/ui/parser/issues/issue-87197-missing-semicolon.fixed diff --git a/src/test/ui/parser/issue-87197-missing-semicolon.rs b/src/test/ui/parser/issues/issue-87197-missing-semicolon.rs similarity index 100% rename from src/test/ui/parser/issue-87197-missing-semicolon.rs rename to src/test/ui/parser/issues/issue-87197-missing-semicolon.rs diff --git a/src/test/ui/parser/issue-87197-missing-semicolon.stderr b/src/test/ui/parser/issues/issue-87197-missing-semicolon.stderr similarity index 100% rename from src/test/ui/parser/issue-87197-missing-semicolon.stderr rename to src/test/ui/parser/issues/issue-87197-missing-semicolon.stderr diff --git a/src/test/ui/parser/issue-87217-keyword-order/const-async-const.rs b/src/test/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs similarity index 100% rename from src/test/ui/parser/issue-87217-keyword-order/const-async-const.rs rename to src/test/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs diff --git a/src/test/ui/parser/issue-87217-keyword-order/const-async-const.stderr b/src/test/ui/parser/issues/issue-87217-keyword-order/const-async-const.stderr similarity index 100% rename from src/test/ui/parser/issue-87217-keyword-order/const-async-const.stderr rename to src/test/ui/parser/issues/issue-87217-keyword-order/const-async-const.stderr diff --git a/src/test/ui/parser/issue-87217-keyword-order/several-kw-jump.rs b/src/test/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.rs similarity index 100% rename from src/test/ui/parser/issue-87217-keyword-order/several-kw-jump.rs rename to src/test/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.rs diff --git a/src/test/ui/parser/issue-87217-keyword-order/several-kw-jump.stderr b/src/test/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.stderr similarity index 100% rename from src/test/ui/parser/issue-87217-keyword-order/several-kw-jump.stderr rename to src/test/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.stderr diff --git a/src/test/ui/parser/issue-87217-keyword-order/wrong-async.rs b/src/test/ui/parser/issues/issue-87217-keyword-order/wrong-async.rs similarity index 100% rename from src/test/ui/parser/issue-87217-keyword-order/wrong-async.rs rename to src/test/ui/parser/issues/issue-87217-keyword-order/wrong-async.rs diff --git a/src/test/ui/parser/issue-87217-keyword-order/wrong-async.stderr b/src/test/ui/parser/issues/issue-87217-keyword-order/wrong-async.stderr similarity index 100% rename from src/test/ui/parser/issue-87217-keyword-order/wrong-async.stderr rename to src/test/ui/parser/issues/issue-87217-keyword-order/wrong-async.stderr diff --git a/src/test/ui/parser/issue-87217-keyword-order/wrong-const.rs b/src/test/ui/parser/issues/issue-87217-keyword-order/wrong-const.rs similarity index 100% rename from src/test/ui/parser/issue-87217-keyword-order/wrong-const.rs rename to src/test/ui/parser/issues/issue-87217-keyword-order/wrong-const.rs diff --git a/src/test/ui/parser/issue-87217-keyword-order/wrong-const.stderr b/src/test/ui/parser/issues/issue-87217-keyword-order/wrong-const.stderr similarity index 100% rename from src/test/ui/parser/issue-87217-keyword-order/wrong-const.stderr rename to src/test/ui/parser/issues/issue-87217-keyword-order/wrong-const.stderr diff --git a/src/test/ui/parser/issue-87217-keyword-order/wrong-unsafe.rs b/src/test/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe.rs similarity index 100% rename from src/test/ui/parser/issue-87217-keyword-order/wrong-unsafe.rs rename to src/test/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe.rs diff --git a/src/test/ui/parser/issue-87217-keyword-order/wrong-unsafe.stderr b/src/test/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe.stderr similarity index 100% rename from src/test/ui/parser/issue-87217-keyword-order/wrong-unsafe.stderr rename to src/test/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe.stderr diff --git a/src/test/ui/parser/issue-87635.rs b/src/test/ui/parser/issues/issue-87635.rs similarity index 100% rename from src/test/ui/parser/issue-87635.rs rename to src/test/ui/parser/issues/issue-87635.rs diff --git a/src/test/ui/parser/issue-87635.stderr b/src/test/ui/parser/issues/issue-87635.stderr similarity index 100% rename from src/test/ui/parser/issue-87635.stderr rename to src/test/ui/parser/issues/issue-87635.stderr diff --git a/src/test/ui/parser/issue-87812-path.rs b/src/test/ui/parser/issues/issue-87812-path.rs similarity index 100% rename from src/test/ui/parser/issue-87812-path.rs rename to src/test/ui/parser/issues/issue-87812-path.rs diff --git a/src/test/ui/parser/issue-87812-path.stderr b/src/test/ui/parser/issues/issue-87812-path.stderr similarity index 100% rename from src/test/ui/parser/issue-87812-path.stderr rename to src/test/ui/parser/issues/issue-87812-path.stderr diff --git a/src/test/ui/parser/issue-87812.rs b/src/test/ui/parser/issues/issue-87812.rs similarity index 100% rename from src/test/ui/parser/issue-87812.rs rename to src/test/ui/parser/issues/issue-87812.rs diff --git a/src/test/ui/parser/issue-87812.stderr b/src/test/ui/parser/issues/issue-87812.stderr similarity index 100% rename from src/test/ui/parser/issue-87812.stderr rename to src/test/ui/parser/issues/issue-87812.stderr diff --git a/src/test/ui/parser/issue-88276-unary-plus.fixed b/src/test/ui/parser/issues/issue-88276-unary-plus.fixed similarity index 100% rename from src/test/ui/parser/issue-88276-unary-plus.fixed rename to src/test/ui/parser/issues/issue-88276-unary-plus.fixed diff --git a/src/test/ui/parser/issue-88276-unary-plus.rs b/src/test/ui/parser/issues/issue-88276-unary-plus.rs similarity index 100% rename from src/test/ui/parser/issue-88276-unary-plus.rs rename to src/test/ui/parser/issues/issue-88276-unary-plus.rs diff --git a/src/test/ui/parser/issue-88276-unary-plus.stderr b/src/test/ui/parser/issues/issue-88276-unary-plus.stderr similarity index 100% rename from src/test/ui/parser/issue-88276-unary-plus.stderr rename to src/test/ui/parser/issues/issue-88276-unary-plus.stderr diff --git a/src/test/ui/parser/issue-88583-union-as-ident.rs b/src/test/ui/parser/issues/issue-88583-union-as-ident.rs similarity index 100% rename from src/test/ui/parser/issue-88583-union-as-ident.rs rename to src/test/ui/parser/issues/issue-88583-union-as-ident.rs diff --git a/src/test/ui/parser/issue-88770.rs b/src/test/ui/parser/issues/issue-88770.rs similarity index 100% rename from src/test/ui/parser/issue-88770.rs rename to src/test/ui/parser/issues/issue-88770.rs diff --git a/src/test/ui/parser/issue-88770.stderr b/src/test/ui/parser/issues/issue-88770.stderr similarity index 100% rename from src/test/ui/parser/issue-88770.stderr rename to src/test/ui/parser/issues/issue-88770.stderr diff --git a/src/test/ui/parser/issue-88818.rs b/src/test/ui/parser/issues/issue-88818.rs similarity index 100% rename from src/test/ui/parser/issue-88818.rs rename to src/test/ui/parser/issues/issue-88818.rs diff --git a/src/test/ui/parser/issue-88818.stderr b/src/test/ui/parser/issues/issue-88818.stderr similarity index 100% rename from src/test/ui/parser/issue-88818.stderr rename to src/test/ui/parser/issues/issue-88818.stderr diff --git a/src/test/ui/parser/issue-89388.rs b/src/test/ui/parser/issues/issue-89388.rs similarity index 100% rename from src/test/ui/parser/issue-89388.rs rename to src/test/ui/parser/issues/issue-89388.rs diff --git a/src/test/ui/parser/issue-89388.stderr b/src/test/ui/parser/issues/issue-89388.stderr similarity index 100% rename from src/test/ui/parser/issue-89388.stderr rename to src/test/ui/parser/issues/issue-89388.stderr diff --git a/src/test/ui/parser/issue-89396.fixed b/src/test/ui/parser/issues/issue-89396.fixed similarity index 100% rename from src/test/ui/parser/issue-89396.fixed rename to src/test/ui/parser/issues/issue-89396.fixed diff --git a/src/test/ui/parser/issue-89396.rs b/src/test/ui/parser/issues/issue-89396.rs similarity index 100% rename from src/test/ui/parser/issue-89396.rs rename to src/test/ui/parser/issues/issue-89396.rs diff --git a/src/test/ui/parser/issue-89396.stderr b/src/test/ui/parser/issues/issue-89396.stderr similarity index 100% rename from src/test/ui/parser/issue-89396.stderr rename to src/test/ui/parser/issues/issue-89396.stderr diff --git a/src/test/ui/parser/issue-89574.rs b/src/test/ui/parser/issues/issue-89574.rs similarity index 100% rename from src/test/ui/parser/issue-89574.rs rename to src/test/ui/parser/issues/issue-89574.rs diff --git a/src/test/ui/parser/issue-89574.stderr b/src/test/ui/parser/issues/issue-89574.stderr similarity index 100% rename from src/test/ui/parser/issue-89574.stderr rename to src/test/ui/parser/issues/issue-89574.stderr diff --git a/src/test/ui/parser/issues/issue-89971-outer-attr-following-inner-attr-ice.rs b/src/test/ui/parser/issues/issue-89971-outer-attr-following-inner-attr-ice.rs new file mode 100644 index 0000000000..fe67d9822f --- /dev/null +++ b/src/test/ui/parser/issues/issue-89971-outer-attr-following-inner-attr-ice.rs @@ -0,0 +1,15 @@ +// aux-build:issue-89971-outer-attr-following-inner-attr-ice.rs + +#[macro_use] +extern crate issue_89971_outer_attr_following_inner_attr_ice; + +fn main() { + Mew(); + X {}; +} + +#![deny(missing_docs)] +//~^ ERROR an inner attribute is not permitted in this context +#[derive(ICE)] +#[deny(missing_docs)] +struct Mew(); diff --git a/src/test/ui/parser/issues/issue-89971-outer-attr-following-inner-attr-ice.stderr b/src/test/ui/parser/issues/issue-89971-outer-attr-following-inner-attr-ice.stderr new file mode 100644 index 0000000000..34a6ab00d7 --- /dev/null +++ b/src/test/ui/parser/issues/issue-89971-outer-attr-following-inner-attr-ice.stderr @@ -0,0 +1,18 @@ +error: an inner attribute is not permitted in this context + --> $DIR/issue-89971-outer-attr-following-inner-attr-ice.rs:11:1 + | +LL | #![deny(missing_docs)] + | ^^^^^^^^^^^^^^^^^^^^^^ +... +LL | struct Mew(); + | ------------- the inner attribute doesn't annotate this struct + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files +help: to annotate the struct, change the attribute from inner to outer style + | +LL - #![deny(missing_docs)] +LL + #[deny(missing_docs)] + | + +error: aborting due to previous error + diff --git a/src/test/ui/parser/issues/issue-90993.rs b/src/test/ui/parser/issues/issue-90993.rs new file mode 100644 index 0000000000..40e6fc7487 --- /dev/null +++ b/src/test/ui/parser/issues/issue-90993.rs @@ -0,0 +1,6 @@ +fn main() { + ...=. + //~^ ERROR: unexpected token: `...` + //~| ERROR: unexpected `=` after inclusive range + //~| ERROR: expected one of `-`, `;`, `}`, or path, found `.` +} diff --git a/src/test/ui/parser/issues/issue-90993.stderr b/src/test/ui/parser/issues/issue-90993.stderr new file mode 100644 index 0000000000..ab6bce410e --- /dev/null +++ b/src/test/ui/parser/issues/issue-90993.stderr @@ -0,0 +1,31 @@ +error: unexpected token: `...` + --> $DIR/issue-90993.rs:2:5 + | +LL | ...=. + | ^^^ + | +help: use `..` for an exclusive range + | +LL | ..=. + | ~~ +help: or `..=` for an inclusive range + | +LL | ..==. + | ~~~ + +error: unexpected `=` after inclusive range + --> $DIR/issue-90993.rs:2:5 + | +LL | ...=. + | ^^^^ help: use `..=` instead + | + = note: inclusive ranges end with a single equals sign (`..=`) + +error: expected one of `-`, `;`, `}`, or path, found `.` + --> $DIR/issue-90993.rs:2:9 + | +LL | ...=. + | ^ expected one of `-`, `;`, `}`, or path + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/obsolete-syntax-impl-for-dotdot.rs b/src/test/ui/parser/obsolete-syntax-impl-for-dotdot.rs similarity index 100% rename from src/test/ui/obsolete-syntax-impl-for-dotdot.rs rename to src/test/ui/parser/obsolete-syntax-impl-for-dotdot.rs diff --git a/src/test/ui/obsolete-syntax-impl-for-dotdot.stderr b/src/test/ui/parser/obsolete-syntax-impl-for-dotdot.stderr similarity index 100% rename from src/test/ui/obsolete-syntax-impl-for-dotdot.stderr rename to src/test/ui/parser/obsolete-syntax-impl-for-dotdot.stderr diff --git a/src/test/ui/operator-associativity.rs b/src/test/ui/parser/operator-associativity.rs similarity index 100% rename from src/test/ui/operator-associativity.rs rename to src/test/ui/parser/operator-associativity.rs diff --git a/src/test/ui/ranges-precedence.rs b/src/test/ui/parser/ranges-precedence.rs similarity index 100% rename from src/test/ui/ranges-precedence.rs rename to src/test/ui/parser/ranges-precedence.rs diff --git a/src/test/ui/parser/recover-for-loop-parens-around-head.rs b/src/test/ui/parser/recover-for-loop-parens-around-head.rs index 8080dbc332..053b428bd1 100644 --- a/src/test/ui/parser/recover-for-loop-parens-around-head.rs +++ b/src/test/ui/parser/recover-for-loop-parens-around-head.rs @@ -9,7 +9,7 @@ fn main() { for ( elem in vec ) { //~^ ERROR expected one of `)`, `,`, `@`, or `|`, found keyword `in` - //~| ERROR unexpected parenthesis surrounding `for` loop head + //~| ERROR unexpected parentheses surrounding `for` loop head const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types } } diff --git a/src/test/ui/parser/recover-for-loop-parens-around-head.stderr b/src/test/ui/parser/recover-for-loop-parens-around-head.stderr index 2199134832..fa55970dbd 100644 --- a/src/test/ui/parser/recover-for-loop-parens-around-head.stderr +++ b/src/test/ui/parser/recover-for-loop-parens-around-head.stderr @@ -4,13 +4,13 @@ error: expected one of `)`, `,`, `@`, or `|`, found keyword `in` LL | for ( elem in vec ) { | ^^ expected one of `)`, `,`, `@`, or `|` -error: unexpected parenthesis surrounding `for` loop head +error: unexpected parentheses surrounding `for` loop head --> $DIR/recover-for-loop-parens-around-head.rs:10:9 | LL | for ( elem in vec ) { | ^ ^ | -help: remove parenthesis in `for` loop +help: remove parentheses in `for` loop | LL - for ( elem in vec ) { LL + for elem in vec { diff --git a/src/test/ui/similar-tokens.rs b/src/test/ui/parser/similar-tokens.rs similarity index 100% rename from src/test/ui/similar-tokens.rs rename to src/test/ui/parser/similar-tokens.rs diff --git a/src/test/ui/similar-tokens.stderr b/src/test/ui/parser/similar-tokens.stderr similarity index 100% rename from src/test/ui/similar-tokens.stderr rename to src/test/ui/parser/similar-tokens.stderr diff --git a/src/test/ui/parser/struct-literal-in-for.stderr b/src/test/ui/parser/struct-literal-in-for.stderr index feabd8f581..4b191710c3 100644 --- a/src/test/ui/parser/struct-literal-in-for.stderr +++ b/src/test/ui/parser/struct-literal-in-for.stderr @@ -25,11 +25,6 @@ LL | | }.hi() { | = help: the trait `Iterator` is not implemented for `bool` = note: required because of the requirements on the impl of `IntoIterator` for `bool` -note: required by `into_iter` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/utf8_idents-rpass.rs b/src/test/ui/parser/utf8_idents-rpass.rs similarity index 100% rename from src/test/ui/utf8_idents-rpass.rs rename to src/test/ui/parser/utf8_idents-rpass.rs diff --git a/src/test/ui/ignore-all-the-things.rs b/src/test/ui/pattern/ignore-all-the-things.rs similarity index 100% rename from src/test/ui/ignore-all-the-things.rs rename to src/test/ui/pattern/ignore-all-the-things.rs diff --git a/src/test/ui/issues/issue-11577.rs b/src/test/ui/pattern/issue-11577.rs similarity index 100% rename from src/test/ui/issues/issue-11577.rs rename to src/test/ui/pattern/issue-11577.rs diff --git a/src/test/ui/issues/issue-15080.rs b/src/test/ui/pattern/issue-15080.rs similarity index 100% rename from src/test/ui/issues/issue-15080.rs rename to src/test/ui/pattern/issue-15080.rs diff --git a/src/test/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs b/src/test/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs index a3023ee906..ae28c14037 100644 --- a/src/test/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs +++ b/src/test/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs @@ -5,7 +5,7 @@ // the tuple struct pattern, has 0 fields, but requires 1 field. // // In emitting E0023, we try to see if this is a case of e.g., `Some(a, b, c)` but where -// the scrutinee was of type `Some((a, b, c))`, and suggest that parenthesis be added. +// the scrutinee was of type `Some((a, b, c))`, and suggest that parentheses be added. // // However, we did not account for the expected type being different than the tuple pattern type. // This caused an issue when the tuple pattern type (`P<T>`) was generic. diff --git a/src/test/ui/issues/issue-72574-2.rs b/src/test/ui/pattern/issue-72574-2.rs similarity index 100% rename from src/test/ui/issues/issue-72574-2.rs rename to src/test/ui/pattern/issue-72574-2.rs diff --git a/src/test/ui/issues/issue-72574-2.stderr b/src/test/ui/pattern/issue-72574-2.stderr similarity index 100% rename from src/test/ui/issues/issue-72574-2.stderr rename to src/test/ui/pattern/issue-72574-2.stderr diff --git a/src/test/ui/issues/issue-8351-1.rs b/src/test/ui/pattern/issue-8351-1.rs similarity index 100% rename from src/test/ui/issues/issue-8351-1.rs rename to src/test/ui/pattern/issue-8351-1.rs diff --git a/src/test/ui/issues/issue-8351-2.rs b/src/test/ui/pattern/issue-8351-2.rs similarity index 100% rename from src/test/ui/issues/issue-8351-2.rs rename to src/test/ui/pattern/issue-8351-2.rs diff --git a/src/test/ui/pattern/non-structural-match-types.rs b/src/test/ui/pattern/non-structural-match-types.rs new file mode 100644 index 0000000000..5c33154736 --- /dev/null +++ b/src/test/ui/pattern/non-structural-match-types.rs @@ -0,0 +1,14 @@ +// edition:2021 +#![allow(incomplete_features)] +#![allow(unreachable_code)] +#![feature(const_async_blocks)] +#![feature(inline_const_pat)] + +fn main() { + match loop {} { + const { || {} } => {}, //~ ERROR cannot be used in patterns + } + match loop {} { + const { async {} } => {}, //~ ERROR cannot be used in patterns + } +} diff --git a/src/test/ui/pattern/non-structural-match-types.stderr b/src/test/ui/pattern/non-structural-match-types.stderr new file mode 100644 index 0000000000..31168e29eb --- /dev/null +++ b/src/test/ui/pattern/non-structural-match-types.stderr @@ -0,0 +1,14 @@ +error: `[closure@$DIR/non-structural-match-types.rs:9:17: 9:22]` cannot be used in patterns + --> $DIR/non-structural-match-types.rs:9:9 + | +LL | const { || {} } => {}, + | ^^^^^^^^^^^^^^^ + +error: `impl Future<Output = [async output]>` cannot be used in patterns + --> $DIR/non-structural-match-types.rs:12:9 + | +LL | const { async {} } => {}, + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/pattern/pat-type-err-let-stmt.stderr b/src/test/ui/pattern/pat-type-err-let-stmt.stderr index 4b4fb08928..090bd67117 100644 --- a/src/test/ui/pattern/pat-type-err-let-stmt.stderr +++ b/src/test/ui/pattern/pat-type-err-let-stmt.stderr @@ -2,14 +2,16 @@ error[E0308]: mismatched types --> $DIR/pat-type-err-let-stmt.rs:6:29 | LL | let Ok(0): Option<u8> = 42u8; - | ---------- ^^^^ - | | | - | | expected enum `Option`, found `u8` - | | help: try using a variant of the expected enum: `Some(42u8)` + | ---------- ^^^^ expected enum `Option`, found `u8` + | | | expected due to this | = note: expected enum `Option<u8>` found type `u8` +help: try wrapping the expression in `Some` + | +LL | let Ok(0): Option<u8> = Some(42u8); + | +++++ + error[E0308]: mismatched types --> $DIR/pat-type-err-let-stmt.rs:6:9 diff --git a/src/test/ui/pattern/usefulness/issue-88747.rs b/src/test/ui/pattern/usefulness/issue-88747.rs new file mode 100644 index 0000000000..948c99f9ce --- /dev/null +++ b/src/test/ui/pattern/usefulness/issue-88747.rs @@ -0,0 +1,14 @@ +// check-pass: this used to be a stack overflow because of recursion in `usefulness.rs` + +macro_rules! long_tuple_arg { + ([$($t:tt)*]#$($h:tt)*) => { + long_tuple_arg!{[$($t)*$($t)*]$($h)*} + }; + ([$([$t:tt $y:tt])*]) => { + pub fn _f(($($t,)*): ($($y,)*)) {} + } +} + +long_tuple_arg!{[[_ u8]]########## ###} + +fn main() {} diff --git a/src/test/ui/auxiliary/impl_privacy_xc_2.rs b/src/test/ui/privacy/auxiliary/impl_privacy_xc_2.rs similarity index 100% rename from src/test/ui/auxiliary/impl_privacy_xc_2.rs rename to src/test/ui/privacy/auxiliary/impl_privacy_xc_2.rs diff --git a/src/test/ui/auxiliary/reachable-unnameable-items.rs b/src/test/ui/privacy/auxiliary/reachable-unnameable-items.rs similarity index 100% rename from src/test/ui/auxiliary/reachable-unnameable-items.rs rename to src/test/ui/privacy/auxiliary/reachable-unnameable-items.rs diff --git a/src/test/ui/privacy/crate-private-reexport.rs b/src/test/ui/privacy/crate-private-reexport.rs new file mode 100644 index 0000000000..fa4f88666d --- /dev/null +++ b/src/test/ui/privacy/crate-private-reexport.rs @@ -0,0 +1,66 @@ +fn f1() {} +enum E1 { V } +struct S1 { + #[rustfmt::skip] + bar: i32, +} +mod m1 { + pub use ::f1; //~ ERROR `f1` is only public within the crate, and cannot be re-exported outside + pub use ::S1; //~ ERROR `S1` is only public within the crate, and cannot be re-exported outside + pub use ::E1; //~ ERROR `E1` is only public within the crate, and cannot be re-exported outside + pub use ::E1::V; //~ ERROR `V` is only public within the crate, and cannot be re-exported outside +} + +pub(crate) fn f2() {} +pub(crate) enum E2 { + V +} +pub(crate) struct S2 { + #[rustfmt::skip] + bar: i32, +} +mod m2 { + pub use ::f2; //~ ERROR `f2` is only public within the crate, and cannot be re-exported outside + pub use ::S2; //~ ERROR `S2` is only public within the crate, and cannot be re-exported outside + pub use ::E2; //~ ERROR `E2` is only public within the crate, and cannot be re-exported outside + pub use ::E2::V; //~ ERROR `V` is only public within the crate, and cannot be re-exported outside +} + +mod m3 { + pub(crate) fn f3() {} + pub(crate) enum E3 { + V + } + pub(crate) struct S3 { + #[rustfmt::skip] + bar: i32, + } +} +pub use m3::f3; //~ ERROR `f3` is only public within the crate, and cannot be re-exported outside +pub use m3::S3; //~ ERROR `S3` is only public within the crate, and cannot be re-exported outside +pub use m3::E3; //~ ERROR `E3` is only public within the crate, and cannot be re-exported outside +pub use m3::E3::V; //~ ERROR `V` is only public within the crate, and cannot be re-exported outside + +pub(self) fn f4() {} +pub use ::f4 as f5; //~ ERROR `f4` is only public within the crate, and cannot be re-exported outside + +pub mod m10 { + pub mod m { + pub(super) fn f6() {} + pub(crate) fn f7() {} + pub(in crate::m10) fn f8() {} + } + pub use self::m::f6; //~ ERROR `f6` is private, and cannot be re-exported + pub use self::m::f7; //~ ERROR `f7` is only public within the crate, and cannot be re-exported outside + pub use self::m::f8; //~ ERROR `f8` is private, and cannot be re-exported +} +pub use m10::m::f6; //~ ERROR function `f6` is private +pub use m10::m::f7; //~ ERROR `f7` is only public within the crate, and cannot be re-exported outside +pub use m10::m::f8; //~ ERROR function `f8` is private + +pub mod m11 { + pub(self) fn f9() {} +} +pub use m11::f9; //~ ERROR function `f9` is private + +fn main() {} diff --git a/src/test/ui/privacy/crate-private-reexport.stderr b/src/test/ui/privacy/crate-private-reexport.stderr new file mode 100644 index 0000000000..66e11e8210 --- /dev/null +++ b/src/test/ui/privacy/crate-private-reexport.stderr @@ -0,0 +1,220 @@ +error[E0364]: `f1` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:8:13 + | +LL | pub use ::f1; + | ^^^^ + | +note: consider marking `f1` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:8:13 + | +LL | pub use ::f1; + | ^^^^ + +error[E0365]: `S1` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:9:13 + | +LL | pub use ::S1; + | ^^^^ re-export of crate public `S1` + | + = note: consider declaring type or module `S1` with `pub` + +error[E0365]: `E1` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:10:13 + | +LL | pub use ::E1; + | ^^^^ re-export of crate public `E1` + | + = note: consider declaring type or module `E1` with `pub` + +error[E0364]: `V` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:11:13 + | +LL | pub use ::E1::V; + | ^^^^^^^ + | +note: consider marking `V` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:11:13 + | +LL | pub use ::E1::V; + | ^^^^^^^ + +error[E0364]: `f2` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:23:13 + | +LL | pub use ::f2; + | ^^^^ + | +note: consider marking `f2` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:23:13 + | +LL | pub use ::f2; + | ^^^^ + +error[E0365]: `S2` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:24:13 + | +LL | pub use ::S2; + | ^^^^ re-export of crate public `S2` + | + = note: consider declaring type or module `S2` with `pub` + +error[E0365]: `E2` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:25:13 + | +LL | pub use ::E2; + | ^^^^ re-export of crate public `E2` + | + = note: consider declaring type or module `E2` with `pub` + +error[E0364]: `V` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:26:13 + | +LL | pub use ::E2::V; + | ^^^^^^^ + | +note: consider marking `V` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:26:13 + | +LL | pub use ::E2::V; + | ^^^^^^^ + +error[E0364]: `f3` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:39:9 + | +LL | pub use m3::f3; + | ^^^^^^ + | +note: consider marking `f3` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:39:9 + | +LL | pub use m3::f3; + | ^^^^^^ + +error[E0365]: `S3` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:40:9 + | +LL | pub use m3::S3; + | ^^^^^^ re-export of crate public `S3` + | + = note: consider declaring type or module `S3` with `pub` + +error[E0365]: `E3` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:41:9 + | +LL | pub use m3::E3; + | ^^^^^^ re-export of crate public `E3` + | + = note: consider declaring type or module `E3` with `pub` + +error[E0364]: `V` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:42:9 + | +LL | pub use m3::E3::V; + | ^^^^^^^^^ + | +note: consider marking `V` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:42:9 + | +LL | pub use m3::E3::V; + | ^^^^^^^^^ + +error[E0364]: `f4` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:45:9 + | +LL | pub use ::f4 as f5; + | ^^^^^^^^^^ + | +note: consider marking `f4` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:45:9 + | +LL | pub use ::f4 as f5; + | ^^^^^^^^^^ + +error[E0364]: `f6` is private, and cannot be re-exported + --> $DIR/crate-private-reexport.rs:53:13 + | +LL | pub use self::m::f6; + | ^^^^^^^^^^^ + | +note: consider marking `f6` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:53:13 + | +LL | pub use self::m::f6; + | ^^^^^^^^^^^ + +error[E0364]: `f7` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:54:13 + | +LL | pub use self::m::f7; + | ^^^^^^^^^^^ + | +note: consider marking `f7` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:54:13 + | +LL | pub use self::m::f7; + | ^^^^^^^^^^^ + +error[E0364]: `f8` is private, and cannot be re-exported + --> $DIR/crate-private-reexport.rs:55:13 + | +LL | pub use self::m::f8; + | ^^^^^^^^^^^ + | +note: consider marking `f8` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:55:13 + | +LL | pub use self::m::f8; + | ^^^^^^^^^^^ + +error[E0364]: `f7` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:58:9 + | +LL | pub use m10::m::f7; + | ^^^^^^^^^^ + | +note: consider marking `f7` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:58:9 + | +LL | pub use m10::m::f7; + | ^^^^^^^^^^ + +error[E0603]: function `f6` is private + --> $DIR/crate-private-reexport.rs:57:17 + | +LL | pub use m10::m::f6; + | ^^ private function + | +note: the function `f6` is defined here + --> $DIR/crate-private-reexport.rs:49:9 + | +LL | pub(super) fn f6() {} + | ^^^^^^^^^^^^^^^^^^ + +error[E0603]: function `f8` is private + --> $DIR/crate-private-reexport.rs:59:17 + | +LL | pub use m10::m::f8; + | ^^ private function + | +note: the function `f8` is defined here + --> $DIR/crate-private-reexport.rs:51:9 + | +LL | pub(in crate::m10) fn f8() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0603]: function `f9` is private + --> $DIR/crate-private-reexport.rs:64:14 + | +LL | pub use m11::f9; + | ^^ private function + | +note: the function `f9` is defined here + --> $DIR/crate-private-reexport.rs:62:5 + | +LL | pub(self) fn f9() {} + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 20 previous errors + +Some errors have detailed explanations: E0364, E0365, E0603. +For more information about an error, try `rustc --explain E0364`. diff --git a/src/test/ui/export-tag-variant.rs b/src/test/ui/privacy/export-tag-variant.rs similarity index 100% rename from src/test/ui/export-tag-variant.rs rename to src/test/ui/privacy/export-tag-variant.rs diff --git a/src/test/ui/export-tag-variant.stderr b/src/test/ui/privacy/export-tag-variant.stderr similarity index 100% rename from src/test/ui/export-tag-variant.stderr rename to src/test/ui/privacy/export-tag-variant.stderr diff --git a/src/test/ui/impl-privacy-xc-2.rs b/src/test/ui/privacy/impl-privacy-xc-2.rs similarity index 100% rename from src/test/ui/impl-privacy-xc-2.rs rename to src/test/ui/privacy/impl-privacy-xc-2.rs diff --git a/src/test/ui/privacy/privacy2.stderr b/src/test/ui/privacy/privacy2.stderr index 882f314655..c2a33ce1f5 100644 --- a/src/test/ui/privacy/privacy2.stderr +++ b/src/test/ui/privacy/privacy2.stderr @@ -23,13 +23,7 @@ LL | pub fn foo() {} error: requires `sized` lang_item -error: requires `sized` lang_item - -error: requires `sized` lang_item - -error: requires `sized` lang_item - -error: aborting due to 6 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0432, E0603. For more information about an error, try `rustc --explain E0432`. diff --git a/src/test/ui/privacy/privacy3.stderr b/src/test/ui/privacy/privacy3.stderr index 42ce456d96..22c1e48b07 100644 --- a/src/test/ui/privacy/privacy3.stderr +++ b/src/test/ui/privacy/privacy3.stderr @@ -6,12 +6,6 @@ LL | use bar::gpriv; error: requires `sized` lang_item -error: requires `sized` lang_item - -error: requires `sized` lang_item - -error: requires `sized` lang_item - -error: aborting due to 5 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/privacy/private-variant-reexport.rs b/src/test/ui/privacy/private-variant-reexport.rs index ce1b0d321c..6882844602 100644 --- a/src/test/ui/privacy/private-variant-reexport.rs +++ b/src/test/ui/privacy/private-variant-reexport.rs @@ -1,13 +1,13 @@ mod m1 { - pub use ::E::V; //~ ERROR `V` is private, and cannot be re-exported + pub use ::E::V; //~ ERROR `V` is only public within the crate, and cannot be re-exported outside } mod m2 { - pub use ::E::{V}; //~ ERROR `V` is private, and cannot be re-exported + pub use ::E::{V}; //~ ERROR `V` is only public within the crate, and cannot be re-exported outside } mod m3 { - pub use ::E::V::{self}; //~ ERROR `V` is private, and cannot be re-exported + pub use ::E::V::{self}; //~ ERROR `V` is only public within the crate, and cannot be re-exported outside } #[deny(unused_imports)] diff --git a/src/test/ui/privacy/private-variant-reexport.stderr b/src/test/ui/privacy/private-variant-reexport.stderr index 7a4c3234db..78771ee30d 100644 --- a/src/test/ui/privacy/private-variant-reexport.stderr +++ b/src/test/ui/privacy/private-variant-reexport.stderr @@ -1,4 +1,4 @@ -error[E0364]: `V` is private, and cannot be re-exported +error[E0364]: `V` is only public within the crate, and cannot be re-exported outside --> $DIR/private-variant-reexport.rs:2:13 | LL | pub use ::E::V; @@ -10,7 +10,7 @@ note: consider marking `V` as `pub` in the imported module LL | pub use ::E::V; | ^^^^^^ -error[E0364]: `V` is private, and cannot be re-exported +error[E0364]: `V` is only public within the crate, and cannot be re-exported outside --> $DIR/private-variant-reexport.rs:6:19 | LL | pub use ::E::{V}; @@ -22,11 +22,11 @@ note: consider marking `V` as `pub` in the imported module LL | pub use ::E::{V}; | ^ -error[E0365]: `V` is private, and cannot be re-exported +error[E0365]: `V` is only public within the crate, and cannot be re-exported outside --> $DIR/private-variant-reexport.rs:10:22 | LL | pub use ::E::V::{self}; - | ^^^^ re-export of private `V` + | ^^^^ re-export of crate public `V` | = note: consider declaring type or module `V` with `pub` diff --git a/src/test/ui/privacy/pub-priv-dep/pub-priv1.rs b/src/test/ui/privacy/pub-priv-dep/pub-priv1.rs index f926eee9d9..ec8666f93f 100644 --- a/src/test/ui/privacy/pub-priv-dep/pub-priv1.rs +++ b/src/test/ui/privacy/pub-priv-dep/pub-priv1.rs @@ -1,5 +1,6 @@ // aux-crate:priv:priv_dep=priv_dep.rs // aux-build:pub_dep.rs +// compile-flags: -Zunstable-options #![deny(exported_private_dependencies)] // This crate is a private dependency diff --git a/src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr b/src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr index e6b4d33f10..f64b856901 100644 --- a/src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr +++ b/src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr @@ -1,23 +1,23 @@ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:20:5 + --> $DIR/pub-priv1.rs:21:5 | LL | pub field: OtherType, | ^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/pub-priv1.rs:3:9 + --> $DIR/pub-priv1.rs:4:9 | LL | #![deny(exported_private_dependencies)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:27:5 + --> $DIR/pub-priv1.rs:28:5 | LL | pub fn pub_fn(param: OtherType) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: trait `OtherTrait` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:34:5 + --> $DIR/pub-priv1.rs:35:5 | LL | type Foo: OtherTrait; | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/reachable-unnameable-items.rs b/src/test/ui/privacy/reachable-unnameable-items.rs similarity index 100% rename from src/test/ui/reachable-unnameable-items.rs rename to src/test/ui/privacy/reachable-unnameable-items.rs diff --git a/src/test/ui/useless-pub.rs b/src/test/ui/privacy/useless-pub.rs similarity index 100% rename from src/test/ui/useless-pub.rs rename to src/test/ui/privacy/useless-pub.rs diff --git a/src/test/ui/useless-pub.stderr b/src/test/ui/privacy/useless-pub.stderr similarity index 100% rename from src/test/ui/useless-pub.stderr rename to src/test/ui/privacy/useless-pub.stderr diff --git a/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs b/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs index 65d8bcd997..695ea69c8e 100644 --- a/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs +++ b/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs @@ -35,5 +35,5 @@ fn main() { } use deny as allow; -#[allow(unused)] //~ ERROR `allow` is ambiguous (built-in attribute vs any other name) +#[allow(unused)] //~ ERROR `allow` is ambiguous fn builtin_renamed() {} diff --git a/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr b/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr index 1ad991db3b..0f4ddc065a 100644 --- a/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr +++ b/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr @@ -4,12 +4,13 @@ error[E0425]: cannot find value `NonExistent` in this scope LL | NonExistent; | ^^^^^^^^^^^ not found in this scope -error[E0659]: `repr` is ambiguous (built-in attribute vs any other name) +error[E0659]: `repr` is ambiguous --> $DIR/ambiguous-builtin-attrs.rs:9:3 | LL | #[repr(C)] | ^^^^ ambiguous name | + = note: ambiguous because of a name conflict with a builtin attribute = note: `repr` could refer to a built-in attribute note: `repr` could also refer to the attribute macro imported here --> $DIR/ambiguous-builtin-attrs.rs:6:5 @@ -18,12 +19,13 @@ LL | use builtin_attrs::*; | ^^^^^^^^^^^^^^^^ = help: use `crate::repr` to refer to this attribute macro unambiguously -error[E0659]: `repr` is ambiguous (built-in attribute vs any other name) +error[E0659]: `repr` is ambiguous --> $DIR/ambiguous-builtin-attrs.rs:11:19 | LL | #[cfg_attr(all(), repr(C))] | ^^^^ ambiguous name | + = note: ambiguous because of a name conflict with a builtin attribute = note: `repr` could refer to a built-in attribute note: `repr` could also refer to the attribute macro imported here --> $DIR/ambiguous-builtin-attrs.rs:6:5 @@ -32,12 +34,13 @@ LL | use builtin_attrs::*; | ^^^^^^^^^^^^^^^^ = help: use `crate::repr` to refer to this attribute macro unambiguously -error[E0659]: `repr` is ambiguous (built-in attribute vs any other name) +error[E0659]: `repr` is ambiguous --> $DIR/ambiguous-builtin-attrs.rs:20:34 | LL | fn non_macro_expanded_location<#[repr(C)] T>() { | ^^^^ ambiguous name | + = note: ambiguous because of a name conflict with a builtin attribute = note: `repr` could refer to a built-in attribute note: `repr` could also refer to the attribute macro imported here --> $DIR/ambiguous-builtin-attrs.rs:6:5 @@ -46,12 +49,13 @@ LL | use builtin_attrs::*; | ^^^^^^^^^^^^^^^^ = help: use `crate::repr` to refer to this attribute macro unambiguously -error[E0659]: `repr` is ambiguous (built-in attribute vs any other name) +error[E0659]: `repr` is ambiguous --> $DIR/ambiguous-builtin-attrs.rs:24:11 | LL | #[repr(C)] | ^^^^ ambiguous name | + = note: ambiguous because of a name conflict with a builtin attribute = note: `repr` could refer to a built-in attribute note: `repr` could also refer to the attribute macro imported here --> $DIR/ambiguous-builtin-attrs.rs:6:5 @@ -60,12 +64,13 @@ LL | use builtin_attrs::*; | ^^^^^^^^^^^^^^^^ = help: use `crate::repr` to refer to this attribute macro unambiguously -error[E0659]: `allow` is ambiguous (built-in attribute vs any other name) +error[E0659]: `allow` is ambiguous --> $DIR/ambiguous-builtin-attrs.rs:38:3 | LL | #[allow(unused)] | ^^^^^ ambiguous name | + = note: ambiguous because of a name conflict with a builtin attribute = note: `allow` could refer to a built-in attribute note: `allow` could also refer to the built-in attribute imported here --> $DIR/ambiguous-builtin-attrs.rs:37:5 @@ -74,12 +79,13 @@ LL | use deny as allow; | ^^^^^^^^^^^^^ = help: use `crate::allow` to refer to this built-in attribute unambiguously -error[E0659]: `feature` is ambiguous (built-in attribute vs any other name) +error[E0659]: `feature` is ambiguous --> $DIR/ambiguous-builtin-attrs.rs:3:4 | LL | #![feature(decl_macro)] | ^^^^^^^ ambiguous name | + = note: ambiguous because of a name conflict with a builtin attribute = note: `feature` could refer to a built-in attribute note: `feature` could also refer to the attribute macro imported here --> $DIR/ambiguous-builtin-attrs.rs:6:5 diff --git a/src/test/ui/proc-macro/auxiliary/api/parse.rs b/src/test/ui/proc-macro/auxiliary/api/parse.rs index 93551ebaf8..6186b941ef 100644 --- a/src/test/ui/proc-macro/auxiliary/api/parse.rs +++ b/src/test/ui/proc-macro/auxiliary/api/parse.rs @@ -1,3 +1,5 @@ +// ignore-tidy-linelength + use proc_macro::Literal; pub fn test() { @@ -8,6 +10,14 @@ pub fn test() { fn test_display_literal() { assert_eq!(Literal::isize_unsuffixed(-10).to_string(), "-10"); assert_eq!(Literal::isize_suffixed(-10).to_string(), "-10isize"); + assert_eq!(Literal::f32_unsuffixed(-10.0).to_string(), "-10.0"); + assert_eq!(Literal::f32_suffixed(-10.0).to_string(), "-10f32"); + assert_eq!(Literal::f64_unsuffixed(-10.0).to_string(), "-10.0"); + assert_eq!(Literal::f64_suffixed(-10.0).to_string(), "-10f64"); + assert_eq!( + Literal::f64_unsuffixed(1e100).to_string(), + "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0", + ); } fn test_parse_literal() { diff --git a/src/test/ui/auxiliary/cond_plugin.rs b/src/test/ui/proc-macro/auxiliary/cond_plugin.rs similarity index 100% rename from src/test/ui/auxiliary/cond_plugin.rs rename to src/test/ui/proc-macro/auxiliary/cond_plugin.rs diff --git a/src/test/ui/proc-macro/auxiliary/expand-expr.rs b/src/test/ui/proc-macro/auxiliary/expand-expr.rs new file mode 100644 index 0000000000..2bc34f3c6b --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/expand-expr.rs @@ -0,0 +1,80 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![deny(warnings)] +#![feature(proc_macro_expand, proc_macro_span)] + +extern crate proc_macro; + +use proc_macro::*; +use std::str::FromStr; + +#[proc_macro] +pub fn expand_expr_is(input: TokenStream) -> TokenStream { + let mut iter = input.into_iter(); + let mut expected_tts = Vec::new(); + loop { + match iter.next() { + Some(TokenTree::Punct(ref p)) if p.as_char() == ',' => break, + Some(tt) => expected_tts.push(tt), + None => panic!("expected comma"), + } + } + + let expected = expected_tts.into_iter().collect::<TokenStream>(); + let expanded = iter.collect::<TokenStream>().expand_expr().expect("expand_expr failed"); + assert!( + expected.to_string() == expanded.to_string(), + "assert failed\nexpected: `{}`\nexpanded: `{}`", + expected.to_string(), + expanded.to_string() + ); + + TokenStream::new() +} + +#[proc_macro] +pub fn expand_expr_fail(input: TokenStream) -> TokenStream { + match input.expand_expr() { + Ok(ts) => panic!("expand_expr unexpectedly succeeded: `{}`", ts), + Err(_) => TokenStream::new(), + } +} + +#[proc_macro] +pub fn check_expand_expr_file(ts: TokenStream) -> TokenStream { + // Check that the passed in `file!()` invocation and a parsed `file!` + // invocation expand to the same literal. + let input_t = ts.expand_expr().expect("expand_expr failed on macro input").to_string(); + let parse_t = TokenStream::from_str("file!{}") + .unwrap() + .expand_expr() + .expect("expand_expr failed on internal macro") + .to_string(); + assert_eq!(input_t, parse_t); + + // Check that the literal matches `Span::call_site().source_file().path()` + let expect_t = + Literal::string(&Span::call_site().source_file().path().to_string_lossy()).to_string(); + assert_eq!(input_t, expect_t); + + TokenStream::new() +} + +#[proc_macro] +pub fn recursive_expand(_: TokenStream) -> TokenStream { + // Recursively call until we hit the recursion limit and get an error. + // + // NOTE: This doesn't panic if expansion fails because that'll cause a very + // large number of errors to fill the output. + TokenStream::from_str("recursive_expand!{}") + .unwrap() + .expand_expr() + .unwrap_or(std::iter::once(TokenTree::Literal(Literal::u32_suffixed(0))).collect()) +} + +#[proc_macro] +pub fn echo_pm(input: TokenStream) -> TokenStream { + input +} diff --git a/src/test/ui/proc-macro/auxiliary/included-file.txt b/src/test/ui/proc-macro/auxiliary/included-file.txt new file mode 100644 index 0000000000..b4720047d6 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/included-file.txt @@ -0,0 +1 @@ +Included file contents diff --git a/src/test/ui/proc-macro/derive-helper-shadowing.stderr b/src/test/ui/proc-macro/derive-helper-shadowing.stderr index df462903fc..d8287eb73d 100644 --- a/src/test/ui/proc-macro/derive-helper-shadowing.stderr +++ b/src/test/ui/proc-macro/derive-helper-shadowing.stderr @@ -33,12 +33,13 @@ LL | gen_helper_use!(); crate::empty_helper = note: this error originates in the macro `gen_helper_use` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0659]: `empty_helper` is ambiguous (name vs any other name during import resolution) +error[E0659]: `empty_helper` is ambiguous --> $DIR/derive-helper-shadowing.rs:26:13 | LL | use empty_helper; | ^^^^^^^^^^^^ ambiguous name | + = note: ambiguous because of multiple potential import sources note: `empty_helper` could refer to the derive helper attribute defined here --> $DIR/derive-helper-shadowing.rs:22:10 | @@ -51,12 +52,13 @@ LL | use test_macros::empty_attr as empty_helper; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: use `crate::empty_helper` to refer to this attribute macro unambiguously -error[E0659]: `empty_helper` is ambiguous (derive helper attribute vs any other name) +error[E0659]: `empty_helper` is ambiguous --> $DIR/derive-helper-shadowing.rs:19:3 | LL | #[empty_helper] | ^^^^^^^^^^^^ ambiguous name | + = note: ambiguous because of a name conflict with a derive helper attribute note: `empty_helper` could refer to the derive helper attribute defined here --> $DIR/derive-helper-shadowing.rs:22:10 | diff --git a/src/test/ui/proc-macro/expand-expr.rs b/src/test/ui/proc-macro/expand-expr.rs new file mode 100644 index 0000000000..d1146d9703 --- /dev/null +++ b/src/test/ui/proc-macro/expand-expr.rs @@ -0,0 +1,121 @@ +// aux-build:expand-expr.rs + +extern crate expand_expr; + +use expand_expr::{ + check_expand_expr_file, echo_pm, expand_expr_fail, expand_expr_is, recursive_expand, +}; + +// Check builtin macros can be expanded. + +expand_expr_is!(11u32, line!()); +expand_expr_is!(24u32, column!()); + +expand_expr_is!("Hello, World!", concat!("Hello, ", "World", "!")); +expand_expr_is!("int10floats5.3booltrue", concat!("int", 10, "floats", 5.3, "bool", true)); +expand_expr_is!("Hello", concat!(r##"Hello"##)); + +expand_expr_is!("Included file contents\n", include_str!("auxiliary/included-file.txt")); +expand_expr_is!(b"Included file contents\n", include_bytes!("auxiliary/included-file.txt")); + +expand_expr_is!( + "contents: Included file contents\n", + concat!("contents: ", include_str!("auxiliary/included-file.txt")) +); + +// Correct value is checked for multiple sources. +check_expand_expr_file!(file!()); + +expand_expr_is!("hello", stringify!(hello)); +expand_expr_is!("10 + 20", stringify!(10 + 20)); + +macro_rules! echo_tts { + ($($t:tt)*) => { $($t)* }; //~ ERROR: expected expression, found `$` +} + +macro_rules! echo_lit { + ($l:literal) => { + $l + }; +} + +macro_rules! echo_expr { + ($e:expr) => { + $e + }; +} + +macro_rules! simple_lit { + ($l:literal) => { + expand_expr_is!($l, $l); + expand_expr_is!($l, echo_lit!($l)); + expand_expr_is!($l, echo_expr!($l)); + expand_expr_is!($l, echo_tts!($l)); + expand_expr_is!($l, echo_pm!($l)); + const _: () = { + macro_rules! mac { + () => { + $l + }; + } + expand_expr_is!($l, mac!()); + expand_expr_is!($l, echo_expr!(mac!())); + expand_expr_is!($l, echo_tts!(mac!())); + expand_expr_is!($l, echo_pm!(mac!())); + }; + }; +} + +simple_lit!("Hello, World"); +simple_lit!('c'); +simple_lit!(b'c'); +simple_lit!(10); +simple_lit!(10.0); +simple_lit!(10.0f64); +simple_lit!(-3.14159); +simple_lit!(-3.5e10); +simple_lit!(0xFEED); +simple_lit!(-0xFEED); +simple_lit!(0b0100); +simple_lit!(-0b0100); +simple_lit!("string"); +simple_lit!(r##"raw string"##); +simple_lit!(b"byte string"); +simple_lit!(br##"raw byte string"##); +simple_lit!(true); +simple_lit!(false); + +// Ensure char escapes aren't normalized by expansion +simple_lit!("\u{0}"); +simple_lit!("\0"); +simple_lit!("\x00"); +simple_lit!('\u{0}'); +simple_lit!('\0'); +simple_lit!('\x00'); +simple_lit!(b"\x00"); +simple_lit!(b"\0"); +simple_lit!(b'\x00'); +simple_lit!(b'\0'); + +// Extra tokens after the string literal aren't ignored +expand_expr_fail!("string"; hello); //~ ERROR: expected one of `.`, `?`, or an operator, found `;` + +// Invalid expressions produce errors in addition to returning `Err(())`. +expand_expr_fail!($); //~ ERROR: expected expression, found `$` +expand_expr_fail!(echo_tts!($)); +expand_expr_fail!(echo_pm!($)); //~ ERROR: expected expression, found `$` + +// We get errors reported and recover during macro expansion if the macro +// doesn't produce a valid expression. +expand_expr_is!("string", echo_tts!("string"; hello)); //~ ERROR: macro expansion ignores token `hello` and any following +expand_expr_is!("string", echo_pm!("string"; hello)); //~ ERROR: macro expansion ignores token `;` and any following + +// For now, fail if a non-literal expression is expanded. +expand_expr_fail!(arbitrary_expression() + "etc"); +expand_expr_fail!(echo_tts!(arbitrary_expression() + "etc")); +expand_expr_fail!(echo_expr!(arbitrary_expression() + "etc")); +expand_expr_fail!(echo_pm!(arbitrary_expression() + "etc")); + +const _: u32 = recursive_expand!(); //~ ERROR: recursion limit reached while expanding `recursive_expand!` + +fn main() {} diff --git a/src/test/ui/proc-macro/expand-expr.stderr b/src/test/ui/proc-macro/expand-expr.stderr new file mode 100644 index 0000000000..8dc2d0cfc2 --- /dev/null +++ b/src/test/ui/proc-macro/expand-expr.stderr @@ -0,0 +1,55 @@ +error: expected one of `.`, `?`, or an operator, found `;` + --> $DIR/expand-expr.rs:101:27 + | +LL | expand_expr_fail!("string"; hello); + | ^ expected one of `.`, `?`, or an operator + +error: expected expression, found `$` + --> $DIR/expand-expr.rs:104:19 + | +LL | expand_expr_fail!($); + | ^ expected expression + +error: expected expression, found `$` + --> $DIR/expand-expr.rs:33:23 + | +LL | ($($t:tt)*) => { $($t)* }; + | ^^^^ expected expression + +error: expected expression, found `$` + --> $DIR/expand-expr.rs:106:28 + | +LL | expand_expr_fail!(echo_pm!($)); + | ^ expected expression + +error: macro expansion ignores token `hello` and any following + --> $DIR/expand-expr.rs:110:47 + | +LL | expand_expr_is!("string", echo_tts!("string"; hello)); + | --------------------^^^^^-- help: you might be missing a semicolon here: `;` + | | + | caused by the macro expansion here + | + = note: the usage of `echo_tts!` is likely invalid in expression context + +error: macro expansion ignores token `;` and any following + --> $DIR/expand-expr.rs:111:44 + | +LL | expand_expr_is!("string", echo_pm!("string"; hello)); + | -----------------^-------- help: you might be missing a semicolon here: `;` + | | + | caused by the macro expansion here + | + = note: the usage of `echo_pm!` is likely invalid in expression context + +error: recursion limit reached while expanding `recursive_expand!` + --> $DIR/expand-expr.rs:119:16 + | +LL | const _: u32 = recursive_expand!(); + | ^^^^^^^^^^^^^^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`expand_expr`) + = note: this error originates in the macro `recursive_expand` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 7 previous errors + diff --git a/src/test/ui/proc-macro/generate-mod.rs b/src/test/ui/proc-macro/generate-mod.rs index e5f967416c..471f317edf 100644 --- a/src/test/ui/proc-macro/generate-mod.rs +++ b/src/test/ui/proc-macro/generate-mod.rs @@ -13,15 +13,15 @@ generate_mod::check!(); //~ ERROR cannot find type `FromOutside` in this scope //~| ERROR cannot find type `OuterAttr` in this scope struct S; -#[derive(generate_mod::CheckDerive)] //~ WARN cannot find type `FromOutside` in this scope - //~| WARN cannot find type `OuterDerive` in this scope +#[derive(generate_mod::CheckDerive)] //~ ERROR cannot find type `FromOutside` in this scope + //~| ERROR cannot find type `OuterDerive` in this scope //~| WARN this was previously accepted //~| WARN this was previously accepted struct Z; fn inner_block() { - #[derive(generate_mod::CheckDerive)] //~ WARN cannot find type `FromOutside` in this scope - //~| WARN cannot find type `OuterDerive` in this scope + #[derive(generate_mod::CheckDerive)] //~ ERROR cannot find type `FromOutside` in this scope + //~| ERROR cannot find type `OuterDerive` in this scope //~| WARN this was previously accepted //~| WARN this was previously accepted struct InnerZ; diff --git a/src/test/ui/proc-macro/generate-mod.stderr b/src/test/ui/proc-macro/generate-mod.stderr index be58cc40ed..a2c1b82b15 100644 --- a/src/test/ui/proc-macro/generate-mod.stderr +++ b/src/test/ui/proc-macro/generate-mod.stderr @@ -38,18 +38,18 @@ LL | #[generate_mod::check_attr] OuterAttr = note: this error originates in the attribute macro `generate_mod::check_attr` (in Nightly builds, run with -Z macro-backtrace for more info) -warning: cannot find type `FromOutside` in this scope +error: cannot find type `FromOutside` in this scope --> $DIR/generate-mod.rs:16:10 | LL | #[derive(generate_mod::CheckDerive)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import | - = note: `#[warn(proc_macro_derive_resolution_fallback)]` on by default + = note: `#[deny(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 #83583 <https://github.com/rust-lang/rust/issues/83583> - = note: this warning originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) -warning: cannot find type `OuterDerive` in this scope +error: cannot find type `OuterDerive` in this scope --> $DIR/generate-mod.rs:16:10 | LL | #[derive(generate_mod::CheckDerive)] @@ -57,9 +57,9 @@ LL | #[derive(generate_mod::CheckDerive)] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583> - = note: this warning originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) -warning: cannot find type `FromOutside` in this scope +error: cannot find type `FromOutside` in this scope --> $DIR/generate-mod.rs:23:14 | LL | #[derive(generate_mod::CheckDerive)] @@ -67,9 +67,9 @@ LL | #[derive(generate_mod::CheckDerive)] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583> - = note: this warning originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) -warning: cannot find type `OuterDerive` in this scope +error: cannot find type `OuterDerive` in this scope --> $DIR/generate-mod.rs:23:14 | LL | #[derive(generate_mod::CheckDerive)] @@ -77,25 +77,25 @@ LL | #[derive(generate_mod::CheckDerive)] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583> - = note: this warning originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 4 previous errors; 4 warnings emitted +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0412`. Future incompatibility report: Future breakage diagnostic: -warning: cannot find type `FromOutside` in this scope +error: cannot find type `FromOutside` in this scope --> $DIR/generate-mod.rs:16:10 | LL | #[derive(generate_mod::CheckDerive)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import | - = note: `#[warn(proc_macro_derive_resolution_fallback)]` on by default + = note: `#[deny(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 #83583 <https://github.com/rust-lang/rust/issues/83583> - = note: this warning originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) Future breakage diagnostic: -warning: cannot find type `OuterDerive` in this scope +error: cannot find type `OuterDerive` in this scope --> $DIR/generate-mod.rs:16:10 | LL | #[derive(generate_mod::CheckDerive)] @@ -103,10 +103,10 @@ LL | #[derive(generate_mod::CheckDerive)] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583> - = note: this warning originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) Future breakage diagnostic: -warning: cannot find type `FromOutside` in this scope +error: cannot find type `FromOutside` in this scope --> $DIR/generate-mod.rs:23:14 | LL | #[derive(generate_mod::CheckDerive)] @@ -114,10 +114,10 @@ LL | #[derive(generate_mod::CheckDerive)] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583> - = note: this warning originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) Future breakage diagnostic: -warning: cannot find type `OuterDerive` in this scope +error: cannot find type `OuterDerive` in this scope --> $DIR/generate-mod.rs:23:14 | LL | #[derive(generate_mod::CheckDerive)] @@ -125,7 +125,7 @@ LL | #[derive(generate_mod::CheckDerive)] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583> - = note: this warning originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) Future breakage diagnostic: warning: cannot find type `FromOutside` in this scope 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 2b742771d6..3a2a6fa225 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 @@ -1,4 +1,3 @@ -// check-pass // aux-build:pin-project-internal-0.4.0.rs // compile-flags: -Z span-debug @@ -24,7 +23,7 @@ mod no_version { } struct Foo; - impl_macros!(Foo); //~ WARN using an old version + impl_macros!(Foo); //~ ERROR using an old version //~| WARN this was previously arrays!(Foo); other!(Foo); @@ -41,9 +40,9 @@ mod with_version { } struct Foo; - impl_macros!(Foo); //~ WARN using an old version + impl_macros!(Foo); //~ ERROR using an old version //~| WARN this was previously - arrays!(Foo); //~ WARN using an old version + arrays!(Foo); //~ ERROR using an old version //~| WARN this was previously other!(Foo); } @@ -52,7 +51,7 @@ mod actix_web_test { include!("actix-web/src/extract.rs"); struct Foo; - tuple_from_req!(Foo); //~ WARN using an old version + tuple_from_req!(Foo); //~ ERROR using an old version //~| WARN this was previously } @@ -60,7 +59,7 @@ mod actix_web_version_test { include!("actix-web-2.0.0/src/extract.rs"); struct Foo; - tuple_from_req!(Foo); //~ WARN using an old version + tuple_from_req!(Foo); //~ ERROR using an old version //~| WARN this was previously } 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 1a56291896..bd9ba6a09f 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 @@ -1,27 +1,27 @@ -warning: using an old version of `time-macros-impl` +error: using an old version of `time-macros-impl` --> $DIR/time-macros-impl/src/lib.rs:5:32 | LL | #[my_macro] struct One($name); | ^^^^^ | - ::: $DIR/group-compat-hack.rs:27:5 + ::: $DIR/group-compat-hack.rs:26:5 | LL | impl_macros!(Foo); | ----------------- in this macro invocation | - = note: `#[warn(proc_macro_back_compat)]` on by default + = note: `#[deny(proc_macro_back_compat)]` 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 #83125 <https://github.com/rust-lang/rust/issues/83125> = note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage - = note: this warning originates in the macro `impl_macros` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `impl_macros` (in Nightly builds, run with -Z macro-backtrace for more info) -warning: using an old version of `time-macros-impl` +error: using an old version of `time-macros-impl` --> $DIR/time-macros-impl-0.1.0/src/lib.rs:5:32 | LL | #[my_macro] struct One($name); | ^^^^^ | - ::: $DIR/group-compat-hack.rs:44:5 + ::: $DIR/group-compat-hack.rs:43:5 | LL | impl_macros!(Foo); | ----------------- in this macro invocation @@ -29,15 +29,15 @@ LL | impl_macros!(Foo); = warning: this was previously accepted 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: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage - = note: this warning originates in the macro `impl_macros` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `impl_macros` (in Nightly builds, run with -Z macro-backtrace for more info) -warning: using an old version of `js-sys` +error: 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 + ::: $DIR/group-compat-hack.rs:45:5 | LL | arrays!(Foo); | ------------ in this macro invocation @@ -45,15 +45,15 @@ LL | arrays!(Foo); = warning: this was previously accepted 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 the macro `arrays` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `arrays` (in Nightly builds, run with -Z macro-backtrace for more info) -warning: using an old version of `actix-web` +error: 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:55:5 + ::: $DIR/group-compat-hack.rs:54:5 | LL | tuple_from_req!(Foo); | -------------------- in this macro invocation @@ -61,15 +61,15 @@ LL | tuple_from_req!(Foo); = warning: this was previously accepted 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: the version of `actix-web` you are using might stop compiling in future versions of Rust; please update to the latest version of the `actix-web` crate to avoid breakage - = note: this warning originates in the macro `tuple_from_req` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `tuple_from_req` (in Nightly builds, run with -Z macro-backtrace for more info) -warning: using an old version of `actix-web` +error: using an old version of `actix-web` --> $DIR/actix-web-2.0.0/src/extract.rs:5:34 | LL | #[my_macro] struct Three($T); | ^^ | - ::: $DIR/group-compat-hack.rs:63:5 + ::: $DIR/group-compat-hack.rs:62:5 | LL | tuple_from_req!(Foo); | -------------------- in this macro invocation @@ -77,36 +77,36 @@ LL | tuple_from_req!(Foo); = warning: this was previously accepted 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: the version of `actix-web` you are using might stop compiling in future versions of Rust; please update to the latest version of the `actix-web` crate to avoid breakage - = note: this warning originates in the macro `tuple_from_req` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `tuple_from_req` (in Nightly builds, run with -Z macro-backtrace for more info) -warning: 5 warnings emitted +error: aborting due to 5 previous errors Future incompatibility report: Future breakage diagnostic: -warning: using an old version of `time-macros-impl` +error: using an old version of `time-macros-impl` --> $DIR/time-macros-impl/src/lib.rs:5:32 | LL | #[my_macro] struct One($name); | ^^^^^ | - ::: $DIR/group-compat-hack.rs:27:5 + ::: $DIR/group-compat-hack.rs:26:5 | LL | impl_macros!(Foo); | ----------------- in this macro invocation | - = note: `#[warn(proc_macro_back_compat)]` on by default + = note: `#[deny(proc_macro_back_compat)]` 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 #83125 <https://github.com/rust-lang/rust/issues/83125> = note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage - = note: this warning originates in the macro `impl_macros` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `impl_macros` (in Nightly builds, run with -Z macro-backtrace for more info) Future breakage diagnostic: -warning: using an old version of `time-macros-impl` +error: using an old version of `time-macros-impl` --> $DIR/time-macros-impl-0.1.0/src/lib.rs:5:32 | LL | #[my_macro] struct One($name); | ^^^^^ | - ::: $DIR/group-compat-hack.rs:44:5 + ::: $DIR/group-compat-hack.rs:43:5 | LL | impl_macros!(Foo); | ----------------- in this macro invocation @@ -114,16 +114,16 @@ LL | impl_macros!(Foo); = warning: this was previously accepted 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: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage - = note: this warning originates in the macro `impl_macros` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `impl_macros` (in Nightly builds, run with -Z macro-backtrace for more info) Future breakage diagnostic: -warning: using an old version of `js-sys` +error: 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 + ::: $DIR/group-compat-hack.rs:45:5 | LL | arrays!(Foo); | ------------ in this macro invocation @@ -131,16 +131,16 @@ LL | arrays!(Foo); = warning: this was previously accepted 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 the macro `arrays` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `arrays` (in Nightly builds, run with -Z macro-backtrace for more info) Future breakage diagnostic: -warning: using an old version of `actix-web` +error: 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:55:5 + ::: $DIR/group-compat-hack.rs:54:5 | LL | tuple_from_req!(Foo); | -------------------- in this macro invocation @@ -148,16 +148,16 @@ LL | tuple_from_req!(Foo); = warning: this was previously accepted 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: the version of `actix-web` you are using might stop compiling in future versions of Rust; please update to the latest version of the `actix-web` crate to avoid breakage - = note: this warning originates in the macro `tuple_from_req` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `tuple_from_req` (in Nightly builds, run with -Z macro-backtrace for more info) Future breakage diagnostic: -warning: using an old version of `actix-web` +error: using an old version of `actix-web` --> $DIR/actix-web-2.0.0/src/extract.rs:5:34 | LL | #[my_macro] struct Three($T); | ^^ | - ::: $DIR/group-compat-hack.rs:63:5 + ::: $DIR/group-compat-hack.rs:62:5 | LL | tuple_from_req!(Foo); | -------------------- in this macro invocation @@ -165,5 +165,5 @@ LL | tuple_from_req!(Foo); = warning: this was previously accepted 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: the version of `actix-web` you are using might stop compiling in future versions of Rust; please update to the latest version of the `actix-web` crate to avoid breakage - = note: this warning originates in the macro `tuple_from_req` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `tuple_from_req` (in Nightly builds, run with -Z macro-backtrace for more info) 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 82d6bc33bf..51312b10ad 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,11 +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 [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: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) }] +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:26:18: 26: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 [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:28:13: 28: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:21:25: 21:31 (#14) }, Ident { ident: "Three", span: $DIR/group-compat-hack.rs:21:32: 21:37 (#14) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:29:12: 29:15 (#0) }], span: $DIR/group-compat-hack.rs:21:38: 21:43 (#14) }], span: $DIR/group-compat-hack.rs:21:37: 21:44 (#14) }, Punct { ch: ';', spacing: Alone, span: $DIR/group-compat-hack.rs:21:44: 21: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:43:18: 43: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:45:13: 45: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:38:25: 38:31 (#28) }, Ident { ident: "Three", span: $DIR/group-compat-hack.rs:38:32: 38: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:38:38: 38:43 (#28) }], span: $DIR/group-compat-hack.rs:38:37: 38:44 (#28) }, Punct { ch: ';', spacing: Alone, span: $DIR/group-compat-hack.rs:38:44: 38: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/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:83:13: 83: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/helper-attr-blocked-by-import-ambig.stderr b/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr index ceb6d78978..45b014c4b6 100644 --- a/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr +++ b/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr @@ -1,9 +1,10 @@ -error[E0659]: `empty_helper` is ambiguous (derive helper attribute vs any other name) +error[E0659]: `empty_helper` is ambiguous --> $DIR/helper-attr-blocked-by-import-ambig.rs:7:3 | LL | #[empty_helper] | ^^^^^^^^^^^^ ambiguous name | + = note: ambiguous because of a name conflict with a derive helper attribute note: `empty_helper` could refer to the derive helper attribute defined here --> $DIR/helper-attr-blocked-by-import-ambig.rs:10:10 | diff --git a/src/test/ui/proc-macro/issue-39889.rs b/src/test/ui/proc-macro/issue-39889.rs index ada125a215..69bfb4f3cb 100644 --- a/src/test/ui/proc-macro/issue-39889.rs +++ b/src/test/ui/proc-macro/issue-39889.rs @@ -1,6 +1,6 @@ // run-pass -#![allow(dead_code)] +#![allow(dead_code, unused_macros)] // aux-build:issue-39889.rs extern crate issue_39889; diff --git a/src/test/ui/proc-macro/issue-41211.stderr b/src/test/ui/proc-macro/issue-41211.stderr index 22ad4aa147..60cd36a9cc 100644 --- a/src/test/ui/proc-macro/issue-41211.stderr +++ b/src/test/ui/proc-macro/issue-41211.stderr @@ -1,9 +1,10 @@ -error[E0659]: `identity_attr` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) +error[E0659]: `identity_attr` is ambiguous --> $DIR/issue-41211.rs:11:4 | LL | #![identity_attr] | ^^^^^^^^^^^^^ ambiguous name | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution note: `identity_attr` could refer to the attribute macro imported here --> $DIR/issue-41211.rs:14:5 | diff --git a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.rs b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.rs index abc3d2691a..113235051b 100644 --- a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.rs +++ b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.rs @@ -1,11 +1,10 @@ -// check-pass // aux-build:test-macros.rs #[macro_use] extern crate test_macros; #[derive(Print)] -enum ProceduralMasqueradeDummyType { //~ WARN using +enum ProceduralMasqueradeDummyType { //~ ERROR using //~| WARN this was previously Input } diff --git a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr index 4d6edab08e..dff71c9eac 100644 --- a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr +++ b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr @@ -1,24 +1,24 @@ -warning: using `procedural-masquerade` crate - --> $DIR/issue-73933-procedural-masquerade.rs:8:6 +error: using `procedural-masquerade` crate + --> $DIR/issue-73933-procedural-masquerade.rs:7:6 | LL | enum ProceduralMasqueradeDummyType { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `#[warn(proc_macro_back_compat)]` on by default + = note: `#[deny(proc_macro_back_compat)]` 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 #83125 <https://github.com/rust-lang/rust/issues/83125> = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling. -warning: 1 warning emitted +error: aborting due to previous error Future incompatibility report: Future breakage diagnostic: -warning: using `procedural-masquerade` crate - --> $DIR/issue-73933-procedural-masquerade.rs:8:6 +error: using `procedural-masquerade` crate + --> $DIR/issue-73933-procedural-masquerade.rs:7:6 | LL | enum ProceduralMasqueradeDummyType { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `#[warn(proc_macro_back_compat)]` on by default + = note: `#[deny(proc_macro_back_compat)]` 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 #83125 <https://github.com/rust-lang/rust/issues/83125> = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling. diff --git a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stdout b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stdout index 8edd68f8a3..8a8fbf0682 100644 --- a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stdout +++ b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stdout @@ -3,20 +3,20 @@ PRINT-DERIVE RE-COLLECTED (DISPLAY): enum ProceduralMasqueradeDummyType { Input PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "enum", - span: #0 bytes(100..104), + span: #0 bytes(86..90), }, Ident { ident: "ProceduralMasqueradeDummyType", - span: #0 bytes(105..134), + span: #0 bytes(91..120), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "Input", - span: #0 bytes(186..191), + span: #0 bytes(173..178), }, ], - span: #0 bytes(135..193), + span: #0 bytes(121..180), }, ] diff --git a/src/test/ui/macro-quote-cond.rs b/src/test/ui/proc-macro/macro-quote-cond.rs similarity index 100% rename from src/test/ui/macro-quote-cond.rs rename to src/test/ui/proc-macro/macro-quote-cond.rs diff --git a/src/test/ui/proc-macro/meta-macro-hygiene.stdout b/src/test/ui/proc-macro/meta-macro-hygiene.stdout index 7f7a1009c9..5d04fe1e3d 100644 --- a/src/test/ui/proc-macro/meta-macro-hygiene.stdout +++ b/src/test/ui/proc-macro/meta-macro-hygiene.stdout @@ -49,6 +49,8 @@ crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "produce_it") crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #4, def_site_ctxt: #0, kind: Macro(Bang, "meta_macro::print_def_site") crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #5, def_site_ctxt: #0, kind: Macro(Bang, "$crate::dummy") +crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "derive") +crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "derive") crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "include") crate2::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports) diff --git a/src/test/ui/proc-macro/nonterminal-token-hygiene.stdout b/src/test/ui/proc-macro/nonterminal-token-hygiene.stdout index 0780386381..709b2a2169 100644 --- a/src/test/ui/proc-macro/nonterminal-token-hygiene.stdout +++ b/src/test/ui/proc-macro/nonterminal-token-hygiene.stdout @@ -73,6 +73,8 @@ crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "outer") crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #4, def_site_ctxt: #4, kind: Macro(Bang, "inner") crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #6, def_site_ctxt: #0, kind: Macro(Bang, "print_bang") +crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "derive") +crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "derive") crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "include") crate2::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports) diff --git a/src/test/ui/proc-macro/proc-macro-attributes.stderr b/src/test/ui/proc-macro/proc-macro-attributes.stderr index 1ba04258df..b66e4575e1 100644 --- a/src/test/ui/proc-macro/proc-macro-attributes.stderr +++ b/src/test/ui/proc-macro/proc-macro-attributes.stderr @@ -4,12 +4,13 @@ error: cannot find attribute `C` in this scope LL | #[C] | ^ help: a derive helper attribute with a similar name exists: `B` -error[E0659]: `B` is ambiguous (derive helper attribute vs any other name) +error[E0659]: `B` is ambiguous --> $DIR/proc-macro-attributes.rs:6:3 | LL | #[B] | ^ ambiguous name | + = note: ambiguous because of a name conflict with a derive helper attribute note: `B` could refer to the derive helper attribute defined here --> $DIR/proc-macro-attributes.rs:19:10 | @@ -21,12 +22,13 @@ note: `B` could also refer to the derive macro imported here LL | #[macro_use] | ^^^^^^^^^^^^ -error[E0659]: `B` is ambiguous (derive helper attribute vs any other name) +error[E0659]: `B` is ambiguous --> $DIR/proc-macro-attributes.rs:10:3 | LL | #[B(D)] | ^ ambiguous name | + = note: ambiguous because of a name conflict with a derive helper attribute note: `B` could refer to the derive helper attribute defined here --> $DIR/proc-macro-attributes.rs:19:10 | @@ -38,12 +40,13 @@ note: `B` could also refer to the derive macro imported here LL | #[macro_use] | ^^^^^^^^^^^^ -error[E0659]: `B` is ambiguous (derive helper attribute vs any other name) +error[E0659]: `B` is ambiguous --> $DIR/proc-macro-attributes.rs:13:3 | LL | #[B(E = "foo")] | ^ ambiguous name | + = note: ambiguous because of a name conflict with a derive helper attribute note: `B` could refer to the derive helper attribute defined here --> $DIR/proc-macro-attributes.rs:19:10 | @@ -55,12 +58,13 @@ note: `B` could also refer to the derive macro imported here LL | #[macro_use] | ^^^^^^^^^^^^ -error[E0659]: `B` is ambiguous (derive helper attribute vs any other name) +error[E0659]: `B` is ambiguous --> $DIR/proc-macro-attributes.rs:16:3 | LL | #[B(arbitrary tokens)] | ^ ambiguous name | + = note: ambiguous because of a name conflict with a derive helper attribute note: `B` could refer to the derive helper attribute defined here --> $DIR/proc-macro-attributes.rs:19:10 | diff --git a/src/test/ui/core-run-destroy.rs b/src/test/ui/process/core-run-destroy.rs similarity index 100% rename from src/test/ui/core-run-destroy.rs rename to src/test/ui/process/core-run-destroy.rs diff --git a/src/test/ui/fds-are-cloexec.rs b/src/test/ui/process/fds-are-cloexec.rs similarity index 100% rename from src/test/ui/fds-are-cloexec.rs rename to src/test/ui/process/fds-are-cloexec.rs diff --git a/src/test/ui/issues/issue-14456.rs b/src/test/ui/process/issue-14456.rs similarity index 100% rename from src/test/ui/issues/issue-14456.rs rename to src/test/ui/process/issue-14456.rs diff --git a/src/test/ui/issues/issue-16272.rs b/src/test/ui/process/issue-16272.rs similarity index 100% rename from src/test/ui/issues/issue-16272.rs rename to src/test/ui/process/issue-16272.rs diff --git a/src/test/ui/issues/issue-20091.rs b/src/test/ui/process/issue-20091.rs similarity index 100% rename from src/test/ui/issues/issue-20091.rs rename to src/test/ui/process/issue-20091.rs diff --git a/src/test/ui/multi-panic.rs b/src/test/ui/process/multi-panic.rs similarity index 100% rename from src/test/ui/multi-panic.rs rename to src/test/ui/process/multi-panic.rs diff --git a/src/test/ui/no-stdio.rs b/src/test/ui/process/no-stdio.rs similarity index 100% rename from src/test/ui/no-stdio.rs rename to src/test/ui/process/no-stdio.rs diff --git a/src/test/ui/signal-exit-status.rs b/src/test/ui/process/signal-exit-status.rs similarity index 100% rename from src/test/ui/signal-exit-status.rs rename to src/test/ui/process/signal-exit-status.rs diff --git a/src/test/ui/sigpipe-should-be-ignored.rs b/src/test/ui/process/sigpipe-should-be-ignored.rs similarity index 100% rename from src/test/ui/sigpipe-should-be-ignored.rs rename to src/test/ui/process/sigpipe-should-be-ignored.rs diff --git a/src/test/ui/try-wait.rs b/src/test/ui/process/try-wait.rs similarity index 100% rename from src/test/ui/try-wait.rs rename to src/test/ui/process/try-wait.rs diff --git a/src/test/ui/pure-sum.rs b/src/test/ui/pure-sum.rs deleted file mode 100644 index 2f2ece75eb..0000000000 --- a/src/test/ui/pure-sum.rs +++ /dev/null @@ -1,51 +0,0 @@ -// run-pass - -#![allow(dead_code)] -// Check that functions can modify local state. - -// pretty-expanded FIXME #23616 - -fn sums_to(v: Vec<isize> , sum: isize) -> bool { - let mut i = 0; - let mut sum0 = 0; - while i < v.len() { - sum0 += v[i]; - i += 1; - } - return sum0 == sum; -} - -fn sums_to_using_uniq(v: Vec<isize> , sum: isize) -> bool { - let mut i = 0; - let mut sum0: Box<_> = 0.into(); - while i < v.len() { - *sum0 += v[i]; - i += 1; - } - return *sum0 == sum; -} - -fn sums_to_using_rec(v: Vec<isize> , sum: isize) -> bool { - let mut i = 0; - let mut sum0 = F {f: 0}; - while i < v.len() { - sum0.f += v[i]; - i += 1; - } - return sum0.f == sum; -} - -struct F<T> { f: T } - -fn sums_to_using_uniq_rec(v: Vec<isize> , sum: isize) -> bool { - let mut i = 0; - let mut sum0 = F::<Box<_>> {f: 0.into() }; - while i < v.len() { - *sum0.f += v[i]; - i += 1; - } - return *sum0.f == sum; -} - -pub fn main() { -} diff --git a/src/test/ui/purity-infer.rs b/src/test/ui/purity-infer.rs deleted file mode 100644 index dc0eb89bfa..0000000000 --- a/src/test/ui/purity-infer.rs +++ /dev/null @@ -1,6 +0,0 @@ -// run-pass - -fn something<F>(f: F) where F: FnOnce() { f(); } -pub fn main() { - something(|| println!("hi!") ); -} diff --git a/src/test/ui/query-system/issue-83479.rs b/src/test/ui/query-system/issue-83479.rs new file mode 100644 index 0000000000..32676dfe9c --- /dev/null +++ b/src/test/ui/query-system/issue-83479.rs @@ -0,0 +1,16 @@ +#![feature(type_alias_impl_trait)] + +type PairCoupledTypes: Trait< + //~^ ERROR: bounds on `type`s in this context have no effect + //~| ERROR: cannot find trait `Trait` in this scope + [u32; { + static FOO: usize; //~ ERROR: free static item without body + }], +> = impl Trait< + //~^ ERROR: cannot find trait `Trait` in this scope + [u32; { + static FOO: usize; //~ ERROR: free static item without body + }], +>; + +fn main() {} diff --git a/src/test/ui/query-system/issue-83479.stderr b/src/test/ui/query-system/issue-83479.stderr new file mode 100644 index 0000000000..7cb41f5cbe --- /dev/null +++ b/src/test/ui/query-system/issue-83479.stderr @@ -0,0 +1,44 @@ +error: bounds on `type`s in this context have no effect + --> $DIR/issue-83479.rs:3:24 + | +LL | type PairCoupledTypes: Trait< + | ________________________^ +LL | | +LL | | +LL | | [u32; { +LL | | static FOO: usize; +LL | | }], +LL | | > = impl Trait< + | |_^ + +error: free static item without body + --> $DIR/issue-83479.rs:7:9 + | +LL | static FOO: usize; + | ^^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the static: `= <expr>;` + +error: free static item without body + --> $DIR/issue-83479.rs:12:9 + | +LL | static FOO: usize; + | ^^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the static: `= <expr>;` + +error[E0405]: cannot find trait `Trait` in this scope + --> $DIR/issue-83479.rs:3:24 + | +LL | type PairCoupledTypes: Trait< + | ^^^^^ not found in this scope + +error[E0405]: cannot find trait `Trait` in this scope + --> $DIR/issue-83479.rs:9:10 + | +LL | > = impl Trait< + | ^^^^^ not found in this scope + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0405`. diff --git a/src/test/ui/range/range-1.stderr b/src/test/ui/range/range-1.stderr index ff494d7d4b..2ce4e1553d 100644 --- a/src/test/ui/range/range-1.stderr +++ b/src/test/ui/range/range-1.stderr @@ -12,11 +12,6 @@ LL | for i in false..true {} | = note: required because of the requirements on the impl of `Iterator` for `std::ops::Range<bool>` = note: required because of the requirements on the impl of `IntoIterator` for `std::ops::Range<bool>` -note: required by `into_iter` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time --> $DIR/range-1.rs:14:17 diff --git a/src/test/ui/range/range_traits-1.stderr b/src/test/ui/range/range_traits-1.stderr index 34c59fcb31..617afc9953 100644 --- a/src/test/ui/range/range_traits-1.stderr +++ b/src/test/ui/range/range_traits-1.stderr @@ -8,11 +8,6 @@ LL | a: Range<usize>, | ^^^^^^^^^^^^^^^ no implementation for `std::ops::Range<usize> < std::ops::Range<usize>` and `std::ops::Range<usize> > std::ops::Range<usize>` | = help: the trait `PartialOrd` is not implemented for `std::ops::Range<usize>` -note: required by `std::cmp::PartialOrd::partial_cmp` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - | -LL | fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: can't compare `std::ops::RangeTo<usize>` with `std::ops::RangeTo<usize>` @@ -25,11 +20,6 @@ LL | b: RangeTo<usize>, | ^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeTo<usize> < std::ops::RangeTo<usize>` and `std::ops::RangeTo<usize> > std::ops::RangeTo<usize>` | = help: the trait `PartialOrd` is not implemented for `std::ops::RangeTo<usize>` -note: required by `std::cmp::PartialOrd::partial_cmp` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - | -LL | fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: can't compare `std::ops::RangeFrom<usize>` with `std::ops::RangeFrom<usize>` @@ -42,11 +32,6 @@ LL | c: RangeFrom<usize>, | ^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeFrom<usize> < std::ops::RangeFrom<usize>` and `std::ops::RangeFrom<usize> > std::ops::RangeFrom<usize>` | = help: the trait `PartialOrd` is not implemented for `std::ops::RangeFrom<usize>` -note: required by `std::cmp::PartialOrd::partial_cmp` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - | -LL | fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: can't compare `std::ops::RangeFull` with `std::ops::RangeFull` @@ -59,11 +44,6 @@ LL | d: RangeFull, | ^^^^^^^^^^^^ no implementation for `std::ops::RangeFull < std::ops::RangeFull` and `std::ops::RangeFull > std::ops::RangeFull` | = help: the trait `PartialOrd` is not implemented for `std::ops::RangeFull` -note: required by `std::cmp::PartialOrd::partial_cmp` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - | -LL | fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: can't compare `std::ops::RangeInclusive<usize>` with `std::ops::RangeInclusive<usize>` @@ -76,11 +56,6 @@ LL | e: RangeInclusive<usize>, | ^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeInclusive<usize> < std::ops::RangeInclusive<usize>` and `std::ops::RangeInclusive<usize> > std::ops::RangeInclusive<usize>` | = help: the trait `PartialOrd` is not implemented for `std::ops::RangeInclusive<usize>` -note: required by `std::cmp::PartialOrd::partial_cmp` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - | -LL | fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: can't compare `std::ops::RangeToInclusive<usize>` with `std::ops::RangeToInclusive<usize>` @@ -93,11 +68,6 @@ LL | f: RangeToInclusive<usize>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeToInclusive<usize> < std::ops::RangeToInclusive<usize>` and `std::ops::RangeToInclusive<usize> > std::ops::RangeToInclusive<usize>` | = help: the trait `PartialOrd` is not implemented for `std::ops::RangeToInclusive<usize>` -note: required by `std::cmp::PartialOrd::partial_cmp` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - | -LL | fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `std::ops::Range<usize>: Ord` is not satisfied @@ -109,11 +79,6 @@ LL | struct AllTheRanges { LL | a: Range<usize>, | ^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::Range<usize>` | -note: required by `std::cmp::Ord::cmp` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - | -LL | fn cmp(&self, other: &Self) -> Ordering; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `std::ops::RangeTo<usize>: Ord` is not satisfied @@ -125,11 +90,6 @@ LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] LL | b: RangeTo<usize>, | ^^^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::RangeTo<usize>` | -note: required by `std::cmp::Ord::cmp` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - | -LL | fn cmp(&self, other: &Self) -> Ordering; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `std::ops::RangeFrom<usize>: Ord` is not satisfied @@ -141,11 +101,6 @@ LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] LL | c: RangeFrom<usize>, | ^^^^^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::RangeFrom<usize>` | -note: required by `std::cmp::Ord::cmp` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - | -LL | fn cmp(&self, other: &Self) -> Ordering; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `std::ops::RangeFull: Ord` is not satisfied @@ -157,11 +112,6 @@ LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] LL | d: RangeFull, | ^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::RangeFull` | -note: required by `std::cmp::Ord::cmp` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - | -LL | fn cmp(&self, other: &Self) -> Ordering; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `std::ops::RangeInclusive<usize>: Ord` is not satisfied @@ -173,11 +123,6 @@ LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] LL | e: RangeInclusive<usize>, | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::RangeInclusive<usize>` | -note: required by `std::cmp::Ord::cmp` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - | -LL | fn cmp(&self, other: &Self) -> Ordering; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `std::ops::RangeToInclusive<usize>: Ord` is not satisfied @@ -189,11 +134,6 @@ LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] LL | f: RangeToInclusive<usize>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::RangeToInclusive<usize>` | -note: required by `std::cmp::Ord::cmp` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - | -LL | fn cmp(&self, other: &Self) -> Ordering; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 12 previous errors diff --git a/src/test/ui/reachable/expr_cast.rs b/src/test/ui/reachable/expr_cast.rs index f53bcb97e6..e8e477ea4f 100644 --- a/src/test/ui/reachable/expr_cast.rs +++ b/src/test/ui/reachable/expr_cast.rs @@ -7,6 +7,7 @@ fn a() { // the cast is unreachable: let x = {return} as !; //~ ERROR unreachable + //~| ERROR non-primitive cast } fn main() { } diff --git a/src/test/ui/reachable/expr_cast.stderr b/src/test/ui/reachable/expr_cast.stderr index 3aa15bde99..6643f1784a 100644 --- a/src/test/ui/reachable/expr_cast.stderr +++ b/src/test/ui/reachable/expr_cast.stderr @@ -13,5 +13,12 @@ note: the lint level is defined here LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error[E0605]: non-primitive cast: `()` as `!` + --> $DIR/expr_cast.rs:9:13 + | +LL | let x = {return} as !; + | ^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0605`. diff --git a/src/test/ui/reachable/unreachable-loop-patterns.rs b/src/test/ui/reachable/unreachable-loop-patterns.rs index 4de29c3c3d..e9cef5f47d 100644 --- a/src/test/ui/reachable/unreachable-loop-patterns.rs +++ b/src/test/ui/reachable/unreachable-loop-patterns.rs @@ -17,5 +17,4 @@ impl Iterator for Void { fn main() { for _ in unimplemented!() as Void {} //~^ ERROR unreachable pattern - //~^^ ERROR unreachable pattern } diff --git a/src/test/ui/reachable/unreachable-loop-patterns.stderr b/src/test/ui/reachable/unreachable-loop-patterns.stderr index 680d22862d..80ffa5d73f 100644 --- a/src/test/ui/reachable/unreachable-loop-patterns.stderr +++ b/src/test/ui/reachable/unreachable-loop-patterns.stderr @@ -10,11 +10,5 @@ note: the lint level is defined here LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ -error: unreachable pattern - --> $DIR/unreachable-loop-patterns.rs:18:14 - | -LL | for _ in unimplemented!() as Void {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/readalias.rs b/src/test/ui/readalias.rs deleted file mode 100644 index a6bf61803c..0000000000 --- a/src/test/ui/readalias.rs +++ /dev/null @@ -1,12 +0,0 @@ -// run-pass - -#![allow(dead_code)] - - - - -struct Point {x: isize, y: isize, z: isize} - -fn f(p: Point) { assert_eq!(p.z, 12); } - -pub fn main() { let x: Point = Point {x: 10, y: 11, z: 12}; f(x); } diff --git a/src/test/ui/instantiable.rs b/src/test/ui/recursion/instantiable.rs similarity index 100% rename from src/test/ui/instantiable.rs rename to src/test/ui/recursion/instantiable.rs diff --git a/src/test/ui/reexport-should-still-link.rs b/src/test/ui/reexport-should-still-link.rs deleted file mode 100644 index 913da56a18..0000000000 --- a/src/test/ui/reexport-should-still-link.rs +++ /dev/null @@ -1,10 +0,0 @@ -// run-pass -// aux-build:reexport-should-still-link.rs - -// pretty-expanded FIXME #23616 - -extern crate reexport_should_still_link as foo; - -pub fn main() { - foo::bar(); -} diff --git a/src/test/ui/init-res-into-things.rs b/src/test/ui/regions/init-res-into-things.rs similarity index 100% rename from src/test/ui/init-res-into-things.rs rename to src/test/ui/regions/init-res-into-things.rs diff --git a/src/test/ui/issues/issue-21520.rs b/src/test/ui/regions/issue-21520.rs similarity index 100% rename from src/test/ui/issues/issue-21520.rs rename to src/test/ui/regions/issue-21520.rs diff --git a/src/test/ui/issues/issue-26448-1.rs b/src/test/ui/regions/issue-26448-1.rs similarity index 100% rename from src/test/ui/issues/issue-26448-1.rs rename to src/test/ui/regions/issue-26448-1.rs diff --git a/src/test/ui/issues/issue-26448-2.rs b/src/test/ui/regions/issue-26448-2.rs similarity index 100% rename from src/test/ui/issues/issue-26448-2.rs rename to src/test/ui/regions/issue-26448-2.rs diff --git a/src/test/ui/issues/issue-26448-3.rs b/src/test/ui/regions/issue-26448-3.rs similarity index 100% rename from src/test/ui/issues/issue-26448-3.rs rename to src/test/ui/regions/issue-26448-3.rs diff --git a/src/test/ui/owned-implies-static.rs b/src/test/ui/regions/owned-implies-static.rs similarity index 100% rename from src/test/ui/owned-implies-static.rs rename to src/test/ui/regions/owned-implies-static.rs diff --git a/src/test/ui/rcvr-borrowed-to-region.rs b/src/test/ui/regions/rcvr-borrowed-to-region.rs similarity index 100% rename from src/test/ui/rcvr-borrowed-to-region.rs rename to src/test/ui/regions/rcvr-borrowed-to-region.rs diff --git a/src/test/ui/regions/regions-bounded-method-type-parameters.stderr b/src/test/ui/regions/regions-bounded-method-type-parameters.stderr index 66b61b1349..318e9d006a 100644 --- a/src/test/ui/regions/regions-bounded-method-type-parameters.stderr +++ b/src/test/ui/regions/regions-bounded-method-type-parameters.stderr @@ -4,7 +4,11 @@ error[E0477]: the type `&'a isize` does not fulfill the required lifetime LL | Foo.some_method::<&'a isize>(); | ^^^^^^^^^^^ | - = note: type must satisfy the static lifetime +note: type must satisfy the static lifetime as required by this binding + --> $DIR/regions-bounded-method-type-parameters.rs:8:22 + | +LL | fn some_method<A:'static>(self) { } + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/regions/regions-close-object-into-object-5.stderr b/src/test/ui/regions/regions-close-object-into-object-5.stderr index 83f8d20b9e..512a7ab35f 100644 --- a/src/test/ui/regions/regions-close-object-into-object-5.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-5.stderr @@ -29,7 +29,13 @@ LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> { | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // oh dear! LL | Box::new(B(&*v)) as Box<dyn X> - | ^ ...so that the type `T` will meet its required lifetime bounds + | ^ ...so that the type `T` will meet its required lifetime bounds... + | +note: ...that is required by this bound + --> $DIR/regions-close-object-into-object-5.rs:9:17 + | +LL | struct B<'a, T: 'a>(&'a (A<T> + 'a)); + | ^^ error[E0310]: the parameter type `T` may not live long enough --> $DIR/regions-close-object-into-object-5.rs:17:14 diff --git a/src/test/ui/regions/regions-static-bound.ll.nll.stderr b/src/test/ui/regions/regions-static-bound.ll.nll.stderr deleted file mode 100644 index d6cec03e0f..0000000000 --- a/src/test/ui/regions/regions-static-bound.ll.nll.stderr +++ /dev/null @@ -1,28 +0,0 @@ -error: lifetime may not live long enough - --> $DIR/regions-static-bound.rs:9:5 - | -LL | fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a { - | -- lifetime `'a` defined here -LL | t //[ll]~ ERROR E0312 - | ^ returning this value requires that `'a` must outlive `'static` - -error[E0621]: explicit lifetime required in the type of `u` - --> $DIR/regions-static-bound.rs:14:5 - | -LL | fn error(u: &(), v: &()) { - | --- help: add explicit lifetime `'static` to the type of `u`: `&'static ()` -LL | static_id(&u); //[ll]~ ERROR explicit lifetime required in the type of `u` [E0621] - | ^^^^^^^^^^^^^ lifetime `'static` required - -error[E0621]: explicit lifetime required in the type of `v` - --> $DIR/regions-static-bound.rs:16:5 - | -LL | fn error(u: &(), v: &()) { - | --- help: add explicit lifetime `'static` to the type of `v`: `&'static ()` -... -LL | static_id_indirect(&v); //[ll]~ ERROR explicit lifetime required in the type of `v` [E0621] - | ^^^^^^^^^^^^^^^^^^^^^^ lifetime `'static` required - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0621`. diff --git a/src/test/ui/regions/regions-static-bound.migrate.nll.stderr b/src/test/ui/regions/regions-static-bound.migrate.nll.stderr deleted file mode 100644 index a280c6f0a0..0000000000 --- a/src/test/ui/regions/regions-static-bound.migrate.nll.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error: lifetime may not live long enough - --> $DIR/regions-static-bound.rs:9:5 - | -LL | fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a { - | -- lifetime `'a` defined here -LL | t - | ^ returning this value requires that `'a` must outlive `'static` - -error[E0621]: explicit lifetime required in the type of `u` - --> $DIR/regions-static-bound.rs:14:5 - | -LL | static_id(&u); - | ^^^^^^^^^^^^^ lifetime `'static` required - -error[E0621]: explicit lifetime required in the type of `v` - --> $DIR/regions-static-bound.rs:16:5 - | -LL | static_id_indirect(&v); - | ^^^^^^^^^^^^^^^^^^^^^^ lifetime `'static` required - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0621`. diff --git a/src/test/ui/regions/regions-static-bound.migrate.stderr b/src/test/ui/regions/regions-static-bound.migrate.stderr deleted file mode 100644 index 8f11e14822..0000000000 --- a/src/test/ui/regions/regions-static-bound.migrate.stderr +++ /dev/null @@ -1,29 +0,0 @@ -error[E0312]: lifetime of reference outlives lifetime of borrowed content... - --> $DIR/regions-static-bound.rs:9:5 - | -LL | t - | ^ - | - = note: ...the reference is valid for the static lifetime... -note: ...but the borrowed content is only valid for the lifetime `'a` as defined here - --> $DIR/regions-static-bound.rs:8:24 - | -LL | fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a { - | ^^ - -error[E0621]: explicit lifetime required in the type of `u` - --> $DIR/regions-static-bound.rs:14:5 - | -LL | static_id(&u); - | ^^^^^^^^^ lifetime `'static` required - -error[E0621]: explicit lifetime required in the type of `v` - --> $DIR/regions-static-bound.rs:16:5 - | -LL | static_id_indirect(&v); - | ^^^^^^^^^^^^^^^^^^ lifetime `'static` required - -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0312, E0621. -For more information about an error, try `rustc --explain E0312`. diff --git a/src/test/ui/regions/regions-static-bound.nll.stderr b/src/test/ui/regions/regions-static-bound.nll.stderr index a280c6f0a0..699638c7ef 100644 --- a/src/test/ui/regions/regions-static-bound.nll.stderr +++ b/src/test/ui/regions/regions-static-bound.nll.stderr @@ -1,23 +1,38 @@ error: lifetime may not live long enough - --> $DIR/regions-static-bound.rs:9:5 + --> $DIR/regions-static-bound.rs:6:5 | LL | fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a { | -- lifetime `'a` defined here LL | t | ^ returning this value requires that `'a` must outlive `'static` -error[E0621]: explicit lifetime required in the type of `u` - --> $DIR/regions-static-bound.rs:14:5 +error[E0521]: borrowed data escapes outside of function + --> $DIR/regions-static-bound.rs:10:5 | +LL | fn error(u: &(), v: &()) { + | - - let's call the lifetime of this reference `'1` + | | + | `u` is a reference that is only valid in the function body LL | static_id(&u); - | ^^^^^^^^^^^^^ lifetime `'static` required + | ^^^^^^^^^^^^^ + | | + | `u` escapes the function body here + | argument requires that `'1` must outlive `'static` -error[E0621]: explicit lifetime required in the type of `v` - --> $DIR/regions-static-bound.rs:16:5 +error[E0521]: borrowed data escapes outside of function + --> $DIR/regions-static-bound.rs:11:5 | +LL | fn error(u: &(), v: &()) { + | - - let's call the lifetime of this reference `'2` + | | + | `v` is a reference that is only valid in the function body +LL | static_id(&u); LL | static_id_indirect(&v); - | ^^^^^^^^^^^^^^^^^^^^^^ lifetime `'static` required + | ^^^^^^^^^^^^^^^^^^^^^^ + | | + | `v` escapes the function body here + | argument requires that `'2` must outlive `'static` error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0621`. +For more information about this error, try `rustc --explain E0521`. diff --git a/src/test/ui/regions/regions-static-bound.rs b/src/test/ui/regions/regions-static-bound.rs index 1db54881d3..a977a8b36d 100644 --- a/src/test/ui/regions/regions-static-bound.rs +++ b/src/test/ui/regions/regions-static-bound.rs @@ -1,20 +1,14 @@ -// revisions: migrate nll -//[nll] compile-flags:-Zborrowck=mir - fn static_id<'a,'b>(t: &'a ()) -> &'static () where 'a: 'static { t } fn static_id_indirect<'a,'b>(t: &'a ()) -> &'static () where 'a: 'b, 'b: 'static { t } fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a { - t //[migrate]~ ERROR E0312 - //[nll]~^ ERROR lifetime may not live long enough + t //~ ERROR E0312 } fn error(u: &(), v: &()) { - static_id(&u); //[migrate]~ ERROR explicit lifetime required in the type of `u` [E0621] - //[nll]~^ ERROR explicit lifetime required in the type of `u` [E0621] - static_id_indirect(&v); //[migrate]~ ERROR explicit lifetime required in the type of `v` [E0621] - //[nll]~^ ERROR explicit lifetime required in the type of `v` [E0621] + static_id(&u); //~ ERROR `u` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement [E0759] + static_id_indirect(&v); //~ ERROR `v` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement [E0759] } fn main() {} diff --git a/src/test/ui/regions/regions-static-bound.stderr b/src/test/ui/regions/regions-static-bound.stderr new file mode 100644 index 0000000000..51fe16ca9d --- /dev/null +++ b/src/test/ui/regions/regions-static-bound.stderr @@ -0,0 +1,46 @@ +error[E0312]: lifetime of reference outlives lifetime of borrowed content... + --> $DIR/regions-static-bound.rs:6:5 + | +LL | t + | ^ + | + = note: ...the reference is valid for the static lifetime... +note: ...but the borrowed content is only valid for the lifetime `'a` as defined here + --> $DIR/regions-static-bound.rs:5:24 + | +LL | fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a { + | ^^ + +error[E0759]: `u` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/regions-static-bound.rs:10:5 + | +LL | fn error(u: &(), v: &()) { + | --- this data with an anonymous lifetime `'_`... +LL | static_id(&u); + | ^^^^^^^^^ -- ...is captured here... + | +note: ...and is required to live as long as `'static` here + --> $DIR/regions-static-bound.rs:10:5 + | +LL | static_id(&u); + | ^^^^^^^^^ + +error[E0759]: `v` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/regions-static-bound.rs:11:5 + | +LL | fn error(u: &(), v: &()) { + | --- this data with an anonymous lifetime `'_`... +LL | static_id(&u); +LL | static_id_indirect(&v); + | ^^^^^^^^^^^^^^^^^^ -- ...is captured here... + | +note: ...and is required to live as long as `'static` here + --> $DIR/regions-static-bound.rs:11:5 + | +LL | static_id_indirect(&v); + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0312, E0759. +For more information about an error, try `rustc --explain E0312`. diff --git a/src/test/ui/wf-bound-region-in-object-type.rs b/src/test/ui/regions/wf-bound-region-in-object-type.rs similarity index 100% rename from src/test/ui/wf-bound-region-in-object-type.rs rename to src/test/ui/regions/wf-bound-region-in-object-type.rs diff --git a/src/test/ui/attr-usage-repr.rs b/src/test/ui/repr/attr-usage-repr.rs similarity index 100% rename from src/test/ui/attr-usage-repr.rs rename to src/test/ui/repr/attr-usage-repr.rs diff --git a/src/test/ui/attr-usage-repr.stderr b/src/test/ui/repr/attr-usage-repr.stderr similarity index 100% rename from src/test/ui/attr-usage-repr.stderr rename to src/test/ui/repr/attr-usage-repr.stderr diff --git a/src/test/ui/repr.rs b/src/test/ui/repr/repr.rs similarity index 100% rename from src/test/ui/repr.rs rename to src/test/ui/repr/repr.rs diff --git a/src/test/ui/repr.stderr b/src/test/ui/repr/repr.stderr similarity index 100% rename from src/test/ui/repr.stderr rename to src/test/ui/repr/repr.stderr diff --git a/src/test/ui/auxiliary/blind-item-mixed-crate-use-item-foo.rs b/src/test/ui/resolve/auxiliary/blind-item-mixed-crate-use-item-foo.rs similarity index 100% rename from src/test/ui/auxiliary/blind-item-mixed-crate-use-item-foo.rs rename to src/test/ui/resolve/auxiliary/blind-item-mixed-crate-use-item-foo.rs diff --git a/src/test/ui/auxiliary/blind-item-mixed-crate-use-item-foo2.rs b/src/test/ui/resolve/auxiliary/blind-item-mixed-crate-use-item-foo2.rs similarity index 100% rename from src/test/ui/auxiliary/blind-item-mixed-crate-use-item-foo2.rs rename to src/test/ui/resolve/auxiliary/blind-item-mixed-crate-use-item-foo2.rs diff --git a/src/test/ui/blind-item-mixed-crate-use-item.rs b/src/test/ui/resolve/blind-item-mixed-crate-use-item.rs similarity index 100% rename from src/test/ui/blind-item-mixed-crate-use-item.rs rename to src/test/ui/resolve/blind-item-mixed-crate-use-item.rs diff --git a/src/test/ui/blind-item-mixed-use-item.rs b/src/test/ui/resolve/blind-item-mixed-use-item.rs similarity index 100% rename from src/test/ui/blind-item-mixed-use-item.rs rename to src/test/ui/resolve/blind-item-mixed-use-item.rs diff --git a/src/test/ui/crate-in-paths.rs b/src/test/ui/resolve/crate-in-paths.rs similarity index 100% rename from src/test/ui/crate-in-paths.rs rename to src/test/ui/resolve/crate-in-paths.rs diff --git a/src/test/ui/crate-in-paths.stderr b/src/test/ui/resolve/crate-in-paths.stderr similarity index 100% rename from src/test/ui/crate-in-paths.stderr rename to src/test/ui/resolve/crate-in-paths.stderr diff --git a/src/test/ui/editions-crate-root-2015.rs b/src/test/ui/resolve/editions-crate-root-2015.rs similarity index 100% rename from src/test/ui/editions-crate-root-2015.rs rename to src/test/ui/resolve/editions-crate-root-2015.rs diff --git a/src/test/ui/editions-crate-root-2015.stderr b/src/test/ui/resolve/editions-crate-root-2015.stderr similarity index 100% rename from src/test/ui/editions-crate-root-2015.stderr rename to src/test/ui/resolve/editions-crate-root-2015.stderr diff --git a/src/test/ui/editions-crate-root-2018.rs b/src/test/ui/resolve/editions-crate-root-2018.rs similarity index 100% rename from src/test/ui/editions-crate-root-2018.rs rename to src/test/ui/resolve/editions-crate-root-2018.rs diff --git a/src/test/ui/editions-crate-root-2018.stderr b/src/test/ui/resolve/editions-crate-root-2018.stderr similarity index 100% rename from src/test/ui/editions-crate-root-2018.stderr rename to src/test/ui/resolve/editions-crate-root-2018.stderr diff --git a/src/test/ui/enums-pats-not-idents.rs b/src/test/ui/resolve/enums-pats-not-idents.rs similarity index 100% rename from src/test/ui/enums-pats-not-idents.rs rename to src/test/ui/resolve/enums-pats-not-idents.rs diff --git a/src/test/ui/enums-pats-not-idents.stderr b/src/test/ui/resolve/enums-pats-not-idents.stderr similarity index 100% rename from src/test/ui/enums-pats-not-idents.stderr rename to src/test/ui/resolve/enums-pats-not-idents.stderr diff --git a/src/test/ui/export-fully-qualified.rs b/src/test/ui/resolve/export-fully-qualified.rs similarity index 100% rename from src/test/ui/export-fully-qualified.rs rename to src/test/ui/resolve/export-fully-qualified.rs diff --git a/src/test/ui/export-fully-qualified.stderr b/src/test/ui/resolve/export-fully-qualified.stderr similarity index 100% rename from src/test/ui/export-fully-qualified.stderr rename to src/test/ui/resolve/export-fully-qualified.stderr diff --git a/src/test/ui/issues/issue-12796.rs b/src/test/ui/resolve/issue-12796.rs similarity index 100% rename from src/test/ui/issues/issue-12796.rs rename to src/test/ui/resolve/issue-12796.rs diff --git a/src/test/ui/issues/issue-12796.stderr b/src/test/ui/resolve/issue-12796.stderr similarity index 100% rename from src/test/ui/issues/issue-12796.stderr rename to src/test/ui/resolve/issue-12796.stderr diff --git a/src/test/ui/issues/issue-23716.rs b/src/test/ui/resolve/issue-23716.rs similarity index 100% rename from src/test/ui/issues/issue-23716.rs rename to src/test/ui/resolve/issue-23716.rs diff --git a/src/test/ui/issues/issue-23716.stderr b/src/test/ui/resolve/issue-23716.stderr similarity index 100% rename from src/test/ui/issues/issue-23716.stderr rename to src/test/ui/resolve/issue-23716.stderr diff --git a/src/test/ui/issues/issue-3021-c.rs b/src/test/ui/resolve/issue-3021-c.rs similarity index 100% rename from src/test/ui/issues/issue-3021-c.rs rename to src/test/ui/resolve/issue-3021-c.rs diff --git a/src/test/ui/issues/issue-3021-c.stderr b/src/test/ui/resolve/issue-3021-c.stderr similarity index 100% rename from src/test/ui/issues/issue-3021-c.stderr rename to src/test/ui/resolve/issue-3021-c.stderr diff --git a/src/test/ui/issues/issue-3021.rs b/src/test/ui/resolve/issue-3021.rs similarity index 100% rename from src/test/ui/issues/issue-3021.rs rename to src/test/ui/resolve/issue-3021.rs diff --git a/src/test/ui/issues/issue-3021.stderr b/src/test/ui/resolve/issue-3021.stderr similarity index 100% rename from src/test/ui/issues/issue-3021.stderr rename to src/test/ui/resolve/issue-3021.stderr diff --git a/src/test/ui/issues/issue-31845.rs b/src/test/ui/resolve/issue-31845.rs similarity index 100% rename from src/test/ui/issues/issue-31845.rs rename to src/test/ui/resolve/issue-31845.rs diff --git a/src/test/ui/issues/issue-31845.stderr b/src/test/ui/resolve/issue-31845.stderr similarity index 100% rename from src/test/ui/issues/issue-31845.stderr rename to src/test/ui/resolve/issue-31845.stderr diff --git a/src/test/ui/issues/issue-5099.rs b/src/test/ui/resolve/issue-5099.rs similarity index 100% rename from src/test/ui/issues/issue-5099.rs rename to src/test/ui/resolve/issue-5099.rs diff --git a/src/test/ui/issues/issue-5099.stderr b/src/test/ui/resolve/issue-5099.stderr similarity index 100% rename from src/test/ui/issues/issue-5099.stderr rename to src/test/ui/resolve/issue-5099.stderr diff --git a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr index 4025b5030d..50446bb659 100644 --- a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr +++ b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr @@ -58,7 +58,7 @@ LL | async fn associated(); | = note: while checking the return type of the `async fn` = note: expected fn pointer `fn()` - found fn pointer `fn() -> impl Future` + found fn pointer `fn() -> impl Future<Output = ()>` error: aborting due to 6 previous errors diff --git a/src/test/ui/resolve/issue-90113.rs b/src/test/ui/resolve/issue-90113.rs new file mode 100644 index 0000000000..f6658b45ed --- /dev/null +++ b/src/test/ui/resolve/issue-90113.rs @@ -0,0 +1,21 @@ +mod list { + pub use self::List::Cons; + + pub enum List<T> { + Cons(T, Box<List<T>>), + } +} + +mod alias { + use crate::list::List; + + pub type Foo = List<String>; +} + +fn foo(l: crate::alias::Foo) { + match l { + Cons(..) => {} //~ ERROR: cannot find tuple struct or tuple variant `Cons` in this scope + } +} + +fn main() {} diff --git a/src/test/ui/resolve/issue-90113.stderr b/src/test/ui/resolve/issue-90113.stderr new file mode 100644 index 0000000000..1b78720571 --- /dev/null +++ b/src/test/ui/resolve/issue-90113.stderr @@ -0,0 +1,14 @@ +error[E0531]: cannot find tuple struct or tuple variant `Cons` in this scope + --> $DIR/issue-90113.rs:17:9 + | +LL | Cons(..) => {} + | ^^^^ not found in this scope + | +help: consider importing this tuple variant + | +LL | use list::List::Cons; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0531`. diff --git a/src/test/ui/no-implicit-prelude-nested.rs b/src/test/ui/resolve/no-implicit-prelude-nested.rs similarity index 100% rename from src/test/ui/no-implicit-prelude-nested.rs rename to src/test/ui/resolve/no-implicit-prelude-nested.rs diff --git a/src/test/ui/no-implicit-prelude-nested.stderr b/src/test/ui/resolve/no-implicit-prelude-nested.stderr similarity index 100% rename from src/test/ui/no-implicit-prelude-nested.stderr rename to src/test/ui/resolve/no-implicit-prelude-nested.stderr diff --git a/src/test/ui/no-std-1.rs b/src/test/ui/resolve/no-std-1.rs similarity index 100% rename from src/test/ui/no-std-1.rs rename to src/test/ui/resolve/no-std-1.rs diff --git a/src/test/ui/no-std-2.rs b/src/test/ui/resolve/no-std-2.rs similarity index 100% rename from src/test/ui/no-std-2.rs rename to src/test/ui/resolve/no-std-2.rs diff --git a/src/test/ui/no-std-3.rs b/src/test/ui/resolve/no-std-3.rs similarity index 100% rename from src/test/ui/no-std-3.rs rename to src/test/ui/resolve/no-std-3.rs diff --git a/src/test/ui/pathless-extern-ok.rs b/src/test/ui/resolve/pathless-extern-ok.rs similarity index 100% rename from src/test/ui/pathless-extern-ok.rs rename to src/test/ui/resolve/pathless-extern-ok.rs diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr index ff72b0b563..c93ba915ef 100644 --- a/src/test/ui/resolve/privacy-enum-ctor.stderr +++ b/src/test/ui/resolve/privacy-enum-ctor.stderr @@ -338,10 +338,11 @@ LL | let _ = Z::Unit(); | | | call expression requires function | -help: `Z::Unit` is a unit variant, you need to write it without the parenthesis +help: `Z::Unit` is a unit variant, you need to write it without the parentheses | -LL | let _ = Z::Unit; - | ~~~~~~~ +LL - let _ = Z::Unit(); +LL + let _ = Z::Unit; + | error[E0308]: mismatched types --> $DIR/privacy-enum-ctor.rs:43:16 @@ -372,10 +373,11 @@ LL | let _: E = m::E::Unit(); | | | call expression requires function | -help: `m::E::Unit` is a unit variant, you need to write it without the parenthesis +help: `m::E::Unit` is a unit variant, you need to write it without the parentheses | -LL | let _: E = m::E::Unit; - | ~~~~~~~~~~ +LL - let _: E = m::E::Unit(); +LL + let _: E = m::E::Unit; + | error[E0308]: mismatched types --> $DIR/privacy-enum-ctor.rs:51:16 @@ -406,10 +408,11 @@ LL | let _: E = E::Unit(); | | | call expression requires function | -help: `E::Unit` is a unit variant, you need to write it without the parenthesis +help: `E::Unit` is a unit variant, you need to write it without the parentheses | -LL | let _: E = E::Unit; - | ~~~~~~~ +LL - let _: E = E::Unit(); +LL + let _: E = E::Unit; + | error: aborting due to 23 previous errors diff --git a/src/test/ui/resolve-issue-2428.rs b/src/test/ui/resolve/resolve-issue-2428.rs similarity index 100% rename from src/test/ui/resolve-issue-2428.rs rename to src/test/ui/resolve/resolve-issue-2428.rs diff --git a/src/test/ui/ret-none.rs b/src/test/ui/ret-none.rs deleted file mode 100644 index d595506e33..0000000000 --- a/src/test/ui/ret-none.rs +++ /dev/null @@ -1,13 +0,0 @@ -// run-pass - -#![allow(non_camel_case_types)] -#![allow(dead_code)] - - -// pretty-expanded FIXME #23616 - -enum option<T> { none, some(T), } - -fn f<T>() -> option<T> { return option::none; } - -pub fn main() { f::<isize>(); } diff --git a/src/test/ui/issues/issue-6804.rs b/src/test/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.rs similarity index 100% rename from src/test/ui/issues/issue-6804.rs rename to src/test/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.rs diff --git a/src/test/ui/issues/issue-6804.stderr b/src/test/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr similarity index 100% rename from src/test/ui/issues/issue-6804.stderr rename to src/test/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr index 5ec4352919..3fc5cb1b07 100644 --- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr +++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr @@ -16,7 +16,7 @@ LL | if &let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:33:9 @@ -25,7 +25,7 @@ LL | if !let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:34:9 @@ -34,7 +34,7 @@ LL | if *let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:36:9 @@ -43,7 +43,7 @@ LL | if -let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:44:9 @@ -52,7 +52,7 @@ LL | if (let 0 = 0)? {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:48:16 @@ -61,7 +61,7 @@ LL | if true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:49:17 @@ -70,7 +70,7 @@ LL | if (true || let 0 = 0) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:50:25 @@ -79,7 +79,7 @@ LL | if true && (true || let 0 = 0) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:51:25 @@ -88,7 +88,7 @@ LL | if true || (true && let 0 = 0) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:54:12 @@ -97,7 +97,7 @@ LL | if x = let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:57:15 @@ -106,7 +106,7 @@ LL | if true..(let 0 = 0) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:59:11 @@ -115,7 +115,7 @@ LL | if ..(let 0 = 0) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:61:9 @@ -124,7 +124,7 @@ LL | if (let 0 = 0).. {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:65:8 @@ -133,7 +133,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:69:8 @@ -142,7 +142,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:76:8 @@ -151,7 +151,7 @@ LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:84:8 @@ -160,7 +160,7 @@ LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:90:19 @@ -169,7 +169,7 @@ LL | if let true = let true = true {} | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:94:12 @@ -178,7 +178,7 @@ LL | while &let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:97:12 @@ -187,7 +187,7 @@ LL | while !let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:98:12 @@ -196,7 +196,7 @@ LL | while *let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:100:12 @@ -205,7 +205,7 @@ LL | while -let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:108:12 @@ -214,7 +214,7 @@ LL | while (let 0 = 0)? {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:112:19 @@ -223,7 +223,7 @@ LL | while true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:113:20 @@ -232,7 +232,7 @@ LL | while (true || let 0 = 0) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:114:28 @@ -241,7 +241,7 @@ LL | while true && (true || let 0 = 0) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:115:28 @@ -250,7 +250,7 @@ LL | while true || (true && let 0 = 0) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:118:15 @@ -259,7 +259,7 @@ LL | while x = let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:121:18 @@ -268,7 +268,7 @@ LL | while true..(let 0 = 0) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:123:14 @@ -277,7 +277,7 @@ LL | while ..(let 0 = 0) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:125:12 @@ -286,7 +286,7 @@ LL | while (let 0 = 0).. {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:129:11 @@ -295,7 +295,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:133:11 @@ -304,7 +304,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:140:11 @@ -313,7 +313,7 @@ LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:148:11 @@ -322,7 +322,7 @@ LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:154:22 @@ -331,7 +331,7 @@ LL | while let true = let true = true {} | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:168:6 @@ -340,7 +340,7 @@ LL | &let 0 = 0; | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:170:6 @@ -349,7 +349,7 @@ LL | !let 0 = 0; | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:171:6 @@ -358,7 +358,7 @@ LL | *let 0 = 0; | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:173:6 @@ -367,7 +367,7 @@ LL | -let 0 = 0; | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:181:6 @@ -376,7 +376,7 @@ LL | (let 0 = 0)?; | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:185:13 @@ -385,7 +385,7 @@ LL | true || let 0 = 0; | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:186:14 @@ -394,7 +394,7 @@ LL | (true || let 0 = 0); | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:187:22 @@ -403,7 +403,7 @@ LL | true && (true || let 0 = 0); | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:190:9 @@ -412,7 +412,7 @@ LL | x = let 0 = 0; | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:192:12 @@ -421,7 +421,7 @@ LL | true..(let 0 = 0); | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:193:8 @@ -430,7 +430,7 @@ LL | ..(let 0 = 0); | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:194:6 @@ -439,7 +439,7 @@ LL | (let 0 = 0)..; | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:196:6 @@ -448,7 +448,7 @@ LL | (let Range { start: _, end: _ } = true..true || false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:200:6 @@ -457,7 +457,7 @@ LL | (let true = let true = true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:204:6 @@ -466,7 +466,7 @@ LL | &let 0 = 0 | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:215:17 @@ -475,7 +475,7 @@ LL | true && let 1 = 1 | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:219:17 @@ -484,7 +484,7 @@ LL | true && let 1 = 1 | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:223:17 @@ -493,7 +493,7 @@ LL | true && let 1 = 1 | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:233:17 @@ -502,7 +502,7 @@ LL | true && let 1 = 1 | ^^^^^^^^^ | = note: only supported directly in conditions of `if`- and `while`-expressions - = note: as well as when nested within `&&` and parenthesis in those conditions + = note: as well as when nested within `&&` and parentheses in those conditions warning: the feature `let_chains` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/disallowed-positions.rs:20:12 @@ -544,11 +544,6 @@ LL | if (let 0 = 0)? {} | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool` | = help: the trait `Try` is not implemented for `bool` -note: required by `branch` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn branch(self) -> ControlFlow<Self::Residual, Self::Output>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) --> $DIR/disallowed-positions.rs:44:19 @@ -566,11 +561,6 @@ LL | | } | |_- this function should return `Result` or `Option` to accept `?` | = help: the trait `FromResidual<_>` is not implemented for `()` -note: required by `from_residual` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn from_residual(residual: R) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:54:8 @@ -710,11 +700,6 @@ LL | if let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` | = help: the trait `Try` is not implemented for `{integer}` -note: required by `branch` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn branch(self) -> ControlFlow<Self::Residual, Self::Output>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:94:11 @@ -747,11 +732,6 @@ LL | while (let 0 = 0)? {} | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool` | = help: the trait `Try` is not implemented for `bool` -note: required by `branch` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn branch(self) -> ControlFlow<Self::Residual, Self::Output>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) --> $DIR/disallowed-positions.rs:108:22 @@ -769,11 +749,6 @@ LL | | } | |_- this function should return `Result` or `Option` to accept `?` | = help: the trait `FromResidual<_>` is not implemented for `()` -note: required by `from_residual` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn from_residual(residual: R) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:118:11 @@ -913,11 +888,6 @@ LL | while let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` | = help: the trait `Try` is not implemented for `{integer}` -note: required by `branch` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn branch(self) -> ControlFlow<Self::Residual, Self::Output>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0614]: type `bool` cannot be dereferenced --> $DIR/disallowed-positions.rs:171:5 @@ -938,11 +908,6 @@ LL | (let 0 = 0)?; | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool` | = help: the trait `Try` is not implemented for `bool` -note: required by `branch` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn branch(self) -> ControlFlow<Self::Residual, Self::Output>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) --> $DIR/disallowed-positions.rs:181:16 @@ -960,11 +925,6 @@ LL | | } | |_- this function should return `Result` or `Option` to accept `?` | = help: the trait `FromResidual<_>` is not implemented for `()` -note: required by `from_residual` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn from_residual(residual: R) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:196:10 @@ -993,11 +953,6 @@ LL | let 0 = 0?; | ^^ the `?` operator cannot be applied to type `{integer}` | = help: the trait `Try` is not implemented for `{integer}` -note: required by `branch` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn branch(self) -> ControlFlow<Self::Residual, Self::Output>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 103 previous errors; 1 warning emitted diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-multiple.rs b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-multiple.rs index 9874121267..0ab994ecd4 100644 --- a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-multiple.rs +++ b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-multiple.rs @@ -4,9 +4,8 @@ #[link(name = "foo", kind = "raw-dylib")] extern "C" { - #[link_ordinal(1)] + #[link_ordinal(1)] //~ ERROR multiple `link_ordinal` attributes #[link_ordinal(2)] - //~^ ERROR multiple `link_ordinal` attributes on a single definition fn foo(); } diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-multiple.stderr b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-multiple.stderr index a79fb2de94..4772533ab2 100644 --- a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-multiple.stderr +++ b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-multiple.stderr @@ -7,7 +7,13 @@ LL | #![feature(raw_dylib)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information -error: multiple `link_ordinal` attributes on a single definition +error: multiple `link_ordinal` attributes + --> $DIR/link-ordinal-multiple.rs:7:5 + | +LL | #[link_ordinal(1)] + | ^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here --> $DIR/link-ordinal-multiple.rs:8:5 | LL | #[link_ordinal(2)] diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs b/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs index 4b2f049b99..961968186d 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs @@ -2,9 +2,8 @@ pub struct Int(i32); -impl const std::ops::Add for i32 { - //~^ ERROR conflicting implementations of trait - //~| ERROR only traits defined in the current crate can be implemented for arbitrary types +impl const std::ops::Add for i32 { //~ ERROR type annotations needed + //~^ ERROR only traits defined in the current crate can be implemented for arbitrary types type Output = Self; fn add(self, rhs: Self) -> Self { @@ -12,7 +11,7 @@ impl const std::ops::Add for i32 { } } -impl std::ops::Add for Int { +impl std::ops::Add for Int { //~ ERROR type annotations needed type Output = Self; fn add(self, rhs: Self) -> Self { @@ -20,7 +19,7 @@ impl std::ops::Add for Int { } } -impl const std::ops::Add for Int { +impl const std::ops::Add for Int { //~ ERROR type annotations needed //~^ ERROR conflicting implementations of trait type Output = Self; 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 a0960a21d4..154a6a35a4 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,14 +1,17 @@ -error[E0119]: conflicting implementations of trait `std::ops::Add` for type `i32` +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types --> $DIR/const-and-non-const-impl.rs:5:1 | LL | impl const std::ops::Add for i32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^-------------^^^^^--- + | | | | + | | | `i32` is not defined in the current crate + | | `i32` is not defined in the current crate + | impl doesn't use only types from inside the current crate | - = note: conflicting implementation in crate `core`: - - impl Add for i32; + = note: define and implement a trait or new type instead error[E0119]: conflicting implementations of trait `std::ops::Add` for type `Int` - --> $DIR/const-and-non-const-impl.rs:23:1 + --> $DIR/const-and-non-const-impl.rs:22:1 | LL | impl std::ops::Add for Int { | -------------------------- first implementation here @@ -16,19 +19,50 @@ LL | impl std::ops::Add for Int { LL | impl const std::ops::Add for Int { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Int` -error[E0117]: only traits defined in the current crate can be implemented for arbitrary types +error[E0283]: type annotations needed + --> $DIR/const-and-non-const-impl.rs:5:12 + | +LL | impl const std::ops::Add for i32 { + | ^^^^^^^^^^^^^ cannot infer type for type `i32` + | +note: multiple `impl`s satisfying `i32: Add` found --> $DIR/const-and-non-const-impl.rs:5:1 | LL | impl const std::ops::Add for i32 { - | ^^^^^^^^^^^-------------^^^^^--- - | | | | - | | | `i32` is not defined in the current crate - | | `i32` is not defined in the current crate - | impl doesn't use only types from inside the current crate + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: and another `impl` found in the `core` crate: `impl Add for i32;` + +error[E0283]: type annotations needed + --> $DIR/const-and-non-const-impl.rs:14:6 | - = note: define and implement a trait or new type instead +LL | impl std::ops::Add for Int { + | ^^^^^^^^^^^^^ cannot infer type for struct `Int` + | +note: multiple `impl`s satisfying `Int: Add` found + --> $DIR/const-and-non-const-impl.rs:14:1 + | +LL | impl std::ops::Add for Int { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl const std::ops::Add for Int { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0283]: type annotations needed + --> $DIR/const-and-non-const-impl.rs:22:12 + | +LL | impl const std::ops::Add for Int { + | ^^^^^^^^^^^^^ cannot infer type for struct `Int` + | +note: multiple `impl`s satisfying `Int: Add` found + --> $DIR/const-and-non-const-impl.rs:14:1 + | +LL | impl std::ops::Add for Int { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl const std::ops::Add for Int { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0117, E0119. +Some errors have detailed explanations: E0117, E0119, E0283. For more information about an error, try `rustc --explain E0117`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/const-drop-bound.rs new file mode 100644 index 0000000000..83fa32bf09 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-bound.rs @@ -0,0 +1,20 @@ +// check-pass + +#![feature(const_trait_impl)] +#![feature(const_fn_trait_bound)] +#![feature(const_precise_live_drops)] + +const fn foo<T, E>(res: Result<T, E>) -> Option<T> where E: ~const Drop { + match res { + Ok(t) => Some(t), + Err(_e) => None, + } +} + +pub struct Foo<T>(T); + +const fn baz<T: ~const Drop, E: ~const Drop>(res: Result<Foo<T>, Foo<E>>) -> Option<Foo<T>> { + foo(res) +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr index 34cd1d2b10..04c21101e7 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr @@ -42,18 +42,15 @@ error[E0277]: the trait bound `NonTrivialDrop: A` is not satisfied LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `A` is not implemented for `NonTrivialDrop` | -note: required by `ConstDropImplWithBounds` - --> $DIR/const-drop-fail.rs:27:1 +note: required by a bound in `ConstDropImplWithBounds` + --> $DIR/const-drop-fail.rs:27:35 | LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ required by this bound in `ConstDropImplWithBounds` error[E0277]: the trait bound `NonTrivialDrop: A` is not satisfied --> $DIR/const-drop-fail.rs:49:5 | -LL | const _: () = check($exp); - | ----- required by a bound introduced by this call -... LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `A` is not implemented for `NonTrivialDrop` | diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr index 34cd1d2b10..04c21101e7 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr @@ -42,18 +42,15 @@ error[E0277]: the trait bound `NonTrivialDrop: A` is not satisfied LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `A` is not implemented for `NonTrivialDrop` | -note: required by `ConstDropImplWithBounds` - --> $DIR/const-drop-fail.rs:27:1 +note: required by a bound in `ConstDropImplWithBounds` + --> $DIR/const-drop-fail.rs:27:35 | LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ required by this bound in `ConstDropImplWithBounds` error[E0277]: the trait bound `NonTrivialDrop: A` is not satisfied --> $DIR/const-drop-fail.rs:49:5 | -LL | const _: () = check($exp); - | ----- required by a bound introduced by this call -... LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `A` is not implemented for `NonTrivialDrop` | diff --git a/src/test/ui/rfc-2632-const-trait-impl/trait-default-body-stability.rs b/src/test/ui/rfc-2632-const-trait-impl/trait-default-body-stability.rs new file mode 100644 index 0000000000..cbfdf89b7b --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/trait-default-body-stability.rs @@ -0,0 +1,51 @@ +// check-pass + +#![feature(staged_api)] +#![feature(const_trait_impl)] +#![feature(const_fn_trait_bound)] +#![feature(const_t_try)] +#![feature(const_try)] +#![feature(try_trait_v2)] + +#![stable(feature = "foo", since = "1.0")] + +use std::ops::{ControlFlow, FromResidual, Try}; + +#[stable(feature = "foo", since = "1.0")] +pub struct T; + +#[stable(feature = "foo", since = "1.0")] +#[rustc_const_unstable(feature = "const_t_try", issue = "none")] +impl const Try for T { + type Output = T; + type Residual = T; + + fn from_output(t: T) -> T { + t + } + + fn branch(self) -> ControlFlow<T, T> { + ControlFlow::Continue(self) + } +} + +#[stable(feature = "foo", since = "1.0")] +#[rustc_const_unstable(feature = "const_t_try", issue = "none")] +impl const FromResidual for T { + fn from_residual(t: T) -> T { + t + } +} + +#[stable(feature = "foo", since = "1.0")] +pub trait Tr { + #[default_method_body_is_const] + #[stable(feature = "foo", since = "1.0")] + fn bar() -> T { + T? + // Should be allowed. + // Must enable unstable features to call this trait fn in const contexts. + } +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr index fffb91f987..08d91d7daf 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr @@ -4,11 +4,11 @@ error[E0277]: the trait bound `T: Bar` is not satisfied LL | T::b(); | ^^^^ the trait `Bar` is not implemented for `T` | -note: required by `Foo::b` - --> $DIR/trait-where-clause.rs:8:5 +note: required by a bound in `Foo::b` + --> $DIR/trait-where-clause.rs:8:24 | LL | fn b() where Self: ~const Bar; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ required by this bound in `Foo::b` help: consider further restricting this bound | LL | const fn test1<T: ~const Foo + Bar + Bar>() { @@ -20,11 +20,11 @@ error[E0277]: the trait bound `T: Bar` is not satisfied LL | T::c::<T>(); | ^^^^^^^^^ the trait `Bar` is not implemented for `T` | -note: required by `Foo::c` - --> $DIR/trait-where-clause.rs:9:5 +note: required by a bound in `Foo::c` + --> $DIR/trait-where-clause.rs:9:13 | LL | fn c<T: ~const Bar>(); - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ required by this bound in `Foo::c` help: consider further restricting this bound | LL | const fn test1<T: ~const Foo + Bar + Bar>() { @@ -36,11 +36,11 @@ error[E0277]: the trait bound `T: Bar` is not satisfied LL | T::b(); | ^^^^ the trait `Bar` is not implemented for `T` | -note: required by `Foo::b` - --> $DIR/trait-where-clause.rs:8:5 +note: required by a bound in `Foo::b` + --> $DIR/trait-where-clause.rs:8:24 | LL | fn b() where Self: ~const Bar; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ required by this bound in `Foo::b` help: consider further restricting this bound | LL | fn test3<T: Foo + Bar>() { @@ -52,11 +52,11 @@ error[E0277]: the trait bound `T: Bar` is not satisfied LL | T::c::<T>(); | ^^^^^^^^^ the trait `Bar` is not implemented for `T` | -note: required by `Foo::c` - --> $DIR/trait-where-clause.rs:9:5 +note: required by a bound in `Foo::c` + --> $DIR/trait-where-clause.rs:9:13 | LL | fn c<T: ~const Bar>(); - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ required by this bound in `Foo::c` help: consider further restricting this bound | LL | fn test3<T: Foo + Bar>() { diff --git a/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.rs b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.rs new file mode 100644 index 0000000000..1e8b99ba56 --- /dev/null +++ b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.rs @@ -0,0 +1,29 @@ +// gate-test-type_changing_struct_update + +#[derive(Debug)] +struct Machine<S> { + state: S, + common_field1: &'static str, + common_field2: i32, +} +#[derive(Debug)] +struct State1; +#[derive(Debug, PartialEq)] +struct State2; + +fn update_to_state2() { + let m1: Machine<State1> = Machine { + state: State1, + common_field1: "hello", + common_field2: 2, + }; + let m2: Machine<State2> = Machine { + state: State2, + ..m1 + //~^ ERROR type changing struct updating is experimental [E0658] + //~| ERROR mismatched types [E0308] + }; + assert_eq!(State2, m2.state); +} + +fn main() {} diff --git a/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.stderr b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.stderr new file mode 100644 index 0000000000..2217b8c049 --- /dev/null +++ b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.stderr @@ -0,0 +1,22 @@ +error[E0658]: type changing struct updating is experimental + --> $DIR/feature-gate.rs:22:11 + | +LL | ..m1 + | ^^ + | + = note: see issue #86555 <https://github.com/rust-lang/rust/issues/86555> for more information + = help: add `#![feature(type_changing_struct_update)]` to the crate attributes to enable + +error[E0308]: mismatched types + --> $DIR/feature-gate.rs:22:11 + | +LL | ..m1 + | ^^ expected struct `State2`, found struct `State1` + | + = note: expected struct `Machine<State2>` + found struct `Machine<State1>` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.rs b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.rs new file mode 100644 index 0000000000..df2fef55dd --- /dev/null +++ b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.rs @@ -0,0 +1,43 @@ +#![feature(type_changing_struct_update)] +#![allow(incomplete_features)] + +#[derive(Clone)] +struct Machine<'a, S> { + state: S, + lt_str: &'a str, + common_field: i32, +} + +#[derive(Clone)] +struct State1; +#[derive(Clone)] +struct State2; + +fn update_to_state2() { + let s = String::from("hello"); + let m1: Machine<State1> = Machine { + state: State1, + lt_str: &s, + //~^ ERROR `s` does not live long enough [E0597] + // FIXME: The error here actually comes from line 34. The + // span of the error message should be corrected to line 34 + common_field: 2, + }; + // update lifetime + let m3: Machine<'static, State1> = Machine { + lt_str: "hello, too", + ..m1.clone() + }; + // update lifetime and type + let m4: Machine<'static, State2> = Machine { + state: State2, + lt_str: "hello, again", + ..m1.clone() + }; + // updating to `static should fail. + let m2: Machine<'static, State1> = Machine { + ..m1 + }; +} + +fn main() {} diff --git a/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr new file mode 100644 index 0000000000..5f93ad6e02 --- /dev/null +++ b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr @@ -0,0 +1,15 @@ +error[E0597]: `s` does not live long enough + --> $DIR/lifetime-update.rs:20:17 + | +LL | lt_str: &s, + | ^^ borrowed value does not live long enough +... +LL | let m2: Machine<'static, State1> = Machine { + | ------------------------ type annotation requires that `s` is borrowed for `'static` +... +LL | } + | - `s` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs new file mode 100644 index 0000000000..d8b1396a69 --- /dev/null +++ b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs @@ -0,0 +1,57 @@ +#![feature(type_changing_struct_update)] +#![allow(incomplete_features)] + +struct Machine<'a, S, M> { + state: S, + message: M, + lt_str: &'a str, + common_field: i32, +} + +struct State1; +struct State2; + +struct Message1; +struct Message2; + +fn update() { + let m1: Machine<State1, Message1> = Machine { + state: State1, + message: Message1, + lt_str: "hello", + common_field: 2, + }; + // single type update + let m2: Machine<State2, Message1> = Machine { + state: State2, + ..m1 + }; + // multiple type update + let m3: Machine<State2, Message2> = Machine { + state: State2, + message: Message2, + ..m1 + }; +} + +fn fail_update() { + let m1: Machine<f64, f64> = Machine { + state: 3.2, + message: 6.4, + lt_str: "hello", + common_field: 2, + }; + // single type update fail + let m2: Machine<i32, f64> = Machine { + ..m1 + //~^ ERROR mismatched types [E0308] + }; + // multiple type update fail + let m3 = Machine::<i32, i32> { + ..m1 + //~^ ERROR mismatched types [E0308] + //~| ERROR mismatched types [E0308] + }; +} + +fn main() {} diff --git a/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr new file mode 100644 index 0000000000..fa8d6ee23d --- /dev/null +++ b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr @@ -0,0 +1,30 @@ +error[E0308]: mismatched types + --> $DIR/type-generic-update.rs:46:11 + | +LL | ..m1 + | ^^ field type mismatch: Machine.state + | + = note: expected type `i32` + found type `f64` + +error[E0308]: mismatched types + --> $DIR/type-generic-update.rs:51:11 + | +LL | ..m1 + | ^^ field type mismatch: Machine.state + | + = note: expected type `i32` + found type `f64` + +error[E0308]: mismatched types + --> $DIR/type-generic-update.rs:51:11 + | +LL | ..m1 + | ^^ field type mismatch: Machine.message + | + = note: expected type `i32` + found type `f64` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/atomic-print.rs b/src/test/ui/runtime/atomic-print.rs similarity index 100% rename from src/test/ui/atomic-print.rs rename to src/test/ui/runtime/atomic-print.rs diff --git a/src/test/ui/backtrace-debuginfo-aux.rs b/src/test/ui/runtime/backtrace-debuginfo-aux.rs similarity index 100% rename from src/test/ui/backtrace-debuginfo-aux.rs rename to src/test/ui/runtime/backtrace-debuginfo-aux.rs diff --git a/src/test/ui/backtrace-debuginfo.rs b/src/test/ui/runtime/backtrace-debuginfo.rs similarity index 100% rename from src/test/ui/backtrace-debuginfo.rs rename to src/test/ui/runtime/backtrace-debuginfo.rs diff --git a/src/test/ui/native-print-no-runtime.rs b/src/test/ui/runtime/native-print-no-runtime.rs similarity index 100% rename from src/test/ui/native-print-no-runtime.rs rename to src/test/ui/runtime/native-print-no-runtime.rs diff --git a/src/test/ui/out-of-stack.rs b/src/test/ui/runtime/out-of-stack.rs similarity index 100% rename from src/test/ui/out-of-stack.rs rename to src/test/ui/runtime/out-of-stack.rs diff --git a/src/test/ui/rt-explody-panic-payloads.rs b/src/test/ui/runtime/rt-explody-panic-payloads.rs similarity index 90% rename from src/test/ui/rt-explody-panic-payloads.rs rename to src/test/ui/runtime/rt-explody-panic-payloads.rs index 1d3a2ff828..dc193582c6 100644 --- a/src/test/ui/rt-explody-panic-payloads.rs +++ b/src/test/ui/runtime/rt-explody-panic-payloads.rs @@ -25,6 +25,6 @@ fn main() { println!("{:#?}", output); let stderr = std::str::from_utf8(&output.stderr); assert!(stderr.map(|v| { - v.ends_with("drop of the panic payload panicked") + v.ends_with("fatal runtime error: drop of the panic payload panicked\n") }).unwrap_or(false)); } diff --git a/src/test/ui/running-with-no-runtime.rs b/src/test/ui/runtime/running-with-no-runtime.rs similarity index 100% rename from src/test/ui/running-with-no-runtime.rs rename to src/test/ui/runtime/running-with-no-runtime.rs diff --git a/src/test/ui/signal-alternate-stack-cleanup.rs b/src/test/ui/runtime/signal-alternate-stack-cleanup.rs similarity index 100% rename from src/test/ui/signal-alternate-stack-cleanup.rs rename to src/test/ui/runtime/signal-alternate-stack-cleanup.rs diff --git a/src/test/ui/stdout-during-shutdown.rs b/src/test/ui/runtime/stdout-during-shutdown.rs similarity index 100% rename from src/test/ui/stdout-during-shutdown.rs rename to src/test/ui/runtime/stdout-during-shutdown.rs diff --git a/src/test/ui/stdout-during-shutdown.run.stdout b/src/test/ui/runtime/stdout-during-shutdown.run.stdout similarity index 100% rename from src/test/ui/stdout-during-shutdown.run.stdout rename to src/test/ui/runtime/stdout-during-shutdown.run.stdout diff --git a/src/test/ui/rust-2018/uniform-paths/ambiguity-macros-nested.stderr b/src/test/ui/rust-2018/uniform-paths/ambiguity-macros-nested.stderr index 2545231a17..7e008d4657 100644 --- a/src/test/ui/rust-2018/uniform-paths/ambiguity-macros-nested.stderr +++ b/src/test/ui/rust-2018/uniform-paths/ambiguity-macros-nested.stderr @@ -1,9 +1,10 @@ -error[E0659]: `std` is ambiguous (name vs any other name during import resolution) +error[E0659]: `std` is ambiguous --> $DIR/ambiguity-macros-nested.rs:8:13 | LL | pub use std::io; | ^^^ ambiguous name | + = note: ambiguous because of multiple potential import sources = note: `std` could refer to a built-in crate = help: use `::std` to refer to this crate unambiguously note: `std` could also refer to the module defined here diff --git a/src/test/ui/rust-2018/uniform-paths/ambiguity-macros.stderr b/src/test/ui/rust-2018/uniform-paths/ambiguity-macros.stderr index af45cd81a3..771d2c10c1 100644 --- a/src/test/ui/rust-2018/uniform-paths/ambiguity-macros.stderr +++ b/src/test/ui/rust-2018/uniform-paths/ambiguity-macros.stderr @@ -1,9 +1,10 @@ -error[E0659]: `std` is ambiguous (name vs any other name during import resolution) +error[E0659]: `std` is ambiguous --> $DIR/ambiguity-macros.rs:7:5 | LL | use std::io; | ^^^ ambiguous name | + = note: ambiguous because of multiple potential import sources = note: `std` could refer to a built-in crate = help: use `::std` to refer to this crate unambiguously note: `std` could also refer to the module defined here diff --git a/src/test/ui/rust-2018/uniform-paths/ambiguity-nested.stderr b/src/test/ui/rust-2018/uniform-paths/ambiguity-nested.stderr index 4129930bdb..defb16f797 100644 --- a/src/test/ui/rust-2018/uniform-paths/ambiguity-nested.stderr +++ b/src/test/ui/rust-2018/uniform-paths/ambiguity-nested.stderr @@ -1,9 +1,10 @@ -error[E0659]: `std` is ambiguous (name vs any other name during import resolution) +error[E0659]: `std` is ambiguous --> $DIR/ambiguity-nested.rs:8:13 | LL | pub use std::io; | ^^^ ambiguous name | + = note: ambiguous because of multiple potential import sources = note: `std` could refer to a built-in crate = help: use `::std` to refer to this crate unambiguously note: `std` could also refer to the module defined here diff --git a/src/test/ui/rust-2018/uniform-paths/ambiguity.stderr b/src/test/ui/rust-2018/uniform-paths/ambiguity.stderr index e123b323e7..2d735c7e3f 100644 --- a/src/test/ui/rust-2018/uniform-paths/ambiguity.stderr +++ b/src/test/ui/rust-2018/uniform-paths/ambiguity.stderr @@ -1,9 +1,10 @@ -error[E0659]: `std` is ambiguous (name vs any other name during import resolution) +error[E0659]: `std` is ambiguous --> $DIR/ambiguity.rs:5:5 | LL | use std::io; | ^^^ ambiguous name | + = note: ambiguous because of multiple potential import sources = note: `std` could refer to a built-in crate = help: use `::std` to refer to this crate unambiguously note: `std` could also refer to the module defined here diff --git a/src/test/ui/rust-2018/uniform-paths/auxiliary/issue-55779-extern-trait.rs b/src/test/ui/rust-2018/uniform-paths/auxiliary/issue-55779-extern-trait.rs new file mode 100644 index 0000000000..1ce9841c1a --- /dev/null +++ b/src/test/ui/rust-2018/uniform-paths/auxiliary/issue-55779-extern-trait.rs @@ -0,0 +1 @@ +pub trait Trait { fn no_op(&self); } diff --git a/src/test/ui/rust-2018/uniform-paths/auxiliary/issue-87932-a.rs b/src/test/ui/rust-2018/uniform-paths/auxiliary/issue-87932-a.rs new file mode 100644 index 0000000000..8fd2d77be3 --- /dev/null +++ b/src/test/ui/rust-2018/uniform-paths/auxiliary/issue-87932-a.rs @@ -0,0 +1,3 @@ +pub trait Deserialize { + fn deserialize(); +} diff --git a/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.stderr b/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.stderr index db17687638..3d45a81402 100644 --- a/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.stderr +++ b/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.stderr @@ -1,9 +1,10 @@ -error[E0659]: `sub` is ambiguous (name vs any other name during import resolution) +error[E0659]: `sub` is ambiguous --> $DIR/block-scoped-shadow-nested.rs:16:13 | LL | use sub::bar; | ^^^ ambiguous name | + = note: ambiguous because of multiple potential import sources note: `sub` could refer to the module imported here --> $DIR/block-scoped-shadow-nested.rs:14:9 | diff --git a/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow.stderr b/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow.stderr index 2767d9ee77..b068312ced 100644 --- a/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow.stderr +++ b/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow.stderr @@ -1,9 +1,10 @@ -error[E0659]: `Foo` is ambiguous (name vs any other name during import resolution) +error[E0659]: `Foo` is ambiguous --> $DIR/block-scoped-shadow.rs:11:9 | LL | use Foo::*; | ^^^ ambiguous name | + = note: ambiguous because of multiple potential import sources note: `Foo` could refer to the enum defined here --> $DIR/block-scoped-shadow.rs:10:5 | @@ -16,12 +17,13 @@ LL | enum Foo {} | ^^^^^^^^^^^ = help: use `crate::Foo` to refer to this enum unambiguously -error[E0659]: `std` is ambiguous (name vs any other name during import resolution) +error[E0659]: `std` is ambiguous --> $DIR/block-scoped-shadow.rs:18:9 | LL | use std as foo; | ^^^ ambiguous name | + = note: ambiguous because of multiple potential import sources note: `std` could refer to the enum defined here --> $DIR/block-scoped-shadow.rs:17:5 | @@ -34,12 +36,13 @@ LL | struct std; | ^^^^^^^^^^^ = help: use `crate::std` to refer to this struct unambiguously -error[E0659]: `std` is ambiguous (name vs any other name during import resolution) +error[E0659]: `std` is ambiguous --> $DIR/block-scoped-shadow.rs:18:9 | LL | use std as foo; | ^^^ ambiguous name | + = note: ambiguous because of multiple potential import sources note: `std` could refer to the function defined here --> $DIR/block-scoped-shadow.rs:16:5 | diff --git a/src/test/ui/rust-2018/uniform-paths/issue-55779.rs b/src/test/ui/rust-2018/uniform-paths/issue-55779.rs new file mode 100644 index 0000000000..0af17a89b1 --- /dev/null +++ b/src/test/ui/rust-2018/uniform-paths/issue-55779.rs @@ -0,0 +1,29 @@ +// run-pass +// edition:2018 +// aux-crate:issue_55779_extern_trait=issue-55779-extern-trait.rs + +use issue_55779_extern_trait::Trait; + +struct Local; +struct Helper; + +impl Trait for Local { + fn no_op(&self) + { + // (Unused) extern crate declaration necessary to reproduce bug + extern crate issue_55779_extern_trait; + + // This one works + // impl Trait for Helper { fn no_op(&self) { } } + + // This one infinite-loops + const _IMPL_SERIALIZE_FOR_HELPER: () = { + // (extern crate can also appear here to reproduce bug, + // as in originating example from serde) + impl Trait for Helper { fn no_op(&self) { } } + }; + + } +} + +fn main() { } diff --git a/src/test/ui/rust-2018/uniform-paths/issue-56596.stderr b/src/test/ui/rust-2018/uniform-paths/issue-56596.stderr index e39840d34d..d2297385f3 100644 --- a/src/test/ui/rust-2018/uniform-paths/issue-56596.stderr +++ b/src/test/ui/rust-2018/uniform-paths/issue-56596.stderr @@ -1,9 +1,10 @@ -error[E0659]: `issue_56596` is ambiguous (name vs any other name during import resolution) +error[E0659]: `issue_56596` is ambiguous --> $DIR/issue-56596.rs:12:5 | LL | use issue_56596; | ^^^^^^^^^^^ ambiguous name | + = note: ambiguous because of multiple potential import sources = note: `issue_56596` could refer to a crate passed with `--extern` = help: use `::issue_56596` to refer to this crate unambiguously note: `issue_56596` could also refer to the module imported here diff --git a/src/test/ui/rust-2018/uniform-paths/issue-87932.rs b/src/test/ui/rust-2018/uniform-paths/issue-87932.rs new file mode 100644 index 0000000000..70a641d8a4 --- /dev/null +++ b/src/test/ui/rust-2018/uniform-paths/issue-87932.rs @@ -0,0 +1,15 @@ +// edition:2018 +// aux-crate:issue_87932_a=issue-87932-a.rs + +pub struct A {} + +impl issue_87932_a::Deserialize for A { + fn deserialize() { + extern crate issue_87932_a as _a; + } +} + +fn main() { + A::deserialize(); + //~^ ERROR no function or associated item named `deserialize` found for struct `A` +} diff --git a/src/test/ui/rust-2018/uniform-paths/issue-87932.stderr b/src/test/ui/rust-2018/uniform-paths/issue-87932.stderr new file mode 100644 index 0000000000..53272abccb --- /dev/null +++ b/src/test/ui/rust-2018/uniform-paths/issue-87932.stderr @@ -0,0 +1,18 @@ +error[E0599]: no function or associated item named `deserialize` found for struct `A` in the current scope + --> $DIR/issue-87932.rs:13:8 + | +LL | pub struct A {} + | ------------ function or associated item `deserialize` not found for this +... +LL | A::deserialize(); + | ^^^^^^^^^^^ function or associated item not found in `A` + | + = 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 <crate::A as issue_87932_a::Deserialize>::deserialize::_a::Deserialize; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/rust-2018/uniform-paths/macro-rules.rs b/src/test/ui/rust-2018/uniform-paths/macro-rules.rs index 6c3f1892cb..2d9a6a9a92 100644 --- a/src/test/ui/rust-2018/uniform-paths/macro-rules.rs +++ b/src/test/ui/rust-2018/uniform-paths/macro-rules.rs @@ -8,7 +8,7 @@ mod m1 { use legacy_macro as _; // OK pub(crate) use legacy_macro as _; // OK - pub use legacy_macro as _; //~ ERROR `legacy_macro` is private, and cannot be re-exported + pub use legacy_macro as _; //~ ERROR `legacy_macro` is only public within the crate, and cannot be re-exported outside } mod m2 { diff --git a/src/test/ui/rust-2018/uniform-paths/macro-rules.stderr b/src/test/ui/rust-2018/uniform-paths/macro-rules.stderr index f1b5e0c5ef..9e48e26b1d 100644 --- a/src/test/ui/rust-2018/uniform-paths/macro-rules.stderr +++ b/src/test/ui/rust-2018/uniform-paths/macro-rules.stderr @@ -1,4 +1,4 @@ -error[E0364]: `legacy_macro` is private, and cannot be re-exported +error[E0364]: `legacy_macro` is only public within the crate, and cannot be re-exported outside --> $DIR/macro-rules.rs:11:13 | LL | pub use legacy_macro as _; @@ -10,12 +10,13 @@ note: consider marking `legacy_macro` as `pub` in the imported module LL | pub use legacy_macro as _; | ^^^^^^^^^^^^^^^^^ -error[E0659]: `legacy_macro` is ambiguous (name vs any other name during import resolution) +error[E0659]: `legacy_macro` is ambiguous --> $DIR/macro-rules.rs:31:13 | LL | use legacy_macro as _; | ^^^^^^^^^^^^ ambiguous name | + = note: ambiguous because of multiple potential import sources note: `legacy_macro` could refer to the macro defined here --> $DIR/macro-rules.rs:28:9 | diff --git a/src/test/ui/rust-2018/uniform-paths/redundant.rs b/src/test/ui/rust-2018/uniform-paths/redundant.rs index 2d306eb920..fd7fc7fbd4 100644 --- a/src/test/ui/rust-2018/uniform-paths/redundant.rs +++ b/src/test/ui/rust-2018/uniform-paths/redundant.rs @@ -13,8 +13,8 @@ mod bar { } fn main() { - io::stdout(); - self::std::io::stdout(); - foo::my_std::io::stdout(); - bar::std::io::stdout(); + let _ = io::stdout(); + let _ = self::std::io::stdout(); + let _ = foo::my_std::io::stdout(); + let _ = bar::std::io::stdout(); } diff --git a/src/test/ui/rust-2021/future-prelude-collision-shadow.stderr b/src/test/ui/rust-2021/future-prelude-collision-shadow.stderr index e4662b430d..d945b4c94c 100644 --- a/src/test/ui/rust-2021/future-prelude-collision-shadow.stderr +++ b/src/test/ui/rust-2021/future-prelude-collision-shadow.stderr @@ -15,6 +15,7 @@ LL | fn try_into(self) -> Result<T, Self::Error>; | the method is available for `Rc<u8>` here | = help: items from traits can only be used if the trait is in scope + = note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021 help: consider wrapping the receiver expression with the appropriate type | LL | let _: u32 = Box::new(3u8).try_into().unwrap(); diff --git a/src/test/ui/rust-2021/prelude2021.rs b/src/test/ui/rust-2021/prelude2021.rs index 3a9fd69322..a63b6fcf26 100644 --- a/src/test/ui/rust-2021/prelude2021.rs +++ b/src/test/ui/rust-2021/prelude2021.rs @@ -1,6 +1,5 @@ // check-pass // edition:2021 -// compile-flags: -Zunstable-options fn main() { let _: u16 = 123i32.try_into().unwrap(); diff --git a/src/test/ui/rust-2021/reserved-prefixes-migration.fixed b/src/test/ui/rust-2021/reserved-prefixes-migration.fixed index e026f01e93..eed2f313ab 100644 --- a/src/test/ui/rust-2021/reserved-prefixes-migration.fixed +++ b/src/test/ui/rust-2021/reserved-prefixes-migration.fixed @@ -1,6 +1,6 @@ // check-pass // run-rustfix -// compile-flags: -Z unstable-options --edition 2018 +// edition:2018 #![warn(rust_2021_prefixes_incompatible_syntax)] diff --git a/src/test/ui/rust-2021/reserved-prefixes-migration.rs b/src/test/ui/rust-2021/reserved-prefixes-migration.rs index d24f296348..0565db793d 100644 --- a/src/test/ui/rust-2021/reserved-prefixes-migration.rs +++ b/src/test/ui/rust-2021/reserved-prefixes-migration.rs @@ -1,6 +1,6 @@ // check-pass // run-rustfix -// compile-flags: -Z unstable-options --edition 2018 +// edition:2018 #![warn(rust_2021_prefixes_incompatible_syntax)] diff --git a/src/test/ui/rustc-rust-log.rs b/src/test/ui/rustc-rust-log.rs index 8ceb24dd2a..52e7dcf449 100644 --- a/src/test/ui/rustc-rust-log.rs +++ b/src/test/ui/rustc-rust-log.rs @@ -1,9 +1,6 @@ // run-pass // This test is just checking that we won't ICE if logging is turned -// on; don't bother trying to compare that (copious) output. (Note -// also that this test potentially silly, since we do not build+test -// debug versions of rustc as part of our continuous integration -// process...) +// on; don't bother trying to compare that (copious) output. // // dont-check-compiler-stdout // dont-check-compiler-stderr diff --git a/src/test/ui/rustdoc/doc_keyword.rs b/src/test/ui/rustdoc/doc_keyword.rs index 4518f77ef9..43b84e5018 100644 --- a/src/test/ui/rustdoc/doc_keyword.rs +++ b/src/test/ui/rustdoc/doc_keyword.rs @@ -1,5 +1,5 @@ #![crate_type = "lib"] -#![feature(doc_keyword)] +#![feature(rustdoc_internals)] #![doc(keyword = "hello")] //~ ERROR diff --git a/src/test/ui/duplicate_doc_alias.rs b/src/test/ui/rustdoc/duplicate_doc_alias.rs similarity index 100% rename from src/test/ui/duplicate_doc_alias.rs rename to src/test/ui/rustdoc/duplicate_doc_alias.rs diff --git a/src/test/ui/duplicate_doc_alias.stderr b/src/test/ui/rustdoc/duplicate_doc_alias.stderr similarity index 100% rename from src/test/ui/duplicate_doc_alias.stderr rename to src/test/ui/rustdoc/duplicate_doc_alias.stderr diff --git a/src/test/ui/rustdoc/hidden-doc-associated-item.rs b/src/test/ui/rustdoc/hidden-doc-associated-item.rs new file mode 100644 index 0000000000..d431f9e899 --- /dev/null +++ b/src/test/ui/rustdoc/hidden-doc-associated-item.rs @@ -0,0 +1,15 @@ +// check-pass +// See issue #85526. +// This test should produce no warnings. + +#![deny(missing_docs)] +//! Crate docs + +#[doc(hidden)] +pub struct Foo; + +impl Foo { + pub fn bar() {} +} + +fn main() {} diff --git a/src/test/ui/rustdoc/renamed-features-rustdoc_internals.rs b/src/test/ui/rustdoc/renamed-features-rustdoc_internals.rs new file mode 100644 index 0000000000..739c624d0c --- /dev/null +++ b/src/test/ui/rustdoc/renamed-features-rustdoc_internals.rs @@ -0,0 +1,5 @@ +#![feature(doc_keyword)] //~ ERROR +#![feature(doc_primitive)] //~ ERROR +#![crate_type = "lib"] + +pub fn foo() {} diff --git a/src/test/ui/rustdoc/renamed-features-rustdoc_internals.stderr b/src/test/ui/rustdoc/renamed-features-rustdoc_internals.stderr new file mode 100644 index 0000000000..d0979ce97a --- /dev/null +++ b/src/test/ui/rustdoc/renamed-features-rustdoc_internals.stderr @@ -0,0 +1,19 @@ +error[E0557]: feature has been removed + --> $DIR/renamed-features-rustdoc_internals.rs:1:12 + | +LL | #![feature(doc_keyword)] + | ^^^^^^^^^^^ feature has been removed + | + = note: merged into `#![feature(rustdoc_internals)]` + +error[E0557]: feature has been removed + --> $DIR/renamed-features-rustdoc_internals.rs:2:12 + | +LL | #![feature(doc_primitive)] + | ^^^^^^^^^^^^^ feature has been removed + | + = note: merged into `#![feature(rustdoc_internals)]` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0557`. diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.nll.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.nll.stderr deleted file mode 100644 index 5d0b2c2ebd..0000000000 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.nll.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error: lifetime may not live long enough - --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:37 - | -LL | async fn f(self: Pin<&Self>) -> impl Clone { self } - | - ^^^^^^^^^^ opaque type requires that `'1` must outlive `'static` - | | - | let's call the lifetime of this reference `'1` - | -help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound - | -LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self } - | ++++ - -error: aborting due to previous error - diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs index 43998ca8c5..a1e7f4aa87 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs @@ -6,7 +6,7 @@ struct Foo; impl Foo { async fn f(self: Pin<&Self>) -> impl Clone { self } - //~^ ERROR E0759 + //~^ ERROR: captures lifetime that does not appear in bounds } fn main() { diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index 04cd2b78da..953d7cd6a0 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -1,17 +1,16 @@ -error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement - --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:16 +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:37 | LL | async fn f(self: Pin<&Self>) -> impl Clone { self } - | ^^^^ ---------- ---------- ...and is required to live as long as `'static` here - | | | - | | this data with an anonymous lifetime `'_`... - | ...is captured here... + | - ^^^^^^^^^^ + | | + | hidden type `Pin<&Foo>` captures the lifetime `'_` as defined here | -help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound +help: to declare that the `impl Trait` captures '_, you can add an explicit `'_` lifetime bound | LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self } | ++++ error: aborting due to previous error -For more information about this error, try `rustc --explain E0759`. +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.nll.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.nll.stderr deleted file mode 100644 index 4301d8f767..0000000000 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.nll.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error: lifetime may not live long enough - --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:31 - | -LL | fn f(self: Pin<&Self>) -> impl Clone { self } - | - ^^^^^^^^^^ 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 f(self: Pin<&Self>) -> impl Clone + '_ { self } - | ++++ - -error: aborting due to previous error - diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs index 04935fc52a..4db2fa7dcb 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs @@ -3,7 +3,8 @@ use std::pin::Pin; struct Foo; impl Foo { - fn f(self: Pin<&Self>) -> impl Clone { self } //~ ERROR E0759 + fn f(self: Pin<&Self>) -> impl Clone { self } + //~^ ERROR: captures lifetime that does not appear in bounds } fn main() { diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr index 54e75aeec3..faa1233ffd 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr @@ -1,21 +1,16 @@ -error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement - --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:44 - | -LL | fn f(self: Pin<&Self>) -> impl Clone { self } - | ---------- ^^^^ ...is captured here... - | | - | this data with an anonymous lifetime `'_`... - | -note: ...and is required to live as long as `'static` here +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:31 | LL | fn f(self: Pin<&Self>) -> impl Clone { self } - | ^^^^^^^^^^ -help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound + | ----- ^^^^^^^^^^ + | | + | hidden type `Pin<&Foo>` captures the anonymous lifetime defined here + | +help: to declare that the `impl Trait` captures '_, you can add an explicit `'_` lifetime bound | LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self } | ++++ error: aborting due to previous error -For more information about this error, try `rustc --explain E0759`. +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/class-missing-self.rs b/src/test/ui/self/class-missing-self.rs similarity index 100% rename from src/test/ui/class-missing-self.rs rename to src/test/ui/self/class-missing-self.rs diff --git a/src/test/ui/class-missing-self.stderr b/src/test/ui/self/class-missing-self.stderr similarity index 100% rename from src/test/ui/class-missing-self.stderr rename to src/test/ui/self/class-missing-self.stderr diff --git a/src/test/ui/issues/issue-61882-2.rs b/src/test/ui/self/issue-61882-2.rs similarity index 100% rename from src/test/ui/issues/issue-61882-2.rs rename to src/test/ui/self/issue-61882-2.rs diff --git a/src/test/ui/issues/issue-61882-2.stderr b/src/test/ui/self/issue-61882-2.stderr similarity index 100% rename from src/test/ui/issues/issue-61882-2.stderr rename to src/test/ui/self/issue-61882-2.stderr diff --git a/src/test/ui/issues/issue-61882.rs b/src/test/ui/self/issue-61882.rs similarity index 100% rename from src/test/ui/issues/issue-61882.rs rename to src/test/ui/self/issue-61882.rs diff --git a/src/test/ui/issues/issue-61882.stderr b/src/test/ui/self/issue-61882.stderr similarity index 100% rename from src/test/ui/issues/issue-61882.stderr rename to src/test/ui/self/issue-61882.stderr diff --git a/src/test/ui/objects-owned-object-owned-method.rs b/src/test/ui/self/objects-owned-object-owned-method.rs similarity index 100% rename from src/test/ui/objects-owned-object-owned-method.rs rename to src/test/ui/self/objects-owned-object-owned-method.rs diff --git a/src/test/ui/simd/intrinsic/generic-bitmask.rs b/src/test/ui/simd/intrinsic/generic-bitmask.rs index 92c4e67dfd..9a23dae77b 100644 --- a/src/test/ui/simd/intrinsic/generic-bitmask.rs +++ b/src/test/ui/simd/intrinsic/generic-bitmask.rs @@ -51,19 +51,19 @@ fn main() { let _: u64 = simd_bitmask(m64); let _: u16 = simd_bitmask(m2); - //~^ ERROR bitmask `u16`, expected `u8` + //~^ ERROR invalid monomorphization of `simd_bitmask` intrinsic let _: u16 = simd_bitmask(m8); - //~^ ERROR bitmask `u16`, expected `u8` + //~^ ERROR invalid monomorphization of `simd_bitmask` intrinsic let _: u32 = simd_bitmask(m16); - //~^ ERROR bitmask `u32`, expected `u16` + //~^ ERROR invalid monomorphization of `simd_bitmask` intrinsic let _: u64 = simd_bitmask(m32); - //~^ ERROR bitmask `u64`, expected `u32` + //~^ ERROR invalid monomorphization of `simd_bitmask` intrinsic let _: u128 = simd_bitmask(m64); - //~^ ERROR bitmask `u128`, expected `u64` + //~^ ERROR invalid monomorphization of `simd_bitmask` intrinsic } } diff --git a/src/test/ui/simd/intrinsic/generic-bitmask.stderr b/src/test/ui/simd/intrinsic/generic-bitmask.stderr index 5aaae68caf..0de3f8eead 100644 --- a/src/test/ui/simd/intrinsic/generic-bitmask.stderr +++ b/src/test/ui/simd/intrinsic/generic-bitmask.stderr @@ -1,28 +1,28 @@ -error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u16`, expected `u8` +error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: cannot return `u16`, expected `u8` or `[u8; 1]` --> $DIR/generic-bitmask.rs:53:22 | LL | let _: u16 = simd_bitmask(m2); | ^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u16`, expected `u8` +error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: cannot return `u16`, expected `u8` or `[u8; 1]` --> $DIR/generic-bitmask.rs:56:22 | LL | let _: u16 = simd_bitmask(m8); | ^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u32`, expected `u16` +error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: cannot return `u32`, expected `u16` or `[u8; 2]` --> $DIR/generic-bitmask.rs:59:22 | LL | let _: u32 = simd_bitmask(m16); | ^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u64`, expected `u32` +error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: cannot return `u64`, expected `u32` or `[u8; 4]` --> $DIR/generic-bitmask.rs:62:22 | LL | let _: u64 = simd_bitmask(m32); | ^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u128`, expected `u64` +error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: cannot return `u128`, expected `u64` or `[u8; 8]` --> $DIR/generic-bitmask.rs:65:23 | LL | let _: u128 = simd_bitmask(m64); diff --git a/src/test/ui/simd/intrinsic/generic-elements-pass.rs b/src/test/ui/simd/intrinsic/generic-elements-pass.rs index 08544bce45..3c913c0adf 100644 --- a/src/test/ui/simd/intrinsic/generic-elements-pass.rs +++ b/src/test/ui/simd/intrinsic/generic-elements-pass.rs @@ -2,7 +2,6 @@ // ignore-emscripten FIXME(#45351) hits an LLVM assert #![feature(repr_simd, platform_intrinsics)] -#![allow(incomplete_features)] #![feature(inline_const)] #[repr(simd)] diff --git a/src/test/ui/simd/intrinsic/generic-select.rs b/src/test/ui/simd/intrinsic/generic-select.rs index 7d68af49e2..248e82ea21 100644 --- a/src/test/ui/simd/intrinsic/generic-select.rs +++ b/src/test/ui/simd/intrinsic/generic-select.rs @@ -20,8 +20,7 @@ struct b8x4(pub i8, pub i8, pub i8, pub i8); #[repr(simd)] #[derive(Copy, Clone, PartialEq)] -struct b8x8(pub i8, pub i8, pub i8, pub i8, - pub i8, pub i8, pub i8, pub i8); +struct b8x8(pub i8, pub i8, pub i8, pub i8, pub i8, pub i8, pub i8, pub i8); extern "platform-intrinsic" { fn simd_select<T, U>(x: T, a: U, b: U) -> U; @@ -50,15 +49,15 @@ fn main() { //~^ ERROR found non-SIMD `u32` simd_select_bitmask(0u16, x, x); - //~^ ERROR mask length `16` != other vector length `4` - // + //~^ ERROR invalid bitmask `u16`, expected `u8` or `[u8; 1]` + simd_select_bitmask(0u8, 1u32, 2u32); //~^ ERROR found non-SIMD `u32` simd_select_bitmask(0.0f32, x, x); - //~^ ERROR `f32` is not an integral type + //~^ ERROR invalid bitmask `f32`, expected `u8` or `[u8; 1]` simd_select_bitmask("x", x, x); - //~^ ERROR `&str` is not an integral type + //~^ ERROR invalid bitmask `&str`, expected `u8` or `[u8; 1]` } } diff --git a/src/test/ui/simd/intrinsic/generic-select.stderr b/src/test/ui/simd/intrinsic/generic-select.stderr index c53d581745..d576f1bc77 100644 --- a/src/test/ui/simd/intrinsic/generic-select.stderr +++ b/src/test/ui/simd/intrinsic/generic-select.stderr @@ -1,47 +1,47 @@ error[E0511]: invalid monomorphization of `simd_select` intrinsic: mismatched lengths: mask length `8` != other vector length `4` - --> $DIR/generic-select.rs:40:9 + --> $DIR/generic-select.rs:39:9 | LL | simd_select(m8, x, x); | ^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_select` intrinsic: mask element type is `u32`, expected `i_` - --> $DIR/generic-select.rs:43:9 + --> $DIR/generic-select.rs:42:9 | LL | simd_select(x, x, x); | ^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_select` intrinsic: mask element type is `f32`, expected `i_` - --> $DIR/generic-select.rs:46:9 + --> $DIR/generic-select.rs:45:9 | LL | simd_select(z, z, z); | ^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_select` intrinsic: expected SIMD argument type, found non-SIMD `u32` - --> $DIR/generic-select.rs:49:9 + --> $DIR/generic-select.rs:48:9 | LL | simd_select(m4, 0u32, 1u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: mismatched lengths: mask length `16` != other vector length `4` - --> $DIR/generic-select.rs:52:9 +error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: invalid bitmask `u16`, expected `u8` or `[u8; 1]` + --> $DIR/generic-select.rs:51:9 | LL | simd_select_bitmask(0u16, x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: expected SIMD argument type, found non-SIMD `u32` - --> $DIR/generic-select.rs:55:9 + --> $DIR/generic-select.rs:54:9 | LL | simd_select_bitmask(0u8, 1u32, 2u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: `f32` is not an integral type - --> $DIR/generic-select.rs:58:9 +error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: invalid bitmask `f32`, expected `u8` or `[u8; 1]` + --> $DIR/generic-select.rs:57:9 | LL | simd_select_bitmask(0.0f32, x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: `&str` is not an integral type - --> $DIR/generic-select.rs:61:9 +error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: invalid bitmask `&str`, expected `u8` or `[u8; 1]` + --> $DIR/generic-select.rs:60:9 | LL | simd_select_bitmask("x", x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/simd/simd-bitmask.rs b/src/test/ui/simd/simd-bitmask.rs new file mode 100644 index 0000000000..14ee2e741b --- /dev/null +++ b/src/test/ui/simd/simd-bitmask.rs @@ -0,0 +1,52 @@ +//run-pass +//ignore-endian-big behavior of simd_select_bitmask is endian-specific +#![feature(repr_simd, platform_intrinsics)] + +extern "platform-intrinsic" { + fn simd_bitmask<T, U>(v: T) -> U; + fn simd_select_bitmask<T, U>(m: T, a: U, b: U) -> U; +} + +#[derive(Copy, Clone)] +#[repr(simd)] +struct Simd<T, const N: usize>([T; N]); + +fn main() { + unsafe { + let v = Simd::<i8, 4>([-1, 0, -1, 0]); + let i: u8 = simd_bitmask(v); + let a: [u8; 1] = simd_bitmask(v); + + assert_eq!(i, 0b0101); + assert_eq!(a, [0b0101]); + + let v = Simd::<i8, 16>([0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0]); + let i: u16 = simd_bitmask(v); + let a: [u8; 2] = simd_bitmask(v); + + assert_eq!(i, 0b0101000000001100); + assert_eq!(a, [0b1100, 0b01010000]); + } + + unsafe { + let a = Simd::<i32, 8>([0, 1, 2, 3, 4, 5, 6, 7]); + let b = Simd::<i32, 8>([8, 9, 10, 11, 12, 13, 14, 15]); + let e = [0, 9, 2, 11, 12, 13, 14, 15]; + + let r = simd_select_bitmask(0b0101u8, a, b); + assert_eq!(r.0, e); + + let r = simd_select_bitmask([0b0101u8], a, b); + assert_eq!(r.0, e); + + let a = Simd::<i32, 16>([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); + let b = Simd::<i32, 16>([16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]); + let e = [16, 17, 2, 3, 20, 21, 22, 23, 24, 25, 26, 27, 12, 29, 14, 31]; + + let r = simd_select_bitmask(0b0101000000001100u16, a, b); + assert_eq!(r.0, e); + + let r = simd_select_bitmask([0b1100u8, 0b01010000u8], a, b); + assert_eq!(r.0, e); + } +} diff --git a/src/test/ui/span/issue-29595.stderr b/src/test/ui/span/issue-29595.stderr index 24dfdf8ebc..92445e4073 100644 --- a/src/test/ui/span/issue-29595.stderr +++ b/src/test/ui/span/issue-29595.stderr @@ -3,12 +3,6 @@ error[E0277]: the trait bound `u8: Tr` is not satisfied | LL | let a: u8 = Tr::C; | ^^^^^ the trait `Tr` is not implemented for `u8` - | -note: required by `Tr::C` - --> $DIR/issue-29595.rs:2:5 - | -LL | const C: Self; - | ^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr index ce981bc009..81e2a9a1ff 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr @@ -20,8 +20,12 @@ LL | struct MyStruct; LL | println!("{}", MyStruct.foo_one()); | ^^^^^^^ method cannot be called on `MyStruct` due to unsatisfied trait bounds | - = note: the following trait bounds were not satisfied: - `MyStruct: Foo` +note: the following trait bounds were not satisfied because of the requirements of the implementation of `Foo` for `_`: + `MyStruct: Foo` + --> $DIR/specialization-trait-not-implemented.rs:14:17 + | +LL | default impl<T> Foo for T { + | ^^^ ^ note: the following trait must be implemented --> $DIR/specialization-trait-not-implemented.rs:7:1 | diff --git a/src/test/ui/transmute-specialization.rs b/src/test/ui/specialization/transmute-specialization.rs similarity index 100% rename from src/test/ui/transmute-specialization.rs rename to src/test/ui/specialization/transmute-specialization.rs diff --git a/src/test/ui/transmute-specialization.stderr b/src/test/ui/specialization/transmute-specialization.stderr similarity index 100% rename from src/test/ui/transmute-specialization.stderr rename to src/test/ui/specialization/transmute-specialization.stderr diff --git a/src/test/ui/stability-attribute/stability-attribute-trait-impl.rs b/src/test/ui/stability-attribute/stability-attribute-trait-impl.rs index 656564fc9e..ce2726ffde 100644 --- a/src/test/ui/stability-attribute/stability-attribute-trait-impl.rs +++ b/src/test/ui/stability-attribute/stability-attribute-trait-impl.rs @@ -1,27 +1,28 @@ #![feature(staged_api)] +//~^ ERROR module has missing stability attribute -#[stable(feature = "x", since = "1")] +#[stable(feature = "a", since = "1")] struct StableType; -#[unstable(feature = "x", issue = "none")] +#[unstable(feature = "b", issue = "none")] struct UnstableType; -#[stable(feature = "x", since = "1")] +#[stable(feature = "c", since = "1")] trait StableTrait {} -#[unstable(feature = "x", issue = "none")] +#[unstable(feature = "d", issue = "none")] trait UnstableTrait {} -#[unstable(feature = "x", issue = "none")] +#[unstable(feature = "e", issue = "none")] impl UnstableTrait for UnstableType {} -#[unstable(feature = "x", issue = "none")] +#[unstable(feature = "f", issue = "none")] impl StableTrait for UnstableType {} -#[unstable(feature = "x", issue = "none")] +#[unstable(feature = "g", issue = "none")] impl UnstableTrait for StableType {} -#[unstable(feature = "x", issue = "none")] +#[unstable(feature = "h", issue = "none")] //~^ ERROR an `#[unstable]` annotation here has no effect [ineffective_unstable_trait_impl] impl StableTrait for StableType {} diff --git a/src/test/ui/stability-attribute/stability-attribute-trait-impl.stderr b/src/test/ui/stability-attribute/stability-attribute-trait-impl.stderr index a11479cc8f..310f02024c 100644 --- a/src/test/ui/stability-attribute/stability-attribute-trait-impl.stderr +++ b/src/test/ui/stability-attribute/stability-attribute-trait-impl.stderr @@ -1,11 +1,23 @@ error: an `#[unstable]` annotation here has no effect - --> $DIR/stability-attribute-trait-impl.rs:24:1 + --> $DIR/stability-attribute-trait-impl.rs:25:1 | -LL | #[unstable(feature = "x", issue = "none")] +LL | #[unstable(feature = "h", issue = "none")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[deny(ineffective_unstable_trait_impl)]` on by default = note: see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information -error: aborting due to previous error +error: module has missing stability attribute + --> $DIR/stability-attribute-trait-impl.rs:1:1 + | +LL | / #![feature(staged_api)] +LL | | +LL | | +LL | | #[stable(feature = "a", since = "1")] +... | +LL | | +LL | | fn main() {} + | |____________^ + +error: aborting due to 2 previous errors diff --git a/src/test/ui/stability-in-private-module.rs b/src/test/ui/stability-attribute/stability-in-private-module.rs similarity index 100% rename from src/test/ui/stability-in-private-module.rs rename to src/test/ui/stability-attribute/stability-in-private-module.rs diff --git a/src/test/ui/stability-in-private-module.stderr b/src/test/ui/stability-attribute/stability-in-private-module.stderr similarity index 100% rename from src/test/ui/stability-in-private-module.stderr rename to src/test/ui/stability-attribute/stability-in-private-module.stderr diff --git a/src/test/ui/stability-attribute/suggest-vec-allocator-api.rs b/src/test/ui/stability-attribute/suggest-vec-allocator-api.rs new file mode 100644 index 0000000000..fac52ab77c --- /dev/null +++ b/src/test/ui/stability-attribute/suggest-vec-allocator-api.rs @@ -0,0 +1,9 @@ +fn main() { + let _: Vec<u8, _> = vec![]; //~ ERROR use of unstable library feature 'allocator_api' + #[rustfmt::skip] + let _: Vec< + String, + _> = vec![]; //~ ERROR use of unstable library feature 'allocator_api' + let _ = Vec::<u16, _>::new(); //~ ERROR use of unstable library feature 'allocator_api' + let _boxed: Box<u32, _> = Box::new(10); //~ ERROR use of unstable library feature 'allocator_api' +} diff --git a/src/test/ui/stability-attribute/suggest-vec-allocator-api.stderr b/src/test/ui/stability-attribute/suggest-vec-allocator-api.stderr new file mode 100644 index 0000000000..41e5787b8c --- /dev/null +++ b/src/test/ui/stability-attribute/suggest-vec-allocator-api.stderr @@ -0,0 +1,49 @@ +error[E0658]: use of unstable library feature 'allocator_api' + --> $DIR/suggest-vec-allocator-api.rs:2:20 + | +LL | let _: Vec<u8, _> = vec![]; + | ----^ + | | + | help: consider wrapping the inner types in tuple: `(u8, _)` + | + = note: see issue #32838 <https://github.com/rust-lang/rust/issues/32838> for more information + = help: add `#![feature(allocator_api)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'allocator_api' + --> $DIR/suggest-vec-allocator-api.rs:6:9 + | +LL | _> = vec![]; + | ^ + | + = note: see issue #32838 <https://github.com/rust-lang/rust/issues/32838> for more information + = help: add `#![feature(allocator_api)]` to the crate attributes to enable +help: consider wrapping the inner types in tuple + | +LL ~ let _: Vec<( +LL + String, +LL ~ _)> = vec![]; + | + +error[E0658]: use of unstable library feature 'allocator_api' + --> $DIR/suggest-vec-allocator-api.rs:8:26 + | +LL | let _boxed: Box<u32, _> = Box::new(10); + | ^ + | + = note: see issue #32838 <https://github.com/rust-lang/rust/issues/32838> for more information + = help: add `#![feature(allocator_api)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'allocator_api' + --> $DIR/suggest-vec-allocator-api.rs:7:24 + | +LL | let _ = Vec::<u16, _>::new(); + | -----^ + | | + | help: consider wrapping the inner types in tuple: `(u16, _)` + | + = note: see issue #32838 <https://github.com/rust-lang/rust/issues/32838> for more information + = help: add `#![feature(allocator_api)]` 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/stack-protector/warn-stack-protector-unsupported.all.stderr b/src/test/ui/stack-protector/warn-stack-protector-unsupported.all.stderr new file mode 100644 index 0000000000..5488771552 --- /dev/null +++ b/src/test/ui/stack-protector/warn-stack-protector-unsupported.all.stderr @@ -0,0 +1,4 @@ +warning: `-Z stack-protector=all` is not supported for target nvptx64-nvidia-cuda and will be ignored + +warning: 1 warning emitted + diff --git a/src/test/ui/stack-protector/warn-stack-protector-unsupported.basic.stderr b/src/test/ui/stack-protector/warn-stack-protector-unsupported.basic.stderr new file mode 100644 index 0000000000..f7a1ee39fb --- /dev/null +++ b/src/test/ui/stack-protector/warn-stack-protector-unsupported.basic.stderr @@ -0,0 +1,4 @@ +warning: `-Z stack-protector=basic` is not supported for target nvptx64-nvidia-cuda and will be ignored + +warning: 1 warning emitted + diff --git a/src/test/ui/stack-protector/warn-stack-protector-unsupported.rs b/src/test/ui/stack-protector/warn-stack-protector-unsupported.rs new file mode 100644 index 0000000000..6df5d3cd5a --- /dev/null +++ b/src/test/ui/stack-protector/warn-stack-protector-unsupported.rs @@ -0,0 +1,19 @@ +// build-pass +// revisions: all strong basic +// compile-flags: --target nvptx64-nvidia-cuda +// needs-llvm-components: nvptx +// [all] compile-flags: -Z stack-protector=all +// [strong] compile-flags: -Z stack-protector=strong +// [basic] compile-flags: -Z stack-protector=basic + +#![crate_type = "lib"] +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +pub fn main(){} diff --git a/src/test/ui/stack-protector/warn-stack-protector-unsupported.strong.stderr b/src/test/ui/stack-protector/warn-stack-protector-unsupported.strong.stderr new file mode 100644 index 0000000000..ccc2f9f2cc --- /dev/null +++ b/src/test/ui/stack-protector/warn-stack-protector-unsupported.strong.stderr @@ -0,0 +1,4 @@ +warning: `-Z stack-protector=strong` is not supported for target nvptx64-nvidia-cuda and will be ignored + +warning: 1 warning emitted + diff --git a/src/test/ui/auxiliary/extern-statics.rs b/src/test/ui/static/auxiliary/extern-statics.rs similarity index 100% rename from src/test/ui/auxiliary/extern-statics.rs rename to src/test/ui/static/auxiliary/extern-statics.rs diff --git a/src/test/ui/auxiliary/nested_item.rs b/src/test/ui/static/auxiliary/nested_item.rs similarity index 100% rename from src/test/ui/auxiliary/nested_item.rs rename to src/test/ui/static/auxiliary/nested_item.rs diff --git a/src/test/ui/nested_item_main.rs b/src/test/ui/static/nested_item_main.rs similarity index 100% rename from src/test/ui/nested_item_main.rs rename to src/test/ui/static/nested_item_main.rs diff --git a/src/test/ui/refer-to-other-statics-by-value.rs b/src/test/ui/static/refer-to-other-statics-by-value.rs similarity index 100% rename from src/test/ui/refer-to-other-statics-by-value.rs rename to src/test/ui/static/refer-to-other-statics-by-value.rs diff --git a/src/test/ui/safe-extern-statics-mut.mir.stderr b/src/test/ui/static/safe-extern-statics-mut.mir.stderr similarity index 100% rename from src/test/ui/safe-extern-statics-mut.mir.stderr rename to src/test/ui/static/safe-extern-statics-mut.mir.stderr diff --git a/src/test/ui/safe-extern-statics-mut.rs b/src/test/ui/static/safe-extern-statics-mut.rs similarity index 100% rename from src/test/ui/safe-extern-statics-mut.rs rename to src/test/ui/static/safe-extern-statics-mut.rs diff --git a/src/test/ui/safe-extern-statics-mut.thir.stderr b/src/test/ui/static/safe-extern-statics-mut.thir.stderr similarity index 100% rename from src/test/ui/safe-extern-statics-mut.thir.stderr rename to src/test/ui/static/safe-extern-statics-mut.thir.stderr diff --git a/src/test/ui/safe-extern-statics.mir.stderr b/src/test/ui/static/safe-extern-statics.mir.stderr similarity index 100% rename from src/test/ui/safe-extern-statics.mir.stderr rename to src/test/ui/static/safe-extern-statics.mir.stderr diff --git a/src/test/ui/safe-extern-statics.rs b/src/test/ui/static/safe-extern-statics.rs similarity index 100% rename from src/test/ui/safe-extern-statics.rs rename to src/test/ui/static/safe-extern-statics.rs diff --git a/src/test/ui/safe-extern-statics.thir.stderr b/src/test/ui/static/safe-extern-statics.thir.stderr similarity index 100% rename from src/test/ui/safe-extern-statics.thir.stderr rename to src/test/ui/static/safe-extern-statics.thir.stderr diff --git a/src/test/ui/static/static-mut-bad-types.stderr b/src/test/ui/static/static-mut-bad-types.stderr index ddd98ff407..983e1026f9 100644 --- a/src/test/ui/static/static-mut-bad-types.stderr +++ b/src/test/ui/static/static-mut-bad-types.stderr @@ -1,6 +1,9 @@ error[E0308]: mismatched types --> $DIR/static-mut-bad-types.rs:5:13 | +LL | static mut a: isize = 3; + | ----- expected due to this type +... LL | a = true; | ^^^^ expected `isize`, found `bool` diff --git a/src/test/ui/static_sized_requirement.rs b/src/test/ui/static/static_sized_requirement.rs similarity index 100% rename from src/test/ui/static_sized_requirement.rs rename to src/test/ui/static/static_sized_requirement.rs diff --git a/src/test/ui/thread-local-in-ctfe.rs b/src/test/ui/static/thread-local-in-ctfe.rs similarity index 100% rename from src/test/ui/thread-local-in-ctfe.rs rename to src/test/ui/static/thread-local-in-ctfe.rs diff --git a/src/test/ui/thread-local-in-ctfe.stderr b/src/test/ui/static/thread-local-in-ctfe.stderr similarity index 100% rename from src/test/ui/thread-local-in-ctfe.stderr rename to src/test/ui/static/thread-local-in-ctfe.stderr diff --git a/src/test/ui/issues/issue-14227.mir.stderr b/src/test/ui/statics/issue-14227.mir.stderr similarity index 100% rename from src/test/ui/issues/issue-14227.mir.stderr rename to src/test/ui/statics/issue-14227.mir.stderr diff --git a/src/test/ui/issues/issue-14227.rs b/src/test/ui/statics/issue-14227.rs similarity index 100% rename from src/test/ui/issues/issue-14227.rs rename to src/test/ui/statics/issue-14227.rs diff --git a/src/test/ui/issues/issue-14227.thir.stderr b/src/test/ui/statics/issue-14227.thir.stderr similarity index 100% rename from src/test/ui/issues/issue-14227.thir.stderr rename to src/test/ui/statics/issue-14227.thir.stderr diff --git a/src/test/ui/statics/issue-91050-1.rs b/src/test/ui/statics/issue-91050-1.rs new file mode 100644 index 0000000000..403a41462e --- /dev/null +++ b/src/test/ui/statics/issue-91050-1.rs @@ -0,0 +1,34 @@ +// build-pass +// compile-flags: --crate-type=rlib --emit=llvm-ir -Cno-prepopulate-passes + +// This test declares globals by the same name with different types, which +// caused problems because Module::getOrInsertGlobal would return a Constant* +// bitcast instead of a GlobalVariable* that could access linkage/visibility. +// In alt builds with LLVM assertions this would fail: +// +// rustc: /checkout/src/llvm-project/llvm/include/llvm/Support/Casting.h:269: +// typename cast_retty<X, Y *>::ret_type llvm::cast(Y *) [X = llvm::GlobalValue, Y = llvm::Value]: +// Assertion `isa<X>(Val) && "cast<Ty>() argument of incompatible type!"' failed. +// +// In regular builds, the bad cast was UB, like "Invalid LLVMRustVisibility value!" + +pub mod before { + #[no_mangle] + pub static GLOBAL1: [u8; 1] = [1]; +} + +pub mod inner { + extern "C" { + pub static GLOBAL1: u8; + pub static GLOBAL2: u8; + } + + pub fn call() { + drop(unsafe { (GLOBAL1, GLOBAL2) }); + } +} + +pub mod after { + #[no_mangle] + pub static GLOBAL2: [u8; 1] = [2]; +} diff --git a/src/test/ui/statics/issue-91050-2.rs b/src/test/ui/statics/issue-91050-2.rs new file mode 100644 index 0000000000..2ff954d15c --- /dev/null +++ b/src/test/ui/statics/issue-91050-2.rs @@ -0,0 +1,24 @@ +// build-pass +// compile-flags: --crate-type=rlib --emit=llvm-ir -Cno-prepopulate-passes + +// This is a variant of issue-91050-1.rs -- see there for an explanation. + +pub mod before { + extern "C" { + pub static GLOBAL1: [u8; 1]; + } + + pub unsafe fn do_something_with_array() -> u8 { + GLOBAL1[0] + } +} + +pub mod inner { + extern "C" { + pub static GLOBAL1: u8; + } + + pub unsafe fn call() -> u8 { + GLOBAL1 + 42 + } +} diff --git a/src/test/ui/statics/uninhabited-static.rs b/src/test/ui/statics/uninhabited-static.rs index cc78f6cfa5..d564547489 100644 --- a/src/test/ui/statics/uninhabited-static.rs +++ b/src/test/ui/statics/uninhabited-static.rs @@ -11,7 +11,11 @@ extern { static VOID2: Void = unsafe { std::mem::transmute(()) }; //~ ERROR static of uninhabited type //~| WARN: previously accepted +//~| ERROR undefined behavior to use this value +//~| WARN: type `Void` does not permit zero-initialization static NEVER2: Void = unsafe { std::mem::transmute(()) }; //~ ERROR static of uninhabited type //~| WARN: previously accepted +//~| ERROR undefined behavior to use this value +//~| WARN: type `Void` does not permit zero-initialization fn main() {} diff --git a/src/test/ui/statics/uninhabited-static.stderr b/src/test/ui/statics/uninhabited-static.stderr index 5d95b29993..c38cf10d6e 100644 --- a/src/test/ui/statics/uninhabited-static.stderr +++ b/src/test/ui/statics/uninhabited-static.stderr @@ -34,7 +34,7 @@ LL | static VOID2: Void = unsafe { std::mem::transmute(()) }; = note: uninhabited statics cannot be initialized, and any access would be an immediate error error: static of uninhabited type - --> $DIR/uninhabited-static.rs:14:1 + --> $DIR/uninhabited-static.rs:16:1 | LL | static NEVER2: Void = unsafe { std::mem::transmute(()) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -43,5 +43,47 @@ LL | static NEVER2: Void = unsafe { std::mem::transmute(()) }; = note: for more information, see issue #74840 <https://github.com/rust-lang/rust/issues/74840> = note: uninhabited statics cannot be initialized, and any access would be an immediate error -error: aborting due to 4 previous errors +error[E0080]: it is undefined behavior to use this value + --> $DIR/uninhabited-static.rs:12:1 + | +LL | static VOID2: Void = unsafe { std::mem::transmute(()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Void + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open 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/uninhabited-static.rs:16:1 + | +LL | static NEVER2: Void = unsafe { std::mem::transmute(()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Void + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open 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 `Void` does not permit zero-initialization + --> $DIR/uninhabited-static.rs:12:31 + | +LL | static VOID2: Void = 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: enums with no variants have no valid value + +warning: the type `Void` does not permit zero-initialization + --> $DIR/uninhabited-static.rs:16:32 + | +LL | static NEVER2: Void = 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: enums with no variants have no valid value + +error: aborting due to 6 previous errors; 2 warnings emitted +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/builtin-clone.rs b/src/test/ui/stdlib-unit-tests/builtin-clone.rs similarity index 100% rename from src/test/ui/builtin-clone.rs rename to src/test/ui/stdlib-unit-tests/builtin-clone.rs diff --git a/src/test/ui/eq-multidispatch.rs b/src/test/ui/stdlib-unit-tests/eq-multidispatch.rs similarity index 100% rename from src/test/ui/eq-multidispatch.rs rename to src/test/ui/stdlib-unit-tests/eq-multidispatch.rs diff --git a/src/test/ui/istr.rs b/src/test/ui/stdlib-unit-tests/istr.rs similarity index 100% rename from src/test/ui/istr.rs rename to src/test/ui/stdlib-unit-tests/istr.rs diff --git a/src/test/ui/log-knows-the-names-of-variants-in-std.rs b/src/test/ui/stdlib-unit-tests/log-knows-the-names-of-variants-in-std.rs similarity index 100% rename from src/test/ui/log-knows-the-names-of-variants-in-std.rs rename to src/test/ui/stdlib-unit-tests/log-knows-the-names-of-variants-in-std.rs diff --git a/src/test/ui/matches2021.rs b/src/test/ui/stdlib-unit-tests/matches2021.rs similarity index 86% rename from src/test/ui/matches2021.rs rename to src/test/ui/stdlib-unit-tests/matches2021.rs index f5497c1d16..9143a8cdd5 100644 --- a/src/test/ui/matches2021.rs +++ b/src/test/ui/stdlib-unit-tests/matches2021.rs @@ -1,6 +1,5 @@ // run-pass // edition:2021 -// compile-flags: -Zunstable-options // regression test for https://github.com/rust-lang/rust/pull/85678 diff --git a/src/test/ui/minmax-stability-issue-23687.rs b/src/test/ui/stdlib-unit-tests/minmax-stability-issue-23687.rs similarity index 100% rename from src/test/ui/minmax-stability-issue-23687.rs rename to src/test/ui/stdlib-unit-tests/minmax-stability-issue-23687.rs diff --git a/src/test/ui/not-sync.rs b/src/test/ui/stdlib-unit-tests/not-sync.rs similarity index 100% rename from src/test/ui/not-sync.rs rename to src/test/ui/stdlib-unit-tests/not-sync.rs diff --git a/src/test/ui/not-sync.stderr b/src/test/ui/stdlib-unit-tests/not-sync.stderr similarity index 100% rename from src/test/ui/not-sync.stderr rename to src/test/ui/stdlib-unit-tests/not-sync.stderr diff --git a/src/test/ui/raw-fat-ptr.rs b/src/test/ui/stdlib-unit-tests/raw-fat-ptr.rs similarity index 100% rename from src/test/ui/raw-fat-ptr.rs rename to src/test/ui/stdlib-unit-tests/raw-fat-ptr.rs diff --git a/src/test/ui/seq-compare.rs b/src/test/ui/stdlib-unit-tests/seq-compare.rs similarity index 100% rename from src/test/ui/seq-compare.rs rename to src/test/ui/stdlib-unit-tests/seq-compare.rs diff --git a/src/test/ui/volatile-fat-ptr.rs b/src/test/ui/stdlib-unit-tests/volatile-fat-ptr.rs similarity index 100% rename from src/test/ui/volatile-fat-ptr.rs rename to src/test/ui/stdlib-unit-tests/volatile-fat-ptr.rs diff --git a/src/test/ui/str/str-idx.stderr b/src/test/ui/str/str-idx.stderr index 47bd6f6bfa..9c3c364613 100644 --- a/src/test/ui/str/str-idx.stderr +++ b/src/test/ui/str/str-idx.stderr @@ -20,6 +20,11 @@ LL | let _ = s.get(4); = help: the trait `SliceIndex<str>` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings> +note: required by a bound in `core::str::<impl str>::get` + --> $SRC_DIR/core/src/str/mod.rs:LL:COL + | +LL | pub fn get<I: SliceIndex<str>>(&self, i: I) -> Option<&I::Output> { + | ^^^^^^^^^^^^^^^ required by this bound in `core::str::<impl str>::get` error[E0277]: the type `str` cannot be indexed by `{integer}` --> $DIR/str-idx.rs:5:29 @@ -32,6 +37,11 @@ LL | let _ = s.get_unchecked(4); = help: the trait `SliceIndex<str>` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings> +note: required by a bound in `core::str::<impl str>::get_unchecked` + --> $SRC_DIR/core/src/str/mod.rs:LL:COL + | +LL | pub unsafe fn get_unchecked<I: SliceIndex<str>>(&self, i: I) -> &I::Output { + | ^^^^^^^^^^^^^^^ required by this bound in `core::str::<impl str>::get_unchecked` error[E0277]: the type `str` cannot be indexed by `char` --> $DIR/str-idx.rs:6:17 diff --git a/src/test/ui/str/str-mut-idx.stderr b/src/test/ui/str/str-mut-idx.stderr index ab647c75cf..2559ee9eb4 100644 --- a/src/test/ui/str/str-mut-idx.stderr +++ b/src/test/ui/str/str-mut-idx.stderr @@ -44,6 +44,11 @@ LL | s.get_mut(1); = help: the trait `SliceIndex<str>` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings> +note: required by a bound in `core::str::<impl str>::get_mut` + --> $SRC_DIR/core/src/str/mod.rs:LL:COL + | +LL | pub fn get_mut<I: SliceIndex<str>>(&mut self, i: I) -> Option<&mut I::Output> { + | ^^^^^^^^^^^^^^^ required by this bound in `core::str::<impl str>::get_mut` error[E0277]: the type `str` cannot be indexed by `{integer}` --> $DIR/str-mut-idx.rs:11:25 @@ -56,6 +61,11 @@ LL | s.get_unchecked_mut(1); = help: the trait `SliceIndex<str>` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings> +note: required by a bound in `core::str::<impl str>::get_unchecked_mut` + --> $SRC_DIR/core/src/str/mod.rs:LL:COL + | +LL | pub unsafe fn get_unchecked_mut<I: SliceIndex<str>>(&mut self, i: I) -> &mut I::Output { + | ^^^^^^^^^^^^^^^ required by this bound in `core::str::<impl str>::get_unchecked_mut` error[E0277]: the type `str` cannot be indexed by `char` --> $DIR/str-mut-idx.rs:13:5 diff --git a/src/test/ui/issues/issue-50731.rs b/src/test/ui/structs-enums/issue-50731.rs similarity index 100% rename from src/test/ui/issues/issue-50731.rs rename to src/test/ui/structs-enums/issue-50731.rs diff --git a/src/test/ui/structs-enums/rec-align-u64.rs b/src/test/ui/structs-enums/rec-align-u64.rs index cc6412e271..3bc2d16cf9 100644 --- a/src/test/ui/structs-enums/rec-align-u64.rs +++ b/src/test/ui/structs-enums/rec-align-u64.rs @@ -36,6 +36,7 @@ struct Outer { target_os = "emscripten", target_os = "freebsd", target_os = "fuchsia", + target_os = "illumos", target_os = "linux", target_os = "macos", target_os = "netbsd", diff --git a/src/test/ui/large-records.rs b/src/test/ui/structs/large-records.rs similarity index 100% rename from src/test/ui/large-records.rs rename to src/test/ui/structs/large-records.rs diff --git a/src/test/ui/structs/struct-path-alias-bounds.stderr b/src/test/ui/structs/struct-path-alias-bounds.stderr index e0a22c2df1..7a80e7270b 100644 --- a/src/test/ui/structs/struct-path-alias-bounds.stderr +++ b/src/test/ui/structs/struct-path-alias-bounds.stderr @@ -4,11 +4,11 @@ error[E0277]: the trait bound `NoClone: Clone` is not satisfied LL | let s = A { a: NoClone }; | ^ the trait `Clone` is not implemented for `NoClone` | -note: required by `S` - --> $DIR/struct-path-alias-bounds.rs:3:1 +note: required by a bound in `S` + --> $DIR/struct-path-alias-bounds.rs:3:13 | LL | struct S<T: Clone> { a: T } - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^ required by this bound in `S` error: aborting due to previous error diff --git a/src/test/ui/suggest-using-chars.rs b/src/test/ui/suggest-using-chars.rs new file mode 100644 index 0000000000..95732881ba --- /dev/null +++ b/src/test/ui/suggest-using-chars.rs @@ -0,0 +1,7 @@ +pub fn main() { + let _ = "foo".iter(); //~ ERROR no method named `iter` found for reference `&'static str` in the current scope + let _ = "foo".foo(); //~ ERROR no method named `foo` found for reference `&'static str` in the current scope + let _ = String::from("bar").iter(); //~ ERROR no method named `iter` found for struct `String` in the current scope + let _ = (&String::from("bar")).iter(); //~ ERROR no method named `iter` found for reference `&String` in the current scope + let _ = 0.iter(); //~ ERROR no method named `iter` found for type `{integer}` in the current scope +} diff --git a/src/test/ui/suggest-using-chars.stderr b/src/test/ui/suggest-using-chars.stderr new file mode 100644 index 0000000000..99bcfb08a0 --- /dev/null +++ b/src/test/ui/suggest-using-chars.stderr @@ -0,0 +1,48 @@ +error[E0599]: no method named `iter` found for reference `&'static str` in the current scope + --> $DIR/suggest-using-chars.rs:2:19 + | +LL | let _ = "foo".iter(); + | ^^^^ method not found in `&'static str` + | +help: because of the in-memory representation of `&str`, to obtain an `Iterator` over each of its codepoint use method `chars` + | +LL | let _ = "foo".chars(); + | ~~~~~ + +error[E0599]: no method named `foo` found for reference `&'static str` in the current scope + --> $DIR/suggest-using-chars.rs:3:19 + | +LL | let _ = "foo".foo(); + | ^^^ method not found in `&'static str` + +error[E0599]: no method named `iter` found for struct `String` in the current scope + --> $DIR/suggest-using-chars.rs:4:33 + | +LL | let _ = String::from("bar").iter(); + | ^^^^ method not found in `String` + | +help: because of the in-memory representation of `&str`, to obtain an `Iterator` over each of its codepoint use method `chars` + | +LL | let _ = String::from("bar").chars(); + | ~~~~~ + +error[E0599]: no method named `iter` found for reference `&String` in the current scope + --> $DIR/suggest-using-chars.rs:5:36 + | +LL | let _ = (&String::from("bar")).iter(); + | ^^^^ method not found in `&String` + | +help: because of the in-memory representation of `&str`, to obtain an `Iterator` over each of its codepoint use method `chars` + | +LL | let _ = (&String::from("bar")).chars(); + | ~~~~~ + +error[E0599]: no method named `iter` found for type `{integer}` in the current scope + --> $DIR/suggest-using-chars.rs:6:15 + | +LL | let _ = 0.iter(); + | ^^^^ method not found in `{integer}` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr index 78ebb3d6bf..4759ebea0e 100644 --- a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr +++ b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -1,15 +1,15 @@ -error[E0277]: `fn() -> impl Future {foo}` is not a future +error[E0277]: `fn() -> impl Future<Output = ()> {foo}` is not a future --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:10:9 | LL | async fn foo() {} | --- consider calling this function ... LL | bar(foo); - | --- ^^^ `fn() -> impl Future {foo}` is not a future + | --- ^^^ `fn() -> impl Future<Output = ()> {foo}` is not a future | | | required by a bound introduced by this call | - = help: the trait `Future` is not implemented for `fn() -> impl Future {foo}` + = help: the trait `Future` is not implemented for `fn() -> impl Future<Output = ()> {foo}` note: required by a bound in `bar` --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16 | diff --git a/src/test/ui/bound-suggestions.fixed b/src/test/ui/suggestions/bound-suggestions.fixed similarity index 100% rename from src/test/ui/bound-suggestions.fixed rename to src/test/ui/suggestions/bound-suggestions.fixed diff --git a/src/test/ui/bound-suggestions.rs b/src/test/ui/suggestions/bound-suggestions.rs similarity index 100% rename from src/test/ui/bound-suggestions.rs rename to src/test/ui/suggestions/bound-suggestions.rs diff --git a/src/test/ui/bound-suggestions.stderr b/src/test/ui/suggestions/bound-suggestions.stderr similarity index 100% rename from src/test/ui/bound-suggestions.stderr rename to src/test/ui/suggestions/bound-suggestions.stderr diff --git a/src/test/ui/suggestions/boxed-variant-field.rs b/src/test/ui/suggestions/boxed-variant-field.rs new file mode 100644 index 0000000000..9b9e70a675 --- /dev/null +++ b/src/test/ui/suggestions/boxed-variant-field.rs @@ -0,0 +1,16 @@ +enum Ty { + Unit, + List(Box<Ty>), +} + +fn foo(x: Ty) -> Ty { + match x { + Ty::Unit => Ty::Unit, + Ty::List(elem) => foo(elem), + //~^ ERROR mismatched types + //~| HELP try dereferencing the `Box` + //~| HELP try wrapping + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/boxed-variant-field.stderr b/src/test/ui/suggestions/boxed-variant-field.stderr new file mode 100644 index 0000000000..e865b993a4 --- /dev/null +++ b/src/test/ui/suggestions/boxed-variant-field.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/boxed-variant-field.rs:9:31 + | +LL | Ty::List(elem) => foo(elem), + | ^^^^ expected enum `Ty`, found struct `Box` + | + = note: expected enum `Ty` + found struct `Box<Ty>` +help: try dereferencing the `Box` + | +LL | Ty::List(elem) => foo(*elem), + | + +help: try wrapping the expression in `Ty::List` + | +LL | Ty::List(elem) => foo(Ty::List(elem)), + | +++++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/core-std-import-order-issue-83564.stderr b/src/test/ui/suggestions/core-std-import-order-issue-83564.stderr index d484fb8cbe..ce85d93b96 100644 --- a/src/test/ui/suggestions/core-std-import-order-issue-83564.stderr +++ b/src/test/ui/suggestions/core-std-import-order-issue-83564.stderr @@ -6,10 +6,10 @@ LL | let _x = NonZeroU32::new(5).unwrap(); | help: consider importing one of these items | -LL | use std::num::NonZeroU32; - | LL | use core::num::NonZeroU32; | +LL | use std::num::NonZeroU32; + | error: aborting due to previous error 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 aa3175dae2..550ed4b03b 100644 --- a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr +++ b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr @@ -46,11 +46,11 @@ LL | Pin::new(x) | ^^^^^^^^ the trait `Unpin` is not implemented for `dyn Future<Output = i32> + Send` | = note: consider using `Box::pin` -note: required by `Pin::<P>::new` +note: required by a bound in `Pin::<P>::new` --> $SRC_DIR/core/src/pin.rs:LL:COL | -LL | pub const fn new(pointer: P) -> Pin<P> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl<P: Deref<Target: Unpin>> Pin<P> { + | ^^^^^ required by this bound in `Pin::<P>::new` error[E0277]: `dyn Future<Output = i32> + Send` cannot be unpinned --> $DIR/expected-boxed-future-isnt-pinned.rs:24:5 @@ -59,11 +59,11 @@ LL | Pin::new(Box::new(x)) | ^^^^^^^^ the trait `Unpin` is not implemented for `dyn Future<Output = i32> + Send` | = note: consider using `Box::pin` -note: required by `Pin::<P>::new` +note: required by a bound in `Pin::<P>::new` --> $SRC_DIR/core/src/pin.rs:LL:COL | -LL | pub const fn new(pointer: P) -> Pin<P> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl<P: Deref<Target: Unpin>> Pin<P> { + | ^^^^^ required by this bound in `Pin::<P>::new` error[E0308]: mismatched types --> $DIR/expected-boxed-future-isnt-pinned.rs:28:5 @@ -81,7 +81,7 @@ LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return> | ------------------------------- the found opaque type | = note: expected struct `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>` - found opaque type `impl Future` + found opaque type `impl Future<Output = [async output]>` help: you need to pin and box this expression | LL ~ Box::pin(async { diff --git a/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr index b111df49f6..101e7aecc0 100644 --- a/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr +++ b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -1,11 +1,11 @@ -error[E0277]: the trait bound `fn() -> impl T {foo}: T` is not satisfied +error[E0277]: the trait bound `fn() -> impl T<O = ()> {foo}: T` is not satisfied --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:17:9 | LL | fn foo() -> impl T<O=()> { S } | --- consider calling this function ... LL | bar(foo); - | --- ^^^ the trait `T` is not implemented for `fn() -> impl T {foo}` + | --- ^^^ the trait `T` is not implemented for `fn() -> impl T<O = ()> {foo}` | | | required by a bound introduced by this call | diff --git a/src/test/ui/suggestions/if-let-typo.stderr b/src/test/ui/suggestions/if-let-typo.stderr index 7f71cb4858..058f42f220 100644 --- a/src/test/ui/suggestions/if-let-typo.stderr +++ b/src/test/ui/suggestions/if-let-typo.stderr @@ -70,11 +70,6 @@ error[E0308]: mismatched types | LL | if 3 = foo {} | ^^^^^^^ expected `bool`, found `()` - | -help: you might have meant to use pattern matching - | -LL | if let 3 = foo {} - | +++ error[E0070]: invalid left-hand side of assignment --> $DIR/if-let-typo.rs:10:16 diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.nll.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.nll.stderr index 80d3c940eb..2dc300ac76 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.nll.stderr +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.nll.stderr @@ -1,17 +1,8 @@ -error[E0597]: `val` does not live long enough +error[E0515]: cannot return reference to function parameter `val` --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:21:9 | -LL | fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> { - | -- lifetime `'a` defined here ------------------- opaque type requires that `val` is borrowed for `'a` LL | val.use_self() - | ^^^^^^^^^^^^^^ borrowed value does not live long enough -LL | } - | - `val` dropped here while still borrowed - | -help: you can add a bound to the opaque type to make it last less than `'static` and match `'a` - | -LL | fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> + 'a { - | ++++ + | ^^^^^^^^^^^^^^ returns a reference to data owned by the current function error[E0515]: cannot return reference to function parameter `val` --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:43:9 @@ -27,5 +18,4 @@ LL | val.use_self() error: aborting due to 3 previous errors -Some errors have detailed explanations: E0515, E0597. -For more information about an error, try `rustc --explain E0515`. +For more information about this error, try `rustc --explain E0515`. diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs index b2dc16a27e..0045d3fcf1 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs @@ -18,7 +18,7 @@ mod bav { impl Bar for i32 {} fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> { - val.use_self() //~ ERROR E0597 + val.use_self() //~ ERROR cannot return reference to function parameter } } diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr index e8c3a7908f..2961d8d7ea 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr @@ -1,17 +1,8 @@ -error[E0597]: `val` does not live long enough +error[E0515]: cannot return reference to function parameter `val` --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:21:9 | -LL | fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> { - | -- lifetime `'a` defined here ------------------- opaque type requires that `val` is borrowed for `'a` LL | val.use_self() - | ^^^^^^^^^^^^^^ borrowed value does not live long enough -LL | } - | - `val` dropped here while still borrowed - | -help: you can add a bound to the opaque type to make it last less than `'static` and match `'a` - | -LL | fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> + 'a { - | ++++ + | ^^^^^^^^^^^^^^ returns a reference to data owned by the current function error[E0515]: cannot return reference to function parameter `val` --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:43:9 @@ -47,5 +38,4 @@ LL | impl MyTrait for Box<dyn ObjectTrait<Assoc = i32> + '_> { error: aborting due to 4 previous errors -Some errors have detailed explanations: E0515, E0597. -For more information about an error, try `rustc --explain E0515`. +For more information about this error, try `rustc --explain E0515`. diff --git a/src/test/ui/suggestions/into-str.stderr b/src/test/ui/suggestions/into-str.stderr index 263d509075..0d9ecc32e0 100644 --- a/src/test/ui/suggestions/into-str.stderr +++ b/src/test/ui/suggestions/into-str.stderr @@ -1,8 +1,10 @@ error[E0277]: the trait bound `&str: From<String>` is not satisfied - --> $DIR/into-str.rs:4:5 + --> $DIR/into-str.rs:4:9 | LL | foo(String::new()); - | ^^^ the trait `From<String>` is not implemented for `&str` + | --- ^^^^^^^^^^^^^ the trait `From<String>` is not implemented for `&str` + | | + | required by a bound introduced by this call | = 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` diff --git a/src/test/ui/suggestions/issue-62843.stderr b/src/test/ui/suggestions/issue-62843.stderr index 29ba39cbe1..bc1c69406d 100644 --- a/src/test/ui/suggestions/issue-62843.stderr +++ b/src/test/ui/suggestions/issue-62843.stderr @@ -8,6 +8,11 @@ LL | println!("{:?}", line.find(pattern)); | = note: the trait bound `String: Pattern<'_>` is not satisfied = note: required because of the requirements on the impl of `Pattern<'_>` for `String` +note: required by a bound in `core::str::<impl str>::find` + --> $SRC_DIR/core/src/str/mod.rs:LL:COL + | +LL | pub fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> { + | ^^^^^^^^^^^ required by this bound in `core::str::<impl str>::find` help: consider borrowing here | LL | println!("{:?}", line.find(&pattern)); diff --git a/src/test/ui/suggestions/issue-72766.stderr b/src/test/ui/suggestions/issue-72766.stderr index 43ba35d020..f257bb9b0e 100644 --- a/src/test/ui/suggestions/issue-72766.stderr +++ b/src/test/ui/suggestions/issue-72766.stderr @@ -2,14 +2,9 @@ error[E0277]: the `?` operator can only be applied to values that implement `Try --> $DIR/issue-72766.rs:14:5 | LL | SadGirl {}.call()?; - | ^^^^^^^^^^^^^^^^^^ the `?` operator cannot be applied to type `impl Future` + | ^^^^^^^^^^^^^^^^^^ the `?` operator cannot be applied to type `impl Future<Output = Result<(), ()>>` | - = help: the trait `Try` is not implemented for `impl Future` -note: required by `branch` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn branch(self) -> ControlFlow<Self::Residual, Self::Output>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: the trait `Try` is not implemented for `impl Future<Output = Result<(), ()>>` help: consider `await`ing on the `Future` | LL | SadGirl {}.call().await?; diff --git a/src/test/ui/suggestions/issue-81839.stderr b/src/test/ui/suggestions/issue-81839.stderr index 1e0aa9ce40..0b1c41b837 100644 --- a/src/test/ui/suggestions/issue-81839.stderr +++ b/src/test/ui/suggestions/issue-81839.stderr @@ -20,7 +20,7 @@ note: while checking the return type of the `async fn` LL | pub async fn answer_str(&self, _s: &str) -> Test { | ^^^^ checked the `Output` of this `async fn`, found opaque type = note: expected type `()` - found opaque type `impl Future` + found opaque type `impl Future<Output = Test>` error: aborting due to previous error diff --git a/src/test/ui/suggestions/issue-84973.stderr b/src/test/ui/suggestions/issue-84973.stderr index 16a28c73aa..24c989ec3e 100644 --- a/src/test/ui/suggestions/issue-84973.stderr +++ b/src/test/ui/suggestions/issue-84973.stderr @@ -6,11 +6,14 @@ LL | let o = Other::new(f); | | | required by a bound introduced by this call | -note: required by `Other::<'a, G>::new` - --> $DIR/issue-84973.rs:27:5 +note: required by a bound in `Other::<'a, G>::new` + --> $DIR/issue-84973.rs:25:8 | +LL | G: SomeTrait, + | ^^^^^^^^^ required by this bound in `Other::<'a, G>::new` +LL | { LL | pub fn new(g: G) -> Self { - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | --- required by a bound in this help: consider borrowing here | LL | let o = Other::new(&f); diff --git a/src/test/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.rs b/src/test/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.rs new file mode 100644 index 0000000000..5cfaf4be96 --- /dev/null +++ b/src/test/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.rs @@ -0,0 +1,8 @@ +// Regression test for #85945: Don't suggest `?Sized` bound if an explicit +// `Sized` bound is already in a `where` clause. +fn foo<T>(_: &T) where T: Sized {} +fn bar() { foo(""); } +//~^ERROR the size for values of type + +pub fn main() { +} diff --git a/src/test/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr b/src/test/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr new file mode 100644 index 0000000000..92be9f764c --- /dev/null +++ b/src/test/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr @@ -0,0 +1,18 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/issue-85945-check-where-clause-before-suggesting-unsized.rs:4:16 + | +LL | fn bar() { foo(""); } + | --- ^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `str` +note: required by a bound in `foo` + --> $DIR/issue-85945-check-where-clause-before-suggesting-unsized.rs:3:8 + | +LL | fn foo<T>(_: &T) where T: Sized {} + | ^ required by this bound in `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/issue-90974.rs b/src/test/ui/suggestions/issue-90974.rs new file mode 100644 index 0000000000..83590dbf7a --- /dev/null +++ b/src/test/ui/suggestions/issue-90974.rs @@ -0,0 +1,3 @@ +fn main() { + println!("{}", (3.).recip()); //~ERROR +} diff --git a/src/test/ui/suggestions/issue-90974.stderr b/src/test/ui/suggestions/issue-90974.stderr new file mode 100644 index 0000000000..e1fb479a3a --- /dev/null +++ b/src/test/ui/suggestions/issue-90974.stderr @@ -0,0 +1,14 @@ +error[E0689]: can't call method `recip` on ambiguous numeric type `{float}` + --> $DIR/issue-90974.rs:2:25 + | +LL | println!("{}", (3.).recip()); + | ^^^^^ + | +help: you must specify a concrete type for this numeric value, like `f32` + | +LL | println!("{}", (3_f32).recip()); + | ~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0689`. diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr index 0cf0074dc3..adb928aa8a 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr @@ -11,11 +11,16 @@ note: the parameter type `T` must be valid for the anonymous lifetime defined he | LL | fn func<T: Test>(foo: &Foo, t: T) { | ^^^ -note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature-2.rs:20:13: 23:6]` will meet its required lifetime bounds +note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature-2.rs:20:13: 23:6]` will meet its required lifetime bounds... --> $DIR/missing-lifetimes-in-signature-2.rs:20:9 | LL | foo.bar(move |_| { | ^^^ +note: ...that is required by this bound + --> $DIR/missing-lifetimes-in-signature-2.rs:11:12 + | +LL | F: 'a, + | ^^ error: aborting due to previous error diff --git a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.nll.stderr b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.nll.stderr index b579635ca7..3ed3827b97 100644 --- a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.nll.stderr +++ b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.nll.stderr @@ -1,10 +1,13 @@ error: lifetime may not live long enough - --> $DIR/trait-object-nested-in-impl-trait.rs:27:23 + --> $DIR/trait-object-nested-in-impl-trait.rs:28:9 | -LL | fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> { - | - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ opaque type requires that `'1` must outlive `'static` - | | - | let's call the lifetime of this reference `'1` +LL | fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> { + | - let's call the lifetime of this reference `'1` +LL | / Iter { +LL | | current: None, +LL | | remaining: self.0.iter(), +LL | | } + | |_________^ returning this value requires that `'1` must outlive `'static` | help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound | @@ -34,12 +37,15 @@ LL | | } | |_________^ returning this value requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/trait-object-nested-in-impl-trait.rs:60:30 + --> $DIR/trait-object-nested-in-impl-trait.rs:61:9 | -LL | fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> { - | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ opaque type requires that `'a` must outlive `'static` - | | - | lifetime `'a` defined here +LL | fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> { + | -- lifetime `'a` defined here +LL | / Iter { +LL | | current: None, +LL | | remaining: self.0.iter(), +LL | | } + | |_________^ returning this value requires that `'a` must outlive `'static` | help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a bound | diff --git a/src/test/ui/suggestions/match-prev-arm-needing-semi.rs b/src/test/ui/suggestions/match-prev-arm-needing-semi.rs index 990a446976..6aa93a24d2 100644 --- a/src/test/ui/suggestions/match-prev-arm-needing-semi.rs +++ b/src/test/ui/suggestions/match-prev-arm-needing-semi.rs @@ -55,7 +55,7 @@ async fn async_different_futures() { //~| HELP consider `await`ing on both `Future`s false => async_dummy2(), //~ ERROR `match` arms have incompatible types //~^ NOTE expected opaque type, found a different opaque type - //~| NOTE expected type `impl Future` + //~| NOTE expected type `impl Future<Output = ()>` //~| NOTE distinct uses of `impl Trait` result in different opaque types }; } diff --git a/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr b/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr index a8f7f3cb17..b55c51b928 100644 --- a/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr +++ b/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr @@ -21,7 +21,7 @@ note: while checking the return type of the `async fn` LL | async fn async_dummy() {} | ^ checked the `Output` of this `async fn`, found opaque type = note: expected type `()` - found opaque type `impl Future` + found opaque type `impl Future<Output = ()>` help: consider `await`ing on the `Future` | LL | false => async_dummy().await, @@ -55,7 +55,7 @@ note: while checking the return type of the `async fn` LL | async fn async_dummy2() {} | ^ checked the `Output` of this `async fn`, found opaque type = note: expected type `()` - found opaque type `impl Future` + found opaque type `impl Future<Output = ()>` help: consider `await`ing on the `Future` | LL | false => async_dummy2().await, @@ -74,7 +74,7 @@ error[E0308]: `match` arms have incompatible types LL | let _ = match true { | _____________- LL | | true => async_dummy(), - | | ------------- this is found to be of type `impl Future` + | | ------------- this is found to be of type `impl Future<Output = ()>` LL | | LL | | false => async_dummy2(), | | ^^^^^^^^^^^^^^ expected opaque type, found a different opaque type @@ -88,8 +88,8 @@ note: while checking the return type of the `async fn` | LL | async fn async_dummy2() {} | ^ checked the `Output` of this `async fn`, found opaque type - = note: expected type `impl Future` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:16:24>) - found opaque type `impl Future` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:19:25>) + = note: expected type `impl Future<Output = ()>` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:16:24>) + found opaque type `impl Future<Output = ()>` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:19:25>) = note: distinct uses of `impl Trait` result in different opaque types help: consider `await`ing on both `Future`s | diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr index e6a2231390..d121932c84 100644 --- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr +++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr @@ -7,11 +7,11 @@ LL | let fp = BufWriter::new(fp); | required by a bound introduced by this call | = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write` -note: required by `BufWriter::<W>::new` +note: required by a bound in `BufWriter::<W>::new` --> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL | -LL | pub fn new(inner: W) -> BufWriter<W> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl<W: Write> BufWriter<W> { + | ^^^^^ required by this bound in `BufWriter::<W>::new` error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied --> $DIR/mut-borrow-needed-by-trait.rs:17:14 diff --git a/src/test/ui/suggestions/mut-ref-reassignment.stderr b/src/test/ui/suggestions/mut-ref-reassignment.stderr index fd5677898e..3bd98c7630 100644 --- a/src/test/ui/suggestions/mut-ref-reassignment.stderr +++ b/src/test/ui/suggestions/mut-ref-reassignment.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/mut-ref-reassignment.rs:2:11 | +LL | fn suggestion(opt: &mut Option<String>) { + | ------------------- expected due to this parameter type LL | opt = None; | ^^^^ expected mutable reference, found enum `Option` | @@ -14,6 +16,8 @@ LL | *opt = None; error[E0308]: mismatched types --> $DIR/mut-ref-reassignment.rs:6:11 | +LL | fn no_suggestion(opt: &mut Result<String, ()>) { + | ----------------------- expected due to this parameter type LL | opt = None | ^^^^ expected mutable reference, found enum `Option` | @@ -23,6 +27,8 @@ LL | opt = None error[E0308]: mismatched types --> $DIR/mut-ref-reassignment.rs:10:11 | +LL | fn suggestion2(opt: &mut Option<String>) { + | ------------------- expected due to this parameter type LL | opt = Some(String::new()) | ^^^^^^^^^^^^^^^^^^^ expected mutable reference, found enum `Option` | @@ -36,6 +42,8 @@ LL | *opt = Some(String::new()) error[E0308]: mismatched types --> $DIR/mut-ref-reassignment.rs:14:11 | +LL | fn no_suggestion2(opt: &mut Option<String>) { + | ------------------- expected due to this parameter type LL | opt = Some(42) | ^^^^^^^^ expected mutable reference, found enum `Option` | diff --git a/src/test/ui/suggestions/opaque-type-error.stderr b/src/test/ui/suggestions/opaque-type-error.stderr index 8510737345..e065e0aaa8 100644 --- a/src/test/ui/suggestions/opaque-type-error.stderr +++ b/src/test/ui/suggestions/opaque-type-error.stderr @@ -13,8 +13,8 @@ LL | | thing_two() LL | | }.await | |_____- `if` and `else` have incompatible types | - = note: expected type `impl Future` (opaque type at <$DIR/opaque-type-error.rs:8:19>) - found opaque type `impl Future` (opaque type at <$DIR/opaque-type-error.rs:12:19>) + = note: expected type `impl Future<Output = Result<(), ()>>` (opaque type at <$DIR/opaque-type-error.rs:8:19>) + found opaque type `impl Future<Output = Result<(), ()>>` (opaque type at <$DIR/opaque-type-error.rs:12:19>) = note: distinct uses of `impl Trait` result in different opaque types help: consider `await`ing on both `Future`s | diff --git a/src/test/ui/suggestions/slice-issue-87994.stderr b/src/test/ui/suggestions/slice-issue-87994.stderr index 0275fd475d..fd2a44f9a8 100644 --- a/src/test/ui/suggestions/slice-issue-87994.stderr +++ b/src/test/ui/suggestions/slice-issue-87994.stderr @@ -6,11 +6,6 @@ LL | for _ in v[1..] { | = note: the trait bound `[i32]: IntoIterator` is not satisfied = note: required because of the requirements on the impl of `IntoIterator` for `[i32]` -note: required by `into_iter` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider borrowing here | LL | for _ in &v[1..] { @@ -26,11 +21,6 @@ LL | for _ in v[1..] { | = note: the trait bound `[i32]: IntoIterator` is not satisfied = note: required because of the requirements on the impl of `IntoIterator` for `[i32]` -note: required by `into_iter` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider borrowing here | LL | for _ in &v[1..] { @@ -46,11 +36,6 @@ LL | for i2 in v2[1..] { | = note: the trait bound `[K]: IntoIterator` is not satisfied = note: required because of the requirements on the impl of `IntoIterator` for `[K]` -note: required by `into_iter` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider borrowing here | LL | for i2 in &v2[1..] { @@ -66,11 +51,6 @@ LL | for i2 in v2[1..] { | = note: the trait bound `[K]: IntoIterator` is not satisfied = note: required because of the requirements on the impl of `IntoIterator` for `[K]` -note: required by `into_iter` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider borrowing here | LL | for i2 in &v2[1..] { diff --git a/src/test/ui/suggestions/suggest-change-mut.stderr b/src/test/ui/suggestions/suggest-change-mut.stderr index 8dfab8dfa1..2fa69cd5a2 100644 --- a/src/test/ui/suggestions/suggest-change-mut.stderr +++ b/src/test/ui/suggestions/suggest-change-mut.stderr @@ -6,11 +6,11 @@ LL | let mut stream_reader = BufReader::new(&stream); | | | required by a bound introduced by this call | -note: required by `BufReader::<R>::new` +note: required by a bound in `BufReader::<R>::new` --> $SRC_DIR/std/src/io/buffered/bufreader.rs:LL:COL | -LL | pub fn new(inner: R) -> BufReader<R> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl<R: Read> BufReader<R> { + | ^^^^ required by this bound in `BufReader::<R>::new` help: consider removing the leading `&`-reference | LL - let mut stream_reader = BufReader::new(&stream); diff --git a/src/test/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr b/src/test/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr index 22a0ce1e91..9b6dba7e9e 100644 --- a/src/test/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr +++ b/src/test/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr @@ -2,14 +2,16 @@ error[E0308]: mismatched types --> $DIR/suggest-full-enum-variant-for-local-module.rs:9:28 | LL | let _: option::O<()> = (); - | ------------- ^^ - | | | - | | expected enum `O`, found `()` - | | help: try using a variant of the expected enum: `option::O::Some(())` + | ------------- ^^ expected enum `O`, found `()` + | | | expected due to this | = note: expected enum `O<()>` found unit type `()` +help: try wrapping the expression in `option::O::Some` + | +LL | let _: option::O<()> = option::O::Some(()); + | ++++++++++++++++ + error: aborting due to previous error diff --git a/src/test/ui/suggestions/suggest-on-bare-closure-call.stderr b/src/test/ui/suggestions/suggest-on-bare-closure-call.stderr index 0c91e2feed..81f2e498fe 100644 --- a/src/test/ui/suggestions/suggest-on-bare-closure-call.stderr +++ b/src/test/ui/suggestions/suggest-on-bare-closure-call.stderr @@ -6,7 +6,7 @@ LL | let _ = ||{}(); | | | call expression requires function | -help: if you meant to create this closure and immediately call it, surround the closure with parenthesis +help: if you meant to create this closure and immediately call it, surround the closure with parentheses | LL | let _ = (||{})(); | + + diff --git a/src/test/ui/suggestions/suggest-remove-refs-1.stderr b/src/test/ui/suggestions/suggest-remove-refs-1.stderr index a5c01484d4..1083b2f971 100644 --- a/src/test/ui/suggestions/suggest-remove-refs-1.stderr +++ b/src/test/ui/suggestions/suggest-remove-refs-1.stderr @@ -9,11 +9,6 @@ LL | for (i, _) in &v.iter().enumerate() { | = help: the trait `Iterator` is not implemented for `&Enumerate<std::slice::Iter<'_, {integer}>>` = note: required because of the requirements on the impl of `IntoIterator` for `&Enumerate<std::slice::Iter<'_, {integer}>>` -note: required by `into_iter` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/suggestions/suggest-remove-refs-2.stderr b/src/test/ui/suggestions/suggest-remove-refs-2.stderr index b128590f9d..197b19a1bf 100644 --- a/src/test/ui/suggestions/suggest-remove-refs-2.stderr +++ b/src/test/ui/suggestions/suggest-remove-refs-2.stderr @@ -9,11 +9,6 @@ LL | for (i, _) in & & & & &v.iter().enumerate() { | = help: the trait `Iterator` is not implemented for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` = note: required because of the requirements on the impl of `IntoIterator` for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` -note: required by `into_iter` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/suggestions/suggest-remove-refs-3.stderr b/src/test/ui/suggestions/suggest-remove-refs-3.stderr index 1c32a33e37..bb0cceac1d 100644 --- a/src/test/ui/suggestions/suggest-remove-refs-3.stderr +++ b/src/test/ui/suggestions/suggest-remove-refs-3.stderr @@ -13,11 +13,6 @@ LL | | .enumerate() { | = help: the trait `Iterator` is not implemented for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` = note: required because of the requirements on the impl of `IntoIterator` for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` -note: required by `into_iter` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/suggestions/suggest-tryinto-edition-change.rs b/src/test/ui/suggestions/suggest-tryinto-edition-change.rs new file mode 100644 index 0000000000..f03b42bbe4 --- /dev/null +++ b/src/test/ui/suggestions/suggest-tryinto-edition-change.rs @@ -0,0 +1,31 @@ +// Make sure that trying to access `TryInto`, `TryFrom`, `FromIterator` in pre-2021 mentions +// Edition 2021 change +// edition:2018 + +fn test() { + let _i: i16 = 0_i32.try_into().unwrap(); + //~^ ERROR no method named `try_into` found for type `i32` in the current scope + //~| NOTE method not found in `i32` + //~| NOTE 'std::convert::TryInto' is included in the prelude starting in Edition 2021 + + let _i: i16 = TryFrom::try_from(0_i32).unwrap(); + //~^ ERROR failed to resolve: use of undeclared type + //~| NOTE not found in this scope + //~| NOTE 'std::convert::TryFrom' is included in the prelude starting in Edition 2021 + //~| NOTE 'core::convert::TryFrom' is included in the prelude starting in Edition 2021 + + let _i: i16 = TryInto::try_into(0_i32).unwrap(); + //~^ ERROR failed to resolve: use of undeclared type + //~| NOTE not found in this scope + //~| NOTE 'std::convert::TryInto' is included in the prelude starting in Edition 2021 + //~| NOTE 'core::convert::TryInto' is included in the prelude starting in Edition 2021 + + let _v: Vec<_> = FromIterator::from_iter(&[1]); + //~^ ERROR failed to resolve: use of undeclared type + //~| NOTE 'std::iter::FromIterator' is included in the prelude starting in Edition 2021 + //~| NOTE 'core::iter::FromIterator' is included in the prelude starting in Edition 2021 +} + +fn main() { + test(); +} diff --git a/src/test/ui/suggestions/suggest-tryinto-edition-change.stderr b/src/test/ui/suggestions/suggest-tryinto-edition-change.stderr new file mode 100644 index 0000000000..86f48716b1 --- /dev/null +++ b/src/test/ui/suggestions/suggest-tryinto-edition-change.stderr @@ -0,0 +1,76 @@ +error[E0433]: failed to resolve: use of undeclared type `TryFrom` + --> $DIR/suggest-tryinto-edition-change.rs:11:19 + | +LL | let _i: i16 = TryFrom::try_from(0_i32).unwrap(); + | ^^^^^^^ not found in this scope + | + = note: 'std::convert::TryFrom' is included in the prelude starting in Edition 2021 + = note: 'core::convert::TryFrom' is included in the prelude starting in Edition 2021 +help: consider importing one of these items + | +LL | use core::convert::TryFrom; + | +LL | use std::convert::TryFrom; + | + +error[E0433]: failed to resolve: use of undeclared type `TryInto` + --> $DIR/suggest-tryinto-edition-change.rs:17:19 + | +LL | let _i: i16 = TryInto::try_into(0_i32).unwrap(); + | ^^^^^^^ not found in this scope + | + = note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021 + = note: 'core::convert::TryInto' is included in the prelude starting in Edition 2021 +help: consider importing one of these items + | +LL | use core::convert::TryInto; + | +LL | use std::convert::TryInto; + | + +error[E0433]: failed to resolve: use of undeclared type `FromIterator` + --> $DIR/suggest-tryinto-edition-change.rs:23:22 + | +LL | let _v: Vec<_> = FromIterator::from_iter(&[1]); + | ^^^^^^^^^^^^ + | + ::: $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | pub trait IntoIterator { + | ---------------------- similarly named trait `IntoIterator` defined here + | + = note: 'std::iter::FromIterator' is included in the prelude starting in Edition 2021 + = note: 'core::iter::FromIterator' is included in the prelude starting in Edition 2021 +help: a trait with a similar name exists + | +LL | let _v: Vec<_> = IntoIterator::from_iter(&[1]); + | ~~~~~~~~~~~~ +help: consider importing one of these items + | +LL | use core::iter::FromIterator; + | +LL | use std::iter::FromIterator; + | + +error[E0599]: no method named `try_into` found for type `i32` in the current scope + --> $DIR/suggest-tryinto-edition-change.rs:6:25 + | +LL | let _i: i16 = 0_i32.try_into().unwrap(); + | ^^^^^^^^ method not found in `i32` + | + ::: $SRC_DIR/core/src/convert/mod.rs:LL:COL + | +LL | fn try_into(self) -> Result<T, Self::Error>; + | -------- the method is available for `i32` here + | + = help: items from traits can only be used if the trait is in scope + = note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021 +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use std::convert::TryInto; + | + +error: aborting due to 4 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/suggestions/undeclared-module-alloc.rs b/src/test/ui/suggestions/undeclared-module-alloc.rs new file mode 100644 index 0000000000..1defa1cef2 --- /dev/null +++ b/src/test/ui/suggestions/undeclared-module-alloc.rs @@ -0,0 +1,5 @@ +// edition:2018 + +use alloc::rc::Rc; //~ ERROR failed to resolve: use of undeclared crate or module `alloc` + +fn main() {} diff --git a/src/test/ui/suggestions/undeclared-module-alloc.stderr b/src/test/ui/suggestions/undeclared-module-alloc.stderr new file mode 100644 index 0000000000..39169dfa9f --- /dev/null +++ b/src/test/ui/suggestions/undeclared-module-alloc.stderr @@ -0,0 +1,11 @@ +error[E0433]: failed to resolve: use of undeclared crate or module `alloc` + --> $DIR/undeclared-module-alloc.rs:3:5 + | +LL | use alloc::rc::Rc; + | ^^^^^ use of undeclared crate or module `alloc` + | + = help: add `extern crate alloc` to use the `alloc` crate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/auxiliary/changing-crates-a1.rs b/src/test/ui/svh/auxiliary/changing-crates-a1.rs similarity index 100% rename from src/test/ui/auxiliary/changing-crates-a1.rs rename to src/test/ui/svh/auxiliary/changing-crates-a1.rs diff --git a/src/test/ui/auxiliary/changing-crates-a2.rs b/src/test/ui/svh/auxiliary/changing-crates-a2.rs similarity index 100% rename from src/test/ui/auxiliary/changing-crates-a2.rs rename to src/test/ui/svh/auxiliary/changing-crates-a2.rs diff --git a/src/test/ui/auxiliary/changing-crates-b.rs b/src/test/ui/svh/auxiliary/changing-crates-b.rs similarity index 100% rename from src/test/ui/auxiliary/changing-crates-b.rs rename to src/test/ui/svh/auxiliary/changing-crates-b.rs diff --git a/src/test/ui/changing-crates.rs b/src/test/ui/svh/changing-crates.rs similarity index 100% rename from src/test/ui/changing-crates.rs rename to src/test/ui/svh/changing-crates.rs diff --git a/src/test/ui/changing-crates.stderr b/src/test/ui/svh/changing-crates.stderr similarity index 100% rename from src/test/ui/changing-crates.stderr rename to src/test/ui/svh/changing-crates.stderr diff --git a/src/test/ui/syntax-trait-polarity-feature-gate.rs b/src/test/ui/syntax-trait-polarity-feature-gate.rs deleted file mode 100644 index 4a3b24383a..0000000000 --- a/src/test/ui/syntax-trait-polarity-feature-gate.rs +++ /dev/null @@ -1,10 +0,0 @@ -use std::marker::Send; - -struct TestType; - -trait TestTrait {} - -impl !Send for TestType {} -//~^ ERROR negative trait bounds - -fn main() {} diff --git a/src/test/ui/syntax-trait-polarity-feature-gate.stderr b/src/test/ui/syntax-trait-polarity-feature-gate.stderr deleted file mode 100644 index 3562deecbd..0000000000 --- a/src/test/ui/syntax-trait-polarity-feature-gate.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: negative trait bounds are not yet fully implemented; use marker types for now - --> $DIR/syntax-trait-polarity-feature-gate.rs:7:6 - | -LL | impl !Send for TestType {} - | ^^^^^ - | - = note: see issue #68318 <https://github.com/rust-lang/rust/issues/68318> for more information - = help: add `#![feature(negative_impls)]` 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/synthetic-param.rs b/src/test/ui/synthetic-param.rs deleted file mode 100644 index e14697f5c3..0000000000 --- a/src/test/ui/synthetic-param.rs +++ /dev/null @@ -1,28 +0,0 @@ -#![feature(rustc_attrs)] - -fn func<#[rustc_synthetic] T>(_: T) {} - -struct Foo; - -impl Foo { - pub fn func<#[rustc_synthetic] T>(_: T) {} -} - -struct Bar<S> { - t: S -} - -impl<S> Bar<S> { - pub fn func<#[rustc_synthetic] T>(_: T) {} -} - -fn main() { - func::<u8>(42); //~ ERROR cannot provide explicit generic arguments - func(42); // Ok - - Foo::func::<u8>(42); //~ ERROR cannot provide explicit generic arguments - Foo::func(42); // Ok - - Bar::<i8>::func::<u8>(42); //~ ERROR cannot provide explicit generic arguments - Bar::<i8>::func(42); // Ok -} diff --git a/src/test/ui/synthetic-param.stderr b/src/test/ui/synthetic-param.stderr deleted file mode 100644 index 101132d05f..0000000000 --- a/src/test/ui/synthetic-param.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position - --> $DIR/synthetic-param.rs:20:12 - | -LL | func::<u8>(42); - | ^^ explicit generic argument not allowed - -error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position - --> $DIR/synthetic-param.rs:23:17 - | -LL | Foo::func::<u8>(42); - | ^^ explicit generic argument not allowed - -error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position - --> $DIR/synthetic-param.rs:26:23 - | -LL | Bar::<i8>::func::<u8>(42); - | ^^ explicit generic argument not allowed - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0632`. diff --git a/src/test/ui/tail-direct.rs b/src/test/ui/tail-direct.rs deleted file mode 100644 index c67c5b7a55..0000000000 --- a/src/test/ui/tail-direct.rs +++ /dev/null @@ -1,7 +0,0 @@ -// run-pass - -pub fn main() { assert!((even(42))); assert!((odd(45))); } - -fn even(n: isize) -> bool { if n == 0 { return true; } else { return odd(n - 1); } } - -fn odd(n: isize) -> bool { if n == 0 { return false; } else { return even(n - 1); } } diff --git a/src/test/ui/terr-sorts.stderr b/src/test/ui/terr-sorts.stderr index 869b372965..65d9067804 100644 --- a/src/test/ui/terr-sorts.stderr +++ b/src/test/ui/terr-sorts.stderr @@ -6,6 +6,10 @@ LL | want_foo(b); | = note: expected struct `Foo` found struct `Box<Foo>` +help: try dereferencing the `Box` + | +LL | want_foo(*b); + | + error: aborting due to previous error diff --git a/src/test/ui/issues/issue-20823.rs b/src/test/ui/test-attrs/issue-20823.rs similarity index 100% rename from src/test/ui/issues/issue-20823.rs rename to src/test/ui/test-attrs/issue-20823.rs diff --git a/src/test/ui/child-outlives-parent.rs b/src/test/ui/threads-sendsync/child-outlives-parent.rs similarity index 100% rename from src/test/ui/child-outlives-parent.rs rename to src/test/ui/threads-sendsync/child-outlives-parent.rs diff --git a/src/test/ui/clone-with-exterior.rs b/src/test/ui/threads-sendsync/clone-with-exterior.rs similarity index 100% rename from src/test/ui/clone-with-exterior.rs rename to src/test/ui/threads-sendsync/clone-with-exterior.rs diff --git a/src/test/ui/issues/issue-24313.rs b/src/test/ui/threads-sendsync/issue-24313.rs similarity index 100% rename from src/test/ui/issues/issue-24313.rs rename to src/test/ui/threads-sendsync/issue-24313.rs diff --git a/src/test/ui/issues/issue-4448.rs b/src/test/ui/threads-sendsync/issue-4448.rs similarity index 100% rename from src/test/ui/issues/issue-4448.rs rename to src/test/ui/threads-sendsync/issue-4448.rs diff --git a/src/test/ui/issues/issue-8827.rs b/src/test/ui/threads-sendsync/issue-8827.rs similarity index 100% rename from src/test/ui/issues/issue-8827.rs rename to src/test/ui/threads-sendsync/issue-8827.rs diff --git a/src/test/ui/issues/issue-9396.rs b/src/test/ui/threads-sendsync/issue-9396.rs similarity index 100% rename from src/test/ui/issues/issue-9396.rs rename to src/test/ui/threads-sendsync/issue-9396.rs diff --git a/src/test/ui/mpsc_stress.rs b/src/test/ui/threads-sendsync/mpsc_stress.rs similarity index 100% rename from src/test/ui/mpsc_stress.rs rename to src/test/ui/threads-sendsync/mpsc_stress.rs diff --git a/src/test/ui/tcp-stress.rs b/src/test/ui/threads-sendsync/tcp-stress.rs similarity index 100% rename from src/test/ui/tcp-stress.rs rename to src/test/ui/threads-sendsync/tcp-stress.rs diff --git a/src/test/ui/trivial-message.rs b/src/test/ui/threads-sendsync/trivial-message.rs similarity index 100% rename from src/test/ui/trivial-message.rs rename to src/test/ui/threads-sendsync/trivial-message.rs diff --git a/src/test/ui/unwind-resource.rs b/src/test/ui/threads-sendsync/unwind-resource.rs similarity index 100% rename from src/test/ui/unwind-resource.rs rename to src/test/ui/threads-sendsync/unwind-resource.rs diff --git a/src/test/ui/yield.rs b/src/test/ui/threads-sendsync/yield.rs similarity index 100% rename from src/test/ui/yield.rs rename to src/test/ui/threads-sendsync/yield.rs diff --git a/src/test/ui/yield1.rs b/src/test/ui/threads-sendsync/yield1.rs similarity index 100% rename from src/test/ui/yield1.rs rename to src/test/ui/threads-sendsync/yield1.rs diff --git a/src/test/ui/yield2.rs b/src/test/ui/threads-sendsync/yield2.rs similarity index 100% rename from src/test/ui/yield2.rs rename to src/test/ui/threads-sendsync/yield2.rs diff --git a/src/test/ui/trait-bounds/issue-75961.rs b/src/test/ui/trait-bounds/issue-75961.rs new file mode 100644 index 0000000000..367eac7182 --- /dev/null +++ b/src/test/ui/trait-bounds/issue-75961.rs @@ -0,0 +1,7 @@ +// check-pass + +pub fn foo<'a>(s: &'a mut ()) where &'a mut (): Clone { + <&mut () as Clone>::clone(&s); +} + +fn main() {} diff --git a/src/test/ui/traits/alias/issue-83613.stderr b/src/test/ui/traits/alias/issue-83613.stderr index 0ab39ae667..6a3498a389 100644 --- a/src/test/ui/traits/alias/issue-83613.stderr +++ b/src/test/ui/traits/alias/issue-83613.stderr @@ -1,11 +1,3 @@ -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 | @@ -18,6 +10,14 @@ note: type alias impl trait defined here LL | type OpaqueType = impl OpaqueTrait; | ^^^^^^^^^^^^^^^^ +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: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/alignment-gep-tup-like-1.rs b/src/test/ui/traits/alignment-gep-tup-like-1.rs similarity index 100% rename from src/test/ui/alignment-gep-tup-like-1.rs rename to src/test/ui/traits/alignment-gep-tup-like-1.rs diff --git a/src/test/ui/traits/bad-method-typaram-kind.stderr b/src/test/ui/traits/bad-method-typaram-kind.stderr index 1e9d151629..8befa4c5f7 100644 --- a/src/test/ui/traits/bad-method-typaram-kind.stderr +++ b/src/test/ui/traits/bad-method-typaram-kind.stderr @@ -4,6 +4,11 @@ error[E0277]: `T` cannot be sent between threads safely LL | 1.bar::<T>(); | ^^^ `T` cannot be sent between threads safely | +note: required by a bound in `Bar::bar` + --> $DIR/bad-method-typaram-kind.rs:6:14 + | +LL | fn bar<T:Send>(&self); + | ^^^^ required by this bound in `Bar::bar` help: consider further restricting this bound | LL | fn foo<T:'static + std::marker::Send>() { diff --git a/src/test/ui/traits/bad-sized.stderr b/src/test/ui/traits/bad-sized.stderr index 5421e71509..6f9113fff5 100644 --- a/src/test/ui/traits/bad-sized.stderr +++ b/src/test/ui/traits/bad-sized.stderr @@ -29,11 +29,11 @@ LL | let x: Vec<dyn Trait + Sized> = Vec::new(); | ^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `dyn Trait` -note: required by `Vec::<T>::new` +note: required by a bound in `Vec::<T>::new` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL | -LL | pub const fn new() -> Self { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl<T> Vec<T> { + | ^ required by this bound in `Vec::<T>::new` error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time --> $DIR/bad-sized.rs:4:37 diff --git a/src/test/ui/traits/bound/on-structs-and-enums-locals.stderr b/src/test/ui/traits/bound/on-structs-and-enums-locals.stderr index cd33e18cfb..c9068a2700 100644 --- a/src/test/ui/traits/bound/on-structs-and-enums-locals.stderr +++ b/src/test/ui/traits/bound/on-structs-and-enums-locals.stderr @@ -16,11 +16,11 @@ error[E0277]: the trait bound `{integer}: Trait` is not satisfied LL | let foo = Foo { | ^^^ the trait `Trait` is not implemented for `{integer}` | -note: required by `Foo` - --> $DIR/on-structs-and-enums-locals.rs:5:1 +note: required by a bound in `Foo` + --> $DIR/on-structs-and-enums-locals.rs:5:14 | LL | struct Foo<T:Trait> { - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^ required by this bound in `Foo` error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/bound/on-structs-and-enums-xc1.stderr b/src/test/ui/traits/bound/on-structs-and-enums-xc1.stderr index 0f25c88568..f4cc64af94 100644 --- a/src/test/ui/traits/bound/on-structs-and-enums-xc1.stderr +++ b/src/test/ui/traits/bound/on-structs-and-enums-xc1.stderr @@ -16,11 +16,11 @@ error[E0277]: the trait bound `{integer}: Trait` is not satisfied LL | let foo = Foo { | ^^^ the trait `Trait` is not implemented for `{integer}` | -note: required by `Foo` - --> $DIR/auxiliary/on_structs_and_enums_xc.rs:5:1 +note: required by a bound in `Foo` + --> $DIR/auxiliary/on_structs_and_enums_xc.rs:5:18 | LL | pub struct Foo<T:Trait> { - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^ required by this bound in `Foo` error: aborting due to 2 previous errors diff --git a/src/test/ui/bug-7295.rs b/src/test/ui/traits/bug-7295.rs similarity index 100% rename from src/test/ui/bug-7295.rs rename to src/test/ui/traits/bug-7295.rs diff --git a/src/test/ui/traits/cache-reached-depth-ice.rs b/src/test/ui/traits/cache-reached-depth-ice.rs index 4318e07d07..c36ac08579 100644 --- a/src/test/ui/traits/cache-reached-depth-ice.rs +++ b/src/test/ui/traits/cache-reached-depth-ice.rs @@ -41,5 +41,5 @@ fn test<X: ?Sized + Send>() {} fn main() { test::<A>(); - //~^ ERROR evaluate(Binder(TraitPredicate(<A as std::marker::Send>), [])) = Ok(EvaluatedToOk) + //~^ ERROR evaluate(Binder(TraitPredicate(<A as std::marker::Send>, polarity:Positive), [])) = Ok(EvaluatedToOk) } diff --git a/src/test/ui/traits/cache-reached-depth-ice.stderr b/src/test/ui/traits/cache-reached-depth-ice.stderr index 5e662970bb..082aa0f5cd 100644 --- a/src/test/ui/traits/cache-reached-depth-ice.stderr +++ b/src/test/ui/traits/cache-reached-depth-ice.stderr @@ -1,4 +1,4 @@ -error: evaluate(Binder(TraitPredicate(<A as std::marker::Send>), [])) = Ok(EvaluatedToOk) +error: evaluate(Binder(TraitPredicate(<A as std::marker::Send>, polarity:Positive), [])) = Ok(EvaluatedToOk) --> $DIR/cache-reached-depth-ice.rs:43:5 | LL | fn test<X: ?Sized + Send>() {} diff --git a/src/test/ui/cycle-generic-bound.rs b/src/test/ui/traits/cycle-generic-bound.rs similarity index 100% rename from src/test/ui/cycle-generic-bound.rs rename to src/test/ui/traits/cycle-generic-bound.rs diff --git a/src/test/ui/early-vtbl-resolution.rs b/src/test/ui/traits/early-vtbl-resolution.rs similarity index 100% rename from src/test/ui/early-vtbl-resolution.rs rename to src/test/ui/traits/early-vtbl-resolution.rs diff --git a/src/test/ui/traits/inheritance/repeated-supertrait-ambig.stderr b/src/test/ui/traits/inheritance/repeated-supertrait-ambig.stderr index fa8799bf7d..2bff84363e 100644 --- a/src/test/ui/traits/inheritance/repeated-supertrait-ambig.stderr +++ b/src/test/ui/traits/inheritance/repeated-supertrait-ambig.stderr @@ -20,12 +20,6 @@ error[E0277]: the trait bound `dyn CompareToInts: CompareTo<i32>` is not satisfi | LL | <dyn CompareToInts>::same_as(c, 22) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `CompareTo<i32>` is not implemented for `dyn CompareToInts` - | -note: required by `CompareTo::same_as` - --> $DIR/repeated-supertrait-ambig.rs:9:5 - | -LL | fn same_as(&self, t: T) -> bool; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `C: CompareTo<i32>` is not satisfied --> $DIR/repeated-supertrait-ambig.rs:38:5 @@ -33,11 +27,6 @@ error[E0277]: the trait bound `C: CompareTo<i32>` is not satisfied LL | CompareTo::same_as(c, 22) | ^^^^^^^^^^^^^^^^^^ the trait `CompareTo<i32>` is not implemented for `C` | -note: required by `CompareTo::same_as` - --> $DIR/repeated-supertrait-ambig.rs:9:5 - | -LL | fn same_as(&self, t: T) -> bool; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider further restricting this bound | LL | fn with_ufcs2<C:CompareToInts + CompareTo<i32>>(c: &C) -> bool { diff --git a/src/test/ui/issues/issue-24010.rs b/src/test/ui/traits/issue-24010.rs similarity index 100% rename from src/test/ui/issues/issue-24010.rs rename to src/test/ui/traits/issue-24010.rs diff --git a/src/test/ui/issues/issue-38604.rs b/src/test/ui/traits/issue-38604.rs similarity index 100% rename from src/test/ui/issues/issue-38604.rs rename to src/test/ui/traits/issue-38604.rs diff --git a/src/test/ui/issues/issue-38604.stderr b/src/test/ui/traits/issue-38604.stderr similarity index 100% rename from src/test/ui/issues/issue-38604.stderr rename to src/test/ui/traits/issue-38604.stderr diff --git a/src/test/ui/issues/issue-3973.rs b/src/test/ui/traits/issue-3973.rs similarity index 100% rename from src/test/ui/issues/issue-3973.rs rename to src/test/ui/traits/issue-3973.rs diff --git a/src/test/ui/issues/issue-3973.stderr b/src/test/ui/traits/issue-3973.stderr similarity index 100% rename from src/test/ui/issues/issue-3973.stderr rename to src/test/ui/traits/issue-3973.stderr diff --git a/src/test/ui/issues/issue-59029-1.rs b/src/test/ui/traits/issue-59029-1.rs similarity index 100% rename from src/test/ui/issues/issue-59029-1.rs rename to src/test/ui/traits/issue-59029-1.rs diff --git a/src/test/ui/issues/issue-59029-1.stderr b/src/test/ui/traits/issue-59029-1.stderr similarity index 100% rename from src/test/ui/issues/issue-59029-1.stderr rename to src/test/ui/traits/issue-59029-1.stderr diff --git a/src/test/ui/traits/issue-71136.stderr b/src/test/ui/traits/issue-71136.stderr index 23b78d023b..45b1e1095c 100644 --- a/src/test/ui/traits/issue-71136.stderr +++ b/src/test/ui/traits/issue-71136.stderr @@ -5,14 +5,9 @@ LL | #[derive(Clone)] | ----- in this derive macro expansion LL | struct FooHolster { LL | the_foos: Vec<Foo>, - | ^^^^^^^^^^^^^^^^^^ expected an implementor of trait `Clone` + | ^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `Foo` | = note: required because of the requirements on the impl of `Clone` for `Vec<Foo>` -note: required by `clone` - --> $SRC_DIR/core/src/clone.rs:LL:COL - | -LL | fn clone(&self) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/issues/issue-72455.rs b/src/test/ui/traits/issue-72455.rs similarity index 100% rename from src/test/ui/issues/issue-72455.rs rename to src/test/ui/traits/issue-72455.rs diff --git a/src/test/ui/traits/issue-77982.rs b/src/test/ui/traits/issue-77982.rs index 03d4fe23cc..f5be6cf21c 100644 --- a/src/test/ui/traits/issue-77982.rs +++ b/src/test/ui/traits/issue-77982.rs @@ -6,6 +6,7 @@ fn what() { let opt = String::new(); opts.get(opt.as_ref()); //~ ERROR type annotations needed + //~^ ERROR type annotations needed } fn main() { diff --git a/src/test/ui/traits/issue-77982.stderr b/src/test/ui/traits/issue-77982.stderr index 68347207bd..3c4a5d95c1 100644 --- a/src/test/ui/traits/issue-77982.stderr +++ b/src/test/ui/traits/issue-77982.stderr @@ -6,43 +6,92 @@ LL | opts.get(opt.as_ref()); | | | cannot infer type for type parameter `Q` declared on the associated function `get` | - = note: cannot satisfy `String: Borrow<_>` + = note: multiple `impl`s satisfying `String: Borrow<_>` found in the following crates: `alloc`, `core`: + - impl Borrow<str> for String; + - impl<T> Borrow<T> for T + where T: ?Sized; +note: required by a bound in `HashMap::<K, V, S>::get` + --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL + | +LL | K: Borrow<Q>, + | ^^^^^^^^^ required by this bound in `HashMap::<K, V, S>::get` +help: consider specifying the type argument in the function call + | +LL | opts.get::<Q>(opt.as_ref()); + | +++++ error[E0283]: type annotations needed - --> $DIR/issue-77982.rs:12:44 + --> $DIR/issue-77982.rs:8:18 + | +LL | opts.get(opt.as_ref()); + | ----^^^^^^-- + | | | + | | cannot infer type for type parameter `T` declared on the trait `AsRef` + | this method call resolves to `&T` + | + = note: multiple `impl`s satisfying `String: AsRef<_>` found in the following crates: `alloc`, `std`: + - impl AsRef<OsStr> for String; + - impl AsRef<Path> for String; + - impl AsRef<[u8]> for String; + - impl AsRef<str> for String; +help: use the fully qualified path for the potential candidates + | +LL | opts.get(<String as AsRef<OsStr>>::as_ref(opt)); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | opts.get(<String as AsRef<Path>>::as_ref(opt)); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | opts.get(<String as AsRef<[u8]>>::as_ref(opt)); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | opts.get(<String as AsRef<str>>::as_ref(opt)); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0283]: type annotations needed + --> $DIR/issue-77982.rs:13:44 | LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect(); | ^^^^^^^^^ ----------- this method call resolves to `T` | | | cannot infer type for type parameter `T` declared on the trait `From` | - = note: cannot satisfy `u32: From<_>` -note: required by `from` - --> $SRC_DIR/core/src/convert/mod.rs:LL:COL - | -LL | fn from(_: T) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^ + = note: multiple `impl`s satisfying `u32: From<_>` found in the following crates: `core`, `std`: + - impl From<Ipv4Addr> for u32; + - impl From<NonZeroU32> for u32; + - impl From<bool> for u32; + - impl From<char> for u32; + and 3 more error[E0283]: type annotations needed for `Box<T>` - --> $DIR/issue-77982.rs:35:16 + --> $DIR/issue-77982.rs:36:16 | LL | let _ = ().foo(); | - ^^^ cannot infer type for type parameter `T` declared on the trait `Foo` | | | consider giving this pattern the explicit type `Box<T>`, where the type parameter `T` is specified | - = note: cannot satisfy `(): Foo<'_, _>` +note: multiple `impl`s satisfying `(): Foo<'_, _>` found + --> $DIR/issue-77982.rs:29:1 + | +LL | impl Foo<'static, u32> for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl<'a> Foo<'a, i16> for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0283]: type annotations needed for `Box<T>` - --> $DIR/issue-77982.rs:39:19 + --> $DIR/issue-77982.rs:40:19 | LL | let _ = (&()).bar(); | - ^^^ cannot infer type for type parameter `T` declared on the trait `Bar` | | | consider giving this pattern the explicit type `Box<T>`, where the type parameter `T` is specified | - = note: cannot satisfy `&(): Bar<'_, _>` +note: multiple `impl`s satisfying `&(): Bar<'_, _>` found + --> $DIR/issue-77982.rs:32:1 + | +LL | impl<'a> Bar<'static, u32> for &'a () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl<'a> Bar<'a, i16> for &'a () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0283`. diff --git a/src/test/ui/traits/issue-78372.stderr b/src/test/ui/traits/issue-78372.stderr index 0150ff4130..49a9f47936 100644 --- a/src/test/ui/traits/issue-78372.stderr +++ b/src/test/ui/traits/issue-78372.stderr @@ -50,12 +50,6 @@ LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {} | = help: add `#![feature(dispatch_from_dyn)]` to the crate attributes to enable -error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures - --> $DIR/issue-78372.rs:3:1 - | -LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Smaht<[type error], [type error]>`) --> $DIR/issue-78372.rs:3:6 | @@ -65,6 +59,12 @@ LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {} = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last +error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures + --> $DIR/issue-78372.rs:3:1 + | +LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: aborting due to 7 previous errors Some errors have detailed explanations: E0210, E0378, E0412, E0658. diff --git a/src/test/ui/traits/issue-79458.stderr b/src/test/ui/traits/issue-79458.stderr index 2f5b4ad0e6..3e83db142e 100644 --- a/src/test/ui/traits/issue-79458.stderr +++ b/src/test/ui/traits/issue-79458.stderr @@ -10,11 +10,6 @@ LL | bar: &'a mut T = help: the following implementations were found: <&T as Clone> = note: `Clone` is implemented for `&T`, but not for `&mut T` -note: required by `clone` - --> $SRC_DIR/core/src/clone.rs:LL:COL - | -LL | fn clone(&self) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.rs b/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.rs index 1be0b05fa2..3cd68ff6f0 100644 --- a/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.rs +++ b/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.rs @@ -57,10 +57,10 @@ fn main() { // Key is that Vec<First> is "ok" and Third<'_, Ty> is "ok modulo regions": forward(); - //~^ ERROR evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>), [])) = Ok(EvaluatedToOk) - //~| ERROR evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions) + //~^ ERROR evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOk) + //~| ERROR evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions) reverse(); - //~^ ERROR evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>), [])) = Ok(EvaluatedToOk) - //~| ERROR evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions) + //~^ ERROR evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOk) + //~| ERROR evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions) } diff --git a/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.stderr b/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.stderr index 43acc66fd7..7c4041144a 100644 --- a/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.stderr +++ b/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.stderr @@ -1,4 +1,4 @@ -error: evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>), [])) = Ok(EvaluatedToOk) +error: evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOk) --> $DIR/issue-83538-tainted-cache-after-cycle.rs:59:5 | LL | Vec<First>: Unpin, @@ -7,7 +7,7 @@ LL | Vec<First>: Unpin, LL | forward(); | ^^^^^^^ -error: evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions) +error: evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions) --> $DIR/issue-83538-tainted-cache-after-cycle.rs:59:5 | LL | Third<'a, Ty>: Unpin, @@ -16,7 +16,7 @@ LL | Third<'a, Ty>: Unpin, LL | forward(); | ^^^^^^^ -error: evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions) +error: evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions) --> $DIR/issue-83538-tainted-cache-after-cycle.rs:63:5 | LL | Third<'a, Ty>: Unpin, @@ -25,7 +25,7 @@ LL | Third<'a, Ty>: Unpin, LL | reverse(); | ^^^^^^^ -error: evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>), [])) = Ok(EvaluatedToOk) +error: evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOk) --> $DIR/issue-83538-tainted-cache-after-cycle.rs:63:5 | LL | Vec<First>: Unpin, diff --git a/src/test/ui/traits/issue-85360-eval-obligation-ice.rs b/src/test/ui/traits/issue-85360-eval-obligation-ice.rs new file mode 100644 index 0000000000..2dbf912d21 --- /dev/null +++ b/src/test/ui/traits/issue-85360-eval-obligation-ice.rs @@ -0,0 +1,130 @@ +// compile-flags: --edition=2021 + +#![feature(rustc_attrs)] + +use core::any::Any; +use core::marker::PhantomData; + +fn main() { + test::<MaskedStorage<GenericComp<Pos>>>(make()); + //~^ ERROR evaluate(Binder(TraitPredicate(<MaskedStorage<GenericComp<Pos>> as std::marker::Sized>, polarity:Positive), [])) = Ok(EvaluatedToOk) + //~| ERROR evaluate(Binder(TraitPredicate(<MaskedStorage<GenericComp<Pos>> as std::marker::Sized>, polarity:Positive), [])) = Ok(EvaluatedToOk) +} + +#[rustc_evaluate_where_clauses] +fn test<T: Sized>(_: T) {} + +fn make<T>() -> T { + todo!() +} + +struct DerefWrap<T>(T); + +impl<T> core::ops::Deref for DerefWrap<T> { + type Target = T; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +struct Storage<T, D> { + phantom: PhantomData<(T, D)>, +} + +type ReadStorage<T> = Storage<T, DerefWrap<MaskedStorage<T>>>; + +pub trait Component { + type Storage; +} + +struct VecStorage; + +struct Pos; + +impl Component for Pos { + type Storage = VecStorage; +} + +struct GenericComp<T> { + _t: T, +} + +impl<T: 'static> Component for GenericComp<T> { + type Storage = VecStorage; +} +struct ReadData { + pos_interpdata: ReadStorage<GenericComp<Pos>>, +} + +trait System { + type SystemData; + + fn run(data: Self::SystemData, any: Box<dyn Any>); +} + +struct Sys; + +impl System for Sys { + type SystemData = (ReadData, ReadStorage<Pos>); + + fn run((data, pos): Self::SystemData, any: Box<dyn Any>) { + <ReadStorage<GenericComp<Pos>> as SystemData>::setup(any); + + ParJoin::par_join((&pos, &data.pos_interpdata)); + } +} + +trait ParJoin { + fn par_join(self) + where + Self: Sized, + { + } +} + +impl<'a, T, D> ParJoin for &'a Storage<T, D> +where + T: Component, + D: core::ops::Deref<Target = MaskedStorage<T>>, + T::Storage: Sync, +{ +} + +impl<A, B> ParJoin for (A, B) +where + A: ParJoin, + B: ParJoin, +{ +} + +pub trait SystemData { + fn setup(any: Box<dyn Any>); +} + +impl<T: 'static> SystemData for ReadStorage<T> +where + T: Component, +{ + fn setup(any: Box<dyn Any>) { + let storage: &MaskedStorage<T> = any.downcast_ref().unwrap(); + + <dyn Any as CastFrom<MaskedStorage<T>>>::cast(&storage); + } +} + +pub struct MaskedStorage<T: Component> { + _inner: T::Storage, +} + +pub unsafe trait CastFrom<T> { + fn cast(t: &T) -> &Self; +} + +unsafe impl<T> CastFrom<T> for dyn Any +where + T: Any + 'static, +{ + fn cast(t: &T) -> &Self { + t + } +} diff --git a/src/test/ui/traits/issue-85360-eval-obligation-ice.stderr b/src/test/ui/traits/issue-85360-eval-obligation-ice.stderr new file mode 100644 index 0000000000..c62aba30f0 --- /dev/null +++ b/src/test/ui/traits/issue-85360-eval-obligation-ice.stderr @@ -0,0 +1,20 @@ +error: evaluate(Binder(TraitPredicate(<MaskedStorage<GenericComp<Pos>> as std::marker::Sized>, polarity:Positive), [])) = Ok(EvaluatedToOk) + --> $DIR/issue-85360-eval-obligation-ice.rs:9:5 + | +LL | test::<MaskedStorage<GenericComp<Pos>>>(make()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn test<T: Sized>(_: T) {} + | - predicate + +error: evaluate(Binder(TraitPredicate(<MaskedStorage<GenericComp<Pos>> as std::marker::Sized>, polarity:Positive), [])) = Ok(EvaluatedToOk) + --> $DIR/issue-85360-eval-obligation-ice.rs:9:5 + | +LL | test::<MaskedStorage<GenericComp<Pos>>>(make()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn test<T: Sized>(_: T) {} + | ----- predicate + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/traits/issue-85735.stderr b/src/test/ui/traits/issue-85735.stderr index 1f81fa7254..33b12ef09e 100644 --- a/src/test/ui/traits/issue-85735.stderr +++ b/src/test/ui/traits/issue-85735.stderr @@ -5,15 +5,6 @@ LL | T: FnMut(&'a ()), | ^^^^^^^^^^^^^ cannot infer type for type parameter `T` | = note: cannot satisfy `T: FnMut<(&'a (),)>` -note: required by a bound in `FnMut` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - | -LL | / pub trait FnMut<Args>: FnOnce<Args> { -LL | | /// Performs the call operation. -LL | | #[unstable(feature = "fn_traits", issue = "29625")] -LL | | extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; -LL | | } - | |_^ required by this bound in `FnMut` error: aborting due to previous error diff --git a/src/test/ui/traits/issue-90195-2.rs b/src/test/ui/traits/issue-90195-2.rs new file mode 100644 index 0000000000..b739dc46e4 --- /dev/null +++ b/src/test/ui/traits/issue-90195-2.rs @@ -0,0 +1,20 @@ +// check-pass +pub trait Archive { + type Archived; +} + +impl<T> Archive for Option<T> { + type Archived = (); +} +pub type Archived<T> = <T as Archive>::Archived; + +pub trait Deserialize<D> {} + +const ARRAY_SIZE: usize = 32; +impl<__D> Deserialize<__D> for () +where + Option<[u8; ARRAY_SIZE]>: Archive, + Archived<Option<[u8; ARRAY_SIZE]>>: Deserialize<__D>, +{ +} +fn main() {} diff --git a/src/test/ui/traits/issue-90195.rs b/src/test/ui/traits/issue-90195.rs new file mode 100644 index 0000000000..543c9f197e --- /dev/null +++ b/src/test/ui/traits/issue-90195.rs @@ -0,0 +1,21 @@ +// check-pass +pub trait Archive { + type Archived; +} + +impl<T> Archive for Option<T> { + type Archived = (); +} +pub type Archived<T> = <T as Archive>::Archived; + +pub trait Deserialize<D> {} + +const ARRAY_SIZE: usize = 32; +impl<__D> Deserialize<__D> for () +where + Option<[u8; ARRAY_SIZE]>: Archive, + Option<[u8; ARRAY_SIZE]>: Archive, + Archived<Option<[u8; ARRAY_SIZE]>>: Deserialize<__D>, +{ +} +fn main() {} diff --git a/src/test/ui/map-types.rs b/src/test/ui/traits/map-types.rs similarity index 100% rename from src/test/ui/map-types.rs rename to src/test/ui/traits/map-types.rs diff --git a/src/test/ui/map-types.stderr b/src/test/ui/traits/map-types.stderr similarity index 100% rename from src/test/ui/map-types.stderr rename to src/test/ui/traits/map-types.stderr diff --git a/src/test/ui/monad.rs b/src/test/ui/traits/monad.rs similarity index 100% rename from src/test/ui/monad.rs rename to src/test/ui/traits/monad.rs diff --git a/src/test/ui/monomorphized-callees-with-ty-params-3314.rs b/src/test/ui/traits/monomorphized-callees-with-ty-params-3314.rs similarity index 100% rename from src/test/ui/monomorphized-callees-with-ty-params-3314.rs rename to src/test/ui/traits/monomorphized-callees-with-ty-params-3314.rs diff --git a/src/test/ui/multidispatch-conditional-impl-not-considered.rs b/src/test/ui/traits/multidispatch-conditional-impl-not-considered.rs similarity index 100% rename from src/test/ui/multidispatch-conditional-impl-not-considered.rs rename to src/test/ui/traits/multidispatch-conditional-impl-not-considered.rs diff --git a/src/test/ui/traits/multidispatch-convert-ambig-dest.rs b/src/test/ui/traits/multidispatch-convert-ambig-dest.rs index 58cb69a05b..aa74e11c36 100644 --- a/src/test/ui/traits/multidispatch-convert-ambig-dest.rs +++ b/src/test/ui/traits/multidispatch-convert-ambig-dest.rs @@ -24,7 +24,8 @@ where T : Convert<U> fn a() { test(22, std::default::Default::default()); - //~^ ERROR type annotations needed [E0282] + //~^ ERROR type annotations needed + //~| ERROR type annotations needed } fn main() {} diff --git a/src/test/ui/traits/multidispatch-convert-ambig-dest.stderr b/src/test/ui/traits/multidispatch-convert-ambig-dest.stderr index 62f5f5aaa8..9fd81b56bf 100644 --- a/src/test/ui/traits/multidispatch-convert-ambig-dest.stderr +++ b/src/test/ui/traits/multidispatch-convert-ambig-dest.stderr @@ -4,6 +4,33 @@ error[E0282]: type annotations needed LL | test(22, std::default::Default::default()); | ^^^^ cannot infer type for type parameter `U` declared on the function `test` -error: aborting due to previous error +error[E0283]: type annotations needed + --> $DIR/multidispatch-convert-ambig-dest.rs:26:5 + | +LL | test(22, std::default::Default::default()); + | ^^^^ cannot infer type for type parameter `U` declared on the function `test` + | +note: multiple `impl`s satisfying `i32: Convert<_>` found + --> $DIR/multidispatch-convert-ambig-dest.rs:8:1 + | +LL | impl Convert<i8> for i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Convert<i16> for i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `test` + --> $DIR/multidispatch-convert-ambig-dest.rs:21:11 + | +LL | fn test<T,U>(_: T, _: U) + | ---- required by a bound in this +LL | where T : Convert<U> + | ^^^^^^^^^^ required by this bound in `test` +help: consider specifying the type arguments in the function call + | +LL | test::<T, U>(22, std::default::Default::default()); + | ++++++++ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0282`. +Some errors have detailed explanations: E0282, E0283. +For more information about an error, try `rustc --explain E0282`. diff --git a/src/test/ui/multidispatch1.rs b/src/test/ui/traits/multidispatch1.rs similarity index 100% rename from src/test/ui/multidispatch1.rs rename to src/test/ui/traits/multidispatch1.rs diff --git a/src/test/ui/multidispatch2.rs b/src/test/ui/traits/multidispatch2.rs similarity index 100% rename from src/test/ui/multidispatch2.rs rename to src/test/ui/traits/multidispatch2.rs 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 8059a8ca71..c5d4ccc2fc 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 @@ -7,11 +7,11 @@ LL | Outer(TestType); | required by a bound introduced by this call | = help: the trait `Send` is not implemented for `dummy::TestType` -note: required by `Outer` - --> $DIR/negated-auto-traits-error.rs:10:1 +note: required by a bound in `Outer` + --> $DIR/negated-auto-traits-error.rs:10:17 | LL | struct Outer<T: Send>(T); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^ required by this bound in `Outer` error[E0277]: `dummy::TestType` cannot be sent between threads safely --> $DIR/negated-auto-traits-error.rs:23:5 @@ -49,7 +49,7 @@ LL | is_send((8, TestType)); | | | required by a bound introduced by this call | - = help: the trait `Send` is not implemented for `dummy1c::TestType` + = help: within `({integer}, dummy1c::TestType)`, the trait `Send` is not implemented for `dummy1c::TestType` = note: required because it appears within the type `({integer}, dummy1c::TestType)` note: required by a bound in `is_send` --> $DIR/negated-auto-traits-error.rs:16:15 @@ -65,7 +65,7 @@ LL | is_send(Box::new(TestType)); | | | required by a bound introduced by this call | - = note: the trait bound `dummy2::TestType: Send` is not satisfied + = note: the trait bound `Unique<dummy2::TestType>: Send` is not satisfied = note: required because of the requirements on the impl of `Send` for `Unique<dummy2::TestType>` = note: required because it appears within the type `Box<dummy2::TestType>` note: required by a bound in `is_send` @@ -86,7 +86,7 @@ LL | is_send(Box::new(Outer2(TestType))); | | | required by a bound introduced by this call | - = help: the trait `Send` is not implemented for `dummy3::TestType` + = 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>` --> $DIR/negated-auto-traits-error.rs:12:8 | @@ -104,11 +104,11 @@ error[E0277]: `main::TestType` cannot be sent between threads safely --> $DIR/negated-auto-traits-error.rs:66:13 | LL | is_sync(Outer2(TestType)); - | ------- ^^^^^^^^^^^^^^^^ expected an implementor of trait `Sync` + | ------- ^^^^^^^^^^^^^^^^ `main::TestType` cannot be sent between threads safely | | | required by a bound introduced by this call | - = note: the trait bound `main::TestType: Sync` is not satisfied + = help: the trait `Send` is not implemented for `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 | @@ -119,12 +119,6 @@ note: required by a bound in `is_sync` | LL | fn is_sync<T: Sync>(_: T) {} | ^^^^ required by this bound in `is_sync` -help: consider borrowing here - | -LL | is_sync(&Outer2(TestType)); - | + -LL | is_sync(&mut Outer2(TestType)); - | ++++ error: aborting due to 7 previous errors diff --git a/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs b/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs index db72aaf180..119ac05c33 100644 --- a/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs +++ b/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs @@ -1,3 +1,5 @@ +// check-pass + #![feature(negative_impls)] // aux-build: foreign_trait.rs @@ -16,6 +18,6 @@ use foreign_trait::ForeignTrait; trait LocalTrait { } impl<T: ForeignTrait> LocalTrait for T { } -impl LocalTrait for String { } //~ ERROR conflicting implementations +impl LocalTrait for String { } fn main() { } 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 deleted file mode 100644 index b970ad7620..0000000000 --- a/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.stderr +++ /dev/null @@ -1,11 +0,0 @@ -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 { } - | -------------------------------------- first implementation here -LL | impl LocalTrait for String { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `std::string::String` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/no_send-struct.rs b/src/test/ui/traits/no_send-struct.rs similarity index 100% rename from src/test/ui/no_send-struct.rs rename to src/test/ui/traits/no_send-struct.rs diff --git a/src/test/ui/no_send-struct.stderr b/src/test/ui/traits/no_send-struct.stderr similarity index 100% rename from src/test/ui/no_send-struct.stderr rename to src/test/ui/traits/no_send-struct.stderr diff --git a/src/test/ui/object-does-not-impl-trait.rs b/src/test/ui/traits/object-does-not-impl-trait.rs similarity index 100% rename from src/test/ui/object-does-not-impl-trait.rs rename to src/test/ui/traits/object-does-not-impl-trait.rs diff --git a/src/test/ui/object-does-not-impl-trait.stderr b/src/test/ui/traits/object-does-not-impl-trait.stderr similarity index 100% rename from src/test/ui/object-does-not-impl-trait.stderr rename to src/test/ui/traits/object-does-not-impl-trait.stderr diff --git a/src/test/ui/objects-owned-object-borrowed-method-headerless.rs b/src/test/ui/traits/objects-owned-object-borrowed-method-headerless.rs similarity index 100% rename from src/test/ui/objects-owned-object-borrowed-method-headerless.rs rename to src/test/ui/traits/objects-owned-object-borrowed-method-headerless.rs diff --git a/src/test/ui/traits/param-without-lifetime-constraint.stderr b/src/test/ui/traits/param-without-lifetime-constraint.stderr index 763fb5186c..118b2cf3ec 100644 --- a/src/test/ui/traits/param-without-lifetime-constraint.stderr +++ b/src/test/ui/traits/param-without-lifetime-constraint.stderr @@ -2,13 +2,13 @@ error: `impl` item signature doesn't match `trait` item signature --> $DIR/param-without-lifetime-constraint.rs:14:5 | LL | fn get_relation(&self) -> To; - | ----------------------------- expected `fn(&Article) -> &ProofReader` + | ----------------------------- expected `fn(&'1 Article) -> &'2 ProofReader` ... LL | fn get_relation(&self) -> &ProofReader { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&Article) -> &ProofReader` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 Article) -> &'1 ProofReader` | - = note: expected `fn(&Article) -> &ProofReader` - found `fn(&Article) -> &ProofReader` + = note: expected `fn(&'1 Article) -> &'2 ProofReader` + found `fn(&'1 Article) -> &'1 ProofReader` help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` --> $DIR/param-without-lifetime-constraint.rs:10:31 | diff --git a/src/test/ui/traits/reservation-impl/no-use.stderr b/src/test/ui/traits/reservation-impl/no-use.stderr index e7d1ee616b..3d5bf3448b 100644 --- a/src/test/ui/traits/reservation-impl/no-use.stderr +++ b/src/test/ui/traits/reservation-impl/no-use.stderr @@ -8,11 +8,6 @@ LL | <() as MyTrait>::foo(&()); | = help: the following implementations were found: <() as MyTrait> -note: required by `MyTrait::foo` - --> $DIR/no-use.rs:5:17 - | -LL | trait MyTrait { fn foo(&self); } - | ^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/traits/self-without-lifetime-constraint.stderr b/src/test/ui/traits/self-without-lifetime-constraint.stderr index 73b5aec022..85fada3b87 100644 --- a/src/test/ui/traits/self-without-lifetime-constraint.stderr +++ b/src/test/ui/traits/self-without-lifetime-constraint.stderr @@ -2,13 +2,13 @@ error: `impl` item signature doesn't match `trait` item signature --> $DIR/self-without-lifetime-constraint.rs:45:5 | LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self, &Self>; - | -------------------------------------------------------------------- expected `fn(ValueRef<'_>) -> Result<(&str, &&str), FromSqlError>` + | -------------------------------------------------------------------- expected `fn(ValueRef<'1>) -> Result<(&'2 str, &'1 &'2 str), FromSqlError>` ... LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult<&str, &&str> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(ValueRef<'_>) -> Result<(&str, &&str), FromSqlError>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(ValueRef<'1>) -> Result<(&'1 str, &'1 &'1 str), FromSqlError>` | - = note: expected `fn(ValueRef<'_>) -> Result<(&str, &&str), _>` - found `fn(ValueRef<'_>) -> Result<(&str, &&str), _>` + = note: expected `fn(ValueRef<'1>) -> Result<(&'2 str, &'1 &'2 str), FromSqlError>` + found `fn(ValueRef<'1>) -> Result<(&'1 str, &'1 &'1 str), FromSqlError>` help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` --> $DIR/self-without-lifetime-constraint.rs:41:60 | diff --git a/src/test/ui/traits/static-method-generic-inference.stderr b/src/test/ui/traits/static-method-generic-inference.stderr index c8c804a901..1a0bcf00a6 100644 --- a/src/test/ui/traits/static-method-generic-inference.stderr +++ b/src/test/ui/traits/static-method-generic-inference.stderr @@ -5,11 +5,6 @@ LL | let _f: base::Foo = base::HasNew::new(); | ^^^^^^^^^^^^^^^^^ cannot infer type | = note: cannot satisfy `_: HasNew<Foo>` -note: required by `HasNew::new` - --> $DIR/static-method-generic-inference.rs:8:9 - | -LL | fn new() -> T; - | ^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/staticness-mismatch.rs b/src/test/ui/traits/staticness-mismatch.rs similarity index 100% rename from src/test/ui/staticness-mismatch.rs rename to src/test/ui/traits/staticness-mismatch.rs diff --git a/src/test/ui/staticness-mismatch.stderr b/src/test/ui/traits/staticness-mismatch.stderr similarity index 100% rename from src/test/ui/staticness-mismatch.stderr rename to src/test/ui/traits/staticness-mismatch.stderr diff --git a/src/test/ui/traits/suggest-where-clause.stderr b/src/test/ui/traits/suggest-where-clause.stderr index d955cb06a1..e2cdd36888 100644 --- a/src/test/ui/traits/suggest-where-clause.stderr +++ b/src/test/ui/traits/suggest-where-clause.stderr @@ -49,11 +49,6 @@ error[E0277]: the trait bound `u64: From<T>` is not satisfied LL | <u64 as From<T>>::from; | ^^^^^^^^^^^^^^^^^^^^^^ the trait `From<T>` is not implemented for `u64` | -note: required by `from` - --> $SRC_DIR/core/src/convert/mod.rs:LL:COL - | -LL | fn from(_: T) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^ help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement | LL | fn check<T: Iterator, U: ?Sized>() where u64: From<T> { @@ -65,11 +60,6 @@ error[E0277]: the trait bound `u64: From<<T as Iterator>::Item>` is not satisfie LL | <u64 as From<<T as Iterator>::Item>>::from; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<<T as Iterator>::Item>` is not implemented for `u64` | -note: required by `from` - --> $SRC_DIR/core/src/convert/mod.rs:LL:COL - | -LL | fn from(_: T) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^ help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement | LL | fn check<T: Iterator, U: ?Sized>() where u64: From<<T as Iterator>::Item> { @@ -80,12 +70,6 @@ error[E0277]: the trait bound `Misc<_>: From<T>` is not satisfied | LL | <Misc<_> as From<T>>::from; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<T>` is not implemented for `Misc<_>` - | -note: required by `from` - --> $SRC_DIR/core/src/convert/mod.rs:LL:COL - | -LL | fn from(_: T) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `[T]` cannot be known at compilation time --> $DIR/suggest-where-clause.rs:28:20 diff --git a/src/test/ui/syntax-trait-polarity.rs b/src/test/ui/traits/syntax-trait-polarity.rs similarity index 100% rename from src/test/ui/syntax-trait-polarity.rs rename to src/test/ui/traits/syntax-trait-polarity.rs diff --git a/src/test/ui/syntax-trait-polarity.stderr b/src/test/ui/traits/syntax-trait-polarity.stderr similarity index 100% rename from src/test/ui/syntax-trait-polarity.stderr rename to src/test/ui/traits/syntax-trait-polarity.stderr diff --git a/src/test/ui/traits/test-2.rs b/src/test/ui/traits/test-2.rs index 342928e882..d062de25ac 100644 --- a/src/test/ui/traits/test-2.rs +++ b/src/test/ui/traits/test-2.rs @@ -6,9 +6,9 @@ impl bar for i32 { fn dup(&self) -> i32 { *self } fn blah<X>(&self) {} } impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah<X>(&self) {} } fn main() { - 10.dup::<i32>(); + 10.dup::<i32>(); //~ ERROR type annotations needed //~^ ERROR this associated function takes 0 generic arguments but 1 - 10.blah::<i32, i32>(); + 10.blah::<i32, i32>(); //~ ERROR type annotations needed //~^ ERROR this associated function takes 1 generic argument but 2 (Box::new(10) as Box<dyn bar>).dup(); //~^ ERROR E0038 diff --git a/src/test/ui/traits/test-2.stderr b/src/test/ui/traits/test-2.stderr index 77ea4e4e97..5eec012458 100644 --- a/src/test/ui/traits/test-2.stderr +++ b/src/test/ui/traits/test-2.stderr @@ -79,7 +79,35 @@ LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); } = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn bar>>` for `Box<{integer}>` = note: required by cast to type `Box<dyn bar>` -error: aborting due to 5 previous errors +error[E0283]: type annotations needed + --> $DIR/test-2.rs:9:8 + | +LL | 10.dup::<i32>(); + | ^^^ cannot infer type for type `{integer}` + | +note: multiple `impl`s satisfying `{integer}: bar` found + --> $DIR/test-2.rs:5:1 + | +LL | impl bar for i32 { fn dup(&self) -> i32 { *self } fn blah<X>(&self) {} } + | ^^^^^^^^^^^^^^^^ +LL | impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah<X>(&self) {} } + | ^^^^^^^^^^^^^^^^ + +error[E0283]: type annotations needed + --> $DIR/test-2.rs:11:8 + | +LL | 10.blah::<i32, i32>(); + | ^^^^ cannot infer type for type `{integer}` + | +note: multiple `impl`s satisfying `{integer}: bar` found + --> $DIR/test-2.rs:5:1 + | +LL | impl bar for i32 { fn dup(&self) -> i32 { *self } fn blah<X>(&self) {} } + | ^^^^^^^^^^^^^^^^ +LL | impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah<X>(&self) {} } + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 7 previous errors -Some errors have detailed explanations: E0038, E0107. +Some errors have detailed explanations: E0038, E0107, E0283. For more information about an error, try `rustc --explain E0038`. diff --git a/src/test/ui/typeclasses-eq-example-static.rs b/src/test/ui/traits/typeclasses-eq-example-static.rs similarity index 100% rename from src/test/ui/typeclasses-eq-example-static.rs rename to src/test/ui/traits/typeclasses-eq-example-static.rs diff --git a/src/test/ui/typeclasses-eq-example.rs b/src/test/ui/traits/typeclasses-eq-example.rs similarity index 100% rename from src/test/ui/typeclasses-eq-example.rs rename to src/test/ui/traits/typeclasses-eq-example.rs diff --git a/src/test/ui/vtable-res-trait-param.rs b/src/test/ui/traits/vtable-res-trait-param.rs similarity index 100% rename from src/test/ui/vtable-res-trait-param.rs rename to src/test/ui/traits/vtable-res-trait-param.rs diff --git a/src/test/ui/vtable-res-trait-param.stderr b/src/test/ui/traits/vtable-res-trait-param.stderr similarity index 62% rename from src/test/ui/vtable-res-trait-param.stderr rename to src/test/ui/traits/vtable-res-trait-param.stderr index c5fff622b6..2b3e3de9b1 100644 --- a/src/test/ui/vtable-res-trait-param.stderr +++ b/src/test/ui/traits/vtable-res-trait-param.stderr @@ -5,6 +5,12 @@ LL | b.gimme_an_a(y) | ---------- ^ the trait `TraitA` is not implemented for `{integer}` | | | required by a bound introduced by this call + | +note: required by a bound in `TraitB::gimme_an_a` + --> $DIR/vtable-res-trait-param.rs:6:21 + | +LL | fn gimme_an_a<A:TraitA>(&self, a: A) -> isize; + | ^^^^^^ required by this bound in `TraitB::gimme_an_a` error: aborting due to previous error diff --git a/src/test/ui/traits/vtable/issue-91807.rs b/src/test/ui/traits/vtable/issue-91807.rs new file mode 100644 index 0000000000..f435ff09dc --- /dev/null +++ b/src/test/ui/traits/vtable/issue-91807.rs @@ -0,0 +1,17 @@ +// check-pass +// incremental + +struct Struct<T>(T); + +impl<T> std::ops::Deref for Struct<T> { + type Target = dyn Fn(T); + fn deref(&self) -> &Self::Target { + unimplemented!() + } +} + +fn main() { + let f = Struct(Default::default()); + f(0); + f(0); +} diff --git a/src/test/ui/traits/vtable/vtable-diamond.stderr b/src/test/ui/traits/vtable/vtable-diamond.stderr index f2b64fac3b..f71bed84d5 100644 --- a/src/test/ui/traits/vtable/vtable-diamond.stderr +++ b/src/test/ui/traits/vtable/vtable-diamond.stderr @@ -1,13 +1,13 @@ error: vtable entries for `<S as D>`: [ - MetadataDropInPlace, - MetadataSize, - MetadataAlign, - Method(<S as A>::foo_a), - Method(<S as B>::foo_b), - Method(<S as C>::foo_c), - TraitVPtr(<S as C>), - Method(<S as D>::foo_d), -] + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as A>::foo_a), + Method(<S as B>::foo_b), + Method(<S as C>::foo_c), + TraitVPtr(<S as C>), + Method(<S as D>::foo_d), + ] --> $DIR/vtable-diamond.rs:21:1 | LL | / trait D: B + C { @@ -17,12 +17,12 @@ LL | | } | |_^ error: vtable entries for `<S as C>`: [ - MetadataDropInPlace, - MetadataSize, - MetadataAlign, - Method(<S as A>::foo_a), - Method(<S as C>::foo_c), -] + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as A>::foo_a), + Method(<S as C>::foo_c), + ] --> $DIR/vtable-diamond.rs:15:1 | LL | / trait C: A { diff --git a/src/test/ui/traits/vtable/vtable-multi-level.stderr b/src/test/ui/traits/vtable/vtable-multi-level.stderr index 742b88ea8a..915fd701b0 100644 --- a/src/test/ui/traits/vtable/vtable-multi-level.stderr +++ b/src/test/ui/traits/vtable/vtable-multi-level.stderr @@ -1,34 +1,34 @@ error: vtable entries for `<S as O>`: [ - MetadataDropInPlace, - MetadataSize, - MetadataAlign, - Method(<S as A>::foo_a), - Method(<S as B>::foo_b), - TraitVPtr(<S as B>), - Method(<S as C>::foo_c), - Method(<S as D>::foo_d), - TraitVPtr(<S as D>), - Method(<S as E>::foo_e), - TraitVPtr(<S as E>), - Method(<S as F>::foo_f), - TraitVPtr(<S as F>), - Method(<S as G>::foo_g), - Method(<S as H>::foo_h), - TraitVPtr(<S as H>), - Method(<S as I>::foo_i), - TraitVPtr(<S as I>), - Method(<S as J>::foo_j), - TraitVPtr(<S as J>), - Method(<S as K>::foo_k), - TraitVPtr(<S as K>), - Method(<S as L>::foo_l), - TraitVPtr(<S as L>), - Method(<S as M>::foo_m), - TraitVPtr(<S as M>), - Method(<S as N>::foo_n), - TraitVPtr(<S as N>), - Method(<S as O>::foo_o), -] + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as A>::foo_a), + Method(<S as B>::foo_b), + TraitVPtr(<S as B>), + Method(<S as C>::foo_c), + Method(<S as D>::foo_d), + TraitVPtr(<S as D>), + Method(<S as E>::foo_e), + TraitVPtr(<S as E>), + Method(<S as F>::foo_f), + TraitVPtr(<S as F>), + Method(<S as G>::foo_g), + Method(<S as H>::foo_h), + TraitVPtr(<S as H>), + Method(<S as I>::foo_i), + TraitVPtr(<S as I>), + Method(<S as J>::foo_j), + TraitVPtr(<S as J>), + Method(<S as K>::foo_k), + TraitVPtr(<S as K>), + Method(<S as L>::foo_l), + TraitVPtr(<S as L>), + Method(<S as M>::foo_m), + TraitVPtr(<S as M>), + Method(<S as N>::foo_n), + TraitVPtr(<S as N>), + Method(<S as O>::foo_o), + ] --> $DIR/vtable-multi-level.rs:95:1 | LL | / trait O: G + N { @@ -38,11 +38,11 @@ LL | | } | |_^ error: vtable entries for `<S as B>`: [ - MetadataDropInPlace, - MetadataSize, - MetadataAlign, - Method(<S as B>::foo_b), -] + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as B>::foo_b), + ] --> $DIR/vtable-multi-level.rs:19:1 | LL | / trait B { @@ -52,11 +52,11 @@ LL | | } | |_^ error: vtable entries for `<S as D>`: [ - MetadataDropInPlace, - MetadataSize, - MetadataAlign, - Method(<S as D>::foo_d), -] + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as D>::foo_d), + ] --> $DIR/vtable-multi-level.rs:30:1 | LL | / trait D { @@ -66,11 +66,11 @@ LL | | } | |_^ error: vtable entries for `<S as E>`: [ - MetadataDropInPlace, - MetadataSize, - MetadataAlign, - Method(<S as E>::foo_e), -] + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as E>::foo_e), + ] --> $DIR/vtable-multi-level.rs:36:1 | LL | / trait E { @@ -80,14 +80,14 @@ LL | | } | |_^ error: vtable entries for `<S as F>`: [ - MetadataDropInPlace, - MetadataSize, - MetadataAlign, - Method(<S as D>::foo_d), - Method(<S as E>::foo_e), - TraitVPtr(<S as E>), - Method(<S as F>::foo_f), -] + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as D>::foo_d), + Method(<S as E>::foo_e), + TraitVPtr(<S as E>), + Method(<S as F>::foo_f), + ] --> $DIR/vtable-multi-level.rs:42:1 | LL | / trait F: D + E { @@ -97,11 +97,11 @@ LL | | } | |_^ error: vtable entries for `<S as H>`: [ - MetadataDropInPlace, - MetadataSize, - MetadataAlign, - Method(<S as H>::foo_h), -] + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as H>::foo_h), + ] --> $DIR/vtable-multi-level.rs:53:1 | LL | / trait H { @@ -111,11 +111,11 @@ LL | | } | |_^ error: vtable entries for `<S as I>`: [ - MetadataDropInPlace, - MetadataSize, - MetadataAlign, - Method(<S as I>::foo_i), -] + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as I>::foo_i), + ] --> $DIR/vtable-multi-level.rs:59:1 | LL | / trait I { @@ -125,14 +125,14 @@ LL | | } | |_^ error: vtable entries for `<S as J>`: [ - MetadataDropInPlace, - MetadataSize, - MetadataAlign, - Method(<S as H>::foo_h), - Method(<S as I>::foo_i), - TraitVPtr(<S as I>), - Method(<S as J>::foo_j), -] + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as H>::foo_h), + Method(<S as I>::foo_i), + TraitVPtr(<S as I>), + Method(<S as J>::foo_j), + ] --> $DIR/vtable-multi-level.rs:65:1 | LL | / trait J: H + I { @@ -142,11 +142,11 @@ LL | | } | |_^ error: vtable entries for `<S as K>`: [ - MetadataDropInPlace, - MetadataSize, - MetadataAlign, - Method(<S as K>::foo_k), -] + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as K>::foo_k), + ] --> $DIR/vtable-multi-level.rs:71:1 | LL | / trait K { @@ -156,11 +156,11 @@ LL | | } | |_^ error: vtable entries for `<S as L>`: [ - MetadataDropInPlace, - MetadataSize, - MetadataAlign, - Method(<S as L>::foo_l), -] + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as L>::foo_l), + ] --> $DIR/vtable-multi-level.rs:77:1 | LL | / trait L { @@ -170,14 +170,14 @@ LL | | } | |_^ error: vtable entries for `<S as M>`: [ - MetadataDropInPlace, - MetadataSize, - MetadataAlign, - Method(<S as K>::foo_k), - Method(<S as L>::foo_l), - TraitVPtr(<S as L>), - Method(<S as M>::foo_m), -] + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as K>::foo_k), + Method(<S as L>::foo_l), + TraitVPtr(<S as L>), + Method(<S as M>::foo_m), + ] --> $DIR/vtable-multi-level.rs:83:1 | LL | / trait M: K + L { @@ -187,21 +187,21 @@ LL | | } | |_^ error: vtable entries for `<S as N>`: [ - MetadataDropInPlace, - MetadataSize, - MetadataAlign, - Method(<S as H>::foo_h), - Method(<S as I>::foo_i), - TraitVPtr(<S as I>), - Method(<S as J>::foo_j), - Method(<S as K>::foo_k), - TraitVPtr(<S as K>), - Method(<S as L>::foo_l), - TraitVPtr(<S as L>), - Method(<S as M>::foo_m), - TraitVPtr(<S as M>), - Method(<S as N>::foo_n), -] + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as H>::foo_h), + Method(<S as I>::foo_i), + TraitVPtr(<S as I>), + Method(<S as J>::foo_j), + Method(<S as K>::foo_k), + TraitVPtr(<S as K>), + Method(<S as L>::foo_l), + TraitVPtr(<S as L>), + Method(<S as M>::foo_m), + TraitVPtr(<S as M>), + Method(<S as N>::foo_n), + ] --> $DIR/vtable-multi-level.rs:89:1 | LL | / trait N: J + M { diff --git a/src/test/ui/traits/vtable/vtable-multiple.stderr b/src/test/ui/traits/vtable/vtable-multiple.stderr index f25ac76fbe..f1c8947f90 100644 --- a/src/test/ui/traits/vtable/vtable-multiple.stderr +++ b/src/test/ui/traits/vtable/vtable-multiple.stderr @@ -1,12 +1,12 @@ error: vtable entries for `<S as C>`: [ - MetadataDropInPlace, - MetadataSize, - MetadataAlign, - Method(<S as A>::foo_a), - Method(<S as B>::foo_b), - TraitVPtr(<S as B>), - Method(<S as C>::foo_c), -] + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as A>::foo_a), + Method(<S as B>::foo_b), + TraitVPtr(<S as B>), + Method(<S as C>::foo_c), + ] --> $DIR/vtable-multiple.rs:16:1 | LL | / trait C: A + B { @@ -16,11 +16,11 @@ LL | | } | |_^ error: vtable entries for `<S as B>`: [ - MetadataDropInPlace, - MetadataSize, - MetadataAlign, - Method(<S as B>::foo_b), -] + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as B>::foo_b), + ] --> $DIR/vtable-multiple.rs:10:1 | LL | / trait B { diff --git a/src/test/ui/traits/vtable/vtable-non-object-safe.stderr b/src/test/ui/traits/vtable/vtable-non-object-safe.stderr index 34fe910525..bbfbde222f 100644 --- a/src/test/ui/traits/vtable/vtable-non-object-safe.stderr +++ b/src/test/ui/traits/vtable/vtable-non-object-safe.stderr @@ -1,12 +1,12 @@ error: vtable entries for `<std::vec::IntoIter<u8> as A>`: [ - MetadataDropInPlace, - MetadataSize, - MetadataAlign, - Method(<std::vec::IntoIter<u8> as Iterator>::next), - Method(<std::vec::IntoIter<u8> as Iterator>::size_hint), - Method(<std::vec::IntoIter<u8> as Iterator>::advance_by), - Method(<std::vec::IntoIter<u8> as Iterator>::nth), -] + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<std::vec::IntoIter<u8> as Iterator>::next), + Method(<std::vec::IntoIter<u8> as Iterator>::size_hint), + Method(<std::vec::IntoIter<u8> as Iterator>::advance_by), + Method(<std::vec::IntoIter<u8> as Iterator>::nth), + ] --> $DIR/vtable-non-object-safe.rs:8:1 | LL | trait A: Iterator {} diff --git a/src/test/ui/traits/vtable/vtable-vacant.stderr b/src/test/ui/traits/vtable/vtable-vacant.stderr index e3b75e7cf3..c8cf583997 100644 --- a/src/test/ui/traits/vtable/vtable-vacant.stderr +++ b/src/test/ui/traits/vtable/vtable-vacant.stderr @@ -1,12 +1,12 @@ error: vtable entries for `<S as B>`: [ - MetadataDropInPlace, - MetadataSize, - MetadataAlign, - Method(<S as A>::foo_a1), - Vacant, - Method(<S as B>::foo_b1), - Vacant, -] + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as A>::foo_a1), + Vacant, + Method(<S as B>::foo_b1), + Vacant, + ] --> $DIR/vtable-vacant.rs:15:1 | LL | / trait B: A { diff --git a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr index d9e0d21541..02c5d5d248 100644 --- a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr +++ b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr @@ -27,12 +27,6 @@ LL | Foo::test(&4i32); | --------- ^^^^^ the trait `Foo` is not implemented for `i32` | | | required by a bound introduced by this call - | -note: required by `Foo::test` - --> $DIR/trivial-bounds-leak.rs:5:5 - | -LL | fn test(&self); - | ^^^^^^^^^^^^^^^ error[E0277]: the trait bound `i32: Foo` is not satisfied --> $DIR/trivial-bounds-leak.rs:26:22 diff --git a/src/test/ui/issues/issue-45124.rs b/src/test/ui/try-block/issue-45124.rs similarity index 100% rename from src/test/ui/issues/issue-45124.rs rename to src/test/ui/try-block/issue-45124.rs diff --git a/src/test/ui/try-block/try-block-bad-type.stderr b/src/test/ui/try-block/try-block-bad-type.stderr index fce8dbab48..cf3a07808d 100644 --- a/src/test/ui/try-block/try-block-bad-type.stderr +++ b/src/test/ui/try-block/try-block-bad-type.stderr @@ -8,11 +8,6 @@ LL | Err("")?; = help: the following implementations were found: <TryFromSliceError as From<Infallible>> = note: required because of the requirements on the impl of `FromResidual<Result<Infallible, &str>>` for `Result<u32, TryFromSliceError>` -note: required by `from_residual` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn from_residual(residual: R) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0271]: type mismatch resolving `<Result<i32, i32> as Try>::Output == &str` --> $DIR/try-block-bad-type.rs:12:9 @@ -33,11 +28,6 @@ LL | let res: () = try { }; | ^ could not wrap the final value of the block as `()` doesn't implement `Try` | = help: the trait `Try` is not implemented for `()` -note: required by `from_output` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn from_output(output: Self::Output) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`) --> $DIR/try-block-bad-type.rs:20:26 @@ -46,11 +36,6 @@ LL | let res: i32 = try { 5 }; | ^ could not wrap the final value of the block as `i32` doesn't implement `Try` | = help: the trait `Try` is not implemented for `i32` -note: required by `from_output` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn from_output(output: Self::Output) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/try-block/try-block-in-while.stderr b/src/test/ui/try-block/try-block-in-while.stderr index 4270df5b40..62cc26dd40 100644 --- a/src/test/ui/try-block/try-block-in-while.stderr +++ b/src/test/ui/try-block/try-block-in-while.stderr @@ -5,11 +5,6 @@ LL | while try { false } {} | ^^^^^ could not wrap the final value of the block as `bool` doesn't implement `Try` | = help: the trait `Try` is not implemented for `bool` -note: required by `from_output` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn from_output(output: Self::Output) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/try-is-identifier-edition2015.rs b/src/test/ui/try-block/try-is-identifier-edition2015.rs similarity index 100% rename from src/test/ui/try-is-identifier-edition2015.rs rename to src/test/ui/try-block/try-is-identifier-edition2015.rs diff --git a/src/test/ui/try-trait/bad-interconversion.stderr b/src/test/ui/try-trait/bad-interconversion.stderr index 5cecf9128b..80c5e6f529 100644 --- a/src/test/ui/try-trait/bad-interconversion.stderr +++ b/src/test/ui/try-trait/bad-interconversion.stderr @@ -11,11 +11,6 @@ LL | Ok(Err(123_i32)?) <u8 as From<NonZeroU8>> <u8 as From<bool>> = note: required because of the requirements on the impl of `FromResidual<Result<Infallible, i32>>` for `Result<u64, u8>` -note: required by `from_residual` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn from_residual(residual: R) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result` --> $DIR/bad-interconversion.rs:11:12 @@ -29,11 +24,6 @@ LL | | } | |_- this function returns a `Result` | = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<u64, String>` -note: required by `from_residual` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn from_residual(residual: R) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used on `Result`s in a function that returns `Result` --> $DIR/bad-interconversion.rs:17:31 @@ -46,11 +36,6 @@ LL | | } | |_- this function returns a `Result` | = help: the trait `FromResidual<ControlFlow<{integer}, Infallible>>` is not implemented for `Result<u64, String>` -note: required by `from_residual` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn from_residual(residual: R) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option` --> $DIR/bad-interconversion.rs:22:22 @@ -63,11 +48,6 @@ LL | | } | |_- this function returns an `Option` | = help: the trait `FromResidual<Result<Infallible, &str>>` is not implemented for `Option<u16>` -note: required by `from_residual` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn from_residual(residual: R) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used on `Option`s in a function that returns `Option` --> $DIR/bad-interconversion.rs:27:33 @@ -80,11 +60,6 @@ LL | | } | |_- this function returns an `Option` | = help: the trait `FromResidual<ControlFlow<{integer}, Infallible>>` is not implemented for `Option<u64>` -note: required by `from_residual` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn from_residual(residual: R) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow` --> $DIR/bad-interconversion.rs:32:39 @@ -97,11 +72,6 @@ LL | | } | |_- this function returns a `ControlFlow` | = help: the trait `FromResidual<Result<Infallible, &str>>` is not implemented for `ControlFlow<String>` -note: required by `from_residual` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn from_residual(residual: R) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow` --> $DIR/bad-interconversion.rs:37:12 @@ -115,11 +85,6 @@ LL | | } | |_- this function returns a `ControlFlow` | = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `ControlFlow<u64>` -note: required by `from_residual` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn from_residual(residual: R) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator in a function that returns `ControlFlow<B, _>` can only be used on other `ControlFlow<B, _>`s (with the same Break type) --> $DIR/bad-interconversion.rs:43:29 @@ -134,11 +99,6 @@ LL | | } | = help: the trait `FromResidual<ControlFlow<u8, Infallible>>` is not implemented for `ControlFlow<i64>` = note: unlike `Result`, there's no `From`-conversion performed for `ControlFlow` -note: required by `from_residual` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn from_residual(residual: R) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 8 previous errors diff --git a/src/test/ui/try-trait/option-to-result.stderr b/src/test/ui/try-trait/option-to-result.stderr index f89813e729..aadfbf61f2 100644 --- a/src/test/ui/try-trait/option-to-result.stderr +++ b/src/test/ui/try-trait/option-to-result.stderr @@ -10,11 +10,6 @@ LL | | } | |_- this function returns a `Result` | = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<(), ()>` -note: required by `from_residual` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn from_residual(residual: R) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option` --> $DIR/option-to-result.rs:11:6 @@ -28,11 +23,6 @@ LL | | } | |_- this function returns an `Option` | = help: the trait `FromResidual<Result<Infallible, i32>>` is not implemented for `Option<i32>` -note: required by `from_residual` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn from_residual(residual: R) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/try-trait/try-on-option-diagnostics.stderr b/src/test/ui/try-trait/try-on-option-diagnostics.stderr index bb65aae561..a6badd1903 100644 --- a/src/test/ui/try-trait/try-on-option-diagnostics.stderr +++ b/src/test/ui/try-trait/try-on-option-diagnostics.stderr @@ -10,11 +10,6 @@ LL | | } | |_- this function should return `Result` or `Option` to accept `?` | = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32` -note: required by `from_residual` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn from_residual(residual: R) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used in a closure that returns `Result` or `Option` (or another type that implements `FromResidual`) --> $DIR/try-on-option-diagnostics.rs:14:10 @@ -29,11 +24,6 @@ LL | | }; | |_____- this function should return `Result` or `Option` to accept `?` | = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `{integer}` -note: required by `from_residual` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn from_residual(residual: R) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `FromResidual`) --> $DIR/try-on-option-diagnostics.rs:26:14 @@ -46,11 +36,6 @@ LL | | } | |_________- this function should return `Result` or `Option` to accept `?` | = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `()` -note: required by `from_residual` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn from_residual(residual: R) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used in a trait method that returns `Result` or `Option` (or another type that implements `FromResidual`) --> $DIR/try-on-option-diagnostics.rs:39:14 @@ -63,11 +48,6 @@ LL | | } | |_________- this function should return `Result` or `Option` to accept `?` | = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `()` -note: required by `from_residual` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn from_residual(residual: R) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/try-trait/try-on-option.stderr b/src/test/ui/try-trait/try-on-option.stderr index b522dd5709..27e33bc022 100644 --- a/src/test/ui/try-trait/try-on-option.stderr +++ b/src/test/ui/try-trait/try-on-option.stderr @@ -10,11 +10,6 @@ LL | | } | |_- this function returns a `Result` | = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<u32, ()>` -note: required by `from_residual` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn from_residual(residual: R) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) --> $DIR/try-on-option.rs:13:6 @@ -28,11 +23,6 @@ LL | | } | |_- this function should return `Result` or `Option` to accept `?` | = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32` -note: required by `from_residual` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn from_residual(residual: R) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/try-trait/try-operator-on-main.stderr b/src/test/ui/try-trait/try-operator-on-main.stderr index d669124e9f..ad55f40b5b 100644 --- a/src/test/ui/try-trait/try-operator-on-main.stderr +++ b/src/test/ui/try-trait/try-operator-on-main.stderr @@ -12,11 +12,6 @@ LL | | } | |_- this function should return `Result` or `Option` to accept `?` | = help: the trait `FromResidual<Result<Infallible, std::io::Error>>` is not implemented for `()` -note: required by `from_residual` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn from_residual(residual: R) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be applied to values that implement `Try` --> $DIR/try-operator-on-main.rs:10:5 @@ -25,11 +20,6 @@ LL | ()?; | ^^^ the `?` operator cannot be applied to type `()` | = help: the trait `Try` is not implemented for `()` -note: required by `branch` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn branch(self) -> ControlFlow<Self::Residual, Self::Output>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) --> $DIR/try-operator-on-main.rs:10:7 @@ -47,11 +37,6 @@ LL | | } | |_- this function should return `Result` or `Option` to accept `?` | = help: the trait `FromResidual<_>` is not implemented for `()` -note: required by `from_residual` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn from_residual(residual: R) -> Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `(): Try` is not satisfied --> $DIR/try-operator-on-main.rs:14:25 @@ -72,11 +57,6 @@ LL | ()?; | ^^^ the `?` operator cannot be applied to type `()` | = help: the trait `Try` is not implemented for `()` -note: required by `branch` - --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL - | -LL | fn branch(self) -> ControlFlow<Self::Residual, Self::Output>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/tuple-index-fat-types.rs b/src/test/ui/tuple/tuple-index-fat-types.rs similarity index 100% rename from src/test/ui/tuple-index-fat-types.rs rename to src/test/ui/tuple/tuple-index-fat-types.rs diff --git a/src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs b/src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs index 5f3b711b31..acbf15dcb6 100644 --- a/src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs +++ b/src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs @@ -31,7 +31,10 @@ impl Tr for E { type V = u8; fn f() -> Self::V { 0 } //~^ ERROR ambiguous associated item + //~| ERROR ambiguous associated item //~| WARN this was previously accepted + //~| WARN this was previously accepted + //~| HELP use fully-qualified syntax //~| HELP use fully-qualified syntax } diff --git a/src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr b/src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr index 870b1eec48..f007f71a73 100644 --- a/src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr +++ b/src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr @@ -18,5 +18,24 @@ note: `V` could also refer to the associated type defined here LL | type V; | ^^^^^^^ -error: aborting due to previous error +error: ambiguous associated item + --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:32:15 + | +LL | fn f() -> Self::V { 0 } + | ^^^^^^^ help: use fully-qualified syntax: `<E as Tr>::V` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57644 <https://github.com/rust-lang/rust/issues/57644> +note: `V` could refer to the variant defined here + --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:22:5 + | +LL | V + | ^ +note: `V` could also refer to the associated type defined here + --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:26:5 + | +LL | type V; + | ^^^^^^^ + +error: aborting due to 2 previous errors 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 2e12b768f7..0cf020861c 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 @@ -27,10 +27,11 @@ LL | Alias::Unit(); | | | call expression requires function | -help: `Alias::Unit` is a unit variant, you need to write it without the parenthesis +help: `Alias::Unit` is a unit variant, you need to write it without the parentheses | -LL | Alias::Unit; - | ~~~~~~~~~~~ +LL - Alias::Unit(); +LL + Alias::Unit; + | error[E0164]: expected tuple struct or tuple variant, found unit variant `Alias::Unit` --> $DIR/incorrect-variant-form-through-alias-caught.rs:17:9 diff --git a/src/test/ui/type-alias-impl-trait/argument-types.stderr b/src/test/ui/type-alias-impl-trait/argument-types.stderr index 1cbf9c95d3..a87e44a048 100644 --- a/src/test/ui/type-alias-impl-trait/argument-types.stderr +++ b/src/test/ui/type-alias-impl-trait/argument-types.stderr @@ -4,6 +4,8 @@ error[E0308]: mismatched types LL | type Foo = impl Debug; | ---------- the expected opaque type ... +LL | fn foo1(mut x: Foo) { + | --- expected due to this parameter type LL | x = 22_u32; | ^^^^^^ expected opaque type, found `u32` | diff --git a/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr b/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr index d60be4b1cc..4a49d6e4ab 100644 --- a/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr +++ b/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr @@ -1,11 +1,13 @@ error[E0277]: `Rc<u32>` cannot be sent between threads safely - --> $DIR/auto-trait-leakage2.rs:17:5 + --> $DIR/auto-trait-leakage2.rs:17:13 | LL | type Foo = impl std::fmt::Debug; | -------------------- within this `impl Debug` ... LL | is_send(m::foo()); - | ^^^^^^^ `Rc<u32>` cannot be sent between threads safely + | ------- ^^^^^^^^ `Rc<u32>` cannot be sent between threads safely + | | + | required by a bound introduced by this call | = help: within `impl Debug`, the trait `Send` is not implemented for `Rc<u32>` = note: required because it appears within the type `impl Debug` diff --git a/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.rs b/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.rs index c46c471592..685d76ee36 100644 --- a/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.rs +++ b/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.rs @@ -8,8 +8,7 @@ trait MyTrait {} impl MyTrait for () {} impl<F> FnOnce<()> for &F { - //~^ ERROR conflicting implementations - //~| ERROR type parameter `F` must be used + //~^ ERROR type parameter `F` must be used type Output = impl MyTrait; extern "rust-call" fn call_once(self, _: ()) -> Self::Output {} } diff --git a/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.stderr b/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.stderr index e1e259187f..b93ea955c8 100644 --- a/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.stderr +++ b/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.stderr @@ -1,13 +1,3 @@ -error[E0119]: conflicting implementations of trait `std::ops::FnOnce<()>` for type `&_` - --> $DIR/incoherent-assoc-imp-trait.rs:10:1 - | -LL | impl<F> FnOnce<()> for &F { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: conflicting implementation in crate `core`: - - impl<A, F> FnOnce<A> for &F - where F: Fn<A>, F: ?Sized; - error[E0210]: type parameter `F` must be used as the type parameter for some local type (e.g., `MyStruct<F>`) --> $DIR/incoherent-assoc-imp-trait.rs:10:6 | @@ -17,7 +7,6 @@ LL | impl<F> FnOnce<()> for &F { = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local = note: only traits defined in the current crate can be implemented for a type parameter -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0119, E0210. -For more information about an error, try `rustc --explain E0119`. +For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/issues/issue-60662.rs b/src/test/ui/type-alias-impl-trait/issue-60662.rs similarity index 100% rename from src/test/ui/issues/issue-60662.rs rename to src/test/ui/type-alias-impl-trait/issue-60662.rs diff --git a/src/test/ui/issues/issue-60662.stdout b/src/test/ui/type-alias-impl-trait/issue-60662.stdout similarity index 100% rename from src/test/ui/issues/issue-60662.stdout rename to src/test/ui/type-alias-impl-trait/issue-60662.stdout diff --git a/src/test/ui/type-alias-impl-trait/issue-89686.rs b/src/test/ui/type-alias-impl-trait/issue-89686.rs new file mode 100644 index 0000000000..5878b26fdd --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-89686.rs @@ -0,0 +1,24 @@ +// edition:2018 + +#![feature(type_alias_impl_trait)] + +use std::future::Future; + +type G<'a, T> = impl Future<Output = ()>; +//~^ ERROR: type mismatch resolving `<impl Future<Output = [async output]> as Future>::Output == ()` +//~| ERROR: the trait bound `T: Trait` is not satisfied + +trait Trait { + type F: Future<Output = ()>; + + fn f(&self) -> Self::F; + + fn g<'a>(&'a self) -> G<'a, Self> + where + Self: Sized, + { + async move { self.f().await } + } +} + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/issue-89686.stderr b/src/test/ui/type-alias-impl-trait/issue-89686.stderr new file mode 100644 index 0000000000..19ed9a7476 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-89686.stderr @@ -0,0 +1,34 @@ +error[E0271]: type mismatch resolving `<impl Future<Output = [async output]> as Future>::Output == ()` + --> $DIR/issue-89686.rs:7:17 + | +LL | type G<'a, T> = impl Future<Output = ()>; + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type +... +LL | async move { self.f().await } + | ------------------ the found `async` block + | + ::: $SRC_DIR/core/src/future/mod.rs:LL:COL + | +LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return> + | ------------------------------- the found opaque type + | + = note: expected unit type `()` + found associated type `<impl Future<Output = [async output]> as Future>::Output` + = help: consider constraining the associated type `<impl Future<Output = [async output]> as Future>::Output` to `()` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +error[E0277]: the trait bound `T: Trait` is not satisfied + --> $DIR/issue-89686.rs:7:17 + | +LL | type G<'a, T> = impl Future<Output = ()>; + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | type G<'a, T: Trait> = impl Future<Output = ()>; + | +++++++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0271, E0277. +For more information about an error, try `rustc --explain E0271`. diff --git a/src/test/ui/type-in-nested-module.rs b/src/test/ui/type-in-nested-module.rs deleted file mode 100644 index 8a92f065f1..0000000000 --- a/src/test/ui/type-in-nested-module.rs +++ /dev/null @@ -1,17 +0,0 @@ -// run-pass - -#![allow(non_camel_case_types)] -#![allow(dead_code)] - - -// pretty-expanded FIXME #23616 - -mod a { - pub mod b { - pub type t = isize; - - pub fn foo() { let _x: t = 10; } - } -} - -pub fn main() { } diff --git a/src/test/ui/issues/issue-30225.rs b/src/test/ui/type-inference/issue-30225.rs similarity index 100% rename from src/test/ui/issues/issue-30225.rs rename to src/test/ui/type-inference/issue-30225.rs diff --git a/src/test/ui/issues/issue-30225.stderr b/src/test/ui/type-inference/issue-30225.stderr similarity index 100% rename from src/test/ui/issues/issue-30225.stderr rename to src/test/ui/type-inference/issue-30225.stderr diff --git a/src/test/ui/type-ascription.rs b/src/test/ui/type/type-ascription.rs similarity index 100% rename from src/test/ui/type-ascription.rs rename to src/test/ui/type/type-ascription.rs diff --git a/src/test/ui/type/type-check-defaults.stderr b/src/test/ui/type/type-check-defaults.stderr index f8dbd66c1c..2a61547997 100644 --- a/src/test/ui/type/type-check-defaults.stderr +++ b/src/test/ui/type/type-check-defaults.stderr @@ -29,36 +29,18 @@ error[E0277]: the trait bound `String: Copy` is not satisfied | LL | struct Bounds<T:Copy=String>(T); | ^^^^ the trait `Copy` is not implemented for `String` - | -note: required by `Bounds` - --> $DIR/type-check-defaults.rs:11:1 - | -LL | struct Bounds<T:Copy=String>(T); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `String: Copy` is not satisfied --> $DIR/type-check-defaults.rs:14:42 | LL | struct WhereClause<T=String>(T) where T: Copy; | ^^^^ the trait `Copy` is not implemented for `String` - | -note: required by `WhereClause` - --> $DIR/type-check-defaults.rs:14:1 - | -LL | struct WhereClause<T=String>(T) where T: Copy; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `String: Copy` is not satisfied --> $DIR/type-check-defaults.rs:17:20 | LL | trait TraitBound<T:Copy=String> {} | ^^^^ the trait `Copy` is not implemented for `String` - | -note: required by `TraitBound` - --> $DIR/type-check-defaults.rs:17:1 - | -LL | trait TraitBound<T:Copy=String> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `T: Copy` is not satisfied --> $DIR/type-check-defaults.rs:21:25 @@ -83,11 +65,6 @@ LL | trait ProjectionPred<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {} | ^^^^^^^ no implementation for `i32 + u8` | = help: the trait `Add<u8>` is not implemented for `i32` -note: required by `ProjectionPred` - --> $DIR/type-check-defaults.rs:24:1 - | -LL | trait ProjectionPred<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 7 previous errors diff --git a/src/test/ui/type/type-check/assignment-expected-bool.stderr b/src/test/ui/type/type-check/assignment-expected-bool.stderr index 862ac65bc2..e2b821f7b0 100644 --- a/src/test/ui/type/type-check/assignment-expected-bool.stderr +++ b/src/test/ui/type/type-check/assignment-expected-bool.stderr @@ -48,10 +48,6 @@ error[E0308]: mismatched types LL | if 0 = 0 {} | ^^^^^ expected `bool`, found `()` | -help: you might have meant to use pattern matching - | -LL | if let 0 = 0 {} - | +++ help: you might have meant to compare for equality | LL | if 0 == 0 {} diff --git a/src/test/ui/type/type-check/assignment-in-if.stderr b/src/test/ui/type/type-check/assignment-in-if.stderr index 710be9d6a0..f4ef44e244 100644 --- a/src/test/ui/type/type-check/assignment-in-if.stderr +++ b/src/test/ui/type/type-check/assignment-in-if.stderr @@ -37,10 +37,6 @@ error[E0308]: mismatched types LL | if 3 = x { | ^^^^^ expected `bool`, found `()` | -help: you might have meant to use pattern matching - | -LL | if let 3 = x { - | +++ help: you might have meant to compare for equality | LL | if 3 == x { diff --git a/src/test/ui/type/type-check/issue-40294.stderr b/src/test/ui/type/type-check/issue-40294.stderr index 9ca07eaba8..6d1e490bcf 100644 --- a/src/test/ui/type/type-check/issue-40294.stderr +++ b/src/test/ui/type/type-check/issue-40294.stderr @@ -5,11 +5,6 @@ LL | where &'a T : Foo, | ^^^ cannot infer type for reference `&'a T` | = note: cannot satisfy `&'a T: Foo` -note: required by a bound in `Foo` - --> $DIR/issue-40294.rs:1:1 - | -LL | trait Foo: Sized { - | ^^^^^^^^^^^^^^^^ required by this bound in `Foo` error: aborting due to previous error diff --git a/src/test/ui/type/type-params-in-different-spaces-2.stderr b/src/test/ui/type/type-params-in-different-spaces-2.stderr index 368adb456d..53610985f3 100644 --- a/src/test/ui/type/type-params-in-different-spaces-2.stderr +++ b/src/test/ui/type/type-params-in-different-spaces-2.stderr @@ -4,11 +4,6 @@ error[E0277]: the trait bound `Self: Tr<U>` is not satisfied LL | Tr::op(u) | ^^^^^^ the trait `Tr<U>` is not implemented for `Self` | -note: required by `Tr::op` - --> $DIR/type-params-in-different-spaces-2.rs:5:5 - | -LL | fn op(_: T) -> Self; - | ^^^^^^^^^^^^^^^^^^^^ help: consider further restricting `Self` | LL | fn test<U>(u: U) -> Self where Self: Tr<U> { @@ -20,11 +15,6 @@ error[E0277]: the trait bound `Self: Tr<U>` is not satisfied LL | Tr::op(u) | ^^^^^^ the trait `Tr<U>` is not implemented for `Self` | -note: required by `Tr::op` - --> $DIR/type-params-in-different-spaces-2.rs:5:5 - | -LL | fn op(_: T) -> Self; - | ^^^^^^^^^^^^^^^^^^^^ help: consider further restricting `Self` | LL | fn test<U>(u: U) -> Self where Self: Tr<U> { diff --git a/src/test/ui/issues/auxiliary/xcrate-issue-43189-a.rs b/src/test/ui/typeck/auxiliary/xcrate-issue-43189-a.rs similarity index 100% rename from src/test/ui/issues/auxiliary/xcrate-issue-43189-a.rs rename to src/test/ui/typeck/auxiliary/xcrate-issue-43189-a.rs diff --git a/src/test/ui/issues/auxiliary/xcrate-issue-43189-b.rs b/src/test/ui/typeck/auxiliary/xcrate-issue-43189-b.rs similarity index 100% rename from src/test/ui/issues/auxiliary/xcrate-issue-43189-b.rs rename to src/test/ui/typeck/auxiliary/xcrate-issue-43189-b.rs diff --git a/src/test/ui/issues/auxiliary/xcrate-issue-46112-rexport-core.rs b/src/test/ui/typeck/auxiliary/xcrate-issue-46112-rexport-core.rs similarity index 100% rename from src/test/ui/issues/auxiliary/xcrate-issue-46112-rexport-core.rs rename to src/test/ui/typeck/auxiliary/xcrate-issue-46112-rexport-core.rs diff --git a/src/test/ui/issues/auxiliary/xcrate-issue-61711-b.rs b/src/test/ui/typeck/auxiliary/xcrate-issue-61711-b.rs similarity index 100% rename from src/test/ui/issues/auxiliary/xcrate-issue-61711-b.rs rename to src/test/ui/typeck/auxiliary/xcrate-issue-61711-b.rs diff --git a/src/test/ui/issues/issue-43189.rs b/src/test/ui/typeck/issue-43189.rs similarity index 100% rename from src/test/ui/issues/issue-43189.rs rename to src/test/ui/typeck/issue-43189.rs diff --git a/src/test/ui/issues/issue-43189.stderr b/src/test/ui/typeck/issue-43189.stderr similarity index 100% rename from src/test/ui/issues/issue-43189.stderr rename to src/test/ui/typeck/issue-43189.stderr diff --git a/src/test/ui/issues/issue-46112.rs b/src/test/ui/typeck/issue-46112.rs similarity index 100% rename from src/test/ui/issues/issue-46112.rs rename to src/test/ui/typeck/issue-46112.rs diff --git a/src/test/ui/issues/issue-46112.stderr b/src/test/ui/typeck/issue-46112.stderr similarity index 58% rename from src/test/ui/issues/issue-46112.stderr rename to src/test/ui/typeck/issue-46112.stderr index ec05fbe580..39bff88e7f 100644 --- a/src/test/ui/issues/issue-46112.stderr +++ b/src/test/ui/typeck/issue-46112.stderr @@ -2,13 +2,14 @@ error[E0308]: mismatched types --> $DIR/issue-46112.rs:9:21 | LL | fn main() { test(Ok(())); } - | ^^ - | | - | expected enum `Option`, found `()` - | help: try using a variant of the expected enum: `Some(())` + | ^^ expected enum `Option`, found `()` | = note: expected enum `Option<()>` found unit type `()` +help: try wrapping the expression in `Some` + | +LL | fn main() { test(Ok(Some(()))); } + | +++++ + error: aborting due to previous error diff --git a/src/test/ui/issues/issue-61711-once-caused-rustc-inf-loop.rs b/src/test/ui/typeck/issue-61711-once-caused-rustc-inf-loop.rs similarity index 100% rename from src/test/ui/issues/issue-61711-once-caused-rustc-inf-loop.rs rename to src/test/ui/typeck/issue-61711-once-caused-rustc-inf-loop.rs diff --git a/src/test/ui/typeck/issue-81293.stderr b/src/test/ui/typeck/issue-81293.stderr index 1e6ff3b5f9..c545a563b0 100644 --- a/src/test/ui/typeck/issue-81293.stderr +++ b/src/test/ui/typeck/issue-81293.stderr @@ -7,6 +7,9 @@ LL | a = c + b * 5; error[E0308]: mismatched types --> $DIR/issue-81293.rs:6:9 | +LL | let a: u16; + | --- expected due to this type +... LL | a = c + b * 5; | ^^^^^^^^^ expected `u16`, found `usize` diff --git a/src/test/ui/typeck/issue-87771-ice-assign-assign-to-bool.stderr b/src/test/ui/typeck/issue-87771-ice-assign-assign-to-bool.stderr index fe10fa733d..56817ee2ca 100644 --- a/src/test/ui/typeck/issue-87771-ice-assign-assign-to-bool.stderr +++ b/src/test/ui/typeck/issue-87771-ice-assign-assign-to-bool.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/issue-87771-ice-assign-assign-to-bool.rs:3:9 | +LL | let mut a; + | ----- expected due to the type of this binding LL | a = a = true; | ^^^^^^^^ expected `bool`, found `()` diff --git a/src/test/ui/typeck/issue-89806.rs b/src/test/ui/typeck/issue-89806.rs new file mode 100644 index 0000000000..69cec08652 --- /dev/null +++ b/src/test/ui/typeck/issue-89806.rs @@ -0,0 +1,3 @@ +fn main() { + 0u8.as_ref(); //~ ERROR no method named `as_ref` found for type `u8` in the current scope +} diff --git a/src/test/ui/typeck/issue-89806.stderr b/src/test/ui/typeck/issue-89806.stderr new file mode 100644 index 0000000000..c36b4967ee --- /dev/null +++ b/src/test/ui/typeck/issue-89806.stderr @@ -0,0 +1,9 @@ +error[E0599]: no method named `as_ref` found for type `u8` in the current scope + --> $DIR/issue-89806.rs:2:9 + | +LL | 0u8.as_ref(); + | ^^^^^^ method not found in `u8` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/typeck/issue-89856.rs b/src/test/ui/typeck/issue-89856.rs new file mode 100644 index 0000000000..b021e349e3 --- /dev/null +++ b/src/test/ui/typeck/issue-89856.rs @@ -0,0 +1,8 @@ +fn take_str_maybe(x: Option<&str>) -> Option<&str> { None } + +fn main() { + let string = String::from("Hello, world"); + let option = Some(&string); + take_str_maybe(option); + //~^ ERROR: mismatched types [E0308] +} diff --git a/src/test/ui/typeck/issue-89856.stderr b/src/test/ui/typeck/issue-89856.stderr new file mode 100644 index 0000000000..4cb46a34a0 --- /dev/null +++ b/src/test/ui/typeck/issue-89856.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/issue-89856.rs:6:20 + | +LL | take_str_maybe(option); + | ^^^^^^ expected `str`, found struct `String` + | + = note: expected enum `Option<&str>` + found enum `Option<&String>` +help: try converting the passed type into a `&str` + | +LL | take_str_maybe(option.map(|x| &**x)); + | ++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/typeck/issue-90101.rs b/src/test/ui/typeck/issue-90101.rs new file mode 100644 index 0000000000..1954ee6f1e --- /dev/null +++ b/src/test/ui/typeck/issue-90101.rs @@ -0,0 +1,8 @@ +use std::path::{Path, PathBuf}; + +fn func(path: impl Into<PathBuf>, code: impl Into<String>) {} + +fn main() { + func(Path::new("hello").to_path_buf().to_string_lossy(), "world") + //~^ ERROR [E0277] +} diff --git a/src/test/ui/typeck/issue-90101.stderr b/src/test/ui/typeck/issue-90101.stderr new file mode 100644 index 0000000000..998b636887 --- /dev/null +++ b/src/test/ui/typeck/issue-90101.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `PathBuf: From<Cow<'_, str>>` is not satisfied + --> $DIR/issue-90101.rs:6:10 + | +LL | func(Path::new("hello").to_path_buf().to_string_lossy(), "world") + | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<Cow<'_, str>>` is not implemented for `PathBuf` + | | + | required by a bound introduced by this call + | + = help: the following implementations were found: + <PathBuf as From<&T>> + <PathBuf as From<Box<Path>>> + <PathBuf as From<Cow<'a, Path>>> + <PathBuf as From<OsString>> + <PathBuf as From<String>> + = note: required because of the requirements on the impl of `Into<PathBuf>` for `Cow<'_, str>` +note: required by a bound in `func` + --> $DIR/issue-90101.rs:3:20 + | +LL | fn func(path: impl Into<PathBuf>, code: impl Into<String>) {} + | ^^^^^^^^^^^^^ required by this bound in `func` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/typeck/issue-90164.rs b/src/test/ui/typeck/issue-90164.rs new file mode 100644 index 0000000000..63350433e4 --- /dev/null +++ b/src/test/ui/typeck/issue-90164.rs @@ -0,0 +1,9 @@ +fn copy<R: Unpin, W>(_: R, _: W) {} + +fn f<T>(r: T) { + let w = (); + copy(r, w); + //~^ ERROR [E0277] +} + +fn main() {} diff --git a/src/test/ui/typeck/issue-90164.stderr b/src/test/ui/typeck/issue-90164.stderr new file mode 100644 index 0000000000..1e2f1bae3b --- /dev/null +++ b/src/test/ui/typeck/issue-90164.stderr @@ -0,0 +1,22 @@ +error[E0277]: `T` cannot be unpinned + --> $DIR/issue-90164.rs:5:10 + | +LL | copy(r, w); + | ---- ^ the trait `Unpin` is not implemented for `T` + | | + | required by a bound introduced by this call + | + = note: consider using `Box::pin` +note: required by a bound in `copy` + --> $DIR/issue-90164.rs:1:12 + | +LL | fn copy<R: Unpin, W>(_: R, _: W) {} + | ^^^^^ required by this bound in `copy` +help: consider restricting type parameter `T` + | +LL | fn f<T: std::marker::Unpin>(r: T) { + | ++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/typeck/issue-90804-incorrect-reference-suggestion.rs b/src/test/ui/typeck/issue-90804-incorrect-reference-suggestion.rs new file mode 100644 index 0000000000..f891a42fc2 --- /dev/null +++ b/src/test/ui/typeck/issue-90804-incorrect-reference-suggestion.rs @@ -0,0 +1,11 @@ +// Do not suggest referencing the parameter to `check` + +trait Marker<T> {} + +impl<T> Marker<i32> for T {} + +pub fn check<T: Marker<u32>>(_: T) {} + +pub fn main() { + check::<()>(()); //~ ERROR [E0277] +} diff --git a/src/test/ui/typeck/issue-90804-incorrect-reference-suggestion.stderr b/src/test/ui/typeck/issue-90804-incorrect-reference-suggestion.stderr new file mode 100644 index 0000000000..08eab02537 --- /dev/null +++ b/src/test/ui/typeck/issue-90804-incorrect-reference-suggestion.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `(): Marker<u32>` is not satisfied + --> $DIR/issue-90804-incorrect-reference-suggestion.rs:10:17 + | +LL | check::<()>(()); + | ----------- ^^ the trait `Marker<u32>` is not implemented for `()` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/issue-90804-incorrect-reference-suggestion.rs:7:17 + | +LL | pub fn check<T: Marker<u32>>(_: T) {} + | ^^^^^^^^^^^ required by this bound in `check` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/no-type-for-node-ice.rs b/src/test/ui/typeck/no-type-for-node-ice.rs similarity index 100% rename from src/test/ui/no-type-for-node-ice.rs rename to src/test/ui/typeck/no-type-for-node-ice.rs diff --git a/src/test/ui/no-type-for-node-ice.stderr b/src/test/ui/typeck/no-type-for-node-ice.stderr similarity index 100% rename from src/test/ui/no-type-for-node-ice.stderr rename to src/test/ui/typeck/no-type-for-node-ice.stderr diff --git a/src/test/ui/prim-with-args.rs b/src/test/ui/typeck/prim-with-args.rs similarity index 100% rename from src/test/ui/prim-with-args.rs rename to src/test/ui/typeck/prim-with-args.rs diff --git a/src/test/ui/prim-with-args.stderr b/src/test/ui/typeck/prim-with-args.stderr similarity index 100% rename from src/test/ui/prim-with-args.stderr rename to src/test/ui/typeck/prim-with-args.stderr diff --git a/src/test/ui/project-cache-issue-37154.rs b/src/test/ui/typeck/project-cache-issue-37154.rs similarity index 100% rename from src/test/ui/project-cache-issue-37154.rs rename to src/test/ui/typeck/project-cache-issue-37154.rs diff --git a/src/test/ui/typeck/typeck-unsafe-always-share.stderr b/src/test/ui/typeck/typeck-unsafe-always-share.stderr index 4b5804253b..154e504996 100644 --- a/src/test/ui/typeck/typeck-unsafe-always-share.stderr +++ b/src/test/ui/typeck/typeck-unsafe-always-share.stderr @@ -29,10 +29,12 @@ LL | fn test<T: Sync>(s: T) {} | ^^^^ required by this bound in `test` error[E0277]: `UnsafeCell<NoSync>` cannot be shared between threads safely - --> $DIR/typeck-unsafe-always-share.rs:27:5 + --> $DIR/typeck-unsafe-always-share.rs:27:10 | LL | test(ms); - | ^^^^ `UnsafeCell<NoSync>` cannot be shared between threads safely + | ---- ^^ `UnsafeCell<NoSync>` cannot be shared between threads safely + | | + | required by a bound introduced by this call | = help: within `MySync<NoSync>`, the trait `Sync` is not implemented for `UnsafeCell<NoSync>` note: required because it appears within the type `MySync<NoSync>` diff --git a/src/test/ui/ufcs-type-params.rs b/src/test/ui/typeck/ufcs-type-params.rs similarity index 100% rename from src/test/ui/ufcs-type-params.rs rename to src/test/ui/typeck/ufcs-type-params.rs diff --git a/src/test/ui/unify-return-ty.rs b/src/test/ui/typeck/unify-return-ty.rs similarity index 100% rename from src/test/ui/unify-return-ty.rs rename to src/test/ui/typeck/unify-return-ty.rs diff --git a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr index 23b9157375..d0bc432a1c 100644 --- a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr +++ b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr @@ -5,11 +5,6 @@ LL | <i32 as Add<u32>>::add(1, 2); | ^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u32` | = help: the trait `Add<u32>` is not implemented for `i32` -note: required by `add` - --> $SRC_DIR/core/src/ops/arith.rs:LL:COL - | -LL | fn add(self, rhs: Rhs) -> Self::Output; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/ufcs-qpath-self-mismatch.rs:6:28 diff --git a/src/test/ui/issues/issue-18652.rs b/src/test/ui/unboxed-closures/issue-18652.rs similarity index 100% rename from src/test/ui/issues/issue-18652.rs rename to src/test/ui/unboxed-closures/issue-18652.rs diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr b/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr index 76c14ccc14..8976da01e7 100644 --- a/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr +++ b/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr @@ -5,6 +5,12 @@ LL | fn foo(x: &mut Vec<&'_ u8>, y: &'_ u8) { x.push(y); } | ------ ------ ^ ...but data from `y` flows into `x` here | | | these two types are declared with different lifetimes... + | + = note: each elided lifetime in input position becomes a distinct lifetime +help: consider introducing a named lifetime parameter + | +LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } + | ++++ ~~ ~~ error: aborting due to previous error diff --git a/src/test/ui/unevaluated_fixed_size_array_len.stderr b/src/test/ui/unevaluated_fixed_size_array_len.stderr index be6ed8d562..03932d5ed0 100644 --- a/src/test/ui/unevaluated_fixed_size_array_len.stderr +++ b/src/test/ui/unevaluated_fixed_size_array_len.stderr @@ -6,11 +6,6 @@ LL | <[(); 0] as Foo>::foo() | = help: the following implementations were found: <[(); 1] as Foo> -note: required by `Foo::foo` - --> $DIR/unevaluated_fixed_size_array_len.rs:4:5 - | -LL | fn foo(); - | ^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/uniform-paths/basic-nested.rs b/src/test/ui/uniform-paths/basic-nested.rs index e4e8b32c70..dcf0eb646f 100644 --- a/src/test/ui/uniform-paths/basic-nested.rs +++ b/src/test/ui/uniform-paths/basic-nested.rs @@ -44,10 +44,10 @@ mod bar { fn main() { foo::Foo(()); - foo::std_io::stdout(); + let _ = foo::std_io::stdout(); foo::local_io(()); - io::stdout(); - bar::io::stdout(); + let _ = io::stdout(); + let _ = bar::io::stdout(); bar::std(); bar::std!(); @@ -56,6 +56,6 @@ fn main() { // scope is allowed, when both resolve to the same definition. use std::io; use io::stdout; - stdout(); + let _ = stdout(); } } diff --git a/src/test/ui/uniform-paths/basic.rs b/src/test/ui/uniform-paths/basic.rs index 4e2e2dedef..ce611a7cac 100644 --- a/src/test/ui/uniform-paths/basic.rs +++ b/src/test/ui/uniform-paths/basic.rs @@ -20,7 +20,7 @@ use self::std::io as local_io; fn main() { Foo(()); - std_io::stdout(); + let _ = std_io::stdout(); local_io(()); { @@ -28,6 +28,6 @@ fn main() { // scope is allowed, when both resolve to the same definition. use ::std::io as std_io; use std_io::stdout; - stdout(); + let _ = stdout(); } } diff --git a/src/test/ui/uniform-paths/macros-nested.rs b/src/test/ui/uniform-paths/macros-nested.rs index a62a28bb94..175ccd34e9 100644 --- a/src/test/ui/uniform-paths/macros-nested.rs +++ b/src/test/ui/uniform-paths/macros-nested.rs @@ -46,8 +46,8 @@ mod bar { fn main() { foo::Foo(()); - foo::std_io::stdout(); + let _ = foo::std_io::stdout(); foo::local_io(()); - io::stdout(); - bar::io::stdout(); + let _ = io::stdout(); + let _ = bar::io::stdout(); } diff --git a/src/test/ui/uniform-paths/macros.rs b/src/test/ui/uniform-paths/macros.rs index 31b809f0cf..bf512b3056 100644 --- a/src/test/ui/uniform-paths/macros.rs +++ b/src/test/ui/uniform-paths/macros.rs @@ -31,6 +31,6 @@ m2!(); fn main() { Foo(()); - std_io::stdout(); + let _ = std_io::stdout(); local_io(()); } diff --git a/src/test/ui/union/issue-41073.stderr b/src/test/ui/union/issue-41073.stderr index 2e9598b227..8edf4db441 100644 --- a/src/test/ui/union/issue-41073.stderr +++ b/src/test/ui/union/issue-41073.stderr @@ -4,11 +4,10 @@ error[E0740]: unions may not contain fields that need dropping LL | a: A, | ^^^^ | -note: `std::mem::ManuallyDrop` can be used to wrap the type - --> $DIR/issue-41073.rs:4:5 +help: wrap the type with `std::mem::ManuallyDrop` and ensure it is manually dropped | -LL | a: A, - | ^^^^ +LL | a: std::mem::ManuallyDrop<A>, + | +++++++++++++++++++++++ + error: aborting due to previous error diff --git a/src/test/ui/union/union-custom-drop.stderr b/src/test/ui/union/union-custom-drop.stderr index ee2333f905..65ca5fd931 100644 --- a/src/test/ui/union/union-custom-drop.stderr +++ b/src/test/ui/union/union-custom-drop.stderr @@ -4,11 +4,10 @@ error[E0740]: unions may not contain fields that need dropping LL | bar: Bar, | ^^^^^^^^ | -note: `std::mem::ManuallyDrop` can be used to wrap the type - --> $DIR/union-custom-drop.rs:7:5 +help: wrap the type with `std::mem::ManuallyDrop` and ensure it is manually dropped | -LL | bar: Bar, - | ^^^^^^^^ +LL | bar: std::mem::ManuallyDrop<Bar>, + | +++++++++++++++++++++++ + error: aborting due to previous error diff --git a/src/test/ui/union/union-generic.mirunsafeck.stderr b/src/test/ui/union/union-generic.mirunsafeck.stderr index cd85778186..a4f0c400d7 100644 --- a/src/test/ui/union/union-generic.mirunsafeck.stderr +++ b/src/test/ui/union/union-generic.mirunsafeck.stderr @@ -4,11 +4,11 @@ error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied LL | let u = U { a: Rc::new(0u32) }; | ^ the trait `Copy` is not implemented for `Rc<u32>` | -note: required by `U` - --> $DIR/union-generic.rs:6:1 +note: required by a bound in `U` + --> $DIR/union-generic.rs:6:12 | LL | union U<T: Copy> { - | ^^^^^^^^^^^^^^^^ + | ^^^^ required by this bound in `U` error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied --> $DIR/union-generic.rs:13:13 @@ -16,11 +16,11 @@ error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied LL | let u = U::<Rc<u32>> { a: Default::default() }; | ^^^^^^^^^^^^ the trait `Copy` is not implemented for `Rc<u32>` | -note: required by `U` - --> $DIR/union-generic.rs:6:1 +note: required by a bound in `U` + --> $DIR/union-generic.rs:6:12 | LL | union U<T: Copy> { - | ^^^^^^^^^^^^^^^^ + | ^^^^ required by this bound in `U` error: aborting due to 2 previous errors diff --git a/src/test/ui/union/union-generic.thirunsafeck.stderr b/src/test/ui/union/union-generic.thirunsafeck.stderr index cd85778186..a4f0c400d7 100644 --- a/src/test/ui/union/union-generic.thirunsafeck.stderr +++ b/src/test/ui/union/union-generic.thirunsafeck.stderr @@ -4,11 +4,11 @@ error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied LL | let u = U { a: Rc::new(0u32) }; | ^ the trait `Copy` is not implemented for `Rc<u32>` | -note: required by `U` - --> $DIR/union-generic.rs:6:1 +note: required by a bound in `U` + --> $DIR/union-generic.rs:6:12 | LL | union U<T: Copy> { - | ^^^^^^^^^^^^^^^^ + | ^^^^ required by this bound in `U` error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied --> $DIR/union-generic.rs:13:13 @@ -16,11 +16,11 @@ error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied LL | let u = U::<Rc<u32>> { a: Default::default() }; | ^^^^^^^^^^^^ the trait `Copy` is not implemented for `Rc<u32>` | -note: required by `U` - --> $DIR/union-generic.rs:6:1 +note: required by a bound in `U` + --> $DIR/union-generic.rs:6:12 | LL | union U<T: Copy> { - | ^^^^^^^^^^^^^^^^ + | ^^^^ required by this bound in `U` error: aborting due to 2 previous errors diff --git a/src/test/ui/union/union-with-drop-fields.mirunsafeck.stderr b/src/test/ui/union/union-with-drop-fields.mirunsafeck.stderr index 2062fb7473..f5e9681735 100644 --- a/src/test/ui/union/union-with-drop-fields.mirunsafeck.stderr +++ b/src/test/ui/union/union-with-drop-fields.mirunsafeck.stderr @@ -4,11 +4,10 @@ error[E0740]: unions may not contain fields that need dropping LL | a: String, | ^^^^^^^^^ | -note: `std::mem::ManuallyDrop` can be used to wrap the type - --> $DIR/union-with-drop-fields.rs:11:5 +help: wrap the type with `std::mem::ManuallyDrop` and ensure it is manually dropped | -LL | a: String, - | ^^^^^^^^^ +LL | a: std::mem::ManuallyDrop<String>, + | +++++++++++++++++++++++ + error[E0740]: unions may not contain fields that need dropping --> $DIR/union-with-drop-fields.rs:19:5 @@ -16,11 +15,10 @@ error[E0740]: unions may not contain fields that need dropping LL | a: S, | ^^^^ | -note: `std::mem::ManuallyDrop` can be used to wrap the type - --> $DIR/union-with-drop-fields.rs:19:5 +help: wrap the type with `std::mem::ManuallyDrop` and ensure it is manually dropped | -LL | a: S, - | ^^^^ +LL | a: std::mem::ManuallyDrop<S>, + | +++++++++++++++++++++++ + error[E0740]: unions may not contain fields that need dropping --> $DIR/union-with-drop-fields.rs:24:5 @@ -28,11 +26,10 @@ error[E0740]: unions may not contain fields that need dropping LL | a: T, | ^^^^ | -note: `std::mem::ManuallyDrop` can be used to wrap the type - --> $DIR/union-with-drop-fields.rs:24:5 +help: wrap the type with `std::mem::ManuallyDrop` and ensure it is manually dropped | -LL | a: T, - | ^^^^ +LL | a: std::mem::ManuallyDrop<T>, + | +++++++++++++++++++++++ + error: aborting due to 3 previous errors diff --git a/src/test/ui/union/union-with-drop-fields.thirunsafeck.stderr b/src/test/ui/union/union-with-drop-fields.thirunsafeck.stderr index 2062fb7473..f5e9681735 100644 --- a/src/test/ui/union/union-with-drop-fields.thirunsafeck.stderr +++ b/src/test/ui/union/union-with-drop-fields.thirunsafeck.stderr @@ -4,11 +4,10 @@ error[E0740]: unions may not contain fields that need dropping LL | a: String, | ^^^^^^^^^ | -note: `std::mem::ManuallyDrop` can be used to wrap the type - --> $DIR/union-with-drop-fields.rs:11:5 +help: wrap the type with `std::mem::ManuallyDrop` and ensure it is manually dropped | -LL | a: String, - | ^^^^^^^^^ +LL | a: std::mem::ManuallyDrop<String>, + | +++++++++++++++++++++++ + error[E0740]: unions may not contain fields that need dropping --> $DIR/union-with-drop-fields.rs:19:5 @@ -16,11 +15,10 @@ error[E0740]: unions may not contain fields that need dropping LL | a: S, | ^^^^ | -note: `std::mem::ManuallyDrop` can be used to wrap the type - --> $DIR/union-with-drop-fields.rs:19:5 +help: wrap the type with `std::mem::ManuallyDrop` and ensure it is manually dropped | -LL | a: S, - | ^^^^ +LL | a: std::mem::ManuallyDrop<S>, + | +++++++++++++++++++++++ + error[E0740]: unions may not contain fields that need dropping --> $DIR/union-with-drop-fields.rs:24:5 @@ -28,11 +26,10 @@ error[E0740]: unions may not contain fields that need dropping LL | a: T, | ^^^^ | -note: `std::mem::ManuallyDrop` can be used to wrap the type - --> $DIR/union-with-drop-fields.rs:24:5 +help: wrap the type with `std::mem::ManuallyDrop` and ensure it is manually dropped | -LL | a: T, - | ^^^^ +LL | a: std::mem::ManuallyDrop<T>, + | +++++++++++++++++++++++ + error: aborting due to 3 previous errors diff --git a/src/test/ui/unsafe/unsafe-unstable-const-fn.mir.stderr b/src/test/ui/unsafe/unsafe-unstable-const-fn.mir.stderr index 99808495ea..dcb84a80cb 100644 --- a/src/test/ui/unsafe/unsafe-unstable-const-fn.mir.stderr +++ b/src/test/ui/unsafe/unsafe-unstable-const-fn.mir.stderr @@ -1,5 +1,5 @@ error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block - --> $DIR/unsafe-unstable-const-fn.rs:11:5 + --> $DIR/unsafe-unstable-const-fn.rs:10:5 | LL | *a == b | ^^ dereference of raw pointer diff --git a/src/test/ui/unsafe/unsafe-unstable-const-fn.rs b/src/test/ui/unsafe/unsafe-unstable-const-fn.rs index 0476759ca6..581b15cdfb 100644 --- a/src/test/ui/unsafe/unsafe-unstable-const-fn.rs +++ b/src/test/ui/unsafe/unsafe-unstable-const-fn.rs @@ -3,7 +3,6 @@ #![stable(feature = "foo", since = "1.33.0")] #![feature(staged_api)] -#![feature(const_raw_ptr_deref)] #[stable(feature = "foo", since = "1.33.0")] #[rustc_const_unstable(feature = "const_foo", issue = "none")] diff --git a/src/test/ui/unsafe/unsafe-unstable-const-fn.thir.stderr b/src/test/ui/unsafe/unsafe-unstable-const-fn.thir.stderr index 99808495ea..dcb84a80cb 100644 --- a/src/test/ui/unsafe/unsafe-unstable-const-fn.thir.stderr +++ b/src/test/ui/unsafe/unsafe-unstable-const-fn.thir.stderr @@ -1,5 +1,5 @@ error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block - --> $DIR/unsafe-unstable-const-fn.rs:11:5 + --> $DIR/unsafe-unstable-const-fn.rs:10:5 | LL | *a == b | ^^ dereference of raw pointer diff --git a/src/test/ui/unsized-locals/unsized-exprs.stderr b/src/test/ui/unsized-locals/unsized-exprs.stderr index 6686e55130..6960255d98 100644 --- a/src/test/ui/unsized-locals/unsized-exprs.stderr +++ b/src/test/ui/unsized-locals/unsized-exprs.stderr @@ -16,7 +16,7 @@ LL | udrop::<A<[u8]>>(A { 0: *foo() }); | | | required by a bound introduced by this call | - = help: the trait `Sized` is not implemented for `[u8]` + = help: within `A<[u8]>`, the trait `Sized` is not implemented for `[u8]` note: required because it appears within the type `A<[u8]>` --> $DIR/unsized-exprs.rs:3:8 | diff --git a/src/test/ui/issues/issue-30355.rs b/src/test/ui/unsized/issue-30355.rs similarity index 100% rename from src/test/ui/issues/issue-30355.rs rename to src/test/ui/unsized/issue-30355.rs diff --git a/src/test/ui/issues/issue-30355.stderr b/src/test/ui/unsized/issue-30355.stderr similarity index 100% rename from src/test/ui/issues/issue-30355.stderr rename to src/test/ui/unsized/issue-30355.stderr diff --git a/src/test/ui/unsized/issue-71659.stderr b/src/test/ui/unsized/issue-71659.stderr index be2df8c85e..d7b95f5576 100644 --- a/src/test/ui/unsized/issue-71659.stderr +++ b/src/test/ui/unsized/issue-71659.stderr @@ -3,6 +3,15 @@ error[E0277]: the trait bound `dyn Foo: CastTo<[i32]>` is not satisfied | LL | let x = x.cast::<[i32]>(); | ^^^^ the trait `CastTo<[i32]>` is not implemented for `dyn Foo` + | +note: required by a bound in `Cast::cast` + --> $DIR/issue-71659.rs:19:15 + | +LL | fn cast<T: ?Sized>(&self) -> &T + | ---- required by a bound in this +LL | where +LL | Self: CastTo<T>, + | ^^^^^^^^^ required by this bound in `Cast::cast` error: aborting due to previous error diff --git a/src/test/ui/maybe-bounds-where-cpass.rs b/src/test/ui/unsized/maybe-bounds-where-cpass.rs similarity index 69% rename from src/test/ui/maybe-bounds-where-cpass.rs rename to src/test/ui/unsized/maybe-bounds-where-cpass.rs index d4bc05f7cb..0e018cdabb 100644 --- a/src/test/ui/maybe-bounds-where-cpass.rs +++ b/src/test/ui/unsized/maybe-bounds-where-cpass.rs @@ -1,4 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass struct S<T>(*const T) where T: ?Sized; diff --git a/src/test/ui/maybe-bounds-where.rs b/src/test/ui/unsized/maybe-bounds-where.rs similarity index 100% rename from src/test/ui/maybe-bounds-where.rs rename to src/test/ui/unsized/maybe-bounds-where.rs diff --git a/src/test/ui/maybe-bounds-where.stderr b/src/test/ui/unsized/maybe-bounds-where.stderr similarity index 100% rename from src/test/ui/maybe-bounds-where.stderr rename to src/test/ui/unsized/maybe-bounds-where.stderr diff --git a/src/test/ui/unsized/unchanged-param.rs b/src/test/ui/unsized/unchanged-param.rs index 83199e8112..93c7af68ac 100644 --- a/src/test/ui/unsized/unchanged-param.rs +++ b/src/test/ui/unsized/unchanged-param.rs @@ -1,4 +1,3 @@ -#![feature(relaxed_struct_unsize)] // run-pass // Test that we allow unsizing even if there is an unchanged param in the // field getting unsized. diff --git a/src/test/ui/unused-crate-deps/extern-loc-missing-loc.rs b/src/test/ui/unused-crate-deps/extern-loc-missing-loc.rs index 9339a004d3..6ac558974d 100644 --- a/src/test/ui/unused-crate-deps/extern-loc-missing-loc.rs +++ b/src/test/ui/unused-crate-deps/extern-loc-missing-loc.rs @@ -1,7 +1,7 @@ // --extern-location with a raw reference // aux-crate:bar=bar.rs -// compile-flags:--extern-location bar +// compile-flags:--extern-location bar -Zunstable-options #![warn(unused_crate_dependencies)] diff --git a/src/test/ui/use-crate-name-alias.rs b/src/test/ui/use-crate-name-alias.rs deleted file mode 100644 index 0920d96858..0000000000 --- a/src/test/ui/use-crate-name-alias.rs +++ /dev/null @@ -1,7 +0,0 @@ -// run-pass -// Issue #1706 -// pretty-expanded FIXME #23616 - -extern crate std as stdlib; - -pub fn main() {} diff --git a/src/test/ui/use/use-nested-groups-unused-imports.rs b/src/test/ui/use/use-nested-groups-unused-imports.rs index 5fe85954dc..ca6b8ba94d 100644 --- a/src/test/ui/use/use-nested-groups-unused-imports.rs +++ b/src/test/ui/use/use-nested-groups-unused-imports.rs @@ -1,4 +1,3 @@ -#![feature(use_nested_groups)] #![allow(dead_code)] #![deny(unused_imports)] diff --git a/src/test/ui/use/use-nested-groups-unused-imports.stderr b/src/test/ui/use/use-nested-groups-unused-imports.stderr index 987d1dcf5f..6610f8ecd4 100644 --- a/src/test/ui/use/use-nested-groups-unused-imports.stderr +++ b/src/test/ui/use/use-nested-groups-unused-imports.stderr @@ -1,23 +1,23 @@ error: unused imports: `*`, `Foo`, `baz::{}`, `foobar::*` - --> $DIR/use-nested-groups-unused-imports.rs:16:11 + --> $DIR/use-nested-groups-unused-imports.rs:15:11 | LL | use foo::{Foo, bar::{baz::{}, foobar::*}, *}; | ^^^ ^^^^^^^ ^^^^^^^^^ ^ | note: the lint level is defined here - --> $DIR/use-nested-groups-unused-imports.rs:3:9 + --> $DIR/use-nested-groups-unused-imports.rs:2:9 | LL | #![deny(unused_imports)] | ^^^^^^^^^^^^^^ error: unused import: `*` - --> $DIR/use-nested-groups-unused-imports.rs:18:24 + --> $DIR/use-nested-groups-unused-imports.rs:17:24 | LL | use foo::bar::baz::{*, *}; | ^ error: unused import: `foo::{}` - --> $DIR/use-nested-groups-unused-imports.rs:20:5 + --> $DIR/use-nested-groups-unused-imports.rs:19:5 | LL | use foo::{}; | ^^^^^^^ diff --git a/src/test/ui/variance/variance-associated-consts.rs b/src/test/ui/variance/variance-associated-consts.rs new file mode 100644 index 0000000000..da55bc9624 --- /dev/null +++ b/src/test/ui/variance/variance-associated-consts.rs @@ -0,0 +1,17 @@ +// Test that the variance computation considers types that +// appear in const expressions to be invariant. + +#![feature(rustc_attrs)] +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +trait Trait { + const Const: usize; +} + +#[rustc_variance] +struct Foo<T: Trait> { //~ ERROR [o] + field: [u8; <T as Trait>::Const] +} + +fn main() { } diff --git a/src/test/ui/variance/variance-associated-consts.stderr b/src/test/ui/variance/variance-associated-consts.stderr new file mode 100644 index 0000000000..d1bf34781d --- /dev/null +++ b/src/test/ui/variance/variance-associated-consts.stderr @@ -0,0 +1,10 @@ +error[E0208]: [o] + --> $DIR/variance-associated-consts.rs:13:1 + | +LL | / struct Foo<T: Trait> { +LL | | field: [u8; <T as Trait>::Const] +LL | | } + | |_^ + +error: aborting due to previous error + diff --git a/src/test/ui/wasm-import-module.rs b/src/test/ui/wasm/wasm-import-module.rs similarity index 100% rename from src/test/ui/wasm-import-module.rs rename to src/test/ui/wasm/wasm-import-module.rs diff --git a/src/test/ui/wasm-import-module.stderr b/src/test/ui/wasm/wasm-import-module.stderr similarity index 100% rename from src/test/ui/wasm-import-module.stderr rename to src/test/ui/wasm/wasm-import-module.stderr diff --git a/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr b/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr index 66bfdbc596..b03023b5fd 100644 --- a/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr +++ b/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr @@ -3,12 +3,6 @@ error[E0277]: the trait bound `(): Foo` is not satisfied | LL | pub fn lint_me() -> <() as Foo>::Assoc; | ^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` - | -note: required by a bound in `Foo` - --> $DIR/wf-foreign-fn-decl-ret.rs:6:1 - | -LL | pub trait Foo { - | ^^^^^^^^^^^^^ required by this bound in `Foo` error[E0277]: the trait bound `u32: Unsatisfied` is not satisfied --> $DIR/wf-foreign-fn-decl-ret.rs:14:32 diff --git a/src/test/ui/where-clauses/where-clause-method-substituion.stderr b/src/test/ui/where-clauses/where-clause-method-substituion.stderr index cb381d2d9f..f431deee73 100644 --- a/src/test/ui/where-clauses/where-clause-method-substituion.stderr +++ b/src/test/ui/where-clauses/where-clause-method-substituion.stderr @@ -3,6 +3,12 @@ error[E0277]: the trait bound `X: Foo<X>` is not satisfied | LL | 1.method::<X>(); | ^^^^^^ the trait `Foo<X>` is not implemented for `X` + | +note: required by a bound in `Bar::method` + --> $DIR/where-clause-method-substituion.rs:6:34 + | +LL | fn method<B>(&self) where A: Foo<B>; + | ^^^^^^ required by this bound in `Bar::method` error: aborting due to previous error diff --git a/src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr b/src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr index 3223dca3cd..3a4cbb62d5 100644 --- a/src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr +++ b/src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr @@ -5,6 +5,12 @@ LL | x.equals(&x); | ------ ^^ the trait `Eq` is not implemented for `Bar` | | | required by a bound introduced by this call + | +note: required by a bound in `Foo::<T>::equals` + --> $DIR/where-clauses-method-unsatisfied.rs:11:52 + | +LL | fn equals(&self, u: &Foo<T>) -> bool where T : Eq { + | ^^ required by this bound in `Foo::<T>::equals` error: aborting due to previous error diff --git a/src/test/ui/writealias.rs b/src/test/ui/writealias.rs deleted file mode 100644 index 8ba4b09ae2..0000000000 --- a/src/test/ui/writealias.rs +++ /dev/null @@ -1,19 +0,0 @@ -// run-pass - -#![allow(dead_code)] - -use std::sync::Mutex; - -struct Point {x: isize, y: isize, z: isize} - -fn f(p: &mut Point) { p.z = 13; } - -pub fn main() { - let x = Some(Mutex::new(true)); - match x { - Some(ref z) if *z.lock().unwrap() => { - assert!(*z.lock().unwrap()); - }, - _ => panic!() - } -} diff --git a/src/tools/bump-stage0/src/main.rs b/src/tools/bump-stage0/src/main.rs index 96d3c87384..d6364e28fe 100644 --- a/src/tools/bump-stage0/src/main.rs +++ b/src/tools/bump-stage0/src/main.rs @@ -196,7 +196,6 @@ struct ManifestPackage { #[derive(Debug, serde::Deserialize)] struct ManifestTargetPackage { - available: bool, url: Option<String>, hash: Option<String>, xz_url: Option<String>, diff --git a/src/tools/clippy/.cargo/config b/src/tools/clippy/.cargo/config.toml similarity index 100% rename from src/tools/clippy/.cargo/config rename to src/tools/clippy/.cargo/config.toml diff --git a/src/tools/clippy/.github/deploy.sh b/src/tools/clippy/.github/deploy.sh index a3c57232f5..34225a5402 100644 --- a/src/tools/clippy/.github/deploy.sh +++ b/src/tools/clippy/.github/deploy.sh @@ -13,7 +13,8 @@ cp util/gh-pages/lints.json out/master if [[ -n $TAG_NAME ]]; then echo "Save the doc for the current tag ($TAG_NAME) and point stable/ to it" cp -Tr out/master "out/$TAG_NAME" - ln -sf "$TAG_NAME" out/stable + rm -f out/stable + ln -s "$TAG_NAME" out/stable fi if [[ $BETA = "true" ]]; then diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md index dabad5d184..85a6a6be8b 100644 --- a/src/tools/clippy/CHANGELOG.md +++ b/src/tools/clippy/CHANGELOG.md @@ -6,11 +6,162 @@ document. ## Unreleased / In Rust Nightly -[7bfc26e...master](https://github.com/rust-lang/rust-clippy/compare/7bfc26e...master) +[b7f3f7f...master](https://github.com/rust-lang/rust-clippy/compare/b7f3f7f...master) + +## Rust 1.57 + +Current beta, release 2021-12-02 + +[7bfc26e...b7f3f7f](https://github.com/rust-lang/rust-clippy/compare/7bfc26e...b7f3f7f) + +### New Lints + +* [`negative_feature_names`] + [#7539](https://github.com/rust-lang/rust-clippy/pull/7539) +* [`redundant_feature_names`] + [#7539](https://github.com/rust-lang/rust-clippy/pull/7539) +* [`mod_module_files`] + [#7543](https://github.com/rust-lang/rust-clippy/pull/7543) +* [`self_named_module_files`] + [#7543](https://github.com/rust-lang/rust-clippy/pull/7543) +* [`manual_split_once`] + [#7565](https://github.com/rust-lang/rust-clippy/pull/7565) +* [`derivable_impls`] + [#7570](https://github.com/rust-lang/rust-clippy/pull/7570) +* [`needless_option_as_deref`] + [#7596](https://github.com/rust-lang/rust-clippy/pull/7596) +* [`iter_not_returning_iterator`] + [#7610](https://github.com/rust-lang/rust-clippy/pull/7610) +* [`same_name_method`] + [#7653](https://github.com/rust-lang/rust-clippy/pull/7653) +* [`manual_assert`] [#7669](https://github.com/rust-lang/rust-clippy/pull/7669) +* [`non_send_fields_in_send_ty`] + [#7709](https://github.com/rust-lang/rust-clippy/pull/7709) +* [`equatable_if_let`] + [#7762](https://github.com/rust-lang/rust-clippy/pull/7762) + +### Moves and Deprecations + +* Move [`shadow_unrelated`] to `restriction` + [#7338](https://github.com/rust-lang/rust-clippy/pull/7338) +* Move [`option_if_let_else`] to `nursery` + [#7568](https://github.com/rust-lang/rust-clippy/pull/7568) +* Move [`branches_sharing_code`] to `nursery` + [#7595](https://github.com/rust-lang/rust-clippy/pull/7595) +* Rename `if_let_some_result` to [`match_result_ok`] which now also handles + `while let` cases [#7608](https://github.com/rust-lang/rust-clippy/pull/7608) +* Move [`many_single_char_names`] to `pedantic` + [#7671](https://github.com/rust-lang/rust-clippy/pull/7671) +* Move [`float_cmp`] to `pedantic` + [#7692](https://github.com/rust-lang/rust-clippy/pull/7692) +* Rename `box_vec` to [`box_collection`] and lint on more general cases + [#7693](https://github.com/rust-lang/rust-clippy/pull/7693) +* Uplift `invalid_atomic_ordering` to rustc + [rust-lang/rust#84039](https://github.com/rust-lang/rust/pull/84039) + +### Enhancements + +* Rewrite the `shadow*` lints, so that they find a lot more shadows and are not + limited to certain patterns + [#7338](https://github.com/rust-lang/rust-clippy/pull/7338) +* The `avoid-breaking-exported-api` configuration now also works for + [`box_collection`], [`redundant_allocation`], [`rc_buffer`], [`vec_box`], + [`option_option`], [`linkedlist`], [`rc_mutex`] + [#7560](https://github.com/rust-lang/rust-clippy/pull/7560) +* [`unnecessary_unwrap`]: Now also checks for `expect`s + [#7584](https://github.com/rust-lang/rust-clippy/pull/7584) +* [`disallowed_method`]: Allow adding a reason that will be displayed with the + lint message + [#7621](https://github.com/rust-lang/rust-clippy/pull/7621) +* [`approx_constant`]: Now checks the MSRV for `LOG10_2` and `LOG2_10` + [#7629](https://github.com/rust-lang/rust-clippy/pull/7629) +* [`approx_constant`]: Add `TAU` + [#7642](https://github.com/rust-lang/rust-clippy/pull/7642) +* [`needless_borrow`]: Now also lints on needless mutable borrows + [#7657](https://github.com/rust-lang/rust-clippy/pull/7657) +* [`missing_safety_doc`]: Now also lints on unsafe traits + [#7734](https://github.com/rust-lang/rust-clippy/pull/7734) + +### False Positive Fixes + +* [`manual_map`]: No longer lints when the option is borrowed in the match and + also consumed in the arm + [#7531](https://github.com/rust-lang/rust-clippy/pull/7531) +* [`filter_next`]: No longer lints if `filter` method is not the + `Iterator::filter` method + [#7562](https://github.com/rust-lang/rust-clippy/pull/7562) +* [`manual_flatten`]: No longer lints if expression is used after `if let` + [#7566](https://github.com/rust-lang/rust-clippy/pull/7566) +* [`option_if_let_else`]: Multiple fixes + [#7573](https://github.com/rust-lang/rust-clippy/pull/7573) + * `break` and `continue` statements local to the would-be closure are + allowed + * Don't lint in const contexts + * Don't lint when yield expressions are used + * Don't lint when the captures made by the would-be closure conflict with + the other branch + * Don't lint when a field of a local is used when the type could be + potentially moved from + * In some cases, don't lint when scrutinee expression conflicts with the + captures of the would-be closure +* [`redundant_allocation`]: No longer lints on `Box<Box<dyn T>>` which replaces + wide pointers with thin pointers + [#7592](https://github.com/rust-lang/rust-clippy/pull/7592) +* [`bool_assert_comparison`]: No longer lints on types that do not implement the + `Not` trait with `Output = bool` + [#7605](https://github.com/rust-lang/rust-clippy/pull/7605) +* [`mut_range_bound`]: No longer lints on range bound mutations, that are + immediately followed by a `break;` + [#7607](https://github.com/rust-lang/rust-clippy/pull/7607) +* [`mutable_key_type`]: Improve accuracy and document remaining false positives + and false negatives + [#7640](https://github.com/rust-lang/rust-clippy/pull/7640) +* [`redundant_closure`]: Rewrite the lint to fix various false positives and + false negatives [#7661](https://github.com/rust-lang/rust-clippy/pull/7661) +* [`large_enum_variant`]: No longer wrongly identifies the second largest + variant [#7677](https://github.com/rust-lang/rust-clippy/pull/7677) +* [`needless_return`]: No longer lints on let-else expressions + [#7685](https://github.com/rust-lang/rust-clippy/pull/7685) +* [`suspicious_else_formatting`]: No longer lints in proc-macros + [#7707](https://github.com/rust-lang/rust-clippy/pull/7707) +* [`excessive_precision`]: No longer lints when in some cases the float was + already written in the shortest form + [#7722](https://github.com/rust-lang/rust-clippy/pull/7722) +* [`doc_markdown`]: No longer lints on intra-doc links + [#7772](https://github.com/rust-lang/rust-clippy/pull/7772) + +### Suggestion Fixes/Improvements + +* [`unnecessary_operation`]: Recommend using an `assert!` instead of using a + function call in an indexing operation + [#7453](https://github.com/rust-lang/rust-clippy/pull/7453) +* [`manual_split_once`]: Produce semantically equivalent suggestion when + `rsplitn` is used [#7663](https://github.com/rust-lang/rust-clippy/pull/7663) +* [`while_let_on_iterator`]: Produce correct suggestion when using `&mut` + [#7690](https://github.com/rust-lang/rust-clippy/pull/7690) +* [`manual_assert`]: No better handles complex conditions + [#7741](https://github.com/rust-lang/rust-clippy/pull/7741) +* Correctly handle signs in exponents in numeric literals lints + [#7747](https://github.com/rust-lang/rust-clippy/pull/7747) +* [`suspicious_map`]: Now also suggests to use `inspect` as an alternative + [#7770](https://github.com/rust-lang/rust-clippy/pull/7770) +* Drop exponent from suggestion if it is 0 in numeric literals lints + [#7774](https://github.com/rust-lang/rust-clippy/pull/7774) + +### ICE Fixes + +* [`implicit_hasher`] + [#7761](https://github.com/rust-lang/rust-clippy/pull/7761) + +### Others + +* Clippy now uses the 2021 + [Edition!](https://www.youtube.com/watch?v=q0aNduqb2Ro) + [#7664](https://github.com/rust-lang/rust-clippy/pull/7664) ## Rust 1.56 -Current beta, release 2021-10-21 +Current stable, released 2021-10-21 [74d1561...7bfc26e](https://github.com/rust-lang/rust-clippy/compare/74d1561...7bfc26e) @@ -74,13 +225,9 @@ Current beta, release 2021-10-21 * [`unnested_or_patterns`]: Removed `or_patterns` feature gate in the code example [#7507](https://github.com/rust-lang/rust-clippy/pull/7507) -### New Lints - -* Renamed Lint: `if_let_some_result` is now called [`match_result_ok`]. Now also handles `while let` case. - ## Rust 1.55 -Current stable, released 2021-09-09 +Released 2021-09-09 [3ae8faf...74d1561](https://github.com/rust-lang/rust-clippy/compare/3ae8faf...74d1561) @@ -2730,11 +2877,13 @@ Released 2018-09-13 [`fn_address_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_address_comparisons [`fn_params_excessive_bools`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_params_excessive_bools [`fn_to_numeric_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast +[`fn_to_numeric_cast_any`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast_any [`fn_to_numeric_cast_with_truncation`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast_with_truncation [`for_kv_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_kv_map [`for_loops_over_fallibles`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_loops_over_fallibles [`forget_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_copy [`forget_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_ref +[`format_in_format_args`]: https://rust-lang.github.io/rust-clippy/master/index.html#format_in_format_args [`from_iter_instead_of_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#from_iter_instead_of_collect [`from_over_into`]: https://rust-lang.github.io/rust-clippy/master/index.html#from_over_into [`from_str_radix_10`]: https://rust-lang.github.io/rust-clippy/master/index.html#from_str_radix_10 @@ -2836,6 +2985,7 @@ Released 2018-09-13 [`match_result_ok`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_result_ok [`match_same_arms`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_same_arms [`match_single_binding`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_single_binding +[`match_str_case_mismatch`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_str_case_mismatch [`match_wild_err_arm`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_wild_err_arm [`match_wildcard_for_single_variants`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_wildcard_for_single_variants [`maybe_infinite_iter`]: https://rust-lang.github.io/rust-clippy/master/index.html#maybe_infinite_iter @@ -2896,6 +3046,7 @@ Released 2018-09-13 [`new_ret_no_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#new_ret_no_self [`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 +[`no_effect_underscore_binding`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_effect_underscore_binding [`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 [`non_send_fields_in_send_ty`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_send_fields_in_send_ty @@ -2972,6 +3123,7 @@ Released 2018-09-13 [`self_named_constructors`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_named_constructors [`self_named_module_files`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_named_module_files [`semicolon_if_nothing_returned`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned +[`separated_literal_suffix`]: https://rust-lang.github.io/rust-clippy/master/index.html#separated_literal_suffix [`serde_api_misuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#serde_api_misuse [`shadow_reuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#shadow_reuse [`shadow_same`]: https://rust-lang.github.io/rust-clippy/master/index.html#shadow_same @@ -2996,6 +3148,7 @@ Released 2018-09-13 [`string_extend_chars`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_extend_chars [`string_from_utf8_as_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_from_utf8_as_bytes [`string_lit_as_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_lit_as_bytes +[`string_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_slice [`string_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_to_string [`strlen_on_c_strings`]: https://rust-lang.github.io/rust-clippy/master/index.html#strlen_on_c_strings [`struct_excessive_bools`]: https://rust-lang.github.io/rust-clippy/master/index.html#struct_excessive_bools @@ -3012,16 +3165,19 @@ Released 2018-09-13 [`temporary_assignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_assignment [`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 +[`to_string_in_format_args`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_string_in_format_args [`todo`]: https://rust-lang.github.io/rust-clippy/master/index.html#todo [`too_many_arguments`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments [`too_many_lines`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines [`toplevel_ref_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#toplevel_ref_arg +[`trailing_empty_array`]: https://rust-lang.github.io/rust-clippy/master/index.html#trailing_empty_array [`trait_duplication_in_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#trait_duplication_in_bounds [`transmute_bytes_to_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_bytes_to_str [`transmute_float_to_int`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_float_to_int [`transmute_int_to_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_bool [`transmute_int_to_char`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_char [`transmute_int_to_float`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_float +[`transmute_num_to_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_num_to_bytes [`transmute_ptr_to_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ptr [`transmute_ptr_to_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ref [`transmutes_expressible_as_ptr_casts`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmutes_expressible_as_ptr_casts @@ -3031,12 +3187,15 @@ Released 2018-09-13 [`try_err`]: https://rust-lang.github.io/rust-clippy/master/index.html#try_err [`type_complexity`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity [`type_repetition_in_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds +[`undocumented_unsafe_blocks`]: https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks [`undropped_manually_drops`]: https://rust-lang.github.io/rust-clippy/master/index.html#undropped_manually_drops [`unicode_not_nfc`]: https://rust-lang.github.io/rust-clippy/master/index.html#unicode_not_nfc [`unimplemented`]: https://rust-lang.github.io/rust-clippy/master/index.html#unimplemented [`uninit_assumed_init`]: https://rust-lang.github.io/rust-clippy/master/index.html#uninit_assumed_init +[`uninit_vec`]: https://rust-lang.github.io/rust-clippy/master/index.html#uninit_vec [`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_hash`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_hash [`unit_return_expecting_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_return_expecting_ord [`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 diff --git a/src/tools/clippy/CONTRIBUTING.md b/src/tools/clippy/CONTRIBUTING.md index 4273fda4e6..97ff31b4bc 100644 --- a/src/tools/clippy/CONTRIBUTING.md +++ b/src/tools/clippy/CONTRIBUTING.md @@ -262,7 +262,9 @@ to be run inside the `rust` directory): 2. Checkout the commit from the latest available nightly. You can get it using `rustup check`. 3. Sync the changes to the rust-copy of Clippy to your Clippy fork: ```bash - # Make sure to change `your-github-name` to your github name in the following command + # Make sure to change `your-github-name` to your github name in the following command. Also be + # sure to either use a net-new branch, e.g. `sync-from-rust`, or delete the branch beforehand + # because changes cannot be fast forwarded git subtree push -P src/tools/clippy git@github.com:your-github-name/rust-clippy sync-from-rust ``` diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml index ba3ed3053a..602877bb9d 100644 --- a/src/tools/clippy/Cargo.toml +++ b/src/tools/clippy/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.1.57" +version = "0.1.58" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" @@ -22,13 +22,13 @@ path = "src/driver.rs" [dependencies] clippy_lints = { version = "0.1", path = "clippy_lints" } -semver = "0.11" +semver = "1.0" rustc_tools_util = { version = "0.2", path = "rustc_tools_util" } tempfile = { version = "3.2", optional = true } [dev-dependencies] -cargo_metadata = "0.12" -compiletest_rs = { version = "0.7", features = ["tmp"] } +cargo_metadata = "0.14" +compiletest_rs = { version = "0.7.1", features = ["tmp"] } tester = "0.9" regex = "1.5" # This is used by the `collect-metadata` alias. diff --git a/src/tools/clippy/clippy_dev/Cargo.toml b/src/tools/clippy/clippy_dev/Cargo.toml index 4a13a45240..affb283017 100644 --- a/src/tools/clippy/clippy_dev/Cargo.toml +++ b/src/tools/clippy/clippy_dev/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] bytecount = "0.6" clap = "2.33" +indoc = "1.0" itertools = "0.10" opener = "0.5" regex = "1.5" diff --git a/src/tools/clippy/clippy_dev/src/main.rs b/src/tools/clippy/clippy_dev/src/main.rs index 8fdeba9842..b5c04efce3 100644 --- a/src/tools/clippy/clippy_dev/src/main.rs +++ b/src/tools/clippy/clippy_dev/src/main.rs @@ -28,6 +28,7 @@ fn main() { matches.value_of("pass"), matches.value_of("name"), matches.value_of("category"), + matches.is_present("msrv"), ) { Ok(_) => update_lints::run(update_lints::UpdateMode::Change), Err(e) => eprintln!("Unable to create lint: {}", e), @@ -147,6 +148,11 @@ fn get_clap_config<'a>() -> ArgMatches<'a> { "internal_warn", ]) .takes_value(true), + ) + .arg( + Arg::with_name("msrv") + .long("msrv") + .help("Add MSRV config code to the lint"), ), ) .subcommand( diff --git a/src/tools/clippy/clippy_dev/src/new_lint.rs b/src/tools/clippy/clippy_dev/src/new_lint.rs index 3a81aaba6d..43a478ee77 100644 --- a/src/tools/clippy/clippy_dev/src/new_lint.rs +++ b/src/tools/clippy/clippy_dev/src/new_lint.rs @@ -1,4 +1,5 @@ use crate::clippy_project_root; +use indoc::indoc; use std::fs::{self, OpenOptions}; use std::io::prelude::*; use std::io::{self, ErrorKind}; @@ -32,7 +33,7 @@ impl<T> Context for io::Result<T> { /// # Errors /// /// This function errors out if the files couldn't be created or written to. -pub fn create(pass: Option<&str>, lint_name: Option<&str>, category: Option<&str>) -> io::Result<()> { +pub fn create(pass: Option<&str>, lint_name: Option<&str>, category: Option<&str>, msrv: bool) -> io::Result<()> { let lint = LintData { pass: pass.expect("`pass` argument is validated by clap"), name: lint_name.expect("`name` argument is validated by clap"), @@ -40,29 +41,13 @@ pub fn create(pass: Option<&str>, lint_name: Option<&str>, category: Option<&str project_root: clippy_project_root(), }; - create_lint(&lint).context("Unable to create lint implementation")?; - create_test(&lint).context("Unable to create a test for the new lint") + create_lint(&lint, msrv).context("Unable to create lint implementation")?; + create_test(&lint).context("Unable to create a test for the new lint")?; + add_lint(&lint, msrv).context("Unable to add lint to clippy_lints/src/lib.rs") } -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"), - _ => { - unreachable!("`pass_type` should only ever be `early` or `late`!"); - }, - }; - - let camel_case_name = to_camel_case(lint.name); - let lint_contents = get_lint_file_contents( - pass_type, - pass_lifetimes, - lint.name, - &camel_case_name, - lint.category, - pass_import, - context_import, - ); +fn create_lint(lint: &LintData<'_>, enable_msrv: bool) -> io::Result<()> { + let lint_contents = get_lint_file_contents(lint, enable_msrv); let lint_path = format!("clippy_lints/src/{}.rs", lint.name); write_file(lint.project_root.join(&lint_path), lint_contents.as_bytes()) @@ -96,6 +81,33 @@ fn create_test(lint: &LintData<'_>) -> io::Result<()> { } } +fn add_lint(lint: &LintData<'_>, enable_msrv: bool) -> io::Result<()> { + let path = "clippy_lints/src/lib.rs"; + let mut lib_rs = fs::read_to_string(path).context("reading")?; + + let comment_start = lib_rs.find("// add lints here,").expect("Couldn't find comment"); + + let new_lint = if enable_msrv { + format!( + "store.register_{lint_pass}_pass(move || Box::new({module_name}::{camel_name}::new(msrv)));\n ", + lint_pass = lint.pass, + module_name = lint.name, + camel_name = to_camel_case(lint.name), + ) + } else { + format!( + "store.register_{lint_pass}_pass(|| Box::new({module_name}::{camel_name}));\n ", + lint_pass = lint.pass, + module_name = lint.name, + camel_name = to_camel_case(lint.name), + ) + }; + + lib_rs.insert_str(comment_start, &new_lint); + + fs::write(path, lib_rs).context("writing") +} + fn write_file<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result<()> { fn inner(path: &Path, contents: &[u8]) -> io::Result<()> { OpenOptions::new() @@ -122,12 +134,13 @@ fn to_camel_case(name: &str) -> String { fn get_test_file_contents(lint_name: &str, header_commands: Option<&str>) -> String { let mut contents = format!( - "#![warn(clippy::{})] + indoc! {" + #![warn(clippy::{})] -fn main() {{ - // test code goes here -}} -", + fn main() {{ + // test code goes here + }} + "}, lint_name ); @@ -140,64 +153,133 @@ fn main() {{ fn get_manifest_contents(lint_name: &str, hint: &str) -> String { format!( - r#" -# {} + indoc! {r#" + # {} -[package] -name = "{}" -version = "0.1.0" -publish = false + [package] + name = "{}" + version = "0.1.0" + publish = false -[workspace] -"#, + [workspace] + "#}, hint, lint_name ) } -fn get_lint_file_contents( - pass_type: &str, - pass_lifetimes: &str, - lint_name: &str, - camel_case_name: &str, - category: &str, - pass_import: &str, - context_import: &str, -) -> String { - format!( - "use rustc_lint::{{{type}, {context_import}}}; -use rustc_session::{{declare_lint_pass, declare_tool_lint}}; -{pass_import} - -declare_clippy_lint! {{ - /// ### What it does - /// - /// ### Why is this bad? - /// - /// ### Example - /// ```rust - /// // example code where clippy issues a warning - /// ``` - /// Use instead: - /// ```rust - /// // example code which does not raise clippy warning - /// ``` - pub {name_upper}, - {category}, - \"default lint description\" -}} - -declare_lint_pass!({name_camel} => [{name_upper}]); - -impl {type}{lifetimes} for {name_camel} {{}} -", - type=pass_type, - lifetimes=pass_lifetimes, - name_upper=lint_name.to_uppercase(), - name_camel=camel_case_name, - category=category, - pass_import=pass_import, - context_import=context_import - ) +fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String { + let mut result = String::new(); + + 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"), + _ => { + unreachable!("`pass_type` should only ever be `early` or `late`!"); + }, + }; + + let lint_name = lint.name; + let category = lint.category; + let name_camel = to_camel_case(lint.name); + let name_upper = lint_name.to_uppercase(); + + result.push_str(&if enable_msrv { + format!( + indoc! {" + use clippy_utils::msrvs; + {pass_import} + use rustc_lint::{{{context_import}, {pass_type}, LintContext}}; + use rustc_semver::RustcVersion; + use rustc_session::{{declare_tool_lint, impl_lint_pass}}; + + "}, + pass_type = pass_type, + pass_import = pass_import, + context_import = context_import, + ) + } else { + format!( + indoc! {" + {pass_import} + use rustc_lint::{{{context_import}, {pass_type}}}; + use rustc_session::{{declare_lint_pass, declare_tool_lint}}; + + "}, + pass_import = pass_import, + pass_type = pass_type, + context_import = context_import + ) + }); + + result.push_str(&format!( + indoc! {" + declare_clippy_lint! {{ + /// ### What it does + /// + /// ### Why is this bad? + /// + /// ### Example + /// ```rust + /// // example code where clippy issues a warning + /// ``` + /// Use instead: + /// ```rust + /// // example code which does not raise clippy warning + /// ``` + pub {name_upper}, + {category}, + \"default lint description\" + }} + "}, + name_upper = name_upper, + category = category, + )); + + result.push_str(&if enable_msrv { + format!( + indoc! {" + pub struct {name_camel} {{ + msrv: Option<RustcVersion>, + }} + + impl {name_camel} {{ + #[must_use] + pub fn new(msrv: Option<RustcVersion>) -> Self {{ + Self {{ msrv }} + }} + }} + + impl_lint_pass!({name_camel} => [{name_upper}]); + + impl {pass_type}{pass_lifetimes} for {name_camel} {{ + extract_msrv_attr!({context_import}); + }} + + // TODO: Add MSRV level to `clippy_utils/src/msrvs.rs` if needed. + // TODO: Add MSRV test to `tests/ui/min_rust_version_attr.rs`. + // TODO: Update msrv config comment in `clippy_lints/src/utils/conf.rs` + "}, + pass_type = pass_type, + pass_lifetimes = pass_lifetimes, + name_upper = name_upper, + name_camel = name_camel, + context_import = context_import, + ) + } else { + format!( + indoc! {" + declare_lint_pass!({name_camel} => [{name_upper}]); + + impl {pass_type}{pass_lifetimes} for {name_camel} {{}} + "}, + pass_type = pass_type, + pass_lifetimes = pass_lifetimes, + name_upper = name_upper, + name_camel = name_camel, + ) + }); + + result } #[test] diff --git a/src/tools/clippy/clippy_dev/src/update_lints.rs b/src/tools/clippy/clippy_dev/src/update_lints.rs index 10d859988f..23f58bc491 100644 --- a/src/tools/clippy/clippy_dev/src/update_lints.rs +++ b/src/tools/clippy/clippy_dev/src/update_lints.rs @@ -619,8 +619,8 @@ mod tests { Lint::new("should_assert_eq2", "group2", "abc", None, "module_name"), ]; let expected = vec![ - format!("[`should_assert_eq`]: {}#should_assert_eq", DOCS_LINK.to_string()), - format!("[`should_assert_eq2`]: {}#should_assert_eq2", DOCS_LINK.to_string()), + format!("[`should_assert_eq`]: {}#should_assert_eq", DOCS_LINK), + format!("[`should_assert_eq2`]: {}#should_assert_eq2", DOCS_LINK), ]; assert_eq!(expected, gen_changelog_lint_list(lints.iter())); } diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml index 7900dc6d04..281480b8d9 100644 --- a/src/tools/clippy/clippy_lints/Cargo.toml +++ b/src/tools/clippy/clippy_lints/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_lints" -version = "0.1.57" +version = "0.1.58" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" @@ -9,7 +9,7 @@ keywords = ["clippy", "lint", "plugin"] edition = "2021" [dependencies] -cargo_metadata = "0.12" +cargo_metadata = "0.14" clippy_utils = { path = "../clippy_utils" } if_chain = "1.0" itertools = "0.10" @@ -21,7 +21,7 @@ serde_json = { version = "1.0", optional = true } toml = "0.5" unicode-normalization = "0.1" unicode-script = { version = "0.5", default-features = false } -semver = "0.11" +semver = "1.0" rustc-semver = "1.1" # NOTE: cargo requires serde feat in its url dep # see <https://github.com/rust-lang/rust/pull/63587#issuecomment-522343864> 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 833ad122e0..4af412ccaf 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,15 +1,88 @@ +use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::span_lint; +use clippy_utils::expr_or_init; use clippy_utils::ty::is_isize_or_usize; -use rustc_hir::Expr; +use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::LateContext; use rustc_middle::ty::{self, FloatTy, Ty}; use super::{utils, CAST_POSSIBLE_TRUNCATION}; -pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) { +fn constant_int(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<u128> { + if let Some((Constant::Int(c), _)) = constant(cx, cx.typeck_results(), expr) { + Some(c) + } else { + None + } +} + +fn get_constant_bits(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<u64> { + constant_int(cx, expr).map(|c| u64::from(128 - c.leading_zeros())) +} + +fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: bool) -> u64 { + match expr_or_init(cx, expr).kind { + ExprKind::Cast(inner, _) => apply_reductions(cx, nbits, inner, signed), + ExprKind::Block(block, _) => block.expr.map_or(nbits, |e| apply_reductions(cx, nbits, e, signed)), + ExprKind::Binary(op, left, right) => match op.node { + BinOpKind::Div => { + apply_reductions(cx, nbits, left, signed) + - (if signed { + 0 // let's be conservative here + } else { + // by dividing by 1, we remove 0 bits, etc. + get_constant_bits(cx, right).map_or(0, |b| b.saturating_sub(1)) + }) + }, + BinOpKind::Rem | BinOpKind::BitAnd => get_constant_bits(cx, right) + .unwrap_or(u64::max_value()) + .min(apply_reductions(cx, nbits, left, signed)), + BinOpKind::Shr => { + apply_reductions(cx, nbits, left, signed) + - constant_int(cx, right).map_or(0, |s| u64::try_from(s).expect("shift too high")) + }, + _ => nbits, + }, + ExprKind::MethodCall(method, _, [left, right], _) => { + if signed { + return nbits; + } + let max_bits = if method.ident.as_str() == "min" { + get_constant_bits(cx, right) + } else { + None + }; + apply_reductions(cx, nbits, left, signed).min(max_bits.unwrap_or(u64::max_value())) + }, + ExprKind::MethodCall(method, _, [_, lo, hi], _) => { + if method.ident.as_str() == "clamp" { + //FIXME: make this a diagnostic item + if let (Some(lo_bits), Some(hi_bits)) = (get_constant_bits(cx, lo), get_constant_bits(cx, hi)) { + return lo_bits.max(hi_bits); + } + } + nbits + }, + ExprKind::MethodCall(method, _, [_value], _) => { + if method.ident.name.as_str() == "signum" { + 0 // do not lint if cast comes from a `signum` function + } else { + nbits + } + }, + _ => nbits, + } +} + +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) { let msg = match (cast_from.is_integral(), cast_to.is_integral()) { (true, true) => { - let from_nbits = utils::int_ty_to_nbits(cast_from, cx.tcx); + let from_nbits = apply_reductions( + cx, + utils::int_ty_to_nbits(cast_from, cx.tcx), + cast_expr, + cast_from.is_signed(), + ); let to_nbits = utils::int_ty_to_nbits(cast_to, cx.tcx); let (should_lint, suffix) = match (is_isize_or_usize(cast_from), is_isize_or_usize(cast_to)) { diff --git a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_any.rs b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_any.rs new file mode 100644 index 0000000000..03621887a3 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_any.rs @@ -0,0 +1,34 @@ +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 super::FN_TO_NUMERIC_CAST_ANY; + +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) { + // We allow casts from any function type to any function type. + match cast_to.kind() { + ty::FnDef(..) | ty::FnPtr(..) => return, + _ => { /* continue to checks */ }, + } + + match cast_from.kind() { + ty::FnDef(..) | ty::FnPtr(_) => { + let mut applicability = Applicability::MaybeIncorrect; + let from_snippet = snippet_with_applicability(cx, cast_expr.span, "..", &mut applicability); + + span_lint_and_sugg( + cx, + FN_TO_NUMERIC_CAST_ANY, + expr.span, + &format!("casting function pointer `{}` to `{}`", from_snippet, cast_to), + "did you mean to invoke the function?", + format!("{}() as {}", from_snippet, cast_to), + applicability, + ); + }, + _ => {}, + } +} diff --git a/src/tools/clippy/clippy_lints/src/casts/mod.rs b/src/tools/clippy/clippy_lints/src/casts/mod.rs index 27e1bea799..233abd1789 100644 --- a/src/tools/clippy/clippy_lints/src/casts/mod.rs +++ b/src/tools/clippy/clippy_lints/src/casts/mod.rs @@ -7,6 +7,7 @@ mod cast_ref_to_mut; mod cast_sign_loss; mod char_lit_as_u8; mod fn_to_numeric_cast; +mod fn_to_numeric_cast_any; mod fn_to_numeric_cast_with_truncation; mod ptr_as_ptr; mod unnecessary_cast; @@ -251,6 +252,42 @@ declare_clippy_lint! { "casting a function pointer to a numeric type not wide enough to store the address" } +declare_clippy_lint! { + /// ### What it does + /// Checks for casts of a function pointer to any integer type. + /// + /// ### Why is this bad? + /// Casting a function pointer to an integer can have surprising results and can occur + /// accidentally if parantheses are omitted from a function call. If you aren't doing anything + /// low-level with function pointers then you can opt-out of casting functions to integers in + /// order to avoid mistakes. Alternatively, you can use this lint to audit all uses of function + /// pointer casts in your code. + /// + /// ### Example + /// ```rust + /// // Bad: fn1 is cast as `usize` + /// fn fn1() -> u16 { + /// 1 + /// }; + /// let _ = fn1 as usize; + /// + /// // Good: maybe you intended to call the function? + /// fn fn2() -> u16 { + /// 1 + /// }; + /// let _ = fn2() as usize; + /// + /// // Good: maybe you intended to cast it to a function type? + /// fn fn3() -> u16 { + /// 1 + /// } + /// let _ = fn3 as fn() -> u16; + /// ``` + pub FN_TO_NUMERIC_CAST_ANY, + restriction, + "casting a function pointer to any integer type" +} + declare_clippy_lint! { /// ### What it does /// Checks for casts of `&T` to `&mut T` anywhere in the code. @@ -360,6 +397,7 @@ impl_lint_pass!(Casts => [ CAST_REF_TO_MUT, CAST_PTR_ALIGNMENT, UNNECESSARY_CAST, + FN_TO_NUMERIC_CAST_ANY, FN_TO_NUMERIC_CAST, FN_TO_NUMERIC_CAST_WITH_TRUNCATION, CHAR_LIT_AS_U8, @@ -385,10 +423,11 @@ impl<'tcx> LateLintPass<'tcx> for Casts { return; } + fn_to_numeric_cast_any::check(cx, expr, cast_expr, cast_from, cast_to); fn_to_numeric_cast::check(cx, expr, cast_expr, cast_from, cast_to); fn_to_numeric_cast_with_truncation::check(cx, expr, cast_expr, cast_from, cast_to); if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx.sess(), expr.span) { - cast_possible_truncation::check(cx, expr, cast_from, cast_to); + cast_possible_truncation::check(cx, expr, cast_expr, cast_from, cast_to); cast_possible_wrap::check(cx, expr, cast_from, cast_to); cast_precision_loss::check(cx, expr, cast_from, cast_to); cast_lossless::check(cx, expr, cast_expr, cast_from, cast_to); diff --git a/src/tools/clippy/clippy_lints/src/copies.rs b/src/tools/clippy/clippy_lints/src/copies.rs index b7385dcfbc..8abf10c0d1 100644 --- a/src/tools/clippy/clippy_lints/src/copies.rs +++ b/src/tools/clippy/clippy_lints/src/copies.rs @@ -459,12 +459,10 @@ fn emit_branches_sharing_code_lint( } else { sm.stmt_span(block.stmts[block.stmts.len() - end_stmts].span, block.span) }; - let moved_end = block - .expr - .map_or_else( - || sm.stmt_span(block.stmts[block.stmts.len() - 1].span, block.span), - |expr| expr.span.source_callsite(), - ); + let moved_end = block.expr.map_or_else( + || sm.stmt_span(block.stmts[block.stmts.len() - 1].span, block.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); diff --git a/src/tools/clippy/clippy_lints/src/default.rs b/src/tools/clippy/clippy_lints/src/default.rs index db8f217134..cde27d3ad2 100644 --- a/src/tools/clippy/clippy_lints/src/default.rs +++ b/src/tools/clippy/clippy_lints/src/default.rs @@ -1,5 +1,6 @@ use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg}; use clippy_utils::source::snippet_with_macro_callsite; +use clippy_utils::ty::{has_drop, is_copy}; use clippy_utils::{any_parent_is_automatically_derived, contains_name, in_macro, match_def_path, paths}; use if_chain::if_chain; use rustc_data_structures::fx::FxHashSet; @@ -139,6 +140,13 @@ impl LateLintPass<'_> for Default { .fields .iter() .all(|field| field.vis.is_accessible_from(module_did, cx.tcx)); + let all_fields_are_copy = variant + .fields + .iter() + .all(|field| { + is_copy(cx, cx.tcx.type_of(field.did)) + }); + if !has_drop(cx, binding_type) || all_fields_are_copy; then { (local, variant, ident.name, binding_type, expr.span) } else { diff --git a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs index c604516742..9d8524ec91 100644 --- a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs +++ b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs @@ -1,3 +1,6 @@ +// NOTE: if you add a deprecated lint in this file, please add a corresponding test in +// tests/ui/deprecated.rs + /// This struct fakes the `Lint` declaration that is usually created by `declare_lint!`. This /// enables the simple extraction of the metadata without changing the current deprecation /// declaration. diff --git a/src/tools/clippy/clippy_lints/src/disallowed_type.rs b/src/tools/clippy/clippy_lints/src/disallowed_type.rs index 87124f093a..48f781516f 100644 --- a/src/tools/clippy/clippy_lints/src/disallowed_type.rs +++ b/src/tools/clippy/clippy_lints/src/disallowed_type.rs @@ -1,12 +1,14 @@ -use clippy_utils::diagnostics::span_lint; +use clippy_utils::diagnostics::span_lint_and_then; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::FxHashMap; use rustc_hir::{ def::Res, def_id::DefId, Item, ItemKind, PolyTraitRef, PrimTy, TraitBoundModifier, Ty, TyKind, UseKind, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::{Span, Symbol}; +use rustc_span::Span; + +use crate::utils::conf; declare_clippy_lint! { /// ### What it does @@ -19,7 +21,15 @@ declare_clippy_lint! { /// An example clippy.toml configuration: /// ```toml /// # clippy.toml - /// disallowed-types = ["std::collections::BTreeMap"] + /// disallowed-types = [ + /// # Can use a string as the path of the disallowed type. + /// "std::collections::BTreeMap", + /// # Can also use an inline table with a `path` key. + /// { path = "std::net::TcpListener" }, + /// # When using an inline table, can add a `reason` for why the type + /// # is disallowed. + /// { path = "std::net::Ipv4Addr", reason = "no IPv4 allowed" }, + /// ] /// ``` /// /// ```rust,ignore @@ -38,33 +48,30 @@ declare_clippy_lint! { } #[derive(Clone, Debug)] pub struct DisallowedType { - disallowed: FxHashSet<Vec<Symbol>>, - def_ids: FxHashSet<DefId>, - prim_tys: FxHashSet<PrimTy>, + conf_disallowed: Vec<conf::DisallowedType>, + def_ids: FxHashMap<DefId, Option<String>>, + prim_tys: FxHashMap<PrimTy, Option<String>>, } impl DisallowedType { - pub fn new(disallowed: &FxHashSet<String>) -> Self { + pub fn new(conf_disallowed: Vec<conf::DisallowedType>) -> Self { Self { - disallowed: disallowed - .iter() - .map(|s| s.split("::").map(Symbol::intern).collect::<Vec<_>>()) - .collect(), - def_ids: FxHashSet::default(), - prim_tys: FxHashSet::default(), + conf_disallowed, + def_ids: FxHashMap::default(), + prim_tys: FxHashMap::default(), } } fn check_res_emit(&self, cx: &LateContext<'_>, res: &Res, span: Span) { match res { Res::Def(_, did) => { - if self.def_ids.contains(did) { - emit(cx, &cx.tcx.def_path_str(*did), span); + if let Some(reason) = self.def_ids.get(did) { + emit(cx, &cx.tcx.def_path_str(*did), span, reason.as_deref()); } }, Res::PrimTy(prim) => { - if self.prim_tys.contains(prim) { - emit(cx, prim.name_str(), span); + if let Some(reason) = self.prim_tys.get(prim) { + emit(cx, prim.name_str(), span, reason.as_deref()); } }, _ => {}, @@ -76,14 +83,21 @@ impl_lint_pass!(DisallowedType => [DISALLOWED_TYPE]); impl<'tcx> LateLintPass<'tcx> for DisallowedType { fn check_crate(&mut self, cx: &LateContext<'_>) { - for path in &self.disallowed { - let segs = path.iter().map(ToString::to_string).collect::<Vec<_>>(); - match clippy_utils::path_to_res(cx, &segs.iter().map(String::as_str).collect::<Vec<_>>()) { + for conf in &self.conf_disallowed { + let (path, reason) = match conf { + conf::DisallowedType::Simple(path) => (path, None), + conf::DisallowedType::WithReason { path, reason } => ( + path, + reason.as_ref().map(|reason| format!("{} (from clippy.toml)", reason)), + ), + }; + let segs: Vec<_> = path.split("::").collect(); + match clippy_utils::path_to_res(cx, &segs) { Res::Def(_, id) => { - self.def_ids.insert(id); + self.def_ids.insert(id, reason); }, Res::PrimTy(ty) => { - self.prim_tys.insert(ty); + self.prim_tys.insert(ty, reason); }, _ => {}, } @@ -107,11 +121,16 @@ impl<'tcx> LateLintPass<'tcx> for DisallowedType { } } -fn emit(cx: &LateContext<'_>, name: &str, span: Span) { - span_lint( +fn emit(cx: &LateContext<'_>, name: &str, span: Span, reason: Option<&str>) { + span_lint_and_then( cx, DISALLOWED_TYPE, span, &format!("`{}` is not allowed according to config", name), + |diag| { + if let Some(reason) = reason { + diag.note(reason); + } + }, ); } diff --git a/src/tools/clippy/clippy_lints/src/doc.rs b/src/tools/clippy/clippy_lints/src/doc.rs index 9840affbf6..d4ba072807 100644 --- a/src/tools/clippy/clippy_lints/src/doc.rs +++ b/src/tools/clippy/clippy_lints/src/doc.rs @@ -1,15 +1,16 @@ -use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_note}; -use clippy_utils::source::first_line_of_span; +use clippy_utils::attrs::is_doc_hidden; +use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_note, span_lint_and_sugg}; +use clippy_utils::source::{first_line_of_span, snippet_with_applicability}; 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}; +use rustc_ast::ast::{Async, AttrKind, Attribute, Fn, FnRetTy, ItemKind}; use rustc_ast::token::CommentKind; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; use rustc_errors::emitter::EmitterWriter; -use rustc_errors::Handler; +use rustc_errors::{Applicability, Handler}; use rustc_hir as hir; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::{AnonConst, Expr, ExprKind, QPath}; @@ -47,7 +48,7 @@ declare_clippy_lint! { /// content are not linted. /// /// In addition, when writing documentation comments, including `[]` brackets - /// inside a link text would trip the parser. Therfore, documenting link with + /// inside a link text would trip the parser. Therefore, documenting link with /// `[`SmallVec<[T; INLINE_CAPACITY]>`]` and then [`SmallVec<[T; INLINE_CAPACITY]>`]: SmallVec /// would fail. /// @@ -297,6 +298,17 @@ fn lint_for_missing_headers<'tcx>( if !cx.access_levels.is_exported(def_id) { return; // Private functions do not require doc comments } + + // do not lint if any parent has `#[doc(hidden)]` attribute (#7347) + if cx + .tcx + .hir() + .parent_iter(cx.tcx.hir().local_def_id_to_hir_id(def_id)) + .any(|(id, _node)| is_doc_hidden(cx.tcx.hir().attrs(id))) + { + return; + } + if !headers.safety && sig.header.unsafety == hir::Unsafety::Unsafe { span_lint( cx, @@ -566,9 +578,12 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize // text "http://example.com" by pulldown-cmark continue; } - headers.safety |= in_heading && text.trim() == "Safety"; - headers.errors |= in_heading && text.trim() == "Errors"; - headers.panics |= in_heading && text.trim() == "Panics"; + let trimmed_text = text.trim(); + headers.safety |= in_heading && trimmed_text == "Safety"; + headers.safety |= in_heading && trimmed_text == "Implementation safety"; + headers.safety |= in_heading && trimmed_text == "Implementation Safety"; + headers.errors |= in_heading && trimmed_text == "Errors"; + headers.panics |= in_heading && trimmed_text == "Panics"; if in_code { if is_rust { let edition = edition.unwrap_or_else(|| cx.tcx.sess.edition()); @@ -624,7 +639,7 @@ fn check_code(cx: &LateContext<'_>, text: &str, edition: Edition, span: Span) { | ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) => return false, // We found a main function ... - ItemKind::Fn(box FnKind(_, sig, _, Some(block))) if item.ident.name == sym::main => { + ItemKind::Fn(box Fn { sig, body: Some(block), .. }) if item.ident.name == sym::main => { let is_async = matches!(sig.header.asyncness, Async::Yes { .. }); let returns_nothing = match &sig.decl.output { FnRetTy::Default(..) => true, @@ -674,10 +689,18 @@ fn check_text(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, text: &str for word in text.split(|c: char| c.is_whitespace() || c == '\'') { // Trim punctuation as in `some comment (see foo::bar).` // ^^ - // Or even as in `_foo bar_` which is emphasized. - let word = word.trim_matches(|c: char| !c.is_alphanumeric()); + // Or even as in `_foo bar_` which is emphasized. Also preserve `::` as a prefix/suffix. + let mut word = word.trim_matches(|c: char| !c.is_alphanumeric() && c != ':'); - if valid_idents.contains(word) { + // Remove leading or trailing single `:` which may be part of a sentence. + if word.starts_with(':') && !word.starts_with("::") { + word = word.trim_start_matches(':'); + } + if word.ends_with(':') && !word.ends_with("::") { + word = word.trim_end_matches(':'); + } + + if valid_idents.contains(word) || word.chars().all(|c| c == ':') { continue; } @@ -732,17 +755,22 @@ fn check_word(cx: &LateContext<'_>, word: &str, span: Span) { } } - // We assume that mixed-case words are not meant to be put inside bacticks. (Issue #2343) + // We assume that mixed-case words are not meant to be put inside backticks. (Issue #2343) if has_underscore(word) && has_hyphen(word) { return; } if has_underscore(word) || word.contains("::") || is_camel_case(word) { - span_lint( + let mut applicability = Applicability::MachineApplicable; + + span_lint_and_sugg( cx, DOC_MARKDOWN, span, - &format!("you should put `{}` between ticks in the documentation", word), + "item in documentation is missing backticks", + "try", + format!("`{}`", snippet_with_applicability(cx, span, "..", &mut applicability)), + applicability, ); } } @@ -781,9 +809,9 @@ impl<'a, 'tcx> Visitor<'tcx> for FindPanicUnwrap<'a, 'tcx> { // 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(); - if is_type_diagnostic_item(self.cx, reciever_ty, sym::Option) - || is_type_diagnostic_item(self.cx, reciever_ty, sym::Result) + let receiver_ty = self.typeck_results.expr_ty(&arglists[0][0]).peel_refs(); + if is_type_diagnostic_item(self.cx, receiver_ty, sym::Option) + || is_type_diagnostic_item(self.cx, receiver_ty, sym::Result) { self.panic_span = Some(expr.span); } diff --git a/src/tools/clippy/clippy_lints/src/enum_variants.rs b/src/tools/clippy/clippy_lints/src/enum_variants.rs index 174260fabd..404b67c8f2 100644 --- a/src/tools/clippy/clippy_lints/src/enum_variants.rs +++ b/src/tools/clippy/clippy_lints/src/enum_variants.rs @@ -1,8 +1,8 @@ //! lint on enum variants that are prefixed or suffixed by the same characters -use clippy_utils::camel_case; use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; use clippy_utils::source::is_present_in_source; +use clippy_utils::str_utils::{self, count_match_end, count_match_start}; use rustc_hir::{EnumDef, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; @@ -117,26 +117,6 @@ impl_lint_pass!(EnumVariantNames => [ MODULE_INCEPTION ]); -/// Returns the number of chars that match from the start -#[must_use] -fn partial_match(pre: &str, name: &str) -> usize { - let mut name_iter = name.chars(); - let _ = name_iter.next_back(); // make sure the name is never fully matched - pre.chars().zip(name_iter).take_while(|&(l, r)| l == r).count() -} - -/// Returns the number of chars that match from the end -#[must_use] -fn partial_rmatch(post: &str, name: &str) -> usize { - let mut name_iter = name.chars(); - let _ = name_iter.next(); // make sure the name is never fully matched - post.chars() - .rev() - .zip(name_iter.rev()) - .take_while(|&(l, r)| l == r) - .count() -} - fn check_variant( cx: &LateContext<'_>, threshold: u64, @@ -150,7 +130,7 @@ fn check_variant( } for var in def.variants { let name = var.ident.name.as_str(); - if partial_match(item_name, &name) == item_name_chars + if count_match_start(item_name, &name).char_count == item_name_chars && name.chars().nth(item_name_chars).map_or(false, |c| !c.is_lowercase()) && name.chars().nth(item_name_chars + 1).map_or(false, |c| !c.is_numeric()) { @@ -161,7 +141,7 @@ fn check_variant( "variant name starts with the enum's name", ); } - if partial_rmatch(item_name, &name) == item_name_chars { + if count_match_end(item_name, &name).char_count == item_name_chars { span_lint( cx, ENUM_VARIANT_NAMES, @@ -171,14 +151,14 @@ fn check_variant( } } let first = &def.variants[0].ident.name.as_str(); - let mut pre = &first[..camel_case::until(&*first)]; - let mut post = &first[camel_case::from(&*first)..]; + let mut pre = &first[..str_utils::camel_case_until(&*first).byte_index]; + let mut post = &first[str_utils::camel_case_start(&*first).byte_index..]; for var in def.variants { let name = var.ident.name.as_str(); - let pre_match = partial_match(pre, &name); + let pre_match = count_match_start(pre, &name).byte_count; pre = &pre[..pre_match]; - let pre_camel = camel_case::until(pre); + let pre_camel = str_utils::camel_case_until(pre).byte_index; pre = &pre[..pre_camel]; while let Some((next, last)) = name[pre.len()..].chars().zip(pre.chars().rev()).next() { if next.is_numeric() { @@ -186,18 +166,18 @@ fn check_variant( } if next.is_lowercase() { let last = pre.len() - last.len_utf8(); - let last_camel = camel_case::until(&pre[..last]); - pre = &pre[..last_camel]; + let last_camel = str_utils::camel_case_until(&pre[..last]); + pre = &pre[..last_camel.byte_index]; } else { break; } } - let post_match = partial_rmatch(post, &name); - let post_end = post.len() - post_match; + let post_match = count_match_end(post, &name); + let post_end = post.len() - post_match.byte_count; post = &post[post_end..]; - let post_camel = camel_case::from(post); - post = &post[post_camel..]; + let post_camel = str_utils::camel_case_start(post); + post = &post[post_camel.byte_index..]; } let (what, value) = match (pre.is_empty(), post.is_empty()) { (true, true) => return, @@ -266,14 +246,16 @@ impl LateLintPass<'_> for EnumVariantNames { ); } } - if item.vis.node.is_pub() { - let matching = partial_match(mod_camel, &item_camel); - let rmatching = partial_rmatch(mod_camel, &item_camel); + // The `module_name_repetitions` lint should only trigger if the item has the module in its + // name. Having the same name is accepted. + if item.vis.node.is_pub() && item_camel.len() > mod_camel.len() { + let matching = count_match_start(mod_camel, &item_camel); + let rmatching = count_match_end(mod_camel, &item_camel); let nchars = mod_camel.chars().count(); let is_word_beginning = |c: char| c == '_' || c.is_uppercase() || c.is_numeric(); - if matching == nchars { + if matching.char_count == nchars { match item_camel.chars().nth(nchars) { Some(c) if is_word_beginning(c) => span_lint( cx, @@ -284,7 +266,7 @@ impl LateLintPass<'_> for EnumVariantNames { _ => (), } } - if rmatching == nchars { + if rmatching.char_count == nchars { span_lint( cx, MODULE_NAME_REPETITIONS, diff --git a/src/tools/clippy/clippy_lints/src/eq_op.rs b/src/tools/clippy/clippy_lints/src/eq_op.rs index 51d5094e8c..655560afd4 100644 --- a/src/tools/clippy/clippy_lints/src/eq_op.rs +++ b/src/tools/clippy/clippy_lints/src/eq_op.rs @@ -1,7 +1,9 @@ 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 clippy_utils::{ + ast_utils::is_useless_with_eq_exprs, eq_expr_value, higher, in_macro, is_expn_of, is_in_test_function, +}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, StmtKind}; @@ -81,7 +83,7 @@ impl<'tcx> LateLintPass<'tcx> for EqOp { if macro_args.len() == 2; let (lhs, rhs) = (macro_args[0], macro_args[1]); if eq_expr_value(cx, lhs, rhs); - + if !is_in_test_function(cx.tcx, e.hir_id); then { span_lint( cx, @@ -108,7 +110,10 @@ impl<'tcx> LateLintPass<'tcx> for EqOp { if macro_with_not_op(&left.kind) || macro_with_not_op(&right.kind) { return; } - if is_useless_with_eq_exprs(op.node.into()) && eq_expr_value(cx, left, right) { + if is_useless_with_eq_exprs(op.node.into()) + && eq_expr_value(cx, left, right) + && !is_in_test_function(cx.tcx, e.hir_id) + { span_lint( cx, EQ_OP, diff --git a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs index 0c6ba91c94..e8b1d6f6ed 100644 --- a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs +++ b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet_with_applicability; +use clippy_utils::source::snippet_with_context; use clippy_utils::ty::implements_trait; use if_chain::if_chain; use rustc_errors::Applicability; @@ -77,9 +77,9 @@ impl<'tcx> LateLintPass<'tcx> for PatternEquality { let pat_str = match pat.kind { PatKind::Struct(..) => format!( "({})", - snippet_with_applicability(cx, pat.span, "..", &mut applicability), + snippet_with_context(cx, pat.span, expr.span.ctxt(), "..", &mut applicability).0, ), - _ => snippet_with_applicability(cx, pat.span, "..", &mut applicability).to_string(), + _ => snippet_with_context(cx, pat.span, expr.span.ctxt(), "..", &mut applicability).0.to_string(), }; span_lint_and_sugg( cx, @@ -89,7 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for PatternEquality { "try", format!( "{} == {}", - snippet_with_applicability(cx, exp.span, "..", &mut applicability), + snippet_with_context(cx, exp.span, expr.span.ctxt(), "..", &mut applicability).0, pat_str, ), applicability, diff --git a/src/tools/clippy/clippy_lints/src/excessive_bools.rs b/src/tools/clippy/clippy_lints/src/excessive_bools.rs index 476e6d23f1..09b6e20083 100644 --- a/src/tools/clippy/clippy_lints/src/excessive_bools.rs +++ b/src/tools/clippy/clippy_lints/src/excessive_bools.rs @@ -1,6 +1,6 @@ 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_ast::ast::{AssocItemKind, Extern, Fn, FnSig, Impl, Item, ItemKind, Trait, Ty, TyKind}; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::{sym, Span}; @@ -162,17 +162,17 @@ impl EarlyLintPass for ExcessiveBools { ); } }, - ItemKind::Impl(box ImplKind { + ItemKind::Impl(box Impl { of_trait: None, items, .. }) - | ItemKind::Trait(box TraitKind(.., items)) => { + | ItemKind::Trait(box Trait { items, .. }) => { for item in items { - if let AssocItemKind::Fn(box FnKind(_, fn_sig, _, _)) = &item.kind { - self.check_fn_sig(cx, fn_sig, item.span); + if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind { + self.check_fn_sig(cx, sig, item.span); } } }, - ItemKind::Fn(box FnKind(_, fn_sig, _, _)) => self.check_fn_sig(cx, fn_sig, item.span), + ItemKind::Fn(box Fn { sig, .. }) => self.check_fn_sig(cx, sig, item.span), _ => (), } } diff --git a/src/tools/clippy/clippy_lints/src/format.rs b/src/tools/clippy/clippy_lints/src/format.rs index 37d9ea3bdc..c205346720 100644 --- a/src/tools/clippy/clippy_lints/src/format.rs +++ b/src/tools/clippy/clippy_lints/src/format.rs @@ -1,16 +1,15 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::higher::FormatExpn; -use clippy_utils::last_path_segment; use clippy_utils::source::{snippet_opt, snippet_with_applicability}; use clippy_utils::sugg::Sugg; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::{BorrowKind, Expr, ExprKind, QPath}; +use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::kw; -use rustc_span::{sym, Span}; +use rustc_span::{sym, BytePos, Span}; declare_clippy_lint! { /// ### What it does @@ -50,15 +49,19 @@ impl<'tcx> LateLintPass<'tcx> for UselessFormat { let mut applicability = Applicability::MachineApplicable; if format_args.value_args.is_empty() { - if_chain! { - if let [e] = &*format_args.format_string_parts; - if let ExprKind::Lit(lit) = &e.kind; - if let Some(s_src) = snippet_opt(cx, lit.span); - then { - // Simulate macro expansion, converting {{ and }} to { and }. - let s_expand = s_src.replace("{{", "{").replace("}}", "}"); - let sugg = format!("{}.to_string()", s_expand); - span_useless_format(cx, call_site, sugg, applicability); + if format_args.format_string_parts.is_empty() { + span_useless_format_empty(cx, call_site, "String::new()".to_owned(), applicability); + } else { + if_chain! { + if let [e] = &*format_args.format_string_parts; + if let ExprKind::Lit(lit) = &e.kind; + if let Some(s_src) = snippet_opt(cx, lit.span); + then { + // Simulate macro expansion, converting {{ and }} to { and }. + let s_expand = s_src.replace("{{", "{").replace("}}", "}"); + let sugg = format!("{}.to_string()", s_expand); + span_useless_format(cx, call_site, sugg, applicability); + } } } } else if let [value] = *format_args.value_args { @@ -69,15 +72,30 @@ impl<'tcx> LateLintPass<'tcx> for UselessFormat { ty::Str => true, _ => false, }; - if format_args.args.iter().all(is_display_arg); - if format_args.fmt_expr.map_or(true, check_unformatted); + if let Some(args) = format_args.args(); + if args.iter().all(|arg| arg.is_display() && !arg.has_string_formatting()); then { let is_new_string = match value.kind { ExprKind::Binary(..) => true, ExprKind::MethodCall(path, ..) => path.ident.name.as_str() == "to_string", _ => false, }; - let sugg = if is_new_string { + let sugg = if format_args.format_string_span.contains(value.span) { + // Implicit argument. e.g. `format!("{x}")` span points to `{x}` + let spdata = value.span.data(); + let span = Span::new( + spdata.lo + BytePos(1), + spdata.hi - BytePos(1), + spdata.ctxt, + spdata.parent + ); + let snip = snippet_with_applicability(cx, span, "..", &mut applicability); + if is_new_string { + snip.into() + } else { + format!("{}.to_string()", snip) + } + } else if is_new_string { snippet_with_applicability(cx, value.span, "..", &mut applicability).into_owned() } else { let sugg = Sugg::hir_with_applicability(cx, value, "<arg>", &mut applicability); @@ -90,58 +108,26 @@ impl<'tcx> LateLintPass<'tcx> for UselessFormat { } } -fn span_useless_format(cx: &LateContext<'_>, span: Span, sugg: String, applicability: Applicability) { +fn span_useless_format_empty(cx: &LateContext<'_>, span: Span, sugg: String, applicability: Applicability) { span_lint_and_sugg( cx, USELESS_FORMAT, span, "useless use of `format!`", - "consider using `.to_string()`", + "consider using `String::new()`", sugg, applicability, ); } -fn is_display_arg(expr: &Expr<'_>) -> bool { - if_chain! { - if let ExprKind::Call(_, [_, fmt]) = expr.kind; - if let ExprKind::Path(QPath::Resolved(_, path)) = fmt.kind; - if let [.., t, _] = path.segments; - if t.ident.name == sym::Display; - then { true } else { false } - } -} - -/// Checks if the expression matches -/// ```rust,ignore -/// &[_ { -/// format: _ { -/// width: _::Implied, -/// precision: _::Implied, -/// ... -/// }, -/// ..., -/// }] -/// ``` -fn check_unformatted(expr: &Expr<'_>) -> bool { - if_chain! { - if let ExprKind::AddrOf(BorrowKind::Ref, _, expr) = expr.kind; - if let ExprKind::Array([expr]) = expr.kind; - // struct `core::fmt::rt::v1::Argument` - if let ExprKind::Struct(_, fields, _) = expr.kind; - if let Some(format_field) = fields.iter().find(|f| f.ident.name == sym::format); - // struct `core::fmt::rt::v1::FormatSpec` - if let ExprKind::Struct(_, fields, _) = format_field.expr.kind; - 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; - if let Some(width_field) = fields.iter().find(|f| f.ident.name == sym::width); - if let ExprKind::Path(ref width_qpath) = width_field.expr.kind; - if last_path_segment(width_qpath).ident.name == sym::Implied; - then { - return true; - } - } - - false +fn span_useless_format(cx: &LateContext<'_>, span: Span, sugg: String, applicability: Applicability) { + span_lint_and_sugg( + cx, + USELESS_FORMAT, + span, + "useless use of `format!`", + "consider using `.to_string()`", + sugg, + applicability, + ); } diff --git a/src/tools/clippy/clippy_lints/src/format_args.rs b/src/tools/clippy/clippy_lints/src/format_args.rs new file mode 100644 index 0000000000..8b27442aa9 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/format_args.rs @@ -0,0 +1,223 @@ +use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::higher::{FormatArgsArg, FormatArgsExpn, FormatExpn}; +use clippy_utils::source::snippet_opt; +use clippy_utils::ty::implements_trait; +use clippy_utils::{is_diag_trait_item, 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_middle::ty::adjustment::{Adjust, Adjustment}; +use rustc_middle::ty::Ty; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::{sym, BytePos, ExpnData, ExpnKind, Span, Symbol}; + +declare_clippy_lint! { + /// ### What it does + /// Detects `format!` within the arguments of another macro that does + /// formatting such as `format!` itself, `write!` or `println!`. Suggests + /// inlining the `format!` call. + /// + /// ### Why is this bad? + /// The recommended code is both shorter and avoids a temporary allocation. + /// + /// ### Example + /// ```rust + /// # use std::panic::Location; + /// println!("error: {}", format!("something failed at {}", Location::caller())); + /// ``` + /// Use instead: + /// ```rust + /// # use std::panic::Location; + /// println!("error: something failed at {}", Location::caller()); + /// ``` + pub FORMAT_IN_FORMAT_ARGS, + perf, + "`format!` used in a macro that does formatting" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for [`ToString::to_string`](https://doc.rust-lang.org/std/string/trait.ToString.html#tymethod.to_string) + /// applied to a type that implements [`Display`](https://doc.rust-lang.org/std/fmt/trait.Display.html) + /// in a macro that does formatting. + /// + /// ### Why is this bad? + /// Since the type implements `Display`, the use of `to_string` is + /// unnecessary. + /// + /// ### Example + /// ```rust + /// # use std::panic::Location; + /// println!("error: something failed at {}", Location::caller().to_string()); + /// ``` + /// Use instead: + /// ```rust + /// # use std::panic::Location; + /// println!("error: something failed at {}", Location::caller()); + /// ``` + pub TO_STRING_IN_FORMAT_ARGS, + perf, + "`to_string` applied to a type that implements `Display` in format args" +} + +declare_lint_pass!(FormatArgs => [FORMAT_IN_FORMAT_ARGS, TO_STRING_IN_FORMAT_ARGS]); + +const FORMAT_MACRO_PATHS: &[&[&str]] = &[ + &paths::FORMAT_ARGS_MACRO, + &paths::ASSERT_EQ_MACRO, + &paths::ASSERT_MACRO, + &paths::ASSERT_NE_MACRO, + &paths::EPRINT_MACRO, + &paths::EPRINTLN_MACRO, + &paths::PRINT_MACRO, + &paths::PRINTLN_MACRO, + &paths::WRITE_MACRO, + &paths::WRITELN_MACRO, +]; + +const FORMAT_MACRO_DIAG_ITEMS: &[Symbol] = &[sym::format_macro, sym::std_panic_macro]; + +impl<'tcx> LateLintPass<'tcx> for FormatArgs { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { + if_chain! { + if let Some(format_args) = FormatArgsExpn::parse(expr); + let expr_expn_data = expr.span.ctxt().outer_expn_data(); + let outermost_expn_data = outermost_expn_data(expr_expn_data); + if let Some(macro_def_id) = outermost_expn_data.macro_def_id; + if FORMAT_MACRO_PATHS + .iter() + .any(|path| match_def_path(cx, macro_def_id, path)) + || FORMAT_MACRO_DIAG_ITEMS + .iter() + .any(|diag_item| cx.tcx.is_diagnostic_item(*diag_item, macro_def_id)); + if let ExpnKind::Macro(_, name) = outermost_expn_data.kind; + if let Some(args) = format_args.args(); + then { + for (i, arg) in args.iter().enumerate() { + if !arg.is_display() { + continue; + } + if arg.has_string_formatting() { + continue; + } + if is_aliased(&args, i) { + continue; + } + check_format_in_format_args(cx, outermost_expn_data.call_site, name, arg); + check_to_string_in_format_args(cx, name, arg); + } + } + } + } +} + +fn outermost_expn_data(expn_data: ExpnData) -> ExpnData { + if expn_data.call_site.from_expansion() { + outermost_expn_data(expn_data.call_site.ctxt().outer_expn_data()) + } else { + expn_data + } +} + +fn check_format_in_format_args(cx: &LateContext<'_>, call_site: Span, name: Symbol, arg: &FormatArgsArg<'_>) { + if_chain! { + if FormatExpn::parse(arg.value).is_some(); + if !arg.value.span.ctxt().outer_expn_data().call_site.from_expansion(); + then { + span_lint_and_then( + cx, + FORMAT_IN_FORMAT_ARGS, + trim_semicolon(cx, call_site), + &format!("`format!` in `{}!` args", name), + |diag| { + diag.help(&format!( + "combine the `format!(..)` arguments with the outer `{}!(..)` call", + name + )); + diag.help("or consider changing `format!` to `format_args!`"); + }, + ); + } + } +} + +fn check_to_string_in_format_args<'tcx>(cx: &LateContext<'tcx>, name: Symbol, arg: &FormatArgsArg<'tcx>) { + let value = arg.value; + if_chain! { + if !value.span.from_expansion(); + if let ExprKind::MethodCall(_, _, [receiver], _) = value.kind; + if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(value.hir_id); + if is_diag_trait_item(cx, method_def_id, sym::ToString); + let receiver_ty = cx.typeck_results().expr_ty(receiver); + if let Some(display_trait_id) = cx.tcx.get_diagnostic_item(sym::Display); + if let Some(receiver_snippet) = snippet_opt(cx, receiver.span); + then { + let (n_needed_derefs, target) = count_needed_derefs( + receiver_ty, + cx.typeck_results().expr_adjustments(receiver).iter(), + ); + if implements_trait(cx, target, display_trait_id, &[]) { + if n_needed_derefs == 0 { + span_lint_and_sugg( + cx, + TO_STRING_IN_FORMAT_ARGS, + value.span.with_lo(receiver.span.hi()), + &format!("`to_string` applied to a type that implements `Display` in `{}!` args", name), + "remove this", + String::new(), + Applicability::MachineApplicable, + ); + } else { + span_lint_and_sugg( + cx, + TO_STRING_IN_FORMAT_ARGS, + value.span, + &format!("`to_string` applied to a type that implements `Display` in `{}!` args", name), + "use this", + format!("{:*>width$}{}", "", receiver_snippet, width = n_needed_derefs), + Applicability::MachineApplicable, + ); + } + } + } + } +} + +// Returns true if `args[i]` "refers to" or "is referred to by" another argument. +fn is_aliased(args: &[FormatArgsArg<'_>], i: usize) -> bool { + let value = args[i].value; + args.iter() + .enumerate() + .any(|(j, arg)| i != j && std::ptr::eq(value, arg.value)) +} + +fn trim_semicolon(cx: &LateContext<'_>, span: Span) -> Span { + snippet_opt(cx, span).map_or(span, |snippet| { + let snippet = snippet.trim_end_matches(';'); + span.with_hi(span.lo() + BytePos(u32::try_from(snippet.len()).unwrap())) + }) +} + +fn count_needed_derefs<'tcx, I>(mut ty: Ty<'tcx>, mut iter: I) -> (usize, Ty<'tcx>) +where + I: Iterator<Item = &'tcx Adjustment<'tcx>>, +{ + let mut n_total = 0; + let mut n_needed = 0; + loop { + if let Some(Adjustment { + kind: Adjust::Deref(overloaded_deref), + target, + }) = iter.next() + { + n_total += 1; + if overloaded_deref.is_some() { + n_needed = n_total; + } + ty = target; + } else { + return (n_needed, ty); + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/functions/mod.rs b/src/tools/clippy/clippy_lints/src/functions/mod.rs index 04fc5887e8..d7c5ec9ba3 100644 --- a/src/tools/clippy/clippy_lints/src/functions/mod.rs +++ b/src/tools/clippy/clippy_lints/src/functions/mod.rs @@ -91,11 +91,9 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for a [`#[must_use]`] attribute on + /// 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. @@ -112,12 +110,10 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for a [`#[must_use]`] attribute without + /// 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 @@ -138,11 +134,9 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does /// Checks for public functions that have no - /// [`#[must_use]`] attribute, but return something not already marked + /// `#[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. 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 e18442515b..6b2ac98555 100644 --- a/src/tools/clippy/clippy_lints/src/future_not_send.rs +++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs @@ -77,13 +77,13 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend { if is_future { let send_trait = cx.tcx.get_diagnostic_item(sym::Send).unwrap(); let span = decl.output.span(); - let send_result = cx.tcx.infer_ctxt().enter(|infcx| { + let send_errors = cx.tcx.infer_ctxt().enter(|infcx| { let cause = traits::ObligationCause::misc(span, hir_id); let mut fulfillment_cx = traits::FulfillmentContext::new(); fulfillment_cx.register_bound(&infcx, cx.param_env, ret_ty, send_trait, cause); fulfillment_cx.select_all_or_error(&infcx) }); - if let Err(send_errors) = send_result { + if !send_errors.is_empty() { span_lint_and_then( cx, FUTURE_NOT_SEND, diff --git a/src/tools/clippy/clippy_lints/src/identity_op.rs b/src/tools/clippy/clippy_lints/src/identity_op.rs index 73bdd67ff5..414f465c49 100644 --- a/src/tools/clippy/clippy_lints/src/identity_op.rs +++ b/src/tools/clippy/clippy_lints/src/identity_op.rs @@ -66,7 +66,6 @@ fn is_allowed(cx: &LateContext<'_>, cmp: BinOp, left: &Expr<'_>, right: &Expr<'_ && constant_simple(cx, cx.typeck_results(), left) == Some(Constant::Int(1)) } -#[allow(clippy::cast_possible_wrap)] fn check(cx: &LateContext<'_>, e: &Expr<'_>, m: i8, span: Span, arg: Span) { if let Some(Constant::Int(v)) = constant_simple(cx, cx.typeck_results(), e) { let check = match *cx.typeck_results().expr_ty(e).kind() { 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 3ce91d421b..ac93815623 100644 --- a/src/tools/clippy/clippy_lints/src/if_not_else.rs +++ b/src/tools/clippy/clippy_lints/src/if_not_else.rs @@ -2,9 +2,9 @@ //! on the condition use clippy_utils::diagnostics::span_lint_and_help; -use rustc_ast::ast::{BinOpKind, Expr, ExprKind, UnOp}; -use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_middle::lint::in_external_macro; +use clippy_utils::is_else_clause; +use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; +use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { @@ -46,14 +46,21 @@ declare_clippy_lint! { declare_lint_pass!(IfNotElse => [IF_NOT_ELSE]); -impl EarlyLintPass for IfNotElse { - fn check_expr(&mut self, cx: &EarlyContext<'_>, item: &Expr) { - if in_external_macro(cx.sess, item.span) { +impl LateLintPass<'_> for IfNotElse { + fn check_expr(&mut self, cx: &LateContext<'_>, item: &Expr<'_>) { + // While loops will be desugared to ExprKind::If. This will cause the lint to fire. + // To fix this, return early if this span comes from a macro or desugaring. + if item.span.from_expansion() { return; } - if let ExprKind::If(ref cond, _, Some(ref els)) = item.kind { + if let ExprKind::If(cond, _, Some(els)) = item.kind { if let ExprKind::Block(..) = els.kind { - match cond.kind { + // Disable firing the lint in "else if" expressions. + if is_else_clause(cx.tcx, item) { + return; + } + + match cond.peel_drop_temps().kind { ExprKind::Unary(UnOp::Not, _) => { span_lint_and_help( cx, 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 79d4d7ddcb..a4f60ded3a 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs @@ -43,7 +43,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub { return; } if_chain! { - if let Some(higher::If { cond, then, .. }) = higher::If::hir(expr); + if let Some(higher::If { cond, then, r#else: None }) = higher::If::hir(expr); // Check if the conditional expression is a binary operation if let ExprKind::Binary(ref cond_op, cond_left, cond_right) = cond.kind; 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 3c40ca50a0..61dd0eb4af 100644 --- a/src/tools/clippy/clippy_lints/src/inherent_to_string.rs +++ b/src/tools/clippy/clippy_lints/src/inherent_to_string.rs @@ -138,10 +138,10 @@ fn show_lint(cx: &LateContext<'_>, item: &ImplItem<'_>) { item.span, &format!( "type `{}` implements inherent method `to_string(&self) -> String` which shadows the implementation of `Display`", - self_type.to_string() + self_type ), None, - &format!("remove the inherent method from type `{}`", self_type.to_string()), + &format!("remove the inherent method from type `{}`", self_type), ); } else { span_lint_and_help( @@ -150,10 +150,10 @@ fn show_lint(cx: &LateContext<'_>, item: &ImplItem<'_>) { item.span, &format!( "implementation of inherent method `to_string(&self) -> String` for type `{}`", - self_type.to_string() + self_type ), None, - &format!("implement trait `Display` for type `{}` instead", self_type.to_string()), + &format!("implement trait `Display` for type `{}` instead", self_type), ); } } diff --git a/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs b/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs index b1f70b30c1..82438d85c7 100644 --- a/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs +++ b/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs @@ -1,5 +1,3 @@ -use std::cmp::Ordering; - use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::layout::LayoutOf; @@ -7,11 +5,11 @@ use rustc_middle::ty::{self, IntTy, UintTy}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::Span; +use clippy_utils::comparisons; use clippy_utils::comparisons::Rel; -use clippy_utils::consts::{constant, Constant}; +use clippy_utils::consts::{constant_full_int, FullInt}; use clippy_utils::diagnostics::span_lint; use clippy_utils::source::snippet; -use clippy_utils::{comparisons, sext}; declare_clippy_lint! { /// ### What it does @@ -39,53 +37,6 @@ declare_clippy_lint! { 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); @@ -118,19 +69,6 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_>, expr: &'a Expr<'_>) -> } } -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( @@ -156,7 +94,7 @@ fn upcast_comparison_bounds_err<'tcx>( invert: bool, ) { if let Some((lb, ub)) = lhs_bounds { - if let Some(norm_rhs_val) = node_as_const_fullint(cx, rhs) { + if let Some(norm_rhs_val) = constant_full_int(cx, cx.typeck_results(), 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); diff --git a/src/tools/clippy/clippy_lints/src/let_underscore.rs b/src/tools/clippy/clippy_lints/src/let_underscore.rs index 89146b4dd2..9efd7aba7e 100644 --- a/src/tools/clippy/clippy_lints/src/let_underscore.rs +++ b/src/tools/clippy/clippy_lints/src/let_underscore.rs @@ -10,12 +10,11 @@ use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { /// ### What it does - /// Checks for `let _ = <expr>` - /// where expr is #[must_use] + /// Checks for `let _ = <expr>` where expr is `#[must_use]` /// /// ### Why is this bad? - /// It's better to explicitly - /// handle the value of a #[must_use] expr + /// It's better to explicitly handle the value of a `#[must_use]` + /// expr /// /// ### Example /// ```rust diff --git a/src/tools/clippy/clippy_lints/src/lib.register_all.rs b/src/tools/clippy/clippy_lints/src/lib.register_all.rs index e67d73c3c6..8dac588b51 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_all.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_all.rs @@ -60,6 +60,8 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS), LintId::of(float_literal::EXCESSIVE_PRECISION), LintId::of(format::USELESS_FORMAT), + LintId::of(format_args::FORMAT_IN_FORMAT_ARGS), + LintId::of(format_args::TO_STRING_IN_FORMAT_ARGS), LintId::of(formatting::POSSIBLE_MISSING_COMMA), LintId::of(formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING), LintId::of(formatting::SUSPICIOUS_ELSE_FORMATTING), @@ -117,6 +119,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(map_unit_fn::OPTION_MAP_UNIT_FN), LintId::of(map_unit_fn::RESULT_MAP_UNIT_FN), LintId::of(match_result_ok::MATCH_RESULT_OK), + LintId::of(match_str_case_mismatch::MATCH_STR_CASE_MISMATCH), LintId::of(matches::INFALLIBLE_DESTRUCTURING_MATCH), LintId::of(matches::MATCH_AS_REF), LintId::of(matches::MATCH_LIKE_MATCHES_MACRO), @@ -264,6 +267,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ 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_NUM_TO_BYTES), LintId::of(transmute::TRANSMUTE_PTR_TO_REF), LintId::of(transmute::UNSOUND_COLLECTION_TRANSMUTE), LintId::of(transmute::WRONG_TRANSMUTE), @@ -276,6 +280,8 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(types::VEC_BOX), LintId::of(undropped_manually_drops::UNDROPPED_MANUALLY_DROPS), LintId::of(unicode::INVISIBLE_CHARACTERS), + LintId::of(uninit_vec::UNINIT_VEC), + LintId::of(unit_hash::UNIT_HASH), LintId::of(unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD), LintId::of(unit_types::UNIT_ARG), LintId::of(unit_types::UNIT_CMP), diff --git a/src/tools/clippy/clippy_lints/src/lib.register_complexity.rs b/src/tools/clippy/clippy_lints/src/lib.register_complexity.rs index 64b82fc0fa..c51341bdf0 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_complexity.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_complexity.rs @@ -82,6 +82,7 @@ store.register_group(true, "clippy::complexity", Some("clippy_complexity"), vec! 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_NUM_TO_BYTES), LintId::of(transmute::TRANSMUTE_PTR_TO_REF), LintId::of(types::BORROWED_BOX), LintId::of(types::TYPE_COMPLEXITY), diff --git a/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs b/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs index bbe47a0e77..4217fd3a3e 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs @@ -36,6 +36,7 @@ store.register_group(true, "clippy::correctness", Some("clippy_correctness"), ve LintId::of(loops::ITER_NEXT_LOOP), LintId::of(loops::NEVER_LOOP), LintId::of(loops::WHILE_IMMUTABLE_CONDITION), + LintId::of(match_str_case_mismatch::MATCH_STR_CASE_MISMATCH), LintId::of(mem_replace::MEM_REPLACE_WITH_UNINIT), LintId::of(methods::CLONE_DOUBLE_REF), LintId::of(methods::ITERATOR_STEP_BY_ZERO), @@ -62,6 +63,8 @@ store.register_group(true, "clippy::correctness", Some("clippy_correctness"), ve LintId::of(transmuting_null::TRANSMUTING_NULL), LintId::of(undropped_manually_drops::UNDROPPED_MANUALLY_DROPS), LintId::of(unicode::INVISIBLE_CHARACTERS), + LintId::of(uninit_vec::UNINIT_VEC), + LintId::of(unit_hash::UNIT_HASH), LintId::of(unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD), LintId::of(unit_types::UNIT_CMP), LintId::of(unnamed_address::FN_ADDRESS_COMPARISONS), diff --git a/src/tools/clippy/clippy_lints/src/lib.register_lints.rs b/src/tools/clippy/clippy_lints/src/lib.register_lints.rs index d5a3734737..2cb86418e3 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_lints.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_lints.rs @@ -67,6 +67,7 @@ store.register_lints(&[ casts::CAST_SIGN_LOSS, casts::CHAR_LIT_AS_U8, casts::FN_TO_NUMERIC_CAST, + casts::FN_TO_NUMERIC_CAST_ANY, casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION, casts::PTR_AS_PTR, casts::UNNECESSARY_CAST, @@ -138,6 +139,8 @@ store.register_lints(&[ floating_point_arithmetic::IMPRECISE_FLOPS, floating_point_arithmetic::SUBOPTIMAL_FLOPS, format::USELESS_FORMAT, + format_args::FORMAT_IN_FORMAT_ARGS, + format_args::TO_STRING_IN_FORMAT_ARGS, formatting::POSSIBLE_MISSING_COMMA, formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING, formatting::SUSPICIOUS_ELSE_FORMATTING, @@ -225,6 +228,7 @@ store.register_lints(&[ map_unit_fn::RESULT_MAP_UNIT_FN, match_on_vec_items::MATCH_ON_VEC_ITEMS, match_result_ok::MATCH_RESULT_OK, + match_str_case_mismatch::MATCH_STR_CASE_MISMATCH, matches::INFALLIBLE_DESTRUCTURING_MATCH, matches::MATCH_AS_REF, matches::MATCH_BOOL, @@ -323,6 +327,7 @@ store.register_lints(&[ misc_early::DUPLICATE_UNDERSCORE_ARGUMENT, misc_early::MIXED_CASE_HEX_LITERALS, misc_early::REDUNDANT_PATTERN, + misc_early::SEPARATED_LITERAL_SUFFIX, misc_early::UNNEEDED_FIELD_PATTERN, misc_early::UNNEEDED_WILDCARD_PATTERN, misc_early::UNSEPARATED_LITERAL_SUFFIX, @@ -359,6 +364,7 @@ store.register_lints(&[ neg_multiply::NEG_MULTIPLY, new_without_default::NEW_WITHOUT_DEFAULT, no_effect::NO_EFFECT, + no_effect::NO_EFFECT_UNDERSCORE_BINDING, no_effect::UNNECESSARY_OPERATION, non_copy_const::BORROW_INTERIOR_MUTABLE_CONST, non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST, @@ -426,6 +432,7 @@ store.register_lints(&[ strings::STRING_ADD_ASSIGN, strings::STRING_FROM_UTF8_AS_BYTES, strings::STRING_LIT_AS_BYTES, + strings::STRING_SLICE, strings::STRING_TO_STRING, strings::STR_TO_STRING, strlen_on_c_strings::STRLEN_ON_C_STRINGS, @@ -438,6 +445,7 @@ store.register_lints(&[ temporary_assignment::TEMPORARY_ASSIGNMENT, to_digit_is_some::TO_DIGIT_IS_SOME, to_string_in_display::TO_STRING_IN_DISPLAY, + trailing_empty_array::TRAILING_EMPTY_ARRAY, trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS, trait_bounds::TYPE_REPETITION_IN_BOUNDS, transmute::CROSSPOINTER_TRANSMUTE, @@ -447,6 +455,7 @@ store.register_lints(&[ transmute::TRANSMUTE_INT_TO_BOOL, transmute::TRANSMUTE_INT_TO_CHAR, transmute::TRANSMUTE_INT_TO_FLOAT, + transmute::TRANSMUTE_NUM_TO_BYTES, transmute::TRANSMUTE_PTR_TO_PTR, transmute::TRANSMUTE_PTR_TO_REF, transmute::UNSOUND_COLLECTION_TRANSMUTE, @@ -463,10 +472,13 @@ store.register_lints(&[ types::REDUNDANT_ALLOCATION, types::TYPE_COMPLEXITY, types::VEC_BOX, + undocumented_unsafe_blocks::UNDOCUMENTED_UNSAFE_BLOCKS, undropped_manually_drops::UNDROPPED_MANUALLY_DROPS, unicode::INVISIBLE_CHARACTERS, unicode::NON_ASCII_LITERAL, unicode::UNICODE_NOT_NFC, + uninit_vec::UNINIT_VEC, + unit_hash::UNIT_HASH, unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD, unit_types::LET_UNIT_VALUE, unit_types::UNIT_ARG, diff --git a/src/tools/clippy/clippy_lints/src/lib.register_nursery.rs b/src/tools/clippy/clippy_lints/src/lib.register_nursery.rs index 96e0b42109..1e54482a8d 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_nursery.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_nursery.rs @@ -25,6 +25,7 @@ store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![ LintId::of(regex::TRIVIAL_REGEX), LintId::of(strings::STRING_LIT_AS_BYTES), LintId::of(suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS), + LintId::of(trailing_empty_array::TRAILING_EMPTY_ARRAY), LintId::of(transmute::USELESS_TRANSMUTE), LintId::of(use_self::USE_SELF), ]) diff --git a/src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs b/src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs index a4b8109a35..404ca20b5a 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs @@ -66,13 +66,13 @@ store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), vec![ LintId::of(methods::MAP_UNWRAP_OR), LintId::of(misc::FLOAT_CMP), LintId::of(misc::USED_UNDERSCORE_BINDING), - LintId::of(misc_early::UNSEPARATED_LITERAL_SUFFIX), LintId::of(mut_mut::MUT_MUT), LintId::of(needless_bitwise_bool::NEEDLESS_BITWISE_BOOL), LintId::of(needless_borrow::REF_BINDING_TO_REFERENCE), 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(no_effect::NO_EFFECT_UNDERSCORE_BINDING), LintId::of(non_expressive_names::MANY_SINGLE_CHAR_NAMES), LintId::of(non_expressive_names::SIMILAR_NAMES), LintId::of(pass_by_ref_or_value::LARGE_TYPES_PASSED_BY_VALUE), @@ -88,7 +88,6 @@ store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), vec![ 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), diff --git a/src/tools/clippy/clippy_lints/src/lib.register_perf.rs b/src/tools/clippy/clippy_lints/src/lib.register_perf.rs index 5432345760..a0d5cf9418 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_perf.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_perf.rs @@ -5,6 +5,8 @@ store.register_group(true, "clippy::perf", Some("clippy_perf"), vec![ LintId::of(entry::MAP_ENTRY), LintId::of(escape::BOXED_LOCAL), + LintId::of(format_args::FORMAT_IN_FORMAT_ARGS), + LintId::of(format_args::TO_STRING_IN_FORMAT_ARGS), LintId::of(large_const_arrays::LARGE_CONST_ARRAYS), LintId::of(large_enum_variant::LARGE_ENUM_VARIANT), LintId::of(loops::MANUAL_MEMCPY), diff --git a/src/tools/clippy/clippy_lints/src/lib.register_restriction.rs b/src/tools/clippy/clippy_lints/src/lib.register_restriction.rs index 4463dea5fc..eab389a9bd 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_restriction.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_restriction.rs @@ -8,6 +8,7 @@ store.register_group(true, "clippy::restriction", Some("clippy_restriction"), ve 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(casts::FN_TO_NUMERIC_CAST_ANY), LintId::of(create_dir::CREATE_DIR), LintId::of(dbg_macro::DBG_MACRO), LintId::of(default_numeric_fallback::DEFAULT_NUMERIC_FALLBACK), @@ -34,7 +35,9 @@ store.register_group(true, "clippy::restriction", Some("clippy_restriction"), ve LintId::of(methods::GET_UNWRAP), LintId::of(methods::UNWRAP_USED), LintId::of(misc::FLOAT_CMP_CONST), + LintId::of(misc_early::SEPARATED_LITERAL_SUFFIX), LintId::of(misc_early::UNNEEDED_FIELD_PATTERN), + LintId::of(misc_early::UNSEPARATED_LITERAL_SUFFIX), LintId::of(missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS), LintId::of(missing_enforced_import_rename::MISSING_ENFORCED_IMPORT_RENAMES), LintId::of(missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS), @@ -52,10 +55,13 @@ store.register_group(true, "clippy::restriction", Some("clippy_restriction"), ve LintId::of(shadow::SHADOW_SAME), LintId::of(shadow::SHADOW_UNRELATED), LintId::of(strings::STRING_ADD), + LintId::of(strings::STRING_SLICE), LintId::of(strings::STRING_TO_STRING), LintId::of(strings::STR_TO_STRING), LintId::of(types::RC_BUFFER), LintId::of(types::RC_MUTEX), + LintId::of(undocumented_unsafe_blocks::UNDOCUMENTED_UNSAFE_BLOCKS), + LintId::of(unicode::NON_ASCII_LITERAL), LintId::of(unnecessary_self_imports::UNNECESSARY_SELF_IMPORTS), LintId::of(unwrap_in_result::UNWRAP_IN_RESULT), LintId::of(verbose_file_reads::VERBOSE_FILE_READS), diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index 78ecdb99be..7174d0a082 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -218,6 +218,7 @@ mod float_equality_without_abs; mod float_literal; mod floating_point_arithmetic; mod format; +mod format_args; mod formatting; mod from_over_into; mod from_str_radix_10; @@ -265,6 +266,7 @@ mod map_err_ignore; mod map_unit_fn; mod match_on_vec_items; mod match_result_ok; +mod match_str_case_mismatch; mod matches; mod mem_forget; mod mem_replace; @@ -352,13 +354,17 @@ mod tabs_in_doc_comments; mod temporary_assignment; mod to_digit_is_some; mod to_string_in_display; +mod trailing_empty_array; mod trait_bounds; mod transmute; mod transmuting_null; mod try_err; mod types; +mod undocumented_unsafe_blocks; mod undropped_manually_drops; mod unicode; +mod uninit_vec; +mod unit_hash; mod unit_return_expecting_ord; mod unit_types; mod unnamed_address; @@ -516,6 +522,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| Box::new(blocks_in_if_conditions::BlocksInIfConditions)); store.register_late_pass(|| Box::new(collapsible_match::CollapsibleMatch)); store.register_late_pass(|| Box::new(unicode::Unicode)); + store.register_late_pass(|| Box::new(uninit_vec::UninitVec)); + store.register_late_pass(|| Box::new(unit_hash::UnitHash)); store.register_late_pass(|| Box::new(unit_return_expecting_ord::UnitReturnExpectingOrd)); store.register_late_pass(|| Box::new(strings::StringAdd)); store.register_late_pass(|| Box::new(implicit_return::ImplicitReturn)); @@ -660,7 +668,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_early_pass(|| Box::new(double_parens::DoubleParens)); store.register_late_pass(|| Box::new(to_string_in_display::ToStringInDisplay::new())); store.register_early_pass(|| Box::new(unsafe_removed_from_name::UnsafeNameRemoval)); - store.register_early_pass(|| Box::new(if_not_else::IfNotElse)); store.register_early_pass(|| Box::new(else_if_without_else::ElseIfWithoutElse)); store.register_early_pass(|| Box::new(int_plus_one::IntPlusOne)); store.register_early_pass(|| Box::new(formatting::Formatting)); @@ -714,6 +721,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| Box::new(option_if_let_else::OptionIfLetElse)); store.register_late_pass(|| Box::new(future_not_send::FutureNotSend)); store.register_late_pass(|| Box::new(if_let_mutex::IfLetMutex)); + store.register_late_pass(|| Box::new(if_not_else::IfNotElse)); store.register_late_pass(|| Box::new(equatable_if_let::PatternEquality)); store.register_late_pass(|| Box::new(mut_mutex_lock::MutMutexLock)); store.register_late_pass(|| Box::new(match_on_vec_items::MatchOnVecItems)); @@ -754,8 +762,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| Box::new(bool_assert_comparison::BoolAssertComparison)); store.register_early_pass(move || Box::new(module_style::ModStyle)); store.register_late_pass(|| Box::new(unused_async::UnusedAsync)); - let disallowed_types = conf.disallowed_types.iter().cloned().collect::<FxHashSet<_>>(); - store.register_late_pass(move || Box::new(disallowed_type::DisallowedType::new(&disallowed_types))); + let disallowed_types = conf.disallowed_types.clone(); + store.register_late_pass(move || Box::new(disallowed_type::DisallowedType::new(disallowed_types.clone()))); let import_renames = conf.enforced_import_renames.clone(); store.register_late_pass(move || Box::new(missing_enforced_import_rename::ImportRename::new(import_renames.clone()))); let scripts = conf.allowed_scripts.clone(); @@ -767,6 +775,11 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(move || Box::new(manual_assert::ManualAssert)); let enable_raw_pointer_heuristic_for_send = conf.enable_raw_pointer_heuristic_for_send; store.register_late_pass(move || Box::new(non_send_fields_in_send_ty::NonSendFieldInSendTy::new(enable_raw_pointer_heuristic_for_send))); + store.register_late_pass(move || Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks::default())); + store.register_late_pass(|| Box::new(match_str_case_mismatch::MatchStrCaseMismatch)); + store.register_late_pass(move || Box::new(format_args::FormatArgs)); + store.register_late_pass(|| Box::new(trailing_empty_array::TrailingEmptyArray)); + // add lints here, do not remove this comment, it's used in `new_lint` } #[rustfmt::skip] @@ -817,6 +830,7 @@ fn register_removed_non_tool_lints(store: &mut rustc_lint::LintStore) { /// /// Used in `./src/driver.rs`. pub fn register_renamed(ls: &mut rustc_lint::LintStore) { + // NOTE: when renaming a lint, add a corresponding test to tests/ui/rename.rs ls.register_renamed("clippy::stutter", "clippy::module_name_repetitions"); ls.register_renamed("clippy::new_without_default_derive", "clippy::new_without_default"); ls.register_renamed("clippy::cyclomatic_complexity", "clippy::cognitive_complexity"); diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index e5e6f8d25c..cb0b96e065 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -378,11 +378,15 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> { fn visit_ty(&mut self, ty: &'tcx Ty<'_>) { match ty.kind { - TyKind::OpaqueDef(item, _) => { + TyKind::OpaqueDef(item, bounds) => { let map = self.cx.tcx.hir(); let item = map.item(item); walk_item(self, item); walk_ty(self, ty); + self.lts.extend(bounds.iter().filter_map(|bound| match bound { + GenericArg::Lifetime(l) => Some(RefLt::Named(l.name.ident().name)), + _ => None, + })); }, TyKind::BareFn(&BareFnTy { decl, .. }) => { let mut sub_visitor = RefVisitor::new(self.cx); 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 98e60f7ed8..6f213d7a69 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,6 +1,4 @@ -use super::{ - get_span_of_entire_for_loop, make_iterator_snippet, IncrementVisitor, InitializeVisitor, EXPLICIT_COUNTER_LOOP, -}; +use super::{make_iterator_snippet, IncrementVisitor, InitializeVisitor, EXPLICIT_COUNTER_LOOP}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::{get_enclosing_block, is_integer_const}; @@ -37,12 +35,10 @@ pub(super) fn check<'tcx>( then { let mut applicability = Applicability::MachineApplicable; - let for_span = get_span_of_entire_for_loop(expr); - span_lint_and_sugg( cx, EXPLICIT_COUNTER_LOOP, - for_span.with_hi(arg.span.hi()), + expr.span.with_hi(arg.span.hi()), &format!("the variable `{}` is used as a loop counter", name), "consider using", format!( 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 72027a163a..2362b4b206 100644 --- a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs +++ b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs @@ -1,4 +1,4 @@ -use super::{get_span_of_entire_for_loop, IncrementVisitor, InitializeVisitor, MANUAL_MEMCPY}; +use super::{IncrementVisitor, InitializeVisitor, MANUAL_MEMCPY}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet; use clippy_utils::sugg::Sugg; @@ -86,7 +86,7 @@ pub(super) fn check<'tcx>( span_lint_and_sugg( cx, MANUAL_MEMCPY, - get_span_of_entire_for_loop(expr), + expr.span, "it looks like you're manually copying between slices", "try replacing the loop by", big_sugg, diff --git a/src/tools/clippy/clippy_lints/src/loops/mod.rs b/src/tools/clippy/clippy_lints/src/loops/mod.rs index 5df1b79640..fd4881b294 100644 --- a/src/tools/clippy/clippy_lints/src/loops/mod.rs +++ b/src/tools/clippy/clippy_lints/src/loops/mod.rs @@ -23,7 +23,7 @@ use rustc_hir::{Expr, ExprKind, LoopSource, Pat}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -use utils::{get_span_of_entire_for_loop, make_iterator_snippet, IncrementVisitor, InitializeVisitor}; +use utils::{make_iterator_snippet, IncrementVisitor, InitializeVisitor}; declare_clippy_lint! { /// ### What it does @@ -566,7 +566,15 @@ declare_lint_pass!(Loops => [ impl<'tcx> LateLintPass<'tcx> for Loops { #[allow(clippy::too_many_lines)] fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let Some(higher::ForLoop { pat, arg, body, span }) = higher::ForLoop::hir(expr) { + let for_loop = higher::ForLoop::hir(expr); + if let Some(higher::ForLoop { + pat, + arg, + body, + loop_id, + span, + }) = for_loop + { // we don't want to check expanded macros // this check is not at the top of the function // since higher::for_loop expressions are marked as expansions @@ -574,6 +582,9 @@ impl<'tcx> LateLintPass<'tcx> for Loops { return; } check_for_loop(cx, pat, arg, body, expr, span); + if let ExprKind::Block(block, _) = body.kind { + never_loop::check(cx, block, loop_id, span, for_loop.as_ref()); + } } // we don't want to check expanded macros @@ -582,7 +593,9 @@ impl<'tcx> LateLintPass<'tcx> for Loops { } // check for never_loop - never_loop::check(cx, expr); + if let ExprKind::Loop(block, ..) = expr.kind { + never_loop::check(cx, block, expr.hir_id, expr.span, None); + } // check for `loop { if let {} else break }` that could be `while let` // (also matches an explicit "match" instead of "if let") 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 c0fde5e516..86b7d6d989 100644 --- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs @@ -4,35 +4,41 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::ForLoop; use clippy_utils::source::snippet; use rustc_errors::Applicability; -use rustc_hir::{Block, Expr, ExprKind, HirId, InlineAsmOperand, LoopSource, Node, Pat, Stmt, StmtKind}; +use rustc_hir::{Block, Expr, ExprKind, HirId, InlineAsmOperand, Pat, Stmt, StmtKind}; use rustc_lint::LateContext; +use rustc_span::Span; use std::iter::{once, Iterator}; -pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let ExprKind::Loop(block, _, source, _) = expr.kind { - match never_loop_block(block, expr.hir_id) { - NeverLoopResult::AlwaysBreak => { - span_lint_and_then(cx, NEVER_LOOP, expr.span, "this loop never actually loops", |diag| { - if_chain! { - if source == LoopSource::ForLoop; - if let Some((_, Node::Expr(parent_match))) = cx.tcx.hir().parent_iter(expr.hir_id).nth(1); - if let Some(ForLoop { arg: iterator, pat, span: for_span, .. }) = ForLoop::hir(parent_match); - then { - // Suggests using an `if let` instead. This is `Unspecified` because the - // loop may (probably) contain `break` statements which would be invalid - // in an `if let`. - diag.span_suggestion_verbose( - for_span.with_hi(iterator.span.hi()), - "if you need the first element of the iterator, try writing", - for_to_if_let_sugg(cx, iterator, pat), - Applicability::Unspecified, - ); - } - }; - }); - }, - NeverLoopResult::MayContinueMainLoop | NeverLoopResult::Otherwise => (), - } +pub(super) fn check( + cx: &LateContext<'tcx>, + block: &'tcx Block<'_>, + loop_id: HirId, + span: Span, + for_loop: Option<&ForLoop<'_>>, +) { + match never_loop_block(block, loop_id) { + NeverLoopResult::AlwaysBreak => { + span_lint_and_then(cx, NEVER_LOOP, span, "this loop never actually loops", |diag| { + if let Some(ForLoop { + arg: iterator, + pat, + span: for_span, + .. + }) = for_loop + { + // Suggests using an `if let` instead. This is `Unspecified` because the + // loop may (probably) contain `break` statements which would be invalid + // in an `if let`. + diag.span_suggestion_verbose( + for_span.with_hi(iterator.span.hi()), + "if you need the first element of the iterator, try writing", + for_to_if_let_sugg(cx, iterator, pat), + Applicability::Unspecified, + ); + } + }); + }, + NeverLoopResult::MayContinueMainLoop | NeverLoopResult::Otherwise => (), } } 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 0fd09ff719..e39605f3e7 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,4 +1,4 @@ -use super::{get_span_of_entire_for_loop, SINGLE_ELEMENT_LOOP}; +use super::SINGLE_ELEMENT_LOOP; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::single_segment_path; use clippy_utils::source::{indent_of, snippet}; @@ -30,7 +30,6 @@ pub(super) fn check<'tcx>( if !block.stmts.is_empty(); then { - let for_span = get_span_of_entire_for_loop(expr); let mut block_str = snippet(cx, block.span, "..").into_owned(); block_str.remove(0); block_str.pop(); @@ -39,7 +38,7 @@ pub(super) fn check<'tcx>( span_lint_and_sugg( cx, SINGLE_ELEMENT_LOOP, - for_span, + expr.span, "for loop over a single element", "try", format!("{{\n{}let {} = &{};{}}}", " ".repeat(indent_of(cx, block.stmts[0].span).unwrap_or(0)), target.name, list_item_name, block_str), diff --git a/src/tools/clippy/clippy_lints/src/loops/utils.rs b/src/tools/clippy/clippy_lints/src/loops/utils.rs index f9f515cc40..c3939a66c6 100644 --- a/src/tools/clippy/clippy_lints/src/loops/utils.rs +++ b/src/tools/clippy/clippy_lints/src/loops/utils.rs @@ -7,7 +7,6 @@ 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::{sym, Symbol}; use std::iter::Iterator; @@ -300,17 +299,6 @@ impl<'tcx> Visitor<'tcx> for LoopNestVisitor { } } -// this function assumes the given expression is a `for` loop. -pub(super) fn get_span_of_entire_for_loop(expr: &Expr<'_>) -> Span { - // for some reason this is the only way to get the `Span` - // of the entire `for` loop - if let ExprKind::Match(_, arms, _) = &expr.kind { - arms[0].body.span - } else { - unreachable!() - } -} - /// 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 { diff --git a/src/tools/clippy/clippy_lints/src/manual_assert.rs b/src/tools/clippy/clippy_lints/src/manual_assert.rs index 42c679e364..e55aa3f185 100644 --- a/src/tools/clippy/clippy_lints/src/manual_assert.rs +++ b/src/tools/clippy/clippy_lints/src/manual_assert.rs @@ -54,23 +54,24 @@ impl LateLintPass<'_> for ManualAssert { if !cx.tcx.sess.source_map().is_multiline(cond.span); then { - let span = if let Some(panic_expn) = PanicExpn::parse(semi) { + let call = if_chain! { + if let ExprKind::Block(block, _) = semi.kind; + if let Some(init) = block.expr; + then { + init + } else { + semi + } + }; + let span = if let Some(panic_expn) = PanicExpn::parse(call) { match *panic_expn.format_args.value_args { [] => panic_expn.format_args.format_string_span, [.., last] => panic_expn.format_args.format_string_span.to(last.span), } + } else if let ExprKind::Call(_, [format_args]) = call.kind { + format_args.span } else { - if_chain! { - if let ExprKind::Block(block, _) = semi.kind; - if let Some(init) = block.expr; - if let ExprKind::Call(_, [format_args]) = init.kind; - - then { - format_args.span - } else { - return - } - } + return }; let mut applicability = Applicability::MachineApplicable; let sugg = snippet_with_applicability(cx, span, "..", &mut applicability); @@ -78,10 +79,10 @@ impl LateLintPass<'_> for ManualAssert { if let Expr{kind: ExprKind::Unary(UnOp::Not, not_expr), ..} = e { sugg::Sugg::hir_with_applicability(cx, not_expr, "..", &mut applicability).maybe_par().to_string() } else { - format!("!{}", sugg::Sugg::hir_with_applicability(cx, e, "..", &mut applicability).maybe_par().to_string()) + format!("!{}", sugg::Sugg::hir_with_applicability(cx, e, "..", &mut applicability).maybe_par()) } } else { - format!("!{}", sugg::Sugg::hir_with_applicability(cx, cond, "..", &mut applicability).maybe_par().to_string()) + format!("!{}", sugg::Sugg::hir_with_applicability(cx, cond, "..", &mut applicability).maybe_par()) }; span_lint_and_sugg( 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 2ae9cb4f9c..42478e3416 100644 --- a/src/tools/clippy/clippy_lints/src/manual_unwrap_or.rs +++ b/src/tools/clippy/clippy_lints/src/manual_unwrap_or.rs @@ -98,7 +98,7 @@ fn lint_manual_unwrap_or<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { 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)` + // we don't want parentheses around macro, e.g. `(some_macro!()).unwrap_or(0)` sugg::Sugg::hir_with_macro_callsite(cx, scrutinee, "..") } else { diff --git a/src/tools/clippy/clippy_lints/src/match_result_ok.rs b/src/tools/clippy/clippy_lints/src/match_result_ok.rs index 3db1f0421e..ecf6ad316a 100644 --- a/src/tools/clippy/clippy_lints/src/match_result_ok.rs +++ b/src/tools/clippy/clippy_lints/src/match_result_ok.rs @@ -35,7 +35,7 @@ declare_clippy_lint! { /// } /// /// if let Ok(value) = iter.next() { - /// vec.push_value) + /// vec.push(value) /// } /// ``` pub MATCH_RESULT_OK, diff --git a/src/tools/clippy/clippy_lints/src/match_str_case_mismatch.rs b/src/tools/clippy/clippy_lints/src/match_str_case_mismatch.rs new file mode 100644 index 0000000000..f501593c51 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/match_str_case_mismatch.rs @@ -0,0 +1,171 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::ty::is_type_diagnostic_item; +use rustc_ast::ast::LitKind; +use rustc_errors::Applicability; +use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; +use rustc_hir::{Arm, Expr, ExprKind, MatchSource, PatKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::hir::map::Map; +use rustc_middle::lint::in_external_macro; +use rustc_middle::ty; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::symbol::SymbolStr; +use rustc_span::{sym, Span}; + +declare_clippy_lint! { + /// ### What it does + /// Checks for `match` expressions modifying the case of a string with non-compliant arms + /// + /// ### Why is this bad? + /// The arm is unreachable, which is likely a mistake + /// + /// ### Example + /// ```rust + /// # let text = "Foo"; + /// + /// match &*text.to_ascii_lowercase() { + /// "foo" => {}, + /// "Bar" => {}, + /// _ => {}, + /// } + /// ``` + /// Use instead: + /// ```rust + /// # let text = "Foo"; + /// + /// match &*text.to_ascii_lowercase() { + /// "foo" => {}, + /// "bar" => {}, + /// _ => {}, + /// } + /// ``` + pub MATCH_STR_CASE_MISMATCH, + correctness, + "creation of a case altering match expression with non-compliant arms" +} + +declare_lint_pass!(MatchStrCaseMismatch => [MATCH_STR_CASE_MISMATCH]); + +#[derive(Debug)] +enum CaseMethod { + LowerCase, + AsciiLowerCase, + UpperCase, + AsciiUppercase, +} + +impl LateLintPass<'_> for MatchStrCaseMismatch { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + if_chain! { + if !in_external_macro(cx.tcx.sess, expr.span); + if let ExprKind::Match(match_expr, arms, MatchSource::Normal) = expr.kind; + if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty(match_expr).kind(); + if let ty::Str = ty.kind(); + then { + let mut visitor = MatchExprVisitor { + cx, + case_method: None, + }; + + visitor.visit_expr(match_expr); + + if let Some(case_method) = visitor.case_method { + if let Some((bad_case_span, bad_case_str)) = verify_case(&case_method, arms) { + lint(cx, &case_method, bad_case_span, &bad_case_str); + } + } + } + } + } +} + +struct MatchExprVisitor<'a, 'tcx> { + cx: &'a LateContext<'tcx>, + case_method: Option<CaseMethod>, +} + +impl<'a, 'tcx> Visitor<'tcx> for MatchExprVisitor<'a, 'tcx> { + type Map = Map<'tcx>; + + fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { + NestedVisitorMap::None + } + + fn visit_expr(&mut self, ex: &'tcx Expr<'_>) { + match ex.kind { + ExprKind::MethodCall(segment, _, [receiver], _) + if self.case_altered(&*segment.ident.as_str(), receiver) => {}, + _ => walk_expr(self, ex), + } + } +} + +impl<'a, 'tcx> MatchExprVisitor<'a, 'tcx> { + fn case_altered(&mut self, segment_ident: &str, receiver: &Expr<'_>) -> bool { + if let Some(case_method) = get_case_method(segment_ident) { + let ty = self.cx.typeck_results().expr_ty(receiver).peel_refs(); + + if is_type_diagnostic_item(self.cx, ty, sym::String) || ty.kind() == &ty::Str { + self.case_method = Some(case_method); + return true; + } + } + + false + } +} + +fn get_case_method(segment_ident_str: &str) -> Option<CaseMethod> { + match segment_ident_str { + "to_lowercase" => Some(CaseMethod::LowerCase), + "to_ascii_lowercase" => Some(CaseMethod::AsciiLowerCase), + "to_uppercase" => Some(CaseMethod::UpperCase), + "to_ascii_uppercase" => Some(CaseMethod::AsciiUppercase), + _ => None, + } +} + +fn verify_case<'a>(case_method: &'a CaseMethod, arms: &'a [Arm<'_>]) -> Option<(Span, SymbolStr)> { + let case_check = match case_method { + CaseMethod::LowerCase => |input: &str| -> bool { input.chars().all(|c| c.to_lowercase().next() == Some(c)) }, + CaseMethod::AsciiLowerCase => |input: &str| -> bool { !input.chars().any(|c| c.is_ascii_uppercase()) }, + CaseMethod::UpperCase => |input: &str| -> bool { input.chars().all(|c| c.to_uppercase().next() == Some(c)) }, + CaseMethod::AsciiUppercase => |input: &str| -> bool { !input.chars().any(|c| c.is_ascii_lowercase()) }, + }; + + for arm in arms { + if_chain! { + if let PatKind::Lit(Expr { + kind: ExprKind::Lit(lit), + .. + }) = arm.pat.kind; + if let LitKind::Str(symbol, _) = lit.node; + let input = symbol.as_str(); + if !case_check(&input); + then { + return Some((lit.span, input)); + } + } + } + + None +} + +fn lint(cx: &LateContext<'_>, case_method: &CaseMethod, bad_case_span: Span, bad_case_str: &str) { + let (method_str, suggestion) = match case_method { + CaseMethod::LowerCase => ("to_lowercase", bad_case_str.to_lowercase()), + CaseMethod::AsciiLowerCase => ("to_ascii_lowercase", bad_case_str.to_ascii_lowercase()), + CaseMethod::UpperCase => ("to_uppercase", bad_case_str.to_uppercase()), + CaseMethod::AsciiUppercase => ("to_ascii_uppercase", bad_case_str.to_ascii_uppercase()), + }; + + span_lint_and_sugg( + cx, + MATCH_STR_CASE_MISMATCH, + bad_case_span, + "this `match` arm has a differing case than its expression", + &*format!("consider changing the case of this arm to respect `{}`", method_str), + format!("\"{}\"", suggestion), + Applicability::MachineApplicable, + ); +} diff --git a/src/tools/clippy/clippy_lints/src/matches.rs b/src/tools/clippy/clippy_lints/src/matches.rs index 56d4163a6b..7142df98c3 100644 --- a/src/tools/clippy/clippy_lints/src/matches.rs +++ b/src/tools/clippy/clippy_lints/src/matches.rs @@ -1,4 +1,4 @@ -use clippy_utils::consts::{constant, miri_to_const, Constant}; +use clippy_utils::consts::{constant, constant_full_int, miri_to_const, FullInt}; use clippy_utils::diagnostics::{ multispan_sugg, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then, }; @@ -930,9 +930,8 @@ fn check_match_bool(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: fn check_overlapping_arms<'tcx>(cx: &LateContext<'tcx>, ex: &'tcx Expr<'_>, arms: &'tcx [Arm<'_>]) { if arms.len() >= 2 && cx.typeck_results().expr_ty(ex).is_integral() { let ranges = all_ranges(cx, arms, cx.typeck_results().expr_ty(ex)); - let type_ranges = type_ranges(&ranges); - if !type_ranges.is_empty() { - if let Some((start, end)) = overlapping(&type_ranges) { + if !ranges.is_empty() { + if let Some((start, end)) = overlapping(&ranges) { span_lint_and_note( cx, MATCH_OVERLAPPING_ARM, @@ -968,8 +967,7 @@ fn check_wild_err_arm<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm } if_chain! { if matching_wild; - if let ExprKind::Block(block, _) = arm.body.kind; - if is_panic_block(block); + if is_panic_call(arm.body); then { // `Err(_)` or `Err(_e)` arm with `panic!` found span_lint_and_note(cx, @@ -1067,7 +1065,10 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) 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( + DefKind::Const | DefKind::ConstParam | DefKind::AnonConst | DefKind::InlineConst, + _, + ) => return, Res::Def(_, id) => id, _ => return, }; @@ -1172,14 +1173,19 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) } // 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(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() - }, - _ => false, - } +fn is_panic_call(expr: &Expr<'_>) -> bool { + // Unwrap any wrapping blocks + let span = if let ExprKind::Block(block, _) = expr.kind { + match (&block.expr, block.stmts.len(), block.stmts.first()) { + (&Some(exp), 0, _) => exp.span, + (&None, 1, Some(stmt)) => stmt.span, + _ => return false, + } + } else { + expr.span + }; + + is_expn_of(span, "panic").is_some() && is_expn_of(span, "unreachable").is_none() } fn check_match_ref_pats<'a, 'b, I>(cx: &LateContext<'_>, ex: &Expr<'_>, pats: I, expr: &Expr<'_>) @@ -1187,7 +1193,7 @@ where 'b: 'a, I: Clone + Iterator<Item = &'a Pat<'b>>, { - if !has_only_ref_pats(pats.clone()) { + if !has_multiple_ref_pats(pats.clone()) { return; } @@ -1601,7 +1607,7 @@ 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>> { +fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>) -> Vec<SpannedRange<FullInt>> { arms.iter() .filter_map(|arm| { if let Arm { pat, guard: None, .. } = *arm { @@ -1614,21 +1620,25 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>) Some(rhs) => constant(cx, cx.typeck_results(), rhs)?.0, None => miri_to_const(ty.numeric_max_val(cx.tcx)?)?, }; - let rhs = match range_end { - RangeEnd::Included => Bound::Included(rhs), - RangeEnd::Excluded => Bound::Excluded(rhs), + + let lhs_val = lhs.int_value(cx, ty)?; + let rhs_val = rhs.int_value(cx, ty)?; + + let rhs_bound = match range_end { + RangeEnd::Included => Bound::Included(rhs_val), + RangeEnd::Excluded => Bound::Excluded(rhs_val), }; return Some(SpannedRange { span: pat.span, - node: (lhs, rhs), + node: (lhs_val, rhs_bound), }); } if let PatKind::Lit(value) = pat.kind { - let value = constant(cx, cx.typeck_results(), value)?.0; + let value = constant_full_int(cx, cx.typeck_results(), value)?; return Some(SpannedRange { span: pat.span, - node: (value.clone(), Bound::Included(value)), + node: (value, Bound::Included(value)), }); } } @@ -1643,32 +1653,6 @@ pub struct SpannedRange<T> { pub node: (T, Bound<T>), } -type TypedRanges = Vec<SpannedRange<u128>>; - -/// Gets all `Int` ranges or all `Uint` ranges. Mixed types are an error anyway -/// and other types than -/// `Uint` and `Int` probably don't make sense. -fn type_ranges(ranges: &[SpannedRange<Constant>]) -> TypedRanges { - ranges - .iter() - .filter_map(|range| match range.node { - (Constant::Int(start), Bound::Included(Constant::Int(end))) => Some(SpannedRange { - span: range.span, - node: (start, Bound::Included(end)), - }), - (Constant::Int(start), Bound::Excluded(Constant::Int(end))) => Some(SpannedRange { - span: range.span, - node: (start, Bound::Excluded(end)), - }), - (Constant::Int(start), Bound::Unbounded) => Some(SpannedRange { - span: range.span, - node: (start, Bound::Unbounded), - }), - _ => None, - }) - .collect() -} - // Checks if arm has the form `None => 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)) @@ -1693,12 +1677,12 @@ fn is_ref_some_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> Option<BindingAnnotat None } -fn has_only_ref_pats<'a, 'b, I>(pats: I) -> bool +fn has_multiple_ref_pats<'a, 'b, I>(pats: I) -> bool where 'b: 'a, I: Iterator<Item = &'a Pat<'b>>, { - let mut at_least_one_is_true = false; + let mut ref_count = 0; for opt in pats.map(|pat| match pat.kind { PatKind::Ref(..) => Some(true), // &-patterns PatKind::Wild => Some(false), // an "anything" wildcard is also fine @@ -1706,13 +1690,13 @@ where }) { if let Some(inner) = opt { if inner { - at_least_one_is_true = true; + ref_count += 1; } } else { return false; } } - at_least_one_is_true + ref_count > 1 } pub fn overlapping<T>(ranges: &[SpannedRange<T>]) -> Option<(&SpannedRange<T>, &SpannedRange<T>)> diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index b26d11c0d6..26c29fbb28 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -1777,14 +1777,13 @@ declare_clippy_lint! { } declare_clippy_lint! { - /// **What it does:** Checks for usages of `str::splitn(2, _)` - /// - /// **Why is this bad?** `split_once` is both clearer in intent and slightly more efficient. - /// - /// **Known problems:** None. + /// ### What it does + /// Checks for usages of `str::splitn(2, _)` /// - /// **Example:** + /// ### Why is this bad? + /// `split_once` is both clearer in intent and slightly more efficient. /// + /// ### Example /// ```rust,ignore /// // Bad /// let (key, value) = _.splitn(2, '=').next_tuple()?; 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 1a5894e48d..ce89189bce 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,9 +1,8 @@ use clippy_utils::diagnostics::span_lint; -use clippy_utils::{is_expr_path_def_path, match_def_path, paths}; +use clippy_utils::{is_expr_path_def_path, paths, ty::is_uninit_value_valid_for_ty}; use if_chain::if_chain; use rustc_hir as hir; use rustc_lint::LateContext; -use rustc_middle::ty::{self, Ty}; use super::UNINIT_ASSUMED_INIT; @@ -13,7 +12,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr if let hir::ExprKind::Call(callee, args) = recv.kind; if args.is_empty(); 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)); + if !is_uninit_value_valid_for_ty(cx, cx.typeck_results().expr_ty_adjusted(expr)); then { span_lint( cx, @@ -24,12 +23,3 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr } } } - -fn is_maybe_uninit_ty_valid(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { - match ty.kind() { - 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/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs index 0f32cd9164..78183add9c 100644 --- a/src/tools/clippy/clippy_lints/src/misc.rs +++ b/src/tools/clippy/clippy_lints/src/misc.rs @@ -20,8 +20,8 @@ use rustc_span::symbol::sym; use clippy_utils::consts::{constant, Constant}; 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, + expr_path_res, get_item_name, get_parent_expr, 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! { @@ -312,7 +312,6 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints { if let StmtKind::Local(local) = stmt.kind; if let PatKind::Binding(an, .., name, None) = local.pat.kind; if let Some(init) = local.init; - if !higher::is_from_for_desugar(local); if an == BindingAnnotation::Ref || an == BindingAnnotation::RefMut; then { // use the macro callsite when the init span (but not the whole local span) diff --git a/src/tools/clippy/clippy_lints/src/misc_early/double_neg.rs b/src/tools/clippy/clippy_lints/src/misc_early/double_neg.rs index 6f65778e11..06ba968fa4 100644 --- a/src/tools/clippy/clippy_lints/src/misc_early/double_neg.rs +++ b/src/tools/clippy/clippy_lints/src/misc_early/double_neg.rs @@ -1,4 +1,3 @@ -use super::MiscEarlyLints; use clippy_utils::diagnostics::span_lint; use rustc_ast::ast::{Expr, ExprKind, UnOp}; use rustc_lint::EarlyContext; @@ -6,18 +5,14 @@ use rustc_lint::EarlyContext; use super::DOUBLE_NEG; pub(super) fn check(cx: &EarlyContext<'_>, expr: &Expr) { - match expr.kind { - ExprKind::Unary(UnOp::Neg, ref inner) => { - if let ExprKind::Unary(UnOp::Neg, _) = inner.kind { - span_lint( - cx, - DOUBLE_NEG, - expr.span, - "`--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op", - ); - } - }, - ExprKind::Lit(ref lit) => MiscEarlyLints::check_lit(cx, lit), - _ => (), + if let ExprKind::Unary(UnOp::Neg, ref inner) = expr.kind { + if let ExprKind::Unary(UnOp::Neg, _) = inner.kind { + span_lint( + cx, + DOUBLE_NEG, + expr.span, + "`--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op", + ); + } } } diff --git a/src/tools/clippy/clippy_lints/src/misc_early/literal_suffix.rs b/src/tools/clippy/clippy_lints/src/misc_early/literal_suffix.rs new file mode 100644 index 0000000000..1165c19a0c --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/misc_early/literal_suffix.rs @@ -0,0 +1,38 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use rustc_ast::ast::Lit; +use rustc_errors::Applicability; +use rustc_lint::EarlyContext; + +use super::{SEPARATED_LITERAL_SUFFIX, UNSEPARATED_LITERAL_SUFFIX}; + +pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, lit_snip: &str, suffix: &str, sugg_type: &str) { + let maybe_last_sep_idx = if let Some(val) = lit_snip.len().checked_sub(suffix.len() + 1) { + val + } else { + return; // It's useless so shouldn't lint. + }; + // Do not lint when literal is unsuffixed. + if !suffix.is_empty() { + if lit_snip.as_bytes()[maybe_last_sep_idx] == b'_' { + span_lint_and_sugg( + cx, + SEPARATED_LITERAL_SUFFIX, + lit.span, + &format!("{} type suffix should not be separated by an underscore", sugg_type), + "remove the underscore", + format!("{}{}", &lit_snip[..maybe_last_sep_idx], suffix), + Applicability::MachineApplicable, + ); + } else { + span_lint_and_sugg( + cx, + UNSEPARATED_LITERAL_SUFFIX, + lit.span, + &format!("{} type suffix should be separated by an underscore", sugg_type), + "add an underscore", + format!("{}_{}", &lit_snip[..=maybe_last_sep_idx], suffix), + Applicability::MachineApplicable, + ); + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/misc_early/mod.rs b/src/tools/clippy/clippy_lints/src/misc_early/mod.rs index b32feab4ee..7c3f5f22ad 100644 --- a/src/tools/clippy/clippy_lints/src/misc_early/mod.rs +++ b/src/tools/clippy/clippy_lints/src/misc_early/mod.rs @@ -1,15 +1,15 @@ mod builtin_type_shadow; mod double_neg; +mod literal_suffix; mod mixed_case_hex_literals; mod redundant_pattern; mod unneeded_field_pattern; mod unneeded_wildcard_pattern; -mod unseparated_literal_suffix; mod zero_prefixed_literal; use clippy_utils::diagnostics::span_lint; use clippy_utils::source::snippet_opt; -use rustc_ast::ast::{Expr, Generics, Lit, LitFloatType, LitIntType, LitKind, NodeId, Pat, PatKind}; +use rustc_ast::ast::{Expr, ExprKind, Generics, Lit, LitFloatType, LitIntType, LitKind, NodeId, Pat, PatKind}; use rustc_ast::visit::FnKind; use rustc_data_structures::fx::FxHashMap; use rustc_lint::{EarlyContext, EarlyLintPass}; @@ -115,9 +115,11 @@ declare_clippy_lint! { /// ### What it does /// Warns if literal suffixes are not separated by an /// underscore. + /// To enforce unseparated literal suffix style, + /// see the `separated_literal_suffix` lint. /// /// ### Why is this bad? - /// It is much less readable. + /// Suffix style should be consistent. /// /// ### Example /// ```rust @@ -128,10 +130,32 @@ declare_clippy_lint! { /// let y = 123832_i32; /// ``` pub UNSEPARATED_LITERAL_SUFFIX, - pedantic, + restriction, "literals whose suffix is not separated by an underscore" } +declare_clippy_lint! { + /// ### What it does + /// Warns if literal suffixes are separated by an underscore. + /// To enforce separated literal suffix style, + /// see the `unseparated_literal_suffix` lint. + /// + /// ### Why is this bad? + /// Suffix style should be consistent. + /// + /// ### Example + /// ```rust + /// // Bad + /// let y = 123832_i32; + /// + /// // Good + /// let y = 123832i32; + /// ``` + pub SEPARATED_LITERAL_SUFFIX, + restriction, + "literals whose suffix is separated by an underscore" +} + declare_clippy_lint! { /// ### What it does /// Warns if an integral constant literal starts with `0`. @@ -260,6 +284,7 @@ declare_lint_pass!(MiscEarlyLints => [ DOUBLE_NEG, MIXED_CASE_HEX_LITERALS, UNSEPARATED_LITERAL_SUFFIX, + SEPARATED_LITERAL_SUFFIX, ZERO_PREFIXED_LITERAL, BUILTIN_TYPE_SHADOW, REDUNDANT_PATTERN, @@ -310,6 +335,10 @@ impl EarlyLintPass for MiscEarlyLints { if in_external_macro(cx.sess, expr.span) { return; } + + if let ExprKind::Lit(ref lit) = expr.kind { + MiscEarlyLints::check_lit(cx, lit); + } double_neg::check(cx, expr); } } @@ -332,7 +361,7 @@ impl MiscEarlyLints { LitIntType::Unsigned(ty) => ty.name_str(), LitIntType::Unsuffixed => "", }; - unseparated_literal_suffix::check(cx, lit, &lit_snip, suffix, "integer"); + literal_suffix::check(cx, lit, &lit_snip, suffix, "integer"); if lit_snip.starts_with("0x") { mixed_case_hex_literals::check(cx, lit, suffix, &lit_snip); } else if lit_snip.starts_with("0b") || lit_snip.starts_with("0o") { @@ -342,7 +371,7 @@ impl MiscEarlyLints { } } else if let LitKind::Float(_, LitFloatType::Suffixed(float_ty)) = lit.kind { let suffix = float_ty.name_str(); - unseparated_literal_suffix::check(cx, lit, &lit_snip, suffix, "float"); + literal_suffix::check(cx, lit, &lit_snip, suffix, "float"); } } } diff --git a/src/tools/clippy/clippy_lints/src/misc_early/unseparated_literal_suffix.rs b/src/tools/clippy/clippy_lints/src/misc_early/unseparated_literal_suffix.rs deleted file mode 100644 index 2018aa6184..0000000000 --- a/src/tools/clippy/clippy_lints/src/misc_early/unseparated_literal_suffix.rs +++ /dev/null @@ -1,26 +0,0 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; -use rustc_ast::ast::Lit; -use rustc_errors::Applicability; -use rustc_lint::EarlyContext; - -use super::UNSEPARATED_LITERAL_SUFFIX; - -pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, lit_snip: &str, suffix: &str, sugg_type: &str) { - let maybe_last_sep_idx = if let Some(val) = lit_snip.len().checked_sub(suffix.len() + 1) { - val - } else { - return; // It's useless so shouldn't lint. - }; - // Do not lint when literal is unsuffixed. - if !suffix.is_empty() && lit_snip.as_bytes()[maybe_last_sep_idx] != b'_' { - span_lint_and_sugg( - cx, - UNSEPARATED_LITERAL_SUFFIX, - lit.span, - &format!("{} type suffix should be separated by an underscore", sugg_type), - "add an underscore", - format!("{}_{}", &lit_snip[..=maybe_last_sep_idx], suffix), - Applicability::MachineApplicable, - ); - } -} diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs index 667cdd8302..b593c74749 100644 --- a/src/tools/clippy/clippy_lints/src/missing_inline.rs +++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs @@ -8,7 +8,7 @@ use rustc_span::sym; declare_clippy_lint! { /// ### What it does - /// it lints if an exported function, method, trait method with default impl, + /// It lints if an exported function, method, trait method with default impl, /// or trait method impl is not `#[inline]`. /// /// ### Why is this bad? diff --git a/src/tools/clippy/clippy_lints/src/mut_mut.rs b/src/tools/clippy/clippy_lints/src/mut_mut.rs index 610152a217..7c4cac29ba 100644 --- a/src/tools/clippy/clippy_lints/src/mut_mut.rs +++ b/src/tools/clippy/clippy_lints/src/mut_mut.rs @@ -82,6 +82,10 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> { } fn visit_ty(&mut self, ty: &'tcx hir::Ty<'_>) { + if in_external_macro(self.cx.sess(), ty.span) { + return; + } + if let hir::TyKind::Rptr( _, hir::MutTy { diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs index c5a5cde4b1..6dae8f3204 100644 --- a/src/tools/clippy/clippy_lints/src/no_effect.rs +++ b/src/tools/clippy/clippy_lints/src/no_effect.rs @@ -1,9 +1,10 @@ use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then}; +use clippy_utils::is_lint_allowed; 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::{is_range_literal, BinOpKind, BlockCheckMode, Expr, ExprKind, Stmt, StmtKind, UnsafeSource}; +use rustc_hir::{is_range_literal, BinOpKind, BlockCheckMode, Expr, ExprKind, PatKind, Stmt, StmtKind, UnsafeSource}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use std::ops::Deref; @@ -13,7 +14,7 @@ declare_clippy_lint! { /// Checks for statements which have no effect. /// /// ### Why is this bad? - /// Similar to dead code, these statements are actually + /// Unlike dead code, these statements are actually /// executed. However, as they have no effect, all they do is make the code less /// readable. /// @@ -26,6 +27,28 @@ declare_clippy_lint! { "statements with no effect" } +declare_clippy_lint! { + /// ### What it does + /// Checks for binding to underscore prefixed variable without side-effects. + /// + /// ### Why is this bad? + /// Unlike dead code, these bindings are actually + /// executed. However, as they have no effect and shouldn't be used further on, all they + /// do is make the code less readable. + /// + /// ### Known problems + /// Further usage of this variable is not checked, which can lead to false positives if it is + /// used later in the code. + /// + /// ### Example + /// ```rust,ignore + /// let _i_serve_no_purpose = 1; + /// ``` + pub NO_EFFECT_UNDERSCORE_BINDING, + pedantic, + "binding to `_` prefixed variable with no side-effect" +} + declare_clippy_lint! { /// ### What it does /// Checks for expression statements that can be reduced to a @@ -44,6 +67,46 @@ declare_clippy_lint! { "outer expressions with no effect" } +declare_lint_pass!(NoEffect => [NO_EFFECT, UNNECESSARY_OPERATION, NO_EFFECT_UNDERSCORE_BINDING]); + +impl<'tcx> LateLintPass<'tcx> for NoEffect { + fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { + if check_no_effect(cx, stmt) { + return; + } + check_unnecessary_operation(cx, stmt); + } +} + +fn check_no_effect(cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) -> bool { + if let StmtKind::Semi(expr) = stmt.kind { + if has_no_effect(cx, expr) { + span_lint_hir(cx, NO_EFFECT, expr.hir_id, stmt.span, "statement with no effect"); + return true; + } + } else if let StmtKind::Local(local) = stmt.kind { + if_chain! { + if !is_lint_allowed(cx, NO_EFFECT_UNDERSCORE_BINDING, local.hir_id); + if let Some(init) = local.init; + if !local.pat.span.from_expansion(); + if has_no_effect(cx, init); + if let PatKind::Binding(_, _, ident, _) = local.pat.kind; + if ident.name.to_ident_string().starts_with('_'); + then { + span_lint_hir( + cx, + NO_EFFECT_UNDERSCORE_BINDING, + init.hir_id, + stmt.span, + "binding to `_` prefixed variable with no side-effect" + ); + return true; + } + } + } + false +} + fn has_no_effect(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { if expr.span.from_expansion() { return false; @@ -88,71 +151,59 @@ fn has_no_effect(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { } } -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(expr) = stmt.kind { - if has_no_effect(cx, expr) { - span_lint_hir(cx, NO_EFFECT, expr.hir_id, stmt.span, "statement with no effect"); - } else if let Some(reduced) = reduce_expression(cx, expr) { - for e in &reduced { - if e.span.from_expansion() { - return; - } - } - if let ExprKind::Index(..) = &expr.kind { - let snippet; - if_chain! { - if let Some(arr) = snippet_opt(cx, reduced[0].span); - if let Some(func) = snippet_opt(cx, reduced[1].span); - then { - snippet = format!("assert!({}.len() > {});", &arr, &func); - } else { - return; - } - } - span_lint_hir_and_then( - cx, - UNNECESSARY_OPERATION, - expr.hir_id, - stmt.span, - "unnecessary operation", - |diag| { - diag.span_suggestion( - stmt.span, - "statement can be written as", - snippet, - Applicability::MaybeIncorrect, - ); - }, - ); +fn check_unnecessary_operation(cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { + if_chain! { + if let StmtKind::Semi(expr) = stmt.kind; + if let Some(reduced) = reduce_expression(cx, expr); + if !&reduced.iter().any(|e| e.span.from_expansion()); + then { + if let ExprKind::Index(..) = &expr.kind { + let snippet; + if let (Some(arr), Some(func)) = (snippet_opt(cx, reduced[0].span), snippet_opt(cx, reduced[1].span)) { + snippet = format!("assert!({}.len() > {});", &arr, &func); } else { - let mut snippet = String::new(); - for e in reduced { - if let Some(snip) = snippet_opt(cx, e.span) { - snippet.push_str(&snip); - snippet.push(';'); - } else { - return; - } + return; + } + span_lint_hir_and_then( + cx, + UNNECESSARY_OPERATION, + expr.hir_id, + stmt.span, + "unnecessary operation", + |diag| { + diag.span_suggestion( + stmt.span, + "statement can be written as", + snippet, + Applicability::MaybeIncorrect, + ); + }, + ); + } else { + let mut snippet = String::new(); + for e in reduced { + if let Some(snip) = snippet_opt(cx, e.span) { + snippet.push_str(&snip); + snippet.push(';'); + } else { + return; } - span_lint_hir_and_then( - cx, - UNNECESSARY_OPERATION, - expr.hir_id, - stmt.span, - "unnecessary operation", - |diag| { - diag.span_suggestion( - stmt.span, - "statement can be reduced to", - snippet, - Applicability::MachineApplicable, - ); - }, - ); } + span_lint_hir_and_then( + cx, + UNNECESSARY_OPERATION, + expr.hir_id, + stmt.span, + "unnecessary operation", + |diag| { + diag.span_suggestion( + stmt.span, + "statement can be reduced to", + snippet, + Applicability::MachineApplicable, + ); + }, + ); } } } 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 5b254bc813..e28cc49bf2 100644 --- a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs +++ b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs @@ -1,6 +1,6 @@ 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, + self, Arm, AssocItem, AssocItemKind, Attribute, Block, FnDecl, Item, ItemKind, Local, Pat, PatKind, }; use rustc_ast::visit::{walk_block, walk_expr, walk_pat, Visitor}; use rustc_lint::{EarlyContext, EarlyLintPass}; @@ -357,7 +357,7 @@ impl EarlyLintPass for NonExpressiveNames { return; } - if let ItemKind::Fn(box FnKind(_, ref sig, _, Some(ref blk))) = item.kind { + if let ItemKind::Fn(box ast::Fn { ref sig, body: Some(ref blk), .. }) = item.kind { do_check(self, cx, &item.attrs, &sig.decl, blk); } } @@ -367,7 +367,7 @@ impl EarlyLintPass for NonExpressiveNames { return; } - if let AssocItemKind::Fn(box FnKind(_, ref sig, _, Some(ref blk))) = item.kind { + if let AssocItemKind::Fn(box ast::Fn { ref sig, body: Some(ref blk), .. }) = item.kind { do_check(self, cx, &item.attrs, &sig.decl, blk); } } 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 a62eb06998..cbe1c5d44d 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 @@ -22,7 +22,7 @@ declare_clippy_lint! { /// expression). /// /// ### Why is this bad? - /// Using the dedicated functions of the Option type is clearer and + /// Using the dedicated functions of the `Option` type is clearer and /// more concise than an `if let` expression. /// /// ### Known problems 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 e7bc244659..018e6d611d 100644 --- a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs +++ b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs @@ -1,16 +1,12 @@ use clippy_utils::diagnostics::span_lint_and_help; -use clippy_utils::last_path_segment; use rustc_hir::{ - intravisit, Body, Expr, ExprKind, FnDecl, HirId, LocalSource, MatchSource, Mutability, Pat, PatField, PatKind, - QPath, Stmt, StmtKind, + intravisit, Body, Expr, ExprKind, FnDecl, HirId, LocalSource, Mutability, Pat, PatKind, Stmt, StmtKind, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_middle::ty::subst::SubstsRef; -use rustc_middle::ty::{AdtDef, FieldDef, Ty, TyKind, VariantDef}; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -use std::iter; declare_clippy_lint! { /// ### What it does @@ -87,43 +83,28 @@ 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(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; - if in_external_macro(cx.sess(), pat.span) { - return; - } - let deref_possible = match local.source { - LocalSource::Normal => DerefPossible::Possible, - _ => DerefPossible::Impossible, - }; - apply_lint(cx, pat, init_ty, deref_possible); - } + if in_external_macro(cx.sess(), local.pat.span) { + return; } + let deref_possible = match local.source { + LocalSource::Normal => DerefPossible::Possible, + _ => DerefPossible::Impossible, + }; + apply_lint(cx, local.pat, deref_possible); } } fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let ExprKind::Match(scrutinee, arms, MatchSource::Normal) = expr.kind { - if let Some(expr_ty) = cx.typeck_results().node_type_opt(scrutinee.hir_id) { - 'pattern_checks: for arm in arms { - let pat = &arm.pat; - if in_external_macro(cx.sess(), pat.span) { - continue 'pattern_checks; - } - if apply_lint(cx, pat, expr_ty, DerefPossible::Possible) { - break 'pattern_checks; - } + if let ExprKind::Match(_, arms, _) = expr.kind { + for arm in arms { + let pat = &arm.pat; + if apply_lint(cx, pat, DerefPossible::Possible) { + break; } } } - if let ExprKind::Let(let_pat, let_expr, _) = expr.kind { - if let Some(expr_ty) = cx.typeck_results().node_type_opt(let_expr.hir_id) { - if in_external_macro(cx.sess(), let_pat.span) { - return; - } - apply_lint(cx, let_pat, expr_ty, DerefPossible::Possible); - } + if let ExprKind::Let(let_pat, ..) = expr.kind { + apply_lint(cx, let_pat, DerefPossible::Possible); } } @@ -134,12 +115,10 @@ impl<'tcx> LateLintPass<'tcx> for PatternTypeMismatch { _: &'tcx FnDecl<'_>, body: &'tcx Body<'_>, _: Span, - hir_id: HirId, + _: HirId, ) { - if let Some(fn_sig) = cx.typeck_results().liberated_fn_sigs().get(hir_id) { - for (param, ty) in iter::zip(body.params, fn_sig.inputs()) { - apply_lint(cx, param.pat, ty, DerefPossible::Impossible); - } + for param in body.params { + apply_lint(cx, param.pat, DerefPossible::Impossible); } } } @@ -150,8 +129,8 @@ enum DerefPossible { Impossible, } -fn apply_lint<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'_>, expr_ty: Ty<'tcx>, deref_possible: DerefPossible) -> bool { - let maybe_mismatch = find_first_mismatch(cx, pat, expr_ty, Level::Top); +fn apply_lint<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'_>, deref_possible: DerefPossible) -> bool { + let maybe_mismatch = find_first_mismatch(cx, pat); if let Some((span, mutability, level)) = maybe_mismatch { span_lint_and_help( cx, @@ -184,132 +163,32 @@ enum Level { } #[allow(rustc::usage_of_ty_tykind)] -fn find_first_mismatch<'tcx>( - cx: &LateContext<'tcx>, - pat: &Pat<'_>, - ty: Ty<'tcx>, - level: Level, -) -> Option<(Span, Mutability, Level)> { - 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); - } - } - - if let TyKind::Ref(_, _, mutability) = *ty.kind() { - if is_non_ref_pattern(&pat.kind) { - return Some((pat.span, mutability, level)); - } - } - - 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); - } +fn find_first_mismatch<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'_>) -> Option<(Span, Mutability, Level)> { + let mut result = None; + pat.walk(|p| { + if result.is_some() { + return false; } - } - - 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)); - return find_first_mismatch_in_tuple(cx, pats, ty_iter); - } - } - } - - if let PatKind::Tuple(pats, _) = pat.kind { - if let TyKind::Tuple(..) = ty.kind() { - return find_first_mismatch_in_tuple(cx, pats, ty.tuple_fields()); + if in_external_macro(cx.sess(), p.span) { + return true; } - } - - if let PatKind::Or(sub_pats) = pat.kind { - for pat in sub_pats { - let maybe_mismatch = find_first_mismatch(cx, pat, ty, level); - if let Some(mismatch) = maybe_mismatch { - return Some(mismatch); - } - } - } - - None -} - -fn get_variant<'a>(adt_def: &'a AdtDef, qpath: &QPath<'_>) -> Option<&'a VariantDef> { - if adt_def.is_struct() { - if let Some(variant) = adt_def.variants.iter().next() { - return Some(variant); - } - } - - if adt_def.is_enum() { - let pat_ident = last_path_segment(qpath).ident; - for variant in &adt_def.variants { - if variant.ident == pat_ident { - return Some(variant); - } - } - } - - None -} - -fn find_first_mismatch_in_tuple<'tcx, I>( - cx: &LateContext<'tcx>, - pats: &[Pat<'_>], - ty_iter_src: I, -) -> Option<(Span, Mutability, Level)> -where - I: IntoIterator<Item = Ty<'tcx>>, -{ - let mut field_tys = ty_iter_src.into_iter(); - 'fields: for pat in pats { - let field_ty = if let Some(ty) = field_tys.next() { - ty - } else { - break 'fields; + let adjust_pat = match p.kind { + PatKind::Or([p, ..]) => p, + _ => p, }; - - let maybe_mismatch = find_first_mismatch(cx, pat, field_ty, Level::Lower); - if let Some(mismatch) = maybe_mismatch { - return Some(mismatch); - } - } - - None -} - -fn find_first_mismatch_in_struct<'tcx>( - cx: &LateContext<'tcx>, - field_pats: &[PatField<'_>], - field_defs: &[FieldDef], - substs_ref: SubstsRef<'tcx>, -) -> Option<(Span, Mutability, Level)> { - for field_pat in field_pats { - 'definitions: for field_def in field_defs { - if field_pat.ident == field_def.ident { - let field_ty = field_def.ty(cx.tcx, substs_ref); - let pat = &field_pat.pat; - let maybe_mismatch = find_first_mismatch(cx, pat, field_ty, Level::Lower); - if let Some(mismatch) = maybe_mismatch { - return Some(mismatch); + if let Some(adjustments) = cx.typeck_results().pat_adjustments().get(adjust_pat.hir_id) { + if let [first, ..] = **adjustments { + if let ty::Ref(.., mutability) = *first.kind() { + let level = if p.hir_id == pat.hir_id { + Level::Top + } else { + Level::Lower + }; + result = Some((p.span, mutability, level)); } - break 'definitions; } } - } - - None -} - -fn is_non_ref_pattern(pat_kind: &PatKind<'_>) -> bool { - match pat_kind { - PatKind::Struct(..) | PatKind::Tuple(..) | PatKind::TupleStruct(..) | PatKind::Path(..) => true, - PatKind::Or(sub_pats) => sub_pats.iter().any(|pat| is_non_ref_pattern(&pat.kind)), - _ => false, - } + result.is_none() + }); + result } diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index d180d6f922..8a36e20fc9 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -3,16 +3,16 @@ 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::ty::walk_ptrs_hir_ty; use clippy_utils::{expr_path_res, is_lint_allowed, match_any_diagnostic_items, paths}; use if_chain::if_chain; use rustc_errors::Applicability; +use rustc_hir::def::Res; use rustc_hir::{ - BinOpKind, BodyId, Expr, ExprKind, FnDecl, FnRetTy, GenericArg, HirId, Impl, ImplItem, ImplItemKind, Item, - ItemKind, Lifetime, MutTy, Mutability, Node, PathSegment, QPath, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, + BinOpKind, BodyId, Expr, ExprKind, FnDecl, FnRetTy, GenericArg, Impl, ImplItem, ImplItemKind, Item, ItemKind, + Lifetime, MutTy, Mutability, Node, PathSegment, QPath, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, }; 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; @@ -139,6 +139,7 @@ declare_clippy_lint! { /// unsafe { std::slice::from_raw_parts(ptr::null(), 0); } /// ``` /// + /// ```ignore /// // Good /// unsafe { std::slice::from_raw_parts(NonNull::dangling().as_ptr(), 0); } /// ``` @@ -152,7 +153,7 @@ declare_lint_pass!(Ptr => [PTR_ARG, CMP_NULL, MUT_FROM_REF, INVALID_NULL_PTR_USA 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, Some(body_id)); } } @@ -164,7 +165,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, Some(body_id)); } } @@ -175,7 +176,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { } else { None }; - check_fn(cx, sig.decl, item.hir_id(), body_id); + check_fn(cx, sig.decl, body_id); } } @@ -243,13 +244,10 @@ fn check_invalid_ptr_usage<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { } #[allow(clippy::too_many_lines)] -fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id: Option<BodyId>) { - let fn_def_id = cx.tcx.hir().local_def_id(fn_id); - let sig = cx.tcx.fn_sig(fn_def_id); - let fn_ty = sig.skip_binder(); +fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, opt_body_id: Option<BodyId>) { let body = opt_body_id.map(|id| cx.tcx.hir().body(id)); - for (idx, (arg, ty)) in decl.inputs.iter().zip(fn_ty.inputs()).enumerate() { + for (idx, arg) in decl.inputs.iter().enumerate() { // Honor the allow attribute on parameters. See issue 5644. if let Some(body) = &body { if is_lint_allowed(cx, PTR_ARG, body.params[idx].hir_id) { @@ -257,8 +255,20 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id: } } - if let ty::Ref(_, ty, Mutability::Not) = ty.kind() { - if is_type_diagnostic_item(cx, ty, sym::Vec) { + let (item_name, path) = if_chain! { + if let TyKind::Rptr(_, MutTy { ty, mutbl: Mutability::Not }) = arg.kind; + if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind; + if let Res::Def(_, did) = path.res; + if let Some(item_name) = cx.tcx.get_diagnostic_name(did); + then { + (item_name, path) + } else { + continue + } + }; + + match item_name { + sym::Vec => { if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_owned()")]) { span_lint_and_then( cx, @@ -288,7 +298,8 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id: }, ); } - } else if is_type_diagnostic_item(cx, ty, sym::String) { + }, + sym::String => { if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_string()"), ("as_str", "")]) { span_lint_and_then( cx, @@ -310,7 +321,8 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id: }, ); } - } else if is_type_diagnostic_item(cx, ty, sym::PathBuf) { + }, + sym::PathBuf => { if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_path_buf()"), ("as_path", "")]) { span_lint_and_then( cx, @@ -337,11 +349,10 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id: }, ); } - } else if match_type(cx, ty, &paths::COW) { + }, + sym::Cow => { if_chain! { - 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 [ref bx] = *path.segments; if let Some(params) = bx.args; if !params.parenthesized; if let Some(inner) = params.args.iter().find_map(|arg| match arg { @@ -362,7 +373,8 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id: ); } } - } + }, + _ => {}, } } diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs index aa6d254e7a..f63ef163bc 100644 --- a/src/tools/clippy/clippy_lints/src/question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/question_mark.rs @@ -4,10 +4,10 @@ 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 clippy_utils::{eq_expr_value, path_to_local, path_to_local_id}; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::LangItem::{OptionNone, OptionSome}; +use rustc_hir::LangItem::{OptionNone, OptionSome, ResultOk}; use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, PatKind, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -48,16 +48,20 @@ impl QuestionMark { /// } /// ``` /// + /// ```ignore + /// if result.is_err() { + /// return result; + /// } + /// ``` + /// /// If it matches, it will suggest to use the question mark operator instead - fn check_is_none_and_early_return_none(cx: &LateContext<'_>, expr: &Expr<'_>) { + fn check_is_none_or_err_and_early_return(cx: &LateContext<'_>, expr: &Expr<'_>) { if_chain! { if let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr); if let ExprKind::MethodCall(segment, _, args, _) = &cond.kind; - if segment.ident.name == sym!(is_none); - if Self::expression_returns_none(cx, then); if let Some(subject) = args.get(0); - if Self::is_option(cx, subject); - + if (Self::option_check_and_early_return(cx, subject, then) && segment.ident.name == sym!(is_none)) || + (Self::result_check_and_early_return(cx, subject, then) && segment.ident.name == sym!(is_err)); then { let mut applicability = Applicability::MachineApplicable; let receiver_str = &Sugg::hir_with_applicability(cx, subject, "..", &mut applicability); @@ -95,31 +99,24 @@ impl QuestionMark { } } - fn check_if_let_some_and_early_return_none(cx: &LateContext<'_>, expr: &Expr<'_>) { + fn check_if_let_some_or_err_and_early_return(cx: &LateContext<'_>, expr: &Expr<'_>) { if_chain! { if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else: Some(if_else) }) = higher::IfLet::hir(cx, expr); - if Self::is_option(cx, let_expr); - if let PatKind::TupleStruct(ref path1, fields, None) = let_pat.kind; - if is_lang_ctor(cx, path1, OptionSome); + if (Self::option_check_and_early_return(cx, let_expr, if_else) && is_lang_ctor(cx, path1, OptionSome)) || + (Self::result_check_and_early_return(cx, let_expr, if_else) && is_lang_ctor(cx, path1, ResultOk)); + 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) = if_then.kind; if block.stmts.is_empty(); if let Some(trailing_expr) = &block.expr; if path_to_local_id(trailing_expr, bind_id); - - if Self::expression_returns_none(cx, if_else); then { let mut applicability = Applicability::MachineApplicable; let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability); - let replacement = format!( - "{}{}?", - receiver_str, - if by_ref { ".as_ref()" } else { "" }, - ); + let replacement = format!("{}{}?", receiver_str, if by_ref { ".as_ref()" } else { "" },); span_lint_and_sugg( cx, @@ -134,6 +131,14 @@ impl QuestionMark { } } + fn result_check_and_early_return(cx: &LateContext<'_>, expr: &Expr<'_>, nested_expr: &Expr<'_>) -> bool { + Self::is_result(cx, expr) && Self::expression_returns_unmodified_err(cx, nested_expr, expr) + } + + fn option_check_and_early_return(cx: &LateContext<'_>, expr: &Expr<'_>, nested_expr: &Expr<'_>) -> bool { + Self::is_option(cx, expr) && Self::expression_returns_none(cx, nested_expr) + } + fn moves_by_default(cx: &LateContext<'_>, expression: &Expr<'_>) -> bool { let expr_ty = cx.typeck_results().expr_ty(expression); @@ -146,6 +151,12 @@ impl QuestionMark { is_type_diagnostic_item(cx, expr_ty, sym::Option) } + fn is_result(cx: &LateContext<'_>, expression: &Expr<'_>) -> bool { + let expr_ty = cx.typeck_results().expr_ty(expression); + + is_type_diagnostic_item(cx, expr_ty, sym::Result) + } + fn expression_returns_none(cx: &LateContext<'_>, expression: &Expr<'_>) -> bool { match expression.kind { ExprKind::Block(block, _) => { @@ -161,6 +172,21 @@ impl QuestionMark { } } + fn expression_returns_unmodified_err(cx: &LateContext<'_>, expr: &Expr<'_>, cond_expr: &Expr<'_>) -> bool { + match expr.kind { + ExprKind::Block(block, _) => { + if let Some(return_expression) = Self::return_expression(block) { + return Self::expression_returns_unmodified_err(cx, return_expression, cond_expr); + } + + false + }, + ExprKind::Ret(Some(ret_expr)) => Self::expression_returns_unmodified_err(cx, ret_expr, cond_expr), + ExprKind::Path(_) => path_to_local(expr) == path_to_local(cond_expr), + _ => false, + } + } + fn return_expression<'tcx>(block: &Block<'tcx>) -> Option<&'tcx Expr<'tcx>> { // Check if last expression is a return statement. Then, return the expression if_chain! { @@ -189,7 +215,7 @@ impl QuestionMark { impl<'tcx> LateLintPass<'tcx> for QuestionMark { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - Self::check_is_none_and_early_return_none(cx, expr); - Self::check_if_let_some_and_early_return_none(cx, expr); + Self::check_is_none_or_err_and_early_return(cx, expr); + Self::check_if_let_some_or_err_and_early_return(cx, expr); } } 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 6966230156..c0e4914efe 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,7 +1,7 @@ use crate::rustc_lint::LintContext; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_macro_callsite; -use clippy_utils::{in_macro, sugg}; +use clippy_utils::sugg; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Block, ExprKind}; @@ -39,7 +39,7 @@ declare_lint_pass!(SemicolonIfNothingReturned => [SEMICOLON_IF_NOTHING_RETURNED] impl LateLintPass<'_> for SemicolonIfNothingReturned { fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) { if_chain! { - if !in_macro(block.span); + if !block.span.from_expansion(); if let Some(expr) = block.expr; let t_expr = cx.typeck_results().expr_ty(expr); if t_expr.is_unit(); diff --git a/src/tools/clippy/clippy_lints/src/shadow.rs b/src/tools/clippy/clippy_lints/src/shadow.rs index 2ca7c18800..64841f33cc 100644 --- a/src/tools/clippy/clippy_lints/src/shadow.rs +++ b/src/tools/clippy/clippy_lints/src/shadow.rs @@ -162,11 +162,7 @@ fn lint_shadow(cx: &LateContext<'_>, pat: &Pat<'_>, shadowed: HirId, span: Span) (SHADOW_SAME, msg) }, Some(expr) if is_local_used(cx, expr, shadowed) => { - let msg = format!( - "`{}` is shadowed by `{}` which reuses the original value", - snippet(cx, pat.span, "_"), - snippet(cx, expr.span, "..") - ); + let msg = format!("`{}` is shadowed", snippet(cx, pat.span, "_")); (SHADOW_REUSE, msg) }, _ => { diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs index 35b6bde569..6435107b8b 100644 --- a/src/tools/clippy/clippy_lints/src/strings.rs +++ b/src/tools/clippy/clippy_lints/src/strings.rs @@ -107,51 +107,87 @@ declare_clippy_lint! { "calling `as_bytes` on a string literal instead of using a byte string literal" } -declare_lint_pass!(StringAdd => [STRING_ADD, STRING_ADD_ASSIGN]); +declare_clippy_lint! { + /// ### What it does + /// Checks for slice operations on strings + /// + /// ### Why is this bad? + /// UTF-8 characters span multiple bytes, and it is easy to inadvertently confuse character + /// counts and string indices. This may lead to panics, and should warrant some test cases + /// containing wide UTF-8 characters. This lint is most useful in code that should avoid + /// panics at all costs. + /// + /// ### Known problems + /// Probably lots of false positives. If an index comes from a known valid position (e.g. + /// obtained via `char_indices` over the same string), it is totally OK. + /// + /// # Example + /// ```rust,should_panic + /// &"Ölkanne"[1..]; + /// ``` + pub STRING_SLICE, + restriction, + "slicing a string" +} + +declare_lint_pass!(StringAdd => [STRING_ADD, STRING_ADD_ASSIGN, STRING_SLICE]); impl<'tcx> LateLintPass<'tcx> for StringAdd { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if in_external_macro(cx.sess(), e.span) { return; } - - if let ExprKind::Binary( - Spanned { - node: BinOpKind::Add, .. - }, - left, - _, - ) = e.kind - { - if is_string(cx, left) { - if !is_lint_allowed(cx, STRING_ADD_ASSIGN, e.hir_id) { - let parent = get_parent_expr(cx, e); - if let Some(p) = parent { - if let ExprKind::Assign(target, _, _) = p.kind { - // avoid duplicate matches - if SpanlessEq::new(cx).eq_expr(target, left) { - return; + match e.kind { + ExprKind::Binary( + Spanned { + node: BinOpKind::Add, .. + }, + left, + _, + ) => { + if is_string(cx, left) { + if !is_lint_allowed(cx, STRING_ADD_ASSIGN, e.hir_id) { + let parent = get_parent_expr(cx, e); + if let Some(p) = parent { + if let ExprKind::Assign(target, _, _) = p.kind { + // avoid duplicate matches + if SpanlessEq::new(cx).eq_expr(target, left) { + return; + } } } } + span_lint( + cx, + STRING_ADD, + e.span, + "you added something to a string. Consider using `String::push_str()` instead", + ); } - span_lint( - cx, - STRING_ADD, - e.span, - "you added something to a string. Consider using `String::push_str()` instead", - ); - } - } else if let ExprKind::Assign(target, src, _) = e.kind { - if is_string(cx, target) && is_add(cx, src, target) { - span_lint( - cx, - STRING_ADD_ASSIGN, - e.span, - "you assigned the result of adding something to this string. Consider using \ - `String::push_str()` instead", - ); - } + }, + ExprKind::Assign(target, src, _) => { + if is_string(cx, target) && is_add(cx, src, target) { + span_lint( + cx, + STRING_ADD_ASSIGN, + e.span, + "you assigned the result of adding something to this string. Consider using \ + `String::push_str()` instead", + ); + } + }, + ExprKind::Index(target, _idx) => { + let e_ty = cx.typeck_results().expr_ty(target).peel_refs(); + if matches!(e_ty.kind(), ty::Str) || is_type_diagnostic_item(cx, e_ty, sym::String) { + span_lint( + cx, + STRING_SLICE, + e.span, + "indexing into a string may panic if the index is within a UTF-8 character", + ); + } + }, + _ => {}, } } } 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 44d5ff0b63..201aa06782 100644 --- a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs +++ b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs @@ -678,7 +678,7 @@ fn suggestion_with_swapped_ident( Some(format!( "{}{}{}", snippet_with_applicability(cx, expr.span.with_hi(current_ident.span.lo()), "..", applicability), - new_ident.to_string(), + new_ident, snippet_with_applicability(cx, expr.span.with_lo(current_ident.span.hi()), "..", applicability), )) }) diff --git a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs new file mode 100644 index 0000000000..c216a1f81e --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs @@ -0,0 +1,77 @@ +use clippy_utils::diagnostics::span_lint_and_help; +use rustc_hir::{HirId, Item, ItemKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::Const; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::sym; + +declare_clippy_lint! { + /// ### What it does + /// Displays a warning when a struct with a trailing zero-sized array is declared without a `repr` attribute. + /// + /// ### Why is this bad? + /// Zero-sized arrays aren't very useful in Rust itself, so such a struct is likely being created to pass to C code or in some other situation where control over memory layout matters (for example, in conjuction with manual allocation to make it easy to compute the offset of the array). Either way, `#[repr(C)]` (or another `repr` attribute) is needed. + /// + /// ### Example + /// ```rust + /// struct RarelyUseful { + /// some_field: u32, + /// last: [u32; 0], + /// } + /// ``` + /// + /// Use instead: + /// ```rust + /// #[repr(C)] + /// struct MoreOftenUseful { + /// some_field: usize, + /// last: [u32; 0], + /// } + /// ``` + pub TRAILING_EMPTY_ARRAY, + nursery, + "struct with a trailing zero-sized array but without `#[repr(C)]` or another `repr` attribute" +} +declare_lint_pass!(TrailingEmptyArray => [TRAILING_EMPTY_ARRAY]); + +impl<'tcx> LateLintPass<'tcx> for TrailingEmptyArray { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { + if is_struct_with_trailing_zero_sized_array(cx, item) && !has_repr_attr(cx, item.hir_id()) { + span_lint_and_help( + cx, + TRAILING_EMPTY_ARRAY, + item.span, + "trailing zero-sized array in a struct which is not marked with a `repr` attribute", + None, + &format!( + "consider annotating `{}` with `#[repr(C)]` or another `repr` attribute", + cx.tcx.def_path_str(item.def_id.to_def_id()) + ), + ); + } + } +} + +fn is_struct_with_trailing_zero_sized_array(cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) -> bool { + if_chain! { + // First check if last field is an array + if let ItemKind::Struct(data, _) = &item.kind; + if let Some(last_field) = data.fields().last(); + if let rustc_hir::TyKind::Array(_, length) = last_field.ty.kind; + + // Then check if that that array zero-sized + let length_ldid = cx.tcx.hir().local_def_id(length.hir_id); + let length = Const::from_anon_const(cx.tcx, length_ldid); + let length = length.try_eval_usize(cx.tcx, cx.param_env); + if let Some(length) = length; + then { + length == 0 + } else { + false + } + } +} + +fn has_repr_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool { + cx.tcx.hir().attrs(hir_id).iter().any(|attr| attr.has_name(sym::repr)) +} diff --git a/src/tools/clippy/clippy_lints/src/transmute/mod.rs b/src/tools/clippy/clippy_lints/src/transmute/mod.rs index 33ec9c331c..e6acf1a94c 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/mod.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/mod.rs @@ -3,6 +3,7 @@ mod transmute_float_to_int; mod transmute_int_to_bool; mod transmute_int_to_char; mod transmute_int_to_float; +mod transmute_num_to_bytes; mod transmute_ptr_to_ptr; mod transmute_ptr_to_ref; mod transmute_ref_to_ref; @@ -261,6 +262,28 @@ declare_clippy_lint! { "transmutes from a float to an integer" } +declare_clippy_lint! { + /// ### What it does + /// Checks for transmutes from a number to an array of `u8` + /// + /// ### Why this is bad? + /// Transmutes are dangerous and error-prone, whereas `to_ne_bytes` + /// is intuitive and safe. + /// + /// ### Example + /// ```rust + /// unsafe { + /// let x: [u8; 8] = std::mem::transmute(1i64); + /// } + /// + /// // should be + /// let x: [u8; 8] = 0i64.to_ne_bytes(); + /// ``` + pub TRANSMUTE_NUM_TO_BYTES, + complexity, + "transmutes from a number to an array of `u8`" +} + declare_clippy_lint! { /// ### What it does /// Checks for transmutes from a pointer to a pointer, or @@ -330,6 +353,7 @@ declare_lint_pass!(Transmute => [ TRANSMUTE_INT_TO_BOOL, TRANSMUTE_INT_TO_FLOAT, TRANSMUTE_FLOAT_TO_INT, + TRANSMUTE_NUM_TO_BYTES, UNSOUND_COLLECTION_TRANSMUTE, TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS, ]); @@ -365,6 +389,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { linted |= transmute_int_to_bool::check(cx, e, from_ty, to_ty, args); linted |= transmute_int_to_float::check(cx, e, from_ty, to_ty, args, const_context); linted |= transmute_float_to_int::check(cx, e, from_ty, to_ty, args, const_context); + linted |= transmute_num_to_bytes::check(cx, e, from_ty, to_ty, args, const_context); linted |= unsound_collection_transmute::check(cx, e, from_ty, to_ty); if !linted { 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 8f884e6a4a..e83d2e06b9 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 @@ -33,7 +33,7 @@ pub(super) fn check<'tcx>( diag.span_suggestion( e.span, "consider using", - format!("std::char::from_u32({}).unwrap()", arg.to_string()), + format!("std::char::from_u32({}).unwrap()", arg), Applicability::Unspecified, ); }, 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 2b6a4cff81..05eee380d6 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 @@ -36,7 +36,7 @@ pub(super) fn check<'tcx>( diag.span_suggestion( e.span, "consider using", - format!("{}::from_bits({})", to_ty, arg.to_string()), + format!("{}::from_bits({})", to_ty, arg), Applicability::Unspecified, ); }, diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs new file mode 100644 index 0000000000..5ba58a7649 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs @@ -0,0 +1,49 @@ +use super::TRANSMUTE_NUM_TO_BYTES; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::sugg; +use rustc_errors::Applicability; +use rustc_hir::Expr; +use rustc_lint::LateContext; +use rustc_middle::ty::{self, Ty, UintTy}; + +/// Checks for `transmute_int_to_float` lint. +/// Returns `true` if it's triggered, otherwise returns `false`. +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + e: &'tcx Expr<'_>, + from_ty: Ty<'tcx>, + to_ty: Ty<'tcx>, + args: &'tcx [Expr<'_>], + const_context: bool, +) -> bool { + match (&from_ty.kind(), &to_ty.kind()) { + (ty::Int(_) | ty::Uint(_) | ty::Float(_), ty::Array(arr_ty, _)) => { + if !matches!(arr_ty.kind(), ty::Uint(UintTy::U8)) { + return false; + } + if matches!(from_ty.kind(), ty::Float(_)) && const_context { + // TODO: Remove when const_float_bits_conv is stabilized + // rust#72447 + return false; + } + + span_lint_and_then( + cx, + TRANSMUTE_NUM_TO_BYTES, + e.span, + &format!("transmute from a `{}` to a `{}`", from_ty, to_ty), + |diag| { + let arg = sugg::Sugg::hir(cx, &args[0], ".."); + diag.span_suggestion( + e.span, + "consider using `to_ne_bytes()`", + format!("{}.to_ne_bytes()", arg), + Applicability::Unspecified, + ); + }, + ); + true + }, + _ => false, + } +} 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 bdeff035e5..63ad65b8af 100644 --- a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs +++ b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs @@ -3,10 +3,8 @@ 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, - SyntheticTyParamKind, TyKind, -}; +use rustc_hir::{self as hir, GenericArg, GenericBounds, GenericParamKind}; +use rustc_hir::{HirId, Lifetime, MutTy, Mutability, Node, QPath, TyKind}; use rustc_lint::LateContext; use super::BORROWED_BOX; @@ -105,7 +103,7 @@ fn get_bounds_if_impl_trait<'tcx>(cx: &LateContext<'tcx>, qpath: &QPath<'_>, id: if let Some(did) = cx.qpath_res(qpath, id).opt_def_id(); if let Some(Node::GenericParam(generic_param)) = cx.tcx.hir().get_if_local(did); if let GenericParamKind::Type { synthetic, .. } = generic_param.kind; - if synthetic == Some(SyntheticTyParamKind::ImplTrait); + if synthetic; then { Some(generic_param.bounds) } else { diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs new file mode 100644 index 0000000000..11aef50991 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -0,0 +1,226 @@ +use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg}; +use clippy_utils::source::{indent_of, reindent_multiline, snippet}; +use clippy_utils::{in_macro, is_lint_allowed}; +use rustc_errors::Applicability; +use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; +use rustc_hir::{Block, BlockCheckMode, Expr, ExprKind, HirId, Local, UnsafeSource}; +use rustc_lexer::TokenKind; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::hir::map::Map; +use rustc_middle::lint::in_external_macro; +use rustc_middle::ty::TyCtxt; +use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_span::{BytePos, Span}; +use std::borrow::Cow; + +declare_clippy_lint! { + /// ### What it does + /// Checks for `unsafe` blocks without a `// Safety: ` comment + /// explaining why the unsafe operations performed inside + /// the block are safe. + /// + /// ### Why is this bad? + /// Undocumented unsafe blocks can make it difficult to + /// read and maintain code, as well as uncover unsoundness + /// and bugs. + /// + /// ### Example + /// ```rust + /// use std::ptr::NonNull; + /// let a = &mut 42; + /// + /// let ptr = unsafe { NonNull::new_unchecked(a) }; + /// ``` + /// Use instead: + /// ```rust + /// use std::ptr::NonNull; + /// let a = &mut 42; + /// + /// // Safety: references are guaranteed to be non-null. + /// let ptr = unsafe { NonNull::new_unchecked(a) }; + /// ``` + pub UNDOCUMENTED_UNSAFE_BLOCKS, + restriction, + "creating an unsafe block without explaining why it is safe" +} + +impl_lint_pass!(UndocumentedUnsafeBlocks => [UNDOCUMENTED_UNSAFE_BLOCKS]); + +#[derive(Default)] +pub struct UndocumentedUnsafeBlocks { + pub local_level: u32, + pub local_span: Option<Span>, + // The local was already checked for an overall safety comment + // There is no need to continue checking the blocks in the local + pub local_checked: bool, + // Since we can only check the blocks from expanded macros + // We have to omit the suggestion due to the actual definition + // Not being available to us + pub macro_expansion: bool, +} + +impl LateLintPass<'_> for UndocumentedUnsafeBlocks { + fn check_block(&mut self, cx: &LateContext<'_>, block: &'_ Block<'_>) { + if_chain! { + if !self.local_checked; + if !is_lint_allowed(cx, UNDOCUMENTED_UNSAFE_BLOCKS, block.hir_id); + if !in_external_macro(cx.tcx.sess, block.span); + if let BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) = block.rules; + if let Some(enclosing_scope_hir_id) = cx.tcx.hir().get_enclosing_scope(block.hir_id); + if self.block_has_safety_comment(cx.tcx, enclosing_scope_hir_id, block.span) == Some(false); + then { + let mut span = block.span; + + if let Some(local_span) = self.local_span { + span = local_span; + + let result = self.block_has_safety_comment(cx.tcx, enclosing_scope_hir_id, span); + + if result.unwrap_or(true) { + self.local_checked = true; + return; + } + } + + self.lint(cx, span); + } + } + } + + fn check_local(&mut self, cx: &LateContext<'_>, local: &'_ Local<'_>) { + if_chain! { + if !is_lint_allowed(cx, UNDOCUMENTED_UNSAFE_BLOCKS, local.hir_id); + if !in_external_macro(cx.tcx.sess, local.span); + if let Some(init) = local.init; + then { + self.visit_expr(init); + + if self.local_level > 0 { + self.local_span = Some(local.span); + } + } + } + } + + fn check_block_post(&mut self, _: &LateContext<'_>, _: &'_ Block<'_>) { + self.local_level = self.local_level.saturating_sub(1); + + if self.local_level == 0 { + self.local_checked = false; + self.local_span = None; + } + } +} + +impl<'hir> Visitor<'hir> for UndocumentedUnsafeBlocks { + type Map = Map<'hir>; + + fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { + NestedVisitorMap::None + } + + fn visit_expr(&mut self, ex: &'v Expr<'v>) { + match ex.kind { + ExprKind::Block(_, _) => self.local_level = self.local_level.saturating_add(1), + _ => walk_expr(self, ex), + } + } +} + +impl UndocumentedUnsafeBlocks { + fn block_has_safety_comment(&mut self, tcx: TyCtxt<'_>, enclosing_hir_id: HirId, block_span: Span) -> Option<bool> { + let map = tcx.hir(); + let source_map = tcx.sess.source_map(); + + let enclosing_scope_span = map.opt_span(enclosing_hir_id)?; + + let between_span = if in_macro(block_span) { + self.macro_expansion = true; + enclosing_scope_span.with_hi(block_span.hi()) + } else { + self.macro_expansion = false; + enclosing_scope_span.to(block_span) + }; + + let file_name = source_map.span_to_filename(between_span); + let source_file = source_map.get_source_file(&file_name)?; + + let lex_start = (between_span.lo().0 - source_file.start_pos.0 + 1) as usize; + let lex_end = (between_span.hi().0 - source_file.start_pos.0) as usize; + let src_str = source_file.src.as_ref()?[lex_start..lex_end].to_string(); + + let mut pos = 0; + let mut comment = false; + + for token in rustc_lexer::tokenize(&src_str) { + match token.kind { + TokenKind::LineComment { doc_style: None } + | TokenKind::BlockComment { + doc_style: None, + terminated: true, + } => { + let comment_str = src_str[pos + 2..pos + token.len].to_ascii_uppercase(); + + if comment_str.contains("SAFETY:") { + comment = true; + } + }, + // We need to add all whitespace to `pos` before checking the comment's line number + TokenKind::Whitespace => {}, + _ => { + if comment { + // Get the line number of the "comment" (really wherever the trailing whitespace ended) + let comment_line_num = source_file + .lookup_file_pos_with_col_display(BytePos((lex_start + pos).try_into().unwrap())) + .0; + // Find the block/local's line number + let block_line_num = tcx.sess.source_map().lookup_char_pos(block_span.lo()).line; + + // Check the comment is immediately followed by the block/local + if block_line_num == comment_line_num + 1 || block_line_num == comment_line_num { + return Some(true); + } + + comment = false; + } + }, + } + + pos += token.len; + } + + Some(false) + } + + fn lint(&self, cx: &LateContext<'_>, mut span: Span) { + let source_map = cx.tcx.sess.source_map(); + + if source_map.is_multiline(span) { + span = source_map.span_until_char(span, '\n'); + } + + if self.macro_expansion { + span_lint_and_help( + cx, + UNDOCUMENTED_UNSAFE_BLOCKS, + span, + "unsafe block in macro expansion missing a safety comment", + None, + "consider adding a safety comment in the macro definition", + ); + } else { + let block_indent = indent_of(cx, span); + let suggestion = format!("// Safety: ...\n{}", snippet(cx, span, "..")); + + span_lint_and_sugg( + cx, + UNDOCUMENTED_UNSAFE_BLOCKS, + span, + "unsafe block missing a safety comment", + "consider adding a safety comment", + reindent_multiline(Cow::Borrowed(&suggestion), true, block_indent).to_string(), + Applicability::HasPlaceholders, + ); + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/unicode.rs b/src/tools/clippy/clippy_lints/src/unicode.rs index f337dec8f2..f49ce696a0 100644 --- a/src/tools/clippy/clippy_lints/src/unicode.rs +++ b/src/tools/clippy/clippy_lints/src/unicode.rs @@ -45,7 +45,7 @@ declare_clippy_lint! { /// let x = String::from("\u{20ac}"); /// ``` pub NON_ASCII_LITERAL, - pedantic, + restriction, "using any literal non-ASCII chars in a string literal instead of using the `\\u` escape" } diff --git a/src/tools/clippy/clippy_lints/src/uninit_vec.rs b/src/tools/clippy/clippy_lints/src/uninit_vec.rs new file mode 100644 index 0000000000..f3e8b68810 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/uninit_vec.rs @@ -0,0 +1,223 @@ +use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; +use clippy_utils::higher::{get_vec_init_kind, VecInitKind}; +use clippy_utils::ty::{is_type_diagnostic_item, is_uninit_value_valid_for_ty}; +use clippy_utils::{is_lint_allowed, path_to_local_id, peel_hir_expr_while, SpanlessEq}; +use rustc_hir::{Block, Expr, ExprKind, HirId, PatKind, PathSegment, Stmt, StmtKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::lint::in_external_macro; +use rustc_middle::ty; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::{sym, Span}; + +// TODO: add `ReadBuf` (RFC 2930) in "How to fix" once it is available in std +declare_clippy_lint! { + /// ### What it does + /// Checks for `set_len()` call that creates `Vec` with uninitialized elements. + /// This is commonly caused by calling `set_len()` right after allocating or + /// reserving a buffer with `new()`, `default()`, `with_capacity()`, or `reserve()`. + /// + /// ### Why is this bad? + /// It creates a `Vec` with uninitialized data, which leads to + /// undefined behavior with most safe operations. Notably, uninitialized + /// `Vec<u8>` must not be used with generic `Read`. + /// + /// Moreover, calling `set_len()` on a `Vec` created with `new()` or `default()` + /// creates out-of-bound values that lead to heap memory corruption when used. + /// + /// ### Known Problems + /// This lint only checks directly adjacent statements. + /// + /// ### Example + /// ```rust,ignore + /// let mut vec: Vec<u8> = Vec::with_capacity(1000); + /// unsafe { vec.set_len(1000); } + /// reader.read(&mut vec); // undefined behavior! + /// ``` + /// + /// ### How to fix? + /// 1. Use an initialized buffer: + /// ```rust,ignore + /// let mut vec: Vec<u8> = vec![0; 1000]; + /// reader.read(&mut vec); + /// ``` + /// 2. Wrap the content in `MaybeUninit`: + /// ```rust,ignore + /// let mut vec: Vec<MaybeUninit<T>> = Vec::with_capacity(1000); + /// vec.set_len(1000); // `MaybeUninit` can be uninitialized + /// ``` + /// 3. If you are on nightly, `Vec::spare_capacity_mut()` is available: + /// ```rust,ignore + /// let mut vec: Vec<u8> = Vec::with_capacity(1000); + /// let remaining = vec.spare_capacity_mut(); // `&mut [MaybeUninit<u8>]` + /// // perform initialization with `remaining` + /// vec.set_len(...); // Safe to call `set_len()` on initialized part + /// ``` + pub UNINIT_VEC, + correctness, + "Vec with uninitialized data" +} + +declare_lint_pass!(UninitVec => [UNINIT_VEC]); + +// FIXME: update to a visitor-based implementation. +// Threads: https://github.com/rust-lang/rust-clippy/pull/7682#discussion_r710998368 +impl<'tcx> LateLintPass<'tcx> for UninitVec { + fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'_>) { + if !in_external_macro(cx.tcx.sess, block.span) { + for w in block.stmts.windows(2) { + if let StmtKind::Expr(expr) | StmtKind::Semi(expr) = w[1].kind { + handle_uninit_vec_pair(cx, &w[0], expr); + } + } + + if let (Some(stmt), Some(expr)) = (block.stmts.last(), block.expr) { + handle_uninit_vec_pair(cx, stmt, expr); + } + } + } +} + +fn handle_uninit_vec_pair( + cx: &LateContext<'tcx>, + maybe_init_or_reserve: &'tcx Stmt<'tcx>, + maybe_set_len: &'tcx Expr<'tcx>, +) { + if_chain! { + if let Some(vec) = extract_init_or_reserve_target(cx, maybe_init_or_reserve); + if let Some((set_len_self, call_span)) = extract_set_len_self(cx, maybe_set_len); + if vec.location.eq_expr(cx, set_len_self); + if let ty::Ref(_, vec_ty, _) = cx.typeck_results().expr_ty_adjusted(set_len_self).kind(); + if let ty::Adt(_, substs) = vec_ty.kind(); + // `#[allow(...)]` attribute can be set on enclosing unsafe block of `set_len()` + if !is_lint_allowed(cx, UNINIT_VEC, maybe_set_len.hir_id); + then { + if vec.has_capacity() { + // with_capacity / reserve -> set_len + + // Check T of Vec<T> + if !is_uninit_value_valid_for_ty(cx, substs.type_at(0)) { + // FIXME: #7698, false positive of the internal lints + #[allow(clippy::collapsible_span_lint_calls)] + span_lint_and_then( + cx, + UNINIT_VEC, + vec![call_span, maybe_init_or_reserve.span], + "calling `set_len()` immediately after reserving a buffer creates uninitialized values", + |diag| { + diag.help("initialize the buffer or wrap the content in `MaybeUninit`"); + }, + ); + } + } else { + // new / default -> set_len + span_lint( + cx, + UNINIT_VEC, + vec![call_span, maybe_init_or_reserve.span], + "calling `set_len()` on empty `Vec` creates out-of-bound values", + ); + } + } + } +} + +/// The target `Vec` that is initialized or reserved +#[derive(Clone, Copy)] +struct TargetVec<'tcx> { + location: VecLocation<'tcx>, + /// `None` if `reserve()` + init_kind: Option<VecInitKind>, +} + +impl TargetVec<'_> { + pub fn has_capacity(self) -> bool { + !matches!(self.init_kind, Some(VecInitKind::New | VecInitKind::Default)) + } +} + +#[derive(Clone, Copy)] +enum VecLocation<'tcx> { + Local(HirId), + Expr(&'tcx Expr<'tcx>), +} + +impl<'tcx> VecLocation<'tcx> { + pub fn eq_expr(self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { + match self { + VecLocation::Local(hir_id) => path_to_local_id(expr, hir_id), + VecLocation::Expr(self_expr) => SpanlessEq::new(cx).eq_expr(self_expr, expr), + } + } +} + +/// Finds the target location where the result of `Vec` initialization is stored +/// or `self` expression for `Vec::reserve()`. +fn extract_init_or_reserve_target<'tcx>(cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'tcx>) -> Option<TargetVec<'tcx>> { + match stmt.kind { + StmtKind::Local(local) => { + if_chain! { + if let Some(init_expr) = local.init; + if let PatKind::Binding(_, hir_id, _, None) = local.pat.kind; + if let Some(init_kind) = get_vec_init_kind(cx, init_expr); + then { + return Some(TargetVec { + location: VecLocation::Local(hir_id), + init_kind: Some(init_kind), + }) + } + } + }, + StmtKind::Expr(expr) | StmtKind::Semi(expr) => match expr.kind { + ExprKind::Assign(lhs, rhs, _span) => { + if let Some(init_kind) = get_vec_init_kind(cx, rhs) { + return Some(TargetVec { + location: VecLocation::Expr(lhs), + init_kind: Some(init_kind), + }); + } + }, + ExprKind::MethodCall(path, _, [self_expr, _], _) if is_reserve(cx, path, self_expr) => { + return Some(TargetVec { + location: VecLocation::Expr(self_expr), + init_kind: None, + }); + }, + _ => (), + }, + StmtKind::Item(_) => (), + } + None +} + +fn is_reserve(cx: &LateContext<'_>, path: &PathSegment<'_>, self_expr: &Expr<'_>) -> bool { + is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_expr).peel_refs(), sym::Vec) + && path.ident.name.as_str() == "reserve" +} + +/// Returns self if the expression is `Vec::set_len()` +fn extract_set_len_self(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Option<(&'tcx Expr<'tcx>, Span)> { + // peel unsafe blocks in `unsafe { vec.set_len() }` + let expr = peel_hir_expr_while(expr, |e| { + if let ExprKind::Block(block, _) = e.kind { + // Extract the first statement/expression + match (block.stmts.get(0).map(|stmt| &stmt.kind), block.expr) { + (None, Some(expr)) => Some(expr), + (Some(StmtKind::Expr(expr) | StmtKind::Semi(expr)), _) => Some(expr), + _ => None, + } + } else { + None + } + }); + match expr.kind { + ExprKind::MethodCall(path, _, [self_expr, _], _) => { + let self_type = cx.typeck_results().expr_ty(self_expr).peel_refs(); + if is_type_diagnostic_item(cx, self_type, sym::Vec) && path.ident.name.as_str() == "set_len" { + Some((self_expr, expr.span)) + } else { + None + } + }, + _ => None, + } +} diff --git a/src/tools/clippy/clippy_lints/src/unit_hash.rs b/src/tools/clippy/clippy_lints/src/unit_hash.rs new file mode 100644 index 0000000000..a3a3f2d41c --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/unit_hash.rs @@ -0,0 +1,77 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::snippet; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::sym; + +declare_clippy_lint! { + /// ### What it does + /// Detects `().hash(_)`. + /// + /// ### Why is this bad? + /// Hashing a unit value doesn't do anything as the implementation of `Hash` for `()` is a no-op. + /// + /// ### Example + /// ```rust + /// # use std::hash::Hash; + /// # use std::collections::hash_map::DefaultHasher; + /// # enum Foo { Empty, WithValue(u8) } + /// # use Foo::*; + /// # let mut state = DefaultHasher::new(); + /// # let my_enum = Foo::Empty; + /// match my_enum { + /// Empty => ().hash(&mut state), + /// WithValue(x) => x.hash(&mut state), + /// } + /// ``` + /// Use instead: + /// ```rust + /// # use std::hash::Hash; + /// # use std::collections::hash_map::DefaultHasher; + /// # enum Foo { Empty, WithValue(u8) } + /// # use Foo::*; + /// # let mut state = DefaultHasher::new(); + /// # let my_enum = Foo::Empty; + /// match my_enum { + /// Empty => 0_u8.hash(&mut state), + /// WithValue(x) => x.hash(&mut state), + /// } + /// ``` + pub UNIT_HASH, + correctness, + "hashing a unit value, which does nothing" +} +declare_lint_pass!(UnitHash => [UNIT_HASH]); + +impl LateLintPass<'tcx> for UnitHash { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { + if_chain! { + if let ExprKind::MethodCall(name_ident, _, args, _) = &expr.kind; + if name_ident.ident.name == sym::hash; + if let [recv, state_param] = args; + if cx.typeck_results().expr_ty(recv).is_unit(); + then { + span_lint_and_then( + cx, + UNIT_HASH, + expr.span, + "this call to `hash` on the unit type will do nothing", + |diag| { + diag.span_suggestion( + expr.span, + "remove the call to `hash` or consider using", + format!( + "0_u8.hash({})", + snippet(cx, state_param.span, ".."), + ), + Applicability::MaybeIncorrect, + ); + diag.note("the implementation of `Hash` for `()` is a no-op"); + } + ); + } + } + } +} 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 index fad647dfb2..b25a6e3375 100644 --- 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 @@ -1,5 +1,4 @@ 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}; @@ -14,9 +13,6 @@ pub(super) fn check(cx: &LateContext<'_>, stmt: &Stmt<'_>) { 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, 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 dd74bf367f..26b56e0f2f 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::sugg::Sugg; -use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::ty::{implements_trait, 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}; @@ -193,10 +193,15 @@ fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<LintTrigger> { let vec_name = Sugg::hir(cx, &args[0], "..").to_string(); let unstable = name == "sort_unstable_by"; + if_chain! { if let ExprKind::Path(QPath::Resolved(_, Path { segments: [PathSegment { ident: left_name, .. }], .. - })) = &left_expr.kind { - if left_name == left_ident { + })) = &left_expr.kind; + if left_name == left_ident; + if cx.tcx.get_diagnostic_item(sym::Ord).map_or(false, |id| { + implements_trait(cx, cx.typeck_results().expr_ty(left_expr), id, &[]) + }); + then { return Some(LintTrigger::Sort(SortDetection { vec_name, unstable })); } } 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 a4680ae137..6447e3fa2c 100644 --- a/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs +++ b/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs @@ -13,7 +13,7 @@ use rustc_span::{sym, Span}; declare_clippy_lint! { /// ### What it does - /// Checks for functions of type Result that contain `expect()` or `unwrap()` + /// Checks for functions of type `Result` that contain `expect()` or `unwrap()` /// /// ### Why is this bad? /// These functions promote recoverable errors to non-recoverable errors which may be undesirable in code bases which wish to avoid panics. diff --git a/src/tools/clippy/clippy_lints/src/utils/conf.rs b/src/tools/clippy/clippy_lints/src/utils/conf.rs index 6cbada4c15..122a5ce3fc 100644 --- a/src/tools/clippy/clippy_lints/src/utils/conf.rs +++ b/src/tools/clippy/clippy_lints/src/utils/conf.rs @@ -23,6 +23,14 @@ pub enum DisallowedMethod { WithReason { path: String, reason: Option<String> }, } +/// A single disallowed type, used by the `DISALLOWED_TYPE` lint. +#[derive(Clone, Debug, Deserialize)] +#[serde(untagged)] +pub enum DisallowedType { + Simple(String), + WithReason { path: String, reason: Option<String> }, +} + /// Conf with parse errors #[derive(Default)] pub struct TryConf { @@ -255,7 +263,7 @@ define_Conf! { /// Lint: DISALLOWED_TYPE. /// /// The list of disallowed types, written as fully qualified paths. - (disallowed_types: Vec<String> = Vec::new()), + (disallowed_types: Vec<crate::utils::conf::DisallowedType> = Vec::new()), /// Lint: UNREADABLE_LITERAL. /// /// Should the fraction of a decimal be linted to include separators. @@ -280,10 +288,10 @@ define_Conf! { /// /// The list of imports to always rename, a fully qualified path followed by the rename. (enforced_import_renames: Vec<crate::utils::conf::Rename> = Vec::new()), - /// Lint: RESTRICTED_SCRIPTS. + /// Lint: DISALLOWED_SCRIPT_IDENTS. /// /// The list of unicode scripts allowed to be used in the scope. - (allowed_scripts: Vec<String> = vec!["Latin".to_string()]), + (allowed_scripts: Vec<String> = ["Latin"].iter().map(ToString::to_string).collect()), /// Lint: NON_SEND_FIELDS_IN_SEND_TY. /// /// Whether to apply the raw pointer heuristic to determine if a type is `Send`. 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 9f9edbf258..824ec53ab9 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs @@ -770,8 +770,7 @@ impl<'tcx> LateLintPass<'tcx> for MatchTypeOnDiagItem { let segments: Vec<&str> = segments.iter().map(|sym| &**sym).collect(); if let Some(ty_did) = path_to_res(cx, &segments[..]).opt_def_id(); // Check if the matched type is a diagnostic item - 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 }); + if let Some(item_name) = cx.tcx.get_diagnostic_name(ty_did); then { // TODO: check paths constants from external crates. let cx_snippet = snippet(cx, context.span, "_"); diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs index 0d27874b7a..99cf4c1ed4 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs @@ -512,12 +512,21 @@ fn extract_attr_docs(cx: &LateContext<'_>, item: &Item<'_>) -> Option<String> { let mut lines = attrs.iter().filter_map(ast::Attribute::doc_str); let mut docs = String::from(&*lines.next()?.as_str()); let mut in_code_block = false; + let mut is_code_block_rust = false; for line in lines { - docs.push('\n'); let line = line.as_str(); let line = &*line; + + // Rustdoc hides code lines starting with `# ` and this removes them from Clippy's lint list :) + if is_code_block_rust && line.trim_start().starts_with("# ") { + continue; + } + + // The line should be represented in the lint list, even if it's just an empty line + docs.push('\n'); if let Some(info) = line.trim_start().strip_prefix("```") { in_code_block = !in_code_block; + is_code_block_rust = false; if in_code_block { let lang = info .trim() @@ -528,6 +537,8 @@ fn extract_attr_docs(cx: &LateContext<'_>, item: &Item<'_>) -> Option<String> { .unwrap_or("rust"); docs.push_str("```"); docs.push_str(lang); + + is_code_block_rust = lang == "rust"; continue; } } diff --git a/src/tools/clippy/clippy_lints/src/vec.rs b/src/tools/clippy/clippy_lints/src/vec.rs index d124d948b5..d3234b5758 100644 --- a/src/tools/clippy/clippy_lints/src/vec.rs +++ b/src/tools/clippy/clippy_lints/src/vec.rs @@ -63,13 +63,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec { if is_copy(cx, vec_type(cx.typeck_results().expr_ty_adjusted(arg))); then { // report the error around the `vec!` not inside `<std macros>:` - let span = arg.span - .ctxt() - .outer_expn_data() - .call_site - .ctxt() - .outer_expn_data() - .call_site; + let span = arg.span.ctxt().outer_expn_data().call_site; self.check_vec_macro(cx, &vec_args, Mutability::Not, span); } } 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 5b71bb29c1..b92b6ca4f4 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,16 +1,14 @@ use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::higher::{get_vec_init_kind, VecInitKind}; 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 clippy_utils::{path_to_local, path_to_local_id}; use if_chain::if_chain; -use rustc_ast::ast::LitKind; use rustc_errors::Applicability; -use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, HirId, Local, PatKind, QPath, Stmt, StmtKind}; +use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, HirId, Local, PatKind, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::{symbol::sym, Span}; -use std::convert::TryInto; +use rustc_span::Span; declare_clippy_lint! { /// ### What it does @@ -41,11 +39,6 @@ pub struct VecInitThenPush { searcher: Option<VecPushSearcher>, } -#[derive(Clone, Copy)] -enum VecInitKind { - New, - WithCapacity(u64), -} struct VecPushSearcher { local_id: HirId, init: VecInitKind, @@ -58,7 +51,8 @@ impl VecPushSearcher { fn display_err(&self, cx: &LateContext<'_>) { match self.init { _ if self.found == 0 => return, - VecInitKind::WithCapacity(x) if x > self.found => return, + VecInitKind::WithLiteralCapacity(x) if x > self.found => return, + VecInitKind::WithExprCapacity(_) => return, _ => (), }; @@ -152,37 +146,3 @@ impl LateLintPass<'_> for VecInitThenPush { } } } - -fn get_vec_init_kind<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<VecInitKind> { - if let ExprKind::Call(func, args) = expr.kind { - match func.kind { - ExprKind::Path(QPath::TypeRelative(ty, name)) - if is_type_diagnostic_item(cx, cx.typeck_results().node_type(ty.hir_id), sym::Vec) => - { - if name.ident.name == sym::new { - return Some(VecInitKind::New); - } else if name.ident.name.as_str() == "with_capacity" { - return args.get(0).and_then(|arg| { - if_chain! { - if let ExprKind::Lit(lit) = &arg.kind; - if let LitKind::Int(num, _) = lit.node; - then { - Some(VecInitKind::WithCapacity(num.try_into().ok()?)) - } else { - None - } - } - }); - } - }, - ExprKind::Path(QPath::Resolved(_, path)) - if match_def_path(cx, path.res.opt_def_id()?, &paths::DEFAULT_TRAIT_METHOD) - && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::Vec) => - { - return Some(VecInitKind::New); - }, - _ => (), - } - } - None -} diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs index 85d1f65c51..b412e15ae4 100644 --- a/src/tools/clippy/clippy_lints/src/write.rs +++ b/src/tools/clippy/clippy_lints/src/write.rs @@ -4,7 +4,7 @@ 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::ast::{Expr, ExprKind, Impl, Item, ItemKind, MacCall, Path, StrLit, StrStyle}; use rustc_ast::token::{self, LitKind}; use rustc_ast::tokenstream::TokenStream; use rustc_errors::Applicability; @@ -243,7 +243,7 @@ impl_lint_pass!(Write => [ impl EarlyLintPass for Write { fn check_item(&mut self, _: &EarlyContext<'_>, item: &Item) { - if let ItemKind::Impl(box ImplKind { + if let ItemKind::Impl(box Impl { of_trait: Some(trait_ref), .. }) = &item.kind diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml index e7fca3ae5d..d99a3d9359 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.57" +version = "0.1.58" edition = "2021" publish = false diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index 2fa98831c7..1b05a8a350 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -250,7 +250,8 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { (Use(l), Use(r)) => eq_use_tree(l, r), (Static(lt, lm, le), Static(rt, rm, re)) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re), (Const(ld, lt, le), Const(rd, rt, re)) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re), - (Fn(box FnKind(ld, lf, lg, lb)), Fn(box FnKind(rd, rf, rg, rb))) => { + (Fn(box ast::Fn { defaultness: ld, sig: lf, generics: lg, body: lb }), + Fn(box ast::Fn { defaultness: rd, sig: rf, generics: rg, body: rb })) => { eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) && eq_generics(lg, rg) && both(lb, rb, |l, r| eq_block(l, r)) }, (Mod(lu, lmk), Mod(ru, rmk)) => { @@ -266,7 +267,8 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { (ForeignMod(l), ForeignMod(r)) => { both(&l.abi, &r.abi, eq_str_lit) && over(&l.items, &r.items, |l, r| eq_item(l, r, eq_foreign_item_kind)) }, - (TyAlias(box TyAliasKind(ld, lg, lb, lt)), TyAlias(box TyAliasKind(rd, rg, rb, rt))) => { + (TyAlias(box ast::TyAlias { defaultness: ld, generics: lg, bounds: lb, ty: lt }), + TyAlias(box ast::TyAlias { defaultness: rd, generics: rg, bounds: rb, ty: rt })) => { eq_defaultness(*ld, *rd) && eq_generics(lg, rg) && over(lb, rb, eq_generic_bound) @@ -276,7 +278,8 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { (Struct(lv, lg), Struct(rv, rg)) | (Union(lv, lg), Union(rv, rg)) => { eq_variant_data(lv, rv) && eq_generics(lg, rg) }, - (Trait(box TraitKind(la, lu, lg, lb, li)), Trait(box TraitKind(ra, ru, rg, rb, ri))) => { + (Trait(box ast::Trait { is_auto: la, unsafety: lu, generics: lg, bounds: lb, items: li }), + Trait(box ast::Trait { is_auto: ra, unsafety: ru, generics: rg, bounds: rb, items: ri })) => { la == ra && matches!(lu, Unsafe::No) == matches!(ru, Unsafe::No) && eq_generics(lg, rg) @@ -285,7 +288,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { }, (TraitAlias(lg, lb), TraitAlias(rg, rb)) => eq_generics(lg, rg) && over(lb, rb, eq_generic_bound), ( - Impl(box ImplKind { + Impl(box ast::Impl { unsafety: lu, polarity: lp, defaultness: ld, @@ -295,7 +298,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { self_ty: lst, items: li, }), - Impl(box ImplKind { + Impl(box ast::Impl { unsafety: ru, polarity: rp, defaultness: rd, @@ -325,10 +328,12 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { use ForeignItemKind::*; match (l, r) { (Static(lt, lm, le), Static(rt, rm, re)) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re), - (Fn(box FnKind(ld, lf, lg, lb)), Fn(box FnKind(rd, rf, rg, rb))) => { + (Fn(box ast::Fn { defaultness: ld, sig: lf, generics: lg, body: lb }), + Fn(box ast::Fn { defaultness: rd, sig: rf, generics: rg, body: rb })) => { eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) && eq_generics(lg, rg) && both(lb, rb, |l, r| eq_block(l, r)) }, - (TyAlias(box TyAliasKind(ld, lg, lb, lt)), TyAlias(box TyAliasKind(rd, rg, rb, rt))) => { + (TyAlias(box ast::TyAlias { defaultness: ld, generics: lg, bounds: lb, ty: lt }), + TyAlias(box ast::TyAlias { defaultness: rd, generics: rg, bounds: rb, ty: rt })) => { eq_defaultness(*ld, *rd) && eq_generics(lg, rg) && over(lb, rb, eq_generic_bound) @@ -343,10 +348,12 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { use AssocItemKind::*; match (l, r) { (Const(ld, lt, le), Const(rd, rt, re)) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re), - (Fn(box FnKind(ld, lf, lg, lb)), Fn(box FnKind(rd, rf, rg, rb))) => { + (Fn(box ast::Fn { defaultness: ld, sig: lf, generics: lg, body: lb }), + Fn(box ast::Fn { defaultness: rd, sig: rf, generics: rg, body: rb })) => { eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) && eq_generics(lg, rg) && both(lb, rb, |l, r| eq_block(l, r)) }, - (TyAlias(box TyAliasKind(ld, lg, lb, lt)), TyAlias(box TyAliasKind(rd, rg, rb, rt))) => { + (TyAlias(box ast::TyAlias { defaultness: ld, generics: lg, bounds: lb, ty: lt }), + TyAlias(box ast::TyAlias { defaultness: rd, generics: rg, bounds: rb, ty: rt })) => { eq_defaultness(*ld, *rd) && eq_generics(lg, rg) && over(lb, rb, eq_generic_bound) diff --git a/src/tools/clippy/clippy_utils/src/camel_case.rs b/src/tools/clippy/clippy_utils/src/camel_case.rs deleted file mode 100644 index a6636e3913..0000000000 --- a/src/tools/clippy/clippy_utils/src/camel_case.rs +++ /dev/null @@ -1,117 +0,0 @@ -/// Returns the index of the character after the first camel-case component of `s`. -#[must_use] -pub fn until(s: &str) -> usize { - let mut iter = s.char_indices(); - if let Some((_, first)) = iter.next() { - if !first.is_uppercase() { - return 0; - } - } else { - return 0; - } - let mut up = true; - let mut last_i = 0; - for (i, c) in iter { - if up { - if c.is_lowercase() { - up = false; - } else { - return last_i; - } - } else if c.is_uppercase() { - up = true; - last_i = i; - } else if !c.is_lowercase() { - return i; - } - } - if up { last_i } else { s.len() } -} - -/// Returns index of the last camel-case component of `s`. -#[must_use] -pub fn from(s: &str) -> usize { - let mut iter = s.char_indices().rev(); - if let Some((_, first)) = iter.next() { - if !first.is_lowercase() { - return s.len(); - } - } else { - return s.len(); - } - let mut down = true; - let mut last_i = s.len(); - for (i, c) in iter { - if down { - if c.is_uppercase() { - down = false; - last_i = i; - } else if !c.is_lowercase() { - return last_i; - } - } else if c.is_lowercase() { - down = true; - } else if c.is_uppercase() { - last_i = i; - } else { - return last_i; - } - } - last_i -} - -#[cfg(test)] -mod test { - use super::{from, until}; - - #[test] - fn from_full() { - assert_eq!(from("AbcDef"), 0); - assert_eq!(from("Abc"), 0); - assert_eq!(from("ABcd"), 0); - assert_eq!(from("ABcdEf"), 0); - assert_eq!(from("AabABcd"), 0); - } - - #[test] - fn from_partial() { - assert_eq!(from("abcDef"), 3); - assert_eq!(from("aDbc"), 1); - assert_eq!(from("aabABcd"), 3); - } - - #[test] - fn from_not() { - assert_eq!(from("AbcDef_"), 7); - assert_eq!(from("AbcDD"), 5); - } - - #[test] - fn from_caps() { - assert_eq!(from("ABCD"), 4); - } - - #[test] - fn until_full() { - assert_eq!(until("AbcDef"), 6); - assert_eq!(until("Abc"), 3); - } - - #[test] - fn until_not() { - assert_eq!(until("abcDef"), 0); - assert_eq!(until("aDbc"), 0); - } - - #[test] - fn until_partial() { - assert_eq!(until("AbcDef_"), 6); - assert_eq!(until("CallTypeC"), 8); - assert_eq!(until("AbcDD"), 3); - } - - #[test] - fn until_caps() { - assert_eq!(until("ABCD"), 0); - } -} diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 8bf31807d5..04347672e0 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -155,6 +155,19 @@ impl Constant { _ => None, } } + + /// Returns the integer value or `None` if `self` or `val_type` is not integer type. + pub fn int_value(&self, cx: &LateContext<'_>, val_type: Ty<'_>) -> Option<FullInt> { + if let Constant::Int(const_int) = *self { + match *val_type.kind() { + ty::Int(ity) => Some(FullInt::S(sext(cx.tcx, const_int, ity))), + ty::Uint(_) => Some(FullInt::U(const_int)), + _ => None, + } + } else { + None + } + } } /// Parses a `LitKind` to a `Constant`. @@ -202,6 +215,52 @@ pub fn constant_simple<'tcx>( constant(lcx, typeck_results, e).and_then(|(cst, res)| if res { None } else { Some(cst) }) } +pub fn constant_full_int( + lcx: &LateContext<'tcx>, + typeck_results: &ty::TypeckResults<'tcx>, + e: &Expr<'_>, +) -> Option<FullInt> { + constant_simple(lcx, typeck_results, e)?.int_value(lcx, typeck_results.expr_ty(e)) +} + +#[derive(Copy, Clone, Debug, Eq)] +pub enum FullInt { + S(i128), + U(u128), +} + +impl PartialEq for FullInt { + #[must_use] + fn eq(&self, other: &Self) -> bool { + self.cmp(other) == Ordering::Equal + } +} + +impl PartialOrd for FullInt { + #[must_use] + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + Some(self.cmp(other)) + } +} + +impl Ord for FullInt { + #[must_use] + fn cmp(&self, other: &Self) -> Ordering { + use FullInt::{S, U}; + + fn cmp_s_u(s: i128, u: u128) -> Ordering { + u128::try_from(s).map_or(Ordering::Less, |x| x.cmp(&u)) + } + + match (*self, *other) { + (S(s), S(o)) => s.cmp(&o), + (U(s), U(o)) => s.cmp(&o), + (S(s), U(o)) => cmp_s_u(s, o), + (U(s), S(o)) => cmp_s_u(o, s).reverse(), + } + } +} + /// Creates a `ConstEvalLateContext` from the given `LateContext` and `TypeckResults`. pub fn constant_context<'a, 'tcx>( lcx: &'a LateContext<'tcx>, diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs index 9302e5c21f..d47b002ad7 100644 --- a/src/tools/clippy/clippy_utils/src/diagnostics.rs +++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs @@ -72,7 +72,7 @@ pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: impl Into<Mult /// 6 | let other_f64_nan = 0.0f64 / 0.0; /// | ^^^^^^^^^^^^ /// | -/// = help: Consider using `f64::NAN` if you would like a constant representing NaN +/// = help: consider using `f64::NAN` if you would like a constant representing NaN /// ``` pub fn span_lint_and_help<'a, T: LintContext>( cx: &'a T, diff --git a/src/tools/clippy/clippy_utils/src/higher.rs b/src/tools/clippy/clippy_utils/src/higher.rs index ba4d50bf74..7297265d08 100644 --- a/src/tools/clippy/clippy_utils/src/higher.rs +++ b/src/tools/clippy/clippy_utils/src/higher.rs @@ -1,14 +1,17 @@ -//! This module contains functions that retrieves specifiec elements. +//! This module contains functions that retrieve specific elements. #![deny(clippy::missing_docs_in_private_items)] -use crate::{is_expn_of, match_def_path, paths}; +use crate::ty::is_type_diagnostic_item; +use crate::{is_expn_of, last_path_segment, match_def_path, paths}; use if_chain::if_chain; use rustc_ast::ast::{self, LitKind}; use rustc_hir as hir; -use rustc_hir::{Arm, Block, BorrowKind, Expr, ExprKind, LoopSource, MatchSource, Node, Pat, StmtKind, UnOp}; +use rustc_hir::{ + Arm, Block, BorrowKind, Expr, ExprKind, HirId, LoopSource, MatchSource, Node, Pat, QPath, StmtKind, UnOp, +}; use rustc_lint::LateContext; -use rustc_span::{sym, ExpnKind, Span, Symbol}; +use rustc_span::{sym, symbol, ExpnKind, Span, Symbol}; /// The essential nodes of a desugared for loop as well as the entire span: /// `for pat in arg { body }` becomes `(pat, arg, body)`. Return `(pat, arg, body, span)`. @@ -19,31 +22,31 @@ pub struct ForLoop<'tcx> { pub arg: &'tcx hir::Expr<'tcx>, /// `for` loop body pub body: &'tcx hir::Expr<'tcx>, + /// Compare this against `hir::Destination.target` + pub loop_id: HirId, /// entire `for` loop span pub span: Span, } impl<'tcx> ForLoop<'tcx> { - #[inline] /// Parses a desugared `for` loop pub fn hir(expr: &Expr<'tcx>) -> Option<Self> { if_chain! { - if let hir::ExprKind::Match(iterexpr, arms, hir::MatchSource::ForLoopDesugar) = expr.kind; - if let Some(first_arm) = arms.get(0); - if let hir::ExprKind::Call(_, iterargs) = iterexpr.kind; - if let Some(first_arg) = iterargs.get(0); - if iterargs.len() == 1 && arms.len() == 1 && first_arm.guard.is_none(); - if let hir::ExprKind::Loop(block, ..) = first_arm.body.kind; - if block.expr.is_none(); - if let [ _, _, ref let_stmt, ref body ] = *block.stmts; - if let hir::StmtKind::Local(local) = let_stmt.kind; - if let hir::StmtKind::Expr(body_expr) = body.kind; + if let hir::ExprKind::DropTemps(e) = expr.kind; + if let hir::ExprKind::Match(iterexpr, [arm], hir::MatchSource::ForLoopDesugar) = e.kind; + if let hir::ExprKind::Call(_, [arg]) = iterexpr.kind; + if let hir::ExprKind::Loop(block, ..) = arm.body.kind; + if let [stmt] = &*block.stmts; + if let hir::StmtKind::Expr(e) = stmt.kind; + if let hir::ExprKind::Match(_, [_, some_arm], _) = e.kind; + if let hir::PatKind::Struct(_, [field], _) = some_arm.pat.kind; then { return Some(Self { - pat: &*local.pat, - arg: first_arg, - body: body_expr, - span: first_arm.span + pat: field.pat, + arg, + body: some_arm.body, + loop_id: arm.body.hir_id, + span: expr.span.ctxt().outer_expn_data().call_site, }); } } @@ -569,38 +572,110 @@ impl FormatArgsExpn<'tcx> { } } } -} -/// Checks if a `let` statement is from a `for` loop desugaring. -pub fn is_from_for_desugar(local: &hir::Local<'_>) -> bool { - // This will detect plain for-loops without an actual variable binding: - // - // ``` - // for x in some_vec { - // // do stuff - // } - // ``` - if_chain! { - if let Some(expr) = local.init; - if let hir::ExprKind::Match(_, _, hir::MatchSource::ForLoopDesugar) = expr.kind; - then { - return true; + /// Returns a vector of `FormatArgsArg`. + pub fn args(&self) -> Option<Vec<FormatArgsArg<'tcx>>> { + if let Some(expr) = self.fmt_expr { + if_chain! { + if let ExprKind::AddrOf(BorrowKind::Ref, _, expr) = expr.kind; + if let ExprKind::Array(exprs) = expr.kind; + then { + exprs.iter().map(|fmt| { + if_chain! { + // struct `core::fmt::rt::v1::Argument` + if let ExprKind::Struct(_, fields, _) = fmt.kind; + if let Some(position_field) = fields.iter().find(|f| f.ident.name == sym::position); + if let ExprKind::Lit(lit) = &position_field.expr.kind; + if let LitKind::Int(position, _) = lit.node; + if let Ok(i) = usize::try_from(position); + let arg = &self.args[i]; + if let ExprKind::Call(_, [arg_name, _]) = arg.kind; + if let ExprKind::Field(_, j) = arg_name.kind; + if let Ok(j) = j.name.as_str().parse::<usize>(); + then { + Some(FormatArgsArg { value: self.value_args[j], arg, fmt: Some(fmt) }) + } else { + None + } + } + }).collect() + } else { + None + } + } + } else { + Some( + self.value_args + .iter() + .zip(self.args.iter()) + .map(|(value, arg)| FormatArgsArg { value, arg, fmt: None }) + .collect(), + ) } } +} + +/// Type representing a `FormatArgsExpn`'s format arguments +pub struct FormatArgsArg<'tcx> { + /// An element of `value_args` according to `position` + pub value: &'tcx Expr<'tcx>, + /// An element of `args` according to `position` + pub arg: &'tcx Expr<'tcx>, + /// An element of `fmt_expn` + pub fmt: Option<&'tcx Expr<'tcx>>, +} - // This detects a variable binding in for loop to avoid `let_unit_value` - // lint (see issue #1964). - // - // ``` - // for _ in vec![()] { - // // anything - // } - // ``` - if let hir::LocalSource::ForLoopDesugar = local.source { - return true; +impl<'tcx> FormatArgsArg<'tcx> { + /// Returns true if any formatting parameters are used that would have an effect on strings, + /// like `{:+2}` instead of just `{}`. + pub fn has_string_formatting(&self) -> bool { + self.fmt.map_or(false, |fmt| { + // `!` because these conditions check that `self` is unformatted. + !if_chain! { + // struct `core::fmt::rt::v1::Argument` + if let ExprKind::Struct(_, fields, _) = fmt.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(_, subfields, _) = format_field.expr.kind; + let mut precision_found = false; + let mut width_found = false; + if subfields.iter().all(|field| { + match field.ident.name { + sym::precision => { + precision_found = true; + if let ExprKind::Path(ref precision_path) = field.expr.kind { + last_path_segment(precision_path).ident.name == sym::Implied + } else { + false + } + } + sym::width => { + width_found = true; + if let ExprKind::Path(ref width_qpath) = field.expr.kind { + last_path_segment(width_qpath).ident.name == sym::Implied + } else { + false + } + } + _ => true, + } + }); + if precision_found && width_found; + then { true } else { false } + } + }) } - false + /// Returns true if the argument is formatted using `Display::fmt`. + pub fn is_display(&self) -> bool { + if_chain! { + if let ExprKind::Call(_, [_, format_field]) = self.arg.kind; + if let ExprKind::Path(QPath::Resolved(_, path)) = format_field.kind; + if let [.., t, _] = path.segments; + if t.ident.name == sym::Display; + then { true } else { false } + } + } } /// A parsed `panic!` expansion @@ -615,11 +690,8 @@ impl PanicExpn<'tcx> { /// Parses an expanded `panic!` invocation pub fn parse(expr: &'tcx Expr<'tcx>) -> Option<Self> { if_chain! { - if let ExprKind::Block(block, _) = expr.kind; - if let Some(init) = block.expr; - if let ExprKind::Call(_, [format_args]) = init.kind; + if let ExprKind::Call(_, [format_args]) = expr.kind; let expn_data = expr.span.ctxt().outer_expn_data(); - if let ExprKind::AddrOf(_, _, format_args) = format_args.kind; if let Some(format_args) = FormatArgsExpn::parse(format_args); then { Some(PanicExpn { @@ -632,3 +704,51 @@ impl PanicExpn<'tcx> { } } } + +/// A parsed `Vec` initialization expression +#[derive(Clone, Copy)] +pub enum VecInitKind { + /// `Vec::new()` + New, + /// `Vec::default()` or `Default::default()` + Default, + /// `Vec::with_capacity(123)` + WithLiteralCapacity(u64), + /// `Vec::with_capacity(slice.len())` + WithExprCapacity(HirId), +} + +/// Checks if given expression is an initialization of `Vec` and returns its kind. +pub fn get_vec_init_kind<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<VecInitKind> { + if let ExprKind::Call(func, args) = expr.kind { + match func.kind { + ExprKind::Path(QPath::TypeRelative(ty, name)) + if is_type_diagnostic_item(cx, cx.typeck_results().node_type(ty.hir_id), sym::Vec) => + { + if name.ident.name == sym::new { + return Some(VecInitKind::New); + } else if name.ident.name == symbol::kw::Default { + return Some(VecInitKind::Default); + } else if name.ident.name.as_str() == "with_capacity" { + let arg = args.get(0)?; + if_chain! { + if let ExprKind::Lit(lit) = &arg.kind; + if let LitKind::Int(num, _) = lit.node; + then { + return Some(VecInitKind::WithLiteralCapacity(num.try_into().ok()?)) + } + } + return Some(VecInitKind::WithExprCapacity(arg.hir_id)); + } + }, + ExprKind::Path(QPath::Resolved(_, path)) + if match_def_path(cx, path.res.opt_def_id()?, &paths::DEFAULT_TRAIT_METHOD) + && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::Vec) => + { + return Some(VecInitKind::Default); + }, + _ => (), + } + } + None +} diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 796c7dd70b..086fbc9d3d 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -37,7 +37,6 @@ pub mod sym_helper; #[allow(clippy::module_name_repetitions)] pub mod ast_utils; pub mod attrs; -pub mod camel_case; pub mod comparisons; pub mod consts; pub mod diagnostics; @@ -50,6 +49,7 @@ pub mod paths; pub mod ptr; pub mod qualify_min_const_fn; pub mod source; +pub mod str_utils; pub mod sugg; pub mod ty; pub mod usage; @@ -69,11 +69,13 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::hir_id::{HirIdMap, HirIdSet}; use rustc_hir::intravisit::{self, walk_expr, ErasedMap, FnKind, NestedVisitorMap, Visitor}; +use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::LangItem::{OptionNone, ResultErr, ResultOk}; use rustc_hir::{ - def, Arm, BindingAnnotation, Block, Body, Constness, Destination, Expr, ExprKind, FnDecl, GenericArgs, HirId, Impl, - ImplItem, ImplItemKind, IsAsync, Item, ItemKind, LangItem, Local, MatchSource, Mutability, Node, Param, Pat, - PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitRef, TyKind, UnOp, + def, Arm, BindingAnnotation, Block, Body, Constness, Destination, Expr, ExprKind, FnDecl, ForeignItem, GenericArgs, + HirId, Impl, ImplItem, ImplItemKind, IsAsync, Item, ItemKind, LangItem, Local, MatchSource, Mutability, Node, + Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitRef, TyKind, + UnOp, }; use rustc_lint::{LateContext, Level, Lint, LintContext}; use rustc_middle::hir::exports::Export; @@ -251,11 +253,7 @@ pub fn is_lang_ctor(cx: &LateContext<'_>, qpath: &QPath<'_>, lang_item: LangItem /// Returns `true` if this `span` was expanded by any macro. #[must_use] pub fn in_macro(span: Span) -> bool { - if span.from_expansion() { - !matches!(span.ctxt().outer_expn_data().kind, ExpnKind::Desugaring(..)) - } else { - false - } + span.from_expansion() && !matches!(span.ctxt().outer_expn_data().kind, ExpnKind::Desugaring(..)) } pub fn is_unit_expr(expr: &Expr<'_>) -> bool { @@ -714,7 +712,7 @@ pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { /// Checks if the top level expression can be moved into a closure as is. /// Currently checks for: /// * Break/Continue outside the given loop HIR ids. -/// * Yield/Return statments. +/// * Yield/Return statements. /// * Inline assembly. /// * Usages of a field of a local where the type of the local can be partially moved. /// @@ -1286,10 +1284,9 @@ pub fn is_integer_const(cx: &LateContext<'_>, e: &Expr<'_>, value: u128) -> bool } let enclosing_body = cx.tcx.hir().local_def_id(cx.tcx.hir().enclosing_body_owner(e.hir_id)); if let Some((Constant::Int(v), _)) = constant(cx, cx.tcx.typeck(enclosing_body), e) { - value == v - } else { - false + return value == v; } + false } /// Checks whether the given expression is a constant literal of the given value. @@ -1316,7 +1313,7 @@ pub fn is_adjusted(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { /// Returns the pre-expansion span if is this comes from an expansion of the /// macro `name`. -/// See also `is_direct_expn_of`. +/// See also [`is_direct_expn_of`]. #[must_use] pub fn is_expn_of(mut span: Span, name: &str) -> Option<Span> { loop { @@ -1339,13 +1336,13 @@ pub fn is_expn_of(mut span: Span, name: &str) -> Option<Span> { /// Returns the pre-expansion span if the span directly comes from an expansion /// of the macro `name`. -/// The difference with `is_expn_of` is that in -/// ```rust,ignore +/// The difference with [`is_expn_of`] is that in +/// ```rust +/// # macro_rules! foo { ($e:tt) => { $e } }; macro_rules! bar { ($e:expr) => { $e } } /// foo!(bar!(42)); /// ``` /// `42` is considered expanded from `foo!` and `bar!` by `is_expn_of` but only -/// `bar!` by -/// `is_direct_expn_of`. +/// from `bar!` by `is_direct_expn_of`. #[must_use] pub fn is_direct_expn_of(span: Span, name: &str) -> Option<Span> { if span.from_expansion() { @@ -1468,11 +1465,9 @@ pub fn is_self(slf: &Param<'_>) -> bool { } pub fn is_self_ty(slf: &hir::Ty<'_>) -> bool { - if_chain! { - if let TyKind::Path(QPath::Resolved(None, path)) = slf.kind; - if let Res::SelfTy(..) = path.res; - then { - return true + if let TyKind::Path(QPath::Resolved(None, path)) = slf.kind { + if let Res::SelfTy(..) = path.res { + return true; } } false @@ -1647,7 +1642,6 @@ pub fn match_panic_def_id(cx: &LateContext<'_>, did: DefId) -> bool { did, &[ &paths::BEGIN_PANIC, - &paths::BEGIN_PANIC_FMT, &paths::PANIC_ANY, &paths::PANICKING_PANIC, &paths::PANICKING_PANIC_FMT, @@ -2066,27 +2060,80 @@ macro_rules! unwrap_cargo_metadata { } pub fn is_hir_ty_cfg_dependant(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool { - if_chain! { - if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind; - if let Res::Def(_, def_id) = path.res; - then { - cx.tcx.has_attr(def_id, sym::cfg) || cx.tcx.has_attr(def_id, sym::cfg_attr) - } else { - false + if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind { + if let Res::Def(_, def_id) = path.res { + return cx.tcx.has_attr(def_id, sym::cfg) || cx.tcx.has_attr(def_id, sym::cfg_attr); } } + false } -/// Checks whether item either has `test` attribute applied, or -/// is a module with `test` in its name. -pub fn is_test_module_or_function(tcx: TyCtxt<'_>, item: &Item<'_>) -> bool { - if let Some(def_id) = tcx.hir().opt_local_def_id(item.hir_id()) { - if tcx.has_attr(def_id.to_def_id(), sym::test) { - return true; +struct VisitConstTestStruct<'tcx> { + tcx: TyCtxt<'tcx>, + names: Vec<Symbol>, + found: bool, +} +impl<'hir> ItemLikeVisitor<'hir> for VisitConstTestStruct<'hir> { + fn visit_item(&mut self, item: &Item<'_>) { + if let ItemKind::Const(ty, _body) = item.kind { + if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind { + // We could also check for the type name `test::TestDescAndFn` + // and the `#[rustc_test_marker]` attribute? + if let Res::Def(DefKind::Struct, _) = path.res { + let has_test_marker = self + .tcx + .hir() + .attrs(item.hir_id()) + .iter() + .any(|a| a.has_name(sym::rustc_test_marker)); + if has_test_marker && self.names.contains(&item.ident.name) { + self.found = true; + } + } + } } } + fn visit_trait_item(&mut self, _: &TraitItem<'_>) {} + fn visit_impl_item(&mut self, _: &ImplItem<'_>) {} + fn visit_foreign_item(&mut self, _: &ForeignItem<'_>) {} +} - matches!(item.kind, ItemKind::Mod(..)) && item.ident.name.as_str().contains("test") +/// Checks if the function containing the given `HirId` is a `#[test]` function +/// +/// Note: If you use this function, please add a `#[test]` case in `tests/ui_test`. +pub fn is_in_test_function(tcx: TyCtxt<'_>, id: hir::HirId) -> bool { + let names: Vec<_> = tcx + .hir() + .parent_iter(id) + // Since you can nest functions we need to collect all until we leave + // function scope + .filter_map(|(_id, node)| { + if let Node::Item(item) = node { + if let ItemKind::Fn(_, _, _) = item.kind { + return Some(item.ident.name); + } + } + None + }) + .collect(); + let parent_mod = tcx.parent_module(id); + let mut vis = VisitConstTestStruct { + tcx, + names, + found: false, + }; + tcx.hir().visit_item_likes_in_module(parent_mod, &mut vis); + vis.found +} + +/// Checks whether item either has `test` attribute applied, or +/// is a module with `test` in its name. +/// +/// Note: If you use this function, please add a `#[test]` case in `tests/ui_test`. +pub fn is_test_module_or_function(tcx: TyCtxt<'_>, item: &Item<'_>) -> bool { + is_in_test_function(tcx, item.hir_id()) + || matches!(item.kind, ItemKind::Mod(..)) + && item.ident.name.as_str().split('_').any(|a| a == "test" || a == "tests") } macro_rules! op_utils { diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs index e43c575602..501b08a47f 100644 --- a/src/tools/clippy/clippy_utils/src/paths.rs +++ b/src/tools/clippy/clippy_utils/src/paths.rs @@ -17,10 +17,15 @@ pub const APPLICABILITY_VALUES: [[&str; 3]; 4] = [ #[cfg(feature = "metadata-collector-lint")] pub const DIAGNOSTIC_BUILDER: [&str; 3] = ["rustc_errors", "diagnostic_builder", "DiagnosticBuilder"]; pub const ARC_PTR_EQ: [&str; 4] = ["alloc", "sync", "Arc", "ptr_eq"]; +#[allow(clippy::invalid_paths)] // `check_path` does not seem to work for macros +pub const ASSERT_EQ_MACRO: [&str; 3] = ["core", "macros", "assert_eq"]; +#[allow(clippy::invalid_paths)] // `check_path` does not seem to work for macros +pub const ASSERT_MACRO: [&str; 4] = ["core", "macros", "builtin", "assert"]; +#[allow(clippy::invalid_paths)] // `check_path` does not seem to work for macros +pub const ASSERT_NE_MACRO: [&str; 3] = ["core", "macros", "assert_ne"]; pub const ASMUT_TRAIT: [&str; 3] = ["core", "convert", "AsMut"]; pub const ASREF_TRAIT: [&str; 3] = ["core", "convert", "AsRef"]; pub(super) const BEGIN_PANIC: [&str; 3] = ["std", "panicking", "begin_panic"]; -pub(super) const BEGIN_PANIC_FMT: [&str; 3] = ["std", "panicking", "begin_panic_fmt"]; /// Preferably use the diagnostic item `sym::Borrow` where possible pub const BORROW_TRAIT: [&str; 3] = ["core", "borrow", "Borrow"]; pub const BTREEMAP_CONTAINS_KEY: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "contains_key"]; @@ -42,11 +47,17 @@ pub const DROP: [&str; 3] = ["core", "mem", "drop"]; pub const DURATION: [&str; 3] = ["core", "time", "Duration"]; #[cfg(feature = "internal-lints")] pub const EARLY_CONTEXT: [&str; 2] = ["rustc_lint", "EarlyContext"]; +#[allow(clippy::invalid_paths)] // `check_path` does not seem to work for macros +pub const EPRINT_MACRO: [&str; 3] = ["std", "macros", "eprint"]; +#[allow(clippy::invalid_paths)] // `check_path` does not seem to work for macros +pub const EPRINTLN_MACRO: [&str; 3] = ["std", "macros", "eprintln"]; pub const EXIT: [&str; 3] = ["std", "process", "exit"]; pub const F32_EPSILON: [&str; 4] = ["core", "f32", "<impl f32>", "EPSILON"]; pub const F64_EPSILON: [&str; 4] = ["core", "f64", "<impl f64>", "EPSILON"]; pub const FILE: [&str; 3] = ["std", "fs", "File"]; pub const FILE_TYPE: [&str; 3] = ["std", "fs", "FileType"]; +#[allow(clippy::invalid_paths)] // `check_path` does not seem to work for macros +pub const FORMAT_ARGS_MACRO: [&str; 4] = ["core", "macros", "builtin", "format_args"]; 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"]; @@ -109,6 +120,10 @@ pub const PERMISSIONS_FROM_MODE: [&str; 6] = ["std", "os", "unix", "fs", "Permis 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"]; +#[allow(clippy::invalid_paths)] // `check_path` does not seem to work for macros +pub const PRINT_MACRO: [&str; 3] = ["std", "macros", "print"]; +#[allow(clippy::invalid_paths)] // `check_path` does not seem to work for macros +pub const PRINTLN_MACRO: [&str; 3] = ["std", "macros", "println"]; 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"]; @@ -185,3 +200,7 @@ pub const VEC_NEW: [&str; 4] = ["alloc", "vec", "Vec", "new"]; pub const VEC_RESIZE: [&str; 4] = ["alloc", "vec", "Vec", "resize"]; pub const WEAK_ARC: [&str; 3] = ["alloc", "sync", "Weak"]; pub const WEAK_RC: [&str; 3] = ["alloc", "rc", "Weak"]; +#[allow(clippy::invalid_paths)] // `check_path` does not seem to work for macros +pub const WRITE_MACRO: [&str; 3] = ["core", "macros", "write"]; +#[allow(clippy::invalid_paths)] // `check_path` does not seem to work for macros +pub const WRITELN_MACRO: [&str; 3] = ["core", "macros", "writeln"]; diff --git a/src/tools/clippy/clippy_utils/src/str_utils.rs b/src/tools/clippy/clippy_utils/src/str_utils.rs new file mode 100644 index 0000000000..cba96e05a2 --- /dev/null +++ b/src/tools/clippy/clippy_utils/src/str_utils.rs @@ -0,0 +1,230 @@ +/// Dealing with sting indices can be hard, this struct ensures that both the +/// character and byte index are provided for correct indexing. +#[derive(Debug, Default, PartialEq, Eq)] +pub struct StrIndex { + pub char_index: usize, + pub byte_index: usize, +} + +impl StrIndex { + pub fn new(char_index: usize, byte_index: usize) -> Self { + Self { char_index, byte_index } + } +} + +/// Returns the index of the character after the first camel-case component of `s`. +/// +/// ``` +/// assert_eq!(camel_case_until("AbcDef"), StrIndex::new(6, 6)); +/// assert_eq!(camel_case_until("ABCD"), StrIndex::new(0, 0)); +/// assert_eq!(camel_case_until("AbcDD"), StrIndex::new(3, 3)); +/// assert_eq!(camel_case_until("Abc\u{f6}\u{f6}DD"), StrIndex::new(5, 7)); +/// ``` +#[must_use] +pub fn camel_case_until(s: &str) -> StrIndex { + let mut iter = s.char_indices().enumerate(); + if let Some((_char_index, (_, first))) = iter.next() { + if !first.is_uppercase() { + return StrIndex::new(0, 0); + } + } else { + return StrIndex::new(0, 0); + } + let mut up = true; + let mut last_index = StrIndex::new(0, 0); + for (char_index, (byte_index, c)) in iter { + if up { + if c.is_lowercase() { + up = false; + } else { + return last_index; + } + } else if c.is_uppercase() { + up = true; + last_index.byte_index = byte_index; + last_index.char_index = char_index; + } else if !c.is_lowercase() { + return StrIndex::new(char_index, byte_index); + } + } + + if up { + last_index + } else { + StrIndex::new(s.chars().count(), s.len()) + } +} + +/// Returns index of the last camel-case component of `s`. +/// +/// ``` +/// assert_eq!(camel_case_start("AbcDef"), StrIndex::new(0, 0)); +/// assert_eq!(camel_case_start("abcDef"), StrIndex::new(3, 3)); +/// assert_eq!(camel_case_start("ABCD"), StrIndex::new(4, 4)); +/// assert_eq!(camel_case_start("abcd"), StrIndex::new(4, 4)); +/// assert_eq!(camel_case_start("\u{f6}\u{f6}cd"), StrIndex::new(4, 6)); +/// ``` +#[must_use] +pub fn camel_case_start(s: &str) -> StrIndex { + let char_count = s.chars().count(); + let range = 0..char_count; + let mut iter = range.rev().zip(s.char_indices().rev()); + if let Some((char_index, (_, first))) = iter.next() { + if !first.is_lowercase() { + return StrIndex::new(char_index, s.len()); + } + } else { + return StrIndex::new(char_count, s.len()); + } + let mut down = true; + let mut last_index = StrIndex::new(char_count, s.len()); + for (char_index, (byte_index, c)) in iter { + if down { + if c.is_uppercase() { + down = false; + last_index.byte_index = byte_index; + last_index.char_index = char_index; + } else if !c.is_lowercase() { + return last_index; + } + } else if c.is_lowercase() { + down = true; + } else if c.is_uppercase() { + last_index.byte_index = byte_index; + last_index.char_index = char_index; + } else { + return last_index; + } + } + last_index +} + +/// Dealing with sting comparison can be complicated, this struct ensures that both the +/// character and byte count are provided for correct indexing. +#[derive(Debug, Default, PartialEq, Eq)] +pub struct StrCount { + pub char_count: usize, + pub byte_count: usize, +} + +impl StrCount { + pub fn new(char_count: usize, byte_count: usize) -> Self { + Self { char_count, byte_count } + } +} + +/// Returns the number of chars that match from the start +/// +/// ``` +/// assert_eq!(count_match_start("hello_mouse", "hello_penguin"), StrCount::new(6, 6)); +/// assert_eq!(count_match_start("hello_clippy", "bye_bugs"), StrCount::new(0, 0)); +/// assert_eq!(count_match_start("hello_world", "hello_world"), StrCount::new(11, 11)); +/// assert_eq!(count_match_start("T\u{f6}ffT\u{f6}ff", "T\u{f6}ff"), StrCount::new(4, 5)); +/// ``` +#[must_use] +pub fn count_match_start(str1: &str, str2: &str) -> StrCount { + // (char_index, char1) + let char_count = str1.chars().count(); + let iter1 = (0..=char_count).zip(str1.chars()); + // (byte_index, char2) + let iter2 = str2.char_indices(); + + iter1 + .zip(iter2) + .take_while(|((_, c1), (_, c2))| c1 == c2) + .last() + .map_or_else(StrCount::default, |((char_index, _), (byte_index, character))| { + StrCount::new(char_index + 1, byte_index + character.len_utf8()) + }) +} + +/// Returns the number of chars and bytes that match from the end +/// +/// ``` +/// assert_eq!(count_match_end("hello_cat", "bye_cat"), StrCount::new(4, 4)); +/// assert_eq!(count_match_end("if_item_thing", "enum_value"), StrCount::new(0, 0)); +/// assert_eq!(count_match_end("Clippy", "Clippy"), StrCount::new(6, 6)); +/// assert_eq!(count_match_end("MyT\u{f6}ff", "YourT\u{f6}ff"), StrCount::new(4, 5)); +/// ``` +#[must_use] +pub fn count_match_end(str1: &str, str2: &str) -> StrCount { + let char_count = str1.chars().count(); + if char_count == 0 { + return StrCount::default(); + } + + // (char_index, char1) + let iter1 = (0..char_count).rev().zip(str1.chars().rev()); + // (byte_index, char2) + let byte_count = str2.len(); + let iter2 = str2.char_indices().rev(); + + iter1 + .zip(iter2) + .take_while(|((_, c1), (_, c2))| c1 == c2) + .last() + .map_or_else(StrCount::default, |((char_index, _), (byte_index, _))| { + StrCount::new(char_count - char_index, byte_count - byte_index) + }) +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn camel_case_start_full() { + assert_eq!(camel_case_start("AbcDef"), StrIndex::new(0, 0)); + assert_eq!(camel_case_start("Abc"), StrIndex::new(0, 0)); + assert_eq!(camel_case_start("ABcd"), StrIndex::new(0, 0)); + assert_eq!(camel_case_start("ABcdEf"), StrIndex::new(0, 0)); + assert_eq!(camel_case_start("AabABcd"), StrIndex::new(0, 0)); + } + + #[test] + fn camel_case_start_partial() { + assert_eq!(camel_case_start("abcDef"), StrIndex::new(3, 3)); + assert_eq!(camel_case_start("aDbc"), StrIndex::new(1, 1)); + assert_eq!(camel_case_start("aabABcd"), StrIndex::new(3, 3)); + assert_eq!(camel_case_start("\u{f6}\u{f6}AabABcd"), StrIndex::new(2, 4)); + } + + #[test] + fn camel_case_start_not() { + assert_eq!(camel_case_start("AbcDef_"), StrIndex::new(7, 7)); + assert_eq!(camel_case_start("AbcDD"), StrIndex::new(5, 5)); + assert_eq!(camel_case_start("all_small"), StrIndex::new(9, 9)); + assert_eq!(camel_case_start("\u{f6}_all_small"), StrIndex::new(11, 12)); + } + + #[test] + fn camel_case_start_caps() { + assert_eq!(camel_case_start("ABCD"), StrIndex::new(4, 4)); + } + + #[test] + fn camel_case_until_full() { + assert_eq!(camel_case_until("AbcDef"), StrIndex::new(6, 6)); + assert_eq!(camel_case_until("Abc"), StrIndex::new(3, 3)); + assert_eq!(camel_case_until("Abc\u{f6}\u{f6}\u{f6}"), StrIndex::new(6, 9)); + } + + #[test] + fn camel_case_until_not() { + assert_eq!(camel_case_until("abcDef"), StrIndex::new(0, 0)); + assert_eq!(camel_case_until("aDbc"), StrIndex::new(0, 0)); + } + + #[test] + fn camel_case_until_partial() { + assert_eq!(camel_case_until("AbcDef_"), StrIndex::new(6, 6)); + assert_eq!(camel_case_until("CallTypeC"), StrIndex::new(8, 8)); + assert_eq!(camel_case_until("AbcDD"), StrIndex::new(3, 3)); + assert_eq!(camel_case_until("Abc\u{f6}\u{f6}DD"), StrIndex::new(5, 7)); + } + + #[test] + fn until_caps() { + assert_eq!(camel_case_until("ABCD"), StrIndex::new(0, 0)); + } +} diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs index 5b0efb1fd7..01fb944cc3 100644 --- a/src/tools/clippy/clippy_utils/src/sugg.rs +++ b/src/tools/clippy/clippy_utils/src/sugg.rs @@ -16,10 +16,10 @@ use std::convert::TryInto; use std::fmt::Display; use std::ops::{Add, Neg, Not, Sub}; -/// A helper type to build suggestion correctly handling parenthesis. +/// A helper type to build suggestion correctly handling parentheses. #[derive(Clone, PartialEq)] pub enum Sugg<'a> { - /// An expression that never needs parenthesis such as `1337` or `[0; 42]`. + /// An expression that never needs parentheses such as `1337` or `[0; 42]`. NonParen(Cow<'a, str>), /// An expression that does not fit in other variants. MaybeParen(Cow<'a, str>), @@ -283,7 +283,7 @@ impl<'a> Sugg<'a> { } } - /// Adds parenthesis to any expression that might need them. Suitable to the + /// Adds parentheses to any expression that might need them. Suitable to the /// `self` argument of a method call /// (e.g., to build `bar.foo()` or `(1 + 2).foo()`). pub fn maybe_par(self) -> Self { diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 6ebe1a0028..ca64ac7de3 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -367,3 +367,13 @@ pub fn same_type_and_consts(a: Ty<'tcx>, b: Ty<'tcx>) -> bool { _ => a == b, } } + +/// Checks if a given type looks safe to be uninitialized. +pub fn is_uninit_value_valid_for_ty(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { + match ty.kind() { + ty::Array(component, _) => is_uninit_value_valid_for_ty(cx, component), + ty::Tuple(types) => types.types().all(|ty| is_uninit_value_valid_for_ty(cx, ty)), + ty::Adt(adt, _) => cx.tcx.lang_items().maybe_uninit() == Some(adt.did), + _ => false, + } +} diff --git a/src/tools/clippy/doc/adding_lints.md b/src/tools/clippy/doc/adding_lints.md index 004eb28b44..bd32696d6d 100644 --- a/src/tools/clippy/doc/adding_lints.md +++ b/src/tools/clippy/doc/adding_lints.md @@ -16,6 +16,7 @@ because that's clearly a non-descriptive name. - [Edition 2018 tests](#edition-2018-tests) - [Testing manually](#testing-manually) - [Lint declaration](#lint-declaration) + - [Lint registration](#lint-registration) - [Lint passes](#lint-passes) - [Emitting a lint](#emitting-a-lint) - [Adding the lint logic](#adding-the-lint-logic) @@ -43,9 +44,9 @@ take a look at our [lint naming guidelines][lint_naming]. To get started on this lint you can run `cargo dev new_lint --name=foo_functions --pass=early --category=pedantic` (category will default to nursery if not provided). This command will create two files: `tests/ui/foo_functions.rs` and -`clippy_lints/src/foo_functions.rs`, as well as run `cargo dev update_lints` to -register the new lint. For cargo lints, two project hierarchies (fail/pass) will -be created by default under `tests/ui-cargo`. +`clippy_lints/src/foo_functions.rs`, as well as +[registering the lint](#lint-registration). For cargo lints, two project +hierarchies (fail/pass) will be created by default under `tests/ui-cargo`. Next, we'll open up these files and add our lint! @@ -220,32 +221,34 @@ declare_lint_pass!(FooFunctions => [FOO_FUNCTIONS]); impl EarlyLintPass for FooFunctions {} ``` -Normally after declaring the lint, we have to run `cargo dev update_lints`, -which updates some files, so Clippy knows about the new lint. Since we used -`cargo dev new_lint ...` to generate the lint declaration, this was done -automatically. While `update_lints` automates most of the things, it doesn't -automate everything. We will have to register our lint pass manually in the -`register_plugins` function in `clippy_lints/src/lib.rs`: +[declare_clippy_lint]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L60 +[example_lint_page]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure +[lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints +[category_level_mapping]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L110 + +## Lint registration + +When using `cargo dev new_lint`, the lint is automatically registered and +nothing more has to be done. + +When declaring a new lint by hand and `cargo dev update_lints` is used, the lint +pass may have to be registered manually in the `register_plugins` function in +`clippy_lints/src/lib.rs`: ```rust -store.register_early_pass(|| box foo_functions::FooFunctions); +store.register_early_pass(|| Box::new(foo_functions::FooFunctions)); ``` As one may expect, there is a corresponding `register_late_pass` method available as well. Without a call to one of `register_early_pass` or `register_late_pass`, the lint pass in question will not be run. -One reason that `cargo dev` does not automate this step is that multiple lints -can use the same lint pass, so registering the lint pass may already be done -when adding a new lint. Another reason that this step is not automated is that -the order that the passes are registered determines the order the passes -actually run, which in turn affects the order that any emitted lints are output -in. - -[declare_clippy_lint]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L60 -[example_lint_page]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure -[lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints -[category_level_mapping]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L110 +One reason that `cargo dev update_lints` does not automate this step is that +multiple lints can use the same lint pass, so registering the lint pass may +already be done when adding a new lint. Another reason that this step is not +automated is that the order that the passes are registered determines the order +the passes actually run, which in turn affects the order that any emitted lints +are output in. ## Lint passes @@ -564,7 +567,8 @@ in the following steps: /// <The configuration field doc comment> (configuration_ident: Type = DefaultValue), ``` - The doc comment will be automatically added to the lint documentation. + The doc comment is automatically added to the documentation of the listed lints. The default + value will be formatted using the `Debug` implementation of the type. 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 generated with the `declare_lint_pass!` macro. This struct needs to be defined manually diff --git a/src/tools/clippy/doc/basics.md b/src/tools/clippy/doc/basics.md index ff2e041743..57a90a924e 100644 --- a/src/tools/clippy/doc/basics.md +++ b/src/tools/clippy/doc/basics.md @@ -96,6 +96,7 @@ cargo dev setup git-hook # (experimental) Setup Clippy to work with IntelliJ-Rust cargo dev setup intellij ``` +More about intellij command usage and reasons [here](../CONTRIBUTING.md#intellij-rust) ## lintcheck `cargo lintcheck` will build and run clippy on a fixed set of crates and generate a log of the results. diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain index f98819303e..09554c0898 100644 --- a/src/tools/clippy/rust-toolchain +++ b/src/tools/clippy/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2021-10-07" +channel = "nightly-2021-11-04" components = ["llvm-tools-preview", "rustc-dev", "rust-src"] diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs index e8b1640c86..f25cf1d3ef 100644 --- a/src/tools/clippy/tests/compile-test.rs +++ b/src/tools/clippy/tests/compile-test.rs @@ -104,7 +104,10 @@ fn extern_flags() -> String { } fn default_config() -> compiletest::Config { - let mut config = compiletest::Config::default(); + let mut config = compiletest::Config { + edition: Some("2021".into()), + ..compiletest::Config::default() + }; if let Ok(filters) = env::var("TESTNAME") { config.filters = filters.split(',').map(std::string::ToString::to_string).collect(); @@ -149,6 +152,19 @@ fn run_ui(cfg: &mut compiletest::Config) { compiletest::run_tests(cfg); } +fn run_ui_test(cfg: &mut compiletest::Config) { + cfg.mode = TestMode::Ui; + cfg.src_base = Path::new("tests").join("ui_test"); + let _g = VarGuard::set("CARGO_MANIFEST_DIR", std::fs::canonicalize("tests").unwrap()); + let rustcflags = cfg.target_rustcflags.get_or_insert_with(Default::default); + let len = rustcflags.len(); + rustcflags.push_str(" --test"); + compiletest::run_tests(cfg); + if let Some(ref mut flags) = &mut cfg.target_rustcflags { + flags.truncate(len); + } +} + fn run_internal_tests(cfg: &mut compiletest::Config) { // only run internal tests with the internal-tests feature if !RUN_INTERNAL_TESTS { @@ -312,6 +328,7 @@ fn compile_test() { prepare_env(); let mut config = default_config(); run_ui(&mut config); + run_ui_test(&mut config); run_ui_toml(&mut config); run_ui_cargo(&mut config); run_internal_tests(&mut config); diff --git a/src/tools/clippy/tests/missing-test-files.rs b/src/tools/clippy/tests/missing-test-files.rs index bd342e390f..7d6edc2b1e 100644 --- a/src/tools/clippy/tests/missing-test-files.rs +++ b/src/tools/clippy/tests/missing-test-files.rs @@ -1,7 +1,10 @@ #![cfg_attr(feature = "deny-warnings", deny(warnings))] #![warn(rust_2018_idioms, unused_lifetimes)] #![allow(clippy::assertions_on_constants)] +#![feature(path_file_prefix)] +use std::cmp::Ordering; +use std::ffi::OsStr; use std::fs::{self, DirEntry}; use std::path::Path; @@ -21,29 +24,39 @@ fn test_missing_tests() { } } -/* -Test for missing files. - -Since rs files are alphabetically before stderr/stdout, we can sort by the full name -and iter in that order. If we've seen the file stem for the first time and it's not -a rust file, it means the rust file has to be missing. -*/ +// Test for missing files. fn explore_directory(dir: &Path) -> Vec<String> { let mut missing_files: Vec<String> = Vec::new(); let mut current_file = String::new(); let mut files: Vec<DirEntry> = fs::read_dir(dir).unwrap().filter_map(Result::ok).collect(); - files.sort_by_key(std::fs::DirEntry::path); + files.sort_by(|x, y| { + match x.path().file_prefix().cmp(&y.path().file_prefix()) { + Ordering::Equal => (), + ord => return ord, + } + // Sort rs files before the others if they share the same prefix. So when we see + // the file prefix for the first time and it's not a rust file, it means the rust + // file has to be missing. + match ( + x.path().extension().and_then(OsStr::to_str), + y.path().extension().and_then(OsStr::to_str), + ) { + (Some("rs"), _) => Ordering::Less, + (_, Some("rs")) => Ordering::Greater, + _ => Ordering::Equal, + } + }); for entry in &files { let path = entry.path(); if path.is_dir() { missing_files.extend(explore_directory(&path)); } else { - let file_stem = path.file_stem().unwrap().to_str().unwrap().to_string(); + let file_prefix = path.file_prefix().unwrap().to_str().unwrap().to_string(); if let Some(ext) = path.extension() { match ext.to_str().unwrap() { - "rs" => current_file = file_stem.clone(), + "rs" => current_file = file_prefix.clone(), "stderr" | "stdout" => { - if file_stem != current_file { + if file_prefix != current_file { missing_files.push(path.to_str().unwrap().to_string()); } }, diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.fixed b/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.fixed index 2ec0efe4c1..95b8c6dfe8 100644 --- a/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.fixed +++ b/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.fixed @@ -11,6 +11,6 @@ fn main() { Symbol::intern("foo") == rustc_span::sym::clippy; Symbol::intern("foo") == rustc_span::symbol::kw::SelfLower; Symbol::intern("foo") != rustc_span::symbol::kw::SelfUpper; - Ident::invalid().name == rustc_span::sym::clippy; - rustc_span::sym::clippy == Ident::invalid().name; + Ident::empty().name == rustc_span::sym::clippy; + rustc_span::sym::clippy == Ident::empty().name; } diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.rs b/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.rs index 87e1b3a2ee..ad6937cf60 100644 --- a/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.rs +++ b/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.rs @@ -11,6 +11,6 @@ fn main() { Symbol::intern("foo").as_str() == "clippy"; Symbol::intern("foo").to_string() == "self"; Symbol::intern("foo").to_ident_string() != "Self"; - &*Ident::invalid().as_str() == "clippy"; - "clippy" == Ident::invalid().to_string(); + &*Ident::empty().as_str() == "clippy"; + "clippy" == Ident::empty().to_string(); } diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.stderr b/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.stderr index b1284b7c8f..12e05eaa7a 100644 --- a/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.stderr +++ b/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.stderr @@ -26,14 +26,14 @@ LL | Symbol::intern("foo").to_ident_string() != "Self"; error: unnecessary `Symbol` to string conversion --> $DIR/unnecessary_symbol_str.rs:14:5 | -LL | &*Ident::invalid().as_str() == "clippy"; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Ident::invalid().name == rustc_span::sym::clippy` +LL | &*Ident::empty().as_str() == "clippy"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Ident::empty().name == rustc_span::sym::clippy` error: unnecessary `Symbol` to string conversion --> $DIR/unnecessary_symbol_str.rs:15:5 | -LL | "clippy" == Ident::invalid().to_string(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `rustc_span::sym::clippy == Ident::invalid().name` +LL | "clippy" == Ident::empty().to_string(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `rustc_span::sym::clippy == Ident::empty().name` error: aborting due to 5 previous errors diff --git a/src/tools/clippy/tests/ui-toml/functions_maxlines/test.rs b/src/tools/clippy/tests/ui-toml/functions_maxlines/test.rs index 33a3ef7513..e678c896fd 100644 --- a/src/tools/clippy/tests/ui-toml/functions_maxlines/test.rs +++ b/src/tools/clippy/tests/ui-toml/functions_maxlines/test.rs @@ -1,5 +1,3 @@ -// edition:2018 - #![warn(clippy::too_many_lines)] // This function should be considered one line. diff --git a/src/tools/clippy/tests/ui-toml/functions_maxlines/test.stderr b/src/tools/clippy/tests/ui-toml/functions_maxlines/test.stderr index 7551cac9f5..d736bf8997 100644 --- a/src/tools/clippy/tests/ui-toml/functions_maxlines/test.stderr +++ b/src/tools/clippy/tests/ui-toml/functions_maxlines/test.stderr @@ -1,5 +1,5 @@ error: this function has too many lines (2/1) - --> $DIR/test.rs:20:1 + --> $DIR/test.rs:18:1 | LL | / fn too_many_lines() { LL | | println!("This is bad."); @@ -10,7 +10,7 @@ LL | | } = note: `-D clippy::too-many-lines` implied by `-D warnings` error: this function has too many lines (4/1) - --> $DIR/test.rs:26:1 + --> $DIR/test.rs:24:1 | LL | / async fn async_too_many_lines() { LL | | println!("This is bad."); @@ -19,7 +19,7 @@ LL | | } | |_^ error: this function has too many lines (4/1) - --> $DIR/test.rs:32:1 + --> $DIR/test.rs:30:1 | LL | / fn closure_too_many_lines() { LL | | let _ = { @@ -30,7 +30,7 @@ LL | | } | |_^ error: this function has too many lines (2/1) - --> $DIR/test.rs:54:1 + --> $DIR/test.rs:52:1 | LL | / fn comment_before_code() { LL | | let _ = "test"; diff --git a/src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.rs b/src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.rs index 9377eb69b2..2498672d77 100644 --- a/src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.rs +++ b/src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.rs @@ -1,3 +1,4 @@ +#![allow(clippy::excessive_precision)] #[deny(clippy::unreadable_literal)] fn allow_inconsistent_digit_grouping() { diff --git a/src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.stderr b/src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.stderr index 9119ef19a7..be505bda47 100644 --- a/src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.stderr +++ b/src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.stderr @@ -1,5 +1,5 @@ error: digits grouped inconsistently by underscores - --> $DIR/test.rs:18:18 + --> $DIR/test.rs:19:18 | LL | let _fail1 = 100_200_300.123456789; | ^^^^^^^^^^^^^^^^^^^^^ help: consider: `100_200_300.123_456_789` diff --git a/src/tools/clippy/tests/ui-toml/toml_disallowed_type/clippy.toml b/src/tools/clippy/tests/ui-toml/toml_disallowed_type/clippy.toml index dac4446703..6cb9e2ef95 100644 --- a/src/tools/clippy/tests/ui-toml/toml_disallowed_type/clippy.toml +++ b/src/tools/clippy/tests/ui-toml/toml_disallowed_type/clippy.toml @@ -7,5 +7,9 @@ disallowed-types = [ "std::time::Instant", "std::io::Read", "std::primitive::usize", - "bool" + "bool", + # can give path and reason with an inline table + { path = "std::net::Ipv4Addr", reason = "no IPv4 allowed" }, + # can use an inline table but omit reason + { path = "std::net::TcpListener" }, ] diff --git a/src/tools/clippy/tests/ui-toml/toml_disallowed_type/conf_disallowed_type.rs b/src/tools/clippy/tests/ui-toml/toml_disallowed_type/conf_disallowed_type.rs index 0871a3073a..410f076505 100644 --- a/src/tools/clippy/tests/ui-toml/toml_disallowed_type/conf_disallowed_type.rs +++ b/src/tools/clippy/tests/ui-toml/toml_disallowed_type/conf_disallowed_type.rs @@ -25,6 +25,10 @@ struct GenArg<const U: usize>([u8; U]); static BAD: foo::atomic::AtomicPtr<()> = foo::atomic::AtomicPtr::new(std::ptr::null_mut()); +fn ip(_: std::net::Ipv4Addr) {} + +fn listener(_: std::net::TcpListener) {} + #[allow(clippy::diverging_sub_expression)] fn main() { let _: std::collections::HashMap<(), ()> = std::collections::HashMap::new(); diff --git a/src/tools/clippy/tests/ui-toml/toml_disallowed_type/conf_disallowed_type.stderr b/src/tools/clippy/tests/ui-toml/toml_disallowed_type/conf_disallowed_type.stderr index 90ce7db2cc..08a400a836 100644 --- a/src/tools/clippy/tests/ui-toml/toml_disallowed_type/conf_disallowed_type.stderr +++ b/src/tools/clippy/tests/ui-toml/toml_disallowed_type/conf_disallowed_type.stderr @@ -60,59 +60,73 @@ error: `usize` is not allowed according to config LL | struct GenArg<const U: usize>([u8; U]); | ^^^^^ +error: `std::net::Ipv4Addr` is not allowed according to config + --> $DIR/conf_disallowed_type.rs:28:10 + | +LL | fn ip(_: std::net::Ipv4Addr) {} + | ^^^^^^^^^^^^^^^^^^ + | + = note: no IPv4 allowed (from clippy.toml) + +error: `std::net::TcpListener` is not allowed according to config + --> $DIR/conf_disallowed_type.rs:30:16 + | +LL | fn listener(_: std::net::TcpListener) {} + | ^^^^^^^^^^^^^^^^^^^^^ + error: `std::collections::HashMap` is not allowed according to config - --> $DIR/conf_disallowed_type.rs:30:48 + --> $DIR/conf_disallowed_type.rs:34:48 | LL | let _: std::collections::HashMap<(), ()> = std::collections::HashMap::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: `std::collections::HashMap` is not allowed according to config - --> $DIR/conf_disallowed_type.rs:30:12 + --> $DIR/conf_disallowed_type.rs:34:12 | LL | let _: std::collections::HashMap<(), ()> = std::collections::HashMap::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `std::time::Instant` is not allowed according to config - --> $DIR/conf_disallowed_type.rs:31:13 + --> $DIR/conf_disallowed_type.rs:35:13 | LL | let _ = Sneaky::now(); | ^^^^^^ error: `std::sync::atomic::AtomicU32` is not allowed according to config - --> $DIR/conf_disallowed_type.rs:32:13 + --> $DIR/conf_disallowed_type.rs:36:13 | LL | let _ = foo::atomic::AtomicU32::new(0); | ^^^^^^^^^^^^^^^^^^^^^^ error: `std::sync::atomic::AtomicU32` is not allowed according to config - --> $DIR/conf_disallowed_type.rs:33:17 + --> $DIR/conf_disallowed_type.rs:37:17 | LL | static FOO: std::sync::atomic::AtomicU32 = foo::atomic::AtomicU32::new(1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `std::sync::atomic::AtomicU32` is not allowed according to config - --> $DIR/conf_disallowed_type.rs:33:48 + --> $DIR/conf_disallowed_type.rs:37:48 | LL | static FOO: std::sync::atomic::AtomicU32 = foo::atomic::AtomicU32::new(1); | ^^^^^^^^^^^^^^^^^^^^^^ error: `syn::TypePath` is not allowed according to config - --> $DIR/conf_disallowed_type.rs:34:43 + --> $DIR/conf_disallowed_type.rs:38:43 | LL | let _: std::collections::BTreeMap<(), syn::TypePath> = Default::default(); | ^^^^^^^^^^^^^ error: `syn::Ident` is not allowed according to config - --> $DIR/conf_disallowed_type.rs:35:13 + --> $DIR/conf_disallowed_type.rs:39:13 | LL | let _ = syn::Ident::new("", todo!()); | ^^^^^^^^^^ error: `usize` is not allowed according to config - --> $DIR/conf_disallowed_type.rs:37:12 + --> $DIR/conf_disallowed_type.rs:41:12 | LL | let _: usize = 64_usize; | ^^^^^ -error: aborting due to 19 previous errors +error: aborting due to 21 previous errors diff --git a/src/tools/clippy/tests/ui/assertions_on_constants.rs b/src/tools/clippy/tests/ui/assertions_on_constants.rs index 2180f848d6..cb516d0f97 100644 --- a/src/tools/clippy/tests/ui/assertions_on_constants.rs +++ b/src/tools/clippy/tests/ui/assertions_on_constants.rs @@ -1,3 +1,4 @@ +//FIXME: suggestions are wrongly expanded, this should be fixed along with #7843 #![allow(non_fmt_panics)] macro_rules! assert_const { @@ -6,7 +7,6 @@ macro_rules! assert_const { debug_assert!($len < 0); }; } - fn main() { assert!(true); assert!(false); @@ -14,7 +14,7 @@ fn main() { assert!(false, "false message"); let msg = "panic message"; - assert!(false, msg.to_uppercase()); + assert!(false, "{}", msg.to_uppercase()); const B: bool = true; assert!(B); diff --git a/src/tools/clippy/tests/ui/assertions_on_constants.stderr b/src/tools/clippy/tests/ui/assertions_on_constants.stderr index 4ca1e6f6e8..ec80ec702f 100644 --- a/src/tools/clippy/tests/ui/assertions_on_constants.stderr +++ b/src/tools/clippy/tests/ui/assertions_on_constants.stderr @@ -26,22 +26,13 @@ LL | assert!(true, "true message"); = help: remove it = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) -error: `assert!(false, "false message")` should probably be replaced +error: `assert!(false, $crate::const_format_args!($($t)+))` should probably be replaced --> $DIR/assertions_on_constants.rs:14:5 | LL | assert!(false, "false message"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: use `panic!("false message")` or `unreachable!("false message")` - = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: `assert!(false, msg.to_uppercase())` should probably be replaced - --> $DIR/assertions_on_constants.rs:17:5 - | -LL | assert!(false, msg.to_uppercase()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: use `panic!(msg.to_uppercase())` or `unreachable!(msg.to_uppercase())` + = help: use `panic!($crate::const_format_args!($($t)+))` or `unreachable!($crate::const_format_args!($($t)+))` = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) error: `assert!(true)` will be optimized out by the compiler @@ -62,13 +53,13 @@ LL | assert!(C); = help: use `panic!()` or `unreachable!()` = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) -error: `assert!(false, "C message")` should probably be replaced +error: `assert!(false, $crate::const_format_args!($($t)+))` should probably be replaced --> $DIR/assertions_on_constants.rs:24:5 | LL | assert!(C, "C message"); | ^^^^^^^^^^^^^^^^^^^^^^^ | - = help: use `panic!("C message")` or `unreachable!("C message")` + = help: use `panic!($crate::const_format_args!($($t)+))` or `unreachable!($crate::const_format_args!($($t)+))` = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) error: `debug_assert!(true)` will be optimized out by the compiler @@ -80,5 +71,5 @@ LL | debug_assert!(true); = help: remove it = note: this error originates in the macro `$crate::assert` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 9 previous errors +error: aborting due to 8 previous errors diff --git a/src/tools/clippy/tests/ui/async_yields_async.fixed b/src/tools/clippy/tests/ui/async_yields_async.fixed index 9b1a7ac3ba..e20b58269b 100644 --- a/src/tools/clippy/tests/ui/async_yields_async.fixed +++ b/src/tools/clippy/tests/ui/async_yields_async.fixed @@ -1,5 +1,4 @@ // run-rustfix -// edition:2018 #![feature(async_closure)] #![warn(clippy::async_yields_async)] diff --git a/src/tools/clippy/tests/ui/async_yields_async.rs b/src/tools/clippy/tests/ui/async_yields_async.rs index 731c094edb..c1dfa39845 100644 --- a/src/tools/clippy/tests/ui/async_yields_async.rs +++ b/src/tools/clippy/tests/ui/async_yields_async.rs @@ -1,5 +1,4 @@ // run-rustfix -// edition:2018 #![feature(async_closure)] #![warn(clippy::async_yields_async)] diff --git a/src/tools/clippy/tests/ui/async_yields_async.stderr b/src/tools/clippy/tests/ui/async_yields_async.stderr index 3f2051458f..b0c4215e7d 100644 --- a/src/tools/clippy/tests/ui/async_yields_async.stderr +++ b/src/tools/clippy/tests/ui/async_yields_async.stderr @@ -1,5 +1,5 @@ error: an async construct yields a type which is itself awaitable - --> $DIR/async_yields_async.rs:40:9 + --> $DIR/async_yields_async.rs:39:9 | LL | let _h = async { | ____________________- @@ -20,7 +20,7 @@ LL + }.await | error: an async construct yields a type which is itself awaitable - --> $DIR/async_yields_async.rs:45:9 + --> $DIR/async_yields_async.rs:44:9 | LL | let _i = async { | ____________________- @@ -33,7 +33,7 @@ LL | | }; | |_____- outer async construct error: an async construct yields a type which is itself awaitable - --> $DIR/async_yields_async.rs:51:9 + --> $DIR/async_yields_async.rs:50:9 | LL | let _j = async || { | _______________________- @@ -53,7 +53,7 @@ LL + }.await | error: an async construct yields a type which is itself awaitable - --> $DIR/async_yields_async.rs:56:9 + --> $DIR/async_yields_async.rs:55:9 | LL | let _k = async || { | _______________________- @@ -66,7 +66,7 @@ LL | | }; | |_____- outer async construct error: an async construct yields a type which is itself awaitable - --> $DIR/async_yields_async.rs:58:23 + --> $DIR/async_yields_async.rs:57:23 | LL | let _l = async || CustomFutureType; | ^^^^^^^^^^^^^^^^ @@ -76,7 +76,7 @@ LL | let _l = async || CustomFutureType; | help: consider awaiting this value: `CustomFutureType.await` error: an async construct yields a type which is itself awaitable - --> $DIR/async_yields_async.rs:64:9 + --> $DIR/async_yields_async.rs:63:9 | LL | let _m = async || { | _______________________- diff --git a/src/tools/clippy/tests/ui/author/for_loop.stdout b/src/tools/clippy/tests/ui/author/for_loop.stdout index f1b4d4e096..4d0e13c833 100644 --- a/src/tools/clippy/tests/ui/author/for_loop.stdout +++ b/src/tools/clippy/tests/ui/author/for_loop.stdout @@ -11,11 +11,8 @@ if_chain! { // unimplemented: field checks if arms.len() == 1; if let ExprKind::Loop(ref body, ref label, LoopSource::ForLoop) = arms[0].body.kind; - if body.stmts.len() == 4; - if let StmtKind::Local(ref local) = body.stmts[0].kind; - if let PatKind::Binding(BindingAnnotation::Mutable, _, name, None) = local.pat.kind; - if name.as_str() == "__next"; - if let StmtKind::Expr(ref e, _) = body.stmts[1].kind + if body.stmts.len() == 1; + if let StmtKind::Expr(ref e, _) = body.stmts[0].kind if let ExprKind::Match(ref expr2, ref arms1, MatchSource::ForLoopDesugar) = e.kind; if let ExprKind::Call(ref func1, ref args1) = expr2.kind; if let ExprKind::Path(ref path2) = func1.kind; @@ -25,39 +22,27 @@ if_chain! { if let ExprKind::Path(ref path3) = inner.kind; if match_qpath(path3, &["iter"]); if arms1.len() == 2; - if let ExprKind::Assign(ref target, ref value, ref _span) = arms1[0].body.kind; - if let ExprKind::Path(ref path4) = target.kind; - if match_qpath(path4, &["__next"]); - if let ExprKind::Path(ref path5) = value.kind; - if match_qpath(path5, &["val"]); - if let PatKind::Struct(ref path6, ref fields1, false) = arms1[0].pat.kind; - if matches!(path6, QPath::LangItem(LangItem::OptionSome, _)); - if fields1.len() == 1; - // unimplemented: field checks - if let ExprKind::Break(ref destination, None) = arms1[1].body.kind; - if let PatKind::Struct(ref path7, ref fields2, false) = arms1[1].pat.kind; - if matches!(path7, QPath::LangItem(LangItem::OptionNone, _)); - if fields2.len() == 0; + if let ExprKind::Break(ref destination, None) = arms1[0].body.kind; + if let PatKind::Struct(ref path4, ref fields1, false) = arms1[0].pat.kind; + if matches!(path4, QPath::LangItem(LangItem::OptionNone, _)); + if fields1.len() == 0; // unimplemented: field checks - if let StmtKind::Local(ref local1) = body.stmts[2].kind; - if let Some(ref init) = local1.init; - if let ExprKind::Path(ref path8) = init.kind; - if match_qpath(path8, &["__next"]); - if let PatKind::Binding(BindingAnnotation::Unannotated, _, name1, None) = local1.pat.kind; - if name1.as_str() == "y"; - if let StmtKind::Expr(ref e1, _) = body.stmts[3].kind - if let ExprKind::Block(ref block) = e1.kind; + if let ExprKind::Block(ref block) = arms1[1].body.kind; if block.stmts.len() == 1; - if let StmtKind::Local(ref local2) = block.stmts[0].kind; - if let Some(ref init1) = local2.init; - if let ExprKind::Path(ref path9) = init1.kind; - if match_qpath(path9, &["y"]); - if let PatKind::Binding(BindingAnnotation::Unannotated, _, name2, None) = local2.pat.kind; - if name2.as_str() == "z"; + if let StmtKind::Local(ref local) = block.stmts[0].kind; + if let Some(ref init) = local.init; + if let ExprKind::Path(ref path5) = init.kind; + if match_qpath(path5, &["y"]); + if let PatKind::Binding(BindingAnnotation::Unannotated, _, name, None) = local.pat.kind; + if name.as_str() == "z"; if block.expr.is_none(); + if let PatKind::Struct(ref path6, ref fields2, false) = arms1[1].pat.kind; + if matches!(path6, QPath::LangItem(LangItem::OptionSome, _)); + if fields2.len() == 1; + // unimplemented: field checks if body.expr.is_none(); - if let PatKind::Binding(BindingAnnotation::Mutable, _, name3, None) = arms[0].pat.kind; - if name3.as_str() == "iter"; + if let PatKind::Binding(BindingAnnotation::Mutable, _, name1, None) = arms[0].pat.kind; + if name1.as_str() == "iter"; then { // report your lint here } diff --git a/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs b/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs index 170955e726..0251fada9e 100644 --- a/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs +++ b/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs @@ -113,3 +113,10 @@ macro_rules! default_numeric_fallback { let x = 22; }; } + +#[macro_export] +macro_rules! mut_mut { + () => { + let mut_mut_ty: &mut &mut u32 = &mut &mut 1u32; + }; +} diff --git a/src/tools/clippy/tests/ui/await_holding_lock.rs b/src/tools/clippy/tests/ui/await_holding_lock.rs index 0458950ede..dd6640a387 100644 --- a/src/tools/clippy/tests/ui/await_holding_lock.rs +++ b/src/tools/clippy/tests/ui/await_holding_lock.rs @@ -1,4 +1,3 @@ -// edition:2018 #![warn(clippy::await_holding_lock)] use std::sync::Mutex; diff --git a/src/tools/clippy/tests/ui/await_holding_lock.stderr b/src/tools/clippy/tests/ui/await_holding_lock.stderr index a5fcff7e0e..ddfb104cdf 100644 --- a/src/tools/clippy/tests/ui/await_holding_lock.stderr +++ b/src/tools/clippy/tests/ui/await_holding_lock.stderr @@ -1,12 +1,12 @@ error: this MutexGuard is held across an 'await' point. Consider using an async-aware Mutex type or ensuring the MutexGuard is dropped before calling await - --> $DIR/await_holding_lock.rs:7:9 + --> $DIR/await_holding_lock.rs:6:9 | LL | let guard = x.lock().unwrap(); | ^^^^^ | = note: `-D clippy::await-holding-lock` implied by `-D warnings` note: these are all the await points this lock is held through - --> $DIR/await_holding_lock.rs:7:5 + --> $DIR/await_holding_lock.rs:6:5 | LL | / let guard = x.lock().unwrap(); LL | | baz().await @@ -14,13 +14,13 @@ LL | | } | |_^ error: this MutexGuard is held across an 'await' point. Consider using an async-aware Mutex type or ensuring the MutexGuard is dropped before calling await - --> $DIR/await_holding_lock.rs:28:9 + --> $DIR/await_holding_lock.rs:27:9 | LL | let guard = x.lock().unwrap(); | ^^^^^ | note: these are all the await points this lock is held through - --> $DIR/await_holding_lock.rs:28:5 + --> $DIR/await_holding_lock.rs:27:5 | LL | / let guard = x.lock().unwrap(); LL | | @@ -32,13 +32,13 @@ LL | | } | |_^ error: this MutexGuard is held across an 'await' point. Consider using an async-aware Mutex type or ensuring the MutexGuard is dropped before calling await - --> $DIR/await_holding_lock.rs:41:13 + --> $DIR/await_holding_lock.rs:40:13 | LL | let guard = x.lock().unwrap(); | ^^^^^ | note: these are all the await points this lock is held through - --> $DIR/await_holding_lock.rs:41:9 + --> $DIR/await_holding_lock.rs:40:9 | LL | / let guard = x.lock().unwrap(); LL | | baz().await @@ -46,13 +46,13 @@ LL | | }; | |_____^ error: this MutexGuard is held across an 'await' point. Consider using an async-aware Mutex type or ensuring the MutexGuard is dropped before calling await - --> $DIR/await_holding_lock.rs:53:13 + --> $DIR/await_holding_lock.rs:52:13 | LL | let guard = x.lock().unwrap(); | ^^^^^ | note: these are all the await points this lock is held through - --> $DIR/await_holding_lock.rs:53:9 + --> $DIR/await_holding_lock.rs:52:9 | LL | / let guard = x.lock().unwrap(); LL | | baz().await diff --git a/src/tools/clippy/tests/ui/await_holding_refcell_ref.rs b/src/tools/clippy/tests/ui/await_holding_refcell_ref.rs index 88841597bb..23b7095de3 100644 --- a/src/tools/clippy/tests/ui/await_holding_refcell_ref.rs +++ b/src/tools/clippy/tests/ui/await_holding_refcell_ref.rs @@ -1,4 +1,3 @@ -// edition:2018 #![warn(clippy::await_holding_refcell_ref)] use std::cell::RefCell; diff --git a/src/tools/clippy/tests/ui/await_holding_refcell_ref.stderr b/src/tools/clippy/tests/ui/await_holding_refcell_ref.stderr index 55e41dbca9..67cc0032be 100644 --- a/src/tools/clippy/tests/ui/await_holding_refcell_ref.stderr +++ b/src/tools/clippy/tests/ui/await_holding_refcell_ref.stderr @@ -1,12 +1,12 @@ error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await - --> $DIR/await_holding_refcell_ref.rs:7:9 + --> $DIR/await_holding_refcell_ref.rs:6:9 | LL | let b = x.borrow(); | ^ | = note: `-D clippy::await-holding-refcell-ref` implied by `-D warnings` note: these are all the await points this ref is held through - --> $DIR/await_holding_refcell_ref.rs:7:5 + --> $DIR/await_holding_refcell_ref.rs:6:5 | LL | / let b = x.borrow(); LL | | baz().await @@ -14,13 +14,13 @@ LL | | } | |_^ error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await - --> $DIR/await_holding_refcell_ref.rs:12:9 + --> $DIR/await_holding_refcell_ref.rs:11:9 | LL | let b = x.borrow_mut(); | ^ | note: these are all the await points this ref is held through - --> $DIR/await_holding_refcell_ref.rs:12:5 + --> $DIR/await_holding_refcell_ref.rs:11:5 | LL | / let b = x.borrow_mut(); LL | | baz().await @@ -28,13 +28,13 @@ LL | | } | |_^ error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await - --> $DIR/await_holding_refcell_ref.rs:33:9 + --> $DIR/await_holding_refcell_ref.rs:32:9 | LL | let b = x.borrow_mut(); | ^ | note: these are all the await points this ref is held through - --> $DIR/await_holding_refcell_ref.rs:33:5 + --> $DIR/await_holding_refcell_ref.rs:32:5 | LL | / let b = x.borrow_mut(); LL | | @@ -46,13 +46,13 @@ LL | | } | |_^ error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await - --> $DIR/await_holding_refcell_ref.rs:45:9 + --> $DIR/await_holding_refcell_ref.rs:44:9 | LL | let b = x.borrow_mut(); | ^ | note: these are all the await points this ref is held through - --> $DIR/await_holding_refcell_ref.rs:45:5 + --> $DIR/await_holding_refcell_ref.rs:44:5 | LL | / let b = x.borrow_mut(); LL | | @@ -64,13 +64,13 @@ LL | | } | |_^ error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await - --> $DIR/await_holding_refcell_ref.rs:60:13 + --> $DIR/await_holding_refcell_ref.rs:59:13 | LL | let b = x.borrow_mut(); | ^ | note: these are all the await points this ref is held through - --> $DIR/await_holding_refcell_ref.rs:60:9 + --> $DIR/await_holding_refcell_ref.rs:59:9 | LL | / let b = x.borrow_mut(); LL | | baz().await @@ -78,13 +78,13 @@ LL | | }; | |_____^ error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await - --> $DIR/await_holding_refcell_ref.rs:72:13 + --> $DIR/await_holding_refcell_ref.rs:71:13 | LL | let b = x.borrow_mut(); | ^ | note: these are all the await points this ref is held through - --> $DIR/await_holding_refcell_ref.rs:72:9 + --> $DIR/await_holding_refcell_ref.rs:71:9 | LL | / let b = x.borrow_mut(); LL | | baz().await diff --git a/src/tools/clippy/tests/ui/cast.rs b/src/tools/clippy/tests/ui/cast.rs index 8ee0969b0f..ebc1ed5587 100644 --- a/src/tools/clippy/tests/ui/cast.rs +++ b/src/tools/clippy/tests/ui/cast.rs @@ -92,4 +92,27 @@ fn main() { (1i64).checked_rem_euclid(-1i64).unwrap() as u64; (1i64).checked_rem_euclid(-1i64).unwrap() as u128; (1isize).checked_rem_euclid(-1isize).unwrap() as usize; + + // no lint for `cast_possible_truncation` + // with `signum` method call (see issue #5395) + let x: i64 = 5; + let _ = x.signum() as i32; + + let s = x.signum(); + let _ = s as i32; + + // Test for signed min + (-99999999999i64).min(1) as i8; // should be linted because signed + + // Test for various operations that remove enough bits for the result to fit + (999999u64 & 1) as u8; + (999999u64 % 15) as u8; + (999999u64 / 0x1_0000_0000_0000) as u16; + ({ 999999u64 >> 56 }) as u8; + ({ + let x = 999999u64; + x.min(1) + }) as u8; + 999999u64.clamp(0, 255) as u8; + 999999u64.clamp(0, 256) as u8; // should still be linted } diff --git a/src/tools/clippy/tests/ui/cast.stderr b/src/tools/clippy/tests/ui/cast.stderr index 4c66d73649..edf8790cf3 100644 --- a/src/tools/clippy/tests/ui/cast.stderr +++ b/src/tools/clippy/tests/ui/cast.stderr @@ -138,5 +138,17 @@ error: casting `isize` to `usize` may lose the sign of the value LL | -1isize as usize; | ^^^^^^^^^^^^^^^^ -error: aborting due to 22 previous errors +error: casting `i64` to `i8` may truncate the value + --> $DIR/cast.rs:105:5 + | +LL | (-99999999999i64).min(1) as i8; // should be linted because signed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: casting `u64` to `u8` may truncate the value + --> $DIR/cast.rs:117:5 + | +LL | 999999u64.clamp(0, 256) as u8; // should still be linted + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 24 previous errors diff --git a/src/tools/clippy/tests/ui/cfg_attr_rustfmt.fixed b/src/tools/clippy/tests/ui/cfg_attr_rustfmt.fixed index 4e583a25b9..061a4ab9b2 100644 --- a/src/tools/clippy/tests/ui/cfg_attr_rustfmt.fixed +++ b/src/tools/clippy/tests/ui/cfg_attr_rustfmt.fixed @@ -1,7 +1,7 @@ // run-rustfix #![feature(stmt_expr_attributes)] -#![allow(unused, clippy::no_effect)] +#![allow(unused, clippy::no_effect, clippy::unnecessary_operation)] #![warn(clippy::deprecated_cfg_attr)] // This doesn't get linted, see known problems diff --git a/src/tools/clippy/tests/ui/cfg_attr_rustfmt.rs b/src/tools/clippy/tests/ui/cfg_attr_rustfmt.rs index 9c0fcf6fb4..035169fab8 100644 --- a/src/tools/clippy/tests/ui/cfg_attr_rustfmt.rs +++ b/src/tools/clippy/tests/ui/cfg_attr_rustfmt.rs @@ -1,7 +1,7 @@ // run-rustfix #![feature(stmt_expr_attributes)] -#![allow(unused, clippy::no_effect)] +#![allow(unused, clippy::no_effect, clippy::unnecessary_operation)] #![warn(clippy::deprecated_cfg_attr)] // This doesn't get linted, see known problems diff --git a/src/tools/clippy/tests/ui/crashes/auxiliary/ice-7868-aux.rs b/src/tools/clippy/tests/ui/crashes/auxiliary/ice-7868-aux.rs new file mode 100644 index 0000000000..bee29894b6 --- /dev/null +++ b/src/tools/clippy/tests/ui/crashes/auxiliary/ice-7868-aux.rs @@ -0,0 +1,3 @@ +fn zero() { + unsafe { 0 }; +} diff --git a/src/tools/clippy/tests/ui/crashes/ice-3969.rs b/src/tools/clippy/tests/ui/crashes/ice-3969.rs index 4feab7910b..9b68cac7ff 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-3969.rs +++ b/src/tools/clippy/tests/ui/crashes/ice-3969.rs @@ -7,7 +7,6 @@ // in type inference. #![feature(trivial_bounds)] #![allow(unused)] - trait A {} impl A for i32 {} @@ -22,9 +21,9 @@ where fn unsized_local() where - for<'a> Dst<A + 'a>: Sized, + for<'a> Dst<dyn A + 'a>: Sized, { - let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>); + let x: Dst<dyn A> = *(Box::new(Dst { x: 1 }) as Box<Dst<dyn A>>); } fn return_str() -> str diff --git a/src/tools/clippy/tests/ui/crashes/ice-3969.stderr b/src/tools/clippy/tests/ui/crashes/ice-3969.stderr index 9a89047f07..7901808088 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-3969.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-3969.stderr @@ -1,30 +1,34 @@ -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/ice-3969.rs:25:17 +error: trait bound str: std::marker::Sized does not depend on any type or lifetime parameters + --> $DIR/ice-3969.rs:20:10 | -LL | for<'a> Dst<A + 'a>: Sized, - | ^^^^^^ help: use `dyn`: `dyn A + 'a` +LL | str: Sized; + | ^^^^^ | - = note: `-D bare-trait-objects` implied by `-D warnings` - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> + = note: `-D trivial-bounds` implied by `-D warnings` -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/ice-3969.rs:27:16 +error: trait bound for<'a> Dst<(dyn A + 'a)>: std::marker::Sized does not depend on any type or lifetime parameters + --> $DIR/ice-3969.rs:24:30 | -LL | let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>); - | ^ help: use `dyn`: `dyn A` +LL | for<'a> Dst<dyn A + 'a>: Sized, + | ^^^^^ + +error: trait bound str: std::marker::Sized does not depend on any type or lifetime parameters + --> $DIR/ice-3969.rs:31:10 | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +LL | str: Sized, + | ^^^^^ -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/ice-3969.rs:27:57 +error: trait bound std::string::String: std::ops::Neg does not depend on any type or lifetime parameters + --> $DIR/ice-3969.rs:38:13 | -LL | let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>); - | ^ help: use `dyn`: `dyn A` +LL | String: ::std::ops::Neg<Output = String>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: trait bound i32: std::iter::Iterator does not depend on any type or lifetime parameters + --> $DIR/ice-3969.rs:45:10 | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +LL | i32: Iterator, + | ^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 5 previous errors diff --git a/src/tools/clippy/tests/ui/crashes/ice-5207.rs b/src/tools/clippy/tests/ui/crashes/ice-5207.rs index 1b20c9defa..f463f78a99 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-5207.rs +++ b/src/tools/clippy/tests/ui/crashes/ice-5207.rs @@ -1,5 +1,3 @@ -// edition:2018 - // Regression test for https://github.com/rust-lang/rust-clippy/issues/5207 pub async fn bar<'a, T: 'a>(_: T) {} diff --git a/src/tools/clippy/tests/ui/crashes/ice-6250.stderr b/src/tools/clippy/tests/ui/crashes/ice-6250.stderr index 439884b7d2..0d7713aa9a 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6250.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-6250.stderr @@ -24,6 +24,9 @@ LL | | } error[E0308]: mismatched types --> $DIR/ice-6250.rs:12:14 | +LL | for reference in vec![1, 2, 3] { + | --------- expected due to the type of this binding +... LL | Some(reference) = cache.data.get(key) { | ^^^^^^^^^ expected integer, found `&i32` | diff --git a/src/tools/clippy/tests/ui/crashes/ice-6252.rs b/src/tools/clippy/tests/ui/crashes/ice-6252.rs index 2e3d9fd1e9..0ccf0aae9d 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6252.rs +++ b/src/tools/clippy/tests/ui/crashes/ice-6252.rs @@ -1,6 +1,5 @@ // originally from glacier fixed/77919.rs // encountered errors resolving bounds after type-checking - trait TypeVal<T> { const VAL: T; } diff --git a/src/tools/clippy/tests/ui/crashes/ice-6252.stderr b/src/tools/clippy/tests/ui/crashes/ice-6252.stderr index eaa5e6f51c..c8239897f3 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6252.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-6252.stderr @@ -1,16 +1,20 @@ error[E0412]: cannot find type `PhantomData` in this scope - --> $DIR/ice-6252.rs:9:9 + --> $DIR/ice-6252.rs:8:9 | LL | _n: PhantomData, | ^^^^^^^^^^^ not found in this scope | -help: consider importing this struct +help: consider importing one of these items + | +LL | use core::marker::PhantomData; + | +LL | use serde::__private::PhantomData; | LL | use std::marker::PhantomData; | error[E0412]: cannot find type `VAL` in this scope - --> $DIR/ice-6252.rs:11:63 + --> $DIR/ice-6252.rs:10:63 | LL | impl<N, M> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {} | - ^^^ not found in this scope @@ -18,7 +22,7 @@ LL | impl<N, M> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {} | help: you might be missing a type parameter: `, VAL` error[E0046]: not all trait items implemented, missing: `VAL` - --> $DIR/ice-6252.rs:11:1 + --> $DIR/ice-6252.rs:10:1 | LL | const VAL: T; | ------------- `VAL` from trait diff --git a/src/tools/clippy/tests/ui/crashes/ice-7231.rs b/src/tools/clippy/tests/ui/crashes/ice-7231.rs index 5595d8d1d6..4ad0d35137 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-7231.rs +++ b/src/tools/clippy/tests/ui/crashes/ice-7231.rs @@ -1,4 +1,3 @@ -// edition:2018 #![allow(clippy::never_loop)] async fn f() { diff --git a/src/tools/clippy/tests/ui/crashes/ice-7868.rs b/src/tools/clippy/tests/ui/crashes/ice-7868.rs new file mode 100644 index 0000000000..c6932164e3 --- /dev/null +++ b/src/tools/clippy/tests/ui/crashes/ice-7868.rs @@ -0,0 +1,7 @@ +#![warn(clippy::undocumented_unsafe_blocks)] +#![allow(clippy::no_effect)] + +#[path = "auxiliary/ice-7868-aux.rs"] +mod zero; + +fn main() {} diff --git a/src/tools/clippy/tests/ui/crashes/ice-7868.stderr b/src/tools/clippy/tests/ui/crashes/ice-7868.stderr new file mode 100644 index 0000000000..d7b49eb89a --- /dev/null +++ b/src/tools/clippy/tests/ui/crashes/ice-7868.stderr @@ -0,0 +1,15 @@ +error: unsafe block missing a safety comment + --> $DIR/auxiliary/ice-7868-aux.rs:2:5 + | +LL | unsafe { 0 }; + | ^^^^^^^^^^^^ + | + = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings` +help: consider adding a safety comment + | +LL ~ // Safety: ... +LL ~ unsafe { 0 }; + | + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui/crashes/ice-7869.rs b/src/tools/clippy/tests/ui/crashes/ice-7869.rs new file mode 100644 index 0000000000..8f97a063a9 --- /dev/null +++ b/src/tools/clippy/tests/ui/crashes/ice-7869.rs @@ -0,0 +1,7 @@ +enum Tila { + TyöAlkoi, + TyöKeskeytyi, + TyöValmis, +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/crashes/ice-7869.stderr b/src/tools/clippy/tests/ui/crashes/ice-7869.stderr new file mode 100644 index 0000000000..4fa9fb27e7 --- /dev/null +++ b/src/tools/clippy/tests/ui/crashes/ice-7869.stderr @@ -0,0 +1,15 @@ +error: all variants have the same prefix: `Työ` + --> $DIR/ice-7869.rs:1:1 + | +LL | / enum Tila { +LL | | TyöAlkoi, +LL | | TyöKeskeytyi, +LL | | TyöValmis, +LL | | } + | |_^ + | + = note: `-D clippy::enum-variant-names` implied by `-D warnings` + = help: remove the prefixes and use full paths to the variants instead of glob imports + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui/crashes/used_underscore_binding_macro.rs b/src/tools/clippy/tests/ui/crashes/used_underscore_binding_macro.rs index c57a45dc7a..901eb4e503 100644 --- a/src/tools/clippy/tests/ui/crashes/used_underscore_binding_macro.rs +++ b/src/tools/clippy/tests/ui/crashes/used_underscore_binding_macro.rs @@ -1,5 +1,3 @@ -// edition:2018 - use serde::Deserialize; /// Tests that we do not lint for unused underscores in a `MacroAttribute` diff --git a/src/tools/clippy/tests/ui/debug_assert_with_mut_call.rs b/src/tools/clippy/tests/ui/debug_assert_with_mut_call.rs index 477a47118d..c5de412556 100644 --- a/src/tools/clippy/tests/ui/debug_assert_with_mut_call.rs +++ b/src/tools/clippy/tests/ui/debug_assert_with_mut_call.rs @@ -1,9 +1,9 @@ -// compile-flags: --edition=2018 #![feature(custom_inner_attributes)] #![rustfmt::skip] #![warn(clippy::debug_assert_with_mut_call)] #![allow(clippy::redundant_closure_call)] + struct S; impl S { diff --git a/src/tools/clippy/tests/ui/deprecated.rs b/src/tools/clippy/tests/ui/deprecated.rs index 1943d0092e..39a2601fee 100644 --- a/src/tools/clippy/tests/ui/deprecated.rs +++ b/src/tools/clippy/tests/ui/deprecated.rs @@ -1,19 +1,18 @@ -#[warn(clippy::unstable_as_slice)] -#[warn(clippy::unstable_as_mut_slice)] -#[warn(clippy::misaligned_transmute)] -#[warn(clippy::unused_collect)] -#[warn(clippy::invalid_ref)] -#[warn(clippy::into_iter_on_array)] -#[warn(clippy::unused_label)] -#[warn(clippy::regex_macro)] -#[warn(clippy::drop_bounds)] -#[warn(clippy::temporary_cstring_as_ptr)] -#[warn(clippy::panic_params)] -#[warn(clippy::unknown_clippy_lints)] -#[warn(clippy::find_map)] -#[warn(clippy::filter_map)] -#[warn(clippy::pub_enum_variant_names)] -#[warn(clippy::wrong_pub_self_convention)] -#[warn(clippy::invalid_atomic_ordering)] +#![warn(clippy::should_assert_eq)] +#![warn(clippy::extend_from_slice)] +#![warn(clippy::range_step_by_zero)] +#![warn(clippy::unstable_as_slice)] +#![warn(clippy::unstable_as_mut_slice)] +#![warn(clippy::misaligned_transmute)] +#![warn(clippy::assign_ops)] +#![warn(clippy::if_let_redundant_pattern_matching)] +#![warn(clippy::unsafe_vector_initialization)] +#![warn(clippy::unused_collect)] +#![warn(clippy::replace_consts)] +#![warn(clippy::regex_macro)] +#![warn(clippy::find_map)] +#![warn(clippy::filter_map)] +#![warn(clippy::pub_enum_variant_names)] +#![warn(clippy::wrong_pub_self_convention)] fn main() {} diff --git a/src/tools/clippy/tests/ui/deprecated.stderr b/src/tools/clippy/tests/ui/deprecated.stderr index 51048e45c0..6095f134d5 100644 --- a/src/tools/clippy/tests/ui/deprecated.stderr +++ b/src/tools/clippy/tests/ui/deprecated.stderr @@ -1,106 +1,100 @@ -error: lint `clippy::unstable_as_slice` has been removed: `Vec::as_slice` has been stabilized in 1.7 - --> $DIR/deprecated.rs:1:8 +error: lint `clippy::should_assert_eq` has been removed: `assert!()` will be more flexible with RFC 2011 + --> $DIR/deprecated.rs:1:9 | -LL | #[warn(clippy::unstable_as_slice)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #![warn(clippy::should_assert_eq)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D renamed-and-removed-lints` implied by `-D warnings` -error: lint `clippy::unstable_as_mut_slice` has been removed: `Vec::as_mut_slice` has been stabilized in 1.7 - --> $DIR/deprecated.rs:2:8 +error: lint `clippy::extend_from_slice` has been removed: `.extend_from_slice(_)` is a faster way to extend a Vec by a slice + --> $DIR/deprecated.rs:2:9 | -LL | #[warn(clippy::unstable_as_mut_slice)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #![warn(clippy::extend_from_slice)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: lint `clippy::misaligned_transmute` has been removed: this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr - --> $DIR/deprecated.rs:3:8 +error: lint `clippy::range_step_by_zero` has been removed: `iterator.step_by(0)` panics nowadays + --> $DIR/deprecated.rs:3:9 | -LL | #[warn(clippy::misaligned_transmute)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #![warn(clippy::range_step_by_zero)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: lint `clippy::unused_collect` has been removed: `collect` has been marked as #[must_use] in rustc and that covers all cases of this lint - --> $DIR/deprecated.rs:4:8 +error: lint `clippy::unstable_as_slice` has been removed: `Vec::as_slice` has been stabilized in 1.7 + --> $DIR/deprecated.rs:4:9 | -LL | #[warn(clippy::unused_collect)] - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | #![warn(clippy::unstable_as_slice)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: lint `clippy::invalid_ref` has been renamed to `invalid_value` - --> $DIR/deprecated.rs:5:8 +error: lint `clippy::unstable_as_mut_slice` has been removed: `Vec::as_mut_slice` has been stabilized in 1.7 + --> $DIR/deprecated.rs:5:9 | -LL | #[warn(clippy::invalid_ref)] - | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value` +LL | #![warn(clippy::unstable_as_mut_slice)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter` - --> $DIR/deprecated.rs:6:8 +error: lint `clippy::misaligned_transmute` has been removed: this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr + --> $DIR/deprecated.rs:6:9 | -LL | #[warn(clippy::into_iter_on_array)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter` +LL | #![warn(clippy::misaligned_transmute)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: lint `clippy::unused_label` has been renamed to `unused_labels` - --> $DIR/deprecated.rs:7:8 +error: lint `clippy::assign_ops` has been removed: using compound assignment operators (e.g., `+=`) is harmless + --> $DIR/deprecated.rs:7:9 | -LL | #[warn(clippy::unused_label)] - | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels` +LL | #![warn(clippy::assign_ops)] + | ^^^^^^^^^^^^^^^^^^ -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 +error: lint `clippy::if_let_redundant_pattern_matching` has been removed: this lint has been changed to redundant_pattern_matching + --> $DIR/deprecated.rs:8:9 | -LL | #[warn(clippy::regex_macro)] - | ^^^^^^^^^^^^^^^^^^^ +LL | #![warn(clippy::if_let_redundant_pattern_matching)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: lint `clippy::drop_bounds` has been renamed to `drop_bounds` - --> $DIR/deprecated.rs:9:8 +error: lint `clippy::unsafe_vector_initialization` has been removed: the replacement suggested by this lint had substantially different behavior + --> $DIR/deprecated.rs:9:9 | -LL | #[warn(clippy::drop_bounds)] - | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds` +LL | #![warn(clippy::unsafe_vector_initialization)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr` - --> $DIR/deprecated.rs:10:8 +error: lint `clippy::unused_collect` has been removed: `collect` has been marked as #[must_use] in rustc and that covers all cases of this lint + --> $DIR/deprecated.rs:10:9 | -LL | #[warn(clippy::temporary_cstring_as_ptr)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr` +LL | #![warn(clippy::unused_collect)] + | ^^^^^^^^^^^^^^^^^^^^^^ -error: lint `clippy::panic_params` has been renamed to `non_fmt_panics` - --> $DIR/deprecated.rs:11:8 +error: lint `clippy::replace_consts` has been removed: associated-constants `MIN`/`MAX` of integers are preferred to `{min,max}_value()` and module constants + --> $DIR/deprecated.rs:11:9 | -LL | #[warn(clippy::panic_params)] - | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics` +LL | #![warn(clippy::replace_consts)] + | ^^^^^^^^^^^^^^^^^^^^^^ -error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints` - --> $DIR/deprecated.rs:12:8 +error: lint `clippy::regex_macro` has been removed: the regex! macro has been removed from the regex crate in 2018 + --> $DIR/deprecated.rs:12:9 | -LL | #[warn(clippy::unknown_clippy_lints)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints` +LL | #![warn(clippy::regex_macro)] + | ^^^^^^^^^^^^^^^^^^^ 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 + --> $DIR/deprecated.rs:13:9 | -LL | #[warn(clippy::find_map)] - | ^^^^^^^^^^^^^^^^ +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 + --> $DIR/deprecated.rs:14:9 | -LL | #[warn(clippy::filter_map)] - | ^^^^^^^^^^^^^^^^^^ +LL | #![warn(clippy::filter_map)] + | ^^^^^^^^^^^^^^^^^^ error: lint `clippy::pub_enum_variant_names` has been removed: set the `avoid-breaking-exported-api` config option to `false` to enable the `enum_variant_names` lint for public items - --> $DIR/deprecated.rs:15:8 + --> $DIR/deprecated.rs:15:9 | -LL | #[warn(clippy::pub_enum_variant_names)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #![warn(clippy::pub_enum_variant_names)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: lint `clippy::wrong_pub_self_convention` has been removed: set the `avoid-breaking-exported-api` config option to `false` to enable the `wrong_self_convention` lint for public items - --> $DIR/deprecated.rs:16:8 - | -LL | #[warn(clippy::wrong_pub_self_convention)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering` - --> $DIR/deprecated.rs:17:8 + --> $DIR/deprecated.rs:16:9 | -LL | #[warn(clippy::invalid_atomic_ordering)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering` +LL | #![warn(clippy::wrong_pub_self_convention)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 17 previous errors +error: aborting due to 16 previous errors diff --git a/src/tools/clippy/tests/ui/deref_addrof.fixed b/src/tools/clippy/tests/ui/deref_addrof.fixed index d4832daa68..9a150c67a2 100644 --- a/src/tools/clippy/tests/ui/deref_addrof.fixed +++ b/src/tools/clippy/tests/ui/deref_addrof.fixed @@ -52,12 +52,14 @@ macro_rules! m_mut { }; } +#[derive(Copy, Clone)] pub struct S; impl S { pub fn f(&self) -> &Self { m!(self) } - pub fn f_mut(&self) -> &Self { + #[allow(unused_mut)] // mut will be unused, once the macro is fixed + pub fn f_mut(mut self) -> Self { m_mut!(self) } } diff --git a/src/tools/clippy/tests/ui/deref_addrof.rs b/src/tools/clippy/tests/ui/deref_addrof.rs index be7cc669b5..80ba7e9bd0 100644 --- a/src/tools/clippy/tests/ui/deref_addrof.rs +++ b/src/tools/clippy/tests/ui/deref_addrof.rs @@ -52,12 +52,14 @@ macro_rules! m_mut { }; } +#[derive(Copy, Clone)] pub struct S; impl S { pub fn f(&self) -> &Self { m!(self) } - pub fn f_mut(&self) -> &Self { + #[allow(unused_mut)] // mut will be unused, once the macro is fixed + pub fn f_mut(mut self) -> Self { m_mut!(self) } } diff --git a/src/tools/clippy/tests/ui/diverging_sub_expression.rs b/src/tools/clippy/tests/ui/diverging_sub_expression.rs index 4df241c9fc..e27f9fea70 100644 --- a/src/tools/clippy/tests/ui/diverging_sub_expression.rs +++ b/src/tools/clippy/tests/ui/diverging_sub_expression.rs @@ -1,6 +1,5 @@ #![warn(clippy::diverging_sub_expression)] #![allow(clippy::match_same_arms, clippy::logic_bug)] - #[allow(clippy::empty_loop)] fn diverge() -> ! { loop {} diff --git a/src/tools/clippy/tests/ui/diverging_sub_expression.stderr b/src/tools/clippy/tests/ui/diverging_sub_expression.stderr index 170e7d92de..c712a6a7e3 100644 --- a/src/tools/clippy/tests/ui/diverging_sub_expression.stderr +++ b/src/tools/clippy/tests/ui/diverging_sub_expression.stderr @@ -1,5 +1,5 @@ error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:20:10 + --> $DIR/diverging_sub_expression.rs:19:10 | LL | b || diverge(); | ^^^^^^^^^ @@ -7,34 +7,42 @@ LL | b || diverge(); = note: `-D clippy::diverging-sub-expression` implied by `-D warnings` error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:21:10 + --> $DIR/diverging_sub_expression.rs:20:10 | LL | b || A.foo(); | ^^^^^^^ error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:30:26 + --> $DIR/diverging_sub_expression.rs:29:26 | LL | 6 => true || return, | ^^^^^^ error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:31:26 + --> $DIR/diverging_sub_expression.rs:30:26 | LL | 7 => true || continue, | ^^^^^^^^ error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:34:26 + --> $DIR/diverging_sub_expression.rs:33:26 | LL | 3 => true || diverge(), | ^^^^^^^^^ error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:39:26 + --> $DIR/diverging_sub_expression.rs:36:30 + | +LL | _ => true || panic!("boo"), + | ^^^^^^^^^^^^^ + | + = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: sub-expression diverges + --> $DIR/diverging_sub_expression.rs:38:26 | LL | _ => true || break, | ^^^^^ -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed new file mode 100644 index 0000000000..747801b40e --- /dev/null +++ b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed @@ -0,0 +1,215 @@ +// run-rustfix +//! This file tests for the `DOC_MARKDOWN` lint. + +#![allow(dead_code, incomplete_features)] +#![warn(clippy::doc_markdown)] +#![feature(custom_inner_attributes, generic_const_exprs, const_option)] +#![rustfmt::skip] + +/// The `foo_bar` function does _nothing_. See also `foo::bar`. (note the dot there) +/// Markdown is _weird_. I mean _really weird_. This \_ is ok. So is `_`. But not `Foo::some_fun` +/// which should be reported only once despite being __doubly bad__. +/// Here be `::a::global:path`, and _`::another::global::path`_. :: is not a path though. +/// Import an item from `::awesome::global::blob::` (Intended postfix) +/// These are the options for `::Cat`: (Intended trailing single colon, shouldn't be linted) +/// That's not code ~`NotInCodeBlock`~. +/// `be_sure_we_got_to_the_end_of_it` +fn foo_bar() { +} + +/// That one tests multiline ticks. +/// ```rust +/// foo_bar FOO_BAR +/// _foo bar_ +/// ``` +/// +/// ~~~rust +/// foo_bar FOO_BAR +/// _foo bar_ +/// ~~~ +/// `be_sure_we_got_to_the_end_of_it` +fn multiline_codeblock() { +} + +/// This _is a test for +/// multiline +/// emphasis_. +/// `be_sure_we_got_to_the_end_of_it` +fn test_emphasis() { +} + +/// This tests units. See also #835. +/// kiB MiB GiB TiB PiB EiB +/// kib Mib Gib Tib Pib Eib +/// kB MB GB TB PB EB +/// kb Mb Gb Tb Pb Eb +/// 32kiB 32MiB 32GiB 32TiB 32PiB 32EiB +/// 32kib 32Mib 32Gib 32Tib 32Pib 32Eib +/// 32kB 32MB 32GB 32TB 32PB 32EB +/// 32kb 32Mb 32Gb 32Tb 32Pb 32Eb +/// NaN +/// `be_sure_we_got_to_the_end_of_it` +fn test_units() { +} + +/// This tests allowed identifiers. +/// KiB MiB GiB TiB PiB EiB +/// DirectX +/// ECMAScript +/// GPLv2 GPLv3 +/// GitHub GitLab +/// IPv4 IPv6 +/// ClojureScript CoffeeScript JavaScript PureScript TypeScript +/// NaN NaNs +/// OAuth GraphQL +/// OCaml +/// OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenDNS +/// WebGL +/// TensorFlow +/// TrueType +/// iOS macOS FreeBSD +/// TeX LaTeX BibTeX BibLaTeX +/// MinGW +/// CamelCase (see also #2395) +/// `be_sure_we_got_to_the_end_of_it` +fn test_allowed() { +} + +/// This test has [a `link_with_underscores`][chunked-example] inside it. See #823. +/// See also [the issue tracker](https://github.com/rust-lang/rust-clippy/search?q=clippy::doc_markdown&type=Issues) +/// on GitHub (which is a camel-cased word, but is OK). And here is another [inline link][inline_link]. +/// It can also be [`inline_link2`]. +/// +/// [chunked-example]: https://en.wikipedia.org/wiki/Chunked_transfer_encoding#Example +/// [inline_link]: https://foobar +/// [inline_link2]: https://foobar +/// The `main` function is the entry point of the program. Here it only calls the `foo_bar` and +/// `multiline_ticks` functions. +/// +/// expression of the type `_ <bit_op> m <cmp_op> c` (where `<bit_op>` +/// is one of {`&`, '|'} and `<cmp_op>` is one of {`!=`, `>=`, `>` , +/// `be_sure_we_got_to_the_end_of_it` +fn main() { + foo_bar(); + multiline_codeblock(); + test_emphasis(); + test_units(); +} + +/// ## `CamelCaseThing` +/// Talks about `CamelCaseThing`. Titles should be ignored; see issue #897. +/// +/// # `CamelCaseThing` +/// +/// Not a title #897 `CamelCaseThing` +/// `be_sure_we_got_to_the_end_of_it` +fn issue897() { +} + +/// I am confused by brackets? (`x_y`) +/// I am confused by brackets? (foo `x_y`) +/// I am confused by brackets? (`x_y` foo) +/// `be_sure_we_got_to_the_end_of_it` +fn issue900() { +} + +/// Diesel queries also have a similar problem to [Iterator][iterator], where +/// /// More talking +/// returning them from a function requires exposing the implementation of that +/// function. The [`helper_types`][helper_types] module exists to help with this, +/// but you might want to hide the return type or have it conditionally change. +/// Boxing can achieve both. +/// +/// [iterator]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html +/// [helper_types]: ../helper_types/index.html +/// `be_sure_we_got_to_the_end_of_it` +fn issue883() { +} + +/// `foo_bar +/// baz_quz` +/// [foo +/// bar](https://doc.rust-lang.org/stable/std/iter/trait.IteratorFooBar.html) +fn multiline() { +} + +/** E.g., serialization of an empty list: `FooBar` +``` +That's in a code block: `PackedNode` +``` + +And `BarQuz` too. +`be_sure_we_got_to_the_end_of_it` +*/ +fn issue1073() { +} + +/** E.g., serialization of an empty list: `FooBar` +``` +That's in a code block: PackedNode +``` + +And `BarQuz` too. +`be_sure_we_got_to_the_end_of_it` +*/ +fn issue1073_alt() { +} + +/// Tests more than three quotes: +/// ```` +/// DoNotWarn +/// ``` +/// StillDont +/// ```` +/// `be_sure_we_got_to_the_end_of_it` +fn four_quotes() { +} + +#[cfg_attr(feature = "a", doc = " ```")] +#[cfg_attr(not(feature = "a"), doc = " ```ignore")] +/// fn main() { +/// let s = "localhost:10000".to_string(); +/// println!("{}", s); +/// } +/// ``` +fn issue_1469() {} + +/** + * This is a doc comment that should not be a list + *This would also be an error under a strict common mark interpretation + */ +fn issue_1920() {} + +/// An iterator over `mycrate::Collection`'s values. +/// It should not lint a `'static` lifetime in ticks. +fn issue_2210() {} + +/// This should not cause the lint to trigger: +/// #REQ-data-family.lint_partof_exists +fn issue_2343() {} + +/// This should not cause an ICE: +/// __|_ _|__||_| +fn pulldown_cmark_crash() {} + +/// This should not lint +/// (regression test for #7758) +/// [plain text][path::to::item] +fn intra_doc_link() {} + +// issue #7033 - generic_const_exprs ICE +struct S<T, const N: usize> +where [(); N.checked_next_power_of_two().unwrap()]: { + arr: [T; N.checked_next_power_of_two().unwrap()], + n: usize, +} + +impl<T: Copy + Default, const N: usize> S<T, N> +where [(); N.checked_next_power_of_two().unwrap()]: { + fn new() -> Self { + Self { + arr: [T::default(); N.checked_next_power_of_two().unwrap()], + n: 0, + } + } +} diff --git a/src/tools/clippy/tests/ui/doc/doc.rs b/src/tools/clippy/tests/ui/doc/doc-fixable.rs similarity index 91% rename from src/tools/clippy/tests/ui/doc/doc.rs rename to src/tools/clippy/tests/ui/doc/doc-fixable.rs index 342208e52b..f3cf966157 100644 --- a/src/tools/clippy/tests/ui/doc/doc.rs +++ b/src/tools/clippy/tests/ui/doc/doc-fixable.rs @@ -1,3 +1,4 @@ +// run-rustfix //! This file tests for the `DOC_MARKDOWN` lint. #![allow(dead_code, incomplete_features)] @@ -8,7 +9,9 @@ /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there) /// Markdown is _weird_. I mean _really weird_. This \_ is ok. So is `_`. But not Foo::some_fun /// which should be reported only once despite being __doubly bad__. -/// Here be ::a::global:path. +/// Here be ::a::global:path, and _::another::global::path_. :: is not a path though. +/// Import an item from ::awesome::global::blob:: (Intended postfix) +/// These are the options for ::Cat: (Intended trailing single colon, shouldn't be linted) /// That's not code ~NotInCodeBlock~. /// be_sure_we_got_to_the_end_of_it fn foo_bar() { @@ -162,12 +165,6 @@ fn issue1073_alt() { fn four_quotes() { } -/// See [NIST SP 800-56A, revision 2]. -/// -/// [NIST SP 800-56A, revision 2]: -/// https://github.com/rust-lang/rust-clippy/issues/902#issuecomment-261919419 -fn issue_902_comment() {} - #[cfg_attr(feature = "a", doc = " ```")] #[cfg_attr(not(feature = "a"), doc = " ```ignore")] /// fn main() { @@ -183,14 +180,6 @@ fn issue_1469() {} */ fn issue_1920() {} -/// Ok: <http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels> -/// -/// Not ok: http://www.unicode.org -/// Not ok: https://www.unicode.org -/// Not ok: http://www.unicode.org/ -/// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels -fn issue_1832() {} - /// An iterator over mycrate::Collection's values. /// It should not lint a `'static` lifetime in ticks. fn issue_2210() {} diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.stderr b/src/tools/clippy/tests/ui/doc/doc-fixable.stderr new file mode 100644 index 0000000000..31132f86ed --- /dev/null +++ b/src/tools/clippy/tests/ui/doc/doc-fixable.stderr @@ -0,0 +1,184 @@ +error: item in documentation is missing backticks + --> $DIR/doc-fixable.rs:9:9 + | +LL | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there) + | ^^^^^^^ help: try: ``foo_bar`` + | + = note: `-D clippy::doc-markdown` implied by `-D warnings` + +error: item in documentation is missing backticks + --> $DIR/doc-fixable.rs:9:51 + | +LL | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there) + | ^^^^^^^^ help: try: ``foo::bar`` + +error: item in documentation is missing backticks + --> $DIR/doc-fixable.rs:10:83 + | +LL | /// Markdown is _weird_. I mean _really weird_. This /_ is ok. So is `_`. But not Foo::some_fun + | ^^^^^^^^^^^^^ help: try: ``Foo::some_fun`` + +error: item in documentation is missing backticks + --> $DIR/doc-fixable.rs:12:13 + | +LL | /// Here be ::a::global:path, and _::another::global::path_. :: is not a path though. + | ^^^^^^^^^^^^^^^^ help: try: ``::a::global:path`` + +error: item in documentation is missing backticks + --> $DIR/doc-fixable.rs:12:36 + | +LL | /// Here be ::a::global:path, and _::another::global::path_. :: is not a path though. + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``::another::global::path`` + +error: item in documentation is missing backticks + --> $DIR/doc-fixable.rs:13:25 + | +LL | /// Import an item from ::awesome::global::blob:: (Intended postfix) + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``::awesome::global::blob::`` + +error: item in documentation is missing backticks + --> $DIR/doc-fixable.rs:14:31 + | +LL | /// These are the options for ::Cat: (Intended trailing single colon, shouldn't be linted) + | ^^^^^ help: try: ``::Cat`` + +error: item in documentation is missing backticks + --> $DIR/doc-fixable.rs:15:22 + | +LL | /// That's not code ~NotInCodeBlock~. + | ^^^^^^^^^^^^^^ help: try: ``NotInCodeBlock`` + +error: item in documentation is missing backticks + --> $DIR/doc-fixable.rs:16:5 + | +LL | /// be_sure_we_got_to_the_end_of_it + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it`` + +error: item in documentation is missing backticks + --> $DIR/doc-fixable.rs:30:5 + | +LL | /// be_sure_we_got_to_the_end_of_it + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it`` + +error: item in documentation is missing backticks + --> $DIR/doc-fixable.rs:37:5 + | +LL | /// be_sure_we_got_to_the_end_of_it + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it`` + +error: item in documentation is missing backticks + --> $DIR/doc-fixable.rs:51:5 + | +LL | /// be_sure_we_got_to_the_end_of_it + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it`` + +error: item in documentation is missing backticks + --> $DIR/doc-fixable.rs:74:5 + | +LL | /// be_sure_we_got_to_the_end_of_it + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it`` + +error: item in documentation is missing backticks + --> $DIR/doc-fixable.rs:78:22 + | +LL | /// This test has [a link_with_underscores][chunked-example] inside it. See #823. + | ^^^^^^^^^^^^^^^^^^^^^ help: try: ``link_with_underscores`` + +error: item in documentation is missing backticks + --> $DIR/doc-fixable.rs:81:21 + | +LL | /// It can also be [inline_link2]. + | ^^^^^^^^^^^^ help: try: ``inline_link2`` + +error: item in documentation is missing backticks + --> $DIR/doc-fixable.rs:91:5 + | +LL | /// be_sure_we_got_to_the_end_of_it + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it`` + +error: item in documentation is missing backticks + --> $DIR/doc-fixable.rs:99:8 + | +LL | /// ## CamelCaseThing + | ^^^^^^^^^^^^^^ help: try: ``CamelCaseThing`` + +error: item in documentation is missing backticks + --> $DIR/doc-fixable.rs:102:7 + | +LL | /// # CamelCaseThing + | ^^^^^^^^^^^^^^ help: try: ``CamelCaseThing`` + +error: item in documentation is missing backticks + --> $DIR/doc-fixable.rs:104:22 + | +LL | /// Not a title #897 CamelCaseThing + | ^^^^^^^^^^^^^^ help: try: ``CamelCaseThing`` + +error: item in documentation is missing backticks + --> $DIR/doc-fixable.rs:105:5 + | +LL | /// be_sure_we_got_to_the_end_of_it + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it`` + +error: item in documentation is missing backticks + --> $DIR/doc-fixable.rs:112:5 + | +LL | /// be_sure_we_got_to_the_end_of_it + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it`` + +error: item in documentation is missing backticks + --> $DIR/doc-fixable.rs:125:5 + | +LL | /// be_sure_we_got_to_the_end_of_it + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it`` + +error: item in documentation is missing backticks + --> $DIR/doc-fixable.rs:136:43 + | +LL | /** E.g., serialization of an empty list: FooBar + | ^^^^^^ help: try: ``FooBar`` + +error: item in documentation is missing backticks + --> $DIR/doc-fixable.rs:141:5 + | +LL | And BarQuz too. + | ^^^^^^ help: try: ``BarQuz`` + +error: item in documentation is missing backticks + --> $DIR/doc-fixable.rs:142:1 + | +LL | be_sure_we_got_to_the_end_of_it + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it`` + +error: item in documentation is missing backticks + --> $DIR/doc-fixable.rs:147:43 + | +LL | /** E.g., serialization of an empty list: FooBar + | ^^^^^^ help: try: ``FooBar`` + +error: item in documentation is missing backticks + --> $DIR/doc-fixable.rs:152:5 + | +LL | And BarQuz too. + | ^^^^^^ help: try: ``BarQuz`` + +error: item in documentation is missing backticks + --> $DIR/doc-fixable.rs:153:1 + | +LL | be_sure_we_got_to_the_end_of_it + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it`` + +error: item in documentation is missing backticks + --> $DIR/doc-fixable.rs:164:5 + | +LL | /// be_sure_we_got_to_the_end_of_it + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it`` + +error: item in documentation is missing backticks + --> $DIR/doc-fixable.rs:183:22 + | +LL | /// An iterator over mycrate::Collection's values. + | ^^^^^^^^^^^^^^^^^^^ help: try: ``mycrate::Collection`` + +error: aborting due to 30 previous errors + diff --git a/src/tools/clippy/tests/ui/doc/doc.stderr b/src/tools/clippy/tests/ui/doc/doc.stderr deleted file mode 100644 index 7eab8a85f0..0000000000 --- a/src/tools/clippy/tests/ui/doc/doc.stderr +++ /dev/null @@ -1,190 +0,0 @@ -error: you should put `foo_bar` between ticks in the documentation - --> $DIR/doc.rs:8:9 - | -LL | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there) - | ^^^^^^^ - | - = note: `-D clippy::doc-markdown` implied by `-D warnings` - -error: you should put `foo::bar` between ticks in the documentation - --> $DIR/doc.rs:8:51 - | -LL | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there) - | ^^^^^^^^ - -error: you should put `Foo::some_fun` between ticks in the documentation - --> $DIR/doc.rs:9:83 - | -LL | /// Markdown is _weird_. I mean _really weird_. This /_ is ok. So is `_`. But not Foo::some_fun - | ^^^^^^^^^^^^^ - -error: you should put `a::global:path` between ticks in the documentation - --> $DIR/doc.rs:11:15 - | -LL | /// Here be ::a::global:path. - | ^^^^^^^^^^^^^^ - -error: you should put `NotInCodeBlock` between ticks in the documentation - --> $DIR/doc.rs:12:22 - | -LL | /// That's not code ~NotInCodeBlock~. - | ^^^^^^^^^^^^^^ - -error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:13:5 - | -LL | /// be_sure_we_got_to_the_end_of_it - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:27:5 - | -LL | /// be_sure_we_got_to_the_end_of_it - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:34:5 - | -LL | /// be_sure_we_got_to_the_end_of_it - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:48:5 - | -LL | /// be_sure_we_got_to_the_end_of_it - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:71:5 - | -LL | /// be_sure_we_got_to_the_end_of_it - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: you should put `link_with_underscores` between ticks in the documentation - --> $DIR/doc.rs:75:22 - | -LL | /// This test has [a link_with_underscores][chunked-example] inside it. See #823. - | ^^^^^^^^^^^^^^^^^^^^^ - -error: you should put `inline_link2` between ticks in the documentation - --> $DIR/doc.rs:78:21 - | -LL | /// It can also be [inline_link2]. - | ^^^^^^^^^^^^ - -error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:88:5 - | -LL | /// be_sure_we_got_to_the_end_of_it - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: you should put `CamelCaseThing` between ticks in the documentation - --> $DIR/doc.rs:96:8 - | -LL | /// ## CamelCaseThing - | ^^^^^^^^^^^^^^ - -error: you should put `CamelCaseThing` between ticks in the documentation - --> $DIR/doc.rs:99:7 - | -LL | /// # CamelCaseThing - | ^^^^^^^^^^^^^^ - -error: you should put `CamelCaseThing` between ticks in the documentation - --> $DIR/doc.rs:101:22 - | -LL | /// Not a title #897 CamelCaseThing - | ^^^^^^^^^^^^^^ - -error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:102:5 - | -LL | /// be_sure_we_got_to_the_end_of_it - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:109:5 - | -LL | /// be_sure_we_got_to_the_end_of_it - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:122:5 - | -LL | /// be_sure_we_got_to_the_end_of_it - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: you should put `FooBar` between ticks in the documentation - --> $DIR/doc.rs:133:43 - | -LL | /** E.g., serialization of an empty list: FooBar - | ^^^^^^ - -error: you should put `BarQuz` between ticks in the documentation - --> $DIR/doc.rs:138:5 - | -LL | And BarQuz too. - | ^^^^^^ - -error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:139:1 - | -LL | be_sure_we_got_to_the_end_of_it - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: you should put `FooBar` between ticks in the documentation - --> $DIR/doc.rs:144:43 - | -LL | /** E.g., serialization of an empty list: FooBar - | ^^^^^^ - -error: you should put `BarQuz` between ticks in the documentation - --> $DIR/doc.rs:149:5 - | -LL | And BarQuz too. - | ^^^^^^ - -error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:150:1 - | -LL | be_sure_we_got_to_the_end_of_it - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation - --> $DIR/doc.rs:161:5 - | -LL | /// be_sure_we_got_to_the_end_of_it - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: you should put bare URLs between `<`/`>` or make a proper Markdown link - --> $DIR/doc.rs:188:13 - | -LL | /// Not ok: http://www.unicode.org - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: you should put bare URLs between `<`/`>` or make a proper Markdown link - --> $DIR/doc.rs:189:13 - | -LL | /// Not ok: https://www.unicode.org - | ^^^^^^^^^^^^^^^^^^^^^^^ - -error: you should put bare URLs between `<`/`>` or make a proper Markdown link - --> $DIR/doc.rs:190:13 - | -LL | /// Not ok: http://www.unicode.org/ - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: you should put bare URLs between `<`/`>` or make a proper Markdown link - --> $DIR/doc.rs:191:13 - | -LL | /// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: you should put `mycrate::Collection` between ticks in the documentation - --> $DIR/doc.rs:194:22 - | -LL | /// An iterator over mycrate::Collection's values. - | ^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 31 previous errors - diff --git a/src/tools/clippy/tests/ui/doc/issue_1832.rs b/src/tools/clippy/tests/ui/doc/issue_1832.rs new file mode 100644 index 0000000000..10586f16d4 --- /dev/null +++ b/src/tools/clippy/tests/ui/doc/issue_1832.rs @@ -0,0 +1,9 @@ +/// Ok: <http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels> +/// +/// Not ok: http://www.unicode.org +/// Not ok: https://www.unicode.org +/// Not ok: http://www.unicode.org/ +/// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels +fn issue_1832() {} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/doc/issue_902.rs b/src/tools/clippy/tests/ui/doc/issue_902.rs new file mode 100644 index 0000000000..4b0c835dd3 --- /dev/null +++ b/src/tools/clippy/tests/ui/doc/issue_902.rs @@ -0,0 +1,7 @@ +/// See [NIST SP 800-56A, revision 2]. +/// +/// [NIST SP 800-56A, revision 2]: +/// https://github.com/rust-lang/rust-clippy/issues/902#issuecomment-261919419 +fn issue_902_comment() {} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/doc/unbalanced_ticks.stderr b/src/tools/clippy/tests/ui/doc/unbalanced_ticks.stderr index 45ca34e2a8..9670e5c24f 100644 --- a/src/tools/clippy/tests/ui/doc/unbalanced_ticks.stderr +++ b/src/tools/clippy/tests/ui/doc/unbalanced_ticks.stderr @@ -18,11 +18,11 @@ LL | /// This paragraph has `unbalanced_tick marks and should stop_linting. | = help: a backtick may be missing a pair -error: you should put `should_be` between ticks in the documentation +error: item in documentation is missing backticks --> $DIR/unbalanced_ticks.rs:15:32 | LL | /// This paragraph is fine and should_be linted normally. - | ^^^^^^^^^ + | ^^^^^^^^^ help: try: ``should_be`` error: backticks are unbalanced --> $DIR/unbalanced_ticks.rs:17:1 @@ -32,11 +32,11 @@ LL | /// Double unbalanced backtick from ``here to here` should lint. | = help: a backtick may be missing a pair -error: you should put `not_fine` between ticks in the documentation +error: item in documentation is missing backticks --> $DIR/unbalanced_ticks.rs:30:8 | LL | /// ## not_fine - | ^^^^^^^^ + | ^^^^^^^^ help: try: ``not_fine`` error: backticks are unbalanced --> $DIR/unbalanced_ticks.rs:32:1 @@ -54,11 +54,11 @@ LL | /// - This `item has unbalanced tick marks | = help: a backtick may be missing a pair -error: you should put `backticks_here` between ticks in the documentation +error: item in documentation is missing backticks --> $DIR/unbalanced_ticks.rs:35:23 | LL | /// - This item needs backticks_here - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ help: try: ``backticks_here`` error: aborting due to 8 previous errors diff --git a/src/tools/clippy/tests/ui/doc_errors.rs b/src/tools/clippy/tests/ui/doc_errors.rs index c77a74a58f..30fdd3b087 100644 --- a/src/tools/clippy/tests/ui/doc_errors.rs +++ b/src/tools/clippy/tests/ui/doc_errors.rs @@ -1,4 +1,3 @@ -// edition:2018 #![warn(clippy::missing_errors_doc)] #![allow(clippy::result_unit_err)] #![allow(clippy::unnecessary_wraps)] diff --git a/src/tools/clippy/tests/ui/doc_errors.stderr b/src/tools/clippy/tests/ui/doc_errors.stderr index b5a81419da..c7b616e289 100644 --- a/src/tools/clippy/tests/ui/doc_errors.stderr +++ b/src/tools/clippy/tests/ui/doc_errors.stderr @@ -1,5 +1,5 @@ error: docs for function returning `Result` missing `# Errors` section - --> $DIR/doc_errors.rs:8:1 + --> $DIR/doc_errors.rs:7:1 | LL | / pub fn pub_fn_missing_errors_header() -> Result<(), ()> { LL | | unimplemented!(); @@ -9,7 +9,7 @@ LL | | } = note: `-D clippy::missing-errors-doc` implied by `-D warnings` error: docs for function returning `Result` missing `# Errors` section - --> $DIR/doc_errors.rs:12:1 + --> $DIR/doc_errors.rs:11:1 | LL | / pub async fn async_pub_fn_missing_errors_header() -> Result<(), ()> { LL | | unimplemented!(); @@ -17,7 +17,7 @@ LL | | } | |_^ error: docs for function returning `Result` missing `# Errors` section - --> $DIR/doc_errors.rs:17:1 + --> $DIR/doc_errors.rs:16:1 | LL | / pub fn pub_fn_returning_io_result() -> io::Result<()> { LL | | unimplemented!(); @@ -25,7 +25,7 @@ LL | | } | |_^ error: docs for function returning `Result` missing `# Errors` section - --> $DIR/doc_errors.rs:22:1 + --> $DIR/doc_errors.rs:21:1 | LL | / pub async fn async_pub_fn_returning_io_result() -> io::Result<()> { LL | | unimplemented!(); @@ -33,7 +33,7 @@ LL | | } | |_^ error: docs for function returning `Result` missing `# Errors` section - --> $DIR/doc_errors.rs:52:5 + --> $DIR/doc_errors.rs:51:5 | LL | / pub fn pub_method_missing_errors_header() -> Result<(), ()> { LL | | unimplemented!(); @@ -41,7 +41,7 @@ LL | | } | |_____^ error: docs for function returning `Result` missing `# Errors` section - --> $DIR/doc_errors.rs:57:5 + --> $DIR/doc_errors.rs:56:5 | LL | / pub async fn async_pub_method_missing_errors_header() -> Result<(), ()> { LL | | unimplemented!(); @@ -49,7 +49,7 @@ LL | | } | |_____^ error: docs for function returning `Result` missing `# Errors` section - --> $DIR/doc_errors.rs:86:5 + --> $DIR/doc_errors.rs:85:5 | LL | fn trait_method_missing_errors_header() -> Result<(), ()>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/doc_unsafe.rs b/src/tools/clippy/tests/ui/doc_unsafe.rs index 8f823f1672..4464a21b3b 100644 --- a/src/tools/clippy/tests/ui/doc_unsafe.rs +++ b/src/tools/clippy/tests/ui/doc_unsafe.rs @@ -115,3 +115,18 @@ fn main() { drive(); } } + +// do not lint if any parent has `#[doc(hidden)]` attribute +// see #7347 +#[doc(hidden)] +pub mod __macro { + pub struct T; + impl T { + pub unsafe fn f() {} + } +} + +/// # Implementation safety +pub unsafe trait DocumentedUnsafeTraitWithImplementationHeader { + fn method(); +} diff --git a/src/tools/clippy/tests/ui/double_neg.rs b/src/tools/clippy/tests/ui/double_neg.rs index d47dfcb5ba..38a8fbd74d 100644 --- a/src/tools/clippy/tests/ui/double_neg.rs +++ b/src/tools/clippy/tests/ui/double_neg.rs @@ -1,4 +1,5 @@ #[warn(clippy::double_neg)] +#[allow(clippy::no_effect)] fn main() { let x = 1; -x; diff --git a/src/tools/clippy/tests/ui/double_neg.stderr b/src/tools/clippy/tests/ui/double_neg.stderr index d82ed05f05..7cdb040b68 100644 --- a/src/tools/clippy/tests/ui/double_neg.stderr +++ b/src/tools/clippy/tests/ui/double_neg.stderr @@ -1,5 +1,5 @@ error: `--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op - --> $DIR/double_neg.rs:6:5 + --> $DIR/double_neg.rs:7:5 | LL | --x; | ^^^ diff --git a/src/tools/clippy/tests/ui/enum_variants.stderr b/src/tools/clippy/tests/ui/enum_variants.stderr index 447fbb9e1b..add8a91e26 100644 --- a/src/tools/clippy/tests/ui/enum_variants.stderr +++ b/src/tools/clippy/tests/ui/enum_variants.stderr @@ -60,7 +60,7 @@ LL | | } | = help: remove the prefixes and use full paths to the variants instead of glob imports -error: all variants have the same prefix: `With` +error: all variants have the same prefix: `WithOut` --> $DIR/enum_variants.rs:81:1 | LL | / enum Seallll { diff --git a/src/tools/clippy/tests/ui/equatable_if_let.fixed b/src/tools/clippy/tests/ui/equatable_if_let.fixed index ba72cc237b..88918d9671 100644 --- a/src/tools/clippy/tests/ui/equatable_if_let.fixed +++ b/src/tools/clippy/tests/ui/equatable_if_let.fixed @@ -66,4 +66,13 @@ fn main() { if g == NotStructuralEq::A {} if let Some(NotPartialEq::A) = Some(f) {} if Some(g) == Some(NotStructuralEq::A) {} + + macro_rules! m1 { + (x) => { + "abc" + }; + } + if "abc" == m1!(x) { + println!("OK"); + } } diff --git a/src/tools/clippy/tests/ui/equatable_if_let.rs b/src/tools/clippy/tests/ui/equatable_if_let.rs index 12526ca193..9a7ab75ef4 100644 --- a/src/tools/clippy/tests/ui/equatable_if_let.rs +++ b/src/tools/clippy/tests/ui/equatable_if_let.rs @@ -66,4 +66,13 @@ fn main() { if let NotStructuralEq::A = g {} if let Some(NotPartialEq::A) = Some(f) {} if let Some(NotStructuralEq::A) = Some(g) {} + + macro_rules! m1 { + (x) => { + "abc" + }; + } + if let m1!(x) = "abc" { + println!("OK"); + } } diff --git a/src/tools/clippy/tests/ui/equatable_if_let.stderr b/src/tools/clippy/tests/ui/equatable_if_let.stderr index 79ef919384..760ff88f44 100644 --- a/src/tools/clippy/tests/ui/equatable_if_let.stderr +++ b/src/tools/clippy/tests/ui/equatable_if_let.stderr @@ -60,5 +60,11 @@ error: this pattern matching can be expressed using equality LL | if let Some(NotStructuralEq::A) = Some(g) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(g) == Some(NotStructuralEq::A)` -error: aborting due to 10 previous errors +error: this pattern matching can be expressed using equality + --> $DIR/equatable_if_let.rs:75:8 + | +LL | if let m1!(x) = "abc" { + | ^^^^^^^^^^^^^^^^^^ help: try: `"abc" == m1!(x)` + +error: aborting due to 11 previous errors diff --git a/src/tools/clippy/tests/ui/eval_order_dependence.rs b/src/tools/clippy/tests/ui/eval_order_dependence.rs index 8e6a32b7be..aad78319d4 100644 --- a/src/tools/clippy/tests/ui/eval_order_dependence.rs +++ b/src/tools/clippy/tests/ui/eval_order_dependence.rs @@ -1,5 +1,3 @@ -// edition:2018 - #[warn(clippy::eval_order_dependence)] #[allow( unused_assignments, diff --git a/src/tools/clippy/tests/ui/eval_order_dependence.stderr b/src/tools/clippy/tests/ui/eval_order_dependence.stderr index 4f611e308e..7c6265a087 100644 --- a/src/tools/clippy/tests/ui/eval_order_dependence.stderr +++ b/src/tools/clippy/tests/ui/eval_order_dependence.stderr @@ -1,48 +1,48 @@ error: unsequenced read of `x` - --> $DIR/eval_order_dependence.rs:16:9 + --> $DIR/eval_order_dependence.rs:14:9 | LL | } + x; | ^ | = note: `-D clippy::eval-order-dependence` implied by `-D warnings` note: whether read occurs before this write depends on evaluation order - --> $DIR/eval_order_dependence.rs:14:9 + --> $DIR/eval_order_dependence.rs:12:9 | LL | x = 1; | ^^^^^ error: unsequenced read of `x` - --> $DIR/eval_order_dependence.rs:19:5 + --> $DIR/eval_order_dependence.rs:17:5 | LL | x += { | ^ | note: whether read occurs before this write depends on evaluation order - --> $DIR/eval_order_dependence.rs:20:9 + --> $DIR/eval_order_dependence.rs:18:9 | LL | x = 20; | ^^^^^^ error: unsequenced read of `x` - --> $DIR/eval_order_dependence.rs:32:12 + --> $DIR/eval_order_dependence.rs:30:12 | LL | a: x, | ^ | note: whether read occurs before this write depends on evaluation order - --> $DIR/eval_order_dependence.rs:34:13 + --> $DIR/eval_order_dependence.rs:32:13 | LL | x = 6; | ^^^^^ error: unsequenced read of `x` - --> $DIR/eval_order_dependence.rs:41:9 + --> $DIR/eval_order_dependence.rs:39:9 | LL | x += { | ^ | note: whether read occurs before this write depends on evaluation order - --> $DIR/eval_order_dependence.rs:42:13 + --> $DIR/eval_order_dependence.rs:40:13 | LL | x = 20; | ^^^^^^ diff --git a/src/tools/clippy/tests/ui/expect_fun_call.fixed b/src/tools/clippy/tests/ui/expect_fun_call.fixed index a756d1cf50..cf923a6a59 100644 --- a/src/tools/clippy/tests/ui/expect_fun_call.fixed +++ b/src/tools/clippy/tests/ui/expect_fun_call.fixed @@ -1,6 +1,7 @@ // run-rustfix #![warn(clippy::expect_fun_call)] +#![allow(clippy::to_string_in_format_args)] /// Checks implementation of the `EXPECT_FUN_CALL` lint diff --git a/src/tools/clippy/tests/ui/expect_fun_call.rs b/src/tools/clippy/tests/ui/expect_fun_call.rs index 60bbaa89d4..e6f252259d 100644 --- a/src/tools/clippy/tests/ui/expect_fun_call.rs +++ b/src/tools/clippy/tests/ui/expect_fun_call.rs @@ -1,6 +1,7 @@ // run-rustfix #![warn(clippy::expect_fun_call)] +#![allow(clippy::to_string_in_format_args)] /// Checks implementation of the `EXPECT_FUN_CALL` lint diff --git a/src/tools/clippy/tests/ui/expect_fun_call.stderr b/src/tools/clippy/tests/ui/expect_fun_call.stderr index 6dc796f5ce..ac48a06671 100644 --- a/src/tools/clippy/tests/ui/expect_fun_call.stderr +++ b/src/tools/clippy/tests/ui/expect_fun_call.stderr @@ -1,5 +1,5 @@ error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:28:26 + --> $DIR/expect_fun_call.rs:29:26 | LL | with_none_and_format.expect(&format!("Error {}: fake error", error_code)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))` @@ -7,67 +7,67 @@ LL | with_none_and_format.expect(&format!("Error {}: fake error", error_code = note: `-D clippy::expect-fun-call` implied by `-D warnings` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:31:26 + --> $DIR/expect_fun_call.rs:32:26 | LL | with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:41:25 + --> $DIR/expect_fun_call.rs:42:25 | LL | with_err_and_format.expect(&format!("Error {}: fake error", error_code)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:44:25 + --> $DIR/expect_fun_call.rs:45:25 | LL | with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:56:17 + --> $DIR/expect_fun_call.rs:57:17 | LL | Some("foo").expect(format!("{} {}", 1, 2).as_ref()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("{} {}", 1, 2))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:77:21 + --> $DIR/expect_fun_call.rs:78:21 | LL | Some("foo").expect(&get_string()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_string()) })` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:78:21 + --> $DIR/expect_fun_call.rs:79:21 | LL | Some("foo").expect(get_string().as_ref()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_string()) })` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:79:21 + --> $DIR/expect_fun_call.rs:80:21 | LL | Some("foo").expect(get_string().as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_string()) })` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:81:21 + --> $DIR/expect_fun_call.rs:82:21 | LL | Some("foo").expect(get_static_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_static_str()) })` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:82:21 + --> $DIR/expect_fun_call.rs:83:21 | LL | Some("foo").expect(get_non_static_str(&0)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_non_static_str(&0).to_string()) })` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:86:16 + --> $DIR/expect_fun_call.rs:87:16 | LL | Some(true).expect(&format!("key {}, {}", 1, 2)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("key {}, {}", 1, 2))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:92:17 + --> $DIR/expect_fun_call.rs:93:17 | LL | opt_ref.expect(&format!("{:?}", opt_ref)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("{:?}", opt_ref))` diff --git a/src/tools/clippy/tests/ui/fallible_impl_from.stderr b/src/tools/clippy/tests/ui/fallible_impl_from.stderr index 5772ff0550..4e0f08a121 100644 --- a/src/tools/clippy/tests/ui/fallible_impl_from.stderr +++ b/src/tools/clippy/tests/ui/fallible_impl_from.stderr @@ -38,7 +38,7 @@ note: potential failure(s) | LL | panic!(); | ^^^^^^^^ - = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info) error: consider implementing `TryFrom` instead --> $DIR/fallible_impl_from.rs:35:1 @@ -65,7 +65,7 @@ LL | } else if s.parse::<u32>().unwrap() != 42 { | ^^^^^^^^^^^^^^^^^^^^^^^^^ LL | panic!("{:?}", s); | ^^^^^^^^^^^^^^^^^ - = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info) error: consider implementing `TryFrom` instead --> $DIR/fallible_impl_from.rs:53:1 @@ -87,7 +87,7 @@ LL | if s.parse::<u32>().ok().unwrap() != 42 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | panic!("{:?}", s); | ^^^^^^^^^^^^^^^^^ - = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 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 787053fb00..7367910eaa 100644 --- a/src/tools/clippy/tests/ui/field_reassign_with_default.rs +++ b/src/tools/clippy/tests/ui/field_reassign_with_default.rs @@ -183,3 +183,67 @@ struct WrapperMulti<T, U> { i: T, j: U, } + +mod issue6312 { + use std::sync::atomic::AtomicBool; + use std::sync::Arc; + + // do not lint: type implements `Drop` but not all fields are `Copy` + #[derive(Clone, Default)] + pub struct ImplDropNotAllCopy { + name: String, + delay_data_sync: Arc<AtomicBool>, + } + + impl Drop for ImplDropNotAllCopy { + fn drop(&mut self) { + self.close() + } + } + + impl ImplDropNotAllCopy { + fn new(name: &str) -> Self { + let mut f = ImplDropNotAllCopy::default(); + f.name = name.to_owned(); + f + } + fn close(&self) {} + } + + // lint: type implements `Drop` and all fields are `Copy` + #[derive(Clone, Default)] + pub struct ImplDropAllCopy { + name: usize, + delay_data_sync: bool, + } + + impl Drop for ImplDropAllCopy { + fn drop(&mut self) { + self.close() + } + } + + impl ImplDropAllCopy { + fn new(name: &str) -> Self { + let mut f = ImplDropAllCopy::default(); + f.name = name.len(); + f + } + fn close(&self) {} + } + + // lint: type does not implement `Drop` though all fields are `Copy` + #[derive(Clone, Default)] + pub struct NoDropAllCopy { + name: usize, + delay_data_sync: bool, + } + + impl NoDropAllCopy { + fn new(name: &str) -> Self { + let mut f = NoDropAllCopy::default(); + f.name = name.len(); + f + } + } +} 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 b56db08ec8..3ce4b91a54 100644 --- a/src/tools/clippy/tests/ui/field_reassign_with_default.stderr +++ b/src/tools/clippy/tests/ui/field_reassign_with_default.stderr @@ -107,5 +107,29 @@ note: consider initializing the variable with `WrapperMulti::<i32, i64> { i: 42, LL | let mut a: WrapperMulti<i32, i64> = Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 9 previous errors +error: field assignment outside of initializer for an instance created with Default::default() + --> $DIR/field_reassign_with_default.rs:229:13 + | +LL | f.name = name.len(); + | ^^^^^^^^^^^^^^^^^^^^ + | +note: consider initializing the variable with `issue6312::ImplDropAllCopy { name: name.len(), ..Default::default() }` and removing relevant reassignments + --> $DIR/field_reassign_with_default.rs:228:13 + | +LL | let mut f = ImplDropAllCopy::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: field assignment outside of initializer for an instance created with Default::default() + --> $DIR/field_reassign_with_default.rs:245:13 + | +LL | f.name = name.len(); + | ^^^^^^^^^^^^^^^^^^^^ + | +note: consider initializing the variable with `issue6312::NoDropAllCopy { name: name.len(), ..Default::default() }` and removing relevant reassignments + --> $DIR/field_reassign_with_default.rs:244:13 + | +LL | let mut f = NoDropAllCopy::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 11 previous errors diff --git a/src/tools/clippy/tests/ui/fn_params_excessive_bools.rs b/src/tools/clippy/tests/ui/fn_params_excessive_bools.rs index 7d6fd607e6..1442ee08e7 100644 --- a/src/tools/clippy/tests/ui/fn_params_excessive_bools.rs +++ b/src/tools/clippy/tests/ui/fn_params_excessive_bools.rs @@ -1,4 +1,5 @@ #![warn(clippy::fn_params_excessive_bools)] +#![allow(clippy::too_many_arguments)] extern "C" { fn f(_: bool, _: bool, _: bool, _: bool); diff --git a/src/tools/clippy/tests/ui/fn_params_excessive_bools.stderr b/src/tools/clippy/tests/ui/fn_params_excessive_bools.stderr index 4e5dbc261d..cd9d07fa11 100644 --- a/src/tools/clippy/tests/ui/fn_params_excessive_bools.stderr +++ b/src/tools/clippy/tests/ui/fn_params_excessive_bools.stderr @@ -1,5 +1,5 @@ error: more than 3 bools in function parameters - --> $DIR/fn_params_excessive_bools.rs:17:1 + --> $DIR/fn_params_excessive_bools.rs:18:1 | LL | fn g(_: bool, _: bool, _: bool, _: bool) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | fn g(_: bool, _: bool, _: bool, _: bool) {} = help: consider refactoring bools into two-variant enums error: more than 3 bools in function parameters - --> $DIR/fn_params_excessive_bools.rs:20:1 + --> $DIR/fn_params_excessive_bools.rs:21:1 | LL | fn t(_: S, _: S, _: Box<S>, _: Vec<u32>, _: bool, _: bool, _: bool, _: bool) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | fn t(_: S, _: S, _: Box<S>, _: Vec<u32>, _: bool, _: bool, _: bool, _: bool = help: consider refactoring bools into two-variant enums error: more than 3 bools in function parameters - --> $DIR/fn_params_excessive_bools.rs:24:5 + --> $DIR/fn_params_excessive_bools.rs:25:5 | LL | fn f(_: bool, _: bool, _: bool, _: bool); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL | fn f(_: bool, _: bool, _: bool, _: bool); = help: consider refactoring bools into two-variant enums error: more than 3 bools in function parameters - --> $DIR/fn_params_excessive_bools.rs:29:5 + --> $DIR/fn_params_excessive_bools.rs:30:5 | LL | fn f(&self, _: bool, _: bool, _: bool, _: bool) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL | fn f(&self, _: bool, _: bool, _: bool, _: bool) {} = help: consider refactoring bools into two-variant enums error: more than 3 bools in function parameters - --> $DIR/fn_params_excessive_bools.rs:41:5 + --> $DIR/fn_params_excessive_bools.rs:42:5 | LL | / fn n(_: bool, _: u32, _: bool, _: Box<u32>, _: bool, _: bool) { LL | | fn nn(_: bool, _: bool, _: bool, _: bool) {} @@ -42,7 +42,7 @@ LL | | } = help: consider refactoring bools into two-variant enums error: more than 3 bools in function parameters - --> $DIR/fn_params_excessive_bools.rs:42:9 + --> $DIR/fn_params_excessive_bools.rs:43:9 | LL | fn nn(_: bool, _: bool, _: bool, _: bool) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/fn_to_numeric_cast_any.rs b/src/tools/clippy/tests/ui/fn_to_numeric_cast_any.rs new file mode 100644 index 0000000000..4670468392 --- /dev/null +++ b/src/tools/clippy/tests/ui/fn_to_numeric_cast_any.rs @@ -0,0 +1,76 @@ +#![warn(clippy::fn_to_numeric_cast_any)] +#![allow(clippy::fn_to_numeric_cast, clippy::fn_to_numeric_cast_with_truncation)] + +fn foo() -> u8 { + 0 +} + +fn generic_foo<T>(x: T) -> T { + x +} + +trait Trait { + fn static_method() -> u32 { + 2 + } +} + +struct Struct; + +impl Trait for Struct {} + +fn fn_pointer_to_integer() { + let _ = foo as i8; + let _ = foo as i16; + let _ = foo as i32; + let _ = foo as i64; + let _ = foo as i128; + let _ = foo as isize; + + let _ = foo as u8; + let _ = foo as u16; + let _ = foo as u32; + let _ = foo as u64; + let _ = foo as u128; + let _ = foo as usize; +} + +fn static_method_to_integer() { + let _ = Struct::static_method as usize; +} + +fn fn_with_fn_arg(f: fn(i32) -> u32) -> usize { + f as usize +} + +fn fn_with_generic_static_trait_method<T: Trait>() -> usize { + T::static_method as usize +} + +fn closure_to_fn_to_integer() { + let clos = |x| x * 2_u32; + + let _ = (clos as fn(u32) -> u32) as usize; +} + +fn fn_to_raw_ptr() { + let _ = foo as *const (); +} + +fn cast_fn_to_self() { + // Casting to the same function pointer type should be permitted. + let _ = foo as fn() -> u8; +} + +fn cast_generic_to_concrete() { + // Casting to a more concrete function pointer type should be permitted. + let _ = generic_foo as fn(usize) -> usize; +} + +fn cast_closure_to_fn() { + // Casting a closure to a function pointer should be permitted. + let id = |x| x; + let _ = id as fn(usize) -> usize; +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/fn_to_numeric_cast_any.stderr b/src/tools/clippy/tests/ui/fn_to_numeric_cast_any.stderr new file mode 100644 index 0000000000..a6c4a77672 --- /dev/null +++ b/src/tools/clippy/tests/ui/fn_to_numeric_cast_any.stderr @@ -0,0 +1,106 @@ +error: casting function pointer `foo` to `i8` + --> $DIR/fn_to_numeric_cast_any.rs:23:13 + | +LL | let _ = foo as i8; + | ^^^^^^^^^ help: did you mean to invoke the function?: `foo() as i8` + | + = note: `-D clippy::fn-to-numeric-cast-any` implied by `-D warnings` + +error: casting function pointer `foo` to `i16` + --> $DIR/fn_to_numeric_cast_any.rs:24:13 + | +LL | let _ = foo as i16; + | ^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as i16` + +error: casting function pointer `foo` to `i32` + --> $DIR/fn_to_numeric_cast_any.rs:25:13 + | +LL | let _ = foo as i32; + | ^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as i32` + +error: casting function pointer `foo` to `i64` + --> $DIR/fn_to_numeric_cast_any.rs:26:13 + | +LL | let _ = foo as i64; + | ^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as i64` + +error: casting function pointer `foo` to `i128` + --> $DIR/fn_to_numeric_cast_any.rs:27:13 + | +LL | let _ = foo as i128; + | ^^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as i128` + +error: casting function pointer `foo` to `isize` + --> $DIR/fn_to_numeric_cast_any.rs:28:13 + | +LL | let _ = foo as isize; + | ^^^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as isize` + +error: casting function pointer `foo` to `u8` + --> $DIR/fn_to_numeric_cast_any.rs:30:13 + | +LL | let _ = foo as u8; + | ^^^^^^^^^ help: did you mean to invoke the function?: `foo() as u8` + +error: casting function pointer `foo` to `u16` + --> $DIR/fn_to_numeric_cast_any.rs:31:13 + | +LL | let _ = foo as u16; + | ^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as u16` + +error: casting function pointer `foo` to `u32` + --> $DIR/fn_to_numeric_cast_any.rs:32:13 + | +LL | let _ = foo as u32; + | ^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as u32` + +error: casting function pointer `foo` to `u64` + --> $DIR/fn_to_numeric_cast_any.rs:33:13 + | +LL | let _ = foo as u64; + | ^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as u64` + +error: casting function pointer `foo` to `u128` + --> $DIR/fn_to_numeric_cast_any.rs:34:13 + | +LL | let _ = foo as u128; + | ^^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as u128` + +error: casting function pointer `foo` to `usize` + --> $DIR/fn_to_numeric_cast_any.rs:35:13 + | +LL | let _ = foo as usize; + | ^^^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as usize` + +error: casting function pointer `Struct::static_method` to `usize` + --> $DIR/fn_to_numeric_cast_any.rs:39:13 + | +LL | let _ = Struct::static_method as usize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean to invoke the function?: `Struct::static_method() as usize` + +error: casting function pointer `f` to `usize` + --> $DIR/fn_to_numeric_cast_any.rs:43:5 + | +LL | f as usize + | ^^^^^^^^^^ help: did you mean to invoke the function?: `f() as usize` + +error: casting function pointer `T::static_method` to `usize` + --> $DIR/fn_to_numeric_cast_any.rs:47:5 + | +LL | T::static_method as usize + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean to invoke the function?: `T::static_method() as usize` + +error: casting function pointer `(clos as fn(u32) -> u32)` to `usize` + --> $DIR/fn_to_numeric_cast_any.rs:53:13 + | +LL | let _ = (clos as fn(u32) -> u32) as usize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean to invoke the function?: `(clos as fn(u32) -> u32)() as usize` + +error: casting function pointer `foo` to `*const ()` + --> $DIR/fn_to_numeric_cast_any.rs:57:13 + | +LL | let _ = foo as *const (); + | ^^^^^^^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as *const ()` + +error: aborting due to 17 previous errors + diff --git a/src/tools/clippy/tests/ui/format.fixed b/src/tools/clippy/tests/ui/format.fixed index 5dd64140e8..78d2bfd474 100644 --- a/src/tools/clippy/tests/ui/format.fixed +++ b/src/tools/clippy/tests/ui/format.fixed @@ -1,6 +1,6 @@ // run-rustfix -#![allow(clippy::print_literal, clippy::redundant_clone)] +#![allow(clippy::print_literal, clippy::redundant_clone, clippy::to_string_in_format_args)] #![warn(clippy::useless_format)] struct Foo(pub String); @@ -16,6 +16,8 @@ fn main() { r##"foo {} " bar"##.to_string(); + let _ = String::new(); + "foo".to_string(); format!("{:?}", "foo"); // Don't warn about `Debug`. format!("{:8}", "foo"); @@ -71,4 +73,10 @@ fn main() { let _s: String = (&*v.join("\n")).to_string(); format!("prepend {:+}", "s"); + + // Issue #8290 + let x = "foo"; + let _ = x.to_string(); + let _ = format!("{x:?}"); // Don't lint on debug + let _ = x.to_string(); } diff --git a/src/tools/clippy/tests/ui/format.rs b/src/tools/clippy/tests/ui/format.rs index 4599fb5207..009c1aa216 100644 --- a/src/tools/clippy/tests/ui/format.rs +++ b/src/tools/clippy/tests/ui/format.rs @@ -1,6 +1,6 @@ // run-rustfix -#![allow(clippy::print_literal, clippy::redundant_clone)] +#![allow(clippy::print_literal, clippy::redundant_clone, clippy::to_string_in_format_args)] #![warn(clippy::useless_format)] struct Foo(pub String); @@ -18,6 +18,8 @@ fn main() { " bar"## ); + let _ = format!(""); + format!("{}", "foo"); format!("{:?}", "foo"); // Don't warn about `Debug`. format!("{:8}", "foo"); @@ -73,4 +75,10 @@ fn main() { let _s: String = format!("{}", &*v.join("\n")); format!("prepend {:+}", "s"); + + // Issue #8290 + let x = "foo"; + let _ = format!("{x}"); + let _ = format!("{x:?}"); // Don't lint on debug + let _ = format!("{y}", y = x); } diff --git a/src/tools/clippy/tests/ui/format.stderr b/src/tools/clippy/tests/ui/format.stderr index 701399b32d..660be57585 100644 --- a/src/tools/clippy/tests/ui/format.stderr +++ b/src/tools/clippy/tests/ui/format.stderr @@ -34,64 +34,82 @@ LL ~ " bar"##.to_string(); | error: useless use of `format!` - --> $DIR/format.rs:21:5 + --> $DIR/format.rs:21:13 + | +LL | let _ = format!(""); + | ^^^^^^^^^^^ help: consider using `String::new()`: `String::new()` + +error: useless use of `format!` + --> $DIR/format.rs:23:5 | LL | format!("{}", "foo"); | ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()` error: useless use of `format!` - --> $DIR/format.rs:25:5 + --> $DIR/format.rs:27:5 | LL | format!("{:+}", "foo"); // Warn when the format makes no difference. | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()` error: useless use of `format!` - --> $DIR/format.rs:26:5 + --> $DIR/format.rs:28:5 | LL | format!("{:<}", "foo"); // Warn when the format makes no difference. | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()` error: useless use of `format!` - --> $DIR/format.rs:31:5 + --> $DIR/format.rs:33:5 | LL | format!("{}", arg); | ^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()` error: useless use of `format!` - --> $DIR/format.rs:35:5 + --> $DIR/format.rs:37:5 | LL | format!("{:+}", arg); // Warn when the format makes no difference. | ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()` error: useless use of `format!` - --> $DIR/format.rs:36:5 + --> $DIR/format.rs:38:5 | LL | format!("{:<}", arg); // Warn when the format makes no difference. | ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()` error: useless use of `format!` - --> $DIR/format.rs:63:5 + --> $DIR/format.rs:65:5 | LL | format!("{}", 42.to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `42.to_string()` error: useless use of `format!` - --> $DIR/format.rs:65:5 + --> $DIR/format.rs:67:5 | LL | format!("{}", x.display().to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.display().to_string()` error: useless use of `format!` - --> $DIR/format.rs:69:18 + --> $DIR/format.rs:71:18 | LL | let _ = Some(format!("{}", a + "bar")); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `a + "bar"` error: useless use of `format!` - --> $DIR/format.rs:73:22 + --> $DIR/format.rs:75: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 +error: useless use of `format!` + --> $DIR/format.rs:81:13 + | +LL | let _ = format!("{x}"); + | ^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.to_string()` + +error: useless use of `format!` + --> $DIR/format.rs:83:13 + | +LL | let _ = format!("{y}", y = x); + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.to_string()` + +error: aborting due to 17 previous errors diff --git a/src/tools/clippy/tests/ui/format_args.fixed b/src/tools/clippy/tests/ui/format_args.fixed new file mode 100644 index 0000000000..69b5e1c722 --- /dev/null +++ b/src/tools/clippy/tests/ui/format_args.fixed @@ -0,0 +1,117 @@ +// run-rustfix + +#![allow(unreachable_code)] +#![allow(unused_macros)] +#![allow(unused_variables)] +#![allow(clippy::assertions_on_constants)] +#![allow(clippy::eq_op)] +#![allow(clippy::print_literal)] +#![warn(clippy::to_string_in_format_args)] + +use std::io::{stdout, Write}; +use std::ops::Deref; +use std::panic::Location; + +struct Somewhere; + +impl ToString for Somewhere { + fn to_string(&self) -> String { + String::from("somewhere") + } +} + +struct X(u32); + +impl Deref for X { + type Target = u32; + + fn deref(&self) -> &u32 { + &self.0 + } +} + +struct Y<'a>(&'a X); + +impl<'a> Deref for Y<'a> { + type Target = &'a X; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +struct Z(u32); + +impl Deref for Z { + type Target = u32; + + fn deref(&self) -> &u32 { + &self.0 + } +} + +impl std::fmt::Display for Z { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Z") + } +} + +macro_rules! my_macro { + () => { + // here be dragons, do not enter (or lint) + println!("error: something failed at {}", Location::caller().to_string()); + }; +} + +macro_rules! my_other_macro { + () => { + Location::caller().to_string() + }; +} + +fn main() { + let x = &X(1); + let x_ref = &x; + + let _ = format!("error: something failed at {}", Location::caller()); + let _ = write!( + stdout(), + "error: something failed at {}", + Location::caller() + ); + let _ = writeln!( + stdout(), + "error: something failed at {}", + Location::caller() + ); + print!("error: something failed at {}", Location::caller()); + println!("error: something failed at {}", Location::caller()); + eprint!("error: something failed at {}", Location::caller()); + eprintln!("error: something failed at {}", Location::caller()); + let _ = format_args!("error: something failed at {}", Location::caller()); + assert!(true, "error: something failed at {}", Location::caller()); + assert_eq!(0, 0, "error: something failed at {}", Location::caller()); + assert_ne!(0, 0, "error: something failed at {}", Location::caller()); + panic!("error: something failed at {}", Location::caller()); + println!("{}", *X(1)); + println!("{}", ***Y(&X(1))); + println!("{}", Z(1)); + println!("{}", **x); + println!("{}", ***x_ref); + // https://github.com/rust-lang/rust-clippy/issues/7903 + println!("{foo}{bar}", foo = "foo", bar = "bar"); + println!("{foo}{bar}", foo = "foo", bar = "bar"); + println!("{foo}{bar}", bar = "bar", foo = "foo"); + println!("{foo}{bar}", bar = "bar", foo = "foo"); + + // negative tests + println!("error: something failed at {}", Somewhere.to_string()); + // The next two tests are negative because caching the string might be faster than calling `<X as + // Display>::fmt` twice. + println!("{} and again {0}", x.to_string()); + println!("{foo}{foo}", foo = "foo".to_string()); + my_macro!(); + println!("error: something failed at {}", my_other_macro!()); + // https://github.com/rust-lang/rust-clippy/issues/7903 + println!("{foo}{foo:?}", foo = "foo".to_string()); +} diff --git a/src/tools/clippy/tests/ui/format_args.rs b/src/tools/clippy/tests/ui/format_args.rs new file mode 100644 index 0000000000..3a434c5bf0 --- /dev/null +++ b/src/tools/clippy/tests/ui/format_args.rs @@ -0,0 +1,117 @@ +// run-rustfix + +#![allow(unreachable_code)] +#![allow(unused_macros)] +#![allow(unused_variables)] +#![allow(clippy::assertions_on_constants)] +#![allow(clippy::eq_op)] +#![allow(clippy::print_literal)] +#![warn(clippy::to_string_in_format_args)] + +use std::io::{stdout, Write}; +use std::ops::Deref; +use std::panic::Location; + +struct Somewhere; + +impl ToString for Somewhere { + fn to_string(&self) -> String { + String::from("somewhere") + } +} + +struct X(u32); + +impl Deref for X { + type Target = u32; + + fn deref(&self) -> &u32 { + &self.0 + } +} + +struct Y<'a>(&'a X); + +impl<'a> Deref for Y<'a> { + type Target = &'a X; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +struct Z(u32); + +impl Deref for Z { + type Target = u32; + + fn deref(&self) -> &u32 { + &self.0 + } +} + +impl std::fmt::Display for Z { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Z") + } +} + +macro_rules! my_macro { + () => { + // here be dragons, do not enter (or lint) + println!("error: something failed at {}", Location::caller().to_string()); + }; +} + +macro_rules! my_other_macro { + () => { + Location::caller().to_string() + }; +} + +fn main() { + let x = &X(1); + let x_ref = &x; + + let _ = format!("error: something failed at {}", Location::caller().to_string()); + let _ = write!( + stdout(), + "error: something failed at {}", + Location::caller().to_string() + ); + let _ = writeln!( + stdout(), + "error: something failed at {}", + Location::caller().to_string() + ); + print!("error: something failed at {}", Location::caller().to_string()); + println!("error: something failed at {}", Location::caller().to_string()); + eprint!("error: something failed at {}", Location::caller().to_string()); + eprintln!("error: something failed at {}", Location::caller().to_string()); + let _ = format_args!("error: something failed at {}", Location::caller().to_string()); + assert!(true, "error: something failed at {}", Location::caller().to_string()); + assert_eq!(0, 0, "error: something failed at {}", Location::caller().to_string()); + assert_ne!(0, 0, "error: something failed at {}", Location::caller().to_string()); + panic!("error: something failed at {}", Location::caller().to_string()); + println!("{}", X(1).to_string()); + println!("{}", Y(&X(1)).to_string()); + println!("{}", Z(1).to_string()); + println!("{}", x.to_string()); + println!("{}", x_ref.to_string()); + // https://github.com/rust-lang/rust-clippy/issues/7903 + println!("{foo}{bar}", foo = "foo".to_string(), bar = "bar"); + println!("{foo}{bar}", foo = "foo", bar = "bar".to_string()); + println!("{foo}{bar}", bar = "bar".to_string(), foo = "foo"); + println!("{foo}{bar}", bar = "bar", foo = "foo".to_string()); + + // negative tests + println!("error: something failed at {}", Somewhere.to_string()); + // The next two tests are negative because caching the string might be faster than calling `<X as + // Display>::fmt` twice. + println!("{} and again {0}", x.to_string()); + println!("{foo}{foo}", foo = "foo".to_string()); + my_macro!(); + println!("error: something failed at {}", my_other_macro!()); + // https://github.com/rust-lang/rust-clippy/issues/7903 + println!("{foo}{foo:?}", foo = "foo".to_string()); +} diff --git a/src/tools/clippy/tests/ui/format_args.stderr b/src/tools/clippy/tests/ui/format_args.stderr new file mode 100644 index 0000000000..c0cbca5079 --- /dev/null +++ b/src/tools/clippy/tests/ui/format_args.stderr @@ -0,0 +1,130 @@ +error: `to_string` applied to a type that implements `Display` in `format!` args + --> $DIR/format_args.rs:76:72 + | +LL | let _ = format!("error: something failed at {}", Location::caller().to_string()); + | ^^^^^^^^^^^^ help: remove this + | + = note: `-D clippy::to-string-in-format-args` implied by `-D warnings` + +error: `to_string` applied to a type that implements `Display` in `write!` args + --> $DIR/format_args.rs:80:27 + | +LL | Location::caller().to_string() + | ^^^^^^^^^^^^ help: remove this + +error: `to_string` applied to a type that implements `Display` in `writeln!` args + --> $DIR/format_args.rs:85:27 + | +LL | Location::caller().to_string() + | ^^^^^^^^^^^^ help: remove this + +error: `to_string` applied to a type that implements `Display` in `print!` args + --> $DIR/format_args.rs:87:63 + | +LL | print!("error: something failed at {}", Location::caller().to_string()); + | ^^^^^^^^^^^^ help: remove this + +error: `to_string` applied to a type that implements `Display` in `println!` args + --> $DIR/format_args.rs:88:65 + | +LL | println!("error: something failed at {}", Location::caller().to_string()); + | ^^^^^^^^^^^^ help: remove this + +error: `to_string` applied to a type that implements `Display` in `eprint!` args + --> $DIR/format_args.rs:89:64 + | +LL | eprint!("error: something failed at {}", Location::caller().to_string()); + | ^^^^^^^^^^^^ help: remove this + +error: `to_string` applied to a type that implements `Display` in `eprintln!` args + --> $DIR/format_args.rs:90:66 + | +LL | eprintln!("error: something failed at {}", Location::caller().to_string()); + | ^^^^^^^^^^^^ help: remove this + +error: `to_string` applied to a type that implements `Display` in `format_args!` args + --> $DIR/format_args.rs:91:77 + | +LL | let _ = format_args!("error: something failed at {}", Location::caller().to_string()); + | ^^^^^^^^^^^^ help: remove this + +error: `to_string` applied to a type that implements `Display` in `assert!` args + --> $DIR/format_args.rs:92:70 + | +LL | assert!(true, "error: something failed at {}", Location::caller().to_string()); + | ^^^^^^^^^^^^ help: remove this + +error: `to_string` applied to a type that implements `Display` in `assert_eq!` args + --> $DIR/format_args.rs:93:73 + | +LL | assert_eq!(0, 0, "error: something failed at {}", Location::caller().to_string()); + | ^^^^^^^^^^^^ help: remove this + +error: `to_string` applied to a type that implements `Display` in `assert_ne!` args + --> $DIR/format_args.rs:94:73 + | +LL | assert_ne!(0, 0, "error: something failed at {}", Location::caller().to_string()); + | ^^^^^^^^^^^^ help: remove this + +error: `to_string` applied to a type that implements `Display` in `panic!` args + --> $DIR/format_args.rs:95:63 + | +LL | panic!("error: something failed at {}", Location::caller().to_string()); + | ^^^^^^^^^^^^ help: remove this + +error: `to_string` applied to a type that implements `Display` in `println!` args + --> $DIR/format_args.rs:96:20 + | +LL | println!("{}", X(1).to_string()); + | ^^^^^^^^^^^^^^^^ help: use this: `*X(1)` + +error: `to_string` applied to a type that implements `Display` in `println!` args + --> $DIR/format_args.rs:97:20 + | +LL | println!("{}", Y(&X(1)).to_string()); + | ^^^^^^^^^^^^^^^^^^^^ help: use this: `***Y(&X(1))` + +error: `to_string` applied to a type that implements `Display` in `println!` args + --> $DIR/format_args.rs:98:24 + | +LL | println!("{}", Z(1).to_string()); + | ^^^^^^^^^^^^ help: remove this + +error: `to_string` applied to a type that implements `Display` in `println!` args + --> $DIR/format_args.rs:99:20 + | +LL | println!("{}", x.to_string()); + | ^^^^^^^^^^^^^ help: use this: `**x` + +error: `to_string` applied to a type that implements `Display` in `println!` args + --> $DIR/format_args.rs:100:20 + | +LL | println!("{}", x_ref.to_string()); + | ^^^^^^^^^^^^^^^^^ help: use this: `***x_ref` + +error: `to_string` applied to a type that implements `Display` in `println!` args + --> $DIR/format_args.rs:102:39 + | +LL | println!("{foo}{bar}", foo = "foo".to_string(), bar = "bar"); + | ^^^^^^^^^^^^ help: remove this + +error: `to_string` applied to a type that implements `Display` in `println!` args + --> $DIR/format_args.rs:103:52 + | +LL | println!("{foo}{bar}", foo = "foo", bar = "bar".to_string()); + | ^^^^^^^^^^^^ help: remove this + +error: `to_string` applied to a type that implements `Display` in `println!` args + --> $DIR/format_args.rs:104:39 + | +LL | println!("{foo}{bar}", bar = "bar".to_string(), foo = "foo"); + | ^^^^^^^^^^^^ help: remove this + +error: `to_string` applied to a type that implements `Display` in `println!` args + --> $DIR/format_args.rs:105:52 + | +LL | println!("{foo}{bar}", bar = "bar", foo = "foo".to_string()); + | ^^^^^^^^^^^^ help: remove this + +error: aborting due to 21 previous errors + diff --git a/src/tools/clippy/tests/ui/format_args_unfixable.rs b/src/tools/clippy/tests/ui/format_args_unfixable.rs new file mode 100644 index 0000000000..b24ddf7321 --- /dev/null +++ b/src/tools/clippy/tests/ui/format_args_unfixable.rs @@ -0,0 +1,61 @@ +#![allow(clippy::assertions_on_constants)] +#![allow(clippy::eq_op)] +#![warn(clippy::format_in_format_args)] +#![warn(clippy::to_string_in_format_args)] + +use std::io::{stdout, Error, ErrorKind, Write}; +use std::ops::Deref; +use std::panic::Location; + +macro_rules! my_macro { + () => { + // here be dragons, do not enter (or lint) + println!("error: {}", format!("something failed at {}", Location::caller())); + }; +} + +macro_rules! my_other_macro { + () => { + format!("something failed at {}", Location::caller()) + }; +} + +fn main() { + let error = Error::new(ErrorKind::Other, "bad thing"); + let x = 'x'; + + println!("error: {}", format!("something failed at {}", Location::caller())); + println!("{}: {}", error, format!("something failed at {}", Location::caller())); + println!("{:?}: {}", error, format!("something failed at {}", Location::caller())); + println!("{{}}: {}", format!("something failed at {}", Location::caller())); + println!(r#"error: "{}""#, format!("something failed at {}", Location::caller())); + println!("error: {}", format!(r#"something failed at "{}""#, Location::caller())); + println!("error: {}", format!("something failed at {} {0}", Location::caller())); + let _ = format!("error: {}", format!("something failed at {}", Location::caller())); + let _ = write!( + stdout(), + "error: {}", + format!("something failed at {}", Location::caller()) + ); + let _ = writeln!( + stdout(), + "error: {}", + format!("something failed at {}", Location::caller()) + ); + print!("error: {}", format!("something failed at {}", Location::caller())); + eprint!("error: {}", format!("something failed at {}", Location::caller())); + eprintln!("error: {}", format!("something failed at {}", Location::caller())); + let _ = format_args!("error: {}", format!("something failed at {}", Location::caller())); + assert!(true, "error: {}", format!("something failed at {}", Location::caller())); + assert_eq!(0, 0, "error: {}", format!("something failed at {}", Location::caller())); + assert_ne!(0, 0, "error: {}", format!("something failed at {}", Location::caller())); + panic!("error: {}", format!("something failed at {}", Location::caller())); + + // negative tests + println!("error: {}", format_args!("something failed at {}", Location::caller())); + println!("error: {:>70}", format!("something failed at {}", Location::caller())); + println!("error: {} {0}", format!("something failed at {}", Location::caller())); + println!("{} and again {0}", format!("hi {}", x)); + my_macro!(); + println!("error: {}", my_other_macro!()); +} diff --git a/src/tools/clippy/tests/ui/format_args_unfixable.stderr b/src/tools/clippy/tests/ui/format_args_unfixable.stderr new file mode 100644 index 0000000000..4476218ad5 --- /dev/null +++ b/src/tools/clippy/tests/ui/format_args_unfixable.stderr @@ -0,0 +1,175 @@ +error: `format!` in `println!` args + --> $DIR/format_args_unfixable.rs:27:5 + | +LL | println!("error: {}", format!("something failed at {}", Location::caller())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::format-in-format-args` implied by `-D warnings` + = help: combine the `format!(..)` arguments with the outer `println!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: `format!` in `println!` args + --> $DIR/format_args_unfixable.rs:28:5 + | +LL | println!("{}: {}", error, format!("something failed at {}", Location::caller())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: combine the `format!(..)` arguments with the outer `println!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: `format!` in `println!` args + --> $DIR/format_args_unfixable.rs:29:5 + | +LL | println!("{:?}: {}", error, format!("something failed at {}", Location::caller())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: combine the `format!(..)` arguments with the outer `println!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: `format!` in `println!` args + --> $DIR/format_args_unfixable.rs:30:5 + | +LL | println!("{{}}: {}", format!("something failed at {}", Location::caller())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: combine the `format!(..)` arguments with the outer `println!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: `format!` in `println!` args + --> $DIR/format_args_unfixable.rs:31:5 + | +LL | println!(r#"error: "{}""#, format!("something failed at {}", Location::caller())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: combine the `format!(..)` arguments with the outer `println!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: `format!` in `println!` args + --> $DIR/format_args_unfixable.rs:32:5 + | +LL | println!("error: {}", format!(r#"something failed at "{}""#, Location::caller())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: combine the `format!(..)` arguments with the outer `println!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: `format!` in `println!` args + --> $DIR/format_args_unfixable.rs:33:5 + | +LL | println!("error: {}", format!("something failed at {} {0}", Location::caller())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: combine the `format!(..)` arguments with the outer `println!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: `format!` in `format!` args + --> $DIR/format_args_unfixable.rs:34:13 + | +LL | let _ = format!("error: {}", format!("something failed at {}", Location::caller())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: combine the `format!(..)` arguments with the outer `format!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: `format!` in `write!` args + --> $DIR/format_args_unfixable.rs:35:13 + | +LL | let _ = write!( + | _____________^ +LL | | stdout(), +LL | | "error: {}", +LL | | format!("something failed at {}", Location::caller()) +LL | | ); + | |_____^ + | + = help: combine the `format!(..)` arguments with the outer `write!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: `format!` in `writeln!` args + --> $DIR/format_args_unfixable.rs:40:13 + | +LL | let _ = writeln!( + | _____________^ +LL | | stdout(), +LL | | "error: {}", +LL | | format!("something failed at {}", Location::caller()) +LL | | ); + | |_____^ + | + = help: combine the `format!(..)` arguments with the outer `writeln!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: `format!` in `print!` args + --> $DIR/format_args_unfixable.rs:45:5 + | +LL | print!("error: {}", format!("something failed at {}", Location::caller())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: combine the `format!(..)` arguments with the outer `print!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: `format!` in `eprint!` args + --> $DIR/format_args_unfixable.rs:46:5 + | +LL | eprint!("error: {}", format!("something failed at {}", Location::caller())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: combine the `format!(..)` arguments with the outer `eprint!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: `format!` in `eprintln!` args + --> $DIR/format_args_unfixable.rs:47:5 + | +LL | eprintln!("error: {}", format!("something failed at {}", Location::caller())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: combine the `format!(..)` arguments with the outer `eprintln!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: `format!` in `format_args!` args + --> $DIR/format_args_unfixable.rs:48:13 + | +LL | let _ = format_args!("error: {}", format!("something failed at {}", Location::caller())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: combine the `format!(..)` arguments with the outer `format_args!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: `format!` in `assert!` args + --> $DIR/format_args_unfixable.rs:49:5 + | +LL | assert!(true, "error: {}", format!("something failed at {}", Location::caller())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: combine the `format!(..)` arguments with the outer `assert!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: `format!` in `assert_eq!` args + --> $DIR/format_args_unfixable.rs:50:5 + | +LL | assert_eq!(0, 0, "error: {}", format!("something failed at {}", Location::caller())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: combine the `format!(..)` arguments with the outer `assert_eq!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: `format!` in `assert_ne!` args + --> $DIR/format_args_unfixable.rs:51:5 + | +LL | assert_ne!(0, 0, "error: {}", format!("something failed at {}", Location::caller())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: combine the `format!(..)` arguments with the outer `assert_ne!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: `format!` in `panic!` args + --> $DIR/format_args_unfixable.rs:52:5 + | +LL | panic!("error: {}", format!("something failed at {}", Location::caller())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: combine the `format!(..)` arguments with the outer `panic!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: aborting due to 18 previous errors + diff --git a/src/tools/clippy/tests/ui/formatting.rs b/src/tools/clippy/tests/ui/formatting.rs index 0d14807ff1..471a8e0de6 100644 --- a/src/tools/clippy/tests/ui/formatting.rs +++ b/src/tools/clippy/tests/ui/formatting.rs @@ -3,6 +3,7 @@ #![allow(unused_assignments)] #![allow(clippy::if_same_then_else)] #![allow(clippy::deref_addrof)] +#![allow(clippy::nonminimal_bool)] fn foo() -> bool { true diff --git a/src/tools/clippy/tests/ui/formatting.stderr b/src/tools/clippy/tests/ui/formatting.stderr index bde434c7e2..9272cd6048 100644 --- a/src/tools/clippy/tests/ui/formatting.stderr +++ b/src/tools/clippy/tests/ui/formatting.stderr @@ -1,5 +1,5 @@ error: this looks like you are trying to use `.. -= ..`, but you really are doing `.. = (- ..)` - --> $DIR/formatting.rs:15:6 + --> $DIR/formatting.rs:16:6 | LL | a =- 35; | ^^^^ @@ -8,7 +8,7 @@ LL | a =- 35; = note: to remove this lint, use either `-=` or `= -` error: this looks like you are trying to use `.. *= ..`, but you really are doing `.. = (* ..)` - --> $DIR/formatting.rs:16:6 + --> $DIR/formatting.rs:17:6 | LL | a =* &191; | ^^^^ @@ -16,7 +16,7 @@ LL | a =* &191; = note: to remove this lint, use either `*=` or `= *` error: this looks like you are trying to use `.. != ..`, but you really are doing `.. = (! ..)` - --> $DIR/formatting.rs:19:6 + --> $DIR/formatting.rs:20:6 | LL | b =! false; | ^^^^ @@ -24,7 +24,7 @@ LL | b =! false; = note: to remove this lint, use either `!=` or `= !` error: possibly missing a comma here - --> $DIR/formatting.rs:28:19 + --> $DIR/formatting.rs:29:19 | LL | -1, -2, -3 // <= no comma here | ^ @@ -33,7 +33,7 @@ LL | -1, -2, -3 // <= no comma here = note: to remove this lint, add a comma or write the expr in a single line error: possibly missing a comma here - --> $DIR/formatting.rs:32:19 + --> $DIR/formatting.rs:33:19 | LL | -1, -2, -3 // <= no comma here | ^ @@ -41,7 +41,7 @@ LL | -1, -2, -3 // <= no comma here = note: to remove this lint, add a comma or write the expr in a single line error: possibly missing a comma here - --> $DIR/formatting.rs:69:11 + --> $DIR/formatting.rs:70:11 | LL | -1 | ^ diff --git a/src/tools/clippy/tests/ui/future_not_send.rs b/src/tools/clippy/tests/ui/future_not_send.rs index d3a920de4b..858036692d 100644 --- a/src/tools/clippy/tests/ui/future_not_send.rs +++ b/src/tools/clippy/tests/ui/future_not_send.rs @@ -1,4 +1,3 @@ -// edition:2018 #![warn(clippy::future_not_send)] use std::cell::Cell; diff --git a/src/tools/clippy/tests/ui/future_not_send.stderr b/src/tools/clippy/tests/ui/future_not_send.stderr index c734051ccf..3cc05e2fdb 100644 --- a/src/tools/clippy/tests/ui/future_not_send.stderr +++ b/src/tools/clippy/tests/ui/future_not_send.stderr @@ -1,12 +1,12 @@ error: future cannot be sent between threads safely - --> $DIR/future_not_send.rs:8:62 + --> $DIR/future_not_send.rs:7:62 | LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool { | ^^^^ future returned by `private_future` is not `Send` | = note: `-D clippy::future-not-send` implied by `-D warnings` note: future is not `Send` as this value is used across an await - --> $DIR/future_not_send.rs:9:5 + --> $DIR/future_not_send.rs:8:5 | LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool { | -- has type `std::rc::Rc<[u8]>` which is not `Send` @@ -16,7 +16,7 @@ LL | } | - `rc` is later dropped here = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send` note: future is not `Send` as this value is used across an await - --> $DIR/future_not_send.rs:9:5 + --> $DIR/future_not_send.rs:8:5 | LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool { | ---- has type `&std::cell::Cell<usize>` which is not `Send` @@ -27,13 +27,13 @@ LL | } = note: `std::cell::Cell<usize>` doesn't implement `std::marker::Sync` error: future cannot be sent between threads safely - --> $DIR/future_not_send.rs:12:42 + --> $DIR/future_not_send.rs:11:42 | LL | pub async fn public_future(rc: Rc<[u8]>) { | ^ future returned by `public_future` is not `Send` | note: future is not `Send` as this value is used across an await - --> $DIR/future_not_send.rs:13:5 + --> $DIR/future_not_send.rs:12:5 | LL | pub async fn public_future(rc: Rc<[u8]>) { | -- has type `std::rc::Rc<[u8]>` which is not `Send` @@ -44,45 +44,45 @@ LL | } = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send` error: future cannot be sent between threads safely - --> $DIR/future_not_send.rs:20:63 + --> $DIR/future_not_send.rs:19:63 | LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool { | ^^^^ future returned by `private_future2` is not `Send` | note: captured value is not `Send` - --> $DIR/future_not_send.rs:20:26 + --> $DIR/future_not_send.rs:19:26 | LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool { | ^^ has type `std::rc::Rc<[u8]>` which is not `Send` = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send` note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync` - --> $DIR/future_not_send.rs:20:40 + --> $DIR/future_not_send.rs:19:40 | LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool { | ^^^^ has type `&std::cell::Cell<usize>` which is not `Send`, because `std::cell::Cell<usize>` is not `Sync` = note: `std::cell::Cell<usize>` doesn't implement `std::marker::Sync` error: future cannot be sent between threads safely - --> $DIR/future_not_send.rs:24:43 + --> $DIR/future_not_send.rs:23:43 | LL | pub async fn public_future2(rc: Rc<[u8]>) {} | ^ future returned by `public_future2` is not `Send` | note: captured value is not `Send` - --> $DIR/future_not_send.rs:24:29 + --> $DIR/future_not_send.rs:23:29 | LL | pub async fn public_future2(rc: Rc<[u8]>) {} | ^^ has type `std::rc::Rc<[u8]>` which is not `Send` = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send` error: future cannot be sent between threads safely - --> $DIR/future_not_send.rs:35:39 + --> $DIR/future_not_send.rs:34:39 | LL | async fn private_future(&self) -> usize { | ^^^^^ future returned by `private_future` is not `Send` | note: future is not `Send` as this value is used across an await - --> $DIR/future_not_send.rs:36:9 + --> $DIR/future_not_send.rs:35:9 | LL | async fn private_future(&self) -> usize { | ----- has type `&Dummy` which is not `Send` @@ -94,13 +94,13 @@ LL | } = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync` error: future cannot be sent between threads safely - --> $DIR/future_not_send.rs:40:39 + --> $DIR/future_not_send.rs:39:39 | LL | pub async fn public_future(&self) { | ^ future returned by `public_future` is not `Send` | note: future is not `Send` as this value is used across an await - --> $DIR/future_not_send.rs:41:9 + --> $DIR/future_not_send.rs:40:9 | LL | pub async fn public_future(&self) { | ----- has type `&Dummy` which is not `Send` @@ -111,13 +111,13 @@ LL | } = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync` error: future cannot be sent between threads safely - --> $DIR/future_not_send.rs:50:37 + --> $DIR/future_not_send.rs:49:37 | LL | async fn generic_future<T>(t: T) -> T | ^ future returned by `generic_future` is not `Send` | note: future is not `Send` as this value is used across an await - --> $DIR/future_not_send.rs:55:5 + --> $DIR/future_not_send.rs:54:5 | LL | let rt = &t; | -- has type `&T` which is not `Send` @@ -129,13 +129,13 @@ LL | } = note: `T` doesn't implement `std::marker::Sync` error: future cannot be sent between threads safely - --> $DIR/future_not_send.rs:66:34 + --> $DIR/future_not_send.rs:65:34 | LL | async fn unclear_future<T>(t: T) {} | ^ future returned by `unclear_future` is not `Send` | note: captured value is not `Send` - --> $DIR/future_not_send.rs:66:28 + --> $DIR/future_not_send.rs:65:28 | LL | async fn unclear_future<T>(t: T) {} | ^ has type `T` which is not `Send` diff --git a/src/tools/clippy/tests/ui/if_not_else.rs b/src/tools/clippy/tests/ui/if_not_else.rs index dc3fb1ceac..b7012b43d2 100644 --- a/src/tools/clippy/tests/ui/if_not_else.rs +++ b/src/tools/clippy/tests/ui/if_not_else.rs @@ -1,6 +1,9 @@ #![warn(clippy::all)] #![warn(clippy::if_not_else)] +fn foo() -> bool { + unimplemented!() +} fn bla() -> bool { unimplemented!() } @@ -16,4 +19,11 @@ fn main() { } else { println!("Bunny"); } + if !foo() { + println!("Foo"); + } else if !bla() { + println!("Bugs"); + } else { + println!("Bunny"); + } } diff --git a/src/tools/clippy/tests/ui/if_not_else.stderr b/src/tools/clippy/tests/ui/if_not_else.stderr index 53d1b86d02..8c8cc44bb0 100644 --- a/src/tools/clippy/tests/ui/if_not_else.stderr +++ b/src/tools/clippy/tests/ui/if_not_else.stderr @@ -1,5 +1,5 @@ error: unnecessary boolean `not` operation - --> $DIR/if_not_else.rs:9:5 + --> $DIR/if_not_else.rs:12:5 | LL | / if !bla() { LL | | println!("Bugs"); @@ -12,7 +12,7 @@ LL | | } = help: remove the `!` and swap the blocks of the `if`/`else` error: unnecessary `!=` operation - --> $DIR/if_not_else.rs:14:5 + --> $DIR/if_not_else.rs:17:5 | LL | / if 4 != 5 { LL | | println!("Bugs"); diff --git a/src/tools/clippy/tests/ui/implicit_hasher.rs b/src/tools/clippy/tests/ui/implicit_hasher.rs index aa69b09741..fd96ca3f46 100644 --- a/src/tools/clippy/tests/ui/implicit_hasher.rs +++ b/src/tools/clippy/tests/ui/implicit_hasher.rs @@ -1,4 +1,3 @@ -// edition:2018 // aux-build:implicit_hasher_macros.rs #![deny(clippy::implicit_hasher)] #![allow(unused)] diff --git a/src/tools/clippy/tests/ui/implicit_hasher.stderr b/src/tools/clippy/tests/ui/implicit_hasher.stderr index 3f5f56b923..59b0fba2a4 100644 --- a/src/tools/clippy/tests/ui/implicit_hasher.stderr +++ b/src/tools/clippy/tests/ui/implicit_hasher.stderr @@ -1,11 +1,11 @@ error: impl for `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:17:35 + --> $DIR/implicit_hasher.rs:16:35 | LL | impl<K: Hash + Eq, V> Foo<i8> for HashMap<K, V> { | ^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/implicit_hasher.rs:3:9 + --> $DIR/implicit_hasher.rs:2:9 | LL | #![deny(clippy::implicit_hasher)] | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default: | ~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: impl for `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:26:36 + --> $DIR/implicit_hasher.rs:25:36 | LL | impl<K: Hash + Eq, V> Foo<i8> for (HashMap<K, V>,) { | ^^^^^^^^^^^^^ @@ -34,7 +34,7 @@ LL | ((HashMap::default(),), (HashMap::with_capacity_and_hasher(10, Defa | ~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: impl for `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:31:19 + --> $DIR/implicit_hasher.rs:30:19 | LL | impl Foo<i16> for HashMap<String, String> { | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default: | ~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: impl for `HashSet` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:48:32 + --> $DIR/implicit_hasher.rs:47:32 | LL | impl<T: Hash + Eq> Foo<i8> for HashSet<T> { | ^^^^^^^^^^ @@ -64,7 +64,7 @@ LL | (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default: | ~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: impl for `HashSet` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:53:19 + --> $DIR/implicit_hasher.rs:52:19 | LL | impl Foo<i16> for HashSet<String> { | ^^^^^^^^^^^^^^^ @@ -79,7 +79,7 @@ LL | (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default: | ~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: parameter of type `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:70:23 + --> $DIR/implicit_hasher.rs:69:23 | LL | pub fn foo(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {} | ^^^^^^^^^^^^^^^^^ @@ -90,7 +90,7 @@ LL | pub fn foo<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i32, S>, _s | +++++++++++++++++++++++++++++ ~~~~~~~~~~~~~~~~~~~~ error: parameter of type `HashSet` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:70:53 + --> $DIR/implicit_hasher.rs:69:53 | LL | pub fn foo(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {} | ^^^^^^^^^^^^ @@ -101,7 +101,7 @@ LL | pub fn foo<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i32>, _set: | +++++++++++++++++++++++++++++ ~~~~~~~~~~~~~~~ error: impl for `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:74:43 + --> $DIR/implicit_hasher.rs:73:43 | LL | impl<K: Hash + Eq, V> Foo<u8> for HashMap<K, V> { | ^^^^^^^^^^^^^ @@ -120,7 +120,7 @@ LL | (HashMap::default(), HashMap::with_capacity_and_hasher(10, | ~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: parameter of type `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:82:33 + --> $DIR/implicit_hasher.rs:81:33 | LL | pub fn $name(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {} | ^^^^^^^^^^^^^^^^^ @@ -135,7 +135,7 @@ LL | pub fn $name<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i | +++++++++++++++++++++++++++++ ~~~~~~~~~~~~~~~~~~~~ error: parameter of type `HashSet` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:82:63 + --> $DIR/implicit_hasher.rs:81:63 | LL | pub fn $name(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {} | ^^^^^^^^^^^^ @@ -150,7 +150,7 @@ LL | pub fn $name<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i | +++++++++++++++++++++++++++++ ~~~~~~~~~~~~~~~ error: parameter of type `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:101:35 + --> $DIR/implicit_hasher.rs:100:35 | LL | pub async fn election_vote(_data: HashMap<i32, i32>) {} | ^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/implicit_return.fixed b/src/tools/clippy/tests/ui/implicit_return.fixed index 7698b88a88..a51f7bc6a2 100644 --- a/src/tools/clippy/tests/ui/implicit_return.fixed +++ b/src/tools/clippy/tests/ui/implicit_return.fixed @@ -1,4 +1,3 @@ -// edition:2018 // run-rustfix #![warn(clippy::implicit_return)] diff --git a/src/tools/clippy/tests/ui/implicit_return.rs b/src/tools/clippy/tests/ui/implicit_return.rs index 45bbc2ec67..03f8ec49d5 100644 --- a/src/tools/clippy/tests/ui/implicit_return.rs +++ b/src/tools/clippy/tests/ui/implicit_return.rs @@ -1,4 +1,3 @@ -// edition:2018 // run-rustfix #![warn(clippy::implicit_return)] diff --git a/src/tools/clippy/tests/ui/implicit_return.stderr b/src/tools/clippy/tests/ui/implicit_return.stderr index 5e078b15ce..522bc3bf89 100644 --- a/src/tools/clippy/tests/ui/implicit_return.stderr +++ b/src/tools/clippy/tests/ui/implicit_return.stderr @@ -1,5 +1,5 @@ error: missing `return` statement - --> $DIR/implicit_return.rs:13:5 + --> $DIR/implicit_return.rs:12:5 | LL | true | ^^^^ help: add `return` as shown: `return true` @@ -7,85 +7,85 @@ LL | true = note: `-D clippy::implicit-return` implied by `-D warnings` error: missing `return` statement - --> $DIR/implicit_return.rs:17:15 + --> $DIR/implicit_return.rs:16:15 | LL | if true { true } else { false } | ^^^^ help: add `return` as shown: `return true` error: missing `return` statement - --> $DIR/implicit_return.rs:17:29 + --> $DIR/implicit_return.rs:16:29 | LL | if true { true } else { false } | ^^^^^ help: add `return` as shown: `return false` error: missing `return` statement - --> $DIR/implicit_return.rs:23:17 + --> $DIR/implicit_return.rs:22:17 | LL | true => false, | ^^^^^ help: add `return` as shown: `return false` error: missing `return` statement - --> $DIR/implicit_return.rs:24:20 + --> $DIR/implicit_return.rs:23:20 | LL | false => { true }, | ^^^^ help: add `return` as shown: `return true` error: missing `return` statement - --> $DIR/implicit_return.rs:37:9 + --> $DIR/implicit_return.rs:36:9 | LL | break true; | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing `return` statement - --> $DIR/implicit_return.rs:44:13 + --> $DIR/implicit_return.rs:43:13 | LL | break true; | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing `return` statement - --> $DIR/implicit_return.rs:52:13 + --> $DIR/implicit_return.rs:51:13 | LL | break true; | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing `return` statement - --> $DIR/implicit_return.rs:70:18 + --> $DIR/implicit_return.rs:69:18 | LL | let _ = || { true }; | ^^^^ help: add `return` as shown: `return true` error: missing `return` statement - --> $DIR/implicit_return.rs:71:16 + --> $DIR/implicit_return.rs:70:16 | LL | let _ = || true; | ^^^^ help: add `return` as shown: `return true` error: missing `return` statement - --> $DIR/implicit_return.rs:79:5 + --> $DIR/implicit_return.rs:78:5 | LL | format!("test {}", "test") | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `return` as shown: `return format!("test {}", "test")` error: missing `return` statement - --> $DIR/implicit_return.rs:88:5 + --> $DIR/implicit_return.rs:87:5 | LL | m!(true, false) | ^^^^^^^^^^^^^^^ help: add `return` as shown: `return m!(true, false)` error: missing `return` statement - --> $DIR/implicit_return.rs:94:13 + --> $DIR/implicit_return.rs:93:13 | LL | break true; | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing `return` statement - --> $DIR/implicit_return.rs:99:17 + --> $DIR/implicit_return.rs:98:17 | LL | break 'outer false; | ^^^^^^^^^^^^^^^^^^ help: change `break` to `return` as shown: `return false` error: missing `return` statement - --> $DIR/implicit_return.rs:114:5 + --> $DIR/implicit_return.rs:113:5 | LL | / loop { LL | | m!(true); @@ -100,7 +100,7 @@ LL + } | error: missing `return` statement - --> $DIR/implicit_return.rs:128:5 + --> $DIR/implicit_return.rs:127:5 | LL | true | ^^^^ help: add `return` as shown: `return true` diff --git a/src/tools/clippy/tests/ui/implicit_saturating_sub.fixed b/src/tools/clippy/tests/ui/implicit_saturating_sub.fixed index 859765d08a..e6f57e9267 100644 --- a/src/tools/clippy/tests/ui/implicit_saturating_sub.fixed +++ b/src/tools/clippy/tests/ui/implicit_saturating_sub.fixed @@ -157,4 +157,12 @@ fn main() { if i_64 != 0 { i_64 -= 1; } + + // issue #7831 + // No Lint + if u_32 > 0 { + u_32 -= 1; + } else { + println!("side effect"); + } } diff --git a/src/tools/clippy/tests/ui/implicit_saturating_sub.rs b/src/tools/clippy/tests/ui/implicit_saturating_sub.rs index 2f32a7b157..8bb28d149c 100644 --- a/src/tools/clippy/tests/ui/implicit_saturating_sub.rs +++ b/src/tools/clippy/tests/ui/implicit_saturating_sub.rs @@ -203,4 +203,12 @@ fn main() { if i_64 != 0 { i_64 -= 1; } + + // issue #7831 + // No Lint + if u_32 > 0 { + u_32 -= 1; + } else { + println!("side effect"); + } } diff --git a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed index d102574379..eb66d1afdd 100644 --- a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed +++ b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed @@ -1,5 +1,4 @@ // run-rustfix -// edition:2018 #![warn(clippy::inconsistent_struct_constructor)] #![allow(clippy::redundant_field_names)] #![allow(clippy::unnecessary_operation)] diff --git a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs index b095aa64a2..5caadc7c62 100644 --- a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs +++ b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs @@ -1,5 +1,4 @@ // run-rustfix -// edition:2018 #![warn(clippy::inconsistent_struct_constructor)] #![allow(clippy::redundant_field_names)] #![allow(clippy::unnecessary_operation)] diff --git a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.stderr b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.stderr index ef308dedb1..c90189e964 100644 --- a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.stderr +++ b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.stderr @@ -1,5 +1,5 @@ error: struct constructor field order is inconsistent with struct definition field order - --> $DIR/inconsistent_struct_constructor.rs:34:9 + --> $DIR/inconsistent_struct_constructor.rs:33:9 | LL | Foo { y, x, z }; | ^^^^^^^^^^^^^^^ help: try: `Foo { x, y, z }` @@ -7,7 +7,7 @@ LL | Foo { y, x, z }; = note: `-D clippy::inconsistent-struct-constructor` implied by `-D warnings` error: struct constructor field order is inconsistent with struct definition field order - --> $DIR/inconsistent_struct_constructor.rs:56:9 + --> $DIR/inconsistent_struct_constructor.rs:55:9 | LL | / Foo { LL | | z, diff --git a/src/tools/clippy/tests/ui/issue-7447.stderr b/src/tools/clippy/tests/ui/issue-7447.stderr new file mode 100644 index 0000000000..463a48b24a --- /dev/null +++ b/src/tools/clippy/tests/ui/issue-7447.stderr @@ -0,0 +1,19 @@ +error: sub-expression diverges + --> $DIR/issue-7447.rs:23:15 + | +LL | byte_view(panic!()); + | ^^^^^^^^ + | + = note: `-D clippy::diverging-sub-expression` implied by `-D warnings` + = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: sub-expression diverges + --> $DIR/issue-7447.rs:24:19 + | +LL | group_entries(panic!()); + | ^^^^^^^^ + | + = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + diff --git a/src/tools/clippy/tests/ui/issue_4266.rs b/src/tools/clippy/tests/ui/issue_4266.rs index cc699b79e4..d9d48189bd 100644 --- a/src/tools/clippy/tests/ui/issue_4266.rs +++ b/src/tools/clippy/tests/ui/issue_4266.rs @@ -1,4 +1,3 @@ -// edition:2018 #![allow(dead_code)] async fn sink1<'a>(_: &'a str) {} // lint diff --git a/src/tools/clippy/tests/ui/issue_4266.stderr b/src/tools/clippy/tests/ui/issue_4266.stderr index 0426508e62..20419457b4 100644 --- a/src/tools/clippy/tests/ui/issue_4266.stderr +++ b/src/tools/clippy/tests/ui/issue_4266.stderr @@ -1,5 +1,5 @@ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/issue_4266.rs:4:1 + --> $DIR/issue_4266.rs:3:1 | LL | async fn sink1<'a>(_: &'a str) {} // lint | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | async fn sink1<'a>(_: &'a str) {} // lint = note: `-D clippy::needless-lifetimes` implied by `-D warnings` error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/issue_4266.rs:8:1 + --> $DIR/issue_4266.rs:7:1 | LL | async fn one_to_one<'a>(s: &'a str) -> &'a str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/iter_count.fixed b/src/tools/clippy/tests/ui/iter_count.fixed index 97c5929783..90a6eef752 100644 --- a/src/tools/clippy/tests/ui/iter_count.fixed +++ b/src/tools/clippy/tests/ui/iter_count.fixed @@ -33,6 +33,7 @@ impl HasIter { } } +#[allow(unused_must_use)] fn main() { let mut vec = vec![0, 1, 2, 3]; let mut boxed_slice: Box<[u8]> = Box::new([0, 1, 2, 3]); @@ -50,7 +51,7 @@ fn main() { linked_list.push_back(1); binary_heap.push(1); - let _ = &vec[..].len(); + &vec[..].len(); vec.len(); boxed_slice.len(); vec_deque.len(); @@ -62,13 +63,13 @@ fn main() { binary_heap.len(); vec.len(); - let _ = &vec[..].len(); + &vec[..].len(); vec_deque.len(); hash_map.len(); b_tree_map.len(); linked_list.len(); - let _ = &vec[..].len(); + &vec[..].len(); vec.len(); vec_deque.len(); hash_set.len(); diff --git a/src/tools/clippy/tests/ui/iter_count.rs b/src/tools/clippy/tests/ui/iter_count.rs index 70bb734763..6681a480a2 100644 --- a/src/tools/clippy/tests/ui/iter_count.rs +++ b/src/tools/clippy/tests/ui/iter_count.rs @@ -33,6 +33,7 @@ impl HasIter { } } +#[allow(unused_must_use)] fn main() { let mut vec = vec![0, 1, 2, 3]; let mut boxed_slice: Box<[u8]> = Box::new([0, 1, 2, 3]); @@ -50,7 +51,7 @@ fn main() { linked_list.push_back(1); binary_heap.push(1); - let _ = &vec[..].iter().count(); + &vec[..].iter().count(); vec.iter().count(); boxed_slice.iter().count(); vec_deque.iter().count(); @@ -62,13 +63,13 @@ fn main() { binary_heap.iter().count(); vec.iter_mut().count(); - let _ = &vec[..].iter_mut().count(); + &vec[..].iter_mut().count(); vec_deque.iter_mut().count(); hash_map.iter_mut().count(); b_tree_map.iter_mut().count(); linked_list.iter_mut().count(); - let _ = &vec[..].into_iter().count(); + &vec[..].into_iter().count(); vec.into_iter().count(); vec_deque.into_iter().count(); hash_set.into_iter().count(); diff --git a/src/tools/clippy/tests/ui/iter_count.stderr b/src/tools/clippy/tests/ui/iter_count.stderr index 1d2c22f9df..2e3d7fc35d 100644 --- a/src/tools/clippy/tests/ui/iter_count.stderr +++ b/src/tools/clippy/tests/ui/iter_count.stderr @@ -1,151 +1,151 @@ error: called `.iter().count()` on a `slice` - --> $DIR/iter_count.rs:53:14 + --> $DIR/iter_count.rs:54:6 | -LL | let _ = &vec[..].iter().count(); - | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()` +LL | &vec[..].iter().count(); + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()` | = note: `-D clippy::iter-count` implied by `-D warnings` error: called `.iter().count()` on a `Vec` - --> $DIR/iter_count.rs:54:5 + --> $DIR/iter_count.rs:55:5 | LL | vec.iter().count(); | ^^^^^^^^^^^^^^^^^^ help: try: `vec.len()` error: called `.iter().count()` on a `slice` - --> $DIR/iter_count.rs:55:5 + --> $DIR/iter_count.rs:56:5 | LL | boxed_slice.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `boxed_slice.len()` error: called `.iter().count()` on a `VecDeque` - --> $DIR/iter_count.rs:56:5 + --> $DIR/iter_count.rs:57:5 | LL | vec_deque.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec_deque.len()` error: called `.iter().count()` on a `HashSet` - --> $DIR/iter_count.rs:57:5 + --> $DIR/iter_count.rs:58:5 | LL | hash_set.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_set.len()` error: called `.iter().count()` on a `HashMap` - --> $DIR/iter_count.rs:58:5 + --> $DIR/iter_count.rs:59:5 | LL | hash_map.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_map.len()` error: called `.iter().count()` on a `BTreeMap` - --> $DIR/iter_count.rs:59:5 + --> $DIR/iter_count.rs:60:5 | LL | b_tree_map.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b_tree_map.len()` error: called `.iter().count()` on a `BTreeSet` - --> $DIR/iter_count.rs:60:5 + --> $DIR/iter_count.rs:61:5 | LL | b_tree_set.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b_tree_set.len()` error: called `.iter().count()` on a `LinkedList` - --> $DIR/iter_count.rs:61:5 + --> $DIR/iter_count.rs:62:5 | LL | linked_list.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `linked_list.len()` error: called `.iter().count()` on a `BinaryHeap` - --> $DIR/iter_count.rs:62:5 + --> $DIR/iter_count.rs:63:5 | LL | binary_heap.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `binary_heap.len()` error: called `.iter_mut().count()` on a `Vec` - --> $DIR/iter_count.rs:64:5 + --> $DIR/iter_count.rs:65:5 | LL | vec.iter_mut().count(); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.len()` error: called `.iter_mut().count()` on a `slice` - --> $DIR/iter_count.rs:65:14 + --> $DIR/iter_count.rs:66:6 | -LL | let _ = &vec[..].iter_mut().count(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()` +LL | &vec[..].iter_mut().count(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()` error: called `.iter_mut().count()` on a `VecDeque` - --> $DIR/iter_count.rs:66:5 + --> $DIR/iter_count.rs:67:5 | LL | vec_deque.iter_mut().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec_deque.len()` error: called `.iter_mut().count()` on a `HashMap` - --> $DIR/iter_count.rs:67:5 + --> $DIR/iter_count.rs:68:5 | LL | hash_map.iter_mut().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_map.len()` error: called `.iter_mut().count()` on a `BTreeMap` - --> $DIR/iter_count.rs:68:5 + --> $DIR/iter_count.rs:69:5 | LL | b_tree_map.iter_mut().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b_tree_map.len()` error: called `.iter_mut().count()` on a `LinkedList` - --> $DIR/iter_count.rs:69:5 + --> $DIR/iter_count.rs:70:5 | LL | linked_list.iter_mut().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `linked_list.len()` error: called `.into_iter().count()` on a `slice` - --> $DIR/iter_count.rs:71:14 + --> $DIR/iter_count.rs:72:6 | -LL | let _ = &vec[..].into_iter().count(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()` +LL | &vec[..].into_iter().count(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()` error: called `.into_iter().count()` on a `Vec` - --> $DIR/iter_count.rs:72:5 + --> $DIR/iter_count.rs:73:5 | LL | vec.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.len()` error: called `.into_iter().count()` on a `VecDeque` - --> $DIR/iter_count.rs:73:5 + --> $DIR/iter_count.rs:74:5 | LL | vec_deque.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec_deque.len()` error: called `.into_iter().count()` on a `HashSet` - --> $DIR/iter_count.rs:74:5 + --> $DIR/iter_count.rs:75:5 | LL | hash_set.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_set.len()` error: called `.into_iter().count()` on a `HashMap` - --> $DIR/iter_count.rs:75:5 + --> $DIR/iter_count.rs:76:5 | LL | hash_map.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_map.len()` error: called `.into_iter().count()` on a `BTreeMap` - --> $DIR/iter_count.rs:76:5 + --> $DIR/iter_count.rs:77:5 | LL | b_tree_map.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b_tree_map.len()` error: called `.into_iter().count()` on a `BTreeSet` - --> $DIR/iter_count.rs:77:5 + --> $DIR/iter_count.rs:78:5 | LL | b_tree_set.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b_tree_set.len()` error: called `.into_iter().count()` on a `LinkedList` - --> $DIR/iter_count.rs:78:5 + --> $DIR/iter_count.rs:79:5 | LL | linked_list.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `linked_list.len()` error: called `.into_iter().count()` on a `BinaryHeap` - --> $DIR/iter_count.rs:79:5 + --> $DIR/iter_count.rs:80:5 | LL | binary_heap.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `binary_heap.len()` 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 b9d66347c2..1e938e72b5 100644 --- a/src/tools/clippy/tests/ui/len_without_is_empty.rs +++ b/src/tools/clippy/tests/ui/len_without_is_empty.rs @@ -1,5 +1,3 @@ -// edition:2018 - #![warn(clippy::len_without_is_empty)] #![allow(dead_code, unused)] 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 3282709bcd..a1f48f7610 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:9:5 + --> $DIR/len_without_is_empty.rs:7: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:57:1 + --> $DIR/len_without_is_empty.rs:55:1 | LL | / pub trait PubTraitsToo { LL | | fn len(&self) -> isize; @@ -15,45 +15,45 @@ LL | | } | |_^ error: struct `HasIsEmpty` has a public `len` method, but a private `is_empty` method - --> $DIR/len_without_is_empty.rs:70:5 + --> $DIR/len_without_is_empty.rs:68:5 | LL | pub fn len(&self) -> isize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `is_empty` defined here - --> $DIR/len_without_is_empty.rs:74:5 + --> $DIR/len_without_is_empty.rs:72: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:82:5 + --> $DIR/len_without_is_empty.rs:80:5 | LL | pub fn len(&self) -> isize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `is_empty` defined here - --> $DIR/len_without_is_empty.rs:86:5 + --> $DIR/len_without_is_empty.rs:84: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:94:5 + --> $DIR/len_without_is_empty.rs:92:5 | LL | pub fn len(self) -> isize { | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `is_empty` defined here - --> $DIR/len_without_is_empty.rs:98:5 + --> $DIR/len_without_is_empty.rs:96: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:173:1 + --> $DIR/len_without_is_empty.rs:171:1 | LL | / pub trait DependsOnFoo: Foo { LL | | fn len(&mut self) -> usize; @@ -61,33 +61,33 @@ LL | | } | |_^ 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 + --> $DIR/len_without_is_empty.rs:216:5 | LL | pub fn len(&self) -> usize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `is_empty` defined here - --> $DIR/len_without_is_empty.rs:223:5 + --> $DIR/len_without_is_empty.rs:221: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 + --> $DIR/len_without_is_empty.rs:228:5 | LL | pub fn len(&self) -> Result<usize, ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `is_empty` defined here - --> $DIR/len_without_is_empty.rs:235:5 + --> $DIR/len_without_is_empty.rs:233: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 + --> $DIR/len_without_is_empty.rs:228:5 | LL | pub fn len(&self) -> Result<usize, ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -96,7 +96,7 @@ 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:242:5 + --> $DIR/len_without_is_empty.rs:240:5 | LL | pub fn len(&self) -> Result<usize, ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -104,7 +104,7 @@ 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 + --> $DIR/len_without_is_empty.rs:244:5 | LL | pub fn is_empty(&self) -> Result<bool, ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -112,7 +112,7 @@ 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 + --> $DIR/len_without_is_empty.rs:251:5 | LL | pub fn len(&self) -> Result<usize, ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/literals.rs b/src/tools/clippy/tests/ui/literals.rs index a72a74b913..0cadd5a3da 100644 --- a/src/tools/clippy/tests/ui/literals.rs +++ b/src/tools/clippy/tests/ui/literals.rs @@ -2,8 +2,9 @@ #![warn(clippy::mixed_case_hex_literals)] #![warn(clippy::zero_prefixed_literal)] -#![allow(clippy::unseparated_literal_suffix)] -#![allow(dead_code)] +#![warn(clippy::unseparated_literal_suffix)] +#![warn(clippy::separated_literal_suffix)] +#![allow(dead_code, overflowing_literals)] fn main() { let ok1 = 0xABCD; diff --git a/src/tools/clippy/tests/ui/literals.stderr b/src/tools/clippy/tests/ui/literals.stderr index 99542e20f7..365b240747 100644 --- a/src/tools/clippy/tests/ui/literals.stderr +++ b/src/tools/clippy/tests/ui/literals.stderr @@ -1,25 +1,65 @@ +error: integer type suffix should not be separated by an underscore + --> $DIR/literals.rs:12:15 + | +LL | let ok4 = 0xab_cd_i32; + | ^^^^^^^^^^^ help: remove the underscore: `0xab_cdi32` + | + = note: `-D clippy::separated-literal-suffix` implied by `-D warnings` + +error: integer type suffix should not be separated by an underscore + --> $DIR/literals.rs:13:15 + | +LL | let ok5 = 0xAB_CD_u32; + | ^^^^^^^^^^^ help: remove the underscore: `0xAB_CDu32` + +error: integer type suffix should not be separated by an underscore + --> $DIR/literals.rs:14:15 + | +LL | let ok5 = 0xAB_CD_isize; + | ^^^^^^^^^^^^^ help: remove the underscore: `0xAB_CDisize` + error: inconsistent casing in hexadecimal literal - --> $DIR/literals.rs:14:17 + --> $DIR/literals.rs:15:17 | LL | let fail1 = 0xabCD; | ^^^^^^ | = note: `-D clippy::mixed-case-hex-literals` implied by `-D warnings` +error: integer type suffix should not be separated by an underscore + --> $DIR/literals.rs:16:17 + | +LL | let fail2 = 0xabCD_u32; + | ^^^^^^^^^^ help: remove the underscore: `0xabCDu32` + error: inconsistent casing in hexadecimal literal - --> $DIR/literals.rs:15:17 + --> $DIR/literals.rs:16:17 | LL | let fail2 = 0xabCD_u32; | ^^^^^^^^^^ +error: integer type suffix should not be separated by an underscore + --> $DIR/literals.rs:17:17 + | +LL | let fail2 = 0xabCD_isize; + | ^^^^^^^^^^^^ help: remove the underscore: `0xabCDisize` + error: inconsistent casing in hexadecimal literal - --> $DIR/literals.rs:16:17 + --> $DIR/literals.rs:17:17 | LL | let fail2 = 0xabCD_isize; | ^^^^^^^^^^^^ +error: integer type suffix should be separated by an underscore + --> $DIR/literals.rs:18:27 + | +LL | let fail_multi_zero = 000_123usize; + | ^^^^^^^^^^^^ help: add an underscore: `000_123_usize` + | + = note: `-D clippy::unseparated-literal-suffix` implied by `-D warnings` + error: this is a decimal constant - --> $DIR/literals.rs:17:27 + --> $DIR/literals.rs:18:27 | LL | let fail_multi_zero = 000_123usize; | ^^^^^^^^^^^^ @@ -34,8 +74,14 @@ help: if you mean to use an octal constant, use `0o` LL | let fail_multi_zero = 0o123usize; | ~~~~~~~~~~ +error: integer type suffix should not be separated by an underscore + --> $DIR/literals.rs:21:16 + | +LL | let ok10 = 0_i64; + | ^^^^^ help: remove the underscore: `0i64` + error: this is a decimal constant - --> $DIR/literals.rs:21:17 + --> $DIR/literals.rs:22:17 | LL | let fail8 = 0123; | ^^^^ @@ -49,8 +95,14 @@ help: if you mean to use an octal constant, use `0o` LL | let fail8 = 0o123; | ~~~~~ +error: integer type suffix should not be separated by an underscore + --> $DIR/literals.rs:31:16 + | +LL | let ok17 = 0x123_4567_8901_usize; + | ^^^^^^^^^^^^^^^^^^^^^ help: remove the underscore: `0x123_4567_8901usize` + error: digits grouped inconsistently by underscores - --> $DIR/literals.rs:33:18 + --> $DIR/literals.rs:34:18 | LL | let fail19 = 12_3456_21; | ^^^^^^^^^^ help: consider: `12_345_621` @@ -58,19 +110,19 @@ LL | let fail19 = 12_3456_21; = note: `-D clippy::inconsistent-digit-grouping` implied by `-D warnings` error: digits grouped inconsistently by underscores - --> $DIR/literals.rs:34:18 + --> $DIR/literals.rs:35:18 | LL | let fail22 = 3__4___23; | ^^^^^^^^^ help: consider: `3_423` error: digits grouped inconsistently by underscores - --> $DIR/literals.rs:35:18 + --> $DIR/literals.rs:36:18 | LL | let fail23 = 3__16___23; | ^^^^^^^^^^ help: consider: `31_623` error: digits of hex or binary literal not grouped by four - --> $DIR/literals.rs:37:18 + --> $DIR/literals.rs:38:18 | LL | let fail24 = 0xAB_ABC_AB; | ^^^^^^^^^^^ help: consider: `0x0ABA_BCAB` @@ -78,10 +130,10 @@ LL | let fail24 = 0xAB_ABC_AB; = note: `-D clippy::unusual-byte-groupings` implied by `-D warnings` error: digits of hex or binary literal not grouped by four - --> $DIR/literals.rs:38:18 + --> $DIR/literals.rs:39:18 | LL | let fail25 = 0b01_100_101; | ^^^^^^^^^^^^ help: consider: `0b0110_0101` -error: aborting due to 10 previous errors +error: aborting due to 18 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 70d49d9f2c..9171558f3a 100644 --- a/src/tools/clippy/tests/ui/macro_use_imports.fixed +++ b/src/tools/clippy/tests/ui/macro_use_imports.fixed @@ -1,4 +1,3 @@ -// compile-flags: --edition 2018 // aux-build:macro_rules.rs // aux-build:macro_use_helper.rs // aux-build:proc_macro_derive.rs diff --git a/src/tools/clippy/tests/ui/macro_use_imports.rs b/src/tools/clippy/tests/ui/macro_use_imports.rs index 6837002386..cd01fd43f6 100644 --- a/src/tools/clippy/tests/ui/macro_use_imports.rs +++ b/src/tools/clippy/tests/ui/macro_use_imports.rs @@ -1,4 +1,3 @@ -// compile-flags: --edition 2018 // aux-build:macro_rules.rs // aux-build:macro_use_helper.rs // aux-build:proc_macro_derive.rs diff --git a/src/tools/clippy/tests/ui/macro_use_imports.stderr b/src/tools/clippy/tests/ui/macro_use_imports.stderr index 49314b7506..f8c86c8d91 100644 --- a/src/tools/clippy/tests/ui/macro_use_imports.stderr +++ b/src/tools/clippy/tests/ui/macro_use_imports.stderr @@ -1,5 +1,5 @@ error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:19:5 + --> $DIR/macro_use_imports.rs:18:5 | LL | #[macro_use] | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{pub_macro, inner_mod_macro, function_macro, ty_macro, pub_in_private_macro};` @@ -7,22 +7,22 @@ LL | #[macro_use] = note: `-D clippy::macro-use-imports` implied by `-D warnings` error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:25:5 + --> $DIR/macro_use_imports.rs:20:5 | LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;` + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest;` error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:21:5 + --> $DIR/macro_use_imports.rs:22:5 | LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest;` + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::foofoo, inner::try_err};` error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:23:5 + --> $DIR/macro_use_imports.rs:24:5 | LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::foofoo, inner::try_err};` + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;` error: aborting due to 4 previous errors diff --git a/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed b/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed new file mode 100644 index 0000000000..11fe06c572 --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed @@ -0,0 +1,43 @@ +// revisions: edition2018 edition2021 +// [edition2018] edition:2018 +// [edition2021] edition:2021 +// run-rustfix +#![warn(clippy::manual_assert)] + +fn main() { + let a = vec![1, 2, 3]; + let c = Some(2); + if !a.is_empty() + && a.len() == 3 + && c != None + && !a.is_empty() + && a.len() == 3 + && !a.is_empty() + && a.len() == 3 + && !a.is_empty() + && a.len() == 3 + { + panic!("qaqaq{:?}", a); + } + assert!(a.is_empty(), "qaqaq{:?}", a); + assert!(a.is_empty(), "qwqwq"); + if a.len() == 3 { + println!("qwq"); + println!("qwq"); + println!("qwq"); + } + if let Some(b) = c { + panic!("orz {}", b); + } + if a.len() == 3 { + panic!("qaqaq"); + } else { + println!("qwq"); + } + let b = vec![1, 2, 3]; + assert!(!b.is_empty(), "panic1"); + assert!(!(b.is_empty() && a.is_empty()), "panic2"); + assert!(!(a.is_empty() && !b.is_empty()), "panic3"); + assert!(!(b.is_empty() || a.is_empty()), "panic4"); + assert!(!(a.is_empty() || !b.is_empty()), "panic5"); +} diff --git a/src/tools/clippy/tests/ui/manual_assert.stderr b/src/tools/clippy/tests/ui/manual_assert.edition2018.stderr similarity index 96% rename from src/tools/clippy/tests/ui/manual_assert.stderr rename to src/tools/clippy/tests/ui/manual_assert.edition2018.stderr index ab2786247b..03c03472f9 100644 --- a/src/tools/clippy/tests/ui/manual_assert.stderr +++ b/src/tools/clippy/tests/ui/manual_assert.edition2018.stderr @@ -1,5 +1,5 @@ error: only a `panic!` in `if`-then statement - --> $DIR/manual_assert.rs:19:5 + --> $DIR/manual_assert.rs:22:5 | LL | / if !a.is_empty() { LL | | panic!("qaqaq{:?}", a); @@ -9,7 +9,7 @@ LL | | } = note: `-D clippy::manual-assert` implied by `-D warnings` error: only a `panic!` in `if`-then statement - --> $DIR/manual_assert.rs:22:5 + --> $DIR/manual_assert.rs:25:5 | LL | / if !a.is_empty() { LL | | panic!("qwqwq"); @@ -17,7 +17,7 @@ LL | | } | |_____^ help: try: `assert!(a.is_empty(), "qwqwq");` error: only a `panic!` in `if`-then statement - --> $DIR/manual_assert.rs:39:5 + --> $DIR/manual_assert.rs:42:5 | LL | / if b.is_empty() { LL | | panic!("panic1"); @@ -25,7 +25,7 @@ LL | | } | |_____^ help: try: `assert!(!b.is_empty(), "panic1");` error: only a `panic!` in `if`-then statement - --> $DIR/manual_assert.rs:42:5 + --> $DIR/manual_assert.rs:45:5 | LL | / if b.is_empty() && a.is_empty() { LL | | panic!("panic2"); @@ -33,7 +33,7 @@ LL | | } | |_____^ help: try: `assert!(!(b.is_empty() && a.is_empty()), "panic2");` error: only a `panic!` in `if`-then statement - --> $DIR/manual_assert.rs:45:5 + --> $DIR/manual_assert.rs:48:5 | LL | / if a.is_empty() && !b.is_empty() { LL | | panic!("panic3"); @@ -41,7 +41,7 @@ LL | | } | |_____^ help: try: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");` error: only a `panic!` in `if`-then statement - --> $DIR/manual_assert.rs:48:5 + --> $DIR/manual_assert.rs:51:5 | LL | / if b.is_empty() || a.is_empty() { LL | | panic!("panic4"); @@ -49,7 +49,7 @@ LL | | } | |_____^ help: try: `assert!(!(b.is_empty() || a.is_empty()), "panic4");` error: only a `panic!` in `if`-then statement - --> $DIR/manual_assert.rs:51:5 + --> $DIR/manual_assert.rs:54:5 | LL | / if a.is_empty() || !b.is_empty() { LL | | panic!("panic5"); diff --git a/src/tools/clippy/tests/ui/manual_assert.edition2021.fixed b/src/tools/clippy/tests/ui/manual_assert.edition2021.fixed new file mode 100644 index 0000000000..11fe06c572 --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_assert.edition2021.fixed @@ -0,0 +1,43 @@ +// revisions: edition2018 edition2021 +// [edition2018] edition:2018 +// [edition2021] edition:2021 +// run-rustfix +#![warn(clippy::manual_assert)] + +fn main() { + let a = vec![1, 2, 3]; + let c = Some(2); + if !a.is_empty() + && a.len() == 3 + && c != None + && !a.is_empty() + && a.len() == 3 + && !a.is_empty() + && a.len() == 3 + && !a.is_empty() + && a.len() == 3 + { + panic!("qaqaq{:?}", a); + } + assert!(a.is_empty(), "qaqaq{:?}", a); + assert!(a.is_empty(), "qwqwq"); + if a.len() == 3 { + println!("qwq"); + println!("qwq"); + println!("qwq"); + } + if let Some(b) = c { + panic!("orz {}", b); + } + if a.len() == 3 { + panic!("qaqaq"); + } else { + println!("qwq"); + } + let b = vec![1, 2, 3]; + assert!(!b.is_empty(), "panic1"); + assert!(!(b.is_empty() && a.is_empty()), "panic2"); + assert!(!(a.is_empty() && !b.is_empty()), "panic3"); + assert!(!(b.is_empty() || a.is_empty()), "panic4"); + assert!(!(a.is_empty() || !b.is_empty()), "panic5"); +} diff --git a/src/tools/clippy/tests/ui/manual_assert.edition2021.stderr b/src/tools/clippy/tests/ui/manual_assert.edition2021.stderr new file mode 100644 index 0000000000..03c03472f9 --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_assert.edition2021.stderr @@ -0,0 +1,60 @@ +error: only a `panic!` in `if`-then statement + --> $DIR/manual_assert.rs:22:5 + | +LL | / if !a.is_empty() { +LL | | panic!("qaqaq{:?}", a); +LL | | } + | |_____^ help: try: `assert!(a.is_empty(), "qaqaq{:?}", a);` + | + = note: `-D clippy::manual-assert` implied by `-D warnings` + +error: only a `panic!` in `if`-then statement + --> $DIR/manual_assert.rs:25:5 + | +LL | / if !a.is_empty() { +LL | | panic!("qwqwq"); +LL | | } + | |_____^ help: try: `assert!(a.is_empty(), "qwqwq");` + +error: only a `panic!` in `if`-then statement + --> $DIR/manual_assert.rs:42:5 + | +LL | / if b.is_empty() { +LL | | panic!("panic1"); +LL | | } + | |_____^ help: try: `assert!(!b.is_empty(), "panic1");` + +error: only a `panic!` in `if`-then statement + --> $DIR/manual_assert.rs:45:5 + | +LL | / if b.is_empty() && a.is_empty() { +LL | | panic!("panic2"); +LL | | } + | |_____^ help: try: `assert!(!(b.is_empty() && a.is_empty()), "panic2");` + +error: only a `panic!` in `if`-then statement + --> $DIR/manual_assert.rs:48:5 + | +LL | / if a.is_empty() && !b.is_empty() { +LL | | panic!("panic3"); +LL | | } + | |_____^ help: try: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");` + +error: only a `panic!` in `if`-then statement + --> $DIR/manual_assert.rs:51:5 + | +LL | / if b.is_empty() || a.is_empty() { +LL | | panic!("panic4"); +LL | | } + | |_____^ help: try: `assert!(!(b.is_empty() || a.is_empty()), "panic4");` + +error: only a `panic!` in `if`-then statement + --> $DIR/manual_assert.rs:54:5 + | +LL | / if a.is_empty() || !b.is_empty() { +LL | | panic!("panic5"); +LL | | } + | |_____^ help: try: `assert!(!(a.is_empty() || !b.is_empty()), "panic5");` + +error: aborting due to 7 previous errors + diff --git a/src/tools/clippy/tests/ui/manual_assert.fixed b/src/tools/clippy/tests/ui/manual_assert.fixed index 9d461cff68..11fe06c572 100644 --- a/src/tools/clippy/tests/ui/manual_assert.fixed +++ b/src/tools/clippy/tests/ui/manual_assert.fixed @@ -1,3 +1,6 @@ +// revisions: edition2018 edition2021 +// [edition2018] edition:2018 +// [edition2021] edition:2021 // run-rustfix #![warn(clippy::manual_assert)] diff --git a/src/tools/clippy/tests/ui/manual_assert.rs b/src/tools/clippy/tests/ui/manual_assert.rs index 6aadff887c..8713426fc8 100644 --- a/src/tools/clippy/tests/ui/manual_assert.rs +++ b/src/tools/clippy/tests/ui/manual_assert.rs @@ -1,3 +1,6 @@ +// revisions: edition2018 edition2021 +// [edition2018] edition:2018 +// [edition2021] edition:2021 // run-rustfix #![warn(clippy::manual_assert)] diff --git a/src/tools/clippy/tests/ui/manual_async_fn.fixed b/src/tools/clippy/tests/ui/manual_async_fn.fixed index 5184f6fdb8..136cc96be7 100644 --- a/src/tools/clippy/tests/ui/manual_async_fn.fixed +++ b/src/tools/clippy/tests/ui/manual_async_fn.fixed @@ -1,5 +1,4 @@ // run-rustfix -// edition:2018 #![warn(clippy::manual_async_fn)] #![allow(unused)] diff --git a/src/tools/clippy/tests/ui/manual_async_fn.rs b/src/tools/clippy/tests/ui/manual_async_fn.rs index 68c0e591f0..ddc453ffdb 100644 --- a/src/tools/clippy/tests/ui/manual_async_fn.rs +++ b/src/tools/clippy/tests/ui/manual_async_fn.rs @@ -1,5 +1,4 @@ // run-rustfix -// edition:2018 #![warn(clippy::manual_async_fn)] #![allow(unused)] diff --git a/src/tools/clippy/tests/ui/manual_async_fn.stderr b/src/tools/clippy/tests/ui/manual_async_fn.stderr index 51f1a52b6d..7435f46074 100644 --- a/src/tools/clippy/tests/ui/manual_async_fn.stderr +++ b/src/tools/clippy/tests/ui/manual_async_fn.stderr @@ -1,5 +1,5 @@ error: this function can be simplified using the `async fn` syntax - --> $DIR/manual_async_fn.rs:8:1 + --> $DIR/manual_async_fn.rs:7:1 | LL | fn fut() -> impl Future<Output = i32> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | fn fut() -> impl Future<Output = i32> { 42 } | ~~~~~~ error: this function can be simplified using the `async fn` syntax - --> $DIR/manual_async_fn.rs:13:1 + --> $DIR/manual_async_fn.rs:12:1 | LL | fn fut2() ->impl Future<Output = i32> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -30,7 +30,7 @@ LL | fn fut2() ->impl Future<Output = i32> { 42 } | ~~~~~~ error: this function can be simplified using the `async fn` syntax - --> $DIR/manual_async_fn.rs:18:1 + --> $DIR/manual_async_fn.rs:17:1 | LL | fn fut3()-> impl Future<Output = i32> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -45,7 +45,7 @@ LL | fn fut3()-> impl Future<Output = i32> { 42 } | ~~~~~~ error: this function can be simplified using the `async fn` syntax - --> $DIR/manual_async_fn.rs:22:1 + --> $DIR/manual_async_fn.rs:21:1 | LL | fn empty_fut() -> impl Future<Output = ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -60,7 +60,7 @@ LL | fn empty_fut() -> impl Future<Output = ()> {} | ~~ error: this function can be simplified using the `async fn` syntax - --> $DIR/manual_async_fn.rs:27:1 + --> $DIR/manual_async_fn.rs:26:1 | LL | fn empty_fut2() ->impl Future<Output = ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -75,7 +75,7 @@ LL | fn empty_fut2() ->impl Future<Output = ()> {} | ~~ error: this function can be simplified using the `async fn` syntax - --> $DIR/manual_async_fn.rs:32:1 + --> $DIR/manual_async_fn.rs:31:1 | LL | fn empty_fut3()-> impl Future<Output = ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -90,7 +90,7 @@ LL | fn empty_fut3()-> impl Future<Output = ()> {} | ~~ error: this function can be simplified using the `async fn` syntax - --> $DIR/manual_async_fn.rs:36:1 + --> $DIR/manual_async_fn.rs:35:1 | LL | fn core_fut() -> impl core::future::Future<Output = i32> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -105,7 +105,7 @@ LL | fn core_fut() -> impl core::future::Future<Output = i32> { 42 } | ~~~~~~ error: this function can be simplified using the `async fn` syntax - --> $DIR/manual_async_fn.rs:58:5 + --> $DIR/manual_async_fn.rs:57:5 | LL | fn inh_fut() -> impl Future<Output = i32> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -125,7 +125,7 @@ LL + let c = 21; ... error: this function can be simplified using the `async fn` syntax - --> $DIR/manual_async_fn.rs:93:1 + --> $DIR/manual_async_fn.rs:92:1 | LL | fn elided(_: &i32) -> impl Future<Output = i32> + '_ { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -140,7 +140,7 @@ LL | fn elided(_: &i32) -> impl Future<Output = i32> + '_ { 42 } | ~~~~~~ error: this function can be simplified using the `async fn` syntax - --> $DIR/manual_async_fn.rs:102:1 + --> $DIR/manual_async_fn.rs:101:1 | LL | fn explicit<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future<Output = i32> + 'a + 'b { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/manual_map_option.fixed b/src/tools/clippy/tests/ui/manual_map_option.fixed index 40d01df637..294d79abc0 100644 --- a/src/tools/clippy/tests/ui/manual_map_option.fixed +++ b/src/tools/clippy/tests/ui/manual_map_option.fixed @@ -1,4 +1,3 @@ -// edition:2018 // run-rustfix #![warn(clippy::manual_map)] diff --git a/src/tools/clippy/tests/ui/manual_map_option.rs b/src/tools/clippy/tests/ui/manual_map_option.rs index cfef0c5cc4..d11bf5ecb8 100644 --- a/src/tools/clippy/tests/ui/manual_map_option.rs +++ b/src/tools/clippy/tests/ui/manual_map_option.rs @@ -1,4 +1,3 @@ -// edition:2018 // run-rustfix #![warn(clippy::manual_map)] diff --git a/src/tools/clippy/tests/ui/manual_map_option.stderr b/src/tools/clippy/tests/ui/manual_map_option.stderr index cdc2c0e62a..0036b8151d 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:15:5 + --> $DIR/manual_map_option.rs:14: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:20:5 + --> $DIR/manual_map_option.rs:19: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:25:5 + --> $DIR/manual_map_option.rs:24: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:30:5 + --> $DIR/manual_map_option.rs:29: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:37:5 + --> $DIR/manual_map_option.rs:36: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:42:5 + --> $DIR/manual_map_option.rs:41: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:52:5 + --> $DIR/manual_map_option.rs:51: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:57:5 + --> $DIR/manual_map_option.rs:56: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:62:5 + --> $DIR/manual_map_option.rs:61: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:67:5 + --> $DIR/manual_map_option.rs:66: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:72:5 + --> $DIR/manual_map_option.rs:71: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:85:9 + --> $DIR/manual_map_option.rs:84: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:91:5 + --> $DIR/manual_map_option.rs:90: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:96:5 + --> $DIR/manual_map_option.rs:95: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:101:5 + --> $DIR/manual_map_option.rs:100: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:106:5 + --> $DIR/manual_map_option.rs:105: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:111:5 + --> $DIR/manual_map_option.rs:110: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:169:5 + --> $DIR/manual_map_option.rs:168: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:174:5 + --> $DIR/manual_map_option.rs:173:5 | LL | / match option_env!("") { LL | | Some(x) => Some(String::from(x)), @@ -173,7 +173,7 @@ LL | | }; | |_____^ help: try this: `option_env!("").map(String::from)` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:194:12 + --> $DIR/manual_map_option.rs:193:12 | LL | } else if let Some(x) = Some(0) { | ____________^ @@ -184,7 +184,7 @@ LL | | }; | |_____^ help: try this: `{ Some(0).map(|x| x + 1) }` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:202:12 + --> $DIR/manual_map_option.rs:201:12 | LL | } else if let Some(x) = Some(0) { | ____________^ diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or.fixed b/src/tools/clippy/tests/ui/manual_unwrap_or.fixed index 3717f96274..05d6c56f2a 100644 --- a/src/tools/clippy/tests/ui/manual_unwrap_or.fixed +++ b/src/tools/clippy/tests/ui/manual_unwrap_or.fixed @@ -74,10 +74,10 @@ fn result_unwrap_or() { let a = Ok::<i32, &str>(1); a.unwrap_or(42); - // int case, suggestion must surround Result expr with parenthesis + // int case, suggestion must surround Result expr with parentheses (Ok(1) as Result<i32, &str>).unwrap_or(42); - // method call case, suggestion must not surround Result expr `s.method()` with parenthesis + // method call case, suggestion must not surround Result expr `s.method()` with parentheses struct S {} impl S { fn method(self) -> Option<i32> { diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or.rs b/src/tools/clippy/tests/ui/manual_unwrap_or.rs index 989adde1f5..09f62c69b7 100644 --- a/src/tools/clippy/tests/ui/manual_unwrap_or.rs +++ b/src/tools/clippy/tests/ui/manual_unwrap_or.rs @@ -95,13 +95,13 @@ fn result_unwrap_or() { Err(_) => 42, }; - // int case, suggestion must surround Result expr with parenthesis + // int case, suggestion must surround Result expr with parentheses match Ok(1) as Result<i32, &str> { Ok(i) => i, Err(_) => 42, }; - // method call case, suggestion must not surround Result expr `s.method()` with parenthesis + // method call case, suggestion must not surround Result expr `s.method()` with parentheses struct S {} impl S { fn method(self) -> Option<i32> { diff --git a/src/tools/clippy/tests/ui/many_single_char_names.rs b/src/tools/clippy/tests/ui/many_single_char_names.rs index 6576981911..88fcce6687 100644 --- a/src/tools/clippy/tests/ui/many_single_char_names.rs +++ b/src/tools/clippy/tests/ui/many_single_char_names.rs @@ -1,3 +1,4 @@ +#![allow(clippy::too_many_arguments, clippy::diverging_sub_expression)] #![warn(clippy::many_single_char_names)] fn bla() { diff --git a/src/tools/clippy/tests/ui/many_single_char_names.stderr b/src/tools/clippy/tests/ui/many_single_char_names.stderr index 27e62e641a..ade0f84bc5 100644 --- a/src/tools/clippy/tests/ui/many_single_char_names.stderr +++ b/src/tools/clippy/tests/ui/many_single_char_names.stderr @@ -1,5 +1,5 @@ error: 5 bindings with single-character names in scope - --> $DIR/many_single_char_names.rs:4:9 + --> $DIR/many_single_char_names.rs:5:9 | LL | let a: i32; | ^ @@ -12,7 +12,7 @@ LL | let e: i32; = note: `-D clippy::many-single-char-names` implied by `-D warnings` error: 6 bindings with single-character names in scope - --> $DIR/many_single_char_names.rs:4:9 + --> $DIR/many_single_char_names.rs:5:9 | LL | let a: i32; | ^ @@ -25,7 +25,7 @@ LL | let f: i32; | ^ error: 5 bindings with single-character names in scope - --> $DIR/many_single_char_names.rs:4:9 + --> $DIR/many_single_char_names.rs:5:9 | LL | let a: i32; | ^ @@ -36,13 +36,13 @@ LL | e => panic!(), | ^ error: 8 bindings with single-character names in scope - --> $DIR/many_single_char_names.rs:29:13 + --> $DIR/many_single_char_names.rs:30:13 | LL | fn bindings(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32, g: i32, h: i32) {} | ^ ^ ^ ^ ^ ^ ^ ^ error: 8 bindings with single-character names in scope - --> $DIR/many_single_char_names.rs:32:10 + --> $DIR/many_single_char_names.rs:33:10 | LL | let (a, b, c, d, e, f, g, h): (bool, bool, bool, bool, bool, bool, bool, bool) = unimplemented!(); | ^ ^ ^ ^ ^ ^ ^ ^ diff --git a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr index 366ef36c36..d7cedf9f9f 100644 --- a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr +++ b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr @@ -110,23 +110,6 @@ LL | | _ => false, LL | | }; | |_________^ help: try this: `matches!(&val, &Some(ref _a))` -error: you don't need to add `&` to both the expression and the patterns - --> $DIR/match_expr_like_matches_macro.rs:166:20 - | -LL | let _res = match &val { - | ____________________^ -LL | | &Some(ref _a) => true, -LL | | _ => false, -LL | | }; - | |_________^ - | - = note: `-D clippy::match-ref-pats` implied by `-D warnings` -help: try - | -LL ~ let _res = match val { -LL ~ Some(ref _a) => true, - | - error: match expression looks like `matches!` macro --> $DIR/match_expr_like_matches_macro.rs:178:20 | @@ -137,21 +120,5 @@ LL | | _ => false, LL | | }; | |_________^ help: try this: `matches!(&val, &Some(ref _a))` -error: you don't need to add `&` to both the expression and the patterns - --> $DIR/match_expr_like_matches_macro.rs:178:20 - | -LL | let _res = match &val { - | ____________________^ -LL | | &Some(ref _a) => true, -LL | | _ => false, -LL | | }; - | |_________^ - | -help: try - | -LL ~ let _res = match val { -LL ~ Some(ref _a) => true, - | - -error: aborting due to 14 previous errors +error: aborting due to 12 previous errors diff --git a/src/tools/clippy/tests/ui/match_overlapping_arm.rs b/src/tools/clippy/tests/ui/match_overlapping_arm.rs index 846d665d1d..845986a4ea 100644 --- a/src/tools/clippy/tests/ui/match_overlapping_arm.rs +++ b/src/tools/clippy/tests/ui/match_overlapping_arm.rs @@ -10,98 +10,102 @@ fn overlapping() { const FOO: u64 = 2; match 42 { - 0..=10 => println!("0 ... 10"), - 0..=11 => println!("0 ... 11"), + 0..=10 => println!("0..=10"), + 0..=11 => println!("0..=11"), _ => (), } match 42 { - 0..=5 => println!("0 ... 5"), - 6..=7 => println!("6 ... 7"), - FOO..=11 => println!("0 ... 11"), + 0..=5 => println!("0..=5"), + 6..=7 => println!("6..=7"), + FOO..=11 => println!("FOO..=11"), _ => (), } match 42 { 2 => println!("2"), - 0..=5 => println!("0 ... 5"), + 0..=5 => println!("0..=5"), _ => (), } match 42 { 2 => println!("2"), - 0..=2 => println!("0 ... 2"), + 0..=2 => println!("0..=2"), _ => (), } match 42 { - 0..=10 => println!("0 ... 10"), - 11..=50 => println!("11 ... 50"), + 0..=10 => println!("0..=10"), + 11..=50 => println!("11..=50"), _ => (), } match 42 { 2 => println!("2"), - 0..2 => println!("0 .. 2"), + 0..2 => println!("0..2"), _ => (), } match 42 { - 0..10 => println!("0 .. 10"), - 10..50 => println!("10 .. 50"), + 0..10 => println!("0..10"), + 10..50 => println!("10..50"), _ => (), } match 42 { - 0..11 => println!("0 .. 11"), - 0..=11 => println!("0 ... 11"), + 0..11 => println!("0..11"), + 0..=11 => println!("0..=11"), _ => (), } match 42 { - 5..7 => println!("5 .. 7"), - 0..10 => println!("0 .. 10"), + 5..7 => println!("5..7"), + 0..10 => println!("0..10"), _ => (), } match 42 { - 5..10 => println!("5 .. 10"), - 0..=10 => println!("0 ... 10"), + 5..10 => println!("5..10"), + 0..=10 => println!("0..=10"), _ => (), } match 42 { - 0..14 => println!("0 .. 14"), - 5..10 => println!("5 .. 10"), + 0..14 => println!("0..14"), + 5..10 => println!("5..10"), _ => (), } match 42 { - 5..14 => println!("5 .. 14"), - 0..=10 => println!("0 ... 10"), + 5..14 => println!("5..14"), + 0..=10 => println!("0..=10"), _ => (), } match 42 { - 0..7 => println!("0 .. 7"), - 0..=10 => println!("0 ... 10"), + 0..7 => println!("0..7"), + 0..=10 => println!("0..=10"), _ => (), } - /* - // FIXME(JohnTitor): uncomment this once rustfmt knows half-open patterns match 42 { - 0.. => println!("0 .. 42"), - 3.. => println!("3 .. 42"), + 3.. => println!("3.."), + 0.. => println!("0.."), _ => (), } match 42 { - ..=23 => println!("0 ... 23"), - ..26 => println!("0 .. 26"), + ..=23 => println!("..=23"), + ..26 => println!("..26"), + _ => (), + } + + // Issue #7829 + match 0 { + -1..=1 => (), + -2..=2 => (), _ => (), } - */ if let None = Some(42) { // nothing diff --git a/src/tools/clippy/tests/ui/match_overlapping_arm.stderr b/src/tools/clippy/tests/ui/match_overlapping_arm.stderr index 359fa49f51..c2b3f173c2 100644 --- a/src/tools/clippy/tests/ui/match_overlapping_arm.stderr +++ b/src/tools/clippy/tests/ui/match_overlapping_arm.stderr @@ -1,63 +1,75 @@ error: some ranges overlap --> $DIR/match_overlapping_arm.rs:13:9 | -LL | 0..=10 => println!("0 ... 10"), +LL | 0..=10 => println!("0..=10"), | ^^^^^^ | = note: `-D clippy::match-overlapping-arm` implied by `-D warnings` note: overlaps with this --> $DIR/match_overlapping_arm.rs:14:9 | -LL | 0..=11 => println!("0 ... 11"), +LL | 0..=11 => println!("0..=11"), | ^^^^^^ error: some ranges overlap --> $DIR/match_overlapping_arm.rs:19:9 | -LL | 0..=5 => println!("0 ... 5"), +LL | 0..=5 => println!("0..=5"), | ^^^^^ | note: overlaps with this --> $DIR/match_overlapping_arm.rs:21:9 | -LL | FOO..=11 => println!("0 ... 11"), +LL | FOO..=11 => println!("FOO..=11"), | ^^^^^^^^ error: some ranges overlap --> $DIR/match_overlapping_arm.rs:56:9 | -LL | 0..11 => println!("0 .. 11"), +LL | 0..11 => println!("0..11"), | ^^^^^ | note: overlaps with this --> $DIR/match_overlapping_arm.rs:57:9 | -LL | 0..=11 => println!("0 ... 11"), +LL | 0..=11 => println!("0..=11"), | ^^^^^^ error: some ranges overlap --> $DIR/match_overlapping_arm.rs:81:9 | -LL | 0..=10 => println!("0 ... 10"), +LL | 0..=10 => println!("0..=10"), | ^^^^^^ | note: overlaps with this --> $DIR/match_overlapping_arm.rs:80:9 | -LL | 5..14 => println!("5 .. 14"), +LL | 5..14 => println!("5..14"), | ^^^^^ error: some ranges overlap --> $DIR/match_overlapping_arm.rs:86:9 | -LL | 0..7 => println!("0 .. 7"), +LL | 0..7 => println!("0..7"), | ^^^^ | note: overlaps with this --> $DIR/match_overlapping_arm.rs:87:9 | -LL | 0..=10 => println!("0 ... 10"), +LL | 0..=10 => println!("0..=10"), | ^^^^^^ -error: aborting due to 5 previous errors +error: some ranges overlap + --> $DIR/match_overlapping_arm.rs:98:9 + | +LL | ..=23 => println!("..=23"), + | ^^^^^ + | +note: overlaps with this + --> $DIR/match_overlapping_arm.rs:99:9 + | +LL | ..26 => println!("..26"), + | ^^^^ + +error: aborting due to 6 previous errors diff --git a/src/tools/clippy/tests/ui/match_ref_pats.rs b/src/tools/clippy/tests/ui/match_ref_pats.rs index 6cbb4d32b0..7e3674ab8c 100644 --- a/src/tools/clippy/tests/ui/match_ref_pats.rs +++ b/src/tools/clippy/tests/ui/match_ref_pats.rs @@ -1,5 +1,5 @@ #![warn(clippy::match_ref_pats)] -#![allow(clippy::equatable_if_let)] +#![allow(clippy::equatable_if_let, clippy::enum_variant_names)] fn ref_pats() { { @@ -72,4 +72,46 @@ mod ice_3719 { } } +mod issue_7740 { + macro_rules! foobar_variant( + ($idx:expr) => (FooBar::get($idx).unwrap()) + ); + + enum FooBar { + Foo, + Bar, + FooBar, + BarFoo, + } + + impl FooBar { + fn get(idx: u8) -> Option<&'static Self> { + match idx { + 0 => Some(&FooBar::Foo), + 1 => Some(&FooBar::Bar), + 2 => Some(&FooBar::FooBar), + 3 => Some(&FooBar::BarFoo), + _ => None, + } + } + } + + fn issue_7740() { + // Issue #7740 + match foobar_variant!(0) { + &FooBar::Foo => println!("Foo"), + &FooBar::Bar => println!("Bar"), + &FooBar::FooBar => println!("FooBar"), + _ => println!("Wild"), + } + + // This shouldn't trigger + if let &FooBar::BarFoo = foobar_variant!(3) { + println!("BarFoo"); + } else { + println!("Wild"); + } + } +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/match_ref_pats.stderr b/src/tools/clippy/tests/ui/match_ref_pats.stderr index 072aff445e..901820077e 100644 --- a/src/tools/clippy/tests/ui/match_ref_pats.stderr +++ b/src/tools/clippy/tests/ui/match_ref_pats.stderr @@ -15,21 +15,6 @@ LL ~ Some(v) => println!("{:?}", v), LL ~ None => println!("none"), | -error: you don't need to add `&` to all patterns - --> $DIR/match_ref_pats.rs:18:5 - | -LL | / match tup { -LL | | &(v, 1) => println!("{}", v), -LL | | _ => println!("none"), -LL | | } - | |_____^ - | -help: instead of prefixing all patterns with `&`, you can dereference the expression - | -LL ~ match *tup { -LL ~ (v, 1) => println!("{}", v), - | - error: you don't need to add `&` to both the expression and the patterns --> $DIR/match_ref_pats.rs:24:5 | @@ -54,52 +39,30 @@ LL | if let &None = a { | = 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:36:5 - | -LL | / if let &None = a { -LL | | println!("none"); -LL | | } - | |_____^ - | -help: instead of prefixing all patterns with `&`, you can dereference the expression - | -LL | if let None = *a { - | ~~~~ ~~ - error: redundant pattern matching, consider using `is_none()` --> $DIR/match_ref_pats.rs:41: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:41:5 - | -LL | / if let &None = &b { -LL | | println!("none"); -LL | | } - | |_____^ - | -help: try - | -LL | if let None = b { - | ~~~~ ~ - error: you don't need to add `&` to all patterns - --> $DIR/match_ref_pats.rs:68:9 + --> $DIR/match_ref_pats.rs:101:9 | -LL | / match foo_variant!(0) { -LL | | &Foo::A => println!("A"), +LL | / match foobar_variant!(0) { +LL | | &FooBar::Foo => println!("Foo"), +LL | | &FooBar::Bar => println!("Bar"), +LL | | &FooBar::FooBar => println!("FooBar"), LL | | _ => println!("Wild"), LL | | } | |_________^ | help: instead of prefixing all patterns with `&`, you can dereference the expression | -LL ~ match *foo_variant!(0) { -LL ~ Foo::A => println!("A"), +LL ~ match *foobar_variant!(0) { +LL ~ FooBar::Foo => println!("Foo"), +LL ~ FooBar::Bar => println!("Bar"), +LL ~ FooBar::FooBar => println!("FooBar"), | -error: aborting due to 8 previous errors +error: aborting due to 5 previous errors diff --git a/src/tools/clippy/tests/ui/match_str_case_mismatch.rs b/src/tools/clippy/tests/ui/match_str_case_mismatch.rs new file mode 100644 index 0000000000..ac555c87d8 --- /dev/null +++ b/src/tools/clippy/tests/ui/match_str_case_mismatch.rs @@ -0,0 +1,184 @@ +#![warn(clippy::match_str_case_mismatch)] + +// Valid + +fn as_str_match() { + let var = "BAR"; + + match var.to_ascii_lowercase().as_str() { + "foo" => {}, + "bar" => {}, + _ => {}, + } +} + +fn non_alphabetic() { + let var = "~!@#$%^&*()-_=+FOO"; + + match var.to_ascii_lowercase().as_str() { + "1234567890" => {}, + "~!@#$%^&*()-_=+foo" => {}, + "\n\r\t\x7F" => {}, + _ => {}, + } +} + +fn unicode_cased() { + let var = "ВОДЫ"; + + match var.to_lowercase().as_str() { + "水" => {}, + "νερό" => {}, + "воды" => {}, + "물" => {}, + _ => {}, + } +} + +fn titlecase() { + let var = "BarDz"; + + match var.to_lowercase().as_str() { + "foolj" => {}, + "bardz" => {}, + _ => {}, + } +} + +fn no_case_equivalent() { + let var = "barʁ"; + + match var.to_uppercase().as_str() { + "FOOɕ" => {}, + "BARʁ" => {}, + _ => {}, + } +} + +fn addrof_unary_match() { + let var = "BAR"; + + match &*var.to_ascii_lowercase() { + "foo" => {}, + "bar" => {}, + _ => {}, + } +} + +fn alternating_chain() { + let var = "BAR"; + + match &*var + .to_ascii_lowercase() + .to_uppercase() + .to_lowercase() + .to_ascii_uppercase() + { + "FOO" => {}, + "BAR" => {}, + _ => {}, + } +} + +fn unrelated_method() { + struct Item { + a: String, + } + + impl Item { + #[allow(clippy::wrong_self_convention)] + fn to_lowercase(self) -> String { + self.a + } + } + + let item = Item { a: String::from("BAR") }; + + match &*item.to_lowercase() { + "FOO" => {}, + "BAR" => {}, + _ => {}, + } +} + +// Invalid + +fn as_str_match_mismatch() { + let var = "BAR"; + + match var.to_ascii_lowercase().as_str() { + "foo" => {}, + "Bar" => {}, + _ => {}, + } +} + +fn non_alphabetic_mismatch() { + let var = "~!@#$%^&*()-_=+FOO"; + + match var.to_ascii_lowercase().as_str() { + "1234567890" => {}, + "~!@#$%^&*()-_=+Foo" => {}, + "\n\r\t\x7F" => {}, + _ => {}, + } +} + +fn unicode_cased_mismatch() { + let var = "ВОДЫ"; + + match var.to_lowercase().as_str() { + "水" => {}, + "νερό" => {}, + "Воды" => {}, + "물" => {}, + _ => {}, + } +} + +fn titlecase_mismatch() { + let var = "BarDz"; + + match var.to_lowercase().as_str() { + "foolj" => {}, + "barDz" => {}, + _ => {}, + } +} + +fn no_case_equivalent_mismatch() { + let var = "barʁ"; + + match var.to_uppercase().as_str() { + "FOOɕ" => {}, + "bARʁ" => {}, + _ => {}, + } +} + +fn addrof_unary_match_mismatch() { + let var = "BAR"; + + match &*var.to_ascii_lowercase() { + "foo" => {}, + "Bar" => {}, + _ => {}, + } +} + +fn alternating_chain_mismatch() { + let var = "BAR"; + + match &*var + .to_ascii_lowercase() + .to_uppercase() + .to_lowercase() + .to_ascii_uppercase() + { + "FOO" => {}, + "bAR" => {}, + _ => {}, + } +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/match_str_case_mismatch.stderr b/src/tools/clippy/tests/ui/match_str_case_mismatch.stderr new file mode 100644 index 0000000000..92baa40ef2 --- /dev/null +++ b/src/tools/clippy/tests/ui/match_str_case_mismatch.stderr @@ -0,0 +1,80 @@ +error: this `match` arm has a differing case than its expression + --> $DIR/match_str_case_mismatch.rs:111:9 + | +LL | "Bar" => {}, + | ^^^^^ + | + = note: `-D clippy::match-str-case-mismatch` implied by `-D warnings` +help: consider changing the case of this arm to respect `to_ascii_lowercase` + | +LL | "bar" => {}, + | ~~~~~ + +error: this `match` arm has a differing case than its expression + --> $DIR/match_str_case_mismatch.rs:121:9 + | +LL | "~!@#$%^&*()-_=+Foo" => {}, + | ^^^^^^^^^^^^^^^^^^^^ + | +help: consider changing the case of this arm to respect `to_ascii_lowercase` + | +LL | "~!@#$%^&*()-_=+foo" => {}, + | ~~~~~~~~~~~~~~~~~~~~ + +error: this `match` arm has a differing case than its expression + --> $DIR/match_str_case_mismatch.rs:133:9 + | +LL | "Воды" => {}, + | ^^^^^^ + | +help: consider changing the case of this arm to respect `to_lowercase` + | +LL | "воды" => {}, + | ~~~~~~ + +error: this `match` arm has a differing case than its expression + --> $DIR/match_str_case_mismatch.rs:144:9 + | +LL | "barDz" => {}, + | ^^^^^^ + | +help: consider changing the case of this arm to respect `to_lowercase` + | +LL | "bardz" => {}, + | ~~~~~~ + +error: this `match` arm has a differing case than its expression + --> $DIR/match_str_case_mismatch.rs:154:9 + | +LL | "bARʁ" => {}, + | ^^^^^^ + | +help: consider changing the case of this arm to respect `to_uppercase` + | +LL | "BARʁ" => {}, + | ~~~~~~ + +error: this `match` arm has a differing case than its expression + --> $DIR/match_str_case_mismatch.rs:164:9 + | +LL | "Bar" => {}, + | ^^^^^ + | +help: consider changing the case of this arm to respect `to_ascii_lowercase` + | +LL | "bar" => {}, + | ~~~~~ + +error: this `match` arm has a differing case than its expression + --> $DIR/match_str_case_mismatch.rs:179:9 + | +LL | "bAR" => {}, + | ^^^^^ + | +help: consider changing the case of this arm to respect `to_ascii_uppercase` + | +LL | "BAR" => {}, + | ~~~~~ + +error: aborting due to 7 previous errors + diff --git a/src/tools/clippy/tests/ui/match_wild_err_arm.stderr b/src/tools/clippy/tests/ui/match_wild_err_arm.edition2018.stderr similarity index 86% rename from src/tools/clippy/tests/ui/match_wild_err_arm.stderr rename to src/tools/clippy/tests/ui/match_wild_err_arm.edition2018.stderr index 6a2a02987d..2a4012039b 100644 --- a/src/tools/clippy/tests/ui/match_wild_err_arm.stderr +++ b/src/tools/clippy/tests/ui/match_wild_err_arm.edition2018.stderr @@ -1,5 +1,5 @@ error: `Err(_)` matches all errors - --> $DIR/match_wild_err_arm.rs:11:9 + --> $DIR/match_wild_err_arm.rs:14:9 | LL | Err(_) => panic!("err"), | ^^^^^^ @@ -8,7 +8,7 @@ LL | Err(_) => panic!("err"), = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable error: `Err(_)` matches all errors - --> $DIR/match_wild_err_arm.rs:17:9 + --> $DIR/match_wild_err_arm.rs:20:9 | LL | Err(_) => panic!(), | ^^^^^^ @@ -16,7 +16,7 @@ LL | Err(_) => panic!(), = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable error: `Err(_)` matches all errors - --> $DIR/match_wild_err_arm.rs:23:9 + --> $DIR/match_wild_err_arm.rs:26:9 | LL | Err(_) => { | ^^^^^^ @@ -24,7 +24,7 @@ LL | Err(_) => { = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable error: `Err(_e)` matches all errors - --> $DIR/match_wild_err_arm.rs:31:9 + --> $DIR/match_wild_err_arm.rs:34:9 | LL | Err(_e) => panic!(), | ^^^^^^^ diff --git a/src/tools/clippy/tests/ui/match_wild_err_arm.edition2021.stderr b/src/tools/clippy/tests/ui/match_wild_err_arm.edition2021.stderr new file mode 100644 index 0000000000..2a4012039b --- /dev/null +++ b/src/tools/clippy/tests/ui/match_wild_err_arm.edition2021.stderr @@ -0,0 +1,35 @@ +error: `Err(_)` matches all errors + --> $DIR/match_wild_err_arm.rs:14:9 + | +LL | Err(_) => panic!("err"), + | ^^^^^^ + | + = note: `-D clippy::match-wild-err-arm` implied by `-D warnings` + = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable + +error: `Err(_)` matches all errors + --> $DIR/match_wild_err_arm.rs:20:9 + | +LL | Err(_) => panic!(), + | ^^^^^^ + | + = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable + +error: `Err(_)` matches all errors + --> $DIR/match_wild_err_arm.rs:26:9 + | +LL | Err(_) => { + | ^^^^^^ + | + = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable + +error: `Err(_e)` matches all errors + --> $DIR/match_wild_err_arm.rs:34:9 + | +LL | Err(_e) => panic!(), + | ^^^^^^^ + | + = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable + +error: aborting due to 4 previous errors + diff --git a/src/tools/clippy/tests/ui/match_wild_err_arm.rs b/src/tools/clippy/tests/ui/match_wild_err_arm.rs index 823be65efe..0a86144b95 100644 --- a/src/tools/clippy/tests/ui/match_wild_err_arm.rs +++ b/src/tools/clippy/tests/ui/match_wild_err_arm.rs @@ -1,3 +1,6 @@ +// revisions: edition2018 edition2021 +// [edition2018] edition:2018 +// [edition2021] edition:2021 #![feature(exclusive_range_pattern)] #![allow(clippy::match_same_arms)] #![warn(clippy::match_wild_err_arm)] diff --git a/src/tools/clippy/tests/ui/methods.rs b/src/tools/clippy/tests/ui/methods.rs index c441b35b99..977ce54327 100644 --- a/src/tools/clippy/tests/ui/methods.rs +++ b/src/tools/clippy/tests/ui/methods.rs @@ -1,5 +1,4 @@ // aux-build:option_helpers.rs -// edition:2018 #![warn(clippy::all, clippy::pedantic)] #![allow( diff --git a/src/tools/clippy/tests/ui/methods.stderr b/src/tools/clippy/tests/ui/methods.stderr index 4643e09e27..b63672dd6f 100644 --- a/src/tools/clippy/tests/ui/methods.stderr +++ b/src/tools/clippy/tests/ui/methods.stderr @@ -1,5 +1,5 @@ error: methods called `new` usually return `Self` - --> $DIR/methods.rs:105:5 + --> $DIR/methods.rs:104:5 | LL | / fn new() -> i32 { LL | | 0 @@ -9,7 +9,7 @@ LL | | } = note: `-D clippy::new-ret-no-self` implied by `-D warnings` error: called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(..)` instead - --> $DIR/methods.rs:126:13 + --> $DIR/methods.rs:125:13 | LL | let _ = v.iter().filter(|&x| { | _____________^ diff --git a/src/tools/clippy/tests/ui/missing-doc.rs b/src/tools/clippy/tests/ui/missing-doc.rs index a9bf7140a1..148531c285 100644 --- a/src/tools/clippy/tests/ui/missing-doc.rs +++ b/src/tools/clippy/tests/ui/missing-doc.rs @@ -3,7 +3,6 @@ // injected intrinsics by the compiler. #![allow(dead_code)] #![feature(global_asm)] - //! Some garbage docs for the crate here #![doc = "More garbage"] @@ -90,10 +89,10 @@ mod internal_impl { } /// dox pub mod public_interface { - pub use internal_impl::documented as foo; - pub use internal_impl::globbed::*; - pub use internal_impl::undocumented1 as bar; - pub use internal_impl::{documented, undocumented2}; + pub use crate::internal_impl::documented as foo; + pub use crate::internal_impl::globbed::*; + pub use crate::internal_impl::undocumented1 as bar; + pub use crate::internal_impl::{documented, undocumented2}; } fn main() {} diff --git a/src/tools/clippy/tests/ui/missing-doc.stderr b/src/tools/clippy/tests/ui/missing-doc.stderr index a876dc078e..7a3a448c9d 100644 --- a/src/tools/clippy/tests/ui/missing-doc.stderr +++ b/src/tools/clippy/tests/ui/missing-doc.stderr @@ -1,5 +1,5 @@ error: missing documentation for a type alias - --> $DIR/missing-doc.rs:10:1 + --> $DIR/missing-doc.rs:9:1 | LL | type Typedef = String; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -7,37 +7,37 @@ LL | type Typedef = String; = note: `-D clippy::missing-docs-in-private-items` implied by `-D warnings` error: missing documentation for a type alias - --> $DIR/missing-doc.rs:11:1 + --> $DIR/missing-doc.rs:10:1 | LL | pub type PubTypedef = String; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a module - --> $DIR/missing-doc.rs:13:1 + --> $DIR/missing-doc.rs:12:1 | LL | mod module_no_dox {} | ^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a module - --> $DIR/missing-doc.rs:14:1 + --> $DIR/missing-doc.rs:13:1 | LL | pub mod pub_module_no_dox {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:18:1 + --> $DIR/missing-doc.rs:17:1 | LL | pub fn foo2() {} | ^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:19:1 + --> $DIR/missing-doc.rs:18:1 | LL | fn foo3() {} | ^^^^^^^^^^^^ error: missing documentation for an enum - --> $DIR/missing-doc.rs:33:1 + --> $DIR/missing-doc.rs:32:1 | LL | / enum Baz { LL | | BazA { a: isize, b: isize }, @@ -46,31 +46,31 @@ LL | | } | |_^ error: missing documentation for a variant - --> $DIR/missing-doc.rs:34:5 + --> $DIR/missing-doc.rs:33:5 | LL | BazA { a: isize, b: isize }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:34:12 + --> $DIR/missing-doc.rs:33:12 | LL | BazA { a: isize, b: isize }, | ^^^^^^^^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:34:22 + --> $DIR/missing-doc.rs:33:22 | LL | BazA { a: isize, b: isize }, | ^^^^^^^^ error: missing documentation for a variant - --> $DIR/missing-doc.rs:35:5 + --> $DIR/missing-doc.rs:34:5 | LL | BarB, | ^^^^ error: missing documentation for an enum - --> $DIR/missing-doc.rs:38:1 + --> $DIR/missing-doc.rs:37:1 | LL | / pub enum PubBaz { LL | | PubBazA { a: isize }, @@ -78,43 +78,43 @@ LL | | } | |_^ error: missing documentation for a variant - --> $DIR/missing-doc.rs:39:5 + --> $DIR/missing-doc.rs:38:5 | LL | PubBazA { a: isize }, | ^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:39:15 + --> $DIR/missing-doc.rs:38:15 | LL | PubBazA { a: isize }, | ^^^^^^^^ error: missing documentation for a constant - --> $DIR/missing-doc.rs:59:1 + --> $DIR/missing-doc.rs:58:1 | LL | const FOO: u32 = 0; | ^^^^^^^^^^^^^^^^^^^ error: missing documentation for a constant - --> $DIR/missing-doc.rs:66:1 + --> $DIR/missing-doc.rs:65:1 | LL | pub const FOO4: u32 = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a static - --> $DIR/missing-doc.rs:68:1 + --> $DIR/missing-doc.rs:67:1 | LL | static BAR: u32 = 0; | ^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a static - --> $DIR/missing-doc.rs:75:1 + --> $DIR/missing-doc.rs:74:1 | LL | pub static BAR4: u32 = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a module - --> $DIR/missing-doc.rs:77:1 + --> $DIR/missing-doc.rs:76:1 | LL | / mod internal_impl { LL | | /// dox @@ -126,31 +126,31 @@ LL | | } | |_^ error: missing documentation for a function - --> $DIR/missing-doc.rs:80:5 + --> $DIR/missing-doc.rs:79:5 | LL | pub fn undocumented1() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:81:5 + --> $DIR/missing-doc.rs:80:5 | LL | pub fn undocumented2() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:82:5 + --> $DIR/missing-doc.rs:81:5 | LL | fn undocumented3() {} | ^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:87:9 + --> $DIR/missing-doc.rs:86:9 | LL | pub fn also_undocumented1() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:88:9 + --> $DIR/missing-doc.rs:87:9 | LL | fn also_undocumented2() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/missing_panics_doc.rs b/src/tools/clippy/tests/ui/missing_panics_doc.rs index 2e1379a58a..7dc4452920 100644 --- a/src/tools/clippy/tests/ui/missing_panics_doc.rs +++ b/src/tools/clippy/tests/ui/missing_panics_doc.rs @@ -1,6 +1,5 @@ #![warn(clippy::missing_panics_doc)] #![allow(clippy::option_map_unit_fn)] - fn main() {} /// This needs to be documented diff --git a/src/tools/clippy/tests/ui/missing_panics_doc.stderr b/src/tools/clippy/tests/ui/missing_panics_doc.stderr index b863063b62..60282939ef 100644 --- a/src/tools/clippy/tests/ui/missing_panics_doc.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/missing_panics_doc.rs:7:1 + --> $DIR/missing_panics_doc.rs:6: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/missing_panics_doc.rs:9:5 + --> $DIR/missing_panics_doc.rs:8:5 | LL | result.unwrap() | ^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> $DIR/missing_panics_doc.rs:13:1 + --> $DIR/missing_panics_doc.rs:12:1 | LL | / pub fn panic() { LL | | panic!("This function panics") @@ -23,14 +23,14 @@ LL | | } | |_^ | note: first possible panic found here - --> $DIR/missing_panics_doc.rs:14:5 + --> $DIR/missing_panics_doc.rs:13:5 | LL | panic!("This function panics") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `$crate::panic::panic_2021` (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:18:1 + --> $DIR/missing_panics_doc.rs:17:1 | LL | / pub fn todo() { LL | | todo!() @@ -38,14 +38,14 @@ LL | | } | |_^ | note: first possible panic found here - --> $DIR/missing_panics_doc.rs:19:5 + --> $DIR/missing_panics_doc.rs:18:5 | LL | todo!() | ^^^^^^^ = note: this error originates in the macro `$crate::panic::panic_2015` (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:23:1 + --> $DIR/missing_panics_doc.rs:22: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/missing_panics_doc.rs:26:13 + --> $DIR/missing_panics_doc.rs:25:13 | LL | panic!() | ^^^^^^^^ - = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `$crate::panic::panic_2021` (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:32:1 + --> $DIR/missing_panics_doc.rs:31:1 | LL | / pub fn unreachable_and_panic() { LL | | if true { unreachable!() } else { panic!() } @@ -72,14 +72,14 @@ LL | | } | |_^ | note: first possible panic found here - --> $DIR/missing_panics_doc.rs:33:39 + --> $DIR/missing_panics_doc.rs:32:39 | LL | if true { unreachable!() } else { panic!() } | ^^^^^^^^ - = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `$crate::panic::panic_2021` (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:37:1 + --> $DIR/missing_panics_doc.rs:36:1 | LL | / pub fn assert_eq() { LL | | let x = 0; @@ -88,14 +88,14 @@ LL | | } | |_^ | note: first possible panic found here - --> $DIR/missing_panics_doc.rs:39:5 + --> $DIR/missing_panics_doc.rs:38:5 | LL | assert_eq!(x, 0); | ^^^^^^^^^^^^^^^^ = note: this error originates in the macro `assert_eq` (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 + --> $DIR/missing_panics_doc.rs:42:1 | LL | / pub fn assert_ne() { LL | | let x = 0; @@ -104,7 +104,7 @@ LL | | } | |_^ | note: first possible panic found here - --> $DIR/missing_panics_doc.rs:45:5 + --> $DIR/missing_panics_doc.rs:44:5 | LL | assert_ne!(x, 0); | ^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/mistyped_literal_suffix.fixed b/src/tools/clippy/tests/ui/mistyped_literal_suffix.fixed index 70cdb067d9..5d57638af4 100644 --- a/src/tools/clippy/tests/ui/mistyped_literal_suffix.fixed +++ b/src/tools/clippy/tests/ui/mistyped_literal_suffix.fixed @@ -3,6 +3,7 @@ #![allow( dead_code, unused_variables, + overflowing_literals, clippy::excessive_precision, clippy::inconsistent_digit_grouping )] @@ -21,7 +22,6 @@ fn main() { let fail25 = 1E2_f32; let fail26 = 43E7_f64; let fail27 = 243E17_f32; - #[allow(overflowing_literals)] let fail28 = 241_251_235E723_f64; let ok29 = 42279.911_32; diff --git a/src/tools/clippy/tests/ui/mistyped_literal_suffix.rs b/src/tools/clippy/tests/ui/mistyped_literal_suffix.rs index 729990af39..1217145288 100644 --- a/src/tools/clippy/tests/ui/mistyped_literal_suffix.rs +++ b/src/tools/clippy/tests/ui/mistyped_literal_suffix.rs @@ -3,6 +3,7 @@ #![allow( dead_code, unused_variables, + overflowing_literals, clippy::excessive_precision, clippy::inconsistent_digit_grouping )] @@ -21,7 +22,6 @@ fn main() { let fail25 = 1E2_32; let fail26 = 43E7_64; let fail27 = 243E17_32; - #[allow(overflowing_literals)] let fail28 = 241251235E723_64; let ok29 = 42279.911_32; diff --git a/src/tools/clippy/tests/ui/mistyped_literal_suffix.stderr b/src/tools/clippy/tests/ui/mistyped_literal_suffix.stderr index b338b8aa62..d24543c26e 100644 --- a/src/tools/clippy/tests/ui/mistyped_literal_suffix.stderr +++ b/src/tools/clippy/tests/ui/mistyped_literal_suffix.stderr @@ -1,5 +1,5 @@ error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:11:18 + --> $DIR/mistyped_literal_suffix.rs:12:18 | LL | let fail14 = 2_32; | ^^^^ help: did you mean to write: `2_i32` @@ -7,49 +7,49 @@ LL | let fail14 = 2_32; = note: `#[deny(clippy::mistyped_literal_suffixes)]` on by default error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:12:18 + --> $DIR/mistyped_literal_suffix.rs:13:18 | LL | let fail15 = 4_64; | ^^^^ help: did you mean to write: `4_i64` error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:13:18 + --> $DIR/mistyped_literal_suffix.rs:14:18 | LL | let fail16 = 7_8; // | ^^^ help: did you mean to write: `7_i8` error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:14:18 + --> $DIR/mistyped_literal_suffix.rs:15:18 | LL | let fail17 = 23_16; // | ^^^^^ help: did you mean to write: `23_i16` error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:17:18 + --> $DIR/mistyped_literal_suffix.rs:18:18 | LL | let fail20 = 2__8; // | ^^^^ help: did you mean to write: `2_i8` error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:18:18 + --> $DIR/mistyped_literal_suffix.rs:19:18 | LL | let fail21 = 4___16; // | ^^^^^^ help: did you mean to write: `4_i16` error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:21:18 + --> $DIR/mistyped_literal_suffix.rs:22:18 | LL | let fail25 = 1E2_32; | ^^^^^^ help: did you mean to write: `1E2_f32` error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:22:18 + --> $DIR/mistyped_literal_suffix.rs:23:18 | LL | let fail26 = 43E7_64; | ^^^^^^^ help: did you mean to write: `43E7_f64` error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:23:18 + --> $DIR/mistyped_literal_suffix.rs:24:18 | LL | let fail27 = 243E17_32; | ^^^^^^^^^ help: did you mean to write: `243E17_f32` diff --git a/src/tools/clippy/tests/ui/mut_mut.rs b/src/tools/clippy/tests/ui/mut_mut.rs index 8965cef66d..be854d9418 100644 --- a/src/tools/clippy/tests/ui/mut_mut.rs +++ b/src/tools/clippy/tests/ui/mut_mut.rs @@ -1,6 +1,11 @@ +// aux-build:macro_rules.rs + #![allow(unused, clippy::no_effect, clippy::unnecessary_operation)] #![warn(clippy::mut_mut)] +#[macro_use] +extern crate macro_rules; + fn fun(x: &mut &mut u32) -> bool { **x > 0 } @@ -47,3 +52,8 @@ fn issue939() { println!(":{}", arg); } } + +fn issue6922() { + // do not lint from an external macro + mut_mut!(); +} diff --git a/src/tools/clippy/tests/ui/mut_mut.stderr b/src/tools/clippy/tests/ui/mut_mut.stderr index 0fed6953cb..6820a85aa5 100644 --- a/src/tools/clippy/tests/ui/mut_mut.stderr +++ b/src/tools/clippy/tests/ui/mut_mut.stderr @@ -1,5 +1,5 @@ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:4:11 + --> $DIR/mut_mut.rs:9:11 | LL | fn fun(x: &mut &mut u32) -> bool { | ^^^^^^^^^^^^^ @@ -7,13 +7,13 @@ LL | fn fun(x: &mut &mut u32) -> bool { = note: `-D clippy::mut-mut` implied by `-D warnings` error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:20:17 + --> $DIR/mut_mut.rs:25:17 | LL | let mut x = &mut &mut 1u32; | ^^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:14:9 + --> $DIR/mut_mut.rs:19:9 | LL | &mut $p | ^^^^^^^ @@ -24,37 +24,37 @@ LL | let mut z = mut_ptr!(&mut 3u32); = note: this error originates in the macro `mut_ptr` (in Nightly builds, run with -Z macro-backtrace for more info) error: this expression mutably borrows a mutable reference. Consider reborrowing - --> $DIR/mut_mut.rs:22:21 + --> $DIR/mut_mut.rs:27:21 | LL | let mut y = &mut x; | ^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:26:32 + --> $DIR/mut_mut.rs:31:32 | LL | let y: &mut &mut u32 = &mut &mut 2; | ^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:26:16 + --> $DIR/mut_mut.rs:31:16 | LL | let y: &mut &mut u32 = &mut &mut 2; | ^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:31:37 + --> $DIR/mut_mut.rs:36:37 | LL | let y: &mut &mut &mut u32 = &mut &mut &mut 2; | ^^^^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:31:16 + --> $DIR/mut_mut.rs:36:16 | LL | let y: &mut &mut &mut u32 = &mut &mut &mut 2; | ^^^^^^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> $DIR/mut_mut.rs:31:21 + --> $DIR/mut_mut.rs:36:21 | LL | let y: &mut &mut &mut u32 = &mut &mut &mut 2; | ^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.rs b/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.rs index a39d96109f..ad0d694a21 100644 --- a/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.rs +++ b/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.rs @@ -38,6 +38,7 @@ mod issue_6089 { // fn call_with_mut_self<'life0>(self: &'life0 mut Self) {} #[rename_my_lifetimes] impl T2 for S2 { + #[allow(clippy::needless_lifetimes)] fn call_with_mut_self(self: &mut Self) {} } } diff --git a/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.stderr b/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.stderr index 44a0e6ddea..b2edbfe432 100644 --- a/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.stderr +++ b/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.stderr @@ -1,5 +1,5 @@ error: the type of the `self` parameter does not need to be arbitrary - --> $DIR/needless_arbitrary_self_type_unfixable.rs:41:31 + --> $DIR/needless_arbitrary_self_type_unfixable.rs:42:31 | LL | fn call_with_mut_self(self: &mut Self) {} | ^^^^^^^^^^^^^^^ help: consider to change this parameter to: `&'_ mut self` diff --git a/src/tools/clippy/tests/ui/needless_borrow_pat.rs b/src/tools/clippy/tests/ui/needless_borrow_pat.rs index 7a8137778b..04b6283da3 100644 --- a/src/tools/clippy/tests/ui/needless_borrow_pat.rs +++ b/src/tools/clippy/tests/ui/needless_borrow_pat.rs @@ -1,4 +1,3 @@ -// edition:2018 // FIXME: run-rustfix waiting on multi-span suggestions #![warn(clippy::needless_borrow)] diff --git a/src/tools/clippy/tests/ui/needless_borrow_pat.stderr b/src/tools/clippy/tests/ui/needless_borrow_pat.stderr index 365ecd68d8..db3b52b885 100644 --- a/src/tools/clippy/tests/ui/needless_borrow_pat.stderr +++ b/src/tools/clippy/tests/ui/needless_borrow_pat.stderr @@ -1,5 +1,5 @@ error: this pattern creates a reference to a reference - --> $DIR/needless_borrow_pat.rs:60:14 + --> $DIR/needless_borrow_pat.rs:59:14 | LL | Some(ref x) => x, | ^^^^^ help: try this: `x` @@ -7,7 +7,7 @@ LL | Some(ref x) => x, = note: `-D clippy::needless-borrow` implied by `-D warnings` error: this pattern creates a reference to a reference - --> $DIR/needless_borrow_pat.rs:66:14 + --> $DIR/needless_borrow_pat.rs:65:14 | LL | Some(ref x) => *x, | ^^^^^ @@ -18,7 +18,7 @@ LL | Some(x) => x, | ~ ~ error: this pattern creates a reference to a reference - --> $DIR/needless_borrow_pat.rs:72:14 + --> $DIR/needless_borrow_pat.rs:71:14 | LL | Some(ref x) => { | ^^^^^ @@ -31,19 +31,19 @@ LL ~ f1(x); | error: this pattern creates a reference to a reference - --> $DIR/needless_borrow_pat.rs:82:14 + --> $DIR/needless_borrow_pat.rs:81:14 | LL | Some(ref x) => m1!(x), | ^^^^^ help: try this: `x` error: this pattern creates a reference to a reference - --> $DIR/needless_borrow_pat.rs:87:15 + --> $DIR/needless_borrow_pat.rs:86:15 | LL | let _ = |&ref x: &&String| { | ^^^^^ help: try this: `x` error: this pattern creates a reference to a reference - --> $DIR/needless_borrow_pat.rs:92:10 + --> $DIR/needless_borrow_pat.rs:91:10 | LL | let (ref y,) = (&x,); | ^^^^^ @@ -55,13 +55,13 @@ LL ~ let _: &String = y; | error: this pattern creates a reference to a reference - --> $DIR/needless_borrow_pat.rs:102:14 + --> $DIR/needless_borrow_pat.rs:101:14 | LL | Some(ref x) => x.0, | ^^^^^ help: try this: `x` error: this pattern creates a reference to a reference - --> $DIR/needless_borrow_pat.rs:112:14 + --> $DIR/needless_borrow_pat.rs:111:14 | LL | E::A(ref x) | E::B(ref x) => *x, | ^^^^^ ^^^^^ @@ -72,13 +72,13 @@ LL | E::A(x) | E::B(x) => x, | ~ ~ ~ error: this pattern creates a reference to a reference - --> $DIR/needless_borrow_pat.rs:118:21 + --> $DIR/needless_borrow_pat.rs:117:21 | LL | if let Some(ref x) = Some(&String::new()); | ^^^^^ help: try this: `x` error: this pattern creates a reference to a reference - --> $DIR/needless_borrow_pat.rs:126:12 + --> $DIR/needless_borrow_pat.rs:125:12 | LL | fn f2<'a>(&ref x: &&'a String) -> &'a String { | ^^^^^ @@ -91,13 +91,13 @@ LL ~ x | error: this pattern creates a reference to a reference - --> $DIR/needless_borrow_pat.rs:133:11 + --> $DIR/needless_borrow_pat.rs:132:11 | LL | fn f(&ref x: &&String) { | ^^^^^ help: try this: `x` error: this pattern creates a reference to a reference - --> $DIR/needless_borrow_pat.rs:141:11 + --> $DIR/needless_borrow_pat.rs:140:11 | LL | fn f(&ref x: &&String) { | ^^^^^ diff --git a/src/tools/clippy/tests/ui/needless_continue.rs b/src/tools/clippy/tests/ui/needless_continue.rs index 83ee27f488..f105d3d659 100644 --- a/src/tools/clippy/tests/ui/needless_continue.rs +++ b/src/tools/clippy/tests/ui/needless_continue.rs @@ -12,6 +12,7 @@ macro_rules! nonzero { }; } +#[allow(clippy::nonminimal_bool)] fn main() { let mut i = 1; while i < 10 { diff --git a/src/tools/clippy/tests/ui/needless_continue.stderr b/src/tools/clippy/tests/ui/needless_continue.stderr index 22b86f25e8..b8657c74ca 100644 --- a/src/tools/clippy/tests/ui/needless_continue.stderr +++ b/src/tools/clippy/tests/ui/needless_continue.stderr @@ -1,5 +1,5 @@ error: this `else` block is redundant - --> $DIR/needless_continue.rs:28:16 + --> $DIR/needless_continue.rs:29:16 | LL | } else { | ________________^ @@ -35,7 +35,7 @@ LL | | } } error: there is no need for an explicit `else` block for this `if` expression - --> $DIR/needless_continue.rs:43:9 + --> $DIR/needless_continue.rs:44:9 | LL | / if (zero!(i % 2) || nonzero!(i % 5)) && i % 3 != 0 { LL | | continue; @@ -55,7 +55,7 @@ LL | | } } error: this `continue` expression is redundant - --> $DIR/needless_continue.rs:56:9 + --> $DIR/needless_continue.rs:57:9 | LL | continue; // should lint here | ^^^^^^^^^ @@ -63,7 +63,7 @@ LL | continue; // should lint here = help: consider dropping the `continue` expression error: this `continue` expression is redundant - --> $DIR/needless_continue.rs:63:9 + --> $DIR/needless_continue.rs:64:9 | LL | continue; // should lint here | ^^^^^^^^^ @@ -71,7 +71,7 @@ LL | continue; // should lint here = help: consider dropping the `continue` expression error: this `continue` expression is redundant - --> $DIR/needless_continue.rs:70:9 + --> $DIR/needless_continue.rs:71:9 | LL | continue // should lint here | ^^^^^^^^ @@ -79,7 +79,7 @@ LL | continue // should lint here = help: consider dropping the `continue` expression error: this `continue` expression is redundant - --> $DIR/needless_continue.rs:78:9 + --> $DIR/needless_continue.rs:79:9 | LL | continue // should lint here | ^^^^^^^^ @@ -87,7 +87,7 @@ LL | continue // should lint here = help: consider dropping the `continue` expression error: this `else` block is redundant - --> $DIR/needless_continue.rs:128:24 + --> $DIR/needless_continue.rs:129:24 | LL | } else { | ________________________^ @@ -110,7 +110,7 @@ LL | | } } error: there is no need for an explicit `else` block for this `if` expression - --> $DIR/needless_continue.rs:134:17 + --> $DIR/needless_continue.rs:135:17 | LL | / if condition() { LL | | continue; // should lint here diff --git a/src/tools/clippy/tests/ui/needless_lifetimes.rs b/src/tools/clippy/tests/ui/needless_lifetimes.rs index 1d77382bf2..b07c4a2381 100644 --- a/src/tools/clippy/tests/ui/needless_lifetimes.rs +++ b/src/tools/clippy/tests/ui/needless_lifetimes.rs @@ -27,6 +27,11 @@ fn multiple_in_and_out_2<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 { x } +// No error; multiple input refs +async fn func<'a>(args: &[&'a str]) -> Option<&'a str> { + args.get(0).cloned() +} + // No error; static involved. fn in_static_and_out<'a>(x: &'a u8, _y: &'static u8) -> &'a u8 { x diff --git a/src/tools/clippy/tests/ui/needless_lifetimes.stderr b/src/tools/clippy/tests/ui/needless_lifetimes.stderr index 33a6de1618..4114e6f183 100644 --- a/src/tools/clippy/tests/ui/needless_lifetimes.stderr +++ b/src/tools/clippy/tests/ui/needless_lifetimes.stderr @@ -19,133 +19,133 @@ LL | fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/needless_lifetimes.rs:45:1 + --> $DIR/needless_lifetimes.rs:50:1 | LL | fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/needless_lifetimes.rs:50:1 + --> $DIR/needless_lifetimes.rs:55:1 | LL | fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/needless_lifetimes.rs:62:1 + --> $DIR/needless_lifetimes.rs:67:1 | LL | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/needless_lifetimes.rs:86:1 + --> $DIR/needless_lifetimes.rs:91:1 | LL | fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/needless_lifetimes.rs:116:5 + --> $DIR/needless_lifetimes.rs:121:5 | LL | fn self_and_out<'s>(&'s self) -> &'s u8 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/needless_lifetimes.rs:125:5 + --> $DIR/needless_lifetimes.rs:130:5 | LL | fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/needless_lifetimes.rs:144:1 + --> $DIR/needless_lifetimes.rs:149:1 | LL | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/needless_lifetimes.rs:174:1 + --> $DIR/needless_lifetimes.rs:179:1 | LL | fn trait_obj_elided2<'a>(_arg: &'a dyn Drop) -> &'a str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/needless_lifetimes.rs:180:1 + --> $DIR/needless_lifetimes.rs:185:1 | LL | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/needless_lifetimes.rs:199:1 + --> $DIR/needless_lifetimes.rs:204:1 | LL | fn named_input_elided_output<'a>(_arg: &'a str) -> &str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/needless_lifetimes.rs:207:1 + --> $DIR/needless_lifetimes.rs:212:1 | LL | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/needless_lifetimes.rs:243:1 + --> $DIR/needless_lifetimes.rs:248:1 | LL | fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/needless_lifetimes.rs:250:9 + --> $DIR/needless_lifetimes.rs:255:9 | LL | fn needless_lt<'a>(x: &'a u8) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/needless_lifetimes.rs:254:9 + --> $DIR/needless_lifetimes.rs:259:9 | LL | fn needless_lt<'a>(_x: &'a u8) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/needless_lifetimes.rs:267:9 + --> $DIR/needless_lifetimes.rs:272:9 | LL | fn baz<'a>(&'a self) -> impl Foo + 'a { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/needless_lifetimes.rs:296:5 + --> $DIR/needless_lifetimes.rs:301:5 | LL | fn impl_trait_elidable_nested_named_lifetimes<'a>(i: &'a i32, f: impl for<'b> Fn(&'b i32) -> &'b i32) -> &'a i32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/needless_lifetimes.rs:299:5 + --> $DIR/needless_lifetimes.rs:304:5 | LL | fn impl_trait_elidable_nested_anonymous_lifetimes<'a>(i: &'a i32, f: impl Fn(&i32) -> &i32) -> &'a i32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/needless_lifetimes.rs:308:5 + --> $DIR/needless_lifetimes.rs:313:5 | LL | fn generics_elidable<'a, T: Fn(&i32) -> &i32>(i: &'a i32, f: T) -> &'a i32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/needless_lifetimes.rs:320:5 + --> $DIR/needless_lifetimes.rs:325:5 | LL | fn where_clause_elidadable<'a, T>(i: &'a i32, f: T) -> &'a i32 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/needless_lifetimes.rs:335:5 + --> $DIR/needless_lifetimes.rs:340:5 | LL | fn pointer_fn_elidable<'a>(i: &'a i32, f: fn(&i32) -> &i32) -> &'a i32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/needless_lifetimes.rs:348:5 + --> $DIR/needless_lifetimes.rs:353:5 | LL | fn nested_fn_pointer_3<'a>(_: &'a i32) -> fn(fn(&i32) -> &i32) -> i32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/needless_lifetimes.rs:351:5 + --> $DIR/needless_lifetimes.rs:356:5 | LL | fn nested_fn_pointer_4<'a>(_: &'a i32) -> impl Fn(fn(&i32)) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/needless_return.fixed b/src/tools/clippy/tests/ui/needless_return.fixed index 9c999e12b4..812ce7163c 100644 --- a/src/tools/clippy/tests/ui/needless_return.fixed +++ b/src/tools/clippy/tests/ui/needless_return.fixed @@ -1,5 +1,4 @@ // run-rustfix -// edition:2018 #![feature(let_else)] #![allow(unused)] diff --git a/src/tools/clippy/tests/ui/needless_return.rs b/src/tools/clippy/tests/ui/needless_return.rs index da7dcf4f0a..c42567b517 100644 --- a/src/tools/clippy/tests/ui/needless_return.rs +++ b/src/tools/clippy/tests/ui/needless_return.rs @@ -1,5 +1,4 @@ // run-rustfix -// edition:2018 #![feature(let_else)] #![allow(unused)] diff --git a/src/tools/clippy/tests/ui/needless_return.stderr b/src/tools/clippy/tests/ui/needless_return.stderr index 2e802cff1e..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:25:5 + --> $DIR/needless_return.rs:24:5 | LL | return true; | ^^^^^^^^^^^^ help: remove `return`: `true` @@ -7,187 +7,187 @@ LL | return true; = note: `-D clippy::needless-return` implied by `-D warnings` error: unneeded `return` statement - --> $DIR/needless_return.rs:29:5 + --> $DIR/needless_return.rs:28:5 | LL | return true; | ^^^^^^^^^^^^ help: remove `return`: `true` error: unneeded `return` statement - --> $DIR/needless_return.rs:34:9 + --> $DIR/needless_return.rs:33:9 | LL | return true; | ^^^^^^^^^^^^ help: remove `return`: `true` error: unneeded `return` statement - --> $DIR/needless_return.rs:36:9 + --> $DIR/needless_return.rs:35:9 | LL | return false; | ^^^^^^^^^^^^^ help: remove `return`: `false` error: unneeded `return` statement - --> $DIR/needless_return.rs:42:17 + --> $DIR/needless_return.rs:41:17 | LL | true => return false, | ^^^^^^^^^^^^ help: remove `return`: `false` error: unneeded `return` statement - --> $DIR/needless_return.rs:44:13 + --> $DIR/needless_return.rs:43:13 | LL | return true; | ^^^^^^^^^^^^ help: remove `return`: `true` error: unneeded `return` statement - --> $DIR/needless_return.rs:51:9 + --> $DIR/needless_return.rs:50:9 | LL | return true; | ^^^^^^^^^^^^ help: remove `return`: `true` error: unneeded `return` statement - --> $DIR/needless_return.rs:53:16 + --> $DIR/needless_return.rs:52:16 | LL | let _ = || return true; | ^^^^^^^^^^^ help: remove `return`: `true` error: unneeded `return` statement - --> $DIR/needless_return.rs:61:5 + --> $DIR/needless_return.rs:60:5 | LL | return; | ^^^^^^^ help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:66:9 + --> $DIR/needless_return.rs:65:9 | LL | return; | ^^^^^^^ help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:68:9 + --> $DIR/needless_return.rs:67:9 | LL | return; | ^^^^^^^ help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:75:14 + --> $DIR/needless_return.rs:74:14 | LL | _ => return, | ^^^^^^ help: replace `return` with an empty block: `{}` error: unneeded `return` statement - --> $DIR/needless_return.rs:90: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:92:9 + --> $DIR/needless_return.rs:91:9 | LL | return String::new(); | ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::new()` error: unneeded `return` statement - --> $DIR/needless_return.rs:113: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:118:13 + --> $DIR/needless_return.rs:117:13 | LL | return; | ^^^^^^^ help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:120: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:126:32 + --> $DIR/needless_return.rs:125:32 | LL | res.unwrap_or_else(|_| return Foo) | ^^^^^^^^^^ help: remove `return`: `Foo` error: unneeded `return` statement - --> $DIR/needless_return.rs:135:5 + --> $DIR/needless_return.rs:134:5 | LL | return true; | ^^^^^^^^^^^^ help: remove `return`: `true` error: unneeded `return` statement - --> $DIR/needless_return.rs:139:5 + --> $DIR/needless_return.rs:138:5 | LL | return true; | ^^^^^^^^^^^^ help: remove `return`: `true` error: unneeded `return` statement - --> $DIR/needless_return.rs:144:9 + --> $DIR/needless_return.rs:143:9 | LL | return true; | ^^^^^^^^^^^^ help: remove `return`: `true` error: unneeded `return` statement - --> $DIR/needless_return.rs:146:9 + --> $DIR/needless_return.rs:145:9 | LL | return false; | ^^^^^^^^^^^^^ help: remove `return`: `false` error: unneeded `return` statement - --> $DIR/needless_return.rs:152:17 + --> $DIR/needless_return.rs:151:17 | LL | true => return false, | ^^^^^^^^^^^^ help: remove `return`: `false` error: unneeded `return` statement - --> $DIR/needless_return.rs:154:13 + --> $DIR/needless_return.rs:153:13 | LL | return true; | ^^^^^^^^^^^^ help: remove `return`: `true` error: unneeded `return` statement - --> $DIR/needless_return.rs:161:9 + --> $DIR/needless_return.rs:160:9 | LL | return true; | ^^^^^^^^^^^^ help: remove `return`: `true` error: unneeded `return` statement - --> $DIR/needless_return.rs:163:16 + --> $DIR/needless_return.rs:162:16 | LL | let _ = || return true; | ^^^^^^^^^^^ help: remove `return`: `true` error: unneeded `return` statement - --> $DIR/needless_return.rs:171:5 + --> $DIR/needless_return.rs:170:5 | LL | return; | ^^^^^^^ help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:176:9 + --> $DIR/needless_return.rs:175:9 | LL | return; | ^^^^^^^ help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:178:9 + --> $DIR/needless_return.rs:177:9 | LL | return; | ^^^^^^^ help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:185:14 + --> $DIR/needless_return.rs:184:14 | LL | _ => return, | ^^^^^^ help: replace `return` with an empty block: `{}` error: unneeded `return` statement - --> $DIR/needless_return.rs:200:9 + --> $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:202:9 + --> $DIR/needless_return.rs:201:9 | LL | return String::new(); | ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::new()` diff --git a/src/tools/clippy/tests/ui/no_effect.rs b/src/tools/clippy/tests/ui/no_effect.rs index 7ec845adfa..7bcc4cad0d 100644 --- a/src/tools/clippy/tests/ui/no_effect.rs +++ b/src/tools/clippy/tests/ui/no_effect.rs @@ -1,5 +1,5 @@ #![feature(box_syntax)] -#![warn(clippy::no_effect)] +#![warn(clippy::no_effect_underscore_binding)] #![allow(dead_code)] #![allow(path_statements)] #![allow(clippy::deref_addrof)] @@ -90,6 +90,10 @@ fn main() { || x += 5; let s: String = "foo".into(); FooString { s: s }; + let _unused = 1; + let _penguin = || println!("Some helpful closure"); + let _duck = Struct { field: 0 }; + let _cat = [2, 4, 6, 8][2]; #[allow(clippy::no_effect)] 0; @@ -97,6 +101,8 @@ fn main() { // Do not warn get_number(); unsafe { unsafe_fn() }; + let _used = get_struct(); + let _x = vec![1]; DropUnit; DropStruct { field: 0 }; DropTuple(0); diff --git a/src/tools/clippy/tests/ui/no_effect.stderr b/src/tools/clippy/tests/ui/no_effect.stderr index 6b24675ac2..a5dbc9fef4 100644 --- a/src/tools/clippy/tests/ui/no_effect.stderr +++ b/src/tools/clippy/tests/ui/no_effect.stderr @@ -156,5 +156,31 @@ error: statement with no effect LL | FooString { s: s }; | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to 26 previous errors +error: binding to `_` prefixed variable with no side-effect + --> $DIR/no_effect.rs:93:5 + | +LL | let _unused = 1; + | ^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::no-effect-underscore-binding` implied by `-D warnings` + +error: binding to `_` prefixed variable with no side-effect + --> $DIR/no_effect.rs:94:5 + | +LL | let _penguin = || println!("Some helpful closure"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: binding to `_` prefixed variable with no side-effect + --> $DIR/no_effect.rs:95:5 + | +LL | let _duck = Struct { field: 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: binding to `_` prefixed variable with no side-effect + --> $DIR/no_effect.rs:96:5 + | +LL | let _cat = [2, 4, 6, 8][2]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 30 previous errors diff --git a/src/tools/clippy/tests/ui/non_expressive_names.rs b/src/tools/clippy/tests/ui/non_expressive_names.rs index 58415b4aed..9937005d68 100644 --- a/src/tools/clippy/tests/ui/non_expressive_names.rs +++ b/src/tools/clippy/tests/ui/non_expressive_names.rs @@ -1,5 +1,5 @@ #![warn(clippy::all)] -#![allow(unused, clippy::println_empty_string)] +#![allow(unused, clippy::println_empty_string, non_snake_case)] #[derive(Clone, Debug)] enum MaybeInst { @@ -14,9 +14,10 @@ struct InstSplit { impl MaybeInst { fn fill(&mut self) { + #[allow(non_fmt_panics)] let filled = match *self { - MaybeInst::Split1(goto1) => panic!(1), - MaybeInst::Split2(goto2) => panic!(2), + MaybeInst::Split1(goto1) => panic!("1"), + MaybeInst::Split2(goto2) => panic!("2"), _ => unimplemented!(), }; unimplemented!() @@ -36,6 +37,7 @@ fn issue2927() { } fn issue3078() { + #[allow(clippy::single_match)] match "a" { stringify!(a) => {}, _ => {}, diff --git a/src/tools/clippy/tests/ui/non_expressive_names.stderr b/src/tools/clippy/tests/ui/non_expressive_names.stderr index a0ca46f0ef..116d5da872 100644 --- a/src/tools/clippy/tests/ui/non_expressive_names.stderr +++ b/src/tools/clippy/tests/ui/non_expressive_names.stderr @@ -1,5 +1,5 @@ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:27:9 + --> $DIR/non_expressive_names.rs:28:9 | LL | let _1 = 1; //~ERROR Consider a more descriptive name | ^^ @@ -7,31 +7,31 @@ LL | let _1 = 1; //~ERROR Consider a more descriptive name = note: `-D clippy::just-underscores-and-digits` implied by `-D warnings` error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:28:9 + --> $DIR/non_expressive_names.rs:29:9 | LL | let ____1 = 1; //~ERROR Consider a more descriptive name | ^^^^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:29:9 + --> $DIR/non_expressive_names.rs:30:9 | LL | let __1___2 = 12; //~ERROR Consider a more descriptive name | ^^^^^^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:49:13 + --> $DIR/non_expressive_names.rs:51:13 | LL | let _1 = 1; | ^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:50:13 + --> $DIR/non_expressive_names.rs:52:13 | LL | let ____1 = 1; | ^^^^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:51:13 + --> $DIR/non_expressive_names.rs:53:13 | LL | let __1___2 = 12; | ^^^^^^^ diff --git a/src/tools/clippy/tests/ui/nonminimal_bool.stderr b/src/tools/clippy/tests/ui/nonminimal_bool.stderr index 1d39bce935..bb93cbbd5e 100644 --- a/src/tools/clippy/tests/ui/nonminimal_bool.stderr +++ b/src/tools/clippy/tests/ui/nonminimal_bool.stderr @@ -50,10 +50,10 @@ LL | let _ = a == b && c == 5 && a == b; | help: try | -LL | let _ = a == b && c == 5; - | ~~~~~~~~~~~~~~~~ LL | let _ = !(a != b || c != 5); | ~~~~~~~~~~~~~~~~~~~ +LL | let _ = a == b && c == 5; + | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified --> $DIR/nonminimal_bool.rs:28:13 @@ -63,10 +63,10 @@ LL | let _ = a == b || c == 5 || a == b; | help: try | -LL | let _ = a == b || c == 5; - | ~~~~~~~~~~~~~~~~ LL | let _ = !(a != b && c != 5); | ~~~~~~~~~~~~~~~~~~~ +LL | let _ = a == b || c == 5; + | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified --> $DIR/nonminimal_bool.rs:29:13 @@ -76,10 +76,10 @@ LL | let _ = a == b && c == 5 && b == a; | help: try | -LL | let _ = a == b && c == 5; - | ~~~~~~~~~~~~~~~~ LL | let _ = !(a != b || c != 5); | ~~~~~~~~~~~~~~~~~~~ +LL | let _ = a == b && c == 5; + | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified --> $DIR/nonminimal_bool.rs:30:13 @@ -89,10 +89,10 @@ LL | let _ = a != b || !(a != b || c == d); | help: try | -LL | let _ = a != b || c != d; - | ~~~~~~~~~~~~~~~~ LL | let _ = !(a == b && c == d); | ~~~~~~~~~~~~~~~~~~~ +LL | let _ = a != b || c != d; + | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified --> $DIR/nonminimal_bool.rs:31:13 @@ -102,10 +102,10 @@ LL | let _ = a != b && !(a != b && c == d); | help: try | -LL | let _ = a != b && c != d; - | ~~~~~~~~~~~~~~~~ LL | let _ = !(a == b || c == d); | ~~~~~~~~~~~~~~~~~~~ +LL | let _ = a != b && c != d; + | ~~~~~~~~~~~~~~~~ error: aborting due to 12 previous errors diff --git a/src/tools/clippy/tests/ui/option_if_let_else.fixed b/src/tools/clippy/tests/ui/option_if_let_else.fixed index a3ebe5d070..9cb6a9d1ec 100644 --- a/src/tools/clippy/tests/ui/option_if_let_else.fixed +++ b/src/tools/clippy/tests/ui/option_if_let_else.fixed @@ -1,8 +1,6 @@ -// edition:2018 // run-rustfix #![warn(clippy::option_if_let_else)] -#![allow(clippy::redundant_closure)] -#![allow(clippy::ref_option_ref, clippy::equatable_if_let)] +#![allow(clippy::redundant_closure, clippy::ref_option_ref, clippy::equatable_if_let)] fn bad1(string: Option<&str>) -> (bool, &str) { string.map_or((false, "hello"), |x| (true, x)) diff --git a/src/tools/clippy/tests/ui/option_if_let_else.rs b/src/tools/clippy/tests/ui/option_if_let_else.rs index b11df3db60..b3ba5eb870 100644 --- a/src/tools/clippy/tests/ui/option_if_let_else.rs +++ b/src/tools/clippy/tests/ui/option_if_let_else.rs @@ -1,8 +1,6 @@ -// edition:2018 // run-rustfix #![warn(clippy::option_if_let_else)] -#![allow(clippy::redundant_closure)] -#![allow(clippy::ref_option_ref, clippy::equatable_if_let)] +#![allow(clippy::redundant_closure, clippy::ref_option_ref, clippy::equatable_if_let)] fn bad1(string: Option<&str>) -> (bool, &str) { if let Some(x) = string { diff --git a/src/tools/clippy/tests/ui/option_if_let_else.stderr b/src/tools/clippy/tests/ui/option_if_let_else.stderr index ed748ee8b3..685bb48ea3 100644 --- a/src/tools/clippy/tests/ui/option_if_let_else.stderr +++ b/src/tools/clippy/tests/ui/option_if_let_else.stderr @@ -1,5 +1,5 @@ error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:8:5 + --> $DIR/option_if_let_else.rs:6:5 | LL | / if let Some(x) = string { LL | | (true, x) @@ -11,19 +11,19 @@ LL | | } = note: `-D clippy::option-if-let-else` implied by `-D warnings` error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:26:13 + --> $DIR/option_if_let_else.rs:24:13 | LL | let _ = if let Some(s) = *string { s.len() } else { 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `string.map_or(0, |s| s.len())` error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:27:13 + --> $DIR/option_if_let_else.rs:25:13 | LL | let _ = if let Some(s) = &num { s } else { &0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)` error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:28:13 + --> $DIR/option_if_let_else.rs:26:13 | LL | let _ = if let Some(s) = &mut num { | _____________^ @@ -43,13 +43,13 @@ LL ~ }); | error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:34:13 + --> $DIR/option_if_let_else.rs:32:13 | LL | let _ = if let Some(ref s) = num { s } else { &0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)` error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:35:13 + --> $DIR/option_if_let_else.rs:33:13 | LL | let _ = if let Some(mut s) = num { | _____________^ @@ -69,7 +69,7 @@ LL ~ }); | error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:41:13 + --> $DIR/option_if_let_else.rs:39:13 | LL | let _ = if let Some(ref mut s) = num { | _____________^ @@ -89,7 +89,7 @@ LL ~ }); | error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:50:5 + --> $DIR/option_if_let_else.rs:48:5 | LL | / if let Some(x) = arg { LL | | let y = x * x; @@ -108,7 +108,7 @@ LL + }) | error: use Option::map_or_else instead of an if let/else - --> $DIR/option_if_let_else.rs:63:13 + --> $DIR/option_if_let_else.rs:61:13 | LL | let _ = if let Some(x) = arg { | _____________^ @@ -120,7 +120,7 @@ LL | | }; | |_____^ help: try: `arg.map_or_else(|| side_effect(), |x| x)` error: use Option::map_or_else instead of an if let/else - --> $DIR/option_if_let_else.rs:72:13 + --> $DIR/option_if_let_else.rs:70:13 | LL | let _ = if let Some(x) = arg { | _____________^ @@ -143,13 +143,13 @@ LL ~ }, |x| x * x * x * x); | error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:101:13 + --> $DIR/option_if_let_else.rs:99:13 | LL | let _ = if let Some(x) = optional { x + 2 } else { 5 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `optional.map_or(5, |x| x + 2)` error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:110:13 + --> $DIR/option_if_let_else.rs:108:13 | LL | let _ = if let Some(x) = Some(0) { | _____________^ @@ -171,13 +171,13 @@ LL ~ }); | error: use Option::map_or_else instead of an if let/else - --> $DIR/option_if_let_else.rs:138:13 + --> $DIR/option_if_let_else.rs:136:13 | LL | let _ = if let Some(x) = Some(0) { s.len() + x } else { s.len() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(0).map_or_else(|| s.len(), |x| s.len() + x)` error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:142:13 + --> $DIR/option_if_let_else.rs:140:13 | LL | let _ = if let Some(x) = Some(0) { | _____________^ diff --git a/src/tools/clippy/tests/ui/panic_in_result_fn.rs b/src/tools/clippy/tests/ui/panic_in_result_fn.rs index 3d3c19a1be..e75eb1b6ea 100644 --- a/src/tools/clippy/tests/ui/panic_in_result_fn.rs +++ b/src/tools/clippy/tests/ui/panic_in_result_fn.rs @@ -1,6 +1,5 @@ #![warn(clippy::panic_in_result_fn)] #![allow(clippy::unnecessary_wraps)] - struct A; impl A { diff --git a/src/tools/clippy/tests/ui/panic_in_result_fn.stderr b/src/tools/clippy/tests/ui/panic_in_result_fn.stderr index f56c2d03c6..78d09b8b21 100644 --- a/src/tools/clippy/tests/ui/panic_in_result_fn.stderr +++ b/src/tools/clippy/tests/ui/panic_in_result_fn.stderr @@ -1,5 +1,5 @@ error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result` - --> $DIR/panic_in_result_fn.rs:7:5 + --> $DIR/panic_in_result_fn.rs:6:5 | LL | / fn result_with_panic() -> Result<bool, String> // should emit lint LL | | { @@ -10,14 +10,14 @@ 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.rs:9:9 + --> $DIR/panic_in_result_fn.rs:8:9 | LL | panic!("error"); | ^^^^^^^^^^^^^^^ - = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `$crate::panic::panic_2021` (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.rs:12:5 + --> $DIR/panic_in_result_fn.rs:11:5 | LL | / fn result_with_unimplemented() -> Result<bool, String> // should emit lint LL | | { @@ -27,14 +27,14 @@ 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.rs:14:9 + --> $DIR/panic_in_result_fn.rs:13:9 | LL | unimplemented!(); | ^^^^^^^^^^^^^^^^ = note: this error originates in the macro `unimplemented` (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.rs:17:5 + --> $DIR/panic_in_result_fn.rs:16:5 | LL | / fn result_with_unreachable() -> Result<bool, String> // should emit lint LL | | { @@ -44,14 +44,14 @@ 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.rs:19:9 + --> $DIR/panic_in_result_fn.rs:18:9 | LL | unreachable!(); | ^^^^^^^^^^^^^^ = note: this error originates in the macro `unreachable` (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.rs:22:5 + --> $DIR/panic_in_result_fn.rs:21:5 | LL | / fn result_with_todo() -> Result<bool, String> // should emit lint LL | | { @@ -61,14 +61,14 @@ 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.rs:24:9 + --> $DIR/panic_in_result_fn.rs:23:9 | LL | todo!("Finish this"); | ^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `todo` (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.rs:53:1 + --> $DIR/panic_in_result_fn.rs:52:1 | LL | / fn function_result_with_panic() -> Result<bool, String> // should emit lint LL | | { @@ -78,14 +78,14 @@ 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.rs:55:5 + --> $DIR/panic_in_result_fn.rs:54:5 | LL | panic!("error"); | ^^^^^^^^^^^^^^^ - = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `$crate::panic::panic_2021` (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.rs:68:1 + --> $DIR/panic_in_result_fn.rs:67:1 | LL | / fn main() -> Result<(), String> { LL | | todo!("finish main method"); @@ -95,7 +95,7 @@ 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.rs:69:5 + --> $DIR/panic_in_result_fn.rs:68:5 | LL | todo!("finish main method"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/ptr_arg.rs b/src/tools/clippy/tests/ui/ptr_arg.rs index 06370dfce6..67bfef06a0 100644 --- a/src/tools/clippy/tests/ui/ptr_arg.rs +++ b/src/tools/clippy/tests/ui/ptr_arg.rs @@ -155,3 +155,7 @@ mod issue6509 { let _ = str.clone().clone(); } } + +// No error for types behind an alias (#7699) +type A = Vec<u8>; +fn aliased(a: &A) {} diff --git a/src/tools/clippy/tests/ui/question_mark.fixed b/src/tools/clippy/tests/ui/question_mark.fixed index 0b5746cb52..e93469e5f5 100644 --- a/src/tools/clippy/tests/ui/question_mark.fixed +++ b/src/tools/clippy/tests/ui/question_mark.fixed @@ -104,6 +104,38 @@ fn func() -> Option<i32> { Some(0) } +fn func_returning_result() -> Result<i32, i32> { + Ok(1) +} + +fn result_func(x: Result<i32, i32>) -> Result<i32, i32> { + let _ = x?; + + x?; + + // No warning + let y = if let Ok(x) = x { + x + } else { + return Err(0); + }; + + // issue #7859 + // no warning + let _ = if let Ok(x) = func_returning_result() { + x + } else { + return Err(0); + }; + + // no warning + if func_returning_result().is_err() { + return func_returning_result(); + } + + Ok(y) +} + fn main() { some_func(Some(42)); some_func(None); @@ -123,4 +155,6 @@ fn main() { returns_something_similar_to_option(so); func(); + + let _ = result_func(Ok(42)); } diff --git a/src/tools/clippy/tests/ui/question_mark.rs b/src/tools/clippy/tests/ui/question_mark.rs index 0f0825c933..dd179e9bee 100644 --- a/src/tools/clippy/tests/ui/question_mark.rs +++ b/src/tools/clippy/tests/ui/question_mark.rs @@ -134,6 +134,40 @@ fn func() -> Option<i32> { Some(0) } +fn func_returning_result() -> Result<i32, i32> { + Ok(1) +} + +fn result_func(x: Result<i32, i32>) -> Result<i32, i32> { + let _ = if let Ok(x) = x { x } else { return x }; + + if x.is_err() { + return x; + } + + // No warning + let y = if let Ok(x) = x { + x + } else { + return Err(0); + }; + + // issue #7859 + // no warning + let _ = if let Ok(x) = func_returning_result() { + x + } else { + return Err(0); + }; + + // no warning + if func_returning_result().is_err() { + return func_returning_result(); + } + + Ok(y) +} + fn main() { some_func(Some(42)); some_func(None); @@ -153,4 +187,6 @@ fn main() { returns_something_similar_to_option(so); func(); + + let _ = result_func(Ok(42)); } diff --git a/src/tools/clippy/tests/ui/question_mark.stderr b/src/tools/clippy/tests/ui/question_mark.stderr index 6f330cfa38..8d782b71dd 100644 --- a/src/tools/clippy/tests/ui/question_mark.stderr +++ b/src/tools/clippy/tests/ui/question_mark.stderr @@ -100,5 +100,19 @@ LL | | return None; LL | | } | |_____^ help: replace it with: `f()?;` -error: aborting due to 11 previous errors +error: this if-let-else may be rewritten with the `?` operator + --> $DIR/question_mark.rs:142:13 + | +LL | let _ = if let Ok(x) = x { x } else { return x }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `x?` + +error: this block may be rewritten with the `?` operator + --> $DIR/question_mark.rs:144:5 + | +LL | / if x.is_err() { +LL | | return x; +LL | | } + | |_____^ help: replace it with: `x?;` + +error: aborting due to 13 previous errors diff --git a/src/tools/clippy/tests/ui/redundant_clone.fixed b/src/tools/clippy/tests/ui/redundant_clone.fixed index 2d71108274..16b40dcd90 100644 --- a/src/tools/clippy/tests/ui/redundant_clone.fixed +++ b/src/tools/clippy/tests/ui/redundant_clone.fixed @@ -196,7 +196,7 @@ fn clone_then_move_cloned() { fn foo<F: Fn()>(_: &Alpha, _: F) {} let x = Alpha; // ok, data is moved while the clone is in use. - foo(&x.clone(), move || { + foo(&x, move || { let _ = x; }); diff --git a/src/tools/clippy/tests/ui/redundant_clone.stderr b/src/tools/clippy/tests/ui/redundant_clone.stderr index fbc90493ae..9f59017b26 100644 --- a/src/tools/clippy/tests/ui/redundant_clone.stderr +++ b/src/tools/clippy/tests/ui/redundant_clone.stderr @@ -167,5 +167,17 @@ note: cloned value is neither consumed nor mutated LL | let y = x.clone().join("matthias"); | ^^^^^^^^^ -error: aborting due to 14 previous errors +error: redundant clone + --> $DIR/redundant_clone.rs:199:11 + | +LL | foo(&x.clone(), move || { + | ^^^^^^^^ help: remove this + | +note: this value is dropped without further use + --> $DIR/redundant_clone.rs:199:10 + | +LL | foo(&x.clone(), move || { + | ^ + +error: aborting due to 15 previous errors diff --git a/src/tools/clippy/tests/ui/redundant_closure_call_early.rs b/src/tools/clippy/tests/ui/redundant_closure_call_early.rs index 3dd365620c..5649d8dd14 100644 --- a/src/tools/clippy/tests/ui/redundant_closure_call_early.rs +++ b/src/tools/clippy/tests/ui/redundant_closure_call_early.rs @@ -15,5 +15,6 @@ fn main() { #[allow(clippy::needless_return)] (|| return 2)(); (|| -> Option<i32> { None? })(); + #[allow(clippy::try_err)] (|| -> Result<i32, i32> { Err(2)? })(); } diff --git a/src/tools/clippy/tests/ui/redundant_else.rs b/src/tools/clippy/tests/ui/redundant_else.rs index 737c8a9f8d..e8a6e940c0 100644 --- a/src/tools/clippy/tests/ui/redundant_else.rs +++ b/src/tools/clippy/tests/ui/redundant_else.rs @@ -1,5 +1,5 @@ #![warn(clippy::redundant_else)] -#![allow(clippy::needless_return)] +#![allow(clippy::needless_return, clippy::if_same_then_else)] fn main() { loop { @@ -105,7 +105,7 @@ fn main() { 1 }; // assign - let a; + let mut a; a = if foo() { return; } else { diff --git a/src/tools/clippy/tests/ui/ref_binding_to_reference.rs b/src/tools/clippy/tests/ui/ref_binding_to_reference.rs index cd6db8ddc8..fe742a4c2f 100644 --- a/src/tools/clippy/tests/ui/ref_binding_to_reference.rs +++ b/src/tools/clippy/tests/ui/ref_binding_to_reference.rs @@ -1,4 +1,3 @@ -// edition:2018 // FIXME: run-rustfix waiting on multi-span suggestions #![warn(clippy::ref_binding_to_reference)] diff --git a/src/tools/clippy/tests/ui/ref_binding_to_reference.stderr b/src/tools/clippy/tests/ui/ref_binding_to_reference.stderr index eb36cd516a..c5856e15fa 100644 --- a/src/tools/clippy/tests/ui/ref_binding_to_reference.stderr +++ b/src/tools/clippy/tests/ui/ref_binding_to_reference.stderr @@ -1,5 +1,5 @@ error: this pattern creates a reference to a reference - --> $DIR/ref_binding_to_reference.rs:31:14 + --> $DIR/ref_binding_to_reference.rs:30:14 | LL | Some(ref x) => x, | ^^^^^ @@ -11,7 +11,7 @@ LL | Some(x) => &x, | ~ ~~ error: this pattern creates a reference to a reference - --> $DIR/ref_binding_to_reference.rs:37:14 + --> $DIR/ref_binding_to_reference.rs:36:14 | LL | Some(ref x) => { | ^^^^^ @@ -25,7 +25,7 @@ LL ~ &x | error: this pattern creates a reference to a reference - --> $DIR/ref_binding_to_reference.rs:47:14 + --> $DIR/ref_binding_to_reference.rs:46:14 | LL | Some(ref x) => m2!(x), | ^^^^^ @@ -36,7 +36,7 @@ LL | Some(x) => m2!(&x), | ~ ~~ error: this pattern creates a reference to a reference - --> $DIR/ref_binding_to_reference.rs:52:15 + --> $DIR/ref_binding_to_reference.rs:51:15 | LL | let _ = |&ref x: &&String| { | ^^^^^ @@ -48,7 +48,7 @@ LL ~ let _: &&String = &x; | error: this pattern creates a reference to a reference - --> $DIR/ref_binding_to_reference.rs:58:12 + --> $DIR/ref_binding_to_reference.rs:57:12 | LL | fn f2<'a>(&ref x: &&'a String) -> &'a String { | ^^^^^ @@ -61,7 +61,7 @@ LL ~ x | error: this pattern creates a reference to a reference - --> $DIR/ref_binding_to_reference.rs:65:11 + --> $DIR/ref_binding_to_reference.rs:64:11 | LL | fn f(&ref x: &&String) { | ^^^^^ @@ -73,7 +73,7 @@ LL ~ let _: &&String = &x; | error: this pattern creates a reference to a reference - --> $DIR/ref_binding_to_reference.rs:73:11 + --> $DIR/ref_binding_to_reference.rs:72:11 | LL | fn f(&ref x: &&String) { | ^^^^^ diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed index a66c2e587c..cc295b509b 100644 --- a/src/tools/clippy/tests/ui/rename.fixed +++ b/src/tools/clippy/tests/ui/rename.fixed @@ -6,15 +6,58 @@ #![allow(clippy::module_name_repetitions)] #![allow(clippy::new_without_default)] #![allow(clippy::redundant_static_lifetimes)] +#![allow(clippy::bind_instead_of_map)] +#![allow(clippy::box_collection)] +#![allow(clippy::blocks_in_if_conditions)] +#![allow(clippy::map_unwrap_or)] +#![allow(clippy::unwrap_used)] +#![allow(clippy::expect_used)] +#![allow(clippy::for_loops_over_fallibles)] +#![allow(clippy::useless_conversion)] +#![allow(clippy::invisible_characters)] +#![allow(clippy::single_char_add_str)] +#![allow(clippy::match_result_ok)] +// uplifted lints +#![allow(invalid_value)] +#![allow(array_into_iter)] +#![allow(unused_labels)] +#![allow(drop_bounds)] +#![allow(temporary_cstring_as_ptr)] +#![allow(non_fmt_panics)] +#![allow(unknown_lints)] +#![allow(invalid_atomic_ordering)] +#![allow(enum_intrinsics_non_enums)] // warn for the old lint name here, to test if the renaming worked +#![warn(clippy::module_name_repetitions)] +#![warn(clippy::new_without_default)] +#![warn(clippy::redundant_static_lifetimes)] #![warn(clippy::cognitive_complexity)] +#![warn(clippy::bind_instead_of_map)] +#![warn(clippy::box_collection)] +#![warn(clippy::blocks_in_if_conditions)] +#![warn(clippy::blocks_in_if_conditions)] +#![warn(clippy::map_unwrap_or)] +#![warn(clippy::map_unwrap_or)] +#![warn(clippy::map_unwrap_or)] +#![warn(clippy::unwrap_used)] +#![warn(clippy::unwrap_used)] +#![warn(clippy::expect_used)] +#![warn(clippy::expect_used)] +#![warn(clippy::for_loops_over_fallibles)] +#![warn(clippy::for_loops_over_fallibles)] +#![warn(clippy::useless_conversion)] +#![warn(clippy::invisible_characters)] +#![warn(clippy::single_char_add_str)] +#![warn(clippy::match_result_ok)] +// uplifted lints +#![warn(invalid_value)] +#![warn(array_into_iter)] +#![warn(unused_labels)] +#![warn(drop_bounds)] +#![warn(temporary_cstring_as_ptr)] +#![warn(non_fmt_panics)] +#![warn(unknown_lints)] +#![warn(invalid_atomic_ordering)] #![warn(enum_intrinsics_non_enums)] -#[warn(clippy::module_name_repetitions)] fn main() {} - -#[warn(clippy::new_without_default)] -struct Foo; - -#[warn(clippy::redundant_static_lifetimes)] -fn foo() {} diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs index fa81201a2d..377075c024 100644 --- a/src/tools/clippy/tests/ui/rename.rs +++ b/src/tools/clippy/tests/ui/rename.rs @@ -6,15 +6,58 @@ #![allow(clippy::module_name_repetitions)] #![allow(clippy::new_without_default)] #![allow(clippy::redundant_static_lifetimes)] +#![allow(clippy::bind_instead_of_map)] +#![allow(clippy::box_collection)] +#![allow(clippy::blocks_in_if_conditions)] +#![allow(clippy::map_unwrap_or)] +#![allow(clippy::unwrap_used)] +#![allow(clippy::expect_used)] +#![allow(clippy::for_loops_over_fallibles)] +#![allow(clippy::useless_conversion)] +#![allow(clippy::invisible_characters)] +#![allow(clippy::single_char_add_str)] +#![allow(clippy::match_result_ok)] +// uplifted lints +#![allow(invalid_value)] +#![allow(array_into_iter)] +#![allow(unused_labels)] +#![allow(drop_bounds)] +#![allow(temporary_cstring_as_ptr)] +#![allow(non_fmt_panics)] +#![allow(unknown_lints)] +#![allow(invalid_atomic_ordering)] +#![allow(enum_intrinsics_non_enums)] // warn for the old lint name here, to test if the renaming worked +#![warn(clippy::stutter)] +#![warn(clippy::new_without_default_derive)] +#![warn(clippy::const_static_lifetime)] #![warn(clippy::cyclomatic_complexity)] +#![warn(clippy::option_and_then_some)] +#![warn(clippy::box_vec)] +#![warn(clippy::block_in_if_condition_expr)] +#![warn(clippy::block_in_if_condition_stmt)] +#![warn(clippy::option_map_unwrap_or)] +#![warn(clippy::option_map_unwrap_or_else)] +#![warn(clippy::result_map_unwrap_or_else)] +#![warn(clippy::option_unwrap_used)] +#![warn(clippy::result_unwrap_used)] +#![warn(clippy::option_expect_used)] +#![warn(clippy::result_expect_used)] +#![warn(clippy::for_loop_over_option)] +#![warn(clippy::for_loop_over_result)] +#![warn(clippy::identity_conversion)] +#![warn(clippy::zero_width_space)] +#![warn(clippy::single_char_push_str)] +#![warn(clippy::if_let_some_result)] +// uplifted lints +#![warn(clippy::invalid_ref)] +#![warn(clippy::into_iter_on_array)] +#![warn(clippy::unused_label)] +#![warn(clippy::drop_bounds)] +#![warn(clippy::temporary_cstring_as_ptr)] +#![warn(clippy::panic_params)] +#![warn(clippy::unknown_clippy_lints)] +#![warn(clippy::invalid_atomic_ordering)] #![warn(clippy::mem_discriminant_non_enum)] -#[warn(clippy::stutter)] fn main() {} - -#[warn(clippy::new_without_default_derive)] -struct Foo; - -#[warn(clippy::const_static_lifetime)] -fn foo() {} diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr index 05c7854074..d720f10d11 100644 --- a/src/tools/clippy/tests/ui/rename.stderr +++ b/src/tools/clippy/tests/ui/rename.stderr @@ -1,34 +1,184 @@ +error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions` + --> $DIR/rename.rs:31:9 + | +LL | #![warn(clippy::stutter)] + | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions` + | + = note: `-D renamed-and-removed-lints` implied by `-D warnings` + +error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default` + --> $DIR/rename.rs:32:9 + | +LL | #![warn(clippy::new_without_default_derive)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default` + +error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes` + --> $DIR/rename.rs:33:9 + | +LL | #![warn(clippy::const_static_lifetime)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes` + error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity` - --> $DIR/rename.rs:10:9 + --> $DIR/rename.rs:34:9 | LL | #![warn(clippy::cyclomatic_complexity)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity` + +error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map` + --> $DIR/rename.rs:35:9 | - = note: `-D renamed-and-removed-lints` implied by `-D warnings` +LL | #![warn(clippy::option_and_then_some)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map` -error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums` - --> $DIR/rename.rs:11:9 +error: lint `clippy::box_vec` has been renamed to `clippy::box_collection` + --> $DIR/rename.rs:36:9 | -LL | #![warn(clippy::mem_discriminant_non_enum)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums` +LL | #![warn(clippy::box_vec)] + | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection` -error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions` - --> $DIR/rename.rs:13:8 +error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions` + --> $DIR/rename.rs:37:9 | -LL | #[warn(clippy::stutter)] - | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions` +LL | #![warn(clippy::block_in_if_condition_expr)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions` -error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default` - --> $DIR/rename.rs:16:8 +error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions` + --> $DIR/rename.rs:38:9 | -LL | #[warn(clippy::new_without_default_derive)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default` +LL | #![warn(clippy::block_in_if_condition_stmt)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions` -error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes` - --> $DIR/rename.rs:19:8 +error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or` + --> $DIR/rename.rs:39:9 + | +LL | #![warn(clippy::option_map_unwrap_or)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` + +error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or` + --> $DIR/rename.rs:40:9 + | +LL | #![warn(clippy::option_map_unwrap_or_else)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` + +error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or` + --> $DIR/rename.rs:41:9 + | +LL | #![warn(clippy::result_map_unwrap_or_else)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` + +error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used` + --> $DIR/rename.rs:42:9 + | +LL | #![warn(clippy::option_unwrap_used)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used` + +error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used` + --> $DIR/rename.rs:43:9 + | +LL | #![warn(clippy::result_unwrap_used)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used` + +error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used` + --> $DIR/rename.rs:44:9 + | +LL | #![warn(clippy::option_expect_used)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used` + +error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used` + --> $DIR/rename.rs:45:9 + | +LL | #![warn(clippy::result_expect_used)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used` + +error: lint `clippy::for_loop_over_option` has been renamed to `clippy::for_loops_over_fallibles` + --> $DIR/rename.rs:46:9 + | +LL | #![warn(clippy::for_loop_over_option)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::for_loops_over_fallibles` + +error: lint `clippy::for_loop_over_result` has been renamed to `clippy::for_loops_over_fallibles` + --> $DIR/rename.rs:47:9 + | +LL | #![warn(clippy::for_loop_over_result)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::for_loops_over_fallibles` + +error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion` + --> $DIR/rename.rs:48:9 + | +LL | #![warn(clippy::identity_conversion)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion` + +error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters` + --> $DIR/rename.rs:49:9 + | +LL | #![warn(clippy::zero_width_space)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters` + +error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str` + --> $DIR/rename.rs:50:9 + | +LL | #![warn(clippy::single_char_push_str)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str` + +error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok` + --> $DIR/rename.rs:51:9 + | +LL | #![warn(clippy::if_let_some_result)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok` + +error: lint `clippy::invalid_ref` has been renamed to `invalid_value` + --> $DIR/rename.rs:53:9 + | +LL | #![warn(clippy::invalid_ref)] + | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value` + +error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter` + --> $DIR/rename.rs:54:9 + | +LL | #![warn(clippy::into_iter_on_array)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter` + +error: lint `clippy::unused_label` has been renamed to `unused_labels` + --> $DIR/rename.rs:55:9 + | +LL | #![warn(clippy::unused_label)] + | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels` + +error: lint `clippy::drop_bounds` has been renamed to `drop_bounds` + --> $DIR/rename.rs:56:9 + | +LL | #![warn(clippy::drop_bounds)] + | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds` + +error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr` + --> $DIR/rename.rs:57:9 + | +LL | #![warn(clippy::temporary_cstring_as_ptr)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr` + +error: lint `clippy::panic_params` has been renamed to `non_fmt_panics` + --> $DIR/rename.rs:58:9 + | +LL | #![warn(clippy::panic_params)] + | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics` + +error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints` + --> $DIR/rename.rs:59:9 + | +LL | #![warn(clippy::unknown_clippy_lints)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints` + +error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering` + --> $DIR/rename.rs:60:9 + | +LL | #![warn(clippy::invalid_atomic_ordering)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering` + +error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums` + --> $DIR/rename.rs:61:9 | -LL | #[warn(clippy::const_static_lifetime)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes` +LL | #![warn(clippy::mem_discriminant_non_enum)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums` -error: aborting due to 5 previous errors +error: aborting due to 30 previous errors diff --git a/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs b/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs index 9644a23296..7a45f1b18d 100644 --- a/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs +++ b/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs @@ -98,3 +98,15 @@ fn unsafe_checks() { let mut s = MaybeUninit::<String>::uninit(); let _d = || unsafe { ptr::drop_in_place(s.as_mut_ptr()) }; } + +// Issue #7768 +#[rustfmt::skip] +fn macro_with_semicolon() { + macro_rules! repro { + () => { + while false { + } + }; + } + repro!(); +} diff --git a/src/tools/clippy/tests/ui/shadow.rs b/src/tools/clippy/tests/ui/shadow.rs index 02e838456d..55caef59f7 100644 --- a/src/tools/clippy/tests/ui/shadow.rs +++ b/src/tools/clippy/tests/ui/shadow.rs @@ -17,6 +17,11 @@ fn shadow_reuse() -> Option<()> { let x = foo(x); let x = || x; let x = Some(1).map(|_| x)?; + let y = 1; + let y = match y { + 1 => 2, + _ => 3, + }; None } diff --git a/src/tools/clippy/tests/ui/shadow.stderr b/src/tools/clippy/tests/ui/shadow.stderr index 8b60e072c9..feed6e1ba8 100644 --- a/src/tools/clippy/tests/ui/shadow.stderr +++ b/src/tools/clippy/tests/ui/shadow.stderr @@ -47,7 +47,7 @@ note: previous binding is here LL | let x = &mut x; | ^ -error: `x` is shadowed by `x.0` which reuses the original value +error: `x` is shadowed --> $DIR/shadow.rs:13:9 | LL | let x = x.0; @@ -60,7 +60,7 @@ note: previous binding is here LL | let x = ([[0]], ()); | ^ -error: `x` is shadowed by `x[0]` which reuses the original value +error: `x` is shadowed --> $DIR/shadow.rs:14:9 | LL | let x = x[0]; @@ -72,7 +72,7 @@ note: previous binding is here LL | let x = x.0; | ^ -error: `x` is shadowed by `x` which reuses the original value +error: `x` is shadowed --> $DIR/shadow.rs:15:10 | LL | let [x] = x; @@ -84,7 +84,7 @@ note: previous binding is here LL | let x = x[0]; | ^ -error: `x` is shadowed by `Some(x)` which reuses the original value +error: `x` is shadowed --> $DIR/shadow.rs:16:9 | LL | let x = Some(x); @@ -96,7 +96,7 @@ note: previous binding is here LL | let [x] = x; | ^ -error: `x` is shadowed by `foo(x)` which reuses the original value +error: `x` is shadowed --> $DIR/shadow.rs:17:9 | LL | let x = foo(x); @@ -108,7 +108,7 @@ note: previous binding is here LL | let x = Some(x); | ^ -error: `x` is shadowed by `|| x` which reuses the original value +error: `x` is shadowed --> $DIR/shadow.rs:18:9 | LL | let x = || x; @@ -120,7 +120,7 @@ note: previous binding is here LL | let x = foo(x); | ^ -error: `x` is shadowed by `Some(1).map(|_| x)?` which reuses the original value +error: `x` is shadowed --> $DIR/shadow.rs:19:9 | LL | let x = Some(1).map(|_| x)?; @@ -132,102 +132,114 @@ note: previous binding is here LL | let x = || x; | ^ +error: `y` is shadowed + --> $DIR/shadow.rs:21:9 + | +LL | let y = match y { + | ^ + | +note: previous binding is here + --> $DIR/shadow.rs:20:9 + | +LL | let y = 1; + | ^ + error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:25:9 + --> $DIR/shadow.rs:30:9 | LL | let x = 2; | ^ | = note: `-D clippy::shadow-unrelated` implied by `-D warnings` note: previous binding is here - --> $DIR/shadow.rs:24:9 + --> $DIR/shadow.rs:29:9 | LL | let x = 1; | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:30:13 + --> $DIR/shadow.rs:35:13 | LL | let x = 1; | ^ | note: previous binding is here - --> $DIR/shadow.rs:29:10 + --> $DIR/shadow.rs:34:10 | LL | fn f(x: u32) { | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:35:14 + --> $DIR/shadow.rs:40:14 | LL | Some(x) => { | ^ | note: previous binding is here - --> $DIR/shadow.rs:32:9 + --> $DIR/shadow.rs:37:9 | LL | let x = 1; | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:36:17 + --> $DIR/shadow.rs:41:17 | LL | let x = 1; | ^ | note: previous binding is here - --> $DIR/shadow.rs:35:14 + --> $DIR/shadow.rs:40:14 | LL | Some(x) => { | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:40:17 + --> $DIR/shadow.rs:45:17 | LL | if let Some(x) = Some(1) {} | ^ | note: previous binding is here - --> $DIR/shadow.rs:32:9 + --> $DIR/shadow.rs:37:9 | LL | let x = 1; | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:41:20 + --> $DIR/shadow.rs:46:20 | LL | while let Some(x) = Some(1) {} | ^ | note: previous binding is here - --> $DIR/shadow.rs:32:9 + --> $DIR/shadow.rs:37:9 | LL | let x = 1; | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:42:15 + --> $DIR/shadow.rs:47:15 | LL | let _ = |[x]: [u32; 1]| { | ^ | note: previous binding is here - --> $DIR/shadow.rs:32:9 + --> $DIR/shadow.rs:37:9 | LL | let x = 1; | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:43:13 + --> $DIR/shadow.rs:48:13 | LL | let x = 1; | ^ | note: previous binding is here - --> $DIR/shadow.rs:42:15 + --> $DIR/shadow.rs:47:15 | LL | let _ = |[x]: [u32; 1]| { | ^ -error: aborting due to 19 previous errors +error: aborting due to 20 previous errors diff --git a/src/tools/clippy/tests/ui/should_impl_trait/corner_cases.rs b/src/tools/clippy/tests/ui/should_impl_trait/corner_cases.rs index a7f8f54f2b..d7e8d02bd1 100644 --- a/src/tools/clippy/tests/ui/should_impl_trait/corner_cases.rs +++ b/src/tools/clippy/tests/ui/should_impl_trait/corner_cases.rs @@ -1,5 +1,3 @@ -// edition:2018 - #![warn(clippy::all, clippy::pedantic)] #![allow( clippy::missing_errors_doc, diff --git a/src/tools/clippy/tests/ui/should_impl_trait/method_list_1.rs b/src/tools/clippy/tests/ui/should_impl_trait/method_list_1.rs index 69a3390b03..ea962f9431 100644 --- a/src/tools/clippy/tests/ui/should_impl_trait/method_list_1.rs +++ b/src/tools/clippy/tests/ui/should_impl_trait/method_list_1.rs @@ -1,5 +1,3 @@ -// edition:2018 - #![warn(clippy::all, clippy::pedantic)] #![allow( clippy::missing_errors_doc, diff --git a/src/tools/clippy/tests/ui/should_impl_trait/method_list_1.stderr b/src/tools/clippy/tests/ui/should_impl_trait/method_list_1.stderr index 86c6394651..bf8b47d562 100644 --- a/src/tools/clippy/tests/ui/should_impl_trait/method_list_1.stderr +++ b/src/tools/clippy/tests/ui/should_impl_trait/method_list_1.stderr @@ -1,5 +1,5 @@ error: method `add` can be confused for the standard trait method `std::ops::Add::add` - --> $DIR/method_list_1.rs:26:5 + --> $DIR/method_list_1.rs:24:5 | LL | / pub fn add(self, other: T) -> T { LL | | unimplemented!() @@ -10,7 +10,7 @@ LL | | } = help: consider implementing the trait `std::ops::Add` or choosing a less ambiguous method name error: method `as_mut` can be confused for the standard trait method `std::convert::AsMut::as_mut` - --> $DIR/method_list_1.rs:30:5 + --> $DIR/method_list_1.rs:28:5 | LL | / pub fn as_mut(&mut self) -> &mut T { LL | | unimplemented!() @@ -20,7 +20,7 @@ LL | | } = help: consider implementing the trait `std::convert::AsMut` or choosing a less ambiguous method name error: method `as_ref` can be confused for the standard trait method `std::convert::AsRef::as_ref` - --> $DIR/method_list_1.rs:34:5 + --> $DIR/method_list_1.rs:32:5 | LL | / pub fn as_ref(&self) -> &T { LL | | unimplemented!() @@ -30,7 +30,7 @@ LL | | } = help: consider implementing the trait `std::convert::AsRef` or choosing a less ambiguous method name error: method `bitand` can be confused for the standard trait method `std::ops::BitAnd::bitand` - --> $DIR/method_list_1.rs:38:5 + --> $DIR/method_list_1.rs:36:5 | LL | / pub fn bitand(self, rhs: T) -> T { LL | | unimplemented!() @@ -40,7 +40,7 @@ LL | | } = help: consider implementing the trait `std::ops::BitAnd` or choosing a less ambiguous method name error: method `bitor` can be confused for the standard trait method `std::ops::BitOr::bitor` - --> $DIR/method_list_1.rs:42:5 + --> $DIR/method_list_1.rs:40:5 | LL | / pub fn bitor(self, rhs: Self) -> Self { LL | | unimplemented!() @@ -50,7 +50,7 @@ LL | | } = help: consider implementing the trait `std::ops::BitOr` or choosing a less ambiguous method name error: method `bitxor` can be confused for the standard trait method `std::ops::BitXor::bitxor` - --> $DIR/method_list_1.rs:46:5 + --> $DIR/method_list_1.rs:44:5 | LL | / pub fn bitxor(self, rhs: Self) -> Self { LL | | unimplemented!() @@ -60,7 +60,7 @@ LL | | } = help: consider implementing the trait `std::ops::BitXor` or choosing a less ambiguous method name error: method `borrow` can be confused for the standard trait method `std::borrow::Borrow::borrow` - --> $DIR/method_list_1.rs:50:5 + --> $DIR/method_list_1.rs:48:5 | LL | / pub fn borrow(&self) -> &str { LL | | unimplemented!() @@ -70,7 +70,7 @@ LL | | } = help: consider implementing the trait `std::borrow::Borrow` or choosing a less ambiguous method name error: method `borrow_mut` can be confused for the standard trait method `std::borrow::BorrowMut::borrow_mut` - --> $DIR/method_list_1.rs:54:5 + --> $DIR/method_list_1.rs:52:5 | LL | / pub fn borrow_mut(&mut self) -> &mut str { LL | | unimplemented!() @@ -80,7 +80,7 @@ LL | | } = help: consider implementing the trait `std::borrow::BorrowMut` or choosing a less ambiguous method name error: method `clone` can be confused for the standard trait method `std::clone::Clone::clone` - --> $DIR/method_list_1.rs:58:5 + --> $DIR/method_list_1.rs:56:5 | LL | / pub fn clone(&self) -> Self { LL | | unimplemented!() @@ -90,7 +90,7 @@ LL | | } = help: consider implementing the trait `std::clone::Clone` or choosing a less ambiguous method name error: method `cmp` can be confused for the standard trait method `std::cmp::Ord::cmp` - --> $DIR/method_list_1.rs:62:5 + --> $DIR/method_list_1.rs:60:5 | LL | / pub fn cmp(&self, other: &Self) -> Self { LL | | unimplemented!() @@ -100,7 +100,7 @@ LL | | } = help: consider implementing the trait `std::cmp::Ord` or choosing a less ambiguous method name error: method `deref` can be confused for the standard trait method `std::ops::Deref::deref` - --> $DIR/method_list_1.rs:70:5 + --> $DIR/method_list_1.rs:68:5 | LL | / pub fn deref(&self) -> &Self { LL | | unimplemented!() @@ -110,7 +110,7 @@ LL | | } = help: consider implementing the trait `std::ops::Deref` or choosing a less ambiguous method name error: method `deref_mut` can be confused for the standard trait method `std::ops::DerefMut::deref_mut` - --> $DIR/method_list_1.rs:74:5 + --> $DIR/method_list_1.rs:72:5 | LL | / pub fn deref_mut(&mut self) -> &mut Self { LL | | unimplemented!() @@ -120,7 +120,7 @@ LL | | } = help: consider implementing the trait `std::ops::DerefMut` or choosing a less ambiguous method name error: method `div` can be confused for the standard trait method `std::ops::Div::div` - --> $DIR/method_list_1.rs:78:5 + --> $DIR/method_list_1.rs:76:5 | LL | / pub fn div(self, rhs: Self) -> Self { LL | | unimplemented!() @@ -130,7 +130,7 @@ LL | | } = help: consider implementing the trait `std::ops::Div` or choosing a less ambiguous method name error: method `drop` can be confused for the standard trait method `std::ops::Drop::drop` - --> $DIR/method_list_1.rs:82:5 + --> $DIR/method_list_1.rs:80:5 | LL | / pub fn drop(&mut self) { LL | | unimplemented!() diff --git a/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.rs b/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.rs index 2cdc1a06fe..b663568806 100644 --- a/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.rs +++ b/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.rs @@ -1,5 +1,3 @@ -// edition:2018 - #![warn(clippy::all, clippy::pedantic)] #![allow( clippy::missing_errors_doc, diff --git a/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.stderr b/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.stderr index 0142e29910..426fe3b1ad 100644 --- a/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.stderr +++ b/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.stderr @@ -1,5 +1,5 @@ error: method `eq` can be confused for the standard trait method `std::cmp::PartialEq::eq` - --> $DIR/method_list_2.rs:27:5 + --> $DIR/method_list_2.rs:25:5 | LL | / pub fn eq(&self, other: &Self) -> bool { LL | | unimplemented!() @@ -10,7 +10,7 @@ LL | | } = help: consider implementing the trait `std::cmp::PartialEq` or choosing a less ambiguous method name error: method `from_iter` can be confused for the standard trait method `std::iter::FromIterator::from_iter` - --> $DIR/method_list_2.rs:31:5 + --> $DIR/method_list_2.rs:29:5 | LL | / pub fn from_iter<T>(iter: T) -> Self { LL | | unimplemented!() @@ -20,7 +20,7 @@ LL | | } = help: consider implementing the trait `std::iter::FromIterator` or choosing a less ambiguous method name error: method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str` - --> $DIR/method_list_2.rs:35:5 + --> $DIR/method_list_2.rs:33:5 | LL | / pub fn from_str(s: &str) -> Result<Self, Self> { LL | | unimplemented!() @@ -30,7 +30,7 @@ LL | | } = help: consider implementing the trait `std::str::FromStr` or choosing a less ambiguous method name error: method `hash` can be confused for the standard trait method `std::hash::Hash::hash` - --> $DIR/method_list_2.rs:39:5 + --> $DIR/method_list_2.rs:37:5 | LL | / pub fn hash(&self, state: &mut T) { LL | | unimplemented!() @@ -40,7 +40,7 @@ LL | | } = help: consider implementing the trait `std::hash::Hash` or choosing a less ambiguous method name error: method `index` can be confused for the standard trait method `std::ops::Index::index` - --> $DIR/method_list_2.rs:43:5 + --> $DIR/method_list_2.rs:41:5 | LL | / pub fn index(&self, index: usize) -> &Self { LL | | unimplemented!() @@ -50,7 +50,7 @@ LL | | } = help: consider implementing the trait `std::ops::Index` or choosing a less ambiguous method name error: method `index_mut` can be confused for the standard trait method `std::ops::IndexMut::index_mut` - --> $DIR/method_list_2.rs:47:5 + --> $DIR/method_list_2.rs:45:5 | LL | / pub fn index_mut(&mut self, index: usize) -> &mut Self { LL | | unimplemented!() @@ -60,7 +60,7 @@ LL | | } = help: consider implementing the trait `std::ops::IndexMut` or choosing a less ambiguous method name error: method `into_iter` can be confused for the standard trait method `std::iter::IntoIterator::into_iter` - --> $DIR/method_list_2.rs:51:5 + --> $DIR/method_list_2.rs:49:5 | LL | / pub fn into_iter(self) -> Self { LL | | unimplemented!() @@ -70,7 +70,7 @@ LL | | } = help: consider implementing the trait `std::iter::IntoIterator` or choosing a less ambiguous method name error: method `mul` can be confused for the standard trait method `std::ops::Mul::mul` - --> $DIR/method_list_2.rs:55:5 + --> $DIR/method_list_2.rs:53:5 | LL | / pub fn mul(self, rhs: Self) -> Self { LL | | unimplemented!() @@ -80,7 +80,7 @@ LL | | } = help: consider implementing the trait `std::ops::Mul` or choosing a less ambiguous method name error: method `neg` can be confused for the standard trait method `std::ops::Neg::neg` - --> $DIR/method_list_2.rs:59:5 + --> $DIR/method_list_2.rs:57:5 | LL | / pub fn neg(self) -> Self { LL | | unimplemented!() @@ -90,7 +90,7 @@ LL | | } = help: consider implementing the trait `std::ops::Neg` or choosing a less ambiguous method name error: method `next` can be confused for the standard trait method `std::iter::Iterator::next` - --> $DIR/method_list_2.rs:63:5 + --> $DIR/method_list_2.rs:61:5 | LL | / pub fn next(&mut self) -> Option<Self> { LL | | unimplemented!() @@ -100,7 +100,7 @@ LL | | } = help: consider implementing the trait `std::iter::Iterator` or choosing a less ambiguous method name error: method `not` can be confused for the standard trait method `std::ops::Not::not` - --> $DIR/method_list_2.rs:67:5 + --> $DIR/method_list_2.rs:65:5 | LL | / pub fn not(self) -> Self { LL | | unimplemented!() @@ -110,7 +110,7 @@ LL | | } = help: consider implementing the trait `std::ops::Not` or choosing a less ambiguous method name error: method `rem` can be confused for the standard trait method `std::ops::Rem::rem` - --> $DIR/method_list_2.rs:71:5 + --> $DIR/method_list_2.rs:69:5 | LL | / pub fn rem(self, rhs: Self) -> Self { LL | | unimplemented!() @@ -120,7 +120,7 @@ LL | | } = help: consider implementing the trait `std::ops::Rem` or choosing a less ambiguous method name error: method `shl` can be confused for the standard trait method `std::ops::Shl::shl` - --> $DIR/method_list_2.rs:75:5 + --> $DIR/method_list_2.rs:73:5 | LL | / pub fn shl(self, rhs: Self) -> Self { LL | | unimplemented!() @@ -130,7 +130,7 @@ LL | | } = help: consider implementing the trait `std::ops::Shl` or choosing a less ambiguous method name error: method `shr` can be confused for the standard trait method `std::ops::Shr::shr` - --> $DIR/method_list_2.rs:79:5 + --> $DIR/method_list_2.rs:77:5 | LL | / pub fn shr(self, rhs: Self) -> Self { LL | | unimplemented!() @@ -140,7 +140,7 @@ LL | | } = help: consider implementing the trait `std::ops::Shr` or choosing a less ambiguous method name error: method `sub` can be confused for the standard trait method `std::ops::Sub::sub` - --> $DIR/method_list_2.rs:83:5 + --> $DIR/method_list_2.rs:81:5 | LL | / pub fn sub(self, rhs: Self) -> Self { LL | | unimplemented!() diff --git a/src/tools/clippy/tests/ui/similar_names.rs b/src/tools/clippy/tests/ui/similar_names.rs index daa0734145..76f6ce9ee6 100644 --- a/src/tools/clippy/tests/ui/similar_names.rs +++ b/src/tools/clippy/tests/ui/similar_names.rs @@ -1,5 +1,10 @@ #![warn(clippy::similar_names)] -#![allow(unused, clippy::println_empty_string)] +#![allow( + unused, + clippy::println_empty_string, + clippy::empty_loop, + clippy::diverging_sub_expression +)] struct Foo { apple: i32, diff --git a/src/tools/clippy/tests/ui/similar_names.stderr b/src/tools/clippy/tests/ui/similar_names.stderr index f621595aba..faf572b0c6 100644 --- a/src/tools/clippy/tests/ui/similar_names.stderr +++ b/src/tools/clippy/tests/ui/similar_names.stderr @@ -1,84 +1,84 @@ error: binding's name is too similar to existing binding - --> $DIR/similar_names.rs:15:9 + --> $DIR/similar_names.rs:20:9 | LL | let bpple: i32; | ^^^^^ | = note: `-D clippy::similar-names` implied by `-D warnings` note: existing binding defined here - --> $DIR/similar_names.rs:13:9 + --> $DIR/similar_names.rs:18:9 | LL | let apple: i32; | ^^^^^ error: binding's name is too similar to existing binding - --> $DIR/similar_names.rs:17:9 + --> $DIR/similar_names.rs:22:9 | LL | let cpple: i32; | ^^^^^ | note: existing binding defined here - --> $DIR/similar_names.rs:13:9 + --> $DIR/similar_names.rs:18:9 | LL | let apple: i32; | ^^^^^ error: binding's name is too similar to existing binding - --> $DIR/similar_names.rs:41:9 + --> $DIR/similar_names.rs:46:9 | LL | let bluby: i32; | ^^^^^ | note: existing binding defined here - --> $DIR/similar_names.rs:40:9 + --> $DIR/similar_names.rs:45:9 | LL | let blubx: i32; | ^^^^^ error: binding's name is too similar to existing binding - --> $DIR/similar_names.rs:45:9 + --> $DIR/similar_names.rs:50:9 | LL | let coke: i32; | ^^^^ | note: existing binding defined here - --> $DIR/similar_names.rs:43:9 + --> $DIR/similar_names.rs:48:9 | LL | let cake: i32; | ^^^^ error: binding's name is too similar to existing binding - --> $DIR/similar_names.rs:63:9 + --> $DIR/similar_names.rs:68:9 | LL | let xyzeabc: i32; | ^^^^^^^ | note: existing binding defined here - --> $DIR/similar_names.rs:61:9 + --> $DIR/similar_names.rs:66:9 | LL | let xyz1abc: i32; | ^^^^^^^ error: binding's name is too similar to existing binding - --> $DIR/similar_names.rs:67:9 + --> $DIR/similar_names.rs:72:9 | LL | let parsee: i32; | ^^^^^^ | note: existing binding defined here - --> $DIR/similar_names.rs:65:9 + --> $DIR/similar_names.rs:70:9 | LL | let parser: i32; | ^^^^^^ error: binding's name is too similar to existing binding - --> $DIR/similar_names.rs:88:16 + --> $DIR/similar_names.rs:93:16 | LL | bpple: sprang, | ^^^^^^ | note: existing binding defined here - --> $DIR/similar_names.rs:87:16 + --> $DIR/similar_names.rs:92:16 | LL | apple: spring, | ^^^^^^ 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 f66b445b7b..4c40739d6f 100644 --- a/src/tools/clippy/tests/ui/single_component_path_imports.fixed +++ b/src/tools/clippy/tests/ui/single_component_path_imports.fixed @@ -1,5 +1,4 @@ // run-rustfix -// edition:2018 #![warn(clippy::single_component_path_imports)] #![allow(unused_imports)] 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 09d4865859..9280bab3c7 100644 --- a/src/tools/clippy/tests/ui/single_component_path_imports.rs +++ b/src/tools/clippy/tests/ui/single_component_path_imports.rs @@ -1,5 +1,4 @@ // run-rustfix -// edition:2018 #![warn(clippy::single_component_path_imports)] #![allow(unused_imports)] 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 7005fa8f12..509c88ac25 100644 --- a/src/tools/clippy/tests/ui/single_component_path_imports.stderr +++ b/src/tools/clippy/tests/ui/single_component_path_imports.stderr @@ -1,5 +1,5 @@ error: this import is redundant - --> $DIR/single_component_path_imports.rs:24:5 + --> $DIR/single_component_path_imports.rs:23:5 | LL | use regex; | ^^^^^^^^^^ help: remove it entirely @@ -7,7 +7,7 @@ LL | use regex; = note: `-D clippy::single-component-path-imports` implied by `-D warnings` error: this import is redundant - --> $DIR/single_component_path_imports.rs:6:1 + --> $DIR/single_component_path_imports.rs:5:1 | LL | use regex; | ^^^^^^^^^^ help: remove it entirely 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 index 05863f9a2b..e43f5d381a 100644 --- a/src/tools/clippy/tests/ui/single_component_path_imports_macro.fixed +++ b/src/tools/clippy/tests/ui/single_component_path_imports_macro.fixed @@ -1,5 +1,4 @@ // run-rustfix -// edition:2018 #![warn(clippy::single_component_path_imports)] #![allow(unused_imports)] 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 index 633deea348..3c65ca3054 100644 --- a/src/tools/clippy/tests/ui/single_component_path_imports_macro.rs +++ b/src/tools/clippy/tests/ui/single_component_path_imports_macro.rs @@ -1,5 +1,4 @@ // run-rustfix -// edition:2018 #![warn(clippy::single_component_path_imports)] #![allow(unused_imports)] 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 index 239efb393b..37d5176129 100644 --- a/src/tools/clippy/tests/ui/single_component_path_imports_macro.stderr +++ b/src/tools/clippy/tests/ui/single_component_path_imports_macro.stderr @@ -1,5 +1,5 @@ error: this import is redundant - --> $DIR/single_component_path_imports_macro.rs:16:1 + --> $DIR/single_component_path_imports_macro.rs:15:1 | LL | use m2; // fail | ^^^^^^^ help: remove it entirely 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 index 94117061b2..c75beb7478 100644 --- 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 @@ -1,4 +1,3 @@ -// edition:2018 #![warn(clippy::single_component_path_imports)] #![allow(unused_imports)] 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 index 0c3256c1ce..cf990be1b9 100644 --- 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 @@ -1,5 +1,5 @@ error: this import is redundant - --> $DIR/single_component_path_imports_nested_first.rs:14:10 + --> $DIR/single_component_path_imports_nested_first.rs:13:10 | LL | use {regex, serde}; | ^^^^^ @@ -8,7 +8,7 @@ LL | use {regex, serde}; = help: remove this import error: this import is redundant - --> $DIR/single_component_path_imports_nested_first.rs:14:17 + --> $DIR/single_component_path_imports_nested_first.rs:13:17 | LL | use {regex, serde}; | ^^^^^ @@ -16,7 +16,7 @@ LL | use {regex, serde}; = help: remove this import error: this import is redundant - --> $DIR/single_component_path_imports_nested_first.rs:5:1 + --> $DIR/single_component_path_imports_nested_first.rs:4:1 | LL | use regex; | ^^^^^^^^^^ help: remove it entirely 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 index 94319ade0a..48e8e53026 100644 --- 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 @@ -1,4 +1,3 @@ -// edition:2018 #![warn(clippy::single_component_path_imports)] #![allow(unused_imports)] 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 index c7437b2345..4fb0cf40b6 100644 --- 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 @@ -1,4 +1,3 @@ -// edition:2018 #![warn(clippy::single_component_path_imports)] #![allow(unused_imports)] diff --git a/src/tools/clippy/tests/ui/string_slice.rs b/src/tools/clippy/tests/ui/string_slice.rs new file mode 100644 index 0000000000..be4dfc8816 --- /dev/null +++ b/src/tools/clippy/tests/ui/string_slice.rs @@ -0,0 +1,10 @@ +#[warn(clippy::string_slice)] +#[allow(clippy::no_effect)] + +fn main() { + &"Ölkanne"[1..]; + let m = "Mötörhead"; + &m[2..5]; + let s = String::from(m); + &s[0..2]; +} diff --git a/src/tools/clippy/tests/ui/string_slice.stderr b/src/tools/clippy/tests/ui/string_slice.stderr new file mode 100644 index 0000000000..55040bf5df --- /dev/null +++ b/src/tools/clippy/tests/ui/string_slice.stderr @@ -0,0 +1,22 @@ +error: indexing into a string may panic if the index is within a UTF-8 character + --> $DIR/string_slice.rs:5:6 + | +LL | &"Ölkanne"[1..]; + | ^^^^^^^^^^^^^^ + | + = note: `-D clippy::string-slice` implied by `-D warnings` + +error: indexing into a string may panic if the index is within a UTF-8 character + --> $DIR/string_slice.rs:7:6 + | +LL | &m[2..5]; + | ^^^^^^^ + +error: indexing into a string may panic if the index is within a UTF-8 character + --> $DIR/string_slice.rs:9:6 + | +LL | &s[0..2]; + | ^^^^^^^ + +error: aborting due to 3 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 be8bc22bf9..fcd827a91c 100644 --- a/src/tools/clippy/tests/ui/suspicious_else_formatting.rs +++ b/src/tools/clippy/tests/ui/suspicious_else_formatting.rs @@ -1,6 +1,7 @@ // aux-build:proc_macro_suspicious_else_formatting.rs #![warn(clippy::suspicious_else_formatting)] +#![allow(clippy::if_same_then_else)] extern crate proc_macro_suspicious_else_formatting; use proc_macro_suspicious_else_formatting::DeriveBadSpan; diff --git a/src/tools/clippy/tests/ui/suspicious_else_formatting.stderr b/src/tools/clippy/tests/ui/suspicious_else_formatting.stderr index d1db195cbb..ee68eb5a79 100644 --- a/src/tools/clippy/tests/ui/suspicious_else_formatting.stderr +++ b/src/tools/clippy/tests/ui/suspicious_else_formatting.stderr @@ -1,5 +1,5 @@ error: this looks like an `else {..}` but the `else` is missing - --> $DIR/suspicious_else_formatting.rs:16:6 + --> $DIR/suspicious_else_formatting.rs:17:6 | LL | } { | ^ @@ -8,7 +8,7 @@ LL | } { = note: to remove this lint, add the missing `else` or add a new line before the next block error: this looks like an `else if` but the `else` is missing - --> $DIR/suspicious_else_formatting.rs:20:6 + --> $DIR/suspicious_else_formatting.rs:21:6 | LL | } if foo() { | ^ @@ -16,7 +16,7 @@ LL | } if foo() { = note: to remove this lint, add the missing `else` or add a new line before the second `if` error: this looks like an `else if` but the `else` is missing - --> $DIR/suspicious_else_formatting.rs:27:10 + --> $DIR/suspicious_else_formatting.rs:28:10 | LL | } if foo() { | ^ @@ -24,7 +24,7 @@ LL | } if foo() { = note: to remove this lint, add the missing `else` or add a new line before the second `if` error: this looks like an `else if` but the `else` is missing - --> $DIR/suspicious_else_formatting.rs:35:10 + --> $DIR/suspicious_else_formatting.rs:36:10 | LL | } if foo() { | ^ @@ -32,7 +32,7 @@ LL | } if foo() { = note: to remove this lint, add the missing `else` or add a new line before the second `if` error: this is an `else {..}` but the formatting might hide it - --> $DIR/suspicious_else_formatting.rs:44:6 + --> $DIR/suspicious_else_formatting.rs:45:6 | LL | } else | ______^ @@ -42,7 +42,7 @@ LL | | { = note: to remove this lint, remove the `else` or remove the new line between `else` and `{..}` error: this is an `else if` but the formatting might hide it - --> $DIR/suspicious_else_formatting.rs:56:6 + --> $DIR/suspicious_else_formatting.rs:57:6 | LL | } else | ______^ @@ -52,7 +52,7 @@ 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:61:6 + --> $DIR/suspicious_else_formatting.rs:62:6 | LL | } | ______^ @@ -63,7 +63,7 @@ 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 {..}` but the formatting might hide it - --> $DIR/suspicious_else_formatting.rs:88:6 + --> $DIR/suspicious_else_formatting.rs:89:6 | LL | } | ______^ @@ -75,7 +75,7 @@ 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:96:6 + --> $DIR/suspicious_else_formatting.rs:97:6 | LL | } | ______^ diff --git a/src/tools/clippy/tests/ui/suspicious_operation_groupings.rs b/src/tools/clippy/tests/ui/suspicious_operation_groupings.rs index 2f8c7cec50..3201d5de0f 100644 --- a/src/tools/clippy/tests/ui/suspicious_operation_groupings.rs +++ b/src/tools/clippy/tests/ui/suspicious_operation_groupings.rs @@ -1,4 +1,5 @@ #![warn(clippy::suspicious_operation_groupings)] +#![allow(clippy::eq_op)] struct Vec3 { x: f64, @@ -187,7 +188,7 @@ fn inside_fn_with_similar_expression(s1: &S, s2: &S, strict: bool) -> bool { } } -fn inside_an_if_statement(s1: &S, s2: &S) { +fn inside_an_if_statement(s1: &mut S, s2: &S) { // There's no `s1.b` if s1.a < s2.a && s1.a < s2.b { s1.c = s2.c; diff --git a/src/tools/clippy/tests/ui/suspicious_operation_groupings.stderr b/src/tools/clippy/tests/ui/suspicious_operation_groupings.stderr index dd6f2f6641..baf9bc74b0 100644 --- a/src/tools/clippy/tests/ui/suspicious_operation_groupings.stderr +++ b/src/tools/clippy/tests/ui/suspicious_operation_groupings.stderr @@ -1,5 +1,5 @@ error: this sequence of operators looks suspiciously like a bug - --> $DIR/suspicious_operation_groupings.rs:14:9 + --> $DIR/suspicious_operation_groupings.rs:15:9 | LL | self.x == other.y && self.y == other.y && self.z == other.z | ^^^^^^^^^^^^^^^^^ help: did you mean: `self.x == other.x` @@ -7,151 +7,151 @@ LL | self.x == other.y && self.y == other.y && self.z == other.z = note: `-D clippy::suspicious-operation-groupings` implied by `-D warnings` error: this sequence of operators looks suspiciously like a bug - --> $DIR/suspicious_operation_groupings.rs:27:20 + --> $DIR/suspicious_operation_groupings.rs:28:20 | LL | s1.a < s2.a && s1.a < s2.b | ^^^^^^^^^^^ help: did you mean: `s1.b < s2.b` error: this sequence of operators looks suspiciously like a bug - --> $DIR/suspicious_operation_groupings.rs:75:33 + --> $DIR/suspicious_operation_groupings.rs:76:33 | LL | s1.a * s2.a + s1.b * s2.b + s1.c * s2.b + s1.d * s2.d | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> $DIR/suspicious_operation_groupings.rs:80:19 + --> $DIR/suspicious_operation_groupings.rs:81:19 | LL | s1.a * s2.a + s1.b * s2.c + s1.c * s2.c | ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b` error: this sequence of operators looks suspiciously like a bug - --> $DIR/suspicious_operation_groupings.rs:80:19 + --> $DIR/suspicious_operation_groupings.rs:81:19 | LL | s1.a * s2.a + s1.b * s2.c + s1.c * s2.c | ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b` error: this sequence of operators looks suspiciously like a bug - --> $DIR/suspicious_operation_groupings.rs:85:19 + --> $DIR/suspicious_operation_groupings.rs:86:19 | LL | s1.a * s2.a + s2.b * s2.b + s1.c * s2.c | ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b` error: this sequence of operators looks suspiciously like a bug - --> $DIR/suspicious_operation_groupings.rs:90:19 + --> $DIR/suspicious_operation_groupings.rs:91:19 | LL | s1.a * s2.a + s1.b * s1.b + s1.c * s2.c | ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b` error: this sequence of operators looks suspiciously like a bug - --> $DIR/suspicious_operation_groupings.rs:95:5 + --> $DIR/suspicious_operation_groupings.rs:96:5 | LL | s1.a * s1.a + s1.b * s2.b + s1.c * s2.c | ^^^^^^^^^^^ help: did you mean: `s1.a * s2.a` error: this sequence of operators looks suspiciously like a bug - --> $DIR/suspicious_operation_groupings.rs:100:33 + --> $DIR/suspicious_operation_groupings.rs:101:33 | LL | s1.a * s2.a + s1.b * s2.b + s1.c * s1.c | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> $DIR/suspicious_operation_groupings.rs:113:20 + --> $DIR/suspicious_operation_groupings.rs:114:20 | LL | (s1.a * s2.a + s1.b * s1.b) | ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b` error: this sequence of operators looks suspiciously like a bug - --> $DIR/suspicious_operation_groupings.rs:118:34 + --> $DIR/suspicious_operation_groupings.rs:119:34 | LL | (s1.a * s2.a + s1.b * s2.b + s1.c * s2.b + s1.d * s2.d) | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> $DIR/suspicious_operation_groupings.rs:123:38 + --> $DIR/suspicious_operation_groupings.rs:124:38 | LL | (s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d) | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> $DIR/suspicious_operation_groupings.rs:128:39 + --> $DIR/suspicious_operation_groupings.rs:129:39 | LL | ((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d)) | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> $DIR/suspicious_operation_groupings.rs:133:42 + --> $DIR/suspicious_operation_groupings.rs:134:42 | LL | (((s1.a * s2.a) + (s1.b * s2.b)) + ((s1.c * s2.b) + (s1.d * s2.d))) | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> $DIR/suspicious_operation_groupings.rs:133:42 + --> $DIR/suspicious_operation_groupings.rs:134:42 | LL | (((s1.a * s2.a) + (s1.b * s2.b)) + ((s1.c * s2.b) + (s1.d * s2.d))) | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> $DIR/suspicious_operation_groupings.rs:138:40 + --> $DIR/suspicious_operation_groupings.rs:139:40 | LL | (((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b)) + (s1.d * s2.d)) | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> $DIR/suspicious_operation_groupings.rs:143:40 + --> $DIR/suspicious_operation_groupings.rs:144:40 | LL | ((s1.a * s2.a) + ((s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d))) | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> $DIR/suspicious_operation_groupings.rs:148:20 + --> $DIR/suspicious_operation_groupings.rs:149:20 | LL | (s1.a * s2.a + s2.b * s2.b) / 2 | ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b` error: this sequence of operators looks suspiciously like a bug - --> $DIR/suspicious_operation_groupings.rs:153:35 + --> $DIR/suspicious_operation_groupings.rs:154:35 | LL | i32::swap_bytes(s1.a * s2.a + s2.b * s2.b) | ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b` error: this sequence of operators looks suspiciously like a bug - --> $DIR/suspicious_operation_groupings.rs:158:29 + --> $DIR/suspicious_operation_groupings.rs:159:29 | LL | s1.a > 0 && s1.b > 0 && s1.d == s2.c && s1.d == s2.d | ^^^^^^^^^^^^ help: did you mean: `s1.c == s2.c` error: this sequence of operators looks suspiciously like a bug - --> $DIR/suspicious_operation_groupings.rs:163:17 + --> $DIR/suspicious_operation_groupings.rs:164:17 | LL | s1.a > 0 && s1.d == s2.c && s1.b > 0 && s1.d == s2.d | ^^^^^^^^^^^^ help: did you mean: `s1.c == s2.c` error: this sequence of operators looks suspiciously like a bug - --> $DIR/suspicious_operation_groupings.rs:172:77 + --> $DIR/suspicious_operation_groupings.rs:173:77 | LL | (n1.inner.0).0 == (n2.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.1).0 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `(n1.inner.2).0 == (n2.inner.2).0` error: this sequence of operators looks suspiciously like a bug - --> $DIR/suspicious_operation_groupings.rs:186:25 + --> $DIR/suspicious_operation_groupings.rs:187:25 | LL | s1.a <= s2.a && s1.a <= s2.b | ^^^^^^^^^^^^ help: did you mean: `s1.b <= s2.b` error: this sequence of operators looks suspiciously like a bug - --> $DIR/suspicious_operation_groupings.rs:192:23 + --> $DIR/suspicious_operation_groupings.rs:193:23 | LL | if s1.a < s2.a && s1.a < s2.b { | ^^^^^^^^^^^ help: did you mean: `s1.b < s2.b` error: this sequence of operators looks suspiciously like a bug - --> $DIR/suspicious_operation_groupings.rs:199:48 + --> $DIR/suspicious_operation_groupings.rs:200:48 | LL | -(-(-s1.a * -s2.a) + (-(-s1.b * -s2.b) + -(-s1.c * -s2.b) + -(-s1.d * -s2.d))) | ^^^^^^^^^^^^^ help: did you mean: `-s1.c * -s2.c` error: this sequence of operators looks suspiciously like a bug - --> $DIR/suspicious_operation_groupings.rs:204:27 + --> $DIR/suspicious_operation_groupings.rs:205:27 | LL | -(if -s1.a < -s2.a && -s1.a < -s2.b { s1.c } else { s2.a }) | ^^^^^^^^^^^^^ help: did you mean: `-s1.b < -s2.b` diff --git a/src/tools/clippy/tests/ui/to_string_in_display.rs b/src/tools/clippy/tests/ui/to_string_in_display.rs index eb8105c6b6..3ccdcd1117 100644 --- a/src/tools/clippy/tests/ui/to_string_in_display.rs +++ b/src/tools/clippy/tests/ui/to_string_in_display.rs @@ -1,5 +1,5 @@ #![warn(clippy::to_string_in_display)] -#![allow(clippy::inherent_to_string_shadow_display)] +#![allow(clippy::inherent_to_string_shadow_display, clippy::to_string_in_format_args)] use std::fmt; diff --git a/src/tools/clippy/tests/ui/trailing_empty_array.rs b/src/tools/clippy/tests/ui/trailing_empty_array.rs new file mode 100644 index 0000000000..501c9eb765 --- /dev/null +++ b/src/tools/clippy/tests/ui/trailing_empty_array.rs @@ -0,0 +1,186 @@ +#![warn(clippy::trailing_empty_array)] +#![feature(const_generics_defaults)] + +// Do lint: + +struct RarelyUseful { + field: i32, + last: [usize; 0], +} + +struct OnlyField { + first_and_last: [usize; 0], +} + +struct GenericArrayType<T> { + field: i32, + last: [T; 0], +} + +#[must_use] +struct OnlyAnotherAttribute { + field: i32, + last: [usize; 0], +} + +#[derive(Debug)] +struct OnlyADeriveAttribute { + field: i32, + last: [usize; 0], +} + +const ZERO: usize = 0; +struct ZeroSizedWithConst { + field: i32, + last: [usize; ZERO], +} + +#[allow(clippy::eq_op)] +const fn compute_zero() -> usize { + (4 + 6) - (2 * 5) +} +struct ZeroSizedWithConstFunction { + field: i32, + last: [usize; compute_zero()], +} + +const fn compute_zero_from_arg(x: usize) -> usize { + x - 1 +} +struct ZeroSizedWithConstFunction2 { + field: i32, + last: [usize; compute_zero_from_arg(1)], +} + +struct ZeroSizedArrayWrapper([usize; 0]); + +struct TupleStruct(i32, [usize; 0]); + +struct LotsOfFields { + f1: u32, + f2: u32, + f3: u32, + f4: u32, + f5: u32, + f6: u32, + f7: u32, + f8: u32, + f9: u32, + f10: u32, + f11: u32, + f12: u32, + f13: u32, + f14: u32, + f15: u32, + f16: u32, + last: [usize; 0], +} + +// Don't lint + +#[repr(C)] +struct GoodReason { + field: i32, + last: [usize; 0], +} + +#[repr(C)] +struct OnlyFieldWithReprC { + first_and_last: [usize; 0], +} + +struct NonZeroSizedArray { + field: i32, + last: [usize; 1], +} + +struct NotLastField { + f1: u32, + zero_sized: [usize; 0], + last: i32, +} + +const ONE: usize = 1; +struct NonZeroSizedWithConst { + field: i32, + last: [usize; ONE], +} + +#[derive(Debug)] +#[repr(C)] +struct AlsoADeriveAttribute { + field: i32, + last: [usize; 0], +} + +#[must_use] +#[repr(C)] +struct AlsoAnotherAttribute { + field: i32, + last: [usize; 0], +} + +#[repr(packed)] +struct ReprPacked { + field: i32, + last: [usize; 0], +} + +#[repr(C, packed)] +struct ReprCPacked { + field: i32, + last: [usize; 0], +} + +#[repr(align(64))] +struct ReprAlign { + field: i32, + last: [usize; 0], +} +#[repr(C, align(64))] +struct ReprCAlign { + field: i32, + last: [usize; 0], +} + +// NOTE: because of https://doc.rust-lang.org/stable/reference/type-layout.html#primitive-representation-of-enums-with-fields and I'm not sure when in the compilation pipeline that would happen +#[repr(C)] +enum DontLintAnonymousStructsFromDesuraging { + A(u32), + B(f32, [u64; 0]), + C { x: u32, y: [u64; 0] }, +} + +#[repr(C)] +struct TupleStructReprC(i32, [usize; 0]); + +type NamedTuple = (i32, [usize; 0]); + +#[rustfmt::skip] // [rustfmt#4995](https://github.com/rust-lang/rustfmt/issues/4995) +struct ConstParamZeroDefault<const N: usize = 0> { + field: i32, + last: [usize; N], +} + +struct ConstParamNoDefault<const N: usize> { + field: i32, + last: [usize; N], +} + +#[rustfmt::skip] +struct ConstParamNonZeroDefault<const N: usize = 1> { + field: i32, + last: [usize; N], +} + +struct TwoGenericParams<T, const N: usize> { + field: i32, + last: [T; N], +} + +type A = ConstParamZeroDefault; +type B = ConstParamZeroDefault<0>; +type C = ConstParamNoDefault<0>; +type D = ConstParamNonZeroDefault<0>; + +fn main() {} diff --git a/src/tools/clippy/tests/ui/trailing_empty_array.stderr b/src/tools/clippy/tests/ui/trailing_empty_array.stderr new file mode 100644 index 0000000000..d88aa0504b --- /dev/null +++ b/src/tools/clippy/tests/ui/trailing_empty_array.stderr @@ -0,0 +1,120 @@ +error: trailing zero-sized array in a struct which is not marked with a `repr` attribute + --> $DIR/trailing_empty_array.rs:6:1 + | +LL | / struct RarelyUseful { +LL | | field: i32, +LL | | last: [usize; 0], +LL | | } + | |_^ + | + = note: `-D clippy::trailing-empty-array` implied by `-D warnings` + = help: consider annotating `RarelyUseful` with `#[repr(C)]` or another `repr` attribute + +error: trailing zero-sized array in a struct which is not marked with a `repr` attribute + --> $DIR/trailing_empty_array.rs:11:1 + | +LL | / struct OnlyField { +LL | | first_and_last: [usize; 0], +LL | | } + | |_^ + | + = help: consider annotating `OnlyField` with `#[repr(C)]` or another `repr` attribute + +error: trailing zero-sized array in a struct which is not marked with a `repr` attribute + --> $DIR/trailing_empty_array.rs:15:1 + | +LL | / struct GenericArrayType<T> { +LL | | field: i32, +LL | | last: [T; 0], +LL | | } + | |_^ + | + = help: consider annotating `GenericArrayType` with `#[repr(C)]` or another `repr` attribute + +error: trailing zero-sized array in a struct which is not marked with a `repr` attribute + --> $DIR/trailing_empty_array.rs:21:1 + | +LL | / struct OnlyAnotherAttribute { +LL | | field: i32, +LL | | last: [usize; 0], +LL | | } + | |_^ + | + = help: consider annotating `OnlyAnotherAttribute` with `#[repr(C)]` or another `repr` attribute + +error: trailing zero-sized array in a struct which is not marked with a `repr` attribute + --> $DIR/trailing_empty_array.rs:27:1 + | +LL | / struct OnlyADeriveAttribute { +LL | | field: i32, +LL | | last: [usize; 0], +LL | | } + | |_^ + | + = help: consider annotating `OnlyADeriveAttribute` with `#[repr(C)]` or another `repr` attribute + +error: trailing zero-sized array in a struct which is not marked with a `repr` attribute + --> $DIR/trailing_empty_array.rs:33:1 + | +LL | / struct ZeroSizedWithConst { +LL | | field: i32, +LL | | last: [usize; ZERO], +LL | | } + | |_^ + | + = help: consider annotating `ZeroSizedWithConst` with `#[repr(C)]` or another `repr` attribute + +error: trailing zero-sized array in a struct which is not marked with a `repr` attribute + --> $DIR/trailing_empty_array.rs:42:1 + | +LL | / struct ZeroSizedWithConstFunction { +LL | | field: i32, +LL | | last: [usize; compute_zero()], +LL | | } + | |_^ + | + = help: consider annotating `ZeroSizedWithConstFunction` with `#[repr(C)]` or another `repr` attribute + +error: trailing zero-sized array in a struct which is not marked with a `repr` attribute + --> $DIR/trailing_empty_array.rs:50:1 + | +LL | / struct ZeroSizedWithConstFunction2 { +LL | | field: i32, +LL | | last: [usize; compute_zero_from_arg(1)], +LL | | } + | |_^ + | + = help: consider annotating `ZeroSizedWithConstFunction2` with `#[repr(C)]` or another `repr` attribute + +error: trailing zero-sized array in a struct which is not marked with a `repr` attribute + --> $DIR/trailing_empty_array.rs:55:1 + | +LL | struct ZeroSizedArrayWrapper([usize; 0]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider annotating `ZeroSizedArrayWrapper` with `#[repr(C)]` or another `repr` attribute + +error: trailing zero-sized array in a struct which is not marked with a `repr` attribute + --> $DIR/trailing_empty_array.rs:57:1 + | +LL | struct TupleStruct(i32, [usize; 0]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider annotating `TupleStruct` with `#[repr(C)]` or another `repr` attribute + +error: trailing zero-sized array in a struct which is not marked with a `repr` attribute + --> $DIR/trailing_empty_array.rs:59:1 + | +LL | / struct LotsOfFields { +LL | | f1: u32, +LL | | f2: u32, +LL | | f3: u32, +... | +LL | | last: [usize; 0], +LL | | } + | |_^ + | + = help: consider annotating `LotsOfFields` with `#[repr(C)]` or another `repr` attribute + +error: aborting due to 11 previous errors + diff --git a/src/tools/clippy/tests/ui/transmute.rs b/src/tools/clippy/tests/ui/transmute.rs index bce4c81b78..6a7037d8f3 100644 --- a/src/tools/clippy/tests/ui/transmute.rs +++ b/src/tools/clippy/tests/ui/transmute.rs @@ -103,6 +103,33 @@ mod int_to_float { } } +mod num_to_bytes { + fn test() { + unsafe { + let _: [u8; 1] = std::mem::transmute(0u8); + let _: [u8; 4] = std::mem::transmute(0u32); + let _: [u8; 16] = std::mem::transmute(0u128); + let _: [u8; 1] = std::mem::transmute(0i8); + let _: [u8; 4] = std::mem::transmute(0i32); + let _: [u8; 16] = std::mem::transmute(0i128); + let _: [u8; 4] = std::mem::transmute(0.0f32); + let _: [u8; 8] = std::mem::transmute(0.0f64); + } + } + const fn test_const() { + unsafe { + let _: [u8; 1] = std::mem::transmute(0u8); + let _: [u8; 4] = std::mem::transmute(0u32); + let _: [u8; 16] = std::mem::transmute(0u128); + let _: [u8; 1] = std::mem::transmute(0i8); + let _: [u8; 4] = std::mem::transmute(0i32); + let _: [u8; 16] = std::mem::transmute(0i128); + let _: [u8; 4] = std::mem::transmute(0.0f32); + let _: [u8; 8] = std::mem::transmute(0.0f64); + } + } +} + fn bytes_to_str(b: &[u8], mb: &mut [u8]) { let _: &str = unsafe { std::mem::transmute(b) }; let _: &mut str = unsafe { std::mem::transmute(mb) }; diff --git a/src/tools/clippy/tests/ui/transmute.stderr b/src/tools/clippy/tests/ui/transmute.stderr index e31accb982..86537153e3 100644 --- a/src/tools/clippy/tests/ui/transmute.stderr +++ b/src/tools/clippy/tests/ui/transmute.stderr @@ -140,8 +140,94 @@ error: transmute from a `i64` to a `f64` LL | let _: f64 = unsafe { std::mem::transmute(0_i64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_i64 as u64)` +error: transmute from a `u8` to a `[u8; 1]` + --> $DIR/transmute.rs:109:30 + | +LL | let _: [u8; 1] = std::mem::transmute(0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u8.to_ne_bytes()` + | + = note: `-D clippy::transmute-num-to-bytes` implied by `-D warnings` + +error: transmute from a `u32` to a `[u8; 4]` + --> $DIR/transmute.rs:110:30 + | +LL | let _: [u8; 4] = std::mem::transmute(0u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u32.to_ne_bytes()` + +error: transmute from a `u128` to a `[u8; 16]` + --> $DIR/transmute.rs:111:31 + | +LL | let _: [u8; 16] = std::mem::transmute(0u128); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u128.to_ne_bytes()` + +error: transmute from a `i8` to a `[u8; 1]` + --> $DIR/transmute.rs:112:30 + | +LL | let _: [u8; 1] = std::mem::transmute(0i8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i8.to_ne_bytes()` + +error: transmute from a `i32` to a `[u8; 4]` + --> $DIR/transmute.rs:113:30 + | +LL | let _: [u8; 4] = std::mem::transmute(0i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i32.to_ne_bytes()` + +error: transmute from a `i128` to a `[u8; 16]` + --> $DIR/transmute.rs:114:31 + | +LL | let _: [u8; 16] = std::mem::transmute(0i128); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i128.to_ne_bytes()` + +error: transmute from a `f32` to a `[u8; 4]` + --> $DIR/transmute.rs:115:30 + | +LL | let _: [u8; 4] = std::mem::transmute(0.0f32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f32.to_ne_bytes()` + +error: transmute from a `f64` to a `[u8; 8]` + --> $DIR/transmute.rs:116:30 + | +LL | let _: [u8; 8] = std::mem::transmute(0.0f64); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f64.to_ne_bytes()` + +error: transmute from a `u8` to a `[u8; 1]` + --> $DIR/transmute.rs:121:30 + | +LL | let _: [u8; 1] = std::mem::transmute(0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u8.to_ne_bytes()` + +error: transmute from a `u32` to a `[u8; 4]` + --> $DIR/transmute.rs:122:30 + | +LL | let _: [u8; 4] = std::mem::transmute(0u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u32.to_ne_bytes()` + +error: transmute from a `u128` to a `[u8; 16]` + --> $DIR/transmute.rs:123:31 + | +LL | let _: [u8; 16] = std::mem::transmute(0u128); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u128.to_ne_bytes()` + +error: transmute from a `i8` to a `[u8; 1]` + --> $DIR/transmute.rs:124:30 + | +LL | let _: [u8; 1] = std::mem::transmute(0i8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i8.to_ne_bytes()` + +error: transmute from a `i32` to a `[u8; 4]` + --> $DIR/transmute.rs:125:30 + | +LL | let _: [u8; 4] = std::mem::transmute(0i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i32.to_ne_bytes()` + +error: transmute from a `i128` to a `[u8; 16]` + --> $DIR/transmute.rs:126:31 + | +LL | let _: [u8; 16] = std::mem::transmute(0i128); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i128.to_ne_bytes()` + error: transmute from a `&[u8]` to a `&str` - --> $DIR/transmute.rs:107:28 + --> $DIR/transmute.rs:134:28 | LL | let _: &str = unsafe { std::mem::transmute(b) }; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(b).unwrap()` @@ -149,10 +235,10 @@ LL | let _: &str = unsafe { std::mem::transmute(b) }; = note: `-D clippy::transmute-bytes-to-str` implied by `-D warnings` error: transmute from a `&mut [u8]` to a `&mut str` - --> $DIR/transmute.rs:108:32 + --> $DIR/transmute.rs:135:32 | LL | let _: &mut str = unsafe { std::mem::transmute(mb) }; | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()` -error: aborting due to 24 previous errors +error: aborting due to 38 previous errors diff --git a/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.rs b/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.rs new file mode 100644 index 0000000000..52577323a5 --- /dev/null +++ b/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.rs @@ -0,0 +1,287 @@ +#![warn(clippy::undocumented_unsafe_blocks)] + +// Valid comments + +fn nested_local() { + let _ = { + let _ = { + // Safety: + let _ = unsafe {}; + }; + }; +} + +fn deep_nest() { + let _ = { + let _ = { + // Safety: + let _ = unsafe {}; + + // Safety: + unsafe {}; + + let _ = { + let _ = { + let _ = { + let _ = { + let _ = { + // Safety: + let _ = unsafe {}; + + // Safety: + unsafe {}; + }; + }; + }; + + // Safety: + unsafe {}; + }; + }; + }; + + // Safety: + unsafe {}; + }; + + // Safety: + unsafe {}; +} + +fn local_tuple_expression() { + // Safety: + let _ = (42, unsafe {}); +} + +fn line_comment() { + // Safety: + unsafe {} +} + +fn line_comment_newlines() { + // Safety: + + unsafe {} +} + +fn line_comment_empty() { + // Safety: + // + // + // + unsafe {} +} + +fn line_comment_with_extras() { + // This is a description + // Safety: + unsafe {} +} + +fn block_comment() { + /* Safety: */ + unsafe {} +} + +fn block_comment_newlines() { + /* Safety: */ + + unsafe {} +} + +#[rustfmt::skip] +fn inline_block_comment() { + /* Safety: */unsafe {} +} + +fn block_comment_with_extras() { + /* This is a description + * Safety: + */ + unsafe {} +} + +fn block_comment_terminator_same_line() { + /* This is a description + * Safety: */ + unsafe {} +} + +fn buried_safety() { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor + // incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation + // ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in + // reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint + // occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est + // laborum. Safety: + // Tellus elementum sagittis vitae et leo duis ut diam quam. Sit amet nulla facilisi + // morbi tempus iaculis urna. Amet luctus venenatis lectus magna. At quis risus sed vulputate odio + // ut. Luctus venenatis lectus magna fringilla urna. Tortor id aliquet lectus proin nibh nisl + // condimentum id venenatis. Vulputate dignissim suspendisse in est ante in nibh mauris cursus. + unsafe {} +} + +fn safety_with_prepended_text() { + // This is a test. Safety: + unsafe {} +} + +fn local_line_comment() { + // Safety: + let _ = unsafe {}; +} + +fn local_block_comment() { + /* Safety: */ + let _ = unsafe {}; +} + +fn comment_array() { + // Safety: + let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; +} + +fn comment_tuple() { + // Safety: + let _ = (42, unsafe {}, "test", unsafe {}); +} + +fn comment_unary() { + // Safety: + let _ = *unsafe { &42 }; +} + +#[allow(clippy::match_single_binding)] +fn comment_match() { + // Safety: + let _ = match unsafe {} { + _ => {}, + }; +} + +fn comment_addr_of() { + // Safety: + let _ = &unsafe {}; +} + +fn comment_repeat() { + // Safety: + let _ = [unsafe {}; 5]; +} + +fn comment_macro_call() { + macro_rules! t { + ($b:expr) => { + $b + }; + } + + t!( + // Safety: + unsafe {} + ); +} + +fn comment_macro_def() { + macro_rules! t { + () => { + // Safety: + unsafe {} + }; + } + + t!(); +} + +fn non_ascii_comment() { + // ॐ᧻໒ Safety: ௵∰ + unsafe {}; +} + +fn local_commented_block() { + let _ = + // Safety: + unsafe {}; +} + +fn local_nest() { + // Safety: + let _ = [(42, unsafe {}, unsafe {}), (52, unsafe {}, unsafe {})]; +} + +// Invalid comments + +fn no_comment() { + unsafe {} +} + +fn no_comment_array() { + let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; +} + +fn no_comment_tuple() { + let _ = (42, unsafe {}, "test", unsafe {}); +} + +fn no_comment_unary() { + let _ = *unsafe { &42 }; +} + +#[allow(clippy::match_single_binding)] +fn no_comment_match() { + let _ = match unsafe {} { + _ => {}, + }; +} + +fn no_comment_addr_of() { + let _ = &unsafe {}; +} + +fn no_comment_repeat() { + let _ = [unsafe {}; 5]; +} + +fn local_no_comment() { + let _ = unsafe {}; +} + +fn no_comment_macro_call() { + macro_rules! t { + ($b:expr) => { + $b + }; + } + + t!(unsafe {}); +} + +fn no_comment_macro_def() { + macro_rules! t { + () => { + unsafe {} + }; + } + + t!(); +} + +fn trailing_comment() { + unsafe {} // Safety: +} + +fn internal_comment() { + unsafe { + // Safety: + } +} + +fn interference() { + // Safety + + let _ = 42; + + unsafe {}; +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.stderr b/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.stderr new file mode 100644 index 0000000000..613e9ffca4 --- /dev/null +++ b/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.stderr @@ -0,0 +1,159 @@ +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:215:5 + | +LL | unsafe {} + | ^^^^^^^^^ + | + = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings` +help: consider adding a safety comment + | +LL ~ // Safety: ... +LL + unsafe {} + | + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:219:5 + | +LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider adding a safety comment + | +LL ~ // Safety: ... +LL + let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; + | + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:223:5 + | +LL | let _ = (42, unsafe {}, "test", unsafe {}); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider adding a safety comment + | +LL ~ // Safety: ... +LL + let _ = (42, unsafe {}, "test", unsafe {}); + | + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:227:5 + | +LL | let _ = *unsafe { &42 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider adding a safety comment + | +LL ~ // Safety: ... +LL + let _ = *unsafe { &42 }; + | + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:232:5 + | +LL | let _ = match unsafe {} { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider adding a safety comment + | +LL ~ // Safety: ... +LL + let _ = match unsafe {} { + | + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:238:5 + | +LL | let _ = &unsafe {}; + | ^^^^^^^^^^^^^^^^^^^ + | +help: consider adding a safety comment + | +LL ~ // Safety: ... +LL + let _ = &unsafe {}; + | + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:242:5 + | +LL | let _ = [unsafe {}; 5]; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider adding a safety comment + | +LL ~ // Safety: ... +LL + let _ = [unsafe {}; 5]; + | + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:246:5 + | +LL | let _ = unsafe {}; + | ^^^^^^^^^^^^^^^^^^ + | +help: consider adding a safety comment + | +LL ~ // Safety: ... +LL + let _ = unsafe {}; + | + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:256:8 + | +LL | t!(unsafe {}); + | ^^^^^^^^^ + | +help: consider adding a safety comment + | +LL ~ t!(// Safety: ... +LL ~ unsafe {}); + | + +error: unsafe block in macro expansion missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:262:13 + | +LL | unsafe {} + | ^^^^^^^^^ +... +LL | t!(); + | ---- in this macro invocation + | + = help: consider adding a safety comment in the macro definition + = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:270:5 + | +LL | unsafe {} // Safety: + | ^^^^^^^^^ + | +help: consider adding a safety comment + | +LL ~ // Safety: ... +LL ~ unsafe {} // Safety: + | + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:274:5 + | +LL | unsafe { + | ^^^^^^^^ + | +help: consider adding a safety comment + | +LL ~ // Safety: ... +LL + unsafe { + | + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:284:5 + | +LL | unsafe {}; + | ^^^^^^^^^ + | +help: consider adding a safety comment + | +LL ~ // Safety: ... +LL ~ unsafe {}; + | + +error: aborting due to 13 previous errors + diff --git a/src/tools/clippy/tests/ui/uninit_vec.rs b/src/tools/clippy/tests/ui/uninit_vec.rs new file mode 100644 index 0000000000..dc150cf28f --- /dev/null +++ b/src/tools/clippy/tests/ui/uninit_vec.rs @@ -0,0 +1,94 @@ +#![warn(clippy::uninit_vec)] + +use std::mem::MaybeUninit; + +#[derive(Default)] +struct MyVec { + vec: Vec<u8>, +} + +fn main() { + // with_capacity() -> set_len() should be detected + let mut vec: Vec<u8> = Vec::with_capacity(1000); + unsafe { + vec.set_len(200); + } + + // reserve() -> set_len() should be detected + vec.reserve(1000); + unsafe { + vec.set_len(200); + } + + // new() -> set_len() should be detected + let mut vec: Vec<u8> = Vec::new(); + unsafe { + vec.set_len(200); + } + + // default() -> set_len() should be detected + let mut vec: Vec<u8> = Default::default(); + unsafe { + vec.set_len(200); + } + + let mut vec: Vec<u8> = Vec::default(); + unsafe { + vec.set_len(200); + } + + // test when both calls are enclosed in the same unsafe block + unsafe { + let mut vec: Vec<u8> = Vec::with_capacity(1000); + vec.set_len(200); + + vec.reserve(1000); + vec.set_len(200); + } + + let mut vec: Vec<u8> = Vec::with_capacity(1000); + unsafe { + // test the case where there are other statements in the following unsafe block + vec.set_len(200); + assert!(vec.len() == 200); + } + + // handle vec stored in the field of a struct + let mut my_vec = MyVec::default(); + my_vec.vec.reserve(1000); + unsafe { + my_vec.vec.set_len(200); + } + + my_vec.vec = Vec::with_capacity(1000); + unsafe { + my_vec.vec.set_len(200); + } + + // Test `#[allow(...)]` attributes on inner unsafe block (shouldn't trigger) + let mut vec: Vec<u8> = Vec::with_capacity(1000); + #[allow(clippy::uninit_vec)] + unsafe { + vec.set_len(200); + } + + // MaybeUninit-wrapped types should not be detected + unsafe { + let mut vec: Vec<MaybeUninit<u8>> = Vec::with_capacity(1000); + vec.set_len(200); + + let mut vec: Vec<(MaybeUninit<u8>, MaybeUninit<bool>)> = Vec::with_capacity(1000); + vec.set_len(200); + + let mut vec: Vec<(MaybeUninit<u8>, [MaybeUninit<bool>; 2])> = Vec::with_capacity(1000); + vec.set_len(200); + } + + // known false negative + let mut vec1: Vec<u8> = Vec::with_capacity(1000); + let mut vec2: Vec<u8> = Vec::with_capacity(1000); + unsafe { + vec1.set_len(200); + vec2.set_len(200); + } +} diff --git a/src/tools/clippy/tests/ui/uninit_vec.stderr b/src/tools/clippy/tests/ui/uninit_vec.stderr new file mode 100644 index 0000000000..520bfb26b6 --- /dev/null +++ b/src/tools/clippy/tests/ui/uninit_vec.stderr @@ -0,0 +1,105 @@ +error: calling `set_len()` immediately after reserving a buffer creates uninitialized values + --> $DIR/uninit_vec.rs:12:5 + | +LL | let mut vec: Vec<u8> = Vec::with_capacity(1000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | unsafe { +LL | vec.set_len(200); + | ^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::uninit-vec` implied by `-D warnings` + = help: initialize the buffer or wrap the content in `MaybeUninit` + +error: calling `set_len()` immediately after reserving a buffer creates uninitialized values + --> $DIR/uninit_vec.rs:18:5 + | +LL | vec.reserve(1000); + | ^^^^^^^^^^^^^^^^^^ +LL | unsafe { +LL | vec.set_len(200); + | ^^^^^^^^^^^^^^^^ + | + = help: initialize the buffer or wrap the content in `MaybeUninit` + +error: calling `set_len()` on empty `Vec` creates out-of-bound values + --> $DIR/uninit_vec.rs:24:5 + | +LL | let mut vec: Vec<u8> = Vec::new(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | unsafe { +LL | vec.set_len(200); + | ^^^^^^^^^^^^^^^^ + +error: calling `set_len()` on empty `Vec` creates out-of-bound values + --> $DIR/uninit_vec.rs:30:5 + | +LL | let mut vec: Vec<u8> = Default::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | unsafe { +LL | vec.set_len(200); + | ^^^^^^^^^^^^^^^^ + +error: calling `set_len()` on empty `Vec` creates out-of-bound values + --> $DIR/uninit_vec.rs:35:5 + | +LL | let mut vec: Vec<u8> = Vec::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | unsafe { +LL | vec.set_len(200); + | ^^^^^^^^^^^^^^^^ + +error: calling `set_len()` immediately after reserving a buffer creates uninitialized values + --> $DIR/uninit_vec.rs:49:5 + | +LL | let mut vec: Vec<u8> = Vec::with_capacity(1000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | vec.set_len(200); + | ^^^^^^^^^^^^^^^^ + | + = help: initialize the buffer or wrap the content in `MaybeUninit` + +error: calling `set_len()` immediately after reserving a buffer creates uninitialized values + --> $DIR/uninit_vec.rs:58:5 + | +LL | my_vec.vec.reserve(1000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | unsafe { +LL | my_vec.vec.set_len(200); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: initialize the buffer or wrap the content in `MaybeUninit` + +error: calling `set_len()` immediately after reserving a buffer creates uninitialized values + --> $DIR/uninit_vec.rs:63:5 + | +LL | my_vec.vec = Vec::with_capacity(1000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | unsafe { +LL | my_vec.vec.set_len(200); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: initialize the buffer or wrap the content in `MaybeUninit` + +error: calling `set_len()` immediately after reserving a buffer creates uninitialized values + --> $DIR/uninit_vec.rs:42:9 + | +LL | let mut vec: Vec<u8> = Vec::with_capacity(1000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | vec.set_len(200); + | ^^^^^^^^^^^^^^^^ + | + = help: initialize the buffer or wrap the content in `MaybeUninit` + +error: calling `set_len()` immediately after reserving a buffer creates uninitialized values + --> $DIR/uninit_vec.rs:45:9 + | +LL | vec.reserve(1000); + | ^^^^^^^^^^^^^^^^^^ +LL | vec.set_len(200); + | ^^^^^^^^^^^^^^^^ + | + = help: initialize the buffer or wrap the content in `MaybeUninit` + +error: aborting due to 10 previous errors + diff --git a/src/tools/clippy/tests/ui/unit_hash.rs b/src/tools/clippy/tests/ui/unit_hash.rs new file mode 100644 index 0000000000..989916c239 --- /dev/null +++ b/src/tools/clippy/tests/ui/unit_hash.rs @@ -0,0 +1,27 @@ +#![warn(clippy::unit_hash)] + +use std::collections::hash_map::DefaultHasher; +use std::hash::Hash; + +enum Foo { + Empty, + WithValue(u8), +} + +fn do_nothing() {} + +fn main() { + let mut state = DefaultHasher::new(); + let my_enum = Foo::Empty; + + match my_enum { + Foo::Empty => ().hash(&mut state), + Foo::WithValue(x) => x.hash(&mut state), + } + + let res = (); + res.hash(&mut state); + + #[allow(clippy::unit_arg)] + do_nothing().hash(&mut state); +} diff --git a/src/tools/clippy/tests/ui/unit_hash.stderr b/src/tools/clippy/tests/ui/unit_hash.stderr new file mode 100644 index 0000000000..da276296e0 --- /dev/null +++ b/src/tools/clippy/tests/ui/unit_hash.stderr @@ -0,0 +1,27 @@ +error: this call to `hash` on the unit type will do nothing + --> $DIR/unit_hash.rs:18:23 + | +LL | Foo::Empty => ().hash(&mut state), + | ^^^^^^^^^^^^^^^^^^^ help: remove the call to `hash` or consider using: `0_u8.hash(&mut state)` + | + = note: `-D clippy::unit-hash` implied by `-D warnings` + = note: the implementation of `Hash` for `()` is a no-op + +error: this call to `hash` on the unit type will do nothing + --> $DIR/unit_hash.rs:23:5 + | +LL | res.hash(&mut state); + | ^^^^^^^^^^^^^^^^^^^^ help: remove the call to `hash` or consider using: `0_u8.hash(&mut state)` + | + = note: the implementation of `Hash` for `()` is a no-op + +error: this call to `hash` on the unit type will do nothing + --> $DIR/unit_hash.rs:26:5 + | +LL | do_nothing().hash(&mut state); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `hash` or consider using: `0_u8.hash(&mut state)` + | + = note: the implementation of `Hash` for `()` is a no-op + +error: aborting due to 3 previous errors + diff --git a/src/tools/clippy/tests/ui/unnecessary_sort_by.fixed b/src/tools/clippy/tests/ui/unnecessary_sort_by.fixed index b45b27d8f2..d806d620b1 100644 --- a/src/tools/clippy/tests/ui/unnecessary_sort_by.fixed +++ b/src/tools/clippy/tests/ui/unnecessary_sort_by.fixed @@ -2,6 +2,7 @@ #![allow(clippy::stable_sort_primitive)] +use std::cell::Ref; use std::cmp::Reverse; fn unnecessary_sort_by() { @@ -33,6 +34,10 @@ fn unnecessary_sort_by() { // `Reverse(b)` would borrow in the following cases, don't lint vec.sort_by(|a, b| b.cmp(a)); vec.sort_unstable_by(|a, b| b.cmp(a)); + + // No warning if element does not implement `Ord` + let mut vec: Vec<Ref<usize>> = Vec::new(); + vec.sort_unstable_by(|a, b| a.cmp(b)); } // Do not suggest returning a reference to the closure parameter of `Vec::sort_by_key` diff --git a/src/tools/clippy/tests/ui/unnecessary_sort_by.rs b/src/tools/clippy/tests/ui/unnecessary_sort_by.rs index be2abe7f70..6ee9c3af45 100644 --- a/src/tools/clippy/tests/ui/unnecessary_sort_by.rs +++ b/src/tools/clippy/tests/ui/unnecessary_sort_by.rs @@ -2,6 +2,7 @@ #![allow(clippy::stable_sort_primitive)] +use std::cell::Ref; use std::cmp::Reverse; fn unnecessary_sort_by() { @@ -33,6 +34,10 @@ fn unnecessary_sort_by() { // `Reverse(b)` would borrow in the following cases, don't lint vec.sort_by(|a, b| b.cmp(a)); vec.sort_unstable_by(|a, b| b.cmp(a)); + + // No warning if element does not implement `Ord` + let mut vec: Vec<Ref<usize>> = Vec::new(); + vec.sort_unstable_by(|a, b| a.cmp(b)); } // Do not suggest returning a reference to the closure parameter of `Vec::sort_by_key` diff --git a/src/tools/clippy/tests/ui/unnecessary_sort_by.stderr b/src/tools/clippy/tests/ui/unnecessary_sort_by.stderr index 50607933e1..ca9641e880 100644 --- a/src/tools/clippy/tests/ui/unnecessary_sort_by.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_sort_by.stderr @@ -1,5 +1,5 @@ error: use Vec::sort here instead - --> $DIR/unnecessary_sort_by.rs:14:5 + --> $DIR/unnecessary_sort_by.rs:15:5 | LL | vec.sort_by(|a, b| a.cmp(b)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort()` @@ -7,67 +7,67 @@ LL | vec.sort_by(|a, b| a.cmp(b)); = note: `-D clippy::unnecessary-sort-by` implied by `-D warnings` error: use Vec::sort here instead - --> $DIR/unnecessary_sort_by.rs:15:5 + --> $DIR/unnecessary_sort_by.rs:16:5 | LL | vec.sort_unstable_by(|a, b| a.cmp(b)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable()` error: use Vec::sort_by_key here instead - --> $DIR/unnecessary_sort_by.rs:16:5 + --> $DIR/unnecessary_sort_by.rs:17:5 | LL | vec.sort_by(|a, b| (a + 5).abs().cmp(&(b + 5).abs())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|a| (a + 5).abs())` error: use Vec::sort_by_key here instead - --> $DIR/unnecessary_sort_by.rs:17:5 + --> $DIR/unnecessary_sort_by.rs:18:5 | LL | vec.sort_unstable_by(|a, b| id(-a).cmp(&id(-b))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable_by_key(|a| id(-a))` error: use Vec::sort_by_key here instead - --> $DIR/unnecessary_sort_by.rs:20:5 + --> $DIR/unnecessary_sort_by.rs:21:5 | LL | vec.sort_by(|a, b| (b + 5).abs().cmp(&(a + 5).abs())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|b| Reverse((b + 5).abs()))` error: use Vec::sort_by_key here instead - --> $DIR/unnecessary_sort_by.rs:21:5 + --> $DIR/unnecessary_sort_by.rs:22:5 | LL | vec.sort_unstable_by(|a, b| id(-b).cmp(&id(-a))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable_by_key(|b| Reverse(id(-b)))` error: use Vec::sort_by_key here instead - --> $DIR/unnecessary_sort_by.rs:31:5 + --> $DIR/unnecessary_sort_by.rs:32:5 | LL | vec.sort_by(|a, b| (***a).abs().cmp(&(***b).abs())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|a| (***a).abs())` error: use Vec::sort_by_key here instead - --> $DIR/unnecessary_sort_by.rs:32:5 + --> $DIR/unnecessary_sort_by.rs:33:5 | LL | vec.sort_unstable_by(|a, b| (***a).abs().cmp(&(***b).abs())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable_by_key(|a| (***a).abs())` error: use Vec::sort_by_key here instead - --> $DIR/unnecessary_sort_by.rs:88:9 + --> $DIR/unnecessary_sort_by.rs:93:9 | LL | args.sort_by(|a, b| a.name().cmp(&b.name())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_by_key(|a| a.name())` error: use Vec::sort_by_key here instead - --> $DIR/unnecessary_sort_by.rs:89:9 + --> $DIR/unnecessary_sort_by.rs:94:9 | LL | args.sort_unstable_by(|a, b| a.name().cmp(&b.name())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_unstable_by_key(|a| a.name())` error: use Vec::sort_by_key here instead - --> $DIR/unnecessary_sort_by.rs:91:9 + --> $DIR/unnecessary_sort_by.rs:96:9 | LL | args.sort_by(|a, b| b.name().cmp(&a.name())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_by_key(|b| Reverse(b.name()))` error: use Vec::sort_by_key here instead - --> $DIR/unnecessary_sort_by.rs:92:9 + --> $DIR/unnecessary_sort_by.rs:97:9 | LL | args.sort_unstable_by(|a, b| b.name().cmp(&a.name())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_unstable_by_key(|b| Reverse(b.name()))` diff --git a/src/tools/clippy/tests/ui/unused_async.rs b/src/tools/clippy/tests/ui/unused_async.rs index 4f4203f5fd..2a3a506a57 100644 --- a/src/tools/clippy/tests/ui/unused_async.rs +++ b/src/tools/clippy/tests/ui/unused_async.rs @@ -1,4 +1,3 @@ -// edition:2018 #![warn(clippy::unused_async)] async fn foo() -> i32 { diff --git a/src/tools/clippy/tests/ui/unused_async.stderr b/src/tools/clippy/tests/ui/unused_async.stderr index 8b834d205b..cc6096d65d 100644 --- a/src/tools/clippy/tests/ui/unused_async.stderr +++ b/src/tools/clippy/tests/ui/unused_async.stderr @@ -1,5 +1,5 @@ error: unused `async` for function with no await statements - --> $DIR/unused_async.rs:4:1 + --> $DIR/unused_async.rs:3:1 | LL | / async fn foo() -> i32 { LL | | 4 diff --git a/src/tools/clippy/tests/ui/use_self.fixed b/src/tools/clippy/tests/ui/use_self.fixed index dcf818f807..4e33e343ce 100644 --- a/src/tools/clippy/tests/ui/use_self.fixed +++ b/src/tools/clippy/tests/ui/use_self.fixed @@ -1,5 +1,4 @@ // run-rustfix -// edition:2018 // aux-build:proc_macro_derive.rs #![warn(clippy::use_self)] diff --git a/src/tools/clippy/tests/ui/use_self.rs b/src/tools/clippy/tests/ui/use_self.rs index 9da6fef7a3..7b621ff9bc 100644 --- a/src/tools/clippy/tests/ui/use_self.rs +++ b/src/tools/clippy/tests/ui/use_self.rs @@ -1,5 +1,4 @@ // run-rustfix -// edition:2018 // aux-build:proc_macro_derive.rs #![warn(clippy::use_self)] diff --git a/src/tools/clippy/tests/ui/use_self.stderr b/src/tools/clippy/tests/ui/use_self.stderr index e14368a11a..ecb78b3f97 100644 --- a/src/tools/clippy/tests/ui/use_self.stderr +++ b/src/tools/clippy/tests/ui/use_self.stderr @@ -1,5 +1,5 @@ error: unnecessary structure name repetition - --> $DIR/use_self.rs:23:21 + --> $DIR/use_self.rs:22:21 | LL | fn new() -> Foo { | ^^^ help: use the applicable keyword: `Self` @@ -7,163 +7,163 @@ LL | fn new() -> Foo { = note: `-D clippy::use-self` implied by `-D warnings` error: unnecessary structure name repetition - --> $DIR/use_self.rs:24:13 + --> $DIR/use_self.rs:23:13 | LL | Foo {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:26:22 + --> $DIR/use_self.rs:25:22 | LL | fn test() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:27:13 + --> $DIR/use_self.rs:26:13 | LL | Foo::new() | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:32:25 + --> $DIR/use_self.rs:31:25 | LL | fn default() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:33:13 + --> $DIR/use_self.rs:32:13 | LL | Foo::new() | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:98:24 + --> $DIR/use_self.rs:97:24 | LL | fn bad(foos: &[Foo]) -> impl Iterator<Item = &Foo> { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:98:55 + --> $DIR/use_self.rs:97:55 | LL | fn bad(foos: &[Foo]) -> impl Iterator<Item = &Foo> { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:113:13 + --> $DIR/use_self.rs:112:13 | LL | TS(0) | ^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:148:29 + --> $DIR/use_self.rs:147:29 | LL | fn bar() -> Bar { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:149:21 + --> $DIR/use_self.rs:148:21 | LL | Bar { foo: Foo {} } | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:160:21 + --> $DIR/use_self.rs:159:21 | LL | fn baz() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:161:13 + --> $DIR/use_self.rs:160:13 | LL | Foo {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:178:21 + --> $DIR/use_self.rs:177:21 | LL | let _ = Enum::B(42); | ^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:179:21 + --> $DIR/use_self.rs:178:21 | LL | let _ = Enum::C { field: true }; | ^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:180:21 + --> $DIR/use_self.rs:179:21 | LL | let _ = Enum::A; | ^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:222:13 + --> $DIR/use_self.rs:221:13 | LL | nested::A::fun_1(); | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:223:13 + --> $DIR/use_self.rs:222:13 | LL | nested::A::A; | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:225:13 + --> $DIR/use_self.rs:224:13 | LL | nested::A {}; | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:244:13 + --> $DIR/use_self.rs:243:13 | LL | TestStruct::from_something() | ^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:258:25 + --> $DIR/use_self.rs:257:25 | LL | async fn g() -> S { | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:259:13 + --> $DIR/use_self.rs:258:13 | LL | S {} | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:263:16 + --> $DIR/use_self.rs:262:16 | LL | &p[S::A..S::B] | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:263:22 + --> $DIR/use_self.rs:262:22 | LL | &p[S::A..S::B] | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:286:29 + --> $DIR/use_self.rs:285:29 | LL | fn foo(value: T) -> Foo<T> { | ^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:287:13 + --> $DIR/use_self.rs:286:13 | LL | Foo::<T> { value } | ^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:459:13 + --> $DIR/use_self.rs:458:13 | LL | A::new::<submod::B>(submod::B {}) | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:496:13 + --> $DIR/use_self.rs:495:13 | LL | S2::new() | ^^ help: use the applicable keyword: `Self` diff --git a/src/tools/clippy/tests/ui/used_underscore_binding.rs b/src/tools/clippy/tests/ui/used_underscore_binding.rs index d8bda7e8f4..21d66d5df7 100644 --- a/src/tools/clippy/tests/ui/used_underscore_binding.rs +++ b/src/tools/clippy/tests/ui/used_underscore_binding.rs @@ -1,4 +1,3 @@ -// edition:2018 // aux-build:proc_macro_derive.rs #![feature(rustc_private)] diff --git a/src/tools/clippy/tests/ui/used_underscore_binding.stderr b/src/tools/clippy/tests/ui/used_underscore_binding.stderr index 2cbfc5ca2e..790b849210 100644 --- a/src/tools/clippy/tests/ui/used_underscore_binding.stderr +++ b/src/tools/clippy/tests/ui/used_underscore_binding.stderr @@ -1,5 +1,5 @@ error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used - --> $DIR/used_underscore_binding.rs:26:5 + --> $DIR/used_underscore_binding.rs:25:5 | LL | _foo + 1 | ^^^^ @@ -7,31 +7,31 @@ LL | _foo + 1 = note: `-D clippy::used-underscore-binding` implied by `-D warnings` error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used - --> $DIR/used_underscore_binding.rs:31:20 + --> $DIR/used_underscore_binding.rs:30:20 | LL | println!("{}", _foo); | ^^^^ error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used - --> $DIR/used_underscore_binding.rs:32:16 + --> $DIR/used_underscore_binding.rs:31:16 | LL | assert_eq!(_foo, _foo); | ^^^^ error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used - --> $DIR/used_underscore_binding.rs:32:22 + --> $DIR/used_underscore_binding.rs:31:22 | LL | assert_eq!(_foo, _foo); | ^^^^ error: used binding `_underscore_field` which is prefixed with an underscore. A leading underscore signals that a binding will not be used - --> $DIR/used_underscore_binding.rs:45:5 + --> $DIR/used_underscore_binding.rs:44:5 | LL | s._underscore_field += 1; | ^^^^^^^^^^^^^^^^^^^ error: used binding `_i` which is prefixed with an underscore. A leading underscore signals that a binding will not be used - --> $DIR/used_underscore_binding.rs:100:16 + --> $DIR/used_underscore_binding.rs:99:16 | LL | uses_i(_i); | ^^ diff --git a/src/tools/clippy/tests/ui/useless_conversion.fixed b/src/tools/clippy/tests/ui/useless_conversion.fixed index 76aa82068d..70ff08f365 100644 --- a/src/tools/clippy/tests/ui/useless_conversion.fixed +++ b/src/tools/clippy/tests/ui/useless_conversion.fixed @@ -66,7 +66,7 @@ fn main() { let _ = vec![1, 2, 3].into_iter(); let _: String = format!("Hello {}", "world"); - // keep parenthesis around `a + b` for suggestion (see #4750) + // keep parentheses around `a + b` for suggestion (see #4750) let a: i32 = 1; let b: i32 = 1; let _ = (a + b) * 3; diff --git a/src/tools/clippy/tests/ui/useless_conversion.rs b/src/tools/clippy/tests/ui/useless_conversion.rs index ccee7abb40..f2444a8f43 100644 --- a/src/tools/clippy/tests/ui/useless_conversion.rs +++ b/src/tools/clippy/tests/ui/useless_conversion.rs @@ -66,7 +66,7 @@ fn main() { let _ = vec![1, 2, 3].into_iter().into_iter(); let _: String = format!("Hello {}", "world").into(); - // keep parenthesis around `a + b` for suggestion (see #4750) + // keep parentheses around `a + b` for suggestion (see #4750) let a: i32 = 1; let b: i32 = 1; let _ = i32::from(a + b) * 3; diff --git a/src/tools/clippy/tests/ui/wildcard_imports.fixed b/src/tools/clippy/tests/ui/wildcard_imports.fixed index ee9c9045ff..8402c33a4c 100644 --- a/src/tools/clippy/tests/ui/wildcard_imports.fixed +++ b/src/tools/clippy/tests/ui/wildcard_imports.fixed @@ -1,8 +1,13 @@ +// edition:2015 // run-rustfix // aux-build:wildcard_imports_helper.rs +// the 2015 edition here is needed because edition 2018 changed the module system +// (see https://doc.rust-lang.org/edition-guide/rust-2018/path-changes.html) which means the lint +// no longer detects some of the cases starting with Rust 2018. +// FIXME: We should likely add another edition 2021 test case for this lint + #![warn(clippy::wildcard_imports)] -//#![allow(clippy::redundant_pub_crate)] #![allow(unused)] #![allow(clippy::unnecessary_wraps)] #![warn(unused_imports)] @@ -230,4 +235,12 @@ mod super_imports { let _ = foofoo(); } } + + mod attestation_should_be_replaced { + use super::foofoo; + + fn with_explicit() { + let _ = foofoo(); + } + } } diff --git a/src/tools/clippy/tests/ui/wildcard_imports.rs b/src/tools/clippy/tests/ui/wildcard_imports.rs index efaa8f9ef6..faaeaade9b 100644 --- a/src/tools/clippy/tests/ui/wildcard_imports.rs +++ b/src/tools/clippy/tests/ui/wildcard_imports.rs @@ -1,8 +1,13 @@ +// edition:2015 // run-rustfix // aux-build:wildcard_imports_helper.rs +// the 2015 edition here is needed because edition 2018 changed the module system +// (see https://doc.rust-lang.org/edition-guide/rust-2018/path-changes.html) which means the lint +// no longer detects some of the cases starting with Rust 2018. +// FIXME: We should likely add another edition 2021 test case for this lint + #![warn(clippy::wildcard_imports)] -//#![allow(clippy::redundant_pub_crate)] #![allow(unused)] #![allow(clippy::unnecessary_wraps)] #![warn(unused_imports)] @@ -231,4 +236,12 @@ mod super_imports { let _ = foofoo(); } } + + mod attestation_should_be_replaced { + use super::*; + + fn with_explicit() { + let _ = foofoo(); + } + } } diff --git a/src/tools/clippy/tests/ui/wildcard_imports.stderr b/src/tools/clippy/tests/ui/wildcard_imports.stderr index 66267dd27b..7534a65ec9 100644 --- a/src/tools/clippy/tests/ui/wildcard_imports.stderr +++ b/src/tools/clippy/tests/ui/wildcard_imports.stderr @@ -1,5 +1,5 @@ error: usage of wildcard import - --> $DIR/wildcard_imports.rs:12:5 + --> $DIR/wildcard_imports.rs:17:5 | LL | use crate::fn_mod::*; | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo` @@ -7,85 +7,85 @@ LL | use crate::fn_mod::*; = note: `-D clippy::wildcard-imports` implied by `-D warnings` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:13:5 + --> $DIR/wildcard_imports.rs:18:5 | LL | use crate::mod_mod::*; | ^^^^^^^^^^^^^^^^^ help: try: `crate::mod_mod::inner_mod` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:14:5 + --> $DIR/wildcard_imports.rs:19:5 | LL | use crate::multi_fn_mod::*; | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:16:5 + --> $DIR/wildcard_imports.rs:21:5 | LL | use crate::struct_mod::*; | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::struct_mod::{A, inner_struct_mod}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:20:5 + --> $DIR/wildcard_imports.rs:25:5 | LL | use wildcard_imports_helper::inner::inner_for_self_import::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:21:5 + --> $DIR/wildcard_imports.rs:26:5 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:92:13 + --> $DIR/wildcard_imports.rs:97:13 | LL | use crate::fn_mod::*; | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:98:75 + --> $DIR/wildcard_imports.rs:103:75 | LL | use wildcard_imports_helper::inner::inner_for_self_import::{self, *}; | ^ help: try: `inner_extern_foo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:99:13 + --> $DIR/wildcard_imports.rs:104:13 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:110:20 + --> $DIR/wildcard_imports.rs:115:20 | LL | use self::{inner::*, inner2::*}; | ^^^^^^^^ help: try: `inner::inner_foo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:110:30 + --> $DIR/wildcard_imports.rs:115:30 | LL | use self::{inner::*, inner2::*}; | ^^^^^^^^^ help: try: `inner2::inner_bar` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:117:13 + --> $DIR/wildcard_imports.rs:122:13 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:146:9 + --> $DIR/wildcard_imports.rs:151:9 | LL | use crate::in_fn_test::*; | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:155:9 + --> $DIR/wildcard_imports.rs:160:9 | LL | use crate:: in_fn_test:: * ; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:156:9 + --> $DIR/wildcard_imports.rs:161:9 | LL | use crate:: fn_mod:: | _________^ @@ -93,34 +93,40 @@ LL | | *; | |_________^ help: try: `crate:: fn_mod::foo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:167:13 + --> $DIR/wildcard_imports.rs:172:13 | LL | use super::*; | ^^^^^^^^ help: try: `super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:202:17 + --> $DIR/wildcard_imports.rs:207:17 | LL | use super::*; | ^^^^^^^^ help: try: `super::insidefoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:210:13 + --> $DIR/wildcard_imports.rs:215:13 | LL | use super_imports::*; | ^^^^^^^^^^^^^^^^ help: try: `super_imports::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:219:17 + --> $DIR/wildcard_imports.rs:224:17 | LL | use super::super::*; | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:228:13 + --> $DIR/wildcard_imports.rs:233:13 | LL | use super::super::super_imports::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo` -error: aborting due to 20 previous errors +error: usage of wildcard import + --> $DIR/wildcard_imports.rs:241:13 + | +LL | use super::*; + | ^^^^^^^^ help: try: `super::foofoo` + +error: aborting due to 21 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 151dd0c27d..1b9da8a55e 100644 --- a/src/tools/clippy/tests/ui/wrong_self_convention.rs +++ b/src/tools/clippy/tests/ui/wrong_self_convention.rs @@ -1,4 +1,3 @@ -// edition:2018 #![warn(clippy::wrong_self_convention)] #![allow(dead_code)] diff --git a/src/tools/clippy/tests/ui/wrong_self_convention.stderr b/src/tools/clippy/tests/ui/wrong_self_convention.stderr index ce23317abf..590ee6d9c5 100644 --- a/src/tools/clippy/tests/ui/wrong_self_convention.stderr +++ b/src/tools/clippy/tests/ui/wrong_self_convention.stderr @@ -1,5 +1,5 @@ error: methods called `from_*` usually take no `self` - --> $DIR/wrong_self_convention.rs:17:17 + --> $DIR/wrong_self_convention.rs:16:17 | LL | fn from_i32(self) {} | ^^^^ @@ -8,7 +8,7 @@ LL | fn from_i32(self) {} = help: consider choosing a less ambiguous name error: methods called `from_*` usually take no `self` - --> $DIR/wrong_self_convention.rs:23:21 + --> $DIR/wrong_self_convention.rs:22:21 | LL | pub fn from_i64(self) {} | ^^^^ @@ -16,7 +16,7 @@ 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 - --> $DIR/wrong_self_convention.rs:35:15 + --> $DIR/wrong_self_convention.rs:34:15 | LL | fn as_i32(self) {} | ^^^^ @@ -24,7 +24,7 @@ LL | fn as_i32(self) {} = help: consider choosing a less ambiguous name error: methods called `into_*` usually take `self` by value - --> $DIR/wrong_self_convention.rs:37:17 + --> $DIR/wrong_self_convention.rs:36:17 | LL | fn into_i32(&self) {} | ^^^^^ @@ -32,7 +32,7 @@ LL | fn into_i32(&self) {} = help: consider choosing a less ambiguous name error: methods called `is_*` usually take `self` by reference or no `self` - --> $DIR/wrong_self_convention.rs:39:15 + --> $DIR/wrong_self_convention.rs:38:15 | LL | fn is_i32(self) {} | ^^^^ @@ -40,7 +40,7 @@ LL | fn is_i32(self) {} = 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:41:15 + --> $DIR/wrong_self_convention.rs:40:15 | LL | fn to_i32(self) {} | ^^^^ @@ -48,7 +48,7 @@ LL | fn to_i32(self) {} = help: consider choosing a less ambiguous name error: methods called `from_*` usually take no `self` - --> $DIR/wrong_self_convention.rs:43:17 + --> $DIR/wrong_self_convention.rs:42:17 | LL | fn from_i32(self) {} | ^^^^ @@ -56,7 +56,7 @@ 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 - --> $DIR/wrong_self_convention.rs:45:19 + --> $DIR/wrong_self_convention.rs:44:19 | LL | pub fn as_i64(self) {} | ^^^^ @@ -64,7 +64,7 @@ LL | pub fn as_i64(self) {} = help: consider choosing a less ambiguous name error: methods called `into_*` usually take `self` by value - --> $DIR/wrong_self_convention.rs:46:21 + --> $DIR/wrong_self_convention.rs:45:21 | LL | pub fn into_i64(&self) {} | ^^^^^ @@ -72,7 +72,7 @@ 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` - --> $DIR/wrong_self_convention.rs:47:19 + --> $DIR/wrong_self_convention.rs:46:19 | LL | pub fn is_i64(self) {} | ^^^^ @@ -80,7 +80,7 @@ LL | pub fn is_i64(self) {} = 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:48:19 + --> $DIR/wrong_self_convention.rs:47:19 | LL | pub fn to_i64(self) {} | ^^^^ @@ -88,7 +88,7 @@ LL | pub fn to_i64(self) {} = help: consider choosing a less ambiguous name error: methods called `from_*` usually take no `self` - --> $DIR/wrong_self_convention.rs:49:21 + --> $DIR/wrong_self_convention.rs:48:21 | LL | pub fn from_i64(self) {} | ^^^^ @@ -96,7 +96,7 @@ 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 - --> $DIR/wrong_self_convention.rs:94:19 + --> $DIR/wrong_self_convention.rs:93:19 | LL | fn as_i32(self) {} | ^^^^ @@ -104,7 +104,7 @@ LL | fn as_i32(self) {} = help: consider choosing a less ambiguous name error: methods called `into_*` usually take `self` by value - --> $DIR/wrong_self_convention.rs:97:25 + --> $DIR/wrong_self_convention.rs:96:25 | LL | fn into_i32_ref(&self) {} | ^^^^^ @@ -112,7 +112,7 @@ 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` - --> $DIR/wrong_self_convention.rs:99:19 + --> $DIR/wrong_self_convention.rs:98:19 | LL | fn is_i32(self) {} | ^^^^ @@ -120,7 +120,7 @@ LL | fn is_i32(self) {} = help: consider choosing a less ambiguous name error: methods called `from_*` usually take no `self` - --> $DIR/wrong_self_convention.rs:103:21 + --> $DIR/wrong_self_convention.rs:102:21 | LL | fn from_i32(self) {} | ^^^^ @@ -128,7 +128,7 @@ 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 - --> $DIR/wrong_self_convention.rs:118:19 + --> $DIR/wrong_self_convention.rs:117:19 | LL | fn as_i32(self); | ^^^^ @@ -136,7 +136,7 @@ LL | fn as_i32(self); = help: consider choosing a less ambiguous name error: methods called `into_*` usually take `self` by value - --> $DIR/wrong_self_convention.rs:121:25 + --> $DIR/wrong_self_convention.rs:120:25 | LL | fn into_i32_ref(&self); | ^^^^^ @@ -144,7 +144,7 @@ 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` - --> $DIR/wrong_self_convention.rs:123:19 + --> $DIR/wrong_self_convention.rs:122:19 | LL | fn is_i32(self); | ^^^^ @@ -152,7 +152,7 @@ LL | fn is_i32(self); = help: consider choosing a less ambiguous name error: methods called `from_*` usually take no `self` - --> $DIR/wrong_self_convention.rs:127:21 + --> $DIR/wrong_self_convention.rs:126:21 | LL | fn from_i32(self); | ^^^^ @@ -160,7 +160,7 @@ LL | fn from_i32(self); = help: consider choosing a less ambiguous name error: methods called `into_*` usually take `self` by value - --> $DIR/wrong_self_convention.rs:145:25 + --> $DIR/wrong_self_convention.rs:144:25 | LL | fn into_i32_ref(&self); | ^^^^^ @@ -168,7 +168,7 @@ LL | fn into_i32_ref(&self); = help: consider choosing a less ambiguous name error: methods called `from_*` usually take no `self` - --> $DIR/wrong_self_convention.rs:151:21 + --> $DIR/wrong_self_convention.rs:150:21 | LL | fn from_i32(self); | ^^^^ @@ -176,7 +176,7 @@ 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:175:22 + --> $DIR/wrong_self_convention.rs:174:22 | LL | fn to_u64_v2(&self) -> u64 { | ^^^^^ @@ -184,7 +184,7 @@ 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:184:19 + --> $DIR/wrong_self_convention.rs:183:19 | LL | fn to_u64(self) -> u64 { | ^^^^ diff --git a/src/tools/clippy/tests/ui/wrong_self_convention2.rs b/src/tools/clippy/tests/ui/wrong_self_convention2.rs index 0d827c1feb..a8fe833113 100644 --- a/src/tools/clippy/tests/ui/wrong_self_convention2.rs +++ b/src/tools/clippy/tests/ui/wrong_self_convention2.rs @@ -1,4 +1,3 @@ -// edition:2018 #![warn(clippy::wrong_self_convention)] #![allow(dead_code)] diff --git a/src/tools/clippy/tests/ui/wrong_self_convention2.stderr b/src/tools/clippy/tests/ui/wrong_self_convention2.stderr index 0e0d066d65..5bdc47f91f 100644 --- a/src/tools/clippy/tests/ui/wrong_self_convention2.stderr +++ b/src/tools/clippy/tests/ui/wrong_self_convention2.stderr @@ -1,5 +1,5 @@ error: methods called `from_*` usually take no `self` - --> $DIR/wrong_self_convention2.rs:55:29 + --> $DIR/wrong_self_convention2.rs:54:29 | LL | pub fn from_be_self(self) -> Self { | ^^^^ @@ -8,7 +8,7 @@ LL | pub fn from_be_self(self) -> Self { = help: consider choosing a less ambiguous name error: methods called `from_*` usually take no `self` - --> $DIR/wrong_self_convention2.rs:64:25 + --> $DIR/wrong_self_convention2.rs:63:25 | LL | fn from_be_self(self) -> Self; | ^^^^ diff --git a/src/tools/clippy/tests/ui/wrong_self_conventions_mut.rs b/src/tools/clippy/tests/ui/wrong_self_conventions_mut.rs index 486a0d7723..5bb2116bd3 100644 --- a/src/tools/clippy/tests/ui/wrong_self_conventions_mut.rs +++ b/src/tools/clippy/tests/ui/wrong_self_conventions_mut.rs @@ -1,4 +1,3 @@ -// edition:2018 #![warn(clippy::wrong_self_convention)] #![allow(dead_code)] diff --git a/src/tools/clippy/tests/ui/wrong_self_conventions_mut.stderr b/src/tools/clippy/tests/ui/wrong_self_conventions_mut.stderr index 6ce37c5949..8665d8dc9a 100644 --- a/src/tools/clippy/tests/ui/wrong_self_conventions_mut.stderr +++ b/src/tools/clippy/tests/ui/wrong_self_conventions_mut.stderr @@ -1,5 +1,5 @@ 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 + --> $DIR/wrong_self_conventions_mut.rs:14:24 | LL | pub fn to_many(&mut self) -> Option<&mut [T]> { | ^^^^^^^^^ @@ -8,7 +8,7 @@ LL | pub fn to_many(&mut self) -> Option<&mut [T]> { = 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 + --> $DIR/wrong_self_conventions_mut.rs:22:28 | LL | pub fn to_many_mut(&self) -> Option<&[T]> { | ^^^^^ diff --git a/src/tools/clippy/tests/ui_test/eq_op.rs b/src/tools/clippy/tests/ui_test/eq_op.rs new file mode 100644 index 0000000000..f2f5f1e588 --- /dev/null +++ b/src/tools/clippy/tests/ui_test/eq_op.rs @@ -0,0 +1,15 @@ +#[warn(clippy::eq_op)] +#[test] +fn eq_op_shouldnt_trigger_in_tests() { + let a = 1; + let result = a + 1 == 1 + a; + assert!(result); +} + +#[test] +fn eq_op_macros_shouldnt_trigger_in_tests() { + let a = 1; + let b = 2; + assert_eq!(a, a); + assert_eq!(a + b, b + a); +} diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index cd0a56d08d..82fe790a57 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -349,6 +349,9 @@ pub struct Config { /// The current Rust channel pub channel: String, + /// The default Rust edition + pub edition: Option<String>, + // Configuration for various run-make tests frobbing things like C compilers // or querying about various LLVM component information. pub cc: String, diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index efd8550279..5fcaa452ca 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -222,6 +222,7 @@ impl TestProps { /// `//[foo]`), then the property is ignored unless `cfg` is /// `Some("foo")`. fn load_from(&mut self, testfile: &Path, cfg: Option<&str>, config: &Config) { + let mut has_edition = false; if !testfile.is_dir() { let file = File::open(testfile).unwrap(); @@ -240,9 +241,7 @@ impl TestProps { if let Some(edition) = config.parse_edition(ln) { self.compile_flags.push(format!("--edition={}", edition)); - if edition == "2021" { - self.compile_flags.push("-Zunstable-options".to_string()); - } + has_edition = true; } config.parse_and_update_revisions(ln, &mut self.revisions); @@ -391,6 +390,10 @@ impl TestProps { } } } + + if let (Some(edition), false) = (&config.edition, has_edition) { + self.compile_flags.push(format!("--edition={}", edition)); + } } fn update_fail_mode(&mut self, ln: &str, config: &Config) { diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 2485dbadab..157b42e2d1 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -168,7 +168,7 @@ fn only_target() { let mut config = config(); config.target = "x86_64-pc-windows-gnu".to_owned(); - assert!(check_ignore(&config, "// only-i686")); + assert!(check_ignore(&config, "// only-x86")); assert!(check_ignore(&config, "// only-linux")); assert!(check_ignore(&config, "// only-msvc")); assert!(check_ignore(&config, "// only-32bit")); diff --git a/src/tools/compiletest/src/json.rs b/src/tools/compiletest/src/json.rs index dc6d67983c..a5ff779a4a 100644 --- a/src/tools/compiletest/src/json.rs +++ b/src/tools/compiletest/src/json.rs @@ -74,8 +74,6 @@ struct DiagnosticSpanMacroExpansion { struct DiagnosticCode { /// The code itself. code: String, - /// An explanation for the code. - explanation: Option<String>, } pub fn rustfix_diagnostics_only(output: &str) -> String { diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 87aba8c5d3..58cde108b3 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -147,7 +147,8 @@ pub fn parse_config(args: Vec<String>) -> Config { ) .optflag("", "force-rerun", "rerun tests even if the inputs are unchanged") .optflag("h", "help", "show this message") - .reqopt("", "channel", "current Rust channel", "CHANNEL"); + .reqopt("", "channel", "current Rust channel", "CHANNEL") + .optopt("", "edition", "default Rust edition", "EDITION"); let (argv0, args_) = args.split_first().unwrap(); if args.len() == 1 || args[1] == "-h" || args[1] == "--help" { @@ -282,6 +283,7 @@ pub fn parse_config(args: Vec<String>) -> Config { rustfix_coverage: matches.opt_present("rustfix-coverage"), has_tidy, channel: matches.opt_str("channel").unwrap(), + edition: matches.opt_str("edition"), cc: matches.opt_str("cc").unwrap(), cxx: matches.opt_str("cxx").unwrap(), diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 4470272a9f..3c85b9076d 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1607,9 +1607,6 @@ impl<'test> TestCx<'test> { get_lib_name(&aux_path.trim_end_matches(".rs").replace('-', "_"), is_dylib); rustc.arg("--extern").arg(format!("{}={}/{}", aux_name, aux_dir.display(), lib_name)); } - if !self.props.aux_crates.is_empty() { - rustc.arg("-Zunstable-options"); - } aux_dir } diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index d03c21dc50..6ca145a58e 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -133,8 +133,10 @@ const BIG_ENDIAN: &[&str] = &[ ]; static ASM_SUPPORTED_ARCHS: &[&str] = &[ - "x86", "x86_64", "arm", "aarch64", "riscv32", "riscv64", "nvptx64", "hexagon", "mips", - "mips64", "spirv", "wasm32", + "x86", "x86_64", "arm", "aarch64", "riscv32", + "riscv64", + // These targets require an additional asm_experimental_arch feature. + // "nvptx64", "hexagon", "mips", "mips64", "spirv", "wasm32", ]; pub fn has_asm_support(triple: &str) -> bool { diff --git a/src/tools/html-checker/main.rs b/src/tools/html-checker/main.rs index 7bdf527d88..f52fbdfe2d 100644 --- a/src/tools/html-checker/main.rs +++ b/src/tools/html-checker/main.rs @@ -79,11 +79,34 @@ fn find_all_html_files(dir: &Path) -> (usize, usize) { (files_read, errors) } +/// Default `tidy` command for macOS is too old that it does not have `mute-id` and `mute` options. +/// `tidy` on macOS Monterey was released on 31 October 2006, and the same date can be seen seven +/// years ago at <https://stackoverflow.com/questions/22283382/overwrite-osx-tidy>. Accordingly, +/// the macOS environment using pre-installed `tidy` should immediately suspend HTML checker process +/// and show a hint to install a newer one. +#[cfg(target_os = "macos")] +fn check_tidy_version() -> Result<(), String> { + let output = Command::new("tidy").arg("-v").output().expect("failed to run tidy command"); + let version = String::from_utf8(output.stdout).expect("failed to read version of tidy command"); + if version.contains("HTML Tidy for Mac OS X released on 31 October 2006") { + eprintln!("The pre-installed HTML Tidy for macOS is not supported."); + eprintln!("Consider installing a newer one and re-running."); + eprintln!("If you're using Homebrew, you can install it by the following command:"); + eprintln!(" brew install tidy-html5"); + eprintln!(); + Err("HTML check failed: 1 error".to_string()) + } else { + Ok(()) + } +} + fn main() -> Result<(), String> { let args = env::args().collect::<Vec<_>>(); if args.len() != 2 { return Err(format!("Usage: {} <doc folder>", args[0])); } + #[cfg(target_os = "macos")] + check_tidy_version()?; println!("Running HTML checker..."); diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index 94ebbb33e8..94e82e3d9f 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -85,6 +85,8 @@ const INTRA_DOC_LINK_EXCEPTIONS: &[(&str, &[&str])] = &[ ("core/slice/trait.SliceIndex.html", &["begin</code>, <code>end"]), ("alloc/slice/trait.SliceIndex.html", &["begin</code>, <code>end"]), ("std/slice/trait.SliceIndex.html", &["begin</code>, <code>end"]), + ("core/primitive.str.html", &["begin</code>, <code>end"]), + ("std/primitive.str.html", &["begin</code>, <code>end"]), ]; diff --git a/src/tools/rustdoc-gui/tester.js b/src/tools/rustdoc-gui/tester.js index b598c63f52..0d6a2605d4 100644 --- a/src/tools/rustdoc-gui/tester.js +++ b/src/tools/rustdoc-gui/tester.js @@ -194,7 +194,7 @@ async function main(argv) { .then(out => { const [output, nb_failures] = out; results[nb_failures === 0 ? "successful" : "failed"].push({ - file_name: file_name, + file_name: testPath, output: output, }); if (nb_failures > 0) { @@ -206,7 +206,7 @@ async function main(argv) { }) .catch(err => { results.errored.push({ - file_name: file_name, + file_name: testPath + file_name, output: err, }); status_bar.erroneous(); @@ -239,7 +239,7 @@ async function main(argv) { console.log(""); results.failed.sort(by_filename); results.failed.forEach(r => { - console.log(r.output); + console.log(r.file_name, r.output); }); } if (results.errored.length > 0) { @@ -247,7 +247,7 @@ async function main(argv) { // print run errors on the bottom so developers see them better results.errored.sort(by_filename); results.errored.forEach(r => { - console.error(r.output); + console.error(r.file_name, r.output); }); } diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index bb9cd00f3f..4f73a7f634 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -401,7 +401,8 @@ function showHelp() { console.log(" --doc-folder [PATH] : location of the generated doc folder"); console.log(" --help : show this message then quit"); console.log(" --crate-name [STRING] : crate name to be used"); - console.log(" --test-file [PATH] : location of the JS test file"); + console.log(" --test-file [PATHs] : location of the JS test files (can be called " + + "multiple times)"); console.log(" --test-folder [PATH] : location of the JS tests folder"); console.log(" --resource-suffix [STRING] : suffix to refer to the correct files"); } @@ -412,9 +413,9 @@ function parseOptions(args) { "resource_suffix": "", "doc_folder": "", "test_folder": "", - "test_file": "", + "test_file": [], }; - var correspondances = { + var correspondences = { "--resource-suffix": "resource_suffix", "--doc-folder": "doc_folder", "--test-folder": "test_folder", @@ -423,17 +424,17 @@ function parseOptions(args) { }; for (var i = 0; i < args.length; ++i) { - if (args[i] === "--resource-suffix" - || args[i] === "--doc-folder" - || args[i] === "--test-folder" - || args[i] === "--test-file" - || args[i] === "--crate-name") { + if (correspondences.hasOwnProperty(args[i])) { i += 1; if (i >= args.length) { console.log("Missing argument after `" + args[i - 1] + "` option."); return null; } - opts[correspondances[args[i - 1]]] = args[i]; + if (args[i - 1] !== "--test-file") { + opts[correspondences[args[i - 1]]] = args[i]; + } else { + opts[correspondences[args[i - 1]]].push(args[i]); + } } else if (args[i] === "--help") { showHelp(); process.exit(0); @@ -475,9 +476,10 @@ function main(argv) { var errors = 0; if (opts["test_file"].length !== 0) { - errors += checkFile(opts["test_file"], opts, loaded, index); - } - if (opts["test_folder"].length !== 0) { + opts["test_file"].forEach(function(file) { + errors += checkFile(file, opts, loaded, index); + }); + } else if (opts["test_folder"].length !== 0) { fs.readdirSync(opts["test_folder"]).forEach(function(file) { if (!file.endsWith(".js")) { return; diff --git a/src/tools/rustfmt/.github/workflows/rustdoc_check.yml b/src/tools/rustfmt/.github/workflows/rustdoc_check.yml new file mode 100644 index 0000000000..ca96d30f58 --- /dev/null +++ b/src/tools/rustfmt/.github/workflows/rustdoc_check.yml @@ -0,0 +1,25 @@ +name: rustdoc check +on: + push: + branches: + - master + pull_request: + +jobs: + rustdoc_check: + runs-on: ubuntu-latest + name: rustdoc check + steps: + - name: checkout + uses: actions/checkout@v2 + + - 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 x86_64-unknown-linux-gnu + + - name: document rustfmt + env: + RUSTDOCFLAGS: --document-private-items --enable-index-page --show-type-layout --generate-link-to-definition -Zunstable-options -Dwarnings + run: cargo doc -Zskip-rustdoc-fingerprint --no-deps -p rustfmt-nightly -p rustfmt-config_proc_macro diff --git a/src/tools/rustfmt/.github/workflows/upload-assets.yml b/src/tools/rustfmt/.github/workflows/upload-assets.yml index 9a5fd0dd1d..f4dd394445 100644 --- a/src/tools/rustfmt/.github/workflows/upload-assets.yml +++ b/src/tools/rustfmt/.github/workflows/upload-assets.yml @@ -1,8 +1,10 @@ name: upload on: + push: release: types: [created] + workflow_dispatch: jobs: build-release: @@ -14,42 +16,40 @@ jobs: - build: linux-x86_64 os: ubuntu-latest rust: nightly + target: x86_64-unknown-linux-gnu - build: macos-x86_64 os: macos-latest rust: nightly + target: x86_64-apple-darwin - build: windows-x86_64-gnu os: windows-latest rust: nightly-x86_64-gnu + target: x86_64-pc-windows-gnu - build: windows-x86_64-msvc os: windows-latest rust: nightly-x86_64-msvc + target: x86_64-pc-windows-msvc runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 - - name: Install Rust - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: ${{ matrix.rust }} - override: true + # Run build + - 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: Add mingw64 to path for x86_64-gnu run: echo "C:\msys64\mingw64\bin" >> $GITHUB_PATH if: matrix.rust == 'nightly-x86_64-gnu' shell: bash - - name: Install cargo-make - uses: actions-rs/cargo@v1 - with: - command: install - args: --force cargo-make - - name: Build release binaries uses: actions-rs/cargo@v1 with: - command: make - args: release + command: build + args: --release - name: Build archive shell: bash @@ -70,6 +70,7 @@ jobs: fi - name: Upload Release Asset + if: github.event_name == 'release' uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/src/tools/rustfmt/.github/workflows/windows.yml b/src/tools/rustfmt/.github/workflows/windows.yml index 08cb52eeda..c05e8d4896 100644 --- a/src/tools/rustfmt/.github/workflows/windows.yml +++ b/src/tools/rustfmt/.github/workflows/windows.yml @@ -54,9 +54,6 @@ jobs: if: matrix.target == 'x86_64-pc-windows-gnu' && matrix.channel == 'nightly' shell: bash - - name: cargo-make - run: cargo install --force cargo-make - - name: build run: | rustc -Vv diff --git a/src/tools/rustfmt/CHANGELOG.md b/src/tools/rustfmt/CHANGELOG.md index 68354b6cea..b59438dc4f 100644 --- a/src/tools/rustfmt/CHANGELOG.md +++ b/src/tools/rustfmt/CHANGELOG.md @@ -2,6 +2,73 @@ ## [Unreleased] +## [1.4.38] 2021-10-20 + +### Changed + +- Switched from `rustc-ap-*` crates to `rustc_private` for consumption model of rustc internals +- `annotate-snippets` updated to v0.8 [PR #4762](https://github.com/rust-lang/rustfmt/pull/4762) +- Greatly improved the performance of `cargo fmt` in large workspaces utilizing the `--all` flag by updating to a newer version of `cargo_metadata` that leverages updated `cargo` output from v1.51+ [PR #4997](https://github.com/rust-lang/rustfmt/pull/4997) +- Improved formatting of long slice patterns [#4530](https://github.com/rust-lang/rustfmt/issues/4530) + - **Note you must have `version = Two` in your configuration to take advantage of the new formatting** +- Stabilized `match_block_trailing_comma` configuration option [#3380](https://github.com/rust-lang/rustfmt/issues/3380) - [https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#match_block_trailing_comma](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#match_block_trailing_comma) +- Stabilized `disable_all_formatting` configuration option [#5026](https://github.com/rust-lang/rustfmt/pull/5026) - [https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#disable_all_formatting](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#disable_all_formatting) +- Various improvements to the configuration documentation website [https://rust-lang.github.io/rustfmt/?version=v1.4.38]([https://rust-lang.github.io/rustfmt/?version=v1.4.38]) +- Addressed various clippy and rustc warnings + + +### Fixed + +- Resolved issue where specious whitespace would be inserted when a block style comment was terminated within string literal processing [#4312](https://github.com/rust-lang/rustfmt/issues/4312) +- Nested out-of-line mods are again parsed and formatted [#4874](https://github.com/rust-lang/rustfmt/issues/4874) +- Accepts `2021` for edition value from rustfmt command line [PR #4847](https://github.com/rust-lang/rustfmt/pull/4847) +- Unstable command line options are no longer displayed in `--help` text on stable [PR #4798](https://github.com/rust-lang/rustfmt/issues/4798) +- Stopped panicking on patterns in match arms which start with non-ascii characters [#4868](https://github.com/rust-lang/rustfmt/issues/4868) +- Stopped stripping defaults on const params [#4816](https://github.com/rust-lang/rustfmt/issues/4816) +- Fixed issue with dropped content with GAT aliases with self bounds in impls [#4911](https://github.com/rust-lang/rustfmt/issues/4911) +- Stopped removing generic args on associated type constraints [#4943](https://github.com/rust-lang/rustfmt/issues/4943) +- Stopped dropping visibility on certain trait and impl items [#4960](https://github.com/rust-lang/rustfmt/issues/4960) +- Fixed dropping of qualified paths in struct patterns [#4908](https://github.com/rust-lang/rustfmt/issues/4908) and [#5005](https://github.com/rust-lang/rustfmt/issues/5005) +- Fixed bug in line width calculation that was causing specious formatting of certain patterns [#4031](https://github.com/rust-lang/rustfmt/issues/4031) + - **Note that this bug fix may cause observable formatting changes in cases where code had been formatted with prior versions of rustfmt that contained the bug** +- Fixed bug where rustfmt would drop parameter attributes if they were too long in certain cases [#4579](https://github.com/rust-lang/rustfmt/issues/4579) +- Resolved idempotency issue with extern body elements [#4963](https://github.com/rust-lang/rustfmt/issues/4963) +- rustfmt will now handle doc-style comments on function parameters, since they could appear with certain macro usage patterns even though it's generally invalid syntax [#4936](https://github.com/rust-lang/rustfmt/issues/4936) +- Fixed bug in `match_block_trailing_comma` where commas were not added to the blocks of bodies whose arm had a guard that did not fit on the same line as the pattern [#4998](https://github.com/rust-lang/rustfmt/pull/4998) +- Fixed bug in cases where derive attributes started with a block style comment [#4984](https://github.com/rust-lang/rustfmt/issues/4984) +- Fixed issue where the struct rest could be lost when `struct_field_align_threshold` was enabled [#4926](https://github.com/rust-lang/rustfmt/issues/4926) +- Handles cases where certain control flow type expressions have comments between patterns/keywords and the pattern ident contains the keyword [#5009](https://github.com/rust-lang/rustfmt/issues/5009) +- Handles tuple structs that have explicit visibilities and start with a block style comment [#5011](https://github.com/rust-lang/rustfmt/issues/5011) +- Handles leading line-style comments in certain types of macro calls [#4615](https://github.com/rust-lang/rustfmt/issues/4615) + + +### Added +- Granular width heuristic options made available for user control [PR #4782](https://github.com/rust-lang/rustfmt/pull/4782). This includes the following: + - [`array_width`](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#array_width) + - [`attr_fn_like_width`](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#attr_fn_like_width) + - [`chain_width`](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#chain_width) + - [`fn_call_width`](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#fn_call_width) + - [`single_line_if_else_max_width`](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#single_line_if_else_max_width) + - [`struct_lit_width`](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#struct_lit_width) + - [`struct_variant_width`](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#struct_variant_width) + +Note this hit the rustup distributions prior to the v1.4.38 release as part of an out-of-cycle updates, but is listed in this version because the feature was not in the other v1.4.37 releases. See also the `use_small_heuristics` section on the configuration site for more information +[https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#use_small_heuristics](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#use_small_heuristics) + +- New `One` variant added to `imports_granularity` configuration option which can be used to reformat all imports into a single use statement [#4669](https://github.com/rust-lang/rustfmt/issues/4669) +- rustfmt will now skip files that are annotated with `@generated` at the top of the file [#3958](https://github.com/rust-lang/rustfmt/issues/3958) +- New configuration option `hex_literal_case` that allows user to control the casing utilized for hex literals [PR #4903](https://github.com/rust-lang/rustfmt/pull/4903) + +See the section on the configuration site for more information +https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#hex_literal_case + +- `cargo fmt` now directly supports the `--check` flag, which means it's now possible to run `cargo fmt --check` instead of the more verbose `cargo fmt -- --check` [#3888](https://github.com/rust-lang/rustfmt/issues/3888) + +### Install/Download Options +- **rustup (nightly)** - *pending* +- **GitHub Release Binaries** - [Release v1.4.38](https://github.com/rust-lang/rustfmt/releases/tag/v1.4.38) +- **Build from source** - [Tag v1.4.38](https://github.com/rust-lang/rustfmt/tree/v1.4.38), see instructions for how to [install rustfmt from source][install-from-source] + ## [1.4.37] 2021-04-03 ### Changed diff --git a/src/tools/rustfmt/Cargo.lock b/src/tools/rustfmt/Cargo.lock index 03bb559800..2ef83ddd1a 100644 --- a/src/tools/rustfmt/Cargo.lock +++ b/src/tools/rustfmt/Cargo.lock @@ -35,21 +35,6 @@ version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9267dff192e68f3399525901e709a48c1d3982c9c072fa32f2127a0cb0babf14" -[[package]] -name = "arrayref" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" - -[[package]] -name = "arrayvec" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" -dependencies = [ - "nodrop", -] - [[package]] name = "atty" version = "0.2.13" @@ -62,40 +47,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" - -[[package]] -name = "backtrace" -version = "0.3.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea" -dependencies = [ - "backtrace-sys", - "cfg-if 0.1.10", - "libc", - "rustc-demangle", -] - -[[package]] -name = "backtrace-sys" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "base64" -version = "0.10.1" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" -dependencies = [ - "byteorder", -] +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "bitflags" @@ -103,17 +57,6 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" -[[package]] -name = "blake2b_simd" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5850aeee1552f495dd0250014cf64b82b7c8879a89d83b33bbdace2cc4f63182" -dependencies = [ - "arrayref", - "arrayvec", - "constant_time_eq", -] - [[package]] name = "bstr" version = "0.2.8" @@ -125,36 +68,43 @@ dependencies = [ [[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]] -name = "byteorder" -version = "1.3.2" +name = "camino" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" +checksum = "52d74260d9bf6944e2208aa46841b4b8f0d7ffc0849a06837b2f510337f86b2b" +dependencies = [ + "serde", +] [[package]] -name = "cargo_metadata" -version = "0.8.2" +name = "cargo-platform" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "700b3731fd7d357223d0000f4dbf1808401b694609035c3c411fbc0cd375c426" +checksum = "0226944a63d1bf35a3b5f948dd7c59e263db83695c9e8bffc4037de02e30f1d7" dependencies = [ - "semver", "serde", - "serde_derive", - "serde_json", ] [[package]] -name = "cc" -version = "1.0.46" +name = "cargo_metadata" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0213d356d3c4ea2c18c40b037c3be23cd639825c18f25ee670ac7813beeef99c" +checksum = "c297bd3135f558552f99a0daa180876984ea2c4ffa7470314540dff8c654109a" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", +] [[package]] name = "cfg-if" @@ -183,48 +133,14 @@ dependencies = [ "vec_map", ] -[[package]] -name = "cloudabi" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -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 = "crossbeam-channel" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acec9a3b0b3559f15aee4f90746c4e5e293b701c0f7d3925d24e01645267b68c" -dependencies = [ - "crossbeam-utils 0.7.0", -] - [[package]] name = "crossbeam-utils" -version = "0.6.6" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" -dependencies = [ - "cfg-if 0.1.10", - "lazy_static", -] - -[[package]] -name = "crossbeam-utils" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" +checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49" dependencies = [ "autocfg", - "cfg-if 0.1.10", + "cfg-if 1.0.0", "lazy_static", ] @@ -257,11 +173,10 @@ dependencies = [ [[package]] name = "dirs-sys" -version = "0.3.4" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" +checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" dependencies = [ - "cfg-if 0.1.10", "libc", "redox_users", "winapi", @@ -275,9 +190,9 @@ checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" [[package]] name = "env_logger" -version = "0.6.2" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" +checksum = "54532e3223c5af90a6a757c90b5c5521564b07e5e7a958681bcd2afad421cdcd" dependencies = [ "atty", "humantime", @@ -286,40 +201,12 @@ dependencies = [ "termcolor", ] -[[package]] -name = "failure" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9" -dependencies = [ - "backtrace", - "failure_derive", -] - -[[package]] -name = "failure_derive" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - [[package]] name = "fnv" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" - [[package]] name = "getopts" version = "0.2.21" @@ -329,11 +216,22 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi", +] + [[package]] name = "globset" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2" +checksum = "c152169ef1e421390738366d2f796655fec62621dabbd0fd476f905934061e4a" dependencies = [ "aho-corasick", "bstr", @@ -353,36 +251,33 @@ dependencies = [ [[package]] name = "humantime" -version = "1.3.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" -dependencies = [ - "quick-error", -] +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "ignore" -version = "0.4.11" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "522daefc3b69036f80c7d2990b28ff9e0471c683bad05ca258e0a01dd22c5a1e" +checksum = "b287fb45c60bb826a0dc68ff08742b9d88a2fea13d6e0c286b3172065aaf878c" dependencies = [ - "crossbeam-channel", + "crossbeam-utils", "globset", "lazy_static", "log", "memchr", "regex", "same-file", - "thread_local 1.0.1", + "thread_local", "walkdir", "winapi-util", ] [[package]] name = "itertools" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" +checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" dependencies = [ "either", ] @@ -405,6 +300,12 @@ version = "0.2.77" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235" +[[package]] +name = "libm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" + [[package]] name = "log" version = "0.4.14" @@ -421,18 +322,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" [[package]] -name = "nodrop" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" - -[[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]] @@ -463,19 +359,13 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.6" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" +checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec" dependencies = [ "unicode-xid", ] -[[package]] -name = "quick-error" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" - [[package]] name = "quote" version = "1.0.6" @@ -486,95 +376,41 @@ dependencies = [ ] [[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -dependencies = [ - "rand_core 0.4.2", -] - -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" - -[[package]] -name = "rand_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 = "rdrand" -version = "0.4.0" +name = "redox_syscall" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +checksum = "05ec8ca9416c5ea37062b502703cd7fcb207736bc294f6e0cf367ac6fc234570" dependencies = [ - "rand_core 0.3.1", + "bitflags", ] -[[package]] -name = "redox_syscall" -version = "0.1.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" - [[package]] name = "redox_users" -version = "0.3.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ecedbca3bf205f8d8f5c2b44d83cd0690e39ee84b951ed649e9f1841132b66d" +checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" dependencies = [ - "failure", - "rand_os", + "getrandom", "redox_syscall", - "rust-argon2", ] [[package]] name = "regex" -version = "1.3.1" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" +checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a" dependencies = [ "aho-corasick", "memchr", "regex-syntax", - "thread_local 0.3.6", + "thread_local", ] [[package]] name = "regex-syntax" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" - -[[package]] -name = "rust-argon2" -version = "0.5.1" +version = "0.6.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf" -dependencies = [ - "base64", - "blake2b_simd", - "crossbeam-utils 0.6.6", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" +checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581" [[package]] name = "rustc-workspace-hack" @@ -593,7 +429,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.4.37" +version = "1.4.38" dependencies = [ "annotate-snippets", "anyhow", @@ -639,34 +475,27 @@ dependencies = [ [[package]] name = "semver" -version = "0.9.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012" dependencies = [ - "semver-parser", "serde", ] -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - [[package]] name = "serde" -version = "1.0.101" +version = "1.0.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd" +checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.101" +version = "1.0.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e" +checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43" dependencies = [ "proc-macro2", "quote", @@ -675,9 +504,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.41" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2" +checksum = "dcac07dbffa1c65e7f816ab9eba78eb142c6d44410f4eeba1e26e4f5dfa56b95" dependencies = [ "itoa", "ryu", @@ -716,9 +545,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.11" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238" +checksum = "f3a1d708c221c5a612956ef9f75b37e454e88d1f7b899fbd3a18d4252012d663" dependencies = [ "proc-macro2", "quote", @@ -736,18 +565,6 @@ dependencies = [ "syn", ] -[[package]] -name = "synstructure" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f085a5855930c0441ca1288cf044ea4aecf4f43a91668abdb870b4ba546a203" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "unicode-xid", -] - [[package]] name = "term" version = "0.6.1" @@ -796,15 +613,6 @@ dependencies = [ "syn", ] -[[package]] -name = "thread_local" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" -dependencies = [ - "lazy_static", -] - [[package]] name = "thread_local" version = "1.0.1" @@ -870,6 +678,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + [[package]] name = "winapi" version = "0.3.8" diff --git a/src/tools/rustfmt/Cargo.toml b/src/tools/rustfmt/Cargo.toml index 7b4667c17c..8d9c4a7fb2 100644 --- a/src/tools/rustfmt/Cargo.toml +++ b/src/tools/rustfmt/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt-nightly" -version = "1.4.37" +version = "1.4.38" description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang/rustfmt" readme = "README.md" @@ -33,7 +33,7 @@ rustfmt-format-diff = [] generic-simd = ["bytecount/generic-simd"] [dependencies] -itertools = "0.8" +itertools = "0.9" toml = "0.5" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" @@ -42,15 +42,15 @@ regex = "1.0" term = "0.6" diff = "0.1" log = "0.4.14" -env_logger = "0.6" +env_logger = "0.8" getopts = "0.2" derive-new = "0.5" -cargo_metadata = "0.8" +cargo_metadata = "0.14" bytecount = "0.6" unicode-width = "0.1.5" unicode_categories = "0.1.1" dirs = "2.0.1" -ignore = "0.4.11" +ignore = "0.4.17" annotate-snippets = { version = "0.8", features = ["color"] } structopt = "0.3" rustfmt-config_proc_macro = { version = "0.2", path = "config_proc_macro" } diff --git a/src/tools/rustfmt/Configurations.md b/src/tools/rustfmt/Configurations.md index d2e5613eba..04c8429e5f 100644 --- a/src/tools/rustfmt/Configurations.md +++ b/src/tools/rustfmt/Configurations.md @@ -521,11 +521,13 @@ fn main() { ## `disable_all_formatting` -Don't reformat anything +Don't reformat anything. + +Note that this option may be soft-deprecated in the future once the [ignore](#ignore) option is stabilized. Nightly toolchain users are encouraged to use [ignore](#ignore) instead when possible. - **Default value**: `false` - **Possible values**: `true`, `false` -- **Stable**: No (tracking issue: #3388) +- **Stable**: Yes ## `edition` @@ -924,6 +926,15 @@ fn add_one(x: i32) -> i32 { } ``` +## `format_generated_files` + +Format generated files. A file is considered generated +if any of the first five lines contain a `@generated` comment marker. + +- **Default value**: `true` +- **Possible values**: `true`, `false` +- **Stable**: No + ## `format_macro_matchers` Format the metavariable matching patterns in macros. @@ -1047,6 +1058,13 @@ fn lorem() -> usize { See also: [`tab_spaces`](#tab_spaces). +## `hex_literal_case` + +Control the case of the letters in hexadecimal literal values + +- **Default value**: `Preserve` +- **Possible values**: `Upper`, `Lower` +- **Stable**: No ## `hide_parse_errors` @@ -1610,7 +1628,7 @@ Put a trailing comma after a block based match arm (non-block arms are not affec - **Default value**: `false` - **Possible values**: `true`, `false` -- **Stable**: No (tracking issue: #3380) +- **Stable**: Yes #### `false` (default): @@ -1668,6 +1686,9 @@ pub enum Foo {} #### `false`: ```rust +#[derive(Eq, PartialEq, Debug, Copy, Clone)] +pub enum Bar {} + #[derive(Eq, PartialEq)] #[derive(Debug)] #[derive(Copy, Clone)] @@ -1679,7 +1700,7 @@ pub enum Foo {} How imports should be grouped into `use` statements. Imports will be merged or split to the configured level of granularity. - **Default value**: `Preserve` -- **Possible values**: `Preserve`, `Crate`, `Module`, `Item` +- **Possible values**: `Preserve`, `Crate`, `Module`, `Item`, `One` - **Stable**: No #### `Preserve` (default): @@ -1733,6 +1754,23 @@ use qux::h; use qux::i; ``` +#### `One`: + +Merge all imports into a single `use` statement as long as they have the same visibility. + +```rust +pub use foo::{x, y}; +use { + bar::{ + a, + b::{self, f, g}, + c, + d::e, + }, + qux::{h, i}, +}; +``` + ## `merge_imports` This option is deprecated. Use `imports_granularity = "Crate"` instead. @@ -1824,6 +1862,9 @@ Convert `#![doc]` and `#[doc]` attributes to `//!` and `///` doc comments. #![doc = "Example documentation"] #[doc = "Example item documentation"] +pub enum Bar {} + +/// Example item documentation pub enum Foo {} ``` @@ -1938,6 +1979,8 @@ fn main() { #### `false`: ```rust fn main() { + (foo()); + ((((foo())))); } ``` @@ -1963,6 +2006,14 @@ impl Iterator for Dummy { type Item = i32; } + +impl Iterator for Dummy { + type Item = i32; + + fn next(&mut self) -> Option<Self::Item> { + None + } +} ``` #### `true` @@ -2011,7 +2062,7 @@ use sit; Controls the strategy for how imports are grouped together. - **Default value**: `Preserve` -- **Possible values**: `Preserve`, `StdExternalCrate` +- **Possible values**: `Preserve`, `StdExternalCrate`, `One` - **Stable**: No #### `Preserve` (default): @@ -2057,6 +2108,23 @@ use super::update::convert_publish_payload; use crate::models::Event; ``` +#### `One`: + +Discard existing import groups, and create a single group for everything + +```rust +use super::schema::{Context, Payload}; +use super::update::convert_publish_payload; +use crate::models::Event; +use alloc::alloc::Layout; +use broker::database::PooledConnection; +use chrono::Utc; +use core::f32; +use juniper::{FieldError, FieldResult}; +use std::sync::Arc; +use uuid::Uuid; +``` + ## `reorder_modules` Reorder `mod` declarations alphabetically in group. @@ -2519,7 +2587,8 @@ fn main() { let x = 1; let y = 2; let z = 3; - let a = Foo { x: x, y: y, z: z }; + let a = Foo { x, y, z }; + let b = Foo { x: x, y: y, z: z }; } ``` @@ -2688,6 +2757,8 @@ Replace uses of the try! macro by the ? shorthand ```rust fn main() { + let lorem = ipsum.map(|dolor| dolor.sit())?; + let lorem = try!(ipsum.map(|dolor| dolor.sit())); } ``` @@ -2759,6 +2830,12 @@ Break comments to fit on the line #### `false` (default): ```rust +// Lorem ipsum dolor sit amet, consectetur adipiscing elit, +// sed do eiusmod tempor incididunt ut labore et dolore +// magna aliqua. Ut enim ad minim veniam, quis nostrud +// exercitation ullamco laboris nisi ut aliquip ex ea +// commodo consequat. + // Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. ``` diff --git a/src/tools/rustfmt/Contributing.md b/src/tools/rustfmt/Contributing.md index e6dc6a2203..3073996019 100644 --- a/src/tools/rustfmt/Contributing.md +++ b/src/tools/rustfmt/Contributing.md @@ -59,7 +59,7 @@ example, the `issue-1111.rs` test file is configured by the file ## Debugging Some `rewrite_*` methods use the `debug!` macro for printing useful information. -These messages can be printed by using the environment variable `RUST_LOG=rustfmt=DEBUG`. +These messages can be printed by using the environment variable `RUSTFMT_LOG=rustfmt=DEBUG`. These traces can be helpful in understanding which part of the code was used and get a better grasp on the execution flow. diff --git a/src/tools/rustfmt/README.md b/src/tools/rustfmt/README.md index 9c7a1c4bc3..b3d21e6fb8 100644 --- a/src/tools/rustfmt/README.md +++ b/src/tools/rustfmt/README.md @@ -47,7 +47,7 @@ cargo +nightly fmt ## Limitations -Rustfmt tries to work on as much Rust code as possible, sometimes, the code +Rustfmt tries to work on as much Rust code as possible. Sometimes, the code doesn't even need to compile! As we approach a 1.0 release we are also looking to limit areas of instability; in particular, post-1.0, the formatting of most code should not change as Rustfmt improves. However, there are some things that @@ -102,6 +102,25 @@ read data from stdin. Alternatively, you can use `cargo fmt` to format all binary and library targets of your crate. You can run `rustfmt --help` for information about available arguments. +The easiest way to run rustfmt against a project is with `cargo fmt`. `cargo fmt` works on both +single-crate projects and [cargo workspaces](https://doc.rust-lang.org/book/ch14-03-cargo-workspaces.html). +Please see `cargo fmt --help` for usage information. + +You can specify the path to your own `rustfmt` binary for cargo to use by setting the`RUSTFMT` +environment variable. This was added in v1.4.22, so you must have this version or newer to leverage this feature (`cargo fmt --version`) + +### Running `rustfmt` directly + +To format individual files or arbitrary codes from stdin, the `rustfmt` binary should be used. Some +examples follow: + +- `rustfmt lib.rs main.rs` will format "lib.rs" and "main.rs" in place +- `rustfmt` will read a code from stdin and write formatting to stdout + - `echo "fn main() {}" | rustfmt` would emit "fn main() {}". + +For more information, including arguments and emit options, see `rustfmt --help`. + +### Verifying code is formatted When running with `--check`, Rustfmt will exit with `0` if Rustfmt would not make any formatting changes to the input, and `1` if Rustfmt would make changes. @@ -129,7 +148,7 @@ rustfmt to exit with an error code if the input is not formatted correctly. It will also print any found differences. (Older versions of Rustfmt don't support `--check`, use `--write-mode diff`). -A minimal Travis setup could look like this (requires Rust 1.24.0 or greater): +A minimal Travis setup could look like this (requires Rust 1.31.0 or greater): ```yaml language: rust diff --git a/src/tools/rustfmt/appveyor.yml b/src/tools/rustfmt/appveyor.yml deleted file mode 100644 index 5ac99fd71f..0000000000 --- a/src/tools/rustfmt/appveyor.yml +++ /dev/null @@ -1,55 +0,0 @@ -# This is based on https://github.com/japaric/rust-everywhere/blob/master/appveyor.yml -# and modified (mainly removal of deployment) to suit rustfmt. - -environment: - global: - PROJECT_NAME: rustfmt - matrix: - # Stable channel - # - TARGET: i686-pc-windows-gnu - # CHANNEL: stable - # - TARGET: i686-pc-windows-msvc - # CHANNEL: stable - # - TARGET: x86_64-pc-windows-gnu - # CHANNEL: stable - # - TARGET: x86_64-pc-windows-msvc - # CHANNEL: stable - # Beta channel - # - TARGET: i686-pc-windows-gnu - # CHANNEL: beta - # - TARGET: i686-pc-windows-msvc - # CHANNEL: beta - # - TARGET: x86_64-pc-windows-gnu - # CHANNEL: beta - # - TARGET: x86_64-pc-windows-msvc - # CHANNEL: beta - # Nightly channel - - TARGET: i686-pc-windows-gnu - CHANNEL: nightly - - TARGET: i686-pc-windows-msvc - CHANNEL: nightly - - TARGET: x86_64-pc-windows-gnu - CHANNEL: nightly - - TARGET: x86_64-pc-windows-msvc - CHANNEL: nightly - -# Install Rust and Cargo -# (Based on from https://github.com/rust-lang/libc/blob/master/appveyor.yml) -install: - - appveyor-retry appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe - - if "%TARGET%" == "i686-pc-windows-gnu" set PATH=%PATH%;C:\msys64\mingw32\bin - - if "%TARGET%" == "x86_64-pc-windows-gnu" set PATH=%PATH%;C:\msys64\mingw64\bin - - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin - - rustup-init.exe --default-host %TARGET% --default-toolchain %CHANNEL% -y - - rustc -Vv - - cargo -V - -# ??? -build: false - -test_script: - - set CFG_RELEASE_CHANNEL=nightly - - set CFG_RELEASE=nightly - - cargo build --verbose - - cargo test - - cargo test -- --ignored diff --git a/src/tools/rustfmt/intellij.md b/src/tools/rustfmt/intellij.md index 7aea6222b8..6a711c0171 100644 --- a/src/tools/rustfmt/intellij.md +++ b/src/tools/rustfmt/intellij.md @@ -3,19 +3,28 @@ ## Installation - Install [CLion](https://www.jetbrains.com/clion/), [IntelliJ Ultimate or CE](https://www.jetbrains.com/idea/) through the direct download link or using the [JetBrains Toolbox](https://www.jetbrains.com/toolbox/). - CLion provides a built-in debugger interface but its not free like IntelliJ CE - which does not provide the debugger interface. (IntelliJ seems to lack the toolchain for that, see this discussion [intellij-rust/issues/535](https://github.com/intellij-rust/intellij-rust/issues/535)) - -- Install the [Rust Plugin](https://intellij-rust.github.io/) by navigating to File -> Settings -> Plugins and press "Install JetBrains Plugin" - ![plugins](https://user-images.githubusercontent.com/1133787/47240861-f40af680-d3e9-11e8-9b82-cdd5c8d5f5b8.png) + CLion and IntelliJ Ultimate [provide a built-in debugger interface](https://github.com/intellij-rust/intellij-rust#compatible-ides) but they are not free like IntelliJ CE. + +- Install the [Rust Plugin](https://intellij-rust.github.io/) by navigating to File → Settings → Plugins and searching the plugin in the Marketplace + ![plugins](https://user-images.githubusercontent.com/6505554/83944518-6f1e5c00-a81d-11ea-9c35-e16948811ba8.png) -- Press "Install" on the rust plugin - ![install rust](https://user-images.githubusercontent.com/1133787/47240803-c0c86780-d3e9-11e8-9265-22f735e4d7ed.png) +- Press "Install" on the Rust plugin + ![install rust](https://user-images.githubusercontent.com/6505554/83944533-82c9c280-a81d-11ea-86b3-ee2e31bc7d12.png) - Restart CLion/IntelliJ ## Configuration -- Open the settings window (File -> Settings) and search for "reformat" +### Run Rustfmt on save + +- Open Rustfmt settings (File → Settings → Languages & Frameworks → Rust → Rustfmt) and enable "Run rustfmt on Save" + ![run_rustfmt_on_save](https://user-images.githubusercontent.com/6505554/83944610-3468f380-a81e-11ea-9c34-0cbd18dd4969.png) + +- IntellJ uses autosave, so now your files will always be formatted according to rustfmt. Alternatively you can use Ctrl+S to reformat file manually + +### Bind shortcut to "Reformat File with Rustfmt" action + +- Open the settings window (File → Settings) and search for "reformat" ![keymap](https://user-images.githubusercontent.com/1133787/47240922-2ae10c80-d3ea-11e8-9d8f-c798d9749240.png) - Right-click on "Reformat File with Rustfmt" and assign a keyboard shortcut diff --git a/src/tools/rustfmt/legacy-rustfmt.toml b/src/tools/rustfmt/legacy-rustfmt.toml deleted file mode 100644 index f976fa68e4..0000000000 --- a/src/tools/rustfmt/legacy-rustfmt.toml +++ /dev/null @@ -1,2 +0,0 @@ -indent_style = "Visual" -combine_control_expr = false diff --git a/src/tools/rustfmt/rust-toolchain b/src/tools/rustfmt/rust-toolchain index b0cd4464df..1d2cad6675 100644 --- a/src/tools/rustfmt/rust-toolchain +++ b/src/tools/rustfmt/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2021-07-23" +channel = "nightly-2021-11-08" components = ["rustc-dev"] diff --git a/src/tools/rustfmt/src/attr.rs b/src/tools/rustfmt/src/attr.rs index 315eb10a9d..76b66e9da8 100644 --- a/src/tools/rustfmt/src/attr.rs +++ b/src/tools/rustfmt/src/attr.rs @@ -13,6 +13,7 @@ use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, use crate::overflow; use crate::rewrite::{Rewrite, RewriteContext}; use crate::shape::Shape; +use crate::source_map::SpanUtils; use crate::types::{rewrite_path, PathContext}; use crate::utils::{count_newlines, mk_sp}; @@ -116,7 +117,9 @@ fn format_derive( |span| span.lo(), |span| span.hi(), |span| Some(context.snippet(*span).to_owned()), - attr.span.lo(), + // We update derive attribute spans to start after the opening '(' + // This helps us focus parsing to just what's inside #[derive(...)] + context.snippet_provider.span_after(attr.span, "("), attr.span.hi(), false, ); @@ -448,7 +451,7 @@ impl Rewrite for [ast::Attribute] { if next.is_doc_comment() { let snippet = context.snippet(missing_span); let (_, mlb) = has_newlines_before_after_comment(snippet); - result.push_str(&mlb); + result.push_str(mlb); } } result.push('\n'); @@ -481,7 +484,7 @@ impl Rewrite for [ast::Attribute] { if next.is_doc_comment() { let snippet = context.snippet(missing_span); let (_, mlb) = has_newlines_before_after_comment(snippet); - result.push_str(&mlb); + result.push_str(mlb); } } result.push('\n'); diff --git a/src/tools/rustfmt/src/attr/doc_comment.rs b/src/tools/rustfmt/src/attr/doc_comment.rs index c3dcb84c94..f653a12a8a 100644 --- a/src/tools/rustfmt/src/attr/doc_comment.rs +++ b/src/tools/rustfmt/src/attr/doc_comment.rs @@ -77,7 +77,7 @@ mod tests { ) { assert_eq!( expected_comment, - format!("{}", DocCommentFormatter::new(&literal, style)) + format!("{}", DocCommentFormatter::new(literal, style)) ); } } diff --git a/src/tools/rustfmt/src/bin/main.rs b/src/tools/rustfmt/src/bin/main.rs index 4b4aa42d93..9d2e97c947 100644 --- a/src/tools/rustfmt/src/bin/main.rs +++ b/src/tools/rustfmt/src/bin/main.rs @@ -20,7 +20,7 @@ use crate::rustfmt::{ }; fn main() { - env_logger::init(); + env_logger::Builder::from_env("RUSTFMT_LOG").init(); let opts = make_opts(); let exit_code = match execute(&opts) { @@ -121,7 +121,7 @@ fn make_opts() -> Options { found reverts to the input file path", "[Path for the configuration file]", ); - opts.optopt("", "edition", "Rust edition to use", "[2015|2018]"); + opts.optopt("", "edition", "Rust edition to use", "[2015|2018|2021]"); opts.optopt( "", "color", diff --git a/src/tools/rustfmt/src/cargo-fmt/main.rs b/src/tools/rustfmt/src/cargo-fmt/main.rs index 90ffad927e..759b21218c 100644 --- a/src/tools/rustfmt/src/cargo-fmt/main.rs +++ b/src/tools/rustfmt/src/cargo-fmt/main.rs @@ -17,6 +17,10 @@ use std::str; use structopt::StructOpt; +#[path = "test/mod.rs"] +#[cfg(test)] +mod cargo_fmt_tests; + #[derive(StructOpt, Debug)] #[structopt( bin_name = "cargo fmt", @@ -36,7 +40,7 @@ pub struct Opts { #[structopt(long = "version")] version: bool, - /// Specify package to format (only usable in workspaces) + /// Specify package to format #[structopt(short = "p", long = "package", value_name = "package")] packages: Vec<String>, @@ -53,9 +57,13 @@ pub struct Opts { #[structopt(name = "rustfmt_options", raw(true))] rustfmt_options: Vec<String>, - /// Format all packages (only usable in workspaces) + /// Format all packages, and also their local path-based dependencies #[structopt(long = "all")] format_all: bool, + + /// Run rustfmt in check mode + #[structopt(long = "check")] + check: bool, } fn main() { @@ -104,6 +112,12 @@ fn execute() -> i32 { let strategy = CargoFmtStrategy::from_opts(&opts); let mut rustfmt_args = opts.rustfmt_options; + if opts.check { + let check_flag = "--check"; + if !rustfmt_args.iter().any(|o| o == check_flag) { + rustfmt_args.push(check_flag.to_owned()); + } + } if let Some(message_format) = opts.message_format { if let Err(msg) = convert_message_format_to_rustfmt_args(&message_format, &mut rustfmt_args) { @@ -346,7 +360,7 @@ fn get_targets_root_only( manifest_path: Option<&Path>, targets: &mut BTreeSet<Target>, ) -> Result<(), io::Error> { - let metadata = get_cargo_metadata(manifest_path, false)?; + let metadata = get_cargo_metadata(manifest_path)?; let workspace_root_path = PathBuf::from(&metadata.workspace_root).canonicalize()?; let (in_workspace_root, current_dir_manifest) = if let Some(target_manifest) = manifest_path { ( @@ -387,38 +401,33 @@ fn get_targets_root_only( fn get_targets_recursive( manifest_path: Option<&Path>, - mut targets: &mut BTreeSet<Target>, + targets: &mut BTreeSet<Target>, visited: &mut BTreeSet<String>, ) -> Result<(), io::Error> { - let metadata = get_cargo_metadata(manifest_path, false)?; - let metadata_with_deps = get_cargo_metadata(manifest_path, true)?; - - for package in metadata.packages { - add_targets(&package.targets, &mut targets); - - // Look for local dependencies. - for dependency in package.dependencies { - if dependency.source.is_some() || visited.contains(&dependency.name) { + let metadata = get_cargo_metadata(manifest_path)?; + for package in &metadata.packages { + add_targets(&package.targets, targets); + + // Look for local dependencies using information available since cargo v1.51 + // It's theoretically possible someone could use a newer version of rustfmt with + // a much older version of `cargo`, but we don't try to explicitly support that scenario. + // If someone reports an issue with path-based deps not being formatted, be sure to + // confirm their version of `cargo` (not `cargo-fmt`) is >= v1.51 + // https://github.com/rust-lang/cargo/pull/8994 + for dependency in &package.dependencies { + if dependency.path.is_none() || visited.contains(&dependency.name) { continue; } - let dependency_package = metadata_with_deps - .packages - .iter() - .find(|p| p.name == dependency.name && p.source.is_none()); - let manifest_path = if let Some(dep_pkg) = dependency_package { - PathBuf::from(&dep_pkg.manifest_path) - } else { - let mut package_manifest_path = PathBuf::from(&package.manifest_path); - package_manifest_path.pop(); - package_manifest_path.push(&dependency.name); - package_manifest_path.push("Cargo.toml"); - package_manifest_path - }; - - if manifest_path.exists() { - visited.insert(dependency.name); - get_targets_recursive(Some(&manifest_path), &mut targets, visited)?; + let manifest_path = PathBuf::from(dependency.path.as_ref().unwrap()).join("Cargo.toml"); + if manifest_path.exists() + && !metadata + .packages + .iter() + .any(|p| p.manifest_path.eq(&manifest_path)) + { + visited.insert(dependency.name.to_owned()); + get_targets_recursive(Some(&manifest_path), targets, visited)?; } } } @@ -431,8 +440,7 @@ fn get_targets_with_hitlist( hitlist: &[String], targets: &mut BTreeSet<Target>, ) -> Result<(), io::Error> { - let metadata = get_cargo_metadata(manifest_path, false)?; - + let metadata = get_cargo_metadata(manifest_path)?; let mut workspace_hitlist: BTreeSet<&String> = BTreeSet::from_iter(hitlist); for package in metadata.packages { @@ -517,18 +525,13 @@ fn run_rustfmt( .unwrap_or(SUCCESS)) } -fn get_cargo_metadata( - manifest_path: Option<&Path>, - include_deps: bool, -) -> Result<cargo_metadata::Metadata, io::Error> { +fn get_cargo_metadata(manifest_path: Option<&Path>) -> Result<cargo_metadata::Metadata, io::Error> { let mut cmd = cargo_metadata::MetadataCommand::new(); - if !include_deps { - cmd.no_deps(); - } + cmd.no_deps(); if let Some(manifest_path) = manifest_path { cmd.manifest_path(manifest_path); } - cmd.other_options(&[String::from("--offline")]); + cmd.other_options(vec![String::from("--offline")]); match cmd.exec() { Ok(metadata) => Ok(metadata), @@ -541,221 +544,3 @@ fn get_cargo_metadata( } } } - -#[cfg(test)] -mod cargo_fmt_tests { - use super::*; - - #[test] - fn default_options() { - let empty: Vec<String> = vec![]; - let o = Opts::from_iter(&empty); - assert_eq!(false, o.quiet); - assert_eq!(false, o.verbose); - assert_eq!(false, o.version); - assert_eq!(empty, o.packages); - assert_eq!(empty, o.rustfmt_options); - assert_eq!(false, o.format_all); - assert_eq!(None, o.manifest_path); - assert_eq!(None, o.message_format); - } - - #[test] - fn good_options() { - let o = Opts::from_iter(&[ - "test", - "-q", - "-p", - "p1", - "-p", - "p2", - "--message-format", - "short", - "--", - "--edition", - "2018", - ]); - assert_eq!(true, o.quiet); - assert_eq!(false, o.verbose); - assert_eq!(false, o.version); - assert_eq!(vec!["p1", "p2"], o.packages); - assert_eq!(vec!["--edition", "2018"], o.rustfmt_options); - assert_eq!(false, o.format_all); - assert_eq!(Some(String::from("short")), o.message_format); - } - - #[test] - fn unexpected_option() { - assert!( - Opts::clap() - .get_matches_from_safe(&["test", "unexpected"]) - .is_err() - ); - } - - #[test] - fn unexpected_flag() { - assert!( - Opts::clap() - .get_matches_from_safe(&["test", "--flag"]) - .is_err() - ); - } - - #[test] - fn mandatory_separator() { - assert!( - Opts::clap() - .get_matches_from_safe(&["test", "--check"]) - .is_err() - ); - assert!( - !Opts::clap() - .get_matches_from_safe(&["test", "--", "--check"]) - .is_err() - ); - } - - #[test] - fn multiple_packages_one_by_one() { - let o = Opts::from_iter(&[ - "test", - "-p", - "package1", - "--package", - "package2", - "-p", - "package3", - ]); - assert_eq!(3, o.packages.len()); - } - - #[test] - fn multiple_packages_grouped() { - let o = Opts::from_iter(&[ - "test", - "--package", - "package1", - "package2", - "-p", - "package3", - "package4", - ]); - assert_eq!(4, o.packages.len()); - } - - #[test] - fn empty_packages_1() { - assert!(Opts::clap().get_matches_from_safe(&["test", "-p"]).is_err()); - } - - #[test] - fn empty_packages_2() { - assert!( - Opts::clap() - .get_matches_from_safe(&["test", "-p", "--", "--check"]) - .is_err() - ); - } - - #[test] - fn empty_packages_3() { - assert!( - Opts::clap() - .get_matches_from_safe(&["test", "-p", "--verbose"]) - .is_err() - ); - } - - #[test] - fn empty_packages_4() { - assert!( - Opts::clap() - .get_matches_from_safe(&["test", "-p", "--check"]) - .is_err() - ); - } - - mod convert_message_format_to_rustfmt_args_tests { - use super::*; - - #[test] - fn invalid_message_format() { - assert_eq!( - convert_message_format_to_rustfmt_args("awesome", &mut vec![]), - Err(String::from( - "invalid --message-format value: awesome. Allowed values are: short|json|human" - )), - ); - } - - #[test] - fn json_message_format_and_check_arg() { - let mut args = vec![String::from("--check")]; - assert_eq!( - convert_message_format_to_rustfmt_args("json", &mut args), - Err(String::from( - "cannot include --check arg when --message-format is set to json" - )), - ); - } - - #[test] - fn json_message_format_and_emit_arg() { - let mut args = vec![String::from("--emit"), String::from("checkstyle")]; - assert_eq!( - convert_message_format_to_rustfmt_args("json", &mut args), - Err(String::from( - "cannot include --emit arg when --message-format is set to json" - )), - ); - } - - #[test] - fn json_message_format() { - let mut args = vec![String::from("--edition"), String::from("2018")]; - assert!(convert_message_format_to_rustfmt_args("json", &mut args).is_ok()); - assert_eq!( - args, - vec![ - String::from("--edition"), - String::from("2018"), - String::from("--emit"), - String::from("json") - ] - ); - } - - #[test] - fn human_message_format() { - let exp_args = vec![String::from("--emit"), String::from("json")]; - let mut act_args = exp_args.clone(); - assert!(convert_message_format_to_rustfmt_args("human", &mut act_args).is_ok()); - assert_eq!(act_args, exp_args); - } - - #[test] - fn short_message_format() { - let mut args = vec![String::from("--check")]; - assert!(convert_message_format_to_rustfmt_args("short", &mut args).is_ok()); - assert_eq!(args, vec![String::from("--check"), String::from("-l")]); - } - - #[test] - fn short_message_format_included_short_list_files_flag() { - let mut args = vec![String::from("--check"), String::from("-l")]; - assert!(convert_message_format_to_rustfmt_args("short", &mut args).is_ok()); - assert_eq!(args, vec![String::from("--check"), String::from("-l")]); - } - - #[test] - fn short_message_format_included_long_list_files_flag() { - let mut args = vec![String::from("--check"), String::from("--files-with-diff")]; - assert!(convert_message_format_to_rustfmt_args("short", &mut args).is_ok()); - assert_eq!( - args, - vec![String::from("--check"), String::from("--files-with-diff")] - ); - } - } -} diff --git a/src/tools/rustfmt/src/cargo-fmt/test/message_format.rs b/src/tools/rustfmt/src/cargo-fmt/test/message_format.rs new file mode 100644 index 0000000000..bf44924f13 --- /dev/null +++ b/src/tools/rustfmt/src/cargo-fmt/test/message_format.rs @@ -0,0 +1,80 @@ +use super::*; + +#[test] +fn invalid_message_format() { + assert_eq!( + convert_message_format_to_rustfmt_args("awesome", &mut vec![]), + Err(String::from( + "invalid --message-format value: awesome. Allowed values are: short|json|human" + )), + ); +} + +#[test] +fn json_message_format_and_check_arg() { + let mut args = vec![String::from("--check")]; + assert_eq!( + convert_message_format_to_rustfmt_args("json", &mut args), + Err(String::from( + "cannot include --check arg when --message-format is set to json" + )), + ); +} + +#[test] +fn json_message_format_and_emit_arg() { + let mut args = vec![String::from("--emit"), String::from("checkstyle")]; + assert_eq!( + convert_message_format_to_rustfmt_args("json", &mut args), + Err(String::from( + "cannot include --emit arg when --message-format is set to json" + )), + ); +} + +#[test] +fn json_message_format() { + let mut args = vec![String::from("--edition"), String::from("2018")]; + assert!(convert_message_format_to_rustfmt_args("json", &mut args).is_ok()); + assert_eq!( + args, + vec![ + String::from("--edition"), + String::from("2018"), + String::from("--emit"), + String::from("json") + ] + ); +} + +#[test] +fn human_message_format() { + let exp_args = vec![String::from("--emit"), String::from("json")]; + let mut act_args = exp_args.clone(); + assert!(convert_message_format_to_rustfmt_args("human", &mut act_args).is_ok()); + assert_eq!(act_args, exp_args); +} + +#[test] +fn short_message_format() { + let mut args = vec![String::from("--check")]; + assert!(convert_message_format_to_rustfmt_args("short", &mut args).is_ok()); + assert_eq!(args, vec![String::from("--check"), String::from("-l")]); +} + +#[test] +fn short_message_format_included_short_list_files_flag() { + let mut args = vec![String::from("--check"), String::from("-l")]; + assert!(convert_message_format_to_rustfmt_args("short", &mut args).is_ok()); + assert_eq!(args, vec![String::from("--check"), String::from("-l")]); +} + +#[test] +fn short_message_format_included_long_list_files_flag() { + let mut args = vec![String::from("--check"), String::from("--files-with-diff")]; + assert!(convert_message_format_to_rustfmt_args("short", &mut args).is_ok()); + assert_eq!( + args, + vec![String::from("--check"), String::from("--files-with-diff")] + ); +} diff --git a/src/tools/rustfmt/src/cargo-fmt/test/mod.rs b/src/tools/rustfmt/src/cargo-fmt/test/mod.rs new file mode 100644 index 0000000000..360503632c --- /dev/null +++ b/src/tools/rustfmt/src/cargo-fmt/test/mod.rs @@ -0,0 +1,137 @@ +use super::*; + +mod message_format; +mod targets; + +#[test] +fn default_options() { + let empty: Vec<String> = vec![]; + let o = Opts::from_iter(&empty); + assert_eq!(false, o.quiet); + assert_eq!(false, o.verbose); + assert_eq!(false, o.version); + assert_eq!(false, o.check); + assert_eq!(empty, o.packages); + assert_eq!(empty, o.rustfmt_options); + assert_eq!(false, o.format_all); + assert_eq!(None, o.manifest_path); + assert_eq!(None, o.message_format); +} + +#[test] +fn good_options() { + let o = Opts::from_iter(&[ + "test", + "-q", + "-p", + "p1", + "-p", + "p2", + "--message-format", + "short", + "--check", + "--", + "--edition", + "2018", + ]); + assert_eq!(true, o.quiet); + assert_eq!(false, o.verbose); + assert_eq!(false, o.version); + assert_eq!(true, o.check); + assert_eq!(vec!["p1", "p2"], o.packages); + assert_eq!(vec!["--edition", "2018"], o.rustfmt_options); + assert_eq!(false, o.format_all); + assert_eq!(Some(String::from("short")), o.message_format); +} + +#[test] +fn unexpected_option() { + assert!( + Opts::clap() + .get_matches_from_safe(&["test", "unexpected"]) + .is_err() + ); +} + +#[test] +fn unexpected_flag() { + assert!( + Opts::clap() + .get_matches_from_safe(&["test", "--flag"]) + .is_err() + ); +} + +#[test] +fn mandatory_separator() { + assert!( + Opts::clap() + .get_matches_from_safe(&["test", "--emit"]) + .is_err() + ); + assert!( + !Opts::clap() + .get_matches_from_safe(&["test", "--", "--emit"]) + .is_err() + ); +} + +#[test] +fn multiple_packages_one_by_one() { + let o = Opts::from_iter(&[ + "test", + "-p", + "package1", + "--package", + "package2", + "-p", + "package3", + ]); + assert_eq!(3, o.packages.len()); +} + +#[test] +fn multiple_packages_grouped() { + let o = Opts::from_iter(&[ + "test", + "--package", + "package1", + "package2", + "-p", + "package3", + "package4", + ]); + assert_eq!(4, o.packages.len()); +} + +#[test] +fn empty_packages_1() { + assert!(Opts::clap().get_matches_from_safe(&["test", "-p"]).is_err()); +} + +#[test] +fn empty_packages_2() { + assert!( + Opts::clap() + .get_matches_from_safe(&["test", "-p", "--", "--check"]) + .is_err() + ); +} + +#[test] +fn empty_packages_3() { + assert!( + Opts::clap() + .get_matches_from_safe(&["test", "-p", "--verbose"]) + .is_err() + ); +} + +#[test] +fn empty_packages_4() { + assert!( + Opts::clap() + .get_matches_from_safe(&["test", "-p", "--check"]) + .is_err() + ); +} diff --git a/src/tools/rustfmt/src/cargo-fmt/test/targets.rs b/src/tools/rustfmt/src/cargo-fmt/test/targets.rs new file mode 100644 index 0000000000..b7e7fabdf7 --- /dev/null +++ b/src/tools/rustfmt/src/cargo-fmt/test/targets.rs @@ -0,0 +1,134 @@ +use super::*; + +struct ExpTarget { + path: &'static str, + edition: &'static str, + kind: &'static str, +} + +mod all_targets { + use super::*; + + fn assert_correct_targets_loaded( + manifest_suffix: &str, + source_root: &str, + exp_targets: &[ExpTarget], + exp_num_targets: usize, + ) { + let root_path = Path::new("tests/cargo-fmt/source").join(source_root); + let get_path = |exp: &str| PathBuf::from(&root_path).join(exp).canonicalize().unwrap(); + let manifest_path = Path::new(&root_path).join(manifest_suffix); + let targets = get_targets(&CargoFmtStrategy::All, Some(manifest_path.as_path())) + .expect("Targets should have been loaded"); + + assert_eq!(targets.len(), exp_num_targets); + + for target in exp_targets { + assert!(targets.contains(&Target { + path: get_path(target.path), + edition: target.edition.to_owned(), + kind: target.kind.to_owned(), + })); + } + } + + mod different_crate_and_dir_names { + use super::*; + + fn assert_correct_targets_loaded(manifest_suffix: &str) { + let exp_targets = vec![ + ExpTarget { + path: "dependency-dir-name/subdep-dir-name/src/lib.rs", + edition: "2018", + kind: "lib", + }, + ExpTarget { + path: "dependency-dir-name/src/lib.rs", + edition: "2018", + kind: "lib", + }, + ExpTarget { + path: "src/main.rs", + edition: "2018", + kind: "main", + }, + ]; + super::assert_correct_targets_loaded( + manifest_suffix, + "divergent-crate-dir-names", + &exp_targets, + 3, + ); + } + + #[test] + fn correct_targets_from_root() { + assert_correct_targets_loaded("Cargo.toml"); + } + + #[test] + fn correct_targets_from_sub_local_dep() { + assert_correct_targets_loaded("dependency-dir-name/Cargo.toml"); + } + } + + mod workspaces { + use super::*; + + fn assert_correct_targets_loaded(manifest_suffix: &str) { + let exp_targets = vec![ + ExpTarget { + path: "ws/a/src/main.rs", + edition: "2018", + kind: "bin", + }, + ExpTarget { + path: "ws/b/src/main.rs", + edition: "2018", + kind: "bin", + }, + ExpTarget { + path: "ws/c/src/lib.rs", + edition: "2018", + kind: "lib", + }, + ExpTarget { + path: "ws/a/d/src/lib.rs", + edition: "2018", + kind: "lib", + }, + ExpTarget { + path: "e/src/main.rs", + edition: "2018", + kind: "main", + }, + ExpTarget { + path: "ws/a/d/f/src/lib.rs", + edition: "2018", + kind: "lib", + }, + ]; + super::assert_correct_targets_loaded( + manifest_suffix, + "workspaces/path-dep-above", + &exp_targets, + 6, + ); + } + + #[test] + fn includes_outside_workspace_deps() { + assert_correct_targets_loaded("ws/Cargo.toml"); + } + + #[test] + fn includes_workspace_from_dep_above() { + assert_correct_targets_loaded("e/Cargo.toml"); + } + + #[test] + fn includes_all_packages_from_workspace_subdir() { + assert_correct_targets_loaded("ws/a/d/f/Cargo.toml"); + } + } +} diff --git a/src/tools/rustfmt/src/chains.rs b/src/tools/rustfmt/src/chains.rs index 614638ea2a..e26e24ec55 100644 --- a/src/tools/rustfmt/src/chains.rs +++ b/src/tools/rustfmt/src/chains.rs @@ -568,7 +568,7 @@ impl<'a> ChainFormatterShared<'a> { } else { self.rewrites .iter() - .map(|rw| utils::unicode_str_width(&rw)) + .map(|rw| utils::unicode_str_width(rw)) .sum() } + last.tries; let one_line_budget = if self.child_count == 1 { @@ -673,7 +673,7 @@ impl<'a> ChainFormatterShared<'a> { ChainItemKind::Comment(_, CommentPosition::Top) => result.push_str(&connector), _ => result.push_str(&connector), } - result.push_str(&rewrite); + result.push_str(rewrite); } Some(result) diff --git a/src/tools/rustfmt/src/comment.rs b/src/tools/rustfmt/src/comment.rs index 58a2b5e6ae..7b76c23293 100644 --- a/src/tools/rustfmt/src/comment.rs +++ b/src/tools/rustfmt/src/comment.rs @@ -10,7 +10,8 @@ use crate::rewrite::RewriteContext; use crate::shape::{Indent, Shape}; use crate::string::{rewrite_string, StringFormat}; use crate::utils::{ - count_newlines, first_line_width, last_line_width, trim_left_preserve_layout, unicode_str_width, + count_newlines, first_line_width, last_line_width, trim_left_preserve_layout, + trimmed_last_line_width, unicode_str_width, }; use crate::{ErrorKind, FormattingError}; @@ -171,11 +172,12 @@ pub(crate) fn combine_strs_with_missing_comments( String::with_capacity(prev_str.len() + next_str.len() + shape.indent.width() + 128); result.push_str(prev_str); let mut allow_one_line = !prev_str.contains('\n') && !next_str.contains('\n'); - let first_sep = if prev_str.is_empty() || next_str.is_empty() { - "" - } else { - " " - }; + let first_sep = + if prev_str.is_empty() || next_str.is_empty() || trimmed_last_line_width(prev_str) == 0 { + "" + } else { + " " + }; let mut one_line_width = last_line_width(prev_str) + first_line_width(next_str) + first_sep.len(); @@ -184,7 +186,7 @@ pub(crate) fn combine_strs_with_missing_comments( let missing_comment = rewrite_missing_comment(span, shape, context)?; if missing_comment.is_empty() { - if allow_extend && prev_str.len() + first_sep.len() + next_str.len() <= shape.width { + if allow_extend && one_line_width <= shape.width { result.push_str(first_sep); } else if !prev_str.is_empty() { result.push_str(&indent.to_string_with_newline(config)) @@ -392,28 +394,26 @@ fn identify_comment( } } -/// Attributes for code blocks in rustdoc. -/// See <https://doc.rust-lang.org/rustdoc/print.html#attributes>. +/// Enum indicating if the code block contains rust based on attributes enum CodeBlockAttribute { Rust, - Ignore, - Text, - ShouldPanic, - NoRun, - CompileFail, + NotRust, } impl CodeBlockAttribute { - fn new(attribute: &str) -> CodeBlockAttribute { - match attribute { - "rust" | "" => CodeBlockAttribute::Rust, - "ignore" => CodeBlockAttribute::Ignore, - "text" => CodeBlockAttribute::Text, - "should_panic" => CodeBlockAttribute::ShouldPanic, - "no_run" => CodeBlockAttribute::NoRun, - "compile_fail" => CodeBlockAttribute::CompileFail, - _ => CodeBlockAttribute::Text, + /// Parse comma separated attributes list. Return rust only if all + /// attributes are valid rust attributes + /// See <https://doc.rust-lang.org/rustdoc/print.html#attributes> + fn new(attributes: &str) -> CodeBlockAttribute { + for attribute in attributes.split(',') { + match attribute.trim() { + "" | "rust" | "should_panic" | "no_run" | "edition2015" | "edition2018" + | "edition2021" => (), + "ignore" | "compile_fail" | "text" => return CodeBlockAttribute::NotRust, + _ => return CodeBlockAttribute::NotRust, + } } + CodeBlockAttribute::Rust } } @@ -563,7 +563,7 @@ impl<'a> CommentRewrite<'a> { result.push_str(line); result.push_str(match iter.peek() { Some(next_line) if next_line.is_empty() => sep.trim_end(), - Some(..) => &sep, + Some(..) => sep, None => "", }); } @@ -622,7 +622,7 @@ impl<'a> CommentRewrite<'a> { let is_last = i == count_newlines(orig); if let Some(ref mut ib) = self.item_block { - if ib.add_line(&line) { + if ib.add_line(line) { return false; } self.is_prev_line_multi_line = false; @@ -647,25 +647,21 @@ impl<'a> CommentRewrite<'a> { } else if self.code_block_attr.is_some() { if line.starts_with("```") { let code_block = match self.code_block_attr.as_ref().unwrap() { - CodeBlockAttribute::Ignore | CodeBlockAttribute::Text => { - trim_custom_comment_prefix(&self.code_block_buffer) - } - _ if self.code_block_buffer.is_empty() => String::new(), - _ => { + CodeBlockAttribute::Rust + if self.fmt.config.format_code_in_doc_comments() + && !self.code_block_buffer.is_empty() => + { let mut config = self.fmt.config.clone(); config.set().wrap_comments(false); - if config.format_code_in_doc_comments() { - if let Some(s) = - crate::format_code_block(&self.code_block_buffer, &config, false) - { - trim_custom_comment_prefix(&s.snippet) - } else { - trim_custom_comment_prefix(&self.code_block_buffer) - } + if let Some(s) = + crate::format_code_block(&self.code_block_buffer, &config, false) + { + trim_custom_comment_prefix(&s.snippet) } else { trim_custom_comment_prefix(&self.code_block_buffer) } } + _ => trim_custom_comment_prefix(&self.code_block_buffer), }; if !code_block.is_empty() { self.result.push_str(&self.comment_line_separator); @@ -688,8 +684,8 @@ impl<'a> CommentRewrite<'a> { self.item_block = None; if let Some(stripped) = line.strip_prefix("```") { self.code_block_attr = Some(CodeBlockAttribute::new(stripped)) - } else if self.fmt.config.wrap_comments() && ItemizedBlock::is_itemized_line(&line) { - let ib = ItemizedBlock::new(&line); + } else if self.fmt.config.wrap_comments() && ItemizedBlock::is_itemized_line(line) { + let ib = ItemizedBlock::new(line); self.item_block = Some(ib); return false; } @@ -945,7 +941,7 @@ fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle<'_>) -> (&'a s { (&line[4..], true) } else if let CommentStyle::Custom(opener) = *style { - if let Some(ref stripped) = line.strip_prefix(opener) { + if let Some(stripped) = line.strip_prefix(opener) { (stripped, true) } else { (&line[opener.trim_end().len()..], false) @@ -1388,7 +1384,7 @@ impl<'a> Iterator for LineClasses<'a> { None => unreachable!(), }; - while let Some((kind, c)) = self.base.next() { + for (kind, c) in self.base.by_ref() { // needed to set the kind of the ending character on the last line self.kind = kind; if c == '\n' { @@ -1574,7 +1570,7 @@ pub(crate) fn recover_comment_removed( context.parse_sess.span_to_filename(span), vec![FormattingError::from_span( span, - &context.parse_sess, + context.parse_sess, ErrorKind::LostComment, )], ); @@ -1679,7 +1675,7 @@ impl<'a> Iterator for CommentReducer<'a> { fn remove_comment_header(comment: &str) -> &str { if comment.starts_with("///") || comment.starts_with("//!") { &comment[3..] - } else if let Some(ref stripped) = comment.strip_prefix("//") { + } else if let Some(stripped) = comment.strip_prefix("//") { stripped } else if (comment.starts_with("/**") && !comment.starts_with("/**/")) || comment.starts_with("/*!") diff --git a/src/tools/rustfmt/src/config/mod.rs b/src/tools/rustfmt/src/config/mod.rs index 8c04363b1f..0aabfceb5e 100644 --- a/src/tools/rustfmt/src/config/mod.rs +++ b/src/tools/rustfmt/src/config/mod.rs @@ -69,6 +69,8 @@ create_config! { format_macro_matchers: bool, false, false, "Format the metavariable matching patterns in macros"; format_macro_bodies: bool, true, false, "Format the bodies of macros"; + hex_literal_case: HexLiteralCase, HexLiteralCase::Preserve, false, + "Format hexadecimal integer literals"; // Single line expressions and items empty_item_single_line: bool, true, false, @@ -125,7 +127,7 @@ create_config! { "Add trailing semicolon after break, continue and return"; trailing_comma: SeparatorTactic, SeparatorTactic::Vertical, false, "How to handle trailing commas for lists"; - match_block_trailing_comma: bool, false, false, + match_block_trailing_comma: bool, false, true, "Put a trailing comma after a block based match arm (non-block arms are not affected)"; blank_lines_upper_bound: usize, 1, false, "Maximum number of blank lines which can be put between items"; @@ -136,6 +138,7 @@ create_config! { inline_attribute_width: usize, 0, false, "Write an item and its attribute on the same line \ if their combined width is below a threshold"; + format_generated_files: bool, true, false, "Format generated files"; // Options that can change the source code beyond whitespace/blocks (somewhat linty things) merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one"; @@ -152,7 +155,7 @@ create_config! { "Require a specific version of rustfmt"; unstable_features: bool, false, false, "Enables unstable features. Only available on nightly channel"; - disable_all_formatting: bool, false, false, "Don't reformat anything"; + disable_all_formatting: bool, false, true, "Don't reformat anything"; skip_children: bool, false, false, "Don't reformat out of line modules"; hide_parse_errors: bool, false, false, "Hide errors from the parser"; error_on_line_overflow: bool, false, false, "Error if unable to get all lines within max_width"; @@ -569,6 +572,7 @@ license_template_path = "" format_strings = false format_macro_matchers = false format_macro_bodies = true +hex_literal_case = "Preserve" empty_item_single_line = true struct_lit_single_line = true fn_single_line = false @@ -604,6 +608,7 @@ blank_lines_lower_bound = 0 edition = "2015" version = "One" inline_attribute_width = 0 +format_generated_files = true merge_derives = true use_try_shorthand = false use_field_init_shorthand = false diff --git a/src/tools/rustfmt/src/config/options.rs b/src/tools/rustfmt/src/config/options.rs index 3b91021813..bce9e5d07f 100644 --- a/src/tools/rustfmt/src/config/options.rs +++ b/src/tools/rustfmt/src/config/options.rs @@ -20,7 +20,7 @@ pub enum NewlineStyle { Windows, /// Force CR (`\n). Unix, - /// `\r\n` in Windows, `\n`` on other platforms. + /// `\r\n` in Windows, `\n` on other platforms. Native, } @@ -112,6 +112,8 @@ pub enum GroupImportsTactic { /// 2. other imports /// 3. `self` / `crate` / `super` imports StdExternalCrate, + /// Discard existing groups, and create a single group for everything + One, } #[config_type] @@ -125,6 +127,19 @@ pub enum ImportGranularity { Module, /// Use one `use` statement per imported item. Item, + /// Use one `use` statement including all items. + One, +} + +/// Controls how rustfmt should handle case in hexadecimal literals. +#[config_type] +pub enum HexLiteralCase { + /// Leave the literal as-is + Preserve, + /// Ensure all literals use uppercase lettering + Upper, + /// Ensure all literals use lowercase lettering + Lower, } #[config_type] diff --git a/src/tools/rustfmt/src/emitter/checkstyle.rs b/src/tools/rustfmt/src/emitter/checkstyle.rs index 4448214f3f..76f2527db3 100644 --- a/src/tools/rustfmt/src/emitter/checkstyle.rs +++ b/src/tools/rustfmt/src/emitter/checkstyle.rs @@ -121,7 +121,7 @@ mod tests { format!(r#"<file name="{}">"#, bin_file), format!( r#"<error line="2" severity="warning" message="Should be `{}`" />"#, - XmlEscaped(&r#" println!("Hello, world!");"#), + XmlEscaped(r#" println!("Hello, world!");"#), ), String::from("</file>"), ]; @@ -129,7 +129,7 @@ mod tests { format!(r#"<file name="{}">"#, lib_file), format!( r#"<error line="2" severity="warning" message="Should be `{}`" />"#, - XmlEscaped(&r#" println!("Greetings!");"#), + XmlEscaped(r#" println!("Greetings!");"#), ), String::from("</file>"), ]; diff --git a/src/tools/rustfmt/src/emitter/diff.rs b/src/tools/rustfmt/src/emitter/diff.rs index 2fbbfedb56..7264ad8bbf 100644 --- a/src/tools/rustfmt/src/emitter/diff.rs +++ b/src/tools/rustfmt/src/emitter/diff.rs @@ -23,7 +23,7 @@ impl Emitter for DiffEmitter { }: FormattedFile<'_>, ) -> Result<EmitterResult, io::Error> { const CONTEXT_SIZE: usize = 3; - let mismatch = make_diff(&original_text, formatted_text, CONTEXT_SIZE); + let mismatch = make_diff(original_text, formatted_text, CONTEXT_SIZE); let has_diff = !mismatch.is_empty(); if has_diff { diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index 975af6c029..58942e442d 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -13,7 +13,7 @@ use crate::comment::{ rewrite_missing_comment, CharClasses, FindUncommented, }; use crate::config::lists::*; -use crate::config::{Config, ControlBraceStyle, IndentStyle, Version}; +use crate::config::{Config, ControlBraceStyle, HexLiteralCase, IndentStyle, Version}; use crate::lists::{ definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, struct_lit_tactic, write_list, ListFormatting, Separator, @@ -257,7 +257,7 @@ pub(crate) fn format_expr( } _ => false, }, - ast::ExprKind::Unary(_, ref expr) => needs_space_before_range(context, &expr), + ast::ExprKind::Unary(_, ref expr) => needs_space_before_range(context, expr), _ => false, } } @@ -423,7 +423,7 @@ fn rewrite_empty_block( prefix: &str, shape: Shape, ) -> Option<String> { - if block_has_statements(&block) { + if block_has_statements(block) { return None; } @@ -822,7 +822,7 @@ impl<'a> ControlFlow<'a> { let pat_string = pat.rewrite(context, pat_shape)?; let comments_lo = context .snippet_provider - .span_after(self.span, self.connector.trim()); + .span_after(self.span.with_lo(pat.span.hi()), self.connector.trim()); let comments_span = mk_sp(comments_lo, expr.span.lo()); return rewrite_assign_rhs_with_comments( context, @@ -1148,7 +1148,7 @@ pub(crate) fn is_empty_block( block: &ast::Block, attrs: Option<&[ast::Attribute]>, ) -> bool { - !block_has_statements(&block) + !block_has_statements(block) && !block_contains_comment(context, block) && attrs.map_or(true, |a| inner_attributes(a).is_empty()) } @@ -1168,6 +1168,7 @@ pub(crate) fn rewrite_literal( ) -> Option<String> { match l.kind { ast::LitKind::Str(_, ast::StrStyle::Cooked) => rewrite_string_lit(context, l.span, shape), + ast::LitKind::Int(..) => rewrite_int_lit(context, l, shape), _ => wrap_str( context.snippet(l.span).to_owned(), context.config.max_width(), @@ -1202,6 +1203,36 @@ fn rewrite_string_lit(context: &RewriteContext<'_>, span: Span, shape: Shape) -> ) } +fn rewrite_int_lit(context: &RewriteContext<'_>, lit: &ast::Lit, shape: Shape) -> Option<String> { + let span = lit.span; + let symbol = lit.token.symbol.as_str(); + + if let Some(symbol_stripped) = symbol.strip_prefix("0x") { + let hex_lit = match context.config.hex_literal_case() { + HexLiteralCase::Preserve => None, + HexLiteralCase::Upper => Some(symbol_stripped.to_ascii_uppercase()), + HexLiteralCase::Lower => Some(symbol_stripped.to_ascii_lowercase()), + }; + if let Some(hex_lit) = hex_lit { + return wrap_str( + format!( + "0x{}{}", + hex_lit, + lit.token.suffix.map_or(String::new(), |s| s.to_string()) + ), + context.config.max_width(), + shape, + ); + } + } + + wrap_str( + context.snippet(span).to_owned(), + context.config.max_width(), + shape, + ) +} + fn choose_separator_tactic(context: &RewriteContext<'_>, span: Span) -> Option<SeparatorTactic> { if context.inside_macro() { if span_ends_with_comma(context, span) { @@ -1497,12 +1528,12 @@ fn rewrite_struct_lit<'a>( let path_shape = shape.sub_width(2)?; let path_str = rewrite_path(context, PathContext::Expr, None, path, path_shape)?; - let has_base = match struct_rest { + let has_base_or_rest = match struct_rest { ast::StructRest::None if fields.is_empty() => return Some(format!("{} {{}}", path_str)), ast::StructRest::Rest(_) if fields.is_empty() => { return Some(format!("{} {{ .. }}", path_str)); } - ast::StructRest::Base(_) => true, + ast::StructRest::Rest(_) | ast::StructRest::Base(_) => true, _ => false, }; @@ -1511,7 +1542,7 @@ fn rewrite_struct_lit<'a>( let one_line_width = h_shape.map_or(0, |shape| shape.width); let body_lo = context.snippet_provider.span_after(span, "{"); - let fields_str = if struct_lit_can_be_aligned(fields, has_base) + let fields_str = if struct_lit_can_be_aligned(fields, has_base_or_rest) && context.config.struct_field_align_threshold() > 0 { rewrite_with_alignment( @@ -1583,17 +1614,14 @@ fn rewrite_struct_lit<'a>( nested_shape, tactic, context, - force_no_trailing_comma - || has_base - || !context.use_block_indent() - || matches!(struct_rest, ast::StructRest::Rest(_)), + force_no_trailing_comma || has_base_or_rest || !context.use_block_indent(), ); write_list(&item_vec, &fmt)? }; let fields_str = - wrap_struct_field(context, &attrs, &fields_str, shape, v_shape, one_line_width)?; + wrap_struct_field(context, attrs, &fields_str, shape, v_shape, one_line_width)?; Some(format!("{} {{{}}}", path_str, fields_str)) // FIXME if context.config.indent_style() == Visual, but we run out @@ -1860,7 +1888,7 @@ pub(crate) fn rewrite_assign_rhs_expr<R: Rewrite>( shape: Shape, rhs_tactics: RhsTactics, ) -> Option<String> { - let last_line_width = last_line_width(&lhs).saturating_sub(if lhs.contains('\n') { + let last_line_width = last_line_width(lhs).saturating_sub(if lhs.contains('\n') { shape.indent.width() } else { 0 @@ -1919,7 +1947,7 @@ pub(crate) fn rewrite_assign_rhs_with_comments<S: Into<String>, R: Rewrite>( if contains_comment { let rhs = rhs.trim_start(); - combine_strs_with_missing_comments(context, &lhs, &rhs, between_span, shape, allow_extend) + combine_strs_with_missing_comments(context, &lhs, rhs, between_span, shape, allow_extend) } else { Some(lhs + &rhs) } @@ -1934,6 +1962,9 @@ fn choose_rhs<R: Rewrite>( has_rhs_comment: bool, ) -> Option<String> { match orig_rhs { + Some(ref new_str) if new_str.is_empty() => { + return Some(String::new()); + } Some(ref new_str) if !new_str.contains('\n') && unicode_str_width(new_str) <= shape.width => { diff --git a/src/tools/rustfmt/src/format-diff/main.rs b/src/tools/rustfmt/src/format-diff/main.rs index c751932273..655aeda42b 100644 --- a/src/tools/rustfmt/src/format-diff/main.rs +++ b/src/tools/rustfmt/src/format-diff/main.rs @@ -64,7 +64,7 @@ pub struct Opts { } fn main() { - env_logger::init(); + env_logger::Builder::from_env("RUSTFMT_LOG").init(); let opts = Opts::from_args(); if let Err(e) = run(opts) { println!("{}", e); diff --git a/src/tools/rustfmt/src/formatting.rs b/src/tools/rustfmt/src/formatting.rs index e0403574ee..05a74d322b 100644 --- a/src/tools/rustfmt/src/formatting.rs +++ b/src/tools/rustfmt/src/formatting.rs @@ -10,6 +10,7 @@ use rustc_span::Span; use self::newline_style::apply_newline_style; use crate::comment::{CharClasses, FullCodeCharKind}; use crate::config::{Config, FileName, Verbosity}; +use crate::formatting::generated::is_generated_file; use crate::issues::BadIssueSeeker; use crate::modules::Module; use crate::syntux::parser::{DirectoryOwnership, Parser, ParserError}; @@ -18,6 +19,7 @@ use crate::utils::count_newlines; use crate::visitor::FmtVisitor; use crate::{modules, source_file, ErrorKind, FormatReport, Input, Session}; +mod generated; mod newline_style; // A map of the files of a crate, with their new content @@ -103,7 +105,12 @@ fn format_project<T: FormatHandler>( context.parse_session.set_silent_emitter(); for (path, module) in files { - let should_ignore = !input_is_stdin && context.ignore_file(&path); + let source_file = context.parse_session.span_to_file_contents(module.span); + let src = source_file.src.as_ref().expect("SourceFile without src"); + + let should_ignore = (!input_is_stdin && context.ignore_file(&path)) + || (!input_is_stdin && !config.format_generated_files() && is_generated_file(src)); + if (config.skip_children() && path != main_file) || should_ignore { continue; } @@ -148,7 +155,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { let snippet_provider = self.parse_session.snippet_provider(module.span); let mut visitor = FmtVisitor::from_parse_sess( &self.parse_session, - &self.config, + self.config, &snippet_provider, self.report.clone(), ); @@ -173,7 +180,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { &mut visitor.buffer, &path, &visitor.skipped_range.borrow(), - &self.config, + self.config, &self.report, ); diff --git a/src/tools/rustfmt/src/formatting/generated.rs b/src/tools/rustfmt/src/formatting/generated.rs new file mode 100644 index 0000000000..58f43f17ee --- /dev/null +++ b/src/tools/rustfmt/src/formatting/generated.rs @@ -0,0 +1,7 @@ +/// Returns `true` if the given span is a part of generated files. +pub(super) fn is_generated_file(original_snippet: &str) -> bool { + original_snippet + .lines() + .take(5) // looking for marker only in the beginning of the file + .any(|line| line.contains("@generated")) +} diff --git a/src/tools/rustfmt/src/git-rustfmt/main.rs b/src/tools/rustfmt/src/git-rustfmt/main.rs index 16f5d1dd4f..579778edbe 100644 --- a/src/tools/rustfmt/src/git-rustfmt/main.rs +++ b/src/tools/rustfmt/src/git-rustfmt/main.rs @@ -170,7 +170,7 @@ impl Config { } fn main() { - env_logger::init(); + env_logger::Builder::from_env("RUSTFMT_LOG").init(); let opts = make_opts(); let matches = opts diff --git a/src/tools/rustfmt/src/imports.rs b/src/tools/rustfmt/src/imports.rs index 64d78605f0..40e0d06f99 100644 --- a/src/tools/rustfmt/src/imports.rs +++ b/src/tools/rustfmt/src/imports.rs @@ -138,6 +138,29 @@ impl UseSegment { } } + // Check if self == other with their aliases removed. + fn equal_except_alias(&self, other: &Self) -> bool { + match (self, other) { + (UseSegment::Ident(ref s1, _), UseSegment::Ident(ref s2, _)) => s1 == s2, + (UseSegment::Slf(_), UseSegment::Slf(_)) + | (UseSegment::Super(_), UseSegment::Super(_)) + | (UseSegment::Crate(_), UseSegment::Crate(_)) + | (UseSegment::Glob, UseSegment::Glob) => true, + (UseSegment::List(ref list1), UseSegment::List(ref list2)) => list1 == list2, + _ => false, + } + } + + fn get_alias(&self) -> Option<&str> { + match self { + UseSegment::Ident(_, a) + | UseSegment::Slf(a) + | UseSegment::Super(a) + | UseSegment::Crate(a) => a.as_deref(), + _ => None, + } + } + fn from_path_segment( context: &RewriteContext<'_>, path_seg: &ast::PathSegment, @@ -252,7 +275,7 @@ impl UseTree { shape: Shape, ) -> Option<String> { let vis = self.visibility.as_ref().map_or(Cow::from(""), |vis| { - crate::utils::format_visibility(context, &vis) + crate::utils::format_visibility(context, vis) }); let use_str = self .rewrite(context, shape.offset_left(vis.len())?) @@ -558,6 +581,7 @@ impl UseTree { SharedPrefix::Module => { self.path[..self.path.len() - 1] == other.path[..other.path.len() - 1] } + SharedPrefix::One => true, } } } @@ -598,7 +622,7 @@ impl UseTree { fn merge(&mut self, other: &UseTree, merge_by: SharedPrefix) { let mut prefix = 0; for (a, b) in self.path.iter().zip(other.path.iter()) { - if *a == *b { + if a.equal_except_alias(b) { prefix += 1; } else { break; @@ -633,14 +657,20 @@ fn merge_rest( return Some(new_path); } } else if len == 1 { - let rest = if a.len() == len { &b[1..] } else { &a[1..] }; - return Some(vec![ - b[0].clone(), - UseSegment::List(vec![ - UseTree::from_path(vec![UseSegment::Slf(None)], DUMMY_SP), - UseTree::from_path(rest.to_vec(), DUMMY_SP), - ]), - ]); + let (common, rest) = if a.len() == len { + (&a[0], &b[1..]) + } else { + (&b[0], &a[1..]) + }; + let mut list = vec![UseTree::from_path( + vec![UseSegment::Slf(common.get_alias().map(ToString::to_string))], + DUMMY_SP, + )]; + match rest { + [UseSegment::List(rest_list)] => list.extend(rest_list.clone()), + _ => list.push(UseTree::from_path(rest.to_vec(), DUMMY_SP)), + } + return Some(vec![b[0].clone(), UseSegment::List(list)]); } else { len -= 1; } @@ -655,18 +685,54 @@ fn merge_rest( } fn merge_use_trees_inner(trees: &mut Vec<UseTree>, use_tree: UseTree, merge_by: SharedPrefix) { - let similar_trees = trees - .iter_mut() - .filter(|tree| tree.share_prefix(&use_tree, merge_by)); + struct SimilarTree<'a> { + similarity: usize, + path_len: usize, + tree: &'a mut UseTree, + } + + let similar_trees = trees.iter_mut().filter_map(|tree| { + if tree.share_prefix(&use_tree, merge_by) { + // In the case of `SharedPrefix::One`, `similarity` is used for deciding with which + // tree `use_tree` should be merge. + // In other cases `similarity` won't be used, so set it to `0` as a dummy value. + let similarity = if merge_by == SharedPrefix::One { + tree.path + .iter() + .zip(&use_tree.path) + .take_while(|(a, b)| a.equal_except_alias(b)) + .count() + } else { + 0 + }; + + let path_len = tree.path.len(); + Some(SimilarTree { + similarity, + tree, + path_len, + }) + } else { + None + } + }); + if use_tree.path.len() == 1 && merge_by == SharedPrefix::Crate { - if let Some(tree) = similar_trees.min_by_key(|tree| tree.path.len()) { - if tree.path.len() == 1 { + if let Some(tree) = similar_trees.min_by_key(|tree| tree.path_len) { + if tree.path_len == 1 { + return; + } + } + } else if merge_by == SharedPrefix::One { + if let Some(sim_tree) = similar_trees.max_by_key(|tree| tree.similarity) { + if sim_tree.similarity > 0 { + sim_tree.tree.merge(&use_tree, merge_by); return; } } - } else if let Some(tree) = similar_trees.max_by_key(|tree| tree.path.len()) { - if tree.path.len() > 1 { - tree.merge(&use_tree, merge_by); + } else if let Some(sim_tree) = similar_trees.max_by_key(|tree| tree.path_len) { + if sim_tree.path_len > 1 { + sim_tree.tree.merge(&use_tree, merge_by); return; } } @@ -863,7 +929,7 @@ impl Rewrite for UseTree { fn rewrite(&self, context: &RewriteContext<'_>, mut shape: Shape) -> Option<String> { let mut result = String::with_capacity(256); let mut iter = self.path.iter().peekable(); - while let Some(ref segment) = iter.next() { + while let Some(segment) = iter.next() { let segment_str = segment.rewrite(context, shape)?; result.push_str(&segment_str); if iter.peek().is_some() { @@ -880,6 +946,7 @@ impl Rewrite for UseTree { pub(crate) enum SharedPrefix { Crate, Module, + One, } #[cfg(test)] @@ -904,7 +971,7 @@ mod test { } fn eat(&mut self, c: char) { - assert!(self.input.next().unwrap() == c); + assert_eq!(self.input.next().unwrap(), c); } fn push_segment( @@ -1094,6 +1161,49 @@ mod test { ); } + #[test] + fn test_use_tree_merge_one() { + test_merge!(One, ["a", "b"], ["{a, b}"]); + + test_merge!(One, ["a::{aa, ab}", "b", "a"], ["{a::{self, aa, ab}, b}"]); + + test_merge!(One, ["a as x", "b as y"], ["{a as x, b as y}"]); + + test_merge!( + One, + ["a::{aa as xa, ab}", "b", "a"], + ["{a::{self, aa as xa, ab}, b}"] + ); + + test_merge!( + One, + ["a", "a::{aa, ab::{aba, abb}}"], + ["a::{self, aa, ab::{aba, abb}}"] + ); + + test_merge!(One, ["a", "b::{ba, *}"], ["{a, b::{ba, *}}"]); + + test_merge!(One, ["a", "b", "a::aa"], ["{a::{self, aa}, b}"]); + + test_merge!( + One, + ["a::aa::aaa", "a::ac::aca", "a::aa::*"], + ["a::{aa::{aaa, *}, ac::aca}"] + ); + + test_merge!( + One, + ["a", "b::{ba, bb}", "a::{aa::*, ab::aba}"], + ["{a::{self, aa::*, ab::aba}, b::{ba, bb}}"] + ); + + test_merge!( + One, + ["b", "a::ac::{aca, acb}", "a::{aa::*, ab}"], + ["{a::{aa::*, ab, ac::{aca, acb}}, b}"] + ); + } + #[test] fn test_flatten_use_trees() { assert_eq!( diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 14041539b9..acc91f861e 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -174,14 +174,14 @@ pub(crate) struct FnSig<'a> { constness: ast::Const, defaultness: ast::Defaultness, unsafety: ast::Unsafe, - visibility: ast::Visibility, + visibility: &'a ast::Visibility, } impl<'a> FnSig<'a> { pub(crate) fn from_method_sig( method_sig: &'a ast::FnSig, generics: &'a ast::Generics, - visibility: ast::Visibility, + visibility: &'a ast::Visibility, ) -> FnSig<'a> { FnSig { unsafety: method_sig.header.unsafety, @@ -204,7 +204,7 @@ impl<'a> FnSig<'a> { match *fn_kind { visit::FnKind::Fn(fn_ctxt, _, fn_sig, vis, _) => match fn_ctxt { visit::FnCtxt::Assoc(..) => { - let mut fn_sig = FnSig::from_method_sig(fn_sig, generics, vis.clone()); + let mut fn_sig = FnSig::from_method_sig(fn_sig, generics, vis); fn_sig.defaultness = defaultness; fn_sig } @@ -216,7 +216,7 @@ impl<'a> FnSig<'a> { is_async: Cow::Borrowed(&fn_sig.header.asyncness), defaultness, unsafety: fn_sig.header.unsafety, - visibility: vis.clone(), + visibility: vis, }, }, _ => unreachable!(), @@ -226,7 +226,7 @@ impl<'a> FnSig<'a> { fn to_str(&self, context: &RewriteContext<'_>) -> String { let mut result = String::with_capacity(128); // Vis defaultness constness unsafety abi. - result.push_str(&*format_visibility(context, &self.visibility)); + result.push_str(&*format_visibility(context, self.visibility)); result.push_str(format_defaultness(self.defaultness)); result.push_str(format_constness(self.constness)); result.push_str(format_async(&self.is_async)); @@ -323,6 +323,7 @@ impl<'a> FmtVisitor<'a> { indent: Indent, ident: symbol::Ident, sig: &ast::FnSig, + vis: &ast::Visibility, generics: &ast::Generics, span: Span, ) -> Option<String> { @@ -334,7 +335,7 @@ impl<'a> FmtVisitor<'a> { &context, indent, ident, - &FnSig::from_method_sig(sig, generics, DEFAULT_VISIBILITY), + &FnSig::from_method_sig(sig, generics, vis), span, FnBraceStyle::None, )?; @@ -621,7 +622,7 @@ impl<'a> FmtVisitor<'a> { fn need_empty_line(a: &ast::AssocItemKind, b: &ast::AssocItemKind) -> bool { match (a, b) { (TyAlias(lty), TyAlias(rty)) - if both_type(<y.3, &rty.3) || both_opaque(<y.3, &rty.3) => + if both_type(<y.ty, &rty.ty) || both_opaque(<y.ty, &rty.ty) => { false } @@ -632,7 +633,7 @@ impl<'a> FmtVisitor<'a> { buffer.sort_by(|(_, a), (_, b)| match (&a.kind, &b.kind) { (TyAlias(lty), TyAlias(rty)) - if both_type(<y.3, &rty.3) || both_opaque(<y.3, &rty.3) => + if both_type(<y.ty, &rty.ty) || both_opaque(<y.ty, &rty.ty) => { a.ident.as_str().cmp(&b.ident.as_str()) } @@ -640,8 +641,8 @@ impl<'a> FmtVisitor<'a> { a.ident.as_str().cmp(&b.ident.as_str()) } (Fn(..), Fn(..)) => a.span.lo().cmp(&b.span.lo()), - (TyAlias(ty), _) if is_type(&ty.3) => Ordering::Less, - (_, TyAlias(ty)) if is_type(&ty.3) => Ordering::Greater, + (TyAlias(ty), _) if is_type(&ty.ty) => Ordering::Less, + (_, TyAlias(ty)) if is_type(&ty.ty) => Ordering::Greater, (TyAlias(..), _) => Ordering::Less, (_, TyAlias(..)) => Ordering::Greater, (Const(..), _) => Ordering::Less, @@ -678,7 +679,7 @@ pub(crate) fn format_impl( offset: Indent, ) -> Option<String> { if let ast::ItemKind::Impl(impl_kind) = &item.kind { - let ast::ImplKind { + let ast::Impl { ref generics, ref self_ty, ref items, @@ -832,7 +833,7 @@ fn format_impl_ref_and_type( offset: Indent, ) -> Option<String> { if let ast::ItemKind::Impl(impl_kind) = &item.kind { - let ast::ImplKind { + let ast::Impl { unsafety, polarity, defaultness, @@ -1028,8 +1029,13 @@ pub(crate) fn format_trait( offset: Indent, ) -> Option<String> { if let ast::ItemKind::Trait(trait_kind) = &item.kind { - let ast::TraitKind(is_auto, unsafety, ref generics, ref generic_bounds, ref trait_items) = - **trait_kind; + let ast::Trait { + is_auto, + unsafety, + ref generics, + ref bounds, + ref items, + } = **trait_kind; let mut result = String::with_capacity(128); let header = format!( "{}{}{}trait ", @@ -1047,11 +1053,11 @@ pub(crate) fn format_trait( result.push_str(&generics_str); // FIXME(#2055): rustfmt fails to format when there are comments between trait bounds. - if !generic_bounds.is_empty() { + if !bounds.is_empty() { let ident_hi = context .snippet_provider .span_after(item.span, &item.ident.as_str()); - let bound_hi = generic_bounds.last().unwrap().span().hi(); + let bound_hi = bounds.last().unwrap().span().hi(); let snippet = context.snippet(mk_sp(ident_hi, bound_hi)); if contains_comment(snippet) { return None; @@ -1060,7 +1066,7 @@ pub(crate) fn format_trait( result = rewrite_assign_rhs_with( context, result + ":", - generic_bounds, + bounds, shape, RhsTactics::ForceNextLineWithoutIndent, )?; @@ -1071,10 +1077,10 @@ pub(crate) fn format_trait( let where_on_new_line = context.config.indent_style() != IndentStyle::Block; let where_budget = context.budget(last_line_width(&result)); - let pos_before_where = if generic_bounds.is_empty() { + let pos_before_where = if bounds.is_empty() { generics.where_clause.span.lo() } else { - generic_bounds[generic_bounds.len() - 1].span().hi() + bounds[bounds.len() - 1].span().hi() }; let option = WhereClauseOption::snuggled(&generics_str); let where_clause_str = rewrite_where_clause( @@ -1121,19 +1127,31 @@ pub(crate) fn format_trait( } } + let block_span = mk_sp(generics.where_clause.span.hi(), item.span.hi()); + let snippet = context.snippet(block_span); + let open_pos = snippet.find_uncommented("{")? + 1; + match context.config.brace_style() { _ if last_line_contains_single_line_comment(&result) || last_line_width(&result) + 2 > context.budget(offset.width()) => { result.push_str(&offset.to_string_with_newline(context.config)); } + _ if context.config.empty_item_single_line() + && items.is_empty() + && !result.contains('\n') + && !contains_comment(&snippet[open_pos..]) => + { + result.push_str(" {}"); + return Some(result); + } BraceStyle::AlwaysNextLine => { result.push_str(&offset.to_string_with_newline(context.config)); } BraceStyle::PreferSameLine => result.push(' '), BraceStyle::SameLineWhere => { if result.contains('\n') - || (!generics.where_clause.predicates.is_empty() && !trait_items.is_empty()) + || (!generics.where_clause.predicates.is_empty() && !items.is_empty()) { result.push_str(&offset.to_string_with_newline(context.config)); } else { @@ -1143,17 +1161,14 @@ pub(crate) fn format_trait( } result.push('{'); - let block_span = mk_sp(generics.where_clause.span.hi(), item.span.hi()); - let snippet = context.snippet(block_span); - let open_pos = snippet.find_uncommented("{")? + 1; let outer_indent_str = offset.block_only().to_string_with_newline(context.config); - if !trait_items.is_empty() || contains_comment(&snippet[open_pos..]) { + if !items.is_empty() || contains_comment(&snippet[open_pos..]) { let mut visitor = FmtVisitor::from_context(context); visitor.block_indent = offset.block_only().block_indent(context.config); visitor.last_pos = block_span.lo() + BytePos(open_pos as u32); - for item in trait_items { + for item in items { visitor.visit_trait_item(item); } @@ -1175,18 +1190,6 @@ pub(crate) fn format_trait( } } -struct OpaqueTypeBounds<'a> { - generic_bounds: &'a ast::GenericBounds, -} - -impl<'a> Rewrite for OpaqueTypeBounds<'a> { - fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> { - self.generic_bounds - .rewrite(context, shape) - .map(|s| format!("impl {}", s)) - } -} - pub(crate) struct TraitAliasBounds<'a> { generic_bounds: &'a ast::GenericBounds, generics: &'a ast::Generics, @@ -1219,7 +1222,7 @@ impl<'a> Rewrite for TraitAliasBounds<'a> { } else if fits_single_line { Cow::from(" ") } else { - shape.indent.to_string_with_newline(&context.config) + shape.indent.to_string_with_newline(context.config) }; Some(format!("{}{}{}", generic_bounds_str, space, where_str)) @@ -1237,7 +1240,7 @@ pub(crate) fn format_trait_alias( let alias = rewrite_ident(context, ident); // 6 = "trait ", 2 = " =" let g_shape = shape.offset_left(6)?.sub_width(2)?; - let generics_str = rewrite_generics(context, &alias, generics, g_shape)?; + let generics_str = rewrite_generics(context, alias, generics, g_shape)?; let vis_str = format_visibility(context, vis); let lhs = format!("{}trait {} =", vis_str, generics_str); // 1 = ";" @@ -1385,7 +1388,7 @@ fn format_empty_struct_or_tuple( closer: &str, ) { // 3 = " {}" or "();" - let used_width = last_line_used_width(&result, offset.width()) + 3; + let used_width = last_line_used_width(result, offset.width()) + 3; if used_width > context.config.max_width() { result.push_str(&offset.to_string_with_newline(context.config)) } @@ -1474,12 +1477,17 @@ fn format_tuple_struct( format_empty_struct_or_tuple(context, inner_span, offset, &mut result, "(", ")"); } else { let shape = Shape::indented(offset, context.config).sub_width(1)?; + let lo = if let Some(generics) = struct_parts.generics { + generics.span.hi() + } else { + struct_parts.ident.span.hi() + }; result = overflow::rewrite_with_parens( context, &result, fields.iter(), shape, - span, + mk_sp(lo, span.hi()), context.config.fn_call_width(), None, )?; @@ -1503,17 +1511,84 @@ fn format_tuple_struct( Some(result) } -fn rewrite_type<R: Rewrite>( - context: &RewriteContext<'_>, +pub(crate) enum ItemVisitorKind<'a> { + Item(&'a ast::Item), + AssocTraitItem(&'a ast::AssocItem), + AssocImplItem(&'a ast::AssocItem), + ForeignItem(&'a ast::ForeignItem), +} + +struct TyAliasRewriteInfo<'c, 'g>( + &'c RewriteContext<'c>, + Indent, + &'g ast::Generics, + symbol::Ident, + Span, +); + +pub(crate) fn rewrite_type_alias<'a, 'b>( + ty_alias_kind: &ast::TyAlias, + context: &RewriteContext<'a>, indent: Indent, - ident: symbol::Ident, - vis: &ast::Visibility, - generics: &ast::Generics, + visitor_kind: &ItemVisitorKind<'b>, + span: Span, +) -> Option<String> { + use ItemVisitorKind::*; + + let ast::TyAlias { + defaultness, + ref generics, + ref bounds, + ref ty, + } = *ty_alias_kind; + let ty_opt = ty.as_ref().map(|t| &**t); + let (ident, vis) = match visitor_kind { + Item(i) => (i.ident, &i.vis), + AssocTraitItem(i) | AssocImplItem(i) => (i.ident, &i.vis), + ForeignItem(i) => (i.ident, &i.vis), + }; + let rw_info = &TyAliasRewriteInfo(context, indent, generics, ident, span); + + // Type Aliases are formatted slightly differently depending on the context + // in which they appear, whether they are opaque, and whether they are associated. + // https://rustc-dev-guide.rust-lang.org/opaque-types-type-alias-impl-trait.html + // https://github.com/rust-dev-tools/fmt-rfcs/blob/master/guide/items.md#type-aliases + match (visitor_kind, ty_opt) { + (Item(_), None) => { + let op_ty = OpaqueType { bounds }; + rewrite_ty(rw_info, Some(bounds), Some(&op_ty), vis) + } + (Item(_), Some(ty)) => rewrite_ty(rw_info, Some(bounds), Some(&*ty), vis), + (AssocImplItem(_), _) => { + let result = if let Some(ast::Ty { + kind: ast::TyKind::ImplTrait(_, ref bounds), + .. + }) = ty_opt + { + let op_ty = OpaqueType { bounds }; + rewrite_ty(rw_info, None, Some(&op_ty), &DEFAULT_VISIBILITY) + } else { + rewrite_ty(rw_info, None, ty.as_ref(), vis) + }?; + match defaultness { + ast::Defaultness::Default(..) => Some(format!("default {}", result)), + _ => Some(result), + } + } + (AssocTraitItem(_), _) | (ForeignItem(_), _) => { + rewrite_ty(rw_info, Some(bounds), ty.as_ref(), vis) + } + } +} + +fn rewrite_ty<R: Rewrite>( + rw_info: &TyAliasRewriteInfo<'_, '_>, generic_bounds_opt: Option<&ast::GenericBounds>, rhs: Option<&R>, - span: Span, + vis: &ast::Visibility, ) -> Option<String> { let mut result = String::with_capacity(128); + let TyAliasRewriteInfo(context, indent, generics, ident, span) = *rw_info; result.push_str(&format!("{}type ", format_visibility(context, vis))); let ident_str = rewrite_ident(context, ident); @@ -1601,28 +1676,6 @@ fn rewrite_type<R: Rewrite>( } } -pub(crate) fn rewrite_opaque_type( - context: &RewriteContext<'_>, - indent: Indent, - ident: symbol::Ident, - generic_bounds: &ast::GenericBounds, - generics: &ast::Generics, - vis: &ast::Visibility, - span: Span, -) -> Option<String> { - let opaque_type_bounds = OpaqueTypeBounds { generic_bounds }; - rewrite_type( - context, - indent, - ident, - vis, - generics, - Some(generic_bounds), - Some(&opaque_type_bounds), - span, - ) -} - fn type_annotation_spacing(config: &Config) -> (&str, &str) { ( if config.space_before_colon() { " " } else { "" }, @@ -1760,7 +1813,7 @@ impl<'a> StaticParts<'a> { }; StaticParts { prefix: "const", - vis: &DEFAULT_VISIBILITY, + vis: &ti.vis, ident: ti.ident, ty, mutability: ast::Mutability::Not, @@ -1847,29 +1900,6 @@ fn rewrite_static( Some(format!("{}{};", prefix, ty_str)) } } - -pub(crate) fn rewrite_type_alias( - ident: symbol::Ident, - ty_opt: Option<&ptr::P<ast::Ty>>, - generics: &ast::Generics, - generic_bounds_opt: Option<&ast::GenericBounds>, - context: &RewriteContext<'_>, - indent: Indent, - vis: &ast::Visibility, - span: Span, -) -> Option<String> { - rewrite_type( - context, - indent, - ident, - vis, - generics, - generic_bounds_opt, - ty_opt, - span, - ) -} - struct OpaqueType<'a> { bounds: &'a ast::GenericBounds, } @@ -1883,49 +1913,6 @@ impl<'a> Rewrite for OpaqueType<'a> { } } -pub(crate) fn rewrite_opaque_impl_type( - context: &RewriteContext<'_>, - ident: symbol::Ident, - generics: &ast::Generics, - generic_bounds: &ast::GenericBounds, - indent: Indent, -) -> Option<String> { - let ident_str = rewrite_ident(context, ident); - // 5 = "type " - let generics_shape = Shape::indented(indent, context.config).offset_left(5)?; - let generics_str = rewrite_generics(context, ident_str, generics, generics_shape)?; - let prefix = format!("type {} =", generics_str); - let rhs = OpaqueType { - bounds: generic_bounds, - }; - - rewrite_assign_rhs( - context, - &prefix, - &rhs, - Shape::indented(indent, context.config).sub_width(1)?, - ) - .map(|s| s + ";") -} - -pub(crate) fn rewrite_associated_impl_type( - ident: symbol::Ident, - vis: &ast::Visibility, - defaultness: ast::Defaultness, - ty_opt: Option<&ptr::P<ast::Ty>>, - generics: &ast::Generics, - context: &RewriteContext<'_>, - indent: Indent, - span: Span, -) -> Option<String> { - let result = rewrite_type_alias(ident, ty_opt, generics, None, context, indent, vis, span)?; - - match defaultness { - ast::Defaultness::Default(..) => Some(format!("default {}", result)), - _ => Some(result), - } -} - impl Rewrite for ast::FnRetTy { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> { match *self { @@ -1995,14 +1982,17 @@ impl Rewrite for ast::Param { let param_attrs_result = self .attrs .rewrite(context, Shape::legacy(shape.width, shape.indent))?; - let (span, has_multiple_attr_lines) = if !self.attrs.is_empty() { + // N.B. Doc comments aren't typically valid syntax, but could appear + // in the presence of certain macros - https://github.com/rust-lang/rustfmt/issues/4936 + let (span, has_multiple_attr_lines, has_doc_comments) = if !self.attrs.is_empty() { let num_attrs = self.attrs.len(); ( mk_sp(self.attrs[num_attrs - 1].span.hi(), self.pat.span.lo()), param_attrs_result.contains('\n'), + self.attrs.iter().any(|a| a.is_doc_comment()), ) } else { - (mk_sp(self.span.lo(), self.span.lo()), false) + (mk_sp(self.span.lo(), self.span.lo()), false, false) }; if let Some(ref explicit_self) = self.to_self() { @@ -2015,15 +2005,16 @@ impl Rewrite for ast::Param { has_multiple_attr_lines, ) } else if is_named_param(self) { + let param_name = &self + .pat + .rewrite(context, Shape::legacy(shape.width, shape.indent))?; let mut result = combine_strs_with_missing_comments( context, ¶m_attrs_result, - &self - .pat - .rewrite(context, Shape::legacy(shape.width, shape.indent))?, + param_name, span, shape, - !has_multiple_attr_lines, + !has_multiple_attr_lines && !has_doc_comments, )?; if !is_empty_infer(&*self.ty, self.pat.span) { @@ -2034,10 +2025,30 @@ impl Rewrite for ast::Param { result.push_str(&after_comment); let overhead = last_line_width(&result); let max_width = shape.width.checked_sub(overhead)?; - let ty_str = self + if let Some(ty_str) = self .ty - .rewrite(context, Shape::legacy(max_width, shape.indent))?; - result.push_str(&ty_str); + .rewrite(context, Shape::legacy(max_width, shape.indent)) + { + result.push_str(&ty_str); + } else { + result = combine_strs_with_missing_comments( + context, + &(param_attrs_result + &shape.to_string_with_newline(context.config)), + param_name, + span, + shape, + !has_multiple_attr_lines, + )?; + result.push_str(&before_comment); + result.push_str(colon_spaces(context.config)); + result.push_str(&after_comment); + let overhead = last_line_width(&result); + let max_width = shape.width.checked_sub(overhead)?; + let ty_str = self + .ty + .rewrite(context, Shape::legacy(max_width, shape.indent))?; + result.push_str(&ty_str); + } } Some(result) @@ -2066,7 +2077,7 @@ fn rewrite_explicit_self( )?; Some(combine_strs_with_missing_comments( context, - ¶m_attrs, + param_attrs, &format!("&{} {}self", lifetime_str, mut_str), span, shape, @@ -2075,7 +2086,7 @@ fn rewrite_explicit_self( } None => Some(combine_strs_with_missing_comments( context, - ¶m_attrs, + param_attrs, &format!("&{}self", mut_str), span, shape, @@ -2091,7 +2102,7 @@ fn rewrite_explicit_self( Some(combine_strs_with_missing_comments( context, - ¶m_attrs, + param_attrs, &format!("{}self: {}", format_mutability(mutability), type_str), span, shape, @@ -2100,7 +2111,7 @@ fn rewrite_explicit_self( } ast::SelfKind::Value(mutability) => Some(combine_strs_with_missing_comments( context, - ¶m_attrs, + param_attrs, &format!("{}self", format_mutability(mutability)), span, shape, @@ -2225,18 +2236,10 @@ fn rewrite_fn_base( result.push_str(¶m_indent.to_string_with_newline(context.config)); } - // Skip `pub(crate)`. - let lo_after_visibility = get_bytepos_after_visibility(&fn_sig.visibility, span); - // A conservative estimation, the goal is to be over all parens in generics - let params_start = fn_sig - .generics - .params - .last() - .map_or(lo_after_visibility, |param| param.span().hi()); let params_end = if fd.inputs.is_empty() { context .snippet_provider - .span_after(mk_sp(params_start, span.hi()), ")") + .span_after(mk_sp(fn_sig.generics.span.hi(), span.hi()), ")") } else { let last_span = mk_sp(fd.inputs[fd.inputs.len() - 1].span().hi(), span.hi()); context.snippet_provider.span_after(last_span, ")") @@ -2244,7 +2247,7 @@ fn rewrite_fn_base( let params_span = mk_sp( context .snippet_provider - .span_after(mk_sp(params_start, span.hi()), "("), + .span_after(mk_sp(fn_sig.generics.span.hi(), span.hi()), "("), params_end, ); let param_str = rewrite_params( @@ -2984,7 +2987,7 @@ fn format_header( let mut result = String::with_capacity(128); let shape = Shape::indented(offset, context.config); - result.push_str(&format_visibility(context, vis).trim()); + result.push_str(format_visibility(context, vis).trim()); // Check for a missing comment between the visibility and the item name. let after_vis = vis.span.hi(); @@ -3005,7 +3008,7 @@ fn format_header( } } - result.push_str(&rewrite_ident(context, ident)); + result.push_str(rewrite_ident(context, ident)); result } @@ -3125,17 +3128,22 @@ impl Rewrite for ast::ForeignItem { let item_str = match self.kind { ast::ForeignItemKind::Fn(ref fn_kind) => { - let ast::FnKind(defaultness, ref fn_sig, ref generics, ref block) = **fn_kind; - if let Some(ref body) = block { + let ast::Fn { + defaultness, + ref sig, + ref generics, + ref body, + } = **fn_kind; + if let Some(ref body) = body { let mut visitor = FmtVisitor::from_context(context); visitor.block_indent = shape.indent; visitor.last_pos = self.span.lo(); let inner_attrs = inner_attributes(&self.attrs); let fn_ctxt = visit::FnCtxt::Foreign; visitor.visit_fn( - visit::FnKind::Fn(fn_ctxt, self.ident, &fn_sig, &self.vis, Some(body)), + visit::FnKind::Fn(fn_ctxt, self.ident, &sig, &self.vis, Some(body)), generics, - &fn_sig.decl, + &sig.decl, self.span, defaultness, Some(&inner_attrs), @@ -3146,7 +3154,7 @@ impl Rewrite for ast::ForeignItem { context, shape.indent, self.ident, - &FnSig::from_method_sig(&fn_sig, generics, self.vis.clone()), + &FnSig::from_method_sig(&sig, generics, &self.vis), span, FnBraceStyle::None, ) @@ -3167,19 +3175,9 @@ impl Rewrite for ast::ForeignItem { // 1 = ; rewrite_assign_rhs(context, prefix, &**ty, shape.sub_width(1)?).map(|s| s + ";") } - ast::ForeignItemKind::TyAlias(ref ty_alias_kind) => { - let ast::TyAliasKind(_, ref generics, ref generic_bounds, ref type_default) = - **ty_alias_kind; - rewrite_type_alias( - self.ident, - type_default.as_ref(), - generics, - Some(generic_bounds), - &context, - shape.indent, - &self.vis, - self.span, - ) + ast::ForeignItemKind::TyAlias(ref ty_alias) => { + let (kind, span) = (&ItemVisitorKind::ForeignItem(&self), self.span); + rewrite_type_alias(ty_alias, context, shape.indent, kind, span) } ast::ForeignItemKind::MacCall(ref mac) => { rewrite_macro(mac, None, context, shape, MacroPosition::Item) @@ -3229,7 +3227,7 @@ fn rewrite_attrs( combine_strs_with_missing_comments( context, &attrs_str, - &item_str, + item_str, missed_span, shape, allow_extend, diff --git a/src/tools/rustfmt/src/lib.rs b/src/tools/rustfmt/src/lib.rs index 47a7b9d4db..792a1080f0 100644 --- a/src/tools/rustfmt/src/lib.rs +++ b/src/tools/rustfmt/src/lib.rs @@ -283,7 +283,7 @@ impl FormatReport { writeln!( t, "{}", - FormatReportFormatterBuilder::new(&self) + FormatReportFormatterBuilder::new(self) .enable_colors(true) .build() )?; @@ -297,7 +297,7 @@ impl FormatReport { impl fmt::Display for FormatReport { // Prints all the formatting errors. fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - write!(fmt, "{}", FormatReportFormatterBuilder::new(&self).build())?; + write!(fmt, "{}", FormatReportFormatterBuilder::new(self).build())?; Ok(()) } } diff --git a/src/tools/rustfmt/src/lists.rs b/src/tools/rustfmt/src/lists.rs index 73e886c556..d341ec8e6b 100644 --- a/src/tools/rustfmt/src/lists.rs +++ b/src/tools/rustfmt/src/lists.rs @@ -367,9 +367,9 @@ where result.push_str(&comment); if !inner_item.is_empty() { - if tactic == DefinitiveListTactic::Vertical || tactic == DefinitiveListTactic::Mixed - { - // We cannot keep pre-comments on the same line if the comment if normalized. + use DefinitiveListTactic::*; + if matches!(tactic, Vertical | Mixed | SpecialMacro(_)) { + // We cannot keep pre-comments on the same line if the comment is normalized. let keep_comment = if formatting.config.normalize_comments() || item.pre_comment_style == ListItemCommentStyle::DifferentLine { @@ -386,10 +386,10 @@ where result.push('\n'); result.push_str(indent_str); // This is the width of the item (without comments). - line_len = item.item.as_ref().map_or(0, |s| unicode_str_width(&s)); + line_len = item.item.as_ref().map_or(0, |s| unicode_str_width(s)); } } else { - result.push(' '); + result.push(' ') } } item_max_width = None; @@ -820,7 +820,7 @@ where pub(crate) fn total_item_width(item: &ListItem) -> usize { comment_len(item.pre_comment.as_ref().map(|x| &(*x)[..])) + comment_len(item.post_comment.as_ref().map(|x| &(*x)[..])) - + item.item.as_ref().map_or(0, |s| unicode_str_width(&s)) + + item.item.as_ref().map_or(0, |s| unicode_str_width(s)) } fn comment_len(comment: Option<&str>) -> usize { diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs index 927187dfd8..ef747638e3 100644 --- a/src/tools/rustfmt/src/macros.rs +++ b/src/tools/rustfmt/src/macros.rs @@ -186,7 +186,7 @@ fn return_macro_parse_failure_fallback( }) .unwrap_or(false); if is_like_block_indent_style { - return trim_left_preserve_layout(context.snippet(span), indent, &context.config); + return trim_left_preserve_layout(context.snippet(span), indent, context.config); } context.skipped_range.borrow_mut().push(( @@ -437,7 +437,7 @@ fn rewrite_macro_inner( // the `macro_name!` and `{ /* macro_body */ }` but skip modifying // anything in between the braces (for now). let snippet = context.snippet(mac.span()).trim_start_matches(|c| c != '{'); - match trim_left_preserve_layout(snippet, shape.indent, &context.config) { + match trim_left_preserve_layout(snippet, shape.indent, context.config) { Some(macro_body) => Some(format!("{} {}", macro_name, macro_body)), None => Some(format!("{} {}", macro_name, snippet)), } @@ -901,7 +901,7 @@ impl MacroArgParser { break; } TokenTree::Token(ref t) => { - buffer.push_str(&pprust::token_to_string(&t)); + buffer.push_str(&pprust::token_to_string(t)); } _ => return None, } @@ -1045,7 +1045,7 @@ fn wrap_macro_args_inner( let mut iter = args.iter().peekable(); let indent_str = shape.indent.to_string_with_newline(context.config); - while let Some(ref arg) = iter.next() { + while let Some(arg) = iter.next() { result.push_str(&arg.rewrite(context, shape, use_multiple_lines)?); if use_multiple_lines @@ -1055,7 +1055,7 @@ fn wrap_macro_args_inner( result.pop(); } result.push_str(&indent_str); - } else if let Some(ref next_arg) = iter.peek() { + } else if let Some(next_arg) = iter.peek() { let space_before_dollar = !arg.kind.ends_with_space() && next_arg.kind.starts_with_dollar(); let space_before_brace = next_arg.kind.starts_with_brace(); @@ -1370,7 +1370,7 @@ impl MacroBranch { { s += &indent_str; } - (s + l + "\n", indent_next_line(kind, &l, &config)) + (s + l + "\n", indent_next_line(kind, l, &config)) }, ) .0; @@ -1514,11 +1514,11 @@ fn rewrite_macro_with_items( MacroArg::Item(item) => item, _ => return None, }; - visitor.visit_item(&item); + visitor.visit_item(item); } let mut result = String::with_capacity(256); - result.push_str(¯o_name); + result.push_str(macro_name); result.push_str(opener); result.push_str(&visitor.block_indent.to_string_with_newline(context.config)); result.push_str(visitor.buffer.trim()); diff --git a/src/tools/rustfmt/src/matches.rs b/src/tools/rustfmt/src/matches.rs index 140ec226c0..22d23fc1cd 100644 --- a/src/tools/rustfmt/src/matches.rs +++ b/src/tools/rustfmt/src/matches.rs @@ -168,7 +168,7 @@ fn collect_beginning_verts( .map(|a| { context .snippet(a.pat.span) - .starts_with("|") + .starts_with('|') .then(|| a.pat.span().lo()) }) .collect() @@ -319,7 +319,7 @@ fn flatten_arm_body<'a>( let can_extend = |expr| !context.config.force_multiline_blocks() && can_flatten_block_around_this(expr); - if let Some(ref block) = block_can_be_flattened(context, body) { + if let Some(block) = block_can_be_flattened(context, body) { if let ast::StmtKind::Expr(ref expr) = block.stmts[0].kind { if let ast::ExprKind::Block(..) = expr.kind { flatten_arm_body(context, expr, None) @@ -393,7 +393,7 @@ fn rewrite_match_body( if comment_str.is_empty() { String::new() } else { - rewrite_comment(comment_str, false, shape, &context.config)? + rewrite_comment(comment_str, false, shape, context.config)? } }; @@ -408,7 +408,8 @@ fn rewrite_match_body( result.push_str(&arrow_comment); } result.push_str(&nested_indent_str); - result.push_str(&body_str); + result.push_str(body_str); + result.push_str(comma); return Some(result); } @@ -450,7 +451,7 @@ fn rewrite_match_body( result.push_str(&arrow_comment); } result.push_str(&block_sep); - result.push_str(&body_str); + result.push_str(body_str); result.push_str(&body_suffix); Some(result) }; diff --git a/src/tools/rustfmt/src/missed_spans.rs b/src/tools/rustfmt/src/missed_spans.rs index 263d840785..28edcb784b 100644 --- a/src/tools/rustfmt/src/missed_spans.rs +++ b/src/tools/rustfmt/src/missed_spans.rs @@ -51,6 +51,14 @@ impl<'a> FmtVisitor<'a> { } pub(crate) fn format_missing_with_indent(&mut self, end: BytePos) { + self.format_missing_indent(end, true) + } + + pub(crate) fn format_missing_no_indent(&mut self, end: BytePos) { + self.format_missing_indent(end, false) + } + + fn format_missing_indent(&mut self, end: BytePos, should_indent: bool) { let config = self.config; self.format_missing_inner(end, |this, last_snippet, snippet| { this.push_str(last_snippet.trim_end()); @@ -58,14 +66,10 @@ impl<'a> FmtVisitor<'a> { // No new lines in the snippet. this.push_str("\n"); } - let indent = this.block_indent.to_string(config); - this.push_str(&indent); - }) - } - - pub(crate) fn format_missing_no_indent(&mut self, end: BytePos) { - self.format_missing_inner(end, |this, last_snippet, _| { - this.push_str(last_snippet.trim_end()); + if should_indent { + let indent = this.block_indent.to_string(config); + this.push_str(&indent); + } }) } diff --git a/src/tools/rustfmt/src/modules.rs b/src/tools/rustfmt/src/modules.rs index ded34d9032..b1f229d9da 100644 --- a/src/tools/rustfmt/src/modules.rs +++ b/src/tools/rustfmt/src/modules.rs @@ -16,7 +16,7 @@ use crate::syntux::parser::{ Directory, DirectoryOwnership, ModError, ModulePathSuccess, Parser, ParserError, }; use crate::syntux::session::ParseSess; -use crate::utils::contains_skip; +use crate::utils::{contains_skip, mk_sp}; mod visitor; @@ -135,10 +135,12 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { self.visit_mod_from_ast(&krate.items)?; } + let snippet_provider = self.parse_sess.snippet_provider(krate.span); + self.file_map.insert( root_filename, Module::new( - krate.span, + mk_sp(snippet_provider.start_pos(), snippet_provider.end_pos()), None, Cow::Borrowed(&krate.items), Cow::Borrowed(&krate.attrs), @@ -197,7 +199,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { /// Visit modules from AST. fn visit_mod_from_ast( &mut self, - items: &'ast Vec<rustc_ast::ptr::P<ast::Item>>, + items: &'ast [rustc_ast::ptr::P<ast::Item>], ) -> Result<(), ModuleResolutionError> { for item in items { if is_cfg_if(item) { @@ -290,7 +292,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { }; self.visit_sub_mod_after_directory_update(sub_mod, Some(directory)) } - SubModKind::Internal(ref item) => { + SubModKind::Internal(item) => { self.push_inline_mod_directory(item.ident, &item.attrs); self.visit_sub_mod_after_directory_update(sub_mod, None) } @@ -317,9 +319,11 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { } match (sub_mod.ast_mod_kind, sub_mod.items) { (Some(Cow::Borrowed(ast::ModKind::Loaded(items, _, _))), _) => { - self.visit_mod_from_ast(&items) + self.visit_mod_from_ast(items) + } + (Some(Cow::Owned(ast::ModKind::Loaded(items, _, _))), _) | (_, Cow::Owned(items)) => { + self.visit_mod_outside_ast(items) } - (Some(Cow::Owned(..)), Cow::Owned(items)) => self.visit_mod_outside_ast(items), (_, _) => Ok(()), } } diff --git a/src/tools/rustfmt/src/overflow.rs b/src/tools/rustfmt/src/overflow.rs index e32213467a..3475f5c378 100644 --- a/src/tools/rustfmt/src/overflow.rs +++ b/src/tools/rustfmt/src/overflow.rs @@ -77,6 +77,7 @@ pub(crate) enum OverflowableItem<'a> { FieldDef(&'a ast::FieldDef), TuplePatField(&'a TuplePatField<'a>), Ty(&'a ast::Ty), + Pat(&'a ast::Pat), } impl<'a> Rewrite for OverflowableItem<'a> { @@ -116,6 +117,7 @@ impl<'a> OverflowableItem<'a> { OverflowableItem::FieldDef(sf) => f(*sf), OverflowableItem::TuplePatField(pat) => f(*pat), OverflowableItem::Ty(ty) => f(*ty), + OverflowableItem::Pat(pat) => f(*pat), } } @@ -232,7 +234,7 @@ macro_rules! impl_into_overflowable_item_for_rustfmt_types { } } -impl_into_overflowable_item_for_ast_node!(Expr, GenericParam, NestedMetaItem, FieldDef, Ty); +impl_into_overflowable_item_for_ast_node!(Expr, GenericParam, NestedMetaItem, FieldDef, Ty, Pat); impl_into_overflowable_item_for_rustfmt_types!([MacroArg], [SegmentParam, TuplePatField]); pub(crate) fn into_overflowable_list<'a, T>( @@ -392,7 +394,7 @@ impl<'a> Context<'a> { ) -> Option<String> { let last_item = self.last_item()?; let rewrite = match last_item { - OverflowableItem::Expr(ref expr) => { + OverflowableItem::Expr(expr) => { match expr.kind { // When overflowing the closure which consists of a single control flow // expression, force to use block if its condition uses multi line. diff --git a/src/tools/rustfmt/src/pairs.rs b/src/tools/rustfmt/src/pairs.rs index 0f3d5e8f87..d1c75126ea 100644 --- a/src/tools/rustfmt/src/pairs.rs +++ b/src/tools/rustfmt/src/pairs.rs @@ -55,11 +55,11 @@ fn rewrite_pairs_one_line<T: Rewrite>( for ((_, rewrite), s) in list.list.iter().zip(list.separators.iter()) { if let Some(rewrite) = rewrite { - if !is_single_line(&rewrite) || result.len() > shape.width { + if !is_single_line(rewrite) || result.len() > shape.width { return None; } - result.push_str(&rewrite); + result.push_str(rewrite); result.push(' '); result.push_str(s); result.push(' '); @@ -94,18 +94,18 @@ fn rewrite_pairs_multiline<T: Rewrite>( shape: Shape, context: &RewriteContext<'_>, ) -> Option<String> { - let rhs_offset = shape.rhs_overhead(&context.config); + let rhs_offset = shape.rhs_overhead(context.config); let nested_shape = (match context.config.indent_style() { IndentStyle::Visual => shape.visual_indent(0), IndentStyle::Block => shape.block_indent(context.config.tab_spaces()), }) - .with_max_width(&context.config) + .with_max_width(context.config) .sub_width(rhs_offset)?; let indent_str = nested_shape.indent.to_string_with_newline(context.config); let mut result = String::new(); - result.push_str(&list.list[0].1.as_ref()?); + result.push_str(list.list[0].1.as_ref()?); for ((e, default_rw), s) in list.list[1..].iter().zip(list.separators.iter()) { // The following test checks if we should keep two subexprs on the same @@ -144,7 +144,7 @@ fn rewrite_pairs_multiline<T: Rewrite>( } } - result.push_str(&default_rw.as_ref()?); + result.push_str(default_rw.as_ref()?); } Some(result) } @@ -264,12 +264,12 @@ impl FlattenPair for ast::Expr { return node.rewrite(context, shape); } let nested_overhead = sep + 1; - let rhs_offset = shape.rhs_overhead(&context.config); + let rhs_offset = shape.rhs_overhead(context.config); let nested_shape = (match context.config.indent_style() { IndentStyle::Visual => shape.visual_indent(0), IndentStyle::Block => shape.block_indent(context.config.tab_spaces()), }) - .with_max_width(&context.config) + .with_max_width(context.config) .sub_width(rhs_offset)?; let default_shape = match context.config.binop_separator() { SeparatorPlace::Back => nested_shape.sub_width(nested_overhead)?, diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs index 0501e76d27..a80d63201f 100644 --- a/src/tools/rustfmt/src/patterns.rs +++ b/src/tools/rustfmt/src/patterns.rs @@ -4,6 +4,7 @@ use rustc_span::{BytePos, Span}; use crate::comment::{combine_strs_with_missing_comments, FindUncommented}; use crate::config::lists::*; +use crate::config::Version; use crate::expr::{can_be_overflowed_expr, rewrite_unary_prefix, wrap_struct_field}; use crate::lists::{ definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, @@ -226,12 +227,13 @@ impl Rewrite for Pat { PatKind::Path(ref q_self, ref path) => { rewrite_path(context, PathContext::Expr, q_self.as_ref(), path, shape) } - PatKind::TupleStruct(_, ref path, ref pat_vec) => { - let path_str = rewrite_path(context, PathContext::Expr, None, path, shape)?; + PatKind::TupleStruct(ref q_self, ref path, ref pat_vec) => { + let path_str = + rewrite_path(context, PathContext::Expr, q_self.as_ref(), path, shape)?; rewrite_tuple_pat(pat_vec, Some(path_str), self.span, context, shape) } PatKind::Lit(ref expr) => expr.rewrite(context, shape), - PatKind::Slice(ref slice_pat) => { + PatKind::Slice(ref slice_pat) if context.config.version() == Version::One => { let rw: Vec<String> = slice_pat .iter() .map(|p| { @@ -244,8 +246,17 @@ impl Rewrite for Pat { .collect(); Some(format!("[{}]", rw.join(", "))) } - PatKind::Struct(_, ref path, ref fields, ellipsis) => { - rewrite_struct_pat(path, fields, ellipsis, self.span, context, shape) + PatKind::Slice(ref slice_pat) => overflow::rewrite_with_square_brackets( + context, + "", + slice_pat.iter(), + shape, + self.span, + None, + None, + ), + PatKind::Struct(ref qself, ref path, ref fields, ellipsis) => { + rewrite_struct_pat(qself, path, fields, ellipsis, self.span, context, shape) } PatKind::MacCall(ref mac) => { rewrite_macro(mac, None, context, shape, MacroPosition::Pat) @@ -258,6 +269,7 @@ impl Rewrite for Pat { } fn rewrite_struct_pat( + qself: &Option<ast::QSelf>, path: &ast::Path, fields: &[ast::PatField], ellipsis: bool, @@ -267,7 +279,7 @@ fn rewrite_struct_pat( ) -> Option<String> { // 2 = ` {` let path_shape = shape.sub_width(2)?; - let path_str = rewrite_path(context, PathContext::Expr, None, path, path_shape)?; + let path_str = rewrite_path(context, PathContext::Expr, qself.as_ref(), path, path_shape)?; if fields.is_empty() && !ellipsis { return Some(format!("{} {{}}", path_str)); @@ -444,11 +456,11 @@ fn rewrite_tuple_pat( context: &RewriteContext<'_>, shape: Shape, ) -> Option<String> { - let mut pat_vec: Vec<_> = pats.iter().map(|x| TuplePatField::Pat(x)).collect(); - - if pat_vec.is_empty() { + if pats.is_empty() { return Some(format!("{}()", path_str.unwrap_or_default())); } + let mut pat_vec: Vec<_> = pats.iter().map(TuplePatField::Pat).collect(); + let wildcard_suffix_len = count_wildcard_suffix_len(context, &pat_vec, span, shape); let (pat_vec, span) = if context.config.condense_wildcard_suffixes() && wildcard_suffix_len >= 2 { @@ -470,7 +482,7 @@ fn rewrite_tuple_pat( let path_str = path_str.unwrap_or_default(); overflow::rewrite_with_parens( - &context, + context, &path_str, pat_vec.iter(), shape, diff --git a/src/tools/rustfmt/src/reorder.rs b/src/tools/rustfmt/src/reorder.rs index ac65ff2c10..0732c8ee70 100644 --- a/src/tools/rustfmt/src/reorder.rs +++ b/src/tools/rustfmt/src/reorder.rs @@ -113,11 +113,14 @@ fn rewrite_reorderable_or_regroupable_items( merge_use_trees(normalized_items, SharedPrefix::Module) } ImportGranularity::Item => flatten_use_trees(normalized_items), + ImportGranularity::One => merge_use_trees(normalized_items, SharedPrefix::One), ImportGranularity::Preserve => normalized_items, }; let mut regrouped_items = match context.config.group_imports() { - GroupImportsTactic::Preserve => vec![normalized_items], + GroupImportsTactic::Preserve | GroupImportsTactic::One => { + vec![normalized_items] + } GroupImportsTactic::StdExternalCrate => group_imports(normalized_items), }; diff --git a/src/tools/rustfmt/src/spanned.rs b/src/tools/rustfmt/src/spanned.rs index 7e3786b7cd..8e6c75a374 100644 --- a/src/tools/rustfmt/src/spanned.rs +++ b/src/tools/rustfmt/src/spanned.rs @@ -104,7 +104,7 @@ impl Spanned for ast::Arm { impl Spanned for ast::Param { fn span(&self) -> Span { if crate::items::is_named_param(self) { - mk_sp(self.pat.span.lo(), self.ty.span.hi()) + mk_sp(crate::items::span_lo_for_param(self), self.ty.span.hi()) } else { self.ty.span } diff --git a/src/tools/rustfmt/src/syntux/parser.rs b/src/tools/rustfmt/src/syntux/parser.rs index b5fe4335dd..d1bb2f8000 100644 --- a/src/tools/rustfmt/src/syntux/parser.rs +++ b/src/tools/rustfmt/src/syntux/parser.rs @@ -112,7 +112,7 @@ impl<'a> Parser<'a> { span: Span, ) -> 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)); + let mut parser = new_parser_from_file(sess.inner(), path, Some(span)); match parser.parse_mod(&TokenKind::Eof) { Ok(result) => Some(result), Err(mut e) => { @@ -125,18 +125,12 @@ impl<'a> Parser<'a> { } })); match result { - Ok(Some(m)) => { - if !sess.has_errors() { - return Ok(m); - } - - if sess.can_reset_errors() { - sess.reset_errors(); - return Ok(m); - } - Err(ParserError::ParseError) + Ok(Some(m)) if !sess.has_errors() => Ok(m), + Ok(Some(m)) if sess.can_reset_errors() => { + sess.reset_errors(); + Ok(m) } - Ok(None) => Err(ParserError::ParseError), + Ok(_) => Err(ParserError::ParseError), Err(..) if path.exists() => Err(ParserError::ParseError), Err(_) => Err(ParserError::ParsePanicError), } diff --git a/src/tools/rustfmt/src/syntux/session.rs b/src/tools/rustfmt/src/syntux/session.rs index 2965b0928a..cdb4893d44 100644 --- a/src/tools/rustfmt/src/syntux/session.rs +++ b/src/tools/rustfmt/src/syntux/session.rs @@ -164,7 +164,7 @@ impl ParseSess { } pub(crate) fn ignore_file(&self, path: &FileName) -> bool { - self.ignore_path_set.as_ref().is_match(&path) + self.ignore_path_set.as_ref().is_match(path) } pub(crate) fn set_silent_emitter(&mut self) { @@ -175,6 +175,12 @@ impl ParseSess { self.parse_sess.source_map().span_to_filename(span).into() } + pub(crate) fn span_to_file_contents(&self, span: Span) -> Lrc<rustc_span::SourceFile> { + self.parse_sess + .source_map() + .lookup_source_file(span.data().lo) + } + pub(crate) fn span_to_first_line_string(&self, span: Span) -> String { let file_lines = self.parse_sess.source_map().span_to_lines(span).ok(); diff --git a/src/tools/rustfmt/src/test/mod.rs b/src/tools/rustfmt/src/test/mod.rs index cb52346a13..f7ae8c6b5b 100644 --- a/src/tools/rustfmt/src/test/mod.rs +++ b/src/tools/rustfmt/src/test/mod.rs @@ -469,11 +469,6 @@ fn stdin_works_with_modified_lines() { #[test] fn stdin_disable_all_formatting_test() { init_log(); - match option_env!("CFG_RELEASE_CHANNEL") { - None | Some("nightly") => {} - // These tests require nightly. - _ => return, - } let input = String::from("fn main() { println!(\"This should not be formatted.\"); }"); let mut child = Command::new(rustfmt().to_str().unwrap()) .stdin(Stdio::piped()) @@ -495,6 +490,24 @@ fn stdin_disable_all_formatting_test() { assert_eq!(input, String::from_utf8(output.stdout).unwrap()); } +#[test] +fn stdin_generated_files_issue_5172() { + init_log(); + let input = Input::Text("//@generated\nfn main() {}".to_owned()); + let mut config = Config::default(); + config.set().emit_mode(EmitMode::Stdout); + config.set().format_generated_files(false); + config.set().newline_style(NewlineStyle::Unix); + let mut buf: Vec<u8> = vec![]; + { + let mut session = Session::new(config, Some(&mut buf)); + session.format(input).unwrap(); + assert!(session.has_no_errors()); + } + // N.B. this should be changed once `format_generated_files` is supported with stdin + assert_eq!(buf, "stdin:\n\n//@generated\nfn main() {}\n".as_bytes()); +} + #[test] fn format_lines_errors_are_reported() { init_log(); @@ -540,9 +553,9 @@ fn check_files(files: Vec<PathBuf>, opt_config: &Option<PathBuf>) -> (Vec<Format debug!("Testing '{}'...", file_name.display()); - match idempotent_check(&file_name, &opt_config) { + match idempotent_check(&file_name, opt_config) { Ok(ref report) if report.has_warnings() => { - print!("{}", FormatReportFormatterBuilder::new(&report).build()); + print!("{}", FormatReportFormatterBuilder::new(report).build()); fails += 1; } Ok(report) => reports.push(report), @@ -694,7 +707,7 @@ fn read_significant_comments(file_name: &Path) -> HashMap<String, String> { reader .lines() .map(|line| line.expect("failed getting line")) - .take_while(|line| line_regex.is_match(line)) + .filter(|line| line_regex.is_match(line)) .filter_map(|line| { regex.captures_iter(&line).next().map(|capture| { ( diff --git a/src/tools/rustfmt/src/test/mod_resolver.rs b/src/tools/rustfmt/src/test/mod_resolver.rs index e0b55e3efb..ae4a0d0fcc 100644 --- a/src/tools/rustfmt/src/test/mod_resolver.rs +++ b/src/tools/rustfmt/src/test/mod_resolver.rs @@ -5,21 +5,39 @@ use super::read_config; use crate::{FileName, Input, Session}; -#[test] -fn nested_out_of_line_mods_loaded() { - // See also https://github.com/rust-lang/rustfmt/issues/4874 - let filename = "tests/mod-resolver/issue-4874/main.rs"; - let input_file = PathBuf::from(filename); +fn verify_mod_resolution(input_file_name: &str, exp_misformatted_files: &[&str]) { + let input_file = PathBuf::from(input_file_name); let config = read_config(&input_file); let mut session = Session::<io::Stdout>::new(config, None); let report = session - .format(Input::File(filename.into())) + .format(Input::File(input_file_name.into())) .expect("Should not have had any execution errors"); let errors_by_file = &report.internal.borrow().0; - assert!(errors_by_file.contains_key(&FileName::Real(PathBuf::from( - "tests/mod-resolver/issue-4874/bar/baz.rs", - )))); - assert!(errors_by_file.contains_key(&FileName::Real(PathBuf::from( - "tests/mod-resolver/issue-4874/foo/qux.rs", - )))); + for exp_file in exp_misformatted_files { + assert!(errors_by_file.contains_key(&FileName::Real(PathBuf::from(exp_file)))); + } +} + +#[test] +fn nested_out_of_line_mods_loaded() { + // See also https://github.com/rust-lang/rustfmt/issues/4874 + verify_mod_resolution( + "tests/mod-resolver/issue-4874/main.rs", + &[ + "tests/mod-resolver/issue-4874/bar/baz.rs", + "tests/mod-resolver/issue-4874/foo/qux.rs", + ], + ); +} + +#[test] +fn out_of_line_nested_inline_within_out_of_line() { + // See also https://github.com/rust-lang/rustfmt/issues/5063 + verify_mod_resolution( + "tests/mod-resolver/issue-5063/main.rs", + &[ + "tests/mod-resolver/issue-5063/foo/bar/baz.rs", + "tests/mod-resolver/issue-5063/foo.rs", + ], + ); } diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index 76bf58e875..9ea90c5e46 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -169,31 +169,38 @@ impl<'a> Rewrite for SegmentParam<'a> { SegmentParam::Const(const_) => const_.rewrite(context, shape), SegmentParam::LifeTime(lt) => lt.rewrite(context, shape), SegmentParam::Type(ty) => ty.rewrite(context, shape), - SegmentParam::Binding(assoc_ty_constraint) => { - let mut result = match assoc_ty_constraint.kind { - ast::AssocTyConstraintKind::Bound { .. } => { - format!("{}: ", rewrite_ident(context, assoc_ty_constraint.ident)) - } - ast::AssocTyConstraintKind::Equality { .. } => { - match context.config.type_punctuation_density() { - TypeDensity::Wide => { - format!("{} = ", rewrite_ident(context, assoc_ty_constraint.ident)) - } - TypeDensity::Compressed => { - format!("{}=", rewrite_ident(context, assoc_ty_constraint.ident)) - } - } - } - }; + SegmentParam::Binding(atc) => atc.rewrite(context, shape), + } + } +} - let budget = shape.width.checked_sub(result.len())?; - let rewrite = assoc_ty_constraint - .kind - .rewrite(context, Shape::legacy(budget, shape.indent + result.len()))?; - result.push_str(&rewrite); - Some(result) - } +impl Rewrite for ast::AssocTyConstraint { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> { + use ast::AssocTyConstraintKind::{Bound, Equality}; + + let mut result = String::with_capacity(128); + result.push_str(rewrite_ident(context, self.ident)); + + if let Some(ref gen_args) = self.gen_args { + let budget = shape.width.checked_sub(result.len())?; + let shape = Shape::legacy(budget, shape.indent + result.len()); + let gen_str = rewrite_generic_args(gen_args, context, shape, gen_args.span())?; + result.push_str(&gen_str); } + + let infix = match (&self.kind, context.config.type_punctuation_density()) { + (Bound { .. }, _) => ": ", + (Equality { .. }, TypeDensity::Wide) => " = ", + (Equality { .. }, TypeDensity::Compressed) => "=", + }; + result.push_str(infix); + + let budget = shape.width.checked_sub(result.len())?; + let shape = Shape::legacy(budget, shape.indent + result.len()); + let rewrite = self.kind.rewrite(context, shape)?; + result.push_str(&rewrite); + + Some(result) } } @@ -235,21 +242,9 @@ fn rewrite_segment( }; if let Some(ref args) = segment.args { + let generics_str = rewrite_generic_args(args, context, shape, mk_sp(*span_lo, span_hi))?; match **args { ast::GenericArgs::AngleBracketed(ref data) if !data.args.is_empty() => { - let param_list = data - .args - .iter() - .map(|x| match x { - ast::AngleBracketedArg::Arg(generic_arg) => { - SegmentParam::from_generic_arg(generic_arg) - } - ast::AngleBracketedArg::Constraint(constraint) => { - SegmentParam::Binding(constraint) - } - }) - .collect::<Vec<_>>(); - // HACK: squeeze out the span between the identifier and the parameters. // The hack is requried so that we don't remove the separator inside macro calls. // This does not work in the presence of comment, hoping that people are @@ -265,33 +260,14 @@ fn rewrite_segment( }; result.push_str(separator); - let generics_str = overflow::rewrite_with_angle_brackets( - context, - "", - param_list.iter(), - shape, - mk_sp(*span_lo, span_hi), - )?; - // Update position of last bracket. *span_lo = context .snippet_provider .span_after(mk_sp(*span_lo, span_hi), "<"); - - result.push_str(&generics_str) - } - ast::GenericArgs::Parenthesized(ref data) => { - result.push_str(&format_function_type( - data.inputs.iter().map(|x| &**x), - &data.output, - false, - data.span, - context, - shape, - )?); } _ => (), } + result.push_str(&generics_str) } Some(result) @@ -484,6 +460,41 @@ impl Rewrite for ast::GenericArg { } } +fn rewrite_generic_args( + gen_args: &ast::GenericArgs, + context: &RewriteContext<'_>, + shape: Shape, + span: Span, +) -> Option<String> { + match gen_args { + ast::GenericArgs::AngleBracketed(ref data) if !data.args.is_empty() => { + let args = data + .args + .iter() + .map(|x| match x { + ast::AngleBracketedArg::Arg(generic_arg) => { + SegmentParam::from_generic_arg(generic_arg) + } + ast::AngleBracketedArg::Constraint(constraint) => { + SegmentParam::Binding(constraint) + } + }) + .collect::<Vec<_>>(); + + overflow::rewrite_with_angle_brackets(context, "", args.iter(), shape, span) + } + ast::GenericArgs::Parenthesized(ref data) => format_function_type( + data.inputs.iter().map(|x| &**x), + &data.output, + false, + data.span, + context, + shape, + ), + _ => Some("".to_owned()), + } +} + fn rewrite_bounded_lifetime( lt: &ast::Lifetime, bounds: &[ast::GenericBound], @@ -566,13 +577,23 @@ impl Rewrite for ast::GenericParam { if let ast::GenericParamKind::Const { ref ty, kw_span: _, - default: _, + default, } = &self.kind { result.push_str("const "); result.push_str(rewrite_ident(context, self.ident)); result.push_str(": "); result.push_str(&ty.rewrite(context, shape)?); + if let Some(default) = default { + let eq_str = match context.config.type_punctuation_density() { + TypeDensity::Compressed => "=", + TypeDensity::Wide => " = ", + }; + result.push_str(eq_str); + let budget = shape.width.checked_sub(result.len())?; + let rewrite = default.rewrite(context, Shape::legacy(budget, shape.indent))?; + result.push_str(&rewrite); + } } else { result.push_str(rewrite_ident(context, self.ident)); } @@ -707,7 +728,7 @@ impl Rewrite for ast::Ty { result = combine_strs_with_missing_comments( context, result.trim_end(), - &mt.ty.rewrite(&context, shape)?, + &mt.ty.rewrite(context, shape)?, before_ty_span, shape, true, @@ -717,7 +738,7 @@ impl Rewrite for ast::Ty { let budget = shape.width.checked_sub(used_width)?; let ty_str = mt .ty - .rewrite(&context, Shape::legacy(budget, shape.indent + used_width))?; + .rewrite(context, Shape::legacy(budget, shape.indent + used_width))?; result.push_str(&ty_str); } diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs index 29e1e070d4..3a8713c5bd 100644 --- a/src/tools/rustfmt/src/utils.rs +++ b/src/tools/rustfmt/src/utils.rs @@ -42,7 +42,7 @@ pub(crate) fn is_same_visibility(a: &Visibility, b: &Visibility) -> bool { ( VisibilityKind::Restricted { path: p, .. }, VisibilityKind::Restricted { path: q, .. }, - ) => pprust::path_to_string(&p) == pprust::path_to_string(&q), + ) => pprust::path_to_string(p) == pprust::path_to_string(q), (VisibilityKind::Public, VisibilityKind::Public) | (VisibilityKind::Inherited, VisibilityKind::Inherited) | ( @@ -689,7 +689,7 @@ mod test { #[test] fn test_remove_trailing_white_spaces() { let s = " r#\"\n test\n \"#"; - assert_eq!(remove_trailing_white_spaces(&s), s); + assert_eq!(remove_trailing_white_spaces(s), s); } #[test] @@ -698,7 +698,7 @@ mod test { let config = Config::default(); let indent = Indent::new(4, 0); assert_eq!( - trim_left_preserve_layout(&s, indent, &config), + trim_left_preserve_layout(s, indent, &config), Some("aaa\n bbb\n ccc".to_string()) ); } diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index 770693d165..527042d098 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -3,7 +3,7 @@ use std::rc::Rc; use rustc_ast::{ast, token::DelimToken, visit, AstLike}; use rustc_data_structures::sync::Lrc; -use rustc_span::{symbol, BytePos, Pos, Span, DUMMY_SP}; +use rustc_span::{symbol, BytePos, Pos, Span}; use crate::attr::*; use crate::comment::{contains_comment, rewrite_comment, CodeCharKind, CommentCodeSlices}; @@ -11,9 +11,8 @@ use crate::config::Version; use crate::config::{BraceStyle, Config}; use crate::coverage::transform_missing_snippet; use crate::items::{ - format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, - rewrite_associated_impl_type, rewrite_extern_crate, rewrite_opaque_impl_type, - rewrite_opaque_type, rewrite_type_alias, FnBraceStyle, FnSig, StaticParts, StructParts, + format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, rewrite_extern_crate, + rewrite_type_alias, FnBraceStyle, FnSig, ItemVisitorKind, StaticParts, StructParts, }; use crate::macros::{macro_style, rewrite_macro, rewrite_macro_def, MacroPosition}; use crate::modules::Module; @@ -164,7 +163,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ); } else { let shape = self.shape(); - let rewrite = self.with_context(|ctx| stmt.rewrite(&ctx, shape)); + let rewrite = self.with_context(|ctx| stmt.rewrite(ctx, shape)); self.push_rewrite(stmt.span(), rewrite) } } @@ -273,9 +272,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let comment_snippet = self.snippet(span); - let align_to_right = if unindent_comment && contains_comment(&comment_snippet) { + let align_to_right = if unindent_comment && contains_comment(comment_snippet) { let first_lines = comment_snippet.splitn(2, '/').next().unwrap_or(""); - last_line_width(first_lines) > last_line_width(&comment_snippet) + last_line_width(first_lines) > last_line_width(comment_snippet) } else { false }; @@ -439,7 +438,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let filtered_attrs; let mut attrs = &item.attrs; let skip_context_saved = self.skip_context.clone(); - self.skip_context.update_with_attrs(&attrs); + self.skip_context.update_with_attrs(attrs); let should_visit_node_again = match item.kind { // For use/extern crate items, skip rewriting attributes but check for a skip attribute. @@ -488,12 +487,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ast::ItemKind::Use(ref tree) => self.format_import(item, tree), ast::ItemKind::Impl { .. } => { let block_indent = self.block_indent; - let rw = self.with_context(|ctx| format_impl(&ctx, item, block_indent)); + let rw = self.with_context(|ctx| format_impl(ctx, item, block_indent)); self.push_rewrite(item.span, rw); } ast::ItemKind::Trait(..) => { let block_indent = self.block_indent; - let rw = self.with_context(|ctx| format_trait(&ctx, item, block_indent)); + let rw = self.with_context(|ctx| format_trait(ctx, item, block_indent)); self.push_rewrite(item.span, rw); } ast::ItemKind::TraitAlias(ref generics, ref generic_bounds) => { @@ -540,24 +539,22 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.visit_static(&StaticParts::from_item(item)); } ast::ItemKind::Fn(ref fn_kind) => { - let ast::FnKind(defaultness, ref fn_signature, ref generics, ref block) = - **fn_kind; - if let Some(ref body) = block { + let ast::Fn { + defaultness, + ref sig, + ref generics, + ref body, + } = **fn_kind; + if let Some(ref body) = body { let inner_attrs = inner_attributes(&item.attrs); - let fn_ctxt = match fn_signature.header.ext { + let fn_ctxt = match sig.header.ext { ast::Extern::None => visit::FnCtxt::Free, _ => visit::FnCtxt::Foreign, }; self.visit_fn( - visit::FnKind::Fn( - fn_ctxt, - item.ident, - &fn_signature, - &item.vis, - Some(body), - ), + visit::FnKind::Fn(fn_ctxt, item.ident, &sig, &item.vis, Some(body)), generics, - &fn_signature.decl, + &sig.decl, item.span, defaultness, Some(&inner_attrs), @@ -565,45 +562,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } else { let indent = self.block_indent; let rewrite = self.rewrite_required_fn( - indent, - item.ident, - &fn_signature, - generics, - item.span, + indent, item.ident, &sig, &item.vis, generics, item.span, ); self.push_rewrite(item.span, rewrite); } } - ast::ItemKind::TyAlias(ref alias_kind) => { - let ast::TyAliasKind(_, ref generics, ref generic_bounds, ref ty) = - **alias_kind; - match ty { - Some(ty) => { - let rewrite = rewrite_type_alias( - item.ident, - Some(&*ty), - generics, - Some(generic_bounds), - &self.get_context(), - self.block_indent, - &item.vis, - item.span, - ); - self.push_rewrite(item.span, rewrite); - } - None => { - let rewrite = rewrite_opaque_type( - &self.get_context(), - self.block_indent, - item.ident, - generic_bounds, - generics, - &item.vis, - item.span, - ); - self.push_rewrite(item.span, rewrite); - } - } + ast::ItemKind::TyAlias(ref ty_alias) => { + use ItemVisitorKind::Item; + self.visit_ty_alias_kind(ty_alias, &Item(&item), item.span); } ast::ItemKind::GlobalAsm(..) => { let snippet = Some(self.snippet(item.span).to_owned()); @@ -626,126 +592,86 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.skip_context = skip_context_saved; } - pub(crate) fn visit_trait_item(&mut self, ti: &ast::AssocItem) { - skip_out_of_file_lines_range_visitor!(self, ti.span); + fn visit_ty_alias_kind( + &mut self, + ty_kind: &ast::TyAlias, + visitor_kind: &ItemVisitorKind<'_>, + span: Span, + ) { + let rewrite = rewrite_type_alias( + ty_kind, + &self.get_context(), + self.block_indent, + visitor_kind, + span, + ); + self.push_rewrite(span, rewrite); + } - if self.visit_attrs(&ti.attrs, ast::AttrStyle::Outer) { - self.push_skipped_with_span(ti.attrs.as_slice(), ti.span(), ti.span()); + fn visit_assoc_item(&mut self, visitor_kind: &ItemVisitorKind<'_>) { + use ItemVisitorKind::*; + // TODO(calebcartwright): Not sure the skip spans are correct + let (ai, skip_span, assoc_ctxt) = match visitor_kind { + AssocTraitItem(ai) => (*ai, ai.span(), visit::AssocCtxt::Trait), + AssocImplItem(ai) => (*ai, ai.span, visit::AssocCtxt::Impl), + _ => unreachable!(), + }; + skip_out_of_file_lines_range_visitor!(self, ai.span); + + if self.visit_attrs(&ai.attrs, ast::AttrStyle::Outer) { + self.push_skipped_with_span(&ai.attrs.as_slice(), skip_span, skip_span); return; } // TODO(calebcartwright): consider enabling box_patterns feature gate - match ti.kind { - ast::AssocItemKind::Const(..) => self.visit_static(&StaticParts::from_trait_item(ti)), - ast::AssocItemKind::Fn(ref fn_kind) => { - let ast::FnKind(defaultness, ref sig, ref generics, ref block) = **fn_kind; - if let Some(ref body) = block { - let inner_attrs = inner_attributes(&ti.attrs); - let vis = ast::Visibility { - kind: ast::VisibilityKind::Inherited, - span: DUMMY_SP, - tokens: None, - }; - let fn_ctxt = visit::FnCtxt::Assoc(visit::AssocCtxt::Trait); + match (&ai.kind, visitor_kind) { + (ast::AssocItemKind::Const(..), AssocTraitItem(_)) => { + self.visit_static(&StaticParts::from_trait_item(&ai)) + } + (ast::AssocItemKind::Const(..), AssocImplItem(_)) => { + self.visit_static(&StaticParts::from_impl_item(&ai)) + } + (ast::AssocItemKind::Fn(ref fn_kind), _) => { + let ast::Fn { + defaultness, + ref sig, + ref generics, + ref body, + } = **fn_kind; + if let Some(ref body) = body { + let inner_attrs = inner_attributes(&ai.attrs); + let fn_ctxt = visit::FnCtxt::Assoc(assoc_ctxt); self.visit_fn( - visit::FnKind::Fn(fn_ctxt, ti.ident, sig, &vis, Some(body)), + visit::FnKind::Fn(fn_ctxt, ai.ident, sig, &ai.vis, Some(body)), generics, &sig.decl, - ti.span, + ai.span, defaultness, Some(&inner_attrs), ); } else { let indent = self.block_indent; let rewrite = - self.rewrite_required_fn(indent, ti.ident, sig, generics, ti.span); - self.push_rewrite(ti.span, rewrite); + self.rewrite_required_fn(indent, ai.ident, sig, &ai.vis, generics, ai.span); + self.push_rewrite(ai.span, rewrite); } } - ast::AssocItemKind::TyAlias(ref ty_alias_kind) => { - let ast::TyAliasKind(_, ref generics, ref generic_bounds, ref type_default) = - **ty_alias_kind; - let rewrite = rewrite_type_alias( - ti.ident, - type_default.as_ref(), - generics, - Some(generic_bounds), - &self.get_context(), - self.block_indent, - &ti.vis, - ti.span, - ); - self.push_rewrite(ti.span, rewrite); + (ast::AssocItemKind::TyAlias(ref ty_alias), _) => { + self.visit_ty_alias_kind(ty_alias, visitor_kind, ai.span); } - ast::AssocItemKind::MacCall(ref mac) => { - self.visit_mac(mac, Some(ti.ident), MacroPosition::Item); + (ast::AssocItemKind::MacCall(ref mac), _) => { + self.visit_mac(mac, Some(ai.ident), MacroPosition::Item); } + _ => unreachable!(), } } - pub(crate) fn visit_impl_item(&mut self, ii: &ast::AssocItem) { - skip_out_of_file_lines_range_visitor!(self, ii.span); - - if self.visit_attrs(&ii.attrs, ast::AttrStyle::Outer) { - self.push_skipped_with_span(ii.attrs.as_slice(), ii.span, ii.span); - return; - } + pub(crate) fn visit_trait_item(&mut self, ti: &ast::AssocItem) { + self.visit_assoc_item(&ItemVisitorKind::AssocTraitItem(ti)); + } - match ii.kind { - ast::AssocItemKind::Fn(ref fn_kind) => { - let ast::FnKind(defaultness, ref sig, ref generics, ref block) = **fn_kind; - if let Some(ref body) = block { - let inner_attrs = inner_attributes(&ii.attrs); - let fn_ctxt = visit::FnCtxt::Assoc(visit::AssocCtxt::Impl); - self.visit_fn( - visit::FnKind::Fn(fn_ctxt, ii.ident, sig, &ii.vis, Some(body)), - generics, - &sig.decl, - ii.span, - defaultness, - Some(&inner_attrs), - ); - } else { - let indent = self.block_indent; - let rewrite = - self.rewrite_required_fn(indent, ii.ident, sig, generics, ii.span); - self.push_rewrite(ii.span, rewrite); - } - } - ast::AssocItemKind::Const(..) => self.visit_static(&StaticParts::from_impl_item(ii)), - ast::AssocItemKind::TyAlias(ref ty_alias_kind) => { - let ast::TyAliasKind(defaultness, ref generics, _, ref ty) = **ty_alias_kind; - let rewrite_associated = || { - rewrite_associated_impl_type( - ii.ident, - &ii.vis, - defaultness, - ty.as_ref(), - &generics, - &self.get_context(), - self.block_indent, - ii.span, - ) - }; - let rewrite = match ty { - None => rewrite_associated(), - Some(ty) => match ty.kind { - ast::TyKind::ImplTrait(_, ref bounds) => rewrite_opaque_impl_type( - &self.get_context(), - ii.ident, - generics, - bounds, - self.block_indent, - ), - _ => rewrite_associated(), - }, - }; - self.push_rewrite(ii.span, rewrite); - } - ast::AssocItemKind::MacCall(ref mac) => { - self.visit_mac(mac, Some(ii.ident), MacroPosition::Item); - } - } + pub(crate) fn visit_impl_item(&mut self, ii: &ast::AssocItem) { + self.visit_assoc_item(&ItemVisitorKind::AssocImplItem(ii)); } fn visit_mac(&mut self, mac: &ast::MacCall, ident: Option<symbol::Ident>, pos: MacroPosition) { @@ -922,7 +848,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } fn walk_mod_items(&mut self, items: &[rustc_ast::ptr::P<ast::Item>]) { - self.visit_items_with_reordering(&ptr_vec_to_ref_vec(&items)); + self.visit_items_with_reordering(&ptr_vec_to_ref_vec(items)); } fn walk_stmts(&mut self, stmts: &[Stmt<'_>], include_current_empty_semi: bool) { diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/Cargo.toml new file mode 100644 index 0000000000..315364a645 --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "cargo-fmt-test" +version = "0.1.0" +authors = ["calebcartwright"] +edition = "2018" + +[dependencies] +indexmap = "1.0.2" + +[workspace] +members = [ + "dependency-dir-name", +] \ No newline at end of file diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/Cargo.toml new file mode 100644 index 0000000000..4493882bf4 --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "dependency-crate-name" +version = "0.1.0" +authors = ["calebcartwright"] +edition = "2018" + +[dependencies] +subdep-crate-name = { path = "subdep-dir-name" } +indexmap = "1.0.2" +rusty-hook = "0.8.4" \ No newline at end of file diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/src/lib.rs b/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/src/lib.rs new file mode 100644 index 0000000000..e93b18d725 --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/src/lib.rs @@ -0,0 +1,7 @@ +#[cfg(test)] +mod tests { +#[test] +fn it_works() { + assert_eq!(2 + 2, 4); +} +} diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/Cargo.toml new file mode 100644 index 0000000000..7dad09f407 --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "subdep-crate-name" +version = "0.1.0" +authors = ["calebcartwright"] +edition = "2018" + +[dependencies] diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/src/lib.rs b/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/src/lib.rs new file mode 100644 index 0000000000..1c08c1c4fd --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/src/lib.rs @@ -0,0 +1,7 @@ +#[cfg(test)] +mod tests { +#[test] +fn sub_test_that_works() { + assert_eq!(3 + 3, 6); +} + } diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/src/main.rs b/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/src/main.rs new file mode 100644 index 0000000000..f5c339a8dd --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/src/main.rs @@ -0,0 +1,3 @@ +fn main() { +println!("Hello, world!"); +} diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/e/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/e/Cargo.toml new file mode 100644 index 0000000000..eaf1d76f99 --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/e/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "e" +version = "0.1.0" +edition = "2018" +[dependencies] +c = { path = "../ws/c" } + +[workspace] diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/e/src/main.rs b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/e/src/main.rs new file mode 100644 index 0000000000..1c26a3895f --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/e/src/main.rs @@ -0,0 +1 @@ +struct E{ } diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/Cargo.toml new file mode 100644 index 0000000000..202739b613 --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/Cargo.toml @@ -0,0 +1,5 @@ +[workspace] +members = [ + "a", + "b" +] \ No newline at end of file diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/Cargo.toml new file mode 100644 index 0000000000..712a113448 --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "a" +version = "0.1.0" +edition = "2018" +[dependencies] +d = { path = "./d" } diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/Cargo.toml new file mode 100644 index 0000000000..fb0f06fe5f --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "d" +version = "0.1.0" +edition = "2018" +[dependencies] +e = { path = "../../../e" } +f = { path = "f" } diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/Cargo.toml new file mode 100644 index 0000000000..5c4fa56178 --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/Cargo.toml @@ -0,0 +1,4 @@ +[package] +name = "f" +version = "0.1.0" +edition = "2018" diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/src/lib.rs b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/src/lib.rs new file mode 100644 index 0000000000..c655c4d5e1 --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/src/lib.rs @@ -0,0 +1 @@ +struct F{ } \ No newline at end of file diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/src/lib.rs b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/src/lib.rs new file mode 100644 index 0000000000..04e6e4cb94 --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/src/lib.rs @@ -0,0 +1 @@ +struct D{ } \ No newline at end of file diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/src/main.rs b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/src/main.rs new file mode 100644 index 0000000000..04e6e4cb94 --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/src/main.rs @@ -0,0 +1 @@ +struct D{ } \ No newline at end of file diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/b/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/b/Cargo.toml new file mode 100644 index 0000000000..47a24ff4f2 --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/b/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "b" +version = "0.1.0" +edition = "2018" +[dependencies] +c = { path = "../c" } diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/b/src/main.rs b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/b/src/main.rs new file mode 100644 index 0000000000..4833bbc69b --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/b/src/main.rs @@ -0,0 +1 @@ +struct B{ } \ No newline at end of file diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/c/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/c/Cargo.toml new file mode 100644 index 0000000000..49fa6c395e --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/c/Cargo.toml @@ -0,0 +1,4 @@ +[package] +name = "c" +version = "0.1.0" +edition = "2018" diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/c/src/lib.rs b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/c/src/lib.rs new file mode 100644 index 0000000000..1245ac91d6 --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/c/src/lib.rs @@ -0,0 +1 @@ +struct C{ } \ No newline at end of file diff --git a/src/tools/rustfmt/tests/mod-resolver/issue-5063/foo.rs b/src/tools/rustfmt/tests/mod-resolver/issue-5063/foo.rs new file mode 100644 index 0000000000..d56974773f --- /dev/null +++ b/src/tools/rustfmt/tests/mod-resolver/issue-5063/foo.rs @@ -0,0 +1,2 @@ +mod bar { + mod baz;} \ No newline at end of file diff --git a/src/tools/rustfmt/tests/mod-resolver/issue-5063/foo/bar/baz.rs b/src/tools/rustfmt/tests/mod-resolver/issue-5063/foo/bar/baz.rs new file mode 100644 index 0000000000..3519b0ee59 --- /dev/null +++ b/src/tools/rustfmt/tests/mod-resolver/issue-5063/foo/bar/baz.rs @@ -0,0 +1 @@ +fn baz() { } \ No newline at end of file diff --git a/src/tools/rustfmt/tests/mod-resolver/issue-5063/main.rs b/src/tools/rustfmt/tests/mod-resolver/issue-5063/main.rs new file mode 100644 index 0000000000..41c81c7bb4 --- /dev/null +++ b/src/tools/rustfmt/tests/mod-resolver/issue-5063/main.rs @@ -0,0 +1,5 @@ +fn main() { + println!("Hello, world!"); +} + +mod foo; \ No newline at end of file diff --git a/src/tools/rustfmt/tests/source/binop-separator-back/bitwise.rs b/src/tools/rustfmt/tests/source/binop-separator-back/bitwise.rs new file mode 100644 index 0000000000..3804bf3215 --- /dev/null +++ b/src/tools/rustfmt/tests/source/binop-separator-back/bitwise.rs @@ -0,0 +1,14 @@ +// rustfmt-binop_separator: Back + +fn main() { + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ^ abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; + + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ & abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; + + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ | abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; + + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ << abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; + + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ >> abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; + +} diff --git a/src/tools/rustfmt/tests/source/binop-separator-back/comp.rs b/src/tools/rustfmt/tests/source/binop-separator-back/comp.rs new file mode 100644 index 0000000000..50a2712744 --- /dev/null +++ b/src/tools/rustfmt/tests/source/binop-separator-back/comp.rs @@ -0,0 +1,23 @@ +// rustfmt-binop_separator: Back + +fn main() { + if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ < abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ { + // + } + + if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ <= abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ { + // + } + + if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ > abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ { + // + } + + if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ >= abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ { + // + } + + if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ == abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ { + // + } +} diff --git a/src/tools/rustfmt/tests/source/binop-separator-back/logic.rs b/src/tools/rustfmt/tests/source/binop-separator-back/logic.rs new file mode 100644 index 0000000000..8c297e5a67 --- /dev/null +++ b/src/tools/rustfmt/tests/source/binop-separator-back/logic.rs @@ -0,0 +1,7 @@ +// rustfmt-binop_separator: Back + +fn main() { + if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ && abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ || abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ { + // + } +} diff --git a/src/tools/rustfmt/tests/source/binop-separator-back/math.rs b/src/tools/rustfmt/tests/source/binop-separator-back/math.rs new file mode 100644 index 0000000000..3af4aad160 --- /dev/null +++ b/src/tools/rustfmt/tests/source/binop-separator-back/math.rs @@ -0,0 +1,7 @@ +// rustfmt-binop_separator: Back + +fn main() { + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; + + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ * abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ - abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ / abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ * abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ * abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ / abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ / abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; +} diff --git a/src/tools/rustfmt/tests/source/binop-separator-back/patterns.rs b/src/tools/rustfmt/tests/source/binop-separator-back/patterns.rs new file mode 100644 index 0000000000..a8c3b5cdd9 --- /dev/null +++ b/src/tools/rustfmt/tests/source/binop-separator-back/patterns.rs @@ -0,0 +1,9 @@ +// rustfmt-binop_separator: Back + +fn main() { + match val { + ThisIsA::ReallyLongPatternNameToHelpOverflowTheNextValueOntoTheNextLine | ThisIsA::SecondValueSeparatedByAPipe | ThisIsA::ThirdValueSeparatedByAPipe => { + // + } + } +} diff --git a/src/tools/rustfmt/tests/source/binop-separator-back/range.rs b/src/tools/rustfmt/tests/source/binop-separator-back/range.rs new file mode 100644 index 0000000000..bdd3de9922 --- /dev/null +++ b/src/tools/rustfmt/tests/source/binop-separator-back/range.rs @@ -0,0 +1,7 @@ +// rustfmt-binop_separator: Back + +fn main() { + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ..abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; + + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ..=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; +} diff --git a/src/tools/rustfmt/tests/source/configs/format_generated_files/false.rs b/src/tools/rustfmt/tests/source/configs/format_generated_files/false.rs new file mode 100644 index 0000000000..dec1e00d11 --- /dev/null +++ b/src/tools/rustfmt/tests/source/configs/format_generated_files/false.rs @@ -0,0 +1,8 @@ +// @generated +// rustfmt-format_generated_files: false + +fn main() +{ + println!("hello, world") + ; +} diff --git a/src/tools/rustfmt/tests/source/configs/format_generated_files/true.rs b/src/tools/rustfmt/tests/source/configs/format_generated_files/true.rs new file mode 100644 index 0000000000..a25ddc25a6 --- /dev/null +++ b/src/tools/rustfmt/tests/source/configs/format_generated_files/true.rs @@ -0,0 +1,8 @@ +// @generated +// rustfmt-format_generated_files: true + +fn main() +{ + println!("hello, world") + ; +} diff --git a/src/tools/rustfmt/tests/source/configs/group_imports/One-merge_imports.rs b/src/tools/rustfmt/tests/source/configs/group_imports/One-merge_imports.rs new file mode 100644 index 0000000000..157d385790 --- /dev/null +++ b/src/tools/rustfmt/tests/source/configs/group_imports/One-merge_imports.rs @@ -0,0 +1,17 @@ +// rustfmt-group_imports: One +// rustfmt-imports_granularity: Crate +use chrono::Utc; +use super::update::convert_publish_payload; + +use juniper::{FieldError, FieldResult}; +use uuid::Uuid; +use alloc::alloc::Layout; + +use std::sync::Arc; +use alloc::vec::Vec; + +use broker::database::PooledConnection; + +use super::schema::{Context, Payload}; +use core::f32; +use crate::models::Event; diff --git a/src/tools/rustfmt/tests/source/configs/group_imports/One-nested.rs b/src/tools/rustfmt/tests/source/configs/group_imports/One-nested.rs new file mode 100644 index 0000000000..109bd07e1e --- /dev/null +++ b/src/tools/rustfmt/tests/source/configs/group_imports/One-nested.rs @@ -0,0 +1,7 @@ +// rustfmt-group_imports: One +mod test { + use crate::foo::bar; + + use std::path; + use crate::foo::bar2; +} diff --git a/src/tools/rustfmt/tests/source/configs/group_imports/One-no_reorder.rs b/src/tools/rustfmt/tests/source/configs/group_imports/One-no_reorder.rs new file mode 100644 index 0000000000..f82f62c7f5 --- /dev/null +++ b/src/tools/rustfmt/tests/source/configs/group_imports/One-no_reorder.rs @@ -0,0 +1,16 @@ +// rustfmt-group_imports: One +// rustfmt-reorder_imports: false +use chrono::Utc; +use super::update::convert_publish_payload; + +use juniper::{FieldError, FieldResult}; +use uuid::Uuid; +use alloc::alloc::Layout; + +use std::sync::Arc; + +use broker::database::PooledConnection; + +use super::schema::{Context, Payload}; +use core::f32; +use crate::models::Event; diff --git a/src/tools/rustfmt/tests/source/configs/group_imports/One.rs b/src/tools/rustfmt/tests/source/configs/group_imports/One.rs new file mode 100644 index 0000000000..5ab7a95080 --- /dev/null +++ b/src/tools/rustfmt/tests/source/configs/group_imports/One.rs @@ -0,0 +1,15 @@ +// rustfmt-group_imports: One +use chrono::Utc; +use super::update::convert_publish_payload; + +use juniper::{FieldError, FieldResult}; +use uuid::Uuid; +use alloc::alloc::Layout; + +use std::sync::Arc; + +use broker::database::PooledConnection; + +use super::schema::{Context, Payload}; +use core::f32; +use crate::models::Event; diff --git a/src/tools/rustfmt/tests/source/empty-item-single-line-false.rs b/src/tools/rustfmt/tests/source/empty-item-single-line-false.rs new file mode 100644 index 0000000000..20c5bc83b4 --- /dev/null +++ b/src/tools/rustfmt/tests/source/empty-item-single-line-false.rs @@ -0,0 +1,46 @@ +// rustfmt-brace_style: AlwaysNextLine +// rustfmt-empty_item_single_line: false + +fn function() +{ + +} + +struct Struct +{ + +} + +enum Enum +{ + +} + +trait Trait +{ + +} + +impl<T> Trait for T +{ + +} + +trait Trait2<T> +where + T: Copy + Display + Write + Read + FromStr, {} + +trait Trait3<T> +where + T: Something + + SomethingElse + + Sync + + Send + + Display + + Debug + + Copy + + Hash + + Debug + + Display + + Write + + Read, {} diff --git a/src/tools/rustfmt/tests/source/hex_literal_lower.rs b/src/tools/rustfmt/tests/source/hex_literal_lower.rs new file mode 100644 index 0000000000..ce307b3aa5 --- /dev/null +++ b/src/tools/rustfmt/tests/source/hex_literal_lower.rs @@ -0,0 +1,5 @@ +// rustfmt-hex_literal_case: Lower +fn main() { + let h1 = 0xCAFE_5EA7; + let h2 = 0xCAFE_F00Du32; +} diff --git a/src/tools/rustfmt/tests/source/hex_literal_upper.rs b/src/tools/rustfmt/tests/source/hex_literal_upper.rs new file mode 100644 index 0000000000..b1092ad71b --- /dev/null +++ b/src/tools/rustfmt/tests/source/hex_literal_upper.rs @@ -0,0 +1,5 @@ +// rustfmt-hex_literal_case: Upper +fn main() { + let h1 = 0xCaFE_5ea7; + let h2 = 0xCAFE_F00Du32; +} diff --git a/src/tools/rustfmt/tests/source/impls.rs b/src/tools/rustfmt/tests/source/impls.rs index fb8701989f..dcd1f0cd5b 100644 --- a/src/tools/rustfmt/tests/source/impls.rs +++ b/src/tools/rustfmt/tests/source/impls.rs @@ -13,6 +13,14 @@ pub impl Foo for Bar { // Comment 3 } +#[inherent] +impl Visible for Bar { + pub const C: i32; + pub type T; + pub fn f(); + pub fn g() {} +} + pub unsafe impl<'a, 'b, X, Y: Foo<Bar>> !Foo<'a, X> for Bar<'b, Y> where X: Foo<'a, Z> { fn foo() { "hi" } } diff --git a/src/tools/rustfmt/tests/source/imports_granularity_one.rs b/src/tools/rustfmt/tests/source/imports_granularity_one.rs new file mode 100644 index 0000000000..c21707df39 --- /dev/null +++ b/src/tools/rustfmt/tests/source/imports_granularity_one.rs @@ -0,0 +1,60 @@ +// rustfmt-imports_granularity: One + +use b; +use a::ac::{aca, acb}; +use a::{aa::*, ab}; + +use a as x; +use b::ba; +use a::{aa, ab}; + +use a::aa::aaa; +use a::ab::aba as x; +use a::aa::*; + +use a::aa; +use a::ad::ada; +#[cfg(test)] +use a::{ab, ac::aca}; +use b; +#[cfg(test)] +use b::{ + ba, bb, + bc::bca::{bcaa, bcab}, +}; + +pub use a::aa; +pub use a::ae; +use a::{ab, ac, ad}; +use b::ba; +pub use b::{bb, bc::bca}; + +use a::aa::aaa; +use a::ac::{aca, acb}; +use a::{aa::*, ab}; +use b::{ + ba, + bb::{self, bba}, +}; + +use crate::a; +use crate::b::ba; +use c::ca; + +use super::a; +use c::ca; +use super::b::ba; + +use crate::a; +use super::b; +use c::{self, ca}; + +use a::{ + // some comment + aa::{aaa, aab}, + ab, + // another comment + ac::aca, +}; +use b as x; +use a::ad::ada; diff --git a/src/tools/rustfmt/tests/source/issue-3158.rs b/src/tools/rustfmt/tests/source/issue-3158.rs new file mode 100644 index 0000000000..315073db6a --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-3158.rs @@ -0,0 +1,74 @@ +// rustfmt-format_code_in_doc_comments: true + +/// Should format +/// ```rust +/// assert!( false ); +/// ``` +/// +/// Should format +/// ```rust,should_panic +/// assert!( false ); +/// ``` +/// +/// Should format +/// ```rust,should_panic,edition2018 +/// assert!( false ); +/// ``` +/// +/// Should format +/// ```rust , should_panic , edition2018 +/// assert!( false ); +/// ``` +/// +/// Should not format +/// ```ignore +/// assert!( false ); +/// ``` +/// +/// Should not format (not all are rust) +/// ```rust,ignore +/// assert!( false ); +/// ``` +/// +/// Should not format (rust compile_fail) +/// ```compile_fail +/// assert!( false ); +/// ``` +/// +/// Should not format (rust compile_fail) +/// ```rust,compile_fail +/// assert!( false ); +/// ``` +/// +/// Various unspecified ones that should format +/// ``` +/// assert!( false ); +/// ``` +/// +/// ```, +/// assert!( false ); +/// ``` +/// +/// ```,,,,, +/// assert!( false ); +/// ``` +/// +/// ```,,, rust ,, +/// assert!( false ); +/// ``` +/// +/// Should not format +/// ```,,, rust , ignore, +/// assert!( false ); +/// ``` +/// +/// Few empty ones +/// ``` +/// ``` +/// +/// ```rust +/// ``` +/// +/// ```ignore +/// ``` +fn foo() {} diff --git a/src/tools/rustfmt/tests/source/issue-4530.rs b/src/tools/rustfmt/tests/source/issue-4530.rs new file mode 100644 index 0000000000..9d2882abb3 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-4530.rs @@ -0,0 +1,4 @@ +// rustfmt-version: Two +fn main() { + let [aaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, cccccccccccccccccccccccccc, ddddddddddddddddddddddddd] = panic!(); +} diff --git a/src/tools/rustfmt/tests/source/issue-4615/minimum_example.rs b/src/tools/rustfmt/tests/source/issue-4615/minimum_example.rs new file mode 100644 index 0000000000..89af5d1239 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-4615/minimum_example.rs @@ -0,0 +1,4 @@ +info!(//debug + "{}: sending function_code={:04x} data={:04x} crc=0x{:04X} data={:02X?}", + self.name, function_code, data, crc, output_cmd +); diff --git a/src/tools/rustfmt/tests/source/issue-4816/lib.rs b/src/tools/rustfmt/tests/source/issue-4816/lib.rs new file mode 100644 index 0000000000..43d540c4a5 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-4816/lib.rs @@ -0,0 +1,10 @@ +#![feature(const_generics_defaults)] +struct Foo<const N: usize = 1, const N2: usize = 2>; +struct Bar<const N: usize, const N2: usize = { N + +1 }>; +struct Lots<const N1BlahFooUwU: usize = { 10 + 28 + 1872 / 10 * 3 },const N2SecondParamOhmyyy: usize = { N1BlahFooUwU / 2 + 10 * 2 },>; +struct NamesRHard<const N: usize = { 1 + 1 + 1 + 1 + 1 + 1 }>; +struct FooBar< + const LessThan100ButClose: usize = {1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1} +>; +struct FooBarrrrrrrr<const N: usize = {13478234326456456444323871+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+1+1+1 + 1},>; diff --git a/src/tools/rustfmt/tests/source/issue-4926/deeply_nested_struct.rs b/src/tools/rustfmt/tests/source/issue-4926/deeply_nested_struct.rs new file mode 100644 index 0000000000..e55e41bd1a --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-4926/deeply_nested_struct.rs @@ -0,0 +1,35 @@ + +// rustfmt-struct_field_align_threshold: 30 + +struct X { + a: i32, + b: i32, + c: i32, +} + +fn test(x: X) { + let d = { + let e = { + let f = { + let g = { + let h = { + let i = { + let j = { + matches!( + x, + X { a: 1_000, b: 1_000, .. } + ) + }; + j + }; + i + }; + h + }; + g + }; + f + }; + e + }; +} \ No newline at end of file diff --git a/src/tools/rustfmt/tests/source/issue-4926/deeply_nested_struct_with_long_field_names.rs b/src/tools/rustfmt/tests/source/issue-4926/deeply_nested_struct_with_long_field_names.rs new file mode 100644 index 0000000000..516699fa2b --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-4926/deeply_nested_struct_with_long_field_names.rs @@ -0,0 +1,43 @@ +// rustfmt-struct_field_align_threshold: 30 + +struct X { + really_really_long_field_a: i32, + really_really_really_long_field_b: i32, + really_really_really_really_long_field_c: i32, + really_really_really_really_really_long_field_d: i32, + really_really_really_really_really_really_long_field_e: i32, + f: i32, +} + +fn test(x: X) { + let d = { + let e = { + let f = { + let g = { + let h = { + let i = { + let j = { + matches!( + x, + X { + really_really_long_field_a: 10, + really_really_really_long_field_b: 10, + really_really_really_really_long_field_c: 10, + really_really_really_really_really_long_field_d: 10, + really_really_really_really_really_really_long_field_e: 10, .. + } + ) + }; + j + }; + i + }; + h + }; + g + }; + f + }; + e + }; +} diff --git a/src/tools/rustfmt/tests/source/issue-4926/deeply_nested_struct_with_many_fields.rs b/src/tools/rustfmt/tests/source/issue-4926/deeply_nested_struct_with_many_fields.rs new file mode 100644 index 0000000000..38fd6f02cf --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-4926/deeply_nested_struct_with_many_fields.rs @@ -0,0 +1,44 @@ +// rustfmt-struct_field_align_threshold: 30 + +struct X { + a: i32, + b: i32, + c: i32, + d: i32, + e: i32, + f: i32, + g: i32, + h: i32, + i: i32, + j: i32, + k: i32, +} + +fn test(x: X) { + let d = { + let e = { + let f = { + let g = { + let h = { + let i = { + let j = { + matches!( + x, + X { + a: 1_000, b: 1_000, c: 1_000, d: 1_000, e: 1_000, f: 1_000, g: 1_000, h: 1_000, i: 1_000, j: 1_000, .. + } + ) + }; + j + }; + i + }; + h + }; + g + }; + f + }; + e + }; +} diff --git a/src/tools/rustfmt/tests/source/issue-4926/enum_struct_field.rs b/src/tools/rustfmt/tests/source/issue-4926/enum_struct_field.rs new file mode 100644 index 0000000000..336378537d --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-4926/enum_struct_field.rs @@ -0,0 +1,35 @@ +// rustfmt-struct_field_align_threshold: 30 +// rustfmt-enum_discrim_align_threshold: 30 +// rustfmt-imports_layout: HorizontalVertical + +#[derive(Default)] +struct InnerStructA { bbbbbbbbb: i32, cccccccc: i32 } + +enum SomeEnumNamedD { + E(InnerStructA), + F { + ggggggggggggggggggggggggg: bool, + h: bool, + } +} + +impl SomeEnumNamedD { + fn f_variant() -> Self { + Self::F { ggggggggggggggggggggggggg: true, h: true } + } +} + +fn main() { + let kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk = SomeEnumNamedD::f_variant(); + let something_we_care_about = matches!( + kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk, + SomeEnumNamedD::F { + ggggggggggggggggggggggggg: true, + .. + } + ); + + if something_we_care_about { + println!("Yup it happened"); + } +} diff --git a/src/tools/rustfmt/tests/source/issue-4926/minimum_example.rs b/src/tools/rustfmt/tests/source/issue-4926/minimum_example.rs new file mode 100644 index 0000000000..2c3045dea4 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-4926/minimum_example.rs @@ -0,0 +1,10 @@ +// rustfmt-struct_field_align_threshold: 30 + +struct X { a: i32, b: i32 } + +fn test(x: X) { + let y = matches!(x, X { + a: 1, + .. + }); +} diff --git a/src/tools/rustfmt/tests/source/issue-4926/struct_with_long_field_names.rs b/src/tools/rustfmt/tests/source/issue-4926/struct_with_long_field_names.rs new file mode 100644 index 0000000000..b8a37f0714 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-4926/struct_with_long_field_names.rs @@ -0,0 +1,21 @@ +// rustfmt-struct_field_align_threshold: 30 + +struct X { + really_really_long_field_a: i32, + really_really_really_long_field_b: i32, + really_really_really_really_long_field_c: i32, + really_really_really_really_really_long_field_d: i32, + really_really_really_really_really_really_long_field_e: i32, + f: i32, +} + +fn test(x: X) { + let y = matches!(x, X { + really_really_long_field_a: 10, + really_really_really_long_field_b: 10, + really_really_really_really_long_field_c: 10, + really_really_really_really_really_long_field_d: 10, + really_really_really_really_really_really_long_field_e: 10, + .. + }); +} diff --git a/src/tools/rustfmt/tests/source/issue-4926/struct_with_many_fields.rs b/src/tools/rustfmt/tests/source/issue-4926/struct_with_many_fields.rs new file mode 100644 index 0000000000..4adfd3b306 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-4926/struct_with_many_fields.rs @@ -0,0 +1,21 @@ +// rustfmt-struct_field_align_threshold: 30 + +struct X { + a: i32, + b: i32, + c: i32, + d: i32, + e: i32, + f: i32, + g: i32, + h: i32, + i: i32, + j: i32, + k: i32, +} + +fn test(x: X) { + let y = matches!(x, X { + a: 1_000, b: 1_000, c: 1_000, d: 1_000, e: 1_000, f: 1_000, g: 1_000, h: 1_000, i: 1_000, j: 1_000, .. + }); +} \ No newline at end of file diff --git a/src/tools/rustfmt/tests/source/issue-4984/minimum_example.rs b/src/tools/rustfmt/tests/source/issue-4984/minimum_example.rs new file mode 100644 index 0000000000..677f873771 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-4984/minimum_example.rs @@ -0,0 +1,2 @@ +#[derive(/*Debug, */Clone)] +struct Foo; diff --git a/src/tools/rustfmt/tests/source/issue-4984/multi_line_derive.rs b/src/tools/rustfmt/tests/source/issue-4984/multi_line_derive.rs new file mode 100644 index 0000000000..73921dd173 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-4984/multi_line_derive.rs @@ -0,0 +1,20 @@ +#[derive( +/* ---------- Some really important comment that just had to go inside the derive --------- */ +Debug, Clone, Eq, PartialEq, +)] +struct Foo { + a: i32, + b: T, +} + +#[derive( +/* + Some really important comment that just had to go inside the derive. + Also had to be put over multiple lines +*/ +Debug, Clone, Eq, PartialEq, +)] +struct Bar { + a: i32, + b: T, +} diff --git a/src/tools/rustfmt/tests/source/issue-4984/multiple_comments_within.rs b/src/tools/rustfmt/tests/source/issue-4984/multiple_comments_within.rs new file mode 100644 index 0000000000..eb474a723d --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-4984/multiple_comments_within.rs @@ -0,0 +1,8 @@ +#[derive( +/* ---------- Some really important comment that just had to go inside the derive --------- */ +Debug, Clone,/* Another comment */Eq, PartialEq, +)] +struct Foo { + a: i32, + b: T, +} diff --git a/src/tools/rustfmt/tests/source/issue-5011.rs b/src/tools/rustfmt/tests/source/issue-5011.rs new file mode 100644 index 0000000000..b48292164e --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-5011.rs @@ -0,0 +1,12 @@ +pub(crate) struct ASlash( + // hello + i32 +); + +pub(crate) struct AStar( + /* hello */ + i32 +); + +pub(crate) struct BStar(/* hello */ i32); + diff --git a/src/tools/rustfmt/tests/source/issue_4032.rs b/src/tools/rustfmt/tests/source/issue_4032.rs new file mode 100644 index 0000000000..11ded074c3 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue_4032.rs @@ -0,0 +1,4 @@ +fn a1(#[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] a: u8) {} +fn b1(#[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] bb: u8) {} +fn a2(#[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] a: u8) {} +fn b2(#[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] bb: u8) {} diff --git a/src/tools/rustfmt/tests/source/issue_4257.rs b/src/tools/rustfmt/tests/source/issue_4257.rs new file mode 100644 index 0000000000..2b887fadb6 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue_4257.rs @@ -0,0 +1,13 @@ +#![feature(generic_associated_types)] +#![allow(incomplete_features)] + +trait Trait<T> { + type Type<'a> where T: 'a; + fn foo(x: &T) -> Self::Type<'_>; +} +impl<T> Trait<T> for () { + type Type<'a> where T: 'a = &'a T; + fn foo(x: &T) -> Self::Type<'_> { + x + } +} diff --git a/src/tools/rustfmt/tests/source/issue_4322.rs b/src/tools/rustfmt/tests/source/issue_4322.rs new file mode 100644 index 0000000000..b28cc7cdd1 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue_4322.rs @@ -0,0 +1,3 @@ +trait Bar { + type X<'a> where Self: 'a; +} diff --git a/src/tools/rustfmt/tests/source/issue_4579.rs b/src/tools/rustfmt/tests/source/issue_4579.rs new file mode 100644 index 0000000000..73f345233b --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue_4579.rs @@ -0,0 +1,15 @@ +// rustfmt-hard_tabs: true + +#[macro_export] +macro_rules! main { + () => { + #[spirv(fragment)] + pub fn main_fs( + mut out_color: ::spirv_std::storage_class::Output<Vec4>, + #[spirv(descriptor_set = 1)]iChannelResolution: ::spirv_std::storage_class::UniformConstant< + [::spirv_std::glam::Vec3A; 4], + >, + ) { + } + }; +} diff --git a/src/tools/rustfmt/tests/source/issue_4911.rs b/src/tools/rustfmt/tests/source/issue_4911.rs new file mode 100644 index 0000000000..21ef6c6c49 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue_4911.rs @@ -0,0 +1,6 @@ +#![feature(generic_associated_types)] +#![feature(min_type_alias_impl_trait)] + +impl SomeTrait for SomeType { + type SomeGAT<'a> where Self: 'a = impl SomeOtherTrait; +} \ No newline at end of file diff --git a/src/tools/rustfmt/tests/source/issue_4943.rs b/src/tools/rustfmt/tests/source/issue_4943.rs new file mode 100644 index 0000000000..0793b7b4fe --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue_4943.rs @@ -0,0 +1,9 @@ +#![feature(generic_associated_types)] + +impl SomeStruct { + fn process<T>(v: T) -> <Self as GAT>::R<T> + where Self: GAT<R<T> = T> + { + SomeStruct::do_something(v) + } +} diff --git a/src/tools/rustfmt/tests/source/issue_4954.rs b/src/tools/rustfmt/tests/source/issue_4954.rs new file mode 100644 index 0000000000..8011c601b6 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue_4954.rs @@ -0,0 +1,5 @@ +trait Foo { + type Arg<'a>; +} + +struct Bar<T>(T) where for<'a> T: Foo<Arg<'a> = ()>; diff --git a/src/tools/rustfmt/tests/source/issue_4963.rs b/src/tools/rustfmt/tests/source/issue_4963.rs new file mode 100644 index 0000000000..32e1f6cd41 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue_4963.rs @@ -0,0 +1,5 @@ +mod test { + extern "C" {fn test();} +} + +extern "C" {fn test();} \ No newline at end of file diff --git a/src/tools/rustfmt/tests/source/item-brace-style-always-next-line.rs b/src/tools/rustfmt/tests/source/item-brace-style-always-next-line.rs index 38094d67a7..0fb6405120 100644 --- a/src/tools/rustfmt/tests/source/item-brace-style-always-next-line.rs +++ b/src/tools/rustfmt/tests/source/item-brace-style-always-next-line.rs @@ -27,3 +27,38 @@ mod M { struct D<T> where T: Copy {} } + + +fn function() +{ + +} + +trait Trait +{ + +} + +impl<T> Trait for T +{ + +} + +trait Trait2<T> +where + T: Copy + Display + Write + Read + FromStr, {} + +trait Trait3<T> +where + T: Something + + SomethingElse + + Sync + + Send + + Display + + Debug + + Copy + + Hash + + Debug + + Display + + Write + + Read, {} diff --git a/src/tools/rustfmt/tests/source/match-block-trailing-comma.rs b/src/tools/rustfmt/tests/source/match-block-trailing-comma.rs index e9daac13bf..baa05b79c1 100644 --- a/src/tools/rustfmt/tests/source/match-block-trailing-comma.rs +++ b/src/tools/rustfmt/tests/source/match-block-trailing-comma.rs @@ -8,6 +8,14 @@ fn foo() { "line1"; "line2" } + ThisIsA::Guard if true => { + "line1"; + "line2" + } + ThisIsA::ReallyLongPattern(ThatWillForce::TheGuard, ToWrapOnto::TheFollowingLine) if true => { + "line1"; + "line2" + } b => (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), } diff --git a/src/tools/rustfmt/tests/source/trait.rs b/src/tools/rustfmt/tests/source/trait.rs index 80ee0188a6..b6db9e1590 100644 --- a/src/tools/rustfmt/tests/source/trait.rs +++ b/src/tools/rustfmt/tests/source/trait.rs @@ -174,3 +174,10 @@ Send + DDDDDDDD + DDDDDDDDD + EEEEEEE; + +trait Visible { + pub const C: i32; + pub type T; + pub fn f(); + pub fn g() {} +} diff --git a/src/tools/rustfmt/tests/target/binop-separator-back/bitwise.rs b/src/tools/rustfmt/tests/target/binop-separator-back/bitwise.rs new file mode 100644 index 0000000000..ce32c05ef7 --- /dev/null +++ b/src/tools/rustfmt/tests/target/binop-separator-back/bitwise.rs @@ -0,0 +1,18 @@ +// rustfmt-binop_separator: Back + +fn main() { + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ^ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; + + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ & + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; + + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ | + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; + + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ << + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; + + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ >> + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; +} diff --git a/src/tools/rustfmt/tests/target/binop-separator-back/comp.rs b/src/tools/rustfmt/tests/target/binop-separator-back/comp.rs new file mode 100644 index 0000000000..efd837bcfe --- /dev/null +++ b/src/tools/rustfmt/tests/target/binop-separator-back/comp.rs @@ -0,0 +1,33 @@ +// rustfmt-binop_separator: Back + +fn main() { + if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ < + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + { + // + } + + if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ <= + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + { + // + } + + if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ > + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + { + // + } + + if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ >= + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + { + // + } + + if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ == + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + { + // + } +} diff --git a/src/tools/rustfmt/tests/target/binop-separator-back/logic.rs b/src/tools/rustfmt/tests/target/binop-separator-back/logic.rs new file mode 100644 index 0000000000..5f69fd5f55 --- /dev/null +++ b/src/tools/rustfmt/tests/target/binop-separator-back/logic.rs @@ -0,0 +1,10 @@ +// rustfmt-binop_separator: Back + +fn main() { + if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ && + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ || + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + { + // + } +} diff --git a/src/tools/rustfmt/tests/target/binop-separator-back/math.rs b/src/tools/rustfmt/tests/target/binop-separator-back/math.rs new file mode 100644 index 0000000000..7a3f27e733 --- /dev/null +++ b/src/tools/rustfmt/tests/target/binop-separator-back/math.rs @@ -0,0 +1,23 @@ +// rustfmt-binop_separator: Back + +fn main() { + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; + + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ * + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ - + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ / + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ * + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ * + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ / + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ / + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; +} diff --git a/src/tools/rustfmt/tests/target/binop-separator-back/patterns.rs b/src/tools/rustfmt/tests/target/binop-separator-back/patterns.rs new file mode 100644 index 0000000000..2e59713526 --- /dev/null +++ b/src/tools/rustfmt/tests/target/binop-separator-back/patterns.rs @@ -0,0 +1,11 @@ +// rustfmt-binop_separator: Back + +fn main() { + match val { + ThisIsA::ReallyLongPatternNameToHelpOverflowTheNextValueOntoTheNextLine | + ThisIsA::SecondValueSeparatedByAPipe | + ThisIsA::ThirdValueSeparatedByAPipe => { + // + } + } +} diff --git a/src/tools/rustfmt/tests/target/binop-separator-back/range.rs b/src/tools/rustfmt/tests/target/binop-separator-back/range.rs new file mode 100644 index 0000000000..19e5a81cd9 --- /dev/null +++ b/src/tools/rustfmt/tests/target/binop-separator-back/range.rs @@ -0,0 +1,9 @@ +// rustfmt-binop_separator: Back + +fn main() { + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.. + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; + + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ..= + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; +} diff --git a/src/tools/rustfmt/tests/target/configs/format_generated_files/false.rs b/src/tools/rustfmt/tests/target/configs/format_generated_files/false.rs new file mode 100644 index 0000000000..dec1e00d11 --- /dev/null +++ b/src/tools/rustfmt/tests/target/configs/format_generated_files/false.rs @@ -0,0 +1,8 @@ +// @generated +// rustfmt-format_generated_files: false + +fn main() +{ + println!("hello, world") + ; +} diff --git a/src/tools/rustfmt/tests/target/configs/format_generated_files/true.rs b/src/tools/rustfmt/tests/target/configs/format_generated_files/true.rs new file mode 100644 index 0000000000..5fea7e8b34 --- /dev/null +++ b/src/tools/rustfmt/tests/target/configs/format_generated_files/true.rs @@ -0,0 +1,6 @@ +// @generated +// rustfmt-format_generated_files: true + +fn main() { + println!("hello, world"); +} diff --git a/src/tools/rustfmt/tests/target/configs/group_imports/One-merge_imports.rs b/src/tools/rustfmt/tests/target/configs/group_imports/One-merge_imports.rs new file mode 100644 index 0000000000..52e0e1c5ac --- /dev/null +++ b/src/tools/rustfmt/tests/target/configs/group_imports/One-merge_imports.rs @@ -0,0 +1,14 @@ +// rustfmt-group_imports: One +// rustfmt-imports_granularity: Crate +use super::{ + schema::{Context, Payload}, + update::convert_publish_payload, +}; +use crate::models::Event; +use alloc::{alloc::Layout, vec::Vec}; +use broker::database::PooledConnection; +use chrono::Utc; +use core::f32; +use juniper::{FieldError, FieldResult}; +use std::sync::Arc; +use uuid::Uuid; diff --git a/src/tools/rustfmt/tests/target/configs/group_imports/One-nested.rs b/src/tools/rustfmt/tests/target/configs/group_imports/One-nested.rs new file mode 100644 index 0000000000..5b64854826 --- /dev/null +++ b/src/tools/rustfmt/tests/target/configs/group_imports/One-nested.rs @@ -0,0 +1,6 @@ +// rustfmt-group_imports: One +mod test { + use crate::foo::bar; + use crate::foo::bar2; + use std::path; +} diff --git a/src/tools/rustfmt/tests/target/configs/group_imports/One-no_reorder.rs b/src/tools/rustfmt/tests/target/configs/group_imports/One-no_reorder.rs new file mode 100644 index 0000000000..015e841d01 --- /dev/null +++ b/src/tools/rustfmt/tests/target/configs/group_imports/One-no_reorder.rs @@ -0,0 +1,12 @@ +// rustfmt-group_imports: One +// rustfmt-reorder_imports: false +use chrono::Utc; +use super::update::convert_publish_payload; +use juniper::{FieldError, FieldResult}; +use uuid::Uuid; +use alloc::alloc::Layout; +use std::sync::Arc; +use broker::database::PooledConnection; +use super::schema::{Context, Payload}; +use core::f32; +use crate::models::Event; diff --git a/src/tools/rustfmt/tests/target/configs/group_imports/One.rs b/src/tools/rustfmt/tests/target/configs/group_imports/One.rs new file mode 100644 index 0000000000..3094c7ae11 --- /dev/null +++ b/src/tools/rustfmt/tests/target/configs/group_imports/One.rs @@ -0,0 +1,11 @@ +// rustfmt-group_imports: One +use super::schema::{Context, Payload}; +use super::update::convert_publish_payload; +use crate::models::Event; +use alloc::alloc::Layout; +use broker::database::PooledConnection; +use chrono::Utc; +use core::f32; +use juniper::{FieldError, FieldResult}; +use std::sync::Arc; +use uuid::Uuid; diff --git a/src/tools/rustfmt/tests/target/empty-item-single-line-false.rs b/src/tools/rustfmt/tests/target/empty-item-single-line-false.rs new file mode 100644 index 0000000000..bf7f70e7c4 --- /dev/null +++ b/src/tools/rustfmt/tests/target/empty-item-single-line-false.rs @@ -0,0 +1,41 @@ +// rustfmt-brace_style: AlwaysNextLine +// rustfmt-empty_item_single_line: false + +fn function() +{ +} + +struct Struct {} + +enum Enum {} + +trait Trait +{ +} + +impl<T> Trait for T +{ +} + +trait Trait2<T> +where + T: Copy + Display + Write + Read + FromStr, +{ +} + +trait Trait3<T> +where + T: Something + + SomethingElse + + Sync + + Send + + Display + + Debug + + Copy + + Hash + + Debug + + Display + + Write + + Read, +{ +} diff --git a/src/tools/rustfmt/tests/target/hex_literal_lower.rs b/src/tools/rustfmt/tests/target/hex_literal_lower.rs new file mode 100644 index 0000000000..5c27fded16 --- /dev/null +++ b/src/tools/rustfmt/tests/target/hex_literal_lower.rs @@ -0,0 +1,5 @@ +// rustfmt-hex_literal_case: Lower +fn main() { + let h1 = 0xcafe_5ea7; + let h2 = 0xcafe_f00du32; +} diff --git a/src/tools/rustfmt/tests/target/hex_literal_preserve.rs b/src/tools/rustfmt/tests/target/hex_literal_preserve.rs new file mode 100644 index 0000000000..e8774d0bb2 --- /dev/null +++ b/src/tools/rustfmt/tests/target/hex_literal_preserve.rs @@ -0,0 +1,5 @@ +// rustfmt-hex_literal_case: Preserve +fn main() { + let h1 = 0xcAfE_5Ea7; + let h2 = 0xCaFe_F00du32; +} diff --git a/src/tools/rustfmt/tests/target/hex_literal_upper.rs b/src/tools/rustfmt/tests/target/hex_literal_upper.rs new file mode 100644 index 0000000000..48bb93d2c1 --- /dev/null +++ b/src/tools/rustfmt/tests/target/hex_literal_upper.rs @@ -0,0 +1,5 @@ +// rustfmt-hex_literal_case: Upper +fn main() { + let h1 = 0xCAFE_5EA7; + let h2 = 0xCAFE_F00Du32; +} diff --git a/src/tools/rustfmt/tests/target/impls.rs b/src/tools/rustfmt/tests/target/impls.rs index bf63f924a3..99e02990e4 100644 --- a/src/tools/rustfmt/tests/target/impls.rs +++ b/src/tools/rustfmt/tests/target/impls.rs @@ -21,6 +21,14 @@ pub impl Foo for Bar { // Comment 3 } +#[inherent] +impl Visible for Bar { + pub const C: i32; + pub type T; + pub fn f(); + pub fn g() {} +} + pub unsafe impl<'a, 'b, X, Y: Foo<Bar>> !Foo<'a, X> for Bar<'b, Y> where X: Foo<'a, Z>, diff --git a/src/tools/rustfmt/tests/target/imports_granularity_one.rs b/src/tools/rustfmt/tests/target/imports_granularity_one.rs new file mode 100644 index 0000000000..78ec5e7325 --- /dev/null +++ b/src/tools/rustfmt/tests/target/imports_granularity_one.rs @@ -0,0 +1,79 @@ +// rustfmt-imports_granularity: One + +use { + a::{ + aa::*, + ab, + ac::{aca, acb}, + }, + b, +}; + +use { + a::{self as x, aa, ab}, + b::ba, +}; + +use a::{ + aa::{aaa, *}, + ab::aba as x, +}; + +#[cfg(test)] +use a::{ab, ac::aca}; +#[cfg(test)] +use b::{ + ba, bb, + bc::bca::{bcaa, bcab}, +}; +use { + a::{aa, ad::ada}, + b, +}; + +pub use { + a::{aa, ae}, + b::{bb, bc::bca}, +}; +use { + a::{ab, ac, ad}, + b::ba, +}; + +use { + a::{ + aa::{aaa, *}, + ab, + ac::{aca, acb}, + }, + b::{ + ba, + bb::{self, bba}, + }, +}; + +use { + crate::{a, b::ba}, + c::ca, +}; + +use { + super::{a, b::ba}, + c::ca, +}; + +use { + super::b, + crate::a, + c::{self, ca}, +}; + +use { + a::{ + aa::{aaa, aab}, + ab, + ac::aca, + ad::ada, + }, + b as x, +}; diff --git a/src/tools/rustfmt/tests/target/issue-3158.rs b/src/tools/rustfmt/tests/target/issue-3158.rs new file mode 100644 index 0000000000..4bbbdc1d03 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-3158.rs @@ -0,0 +1,74 @@ +// rustfmt-format_code_in_doc_comments: true + +/// Should format +/// ```rust +/// assert!(false); +/// ``` +/// +/// Should format +/// ```rust,should_panic +/// assert!(false); +/// ``` +/// +/// Should format +/// ```rust,should_panic,edition2018 +/// assert!(false); +/// ``` +/// +/// Should format +/// ```rust , should_panic , edition2018 +/// assert!(false); +/// ``` +/// +/// Should not format +/// ```ignore +/// assert!( false ); +/// ``` +/// +/// Should not format (not all are rust) +/// ```rust,ignore +/// assert!( false ); +/// ``` +/// +/// Should not format (rust compile_fail) +/// ```compile_fail +/// assert!( false ); +/// ``` +/// +/// Should not format (rust compile_fail) +/// ```rust,compile_fail +/// assert!( false ); +/// ``` +/// +/// Various unspecified ones that should format +/// ``` +/// assert!(false); +/// ``` +/// +/// ```, +/// assert!(false); +/// ``` +/// +/// ```,,,,, +/// assert!(false); +/// ``` +/// +/// ```,,, rust ,, +/// assert!(false); +/// ``` +/// +/// Should not format +/// ```,,, rust , ignore, +/// assert!( false ); +/// ``` +/// +/// Few empty ones +/// ``` +/// ``` +/// +/// ```rust +/// ``` +/// +/// ```ignore +/// ``` +fn foo() {} diff --git a/src/tools/rustfmt/tests/target/issue-4530.rs b/src/tools/rustfmt/tests/target/issue-4530.rs new file mode 100644 index 0000000000..296dc559a9 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4530.rs @@ -0,0 +1,9 @@ +// rustfmt-version: Two +fn main() { + let [ + aaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + cccccccccccccccccccccccccc, + ddddddddddddddddddddddddd, + ] = panic!(); +} diff --git a/src/tools/rustfmt/tests/target/issue-4615/minimum_example.rs b/src/tools/rustfmt/tests/target/issue-4615/minimum_example.rs new file mode 100644 index 0000000000..223b89b812 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4615/minimum_example.rs @@ -0,0 +1,5 @@ +info!( + //debug + "{}: sending function_code={:04x} data={:04x} crc=0x{:04X} data={:02X?}", + self.name, function_code, data, crc, output_cmd +); diff --git a/src/tools/rustfmt/tests/target/issue-4816/lib.rs b/src/tools/rustfmt/tests/target/issue-4816/lib.rs new file mode 100644 index 0000000000..246e775e1f --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4816/lib.rs @@ -0,0 +1,35 @@ +#![feature(const_generics_defaults)] +struct Foo<const N: usize = 1, const N2: usize = 2>; +struct Bar<const N: usize, const N2: usize = { N + 1 }>; +struct Lots< + const N1BlahFooUwU: usize = { 10 + 28 + 1872 / 10 * 3 }, + const N2SecondParamOhmyyy: usize = { N1BlahFooUwU / 2 + 10 * 2 }, +>; +struct NamesRHard<const N: usize = { 1 + 1 + 1 + 1 + 1 + 1 }>; +struct FooBar< + const LessThan100ButClose: usize = { + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + }, +>; +struct FooBarrrrrrrr< + const N: usize = { + 13478234326456456444323871 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + }, +>; diff --git a/src/tools/rustfmt/tests/target/issue-4908-2.rs b/src/tools/rustfmt/tests/target/issue-4908-2.rs new file mode 100644 index 0000000000..023b323cb2 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4908-2.rs @@ -0,0 +1,20 @@ +#![feature(more_qualified_paths)] + +fn main() { + // destructure through a qualified path + let <Foo as A>::Assoc { br } = StructStruct { br: 2 }; +} + +struct StructStruct { + br: i8, +} + +struct Foo; + +trait A { + type Assoc; +} + +impl A for Foo { + type Assoc = StructStruct; +} diff --git a/src/tools/rustfmt/tests/target/issue-4908.rs b/src/tools/rustfmt/tests/target/issue-4908.rs new file mode 100644 index 0000000000..ac5357abe2 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4908.rs @@ -0,0 +1,34 @@ +#![feature(more_qualified_paths)] + +mod foo_bar { + pub enum Example { + Example1 {}, + Example2 {}, + } +} + +fn main() { + foo!(crate::foo_bar::Example, Example1); + + let i1 = foo_bar::Example::Example1 {}; + + assert_eq!(i1.foo_example(), 1); + + let i2 = foo_bar::Example::Example2 {}; + + assert_eq!(i2.foo_example(), 2); +} + +#[macro_export] +macro_rules! foo { + ($struct:path, $variant:ident) => { + impl $struct { + pub fn foo_example(&self) -> i32 { + match self { + <$struct>::$variant { .. } => 1, + _ => 2, + } + } + } + }; +} diff --git a/src/tools/rustfmt/tests/target/issue-4926/deeply_nested_struct.rs b/src/tools/rustfmt/tests/target/issue-4926/deeply_nested_struct.rs new file mode 100644 index 0000000000..072cf2f667 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4926/deeply_nested_struct.rs @@ -0,0 +1,38 @@ +// rustfmt-struct_field_align_threshold: 30 + +struct X { + a: i32, + b: i32, + c: i32, +} + +fn test(x: X) { + let d = { + let e = { + let f = { + let g = { + let h = { + let i = { + let j = { + matches!( + x, + X { + a: 1_000, + b: 1_000, + .. + } + ) + }; + j + }; + i + }; + h + }; + g + }; + f + }; + e + }; +} diff --git a/src/tools/rustfmt/tests/target/issue-4926/deeply_nested_struct_with_long_field_names.rs b/src/tools/rustfmt/tests/target/issue-4926/deeply_nested_struct_with_long_field_names.rs new file mode 100644 index 0000000000..c7bc7f7296 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4926/deeply_nested_struct_with_long_field_names.rs @@ -0,0 +1,44 @@ +// rustfmt-struct_field_align_threshold: 30 + +struct X { + really_really_long_field_a: i32, + really_really_really_long_field_b: i32, + really_really_really_really_long_field_c: i32, + really_really_really_really_really_long_field_d: i32, + really_really_really_really_really_really_long_field_e: i32, + f: i32, +} + +fn test(x: X) { + let d = { + let e = { + let f = { + let g = { + let h = { + let i = { + let j = { + matches!( + x, + X { + really_really_long_field_a: 10, + really_really_really_long_field_b: 10, + really_really_really_really_long_field_c: 10, + really_really_really_really_really_long_field_d: 10, + really_really_really_really_really_really_long_field_e: 10, + .. + } + ) + }; + j + }; + i + }; + h + }; + g + }; + f + }; + e + }; +} diff --git a/src/tools/rustfmt/tests/target/issue-4926/deeply_nested_struct_with_many_fields.rs b/src/tools/rustfmt/tests/target/issue-4926/deeply_nested_struct_with_many_fields.rs new file mode 100644 index 0000000000..6979316251 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4926/deeply_nested_struct_with_many_fields.rs @@ -0,0 +1,54 @@ +// rustfmt-struct_field_align_threshold: 30 + +struct X { + a: i32, + b: i32, + c: i32, + d: i32, + e: i32, + f: i32, + g: i32, + h: i32, + i: i32, + j: i32, + k: i32, +} + +fn test(x: X) { + let d = { + let e = { + let f = { + let g = { + let h = { + let i = { + let j = { + matches!( + x, + X { + a: 1_000, + b: 1_000, + c: 1_000, + d: 1_000, + e: 1_000, + f: 1_000, + g: 1_000, + h: 1_000, + i: 1_000, + j: 1_000, + .. + } + ) + }; + j + }; + i + }; + h + }; + g + }; + f + }; + e + }; +} diff --git a/src/tools/rustfmt/tests/target/issue-4926/enum_struct_field.rs b/src/tools/rustfmt/tests/target/issue-4926/enum_struct_field.rs new file mode 100644 index 0000000000..2471df8465 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4926/enum_struct_field.rs @@ -0,0 +1,41 @@ +// rustfmt-struct_field_align_threshold: 30 +// rustfmt-enum_discrim_align_threshold: 30 +// rustfmt-imports_layout: HorizontalVertical + +#[derive(Default)] +struct InnerStructA { + bbbbbbbbb: i32, + cccccccc: i32, +} + +enum SomeEnumNamedD { + E(InnerStructA), + F { + ggggggggggggggggggggggggg: bool, + h: bool, + }, +} + +impl SomeEnumNamedD { + fn f_variant() -> Self { + Self::F { + ggggggggggggggggggggggggg: true, + h: true, + } + } +} + +fn main() { + let kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk = SomeEnumNamedD::f_variant(); + let something_we_care_about = matches!( + kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk, + SomeEnumNamedD::F { + ggggggggggggggggggggggggg: true, + .. + } + ); + + if something_we_care_about { + println!("Yup it happened"); + } +} diff --git a/src/tools/rustfmt/tests/target/issue-4926/minimum_example.rs b/src/tools/rustfmt/tests/target/issue-4926/minimum_example.rs new file mode 100644 index 0000000000..06e1842746 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4926/minimum_example.rs @@ -0,0 +1,10 @@ +// rustfmt-struct_field_align_threshold: 30 + +struct X { + a: i32, + b: i32, +} + +fn test(x: X) { + let y = matches!(x, X { a: 1, .. }); +} diff --git a/src/tools/rustfmt/tests/target/issue-4926/struct_with_long_field_names.rs b/src/tools/rustfmt/tests/target/issue-4926/struct_with_long_field_names.rs new file mode 100644 index 0000000000..ac4674ab5d --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4926/struct_with_long_field_names.rs @@ -0,0 +1,24 @@ +// rustfmt-struct_field_align_threshold: 30 + +struct X { + really_really_long_field_a: i32, + really_really_really_long_field_b: i32, + really_really_really_really_long_field_c: i32, + really_really_really_really_really_long_field_d: i32, + really_really_really_really_really_really_long_field_e: i32, + f: i32, +} + +fn test(x: X) { + let y = matches!( + x, + X { + really_really_long_field_a: 10, + really_really_really_long_field_b: 10, + really_really_really_really_long_field_c: 10, + really_really_really_really_really_long_field_d: 10, + really_really_really_really_really_really_long_field_e: 10, + .. + } + ); +} diff --git a/src/tools/rustfmt/tests/target/issue-4926/struct_with_many_fields.rs b/src/tools/rustfmt/tests/target/issue-4926/struct_with_many_fields.rs new file mode 100644 index 0000000000..96dfe14bf7 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4926/struct_with_many_fields.rs @@ -0,0 +1,34 @@ +// rustfmt-struct_field_align_threshold: 30 + +struct X { + a: i32, + b: i32, + c: i32, + d: i32, + e: i32, + f: i32, + g: i32, + h: i32, + i: i32, + j: i32, + k: i32, +} + +fn test(x: X) { + let y = matches!( + x, + X { + a: 1_000, + b: 1_000, + c: 1_000, + d: 1_000, + e: 1_000, + f: 1_000, + g: 1_000, + h: 1_000, + i: 1_000, + j: 1_000, + .. + } + ); +} diff --git a/src/tools/rustfmt/tests/target/issue-4984/minimum_example.rs b/src/tools/rustfmt/tests/target/issue-4984/minimum_example.rs new file mode 100644 index 0000000000..f0599c5d69 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4984/minimum_example.rs @@ -0,0 +1,2 @@ +#[derive(/*Debug, */ Clone)] +struct Foo; diff --git a/src/tools/rustfmt/tests/target/issue-4984/multi_line_derive.rs b/src/tools/rustfmt/tests/target/issue-4984/multi_line_derive.rs new file mode 100644 index 0000000000..5fbd9784ad --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4984/multi_line_derive.rs @@ -0,0 +1,26 @@ +#[derive( + /* ---------- Some really important comment that just had to go inside the derive --------- */ + Debug, + Clone, + Eq, + PartialEq, +)] +struct Foo { + a: i32, + b: T, +} + +#[derive( + /* + Some really important comment that just had to go inside the derive. + Also had to be put over multiple lines + */ + Debug, + Clone, + Eq, + PartialEq, +)] +struct Bar { + a: i32, + b: T, +} diff --git a/src/tools/rustfmt/tests/target/issue-4984/multiple_comments_within.rs b/src/tools/rustfmt/tests/target/issue-4984/multiple_comments_within.rs new file mode 100644 index 0000000000..d2924f0d0f --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4984/multiple_comments_within.rs @@ -0,0 +1,11 @@ +#[derive( + /* ---------- Some really important comment that just had to go inside the derive --------- */ + Debug, + Clone, + /* Another comment */ Eq, + PartialEq, +)] +struct Foo { + a: i32, + b: T, +} diff --git a/src/tools/rustfmt/tests/target/issue-4984/should_not_change.rs b/src/tools/rustfmt/tests/target/issue-4984/should_not_change.rs new file mode 100644 index 0000000000..e46ee51108 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4984/should_not_change.rs @@ -0,0 +1,5 @@ +#[derive(Clone, Debug, Eq, PartialEq)] +struct Foo; + +#[derive(Clone)] +struct Bar; diff --git a/src/tools/rustfmt/tests/target/issue-5005/minimum_example.rs b/src/tools/rustfmt/tests/target/issue-5005/minimum_example.rs new file mode 100644 index 0000000000..11cc645fa5 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5005/minimum_example.rs @@ -0,0 +1,9 @@ +#![feature(more_qualified_paths)] +macro_rules! show { + ($ty:ty, $ex:expr) => { + match $ex { + <$ty>::A(_val) => println!("got a"), // formatting should not remove <$ty>:: + <$ty>::B => println!("got b"), + } + }; +} diff --git a/src/tools/rustfmt/tests/target/issue-5009/1_minimum_example.rs b/src/tools/rustfmt/tests/target/issue-5009/1_minimum_example.rs new file mode 100644 index 0000000000..55836f4bf5 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5009/1_minimum_example.rs @@ -0,0 +1,4 @@ +fn main() { + // the "in" inside the pattern produced invalid syntax + for variable_in_here /* ... */ in 0..1 {} +} diff --git a/src/tools/rustfmt/tests/target/issue-5009/2_many_in_connectors_in_pattern.rs b/src/tools/rustfmt/tests/target/issue-5009/2_many_in_connectors_in_pattern.rs new file mode 100644 index 0000000000..d83590c685 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5009/2_many_in_connectors_in_pattern.rs @@ -0,0 +1,3 @@ +fn main() { + for in_in_in_in_in_in_in_in /* ... */ in 0..1 {} +} diff --git a/src/tools/rustfmt/tests/target/issue-5009/3_nested_for_loop_with_connector_in_pattern.rs b/src/tools/rustfmt/tests/target/issue-5009/3_nested_for_loop_with_connector_in_pattern.rs new file mode 100644 index 0000000000..9c80072393 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5009/3_nested_for_loop_with_connector_in_pattern.rs @@ -0,0 +1,5 @@ +fn main() { + for variable_in_x /* ... */ in 0..1 { + for variable_in_y /* ... */ in 0..1 {} + } +} diff --git a/src/tools/rustfmt/tests/target/issue-5009/4_nested_for_loop_with_if_elseif_else.rs b/src/tools/rustfmt/tests/target/issue-5009/4_nested_for_loop_with_if_elseif_else.rs new file mode 100644 index 0000000000..a716d0d308 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5009/4_nested_for_loop_with_if_elseif_else.rs @@ -0,0 +1,13 @@ +fn main() { + for variable_in_x /* ... */ in 0..1 { + for variable_in_y /* ... */ in 0..1 { + if false { + + } else if false { + + } else { + + } + } + } +} diff --git a/src/tools/rustfmt/tests/target/issue-5009/5_nested_for_loop_with_connector_in_if_elseif_else.rs b/src/tools/rustfmt/tests/target/issue-5009/5_nested_for_loop_with_connector_in_if_elseif_else.rs new file mode 100644 index 0000000000..41ea46d4cb --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5009/5_nested_for_loop_with_connector_in_if_elseif_else.rs @@ -0,0 +1,15 @@ +fn main() { + let in_ = false; + + for variable_in_x /* ... */ in 0..1 { + for variable_in_y /* ... */ in 0..1 { + if in_ { + + } else if in_ { + + } else { + + } + } + } +} diff --git a/src/tools/rustfmt/tests/target/issue-5009/6_deeply_nested_for_loop_with_connector_in_pattern.rs b/src/tools/rustfmt/tests/target/issue-5009/6_deeply_nested_for_loop_with_connector_in_pattern.rs new file mode 100644 index 0000000000..789e54f7e5 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5009/6_deeply_nested_for_loop_with_connector_in_pattern.rs @@ -0,0 +1,32 @@ +fn main() { + for variable_in_a /* ... */ in 0..1 { + for variable_in_b /* ... */ in 0..1 { + for variable_in_c /* ... */ in 0..1 { + for variable_in_d /* ... */ in 0..1 { + for variable_in_e /* ... */ in 0..1 { + for variable_in_f /* ... */ in 0..1 { + for variable_in_g /* ... */ in 0..1 { + for variable_in_h /* ... */ in 0..1 { + for variable_in_i /* ... */ in 0..1 { + for variable_in_j /* ... */ in 0..1 { + for variable_in_k /* ... */ in 0..1 { + for variable_in_l /* ... */ in 0..1 { + for variable_in_m /* ... */ in 0..1 { + for variable_in_n /* ... */ in 0..1 { + for variable_in_o /* ... */ in 0..1 { + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } +} diff --git a/src/tools/rustfmt/tests/target/issue-5011.rs b/src/tools/rustfmt/tests/target/issue-5011.rs new file mode 100644 index 0000000000..9ad4a1929b --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5011.rs @@ -0,0 +1,8 @@ +pub(crate) struct ASlash( + // hello + i32, +); + +pub(crate) struct AStar(/* hello */ i32); + +pub(crate) struct BStar(/* hello */ i32); diff --git a/src/tools/rustfmt/tests/target/issue-5012/trailing_comma_always.rs b/src/tools/rustfmt/tests/target/issue-5012/trailing_comma_always.rs new file mode 100644 index 0000000000..ff9c40fbbd --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5012/trailing_comma_always.rs @@ -0,0 +1,8 @@ +// rustfmt-trailing_comma: Always + +pub struct Matrix<T, const R: usize, const C: usize,> +where + [T; R * C]:, +{ + contents: [T; R * C], +} diff --git a/src/tools/rustfmt/tests/target/issue-5012/trailing_comma_never.rs b/src/tools/rustfmt/tests/target/issue-5012/trailing_comma_never.rs new file mode 100644 index 0000000000..2fac8eae52 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5012/trailing_comma_never.rs @@ -0,0 +1,8 @@ +// rustfmt-trailing_comma: Never + +pub struct Matrix<T, const R: usize, const C: usize> +where + [T; R * C]: +{ + contents: [T; R * C] +} diff --git a/src/tools/rustfmt/tests/target/issue-5033/minimum_example.rs b/src/tools/rustfmt/tests/target/issue-5033/minimum_example.rs new file mode 100644 index 0000000000..0e7df41deb --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5033/minimum_example.rs @@ -0,0 +1,8 @@ +// leading comment + +#![rustfmt::skip] +fn main() { + println!("main"); // commented +} + +// post comment diff --git a/src/tools/rustfmt/tests/target/issue-5033/nested_modules.rs b/src/tools/rustfmt/tests/target/issue-5033/nested_modules.rs new file mode 100644 index 0000000000..7a11133b60 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5033/nested_modules.rs @@ -0,0 +1,11 @@ +#![rustfmt::skip] + +mod a { + mod b { + + } + + // trailing comment b +} + +// trailing comment a diff --git a/src/tools/rustfmt/tests/target/issue_4031.rs b/src/tools/rustfmt/tests/target/issue_4031.rs new file mode 100644 index 0000000000..065d5395c7 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_4031.rs @@ -0,0 +1,21 @@ +fn foo() { + with_woff2_glyf_table("tests/fonts/woff2/SFNT-TTF-Composite.woff2", |glyf| { + let actual = glyf + .records + .iter() + .map(|glyph| match glyph { + GlyfRecord::Parsed( + found @ Glyph { + data: GlyphData::Composite { .. }, + .. + }, + ) => Some(found), + _ => None, + }) + .find(|candidate| candidate.is_some()) + .unwrap() + .unwrap(); + + assert_eq!(*actual, expected) + }); +} diff --git a/src/tools/rustfmt/tests/target/issue_4032.rs b/src/tools/rustfmt/tests/target/issue_4032.rs new file mode 100644 index 0000000000..2e7e624ca6 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_4032.rs @@ -0,0 +1,18 @@ +fn a1( + #[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] + a: u8, +) { +} +fn b1( + #[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] + bb: u8, +) { +} +fn a2( + #[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] a: u8, +) { +} +fn b2( + #[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] bb: u8, +) { +} diff --git a/src/tools/rustfmt/tests/target/issue_4110.rs b/src/tools/rustfmt/tests/target/issue_4110.rs new file mode 100644 index 0000000000..4a58c3946e --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_4110.rs @@ -0,0 +1,55 @@ +fn bindings() { + let err = match (place_desc, explanation) { + ( + Some(ref name), + BorrowExplanation::MustBeValidFor { + category: + category @ (ConstraintCategory::Return + | ConstraintCategory::CallArgument + | ConstraintCategory::OpaqueType), + from_closure: false, + ref region_name, + span, + .. + }, + ) if borrow_spans.for_generator() | borrow_spans.for_closure() => self + .report_escaping_closure_capture( + borrow_spans, + borrow_span, + region_name, + category, + span, + &format!("`{}`", name), + ), + ( + ref name, + BorrowExplanation::MustBeValidFor { + category: ConstraintCategory::Assignment, + from_closure: false, + region_name: + RegionName { + source: RegionNameSource::AnonRegionFromUpvar(upvar_span, ref upvar_name), + .. + }, + span, + .. + }, + ) => self.report_escaping_data(borrow_span, name, upvar_span, upvar_name, span), + (Some(name), explanation) => self.report_local_value_does_not_live_long_enough( + location, + &name, + &borrow, + drop_span, + borrow_spans, + explanation, + ), + (None, explanation) => self.report_temporary_value_does_not_live_long_enough( + location, + &borrow, + drop_span, + borrow_spans, + proper_span, + explanation, + ), + }; +} diff --git a/src/tools/rustfmt/tests/target/issue_4257.rs b/src/tools/rustfmt/tests/target/issue_4257.rs new file mode 100644 index 0000000000..1ebaaf2b60 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_4257.rs @@ -0,0 +1,18 @@ +#![feature(generic_associated_types)] +#![allow(incomplete_features)] + +trait Trait<T> { + type Type<'a> + where + T: 'a; + fn foo(x: &T) -> Self::Type<'_>; +} +impl<T> Trait<T> for () { + type Type<'a> + where + T: 'a, + = &'a T; + fn foo(x: &T) -> Self::Type<'_> { + x + } +} diff --git a/src/tools/rustfmt/tests/target/issue_4322.rs b/src/tools/rustfmt/tests/target/issue_4322.rs new file mode 100644 index 0000000000..0ec0547119 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_4322.rs @@ -0,0 +1,5 @@ +trait Bar { + type X<'a> + where + Self: 'a; +} diff --git a/src/tools/rustfmt/tests/target/issue_4579.rs b/src/tools/rustfmt/tests/target/issue_4579.rs new file mode 100644 index 0000000000..7b0a5f3a62 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_4579.rs @@ -0,0 +1,16 @@ +// rustfmt-hard_tabs: true + +#[macro_export] +macro_rules! main { + () => { + #[spirv(fragment)] + pub fn main_fs( + mut out_color: ::spirv_std::storage_class::Output<Vec4>, + #[spirv(descriptor_set = 1)] + iChannelResolution: ::spirv_std::storage_class::UniformConstant< + [::spirv_std::glam::Vec3A; 4], + >, + ) { + } + }; +} diff --git a/src/tools/rustfmt/tests/target/issue_4850.rs b/src/tools/rustfmt/tests/target/issue_4850.rs new file mode 100644 index 0000000000..7d4da9022f --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_4850.rs @@ -0,0 +1,4 @@ +impl ThisIsALongStructNameToPushTheWhereToWrapLolololol where + [(); this_is_a_long_const_function_name()]: +{ +} diff --git a/src/tools/rustfmt/tests/target/issue_4911.rs b/src/tools/rustfmt/tests/target/issue_4911.rs new file mode 100644 index 0000000000..890a62267c --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_4911.rs @@ -0,0 +1,9 @@ +#![feature(generic_associated_types)] +#![feature(min_type_alias_impl_trait)] + +impl SomeTrait for SomeType { + type SomeGAT<'a> + where + Self: 'a, + = impl SomeOtherTrait; +} diff --git a/src/tools/rustfmt/tests/target/issue_4936.rs b/src/tools/rustfmt/tests/target/issue_4936.rs new file mode 100644 index 0000000000..c19e505fd0 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_4936.rs @@ -0,0 +1,10 @@ +#[discard_params_doc] +trait Trait { + fn foo( + &self, + /// some docs + bar: String, + /// another docs + baz: i32, + ); +} diff --git a/src/tools/rustfmt/tests/target/issue_4943.rs b/src/tools/rustfmt/tests/target/issue_4943.rs new file mode 100644 index 0000000000..318f7ebed6 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_4943.rs @@ -0,0 +1,10 @@ +#![feature(generic_associated_types)] + +impl SomeStruct { + fn process<T>(v: T) -> <Self as GAT>::R<T> + where + Self: GAT<R<T> = T>, + { + SomeStruct::do_something(v) + } +} diff --git a/src/tools/rustfmt/tests/target/issue_4954.rs b/src/tools/rustfmt/tests/target/issue_4954.rs new file mode 100644 index 0000000000..aa5e79befe --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_4954.rs @@ -0,0 +1,7 @@ +trait Foo { + type Arg<'a>; +} + +struct Bar<T>(T) +where + for<'a> T: Foo<Arg<'a> = ()>; diff --git a/src/tools/rustfmt/tests/target/issue_4963.rs b/src/tools/rustfmt/tests/target/issue_4963.rs new file mode 100644 index 0000000000..0c3c13579c --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_4963.rs @@ -0,0 +1,9 @@ +mod test { + extern "C" { + fn test(); + } +} + +extern "C" { + fn test(); +} diff --git a/src/tools/rustfmt/tests/target/item-brace-style-always-next-line.rs b/src/tools/rustfmt/tests/target/item-brace-style-always-next-line.rs index 531ac59868..4935fac04f 100644 --- a/src/tools/rustfmt/tests/target/item-brace-style-always-next-line.rs +++ b/src/tools/rustfmt/tests/target/item-brace-style-always-next-line.rs @@ -40,3 +40,32 @@ mod M where T: Copy, {} } + +fn function() {} + +trait Trait {} + +impl<T> Trait for T {} + +trait Trait2<T> +where + T: Copy + Display + Write + Read + FromStr, +{ +} + +trait Trait3<T> +where + T: Something + + SomethingElse + + Sync + + Send + + Display + + Debug + + Copy + + Hash + + Debug + + Display + + Write + + Read, +{ +} diff --git a/src/tools/rustfmt/tests/target/match-block-trailing-comma.rs b/src/tools/rustfmt/tests/target/match-block-trailing-comma.rs index 44d1f289f8..5ab433a2e6 100644 --- a/src/tools/rustfmt/tests/target/match-block-trailing-comma.rs +++ b/src/tools/rustfmt/tests/target/match-block-trailing-comma.rs @@ -8,6 +8,16 @@ fn foo() { "line1"; "line2" }, + ThisIsA::Guard if true => { + "line1"; + "line2" + }, + ThisIsA::ReallyLongPattern(ThatWillForce::TheGuard, ToWrapOnto::TheFollowingLine) + if true => + { + "line1"; + "line2" + }, b => ( aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, diff --git a/src/tools/rustfmt/tests/target/trait.rs b/src/tools/rustfmt/tests/target/trait.rs index 620046a71b..7f067991b2 100644 --- a/src/tools/rustfmt/tests/target/trait.rs +++ b/src/tools/rustfmt/tests/target/trait.rs @@ -211,3 +211,10 @@ where + DDDDDDDD + DDDDDDDDD + EEEEEEE; + +trait Visible { + pub const C: i32; + pub type T; + pub fn f(); + pub fn g() {} +} diff --git a/src/tools/rustfmt/triagebot.toml b/src/tools/rustfmt/triagebot.toml new file mode 100644 index 0000000000..fa0824ac53 --- /dev/null +++ b/src/tools/rustfmt/triagebot.toml @@ -0,0 +1 @@ +[assign] diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index c1719a9ffe..bc33284f31 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -82,8 +82,8 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[ "bitflags", "block-buffer", "block-padding", - "byteorder", "byte-tools", + "byteorder", "cc", "cfg-if", "chalk-derive", @@ -140,9 +140,9 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[ "memmap2", "memoffset", "miniz_oxide", - "num_cpus", "num-integer", "num-traits", + "num_cpus", "object", "odht", "once_cell", @@ -190,8 +190,8 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[ "serde_json", "sha-1", "sha2", - "smallvec", "sharded-slab", + "smallvec", "snap", "stable_deref_trait", "stacker", @@ -211,6 +211,11 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[ "tracing-subscriber", "tracing-tree", "typenum", + "unic-char-property", + "unic-char-range", + "unic-common", + "unic-emoji-char", + "unic-ucd-version", "unicode-normalization", "unicode-script", "unicode-security", diff --git a/src/tools/tidy/src/edition.rs b/src/tools/tidy/src/edition.rs index b5e9ceddba..3f59fefd04 100644 --- a/src/tools/tidy/src/edition.rs +++ b/src/tools/tidy/src/edition.rs @@ -18,21 +18,13 @@ pub fn check(path: &Path, bad: &mut bool) { &mut |path| super::filter_dirs(path) || path.ends_with("src/test"), &mut |entry, contents| { let file = entry.path(); - let filestr = file.to_string_lossy().replace("\\", "/"); let filename = file.file_name().unwrap(); if filename != "Cargo.toml" { return; } // Library crates are not yet ready to migrate to 2021. - // - // The reference and rustc-dev-guide are submodules, so are left at - // 2018 for now. They should be removed from this exception list - // when bumped. - if path.components().any(|c| c.as_os_str() == "library") - || filestr.contains("src/doc/reference/style-check/Cargo.toml") - || filestr.contains("src/doc/rustc-dev-guide/ci/date-check/Cargo.toml") - { + if path.components().any(|c| c.as_os_str() == "library") { let has = contents.lines().any(is_edition_2018); if !has { tidy_error!( diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index 129237775f..9b6037c6a4 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -7,7 +7,7 @@ //! * Library features have at most one stability level. //! * Library features have at most one `since` value. //! * All unstable lang features have tests to ensure they are actually unstable. -//! * Language features in a group are sorted by `since` value. +//! * Language features in a group are sorted by feature name. use std::collections::HashMap; use std::fmt; @@ -258,7 +258,7 @@ fn collect_lang_features_in(base: &Path, file: &str, bad: &mut bool) -> Features let mut next_feature_omits_tracking_issue = false; let mut in_feature_group = false; - let mut prev_since = None; + let mut prev_names = vec![]; contents .lines() @@ -291,11 +291,11 @@ fn collect_lang_features_in(base: &Path, file: &str, bad: &mut bool) -> Features } in_feature_group = true; - prev_since = None; + prev_names = vec![]; return None; } else if line.starts_with(FEATURE_GROUP_END_PREFIX) { in_feature_group = false; - prev_since = None; + prev_names = vec![]; return None; } @@ -325,16 +325,49 @@ fn collect_lang_features_in(base: &Path, file: &str, bad: &mut bool) -> Features } }; if in_feature_group { - if prev_since > since { + if prev_names.last() > Some(&name) { + // This assumes the user adds the feature name at the end of the list, as we're + // not looking ahead. + let correct_index = match prev_names.binary_search(&name) { + Ok(_) => { + // This only occurs when the feature name has already been declared. + tidy_error!( + bad, + "{}:{}: duplicate feature {}", + path.display(), + line_number, + name, + ); + // skip any additional checks for this line + return None; + } + Err(index) => index, + }; + + let correct_placement = if correct_index == 0 { + "at the beginning of the feature group".to_owned() + } else if correct_index == prev_names.len() { + // I don't believe this is reachable given the above assumption, but it + // doesn't hurt to be safe. + "at the end of the feature group".to_owned() + } else { + format!( + "between {} and {}", + prev_names[correct_index - 1], + prev_names[correct_index], + ) + }; + tidy_error!( bad, - "{}:{}: feature {} is not sorted by \"since\" (version number)", + "{}:{}: feature {} is not sorted by feature name (should be {})", path.display(), line_number, name, + correct_placement, ); } - prev_since = since; + prev_names.push(name); } let issue_str = parts.next().unwrap().trim(); diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index a20ea3235e..09848462ae 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -60,6 +60,7 @@ fn filter_dirs(path: &Path) -> bool { "compiler/rustc_codegen_gcc", "src/llvm-project", "library/backtrace", + "library/portable-simd", "library/stdarch", "src/tools/cargo", "src/tools/clippy", diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index 022a3dfde8..6ece947714 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -266,6 +266,8 @@ pub fn check(path: &Path, bad: &mut bool) { contains_ignore_directive(can_contain, &contents, "end-whitespace"); let mut skip_trailing_newlines = contains_ignore_directive(can_contain, &contents, "trailing-newlines"); + let mut skip_leading_newlines = + contains_ignore_directive(can_contain, &contents, "leading-newlines"); let mut skip_copyright = contains_ignore_directive(can_contain, &contents, "copyright"); let mut leading_new_lines = false; let mut trailing_new_lines = 0; @@ -350,7 +352,10 @@ pub fn check(path: &Path, bad: &mut bool) { } } if leading_new_lines { - tidy_error!(bad, "{}: leading newline", file.display()); + let mut err = |_| { + tidy_error!(bad, "{}: leading newline", file.display()); + }; + suppressible_tidy_err!(err, skip_leading_newlines, "mising leading newline"); } let mut err = |msg: &str| { tidy_error!(bad, "{}: {}", file.display(), msg); @@ -395,6 +400,9 @@ pub fn check(path: &Path, bad: &mut bool) { if let Directive::Ignore(false) = skip_trailing_newlines { tidy_error!(bad, "{}: ignoring trailing newlines unnecessarily", file.display()); } + if let Directive::Ignore(false) = skip_leading_newlines { + tidy_error!(bad, "{}: ignoring leading newlines unnecessarily", file.display()); + } if let Directive::Ignore(false) = skip_copyright { tidy_error!(bad, "{}: ignoring copyright unnecessarily", file.display()); } diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index a341527c84..203e33e8b1 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 = 1330; -const ISSUES_ENTRY_LIMIT: usize = 2488; +const ROOT_ENTRY_LIMIT: usize = 982; +const ISSUES_ENTRY_LIMIT: usize = 2310; 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 373aea9757..69478d187b 100644 --- a/src/version +++ b/src/version @@ -1 +1 @@ -1.57.0 +1.58.1 diff --git a/vendor/addr2line/.cargo-checksum.json b/vendor/addr2line-0.16.0/.cargo-checksum.json similarity index 100% rename from vendor/addr2line/.cargo-checksum.json rename to vendor/addr2line-0.16.0/.cargo-checksum.json diff --git a/vendor/addr2line/CHANGELOG.md b/vendor/addr2line-0.16.0/CHANGELOG.md similarity index 100% rename from vendor/addr2line/CHANGELOG.md rename to vendor/addr2line-0.16.0/CHANGELOG.md diff --git a/vendor/addr2line/Cargo.lock b/vendor/addr2line-0.16.0/Cargo.lock similarity index 100% rename from vendor/addr2line/Cargo.lock rename to vendor/addr2line-0.16.0/Cargo.lock diff --git a/vendor/addr2line/Cargo.toml b/vendor/addr2line-0.16.0/Cargo.toml similarity index 100% rename from vendor/addr2line/Cargo.toml rename to vendor/addr2line-0.16.0/Cargo.toml diff --git a/vendor/addr2line/LICENSE-APACHE b/vendor/addr2line-0.16.0/LICENSE-APACHE similarity index 100% rename from vendor/addr2line/LICENSE-APACHE rename to vendor/addr2line-0.16.0/LICENSE-APACHE diff --git a/vendor/addr2line/LICENSE-MIT b/vendor/addr2line-0.16.0/LICENSE-MIT similarity index 100% rename from vendor/addr2line/LICENSE-MIT rename to vendor/addr2line-0.16.0/LICENSE-MIT diff --git a/vendor/addr2line/README.md b/vendor/addr2line-0.16.0/README.md similarity index 100% rename from vendor/addr2line/README.md rename to vendor/addr2line-0.16.0/README.md diff --git a/vendor/addr2line/bench.plot.r b/vendor/addr2line-0.16.0/bench.plot.r similarity index 100% rename from vendor/addr2line/bench.plot.r rename to vendor/addr2line-0.16.0/bench.plot.r diff --git a/vendor/addr2line/benchmark.sh b/vendor/addr2line-0.16.0/benchmark.sh similarity index 100% rename from vendor/addr2line/benchmark.sh rename to vendor/addr2line-0.16.0/benchmark.sh diff --git a/vendor/addr2line/coverage b/vendor/addr2line-0.16.0/coverage similarity index 100% rename from vendor/addr2line/coverage rename to vendor/addr2line-0.16.0/coverage diff --git a/vendor/addr2line/examples/addr2line.rs b/vendor/addr2line-0.16.0/examples/addr2line.rs similarity index 100% rename from vendor/addr2line/examples/addr2line.rs rename to vendor/addr2line-0.16.0/examples/addr2line.rs diff --git a/vendor/addr2line/rustfmt.toml b/vendor/addr2line-0.16.0/rustfmt.toml similarity index 100% rename from vendor/addr2line/rustfmt.toml rename to vendor/addr2line-0.16.0/rustfmt.toml diff --git a/vendor/addr2line/src/function.rs b/vendor/addr2line-0.16.0/src/function.rs similarity index 100% rename from vendor/addr2line/src/function.rs rename to vendor/addr2line-0.16.0/src/function.rs diff --git a/vendor/addr2line/src/lazy.rs b/vendor/addr2line-0.16.0/src/lazy.rs similarity index 100% rename from vendor/addr2line/src/lazy.rs rename to vendor/addr2line-0.16.0/src/lazy.rs diff --git a/vendor/addr2line/src/lib.rs b/vendor/addr2line-0.16.0/src/lib.rs similarity index 100% rename from vendor/addr2line/src/lib.rs rename to vendor/addr2line-0.16.0/src/lib.rs diff --git a/vendor/addr2line/tests/correctness.rs b/vendor/addr2line-0.16.0/tests/correctness.rs similarity index 100% rename from vendor/addr2line/tests/correctness.rs rename to vendor/addr2line-0.16.0/tests/correctness.rs diff --git a/vendor/addr2line/tests/output_equivalence.rs b/vendor/addr2line-0.16.0/tests/output_equivalence.rs similarity index 100% rename from vendor/addr2line/tests/output_equivalence.rs rename to vendor/addr2line-0.16.0/tests/output_equivalence.rs diff --git a/vendor/addr2line/tests/parse.rs b/vendor/addr2line-0.16.0/tests/parse.rs similarity index 100% rename from vendor/addr2line/tests/parse.rs rename to vendor/addr2line-0.16.0/tests/parse.rs diff --git a/vendor/anyhow/.cargo-checksum.json b/vendor/anyhow/.cargo-checksum.json index cea6b88f00..c801671a55 100644 --- a/vendor/anyhow/.cargo-checksum.json +++ b/vendor/anyhow/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"0218041b9cab819f48fd47156fadb8500a9bcac2bdbd364d5556ecb25cdc878d","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"cbdc37a6cbd0cdeba37afdf36649f44338cc4d2560766e74fcc38dcb8e52b654","build.rs":"60a08ce87ac48e8a569e73344c2b66b637c172cd35f87358cf95810ce3eba213","src/backtrace.rs":"a1a52f9874f0aa1382fb404f029c6fa88e53afe38fb2417877d5711f1f2b90c9","src/chain.rs":"6edefc5f3c7d69683095862e54e3bb56faba5b3387bf2eeaed429da090007a0a","src/context.rs":"559478ae785ce913523aa21358cc1561ef4b0b95c5c87675a77890364c0162fe","src/error.rs":"fb7b125efc050ecd3f757e0dd88f83772ddf38e647b7a83c393b50ebf7d7c938","src/fmt.rs":"c2d4aad6ce20625a70a7c091e3087b6a2c19a4a87c7a12edb4c98978307245ea","src/kind.rs":"b21b15dbee77d50abe88684a9571b39659076465dd4b1956f366af8fdd26e95a","src/lib.rs":"5f148e2557aba6be27e78d0034a0f253e05171de3454f8686de288e980faab34","src/macros.rs":"88daf58370b2fcc93c43ebd5b9c1659bf5460c972681b63d89d51132126e5560","src/ptr.rs":"f1ece995b5be064773ee3d516710b4948b0bee3c237786d9988c7d2acc52c95c","src/wrapper.rs":"1229beca67dbd95ca77c9ecce282272acc55276c267c58cb73a75388b4693dda","tests/common/mod.rs":"f9088c2d7afafa64ff730b629272045b776bfafc2f5957508242da630635f2e1","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/drop/mod.rs":"382956f4bd3dcd1f6036efb8f11193595a7c60e0a5dbf5f2da149f1f25183abf","tests/test_autotrait.rs":"981e792db353be2f14c7a1cabe43b5f1329c168cb7679077cc2be786a0920d48","tests/test_backtrace.rs":"0e50edbb33b6bd07ba89ff3db72fb7c688ba2a4371fccdbbb20309ab02948b6a","tests/test_boxed.rs":"6b26db0e2eb72afe9af7352ea820837aab90f8d486294616dd5dc34c1b94038c","tests/test_chain.rs":"0e81cf36c45ef1e77f0765f93ea56d07146be090ab35efec573a9fce34e36a23","tests/test_context.rs":"5399c609760b71f16bb63ed593f1adaf9f265bcfbc9aa5ab3361de35ddad48fe","tests/test_convert.rs":"7e7a8b4772a427a911014ac4d1083f9519000e786177f898808980dd9bdfde61","tests/test_downcast.rs":"ce8438cb58a1b7f3599740c261f6ef05855127ccde20c83c82db15eaf51c57ad","tests/test_ffi.rs":"d0cb4c1d6d9154090982dee72ae3ebe05a5981f976058c3250f1c9da5a45edef","tests/test_fmt.rs":"17572596f257aac9aa2ec4620e292ca6a954128b94772bb948399fab53832e70","tests/test_macros.rs":"0288c879c4735a8d317560baa3d4a6efbf1435d8ec350c5cb12cc1ba7c484080","tests/test_repr.rs":"dbb9b04ddbe1ab31eb5331ea69f05bb3a147299da2275a3d4dcc92947b5591b9","tests/test_source.rs":"b80723cf635a4f8c4df21891b34bfab9ed2b2aa407e7a2f826d24e334cd5f88e","tests/ui/no-impl.rs":"fab6cbf2f6ea510b86f567dfb3b7c31250a9fd71ae5d110dbb9188be569ec593","tests/ui/no-impl.stderr":"7dd1b84a267c83121d9f85a9c1aadc072a863ec324e170af4d7d19516f0f526c","tests/ui/temporary-value.rs":"4dcc96271b2403e6372cf4cfc813445e5ce4365fc6e156b6bc38274098499a70","tests/ui/temporary-value.stderr":"4b0cceae9e9b27fe2594e6c02bb3e3fd9965ed04498738e5877934dab807b50f"},"package":"61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1"} \ No newline at end of file +{"files":{"Cargo.toml":"cc2432539cccf2fabff95529049b98cf4f4cf12e69d635a29c8cd2362cc915aa","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"4e01a835c420eada53d0c48cf938eed3ff2355379618a6d8d3a6e5c61bd1f0d8","build.rs":"60a08ce87ac48e8a569e73344c2b66b637c172cd35f87358cf95810ce3eba213","rust-toolchain.toml":"6bbb61302978c736b2da03e4fb40e3beab908f85d533ab46fd541e637b5f3e0f","src/backtrace.rs":"a1a52f9874f0aa1382fb404f029c6fa88e53afe38fb2417877d5711f1f2b90c9","src/chain.rs":"6edefc5f3c7d69683095862e54e3bb56faba5b3387bf2eeaed429da090007a0a","src/context.rs":"559478ae785ce913523aa21358cc1561ef4b0b95c5c87675a77890364c0162fe","src/error.rs":"fb7b125efc050ecd3f757e0dd88f83772ddf38e647b7a83c393b50ebf7d7c938","src/fmt.rs":"c2d4aad6ce20625a70a7c091e3087b6a2c19a4a87c7a12edb4c98978307245ea","src/kind.rs":"b21b15dbee77d50abe88684a9571b39659076465dd4b1956f366af8fdd26e95a","src/lib.rs":"fd94a7a42db1351fd41956866d7be298ae529481f0b2cd37f0d3d0de72f4962d","src/macros.rs":"85f3fd05c593694f174b8378378e4de191eff471141201b18d4f639fb4c45661","src/ptr.rs":"f1ece995b5be064773ee3d516710b4948b0bee3c237786d9988c7d2acc52c95c","src/wrapper.rs":"1229beca67dbd95ca77c9ecce282272acc55276c267c58cb73a75388b4693dda","tests/common/mod.rs":"f9088c2d7afafa64ff730b629272045b776bfafc2f5957508242da630635f2e1","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/drop/mod.rs":"382956f4bd3dcd1f6036efb8f11193595a7c60e0a5dbf5f2da149f1f25183abf","tests/test_autotrait.rs":"981e792db353be2f14c7a1cabe43b5f1329c168cb7679077cc2be786a0920d48","tests/test_backtrace.rs":"0e50edbb33b6bd07ba89ff3db72fb7c688ba2a4371fccdbbb20309ab02948b6a","tests/test_boxed.rs":"6b26db0e2eb72afe9af7352ea820837aab90f8d486294616dd5dc34c1b94038c","tests/test_chain.rs":"0e81cf36c45ef1e77f0765f93ea56d07146be090ab35efec573a9fce34e36a23","tests/test_context.rs":"8409c53b328562c11e822bd6c3cd17e0d4d50b9bbb8fc3617333fd77303a6a33","tests/test_convert.rs":"7e7a8b4772a427a911014ac4d1083f9519000e786177f898808980dd9bdfde61","tests/test_downcast.rs":"ce8438cb58a1b7f3599740c261f6ef05855127ccde20c83c82db15eaf51c57ad","tests/test_ffi.rs":"d0cb4c1d6d9154090982dee72ae3ebe05a5981f976058c3250f1c9da5a45edef","tests/test_fmt.rs":"17572596f257aac9aa2ec4620e292ca6a954128b94772bb948399fab53832e70","tests/test_macros.rs":"0288c879c4735a8d317560baa3d4a6efbf1435d8ec350c5cb12cc1ba7c484080","tests/test_repr.rs":"dbb9b04ddbe1ab31eb5331ea69f05bb3a147299da2275a3d4dcc92947b5591b9","tests/test_source.rs":"b80723cf635a4f8c4df21891b34bfab9ed2b2aa407e7a2f826d24e334cd5f88e","tests/ui/no-impl.rs":"fab6cbf2f6ea510b86f567dfb3b7c31250a9fd71ae5d110dbb9188be569ec593","tests/ui/no-impl.stderr":"9d2d9cdf441f1c4a0ccbc4a7433013166425b98cd8dd8738381e8fd070c1aed9","tests/ui/temporary-value.rs":"4dcc96271b2403e6372cf4cfc813445e5ce4365fc6e156b6bc38274098499a70","tests/ui/temporary-value.stderr":"f1c9da503b75490cc4e85b47b4cf3c29f6b84cd3dc82206cd51079d6b974052f"},"package":"ee10e43ae4a853c0a3591d4e2ada1719e553be18199d9da9d4a83f5927c2f5c7"} \ No newline at end of file diff --git a/vendor/anyhow/Cargo.toml b/vendor/anyhow/Cargo.toml index 881fc23010..1cdf9b5ab5 100644 --- a/vendor/anyhow/Cargo.toml +++ b/vendor/anyhow/Cargo.toml @@ -11,8 +11,9 @@ [package] edition = "2018" +rust-version = "1.34" name = "anyhow" -version = "1.0.44" +version = "1.0.45" authors = ["David Tolnay <dtolnay@gmail.com>"] description = "Flexible concrete Error type built on std::error::Error" documentation = "https://docs.rs/anyhow" @@ -41,7 +42,7 @@ features = ["full"] version = "1.0" [dev-dependencies.trybuild] -version = "1.0.19" +version = "1.0.49" features = ["diff"] [features] diff --git a/vendor/anyhow/README.md b/vendor/anyhow/README.md index e10063f27b..00f7ca57c3 100644 --- a/vendor/anyhow/README.md +++ b/vendor/anyhow/README.md @@ -76,9 +76,9 @@ anyhow = "1.0" ``` - If using the nightly channel, or stable with `features = ["backtrace"]`, a - a backtrace is captured and printed with the error if the underlying error - type does not already provide its own. In order to see backtraces, they must - be enabled through the environment variables described in [`std::backtrace`]: + backtrace is captured and printed with the error if the underlying error type + does not already provide its own. In order to see backtraces, they must be + enabled through the environment variables described in [`std::backtrace`]: - If you want panics and errors to both have backtraces, set `RUST_BACKTRACE=1`; diff --git a/vendor/anyhow/rust-toolchain.toml b/vendor/anyhow/rust-toolchain.toml new file mode 100644 index 0000000000..20fe888c30 --- /dev/null +++ b/vendor/anyhow/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +components = ["rust-src"] diff --git a/vendor/anyhow/src/lib.rs b/vendor/anyhow/src/lib.rs index 2b7a0b1558..785e9aa2f9 100644 --- a/vendor/anyhow/src/lib.rs +++ b/vendor/anyhow/src/lib.rs @@ -210,7 +210,7 @@ //! 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.44")] +#![doc(html_root_url = "https://docs.rs/anyhow/1.0.45")] #![cfg_attr(backtrace, feature(backtrace))] #![cfg_attr(doc_cfg, feature(doc_cfg))] #![cfg_attr(not(feature = "std"), no_std)] @@ -233,7 +233,7 @@ mod alloc { #[cfg(not(feature = "std"))] - extern crate alloc; + pub extern crate alloc; #[cfg(not(feature = "std"))] pub use alloc::boxed::Box; @@ -613,9 +613,6 @@ pub trait Context<T, E>: context::private::Sealed { // Not public API. Referenced by macro-generated code. #[doc(hidden)] pub mod private { - use crate::Error; - use core::fmt::{Debug, Display}; - pub use core::result::Result::Err; #[doc(hidden)] @@ -626,19 +623,18 @@ pub mod private { pub use crate::kind::BoxedKind; } - #[cold] - pub fn new_adhoc<M>(message: M) -> Error - where - M: Display + Debug + Send + Sync + 'static, - { - Error::from_adhoc(message, backtrace!()) - } - #[cfg(anyhow_no_macro_reexport)] - pub use crate::{__anyhow_concat as concat, __anyhow_stringify as stringify}; + pub use crate::{ + __anyhow_concat as concat, __anyhow_format as format, __anyhow_stringify as stringify, + }; #[cfg(not(anyhow_no_macro_reexport))] pub use core::{concat, stringify}; + #[cfg(all(not(anyhow_no_macro_reexport), not(feature = "std")))] + pub use crate::alloc::alloc::format; + #[cfg(all(not(anyhow_no_macro_reexport), feature = "std"))] + pub use std::format; + #[cfg(anyhow_no_macro_reexport)] #[doc(hidden)] #[macro_export] @@ -648,6 +644,15 @@ pub mod private { }; } + #[cfg(anyhow_no_macro_reexport)] + #[doc(hidden)] + #[macro_export] + macro_rules! __anyhow_format { + ($($tt:tt)*) => { + format!($($tt)*) + }; + } + #[cfg(anyhow_no_macro_reexport)] #[doc(hidden)] #[macro_export] diff --git a/vendor/anyhow/src/macros.rs b/vendor/anyhow/src/macros.rs index a0f4cae469..495caa980b 100644 --- a/vendor/anyhow/src/macros.rs +++ b/vendor/anyhow/src/macros.rs @@ -114,10 +114,11 @@ macro_rules! bail { #[macro_export] macro_rules! ensure { ($cond:expr $(,)?) => { - $crate::ensure!( - $cond, - $crate::private::concat!("Condition failed: `", $crate::private::stringify!($cond), "`"), - ) + if !$cond { + return $crate::private::Err($crate::Error::msg( + $crate::private::concat!("Condition failed: `", $crate::private::stringify!($cond), "`") + )); + } }; ($cond:expr, $msg:literal $(,)?) => { if !$cond { @@ -169,7 +170,7 @@ macro_rules! anyhow { ($msg:literal $(,)?) => { // Handle $:literal as a special case to make cargo-expanded code more // concise in the common case. - $crate::private::new_adhoc($msg) + $crate::Error::msg($msg) }; ($err:expr $(,)?) => ({ use $crate::private::kind::*; @@ -178,6 +179,6 @@ macro_rules! anyhow { } }); ($fmt:expr, $($arg:tt)*) => { - $crate::private::new_adhoc(format!($fmt, $($arg)*)) + $crate::Error::msg($crate::private::format!($fmt, $($arg)*)) }; } diff --git a/vendor/anyhow/tests/test_context.rs b/vendor/anyhow/tests/test_context.rs index e2d4a29be8..2053fc9e57 100644 --- a/vendor/anyhow/tests/test_context.rs +++ b/vendor/anyhow/tests/test_context.rs @@ -24,6 +24,7 @@ macro_rules! context_type { #[derive(Debug)] struct $name { message: &'static str, + #[allow(dead_code)] drop: DetectDrop, } diff --git a/vendor/anyhow/tests/ui/no-impl.stderr b/vendor/anyhow/tests/ui/no-impl.stderr index 976b62c7bc..42b86c77cc 100644 --- a/vendor/anyhow/tests/ui/no-impl.stderr +++ b/vendor/anyhow/tests/ui/no-impl.stderr @@ -1,21 +1,42 @@ 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; - | ------------- - | | - | doesn't satisfy `Error: Into<anyhow::Error>` - | doesn't satisfy `Error: anyhow::private::kind::TraitKind` - | doesn't satisfy `Error: std::fmt::Display` + --> tests/ui/no-impl.rs:7:13 + | +4 | struct Error; + | ------------- + | | + | doesn't satisfy `Error: Into<anyhow::Error>` + | doesn't satisfy `Error: anyhow::private::kind::TraitKind` + | doesn't satisfy `Error: std::fmt::Display` ... -7 | let _ = anyhow!(Error); - | ^^^^^^^^^^^^^^ method cannot be called on `&Error` due to unsatisfied trait bounds - | - = 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` - which is required by `&Error: anyhow::private::kind::AdhocKind` - `&Error: Into<anyhow::Error>` - which is required by `&Error: anyhow::private::kind::TraitKind` - = note: this error originates in the macro `anyhow` (in Nightly builds, run with -Z macro-backtrace for more info) +7 | let _ = anyhow!(Error); + | ^^^^^^^^^^^^^^ method cannot be called on `&Error` due to unsatisfied trait bounds + | + = 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` + which is required by `&Error: anyhow::private::kind::AdhocKind` + `&Error: Into<anyhow::Error>` + which is required by `&Error: anyhow::private::kind::TraitKind` +note: the following traits must be implemented + --> $RUST/core/src/convert/mod.rs + | + | / pub trait Into<T>: Sized { + | | /// Performs the conversion. + | | #[must_use] + | | #[stable(feature = "rust1", since = "1.0.0")] + | | fn into(self) -> T; + | | } + | |_^ + | + ::: $RUST/core/src/fmt/mod.rs + | + | / pub trait Display { + | | /// Formats the value using the given formatter. + | | /// + | | /// # Examples +... | + | | fn fmt(&self, f: &mut Formatter<'_>) -> Result; + | | } + | |_^ + = note: this error originates in the macro `anyhow` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/vendor/anyhow/tests/ui/temporary-value.stderr b/vendor/anyhow/tests/ui/temporary-value.stderr index fa753d2e78..a89ddaf169 100644 --- a/vendor/anyhow/tests/ui/temporary-value.stderr +++ b/vendor/anyhow/tests/ui/temporary-value.stderr @@ -1,5 +1,5 @@ error[E0716]: temporary value dropped while borrowed - --> $DIR/temporary-value.rs:4:22 + --> tests/ui/temporary-value.rs:4:22 | 4 | let _ = anyhow!(&String::new()); | ---------^^^^^^^^^^^^^-- temporary value is freed at the end of this statement diff --git a/vendor/arrayvec/.cargo-checksum.json b/vendor/arrayvec/.cargo-checksum.json index 6e5ca468a6..d0de9348ca 100644 --- a/vendor/arrayvec/.cargo-checksum.json +++ b/vendor/arrayvec/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"9608f4cde67279f69e80b85373f19c1dde90a075b51d930e25e26d7ddabbfa03","Cargo.toml":"f4001657c27de1386a449fc5035abc0016f4f70ad99161b16e263d1eb2892dd8","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0245ee104228a100ce5fceecf43e25faae450494d9173f43fd94c27d69fdac13","README.md":"2264c34c62ea4c617d72047b00749b4786dfb9dff2fac24e0320170ee0cd19c8","benches/arraystring.rs":"fad1cecef71c290375befc77c75a868988b8d74135e8f8732bc5b58c85a8ab46","benches/extend.rs":"c38ecedbc88217a7e9fe1a73f916b168a96e48010a7ccd3dba5c3f8dea030d5d","ci/miri.sh":"6bad1d135e1bdd67a6b91c870a7cf5ee09a85f9515633592a6abfbba95fdaf52","src/array_string.rs":"cefc432a025d780e01113144cbd5c0856d4424ec7fba4e626ddea523fbc8bbaf","src/arrayvec.rs":"32da1d3202f621852a3b884491f7a1086b7d813fe64b5cd7cab858ad3e967560","src/arrayvec_impl.rs":"a5e3391dc350041651f0ba3816c863ff7f552ff553e4a88f801481dfad7e7613","src/char.rs":"1de50e1d6045af2b3496426492315ba774986f9bc8301ffa391de861a08cc9cb","src/errors.rs":"ca44c0987f59ae57623088d80013e75129101caea93c278c8ebb0df898bc6b1b","src/lib.rs":"29a4123616c0912ccae5d931d45f0ccc3746647da1ba077c34538824910dd0ca","src/utils.rs":"d1cdc508dfca385e63f1f57bc8b53ed4a7f515e4ac1ebaa97b1d543fc8369432","tests/serde.rs":"117eb2961b5954d13c577edf60bbb07cb7481685cc9d6c49760a981d71465849","tests/tests.rs":"c1cd94337f4dc9aa31a6c16e334319389c605a98ccc5792e5489167cb614b7cb"},"package":"be4dc07131ffa69b8072d35f5007352af944213cde02545e2103680baed38fcd"} \ No newline at end of file +{"files":{"CHANGELOG.md":"f684ba712e1546b4cc7de9637f484598cd3fa49b7e7b32c2d98562a8f78ce98c","Cargo.toml":"94a588809d4be252f0146b9e193abc1b22d8afcce0265af19f12905a3db37998","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":"4f0c2dab882e6df7d10a0b043220587626e64ff94dd53a80949667ed861490de","src/arrayvec.rs":"61fba79217f564e54761c25651c06ec3f6d23b9c6af4bfd621992ef2bb95a74b","src/arrayvec_impl.rs":"a5e3391dc350041651f0ba3816c863ff7f552ff553e4a88f801481dfad7e7613","src/char.rs":"1de50e1d6045af2b3496426492315ba774986f9bc8301ffa391de861a08cc9cb","src/errors.rs":"7fa2ff2350f811d52a210a7346c526d6715cacefd38a46e2d3b57ab7dc62b1ab","src/lib.rs":"29a4123616c0912ccae5d931d45f0ccc3746647da1ba077c34538824910dd0ca","src/utils.rs":"d1cdc508dfca385e63f1f57bc8b53ed4a7f515e4ac1ebaa97b1d543fc8369432","tests/serde.rs":"117eb2961b5954d13c577edf60bbb07cb7481685cc9d6c49760a981d71465849","tests/tests.rs":"f8a18ff5deadb167832964ca0fff4f280129dd4a1de024e9cc76ffb7efe1c12c"},"package":"8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"} \ No newline at end of file diff --git a/vendor/arrayvec/CHANGELOG.md b/vendor/arrayvec/CHANGELOG.md index 8abfc0f2fb..903ef582f7 100644 --- a/vendor/arrayvec/CHANGELOG.md +++ b/vendor/arrayvec/CHANGELOG.md @@ -1,6 +1,20 @@ Recent Changes (arrayvec) ========================= +## 0.7.2 + +- Add `.as_mut_str()` to `ArrayString` by @clarfonthey +- Add `remaining_capacity` to `ArrayString` by @bhgomes +- Add `zero_filled` constructor by @c410-f3r +- Optimize `retain` by @TennyZhuang and @niklasf +- Make the following methods `const` by @bhgomes: + - len + - is_empty + - capacity + - is_full + - remaining_capacity + - CapacityError::new + ## 0.7.1 - Add new ArrayVec methods `.take()` and `.into_inner_unchecked()` by @conradludgate diff --git a/vendor/arrayvec/Cargo.toml b/vendor/arrayvec/Cargo.toml index a71ed05d49..54b00740c1 100644 --- a/vendor/arrayvec/Cargo.toml +++ b/vendor/arrayvec/Cargo.toml @@ -3,17 +3,16 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies +# to registry (e.g., crates.io) dependencies. # -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. [package] edition = "2018" name = "arrayvec" -version = "0.7.1" +version = "0.7.2" 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/" diff --git a/vendor/arrayvec/src/array_string.rs b/vendor/arrayvec/src/array_string.rs index fdce16a66a..c4712a0cbe 100644 --- a/vendor/arrayvec/src/array_string.rs +++ b/vendor/arrayvec/src/array_string.rs @@ -82,11 +82,11 @@ impl<const CAP: usize> ArrayString<CAP> /// Return the length of the string. #[inline] - pub fn len(&self) -> usize { self.len as usize } + pub const fn len(&self) -> usize { self.len as usize } /// Returns whether the string is empty. #[inline] - pub fn is_empty(&self) -> bool { self.len() == 0 } + pub const fn is_empty(&self) -> bool { self.len() == 0 } /// Create a new `ArrayString` from a `str`. /// @@ -129,6 +129,28 @@ impl<const CAP: usize> ArrayString<CAP> Ok(vec) } + /// Create a new `ArrayString` value fully filled with ASCII NULL characters (`\0`). Useful + /// to be used as a buffer to collect external data or as a buffer for intermediate processing. + /// + /// ``` + /// use arrayvec::ArrayString; + /// + /// let string = ArrayString::<16>::zero_filled(); + /// assert_eq!(string.len(), 16); + /// ``` + #[inline] + pub fn zero_filled() -> Self { + assert_capacity_limit!(CAP); + // SAFETY: `assert_capacity_limit` asserts that `len` won't overflow and + // `zeroed` fully fills the array with nulls. + unsafe { + ArrayString { + xs: MaybeUninit::zeroed().assume_init(), + len: CAP as _ + } + } + } + /// Return the capacity of the `ArrayString`. /// /// ``` @@ -138,7 +160,7 @@ impl<const CAP: usize> ArrayString<CAP> /// assert_eq!(string.capacity(), 3); /// ``` #[inline(always)] - pub fn capacity(&self) -> usize { CAP } + pub const fn capacity(&self) -> usize { CAP } /// Return if the `ArrayString` is completely filled. /// @@ -150,7 +172,20 @@ impl<const CAP: usize> ArrayString<CAP> /// string.push_str("A"); /// assert!(string.is_full()); /// ``` - pub fn is_full(&self) -> bool { self.len() == self.capacity() } + pub const fn is_full(&self) -> bool { self.len() == self.capacity() } + + /// Returns the capacity left in the `ArrayString`. + /// + /// ``` + /// use arrayvec::ArrayString; + /// + /// let mut string = ArrayString::<3>::from("abc").unwrap(); + /// string.pop(); + /// assert_eq!(string.remaining_capacity(), 1); + /// ``` + pub const fn remaining_capacity(&self) -> usize { + self.capacity() - self.len() + } /// Adds the given char to the end of the string. /// @@ -370,6 +405,11 @@ impl<const CAP: usize> ArrayString<CAP> self } + /// Return a mutable string slice of the whole `ArrayString`. + pub fn as_mut_str(&mut self) -> &mut str { + self + } + fn as_ptr(&self) -> *const u8 { self.xs.as_ptr() as *const u8 } diff --git a/vendor/arrayvec/src/arrayvec.rs b/vendor/arrayvec/src/arrayvec.rs index 6b4faf8a83..e69e60c180 100644 --- a/vendor/arrayvec/src/arrayvec.rs +++ b/vendor/arrayvec/src/arrayvec.rs @@ -108,7 +108,7 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> { /// assert_eq!(array.len(), 2); /// ``` #[inline(always)] - pub fn len(&self) -> usize { self.len as usize } + pub const fn len(&self) -> usize { self.len as usize } /// Returns whether the `ArrayVec` is empty. /// @@ -120,7 +120,7 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> { /// assert_eq!(array.is_empty(), true); /// ``` #[inline] - pub fn is_empty(&self) -> bool { self.len() == 0 } + pub const fn is_empty(&self) -> bool { self.len() == 0 } /// Return the capacity of the `ArrayVec`. /// @@ -131,7 +131,7 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> { /// assert_eq!(array.capacity(), 3); /// ``` #[inline(always)] - pub fn capacity(&self) -> usize { CAP } + pub const fn capacity(&self) -> usize { CAP } /// Return true if the `ArrayVec` is completely filled to its capacity, false otherwise. /// @@ -143,7 +143,7 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> { /// array.push(1); /// assert!(array.is_full()); /// ``` - pub fn is_full(&self) -> bool { self.len() == self.capacity() } + pub const fn is_full(&self) -> bool { self.len() == self.capacity() } /// Returns the capacity left in the `ArrayVec`. /// @@ -154,7 +154,7 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> { /// array.pop(); /// assert_eq!(array.remaining_capacity(), 1); /// ``` - pub fn remaining_capacity(&self) -> usize { + pub const fn remaining_capacity(&self) -> usize { self.capacity() - self.len() } @@ -493,21 +493,38 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> { let mut g = BackshiftOnDrop { v: self, processed_len: 0, deleted_cnt: 0, original_len }; - while g.processed_len < original_len { + #[inline(always)] + fn process_one<F: FnMut(&mut T) -> bool, T, const CAP: usize, const DELETED: bool>( + f: &mut F, + g: &mut BackshiftOnDrop<'_, T, CAP> + ) -> bool { 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; + return false; } - if g.deleted_cnt > 0 { + if DELETED { 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; + true + } + + // Stage 1: Nothing was deleted. + while g.processed_len != original_len { + if !process_one::<F, T, CAP, false>(&mut f, &mut g) { + break; + } + } + + // Stage 2: Some elements were deleted. + while g.processed_len != original_len { + process_one::<F, T, CAP, true>(&mut f, &mut g); } drop(g); diff --git a/vendor/arrayvec/src/errors.rs b/vendor/arrayvec/src/errors.rs index 380742a807..7ca3ebc4dc 100644 --- a/vendor/arrayvec/src/errors.rs +++ b/vendor/arrayvec/src/errors.rs @@ -12,7 +12,7 @@ pub struct CapacityError<T = ()> { impl<T> CapacityError<T> { /// Create a new `CapacityError` from `element`. - pub fn new(element: T) -> CapacityError<T> { + pub const fn new(element: T) -> CapacityError<T> { CapacityError { element: element, } diff --git a/vendor/arrayvec/tests/tests.rs b/vendor/arrayvec/tests/tests.rs index 26d09ae6bb..2f8a5ef52e 100644 --- a/vendor/arrayvec/tests/tests.rs +++ b/vendor/arrayvec/tests/tests.rs @@ -773,7 +773,6 @@ fn test_arrayvec_const_constructible() { assert_eq!(var[..], [vec![3, 5, 8]]); } - #[test] fn test_arraystring_const_constructible() { const AS: ArrayString<10> = ArrayString::new_const(); @@ -786,3 +785,9 @@ fn test_arraystring_const_constructible() { } +#[test] +fn test_arraystring_zero_filled_has_some_sanity_checks() { + let string = ArrayString::<4>::zero_filled(); + assert_eq!(string.as_str(), "\0\0\0\0"); + assert_eq!(string.len(), 4); +} \ No newline at end of file diff --git a/vendor/camino/.cargo-checksum.json b/vendor/camino/.cargo-checksum.json new file mode 100644 index 0000000000..725394d946 --- /dev/null +++ b/vendor/camino/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"CHANGELOG.md":"89a7c6c24aef4eb3cee4fe5ffc9343e05530d34f6066725548b6642963eb3102","CODE_OF_CONDUCT.md":"f51e207c2961ec061cac5c8aa9dd3098c3437de2c106d740c2aae90771bc0f86","Cargo.lock":"1226d20c067d20520aa439b08d454f75fd95afc591d435f6397dd0ad0ab566d9","Cargo.toml":"45edc5ce3e815c2c1dfd3270505590f06a1c76eae3a7eefa79a004990f90aa2d","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"1998fbe69f0ca946b7f9001c50f5359ba5a11d266e1126286ff796404fc2182f","build.rs":"4e46d73efd79ec269ddc1b2578cad051c66195225bfdf012e4ed430f9f98a3ab","clippy.toml":"818cba7332cc56b019d59e09805a3498f523da788f51454742905f1987c0b563","examples/serde.rs":"0cfbaf99e0fa75325748b614247d97c3c5954a31669ae4834491fb314d275945","examples/structopt.rs":"ea0ec4247aaf71a59cbba55046400306c2caf5cc54c0b234654c9295d4e3331e","rustfmt.toml":"bf9776adb152b3fdc0d75c0929ede148c3e28c58f909a7d052865bc332e8958f","src/lib.rs":"3bf60fc115e23b5263af07759fccff28d48e071e8891405ef9c4465d18e42c0c","src/serde_impls.rs":"6de708d07f79a1366d9c8c19dfdbcb33498a1c0eaf58aa07d4ffb7b61c57a8c6","src/tests.rs":"28695cf9fe0065226ac252384c9d07279656833853728d9a3812e56291684f63","tests/integration_tests.rs":"b664a7555d2e5ac9ab71384e3ccfb73c01abe4c401f8de32e234c03b4d19d0f8"},"package":"52d74260d9bf6944e2208aa46841b4b8f0d7ffc0849a06837b2f510337f86b2b"} \ No newline at end of file diff --git a/vendor/camino/CHANGELOG.md b/vendor/camino/CHANGELOG.md new file mode 100644 index 0000000000..ea9d139dab --- /dev/null +++ b/vendor/camino/CHANGELOG.md @@ -0,0 +1,57 @@ +# Changelog + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [1.0.5] - 2021-07-27 + +### Added + +- `Utf8PathBuf::into_std_path_buf` converts a `Utf8PathBuf` to a `PathBuf`; equivalent to the + `From<Utf8PathBuf> for PathBuf` impl, but may aid in type inference. +- `Utf8Path::as_std_path` converts a `Utf8Path` to a `Path`; equivalent to the + `AsRef<&Path> for &Utf8Path` impl, but may aid in type inference. + +## [1.0.4] - 2021-03-19 + +### Fixed + +- `Hash` impls for `Utf8PathBuf` and `Utf8Path` now match as required by the `Borrow` contract ([#9]). + +[#9]: https://github.com/withoutboats/camino/issues/9 + +## [1.0.3] - 2021-03-11 + +### Added + +- `TryFrom<PathBuf> for Utf8PathBuf` and `TryFrom<&Path> for &Utf8Path`, both of which return new error types ([#6]). +- `AsRef<Utf8Path>`, `AsRef<Path>`, `AsRef<str>` and `AsRef<OsStr>` impls for `Utf8Components`, `Utf8Component` and + `Iter`. + +[#6]: https://github.com/withoutboats/camino/issues/6 + +## [1.0.2] - 2021-03-02 + +### Added + +- `From` impls for converting a `&Utf8Path` or a `Utf8PathBuf` into `Box<Path>`, `Rc<Path>`, `Arc<Path>` and `Cow<'a, Path>`. +- `PartialEq` and `PartialOrd` implementations comparing `Utf8Path` and `Utf8PathBuf` with `Path`, `PathBuf` and its + variants, and comparing `OsStr`, `OsString` and its variants. + +## [1.0.1] - 2021-02-25 + +### Added + +- More `PartialEq` and `PartialOrd` implementations. +- MSRV lowered to 1.34. + +## [1.0.0] - 2021-02-23 + +Initial release. + +[1.0.5]: https://github.com/withoutboats/camino/releases/tag/camino-1.0.5 +[1.0.4]: https://github.com/withoutboats/camino/releases/tag/camino-1.0.4 +[1.0.3]: https://github.com/withoutboats/camino/releases/tag/camino-1.0.3 +[1.0.2]: https://github.com/withoutboats/camino/releases/tag/camino-1.0.2 +[1.0.1]: https://github.com/withoutboats/camino/releases/tag/camino-1.0.1 +[1.0.0]: https://github.com/withoutboats/camino/releases/tag/camino-1.0.0 diff --git a/vendor/camino/CODE_OF_CONDUCT.md b/vendor/camino/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000..2ea2606d04 --- /dev/null +++ b/vendor/camino/CODE_OF_CONDUCT.md @@ -0,0 +1,133 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at the email +address: [codeofconduct@sunshowers.io](mailto:codeofconduct@sunshowers.io). +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +[https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available +at [https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations + diff --git a/vendor/camino/Cargo.lock b/vendor/camino/Cargo.lock new file mode 100644 index 0000000000..f01048fb57 --- /dev/null +++ b/vendor/camino/Cargo.lock @@ -0,0 +1,277 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +dependencies = [ + "winapi", +] + +[[package]] +name = "anyhow" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "camino" +version = "1.0.5" +dependencies = [ + "anyhow", + "serde", + "serde_json", + "structopt", +] + +[[package]] +name = "clap" +version = "2.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +dependencies = [ + "ansi_term", + "atty", + "bitflags", + "strsim", + "textwrap", + "unicode-width", + "vec_map", +] + +[[package]] +name = "heck" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "hermit-abi" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" +dependencies = [ + "libc", +] + +[[package]] +name = "itoa" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba4aede83fc3617411dc6993bc8c70919750c1c257c6ca6a502aed6e0e2394ae" + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "ryu" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" + +[[package]] +name = "serde" +version = "1.0.124" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd761ff957cb2a45fbb9ab3da6512de9de55872866160b23c25f1a841e99d29f" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.124" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1800f7693e94e186f5e25a28291ae1570da908aff7d97a095dec1e56ff99069b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + +[[package]] +name = "structopt" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5277acd7ee46e63e5168a80734c9f6ee81b1367a7d8772a2d765df2a3705d28c" +dependencies = [ + "clap", + "lazy_static", + "structopt-derive", +] + +[[package]] +name = "structopt-derive" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ba9cdfda491b814720b6b06e0cac513d922fc407582032e8706e9f137976f90" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fd9d1e9976102a03c542daa2eff1b43f9d72306342f3f8b3ed5fb8908195d6f" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "unicode-segmentation" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796" + +[[package]] +name = "unicode-width" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" + +[[package]] +name = "unicode-xid" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" + +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + +[[package]] +name = "version_check" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/vendor/camino/Cargo.toml b/vendor/camino/Cargo.toml new file mode 100644 index 0000000000..05592847ed --- /dev/null +++ b/vendor/camino/Cargo.toml @@ -0,0 +1,46 @@ +# 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 = "camino" +version = "1.0.5" +authors = ["Without Boats <saoirse@without.boats>", "Ashley Williams <ashley666ashley@gmail.com>", "Steve Klabnik <steve@steveklabnik.com>", "Rain <rain@sunshowers.io>"] +exclude = [".cargo/**/*", ".github/**/*"] +description = "UTF-8 paths" +documentation = "https://docs.rs/camino" +readme = "README.md" +keywords = ["paths", "utf8", "unicode", "filesystem"] +categories = ["development-tools", "filesystem", "os"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/withoutboats/camino" +[package.metadata.docs.rs] +all-features = true + +[[example]] +name = "serde" +required-features = ["serde1"] +[dependencies.serde] +version = "1" +features = ["derive"] +optional = true +[dev-dependencies.anyhow] +version = "1.0.38" + +[dev-dependencies.serde_json] +version = "1.0.62" + +[dev-dependencies.structopt] +version = "0.3.21" + +[features] +serde1 = ["serde"] diff --git a/vendor/gimli/LICENSE-APACHE b/vendor/camino/LICENSE-APACHE similarity index 100% rename from vendor/gimli/LICENSE-APACHE rename to vendor/camino/LICENSE-APACHE diff --git a/vendor/itertools-0.8.2/LICENSE-MIT b/vendor/camino/LICENSE-MIT similarity index 98% rename from vendor/itertools-0.8.2/LICENSE-MIT rename to vendor/camino/LICENSE-MIT index 9203baa055..31aa79387f 100644 --- a/vendor/itertools-0.8.2/LICENSE-MIT +++ b/vendor/camino/LICENSE-MIT @@ -1,5 +1,3 @@ -Copyright (c) 2015 - 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 diff --git a/vendor/camino/README.md b/vendor/camino/README.md new file mode 100644 index 0000000000..dce026435c --- /dev/null +++ b/vendor/camino/README.md @@ -0,0 +1,125 @@ +# camino - UTF-8 encoded paths + +[![camino on crates.io](https://img.shields.io/crates/v/camino)](https://crates.io/crates/camino) +[![crates.io download count](https://img.shields.io/crates/d/camino)](https://crates.io/crates/camino) +[![Documentation (latest release)](https://docs.rs/camino/badge.svg)](https://docs.rs/camino) +[![License](https://img.shields.io/badge/license-Apache-green.svg)](LICENSE-APACHE) +[![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE-MIT) + +This repository contains the source code for `camino`, an extension of the `std::path` module that adds new +[`Utf8PathBuf`] and [`Utf8Path`] types. + +## What is camino? + +`camino`'s [`Utf8PathBuf`] and [`Utf8Path`] types are like the standard library's [`PathBuf`] and [`Path`] types, except +they are guaranteed to only contain UTF-8 encoded data. Therefore, they expose the ability to get their +contents as strings, they implement `Display`, etc. + +The `std::path` types are not guaranteed to be valid UTF-8. This is the right decision for the standard library, +since it must be as general as possible. However, on all platforms, non-Unicode paths are vanishingly uncommon for a +number of reasons: +* Unicode won. There are still some legacy codebases that store paths in encodings like [Shift JIS], but most + have been converted to Unicode at this point. +* Unicode is the common subset of supported paths across Windows and Unix platforms. (On Windows, Rust stores paths + as [an extension to UTF-8](https://simonsapin.github.io/wtf-8/), and converts them to UTF-16 at Win32 + API boundaries.) +* There are already many systems, such as Cargo, that only support UTF-8 paths. If your own tool interacts with any such + system, you can assume that paths are valid UTF-8 without creating any additional burdens on consumers. +* The ["makefile problem"](https://www.mercurial-scm.org/wiki/EncodingStrategy#The_.22makefile_problem.22) asks: given a + Makefile or other metadata file (such as `Cargo.toml`) that lists the names of other files, how should the names in + the Makefile be matched with the ones on disk? This has *no general, cross-platform solution* in systems that support + non-UTF-8 paths. However, restricting paths to UTF-8 eliminates this problem. + +[Shift JIS]: https://en.wikipedia.org/wiki/Shift_JIS + +Therefore, many programs that want to manipulate paths *do* assume they contain UTF-8 data, and convert them to `str`s +as necessary. However, because this invariant is not encoded in the `Path` type, conversions such as +`path.to_str().unwrap()` need to be repeated again and again, creating a frustrating experience. + +Instead, `camino` allows you to check that your paths are UTF-8 *once*, and then manipulate them +as valid UTF-8 from there on, avoiding repeated lossy and confusing conversions. + +## Examples + +The documentation for [`Utf8PathBuf`] and [`Utf8Path`] contains several examples. + +For examples of how to use `camino` with other libraries like `serde` and `structopt`, see the [`examples`] directory. + +## API design + +`camino` is a very thin wrapper around `std::path`. [`Utf8Path`] and [`Utf8PathBuf`] are drop-in replacements +for [`Path`] and [`PathBuf`]. + +Most APIs are the same, but those at the boundary with `str` are different. Some examples: +* `Path::to_str() -> Option<&str>` has been renamed to `Utf8Path::as_str() -> &str`. +* [`Utf8Path`] implements `Display`, and `Path::display()` has been removed. +* Iterating over a [`Utf8Path`] returns `&str`, not `&OsStr`. + +Every [`Utf8Path`] is a valid [`Path`], so [`Utf8Path`] implements `AsRef<Path>`. Any APIs that accept `impl AsRef<Path>` +will continue to work with [`Utf8Path`] instances. + +## Should you use camino? + +`camino` trades off some utility for a great deal of simplicity. Whether `camino` is appropriate for a project or not +is ultimately a case-by-case decision. Here are some general guidelines that may help. + +*You should consider using camino if...* + +* **You're building portable, cross-platform software.** While both Unix and Windows platforms support different kinds + of non-Unicode paths, Unicode is the common subset that's supported across them. +* **Your system has files that contain the names of other files.** If you don't use UTF-8 paths, you will run into the + makefile problem described above, which has no general, cross-platform solution. +* **You're interacting with existing systems that already assume UTF-8 paths.** In that case you won't be adding any new + burdens on downstream consumers. +* **You're building something brand new and are willing to ask your users to rename their paths if necessary.** Projects + that don't have to worry about legacy compatibility have more flexibility in choosing what paths they support. + +*You should **NOT** use camino, if...* + +* **You're writing a core system utility.** If you're writing, say, an `mv` or `cat` replacement, you should + **not** use camino. Instead, use [`std::path::Path`] and add extensive tests for non-UTF-8 paths. +* **You have legacy compatibility constraints.** For example, Git supports non-UTF-8 paths. If your tool needs to handle + arbitrary Git repositories, it should use its own path type that's a wrapper around `Vec<u8>`. + * [`std::path::Path`] supports arbitrary bytestrings [on Unix] but not on Windows. +* **There's some other reason you need to support non-UTF-8 paths.** Some tools like disk recovery utilities need to + handle potentially corrupt filenames: only being able to handle UTF-8 paths would greatly diminish their utility. + +[on Unix]: https://doc.rust-lang.org/std/os/unix/ffi/index.html + +## Optional features + +By default, `camino` has **no dependencies** other than `std`. There are some optional features that enable +dependencies: +* `serde1` adds serde [`Serialize`] and [`Deserialize`] impls for [`Utf8PathBuf`] and [`Utf8Path`] (zero-copy). + +## Rust version support + +The minimum supported Rust version (MSRV) for `camino` with default features is **1.34**. This project is tested in CI +against the latest stable version of Rust and the MSRV. +* *Stable APIs* added in later Rust versions are supported through conditional compilation in `build.rs`. +* *Deprecations* are kept in sync with the version of Rust they're added in. +* *Unstable APIs* are currently not supported. Please + [file an issue on GitHub](https://github.com/withoutboats/camino/issues/new) if you need an unstable API. + +`camino` is designed to be a core library and has a conservative MSRV policy. MSRV increases will only happen for +a compelling enough reason, and will involve at least a minor version bump. + +Optional features may pull in dependencies that require a newer version of Rust. + +## License + +This project is available under the terms of either the [Apache 2.0 license](LICENSE-APACHE) or the [MIT +license](LICENSE-MIT). + +This project's documentation is adapted from [The Rust Programming Language](https://github.com/rust-lang/rust/), which is +available under the terms of either the [Apache 2.0 license](https://github.com/rust-lang/rust/blob/master/LICENSE-APACHE) +or the [MIT license](https://github.com/rust-lang/rust/blob/master/LICENSE-MIT). + +[`Utf8PathBuf`]: https://docs.rs/camino/*/camino/struct.Utf8PathBuf.html +[`Utf8Path`]: https://docs.rs/camino/*/camino/struct.Utf8Path.html +[`PathBuf`]: https://doc.rust-lang.org/std/path/struct.PathBuf.html +[`Path`]: https://doc.rust-lang.org/std/path/struct.Path.html +[`std::path::Path`]: https://doc.rust-lang.org/std/path/struct.Path.html +[`Serialize`]: https://docs.rs/serde/1/serde/trait.Serialize.html +[`Deserialize`]: https://docs.rs/serde/1/serde/trait.Deserialize.html +[`examples`]: https://github.com/withoutboats/camino/tree/master/examples diff --git a/vendor/camino/build.rs b/vendor/camino/build.rs new file mode 100644 index 0000000000..bc3e4480dc --- /dev/null +++ b/vendor/camino/build.rs @@ -0,0 +1,40 @@ +// Copyright (c) The camino Contributors +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Adapted from +//! https://github.com/dtolnay/syn/blob/a54fb0098c6679f1312113ae2eec0305c51c7390/build.rs. + +use std::{env, process::Command, str}; + +// The rustc-cfg strings below are *not* public API. Please let us know by +// opening a GitHub issue if your build environment requires some way to enable +// these cfgs other than by executing our build script. +fn main() { + let compiler = match rustc_version() { + Some(compiler) => compiler, + None => return, + }; + + // NOTE: + // Adding a new cfg gated by Rust version MUST be accompanied by an addition to the matrix in + // .github/workflows/ci.yml. + if compiler.minor >= 44 { + println!("cargo:rustc-cfg=path_buf_capacity"); + } +} + +struct Compiler { + minor: u32, +} + +fn rustc_version() -> Option<Compiler> { + let rustc = env::var_os("RUSTC")?; + let output = Command::new(rustc).arg("--version").output().ok()?; + let version = str::from_utf8(&output.stdout).ok()?; + let mut pieces = version.split('.'); + if pieces.next() != Some("rustc 1") { + return None; + } + let minor = pieces.next()?.parse().ok()?; + Some(Compiler { minor }) +} diff --git a/vendor/camino/clippy.toml b/vendor/camino/clippy.toml new file mode 100644 index 0000000000..b32f6d50a4 --- /dev/null +++ b/vendor/camino/clippy.toml @@ -0,0 +1 @@ +msrv = "1.34.0" diff --git a/vendor/camino/examples/serde.rs b/vendor/camino/examples/serde.rs new file mode 100644 index 0000000000..27037c52da --- /dev/null +++ b/vendor/camino/examples/serde.rs @@ -0,0 +1,64 @@ +// Copyright (c) The camino Contributors +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use anyhow::Result; +use camino::{Utf8Path, Utf8PathBuf}; +use serde::{Deserialize, Serialize}; +use std::borrow::Cow; + +/// This example demonstrates how to use a `Utf8Path` in a `serde` struct. +/// +/// With the `serde1` feature, `camino` paths can be used as targets for `serde` serialization and +/// deserialization. (Note that serde itself [does not support] parsing non-UTF-8 `PathBuf`s, so +/// there is no loss of generality in switching to `Utf8PathBuf` instances.) +/// +/// To run this example, run `cargo run --features serde1 --example serde`. +/// +/// [does not support]: https://docs.rs/crate/serde/1.0.123/source/src/de/impls.rs +#[derive(Serialize, Deserialize)] +struct MyStruct { + input: Utf8PathBuf, + output: Utf8PathBuf, +} + +/// A borrowed version of `MyStruct`, to demonstrate zero-copy deserialization to `Utf8Path`s. +#[derive(Serialize, Deserialize)] +struct MyStructBorrowed<'a> { + #[serde(borrow)] + input: &'a Utf8Path, + // Note: This always deserializes to an owned string because of + // https://github.com/serde-rs/serde/issues/1852. In the future we may add a `camino-utils` + // library with a `CowUtf8Path<'a>` wrapper which can deserialize to the borrowed implementation + // if possible. + #[serde(borrow)] + output: Cow<'a, Utf8Path>, +} + +static JSON_STR: &str = "{ \"input\": \"/foo/bar\", \"output\": \"/baz\\\\/quux\" }"; +pub fn main() -> Result<()> { + println!("*** json string: {}", JSON_STR); + + println!("*** Trying deserialize..."); + + // Deserialize to MyStruct. + let deserialized: MyStruct = serde_json::from_str(JSON_STR)?; + assert_eq!(deserialized.input, "/foo/bar"); + assert_eq!(deserialized.output, "/baz\\/quux"); + + println!("*** Trying serialize..."); + let serialized = serde_json::to_string_pretty(&deserialized)?; + println!("serialize output: {}", serialized); + + println!("*** Trying zero-copy deserialize..."); + + // Zero-copy deserialize to MyStructBorrowed. + let zero_copy: MyStructBorrowed<'_> = serde_json::from_str(JSON_STR)?; + assert_eq!(zero_copy.input, "/foo/bar"); + assert_eq!(zero_copy.output.as_str(), "/baz\\/quux"); + + println!("*** Trying zero-copy serialize..."); + let serialized = serde_json::to_string_pretty(&zero_copy)?; + println!("serialize output: {}", serialized); + + Ok(()) +} diff --git a/vendor/camino/examples/structopt.rs b/vendor/camino/examples/structopt.rs new file mode 100644 index 0000000000..da03733085 --- /dev/null +++ b/vendor/camino/examples/structopt.rs @@ -0,0 +1,33 @@ +// Copyright (c) The camino Contributors +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use camino::Utf8PathBuf; +use structopt::StructOpt; + +/// This example shows how a `Utf8Path` can be used with `structopt` argument parsing. +/// +/// Using a `Utf8Path` in argument parsing in this manner means that non-UTF-8 paths can be rejected +/// at the boundaries of your program. +/// +/// To run this example, run `cargo run --example structopt`. +#[derive(StructOpt)] +#[structopt(rename_all = "kebab-case")] +struct Opt { + /// Input file + input: Utf8PathBuf, + + /// Output file + output: Option<Utf8PathBuf>, +} + +pub fn main() { + // Parse the arguments. + let opt = Opt::from_args(); + + // Print the input and output files. + println!("input file: {}", opt.input); + match &opt.output { + Some(output) => println!("output file: {}", output), + None => println!("no output file"), + } +} diff --git a/vendor/camino/rustfmt.toml b/vendor/camino/rustfmt.toml new file mode 100644 index 0000000000..80eeb4054d --- /dev/null +++ b/vendor/camino/rustfmt.toml @@ -0,0 +1,2 @@ +edition = "2018" +use_field_init_shorthand = true diff --git a/vendor/camino/src/lib.rs b/vendor/camino/src/lib.rs new file mode 100644 index 0000000000..cd02b38b4c --- /dev/null +++ b/vendor/camino/src/lib.rs @@ -0,0 +1,2458 @@ +// Copyright (c) The camino Contributors +// SPDX-License-Identifier: MIT OR Apache-2.0 + +#![warn(missing_docs)] + +//! UTF-8 encoded paths. +//! +//! `camino` is an extension of the `std::path` module that adds new `Utf8PathBuf` and `Utf8Path` +//! types. These are like the standard library's [`PathBuf`] and [`Path`] types, except they are +//! guaranteed to only contain UTF-8 encoded data. Therefore, they expose the ability to get their +//! contents as strings, they implement `Display`, etc. +//! +//! The `std::path` types are not guaranteed to be valid UTF-8. This is the right decision for the standard library, +//! since it must be as general as possible. However, on all platforms, non-Unicode paths are vanishingly uncommon for a +//! number of reasons: +//! * Unicode won. There are still some legacy codebases that store paths in encodings like Shift-JIS, but most +//! have been converted to Unicode at this point. +//! * Unicode is the common subset of supported paths across Windows and Unix platforms. (On Windows, Rust stores paths +//! as [an extension to UTF-8](https://simonsapin.github.io/wtf-8/), and converts them to UTF-16 at Win32 +//! API boundaries.) +//! * There are already many systems, such as Cargo, that only support UTF-8 paths. If your own tool interacts with any such +//! system, you can assume that paths are valid UTF-8 without creating any additional burdens on consumers. +//! * The ["makefile problem"](https://www.mercurial-scm.org/wiki/EncodingStrategy#The_.22makefile_problem.22) +//! (which also applies to `Cargo.toml`, and any other metadata file that lists the names of other files) has *no general, +//! cross-platform solution* in systems that support non-UTF-8 paths. However, restricting paths to UTF-8 eliminates +//! this problem. +//! +//! Therefore, many programs that want to manipulate paths *do* assume they contain UTF-8 data, and convert them to `str`s +//! as necessary. However, because this invariant is not encoded in the `Path` type, conversions such as +//! `path.to_str().unwrap()` need to be repeated again and again, creating a frustrating experience. +//! +//! Instead, `camino` allows you to check that your paths are UTF-8 *once*, and then manipulate them +//! as valid UTF-8 from there on, avoiding repeated lossy and confusing conversions. + +use std::{ + borrow::{Borrow, Cow}, + cmp::Ordering, + convert::{Infallible, TryFrom}, + error, + ffi::{OsStr, OsString}, + fmt, fs, + hash::{Hash, Hasher}, + io, + iter::FusedIterator, + ops::Deref, + path::*, + rc::Rc, + str::FromStr, + sync::Arc, +}; + +#[cfg(feature = "serde1")] +mod serde_impls; +#[cfg(test)] +mod tests; + +/// An owned, mutable UTF-8 path (akin to [`String`]). +/// +/// This type provides methods like [`push`] and [`set_extension`] that mutate +/// the path in place. It also implements [`Deref`] to [`Utf8Path`], meaning that +/// all methods on [`Utf8Path`] slices are available on `Utf8PathBuf` values as well. +/// +/// [`push`]: Utf8PathBuf::push +/// [`set_extension`]: Utf8PathBuf::set_extension +/// +/// # Examples +/// +/// You can use [`push`] to build up a `Utf8PathBuf` from +/// components: +/// +/// ``` +/// use camino::Utf8PathBuf; +/// +/// let mut path = Utf8PathBuf::new(); +/// +/// path.push(r"C:\"); +/// path.push("windows"); +/// path.push("system32"); +/// +/// path.set_extension("dll"); +/// ``` +/// +/// However, [`push`] is best used for dynamic situations. This is a better way +/// to do this when you know all of the components ahead of time: +/// +/// ``` +/// use camino::Utf8PathBuf; +/// +/// let path: Utf8PathBuf = [r"C:\", "windows", "system32.dll"].iter().collect(); +/// ``` +/// +/// We can still do better than this! Since these are all strings, we can use +/// `From::from`: +/// +/// ``` +/// use camino::Utf8PathBuf; +/// +/// let path = Utf8PathBuf::from(r"C:\windows\system32.dll"); +/// ``` +/// +/// Which method works best depends on what kind of situation you're in. +// NB: Internal PathBuf must only contain utf8 data +#[derive(Clone, Default)] +#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde1", serde(transparent))] +#[repr(transparent)] +pub struct Utf8PathBuf(PathBuf); + +impl Utf8PathBuf { + /// Allocates an empty `Utf8PathBuf`. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8PathBuf; + /// + /// let path = Utf8PathBuf::new(); + /// ``` + pub fn new() -> Utf8PathBuf { + Utf8PathBuf(PathBuf::new()) + } + + /// Creates a new `Utf8PathBuf` from a `PathBuf` containing valid UTF-8 characters. + /// + /// Errors with the original `PathBuf` if it is not valid UTF-8. + /// + /// For a version that returns a type that implements [`std::error::Error`], use the + /// `TryFrom<PathBuf>` impl. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8PathBuf; + /// use std::ffi::OsStr; + /// # #[cfg(unix)] + /// use std::os::unix::ffi::OsStrExt; + /// use std::path::PathBuf; + /// + /// let unicode_path = PathBuf::from("/valid/unicode"); + /// Utf8PathBuf::from_path_buf(unicode_path).expect("valid Unicode path succeeded"); + /// + /// // Paths on Unix can be non-UTF-8. + /// # #[cfg(unix)] + /// let non_unicode_str = OsStr::from_bytes(b"\xFF\xFF\xFF"); + /// # #[cfg(unix)] + /// let non_unicode_path = PathBuf::from(non_unicode_str); + /// # #[cfg(unix)] + /// Utf8PathBuf::from_path_buf(non_unicode_path).expect_err("non-Unicode path failed"); + /// ``` + pub fn from_path_buf(path: PathBuf) -> Result<Utf8PathBuf, PathBuf> { + match path.into_os_string().into_string() { + Ok(string) => Ok(Utf8PathBuf::from(string)), + Err(os_string) => Err(PathBuf::from(os_string)), + } + } + + /// Converts a `Utf8PathBuf` to a [`PathBuf`]. + /// + /// This is equivalent to the `From<Utf8PathBuf> for PathBuf` impl, but may aid in type + /// inference. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8PathBuf; + /// use std::path::PathBuf; + /// + /// let utf8_path_buf = Utf8PathBuf::from("foo.txt"); + /// let std_path_buf = utf8_path_buf.into_std_path_buf(); + /// assert_eq!(std_path_buf.to_str(), Some("foo.txt")); + /// + /// // Convert back to a Utf8PathBuf. + /// let new_utf8_path_buf = Utf8PathBuf::from_path_buf(std_path_buf).unwrap(); + /// assert_eq!(new_utf8_path_buf, "foo.txt"); + /// ``` + pub fn into_std_path_buf(self) -> PathBuf { + self.into() + } + + /// Creates a new `Utf8PathBuf` with a given capacity used to create the internal [`PathBuf`]. + /// See [`with_capacity`] defined on [`PathBuf`]. + /// + /// *Requires Rust 1.44 or newer.* + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8PathBuf; + /// + /// let mut path = Utf8PathBuf::with_capacity(10); + /// let capacity = path.capacity(); + /// + /// // This push is done without reallocating + /// path.push(r"C:\"); + /// + /// assert_eq!(capacity, path.capacity()); + /// ``` + /// + /// [`with_capacity`]: PathBuf::with_capacity + #[cfg(path_buf_capacity)] + pub fn with_capacity(capacity: usize) -> Utf8PathBuf { + Utf8PathBuf(PathBuf::with_capacity(capacity)) + } + + /// Coerces to a [`Utf8Path`] slice. + /// + /// # Examples + /// + /// ``` + /// use camino::{Utf8Path, Utf8PathBuf}; + /// + /// let p = Utf8PathBuf::from("/test"); + /// assert_eq!(Utf8Path::new("/test"), p.as_path()); + /// ``` + pub fn as_path(&self) -> &Utf8Path { + // SAFETY: every Utf8PathBuf constructor ensures that self is valid UTF-8 + unsafe { Utf8Path::assume_utf8(&*self.0) } + } + + /// Extends `self` with `path`. + /// + /// If `path` is absolute, it replaces the current path. + /// + /// On Windows: + /// + /// * if `path` has a root but no prefix (e.g., `\windows`), it + /// replaces everything except for the prefix (if any) of `self`. + /// * if `path` has a prefix but no root, it replaces `self`. + /// + /// # Examples + /// + /// Pushing a relative path extends the existing path: + /// + /// ``` + /// use camino::Utf8PathBuf; + /// + /// let mut path = Utf8PathBuf::from("/tmp"); + /// path.push("file.bk"); + /// assert_eq!(path, Utf8PathBuf::from("/tmp/file.bk")); + /// ``` + /// + /// Pushing an absolute path replaces the existing path: + /// + /// ``` + /// use camino::Utf8PathBuf; + /// + /// let mut path = Utf8PathBuf::from("/tmp"); + /// path.push("/etc"); + /// assert_eq!(path, Utf8PathBuf::from("/etc")); + /// ``` + pub fn push(&mut self, path: impl AsRef<Utf8Path>) { + self.0.push(&path.as_ref().0) + } + + /// Truncates `self` to [`self.parent`]. + /// + /// Returns `false` and does nothing if [`self.parent`] is [`None`]. + /// Otherwise, returns `true`. + /// + /// [`self.parent`]: Utf8Path::parent + /// + /// # Examples + /// + /// ``` + /// use camino::{Utf8Path, Utf8PathBuf}; + /// + /// let mut p = Utf8PathBuf::from("/spirited/away.rs"); + /// + /// p.pop(); + /// assert_eq!(Utf8Path::new("/spirited"), p); + /// p.pop(); + /// assert_eq!(Utf8Path::new("/"), p); + /// ``` + pub fn pop(&mut self) -> bool { + self.0.pop() + } + + /// Updates [`self.file_name`] to `file_name`. + /// + /// If [`self.file_name`] was [`None`], this is equivalent to pushing + /// `file_name`. + /// + /// Otherwise it is equivalent to calling [`pop`] and then pushing + /// `file_name`. The new path will be a sibling of the original path. + /// (That is, it will have the same parent.) + /// + /// [`self.file_name`]: Utf8Path::file_name + /// [`pop`]: Utf8PathBuf::pop + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8PathBuf; + /// + /// let mut buf = Utf8PathBuf::from("/"); + /// assert_eq!(buf.file_name(), None); + /// buf.set_file_name("bar"); + /// assert_eq!(buf, Utf8PathBuf::from("/bar")); + /// assert!(buf.file_name().is_some()); + /// buf.set_file_name("baz.txt"); + /// assert_eq!(buf, Utf8PathBuf::from("/baz.txt")); + /// ``` + pub fn set_file_name(&mut self, file_name: impl AsRef<str>) { + self.0.set_file_name(file_name.as_ref()) + } + + /// Updates [`self.extension`] to `extension`. + /// + /// Returns `false` and does nothing if [`self.file_name`] is [`None`], + /// returns `true` and updates the extension otherwise. + /// + /// If [`self.extension`] is [`None`], the extension is added; otherwise + /// it is replaced. + /// + /// [`self.file_name`]: Utf8Path::file_name + /// [`self.extension`]: Utf8Path::extension + /// + /// # Examples + /// + /// ``` + /// use camino::{Utf8Path, Utf8PathBuf}; + /// + /// let mut p = Utf8PathBuf::from("/feel/the"); + /// + /// p.set_extension("force"); + /// assert_eq!(Utf8Path::new("/feel/the.force"), p.as_path()); + /// + /// p.set_extension("dark_side"); + /// assert_eq!(Utf8Path::new("/feel/the.dark_side"), p.as_path()); + /// ``` + pub fn set_extension(&mut self, extension: impl AsRef<str>) -> bool { + self.0.set_extension(extension.as_ref()) + } + + /// Consumes the `Utf8PathBuf`, yielding its internal [`String`] storage. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8PathBuf; + /// + /// let p = Utf8PathBuf::from("/the/head"); + /// let s = p.into_string(); + /// assert_eq!(s, "/the/head"); + /// ``` + pub fn into_string(self) -> String { + self.into_os_string().into_string().unwrap() + } + + /// Consumes the `Utf8PathBuf`, yielding its internal [`OsString`] storage. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8PathBuf; + /// use std::ffi::OsStr; + /// + /// let p = Utf8PathBuf::from("/the/head"); + /// let s = p.into_os_string(); + /// assert_eq!(s, OsStr::new("/the/head")); + /// ``` + pub fn into_os_string(self) -> OsString { + self.0.into_os_string() + } + + /// Converts this `Utf8PathBuf` into a [boxed](Box) [`Utf8Path`]. + pub fn into_boxed_path(self) -> Box<Utf8Path> { + let ptr = Box::into_raw(self.0.into_boxed_path()) as *mut Utf8Path; + // SAFETY: + // * self is valid UTF-8 + // * ptr was constructed by consuming self so it represents an owned path + // * Utf8Path is marked as #[repr(transparent)] so the conversion from *mut Path to + // *mut Utf8Path is valid + unsafe { Box::from_raw(ptr) } + } + + /// Invokes [`capacity`] on the underlying instance of [`PathBuf`]. + /// + /// *Requires Rust 1.44 or newer.* + /// + /// [`capacity`]: PathBuf::capacity + #[cfg(path_buf_capacity)] + pub fn capacity(&self) -> usize { + self.0.capacity() + } + + /// Invokes [`clear`] on the underlying instance of [`PathBuf`]. + /// + /// *Requires Rust 1.44 or newer.* + /// + /// [`clear`]: PathBuf::clear + #[cfg(path_buf_capacity)] + pub fn clear(&mut self) { + self.0.clear() + } + + /// Invokes [`reserve`] on the underlying instance of [`PathBuf`]. + /// + /// *Requires Rust 1.44 or newer.* + /// + /// [`reserve`]: PathBuf::reserve + #[cfg(path_buf_capacity)] + pub fn reserve(&mut self, additional: usize) { + self.0.reserve(additional) + } + + /// Invokes [`reserve_exact`] on the underlying instance of [`PathBuf`]. + /// + /// *Requires Rust 1.44 or newer.* + /// + /// [`reserve_exact`]: PathBuf::reserve_exact + #[cfg(path_buf_capacity)] + pub fn reserve_exact(&mut self, additional: usize) { + self.0.reserve_exact(additional) + } + + /// Invokes [`shrink_to_fit`] on the underlying instance of [`PathBuf`]. + /// + /// *Requires Rust 1.44 or newer.* + /// + /// [`shrink_to_fit`]: PathBuf::shrink_to_fit + #[cfg(path_buf_capacity)] + pub fn shrink_to_fit(&mut self) { + self.0.shrink_to_fit() + } +} + +impl Deref for Utf8PathBuf { + type Target = Utf8Path; + + fn deref(&self) -> &Utf8Path { + self.as_path() + } +} + +impl fmt::Debug for Utf8PathBuf { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +impl fmt::Display for Utf8PathBuf { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self.as_str(), f) + } +} + +impl<P: AsRef<Utf8Path>> Extend<P> for Utf8PathBuf { + fn extend<I: IntoIterator<Item = P>>(&mut self, iter: I) { + for path in iter { + self.push(path); + } + } +} + +/// A slice of a UTF-8 path (akin to [`str`]). +/// +/// This type supports a number of operations for inspecting a path, including +/// breaking the path into its components (separated by `/` on Unix and by either +/// `/` or `\` on Windows), extracting the file name, determining whether the path +/// is absolute, and so on. +/// +/// This is an *unsized* type, meaning that it must always be used behind a +/// pointer like `&` or [`Box`]. For an owned version of this type, +/// see [`Utf8PathBuf`]. +/// +/// # Examples +/// +/// ``` +/// use camino::Utf8Path; +/// +/// // Note: this example does work on Windows +/// let path = Utf8Path::new("./foo/bar.txt"); +/// +/// let parent = path.parent(); +/// assert_eq!(parent, Some(Utf8Path::new("./foo"))); +/// +/// let file_stem = path.file_stem(); +/// assert_eq!(file_stem, Some("bar")); +/// +/// let extension = path.extension(); +/// assert_eq!(extension, Some("txt")); +/// ``` +// NB: Internal Path must only contain utf8 data +#[repr(transparent)] +pub struct Utf8Path(Path); + +impl Utf8Path { + /// Directly wraps a string slice as a `Utf8Path` slice. + /// + /// This is a cost-free conversion. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// Utf8Path::new("foo.txt"); + /// ``` + /// + /// You can create `Utf8Path`s from `String`s, or even other `Utf8Path`s: + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let string = String::from("foo.txt"); + /// let from_string = Utf8Path::new(&string); + /// let from_path = Utf8Path::new(&from_string); + /// assert_eq!(from_string, from_path); + /// ``` + pub fn new(s: &(impl AsRef<str> + ?Sized)) -> &Utf8Path { + let path = Path::new(s.as_ref()); + // SAFETY: s is a str which means it is always valid UTF-8 + unsafe { Utf8Path::assume_utf8(path) } + } + + /// Converts a [`Path`] to a `Utf8Path`. + /// + /// Returns `None` if the path is not valid UTF-8. + /// + /// For a version that returns a type that implements [`std::error::Error`], use the + /// `TryFrom<&Path>` impl. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// use std::ffi::OsStr; + /// # #[cfg(unix)] + /// use std::os::unix::ffi::OsStrExt; + /// use std::path::Path; + /// + /// let unicode_path = Path::new("/valid/unicode"); + /// Utf8Path::from_path(unicode_path).expect("valid Unicode path succeeded"); + /// + /// // Paths on Unix can be non-UTF-8. + /// # #[cfg(unix)] + /// let non_unicode_str = OsStr::from_bytes(b"\xFF\xFF\xFF"); + /// # #[cfg(unix)] + /// let non_unicode_path = Path::new(non_unicode_str); + /// # #[cfg(unix)] + /// assert!(Utf8Path::from_path(non_unicode_path).is_none(), "non-Unicode path failed"); + /// ``` + pub fn from_path(path: &Path) -> Option<&Utf8Path> { + path.as_os_str().to_str().map(|s| Utf8Path::new(s)) + } + + /// Converts a `Utf8Path` to a [`Path`]. + /// + /// This is equivalent to the `AsRef<&Path> for &Utf8Path` impl, but may aid in type inference. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// use std::path::Path; + /// + /// let utf8_path = Utf8Path::new("foo.txt"); + /// let std_path: &Path = utf8_path.as_std_path(); + /// assert_eq!(std_path.to_str(), Some("foo.txt")); + /// + /// // Convert back to a Utf8Path. + /// let new_utf8_path = Utf8Path::from_path(std_path).unwrap(); + /// assert_eq!(new_utf8_path, "foo.txt"); + /// ``` + pub fn as_std_path(&self) -> &Path { + self.as_ref() + } + + /// Yields the underlying [`str`] slice. + /// + /// Unlike [`Path::to_str`], this always returns a slice because the contents of a `Utf8Path` + /// are guaranteed to be valid UTF-8. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let s = Utf8Path::new("foo.txt").as_str(); + /// assert_eq!(s, "foo.txt"); + /// ``` + /// + /// [`str`]: str + pub fn as_str(&self) -> &str { + // SAFETY: every Utf8Path constructor ensures that self is valid UTF-8 + unsafe { assume_utf8(self.as_os_str()) } + } + + /// Yields the underlying [`OsStr`] slice. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let os_str = Utf8Path::new("foo.txt").as_os_str(); + /// assert_eq!(os_str, std::ffi::OsStr::new("foo.txt")); + /// ``` + pub fn as_os_str(&self) -> &OsStr { + self.0.as_os_str() + } + + /// Converts a `Utf8Path` to an owned [`Utf8PathBuf`]. + /// + /// # Examples + /// + /// ``` + /// use camino::{Utf8Path, Utf8PathBuf}; + /// + /// let path_buf = Utf8Path::new("foo.txt").to_path_buf(); + /// assert_eq!(path_buf, Utf8PathBuf::from("foo.txt")); + /// ``` + pub fn to_path_buf(&self) -> Utf8PathBuf { + Utf8PathBuf(self.0.to_path_buf()) + } + + /// Returns `true` if the `Utf8Path` is absolute, i.e., if it is independent of + /// the current directory. + /// + /// * On Unix, a path is absolute if it starts with the root, so + /// `is_absolute` and [`has_root`] are equivalent. + /// + /// * On Windows, a path is absolute if it has a prefix and starts with the + /// root: `c:\windows` is absolute, while `c:temp` and `\temp` are not. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// assert!(!Utf8Path::new("foo.txt").is_absolute()); + /// ``` + /// + /// [`has_root`]: Utf8Path::has_root + pub fn is_absolute(&self) -> bool { + self.0.is_absolute() + } + + /// Returns `true` if the `Utf8Path` is relative, i.e., not absolute. + /// + /// See [`is_absolute`]'s documentation for more details. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// assert!(Utf8Path::new("foo.txt").is_relative()); + /// ``` + /// + /// [`is_absolute`]: Utf8Path::is_absolute + pub fn is_relative(&self) -> bool { + self.0.is_relative() + } + + /// Returns `true` if the `Utf8Path` has a root. + /// + /// * On Unix, a path has a root if it begins with `/`. + /// + /// * On Windows, a path has a root if it: + /// * has no prefix and begins with a separator, e.g., `\windows` + /// * has a prefix followed by a separator, e.g., `c:\windows` but not `c:windows` + /// * has any non-disk prefix, e.g., `\\server\share` + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// assert!(Utf8Path::new("/etc/passwd").has_root()); + /// ``` + pub fn has_root(&self) -> bool { + self.0.has_root() + } + + /// Returns the `Path` without its final component, if there is one. + /// + /// Returns [`None`] if the path terminates in a root or prefix. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let path = Utf8Path::new("/foo/bar"); + /// let parent = path.parent().unwrap(); + /// assert_eq!(parent, Utf8Path::new("/foo")); + /// + /// let grand_parent = parent.parent().unwrap(); + /// assert_eq!(grand_parent, Utf8Path::new("/")); + /// assert_eq!(grand_parent.parent(), None); + /// ``` + pub fn parent(&self) -> Option<&Utf8Path> { + self.0.parent().map(|path| { + // SAFETY: self is valid UTF-8, so parent is valid UTF-8 as well + unsafe { Utf8Path::assume_utf8(path) } + }) + } + + /// Produces an iterator over `Utf8Path` and its ancestors. + /// + /// The iterator will yield the `Utf8Path` that is returned if the [`parent`] method is used zero + /// or more times. That means, the iterator will yield `&self`, `&self.parent().unwrap()`, + /// `&self.parent().unwrap().parent().unwrap()` and so on. If the [`parent`] method returns + /// [`None`], the iterator will do likewise. The iterator will always yield at least one value, + /// namely `&self`. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let mut ancestors = Utf8Path::new("/foo/bar").ancestors(); + /// assert_eq!(ancestors.next(), Some(Utf8Path::new("/foo/bar"))); + /// assert_eq!(ancestors.next(), Some(Utf8Path::new("/foo"))); + /// assert_eq!(ancestors.next(), Some(Utf8Path::new("/"))); + /// assert_eq!(ancestors.next(), None); + /// + /// let mut ancestors = Utf8Path::new("../foo/bar").ancestors(); + /// assert_eq!(ancestors.next(), Some(Utf8Path::new("../foo/bar"))); + /// assert_eq!(ancestors.next(), Some(Utf8Path::new("../foo"))); + /// assert_eq!(ancestors.next(), Some(Utf8Path::new(".."))); + /// assert_eq!(ancestors.next(), Some(Utf8Path::new(""))); + /// assert_eq!(ancestors.next(), None); + /// ``` + /// + /// [`parent`]: Utf8Path::parent + pub fn ancestors(&self) -> Utf8Ancestors<'_> { + Utf8Ancestors(self.0.ancestors()) + } + + /// Returns the final component of the `Utf8Path`, if there is one. + /// + /// If the path is a normal file, this is the file name. If it's the path of a directory, this + /// is the directory name. + /// + /// Returns [`None`] if the path terminates in `..`. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// assert_eq!(Some("bin"), Utf8Path::new("/usr/bin/").file_name()); + /// assert_eq!(Some("foo.txt"), Utf8Path::new("tmp/foo.txt").file_name()); + /// assert_eq!(Some("foo.txt"), Utf8Path::new("foo.txt/.").file_name()); + /// assert_eq!(Some("foo.txt"), Utf8Path::new("foo.txt/.//").file_name()); + /// assert_eq!(None, Utf8Path::new("foo.txt/..").file_name()); + /// assert_eq!(None, Utf8Path::new("/").file_name()); + /// ``` + pub fn file_name(&self) -> Option<&str> { + self.0.file_name().map(|s| { + // SAFETY: self is valid UTF-8, so file_name is valid UTF-8 as well + unsafe { assume_utf8(s) } + }) + } + + /// Returns a path that, when joined onto `base`, yields `self`. + /// + /// # Errors + /// + /// If `base` is not a prefix of `self` (i.e., [`starts_with`] + /// returns `false`), returns [`Err`]. + /// + /// [`starts_with`]: Utf8Path::starts_with + /// + /// # Examples + /// + /// ``` + /// use camino::{Utf8Path, Utf8PathBuf}; + /// + /// let path = Utf8Path::new("/test/haha/foo.txt"); + /// + /// assert_eq!(path.strip_prefix("/"), Ok(Utf8Path::new("test/haha/foo.txt"))); + /// assert_eq!(path.strip_prefix("/test"), Ok(Utf8Path::new("haha/foo.txt"))); + /// assert_eq!(path.strip_prefix("/test/"), Ok(Utf8Path::new("haha/foo.txt"))); + /// assert_eq!(path.strip_prefix("/test/haha/foo.txt"), Ok(Utf8Path::new(""))); + /// assert_eq!(path.strip_prefix("/test/haha/foo.txt/"), Ok(Utf8Path::new(""))); + /// + /// assert!(path.strip_prefix("test").is_err()); + /// assert!(path.strip_prefix("/haha").is_err()); + /// + /// let prefix = Utf8PathBuf::from("/test/"); + /// assert_eq!(path.strip_prefix(prefix), Ok(Utf8Path::new("haha/foo.txt"))); + /// ``` + pub fn strip_prefix(&self, base: impl AsRef<Path>) -> Result<&Utf8Path, StripPrefixError> { + self.0.strip_prefix(base).map(|path| { + // SAFETY: self is valid UTF-8, and strip_prefix returns a part of self (or an empty + // string), so it is valid UTF-8 as well. + unsafe { Utf8Path::assume_utf8(path) } + }) + } + + /// Determines whether `base` is a prefix of `self`. + /// + /// Only considers whole path components to match. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let path = Utf8Path::new("/etc/passwd"); + /// + /// assert!(path.starts_with("/etc")); + /// assert!(path.starts_with("/etc/")); + /// assert!(path.starts_with("/etc/passwd")); + /// assert!(path.starts_with("/etc/passwd/")); // extra slash is okay + /// assert!(path.starts_with("/etc/passwd///")); // multiple extra slashes are okay + /// + /// assert!(!path.starts_with("/e")); + /// assert!(!path.starts_with("/etc/passwd.txt")); + /// + /// assert!(!Utf8Path::new("/etc/foo.rs").starts_with("/etc/foo")); + /// ``` + pub fn starts_with(&self, base: impl AsRef<Path>) -> bool { + self.0.starts_with(base) + } + + /// Determines whether `child` is a suffix of `self`. + /// + /// Only considers whole path components to match. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let path = Utf8Path::new("/etc/resolv.conf"); + /// + /// assert!(path.ends_with("resolv.conf")); + /// assert!(path.ends_with("etc/resolv.conf")); + /// assert!(path.ends_with("/etc/resolv.conf")); + /// + /// assert!(!path.ends_with("/resolv.conf")); + /// assert!(!path.ends_with("conf")); // use .extension() instead + /// ``` + pub fn ends_with(&self, base: impl AsRef<Path>) -> bool { + self.0.ends_with(base) + } + + /// Extracts the stem (non-extension) portion of [`self.file_name`]. + /// + /// [`self.file_name`]: Utf8Path::file_name + /// + /// The stem is: + /// + /// * [`None`], if there is no file name; + /// * The entire file name if there is no embedded `.`; + /// * The entire file name if the file name begins with `.` and has no other `.`s within; + /// * Otherwise, the portion of the file name before the final `.` + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// assert_eq!("foo", Utf8Path::new("foo.rs").file_stem().unwrap()); + /// assert_eq!("foo.tar", Utf8Path::new("foo.tar.gz").file_stem().unwrap()); + /// ``` + pub fn file_stem(&self) -> Option<&str> { + self.0.file_stem().map(|s| { + // SAFETY: self is valid UTF-8, so file_stem is valid UTF-8 as well + unsafe { assume_utf8(s) } + }) + } + + /// Extracts the extension of [`self.file_name`], if possible. + /// + /// The extension is: + /// + /// * [`None`], if there is no file name; + /// * [`None`], if there is no embedded `.`; + /// * [`None`], if the file name begins with `.` and has no other `.`s within; + /// * Otherwise, the portion of the file name after the final `.` + /// + /// [`self.file_name`]: Utf8Path::file_name + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// assert_eq!("rs", Utf8Path::new("foo.rs").extension().unwrap()); + /// assert_eq!("gz", Utf8Path::new("foo.tar.gz").extension().unwrap()); + /// ``` + pub fn extension(&self) -> Option<&str> { + self.0.extension().map(|s| { + // SAFETY: self is valid UTF-8, so extension is valid UTF-8 as well + unsafe { assume_utf8(s) } + }) + } + + /// Creates an owned [`Utf8PathBuf`] with `path` adjoined to `self`. + /// + /// See [`Utf8PathBuf::push`] for more details on what it means to adjoin a path. + /// + /// # Examples + /// + /// ``` + /// use camino::{Utf8Path, Utf8PathBuf}; + /// + /// assert_eq!(Utf8Path::new("/etc").join("passwd"), Utf8PathBuf::from("/etc/passwd")); + /// ``` + pub fn join(&self, path: impl AsRef<Utf8Path>) -> Utf8PathBuf { + Utf8PathBuf(self.0.join(&path.as_ref().0)) + } + + /// Creates an owned [`PathBuf`] with `path` adjoined to `self`. + /// + /// See [`PathBuf::push`] for more details on what it means to adjoin a path. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// use std::path::PathBuf; + /// + /// assert_eq!(Utf8Path::new("/etc").join_os("passwd"), PathBuf::from("/etc/passwd")); + /// ``` + pub fn join_os(&self, path: impl AsRef<Path>) -> PathBuf { + self.0.join(path) + } + + /// Creates an owned [`Utf8PathBuf`] like `self` but with the given file name. + /// + /// See [`Utf8PathBuf::set_file_name`] for more details. + /// + /// # Examples + /// + /// ``` + /// use camino::{Utf8Path, Utf8PathBuf}; + /// + /// let path = Utf8Path::new("/tmp/foo.txt"); + /// assert_eq!(path.with_file_name("bar.txt"), Utf8PathBuf::from("/tmp/bar.txt")); + /// + /// let path = Utf8Path::new("/tmp"); + /// assert_eq!(path.with_file_name("var"), Utf8PathBuf::from("/var")); + /// ``` + pub fn with_file_name(&self, file_name: impl AsRef<str>) -> Utf8PathBuf { + Utf8PathBuf(self.0.with_file_name(file_name.as_ref())) + } + + /// Creates an owned [`Utf8PathBuf`] like `self` but with the given extension. + /// + /// See [`Utf8PathBuf::set_extension`] for more details. + /// + /// # Examples + /// + /// ``` + /// use camino::{Utf8Path, Utf8PathBuf}; + /// + /// let path = Utf8Path::new("foo.rs"); + /// assert_eq!(path.with_extension("txt"), Utf8PathBuf::from("foo.txt")); + /// + /// let path = Utf8Path::new("foo.tar.gz"); + /// assert_eq!(path.with_extension(""), Utf8PathBuf::from("foo.tar")); + /// assert_eq!(path.with_extension("xz"), Utf8PathBuf::from("foo.tar.xz")); + /// assert_eq!(path.with_extension("").with_extension("txt"), Utf8PathBuf::from("foo.txt")); + /// ``` + pub fn with_extension(&self, extension: impl AsRef<str>) -> Utf8PathBuf { + Utf8PathBuf(self.0.with_extension(extension.as_ref())) + } + + /// Produces an iterator over the [`Utf8Component`]s of the path. + /// + /// When parsing the path, there is a small amount of normalization: + /// + /// * Repeated separators are ignored, so `a/b` and `a//b` both have + /// `a` and `b` as components. + /// + /// * Occurrences of `.` are normalized away, except if they are at the + /// beginning of the path. For example, `a/./b`, `a/b/`, `a/b/.` and + /// `a/b` all have `a` and `b` as components, but `./a/b` starts with + /// an additional [`CurDir`] component. + /// + /// * A trailing slash is normalized away, `/a/b` and `/a/b/` are equivalent. + /// + /// Note that no other normalization takes place; in particular, `a/c` + /// and `a/b/../c` are distinct, to account for the possibility that `b` + /// is a symbolic link (so its parent isn't `a`). + /// + /// # Examples + /// + /// ``` + /// use camino::{Utf8Component, Utf8Path}; + /// + /// let mut components = Utf8Path::new("/tmp/foo.txt").components(); + /// + /// assert_eq!(components.next(), Some(Utf8Component::RootDir)); + /// assert_eq!(components.next(), Some(Utf8Component::Normal("tmp"))); + /// assert_eq!(components.next(), Some(Utf8Component::Normal("foo.txt"))); + /// assert_eq!(components.next(), None) + /// ``` + /// + /// [`CurDir`]: Utf8Component::CurDir + pub fn components(&self) -> Utf8Components { + Utf8Components(self.0.components()) + } + + /// Produces an iterator over the path's components viewed as [`str`] + /// slices. + /// + /// For more information about the particulars of how the path is separated + /// into components, see [`components`]. + /// + /// [`components`]: Utf8Path::components + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let mut it = Utf8Path::new("/tmp/foo.txt").iter(); + /// assert_eq!(it.next(), Some(std::path::MAIN_SEPARATOR.to_string().as_str())); + /// assert_eq!(it.next(), Some("tmp")); + /// assert_eq!(it.next(), Some("foo.txt")); + /// assert_eq!(it.next(), None) + /// ``` + pub fn iter(&self) -> Iter<'_> { + Iter { + inner: self.components(), + } + } + + /// Queries the file system to get information about a file, directory, etc. + /// + /// This function will traverse symbolic links to query information about the + /// destination file. + /// + /// This is an alias to [`fs::metadata`]. + /// + /// # Examples + /// + /// ```no_run + /// use camino::Utf8Path; + /// + /// let path = Utf8Path::new("/Minas/tirith"); + /// let metadata = path.metadata().expect("metadata call failed"); + /// println!("{:?}", metadata.file_type()); + /// ``` + pub fn metadata(&self) -> io::Result<fs::Metadata> { + self.0.metadata() + } + + /// Queries the metadata about a file without following symlinks. + /// + /// This is an alias to [`fs::symlink_metadata`]. + /// + /// # Examples + /// + /// ```no_run + /// use camino::Utf8Path; + /// + /// let path = Utf8Path::new("/Minas/tirith"); + /// let metadata = path.symlink_metadata().expect("symlink_metadata call failed"); + /// println!("{:?}", metadata.file_type()); + /// ``` + pub fn symlink_metadata(&self) -> io::Result<fs::Metadata> { + self.0.symlink_metadata() + } + + /// Returns the canonical, absolute form of the path with all intermediate + /// components normalized and symbolic links resolved. + /// + /// This returns a [`PathBuf`] because even if a symlink is valid Unicode, its target may not + /// be. + /// + /// This is an alias to [`fs::canonicalize`]. + /// + /// # Examples + /// + /// ```no_run + /// use camino::Utf8Path; + /// use std::path::PathBuf; + /// + /// let path = Utf8Path::new("/foo/test/../test/bar.rs"); + /// assert_eq!(path.canonicalize().unwrap(), PathBuf::from("/foo/test/bar.rs")); + /// ``` + pub fn canonicalize(&self) -> io::Result<PathBuf> { + self.0.canonicalize() + } + + /// Reads a symbolic link, returning the file that the link points to. + /// + /// This returns a [`PathBuf`] because even if a symlink is valid Unicode, its target may not + /// be. + /// + /// This is an alias to [`fs::read_link`]. + /// + /// # Examples + /// + /// ```no_run + /// use camino::Utf8Path; + /// + /// let path = Utf8Path::new("/laputa/sky_castle.rs"); + /// let path_link = path.read_link().expect("read_link call failed"); + /// ``` + pub fn read_link(&self) -> io::Result<PathBuf> { + self.0.read_link() + } + + /// Returns an iterator over the entries within a directory. + /// + /// The iterator will yield instances of [`io::Result`]`<`[`fs::DirEntry`]`>`. New + /// errors may be encountered after an iterator is initially constructed. + /// + /// This is an alias to [`fs::read_dir`]. + /// + /// # Examples + /// + /// ```no_run + /// use camino::Utf8Path; + /// + /// let path = Utf8Path::new("/laputa"); + /// for entry in path.read_dir().expect("read_dir call failed") { + /// if let Ok(entry) = entry { + /// println!("{:?}", entry.path()); + /// } + /// } + /// ``` + pub fn read_dir(&self) -> io::Result<fs::ReadDir> { + self.0.read_dir() + } + + /// Returns `true` if the path points at an existing entity. + /// + /// This function will traverse symbolic links to query information about the + /// destination file. In case of broken symbolic links this will return `false`. + /// + /// If you cannot access the directory containing the file, e.g., because of a + /// permission error, this will return `false`. + /// + /// # Examples + /// + /// ```no_run + /// use camino::Utf8Path; + /// assert!(!Utf8Path::new("does_not_exist.txt").exists()); + /// ``` + /// + /// # See Also + /// + /// This is a convenience function that coerces errors to false. If you want to + /// check errors, call [`fs::metadata`]. + pub fn exists(&self) -> bool { + self.0.exists() + } + + /// Returns `true` if the path exists on disk and is pointing at a regular file. + /// + /// This function will traverse symbolic links to query information about the + /// destination file. In case of broken symbolic links this will return `false`. + /// + /// If you cannot access the directory containing the file, e.g., because of a + /// permission error, this will return `false`. + /// + /// # Examples + /// + /// ```no_run + /// use camino::Utf8Path; + /// assert_eq!(Utf8Path::new("./is_a_directory/").is_file(), false); + /// assert_eq!(Utf8Path::new("a_file.txt").is_file(), true); + /// ``` + /// + /// # See Also + /// + /// This is a convenience function that coerces errors to false. If you want to + /// check errors, call [`fs::metadata`] and handle its [`Result`]. Then call + /// [`fs::Metadata::is_file`] if it was [`Ok`]. + /// + /// When the goal is simply to read from (or write to) the source, the most + /// reliable way to test the source can be read (or written to) is to open + /// it. Only using `is_file` can break workflows like `diff <( prog_a )` on + /// a Unix-like system for example. See [`fs::File::open`] or + /// [`fs::OpenOptions::open`] for more information. + pub fn is_file(&self) -> bool { + self.0.is_file() + } + + /// Returns `true` if the path exists on disk and is pointing at a directory. + /// + /// This function will traverse symbolic links to query information about the + /// destination file. In case of broken symbolic links this will return `false`. + /// + /// If you cannot access the directory containing the file, e.g., because of a + /// permission error, this will return `false`. + /// + /// # Examples + /// + /// ```no_run + /// use camino::Utf8Path; + /// assert_eq!(Utf8Path::new("./is_a_directory/").is_dir(), true); + /// assert_eq!(Utf8Path::new("a_file.txt").is_dir(), false); + /// ``` + /// + /// # See Also + /// + /// This is a convenience function that coerces errors to false. If you want to + /// check errors, call [`fs::metadata`] and handle its [`Result`]. Then call + /// [`fs::Metadata::is_dir`] if it was [`Ok`]. + pub fn is_dir(&self) -> bool { + self.0.is_dir() + } + + /// Converts a `Box<Utf8Path>` into a [`Utf8PathBuf`] without copying or allocating. + pub fn into_path_buf(self: Box<Utf8Path>) -> Utf8PathBuf { + let ptr = Box::into_raw(self) as *mut Path; + // SAFETY: + // * self is valid UTF-8 + // * ptr was constructed by consuming self so it represents an owned path. + // * Utf8Path is marked as #[repr(transparent)] so the conversion from a *mut Utf8Path to a + // *mut Path is valid. + let boxed_path = unsafe { Box::from_raw(ptr) }; + Utf8PathBuf(boxed_path.into_path_buf()) + } + + // invariant: Path must be guaranteed to be utf-8 data + unsafe fn assume_utf8(path: &Path) -> &Utf8Path { + // SAFETY: Utf8Path is marked as #[repr(transparent)] so the conversion from a + // *const Path to a *const Utf8Path is valid. + &*(path as *const Path as *const Utf8Path) + } +} + +impl Clone for Box<Utf8Path> { + fn clone(&self) -> Self { + let boxed: Box<Path> = self.0.into(); + let ptr = Box::into_raw(boxed) as *mut Utf8Path; + // SAFETY: + // * self is valid UTF-8 + // * ptr was created by consuming a Box<Path> so it represents an rced pointer + // * Utf8Path is marked as #[repr(transparent)] so the conversion from *mut Path to + // *mut Utf8Path is valid + unsafe { Box::from_raw(ptr) } + } +} + +impl fmt::Display for Utf8Path { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self.as_str(), f) + } +} + +impl fmt::Debug for Utf8Path { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(self.as_str(), f) + } +} + +/// An iterator over [`Utf8Path`] and its ancestors. +/// +/// This `struct` is created by the [`ancestors`] method on [`Utf8Path`]. +/// See its documentation for more. +/// +/// # Examples +/// +/// ``` +/// use camino::Utf8Path; +/// +/// let path = Utf8Path::new("/foo/bar"); +/// +/// for ancestor in path.ancestors() { +/// println!("{}", ancestor); +/// } +/// ``` +/// +/// [`ancestors`]: Utf8Path::ancestors +#[derive(Copy, Clone)] +#[repr(transparent)] +pub struct Utf8Ancestors<'a>(Ancestors<'a>); + +impl<'a> fmt::Debug for Utf8Ancestors<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.0, f) + } +} + +impl<'a> Iterator for Utf8Ancestors<'a> { + type Item = &'a Utf8Path; + + fn next(&mut self) -> Option<Self::Item> { + self.0.next().map(|path| { + // SAFETY: Utf8Ancestors was constructed from a Utf8Path, so it is guaranteed to + // be valid UTF-8 + unsafe { Utf8Path::assume_utf8(path) } + }) + } +} + +impl<'a> FusedIterator for Utf8Ancestors<'a> {} + +/// An iterator over the [`Utf8Component`]s of a [`Utf8Path`]. +/// +/// This `struct` is created by the [`components`] method on [`Utf8Path`]. +/// See its documentation for more. +/// +/// # Examples +/// +/// ``` +/// use camino::Utf8Path; +/// +/// let path = Utf8Path::new("/tmp/foo/bar.txt"); +/// +/// for component in path.components() { +/// println!("{:?}", component); +/// } +/// ``` +/// +/// [`components`]: Utf8Path::components +#[derive(Clone, Eq, Ord, PartialEq, PartialOrd)] +pub struct Utf8Components<'a>(Components<'a>); + +impl<'a> Utf8Components<'a> { + /// Extracts a slice corresponding to the portion of the path remaining for iteration. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let mut components = Utf8Path::new("/tmp/foo/bar.txt").components(); + /// components.next(); + /// components.next(); + /// + /// assert_eq!(Utf8Path::new("foo/bar.txt"), components.as_path()); + /// ``` + pub fn as_path(&self) -> &'a Utf8Path { + // SAFETY: Utf8Components was constructed from a Utf8Path, so it is guaranteed to be valid + // UTF-8 + unsafe { Utf8Path::assume_utf8(self.0.as_path()) } + } +} + +impl<'a> Iterator for Utf8Components<'a> { + type Item = Utf8Component<'a>; + + fn next(&mut self) -> Option<Self::Item> { + self.0.next().map(|component| { + // SAFETY: Utf8Component was constructed from a Utf8Path, so it is guaranteed to be + // valid UTF-8 + unsafe { Utf8Component::new(component) } + }) + } +} + +impl<'a> FusedIterator for Utf8Components<'a> {} + +impl<'a> DoubleEndedIterator for Utf8Components<'a> { + fn next_back(&mut self) -> Option<Self::Item> { + self.0.next_back().map(|component| { + // SAFETY: Utf8Component was constructed from a Utf8Path, so it is guaranteed to be + // valid UTF-8 + unsafe { Utf8Component::new(component) } + }) + } +} + +impl<'a> fmt::Debug for Utf8Components<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.0, f) + } +} + +impl AsRef<Utf8Path> for Utf8Components<'_> { + fn as_ref(&self) -> &Utf8Path { + self.as_path() + } +} + +impl AsRef<Path> for Utf8Components<'_> { + fn as_ref(&self) -> &Path { + self.as_path().as_ref() + } +} + +impl AsRef<str> for Utf8Components<'_> { + fn as_ref(&self) -> &str { + self.as_path().as_ref() + } +} + +impl AsRef<OsStr> for Utf8Components<'_> { + fn as_ref(&self) -> &OsStr { + self.as_path().as_os_str() + } +} + +/// An iterator over the [`Utf8Component`]s of a [`Utf8Path`], as [`str`] slices. +/// +/// This `struct` is created by the [`iter`] method on [`Utf8Path`]. +/// See its documentation for more. +/// +/// [`iter`]: Utf8Path::iter +#[derive(Clone)] +pub struct Iter<'a> { + inner: Utf8Components<'a>, +} + +impl fmt::Debug for Iter<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + struct DebugHelper<'a>(&'a Utf8Path); + + impl fmt::Debug for DebugHelper<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self.0.iter()).finish() + } + } + + f.debug_tuple("Iter") + .field(&DebugHelper(self.as_path())) + .finish() + } +} + +impl<'a> Iter<'a> { + /// Extracts a slice corresponding to the portion of the path remaining for iteration. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let mut iter = Utf8Path::new("/tmp/foo/bar.txt").iter(); + /// iter.next(); + /// iter.next(); + /// + /// assert_eq!(Utf8Path::new("foo/bar.txt"), iter.as_path()); + /// ``` + pub fn as_path(&self) -> &'a Utf8Path { + self.inner.as_path() + } +} + +impl AsRef<Utf8Path> for Iter<'_> { + fn as_ref(&self) -> &Utf8Path { + self.as_path() + } +} + +impl AsRef<Path> for Iter<'_> { + fn as_ref(&self) -> &Path { + self.as_path().as_ref() + } +} + +impl AsRef<str> for Iter<'_> { + fn as_ref(&self) -> &str { + self.as_path().as_ref() + } +} + +impl AsRef<OsStr> for Iter<'_> { + fn as_ref(&self) -> &OsStr { + self.as_path().as_os_str() + } +} + +impl<'a> Iterator for Iter<'a> { + type Item = &'a str; + + fn next(&mut self) -> Option<&'a str> { + self.inner.next().map(|component| component.as_str()) + } +} + +impl<'a> DoubleEndedIterator for Iter<'a> { + fn next_back(&mut self) -> Option<&'a str> { + self.inner.next_back().map(|component| component.as_str()) + } +} + +impl FusedIterator for Iter<'_> {} + +/// A single component of a path. +/// +/// A `Utf8Component` roughly corresponds to a substring between path separators +/// (`/` or `\`). +/// +/// This `enum` is created by iterating over [`Utf8Components`], which in turn is +/// created by the [`components`](Utf8Path::components) method on [`Utf8Path`]. +/// +/// # Examples +/// +/// ```rust +/// use camino::{Utf8Component, Utf8Path}; +/// +/// let path = Utf8Path::new("/tmp/foo/bar.txt"); +/// let components = path.components().collect::<Vec<_>>(); +/// assert_eq!(&components, &[ +/// Utf8Component::RootDir, +/// Utf8Component::Normal("tmp"), +/// Utf8Component::Normal("foo"), +/// Utf8Component::Normal("bar.txt"), +/// ]); +/// ``` +#[derive(Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)] +pub enum Utf8Component<'a> { + /// A Windows path prefix, e.g., `C:` or `\\server\share`. + /// + /// There is a large variety of prefix types, see [`Utf8Prefix`]'s documentation + /// for more. + /// + /// Does not occur on Unix. + Prefix(Utf8PrefixComponent<'a>), + + /// The root directory component, appears after any prefix and before anything else. + /// + /// It represents a separator that designates that a path starts from root. + RootDir, + + /// A reference to the current directory, i.e., `.`. + CurDir, + + /// A reference to the parent directory, i.e., `..`. + ParentDir, + + /// A normal component, e.g., `a` and `b` in `a/b`. + /// + /// This variant is the most common one, it represents references to files + /// or directories. + Normal(&'a str), +} + +impl<'a> Utf8Component<'a> { + unsafe fn new(component: Component<'a>) -> Utf8Component<'a> { + match component { + Component::Prefix(prefix) => Utf8Component::Prefix(Utf8PrefixComponent(prefix)), + Component::RootDir => Utf8Component::RootDir, + Component::CurDir => Utf8Component::CurDir, + Component::ParentDir => Utf8Component::ParentDir, + Component::Normal(s) => Utf8Component::Normal(assume_utf8(s)), + } + } + + /// Extracts the underlying [`str`] slice. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let path = Utf8Path::new("./tmp/foo/bar.txt"); + /// let components: Vec<_> = path.components().map(|comp| comp.as_str()).collect(); + /// assert_eq!(&components, &[".", "tmp", "foo", "bar.txt"]); + /// ``` + pub fn as_str(&self) -> &'a str { + // SAFETY: Utf8Component was constructed from a Utf8Path, so it is guaranteed to be + // valid UTF-8 + unsafe { assume_utf8(self.as_os_str()) } + } + + /// Extracts the underlying [`OsStr`] slice. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let path = Utf8Path::new("./tmp/foo/bar.txt"); + /// let components: Vec<_> = path.components().map(|comp| comp.as_os_str()).collect(); + /// assert_eq!(&components, &[".", "tmp", "foo", "bar.txt"]); + /// ``` + pub fn as_os_str(&self) -> &'a OsStr { + match *self { + Utf8Component::Prefix(prefix) => prefix.as_os_str(), + Utf8Component::RootDir => Component::RootDir.as_os_str(), + Utf8Component::CurDir => Component::CurDir.as_os_str(), + Utf8Component::ParentDir => Component::ParentDir.as_os_str(), + Utf8Component::Normal(s) => OsStr::new(s), + } + } +} + +impl<'a> fmt::Debug for Utf8Component<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(self.as_os_str(), f) + } +} + +impl<'a> fmt::Display for Utf8Component<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self.as_str(), f) + } +} + +impl AsRef<Utf8Path> for Utf8Component<'_> { + fn as_ref(&self) -> &Utf8Path { + self.as_str().as_ref() + } +} + +impl AsRef<Path> for Utf8Component<'_> { + fn as_ref(&self) -> &Path { + self.as_os_str().as_ref() + } +} + +impl AsRef<str> for Utf8Component<'_> { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl AsRef<OsStr> for Utf8Component<'_> { + fn as_ref(&self) -> &OsStr { + self.as_os_str() + } +} + +/// Windows path prefixes, e.g., `C:` or `\\server\share`. +/// +/// Windows uses a variety of path prefix styles, including references to drive +/// volumes (like `C:`), network shared folders (like `\\server\share`), and +/// others. In addition, some path prefixes are "verbatim" (i.e., prefixed with +/// `\\?\`), in which case `/` is *not* treated as a separator and essentially +/// no normalization is performed. +/// +/// # Examples +/// +/// ``` +/// use camino::{Utf8Component, Utf8Path, Utf8Prefix}; +/// use camino::Utf8Prefix::*; +/// +/// fn get_path_prefix(s: &str) -> Utf8Prefix { +/// let path = Utf8Path::new(s); +/// match path.components().next().unwrap() { +/// Utf8Component::Prefix(prefix_component) => prefix_component.kind(), +/// _ => panic!(), +/// } +/// } +/// +/// # if cfg!(windows) { +/// assert_eq!(Verbatim("pictures"), get_path_prefix(r"\\?\pictures\kittens")); +/// assert_eq!(VerbatimUNC("server", "share"), get_path_prefix(r"\\?\UNC\server\share")); +/// assert_eq!(VerbatimDisk(b'C'), get_path_prefix(r"\\?\c:\")); +/// assert_eq!(DeviceNS("BrainInterface"), get_path_prefix(r"\\.\BrainInterface")); +/// assert_eq!(UNC("server", "share"), get_path_prefix(r"\\server\share")); +/// assert_eq!(Disk(b'C'), get_path_prefix(r"C:\Users\Rust\Pictures\Ferris")); +/// # } +/// ``` +#[derive(Copy, Clone, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)] +pub enum Utf8Prefix<'a> { + /// Verbatim prefix, e.g., `\\?\cat_pics`. + /// + /// Verbatim prefixes consist of `\\?\` immediately followed by the given + /// component. + Verbatim(&'a str), + + /// Verbatim prefix using Windows' _**U**niform **N**aming **C**onvention_, + /// e.g., `\\?\UNC\server\share`. + /// + /// Verbatim UNC prefixes consist of `\\?\UNC\` immediately followed by the + /// server's hostname and a share name. + VerbatimUNC(&'a str, &'a str), + + /// Verbatim disk prefix, e.g., `\\?\C:`. + /// + /// Verbatim disk prefixes consist of `\\?\` immediately followed by the + /// drive letter and `:`. + VerbatimDisk(u8), + + /// Device namespace prefix, e.g., `\\.\COM42`. + /// + /// Device namespace prefixes consist of `\\.\` immediately followed by the + /// device name. + DeviceNS(&'a str), + + /// Prefix using Windows' _**U**niform **N**aming **C**onvention_, e.g. + /// `\\server\share`. + /// + /// UNC prefixes consist of the server's hostname and a share name. + UNC(&'a str, &'a str), + + /// Prefix `C:` for the given disk drive. + Disk(u8), +} + +impl<'a> Utf8Prefix<'a> { + /// Determines if the prefix is verbatim, i.e., begins with `\\?\`. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Prefix::*; + /// + /// assert!(Verbatim("pictures").is_verbatim()); + /// assert!(VerbatimUNC("server", "share").is_verbatim()); + /// assert!(VerbatimDisk(b'C').is_verbatim()); + /// assert!(!DeviceNS("BrainInterface").is_verbatim()); + /// assert!(!UNC("server", "share").is_verbatim()); + /// assert!(!Disk(b'C').is_verbatim()); + /// ``` + pub fn is_verbatim(&self) -> bool { + use Utf8Prefix::*; + match self { + Verbatim(_) | VerbatimDisk(_) | VerbatimUNC(..) => true, + _ => false, + } + } +} + +/// A structure wrapping a Windows path prefix as well as its unparsed string +/// representation. +/// +/// In addition to the parsed [`Utf8Prefix`] information returned by [`kind`], +/// `Utf8PrefixComponent` also holds the raw and unparsed [`str`] slice, +/// returned by [`as_str`]. +/// +/// Instances of this `struct` can be obtained by matching against the +/// [`Prefix` variant] on [`Utf8Component`]. +/// +/// Does not occur on Unix. +/// +/// # Examples +/// +/// ``` +/// # if cfg!(windows) { +/// use camino::{Utf8Component, Utf8Path, Utf8Prefix}; +/// use std::ffi::OsStr; +/// +/// let path = Utf8Path::new(r"c:\you\later\"); +/// match path.components().next().unwrap() { +/// Utf8Component::Prefix(prefix_component) => { +/// assert_eq!(Utf8Prefix::Disk(b'C'), prefix_component.kind()); +/// assert_eq!("c:", prefix_component.as_str()); +/// } +/// _ => unreachable!(), +/// } +/// # } +/// ``` +/// +/// [`as_str`]: Utf8PrefixComponent::as_str +/// [`kind`]: Utf8PrefixComponent::kind +/// [`Prefix` variant]: Utf8Component::Prefix +#[repr(transparent)] +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd)] +pub struct Utf8PrefixComponent<'a>(PrefixComponent<'a>); + +impl<'a> Utf8PrefixComponent<'a> { + /// Returns the parsed prefix data. + /// + /// See [`Utf8Prefix`]'s documentation for more information on the different + /// kinds of prefixes. + pub fn kind(&self) -> Utf8Prefix<'a> { + // SAFETY for all the below unsafe blocks: the path self was originally constructed from was + // UTF-8 so any parts of it are valid UTF-8 + match self.0.kind() { + Prefix::Verbatim(prefix) => Utf8Prefix::Verbatim(unsafe { assume_utf8(prefix) }), + Prefix::VerbatimUNC(server, share) => { + let server = unsafe { assume_utf8(server) }; + let share = unsafe { assume_utf8(share) }; + Utf8Prefix::VerbatimUNC(server, share) + } + Prefix::VerbatimDisk(drive) => Utf8Prefix::VerbatimDisk(drive), + Prefix::DeviceNS(prefix) => Utf8Prefix::DeviceNS(unsafe { assume_utf8(prefix) }), + Prefix::UNC(server, share) => { + let server = unsafe { assume_utf8(server) }; + let share = unsafe { assume_utf8(share) }; + Utf8Prefix::UNC(server, share) + } + Prefix::Disk(drive) => Utf8Prefix::Disk(drive), + } + } + + /// Returns the [`str`] slice for this prefix. + pub fn as_str(&self) -> &'a str { + // SAFETY: Utf8PrefixComponent was constructed from a Utf8Path, so it is guaranteed to be + // valid UTF-8 + unsafe { assume_utf8(self.as_os_str()) } + } + + /// Returns the raw [`OsStr`] slice for this prefix. + pub fn as_os_str(&self) -> &'a OsStr { + self.0.as_os_str() + } +} + +impl<'a> fmt::Debug for Utf8PrefixComponent<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.0, f) + } +} + +impl<'a> fmt::Display for Utf8PrefixComponent<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self.as_str(), f) + } +} + +// --- + +impl From<String> for Utf8PathBuf { + fn from(string: String) -> Utf8PathBuf { + Utf8PathBuf(string.into()) + } +} + +impl FromStr for Utf8PathBuf { + type Err = Infallible; + + fn from_str(s: &str) -> Result<Self, Self::Err> { + Ok(Utf8PathBuf(s.into())) + } +} + +// --- +// From impls: borrowed -> borrowed +// --- + +impl<'a> From<&'a str> for &'a Utf8Path { + fn from(s: &'a str) -> &'a Utf8Path { + Utf8Path::new(s) + } +} + +// --- +// From impls: borrowed -> owned +// --- + +impl<T: ?Sized + AsRef<str>> From<&T> for Utf8PathBuf { + fn from(s: &T) -> Utf8PathBuf { + Utf8PathBuf::from(s.as_ref().to_owned()) + } +} + +impl<T: ?Sized + AsRef<str>> From<&T> for Box<Utf8Path> { + fn from(s: &T) -> Box<Utf8Path> { + Utf8PathBuf::from(s).into_boxed_path() + } +} + +impl From<&'_ Utf8Path> for Arc<Utf8Path> { + fn from(path: &Utf8Path) -> Arc<Utf8Path> { + let arc: Arc<Path> = Arc::from(AsRef::<Path>::as_ref(path)); + let ptr = Arc::into_raw(arc) as *const Utf8Path; + // SAFETY: + // * path is valid UTF-8 + // * ptr was created by consuming an Arc<Path> so it represents an arced pointer + // * Utf8Path is marked as #[repr(transparent)] so the conversion from *const Path to + // *const Utf8Path is valid + unsafe { Arc::from_raw(ptr) } + } +} + +impl From<&'_ Utf8Path> for Rc<Utf8Path> { + fn from(path: &Utf8Path) -> Rc<Utf8Path> { + let rc: Rc<Path> = Rc::from(AsRef::<Path>::as_ref(path)); + let ptr = Rc::into_raw(rc) as *const Utf8Path; + // SAFETY: + // * path is valid UTF-8 + // * ptr was created by consuming an Rc<Path> so it represents an rced pointer + // * Utf8Path is marked as #[repr(transparent)] so the conversion from *const Path to + // *const Utf8Path is valid + unsafe { Rc::from_raw(ptr) } + } +} + +impl<'a> From<&'a Utf8Path> for Cow<'a, Utf8Path> { + fn from(path: &'a Utf8Path) -> Cow<'a, Utf8Path> { + Cow::Borrowed(path) + } +} + +impl From<&'_ Utf8Path> for Box<Path> { + fn from(path: &Utf8Path) -> Box<Path> { + AsRef::<Path>::as_ref(path).into() + } +} + +impl From<&'_ Utf8Path> for Arc<Path> { + fn from(path: &Utf8Path) -> Arc<Path> { + AsRef::<Path>::as_ref(path).into() + } +} + +impl From<&'_ Utf8Path> for Rc<Path> { + fn from(path: &Utf8Path) -> Rc<Path> { + AsRef::<Path>::as_ref(path).into() + } +} + +impl<'a> From<&'a Utf8Path> for Cow<'a, Path> { + fn from(path: &'a Utf8Path) -> Cow<'a, Path> { + Cow::Borrowed(path.as_ref()) + } +} + +// --- +// From impls: owned -> owned +// --- + +impl From<Box<Utf8Path>> for Utf8PathBuf { + fn from(path: Box<Utf8Path>) -> Utf8PathBuf { + path.into_path_buf() + } +} + +impl From<Utf8PathBuf> for Box<Utf8Path> { + fn from(path: Utf8PathBuf) -> Box<Utf8Path> { + path.into_boxed_path() + } +} + +impl<'a> From<Cow<'a, Utf8Path>> for Utf8PathBuf { + fn from(path: Cow<'a, Utf8Path>) -> Utf8PathBuf { + path.into_owned() + } +} + +impl From<Utf8PathBuf> for String { + fn from(path: Utf8PathBuf) -> String { + path.into_string() + } +} + +impl From<Utf8PathBuf> for OsString { + fn from(path: Utf8PathBuf) -> OsString { + path.into_os_string() + } +} + +impl<'a> From<Utf8PathBuf> for Cow<'a, Utf8Path> { + fn from(path: Utf8PathBuf) -> Cow<'a, Utf8Path> { + Cow::Owned(path) + } +} + +impl From<Utf8PathBuf> for Arc<Utf8Path> { + fn from(path: Utf8PathBuf) -> Arc<Utf8Path> { + let arc: Arc<Path> = Arc::from(path.0); + let ptr = Arc::into_raw(arc) as *const Utf8Path; + // SAFETY: + // * path is valid UTF-8 + // * ptr was created by consuming an Arc<Path> so it represents an arced pointer + // * Utf8Path is marked as #[repr(transparent)] so the conversion from *const Path to + // *const Utf8Path is valid + unsafe { Arc::from_raw(ptr) } + } +} + +impl From<Utf8PathBuf> for Rc<Utf8Path> { + fn from(path: Utf8PathBuf) -> Rc<Utf8Path> { + let rc: Rc<Path> = Rc::from(path.0); + let ptr = Rc::into_raw(rc) as *const Utf8Path; + // SAFETY: + // * path is valid UTF-8 + // * ptr was created by consuming an Rc<Path> so it represents an rced pointer + // * Utf8Path is marked as #[repr(transparent)] so the conversion from *const Path to + // *const Utf8Path is valid + unsafe { Rc::from_raw(ptr) } + } +} + +impl From<Utf8PathBuf> for PathBuf { + fn from(path: Utf8PathBuf) -> PathBuf { + path.0 + } +} + +impl From<Utf8PathBuf> for Box<Path> { + fn from(path: Utf8PathBuf) -> Box<Path> { + PathBuf::from(path).into_boxed_path() + } +} + +impl From<Utf8PathBuf> for Arc<Path> { + fn from(path: Utf8PathBuf) -> Arc<Path> { + PathBuf::from(path).into() + } +} + +impl From<Utf8PathBuf> for Rc<Path> { + fn from(path: Utf8PathBuf) -> Rc<Path> { + PathBuf::from(path).into() + } +} + +impl<'a> From<Utf8PathBuf> for Cow<'a, Path> { + fn from(path: Utf8PathBuf) -> Cow<'a, Path> { + PathBuf::from(path).into() + } +} + +// --- +// TryFrom impls +// --- + +impl TryFrom<PathBuf> for Utf8PathBuf { + type Error = FromPathBufError; + + fn try_from(path: PathBuf) -> Result<Utf8PathBuf, Self::Error> { + Utf8PathBuf::from_path_buf(path).map_err(|path| FromPathBufError { + path, + error: FromPathError(()), + }) + } +} + +impl<'a> TryFrom<&'a Path> for &'a Utf8Path { + type Error = FromPathError; + + fn try_from(path: &'a Path) -> Result<&'a Utf8Path, Self::Error> { + Utf8Path::from_path(path).ok_or(FromPathError(())) + } +} + +/// A possible error value while converting a [`PathBuf`] to a [`Utf8PathBuf`]. +/// +/// Produced by the `TryFrom<PathBuf>` implementation for [`Utf8PathBuf`]. +/// +/// # Examples +/// +/// ``` +/// use camino::{Utf8PathBuf, FromPathBufError}; +/// use std::convert::{TryFrom, TryInto}; +/// use std::ffi::OsStr; +/// # #[cfg(unix)] +/// use std::os::unix::ffi::OsStrExt; +/// use std::path::PathBuf; +/// +/// let unicode_path = PathBuf::from("/valid/unicode"); +/// let utf8_path_buf: Utf8PathBuf = unicode_path.try_into().expect("valid Unicode path succeeded"); +/// +/// // Paths on Unix can be non-UTF-8. +/// # #[cfg(unix)] +/// let non_unicode_str = OsStr::from_bytes(b"\xFF\xFF\xFF"); +/// # #[cfg(unix)] +/// let non_unicode_path = PathBuf::from(non_unicode_str); +/// # #[cfg(unix)] +/// let err: FromPathBufError = Utf8PathBuf::try_from(non_unicode_path.clone()) +/// .expect_err("non-Unicode path failed"); +/// # #[cfg(unix)] +/// assert_eq!(err.as_path(), &non_unicode_path); +/// # #[cfg(unix)] +/// assert_eq!(err.into_path_buf(), non_unicode_path); +/// ``` +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct FromPathBufError { + path: PathBuf, + error: FromPathError, +} + +impl FromPathBufError { + /// Returns the [`Path`] slice that was attempted to be converted to [`Utf8PathBuf`]. + pub fn as_path(&self) -> &Path { + &self.path + } + + /// Returns the [`PathBuf`] that was attempted to be converted to [`Utf8PathBuf`]. + pub fn into_path_buf(self) -> PathBuf { + self.path + } + + /// Fetch a [`FromPathError`] for more about the conversion failure. + /// + /// At the moment this struct does not contain any additional information, but is provided for + /// completeness. + pub fn from_path_error(&self) -> FromPathError { + self.error + } +} + +impl fmt::Display for FromPathBufError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "PathBuf contains invalid UTF-8: {}", self.path.display()) + } +} + +impl error::Error for FromPathBufError { + fn source(&self) -> Option<&(dyn error::Error + 'static)> { + Some(&self.error) + } +} + +/// A possible error value while converting a [`Path`] to a [`Utf8Path`]. +/// +/// Produced by the `TryFrom<&Path>` implementation for [`&Utf8Path`](Utf8Path). +/// +/// +/// # Examples +/// +/// ``` +/// use camino::{Utf8Path, FromPathError}; +/// use std::convert::{TryFrom, TryInto}; +/// use std::ffi::OsStr; +/// # #[cfg(unix)] +/// use std::os::unix::ffi::OsStrExt; +/// use std::path::Path; +/// +/// let unicode_path = Path::new("/valid/unicode"); +/// let utf8_path: &Utf8Path = unicode_path.try_into().expect("valid Unicode path succeeded"); +/// +/// // Paths on Unix can be non-UTF-8. +/// # #[cfg(unix)] +/// let non_unicode_str = OsStr::from_bytes(b"\xFF\xFF\xFF"); +/// # #[cfg(unix)] +/// let non_unicode_path = Path::new(non_unicode_str); +/// # #[cfg(unix)] +/// let err: FromPathError = <&Utf8Path>::try_from(non_unicode_path) +/// .expect_err("non-Unicode path failed"); +/// ``` +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub struct FromPathError(()); + +impl fmt::Display for FromPathError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Path contains invalid UTF-8") + } +} + +impl error::Error for FromPathError { + fn source(&self) -> Option<&(dyn error::Error + 'static)> { + None + } +} + +// --- +// AsRef impls +// --- + +impl AsRef<Utf8Path> for Utf8Path { + fn as_ref(&self) -> &Utf8Path { + self + } +} + +impl AsRef<Utf8Path> for Utf8PathBuf { + fn as_ref(&self) -> &Utf8Path { + self.as_path() + } +} + +impl AsRef<Utf8Path> for str { + fn as_ref(&self) -> &Utf8Path { + Utf8Path::new(self) + } +} + +impl AsRef<Utf8Path> for String { + fn as_ref(&self) -> &Utf8Path { + Utf8Path::new(self) + } +} + +impl AsRef<Path> for Utf8Path { + fn as_ref(&self) -> &Path { + &self.0 + } +} + +impl AsRef<Path> for Utf8PathBuf { + fn as_ref(&self) -> &Path { + &*self.0 + } +} + +impl AsRef<str> for Utf8Path { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl AsRef<str> for Utf8PathBuf { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl AsRef<OsStr> for Utf8Path { + fn as_ref(&self) -> &OsStr { + self.as_os_str() + } +} + +impl AsRef<OsStr> for Utf8PathBuf { + fn as_ref(&self) -> &OsStr { + self.as_os_str() + } +} + +// --- +// Borrow and ToOwned +// --- + +impl Borrow<Utf8Path> for Utf8PathBuf { + fn borrow(&self) -> &Utf8Path { + self.as_path() + } +} + +impl ToOwned for Utf8Path { + type Owned = Utf8PathBuf; + + fn to_owned(&self) -> Utf8PathBuf { + self.to_path_buf() + } +} + +impl<P: AsRef<Utf8Path>> std::iter::FromIterator<P> for Utf8PathBuf { + fn from_iter<I: IntoIterator<Item = P>>(iter: I) -> Utf8PathBuf { + let mut buf = Utf8PathBuf::new(); + buf.extend(iter); + buf + } +} + +// --- +// [Partial]Eq, [Partial]Ord, Hash +// --- + +impl PartialEq for Utf8PathBuf { + fn eq(&self, other: &Utf8PathBuf) -> bool { + self.components() == other.components() + } +} + +impl Eq for Utf8PathBuf {} + +impl Hash for Utf8PathBuf { + fn hash<H: Hasher>(&self, state: &mut H) { + self.as_path().hash(state) + } +} + +impl PartialOrd for Utf8PathBuf { + fn partial_cmp(&self, other: &Utf8PathBuf) -> Option<Ordering> { + self.components().partial_cmp(other.components()) + } +} + +impl Ord for Utf8PathBuf { + fn cmp(&self, other: &Utf8PathBuf) -> Ordering { + self.components().cmp(other.components()) + } +} + +impl PartialEq for Utf8Path { + fn eq(&self, other: &Utf8Path) -> bool { + self.components().eq(other.components()) + } +} + +impl Eq for Utf8Path {} + +impl Hash for Utf8Path { + fn hash<H: Hasher>(&self, state: &mut H) { + for component in self.components() { + component.hash(state) + } + } +} + +impl PartialOrd for Utf8Path { + fn partial_cmp(&self, other: &Utf8Path) -> Option<Ordering> { + self.components().partial_cmp(other.components()) + } +} + +impl Ord for Utf8Path { + fn cmp(&self, other: &Utf8Path) -> Ordering { + self.components().cmp(other.components()) + } +} + +impl<'a> IntoIterator for &'a Utf8PathBuf { + type Item = &'a str; + type IntoIter = Iter<'a>; + fn into_iter(self) -> Iter<'a> { + self.iter() + } +} + +impl<'a> IntoIterator for &'a Utf8Path { + type Item = &'a str; + type IntoIter = Iter<'a>; + fn into_iter(self) -> Iter<'a> { + self.iter() + } +} + +macro_rules! impl_cmp { + ($lhs:ty, $rhs: ty) => { + impl<'a, 'b> PartialEq<$rhs> for $lhs { + #[inline] + fn eq(&self, other: &$rhs) -> bool { + <Utf8Path as PartialEq>::eq(self, other) + } + } + + impl<'a, 'b> PartialEq<$lhs> for $rhs { + #[inline] + fn eq(&self, other: &$lhs) -> bool { + <Utf8Path as PartialEq>::eq(self, other) + } + } + + impl<'a, 'b> PartialOrd<$rhs> for $lhs { + #[inline] + fn partial_cmp(&self, other: &$rhs) -> Option<Ordering> { + <Utf8Path as PartialOrd>::partial_cmp(self, other) + } + } + + impl<'a, 'b> PartialOrd<$lhs> for $rhs { + #[inline] + fn partial_cmp(&self, other: &$lhs) -> Option<Ordering> { + <Utf8Path as PartialOrd>::partial_cmp(self, other) + } + } + }; +} + +impl_cmp!(Utf8PathBuf, Utf8Path); +impl_cmp!(Utf8PathBuf, &'a Utf8Path); +impl_cmp!(Cow<'a, Utf8Path>, Utf8Path); +impl_cmp!(Cow<'a, Utf8Path>, &'b Utf8Path); +impl_cmp!(Cow<'a, Utf8Path>, Utf8PathBuf); + +macro_rules! impl_cmp_std_path { + ($lhs:ty, $rhs: ty) => { + impl<'a, 'b> PartialEq<$rhs> for $lhs { + #[inline] + fn eq(&self, other: &$rhs) -> bool { + <Path as PartialEq>::eq(self.as_ref(), other) + } + } + + impl<'a, 'b> PartialEq<$lhs> for $rhs { + #[inline] + fn eq(&self, other: &$lhs) -> bool { + <Path as PartialEq>::eq(self, other.as_ref()) + } + } + + impl<'a, 'b> PartialOrd<$rhs> for $lhs { + #[inline] + fn partial_cmp(&self, other: &$rhs) -> Option<std::cmp::Ordering> { + <Path as PartialOrd>::partial_cmp(self.as_ref(), other) + } + } + + impl<'a, 'b> PartialOrd<$lhs> for $rhs { + #[inline] + fn partial_cmp(&self, other: &$lhs) -> Option<std::cmp::Ordering> { + <Path as PartialOrd>::partial_cmp(self, other.as_ref()) + } + } + }; +} + +impl_cmp_std_path!(Utf8PathBuf, Path); +impl_cmp_std_path!(Utf8PathBuf, &'a Path); +impl_cmp_std_path!(Utf8PathBuf, Cow<'a, Path>); +impl_cmp_std_path!(Utf8PathBuf, PathBuf); +impl_cmp_std_path!(Utf8Path, Path); +impl_cmp_std_path!(Utf8Path, &'a Path); +impl_cmp_std_path!(Utf8Path, Cow<'a, Path>); +impl_cmp_std_path!(Utf8Path, PathBuf); +impl_cmp_std_path!(&'a Utf8Path, Path); +impl_cmp_std_path!(&'a Utf8Path, Cow<'b, Path>); +impl_cmp_std_path!(&'a Utf8Path, PathBuf); +// NOTE: impls for Cow<'a, Utf8Path> cannot be defined because of the orphan rule (E0117) + +macro_rules! impl_cmp_str { + ($lhs:ty, $rhs: ty) => { + impl<'a, 'b> PartialEq<$rhs> for $lhs { + #[inline] + fn eq(&self, other: &$rhs) -> bool { + <Utf8Path as PartialEq>::eq(self, Utf8Path::new(other)) + } + } + + impl<'a, 'b> PartialEq<$lhs> for $rhs { + #[inline] + fn eq(&self, other: &$lhs) -> bool { + <Utf8Path as PartialEq>::eq(Utf8Path::new(self), other) + } + } + + impl<'a, 'b> PartialOrd<$rhs> for $lhs { + #[inline] + fn partial_cmp(&self, other: &$rhs) -> Option<std::cmp::Ordering> { + <Utf8Path as PartialOrd>::partial_cmp(self, Utf8Path::new(other)) + } + } + + impl<'a, 'b> PartialOrd<$lhs> for $rhs { + #[inline] + fn partial_cmp(&self, other: &$lhs) -> Option<std::cmp::Ordering> { + <Utf8Path as PartialOrd>::partial_cmp(Utf8Path::new(self), other) + } + } + }; +} + +impl_cmp_str!(Utf8PathBuf, str); +impl_cmp_str!(Utf8PathBuf, &'a str); +impl_cmp_str!(Utf8PathBuf, Cow<'a, str>); +impl_cmp_str!(Utf8PathBuf, String); +impl_cmp_str!(Utf8Path, str); +impl_cmp_str!(Utf8Path, &'a str); +impl_cmp_str!(Utf8Path, Cow<'a, str>); +impl_cmp_str!(Utf8Path, String); +impl_cmp_str!(&'a Utf8Path, str); +impl_cmp_str!(&'a Utf8Path, Cow<'b, str>); +impl_cmp_str!(&'a Utf8Path, String); +// NOTE: impls for Cow<'a, Utf8Path> cannot be defined because of the orphan rule (E0117) + +macro_rules! impl_cmp_os_str { + ($lhs:ty, $rhs: ty) => { + impl<'a, 'b> PartialEq<$rhs> for $lhs { + #[inline] + fn eq(&self, other: &$rhs) -> bool { + <Path as PartialEq>::eq(self.as_ref(), other.as_ref()) + } + } + + impl<'a, 'b> PartialEq<$lhs> for $rhs { + #[inline] + fn eq(&self, other: &$lhs) -> bool { + <Path as PartialEq>::eq(self.as_ref(), other.as_ref()) + } + } + + impl<'a, 'b> PartialOrd<$rhs> for $lhs { + #[inline] + fn partial_cmp(&self, other: &$rhs) -> Option<std::cmp::Ordering> { + <Path as PartialOrd>::partial_cmp(self.as_ref(), other.as_ref()) + } + } + + impl<'a, 'b> PartialOrd<$lhs> for $rhs { + #[inline] + fn partial_cmp(&self, other: &$lhs) -> Option<std::cmp::Ordering> { + <Path as PartialOrd>::partial_cmp(self.as_ref(), other.as_ref()) + } + } + }; +} + +impl_cmp_os_str!(Utf8PathBuf, OsStr); +impl_cmp_os_str!(Utf8PathBuf, &'a OsStr); +impl_cmp_os_str!(Utf8PathBuf, Cow<'a, OsStr>); +impl_cmp_os_str!(Utf8PathBuf, OsString); +impl_cmp_os_str!(Utf8Path, OsStr); +impl_cmp_os_str!(Utf8Path, &'a OsStr); +impl_cmp_os_str!(Utf8Path, Cow<'a, OsStr>); +impl_cmp_os_str!(Utf8Path, OsString); +impl_cmp_os_str!(&'a Utf8Path, OsStr); +impl_cmp_os_str!(&'a Utf8Path, Cow<'b, OsStr>); +impl_cmp_os_str!(&'a Utf8Path, OsString); +// NOTE: impls for Cow<'a, Utf8Path> cannot be defined because of the orphan rule (E0117) + +// invariant: OsStr must be guaranteed to be utf8 data +unsafe fn assume_utf8(string: &OsStr) -> &str { + &*(string as *const OsStr as *const str) +} diff --git a/vendor/camino/src/serde_impls.rs b/vendor/camino/src/serde_impls.rs new file mode 100644 index 0000000000..214fe3313d --- /dev/null +++ b/vendor/camino/src/serde_impls.rs @@ -0,0 +1,55 @@ +// Copyright (c) The camino Contributors +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Serde implementations for `Utf8Path`. +//! +//! The Serde implementations for `Utf8PathBuf` are derived, but `Utf8Path` is an unsized type which +//! the derive impls can't handle. Implement these by hand. + +use crate::Utf8Path; +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; +use std::fmt; + +struct Utf8PathVisitor; + +impl<'a> de::Visitor<'a> for Utf8PathVisitor { + type Value = &'a Utf8Path; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a borrowed path") + } + + fn visit_borrowed_str<E>(self, v: &'a str) -> Result<Self::Value, E> + where + E: de::Error, + { + Ok(v.as_ref()) + } + + fn visit_borrowed_bytes<E>(self, v: &'a [u8]) -> Result<Self::Value, E> + where + E: de::Error, + { + std::str::from_utf8(v) + .map(AsRef::as_ref) + .map_err(|_| de::Error::invalid_value(de::Unexpected::Bytes(v), &self)) + } +} + +impl<'de: 'a, 'a> Deserialize<'de> for &'a Utf8Path { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + deserializer.deserialize_str(Utf8PathVisitor) + } +} + +impl Serialize for Utf8Path { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + self.as_str().serialize(serializer) + } +} diff --git a/vendor/camino/src/tests.rs b/vendor/camino/src/tests.rs new file mode 100644 index 0000000000..efc43445d1 --- /dev/null +++ b/vendor/camino/src/tests.rs @@ -0,0 +1,46 @@ +// Copyright (c) The camino Contributors +// SPDX-License-Identifier: MIT OR Apache-2.0 + +// Test that all required impls exist. + +use crate::{Utf8Path, Utf8PathBuf}; +use std::{ + borrow::Cow, + path::{Path, PathBuf}, + rc::Rc, + sync::Arc, +}; + +macro_rules! all_into { + ($t:ty, $x:ident) => { + test_into::<$t, Utf8PathBuf>($x.clone()); + test_into::<$t, Box<Utf8Path>>($x.clone()); + test_into::<$t, Arc<Utf8Path>>($x.clone()); + test_into::<$t, Rc<Utf8Path>>($x.clone()); + test_into::<$t, Cow<'_, Utf8Path>>($x.clone()); + test_into::<$t, PathBuf>($x.clone()); + test_into::<$t, Box<Path>>($x.clone()); + test_into::<$t, Arc<Path>>($x.clone()); + test_into::<$t, Rc<Path>>($x.clone()); + test_into::<$t, Cow<'_, Path>>($x.clone()); + }; +} + +#[test] +fn test_borrowed_into() { + let utf8_path = Utf8Path::new("test/path"); + all_into!(&Utf8Path, utf8_path); +} + +#[test] +fn test_owned_into() { + let utf8_path_buf = Utf8PathBuf::from("test/path"); + all_into!(Utf8PathBuf, utf8_path_buf); +} + +fn test_into<T, U>(orig: T) +where + T: Into<U>, +{ + orig.into(); +} diff --git a/vendor/camino/tests/integration_tests.rs b/vendor/camino/tests/integration_tests.rs new file mode 100644 index 0000000000..a8b00f2fed --- /dev/null +++ b/vendor/camino/tests/integration_tests.rs @@ -0,0 +1,115 @@ +// Copyright (c) The camino Contributors +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use camino::{Utf8Path, Utf8PathBuf}; +use std::{ + collections::hash_map::DefaultHasher, + hash::{Hash, Hasher}, + path::Path, +}; + +static PATH_CORPUS: &[&str] = &[ + "", + "foo", + "foo/bar", + "foo//bar", + "foo/bar/baz", + "foo/bar/./baz", + "foo/bar/../baz", + "../foo/bar/./../baz", + "/foo", + "/foo/bar", + "/", + "///", + // --- + // Windows-only paths + // --- + #[cfg(windows)] + "foo\\bar", + #[cfg(windows)] + "\\foo\\bar", + #[cfg(windows)] + "C:\\foo", + #[cfg(windows)] + "C:foo\\bar", + #[cfg(windows)] + "C:\\foo\\..\\.\\bar", + #[cfg(windows)] + "\\\\server\\foo\\bar", + #[cfg(windows)] + "\\\\.\\C:\\foo\\bar.txt", +]; + +#[test] +fn test_borrow_eq_ord() { + // Utf8PathBuf implements Borrow<Utf8Path> so equality and ordering comparisons should + // match. + for (idx, &path1) in PATH_CORPUS.iter().enumerate() { + for &path2 in &PATH_CORPUS[idx..] { + let borrowed1 = Utf8Path::new(path1); + let borrowed2 = Utf8Path::new(path2); + let owned1 = Utf8PathBuf::from(path1); + let owned2 = Utf8PathBuf::from(path2); + + assert_eq!( + borrowed1 == borrowed2, + owned1 == owned2, + "Eq impls match: {} == {}", + borrowed1, + borrowed2 + ); + assert_eq!( + borrowed1.cmp(borrowed2), + owned1.cmp(&owned2), + "Ord impls match: {} and {}", + borrowed1, + borrowed2 + ); + + // Also check against std paths. + let std1 = Path::new(path1); + let std2 = Path::new(path2); + assert_eq!( + borrowed1, std1, + "Eq between Path and Utf8Path: {}", + borrowed1 + ); + assert_eq!( + borrowed1 == borrowed2, + std1 == std2, + "Eq impl matches Path: {} == {}", + borrowed1, + borrowed2 + ); + assert_eq!( + borrowed1.cmp(borrowed2), + std1.cmp(std2), + "Ord impl matches Path: {} and {}", + borrowed1, + borrowed2 + ); + } + } +} + +#[test] +fn test_borrow_hash() { + // Utf8PathBuf implements Borrow<Utf8Path> so hash comparisons should match. + fn hash_output(x: impl Hash) -> u64 { + let mut hasher = DefaultHasher::new(); + x.hash(&mut hasher); + hasher.finish() + } + + for &path in PATH_CORPUS { + let borrowed = Utf8Path::new(path); + let owned = Utf8PathBuf::from(path); + + assert_eq!( + hash_output(&owned), + hash_output(borrowed), + "consistent Hash: {}", + borrowed + ); + } +} diff --git a/vendor/cargo-platform/.cargo-checksum.json b/vendor/cargo-platform/.cargo-checksum.json new file mode 100644 index 0000000000..2b06d73774 --- /dev/null +++ b/vendor/cargo-platform/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.lock":"9832d7e589baf011943280a694337d220581b600e089793f9935c8e3c34c36c2","Cargo.toml":"7e05573b44b23a026995d557ea85957fa19f437328a116be1ada5400274fe42e","LICENSE-APACHE":"8ada45cd9f843acf64e4722ae262c622a2b3b3007c7310ef36ac1061a30f6adb","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","examples/matches.rs":"5485312cf426b1de01ef3d37cbbc7358d264e62509fa101614ecb44835b98229","src/cfg.rs":"2a5943f53d364c12edc0279db9f4c623add6d65b1a7b70843d8786e5d93d90ba","src/error.rs":"f9e5b3833ebd98ba5f959da34644a1a02687b6d896f94462ff43c05594bad467","src/lib.rs":"1c1ce4eb0143744427a01600541d3a852506922c4d3c558be29d8ce821516711","tests/test_cfg.rs":"d97202ea588e86b4c5603f199afbd7715852ddd8ddad772217a0826c9afd7304"},"package":"cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27"} \ No newline at end of file diff --git a/vendor/cargo-platform/Cargo.lock b/vendor/cargo-platform/Cargo.lock new file mode 100644 index 0000000000..059f730297 --- /dev/null +++ b/vendor/cargo-platform/Cargo.lock @@ -0,0 +1,65 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "cargo-platform" +version = "0.1.2" +dependencies = [ + "serde", +] + +[[package]] +name = "proc-macro2" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "serde" +version = "1.0.127" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f03b9878abf6d14e6779d3f24f07b2cfa90352cfec4acc5aab8f1ac7f146fae8" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.127" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a024926d3432516606328597e0f224a51355a493b49fdd67e9209187cbe55ecc" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "1.0.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" diff --git a/vendor/cargo-platform/Cargo.toml b/vendor/cargo-platform/Cargo.toml new file mode 100644 index 0000000000..ebf12c855e --- /dev/null +++ b/vendor/cargo-platform/Cargo.toml @@ -0,0 +1,24 @@ +# 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 are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +name = "cargo-platform" +version = "0.1.2" +authors = ["The Cargo Project Developers"] +description = "Cargo's representation of a target platform." +homepage = "https://github.com/rust-lang/cargo" +documentation = "https://docs.rs/cargo-platform" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/cargo" +[dependencies.serde] +version = "1.0.82" +features = ["derive"] diff --git a/vendor/cargo-platform/LICENSE-APACHE b/vendor/cargo-platform/LICENSE-APACHE new file mode 100644 index 0000000000..c98d27d4f3 --- /dev/null +++ b/vendor/cargo-platform/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/LICENSE-2.0 + +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/cargo-platform/LICENSE-MIT b/vendor/cargo-platform/LICENSE-MIT new file mode 100644 index 0000000000..31aa79387f --- /dev/null +++ b/vendor/cargo-platform/LICENSE-MIT @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/vendor/cargo-platform/examples/matches.rs b/vendor/cargo-platform/examples/matches.rs new file mode 100644 index 0000000000..9ad5d10dd5 --- /dev/null +++ b/vendor/cargo-platform/examples/matches.rs @@ -0,0 +1,55 @@ +//! This example demonstrates how to filter a Platform based on the current +//! host target. + +use cargo_platform::{Cfg, Platform}; +use std::process::Command; +use std::str::FromStr; + +static EXAMPLES: &[&str] = &[ + "cfg(windows)", + "cfg(unix)", + "cfg(target_os=\"macos\")", + "cfg(target_os=\"linux\")", + "cfg(any(target_arch=\"x86\", target_arch=\"x86_64\"))", +]; + +fn main() { + let target = get_target(); + let cfgs = get_cfgs(); + println!("host target={} cfgs:", target); + for cfg in &cfgs { + println!(" {}", cfg); + } + let mut examples: Vec<&str> = EXAMPLES.iter().copied().collect(); + examples.push(target.as_str()); + for example in examples { + let p = Platform::from_str(example).unwrap(); + println!("{:?} matches: {:?}", example, p.matches(&target, &cfgs)); + } +} + +fn get_target() -> String { + let output = Command::new("rustc") + .arg("-Vv") + .output() + .expect("rustc failed to run"); + let stdout = String::from_utf8(output.stdout).unwrap(); + for line in stdout.lines() { + if line.starts_with("host: ") { + return String::from(&line[6..]); + } + } + panic!("Failed to find host: {}", stdout); +} + +fn get_cfgs() -> Vec<Cfg> { + let output = Command::new("rustc") + .arg("--print=cfg") + .output() + .expect("rustc failed to run"); + let stdout = String::from_utf8(output.stdout).unwrap(); + stdout + .lines() + .map(|line| Cfg::from_str(line).unwrap()) + .collect() +} diff --git a/vendor/cargo-platform/src/cfg.rs b/vendor/cargo-platform/src/cfg.rs new file mode 100644 index 0000000000..c3ddb69bc8 --- /dev/null +++ b/vendor/cargo-platform/src/cfg.rs @@ -0,0 +1,319 @@ +use crate::error::{ParseError, ParseErrorKind::*}; +use std::fmt; +use std::iter; +use std::str::{self, FromStr}; + +/// A cfg expression. +#[derive(Eq, PartialEq, Hash, Ord, PartialOrd, Clone, Debug)] +pub enum CfgExpr { + Not(Box<CfgExpr>), + All(Vec<CfgExpr>), + Any(Vec<CfgExpr>), + Value(Cfg), +} + +/// A cfg value. +#[derive(Eq, PartialEq, Hash, Ord, PartialOrd, Clone, Debug)] +pub enum Cfg { + /// A named cfg value, like `unix`. + Name(String), + /// A key/value cfg pair, like `target_os = "linux"`. + KeyPair(String, String), +} + +#[derive(PartialEq)] +enum Token<'a> { + LeftParen, + RightParen, + Ident(&'a str), + Comma, + Equals, + String(&'a str), +} + +#[derive(Clone)] +struct Tokenizer<'a> { + s: iter::Peekable<str::CharIndices<'a>>, + orig: &'a str, +} + +struct Parser<'a> { + t: Tokenizer<'a>, +} + +impl FromStr for Cfg { + type Err = ParseError; + + fn from_str(s: &str) -> Result<Cfg, Self::Err> { + let mut p = Parser::new(s); + let e = p.cfg()?; + if let Some(rest) = p.rest() { + return Err(ParseError::new( + p.t.orig, + UnterminatedExpression(rest.to_string()), + )); + } + Ok(e) + } +} + +impl fmt::Display for Cfg { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + Cfg::Name(ref s) => s.fmt(f), + Cfg::KeyPair(ref k, ref v) => write!(f, "{} = \"{}\"", k, v), + } + } +} + +impl CfgExpr { + /// Utility function to check if the key, "cfg(..)" matches the `target_cfg` + pub fn matches_key(key: &str, target_cfg: &[Cfg]) -> bool { + if key.starts_with("cfg(") && key.ends_with(')') { + let cfg = &key[4..key.len() - 1]; + + CfgExpr::from_str(cfg) + .ok() + .map(|ce| ce.matches(target_cfg)) + .unwrap_or(false) + } else { + false + } + } + + pub fn matches(&self, cfg: &[Cfg]) -> bool { + match *self { + CfgExpr::Not(ref e) => !e.matches(cfg), + CfgExpr::All(ref e) => e.iter().all(|e| e.matches(cfg)), + CfgExpr::Any(ref e) => e.iter().any(|e| e.matches(cfg)), + CfgExpr::Value(ref e) => cfg.contains(e), + } + } +} + +impl FromStr for CfgExpr { + type Err = ParseError; + + fn from_str(s: &str) -> Result<CfgExpr, Self::Err> { + let mut p = Parser::new(s); + let e = p.expr()?; + if let Some(rest) = p.rest() { + return Err(ParseError::new( + p.t.orig, + UnterminatedExpression(rest.to_string()), + )); + } + Ok(e) + } +} + +impl fmt::Display for CfgExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + CfgExpr::Not(ref e) => write!(f, "not({})", e), + CfgExpr::All(ref e) => write!(f, "all({})", CommaSep(e)), + CfgExpr::Any(ref e) => write!(f, "any({})", CommaSep(e)), + CfgExpr::Value(ref e) => write!(f, "{}", e), + } + } +} + +struct CommaSep<'a, T>(&'a [T]); + +impl<'a, T: fmt::Display> fmt::Display for CommaSep<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + for (i, v) in self.0.iter().enumerate() { + if i > 0 { + write!(f, ", ")?; + } + write!(f, "{}", v)?; + } + Ok(()) + } +} + +impl<'a> Parser<'a> { + fn new(s: &'a str) -> Parser<'a> { + Parser { + t: Tokenizer { + s: s.char_indices().peekable(), + orig: s, + }, + } + } + + fn expr(&mut self) -> Result<CfgExpr, ParseError> { + match self.peek() { + Some(Ok(Token::Ident(op @ "all"))) | Some(Ok(Token::Ident(op @ "any"))) => { + self.t.next(); + let mut e = Vec::new(); + self.eat(&Token::LeftParen)?; + while !self.r#try(&Token::RightParen) { + e.push(self.expr()?); + if !self.r#try(&Token::Comma) { + self.eat(&Token::RightParen)?; + break; + } + } + if op == "all" { + Ok(CfgExpr::All(e)) + } else { + Ok(CfgExpr::Any(e)) + } + } + Some(Ok(Token::Ident("not"))) => { + self.t.next(); + self.eat(&Token::LeftParen)?; + let e = self.expr()?; + self.eat(&Token::RightParen)?; + Ok(CfgExpr::Not(Box::new(e))) + } + Some(Ok(..)) => self.cfg().map(CfgExpr::Value), + Some(Err(..)) => Err(self.t.next().unwrap().err().unwrap()), + None => Err(ParseError::new( + self.t.orig, + IncompleteExpr("start of a cfg expression"), + )), + } + } + + fn cfg(&mut self) -> Result<Cfg, ParseError> { + match self.t.next() { + Some(Ok(Token::Ident(name))) => { + let e = if self.r#try(&Token::Equals) { + let val = match self.t.next() { + Some(Ok(Token::String(s))) => s, + Some(Ok(t)) => { + return Err(ParseError::new( + self.t.orig, + UnexpectedToken { + expected: "a string", + found: t.classify(), + }, + )) + } + Some(Err(e)) => return Err(e), + None => { + return Err(ParseError::new(self.t.orig, IncompleteExpr("a string"))) + } + }; + Cfg::KeyPair(name.to_string(), val.to_string()) + } else { + Cfg::Name(name.to_string()) + }; + Ok(e) + } + Some(Ok(t)) => Err(ParseError::new( + self.t.orig, + UnexpectedToken { + expected: "identifier", + found: t.classify(), + }, + )), + Some(Err(e)) => Err(e), + None => Err(ParseError::new(self.t.orig, IncompleteExpr("identifier"))), + } + } + + fn peek(&mut self) -> Option<Result<Token<'a>, ParseError>> { + self.t.clone().next() + } + + fn r#try(&mut self, token: &Token<'a>) -> bool { + match self.peek() { + Some(Ok(ref t)) if token == t => {} + _ => return false, + } + self.t.next(); + true + } + + fn eat(&mut self, token: &Token<'a>) -> Result<(), ParseError> { + match self.t.next() { + Some(Ok(ref t)) if token == t => Ok(()), + Some(Ok(t)) => Err(ParseError::new( + self.t.orig, + UnexpectedToken { + expected: token.classify(), + found: t.classify(), + }, + )), + Some(Err(e)) => Err(e), + None => Err(ParseError::new( + self.t.orig, + IncompleteExpr(token.classify()), + )), + } + } + + /// Returns the rest of the input from the current location. + fn rest(&self) -> Option<&str> { + let mut s = self.t.s.clone(); + loop { + match s.next() { + Some((_, ' ')) => {} + Some((start, _ch)) => return Some(&self.t.orig[start..]), + None => return None, + } + } + } +} + +impl<'a> Iterator for Tokenizer<'a> { + type Item = Result<Token<'a>, ParseError>; + + fn next(&mut self) -> Option<Result<Token<'a>, ParseError>> { + loop { + match self.s.next() { + Some((_, ' ')) => {} + Some((_, '(')) => return Some(Ok(Token::LeftParen)), + Some((_, ')')) => return Some(Ok(Token::RightParen)), + Some((_, ',')) => return Some(Ok(Token::Comma)), + Some((_, '=')) => return Some(Ok(Token::Equals)), + Some((start, '"')) => { + while let Some((end, ch)) = self.s.next() { + if ch == '"' { + return Some(Ok(Token::String(&self.orig[start + 1..end]))); + } + } + return Some(Err(ParseError::new(self.orig, UnterminatedString))); + } + Some((start, ch)) if is_ident_start(ch) => { + while let Some(&(end, ch)) = self.s.peek() { + if !is_ident_rest(ch) { + return Some(Ok(Token::Ident(&self.orig[start..end]))); + } else { + self.s.next(); + } + } + return Some(Ok(Token::Ident(&self.orig[start..]))); + } + Some((_, ch)) => { + return Some(Err(ParseError::new(self.orig, UnexpectedChar(ch)))); + } + None => return None, + } + } + } +} + +fn is_ident_start(ch: char) -> bool { + ch == '_' || ch.is_ascii_alphabetic() +} + +fn is_ident_rest(ch: char) -> bool { + is_ident_start(ch) || ch.is_ascii_digit() +} + +impl<'a> Token<'a> { + fn classify(&self) -> &'static str { + match *self { + Token::LeftParen => "`(`", + Token::RightParen => "`)`", + Token::Ident(..) => "an identifier", + Token::Comma => "`,`", + Token::Equals => "`=`", + Token::String(..) => "a string", + } + } +} diff --git a/vendor/cargo-platform/src/error.rs b/vendor/cargo-platform/src/error.rs new file mode 100644 index 0000000000..bf4b35f271 --- /dev/null +++ b/vendor/cargo-platform/src/error.rs @@ -0,0 +1,67 @@ +use std::fmt; + +#[derive(Debug)] +pub struct ParseError { + kind: ParseErrorKind, + orig: String, +} + +#[non_exhaustive] +#[derive(Debug)] +pub enum ParseErrorKind { + UnterminatedString, + UnexpectedChar(char), + UnexpectedToken { + expected: &'static str, + found: &'static str, + }, + IncompleteExpr(&'static str), + UnterminatedExpression(String), + InvalidTarget(String), +} + +impl fmt::Display for ParseError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "failed to parse `{}` as a cfg expression: {}", + self.orig, self.kind + ) + } +} + +impl fmt::Display for ParseErrorKind { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use ParseErrorKind::*; + match self { + UnterminatedString => write!(f, "unterminated string in cfg"), + UnexpectedChar(ch) => write!( + f, + "unexpected character `{}` in cfg, expected parens, a comma, \ + an identifier, or a string", + ch + ), + UnexpectedToken { expected, found } => { + write!(f, "expected {}, found {}", expected, found) + } + IncompleteExpr(expected) => { + write!(f, "expected {}, but cfg expression ended", expected) + } + UnterminatedExpression(s) => { + write!(f, "unexpected content `{}` found after cfg expression", s) + } + InvalidTarget(s) => write!(f, "invalid target specifier: {}", s), + } + } +} + +impl std::error::Error for ParseError {} + +impl ParseError { + pub fn new(orig: &str, kind: ParseErrorKind) -> ParseError { + ParseError { + kind, + orig: orig.to_string(), + } + } +} diff --git a/vendor/cargo-platform/src/lib.rs b/vendor/cargo-platform/src/lib.rs new file mode 100644 index 0000000000..0a3dcf1af1 --- /dev/null +++ b/vendor/cargo-platform/src/lib.rs @@ -0,0 +1,146 @@ +//! Platform definition used by Cargo. +//! +//! This defines a [`Platform`] type which is used in Cargo to specify a target platform. +//! There are two kinds, a named target like `x86_64-apple-darwin`, and a "cfg expression" +//! like `cfg(any(target_os = "macos", target_os = "ios"))`. +//! +//! See `examples/matches.rs` for an example of how to match against a `Platform`. +//! +//! [`Platform`]: enum.Platform.html + +use std::fmt; +use std::str::FromStr; + +mod cfg; +mod error; + +pub use cfg::{Cfg, CfgExpr}; +pub use error::{ParseError, ParseErrorKind}; + +/// Platform definition. +#[derive(Eq, PartialEq, Hash, Ord, PartialOrd, Clone, Debug)] +pub enum Platform { + /// A named platform, like `x86_64-apple-darwin`. + Name(String), + /// A cfg expression, like `cfg(windows)`. + Cfg(CfgExpr), +} + +impl Platform { + /// Returns whether the Platform matches the given target and cfg. + /// + /// The named target and cfg values should be obtained from `rustc`. + pub fn matches(&self, name: &str, cfg: &[Cfg]) -> bool { + match *self { + Platform::Name(ref p) => p == name, + Platform::Cfg(ref p) => p.matches(cfg), + } + } + + fn validate_named_platform(name: &str) -> Result<(), ParseError> { + if let Some(ch) = name + .chars() + .find(|&c| !(c.is_alphanumeric() || c == '_' || c == '-' || c == '.')) + { + if name.chars().any(|c| c == '(') { + return Err(ParseError::new( + name, + ParseErrorKind::InvalidTarget( + "unexpected `(` character, cfg expressions must start with `cfg(`" + .to_string(), + ), + )); + } + return Err(ParseError::new( + name, + ParseErrorKind::InvalidTarget(format!( + "unexpected character {} in target name", + ch + )), + )); + } + Ok(()) + } + + pub fn check_cfg_attributes(&self, warnings: &mut Vec<String>) { + fn check_cfg_expr(expr: &CfgExpr, warnings: &mut Vec<String>) { + match *expr { + CfgExpr::Not(ref e) => check_cfg_expr(e, warnings), + CfgExpr::All(ref e) | CfgExpr::Any(ref e) => { + for e in e { + check_cfg_expr(e, warnings); + } + } + CfgExpr::Value(ref e) => match e { + Cfg::Name(name) => match name.as_str() { + "test" | "debug_assertions" | "proc_macro" => + warnings.push(format!( + "Found `{}` in `target.'cfg(...)'.dependencies`. \ + This value is not supported for selecting dependencies \ + and will not work as expected. \ + To learn more visit \ + https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#platform-specific-dependencies", + name + )), + _ => (), + }, + Cfg::KeyPair(name, _) => if name.as_str() == "feature" { + warnings.push(String::from( + "Found `feature = ...` in `target.'cfg(...)'.dependencies`. \ + This key is not supported for selecting dependencies \ + and will not work as expected. \ + Use the [features] section instead: \ + https://doc.rust-lang.org/cargo/reference/features.html" + )) + }, + } + } + } + + if let Platform::Cfg(cfg) = self { + check_cfg_expr(cfg, warnings); + } + } +} + +impl serde::Serialize for Platform { + fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error> + where + S: serde::Serializer, + { + self.to_string().serialize(s) + } +} + +impl<'de> serde::Deserialize<'de> for Platform { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: serde::Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + FromStr::from_str(&s).map_err(serde::de::Error::custom) + } +} + +impl FromStr for Platform { + type Err = ParseError; + + fn from_str(s: &str) -> Result<Platform, ParseError> { + if s.starts_with("cfg(") && s.ends_with(')') { + let s = &s[4..s.len() - 1]; + s.parse().map(Platform::Cfg) + } else { + Platform::validate_named_platform(s)?; + Ok(Platform::Name(s.to_string())) + } + } +} + +impl fmt::Display for Platform { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + Platform::Name(ref n) => n.fmt(f), + Platform::Cfg(ref e) => write!(f, "cfg({})", e), + } + } +} diff --git a/vendor/cargo-platform/tests/test_cfg.rs b/vendor/cargo-platform/tests/test_cfg.rs new file mode 100644 index 0000000000..dd99d9a79b --- /dev/null +++ b/vendor/cargo-platform/tests/test_cfg.rs @@ -0,0 +1,251 @@ +use cargo_platform::{Cfg, CfgExpr, Platform}; +use std::fmt; +use std::str::FromStr; + +macro_rules! c { + ($a:ident) => { + Cfg::Name(stringify!($a).to_string()) + }; + ($a:ident = $e:expr) => { + Cfg::KeyPair(stringify!($a).to_string(), $e.to_string()) + }; +} + +macro_rules! e { + (any($($t:tt),*)) => (CfgExpr::Any(vec![$(e!($t)),*])); + (all($($t:tt),*)) => (CfgExpr::All(vec![$(e!($t)),*])); + (not($($t:tt)*)) => (CfgExpr::Not(Box::new(e!($($t)*)))); + (($($t:tt)*)) => (e!($($t)*)); + ($($t:tt)*) => (CfgExpr::Value(c!($($t)*))); +} + +fn good<T>(s: &str, expected: T) +where + T: FromStr + PartialEq + fmt::Debug, + T::Err: fmt::Display, +{ + let c = match T::from_str(s) { + Ok(c) => c, + Err(e) => panic!("failed to parse `{}`: {}", s, e), + }; + assert_eq!(c, expected); +} + +fn bad<T>(s: &str, err: &str) +where + T: FromStr + fmt::Display, + T::Err: fmt::Display, +{ + let e = match T::from_str(s) { + Ok(cfg) => panic!("expected `{}` to not parse but got {}", s, cfg), + Err(e) => e.to_string(), + }; + assert!( + e.contains(err), + "when parsing `{}`,\n\"{}\" not contained \ + inside: {}", + s, + err, + e + ); +} + +#[test] +fn cfg_syntax() { + good("foo", c!(foo)); + good("_bar", c!(_bar)); + good(" foo", c!(foo)); + good(" foo ", c!(foo)); + good(" foo = \"bar\"", c!(foo = "bar")); + good("foo=\"\"", c!(foo = "")); + good(" foo=\"3\" ", c!(foo = "3")); + good("foo = \"3 e\"", c!(foo = "3 e")); +} + +#[test] +fn cfg_syntax_bad() { + bad::<Cfg>("", "but cfg expression ended"); + bad::<Cfg>(" ", "but cfg expression ended"); + bad::<Cfg>("\t", "unexpected character"); + bad::<Cfg>("7", "unexpected character"); + bad::<Cfg>("=", "expected identifier"); + bad::<Cfg>(",", "expected identifier"); + bad::<Cfg>("(", "expected identifier"); + bad::<Cfg>("foo (", "unexpected content `(` found after cfg expression"); + bad::<Cfg>("bar =", "expected a string"); + bad::<Cfg>("bar = \"", "unterminated string"); + bad::<Cfg>( + "foo, bar", + "unexpected content `, bar` found after cfg expression", + ); +} + +#[test] +fn cfg_expr() { + good("foo", e!(foo)); + good("_bar", e!(_bar)); + good(" foo", e!(foo)); + good(" foo ", e!(foo)); + good(" foo = \"bar\"", e!(foo = "bar")); + good("foo=\"\"", e!(foo = "")); + good(" foo=\"3\" ", e!(foo = "3")); + good("foo = \"3 e\"", e!(foo = "3 e")); + + good("all()", e!(all())); + good("all(a)", e!(all(a))); + good("all(a, b)", e!(all(a, b))); + good("all(a, )", e!(all(a))); + good("not(a = \"b\")", e!(not(a = "b"))); + good("not(all(a))", e!(not(all(a)))); +} + +#[test] +fn cfg_expr_bad() { + bad::<CfgExpr>(" ", "but cfg expression ended"); + bad::<CfgExpr>(" all", "expected `(`"); + bad::<CfgExpr>("all(a", "expected `)`"); + bad::<CfgExpr>("not", "expected `(`"); + bad::<CfgExpr>("not(a", "expected `)`"); + bad::<CfgExpr>("a = ", "expected a string"); + bad::<CfgExpr>("all(not())", "expected identifier"); + bad::<CfgExpr>( + "foo(a)", + "unexpected content `(a)` found after cfg expression", + ); +} + +#[test] +fn cfg_matches() { + assert!(e!(foo).matches(&[c!(bar), c!(foo), c!(baz)])); + assert!(e!(any(foo)).matches(&[c!(bar), c!(foo), c!(baz)])); + assert!(e!(any(foo, bar)).matches(&[c!(bar)])); + assert!(e!(any(foo, bar)).matches(&[c!(foo)])); + assert!(e!(all(foo, bar)).matches(&[c!(foo), c!(bar)])); + assert!(e!(all(foo, bar)).matches(&[c!(foo), c!(bar)])); + assert!(e!(not(foo)).matches(&[c!(bar)])); + assert!(e!(not(foo)).matches(&[])); + assert!(e!(any((not(foo)), (all(foo, bar)))).matches(&[c!(bar)])); + assert!(e!(any((not(foo)), (all(foo, bar)))).matches(&[c!(foo), c!(bar)])); + + assert!(!e!(foo).matches(&[])); + assert!(!e!(foo).matches(&[c!(bar)])); + assert!(!e!(foo).matches(&[c!(fo)])); + assert!(!e!(any(foo)).matches(&[])); + assert!(!e!(any(foo)).matches(&[c!(bar)])); + assert!(!e!(any(foo)).matches(&[c!(bar), c!(baz)])); + assert!(!e!(all(foo)).matches(&[c!(bar), c!(baz)])); + assert!(!e!(all(foo, bar)).matches(&[c!(bar)])); + assert!(!e!(all(foo, bar)).matches(&[c!(foo)])); + assert!(!e!(all(foo, bar)).matches(&[])); + assert!(!e!(not(bar)).matches(&[c!(bar)])); + assert!(!e!(not(bar)).matches(&[c!(baz), c!(bar)])); + assert!(!e!(any((not(foo)), (all(foo, bar)))).matches(&[c!(foo)])); +} + +#[test] +fn bad_target_name() { + bad::<Platform>( + "any(cfg(unix), cfg(windows))", + "failed to parse `any(cfg(unix), cfg(windows))` as a cfg expression: \ + invalid target specifier: unexpected `(` character, \ + cfg expressions must start with `cfg(`", + ); + bad::<Platform>( + "!foo", + "failed to parse `!foo` as a cfg expression: \ + invalid target specifier: unexpected character ! in target name", + ); +} + +#[test] +fn round_trip_platform() { + fn rt(s: &str) { + let p = Platform::from_str(s).unwrap(); + let s2 = p.to_string(); + let p2 = Platform::from_str(&s2).unwrap(); + assert_eq!(p, p2); + } + rt("x86_64-apple-darwin"); + rt("foo"); + rt("cfg(windows)"); + rt("cfg(target_os = \"windows\")"); + rt( + "cfg(any(all(any(target_os = \"android\", target_os = \"linux\"), \ + any(target_arch = \"aarch64\", target_arch = \"arm\", target_arch = \"powerpc64\", \ + target_arch = \"x86\", target_arch = \"x86_64\")), \ + all(target_os = \"freebsd\", target_arch = \"x86_64\")))", + ); +} + +#[test] +fn check_cfg_attributes() { + fn ok(s: &str) { + let p = Platform::Cfg(s.parse().unwrap()); + let mut warnings = Vec::new(); + p.check_cfg_attributes(&mut warnings); + assert!( + warnings.is_empty(), + "Expected no warnings but got: {:?}", + warnings, + ); + } + + fn warn(s: &str, names: &[&str]) { + let p = Platform::Cfg(s.parse().unwrap()); + let mut warnings = Vec::new(); + p.check_cfg_attributes(&mut warnings); + assert_eq!( + warnings.len(), + names.len(), + "Expecter warnings about {:?} but got {:?}", + names, + warnings, + ); + for (name, warning) in names.iter().zip(warnings.iter()) { + assert!( + warning.contains(name), + "Expected warning about '{}' but got: {}", + name, + warning, + ); + } + } + + ok("unix"); + ok("windows"); + ok("any(not(unix), windows)"); + ok("foo"); + + ok("target_arch = \"abc\""); + ok("target_feature = \"abc\""); + ok("target_os = \"abc\""); + ok("target_family = \"abc\""); + ok("target_env = \"abc\""); + ok("target_endian = \"abc\""); + ok("target_pointer_width = \"abc\""); + ok("target_vendor = \"abc\""); + ok("bar = \"def\""); + + warn("test", &["test"]); + warn("debug_assertions", &["debug_assertions"]); + warn("proc_macro", &["proc_macro"]); + warn("feature = \"abc\"", &["feature"]); + + warn("any(not(debug_assertions), windows)", &["debug_assertions"]); + warn( + "any(not(feature = \"def\"), target_arch = \"abc\")", + &["feature"], + ); + warn( + "any(not(target_os = \"windows\"), proc_macro)", + &["proc_macro"], + ); + warn( + "any(not(feature = \"windows\"), proc_macro)", + &["feature", "proc_macro"], + ); + warn( + "all(not(debug_assertions), any(windows, proc_macro))", + &["debug_assertions", "proc_macro"], + ); +} diff --git a/vendor/cargo_metadata/.cargo-checksum.json b/vendor/cargo_metadata/.cargo-checksum.json new file mode 100644 index 0000000000..754096f9a4 --- /dev/null +++ b/vendor/cargo_metadata/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"eccd5c2f258c7d45f268f4d3b38e62d2d0c7ba61bb5a1b473085f1e755a592c6","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"d51a5b3347bed2441b20986be81bfd4611ca2c5614f950116b273199a9bcf2de","src/dependency.rs":"0220bc9b10b9b234c4fad5bfd3b7d17bf2901e809fe8ca2f0f983701dc8a7be0","src/diagnostic.rs":"fee47d27390f1026ff99ffade5dfd2ab3e9b9839c3f33ce91a7dcde875551374","src/errors.rs":"2d67e46ef8f29a9ae2dd00ce39cc50e6ccae4dec9a09a9bad7c36bd8be4f62cc","src/lib.rs":"857c9265b966733023aa16047d3859b50574cad4bd3c31c81eb2d91d961633c6","src/messages.rs":"a6c32c539d079be131746cb175039e0d2d73416351f2bc1f7ded0e465a6fae9c","tests/selftest.rs":"3a48e0b44679945af6ae7f05e2a473a38684bb106dc5b22cab12b40d8b087b51","tests/test_samples.rs":"4791e28a9c5b2bb19661c7cc2a835787934b911b26271ab0864efd640a7caa62"},"package":"ba2ae6de944143141f6155a473a6b02f66c7c3f9f47316f802f80204ebfe6e12"} \ No newline at end of file diff --git a/vendor/cargo_metadata/Cargo.toml b/vendor/cargo_metadata/Cargo.toml new file mode 100644 index 0000000000..549e0d741c --- /dev/null +++ b/vendor/cargo_metadata/Cargo.toml @@ -0,0 +1,49 @@ +# 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 are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +name = "cargo_metadata" +version = "0.14.1" +authors = ["Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>"] +description = "structured access to the output of `cargo metadata`" +readme = "README.md" +license = "MIT" +repository = "https://github.com/oli-obk/cargo_metadata" +[package.metadata.cargo_metadata_test] +other_field = "foo" +some_field = true +[dependencies.camino] +version = "1.0.1" +features = ["serde1"] + +[dependencies.cargo-platform] +version = "0.1" + +[dependencies.derive_builder] +version = "0.9.0" +optional = true + +[dependencies.semver] +version = "1" +features = ["serde"] + +[dependencies.serde] +version = "1.0.107" +features = ["derive"] + +[dependencies.serde_json] +version = "1.0.59" +features = ["unbounded_depth"] + +[features] +builder = ["derive_builder"] +default = [] diff --git a/vendor/cargo_metadata/LICENSE-MIT b/vendor/cargo_metadata/LICENSE-MIT new file mode 100644 index 0000000000..31aa79387f --- /dev/null +++ b/vendor/cargo_metadata/LICENSE-MIT @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/vendor/cargo_metadata/README.md b/vendor/cargo_metadata/README.md new file mode 100644 index 0000000000..03743f31bc --- /dev/null +++ b/vendor/cargo_metadata/README.md @@ -0,0 +1,12 @@ +# cargo_metadata + +Structured access to the output of `cargo metadata`. Usually used from within a `cargo-*` executable. + +Also supports serialization to aid in implementing `--message-format=json`-like +output generation in `cargo-*` subcommands, since some of the types in what +`cargo --message-format=json` emits are exactly the same as the ones from `cargo metadata`. + +[![Build Status](https://api.travis-ci.org/oli-obk/cargo_metadata.svg?branch=master)](https://travis-ci.org/oli-obk/cargo_metadata) +[![crates.io](https://img.shields.io/crates/v/cargo_metadata.svg)](https://crates.io/crates/cargo_metadata) + +[Documentation](https://docs.rs/cargo_metadata/) diff --git a/vendor/cargo_metadata/src/dependency.rs b/vendor/cargo_metadata/src/dependency.rs new file mode 100644 index 0000000000..fa0f21dabd --- /dev/null +++ b/vendor/cargo_metadata/src/dependency.rs @@ -0,0 +1,90 @@ +//! This module contains `Dependency` and the types/functions it uses for deserialization. + +use std::fmt; + +use camino::Utf8PathBuf; +#[cfg(feature = "builder")] +use derive_builder::Builder; +use semver::VersionReq; +use serde::{Deserialize, Deserializer, Serialize}; + +#[derive(Eq, PartialEq, Clone, Debug, Copy, Hash, Serialize, Deserialize)] +/// Dependencies can come in three kinds +pub enum DependencyKind { + #[serde(rename = "normal")] + /// The 'normal' kind + Normal, + #[serde(rename = "dev")] + /// Those used in tests only + Development, + #[serde(rename = "build")] + /// Those used in build scripts only + Build, + #[doc(hidden)] + #[serde(other)] + Unknown, +} + +impl Default for DependencyKind { + fn default() -> DependencyKind { + DependencyKind::Normal + } +} + +impl fmt::Display for DependencyKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let s = serde_json::to_string(self).unwrap(); + // skip opening and closing quotes + f.write_str(&s[1..s.len() - 1]) + } +} + +/// The `kind` can be `null`, which is interpreted as the default - `Normal`. +pub(super) fn parse_dependency_kind<'de, D>(d: D) -> Result<DependencyKind, D::Error> +where + D: Deserializer<'de>, +{ + Deserialize::deserialize(d).map(|x: Option<_>| x.unwrap_or_default()) +} + +#[derive(Clone, Serialize, Deserialize, Debug)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +/// A dependency of the main crate +pub struct Dependency { + /// Name as given in the `Cargo.toml` + pub name: String, + /// The source of dependency + pub source: Option<String>, + /// The required version + pub req: VersionReq, + /// The kind of dependency this is + #[serde(deserialize_with = "parse_dependency_kind")] + pub kind: DependencyKind, + /// Whether this dependency is required or optional + pub optional: bool, + /// Whether the default features in this dependency are used. + pub uses_default_features: bool, + /// The list of features enabled for this dependency. + pub features: Vec<String>, + /// The target this dependency is specific to. + /// + /// Use the [`Display`] trait to access the contents. + /// + /// [`Display`]: std::fmt::Display + pub target: Option<Platform>, + /// If the dependency is renamed, this is the new name for the dependency + /// as a string. None if it is not renamed. + pub rename: Option<String>, + /// The URL of the index of the registry where this dependency is from. + /// + /// If None, the dependency is from crates.io. + pub registry: Option<String>, + /// The file system path for a local path dependency. + /// + /// Only produced on cargo 1.51+ + pub path: Option<Utf8PathBuf>, +} + +pub use cargo_platform::Platform; diff --git a/vendor/cargo_metadata/src/diagnostic.rs b/vendor/cargo_metadata/src/diagnostic.rs new file mode 100644 index 0000000000..dbe21128a0 --- /dev/null +++ b/vendor/cargo_metadata/src/diagnostic.rs @@ -0,0 +1,160 @@ +//! This module contains `Diagnostic` and the types/functions it uses for deserialization. + +#[cfg(feature = "builder")] +use derive_builder::Builder; +use serde::{Deserialize, Serialize}; +use std::fmt; + +/// The error code associated to this diagnostic. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +pub struct DiagnosticCode { + /// The code itself. + pub code: String, + /// An explanation for the code + pub explanation: Option<String>, +} + +/// A line of code associated with the Diagnostic +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +pub struct DiagnosticSpanLine { + /// The line of code associated with the error + pub text: String, + /// Start of the section of the line to highlight. 1-based, character offset in self.text + pub highlight_start: usize, + /// End of the section of the line to highlight. 1-based, character offset in self.text + pub highlight_end: usize, +} + +/// Macro expansion information associated with a diagnostic. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +pub struct DiagnosticSpanMacroExpansion { + /// span where macro was applied to generate this code; note that + /// this may itself derive from a macro (if + /// `span.expansion.is_some()`) + pub span: DiagnosticSpan, + + /// name of macro that was applied (e.g., "foo!" or "#[derive(Eq)]") + pub macro_decl_name: String, + + /// span where macro was defined (if known) + pub def_site_span: Option<DiagnosticSpan>, +} + +/// A section of the source code associated with a Diagnostic +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +pub struct DiagnosticSpan { + /// The file name or the macro name this diagnostic comes from. + pub file_name: String, + /// The byte offset in the file where this diagnostic starts from. + pub byte_start: u32, + /// The byte offset in the file where this diagnostic ends. + pub byte_end: u32, + /// 1-based. The line in the file. + pub line_start: usize, + /// 1-based. The line in the file. + pub line_end: usize, + /// 1-based, character offset. + pub column_start: usize, + /// 1-based, character offset. + pub column_end: usize, + /// Is this a "primary" span -- meaning the point, or one of the points, + /// where the error occurred? + /// + /// There are rare cases where multiple spans are marked as primary, + /// e.g. "immutable borrow occurs here" and "mutable borrow ends here" can + /// be two separate spans both "primary". Top (parent) messages should + /// always have at least one primary span, unless it has 0 spans. Child + /// messages may have 0 or more primary spans. + pub is_primary: bool, + /// Source text from the start of line_start to the end of line_end. + pub text: Vec<DiagnosticSpanLine>, + /// Label that should be placed at this location (if any) + pub label: Option<String>, + /// If we are suggesting a replacement, this will contain text + /// that should be sliced in atop this span. + pub suggested_replacement: Option<String>, + /// If the suggestion is approximate + pub suggestion_applicability: Option<Applicability>, + /// Macro invocations that created the code at this span, if any. + pub expansion: Option<Box<DiagnosticSpanMacroExpansion>>, +} + +/// Whether a suggestion can be safely applied. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[non_exhaustive] +pub enum Applicability { + /// The suggested replacement can be applied automatically safely + MachineApplicable, + /// The suggested replacement has placeholders that will need to be manually + /// replaced. + HasPlaceholders, + /// The suggested replacement may be incorrect in some circumstances. Needs + /// human review. + MaybeIncorrect, + /// The suggested replacement will probably not work. + Unspecified, +} + +/// The diagnostic level +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[non_exhaustive] +#[serde(rename_all = "lowercase")] +pub enum DiagnosticLevel { + /// Internal compiler error + #[serde(rename = "error: internal compiler error")] + Ice, + /// Error + Error, + /// Warning + Warning, + /// Failure note + #[serde(rename = "failure-note")] + FailureNote, + /// Note + Note, + /// Help + Help, +} + +/// A diagnostic message generated by rustc +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +pub struct Diagnostic { + /// The error message of this diagnostic. + pub message: String, + /// The associated error code for this diagnostic + pub code: Option<DiagnosticCode>, + /// "error: internal compiler error", "error", "warning", "note", "help" + pub level: DiagnosticLevel, + /// A list of source code spans this diagnostic is associated with. + pub spans: Vec<DiagnosticSpan>, + /// Associated diagnostic messages. + pub children: Vec<Diagnostic>, + /// The message as rustc would render it + pub rendered: Option<String>, +} + +impl fmt::Display for Diagnostic { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if let Some(ref rendered) = self.rendered { + f.write_str(rendered)?; + } else { + f.write_str("cargo didn't render this message")?; + } + Ok(()) + } +} diff --git a/vendor/cargo_metadata/src/errors.rs b/vendor/cargo_metadata/src/errors.rs new file mode 100644 index 0000000000..7172057e7f --- /dev/null +++ b/vendor/cargo_metadata/src/errors.rs @@ -0,0 +1,110 @@ +use std::fmt; +use std::io; +use std::str::Utf8Error; +use std::string::FromUtf8Error; + +/// Custom result type for `cargo_metadata::Error` +pub type Result<T> = ::std::result::Result<T, Error>; + +/// Error returned when executing/parsing `cargo metadata` fails. +/// +/// # Note about Backtraces +/// +/// This error type does not contain backtraces, but each error variant +/// comes from _one_ specific place, so it's not really needed for the +/// inside of this crate. If you need a backtrace down to, but not inside +/// of, a failed call of `cargo_metadata` you can do one of multiple thinks: +/// +/// 1. Convert it to a `failure::Error` (possible using the `?` operator), +/// which is similar to a `Box<::std::error::Error + 'static + Send + Sync>`. +/// 2. Have appropriate variants in your own error type. E.g. you could wrap +/// a `failure::Context<Error>` or add a `failure::Backtrace` field (which +/// is empty if `RUST_BACKTRACE` is not set, so it's simple to use). +/// 3. You still can place a failure based error into a `error_chain` if you +/// really want to. (Either through foreign_links or by making it a field +/// value of a `ErrorKind` variant). +/// +#[derive(Debug)] +pub enum Error { + /// Error during execution of `cargo metadata` + CargoMetadata { + /// stderr returned by the `cargo metadata` command + stderr: String, + }, + + /// IO Error during execution of `cargo metadata` + Io(io::Error), + + /// Output of `cargo metadata` was not valid utf8 + Utf8(Utf8Error), + + /// Error output of `cargo metadata` was not valid utf8 + ErrUtf8(FromUtf8Error), + + /// Deserialization error (structure of json did not match expected structure) + Json(::serde_json::Error), + + /// The output did not contain any json + NoJson, +} + +impl From<io::Error> for Error { + fn from(v: io::Error) -> Self { + Error::Io(v) + } +} + +impl From<Utf8Error> for Error { + fn from(v: Utf8Error) -> Self { + Error::Utf8(v) + } +} + +impl From<FromUtf8Error> for Error { + fn from(v: FromUtf8Error) -> Self { + Error::ErrUtf8(v) + } +} + +impl From<::serde_json::Error> for Error { + fn from(v: ::serde_json::Error) -> Self { + Error::Json(v) + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Error::CargoMetadata { stderr } => { + write!( + f, + "`cargo metadata` exited with an error: {}", + stderr.trim_end() + ) + } + Error::Io(err) => write!(f, "failed to start `cargo metadata`: {}", err), + Error::Utf8(err) => write!(f, "cannot convert the stdout of `cargo metadata`: {}", err), + Error::ErrUtf8(err) => { + write!(f, "cannot convert the stderr of `cargo metadata`: {}", err) + } + Error::Json(err) => write!(f, "failed to interpret `cargo metadata`'s json: {}", err), + Error::NoJson => write!( + f, + "could not find any json in the output of `cargo metadata`" + ), + } + } +} + +impl ::std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Error::CargoMetadata { .. } => None, + Error::Io(err) => Some(err), + Error::Utf8(err) => Some(err), + Error::ErrUtf8(err) => Some(err), + Error::Json(err) => Some(err), + Error::NoJson => None, + } + } +} diff --git a/vendor/cargo_metadata/src/lib.rs b/vendor/cargo_metadata/src/lib.rs new file mode 100644 index 0000000000..6e111efe21 --- /dev/null +++ b/vendor/cargo_metadata/src/lib.rs @@ -0,0 +1,641 @@ +#![deny(missing_docs)] +//! Structured access to the output of `cargo metadata` and `cargo --message-format=json`. +//! Usually used from within a `cargo-*` executable +//! +//! See the [cargo book](https://doc.rust-lang.org/cargo/index.html) for +//! details on cargo itself. +//! +//! ## Examples +//! +//! ```rust +//! # extern crate cargo_metadata; +//! # use std::path::Path; +//! let mut args = std::env::args().skip_while(|val| !val.starts_with("--manifest-path")); +//! +//! let mut cmd = cargo_metadata::MetadataCommand::new(); +//! let manifest_path = match args.next() { +//! Some(ref p) if p == "--manifest-path" => { +//! cmd.manifest_path(args.next().unwrap()); +//! } +//! Some(p) => { +//! cmd.manifest_path(p.trim_start_matches("--manifest-path=")); +//! } +//! None => {} +//! }; +//! +//! let _metadata = cmd.exec().unwrap(); +//! ``` +//! +//! Pass features flags +//! +//! ```rust +//! # // This should be kept in sync with the equivalent example in the readme. +//! # extern crate cargo_metadata; +//! # use std::path::Path; +//! # fn main() { +//! use cargo_metadata::{MetadataCommand, CargoOpt}; +//! +//! let _metadata = MetadataCommand::new() +//! .manifest_path("./Cargo.toml") +//! .features(CargoOpt::AllFeatures) +//! .exec() +//! .unwrap(); +//! # } +//! ``` +//! +//! Parse message-format output: +//! +//! ``` +//! # extern crate cargo_metadata; +//! use std::process::{Stdio, Command}; +//! use cargo_metadata::Message; +//! +//! let mut command = Command::new("cargo") +//! .args(&["build", "--message-format=json-render-diagnostics"]) +//! .stdout(Stdio::piped()) +//! .spawn() +//! .unwrap(); +//! +//! let reader = std::io::BufReader::new(command.stdout.take().unwrap()); +//! for message in cargo_metadata::Message::parse_stream(reader) { +//! match message.unwrap() { +//! Message::CompilerMessage(msg) => { +//! println!("{:?}", msg); +//! }, +//! Message::CompilerArtifact(artifact) => { +//! println!("{:?}", artifact); +//! }, +//! Message::BuildScriptExecuted(script) => { +//! println!("{:?}", script); +//! }, +//! Message::BuildFinished(finished) => { +//! println!("{:?}", finished); +//! }, +//! _ => () // Unknown message +//! } +//! } +//! +//! let output = command.wait().expect("Couldn't get cargo's exit status"); +//! ``` + +use camino::Utf8PathBuf; +#[cfg(feature = "builder")] +use derive_builder::Builder; +use std::collections::HashMap; +use std::env; +use std::fmt; +use std::path::PathBuf; +use std::process::Command; +use std::str::from_utf8; + +pub use camino; +pub use semver::{Version, VersionReq}; + +pub use dependency::{Dependency, DependencyKind}; +use diagnostic::Diagnostic; +pub use errors::{Error, Result}; +#[allow(deprecated)] +pub use messages::parse_messages; +pub use messages::{ + Artifact, ArtifactProfile, BuildFinished, BuildScript, CompilerMessage, Message, MessageIter, +}; +use serde::{Deserialize, Serialize}; + +mod dependency; +pub mod diagnostic; +mod errors; +mod messages; + +/// An "opaque" identifier for a package. +/// It is possible to inspect the `repr` field, if the need arises, but its +/// precise format is an implementation detail and is subject to change. +/// +/// `Metadata` can be indexed by `PackageId`. +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[serde(transparent)] +pub struct PackageId { + /// The underlying string representation of id. + pub repr: String, +} + +impl std::fmt::Display for PackageId { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.repr, f) + } +} + +// Helpers for default metadata fields +fn is_null(value: &serde_json::Value) -> bool { + match value { + serde_json::Value::Null => true, + _ => false, + } +} + +#[derive(Clone, Serialize, Deserialize, Debug)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +/// Starting point for metadata returned by `cargo metadata` +pub struct Metadata { + /// A list of all crates referenced by this crate (and the crate itself) + pub packages: Vec<Package>, + /// A list of all workspace members + pub workspace_members: Vec<PackageId>, + /// Dependencies graph + pub resolve: Option<Resolve>, + /// Workspace root + pub workspace_root: Utf8PathBuf, + /// Build directory + pub target_directory: Utf8PathBuf, + /// The workspace-level metadata object. Null if non-existent. + #[serde(rename = "metadata", default, skip_serializing_if = "is_null")] + pub workspace_metadata: serde_json::Value, + /// The metadata format version + version: usize, +} + +impl Metadata { + /// Get the root package of this metadata instance. + pub fn root_package(&self) -> Option<&Package> { + let root = self.resolve.as_ref()?.root.as_ref()?; + self.packages.iter().find(|pkg| &pkg.id == root) + } +} + +impl<'a> std::ops::Index<&'a PackageId> for Metadata { + type Output = Package; + + fn index(&self, idx: &'a PackageId) -> &Package { + self.packages + .iter() + .find(|p| p.id == *idx) + .unwrap_or_else(|| panic!("no package with this id: {:?}", idx)) + } +} + +#[derive(Clone, Serialize, Deserialize, Debug)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +/// A dependency graph +pub struct Resolve { + /// Nodes in a dependencies graph + pub nodes: Vec<Node>, + + /// The crate for which the metadata was read. + pub root: Option<PackageId>, +} + +#[derive(Clone, Serialize, Deserialize, Debug)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +/// A node in a dependencies graph +pub struct Node { + /// An opaque identifier for a package + pub id: PackageId, + /// Dependencies in a structured format. + /// + /// `deps` handles renamed dependencies whereas `dependencies` does not. + #[serde(default)] + pub deps: Vec<NodeDep>, + + /// List of opaque identifiers for this node's dependencies. + /// It doesn't support renamed dependencies. See `deps`. + pub dependencies: Vec<PackageId>, + + /// Features enabled on the crate + #[serde(default)] + pub features: Vec<String>, +} + +#[derive(Clone, Serialize, Deserialize, Debug)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +/// A dependency in a node +pub struct NodeDep { + /// The name of the dependency's library target. + /// If the crate was renamed, it is the new name. + pub name: String, + /// Package ID (opaque unique identifier) + pub pkg: PackageId, + /// The kinds of dependencies. + /// + /// This field was added in Rust 1.41. + #[serde(default)] + pub dep_kinds: Vec<DepKindInfo>, +} + +#[derive(Clone, Serialize, Deserialize, Debug)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +/// Information about a dependency kind. +pub struct DepKindInfo { + /// The kind of dependency. + #[serde(deserialize_with = "dependency::parse_dependency_kind")] + pub kind: DependencyKind, + /// The target platform for the dependency. + /// + /// This is `None` if it is not a target dependency. + /// + /// Use the [`Display`] trait to access the contents. + /// + /// By default all platform dependencies are included in the resolve + /// graph. Use Cargo's `--filter-platform` flag if you only want to + /// include dependencies for a specific platform. + /// + /// [`Display`]: std::fmt::Display + pub target: Option<dependency::Platform>, +} + +#[derive(Clone, Serialize, Deserialize, Debug)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +/// One or more crates described by a single `Cargo.toml` +/// +/// Each [`target`][Package::targets] of a `Package` will be built as a crate. +/// For more information, see <https://doc.rust-lang.org/book/ch07-01-packages-and-crates.html>. +pub struct Package { + /// Name as given in the `Cargo.toml` + pub name: String, + /// Version given in the `Cargo.toml` + pub version: Version, + /// Authors given in the `Cargo.toml` + #[serde(default)] + pub authors: Vec<String>, + /// An opaque identifier for a package + pub id: PackageId, + /// The source of the package, e.g. + /// crates.io or `None` for local projects. + pub source: Option<Source>, + /// Description as given in the `Cargo.toml` + pub description: Option<String>, + /// List of dependencies of this particular package + pub dependencies: Vec<Dependency>, + /// License as given in the `Cargo.toml` + pub license: Option<String>, + /// If the package is using a nonstandard license, this key may be specified instead of + /// `license`, and must point to a file relative to the manifest. + pub license_file: Option<Utf8PathBuf>, + /// Targets provided by the crate (lib, bin, example, test, ...) + pub targets: Vec<Target>, + /// Features provided by the crate, mapped to the features required by that feature. + pub features: HashMap<String, Vec<String>>, + /// Path containing the `Cargo.toml` + pub manifest_path: Utf8PathBuf, + /// Categories as given in the `Cargo.toml` + #[serde(default)] + pub categories: Vec<String>, + /// Keywords as given in the `Cargo.toml` + #[serde(default)] + pub keywords: Vec<String>, + /// Readme as given in the `Cargo.toml` + pub readme: Option<Utf8PathBuf>, + /// Repository as given in the `Cargo.toml` + // can't use `url::Url` because that requires a more recent stable compiler + pub repository: Option<String>, + /// Homepage as given in the `Cargo.toml` + /// + /// On versions of cargo before 1.49, this will always be [`None`]. + pub homepage: Option<String>, + /// Documentation URL as given in the `Cargo.toml` + /// + /// On versions of cargo before 1.49, this will always be [`None`]. + pub documentation: Option<String>, + /// Default Rust edition for the package + /// + /// Beware that individual targets may specify their own edition in + /// [`Target::edition`]. + #[serde(default = "edition_default")] + pub edition: String, + /// Contents of the free form package.metadata section + /// + /// This contents can be serialized to a struct using serde: + /// + /// ```rust + /// use serde::Deserialize; + /// use serde_json::json; + /// + /// #[derive(Debug, Deserialize)] + /// struct SomePackageMetadata { + /// some_value: i32, + /// } + /// + /// fn main() { + /// let value = json!({ + /// "some_value": 42, + /// }); + /// + /// let package_metadata: SomePackageMetadata = serde_json::from_value(value).unwrap(); + /// assert_eq!(package_metadata.some_value, 42); + /// } + /// + /// ``` + #[serde(default, skip_serializing_if = "is_null")] + pub metadata: serde_json::Value, + /// The name of a native library the package is linking to. + pub links: Option<String>, + /// List of registries to which this package may be published. + /// + /// Publishing is unrestricted if `None`, and forbidden if the `Vec` is empty. + /// + /// This is always `None` if running with a version of Cargo older than 1.39. + pub publish: Option<Vec<String>>, + /// The default binary to run by `cargo run`. + /// + /// This is always `None` if running with a version of Cargo older than 1.55. + pub default_run: Option<String>, + /// The minimum supported Rust version of this package. + /// + /// This is always `None` if running with a version of Cargo older than 1.58. + pub rust_version: Option<VersionReq>, +} + +impl Package { + /// Full path to the license file if one is present in the manifest + pub fn license_file(&self) -> Option<Utf8PathBuf> { + self.license_file.as_ref().map(|file| { + self.manifest_path + .parent() + .unwrap_or(&self.manifest_path) + .join(file) + }) + } + + /// Full path to the readme file if one is present in the manifest + pub fn readme(&self) -> Option<Utf8PathBuf> { + self.readme + .as_ref() + .map(|file| self.manifest_path.join(file)) + } +} + +/// The source of a package such as crates.io. +#[derive(Clone, Serialize, Deserialize, Debug)] +#[serde(transparent)] +pub struct Source { + /// The underlying string representation of a source. + pub repr: String, +} + +impl Source { + /// Returns true if the source is crates.io. + pub fn is_crates_io(&self) -> bool { + self.repr == "registry+https://github.com/rust-lang/crates.io-index" + } +} + +impl std::fmt::Display for Source { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.repr, f) + } +} + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +#[non_exhaustive] +/// A single target (lib, bin, example, ...) provided by a crate +pub struct Target { + /// Name as given in the `Cargo.toml` or generated from the file name + pub name: String, + /// Kind of target ("bin", "example", "test", "bench", "lib") + pub kind: Vec<String>, + /// Almost the same as `kind`, except when an example is a library instead of an executable. + /// In that case `crate_types` contains things like `rlib` and `dylib` while `kind` is `example` + #[serde(default)] + #[cfg_attr(feature = "builder", builder(default))] + pub crate_types: Vec<String>, + + #[serde(default)] + #[cfg_attr(feature = "builder", builder(default))] + #[serde(rename = "required-features")] + /// This target is built only if these features are enabled. + /// It doesn't apply to `lib` targets. + pub required_features: Vec<String>, + /// Path to the main source file of the target + pub src_path: Utf8PathBuf, + /// Rust edition for this target + #[serde(default = "edition_default")] + #[cfg_attr(feature = "builder", builder(default = "edition_default()"))] + pub edition: String, + /// Whether or not this target has doc tests enabled, and the target is + /// compatible with doc testing. + /// + /// This is always `true` if running with a version of Cargo older than 1.37. + #[serde(default = "default_true")] + #[cfg_attr(feature = "builder", builder(default = "true"))] + pub doctest: bool, + /// Whether or not this target is tested by default by `cargo test`. + /// + /// This is always `true` if running with a version of Cargo older than 1.47. + #[serde(default = "default_true")] + #[cfg_attr(feature = "builder", builder(default = "true"))] + pub test: bool, + /// Whether or not this target is documented by `cargo doc`. + /// + /// This is always `true` if running with a version of Cargo older than 1.50. + #[serde(default = "default_true")] + #[cfg_attr(feature = "builder", builder(default = "true"))] + pub doc: bool, +} + +fn default_true() -> bool { + true +} + +fn edition_default() -> String { + "2015".to_string() +} + +/// Cargo features flags +#[derive(Debug, Clone)] +pub enum CargoOpt { + /// Run cargo with `--features-all` + AllFeatures, + /// Run cargo with `--no-default-features` + NoDefaultFeatures, + /// Run cargo with `--features <FEATURES>` + SomeFeatures(Vec<String>), +} + +/// A builder for configurating `cargo metadata` invocation. +#[derive(Debug, Clone, Default)] +pub struct MetadataCommand { + /// Path to `cargo` executable. If not set, this will use the + /// the `$CARGO` environment variable, and if that is not set, will + /// simply be `cargo`. + cargo_path: Option<PathBuf>, + /// Path to `Cargo.toml` + manifest_path: Option<PathBuf>, + /// Current directory of the `cargo metadata` process. + current_dir: Option<PathBuf>, + /// Output information only about the root package and don't fetch dependencies. + no_deps: bool, + /// Collections of `CargoOpt::SomeFeatures(..)` + features: Vec<String>, + /// Latched `CargoOpt::AllFeatures` + all_features: bool, + /// Latched `CargoOpt::NoDefaultFeatures` + no_default_features: bool, + /// Arbitrary command line flags to pass to `cargo`. These will be added + /// to the end of the command line invocation. + other_options: Vec<String>, +} + +impl MetadataCommand { + /// Creates a default `cargo metadata` command, which will look for + /// `Cargo.toml` in the ancestors of the current directory. + pub fn new() -> MetadataCommand { + MetadataCommand::default() + } + /// Path to `cargo` executable. If not set, this will use the + /// the `$CARGO` environment variable, and if that is not set, will + /// simply be `cargo`. + pub fn cargo_path(&mut self, path: impl Into<PathBuf>) -> &mut MetadataCommand { + self.cargo_path = Some(path.into()); + self + } + /// Path to `Cargo.toml` + pub fn manifest_path(&mut self, path: impl Into<PathBuf>) -> &mut MetadataCommand { + self.manifest_path = Some(path.into()); + self + } + /// Current directory of the `cargo metadata` process. + pub fn current_dir(&mut self, path: impl Into<PathBuf>) -> &mut MetadataCommand { + self.current_dir = Some(path.into()); + self + } + /// Output information only about the root package and don't fetch dependencies. + pub fn no_deps(&mut self) -> &mut MetadataCommand { + self.no_deps = true; + self + } + /// Which features to include. + /// + /// Call this multiple times to specify advanced feature configurations: + /// + /// ```no_run + /// # use cargo_metadata::{CargoOpt, MetadataCommand}; + /// MetadataCommand::new() + /// .features(CargoOpt::NoDefaultFeatures) + /// .features(CargoOpt::SomeFeatures(vec!["feat1".into(), "feat2".into()])) + /// .features(CargoOpt::SomeFeatures(vec!["feat3".into()])) + /// // ... + /// # ; + /// ``` + /// + /// # Panics + /// + /// `cargo metadata` rejects multiple `--no-default-features` flags. Similarly, the `features()` + /// method panics when specifying multiple `CargoOpt::NoDefaultFeatures`: + /// + /// ```should_panic + /// # use cargo_metadata::{CargoOpt, MetadataCommand}; + /// MetadataCommand::new() + /// .features(CargoOpt::NoDefaultFeatures) + /// .features(CargoOpt::NoDefaultFeatures) // <-- panic! + /// // ... + /// # ; + /// ``` + /// + /// The method also panics for multiple `CargoOpt::AllFeatures` arguments: + /// + /// ```should_panic + /// # use cargo_metadata::{CargoOpt, MetadataCommand}; + /// MetadataCommand::new() + /// .features(CargoOpt::AllFeatures) + /// .features(CargoOpt::AllFeatures) // <-- panic! + /// // ... + /// # ; + /// ``` + pub fn features(&mut self, features: CargoOpt) -> &mut MetadataCommand { + match features { + CargoOpt::SomeFeatures(features) => self.features.extend(features), + CargoOpt::NoDefaultFeatures => { + assert!( + !self.no_default_features, + "Do not supply CargoOpt::NoDefaultFeatures more than once!" + ); + self.no_default_features = true; + } + CargoOpt::AllFeatures => { + assert!( + !self.all_features, + "Do not supply CargoOpt::AllFeatures more than once!" + ); + self.all_features = true; + } + } + self + } + /// Arbitrary command line flags to pass to `cargo`. These will be added + /// to the end of the command line invocation. + pub fn other_options(&mut self, options: impl Into<Vec<String>>) -> &mut MetadataCommand { + self.other_options = options.into(); + self + } + + /// Builds a command for `cargo metadata`. This is the first + /// part of the work of `exec`. + pub fn cargo_command(&self) -> Command { + let cargo = self + .cargo_path + .clone() + .or_else(|| env::var("CARGO").map(PathBuf::from).ok()) + .unwrap_or_else(|| PathBuf::from("cargo")); + let mut cmd = Command::new(cargo); + cmd.args(&["metadata", "--format-version", "1"]); + + if self.no_deps { + cmd.arg("--no-deps"); + } + + if let Some(path) = self.current_dir.as_ref() { + cmd.current_dir(path); + } + + if !self.features.is_empty() { + cmd.arg("--features").arg(self.features.join(",")); + } + if self.all_features { + cmd.arg("--all-features"); + } + if self.no_default_features { + cmd.arg("--no-default-features"); + } + + if let Some(manifest_path) = &self.manifest_path { + cmd.arg("--manifest-path").arg(manifest_path.as_os_str()); + } + cmd.args(&self.other_options); + + cmd + } + + /// Parses `cargo metadata` output. `data` must have been + /// produced by a command built with `cargo_command`. + pub fn parse<T: AsRef<str>>(data: T) -> Result<Metadata> { + let meta = serde_json::from_str(data.as_ref())?; + Ok(meta) + } + + /// Runs configured `cargo metadata` and returns parsed `Metadata`. + pub fn exec(&self) -> Result<Metadata> { + let output = self.cargo_command().output()?; + if !output.status.success() { + return Err(Error::CargoMetadata { + stderr: String::from_utf8(output.stderr)?, + }); + } + let stdout = from_utf8(&output.stdout)? + .lines() + .find(|line| line.starts_with('{')) + .ok_or_else(|| Error::NoJson)?; + Self::parse(stdout) + } +} diff --git a/vendor/cargo_metadata/src/messages.rs b/vendor/cargo_metadata/src/messages.rs new file mode 100644 index 0000000000..a52cde1690 --- /dev/null +++ b/vendor/cargo_metadata/src/messages.rs @@ -0,0 +1,165 @@ +use super::{Diagnostic, PackageId, Target}; +use camino::Utf8PathBuf; +#[cfg(feature = "builder")] +use derive_builder::Builder; +use serde::{Deserialize, Serialize}; +use std::fmt; +use std::io::{self, BufRead, Lines, Read}; + +/// Profile settings used to determine which compiler flags to use for a +/// target. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +pub struct ArtifactProfile { + /// Optimization level. Possible values are 0-3, s or z. + pub opt_level: String, + /// The amount of debug info. 0 for none, 1 for limited, 2 for full + pub debuginfo: Option<u32>, + /// State of the `cfg(debug_assertions)` directive, enabling macros like + /// `debug_assert!` + pub debug_assertions: bool, + /// State of the overflow checks. + pub overflow_checks: bool, + /// Whether this profile is a test + pub test: bool, +} + +/// A compiler-generated file. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +pub struct Artifact { + /// The package this artifact belongs to + pub package_id: PackageId, + /// The target this artifact was compiled for + pub target: Target, + /// The profile this artifact was compiled with + pub profile: ArtifactProfile, + /// The enabled features for this artifact + pub features: Vec<String>, + /// The full paths to the generated artifacts + /// (e.g. binary file and separate debug info) + pub filenames: Vec<Utf8PathBuf>, + /// Path to the executable file + pub executable: Option<Utf8PathBuf>, + /// If true, then the files were already generated + pub fresh: bool, +} + +/// Message left by the compiler +// TODO: Better name. This one comes from machine_message.rs +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +pub struct CompilerMessage { + /// The package this message belongs to + pub package_id: PackageId, + /// The target this message is aimed at + pub target: Target, + /// The message the compiler sent. + pub message: Diagnostic, +} + +/// Output of a build script execution. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +pub struct BuildScript { + /// The package this build script execution belongs to + pub package_id: PackageId, + /// The libs to link + pub linked_libs: Vec<Utf8PathBuf>, + /// The paths to search when resolving libs + pub linked_paths: Vec<Utf8PathBuf>, + /// Various `--cfg` flags to pass to the compiler + pub cfgs: Vec<String>, + /// The environment variables to add to the compilation + pub env: Vec<(String, String)>, + /// The `OUT_DIR` environment variable where this script places its output + /// + /// Added in Rust 1.41. + #[serde(default)] + pub out_dir: Utf8PathBuf, +} + +/// Final result of a build. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +pub struct BuildFinished { + /// Whether or not the build finished successfully. + pub success: bool, +} + +/// A cargo message +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[non_exhaustive] +#[serde(tag = "reason", rename_all = "kebab-case")] +pub enum Message { + /// The compiler generated an artifact + CompilerArtifact(Artifact), + /// The compiler wants to display a message + CompilerMessage(CompilerMessage), + /// A build script successfully executed. + BuildScriptExecuted(BuildScript), + /// The build has finished. + /// + /// This is emitted at the end of the build as the last message. + /// Added in Rust 1.44. + BuildFinished(BuildFinished), + /// A line of text which isn't a cargo or compiler message. + /// Line separator is not included + #[serde(skip)] + TextLine(String), +} + +impl Message { + /// Creates an iterator of Message from a Read outputting a stream of JSON + /// messages. For usage information, look at the top-level documentation. + pub fn parse_stream<R: BufRead>(input: R) -> MessageIter<R> { + MessageIter { + lines: input.lines(), + } + } +} + +impl fmt::Display for CompilerMessage { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.message) + } +} + +/// An iterator of Messages. +pub struct MessageIter<R> { + lines: Lines<R>, +} + +impl<R: BufRead> Iterator for MessageIter<R> { + type Item = io::Result<Message>; + fn next(&mut self) -> Option<Self::Item> { + let line = self.lines.next()?; + let message = line.map(|it| { + let mut deserializer = serde_json::Deserializer::from_str(&it); + deserializer.disable_recursion_limit(); + Message::deserialize(&mut deserializer).unwrap_or(Message::TextLine(it)) + }); + Some(message) + } +} + +/// An iterator of Message. +type MessageIterator<R> = + serde_json::StreamDeserializer<'static, serde_json::de::IoRead<R>, Message>; + +/// Creates an iterator of Message from a Read outputting a stream of JSON +/// messages. For usage information, look at the top-level documentation. +#[deprecated(note = "Use Message::parse_stream instead")] +pub fn parse_messages<R: Read>(input: R) -> MessageIterator<R> { + serde_json::Deserializer::from_reader(input).into_iter::<Message>() +} diff --git a/vendor/cargo_metadata/tests/selftest.rs b/vendor/cargo_metadata/tests/selftest.rs new file mode 100644 index 0000000000..70b131b530 --- /dev/null +++ b/vendor/cargo_metadata/tests/selftest.rs @@ -0,0 +1,159 @@ +use std::env::current_dir; +use std::path::PathBuf; + +use semver::Version; + +use cargo_metadata::{CargoOpt, Error, MetadataCommand}; +use serde::Deserialize; + +#[derive(Debug, PartialEq, Eq, Deserialize)] +struct TestPackageMetadata { + some_field: bool, + other_field: String, +} + +#[test] +fn metadata() { + let metadata = MetadataCommand::new().no_deps().exec().unwrap(); + + let this = &metadata.packages[0]; + assert_eq!(this.name, "cargo_metadata"); + assert_eq!(this.targets.len(), 3); + + let lib = this + .targets + .iter() + .find(|t| t.name == "cargo_metadata") + .unwrap(); + assert_eq!(lib.kind[0], "lib"); + assert_eq!(lib.crate_types[0], "lib"); + + let selftest = this.targets.iter().find(|t| t.name == "selftest").unwrap(); + assert_eq!(selftest.name, "selftest"); + assert_eq!(selftest.kind[0], "test"); + assert_eq!(selftest.crate_types[0], "bin"); + + let package_metadata = &metadata.packages[0] + .metadata + .as_object() + .expect("package.metadata must be a table."); + assert_eq!(package_metadata.len(), 1); + + let value = package_metadata.get("cargo_metadata_test").unwrap(); + let test_package_metadata: TestPackageMetadata = serde_json::from_value(value.clone()).unwrap(); + assert_eq!( + test_package_metadata, + TestPackageMetadata { + some_field: true, + other_field: "foo".into(), + } + ); +} + +#[test] +fn builder_interface() { + let _ = MetadataCommand::new() + .manifest_path("Cargo.toml") + .exec() + .unwrap(); + let _ = MetadataCommand::new() + .manifest_path(String::from("Cargo.toml")) + .exec() + .unwrap(); + let _ = MetadataCommand::new() + .manifest_path(PathBuf::from("Cargo.toml")) + .exec() + .unwrap(); + let _ = MetadataCommand::new() + .manifest_path("Cargo.toml") + .no_deps() + .exec() + .unwrap(); + let _ = MetadataCommand::new() + .manifest_path("Cargo.toml") + .features(CargoOpt::AllFeatures) + .exec() + .unwrap(); + let _ = MetadataCommand::new() + .manifest_path("Cargo.toml") + .current_dir(current_dir().unwrap()) + .exec() + .unwrap(); +} + +#[test] +fn error1() { + match MetadataCommand::new().manifest_path("foo").exec() { + Err(Error::CargoMetadata { stderr }) => assert_eq!( + stderr.trim(), + "error: the manifest-path must be a path to a Cargo.toml file" + ), + _ => unreachable!(), + } +} + +#[test] +fn error2() { + match MetadataCommand::new() + .manifest_path("foo/Cargo.toml") + .exec() + { + Err(Error::CargoMetadata { stderr }) => assert_eq!( + stderr.trim(), + "error: manifest path `foo/Cargo.toml` does not exist" + ), + _ => unreachable!(), + } +} + +#[test] +fn cargo_path() { + match MetadataCommand::new() + .cargo_path("this does not exist") + .exec() + { + Err(Error::Io(e)) => assert_eq!(e.kind(), std::io::ErrorKind::NotFound), + _ => unreachable!(), + } +} + +#[test] +fn metadata_deps() { + std::env::set_var("CARGO_PROFILE", "3"); + let metadata = MetadataCommand::new() + .manifest_path("Cargo.toml") + .exec() + .unwrap(); + let this_id = metadata + .workspace_members + .first() + .expect("Did not find ourselves"); + let this = &metadata[this_id]; + + assert_eq!(this.name, "cargo_metadata"); + + let lib = this + .targets + .iter() + .find(|t| t.name == "cargo_metadata") + .unwrap(); + assert_eq!(lib.kind[0], "lib"); + assert_eq!(lib.crate_types[0], "lib"); + + let selftest = this.targets.iter().find(|t| t.name == "selftest").unwrap(); + assert_eq!(selftest.name, "selftest"); + assert_eq!(selftest.kind[0], "test"); + assert_eq!(selftest.crate_types[0], "bin"); + + let dependencies = &this.dependencies; + + let serde = dependencies + .iter() + .find(|dep| dep.name == "serde") + .expect("Did not find serde dependency"); + + assert_eq!(serde.kind, cargo_metadata::DependencyKind::Normal); + assert!(!serde.req.matches(&Version::parse("1.0.0").unwrap())); + assert!(serde.req.matches(&Version::parse("1.99.99").unwrap())); + assert!(!serde.req.matches(&Version::parse("2.0.0").unwrap())); +} diff --git a/vendor/cargo_metadata/tests/test_samples.rs b/vendor/cargo_metadata/tests/test_samples.rs new file mode 100644 index 0000000000..c5d9c3ce61 --- /dev/null +++ b/vendor/cargo_metadata/tests/test_samples.rs @@ -0,0 +1,621 @@ +extern crate cargo_metadata; +extern crate semver; +#[macro_use] +extern crate serde_json; + +use camino::Utf8PathBuf; +use cargo_metadata::{CargoOpt, DependencyKind, Metadata, MetadataCommand}; + +#[test] +fn old_minimal() { + // Output from oldest supported version (1.24). + // This intentionally has as many null fields as possible. + // 1.8 is when metadata was introduced. + // Older versions not supported because the following are required: + // - `workspace_members` added in 1.13 + // - `target_directory` added in 1.19 + // - `workspace_root` added in 1.24 + let json = r#" +{ + "packages": [ + { + "name": "foo", + "version": "0.1.0", + "id": "foo 0.1.0 (path+file:///foo)", + "license": null, + "license_file": null, + "description": null, + "source": null, + "dependencies": [ + { + "name": "somedep", + "source": null, + "req": "^1.0", + "kind": null, + "optional": false, + "uses_default_features": true, + "features": [], + "target": null + } + ], + "targets": [ + { + "kind": [ + "bin" + ], + "crate_types": [ + "bin" + ], + "name": "foo", + "src_path": "/foo/src/main.rs" + } + ], + "features": {}, + "manifest_path": "/foo/Cargo.toml" + } + ], + "workspace_members": [ + "foo 0.1.0 (path+file:///foo)" + ], + "resolve": null, + "target_directory": "/foo/target", + "version": 1, + "workspace_root": "/foo" +} +"#; + let meta: Metadata = serde_json::from_str(json).unwrap(); + assert_eq!(meta.packages.len(), 1); + let pkg = &meta.packages[0]; + assert_eq!(pkg.name, "foo"); + assert_eq!(pkg.version, semver::Version::parse("0.1.0").unwrap()); + assert_eq!(pkg.authors.len(), 0); + assert_eq!(pkg.id.to_string(), "foo 0.1.0 (path+file:///foo)"); + assert_eq!(pkg.description, None); + assert_eq!(pkg.license, None); + assert_eq!(pkg.license_file, None); + assert_eq!(pkg.default_run, None); + assert_eq!(pkg.rust_version, None); + assert_eq!(pkg.dependencies.len(), 1); + let dep = &pkg.dependencies[0]; + assert_eq!(dep.name, "somedep"); + assert_eq!(dep.source, None); + assert_eq!(dep.req, semver::VersionReq::parse("^1.0").unwrap()); + assert_eq!(dep.kind, DependencyKind::Normal); + assert_eq!(dep.optional, false); + assert_eq!(dep.uses_default_features, true); + assert_eq!(dep.features.len(), 0); + assert!(dep.target.is_none()); + assert_eq!(dep.rename, None); + assert_eq!(dep.registry, None); + assert_eq!(pkg.targets.len(), 1); + let target = &pkg.targets[0]; + assert_eq!(target.name, "foo"); + assert_eq!(target.kind, vec!["bin"]); + assert_eq!(target.crate_types, vec!["bin"]); + assert_eq!(target.required_features.len(), 0); + assert_eq!(target.src_path, "/foo/src/main.rs"); + assert_eq!(target.edition, "2015"); + assert_eq!(target.doctest, true); + assert_eq!(target.test, true); + assert_eq!(target.doc, true); + assert_eq!(pkg.features.len(), 0); + assert_eq!(pkg.manifest_path, "/foo/Cargo.toml"); + assert_eq!(pkg.categories.len(), 0); + assert_eq!(pkg.keywords.len(), 0); + assert_eq!(pkg.readme, None); + assert_eq!(pkg.repository, None); + assert_eq!(pkg.homepage, None); + assert_eq!(pkg.documentation, None); + assert_eq!(pkg.edition, "2015"); + assert_eq!(pkg.metadata, serde_json::Value::Null); + assert_eq!(pkg.links, None); + assert_eq!(pkg.publish, None); + assert_eq!(meta.workspace_members.len(), 1); + assert_eq!( + meta.workspace_members[0].to_string(), + "foo 0.1.0 (path+file:///foo)" + ); + assert!(meta.resolve.is_none()); + assert_eq!(meta.workspace_root, "/foo"); + assert_eq!(meta.workspace_metadata, serde_json::Value::Null); + assert_eq!(meta.target_directory, "/foo/target"); +} + +macro_rules! sorted { + ($e:expr) => {{ + let mut v = $e.clone(); + v.sort(); + v + }}; +} + +fn cargo_version() -> semver::Version { + let output = std::process::Command::new("cargo") + .arg("-V") + .output() + .expect("Failed to exec cargo."); + let out = std::str::from_utf8(&output.stdout) + .expect("invalid utf8") + .trim(); + let split: Vec<&str> = out.split_whitespace().collect(); + assert!(split.len() >= 2, "cargo -V output is unexpected: {}", out); + let mut ver = semver::Version::parse(split[1]).expect("cargo -V semver could not be parsed"); + // Don't care about metadata, it is awkward to compare. + ver.pre = semver::Prerelease::EMPTY; + ver.build = semver::BuildMetadata::EMPTY; + ver +} + +#[derive(serde::Deserialize, PartialEq, Eq, Debug)] +struct WorkspaceMetadata { + testobject: TestObject, +} + +#[derive(serde::Deserialize, PartialEq, Eq, Debug)] +struct TestObject { + myvalue: String, +} + +#[test] +fn all_the_fields() { + // All the fields currently generated as of 1.58. This tries to exercise as + // much as possible. + let ver = cargo_version(); + let minimum = semver::Version::parse("1.56.0").unwrap(); + if ver < minimum { + // edition added in 1.30 + // rename added in 1.31 + // links added in 1.33 + // doctest added in 1.37 + // publish added in 1.39 + // dep_kinds added in 1.41 + // test added in 1.47 + // homepage added in 1.49 + // documentation added in 1.49 + // doc added in 1.50 + // path added in 1.51 + // default_run added in 1.55 + // rust_version added in 1.58 + eprintln!("Skipping all_the_fields test, cargo {} is too old.", ver); + return; + } + let meta = MetadataCommand::new() + .manifest_path("tests/all/Cargo.toml") + .exec() + .unwrap(); + assert_eq!(meta.workspace_root.file_name().unwrap(), "all"); + assert_eq!( + serde_json::from_value::<WorkspaceMetadata>(meta.workspace_metadata).unwrap(), + WorkspaceMetadata { + testobject: TestObject { + myvalue: "abc".to_string() + } + } + ); + assert_eq!(meta.workspace_members.len(), 1); + assert!(meta.workspace_members[0].to_string().starts_with("all")); + + assert_eq!(meta.packages.len(), 9); + let all = meta.packages.iter().find(|p| p.name == "all").unwrap(); + assert_eq!(all.version, semver::Version::parse("0.1.0").unwrap()); + assert_eq!(all.authors, vec!["Jane Doe <user@example.com>"]); + assert!(all.id.to_string().starts_with("all")); + assert_eq!(all.description, Some("Package description.".to_string())); + assert_eq!(all.license, Some("MIT/Apache-2.0".to_string())); + assert_eq!(all.license_file, Some(Utf8PathBuf::from("LICENSE"))); + assert!(all.license_file().unwrap().ends_with("tests/all/LICENSE")); + assert_eq!(all.publish, Some(vec![])); + assert_eq!(all.links, Some("foo".to_string())); + assert_eq!(all.default_run, Some("otherbin".to_string())); + if ver >= semver::Version::parse("1.58.0").unwrap() { + assert_eq!( + all.rust_version, + Some(semver::VersionReq::parse("1.56").unwrap()) + ); + } + + assert_eq!(all.dependencies.len(), 8); + let bitflags = all + .dependencies + .iter() + .find(|d| d.name == "bitflags") + .unwrap(); + assert_eq!( + bitflags.source, + Some("registry+https://github.com/rust-lang/crates.io-index".to_string()) + ); + assert_eq!(bitflags.optional, true); + assert_eq!(bitflags.req, semver::VersionReq::parse("^1.0").unwrap()); + + let path_dep = all + .dependencies + .iter() + .find(|d| d.name == "path-dep") + .unwrap(); + assert_eq!(path_dep.source, None); + assert_eq!(path_dep.kind, DependencyKind::Normal); + assert_eq!(path_dep.req, semver::VersionReq::parse("*").unwrap()); + assert_eq!( + path_dep.path.as_ref().map(|p| p.ends_with("path-dep")), + Some(true), + ); + + all.dependencies + .iter() + .find(|d| d.name == "namedep") + .unwrap(); + + let featdep = all + .dependencies + .iter() + .find(|d| d.name == "featdep") + .unwrap(); + assert_eq!(featdep.features, vec!["i128"]); + assert_eq!(featdep.uses_default_features, false); + + let renamed = all + .dependencies + .iter() + .find(|d| d.name == "oldname") + .unwrap(); + assert_eq!(renamed.rename, Some("newname".to_string())); + + let devdep = all + .dependencies + .iter() + .find(|d| d.name == "devdep") + .unwrap(); + assert_eq!(devdep.kind, DependencyKind::Development); + + let bdep = all.dependencies.iter().find(|d| d.name == "bdep").unwrap(); + assert_eq!(bdep.kind, DependencyKind::Build); + + let windep = all + .dependencies + .iter() + .find(|d| d.name == "windep") + .unwrap(); + assert_eq!( + windep.target.as_ref().map(|x| x.to_string()), + Some("cfg(windows)".to_string()) + ); + + macro_rules! get_file_name { + ($v:expr) => { + all.targets + .iter() + .find(|t| t.src_path.file_name().unwrap() == $v) + .unwrap() + }; + } + assert_eq!(all.targets.len(), 8); + let lib = get_file_name!("lib.rs"); + assert_eq!(lib.name, "all"); + assert_eq!( + sorted!(lib.kind), + vec!["cdylib", "dylib", "rlib", "staticlib"] + ); + assert_eq!( + sorted!(lib.crate_types), + vec!["cdylib", "dylib", "rlib", "staticlib"] + ); + assert_eq!(lib.required_features.len(), 0); + assert_eq!(lib.edition, "2018"); + assert_eq!(lib.doctest, true); + assert_eq!(lib.test, true); + assert_eq!(lib.doc, true); + + let main = get_file_name!("main.rs"); + assert_eq!(main.crate_types, vec!["bin"]); + assert_eq!(main.kind, vec!["bin"]); + assert_eq!(main.doctest, false); + assert_eq!(main.test, true); + assert_eq!(main.doc, true); + + let otherbin = get_file_name!("otherbin.rs"); + assert_eq!(otherbin.edition, "2015"); + assert_eq!(otherbin.doc, false); + + let reqfeat = get_file_name!("reqfeat.rs"); + assert_eq!(reqfeat.required_features, vec!["feat2"]); + + let ex1 = get_file_name!("ex1.rs"); + assert_eq!(ex1.kind, vec!["example"]); + assert_eq!(ex1.test, false); + + let t1 = get_file_name!("t1.rs"); + assert_eq!(t1.kind, vec!["test"]); + + let b1 = get_file_name!("b1.rs"); + assert_eq!(b1.kind, vec!["bench"]); + + let build = get_file_name!("build.rs"); + assert_eq!(build.kind, vec!["custom-build"]); + + assert_eq!(all.features.len(), 3); + assert_eq!(all.features["feat1"].len(), 0); + assert_eq!(all.features["feat2"].len(), 0); + assert_eq!(sorted!(all.features["default"]), vec!["bitflags", "feat1"]); + + assert!(all.manifest_path.ends_with("all/Cargo.toml")); + assert_eq!(all.categories, vec!["command-line-utilities"]); + assert_eq!(all.keywords, vec!["cli"]); + assert_eq!(all.readme, Some(Utf8PathBuf::from("README.md"))); + assert_eq!( + all.repository, + Some("https://github.com/oli-obk/cargo_metadata/".to_string()) + ); + assert_eq!( + all.homepage, + Some("https://github.com/oli-obk/cargo_metadata/".to_string()) + ); + assert_eq!( + all.documentation, + Some("https://docs.rs/cargo_metadata/".to_string()) + ); + assert_eq!(all.edition, "2018"); + assert_eq!( + all.metadata, + json!({ + "docs": { + "rs": { + "all-features": true, + "default-target": "x86_64-unknown-linux-gnu", + "rustc-args": ["--example-rustc-arg"] + } + } + }) + ); + + let resolve = meta.resolve.as_ref().unwrap(); + assert!(resolve + .root + .as_ref() + .unwrap() + .to_string() + .starts_with("all")); + + assert_eq!(resolve.nodes.len(), 9); + let path_dep = resolve + .nodes + .iter() + .find(|n| n.id.to_string().starts_with("path-dep")) + .unwrap(); + assert_eq!(path_dep.deps.len(), 0); + assert_eq!(path_dep.dependencies.len(), 0); + assert_eq!(path_dep.features.len(), 0); + + let bitflags = resolve + .nodes + .iter() + .find(|n| n.id.to_string().starts_with("bitflags")) + .unwrap(); + assert_eq!(bitflags.features, vec!["default"]); + + let featdep = resolve + .nodes + .iter() + .find(|n| n.id.to_string().starts_with("featdep")) + .unwrap(); + assert_eq!(featdep.features, vec!["i128"]); + + let all = resolve + .nodes + .iter() + .find(|n| n.id.to_string().starts_with("all")) + .unwrap(); + assert_eq!(all.dependencies.len(), 8); + assert_eq!(all.deps.len(), 8); + let newname = all.deps.iter().find(|d| d.name == "newname").unwrap(); + assert!(newname.pkg.to_string().starts_with("oldname")); + // Note the underscore here. + let path_dep = all.deps.iter().find(|d| d.name == "path_dep").unwrap(); + assert!(path_dep.pkg.to_string().starts_with("path-dep")); + assert_eq!(path_dep.dep_kinds.len(), 1); + let kind = &path_dep.dep_kinds[0]; + assert_eq!(kind.kind, DependencyKind::Normal); + assert!(kind.target.is_none()); + + let namedep = all + .deps + .iter() + .find(|d| d.name == "different_name") + .unwrap(); + assert!(namedep.pkg.to_string().starts_with("namedep")); + assert_eq!(sorted!(all.features), vec!["bitflags", "default", "feat1"]); + + let bdep = all.deps.iter().find(|d| d.name == "bdep").unwrap(); + assert_eq!(bdep.dep_kinds.len(), 1); + let kind = &bdep.dep_kinds[0]; + assert_eq!(kind.kind, DependencyKind::Build); + assert!(kind.target.is_none()); + + let devdep = all.deps.iter().find(|d| d.name == "devdep").unwrap(); + assert_eq!(devdep.dep_kinds.len(), 1); + let kind = &devdep.dep_kinds[0]; + assert_eq!(kind.kind, DependencyKind::Development); + assert!(kind.target.is_none()); + + let windep = all.deps.iter().find(|d| d.name == "windep").unwrap(); + assert_eq!(windep.dep_kinds.len(), 1); + let kind = &windep.dep_kinds[0]; + assert_eq!(kind.kind, DependencyKind::Normal); + assert_eq!( + kind.target.as_ref().map(|x| x.to_string()), + Some("cfg(windows)".to_string()) + ); +} + +#[test] +fn alt_registry() { + // This is difficult to test (would need to set up a custom index). + // Just manually check the JSON is handled. + let json = r#" +{ + "packages": [ + { + "name": "alt", + "version": "0.1.0", + "id": "alt 0.1.0 (path+file:///alt)", + "source": null, + "dependencies": [ + { + "name": "alt2", + "source": "registry+https://example.com", + "req": "^0.1", + "kind": null, + "rename": null, + "optional": false, + "uses_default_features": true, + "features": [], + "target": null, + "registry": "https://example.com" + } + ], + "targets": [ + { + "kind": [ + "lib" + ], + "crate_types": [ + "lib" + ], + "name": "alt", + "src_path": "/alt/src/lib.rs", + "edition": "2018" + } + ], + "features": {}, + "manifest_path": "/alt/Cargo.toml", + "metadata": null, + "authors": [], + "categories": [], + "keywords": [], + "readme": null, + "repository": null, + "edition": "2018", + "links": null + } + ], + "workspace_members": [ + "alt 0.1.0 (path+file:///alt)" + ], + "resolve": null, + "target_directory": "/alt/target", + "version": 1, + "workspace_root": "/alt" +} +"#; + let meta: Metadata = serde_json::from_str(json).unwrap(); + assert_eq!(meta.packages.len(), 1); + let alt = &meta.packages[0]; + let deps = &alt.dependencies; + assert_eq!(deps.len(), 1); + let dep = &deps[0]; + assert_eq!(dep.registry, Some("https://example.com".to_string())); +} + +#[test] +fn current_dir() { + let meta = MetadataCommand::new() + .current_dir("tests/all/namedep") + .exec() + .unwrap(); + let namedep = meta.packages.iter().find(|p| p.name == "namedep").unwrap(); + assert!(namedep.name.starts_with("namedep")); +} + +#[test] +fn parse_stream_is_robust() { + // Proc macros can print stuff to stdout, which naturally breaks JSON messages. + // Let's check that we don't die horribly in this case, and report an error. + let json_output = r##"{"reason":"compiler-artifact","package_id":"chatty 0.1.0 (path+file:///chatty-macro/chatty)","target":{"kind":["proc-macro"],"crate_types":["proc-macro"],"name":"chatty","src_path":"/chatty-macro/chatty/src/lib.rs","edition":"2018","doctest":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/chatty-macro/target/debug/deps/libchatty-f2adcff24cdf3bb2.so"],"executable":null,"fresh":false} +Evil proc macro was here! +{"reason":"compiler-artifact","package_id":"chatty-macro 0.1.0 (path+file:///chatty-macro)","target":{"kind":["lib"],"crate_types":["lib"],"name":"chatty-macro","src_path":"/chatty-macro/src/lib.rs","edition":"2018","doctest":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/chatty-macro/target/debug/libchatty_macro.rlib","/chatty-macro/target/debug/deps/libchatty_macro-cb5956ed52a11fb6.rmeta"],"executable":null,"fresh":false} +"##; + let mut n_messages = 0; + let mut text = String::new(); + for message in cargo_metadata::Message::parse_stream(json_output.as_bytes()) { + let message = message.unwrap(); + match message { + cargo_metadata::Message::TextLine(line) => text = line, + _ => n_messages += 1, + } + } + assert_eq!(n_messages, 2); + assert_eq!(text, "Evil proc macro was here!"); +} + +#[test] +fn advanced_feature_configuration() { + fn build_features<F: FnOnce(&mut MetadataCommand) -> &mut MetadataCommand>( + func: F, + ) -> Vec<String> { + let mut meta = MetadataCommand::new(); + let meta = meta.manifest_path("tests/all/Cargo.toml"); + + let meta = func(meta); + let meta = meta.exec().unwrap(); + + let resolve = meta.resolve.as_ref().unwrap(); + + let all = resolve + .nodes + .iter() + .find(|n| n.id.to_string().starts_with("all")) + .unwrap(); + + all.features.clone() + } + + // Default behavior; tested above + let default_features = build_features(|meta| meta); + assert_eq!( + sorted!(default_features), + vec!["bitflags", "default", "feat1"] + ); + + // Manually specify the same default features + let manual_features = build_features(|meta| { + meta.features(CargoOpt::NoDefaultFeatures) + .features(CargoOpt::SomeFeatures(vec![ + "feat1".into(), + "bitflags".into(), + ])) + }); + assert_eq!(sorted!(manual_features), vec!["bitflags", "feat1"]); + + // Multiple SomeFeatures is same as one longer SomeFeatures + let manual_features = build_features(|meta| { + meta.features(CargoOpt::NoDefaultFeatures) + .features(CargoOpt::SomeFeatures(vec!["feat1".into()])) + .features(CargoOpt::SomeFeatures(vec!["feat2".into()])) + }); + assert_eq!(sorted!(manual_features), vec!["feat1", "feat2"]); + + // No features + All features == All features + let all_features = build_features(|meta| { + meta.features(CargoOpt::AllFeatures) + .features(CargoOpt::NoDefaultFeatures) + }); + assert_eq!( + sorted!(all_features), + vec!["bitflags", "default", "feat1", "feat2"] + ); + + // The '--all-features' flag supersedes other feature flags + let all_flag_variants = build_features(|meta| { + meta.features(CargoOpt::SomeFeatures(vec!["feat2".into()])) + .features(CargoOpt::NoDefaultFeatures) + .features(CargoOpt::AllFeatures) + }); + assert_eq!(sorted!(all_flag_variants), sorted!(all_features)); +} + +#[test] +fn depkind_to_string() { + assert_eq!(DependencyKind::Normal.to_string(), "normal"); + assert_eq!(DependencyKind::Development.to_string(), "dev"); + assert_eq!(DependencyKind::Build.to_string(), "build"); + assert_eq!(DependencyKind::Unknown.to_string(), "Unknown"); +} diff --git a/vendor/cc/.cargo-checksum.json b/vendor/cc/.cargo-checksum.json index 9e4e9cbfad..1833e320e7 100644 --- a/vendor/cc/.cargo-checksum.json +++ b/vendor/cc/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.lock":"80af52afb5e95100c7c480bf7787da9b36bc10d6bb206f1532785e5d581c8586","Cargo.toml":"fa1e64b64ffb20974689c18921df58f20d5476141f2eb2311306a6b8c2851d38","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"1fd66e1fe6d618030b9452c667e89d7a31b27331ad831d83b41f9762fd6858d4","src/bin/gcc-shim.rs":"b77907875029494b6288841c3aed2e4939ed40708c7f597fca5c9e2570490ca6","src/com.rs":"bcdaf1c28b71e6ef889c6b08d1ce9d7c0761344a677f523bc4c3cd297957f804","src/lib.rs":"6f1a2b2a92066b8ff413d3a58fe89ab35d5ff9ee97aaa4d4045ef9748b27fed4","src/registry.rs":"3cc1b5a50879fa751572878ae1d0afbfc960c11665258492754b2c8bccb0ff5d","src/setup_config.rs":"7014103587d3382eac599cb76f016e2609b8140970861b2237982d1db24af265","src/vs_instances.rs":"2d3f8278a803b0e7052f4eeb1979b29f963dd0143f4458e2cb5f33c4e5f0963b","src/winapi.rs":"ea8b7edbb9ff87957254f465c2334e714c5d6b3b19a8d757c48ea7ca0881c50c","src/windows_registry.rs":"d8f3014140d637b50a1fa4a9739b3617299ab43f829e65b2728f515a969a5376","tests/cc_env.rs":"e02b3b0824ad039b47e4462c5ef6dbe6c824c28e7953af94a0f28f7b5158042e","tests/cflags.rs":"57f06eb5ce1557e5b4a032d0c4673e18fbe6f8d26c1deb153126e368b96b41b3","tests/cxxflags.rs":"c2c6c6d8a0d7146616fa1caed26876ee7bc9fcfffd525eb4743593cade5f3371","tests/support/mod.rs":"16274867f23871e9b07614eda4c7344da13d1751fed63d4f633857e40be86394","tests/test.rs":"65c073e0e2cf4aa0433066102788e9f57442719e6f32f5ad5248aa7132bb4597"},"package":"d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0"} \ No newline at end of file +{"files":{"Cargo.lock":"c709d9de00dae7ef6d4a6ac36b56d6c0c4b1362cbfd7ed34e24c59471bef9d00","Cargo.toml":"eb6b50e2773484e0989864189cce7bb884b2893ccdb0370a628682922bcbc8db","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"1fd66e1fe6d618030b9452c667e89d7a31b27331ad831d83b41f9762fd6858d4","src/bin/gcc-shim.rs":"b77907875029494b6288841c3aed2e4939ed40708c7f597fca5c9e2570490ca6","src/com.rs":"bcdaf1c28b71e6ef889c6b08d1ce9d7c0761344a677f523bc4c3cd297957f804","src/lib.rs":"4e4ad7228f6e5ac084022b2ed3dd5423212bedfa16d71b1949e7865f4a9c406e","src/registry.rs":"3cc1b5a50879fa751572878ae1d0afbfc960c11665258492754b2c8bccb0ff5d","src/setup_config.rs":"7014103587d3382eac599cb76f016e2609b8140970861b2237982d1db24af265","src/vs_instances.rs":"2d3f8278a803b0e7052f4eeb1979b29f963dd0143f4458e2cb5f33c4e5f0963b","src/winapi.rs":"ea8b7edbb9ff87957254f465c2334e714c5d6b3b19a8d757c48ea7ca0881c50c","src/windows_registry.rs":"d8f3014140d637b50a1fa4a9739b3617299ab43f829e65b2728f515a969a5376","tests/cc_env.rs":"e02b3b0824ad039b47e4462c5ef6dbe6c824c28e7953af94a0f28f7b5158042e","tests/cflags.rs":"57f06eb5ce1557e5b4a032d0c4673e18fbe6f8d26c1deb153126e368b96b41b3","tests/cxxflags.rs":"c2c6c6d8a0d7146616fa1caed26876ee7bc9fcfffd525eb4743593cade5f3371","tests/support/mod.rs":"16274867f23871e9b07614eda4c7344da13d1751fed63d4f633857e40be86394","tests/test.rs":"65c073e0e2cf4aa0433066102788e9f57442719e6f32f5ad5248aa7132bb4597"},"package":"79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd"} \ No newline at end of file diff --git a/vendor/cc/Cargo.lock b/vendor/cc/Cargo.lock index dc293dcc8b..593a4ef274 100644 --- a/vendor/cc/Cargo.lock +++ b/vendor/cc/Cargo.lock @@ -2,9 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "cc" -version = "1.0.70" +version = "1.0.71" dependencies = [ "jobserver", "tempfile", @@ -12,15 +18,15 @@ dependencies = [ [[package]] name = "cfg-if" -version = "0.1.10" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "getrandom" -version = "0.1.15" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" dependencies = [ "cfg-if", "libc", @@ -29,18 +35,18 @@ dependencies = [ [[package]] name = "jobserver" -version = "0.1.21" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2" +checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" dependencies = [ "libc", ] [[package]] name = "libc" -version = "0.2.80" +version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614" +checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" [[package]] name = "ppv-lite86" @@ -50,11 +56,10 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.7.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" dependencies = [ - "getrandom", "libc", "rand_chacha", "rand_core", @@ -63,9 +68,9 @@ dependencies = [ [[package]] name = "rand_chacha" -version = "0.2.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", "rand_core", @@ -73,27 +78,30 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.5.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ "getrandom", ] [[package]] name = "rand_hc" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" dependencies = [ "rand_core", ] [[package]] name = "redox_syscall" -version = "0.1.57" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] [[package]] name = "remove_dir_all" @@ -106,9 +114,9 @@ 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", "libc", @@ -120,9 +128,9 @@ dependencies = [ [[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" [[package]] name = "winapi" diff --git a/vendor/cc/Cargo.toml b/vendor/cc/Cargo.toml index 25639148fe..c43838d098 100644 --- a/vendor/cc/Cargo.toml +++ b/vendor/cc/Cargo.toml @@ -3,17 +3,16 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies +# to registry (e.g., crates.io) dependencies. # -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. [package] edition = "2018" name = "cc" -version = "1.0.70" +version = "1.0.71" authors = ["Alex Crichton <alex@alexcrichton.com>"] exclude = ["/.github", "/.travis.yml", "/appveyor.yml"] description = "A build-time dependency for Cargo build scripts to assist in invoking the native\nC compiler to compile native C code into a static archive to be linked into Rust\ncode.\n" diff --git a/vendor/cc/src/lib.rs b/vendor/cc/src/lib.rs index 2de245717c..a829a5b68a 100644 --- a/vendor/cc/src/lib.rs +++ b/vendor/cc/src/lib.rs @@ -1490,10 +1490,11 @@ impl Build { cmd.push_cc_arg("-fdata-sections".into()); } // Disable generation of PIC on bare-metal for now: rust-lld doesn't support this yet - if self - .pic - .unwrap_or(!target.contains("windows") && !target.contains("-none-")) - { + if self.pic.unwrap_or( + !target.contains("windows") + && !target.contains("-none-") + && !target.contains("uefi"), + ) { cmd.push_cc_arg("-fPIC".into()); // PLT only applies if code is compiled with PIC support, // and only for ELF targets. @@ -1556,6 +1557,12 @@ impl Build { cmd.args.push( format!("--target={}", target.replace("riscv64gc", "riscv64")).into(), ); + } else if target.contains("uefi") { + if target.contains("x86_64") { + cmd.args.push("--target=x86_64-unknown-windows-gnu".into()); + } else if target.contains("i686") { + cmd.args.push("--target=i686-unknown-windows-gnu".into()) + } } else { cmd.args.push(format!("--target={}", target).into()); } @@ -1613,6 +1620,10 @@ impl Build { } } + if target.contains("-kmc-solid_") { + cmd.args.push("-finput-charset=utf-8".into()); + } + if self.static_flag.is_none() { let features = self .getenv("CARGO_CFG_TARGET_FEATURE") @@ -1624,7 +1635,7 @@ impl Build { // armv7 targets get to use armv7 instructions if (target.starts_with("armv7") || target.starts_with("thumbv7")) - && target.contains("-linux-") + && (target.contains("-linux-") || target.contains("-kmc-solid_")) { cmd.args.push("-march=armv7-a".into()); } @@ -2180,6 +2191,10 @@ impl Build { } else { "wr-cc".to_string() } + } else if target.starts_with("armv7a-kmc-solid_") { + format!("arm-kmc-eabi-{}", gnu) + } else if target.starts_with("aarch64-kmc-solid_") { + format!("aarch64-kmc-elf-{}", gnu) } else if self.get_host()? != target { let prefix = self.prefix_for_target(&target); match prefix { @@ -2355,7 +2370,7 @@ impl Build { // // It's true that everything here is a bit of a pain, but apparently if // you're not literally make or bash then you get a lot of bug reports. - let known_wrappers = ["ccache", "distcc", "sccache", "icecc"]; + let known_wrappers = ["ccache", "distcc", "sccache", "icecc", "cachepot"]; let mut parts = tool.split_whitespace(); let maybe_wrapper = match parts.next() { @@ -2504,6 +2519,10 @@ impl Build { "i586-unknown-linux-musl" => Some("musl"), "i686-pc-windows-gnu" => Some("i686-w64-mingw32"), "i686-uwp-windows-gnu" => Some("i686-w64-mingw32"), + "i686-unknown-linux-gnu" => self.find_working_gnu_prefix(&[ + "i686-linux-gnu", + "x86_64-linux-gnu", // transparently support gcc-multilib + ]), // explicit None if not found, so caller knows to fall back "i686-unknown-linux-musl" => Some("musl"), "i686-unknown-netbsd" => Some("i486--netbsdelf"), "mips-unknown-linux-gnu" => Some("mips-linux-gnu"), @@ -2571,6 +2590,9 @@ impl Build { "x86_64-pc-windows-gnu" => Some("x86_64-w64-mingw32"), "x86_64-uwp-windows-gnu" => Some("x86_64-w64-mingw32"), "x86_64-rumprun-netbsd" => Some("x86_64-rumprun-netbsd"), + "x86_64-unknown-linux-gnu" => self.find_working_gnu_prefix(&[ + "x86_64-linux-gnu", // rustfmt wrap + ]), // explicit None if not found, so caller knows to fall back "x86_64-unknown-linux-musl" => Some("musl"), "x86_64-unknown-netbsd" => Some("x86_64--netbsd"), _ => None, diff --git a/vendor/compiler_builtins/.cargo-checksum.json b/vendor/compiler_builtins/.cargo-checksum.json index e034df1fea..c15ffb23d5 100644 --- a/vendor/compiler_builtins/.cargo-checksum.json +++ b/vendor/compiler_builtins/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.lock":"0a0375936cc507935d8610a792439b6a2510ac25c67c23fa79d6d14a2cfb441a","Cargo.toml":"39c8c0de50ff2e359a55057445d85dc5d10b3bd4add2b56bc06e8d012b46c1a1","README.md":"2dd28b207028773ffee09ed0db563ac71b255b6b67256289d67a13cb19d15f94","build.rs":"28277271ffc69b0b549310656411eb8f6ef23c1679be0d82d22d243c92421a32","examples/intrinsics.rs":"c4cdcc9f777e528fa54cb3bc3d6da4239373b8f9a5cdfe7bdf1df4598eaab64f","libm/src/math/acos.rs":"fb066ba84aba1372d706425ec14f35ff8d971756d15eeebd22ecf42a716493bb","libm/src/math/acosf.rs":"a112b82309bba1d35c4e3d6ad4d6c21ef305343d9ab601ddf4bc61d43bc9f1af","libm/src/math/acosh.rs":"56dac8538e4350cd7cf001327c89f087b68abb2e6aaad58edba8a094b09f6b0f","libm/src/math/acoshf.rs":"df5b0c4d8e37e64cf5ff2d8328b28bc35c78e84060ff769e64523ea9ff9065c1","libm/src/math/asin.rs":"095a1e98996daff45df0b154ca0ec35bbf31db964ee9fdda0207308cb20df441","libm/src/math/asinf.rs":"49cccb4db2881982643a4a7d5453f4f8daf527711bbb67313607a3c178856d61","libm/src/math/asinh.rs":"e8fc94031015fddf35e9c26b94da9f6431ee17c81cd7bd37da8ffc98f7e0b32c","libm/src/math/asinhf.rs":"8a0b8933a98a17617a66fef4c7b89eba645fdf05302000babf4a5a5f45328430","libm/src/math/atan.rs":"d4fe46e1c5739dd09997869dcfbc3c85f03c534af52e700d6c6bcf9c3fedda07","libm/src/math/atan2.rs":"2623bc8ca707d13a7092ce49adf68e9cbf4452ad1bf4a861dc40ca858606a747","libm/src/math/atan2f.rs":"dd01943e0e1f1955912e5c3ffc9467529cf64bd02ac0a6ad5ab31dbe6657f05d","libm/src/math/atanf.rs":"e41b41569474a59c970ede3538e00bda4072cf4d90040017101cc79d7dc28caa","libm/src/math/atanh.rs":"5934dbd6b7395ca4f103ace7598da723a9270e1cf6b47e7f786debe4bb3651ff","libm/src/math/atanhf.rs":"8ba4711dda19ef2dc33622be65c1483902868083543198c6bbd040d4026293de","libm/src/math/cbrt.rs":"f2c45612d2eecd93cfcdd9ebf824c754fc8f8dfd6d16862c0b9c4ccea78c2a0f","libm/src/math/cbrtf.rs":"ad0b483854aa9f17a44d36c049bf0e8ebab34c27e90b787c05f45cc230ec7d19","libm/src/math/ceil.rs":"0e6caff1597818471c28b7c3226dbfe9976fdb38ace5246172ac030754be6b79","libm/src/math/ceilf.rs":"f942bcea617de7da880b68bdfe676837a7984e2a887eaafe181be24c6bc13cc2","libm/src/math/copysign.rs":"d80c880efaf0cdf2ce0a4d4f5a68dd6c36c88d46fa997ec8ac8604bfdb26fa33","libm/src/math/copysignf.rs":"1547116071e68a42b1605eb2fc722db6466a34517dc96b92de1f29a274c3d8e3","libm/src/math/cos.rs":"74babdc13ede78e400c5ca1854c3e22d2e08cbdc5618aefa5bba6f9303ef65b6","libm/src/math/cosf.rs":"09c40f93c445b741e22477ceedf163ca33b6a47f973f7c9876cfba2692edb29c","libm/src/math/cosh.rs":"0d0a7cef18577f321996b8b87561963139f754ad7f2ea0a3b3883811f3f0693a","libm/src/math/coshf.rs":"be8ca8739e4cf1978425b349f941cb4838bba8c10cb559c7940b9fd4fdde21ad","libm/src/math/erf.rs":"9c55fc6756ba816996f0b585e07ccfa4cd87575ad525cd30c4a968b30acffda3","libm/src/math/erff.rs":"cb020e8bada9a54573a11fe3271750d73f14fed3092a881a9ceaf98fe32fd5a6","libm/src/math/exp.rs":"ca7405ad0d1993fffcf9aae96f9256307bed3c4916545aaebd1cf1d2df1807fa","libm/src/math/exp10.rs":"2deb037f88feac87a0e924b69dd496f0dd3b5d35f2a58e09d4c5166b207e517b","libm/src/math/exp10f.rs":"6979464dfe3f4f2da1f9afc909646499c4bfaef15e10a039384750e2f1586fea","libm/src/math/exp2.rs":"94a9304a2ce3bc81f6d2aefd3cde6faa30f13260d46cb13692863cdea1c9a3a1","libm/src/math/exp2f.rs":"785f2630accd35118ec07bf60273e219ed91a215b956b1552eeea5bc2a708cc8","libm/src/math/expf.rs":"ec14c18f891a9e37735ec39e6fc2e9bf674a2c2e083f22e2533b481177359c98","libm/src/math/expm1.rs":"124069f456c8ad331f265c7509d9e223b2a300e461bbfd3d6adfdcdd2ee5b8ac","libm/src/math/expm1f.rs":"18e2116d31ea8410051cc709b9d04b754b0e3ba6758ee1bf0b48749f4999b840","libm/src/math/expo2.rs":"4f4f9fecfccb43f30c2784aa7c0bb656754a52b8ab431f7d1b551c673ab133f1","libm/src/math/fabs.rs":"e6c7db39f98508098cdf64ac0c2f53866c466149a7490afb9fe22b44c4dd81b3","libm/src/math/fabsf.rs":"dc85b66e4ef662721276ae3a301af22795524e4367ee8dd40f0c24c439773c6d","libm/src/math/fdim.rs":"8ec091996005207297c2389ae563e1b18dbc6a9eac951de29a976c5cd7bc32a7","libm/src/math/fdimf.rs":"c7f3f2269834d55be26b6580ddc07c42531577955fa4de35bad1e2a361085614","libm/src/math/fenv.rs":"8730d45aa4c591f91dccdcc1ce533fa23e9c6df0c38defb9c57f749cb25e1cd0","libm/src/math/floor.rs":"be15e687a6798defc6f2c6b43028481f8104fb93d2b3f359d3d5d16b78e79d4f","libm/src/math/floorf.rs":"4ec41aa64cfafd23b8cfc043eacea5e9125cca5dcb3f5e655cc3d3458c6ba2c5","libm/src/math/fma.rs":"7163e384eb3b75738952cb1976d387a3f2d81890fbddcc370c44132433128688","libm/src/math/fmaf.rs":"3e0f5727e56f31218f674b9b8975d7e67b3a24a097f06a2a3eca9723cd786213","libm/src/math/fmax.rs":"f6c8e96a8b1a170648d2fa3513e7b6b459085d708c839869f82e305fe58fac37","libm/src/math/fmaxf.rs":"dff0025433232e8a5ec7bd54d847ccf596d762ea4e35f5c54fbaac9404d732fd","libm/src/math/fmin.rs":"95b6cb66ca0e0e22276f0bf88dbe8fb69796a69a196a7491bd4802efbcf2e298","libm/src/math/fminf.rs":"304bc839b15ea3d84e68d2af9f40524ec120d30a36a667b22fcb98a6c258f4c7","libm/src/math/fmod.rs":"a1c0550fc7df8164733d914e222ff0966a2ab886d6e75a1098f24fe0283ae227","libm/src/math/fmodf.rs":"ee51ed092c0eeb8195f35735ff725cfd46612e0d689a7c483538bd92fbe61828","libm/src/math/frexp.rs":"28af70026922a8ab979744c7ad4d8faba6079c4743b7eeb6d14c983a982fbbcc","libm/src/math/frexpf.rs":"2e2593ae8002ba420809ebfaf737ef001cdc912354be3d978a8c0cb930350d4d","libm/src/math/hypot.rs":"841131c4a0cea75bc8a86e29f3f6d0815a61fc99731c9984651ce83d3050d218","libm/src/math/hypotf.rs":"5f317323edc2eb699580fe54b074b7e570a7734d51a0a149c0b49b54470a836c","libm/src/math/ilogb.rs":"813413bf6266d4fc40db9c5921af3cef4f892ba93e8f6d9efe62a449d1234532","libm/src/math/ilogbf.rs":"dec462780f46682e16cfaa733238bed3b692729e951f53a44726100b6c73a716","libm/src/math/j0.rs":"9572b6396c489927d332d0e717920e61ec0618e5e9c31f7eeeec70f5e4abab06","libm/src/math/j0f.rs":"802c8254bded9b3afb6eea8b9af240038a5a4a5d811396729f69ca509e3e7d87","libm/src/math/j1.rs":"97b1af1611fa3d110c2b349ee8e4176100132ea1391b619086b47ac063b81803","libm/src/math/j1f.rs":"1d504d7750c0481273baad88196d3644f258af9ad10f8b5b16341c0aab8b9125","libm/src/math/jn.rs":"847d122334e5707ad9627146cddccc082a1f2f5bcd3e5ef54399013a7007ce88","libm/src/math/jnf.rs":"4045076f7d1a1b89882ed60d4dd60a4cbbc66b85cfb90491378c8015effcc476","libm/src/math/k_cos.rs":"f34a69e44d6b8901b03b578a75972f438ab20a7b98a0903fc1903d6fde3899be","libm/src/math/k_cosf.rs":"8f7117ff21cebf8e890a5bcfd7ea858a94172f4172b79a66d53824c2cb0888b1","libm/src/math/k_expo2.rs":"eb4ca9e6a525b7ea6da868c3cb136896682cc46f8396ba2a2ebc3ae9e9ba54b0","libm/src/math/k_expo2f.rs":"d51ad5df61cb5d1258bdb90c52bfed4572bb446a9337de9c04411ed9454ae0cb","libm/src/math/k_sin.rs":"14b2aba6ca07150c92768b5a72acaf5cde6a11d6619e14896512a7ba242e289a","libm/src/math/k_sinf.rs":"2775fcc710807164e6f37a4f8da3c8143cd5f16e19ce7c31c5591522151d7a96","libm/src/math/k_tan.rs":"a72beae4ccd9631eeeb61d6365bbeecae81c8411f3120a999c515cca0d5ea5c5","libm/src/math/k_tanf.rs":"6a794be56fa4b2f60452b9bab19af01c388f174560acbf829a351378ea39495d","libm/src/math/ldexp.rs":"b647f0096e80e4d926d8dd18d294c892ee2cb1778effe2c5e1b2664ae5cb1a4e","libm/src/math/ldexpf.rs":"98743fad2cd97a7be496f40ba3157ac1438fce0d0c25d5ab90c3b8c71c3fd0ed","libm/src/math/lgamma.rs":"498552658cc8106d7754f85ae8dbc3306ac2f0a9f7eb5a796be70c5beac92c41","libm/src/math/lgamma_r.rs":"77fb6442aeb5343926d8965e1549dde3e2cc4fd09555de6b56506001d956c344","libm/src/math/lgammaf.rs":"457105f53a4c8717e8f5a117d261dcf94e222e83981337fe23602abe883fe3f7","libm/src/math/lgammaf_r.rs":"44de75babbdd53c4a5879cd6f426e7311db82669def39df5f63914d67d6cc1b1","libm/src/math/log.rs":"b5e0c5f30d9e94351488732801be3107c12b854c3f95ad37e256dd88eeca408f","libm/src/math/log10.rs":"3425ff8be001fd1646ba15e254eb6ef4bdc6ccaf0cbee27ddf1fa84e04178b90","libm/src/math/log10f.rs":"fee4f71879bc4c99259e68c0c641364901629fb29a8ebddfcc0d090102cceddd","libm/src/math/log1p.rs":"9cf400852f165e6be19b97036ae9521fb9ca857d0a9a91c117d9123221622185","libm/src/math/log1pf.rs":"2716e6d2afa271996b7c8f47fd9e4952c88f4c1fd8c07c3e8ce8c62794bf71d8","libm/src/math/log2.rs":"dbbbfbaaa8aa6a4dbefea554ea3983090a9691228b011910c751f6adca912c40","libm/src/math/log2f.rs":"92a90350d8edce21c31c285c3e620fca7c62a2366008921715945c2c73b5b79f","libm/src/math/logf.rs":"845342cffc34d3db1f5ec12d8e5b773cd5a79056e28662fcb9bcd80207596f50","libm/src/math/mod.rs":"ffa73c08f4c0a4dc6c9d1cb9d62fe97f3a5046edede128c9441cc3adc9170dd3","libm/src/math/modf.rs":"d012ed5a708ef52b6d1313c22a46cadaf5764dde1220816e3df2f03a0fcc60ae","libm/src/math/modff.rs":"f8f1e4c27a85d2cdb3c8e74439d59ef64aa543b948f22c23227d02d8388d61c2","libm/src/math/nextafter.rs":"3282e7eef214a32736fb6928d490198ad394b26b402b45495115b104839eebfe","libm/src/math/nextafterf.rs":"0937dc8a8155c19842c12181e741cec1f7df1f7a00cee81fcb2475e2842761b7","libm/src/math/pow.rs":"bc67d59403b0b35cbdbd28968bb60898254cb3700cdf491b299f81fda51037ed","libm/src/math/powf.rs":"2c423a0ea57fdc4e20f3533f744c6e6288c998b4de8f2914fafaa0e78be81b04","libm/src/math/rem_pio2.rs":"9be99c44493b2b7088578c0fa2872630725b2da544c751516df0c6c686112a43","libm/src/math/rem_pio2_large.rs":"21762d08d72dc6f2e313123a7311683000974a09b8fcae50994d9c39239721b1","libm/src/math/rem_pio2f.rs":"377349d1308bda8cd2f776e4856fe090baa78fa3db816b680780ddf31b80d446","libm/src/math/remainder.rs":"63865f4370853c476b45bb27a5c54a4072146aa4a626835ae5263871a4e7e5dc","libm/src/math/remainderf.rs":"dd3fa432dbda8f2135428198be7bd69c57f8d13df3f365b12f52bf6a82352ac4","libm/src/math/remquo.rs":"3cc0bf55069f165c4843f2c358b3a27279c01e8cdd99f9057a3f7f31f45408f2","libm/src/math/remquof.rs":"cc749e18ecb7e766b8b8eeabdbf89ac99087d3d587e71e30f690676a3d2c1f9b","libm/src/math/round.rs":"955649c893fa3151b4a81c8e550fbc03f01bb99b40d60986e5f153ee71043f69","libm/src/math/roundf.rs":"8ae8f1f71eedd158566771cfe80b352d2f13c170a0ce8dc2691a14e8a791cfbb","libm/src/math/scalbn.rs":"b5c9d6d4177fe393cbfe1c634d75ce14b754f6cbce87c5bf979a9661491748a2","libm/src/math/scalbnf.rs":"4f198d06db1896386256fb9a5ac5b805b16b836226c18780a475cf18d7c1449c","libm/src/math/sin.rs":"0e014e6377c9673a73395ab2ffcf5962e512392afddf8a4e731fb694098faf34","libm/src/math/sincos.rs":"59e9f196140681fa817652134b8d1bdd2d6dd47bb8557b0346c77b176389f883","libm/src/math/sincosf.rs":"d37d71c7204c7892fe24c956df0fb95e7a014a808f5cbd5e125aee48c3c449b5","libm/src/math/sinf.rs":"dcddac1d56b084cbb8d0e019433c9c5fe2201d9b257a7dcf2f85c9a8f14b79cf","libm/src/math/sinh.rs":"d8ee4c7af883a526f36c1a6da13bb81fba9181b477e2f2538161a2bee97edc35","libm/src/math/sinhf.rs":"d06eb030ba9dbf7094df127262bfe99f149b4db49fa8ab8c15499660f1e46b26","libm/src/math/sqrt.rs":"824570a631c2542ccee68b65e3eb08fe79c037a29bbaaf54da5367e7b236124a","libm/src/math/sqrtf.rs":"d9e12ac55c5471c18175efdfb15c092ba71a2eb914d2e1ee3b3310a22202042e","libm/src/math/tan.rs":"930ecedaadc60f704c2dfa4e15186f59713c1ba7d948529d215223b424827db5","libm/src/math/tanf.rs":"894156a3b107aee08461eb4e7e412fc049aa237d176ae705c6e3e2d7060d94e3","libm/src/math/tanh.rs":"f1f08eb98ed959a17370a7aaf0177be36e3764543424e78feb033ed3f5e8ec98","libm/src/math/tanhf.rs":"74027b0c672a4e64bdef6d7a3069b90caec50e1e7dbb2c12d2828f310502f41e","libm/src/math/tgamma.rs":"a6aabb8365410af6611f19f58694ccb74e82bb9ba9e1cdec7e1af787cfa44815","libm/src/math/tgammaf.rs":"c95bd69957387533853532164f7e2251d2b04f5e775406b9e647226ae2bdd5ad","libm/src/math/trunc.rs":"642264897cc1505e720c8cf313be81aa9fd53aae866644a2e988d01dbc77fd8a","libm/src/math/truncf.rs":"619b675b6a9bb81eccddb1fa8214cff63e1f62136629b645c87f036672311732","src/arm.rs":"34aeb8a51784d23d32c8bda677569c8661a96f920d5343c533e204d61ca43519","src/arm_linux.rs":"80d18ce84bdfa841fa133f5ee9e9fd50167344436d2d398f74347a90f27606c6","src/float/add.rs":"3ec32ceaf470a89777b54f9cde61832fdadeade0f4894f268a949e968520bc57","src/float/cmp.rs":"79b1fdc8d5f943c4ad5ea4ad32623b18f63e17ac3852fbc64a4942228007e1fc","src/float/conv.rs":"462102f7160e30c5ca7b332a1140c8d1229d1821fdce59fbf93f2c530364b197","src/float/div.rs":"1bd41ba756dc4b2d488ed4d4b59e5029a7774900fca5d542839e3b98b3805249","src/float/extend.rs":"180b2e791c58e0526de0a798845c580ce3222c8a15c8665e6e6a4bf5cf1a34aa","src/float/mod.rs":"9b83d3f058351bee41bbae9cb72ecc5e131d257f18cf9723af17d3538ed3e58c","src/float/mul.rs":"0d0c1f0c28c149ecadeafd459d3c4c9327e4cfcae2cba479957bb8010ef51a01","src/float/pow.rs":"6231c53cad103809d84f9ab6487d31eefc516eff8cfc0fda9ef6700f1d075d38","src/float/sub.rs":"c2a87f4628f51d5d908d0f25b5d51ce0599dc559d5a72b20e131261f484d5848","src/int/addsub.rs":"7ec45ce1ba15b56a5b7129d3e5722c4db764c6545306d3fa9090983bcabd6f17","src/int/leading_zeros.rs":"9f7b10c723baae8dcbd649e44a00eb40f7e082ba7c535c8d7701c1757f2ba76d","src/int/mod.rs":"bab1b77535ceebdebb89fd4e59e7105f8c45347bb638351a626615b24544a0b1","src/int/mul.rs":"40c5a84c0bff28797eccc9cf8884b5880261818dee21c961f17f727b74d02261","src/int/sdiv.rs":"ec870b6a4b92e6f6c2ce5189bb98ce04f54272d32f8796d9d543b576ba32b76d","src/int/shift.rs":"3967c28a8d61279546e91958d64745fec63f15aee9175eb0602cc6353830da6c","src/int/specialized_div_rem/asymmetric.rs":"27f5bf70a35109f9d4e4e1ad1e8003aa17da5a1e436bf3e63a493d7528a3a566","src/int/specialized_div_rem/binary_long.rs":"9f1ced81a394f000a21a329683144d68ee431a954136a3634eb55b1ee2cf6d51","src/int/specialized_div_rem/delegate.rs":"9df141af98e391361e25d71ae38d5e845a91d896edd2c041132fd46af8268e85","src/int/specialized_div_rem/mod.rs":"cb5776ac628d6ac56a99d8bef8c2b5fac65fa39cc5f9fb9d20fe83b7d9493c01","src/int/specialized_div_rem/norm_shift.rs":"3be7ee0dea545c1f702d9daf67dad2b624bf7b17b075c8b90d3d3f7b53df4c21","src/int/specialized_div_rem/trifecta.rs":"87eef69da255b809fd710b14f2eb3f9f59e3dac625f8564ebc8ba78f9763523b","src/int/udiv.rs":"2173ec21ced1ecf660dd6f001690b4275b0bdc36a97b3e4b31bce89e33cb1d71","src/lib.rs":"d423f142ea038aea1ba251aa49c44ecbc0c567d078d3cae0667f7eec12a3ce3d","src/macros.rs":"016100d5043d3af66584d67b38c39b9fc6934a44dd762f99bf0b4653fad79223","src/math.rs":"c97e2ad283089362721ea48e9355f8a3119559c14e1c249c67044e865827a164","src/mem/impls.rs":"8148e22bb2ac018141ec1062703a49ad154e4bee2f29211a56a4afd3d42247ea","src/mem/mod.rs":"c2918bdf0250a4b085a66e9009513e9a0fe45a553f3c7f66047a485fe66ec767","src/mem/x86_64.rs":"ee2b6bb0449de5e4b20854bd9d3403f5e4808f8356eadf0dda26866847f6b929","src/probestack.rs":"23f5de88b87a853c6e89c38563c11ecdadab34d325a58128c9e5f927b8afb671","src/riscv32.rs":"b9b433d248fce35e43a7df430697545f39898fad46be7d0197284764e44993b2","src/x86.rs":"5d5f9972cfd733fc8a5e50674db2cc2ad697b4469a254181f624dd0e0c9a8047","src/x86_64.rs":"db90462211c1dc85b784e9d229cac761dbd3de5c5fef3a18784bb5650208ef6e"},"package":"20b1438ef42c655665a8ab2c1c6d605a305f031d38d9be689ddfef41a20f3aa2"} \ No newline at end of file +{"files":{"Cargo.lock":"6763023c049de914ad3ccfc9956126f982631a04899eaaf8e5458f7d944557aa","Cargo.toml":"7681b982e3066ffd9443887ca9b7ccbe57eb79b6cdb7989f4e3bf9b1f5419bd7","README.md":"2dd28b207028773ffee09ed0db563ac71b255b6b67256289d67a13cb19d15f94","build.rs":"3957530a46eaf5bdcab91f68c6443f2378d4f944adf5c71e8094ddaf99793400","examples/intrinsics.rs":"c4cdcc9f777e528fa54cb3bc3d6da4239373b8f9a5cdfe7bdf1df4598eaab64f","libm/src/math/acos.rs":"fb066ba84aba1372d706425ec14f35ff8d971756d15eeebd22ecf42a716493bb","libm/src/math/acosf.rs":"a112b82309bba1d35c4e3d6ad4d6c21ef305343d9ab601ddf4bc61d43bc9f1af","libm/src/math/acosh.rs":"56dac8538e4350cd7cf001327c89f087b68abb2e6aaad58edba8a094b09f6b0f","libm/src/math/acoshf.rs":"df5b0c4d8e37e64cf5ff2d8328b28bc35c78e84060ff769e64523ea9ff9065c1","libm/src/math/asin.rs":"095a1e98996daff45df0b154ca0ec35bbf31db964ee9fdda0207308cb20df441","libm/src/math/asinf.rs":"49cccb4db2881982643a4a7d5453f4f8daf527711bbb67313607a3c178856d61","libm/src/math/asinh.rs":"e8fc94031015fddf35e9c26b94da9f6431ee17c81cd7bd37da8ffc98f7e0b32c","libm/src/math/asinhf.rs":"8a0b8933a98a17617a66fef4c7b89eba645fdf05302000babf4a5a5f45328430","libm/src/math/atan.rs":"d4fe46e1c5739dd09997869dcfbc3c85f03c534af52e700d6c6bcf9c3fedda07","libm/src/math/atan2.rs":"2623bc8ca707d13a7092ce49adf68e9cbf4452ad1bf4a861dc40ca858606a747","libm/src/math/atan2f.rs":"dd01943e0e1f1955912e5c3ffc9467529cf64bd02ac0a6ad5ab31dbe6657f05d","libm/src/math/atanf.rs":"e41b41569474a59c970ede3538e00bda4072cf4d90040017101cc79d7dc28caa","libm/src/math/atanh.rs":"5934dbd6b7395ca4f103ace7598da723a9270e1cf6b47e7f786debe4bb3651ff","libm/src/math/atanhf.rs":"8ba4711dda19ef2dc33622be65c1483902868083543198c6bbd040d4026293de","libm/src/math/cbrt.rs":"f2c45612d2eecd93cfcdd9ebf824c754fc8f8dfd6d16862c0b9c4ccea78c2a0f","libm/src/math/cbrtf.rs":"ad0b483854aa9f17a44d36c049bf0e8ebab34c27e90b787c05f45cc230ec7d19","libm/src/math/ceil.rs":"0e6caff1597818471c28b7c3226dbfe9976fdb38ace5246172ac030754be6b79","libm/src/math/ceilf.rs":"f942bcea617de7da880b68bdfe676837a7984e2a887eaafe181be24c6bc13cc2","libm/src/math/copysign.rs":"d80c880efaf0cdf2ce0a4d4f5a68dd6c36c88d46fa997ec8ac8604bfdb26fa33","libm/src/math/copysignf.rs":"1547116071e68a42b1605eb2fc722db6466a34517dc96b92de1f29a274c3d8e3","libm/src/math/cos.rs":"74babdc13ede78e400c5ca1854c3e22d2e08cbdc5618aefa5bba6f9303ef65b6","libm/src/math/cosf.rs":"09c40f93c445b741e22477ceedf163ca33b6a47f973f7c9876cfba2692edb29c","libm/src/math/cosh.rs":"0d0a7cef18577f321996b8b87561963139f754ad7f2ea0a3b3883811f3f0693a","libm/src/math/coshf.rs":"be8ca8739e4cf1978425b349f941cb4838bba8c10cb559c7940b9fd4fdde21ad","libm/src/math/erf.rs":"9c55fc6756ba816996f0b585e07ccfa4cd87575ad525cd30c4a968b30acffda3","libm/src/math/erff.rs":"cb020e8bada9a54573a11fe3271750d73f14fed3092a881a9ceaf98fe32fd5a6","libm/src/math/exp.rs":"ca7405ad0d1993fffcf9aae96f9256307bed3c4916545aaebd1cf1d2df1807fa","libm/src/math/exp10.rs":"2deb037f88feac87a0e924b69dd496f0dd3b5d35f2a58e09d4c5166b207e517b","libm/src/math/exp10f.rs":"6979464dfe3f4f2da1f9afc909646499c4bfaef15e10a039384750e2f1586fea","libm/src/math/exp2.rs":"94a9304a2ce3bc81f6d2aefd3cde6faa30f13260d46cb13692863cdea1c9a3a1","libm/src/math/exp2f.rs":"785f2630accd35118ec07bf60273e219ed91a215b956b1552eeea5bc2a708cc8","libm/src/math/expf.rs":"ec14c18f891a9e37735ec39e6fc2e9bf674a2c2e083f22e2533b481177359c98","libm/src/math/expm1.rs":"124069f456c8ad331f265c7509d9e223b2a300e461bbfd3d6adfdcdd2ee5b8ac","libm/src/math/expm1f.rs":"18e2116d31ea8410051cc709b9d04b754b0e3ba6758ee1bf0b48749f4999b840","libm/src/math/expo2.rs":"4f4f9fecfccb43f30c2784aa7c0bb656754a52b8ab431f7d1b551c673ab133f1","libm/src/math/fabs.rs":"e6c7db39f98508098cdf64ac0c2f53866c466149a7490afb9fe22b44c4dd81b3","libm/src/math/fabsf.rs":"dc85b66e4ef662721276ae3a301af22795524e4367ee8dd40f0c24c439773c6d","libm/src/math/fdim.rs":"8ec091996005207297c2389ae563e1b18dbc6a9eac951de29a976c5cd7bc32a7","libm/src/math/fdimf.rs":"c7f3f2269834d55be26b6580ddc07c42531577955fa4de35bad1e2a361085614","libm/src/math/fenv.rs":"8730d45aa4c591f91dccdcc1ce533fa23e9c6df0c38defb9c57f749cb25e1cd0","libm/src/math/floor.rs":"be15e687a6798defc6f2c6b43028481f8104fb93d2b3f359d3d5d16b78e79d4f","libm/src/math/floorf.rs":"4ec41aa64cfafd23b8cfc043eacea5e9125cca5dcb3f5e655cc3d3458c6ba2c5","libm/src/math/fma.rs":"7163e384eb3b75738952cb1976d387a3f2d81890fbddcc370c44132433128688","libm/src/math/fmaf.rs":"3e0f5727e56f31218f674b9b8975d7e67b3a24a097f06a2a3eca9723cd786213","libm/src/math/fmax.rs":"f6c8e96a8b1a170648d2fa3513e7b6b459085d708c839869f82e305fe58fac37","libm/src/math/fmaxf.rs":"dff0025433232e8a5ec7bd54d847ccf596d762ea4e35f5c54fbaac9404d732fd","libm/src/math/fmin.rs":"95b6cb66ca0e0e22276f0bf88dbe8fb69796a69a196a7491bd4802efbcf2e298","libm/src/math/fminf.rs":"304bc839b15ea3d84e68d2af9f40524ec120d30a36a667b22fcb98a6c258f4c7","libm/src/math/fmod.rs":"a1c0550fc7df8164733d914e222ff0966a2ab886d6e75a1098f24fe0283ae227","libm/src/math/fmodf.rs":"ee51ed092c0eeb8195f35735ff725cfd46612e0d689a7c483538bd92fbe61828","libm/src/math/frexp.rs":"28af70026922a8ab979744c7ad4d8faba6079c4743b7eeb6d14c983a982fbbcc","libm/src/math/frexpf.rs":"2e2593ae8002ba420809ebfaf737ef001cdc912354be3d978a8c0cb930350d4d","libm/src/math/hypot.rs":"841131c4a0cea75bc8a86e29f3f6d0815a61fc99731c9984651ce83d3050d218","libm/src/math/hypotf.rs":"5f317323edc2eb699580fe54b074b7e570a7734d51a0a149c0b49b54470a836c","libm/src/math/ilogb.rs":"813413bf6266d4fc40db9c5921af3cef4f892ba93e8f6d9efe62a449d1234532","libm/src/math/ilogbf.rs":"dec462780f46682e16cfaa733238bed3b692729e951f53a44726100b6c73a716","libm/src/math/j0.rs":"9572b6396c489927d332d0e717920e61ec0618e5e9c31f7eeeec70f5e4abab06","libm/src/math/j0f.rs":"802c8254bded9b3afb6eea8b9af240038a5a4a5d811396729f69ca509e3e7d87","libm/src/math/j1.rs":"97b1af1611fa3d110c2b349ee8e4176100132ea1391b619086b47ac063b81803","libm/src/math/j1f.rs":"1d504d7750c0481273baad88196d3644f258af9ad10f8b5b16341c0aab8b9125","libm/src/math/jn.rs":"847d122334e5707ad9627146cddccc082a1f2f5bcd3e5ef54399013a7007ce88","libm/src/math/jnf.rs":"4045076f7d1a1b89882ed60d4dd60a4cbbc66b85cfb90491378c8015effcc476","libm/src/math/k_cos.rs":"f34a69e44d6b8901b03b578a75972f438ab20a7b98a0903fc1903d6fde3899be","libm/src/math/k_cosf.rs":"8f7117ff21cebf8e890a5bcfd7ea858a94172f4172b79a66d53824c2cb0888b1","libm/src/math/k_expo2.rs":"eb4ca9e6a525b7ea6da868c3cb136896682cc46f8396ba2a2ebc3ae9e9ba54b0","libm/src/math/k_expo2f.rs":"d51ad5df61cb5d1258bdb90c52bfed4572bb446a9337de9c04411ed9454ae0cb","libm/src/math/k_sin.rs":"14b2aba6ca07150c92768b5a72acaf5cde6a11d6619e14896512a7ba242e289a","libm/src/math/k_sinf.rs":"2775fcc710807164e6f37a4f8da3c8143cd5f16e19ce7c31c5591522151d7a96","libm/src/math/k_tan.rs":"a72beae4ccd9631eeeb61d6365bbeecae81c8411f3120a999c515cca0d5ea5c5","libm/src/math/k_tanf.rs":"6a794be56fa4b2f60452b9bab19af01c388f174560acbf829a351378ea39495d","libm/src/math/ldexp.rs":"b647f0096e80e4d926d8dd18d294c892ee2cb1778effe2c5e1b2664ae5cb1a4e","libm/src/math/ldexpf.rs":"98743fad2cd97a7be496f40ba3157ac1438fce0d0c25d5ab90c3b8c71c3fd0ed","libm/src/math/lgamma.rs":"498552658cc8106d7754f85ae8dbc3306ac2f0a9f7eb5a796be70c5beac92c41","libm/src/math/lgamma_r.rs":"77fb6442aeb5343926d8965e1549dde3e2cc4fd09555de6b56506001d956c344","libm/src/math/lgammaf.rs":"457105f53a4c8717e8f5a117d261dcf94e222e83981337fe23602abe883fe3f7","libm/src/math/lgammaf_r.rs":"44de75babbdd53c4a5879cd6f426e7311db82669def39df5f63914d67d6cc1b1","libm/src/math/log.rs":"b5e0c5f30d9e94351488732801be3107c12b854c3f95ad37e256dd88eeca408f","libm/src/math/log10.rs":"3425ff8be001fd1646ba15e254eb6ef4bdc6ccaf0cbee27ddf1fa84e04178b90","libm/src/math/log10f.rs":"fee4f71879bc4c99259e68c0c641364901629fb29a8ebddfcc0d090102cceddd","libm/src/math/log1p.rs":"9cf400852f165e6be19b97036ae9521fb9ca857d0a9a91c117d9123221622185","libm/src/math/log1pf.rs":"2716e6d2afa271996b7c8f47fd9e4952c88f4c1fd8c07c3e8ce8c62794bf71d8","libm/src/math/log2.rs":"dbbbfbaaa8aa6a4dbefea554ea3983090a9691228b011910c751f6adca912c40","libm/src/math/log2f.rs":"92a90350d8edce21c31c285c3e620fca7c62a2366008921715945c2c73b5b79f","libm/src/math/logf.rs":"845342cffc34d3db1f5ec12d8e5b773cd5a79056e28662fcb9bcd80207596f50","libm/src/math/mod.rs":"ffa73c08f4c0a4dc6c9d1cb9d62fe97f3a5046edede128c9441cc3adc9170dd3","libm/src/math/modf.rs":"d012ed5a708ef52b6d1313c22a46cadaf5764dde1220816e3df2f03a0fcc60ae","libm/src/math/modff.rs":"f8f1e4c27a85d2cdb3c8e74439d59ef64aa543b948f22c23227d02d8388d61c2","libm/src/math/nextafter.rs":"3282e7eef214a32736fb6928d490198ad394b26b402b45495115b104839eebfe","libm/src/math/nextafterf.rs":"0937dc8a8155c19842c12181e741cec1f7df1f7a00cee81fcb2475e2842761b7","libm/src/math/pow.rs":"bc67d59403b0b35cbdbd28968bb60898254cb3700cdf491b299f81fda51037ed","libm/src/math/powf.rs":"2c423a0ea57fdc4e20f3533f744c6e6288c998b4de8f2914fafaa0e78be81b04","libm/src/math/rem_pio2.rs":"9be99c44493b2b7088578c0fa2872630725b2da544c751516df0c6c686112a43","libm/src/math/rem_pio2_large.rs":"21762d08d72dc6f2e313123a7311683000974a09b8fcae50994d9c39239721b1","libm/src/math/rem_pio2f.rs":"377349d1308bda8cd2f776e4856fe090baa78fa3db816b680780ddf31b80d446","libm/src/math/remainder.rs":"63865f4370853c476b45bb27a5c54a4072146aa4a626835ae5263871a4e7e5dc","libm/src/math/remainderf.rs":"dd3fa432dbda8f2135428198be7bd69c57f8d13df3f365b12f52bf6a82352ac4","libm/src/math/remquo.rs":"3cc0bf55069f165c4843f2c358b3a27279c01e8cdd99f9057a3f7f31f45408f2","libm/src/math/remquof.rs":"cc749e18ecb7e766b8b8eeabdbf89ac99087d3d587e71e30f690676a3d2c1f9b","libm/src/math/round.rs":"955649c893fa3151b4a81c8e550fbc03f01bb99b40d60986e5f153ee71043f69","libm/src/math/roundf.rs":"8ae8f1f71eedd158566771cfe80b352d2f13c170a0ce8dc2691a14e8a791cfbb","libm/src/math/scalbn.rs":"b5c9d6d4177fe393cbfe1c634d75ce14b754f6cbce87c5bf979a9661491748a2","libm/src/math/scalbnf.rs":"4f198d06db1896386256fb9a5ac5b805b16b836226c18780a475cf18d7c1449c","libm/src/math/sin.rs":"0e014e6377c9673a73395ab2ffcf5962e512392afddf8a4e731fb694098faf34","libm/src/math/sincos.rs":"59e9f196140681fa817652134b8d1bdd2d6dd47bb8557b0346c77b176389f883","libm/src/math/sincosf.rs":"d37d71c7204c7892fe24c956df0fb95e7a014a808f5cbd5e125aee48c3c449b5","libm/src/math/sinf.rs":"dcddac1d56b084cbb8d0e019433c9c5fe2201d9b257a7dcf2f85c9a8f14b79cf","libm/src/math/sinh.rs":"d8ee4c7af883a526f36c1a6da13bb81fba9181b477e2f2538161a2bee97edc35","libm/src/math/sinhf.rs":"d06eb030ba9dbf7094df127262bfe99f149b4db49fa8ab8c15499660f1e46b26","libm/src/math/sqrt.rs":"824570a631c2542ccee68b65e3eb08fe79c037a29bbaaf54da5367e7b236124a","libm/src/math/sqrtf.rs":"d9e12ac55c5471c18175efdfb15c092ba71a2eb914d2e1ee3b3310a22202042e","libm/src/math/tan.rs":"930ecedaadc60f704c2dfa4e15186f59713c1ba7d948529d215223b424827db5","libm/src/math/tanf.rs":"894156a3b107aee08461eb4e7e412fc049aa237d176ae705c6e3e2d7060d94e3","libm/src/math/tanh.rs":"f1f08eb98ed959a17370a7aaf0177be36e3764543424e78feb033ed3f5e8ec98","libm/src/math/tanhf.rs":"74027b0c672a4e64bdef6d7a3069b90caec50e1e7dbb2c12d2828f310502f41e","libm/src/math/tgamma.rs":"a6aabb8365410af6611f19f58694ccb74e82bb9ba9e1cdec7e1af787cfa44815","libm/src/math/tgammaf.rs":"c95bd69957387533853532164f7e2251d2b04f5e775406b9e647226ae2bdd5ad","libm/src/math/trunc.rs":"642264897cc1505e720c8cf313be81aa9fd53aae866644a2e988d01dbc77fd8a","libm/src/math/truncf.rs":"619b675b6a9bb81eccddb1fa8214cff63e1f62136629b645c87f036672311732","src/arm.rs":"34aeb8a51784d23d32c8bda677569c8661a96f920d5343c533e204d61ca43519","src/arm_linux.rs":"80d18ce84bdfa841fa133f5ee9e9fd50167344436d2d398f74347a90f27606c6","src/float/add.rs":"3ec32ceaf470a89777b54f9cde61832fdadeade0f4894f268a949e968520bc57","src/float/cmp.rs":"79b1fdc8d5f943c4ad5ea4ad32623b18f63e17ac3852fbc64a4942228007e1fc","src/float/conv.rs":"462102f7160e30c5ca7b332a1140c8d1229d1821fdce59fbf93f2c530364b197","src/float/div.rs":"1bd41ba756dc4b2d488ed4d4b59e5029a7774900fca5d542839e3b98b3805249","src/float/extend.rs":"180b2e791c58e0526de0a798845c580ce3222c8a15c8665e6e6a4bf5cf1a34aa","src/float/mod.rs":"9b83d3f058351bee41bbae9cb72ecc5e131d257f18cf9723af17d3538ed3e58c","src/float/mul.rs":"0d0c1f0c28c149ecadeafd459d3c4c9327e4cfcae2cba479957bb8010ef51a01","src/float/pow.rs":"6231c53cad103809d84f9ab6487d31eefc516eff8cfc0fda9ef6700f1d075d38","src/float/sub.rs":"c2a87f4628f51d5d908d0f25b5d51ce0599dc559d5a72b20e131261f484d5848","src/int/addsub.rs":"7ec45ce1ba15b56a5b7129d3e5722c4db764c6545306d3fa9090983bcabd6f17","src/int/leading_zeros.rs":"9f7b10c723baae8dcbd649e44a00eb40f7e082ba7c535c8d7701c1757f2ba76d","src/int/mod.rs":"bab1b77535ceebdebb89fd4e59e7105f8c45347bb638351a626615b24544a0b1","src/int/mul.rs":"40c5a84c0bff28797eccc9cf8884b5880261818dee21c961f17f727b74d02261","src/int/sdiv.rs":"ec870b6a4b92e6f6c2ce5189bb98ce04f54272d32f8796d9d543b576ba32b76d","src/int/shift.rs":"3967c28a8d61279546e91958d64745fec63f15aee9175eb0602cc6353830da6c","src/int/specialized_div_rem/asymmetric.rs":"27f5bf70a35109f9d4e4e1ad1e8003aa17da5a1e436bf3e63a493d7528a3a566","src/int/specialized_div_rem/binary_long.rs":"9f1ced81a394f000a21a329683144d68ee431a954136a3634eb55b1ee2cf6d51","src/int/specialized_div_rem/delegate.rs":"9df141af98e391361e25d71ae38d5e845a91d896edd2c041132fd46af8268e85","src/int/specialized_div_rem/mod.rs":"cb5776ac628d6ac56a99d8bef8c2b5fac65fa39cc5f9fb9d20fe83b7d9493c01","src/int/specialized_div_rem/norm_shift.rs":"3be7ee0dea545c1f702d9daf67dad2b624bf7b17b075c8b90d3d3f7b53df4c21","src/int/specialized_div_rem/trifecta.rs":"87eef69da255b809fd710b14f2eb3f9f59e3dac625f8564ebc8ba78f9763523b","src/int/udiv.rs":"2173ec21ced1ecf660dd6f001690b4275b0bdc36a97b3e4b31bce89e33cb1d71","src/lib.rs":"b8e105ce0550e2c022e7b2b4e98719e29ba17ea282e1b5ab872d40d82bac8ccc","src/macros.rs":"016100d5043d3af66584d67b38c39b9fc6934a44dd762f99bf0b4653fad79223","src/math.rs":"48bb0d97a1b56d960c6b5130b9a62a1cb1e8e5d62a522163022b8ea24c6cfcca","src/mem/impls.rs":"6572d6226ddaf56b5e0367fa5d46e09c15572fc80ca93a059be5975d2f81c5c9","src/mem/mod.rs":"c2918bdf0250a4b085a66e9009513e9a0fe45a553f3c7f66047a485fe66ec767","src/mem/x86_64.rs":"ee2b6bb0449de5e4b20854bd9d3403f5e4808f8356eadf0dda26866847f6b929","src/probestack.rs":"23f5de88b87a853c6e89c38563c11ecdadab34d325a58128c9e5f927b8afb671","src/riscv32.rs":"b9b433d248fce35e43a7df430697545f39898fad46be7d0197284764e44993b2","src/x86.rs":"5d5f9972cfd733fc8a5e50674db2cc2ad697b4469a254181f624dd0e0c9a8047","src/x86_64.rs":"db90462211c1dc85b784e9d229cac761dbd3de5c5fef3a18784bb5650208ef6e"},"package":"2467ff455350a4df7d02f1ed1449d0279605a763de5d586dcf6aa7d732508bcb"} \ No newline at end of file diff --git a/vendor/compiler_builtins/Cargo.lock b/vendor/compiler_builtins/Cargo.lock index 58451163b2..d0ad9fdb35 100644 --- a/vendor/compiler_builtins/Cargo.lock +++ b/vendor/compiler_builtins/Cargo.lock @@ -10,7 +10,7 @@ checksum = "7db2f146208d7e0fbee761b09cd65a7f51ccc38705d4e7262dad4d73b12a76b1" [[package]] name = "compiler_builtins" -version = "0.1.49" +version = "0.1.53" dependencies = [ "cc", "rustc-std-workspace-core", diff --git a/vendor/compiler_builtins/Cargo.toml b/vendor/compiler_builtins/Cargo.toml index 9c4f37006b..29030f4b2a 100644 --- a/vendor/compiler_builtins/Cargo.toml +++ b/vendor/compiler_builtins/Cargo.toml @@ -11,7 +11,7 @@ [package] name = "compiler_builtins" -version = "0.1.49" +version = "0.1.53" authors = ["Jorge Aparicio <japaricious@gmail.com>"] links = "compiler-rt" include = ["/Cargo.toml", "/build.rs", "/src/*", "/examples/*", "/LICENSE.txt", "/README.md", "/compiler-rt/*", "/libm/src/math/*"] diff --git a/vendor/compiler_builtins/build.rs b/vendor/compiler_builtins/build.rs index d4cfe0e1c2..b930f1d8d6 100644 --- a/vendor/compiler_builtins/build.rs +++ b/vendor/compiler_builtins/build.rs @@ -23,9 +23,9 @@ fn main() { return; } - // Forcibly enable memory intrinsics on wasm32 & SGX as we don't have a libc to + // Forcibly enable memory intrinsics on wasm & SGX as we don't have a libc to // provide them. - if (target.contains("wasm32") && !target.contains("wasi")) + if (target.contains("wasm") && !target.contains("wasi")) || (target.contains("sgx") && target.contains("fortanix")) || target.contains("-none") || target.contains("nvptx") @@ -33,6 +33,15 @@ fn main() { println!("cargo:rustc-cfg=feature=\"mem\""); } + // These targets have hardware unaligned access support. + if target.contains("x86_64") + || target.contains("i686") + || target.contains("aarch64") + || target.contains("bpf") + { + println!("cargo:rustc-cfg=feature=\"mem-unaligned\""); + } + // NOTE we are going to assume that llvm-target, what determines our codegen option, matches the // target triple. This is usually correct for our built-in targets but can break in presence of // custom targets, which can have arbitrary names. @@ -45,13 +54,13 @@ fn main() { if !cfg!(feature = "mangled-names") && cfg!(feature = "c") { // Don't use a C compiler for these targets: // - // * wasm32 - clang 8 for wasm is somewhat hard to come by and it's + // * wasm - clang for wasm is somewhat hard to come by and it's // unlikely that the C is really that much better than our own Rust. // * nvptx - everything is bitcode, not compatible with mixed C/Rust // * riscv - the rust-lang/rust distribution container doesn't have a C // compiler nor is cc-rs ready for compilation to riscv (at this // time). This can probably be removed in the future - if !target.contains("wasm32") && !target.contains("nvptx") && !target.starts_with("riscv") { + if !target.contains("wasm") && !target.contains("nvptx") && !target.starts_with("riscv") { #[cfg(feature = "c")] c::compile(&llvm_target, &target); } diff --git a/vendor/compiler_builtins/src/lib.rs b/vendor/compiler_builtins/src/lib.rs index 21796ca554..fcafb8978f 100644 --- a/vendor/compiler_builtins/src/lib.rs +++ b/vendor/compiler_builtins/src/lib.rs @@ -39,7 +39,8 @@ pub mod float; pub mod int; #[cfg(any( - all(target_arch = "wasm32", target_os = "unknown"), + all(target_family = "wasm", target_os = "unknown"), + all(target_arch = "x86_64", target_os = "uefi"), all(target_arch = "arm", target_os = "none"), all(target_vendor = "fortanix", target_env = "sgx") ))] diff --git a/vendor/compiler_builtins/src/math.rs b/vendor/compiler_builtins/src/math.rs index 94f91124bf..fa59753f8f 100644 --- a/vendor/compiler_builtins/src/math.rs +++ b/vendor/compiler_builtins/src/math.rs @@ -16,28 +16,22 @@ macro_rules! no_mangle { #[cfg(any( all( - target_arch = "wasm32", + target_family = "wasm", target_os = "unknown", not(target_env = "wasi") ), + all(target_arch = "x86_64", target_os = "uefi"), + all(target_arch = "xtensa", target_os = "none"), all(target_vendor = "fortanix", target_env = "sgx") ))] no_mangle! { fn acos(x: f64) -> f64; fn asin(x: f64) -> f64; - fn atan(x: f64) -> f64; - fn atan2(x: f64, y: f64) -> f64; fn cbrt(x: f64) -> f64; - fn cosh(x: f64) -> f64; fn expm1(x: f64) -> f64; fn hypot(x: f64, y: f64) -> f64; - fn log1p(x: f64) -> f64; - fn sinh(x: f64) -> f64; fn tan(x: f64) -> f64; - fn tanh(x: f64) -> f64; fn cos(x: f64) -> f64; - fn cosf(x: f32) -> f32; - fn exp(x: f64) -> f64; fn expf(x: f32) -> f32; fn log2(x: f64) -> f64; fn log2f(x: f32) -> f32; @@ -52,33 +46,53 @@ no_mangle! { fn round(x: f64) -> f64; fn roundf(x: f32) -> f32; fn sin(x: f64) -> f64; - fn sinf(x: f32) -> f32; fn pow(x: f64, y: f64) -> f64; fn powf(x: f32, y: f32) -> f32; - fn exp2(x: f64) -> f64; - fn exp2f(x: f32) -> f32; fn fmod(x: f64, y: f64) -> f64; fn fmodf(x: f32, y: f32) -> f32; - fn fma(x: f64, y: f64, z: f64) -> f64; - fn fmaf(x: f32, y: f32, z: f32) -> f32; fn acosf(n: f32) -> f32; - fn asinf(n: f32) -> f32; fn atan2f(a: f32, b: f32) -> f32; fn atanf(n: f32) -> f32; - fn cbrtf(n: f32) -> f32; fn coshf(n: f32) -> f32; fn expm1f(n: f32) -> f32; fn fdim(a: f64, b: f64) -> f64; fn fdimf(a: f32, b: f32) -> f32; - fn hypotf(x: f32, y: f32) -> f32; fn log1pf(n: f32) -> f32; fn sinhf(n: f32) -> f32; - fn tanf(n: f32) -> f32; fn tanhf(n: f32) -> f32; fn ldexp(f: f64, n: i32) -> f64; fn ldexpf(f: f32, n: i32) -> f32; } +#[cfg(any( + all( + target_family = "wasm", + target_os = "unknown", + not(target_env = "wasi") + ), + all(target_arch = "xtensa", target_os = "none"), + all(target_vendor = "fortanix", target_env = "sgx") +))] +no_mangle! { + fn atan(x: f64) -> f64; + fn atan2(x: f64, y: f64) -> f64; + fn cosh(x: f64) -> f64; + fn log1p(x: f64) -> f64; + fn sinh(x: f64) -> f64; + fn tanh(x: f64) -> f64; + fn cosf(x: f32) -> f32; + fn exp(x: f64) -> f64; + fn sinf(x: f32) -> f32; + fn exp2(x: f64) -> f64; + fn exp2f(x: f32) -> f32; + fn fma(x: f64, y: f64, z: f64) -> f64; + fn fmaf(x: f32, y: f32, z: f32) -> f32; + fn asinf(n: f32) -> f32; + fn cbrtf(n: f32) -> f32; + fn hypotf(x: f32, y: f32) -> f32; + fn tanf(n: f32) -> f32; +} + #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] no_mangle! { fn ceil(x: f64) -> f64; diff --git a/vendor/compiler_builtins/src/mem/impls.rs b/vendor/compiler_builtins/src/mem/impls.rs index b3eef9901d..65887a3389 100644 --- a/vendor/compiler_builtins/src/mem/impls.rs +++ b/vendor/compiler_builtins/src/mem/impls.rs @@ -1,27 +1,257 @@ +use core::intrinsics::likely; + +const WORD_SIZE: usize = core::mem::size_of::<usize>(); +const WORD_MASK: usize = WORD_SIZE - 1; + +// If the number of bytes involved exceed this threshold we will opt in word-wise copy. +// The value here selected is max(2 * WORD_SIZE, 16): +// * We need at least 2 * WORD_SIZE bytes to guarantee that at least 1 word will be copied through +// word-wise copy. +// * The word-wise copy logic needs to perform some checks so it has some small overhead. +// ensures that even on 32-bit platforms we have copied at least 8 bytes through +// word-wise copy so the saving of word-wise copy outweights the fixed overhead. +const WORD_COPY_THRESHOLD: usize = if 2 * WORD_SIZE > 16 { + 2 * WORD_SIZE +} else { + 16 +}; + +#[cfg(feature = "mem-unaligned")] +unsafe fn read_usize_unaligned(x: *const usize) -> usize { + // Do not use `core::ptr::read_unaligned` here, since it calls `copy_nonoverlapping` which + // is translated to memcpy in LLVM. + let x_read = (x as *const [u8; core::mem::size_of::<usize>()]).read(); + core::mem::transmute(x_read) +} + #[inline(always)] -pub unsafe fn copy_forward(dest: *mut u8, src: *const u8, n: usize) { - let mut i = 0; - while i < n { - *dest.add(i) = *src.add(i); - i += 1; +pub unsafe fn copy_forward(mut dest: *mut u8, mut src: *const u8, mut n: usize) { + #[inline(always)] + unsafe fn copy_forward_bytes(mut dest: *mut u8, mut src: *const u8, n: usize) { + let dest_end = dest.add(n); + while dest < dest_end { + *dest = *src; + dest = dest.add(1); + src = src.add(1); + } + } + + #[inline(always)] + unsafe fn copy_forward_aligned_words(dest: *mut u8, src: *const u8, n: usize) { + let mut dest_usize = dest as *mut usize; + let mut src_usize = src as *mut usize; + let dest_end = dest.add(n) as *mut usize; + + while dest_usize < dest_end { + *dest_usize = *src_usize; + dest_usize = dest_usize.add(1); + src_usize = src_usize.add(1); + } + } + + #[cfg(not(feature = "mem-unaligned"))] + #[inline(always)] + unsafe fn copy_forward_misaligned_words(dest: *mut u8, src: *const u8, n: usize) { + let mut dest_usize = dest as *mut usize; + let dest_end = dest.add(n) as *mut usize; + + // Calculate the misalignment offset and shift needed to reassemble value. + let offset = src as usize & WORD_MASK; + let shift = offset * 8; + + // Realign src + let mut src_aligned = (src as usize & !WORD_MASK) as *mut usize; + // This will read (but won't use) bytes out of bound. + let mut prev_word = core::intrinsics::atomic_load_unordered(src_aligned); + + while dest_usize < dest_end { + src_aligned = src_aligned.add(1); + let cur_word = *src_aligned; + #[cfg(target_endian = "little")] + let resembled = prev_word >> shift | cur_word << (WORD_SIZE * 8 - shift); + #[cfg(target_endian = "big")] + let resembled = prev_word << shift | cur_word >> (WORD_SIZE * 8 - shift); + prev_word = cur_word; + + *dest_usize = resembled; + dest_usize = dest_usize.add(1); + } + } + + #[cfg(feature = "mem-unaligned")] + #[inline(always)] + unsafe fn copy_forward_misaligned_words(dest: *mut u8, src: *const u8, n: usize) { + let mut dest_usize = dest as *mut usize; + let mut src_usize = src as *mut usize; + let dest_end = dest.add(n) as *mut usize; + + while dest_usize < dest_end { + *dest_usize = read_usize_unaligned(src_usize); + dest_usize = dest_usize.add(1); + src_usize = src_usize.add(1); + } } + + if n >= WORD_COPY_THRESHOLD { + // Align dest + // Because of n >= 2 * WORD_SIZE, dst_misalignment < n + let dest_misalignment = (dest as usize).wrapping_neg() & WORD_MASK; + copy_forward_bytes(dest, src, dest_misalignment); + dest = dest.add(dest_misalignment); + src = src.add(dest_misalignment); + n -= dest_misalignment; + + let n_words = n & !WORD_MASK; + let src_misalignment = src as usize & WORD_MASK; + if likely(src_misalignment == 0) { + copy_forward_aligned_words(dest, src, n_words); + } else { + copy_forward_misaligned_words(dest, src, n_words); + } + dest = dest.add(n_words); + src = src.add(n_words); + n -= n_words; + } + copy_forward_bytes(dest, src, n); } #[inline(always)] -pub unsafe fn copy_backward(dest: *mut u8, src: *const u8, n: usize) { - // copy from end - let mut i = n; - while i != 0 { - i -= 1; - *dest.add(i) = *src.add(i); +pub unsafe fn copy_backward(dest: *mut u8, src: *const u8, mut n: usize) { + // The following backward copy helper functions uses the pointers past the end + // as their inputs instead of pointers to the start! + #[inline(always)] + unsafe fn copy_backward_bytes(mut dest: *mut u8, mut src: *const u8, n: usize) { + let dest_start = dest.sub(n); + while dest_start < dest { + dest = dest.sub(1); + src = src.sub(1); + *dest = *src; + } } + + #[inline(always)] + unsafe fn copy_backward_aligned_words(dest: *mut u8, src: *const u8, n: usize) { + let mut dest_usize = dest as *mut usize; + let mut src_usize = src as *mut usize; + let dest_start = dest.sub(n) as *mut usize; + + while dest_start < dest_usize { + dest_usize = dest_usize.sub(1); + src_usize = src_usize.sub(1); + *dest_usize = *src_usize; + } + } + + #[cfg(not(feature = "mem-unaligned"))] + #[inline(always)] + unsafe fn copy_backward_misaligned_words(dest: *mut u8, src: *const u8, n: usize) { + let mut dest_usize = dest as *mut usize; + let dest_start = dest.sub(n) as *mut usize; + + // Calculate the misalignment offset and shift needed to reassemble value. + let offset = src as usize & WORD_MASK; + let shift = offset * 8; + + // Realign src_aligned + let mut src_aligned = (src as usize & !WORD_MASK) as *mut usize; + // This will read (but won't use) bytes out of bound. + let mut prev_word = core::intrinsics::atomic_load_unordered(src_aligned); + + while dest_start < dest_usize { + src_aligned = src_aligned.sub(1); + let cur_word = *src_aligned; + #[cfg(target_endian = "little")] + let resembled = prev_word << (WORD_SIZE * 8 - shift) | cur_word >> shift; + #[cfg(target_endian = "big")] + let resembled = prev_word >> (WORD_SIZE * 8 - shift) | cur_word << shift; + prev_word = cur_word; + + dest_usize = dest_usize.sub(1); + *dest_usize = resembled; + } + } + + #[cfg(feature = "mem-unaligned")] + #[inline(always)] + unsafe fn copy_backward_misaligned_words(dest: *mut u8, src: *const u8, n: usize) { + let mut dest_usize = dest as *mut usize; + let mut src_usize = src as *mut usize; + let dest_start = dest.sub(n) as *mut usize; + + while dest_start < dest_usize { + dest_usize = dest_usize.sub(1); + src_usize = src_usize.sub(1); + *dest_usize = read_usize_unaligned(src_usize); + } + } + + let mut dest = dest.add(n); + let mut src = src.add(n); + + if n >= WORD_COPY_THRESHOLD { + // Align dest + // Because of n >= 2 * WORD_SIZE, dst_misalignment < n + let dest_misalignment = dest as usize & WORD_MASK; + copy_backward_bytes(dest, src, dest_misalignment); + dest = dest.sub(dest_misalignment); + src = src.sub(dest_misalignment); + n -= dest_misalignment; + + let n_words = n & !WORD_MASK; + let src_misalignment = src as usize & WORD_MASK; + if likely(src_misalignment == 0) { + copy_backward_aligned_words(dest, src, n_words); + } else { + copy_backward_misaligned_words(dest, src, n_words); + } + dest = dest.sub(n_words); + src = src.sub(n_words); + n -= n_words; + } + copy_backward_bytes(dest, src, n); } #[inline(always)] -pub unsafe fn set_bytes(s: *mut u8, c: u8, n: usize) { - let mut i = 0; - while i < n { - *s.add(i) = c; - i += 1; +pub unsafe fn set_bytes(mut s: *mut u8, c: u8, mut n: usize) { + #[inline(always)] + pub unsafe fn set_bytes_bytes(mut s: *mut u8, c: u8, n: usize) { + let end = s.add(n); + while s < end { + *s = c; + s = s.add(1); + } + } + + #[inline(always)] + pub unsafe fn set_bytes_words(s: *mut u8, c: u8, n: usize) { + let mut broadcast = c as usize; + let mut bits = 8; + while bits < WORD_SIZE * 8 { + broadcast |= broadcast << bits; + bits *= 2; + } + + let mut s_usize = s as *mut usize; + let end = s.add(n) as *mut usize; + + while s_usize < end { + *s_usize = broadcast; + s_usize = s_usize.add(1); + } + } + + if likely(n >= WORD_COPY_THRESHOLD) { + // Align s + // Because of n >= 2 * WORD_SIZE, dst_misalignment < n + let misalignment = (s as usize).wrapping_neg() & WORD_MASK; + set_bytes_bytes(s, c, misalignment); + s = s.add(misalignment); + n -= misalignment; + + let n_words = n & !WORD_MASK; + set_bytes_words(s, c, n_words); + s = s.add(n_words); + n -= n_words; } + set_bytes_bytes(s, c, n); } diff --git a/vendor/compiletest_rs/.cargo-checksum.json b/vendor/compiletest_rs/.cargo-checksum.json index 57918c7942..fcb51a348b 100644 --- a/vendor/compiletest_rs/.cargo-checksum.json +++ b/vendor/compiletest_rs/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"4891fdd5edf9f1985a8a034d5d5f2b6db3316dd008db49166bfcbbab5e522134","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","README.md":"e0655e85239c6e887c0f35e1b97fb2574127ea61c28e3deec93c20b560f47892","build.rs":"905784fbb4a75c17279a88fd476e7221104adf00b4dd745a4a66bd41cac8d77a","src/common.rs":"7dd4be7b62e4b3ef8a42f6e0dfe70b9a23b1dbca0df79c1ac78021923865fb0b","src/errors.rs":"88a36d1726d90b11bf9272b1439dd52cd4fdf2e70e6e0cb6cfb323f76d84e3ff","src/header.rs":"37a25336e896f3179ed4a1e2af19adc26ef79cc918d5ec49d7ae28205d32a29f","src/json.rs":"e278c4c3c32c60e840a250b0979926e2ac333dcbbbaae5ab6fcf01ca05bef625","src/lib.rs":"6d0263ac1848813cf1da27bbff748e265af70cefe3f0c186daafdc69262ff3b6","src/raise_fd_limit.rs":"b0840fe16df9edaae0571499e105db47768050fcd62729d1e56295f2db34318e","src/read2.rs":"fb9caa84bec8c9c3d2c1ee39a4a6698c461fdc77aec086c74fd7738a6acf4155","src/runtest.rs":"bdaf095ebe777987b35cecd657542375d32a897b3e886ec8e4e14580534d86d7","src/uidiff.rs":"2f612bd4ed76d68c0f6b3eb8dda5adf14a3e6ceef261c88c810ac6b6857e2d34","src/util.rs":"a8a04a1111e3f9d11a9f19889215d8fff58d4b5449213912b3d1bd2c5fabca64","tests/bless.rs":"29031f02666102ab8cde316b9206bf1e770275f9fa6e0172754dcad859a52b5b","tests/test_support/mod.rs":"21ec96cca07cf95b6e3333917a5158a6c47356940063f77d52503b97fd3d8b79"},"package":"64698e5e2435db061a85e6320af12c30c5fd88eb84b35d2c1e03ce4f143255ca"} \ No newline at end of file +{"files":{"Cargo.toml":"0c7fa650d4c35d132ad94e06e24b899e359b315db152485907b20ca30638e18a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","README.md":"e0655e85239c6e887c0f35e1b97fb2574127ea61c28e3deec93c20b560f47892","build.rs":"905784fbb4a75c17279a88fd476e7221104adf00b4dd745a4a66bd41cac8d77a","src/common.rs":"df14f9c75c6a341c5bbc90c4b386c20f66164196f3b4b2ffc19b454d6b658e2b","src/errors.rs":"88a36d1726d90b11bf9272b1439dd52cd4fdf2e70e6e0cb6cfb323f76d84e3ff","src/header.rs":"833a733a231d32139085683063caec6d28a6896328e79ebc72f57f5b9b3024ab","src/json.rs":"e278c4c3c32c60e840a250b0979926e2ac333dcbbbaae5ab6fcf01ca05bef625","src/lib.rs":"e6b04ba2b9108cfc72dae24ef1a38bac03a27e37e6efe0ae9a0d455c8be6105e","src/raise_fd_limit.rs":"b0840fe16df9edaae0571499e105db47768050fcd62729d1e56295f2db34318e","src/read2.rs":"fb9caa84bec8c9c3d2c1ee39a4a6698c461fdc77aec086c74fd7738a6acf4155","src/runtest.rs":"9dc12384637275790ca5a030f79e7ea72be991ff8d5365193e48895a30db6454","src/uidiff.rs":"2f612bd4ed76d68c0f6b3eb8dda5adf14a3e6ceef261c88c810ac6b6857e2d34","src/util.rs":"a8a04a1111e3f9d11a9f19889215d8fff58d4b5449213912b3d1bd2c5fabca64","tests/bless.rs":"29031f02666102ab8cde316b9206bf1e770275f9fa6e0172754dcad859a52b5b","tests/test_support/mod.rs":"21ec96cca07cf95b6e3333917a5158a6c47356940063f77d52503b97fd3d8b79"},"package":"29843cb8d351febf86557681d049d1e1652b81a086a190fa1173c07fd17fbf83"} \ No newline at end of file diff --git a/vendor/compiletest_rs/Cargo.toml b/vendor/compiletest_rs/Cargo.toml index 88da576de4..89b46680ca 100644 --- a/vendor/compiletest_rs/Cargo.toml +++ b/vendor/compiletest_rs/Cargo.toml @@ -3,16 +3,15 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies +# to registry (e.g., crates.io) dependencies. # -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. [package] name = "compiletest_rs" -version = "0.7.0" +version = "0.7.1" authors = ["The Rust Project Developers", "Thomas Bracht Laumann Jespersen <laumann.thomas@gmail.com>", "Manish Goregaokar <manishsmail@gmail.com>"] description = "The compiletest utility from the Rust compiler as a standalone testing harness" readme = "README.md" diff --git a/vendor/compiletest_rs/src/common.rs b/vendor/compiletest_rs/src/common.rs index 7ab82ee40b..17eaa54473 100644 --- a/vendor/compiletest_rs/src/common.rs +++ b/vendor/compiletest_rs/src/common.rs @@ -226,6 +226,9 @@ pub struct Config { /// created in `/<build_base>/rustfix_missing_coverage.txt` pub rustfix_coverage: bool, + /// The default Rust edition + pub edition: Option<String>, + // Configuration for various run-make tests frobbing things like C compilers // or querying about various LLVM component information. pub cc: String, @@ -416,6 +419,7 @@ impl Default for Config { llvm_components: "llvm-components".to_string(), llvm_cxxflags: "llvm-cxxflags".to_string(), nodejs: None, + edition: None, } } } diff --git a/vendor/compiletest_rs/src/header.rs b/vendor/compiletest_rs/src/header.rs index 2bce29a29d..77b5eb16f7 100644 --- a/vendor/compiletest_rs/src/header.rs +++ b/vendor/compiletest_rs/src/header.rs @@ -111,7 +111,7 @@ impl EarlyProps { let v_max = range_components[1].expect(ERROR_MESSAGE); (v_min, v_max) } - _ => panic!(ERROR_MESSAGE), + _ => panic!("{}", ERROR_MESSAGE), } } @@ -287,6 +287,7 @@ impl TestProps { testfile: &Path, cfg: Option<&str>, config: &Config) { + let mut has_edition = false; iter_header(testfile, cfg, &mut |ln| { @@ -301,6 +302,7 @@ impl TestProps { if let Some(edition) = config.parse_edition(ln) { self.compile_flags.push(format!("--edition={}", edition)); + has_edition = true; } if let Some(r) = config.parse_revisions(ln) { @@ -403,6 +405,10 @@ impl TestProps { } } } + + if let (Some(edition), false) = (&config.edition, has_edition) { + self.compile_flags.push(format!("--edition={}", edition)); + } } } diff --git a/vendor/compiletest_rs/src/lib.rs b/vendor/compiletest_rs/src/lib.rs index d0f4875fb5..cdf6ece8e6 100644 --- a/vendor/compiletest_rs/src/lib.rs +++ b/vendor/compiletest_rs/src/lib.rs @@ -261,6 +261,10 @@ pub fn make_test(config: &Config, testpaths: &TestPaths) -> test::TestDescAndFn ignore: early_props.ignore, should_panic: should_panic, allow_fail: false, + #[cfg(feature = "rustc")] + compile_fail: false, + #[cfg(feature = "rustc")] + no_run: false, test_type: test::TestType::IntegrationTest, }, testfn: make_test_closure(config, testpaths), diff --git a/vendor/compiletest_rs/src/runtest.rs b/vendor/compiletest_rs/src/runtest.rs index 52364a5f7d..c52551488f 100644 --- a/vendor/compiletest_rs/src/runtest.rs +++ b/vendor/compiletest_rs/src/runtest.rs @@ -2616,6 +2616,11 @@ actual:\n\ let parent_dir = self.testpaths.file.parent().unwrap(); normalize_path(parent_dir, "$DIR"); + if let Ok(src_dir_str) = std::env::var("CARGO_MANIFEST_DIR") { + let src_dir = Path::new(&src_dir_str); + normalize_path(src_dir, "$SRC_DIR"); + } + // Paths into the build directory let test_build_dir = &self.config.build_base; normalize_path(test_build_dir, "$TEST_BUILD_DIR"); diff --git a/vendor/dlmalloc/.cargo-checksum.json b/vendor/dlmalloc/.cargo-checksum.json index 9f2a10f2b0..2d92af1558 100644 --- a/vendor/dlmalloc/.cargo-checksum.json +++ b/vendor/dlmalloc/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"444e27e88cbc42aad5a61d471747cf51c779c8ca33ba40237f52c4ef06d0f874","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"e26786bd9af68f3065532fa85b68b8de12e0f6f455240d9a903ae947986aaa5f","build.rs":"1423186016b6fecf4dc2c3a7d506face8f644ec9c3dda035fe485d25a7e6a02d","src/dlmalloc.c":"103602c3fcbe200d5e257cdd7353d84bcc033d887bea3b245321319bf5401f47","src/dlmalloc.rs":"d8120a4e3069107d2782e4df7e8d062486ed2d9534237aa270d78e4cdacd1f34","src/dummy.rs":"00dc39321426add094ab8efba58fb5f886726c06f032b8cb184b3d5fc71ad8ff","src/global.rs":"51b9cd2c1ed33bad34a2d4565113338eedc9154690fe06b6b67182b994ec5ac0","src/lib.rs":"86824bdfb667e88a9ef9b4baa535cd045229ca2b8b881640683f47bff904e767","src/linux.rs":"52e13e1e0c83e53a1b6da6b928c6d410cef1627008f021c12d45271aac007e6c","src/macos.rs":"63887811f49e96953aaa8472211bda54c052e21e232113adb09e73a96bd3a8f0","src/wasm.rs":"e7e47ad1e3851d5453ebfdb3fdf82825a537c27737e048bf33377fbab522ad97","tests/global.rs":"6f3ca05b44fb60fd7967d2ca1d11338e177b0266d75454410b82ea704c246892","tests/smoke.rs":"e22bbf7c4d0e297428c5c58d117957e61c21f494d129e6e93f9490360631bc36"},"package":"332570860c2edf2d57914987bf9e24835425f75825086b6ba7d1e6a3e4f1f254"} \ No newline at end of file +{"files":{"Cargo.toml":"8fb851b6256b2897689a27179da1683db869dc6625b7b0e02fba263c3c16a6b7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"e26786bd9af68f3065532fa85b68b8de12e0f6f455240d9a903ae947986aaa5f","build.rs":"1423186016b6fecf4dc2c3a7d506face8f644ec9c3dda035fe485d25a7e6a02d","src/dlmalloc.c":"103602c3fcbe200d5e257cdd7353d84bcc033d887bea3b245321319bf5401f47","src/dlmalloc.rs":"33111e31c78c43a0fffb618a84c0e9644f1bc830167ad25342529919ecc897ad","src/dummy.rs":"00dc39321426add094ab8efba58fb5f886726c06f032b8cb184b3d5fc71ad8ff","src/global.rs":"41a14b65509d87e4b010c3f06550bd3a1b3987e1d8703f6d915285558b4c1f43","src/lib.rs":"cb0e7add0947e2778a79a799554bd2e4765bf2a1bc6662c8cf3b5f1aecfb03ca","src/unix.rs":"9b062bc1f24ae99aa4ccbf621c020e4c3f626f70c3603e51a1fb834375b1bec4","src/wasm.rs":"ca080eab006215b4ec3d1550cb300cec02c62d3bde5e447f04dfdf74d3f87972","tests/global.rs":"6f3ca05b44fb60fd7967d2ca1d11338e177b0266d75454410b82ea704c246892","tests/smoke.rs":"e22bbf7c4d0e297428c5c58d117957e61c21f494d129e6e93f9490360631bc36"},"package":"a6fe28e0bf9357092740362502f5cc7955d8dc125ebda71dec72336c2e15c62e"} \ No newline at end of file diff --git a/vendor/dlmalloc/Cargo.toml b/vendor/dlmalloc/Cargo.toml index 85efa71a10..a8caf460d6 100644 --- a/vendor/dlmalloc/Cargo.toml +++ b/vendor/dlmalloc/Cargo.toml @@ -3,16 +3,15 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies +# to registry (e.g., crates.io) dependencies. # -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. [package] name = "dlmalloc" -version = "0.2.1" +version = "0.2.3" authors = ["Alex Crichton <alex@alexcrichton.com>"] description = "A Rust port of the dlmalloc allocator\n" homepage = "https://github.com/alexcrichton/dlmalloc-rs" diff --git a/vendor/dlmalloc/src/dlmalloc.rs b/vendor/dlmalloc/src/dlmalloc.rs index d16f523269..a4b4b71b4e 100644 --- a/vendor/dlmalloc/src/dlmalloc.rs +++ b/vendor/dlmalloc/src/dlmalloc.rs @@ -193,11 +193,15 @@ impl<A: Allocator> Dlmalloc<A> { } fn align_offset(&self, addr: *mut u8) -> usize { - align_up(addr as usize, self.malloc_alignment()) - (addr as usize) + self.align_offset_usize(addr as usize) + } + + fn align_offset_usize(&self, addr: usize) -> usize { + align_up(addr, self.malloc_alignment()) - (addr as usize) } fn top_foot_size(&self) -> usize { - self.align_offset(unsafe { Chunk::to_mem(ptr::null_mut()) }) + self.align_offset_usize(Chunk::mem_offset() as usize) + self.pad_request(mem::size_of::<Segment>()) + self.min_chunk_size() } @@ -1723,7 +1727,11 @@ impl Chunk { } unsafe fn to_mem(me: *mut Chunk) -> *mut u8 { - (me as *mut u8).offset(2 * (mem::size_of::<usize>() as isize)) + (me as *mut u8).offset(Chunk::mem_offset()) + } + + fn mem_offset() -> isize { + 2 * (mem::size_of::<usize>() as isize) } unsafe fn from_mem(mem: *mut u8) -> *mut Chunk { diff --git a/vendor/dlmalloc/src/global.rs b/vendor/dlmalloc/src/global.rs index fbac31539c..c761fdeaf8 100644 --- a/vendor/dlmalloc/src/global.rs +++ b/vendor/dlmalloc/src/global.rs @@ -3,6 +3,8 @@ use core::ops::{Deref, DerefMut}; use Dlmalloc; +pub use sys::enable_alloc_after_fork; + /// An instance of a "global allocator" backed by `Dlmalloc` /// /// This API requires the `global` feature is activated, and this type diff --git a/vendor/dlmalloc/src/lib.rs b/vendor/dlmalloc/src/lib.rs index 22a43c65e8..238386fbc8 100644 --- a/vendor/dlmalloc/src/lib.rs +++ b/vendor/dlmalloc/src/lib.rs @@ -14,13 +14,14 @@ #![allow(dead_code)] #![no_std] #![deny(missing_docs)] +#![cfg_attr(target_arch = "wasm64", feature(simd_wasm64))] use core::cmp; use core::ptr; use sys::System; #[cfg(feature = "global")] -pub use self::global::GlobalDlmalloc; +pub use self::global::{enable_alloc_after_fork, GlobalDlmalloc}; mod dlmalloc; #[cfg(feature = "global")] @@ -72,19 +73,15 @@ pub unsafe trait Allocator: Send { /// lingering memory back to the OS. That may happen eventually though! pub struct Dlmalloc<A = System>(dlmalloc::Dlmalloc<A>); -#[cfg(target_arch = "wasm32")] +#[cfg(target_family = "wasm")] #[path = "wasm.rs"] mod sys; -#[cfg(target_os = "macos")] -#[path = "macos.rs"] +#[cfg(any(target_os = "linux", target_os = "macos"))] +#[path = "unix.rs"] mod sys; -#[cfg(target_os = "linux")] -#[path = "linux.rs"] -mod sys; - -#[cfg(not(any(target_os = "linux", target_os = "macos", target_arch = "wasm32")))] +#[cfg(not(any(target_os = "linux", target_os = "macos", target_family = "wasm")))] #[path = "dummy.rs"] mod sys; diff --git a/vendor/dlmalloc/src/macos.rs b/vendor/dlmalloc/src/macos.rs deleted file mode 100644 index d131271899..0000000000 --- a/vendor/dlmalloc/src/macos.rs +++ /dev/null @@ -1,72 +0,0 @@ -extern crate libc; - -use core::ptr; -use Allocator; - -/// System setting for MacOS -pub struct System { - _priv: (), -} - -impl System { - pub const fn new() -> System { - System { _priv: () } - } -} - -#[cfg(feature = "global")] -static mut LOCK: libc::pthread_mutex_t = libc::PTHREAD_MUTEX_INITIALIZER; - -unsafe impl Allocator for System { - fn alloc(&self, size: usize) -> (*mut u8, usize, u32) { - let addr = unsafe { - libc::mmap( - 0 as *mut _, - size, - libc::PROT_WRITE | libc::PROT_READ, - libc::MAP_ANON | libc::MAP_PRIVATE, - -1, - 0, - ) - }; - if addr == libc::MAP_FAILED { - (ptr::null_mut(), 0, 0) - } else { - (addr as *mut u8, size, 0) - } - } - - fn remap(&self, _ptr: *mut u8, _oldsize: usize, _newsize: usize, _can_move: bool) -> *mut u8 { - ptr::null_mut() - } - - fn free_part(&self, ptr: *mut u8, oldsize: usize, newsize: usize) -> bool { - unsafe { libc::munmap(ptr.offset(newsize as isize) as *mut _, oldsize - newsize) == 0 } - } - - fn free(&self, ptr: *mut u8, size: usize) -> bool { - unsafe { libc::munmap(ptr as *mut _, size) == 0 } - } - - fn can_release_part(&self, _flags: u32) -> bool { - true - } - - fn allocates_zeros(&self) -> bool { - true - } - - fn page_size(&self) -> usize { - 4096 - } -} - -#[cfg(feature = "global")] -pub fn acquire_global_lock() { - unsafe { assert_eq!(libc::pthread_mutex_lock(&mut LOCK), 0) } -} - -#[cfg(feature = "global")] -pub fn release_global_lock() { - unsafe { assert_eq!(libc::pthread_mutex_unlock(&mut LOCK), 0) } -} diff --git a/vendor/dlmalloc/src/linux.rs b/vendor/dlmalloc/src/unix.rs similarity index 56% rename from vendor/dlmalloc/src/linux.rs rename to vendor/dlmalloc/src/unix.rs index 42e6549ec9..a4f9914ec6 100644 --- a/vendor/dlmalloc/src/linux.rs +++ b/vendor/dlmalloc/src/unix.rs @@ -24,7 +24,7 @@ unsafe impl Allocator for System { 0 as *mut _, size, libc::PROT_WRITE | libc::PROT_READ, - libc::MAP_ANONYMOUS | libc::MAP_PRIVATE, + libc::MAP_ANON | libc::MAP_PRIVATE, -1, 0, ) @@ -36,6 +36,7 @@ unsafe impl Allocator for System { } } + #[cfg(target_os = "linux")] fn remap(&self, ptr: *mut u8, oldsize: usize, newsize: usize, can_move: bool) -> *mut u8 { let flags = if can_move { libc::MREMAP_MAYMOVE } else { 0 }; let ptr = unsafe { libc::mremap(ptr as *mut _, oldsize, newsize, flags) }; @@ -46,6 +47,12 @@ unsafe impl Allocator for System { } } + #[cfg(target_os = "macos")] + fn remap(&self, _ptr: *mut u8, _oldsize: usize, _newsize: usize, _can_move: bool) -> *mut u8 { + ptr::null_mut() + } + + #[cfg(target_os = "linux")] fn free_part(&self, ptr: *mut u8, oldsize: usize, newsize: usize) -> bool { unsafe { let rc = libc::mremap(ptr as *mut _, oldsize, newsize, 0); @@ -56,6 +63,11 @@ unsafe impl Allocator for System { } } + #[cfg(target_os = "macos")] + fn free_part(&self, ptr: *mut u8, oldsize: usize, newsize: usize) -> bool { + unsafe { libc::munmap(ptr.offset(newsize as isize) as *mut _, oldsize - newsize) == 0 } + } + fn free(&self, ptr: *mut u8, size: usize) -> bool { unsafe { libc::munmap(ptr as *mut _, size) == 0 } } @@ -82,3 +94,40 @@ pub fn acquire_global_lock() { pub fn release_global_lock() { unsafe { assert_eq!(libc::pthread_mutex_unlock(&mut LOCK), 0) } } + +#[cfg(feature = "global")] +/// allows the allocator to remain unsable in the child process, +/// after a call to `fork(2)` +/// +/// #Safety +/// +/// if used, this function must be called, +/// before any allocations are made with the global allocator. +pub unsafe fn enable_alloc_after_fork() { + // atfork must only be called once, to avoid a deadlock, + // where the handler attempts to acquire the global lock twice + static mut FORK_PROTECTED: bool = false; + + unsafe extern "C" fn _acquire_global_lock() { + acquire_global_lock() + } + + unsafe extern "C" fn _release_global_lock() { + release_global_lock() + } + + acquire_global_lock(); + // if a process forks, + // it will acquire the lock before any other thread, + // protecting it from deadlock, + // due to the child being created with only the calling thread. + if !FORK_PROTECTED { + libc::pthread_atfork( + Some(_acquire_global_lock), + Some(_release_global_lock), + Some(_release_global_lock), + ); + FORK_PROTECTED = true; + } + release_global_lock(); +} diff --git a/vendor/dlmalloc/src/wasm.rs b/vendor/dlmalloc/src/wasm.rs index 381fb025fe..216fe43afd 100644 --- a/vendor/dlmalloc/src/wasm.rs +++ b/vendor/dlmalloc/src/wasm.rs @@ -1,4 +1,7 @@ -use core::arch::wasm32; +#[cfg(target_arch = "wasm32")] +use core::arch::wasm32 as wasm; +#[cfg(target_arch = "wasm64")] +use core::arch::wasm64 as wasm; use core::ptr; use Allocator; @@ -16,7 +19,7 @@ impl System { unsafe impl Allocator for System { fn alloc(&self, size: usize) -> (*mut u8, usize, u32) { let pages = size / self.page_size(); - let prev = wasm32::memory_grow(0, pages); + let prev = wasm::memory_grow(0, pages); if prev == usize::max_value() { return (ptr::null_mut(), 0, 0); } @@ -62,3 +65,8 @@ pub fn acquire_global_lock() { pub fn release_global_lock() { // single threaded, no need! } + +#[cfg(feature = "global")] +pub unsafe fn enable_alloc_after_fork() { + // single threaded, no need! +} diff --git a/vendor/env_logger-0.8.4/.cargo-checksum.json b/vendor/env_logger-0.8.4/.cargo-checksum.json new file mode 100644 index 0000000000..4a633b032f --- /dev/null +++ b/vendor/env_logger-0.8.4/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"CHANGELOG.md":"34c3abc5bfaeb865e9b901c245f7e41f02a96b6be50beef5302458bff548ef3c","Cargo.toml":"1003082e60245b8e54440285a0004e41b79bbece07dd077f831a82d59067e9cf","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"534d72fab83eaa93e0e61e3d092b888681e4705c77e568e4acad6d42993278ed","src/filter/mod.rs":"adc194701c7176a06e46f0e5d7f7fef101516ba51204aca9b7351c1dbc127daf","src/filter/regex.rs":"bdf875bac25e089e1e462f5dd01a88678067c24118ecd6268561c6a6af39747d","src/filter/string.rs":"fac54d51189fc0b5d2bff334b7a7e465177b431e3428299e345e1f90062d832e","src/fmt/humantime/extern_impl.rs":"f3087b29eedb8b4d5573621ad206e48a2eac72a77277be3b0e631d7dc9fb7a2e","src/fmt/humantime/mod.rs":"f4111c26cf2ffb85c1d639bd7674d55af7e1736e7e98c52f7be3070046a3253f","src/fmt/humantime/shim_impl.rs":"cce9a252abd5952fa109a72b1dfb85a593d237e22606b2b608a32c69184560e9","src/fmt/mod.rs":"e34bc64dea71c7439605aaafe53f08abd243e3478c99dd0425f6406b5f1a30dd","src/fmt/writer/atty.rs":"09d14097dee61492828daaabdbde9f43251e2cb32e79d66c1c0e63f317761704","src/fmt/writer/mod.rs":"960d9bdeb356b555d32269c6a2f68252c0553078d0c2b7915fdaf98842ef4ef3","src/fmt/writer/termcolor/extern_impl.rs":"839b8bf043939f3f22a6cd21c94e339149e5d0578a9b40fa8ca4fbe574573475","src/fmt/writer/termcolor/mod.rs":"a790f9391a50cd52be6823e3e55942de13a8d12e23d63765342ae9e8dd6d091c","src/fmt/writer/termcolor/shim_impl.rs":"9e9997823434d6741934ddeb5f4354c7da5083cee1e9dda997b4c6ccb31f9842","src/lib.rs":"cb93648746aad20da76a0630fc8ef904c2152a88e64f19123cb79284e7e35ed5","tests/init-twice-retains-filter.rs":"be5cd2132342d89ede1f5c4266173bb3c4d51cc22a1847f133d299a1c5430ccb","tests/log-in-log.rs":"29fecc65c1e0d1c22d79c97e7ca843ad44a91f27934148d7a05c48899a3f39d8","tests/log_tls_dtors.rs":"7320667d774a9b05037f7bf273fb2574dec0705707692a9cd2f46f4cd5bc68dd","tests/regexp_filter.rs":"a84263c995b534b6479a1d0abadf63f4f0264958ff86d9173d6b2139b82c4dc5"},"package":"a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3"} \ No newline at end of file diff --git a/vendor/env_logger-0.8.4/CHANGELOG.md b/vendor/env_logger-0.8.4/CHANGELOG.md new file mode 100644 index 0000000000..266e24a78b --- /dev/null +++ b/vendor/env_logger-0.8.4/CHANGELOG.md @@ -0,0 +1,3 @@ +Changes to this crate are tracked via [GitHub Releases][releases]. + +[releases]: https://github.com/env-logger-rs/env_logger/releases diff --git a/vendor/env_logger-0.8.4/Cargo.toml b/vendor/env_logger-0.8.4/Cargo.toml new file mode 100644 index 0000000000..56361f9557 --- /dev/null +++ b/vendor/env_logger-0.8.4/Cargo.toml @@ -0,0 +1,65 @@ +# 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 = "env_logger" +version = "0.8.4" +authors = ["The Rust Project Developers"] +include = ["src/**/*", "tests", "LICENSE-*", "README.md", "CHANGELOG.md"] +description = "A logging implementation for `log` which is configured via an environment\nvariable.\n" +documentation = "https://docs.rs/env_logger" +readme = "README.md" +keywords = ["logging", "log", "logger"] +categories = ["development-tools::debugging"] +license = "MIT/Apache-2.0" +repository = "https://github.com/env-logger-rs/env_logger/" + +[[test]] +name = "regexp_filter" +harness = false + +[[test]] +name = "log-in-log" +harness = false + +[[test]] +name = "log_tls_dtors" +harness = false + +[[test]] +name = "init-twice-retains-filter" +harness = false +[dependencies.atty] +version = "0.2.5" +optional = true + +[dependencies.humantime] +version = "2.0.0" +optional = true + +[dependencies.log] +version = "0.4.8" +features = ["std"] + +[dependencies.regex] +version = "1.0.3" +features = ["std", "perf"] +optional = true +default-features = false + +[dependencies.termcolor] +version = "1.0.2" +optional = true + +[features] +default = ["termcolor", "atty", "humantime", "regex"] diff --git a/vendor/itertools-0.8.2/LICENSE-APACHE b/vendor/env_logger-0.8.4/LICENSE-APACHE similarity index 100% rename from vendor/itertools-0.8.2/LICENSE-APACHE rename to vendor/env_logger-0.8.4/LICENSE-APACHE diff --git a/vendor/env_logger-0.8.4/LICENSE-MIT b/vendor/env_logger-0.8.4/LICENSE-MIT new file mode 100644 index 0000000000..39d4bdb5ac --- /dev/null +++ b/vendor/env_logger-0.8.4/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2014 The Rust Project Developers + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/vendor/env_logger-0.8.4/README.md b/vendor/env_logger-0.8.4/README.md new file mode 100644 index 0000000000..4e84e8f342 --- /dev/null +++ b/vendor/env_logger-0.8.4/README.md @@ -0,0 +1,185 @@ +# env_logger + +[![Maintenance](https://img.shields.io/badge/maintenance-actively%20maintained-brightgreen.svg)](https://github.com/env-logger-rs/env_logger) +[![crates.io](https://img.shields.io/crates/v/env_logger.svg)](https://crates.io/crates/env_logger) +[![Documentation](https://docs.rs/env_logger/badge.svg)](https://docs.rs/env_logger) +[![Documentation](https://img.shields.io/badge/docs-master-blue.svg)](https://env-logger-rs.github.io/env_logger/env_logger/index.html) +========== + +Implements a logger that can be configured via environment variables. + +## Usage + +### In libraries + +`env_logger` makes sense when used in executables (binary projects). Libraries should use the [`log`](https://doc.rust-lang.org/log) crate instead. + +### In executables + +It must be added along with `log` to the project dependencies: + +```toml +[dependencies] +log = "0.4.0" +env_logger = "0.8.4" +``` + +`env_logger` must be initialized as early as possible in the project. After it's initialized, you can use the `log` macros to do actual logging. + +```rust +#[macro_use] +extern crate log; + +fn main() { + env_logger::init(); + + info!("starting up"); + + // ... +} +``` + +Then when running the executable, specify a value for the **`RUST_LOG`** +environment variable that corresponds with the log messages you want to show. + +```bash +$ RUST_LOG=info ./main +[2018-11-03T06:09:06Z INFO default] starting up +``` + +The letter case is not significant for the logging level names; e.g., `debug`, +`DEBUG`, and `dEbuG` all represent the same logging level. Therefore, the +previous example could also have been written this way, specifying the log +level as `INFO` rather than as `info`: + +```bash +$ RUST_LOG=INFO ./main +[2018-11-03T06:09:06Z INFO default] starting up +``` + +So which form should you use? For consistency, our convention is to use lower +case names. Where our docs do use other forms, they do so in the context of +specific examples, so you won't be surprised if you see similar usage in the +wild. + +The log levels that may be specified correspond to the [`log::Level`][level-enum] +enum from the `log` crate. They are: + + * `error` + * `warn` + * `info` + * `debug` + * `trace` + +[level-enum]: https://docs.rs/log/latest/log/enum.Level.html "log::Level (docs.rs)" + +There is also a pseudo logging level, `off`, which may be specified to disable +all logging for a given module or for the entire application. As with the +logging levels, the letter case is not significant. + +`env_logger` can be configured in other ways besides an environment variable. See [the examples](https://github.com/env-logger-rs/env_logger/tree/master/examples) for more approaches. + +### In tests + +Tests can use the `env_logger` crate to see log messages generated during that test: + +```toml +[dependencies] +log = "0.4.0" + +[dev-dependencies] +env_logger = "0.8.4" +``` + +```rust +#[macro_use] +extern crate log; + +fn add_one(num: i32) -> i32 { + info!("add_one called with {}", num); + num + 1 +} + +#[cfg(test)] +mod tests { + use super::*; + + fn init() { + let _ = env_logger::builder().is_test(true).try_init(); + } + + #[test] + fn it_adds_one() { + init(); + + info!("can log from the test too"); + assert_eq!(3, add_one(2)); + } + + #[test] + fn it_handles_negative_numbers() { + init(); + + info!("logging from another test"); + assert_eq!(-7, add_one(-8)); + } +} +``` + +Assuming the module under test is called `my_lib`, running the tests with the +`RUST_LOG` filtering to info messages from this module looks like: + +```bash +$ RUST_LOG=my_lib=info cargo test + Running target/debug/my_lib-... + +running 2 tests +[INFO my_lib::tests] logging from another test +[INFO my_lib] add_one called with -8 +test tests::it_handles_negative_numbers ... ok +[INFO my_lib::tests] can log from the test too +[INFO my_lib] add_one called with 2 +test tests::it_adds_one ... ok + +test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured +``` + +Note that `env_logger::try_init()` needs to be called in each test in which you +want to enable logging. Additionally, the default behavior of tests to +run in parallel means that logging output may be interleaved with test output. +Either run tests in a single thread by specifying `RUST_TEST_THREADS=1` or by +running one test by specifying its name as an argument to the test binaries as +directed by the `cargo test` help docs: + +```bash +$ RUST_LOG=my_lib=info cargo test it_adds_one + Running target/debug/my_lib-... + +running 1 test +[INFO my_lib::tests] can log from the test too +[INFO my_lib] add_one called with 2 +test tests::it_adds_one ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured +``` + +## Configuring log target + +By default, `env_logger` logs to stderr. If you want to log to stdout instead, +you can use the `Builder` to change the log target: + +```rust +use std::env; +use env_logger::{Builder, Target}; + +let mut builder = Builder::from_default_env(); +builder.target(Target::Stdout); + +builder.init(); +``` + +## Stability of the default format + +The default format won't optimise for long-term stability, and explicitly makes no guarantees about the stability of its output across major, minor or patch version bumps during `0.x`. + +If you want to capture or interpret the output of `env_logger` programmatically then you should use a custom format. diff --git a/vendor/env_logger-0.8.4/src/filter/mod.rs b/vendor/env_logger-0.8.4/src/filter/mod.rs new file mode 100644 index 0000000000..7ef3f3941b --- /dev/null +++ b/vendor/env_logger-0.8.4/src/filter/mod.rs @@ -0,0 +1,868 @@ +//! Filtering for log records. +//! +//! This module contains the log filtering used by `env_logger` to match records. +//! You can use the `Filter` type in your own logger implementation to use the same +//! filter parsing and matching as `env_logger`. For more details about the format +//! for directive strings see [Enabling Logging]. +//! +//! ## Using `env_logger` in your own logger +//! +//! You can use `env_logger`'s filtering functionality with your own logger. +//! Call [`Builder::parse`] to parse directives from a string when constructing +//! your logger. Call [`Filter::matches`] to check whether a record should be +//! logged based on the parsed filters when log records are received. +//! +//! ``` +//! extern crate log; +//! extern crate env_logger; +//! use env_logger::filter::Filter; +//! use log::{Log, Metadata, Record}; +//! +//! struct MyLogger { +//! filter: Filter +//! } +//! +//! impl MyLogger { +//! fn new() -> MyLogger { +//! use env_logger::filter::Builder; +//! let mut builder = Builder::new(); +//! +//! // Parse a directives string from an environment variable +//! if let Ok(ref filter) = std::env::var("MY_LOG_LEVEL") { +//! builder.parse(filter); +//! } +//! +//! MyLogger { +//! filter: builder.build() +//! } +//! } +//! } +//! +//! impl Log for MyLogger { +//! fn enabled(&self, metadata: &Metadata) -> bool { +//! self.filter.enabled(metadata) +//! } +//! +//! fn log(&self, record: &Record) { +//! // Check if the record is matched by the filter +//! if self.filter.matches(record) { +//! println!("{:?}", record); +//! } +//! } +//! +//! fn flush(&self) {} +//! } +//! ``` +//! +//! [Enabling Logging]: ../index.html#enabling-logging +//! [`Builder::parse`]: struct.Builder.html#method.parse +//! [`Filter::matches`]: struct.Filter.html#method.matches + +use log::{Level, LevelFilter, Metadata, Record}; +use std::collections::HashMap; +use std::env; +use std::fmt; +use std::mem; + +#[cfg(feature = "regex")] +#[path = "regex.rs"] +mod inner; + +#[cfg(not(feature = "regex"))] +#[path = "string.rs"] +mod inner; + +/// A log filter. +/// +/// This struct can be used to determine whether or not a log record +/// should be written to the output. +/// Use the [`Builder`] type to parse and construct a `Filter`. +/// +/// [`Builder`]: struct.Builder.html +pub struct Filter { + directives: Vec<Directive>, + filter: Option<inner::Filter>, +} + +/// A builder for a log filter. +/// +/// It can be used to parse a set of directives from a string before building +/// a [`Filter`] instance. +/// +/// ## Example +/// +/// ``` +/// # #[macro_use] extern crate log; +/// # use std::env; +/// use env_logger::filter::Builder; +/// +/// let mut builder = Builder::new(); +/// +/// // Parse a logging filter from an environment variable. +/// if let Ok(rust_log) = env::var("RUST_LOG") { +/// builder.parse(&rust_log); +/// } +/// +/// let filter = builder.build(); +/// ``` +/// +/// [`Filter`]: struct.Filter.html +pub struct Builder { + directives: HashMap<Option<String>, LevelFilter>, + filter: Option<inner::Filter>, + built: bool, +} + +#[derive(Debug)] +struct Directive { + name: Option<String>, + level: LevelFilter, +} + +impl Filter { + /// Returns the maximum `LevelFilter` that this filter instance is + /// configured to output. + /// + /// # Example + /// + /// ```rust + /// use log::LevelFilter; + /// use env_logger::filter::Builder; + /// + /// let mut builder = Builder::new(); + /// builder.filter(Some("module1"), LevelFilter::Info); + /// builder.filter(Some("module2"), LevelFilter::Error); + /// + /// let filter = builder.build(); + /// assert_eq!(filter.filter(), LevelFilter::Info); + /// ``` + pub fn filter(&self) -> LevelFilter { + self.directives + .iter() + .map(|d| d.level) + .max() + .unwrap_or(LevelFilter::Off) + } + + /// Checks if this record matches the configured filter. + pub fn matches(&self, record: &Record) -> bool { + if !self.enabled(record.metadata()) { + return false; + } + + if let Some(filter) = self.filter.as_ref() { + if !filter.is_match(&*record.args().to_string()) { + return false; + } + } + + true + } + + /// Determines if a log message with the specified metadata would be logged. + pub fn enabled(&self, metadata: &Metadata) -> bool { + let level = metadata.level(); + let target = metadata.target(); + + enabled(&self.directives, level, target) + } +} + +impl Builder { + /// Initializes the filter builder with defaults. + pub fn new() -> Builder { + Builder { + directives: HashMap::new(), + filter: None, + built: false, + } + } + + /// Initializes the filter builder from an environment. + pub fn from_env(env: &str) -> Builder { + let mut builder = Builder::new(); + + if let Ok(s) = env::var(env) { + builder.parse(&s); + } + + builder + } + + /// Adds a directive to the filter for a specific module. + pub fn filter_module(&mut self, module: &str, level: LevelFilter) -> &mut Self { + self.filter(Some(module), level) + } + + /// Adds a directive to the filter for all modules. + pub fn filter_level(&mut self, level: LevelFilter) -> &mut Self { + self.filter(None, level) + } + + /// Adds a directive to the filter. + /// + /// The given module (if any) will log at most the specified level provided. + /// If no module is provided then the filter will apply to all log messages. + pub fn filter(&mut self, module: Option<&str>, level: LevelFilter) -> &mut Self { + self.directives.insert(module.map(|s| s.to_string()), level); + self + } + + /// Parses the directives string. + /// + /// See the [Enabling Logging] section for more details. + /// + /// [Enabling Logging]: ../index.html#enabling-logging + pub fn parse(&mut self, filters: &str) -> &mut Self { + let (directives, filter) = parse_spec(filters); + + self.filter = filter; + + for directive in directives { + self.directives.insert(directive.name, directive.level); + } + self + } + + /// Build a log filter. + pub fn build(&mut self) -> Filter { + assert!(!self.built, "attempt to re-use consumed builder"); + self.built = true; + + let mut directives = Vec::new(); + if self.directives.is_empty() { + // Adds the default filter if none exist + directives.push(Directive { + name: None, + level: LevelFilter::Error, + }); + } else { + // Consume map of directives. + let directives_map = mem::replace(&mut self.directives, HashMap::new()); + directives = directives_map + .into_iter() + .map(|(name, level)| Directive { name, level }) + .collect(); + // Sort the directives by length of their name, this allows a + // little more efficient lookup at runtime. + directives.sort_by(|a, b| { + let alen = a.name.as_ref().map(|a| a.len()).unwrap_or(0); + let blen = b.name.as_ref().map(|b| b.len()).unwrap_or(0); + alen.cmp(&blen) + }); + } + + Filter { + directives: mem::replace(&mut directives, Vec::new()), + filter: mem::replace(&mut self.filter, None), + } + } +} + +impl Default for Builder { + fn default() -> Self { + Builder::new() + } +} + +impl fmt::Debug for Filter { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Filter") + .field("filter", &self.filter) + .field("directives", &self.directives) + .finish() + } +} + +impl fmt::Debug for Builder { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if self.built { + f.debug_struct("Filter").field("built", &true).finish() + } else { + f.debug_struct("Filter") + .field("filter", &self.filter) + .field("directives", &self.directives) + .finish() + } + } +} + +/// Parse a logging specification string (e.g: "crate1,crate2::mod3,crate3::x=error/foo") +/// and return a vector with log directives. +fn parse_spec(spec: &str) -> (Vec<Directive>, Option<inner::Filter>) { + let mut dirs = Vec::new(); + + let mut parts = spec.split('/'); + let mods = parts.next(); + let filter = parts.next(); + if parts.next().is_some() { + eprintln!( + "warning: invalid logging spec '{}', \ + ignoring it (too many '/'s)", + spec + ); + return (dirs, None); + } + if let Some(m) = mods { + for s in m.split(',').map(|ss| ss.trim()) { + if s.is_empty() { + continue; + } + let mut parts = s.split('='); + let (log_level, name) = + match (parts.next(), parts.next().map(|s| s.trim()), parts.next()) { + (Some(part0), None, None) => { + // if the single argument is a log-level string or number, + // treat that as a global fallback + match part0.parse() { + Ok(num) => (num, None), + Err(_) => (LevelFilter::max(), Some(part0)), + } + } + (Some(part0), Some(""), None) => (LevelFilter::max(), Some(part0)), + (Some(part0), Some(part1), None) => match part1.parse() { + Ok(num) => (num, Some(part0)), + _ => { + eprintln!( + "warning: invalid logging spec '{}', \ + ignoring it", + part1 + ); + continue; + } + }, + _ => { + eprintln!( + "warning: invalid logging spec '{}', \ + ignoring it", + s + ); + continue; + } + }; + dirs.push(Directive { + name: name.map(|s| s.to_string()), + level: log_level, + }); + } + } + + let filter = filter.and_then(|filter| match inner::Filter::new(filter) { + Ok(re) => Some(re), + Err(e) => { + eprintln!("warning: invalid regex filter - {}", e); + None + } + }); + + (dirs, filter) +} + +// Check whether a level and target are enabled by the set of directives. +fn enabled(directives: &[Directive], level: Level, target: &str) -> bool { + // Search for the longest match, the vector is assumed to be pre-sorted. + for directive in directives.iter().rev() { + match directive.name { + Some(ref name) if !target.starts_with(&**name) => {} + Some(..) | None => return level <= directive.level, + } + } + false +} + +#[cfg(test)] +mod tests { + use log::{Level, LevelFilter}; + + use super::{enabled, parse_spec, Builder, Directive, Filter}; + + fn make_logger_filter(dirs: Vec<Directive>) -> Filter { + let mut logger = Builder::new().build(); + logger.directives = dirs; + logger + } + + #[test] + fn filter_info() { + let logger = Builder::new().filter(None, LevelFilter::Info).build(); + assert!(enabled(&logger.directives, Level::Info, "crate1")); + assert!(!enabled(&logger.directives, Level::Debug, "crate1")); + } + + #[test] + fn filter_beginning_longest_match() { + let logger = Builder::new() + .filter(Some("crate2"), LevelFilter::Info) + .filter(Some("crate2::mod"), LevelFilter::Debug) + .filter(Some("crate1::mod1"), LevelFilter::Warn) + .build(); + assert!(enabled(&logger.directives, Level::Debug, "crate2::mod1")); + assert!(!enabled(&logger.directives, Level::Debug, "crate2")); + } + + // Some of our tests are only correct or complete when they cover the full + // universe of variants for log::Level. In the unlikely event that a new + // variant is added in the future, this test will detect the scenario and + // alert us to the need to review and update the tests. In such a + // situation, this test will fail to compile, and the error message will + // look something like this: + // + // error[E0004]: non-exhaustive patterns: `NewVariant` not covered + // --> src/filter/mod.rs:413:15 + // | + // 413 | match level_universe { + // | ^^^^^^^^^^^^^^ pattern `NewVariant` not covered + #[test] + fn ensure_tests_cover_level_universe() { + let level_universe: Level = Level::Trace; // use of trace variant is arbitrary + match level_universe { + Level::Error | Level::Warn | Level::Info | Level::Debug | Level::Trace => (), + } + } + + #[test] + fn parse_default() { + let logger = Builder::new().parse("info,crate1::mod1=warn").build(); + assert!(enabled(&logger.directives, Level::Warn, "crate1::mod1")); + assert!(enabled(&logger.directives, Level::Info, "crate2::mod2")); + } + + #[test] + fn parse_default_bare_level_off_lc() { + let logger = Builder::new().parse("off").build(); + assert!(!enabled(&logger.directives, Level::Error, "")); + assert!(!enabled(&logger.directives, Level::Warn, "")); + assert!(!enabled(&logger.directives, Level::Info, "")); + assert!(!enabled(&logger.directives, Level::Debug, "")); + assert!(!enabled(&logger.directives, Level::Trace, "")); + } + + #[test] + fn parse_default_bare_level_off_uc() { + let logger = Builder::new().parse("OFF").build(); + assert!(!enabled(&logger.directives, Level::Error, "")); + assert!(!enabled(&logger.directives, Level::Warn, "")); + assert!(!enabled(&logger.directives, Level::Info, "")); + assert!(!enabled(&logger.directives, Level::Debug, "")); + assert!(!enabled(&logger.directives, Level::Trace, "")); + } + + #[test] + fn parse_default_bare_level_error_lc() { + let logger = Builder::new().parse("error").build(); + assert!(enabled(&logger.directives, Level::Error, "")); + assert!(!enabled(&logger.directives, Level::Warn, "")); + assert!(!enabled(&logger.directives, Level::Info, "")); + assert!(!enabled(&logger.directives, Level::Debug, "")); + assert!(!enabled(&logger.directives, Level::Trace, "")); + } + + #[test] + fn parse_default_bare_level_error_uc() { + let logger = Builder::new().parse("ERROR").build(); + assert!(enabled(&logger.directives, Level::Error, "")); + assert!(!enabled(&logger.directives, Level::Warn, "")); + assert!(!enabled(&logger.directives, Level::Info, "")); + assert!(!enabled(&logger.directives, Level::Debug, "")); + assert!(!enabled(&logger.directives, Level::Trace, "")); + } + + #[test] + fn parse_default_bare_level_warn_lc() { + let logger = Builder::new().parse("warn").build(); + assert!(enabled(&logger.directives, Level::Error, "")); + assert!(enabled(&logger.directives, Level::Warn, "")); + assert!(!enabled(&logger.directives, Level::Info, "")); + assert!(!enabled(&logger.directives, Level::Debug, "")); + assert!(!enabled(&logger.directives, Level::Trace, "")); + } + + #[test] + fn parse_default_bare_level_warn_uc() { + let logger = Builder::new().parse("WARN").build(); + assert!(enabled(&logger.directives, Level::Error, "")); + assert!(enabled(&logger.directives, Level::Warn, "")); + assert!(!enabled(&logger.directives, Level::Info, "")); + assert!(!enabled(&logger.directives, Level::Debug, "")); + assert!(!enabled(&logger.directives, Level::Trace, "")); + } + + #[test] + fn parse_default_bare_level_info_lc() { + let logger = Builder::new().parse("info").build(); + assert!(enabled(&logger.directives, Level::Error, "")); + assert!(enabled(&logger.directives, Level::Warn, "")); + assert!(enabled(&logger.directives, Level::Info, "")); + assert!(!enabled(&logger.directives, Level::Debug, "")); + assert!(!enabled(&logger.directives, Level::Trace, "")); + } + + #[test] + fn parse_default_bare_level_info_uc() { + let logger = Builder::new().parse("INFO").build(); + assert!(enabled(&logger.directives, Level::Error, "")); + assert!(enabled(&logger.directives, Level::Warn, "")); + assert!(enabled(&logger.directives, Level::Info, "")); + assert!(!enabled(&logger.directives, Level::Debug, "")); + assert!(!enabled(&logger.directives, Level::Trace, "")); + } + + #[test] + fn parse_default_bare_level_debug_lc() { + let logger = Builder::new().parse("debug").build(); + assert!(enabled(&logger.directives, Level::Error, "")); + assert!(enabled(&logger.directives, Level::Warn, "")); + assert!(enabled(&logger.directives, Level::Info, "")); + assert!(enabled(&logger.directives, Level::Debug, "")); + assert!(!enabled(&logger.directives, Level::Trace, "")); + } + + #[test] + fn parse_default_bare_level_debug_uc() { + let logger = Builder::new().parse("DEBUG").build(); + assert!(enabled(&logger.directives, Level::Error, "")); + assert!(enabled(&logger.directives, Level::Warn, "")); + assert!(enabled(&logger.directives, Level::Info, "")); + assert!(enabled(&logger.directives, Level::Debug, "")); + assert!(!enabled(&logger.directives, Level::Trace, "")); + } + + #[test] + fn parse_default_bare_level_trace_lc() { + let logger = Builder::new().parse("trace").build(); + assert!(enabled(&logger.directives, Level::Error, "")); + assert!(enabled(&logger.directives, Level::Warn, "")); + assert!(enabled(&logger.directives, Level::Info, "")); + assert!(enabled(&logger.directives, Level::Debug, "")); + assert!(enabled(&logger.directives, Level::Trace, "")); + } + + #[test] + fn parse_default_bare_level_trace_uc() { + let logger = Builder::new().parse("TRACE").build(); + assert!(enabled(&logger.directives, Level::Error, "")); + assert!(enabled(&logger.directives, Level::Warn, "")); + assert!(enabled(&logger.directives, Level::Info, "")); + assert!(enabled(&logger.directives, Level::Debug, "")); + assert!(enabled(&logger.directives, Level::Trace, "")); + } + + // In practice, the desired log level is typically specified by a token + // that is either all lowercase (e.g., 'trace') or all uppercase (.e.g, + // 'TRACE'), but this tests serves as a reminder that + // log::Level::from_str() ignores all case variants. + #[test] + fn parse_default_bare_level_debug_mixed() { + { + let logger = Builder::new().parse("Debug").build(); + assert!(enabled(&logger.directives, Level::Error, "")); + assert!(enabled(&logger.directives, Level::Warn, "")); + assert!(enabled(&logger.directives, Level::Info, "")); + assert!(enabled(&logger.directives, Level::Debug, "")); + assert!(!enabled(&logger.directives, Level::Trace, "")); + } + { + let logger = Builder::new().parse("debuG").build(); + assert!(enabled(&logger.directives, Level::Error, "")); + assert!(enabled(&logger.directives, Level::Warn, "")); + assert!(enabled(&logger.directives, Level::Info, "")); + assert!(enabled(&logger.directives, Level::Debug, "")); + assert!(!enabled(&logger.directives, Level::Trace, "")); + } + { + let logger = Builder::new().parse("deBug").build(); + assert!(enabled(&logger.directives, Level::Error, "")); + assert!(enabled(&logger.directives, Level::Warn, "")); + assert!(enabled(&logger.directives, Level::Info, "")); + assert!(enabled(&logger.directives, Level::Debug, "")); + assert!(!enabled(&logger.directives, Level::Trace, "")); + } + { + let logger = Builder::new().parse("DeBuG").build(); // LaTeX flavor! + assert!(enabled(&logger.directives, Level::Error, "")); + assert!(enabled(&logger.directives, Level::Warn, "")); + assert!(enabled(&logger.directives, Level::Info, "")); + assert!(enabled(&logger.directives, Level::Debug, "")); + assert!(!enabled(&logger.directives, Level::Trace, "")); + } + } + + #[test] + fn match_full_path() { + let logger = make_logger_filter(vec![ + Directive { + name: Some("crate2".to_string()), + level: LevelFilter::Info, + }, + Directive { + name: Some("crate1::mod1".to_string()), + level: LevelFilter::Warn, + }, + ]); + assert!(enabled(&logger.directives, Level::Warn, "crate1::mod1")); + assert!(!enabled(&logger.directives, Level::Info, "crate1::mod1")); + assert!(enabled(&logger.directives, Level::Info, "crate2")); + assert!(!enabled(&logger.directives, Level::Debug, "crate2")); + } + + #[test] + fn no_match() { + let logger = make_logger_filter(vec![ + Directive { + name: Some("crate2".to_string()), + level: LevelFilter::Info, + }, + Directive { + name: Some("crate1::mod1".to_string()), + level: LevelFilter::Warn, + }, + ]); + assert!(!enabled(&logger.directives, Level::Warn, "crate3")); + } + + #[test] + fn match_beginning() { + let logger = make_logger_filter(vec![ + Directive { + name: Some("crate2".to_string()), + level: LevelFilter::Info, + }, + Directive { + name: Some("crate1::mod1".to_string()), + level: LevelFilter::Warn, + }, + ]); + assert!(enabled(&logger.directives, Level::Info, "crate2::mod1")); + } + + #[test] + fn match_beginning_longest_match() { + let logger = make_logger_filter(vec![ + Directive { + name: Some("crate2".to_string()), + level: LevelFilter::Info, + }, + Directive { + name: Some("crate2::mod".to_string()), + level: LevelFilter::Debug, + }, + Directive { + name: Some("crate1::mod1".to_string()), + level: LevelFilter::Warn, + }, + ]); + assert!(enabled(&logger.directives, Level::Debug, "crate2::mod1")); + assert!(!enabled(&logger.directives, Level::Debug, "crate2")); + } + + #[test] + fn match_default() { + let logger = make_logger_filter(vec![ + Directive { + name: None, + level: LevelFilter::Info, + }, + Directive { + name: Some("crate1::mod1".to_string()), + level: LevelFilter::Warn, + }, + ]); + assert!(enabled(&logger.directives, Level::Warn, "crate1::mod1")); + assert!(enabled(&logger.directives, Level::Info, "crate2::mod2")); + } + + #[test] + fn zero_level() { + let logger = make_logger_filter(vec![ + Directive { + name: None, + level: LevelFilter::Info, + }, + Directive { + name: Some("crate1::mod1".to_string()), + level: LevelFilter::Off, + }, + ]); + assert!(!enabled(&logger.directives, Level::Error, "crate1::mod1")); + assert!(enabled(&logger.directives, Level::Info, "crate2::mod2")); + } + + #[test] + fn parse_spec_valid() { + let (dirs, filter) = parse_spec("crate1::mod1=error,crate1::mod2,crate2=debug"); + assert_eq!(dirs.len(), 3); + assert_eq!(dirs[0].name, Some("crate1::mod1".to_string())); + assert_eq!(dirs[0].level, LevelFilter::Error); + + assert_eq!(dirs[1].name, Some("crate1::mod2".to_string())); + assert_eq!(dirs[1].level, LevelFilter::max()); + + assert_eq!(dirs[2].name, Some("crate2".to_string())); + assert_eq!(dirs[2].level, LevelFilter::Debug); + assert!(filter.is_none()); + } + + #[test] + fn parse_spec_invalid_crate() { + // test parse_spec with multiple = in specification + let (dirs, filter) = parse_spec("crate1::mod1=warn=info,crate2=debug"); + assert_eq!(dirs.len(), 1); + assert_eq!(dirs[0].name, Some("crate2".to_string())); + assert_eq!(dirs[0].level, LevelFilter::Debug); + assert!(filter.is_none()); + } + + #[test] + fn parse_spec_invalid_level() { + // test parse_spec with 'noNumber' as log level + let (dirs, filter) = parse_spec("crate1::mod1=noNumber,crate2=debug"); + assert_eq!(dirs.len(), 1); + assert_eq!(dirs[0].name, Some("crate2".to_string())); + assert_eq!(dirs[0].level, LevelFilter::Debug); + assert!(filter.is_none()); + } + + #[test] + fn parse_spec_string_level() { + // test parse_spec with 'warn' as log level + let (dirs, filter) = parse_spec("crate1::mod1=wrong,crate2=warn"); + assert_eq!(dirs.len(), 1); + assert_eq!(dirs[0].name, Some("crate2".to_string())); + assert_eq!(dirs[0].level, LevelFilter::Warn); + assert!(filter.is_none()); + } + + #[test] + fn parse_spec_empty_level() { + // test parse_spec with '' as log level + let (dirs, filter) = parse_spec("crate1::mod1=wrong,crate2="); + assert_eq!(dirs.len(), 1); + assert_eq!(dirs[0].name, Some("crate2".to_string())); + assert_eq!(dirs[0].level, LevelFilter::max()); + assert!(filter.is_none()); + } + + #[test] + fn parse_spec_empty_level_isolated() { + // test parse_spec with "" as log level (and the entire spec str) + let (dirs, filter) = parse_spec(""); // should be ignored + assert_eq!(dirs.len(), 0); + assert!(filter.is_none()); + } + + #[test] + fn parse_spec_blank_level_isolated() { + // test parse_spec with a white-space-only string specified as the log + // level (and the entire spec str) + let (dirs, filter) = parse_spec(" "); // should be ignored + assert_eq!(dirs.len(), 0); + assert!(filter.is_none()); + } + + #[test] + fn parse_spec_blank_level_isolated_comma_only() { + // The spec should contain zero or more comma-separated string slices, + // so a comma-only string should be interpretted as two empty strings + // (which should both be treated as invalid, so ignored). + let (dirs, filter) = parse_spec(","); // should be ignored + assert_eq!(dirs.len(), 0); + assert!(filter.is_none()); + } + + #[test] + fn parse_spec_blank_level_isolated_comma_blank() { + // The spec should contain zero or more comma-separated string slices, + // so this bogus spec should be interpretted as containing one empty + // string and one blank string. Both should both be treated as + // invalid, so ignored. + let (dirs, filter) = parse_spec(", "); // should be ignored + assert_eq!(dirs.len(), 0); + assert!(filter.is_none()); + } + + #[test] + fn parse_spec_blank_level_isolated_blank_comma() { + // The spec should contain zero or more comma-separated string slices, + // so this bogus spec should be interpretted as containing one blank + // string and one empty string. Both should both be treated as + // invalid, so ignored. + let (dirs, filter) = parse_spec(" ,"); // should be ignored + assert_eq!(dirs.len(), 0); + assert!(filter.is_none()); + } + + #[test] + fn parse_spec_global() { + // test parse_spec with no crate + let (dirs, filter) = parse_spec("warn,crate2=debug"); + assert_eq!(dirs.len(), 2); + assert_eq!(dirs[0].name, None); + assert_eq!(dirs[0].level, LevelFilter::Warn); + assert_eq!(dirs[1].name, Some("crate2".to_string())); + assert_eq!(dirs[1].level, LevelFilter::Debug); + assert!(filter.is_none()); + } + + #[test] + fn parse_spec_global_bare_warn_lc() { + // test parse_spec with no crate, in isolation, all lowercase + let (dirs, filter) = parse_spec("warn"); + assert_eq!(dirs.len(), 1); + assert_eq!(dirs[0].name, None); + assert_eq!(dirs[0].level, LevelFilter::Warn); + assert!(filter.is_none()); + } + + #[test] + fn parse_spec_global_bare_warn_uc() { + // test parse_spec with no crate, in isolation, all uppercase + let (dirs, filter) = parse_spec("WARN"); + assert_eq!(dirs.len(), 1); + assert_eq!(dirs[0].name, None); + assert_eq!(dirs[0].level, LevelFilter::Warn); + assert!(filter.is_none()); + } + + #[test] + fn parse_spec_global_bare_warn_mixed() { + // test parse_spec with no crate, in isolation, mixed case + let (dirs, filter) = parse_spec("wArN"); + assert_eq!(dirs.len(), 1); + assert_eq!(dirs[0].name, None); + assert_eq!(dirs[0].level, LevelFilter::Warn); + assert!(filter.is_none()); + } + + #[test] + fn parse_spec_valid_filter() { + let (dirs, filter) = parse_spec("crate1::mod1=error,crate1::mod2,crate2=debug/abc"); + assert_eq!(dirs.len(), 3); + assert_eq!(dirs[0].name, Some("crate1::mod1".to_string())); + assert_eq!(dirs[0].level, LevelFilter::Error); + + assert_eq!(dirs[1].name, Some("crate1::mod2".to_string())); + assert_eq!(dirs[1].level, LevelFilter::max()); + + assert_eq!(dirs[2].name, Some("crate2".to_string())); + assert_eq!(dirs[2].level, LevelFilter::Debug); + assert!(filter.is_some() && filter.unwrap().to_string() == "abc"); + } + + #[test] + fn parse_spec_invalid_crate_filter() { + let (dirs, filter) = parse_spec("crate1::mod1=error=warn,crate2=debug/a.c"); + assert_eq!(dirs.len(), 1); + assert_eq!(dirs[0].name, Some("crate2".to_string())); + assert_eq!(dirs[0].level, LevelFilter::Debug); + assert!(filter.is_some() && filter.unwrap().to_string() == "a.c"); + } + + #[test] + fn parse_spec_empty_with_filter() { + let (dirs, filter) = parse_spec("crate1/a*c"); + assert_eq!(dirs.len(), 1); + assert_eq!(dirs[0].name, Some("crate1".to_string())); + assert_eq!(dirs[0].level, LevelFilter::max()); + assert!(filter.is_some() && filter.unwrap().to_string() == "a*c"); + } +} diff --git a/vendor/env_logger-0.8.4/src/filter/regex.rs b/vendor/env_logger-0.8.4/src/filter/regex.rs new file mode 100644 index 0000000000..fb21528a12 --- /dev/null +++ b/vendor/env_logger-0.8.4/src/filter/regex.rs @@ -0,0 +1,29 @@ +extern crate regex; + +use std::fmt; + +use self::regex::Regex; + +#[derive(Debug)] +pub struct Filter { + inner: Regex, +} + +impl Filter { + pub fn new(spec: &str) -> Result<Filter, String> { + match Regex::new(spec) { + Ok(r) => Ok(Filter { inner: r }), + Err(e) => Err(e.to_string()), + } + } + + pub fn is_match(&self, s: &str) -> bool { + self.inner.is_match(s) + } +} + +impl fmt::Display for Filter { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.inner.fmt(f) + } +} diff --git a/vendor/env_logger-0.8.4/src/filter/string.rs b/vendor/env_logger-0.8.4/src/filter/string.rs new file mode 100644 index 0000000000..ea476e42f9 --- /dev/null +++ b/vendor/env_logger-0.8.4/src/filter/string.rs @@ -0,0 +1,24 @@ +use std::fmt; + +#[derive(Debug)] +pub struct Filter { + inner: String, +} + +impl Filter { + pub fn new(spec: &str) -> Result<Filter, String> { + Ok(Filter { + inner: spec.to_string(), + }) + } + + pub fn is_match(&self, s: &str) -> bool { + s.contains(&self.inner) + } +} + +impl fmt::Display for Filter { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.inner.fmt(f) + } +} diff --git a/vendor/env_logger-0.8.4/src/fmt/humantime/extern_impl.rs b/vendor/env_logger-0.8.4/src/fmt/humantime/extern_impl.rs new file mode 100644 index 0000000000..19dec1b65d --- /dev/null +++ b/vendor/env_logger-0.8.4/src/fmt/humantime/extern_impl.rs @@ -0,0 +1,118 @@ +use std::fmt; +use std::time::SystemTime; + +use humantime::{ + format_rfc3339_micros, format_rfc3339_millis, format_rfc3339_nanos, format_rfc3339_seconds, +}; + +use crate::fmt::{Formatter, TimestampPrecision}; + +pub(in crate::fmt) mod glob { + pub use super::*; +} + +impl Formatter { + /// Get a [`Timestamp`] for the current date and time in UTC. + /// + /// # Examples + /// + /// Include the current timestamp with the log record: + /// + /// ``` + /// use std::io::Write; + /// + /// let mut builder = env_logger::Builder::new(); + /// + /// builder.format(|buf, record| { + /// let ts = buf.timestamp(); + /// + /// writeln!(buf, "{}: {}: {}", ts, record.level(), record.args()) + /// }); + /// ``` + /// + /// [`Timestamp`]: struct.Timestamp.html + pub fn timestamp(&self) -> Timestamp { + Timestamp { + time: SystemTime::now(), + precision: TimestampPrecision::Seconds, + } + } + + /// Get a [`Timestamp`] for the current date and time in UTC with full + /// second precision. + pub fn timestamp_seconds(&self) -> Timestamp { + Timestamp { + time: SystemTime::now(), + precision: TimestampPrecision::Seconds, + } + } + + /// Get a [`Timestamp`] for the current date and time in UTC with + /// millisecond precision. + pub fn timestamp_millis(&self) -> Timestamp { + Timestamp { + time: SystemTime::now(), + precision: TimestampPrecision::Millis, + } + } + + /// Get a [`Timestamp`] for the current date and time in UTC with + /// microsecond precision. + pub fn timestamp_micros(&self) -> Timestamp { + Timestamp { + time: SystemTime::now(), + precision: TimestampPrecision::Micros, + } + } + + /// Get a [`Timestamp`] for the current date and time in UTC with + /// nanosecond precision. + pub fn timestamp_nanos(&self) -> Timestamp { + Timestamp { + time: SystemTime::now(), + precision: TimestampPrecision::Nanos, + } + } +} + +/// An [RFC3339] formatted timestamp. +/// +/// The timestamp implements [`Display`] and can be written to a [`Formatter`]. +/// +/// [RFC3339]: https://www.ietf.org/rfc/rfc3339.txt +/// [`Display`]: https://doc.rust-lang.org/stable/std/fmt/trait.Display.html +/// [`Formatter`]: struct.Formatter.html +pub struct Timestamp { + time: SystemTime, + precision: TimestampPrecision, +} + +impl fmt::Debug for Timestamp { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + /// A `Debug` wrapper for `Timestamp` that uses the `Display` implementation. + struct TimestampValue<'a>(&'a Timestamp); + + impl<'a> fmt::Debug for TimestampValue<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.0, f) + } + } + + f.debug_tuple("Timestamp") + .field(&TimestampValue(&self)) + .finish() + } +} + +impl fmt::Display for Timestamp { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let formatter = match self.precision { + TimestampPrecision::Seconds => format_rfc3339_seconds, + TimestampPrecision::Millis => format_rfc3339_millis, + TimestampPrecision::Micros => format_rfc3339_micros, + TimestampPrecision::Nanos => format_rfc3339_nanos, + }; + + formatter(self.time).fmt(f) + } +} diff --git a/vendor/env_logger-0.8.4/src/fmt/humantime/mod.rs b/vendor/env_logger-0.8.4/src/fmt/humantime/mod.rs new file mode 100644 index 0000000000..ac23ae2493 --- /dev/null +++ b/vendor/env_logger-0.8.4/src/fmt/humantime/mod.rs @@ -0,0 +1,11 @@ +/* +This internal module contains the timestamp implementation. + +Its public API is available when the `humantime` crate is available. +*/ + +#[cfg_attr(feature = "humantime", path = "extern_impl.rs")] +#[cfg_attr(not(feature = "humantime"), path = "shim_impl.rs")] +mod imp; + +pub(in crate::fmt) use self::imp::*; diff --git a/vendor/env_logger-0.8.4/src/fmt/humantime/shim_impl.rs b/vendor/env_logger-0.8.4/src/fmt/humantime/shim_impl.rs new file mode 100644 index 0000000000..906bf9e4c1 --- /dev/null +++ b/vendor/env_logger-0.8.4/src/fmt/humantime/shim_impl.rs @@ -0,0 +1,5 @@ +/* +Timestamps aren't available when we don't have a `humantime` dependency. +*/ + +pub(in crate::fmt) mod glob {} diff --git a/vendor/env_logger-0.8.4/src/fmt/mod.rs b/vendor/env_logger-0.8.4/src/fmt/mod.rs new file mode 100644 index 0000000000..3c4fee0add --- /dev/null +++ b/vendor/env_logger-0.8.4/src/fmt/mod.rs @@ -0,0 +1,547 @@ +//! Formatting for log records. +//! +//! This module contains a [`Formatter`] that can be used to format log records +//! into without needing temporary allocations. Usually you won't need to worry +//! about the contents of this module and can use the `Formatter` like an ordinary +//! [`Write`]. +//! +//! # Formatting log records +//! +//! The format used to print log records can be customised using the [`Builder::format`] +//! method. +//! Custom formats can apply different color and weight to printed values using +//! [`Style`] builders. +//! +//! ``` +//! use std::io::Write; +//! +//! let mut builder = env_logger::Builder::new(); +//! +//! builder.format(|buf, record| { +//! writeln!(buf, "{}: {}", +//! record.level(), +//! record.args()) +//! }); +//! ``` +//! +//! [`Formatter`]: struct.Formatter.html +//! [`Style`]: struct.Style.html +//! [`Builder::format`]: ../struct.Builder.html#method.format +//! [`Write`]: https://doc.rust-lang.org/stable/std/io/trait.Write.html + +use std::cell::RefCell; +use std::fmt::Display; +use std::io::prelude::*; +use std::rc::Rc; +use std::{fmt, io, mem}; + +use log::Record; + +mod humantime; +pub(crate) mod writer; + +pub use self::humantime::glob::*; +pub use self::writer::glob::*; + +use self::writer::{Buffer, Writer}; + +pub(crate) mod glob { + pub use super::{Target, TimestampPrecision, WriteStyle}; +} + +/// Formatting precision of timestamps. +/// +/// Seconds give precision of full seconds, milliseconds give thousands of a +/// second (3 decimal digits), microseconds are millionth of a second (6 decimal +/// digits) and nanoseconds are billionth of a second (9 decimal digits). +#[derive(Copy, Clone, Debug)] +pub enum TimestampPrecision { + /// Full second precision (0 decimal digits) + Seconds, + /// Millisecond precision (3 decimal digits) + Millis, + /// Microsecond precision (6 decimal digits) + Micros, + /// Nanosecond precision (9 decimal digits) + Nanos, +} + +/// The default timestamp precision is seconds. +impl Default for TimestampPrecision { + fn default() -> Self { + TimestampPrecision::Seconds + } +} + +/// A formatter to write logs into. +/// +/// `Formatter` implements the standard [`Write`] trait for writing log records. +/// It also supports terminal colors, through the [`style`] method. +/// +/// # Examples +/// +/// Use the [`writeln`] macro to format a log record. +/// An instance of a `Formatter` is passed to an `env_logger` format as `buf`: +/// +/// ``` +/// use std::io::Write; +/// +/// let mut builder = env_logger::Builder::new(); +/// +/// builder.format(|buf, record| writeln!(buf, "{}: {}", record.level(), record.args())); +/// ``` +/// +/// [`Write`]: https://doc.rust-lang.org/stable/std/io/trait.Write.html +/// [`writeln`]: https://doc.rust-lang.org/stable/std/macro.writeln.html +/// [`style`]: #method.style +pub struct Formatter { + buf: Rc<RefCell<Buffer>>, + write_style: WriteStyle, +} + +impl Formatter { + pub(crate) fn new(writer: &Writer) -> Self { + Formatter { + buf: Rc::new(RefCell::new(writer.buffer())), + write_style: writer.write_style(), + } + } + + pub(crate) fn write_style(&self) -> WriteStyle { + self.write_style + } + + pub(crate) fn print(&self, writer: &Writer) -> io::Result<()> { + writer.print(&self.buf.borrow()) + } + + pub(crate) fn clear(&mut self) { + self.buf.borrow_mut().clear() + } +} + +impl Write for Formatter { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.buf.borrow_mut().write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + self.buf.borrow_mut().flush() + } +} + +impl fmt::Debug for Formatter { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Formatter").finish() + } +} + +pub(crate) type FormatFn = Box<dyn Fn(&mut Formatter, &Record) -> io::Result<()> + Sync + Send>; + +pub(crate) struct Builder { + pub format_timestamp: Option<TimestampPrecision>, + pub format_module_path: bool, + pub format_level: bool, + pub format_indent: Option<usize>, + pub custom_format: Option<FormatFn>, + pub format_suffix: &'static str, + built: bool, +} + +impl Default for Builder { + fn default() -> Self { + Builder { + format_timestamp: Some(Default::default()), + format_module_path: true, + format_level: true, + format_indent: Some(4), + custom_format: None, + format_suffix: "\n", + built: false, + } + } +} + +impl Builder { + /// Convert the format into a callable function. + /// + /// If the `custom_format` is `Some`, then any `default_format` switches are ignored. + /// If the `custom_format` is `None`, then a default format is returned. + /// Any `default_format` switches set to `false` won't be written by the format. + pub fn build(&mut self) -> FormatFn { + assert!(!self.built, "attempt to re-use consumed builder"); + + let built = mem::replace( + self, + Builder { + built: true, + ..Default::default() + }, + ); + + if let Some(fmt) = built.custom_format { + fmt + } else { + Box::new(move |buf, record| { + let fmt = DefaultFormat { + timestamp: built.format_timestamp, + module_path: built.format_module_path, + level: built.format_level, + written_header_value: false, + indent: built.format_indent, + suffix: built.format_suffix, + buf, + }; + + fmt.write(record) + }) + } + } +} + +#[cfg(feature = "termcolor")] +type SubtleStyle = StyledValue<'static, &'static str>; +#[cfg(not(feature = "termcolor"))] +type SubtleStyle = &'static str; + +/// The default format. +/// +/// This format needs to work with any combination of crate features. +struct DefaultFormat<'a> { + timestamp: Option<TimestampPrecision>, + module_path: bool, + level: bool, + written_header_value: bool, + indent: Option<usize>, + buf: &'a mut Formatter, + suffix: &'a str, +} + +impl<'a> DefaultFormat<'a> { + fn write(mut self, record: &Record) -> io::Result<()> { + self.write_timestamp()?; + self.write_level(record)?; + self.write_module_path(record)?; + self.finish_header()?; + + self.write_args(record) + } + + fn subtle_style(&self, text: &'static str) -> SubtleStyle { + #[cfg(feature = "termcolor")] + { + self.buf + .style() + .set_color(Color::Black) + .set_intense(true) + .clone() + .into_value(text) + } + #[cfg(not(feature = "termcolor"))] + { + text + } + } + + fn write_header_value<T>(&mut self, value: T) -> io::Result<()> + where + T: Display, + { + if !self.written_header_value { + self.written_header_value = true; + + let open_brace = self.subtle_style("["); + write!(self.buf, "{}{}", open_brace, value) + } else { + write!(self.buf, " {}", value) + } + } + + fn write_level(&mut self, record: &Record) -> io::Result<()> { + if !self.level { + return Ok(()); + } + + let level = { + #[cfg(feature = "termcolor")] + { + self.buf.default_styled_level(record.level()) + } + #[cfg(not(feature = "termcolor"))] + { + record.level() + } + }; + + self.write_header_value(format_args!("{:<5}", level)) + } + + fn write_timestamp(&mut self) -> io::Result<()> { + #[cfg(feature = "humantime")] + { + use self::TimestampPrecision::*; + let ts = match self.timestamp { + None => return Ok(()), + Some(Seconds) => self.buf.timestamp_seconds(), + Some(Millis) => self.buf.timestamp_millis(), + Some(Micros) => self.buf.timestamp_micros(), + Some(Nanos) => self.buf.timestamp_nanos(), + }; + + self.write_header_value(ts) + } + #[cfg(not(feature = "humantime"))] + { + // Trick the compiler to think we have used self.timestamp + // Workaround for "field is never used: `timestamp`" compiler nag. + let _ = self.timestamp; + Ok(()) + } + } + + fn write_module_path(&mut self, record: &Record) -> io::Result<()> { + if !self.module_path { + return Ok(()); + } + + if let Some(module_path) = record.module_path() { + self.write_header_value(module_path) + } else { + Ok(()) + } + } + + fn finish_header(&mut self) -> io::Result<()> { + if self.written_header_value { + let close_brace = self.subtle_style("]"); + write!(self.buf, "{} ", close_brace) + } else { + Ok(()) + } + } + + fn write_args(&mut self, record: &Record) -> io::Result<()> { + match self.indent { + // Fast path for no indentation + None => write!(self.buf, "{}{}", record.args(), self.suffix), + + Some(indent_count) => { + // Create a wrapper around the buffer only if we have to actually indent the message + + struct IndentWrapper<'a, 'b: 'a> { + fmt: &'a mut DefaultFormat<'b>, + indent_count: usize, + } + + impl<'a, 'b> Write for IndentWrapper<'a, 'b> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + let mut first = true; + for chunk in buf.split(|&x| x == b'\n') { + if !first { + write!( + self.fmt.buf, + "{}{:width$}", + self.fmt.suffix, + "", + width = self.indent_count + )?; + } + self.fmt.buf.write_all(chunk)?; + first = false; + } + + Ok(buf.len()) + } + + fn flush(&mut self) -> io::Result<()> { + self.fmt.buf.flush() + } + } + + // The explicit scope here is just to make older versions of Rust happy + { + let mut wrapper = IndentWrapper { + fmt: self, + indent_count, + }; + write!(wrapper, "{}", record.args())?; + } + + write!(self.buf, "{}", self.suffix)?; + + Ok(()) + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use log::{Level, Record}; + + fn write(fmt: DefaultFormat) -> String { + let buf = fmt.buf.buf.clone(); + + let record = Record::builder() + .args(format_args!("log\nmessage")) + .level(Level::Info) + .file(Some("test.rs")) + .line(Some(144)) + .module_path(Some("test::path")) + .build(); + + fmt.write(&record).expect("failed to write record"); + + let buf = buf.borrow(); + String::from_utf8(buf.bytes().to_vec()).expect("failed to read record") + } + + #[test] + fn format_with_header() { + let writer = writer::Builder::new() + .write_style(WriteStyle::Never) + .build(); + + let mut f = Formatter::new(&writer); + + let written = write(DefaultFormat { + timestamp: None, + module_path: true, + level: true, + written_header_value: false, + indent: None, + suffix: "\n", + buf: &mut f, + }); + + assert_eq!("[INFO test::path] log\nmessage\n", written); + } + + #[test] + fn format_no_header() { + let writer = writer::Builder::new() + .write_style(WriteStyle::Never) + .build(); + + let mut f = Formatter::new(&writer); + + let written = write(DefaultFormat { + timestamp: None, + module_path: false, + level: false, + written_header_value: false, + indent: None, + suffix: "\n", + buf: &mut f, + }); + + assert_eq!("log\nmessage\n", written); + } + + #[test] + fn format_indent_spaces() { + let writer = writer::Builder::new() + .write_style(WriteStyle::Never) + .build(); + + let mut f = Formatter::new(&writer); + + let written = write(DefaultFormat { + timestamp: None, + module_path: true, + level: true, + written_header_value: false, + indent: Some(4), + suffix: "\n", + buf: &mut f, + }); + + assert_eq!("[INFO test::path] log\n message\n", written); + } + + #[test] + fn format_indent_zero_spaces() { + let writer = writer::Builder::new() + .write_style(WriteStyle::Never) + .build(); + + let mut f = Formatter::new(&writer); + + let written = write(DefaultFormat { + timestamp: None, + module_path: true, + level: true, + written_header_value: false, + indent: Some(0), + suffix: "\n", + buf: &mut f, + }); + + assert_eq!("[INFO test::path] log\nmessage\n", written); + } + + #[test] + fn format_indent_spaces_no_header() { + let writer = writer::Builder::new() + .write_style(WriteStyle::Never) + .build(); + + let mut f = Formatter::new(&writer); + + let written = write(DefaultFormat { + timestamp: None, + module_path: false, + level: false, + written_header_value: false, + indent: Some(4), + suffix: "\n", + buf: &mut f, + }); + + assert_eq!("log\n message\n", written); + } + + #[test] + fn format_suffix() { + let writer = writer::Builder::new() + .write_style(WriteStyle::Never) + .build(); + + let mut f = Formatter::new(&writer); + + let written = write(DefaultFormat { + timestamp: None, + module_path: false, + level: false, + written_header_value: false, + indent: None, + suffix: "\n\n", + buf: &mut f, + }); + + assert_eq!("log\nmessage\n\n", written); + } + + #[test] + fn format_suffix_with_indent() { + let writer = writer::Builder::new() + .write_style(WriteStyle::Never) + .build(); + + let mut f = Formatter::new(&writer); + + let written = write(DefaultFormat { + timestamp: None, + module_path: false, + level: false, + written_header_value: false, + indent: Some(4), + suffix: "\n\n", + buf: &mut f, + }); + + assert_eq!("log\n\n message\n\n", written); + } +} diff --git a/vendor/env_logger-0.8.4/src/fmt/writer/atty.rs b/vendor/env_logger-0.8.4/src/fmt/writer/atty.rs new file mode 100644 index 0000000000..343539c157 --- /dev/null +++ b/vendor/env_logger-0.8.4/src/fmt/writer/atty.rs @@ -0,0 +1,32 @@ +/* +This internal module contains the terminal detection implementation. + +If the `atty` crate is available then we use it to detect whether we're +attached to a particular TTY. If the `atty` crate is not available we +assume we're not attached to anything. This effectively prevents styles +from being printed. +*/ + +#[cfg(feature = "atty")] +mod imp { + pub(in crate::fmt) fn is_stdout() -> bool { + atty::is(atty::Stream::Stdout) + } + + pub(in crate::fmt) fn is_stderr() -> bool { + atty::is(atty::Stream::Stderr) + } +} + +#[cfg(not(feature = "atty"))] +mod imp { + pub(in crate::fmt) fn is_stdout() -> bool { + false + } + + pub(in crate::fmt) fn is_stderr() -> bool { + false + } +} + +pub(in crate::fmt) use self::imp::*; diff --git a/vendor/env_logger-0.8.4/src/fmt/writer/mod.rs b/vendor/env_logger-0.8.4/src/fmt/writer/mod.rs new file mode 100644 index 0000000000..5bb5353927 --- /dev/null +++ b/vendor/env_logger-0.8.4/src/fmt/writer/mod.rs @@ -0,0 +1,252 @@ +mod atty; +mod termcolor; + +use self::atty::{is_stderr, is_stdout}; +use self::termcolor::BufferWriter; +use std::{fmt, io, mem, sync::Mutex}; + +pub(super) mod glob { + pub use super::termcolor::glob::*; + pub use super::*; +} + +pub(super) use self::termcolor::Buffer; + +/// Log target, either `stdout`, `stderr` or a custom pipe. +#[non_exhaustive] +pub enum Target { + /// Logs will be sent to standard output. + Stdout, + /// Logs will be sent to standard error. + Stderr, + /// Logs will be sent to a custom pipe. + Pipe(Box<dyn io::Write + Send + 'static>), +} + +impl Default for Target { + fn default() -> Self { + Target::Stderr + } +} + +impl fmt::Debug for Target { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "{}", + match self { + Self::Stdout => "stdout", + Self::Stderr => "stderr", + Self::Pipe(_) => "pipe", + } + ) + } +} + +/// Log target, either `stdout`, `stderr` or a custom pipe. +/// +/// Same as `Target`, except the pipe is wrapped in a mutex for interior mutability. +pub(super) enum WritableTarget { + /// Logs will be sent to standard output. + Stdout, + /// Logs will be sent to standard error. + Stderr, + /// Logs will be sent to a custom pipe. + Pipe(Box<Mutex<dyn io::Write + Send + 'static>>), +} + +impl From<Target> for WritableTarget { + fn from(target: Target) -> Self { + match target { + Target::Stdout => Self::Stdout, + Target::Stderr => Self::Stderr, + Target::Pipe(pipe) => Self::Pipe(Box::new(Mutex::new(pipe))), + } + } +} + +impl Default for WritableTarget { + fn default() -> Self { + Self::from(Target::default()) + } +} + +impl fmt::Debug for WritableTarget { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "{}", + match self { + Self::Stdout => "stdout", + Self::Stderr => "stderr", + Self::Pipe(_) => "pipe", + } + ) + } +} +/// Whether or not to print styles to the target. +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +pub enum WriteStyle { + /// Try to print styles, but don't force the issue. + Auto, + /// Try very hard to print styles. + Always, + /// Never print styles. + Never, +} + +impl Default for WriteStyle { + fn default() -> Self { + WriteStyle::Auto + } +} + +/// A terminal target with color awareness. +pub(crate) struct Writer { + inner: BufferWriter, + write_style: WriteStyle, +} + +impl Writer { + pub fn write_style(&self) -> WriteStyle { + self.write_style + } + + pub(super) fn buffer(&self) -> Buffer { + self.inner.buffer() + } + + pub(super) fn print(&self, buf: &Buffer) -> io::Result<()> { + self.inner.print(buf) + } +} + +/// A builder for a terminal writer. +/// +/// The target and style choice can be configured before building. +#[derive(Debug)] +pub(crate) struct Builder { + target: WritableTarget, + write_style: WriteStyle, + is_test: bool, + built: bool, +} + +impl Builder { + /// Initialize the writer builder with defaults. + pub(crate) fn new() -> Self { + Builder { + target: Default::default(), + write_style: Default::default(), + is_test: false, + built: false, + } + } + + /// Set the target to write to. + pub(crate) fn target(&mut self, target: Target) -> &mut Self { + self.target = target.into(); + self + } + + /// Parses a style choice string. + /// + /// See the [Disabling colors] section for more details. + /// + /// [Disabling colors]: ../index.html#disabling-colors + pub(crate) fn parse_write_style(&mut self, write_style: &str) -> &mut Self { + self.write_style(parse_write_style(write_style)) + } + + /// Whether or not to print style characters when writing. + pub(crate) fn write_style(&mut self, write_style: WriteStyle) -> &mut Self { + self.write_style = write_style; + self + } + + /// Whether or not to capture logs for `cargo test`. + pub(crate) fn is_test(&mut self, is_test: bool) -> &mut Self { + self.is_test = is_test; + self + } + + /// Build a terminal writer. + pub(crate) fn build(&mut self) -> Writer { + assert!(!self.built, "attempt to re-use consumed builder"); + self.built = true; + + let color_choice = match self.write_style { + WriteStyle::Auto => { + if match &self.target { + WritableTarget::Stderr => is_stderr(), + WritableTarget::Stdout => is_stdout(), + WritableTarget::Pipe(_) => false, + } { + WriteStyle::Auto + } else { + WriteStyle::Never + } + } + color_choice => color_choice, + }; + + let writer = match mem::take(&mut self.target) { + WritableTarget::Stderr => BufferWriter::stderr(self.is_test, color_choice), + WritableTarget::Stdout => BufferWriter::stdout(self.is_test, color_choice), + WritableTarget::Pipe(pipe) => BufferWriter::pipe(self.is_test, color_choice, pipe), + }; + + Writer { + inner: writer, + write_style: self.write_style, + } + } +} + +impl Default for Builder { + fn default() -> Self { + Builder::new() + } +} + +impl fmt::Debug for Writer { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Writer").finish() + } +} + +fn parse_write_style(spec: &str) -> WriteStyle { + match spec { + "auto" => WriteStyle::Auto, + "always" => WriteStyle::Always, + "never" => WriteStyle::Never, + _ => Default::default(), + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn parse_write_style_valid() { + let inputs = vec![ + ("auto", WriteStyle::Auto), + ("always", WriteStyle::Always), + ("never", WriteStyle::Never), + ]; + + for (input, expected) in inputs { + assert_eq!(expected, parse_write_style(input)); + } + } + + #[test] + fn parse_write_style_invalid() { + let inputs = vec!["", "true", "false", "NEVER!!"]; + + for input in inputs { + assert_eq!(WriteStyle::Auto, parse_write_style(input)); + } + } +} diff --git a/vendor/env_logger-0.8.4/src/fmt/writer/termcolor/extern_impl.rs b/vendor/env_logger-0.8.4/src/fmt/writer/termcolor/extern_impl.rs new file mode 100644 index 0000000000..11012fb158 --- /dev/null +++ b/vendor/env_logger-0.8.4/src/fmt/writer/termcolor/extern_impl.rs @@ -0,0 +1,510 @@ +use std::borrow::Cow; +use std::cell::RefCell; +use std::fmt; +use std::io::{self, Write}; +use std::rc::Rc; +use std::sync::Mutex; + +use log::Level; +use termcolor::{self, ColorChoice, ColorSpec, WriteColor}; + +use crate::fmt::{Formatter, WritableTarget, WriteStyle}; + +pub(in crate::fmt::writer) mod glob { + pub use super::*; +} + +impl Formatter { + /// Begin a new [`Style`]. + /// + /// # Examples + /// + /// Create a bold, red colored style and use it to print the log level: + /// + /// ``` + /// use std::io::Write; + /// use env_logger::fmt::Color; + /// + /// let mut builder = env_logger::Builder::new(); + /// + /// builder.format(|buf, record| { + /// let mut level_style = buf.style(); + /// + /// level_style.set_color(Color::Red).set_bold(true); + /// + /// writeln!(buf, "{}: {}", + /// level_style.value(record.level()), + /// record.args()) + /// }); + /// ``` + /// + /// [`Style`]: struct.Style.html + pub fn style(&self) -> Style { + Style { + buf: self.buf.clone(), + spec: ColorSpec::new(), + } + } + + /// Get the default [`Style`] for the given level. + /// + /// The style can be used to print other values besides the level. + pub fn default_level_style(&self, level: Level) -> Style { + let mut level_style = self.style(); + match level { + Level::Trace => level_style.set_color(Color::Cyan), + Level::Debug => level_style.set_color(Color::Blue), + Level::Info => level_style.set_color(Color::Green), + Level::Warn => level_style.set_color(Color::Yellow), + Level::Error => level_style.set_color(Color::Red).set_bold(true), + }; + level_style + } + + /// Get a printable [`Style`] for the given level. + /// + /// The style can only be used to print the level. + pub fn default_styled_level(&self, level: Level) -> StyledValue<'static, Level> { + self.default_level_style(level).into_value(level) + } +} + +pub(in crate::fmt::writer) struct BufferWriter { + inner: termcolor::BufferWriter, + test_target: Option<WritableTarget>, +} + +pub(in crate::fmt) struct Buffer { + inner: termcolor::Buffer, + has_test_target: bool, +} + +impl BufferWriter { + pub(in crate::fmt::writer) fn stderr(is_test: bool, write_style: WriteStyle) -> Self { + BufferWriter { + inner: termcolor::BufferWriter::stderr(write_style.into_color_choice()), + test_target: if is_test { + Some(WritableTarget::Stderr) + } else { + None + }, + } + } + + pub(in crate::fmt::writer) fn stdout(is_test: bool, write_style: WriteStyle) -> Self { + BufferWriter { + inner: termcolor::BufferWriter::stdout(write_style.into_color_choice()), + test_target: if is_test { + Some(WritableTarget::Stdout) + } else { + None + }, + } + } + + pub(in crate::fmt::writer) fn pipe( + is_test: bool, + write_style: WriteStyle, + pipe: Box<Mutex<dyn io::Write + Send + 'static>>, + ) -> Self { + BufferWriter { + // The inner Buffer is never printed from, but it is still needed to handle coloring and other formating + inner: termcolor::BufferWriter::stderr(write_style.into_color_choice()), + test_target: if is_test { + Some(WritableTarget::Pipe(pipe)) + } else { + None + }, + } + } + + pub(in crate::fmt::writer) fn buffer(&self) -> Buffer { + Buffer { + inner: self.inner.buffer(), + has_test_target: self.test_target.is_some(), + } + } + + pub(in crate::fmt::writer) fn print(&self, buf: &Buffer) -> io::Result<()> { + if let Some(target) = &self.test_target { + // This impl uses the `eprint` and `print` macros + // instead of `termcolor`'s buffer. + // This is so their output can be captured by `cargo test` + let log = String::from_utf8_lossy(buf.bytes()); + + match target { + WritableTarget::Stderr => eprint!("{}", log), + WritableTarget::Stdout => print!("{}", log), + WritableTarget::Pipe(pipe) => write!(pipe.lock().unwrap(), "{}", log)?, + } + + Ok(()) + } else { + self.inner.print(&buf.inner) + } + } +} + +impl Buffer { + pub(in crate::fmt) fn clear(&mut self) { + self.inner.clear() + } + + pub(in crate::fmt) fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.inner.write(buf) + } + + pub(in crate::fmt) fn flush(&mut self) -> io::Result<()> { + self.inner.flush() + } + + pub(in crate::fmt) fn bytes(&self) -> &[u8] { + self.inner.as_slice() + } + + fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> { + // Ignore styles for test captured logs because they can't be printed + if !self.has_test_target { + self.inner.set_color(spec) + } else { + Ok(()) + } + } + + fn reset(&mut self) -> io::Result<()> { + // Ignore styles for test captured logs because they can't be printed + if !self.has_test_target { + self.inner.reset() + } else { + Ok(()) + } + } +} + +impl WriteStyle { + fn into_color_choice(self) -> ColorChoice { + match self { + WriteStyle::Always => ColorChoice::Always, + WriteStyle::Auto => ColorChoice::Auto, + WriteStyle::Never => ColorChoice::Never, + } + } +} + +/// A set of styles to apply to the terminal output. +/// +/// Call [`Formatter::style`] to get a `Style` and use the builder methods to +/// set styling properties, like [color] and [weight]. +/// To print a value using the style, wrap it in a call to [`value`] when the log +/// record is formatted. +/// +/// # Examples +/// +/// Create a bold, red colored style and use it to print the log level: +/// +/// ``` +/// use std::io::Write; +/// use env_logger::fmt::Color; +/// +/// let mut builder = env_logger::Builder::new(); +/// +/// builder.format(|buf, record| { +/// let mut level_style = buf.style(); +/// +/// level_style.set_color(Color::Red).set_bold(true); +/// +/// writeln!(buf, "{}: {}", +/// level_style.value(record.level()), +/// record.args()) +/// }); +/// ``` +/// +/// Styles can be re-used to output multiple values: +/// +/// ``` +/// use std::io::Write; +/// use env_logger::fmt::Color; +/// +/// let mut builder = env_logger::Builder::new(); +/// +/// builder.format(|buf, record| { +/// let mut bold = buf.style(); +/// +/// bold.set_bold(true); +/// +/// writeln!(buf, "{}: {} {}", +/// bold.value(record.level()), +/// bold.value("some bold text"), +/// record.args()) +/// }); +/// ``` +/// +/// [`Formatter::style`]: struct.Formatter.html#method.style +/// [color]: #method.set_color +/// [weight]: #method.set_bold +/// [`value`]: #method.value +#[derive(Clone)] +pub struct Style { + buf: Rc<RefCell<Buffer>>, + spec: ColorSpec, +} + +/// A value that can be printed using the given styles. +/// +/// It is the result of calling [`Style::value`]. +/// +/// [`Style::value`]: struct.Style.html#method.value +pub struct StyledValue<'a, T> { + style: Cow<'a, Style>, + value: T, +} + +impl Style { + /// Set the text color. + /// + /// # Examples + /// + /// Create a style with red text: + /// + /// ``` + /// use std::io::Write; + /// use env_logger::fmt::Color; + /// + /// let mut builder = env_logger::Builder::new(); + /// + /// builder.format(|buf, record| { + /// let mut style = buf.style(); + /// + /// style.set_color(Color::Red); + /// + /// writeln!(buf, "{}", style.value(record.args())) + /// }); + /// ``` + pub fn set_color(&mut self, color: Color) -> &mut Style { + self.spec.set_fg(Some(color.into_termcolor())); + self + } + + /// Set the text weight. + /// + /// If `yes` is true then text will be written in bold. + /// If `yes` is false then text will be written in the default weight. + /// + /// # Examples + /// + /// Create a style with bold text: + /// + /// ``` + /// use std::io::Write; + /// + /// let mut builder = env_logger::Builder::new(); + /// + /// builder.format(|buf, record| { + /// let mut style = buf.style(); + /// + /// style.set_bold(true); + /// + /// writeln!(buf, "{}", style.value(record.args())) + /// }); + /// ``` + pub fn set_bold(&mut self, yes: bool) -> &mut Style { + self.spec.set_bold(yes); + self + } + + /// Set the text intensity. + /// + /// If `yes` is true then text will be written in a brighter color. + /// If `yes` is false then text will be written in the default color. + /// + /// # Examples + /// + /// Create a style with intense text: + /// + /// ``` + /// use std::io::Write; + /// + /// let mut builder = env_logger::Builder::new(); + /// + /// builder.format(|buf, record| { + /// let mut style = buf.style(); + /// + /// style.set_intense(true); + /// + /// writeln!(buf, "{}", style.value(record.args())) + /// }); + /// ``` + pub fn set_intense(&mut self, yes: bool) -> &mut Style { + self.spec.set_intense(yes); + self + } + + /// Set the background color. + /// + /// # Examples + /// + /// Create a style with a yellow background: + /// + /// ``` + /// use std::io::Write; + /// use env_logger::fmt::Color; + /// + /// let mut builder = env_logger::Builder::new(); + /// + /// builder.format(|buf, record| { + /// let mut style = buf.style(); + /// + /// style.set_bg(Color::Yellow); + /// + /// writeln!(buf, "{}", style.value(record.args())) + /// }); + /// ``` + pub fn set_bg(&mut self, color: Color) -> &mut Style { + self.spec.set_bg(Some(color.into_termcolor())); + self + } + + /// Wrap a value in the style. + /// + /// The same `Style` can be used to print multiple different values. + /// + /// # Examples + /// + /// Create a bold, red colored style and use it to print the log level: + /// + /// ``` + /// use std::io::Write; + /// use env_logger::fmt::Color; + /// + /// let mut builder = env_logger::Builder::new(); + /// + /// builder.format(|buf, record| { + /// let mut style = buf.style(); + /// + /// style.set_color(Color::Red).set_bold(true); + /// + /// writeln!(buf, "{}: {}", + /// style.value(record.level()), + /// record.args()) + /// }); + /// ``` + pub fn value<T>(&self, value: T) -> StyledValue<T> { + StyledValue { + style: Cow::Borrowed(self), + value, + } + } + + /// Wrap a value in the style by taking ownership of it. + pub(crate) fn into_value<T>(self, value: T) -> StyledValue<'static, T> { + StyledValue { + style: Cow::Owned(self), + value, + } + } +} + +impl<'a, T> StyledValue<'a, T> { + fn write_fmt<F>(&self, f: F) -> fmt::Result + where + F: FnOnce() -> fmt::Result, + { + self.style + .buf + .borrow_mut() + .set_color(&self.style.spec) + .map_err(|_| fmt::Error)?; + + // Always try to reset the terminal style, even if writing failed + let write = f(); + let reset = self.style.buf.borrow_mut().reset().map_err(|_| fmt::Error); + + write.and(reset) + } +} + +impl fmt::Debug for Style { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Style").field("spec", &self.spec).finish() + } +} + +macro_rules! impl_styled_value_fmt { + ($($fmt_trait:path),*) => { + $( + impl<'a, T: $fmt_trait> $fmt_trait for StyledValue<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter)->fmt::Result { + self.write_fmt(|| T::fmt(&self.value, f)) + } + } + )* + }; +} + +impl_styled_value_fmt!( + fmt::Debug, + fmt::Display, + fmt::Pointer, + fmt::Octal, + fmt::Binary, + fmt::UpperHex, + fmt::LowerHex, + fmt::UpperExp, + fmt::LowerExp +); + +// The `Color` type is copied from https://github.com/BurntSushi/ripgrep/tree/master/termcolor + +/// The set of available colors for the terminal foreground/background. +/// +/// The `Ansi256` and `Rgb` colors will only output the correct codes when +/// paired with the `Ansi` `WriteColor` implementation. +/// +/// The `Ansi256` and `Rgb` color types are not supported when writing colors +/// on Windows using the console. If they are used on Windows, then they are +/// silently ignored and no colors will be emitted. +/// +/// This set may expand over time. +/// +/// This type has a `FromStr` impl that can parse colors from their human +/// readable form. The format is as follows: +/// +/// 1. Any of the explicitly listed colors in English. They are matched +/// case insensitively. +/// 2. A single 8-bit integer, in either decimal or hexadecimal format. +/// 3. A triple of 8-bit integers separated by a comma, where each integer is +/// in decimal or hexadecimal format. +/// +/// Hexadecimal numbers are written with a `0x` prefix. +#[allow(missing_docs)] +#[non_exhaustive] +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum Color { + Black, + Blue, + Green, + Red, + Cyan, + Magenta, + Yellow, + White, + Ansi256(u8), + Rgb(u8, u8, u8), +} + +impl Color { + fn into_termcolor(self) -> termcolor::Color { + match self { + Color::Black => termcolor::Color::Black, + Color::Blue => termcolor::Color::Blue, + Color::Green => termcolor::Color::Green, + Color::Red => termcolor::Color::Red, + Color::Cyan => termcolor::Color::Cyan, + Color::Magenta => termcolor::Color::Magenta, + Color::Yellow => termcolor::Color::Yellow, + Color::White => termcolor::Color::White, + Color::Ansi256(value) => termcolor::Color::Ansi256(value), + Color::Rgb(r, g, b) => termcolor::Color::Rgb(r, g, b), + } + } +} diff --git a/vendor/env_logger-0.8.4/src/fmt/writer/termcolor/mod.rs b/vendor/env_logger-0.8.4/src/fmt/writer/termcolor/mod.rs new file mode 100644 index 0000000000..f3e6768cd0 --- /dev/null +++ b/vendor/env_logger-0.8.4/src/fmt/writer/termcolor/mod.rs @@ -0,0 +1,12 @@ +/* +This internal module contains the style and terminal writing implementation. + +Its public API is available when the `termcolor` crate is available. +The terminal printing is shimmed when the `termcolor` crate is not available. +*/ + +#[cfg_attr(feature = "termcolor", path = "extern_impl.rs")] +#[cfg_attr(not(feature = "termcolor"), path = "shim_impl.rs")] +mod imp; + +pub(in crate::fmt) use self::imp::*; diff --git a/vendor/env_logger-0.8.4/src/fmt/writer/termcolor/shim_impl.rs b/vendor/env_logger-0.8.4/src/fmt/writer/termcolor/shim_impl.rs new file mode 100644 index 0000000000..bfc31d0874 --- /dev/null +++ b/vendor/env_logger-0.8.4/src/fmt/writer/termcolor/shim_impl.rs @@ -0,0 +1,73 @@ +use std::{io, sync::Mutex}; + +use crate::fmt::{WritableTarget, WriteStyle}; + +pub(in crate::fmt::writer) mod glob {} + +pub(in crate::fmt::writer) struct BufferWriter { + target: WritableTarget, +} + +pub(in crate::fmt) struct Buffer(Vec<u8>); + +impl BufferWriter { + pub(in crate::fmt::writer) fn stderr(_is_test: bool, _write_style: WriteStyle) -> Self { + BufferWriter { + target: WritableTarget::Stderr, + } + } + + pub(in crate::fmt::writer) fn stdout(_is_test: bool, _write_style: WriteStyle) -> Self { + BufferWriter { + target: WritableTarget::Stdout, + } + } + + pub(in crate::fmt::writer) fn pipe( + _is_test: bool, + _write_style: WriteStyle, + pipe: Box<Mutex<dyn io::Write + Send + 'static>>, + ) -> Self { + BufferWriter { + target: WritableTarget::Pipe(pipe), + } + } + + pub(in crate::fmt::writer) fn buffer(&self) -> Buffer { + Buffer(Vec::new()) + } + + pub(in crate::fmt::writer) fn print(&self, buf: &Buffer) -> io::Result<()> { + // This impl uses the `eprint` and `print` macros + // instead of using the streams directly. + // This is so their output can be captured by `cargo test`. + match &self.target { + // Safety: If the target type is `Pipe`, `target_pipe` will always be non-empty. + WritableTarget::Pipe(pipe) => pipe.lock().unwrap().write_all(&buf.0)?, + WritableTarget::Stdout => print!("{}", String::from_utf8_lossy(&buf.0)), + WritableTarget::Stderr => eprint!("{}", String::from_utf8_lossy(&buf.0)), + } + + Ok(()) + } +} + +impl Buffer { + pub(in crate::fmt) fn clear(&mut self) { + self.0.clear(); + } + + pub(in crate::fmt) fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.0.extend(buf); + Ok(buf.len()) + } + + pub(in crate::fmt) fn flush(&mut self) -> io::Result<()> { + Ok(()) + } + + #[cfg(test)] + pub(in crate::fmt) fn bytes(&self) -> &[u8] { + &self.0 + } +} diff --git a/vendor/env_logger-0.8.4/src/lib.rs b/vendor/env_logger-0.8.4/src/lib.rs new file mode 100644 index 0000000000..6a77266bb0 --- /dev/null +++ b/vendor/env_logger-0.8.4/src/lib.rs @@ -0,0 +1,1299 @@ +// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! A simple logger that can be configured via environment variables, for use +//! with the logging facade exposed by the [`log` crate][log-crate-url]. +//! +//! Despite having "env" in its name, **`env_logger`** can also be configured by +//! other means besides environment variables. See [the examples][gh-repo-examples] +//! in the source repository for more approaches. +//! +//! By default, `env_logger` writes logs to `stderr`, but can be configured to +//! instead write them to `stdout`. +//! +//! ## Example +//! +//! ``` +//! use log::{debug, error, log_enabled, info, Level}; +//! +//! env_logger::init(); +//! +//! debug!("this is a debug {}", "message"); +//! error!("this is printed by default"); +//! +//! if log_enabled!(Level::Info) { +//! let x = 3 * 4; // expensive computation +//! info!("the answer was: {}", x); +//! } +//! ``` +//! +//! Assumes the binary is `main`: +//! +//! ```{.bash} +//! $ RUST_LOG=error ./main +//! [2017-11-09T02:12:24Z ERROR main] this is printed by default +//! ``` +//! +//! ```{.bash} +//! $ RUST_LOG=info ./main +//! [2017-11-09T02:12:24Z ERROR main] this is printed by default +//! [2017-11-09T02:12:24Z INFO main] the answer was: 12 +//! ``` +//! +//! ```{.bash} +//! $ RUST_LOG=debug ./main +//! [2017-11-09T02:12:24Z DEBUG main] this is a debug message +//! [2017-11-09T02:12:24Z ERROR main] this is printed by default +//! [2017-11-09T02:12:24Z INFO main] the answer was: 12 +//! ``` +//! +//! You can also set the log level on a per module basis: +//! +//! ```{.bash} +//! $ RUST_LOG=main=info ./main +//! [2017-11-09T02:12:24Z ERROR main] this is printed by default +//! [2017-11-09T02:12:24Z INFO main] the answer was: 12 +//! ``` +//! +//! And enable all logging: +//! +//! ```{.bash} +//! $ RUST_LOG=main ./main +//! [2017-11-09T02:12:24Z DEBUG main] this is a debug message +//! [2017-11-09T02:12:24Z ERROR main] this is printed by default +//! [2017-11-09T02:12:24Z INFO main] the answer was: 12 +//! ``` +//! +//! If the binary name contains hyphens, you will need to replace +//! them with underscores: +//! +//! ```{.bash} +//! $ RUST_LOG=my_app ./my-app +//! [2017-11-09T02:12:24Z DEBUG my_app] this is a debug message +//! [2017-11-09T02:12:24Z ERROR my_app] this is printed by default +//! [2017-11-09T02:12:24Z INFO my_app] the answer was: 12 +//! ``` +//! +//! This is because Rust modules and crates cannot contain hyphens +//! in their name, although `cargo` continues to accept them. +//! +//! See the documentation for the [`log` crate][log-crate-url] for more +//! information about its API. +//! +//! ## Enabling logging +//! +//! Log levels are controlled on a per-module basis, and **by default all +//! logging is disabled except for the `error` level**. +//! +//! Logging is controlled via the **`RUST_LOG`** environment variable. The +//! value of this environment variable is a comma-separated list of *logging +//! directives*. A logging directive is of the form: +//! +//! ```text +//! path::to::module=level +//! ``` +//! +//! The path to the module is rooted in the name of the crate it was compiled +//! for, so if your program is contained in a file `hello.rs`, for example, to +//! turn on logging for this file you would use a value of `RUST_LOG=hello`. +//! Furthermore, this path is a prefix-search, so all modules nested in the +//! specified module will also have logging enabled. +//! +//! When providing the crate name or a module path, explicitly specifying the +//! log level is optional. If omitted, all logging for the item (and its +//! children) will be enabled. +//! +//! The names of the log levels that may be specified correspond to the +//! variations of the [`log::Level`][level-enum] enum from the `log` +//! crate. They are: +//! +//! * `error` +//! * `warn` +//! * `info` +//! * `debug` +//! * `trace` +//! +//! There is also a pseudo logging level, `off`, which may be specified to +//! disable all logging for a given module or for the entire application. As +//! with the logging levels, the letter case is not significant[^fn-off]. +//! +//! [^fn-off]: Similar to the universe of log level names, the `off` pseudo +//! log level feature is also provided by the underlying `log` crate. +//! +//! The letter case is not significant for the logging level names; e.g., +//! `debug`, `DEBUG`, and `dEbuG` all represent the same logging level. For +//! consistency, our convention is to use the lower case names. Where our docs +//! do use other forms, they do so in the context of specific examples, so you +//! won't be surprised if you see similar usage in the wild. +//! +//! As the log level for a module is optional, the module to enable logging for +//! is also optional. **If only a level is provided, then the global log +//! level for all modules is set to this value.** +//! +//! Some examples of valid values of `RUST_LOG` are: +//! +//! * `hello` turns on all logging for the 'hello' module +//! * `trace` turns on all logging for the application, regardless of its name +//! * `TRACE` turns on all logging for the application, regardless of its name (same as previous) +//! * `info` turns on all info logging +//! * `INFO` turns on all info logging (same as previous) +//! * `hello=debug` turns on debug logging for 'hello' +//! * `hello=DEBUG` turns on debug logging for 'hello' (same as previous) +//! * `hello,std::option` turns on hello, and std's option logging +//! * `error,hello=warn` turn on global error logging and also warn for hello +//! * `error,hello=off` turn on global error logging, but turn off logging for hello +//! * `off` turns off all logging for the application +//! * `OFF` turns off all logging for the application (same as previous) +//! +//! ## Filtering results +//! +//! A `RUST_LOG` directive may include a regex filter. The syntax is to append `/` +//! followed by a regex. Each message is checked against the regex, and is only +//! logged if it matches. Note that the matching is done after formatting the +//! log string but before adding any logging meta-data. There is a single filter +//! for all modules. +//! +//! Some examples: +//! +//! * `hello/foo` turns on all logging for the 'hello' module where the log +//! message includes 'foo'. +//! * `info/f.o` turns on all info logging where the log message includes 'foo', +//! 'f1o', 'fao', etc. +//! * `hello=debug/foo*foo` turns on debug logging for 'hello' where the log +//! message includes 'foofoo' or 'fofoo' or 'fooooooofoo', etc. +//! * `error,hello=warn/[0-9]scopes` turn on global error logging and also +//! warn for hello. In both cases the log message must include a single digit +//! number followed by 'scopes'. +//! +//! ## Capturing logs in tests +//! +//! Records logged during `cargo test` will not be captured by the test harness by default. +//! The [`Builder::is_test`] method can be used in unit tests to ensure logs will be captured: +//! +//! ``` +//! # #[macro_use] extern crate log; +//! #[cfg(test)] +//! mod tests { +//! fn init() { +//! let _ = env_logger::builder().is_test(true).try_init(); +//! } +//! +//! #[test] +//! fn it_works() { +//! init(); +//! +//! info!("This record will be captured by `cargo test`"); +//! +//! assert_eq!(2, 1 + 1); +//! } +//! } +//! ``` +//! +//! Enabling test capturing comes at the expense of color and other style support +//! and may have performance implications. +//! +//! ## Disabling colors +//! +//! Colors and other styles can be configured with the `RUST_LOG_STYLE` +//! environment variable. It accepts the following values: +//! +//! * `auto` (default) will attempt to print style characters, but don't force the issue. +//! If the console isn't available on Windows, or if TERM=dumb, for example, then don't print colors. +//! * `always` will always print style characters even if they aren't supported by the terminal. +//! This includes emitting ANSI colors on Windows if the console API is unavailable. +//! * `never` will never print style characters. +//! +//! ## Tweaking the default format +//! +//! Parts of the default format can be excluded from the log output using the [`Builder`]. +//! The following example excludes the timestamp from the log output: +//! +//! ``` +//! env_logger::builder() +//! .format_timestamp(None) +//! .init(); +//! ``` +//! +//! ### Stability of the default format +//! +//! The default format won't optimise for long-term stability, and explicitly makes no +//! guarantees about the stability of its output across major, minor or patch version +//! bumps during `0.x`. +//! +//! If you want to capture or interpret the output of `env_logger` programmatically +//! then you should use a custom format. +//! +//! ### Using a custom format +//! +//! Custom formats can be provided as closures to the [`Builder`]. +//! These closures take a [`Formatter`] and `log::Record` as arguments: +//! +//! ``` +//! use std::io::Write; +//! +//! env_logger::builder() +//! .format(|buf, record| { +//! writeln!(buf, "{}: {}", record.level(), record.args()) +//! }) +//! .init(); +//! ``` +//! +//! See the [`fmt`] module for more details about custom formats. +//! +//! ## Specifying defaults for environment variables +//! +//! `env_logger` can read configuration from environment variables. +//! If these variables aren't present, the default value to use can be tweaked with the [`Env`] type. +//! The following example defaults to log `warn` and above if the `RUST_LOG` environment variable +//! isn't set: +//! +//! ``` +//! use env_logger::Env; +//! +//! env_logger::Builder::from_env(Env::default().default_filter_or("warn")).init(); +//! ``` +//! +//! [gh-repo-examples]: https://github.com/env-logger-rs/env_logger/tree/master/examples +//! [level-enum]: https://docs.rs/log/latest/log/enum.Level.html +//! [log-crate-url]: https://docs.rs/log/ +//! [`Builder`]: struct.Builder.html +//! [`Builder::is_test`]: struct.Builder.html#method.is_test +//! [`Env`]: struct.Env.html +//! [`fmt`]: fmt/index.html + +#![doc( + html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", + html_favicon_url = "https://www.rust-lang.org/static/images/favicon.ico" +)] +// When compiled for the rustc compiler itself we want to make sure that this is +// an unstable crate +#![cfg_attr(rustbuild, feature(staged_api, rustc_private))] +#![cfg_attr(rustbuild, unstable(feature = "rustc_private", issue = "27812"))] +#![deny(missing_debug_implementations, missing_docs)] + +use std::{borrow::Cow, cell::RefCell, env, io}; + +use log::{LevelFilter, Log, Metadata, Record, SetLoggerError}; + +pub mod filter; +pub mod fmt; + +pub use self::fmt::glob::*; + +use self::filter::Filter; +use self::fmt::writer::{self, Writer}; +use self::fmt::{FormatFn, Formatter}; + +/// The default name for the environment variable to read filters from. +pub const DEFAULT_FILTER_ENV: &str = "RUST_LOG"; + +/// The default name for the environment variable to read style preferences from. +pub const DEFAULT_WRITE_STYLE_ENV: &str = "RUST_LOG_STYLE"; + +/// Set of environment variables to configure from. +/// +/// # Default environment variables +/// +/// By default, the `Env` will read the following environment variables: +/// +/// - `RUST_LOG`: the level filter +/// - `RUST_LOG_STYLE`: whether or not to print styles with records. +/// +/// These sources can be configured using the builder methods on `Env`. +#[derive(Debug)] +pub struct Env<'a> { + filter: Var<'a>, + write_style: Var<'a>, +} + +#[derive(Debug)] +struct Var<'a> { + name: Cow<'a, str>, + default: Option<Cow<'a, str>>, +} + +/// The env logger. +/// +/// This struct implements the `Log` trait from the [`log` crate][log-crate-url], +/// which allows it to act as a logger. +/// +/// The [`init()`], [`try_init()`], [`Builder::init()`] and [`Builder::try_init()`] +/// methods will each construct a `Logger` and immediately initialize it as the +/// default global logger. +/// +/// If you'd instead need access to the constructed `Logger`, you can use +/// the associated [`Builder`] and install it with the +/// [`log` crate][log-crate-url] directly. +/// +/// [log-crate-url]: https://docs.rs/log/ +/// [`init()`]: fn.init.html +/// [`try_init()`]: fn.try_init.html +/// [`Builder::init()`]: struct.Builder.html#method.init +/// [`Builder::try_init()`]: struct.Builder.html#method.try_init +/// [`Builder`]: struct.Builder.html +pub struct Logger { + writer: Writer, + filter: Filter, + format: FormatFn, +} + +/// `Builder` acts as builder for initializing a `Logger`. +/// +/// It can be used to customize the log format, change the environment variable used +/// to provide the logging directives and also set the default log level filter. +/// +/// # Examples +/// +/// ``` +/// # #[macro_use] extern crate log; +/// # use std::io::Write; +/// use env_logger::Builder; +/// use log::LevelFilter; +/// +/// let mut builder = Builder::from_default_env(); +/// +/// builder +/// .format(|buf, record| writeln!(buf, "{} - {}", record.level(), record.args())) +/// .filter(None, LevelFilter::Info) +/// .init(); +/// +/// error!("error message"); +/// info!("info message"); +/// ``` +#[derive(Default)] +pub struct Builder { + filter: filter::Builder, + writer: writer::Builder, + format: fmt::Builder, + built: bool, +} + +impl Builder { + /// Initializes the log builder with defaults. + /// + /// **NOTE:** This method won't read from any environment variables. + /// Use the [`filter`] and [`write_style`] methods to configure the builder + /// or use [`from_env`] or [`from_default_env`] instead. + /// + /// # Examples + /// + /// Create a new builder and configure filters and style: + /// + /// ``` + /// use log::LevelFilter; + /// use env_logger::{Builder, WriteStyle}; + /// + /// let mut builder = Builder::new(); + /// + /// builder + /// .filter(None, LevelFilter::Info) + /// .write_style(WriteStyle::Always) + /// .init(); + /// ``` + /// + /// [`filter`]: #method.filter + /// [`write_style`]: #method.write_style + /// [`from_env`]: #method.from_env + /// [`from_default_env`]: #method.from_default_env + pub fn new() -> Builder { + Default::default() + } + + /// Initializes the log builder from the environment. + /// + /// The variables used to read configuration from can be tweaked before + /// passing in. + /// + /// # Examples + /// + /// Initialise a logger reading the log filter from an environment variable + /// called `MY_LOG`: + /// + /// ``` + /// use env_logger::Builder; + /// + /// let mut builder = Builder::from_env("MY_LOG"); + /// builder.init(); + /// ``` + /// + /// Initialise a logger using the `MY_LOG` variable for filtering and + /// `MY_LOG_STYLE` for whether or not to write styles: + /// + /// ``` + /// use env_logger::{Builder, Env}; + /// + /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE"); + /// + /// let mut builder = Builder::from_env(env); + /// builder.init(); + /// ``` + pub fn from_env<'a, E>(env: E) -> Self + where + E: Into<Env<'a>>, + { + let mut builder = Builder::new(); + builder.parse_env(env); + builder + } + + /// Applies the configuration from the environment. + /// + /// This function allows a builder to be configured with default parameters, + /// to be then overridden by the environment. + /// + /// # Examples + /// + /// Initialise a logger with filter level `Off`, then override the log + /// filter from an environment variable called `MY_LOG`: + /// + /// ``` + /// use log::LevelFilter; + /// use env_logger::Builder; + /// + /// let mut builder = Builder::new(); + /// + /// builder.filter_level(LevelFilter::Off); + /// builder.parse_env("MY_LOG"); + /// builder.init(); + /// ``` + /// + /// Initialise a logger with filter level `Off`, then use the `MY_LOG` + /// variable to override filtering and `MY_LOG_STYLE` to override whether + /// or not to write styles: + /// + /// ``` + /// use log::LevelFilter; + /// use env_logger::{Builder, Env}; + /// + /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE"); + /// + /// let mut builder = Builder::new(); + /// builder.filter_level(LevelFilter::Off); + /// builder.parse_env(env); + /// builder.init(); + /// ``` + pub fn parse_env<'a, E>(&mut self, env: E) -> &mut Self + where + E: Into<Env<'a>>, + { + let env = env.into(); + + if let Some(s) = env.get_filter() { + self.parse_filters(&s); + } + + if let Some(s) = env.get_write_style() { + self.parse_write_style(&s); + } + + self + } + + /// Initializes the log builder from the environment using default variable names. + /// + /// This method is a convenient way to call `from_env(Env::default())` without + /// having to use the `Env` type explicitly. The builder will use the + /// [default environment variables]. + /// + /// # Examples + /// + /// Initialise a logger using the default environment variables: + /// + /// ``` + /// use env_logger::Builder; + /// + /// let mut builder = Builder::from_default_env(); + /// builder.init(); + /// ``` + /// + /// [default environment variables]: struct.Env.html#default-environment-variables + pub fn from_default_env() -> Self { + Self::from_env(Env::default()) + } + + /// Applies the configuration from the environment using default variable names. + /// + /// This method is a convenient way to call `parse_env(Env::default())` without + /// having to use the `Env` type explicitly. The builder will use the + /// [default environment variables]. + /// + /// # Examples + /// + /// Initialise a logger with filter level `Off`, then configure it using the + /// default environment variables: + /// + /// ``` + /// use log::LevelFilter; + /// use env_logger::Builder; + /// + /// let mut builder = Builder::new(); + /// builder.filter_level(LevelFilter::Off); + /// builder.parse_default_env(); + /// builder.init(); + /// ``` + /// + /// [default environment variables]: struct.Env.html#default-environment-variables + pub fn parse_default_env(&mut self) -> &mut Self { + self.parse_env(Env::default()) + } + + /// Sets the format function for formatting the log output. + /// + /// This function is called on each record logged and should format the + /// log record and output it to the given [`Formatter`]. + /// + /// The format function is expected to output the string directly to the + /// `Formatter` so that implementations can use the [`std::fmt`] macros + /// to format and output without intermediate heap allocations. The default + /// `env_logger` formatter takes advantage of this. + /// + /// # Examples + /// + /// Use a custom format to write only the log message: + /// + /// ``` + /// use std::io::Write; + /// use env_logger::Builder; + /// + /// let mut builder = Builder::new(); + /// + /// builder.format(|buf, record| writeln!(buf, "{}", record.args())); + /// ``` + /// + /// [`Formatter`]: fmt/struct.Formatter.html + /// [`String`]: https://doc.rust-lang.org/stable/std/string/struct.String.html + /// [`std::fmt`]: https://doc.rust-lang.org/std/fmt/index.html + pub fn format<F: 'static>(&mut self, format: F) -> &mut Self + where + F: Fn(&mut Formatter, &Record) -> io::Result<()> + Sync + Send, + { + self.format.custom_format = Some(Box::new(format)); + self + } + + /// Use the default format. + /// + /// This method will clear any custom format set on the builder. + pub fn default_format(&mut self) -> &mut Self { + self.format = Default::default(); + self + } + + /// Whether or not to write the level in the default format. + pub fn format_level(&mut self, write: bool) -> &mut Self { + self.format.format_level = write; + self + } + + /// Whether or not to write the module path in the default format. + pub fn format_module_path(&mut self, write: bool) -> &mut Self { + self.format.format_module_path = write; + self + } + + /// Configures the amount of spaces to use to indent multiline log records. + /// A value of `None` disables any kind of indentation. + pub fn format_indent(&mut self, indent: Option<usize>) -> &mut Self { + self.format.format_indent = indent; + self + } + + /// Configures if timestamp should be included and in what precision. + pub fn format_timestamp(&mut self, timestamp: Option<fmt::TimestampPrecision>) -> &mut Self { + self.format.format_timestamp = timestamp; + self + } + + /// Configures the timestamp to use second precision. + pub fn format_timestamp_secs(&mut self) -> &mut Self { + self.format_timestamp(Some(fmt::TimestampPrecision::Seconds)) + } + + /// Configures the timestamp to use millisecond precision. + pub fn format_timestamp_millis(&mut self) -> &mut Self { + self.format_timestamp(Some(fmt::TimestampPrecision::Millis)) + } + + /// Configures the timestamp to use microsecond precision. + pub fn format_timestamp_micros(&mut self) -> &mut Self { + self.format_timestamp(Some(fmt::TimestampPrecision::Micros)) + } + + /// Configures the timestamp to use nanosecond precision. + pub fn format_timestamp_nanos(&mut self) -> &mut Self { + self.format_timestamp(Some(fmt::TimestampPrecision::Nanos)) + } + + /// Configures the end of line suffix. + pub fn format_suffix(&mut self, suffix: &'static str) -> &mut Self { + self.format.format_suffix = suffix; + self + } + + /// Adds a directive to the filter for a specific module. + /// + /// # Examples + /// + /// Only include messages for info and above for logs in `path::to::module`: + /// + /// ``` + /// use env_logger::Builder; + /// use log::LevelFilter; + /// + /// let mut builder = Builder::new(); + /// + /// builder.filter_module("path::to::module", LevelFilter::Info); + /// ``` + pub fn filter_module(&mut self, module: &str, level: LevelFilter) -> &mut Self { + self.filter.filter_module(module, level); + self + } + + /// Adds a directive to the filter for all modules. + /// + /// # Examples + /// + /// Only include messages for info and above for logs in `path::to::module`: + /// + /// ``` + /// use env_logger::Builder; + /// use log::LevelFilter; + /// + /// let mut builder = Builder::new(); + /// + /// builder.filter_level(LevelFilter::Info); + /// ``` + pub fn filter_level(&mut self, level: LevelFilter) -> &mut Self { + self.filter.filter_level(level); + self + } + + /// Adds filters to the logger. + /// + /// The given module (if any) will log at most the specified level provided. + /// If no module is provided then the filter will apply to all log messages. + /// + /// # Examples + /// + /// Only include messages for info and above for logs in `path::to::module`: + /// + /// ``` + /// use env_logger::Builder; + /// use log::LevelFilter; + /// + /// let mut builder = Builder::new(); + /// + /// builder.filter(Some("path::to::module"), LevelFilter::Info); + /// ``` + pub fn filter(&mut self, module: Option<&str>, level: LevelFilter) -> &mut Self { + self.filter.filter(module, level); + self + } + + /// Parses the directives string in the same form as the `RUST_LOG` + /// environment variable. + /// + /// See the module documentation for more details. + pub fn parse_filters(&mut self, filters: &str) -> &mut Self { + self.filter.parse(filters); + self + } + + /// Sets the target for the log output. + /// + /// Env logger can log to either stdout, stderr or a custom pipe. The default is stderr. + /// + /// The custom pipe can be used to send the log messages to a custom sink (for example a file). + /// Do note that direct writes to a file can become a bottleneck due to IO operation times. + /// + /// # Examples + /// + /// Write log message to `stdout`: + /// + /// ``` + /// use env_logger::{Builder, Target}; + /// + /// let mut builder = Builder::new(); + /// + /// builder.target(Target::Stdout); + /// ``` + pub fn target(&mut self, target: fmt::Target) -> &mut Self { + self.writer.target(target); + self + } + + /// Sets whether or not styles will be written. + /// + /// This can be useful in environments that don't support control characters + /// for setting colors. + /// + /// # Examples + /// + /// Never attempt to write styles: + /// + /// ``` + /// use env_logger::{Builder, WriteStyle}; + /// + /// let mut builder = Builder::new(); + /// + /// builder.write_style(WriteStyle::Never); + /// ``` + pub fn write_style(&mut self, write_style: fmt::WriteStyle) -> &mut Self { + self.writer.write_style(write_style); + self + } + + /// Parses whether or not to write styles in the same form as the `RUST_LOG_STYLE` + /// environment variable. + /// + /// See the module documentation for more details. + pub fn parse_write_style(&mut self, write_style: &str) -> &mut Self { + self.writer.parse_write_style(write_style); + self + } + + /// Sets whether or not the logger will be used in unit tests. + /// + /// If `is_test` is `true` then the logger will allow the testing framework to + /// capture log records rather than printing them to the terminal directly. + pub fn is_test(&mut self, is_test: bool) -> &mut Self { + self.writer.is_test(is_test); + self + } + + /// Initializes the global logger with the built env logger. + /// + /// This should be called early in the execution of a Rust program. Any log + /// events that occur before initialization will be ignored. + /// + /// # Errors + /// + /// This function will fail if it is called more than once, or if another + /// library has already initialized a global logger. + pub fn try_init(&mut self) -> Result<(), SetLoggerError> { + let logger = self.build(); + + let max_level = logger.filter(); + let r = log::set_boxed_logger(Box::new(logger)); + + if r.is_ok() { + log::set_max_level(max_level); + } + + r + } + + /// Initializes the global logger with the built env logger. + /// + /// This should be called early in the execution of a Rust program. Any log + /// events that occur before initialization will be ignored. + /// + /// # Panics + /// + /// This function will panic if it is called more than once, or if another + /// library has already initialized a global logger. + pub fn init(&mut self) { + self.try_init() + .expect("Builder::init should not be called after logger initialized"); + } + + /// Build an env logger. + /// + /// The returned logger implements the `Log` trait and can be installed manually + /// or nested within another logger. + pub fn build(&mut self) -> Logger { + assert!(!self.built, "attempt to re-use consumed builder"); + self.built = true; + + Logger { + writer: self.writer.build(), + filter: self.filter.build(), + format: self.format.build(), + } + } +} + +impl Logger { + /// Creates the logger from the environment. + /// + /// The variables used to read configuration from can be tweaked before + /// passing in. + /// + /// # Examples + /// + /// Create a logger reading the log filter from an environment variable + /// called `MY_LOG`: + /// + /// ``` + /// use env_logger::Logger; + /// + /// let logger = Logger::from_env("MY_LOG"); + /// ``` + /// + /// Create a logger using the `MY_LOG` variable for filtering and + /// `MY_LOG_STYLE` for whether or not to write styles: + /// + /// ``` + /// use env_logger::{Logger, Env}; + /// + /// let env = Env::new().filter_or("MY_LOG", "info").write_style_or("MY_LOG_STYLE", "always"); + /// + /// let logger = Logger::from_env(env); + /// ``` + pub fn from_env<'a, E>(env: E) -> Self + where + E: Into<Env<'a>>, + { + Builder::from_env(env).build() + } + + /// Creates the logger from the environment using default variable names. + /// + /// This method is a convenient way to call `from_env(Env::default())` without + /// having to use the `Env` type explicitly. The logger will use the + /// [default environment variables]. + /// + /// # Examples + /// + /// Creates a logger using the default environment variables: + /// + /// ``` + /// use env_logger::Logger; + /// + /// let logger = Logger::from_default_env(); + /// ``` + /// + /// [default environment variables]: struct.Env.html#default-environment-variables + pub fn from_default_env() -> Self { + Builder::from_default_env().build() + } + + /// Returns the maximum `LevelFilter` that this env logger instance is + /// configured to output. + pub fn filter(&self) -> LevelFilter { + self.filter.filter() + } + + /// Checks if this record matches the configured filter. + pub fn matches(&self, record: &Record) -> bool { + self.filter.matches(record) + } +} + +impl Log for Logger { + fn enabled(&self, metadata: &Metadata) -> bool { + self.filter.enabled(metadata) + } + + fn log(&self, record: &Record) { + if self.matches(record) { + // Log records are written to a thread-local buffer before being printed + // to the terminal. We clear these buffers afterwards, but they aren't shrinked + // so will always at least have capacity for the largest log record formatted + // on that thread. + // + // If multiple `Logger`s are used by the same threads then the thread-local + // formatter might have different color support. If this is the case the + // formatter and its buffer are discarded and recreated. + + thread_local! { + static FORMATTER: RefCell<Option<Formatter>> = RefCell::new(None); + } + + let print = |formatter: &mut Formatter, record: &Record| { + let _ = + (self.format)(formatter, record).and_then(|_| formatter.print(&self.writer)); + + // Always clear the buffer afterwards + formatter.clear(); + }; + + let printed = FORMATTER + .try_with(|tl_buf| { + match tl_buf.try_borrow_mut() { + // There are no active borrows of the buffer + Ok(mut tl_buf) => match *tl_buf { + // We have a previously set formatter + Some(ref mut formatter) => { + // Check the buffer style. If it's different from the logger's + // style then drop the buffer and recreate it. + if formatter.write_style() != self.writer.write_style() { + *formatter = Formatter::new(&self.writer); + } + + print(formatter, record); + } + // We don't have a previously set formatter + None => { + let mut formatter = Formatter::new(&self.writer); + print(&mut formatter, record); + + *tl_buf = Some(formatter); + } + }, + // There's already an active borrow of the buffer (due to re-entrancy) + Err(_) => { + print(&mut Formatter::new(&self.writer), record); + } + } + }) + .is_ok(); + + if !printed { + // The thread-local storage was not available (because its + // destructor has already run). Create a new single-use + // Formatter on the stack for this call. + print(&mut Formatter::new(&self.writer), record); + } + } + } + + fn flush(&self) {} +} + +impl<'a> Env<'a> { + /// Get a default set of environment variables. + pub fn new() -> Self { + Self::default() + } + + /// Specify an environment variable to read the filter from. + pub fn filter<E>(mut self, filter_env: E) -> Self + where + E: Into<Cow<'a, str>>, + { + self.filter = Var::new(filter_env); + + self + } + + /// Specify an environment variable to read the filter from. + /// + /// If the variable is not set, the default value will be used. + pub fn filter_or<E, V>(mut self, filter_env: E, default: V) -> Self + where + E: Into<Cow<'a, str>>, + V: Into<Cow<'a, str>>, + { + self.filter = Var::new_with_default(filter_env, default); + + self + } + + /// Use the default environment variable to read the filter from. + /// + /// If the variable is not set, the default value will be used. + pub fn default_filter_or<V>(mut self, default: V) -> Self + where + V: Into<Cow<'a, str>>, + { + self.filter = Var::new_with_default(DEFAULT_FILTER_ENV, default); + + self + } + + fn get_filter(&self) -> Option<String> { + self.filter.get() + } + + /// Specify an environment variable to read the style from. + pub fn write_style<E>(mut self, write_style_env: E) -> Self + where + E: Into<Cow<'a, str>>, + { + self.write_style = Var::new(write_style_env); + + self + } + + /// Specify an environment variable to read the style from. + /// + /// If the variable is not set, the default value will be used. + pub fn write_style_or<E, V>(mut self, write_style_env: E, default: V) -> Self + where + E: Into<Cow<'a, str>>, + V: Into<Cow<'a, str>>, + { + self.write_style = Var::new_with_default(write_style_env, default); + + self + } + + /// Use the default environment variable to read the style from. + /// + /// If the variable is not set, the default value will be used. + pub fn default_write_style_or<V>(mut self, default: V) -> Self + where + V: Into<Cow<'a, str>>, + { + self.write_style = Var::new_with_default(DEFAULT_WRITE_STYLE_ENV, default); + + self + } + + fn get_write_style(&self) -> Option<String> { + self.write_style.get() + } +} + +impl<'a> Var<'a> { + fn new<E>(name: E) -> Self + where + E: Into<Cow<'a, str>>, + { + Var { + name: name.into(), + default: None, + } + } + + fn new_with_default<E, V>(name: E, default: V) -> Self + where + E: Into<Cow<'a, str>>, + V: Into<Cow<'a, str>>, + { + Var { + name: name.into(), + default: Some(default.into()), + } + } + + fn get(&self) -> Option<String> { + env::var(&*self.name) + .ok() + .or_else(|| self.default.to_owned().map(|v| v.into_owned())) + } +} + +impl<'a, T> From<T> for Env<'a> +where + T: Into<Cow<'a, str>>, +{ + fn from(filter_env: T) -> Self { + Env::default().filter(filter_env.into()) + } +} + +impl<'a> Default for Env<'a> { + fn default() -> Self { + Env { + filter: Var::new(DEFAULT_FILTER_ENV), + write_style: Var::new(DEFAULT_WRITE_STYLE_ENV), + } + } +} + +mod std_fmt_impls { + use super::*; + use std::fmt; + + impl fmt::Debug for Logger { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Logger") + .field("filter", &self.filter) + .finish() + } + } + + impl fmt::Debug for Builder { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if self.built { + f.debug_struct("Logger").field("built", &true).finish() + } else { + f.debug_struct("Logger") + .field("filter", &self.filter) + .field("writer", &self.writer) + .finish() + } + } + } +} + +/// Attempts to initialize the global logger with an env logger. +/// +/// This should be called early in the execution of a Rust program. Any log +/// events that occur before initialization will be ignored. +/// +/// # Errors +/// +/// This function will fail if it is called more than once, or if another +/// library has already initialized a global logger. +pub fn try_init() -> Result<(), SetLoggerError> { + try_init_from_env(Env::default()) +} + +/// Initializes the global logger with an env logger. +/// +/// This should be called early in the execution of a Rust program. Any log +/// events that occur before initialization will be ignored. +/// +/// # Panics +/// +/// This function will panic if it is called more than once, or if another +/// library has already initialized a global logger. +pub fn init() { + try_init().expect("env_logger::init should not be called after logger initialized"); +} + +/// Attempts to initialize the global logger with an env logger from the given +/// environment variables. +/// +/// This should be called early in the execution of a Rust program. Any log +/// events that occur before initialization will be ignored. +/// +/// # Examples +/// +/// Initialise a logger using the `MY_LOG` environment variable for filters +/// and `MY_LOG_STYLE` for writing colors: +/// +/// ``` +/// use env_logger::{Builder, Env}; +/// +/// # fn run() -> Result<(), Box<::std::error::Error>> { +/// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE"); +/// +/// env_logger::try_init_from_env(env)?; +/// +/// Ok(()) +/// # } +/// # run().unwrap(); +/// ``` +/// +/// # Errors +/// +/// This function will fail if it is called more than once, or if another +/// library has already initialized a global logger. +pub fn try_init_from_env<'a, E>(env: E) -> Result<(), SetLoggerError> +where + E: Into<Env<'a>>, +{ + let mut builder = Builder::from_env(env); + + builder.try_init() +} + +/// Initializes the global logger with an env logger from the given environment +/// variables. +/// +/// This should be called early in the execution of a Rust program. Any log +/// events that occur before initialization will be ignored. +/// +/// # Examples +/// +/// Initialise a logger using the `MY_LOG` environment variable for filters +/// and `MY_LOG_STYLE` for writing colors: +/// +/// ``` +/// use env_logger::{Builder, Env}; +/// +/// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE"); +/// +/// env_logger::init_from_env(env); +/// ``` +/// +/// # Panics +/// +/// This function will panic if it is called more than once, or if another +/// library has already initialized a global logger. +pub fn init_from_env<'a, E>(env: E) +where + E: Into<Env<'a>>, +{ + try_init_from_env(env) + .expect("env_logger::init_from_env should not be called after logger initialized"); +} + +/// Create a new builder with the default environment variables. +/// +/// The builder can be configured before being initialized. +/// This is a convenient way of calling [`Builder::from_default_env`]. +/// +/// [`Builder::from_default_env`]: struct.Builder.html#method.from_default_env +pub fn builder() -> Builder { + Builder::from_default_env() +} + +/// Create a builder from the given environment variables. +/// +/// The builder can be configured before being initialized. +#[deprecated( + since = "0.8.0", + note = "Prefer `env_logger::Builder::from_env()` instead." +)] +pub fn from_env<'a, E>(env: E) -> Builder +where + E: Into<Env<'a>>, +{ + Builder::from_env(env) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn env_get_filter_reads_from_var_if_set() { + env::set_var("env_get_filter_reads_from_var_if_set", "from var"); + + let env = Env::new().filter_or("env_get_filter_reads_from_var_if_set", "from default"); + + assert_eq!(Some("from var".to_owned()), env.get_filter()); + } + + #[test] + fn env_get_filter_reads_from_default_if_var_not_set() { + env::remove_var("env_get_filter_reads_from_default_if_var_not_set"); + + let env = Env::new().filter_or( + "env_get_filter_reads_from_default_if_var_not_set", + "from default", + ); + + assert_eq!(Some("from default".to_owned()), env.get_filter()); + } + + #[test] + fn env_get_write_style_reads_from_var_if_set() { + env::set_var("env_get_write_style_reads_from_var_if_set", "from var"); + + let env = + Env::new().write_style_or("env_get_write_style_reads_from_var_if_set", "from default"); + + assert_eq!(Some("from var".to_owned()), env.get_write_style()); + } + + #[test] + fn env_get_write_style_reads_from_default_if_var_not_set() { + env::remove_var("env_get_write_style_reads_from_default_if_var_not_set"); + + let env = Env::new().write_style_or( + "env_get_write_style_reads_from_default_if_var_not_set", + "from default", + ); + + assert_eq!(Some("from default".to_owned()), env.get_write_style()); + } + + #[test] + fn builder_parse_env_overrides_existing_filters() { + env::set_var( + "builder_parse_default_env_overrides_existing_filters", + "debug", + ); + let env = Env::new().filter("builder_parse_default_env_overrides_existing_filters"); + + let mut builder = Builder::new(); + builder.filter_level(LevelFilter::Trace); + // Overrides global level to debug + builder.parse_env(env); + + assert_eq!(builder.filter.build().filter(), LevelFilter::Debug); + } +} diff --git a/vendor/env_logger-0.8.4/tests/init-twice-retains-filter.rs b/vendor/env_logger-0.8.4/tests/init-twice-retains-filter.rs new file mode 100644 index 0000000000..673da3fd28 --- /dev/null +++ b/vendor/env_logger-0.8.4/tests/init-twice-retains-filter.rs @@ -0,0 +1,40 @@ +extern crate env_logger; +extern crate log; + +use std::env; +use std::process; +use std::str; + +fn main() { + if env::var("YOU_ARE_TESTING_NOW").is_ok() { + // Init from the env (which should set the max level to `Debug`) + env_logger::init(); + + assert_eq!(log::LevelFilter::Debug, log::max_level()); + + // Init again using a different max level + // This shouldn't clobber the level that was previously set + env_logger::Builder::new() + .parse_filters("info") + .try_init() + .unwrap_err(); + + assert_eq!(log::LevelFilter::Debug, log::max_level()); + return; + } + + let exe = env::current_exe().unwrap(); + let out = process::Command::new(exe) + .env("YOU_ARE_TESTING_NOW", "1") + .env("RUST_LOG", "debug") + .output() + .unwrap_or_else(|e| panic!("Unable to start child process: {}", e)); + if out.status.success() { + return; + } + + println!("test failed: {}", out.status); + println!("--- stdout\n{}", str::from_utf8(&out.stdout).unwrap()); + println!("--- stderr\n{}", str::from_utf8(&out.stderr).unwrap()); + process::exit(1); +} diff --git a/vendor/env_logger-0.8.4/tests/log-in-log.rs b/vendor/env_logger-0.8.4/tests/log-in-log.rs new file mode 100644 index 0000000000..89517ff362 --- /dev/null +++ b/vendor/env_logger-0.8.4/tests/log-in-log.rs @@ -0,0 +1,39 @@ +#[macro_use] +extern crate log; +extern crate env_logger; + +use std::env; +use std::fmt; +use std::process; +use std::str; + +struct Foo; + +impl fmt::Display for Foo { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + info!("test"); + f.write_str("bar") + } +} + +fn main() { + env_logger::init(); + if env::var("YOU_ARE_TESTING_NOW").is_ok() { + return info!("{}", Foo); + } + + let exe = env::current_exe().unwrap(); + let out = process::Command::new(exe) + .env("YOU_ARE_TESTING_NOW", "1") + .env("RUST_LOG", "debug") + .output() + .unwrap_or_else(|e| panic!("Unable to start child process: {}", e)); + if out.status.success() { + return; + } + + println!("test failed: {}", out.status); + println!("--- stdout\n{}", str::from_utf8(&out.stdout).unwrap()); + println!("--- stderr\n{}", str::from_utf8(&out.stderr).unwrap()); + process::exit(1); +} diff --git a/vendor/env_logger-0.8.4/tests/log_tls_dtors.rs b/vendor/env_logger-0.8.4/tests/log_tls_dtors.rs new file mode 100644 index 0000000000..5db87bd6c5 --- /dev/null +++ b/vendor/env_logger-0.8.4/tests/log_tls_dtors.rs @@ -0,0 +1,66 @@ +#[macro_use] +extern crate log; +extern crate env_logger; + +use std::env; +use std::process; +use std::str; +use std::thread; + +struct DropMe; + +impl Drop for DropMe { + fn drop(&mut self) { + debug!("Dropping now"); + } +} + +fn run() { + // Use multiple thread local values to increase the chance that our TLS + // value will get destroyed after the FORMATTER key in the library + thread_local! { + static DROP_ME_0: DropMe = DropMe; + static DROP_ME_1: DropMe = DropMe; + static DROP_ME_2: DropMe = DropMe; + static DROP_ME_3: DropMe = DropMe; + static DROP_ME_4: DropMe = DropMe; + static DROP_ME_5: DropMe = DropMe; + static DROP_ME_6: DropMe = DropMe; + static DROP_ME_7: DropMe = DropMe; + static DROP_ME_8: DropMe = DropMe; + static DROP_ME_9: DropMe = DropMe; + } + DROP_ME_0.with(|_| {}); + DROP_ME_1.with(|_| {}); + DROP_ME_2.with(|_| {}); + DROP_ME_3.with(|_| {}); + DROP_ME_4.with(|_| {}); + DROP_ME_5.with(|_| {}); + DROP_ME_6.with(|_| {}); + DROP_ME_7.with(|_| {}); + DROP_ME_8.with(|_| {}); + DROP_ME_9.with(|_| {}); +} + +fn main() { + env_logger::init(); + if env::var("YOU_ARE_TESTING_NOW").is_ok() { + // Run on a separate thread because TLS values on the main thread + // won't have their destructors run if pthread is used. + // https://doc.rust-lang.org/std/thread/struct.LocalKey.html#platform-specific-behavior + thread::spawn(run).join().unwrap(); + } else { + let exe = env::current_exe().unwrap(); + let out = process::Command::new(exe) + .env("YOU_ARE_TESTING_NOW", "1") + .env("RUST_LOG", "debug") + .output() + .unwrap_or_else(|e| panic!("Unable to start child process: {}", e)); + if !out.status.success() { + println!("test failed: {}", out.status); + println!("--- stdout\n{}", str::from_utf8(&out.stdout).unwrap()); + println!("--- stderr\n{}", str::from_utf8(&out.stderr).unwrap()); + process::exit(1); + } + } +} diff --git a/vendor/env_logger-0.8.4/tests/regexp_filter.rs b/vendor/env_logger-0.8.4/tests/regexp_filter.rs new file mode 100644 index 0000000000..40178bac7f --- /dev/null +++ b/vendor/env_logger-0.8.4/tests/regexp_filter.rs @@ -0,0 +1,57 @@ +#[macro_use] +extern crate log; +extern crate env_logger; + +use std::env; +use std::process; +use std::str; + +fn main() { + if env::var("LOG_REGEXP_TEST").ok() == Some(String::from("1")) { + child_main(); + } else { + parent_main() + } +} + +fn child_main() { + env_logger::init(); + info!("XYZ Message"); +} + +fn run_child(rust_log: String) -> bool { + let exe = env::current_exe().unwrap(); + let out = process::Command::new(exe) + .env("LOG_REGEXP_TEST", "1") + .env("RUST_LOG", rust_log) + .output() + .unwrap_or_else(|e| panic!("Unable to start child process: {}", e)); + str::from_utf8(out.stderr.as_ref()) + .unwrap() + .contains("XYZ Message") +} + +fn assert_message_printed(rust_log: &str) { + if !run_child(rust_log.to_string()) { + panic!("RUST_LOG={} should allow the test log message", rust_log) + } +} + +fn assert_message_not_printed(rust_log: &str) { + if run_child(rust_log.to_string()) { + panic!( + "RUST_LOG={} should not allow the test log message", + rust_log + ) + } +} + +fn parent_main() { + // test normal log severity levels + assert_message_printed("info"); + assert_message_not_printed("warn"); + + // test of regular expression filters + assert_message_printed("info/XYZ"); + assert_message_not_printed("info/XXX"); +} diff --git a/vendor/gimli/.cargo-checksum.json b/vendor/gimli-0.25.0/.cargo-checksum.json similarity index 100% rename from vendor/gimli/.cargo-checksum.json rename to vendor/gimli-0.25.0/.cargo-checksum.json diff --git a/vendor/gimli/CHANGELOG.md b/vendor/gimli-0.25.0/CHANGELOG.md similarity index 100% rename from vendor/gimli/CHANGELOG.md rename to vendor/gimli-0.25.0/CHANGELOG.md diff --git a/vendor/gimli/CONTRIBUTING.md b/vendor/gimli-0.25.0/CONTRIBUTING.md similarity index 100% rename from vendor/gimli/CONTRIBUTING.md rename to vendor/gimli-0.25.0/CONTRIBUTING.md diff --git a/vendor/gimli/Cargo.lock b/vendor/gimli-0.25.0/Cargo.lock similarity index 100% rename from vendor/gimli/Cargo.lock rename to vendor/gimli-0.25.0/Cargo.lock diff --git a/vendor/gimli/Cargo.toml b/vendor/gimli-0.25.0/Cargo.toml similarity index 100% rename from vendor/gimli/Cargo.toml rename to vendor/gimli-0.25.0/Cargo.toml diff --git a/vendor/object/LICENSE-APACHE b/vendor/gimli-0.25.0/LICENSE-APACHE similarity index 100% rename from vendor/object/LICENSE-APACHE rename to vendor/gimli-0.25.0/LICENSE-APACHE diff --git a/vendor/gimli/LICENSE-MIT b/vendor/gimli-0.25.0/LICENSE-MIT similarity index 100% rename from vendor/gimli/LICENSE-MIT rename to vendor/gimli-0.25.0/LICENSE-MIT diff --git a/vendor/gimli/README.md b/vendor/gimli-0.25.0/README.md similarity index 100% rename from vendor/gimli/README.md rename to vendor/gimli-0.25.0/README.md diff --git a/vendor/gimli/benches/bench.rs b/vendor/gimli-0.25.0/benches/bench.rs similarity index 100% rename from vendor/gimli/benches/bench.rs rename to vendor/gimli-0.25.0/benches/bench.rs diff --git a/vendor/gimli/examples/dwarf-validate.rs b/vendor/gimli-0.25.0/examples/dwarf-validate.rs similarity index 100% rename from vendor/gimli/examples/dwarf-validate.rs rename to vendor/gimli-0.25.0/examples/dwarf-validate.rs diff --git a/vendor/gimli/examples/dwarfdump.rs b/vendor/gimli-0.25.0/examples/dwarfdump.rs similarity index 100% rename from vendor/gimli/examples/dwarfdump.rs rename to vendor/gimli-0.25.0/examples/dwarfdump.rs diff --git a/vendor/gimli/examples/simple.rs b/vendor/gimli-0.25.0/examples/simple.rs similarity index 100% rename from vendor/gimli/examples/simple.rs rename to vendor/gimli-0.25.0/examples/simple.rs diff --git a/vendor/gimli/examples/simple_line.rs b/vendor/gimli-0.25.0/examples/simple_line.rs similarity index 100% rename from vendor/gimli/examples/simple_line.rs rename to vendor/gimli-0.25.0/examples/simple_line.rs diff --git a/vendor/gimli/fixtures/self/README.md b/vendor/gimli-0.25.0/fixtures/self/README.md similarity index 100% rename from vendor/gimli/fixtures/self/README.md rename to vendor/gimli-0.25.0/fixtures/self/README.md diff --git a/vendor/gimli/fixtures/self/debug_abbrev b/vendor/gimli-0.25.0/fixtures/self/debug_abbrev similarity index 100% rename from vendor/gimli/fixtures/self/debug_abbrev rename to vendor/gimli-0.25.0/fixtures/self/debug_abbrev diff --git a/vendor/gimli/fixtures/self/debug_aranges b/vendor/gimli-0.25.0/fixtures/self/debug_aranges similarity index 100% rename from vendor/gimli/fixtures/self/debug_aranges rename to vendor/gimli-0.25.0/fixtures/self/debug_aranges diff --git a/vendor/gimli/fixtures/self/debug_info b/vendor/gimli-0.25.0/fixtures/self/debug_info similarity index 100% rename from vendor/gimli/fixtures/self/debug_info rename to vendor/gimli-0.25.0/fixtures/self/debug_info diff --git a/vendor/gimli/fixtures/self/debug_inlined b/vendor/gimli-0.25.0/fixtures/self/debug_inlined similarity index 100% rename from vendor/gimli/fixtures/self/debug_inlined rename to vendor/gimli-0.25.0/fixtures/self/debug_inlined diff --git a/vendor/gimli/fixtures/self/debug_line b/vendor/gimli-0.25.0/fixtures/self/debug_line similarity index 100% rename from vendor/gimli/fixtures/self/debug_line rename to vendor/gimli-0.25.0/fixtures/self/debug_line diff --git a/vendor/gimli/fixtures/self/debug_loc b/vendor/gimli-0.25.0/fixtures/self/debug_loc similarity index 100% rename from vendor/gimli/fixtures/self/debug_loc rename to vendor/gimli-0.25.0/fixtures/self/debug_loc diff --git a/vendor/gimli/fixtures/self/debug_pubnames b/vendor/gimli-0.25.0/fixtures/self/debug_pubnames similarity index 100% rename from vendor/gimli/fixtures/self/debug_pubnames rename to vendor/gimli-0.25.0/fixtures/self/debug_pubnames diff --git a/vendor/gimli/fixtures/self/debug_pubtypes b/vendor/gimli-0.25.0/fixtures/self/debug_pubtypes similarity index 100% rename from vendor/gimli/fixtures/self/debug_pubtypes rename to vendor/gimli-0.25.0/fixtures/self/debug_pubtypes diff --git a/vendor/gimli/fixtures/self/debug_ranges b/vendor/gimli-0.25.0/fixtures/self/debug_ranges similarity index 100% rename from vendor/gimli/fixtures/self/debug_ranges rename to vendor/gimli-0.25.0/fixtures/self/debug_ranges diff --git a/vendor/gimli/fixtures/self/debug_str b/vendor/gimli-0.25.0/fixtures/self/debug_str similarity index 100% rename from vendor/gimli/fixtures/self/debug_str rename to vendor/gimli-0.25.0/fixtures/self/debug_str diff --git a/vendor/gimli/fixtures/self/eh_frame b/vendor/gimli-0.25.0/fixtures/self/eh_frame similarity index 100% rename from vendor/gimli/fixtures/self/eh_frame rename to vendor/gimli-0.25.0/fixtures/self/eh_frame diff --git a/vendor/gimli/fixtures/self/eh_frame_hdr b/vendor/gimli-0.25.0/fixtures/self/eh_frame_hdr similarity index 100% rename from vendor/gimli/fixtures/self/eh_frame_hdr rename to vendor/gimli-0.25.0/fixtures/self/eh_frame_hdr diff --git a/vendor/gimli-0.25.0/rustfmt.toml b/vendor/gimli-0.25.0/rustfmt.toml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/vendor/gimli/src/arch.rs b/vendor/gimli-0.25.0/src/arch.rs similarity index 100% rename from vendor/gimli/src/arch.rs rename to vendor/gimli-0.25.0/src/arch.rs diff --git a/vendor/gimli/src/common.rs b/vendor/gimli-0.25.0/src/common.rs similarity index 100% rename from vendor/gimli/src/common.rs rename to vendor/gimli-0.25.0/src/common.rs diff --git a/vendor/gimli/src/constants.rs b/vendor/gimli-0.25.0/src/constants.rs similarity index 100% rename from vendor/gimli/src/constants.rs rename to vendor/gimli-0.25.0/src/constants.rs diff --git a/vendor/gimli/src/endianity.rs b/vendor/gimli-0.25.0/src/endianity.rs similarity index 100% rename from vendor/gimli/src/endianity.rs rename to vendor/gimli-0.25.0/src/endianity.rs diff --git a/vendor/gimli/src/leb128.rs b/vendor/gimli-0.25.0/src/leb128.rs similarity index 100% rename from vendor/gimli/src/leb128.rs rename to vendor/gimli-0.25.0/src/leb128.rs diff --git a/vendor/gimli/src/lib.rs b/vendor/gimli-0.25.0/src/lib.rs similarity index 100% rename from vendor/gimli/src/lib.rs rename to vendor/gimli-0.25.0/src/lib.rs diff --git a/vendor/gimli/src/read/abbrev.rs b/vendor/gimli-0.25.0/src/read/abbrev.rs similarity index 100% rename from vendor/gimli/src/read/abbrev.rs rename to vendor/gimli-0.25.0/src/read/abbrev.rs diff --git a/vendor/gimli/src/read/addr.rs b/vendor/gimli-0.25.0/src/read/addr.rs similarity index 100% rename from vendor/gimli/src/read/addr.rs rename to vendor/gimli-0.25.0/src/read/addr.rs diff --git a/vendor/gimli/src/read/aranges.rs b/vendor/gimli-0.25.0/src/read/aranges.rs similarity index 100% rename from vendor/gimli/src/read/aranges.rs rename to vendor/gimli-0.25.0/src/read/aranges.rs diff --git a/vendor/gimli/src/read/cfi.rs b/vendor/gimli-0.25.0/src/read/cfi.rs similarity index 100% rename from vendor/gimli/src/read/cfi.rs rename to vendor/gimli-0.25.0/src/read/cfi.rs diff --git a/vendor/gimli/src/read/dwarf.rs b/vendor/gimli-0.25.0/src/read/dwarf.rs similarity index 100% rename from vendor/gimli/src/read/dwarf.rs rename to vendor/gimli-0.25.0/src/read/dwarf.rs diff --git a/vendor/gimli/src/read/endian_reader.rs b/vendor/gimli-0.25.0/src/read/endian_reader.rs similarity index 100% rename from vendor/gimli/src/read/endian_reader.rs rename to vendor/gimli-0.25.0/src/read/endian_reader.rs diff --git a/vendor/gimli/src/read/endian_slice.rs b/vendor/gimli-0.25.0/src/read/endian_slice.rs similarity index 100% rename from vendor/gimli/src/read/endian_slice.rs rename to vendor/gimli-0.25.0/src/read/endian_slice.rs diff --git a/vendor/gimli/src/read/line.rs b/vendor/gimli-0.25.0/src/read/line.rs similarity index 100% rename from vendor/gimli/src/read/line.rs rename to vendor/gimli-0.25.0/src/read/line.rs diff --git a/vendor/gimli/src/read/lists.rs b/vendor/gimli-0.25.0/src/read/lists.rs similarity index 100% rename from vendor/gimli/src/read/lists.rs rename to vendor/gimli-0.25.0/src/read/lists.rs diff --git a/vendor/gimli/src/read/loclists.rs b/vendor/gimli-0.25.0/src/read/loclists.rs similarity index 100% rename from vendor/gimli/src/read/loclists.rs rename to vendor/gimli-0.25.0/src/read/loclists.rs diff --git a/vendor/gimli/src/read/lookup.rs b/vendor/gimli-0.25.0/src/read/lookup.rs similarity index 100% rename from vendor/gimli/src/read/lookup.rs rename to vendor/gimli-0.25.0/src/read/lookup.rs diff --git a/vendor/gimli/src/read/mod.rs b/vendor/gimli-0.25.0/src/read/mod.rs similarity index 100% rename from vendor/gimli/src/read/mod.rs rename to vendor/gimli-0.25.0/src/read/mod.rs diff --git a/vendor/gimli/src/read/op.rs b/vendor/gimli-0.25.0/src/read/op.rs similarity index 100% rename from vendor/gimli/src/read/op.rs rename to vendor/gimli-0.25.0/src/read/op.rs diff --git a/vendor/gimli/src/read/pubnames.rs b/vendor/gimli-0.25.0/src/read/pubnames.rs similarity index 100% rename from vendor/gimli/src/read/pubnames.rs rename to vendor/gimli-0.25.0/src/read/pubnames.rs diff --git a/vendor/gimli/src/read/pubtypes.rs b/vendor/gimli-0.25.0/src/read/pubtypes.rs similarity index 100% rename from vendor/gimli/src/read/pubtypes.rs rename to vendor/gimli-0.25.0/src/read/pubtypes.rs diff --git a/vendor/gimli/src/read/reader.rs b/vendor/gimli-0.25.0/src/read/reader.rs similarity index 100% rename from vendor/gimli/src/read/reader.rs rename to vendor/gimli-0.25.0/src/read/reader.rs diff --git a/vendor/gimli/src/read/rnglists.rs b/vendor/gimli-0.25.0/src/read/rnglists.rs similarity index 100% rename from vendor/gimli/src/read/rnglists.rs rename to vendor/gimli-0.25.0/src/read/rnglists.rs diff --git a/vendor/gimli/src/read/str.rs b/vendor/gimli-0.25.0/src/read/str.rs similarity index 100% rename from vendor/gimli/src/read/str.rs rename to vendor/gimli-0.25.0/src/read/str.rs diff --git a/vendor/gimli/src/read/unit.rs b/vendor/gimli-0.25.0/src/read/unit.rs similarity index 100% rename from vendor/gimli/src/read/unit.rs rename to vendor/gimli-0.25.0/src/read/unit.rs diff --git a/vendor/gimli/src/read/value.rs b/vendor/gimli-0.25.0/src/read/value.rs similarity index 100% rename from vendor/gimli/src/read/value.rs rename to vendor/gimli-0.25.0/src/read/value.rs diff --git a/vendor/gimli/src/test_util.rs b/vendor/gimli-0.25.0/src/test_util.rs similarity index 100% rename from vendor/gimli/src/test_util.rs rename to vendor/gimli-0.25.0/src/test_util.rs diff --git a/vendor/gimli/src/write/abbrev.rs b/vendor/gimli-0.25.0/src/write/abbrev.rs similarity index 100% rename from vendor/gimli/src/write/abbrev.rs rename to vendor/gimli-0.25.0/src/write/abbrev.rs diff --git a/vendor/gimli/src/write/cfi.rs b/vendor/gimli-0.25.0/src/write/cfi.rs similarity index 100% rename from vendor/gimli/src/write/cfi.rs rename to vendor/gimli-0.25.0/src/write/cfi.rs diff --git a/vendor/gimli/src/write/dwarf.rs b/vendor/gimli-0.25.0/src/write/dwarf.rs similarity index 100% rename from vendor/gimli/src/write/dwarf.rs rename to vendor/gimli-0.25.0/src/write/dwarf.rs diff --git a/vendor/gimli/src/write/endian_vec.rs b/vendor/gimli-0.25.0/src/write/endian_vec.rs similarity index 100% rename from vendor/gimli/src/write/endian_vec.rs rename to vendor/gimli-0.25.0/src/write/endian_vec.rs diff --git a/vendor/gimli/src/write/line.rs b/vendor/gimli-0.25.0/src/write/line.rs similarity index 100% rename from vendor/gimli/src/write/line.rs rename to vendor/gimli-0.25.0/src/write/line.rs diff --git a/vendor/gimli/src/write/loc.rs b/vendor/gimli-0.25.0/src/write/loc.rs similarity index 100% rename from vendor/gimli/src/write/loc.rs rename to vendor/gimli-0.25.0/src/write/loc.rs diff --git a/vendor/gimli/src/write/mod.rs b/vendor/gimli-0.25.0/src/write/mod.rs similarity index 100% rename from vendor/gimli/src/write/mod.rs rename to vendor/gimli-0.25.0/src/write/mod.rs diff --git a/vendor/gimli/src/write/op.rs b/vendor/gimli-0.25.0/src/write/op.rs similarity index 100% rename from vendor/gimli/src/write/op.rs rename to vendor/gimli-0.25.0/src/write/op.rs diff --git a/vendor/gimli/src/write/range.rs b/vendor/gimli-0.25.0/src/write/range.rs similarity index 100% rename from vendor/gimli/src/write/range.rs rename to vendor/gimli-0.25.0/src/write/range.rs diff --git a/vendor/gimli/src/write/section.rs b/vendor/gimli-0.25.0/src/write/section.rs similarity index 100% rename from vendor/gimli/src/write/section.rs rename to vendor/gimli-0.25.0/src/write/section.rs diff --git a/vendor/gimli/src/write/str.rs b/vendor/gimli-0.25.0/src/write/str.rs similarity index 100% rename from vendor/gimli/src/write/str.rs rename to vendor/gimli-0.25.0/src/write/str.rs diff --git a/vendor/gimli/src/write/unit.rs b/vendor/gimli-0.25.0/src/write/unit.rs similarity index 100% rename from vendor/gimli/src/write/unit.rs rename to vendor/gimli-0.25.0/src/write/unit.rs diff --git a/vendor/gimli/src/write/writer.rs b/vendor/gimli-0.25.0/src/write/writer.rs similarity index 100% rename from vendor/gimli/src/write/writer.rs rename to vendor/gimli-0.25.0/src/write/writer.rs diff --git a/vendor/gimli/tests/convert_self.rs b/vendor/gimli-0.25.0/tests/convert_self.rs similarity index 100% rename from vendor/gimli/tests/convert_self.rs rename to vendor/gimli-0.25.0/tests/convert_self.rs diff --git a/vendor/gimli/tests/parse_self.rs b/vendor/gimli-0.25.0/tests/parse_self.rs similarity index 100% rename from vendor/gimli/tests/parse_self.rs rename to vendor/gimli-0.25.0/tests/parse_self.rs diff --git a/vendor/humantime/.cargo-checksum.json b/vendor/humantime/.cargo-checksum.json new file mode 100644 index 0000000000..a5277e4450 --- /dev/null +++ b/vendor/humantime/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"74afb84b99fa5ba0f58b483df1ef0749821d4c2b5c5a9df299cb1cc0002c236f","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"f6deca8261a8f4a3403dc74c725c46051157fd36c27cd4b100277eb1f303ad11","README.md":"e4bb65f28ddffb11d7eb337e9585947651f2fc11a5e4290f0ca126e21c582c1e","benches/datetime_format.rs":"ffe2e459e9b48e8fdbfb3686f6297257d66b29369ecd6750ae9fbba527ccc681","benches/datetime_parse.rs":"8039c4bd5f1795dbb54e1e39da5988f1d2df6c86c42d8fd378094fc78074d31e","bulk.yaml":"17c2548388e0cd3a63473021a2f1e4ddedee082d79d9167cb31ad06a1890d3fc","src/date.rs":"3f21e426f449e434e5973db9bd06a09d3f0cd6aa77708dbf0e3230bce7e48f44","src/duration.rs":"5a91e6e94c9ca2078ede527a4c159ddfc1cd67ade0d75a1c1db5474b40d2916f","src/lib.rs":"ad4dbed28080d9a64ef0100c96b20ff4988d9dde908f56e28ece7252f5932990","src/wrapper.rs":"badc640e77379a42b2fcb728337d60a764b7f00a1b5b1d50c7372ddc20941967","vagga.yaml":"8396fe1510117c1c7bc3e896b62290dcf2dd300346071297018b0077ad9e45ce"},"package":"3c1ad908cc71012b7bea4d0c53ba96a8cba9962f048fa68d143376143d863b7a"} \ No newline at end of file diff --git a/vendor/humantime/Cargo.toml b/vendor/humantime/Cargo.toml new file mode 100644 index 0000000000..8d58389519 --- /dev/null +++ b/vendor/humantime/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 = "humantime" +version = "2.0.1" +authors = ["Paul Colomiets <paul@colomiets.name>"] +description = " A parser and formatter for std::time::{Duration, SystemTime}\n" +homepage = "https://github.com/tailhook/humantime" +documentation = "https://docs.rs/humantime" +readme = "README.md" +keywords = ["time", "human", "human-friendly", "parser", "duration"] +categories = ["date-and-time"] +license = "MIT/Apache-2.0" +repository = "https://github.com/tailhook/humantime" + +[lib] +name = "humantime" +path = "src/lib.rs" +[dev-dependencies.chrono] +version = "0.4" + +[dev-dependencies.rand] +version = "0.6" + +[dev-dependencies.time] +version = "0.1" diff --git a/vendor/humantime/LICENSE-APACHE b/vendor/humantime/LICENSE-APACHE new file mode 100644 index 0000000000..8f71f43fee --- /dev/null +++ b/vendor/humantime/LICENSE-APACHE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/vendor/humantime/LICENSE-MIT b/vendor/humantime/LICENSE-MIT new file mode 100644 index 0000000000..a099fbade4 --- /dev/null +++ b/vendor/humantime/LICENSE-MIT @@ -0,0 +1,26 @@ +Copyright (c) 2016 The humantime Developers + +Includes parts of http date with the following copyright: +Copyright (c) 2016 Pyfisch + +Includes portions of musl libc with the following copyright: +Copyright © 2005-2013 Rich Felker + + +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/humantime/README.md b/vendor/humantime/README.md new file mode 100644 index 0000000000..39156dcdc9 --- /dev/null +++ b/vendor/humantime/README.md @@ -0,0 +1,68 @@ +Human Time +========== + +**Status: stable** + +[Documentation](https://docs.rs/humantime) | +[Github](https://github.com/tailhook/humantime) | +[Crate](https://crates.io/crates/humantime) + + +Features: + +* Parses durations in free form like `15days 2min 2s` +* Formats durations in similar form `2years 2min 12us` +* Parses and formats timestamp in `rfc3339` format: `2018-01-01T12:53:00Z` +* Parses timestamps in a weaker format: `2018-01-01 12:53:00` + +Timestamp parsing/formatting is super-fast because format is basically +fixed. + +Here are some micro-benchmarks: + +``` +test result: ok. 0 passed; 0 failed; 26 ignored; 0 measured; 0 filtered out + + Running target/release/deps/datetime_format-8facb4ac832d9770 + +running 2 tests +test rfc3339_chrono ... bench: 737 ns/iter (+/- 37) +test rfc3339_humantime_seconds ... bench: 73 ns/iter (+/- 2) + +test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured; 0 filtered out + + Running target/release/deps/datetime_parse-342628f877d7867c + +running 6 tests +test datetime_utc_parse_millis ... bench: 228 ns/iter (+/- 11) +test datetime_utc_parse_nanos ... bench: 236 ns/iter (+/- 10) +test datetime_utc_parse_seconds ... bench: 204 ns/iter (+/- 18) +test rfc3339_humantime_millis ... bench: 28 ns/iter (+/- 1) +test rfc3339_humantime_nanos ... bench: 36 ns/iter (+/- 2) +test rfc3339_humantime_seconds ... bench: 24 ns/iter (+/- 1) + +test result: ok. 0 passed; 0 failed; 0 ignored; 6 measured; 0 filtered out +``` + +See [humantime-serde] for serde integration (previous crate [serde-humantime] looks unmaintained). + +[serde-humantime]: https://docs.rs/serde-humantime/0.1.1/serde_humantime/ +[humantime-serde]: https://docs.rs/humantime-serde + +License +======= + +Licensed under either of + +* Apache License, Version 2.0, (./LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) +* MIT license (./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/humantime/benches/datetime_format.rs b/vendor/humantime/benches/datetime_format.rs new file mode 100644 index 0000000000..77d47667c0 --- /dev/null +++ b/vendor/humantime/benches/datetime_format.rs @@ -0,0 +1,56 @@ +#![feature(test)] +extern crate test; + +use std::io::Write; +use std::time::{Duration, UNIX_EPOCH}; + +use humantime::format_rfc3339; + +#[bench] +fn rfc3339_humantime_seconds(b: &mut test::Bencher) { + let time = UNIX_EPOCH + Duration::new(1_483_228_799, 0); + let mut buf = Vec::with_capacity(100); + b.iter(|| { + buf.truncate(0); + write!(&mut buf, "{}", format_rfc3339(time)).unwrap() + }); +} + +#[bench] +fn rfc3339_chrono(b: &mut test::Bencher) { + use chrono::{DateTime, NaiveDateTime, Utc}; + use chrono::format::Item; + use chrono::format::Item::*; + use chrono::format::Numeric::*; + use chrono::format::Fixed::*; + use chrono::format::Pad::*; + + let time = DateTime::<Utc>::from_utc( + NaiveDateTime::from_timestamp(1_483_228_799, 0), Utc); + let mut buf = Vec::with_capacity(100); + + // formatting code from env_logger + const ITEMS: &[Item<'static>] = { + &[ + Numeric(Year, Zero), + Literal("-"), + Numeric(Month, Zero), + Literal("-"), + Numeric(Day, Zero), + Literal("T"), + Numeric(Hour, Zero), + Literal(":"), + Numeric(Minute, Zero), + Literal(":"), + Numeric(Second, Zero), + Fixed(TimezoneOffsetZ), + ] + }; + + + b.iter(|| { + buf.truncate(0); + write!(&mut buf, "{}", time.format_with_items(ITEMS.iter().cloned())) + .unwrap() + }); +} diff --git a/vendor/humantime/benches/datetime_parse.rs b/vendor/humantime/benches/datetime_parse.rs new file mode 100644 index 0000000000..4248da281e --- /dev/null +++ b/vendor/humantime/benches/datetime_parse.rs @@ -0,0 +1,47 @@ +#![feature(test)] +extern crate test; + +use chrono::{DateTime}; +use humantime::parse_rfc3339; + +#[bench] +fn rfc3339_humantime_seconds(b: &mut test::Bencher) { + b.iter(|| { + parse_rfc3339("2018-02-13T23:08:32Z").unwrap() + }); +} + +#[bench] +fn datetime_utc_parse_seconds(b: &mut test::Bencher) { + b.iter(|| { + DateTime::parse_from_rfc3339("2018-02-13T23:08:32Z").unwrap() + }); +} + +#[bench] +fn rfc3339_humantime_millis(b: &mut test::Bencher) { + b.iter(|| { + parse_rfc3339("2018-02-13T23:08:32.123Z").unwrap() + }); +} + +#[bench] +fn datetime_utc_parse_millis(b: &mut test::Bencher) { + b.iter(|| { + DateTime::parse_from_rfc3339("2018-02-13T23:08:32.123Z").unwrap() + }); +} + +#[bench] +fn rfc3339_humantime_nanos(b: &mut test::Bencher) { + b.iter(|| { + parse_rfc3339("2018-02-13T23:08:32.123456983Z").unwrap() + }); +} + +#[bench] +fn datetime_utc_parse_nanos(b: &mut test::Bencher) { + b.iter(|| { + DateTime::parse_from_rfc3339("2018-02-13T23:08:32.123456983Z").unwrap() + }); +} diff --git a/vendor/humantime/bulk.yaml b/vendor/humantime/bulk.yaml new file mode 100644 index 0000000000..cdb9763b67 --- /dev/null +++ b/vendor/humantime/bulk.yaml @@ -0,0 +1,8 @@ +minimum-bulk: v0.4.5 + +versions: + +- file: Cargo.toml + block-start: ^\[package\] + block-end: ^\[.*\] + regex: ^version\s*=\s*"(\S+)" diff --git a/vendor/humantime/src/date.rs b/vendor/humantime/src/date.rs new file mode 100644 index 0000000000..0afe1f2509 --- /dev/null +++ b/vendor/humantime/src/date.rs @@ -0,0 +1,616 @@ +use std::error::Error as StdError; +use std::fmt; +use std::str; +use std::time::{SystemTime, Duration, UNIX_EPOCH}; + +#[cfg(target_os="cloudabi")] +mod max { + pub const SECONDS: u64 = ::std::u64::MAX / 1_000_000_000; + #[allow(unused)] + pub const TIMESTAMP: &'static str = "2554-07-21T23:34:33Z"; +} +#[cfg(all( + target_pointer_width="32", + not(target_os="cloudabi"), + not(target_os="windows"), + not(all(target_arch="wasm32", not(target_os="emscripten"))) +))] +mod max { + pub const SECONDS: u64 = ::std::i32::MAX as u64; + #[allow(unused)] + pub const TIMESTAMP: &'static str = "2038-01-19T03:14:07Z"; +} + +#[cfg(any( + target_pointer_width="64", + target_os="windows", + all(target_arch="wasm32", not(target_os="emscripten")), +))] +mod max { + pub const SECONDS: u64 = 253_402_300_800-1; // last second of year 9999 + #[allow(unused)] + pub const TIMESTAMP: &str = "9999-12-31T23:59:59Z"; +} + +/// Error parsing datetime (timestamp) +#[derive(Debug, PartialEq, Clone, Copy)] +pub enum Error { + /// Numeric component is out of range + OutOfRange, + /// Bad character where digit is expected + InvalidDigit, + /// Other formatting errors + InvalidFormat, +} + +impl StdError for Error {} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Error::OutOfRange => write!(f, "numeric component is out of range"), + Error::InvalidDigit => write!(f, "bad character where digit is expected"), + Error::InvalidFormat => write!(f, "timestamp format is invalid"), + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +enum Precision { + Smart, + Seconds, + Millis, + Micros, + Nanos, +} + +/// A wrapper type that allows you to Display a SystemTime +#[derive(Debug, Clone)] +pub struct Rfc3339Timestamp(SystemTime, Precision); + +#[inline] +fn two_digits(b1: u8, b2: u8) -> Result<u64, Error> { + if b1 < b'0' || b2 < b'0' || b1 > b'9' || b2 > b'9' { + return Err(Error::InvalidDigit); + } + Ok(((b1 - b'0')*10 + (b2 - b'0')) as u64) +} + +/// Parse RFC3339 timestamp `2018-02-14T00:28:07Z` +/// +/// Supported feature: any precision of fractional +/// digits `2018-02-14T00:28:07.133Z`. +/// +/// Unsupported feature: localized timestamps. Only UTC is supported. +pub fn parse_rfc3339(s: &str) -> Result<SystemTime, Error> { + if s.len() < "2018-02-14T00:28:07Z".len() { + return Err(Error::InvalidFormat); + } + let b = s.as_bytes(); + if b[10] != b'T' || b[b.len()-1] != b'Z' { + return Err(Error::InvalidFormat); + } + parse_rfc3339_weak(s) +} + +/// Parse RFC3339-like timestamp `2018-02-14 00:28:07` +/// +/// Supported features: +/// +/// 1. Any precision of fractional digits `2018-02-14 00:28:07.133`. +/// 2. Supports timestamp with or without either of `T` or `Z` +/// 3. Anything valid for `parse_3339` is valid for this function +/// +/// Unsupported feature: localized timestamps. Only UTC is supported, even if +/// `Z` is not specified. +/// +/// This function is intended to use for parsing human input. Whereas +/// `parse_rfc3339` is for strings generated programmatically. +pub fn parse_rfc3339_weak(s: &str) -> Result<SystemTime, Error> { + if s.len() < "2018-02-14T00:28:07".len() { + return Err(Error::InvalidFormat); + } + let b = s.as_bytes(); // for careless slicing + if b[4] != b'-' || b[7] != b'-' || (b[10] != b'T' && b[10] != b' ') || + b[13] != b':' || b[16] != b':' + { + return Err(Error::InvalidFormat); + } + let year = two_digits(b[0], b[1])? * 100 + two_digits(b[2], b[3])?; + let month = two_digits(b[5], b[6])?; + let day = two_digits(b[8], b[9])?; + let hour = two_digits(b[11], b[12])?; + let minute = two_digits(b[14], b[15])?; + let mut second = two_digits(b[17], b[18])?; + + if year < 1970 || hour > 23 || minute > 59 || second > 60 { + return Err(Error::OutOfRange); + } + // TODO(tailhook) should we check that leaps second is only on midnight ? + if second == 60 { + second = 59 + }; + let leap_years = ((year - 1) - 1968) / 4 - ((year - 1) - 1900) / 100 + + ((year - 1) - 1600) / 400; + let leap = is_leap_year(year); + let (mut ydays, mdays) = match month { + 1 => (0, 31), + 2 if leap => (31, 29), + 2 => (31, 28), + 3 => (59, 31), + 4 => (90, 30), + 5 => (120, 31), + 6 => (151, 30), + 7 => (181, 31), + 8 => (212, 31), + 9 => (243, 30), + 10 => (273, 31), + 11 => (304, 30), + 12 => (334, 31), + _ => return Err(Error::OutOfRange), + }; + if day > mdays || day == 0 { + return Err(Error::OutOfRange); + } + ydays += day - 1; + if leap && month > 2 { + ydays += 1; + } + let days = (year - 1970) * 365 + leap_years + ydays; + + let time = second + minute * 60 + hour * 3600; + + let mut nanos = 0; + let mut mult = 100_000_000; + if b.get(19) == Some(&b'.') { + for idx in 20..b.len() { + if b[idx] == b'Z' { + if idx == b.len()-1 { + break; + } else { + return Err(Error::InvalidDigit); + } + } + if b[idx] < b'0' || b[idx] > b'9' { + return Err(Error::InvalidDigit); + } + nanos += mult * (b[idx] - b'0') as u32; + mult /= 10; + } + } else if b.len() != 19 && (b.len() > 20 || b[19] != b'Z') { + return Err(Error::InvalidFormat); + } + + let total_seconds = time + days * 86400; + if total_seconds > max::SECONDS { + return Err(Error::OutOfRange); + } + + Ok(UNIX_EPOCH + Duration::new(total_seconds, nanos)) +} + +fn is_leap_year(y: u64) -> bool { + y % 4 == 0 && (y % 100 != 0 || y % 400 == 0) +} + +/// Format an RFC3339 timestamp `2018-02-14T00:28:07Z` +/// +/// This function formats timestamp with smart precision: i.e. if it has no +/// fractional seconds, they aren't written at all. And up to nine digits if +/// they are. +/// +/// The value is always UTC and ignores system timezone. +pub fn format_rfc3339(system_time: SystemTime) -> Rfc3339Timestamp { + Rfc3339Timestamp(system_time, Precision::Smart) +} + +/// Format an RFC3339 timestamp `2018-02-14T00:28:07Z` +/// +/// This format always shows timestamp without fractional seconds. +/// +/// The value is always UTC and ignores system timezone. +pub fn format_rfc3339_seconds(system_time: SystemTime) -> Rfc3339Timestamp { + Rfc3339Timestamp(system_time, Precision::Seconds) +} + +/// Format an RFC3339 timestamp `2018-02-14T00:28:07.000Z` +/// +/// This format always shows milliseconds even if millisecond value is zero. +/// +/// The value is always UTC and ignores system timezone. +pub fn format_rfc3339_millis(system_time: SystemTime) -> Rfc3339Timestamp { + Rfc3339Timestamp(system_time, Precision::Millis) +} + +/// Format an RFC3339 timestamp `2018-02-14T00:28:07.000000Z` +/// +/// This format always shows microseconds even if microsecond value is zero. +/// +/// The value is always UTC and ignores system timezone. +pub fn format_rfc3339_micros(system_time: SystemTime) -> Rfc3339Timestamp { + Rfc3339Timestamp(system_time, Precision::Micros) +} + +/// Format an RFC3339 timestamp `2018-02-14T00:28:07.000000000Z` +/// +/// This format always shows nanoseconds even if nanosecond value is zero. +/// +/// The value is always UTC and ignores system timezone. +pub fn format_rfc3339_nanos(system_time: SystemTime) -> Rfc3339Timestamp { + Rfc3339Timestamp(system_time, Precision::Nanos) +} + +impl fmt::Display for Rfc3339Timestamp { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use self::Precision::*; + + let dur = self.0.duration_since(UNIX_EPOCH) + .expect("all times should be after the epoch"); + let secs_since_epoch = dur.as_secs(); + let nanos = dur.subsec_nanos(); + + if secs_since_epoch >= 253_402_300_800 { // year 9999 + return Err(fmt::Error); + } + + /* 2000-03-01 (mod 400 year, immediately after feb29 */ + const LEAPOCH: i64 = 11017; + const DAYS_PER_400Y: i64 = 365*400 + 97; + const DAYS_PER_100Y: i64 = 365*100 + 24; + const DAYS_PER_4Y: i64 = 365*4 + 1; + + let days = (secs_since_epoch / 86400) as i64 - LEAPOCH; + let secs_of_day = secs_since_epoch % 86400; + + let mut qc_cycles = days / DAYS_PER_400Y; + let mut remdays = days % DAYS_PER_400Y; + + if remdays < 0 { + remdays += DAYS_PER_400Y; + qc_cycles -= 1; + } + + let mut c_cycles = remdays / DAYS_PER_100Y; + if c_cycles == 4 { c_cycles -= 1; } + remdays -= c_cycles * DAYS_PER_100Y; + + let mut q_cycles = remdays / DAYS_PER_4Y; + if q_cycles == 25 { q_cycles -= 1; } + remdays -= q_cycles * DAYS_PER_4Y; + + let mut remyears = remdays / 365; + if remyears == 4 { remyears -= 1; } + remdays -= remyears * 365; + + let mut year = 2000 + + remyears + 4*q_cycles + 100*c_cycles + 400*qc_cycles; + + let months = [31,30,31,30,31,31,30,31,30,31,31,29]; + let mut mon = 0; + for mon_len in months.iter() { + mon += 1; + if remdays < *mon_len { + break; + } + remdays -= *mon_len; + } + let mday = remdays+1; + let mon = if mon + 2 > 12 { + year += 1; + mon - 10 + } else { + mon + 2 + }; + + let mut buf: [u8; 30] = [ + // Too long to write as: b"0000-00-00T00:00:00.000000000Z" + b'0', b'0', b'0', b'0', b'-', b'0', b'0', b'-', b'0', b'0', b'T', + b'0', b'0', b':', b'0', b'0', b':', b'0', b'0', + b'.', b'0', b'0', b'0', b'0', b'0', b'0', b'0', b'0', b'0', b'Z', + ]; + buf[0] = b'0' + (year / 1000) as u8; + buf[1] = b'0' + (year / 100 % 10) as u8; + buf[2] = b'0' + (year / 10 % 10) as u8; + buf[3] = b'0' + (year % 10) as u8; + buf[5] = b'0' + (mon / 10) as u8; + buf[6] = b'0' + (mon % 10) as u8; + buf[8] = b'0' + (mday / 10) as u8; + buf[9] = b'0' + (mday % 10) as u8; + buf[11] = b'0' + (secs_of_day / 3600 / 10) as u8; + buf[12] = b'0' + (secs_of_day / 3600 % 10) as u8; + buf[14] = b'0' + (secs_of_day / 60 / 10 % 6) as u8; + buf[15] = b'0' + (secs_of_day / 60 % 10) as u8; + buf[17] = b'0' + (secs_of_day / 10 % 6) as u8; + buf[18] = b'0' + (secs_of_day % 10) as u8; + + let offset = if self.1 == Seconds || nanos == 0 && self.1 == Smart { + buf[19] = b'Z'; + 19 + } else if self.1 == Millis { + buf[20] = b'0' + (nanos / 100_000_000) as u8; + buf[21] = b'0' + (nanos / 10_000_000 % 10) as u8; + buf[22] = b'0' + (nanos / 1_000_000 % 10) as u8; + buf[23] = b'Z'; + 23 + } else if self.1 == Micros { + buf[20] = b'0' + (nanos / 100_000_000) as u8; + buf[21] = b'0' + (nanos / 10_000_000 % 10) as u8; + buf[22] = b'0' + (nanos / 1_000_000 % 10) as u8; + buf[23] = b'0' + (nanos / 100_000 % 10) as u8; + buf[24] = b'0' + (nanos / 10_000 % 10) as u8; + buf[25] = b'0' + (nanos / 1_000 % 10) as u8; + buf[26] = b'Z'; + 26 + } else { + buf[20] = b'0' + (nanos / 100_000_000) as u8; + buf[21] = b'0' + (nanos / 10_000_000 % 10) as u8; + buf[22] = b'0' + (nanos / 1_000_000 % 10) as u8; + buf[23] = b'0' + (nanos / 100_000 % 10) as u8; + buf[24] = b'0' + (nanos / 10_000 % 10) as u8; + buf[25] = b'0' + (nanos / 1_000 % 10) as u8; + buf[26] = b'0' + (nanos / 100 % 10) as u8; + buf[27] = b'0' + (nanos / 10 % 10) as u8; + buf[28] = b'0' + (nanos / 1 % 10) as u8; + // 29th is 'Z' + 29 + }; + + // we know our chars are all ascii + f.write_str(str::from_utf8(&buf[..=offset]).expect("Conversion to utf8 failed")) + } +} + +#[cfg(test)] +mod test { + use std::str::from_utf8; + use std::time::{UNIX_EPOCH, SystemTime, Duration}; + + use rand::Rng; + + use super::{parse_rfc3339, parse_rfc3339_weak, format_rfc3339}; + use super::{format_rfc3339_millis, format_rfc3339_micros}; + use super::{format_rfc3339_nanos}; + use super::max; + + fn from_sec(sec: u64) -> (String, SystemTime) { + let s = time::at_utc(time::Timespec { sec: sec as i64, nsec: 0 }) + .rfc3339().to_string(); + let time = UNIX_EPOCH + Duration::new(sec, 0); + (s, time) + } + + #[test] + #[cfg(all(target_pointer_width="32", target_os="linux"))] + fn year_after_2038_fails_gracefully() { + // next second + assert_eq!(parse_rfc3339("2038-01-19T03:14:08Z").unwrap_err(), + super::Error::OutOfRange); + assert_eq!(parse_rfc3339("9999-12-31T23:59:59Z").unwrap_err(), + super::Error::OutOfRange); + } + + #[test] + fn smoke_tests_parse() { + assert_eq!(parse_rfc3339("1970-01-01T00:00:00Z").unwrap(), + UNIX_EPOCH + Duration::new(0, 0)); + assert_eq!(parse_rfc3339("1970-01-01T00:00:01Z").unwrap(), + UNIX_EPOCH + Duration::new(1, 0)); + assert_eq!(parse_rfc3339("2018-02-13T23:08:32Z").unwrap(), + UNIX_EPOCH + Duration::new(1_518_563_312, 0)); + assert_eq!(parse_rfc3339("2012-01-01T00:00:00Z").unwrap(), + UNIX_EPOCH + Duration::new(1_325_376_000, 0)); + } + + #[test] + fn smoke_tests_format() { + assert_eq!( + format_rfc3339(UNIX_EPOCH + Duration::new(0, 0)).to_string(), + "1970-01-01T00:00:00Z"); + assert_eq!( + format_rfc3339(UNIX_EPOCH + Duration::new(1, 0)).to_string(), + "1970-01-01T00:00:01Z"); + assert_eq!( + format_rfc3339(UNIX_EPOCH + Duration::new(1_518_563_312, 0)).to_string(), + "2018-02-13T23:08:32Z"); + assert_eq!( + format_rfc3339(UNIX_EPOCH + Duration::new(1_325_376_000, 0)).to_string(), + "2012-01-01T00:00:00Z"); + } + + #[test] + fn smoke_tests_format_millis() { + assert_eq!( + format_rfc3339_millis(UNIX_EPOCH + + Duration::new(0, 0)).to_string(), + "1970-01-01T00:00:00.000Z"); + assert_eq!( + format_rfc3339_millis(UNIX_EPOCH + + Duration::new(1_518_563_312, 123_000_000)).to_string(), + "2018-02-13T23:08:32.123Z"); + } + + #[test] + fn smoke_tests_format_micros() { + assert_eq!( + format_rfc3339_micros(UNIX_EPOCH + + Duration::new(0, 0)).to_string(), + "1970-01-01T00:00:00.000000Z"); + assert_eq!( + format_rfc3339_micros(UNIX_EPOCH + + Duration::new(1_518_563_312, 123_000_000)).to_string(), + "2018-02-13T23:08:32.123000Z"); + assert_eq!( + format_rfc3339_micros(UNIX_EPOCH + + Duration::new(1_518_563_312, 456_123_000)).to_string(), + "2018-02-13T23:08:32.456123Z"); + } + + #[test] + fn smoke_tests_format_nanos() { + assert_eq!( + format_rfc3339_nanos(UNIX_EPOCH + + Duration::new(0, 0)).to_string(), + "1970-01-01T00:00:00.000000000Z"); + assert_eq!( + format_rfc3339_nanos(UNIX_EPOCH + + Duration::new(1_518_563_312, 123_000_000)).to_string(), + "2018-02-13T23:08:32.123000000Z"); + assert_eq!( + format_rfc3339_nanos(UNIX_EPOCH + + Duration::new(1_518_563_312, 789_456_123)).to_string(), + "2018-02-13T23:08:32.789456123Z"); + } + + #[test] + fn upper_bound() { + let max = UNIX_EPOCH + Duration::new(max::SECONDS, 0); + assert_eq!(parse_rfc3339(&max::TIMESTAMP).unwrap(), max); + assert_eq!(format_rfc3339(max).to_string(), max::TIMESTAMP); + } + + #[test] + fn leap_second() { + assert_eq!(parse_rfc3339("2016-12-31T23:59:60Z").unwrap(), + UNIX_EPOCH + Duration::new(1_483_228_799, 0)); + } + + #[test] + fn first_731_days() { + let year_start = 0; // 1970 + for day in 0..= 365 * 2 { // scan leap year and non-leap year + let (s, time) = from_sec(year_start + day * 86400); + assert_eq!(parse_rfc3339(&s).unwrap(), time); + assert_eq!(format_rfc3339(time).to_string(), s); + } + } + + #[test] + fn the_731_consecutive_days() { + let year_start = 1_325_376_000; // 2012 + for day in 0..= 365 * 2 { // scan leap year and non-leap year + let (s, time) = from_sec(year_start + day * 86400); + assert_eq!(parse_rfc3339(&s).unwrap(), time); + assert_eq!(format_rfc3339(time).to_string(), s); + } + } + + #[test] + fn all_86400_seconds() { + let day_start = 1_325_376_000; + for second in 0..86400 { // scan leap year and non-leap year + let (s, time) = from_sec(day_start + second); + assert_eq!(parse_rfc3339(&s).unwrap(), time); + assert_eq!(format_rfc3339(time).to_string(), s); + } + } + + #[test] + fn random_past() { + let upper = SystemTime::now().duration_since(UNIX_EPOCH).unwrap() + .as_secs(); + for _ in 0..10000 { + let sec = rand::thread_rng().gen_range(0, upper); + let (s, time) = from_sec(sec); + assert_eq!(parse_rfc3339(&s).unwrap(), time); + assert_eq!(format_rfc3339(time).to_string(), s); + } + } + + #[test] + fn random_wide_range() { + for _ in 0..100_000 { + let sec = rand::thread_rng().gen_range(0, max::SECONDS); + let (s, time) = from_sec(sec); + assert_eq!(parse_rfc3339(&s).unwrap(), time); + assert_eq!(format_rfc3339(time).to_string(), s); + } + } + + #[test] + fn milliseconds() { + assert_eq!(parse_rfc3339("1970-01-01T00:00:00.123Z").unwrap(), + UNIX_EPOCH + Duration::new(0, 123_000_000)); + assert_eq!(format_rfc3339(UNIX_EPOCH + Duration::new(0, 123_000_000)) + .to_string(), "1970-01-01T00:00:00.123000000Z"); + } + + #[test] + #[should_panic(expected="OutOfRange")] + fn zero_month() { + parse_rfc3339("1970-00-01T00:00:00Z").unwrap(); + } + + #[test] + #[should_panic(expected="OutOfRange")] + fn big_month() { + parse_rfc3339("1970-32-01T00:00:00Z").unwrap(); + } + + #[test] + #[should_panic(expected="OutOfRange")] + fn zero_day() { + parse_rfc3339("1970-01-00T00:00:00Z").unwrap(); + } + + #[test] + #[should_panic(expected="OutOfRange")] + fn big_day() { + parse_rfc3339("1970-12-35T00:00:00Z").unwrap(); + } + + #[test] + #[should_panic(expected="OutOfRange")] + fn big_day2() { + parse_rfc3339("1970-02-30T00:00:00Z").unwrap(); + } + + #[test] + #[should_panic(expected="OutOfRange")] + fn big_second() { + parse_rfc3339("1970-12-30T00:00:78Z").unwrap(); + } + + #[test] + #[should_panic(expected="OutOfRange")] + fn big_minute() { + parse_rfc3339("1970-12-30T00:78:00Z").unwrap(); + } + + #[test] + #[should_panic(expected="OutOfRange")] + fn big_hour() { + parse_rfc3339("1970-12-30T24:00:00Z").unwrap(); + } + + #[test] + fn break_data() { + for pos in 0.."2016-12-31T23:59:60Z".len() { + let mut s = b"2016-12-31T23:59:60Z".to_vec(); + s[pos] = b'x'; + parse_rfc3339(from_utf8(&s).unwrap()).unwrap_err(); + } + } + + #[test] + fn weak_smoke_tests() { + assert_eq!(parse_rfc3339_weak("1970-01-01 00:00:00").unwrap(), + UNIX_EPOCH + Duration::new(0, 0)); + parse_rfc3339("1970-01-01 00:00:00").unwrap_err(); + + assert_eq!(parse_rfc3339_weak("1970-01-01 00:00:00.000123").unwrap(), + UNIX_EPOCH + Duration::new(0, 123_000)); + parse_rfc3339("1970-01-01 00:00:00.000123").unwrap_err(); + + assert_eq!(parse_rfc3339_weak("1970-01-01T00:00:00.000123").unwrap(), + UNIX_EPOCH + Duration::new(0, 123_000)); + parse_rfc3339("1970-01-01T00:00:00.000123").unwrap_err(); + + assert_eq!(parse_rfc3339_weak("1970-01-01 00:00:00.000123Z").unwrap(), + UNIX_EPOCH + Duration::new(0, 123_000)); + parse_rfc3339("1970-01-01 00:00:00.000123Z").unwrap_err(); + + assert_eq!(parse_rfc3339_weak("1970-01-01 00:00:00Z").unwrap(), + UNIX_EPOCH + Duration::new(0, 0)); + parse_rfc3339("1970-01-01 00:00:00Z").unwrap_err(); + } +} diff --git a/vendor/humantime/src/duration.rs b/vendor/humantime/src/duration.rs new file mode 100644 index 0000000000..8359b851db --- /dev/null +++ b/vendor/humantime/src/duration.rs @@ -0,0 +1,449 @@ +use std::error::Error as StdError; +use std::fmt; +use std::str::Chars; +use std::time::Duration; + +/// Error parsing human-friendly duration +#[derive(Debug, PartialEq, Clone)] +pub enum Error { + /// Invalid character during parsing + /// + /// More specifically anything that is not alphanumeric is prohibited + /// + /// The field is an byte offset of the character in the string. + InvalidCharacter(usize), + /// Non-numeric value where number is expected + /// + /// This usually means that either time unit is broken into words, + /// e.g. `m sec` instead of `msec`, or just number is omitted, + /// for example `2 hours min` instead of `2 hours 1 min` + /// + /// The field is an byte offset of the errorneous character + /// in the string. + NumberExpected(usize), + /// Unit in the number is not one of allowed units + /// + /// See documentation of `parse_duration` for the list of supported + /// time units. + /// + /// The two fields are start and end (exclusive) of the slice from + /// the original string, containing errorneous value + UnknownUnit { + /// Start of the invalid unit inside the original string + start: usize, + /// End of the invalid unit inside the original string + end: usize, + /// The unit verbatim + unit: String, + /// A number associated with the unit + value: u64, + }, + /// The numeric value is too large + /// + /// Usually this means value is too large to be useful. If user writes + /// data in subsecond units, then the maximum is about 3k years. When + /// using seconds, or larger units, the limit is even larger. + NumberOverflow, + /// The value was an empty string (or consists only whitespace) + Empty, +} + +impl StdError for Error {} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Error::InvalidCharacter(offset) => write!(f, "invalid character at {}", offset), + Error::NumberExpected(offset) => write!(f, "expected number at {}", offset), + Error::UnknownUnit { unit, value, .. } if &unit == &"" => { + write!(f, + "time unit needed, for example {0}sec or {0}ms", + value, + ) + } + Error::UnknownUnit { unit, .. } => { + write!( + f, + "unknown time unit {:?}, \ + supported units: ns, us, ms, sec, min, hours, days, \ + weeks, months, years (and few variations)", + unit + ) + } + Error::NumberOverflow => write!(f, "number is too large"), + Error::Empty => write!(f, "value was empty"), + } + } +} + +/// A wrapper type that allows you to Display a Duration +#[derive(Debug, Clone)] +pub struct FormattedDuration(Duration); + +trait OverflowOp: Sized { + fn mul(self, other: Self) -> Result<Self, Error>; + fn add(self, other: Self) -> Result<Self, Error>; +} + +impl OverflowOp for u64 { + fn mul(self, other: Self) -> Result<Self, Error> { + self.checked_mul(other).ok_or(Error::NumberOverflow) + } + fn add(self, other: Self) -> Result<Self, Error> { + self.checked_add(other).ok_or(Error::NumberOverflow) + } +} + +struct Parser<'a> { + iter: Chars<'a>, + src: &'a str, + current: (u64, u64), +} + +impl<'a> Parser<'a> { + fn off(&self) -> usize { + self.src.len() - self.iter.as_str().len() + } + + fn parse_first_char(&mut self) -> Result<Option<u64>, Error> { + let off = self.off(); + for c in self.iter.by_ref() { + match c { + '0'..='9' => { + return Ok(Some(c as u64 - '0' as u64)); + } + c if c.is_whitespace() => continue, + _ => { + return Err(Error::NumberExpected(off)); + } + } + } + Ok(None) + } + fn parse_unit(&mut self, n: u64, start: usize, end: usize) + -> Result<(), Error> + { + let (mut sec, nsec) = match &self.src[start..end] { + "nanos" | "nsec" | "ns" => (0u64, n), + "usec" | "us" => (0u64, n.mul(1000)?), + "millis" | "msec" | "ms" => (0u64, n.mul(1_000_000)?), + "seconds" | "second" | "secs" | "sec" | "s" => (n, 0), + "minutes" | "minute" | "min" | "mins" | "m" + => (n.mul(60)?, 0), + "hours" | "hour" | "hr" | "hrs" | "h" => (n.mul(3600)?, 0), + "days" | "day" | "d" => (n.mul(86400)?, 0), + "weeks" | "week" | "w" => (n.mul(86400*7)?, 0), + "months" | "month" | "M" => (n.mul(2_630_016)?, 0), // 30.44d + "years" | "year" | "y" => (n.mul(31_557_600)?, 0), // 365.25d + _ => { + return Err(Error::UnknownUnit { + start, end, + unit: self.src[start..end].to_string(), + value: n, + }); + } + }; + let mut nsec = self.current.1.add(nsec)?; + if nsec > 1_000_000_000 { + sec = sec.add(nsec / 1_000_000_000)?; + nsec %= 1_000_000_000; + } + sec = self.current.0.add(sec)?; + self.current = (sec, nsec); + Ok(()) + } + + fn parse(mut self) -> Result<Duration, Error> { + let mut n = self.parse_first_char()?.ok_or(Error::Empty)?; + 'outer: loop { + let mut off = self.off(); + while let Some(c) = self.iter.next() { + match c { + '0'..='9' => { + n = n.checked_mul(10) + .and_then(|x| x.checked_add(c as u64 - '0' as u64)) + .ok_or(Error::NumberOverflow)?; + } + c if c.is_whitespace() => {} + 'a'..='z' | 'A'..='Z' => { + break; + } + _ => { + return Err(Error::InvalidCharacter(off)); + } + } + off = self.off(); + } + let start = off; + let mut off = self.off(); + while let Some(c) = self.iter.next() { + match c { + '0'..='9' => { + self.parse_unit(n, start, off)?; + n = c as u64 - '0' as u64; + continue 'outer; + } + c if c.is_whitespace() => break, + 'a'..='z' | 'A'..='Z' => {} + _ => { + return Err(Error::InvalidCharacter(off)); + } + } + off = self.off(); + } + self.parse_unit(n, start, off)?; + n = match self.parse_first_char()? { + Some(n) => n, + None => return Ok( + Duration::new(self.current.0, self.current.1 as u32)), + }; + } + } + +} + +/// Parse duration object `1hour 12min 5s` +/// +/// The duration object is a concatenation of time spans. Where each time +/// span is an integer number and a suffix. Supported suffixes: +/// +/// * `nsec`, `ns` -- nanoseconds +/// * `usec`, `us` -- microseconds +/// * `msec`, `ms` -- milliseconds +/// * `seconds`, `second`, `sec`, `s` +/// * `minutes`, `minute`, `min`, `m` +/// * `hours`, `hour`, `hr`, `h` +/// * `days`, `day`, `d` +/// * `weeks`, `week`, `w` +/// * `months`, `month`, `M` -- defined as 30.44 days +/// * `years`, `year`, `y` -- defined as 365.25 days +/// +/// # Examples +/// +/// ``` +/// use std::time::Duration; +/// use humantime::parse_duration; +/// +/// assert_eq!(parse_duration("2h 37min"), Ok(Duration::new(9420, 0))); +/// assert_eq!(parse_duration("32ms"), Ok(Duration::new(0, 32_000_000))); +/// ``` +pub fn parse_duration(s: &str) -> Result<Duration, Error> { + Parser { + iter: s.chars(), + src: s, + current: (0, 0), + }.parse() +} + +/// Formats duration into a human-readable string +/// +/// Note: this format is guaranteed to have same value when using +/// parse_duration, but we can change some details of the exact composition +/// of the value. +/// +/// # Examples +/// +/// ``` +/// use std::time::Duration; +/// use humantime::format_duration; +/// +/// let val1 = Duration::new(9420, 0); +/// assert_eq!(format_duration(val1).to_string(), "2h 37m"); +/// let val2 = Duration::new(0, 32_000_000); +/// assert_eq!(format_duration(val2).to_string(), "32ms"); +/// ``` +pub fn format_duration(val: Duration) -> FormattedDuration { + FormattedDuration(val) +} + +fn item_plural(f: &mut fmt::Formatter, started: &mut bool, + name: &str, value: u64) + -> fmt::Result +{ + if value > 0 { + if *started { + f.write_str(" ")?; + } + write!(f, "{}{}", value, name)?; + if value > 1 { + f.write_str("s")?; + } + *started = true; + } + Ok(()) +} +fn item(f: &mut fmt::Formatter, started: &mut bool, name: &str, value: u32) + -> fmt::Result +{ + if value > 0 { + if *started { + f.write_str(" ")?; + } + write!(f, "{}{}", value, name)?; + *started = true; + } + Ok(()) +} + +impl fmt::Display for FormattedDuration { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let secs = self.0.as_secs(); + let nanos = self.0.subsec_nanos(); + + if secs == 0 && nanos == 0 { + f.write_str("0s")?; + return Ok(()); + } + + let years = secs / 31_557_600; // 365.25d + let ydays = secs % 31_557_600; + let months = ydays / 2_630_016; // 30.44d + let mdays = ydays % 2_630_016; + let days = mdays / 86400; + let day_secs = mdays % 86400; + let hours = day_secs / 3600; + let minutes = day_secs % 3600 / 60; + let seconds = day_secs % 60; + + let millis = nanos / 1_000_000; + let micros = nanos / 1000 % 1000; + let nanosec = nanos % 1000; + + let ref mut started = false; + item_plural(f, started, "year", years)?; + item_plural(f, started, "month", months)?; + item_plural(f, started, "day", days)?; + item(f, started, "h", hours as u32)?; + item(f, started, "m", minutes as u32)?; + item(f, started, "s", seconds as u32)?; + item(f, started, "ms", millis)?; + item(f, started, "us", micros)?; + item(f, started, "ns", nanosec)?; + Ok(()) + } +} + +#[cfg(test)] +mod test { + use std::time::Duration; + + use rand::Rng; + + use super::{parse_duration, format_duration}; + use super::Error; + + #[test] + #[allow(clippy::cognitive_complexity)] + fn test_units() { + assert_eq!(parse_duration("17nsec"), Ok(Duration::new(0, 17))); + assert_eq!(parse_duration("17nanos"), Ok(Duration::new(0, 17))); + assert_eq!(parse_duration("33ns"), Ok(Duration::new(0, 33))); + assert_eq!(parse_duration("3usec"), Ok(Duration::new(0, 3000))); + assert_eq!(parse_duration("78us"), Ok(Duration::new(0, 78000))); + assert_eq!(parse_duration("31msec"), Ok(Duration::new(0, 31_000_000))); + assert_eq!(parse_duration("31millis"), Ok(Duration::new(0, 31_000_000))); + assert_eq!(parse_duration("6ms"), Ok(Duration::new(0, 6_000_000))); + assert_eq!(parse_duration("3000s"), Ok(Duration::new(3000, 0))); + assert_eq!(parse_duration("300sec"), Ok(Duration::new(300, 0))); + assert_eq!(parse_duration("300secs"), Ok(Duration::new(300, 0))); + assert_eq!(parse_duration("50seconds"), Ok(Duration::new(50, 0))); + assert_eq!(parse_duration("1second"), Ok(Duration::new(1, 0))); + assert_eq!(parse_duration("100m"), Ok(Duration::new(6000, 0))); + assert_eq!(parse_duration("12min"), Ok(Duration::new(720, 0))); + assert_eq!(parse_duration("12mins"), Ok(Duration::new(720, 0))); + assert_eq!(parse_duration("1minute"), Ok(Duration::new(60, 0))); + assert_eq!(parse_duration("7minutes"), Ok(Duration::new(420, 0))); + assert_eq!(parse_duration("2h"), Ok(Duration::new(7200, 0))); + assert_eq!(parse_duration("7hr"), Ok(Duration::new(25200, 0))); + assert_eq!(parse_duration("7hrs"), Ok(Duration::new(25200, 0))); + assert_eq!(parse_duration("1hour"), Ok(Duration::new(3600, 0))); + assert_eq!(parse_duration("24hours"), Ok(Duration::new(86400, 0))); + assert_eq!(parse_duration("1day"), Ok(Duration::new(86400, 0))); + assert_eq!(parse_duration("2days"), Ok(Duration::new(172_800, 0))); + assert_eq!(parse_duration("365d"), Ok(Duration::new(31_536_000, 0))); + assert_eq!(parse_duration("1week"), Ok(Duration::new(604_800, 0))); + assert_eq!(parse_duration("7weeks"), Ok(Duration::new(4_233_600, 0))); + assert_eq!(parse_duration("52w"), Ok(Duration::new(31_449_600, 0))); + assert_eq!(parse_duration("1month"), Ok(Duration::new(2_630_016, 0))); + assert_eq!(parse_duration("3months"), Ok(Duration::new(3*2_630_016, 0))); + assert_eq!(parse_duration("12M"), Ok(Duration::new(31_560_192, 0))); + assert_eq!(parse_duration("1year"), Ok(Duration::new(31_557_600, 0))); + assert_eq!(parse_duration("7years"), Ok(Duration::new(7*31_557_600, 0))); + assert_eq!(parse_duration("17y"), Ok(Duration::new(536_479_200, 0))); + } + + #[test] + fn test_combo() { + assert_eq!(parse_duration("20 min 17 nsec "), Ok(Duration::new(1200, 17))); + assert_eq!(parse_duration("2h 15m"), Ok(Duration::new(8100, 0))); + } + + #[test] + fn all_86400_seconds() { + for second in 0..86400 { // scan leap year and non-leap year + let d = Duration::new(second, 0); + assert_eq!(d, + parse_duration(&format_duration(d).to_string()).unwrap()); + } + } + + #[test] + fn random_second() { + for _ in 0..10000 { + let sec = rand::thread_rng().gen_range(0, 253_370_764_800); + let d = Duration::new(sec, 0); + assert_eq!(d, + parse_duration(&format_duration(d).to_string()).unwrap()); + } + } + + #[test] + fn random_any() { + for _ in 0..10000 { + let sec = rand::thread_rng().gen_range(0, 253_370_764_800); + let nanos = rand::thread_rng().gen_range(0, 1_000_000_000); + let d = Duration::new(sec, nanos); + assert_eq!(d, + parse_duration(&format_duration(d).to_string()).unwrap()); + } + } + + #[test] + fn test_overlow() { + // Overflow on subseconds is earlier because of how we do conversion + // we could fix it, but I don't see any good reason for this + assert_eq!(parse_duration("100000000000000000000ns"), + Err(Error::NumberOverflow)); + assert_eq!(parse_duration("100000000000000000us"), + Err(Error::NumberOverflow)); + assert_eq!(parse_duration("100000000000000ms"), + Err(Error::NumberOverflow)); + + assert_eq!(parse_duration("100000000000000000000s"), + Err(Error::NumberOverflow)); + assert_eq!(parse_duration("10000000000000000000m"), + Err(Error::NumberOverflow)); + assert_eq!(parse_duration("1000000000000000000h"), + Err(Error::NumberOverflow)); + assert_eq!(parse_duration("100000000000000000d"), + Err(Error::NumberOverflow)); + assert_eq!(parse_duration("10000000000000000w"), + Err(Error::NumberOverflow)); + assert_eq!(parse_duration("1000000000000000M"), + Err(Error::NumberOverflow)); + assert_eq!(parse_duration("10000000000000y"), + Err(Error::NumberOverflow)); + } + + #[test] + fn test_nice_error_message() { + assert_eq!(parse_duration("123").unwrap_err().to_string(), + "time unit needed, for example 123sec or 123ms"); + assert_eq!(parse_duration("10 months 1").unwrap_err().to_string(), + "time unit needed, for example 1sec or 1ms"); + assert_eq!(parse_duration("10nights").unwrap_err().to_string(), + "unknown time unit \"nights\", supported units: \ + ns, us, ms, sec, min, hours, days, weeks, months, \ + years (and few variations)"); + } +} diff --git a/vendor/humantime/src/lib.rs b/vendor/humantime/src/lib.rs new file mode 100644 index 0000000000..9be6f22852 --- /dev/null +++ b/vendor/humantime/src/lib.rs @@ -0,0 +1,34 @@ +//! Human-friendly time parser and formatter +//! +//! Features: +//! +//! * Parses durations in free form like `15days 2min 2s` +//! * Formats durations in similar form `2years 2min 12us` +//! * Parses and formats timestamp in `rfc3339` format: `2018-01-01T12:53:00Z` +//! * Parses timestamps in a weaker format: `2018-01-01 12:53:00` +//! +//! Timestamp parsing/formatting is super-fast because format is basically +//! fixed. +//! +//! See [humantime-serde] for serde integration (previous crate [serde-humantime] looks unmaintained). +//! +//! [serde-humantime]: https://docs.rs/serde-humantime/0.1.1/serde_humantime/ +//! [humantime-serde]: https://docs.rs/humantime-serde + +#![forbid(unsafe_code)] +#![warn(missing_debug_implementations)] +#![warn(missing_docs)] + +mod duration; +mod wrapper; +mod date; + +pub use self::duration::{parse_duration, Error as DurationError}; +pub use self::duration::{format_duration, FormattedDuration}; +pub use self::wrapper::{Duration, Timestamp}; +pub use self::date::{parse_rfc3339, parse_rfc3339_weak, Error as TimestampError}; +pub use self::date::{ + format_rfc3339, format_rfc3339_micros, format_rfc3339_millis, format_rfc3339_nanos, + format_rfc3339_seconds, +}; +pub use self::date::{Rfc3339Timestamp}; diff --git a/vendor/humantime/src/wrapper.rs b/vendor/humantime/src/wrapper.rs new file mode 100644 index 0000000000..99af6502ae --- /dev/null +++ b/vendor/humantime/src/wrapper.rs @@ -0,0 +1,107 @@ +use std::str::FromStr; +use std::ops::Deref; +use std::fmt; +use std::time::{Duration as StdDuration, SystemTime}; + +use crate::duration::{self, parse_duration, format_duration}; +use crate::date::{self, parse_rfc3339_weak, format_rfc3339}; + +/// A wrapper for duration that has `FromStr` implementation +/// +/// This is useful if you want to use it somewhere where `FromStr` is +/// expected. +/// +/// See `parse_duration` for the description of the format. +/// +/// # Example +/// +/// ``` +/// use std::time::Duration; +/// let x: Duration; +/// x = "12h 5min 2ns".parse::<humantime::Duration>().unwrap().into(); +/// assert_eq!(x, Duration::new(12*3600 + 5*60, 2)) +/// ``` +/// +#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] +pub struct Duration(StdDuration); + +/// A wrapper for SystemTime that has `FromStr` implementation +/// +/// This is useful if you want to use it somewhere where `FromStr` is +/// expected. +/// +/// See `parse_rfc3339_weak` for the description of the format. The "weak" +/// format is used as it's more pemissive for human input as this is the +/// expected use of the type (e.g. command-line parsing). +/// +/// # Example +/// +/// ``` +/// use std::time::SystemTime; +/// let x: SystemTime; +/// x = "2018-02-16T00:31:37Z".parse::<humantime::Timestamp>().unwrap().into(); +/// assert_eq!(humantime::format_rfc3339(x).to_string(), "2018-02-16T00:31:37Z"); +/// ``` +/// +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct Timestamp(SystemTime); + +impl AsRef<StdDuration> for Duration { + fn as_ref(&self) -> &StdDuration { &self.0 } +} + +impl Deref for Duration { + type Target = StdDuration; + fn deref(&self) -> &StdDuration { &self.0 } +} + +impl Into<StdDuration> for Duration { + fn into(self) -> StdDuration { self.0 } +} + +impl From<StdDuration> for Duration { + fn from(dur: StdDuration) -> Duration { Duration(dur) } +} + +impl FromStr for Duration { + type Err = duration::Error; + fn from_str(s: &str) -> Result<Duration, Self::Err> { + parse_duration(s).map(Duration) + } +} + +impl fmt::Display for Duration { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + format_duration(self.0).fmt(f) + } +} + +impl AsRef<SystemTime> for Timestamp { + fn as_ref(&self) -> &SystemTime { &self.0 } +} + +impl Deref for Timestamp { + type Target = SystemTime; + fn deref(&self) -> &SystemTime { &self.0 } +} + +impl Into<SystemTime> for Timestamp { + fn into(self) -> SystemTime { self.0 } +} + +impl From<SystemTime> for Timestamp { + fn from(dur: SystemTime) -> Timestamp { Timestamp(dur) } +} + +impl FromStr for Timestamp { + type Err = date::Error; + fn from_str(s: &str) -> Result<Timestamp, Self::Err> { + parse_rfc3339_weak(s).map(Timestamp) + } +} + +impl fmt::Display for Timestamp { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + format_rfc3339(self.0).fmt(f) + } +} diff --git a/vendor/humantime/vagga.yaml b/vendor/humantime/vagga.yaml new file mode 100644 index 0000000000..8a6b5847e0 --- /dev/null +++ b/vendor/humantime/vagga.yaml @@ -0,0 +1,92 @@ +commands: + + cargo: !Command + description: Run any cargo command + container: ubuntu + run: [cargo] + + make: !Command + description: Build the library + container: ubuntu + run: [cargo, build] + + test64: !Command + description: Test the 64bit library + container: ubuntu + environ: { RUST_BACKTRACE: 1 } + run: [cargo, test] + + test32: !Command + description: Test the 32bit library + container: ubuntu32 + environ: { RUST_BACKTRACE: 1 } + run: [cargo, test] + + test: !Command + description: Test the 64bit library + container: ubuntu + environ: { RUST_BACKTRACE: 1 } + prerequisites: [test64, test32] + run: [echo, okay] + + bench: !Command + description: Run benchmarks + container: bench + environ: { RUST_BACKTRACE: 1 } + run: [cargo, bench] + + _bulk: !Command + description: Run `bulk` command (for version bookkeeping) + container: ubuntu + run: [bulk] + +containers: + + ubuntu: + setup: + - !Ubuntu xenial + - !UbuntuUniverse + - !Install [ca-certificates, build-essential, vim] + + - !TarInstall + url: "https://static.rust-lang.org/dist/rust-1.31.0-x86_64-unknown-linux-gnu.tar.gz" + script: "./install.sh --prefix=/usr \ + --components=rustc,rust-std-x86_64-unknown-linux-gnu,cargo" + - &bulk !Tar + url: "https://github.com/tailhook/bulk/releases/download/v0.4.10/bulk-v0.4.10.tar.gz" + sha256: 481513f8a0306a9857d045497fb5b50b50a51e9ff748909ecf7d2bda1de275ab + path: / + + environ: + HOME: /work/target + USER: pc + + ubuntu32: + setup: + - !UbuntuRelease + codename: xenial + arch: i386 + - !UbuntuUniverse + - !Install [ca-certificates, build-essential, vim] + + - !TarInstall + url: "https://static.rust-lang.org/dist/rust-1.31.0-i686-unknown-linux-gnu.tar.gz" + script: "./install.sh --prefix=/usr \ + --components=rustc,rust-std-i686-unknown-linux-gnu,cargo" + + environ: + HOME: /work/target + USER: pc + + bench: + setup: + - !Ubuntu xenial + - !Install [ca-certificates, wget, build-essential] + - !TarInstall + url: https://static.rust-lang.org/dist/rust-nightly-x86_64-unknown-linux-gnu.tar.gz + script: | + ./install.sh --prefix=/usr \ + --components=rustc,rust-std-x86_64-unknown-linux-gnu,cargo + environ: + HOME: /work/target + USER: pc diff --git a/vendor/indoc/.cargo-checksum.json b/vendor/indoc/.cargo-checksum.json new file mode 100644 index 0000000000..a527685266 --- /dev/null +++ b/vendor/indoc/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"f9361ce1255e444b57735dd9fa199ee6b73bd0a3f3ae98ca88285b71f0d67075","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"54b410081f121f119ec7e736aedd68428c658498725ee1694c17e574b85badc6","src/error.rs":"be08d9d48b4cb9984b5141b12f21c31bd7293942c18b3ce25754723930cf54f5","src/expr.rs":"4f3e64f1c890a64f441e5a08820fe73d5d1949f6e3e921f3e4a116ef5d4c6dc8","src/lib.rs":"207b81b4d15024e15296e8087f8e152128967d5ae83bf93de2c22149a1805d46","tests/compiletest.rs":"0a52a44786aea1c299c695bf948b2ed2081e4cc344e5c2cadceab4eb03d0010d","tests/test_formatdoc.rs":"8b341b13758b6d55cdaedad16049369d9bd907fb1fbccb3a236e6024401b47fd","tests/test_indoc.rs":"154cc7b07b93e3790b4663eea853cd87652db6962bb53238861dd9a3f4739084","tests/test_unindent.rs":"150432ff625085eaadaea5a05012c6c509880850b4edcbbcddb066292505f29c","tests/test_writedoc.rs":"e345f43e522ea982144cedd4e3a68280adca680619eb40387596340800c1e49b","tests/ui/no-arguments.rs":"d544b1a510efbef42a1fb7b7b40009da2d9be815a55ef76dd2362c8c7754734e","tests/ui/no-arguments.stderr":"0b8c03b2e8553f4d9482a05c9f6a73e69983529552c4922e171f73e16e9727ea","tests/ui/non-lit.rs":"3e7d7b4b5e141b5eb4c76d64b47f7a5f60325091a8e4d8cc2d97b7d590dd2857","tests/ui/non-lit.stderr":"4089ba6995f65328dc50bbba2ea4f9637be1e17a7c91c3a97ba685bed26a5fc0","tests/ui/non-string.rs":"0b56f281761edaee1c7341c9ba231371c86752456179d84777c62f03f52ce173","tests/ui/non-string.stderr":"ddf9793e0bb58ade04b1fba093d618812f237ee994c1b38f8a8f4c98278b83c7","tests/ui/printdoc-binary.rs":"0122fd6b783cb9c25c8aede8f0cc69c1c3ffcef656bf7d9ee476e8e0ff49e59f","tests/ui/printdoc-binary.stderr":"6da2f4815e448483adcba63db34fa532d9ec3ec681b23b25835517b280cee2c2","tests/ui/printdoc-extra-arg.rs":"fa31182019534b5b258f8335799c8ba53a7715c1d9e6fc9d25fbc0952d28bd7a","tests/ui/printdoc-extra-arg.stderr":"1fcd5dc979d4cdd3d3438285fcfd2b4549f2b2f9404c9f8a0ac44c3035ea2f1d","tests/ui/printdoc-no-arg.rs":"087d8e5295f7809abf596a076743401f6ba019fd5b3b2e290bfd6551b4bdcdf3","tests/ui/printdoc-no-arg.stderr":"5a58ce18bb21a4118ab2c5d7a25e7281cc15a955dba846b7ecbce2d4dcd318aa","tests/ui/printdoc-no-display.rs":"afeafb1f41a6f7aa68bd5da14c2057e54f2756c1726098ac8be9ab0517a85879","tests/ui/printdoc-no-display.stderr":"2866bf39b34a28c13f5dfcbc5c48219a484f1b49522e49b1f167993a2d234fe6","tests/ui/printdoc-no-named-arg.rs":"beeb8447ab95a0e0a21aec78872be79ad1b2a8fe1be4a276fe191f47f3b8082b","tests/ui/printdoc-no-named-arg.stderr":"3ccbfd859653d6e97af6df6448e1936f014c4c36831a8cdf2bf5b1a607ea2294","tests/ui/three-arguments.rs":"47b74a9918de87bad00cdd94dc7091a499a586edcfbc05035ef79ce0d52dbe27","tests/ui/three-arguments.stderr":"57ceab1de91a5e48103f3d9ad190aa75d73ac495c5613ab68d3e74219a516031","tests/ui/two-arguments.rs":"1607e7c149cc0ed5e3fb5984ac1d39d8dff0bd8325911518b02d05daa95b06b0","tests/ui/two-arguments.stderr":"01249fe1900c8f409ca7b703c7d06a433d45d9947a82c01fe5b690ee6822bec4"},"package":"e5a75aeaaef0ce18b58056d306c27b07436fbb34b8816c53094b76dd81803136"} \ No newline at end of file diff --git a/vendor/indoc/Cargo.toml b/vendor/indoc/Cargo.toml new file mode 100644 index 0000000000..7697c1047c --- /dev/null +++ b/vendor/indoc/Cargo.toml @@ -0,0 +1,36 @@ +# 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 = "indoc" +version = "1.0.3" +authors = ["David Tolnay <dtolnay@gmail.com>"] +description = "Indented document literals" +documentation = "https://docs.rs/indoc" +readme = "README.md" +keywords = ["heredoc", "nowdoc", "multiline", "string", "literal"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/dtolnay/indoc" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +proc-macro = true +[dependencies.unindent] +version = "0.1.7" +[dev-dependencies.rustversion] +version = "1.0" + +[dev-dependencies.trybuild] +version = "1.0.19" +features = ["diff"] diff --git a/vendor/indoc/LICENSE-APACHE b/vendor/indoc/LICENSE-APACHE new file mode 100644 index 0000000000..16fe87b06e --- /dev/null +++ b/vendor/indoc/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/vendor/indoc/LICENSE-MIT b/vendor/indoc/LICENSE-MIT new file mode 100644 index 0000000000..31aa79387f --- /dev/null +++ b/vendor/indoc/LICENSE-MIT @@ -0,0 +1,23 @@ +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/indoc/README.md b/vendor/indoc/README.md new file mode 100644 index 0000000000..795d5ab867 --- /dev/null +++ b/vendor/indoc/README.md @@ -0,0 +1,150 @@ +Indented Documents (indoc) +========================== + +[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/indoc-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/indoc) +[<img alt="crates.io" src="https://img.shields.io/crates/v/indoc.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/indoc) +[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-indoc-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K" height="20">](https://docs.rs/indoc) +[<img alt="build status" src="https://img.shields.io/github/workflow/status/dtolnay/indoc/CI/master?style=for-the-badge" height="20">](https://github.com/dtolnay/indoc/actions?query=branch%3Amaster) + +This crate provides a procedural macro for indented string literals. The +`indoc!()` macro takes a multiline string literal and un-indents it at compile +time so the leftmost non-space character is in the first column. + +```toml +[dependencies] +indoc = "1.0" +``` + +*Compiler requirement: rustc 1.45 or greater.* + +<br> + +## Using indoc + +```rust +use indoc::indoc; + +fn main() { + let testing = indoc! {" + def hello(): + print('Hello, world!') + + hello() + "}; + let expected = "def hello():\n print('Hello, world!')\n\nhello()\n"; + assert_eq!(testing, expected); +} +``` + +Indoc also works with raw string literals: + +```rust +use indoc::indoc; + +fn main() { + let testing = indoc! {r#" + def hello(): + print("Hello, world!") + + hello() + "#}; + let expected = "def hello():\n print(\"Hello, world!\")\n\nhello()\n"; + assert_eq!(testing, expected); +} +``` + +And byte string literals: + +```rust +use indoc::indoc; + +fn main() { + let testing = indoc! {b" + def hello(): + print('Hello, world!') + + hello() + "}; + let expected = b"def hello():\n print('Hello, world!')\n\nhello()\n"; + assert_eq!(testing[..], expected[..]); +} +``` + +<br> + +## Formatting macros + +The indoc crate exports four additional macros to substitute conveniently for +the standard library's formatting macros: + +- `formatdoc!($fmt, ...)` — equivalent to `format!(indoc!($fmt), ...)` +- `printdoc!($fmt, ...)` — equivalent to `print!(indoc!($fmt), ...)` +- `eprintdoc!($fmt, ...)` — equivalent to `eprint!(indoc!($fmt), ...)` +- `writedoc!($dest, $fmt, ...)` — equivalent to `write!($dest, indoc!($fmt), ...)` + +```rust +use indoc::printdoc; + +fn main() { + printdoc! {" + GET {url} + Accept: {mime} + ", + url = "http://localhost:8080", + mime = "application/json", + } +} +``` + +<br> + +## Explanation + +The following rules characterize the behavior of the `indoc!()` macro: + +1. Count the leading spaces of each line, ignoring the first line and any lines + that are empty or contain spaces only. +2. Take the minimum. +3. If the first line is empty i.e. the string begins with a newline, remove the + first line. +4. Remove the computed number of spaces from the beginning of each line. + +<br> + +## Unindent + +Indoc's indentation logic is available in the `unindent` crate. This may be +useful for processing strings that are not statically known at compile time. + +The crate exposes two functions: + +- `unindent(&str) -> String` +- `unindent_bytes(&[u8]) -> Vec<u8>` + +```rust +use unindent::unindent; + +fn main() { + let indented = " + line one + line two"; + assert_eq!("line one\nline two", unindent(indented)); +} +``` + +<br> + +#### License + +<sup> +Licensed under either of <a href="LICENSE-APACHE">Apache License, Version +2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option. +</sup> + +<br> + +<sub> +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in this crate by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. +</sub> diff --git a/vendor/indoc/src/error.rs b/vendor/indoc/src/error.rs new file mode 100644 index 0000000000..7c5badb257 --- /dev/null +++ b/vendor/indoc/src/error.rs @@ -0,0 +1,47 @@ +use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; +use std::iter::FromIterator; + +pub type Result<T> = std::result::Result<T, Error>; + +pub struct Error { + begin: Span, + end: Span, + msg: String, +} + +impl Error { + pub fn new(span: Span, msg: &str) -> Self { + Self::new2(span, span, msg) + } + + pub fn new2(begin: Span, end: Span, msg: &str) -> Self { + Error { + begin, + end, + msg: msg.to_owned(), + } + } + + pub fn to_compile_error(&self) -> TokenStream { + // compile_error! { $msg } + TokenStream::from_iter(vec![ + TokenTree::Ident(Ident::new("compile_error", self.begin)), + TokenTree::Punct({ + let mut punct = Punct::new('!', Spacing::Alone); + punct.set_span(self.begin); + punct + }), + TokenTree::Group({ + let mut group = Group::new(Delimiter::Brace, { + TokenStream::from_iter(vec![TokenTree::Literal({ + let mut string = Literal::string(&self.msg); + string.set_span(self.end); + string + })]) + }); + group.set_span(self.end); + group + }), + ]) + } +} diff --git a/vendor/indoc/src/expr.rs b/vendor/indoc/src/expr.rs new file mode 100644 index 0000000000..e802e2015c --- /dev/null +++ b/vendor/indoc/src/expr.rs @@ -0,0 +1,56 @@ +use crate::error::{Error, Result}; +use proc_macro::token_stream::IntoIter as TokenIter; +use proc_macro::{Spacing, Span, TokenStream, TokenTree}; +use std::iter; + +pub struct Expr(TokenStream); + +pub fn parse(input: &mut TokenIter) -> Result<Expr> { + #[derive(PartialEq)] + enum Lookbehind { + JointColon, + DoubleColon, + Other, + } + + let mut expr = TokenStream::new(); + let mut lookbehind = Lookbehind::Other; + let mut angle_bracket_depth = 0; + + loop { + match input.next() { + Some(TokenTree::Punct(punct)) => { + let ch = punct.as_char(); + let spacing = punct.spacing(); + expr.extend(iter::once(TokenTree::Punct(punct))); + lookbehind = match ch { + ',' if angle_bracket_depth == 0 => return Ok(Expr(expr)), + ':' if lookbehind == Lookbehind::JointColon => Lookbehind::DoubleColon, + ':' if spacing == Spacing::Joint => Lookbehind::JointColon, + '<' if lookbehind == Lookbehind::DoubleColon => { + angle_bracket_depth += 1; + Lookbehind::Other + } + '>' if angle_bracket_depth > 0 => { + angle_bracket_depth -= 1; + Lookbehind::Other + } + _ => Lookbehind::Other, + }; + } + Some(token) => expr.extend(iter::once(token)), + None => { + return Err(Error::new( + Span::call_site(), + "unexpected end of macro input", + )) + } + } + } +} + +impl Expr { + pub fn into_tokens(self) -> TokenStream { + self.0 + } +} diff --git a/vendor/indoc/src/lib.rs b/vendor/indoc/src/lib.rs new file mode 100644 index 0000000000..7415674ca7 --- /dev/null +++ b/vendor/indoc/src/lib.rs @@ -0,0 +1,385 @@ +//! [![github]](https://github.com/dtolnay/indoc) [![crates-io]](https://crates.io/crates/indoc) [![docs-rs]](https://docs.rs/indoc) +//! +//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github +//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust +//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K +//! +//! <br> +//! +//! This crate provides a procedural macro for indented string literals. The +//! `indoc!()` macro takes a multiline string literal and un-indents it at +//! compile time so the leftmost non-space character is in the first column. +//! +//! ```toml +//! [dependencies] +//! indoc = "1.0" +//! ``` +//! +//! <br> +//! +//! # Using indoc +//! +//! ``` +//! use indoc::indoc; +//! +//! fn main() { +//! let testing = indoc! {" +//! def hello(): +//! print('Hello, world!') +//! +//! hello() +//! "}; +//! let expected = "def hello():\n print('Hello, world!')\n\nhello()\n"; +//! assert_eq!(testing, expected); +//! } +//! ``` +//! +//! Indoc also works with raw string literals: +//! +//! ``` +//! use indoc::indoc; +//! +//! fn main() { +//! let testing = indoc! {r#" +//! def hello(): +//! print("Hello, world!") +//! +//! hello() +//! "#}; +//! let expected = "def hello():\n print(\"Hello, world!\")\n\nhello()\n"; +//! assert_eq!(testing, expected); +//! } +//! ``` +//! +//! And byte string literals: +//! +//! ``` +//! use indoc::indoc; +//! +//! fn main() { +//! let testing = indoc! {b" +//! def hello(): +//! print('Hello, world!') +//! +//! hello() +//! "}; +//! let expected = b"def hello():\n print('Hello, world!')\n\nhello()\n"; +//! assert_eq!(testing[..], expected[..]); +//! } +//! ``` +//! +//! <br><br> +//! +//! # Formatting macros +//! +//! The indoc crate exports four additional macros to substitute conveniently +//! for the standard library's formatting macros: +//! +//! - `formatdoc!($fmt, ...)` — equivalent to `format!(indoc!($fmt), ...)` +//! - `printdoc!($fmt, ...)` — equivalent to `print!(indoc!($fmt), ...)` +//! - `eprintdoc!($fmt, ...)` — equivalent to `eprint!(indoc!($fmt), ...)` +//! - `writedoc!($dest, $fmt, ...)` — equivalent to `write!($dest, indoc!($fmt), ...)` +//! +//! ``` +//! use indoc::printdoc; +//! +//! fn main() { +//! printdoc! {" +//! GET {url} +//! Accept: {mime} +//! ", +//! url = "http://localhost:8080", +//! mime = "application/json", +//! } +//! } +//! ``` +//! +//! <br><br> +//! +//! # Explanation +//! +//! The following rules characterize the behavior of the `indoc!()` macro: +//! +//! 1. Count the leading spaces of each line, ignoring the first line and any +//! lines that are empty or contain spaces only. +//! 2. Take the minimum. +//! 3. If the first line is empty i.e. the string begins with a newline, remove +//! the first line. +//! 4. Remove the computed number of spaces from the beginning of each line. + +#![allow(clippy::needless_doctest_main)] + +mod error; +mod expr; + +use crate::error::{Error, Result}; +use crate::expr::Expr; +use proc_macro::token_stream::IntoIter as TokenIter; +use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; +use std::iter::{self, FromIterator}; +use std::str::FromStr; +use unindent::unindent; + +#[derive(Copy, Clone, PartialEq)] +enum Macro { + Indoc, + Format, + Print, + Eprint, + Write, +} + +/// Unindent and produce `&'static str`. +/// +/// # Example +/// +/// ``` +/// # use indoc::indoc; +/// # +/// // The type of `program` is &'static str +/// let program = indoc! {" +/// def hello(): +/// print('Hello, world!') +/// +/// hello() +/// "}; +/// print!("{}", program); +/// ``` +/// +/// ```text +/// def hello(): +/// print('Hello, world!') +/// +/// hello() +/// ``` +#[proc_macro] +pub fn indoc(input: TokenStream) -> TokenStream { + expand(input, Macro::Indoc) +} + +/// Unindent and call `format!`. +/// +/// Argument syntax is the same as for [`std::format!`]. +/// +/// # Example +/// +/// ``` +/// # use indoc::formatdoc; +/// # +/// let request = formatdoc! {" +/// GET {url} +/// Accept: {mime} +/// ", +/// url = "http://localhost:8080", +/// mime = "application/json", +/// }; +/// println!("{}", request); +/// ``` +/// +/// ```text +/// GET http://localhost:8080 +/// Accept: application/json +/// ``` +#[proc_macro] +pub fn formatdoc(input: TokenStream) -> TokenStream { + expand(input, Macro::Format) +} + +/// Unindent and call `print!`. +/// +/// Argument syntax is the same as for [`std::print!`]. +/// +/// # Example +/// +/// ``` +/// # use indoc::printdoc; +/// # +/// printdoc! {" +/// GET {url} +/// Accept: {mime} +/// ", +/// url = "http://localhost:8080", +/// mime = "application/json", +/// } +/// ``` +/// +/// ```text +/// GET http://localhost:8080 +/// Accept: application/json +/// ``` +#[proc_macro] +pub fn printdoc(input: TokenStream) -> TokenStream { + expand(input, Macro::Print) +} + +/// Unindent and call `eprint!`. +/// +/// Argument syntax is the same as for [`std::eprint!`]. +/// +/// # Example +/// +/// ``` +/// # use indoc::eprintdoc; +/// # +/// eprintdoc! {" +/// GET {url} +/// Accept: {mime} +/// ", +/// url = "http://localhost:8080", +/// mime = "application/json", +/// } +/// ``` +/// +/// ```text +/// GET http://localhost:8080 +/// Accept: application/json +/// ``` +#[proc_macro] +pub fn eprintdoc(input: TokenStream) -> TokenStream { + expand(input, Macro::Eprint) +} + +/// Unindent and call `write!`. +/// +/// Argument syntax is the same as for [`std::write!`]. +/// +/// # Example +/// +/// ``` +/// # use indoc::writedoc; +/// # use std::io::Write; +/// # +/// let _ = writedoc!( +/// std::io::stdout(), +/// " +/// GET {url} +/// Accept: {mime} +/// ", +/// url = "http://localhost:8080", +/// mime = "application/json", +/// ); +/// ``` +/// +/// ```text +/// GET http://localhost:8080 +/// Accept: application/json +/// ``` +#[proc_macro] +pub fn writedoc(input: TokenStream) -> TokenStream { + expand(input, Macro::Write) +} + +fn expand(input: TokenStream, mode: Macro) -> TokenStream { + match try_expand(input, mode) { + Ok(tokens) => tokens, + Err(err) => err.to_compile_error(), + } +} + +fn try_expand(input: TokenStream, mode: Macro) -> Result<TokenStream> { + let mut input = input.into_iter(); + + let prefix = if mode == Macro::Write { + Some(expr::parse(&mut input)?) + } else { + None + }; + + let first = input.next().ok_or_else(|| { + Error::new( + Span::call_site(), + "unexpected end of macro invocation, expected format string", + ) + })?; + + let unindented_lit = lit_indoc(first, mode)?; + + let macro_name = match mode { + Macro::Indoc => { + require_empty_or_trailing_comma(&mut input)?; + return Ok(TokenStream::from(TokenTree::Literal(unindented_lit))); + } + Macro::Format => "format", + Macro::Print => "print", + Macro::Eprint => "eprint", + Macro::Write => "write", + }; + + // #macro_name! { #unindented_lit #args } + Ok(TokenStream::from_iter(vec![ + TokenTree::Ident(Ident::new(macro_name, Span::call_site())), + TokenTree::Punct(Punct::new('!', Spacing::Alone)), + TokenTree::Group(Group::new( + Delimiter::Brace, + prefix + .map_or_else(TokenStream::new, Expr::into_tokens) + .into_iter() + .chain(iter::once(TokenTree::Literal(unindented_lit))) + .chain(input) + .collect(), + )), + ])) +} + +fn lit_indoc(token: TokenTree, mode: Macro) -> Result<Literal> { + let repr = token.to_string(); + let repr = repr.trim(); + let is_string = repr.starts_with('"') || repr.starts_with('r'); + let is_byte_string = repr.starts_with("b\"") || repr.starts_with("br"); + + if !is_string && !is_byte_string { + return Err(Error::new( + token.span(), + "argument must be a single string literal", + )); + } + + if is_byte_string && mode != Macro::Indoc { + return Err(Error::new( + token.span(), + "byte strings are not supported in formatting macros", + )); + } + + let begin = repr.find('"').unwrap() + 1; + let end = repr.rfind('"').unwrap(); + let repr = format!( + "{open}{content}{close}", + open = &repr[..begin], + content = unindent(&repr[begin..end]), + close = &repr[end..], + ); + + match TokenStream::from_str(&repr) + .unwrap() + .into_iter() + .next() + .unwrap() + { + TokenTree::Literal(mut lit) => { + lit.set_span(token.span()); + Ok(lit) + } + _ => unreachable!(), + } +} + +fn require_empty_or_trailing_comma(input: &mut TokenIter) -> Result<()> { + let first = match input.next() { + Some(TokenTree::Punct(punct)) if punct.as_char() == ',' => match input.next() { + Some(second) => second, + None => return Ok(()), + }, + Some(first) => first, + None => return Ok(()), + }; + let last = input.last(); + + let begin_span = first.span(); + let end_span = last.as_ref().map_or(begin_span, TokenTree::span); + let msg = format!( + "unexpected {token} in macro invocation; indoc argument must be a single string literal", + token = if last.is_some() { "tokens" } else { "token" } + ); + Err(Error::new2(begin_span, end_span, &msg)) +} diff --git a/vendor/indoc/tests/compiletest.rs b/vendor/indoc/tests/compiletest.rs new file mode 100644 index 0000000000..f9aea23b51 --- /dev/null +++ b/vendor/indoc/tests/compiletest.rs @@ -0,0 +1,6 @@ +#[rustversion::attr(not(nightly), ignore)] +#[test] +fn ui() { + let t = trybuild::TestCases::new(); + t.compile_fail("tests/ui/*.rs"); +} diff --git a/vendor/indoc/tests/test_formatdoc.rs b/vendor/indoc/tests/test_formatdoc.rs new file mode 100644 index 0000000000..5e4779504c --- /dev/null +++ b/vendor/indoc/tests/test_formatdoc.rs @@ -0,0 +1,117 @@ +use indoc::formatdoc; + +#[test] +fn carriage_return() { + // Every line in the string ends with \r\n + let indoc = formatdoc! {" + {} + + \\{} + {}", + 'a', 'b', 'c' + }; + let expected = "a\n\n \\b\nc"; + assert_eq!(indoc, expected); +} + +#[test] +fn empty_string() { + let indoc = formatdoc! {""}; + let expected = ""; + assert_eq!(indoc, expected); +} + +#[test] +fn joined_first_line() { + let indoc = formatdoc! {"\ + {}", 'a' + }; + let expected = "a"; + assert_eq!(indoc, expected); +} + +#[test] +fn joined_lines() { + let indoc = formatdoc! {" + {}\ + {} + {}\ + {} + {}", + 'a', 'b', 'c', 'd', 'e' + }; + let expected = "ab\ncd\ne"; + assert_eq!(indoc, expected); +} + +#[test] +fn no_leading_newline() { + let indoc = formatdoc! {"{} + {} + {}", 'a', 'b', 'c'}; + let expected = "a\nb\nc"; + assert_eq!(indoc, expected); +} + +#[test] +fn one_line() { + let indoc = formatdoc! {"a"}; + let expected = "a"; + assert_eq!(indoc, expected); +} + +#[test] +fn raw_string() { + let indoc = formatdoc! {r#" + {:?} + + \\{} + {}"#, + "a", 'b', 'c' + }; + let expected = "\"a\"\n\n \\\\b\nc"; + assert_eq!(indoc, expected); +} + +#[test] +fn string() { + let indoc = formatdoc! {" + {} + + \\{} + {}", + 'a', 'b', 'c' + }; + let expected = "a\n\n \\b\nc"; + assert_eq!(indoc, expected); +} + +#[test] +fn string_trailing_newline() { + let indoc = formatdoc! {" + {} + + \\{} + {} + ", + 'a', 'b', 'c' + }; + let expected = "a\n\n \\b\nc\n"; + assert_eq!(indoc, expected); +} + +#[test] +fn trailing_whitespace() { + let indoc = formatdoc! {" + {} {below} + + {} {below} + + {} {below} + + end", + 2, 0, -2, below = "below" + }; + let expected = "2 below\n \n0 below\n\n-2 below\n\nend"; + assert_eq!(indoc, expected); +} diff --git a/vendor/indoc/tests/test_indoc.rs b/vendor/indoc/tests/test_indoc.rs new file mode 100644 index 0000000000..e0ead11b69 --- /dev/null +++ b/vendor/indoc/tests/test_indoc.rs @@ -0,0 +1,166 @@ +use indoc::indoc; + +#[test] +fn byte_string() { + let indoc = indoc! {b" + a + + \\b + c" + }; + let expected = b"a\n\n \\b\nc"; + assert_eq!(indoc, expected); +} + +#[test] +fn carriage_return() { + // Every line in the string ends with \r\n + let indoc = indoc! {" + a + + \\b + c" + }; + let expected = "a\n\n \\b\nc"; + assert_eq!(indoc, expected); +} + +#[test] +fn trailing_comma() { + let indoc = indoc! { + " + test + ", + }; + let expected = "test\n"; + assert_eq!(indoc, expected); +} + +#[test] +fn empty_string() { + let indoc = indoc! {""}; + let expected = ""; + assert_eq!(indoc, expected); +} + +#[test] +fn joined_first_line() { + let indoc = indoc! {"\ + a" + }; + let expected = "a"; + assert_eq!(indoc, expected); +} + +#[test] +fn joined_lines() { + let indoc = indoc! {" + a\ + b + c\ + d + e" + }; + let expected = "ab\ncd\ne"; + assert_eq!(indoc, expected); +} + +#[test] +fn no_leading_newline() { + let indoc = indoc! {"a + b + c"}; + let expected = "a\nb\nc"; + assert_eq!(indoc, expected); +} + +#[test] +fn one_line() { + let indoc = indoc! {"a"}; + let expected = "a"; + assert_eq!(indoc, expected); +} + +#[test] +fn raw_byte_string() { + let indoc = indoc! {br#" + "a" + + \\b + c"# + }; + let expected = b"\"a\"\n\n \\\\b\nc"; + assert_eq!(indoc, expected); +} + +#[test] +fn raw_string() { + let indoc = indoc! {r#" + "a" + + \\b + c"# + }; + let expected = "\"a\"\n\n \\\\b\nc"; + assert_eq!(indoc, expected); +} + +#[test] +fn string() { + let indoc = indoc! {" + a + + \\b + c" + }; + let expected = "a\n\n \\b\nc"; + assert_eq!(indoc, expected); +} + +#[test] +fn string_trailing_newline() { + let indoc = indoc! {" + a + + \\b + c + "}; + let expected = "a\n\n \\b\nc\n"; + assert_eq!(indoc, expected); +} + +#[test] +fn trailing_whitespace() { + let indoc = indoc! {" + 2 below + + 0 below + + -2 below + + end" + }; + let expected = "2 below\n \n0 below\n\n-2 below\n\nend"; + assert_eq!(indoc, expected); +} + +#[test] +fn indoc_as_format_string() { + let s = format!(indoc! {"{}"}, true); + assert_eq!(s, "true"); +} + +#[test] +fn test_metavariable() { + macro_rules! indoc_wrapper { + ($e:expr) => { + indoc!($e) + }; + } + + let indoc = indoc_wrapper! {" + macros, how do they work + "}; + let expected = "macros, how do they work\n"; + assert_eq!(indoc, expected); +} diff --git a/vendor/indoc/tests/test_unindent.rs b/vendor/indoc/tests/test_unindent.rs new file mode 100644 index 0000000000..90853c8d3d --- /dev/null +++ b/vendor/indoc/tests/test_unindent.rs @@ -0,0 +1,51 @@ +use unindent::{unindent, unindent_bytes, Unindent}; + +#[test] +fn fn_unindent_str() { + let s = " + line one + line two"; + assert_eq!(unindent(s), "line one\nline two"); + + let s = "\n\t\t\tline one\n\t\t\tline two"; + assert_eq!(unindent(s), "line one\nline two"); +} + +#[test] +fn fn_unindent_bytes() { + let b = b" + line one + line two"; + assert_eq!(unindent_bytes(b), b"line one\nline two"); + + let b = b"\n\t\t\tline one\n\t\t\tline two"; + assert_eq!(unindent_bytes(b), b"line one\nline two"); +} + +#[test] +fn trait_unindent_str() { + let s = " + line one + line two"; + assert_eq!(s.unindent(), "line one\nline two"); + + let s = "\n\t\t\tline one\n\t\t\tline two"; + assert_eq!(s.unindent(), "line one\nline two"); +} + +#[test] +fn trait_unindent_bytes() { + let b = b" + line one + line two"; + assert_eq!(b.unindent(), b"line one\nline two"); + + let b = b"\n\t\t\tline one\n\t\t\tline two"; + assert_eq!(b.unindent(), b"line one\nline two"); +} + +#[test] +fn carriage_returns() { + let s = "\r\n\tline one\r\n\tline two"; + assert_eq!(unindent(s), "line one\r\nline two"); +} diff --git a/vendor/indoc/tests/test_writedoc.rs b/vendor/indoc/tests/test_writedoc.rs new file mode 100644 index 0000000000..91a45d2cae --- /dev/null +++ b/vendor/indoc/tests/test_writedoc.rs @@ -0,0 +1,55 @@ +use indoc::writedoc; +use std::fmt::Write as _; + +#[test] +fn test_write_to_string() { + let mut s = String::new(); + writedoc!( + s, + " + one + two + ", + ) + .unwrap(); + + let expected = "one\ntwo\n"; + assert_eq!(s, expected); +} + +#[test] +fn test_format_args() { + let mut s = String::new(); + writedoc!( + s, + " + {} + {} + ", + 0, + 0, + ) + .unwrap(); + + let expected = "0\n0\n"; + assert_eq!(s, expected); +} + +#[test] +fn test_angle_bracket_parsing() { + const ZERO: usize = 0; + + struct Pair<A, B>(A, B); + impl Pair<(), ()> { + const ONE: usize = 1; + } + + let mut s = String::new(); + let _ = writedoc! { + if ZERO < Pair::<(), ()>::ONE { &mut s } else { &mut s }, + "writedoc", + }; + + let expected = "writedoc"; + assert_eq!(s, expected); +} diff --git a/vendor/indoc/tests/ui/no-arguments.rs b/vendor/indoc/tests/ui/no-arguments.rs new file mode 100644 index 0000000000..ea394d8f22 --- /dev/null +++ b/vendor/indoc/tests/ui/no-arguments.rs @@ -0,0 +1,5 @@ +use indoc::indoc; + +fn main() { + indoc!(); +} diff --git a/vendor/indoc/tests/ui/no-arguments.stderr b/vendor/indoc/tests/ui/no-arguments.stderr new file mode 100644 index 0000000000..fa11fd5002 --- /dev/null +++ b/vendor/indoc/tests/ui/no-arguments.stderr @@ -0,0 +1,7 @@ +error: unexpected end of macro invocation, expected format string + --> $DIR/no-arguments.rs:4:5 + | +4 | indoc!(); + | ^^^^^^^^^ + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/vendor/indoc/tests/ui/non-lit.rs b/vendor/indoc/tests/ui/non-lit.rs new file mode 100644 index 0000000000..d51072d884 --- /dev/null +++ b/vendor/indoc/tests/ui/non-lit.rs @@ -0,0 +1,5 @@ +use indoc::indoc; + +fn main() { + indoc!(fail); +} diff --git a/vendor/indoc/tests/ui/non-lit.stderr b/vendor/indoc/tests/ui/non-lit.stderr new file mode 100644 index 0000000000..f2f6bd6eed --- /dev/null +++ b/vendor/indoc/tests/ui/non-lit.stderr @@ -0,0 +1,5 @@ +error: argument must be a single string literal + --> $DIR/non-lit.rs:4:12 + | +4 | indoc!(fail); + | ^^^^ diff --git a/vendor/indoc/tests/ui/non-string.rs b/vendor/indoc/tests/ui/non-string.rs new file mode 100644 index 0000000000..174ea95a84 --- /dev/null +++ b/vendor/indoc/tests/ui/non-string.rs @@ -0,0 +1,5 @@ +use indoc::indoc; + +fn main() { + indoc!(64); +} diff --git a/vendor/indoc/tests/ui/non-string.stderr b/vendor/indoc/tests/ui/non-string.stderr new file mode 100644 index 0000000000..ce7c853c43 --- /dev/null +++ b/vendor/indoc/tests/ui/non-string.stderr @@ -0,0 +1,5 @@ +error: argument must be a single string literal + --> $DIR/non-string.rs:4:12 + | +4 | indoc!(64); + | ^^ diff --git a/vendor/indoc/tests/ui/printdoc-binary.rs b/vendor/indoc/tests/ui/printdoc-binary.rs new file mode 100644 index 0000000000..24e500e665 --- /dev/null +++ b/vendor/indoc/tests/ui/printdoc-binary.rs @@ -0,0 +1,5 @@ +use indoc::printdoc; + +fn main() { + printdoc!(b""); +} diff --git a/vendor/indoc/tests/ui/printdoc-binary.stderr b/vendor/indoc/tests/ui/printdoc-binary.stderr new file mode 100644 index 0000000000..65cb89592b --- /dev/null +++ b/vendor/indoc/tests/ui/printdoc-binary.stderr @@ -0,0 +1,5 @@ +error: byte strings are not supported in formatting macros + --> $DIR/printdoc-binary.rs:4:15 + | +4 | printdoc!(b""); + | ^^^ diff --git a/vendor/indoc/tests/ui/printdoc-extra-arg.rs b/vendor/indoc/tests/ui/printdoc-extra-arg.rs new file mode 100644 index 0000000000..661e3a0b61 --- /dev/null +++ b/vendor/indoc/tests/ui/printdoc-extra-arg.rs @@ -0,0 +1,5 @@ +use indoc::printdoc; + +fn main() { + printdoc!("", 0); +} diff --git a/vendor/indoc/tests/ui/printdoc-extra-arg.stderr b/vendor/indoc/tests/ui/printdoc-extra-arg.stderr new file mode 100644 index 0000000000..1aba276c9e --- /dev/null +++ b/vendor/indoc/tests/ui/printdoc-extra-arg.stderr @@ -0,0 +1,7 @@ +error: argument never used + --> $DIR/printdoc-extra-arg.rs:4:19 + | +4 | printdoc!("", 0); + | -- ^ argument never used + | | + | formatting specifier missing diff --git a/vendor/indoc/tests/ui/printdoc-no-arg.rs b/vendor/indoc/tests/ui/printdoc-no-arg.rs new file mode 100644 index 0000000000..90ea148a19 --- /dev/null +++ b/vendor/indoc/tests/ui/printdoc-no-arg.rs @@ -0,0 +1,5 @@ +use indoc::printdoc; + +fn main() { + printdoc!("{}"); +} diff --git a/vendor/indoc/tests/ui/printdoc-no-arg.stderr b/vendor/indoc/tests/ui/printdoc-no-arg.stderr new file mode 100644 index 0000000000..e9b4940f94 --- /dev/null +++ b/vendor/indoc/tests/ui/printdoc-no-arg.stderr @@ -0,0 +1,5 @@ +error: 1 positional argument in format string, but no arguments were given + --> $DIR/printdoc-no-arg.rs:4:16 + | +4 | printdoc!("{}"); + | ^^ diff --git a/vendor/indoc/tests/ui/printdoc-no-display.rs b/vendor/indoc/tests/ui/printdoc-no-display.rs new file mode 100644 index 0000000000..22c3ebc0e2 --- /dev/null +++ b/vendor/indoc/tests/ui/printdoc-no-display.rs @@ -0,0 +1,7 @@ +use indoc::printdoc; + +struct NoDisplay; + +fn main() { + printdoc!("{}", NoDisplay); +} diff --git a/vendor/indoc/tests/ui/printdoc-no-display.stderr b/vendor/indoc/tests/ui/printdoc-no-display.stderr new file mode 100644 index 0000000000..24f90d4315 --- /dev/null +++ b/vendor/indoc/tests/ui/printdoc-no-display.stderr @@ -0,0 +1,10 @@ +error[E0277]: `NoDisplay` doesn't implement `std::fmt::Display` + --> $DIR/printdoc-no-display.rs:6:21 + | +6 | printdoc!("{}", NoDisplay); + | ^^^^^^^^^ `NoDisplay` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `NoDisplay` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: required by `std::fmt::Display::fmt` + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/vendor/indoc/tests/ui/printdoc-no-named-arg.rs b/vendor/indoc/tests/ui/printdoc-no-named-arg.rs new file mode 100644 index 0000000000..e4d5d97997 --- /dev/null +++ b/vendor/indoc/tests/ui/printdoc-no-named-arg.rs @@ -0,0 +1,5 @@ +use indoc::printdoc; + +fn main() { + printdoc!("{named}"); +} diff --git a/vendor/indoc/tests/ui/printdoc-no-named-arg.stderr b/vendor/indoc/tests/ui/printdoc-no-named-arg.stderr new file mode 100644 index 0000000000..e40cf72c78 --- /dev/null +++ b/vendor/indoc/tests/ui/printdoc-no-named-arg.stderr @@ -0,0 +1,7 @@ +error: there is no argument named `named` + --> $DIR/printdoc-no-named-arg.rs:4:16 + | +4 | printdoc!("{named}"); + | ^^^^^^^ + | + = help: if you intended to capture `named` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes diff --git a/vendor/indoc/tests/ui/three-arguments.rs b/vendor/indoc/tests/ui/three-arguments.rs new file mode 100644 index 0000000000..7bd11e2d24 --- /dev/null +++ b/vendor/indoc/tests/ui/three-arguments.rs @@ -0,0 +1,9 @@ +use indoc::indoc; + +fn main() { + indoc!(" + a + b + c + " 64 128); +} diff --git a/vendor/indoc/tests/ui/three-arguments.stderr b/vendor/indoc/tests/ui/three-arguments.stderr new file mode 100644 index 0000000000..4fb7622ab5 --- /dev/null +++ b/vendor/indoc/tests/ui/three-arguments.stderr @@ -0,0 +1,5 @@ +error: unexpected tokens in macro invocation; indoc argument must be a single string literal + --> $DIR/three-arguments.rs:8:11 + | +8 | " 64 128); + | ^^^^^^ diff --git a/vendor/indoc/tests/ui/two-arguments.rs b/vendor/indoc/tests/ui/two-arguments.rs new file mode 100644 index 0000000000..f979fed426 --- /dev/null +++ b/vendor/indoc/tests/ui/two-arguments.rs @@ -0,0 +1,9 @@ +use indoc::indoc; + +fn main() { + indoc!(" + a + b + c + " 64); +} diff --git a/vendor/indoc/tests/ui/two-arguments.stderr b/vendor/indoc/tests/ui/two-arguments.stderr new file mode 100644 index 0000000000..7abbdc5ea1 --- /dev/null +++ b/vendor/indoc/tests/ui/two-arguments.stderr @@ -0,0 +1,5 @@ +error: unexpected token in macro invocation; indoc argument must be a single string literal + --> $DIR/two-arguments.rs:8:11 + | +8 | " 64); + | ^^ diff --git a/vendor/instant/.cargo-checksum.json b/vendor/instant/.cargo-checksum.json index 7067fc117c..42dbf0c43b 100644 --- a/vendor/instant/.cargo-checksum.json +++ b/vendor/instant/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"AUTHORS":"451a1be16acafff0cb0eaedc49b46063cc6ce087d0c36f6d64d67aa93d20e485","Cargo.toml":"d60aeb70fc62137350e382309a30b1c4ffd840b3336e9eb2c599f386e0405184","LICENSE":"2510d4cde8c4e13d8c54b9fe2a9d144daf567ec8d02832f1454e7ca2d58cdda6","README.md":"0da64b98ed8158455bfc34c119106a9bd7f4641cc7e459f2a50d26c42bea381c","src/lib.rs":"33d3c91a71034c158e224fe0a5fc3123219ebe0461cc6d179d239dd6a5c9c26d","src/native.rs":"4755b502c87d6d0ecbaece30401f603bee6213def48092c6d3dbad59eed4c8ed","src/wasm.rs":"31c181c479016d92d8b55128f956203896be5cf5ad9a4645e1db3dc55c185a9e","tests/wasm.rs":"dafd0ce2a92f969ee9a381d73589e31a4f54ddf97a5b0169ff1990cba00f6699"},"package":"716d3d89f35ac6a34fd0eed635395f4c3b76fa889338a4632e5231a8684216bd"} \ No newline at end of file +{"files":{"AUTHORS":"451a1be16acafff0cb0eaedc49b46063cc6ce087d0c36f6d64d67aa93d20e485","CHANGELOGS.md":"bb587c08dd9b1f04cba934a241a99655f9d7e38bc70e4d45feca95efa09bd799","Cargo.toml":"a64c7ab3a5906d2e7360fb30cc23e5042bd7c22aa640e8e47bb3dad1a3dbf8eb","LICENSE":"2510d4cde8c4e13d8c54b9fe2a9d144daf567ec8d02832f1454e7ca2d58cdda6","README.md":"22b54b9f16ad18144f29e50d1b1f16791c5e8f1afee81265bad9b72f6efb8e62","src/lib.rs":"cc4822f1c4ac7926859045608d91e3f855914468039bffb75bc9b455c0950ab3","src/native.rs":"bd4cd1f888b83a9eaf07f640bef51c4f16138ceb427a685d3ab07152eec53d1c","src/wasm.rs":"c17c7bf8a28fee134444201212d1cf62bff49650f297e42367ec1b7aeaddc7c9","tests/wasm.rs":"1b81ff541bec36bac824a7ec41cd15f68d9919c3c7522290aa003fa4c253e840"},"package":"7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"} \ No newline at end of file diff --git a/vendor/instant/CHANGELOGS.md b/vendor/instant/CHANGELOGS.md new file mode 100644 index 0000000000..092d8aea3a --- /dev/null +++ b/vendor/instant/CHANGELOGS.md @@ -0,0 +1,7 @@ +# v0.1.12 +## Added +- Add `SystemTime` which works in both native and WASM environments. + +## Modified +- The `now` function is always available now: there is no need to enable the `now` feature any more. The `now` feature + still exists (but doesn’t do anything) for backwards compatibility. \ No newline at end of file diff --git a/vendor/instant/Cargo.toml b/vendor/instant/Cargo.toml index 8f41b0d55b..fcd0adff1a 100644 --- a/vendor/instant/Cargo.toml +++ b/vendor/instant/Cargo.toml @@ -12,7 +12,7 @@ [package] edition = "2018" name = "instant" -version = "0.1.11" +version = "0.1.12" authors = ["sebcrozet <developer@crozet.re>"] description = "A partial replacement for std::time::Instant that works on WASM too." readme = "README.md" @@ -26,7 +26,7 @@ version = "0.3" [features] inaccurate = [] -now = ["time"] +now = [] wasm-bindgen = ["js-sys", "wasm-bindgen_rs", "web-sys"] [target.asmjs-unknown-emscripten.dependencies.js-sys] version = "0.3" @@ -45,9 +45,6 @@ package = "wasm-bindgen" version = "0.3" features = ["Window", "Performance", "PerformanceTiming"] optional = true -[target."cfg(not(any(feature = \"stdweb\", feature = \"wasm-bindgen\")))".dependencies.time] -version = "0.2" -optional = true [target.wasm32-unknown-emscripten.dependencies.js-sys] version = "0.3" optional = true diff --git a/vendor/instant/README.md b/vendor/instant/README.md index cad6b59777..0e35ad656c 100644 --- a/vendor/instant/README.md +++ b/vendor/instant/README.md @@ -12,13 +12,12 @@ replacement for `std::time::Instant` that works on WASM too. This defines the ty Note that even if the **stdweb** or **wasm-bindgen** feature is enabled, this crate will continue to rely on `std::time::Instant` as long as you are not targeting wasm32. This allows for portable code that will work on both native and WASM platforms. -### The feature `now`. -By enabling the feature `now` the function `instant::now()` will be exported and will either: +This crate also exports the function `instant::now()` which returns a representation of the current time as an `f64`, expressed in milliseconds, in a platform-agnostic way. `instant::now()` will either: * Call `performance.now()` when compiling for a WASM platform with the features **stdweb** or **wasm-bindgen** enabled, or using a custom javascript function. -* Call `time::precise_time_s() * 1000.0` otherwise. +* Return the time elapsed since the *Unix Epoch* on *native*, *non-WASM* platforms. -The result is expressed in milliseconds. +*Note*: The old feature, `now`, has been deprecated. `instant::now()` is always exported and the `now` feature flag no longer has any effect. It remains listed in `Cargo.toml` to avoid introducing breaking changes and may be removed in future versions. ## Examples ### Using `instant` for a native platform. @@ -32,7 +31,7 @@ _main.rs_: ```rust fn main() { // Will be the same as `std::time::Instant`. - let now = instant::Instant::new(); + let now = instant::Instant::now(); } ``` @@ -51,7 +50,7 @@ _main.rs_: ```rust fn main() { // Will emulate `std::time::Instant` based on `performance.now()`. - let now = instant::Instant::new(); + let now = instant::Instant::now(); } ``` @@ -70,7 +69,7 @@ _main.rs_: ```rust fn main() { // Will emulate `std::time::Instant` based on `Date.now()`. - let now = instant::Instant::new(); + let now = instant::Instant::now(); } ``` @@ -93,13 +92,13 @@ _lib.rs_: fn my_function() { // Will select the proper implementation depending on the // feature selected by the user. - let now = instant::Instant::new(); + let now = instant::Instant::now(); } ``` ----- -### Using the feature `now`. +### Using `instant::now()` _Cargo.toml_: ```toml [features] @@ -107,7 +106,7 @@ stdweb = [ "instant/stdweb" ] wasm-bindgen = [ "instant/wasm-bindgen" ] [dependencies] -instant = { version = "0.1", features = [ "now" ] } +instant = "0.1" ``` _lib.rs_: @@ -115,7 +114,7 @@ _lib.rs_: fn my_function() { // Will select the proper implementation depending on the // feature selected by the user. - let now_instant = instant::Instant::new(); + let now_instant = instant::Instant::now(); let now_milliseconds = instant::now(); // In milliseconds. } ``` @@ -124,14 +123,14 @@ fn my_function() { _Cargo.toml_: ```toml [dependencies] -instant = { version = "0.", features = [ "now" ] } +instant = "0.1" ``` _lib.rs_: ```rust fn my_function() { // Will use the 'now' javascript implementation. - let now_instant = instant::Instant::new(); + let now_instant = instant::Instant::now(); let now_milliseconds = instant::now(); // In milliseconds. } ``` diff --git a/vendor/instant/src/lib.rs b/vendor/instant/src/lib.rs index b3924bdfdd..00d59e7f16 100644 --- a/vendor/instant/src/lib.rs +++ b/vendor/instant/src/lib.rs @@ -9,13 +9,13 @@ cfg_if::cfg_if! { mod wasm; pub use wasm::Instant; - #[cfg(feature = "now")] pub use crate::wasm::now; + pub use wasm::SystemTime; } else { mod native; pub use native::Instant; - #[cfg(feature = "now")] pub use native::now; + pub use native::SystemTime; } } diff --git a/vendor/instant/src/native.rs b/vendor/instant/src/native.rs index 1768ee3d93..37b34f3e8b 100644 --- a/vendor/instant/src/native.rs +++ b/vendor/instant/src/native.rs @@ -1,7 +1,9 @@ pub type Instant = std::time::Instant; +pub type SystemTime = std::time::SystemTime; -/// The current time, in milliseconds. -#[cfg(feature = "now")] +/// The current time, expressed in milliseconds since the Unix Epoch. pub fn now() -> f64 { - time::precise_time_s() * 1000.0 + std::time::SystemTime::now().duration_since(std::time::SystemTime::UNIX_EPOCH) + .expect("System clock was before 1970.") + .as_secs_f64() * 1000.0 } diff --git a/vendor/instant/src/wasm.rs b/vendor/instant/src/wasm.rs index 90bb43f07f..f11b82a703 100644 --- a/vendor/instant/src/wasm.rs +++ b/vendor/instant/src/wasm.rs @@ -1,3 +1,4 @@ +use std::cmp::Ordering; use std::ops::{Add, AddAssign, Sub, SubAssign}; use std::time::Duration; @@ -160,3 +161,80 @@ pub fn now() -> f64 { #[cfg(target_os = "emscripten")] return unsafe { js::_emscripten_get_now() }; } + +/// Returns the number of millisecods elapsed since January 1, 1970 00:00:00 UTC. +#[cfg(any(feature = "wasm-bindgen", feature = "stdweb"))] +fn get_time() -> f64 { + #[cfg(feature = "wasm-bindgen")] + return js_sys::Date::now(); + #[cfg(all(feature = "stdweb", not(feature = "wasm-bindgen")))] + { + let v = js! { return Date.now(); }; + return v.try_into().unwrap(); + } +} + +#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)] +pub struct SystemTime(f64); + +impl SystemTime { + pub const UNIX_EPOCH: SystemTime = SystemTime(0.0); + + pub fn now() -> SystemTime { + cfg_if::cfg_if! { + if #[cfg(any(feature = "wasm-bindgen", feature = "stdweb"))] { + SystemTime(get_time()) + } else { + SystemTime(now()) + } + } + } + + pub fn duration_since(&self, earlier: SystemTime) -> Result<Duration, ()> { + let dur_ms = self.0 - earlier.0; + if dur_ms < 0.0 { + return Err(()); + } + Ok(Duration::from_millis(dur_ms as u64)) + } + + pub fn elapsed(&self) -> Result<Duration, ()> { + self.duration_since(SystemTime::now()) + } + + pub fn checked_add(&self, duration: Duration) -> Option<SystemTime> { + Some(*self + duration) + } + + pub fn checked_sub(&self, duration: Duration) -> Option<SystemTime> { + Some(*self - duration) + } +} + +impl Add<Duration> for SystemTime { + type Output = SystemTime; + + fn add(self, other: Duration) -> SystemTime { + SystemTime(self.0 + other.as_millis() as f64) + } +} + +impl Sub<Duration> for SystemTime { + type Output = SystemTime; + + fn sub(self, other: Duration) -> SystemTime { + SystemTime(self.0 - other.as_millis() as f64) + } +} + +impl AddAssign<Duration> for SystemTime { + fn add_assign(&mut self, rhs: Duration) { + *self = *self + rhs; + } +} + +impl SubAssign<Duration> for SystemTime { + fn sub_assign(&mut self, rhs: Duration) { + *self = *self - rhs; + } +} diff --git a/vendor/instant/tests/wasm.rs b/vendor/instant/tests/wasm.rs index 0f7f905a11..7dacdc4f9e 100644 --- a/vendor/instant/tests/wasm.rs +++ b/vendor/instant/tests/wasm.rs @@ -1,6 +1,6 @@ extern crate wasm_bindgen_test; -use instant::Instant; +use instant::{Instant, SystemTime}; use std::time::Duration; use wasm_bindgen_test::*; @@ -47,3 +47,11 @@ fn test_checked_sub() { .checked_sub(Duration::new(u64::MAX, ONE_BILLION - 1)) .is_none()); } + +#[wasm_bindgen_test] +fn test_system_time() { + assert!(SystemTime::UNIX_EPOCH + .duration_since(SystemTime::now()) + .is_err()); +} + diff --git a/vendor/itertools-0.8.2/.cargo-checksum.json b/vendor/itertools-0.8.2/.cargo-checksum.json deleted file mode 100644 index 4df07cd850..0000000000 --- a/vendor/itertools-0.8.2/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"Cargo.lock":"bb03f756d39151fea8de875ac282889d4370443e6fee0c4edf5b33e53f983246","Cargo.toml":"e0c22789bdbb1efe1c80b861e7c00da2015b4d7eacb00fcf827ba28d82e36a2e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7576269ea71f767b99297934c0b2367532690f8c4badc695edf8e04ab6a1e545","README.rst":"86c2f8499d778ff74de701ca291420c244bf4c7be94fb73bed32fcafc4cf467a","benches/bench1.rs":"126211884ea482d5176535ca0b35bfa4d28c62c3377db77aaf7b7c12f712577c","benches/combinations_with_replacement.rs":"b15e1694991a35936b5b4eb8525fbc2bfa3720ecebffb01684e7b4b72541c328","benches/extra/mod.rs":"4c5b03e74fc5b02383500c9da9fd6550262706ee569d70d085700f6d0b5749ba","benches/extra/zipslices.rs":"108dd488de366b2d83fb6bcc603ecbf9a017e165ac19d03440074fa244af3fb2","benches/fold_specialization.rs":"1b9753d6adaf6d1e979d9d2af535255e23a94bb0d4f27b57bb9005a944aaec81","benches/tree_fold1.rs":"84cddbabb1a681f3196430a8e27b060103366143a3ee4c42c3b0628fc00a7543","benches/tuple_combinations.rs":"6a4b89eb2e45fa0c99e5e5942b3196b76998213c66c44b3765b869be42016a82","benches/tuples.rs":"412a952f08bb03695952d5cfd57949dcf28be8b99e3c6653994bdb8af9654653","examples/iris.data":"596ffd580471ca4d4880f8e439c7281f3b50d8249a5960353cb200b1490f63a0","examples/iris.rs":"3996ca0a62762aec2b102f0f4244fe90d4b4354286d68d80cdc40e35f4352ba3","src/adaptors/mod.rs":"d4be18d69488b2c5dc6679f554c0a3eacc079bb9b55996505e56491be13d22cb","src/adaptors/multi_product.rs":"bb239555be38cde1f419bacfd09728f6ccaf51b6b4811c266b5677705175e685","src/combinations.rs":"bfbb4cb3975128b1a4daa96350be6b2f3de1d1a937d8351034a72f9f051cdd73","src/combinations_with_replacement.rs":"dc05611ab3f86a9ffe96dcb10c16d65c7619343d323f20e7142d094abe539bc2","src/concat_impl.rs":"276339b00588f54c25f8ffbe0ae3c0031f7e52fb53c6578554a0bde1681b58a5","src/cons_tuples_impl.rs":"87c620d2ffdd3475218f5f493dbef601491be9f6cdfe57c44929449b32e6709f","src/diff.rs":"921e2b867d7b32ffedc72a5eb780811322d14d1e0883a608b9028a2afcad0df2","src/either_or_both.rs":"b7bf810817795465d9e6e43fd0ba02eebbb58d19b62b2eaaebef10dc2a51e769","src/exactly_one_err.rs":"94aa8d7495dd138720863cfddd6da07ec6f85ea74d9af88d3f08805e7cae2310","src/format.rs":"412fbe02f12311c6fbcec1044f57ad6991783f5a3f323b9c391accfe4915106f","src/free.rs":"473d19906720eb2a1309c0505497658b1426f3ea0c845b40f41f3154194fff18","src/group_map.rs":"872d6e243e649ad30c94973c034596cc3377b10018e361bca07e11c612006de6","src/groupbylazy.rs":"a067a12671be9ae05a9152518103f39f7286fde09f758de8af75a1064a3b5567","src/impl_macros.rs":"eb0bb3f70ec1bcaffa6110ae4134c777951ed1e5f48d8c811dbf0a597dc48faa","src/intersperse.rs":"5ea6966e91b26d3e883a3a68b74c107c7ec47da8ccb5b3b95acd9cbb0bc66e2a","src/kmerge_impl.rs":"44c3645d864a00ae1ae6aa2f09ff8be704e7e2452da02e95d02cd3f588caa3ac","src/lazy_buffer.rs":"ed60449deb6d775b054f6165718ae1b70ee84d69ffc015df5b769b73c3133054","src/lib.rs":"359c00d77510384e3ed18647ecd8e2f618758ab7944ca31eb960dabcfa25fc2a","src/merge_join.rs":"98e6fcc761a558ad21789efe041c3f90e62f6c75e05840670df45ad4f9b07e1f","src/minmax.rs":"4668a7f824fbc133599f43ffb6f7283e5bd603e07df2d8176abc6f25d6af9db0","src/multipeek_impl.rs":"ebe9544d94d0bf7200f7625241a3b5a291b7b564091a08cad40ff08b51f1b1bf","src/pad_tail.rs":"078615a2892f8c6db665074cf6f1be1bef4cf5ee418bc174edcfd4dc703e163f","src/peeking_take_while.rs":"6aea3bb40fb480e9f3695ce2a7a3a2e2346d437ca846d20e6bb3c09beb0934f4","src/permutations.rs":"862a53d18e8f5d600da1c60befcda98978617ab01c744bd9baf1ed3dd74f1261","src/process_results_impl.rs":"5f454cf62ceb82cab7c08c0c190de3ae083e219a8acc7a1a22f17eec9cfcd65c","src/put_back_n_impl.rs":"d35858184c525372b22d14d42cdf63726cf0fd50f5bd42ec7a82d55a8e180e9f","src/rciter_impl.rs":"8f51abc7e1ae3320cc5d56fadd66f880a7a06773be656bd8c4712357f01ae1d9","src/repeatn.rs":"4bd1782364b16105fbef3f3de7bf62780710e5c996db44a00e4b5f16c2625d86","src/size_hint.rs":"c1d35b422a696cf3d63e7c90d8f9fdf01a304cf8156e914287c4ef48fea62dd3","src/sources.rs":"cb6ebe06b05f7da0ac1073ba486c45afaeebf8b558c0f5499f0eacd2cd1785da","src/tee.rs":"59cf9ef0b41882307ea1e3503a2ff351f401f4c43d95acf423a990b0bf0e29ae","src/tuple_impl.rs":"0c7f907e85d2ef0661583b36c7b8a7341b8feadafe28d10539a211dff5c028ea","src/unique_impl.rs":"63db2d720ff5e3d9c0d6c2b245ffff25d4040e4fcbcb2a6524b0f912826f86af","src/with_position.rs":"d922f045f6fa090a431be928f3221c6dc37ac6f9bb54461b3b84f99a7e91244a","src/zip_eq_impl.rs":"f857c69120255db16ad6ddec628c79cb573b1d5179fcebab1906bf5b762c02e3","src/zip_longest.rs":"375325ef069970e6fb83c6097c2824877bb0f06e4f1e664e4fe681804abe003c","src/ziptuple.rs":"d7ae7d3c33185ad74ab2bba750ac337b5c236750cc8341dd9883faf6465712a1","tests/adaptors_no_collect.rs":"2572c5555cc2e494a44714710dbaf5d62965d847f4e620ea09e52a7158371364","tests/fold_specialization.rs":"de403af575c6c77234bff2a5e56581159c5ceeff30eadaac14bfd8d405c16bec","tests/merge_join.rs":"546eaffae40010f15a7bcf95bc53f5e9b67424c5b93df6ffb0aaa1e48e8b90c0","tests/peeking_take_while.rs":"a2ae6474e09620a47bb8a6e3c62929261e72c52881370adb2d22e89aa9e9aec8","tests/quick.rs":"b0d36a7ab4aa8b7283c9440b8a4f4867acab951da9aaec59a7314e1b39782be8","tests/test_core.rs":"8d73cb165698dbfaf0d14e278fbd02bda4b92c2a552912ce1a67388a9fe54bcf","tests/test_std.rs":"40a7a001afbf79e08ec970e091799d7e35ee72fdad8baf16a850a1abecf4e921","tests/tuples.rs":"5323d15a7abf6545b2655167d3206b6cf6a947e9409a244ea6a8cf4ad8ceac64","tests/zip.rs":"fe213d70c4fa114cb4d1930a6b971f4af617a239041ddb87e6b5a9bbe62261b8"},"package":"f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484"} \ No newline at end of file diff --git a/vendor/itertools-0.8.2/Cargo.lock b/vendor/itertools-0.8.2/Cargo.lock deleted file mode 100644 index a34644cf2c..0000000000 --- a/vendor/itertools-0.8.2/Cargo.lock +++ /dev/null @@ -1,227 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -[[package]] -name = "autocfg" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bitflags" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "cloudabi" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "either" -version = "1.5.3" -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 = "itertools" -version = "0.8.2" -dependencies = [ - "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "permutohedron 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "quickcheck 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (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 = "permutohedron" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "quickcheck" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand" -version = "0.5.6" -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.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (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.7 (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.2 (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.8 (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.7 (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.2.2" -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_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "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.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (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.2 (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.8 (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.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (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 = "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 = "winapi" -version = "0.3.8" -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" - -[metadata] -"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" -"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" -"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" -"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -"checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8" -"checksum permutohedron 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b687ff7b5da449d39e418ad391e5e08da53ec334903ddbb921db208908fc372c" -"checksum quickcheck 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4537d3e4edf73a15dd059b75bed1c292d17d3ea7517f583cebe716794fcf816" -"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" -"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.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" -"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" -"checksum 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_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 rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" -"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" diff --git a/vendor/itertools-0.8.2/Cargo.toml b/vendor/itertools-0.8.2/Cargo.toml deleted file mode 100644 index db22e36866..0000000000 --- a/vendor/itertools-0.8.2/Cargo.toml +++ /dev/null @@ -1,47 +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 = "itertools" -version = "0.8.2" -authors = ["bluss"] -exclude = ["/bors.toml"] -description = "Extra iterator adaptors, iterator methods, free functions, and macros." -documentation = "https://docs.rs/itertools/" -keywords = ["iterator", "data-structure", "zip", "product", "group-by"] -categories = ["algorithms", "rust-patterns"] -license = "MIT/Apache-2.0" -repository = "https://github.com/bluss/rust-itertools" -[package.metadata.release] -no-dev-version = true -[profile.bench] -debug = true - -[lib] -test = false -bench = false -[dependencies.either] -version = "1.0" -default-features = false -[dev-dependencies.permutohedron] -version = "0.2" - -[dev-dependencies.quickcheck] -version = "0.7" -default-features = false - -[dev-dependencies.rand] -version = "0.6" - -[features] -default = ["use_std"] -use_std = [] diff --git a/vendor/itertools-0.8.2/README.rst b/vendor/itertools-0.8.2/README.rst deleted file mode 100644 index b06751afef..0000000000 --- a/vendor/itertools-0.8.2/README.rst +++ /dev/null @@ -1,620 +0,0 @@ - -Itertools -========= - -Extra iterator adaptors, functions and macros. - -Please read the `API documentation here`__ - -__ https://docs.rs/itertools/ - -|build_status|_ |crates|_ - -.. |build_status| image:: https://travis-ci.org/rust-itertools/itertools.svg?branch=master -.. _build_status: https://travis-ci.org/rust-itertools/itertools - -.. |crates| image:: http://meritbadge.herokuapp.com/itertools -.. _crates: https://crates.io/crates/itertools - -How to use with cargo: - -.. code:: toml - - [dependencies] - itertools = "0.8" - -How to use in your crate: - -.. code:: rust - - #[macro_use] extern crate itertools; - - use itertools::Itertools; - -How to contribute ------------------ - -- Fix a bug or implement a new thing -- Include tests for your new feature, preferably a quickcheck test -- Make a Pull Request - -For new features, please first consider filing a PR to `rust-lang/rust <https://github.com/rust-lang/rust/>`_, -adding your new feature to the `Iterator` trait of the standard library, if you believe it is reasonable. -If it isn't accepted there, proposing it for inclusion in ``itertools`` is a good idea. -The reason for doing is this is so that we avoid future breakage as with ``.flatten()``. -However, if your feature involves heap allocation, such as storing elements in a ``Vec<T>``, -then it can't be accepted into ``libcore``, and you should propose it for ``itertools`` directly instead. - -Recent Changes --------------- -- 0.8.2 - - - Use :code:`slice::iter` instead of :code:`into_iter` to avoid future breakage (`#378 <https://github.com/rust-itertools/itertools/pull/378>`_, by `@LukasKalbertodt <https://github.com/LukasKalbertodt>`_) - -- 0.8.1 - - - Added a `.exactly_one() <https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.exactly_one>`_ - iterator method that, on success, extracts the single value of an - iterator - ; by `@Xaeroxe <https://github.com/Xaeroxe>`_ - - - Added combinatory iterator adaptors: - - - `.permutations(k) <https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.permutations>`_: - - ``[0, 1, 2].iter().permutations(2)`` yields - - .. code:: rust - - [ - vec![0, 1], - vec![0, 2], - vec![1, 0], - vec![1, 2], - vec![2, 0], - vec![2, 1], - ] - - ; by `@tobz1000 <https://github.com/tobz1000>`_ - - - `.combinations_with_replacement(k) <https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.combinations_with_replacement>`_: - - ``[0, 1, 2].iter().combinations_with_replacement(2)`` yields - - .. code:: rust - - [ - vec![0, 0], - vec![0, 1], - vec![0, 2], - vec![1, 1], - vec![1, 2], - vec![2, 2], - ] - - ; by `@tommilligan <https://github.com/tommilligan>`_ - - - For reference, these methods join the already existing - `.combinations(k) <https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.combinations>`_: - - ``[0, 1, 2].iter().combinations(2)`` yields - - .. code:: rust - - [ - vec![0, 1], - vec![0, 2], - vec![1, 2], - ] - - - Improved the performance of `.fold() <https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.fold>`_-based internal iteration for the - `.intersperse() <https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.intersperse>`_ iterator - ; by `@jswrenn <https://github.com/jswrenn>`_ - - - Added - `.dedup_by() <https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.dedup_by>`_, - `.merge_by() <https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.merge_by>`_ - and `.kmerge_by() <https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.kmerge_by>`_ - adaptors that work like - `.dedup() <https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.dedup>`_, - `.merge() <https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.merge>`_ and - `.kmerge() <https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.kmerge>`_, - but taking an additional custom comparison closure parameter. - ; by `@phimuemue <https://github.com/phimuemue>`_ - - - Improved the performance of `.all_equal() <https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.all_equal>`_ - ; by `@fyrchik <https://github.com/fyrchik>`_ - - - Loosened the bounds on `.partition_map() <https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.partition_map>`_ - to take just a ``FnMut`` closure rather than a ``Fn`` closure, and made its - implementation use internal iteration for better performance - ; by `@danielhenrymantilla <https://github.com/danielhenrymantilla>`_ - - - Added convenience methods to - `EitherOrBoth <https://docs.rs/itertools/0.8.1/itertools/enum.EitherOrBoth.html>`_ elements yielded from the - `.zip_longest() <https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.zip_longest>`_ iterator adaptor - ; by `@Avi-D-coder <https://github.com/Avi-D-coder>`_ - - - Added `.sum1() <https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.sum1>`_ - and `.product1() <https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.product1>`_ - iterator methods that respectively try to return the sum and the product of - the elements of an iterator **when it is not empty**, otherwise they return - ``None`` - ; by `@Emerentius <https://github.com/Emerentius>`_ - -- 0.8.0 - - - Added new adaptor ``.map_into()`` for conversions using ``Into`` by @vorner - - Improved ``Itertools`` docs by @JohnHeitmann - - The return type of ``.sorted/_by/_by_key()`` is now an iterator, not a Vec. - - The return type of the ``izip!(x, y)`` macro with exactly two arguments - is now the usual ``Iterator::zip``. - - Remove ``.flatten()`` in favour of std's ``.flatten()`` - - Deprecate ``.foreach()`` in favour of std's ``.for_each()`` - - Deprecate ``.step()`` in favour of std's ``.step_by()`` - - Deprecate ``repeat_call`` in favour of std's ``repeat_with`` - - Deprecate ``.fold_while()`` in favour of std's ``.try_fold()`` - - Require Rust 1.24 as minimal version. - -- 0.7.11 - - - Add convenience methods to ``EitherOrBoth``, making it more similar to ``Option`` - and ``Either`` by @jethrogb - -- 0.7.10 - - - No changes. - -- 0.7.9 - - - New inclusion policy: See the readme about suggesting features for std before - accepting them in itertools. - - The ``FoldWhile`` type now implements ``Eq`` and ``PartialEq`` by @jturner314 - -- 0.7.8 - - - Add new iterator method ``.tree_fold1()`` which is like ``.fold1()`` - except items are combined in a tree structure (see its docs). - By @scottmcm - - Add more ``Debug`` impls by @phimuemue: KMerge, KMergeBy, MergeJoinBy, - ConsTuples, Intersperse, ProcessResults, RcIter, Tee, TupleWindows, Tee, - ZipLongest, ZipEq, Zip. - -- 0.7.7 - - - Add new iterator method ``.into_group_map() -> HashMap<K, Vec<V>>`` - which turns an iterator of ``(K, V)`` elements into such a hash table, - where values are grouped by key. By @tobz1000 - - Add new free function ``flatten`` for the ``.flatten()`` adaptor. - **NOTE:** recent Rust nightlies have ``Iterator::flatten`` and thus a clash - with our flatten adaptor. One workaround is to use the itertools ``flatten`` - free function. - -- 0.7.6 - - - Add new adaptor ``.multi_cartesian_product()`` which is an n-ary product - iterator by @tobz1000 - - Add new method ``.sorted_by_key()`` by @Xion - - Provide simpler and faster ``.count()`` for ``.unique()`` and ``.unique_by()`` - -- 0.7.5 - - - ``.multipeek()`` now implements ``PeekingNext``, by @nicopap. - -- 0.7.4 - - - Add new adaptor ``.update()`` by @lucasem; this adaptor is used - to modify an element before passing it on in an iterator chain. - -- 0.7.3 - - - Add new method ``.collect_tuple()`` by @matklad; it makes a tuple out of - the iterator's elements if the number of them matches **exactly**. - - Implement ``fold`` and ``collect`` for ``.map_results()`` which means - it reuses the code of the standard ``.map()`` for these methods. - -- 0.7.2 - - - Add new adaptor ``.merge_join_by`` by @srijs; a heterogeneous merge join - for two ordered sequences. - -- 0.7.1 - - - Iterator adaptors and iterators in itertools now use the same ``must_use`` - reminder that the standard library adaptors do, by @matematikaedit and @bluss - *“iterator adaptors are lazy and do nothing unless consumed”*. - -- 0.7.0 - - - Faster ``izip!()`` by @krdln - - - ``izip!()`` is now a wrapper for repeated regular ``.zip()`` and - a single ``.map()``. This means it optimizes as well as the standard - library ``.zip()`` it uses. - **Note:** ``multizip`` and ``izip!()`` are now different! The former - has a named type but the latter optimizes better. - - - Faster ``.unique()`` - - - ``no_std`` support, which is opt-in! - - - Many lovable features are still there without std, like ``izip!()`` - or ``.format()`` or ``.merge()``, but not those that use collections. - - - Trait bounds were required up front instead of just on the type: - ``group_by``'s ``PartialEq`` by @Phlosioneer and ``repeat_call``'s - ``FnMut``. - - Removed deprecated constructor ``Zip::new`` — use ``izip!()`` or ``multizip()`` - -- 0.6.5 - - - Fix bug in ``.cartesian_product()``'s fold (which only was visible for - unfused iterators). - -- 0.6.4 - - - Add specific ``fold`` implementations for ``.cartesian_product()`` and - ``cons_tuples()``, which improves their performance in fold, foreach, and - iterator consumers derived from them. - -- 0.6.3 - - - Add iterator adaptor ``.positions(predicate)`` by @tmccombs - -- 0.6.2 - - - Add function ``process_results`` which can “lift” a function of the regular - values of an iterator so that it can process the ``Ok`` values from an - iterator of ``Results`` instead, by @shepmaster - - Add iterator method ``.concat()`` which combines all iterator elements - into a single collection using the ``Extend`` trait, by @srijs - -- 0.6.1 - - - Better size hint testing and subsequent size hint bugfixes by @rkarp. - Fixes bugs in product, interleave_shortest size hints. - - New iterator method ``.all_equal()`` by @phimuemue - -- 0.6.0 - - - Deprecated names were removed in favour of their replacements - - ``.flatten()`` does not implement double ended iteration anymore - - ``.fold_while()`` uses ``&mut self`` and returns ``FoldWhile<T>``, for - composability (#168) - - ``.foreach()`` and ``.fold1()`` use ``self``, like ``.fold()`` does. - - ``.combinations(0)`` now produces a single empty vector. (#174) - -- 0.5.10 - - - Add itertools method ``.kmerge_by()`` (and corresponding free function) - - Relaxed trait requirement of ``.kmerge()`` and ``.minmax()`` to PartialOrd. - -- 0.5.9 - - - Add multipeek method ``.reset_peek()`` - - Add categories - -- 0.5.8 - - - Add iterator adaptor ``.peeking_take_while()`` and its trait ``PeekingNext``. - -- 0.5.7 - - - Add iterator adaptor ``.with_position()`` - - Fix multipeek's performance for long peeks by using ``VecDeque``. - -- 0.5.6 - - - Add ``.map_results()`` - -- 0.5.5 - - - Many more adaptors now implement ``Debug`` - - Add free function constructor ``repeat_n``. ``RepeatN::new`` is now - deprecated. - -- 0.5.4 - - - Add infinite generator function ``iterate``, that takes a seed and a - closure. - -- 0.5.3 - - - Special-cased ``.fold()`` for flatten and put back. ``.foreach()`` - now uses fold on the iterator, to pick up any iterator specific loop - implementation. - - ``.combinations(n)`` asserts up front that ``n != 0``, instead of - running into an error on the second iterator element. - -- 0.5.2 - - - Add ``.tuples::<T>()`` that iterates by two, three or four elements at - a time (where ``T`` is a tuple type). - - Add ``.tuple_windows::<T>()`` that iterates using a window of the - two, three or four most recent elements. - - Add ``.next_tuple::<T>()`` method, that picks the next two, three or four - elements in one go. - - ``.interleave()`` now has an accurate size hint. - -- 0.5.1 - - - Workaround module/function name clash that made racer crash on completing - itertools. Only internal changes needed. - -- 0.5.0 - - - `Release announcement <http://bluss.github.io/rust/2016/09/26/itertools-0.5.0/>`_ - - Renamed: - - - combinations is now tuple_combinations - - combinations_n to combinations - - group_by_lazy, chunks_lazy to group_by, chunks - - Unfold::new to unfold() - - RepeatCall::new to repeat_call() - - Zip::new to multizip - - PutBack::new, PutBackN::new to put_back, put_back_n - - PutBack::with_value is now a builder setter, not a constructor - - MultiPeek::new, .multipeek() to multipeek() - - format to format_with and format_default to format - - .into_rc() to rciter - - ``Partition`` enum is now ``Either`` - - - Module reorganization: - - - All iterator structs are under ``itertools::structs`` but also - reexported to the top level, for backwards compatibility - - All free functions are reexported at the root, ``itertools::free`` will - be removed in the next version - - - Removed: - - - ZipSlices, use .zip() instead - - .enumerate_from(), ZipTrusted, due to being unstable - - .mend_slices(), moved to crate odds - - Stride, StrideMut, moved to crate odds - - linspace(), moved to crate itertools-num - - .sort_by(), use .sorted_by() - - .is_empty_hint(), use .size_hint() - - .dropn(), use .dropping() - - .map_fn(), use .map() - - .slice(), use .take() / .skip() - - helper traits in misc - - ``new`` constructors on iterator structs, use Itertools trait or free - functions instead - - ``itertools::size_hint`` is now private - - - Behaviour changes: - - - format and format_with helpers now panic if you try to format them more - than once. - - ``repeat_call`` is not double ended anymore - - - New features: - - - tuple flattening iterator is constructible with ``cons_tuples`` - - itertools reexports ``Either`` from the ``either`` crate. ``Either<L, R>`` - is an iterator when ``L, R`` are. - - ``MinMaxResult`` now implements Copy and Clone - - tuple_combinations supports 1-4 tuples of combinations (previously just 2) - -- 0.4.19 - - - Add ``.minmax_by()`` - - Add ``itertools::free::cloned`` - - Add ``itertools::free::rciter`` - - Improve ``.step(n)`` slightly to take advantage of specialized Fuse better. - -- 0.4.18 - - - Only changes related to the "unstable" crate feature. This feature is more - or less deprecated. - - - Use deprecated warnings when unstable is enabled. .enumerate_from() will - be removed imminently since it's using a deprecated libstd trait. - -- 0.4.17 - - - Fix bug in .kmerge() that caused it to often produce the wrong order (#134) - -- 0.4.16 - - - Improve precision of the interleave_shortest adaptor's size hint (it is - now computed exactly when possible). - -- 0.4.15 - - - Fixup on top of the workaround in 0.4.14. A function in itertools::free was - removed by mistake and now it is added back again. - -- 0.4.14 - - - Workaround an upstream regression in a rust nightly build that broke - compilation of of itertools::free::{interleave, merge} - -- 0.4.13 - - - Add .minmax() and .minmax_by_key(), iterator methods for finding both minimum - and maximum in one scan. - - Add .format_default(), a simpler version of .format() (lazy formatting - for iterators). - -- 0.4.12 - - - Add .zip_eq(), an adaptor like .zip() except it ensures iterators - of inequal length don't pass silently (instead it panics). - - Add .fold_while(), an iterator method that is a fold that - can short-circuit. - - Add .partition_map(), an iterator method that can separate elements - into two collections. - -- 0.4.11 - - - Add .get() for Stride{,Mut} and .get_mut() for StrideMut - -- 0.4.10 - - - Improve performance of .kmerge() - -- 0.4.9 - - - Add k-ary merge adaptor .kmerge() - - Fix a bug in .islice() with ranges a..b where a > b. - -- 0.4.8 - - - Implement Clone, Debug for Linspace - -- 0.4.7 - - - Add function diff_with() that compares two iterators - - Add .combinations_n(), an n-ary combinations iterator - - Add methods PutBack::with_value and PutBack::into_parts. - -- 0.4.6 - - - Add method .sorted() - - Add module ``itertools::free`` with free function variants of common - iterator adaptors and methods. - For example ``enumerate(iterable)``, ``rev(iterable)``, and so on. - -- 0.4.5 - - - Add .flatten() - -- 0.4.4 - - - Allow composing ZipSlices with itself - -- 0.4.3 - - - Write iproduct!() as a single expression; this allows temporary values - in its arguments. - -- 0.4.2 - - - Add .fold_options() - - Require Rust 1.1 or later - -- 0.4.1 - - - Update .dropping() to take advantage of .nth() - -- 0.4.0 - - - .merge(), .unique() and .dedup() now perform better due to not using - function pointers - - Add free functions enumerate() and rev() - - Breaking changes: - - - Return types of .merge() and .merge_by() renamed and changed - - Method Merge::new removed - - .merge_by() now takes a closure that returns bool. - - Return type of .dedup() changed - - Return type of .mend_slices() changed - - Return type of .unique() changed - - Removed function times(), struct Times: use a range instead - - Removed deprecated macro icompr!() - - Removed deprecated FnMap and method .fn_map(): use .map_fn() - - .interleave_shortest() is no longer guaranteed to act like fused - -- 0.3.25 - - - Rename .sort_by() to .sorted_by(). Old name is deprecated. - - Fix well-formedness warnings from RFC 1214, no user visible impact - -- 0.3.24 - - - Improve performance of .merge()'s ordering function slightly - -- 0.3.23 - - - Added .chunks(), similar to (and based on) .group_by_lazy(). - - Tweak linspace to match numpy.linspace and make it double ended. - -- 0.3.22 - - - Added ZipSlices, a fast zip for slices - -- 0.3.21 - - - Remove `Debug` impl for `Format`, it will have different use later - -- 0.3.20 - - - Optimize .group_by_lazy() - -- 0.3.19 - - - Added .group_by_lazy(), a possibly nonallocating group by - - Added .format(), a nonallocating formatting helper for iterators - - Remove uses of RandomAccessIterator since it has been deprecated in rust. - -- 0.3.17 - - - Added (adopted) Unfold from rust - -- 0.3.16 - - - Added adaptors .unique(), .unique_by() - -- 0.3.15 - - - Added method .sort_by() - -- 0.3.14 - - - Added adaptor .while_some() - -- 0.3.13 - - - Added adaptor .interleave_shortest() - - Added adaptor .pad_using() - -- 0.3.11 - - - Added assert_equal function - -- 0.3.10 - - - Bugfix .combinations() size_hint. - -- 0.3.8 - - - Added source RepeatCall - -- 0.3.7 - - - Added adaptor PutBackN - - Added adaptor .combinations() - -- 0.3.6 - - - Added itertools::partition, partition a sequence in place based on a predicate. - - Deprecate icompr!() with no replacement. - -- 0.3.5 - - - .map_fn() replaces deprecated .fn_map(). - -- 0.3.4 - - - .take_while_ref() *by-ref adaptor* - - .coalesce() *adaptor* - - .mend_slices() *adaptor* - -- 0.3.3 - - - .dropping_back() *method* - - .fold1() *method* - - .is_empty_hint() *method* - -License -------- - -Dual-licensed to be compatible with the Rust project. - -Licensed under the Apache License, Version 2.0 -http://www.apache.org/licenses/LICENSE-2.0 or the MIT license -http://opensource.org/licenses/MIT, at your -option. This file may not be copied, modified, or distributed -except according to those terms. diff --git a/vendor/itertools-0.8.2/benches/bench1.rs b/vendor/itertools-0.8.2/benches/bench1.rs deleted file mode 100644 index 5d2adcad40..0000000000 --- a/vendor/itertools-0.8.2/benches/bench1.rs +++ /dev/null @@ -1,806 +0,0 @@ -#![feature(test)] - -extern crate test; -#[macro_use] extern crate itertools; - -use test::{black_box}; -use itertools::Itertools; - -use itertools::free::cloned; -use itertools::Permutations; - -use std::iter::repeat; -use std::cmp; -use std::ops::{Add, Range}; - -mod extra; - -use extra::ZipSlices; - -#[bench] -fn slice_iter(b: &mut test::Bencher) -{ - let xs: Vec<_> = repeat(1i32).take(20).collect(); - b.iter(|| for elt in xs.iter() { - test::black_box(elt); - }) -} - -#[bench] -fn slice_iter_rev(b: &mut test::Bencher) -{ - let xs: Vec<_> = repeat(1i32).take(20).collect(); - b.iter(|| for elt in xs.iter().rev() { - test::black_box(elt); - }) -} - -#[bench] -fn zip_default_zip(b: &mut test::Bencher) -{ - let xs = vec![0; 1024]; - let ys = vec![0; 768]; - let xs = black_box(xs); - let ys = black_box(ys); - - b.iter(|| { - for (&x, &y) in xs.iter().zip(&ys) { - test::black_box(x); - test::black_box(y); - } - }) -} - -#[bench] -fn zipdot_i32_default_zip(b: &mut test::Bencher) -{ - let xs = vec![2; 1024]; - let ys = vec![2; 768]; - let xs = black_box(xs); - let ys = black_box(ys); - - b.iter(|| { - let mut s = 0; - for (&x, &y) in xs.iter().zip(&ys) { - s += x * y; - } - s - }) -} - -#[bench] -fn zipdot_f32_default_zip(b: &mut test::Bencher) -{ - let xs = vec![2f32; 1024]; - let ys = vec![2f32; 768]; - let xs = black_box(xs); - let ys = black_box(ys); - - b.iter(|| { - let mut s = 0.; - for (&x, &y) in xs.iter().zip(&ys) { - s += x * y; - } - s - }) -} - -#[bench] -fn zip_default_zip3(b: &mut test::Bencher) -{ - let xs = vec![0; 1024]; - let ys = vec![0; 768]; - let zs = vec![0; 766]; - let xs = black_box(xs); - let ys = black_box(ys); - let zs = black_box(zs); - - b.iter(|| { - for ((&x, &y), &z) in xs.iter().zip(&ys).zip(&zs) { - test::black_box(x); - test::black_box(y); - test::black_box(z); - } - }) -} - -#[bench] -fn zip_slices_ziptuple(b: &mut test::Bencher) -{ - let xs = vec![0; 1024]; - let ys = vec![0; 768]; - - b.iter(|| { - let xs = black_box(&xs); - let ys = black_box(&ys); - for (&x, &y) in itertools::multizip((xs, ys)) { - test::black_box(x); - test::black_box(y); - } - }) -} - -#[bench] -fn zipslices(b: &mut test::Bencher) -{ - let xs = vec![0; 1024]; - let ys = vec![0; 768]; - let xs = black_box(xs); - let ys = black_box(ys); - - b.iter(|| { - for (&x, &y) in ZipSlices::new(&xs, &ys) { - test::black_box(x); - test::black_box(y); - } - }) -} - -#[bench] -fn zipslices_mut(b: &mut test::Bencher) -{ - let xs = vec![0; 1024]; - let ys = vec![0; 768]; - let xs = black_box(xs); - let mut ys = black_box(ys); - - b.iter(|| { - for (&x, &mut y) in ZipSlices::from_slices(&xs[..], &mut ys[..]) { - test::black_box(x); - test::black_box(y); - } - }) -} - -#[bench] -fn zipdot_i32_zipslices(b: &mut test::Bencher) -{ - let xs = vec![2; 1024]; - let ys = vec![2; 768]; - let xs = black_box(xs); - let ys = black_box(ys); - - b.iter(|| { - let mut s = 0i32; - for (&x, &y) in ZipSlices::new(&xs, &ys) { - s += x * y; - } - s - }) -} - -#[bench] -fn zipdot_f32_zipslices(b: &mut test::Bencher) -{ - let xs = vec![2f32; 1024]; - let ys = vec![2f32; 768]; - let xs = black_box(xs); - let ys = black_box(ys); - - b.iter(|| { - let mut s = 0.; - for (&x, &y) in ZipSlices::new(&xs, &ys) { - s += x * y; - } - s - }) -} - - -#[bench] -fn zip_checked_counted_loop(b: &mut test::Bencher) -{ - let xs = vec![0; 1024]; - let ys = vec![0; 768]; - let xs = black_box(xs); - let ys = black_box(ys); - - b.iter(|| { - // Must slice to equal lengths, and then bounds checks are eliminated! - let len = cmp::min(xs.len(), ys.len()); - let xs = &xs[..len]; - let ys = &ys[..len]; - - for i in 0..len { - let x = xs[i]; - let y = ys[i]; - test::black_box(x); - test::black_box(y); - } - }) -} - -#[bench] -fn zipdot_i32_checked_counted_loop(b: &mut test::Bencher) -{ - let xs = vec![2; 1024]; - let ys = vec![2; 768]; - let xs = black_box(xs); - let ys = black_box(ys); - - b.iter(|| { - // Must slice to equal lengths, and then bounds checks are eliminated! - let len = cmp::min(xs.len(), ys.len()); - let xs = &xs[..len]; - let ys = &ys[..len]; - - let mut s = 0i32; - - for i in 0..len { - s += xs[i] * ys[i]; - } - s - }) -} - -#[bench] -fn zipdot_f32_checked_counted_loop(b: &mut test::Bencher) -{ - let xs = vec![2f32; 1024]; - let ys = vec![2f32; 768]; - let xs = black_box(xs); - let ys = black_box(ys); - - b.iter(|| { - // Must slice to equal lengths, and then bounds checks are eliminated! - let len = cmp::min(xs.len(), ys.len()); - let xs = &xs[..len]; - let ys = &ys[..len]; - - let mut s = 0.; - - for i in 0..len { - s += xs[i] * ys[i]; - } - s - }) -} - -#[bench] -fn zipdot_f32_checked_counted_unrolled_loop(b: &mut test::Bencher) -{ - let xs = vec![2f32; 1024]; - let ys = vec![2f32; 768]; - let xs = black_box(xs); - let ys = black_box(ys); - - b.iter(|| { - // Must slice to equal lengths, and then bounds checks are eliminated! - let len = cmp::min(xs.len(), ys.len()); - let mut xs = &xs[..len]; - let mut ys = &ys[..len]; - - let mut s = 0.; - let (mut p0, mut p1, mut p2, mut p3, mut p4, mut p5, mut p6, mut p7) = - (0., 0., 0., 0., 0., 0., 0., 0.); - - // how to unroll and have bounds checks eliminated (by cristicbz) - // split sum into eight parts to enable vectorization (by bluss) - while xs.len() >= 8 { - p0 += xs[0] * ys[0]; - p1 += xs[1] * ys[1]; - p2 += xs[2] * ys[2]; - p3 += xs[3] * ys[3]; - p4 += xs[4] * ys[4]; - p5 += xs[5] * ys[5]; - p6 += xs[6] * ys[6]; - p7 += xs[7] * ys[7]; - - xs = &xs[8..]; - ys = &ys[8..]; - } - s += p0 + p4; - s += p1 + p5; - s += p2 + p6; - s += p3 + p7; - - for i in 0..xs.len() { - s += xs[i] * ys[i]; - } - s - }) -} - -#[bench] -fn zip_unchecked_counted_loop(b: &mut test::Bencher) -{ - let xs = vec![0; 1024]; - let ys = vec![0; 768]; - let xs = black_box(xs); - let ys = black_box(ys); - - b.iter(|| { - let len = cmp::min(xs.len(), ys.len()); - for i in 0..len { - unsafe { - let x = *xs.get_unchecked(i); - let y = *ys.get_unchecked(i); - test::black_box(x); - test::black_box(y); - } - } - }) -} - -#[bench] -fn zipdot_i32_unchecked_counted_loop(b: &mut test::Bencher) -{ - let xs = vec![2; 1024]; - let ys = vec![2; 768]; - let xs = black_box(xs); - let ys = black_box(ys); - - b.iter(|| { - let len = cmp::min(xs.len(), ys.len()); - let mut s = 0i32; - for i in 0..len { - unsafe { - let x = *xs.get_unchecked(i); - let y = *ys.get_unchecked(i); - s += x * y; - } - } - s - }) -} - -#[bench] -fn zipdot_f32_unchecked_counted_loop(b: &mut test::Bencher) -{ - let xs = vec![2.; 1024]; - let ys = vec![2.; 768]; - let xs = black_box(xs); - let ys = black_box(ys); - - b.iter(|| { - let len = cmp::min(xs.len(), ys.len()); - let mut s = 0f32; - for i in 0..len { - unsafe { - let x = *xs.get_unchecked(i); - let y = *ys.get_unchecked(i); - s += x * y; - } - } - s - }) -} - -#[bench] -fn zip_unchecked_counted_loop3(b: &mut test::Bencher) -{ - let xs = vec![0; 1024]; - let ys = vec![0; 768]; - let zs = vec![0; 766]; - let xs = black_box(xs); - let ys = black_box(ys); - let zs = black_box(zs); - - b.iter(|| { - let len = cmp::min(xs.len(), cmp::min(ys.len(), zs.len())); - for i in 0..len { - unsafe { - let x = *xs.get_unchecked(i); - let y = *ys.get_unchecked(i); - let z = *zs.get_unchecked(i); - test::black_box(x); - test::black_box(y); - test::black_box(z); - } - } - }) -} - -#[bench] -fn group_by_lazy_1(b: &mut test::Bencher) { - let mut data = vec![0; 1024]; - for (index, elt) in data.iter_mut().enumerate() { - *elt = index / 10; - } - - let data = test::black_box(data); - - b.iter(|| { - for (_key, group) in &data.iter().group_by(|elt| **elt) { - for elt in group { - test::black_box(elt); - } - } - }) -} - -#[bench] -fn group_by_lazy_2(b: &mut test::Bencher) { - let mut data = vec![0; 1024]; - for (index, elt) in data.iter_mut().enumerate() { - *elt = index / 2; - } - - let data = test::black_box(data); - - b.iter(|| { - for (_key, group) in &data.iter().group_by(|elt| **elt) { - for elt in group { - test::black_box(elt); - } - } - }) -} - -#[bench] -fn slice_chunks(b: &mut test::Bencher) { - let data = vec![0; 1024]; - - let data = test::black_box(data); - let sz = test::black_box(10); - - b.iter(|| { - for group in data.chunks(sz) { - for elt in group { - test::black_box(elt); - } - } - }) -} - -#[bench] -fn chunks_lazy_1(b: &mut test::Bencher) { - let data = vec![0; 1024]; - - let data = test::black_box(data); - let sz = test::black_box(10); - - b.iter(|| { - for group in &data.iter().chunks(sz) { - for elt in group { - test::black_box(elt); - } - } - }) -} - -#[bench] -fn equal(b: &mut test::Bencher) { - let data = vec![7; 1024]; - let l = data.len(); - let alpha = test::black_box(&data[1..]); - let beta = test::black_box(&data[..l - 1]); - b.iter(|| { - itertools::equal(alpha, beta) - }) -} - -#[bench] -fn merge_default(b: &mut test::Bencher) { - let mut data1 = vec![0; 1024]; - let mut data2 = vec![0; 800]; - let mut x = 0; - for (_, elt) in data1.iter_mut().enumerate() { - *elt = x; - x += 1; - } - - let mut y = 0; - for (i, elt) in data2.iter_mut().enumerate() { - *elt += y; - if i % 3 == 0 { - y += 3; - } else { - y += 0; - } - } - let data1 = test::black_box(data1); - let data2 = test::black_box(data2); - b.iter(|| { - data1.iter().merge(&data2).count() - }) -} - -#[bench] -fn merge_by_cmp(b: &mut test::Bencher) { - let mut data1 = vec![0; 1024]; - let mut data2 = vec![0; 800]; - let mut x = 0; - for (_, elt) in data1.iter_mut().enumerate() { - *elt = x; - x += 1; - } - - let mut y = 0; - for (i, elt) in data2.iter_mut().enumerate() { - *elt += y; - if i % 3 == 0 { - y += 3; - } else { - y += 0; - } - } - let data1 = test::black_box(data1); - let data2 = test::black_box(data2); - b.iter(|| { - data1.iter().merge_by(&data2, PartialOrd::le).count() - }) -} - -#[bench] -fn merge_by_lt(b: &mut test::Bencher) { - let mut data1 = vec![0; 1024]; - let mut data2 = vec![0; 800]; - let mut x = 0; - for (_, elt) in data1.iter_mut().enumerate() { - *elt = x; - x += 1; - } - - let mut y = 0; - for (i, elt) in data2.iter_mut().enumerate() { - *elt += y; - if i % 3 == 0 { - y += 3; - } else { - y += 0; - } - } - let data1 = test::black_box(data1); - let data2 = test::black_box(data2); - b.iter(|| { - data1.iter().merge_by(&data2, |a, b| a <= b).count() - }) -} - -#[bench] -fn kmerge_default(b: &mut test::Bencher) { - let mut data1 = vec![0; 1024]; - let mut data2 = vec![0; 800]; - let mut x = 0; - for (_, elt) in data1.iter_mut().enumerate() { - *elt = x; - x += 1; - } - - let mut y = 0; - for (i, elt) in data2.iter_mut().enumerate() { - *elt += y; - if i % 3 == 0 { - y += 3; - } else { - y += 0; - } - } - let data1 = test::black_box(data1); - let data2 = test::black_box(data2); - let its = &[data1.iter(), data2.iter()]; - b.iter(|| { - its.iter().cloned().kmerge().count() - }) -} - -#[bench] -fn kmerge_tenway(b: &mut test::Bencher) { - let mut data = vec![0; 10240]; - - let mut state = 1729u16; - fn rng(state: &mut u16) -> u16 { - let new = state.wrapping_mul(31421) + 6927; - *state = new; - new - } - - for elt in &mut data { - *elt = rng(&mut state); - } - - let mut chunks = Vec::new(); - let mut rest = &mut data[..]; - while rest.len() > 0 { - let chunk_len = 1 + rng(&mut state) % 512; - let chunk_len = cmp::min(rest.len(), chunk_len as usize); - let (fst, tail) = {rest}.split_at_mut(chunk_len); - fst.sort(); - chunks.push(fst.iter().cloned()); - rest = tail; - } - - // println!("Chunk lengths: {}", chunks.iter().format_with(", ", |elt, f| f(&elt.len()))); - - b.iter(|| { - chunks.iter().cloned().kmerge().count() - }) -} - - -fn fast_integer_sum<I>(iter: I) -> I::Item - where I: IntoIterator, - I::Item: Default + Add<Output=I::Item> -{ - iter.into_iter().fold(<_>::default(), |x, y| x + y) -} - - -#[bench] -fn step_vec_2(b: &mut test::Bencher) { - let v = vec![0; 1024]; - b.iter(|| { - fast_integer_sum(cloned(v.iter().step(2))) - }); -} - -#[bench] -fn step_vec_10(b: &mut test::Bencher) { - let v = vec![0; 1024]; - b.iter(|| { - fast_integer_sum(cloned(v.iter().step(10))) - }); -} - -#[bench] -fn step_range_2(b: &mut test::Bencher) { - let v = black_box(0..1024); - b.iter(|| { - fast_integer_sum(v.clone().step(2)) - }); -} - -#[bench] -fn step_range_10(b: &mut test::Bencher) { - let v = black_box(0..1024); - b.iter(|| { - fast_integer_sum(v.clone().step(10)) - }); -} - -#[bench] -fn cartesian_product_iterator(b: &mut test::Bencher) -{ - let xs = vec![0; 16]; - - b.iter(|| { - let mut sum = 0; - for (&x, &y, &z) in iproduct!(&xs, &xs, &xs) { - sum += x; - sum += y; - sum += z; - } - sum - }) -} - -#[bench] -fn cartesian_product_fold(b: &mut test::Bencher) -{ - let xs = vec![0; 16]; - - b.iter(|| { - let mut sum = 0; - iproduct!(&xs, &xs, &xs).fold((), |(), (&x, &y, &z)| { - sum += x; - sum += y; - sum += z; - }); - sum - }) -} - -#[bench] -fn multi_cartesian_product_iterator(b: &mut test::Bencher) -{ - let xs = [vec![0; 16], vec![0; 16], vec![0; 16]]; - - b.iter(|| { - let mut sum = 0; - for x in xs.iter().multi_cartesian_product() { - sum += x[0]; - sum += x[1]; - sum += x[2]; - } - sum - }) -} - -#[bench] -fn multi_cartesian_product_fold(b: &mut test::Bencher) -{ - let xs = [vec![0; 16], vec![0; 16], vec![0; 16]]; - - b.iter(|| { - let mut sum = 0; - xs.iter().multi_cartesian_product().fold((), |(), x| { - sum += x[0]; - sum += x[1]; - sum += x[2]; - }); - sum - }) -} - -#[bench] -fn cartesian_product_nested_for(b: &mut test::Bencher) -{ - let xs = vec![0; 16]; - - b.iter(|| { - let mut sum = 0; - for &x in &xs { - for &y in &xs { - for &z in &xs { - sum += x; - sum += y; - sum += z; - } - } - } - sum - }) -} - -#[bench] -fn all_equal(b: &mut test::Bencher) { - let mut xs = vec![0; 5_000_000]; - xs.extend(vec![1; 5_000_000]); - - b.iter(|| xs.iter().all_equal()) -} - -#[bench] -fn all_equal_for(b: &mut test::Bencher) { - let mut xs = vec![0; 5_000_000]; - xs.extend(vec![1; 5_000_000]); - - b.iter(|| { - for &x in &xs { - if x != xs[0] { - return false; - } - } - true - }) -} - -#[bench] -fn all_equal_default(b: &mut test::Bencher) { - let mut xs = vec![0; 5_000_000]; - xs.extend(vec![1; 5_000_000]); - - b.iter(|| xs.iter().dedup().nth(1).is_none()) -} - -const PERM_COUNT: usize = 6; - -#[bench] -fn permutations_iter(b: &mut test::Bencher) { - struct NewIterator(Range<usize>); - - impl Iterator for NewIterator { - type Item = usize; - - fn next(&mut self) -> Option<Self::Item> { - self.0.next() - } - } - - b.iter(|| { - for _ in NewIterator(0..PERM_COUNT).permutations(PERM_COUNT) { - - } - }) -} - -#[bench] -fn permutations_range(b: &mut test::Bencher) { - b.iter(|| { - for _ in (0..PERM_COUNT).permutations(PERM_COUNT) { - - } - }) -} - -#[bench] -fn permutations_slice(b: &mut test::Bencher) { - let v = (0..PERM_COUNT).collect_vec(); - - b.iter(|| { - for _ in v.as_slice().iter().permutations(PERM_COUNT) { - - } - }) -} diff --git a/vendor/itertools-0.8.2/benches/combinations_with_replacement.rs b/vendor/itertools-0.8.2/benches/combinations_with_replacement.rs deleted file mode 100644 index 0652e49e79..0000000000 --- a/vendor/itertools-0.8.2/benches/combinations_with_replacement.rs +++ /dev/null @@ -1,34 +0,0 @@ -#![feature(test)] - -extern crate itertools; -extern crate test; - -use itertools::Itertools; -use test::{black_box, Bencher}; - -#[bench] -fn comb_replacement_n10_k5(b: &mut Bencher) { - b.iter(|| { - for i in (0..10).combinations_with_replacement(5) { - black_box(i); - } - }); -} - -#[bench] -fn comb_replacement_n5_k10(b: &mut Bencher) { - b.iter(|| { - for i in (0..5).combinations_with_replacement(10) { - black_box(i); - } - }); -} - -#[bench] -fn comb_replacement_n10_k10(b: &mut Bencher) { - b.iter(|| { - for i in (0..10).combinations_with_replacement(10) { - black_box(i); - } - }); -} diff --git a/vendor/itertools-0.8.2/benches/extra/mod.rs b/vendor/itertools-0.8.2/benches/extra/mod.rs deleted file mode 100644 index 5ddb5772f4..0000000000 --- a/vendor/itertools-0.8.2/benches/extra/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ - - -pub use self::zipslices::ZipSlices; -mod zipslices; diff --git a/vendor/itertools-0.8.2/benches/extra/zipslices.rs b/vendor/itertools-0.8.2/benches/extra/zipslices.rs deleted file mode 100644 index 493a539fd6..0000000000 --- a/vendor/itertools-0.8.2/benches/extra/zipslices.rs +++ /dev/null @@ -1,189 +0,0 @@ -use std::cmp; - -// Note: There are different ways to implement ZipSlices. -// This version performed the best in benchmarks. -// -// I also implemented a version with three pointes (tptr, tend, uptr), -// that mimiced slice::Iter and only checked bounds by using tptr == tend, -// but that was inferior to this solution. - -/// An iterator which iterates two slices simultaneously. -/// -/// `ZipSlices` acts like a double-ended `.zip()` iterator. -/// -/// It was intended to be more efficient than `.zip()`, and it was, then -/// rustc changed how it optimizes so it can not promise improved performance -/// at this time. -/// -/// Note that elements past the end of the shortest of the two slices are ignored. -/// -/// Iterator element type for `ZipSlices<T, U>` is `(T::Item, U::Item)`. For example, -/// for a `ZipSlices<&'a [A], &'b mut [B]>`, the element type is `(&'a A, &'b mut B)`. -#[derive(Clone)] -pub struct ZipSlices<T, U> { - t: T, - u: U, - len: usize, - index: usize, -} - -impl<'a, 'b, A, B> ZipSlices<&'a [A], &'b [B]> { - /// Create a new `ZipSlices` from slices `a` and `b`. - /// - /// Act like a double-ended `.zip()` iterator, but more efficiently. - /// - /// Note that elements past the end of the shortest of the two slices are ignored. - #[inline(always)] - pub fn new(a: &'a [A], b: &'b [B]) -> Self { - let minl = cmp::min(a.len(), b.len()); - ZipSlices { - t: a, - u: b, - len: minl, - index: 0, - } - } -} - -impl<T, U> ZipSlices<T, U> - where T: Slice, - U: Slice -{ - /// Create a new `ZipSlices` from slices `a` and `b`. - /// - /// Act like a double-ended `.zip()` iterator, but more efficiently. - /// - /// Note that elements past the end of the shortest of the two slices are ignored. - #[inline(always)] - pub fn from_slices(a: T, b: U) -> Self { - let minl = cmp::min(a.len(), b.len()); - ZipSlices { - t: a, - u: b, - len: minl, - index: 0, - } - } -} - -impl<T, U> Iterator for ZipSlices<T, U> - where T: Slice, - U: Slice -{ - type Item = (T::Item, U::Item); - - #[inline(always)] - fn next(&mut self) -> Option<Self::Item> { - unsafe { - if self.index >= self.len { - None - } else { - let i = self.index; - self.index += 1; - Some(( - self.t.get_unchecked(i), - self.u.get_unchecked(i))) - } - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - let len = self.len - self.index; - (len, Some(len)) - } -} - -impl<T, U> DoubleEndedIterator for ZipSlices<T, U> - where T: Slice, - U: Slice -{ - #[inline(always)] - fn next_back(&mut self) -> Option<Self::Item> { - unsafe { - if self.index >= self.len { - None - } else { - self.len -= 1; - let i = self.len; - Some(( - self.t.get_unchecked(i), - self.u.get_unchecked(i))) - } - } - } -} - -impl<T, U> ExactSizeIterator for ZipSlices<T, U> - where T: Slice, - U: Slice -{} - -unsafe impl<T, U> Slice for ZipSlices<T, U> - where T: Slice, - U: Slice -{ - type Item = (T::Item, U::Item); - - fn len(&self) -> usize { - self.len - self.index - } - - unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item { - (self.t.get_unchecked(i), - self.u.get_unchecked(i)) - } -} - -/// A helper trait to let `ZipSlices` accept both `&[T]` and `&mut [T]`. -/// -/// Unsafe trait because: -/// -/// - Implementors must guarantee that `get_unchecked` is valid for all indices `0..len()`. -pub unsafe trait Slice { - /// The type of a reference to the slice's elements - type Item; - #[doc(hidden)] - fn len(&self) -> usize; - #[doc(hidden)] - unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item; -} - -unsafe impl<'a, T> Slice for &'a [T] { - type Item = &'a T; - #[inline(always)] - fn len(&self) -> usize { (**self).len() } - #[inline(always)] - unsafe fn get_unchecked(&mut self, i: usize) -> &'a T { - debug_assert!(i < self.len()); - (**self).get_unchecked(i) - } -} - -unsafe impl<'a, T> Slice for &'a mut [T] { - type Item = &'a mut T; - #[inline(always)] - fn len(&self) -> usize { (**self).len() } - #[inline(always)] - unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut T { - debug_assert!(i < self.len()); - // override the lifetime constraints of &mut &'a mut [T] - (*(*self as *mut [T])).get_unchecked_mut(i) - } -} - -#[test] -fn zipslices() { - - let xs = [1, 2, 3, 4, 5, 6]; - let ys = [1, 2, 3, 7]; - ::itertools::assert_equal(ZipSlices::new(&xs, &ys), xs.iter().zip(&ys)); - - let xs = [1, 2, 3, 4, 5, 6]; - let mut ys = [0; 6]; - for (x, y) in ZipSlices::from_slices(&xs[..], &mut ys[..]) { - *y = *x; - } - ::itertools::assert_equal(&xs, &ys); -} - diff --git a/vendor/itertools-0.8.2/benches/fold_specialization.rs b/vendor/itertools-0.8.2/benches/fold_specialization.rs deleted file mode 100644 index db3c995876..0000000000 --- a/vendor/itertools-0.8.2/benches/fold_specialization.rs +++ /dev/null @@ -1,66 +0,0 @@ -#![feature(test)] - -extern crate test; -extern crate itertools; - -use itertools::Itertools; - -struct Unspecialized<I>(I); - -impl<I> Iterator for Unspecialized<I> -where I: Iterator -{ - type Item = I::Item; - - #[inline(always)] - fn next(&mut self) -> Option<I::Item> { - self.0.next() - } - - #[inline(always)] - fn size_hint(&self) -> (usize, Option<usize>) { - self.0.size_hint() - } -} - -mod specialization { - use super::*; - - mod intersperse { - use super::*; - - #[bench] - fn external(b: &mut test::Bencher) - { - let arr = [1; 1024]; - - b.iter(|| { - let mut sum = 0; - for &x in arr.into_iter().intersperse(&0) { - sum += x; - } - sum - }) - } - - #[bench] - fn internal_specialized(b: &mut test::Bencher) - { - let arr = [1; 1024]; - - b.iter(|| { - arr.into_iter().intersperse(&0).fold(0, |acc, x| acc + x) - }) - } - - #[bench] - fn internal_unspecialized(b: &mut test::Bencher) - { - let arr = [1; 1024]; - - b.iter(|| { - Unspecialized(arr.into_iter().intersperse(&0)).fold(0, |acc, x| acc + x) - }) - } - } -} diff --git a/vendor/itertools-0.8.2/benches/tree_fold1.rs b/vendor/itertools-0.8.2/benches/tree_fold1.rs deleted file mode 100644 index b71589f3fe..0000000000 --- a/vendor/itertools-0.8.2/benches/tree_fold1.rs +++ /dev/null @@ -1,126 +0,0 @@ -#![feature(test)] - -extern crate test; -extern crate itertools; - -use itertools::Itertools; -use itertools::cloned; -use test::Bencher; - -trait IterEx : Iterator { - // Another efficient implementation against which to compare, - // but needs `std` so is less desirable. - fn tree_fold1_vec<F>(self, mut f: F) -> Option<Self::Item> - where F: FnMut(Self::Item, Self::Item) -> Self::Item, - Self: Sized, - { - let hint = self.size_hint().0; - let cap = std::mem::size_of::<usize>() * 8 - hint.leading_zeros() as usize; - let mut stack = Vec::with_capacity(cap); - self.enumerate().foreach(|(mut i, mut x)| { - while (i & 1) != 0 { - x = f(stack.pop().unwrap(), x); - i >>= 1; - } - stack.push(x); - }); - stack.into_iter().fold1(f) - } -} -impl<T:Iterator> IterEx for T {} - -macro_rules! def_benchs { - ($N:expr, - $FUN:ident, - $BENCH_NAME:ident, - ) => ( - mod $BENCH_NAME { - use super::*; - - #[bench] - fn sum(b: &mut Bencher) { - let v: Vec<u32> = (0.. $N).collect(); - b.iter(|| { - cloned(&v).$FUN(|x, y| x + y) - }); - } - - #[bench] - fn complex_iter(b: &mut Bencher) { - let u = (3..).take($N / 2); - let v = (5..).take($N / 2); - let it = u.chain(v); - - b.iter(|| { - it.clone().map(|x| x as f32).$FUN(f32::atan2) - }); - } - - #[bench] - fn string_format(b: &mut Bencher) { - // This goes quadratic with linear `fold1`, so use a smaller - // size to not waste too much time in travis. The allocations - // in here are so expensive anyway that it'll still take - // way longer per iteration than the other two benchmarks. - let v: Vec<u32> = (0.. ($N/4)).collect(); - b.iter(|| { - cloned(&v).map(|x| x.to_string()).$FUN(|x, y| format!("{} + {}", x, y)) - }); - } - } - ) -} - -def_benchs!{ - 10_000, - fold1, - fold1_10k, -} - -def_benchs!{ - 10_000, - tree_fold1, - tree_fold1_stack_10k, -} - -def_benchs!{ - 10_000, - tree_fold1_vec, - tree_fold1_vec_10k, -} - -def_benchs!{ - 100, - fold1, - fold1_100, -} - -def_benchs!{ - 100, - tree_fold1, - tree_fold1_stack_100, -} - -def_benchs!{ - 100, - tree_fold1_vec, - tree_fold1_vec_100, -} - -def_benchs!{ - 8, - fold1, - fold1_08, -} - -def_benchs!{ - 8, - tree_fold1, - tree_fold1_stack_08, -} - -def_benchs!{ - 8, - tree_fold1_vec, - tree_fold1_vec_08, -} diff --git a/vendor/itertools-0.8.2/benches/tuple_combinations.rs b/vendor/itertools-0.8.2/benches/tuple_combinations.rs deleted file mode 100644 index 4a14b1d0bd..0000000000 --- a/vendor/itertools-0.8.2/benches/tuple_combinations.rs +++ /dev/null @@ -1,97 +0,0 @@ -#![feature(test)] - -extern crate test; -extern crate itertools; - -use test::{black_box, Bencher}; -use itertools::Itertools; - -// approximate 100_000 iterations for each combination -const N1: usize = 100_000; -const N2: usize = 448; -const N3: usize = 86; -const N4: usize = 41; - -#[bench] -fn comb_for1(b: &mut Bencher) { - b.iter(|| { - for i in 0..N1 { - black_box(i); - } - }); -} - -#[bench] -fn comb_for2(b: &mut Bencher) { - b.iter(|| { - for i in 0..N2 { - for j in (i + 1)..N2 { - black_box(i + j); - } - } - }); -} - -#[bench] -fn comb_for3(b: &mut Bencher) { - b.iter(|| { - for i in 0..N3 { - for j in (i + 1)..N3 { - for k in (j + 1)..N3 { - black_box(i + j + k); - } - } - } - }); -} - -#[bench] -fn comb_for4(b: &mut Bencher) { - b.iter(|| { - for i in 0..N4 { - for j in (i + 1)..N4 { - for k in (j + 1)..N4 { - for l in (k + 1)..N4 { - black_box(i + j + k + l); - } - } - } - } - }); -} - -#[bench] -fn comb_c1(b: &mut Bencher) { - b.iter(|| { - for (i,) in (0..N1).tuple_combinations() { - black_box(i); - } - }); -} - -#[bench] -fn comb_c2(b: &mut Bencher) { - b.iter(|| { - for (i, j) in (0..N2).tuple_combinations() { - black_box(i + j); - } - }); -} - -#[bench] -fn comb_c3(b: &mut Bencher) { - b.iter(|| { - for (i, j, k) in (0..N3).tuple_combinations() { - black_box(i + j + k); - } - }); -} - -#[bench] -fn comb_c4(b: &mut Bencher) { - b.iter(|| { - for (i, j, k, l) in (0..N4).tuple_combinations() { - black_box(i + j + k + l); - } - }); -} diff --git a/vendor/itertools-0.8.2/benches/tuples.rs b/vendor/itertools-0.8.2/benches/tuples.rs deleted file mode 100644 index b0f2990fdf..0000000000 --- a/vendor/itertools-0.8.2/benches/tuples.rs +++ /dev/null @@ -1,190 +0,0 @@ -#![feature(test)] - -extern crate test; -extern crate itertools; - -use test::Bencher; -use itertools::Itertools; - -fn s1(a: u32) -> u32 { - a -} - -fn s2(a: u32, b: u32) -> u32 { - a + b -} - -fn s3(a: u32, b: u32, c: u32) -> u32 { - a + b + c -} - -fn s4(a: u32, b: u32, c: u32, d: u32) -> u32 { - a + b + c + d -} - -fn sum_s1(s: &[u32]) -> u32 { - s1(s[0]) -} - -fn sum_s2(s: &[u32]) -> u32 { - s2(s[0], s[1]) -} - -fn sum_s3(s: &[u32]) -> u32 { - s3(s[0], s[1], s[2]) -} - -fn sum_s4(s: &[u32]) -> u32 { - s4(s[0], s[1], s[2], s[3]) -} - -fn sum_t1(s: &(&u32, )) -> u32 { - s1(*s.0) -} - -fn sum_t2(s: &(&u32, &u32)) -> u32 { - s2(*s.0, *s.1) -} - -fn sum_t3(s: &(&u32, &u32, &u32)) -> u32 { - s3(*s.0, *s.1, *s.2) -} - -fn sum_t4(s: &(&u32, &u32, &u32, &u32)) -> u32 { - s4(*s.0, *s.1, *s.2, *s.3) -} - -macro_rules! def_benchs { - ($N:expr; - $TUPLE_FUN:ident, - $TUPLES:ident, - $TUPLE_WINDOWS:ident; - $SLICE_FUN:ident, - $CHUNKS:ident, - $WINDOWS:ident; - $FOR_CHUNKS:ident, - $FOR_WINDOWS:ident - ) => ( - #[bench] - fn $FOR_CHUNKS(b: &mut Bencher) { - let v: Vec<u32> = (0.. $N * 1_000).collect(); - let mut s = 0; - b.iter(|| { - let mut j = 0; - for _ in 0..1_000 { - s += $SLICE_FUN(&v[j..(j + $N)]); - j += $N; - } - s - }); - } - - #[bench] - fn $FOR_WINDOWS(b: &mut Bencher) { - let v: Vec<u32> = (0..1_000).collect(); - let mut s = 0; - b.iter(|| { - for i in 0..(1_000 - $N) { - s += $SLICE_FUN(&v[i..(i + $N)]); - } - s - }); - } - - #[bench] - fn $TUPLES(b: &mut Bencher) { - let v: Vec<u32> = (0.. $N * 1_000).collect(); - let mut s = 0; - b.iter(|| { - for x in v.iter().tuples() { - s += $TUPLE_FUN(&x); - } - s - }); - } - - #[bench] - fn $CHUNKS(b: &mut Bencher) { - let v: Vec<u32> = (0.. $N * 1_000).collect(); - let mut s = 0; - b.iter(|| { - for x in v.chunks($N) { - s += $SLICE_FUN(x); - } - s - }); - } - - #[bench] - fn $TUPLE_WINDOWS(b: &mut Bencher) { - let v: Vec<u32> = (0..1_000).collect(); - let mut s = 0; - b.iter(|| { - for x in v.iter().tuple_windows() { - s += $TUPLE_FUN(&x); - } - s - }); - } - - #[bench] - fn $WINDOWS(b: &mut Bencher) { - let v: Vec<u32> = (0..1_000).collect(); - let mut s = 0; - b.iter(|| { - for x in v.windows($N) { - s += $SLICE_FUN(x); - } - s - }); - } - ) -} - -def_benchs!{ - 1; - sum_t1, - tuple_chunks_1, - tuple_windows_1; - sum_s1, - slice_chunks_1, - slice_windows_1; - for_chunks_1, - for_windows_1 -} - -def_benchs!{ - 2; - sum_t2, - tuple_chunks_2, - tuple_windows_2; - sum_s2, - slice_chunks_2, - slice_windows_2; - for_chunks_2, - for_windows_2 -} - -def_benchs!{ - 3; - sum_t3, - tuple_chunks_3, - tuple_windows_3; - sum_s3, - slice_chunks_3, - slice_windows_3; - for_chunks_3, - for_windows_3 -} - -def_benchs!{ - 4; - sum_t4, - tuple_chunks_4, - tuple_windows_4; - sum_s4, - slice_chunks_4, - slice_windows_4; - for_chunks_4, - for_windows_4 -} diff --git a/vendor/itertools-0.8.2/examples/iris.data b/vendor/itertools-0.8.2/examples/iris.data deleted file mode 100644 index a3490e0e07..0000000000 --- a/vendor/itertools-0.8.2/examples/iris.data +++ /dev/null @@ -1,150 +0,0 @@ -5.1,3.5,1.4,0.2,Iris-setosa -4.9,3.0,1.4,0.2,Iris-setosa -4.7,3.2,1.3,0.2,Iris-setosa -4.6,3.1,1.5,0.2,Iris-setosa -5.0,3.6,1.4,0.2,Iris-setosa -5.4,3.9,1.7,0.4,Iris-setosa -4.6,3.4,1.4,0.3,Iris-setosa -5.0,3.4,1.5,0.2,Iris-setosa -4.4,2.9,1.4,0.2,Iris-setosa -4.9,3.1,1.5,0.1,Iris-setosa -5.4,3.7,1.5,0.2,Iris-setosa -4.8,3.4,1.6,0.2,Iris-setosa -4.8,3.0,1.4,0.1,Iris-setosa -4.3,3.0,1.1,0.1,Iris-setosa -5.8,4.0,1.2,0.2,Iris-setosa -5.7,4.4,1.5,0.4,Iris-setosa -5.4,3.9,1.3,0.4,Iris-setosa -5.1,3.5,1.4,0.3,Iris-setosa -5.7,3.8,1.7,0.3,Iris-setosa -5.1,3.8,1.5,0.3,Iris-setosa -5.4,3.4,1.7,0.2,Iris-setosa -5.1,3.7,1.5,0.4,Iris-setosa -4.6,3.6,1.0,0.2,Iris-setosa -5.1,3.3,1.7,0.5,Iris-setosa -4.8,3.4,1.9,0.2,Iris-setosa -5.0,3.0,1.6,0.2,Iris-setosa -5.0,3.4,1.6,0.4,Iris-setosa -5.2,3.5,1.5,0.2,Iris-setosa -5.2,3.4,1.4,0.2,Iris-setosa -4.7,3.2,1.6,0.2,Iris-setosa -4.8,3.1,1.6,0.2,Iris-setosa -5.4,3.4,1.5,0.4,Iris-setosa -5.2,4.1,1.5,0.1,Iris-setosa -5.5,4.2,1.4,0.2,Iris-setosa -4.9,3.1,1.5,0.1,Iris-setosa -5.0,3.2,1.2,0.2,Iris-setosa -5.5,3.5,1.3,0.2,Iris-setosa -4.9,3.1,1.5,0.1,Iris-setosa -4.4,3.0,1.3,0.2,Iris-setosa -5.1,3.4,1.5,0.2,Iris-setosa -5.0,3.5,1.3,0.3,Iris-setosa -4.5,2.3,1.3,0.3,Iris-setosa -4.4,3.2,1.3,0.2,Iris-setosa -5.0,3.5,1.6,0.6,Iris-setosa -5.1,3.8,1.9,0.4,Iris-setosa -4.8,3.0,1.4,0.3,Iris-setosa -5.1,3.8,1.6,0.2,Iris-setosa -4.6,3.2,1.4,0.2,Iris-setosa -5.3,3.7,1.5,0.2,Iris-setosa -5.0,3.3,1.4,0.2,Iris-setosa -7.0,3.2,4.7,1.4,Iris-versicolor -6.4,3.2,4.5,1.5,Iris-versicolor -6.9,3.1,4.9,1.5,Iris-versicolor -5.5,2.3,4.0,1.3,Iris-versicolor -6.5,2.8,4.6,1.5,Iris-versicolor -5.7,2.8,4.5,1.3,Iris-versicolor -6.3,3.3,4.7,1.6,Iris-versicolor -4.9,2.4,3.3,1.0,Iris-versicolor -6.6,2.9,4.6,1.3,Iris-versicolor -5.2,2.7,3.9,1.4,Iris-versicolor -5.0,2.0,3.5,1.0,Iris-versicolor -5.9,3.0,4.2,1.5,Iris-versicolor -6.0,2.2,4.0,1.0,Iris-versicolor -6.1,2.9,4.7,1.4,Iris-versicolor -5.6,2.9,3.6,1.3,Iris-versicolor -6.7,3.1,4.4,1.4,Iris-versicolor -5.6,3.0,4.5,1.5,Iris-versicolor -5.8,2.7,4.1,1.0,Iris-versicolor -6.2,2.2,4.5,1.5,Iris-versicolor -5.6,2.5,3.9,1.1,Iris-versicolor -5.9,3.2,4.8,1.8,Iris-versicolor -6.1,2.8,4.0,1.3,Iris-versicolor -6.3,2.5,4.9,1.5,Iris-versicolor -6.1,2.8,4.7,1.2,Iris-versicolor -6.4,2.9,4.3,1.3,Iris-versicolor -6.6,3.0,4.4,1.4,Iris-versicolor -6.8,2.8,4.8,1.4,Iris-versicolor -6.7,3.0,5.0,1.7,Iris-versicolor -6.0,2.9,4.5,1.5,Iris-versicolor -5.7,2.6,3.5,1.0,Iris-versicolor -5.5,2.4,3.8,1.1,Iris-versicolor -5.5,2.4,3.7,1.0,Iris-versicolor -5.8,2.7,3.9,1.2,Iris-versicolor -6.0,2.7,5.1,1.6,Iris-versicolor -5.4,3.0,4.5,1.5,Iris-versicolor -6.0,3.4,4.5,1.6,Iris-versicolor -6.7,3.1,4.7,1.5,Iris-versicolor -6.3,2.3,4.4,1.3,Iris-versicolor -5.6,3.0,4.1,1.3,Iris-versicolor -5.5,2.5,4.0,1.3,Iris-versicolor -5.5,2.6,4.4,1.2,Iris-versicolor -6.1,3.0,4.6,1.4,Iris-versicolor -5.8,2.6,4.0,1.2,Iris-versicolor -5.0,2.3,3.3,1.0,Iris-versicolor -5.6,2.7,4.2,1.3,Iris-versicolor -5.7,3.0,4.2,1.2,Iris-versicolor -5.7,2.9,4.2,1.3,Iris-versicolor -6.2,2.9,4.3,1.3,Iris-versicolor -5.1,2.5,3.0,1.1,Iris-versicolor -5.7,2.8,4.1,1.3,Iris-versicolor -6.3,3.3,6.0,2.5,Iris-virginica -5.8,2.7,5.1,1.9,Iris-virginica -7.1,3.0,5.9,2.1,Iris-virginica -6.3,2.9,5.6,1.8,Iris-virginica -6.5,3.0,5.8,2.2,Iris-virginica -7.6,3.0,6.6,2.1,Iris-virginica -4.9,2.5,4.5,1.7,Iris-virginica -7.3,2.9,6.3,1.8,Iris-virginica -6.7,2.5,5.8,1.8,Iris-virginica -7.2,3.6,6.1,2.5,Iris-virginica -6.5,3.2,5.1,2.0,Iris-virginica -6.4,2.7,5.3,1.9,Iris-virginica -6.8,3.0,5.5,2.1,Iris-virginica -5.7,2.5,5.0,2.0,Iris-virginica -5.8,2.8,5.1,2.4,Iris-virginica -6.4,3.2,5.3,2.3,Iris-virginica -6.5,3.0,5.5,1.8,Iris-virginica -7.7,3.8,6.7,2.2,Iris-virginica -7.7,2.6,6.9,2.3,Iris-virginica -6.0,2.2,5.0,1.5,Iris-virginica -6.9,3.2,5.7,2.3,Iris-virginica -5.6,2.8,4.9,2.0,Iris-virginica -7.7,2.8,6.7,2.0,Iris-virginica -6.3,2.7,4.9,1.8,Iris-virginica -6.7,3.3,5.7,2.1,Iris-virginica -7.2,3.2,6.0,1.8,Iris-virginica -6.2,2.8,4.8,1.8,Iris-virginica -6.1,3.0,4.9,1.8,Iris-virginica -6.4,2.8,5.6,2.1,Iris-virginica -7.2,3.0,5.8,1.6,Iris-virginica -7.4,2.8,6.1,1.9,Iris-virginica -7.9,3.8,6.4,2.0,Iris-virginica -6.4,2.8,5.6,2.2,Iris-virginica -6.3,2.8,5.1,1.5,Iris-virginica -6.1,2.6,5.6,1.4,Iris-virginica -7.7,3.0,6.1,2.3,Iris-virginica -6.3,3.4,5.6,2.4,Iris-virginica -6.4,3.1,5.5,1.8,Iris-virginica -6.0,3.0,4.8,1.8,Iris-virginica -6.9,3.1,5.4,2.1,Iris-virginica -6.7,3.1,5.6,2.4,Iris-virginica -6.9,3.1,5.1,2.3,Iris-virginica -5.8,2.7,5.1,1.9,Iris-virginica -6.8,3.2,5.9,2.3,Iris-virginica -6.7,3.3,5.7,2.5,Iris-virginica -6.7,3.0,5.2,2.3,Iris-virginica -6.3,2.5,5.0,1.9,Iris-virginica -6.5,3.0,5.2,2.0,Iris-virginica -6.2,3.4,5.4,2.3,Iris-virginica -5.9,3.0,5.1,1.8,Iris-virginica diff --git a/vendor/itertools-0.8.2/examples/iris.rs b/vendor/itertools-0.8.2/examples/iris.rs deleted file mode 100644 index c09afbea0d..0000000000 --- a/vendor/itertools-0.8.2/examples/iris.rs +++ /dev/null @@ -1,141 +0,0 @@ -/// -/// This example parses, sorts and groups the iris dataset -/// and does some simple manipulations. -/// -/// Iterators and itertools functionality are used throughout. -/// -/// - -extern crate itertools; - -use itertools::Itertools; -use std::collections::HashMap; -use std::iter::repeat; -use std::num::ParseFloatError; -use std::str::FromStr; - -static DATA: &'static str = include_str!("iris.data"); - -#[derive(Clone, Debug)] -struct Iris { - name: String, - data: [f32; 4], -} - -#[derive(Clone, Debug)] -enum ParseError { - Numeric(ParseFloatError), - Other(&'static str), -} - -impl From<ParseFloatError> for ParseError { - fn from(err: ParseFloatError) -> Self { - ParseError::Numeric(err) - } -} - -/// Parse an Iris from a comma-separated line -impl FromStr for Iris { - type Err = ParseError; - - fn from_str(s: &str) -> Result<Self, Self::Err> { - let mut iris = Iris { name: "".into(), data: [0.; 4] }; - let mut parts = s.split(",").map(str::trim); - - // using Iterator::by_ref() - for (index, part) in parts.by_ref().take(4).enumerate() { - iris.data[index] = try!(part.parse::<f32>()); - } - if let Some(name) = parts.next() { - iris.name = name.into(); - } else { - return Err(ParseError::Other("Missing name")) - } - Ok(iris) - } -} - -fn main() { - // using Itertools::fold_results to create the result of parsing - let irises = DATA.lines() - .map(str::parse) - .fold_results(Vec::new(), |mut v, iris: Iris| { - v.push(iris); - v - }); - let mut irises = match irises { - Err(e) => { - println!("Error parsing: {:?}", e); - std::process::exit(1); - } - Ok(data) => data, - }; - - // Sort them and group them - irises.sort_by(|a, b| Ord::cmp(&a.name, &b.name)); - - // using Iterator::cycle() - let mut plot_symbols = "+ox".chars().cycle(); - let mut symbolmap = HashMap::new(); - - // using Itertools::group_by - for (species, species_group) in &irises.iter().group_by(|iris| &iris.name) { - // assign a plot symbol - symbolmap.entry(species).or_insert_with(|| { - plot_symbols.next().unwrap() - }); - println!("{} (symbol={})", species, symbolmap[species]); - - for iris in species_group { - // using Itertools::format for lazy formatting - println!("{:>3.1}", iris.data.iter().format(", ")); - } - - } - - // Look at all combinations of the four columns - // - // See https://en.wikipedia.org/wiki/Iris_flower_data_set - // - let n = 30; // plot size - let mut plot = vec![' '; n * n]; - - // using Itertools::tuple_combinations - for (a, b) in (0..4).tuple_combinations() { - println!("Column {} vs {}:", a, b); - - // Clear plot - // - // using std::iter::repeat; - // using Itertools::set_from - plot.iter_mut().set_from(repeat(' ')); - - // using Itertools::minmax - let min_max = |data: &[Iris], col| { - data.iter() - .map(|iris| iris.data[col]) - .minmax() - .into_option() - .expect("Can't find min/max of empty iterator") - }; - let (min_x, max_x) = min_max(&irises, a); - let (min_y, max_y) = min_max(&irises, b); - - // Plot the data points - let round_to_grid = |x, min, max| ((x - min) / (max - min) * ((n - 1) as f32)) as usize; - let flip = |ix| n - 1 - ix; // reverse axis direction - - for iris in &irises { - let ix = round_to_grid(iris.data[a], min_x, max_x); - let iy = flip(round_to_grid(iris.data[b], min_y, max_y)); - plot[n * iy + ix] = symbolmap[&iris.name]; - } - - // render plot - // - // using Itertools::join - for line in plot.chunks(n) { - println!("{}", line.iter().join(" ")) - } - } -} diff --git a/vendor/itertools-0.8.2/src/adaptors/mod.rs b/vendor/itertools-0.8.2/src/adaptors/mod.rs deleted file mode 100644 index 4d0f5e1291..0000000000 --- a/vendor/itertools-0.8.2/src/adaptors/mod.rs +++ /dev/null @@ -1,1251 +0,0 @@ -//! Licensed under the Apache License, Version 2.0 -//! http://www.apache.org/licenses/LICENSE-2.0 or the MIT license -//! http://opensource.org/licenses/MIT, at your -//! option. This file may not be copied, modified, or distributed -//! except according to those terms. - -mod multi_product; -#[cfg(feature = "use_std")] -pub use self::multi_product::*; - -use std::fmt; -use std::mem::replace; -use std::iter::{Fuse, Peekable, FromIterator}; -use std::marker::PhantomData; -use size_hint; - -macro_rules! clone_fields { - ($name:ident, $base:expr, $($field:ident),+) => ( - $name { - $( - $field : $base . $field .clone() - ),* - } - ); -} - -/// An iterator adaptor that alternates elements from two iterators until both -/// run out. -/// -/// This iterator is *fused*. -/// -/// See [`.interleave()`](../trait.Itertools.html#method.interleave) for more information. -#[derive(Clone, Debug)] -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Interleave<I, J> { - a: Fuse<I>, - b: Fuse<J>, - flag: bool, -} - -/// Create an iterator that interleaves elements in `i` and `j`. -/// -/// `IntoIterator` enabled version of `i.interleave(j)`. -/// -/// ``` -/// use itertools::interleave; -/// -/// for elt in interleave(&[1, 2, 3], &[2, 3, 4]) { -/// /* loop body */ -/// } -/// ``` -pub fn interleave<I, J>(i: I, j: J) -> Interleave<<I as IntoIterator>::IntoIter, <J as IntoIterator>::IntoIter> - where I: IntoIterator, - J: IntoIterator<Item = I::Item> -{ - Interleave { - a: i.into_iter().fuse(), - b: j.into_iter().fuse(), - flag: false, - } -} - -impl<I, J> Iterator for Interleave<I, J> - where I: Iterator, - J: Iterator<Item = I::Item> -{ - type Item = I::Item; - #[inline] - fn next(&mut self) -> Option<I::Item> { - self.flag = !self.flag; - if self.flag { - match self.a.next() { - None => self.b.next(), - r => r, - } - } else { - match self.b.next() { - None => self.a.next(), - r => r, - } - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - size_hint::add(self.a.size_hint(), self.b.size_hint()) - } -} - -/// An iterator adaptor that alternates elements from the two iterators until -/// one of them runs out. -/// -/// This iterator is *fused*. -/// -/// See [`.interleave_shortest()`](../trait.Itertools.html#method.interleave_shortest) -/// for more information. -#[derive(Clone, Debug)] -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct InterleaveShortest<I, J> - where I: Iterator, - J: Iterator<Item = I::Item> -{ - it0: I, - it1: J, - phase: bool, // false ==> it0, true ==> it1 -} - -/// Create a new `InterleaveShortest` iterator. -pub fn interleave_shortest<I, J>(a: I, b: J) -> InterleaveShortest<I, J> - where I: Iterator, - J: Iterator<Item = I::Item> -{ - InterleaveShortest { - it0: a, - it1: b, - phase: false, - } -} - -impl<I, J> Iterator for InterleaveShortest<I, J> - where I: Iterator, - J: Iterator<Item = I::Item> -{ - type Item = I::Item; - - #[inline] - fn next(&mut self) -> Option<I::Item> { - match self.phase { - false => match self.it0.next() { - None => None, - e => { - self.phase = true; - e - } - }, - true => match self.it1.next() { - None => None, - e => { - self.phase = false; - e - } - }, - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - let (curr_hint, next_hint) = { - let it0_hint = self.it0.size_hint(); - let it1_hint = self.it1.size_hint(); - if self.phase { - (it1_hint, it0_hint) - } else { - (it0_hint, it1_hint) - } - }; - let (curr_lower, curr_upper) = curr_hint; - let (next_lower, next_upper) = next_hint; - let (combined_lower, combined_upper) = - size_hint::mul_scalar(size_hint::min(curr_hint, next_hint), 2); - let lower = - if curr_lower > next_lower { - combined_lower + 1 - } else { - combined_lower - }; - let upper = { - let extra_elem = match (curr_upper, next_upper) { - (_, None) => false, - (None, Some(_)) => true, - (Some(curr_max), Some(next_max)) => curr_max > next_max, - }; - if extra_elem { - combined_upper.and_then(|x| x.checked_add(1)) - } else { - combined_upper - } - }; - (lower, upper) - } -} - -#[derive(Clone, Debug)] -/// An iterator adaptor that allows putting back a single -/// item to the front of the iterator. -/// -/// Iterator element type is `I::Item`. -pub struct PutBack<I> - where I: Iterator -{ - top: Option<I::Item>, - iter: I, -} - -/// Create an iterator where you can put back a single item -pub fn put_back<I>(iterable: I) -> PutBack<I::IntoIter> - where I: IntoIterator -{ - PutBack { - top: None, - iter: iterable.into_iter(), - } -} - -impl<I> PutBack<I> - where I: Iterator -{ - /// put back value `value` (builder method) - pub fn with_value(mut self, value: I::Item) -> Self { - self.put_back(value); - self - } - - /// Split the `PutBack` into its parts. - #[inline] - pub fn into_parts(self) -> (Option<I::Item>, I) { - let PutBack{top, iter} = self; - (top, iter) - } - - /// Put back a single value to the front of the iterator. - /// - /// If a value is already in the put back slot, it is overwritten. - #[inline] - pub fn put_back(&mut self, x: I::Item) { - self.top = Some(x) - } -} - -impl<I> Iterator for PutBack<I> - where I: Iterator -{ - type Item = I::Item; - #[inline] - fn next(&mut self) -> Option<I::Item> { - match self.top { - None => self.iter.next(), - ref mut some => some.take(), - } - } - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - // Not ExactSizeIterator because size may be larger than usize - size_hint::add_scalar(self.iter.size_hint(), self.top.is_some() as usize) - } - - fn all<G>(&mut self, mut f: G) -> bool - where G: FnMut(Self::Item) -> bool - { - if let Some(elt) = self.top.take() { - if !f(elt) { - return false; - } - } - self.iter.all(f) - } - - fn fold<Acc, G>(mut self, init: Acc, mut f: G) -> Acc - where G: FnMut(Acc, Self::Item) -> Acc, - { - let mut accum = init; - if let Some(elt) = self.top.take() { - accum = f(accum, elt); - } - self.iter.fold(accum, f) - } -} - -#[derive(Debug, Clone)] -/// An iterator adaptor that iterates over the cartesian product of -/// the element sets of two iterators `I` and `J`. -/// -/// Iterator element type is `(I::Item, J::Item)`. -/// -/// See [`.cartesian_product()`](../trait.Itertools.html#method.cartesian_product) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Product<I, J> - where I: Iterator -{ - a: I, - a_cur: Option<I::Item>, - b: J, - b_orig: J, -} - -/// Create a new cartesian product iterator -/// -/// Iterator element type is `(I::Item, J::Item)`. -pub fn cartesian_product<I, J>(mut i: I, j: J) -> Product<I, J> - where I: Iterator, - J: Clone + Iterator, - I::Item: Clone -{ - Product { - a_cur: i.next(), - a: i, - b: j.clone(), - b_orig: j, - } -} - - -impl<I, J> Iterator for Product<I, J> - where I: Iterator, - J: Clone + Iterator, - I::Item: Clone -{ - type Item = (I::Item, J::Item); - fn next(&mut self) -> Option<(I::Item, J::Item)> { - let elt_b = match self.b.next() { - None => { - self.b = self.b_orig.clone(); - match self.b.next() { - None => return None, - Some(x) => { - self.a_cur = self.a.next(); - x - } - } - } - Some(x) => x - }; - match self.a_cur { - None => None, - Some(ref a) => { - Some((a.clone(), elt_b)) - } - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - let has_cur = self.a_cur.is_some() as usize; - // Not ExactSizeIterator because size may be larger than usize - let (b_min, b_max) = self.b.size_hint(); - - // Compute a * b_orig + b for both lower and upper bound - size_hint::add( - size_hint::mul(self.a.size_hint(), self.b_orig.size_hint()), - (b_min * has_cur, b_max.map(move |x| x * has_cur))) - } - - fn fold<Acc, G>(mut self, mut accum: Acc, mut f: G) -> Acc - where G: FnMut(Acc, Self::Item) -> Acc, - { - // use a split loop to handle the loose a_cur as well as avoiding to - // clone b_orig at the end. - if let Some(mut a) = self.a_cur.take() { - let mut b = self.b; - loop { - accum = b.fold(accum, |acc, elt| f(acc, (a.clone(), elt))); - - // we can only continue iterating a if we had a first element; - if let Some(next_a) = self.a.next() { - b = self.b_orig.clone(); - a = next_a; - } else { - break; - } - } - } - accum - } -} - -/// A “meta iterator adaptor”. Its closure receives a reference to the iterator -/// and may pick off as many elements as it likes, to produce the next iterator element. -/// -/// Iterator element type is *X*, if the return type of `F` is *Option\<X\>*. -/// -/// See [`.batching()`](../trait.Itertools.html#method.batching) for more information. -#[derive(Clone)] -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Batching<I, F> { - f: F, - iter: I, -} - -impl<I, F> fmt::Debug for Batching<I, F> where I: fmt::Debug { - debug_fmt_fields!(Batching, iter); -} - -/// Create a new Batching iterator. -pub fn batching<I, F>(iter: I, f: F) -> Batching<I, F> { - Batching { f: f, iter: iter } -} - -impl<B, F, I> Iterator for Batching<I, F> - where I: Iterator, - F: FnMut(&mut I) -> Option<B> -{ - type Item = B; - #[inline] - fn next(&mut self) -> Option<B> { - (self.f)(&mut self.iter) - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - // No information about closue behavior - (0, None) - } -} - -/// An iterator adaptor that steps a number elements in the base iterator -/// for each iteration. -/// -/// The iterator steps by yielding the next element from the base iterator, -/// then skipping forward *n-1* elements. -/// -/// See [`.step()`](../trait.Itertools.html#method.step) for more information. -#[deprecated(note="Use std .step_by() instead", since="0.8")] -#[allow(deprecated)] -#[derive(Clone, Debug)] -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Step<I> { - iter: Fuse<I>, - skip: usize, -} - -/// Create a `Step` iterator. -/// -/// **Panics** if the step is 0. -#[allow(deprecated)] -pub fn step<I>(iter: I, step: usize) -> Step<I> - where I: Iterator -{ - assert!(step != 0); - Step { - iter: iter.fuse(), - skip: step - 1, - } -} - -#[allow(deprecated)] -impl<I> Iterator for Step<I> - where I: Iterator -{ - type Item = I::Item; - #[inline] - fn next(&mut self) -> Option<I::Item> { - let elt = self.iter.next(); - if self.skip > 0 { - self.iter.nth(self.skip - 1); - } - elt - } - - fn size_hint(&self) -> (usize, Option<usize>) { - let (low, high) = self.iter.size_hint(); - let div = |x: usize| { - if x == 0 { - 0 - } else { - 1 + (x - 1) / (self.skip + 1) - } - }; - (div(low), high.map(div)) - } -} - -// known size -#[allow(deprecated)] -impl<I> ExactSizeIterator for Step<I> - where I: ExactSizeIterator -{} - -pub trait MergePredicate<T> { - fn merge_pred(&mut self, a: &T, b: &T) -> bool; -} - -#[derive(Clone)] -pub struct MergeLte; - -impl<T: PartialOrd> MergePredicate<T> for MergeLte { - fn merge_pred(&mut self, a: &T, b: &T) -> bool { - a <= b - } -} - -/// An iterator adaptor that merges the two base iterators in ascending order. -/// If both base iterators are sorted (ascending), the result is sorted. -/// -/// Iterator element type is `I::Item`. -/// -/// See [`.merge()`](../trait.Itertools.html#method.merge_by) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub type Merge<I, J> = MergeBy<I, J, MergeLte>; - -/// Create an iterator that merges elements in `i` and `j`. -/// -/// `IntoIterator` enabled version of `i.merge(j)`. -/// -/// ``` -/// use itertools::merge; -/// -/// for elt in merge(&[1, 2, 3], &[2, 3, 4]) { -/// /* loop body */ -/// } -/// ``` -pub fn merge<I, J>(i: I, j: J) -> Merge<<I as IntoIterator>::IntoIter, <J as IntoIterator>::IntoIter> - where I: IntoIterator, - J: IntoIterator<Item = I::Item>, - I::Item: PartialOrd -{ - merge_by_new(i, j, MergeLte) -} - -/// An iterator adaptor that merges the two base iterators in ascending order. -/// If both base iterators are sorted (ascending), the result is sorted. -/// -/// Iterator element type is `I::Item`. -/// -/// See [`.merge_by()`](../trait.Itertools.html#method.merge_by) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct MergeBy<I, J, F> - where I: Iterator, - J: Iterator<Item = I::Item> -{ - a: Peekable<I>, - b: Peekable<J>, - fused: Option<bool>, - cmp: F, -} - -impl<I, J, F> fmt::Debug for MergeBy<I, J, F> - where I: Iterator + fmt::Debug, J: Iterator<Item = I::Item> + fmt::Debug, - I::Item: fmt::Debug, -{ - debug_fmt_fields!(MergeBy, a, b); -} - -impl<T, F: FnMut(&T, &T)->bool> MergePredicate<T> for F { - fn merge_pred(&mut self, a: &T, b: &T) -> bool { - self(a, b) - } -} - -/// Create a `MergeBy` iterator. -pub fn merge_by_new<I, J, F>(a: I, b: J, cmp: F) -> MergeBy<I::IntoIter, J::IntoIter, F> - where I: IntoIterator, - J: IntoIterator<Item = I::Item>, - F: MergePredicate<I::Item>, -{ - MergeBy { - a: a.into_iter().peekable(), - b: b.into_iter().peekable(), - fused: None, - cmp: cmp, - } -} - -impl<I, J, F> Clone for MergeBy<I, J, F> - where I: Iterator, - J: Iterator<Item = I::Item>, - Peekable<I>: Clone, - Peekable<J>: Clone, - F: Clone -{ - fn clone(&self) -> Self { - clone_fields!(MergeBy, self, a, b, fused, cmp) - } -} - -impl<I, J, F> Iterator for MergeBy<I, J, F> - where I: Iterator, - J: Iterator<Item = I::Item>, - F: MergePredicate<I::Item> -{ - type Item = I::Item; - - fn next(&mut self) -> Option<I::Item> { - let less_than = match self.fused { - Some(lt) => lt, - None => match (self.a.peek(), self.b.peek()) { - (Some(a), Some(b)) => self.cmp.merge_pred(a, b), - (Some(_), None) => { - self.fused = Some(true); - true - } - (None, Some(_)) => { - self.fused = Some(false); - false - } - (None, None) => return None, - } - }; - if less_than { - self.a.next() - } else { - self.b.next() - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - // Not ExactSizeIterator because size may be larger than usize - size_hint::add(self.a.size_hint(), self.b.size_hint()) - } -} - -#[derive(Clone, Debug)] -pub struct CoalesceCore<I> - where I: Iterator -{ - iter: I, - last: Option<I::Item>, -} - -impl<I> CoalesceCore<I> - where I: Iterator -{ - fn next_with<F>(&mut self, mut f: F) -> Option<I::Item> - where F: FnMut(I::Item, I::Item) -> Result<I::Item, (I::Item, I::Item)> - { - // this fuses the iterator - let mut last = match self.last.take() { - None => return None, - Some(x) => x, - }; - for next in &mut self.iter { - match f(last, next) { - Ok(joined) => last = joined, - Err((last_, next_)) => { - self.last = Some(next_); - return Some(last_); - } - } - } - - Some(last) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - let (low, hi) = size_hint::add_scalar(self.iter.size_hint(), - self.last.is_some() as usize); - ((low > 0) as usize, hi) - } -} - -/// An iterator adaptor that may join together adjacent elements. -/// -/// See [`.coalesce()`](../trait.Itertools.html#method.coalesce) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Coalesce<I, F> - where I: Iterator -{ - iter: CoalesceCore<I>, - f: F, -} - -impl<I: Clone, F: Clone> Clone for Coalesce<I, F> - where I: Iterator, - I::Item: Clone -{ - fn clone(&self) -> Self { - clone_fields!(Coalesce, self, iter, f) - } -} - -impl<I, F> fmt::Debug for Coalesce<I, F> - where I: Iterator + fmt::Debug, - I::Item: fmt::Debug, -{ - debug_fmt_fields!(Coalesce, iter); -} - -/// Create a new `Coalesce`. -pub fn coalesce<I, F>(mut iter: I, f: F) -> Coalesce<I, F> - where I: Iterator -{ - Coalesce { - iter: CoalesceCore { - last: iter.next(), - iter: iter, - }, - f: f, - } -} - -impl<I, F> Iterator for Coalesce<I, F> - where I: Iterator, - F: FnMut(I::Item, I::Item) -> Result<I::Item, (I::Item, I::Item)> -{ - type Item = I::Item; - - fn next(&mut self) -> Option<I::Item> { - self.iter.next_with(&mut self.f) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - self.iter.size_hint() - } -} - -/// An iterator adaptor that removes repeated duplicates, determining equality using a comparison function. -/// -/// See [`.dedup_by()`](../trait.Itertools.html#method.dedup_by) or [`.dedup()`](../trait.Itertools.html#method.dedup) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct DedupBy<I, Pred> - where I: Iterator -{ - iter: CoalesceCore<I>, - dedup_pred: Pred, -} - -pub trait DedupPredicate<T> { // TODO replace by Fn(&T, &T)->bool once Rust supports it - fn dedup_pair(&mut self, a: &T, b: &T) -> bool; -} - -#[derive(Clone)] -pub struct DedupEq; - -impl<T: PartialEq> DedupPredicate<T> for DedupEq { - fn dedup_pair(&mut self, a: &T, b: &T) -> bool { - a==b - } -} - -impl<T, F: FnMut(&T, &T)->bool> DedupPredicate<T> for F { - fn dedup_pair(&mut self, a: &T, b: &T) -> bool { - self(a, b) - } -} - -/// An iterator adaptor that removes repeated duplicates. -/// -/// See [`.dedup()`](../trait.Itertools.html#method.dedup) for more information. -pub type Dedup<I>=DedupBy<I, DedupEq>; - -impl<I: Clone, Pred: Clone> Clone for DedupBy<I, Pred> - where I: Iterator, - I::Item: Clone, -{ - fn clone(&self) -> Self { - clone_fields!(DedupBy, self, iter, dedup_pred) - } -} - -/// Create a new `DedupBy`. -pub fn dedup_by<I, Pred>(mut iter: I, dedup_pred: Pred) -> DedupBy<I, Pred> - where I: Iterator, -{ - DedupBy { - iter: CoalesceCore { - last: iter.next(), - iter: iter, - }, - dedup_pred, - } -} - -/// Create a new `Dedup`. -pub fn dedup<I>(iter: I) -> Dedup<I> - where I: Iterator -{ - dedup_by(iter, DedupEq) -} - -impl<I, Pred> fmt::Debug for DedupBy<I, Pred> - where I: Iterator + fmt::Debug, - I::Item: fmt::Debug, -{ - debug_fmt_fields!(Dedup, iter); -} - -impl<I, Pred> Iterator for DedupBy<I, Pred> - where I: Iterator, - I::Item: PartialEq, - Pred: DedupPredicate<I::Item>, -{ - type Item = I::Item; - - fn next(&mut self) -> Option<I::Item> { - let ref mut dedup_pred = self.dedup_pred; - self.iter.next_with(|x, y| { - if dedup_pred.dedup_pair(&x, &y) { Ok(x) } else { Err((x, y)) } - }) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - self.iter.size_hint() - } - - fn fold<Acc, G>(self, mut accum: Acc, mut f: G) -> Acc - where G: FnMut(Acc, Self::Item) -> Acc, - { - if let Some(mut last) = self.iter.last { - let mut dedup_pred = self.dedup_pred; - accum = self.iter.iter.fold(accum, |acc, elt| { - if dedup_pred.dedup_pair(&elt, &last) { - acc - } else { - f(acc, replace(&mut last, elt)) - } - }); - f(accum, last) - } else { - accum - } - } -} - -/// An iterator adaptor that borrows from a `Clone`-able iterator -/// to only pick off elements while the predicate returns `true`. -/// -/// See [`.take_while_ref()`](../trait.Itertools.html#method.take_while_ref) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct TakeWhileRef<'a, I: 'a, F> { - iter: &'a mut I, - f: F, -} - -impl<'a, I, F> fmt::Debug for TakeWhileRef<'a, I, F> - where I: Iterator + fmt::Debug, -{ - debug_fmt_fields!(TakeWhileRef, iter); -} - -/// Create a new `TakeWhileRef` from a reference to clonable iterator. -pub fn take_while_ref<I, F>(iter: &mut I, f: F) -> TakeWhileRef<I, F> - where I: Iterator + Clone -{ - TakeWhileRef { iter: iter, f: f } -} - -impl<'a, I, F> Iterator for TakeWhileRef<'a, I, F> - where I: Iterator + Clone, - F: FnMut(&I::Item) -> bool -{ - type Item = I::Item; - - fn next(&mut self) -> Option<I::Item> { - let old = self.iter.clone(); - match self.iter.next() { - None => None, - Some(elt) => { - if (self.f)(&elt) { - Some(elt) - } else { - *self.iter = old; - None - } - } - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - let (_, hi) = self.iter.size_hint(); - (0, hi) - } -} - -/// An iterator adaptor that filters `Option<A>` iterator elements -/// and produces `A`. Stops on the first `None` encountered. -/// -/// See [`.while_some()`](../trait.Itertools.html#method.while_some) for more information. -#[derive(Clone, Debug)] -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct WhileSome<I> { - iter: I, -} - -/// Create a new `WhileSome<I>`. -pub fn while_some<I>(iter: I) -> WhileSome<I> { - WhileSome { iter: iter } -} - -impl<I, A> Iterator for WhileSome<I> - where I: Iterator<Item = Option<A>> -{ - type Item = A; - - fn next(&mut self) -> Option<A> { - match self.iter.next() { - None | Some(None) => None, - Some(elt) => elt, - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - let sh = self.iter.size_hint(); - (0, sh.1) - } -} - -/// An iterator to iterate through all combinations in a `Clone`-able iterator that produces tuples -/// of a specific size. -/// -/// See [`.tuple_combinations()`](../trait.Itertools.html#method.tuple_combinations) for more -/// information. -#[derive(Debug)] -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct TupleCombinations<I, T> - where I: Iterator, - T: HasCombination<I> -{ - iter: T::Combination, - _mi: PhantomData<I>, - _mt: PhantomData<T> -} - -pub trait HasCombination<I>: Sized { - type Combination: From<I> + Iterator<Item = Self>; -} - -/// Create a new `TupleCombinations` from a clonable iterator. -pub fn tuple_combinations<T, I>(iter: I) -> TupleCombinations<I, T> - where I: Iterator + Clone, - I::Item: Clone, - T: HasCombination<I>, -{ - TupleCombinations { - iter: T::Combination::from(iter), - _mi: PhantomData, - _mt: PhantomData, - } -} - -impl<I, T> Iterator for TupleCombinations<I, T> - where I: Iterator, - T: HasCombination<I>, -{ - type Item = T; - - fn next(&mut self) -> Option<Self::Item> { - self.iter.next() - } -} - -#[derive(Debug)] -pub struct Tuple1Combination<I> { - iter: I, -} - -impl<I> From<I> for Tuple1Combination<I> { - fn from(iter: I) -> Self { - Tuple1Combination { iter: iter } - } -} - -impl<I: Iterator> Iterator for Tuple1Combination<I> { - type Item = (I::Item,); - - fn next(&mut self) -> Option<Self::Item> { - self.iter.next().map(|x| (x,)) - } -} - -impl<I: Iterator> HasCombination<I> for (I::Item,) { - type Combination = Tuple1Combination<I>; -} - -macro_rules! impl_tuple_combination { - ($C:ident $P:ident ; $A:ident, $($I:ident),* ; $($X:ident)*) => ( - #[derive(Debug)] - pub struct $C<I: Iterator> { - item: Option<I::Item>, - iter: I, - c: $P<I>, - } - - impl<I: Iterator + Clone> From<I> for $C<I> { - fn from(mut iter: I) -> Self { - $C { - item: iter.next(), - iter: iter.clone(), - c: $P::from(iter), - } - } - } - - impl<I: Iterator + Clone> From<I> for $C<Fuse<I>> { - fn from(iter: I) -> Self { - let mut iter = iter.fuse(); - $C { - item: iter.next(), - iter: iter.clone(), - c: $P::from(iter), - } - } - } - - impl<I, $A> Iterator for $C<I> - where I: Iterator<Item = $A> + Clone, - I::Item: Clone - { - type Item = ($($I),*); - - fn next(&mut self) -> Option<Self::Item> { - if let Some(($($X),*,)) = self.c.next() { - let z = self.item.clone().unwrap(); - Some((z, $($X),*)) - } else { - self.item = self.iter.next(); - self.item.clone().and_then(|z| { - self.c = $P::from(self.iter.clone()); - self.c.next().map(|($($X),*,)| (z, $($X),*)) - }) - } - } - } - - impl<I, $A> HasCombination<I> for ($($I),*) - where I: Iterator<Item = $A> + Clone, - I::Item: Clone - { - type Combination = $C<Fuse<I>>; - } - ) -} - -impl_tuple_combination!(Tuple2Combination Tuple1Combination ; A, A, A ; a); -impl_tuple_combination!(Tuple3Combination Tuple2Combination ; A, A, A, A ; a b); -impl_tuple_combination!(Tuple4Combination Tuple3Combination ; A, A, A, A, A; a b c); - -/// An iterator adapter to apply `Into` conversion to each element. -/// -/// See [`.map_into()`](../trait.Itertools.html#method.map_into) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct MapInto<I, R> { - iter: I, - _res: PhantomData<fn() -> R>, -} - -/// Create a new [`MapInto`](struct.MapInto.html) iterator. -pub fn map_into<I, R>(iter: I) -> MapInto<I, R> { - MapInto { - iter: iter, - _res: PhantomData, - } -} - -impl<I, R> Iterator for MapInto<I, R> - where I: Iterator, - I::Item: Into<R>, -{ - type Item = R; - - fn next(&mut self) -> Option<R> { - self.iter - .next() - .map(|i| i.into()) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - self.iter.size_hint() - } - - fn fold<Acc, Fold>(self, init: Acc, mut fold_f: Fold) -> Acc - where Fold: FnMut(Acc, Self::Item) -> Acc, - { - self.iter.fold(init, move |acc, v| fold_f(acc, v.into())) - } -} - -impl<I, R> DoubleEndedIterator for MapInto<I, R> - where I: DoubleEndedIterator, - I::Item: Into<R>, -{ - fn next_back(&mut self) -> Option<Self::Item> { - self.iter - .next_back() - .map(|i| i.into()) - } -} - -impl<I, R> ExactSizeIterator for MapInto<I, R> -where - I: ExactSizeIterator, - I::Item: Into<R>, -{} - -/// An iterator adapter to apply a transformation within a nested `Result`. -/// -/// See [`.map_results()`](../trait.Itertools.html#method.map_results) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct MapResults<I, F> { - iter: I, - f: F -} - -/// Create a new `MapResults` iterator. -pub fn map_results<I, F, T, U, E>(iter: I, f: F) -> MapResults<I, F> - where I: Iterator<Item = Result<T, E>>, - F: FnMut(T) -> U, -{ - MapResults { - iter: iter, - f: f, - } -} - -impl<I, F, T, U, E> Iterator for MapResults<I, F> - where I: Iterator<Item = Result<T, E>>, - F: FnMut(T) -> U, -{ - type Item = Result<U, E>; - - fn next(&mut self) -> Option<Self::Item> { - self.iter.next().map(|v| v.map(&mut self.f)) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - self.iter.size_hint() - } - - fn fold<Acc, Fold>(self, init: Acc, mut fold_f: Fold) -> Acc - where Fold: FnMut(Acc, Self::Item) -> Acc, - { - let mut f = self.f; - self.iter.fold(init, move |acc, v| fold_f(acc, v.map(&mut f))) - } - - fn collect<C>(self) -> C - where C: FromIterator<Self::Item> - { - let mut f = self.f; - self.iter.map(move |v| v.map(&mut f)).collect() - } -} - -/// An iterator adapter to get the positions of each element that matches a predicate. -/// -/// See [`.positions()`](../trait.Itertools.html#method.positions) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Positions<I, F> { - iter: I, - f: F, - count: usize, -} - -/// Create a new `Positions` iterator. -pub fn positions<I, F>(iter: I, f: F) -> Positions<I, F> - where I: Iterator, - F: FnMut(I::Item) -> bool, -{ - Positions { - iter: iter, - f: f, - count: 0 - } -} - -impl<I, F> Iterator for Positions<I, F> - where I: Iterator, - F: FnMut(I::Item) -> bool, -{ - type Item = usize; - - fn next(&mut self) -> Option<Self::Item> { - while let Some(v) = self.iter.next() { - let i = self.count; - self.count = i + 1; - if (self.f)(v) { - return Some(i); - } - } - None - } - - fn size_hint(&self) -> (usize, Option<usize>) { - (0, self.iter.size_hint().1) - } -} - -impl<I, F> DoubleEndedIterator for Positions<I, F> - where I: DoubleEndedIterator + ExactSizeIterator, - F: FnMut(I::Item) -> bool, -{ - fn next_back(&mut self) -> Option<Self::Item> { - while let Some(v) = self.iter.next_back() { - if (self.f)(v) { - return Some(self.count + self.iter.len()) - } - } - None - } -} - -/// An iterator adapter to apply a mutating function to each element before yielding it. -/// -/// See [`.update()`](../trait.Itertools.html#method.update) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Update<I, F> { - iter: I, - f: F, -} - -/// Create a new `Update` iterator. -pub fn update<I, F>(iter: I, f: F) -> Update<I, F> -where - I: Iterator, - F: FnMut(&mut I::Item), -{ - Update { iter: iter, f: f } -} - -impl<I, F> Iterator for Update<I, F> -where - I: Iterator, - F: FnMut(&mut I::Item), -{ - type Item = I::Item; - - fn next(&mut self) -> Option<Self::Item> { - if let Some(mut v) = self.iter.next() { - (self.f)(&mut v); - Some(v) - } else { - None - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - self.iter.size_hint() - } - - fn fold<Acc, G>(self, init: Acc, mut g: G) -> Acc - where G: FnMut(Acc, Self::Item) -> Acc, - { - let mut f = self.f; - self.iter.fold(init, move |acc, mut v| { f(&mut v); g(acc, v) }) - } - - // if possible, re-use inner iterator specializations in collect - fn collect<C>(self) -> C - where C: FromIterator<Self::Item> - { - let mut f = self.f; - self.iter.map(move |mut v| { f(&mut v); v }).collect() - } -} - -impl<I, F> ExactSizeIterator for Update<I, F> -where - I: ExactSizeIterator, - F: FnMut(&mut I::Item), -{} - -impl<I, F> DoubleEndedIterator for Update<I, F> -where - I: DoubleEndedIterator, - F: FnMut(&mut I::Item), -{ - fn next_back(&mut self) -> Option<Self::Item> { - if let Some(mut v) = self.iter.next_back() { - (self.f)(&mut v); - Some(v) - } else { - None - } - } -} diff --git a/vendor/itertools-0.8.2/src/adaptors/multi_product.rs b/vendor/itertools-0.8.2/src/adaptors/multi_product.rs deleted file mode 100644 index a6796386ed..0000000000 --- a/vendor/itertools-0.8.2/src/adaptors/multi_product.rs +++ /dev/null @@ -1,220 +0,0 @@ -#![cfg(feature = "use_std")] - -use size_hint; -use Itertools; - -#[derive(Clone)] -/// An iterator adaptor that iterates over the cartesian product of -/// multiple iterators of type `I`. -/// -/// An iterator element type is `Vec<I>`. -/// -/// See [`.multi_cartesian_product()`](../trait.Itertools.html#method.multi_cartesian_product) -/// for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct MultiProduct<I>(Vec<MultiProductIter<I>>) - where I: Iterator + Clone, - I::Item: Clone; - -/// Create a new cartesian product iterator over an arbitrary number -/// of iterators of the same type. -/// -/// Iterator element is of type `Vec<H::Item::Item>`. -pub fn multi_cartesian_product<H>(iters: H) -> MultiProduct<<H::Item as IntoIterator>::IntoIter> - where H: Iterator, - H::Item: IntoIterator, - <H::Item as IntoIterator>::IntoIter: Clone, - <H::Item as IntoIterator>::Item: Clone -{ - MultiProduct(iters.map(|i| MultiProductIter::new(i.into_iter())).collect()) -} - -#[derive(Clone, Debug)] -/// Holds the state of a single iterator within a MultiProduct. -struct MultiProductIter<I> - where I: Iterator + Clone, - I::Item: Clone -{ - cur: Option<I::Item>, - iter: I, - iter_orig: I, -} - -/// Holds the current state during an iteration of a MultiProduct. -#[derive(Debug)] -enum MultiProductIterState { - StartOfIter, - MidIter { on_first_iter: bool }, -} - -impl<I> MultiProduct<I> - where I: Iterator + Clone, - I::Item: Clone -{ - /// Iterates the rightmost iterator, then recursively iterates iterators - /// to the left if necessary. - /// - /// Returns true if the iteration succeeded, else false. - fn iterate_last( - multi_iters: &mut [MultiProductIter<I>], - mut state: MultiProductIterState - ) -> bool { - use self::MultiProductIterState::*; - - if let Some((last, rest)) = multi_iters.split_last_mut() { - let on_first_iter = match state { - StartOfIter => { - let on_first_iter = !last.in_progress(); - state = MidIter { on_first_iter: on_first_iter }; - on_first_iter - }, - MidIter { on_first_iter } => on_first_iter - }; - - if !on_first_iter { - last.iterate(); - } - - if last.in_progress() { - true - } else if MultiProduct::iterate_last(rest, state) { - last.reset(); - last.iterate(); - // If iterator is None twice consecutively, then iterator is - // empty; whole product is empty. - last.in_progress() - } else { - false - } - } else { - // Reached end of iterator list. On initialisation, return true. - // At end of iteration (final iterator finishes), finish. - match state { - StartOfIter => false, - MidIter { on_first_iter } => on_first_iter - } - } - } - - /// Returns the unwrapped value of the next iteration. - fn curr_iterator(&self) -> Vec<I::Item> { - self.0.iter().map(|multi_iter| { - multi_iter.cur.clone().unwrap() - }).collect() - } - - /// Returns true if iteration has started and has not yet finished; false - /// otherwise. - fn in_progress(&self) -> bool { - if let Some(last) = self.0.last() { - last.in_progress() - } else { - false - } - } -} - -impl<I> MultiProductIter<I> - where I: Iterator + Clone, - I::Item: Clone -{ - fn new(iter: I) -> Self { - MultiProductIter { - cur: None, - iter: iter.clone(), - iter_orig: iter - } - } - - /// Iterate the managed iterator. - fn iterate(&mut self) { - self.cur = self.iter.next(); - } - - /// Reset the managed iterator. - fn reset(&mut self) { - self.iter = self.iter_orig.clone(); - } - - /// Returns true if the current iterator has been started and has not yet - /// finished; false otherwise. - fn in_progress(&self) -> bool { - self.cur.is_some() - } -} - -impl<I> Iterator for MultiProduct<I> - where I: Iterator + Clone, - I::Item: Clone -{ - type Item = Vec<I::Item>; - - fn next(&mut self) -> Option<Self::Item> { - if MultiProduct::iterate_last( - &mut self.0, - MultiProductIterState::StartOfIter - ) { - Some(self.curr_iterator()) - } else { - None - } - } - - fn count(self) -> usize { - if self.0.len() == 0 { - return 0; - } - - if !self.in_progress() { - return self.0.into_iter().fold(1, |acc, multi_iter| { - acc * multi_iter.iter.count() - }); - } - - self.0.into_iter().fold( - 0, - |acc, MultiProductIter { iter, iter_orig, cur: _ }| { - let total_count = iter_orig.count(); - let cur_count = iter.count(); - acc * total_count + cur_count - } - ) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - // Not ExactSizeIterator because size may be larger than usize - if self.0.len() == 0 { - return (0, Some(0)); - } - - if !self.in_progress() { - return self.0.iter().fold((1, Some(1)), |acc, multi_iter| { - size_hint::mul(acc, multi_iter.iter.size_hint()) - }); - } - - self.0.iter().fold( - (0, Some(0)), - |acc, &MultiProductIter { ref iter, ref iter_orig, cur: _ }| { - let cur_size = iter.size_hint(); - let total_size = iter_orig.size_hint(); - size_hint::add(size_hint::mul(acc, total_size), cur_size) - } - ) - } - - fn last(self) -> Option<Self::Item> { - let iter_count = self.0.len(); - - let lasts: Self::Item = self.0.into_iter() - .map(|multi_iter| multi_iter.iter.last()) - .while_some() - .collect(); - - if lasts.len() == iter_count { - Some(lasts) - } else { - None - } - } -} diff --git a/vendor/itertools-0.8.2/src/combinations.rs b/vendor/itertools-0.8.2/src/combinations.rs deleted file mode 100644 index 61833cecd3..0000000000 --- a/vendor/itertools-0.8.2/src/combinations.rs +++ /dev/null @@ -1,100 +0,0 @@ -use std::fmt; - -use super::lazy_buffer::LazyBuffer; - -/// An iterator to iterate through all the `k`-length combinations in an iterator. -/// -/// See [`.combinations()`](../trait.Itertools.html#method.combinations) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Combinations<I: Iterator> { - k: usize, - indices: Vec<usize>, - pool: LazyBuffer<I>, - first: bool, -} - -impl<I> fmt::Debug for Combinations<I> - where I: Iterator + fmt::Debug, - I::Item: fmt::Debug, -{ - debug_fmt_fields!(Combinations, k, indices, pool, first); -} - -/// Create a new `Combinations` from a clonable iterator. -pub fn combinations<I>(iter: I, k: usize) -> Combinations<I> - where I: Iterator -{ - let mut indices: Vec<usize> = Vec::with_capacity(k); - for i in 0..k { - indices.push(i); - } - let mut pool: LazyBuffer<I> = LazyBuffer::new(iter); - - for _ in 0..k { - if !pool.get_next() { - break; - } - } - - Combinations { - k: k, - indices: indices, - pool: pool, - first: true, - } -} - -impl<I> Iterator for Combinations<I> - where I: Iterator, - I::Item: Clone -{ - type Item = Vec<I::Item>; - fn next(&mut self) -> Option<Self::Item> { - let mut pool_len = self.pool.len(); - if self.pool.is_done() { - if pool_len == 0 || self.k > pool_len { - return None; - } - } - - if self.first { - self.first = false; - } else if self.k == 0 { - return None; - } else { - // Scan from the end, looking for an index to increment - let mut i: usize = self.k - 1; - - // Check if we need to consume more from the iterator - if self.indices[i] == pool_len - 1 && !self.pool.is_done() { - if self.pool.get_next() { - pool_len += 1; - } - } - - while self.indices[i] == i + pool_len - self.k { - if i > 0 { - i -= 1; - } else { - // Reached the last combination - return None; - } - } - - // Increment index, and reset the ones to its right - self.indices[i] += 1; - let mut j = i + 1; - while j < self.k { - self.indices[j] = self.indices[j - 1] + 1; - j += 1; - } - } - - // Create result vector based on the indices - let mut result = Vec::with_capacity(self.k); - for i in self.indices.iter() { - result.push(self.pool[*i].clone()); - } - Some(result) - } -} diff --git a/vendor/itertools-0.8.2/src/combinations_with_replacement.rs b/vendor/itertools-0.8.2/src/combinations_with_replacement.rs deleted file mode 100644 index 499ccf70d1..0000000000 --- a/vendor/itertools-0.8.2/src/combinations_with_replacement.rs +++ /dev/null @@ -1,108 +0,0 @@ -use std::fmt; - -use super::lazy_buffer::LazyBuffer; - -/// An iterator to iterate through all the `n`-length combinations in an iterator, with replacement. -/// -/// See [`.combinations_with_replacement()`](../trait.Itertools.html#method.combinations_with_replacement) for more information. -#[derive(Clone)] -pub struct CombinationsWithReplacement<I> -where - I: Iterator, - I::Item: Clone, -{ - k: usize, - indices: Vec<usize>, - // The current known max index value. This increases as pool grows. - max_index: usize, - pool: LazyBuffer<I>, - first: bool, -} - -impl<I> fmt::Debug for CombinationsWithReplacement<I> -where - I: Iterator + fmt::Debug, - I::Item: fmt::Debug + Clone, -{ - debug_fmt_fields!(Combinations, k, indices, max_index, pool, first); -} - -impl<I> CombinationsWithReplacement<I> -where - I: Iterator, - I::Item: Clone, -{ - /// Map the current mask over the pool to get an output combination - fn current(&self) -> Vec<I::Item> { - self.indices.iter().map(|i| self.pool[*i].clone()).collect() - } -} - -/// Create a new `CombinationsWithReplacement` from a clonable iterator. -pub fn combinations_with_replacement<I>(iter: I, k: usize) -> CombinationsWithReplacement<I> -where - I: Iterator, - I::Item: Clone, -{ - let indices: Vec<usize> = vec![0; k]; - let pool: LazyBuffer<I> = LazyBuffer::new(iter); - - CombinationsWithReplacement { - k, - indices, - max_index: 0, - pool: pool, - first: true, - } -} - -impl<I> Iterator for CombinationsWithReplacement<I> -where - I: Iterator, - I::Item: Clone, -{ - type Item = Vec<I::Item>; - fn next(&mut self) -> Option<Self::Item> { - // If this is the first iteration, return early - if self.first { - // In empty edge cases, stop iterating immediately - return if self.k == 0 || self.pool.is_done() { - None - // Otherwise, yield the initial state - } else { - self.first = false; - Some(self.current()) - }; - } - - // Check if we need to consume more from the iterator - // This will run while we increment our first index digit - if !self.pool.is_done() { - self.pool.get_next(); - self.max_index = self.pool.len() - 1; - } - - // Work out where we need to update our indices - let mut increment: Option<(usize, usize)> = None; - for (i, indices_int) in self.indices.iter().enumerate().rev() { - if indices_int < &self.max_index { - increment = Some((i, indices_int + 1)); - break; - } - } - - match increment { - // If we can update the indices further - Some((increment_from, increment_value)) => { - // We need to update the rightmost non-max value - // and all those to the right - for indices_index in increment_from..self.indices.len() { - self.indices[indices_index] = increment_value - } - Some(self.current()) - } - // Otherwise, we're done - None => None, - } - } -} diff --git a/vendor/itertools-0.8.2/src/concat_impl.rs b/vendor/itertools-0.8.2/src/concat_impl.rs deleted file mode 100644 index 05b370e1c6..0000000000 --- a/vendor/itertools-0.8.2/src/concat_impl.rs +++ /dev/null @@ -1,22 +0,0 @@ -use Itertools; - -/// Combine all an iterator's elements into one element by using `Extend`. -/// -/// `IntoIterator`-enabled version of `.concat()` -/// -/// This combinator will extend the first item with each of the rest of the -/// items of the iterator. If the iterator is empty, the default value of -/// `I::Item` is returned. -/// -/// ```rust -/// use itertools::concat; -/// -/// let input = vec![vec![1], vec![2, 3], vec![4, 5, 6]]; -/// assert_eq!(concat(input), vec![1, 2, 3, 4, 5, 6]); -/// ``` -pub fn concat<I>(iterable: I) -> I::Item - where I: IntoIterator, - I::Item: Extend<<<I as IntoIterator>::Item as IntoIterator>::Item> + IntoIterator + Default -{ - iterable.into_iter().fold1(|mut a, b| { a.extend(b); a }).unwrap_or_else(|| <_>::default()) -} diff --git a/vendor/itertools-0.8.2/src/cons_tuples_impl.rs b/vendor/itertools-0.8.2/src/cons_tuples_impl.rs deleted file mode 100644 index 9b27e7580f..0000000000 --- a/vendor/itertools-0.8.2/src/cons_tuples_impl.rs +++ /dev/null @@ -1,68 +0,0 @@ - -macro_rules! impl_cons_iter( - ($_A:ident, $_B:ident, ) => (); // stop - - ($A:ident, $($B:ident,)*) => ( - impl_cons_iter!($($B,)*); - #[allow(non_snake_case)] - impl<X, Iter, $($B),*> Iterator for ConsTuples<Iter, (($($B,)*), X)> - where Iter: Iterator<Item = (($($B,)*), X)>, - { - type Item = ($($B,)* X, ); - fn next(&mut self) -> Option<Self::Item> { - self.iter.next().map(|(($($B,)*), x)| ($($B,)* x, )) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - self.iter.size_hint() - } - fn fold<Acc, Fold>(self, accum: Acc, mut f: Fold) -> Acc - where Fold: FnMut(Acc, Self::Item) -> Acc, - { - self.iter.fold(accum, move |acc, (($($B,)*), x)| f(acc, ($($B,)* x, ))) - } - } - - #[allow(non_snake_case)] - impl<X, Iter, $($B),*> DoubleEndedIterator for ConsTuples<Iter, (($($B,)*), X)> - where Iter: DoubleEndedIterator<Item = (($($B,)*), X)>, - { - fn next_back(&mut self) -> Option<Self::Item> { - self.iter.next().map(|(($($B,)*), x)| ($($B,)* x, )) - } - } - - ); -); - -impl_cons_iter!(A, B, C, D, E, F, G, H,); - -/// An iterator that maps an iterator of tuples like -/// `((A, B), C)` to an iterator of `(A, B, C)`. -/// -/// Used by the `iproduct!()` macro. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -#[derive(Debug)] -pub struct ConsTuples<I, J> - where I: Iterator<Item=J>, -{ - iter: I, -} - -impl<I, J> Clone for ConsTuples<I, J> - where I: Clone + Iterator<Item=J>, -{ - fn clone(&self) -> Self { - ConsTuples { - iter: self.iter.clone(), - } - } -} - -/// Create an iterator that maps for example iterators of -/// `((A, B), C)` to `(A, B, C)`. -pub fn cons_tuples<I, J>(iterable: I) -> ConsTuples<I, J> - where I: Iterator<Item=J> -{ - ConsTuples { iter: iterable.into_iter() } -} diff --git a/vendor/itertools-0.8.2/src/diff.rs b/vendor/itertools-0.8.2/src/diff.rs deleted file mode 100644 index 2951bc422e..0000000000 --- a/vendor/itertools-0.8.2/src/diff.rs +++ /dev/null @@ -1,61 +0,0 @@ -//! "Diff"ing iterators for caching elements to sequential collections without requiring the new -//! elements' iterator to be `Clone`. -//! -//! - [**Diff**](./enum.Diff.html) (produced by the [**diff_with**](./fn.diff_with.html) function) -//! describes the difference between two non-`Clone` iterators `I` and `J` after breaking ASAP from -//! a lock-step comparison. - -use free::put_back; -use structs::PutBack; - -/// A type returned by the [`diff_with`](./fn.diff_with.html) function. -/// -/// `Diff` represents the way in which the elements yielded by the iterator `I` differ to some -/// iterator `J`. -pub enum Diff<I, J> - where I: Iterator, - J: Iterator -{ - /// The index of the first non-matching element along with both iterator's remaining elements - /// starting with the first mis-match. - FirstMismatch(usize, PutBack<I>, PutBack<J>), - /// The total number of elements that were in `J` along with the remaining elements of `I`. - Shorter(usize, PutBack<I>), - /// The total number of elements that were in `I` along with the remaining elements of `J`. - Longer(usize, PutBack<J>), -} - -/// Compares every element yielded by both `i` and `j` with the given function in lock-step and -/// returns a `Diff` which describes how `j` differs from `i`. -/// -/// If the number of elements yielded by `j` is less than the number of elements yielded by `i`, -/// the number of `j` elements yielded will be returned along with `i`'s remaining elements as -/// `Diff::Shorter`. -/// -/// If the two elements of a step differ, the index of those elements along with the remaining -/// elements of both `i` and `j` are returned as `Diff::FirstMismatch`. -/// -/// If `i` becomes exhausted before `j` becomes exhausted, the number of elements in `i` along with -/// the remaining `j` elements will be returned as `Diff::Longer`. -pub fn diff_with<I, J, F>(i: I, j: J, is_equal: F) - -> Option<Diff<I::IntoIter, J::IntoIter>> - where I: IntoIterator, - J: IntoIterator, - F: Fn(&I::Item, &J::Item) -> bool -{ - let mut i = i.into_iter(); - let mut j = j.into_iter(); - let mut idx = 0; - while let Some(i_elem) = i.next() { - match j.next() { - None => return Some(Diff::Shorter(idx, put_back(i).with_value(i_elem))), - Some(j_elem) => if !is_equal(&i_elem, &j_elem) { - let remaining_i = put_back(i).with_value(i_elem); - let remaining_j = put_back(j).with_value(j_elem); - return Some(Diff::FirstMismatch(idx, remaining_i, remaining_j)); - }, - } - idx += 1; - } - j.next().map(|j_elem| Diff::Longer(idx, put_back(j).with_value(j_elem))) -} diff --git a/vendor/itertools-0.8.2/src/either_or_both.rs b/vendor/itertools-0.8.2/src/either_or_both.rs deleted file mode 100644 index 03130b128c..0000000000 --- a/vendor/itertools-0.8.2/src/either_or_both.rs +++ /dev/null @@ -1,190 +0,0 @@ -use EitherOrBoth::*; - -use either::Either; - -/// Value that either holds a single A or B, or both. -#[derive(Clone, PartialEq, Eq, Debug)] -pub enum EitherOrBoth<A, B> { - /// Both values are present. - Both(A, B), - /// Only the left value of type `A` is present. - Left(A), - /// Only the right value of type `B` is present. - Right(B), -} - -impl<A, B> EitherOrBoth<A, B> { - /// If `Left`, or `Both`, return true, otherwise, return false. - pub fn has_left(&self) -> bool { - self.as_ref().left().is_some() - } - - /// If `Right`, or `Both`, return true, otherwise, return false. - pub fn has_right(&self) -> bool { - self.as_ref().right().is_some() - } - - /// If Left, return true otherwise, return false. - /// Exclusive version of [`has_left`]. - pub fn is_left(&self) -> bool { - match *self { - Left(_) => true, - _ => false, - } - } - - /// If Right, return true otherwise, return false. - /// Exclusive version of [`has_right`]. - pub fn is_right(&self) -> bool { - match *self { - Right(_) => true, - _ => false, - } - } - - /// If Right, return true otherwise, return false. - /// Equivalent to `self.as_ref().both().is_some()`. - pub fn is_both(&self) -> bool { - self.as_ref().both().is_some() - } - - /// If `Left`, or `Both`, return `Some` with the left value, otherwise, return `None`. - pub fn left(self) -> Option<A> { - match self { - Left(left) | Both(left, _) => Some(left), - _ => None, - } - } - - /// If `Right`, or `Both`, return `Some` with the right value, otherwise, return `None`. - pub fn right(self) -> Option<B> { - match self { - Right(right) | Both(_, right) => Some(right), - _ => None, - } - } - - /// If Both, return `Some` tuple containing left and right. - pub fn both(self) -> Option<(A, B)> { - match self { - Both(a, b) => Some((a, b)), - _ => None, - } - } - - /// Converts from `&EitherOrBoth<A, B>` to `EitherOrBoth<&A, &B>`. - pub fn as_ref(&self) -> EitherOrBoth<&A, &B> { - match *self { - Left(ref left) => Left(left), - Right(ref right) => Right(right), - Both(ref left, ref right) => Both(left, right), - } - } - - /// Converts from `&mut EitherOrBoth<A, B>` to `EitherOrBoth<&mut A, &mut B>`. - pub fn as_mut(&mut self) -> EitherOrBoth<&mut A, &mut B> { - match *self { - Left(ref mut left) => Left(left), - Right(ref mut right) => Right(right), - Both(ref mut left, ref mut right) => Both(left, right), - } - } - - /// Convert `EitherOrBoth<A, B>` to `EitherOrBoth<B, A>`. - pub fn flip(self) -> EitherOrBoth<B, A> { - match self { - Left(a) => Right(a), - Right(b) => Left(b), - Both(a, b) => Both(b, a), - } - } - - /// Apply the function `f` on the value `a` in `Left(a)` or `Both(a, b)` variants. If it is - /// present rewrapping the result in `self`'s original variant. - pub fn map_left<F, M>(self, f: F) -> EitherOrBoth<M, B> - where - F: FnOnce(A) -> M, - { - match self { - Both(a, b) => Both(f(a), b), - Left(a) => Left(f(a)), - Right(b) => Right(b), - } - } - - /// Apply the function `f` on the value `b` in `Right(b)` or `Both(a, b)` variants. - /// If it is present rewrapping the result in `self`'s original variant. - pub fn map_right<F, M>(self, f: F) -> EitherOrBoth<A, M> - where - F: FnOnce(B) -> M, - { - match self { - Left(a) => Left(a), - Right(b) => Right(f(b)), - Both(a, b) => Both(a, f(b)), - } - } - - /// Apply the functions `f` and `g` on the value `a` and `b` respectively; - /// found in `Left(a)`, `Right(b)`, or `Both(a, b)` variants. - /// The Result is rewrapped `self`'s original variant. - pub fn map_any<F, L, G, R>(self, f: F, g: G) -> EitherOrBoth<L, R> - where - F: FnOnce(A) -> L, - G: FnOnce(B) -> R, - { - match self { - Left(a) => Left(f(a)), - Right(b) => Right(g(b)), - Both(a, b) => Both(f(a), g(b)), - } - } - - /// Apply the function `f` on the value `b` in `Right(b)` or `Both(a, _)` variants if it is - /// present. - pub fn left_and_then<F, L>(self, f: F) -> EitherOrBoth<L, B> - where - F: FnOnce(A) -> EitherOrBoth<L, B>, - { - match self { - Left(a) | Both(a, _) => f(a), - Right(b) => Right(b), - } - } - - /// Apply the function `f` on the value `a` - /// in `Left(a)` or `Both(a, _)` variants if it is present. - pub fn right_and_then<F, R>(self, f: F) -> EitherOrBoth<A, R> - where - F: FnOnce(B) -> EitherOrBoth<A, R>, - { - match self { - Left(a) => Left(a), - Right(b) | Both(_, b) => f(b), - } - } -} - -impl<T> EitherOrBoth<T, T> { - /// Return either value of left, right, or the product of `f` applied where `Both` are present. - pub fn reduce<F>(self, f: F) -> T - where - F: FnOnce(T, T) -> T, - { - match self { - Left(a) => a, - Right(b) => b, - Both(a, b) => f(a, b), - } - } -} - -impl<A, B> Into<Option<Either<A, B>>> for EitherOrBoth<A, B> { - fn into(self) -> Option<Either<A, B>> { - match self { - EitherOrBoth::Left(l) => Some(Either::Left(l)), - EitherOrBoth::Right(r) => Some(Either::Right(r)), - _ => None, - } - } -} diff --git a/vendor/itertools-0.8.2/src/exactly_one_err.rs b/vendor/itertools-0.8.2/src/exactly_one_err.rs deleted file mode 100644 index 6b7bad56d2..0000000000 --- a/vendor/itertools-0.8.2/src/exactly_one_err.rs +++ /dev/null @@ -1,58 +0,0 @@ -use std::iter::ExactSizeIterator; - -use size_hint; - -/// Iterator returned for the error case of `IterTools::exactly_one()` -/// This iterator yields exactly the same elements as the input iterator. -/// -/// During the execution of exactly_one the iterator must be mutated. This wrapper -/// effectively "restores" the state of the input iterator when it's handed back. -/// -/// This is very similar to PutBackN except this iterator only supports 0-2 elements and does not -/// use a `Vec`. -#[derive(Debug, Clone)] -pub struct ExactlyOneError<I> -where - I: Iterator, -{ - first_two: (Option<I::Item>, Option<I::Item>), - inner: I, -} - -impl<I> ExactlyOneError<I> -where - I: Iterator, -{ - /// Creates a new `ExactlyOneErr` iterator. - pub(crate) fn new(first_two: (Option<I::Item>, Option<I::Item>), inner: I) -> Self { - Self { first_two, inner } - } -} - -impl<I> Iterator for ExactlyOneError<I> -where - I: Iterator, -{ - type Item = I::Item; - - fn next(&mut self) -> Option<Self::Item> { - self.first_two - .0 - .take() - .or_else(|| self.first_two.1.take()) - .or_else(|| self.inner.next()) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - let mut additional_len = 0; - if self.first_two.0.is_some() { - additional_len += 1; - } - if self.first_two.1.is_some() { - additional_len += 1; - } - size_hint::add_scalar(self.inner.size_hint(), additional_len) - } -} - -impl<I> ExactSizeIterator for ExactlyOneError<I> where I: ExactSizeIterator {} diff --git a/vendor/itertools-0.8.2/src/format.rs b/vendor/itertools-0.8.2/src/format.rs deleted file mode 100644 index c42806b01c..0000000000 --- a/vendor/itertools-0.8.2/src/format.rs +++ /dev/null @@ -1,113 +0,0 @@ -use std::fmt; -use std::cell::RefCell; - -/// Format all iterator elements lazily, separated by `sep`. -/// -/// The format value can only be formatted once, after that the iterator is -/// exhausted. -/// -/// See [`.format_with()`](../trait.Itertools.html#method.format_with) for more information. -pub struct FormatWith<'a, I, F> { - sep: &'a str, - /// FormatWith uses interior mutability because Display::fmt takes &self. - inner: RefCell<Option<(I, F)>>, -} - -/// Format all iterator elements lazily, separated by `sep`. -/// -/// The format value can only be formatted once, after that the iterator is -/// exhausted. -/// -/// See [`.format()`](../trait.Itertools.html#method.format) -/// for more information. -#[derive(Clone)] -pub struct Format<'a, I> { - sep: &'a str, - /// Format uses interior mutability because Display::fmt takes &self. - inner: RefCell<Option<I>>, -} - -pub fn new_format<'a, I, F>(iter: I, separator: &'a str, f: F) -> FormatWith<'a, I, F> - where I: Iterator, - F: FnMut(I::Item, &mut FnMut(&fmt::Display) -> fmt::Result) -> fmt::Result -{ - FormatWith { - sep: separator, - inner: RefCell::new(Some((iter, f))), - } -} - -pub fn new_format_default<'a, I>(iter: I, separator: &'a str) -> Format<'a, I> - where I: Iterator, -{ - Format { - sep: separator, - inner: RefCell::new(Some(iter)), - } -} - -impl<'a, I, F> fmt::Display for FormatWith<'a, I, F> - where I: Iterator, - F: FnMut(I::Item, &mut FnMut(&fmt::Display) -> fmt::Result) -> fmt::Result -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let (mut iter, mut format) = match self.inner.borrow_mut().take() { - Some(t) => t, - None => panic!("FormatWith: was already formatted once"), - }; - - if let Some(fst) = iter.next() { - try!(format(fst, &mut |disp: &fmt::Display| disp.fmt(f))); - for elt in iter { - if self.sep.len() > 0 { - - try!(f.write_str(self.sep)); - } - try!(format(elt, &mut |disp: &fmt::Display| disp.fmt(f))); - } - } - Ok(()) - } -} - -impl<'a, I> Format<'a, I> - where I: Iterator, -{ - fn format<F>(&self, f: &mut fmt::Formatter, mut cb: F) -> fmt::Result - where F: FnMut(&I::Item, &mut fmt::Formatter) -> fmt::Result, - { - let mut iter = match self.inner.borrow_mut().take() { - Some(t) => t, - None => panic!("Format: was already formatted once"), - }; - - if let Some(fst) = iter.next() { - try!(cb(&fst, f)); - for elt in iter { - if self.sep.len() > 0 { - try!(f.write_str(self.sep)); - } - try!(cb(&elt, f)); - } - } - Ok(()) - } -} - -macro_rules! impl_format { - ($($fmt_trait:ident)*) => { - $( - impl<'a, I> fmt::$fmt_trait for Format<'a, I> - where I: Iterator, - I::Item: fmt::$fmt_trait, - { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.format(f, fmt::$fmt_trait::fmt) - } - } - )* - } -} - -impl_format!{Display Debug - UpperExp LowerExp UpperHex LowerHex Octal Binary Pointer} diff --git a/vendor/itertools-0.8.2/src/free.rs b/vendor/itertools-0.8.2/src/free.rs deleted file mode 100644 index 2bc72a9aa1..0000000000 --- a/vendor/itertools-0.8.2/src/free.rs +++ /dev/null @@ -1,236 +0,0 @@ -//! Free functions that create iterator adaptors or call iterator methods. -//! -//! The benefit of free functions is that they accept any `IntoIterator` as -//! argument, so the resulting code may be easier to read. - -#[cfg(feature = "use_std")] -use std::fmt::Display; -use std::iter::{self, Zip}; -#[cfg(feature = "use_std")] -type VecIntoIter<T> = ::std::vec::IntoIter<T>; - -#[cfg(feature = "use_std")] -use Itertools; - -pub use adaptors::{ - interleave, - merge, - put_back, -}; -#[cfg(feature = "use_std")] -pub use put_back_n_impl::put_back_n; -#[cfg(feature = "use_std")] -pub use multipeek_impl::multipeek; -#[cfg(feature = "use_std")] -pub use kmerge_impl::kmerge; -pub use zip_eq_impl::zip_eq; -pub use merge_join::merge_join_by; -#[cfg(feature = "use_std")] -pub use rciter_impl::rciter; - -/// Iterate `iterable` with a running index. -/// -/// `IntoIterator` enabled version of `.enumerate()`. -/// -/// ``` -/// use itertools::enumerate; -/// -/// for (i, elt) in enumerate(&[1, 2, 3]) { -/// /* loop body */ -/// } -/// ``` -pub fn enumerate<I>(iterable: I) -> iter::Enumerate<I::IntoIter> - where I: IntoIterator -{ - iterable.into_iter().enumerate() -} - -/// Iterate `iterable` in reverse. -/// -/// `IntoIterator` enabled version of `.rev()`. -/// -/// ``` -/// use itertools::rev; -/// -/// for elt in rev(&[1, 2, 3]) { -/// /* loop body */ -/// } -/// ``` -pub fn rev<I>(iterable: I) -> iter::Rev<I::IntoIter> - where I: IntoIterator, - I::IntoIter: DoubleEndedIterator -{ - iterable.into_iter().rev() -} - -/// Iterate `i` and `j` in lock step. -/// -/// `IntoIterator` enabled version of `i.zip(j)`. -/// -/// ``` -/// use itertools::zip; -/// -/// let data = [1, 2, 3, 4, 5]; -/// for (a, b) in zip(&data, &data[1..]) { -/// /* loop body */ -/// } -/// ``` -pub fn zip<I, J>(i: I, j: J) -> Zip<I::IntoIter, J::IntoIter> - where I: IntoIterator, - J: IntoIterator -{ - i.into_iter().zip(j) -} - -/// Create an iterator that first iterates `i` and then `j`. -/// -/// `IntoIterator` enabled version of `i.chain(j)`. -/// -/// ``` -/// use itertools::chain; -/// -/// for elt in chain(&[1, 2, 3], &[4]) { -/// /* loop body */ -/// } -/// ``` -pub fn chain<I, J>(i: I, j: J) -> iter::Chain<<I as IntoIterator>::IntoIter, <J as IntoIterator>::IntoIter> - where I: IntoIterator, - J: IntoIterator<Item = I::Item> -{ - i.into_iter().chain(j) -} - -/// Create an iterator that clones each element from &T to T -/// -/// `IntoIterator` enabled version of `i.cloned()`. -/// -/// ``` -/// use itertools::cloned; -/// -/// assert_eq!(cloned(b"abc").next(), Some(b'a')); -/// ``` -pub fn cloned<'a, I, T: 'a>(iterable: I) -> iter::Cloned<I::IntoIter> - where I: IntoIterator<Item=&'a T>, - T: Clone, -{ - iterable.into_iter().cloned() -} - -/// Perform a fold operation over the iterable. -/// -/// `IntoIterator` enabled version of `i.fold(init, f)` -/// -/// ``` -/// use itertools::fold; -/// -/// assert_eq!(fold(&[1., 2., 3.], 0., |a, &b| f32::max(a, b)), 3.); -/// ``` -pub fn fold<I, B, F>(iterable: I, init: B, f: F) -> B - where I: IntoIterator, - F: FnMut(B, I::Item) -> B -{ - iterable.into_iter().fold(init, f) -} - -/// Test whether the predicate holds for all elements in the iterable. -/// -/// `IntoIterator` enabled version of `i.all(f)` -/// -/// ``` -/// use itertools::all; -/// -/// assert!(all(&[1, 2, 3], |elt| *elt > 0)); -/// ``` -pub fn all<I, F>(iterable: I, f: F) -> bool - where I: IntoIterator, - F: FnMut(I::Item) -> bool -{ - iterable.into_iter().all(f) -} - -/// Test whether the predicate holds for any elements in the iterable. -/// -/// `IntoIterator` enabled version of `i.any(f)` -/// -/// ``` -/// use itertools::any; -/// -/// assert!(any(&[0, -1, 2], |elt| *elt > 0)); -/// ``` -pub fn any<I, F>(iterable: I, f: F) -> bool - where I: IntoIterator, - F: FnMut(I::Item) -> bool -{ - iterable.into_iter().any(f) -} - -/// Return the maximum value of the iterable. -/// -/// `IntoIterator` enabled version of `i.max()`. -/// -/// ``` -/// use itertools::max; -/// -/// assert_eq!(max(0..10), Some(9)); -/// ``` -pub fn max<I>(iterable: I) -> Option<I::Item> - where I: IntoIterator, - I::Item: Ord -{ - iterable.into_iter().max() -} - -/// Return the minimum value of the iterable. -/// -/// `IntoIterator` enabled version of `i.min()`. -/// -/// ``` -/// use itertools::min; -/// -/// assert_eq!(min(0..10), Some(0)); -/// ``` -pub fn min<I>(iterable: I) -> Option<I::Item> - where I: IntoIterator, - I::Item: Ord -{ - iterable.into_iter().min() -} - - -/// Combine all iterator elements into one String, seperated by `sep`. -/// -/// `IntoIterator` enabled version of `iterable.join(sep)`. -/// -/// ``` -/// use itertools::join; -/// -/// assert_eq!(join(&[1, 2, 3], ", "), "1, 2, 3"); -/// ``` -#[cfg(feature = "use_std")] -pub fn join<I>(iterable: I, sep: &str) -> String - where I: IntoIterator, - I::Item: Display -{ - iterable.into_iter().join(sep) -} - -/// Sort all iterator elements into a new iterator in ascending order. -/// -/// `IntoIterator` enabled version of [`iterable.sorted()`][1]. -/// -/// [1]: trait.Itertools.html#method.sorted -/// -/// ``` -/// use itertools::sorted; -/// use itertools::assert_equal; -/// -/// assert_equal(sorted("rust".chars()), "rstu".chars()); -/// ``` -#[cfg(feature = "use_std")] -pub fn sorted<I>(iterable: I) -> VecIntoIter<I::Item> - where I: IntoIterator, - I::Item: Ord -{ - iterable.into_iter().sorted() -} - diff --git a/vendor/itertools-0.8.2/src/group_map.rs b/vendor/itertools-0.8.2/src/group_map.rs deleted file mode 100644 index be9f8420d8..0000000000 --- a/vendor/itertools-0.8.2/src/group_map.rs +++ /dev/null @@ -1,22 +0,0 @@ -#![cfg(feature = "use_std")] - -use std::collections::HashMap; -use std::hash::Hash; -use std::iter::Iterator; - -/// Return a `HashMap` of keys mapped to a list of their corresponding values. -/// -/// See [`.into_group_map()`](../trait.Itertools.html#method.into_group_map) -/// for more information. -pub fn into_group_map<I, K, V>(iter: I) -> HashMap<K, Vec<V>> - where I: Iterator<Item=(K, V)>, - K: Hash + Eq, -{ - let mut lookup = HashMap::new(); - - for (key, val) in iter { - lookup.entry(key).or_insert(Vec::new()).push(val); - } - - lookup -} \ No newline at end of file diff --git a/vendor/itertools-0.8.2/src/groupbylazy.rs b/vendor/itertools-0.8.2/src/groupbylazy.rs deleted file mode 100644 index ff253e845d..0000000000 --- a/vendor/itertools-0.8.2/src/groupbylazy.rs +++ /dev/null @@ -1,571 +0,0 @@ -use std::cell::{Cell, RefCell}; -use std::vec; - -/// A trait to unify FnMut for GroupBy with the chunk key in IntoChunks -trait KeyFunction<A> { - type Key; - fn call_mut(&mut self, arg: A) -> Self::Key; -} - -impl<'a, A, K, F: ?Sized> KeyFunction<A> for F - where F: FnMut(A) -> K -{ - type Key = K; - #[inline] - fn call_mut(&mut self, arg: A) -> Self::Key { - (*self)(arg) - } -} - - -/// ChunkIndex acts like the grouping key function for IntoChunks -#[derive(Debug)] -struct ChunkIndex { - size: usize, - index: usize, - key: usize, -} - -impl ChunkIndex { - #[inline(always)] - fn new(size: usize) -> Self { - ChunkIndex { - size: size, - index: 0, - key: 0, - } - } -} - -impl<'a, A> KeyFunction<A> for ChunkIndex { - type Key = usize; - #[inline(always)] - fn call_mut(&mut self, _arg: A) -> Self::Key { - if self.index == self.size { - self.key += 1; - self.index = 0; - } - self.index += 1; - self.key - } -} - - -struct GroupInner<K, I, F> - where I: Iterator -{ - key: F, - iter: I, - current_key: Option<K>, - current_elt: Option<I::Item>, - /// flag set if iterator is exhausted - done: bool, - /// Index of group we are currently buffering or visiting - top_group: usize, - /// Least index for which we still have elements buffered - oldest_buffered_group: usize, - /// Group index for `buffer[0]` -- the slots - /// bottom_group..oldest_buffered_group are unused and will be erased when - /// that range is large enough. - bottom_group: usize, - /// Buffered groups, from `bottom_group` (index 0) to `top_group`. - buffer: Vec<vec::IntoIter<I::Item>>, - /// index of last group iter that was dropped, usize::MAX == none - dropped_group: usize, -} - -impl<K, I, F> GroupInner<K, I, F> - where I: Iterator, - F: for<'a> KeyFunction<&'a I::Item, Key=K>, - K: PartialEq, -{ - /// `client`: Index of group that requests next element - #[inline(always)] - fn step(&mut self, client: usize) -> Option<I::Item> { - /* - println!("client={}, bottom_group={}, oldest_buffered_group={}, top_group={}, buffers=[{}]", - client, self.bottom_group, self.oldest_buffered_group, - self.top_group, - self.buffer.iter().map(|elt| elt.len()).format(", ")); - */ - if client < self.oldest_buffered_group { - None - } else if client < self.top_group || - (client == self.top_group && - self.buffer.len() > self.top_group - self.bottom_group) - { - self.lookup_buffer(client) - } else if self.done { - None - } else if self.top_group == client { - self.step_current() - } else { - self.step_buffering(client) - } - } - - #[inline(never)] - fn lookup_buffer(&mut self, client: usize) -> Option<I::Item> { - // if `bufidx` doesn't exist in self.buffer, it might be empty - let bufidx = client - self.bottom_group; - if client < self.oldest_buffered_group { - return None; - } - let elt = self.buffer.get_mut(bufidx).and_then(|queue| queue.next()); - if elt.is_none() && client == self.oldest_buffered_group { - // FIXME: VecDeque is unfortunately not zero allocation when empty, - // so we do this job manually. - // `bottom_group..oldest_buffered_group` is unused, and if it's large enough, erase it. - self.oldest_buffered_group += 1; - // skip forward further empty queues too - while self.buffer.get(self.oldest_buffered_group - self.bottom_group) - .map_or(false, |buf| buf.len() == 0) - { - self.oldest_buffered_group += 1; - } - - let nclear = self.oldest_buffered_group - self.bottom_group; - if nclear > 0 && nclear >= self.buffer.len() / 2 { - let mut i = 0; - self.buffer.retain(|buf| { - i += 1; - debug_assert!(buf.len() == 0 || i > nclear); - i > nclear - }); - self.bottom_group = self.oldest_buffered_group; - } - } - elt - } - - /// Take the next element from the iterator, and set the done - /// flag if exhausted. Must not be called after done. - #[inline(always)] - fn next_element(&mut self) -> Option<I::Item> { - debug_assert!(!self.done); - match self.iter.next() { - None => { self.done = true; None } - otherwise => otherwise, - } - } - - - #[inline(never)] - fn step_buffering(&mut self, client: usize) -> Option<I::Item> { - // requested a later group -- walk through the current group up to - // the requested group index, and buffer the elements (unless - // the group is marked as dropped). - // Because the `Groups` iterator is always the first to request - // each group index, client is the next index efter top_group. - debug_assert!(self.top_group + 1 == client); - let mut group = Vec::new(); - - if let Some(elt) = self.current_elt.take() { - if self.top_group != self.dropped_group { - group.push(elt); - } - } - let mut first_elt = None; // first element of the next group - - while let Some(elt) = self.next_element() { - let key = self.key.call_mut(&elt); - match self.current_key.take() { - None => {} - Some(old_key) => if old_key != key { - self.current_key = Some(key); - first_elt = Some(elt); - break; - }, - } - self.current_key = Some(key); - if self.top_group != self.dropped_group { - group.push(elt); - } - } - - if self.top_group != self.dropped_group { - self.push_next_group(group); - } - if first_elt.is_some() { - self.top_group += 1; - debug_assert!(self.top_group == client); - } - first_elt - } - - fn push_next_group(&mut self, group: Vec<I::Item>) { - // When we add a new buffered group, fill up slots between oldest_buffered_group and top_group - while self.top_group - self.bottom_group > self.buffer.len() { - if self.buffer.is_empty() { - self.bottom_group += 1; - self.oldest_buffered_group += 1; - } else { - self.buffer.push(Vec::new().into_iter()); - } - } - self.buffer.push(group.into_iter()); - debug_assert!(self.top_group + 1 - self.bottom_group == self.buffer.len()); - } - - /// This is the immediate case, where we use no buffering - #[inline] - fn step_current(&mut self) -> Option<I::Item> { - debug_assert!(!self.done); - if let elt @ Some(..) = self.current_elt.take() { - return elt; - } - match self.next_element() { - None => None, - Some(elt) => { - let key = self.key.call_mut(&elt); - match self.current_key.take() { - None => {} - Some(old_key) => if old_key != key { - self.current_key = Some(key); - self.current_elt = Some(elt); - self.top_group += 1; - return None; - }, - } - self.current_key = Some(key); - Some(elt) - } - } - } - - /// Request the just started groups' key. - /// - /// `client`: Index of group - /// - /// **Panics** if no group key is available. - fn group_key(&mut self, client: usize) -> K { - // This can only be called after we have just returned the first - // element of a group. - // Perform this by simply buffering one more element, grabbing the - // next key. - debug_assert!(!self.done); - debug_assert!(client == self.top_group); - debug_assert!(self.current_key.is_some()); - debug_assert!(self.current_elt.is_none()); - let old_key = self.current_key.take().unwrap(); - if let Some(elt) = self.next_element() { - let key = self.key.call_mut(&elt); - if old_key != key { - self.top_group += 1; - } - self.current_key = Some(key); - self.current_elt = Some(elt); - } - old_key - } -} - -impl<K, I, F> GroupInner<K, I, F> - where I: Iterator, -{ - /// Called when a group is dropped - fn drop_group(&mut self, client: usize) { - // It's only useful to track the maximal index - if self.dropped_group == !0 || client > self.dropped_group { - self.dropped_group = client; - } - } -} - -/// `GroupBy` is the storage for the lazy grouping operation. -/// -/// If the groups are consumed in their original order, or if each -/// group is dropped without keeping it around, then `GroupBy` uses -/// no allocations. It needs allocations only if several group iterators -/// are alive at the same time. -/// -/// This type implements `IntoIterator` (it is **not** an iterator -/// itself), because the group iterators need to borrow from this -/// value. It should be stored in a local variable or temporary and -/// iterated. -/// -/// See [`.group_by()`](../trait.Itertools.html#method.group_by) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct GroupBy<K, I, F> - where I: Iterator, -{ - inner: RefCell<GroupInner<K, I, F>>, - // the group iterator's current index. Keep this in the main value - // so that simultaneous iterators all use the same state. - index: Cell<usize>, -} - -/// Create a new -pub fn new<K, J, F>(iter: J, f: F) -> GroupBy<K, J::IntoIter, F> - where J: IntoIterator, - F: FnMut(&J::Item) -> K, -{ - GroupBy { - inner: RefCell::new(GroupInner { - key: f, - iter: iter.into_iter(), - current_key: None, - current_elt: None, - done: false, - top_group: 0, - oldest_buffered_group: 0, - bottom_group: 0, - buffer: Vec::new(), - dropped_group: !0, - }), - index: Cell::new(0), - } -} - -impl<K, I, F> GroupBy<K, I, F> - where I: Iterator, -{ - /// `client`: Index of group that requests next element - fn step(&self, client: usize) -> Option<I::Item> - where F: FnMut(&I::Item) -> K, - K: PartialEq, - { - self.inner.borrow_mut().step(client) - } - - /// `client`: Index of group - fn drop_group(&self, client: usize) { - self.inner.borrow_mut().drop_group(client) - } -} - -impl<'a, K, I, F> IntoIterator for &'a GroupBy<K, I, F> - where I: Iterator, - I::Item: 'a, - F: FnMut(&I::Item) -> K, - K: PartialEq -{ - type Item = (K, Group<'a, K, I, F>); - type IntoIter = Groups<'a, K, I, F>; - - fn into_iter(self) -> Self::IntoIter { - Groups { parent: self } - } -} - - -/// An iterator that yields the Group iterators. -/// -/// Iterator element type is `(K, Group)`: -/// the group's key `K` and the group's iterator. -/// -/// See [`.group_by()`](../trait.Itertools.html#method.group_by) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Groups<'a, K: 'a, I: 'a, F: 'a> - where I: Iterator, - I::Item: 'a -{ - parent: &'a GroupBy<K, I, F>, -} - -impl<'a, K, I, F> Iterator for Groups<'a, K, I, F> - where I: Iterator, - I::Item: 'a, - F: FnMut(&I::Item) -> K, - K: PartialEq -{ - type Item = (K, Group<'a, K, I, F>); - - #[inline] - fn next(&mut self) -> Option<Self::Item> { - let index = self.parent.index.get(); - self.parent.index.set(index + 1); - let inner = &mut *self.parent.inner.borrow_mut(); - inner.step(index).map(|elt| { - let key = inner.group_key(index); - (key, Group { - parent: self.parent, - index: index, - first: Some(elt), - }) - }) - } -} - -/// An iterator for the elements in a single group. -/// -/// Iterator element type is `I::Item`. -pub struct Group<'a, K: 'a, I: 'a, F: 'a> - where I: Iterator, - I::Item: 'a, -{ - parent: &'a GroupBy<K, I, F>, - index: usize, - first: Option<I::Item>, -} - -impl<'a, K, I, F> Drop for Group<'a, K, I, F> - where I: Iterator, - I::Item: 'a, -{ - fn drop(&mut self) { - self.parent.drop_group(self.index); - } -} - -impl<'a, K, I, F> Iterator for Group<'a, K, I, F> - where I: Iterator, - I::Item: 'a, - F: FnMut(&I::Item) -> K, - K: PartialEq, -{ - type Item = I::Item; - #[inline] - fn next(&mut self) -> Option<Self::Item> { - if let elt @ Some(..) = self.first.take() { - return elt; - } - self.parent.step(self.index) - } -} - -///// IntoChunks ///// - -/// Create a new -pub fn new_chunks<J>(iter: J, size: usize) -> IntoChunks<J::IntoIter> - where J: IntoIterator, -{ - IntoChunks { - inner: RefCell::new(GroupInner { - key: ChunkIndex::new(size), - iter: iter.into_iter(), - current_key: None, - current_elt: None, - done: false, - top_group: 0, - oldest_buffered_group: 0, - bottom_group: 0, - buffer: Vec::new(), - dropped_group: !0, - }), - index: Cell::new(0), - } -} - - -/// `ChunkLazy` is the storage for a lazy chunking operation. -/// -/// `IntoChunks` behaves just like `GroupBy`: it is iterable, and -/// it only buffers if several chunk iterators are alive at the same time. -/// -/// This type implements `IntoIterator` (it is **not** an iterator -/// itself), because the chunk iterators need to borrow from this -/// value. It should be stored in a local variable or temporary and -/// iterated. -/// -/// Iterator element type is `Chunk`, each chunk's iterator. -/// -/// See [`.chunks()`](../trait.Itertools.html#method.chunks) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct IntoChunks<I> - where I: Iterator, -{ - inner: RefCell<GroupInner<usize, I, ChunkIndex>>, - // the chunk iterator's current index. Keep this in the main value - // so that simultaneous iterators all use the same state. - index: Cell<usize>, -} - - -impl<I> IntoChunks<I> - where I: Iterator, -{ - /// `client`: Index of chunk that requests next element - fn step(&self, client: usize) -> Option<I::Item> { - self.inner.borrow_mut().step(client) - } - - /// `client`: Index of chunk - fn drop_group(&self, client: usize) { - self.inner.borrow_mut().drop_group(client) - } -} - -impl<'a, I> IntoIterator for &'a IntoChunks<I> - where I: Iterator, - I::Item: 'a, -{ - type Item = Chunk<'a, I>; - type IntoIter = Chunks<'a, I>; - - fn into_iter(self) -> Self::IntoIter { - Chunks { - parent: self, - } - } -} - - -/// An iterator that yields the Chunk iterators. -/// -/// Iterator element type is `Chunk`. -/// -/// See [`.chunks()`](../trait.Itertools.html#method.chunks) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Chunks<'a, I: 'a> - where I: Iterator, - I::Item: 'a, -{ - parent: &'a IntoChunks<I>, -} - -impl<'a, I> Iterator for Chunks<'a, I> - where I: Iterator, - I::Item: 'a, -{ - type Item = Chunk<'a, I>; - - #[inline] - fn next(&mut self) -> Option<Self::Item> { - let index = self.parent.index.get(); - self.parent.index.set(index + 1); - let inner = &mut *self.parent.inner.borrow_mut(); - inner.step(index).map(|elt| { - Chunk { - parent: self.parent, - index: index, - first: Some(elt), - } - }) - } -} - -/// An iterator for the elements in a single chunk. -/// -/// Iterator element type is `I::Item`. -pub struct Chunk<'a, I: 'a> - where I: Iterator, - I::Item: 'a, -{ - parent: &'a IntoChunks<I>, - index: usize, - first: Option<I::Item>, -} - -impl<'a, I> Drop for Chunk<'a, I> - where I: Iterator, - I::Item: 'a, -{ - fn drop(&mut self) { - self.parent.drop_group(self.index); - } -} - -impl<'a, I> Iterator for Chunk<'a, I> - where I: Iterator, - I::Item: 'a, -{ - type Item = I::Item; - #[inline] - fn next(&mut self) -> Option<Self::Item> { - if let elt @ Some(..) = self.first.take() { - return elt; - } - self.parent.step(self.index) - } -} diff --git a/vendor/itertools-0.8.2/src/impl_macros.rs b/vendor/itertools-0.8.2/src/impl_macros.rs deleted file mode 100644 index b41760aee8..0000000000 --- a/vendor/itertools-0.8.2/src/impl_macros.rs +++ /dev/null @@ -1,14 +0,0 @@ -//! -//! Implementation's internal macros - -macro_rules! debug_fmt_fields { - ($tyname:ident, $($($field:ident).+),*) => { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - f.debug_struct(stringify!($tyname)) - $( - .field(stringify!($($field).+), &self.$($field).+) - )* - .finish() - } - } -} diff --git a/vendor/itertools-0.8.2/src/intersperse.rs b/vendor/itertools-0.8.2/src/intersperse.rs deleted file mode 100644 index f82544229c..0000000000 --- a/vendor/itertools-0.8.2/src/intersperse.rs +++ /dev/null @@ -1,79 +0,0 @@ -use std::iter::Fuse; -use super::size_hint; - -#[derive(Clone)] -/// An iterator adaptor to insert a particular value -/// between each element of the adapted iterator. -/// -/// Iterator element type is `I::Item` -/// -/// This iterator is *fused*. -/// -/// See [`.intersperse()`](../trait.Itertools.html#method.intersperse) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -#[derive(Debug)] -pub struct Intersperse<I> - where I: Iterator -{ - element: I::Item, - iter: Fuse<I>, - peek: Option<I::Item>, -} - -/// Create a new Intersperse iterator -pub fn intersperse<I>(iter: I, elt: I::Item) -> Intersperse<I> - where I: Iterator -{ - let mut iter = iter.fuse(); - Intersperse { - peek: iter.next(), - iter: iter, - element: elt, - } -} - -impl<I> Iterator for Intersperse<I> - where I: Iterator, - I::Item: Clone -{ - type Item = I::Item; - #[inline] - fn next(&mut self) -> Option<I::Item> { - if self.peek.is_some() { - self.peek.take() - } else { - self.peek = self.iter.next(); - if self.peek.is_some() { - Some(self.element.clone()) - } else { - None - } - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - // 2 * SH + { 1 or 0 } - let has_peek = self.peek.is_some() as usize; - let sh = self.iter.size_hint(); - size_hint::add_scalar(size_hint::add(sh, sh), has_peek) - } - - fn fold<B, F>(mut self, init: B, mut f: F) -> B where - Self: Sized, F: FnMut(B, Self::Item) -> B, - { - let mut accum = init; - - if let Some(x) = self.peek.take() { - accum = f(accum, x); - } - - let element = &self.element; - - self.iter.fold(accum, - |accum, x| { - let accum = f(accum, element.clone()); - let accum = f(accum, x); - accum - }) - } -} diff --git a/vendor/itertools-0.8.2/src/kmerge_impl.rs b/vendor/itertools-0.8.2/src/kmerge_impl.rs deleted file mode 100644 index a79b7bdace..0000000000 --- a/vendor/itertools-0.8.2/src/kmerge_impl.rs +++ /dev/null @@ -1,231 +0,0 @@ - -use size_hint; -use Itertools; - -use std::mem::replace; -use std::fmt; - -macro_rules! clone_fields { - ($name:ident, $base:expr, $($field:ident),+) => ( - $name { - $( - $field : $base . $field .clone() - ),* - } - ); -} - -/// Head element and Tail iterator pair -/// -/// `PartialEq`, `Eq`, `PartialOrd` and `Ord` are implemented by comparing sequences based on -/// first items (which are guaranteed to exist). -/// -/// The meanings of `PartialOrd` and `Ord` are reversed so as to turn the heap used in -/// `KMerge` into a min-heap. -#[derive(Debug)] -struct HeadTail<I> - where I: Iterator -{ - head: I::Item, - tail: I, -} - -impl<I> HeadTail<I> - where I: Iterator -{ - /// Constructs a `HeadTail` from an `Iterator`. Returns `None` if the `Iterator` is empty. - fn new(mut it: I) -> Option<HeadTail<I>> { - let head = it.next(); - head.map(|h| { - HeadTail { - head: h, - tail: it, - } - }) - } - - /// Get the next element and update `head`, returning the old head in `Some`. - /// - /// Returns `None` when the tail is exhausted (only `head` then remains). - fn next(&mut self) -> Option<I::Item> { - if let Some(next) = self.tail.next() { - Some(replace(&mut self.head, next)) - } else { - None - } - } - - /// Hints at the size of the sequence, same as the `Iterator` method. - fn size_hint(&self) -> (usize, Option<usize>) { - size_hint::add_scalar(self.tail.size_hint(), 1) - } -} - -impl<I> Clone for HeadTail<I> - where I: Iterator + Clone, - I::Item: Clone -{ - fn clone(&self) -> Self { - clone_fields!(HeadTail, self, head, tail) - } -} - -/// Make `data` a heap (min-heap w.r.t the sorting). -fn heapify<T, S>(data: &mut [T], mut less_than: S) - where S: FnMut(&T, &T) -> bool -{ - for i in (0..data.len() / 2).rev() { - sift_down(data, i, &mut less_than); - } -} - -/// Sift down element at `index` (`heap` is a min-heap wrt the ordering) -fn sift_down<T, S>(heap: &mut [T], index: usize, mut less_than: S) - where S: FnMut(&T, &T) -> bool -{ - debug_assert!(index <= heap.len()); - let mut pos = index; - let mut child = 2 * pos + 1; - // the `pos` conditional is to avoid a bounds check - while pos < heap.len() && child < heap.len() { - let right = child + 1; - - // pick the smaller of the two children - if right < heap.len() && less_than(&heap[right], &heap[child]) { - child = right; - } - - // sift down is done if we are already in order - if !less_than(&heap[child], &heap[pos]) { - return; - } - heap.swap(pos, child); - pos = child; - child = 2 * pos + 1; - } -} - -/// An iterator adaptor that merges an abitrary number of base iterators in ascending order. -/// If all base iterators are sorted (ascending), the result is sorted. -/// -/// Iterator element type is `I::Item`. -/// -/// See [`.kmerge()`](../trait.Itertools.html#method.kmerge) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub type KMerge<I> = KMergeBy<I, KMergeByLt>; - -pub trait KMergePredicate<T> { - fn kmerge_pred(&mut self, a: &T, b: &T) -> bool; -} - -#[derive(Clone)] -pub struct KMergeByLt; - -impl<T: PartialOrd> KMergePredicate<T> for KMergeByLt { - fn kmerge_pred(&mut self, a: &T, b: &T) -> bool { - a < b - } -} - -impl<T, F: FnMut(&T, &T)->bool> KMergePredicate<T> for F { - fn kmerge_pred(&mut self, a: &T, b: &T) -> bool { - self(a, b) - } -} - -/// Create an iterator that merges elements of the contained iterators using -/// the ordering function. -/// -/// Equivalent to `iterable.into_iter().kmerge()`. -/// -/// ``` -/// use itertools::kmerge; -/// -/// for elt in kmerge(vec![vec![0, 2, 4], vec![1, 3, 5], vec![6, 7]]) { -/// /* loop body */ -/// } -/// ``` -pub fn kmerge<I>(iterable: I) -> KMerge<<I::Item as IntoIterator>::IntoIter> - where I: IntoIterator, - I::Item: IntoIterator, - <<I as IntoIterator>::Item as IntoIterator>::Item: PartialOrd -{ - kmerge_by(iterable, KMergeByLt) -} - -/// An iterator adaptor that merges an abitrary number of base iterators -/// according to an ordering function. -/// -/// Iterator element type is `I::Item`. -/// -/// See [`.kmerge_by()`](../trait.Itertools.html#method.kmerge_by) for more -/// information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct KMergeBy<I, F> - where I: Iterator, -{ - heap: Vec<HeadTail<I>>, - less_than: F, -} - -impl<I, F> fmt::Debug for KMergeBy<I, F> - where I: Iterator + fmt::Debug, - I::Item: fmt::Debug, -{ - debug_fmt_fields!(KMergeBy, heap); -} - -/// Create an iterator that merges elements of the contained iterators. -/// -/// Equivalent to `iterable.into_iter().kmerge_by(less_than)`. -pub fn kmerge_by<I, F>(iterable: I, mut less_than: F) - -> KMergeBy<<I::Item as IntoIterator>::IntoIter, F> - where I: IntoIterator, - I::Item: IntoIterator, - F: KMergePredicate<<<I as IntoIterator>::Item as IntoIterator>::Item>, -{ - let iter = iterable.into_iter(); - let (lower, _) = iter.size_hint(); - let mut heap: Vec<_> = Vec::with_capacity(lower); - heap.extend(iter.filter_map(|it| HeadTail::new(it.into_iter()))); - heapify(&mut heap, |a, b| less_than.kmerge_pred(&a.head, &b.head)); - KMergeBy { heap: heap, less_than: less_than } -} - -impl<I, F> Clone for KMergeBy<I, F> - where I: Iterator + Clone, - I::Item: Clone, - F: Clone, -{ - fn clone(&self) -> KMergeBy<I, F> { - clone_fields!(KMergeBy, self, heap, less_than) - } -} - -impl<I, F> Iterator for KMergeBy<I, F> - where I: Iterator, - F: KMergePredicate<I::Item> -{ - type Item = I::Item; - - fn next(&mut self) -> Option<Self::Item> { - if self.heap.is_empty() { - return None; - } - let result = if let Some(next) = self.heap[0].next() { - next - } else { - self.heap.swap_remove(0).head - }; - let less_than = &mut self.less_than; - sift_down(&mut self.heap, 0, |a, b| less_than.kmerge_pred(&a.head, &b.head)); - Some(result) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - self.heap.iter() - .map(|i| i.size_hint()) - .fold1(size_hint::add) - .unwrap_or((0, Some(0))) - } -} diff --git a/vendor/itertools-0.8.2/src/lazy_buffer.rs b/vendor/itertools-0.8.2/src/lazy_buffer.rs deleted file mode 100644 index 09a8cd9569..0000000000 --- a/vendor/itertools-0.8.2/src/lazy_buffer.rs +++ /dev/null @@ -1,68 +0,0 @@ -use std::ops::Index; - -#[derive(Debug, Clone)] -pub struct LazyBuffer<I: Iterator> { - pub it: I, - done: bool, - buffer: Vec<I::Item>, -} - -impl<I> LazyBuffer<I> -where - I: Iterator, -{ - pub fn new(it: I) -> LazyBuffer<I> { - let mut it = it; - let mut buffer = Vec::new(); - let done; - if let Some(first) = it.next() { - buffer.push(first); - done = false; - } else { - done = true; - } - LazyBuffer { - it: it, - done: done, - buffer: buffer, - } - } - - pub fn len(&self) -> usize { - self.buffer.len() - } - - pub fn is_done(&self) -> bool { - self.done - } - - pub fn get_next(&mut self) -> bool { - if self.done { - return false; - } - let next_item = self.it.next(); - match next_item { - Some(x) => { - self.buffer.push(x); - true - } - None => { - self.done = true; - false - } - } - } -} - -impl<I, J> Index<J> for LazyBuffer<I> -where - I: Iterator, - I::Item: Sized, - Vec<I::Item>: Index<J> -{ - type Output = <Vec<I::Item> as Index<J>>::Output; - - fn index(&self, _index: J) -> &Self::Output { - self.buffer.index(_index) - } -} diff --git a/vendor/itertools-0.8.2/src/lib.rs b/vendor/itertools-0.8.2/src/lib.rs deleted file mode 100644 index d7c7960bb7..0000000000 --- a/vendor/itertools-0.8.2/src/lib.rs +++ /dev/null @@ -1,2391 +0,0 @@ -#![warn(missing_docs)] -#![crate_name="itertools"] -#![cfg_attr(not(feature = "use_std"), no_std)] - -//! Extra iterator adaptors, functions and macros. -//! -//! To extend [`Iterator`] with methods in this crate, import -//! the [`Itertools` trait](./trait.Itertools.html): -//! -//! ``` -//! use itertools::Itertools; -//! ``` -//! -//! Now, new methods like [`interleave`](./trait.Itertools.html#method.interleave) -//! are available on all iterators: -//! -//! ``` -//! use itertools::Itertools; -//! -//! let it = (1..3).interleave(vec![-1, -2]); -//! itertools::assert_equal(it, vec![1, -1, 2, -2]); -//! ``` -//! -//! Most iterator methods are also provided as functions (with the benefit -//! that they convert parameters using [`IntoIterator`]): -//! -//! ``` -//! use itertools::interleave; -//! -//! for elt in interleave(&[1, 2, 3], &[2, 3, 4]) { -//! /* loop body */ -//! } -//! ``` -//! -//! ## Crate Features -//! -//! - `use_std` -//! - Enabled by default. -//! - Disable to compile itertools using `#![no_std]`. This disables -//! any items that depend on collections (like `group_by`, `unique`, -//! `kmerge`, `join` and many more). -//! -//! ## Rust Version -//! -//! This version of itertools requires Rust 1.24 or later. -//! -//! [`Iterator`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html -#![doc(html_root_url="https://docs.rs/itertools/0.8/")] - -extern crate either; - -#[cfg(not(feature = "use_std"))] -extern crate core as std; - -pub use either::Either; - -#[cfg(feature = "use_std")] -use std::collections::HashMap; -use std::iter::{IntoIterator, once}; -use std::cmp::Ordering; -use std::fmt; -#[cfg(feature = "use_std")] -use std::hash::Hash; -#[cfg(feature = "use_std")] -use std::fmt::Write; -#[cfg(feature = "use_std")] -type VecIntoIter<T> = ::std::vec::IntoIter<T>; -#[cfg(feature = "use_std")] -use std::iter::FromIterator; - -#[macro_use] -mod impl_macros; - -// for compatibility with no std and macros -#[doc(hidden)] -pub use std::iter as __std_iter; - -/// The concrete iterator types. -pub mod structs { - pub use adaptors::{ - Dedup, - DedupBy, - Interleave, - InterleaveShortest, - Product, - PutBack, - Batching, - MapInto, - MapResults, - Merge, - MergeBy, - TakeWhileRef, - WhileSome, - Coalesce, - TupleCombinations, - Positions, - Update, - }; - #[allow(deprecated)] - pub use adaptors::Step; - #[cfg(feature = "use_std")] - pub use adaptors::MultiProduct; - #[cfg(feature = "use_std")] - pub use combinations::Combinations; - #[cfg(feature = "use_std")] - pub use combinations_with_replacement::CombinationsWithReplacement; - pub use cons_tuples_impl::ConsTuples; - pub use exactly_one_err::ExactlyOneError; - pub use format::{Format, FormatWith}; - #[cfg(feature = "use_std")] - pub use groupbylazy::{IntoChunks, Chunk, Chunks, GroupBy, Group, Groups}; - pub use intersperse::Intersperse; - #[cfg(feature = "use_std")] - pub use kmerge_impl::{KMerge, KMergeBy}; - pub use merge_join::MergeJoinBy; - #[cfg(feature = "use_std")] - pub use multipeek_impl::MultiPeek; - pub use pad_tail::PadUsing; - pub use peeking_take_while::PeekingTakeWhile; - #[cfg(feature = "use_std")] - pub use permutations::Permutations; - pub use process_results_impl::ProcessResults; - #[cfg(feature = "use_std")] - pub use put_back_n_impl::PutBackN; - #[cfg(feature = "use_std")] - pub use rciter_impl::RcIter; - pub use repeatn::RepeatN; - #[allow(deprecated)] - pub use sources::{RepeatCall, Unfold, Iterate}; - #[cfg(feature = "use_std")] - pub use tee::Tee; - pub use tuple_impl::{TupleBuffer, TupleWindows, Tuples}; - #[cfg(feature = "use_std")] - pub use unique_impl::{Unique, UniqueBy}; - pub use with_position::WithPosition; - pub use zip_eq_impl::ZipEq; - pub use zip_longest::ZipLongest; - pub use ziptuple::Zip; -} -#[allow(deprecated)] -pub use structs::*; -pub use concat_impl::concat; -pub use cons_tuples_impl::cons_tuples; -pub use diff::diff_with; -pub use diff::Diff; -#[cfg(feature = "use_std")] -pub use kmerge_impl::{kmerge_by}; -pub use minmax::MinMaxResult; -pub use peeking_take_while::PeekingNext; -pub use process_results_impl::process_results; -pub use repeatn::repeat_n; -#[allow(deprecated)] -pub use sources::{repeat_call, unfold, iterate}; -pub use with_position::Position; -pub use ziptuple::multizip; -mod adaptors; -mod either_or_both; -pub use either_or_both::EitherOrBoth; -#[doc(hidden)] -pub mod free; -#[doc(inline)] -pub use free::*; -mod concat_impl; -mod cons_tuples_impl; -#[cfg(feature = "use_std")] -mod combinations; -#[cfg(feature = "use_std")] -mod combinations_with_replacement; -mod exactly_one_err; -mod diff; -mod format; -#[cfg(feature = "use_std")] -mod group_map; -#[cfg(feature = "use_std")] -mod groupbylazy; -mod intersperse; -#[cfg(feature = "use_std")] -mod kmerge_impl; -#[cfg(feature = "use_std")] -mod lazy_buffer; -mod merge_join; -mod minmax; -#[cfg(feature = "use_std")] -mod multipeek_impl; -mod pad_tail; -mod peeking_take_while; -#[cfg(feature = "use_std")] -mod permutations; -mod process_results_impl; -#[cfg(feature = "use_std")] -mod put_back_n_impl; -#[cfg(feature = "use_std")] -mod rciter_impl; -mod repeatn; -mod size_hint; -mod sources; -#[cfg(feature = "use_std")] -mod tee; -mod tuple_impl; -#[cfg(feature = "use_std")] -mod unique_impl; -mod with_position; -mod zip_eq_impl; -mod zip_longest; -mod ziptuple; - -#[macro_export] -/// Create an iterator over the “cartesian product” of iterators. -/// -/// Iterator element type is like `(A, B, ..., E)` if formed -/// from iterators `(I, J, ..., M)` with element types `I::Item = A`, `J::Item = B`, etc. -/// -/// ``` -/// #[macro_use] extern crate itertools; -/// # fn main() { -/// // Iterate over the coordinates of a 4 x 4 x 4 grid -/// // from (0, 0, 0), (0, 0, 1), .., (0, 1, 0), (0, 1, 1), .. etc until (3, 3, 3) -/// for (i, j, k) in iproduct!(0..4, 0..4, 0..4) { -/// // .. -/// } -/// # } -/// ``` -/// -/// **Note:** To enable the macros in this crate, use the `#[macro_use]` -/// attribute when importing the crate: -/// -/// ``` -/// #[macro_use] extern crate itertools; -/// # fn main() { } -/// ``` -macro_rules! iproduct { - (@flatten $I:expr,) => ( - $I - ); - (@flatten $I:expr, $J:expr, $($K:expr,)*) => ( - iproduct!(@flatten $crate::cons_tuples(iproduct!($I, $J)), $($K,)*) - ); - ($I:expr) => ( - $crate::__std_iter::IntoIterator::into_iter($I) - ); - ($I:expr, $J:expr) => ( - $crate::Itertools::cartesian_product(iproduct!($I), iproduct!($J)) - ); - ($I:expr, $J:expr, $($K:expr),+) => ( - iproduct!(@flatten iproduct!($I, $J), $($K,)+) - ); -} - -#[macro_export] -/// Create an iterator running multiple iterators in lockstep. -/// -/// The `izip!` iterator yields elements until any subiterator -/// returns `None`. -/// -/// This is a version of the standard ``.zip()`` that's supporting more than -/// two iterators. The iterator element type is a tuple with one element -/// from each of the input iterators. Just like ``.zip()``, the iteration stops -/// when the shortest of the inputs reaches its end. -/// -/// **Note:** The result of this macro is in the general case an iterator -/// composed of repeated `.zip()` and a `.map()`; it has an anonymous type. -/// The special cases of one and two arguments produce the equivalent of -/// `$a.into_iter()` and `$a.into_iter().zip($b)` respectively. -/// -/// Prefer this macro `izip!()` over [`multizip`] for the performance benefits -/// of using the standard library `.zip()`. -/// -/// [`multizip`]: fn.multizip.html -/// -/// ``` -/// #[macro_use] extern crate itertools; -/// # fn main() { -/// -/// // iterate over three sequences side-by-side -/// let mut results = [0, 0, 0, 0]; -/// let inputs = [3, 7, 9, 6]; -/// -/// for (r, index, input) in izip!(&mut results, 0..10, &inputs) { -/// *r = index * 10 + input; -/// } -/// -/// assert_eq!(results, [0 + 3, 10 + 7, 29, 36]); -/// # } -/// ``` -/// -/// **Note:** To enable the macros in this crate, use the `#[macro_use]` -/// attribute when importing the crate: -/// -/// ``` -/// #[macro_use] extern crate itertools; -/// # fn main() { } -/// ``` -macro_rules! izip { - // @closure creates a tuple-flattening closure for .map() call. usage: - // @closure partial_pattern => partial_tuple , rest , of , iterators - // eg. izip!( @closure ((a, b), c) => (a, b, c) , dd , ee ) - ( @closure $p:pat => $tup:expr ) => { - |$p| $tup - }; - - // The "b" identifier is a different identifier on each recursion level thanks to hygiene. - ( @closure $p:pat => ( $($tup:tt)* ) , $_iter:expr $( , $tail:expr )* ) => { - izip!(@closure ($p, b) => ( $($tup)*, b ) $( , $tail )*) - }; - - // unary - ($first:expr $(,)*) => { - $crate::__std_iter::IntoIterator::into_iter($first) - }; - - // binary - ($first:expr, $second:expr $(,)*) => { - izip!($first) - .zip($second) - }; - - // n-ary where n > 2 - ( $first:expr $( , $rest:expr )* $(,)* ) => { - izip!($first) - $( - .zip($rest) - )* - .map( - izip!(@closure a => (a) $( , $rest )*) - ) - }; -} - -/// An [`Iterator`] blanket implementation that provides extra adaptors and -/// methods. -/// -/// This trait defines a number of methods. They are divided into two groups: -/// -/// * *Adaptors* take an iterator and parameter as input, and return -/// a new iterator value. These are listed first in the trait. An example -/// of an adaptor is [`.interleave()`](#method.interleave) -/// -/// * *Regular methods* are those that don't return iterators and instead -/// return a regular value of some other kind. -/// [`.next_tuple()`](#method.next_tuple) is an example and the first regular -/// method in the list. -/// -/// [`Iterator`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html -pub trait Itertools : Iterator { - // adaptors - - /// Alternate elements from two iterators until both have run out. - /// - /// Iterator element type is `Self::Item`. - /// - /// This iterator is *fused*. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let it = (1..7).interleave(vec![-1, -2]); - /// itertools::assert_equal(it, vec![1, -1, 2, -2, 3, 4, 5, 6]); - /// ``` - fn interleave<J>(self, other: J) -> Interleave<Self, J::IntoIter> - where J: IntoIterator<Item = Self::Item>, - Self: Sized - { - interleave(self, other) - } - - /// Alternate elements from two iterators until at least one of them has run - /// out. - /// - /// Iterator element type is `Self::Item`. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let it = (1..7).interleave_shortest(vec![-1, -2]); - /// itertools::assert_equal(it, vec![1, -1, 2, -2, 3]); - /// ``` - fn interleave_shortest<J>(self, other: J) -> InterleaveShortest<Self, J::IntoIter> - where J: IntoIterator<Item = Self::Item>, - Self: Sized - { - adaptors::interleave_shortest(self, other.into_iter()) - } - - /// An iterator adaptor to insert a particular value - /// between each element of the adapted iterator. - /// - /// Iterator element type is `Self::Item`. - /// - /// This iterator is *fused*. - /// - /// ``` - /// use itertools::Itertools; - /// - /// itertools::assert_equal((0..3).intersperse(8), vec![0, 8, 1, 8, 2]); - /// ``` - fn intersperse(self, element: Self::Item) -> Intersperse<Self> - where Self: Sized, - Self::Item: Clone - { - intersperse::intersperse(self, element) - } - - /// Create an iterator which iterates over both this and the specified - /// iterator simultaneously, yielding pairs of two optional elements. - /// - /// This iterator is *fused*. - /// - /// As long as neither input iterator is exhausted yet, it yields two values - /// via `EitherOrBoth::Both`. - /// - /// When the parameter iterator is exhausted, it only yields a value from the - /// `self` iterator via `EitherOrBoth::Left`. - /// - /// When the `self` iterator is exhausted, it only yields a value from the - /// parameter iterator via `EitherOrBoth::Right`. - /// - /// When both iterators return `None`, all further invocations of `.next()` - /// will return `None`. - /// - /// Iterator element type is - /// [`EitherOrBoth<Self::Item, J::Item>`](enum.EitherOrBoth.html). - /// - /// ```rust - /// use itertools::EitherOrBoth::{Both, Right}; - /// use itertools::Itertools; - /// let it = (0..1).zip_longest(1..3); - /// itertools::assert_equal(it, vec![Both(0, 1), Right(2)]); - /// ``` - #[inline] - fn zip_longest<J>(self, other: J) -> ZipLongest<Self, J::IntoIter> - where J: IntoIterator, - Self: Sized - { - zip_longest::zip_longest(self, other.into_iter()) - } - - /// Create an iterator which iterates over both this and the specified - /// iterator simultaneously, yielding pairs of elements. - /// - /// **Panics** if the iterators reach an end and they are not of equal - /// lengths. - #[inline] - fn zip_eq<J>(self, other: J) -> ZipEq<Self, J::IntoIter> - where J: IntoIterator, - Self: Sized - { - zip_eq(self, other) - } - - /// A “meta iterator adaptor”. Its closure receives a reference to the - /// iterator and may pick off as many elements as it likes, to produce the - /// next iterator element. - /// - /// Iterator element type is `B`. - /// - /// ``` - /// use itertools::Itertools; - /// - /// // An adaptor that gathers elements in pairs - /// let pit = (0..4).batching(|it| { - /// match it.next() { - /// None => None, - /// Some(x) => match it.next() { - /// None => None, - /// Some(y) => Some((x, y)), - /// } - /// } - /// }); - /// - /// itertools::assert_equal(pit, vec![(0, 1), (2, 3)]); - /// ``` - /// - fn batching<B, F>(self, f: F) -> Batching<Self, F> - where F: FnMut(&mut Self) -> Option<B>, - Self: Sized - { - adaptors::batching(self, f) - } - - /// Return an *iterable* that can group iterator elements. - /// Consecutive elements that map to the same key (“runs”), are assigned - /// to the same group. - /// - /// `GroupBy` is the storage for the lazy grouping operation. - /// - /// If the groups are consumed in order, or if each group's iterator is - /// dropped without keeping it around, then `GroupBy` uses no - /// allocations. It needs allocations only if several group iterators - /// are alive at the same time. - /// - /// This type implements `IntoIterator` (it is **not** an iterator - /// itself), because the group iterators need to borrow from this - /// value. It should be stored in a local variable or temporary and - /// iterated. - /// - /// Iterator element type is `(K, Group)`: the group's key and the - /// group iterator. - /// - /// ``` - /// use itertools::Itertools; - /// - /// // group data into runs of larger than zero or not. - /// let data = vec![1, 3, -2, -2, 1, 0, 1, 2]; - /// // groups: |---->|------>|--------->| - /// - /// // Note: The `&` is significant here, `GroupBy` is iterable - /// // only by reference. You can also call `.into_iter()` explicitly. - /// for (key, group) in &data.into_iter().group_by(|elt| *elt >= 0) { - /// // Check that the sum of each group is +/- 4. - /// assert_eq!(4, group.sum::<i32>().abs()); - /// } - /// ``` - #[cfg(feature = "use_std")] - fn group_by<K, F>(self, key: F) -> GroupBy<K, Self, F> - where Self: Sized, - F: FnMut(&Self::Item) -> K, - K: PartialEq, - { - groupbylazy::new(self, key) - } - - /// Return an *iterable* that can chunk the iterator. - /// - /// Yield subiterators (chunks) that each yield a fixed number elements, - /// determined by `size`. The last chunk will be shorter if there aren't - /// enough elements. - /// - /// `IntoChunks` is based on `GroupBy`: it is iterable (implements - /// `IntoIterator`, **not** `Iterator`), and it only buffers if several - /// chunk iterators are alive at the same time. - /// - /// Iterator element type is `Chunk`, each chunk's iterator. - /// - /// **Panics** if `size` is 0. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let data = vec![1, 1, 2, -2, 6, 0, 3, 1]; - /// //chunk size=3 |------->|-------->|--->| - /// - /// // Note: The `&` is significant here, `IntoChunks` is iterable - /// // only by reference. You can also call `.into_iter()` explicitly. - /// for chunk in &data.into_iter().chunks(3) { - /// // Check that the sum of each chunk is 4. - /// assert_eq!(4, chunk.sum()); - /// } - /// ``` - #[cfg(feature = "use_std")] - fn chunks(self, size: usize) -> IntoChunks<Self> - where Self: Sized, - { - assert!(size != 0); - groupbylazy::new_chunks(self, size) - } - - /// Return an iterator over all contiguous windows producing tuples of - /// a specific size (up to 4). - /// - /// `tuple_windows` clones the iterator elements so that they can be - /// part of successive windows, this makes it most suited for iterators - /// of references and other values that are cheap to copy. - /// - /// ``` - /// use itertools::Itertools; - /// let mut v = Vec::new(); - /// for (a, b) in (1..5).tuple_windows() { - /// v.push((a, b)); - /// } - /// assert_eq!(v, vec![(1, 2), (2, 3), (3, 4)]); - /// - /// let mut it = (1..5).tuple_windows(); - /// assert_eq!(Some((1, 2, 3)), it.next()); - /// assert_eq!(Some((2, 3, 4)), it.next()); - /// assert_eq!(None, it.next()); - /// - /// // this requires a type hint - /// let it = (1..5).tuple_windows::<(_, _, _)>(); - /// itertools::assert_equal(it, vec![(1, 2, 3), (2, 3, 4)]); - /// - /// // you can also specify the complete type - /// use itertools::TupleWindows; - /// use std::ops::Range; - /// - /// let it: TupleWindows<Range<u32>, (u32, u32, u32)> = (1..5).tuple_windows(); - /// itertools::assert_equal(it, vec![(1, 2, 3), (2, 3, 4)]); - /// ``` - fn tuple_windows<T>(self) -> TupleWindows<Self, T> - where Self: Sized + Iterator<Item = T::Item>, - T: tuple_impl::TupleCollect, - T::Item: Clone - { - tuple_impl::tuple_windows(self) - } - - /// Return an iterator that groups the items in tuples of a specific size - /// (up to 4). - /// - /// See also the method [`.next_tuple()`](#method.next_tuple). - /// - /// ``` - /// use itertools::Itertools; - /// let mut v = Vec::new(); - /// for (a, b) in (1..5).tuples() { - /// v.push((a, b)); - /// } - /// assert_eq!(v, vec![(1, 2), (3, 4)]); - /// - /// let mut it = (1..7).tuples(); - /// assert_eq!(Some((1, 2, 3)), it.next()); - /// assert_eq!(Some((4, 5, 6)), it.next()); - /// assert_eq!(None, it.next()); - /// - /// // this requires a type hint - /// let it = (1..7).tuples::<(_, _, _)>(); - /// itertools::assert_equal(it, vec![(1, 2, 3), (4, 5, 6)]); - /// - /// // you can also specify the complete type - /// use itertools::Tuples; - /// use std::ops::Range; - /// - /// let it: Tuples<Range<u32>, (u32, u32, u32)> = (1..7).tuples(); - /// itertools::assert_equal(it, vec![(1, 2, 3), (4, 5, 6)]); - /// ``` - /// - /// See also [`Tuples::into_buffer`](structs/struct.Tuples.html#method.into_buffer). - fn tuples<T>(self) -> Tuples<Self, T> - where Self: Sized + Iterator<Item = T::Item>, - T: tuple_impl::TupleCollect - { - tuple_impl::tuples(self) - } - - /// Split into an iterator pair that both yield all elements from - /// the original iterator. - /// - /// **Note:** If the iterator is clonable, prefer using that instead - /// of using this method. It is likely to be more efficient. - /// - /// Iterator element type is `Self::Item`. - /// - /// ``` - /// use itertools::Itertools; - /// let xs = vec![0, 1, 2, 3]; - /// - /// let (mut t1, t2) = xs.into_iter().tee(); - /// itertools::assert_equal(t1.next(), Some(0)); - /// itertools::assert_equal(t2, 0..4); - /// itertools::assert_equal(t1, 1..4); - /// ``` - #[cfg(feature = "use_std")] - fn tee(self) -> (Tee<Self>, Tee<Self>) - where Self: Sized, - Self::Item: Clone - { - tee::new(self) - } - - /// Return an iterator adaptor that steps `n` elements in the base iterator - /// for each iteration. - /// - /// The iterator steps by yielding the next element from the base iterator, - /// then skipping forward `n - 1` elements. - /// - /// Iterator element type is `Self::Item`. - /// - /// **Panics** if the step is 0. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let it = (0..8).step(3); - /// itertools::assert_equal(it, vec![0, 3, 6]); - /// ``` - #[deprecated(note="Use std .step_by() instead", since="0.8")] - #[allow(deprecated)] - fn step(self, n: usize) -> Step<Self> - where Self: Sized - { - adaptors::step(self, n) - } - - /// Convert each item of the iterator using the `Into` trait. - /// - /// ```rust - /// use itertools::Itertools; - /// - /// (1i32..42i32).map_into::<f64>().collect_vec(); - /// ``` - fn map_into<R>(self) -> MapInto<Self, R> - where Self: Sized, - Self::Item: Into<R>, - { - adaptors::map_into(self) - } - - /// Return an iterator adaptor that applies the provided closure - /// to every `Result::Ok` value. `Result::Err` values are - /// unchanged. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let input = vec![Ok(41), Err(false), Ok(11)]; - /// let it = input.into_iter().map_results(|i| i + 1); - /// itertools::assert_equal(it, vec![Ok(42), Err(false), Ok(12)]); - /// ``` - fn map_results<F, T, U, E>(self, f: F) -> MapResults<Self, F> - where Self: Iterator<Item = Result<T, E>> + Sized, - F: FnMut(T) -> U, - { - adaptors::map_results(self, f) - } - - /// Return an iterator adaptor that merges the two base iterators in - /// ascending order. If both base iterators are sorted (ascending), the - /// result is sorted. - /// - /// Iterator element type is `Self::Item`. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let a = (0..11).step(3); - /// let b = (0..11).step(5); - /// let it = a.merge(b); - /// itertools::assert_equal(it, vec![0, 0, 3, 5, 6, 9, 10]); - /// ``` - fn merge<J>(self, other: J) -> Merge<Self, J::IntoIter> - where Self: Sized, - Self::Item: PartialOrd, - J: IntoIterator<Item = Self::Item> - { - merge(self, other) - } - - /// Return an iterator adaptor that merges the two base iterators in order. - /// This is much like `.merge()` but allows for a custom ordering. - /// - /// This can be especially useful for sequences of tuples. - /// - /// Iterator element type is `Self::Item`. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let a = (0..).zip("bc".chars()); - /// let b = (0..).zip("ad".chars()); - /// let it = a.merge_by(b, |x, y| x.1 <= y.1); - /// itertools::assert_equal(it, vec![(0, 'a'), (0, 'b'), (1, 'c'), (1, 'd')]); - /// ``` - - fn merge_by<J, F>(self, other: J, is_first: F) -> MergeBy<Self, J::IntoIter, F> - where Self: Sized, - J: IntoIterator<Item = Self::Item>, - F: FnMut(&Self::Item, &Self::Item) -> bool - { - adaptors::merge_by_new(self, other.into_iter(), is_first) - } - - /// Create an iterator that merges items from both this and the specified - /// iterator in ascending order. - /// - /// It chooses whether to pair elements based on the `Ordering` returned by the - /// specified compare function. At any point, inspecting the tip of the - /// iterators `I` and `J` as items `i` of type `I::Item` and `j` of type - /// `J::Item` respectively, the resulting iterator will: - /// - /// - Emit `EitherOrBoth::Left(i)` when `i < j`, - /// and remove `i` from its source iterator - /// - Emit `EitherOrBoth::Right(j)` when `i > j`, - /// and remove `j` from its source iterator - /// - Emit `EitherOrBoth::Both(i, j)` when `i == j`, - /// and remove both `i` and `j` from their respective source iterators - /// - /// ``` - /// use itertools::Itertools; - /// use itertools::EitherOrBoth::{Left, Right, Both}; - /// - /// let ki = (0..10).step(3); - /// let ku = (0..10).step(5); - /// let ki_ku = ki.merge_join_by(ku, |i, j| i.cmp(j)).map(|either| { - /// match either { - /// Left(_) => "Ki", - /// Right(_) => "Ku", - /// Both(_, _) => "KiKu" - /// } - /// }); - /// - /// itertools::assert_equal(ki_ku, vec!["KiKu", "Ki", "Ku", "Ki", "Ki"]); - /// ``` - #[inline] - fn merge_join_by<J, F>(self, other: J, cmp_fn: F) -> MergeJoinBy<Self, J::IntoIter, F> - where J: IntoIterator, - F: FnMut(&Self::Item, &J::Item) -> std::cmp::Ordering, - Self: Sized - { - merge_join_by(self, other, cmp_fn) - } - - - /// Return an iterator adaptor that flattens an iterator of iterators by - /// merging them in ascending order. - /// - /// If all base iterators are sorted (ascending), the result is sorted. - /// - /// Iterator element type is `Self::Item`. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let a = (0..6).step(3); - /// let b = (1..6).step(3); - /// let c = (2..6).step(3); - /// let it = vec![a, b, c].into_iter().kmerge(); - /// itertools::assert_equal(it, vec![0, 1, 2, 3, 4, 5]); - /// ``` - #[cfg(feature = "use_std")] - fn kmerge(self) -> KMerge<<Self::Item as IntoIterator>::IntoIter> - where Self: Sized, - Self::Item: IntoIterator, - <Self::Item as IntoIterator>::Item: PartialOrd, - { - kmerge(self) - } - - /// Return an iterator adaptor that flattens an iterator of iterators by - /// merging them according to the given closure. - /// - /// The closure `first` is called with two elements *a*, *b* and should - /// return `true` if *a* is ordered before *b*. - /// - /// If all base iterators are sorted according to `first`, the result is - /// sorted. - /// - /// Iterator element type is `Self::Item`. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let a = vec![-1f64, 2., 3., -5., 6., -7.]; - /// let b = vec![0., 2., -4.]; - /// let mut it = vec![a, b].into_iter().kmerge_by(|a, b| a.abs() < b.abs()); - /// assert_eq!(it.next(), Some(0.)); - /// assert_eq!(it.last(), Some(-7.)); - /// ``` - #[cfg(feature = "use_std")] - fn kmerge_by<F>(self, first: F) - -> KMergeBy<<Self::Item as IntoIterator>::IntoIter, F> - where Self: Sized, - Self::Item: IntoIterator, - F: FnMut(&<Self::Item as IntoIterator>::Item, - &<Self::Item as IntoIterator>::Item) -> bool - { - kmerge_by(self, first) - } - - /// Return an iterator adaptor that iterates over the cartesian product of - /// the element sets of two iterators `self` and `J`. - /// - /// Iterator element type is `(Self::Item, J::Item)`. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let it = (0..2).cartesian_product("αβ".chars()); - /// itertools::assert_equal(it, vec![(0, 'α'), (0, 'β'), (1, 'α'), (1, 'β')]); - /// ``` - fn cartesian_product<J>(self, other: J) -> Product<Self, J::IntoIter> - where Self: Sized, - Self::Item: Clone, - J: IntoIterator, - J::IntoIter: Clone - { - adaptors::cartesian_product(self, other.into_iter()) - } - - /// Return an iterator adaptor that iterates over the cartesian product of - /// all subiterators returned by meta-iterator `self`. - /// - /// All provided iterators must yield the same `Item` type. To generate - /// the product of iterators yielding multiple types, use the - /// [`iproduct`](macro.iproduct.html) macro instead. - /// - /// - /// The iterator element type is `Vec<T>`, where `T` is the iterator element - /// of the subiterators. - /// - /// ``` - /// use itertools::Itertools; - /// let mut multi_prod = (0..3).map(|i| (i * 2)..(i * 2 + 2)) - /// .multi_cartesian_product(); - /// assert_eq!(multi_prod.next(), Some(vec![0, 2, 4])); - /// assert_eq!(multi_prod.next(), Some(vec![0, 2, 5])); - /// assert_eq!(multi_prod.next(), Some(vec![0, 3, 4])); - /// assert_eq!(multi_prod.next(), Some(vec![0, 3, 5])); - /// assert_eq!(multi_prod.next(), Some(vec![1, 2, 4])); - /// assert_eq!(multi_prod.next(), Some(vec![1, 2, 5])); - /// assert_eq!(multi_prod.next(), Some(vec![1, 3, 4])); - /// assert_eq!(multi_prod.next(), Some(vec![1, 3, 5])); - /// assert_eq!(multi_prod.next(), None); - /// ``` - #[cfg(feature = "use_std")] - fn multi_cartesian_product(self) -> MultiProduct<<Self::Item as IntoIterator>::IntoIter> - where Self: Iterator + Sized, - Self::Item: IntoIterator, - <Self::Item as IntoIterator>::IntoIter: Clone, - <Self::Item as IntoIterator>::Item: Clone - { - adaptors::multi_cartesian_product(self) - } - - /// Return an iterator adaptor that uses the passed-in closure to - /// optionally merge together consecutive elements. - /// - /// The closure `f` is passed two elements, `previous` and `current` and may - /// return either (1) `Ok(combined)` to merge the two values or - /// (2) `Err((previous', current'))` to indicate they can't be merged. - /// In (2), the value `previous'` is emitted by the iterator. - /// Either (1) `combined` or (2) `current'` becomes the previous value - /// when coalesce continues with the next pair of elements to merge. The - /// value that remains at the end is also emitted by the iterator. - /// - /// Iterator element type is `Self::Item`. - /// - /// This iterator is *fused*. - /// - /// ``` - /// use itertools::Itertools; - /// - /// // sum same-sign runs together - /// let data = vec![-1., -2., -3., 3., 1., 0., -1.]; - /// itertools::assert_equal(data.into_iter().coalesce(|x, y| - /// if (x >= 0.) == (y >= 0.) { - /// Ok(x + y) - /// } else { - /// Err((x, y)) - /// }), - /// vec![-6., 4., -1.]); - /// ``` - fn coalesce<F>(self, f: F) -> Coalesce<Self, F> - where Self: Sized, - F: FnMut(Self::Item, Self::Item) - -> Result<Self::Item, (Self::Item, Self::Item)> - { - adaptors::coalesce(self, f) - } - - /// Remove duplicates from sections of consecutive identical elements. - /// If the iterator is sorted, all elements will be unique. - /// - /// Iterator element type is `Self::Item`. - /// - /// This iterator is *fused*. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let data = vec![1., 1., 2., 3., 3., 2., 2.]; - /// itertools::assert_equal(data.into_iter().dedup(), - /// vec![1., 2., 3., 2.]); - /// ``` - fn dedup(self) -> Dedup<Self> - where Self: Sized, - Self::Item: PartialEq, - { - adaptors::dedup(self) - } - - /// Remove duplicates from sections of consecutive identical elements, - /// determining equality using a comparison function. - /// If the iterator is sorted, all elements will be unique. - /// - /// Iterator element type is `Self::Item`. - /// - /// This iterator is *fused*. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let data = vec![(0, 1.), (1, 1.), (0, 2.), (0, 3.), (1, 3.), (1, 2.), (2, 2.)]; - /// itertools::assert_equal(data.into_iter().dedup_by(|x, y| x.1==y.1), - /// vec![(0, 1.), (0, 2.), (0, 3.), (1, 2.)]); - /// ``` - fn dedup_by<Cmp>(self, cmp: Cmp) -> DedupBy<Self, Cmp> - where Self: Sized, - Cmp: FnMut(&Self::Item, &Self::Item)->bool, - { - adaptors::dedup_by(self, cmp) - } - - /// Return an iterator adaptor that filters out elements that have - /// already been produced once during the iteration. Duplicates - /// are detected using hash and equality. - /// - /// Clones of visited elements are stored in a hash set in the - /// iterator. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let data = vec![10, 20, 30, 20, 40, 10, 50]; - /// itertools::assert_equal(data.into_iter().unique(), - /// vec![10, 20, 30, 40, 50]); - /// ``` - #[cfg(feature = "use_std")] - fn unique(self) -> Unique<Self> - where Self: Sized, - Self::Item: Clone + Eq + Hash - { - unique_impl::unique(self) - } - - /// Return an iterator adaptor that filters out elements that have - /// already been produced once during the iteration. - /// - /// Duplicates are detected by comparing the key they map to - /// with the keying function `f` by hash and equality. - /// The keys are stored in a hash set in the iterator. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let data = vec!["a", "bb", "aa", "c", "ccc"]; - /// itertools::assert_equal(data.into_iter().unique_by(|s| s.len()), - /// vec!["a", "bb", "ccc"]); - /// ``` - #[cfg(feature = "use_std")] - fn unique_by<V, F>(self, f: F) -> UniqueBy<Self, V, F> - where Self: Sized, - V: Eq + Hash, - F: FnMut(&Self::Item) -> V - { - unique_impl::unique_by(self, f) - } - - /// Return an iterator adaptor that borrows from this iterator and - /// takes items while the closure `accept` returns `true`. - /// - /// This adaptor can only be used on iterators that implement `PeekingNext` - /// like `.peekable()`, `put_back` and a few other collection iterators. - /// - /// The last and rejected element (first `false`) is still available when - /// `peeking_take_while` is done. - /// - /// - /// See also [`.take_while_ref()`](#method.take_while_ref) - /// which is a similar adaptor. - fn peeking_take_while<F>(&mut self, accept: F) -> PeekingTakeWhile<Self, F> - where Self: Sized + PeekingNext, - F: FnMut(&Self::Item) -> bool, - { - peeking_take_while::peeking_take_while(self, accept) - } - - /// Return an iterator adaptor that borrows from a `Clone`-able iterator - /// to only pick off elements while the predicate `accept` returns `true`. - /// - /// It uses the `Clone` trait to restore the original iterator so that the - /// last and rejected element (first `false`) is still available when - /// `take_while_ref` is done. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let mut hexadecimals = "0123456789abcdef".chars(); - /// - /// let decimals = hexadecimals.take_while_ref(|c| c.is_numeric()) - /// .collect::<String>(); - /// assert_eq!(decimals, "0123456789"); - /// assert_eq!(hexadecimals.next(), Some('a')); - /// - /// ``` - fn take_while_ref<F>(&mut self, accept: F) -> TakeWhileRef<Self, F> - where Self: Clone, - F: FnMut(&Self::Item) -> bool - { - adaptors::take_while_ref(self, accept) - } - - /// Return an iterator adaptor that filters `Option<A>` iterator elements - /// and produces `A`. Stops on the first `None` encountered. - /// - /// Iterator element type is `A`, the unwrapped element. - /// - /// ``` - /// use itertools::Itertools; - /// - /// // List all hexadecimal digits - /// itertools::assert_equal( - /// (0..).map(|i| std::char::from_digit(i, 16)).while_some(), - /// "0123456789abcdef".chars()); - /// - /// ``` - fn while_some<A>(self) -> WhileSome<Self> - where Self: Sized + Iterator<Item = Option<A>> - { - adaptors::while_some(self) - } - - /// Return an iterator adaptor that iterates over the combinations of the - /// elements from an iterator. - /// - /// Iterator element can be any homogeneous tuple of type `Self::Item` with - /// size up to 4. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let mut v = Vec::new(); - /// for (a, b) in (1..5).tuple_combinations() { - /// v.push((a, b)); - /// } - /// assert_eq!(v, vec![(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]); - /// - /// let mut it = (1..5).tuple_combinations(); - /// assert_eq!(Some((1, 2, 3)), it.next()); - /// assert_eq!(Some((1, 2, 4)), it.next()); - /// assert_eq!(Some((1, 3, 4)), it.next()); - /// assert_eq!(Some((2, 3, 4)), it.next()); - /// assert_eq!(None, it.next()); - /// - /// // this requires a type hint - /// let it = (1..5).tuple_combinations::<(_, _, _)>(); - /// itertools::assert_equal(it, vec![(1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]); - /// - /// // you can also specify the complete type - /// use itertools::TupleCombinations; - /// use std::ops::Range; - /// - /// let it: TupleCombinations<Range<u32>, (u32, u32, u32)> = (1..5).tuple_combinations(); - /// itertools::assert_equal(it, vec![(1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]); - /// ``` - fn tuple_combinations<T>(self) -> TupleCombinations<Self, T> - where Self: Sized + Clone, - Self::Item: Clone, - T: adaptors::HasCombination<Self>, - { - adaptors::tuple_combinations(self) - } - - /// Return an iterator adaptor that iterates over the `k`-length combinations of - /// the elements from an iterator. - /// - /// Iterator element type is `Vec<Self::Item>`. The iterator produces a new Vec per iteration, - /// and clones the iterator elements. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let it = (1..5).combinations(3); - /// itertools::assert_equal(it, vec![ - /// vec![1, 2, 3], - /// vec![1, 2, 4], - /// vec![1, 3, 4], - /// vec![2, 3, 4], - /// ]); - /// ``` - /// - /// Note: Combinations does not take into account the equality of the iterated values. - /// ``` - /// use itertools::Itertools; - /// - /// let it = vec![1, 2, 2].into_iter().combinations(2); - /// itertools::assert_equal(it, vec![ - /// vec![1, 2], // Note: these are the same - /// vec![1, 2], // Note: these are the same - /// vec![2, 2], - /// ]); - /// ``` - #[cfg(feature = "use_std")] - fn combinations(self, k: usize) -> Combinations<Self> - where Self: Sized, - Self::Item: Clone - { - combinations::combinations(self, k) - } - - /// Return an iterator that iterates over the `k`-length combinations of - /// the elements from an iterator, with replacement. - /// - /// Iterator element type is `Vec<Self::Item>`. The iterator produces a new Vec per iteration, - /// and clones the iterator elements. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let it = (1..4).combinations_with_replacement(2); - /// itertools::assert_equal(it, vec![ - /// vec![1, 1], - /// vec![1, 2], - /// vec![1, 3], - /// vec![2, 2], - /// vec![2, 3], - /// vec![3, 3], - /// ]); - /// ``` - #[cfg(feature = "use_std")] - fn combinations_with_replacement(self, k: usize) -> CombinationsWithReplacement<Self> - where - Self: Sized, - Self::Item: Clone, - { - combinations_with_replacement::combinations_with_replacement(self, k) - } - - /// Return an iterator adaptor that iterates over all k-permutations of the - /// elements from an iterator. - /// - /// Iterator element type is `Vec<Self::Item>` with length `k`. The iterator - /// produces a new Vec per iteration, and clones the iterator elements. - /// - /// If `k` is greater than the length of the input iterator, the resultant - /// iterator adaptor will be empty. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let perms = (5..8).permutations(2); - /// itertools::assert_equal(perms, vec![ - /// vec![5, 6], - /// vec![5, 7], - /// vec![6, 5], - /// vec![6, 7], - /// vec![7, 5], - /// vec![7, 6], - /// ]); - /// ``` - /// - /// Note: Permutations does not take into account the equality of the iterated values. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let it = vec![2, 2].into_iter().permutations(2); - /// itertools::assert_equal(it, vec![ - /// vec![2, 2], // Note: these are the same - /// vec![2, 2], // Note: these are the same - /// ]); - /// ``` - /// - /// Note: The source iterator is collected lazily, and will not be - /// re-iterated if the permutations adaptor is completed and re-iterated. - #[cfg(feature = "use_std")] - fn permutations(self, k: usize) -> Permutations<Self> - where Self: Sized, - Self::Item: Clone - { - permutations::permutations(self, k) - } - - /// Return an iterator adaptor that pads the sequence to a minimum length of - /// `min` by filling missing elements using a closure `f`. - /// - /// Iterator element type is `Self::Item`. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let it = (0..5).pad_using(10, |i| 2*i); - /// itertools::assert_equal(it, vec![0, 1, 2, 3, 4, 10, 12, 14, 16, 18]); - /// - /// let it = (0..10).pad_using(5, |i| 2*i); - /// itertools::assert_equal(it, vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); - /// - /// let it = (0..5).pad_using(10, |i| 2*i).rev(); - /// itertools::assert_equal(it, vec![18, 16, 14, 12, 10, 4, 3, 2, 1, 0]); - /// ``` - fn pad_using<F>(self, min: usize, f: F) -> PadUsing<Self, F> - where Self: Sized, - F: FnMut(usize) -> Self::Item - { - pad_tail::pad_using(self, min, f) - } - - /// Return an iterator adaptor that wraps each element in a `Position` to - /// ease special-case handling of the first or last elements. - /// - /// Iterator element type is - /// [`Position<Self::Item>`](enum.Position.html) - /// - /// ``` - /// use itertools::{Itertools, Position}; - /// - /// let it = (0..4).with_position(); - /// itertools::assert_equal(it, - /// vec![Position::First(0), - /// Position::Middle(1), - /// Position::Middle(2), - /// Position::Last(3)]); - /// - /// let it = (0..1).with_position(); - /// itertools::assert_equal(it, vec![Position::Only(0)]); - /// ``` - fn with_position(self) -> WithPosition<Self> - where Self: Sized, - { - with_position::with_position(self) - } - - /// Return an iterator adaptor that yields the indices of all elements - /// satisfying a predicate, counted from the start of the iterator. - /// - /// Equivalent to `iter.enumerate().filter(|(_, v)| predicate(v)).map(|(i, _)| i)`. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let data = vec![1, 2, 3, 3, 4, 6, 7, 9]; - /// itertools::assert_equal(data.iter().positions(|v| v % 2 == 0), vec![1, 4, 5]); - /// - /// itertools::assert_equal(data.iter().positions(|v| v % 2 == 1).rev(), vec![7, 6, 3, 2, 0]); - /// ``` - fn positions<P>(self, predicate: P) -> Positions<Self, P> - where Self: Sized, - P: FnMut(Self::Item) -> bool, - { - adaptors::positions(self, predicate) - } - - /// Return an iterator adaptor that applies a mutating function - /// to each element before yielding it. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let input = vec![vec![1], vec![3, 2, 1]]; - /// let it = input.into_iter().update(|mut v| v.push(0)); - /// itertools::assert_equal(it, vec![vec![1, 0], vec![3, 2, 1, 0]]); - /// ``` - fn update<F>(self, updater: F) -> Update<Self, F> - where Self: Sized, - F: FnMut(&mut Self::Item), - { - adaptors::update(self, updater) - } - - // non-adaptor methods - /// Advances the iterator and returns the next items grouped in a tuple of - /// a specific size (up to 4). - /// - /// If there are enough elements to be grouped in a tuple, then the tuple is - /// returned inside `Some`, otherwise `None` is returned. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let mut iter = 1..5; - /// - /// assert_eq!(Some((1, 2)), iter.next_tuple()); - /// ``` - fn next_tuple<T>(&mut self) -> Option<T> - where Self: Sized + Iterator<Item = T::Item>, - T: tuple_impl::TupleCollect - { - T::collect_from_iter_no_buf(self) - } - - /// Collects all items from the iterator into a tuple of a specific size - /// (up to 4). - /// - /// If the number of elements inside the iterator is **exactly** equal to - /// the tuple size, then the tuple is returned inside `Some`, otherwise - /// `None` is returned. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let iter = 1..3; - /// - /// if let Some((x, y)) = iter.collect_tuple() { - /// assert_eq!((x, y), (1, 2)) - /// } else { - /// panic!("Expected two elements") - /// } - /// ``` - fn collect_tuple<T>(mut self) -> Option<T> - where Self: Sized + Iterator<Item = T::Item>, - T: tuple_impl::TupleCollect - { - match self.next_tuple() { - elt @ Some(_) => match self.next() { - Some(_) => None, - None => elt, - }, - _ => None - } - } - - - /// Find the position and value of the first element satisfying a predicate. - /// - /// The iterator is not advanced past the first element found. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let text = "Hα"; - /// assert_eq!(text.chars().find_position(|ch| ch.is_lowercase()), Some((1, 'α'))); - /// ``` - fn find_position<P>(&mut self, mut pred: P) -> Option<(usize, Self::Item)> - where P: FnMut(&Self::Item) -> bool - { - let mut index = 0usize; - for elt in self { - if pred(&elt) { - return Some((index, elt)); - } - index += 1; - } - None - } - - /// Check whether all elements compare equal. - /// - /// Empty iterators are considered to have equal elements: - /// - /// ``` - /// use itertools::Itertools; - /// - /// let data = vec![1, 1, 1, 2, 2, 3, 3, 3, 4, 5, 5]; - /// assert!(!data.iter().all_equal()); - /// assert!(data[0..3].iter().all_equal()); - /// assert!(data[3..5].iter().all_equal()); - /// assert!(data[5..8].iter().all_equal()); - /// - /// let data : Option<usize> = None; - /// assert!(data.into_iter().all_equal()); - /// ``` - fn all_equal(&mut self) -> bool - where Self: Sized, - Self::Item: PartialEq, - { - match self.next() { - None => true, - Some(a) => self.all(|x| a == x), - } - } - - /// Consume the first `n` elements from the iterator eagerly, - /// and return the same iterator again. - /// - /// It works similarly to *.skip(* `n` *)* except it is eager and - /// preserves the iterator type. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let mut iter = "αβγ".chars().dropping(2); - /// itertools::assert_equal(iter, "γ".chars()); - /// ``` - /// - /// *Fusing notes: if the iterator is exhausted by dropping, - /// the result of calling `.next()` again depends on the iterator implementation.* - fn dropping(mut self, n: usize) -> Self - where Self: Sized - { - if n > 0 { - self.nth(n - 1); - } - self - } - - /// Consume the last `n` elements from the iterator eagerly, - /// and return the same iterator again. - /// - /// This is only possible on double ended iterators. `n` may be - /// larger than the number of elements. - /// - /// Note: This method is eager, dropping the back elements immediately and - /// preserves the iterator type. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let init = vec![0, 3, 6, 9].into_iter().dropping_back(1); - /// itertools::assert_equal(init, vec![0, 3, 6]); - /// ``` - fn dropping_back(mut self, n: usize) -> Self - where Self: Sized, - Self: DoubleEndedIterator - { - if n > 0 { - (&mut self).rev().nth(n - 1); - } - self - } - - /// Run the closure `f` eagerly on each element of the iterator. - /// - /// Consumes the iterator until its end. - /// - /// ``` - /// use std::sync::mpsc::channel; - /// use itertools::Itertools; - /// - /// let (tx, rx) = channel(); - /// - /// // use .foreach() to apply a function to each value -- sending it - /// (0..5).map(|x| x * 2 + 1).foreach(|x| { tx.send(x).unwrap(); } ); - /// - /// drop(tx); - /// - /// itertools::assert_equal(rx.iter(), vec![1, 3, 5, 7, 9]); - /// ``` - #[deprecated(note="Use .for_each() instead", since="0.8")] - fn foreach<F>(self, f: F) - where F: FnMut(Self::Item), - Self: Sized, - { - self.for_each(f) - } - - /// Combine all an iterator's elements into one element by using `Extend`. - /// - /// This combinator will extend the first item with each of the rest of the - /// items of the iterator. If the iterator is empty, the default value of - /// `I::Item` is returned. - /// - /// ```rust - /// use itertools::Itertools; - /// - /// let input = vec![vec![1], vec![2, 3], vec![4, 5, 6]]; - /// assert_eq!(input.into_iter().concat(), - /// vec![1, 2, 3, 4, 5, 6]); - /// ``` - fn concat(self) -> Self::Item - where Self: Sized, - Self::Item: Extend<<<Self as Iterator>::Item as IntoIterator>::Item> + IntoIterator + Default - { - concat(self) - } - - /// `.collect_vec()` is simply a type specialization of `.collect()`, - /// for convenience. - #[cfg(feature = "use_std")] - fn collect_vec(self) -> Vec<Self::Item> - where Self: Sized - { - self.collect() - } - - /// Assign to each reference in `self` from the `from` iterator, - /// stopping at the shortest of the two iterators. - /// - /// The `from` iterator is queried for its next element before the `self` - /// iterator, and if either is exhausted the method is done. - /// - /// Return the number of elements written. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let mut xs = [0; 4]; - /// xs.iter_mut().set_from(1..); - /// assert_eq!(xs, [1, 2, 3, 4]); - /// ``` - #[inline] - fn set_from<'a, A: 'a, J>(&mut self, from: J) -> usize - where Self: Iterator<Item = &'a mut A>, - J: IntoIterator<Item = A> - { - let mut count = 0; - for elt in from { - match self.next() { - None => break, - Some(ptr) => *ptr = elt, - } - count += 1; - } - count - } - - /// Combine all iterator elements into one String, separated by `sep`. - /// - /// Use the `Display` implementation of each element. - /// - /// ``` - /// use itertools::Itertools; - /// - /// assert_eq!(["a", "b", "c"].iter().join(", "), "a, b, c"); - /// assert_eq!([1, 2, 3].iter().join(", "), "1, 2, 3"); - /// ``` - #[cfg(feature = "use_std")] - fn join(&mut self, sep: &str) -> String - where Self::Item: std::fmt::Display - { - match self.next() { - None => String::new(), - Some(first_elt) => { - // estimate lower bound of capacity needed - let (lower, _) = self.size_hint(); - let mut result = String::with_capacity(sep.len() * lower); - write!(&mut result, "{}", first_elt).unwrap(); - for elt in self { - result.push_str(sep); - write!(&mut result, "{}", elt).unwrap(); - } - result - } - } - } - - /// Format all iterator elements, separated by `sep`. - /// - /// All elements are formatted (any formatting trait) - /// with `sep` inserted between each element. - /// - /// **Panics** if the formatter helper is formatted more than once. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let data = [1.1, 2.71828, -3.]; - /// assert_eq!( - /// format!("{:.2}", data.iter().format(", ")), - /// "1.10, 2.72, -3.00"); - /// ``` - fn format(self, sep: &str) -> Format<Self> - where Self: Sized, - { - format::new_format_default(self, sep) - } - - /// Format all iterator elements, separated by `sep`. - /// - /// This is a customizable version of `.format()`. - /// - /// The supplied closure `format` is called once per iterator element, - /// with two arguments: the element and a callback that takes a - /// `&Display` value, i.e. any reference to type that implements `Display`. - /// - /// Using `&format_args!(...)` is the most versatile way to apply custom - /// element formatting. The callback can be called multiple times if needed. - /// - /// **Panics** if the formatter helper is formatted more than once. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let data = [1.1, 2.71828, -3.]; - /// let data_formatter = data.iter().format_with(", ", |elt, f| f(&format_args!("{:.2}", elt))); - /// assert_eq!(format!("{}", data_formatter), - /// "1.10, 2.72, -3.00"); - /// - /// // .format_with() is recursively composable - /// let matrix = [[1., 2., 3.], - /// [4., 5., 6.]]; - /// let matrix_formatter = matrix.iter().format_with("\n", |row, f| { - /// f(&row.iter().format_with(", ", |elt, g| g(&elt))) - /// }); - /// assert_eq!(format!("{}", matrix_formatter), - /// "1, 2, 3\n4, 5, 6"); - /// - /// - /// ``` - fn format_with<F>(self, sep: &str, format: F) -> FormatWith<Self, F> - where Self: Sized, - F: FnMut(Self::Item, &mut FnMut(&fmt::Display) -> fmt::Result) -> fmt::Result, - { - format::new_format(self, sep, format) - } - - /// Fold `Result` values from an iterator. - /// - /// Only `Ok` values are folded. If no error is encountered, the folded - /// value is returned inside `Ok`. Otherwise, the operation terminates - /// and returns the first `Err` value it encounters. No iterator elements are - /// consumed after the first error. - /// - /// The first accumulator value is the `start` parameter. - /// Each iteration passes the accumulator value and the next value inside `Ok` - /// to the fold function `f` and its return value becomes the new accumulator value. - /// - /// For example the sequence *Ok(1), Ok(2), Ok(3)* will result in a - /// computation like this: - /// - /// ```ignore - /// let mut accum = start; - /// accum = f(accum, 1); - /// accum = f(accum, 2); - /// accum = f(accum, 3); - /// ``` - /// - /// With a `start` value of 0 and an addition as folding function, - /// this effectively results in *((0 + 1) + 2) + 3* - /// - /// ``` - /// use std::ops::Add; - /// use itertools::Itertools; - /// - /// let values = [1, 2, -2, -1, 2, 1]; - /// assert_eq!( - /// values.iter() - /// .map(Ok::<_, ()>) - /// .fold_results(0, Add::add), - /// Ok(3) - /// ); - /// assert!( - /// values.iter() - /// .map(|&x| if x >= 0 { Ok(x) } else { Err("Negative number") }) - /// .fold_results(0, Add::add) - /// .is_err() - /// ); - /// ``` - fn fold_results<A, E, B, F>(&mut self, mut start: B, mut f: F) -> Result<B, E> - where Self: Iterator<Item = Result<A, E>>, - F: FnMut(B, A) -> B - { - for elt in self { - match elt { - Ok(v) => start = f(start, v), - Err(u) => return Err(u), - } - } - Ok(start) - } - - /// Fold `Option` values from an iterator. - /// - /// Only `Some` values are folded. If no `None` is encountered, the folded - /// value is returned inside `Some`. Otherwise, the operation terminates - /// and returns `None`. No iterator elements are consumed after the `None`. - /// - /// This is the `Option` equivalent to `fold_results`. - /// - /// ``` - /// use std::ops::Add; - /// use itertools::Itertools; - /// - /// let mut values = vec![Some(1), Some(2), Some(-2)].into_iter(); - /// assert_eq!(values.fold_options(5, Add::add), Some(5 + 1 + 2 - 2)); - /// - /// let mut more_values = vec![Some(2), None, Some(0)].into_iter(); - /// assert!(more_values.fold_options(0, Add::add).is_none()); - /// assert_eq!(more_values.next().unwrap(), Some(0)); - /// ``` - fn fold_options<A, B, F>(&mut self, mut start: B, mut f: F) -> Option<B> - where Self: Iterator<Item = Option<A>>, - F: FnMut(B, A) -> B - { - for elt in self { - match elt { - Some(v) => start = f(start, v), - None => return None, - } - } - Some(start) - } - - /// Accumulator of the elements in the iterator. - /// - /// Like `.fold()`, without a base case. If the iterator is - /// empty, return `None`. With just one element, return it. - /// Otherwise elements are accumulated in sequence using the closure `f`. - /// - /// ``` - /// use itertools::Itertools; - /// - /// assert_eq!((0..10).fold1(|x, y| x + y).unwrap_or(0), 45); - /// assert_eq!((0..0).fold1(|x, y| x * y), None); - /// ``` - fn fold1<F>(mut self, f: F) -> Option<Self::Item> - where F: FnMut(Self::Item, Self::Item) -> Self::Item, - Self: Sized, - { - self.next().map(move |x| self.fold(x, f)) - } - - /// Accumulate the elements in the iterator in a tree-like manner. - /// - /// You can think of it as, while there's more than one item, repeatedly - /// combining adjacent items. It does so in bottom-up-merge-sort order, - /// however, so that it needs only logarithmic stack space. - /// - /// This produces a call tree like the following (where the calls under - /// an item are done after reading that item): - /// - /// ```text - /// 1 2 3 4 5 6 7 - /// │ │ │ │ │ │ │ - /// └─f └─f └─f │ - /// │ │ │ │ - /// └───f └─f - /// │ │ - /// └─────f - /// ``` - /// - /// Which, for non-associative functions, will typically produce a different - /// result than the linear call tree used by `fold1`: - /// - /// ```text - /// 1 2 3 4 5 6 7 - /// │ │ │ │ │ │ │ - /// └─f─f─f─f─f─f - /// ``` - /// - /// If `f` is associative, prefer the normal `fold1` instead. - /// - /// ``` - /// use itertools::Itertools; - /// - /// // The same tree as above - /// let num_strings = (1..8).map(|x| x.to_string()); - /// assert_eq!(num_strings.tree_fold1(|x, y| format!("f({}, {})", x, y)), - /// Some(String::from("f(f(f(1, 2), f(3, 4)), f(f(5, 6), 7))"))); - /// - /// // Like fold1, an empty iterator produces None - /// assert_eq!((0..0).tree_fold1(|x, y| x * y), None); - /// - /// // tree_fold1 matches fold1 for associative operations... - /// assert_eq!((0..10).tree_fold1(|x, y| x + y), - /// (0..10).fold1(|x, y| x + y)); - /// // ...but not for non-associative ones - /// assert_ne!((0..10).tree_fold1(|x, y| x - y), - /// (0..10).fold1(|x, y| x - y)); - /// ``` - fn tree_fold1<F>(mut self, mut f: F) -> Option<Self::Item> - where F: FnMut(Self::Item, Self::Item) -> Self::Item, - Self: Sized, - { - type State<T> = Result<T, Option<T>>; - - fn inner0<T, II, FF>(it: &mut II, f: &mut FF) -> State<T> - where - II: Iterator<Item = T>, - FF: FnMut(T, T) -> T - { - // This function could be replaced with `it.next().ok_or(None)`, - // but half the useful tree_fold1 work is combining adjacent items, - // so put that in a form that LLVM is more likely to optimize well. - - let a = - if let Some(v) = it.next() { v } - else { return Err(None) }; - let b = - if let Some(v) = it.next() { v } - else { return Err(Some(a)) }; - Ok(f(a, b)) - } - - fn inner<T, II, FF>(stop: usize, it: &mut II, f: &mut FF) -> State<T> - where - II: Iterator<Item = T>, - FF: FnMut(T, T) -> T - { - let mut x = try!(inner0(it, f)); - for height in 0..stop { - // Try to get another tree the same size with which to combine it, - // creating a new tree that's twice as big for next time around. - let next = - if height == 0 { - inner0(it, f) - } else { - inner(height, it, f) - }; - match next { - Ok(y) => x = f(x, y), - - // If we ran out of items, combine whatever we did manage - // to get. It's better combined with the current value - // than something in a parent frame, because the tree in - // the parent is always as least as big as this one. - Err(None) => return Err(Some(x)), - Err(Some(y)) => return Err(Some(f(x, y))), - } - } - Ok(x) - } - - match inner(usize::max_value(), &mut self, &mut f) { - Err(x) => x, - _ => unreachable!(), - } - } - - /// An iterator method that applies a function, producing a single, final value. - /// - /// `fold_while()` is basically equivalent to `fold()` but with additional support for - /// early exit via short-circuiting. - /// - /// ``` - /// use itertools::Itertools; - /// use itertools::FoldWhile::{Continue, Done}; - /// - /// let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - /// - /// let mut result = 0; - /// - /// // for loop: - /// for i in &numbers { - /// if *i > 5 { - /// break; - /// } - /// result = result + i; - /// } - /// - /// // fold: - /// let result2 = numbers.iter().fold(0, |acc, x| { - /// if *x > 5 { acc } else { acc + x } - /// }); - /// - /// // fold_while: - /// let result3 = numbers.iter().fold_while(0, |acc, x| { - /// if *x > 5 { Done(acc) } else { Continue(acc + x) } - /// }).into_inner(); - /// - /// // they're the same - /// assert_eq!(result, result2); - /// assert_eq!(result2, result3); - /// ``` - /// - /// The big difference between the computations of `result2` and `result3` is that while - /// `fold()` called the provided closure for every item of the callee iterator, - /// `fold_while()` actually stopped iterating as soon as it encountered `Fold::Done(_)`. - #[deprecated(note="Use .try_fold() instead", since="0.8")] - fn fold_while<B, F>(&mut self, init: B, mut f: F) -> FoldWhile<B> - where Self: Sized, - F: FnMut(B, Self::Item) -> FoldWhile<B> - { - let mut acc = init; - while let Some(item) = self.next() { - match f(acc, item) { - FoldWhile::Continue(res) => acc = res, - res @ FoldWhile::Done(_) => return res, - } - } - FoldWhile::Continue(acc) - } - - /// Iterate over the entire iterator and add all the elements. - /// - /// An empty iterator returns `None`, otherwise `Some(sum)`. - /// - /// # Panics - /// - /// When calling `sum1()` and a primitive integer type is being returned, this - /// method will panic if the computation overflows and debug assertions are - /// enabled. - /// - /// # Examples - /// - /// ``` - /// use itertools::Itertools; - /// - /// let empty_sum = (1..1).sum1::<i32>(); - /// assert_eq!(empty_sum, None); - /// - /// let nonempty_sum = (1..11).sum1::<i32>(); - /// assert_eq!(nonempty_sum, Some(55)); - /// ``` - fn sum1<S>(mut self) -> Option<S> - where Self: Sized, - S: std::iter::Sum<Self::Item>, - { - self.next() - .map(|first| once(first).chain(self).sum()) - } - - /// Iterate over the entire iterator and multiply all the elements. - /// - /// An empty iterator returns `None`, otherwise `Some(product)`. - /// - /// # Panics - /// - /// When calling `product1()` and a primitive integer type is being returned, - /// method will panic if the computation overflows and debug assertions are - /// enabled. - /// - /// # Examples - /// ``` - /// use itertools::Itertools; - /// - /// let empty_product = (1..1).product1::<i32>(); - /// assert_eq!(empty_product, None); - /// - /// let nonempty_product = (1..11).product1::<i32>(); - /// assert_eq!(nonempty_product, Some(3628800)); - /// ``` - fn product1<P>(mut self) -> Option<P> - where Self: Sized, - P: std::iter::Product<Self::Item>, - { - self.next() - .map(|first| once(first).chain(self).product()) - } - - - /// Sort all iterator elements into a new iterator in ascending order. - /// - /// **Note:** This consumes the entire iterator, uses the - /// `slice::sort()` method and returns the result as a new - /// iterator that owns its elements. - /// - /// The sorted iterator, if directly collected to a `Vec`, is converted - /// without any extra copying or allocation cost. - /// - /// ``` - /// use itertools::Itertools; - /// - /// // sort the letters of the text in ascending order - /// let text = "bdacfe"; - /// itertools::assert_equal(text.chars().sorted(), - /// "abcdef".chars()); - /// ``` - #[cfg(feature = "use_std")] - fn sorted(self) -> VecIntoIter<Self::Item> - where Self: Sized, - Self::Item: Ord - { - // Use .sort() directly since it is not quite identical with - // .sort_by(Ord::cmp) - let mut v = Vec::from_iter(self); - v.sort(); - v.into_iter() - } - - /// Sort all iterator elements into a new iterator in ascending order. - /// - /// **Note:** This consumes the entire iterator, uses the - /// `slice::sort_by()` method and returns the result as a new - /// iterator that owns its elements. - /// - /// The sorted iterator, if directly collected to a `Vec`, is converted - /// without any extra copying or allocation cost. - /// - /// ``` - /// use itertools::Itertools; - /// - /// // sort people in descending order by age - /// let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 27)]; - /// - /// let oldest_people_first = people - /// .into_iter() - /// .sorted_by(|a, b| Ord::cmp(&b.1, &a.1)) - /// .map(|(person, _age)| person); - /// - /// itertools::assert_equal(oldest_people_first, - /// vec!["Jill", "Jack", "Jane", "John"]); - /// ``` - #[cfg(feature = "use_std")] - fn sorted_by<F>(self, cmp: F) -> VecIntoIter<Self::Item> - where Self: Sized, - F: FnMut(&Self::Item, &Self::Item) -> Ordering, - { - let mut v = Vec::from_iter(self); - v.sort_by(cmp); - v.into_iter() - } - - /// Sort all iterator elements into a new iterator in ascending order. - /// - /// **Note:** This consumes the entire iterator, uses the - /// `slice::sort_by_key()` method and returns the result as a new - /// iterator that owns its elements. - /// - /// The sorted iterator, if directly collected to a `Vec`, is converted - /// without any extra copying or allocation cost. - /// - /// ``` - /// use itertools::Itertools; - /// - /// // sort people in descending order by age - /// let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 27)]; - /// - /// let oldest_people_first = people - /// .into_iter() - /// .sorted_by_key(|x| -x.1) - /// .map(|(person, _age)| person); - /// - /// itertools::assert_equal(oldest_people_first, - /// vec!["Jill", "Jack", "Jane", "John"]); - /// ``` - #[cfg(feature = "use_std")] - fn sorted_by_key<K, F>(self, f: F) -> VecIntoIter<Self::Item> - where Self: Sized, - K: Ord, - F: FnMut(&Self::Item) -> K, - { - let mut v = Vec::from_iter(self); - v.sort_by_key(f); - v.into_iter() - } - - /// Collect all iterator elements into one of two - /// partitions. Unlike `Iterator::partition`, each partition may - /// have a distinct type. - /// - /// ``` - /// use itertools::{Itertools, Either}; - /// - /// let successes_and_failures = vec![Ok(1), Err(false), Err(true), Ok(2)]; - /// - /// let (successes, failures): (Vec<_>, Vec<_>) = successes_and_failures - /// .into_iter() - /// .partition_map(|r| { - /// match r { - /// Ok(v) => Either::Left(v), - /// Err(v) => Either::Right(v), - /// } - /// }); - /// - /// assert_eq!(successes, [1, 2]); - /// assert_eq!(failures, [false, true]); - /// ``` - fn partition_map<A, B, F, L, R>(self, mut predicate: F) -> (A, B) - where Self: Sized, - F: FnMut(Self::Item) -> Either<L, R>, - A: Default + Extend<L>, - B: Default + Extend<R>, - { - let mut left = A::default(); - let mut right = B::default(); - - self.for_each(|val| match predicate(val) { - Either::Left(v) => left.extend(Some(v)), - Either::Right(v) => right.extend(Some(v)), - }); - - (left, right) - } - - /// Return a `HashMap` of keys mapped to `Vec`s of values. Keys and values - /// are taken from `(Key, Value)` tuple pairs yielded by the input iterator. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let data = vec![(0, 10), (2, 12), (3, 13), (0, 20), (3, 33), (2, 42)]; - /// let lookup = data.into_iter().into_group_map(); - /// - /// assert_eq!(lookup[&0], vec![10, 20]); - /// assert_eq!(lookup.get(&1), None); - /// assert_eq!(lookup[&2], vec![12, 42]); - /// assert_eq!(lookup[&3], vec![13, 33]); - /// ``` - #[cfg(feature = "use_std")] - fn into_group_map<K, V>(self) -> HashMap<K, Vec<V>> - where Self: Iterator<Item=(K, V)> + Sized, - K: Hash + Eq, - { - group_map::into_group_map(self) - } - - /// Return the minimum and maximum elements in the iterator. - /// - /// The return type `MinMaxResult` is an enum of three variants: - /// - /// - `NoElements` if the iterator is empty. - /// - `OneElement(x)` if the iterator has exactly one element. - /// - `MinMax(x, y)` is returned otherwise, where `x <= y`. Two - /// values are equal if and only if there is more than one - /// element in the iterator and all elements are equal. - /// - /// On an iterator of length `n`, `minmax` does `1.5 * n` comparisons, - /// and so is faster than calling `min` and `max` separately which does - /// `2 * n` comparisons. - /// - /// # Examples - /// - /// ``` - /// use itertools::Itertools; - /// use itertools::MinMaxResult::{NoElements, OneElement, MinMax}; - /// - /// let a: [i32; 0] = []; - /// assert_eq!(a.iter().minmax(), NoElements); - /// - /// let a = [1]; - /// assert_eq!(a.iter().minmax(), OneElement(&1)); - /// - /// let a = [1, 2, 3, 4, 5]; - /// assert_eq!(a.iter().minmax(), MinMax(&1, &5)); - /// - /// let a = [1, 1, 1, 1]; - /// assert_eq!(a.iter().minmax(), MinMax(&1, &1)); - /// ``` - /// - /// The elements can be floats but no particular result is guaranteed - /// if an element is NaN. - fn minmax(self) -> MinMaxResult<Self::Item> - where Self: Sized, Self::Item: PartialOrd - { - minmax::minmax_impl(self, |_| (), |x, y, _, _| x < y) - } - - /// Return the minimum and maximum element of an iterator, as determined by - /// the specified function. - /// - /// The return value is a variant of `MinMaxResult` like for `minmax()`. - /// - /// For the minimum, the first minimal element is returned. For the maximum, - /// the last maximal element wins. This matches the behavior of the standard - /// `Iterator::min()` and `Iterator::max()` methods. - /// - /// The keys can be floats but no particular result is guaranteed - /// if a key is NaN. - fn minmax_by_key<K, F>(self, key: F) -> MinMaxResult<Self::Item> - where Self: Sized, K: PartialOrd, F: FnMut(&Self::Item) -> K - { - minmax::minmax_impl(self, key, |_, _, xk, yk| xk < yk) - } - - /// Return the minimum and maximum element of an iterator, as determined by - /// the specified comparison function. - /// - /// The return value is a variant of `MinMaxResult` like for `minmax()`. - /// - /// For the minimum, the first minimal element is returned. For the maximum, - /// the last maximal element wins. This matches the behavior of the standard - /// `Iterator::min()` and `Iterator::max()` methods. - fn minmax_by<F>(self, mut compare: F) -> MinMaxResult<Self::Item> - where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering - { - minmax::minmax_impl( - self, - |_| (), - |x, y, _, _| Ordering::Less == compare(x, y) - ) - } - - /// If the iterator yields exactly one element, that element will be returned, otherwise - /// an error will be returned containing an iterator that has the same output as the input - /// iterator. - /// - /// This provides an additional layer of validation over just calling `Iterator::next()`. - /// If your assumption that there should only be one element yielded is false this provides - /// the opportunity to detect and handle that, preventing errors at a distance. - /// - /// # Examples - /// ``` - /// use itertools::Itertools; - /// - /// assert_eq!((0..10).filter(|&x| x == 2).exactly_one().unwrap(), 2); - /// assert!((0..10).filter(|&x| x > 1 && x < 4).exactly_one().unwrap_err().eq(2..4)); - /// assert!((0..10).filter(|&x| x > 1 && x < 5).exactly_one().unwrap_err().eq(2..5)); - /// assert!((0..10).filter(|&_| false).exactly_one().unwrap_err().eq(0..0)); - /// ``` - fn exactly_one(mut self) -> Result<Self::Item, ExactlyOneError<Self>> - where - Self: Sized, - { - match self.next() { - Some(first) => { - match self.next() { - Some(second) => { - Err(ExactlyOneError::new((Some(first), Some(second)), self)) - } - None => { - Ok(first) - } - } - } - None => Err(ExactlyOneError::new((None, None), self)), - } - } -} - -impl<T: ?Sized> Itertools for T where T: Iterator { } - -/// Return `true` if both iterables produce equal sequences -/// (elements pairwise equal and sequences of the same length), -/// `false` otherwise. -/// -/// This is an `IntoIterator` enabled function that is similar to the standard -/// library method `Iterator::eq`. -/// -/// ``` -/// assert!(itertools::equal(vec![1, 2, 3], 1..4)); -/// assert!(!itertools::equal(&[0, 0], &[0, 0, 0])); -/// ``` -pub fn equal<I, J>(a: I, b: J) -> bool - where I: IntoIterator, - J: IntoIterator, - I::Item: PartialEq<J::Item> -{ - let mut ia = a.into_iter(); - let mut ib = b.into_iter(); - loop { - match ia.next() { - Some(x) => match ib.next() { - Some(y) => if x != y { return false; }, - None => return false, - }, - None => return ib.next().is_none() - } - } -} - -/// Assert that two iterables produce equal sequences, with the same -/// semantics as *equal(a, b)*. -/// -/// **Panics** on assertion failure with a message that shows the -/// two iteration elements. -/// -/// ```ignore -/// assert_equal("exceed".split('c'), "excess".split('c')); -/// // ^PANIC: panicked at 'Failed assertion Some("eed") == Some("ess") for iteration 1', -/// ``` -pub fn assert_equal<I, J>(a: I, b: J) - where I: IntoIterator, - J: IntoIterator, - I::Item: fmt::Debug + PartialEq<J::Item>, - J::Item: fmt::Debug, -{ - let mut ia = a.into_iter(); - let mut ib = b.into_iter(); - let mut i = 0; - loop { - match (ia.next(), ib.next()) { - (None, None) => return, - (a, b) => { - let equal = match (&a, &b) { - (&Some(ref a), &Some(ref b)) => a == b, - _ => false, - }; - assert!(equal, "Failed assertion {a:?} == {b:?} for iteration {i}", - i=i, a=a, b=b); - i += 1; - } - } - } -} - -/// Partition a sequence using predicate `pred` so that elements -/// that map to `true` are placed before elements which map to `false`. -/// -/// The order within the partitions is arbitrary. -/// -/// Return the index of the split point. -/// -/// ``` -/// use itertools::partition; -/// -/// # // use repeated numbers to not promise any ordering -/// let mut data = [7, 1, 1, 7, 1, 1, 7]; -/// let split_index = partition(&mut data, |elt| *elt >= 3); -/// -/// assert_eq!(data, [7, 7, 7, 1, 1, 1, 1]); -/// assert_eq!(split_index, 3); -/// ``` -pub fn partition<'a, A: 'a, I, F>(iter: I, mut pred: F) -> usize - where I: IntoIterator<Item = &'a mut A>, - I::IntoIter: DoubleEndedIterator, - F: FnMut(&A) -> bool -{ - let mut split_index = 0; - let mut iter = iter.into_iter(); - 'main: while let Some(front) = iter.next() { - if !pred(front) { - loop { - match iter.next_back() { - Some(back) => if pred(back) { - std::mem::swap(front, back); - break; - }, - None => break 'main, - } - } - } - split_index += 1; - } - split_index -} - -/// An enum used for controlling the execution of `.fold_while()`. -/// -/// See [`.fold_while()`](trait.Itertools.html#method.fold_while) for more information. -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub enum FoldWhile<T> { - /// Continue folding with this value - Continue(T), - /// Fold is complete and will return this value - Done(T), -} - -impl<T> FoldWhile<T> { - /// Return the value in the continue or done. - pub fn into_inner(self) -> T { - match self { - FoldWhile::Continue(x) | FoldWhile::Done(x) => x, - } - } - - /// Return true if `self` is `Done`, false if it is `Continue`. - pub fn is_done(&self) -> bool { - match *self { - FoldWhile::Continue(_) => false, - FoldWhile::Done(_) => true, - } - } -} diff --git a/vendor/itertools-0.8.2/src/merge_join.rs b/vendor/itertools-0.8.2/src/merge_join.rs deleted file mode 100644 index 5f9a0f4013..0000000000 --- a/vendor/itertools-0.8.2/src/merge_join.rs +++ /dev/null @@ -1,87 +0,0 @@ -use std::cmp::Ordering; -use std::iter::Fuse; -use std::fmt; - -use super::adaptors::{PutBack, put_back}; -use either_or_both::EitherOrBoth; - -/// Return an iterator adaptor that merge-joins items from the two base iterators in ascending order. -/// -/// See [`.merge_join_by()`](trait.Itertools.html#method.merge_join_by) for more information. -pub fn merge_join_by<I, J, F>(left: I, right: J, cmp_fn: F) - -> MergeJoinBy<I::IntoIter, J::IntoIter, F> - where I: IntoIterator, - J: IntoIterator, - F: FnMut(&I::Item, &J::Item) -> Ordering -{ - MergeJoinBy { - left: put_back(left.into_iter().fuse()), - right: put_back(right.into_iter().fuse()), - cmp_fn: cmp_fn - } -} - -/// An iterator adaptor that merge-joins items from the two base iterators in ascending order. -/// -/// See [`.merge_join_by()`](../trait.Itertools.html#method.merge_join_by) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct MergeJoinBy<I: Iterator, J: Iterator, F> { - left: PutBack<Fuse<I>>, - right: PutBack<Fuse<J>>, - cmp_fn: F -} - -impl<I, J, F> fmt::Debug for MergeJoinBy<I, J, F> - where I: Iterator + fmt::Debug, - I::Item: fmt::Debug, - J: Iterator + fmt::Debug, - J::Item: fmt::Debug, -{ - debug_fmt_fields!(MergeJoinBy, left, right); -} - -impl<I, J, F> Iterator for MergeJoinBy<I, J, F> - where I: Iterator, - J: Iterator, - F: FnMut(&I::Item, &J::Item) -> Ordering -{ - type Item = EitherOrBoth<I::Item, J::Item>; - - fn next(&mut self) -> Option<Self::Item> { - match (self.left.next(), self.right.next()) { - (None, None) => None, - (Some(left), None) => - Some(EitherOrBoth::Left(left)), - (None, Some(right)) => - Some(EitherOrBoth::Right(right)), - (Some(left), Some(right)) => { - match (self.cmp_fn)(&left, &right) { - Ordering::Equal => - Some(EitherOrBoth::Both(left, right)), - Ordering::Less => { - self.right.put_back(right); - Some(EitherOrBoth::Left(left)) - }, - Ordering::Greater => { - self.left.put_back(left); - Some(EitherOrBoth::Right(right)) - } - } - } - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - let (a_lower, a_upper) = self.left.size_hint(); - let (b_lower, b_upper) = self.right.size_hint(); - - let lower = ::std::cmp::max(a_lower, b_lower); - - let upper = match (a_upper, b_upper) { - (Some(x), Some(y)) => Some(x + y), - _ => None, - }; - - (lower, upper) - } -} diff --git a/vendor/itertools-0.8.2/src/minmax.rs b/vendor/itertools-0.8.2/src/minmax.rs deleted file mode 100644 index 38180ef6d0..0000000000 --- a/vendor/itertools-0.8.2/src/minmax.rs +++ /dev/null @@ -1,114 +0,0 @@ - -/// `MinMaxResult` is an enum returned by `minmax`. See `Itertools::minmax()` for -/// more detail. -#[derive(Copy, Clone, PartialEq, Debug)] -pub enum MinMaxResult<T> { - /// Empty iterator - NoElements, - - /// Iterator with one element, so the minimum and maximum are the same - OneElement(T), - - /// More than one element in the iterator, the first element is not larger - /// than the second - MinMax(T, T) -} - -impl<T: Clone> MinMaxResult<T> { - /// `into_option` creates an `Option` of type `(T, T)`. The returned `Option` - /// has variant `None` if and only if the `MinMaxResult` has variant - /// `NoElements`. Otherwise `Some((x, y))` is returned where `x <= y`. - /// If the `MinMaxResult` has variant `OneElement(x)`, performing this - /// operation will make one clone of `x`. - /// - /// # Examples - /// - /// ``` - /// use itertools::MinMaxResult::{self, NoElements, OneElement, MinMax}; - /// - /// let r: MinMaxResult<i32> = NoElements; - /// assert_eq!(r.into_option(), None); - /// - /// let r = OneElement(1); - /// assert_eq!(r.into_option(), Some((1, 1))); - /// - /// let r = MinMax(1, 2); - /// assert_eq!(r.into_option(), Some((1, 2))); - /// ``` - pub fn into_option(self) -> Option<(T,T)> { - match self { - MinMaxResult::NoElements => None, - MinMaxResult::OneElement(x) => Some((x.clone(), x)), - MinMaxResult::MinMax(x, y) => Some((x, y)) - } - } -} - -/// Implementation guts for `minmax` and `minmax_by_key`. -pub fn minmax_impl<I, K, F, L>(mut it: I, mut key_for: F, - mut lt: L) -> MinMaxResult<I::Item> - where I: Iterator, - F: FnMut(&I::Item) -> K, - L: FnMut(&I::Item, &I::Item, &K, &K) -> bool, -{ - let (mut min, mut max, mut min_key, mut max_key) = match it.next() { - None => return MinMaxResult::NoElements, - Some(x) => { - match it.next() { - None => return MinMaxResult::OneElement(x), - Some(y) => { - let xk = key_for(&x); - let yk = key_for(&y); - if !lt(&y, &x, &yk, &xk) {(x, y, xk, yk)} else {(y, x, yk, xk)} - } - } - } - }; - - loop { - // `first` and `second` are the two next elements we want to look - // at. We first compare `first` and `second` (#1). The smaller one - // is then compared to current minimum (#2). The larger one is - // compared to current maximum (#3). This way we do 3 comparisons - // for 2 elements. - let first = match it.next() { - None => break, - Some(x) => x - }; - let second = match it.next() { - None => { - let first_key = key_for(&first); - if lt(&first, &min, &first_key, &min_key) { - min = first; - } else if !lt(&first, &max, &first_key, &max_key) { - max = first; - } - break; - } - Some(x) => x - }; - let first_key = key_for(&first); - let second_key = key_for(&second); - if !lt(&second, &first, &second_key, &first_key) { - if lt(&first, &min, &first_key, &min_key) { - min = first; - min_key = first_key; - } - if !lt(&second, &max, &second_key, &max_key) { - max = second; - max_key = second_key; - } - } else { - if lt(&second, &min, &second_key, &min_key) { - min = second; - min_key = second_key; - } - if !lt(&first, &max, &first_key, &max_key) { - max = first; - max_key = first_key; - } - } - } - - MinMaxResult::MinMax(min, max) -} diff --git a/vendor/itertools-0.8.2/src/multipeek_impl.rs b/vendor/itertools-0.8.2/src/multipeek_impl.rs deleted file mode 100644 index a6a2fb33eb..0000000000 --- a/vendor/itertools-0.8.2/src/multipeek_impl.rs +++ /dev/null @@ -1,104 +0,0 @@ - - -use std::iter::Fuse; -use std::collections::VecDeque; -use size_hint; -use PeekingNext; - -/// See [`multipeek()`](../fn.multipeek.html) for more information. -#[derive(Clone, Debug)] -pub struct MultiPeek<I> - where I: Iterator -{ - iter: Fuse<I>, - buf: VecDeque<I::Item>, - index: usize, -} - -/// An iterator adaptor that allows the user to peek at multiple `.next()` -/// values without advancing the base iterator. -pub fn multipeek<I>(iterable: I) -> MultiPeek<I::IntoIter> - where I: IntoIterator -{ - MultiPeek { - iter: iterable.into_iter().fuse(), - buf: VecDeque::new(), - index: 0, - } -} - -impl<I> MultiPeek<I> - where I: Iterator -{ - /// Reset the peeking “cursor” - pub fn reset_peek(&mut self) { - self.index = 0; - } -} - -impl<I: Iterator> MultiPeek<I> { - /// Works exactly like `.next()` with the only difference that it doesn't - /// advance itself. `.peek()` can be called multiple times, to peek - /// further ahead. - pub fn peek(&mut self) -> Option<&I::Item> { - let ret = if self.index < self.buf.len() { - Some(&self.buf[self.index]) - } else { - match self.iter.next() { - Some(x) => { - self.buf.push_back(x); - Some(&self.buf[self.index]) - } - None => return None, - } - }; - - self.index += 1; - ret - } -} - -impl<I> PeekingNext for MultiPeek<I> - where I: Iterator, -{ - fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> - where F: FnOnce(&Self::Item) -> bool - { - if self.buf.is_empty() { - if let Some(r) = self.peek() { - if !accept(r) { return None } - } - } else { - if let Some(r) = self.buf.get(0) { - if !accept(r) { return None } - } - } - self.next() - } -} - -impl<I> Iterator for MultiPeek<I> - where I: Iterator -{ - type Item = I::Item; - - fn next(&mut self) -> Option<I::Item> { - self.index = 0; - if self.buf.is_empty() { - self.iter.next() - } else { - self.buf.pop_front() - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - size_hint::add_scalar(self.iter.size_hint(), self.buf.len()) - } -} - -// Same size -impl<I> ExactSizeIterator for MultiPeek<I> - where I: ExactSizeIterator -{} - - diff --git a/vendor/itertools-0.8.2/src/pad_tail.rs b/vendor/itertools-0.8.2/src/pad_tail.rs deleted file mode 100644 index c9cfe6af30..0000000000 --- a/vendor/itertools-0.8.2/src/pad_tail.rs +++ /dev/null @@ -1,83 +0,0 @@ -use std::iter::Fuse; -use size_hint; - -/// An iterator adaptor that pads a sequence to a minimum length by filling -/// missing elements using a closure. -/// -/// Iterator element type is `I::Item`. -/// -/// See [`.pad_using()`](../trait.Itertools.html#method.pad_using) for more information. -#[derive(Clone)] -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct PadUsing<I, F> { - iter: Fuse<I>, - min: usize, - pos: usize, - filler: F, -} - -/// Create a new **PadUsing** iterator. -pub fn pad_using<I, F>(iter: I, min: usize, filler: F) -> PadUsing<I, F> - where I: Iterator, - F: FnMut(usize) -> I::Item -{ - PadUsing { - iter: iter.fuse(), - min: min, - pos: 0, - filler: filler, - } -} - -impl<I, F> Iterator for PadUsing<I, F> - where I: Iterator, - F: FnMut(usize) -> I::Item -{ - type Item = I::Item; - - #[inline] - fn next(&mut self) -> Option<I::Item> { - match self.iter.next() { - None => { - if self.pos < self.min { - let e = Some((self.filler)(self.pos)); - self.pos += 1; - e - } else { - None - } - }, - e => { - self.pos += 1; - e - } - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - let tail = self.min.saturating_sub(self.pos); - size_hint::max(self.iter.size_hint(), (tail, Some(tail))) - } -} - -impl<I, F> DoubleEndedIterator for PadUsing<I, F> - where I: DoubleEndedIterator + ExactSizeIterator, - F: FnMut(usize) -> I::Item -{ - fn next_back(&mut self) -> Option<I::Item> { - if self.min == 0 { - self.iter.next_back() - } else if self.iter.len() >= self.min { - self.min -= 1; - self.iter.next_back() - } else { - self.min -= 1; - Some((self.filler)(self.min)) - } - } -} - -impl<I, F> ExactSizeIterator for PadUsing<I, F> - where I: ExactSizeIterator, - F: FnMut(usize) -> I::Item -{} diff --git a/vendor/itertools-0.8.2/src/peeking_take_while.rs b/vendor/itertools-0.8.2/src/peeking_take_while.rs deleted file mode 100644 index 0b2291dfdd..0000000000 --- a/vendor/itertools-0.8.2/src/peeking_take_while.rs +++ /dev/null @@ -1,149 +0,0 @@ - -use std::iter::Peekable; -use PutBack; -#[cfg(feature = "use_std")] -use PutBackN; - -/// An iterator that allows peeking at an element before deciding to accept it. -/// -/// See [`.peeking_take_while()`](trait.Itertools.html#method.peeking_take_while) -/// for more information. -/// -/// This is implemented by peeking adaptors like peekable and put back, -/// but also by a few iterators that can be peeked natively, like the slice’s -/// by reference iterator (`std::slice::Iter`). -pub trait PeekingNext : Iterator { - /// Pass a reference to the next iterator element to the closure `accept`; - /// if `accept` returns true, return it as the next element, - /// else None. - fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> - where F: FnOnce(&Self::Item) -> bool; -} - -impl<I> PeekingNext for Peekable<I> - where I: Iterator, -{ - fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> - where F: FnOnce(&Self::Item) -> bool - { - if let Some(r) = self.peek() { - if !accept(r) { - return None; - } - } - self.next() - } -} - -impl<I> PeekingNext for PutBack<I> - where I: Iterator, -{ - fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> - where F: FnOnce(&Self::Item) -> bool - { - if let Some(r) = self.next() { - if !accept(&r) { - self.put_back(r); - return None; - } - Some(r) - } else { - None - } - } -} - -#[cfg(feature = "use_std")] -impl<I> PeekingNext for PutBackN<I> - where I: Iterator, -{ - fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> - where F: FnOnce(&Self::Item) -> bool - { - if let Some(r) = self.next() { - if !accept(&r) { - self.put_back(r); - return None; - } - Some(r) - } else { - None - } - } -} - -/// An iterator adaptor that takes items while a closure returns `true`. -/// -/// See [`.peeking_take_while()`](../trait.Itertools.html#method.peeking_take_while) -/// for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct PeekingTakeWhile<'a, I: 'a, F> - where I: Iterator, -{ - iter: &'a mut I, - f: F, -} - -/// Create a PeekingTakeWhile -pub fn peeking_take_while<I, F>(iter: &mut I, f: F) -> PeekingTakeWhile<I, F> - where I: Iterator, -{ - PeekingTakeWhile { - iter: iter, - f: f, - } -} - -impl<'a, I, F> Iterator for PeekingTakeWhile<'a, I, F> - where I: PeekingNext, - F: FnMut(&I::Item) -> bool, - -{ - type Item = I::Item; - fn next(&mut self) -> Option<Self::Item> { - self.iter.peeking_next(&mut self.f) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - let (_, hi) = self.iter.size_hint(); - (0, hi) - } -} - -// Some iterators are so lightweight we can simply clone them to save their -// state and use that for peeking. -macro_rules! peeking_next_by_clone { - ([$($typarm:tt)*] $type_:ty) => { - impl<$($typarm)*> PeekingNext for $type_ { - fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> - where F: FnOnce(&Self::Item) -> bool - { - let saved_state = self.clone(); - if let Some(r) = self.next() { - if !accept(&r) { - *self = saved_state; - } else { - return Some(r) - } - } - None - } - } - } -} - -peeking_next_by_clone! { ['a, T] ::std::slice::Iter<'a, T> } -peeking_next_by_clone! { ['a] ::std::str::Chars<'a> } -peeking_next_by_clone! { ['a] ::std::str::CharIndices<'a> } -peeking_next_by_clone! { ['a] ::std::str::Bytes<'a> } -peeking_next_by_clone! { ['a, T] ::std::option::Iter<'a, T> } -peeking_next_by_clone! { ['a, T] ::std::result::Iter<'a, T> } -peeking_next_by_clone! { [T] ::std::iter::Empty<T> } -#[cfg(feature = "use_std")] -peeking_next_by_clone! { ['a, T] ::std::collections::linked_list::Iter<'a, T> } -#[cfg(feature = "use_std")] -peeking_next_by_clone! { ['a, T] ::std::collections::vec_deque::Iter<'a, T> } - -// cloning a Rev has no extra overhead; peekable and put backs are never DEI. -peeking_next_by_clone! { [I: Clone + PeekingNext + DoubleEndedIterator] - ::std::iter::Rev<I> } diff --git a/vendor/itertools-0.8.2/src/permutations.rs b/vendor/itertools-0.8.2/src/permutations.rs deleted file mode 100644 index a9423375fd..0000000000 --- a/vendor/itertools-0.8.2/src/permutations.rs +++ /dev/null @@ -1,272 +0,0 @@ -use std::fmt; -use std::iter::once; - -use super::lazy_buffer::LazyBuffer; - -/// An iterator adaptor that iterates through all the `k`-permutations of the -/// elements from an iterator. -/// -/// See [`.permutations()`](../trait.Itertools.html#method.permutations) for -/// more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Permutations<I: Iterator> { - vals: LazyBuffer<I>, - state: PermutationState, -} - -#[derive(Debug)] -enum PermutationState { - StartUnknownLen { - k: usize, - }, - OngoingUnknownLen { - k: usize, - min_n: usize, - }, - Complete(CompleteState), - Empty, -} - -#[derive(Debug)] -enum CompleteState { - Start { - n: usize, - k: usize, - }, - Ongoing { - indices: Vec<usize>, - cycles: Vec<usize>, - } -} - -enum CompleteStateRemaining { - Known(usize), - Overflow, -} - -impl<I> fmt::Debug for Permutations<I> - where I: Iterator + fmt::Debug, - I::Item: fmt::Debug, -{ - debug_fmt_fields!(Permutations, vals, state); -} - -pub fn permutations<I: Iterator>(iter: I, k: usize) -> Permutations<I> { - let mut vals = LazyBuffer::new(iter); - - if k == 0 { - // Special case, yields single empty vec; `n` is irrelevant - let state = PermutationState::Complete(CompleteState::Start { n: 0, k: 0 }); - - return Permutations { - vals, - state - }; - } - - let mut enough_vals = true; - - while vals.len() < k { - if !vals.get_next() { - enough_vals = false; - break; - } - } - - let state = if enough_vals { - PermutationState::StartUnknownLen { k } - } else { - PermutationState::Empty - }; - - Permutations { - vals, - state - } -} - -impl<I> Iterator for Permutations<I> -where - I: Iterator, - I::Item: Clone -{ - type Item = Vec<I::Item>; - - fn next(&mut self) -> Option<Self::Item> { - self.advance(); - - let &mut Permutations { ref vals, ref state } = self; - - match state { - &PermutationState::StartUnknownLen { .. } => panic!("unexpected iterator state"), - &PermutationState::OngoingUnknownLen { k, min_n } => { - let latest_idx = min_n - 1; - let indices = (0..(k - 1)).chain(once(latest_idx)); - - Some(indices.map(|i| vals[i].clone()).collect()) - } - &PermutationState::Complete(CompleteState::Start { .. }) => None, - &PermutationState::Complete(CompleteState::Ongoing { ref indices, ref cycles }) => { - let k = cycles.len(); - - Some(indices[0..k].iter().map(|&i| vals[i].clone()).collect()) - }, - &PermutationState::Empty => None - } - } - - fn count(self) -> usize { - let Permutations { vals, state } = self; - - fn from_complete(complete_state: CompleteState) -> usize { - match complete_state.remaining() { - CompleteStateRemaining::Known(count) => count, - CompleteStateRemaining::Overflow => { - panic!("Iterator count greater than usize::MAX"); - } - } - } - - match state { - PermutationState::StartUnknownLen { k } => { - let n = vals.len() + vals.it.count(); - let complete_state = CompleteState::Start { n, k }; - - from_complete(complete_state) - } - PermutationState::OngoingUnknownLen { k, min_n } => { - let prev_iteration_count = min_n - k + 1; - let n = vals.len() + vals.it.count(); - let complete_state = CompleteState::Start { n, k }; - - from_complete(complete_state) - prev_iteration_count - }, - PermutationState::Complete(state) => from_complete(state), - PermutationState::Empty => 0 - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - match self.state { - PermutationState::StartUnknownLen { .. } | - PermutationState::OngoingUnknownLen { .. } => (0, None), // TODO can we improve this lower bound? - PermutationState::Complete(ref state) => match state.remaining() { - CompleteStateRemaining::Known(count) => (count, Some(count)), - CompleteStateRemaining::Overflow => (::std::usize::MAX, None) - } - PermutationState::Empty => (0, Some(0)) - } - } -} - -impl<I> Permutations<I> -where - I: Iterator, - I::Item: Clone -{ - fn advance(&mut self) { - let &mut Permutations { ref mut vals, ref mut state } = self; - - *state = match state { - &mut PermutationState::StartUnknownLen { k } => { - PermutationState::OngoingUnknownLen { k, min_n: k } - } - &mut PermutationState::OngoingUnknownLen { k, min_n } => { - if vals.get_next() { - PermutationState::OngoingUnknownLen { k, min_n: min_n + 1 } - } else { - let n = min_n; - let prev_iteration_count = n - k + 1; - let mut complete_state = CompleteState::Start { n, k }; - - // Advance the complete-state iterator to the correct point - for _ in 0..(prev_iteration_count + 1) { - complete_state.advance(); - } - - PermutationState::Complete(complete_state) - } - } - &mut PermutationState::Complete(ref mut state) => { - state.advance(); - - return; - } - &mut PermutationState::Empty => { return; } - }; - } -} - -impl CompleteState { - fn advance(&mut self) { - *self = match self { - &mut CompleteState::Start { n, k } => { - let indices = (0..n).collect(); - let cycles = ((n - k)..n).rev().collect(); - - CompleteState::Ongoing { - cycles, - indices - } - }, - &mut CompleteState::Ongoing { ref mut indices, ref mut cycles } => { - let n = indices.len(); - let k = cycles.len(); - - for i in (0..k).rev() { - if cycles[i] == 0 { - cycles[i] = n - i - 1; - - let to_push = indices.remove(i); - indices.push(to_push); - } else { - let swap_index = n - cycles[i]; - indices.swap(i, swap_index); - - cycles[i] -= 1; - return; - } - } - - CompleteState::Start { n, k } - } - } - } - - fn remaining(&self) -> CompleteStateRemaining { - use self::CompleteStateRemaining::{Known, Overflow}; - - match self { - &CompleteState::Start { n, k } => { - if n < k { - return Known(0); - } - - let count: Option<usize> = (n - k + 1..n + 1).fold(Some(1), |acc, i| { - acc.and_then(|acc| acc.checked_mul(i)) - }); - - match count { - Some(count) => Known(count), - None => Overflow - } - } - &CompleteState::Ongoing { ref indices, ref cycles } => { - let mut count: usize = 0; - - for (i, &c) in cycles.iter().enumerate() { - let radix = indices.len() - i; - let next_count = count.checked_mul(radix) - .and_then(|count| count.checked_add(c)); - - count = match next_count { - Some(count) => count, - None => { return Overflow; } - }; - } - - Known(count) - } - } - } -} \ No newline at end of file diff --git a/vendor/itertools-0.8.2/src/process_results_impl.rs b/vendor/itertools-0.8.2/src/process_results_impl.rs deleted file mode 100644 index f78515d77f..0000000000 --- a/vendor/itertools-0.8.2/src/process_results_impl.rs +++ /dev/null @@ -1,81 +0,0 @@ - -/// An iterator that produces only the `T` values as long as the -/// inner iterator produces `Ok(T)`. -/// -/// Used by [`process_results`](../fn.process_results.html), see its docs -/// for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -#[derive(Debug)] -pub struct ProcessResults<'a, I, E: 'a> { - error: &'a mut Result<(), E>, - iter: I, -} - -impl<'a, I, T, E> Iterator for ProcessResults<'a, I, E> - where I: Iterator<Item = Result<T, E>> -{ - type Item = T; - - fn next(&mut self) -> Option<Self::Item> { - match self.iter.next() { - Some(Ok(x)) => Some(x), - Some(Err(e)) => { - *self.error = Err(e); - None - } - None => None, - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - let (_, hi) = self.iter.size_hint(); - (0, hi) - } -} - -/// “Lift” a function of the values of an iterator so that it can process -/// an iterator of `Result` values instead. -/// -/// `iterable` is an iterator or iterable with `Result<T, E>` elements, where -/// `T` is the value type and `E` the error type. -/// -/// `processor` is a closure that receives an adapted version of the iterable -/// as the only argument — the adapted iterator produces elements of type `T`, -/// as long as the original iterator produces `Ok` values. -/// -/// If the original iterable produces an error at any point, the adapted -/// iterator ends and the `process_results` function will return the -/// error iself. -/// -/// Otherwise, the return value from the closure is returned wrapped -/// inside `Ok`. -/// -/// # Example -/// -/// ``` -/// use itertools::process_results; -/// -/// type R = Result<i32, &'static str>; -/// -/// let first_values: Vec<R> = vec![Ok(1), Ok(0), Ok(3)]; -/// let second_values: Vec<R> = vec![Ok(2), Ok(1), Err("overflow")]; -/// -/// // “Lift” the iterator .max() method to work on the values in Results using process_results -/// -/// let first_max = process_results(first_values, |iter| iter.max().unwrap_or(0)); -/// let second_max = process_results(second_values, |iter| iter.max().unwrap_or(0)); -/// -/// assert_eq!(first_max, Ok(3)); -/// assert!(second_max.is_err()); -/// ``` -pub fn process_results<I, F, T, E, R>(iterable: I, processor: F) -> Result<R, E> - where I: IntoIterator<Item = Result<T, E>>, - F: FnOnce(ProcessResults<I::IntoIter, E>) -> R -{ - let iter = iterable.into_iter(); - let mut error = Ok(()); - - let result = processor(ProcessResults { error: &mut error, iter: iter }); - - error.map(|_| result) -} diff --git a/vendor/itertools-0.8.2/src/put_back_n_impl.rs b/vendor/itertools-0.8.2/src/put_back_n_impl.rs deleted file mode 100644 index cc08320714..0000000000 --- a/vendor/itertools-0.8.2/src/put_back_n_impl.rs +++ /dev/null @@ -1,63 +0,0 @@ -use size_hint; - -/// An iterator adaptor that allows putting multiple -/// items in front of the iterator. -/// -/// Iterator element type is `I::Item`. -#[derive(Debug, Clone)] -pub struct PutBackN<I: Iterator> { - top: Vec<I::Item>, - iter: I, -} - -/// Create an iterator where you can put back multiple values to the front -/// of the iteration. -/// -/// Iterator element type is `I::Item`. -pub fn put_back_n<I>(iterable: I) -> PutBackN<I::IntoIter> - where I: IntoIterator -{ - PutBackN { - top: Vec::new(), - iter: iterable.into_iter(), - } -} - -impl<I: Iterator> PutBackN<I> { - /// Puts x in front of the iterator. - /// The values are yielded in order of the most recently put back - /// values first. - /// - /// ```rust - /// use itertools::put_back_n; - /// - /// let mut it = put_back_n(1..5); - /// it.next(); - /// it.put_back(1); - /// it.put_back(0); - /// - /// assert!(itertools::equal(it, 0..5)); - /// ``` - #[inline] - pub fn put_back(&mut self, x: I::Item) { - self.top.push(x); - } -} - -impl<I: Iterator> Iterator for PutBackN<I> { - type Item = I::Item; - #[inline] - fn next(&mut self) -> Option<I::Item> { - if self.top.is_empty() { - self.iter.next() - } else { - self.top.pop() - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - size_hint::add_scalar(self.iter.size_hint(), self.top.len()) - } -} - diff --git a/vendor/itertools-0.8.2/src/rciter_impl.rs b/vendor/itertools-0.8.2/src/rciter_impl.rs deleted file mode 100644 index 1c3b03b5bc..0000000000 --- a/vendor/itertools-0.8.2/src/rciter_impl.rs +++ /dev/null @@ -1,98 +0,0 @@ - -use std::iter::IntoIterator; -use std::rc::Rc; -use std::cell::RefCell; - -/// A wrapper for `Rc<RefCell<I>>`, that implements the `Iterator` trait. -#[derive(Debug)] -pub struct RcIter<I> { - /// The boxed iterator. - pub rciter: Rc<RefCell<I>>, -} - -/// Return an iterator inside a `Rc<RefCell<_>>` wrapper. -/// -/// The returned `RcIter` can be cloned, and each clone will refer back to the -/// same original iterator. -/// -/// `RcIter` allows doing interesting things like using `.zip()` on an iterator with -/// itself, at the cost of runtime borrow checking which may have a performance -/// penalty. -/// -/// Iterator element type is `Self::Item`. -/// -/// ``` -/// use itertools::rciter; -/// use itertools::zip; -/// -/// // In this example a range iterator is created and we iterate it using -/// // three separate handles (two of them given to zip). -/// // We also use the IntoIterator implementation for `&RcIter`. -/// -/// let mut iter = rciter(0..9); -/// let mut z = zip(&iter, &iter); -/// -/// assert_eq!(z.next(), Some((0, 1))); -/// assert_eq!(z.next(), Some((2, 3))); -/// assert_eq!(z.next(), Some((4, 5))); -/// assert_eq!(iter.next(), Some(6)); -/// assert_eq!(z.next(), Some((7, 8))); -/// assert_eq!(z.next(), None); -/// ``` -/// -/// **Panics** in iterator methods if a borrow error is encountered in the -/// iterator methods. It can only happen if the `RcIter` is reentered in -/// `.next()`, i.e. if it somehow participates in an “iterator knot” -/// where it is an adaptor of itself. -pub fn rciter<I>(iterable: I) -> RcIter<I::IntoIter> - where I: IntoIterator -{ - RcIter { rciter: Rc::new(RefCell::new(iterable.into_iter())) } -} - -impl<I> Clone for RcIter<I> { - #[inline] - fn clone(&self) -> RcIter<I> { - RcIter { rciter: self.rciter.clone() } - } -} - -impl<A, I> Iterator for RcIter<I> - where I: Iterator<Item = A> -{ - type Item = A; - #[inline] - fn next(&mut self) -> Option<A> { - self.rciter.borrow_mut().next() - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - // To work sanely with other API that assume they own an iterator, - // so it can't change in other places, we can't guarantee as much - // in our size_hint. Other clones may drain values under our feet. - let (_, hi) = self.rciter.borrow().size_hint(); - (0, hi) - } -} - -impl<I> DoubleEndedIterator for RcIter<I> - where I: DoubleEndedIterator -{ - #[inline] - fn next_back(&mut self) -> Option<I::Item> { - self.rciter.borrow_mut().next_back() - } -} - -/// Return an iterator from `&RcIter<I>` (by simply cloning it). -impl<'a, I> IntoIterator for &'a RcIter<I> - where I: Iterator -{ - type Item = I::Item; - type IntoIter = RcIter<I>; - - fn into_iter(self) -> RcIter<I> { - self.clone() - } -} diff --git a/vendor/itertools-0.8.2/src/repeatn.rs b/vendor/itertools-0.8.2/src/repeatn.rs deleted file mode 100644 index 1c7c310014..0000000000 --- a/vendor/itertools-0.8.2/src/repeatn.rs +++ /dev/null @@ -1,54 +0,0 @@ - -/// An iterator that produces *n* repetitions of an element. -/// -/// See [`repeat_n()`](../fn.repeat_n.html) for more information. -#[must_use = "iterators are lazy and do nothing unless consumed"] -#[derive(Debug)] -pub struct RepeatN<A> { - elt: Option<A>, - n: usize, -} - -/// Create an iterator that produces `n` repetitions of `element`. -pub fn repeat_n<A>(element: A, n: usize) -> RepeatN<A> - where A: Clone, -{ - if n == 0 { - RepeatN { elt: None, n: n, } - } else { - RepeatN { elt: Some(element), n: n, } - } -} - -impl<A> Iterator for RepeatN<A> - where A: Clone -{ - type Item = A; - - fn next(&mut self) -> Option<Self::Item> { - if self.n > 1 { - self.n -= 1; - self.elt.as_ref().cloned() - } else { - self.n = 0; - self.elt.take() - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - (self.n, Some(self.n)) - } -} - -impl<A> DoubleEndedIterator for RepeatN<A> - where A: Clone -{ - #[inline] - fn next_back(&mut self) -> Option<Self::Item> { - self.next() - } -} - -impl<A> ExactSizeIterator for RepeatN<A> - where A: Clone -{} diff --git a/vendor/itertools-0.8.2/src/size_hint.rs b/vendor/itertools-0.8.2/src/size_hint.rs deleted file mode 100644 index be54443f29..0000000000 --- a/vendor/itertools-0.8.2/src/size_hint.rs +++ /dev/null @@ -1,104 +0,0 @@ -//! Arithmetic on **Iterator** *.size_hint()* values. -//! - -use std::usize; -use std::cmp; - -/// **SizeHint** is the return type of **Iterator::size_hint()**. -pub type SizeHint = (usize, Option<usize>); - -/// Add **SizeHint** correctly. -#[inline] -pub fn add(a: SizeHint, b: SizeHint) -> SizeHint { - let min = a.0.checked_add(b.0).unwrap_or(usize::MAX); - let max = match (a.1, b.1) { - (Some(x), Some(y)) => x.checked_add(y), - _ => None, - }; - - (min, max) -} - -/// Add **x** correctly to a **SizeHint**. -#[inline] -pub fn add_scalar(sh: SizeHint, x: usize) -> SizeHint { - let (mut low, mut hi) = sh; - low = low.saturating_add(x); - hi = hi.and_then(|elt| elt.checked_add(x)); - (low, hi) -} - -/// Sbb **x** correctly to a **SizeHint**. -#[inline] -#[allow(dead_code)] -pub fn sub_scalar(sh: SizeHint, x: usize) -> SizeHint { - let (mut low, mut hi) = sh; - low = low.saturating_sub(x); - hi = hi.map(|elt| elt.saturating_sub(x)); - (low, hi) -} - - -/// Multiply **SizeHint** correctly -/// -/// ```ignore -/// use std::usize; -/// use itertools::size_hint; -/// -/// assert_eq!(size_hint::mul((3, Some(4)), (3, Some(4))), -/// (9, Some(16))); -/// -/// assert_eq!(size_hint::mul((3, Some(4)), (usize::MAX, None)), -/// (usize::MAX, None)); -/// -/// assert_eq!(size_hint::mul((3, None), (0, Some(0))), -/// (0, Some(0))); -/// ``` -#[inline] -pub fn mul(a: SizeHint, b: SizeHint) -> SizeHint { - let low = a.0.checked_mul(b.0).unwrap_or(usize::MAX); - let hi = match (a.1, b.1) { - (Some(x), Some(y)) => x.checked_mul(y), - (Some(0), None) | (None, Some(0)) => Some(0), - _ => None, - }; - (low, hi) -} - -/// Multiply **x** correctly with a **SizeHint**. -#[inline] -pub fn mul_scalar(sh: SizeHint, x: usize) -> SizeHint { - let (mut low, mut hi) = sh; - low = low.saturating_mul(x); - hi = hi.and_then(|elt| elt.checked_mul(x)); - (low, hi) -} - -/// Return the maximum -#[inline] -pub fn max(a: SizeHint, b: SizeHint) -> SizeHint { - let (a_lower, a_upper) = a; - let (b_lower, b_upper) = b; - - let lower = cmp::max(a_lower, b_lower); - - let upper = match (a_upper, b_upper) { - (Some(x), Some(y)) => Some(cmp::max(x, y)), - _ => None, - }; - - (lower, upper) -} - -/// Return the minimum -#[inline] -pub fn min(a: SizeHint, b: SizeHint) -> SizeHint { - let (a_lower, a_upper) = a; - let (b_lower, b_upper) = b; - let lower = cmp::min(a_lower, b_lower); - let upper = match (a_upper, b_upper) { - (Some(u1), Some(u2)) => Some(cmp::min(u1, u2)), - _ => a_upper.or(b_upper), - }; - (lower, upper) -} diff --git a/vendor/itertools-0.8.2/src/sources.rs b/vendor/itertools-0.8.2/src/sources.rs deleted file mode 100644 index a579f3d9c2..0000000000 --- a/vendor/itertools-0.8.2/src/sources.rs +++ /dev/null @@ -1,190 +0,0 @@ -//! Iterators that are sources (produce elements from parameters, -//! not from another iterator). -#![allow(deprecated)] - -use std::fmt; -use std::mem; - -/// See [`repeat_call`](../fn.repeat_call.html) for more information. -#[deprecated(note="Use std repeat_with() instead", since="0.8")] -pub struct RepeatCall<F> { - f: F, -} - -impl<F> fmt::Debug for RepeatCall<F> -{ - debug_fmt_fields!(RepeatCall, ); -} - -/// An iterator source that produces elements indefinitely by calling -/// a given closure. -/// -/// Iterator element type is the return type of the closure. -/// -/// ``` -/// use itertools::repeat_call; -/// use itertools::Itertools; -/// use std::collections::BinaryHeap; -/// -/// let mut heap = BinaryHeap::from(vec![2, 5, 3, 7, 8]); -/// -/// // extract each element in sorted order -/// for element in repeat_call(|| heap.pop()).while_some() { -/// print!("{}", element); -/// } -/// -/// itertools::assert_equal( -/// repeat_call(|| 1).take(5), -/// vec![1, 1, 1, 1, 1] -/// ); -/// ``` -#[deprecated(note="Use std repeat_with() instead", since="0.8")] -pub fn repeat_call<F, A>(function: F) -> RepeatCall<F> - where F: FnMut() -> A -{ - RepeatCall { f: function } -} - -impl<A, F> Iterator for RepeatCall<F> - where F: FnMut() -> A -{ - type Item = A; - - #[inline] - fn next(&mut self) -> Option<A> { - Some((self.f)()) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - (usize::max_value(), None) - } -} - -/// Creates a new unfold source with the specified closure as the "iterator -/// function" and an initial state to eventually pass to the closure -/// -/// `unfold` is a general iterator builder: it has a mutable state value, -/// and a closure with access to the state that produces the next value. -/// -/// This more or less equivalent to a regular struct with an `Iterator` -/// implementation, and is useful for one-off iterators. -/// -/// ``` -/// // an iterator that yields sequential Fibonacci numbers, -/// // and stops at the maximum representable value. -/// -/// use itertools::unfold; -/// -/// let (mut x1, mut x2) = (1u32, 1u32); -/// let mut fibonacci = unfold((), move |_| { -/// // Attempt to get the next Fibonacci number -/// let next = x1.saturating_add(x2); -/// -/// // Shift left: ret <- x1 <- x2 <- next -/// let ret = x1; -/// x1 = x2; -/// x2 = next; -/// -/// // If addition has saturated at the maximum, we are finished -/// if ret == x1 && ret > 1 { -/// return None; -/// } -/// -/// Some(ret) -/// }); -/// -/// itertools::assert_equal(fibonacci.by_ref().take(8), -/// vec![1, 1, 2, 3, 5, 8, 13, 21]); -/// assert_eq!(fibonacci.last(), Some(2_971_215_073)) -/// ``` -pub fn unfold<A, St, F>(initial_state: St, f: F) -> Unfold<St, F> - where F: FnMut(&mut St) -> Option<A> -{ - Unfold { - f: f, - state: initial_state, - } -} - -impl<St, F> fmt::Debug for Unfold<St, F> - where St: fmt::Debug, -{ - debug_fmt_fields!(Unfold, state); -} - -/// See [`unfold`](../fn.unfold.html) for more information. -#[derive(Clone)] -#[must_use = "iterators are lazy and do nothing unless consumed"] -pub struct Unfold<St, F> { - f: F, - /// Internal state that will be passed to the closure on the next iteration - pub state: St, -} - -impl<A, St, F> Iterator for Unfold<St, F> - where F: FnMut(&mut St) -> Option<A> -{ - type Item = A; - - #[inline] - fn next(&mut self) -> Option<A> { - (self.f)(&mut self.state) - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - // no possible known bounds at this point - (0, None) - } -} - -/// An iterator that infinitely applies function to value and yields results. -/// -/// This `struct` is created by the [`iterate()`] function. See its documentation for more. -/// -/// [`iterate()`]: ../fn.iterate.html -#[derive(Clone)] -#[must_use = "iterators are lazy and do nothing unless consumed"] -pub struct Iterate<St, F> { - state: St, - f: F, -} - -impl<St, F> fmt::Debug for Iterate<St, F> - where St: fmt::Debug, -{ - debug_fmt_fields!(Iterate, state); -} - -impl<St, F> Iterator for Iterate<St, F> - where F: FnMut(&St) -> St -{ - type Item = St; - - #[inline] - fn next(&mut self) -> Option<Self::Item> { - let next_state = (self.f)(&self.state); - Some(mem::replace(&mut self.state, next_state)) - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - (usize::max_value(), None) - } -} - -/// Creates a new iterator that infinitely applies function to value and yields results. -/// -/// ``` -/// use itertools::iterate; -/// -/// itertools::assert_equal(iterate(1, |&i| i * 3).take(5), vec![1, 3, 9, 27, 81]); -/// ``` -pub fn iterate<St, F>(initial_value: St, f: F) -> Iterate<St, F> - where F: FnMut(&St) -> St -{ - Iterate { - state: initial_value, - f: f, - } -} diff --git a/vendor/itertools-0.8.2/src/tee.rs b/vendor/itertools-0.8.2/src/tee.rs deleted file mode 100644 index 77d261759d..0000000000 --- a/vendor/itertools-0.8.2/src/tee.rs +++ /dev/null @@ -1,78 +0,0 @@ -use super::size_hint; - -use std::cell::RefCell; -use std::collections::VecDeque; -use std::rc::Rc; - -/// Common buffer object for the two tee halves -#[derive(Debug)] -struct TeeBuffer<A, I> { - backlog: VecDeque<A>, - iter: I, - /// The owner field indicates which id should read from the backlog - owner: bool, -} - -/// One half of an iterator pair where both return the same elements. -/// -/// See [`.tee()`](../trait.Itertools.html#method.tee) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -#[derive(Debug)] -pub struct Tee<I> - where I: Iterator -{ - rcbuffer: Rc<RefCell<TeeBuffer<I::Item, I>>>, - id: bool, -} - -pub fn new<I>(iter: I) -> (Tee<I>, Tee<I>) - where I: Iterator -{ - let buffer = TeeBuffer{backlog: VecDeque::new(), iter: iter, owner: false}; - let t1 = Tee{rcbuffer: Rc::new(RefCell::new(buffer)), id: true}; - let t2 = Tee{rcbuffer: t1.rcbuffer.clone(), id: false}; - (t1, t2) -} - -impl<I> Iterator for Tee<I> - where I: Iterator, - I::Item: Clone -{ - type Item = I::Item; - fn next(&mut self) -> Option<I::Item> { - // .borrow_mut may fail here -- but only if the user has tied some kind of weird - // knot where the iterator refers back to itself. - let mut buffer = self.rcbuffer.borrow_mut(); - if buffer.owner == self.id { - match buffer.backlog.pop_front() { - None => {} - some_elt => return some_elt, - } - } - match buffer.iter.next() { - None => None, - Some(elt) => { - buffer.backlog.push_back(elt.clone()); - buffer.owner = !self.id; - Some(elt) - } - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - let buffer = self.rcbuffer.borrow(); - let sh = buffer.iter.size_hint(); - - if buffer.owner == self.id { - let log_len = buffer.backlog.len(); - size_hint::add_scalar(sh, log_len) - } else { - sh - } - } -} - -impl<I> ExactSizeIterator for Tee<I> - where I: ExactSizeIterator, - I::Item: Clone -{} diff --git a/vendor/itertools-0.8.2/src/tuple_impl.rs b/vendor/itertools-0.8.2/src/tuple_impl.rs deleted file mode 100644 index 0daa7800c1..0000000000 --- a/vendor/itertools-0.8.2/src/tuple_impl.rs +++ /dev/null @@ -1,266 +0,0 @@ -//! Some iterator that produces tuples - -use std::iter::Fuse; - -/// An iterator over a incomplete tuple. -/// -/// See [`.tuples()`](../trait.Itertools.html#method.tuples) and -/// [`Tuples::into_buffer()`](struct.Tuples.html#method.into_buffer). -#[derive(Debug)] -pub struct TupleBuffer<T> - where T: TupleCollect -{ - cur: usize, - buf: T::Buffer, -} - -impl<T> TupleBuffer<T> - where T: TupleCollect -{ - fn new(buf: T::Buffer) -> Self { - TupleBuffer { - cur: 0, - buf: buf, - } - } -} - -impl<T> Iterator for TupleBuffer<T> - where T: TupleCollect -{ - type Item = T::Item; - - fn next(&mut self) -> Option<Self::Item> { - let s = self.buf.as_mut(); - if let Some(ref mut item) = s.get_mut(self.cur) { - self.cur += 1; - item.take() - } else { - None - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - let buffer = &self.buf.as_ref()[self.cur..]; - let len = if buffer.len() == 0 { - 0 - } else { - buffer.iter() - .position(|x| x.is_none()) - .unwrap_or(buffer.len()) - }; - (len, Some(len)) - } -} - -impl<T> ExactSizeIterator for TupleBuffer<T> - where T: TupleCollect -{ -} - -/// An iterator that groups the items in tuples of a specific size. -/// -/// See [`.tuples()`](../trait.Itertools.html#method.tuples) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Tuples<I, T> - where I: Iterator<Item = T::Item>, - T: TupleCollect -{ - iter: Fuse<I>, - buf: T::Buffer, -} - -/// Create a new tuples iterator. -pub fn tuples<I, T>(iter: I) -> Tuples<I, T> - where I: Iterator<Item = T::Item>, - T: TupleCollect -{ - Tuples { - iter: iter.fuse(), - buf: Default::default(), - } -} - -impl<I, T> Iterator for Tuples<I, T> - where I: Iterator<Item = T::Item>, - T: TupleCollect -{ - type Item = T; - - fn next(&mut self) -> Option<T> { - T::collect_from_iter(&mut self.iter, &mut self.buf) - } -} - -impl<I, T> Tuples<I, T> - where I: Iterator<Item = T::Item>, - T: TupleCollect -{ - /// Return a buffer with the produced items that was not enough to be grouped in a tuple. - /// - /// ``` - /// use itertools::Itertools; - /// - /// let mut iter = (0..5).tuples(); - /// assert_eq!(Some((0, 1, 2)), iter.next()); - /// assert_eq!(None, iter.next()); - /// itertools::assert_equal(vec![3, 4], iter.into_buffer()); - /// ``` - pub fn into_buffer(self) -> TupleBuffer<T> { - TupleBuffer::new(self.buf) - } -} - - -/// An iterator over all contiguous windows that produces tuples of a specific size. -/// -/// See [`.tuple_windows()`](../trait.Itertools.html#method.tuple_windows) for more -/// information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -#[derive(Debug)] -pub struct TupleWindows<I, T> - where I: Iterator<Item = T::Item>, - T: TupleCollect -{ - iter: I, - last: Option<T>, -} - -/// Create a new tuple windows iterator. -pub fn tuple_windows<I, T>(mut iter: I) -> TupleWindows<I, T> - where I: Iterator<Item = T::Item>, - T: TupleCollect, - T::Item: Clone -{ - use std::iter::once; - - let mut last = None; - if T::num_items() != 1 { - // put in a duplicate item in front of the tuple; this simplifies - // .next() function. - if let Some(item) = iter.next() { - let iter = once(item.clone()).chain(once(item)).chain(&mut iter); - last = T::collect_from_iter_no_buf(iter); - } - } - - TupleWindows { - last: last, - iter: iter, - } -} - -impl<I, T> Iterator for TupleWindows<I, T> - where I: Iterator<Item = T::Item>, - T: TupleCollect + Clone, - T::Item: Clone -{ - type Item = T; - - fn next(&mut self) -> Option<T> { - if T::num_items() == 1 { - return T::collect_from_iter_no_buf(&mut self.iter) - } - if let Some(ref mut last) = self.last { - if let Some(new) = self.iter.next() { - last.left_shift_push(new); - return Some(last.clone()); - } - } - None - } -} - -pub trait TupleCollect: Sized { - type Item; - type Buffer: Default + AsRef<[Option<Self::Item>]> + AsMut<[Option<Self::Item>]>; - - fn collect_from_iter<I>(iter: I, buf: &mut Self::Buffer) -> Option<Self> - where I: IntoIterator<Item = Self::Item>; - - fn collect_from_iter_no_buf<I>(iter: I) -> Option<Self> - where I: IntoIterator<Item = Self::Item>; - - fn num_items() -> usize; - - fn left_shift_push(&mut self, item: Self::Item); -} - -macro_rules! impl_tuple_collect { - () => (); - ($N:expr; $A:ident ; $($X:ident),* ; $($Y:ident),* ; $($Y_rev:ident),*) => ( - impl<$A> TupleCollect for ($($X),*,) { - type Item = $A; - type Buffer = [Option<$A>; $N - 1]; - - #[allow(unused_assignments, unused_mut)] - fn collect_from_iter<I>(iter: I, buf: &mut Self::Buffer) -> Option<Self> - where I: IntoIterator<Item = $A> - { - let mut iter = iter.into_iter(); - $( - let mut $Y = None; - )* - - loop { - $( - $Y = iter.next(); - if $Y.is_none() { - break - } - )* - return Some(($($Y.unwrap()),*,)) - } - - let mut i = 0; - let mut s = buf.as_mut(); - $( - if i < s.len() { - s[i] = $Y; - i += 1; - } - )* - return None; - } - - #[allow(unused_assignments)] - fn collect_from_iter_no_buf<I>(iter: I) -> Option<Self> - where I: IntoIterator<Item = $A> - { - let mut iter = iter.into_iter(); - loop { - $( - let $Y = if let Some($Y) = iter.next() { - $Y - } else { - break; - }; - )* - return Some(($($Y),*,)) - } - - return None; - } - - fn num_items() -> usize { - $N - } - - fn left_shift_push(&mut self, item: $A) { - use std::mem::replace; - - let &mut ($(ref mut $Y),*,) = self; - let tmp = item; - $( - let tmp = replace($Y_rev, tmp); - )* - drop(tmp); - } - } - ) -} - -impl_tuple_collect!(1; A; A; a; a); -impl_tuple_collect!(2; A; A, A; a, b; b, a); -impl_tuple_collect!(3; A; A, A, A; a, b, c; c, b, a); -impl_tuple_collect!(4; A; A, A, A, A; a, b, c, d; d, c, b, a); diff --git a/vendor/itertools-0.8.2/src/unique_impl.rs b/vendor/itertools-0.8.2/src/unique_impl.rs deleted file mode 100644 index d9e7fd3dc8..0000000000 --- a/vendor/itertools-0.8.2/src/unique_impl.rs +++ /dev/null @@ -1,134 +0,0 @@ - -use std::collections::HashMap; -use std::collections::hash_map::{Entry}; -use std::hash::Hash; -use std::fmt; - -/// An iterator adapter to filter out duplicate elements. -/// -/// See [`.unique_by()`](../trait.Itertools.html#method.unique) for more information. -#[derive(Clone)] -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct UniqueBy<I: Iterator, V, F> { - iter: I, - // Use a hashmap for the entry API - used: HashMap<V, ()>, - f: F, -} - -impl<I, V, F> fmt::Debug for UniqueBy<I, V, F> - where I: Iterator + fmt::Debug, - V: fmt::Debug + Hash + Eq, -{ - debug_fmt_fields!(UniqueBy, iter, used); -} - -/// Create a new `UniqueBy` iterator. -pub fn unique_by<I, V, F>(iter: I, f: F) -> UniqueBy<I, V, F> - where V: Eq + Hash, - F: FnMut(&I::Item) -> V, - I: Iterator, -{ - UniqueBy { - iter: iter, - used: HashMap::new(), - f: f, - } -} - -// count the number of new unique keys in iterable (`used` is the set already seen) -fn count_new_keys<I, K>(mut used: HashMap<K, ()>, iterable: I) -> usize - where I: IntoIterator<Item=K>, - K: Hash + Eq, -{ - let iter = iterable.into_iter(); - let current_used = used.len(); - used.extend(iter.map(|key| (key, ()))); - used.len() - current_used -} - -impl<I, V, F> Iterator for UniqueBy<I, V, F> - where I: Iterator, - V: Eq + Hash, - F: FnMut(&I::Item) -> V -{ - type Item = I::Item; - - fn next(&mut self) -> Option<I::Item> { - while let Some(v) = self.iter.next() { - let key = (self.f)(&v); - if self.used.insert(key, ()).is_none() { - return Some(v); - } - } - None - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - let (low, hi) = self.iter.size_hint(); - ((low > 0 && self.used.is_empty()) as usize, hi) - } - - fn count(self) -> usize { - let mut key_f = self.f; - count_new_keys(self.used, self.iter.map(move |elt| key_f(&elt))) - } -} - -impl<I> Iterator for Unique<I> - where I: Iterator, - I::Item: Eq + Hash + Clone -{ - type Item = I::Item; - - fn next(&mut self) -> Option<I::Item> { - while let Some(v) = self.iter.iter.next() { - if let Entry::Vacant(entry) = self.iter.used.entry(v) { - let elt = entry.key().clone(); - entry.insert(()); - return Some(elt); - } - } - None - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - let (low, hi) = self.iter.iter.size_hint(); - ((low > 0 && self.iter.used.is_empty()) as usize, hi) - } - - fn count(self) -> usize { - count_new_keys(self.iter.used, self.iter.iter) - } -} - -/// An iterator adapter to filter out duplicate elements. -/// -/// See [`.unique()`](../trait.Itertools.html#method.unique) for more information. -#[derive(Clone)] -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Unique<I: Iterator> { - iter: UniqueBy<I, I::Item, ()>, -} - -impl<I> fmt::Debug for Unique<I> - where I: Iterator + fmt::Debug, - I::Item: Hash + Eq + fmt::Debug, -{ - debug_fmt_fields!(Unique, iter); -} - -pub fn unique<I>(iter: I) -> Unique<I> - where I: Iterator, - I::Item: Eq + Hash, -{ - Unique { - iter: UniqueBy { - iter: iter, - used: HashMap::new(), - f: (), - } - } -} diff --git a/vendor/itertools-0.8.2/src/with_position.rs b/vendor/itertools-0.8.2/src/with_position.rs deleted file mode 100644 index 2a7c2b8ad6..0000000000 --- a/vendor/itertools-0.8.2/src/with_position.rs +++ /dev/null @@ -1,90 +0,0 @@ -use std::iter::{Fuse,Peekable}; - -/// An iterator adaptor that wraps each element in an [`Position`](../enum.Position.html). -/// -/// Iterator element type is `Position<I::Item>`. -/// -/// See [`.with_position()`](../trait.Itertools.html#method.with_position) for more information. -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct WithPosition<I> - where I: Iterator, -{ - handled_first: bool, - peekable: Peekable<Fuse<I>>, -} - -/// Create a new `WithPosition` iterator. -pub fn with_position<I>(iter: I) -> WithPosition<I> - where I: Iterator, -{ - WithPosition { - handled_first: false, - peekable: iter.fuse().peekable(), - } -} - -/// A value yielded by `WithPosition`. -/// Indicates the position of this element in the iterator results. -/// -/// See [`.with_position()`](trait.Itertools.html#method.with_position) for more information. -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum Position<T> { - /// This is the first element. - First(T), - /// This is neither the first nor the last element. - Middle(T), - /// This is the last element. - Last(T), - /// This is the only element. - Only(T), -} - -impl<T> Position<T> { - /// Return the inner value. - pub fn into_inner(self) -> T { - match self { - Position::First(x) | - Position::Middle(x) | - Position::Last(x) | - Position::Only(x) => x, - } - } -} - -impl<I: Iterator> Iterator for WithPosition<I> { - type Item = Position<I::Item>; - - fn next(&mut self) -> Option<Self::Item> { - match self.peekable.next() { - Some(item) => { - if !self.handled_first { - // Haven't seen the first item yet, and there is one to give. - self.handled_first = true; - // Peek to see if this is also the last item, - // in which case tag it as `Only`. - match self.peekable.peek() { - Some(_) => Some(Position::First(item)), - None => Some(Position::Only(item)), - } - } else { - // Have seen the first item, and there's something left. - // Peek to see if this is the last item. - match self.peekable.peek() { - Some(_) => Some(Position::Middle(item)), - None => Some(Position::Last(item)), - } - } - } - // Iterator is finished. - None => None, - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - self.peekable.size_hint() - } -} - -impl<I> ExactSizeIterator for WithPosition<I> - where I: ExactSizeIterator, -{ } diff --git a/vendor/itertools-0.8.2/src/zip_eq_impl.rs b/vendor/itertools-0.8.2/src/zip_eq_impl.rs deleted file mode 100644 index 857465da41..0000000000 --- a/vendor/itertools-0.8.2/src/zip_eq_impl.rs +++ /dev/null @@ -1,60 +0,0 @@ -use super::size_hint; - -/// An iterator which iterates two other iterators simultaneously -/// -/// See [`.zip_eq()`](../trait.Itertools.html#method.zip_eq) for more information. -#[derive(Clone, Debug)] -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct ZipEq<I, J> { - a: I, - b: J, -} - -/// Iterate `i` and `j` in lock step. -/// -/// **Panics** if the iterators are not of the same length. -/// -/// `IntoIterator` enabled version of `i.zip_eq(j)`. -/// -/// ``` -/// use itertools::zip_eq; -/// -/// let data = [1, 2, 3, 4, 5]; -/// for (a, b) in zip_eq(&data[..data.len() - 1], &data[1..]) { -/// /* loop body */ -/// } -/// ``` -pub fn zip_eq<I, J>(i: I, j: J) -> ZipEq<I::IntoIter, J::IntoIter> - where I: IntoIterator, - J: IntoIterator -{ - ZipEq { - a: i.into_iter(), - b: j.into_iter(), - } -} - -impl<I, J> Iterator for ZipEq<I, J> - where I: Iterator, - J: Iterator -{ - type Item = (I::Item, J::Item); - - fn next(&mut self) -> Option<Self::Item> { - match (self.a.next(), self.b.next()) { - (None, None) => None, - (Some(a), Some(b)) => Some((a, b)), - (None, Some(_)) | (Some(_), None) => - panic!("itertools: .zip_eq() reached end of one iterator before the other") - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - size_hint::min(self.a.size_hint(), self.b.size_hint()) - } -} - -impl<I, J> ExactSizeIterator for ZipEq<I, J> - where I: ExactSizeIterator, - J: ExactSizeIterator -{} diff --git a/vendor/itertools-0.8.2/src/zip_longest.rs b/vendor/itertools-0.8.2/src/zip_longest.rs deleted file mode 100644 index 68a381acee..0000000000 --- a/vendor/itertools-0.8.2/src/zip_longest.rs +++ /dev/null @@ -1,78 +0,0 @@ -use std::cmp::Ordering::{Equal, Greater, Less}; -use super::size_hint; -use std::iter::Fuse; - -use either_or_both::EitherOrBoth; - -// ZipLongest originally written by SimonSapin, -// and dedicated to itertools https://github.com/rust-lang/rust/pull/19283 - -/// An iterator which iterates two other iterators simultaneously -/// -/// This iterator is *fused*. -/// -/// See [`.zip_longest()`](../trait.Itertools.html#method.zip_longest) for more information. -#[derive(Clone, Debug)] -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct ZipLongest<T, U> { - a: Fuse<T>, - b: Fuse<U>, -} - -/// Create a new `ZipLongest` iterator. -pub fn zip_longest<T, U>(a: T, b: U) -> ZipLongest<T, U> - where T: Iterator, - U: Iterator -{ - ZipLongest { - a: a.fuse(), - b: b.fuse(), - } -} - -impl<T, U> Iterator for ZipLongest<T, U> - where T: Iterator, - U: Iterator -{ - type Item = EitherOrBoth<T::Item, U::Item>; - - #[inline] - fn next(&mut self) -> Option<Self::Item> { - match (self.a.next(), self.b.next()) { - (None, None) => None, - (Some(a), None) => Some(EitherOrBoth::Left(a)), - (None, Some(b)) => Some(EitherOrBoth::Right(b)), - (Some(a), Some(b)) => Some(EitherOrBoth::Both(a, b)), - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - size_hint::max(self.a.size_hint(), self.b.size_hint()) - } -} - -impl<T, U> DoubleEndedIterator for ZipLongest<T, U> - where T: DoubleEndedIterator + ExactSizeIterator, - U: DoubleEndedIterator + ExactSizeIterator -{ - #[inline] - fn next_back(&mut self) -> Option<Self::Item> { - match self.a.len().cmp(&self.b.len()) { - Equal => match (self.a.next_back(), self.b.next_back()) { - (None, None) => None, - (Some(a), Some(b)) => Some(EitherOrBoth::Both(a, b)), - // These can only happen if .len() is inconsistent with .next_back() - (Some(a), None) => Some(EitherOrBoth::Left(a)), - (None, Some(b)) => Some(EitherOrBoth::Right(b)), - }, - Greater => self.a.next_back().map(EitherOrBoth::Left), - Less => self.b.next_back().map(EitherOrBoth::Right), - } - } -} - -impl<T, U> ExactSizeIterator for ZipLongest<T, U> - where T: ExactSizeIterator, - U: ExactSizeIterator -{} diff --git a/vendor/itertools-0.8.2/src/ziptuple.rs b/vendor/itertools-0.8.2/src/ziptuple.rs deleted file mode 100644 index 2dc3ea5e0b..0000000000 --- a/vendor/itertools-0.8.2/src/ziptuple.rs +++ /dev/null @@ -1,111 +0,0 @@ -use super::size_hint; - -/// See [`multizip`](../fn.multizip.html) for more information. -#[derive(Clone, Debug)] -#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -pub struct Zip<T> { - t: T, -} - -/// An iterator that generalizes *.zip()* and allows running multiple iterators in lockstep. -/// -/// The iterator `Zip<(I, J, ..., M)>` is formed from a tuple of iterators (or values that -/// implement `IntoIterator`) and yields elements -/// until any of the subiterators yields `None`. -/// -/// The iterator element type is a tuple like like `(A, B, ..., E)` where `A` to `E` are the -/// element types of the subiterator. -/// -/// **Note:** The result of this macro is a value of a named type (`Zip<(I, J, -/// ..)>` of each component iterator `I, J, ...`) if each component iterator is -/// nameable. -/// -/// Prefer [`izip!()`] over `multizip` for the performance benefits of using the -/// standard library `.zip()`. Prefer `multizip` if a nameable type is needed. -/// -/// [`izip!()`]: macro.izip.html -/// -/// ``` -/// use itertools::multizip; -/// -/// // iterate over three sequences side-by-side -/// let mut results = [0, 0, 0, 0]; -/// let inputs = [3, 7, 9, 6]; -/// -/// for (r, index, input) in multizip((&mut results, 0..10, &inputs)) { -/// *r = index * 10 + input; -/// } -/// -/// assert_eq!(results, [0 + 3, 10 + 7, 29, 36]); -/// ``` -pub fn multizip<T, U>(t: U) -> Zip<T> - where Zip<T>: From<U>, - Zip<T>: Iterator, -{ - Zip::from(t) -} - -macro_rules! impl_zip_iter { - ($($B:ident),*) => ( - #[allow(non_snake_case)] - impl<$($B: IntoIterator),*> From<($($B,)*)> for Zip<($($B::IntoIter,)*)> { - fn from(t: ($($B,)*)) -> Self { - let ($($B,)*) = t; - Zip { t: ($($B.into_iter(),)*) } - } - } - - #[allow(non_snake_case)] - #[allow(unused_assignments)] - impl<$($B),*> Iterator for Zip<($($B,)*)> - where - $( - $B: Iterator, - )* - { - type Item = ($($B::Item,)*); - - fn next(&mut self) -> Option<Self::Item> - { - let ($(ref mut $B,)*) = self.t; - - // NOTE: Just like iter::Zip, we check the iterators - // for None in order. We may finish unevenly (some - // iterators gave n + 1 elements, some only n). - $( - let $B = match $B.next() { - None => return None, - Some(elt) => elt - }; - )* - Some(($($B,)*)) - } - - fn size_hint(&self) -> (usize, Option<usize>) - { - let sh = (::std::usize::MAX, None); - let ($(ref $B,)*) = self.t; - $( - let sh = size_hint::min($B.size_hint(), sh); - )* - sh - } - } - - #[allow(non_snake_case)] - impl<$($B),*> ExactSizeIterator for Zip<($($B,)*)> where - $( - $B: ExactSizeIterator, - )* - { } - ); -} - -impl_zip_iter!(A); -impl_zip_iter!(A, B); -impl_zip_iter!(A, B, C); -impl_zip_iter!(A, B, C, D); -impl_zip_iter!(A, B, C, D, E); -impl_zip_iter!(A, B, C, D, E, F); -impl_zip_iter!(A, B, C, D, E, F, G); -impl_zip_iter!(A, B, C, D, E, F, G, H); diff --git a/vendor/itertools-0.8.2/tests/adaptors_no_collect.rs b/vendor/itertools-0.8.2/tests/adaptors_no_collect.rs deleted file mode 100644 index 4da6fcf4e9..0000000000 --- a/vendor/itertools-0.8.2/tests/adaptors_no_collect.rs +++ /dev/null @@ -1,49 +0,0 @@ -extern crate itertools; - -use itertools::Itertools; - -struct PanickingCounter { - curr: usize, - max: usize, -} - -impl Iterator for PanickingCounter { - type Item = (); - - fn next(&mut self) -> Option<Self::Item> { - self.curr += 1; - - if self.curr == self.max { - panic!( - "Input iterator reached maximum of {} suggesting collection by adaptor", - self.max - ); - } - - Some(()) - } -} - -fn no_collect_test<A, T>(to_adaptor: T) - where A: Iterator, T: Fn(PanickingCounter) -> A -{ - let counter = PanickingCounter { curr: 0, max: 10_000 }; - let adaptor = to_adaptor(counter); - - for _ in adaptor.take(5) {} -} - -#[test] -fn permutations_no_collect() { - no_collect_test(|iter| iter.permutations(5)) -} - -#[test] -fn combinations_no_collect() { - no_collect_test(|iter| iter.combinations(5)) -} - -#[test] -fn combinations_with_replacement_no_collect() { - no_collect_test(|iter| iter.combinations_with_replacement(5)) -} \ No newline at end of file diff --git a/vendor/itertools-0.8.2/tests/fold_specialization.rs b/vendor/itertools-0.8.2/tests/fold_specialization.rs deleted file mode 100644 index ac5d6a25dc..0000000000 --- a/vendor/itertools-0.8.2/tests/fold_specialization.rs +++ /dev/null @@ -1,15 +0,0 @@ -extern crate itertools; - -use itertools::Itertools; - -#[test] -fn specialization_intersperse() { - let mut iter = (1..2).intersperse(0); - iter.clone().for_each(|x| assert_eq!(Some(x), iter.next())); - - let mut iter = (1..3).intersperse(0); - iter.clone().for_each(|x| assert_eq!(Some(x), iter.next())); - - let mut iter = (1..4).intersperse(0); - iter.clone().for_each(|x| assert_eq!(Some(x), iter.next())); -} diff --git a/vendor/itertools-0.8.2/tests/merge_join.rs b/vendor/itertools-0.8.2/tests/merge_join.rs deleted file mode 100644 index 41829202b8..0000000000 --- a/vendor/itertools-0.8.2/tests/merge_join.rs +++ /dev/null @@ -1,110 +0,0 @@ -extern crate itertools; - -use itertools::EitherOrBoth; -use itertools::free::merge_join_by; - -#[test] -fn empty() { - let left: Vec<u32> = vec![]; - let right: Vec<u32> = vec![]; - let expected_result: Vec<EitherOrBoth<u32, u32>> = vec![]; - let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) - .collect::<Vec<_>>(); - assert_eq!(expected_result, actual_result); -} - -#[test] -fn left_only() { - let left: Vec<u32> = vec![1,2,3]; - let right: Vec<u32> = vec![]; - let expected_result: Vec<EitherOrBoth<u32, u32>> = vec![ - EitherOrBoth::Left(1), - EitherOrBoth::Left(2), - EitherOrBoth::Left(3) - ]; - let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) - .collect::<Vec<_>>(); - assert_eq!(expected_result, actual_result); -} - -#[test] -fn right_only() { - let left: Vec<u32> = vec![]; - let right: Vec<u32> = vec![1,2,3]; - let expected_result: Vec<EitherOrBoth<u32, u32>> = vec![ - EitherOrBoth::Right(1), - EitherOrBoth::Right(2), - EitherOrBoth::Right(3) - ]; - let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) - .collect::<Vec<_>>(); - assert_eq!(expected_result, actual_result); -} - -#[test] -fn first_left_then_right() { - let left: Vec<u32> = vec![1,2,3]; - let right: Vec<u32> = vec![4,5,6]; - let expected_result: Vec<EitherOrBoth<u32, u32>> = vec![ - EitherOrBoth::Left(1), - EitherOrBoth::Left(2), - EitherOrBoth::Left(3), - EitherOrBoth::Right(4), - EitherOrBoth::Right(5), - EitherOrBoth::Right(6) - ]; - let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) - .collect::<Vec<_>>(); - assert_eq!(expected_result, actual_result); -} - -#[test] -fn first_right_then_left() { - let left: Vec<u32> = vec![4,5,6]; - let right: Vec<u32> = vec![1,2,3]; - let expected_result: Vec<EitherOrBoth<u32, u32>> = vec![ - EitherOrBoth::Right(1), - EitherOrBoth::Right(2), - EitherOrBoth::Right(3), - EitherOrBoth::Left(4), - EitherOrBoth::Left(5), - EitherOrBoth::Left(6) - ]; - let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) - .collect::<Vec<_>>(); - assert_eq!(expected_result, actual_result); -} - -#[test] -fn interspersed_left_and_right() { - let left: Vec<u32> = vec![1,3,5]; - let right: Vec<u32> = vec![2,4,6]; - let expected_result: Vec<EitherOrBoth<u32, u32>> = vec![ - EitherOrBoth::Left(1), - EitherOrBoth::Right(2), - EitherOrBoth::Left(3), - EitherOrBoth::Right(4), - EitherOrBoth::Left(5), - EitherOrBoth::Right(6) - ]; - let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) - .collect::<Vec<_>>(); - assert_eq!(expected_result, actual_result); -} - -#[test] -fn overlapping_left_and_right() { - let left: Vec<u32> = vec![1,3,4,6]; - let right: Vec<u32> = vec![2,3,4,5]; - let expected_result: Vec<EitherOrBoth<u32, u32>> = vec![ - EitherOrBoth::Left(1), - EitherOrBoth::Right(2), - EitherOrBoth::Both(3, 3), - EitherOrBoth::Both(4, 4), - EitherOrBoth::Right(5), - EitherOrBoth::Left(6) - ]; - let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) - .collect::<Vec<_>>(); - assert_eq!(expected_result, actual_result); -} diff --git a/vendor/itertools-0.8.2/tests/peeking_take_while.rs b/vendor/itertools-0.8.2/tests/peeking_take_while.rs deleted file mode 100644 index 45c76c2d5c..0000000000 --- a/vendor/itertools-0.8.2/tests/peeking_take_while.rs +++ /dev/null @@ -1,53 +0,0 @@ - -extern crate itertools; - -use itertools::Itertools; -use itertools::{put_back, put_back_n}; - -#[test] -fn peeking_take_while_peekable() { - let mut r = (0..10).peekable(); - r.peeking_take_while(|x| *x <= 3).count(); - assert_eq!(r.next(), Some(4)); -} - -#[test] -fn peeking_take_while_put_back() { - let mut r = put_back(0..10); - r.peeking_take_while(|x| *x <= 3).count(); - assert_eq!(r.next(), Some(4)); - r.peeking_take_while(|_| true).count(); - assert_eq!(r.next(), None); -} - -#[test] -fn peeking_take_while_put_back_n() { - let mut r = put_back_n(6..10); - for elt in (0..6).rev() { - r.put_back(elt); - } - r.peeking_take_while(|x| *x <= 3).count(); - assert_eq!(r.next(), Some(4)); - r.peeking_take_while(|_| true).count(); - assert_eq!(r.next(), None); -} - -#[test] -fn peeking_take_while_slice_iter() { - let v = [1, 2, 3, 4, 5, 6]; - let mut r = v.iter(); - r.peeking_take_while(|x| **x <= 3).count(); - assert_eq!(r.next(), Some(&4)); - r.peeking_take_while(|_| true).count(); - assert_eq!(r.next(), None); -} - -#[test] -fn peeking_take_while_slice_iter_rev() { - let v = [1, 2, 3, 4, 5, 6]; - let mut r = v.iter().rev(); - r.peeking_take_while(|x| **x >= 3).count(); - assert_eq!(r.next(), Some(&2)); - r.peeking_take_while(|_| true).count(); - assert_eq!(r.next(), None); -} diff --git a/vendor/itertools-0.8.2/tests/quick.rs b/vendor/itertools-0.8.2/tests/quick.rs deleted file mode 100644 index 7767447268..0000000000 --- a/vendor/itertools-0.8.2/tests/quick.rs +++ /dev/null @@ -1,1161 +0,0 @@ -//! The purpose of these tests is to cover corner cases of iterators -//! and adaptors. -//! -//! In particular we test the tedious size_hint and exact size correctness. - -#[macro_use] extern crate itertools; - -extern crate quickcheck; -extern crate rand; - -use std::default::Default; - -use quickcheck as qc; -use std::ops::Range; -use std::cmp::{max, min, Ordering}; -use std::collections::HashSet; -use itertools::Itertools; -use itertools::{ - multizip, - EitherOrBoth, -}; -use itertools::free::{ - cloned, - enumerate, - multipeek, - put_back, - put_back_n, - rciter, - zip, - zip_eq, -}; - -use rand::Rng; -use rand::seq::SliceRandom; -use quickcheck::TestResult; - -/// Trait for size hint modifier types -trait HintKind: Copy + Send + qc::Arbitrary { - fn loosen_bounds(&self, org_hint: (usize, Option<usize>)) -> (usize, Option<usize>); -} - -/// Exact size hint variant that leaves hints unchanged -#[derive(Clone, Copy, Debug)] -struct Exact {} - -impl HintKind for Exact { - fn loosen_bounds(&self, org_hint: (usize, Option<usize>)) -> (usize, Option<usize>) { - org_hint - } -} - -impl qc::Arbitrary for Exact { - fn arbitrary<G: qc::Gen>(_: &mut G) -> Self { - Exact {} - } -} - -/// Inexact size hint variant to simulate imprecise (but valid) size hints -/// -/// Will always decrease the lower bound and increase the upper bound -/// of the size hint by set amounts. -#[derive(Clone, Copy, Debug)] -struct Inexact { - underestimate: usize, - overestimate: usize, -} - -impl HintKind for Inexact { - fn loosen_bounds(&self, org_hint: (usize, Option<usize>)) -> (usize, Option<usize>) { - let (org_lower, org_upper) = org_hint; - (org_lower.saturating_sub(self.underestimate), - org_upper.and_then(move |x| x.checked_add(self.overestimate))) - } -} - -impl qc::Arbitrary for Inexact { - fn arbitrary<G: qc::Gen>(g: &mut G) -> Self { - let ue_value = usize::arbitrary(g); - let oe_value = usize::arbitrary(g); - // Compensate for quickcheck using extreme values too rarely - let ue_choices = &[0, ue_value, usize::max_value()]; - let oe_choices = &[0, oe_value, usize::max_value()]; - Inexact { - underestimate: *ue_choices.choose(g).unwrap(), - overestimate: *oe_choices.choose(g).unwrap(), - } - } - - fn shrink(&self) -> Box<Iterator<Item=Self>> { - let underestimate_value = self.underestimate; - let overestimate_value = self.overestimate; - Box::new( - underestimate_value.shrink().flat_map(move |ue_value| - overestimate_value.shrink().map(move |oe_value| - Inexact { - underestimate: ue_value, - overestimate: oe_value, - } - ) - ) - ) - } -} - -/// Our base iterator that we can impl Arbitrary for -/// -/// By default we'll return inexact bounds estimates for size_hint -/// to make tests harder to pass. -/// -/// NOTE: Iter is tricky and is not fused, to help catch bugs. -/// At the end it will return None once, then return Some(0), -/// then return None again. -#[derive(Clone, Debug)] -struct Iter<T, SK: HintKind = Inexact> { - iterator: Range<T>, - // fuse/done flag - fuse_flag: i32, - hint_kind: SK, -} - -impl<T, HK> Iter<T, HK> where HK: HintKind -{ - fn new(it: Range<T>, hint_kind: HK) -> Self { - Iter { - iterator: it, - fuse_flag: 0, - hint_kind: hint_kind - } - } -} - -impl<T, HK> Iterator for Iter<T, HK> - where Range<T>: Iterator, - <Range<T> as Iterator>::Item: Default, - HK: HintKind, -{ - type Item = <Range<T> as Iterator>::Item; - - fn next(&mut self) -> Option<Self::Item> - { - let elt = self.iterator.next(); - if elt.is_none() { - self.fuse_flag += 1; - // check fuse flag - if self.fuse_flag == 2 { - return Some(Default::default()) - } - } - elt - } - - fn size_hint(&self) -> (usize, Option<usize>) - { - let org_hint = self.iterator.size_hint(); - self.hint_kind.loosen_bounds(org_hint) - } -} - -impl<T, HK> DoubleEndedIterator for Iter<T, HK> - where Range<T>: DoubleEndedIterator, - <Range<T> as Iterator>::Item: Default, - HK: HintKind -{ - fn next_back(&mut self) -> Option<Self::Item> { self.iterator.next_back() } -} - -impl<T> ExactSizeIterator for Iter<T, Exact> where Range<T>: ExactSizeIterator, - <Range<T> as Iterator>::Item: Default, -{ } - -impl<T, HK> qc::Arbitrary for Iter<T, HK> - where T: qc::Arbitrary, - HK: HintKind, -{ - fn arbitrary<G: qc::Gen>(g: &mut G) -> Self - { - Iter::new(T::arbitrary(g)..T::arbitrary(g), HK::arbitrary(g)) - } - - fn shrink(&self) -> Box<Iterator<Item=Iter<T, HK>>> - { - let r = self.iterator.clone(); - let hint_kind = self.hint_kind; - Box::new( - r.start.shrink().flat_map(move |a| - r.end.shrink().map(move |b| - Iter::new(a.clone()..b, hint_kind) - ) - ) - ) - } -} - -/// A meta-iterator which yields `Iter<i32>`s whose start/endpoints are -/// increased or decreased linearly on each iteration. -#[derive(Clone, Debug)] -struct ShiftRange<HK = Inexact> { - range_start: i32, - range_end: i32, - start_step: i32, - end_step: i32, - iter_count: u32, - hint_kind: HK, -} - -impl<HK> Iterator for ShiftRange<HK> where HK: HintKind { - type Item = Iter<i32, HK>; - - fn next(&mut self) -> Option<Self::Item> { - if self.iter_count == 0 { - return None; - } - - let iter = Iter::new(self.range_start..self.range_end, self.hint_kind); - - self.range_start += self.start_step; - self.range_end += self.end_step; - self.iter_count -= 1; - - Some(iter) - } -} - -impl ExactSizeIterator for ShiftRange<Exact> { } - -impl<HK> qc::Arbitrary for ShiftRange<HK> - where HK: HintKind -{ - fn arbitrary<G: qc::Gen>(g: &mut G) -> Self { - const MAX_STARTING_RANGE_DIFF: i32 = 32; - const MAX_STEP_MODULO: i32 = 8; - const MAX_ITER_COUNT: u32 = 3; - - let range_start = qc::Arbitrary::arbitrary(g); - let range_end = range_start + g.gen_range(0, MAX_STARTING_RANGE_DIFF + 1); - let start_step = g.gen_range(-MAX_STEP_MODULO, MAX_STEP_MODULO + 1); - let end_step = g.gen_range(-MAX_STEP_MODULO, MAX_STEP_MODULO + 1); - let iter_count = g.gen_range(0, MAX_ITER_COUNT + 1); - let hint_kind = qc::Arbitrary::arbitrary(g); - - ShiftRange { - range_start: range_start, - range_end: range_end, - start_step: start_step, - end_step: end_step, - iter_count: iter_count, - hint_kind: hint_kind - } - } -} - -fn correct_count<I, F>(get_it: F) -> bool -where - I: Iterator, - F: Fn() -> I -{ - let mut counts = vec![get_it().count()]; - - 'outer: loop { - let mut it = get_it(); - - for _ in 0..(counts.len() - 1) { - if let None = it.next() { - panic!("Iterator shouldn't be finished, may not be deterministic"); - } - } - - if let None = it.next() { - break 'outer; - } - - counts.push(it.count()); - } - - let total_actual_count = counts.len() - 1; - - for (i, returned_count) in counts.into_iter().enumerate() { - let actual_count = total_actual_count - i; - if actual_count != returned_count { - println!("Total iterations: {} True count: {} returned count: {}", i, actual_count, returned_count); - - return false; - } - } - - true -} - -fn correct_size_hint<I: Iterator>(mut it: I) -> bool { - // record size hint at each iteration - let initial_hint = it.size_hint(); - let mut hints = Vec::with_capacity(initial_hint.0 + 1); - hints.push(initial_hint); - while let Some(_) = it.next() { - hints.push(it.size_hint()) - } - - let mut true_count = hints.len(); // start off +1 too much - - // check all the size hints - for &(low, hi) in &hints { - true_count -= 1; - if low > true_count || - (hi.is_some() && hi.unwrap() < true_count) - { - println!("True size: {:?}, size hint: {:?}", true_count, (low, hi)); - //println!("All hints: {:?}", hints); - return false - } - } - true -} - -fn exact_size<I: ExactSizeIterator>(mut it: I) -> bool { - // check every iteration - let (mut low, mut hi) = it.size_hint(); - if Some(low) != hi { return false; } - while let Some(_) = it.next() { - let (xlow, xhi) = it.size_hint(); - if low != xlow + 1 { return false; } - low = xlow; - hi = xhi; - if Some(low) != hi { return false; } - } - let (low, hi) = it.size_hint(); - low == 0 && hi == Some(0) -} - -// Exact size for this case, without ExactSizeIterator -fn exact_size_for_this<I: Iterator>(mut it: I) -> bool { - // check every iteration - let (mut low, mut hi) = it.size_hint(); - if Some(low) != hi { return false; } - while let Some(_) = it.next() { - let (xlow, xhi) = it.size_hint(); - if low != xlow + 1 { return false; } - low = xlow; - hi = xhi; - if Some(low) != hi { return false; } - } - let (low, hi) = it.size_hint(); - low == 0 && hi == Some(0) -} - -/* - * NOTE: Range<i8> is broken! - * (all signed ranges are) -#[quickcheck] -fn size_range_i8(a: Iter<i8>) -> bool { - exact_size(a) -} - -#[quickcheck] -fn size_range_i16(a: Iter<i16>) -> bool { - exact_size(a) -} - -#[quickcheck] -fn size_range_u8(a: Iter<u8>) -> bool { - exact_size(a) -} - */ - -macro_rules! quickcheck { - // accept several property function definitions - // The property functions can use pattern matching and `mut` as usual - // in the function arguments, but the functions can not be generic. - {$($(#$attr:tt)* fn $fn_name:ident($($arg:tt)*) -> $ret:ty { $($code:tt)* })*} => ( - $( - #[test] - $(#$attr)* - fn $fn_name() { - fn prop($($arg)*) -> $ret { - $($code)* - } - ::quickcheck::quickcheck(quickcheck!(@fn prop [] $($arg)*)); - } - )* - ); - // parse argument list (with patterns allowed) into prop as fn(_, _) -> _ - (@fn $f:ident [$($t:tt)*]) => { - $f as fn($($t),*) -> _ - }; - (@fn $f:ident [$($p:tt)*] : $($tail:tt)*) => { - quickcheck!(@fn $f [$($p)* _] $($tail)*) - }; - (@fn $f:ident [$($p:tt)*] $t:tt $($tail:tt)*) => { - quickcheck!(@fn $f [$($p)*] $($tail)*) - }; -} - -quickcheck! { - - fn size_product(a: Iter<u16>, b: Iter<u16>) -> bool { - correct_size_hint(a.cartesian_product(b)) - } - fn size_product3(a: Iter<u16>, b: Iter<u16>, c: Iter<u16>) -> bool { - correct_size_hint(iproduct!(a, b, c)) - } - - fn correct_cartesian_product3(a: Iter<u16>, b: Iter<u16>, c: Iter<u16>, - take_manual: usize) -> () - { - // test correctness of iproduct through regular iteration (take) - // and through fold. - let ac = a.clone(); - let br = &b.clone(); - let cr = &c.clone(); - let answer: Vec<_> = ac.flat_map(move |ea| br.clone().flat_map(move |eb| cr.clone().map(move |ec| (ea, eb, ec)))).collect(); - let mut product_iter = iproduct!(a, b, c); - let mut actual = Vec::new(); - - actual.extend((&mut product_iter).take(take_manual)); - if actual.len() == take_manual { - product_iter.fold((), |(), elt| actual.push(elt)); - } - assert_eq!(answer, actual); - } - - fn size_multi_product(a: ShiftRange) -> bool { - correct_size_hint(a.multi_cartesian_product()) - } - fn correct_multi_product3(a: ShiftRange, take_manual: usize) -> () { - // Fix no. of iterators at 3 - let a = ShiftRange { iter_count: 3, ..a }; - - // test correctness of MultiProduct through regular iteration (take) - // and through fold. - let mut iters = a.clone(); - let i0 = iters.next().unwrap(); - let i1r = &iters.next().unwrap(); - let i2r = &iters.next().unwrap(); - let answer: Vec<_> = i0.flat_map(move |ei0| i1r.clone().flat_map(move |ei1| i2r.clone().map(move |ei2| vec![ei0, ei1, ei2]))).collect(); - let mut multi_product = a.clone().multi_cartesian_product(); - let mut actual = Vec::new(); - - actual.extend((&mut multi_product).take(take_manual)); - if actual.len() == take_manual { - multi_product.fold((), |(), elt| actual.push(elt)); - } - assert_eq!(answer, actual); - - assert_eq!(answer.into_iter().last(), a.clone().multi_cartesian_product().last()); - } - - #[allow(deprecated)] - fn size_step(a: Iter<i16, Exact>, s: usize) -> bool { - let mut s = s; - if s == 0 { - s += 1; // never zero - } - let filt = a.clone().dedup(); - correct_size_hint(filt.step(s)) && - exact_size(a.step(s)) - } - - #[allow(deprecated)] - fn equal_step(a: Iter<i16>, s: usize) -> bool { - let mut s = s; - if s == 0 { - s += 1; // never zero - } - let mut i = 0; - itertools::equal(a.clone().step(s), a.filter(|_| { - let keep = i % s == 0; - i += 1; - keep - })) - } - - #[allow(deprecated)] - fn equal_step_vec(a: Vec<i16>, s: usize) -> bool { - let mut s = s; - if s == 0 { - s += 1; // never zero - } - let mut i = 0; - itertools::equal(a.iter().step(s), a.iter().filter(|_| { - let keep = i % s == 0; - i += 1; - keep - })) - } - - fn size_multipeek(a: Iter<u16, Exact>, s: u8) -> bool { - let mut it = multipeek(a); - // peek a few times - for _ in 0..s { - it.peek(); - } - exact_size(it) - } - - fn equal_merge(a: Vec<i16>, b: Vec<i16>) -> bool { - let mut sa = a.clone(); - let mut sb = b.clone(); - sa.sort(); - sb.sort(); - let mut merged = sa.clone(); - merged.extend(sb.iter().cloned()); - merged.sort(); - itertools::equal(&merged, sa.iter().merge(&sb)) - } - fn size_merge(a: Iter<u16>, b: Iter<u16>) -> bool { - correct_size_hint(a.merge(b)) - } - fn size_zip(a: Iter<i16, Exact>, b: Iter<i16, Exact>, c: Iter<i16, Exact>) -> bool { - let filt = a.clone().dedup(); - correct_size_hint(multizip((filt, b.clone(), c.clone()))) && - exact_size(multizip((a, b, c))) - } - fn size_zip_rc(a: Iter<i16>, b: Iter<i16>) -> bool { - let rc = rciter(a.clone()); - correct_size_hint(multizip((&rc, &rc, b))) - } - - fn size_zip_macro(a: Iter<i16, Exact>, b: Iter<i16, Exact>, c: Iter<i16, Exact>) -> bool { - let filt = a.clone().dedup(); - correct_size_hint(izip!(filt, b.clone(), c.clone())) && - exact_size(izip!(a, b, c)) - } - fn equal_kmerge(a: Vec<i16>, b: Vec<i16>, c: Vec<i16>) -> bool { - use itertools::free::kmerge; - let mut sa = a.clone(); - let mut sb = b.clone(); - let mut sc = c.clone(); - sa.sort(); - sb.sort(); - sc.sort(); - let mut merged = sa.clone(); - merged.extend(sb.iter().cloned()); - merged.extend(sc.iter().cloned()); - merged.sort(); - itertools::equal(merged.into_iter(), kmerge(vec![sa, sb, sc])) - } - - // Any number of input iterators - fn equal_kmerge_2(mut inputs: Vec<Vec<i16>>) -> bool { - use itertools::free::kmerge; - // sort the inputs - for input in &mut inputs { - input.sort(); - } - let mut merged = inputs.concat(); - merged.sort(); - itertools::equal(merged.into_iter(), kmerge(inputs)) - } - - // Any number of input iterators - fn equal_kmerge_by_ge(mut inputs: Vec<Vec<i16>>) -> bool { - // sort the inputs - for input in &mut inputs { - input.sort(); - input.reverse(); - } - let mut merged = inputs.concat(); - merged.sort(); - merged.reverse(); - itertools::equal(merged.into_iter(), - inputs.into_iter().kmerge_by(|x, y| x >= y)) - } - - // Any number of input iterators - fn equal_kmerge_by_lt(mut inputs: Vec<Vec<i16>>) -> bool { - // sort the inputs - for input in &mut inputs { - input.sort(); - } - let mut merged = inputs.concat(); - merged.sort(); - itertools::equal(merged.into_iter(), - inputs.into_iter().kmerge_by(|x, y| x < y)) - } - - // Any number of input iterators - fn equal_kmerge_by_le(mut inputs: Vec<Vec<i16>>) -> bool { - // sort the inputs - for input in &mut inputs { - input.sort(); - } - let mut merged = inputs.concat(); - merged.sort(); - itertools::equal(merged.into_iter(), - inputs.into_iter().kmerge_by(|x, y| x <= y)) - } - fn size_kmerge(a: Iter<i16>, b: Iter<i16>, c: Iter<i16>) -> bool { - use itertools::free::kmerge; - correct_size_hint(kmerge(vec![a, b, c])) - } - fn equal_zip_eq(a: Vec<i32>, b: Vec<i32>) -> bool { - let len = std::cmp::min(a.len(), b.len()); - let a = &a[..len]; - let b = &b[..len]; - itertools::equal(zip_eq(a, b), zip(a, b)) - } - fn size_zip_longest(a: Iter<i16, Exact>, b: Iter<i16, Exact>) -> bool { - let filt = a.clone().dedup(); - let filt2 = b.clone().dedup(); - correct_size_hint(filt.zip_longest(b.clone())) && - correct_size_hint(a.clone().zip_longest(filt2)) && - exact_size(a.zip_longest(b)) - } - fn size_2_zip_longest(a: Iter<i16>, b: Iter<i16>) -> bool { - let it = a.clone().zip_longest(b.clone()); - let jt = a.clone().zip_longest(b.clone()); - itertools::equal(a.clone(), - it.filter_map(|elt| match elt { - EitherOrBoth::Both(x, _) => Some(x), - EitherOrBoth::Left(x) => Some(x), - _ => None, - } - )) - && - itertools::equal(b.clone(), - jt.filter_map(|elt| match elt { - EitherOrBoth::Both(_, y) => Some(y), - EitherOrBoth::Right(y) => Some(y), - _ => None, - } - )) - } - fn size_interleave(a: Iter<i16>, b: Iter<i16>) -> bool { - correct_size_hint(a.interleave(b)) - } - fn exact_interleave(a: Iter<i16, Exact>, b: Iter<i16, Exact>) -> bool { - exact_size_for_this(a.interleave(b)) - } - fn size_interleave_shortest(a: Iter<i16>, b: Iter<i16>) -> bool { - correct_size_hint(a.interleave_shortest(b)) - } - fn exact_interleave_shortest(a: Vec<()>, b: Vec<()>) -> bool { - exact_size_for_this(a.iter().interleave_shortest(&b)) - } - fn size_intersperse(a: Iter<i16>, x: i16) -> bool { - correct_size_hint(a.intersperse(x)) - } - fn equal_intersperse(a: Vec<i32>, x: i32) -> bool { - let mut inter = false; - let mut i = 0; - for elt in a.iter().cloned().intersperse(x) { - if inter { - if elt != x { return false } - } else { - if elt != a[i] { return false } - i += 1; - } - inter = !inter; - } - true - } - - fn equal_combinations_2(a: Vec<u8>) -> bool { - let mut v = Vec::new(); - for (i, x) in enumerate(&a) { - for y in &a[i + 1..] { - v.push((x, y)); - } - } - itertools::equal(a.iter().tuple_combinations::<(_, _)>(), v) - } - - fn collect_tuple_matches_size(a: Iter<i16>) -> bool { - let size = a.clone().count(); - a.collect_tuple::<(_, _, _)>().is_some() == (size == 3) - } - - fn correct_permutations(vals: HashSet<i32>, k: usize) -> () { - // Test permutations only on iterators of distinct integers, to prevent - // false positives. - - const MAX_N: usize = 5; - - let n = min(vals.len(), MAX_N); - let vals: HashSet<i32> = vals.into_iter().take(n).collect(); - - let perms = vals.iter().permutations(k); - - let mut actual = HashSet::new(); - - for perm in perms { - assert_eq!(perm.len(), k); - - let all_items_valid = perm.iter().all(|p| vals.contains(p)); - assert!(all_items_valid, "perm contains value not from input: {:?}", perm); - - // Check that all perm items are distinct - let distinct_len = { - let perm_set: HashSet<_> = perm.iter().collect(); - perm_set.len() - }; - assert_eq!(perm.len(), distinct_len); - - // Check that the perm is new - assert!(actual.insert(perm.clone()), "perm already encountered: {:?}", perm); - } - } - - fn permutations_lexic_order(a: usize, b: usize) -> () { - let a = a % 6; - let b = b % 6; - - let n = max(a, b); - let k = min (a, b); - - let expected_first: Vec<usize> = (0..k).collect(); - let expected_last: Vec<usize> = ((n - k)..n).rev().collect(); - - let mut perms = (0..n).permutations(k); - - let mut curr_perm = match perms.next() { - Some(p) => p, - None => { return; } - }; - - assert_eq!(expected_first, curr_perm); - - while let Some(next_perm) = perms.next() { - assert!( - next_perm > curr_perm, - "next perm isn't greater-than current; next_perm={:?} curr_perm={:?} n={}", - next_perm, curr_perm, n - ); - - curr_perm = next_perm; - } - - assert_eq!(expected_last, curr_perm); - - } - - fn permutations_count(n: usize, k: usize) -> bool { - let n = n % 6; - - correct_count(|| (0..n).permutations(k)) - } - - fn permutations_size(a: Iter<i32>, k: usize) -> bool { - correct_size_hint(a.take(5).permutations(k)) - } - - fn permutations_k0_yields_once(n: usize) -> () { - let k = 0; - let expected: Vec<Vec<usize>> = vec![vec![]]; - let actual = (0..n).permutations(k).collect_vec(); - - assert_eq!(expected, actual); - } -} - -quickcheck! { - fn equal_dedup(a: Vec<i32>) -> bool { - let mut b = a.clone(); - b.dedup(); - itertools::equal(&b, a.iter().dedup()) - } -} - -quickcheck! { - fn equal_dedup_by(a: Vec<(i32, i32)>) -> bool { - let mut b = a.clone(); - b.dedup_by(|x, y| x.0==y.0); - itertools::equal(&b, a.iter().dedup_by(|x, y| x.0==y.0)) - } -} - -quickcheck! { - fn size_dedup(a: Vec<i32>) -> bool { - correct_size_hint(a.iter().dedup()) - } -} - -quickcheck! { - fn size_dedup_by(a: Vec<(i32, i32)>) -> bool { - correct_size_hint(a.iter().dedup_by(|x, y| x.0==y.0)) - } -} - -quickcheck! { - fn exact_repeatn((n, x): (usize, i32)) -> bool { - let it = itertools::repeat_n(x, n); - exact_size(it) - } -} - -quickcheck! { - fn size_put_back(a: Vec<u8>, x: Option<u8>) -> bool { - let mut it = put_back(a.into_iter()); - match x { - Some(t) => it.put_back(t), - None => {} - } - correct_size_hint(it) - } -} - -quickcheck! { - fn size_put_backn(a: Vec<u8>, b: Vec<u8>) -> bool { - let mut it = put_back_n(a.into_iter()); - for elt in b { - it.put_back(elt) - } - correct_size_hint(it) - } -} - -quickcheck! { - fn size_tee(a: Vec<u8>) -> bool { - let (mut t1, mut t2) = a.iter().tee(); - t1.next(); - t1.next(); - t2.next(); - exact_size(t1) && exact_size(t2) - } -} - -quickcheck! { - fn size_tee_2(a: Vec<u8>) -> bool { - let (mut t1, mut t2) = a.iter().dedup().tee(); - t1.next(); - t1.next(); - t2.next(); - correct_size_hint(t1) && correct_size_hint(t2) - } -} - -quickcheck! { - fn size_take_while_ref(a: Vec<u8>, stop: u8) -> bool { - correct_size_hint(a.iter().take_while_ref(|x| **x != stop)) - } -} - -quickcheck! { - fn equal_partition(a: Vec<i32>) -> bool { - let mut a = a; - let mut ap = a.clone(); - let split_index = itertools::partition(&mut ap, |x| *x >= 0); - let parted = (0..split_index).all(|i| ap[i] >= 0) && - (split_index..a.len()).all(|i| ap[i] < 0); - - a.sort(); - ap.sort(); - parted && (a == ap) - } -} - -quickcheck! { - fn size_combinations(it: Iter<i16>) -> bool { - correct_size_hint(it.tuple_combinations::<(_, _)>()) - } -} - -quickcheck! { - fn equal_combinations(it: Iter<i16>) -> bool { - let values = it.clone().collect_vec(); - let mut cmb = it.tuple_combinations(); - for i in 0..values.len() { - for j in i+1..values.len() { - let pair = (values[i], values[j]); - if pair != cmb.next().unwrap() { - return false; - } - } - } - cmb.next() == None - } -} - -quickcheck! { - fn size_pad_tail(it: Iter<i8>, pad: u8) -> bool { - correct_size_hint(it.clone().pad_using(pad as usize, |_| 0)) && - correct_size_hint(it.dropping(1).rev().pad_using(pad as usize, |_| 0)) - } -} - -quickcheck! { - fn size_pad_tail2(it: Iter<i8, Exact>, pad: u8) -> bool { - exact_size(it.pad_using(pad as usize, |_| 0)) - } -} - -quickcheck! { - fn size_unique(it: Iter<i8>) -> bool { - correct_size_hint(it.unique()) - } - - fn count_unique(it: Vec<i8>, take_first: u8) -> () { - let answer = { - let mut v = it.clone(); - v.sort(); v.dedup(); - v.len() - }; - let mut iter = cloned(&it).unique(); - let first_count = (&mut iter).take(take_first as usize).count(); - let rest_count = iter.count(); - assert_eq!(answer, first_count + rest_count); - } -} - -quickcheck! { - fn fuzz_group_by_lazy_1(it: Iter<u8>) -> bool { - let jt = it.clone(); - let groups = it.group_by(|k| *k); - let res = itertools::equal(jt, groups.into_iter().flat_map(|(_, x)| x)); - res - } -} - -quickcheck! { - fn fuzz_group_by_lazy_2(data: Vec<u8>) -> bool { - let groups = data.iter().group_by(|k| *k / 10); - let res = itertools::equal(data.iter(), groups.into_iter().flat_map(|(_, x)| x)); - res - } -} - -quickcheck! { - fn fuzz_group_by_lazy_3(data: Vec<u8>) -> bool { - let grouper = data.iter().group_by(|k| *k / 10); - let groups = grouper.into_iter().collect_vec(); - let res = itertools::equal(data.iter(), groups.into_iter().flat_map(|(_, x)| x)); - res - } -} - -quickcheck! { - fn fuzz_group_by_lazy_duo(data: Vec<u8>, order: Vec<(bool, bool)>) -> bool { - let grouper = data.iter().group_by(|k| *k / 3); - let mut groups1 = grouper.into_iter(); - let mut groups2 = grouper.into_iter(); - let mut elts = Vec::<&u8>::new(); - let mut old_groups = Vec::new(); - - let tup1 = |(_, b)| b; - for &(ord, consume_now) in &order { - let iter = &mut [&mut groups1, &mut groups2][ord as usize]; - match iter.next() { - Some((_, gr)) => if consume_now { - for og in old_groups.drain(..) { - elts.extend(og); - } - elts.extend(gr); - } else { - old_groups.push(gr); - }, - None => break, - } - } - for og in old_groups.drain(..) { - elts.extend(og); - } - for gr in groups1.map(&tup1) { elts.extend(gr); } - for gr in groups2.map(&tup1) { elts.extend(gr); } - itertools::assert_equal(&data, elts); - true - } -} - -quickcheck! { - fn equal_chunks_lazy(a: Vec<u8>, size: u8) -> bool { - let mut size = size; - if size == 0 { - size += 1; - } - let chunks = a.iter().chunks(size as usize); - let it = a.chunks(size as usize); - for (a, b) in chunks.into_iter().zip(it) { - if !itertools::equal(a, b) { - return false; - } - } - true - } -} - -quickcheck! { - fn equal_tuple_windows_1(a: Vec<u8>) -> bool { - let x = a.windows(1).map(|s| (&s[0], )); - let y = a.iter().tuple_windows::<(_,)>(); - itertools::equal(x, y) - } - - fn equal_tuple_windows_2(a: Vec<u8>) -> bool { - let x = a.windows(2).map(|s| (&s[0], &s[1])); - let y = a.iter().tuple_windows::<(_, _)>(); - itertools::equal(x, y) - } - - fn equal_tuple_windows_3(a: Vec<u8>) -> bool { - let x = a.windows(3).map(|s| (&s[0], &s[1], &s[2])); - let y = a.iter().tuple_windows::<(_, _, _)>(); - itertools::equal(x, y) - } - - fn equal_tuple_windows_4(a: Vec<u8>) -> bool { - let x = a.windows(4).map(|s| (&s[0], &s[1], &s[2], &s[3])); - let y = a.iter().tuple_windows::<(_, _, _, _)>(); - itertools::equal(x, y) - } - - fn equal_tuples_1(a: Vec<u8>) -> bool { - let x = a.chunks(1).map(|s| (&s[0], )); - let y = a.iter().tuples::<(_,)>(); - itertools::equal(x, y) - } - - fn equal_tuples_2(a: Vec<u8>) -> bool { - let x = a.chunks(2).filter(|s| s.len() == 2).map(|s| (&s[0], &s[1])); - let y = a.iter().tuples::<(_, _)>(); - itertools::equal(x, y) - } - - fn equal_tuples_3(a: Vec<u8>) -> bool { - let x = a.chunks(3).filter(|s| s.len() == 3).map(|s| (&s[0], &s[1], &s[2])); - let y = a.iter().tuples::<(_, _, _)>(); - itertools::equal(x, y) - } - - fn equal_tuples_4(a: Vec<u8>) -> bool { - let x = a.chunks(4).filter(|s| s.len() == 4).map(|s| (&s[0], &s[1], &s[2], &s[3])); - let y = a.iter().tuples::<(_, _, _, _)>(); - itertools::equal(x, y) - } - - fn exact_tuple_buffer(a: Vec<u8>) -> bool { - let mut iter = a.iter().tuples::<(_, _, _, _)>(); - (&mut iter).last(); - let buffer = iter.into_buffer(); - assert_eq!(buffer.len(), a.len() % 4); - exact_size(buffer) - } -} - -// with_position -quickcheck! { - fn with_position_exact_size_1(a: Vec<u8>) -> bool { - exact_size_for_this(a.iter().with_position()) - } - fn with_position_exact_size_2(a: Iter<u8, Exact>) -> bool { - exact_size_for_this(a.with_position()) - } -} - -quickcheck! { - fn correct_group_map_modulo_key(a: Vec<u8>, modulo: u8) -> () { - let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0` - let count = a.len(); - let lookup = a.into_iter().map(|i| (i % modulo, i)).into_group_map(); - - assert_eq!(lookup.values().flat_map(|vals| vals.iter()).count(), count); - - for (&key, vals) in lookup.iter() { - assert!(vals.iter().all(|&val| val % modulo == key)); - } - } -} - -/// A peculiar type: Equality compares both tuple items, but ordering only the -/// first item. This is so we can check the stability property easily. -#[derive(Clone, Debug, PartialEq, Eq)] -struct Val(u32, u32); - -impl PartialOrd<Val> for Val { - fn partial_cmp(&self, other: &Val) -> Option<Ordering> { - self.0.partial_cmp(&other.0) - } -} - -impl Ord for Val { - fn cmp(&self, other: &Val) -> Ordering { - self.0.cmp(&other.0) - } -} - -impl qc::Arbitrary for Val { - fn arbitrary<G: qc::Gen>(g: &mut G) -> Self { - let (x, y) = <(u32, u32)>::arbitrary(g); - Val(x, y) - } - fn shrink(&self) -> Box<Iterator<Item = Self>> { - Box::new((self.0, self.1).shrink().map(|(x, y)| Val(x, y))) - } -} - -quickcheck! { - fn minmax(a: Vec<Val>) -> bool { - use itertools::MinMaxResult; - - - let minmax = a.iter().minmax(); - let expected = match a.len() { - 0 => MinMaxResult::NoElements, - 1 => MinMaxResult::OneElement(&a[0]), - _ => MinMaxResult::MinMax(a.iter().min().unwrap(), - a.iter().max().unwrap()), - }; - minmax == expected - } -} - -quickcheck! { - fn minmax_f64(a: Vec<f64>) -> TestResult { - use itertools::MinMaxResult; - - if a.iter().any(|x| x.is_nan()) { - return TestResult::discard(); - } - - let min = cloned(&a).fold1(f64::min); - let max = cloned(&a).fold1(f64::max); - - let minmax = cloned(&a).minmax(); - let expected = match a.len() { - 0 => MinMaxResult::NoElements, - 1 => MinMaxResult::OneElement(min.unwrap()), - _ => MinMaxResult::MinMax(min.unwrap(), max.unwrap()), - }; - TestResult::from_bool(minmax == expected) - } -} - -quickcheck! { - #[allow(deprecated)] - fn tree_fold1_f64(mut a: Vec<f64>) -> TestResult { - fn collapse_adjacent<F>(x: Vec<f64>, mut f: F) -> Vec<f64> - where F: FnMut(f64, f64) -> f64 - { - let mut out = Vec::new(); - for i in (0..x.len()).step(2) { - if i == x.len()-1 { - out.push(x[i]) - } else { - out.push(f(x[i], x[i+1])); - } - } - out - } - - if a.iter().any(|x| x.is_nan()) { - return TestResult::discard(); - } - - let actual = a.iter().cloned().tree_fold1(f64::atan2); - - while a.len() > 1 { - a = collapse_adjacent(a, f64::atan2); - } - let expected = a.pop(); - - TestResult::from_bool(actual == expected) - } -} - -quickcheck! { - fn exactly_one_i32(a: Vec<i32>) -> TestResult { - let ret = a.iter().cloned().exactly_one(); - match a.len() { - 1 => TestResult::from_bool(ret.unwrap() == a[0]), - _ => TestResult::from_bool(ret.unwrap_err().eq(a.iter().cloned())), - } - } -} diff --git a/vendor/itertools-0.8.2/tests/test_core.rs b/vendor/itertools-0.8.2/tests/test_core.rs deleted file mode 100644 index b1e03cf672..0000000000 --- a/vendor/itertools-0.8.2/tests/test_core.rs +++ /dev/null @@ -1,272 +0,0 @@ -//! Licensed under the Apache License, Version 2.0 -//! http://www.apache.org/licenses/LICENSE-2.0 or the MIT license -//! http://opensource.org/licenses/MIT, at your -//! option. This file may not be copied, modified, or distributed -//! except according to those terms. -#![no_std] - -#[macro_use] extern crate itertools as it; - -use core::iter; - -use it::Itertools; -use it::interleave; -use it::multizip; -use it::free::put_back; - -#[test] -fn product2() { - let s = "αβ"; - - let mut prod = iproduct!(s.chars(), 0..2); - assert!(prod.next() == Some(('α', 0))); - assert!(prod.next() == Some(('α', 1))); - assert!(prod.next() == Some(('β', 0))); - assert!(prod.next() == Some(('β', 1))); - assert!(prod.next() == None); -} - -#[test] -fn product_temporary() { - for (_x, _y, _z) in iproduct!( - [0, 1, 2].iter().cloned(), - [0, 1, 2].iter().cloned(), - [0, 1, 2].iter().cloned()) - { - // ok - } -} - - -#[test] -fn izip_macro() { - let mut zip = izip!(2..3); - assert!(zip.next() == Some(2)); - assert!(zip.next().is_none()); - - let mut zip = izip!(0..3, 0..2, 0..2i8); - for i in 0..2 { - assert!((i as usize, i, i as i8) == zip.next().unwrap()); - } - assert!(zip.next().is_none()); - - let xs: [isize; 0] = []; - let mut zip = izip!(0..3, 0..2, 0..2i8, &xs); - assert!(zip.next().is_none()); -} - -#[test] -fn izip2() { - let _zip1: iter::Zip<_, _> = izip!(1.., 2..); - let _zip2: iter::Zip<_, _> = izip!(1.., 2.., ); -} - -#[test] -fn izip3() { - let mut zip: iter::Map<iter::Zip<_, _>, _> = izip!(0..3, 0..2, 0..2i8); - for i in 0..2 { - assert!((i as usize, i, i as i8) == zip.next().unwrap()); - } - assert!(zip.next().is_none()); -} - -#[test] -fn multizip3() { - let mut zip = multizip((0..3, 0..2, 0..2i8)); - for i in 0..2 { - assert!((i as usize, i, i as i8) == zip.next().unwrap()); - } - assert!(zip.next().is_none()); - - let xs: [isize; 0] = []; - let mut zip = multizip((0..3, 0..2, 0..2i8, xs.iter())); - assert!(zip.next().is_none()); - - for (_, _, _, _, _) in multizip((0..3, 0..2, xs.iter(), &xs, xs.to_vec())) { - /* test compiles */ - } -} - -#[test] -fn write_to() { - let xs = [7, 9, 8]; - let mut ys = [0; 5]; - let cnt = ys.iter_mut().set_from(xs.iter().map(|x| *x)); - assert!(cnt == xs.len()); - assert!(ys == [7, 9, 8, 0, 0]); - - let cnt = ys.iter_mut().set_from(0..10); - assert!(cnt == ys.len()); - assert!(ys == [0, 1, 2, 3, 4]); -} - -#[test] -fn test_interleave() { - let xs: [u8; 0] = []; - let ys = [7u8, 9, 8, 10]; - let zs = [2u8, 77]; - let it = interleave(xs.iter(), ys.iter()); - it::assert_equal(it, ys.iter()); - - let rs = [7u8, 2, 9, 77, 8, 10]; - let it = interleave(ys.iter(), zs.iter()); - it::assert_equal(it, rs.iter()); -} - -#[allow(deprecated)] -#[test] -fn foreach() { - let xs = [1i32, 2, 3]; - let mut sum = 0; - xs.iter().foreach(|elt| sum += *elt); - assert!(sum == 6); -} - -#[test] -fn dropping() { - let xs = [1, 2, 3]; - let mut it = xs.iter().dropping(2); - assert_eq!(it.next(), Some(&3)); - assert!(it.next().is_none()); - let mut it = xs.iter().dropping(5); - assert!(it.next().is_none()); -} - -#[test] -fn batching() { - let xs = [0, 1, 2, 1, 3]; - let ys = [(0, 1), (2, 1)]; - - // An iterator that gathers elements up in pairs - let pit = xs.iter().cloned().batching(|it| { - match it.next() { - None => None, - Some(x) => match it.next() { - None => None, - Some(y) => Some((x, y)), - } - } - }); - it::assert_equal(pit, ys.iter().cloned()); -} - -#[test] -fn test_put_back() { - let xs = [0, 1, 1, 1, 2, 1, 3, 3]; - let mut pb = put_back(xs.iter().cloned()); - pb.next(); - pb.put_back(1); - pb.put_back(0); - it::assert_equal(pb, xs.iter().cloned()); -} - -#[allow(deprecated)] -#[test] -fn step() { - it::assert_equal((0..10).step(1), 0..10); - it::assert_equal((0..10).step(2), (0..10).filter(|x: &i32| *x % 2 == 0)); - it::assert_equal((0..10).step(10), 0..1); -} - -#[allow(deprecated)] -#[test] -fn merge() { - it::assert_equal((0..10).step(2).merge((1..10).step(2)), 0..10); -} - - -#[test] -fn repeatn() { - let s = "α"; - let mut it = it::repeat_n(s, 3); - assert_eq!(it.len(), 3); - assert_eq!(it.next(), Some(s)); - assert_eq!(it.next(), Some(s)); - assert_eq!(it.next(), Some(s)); - assert_eq!(it.next(), None); - assert_eq!(it.next(), None); -} - -#[test] -fn count_clones() { - // Check that RepeatN only clones N - 1 times. - - use core::cell::Cell; - #[derive(PartialEq, Debug)] - struct Foo { - n: Cell<usize> - } - - impl Clone for Foo - { - fn clone(&self) -> Self - { - let n = self.n.get(); - self.n.set(n + 1); - Foo { n: Cell::new(n + 1) } - } - } - - - for n in 0..10 { - let f = Foo{n: Cell::new(0)}; - let it = it::repeat_n(f, n); - // drain it - let last = it.last(); - if n == 0 { - assert_eq!(last, None); - } else { - assert_eq!(last, Some(Foo{n: Cell::new(n - 1)})); - } - } -} - -#[test] -fn part() { - let mut data = [7, 1, 1, 9, 1, 1, 3]; - let i = it::partition(&mut data, |elt| *elt >= 3); - assert_eq!(i, 3); - assert_eq!(data, [7, 3, 9, 1, 1, 1, 1]); - - let i = it::partition(&mut data, |elt| *elt == 1); - assert_eq!(i, 4); - assert_eq!(data, [1, 1, 1, 1, 9, 3, 7]); - - let mut data = [1, 2, 3, 4, 5, 6, 7, 8, 9]; - let i = it::partition(&mut data, |elt| *elt % 3 == 0); - assert_eq!(i, 3); - assert_eq!(data, [9, 6, 3, 4, 5, 2, 7, 8, 1]); -} - -#[test] -fn tree_fold1() { - for i in 0..100 { - assert_eq!((0..i).tree_fold1(|x, y| x + y), (0..i).fold1(|x, y| x + y)); - } -} - -#[test] -fn exactly_one() { - assert_eq!((0..10).filter(|&x| x == 2).exactly_one().unwrap(), 2); - assert!((0..10).filter(|&x| x > 1 && x < 4).exactly_one().unwrap_err().eq(2..4)); - assert!((0..10).filter(|&x| x > 1 && x < 5).exactly_one().unwrap_err().eq(2..5)); - assert!((0..10).filter(|&_| false).exactly_one().unwrap_err().eq(0..0)); -} - -#[test] -fn sum1() { - let v: &[i32] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - assert_eq!(v[..0].iter().cloned().sum1::<i32>(), None); - assert_eq!(v[1..2].iter().cloned().sum1::<i32>(), Some(1)); - assert_eq!(v[1..3].iter().cloned().sum1::<i32>(), Some(3)); - assert_eq!(v.iter().cloned().sum1::<i32>(), Some(55)); -} - -#[test] -fn product1() { - let v: &[i32] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - assert_eq!(v[..0].iter().cloned().product1::<i32>(), None); - assert_eq!(v[..1].iter().cloned().product1::<i32>(), Some(0)); - assert_eq!(v[1..3].iter().cloned().product1::<i32>(), Some(2)); - assert_eq!(v[1..5].iter().cloned().product1::<i32>(), Some(24)); -} diff --git a/vendor/itertools-0.8.2/tests/test_std.rs b/vendor/itertools-0.8.2/tests/test_std.rs deleted file mode 100644 index 4f48c55cf3..0000000000 --- a/vendor/itertools-0.8.2/tests/test_std.rs +++ /dev/null @@ -1,781 +0,0 @@ - -#[macro_use] extern crate itertools as it; -extern crate permutohedron; - -use it::Itertools; -use it::multizip; -use it::multipeek; -use it::free::rciter; -use it::free::put_back_n; -use it::FoldWhile; -use it::cloned; - -#[test] -fn product3() { - let prod = iproduct!(0..3, 0..2, 0..2); - assert_eq!(prod.size_hint(), (12, Some(12))); - let v = prod.collect_vec(); - for i in 0..3 { - for j in 0..2 { - for k in 0..2 { - assert!((i, j, k) == v[(i * 2 * 2 + j * 2 + k) as usize]); - } - } - } - for (_, _, _, _) in iproduct!(0..3, 0..2, 0..2, 0..3) { - /* test compiles */ - } -} - -#[test] -fn interleave_shortest() { - let v0: Vec<i32> = vec![0, 2, 4]; - let v1: Vec<i32> = vec![1, 3, 5, 7]; - let it = v0.into_iter().interleave_shortest(v1.into_iter()); - assert_eq!(it.size_hint(), (6, Some(6))); - assert_eq!(it.collect_vec(), vec![0, 1, 2, 3, 4, 5]); - - let v0: Vec<i32> = vec![0, 2, 4, 6, 8]; - let v1: Vec<i32> = vec![1, 3, 5]; - let it = v0.into_iter().interleave_shortest(v1.into_iter()); - assert_eq!(it.size_hint(), (7, Some(7))); - assert_eq!(it.collect_vec(), vec![0, 1, 2, 3, 4, 5, 6]); - - let i0 = ::std::iter::repeat(0); - let v1: Vec<_> = vec![1, 3, 5]; - let it = i0.interleave_shortest(v1.into_iter()); - assert_eq!(it.size_hint(), (7, Some(7))); - - let v0: Vec<_> = vec![0, 2, 4]; - let i1 = ::std::iter::repeat(1); - let it = v0.into_iter().interleave_shortest(i1); - assert_eq!(it.size_hint(), (6, Some(6))); -} - - -#[test] -fn unique_by() { - let xs = ["aaa", "bbbbb", "aa", "ccc", "bbbb", "aaaaa", "cccc"]; - let ys = ["aaa", "bbbbb", "ccc"]; - it::assert_equal(ys.iter(), xs.iter().unique_by(|x| x[..2].to_string())); -} - -#[test] -fn unique() { - let xs = [0, 1, 2, 3, 2, 1, 3]; - let ys = [0, 1, 2, 3]; - it::assert_equal(ys.iter(), xs.iter().unique()); - let xs = [0, 1]; - let ys = [0, 1]; - it::assert_equal(ys.iter(), xs.iter().unique()); -} - -#[test] -fn intersperse() { - let xs = ["a", "", "b", "c"]; - let v: Vec<&str> = xs.iter().map(|x| x.clone()).intersperse(", ").collect(); - let text: String = v.concat(); - assert_eq!(text, "a, , b, c".to_string()); - - let ys = [0, 1, 2, 3]; - let mut it = ys[..0].iter().map(|x| *x).intersperse(1); - assert!(it.next() == None); -} - -#[test] -fn dedup() { - let xs = [0, 1, 1, 1, 2, 1, 3, 3]; - let ys = [0, 1, 2, 1, 3]; - it::assert_equal(ys.iter(), xs.iter().dedup()); - let xs = [0, 0, 0, 0, 0]; - let ys = [0]; - it::assert_equal(ys.iter(), xs.iter().dedup()); - - let xs = [0, 1, 1, 1, 2, 1, 3, 3]; - let ys = [0, 1, 2, 1, 3]; - let mut xs_d = Vec::new(); - xs.iter().dedup().fold((), |(), &elt| xs_d.push(elt)); - assert_eq!(&xs_d, &ys); -} - -#[test] -fn dedup_by() { - let xs = [(0, 0), (0, 1), (1, 1), (2, 1), (0, 2), (3, 1), (0, 3), (1, 3)]; - let ys = [(0, 0), (0, 1), (0, 2), (3, 1), (0, 3)]; - it::assert_equal(ys.iter(), xs.iter().dedup_by(|x, y| x.1==y.1)); - let xs = [(0, 1), (0, 2), (0, 3), (0, 4), (0, 5)]; - let ys = [(0, 1)]; - it::assert_equal(ys.iter(), xs.iter().dedup_by(|x, y| x.0==y.0)); - - let xs = [(0, 0), (0, 1), (1, 1), (2, 1), (0, 2), (3, 1), (0, 3), (1, 3)]; - let ys = [(0, 0), (0, 1), (0, 2), (3, 1), (0, 3)]; - let mut xs_d = Vec::new(); - xs.iter().dedup_by(|x, y| x.1==y.1).fold((), |(), &elt| xs_d.push(elt)); - assert_eq!(&xs_d, &ys); -} - -#[test] -fn all_equal() { - assert!("".chars().all_equal()); - assert!("A".chars().all_equal()); - assert!(!"AABBCCC".chars().all_equal()); - assert!("AAAAAAA".chars().all_equal()); - for (_key, mut sub) in &"AABBCCC".chars().group_by(|&x| x) { - assert!(sub.all_equal()); - } -} - -#[test] -fn test_put_back_n() { - let xs = [0, 1, 1, 1, 2, 1, 3, 3]; - let mut pb = put_back_n(xs.iter().cloned()); - pb.next(); - pb.next(); - pb.put_back(1); - pb.put_back(0); - it::assert_equal(pb, xs.iter().cloned()); -} - -#[test] -fn tee() { - let xs = [0, 1, 2, 3]; - let (mut t1, mut t2) = xs.iter().cloned().tee(); - assert_eq!(t1.next(), Some(0)); - assert_eq!(t2.next(), Some(0)); - assert_eq!(t1.next(), Some(1)); - assert_eq!(t1.next(), Some(2)); - assert_eq!(t1.next(), Some(3)); - assert_eq!(t1.next(), None); - assert_eq!(t2.next(), Some(1)); - assert_eq!(t2.next(), Some(2)); - assert_eq!(t1.next(), None); - assert_eq!(t2.next(), Some(3)); - assert_eq!(t2.next(), None); - assert_eq!(t1.next(), None); - assert_eq!(t2.next(), None); - - let (t1, t2) = xs.iter().cloned().tee(); - it::assert_equal(t1, xs.iter().cloned()); - it::assert_equal(t2, xs.iter().cloned()); - - let (t1, t2) = xs.iter().cloned().tee(); - it::assert_equal(t1.zip(t2), xs.iter().cloned().zip(xs.iter().cloned())); -} - - -#[test] -fn test_rciter() { - let xs = [0, 1, 1, 1, 2, 1, 3, 5, 6]; - - let mut r1 = rciter(xs.iter().cloned()); - let mut r2 = r1.clone(); - assert_eq!(r1.next(), Some(0)); - assert_eq!(r2.next(), Some(1)); - let mut z = r1.zip(r2); - assert_eq!(z.next(), Some((1, 1))); - assert_eq!(z.next(), Some((2, 1))); - assert_eq!(z.next(), Some((3, 5))); - assert_eq!(z.next(), None); - - // test intoiterator - let r1 = rciter(0..5); - let mut z = izip!(&r1, r1); - assert_eq!(z.next(), Some((0, 1))); -} - -#[allow(deprecated)] -#[test] -fn trait_pointers() { - struct ByRef<'r, I: ?Sized>(&'r mut I) where I: 'r; - - impl<'r, X, I: ?Sized> Iterator for ByRef<'r, I> where - I: 'r + Iterator<Item=X> - { - type Item = X; - fn next(&mut self) -> Option<X> - { - self.0.next() - } - } - - let mut it = Box::new(0..10) as Box<Iterator<Item=i32>>; - assert_eq!(it.next(), Some(0)); - - { - /* make sure foreach works on non-Sized */ - let jt: &mut Iterator<Item = i32> = &mut *it; - assert_eq!(jt.next(), Some(1)); - - { - let mut r = ByRef(jt); - assert_eq!(r.next(), Some(2)); - } - - assert_eq!(jt.find_position(|x| *x == 4), Some((1, 4))); - jt.foreach(|_| ()); - } -} - -#[test] -fn merge_by() { - let odd : Vec<(u32, &str)> = vec![(1, "hello"), (3, "world"), (5, "!")]; - let even = vec![(2, "foo"), (4, "bar"), (6, "baz")]; - let expected = vec![(1, "hello"), (2, "foo"), (3, "world"), (4, "bar"), (5, "!"), (6, "baz")]; - let results = odd.iter().merge_by(even.iter(), |a, b| a.0 <= b.0); - it::assert_equal(results, expected.iter()); -} - -#[test] -fn merge_by_btree() { - use std::collections::BTreeMap; - let mut bt1 = BTreeMap::new(); - bt1.insert("hello", 1); - bt1.insert("world", 3); - let mut bt2 = BTreeMap::new(); - bt2.insert("foo", 2); - bt2.insert("bar", 4); - let results = bt1.into_iter().merge_by(bt2.into_iter(), |a, b| a.0 <= b.0 ); - let expected = vec![("bar", 4), ("foo", 2), ("hello", 1), ("world", 3)]; - it::assert_equal(results, expected.into_iter()); -} - -#[allow(deprecated)] -#[test] -fn kmerge() { - let its = (0..4).map(|s| (s..10).step(4)); - - it::assert_equal(its.kmerge(), 0..10); -} - -#[allow(deprecated)] -#[test] -fn kmerge_2() { - let its = vec![3, 2, 1, 0].into_iter().map(|s| (s..10).step(4)); - - it::assert_equal(its.kmerge(), 0..10); -} - -#[test] -fn kmerge_empty() { - let its = (0..4).map(|_| 0..0); - assert_eq!(its.kmerge().next(), None); -} - -#[test] -fn kmerge_size_hint() { - let its = (0..5).map(|_| (0..10)); - assert_eq!(its.kmerge().size_hint(), (50, Some(50))); -} - -#[test] -fn kmerge_empty_size_hint() { - let its = (0..5).map(|_| (0..0)); - assert_eq!(its.kmerge().size_hint(), (0, Some(0))); -} - -#[test] -fn join() { - let many = [1, 2, 3]; - let one = [1]; - let none: Vec<i32> = vec![]; - - assert_eq!(many.iter().join(", "), "1, 2, 3"); - assert_eq!( one.iter().join(", "), "1"); - assert_eq!(none.iter().join(", "), ""); -} - -#[test] -fn sorted_by() { - let sc = [3, 4, 1, 2].iter().cloned().sorted_by(|&a, &b| { - a.cmp(&b) - }); - it::assert_equal(sc, vec![1, 2, 3, 4]); - - let v = (0..5).sorted_by(|&a, &b| a.cmp(&b).reverse()); - it::assert_equal(v, vec![4, 3, 2, 1, 0]); -} - -#[test] -fn sorted_by_key() { - let sc = [3, 4, 1, 2].iter().cloned().sorted_by_key(|&x| x); - it::assert_equal(sc, vec![1, 2, 3, 4]); - - let v = (0..5).sorted_by_key(|&x| -x); - it::assert_equal(v, vec![4, 3, 2, 1, 0]); -} - -#[test] -fn test_multipeek() { - let nums = vec![1u8,2,3,4,5]; - - let mp = multipeek(nums.iter().map(|&x| x)); - assert_eq!(nums, mp.collect::<Vec<_>>()); - - let mut mp = multipeek(nums.iter().map(|&x| x)); - assert_eq!(mp.peek(), Some(&1)); - assert_eq!(mp.next(), Some(1)); - assert_eq!(mp.peek(), Some(&2)); - assert_eq!(mp.peek(), Some(&3)); - assert_eq!(mp.next(), Some(2)); - assert_eq!(mp.peek(), Some(&3)); - assert_eq!(mp.peek(), Some(&4)); - assert_eq!(mp.peek(), Some(&5)); - assert_eq!(mp.peek(), None); - assert_eq!(mp.next(), Some(3)); - assert_eq!(mp.next(), Some(4)); - assert_eq!(mp.peek(), Some(&5)); - assert_eq!(mp.peek(), None); - assert_eq!(mp.next(), Some(5)); - assert_eq!(mp.next(), None); - assert_eq!(mp.peek(), None); - -} - -#[test] -fn test_multipeek_reset() { - let data = [1, 2, 3, 4]; - - let mut mp = multipeek(cloned(&data)); - assert_eq!(mp.peek(), Some(&1)); - assert_eq!(mp.next(), Some(1)); - assert_eq!(mp.peek(), Some(&2)); - assert_eq!(mp.peek(), Some(&3)); - mp.reset_peek(); - assert_eq!(mp.peek(), Some(&2)); - assert_eq!(mp.next(), Some(2)); -} - -#[test] -fn test_multipeek_peeking_next() { - use it::PeekingNext; - let nums = vec![1u8,2,3,4,5,6,7]; - - let mut mp = multipeek(nums.iter().map(|&x| x)); - assert_eq!(mp.peeking_next(|&x| x != 0), Some(1)); - assert_eq!(mp.next(), Some(2)); - assert_eq!(mp.peek(), Some(&3)); - assert_eq!(mp.peek(), Some(&4)); - assert_eq!(mp.peeking_next(|&x| x == 3), Some(3)); - assert_eq!(mp.peek(), Some(&4)); - assert_eq!(mp.peeking_next(|&x| x != 4), None); - assert_eq!(mp.peeking_next(|&x| x == 4), Some(4)); - assert_eq!(mp.peek(), Some(&5)); - assert_eq!(mp.peek(), Some(&6)); - assert_eq!(mp.peeking_next(|&x| x != 5), None); - assert_eq!(mp.peek(), Some(&7)); - assert_eq!(mp.peeking_next(|&x| x == 5), Some(5)); - assert_eq!(mp.peeking_next(|&x| x == 6), Some(6)); - assert_eq!(mp.peek(), Some(&7)); - assert_eq!(mp.peek(), None); - assert_eq!(mp.next(), Some(7)); - assert_eq!(mp.peek(), None); -} - -#[test] -fn pad_using() { - it::assert_equal((0..0).pad_using(1, |_| 1), 1..2); - - let v: Vec<usize> = vec![0, 1, 2]; - let r = v.into_iter().pad_using(5, |n| n); - it::assert_equal(r, vec![0, 1, 2, 3, 4]); - - let v: Vec<usize> = vec![0, 1, 2]; - let r = v.into_iter().pad_using(1, |_| panic!()); - it::assert_equal(r, vec![0, 1, 2]); -} - -#[test] -fn group_by() { - for (ch1, sub) in &"AABBCCC".chars().group_by(|&x| x) { - for ch2 in sub { - assert_eq!(ch1, ch2); - } - } - - for (ch1, sub) in &"AAABBBCCCCDDDD".chars().group_by(|&x| x) { - for ch2 in sub { - assert_eq!(ch1, ch2); - if ch1 == 'C' { - break; - } - } - } - - let toupper = |ch: &char| ch.to_uppercase().nth(0).unwrap(); - - // try all possible orderings - for indices in permutohedron::Heap::new(&mut [0, 1, 2, 3]) { - let groups = "AaaBbbccCcDDDD".chars().group_by(&toupper); - let mut subs = groups.into_iter().collect_vec(); - - for &idx in &indices[..] { - let (key, text) = match idx { - 0 => ('A', "Aaa".chars()), - 1 => ('B', "Bbb".chars()), - 2 => ('C', "ccCc".chars()), - 3 => ('D', "DDDD".chars()), - _ => unreachable!(), - }; - assert_eq!(key, subs[idx].0); - it::assert_equal(&mut subs[idx].1, text); - } - } - - let groups = "AAABBBCCCCDDDD".chars().group_by(|&x| x); - let mut subs = groups.into_iter().map(|(_, g)| g).collect_vec(); - - let sd = subs.pop().unwrap(); - let sc = subs.pop().unwrap(); - let sb = subs.pop().unwrap(); - let sa = subs.pop().unwrap(); - for (a, b, c, d) in multizip((sa, sb, sc, sd)) { - assert_eq!(a, 'A'); - assert_eq!(b, 'B'); - assert_eq!(c, 'C'); - assert_eq!(d, 'D'); - } - - // check that the key closure is called exactly n times - { - let mut ntimes = 0; - let text = "AABCCC"; - for (_, sub) in &text.chars().group_by(|&x| { ntimes += 1; x}) { - for _ in sub { - } - } - assert_eq!(ntimes, text.len()); - } - - { - let mut ntimes = 0; - let text = "AABCCC"; - for _ in &text.chars().group_by(|&x| { ntimes += 1; x}) { - } - assert_eq!(ntimes, text.len()); - } - - { - let text = "ABCCCDEEFGHIJJKK"; - let gr = text.chars().group_by(|&x| x); - it::assert_equal(gr.into_iter().flat_map(|(_, sub)| sub), text.chars()); - } -} - -#[test] -fn group_by_lazy_2() { - let data = vec![0, 1]; - let groups = data.iter().group_by(|k| *k); - let gs = groups.into_iter().collect_vec(); - it::assert_equal(data.iter(), gs.into_iter().flat_map(|(_k, g)| g)); - - let data = vec![0, 1, 1, 0, 0]; - let groups = data.iter().group_by(|k| *k); - let mut gs = groups.into_iter().collect_vec(); - gs[1..].reverse(); - it::assert_equal(&[0, 0, 0, 1, 1], gs.into_iter().flat_map(|(_, g)| g)); - - let grouper = data.iter().group_by(|k| *k); - let mut groups = Vec::new(); - for (k, group) in &grouper { - if *k == 1 { - groups.push(group); - } - } - it::assert_equal(&mut groups[0], &[1, 1]); - - let data = vec![0, 0, 0, 1, 1, 0, 0, 2, 2, 3, 3]; - let grouper = data.iter().group_by(|k| *k); - let mut groups = Vec::new(); - for (i, (_, group)) in grouper.into_iter().enumerate() { - if i < 2 { - groups.push(group); - } else if i < 4 { - for _ in group { - } - } else { - groups.push(group); - } - } - it::assert_equal(&mut groups[0], &[0, 0, 0]); - it::assert_equal(&mut groups[1], &[1, 1]); - it::assert_equal(&mut groups[2], &[3, 3]); - - // use groups as chunks - let data = vec![0, 0, 0, 1, 1, 0, 0, 2, 2, 3, 3]; - let mut i = 0; - let grouper = data.iter().group_by(move |_| { let k = i / 3; i += 1; k }); - for (i, group) in &grouper { - match i { - 0 => it::assert_equal(group, &[0, 0, 0]), - 1 => it::assert_equal(group, &[1, 1, 0]), - 2 => it::assert_equal(group, &[0, 2, 2]), - 3 => it::assert_equal(group, &[3, 3]), - _ => unreachable!(), - } - } -} - -#[test] -fn group_by_lazy_3() { - // test consuming each group on the lap after it was produced - let data = vec![0, 0, 0, 1, 1, 0, 0, 1, 1, 2, 2]; - let grouper = data.iter().group_by(|elt| *elt); - let mut last = None; - for (key, group) in &grouper { - if let Some(gr) = last.take() { - for elt in gr { - assert!(elt != key && i32::abs(elt - key) == 1); - } - } - last = Some(group); - } -} - -#[test] -fn chunks() { - let data = vec![0, 0, 0, 1, 1, 0, 0, 2, 2, 3, 3]; - let grouper = data.iter().chunks(3); - for (i, chunk) in grouper.into_iter().enumerate() { - match i { - 0 => it::assert_equal(chunk, &[0, 0, 0]), - 1 => it::assert_equal(chunk, &[1, 1, 0]), - 2 => it::assert_equal(chunk, &[0, 2, 2]), - 3 => it::assert_equal(chunk, &[3, 3]), - _ => unreachable!(), - } - } -} - -#[test] -fn concat_empty() { - let data: Vec<Vec<()>> = Vec::new(); - assert_eq!(data.into_iter().concat(), Vec::new()) -} - -#[test] -fn concat_non_empty() { - let data = vec![vec![1,2,3], vec![4,5,6], vec![7,8,9]]; - assert_eq!(data.into_iter().concat(), vec![1,2,3,4,5,6,7,8,9]) -} - -#[test] -fn combinations() { - assert!((1..3).combinations(5).next().is_none()); - - let it = (1..3).combinations(2); - it::assert_equal(it, vec![ - vec![1, 2], - ]); - - let it = (1..5).combinations(2); - it::assert_equal(it, vec![ - vec![1, 2], - vec![1, 3], - vec![1, 4], - vec![2, 3], - vec![2, 4], - vec![3, 4], - ]); - - it::assert_equal((0..0).tuple_combinations::<(_, _)>(), <Vec<_>>::new()); - it::assert_equal((0..1).tuple_combinations::<(_, _)>(), <Vec<_>>::new()); - it::assert_equal((0..2).tuple_combinations::<(_, _)>(), vec![(0, 1)]); - - it::assert_equal((0..0).combinations(2), <Vec<Vec<_>>>::new()); - it::assert_equal((0..1).combinations(1), vec![vec![0]]); - it::assert_equal((0..2).combinations(1), vec![vec![0], vec![1]]); - it::assert_equal((0..2).combinations(2), vec![vec![0, 1]]); -} - -#[test] -fn combinations_of_too_short() { - for i in 1..10 { - assert!((0..0).combinations(i).next().is_none()); - assert!((0..i - 1).combinations(i).next().is_none()); - } -} - - -#[test] -fn combinations_zero() { - it::assert_equal((1..3).combinations(0), vec![vec![]]); -} - -#[test] -fn combinations_with_replacement() { - // Pool smaller than n - it::assert_equal((0..1).combinations_with_replacement(2), vec![vec![0, 0]]); - // Pool larger than n - it::assert_equal( - (0..3).combinations_with_replacement(2), - vec![ - vec![0, 0], - vec![0, 1], - vec![0, 2], - vec![1, 1], - vec![1, 2], - vec![2, 2], - ], - ); - // Zero size - it::assert_equal( - (0..3).combinations_with_replacement(0), - <Vec<Vec<_>>>::new(), - ); - // Empty pool - it::assert_equal( - (0..0).combinations_with_replacement(2), - <Vec<Vec<_>>>::new(), - ); -} - -#[test] -fn diff_mismatch() { - let a = vec![1, 2, 3, 4]; - let b = vec![1.0, 5.0, 3.0, 4.0]; - let b_map = b.into_iter().map(|f| f as i32); - let diff = it::diff_with(a.iter(), b_map, |a, b| *a == b); - - assert!(match diff { - Some(it::Diff::FirstMismatch(1, _, from_diff)) => - from_diff.collect::<Vec<_>>() == vec![5, 3, 4], - _ => false, - }); -} - -#[test] -fn diff_longer() { - let a = vec![1, 2, 3, 4]; - let b = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]; - let b_map = b.into_iter().map(|f| f as i32); - let diff = it::diff_with(a.iter(), b_map, |a, b| *a == b); - - assert!(match diff { - Some(it::Diff::Longer(_, remaining)) => - remaining.collect::<Vec<_>>() == vec![5, 6], - _ => false, - }); -} - -#[test] -fn diff_shorter() { - let a = vec![1, 2, 3, 4]; - let b = vec![1.0, 2.0]; - let b_map = b.into_iter().map(|f| f as i32); - let diff = it::diff_with(a.iter(), b_map, |a, b| *a == b); - - assert!(match diff { - Some(it::Diff::Shorter(len, _)) => len == 2, - _ => false, - }); -} - -#[test] -fn minmax() { - use std::cmp::Ordering; - use it::MinMaxResult; - - // A peculiar type: Equality compares both tuple items, but ordering only the - // first item. This is so we can check the stability property easily. - #[derive(Clone, Debug, PartialEq, Eq)] - struct Val(u32, u32); - - impl PartialOrd<Val> for Val { - fn partial_cmp(&self, other: &Val) -> Option<Ordering> { - self.0.partial_cmp(&other.0) - } - } - - impl Ord for Val { - fn cmp(&self, other: &Val) -> Ordering { - self.0.cmp(&other.0) - } - } - - assert_eq!(None::<Option<u32>>.iter().minmax(), MinMaxResult::NoElements); - - assert_eq!(Some(1u32).iter().minmax(), MinMaxResult::OneElement(&1)); - - let data = vec![Val(0, 1), Val(2, 0), Val(0, 2), Val(1, 0), Val(2, 1)]; - - let minmax = data.iter().minmax(); - assert_eq!(minmax, MinMaxResult::MinMax(&Val(0, 1), &Val(2, 1))); - - let (min, max) = data.iter().minmax_by_key(|v| v.1).into_option().unwrap(); - assert_eq!(min, &Val(2, 0)); - assert_eq!(max, &Val(0, 2)); - - let (min, max) = data.iter().minmax_by(|x, y| x.1.cmp(&y.1)).into_option().unwrap(); - assert_eq!(min, &Val(2, 0)); - assert_eq!(max, &Val(0, 2)); -} - -#[test] -fn format() { - let data = [0, 1, 2, 3]; - let ans1 = "0, 1, 2, 3"; - let ans2 = "0--1--2--3"; - - let t1 = format!("{}", data.iter().format(", ")); - assert_eq!(t1, ans1); - let t2 = format!("{:?}", data.iter().format("--")); - assert_eq!(t2, ans2); - - let dataf = [1.1, 2.71828, -22.]; - let t3 = format!("{:.2e}", dataf.iter().format(", ")); - assert_eq!(t3, "1.10e0, 2.72e0, -2.20e1"); -} - -#[test] -fn while_some() { - let ns = (1..10).map(|x| if x % 5 != 0 { Some(x) } else { None }) - .while_some(); - it::assert_equal(ns, vec![1, 2, 3, 4]); -} - -#[allow(deprecated)] -#[test] -fn fold_while() { - let mut iterations = 0; - let vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - let sum = vec.into_iter().fold_while(0, |acc, item| { - iterations += 1; - let new_sum = acc.clone() + item; - if new_sum <= 20 { - FoldWhile::Continue(new_sum) - } else { - FoldWhile::Done(acc) - } - }).into_inner(); - assert_eq!(iterations, 6); - assert_eq!(sum, 15); -} - -#[test] -fn tree_fold1() { - let x = [ - "", - "0", - "0 1 x", - "0 1 x 2 x", - "0 1 x 2 3 x x", - "0 1 x 2 3 x x 4 x", - "0 1 x 2 3 x x 4 5 x x", - "0 1 x 2 3 x x 4 5 x 6 x x", - "0 1 x 2 3 x x 4 5 x 6 7 x x x", - "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 x", - "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x x", - "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 x x", - "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 11 x x x", - "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 11 x x 12 x x", - "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 11 x x 12 13 x x x", - "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 11 x x 12 13 x 14 x x x", - "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 11 x x 12 13 x 14 15 x x x x", - ]; - for (i, &s) in x.iter().enumerate() { - let expected = if s == "" { None } else { Some(s.to_string()) }; - let num_strings = (0..i).map(|x| x.to_string()); - let actual = num_strings.tree_fold1(|a, b| format!("{} {} x", a, b)); - assert_eq!(actual, expected); - } -} diff --git a/vendor/itertools-0.8.2/tests/tuples.rs b/vendor/itertools-0.8.2/tests/tuples.rs deleted file mode 100644 index 07dba57fe6..0000000000 --- a/vendor/itertools-0.8.2/tests/tuples.rs +++ /dev/null @@ -1,88 +0,0 @@ -extern crate itertools; - -use itertools::Itertools; - -#[test] -fn tuples() { - let v = [1, 2, 3, 4, 5]; - let mut iter = v.iter().cloned().tuples(); - assert_eq!(Some((1,)), iter.next()); - assert_eq!(Some((2,)), iter.next()); - assert_eq!(Some((3,)), iter.next()); - assert_eq!(Some((4,)), iter.next()); - assert_eq!(Some((5,)), iter.next()); - assert_eq!(None, iter.next()); - assert_eq!(None, iter.into_buffer().next()); - - let mut iter = v.iter().cloned().tuples(); - assert_eq!(Some((1, 2)), iter.next()); - assert_eq!(Some((3, 4)), iter.next()); - assert_eq!(None, iter.next()); - itertools::assert_equal(vec![5], iter.into_buffer()); - - let mut iter = v.iter().cloned().tuples(); - assert_eq!(Some((1, 2, 3)), iter.next()); - assert_eq!(None, iter.next()); - itertools::assert_equal(vec![4, 5], iter.into_buffer()); - - let mut iter = v.iter().cloned().tuples(); - assert_eq!(Some((1, 2, 3, 4)), iter.next()); - assert_eq!(None, iter.next()); - itertools::assert_equal(vec![5], iter.into_buffer()); -} - -#[test] -fn tuple_windows() { - let v = [1, 2, 3, 4, 5]; - - let mut iter = v.iter().cloned().tuple_windows(); - assert_eq!(Some((1,)), iter.next()); - assert_eq!(Some((2,)), iter.next()); - assert_eq!(Some((3,)), iter.next()); - - let mut iter = v.iter().cloned().tuple_windows(); - assert_eq!(Some((1, 2)), iter.next()); - assert_eq!(Some((2, 3)), iter.next()); - assert_eq!(Some((3, 4)), iter.next()); - assert_eq!(Some((4, 5)), iter.next()); - assert_eq!(None, iter.next()); - - let mut iter = v.iter().cloned().tuple_windows(); - assert_eq!(Some((1, 2, 3)), iter.next()); - assert_eq!(Some((2, 3, 4)), iter.next()); - assert_eq!(Some((3, 4, 5)), iter.next()); - assert_eq!(None, iter.next()); - - let mut iter = v.iter().cloned().tuple_windows(); - assert_eq!(Some((1, 2, 3, 4)), iter.next()); - assert_eq!(Some((2, 3, 4, 5)), iter.next()); - assert_eq!(None, iter.next()); - - let v = [1, 2, 3]; - let mut iter = v.iter().cloned().tuple_windows::<(_, _, _, _)>(); - assert_eq!(None, iter.next()); -} - -#[test] -fn next_tuple() { - let v = [1, 2, 3, 4, 5]; - let mut iter = v.iter(); - assert_eq!(iter.next_tuple().map(|(&x, &y)| (x, y)), Some((1, 2))); - assert_eq!(iter.next_tuple().map(|(&x, &y)| (x, y)), Some((3, 4))); - assert_eq!(iter.next_tuple::<(_, _)>(), None); -} - -#[test] -fn collect_tuple() { - let v = [1, 2]; - let iter = v.iter().cloned(); - assert_eq!(iter.collect_tuple(), Some((1, 2))); - - let v = [1]; - let iter = v.iter().cloned(); - assert_eq!(iter.collect_tuple::<(_, _)>(), None); - - let v = [1, 2, 3]; - let iter = v.iter().cloned(); - assert_eq!(iter.collect_tuple::<(_, _)>(), None); -} diff --git a/vendor/itertools-0.8.2/tests/zip.rs b/vendor/itertools-0.8.2/tests/zip.rs deleted file mode 100644 index c5c51899b8..0000000000 --- a/vendor/itertools-0.8.2/tests/zip.rs +++ /dev/null @@ -1,65 +0,0 @@ -extern crate itertools; - -use itertools::Itertools; -use itertools::EitherOrBoth::{Both, Left, Right}; -use itertools::free::zip_eq; - -#[test] -fn zip_longest_fused() { - let a = [Some(1), None, Some(3), Some(4)]; - let b = [1, 2, 3]; - - let unfused = a.iter().batching(|it| *it.next().unwrap()) - .zip_longest(b.iter().cloned()); - itertools::assert_equal(unfused, - vec![Both(1, 1), Right(2), Right(3)]); -} - -#[test] -fn test_zip_longest_size_hint() { - let c = (1..10).cycle(); - let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; - let v2 = &[10, 11, 12]; - - assert_eq!(c.zip_longest(v.iter()).size_hint(), (std::usize::MAX, None)); - - assert_eq!(v.iter().zip_longest(v2.iter()).size_hint(), (10, Some(10))); -} - -#[test] -fn test_double_ended_zip_longest() { - let xs = [1, 2, 3, 4, 5, 6]; - let ys = [1, 2, 3, 7]; - let a = xs.iter().map(|&x| x); - let b = ys.iter().map(|&x| x); - let mut it = a.zip_longest(b); - assert_eq!(it.next(), Some(Both(1, 1))); - assert_eq!(it.next(), Some(Both(2, 2))); - assert_eq!(it.next_back(), Some(Left(6))); - assert_eq!(it.next_back(), Some(Left(5))); - assert_eq!(it.next_back(), Some(Both(4, 7))); - assert_eq!(it.next(), Some(Both(3, 3))); - assert_eq!(it.next(), None); -} - - -#[should_panic] -#[test] -fn zip_eq_panic1() -{ - let a = [1, 2]; - let b = [1, 2, 3]; - - zip_eq(&a, &b).count(); -} - -#[should_panic] -#[test] -fn zip_eq_panic2() -{ - let a: [i32; 0] = []; - let b = [1, 2, 3]; - - zip_eq(&a, &b).count(); -} - diff --git a/vendor/libc/.cargo-checksum.json b/vendor/libc/.cargo-checksum.json index 38ea3c65db..8cf4eba1bc 100644 --- a/vendor/libc/.cargo-checksum.json +++ b/vendor/libc/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"CONTRIBUTING.md":"752eea5a703d11b485c6b5f195f51bd2c79aa5159b619ce09555c779e1fb586b","Cargo.toml":"aad61c58f04e78be520769d8927ab4c121a6536f532b159be1b706550fcd0234","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"a8d47ff51ca256f56a8932dba07660672dbfe3004257ca8de708aac1415937a1","README.md":"8228847944f1332882fbb00275b6f30e4a8aad08a13569c25d52cac012cc2a47","build.rs":"8e0e8d33cc9e7c25cde75c2b502420f943266a681024169f94084774b422681d","rustfmt.toml":"eaa2ea84fc1ba0359b77680804903e07bb38d257ab11986b95b158e460f787b2","src/fixed_width_ints.rs":"34c60f12ec5eeb90f13ec3b954427532111c2446e69617616a97aefc1086a9f1","src/fuchsia/aarch64.rs":"378776a9e40766154a54c94c2a7b4675b5c302a38e6e42da99e67bfbaee60e56","src/fuchsia/align.rs":"ae1cf8f011a99737eabeb14ffff768e60f13b13363d7646744dbb0f443dab3d6","src/fuchsia/mod.rs":"520300ff260d377930f2f456135ec9a3ac7740a949ce7bf5269c0dc60d56c0df","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":"e0ebe1040b8ff87c52d581f96234291a6380ebe3af3088c4f6ff748fbd7d2a7a","src/unix/bsd/freebsdlike/dragonfly/errno.rs":"8295b8bb0dfd38d2cdb4d9192cdeeb534cc6c3b208170e64615fa3e0edb3e578","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"1466715589ed18b66789d60904e8258b20d7783a6f3bf72f775617bc0d9373d8","src/unix/bsd/freebsdlike/freebsd/aarch64.rs":"2a215bd6136b8617aacedf9be738ccee94da9d29b418e9a78101d6291c182352","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":"0821543bf2073cb3dc46157e47140caa30704e062b23099d52bf80cb56e25321","src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd13/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs":"21416cad3e76f53d10d0c73840469290aa80c2d92c773307a1ca92485d3c0e13","src/unix/bsd/freebsdlike/freebsd/freebsd13/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/mod.rs":"0ee5530ddde5690cdc6f91acca86ce74c37ec06886418c34b201c154fd2c9e41","src/unix/bsd/freebsdlike/freebsd/powerpc.rs":"9ca3f82f88974e6db5569f2d76a5a3749b248a31747a6c0da5820492bdfeca42","src/unix/bsd/freebsdlike/freebsd/powerpc64.rs":"2dae3ecc87eac3b11657aa98915def55fc4b5c0de11fe26aae23329a54628a9a","src/unix/bsd/freebsdlike/freebsd/x86.rs":"c5005e3249eb7c93cfbac72a9e9272320d80ce7983da990ceb05a447f59a02c5","src/unix/bsd/freebsdlike/freebsd/x86_64/align.rs":"0e1f69a88fca1c32874b1daf5db3d446fefbe518dca497f096cc9168c39dde70","src/unix/bsd/freebsdlike/freebsd/x86_64/mod.rs":"c3a0111252e201c172b99e7d9cbee4cf088d3dd47995110e819f04276bccd198","src/unix/bsd/freebsdlike/mod.rs":"77763a8dfe2d31c78ee7c3e64001ceee6d4ba34cc77b7fd4fdde153e5abbbeb8","src/unix/bsd/mod.rs":"2fed08973739d7f6a7412b204724af64b1a915c712689c250cf9a08263ba05ff","src/unix/bsd/netbsdlike/mod.rs":"4e9da54e541773c7ad4cca9dade1df00f28f2fdac3f8df5957f4c74b7e082344","src/unix/bsd/netbsdlike/netbsd/aarch64.rs":"65dcb58d11e8d8028401a9d07ca3eb4cb4f053e04249cc877353449d84ccc4cb","src/unix/bsd/netbsdlike/netbsd/arm.rs":"58cdbb70b0d6f536551f0f3bb3725d2d75c4690db12c26c034e7d6ec4a924452","src/unix/bsd/netbsdlike/netbsd/mod.rs":"96edbcf448b89c991c9254c194232322dce69fb8050bab9f9741f5aecb2104ea","src/unix/bsd/netbsdlike/netbsd/powerpc.rs":"ee7ff5d89d0ed22f531237b5059aa669df93a3b5c489fa641465ace8d405bf41","src/unix/bsd/netbsdlike/netbsd/sparc64.rs":"9489f4b3e4566f43bb12dfb92238960613dac7f6a45cc13068a8d152b902d7d9","src/unix/bsd/netbsdlike/netbsd/x86.rs":"20692320e36bfe028d1a34d16fe12ca77aa909cb02bda167376f98f1a09aefe7","src/unix/bsd/netbsdlike/netbsd/x86_64.rs":"1afe5ef46b14397cdd68664b5b232e4f5b035b6db1d4cf411c899d51ebca9f30","src/unix/bsd/netbsdlike/openbsd/aarch64.rs":"dd91931d373b7ecaf6e2de25adadee10d16fa9b12c2cbacdff3eb291e1ba36af","src/unix/bsd/netbsdlike/openbsd/mod.rs":"9a9878e70ee8765d95cb1b010e39d74004278ca6da58fb82354f69752a84c926","src/unix/bsd/netbsdlike/openbsd/sparc64.rs":"d04fd287afbaa2c5df9d48c94e8374a532a3ba491b424ddf018270c7312f4085","src/unix/bsd/netbsdlike/openbsd/x86.rs":"6f7f5c4fde2a2259eb547890cbd86570cea04ef85347d7569e94e679448bec87","src/unix/bsd/netbsdlike/openbsd/x86_64.rs":"d31db31630289c85af3339dbe357998a21ca584cbae31607448fe2cf7675a4e1","src/unix/haiku/b32.rs":"69ae47fc52c6880e85416b4744500d5655c9ec6131cb737f3b649fceaadce15a","src/unix/haiku/b64.rs":"73e64db09275a8da8d50a13cce2cfa2b136036ddf3a930d2939f337fc995900b","src/unix/haiku/mod.rs":"912969bc1d59a6cec74de3140982b7f0b69e74d44936646587f1c8820be7c0fe","src/unix/haiku/native.rs":"44855f52906f607de137fc4baa8c6b1b9a26baaa666f25d5f7a7ec5e017c8be6","src/unix/haiku/x86_64.rs":"3ec3aeeb7ed208b8916f3e32d42bfd085ff5e16936a1a35d9a52789f043b7237","src/unix/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/unix/hermit/mod.rs":"859814f5df89e28fd4b345db399d181e11e7ed413841b6ff703a1fcbdbf013ae","src/unix/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/unix/linux_like/android/b32/arm.rs":"433c1530f602cc5ed26610c58055dde0c4ceea5e00150063b24ddc60768332a4","src/unix/linux_like/android/b32/mod.rs":"d971b98530a96f5892f98e1edc3133cf278d1b3939d77ab0a27a6323e0961715","src/unix/linux_like/android/b32/x86/align.rs":"812914e4241df82e32b12375ca3374615dc3a4bdd4cf31f0423c5815320c0dab","src/unix/linux_like/android/b32/x86/mod.rs":"8388bd3a0fcb5636bf965eee6dc95ae6860b85a2b555b387c868aa4d4e01ec89","src/unix/linux_like/android/b64/aarch64/align.rs":"2179c3b1608fa4bf68840482bfc2b2fa3ee2faf6fcae3770f9e505cddca35c7b","src/unix/linux_like/android/b64/aarch64/mod.rs":"8fe667d2b14abc5ac8aad32e16c3da24350471d8156eaea9ab4989f73dd9f9fc","src/unix/linux_like/android/b64/mod.rs":"d7bbbadafdb2cb2ff8e9cde3d89a03b9facaabb6b2d45705225d3ece1c5cce37","src/unix/linux_like/android/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/android/b64/x86_64/mod.rs":"06b22dc184e85a988ab969c75cadc52b9878faeab0eb9d21215878c95fe07c19","src/unix/linux_like/android/mod.rs":"8688204b3236db28b66ff0f1de5320f47ec5c1ef5395dddcc9df025a8d78630a","src/unix/linux_like/emscripten/align.rs":"86c95cbed7a7161b1f23ee06843e7b0e2340ad92b2cb86fe2a8ef3e0e8c36216","src/unix/linux_like/emscripten/mod.rs":"6ef97140ca6fb24125fdd0aacb986ef785aa21993229660d7f703f8875ebfe49","src/unix/linux_like/emscripten/no_align.rs":"0128e4aa721a9902754828b61b5ec7d8a86619983ed1e0544a85d35b1051fad6","src/unix/linux_like/linux/align.rs":"213e70ebed2703e14a9cf17666b21ecbf180b7bff7fa22fdbb36dbbd52df326d","src/unix/linux_like/linux/arch/generic/mod.rs":"ff1fe8fad4ea15d9bec3db25efcfcb4939190c5189f86cfa4d05825aa8c10956","src/unix/linux_like/linux/arch/mips/mod.rs":"e4a980b002105aaa057eb6568e1e2c6168ade5c00e13a31ef67e316ddffdb900","src/unix/linux_like/linux/arch/mod.rs":"466a29622e47c6c7f1500682b2eb17f5566dd81b322cd6348f0fdd355cec593a","src/unix/linux_like/linux/arch/powerpc/mod.rs":"1789eb5b41f75c29239795124a4a7cdcf7c8d213b88cf581b2f5bda08d7cf15b","src/unix/linux_like/linux/arch/sparc/mod.rs":"ded708124ee610267d011dee31fb02d1ec697c334aa822776ec95a7ddf6fc541","src/unix/linux_like/linux/gnu/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/gnu/b32/arm/align.rs":"3fed009dc9af3cc81be7087da9d2d7d1f39845e4497e290259c5cdbae25f039d","src/unix/linux_like/linux/gnu/b32/arm/mod.rs":"07adf9f4b96854062db518aaf08521fde0ad4a21a5c049efccba437bd97b2b5a","src/unix/linux_like/linux/gnu/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/gnu/b32/mips/mod.rs":"1cb5c0c9df3af2bbe131a91593583259fac9118931744c8435e197a394eb0462","src/unix/linux_like/linux/gnu/b32/mod.rs":"794dbcbae7dae8fd6b0b814573243197ceb532b56ef0772ad86b4b401478fcd9","src/unix/linux_like/linux/gnu/b32/powerpc.rs":"0cd7348badb9c4f8a0db31a2503b30c456a2bfcc7a0e5919762b1e12f912c5ad","src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs":"ee5145a383386b716605a8d1ff3df212d418aae1aa1f37d2307d4f9cd1a08e99","src/unix/linux_like/linux/gnu/b32/sparc/align.rs":"21adbed27df73e2d1ed934aaf733a643003d7baf2bde9c48ea440895bcca6d41","src/unix/linux_like/linux/gnu/b32/sparc/mod.rs":"1bcec269a8416ccc48a384ca5765eaaa23f30f39f32311f50008ef4eeadafb2f","src/unix/linux_like/linux/gnu/b32/x86/align.rs":"e4bafdc4a519a7922a81b37a62bbfd1177a2f620890eef8f1fbc47162e9eb413","src/unix/linux_like/linux/gnu/b32/x86/mod.rs":"5317dbf2323577b89370bbee3894882b89d8333176db4f7b271ddc2f036ef43c","src/unix/linux_like/linux/gnu/b64/aarch64/align.rs":"2179c3b1608fa4bf68840482bfc2b2fa3ee2faf6fcae3770f9e505cddca35c7b","src/unix/linux_like/linux/gnu/b64/aarch64/ilp32.rs":"21a21503ef2e095f4371044915d4bfb07a8578011cb5c713cd9f45947b0b5730","src/unix/linux_like/linux/gnu/b64/aarch64/lp64.rs":"e78c3cd197f44832338b414d1a9bc0d194f44c74db77bd7bf830c1fff62b2690","src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs":"c3730792dabcc166d8fd22929ef2633d49bc626875382dfcd401e8e125fb7a84","src/unix/linux_like/linux/gnu/b64/mips64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/mips64/mod.rs":"68bcb71bbfccb4e8648948e494366d94767ce96f36daab9c1329375cdd32a459","src/unix/linux_like/linux/gnu/b64/mod.rs":"6336065423c26b59681fd2ce77f1117ea36af13e163fdadaefd108bd8191e8c8","src/unix/linux_like/linux/gnu/b64/powerpc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs":"dbb8905e363ed4a2dfb984554ad9b6389d27f6a2d599ec2d80e38a6c7551a019","src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs":"5b982c41097f4f91adcb0968290afeccb27dce1695a261c964d34ef85df87cf4","src/unix/linux_like/linux/gnu/b64/s390x.rs":"a9484dfd3c7ca1174537957bef997c3ba7ea41989cdf61ede22b1bbc45a667bf","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":"a040250bc2b4b2831ae2cad6f1abf3dc73e6015c4f570abf21350e220e898338","src/unix/linux_like/linux/gnu/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/mod.rs":"8f282fe98fe7fcdae158aad41b2a9e6130c130c7a041fe13919357bf7b548057","src/unix/linux_like/linux/musl/b32/arm/align.rs":"3e8ac052c1043764776b54c93ba4260e061df998631737a897d9d47d54f7b80c","src/unix/linux_like/linux/musl/b32/arm/mod.rs":"6255abe2ee04986832d12b7b2190589580f2a43e9bfb285b32b5747227f62727","src/unix/linux_like/linux/musl/b32/hexagon.rs":"a8811791809672be8338e6e27d1c4fcf383c2f26585be8bf9ab2923b219de032","src/unix/linux_like/linux/musl/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/musl/b32/mips/mod.rs":"b9e9ff42363ebbb884ddf6445129ec4164471df45846874fc08f5f458e659254","src/unix/linux_like/linux/musl/b32/mod.rs":"8ede3985e6243882814ce91e8ce543e7edbafc0cee5932816072b6f14207a671","src/unix/linux_like/linux/musl/b32/powerpc.rs":"4592dc5f1f2fe888dfef85fa862d42d168e73a2c6f4fc052b58287d0f4d4ffcd","src/unix/linux_like/linux/musl/b32/x86/align.rs":"08e77fbd7435d7dec2ff56932433bece3f02e47ce810f89004a275a86d39cbe1","src/unix/linux_like/linux/musl/b32/x86/mod.rs":"a19a8decfab185af3cebd34aae4b15082e7552be573904b8c1a3f0c0e493ef34","src/unix/linux_like/linux/musl/b64/aarch64/align.rs":"798a9229d70ce235394f2dd625f6c4c1e10519a94382dc5b091952b638ae2928","src/unix/linux_like/linux/musl/b64/aarch64/mod.rs":"a73035c6d9b776f13b839008e15c04c2c53455571efd06664affcb047e457112","src/unix/linux_like/linux/musl/b64/mips64.rs":"2744895451f3a777fbe54f7f2695be53310b965fd62084c9b7e9121c7fe28346","src/unix/linux_like/linux/musl/b64/mod.rs":"d18abc0aeba2e26342bf3416a4dba0836db2bb0ee013b0a39629475cf8640289","src/unix/linux_like/linux/musl/b64/powerpc64.rs":"e5a55525b42493923956d668f978fb45e22d51deea00ce5edbfddf76ff19c741","src/unix/linux_like/linux/musl/b64/s390x.rs":"03dfec6794d93cb31a7c52b2d53a0973755168f91f8fa437cc5dbd54882c8ee7","src/unix/linux_like/linux/musl/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/musl/b64/x86_64/mod.rs":"0dd168f5a6881f32e5239fb312b23cf137b800d0ff323286a92c8a2c382b5456","src/unix/linux_like/linux/musl/mod.rs":"55ccd71342276ccb4c441a4bc2772aebfd163af299669b658c6c8c6add331ec3","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":"1e3bf809508b5872949136859bf48ddf58b7d24ae9f0b663e79f0efd1aaeb6a6","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":"fa4102d9a596d90de604ce2962b0e64f184dfbf10552a4c3ecf28f12d4704379","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":"a2877679fef0f14f54a89ccbc41fb02f0c25bf6e536f9eb2cb2fa437e1d3f739","src/unix/linux_like/linux/uclibc/mod.rs":"82d504d3aa12cb0f7933980f81c4708fa6e070d4c57efdf407f2de05b71bc06d","src/unix/linux_like/linux/uclibc/no_align.rs":"3f28637046524618adaa1012e26cb7ffe94b9396e6b518cccdc69d59f274d709","src/unix/linux_like/linux/uclibc/x86_64/l4re.rs":"024eba5753e852dbdd212427351affe7e83f9916c1864bce414d7aa2618f192e","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":"0a97d43fdce7f9bd57a0b47d770867f4e234eba602adc9ef993ed02a182276f2","src/unix/mod.rs":"6b2b57833e37cd3231944696c8216eb587a2a68069346150cf321153eaf04d03","src/unix/newlib/aarch64/mod.rs":"bb269c1468a9676442554600e87417079a787fe6220dfc23b3109639259e8710","src/unix/newlib/align.rs":"28aaf87fafbc6b312622719d472d8cf65f9e5467d15339df5f73e66d8502b28a","src/unix/newlib/arm/mod.rs":"c71be856bfd7f576b2db28af9f680211cbe6c1cac7d537bbc8020b39591af07c","src/unix/newlib/espidf/mod.rs":"c198cb4beccdab483be61c102da74dc51ac80f766797e33021f3110394ed5a3d","src/unix/newlib/mod.rs":"d7271c13748be08305d36f9af6f41f6950a7a1d6d4382149194a35d5fe2090de","src/unix/newlib/no_align.rs":"e0743b2179495a9514bc3a4d1781e492878c4ec834ee0085d0891dd1712e82fb","src/unix/newlib/powerpc/mod.rs":"2d0f7af28b47f7a2a6c210ebd1c1f33ed8eac62e56b5af2b856de2ad3fdc5187","src/unix/no_align.rs":"c06e95373b9088266e0b14bba0954eef95f93fb2b01d951855e382d22de78e53","src/unix/redox/mod.rs":"267a413e63dbdcaed6e758f9a5c10bd00178ed76c7b3527e8e984341f617d3a5","src/unix/solarish/compat.rs":"b07a5bfac925eb012003a459ba6bddbd3bfa9c44b3394da2ac5a602e54beae9c","src/unix/solarish/illumos.rs":"7d8f47fd37880715b449723688aaee568785325a46f1c360a05bdca13252278e","src/unix/solarish/mod.rs":"080e0cf03b50874ba9d5082b314eabb0d253532dc4b13d8af095a0c78e0fba84","src/unix/solarish/solaris.rs":"65b005453aefa9b9d4fc860fe77cfec80d8c97a51342b15daf55fc3e808bb384","src/unix/solarish/x86_64.rs":"9d761573bdccbdd1ac61da571f7e96b5374df70241d9b72d45a069611f495085","src/vxworks/aarch64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/arm.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/mod.rs":"aea3da66f2140f2a82dfc9c58f6e6531d2dd9c15ea696e0f95a0d4a2a187b5b6","src/vxworks/powerpc.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/powerpc64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/x86.rs":"552f007f38317620b23889cb7c49d1d115841252439060122f52f434fbc6e5ba","src/vxworks/x86_64.rs":"018d92be3ad628a129eff9f2f5dfbc0883d8b8e5f2fa917b900a7f98ed6b514a","src/wasi.rs":"2c945bce3ddd26bf20ff03fb4192c9c3f625f1308a479c5cb4bd4510a892629a","src/windows/gnu/align.rs":"b2c13ec1b9f3b39a75c452c80c951dff9d0215e31d77e883b4502afb31794647","src/windows/gnu/mod.rs":"3c8c7edb7cdf5d0c44af936db2a94869585c69dfabeef30571b4f4e38375767a","src/windows/mod.rs":"1cd9223293255b994814487e28d9979fb8ebef4538a236c1aa47fdc166a149cc","src/windows/msvc/mod.rs":"860dc98245039bc3aa5782ef2b5798d009ea6655bd27a63f244be2206d2cb47f","src/windows/msvc/x86_64.rs":"25d35a5ba8e19569a5bed573dcf8c82f7ce53da7c91941f9ceda6fe86cab1088","tests/const_fn.rs":"cb75a1f0864f926aebe79118fc34d51a0d1ade2c20a394e7774c7e545f21f1f4"},"package":"dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6"} \ No newline at end of file +{"files":{"CONTRIBUTING.md":"752eea5a703d11b485c6b5f195f51bd2c79aa5159b619ce09555c779e1fb586b","Cargo.toml":"d6f6253f05d207b6c676e5647b31ad0ca3f05da3ac05db47f81d4ebd901ba22f","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"a8d47ff51ca256f56a8932dba07660672dbfe3004257ca8de708aac1415937a1","README.md":"8228847944f1332882fbb00275b6f30e4a8aad08a13569c25d52cac012cc2a47","build.rs":"a71b92db5077b33af4ee6f1de33574ac33c2b292840eddbe3f7cce37f1fb16b9","rustfmt.toml":"eaa2ea84fc1ba0359b77680804903e07bb38d257ab11986b95b158e460f787b2","src/fixed_width_ints.rs":"34c60f12ec5eeb90f13ec3b954427532111c2446e69617616a97aefc1086a9f1","src/fuchsia/aarch64.rs":"378776a9e40766154a54c94c2a7b4675b5c302a38e6e42da99e67bfbaee60e56","src/fuchsia/align.rs":"ae1cf8f011a99737eabeb14ffff768e60f13b13363d7646744dbb0f443dab3d6","src/fuchsia/mod.rs":"520300ff260d377930f2f456135ec9a3ac7740a949ce7bf5269c0dc60d56c0df","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":"e92c56b42f1bd1b9e66be2a9b73aca6ba29024b9bd17c16f327dfbe8831e3f86","src/macros.rs":"c1a299d5327ba033f079388f8ac8a44848f9aeff6a72e9be6dfa70f4769cc619","src/psp.rs":"dd31aabd46171d474ec5828372e28588935120e7355c90c105360d8fa9264c1c","src/sgx.rs":"16a95cdefc81c5ee00d8353a60db363c4cc3e0f75abcd5d0144723f2a306ed1b","src/solid/aarch64.rs":"8cdae0cc37c43dabd4253a534e700bec6b6a57293c0c8e36c9ce16675d16799a","src/solid/arm.rs":"852b58a0837fde089cb9b5af131bf653daeb8c726f7540032756db8b7d4f8149","src/solid/mod.rs":"98dc29c3e5773318ba258a4a2b7407f25aa52d40885a0024fbe43676fe54d14b","src/switch.rs":"9da3dd39b3de45a7928789926e8572d00e1e11a39e6f7289a1349aadce90edba","src/unix/align.rs":"2cdc7c826ef7ae61f5171c5ae8c445a743d86f1a7f2d9d7e4ceeec56d6874f65","src/unix/bsd/apple/b32/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b32/mod.rs":"2546ad3eb6aecb95f916648bc63264117c92b4b4859532b34cb011e4c75a5a72","src/unix/bsd/apple/b64/aarch64/align.rs":"f0c321265dd7671f16106b84951ac7dd77ed2e65c6623cbf2d29e76531984770","src/unix/bsd/apple/b64/aarch64/mod.rs":"44c217a4f263afe7a97435de9323d20a96c37836f899ca0925306d4b7e073c27","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":"8c87c5855038aae5d433c8f5eb3b29b0a175879a0245342b3bfd83bdf4cfd936","src/unix/bsd/apple/mod.rs":"96f101bdab46a9f0a5249a8143d4a9def055284a0c2bd62bce15532a5bed428c","src/unix/bsd/freebsdlike/dragonfly/errno.rs":"8295b8bb0dfd38d2cdb4d9192cdeeb534cc6c3b208170e64615fa3e0edb3e578","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"6ea4129eb5d6da5c09f8cf3692b5e7716f058b48d1e8c61115691709eda7ce51","src/unix/bsd/freebsdlike/freebsd/aarch64.rs":"2a215bd6136b8617aacedf9be738ccee94da9d29b418e9a78101d6291c182352","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":"bf0a994e2079b8aad9da5efd3a3b9a7194a53ae60887a25c57964fb68499e847","src/unix/bsd/freebsdlike/freebsd/freebsd12/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs":"295b3e3b67394f731d4e88d169e3d3d1d80026b99898745cd0d1d163f085ff61","src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd13/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs":"98f6af2021b434f9c3197094312b457774381220f31a22c3b15b1fe8a60cb365","src/unix/bsd/freebsdlike/freebsd/freebsd13/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/mod.rs":"6b825079ffe3f9aec6e78ea6b50acedcb91a4e1312d721105b7f8b1555f254df","src/unix/bsd/freebsdlike/freebsd/powerpc.rs":"9ca3f82f88974e6db5569f2d76a5a3749b248a31747a6c0da5820492bdfeca42","src/unix/bsd/freebsdlike/freebsd/powerpc64.rs":"2dae3ecc87eac3b11657aa98915def55fc4b5c0de11fe26aae23329a54628a9a","src/unix/bsd/freebsdlike/freebsd/x86.rs":"c5005e3249eb7c93cfbac72a9e9272320d80ce7983da990ceb05a447f59a02c5","src/unix/bsd/freebsdlike/freebsd/x86_64/align.rs":"0e1f69a88fca1c32874b1daf5db3d446fefbe518dca497f096cc9168c39dde70","src/unix/bsd/freebsdlike/freebsd/x86_64/mod.rs":"c3a0111252e201c172b99e7d9cbee4cf088d3dd47995110e819f04276bccd198","src/unix/bsd/freebsdlike/mod.rs":"98d322b22050a80636841287d9ed12549a2004a9dbe151763e5b1270f5e73ea3","src/unix/bsd/mod.rs":"2fed08973739d7f6a7412b204724af64b1a915c712689c250cf9a08263ba05ff","src/unix/bsd/netbsdlike/mod.rs":"4e9da54e541773c7ad4cca9dade1df00f28f2fdac3f8df5957f4c74b7e082344","src/unix/bsd/netbsdlike/netbsd/aarch64.rs":"65dcb58d11e8d8028401a9d07ca3eb4cb4f053e04249cc877353449d84ccc4cb","src/unix/bsd/netbsdlike/netbsd/arm.rs":"58cdbb70b0d6f536551f0f3bb3725d2d75c4690db12c26c034e7d6ec4a924452","src/unix/bsd/netbsdlike/netbsd/mod.rs":"f6de6981382af87518e4a5b6d26c2ea551ed74640dd7166107a824af30ced243","src/unix/bsd/netbsdlike/netbsd/powerpc.rs":"ee7ff5d89d0ed22f531237b5059aa669df93a3b5c489fa641465ace8d405bf41","src/unix/bsd/netbsdlike/netbsd/sparc64.rs":"9489f4b3e4566f43bb12dfb92238960613dac7f6a45cc13068a8d152b902d7d9","src/unix/bsd/netbsdlike/netbsd/x86.rs":"20692320e36bfe028d1a34d16fe12ca77aa909cb02bda167376f98f1a09aefe7","src/unix/bsd/netbsdlike/netbsd/x86_64.rs":"1afe5ef46b14397cdd68664b5b232e4f5b035b6db1d4cf411c899d51ebca9f30","src/unix/bsd/netbsdlike/openbsd/aarch64.rs":"dd91931d373b7ecaf6e2de25adadee10d16fa9b12c2cbacdff3eb291e1ba36af","src/unix/bsd/netbsdlike/openbsd/mod.rs":"47aaab2bd8238e937112ff17e8262945c8e5865d5e696f218b11c1da59830808","src/unix/bsd/netbsdlike/openbsd/sparc64.rs":"d04fd287afbaa2c5df9d48c94e8374a532a3ba491b424ddf018270c7312f4085","src/unix/bsd/netbsdlike/openbsd/x86.rs":"6f7f5c4fde2a2259eb547890cbd86570cea04ef85347d7569e94e679448bec87","src/unix/bsd/netbsdlike/openbsd/x86_64.rs":"d31db31630289c85af3339dbe357998a21ca584cbae31607448fe2cf7675a4e1","src/unix/haiku/b32.rs":"69ae47fc52c6880e85416b4744500d5655c9ec6131cb737f3b649fceaadce15a","src/unix/haiku/b64.rs":"73e64db09275a8da8d50a13cce2cfa2b136036ddf3a930d2939f337fc995900b","src/unix/haiku/mod.rs":"80a6cfb58acbbc471dbd412dd76a41f372befc8f217fb1671ed4ce8d391dced0","src/unix/haiku/native.rs":"44855f52906f607de137fc4baa8c6b1b9a26baaa666f25d5f7a7ec5e017c8be6","src/unix/haiku/x86_64.rs":"3ec3aeeb7ed208b8916f3e32d42bfd085ff5e16936a1a35d9a52789f043b7237","src/unix/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/unix/hermit/mod.rs":"859814f5df89e28fd4b345db399d181e11e7ed413841b6ff703a1fcbdbf013ae","src/unix/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/unix/linux_like/android/b32/arm.rs":"433c1530f602cc5ed26610c58055dde0c4ceea5e00150063b24ddc60768332a4","src/unix/linux_like/android/b32/mod.rs":"d971b98530a96f5892f98e1edc3133cf278d1b3939d77ab0a27a6323e0961715","src/unix/linux_like/android/b32/x86/align.rs":"812914e4241df82e32b12375ca3374615dc3a4bdd4cf31f0423c5815320c0dab","src/unix/linux_like/android/b32/x86/mod.rs":"8388bd3a0fcb5636bf965eee6dc95ae6860b85a2b555b387c868aa4d4e01ec89","src/unix/linux_like/android/b64/aarch64/align.rs":"2179c3b1608fa4bf68840482bfc2b2fa3ee2faf6fcae3770f9e505cddca35c7b","src/unix/linux_like/android/b64/aarch64/mod.rs":"8fe667d2b14abc5ac8aad32e16c3da24350471d8156eaea9ab4989f73dd9f9fc","src/unix/linux_like/android/b64/mod.rs":"d7bbbadafdb2cb2ff8e9cde3d89a03b9facaabb6b2d45705225d3ece1c5cce37","src/unix/linux_like/android/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/android/b64/x86_64/mod.rs":"06b22dc184e85a988ab969c75cadc52b9878faeab0eb9d21215878c95fe07c19","src/unix/linux_like/android/mod.rs":"07cebaa8d953446b8df5cb7c5de3932ae85b04d9e9993e3a3a126ff8f15111a4","src/unix/linux_like/emscripten/align.rs":"86c95cbed7a7161b1f23ee06843e7b0e2340ad92b2cb86fe2a8ef3e0e8c36216","src/unix/linux_like/emscripten/mod.rs":"b71d37106750f57bc2dae4e9bcb473ff098ef48235827e41a1687a39825f0aa4","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":"1618634d37348032f5ce1dc9df1aaa1f1681bca4a275f23d41f42098c4d3b423","src/unix/linux_like/linux/arch/mips/mod.rs":"dac02cd01dbd3b222286887c64d398c031afc08d38850c2b3ce2fe7158d888e0","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":"e7139d3bfb291a283c767e6201eac8bbb58c91839a36fa56bfe500fcb3aa754a","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":"5e40c273b767c369a46c3315c7cfde97379944ed63c74735e98d4dae2c49d414","src/unix/linux_like/linux/gnu/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/gnu/b32/mips/mod.rs":"20b4c897fb3f63e31a04849b348ec8e6e6405ce9463048d411114f8c9dbabd8a","src/unix/linux_like/linux/gnu/b32/mod.rs":"794dbcbae7dae8fd6b0b814573243197ceb532b56ef0772ad86b4b401478fcd9","src/unix/linux_like/linux/gnu/b32/powerpc.rs":"0cd7348badb9c4f8a0db31a2503b30c456a2bfcc7a0e5919762b1e12f912c5ad","src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs":"ee5145a383386b716605a8d1ff3df212d418aae1aa1f37d2307d4f9cd1a08e99","src/unix/linux_like/linux/gnu/b32/sparc/align.rs":"21adbed27df73e2d1ed934aaf733a643003d7baf2bde9c48ea440895bcca6d41","src/unix/linux_like/linux/gnu/b32/sparc/mod.rs":"a2c4ae8f31a74e4843b8ff4b6507419f403b52713169fcee9b1b24eb2324162a","src/unix/linux_like/linux/gnu/b32/x86/align.rs":"e4bafdc4a519a7922a81b37a62bbfd1177a2f620890eef8f1fbc47162e9eb413","src/unix/linux_like/linux/gnu/b32/x86/mod.rs":"525ee4917b54790cefc1298ec1015cea6332d818d9c7475434e94d06afdd59c0","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":"d179cbb462c451ff8805029b2b922c4bf90e35f667e80d716d5064f563aebc52","src/unix/linux_like/linux/gnu/b64/mips64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/mips64/mod.rs":"7d456da436017cb388b65b2c4b626c83b489cbb19a591673b9c627a608d53cfc","src/unix/linux_like/linux/gnu/b64/mod.rs":"6336065423c26b59681fd2ce77f1117ea36af13e163fdadaefd108bd8191e8c8","src/unix/linux_like/linux/gnu/b64/powerpc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs":"dbb8905e363ed4a2dfb984554ad9b6389d27f6a2d599ec2d80e38a6c7551a019","src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs":"5b982c41097f4f91adcb0968290afeccb27dce1695a261c964d34ef85df87cf4","src/unix/linux_like/linux/gnu/b64/s390x.rs":"fce37140468f8914411eed0b25a882e60e1b54bcffcd33d6263a91b57d04f6c1","src/unix/linux_like/linux/gnu/b64/sparc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs":"518ef78da0d81fe74cec30be411145d763fdfd249de4d108602fd0995781f590","src/unix/linux_like/linux/gnu/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs":"76cba0a3f9456a968d2ae6ea587162b2ff04278dc5250cb176395c936579771b","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":"af3590c392bd06394cb307ccb993e66f53de7e2a0211c689dbb1845220475445","src/unix/linux_like/linux/gnu/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/mod.rs":"88ce2c4105c07c1262495e0ff1bd53f3ceec99adba9c20c612439838b4dbfdd6","src/unix/linux_like/linux/musl/b32/arm/align.rs":"3e8ac052c1043764776b54c93ba4260e061df998631737a897d9d47d54f7b80c","src/unix/linux_like/linux/musl/b32/arm/mod.rs":"6255abe2ee04986832d12b7b2190589580f2a43e9bfb285b32b5747227f62727","src/unix/linux_like/linux/musl/b32/hexagon.rs":"10067cde5706e1173aa8e0a3a364cf44fe5b7a9f8b71cb086c653be71af00564","src/unix/linux_like/linux/musl/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/musl/b32/mips/mod.rs":"b9e9ff42363ebbb884ddf6445129ec4164471df45846874fc08f5f458e659254","src/unix/linux_like/linux/musl/b32/mod.rs":"8ede3985e6243882814ce91e8ce543e7edbafc0cee5932816072b6f14207a671","src/unix/linux_like/linux/musl/b32/powerpc.rs":"4592dc5f1f2fe888dfef85fa862d42d168e73a2c6f4fc052b58287d0f4d4ffcd","src/unix/linux_like/linux/musl/b32/x86/align.rs":"08e77fbd7435d7dec2ff56932433bece3f02e47ce810f89004a275a86d39cbe1","src/unix/linux_like/linux/musl/b32/x86/mod.rs":"a19a8decfab185af3cebd34aae4b15082e7552be573904b8c1a3f0c0e493ef34","src/unix/linux_like/linux/musl/b64/aarch64/align.rs":"798a9229d70ce235394f2dd625f6c4c1e10519a94382dc5b091952b638ae2928","src/unix/linux_like/linux/musl/b64/aarch64/mod.rs":"a73035c6d9b776f13b839008e15c04c2c53455571efd06664affcb047e457112","src/unix/linux_like/linux/musl/b64/mips64.rs":"2744895451f3a777fbe54f7f2695be53310b965fd62084c9b7e9121c7fe28346","src/unix/linux_like/linux/musl/b64/mod.rs":"d18abc0aeba2e26342bf3416a4dba0836db2bb0ee013b0a39629475cf8640289","src/unix/linux_like/linux/musl/b64/powerpc64.rs":"e5a55525b42493923956d668f978fb45e22d51deea00ce5edbfddf76ff19c741","src/unix/linux_like/linux/musl/b64/s390x.rs":"03dfec6794d93cb31a7c52b2d53a0973755168f91f8fa437cc5dbd54882c8ee7","src/unix/linux_like/linux/musl/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/musl/b64/x86_64/mod.rs":"0dd168f5a6881f32e5239fb312b23cf137b800d0ff323286a92c8a2c382b5456","src/unix/linux_like/linux/musl/mod.rs":"55ccd71342276ccb4c441a4bc2772aebfd163af299669b658c6c8c6add331ec3","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":"1e3bf809508b5872949136859bf48ddf58b7d24ae9f0b663e79f0efd1aaeb6a6","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":"fa4102d9a596d90de604ce2962b0e64f184dfbf10552a4c3ecf28f12d4704379","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":"a2877679fef0f14f54a89ccbc41fb02f0c25bf6e536f9eb2cb2fa437e1d3f739","src/unix/linux_like/linux/uclibc/mod.rs":"82d504d3aa12cb0f7933980f81c4708fa6e070d4c57efdf407f2de05b71bc06d","src/unix/linux_like/linux/uclibc/no_align.rs":"3f28637046524618adaa1012e26cb7ffe94b9396e6b518cccdc69d59f274d709","src/unix/linux_like/linux/uclibc/x86_64/l4re.rs":"024eba5753e852dbdd212427351affe7e83f9916c1864bce414d7aa2618f192e","src/unix/linux_like/linux/uclibc/x86_64/mod.rs":"66e8f5b7509a6e638b8b904906f89badbab0da8fb5b602d07ebd88649c4b961a","src/unix/linux_like/linux/uclibc/x86_64/other.rs":"42c3f71e58cabba373f6a55a623f3c31b85049eb64824c09c2b082b3b2d6a0a8","src/unix/linux_like/mod.rs":"ffce98bdd208fd9d335c65feafbf0d9742bea67c7eec1ee48657f292132ec3f0","src/unix/mod.rs":"b72f18e053cca0ade0f0606f1848a773fcf1885c72cbb31889275e8195f060bd","src/unix/newlib/aarch64/mod.rs":"bb269c1468a9676442554600e87417079a787fe6220dfc23b3109639259e8710","src/unix/newlib/align.rs":"28aaf87fafbc6b312622719d472d8cf65f9e5467d15339df5f73e66d8502b28a","src/unix/newlib/arm/mod.rs":"c71be856bfd7f576b2db28af9f680211cbe6c1cac7d537bbc8020b39591af07c","src/unix/newlib/espidf/mod.rs":"c198cb4beccdab483be61c102da74dc51ac80f766797e33021f3110394ed5a3d","src/unix/newlib/mod.rs":"d7271c13748be08305d36f9af6f41f6950a7a1d6d4382149194a35d5fe2090de","src/unix/newlib/no_align.rs":"e0743b2179495a9514bc3a4d1781e492878c4ec834ee0085d0891dd1712e82fb","src/unix/newlib/powerpc/mod.rs":"2d0f7af28b47f7a2a6c210ebd1c1f33ed8eac62e56b5af2b856de2ad3fdc5187","src/unix/no_align.rs":"c06e95373b9088266e0b14bba0954eef95f93fb2b01d951855e382d22de78e53","src/unix/redox/mod.rs":"cc4794afa4fbed9d6612894ea476228f9d8533950162d6416fc4d16073e1dac4","src/unix/solarish/compat.rs":"b07a5bfac925eb012003a459ba6bddbd3bfa9c44b3394da2ac5a602e54beae9c","src/unix/solarish/illumos.rs":"7d8f47fd37880715b449723688aaee568785325a46f1c360a05bdca13252278e","src/unix/solarish/mod.rs":"ea9dd1c1d68927408342762ee8998a9628838974c91089f620c867910c29adba","src/unix/solarish/solaris.rs":"65b005453aefa9b9d4fc860fe77cfec80d8c97a51342b15daf55fc3e808bb384","src/unix/solarish/x86_64.rs":"9d761573bdccbdd1ac61da571f7e96b5374df70241d9b72d45a069611f495085","src/vxworks/aarch64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/arm.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/mod.rs":"aea3da66f2140f2a82dfc9c58f6e6531d2dd9c15ea696e0f95a0d4a2a187b5b6","src/vxworks/powerpc.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/powerpc64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/x86.rs":"552f007f38317620b23889cb7c49d1d115841252439060122f52f434fbc6e5ba","src/vxworks/x86_64.rs":"018d92be3ad628a129eff9f2f5dfbc0883d8b8e5f2fa917b900a7f98ed6b514a","src/wasi.rs":"44ce56183380d18aedea9b7bec2edc5819e8529302c913bfe5d01f760155b82a","src/windows/gnu/align.rs":"b2c13ec1b9f3b39a75c452c80c951dff9d0215e31d77e883b4502afb31794647","src/windows/gnu/mod.rs":"3c8c7edb7cdf5d0c44af936db2a94869585c69dfabeef30571b4f4e38375767a","src/windows/mod.rs":"1cd9223293255b994814487e28d9979fb8ebef4538a236c1aa47fdc166a149cc","src/windows/msvc/mod.rs":"c068271e00fca6b62bc4bf44bcf142cfc38caeded9b6c4e01d1ceef3ccf986f4","tests/const_fn.rs":"cb75a1f0864f926aebe79118fc34d51a0d1ade2c20a394e7774c7e545f21f1f4"},"package":"fbe5e23404da5b4f555ef85ebed98fb4083e55a00c317800bc2a50ede9f3d219"} \ No newline at end of file diff --git a/vendor/libc/Cargo.toml b/vendor/libc/Cargo.toml index 0a49396f43..2a8ac876f4 100644 --- a/vendor/libc/Cargo.toml +++ b/vendor/libc/Cargo.toml @@ -11,7 +11,7 @@ [package] name = "libc" -version = "0.2.103" +version = "0.2.107" 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 c4982111e7..0e40178638 100644 --- a/vendor/libc/build.rs +++ b/vendor/libc/build.rs @@ -72,6 +72,10 @@ fn main() { println!("cargo:rustc-cfg=libc_cfg_target_vendor"); } + if rustc_minor_ver >= 51 || rustc_dep_of_std { + println!("cargo:rustc-cfg=libc_ptr_addr_of"); + } + // #[thread_local] is currently unstable if rustc_dep_of_std { println!("cargo:rustc-cfg=libc_thread_local"); diff --git a/vendor/libc/src/lib.rs b/vendor/libc/src/lib.rs index 30c94b0969..19fed28de2 100644 --- a/vendor/libc/src/lib.rs +++ b/vendor/libc/src/lib.rs @@ -26,7 +26,7 @@ #![cfg_attr(feature = "rustc-dep-of-std", no_core)] #![cfg_attr( any(feature = "rustc-dep-of-std", target_os = "redox"), - feature(static_nobundle) + feature(static_nobundle, native_link_modifiers, native_link_modifiers_bundle) )] #![cfg_attr(libc_const_extern_fn, feature(const_extern_fn))] @@ -123,6 +123,12 @@ cfg_if! { mod vxworks; pub use vxworks::*; + } else if #[cfg(target_os = "solid_asp3")] { + mod fixed_width_ints; + pub use fixed_width_ints::*; + + mod solid; + pub use solid::*; } else if #[cfg(unix)] { mod fixed_width_ints; pub use fixed_width_ints::*; diff --git a/vendor/libc/src/macros.rs b/vendor/libc/src/macros.rs index 1871cfafda..d52c4ad81e 100644 --- a/vendor/libc/src/macros.rs +++ b/vendor/libc/src/macros.rs @@ -341,3 +341,19 @@ macro_rules! deprecated_mach { )* } } + +#[allow(unused_macros)] +#[cfg(not(libc_ptr_addr_of))] +macro_rules! ptr_addr_of { + ($place:expr) => { + &$place + }; +} + +#[allow(unused_macros)] +#[cfg(libc_ptr_addr_of)] +macro_rules! ptr_addr_of { + ($place:expr) => { + ::core::ptr::addr_of!($place) + }; +} diff --git a/vendor/libc/src/solid/aarch64.rs b/vendor/libc/src/solid/aarch64.rs new file mode 100644 index 0000000000..d614fadb16 --- /dev/null +++ b/vendor/libc/src/solid/aarch64.rs @@ -0,0 +1,4 @@ +pub type c_char = i8; +pub type wchar_t = i16; +pub type c_long = i64; +pub type c_ulong = u64; diff --git a/vendor/libc/src/solid/arm.rs b/vendor/libc/src/solid/arm.rs new file mode 100644 index 0000000000..225613c4de --- /dev/null +++ b/vendor/libc/src/solid/arm.rs @@ -0,0 +1,4 @@ +pub type c_char = i8; +pub type wchar_t = i16; +pub type c_long = i32; +pub type c_ulong = u32; diff --git a/vendor/libc/src/solid/mod.rs b/vendor/libc/src/solid/mod.rs new file mode 100644 index 0000000000..670e430f12 --- /dev/null +++ b/vendor/libc/src/solid/mod.rs @@ -0,0 +1,904 @@ +//! Interface to the [SOLID] C library +//! +//! [SOLID]: https://solid.kmckk.com/ + +pub type c_schar = i8; +pub type c_uchar = u8; +pub type c_short = i16; +pub type c_ushort = u16; +pub type c_int = i32; +pub type c_uint = u32; +pub type c_float = f32; +pub type c_double = f64; +pub type c_longlong = i64; +pub type c_ulonglong = u64; +pub type intmax_t = i64; +pub type uintmax_t = u64; + +pub type uintptr_t = usize; +pub type intptr_t = isize; +pub type ptrdiff_t = isize; +pub type size_t = ::uintptr_t; +pub type ssize_t = ::intptr_t; + +pub type clock_t = c_uint; +pub type time_t = i64; +pub type clockid_t = c_int; +pub type timer_t = c_int; +pub type suseconds_t = c_int; +pub type useconds_t = c_uint; + +pub type sighandler_t = size_t; + +// sys/ansi.h +pub type __caddr_t = *mut c_char; +pub type __gid_t = u32; +pub type __in_addr_t = u32; +pub type __in_port_t = u16; +pub type __mode_t = u32; +pub type __off_t = i64; +pub type __pid_t = i32; +pub type __sa_family_t = u8; +pub type __socklen_t = c_uint; +pub type __uid_t = u32; +pub type __fsblkcnt_t = u64; +pub type __fsfilcnt_t = u64; + +// locale.h +pub type locale_t = usize; + +// nl_types.h +pub type nl_item = c_long; + +// sys/types.h +pub type __va_list = *mut c_char; +pub type u_int8_t = u8; +pub type u_int16_t = u16; +pub type u_int32_t = u32; +pub type u_int64_t = u64; +pub type u_char = c_uchar; +pub type u_short = c_ushort; +pub type u_int = c_uint; +pub type u_long = c_ulong; +pub type unchar = c_uchar; +pub type ushort = c_ushort; +pub type uint = c_uint; +pub type ulong = c_ulong; +pub type u_quad_t = u64; +pub type quad_t = i64; +pub type qaddr_t = *mut quad_t; +pub type longlong_t = i64; +pub type u_longlong_t = u64; +pub type blkcnt_t = i64; +pub type blksize_t = i32; +pub type fsblkcnt_t = __fsblkcnt_t; +pub type fsfilcnt_t = __fsfilcnt_t; +pub type caddr_t = __caddr_t; +pub type daddr_t = i64; +pub type dev_t = u64; +pub type fixpt_t = u32; +pub type gid_t = __gid_t; +pub type idtype_t = c_int; +pub type id_t = u32; +pub type ino_t = u64; +pub type key_t = c_long; +pub type mode_t = __mode_t; +pub type nlink_t = u32; +pub type off_t = __off_t; +pub type pid_t = __pid_t; +pub type lwpid_t = i32; +pub type rlim_t = u64; +pub type segsz_t = i32; +pub type swblk_t = i32; +pub type mqd_t = c_int; +pub type cpuid_t = c_ulong; +pub type psetid_t = c_int; + +s! { + // stat.h + pub struct stat { + pub st_dev: dev_t, + pub st_ino: ino_t, + pub st_mode: c_short, + pub st_nlink: c_short, + pub st_uid: c_short, + pub st_gid: c_short, + pub st_rdev: dev_t, + pub st_size: off_t, + pub st_atime: time_t, + pub st_mtime: time_t, + pub st_ctime: time_t, + pub st_blksize: blksize_t, + } + + // time.h + pub struct tm { + pub tm_sec: c_int, + pub tm_min: c_int, + pub tm_hour: c_int, + pub tm_mday: c_int, + pub tm_mon: c_int, + pub tm_year: c_int, + pub tm_wday: c_int, + pub tm_yday: c_int, + pub tm_isdst: c_int, + pub tm_gmtoff: c_long, + pub tm_zone: *mut c_char, + } + + // stdlib.h + pub struct qdiv_t { + pub quot: quad_t, + pub rem: quad_t, + } + pub struct lldiv_t { + pub quot: c_longlong, + pub rem: c_longlong, + } + pub struct div_t { + pub quot: c_int, + pub rem: c_int, + } + pub struct ldiv_t { + pub quot: c_long, + pub rem: c_long, + } + + // locale.h + pub struct lconv { + pub decimal_point: *mut c_char, + pub thousands_sep: *mut c_char, + pub grouping: *mut c_char, + pub int_curr_symbol: *mut c_char, + pub currency_symbol: *mut c_char, + pub mon_decimal_point: *mut c_char, + pub mon_thousands_sep: *mut c_char, + pub mon_grouping: *mut c_char, + pub positive_sign: *mut c_char, + pub negative_sign: *mut c_char, + pub int_frac_digits: c_char, + pub frac_digits: c_char, + pub p_cs_precedes: c_char, + pub p_sep_by_space: c_char, + pub n_cs_precedes: c_char, + pub n_sep_by_space: c_char, + pub p_sign_posn: c_char, + pub n_sign_posn: c_char, + pub int_p_cs_precedes: c_char, + pub int_n_cs_precedes: c_char, + pub int_p_sep_by_space: c_char, + pub int_n_sep_by_space: c_char, + pub int_p_sign_posn: c_char, + pub int_n_sign_posn: c_char, + } + + pub struct iovec { + pub iov_base: *mut c_void, + pub iov_len: size_t, + } + + pub struct timeval { + pub tv_sec: c_long, + pub tv_usec: c_long, + } +} + +pub const INT_MIN: c_int = -2147483648; +pub const INT_MAX: c_int = 2147483647; + +pub const EXIT_FAILURE: c_int = 1; +pub const EXIT_SUCCESS: c_int = 0; +pub const RAND_MAX: c_int = 0x7fffffff; +pub const EOF: c_int = -1; +pub const SEEK_SET: c_int = 0; +pub const SEEK_CUR: c_int = 1; +pub const SEEK_END: c_int = 2; +pub const _IOFBF: c_int = 0; +pub const _IONBF: c_int = 2; +pub const _IOLBF: c_int = 1; +pub const BUFSIZ: c_uint = 1024; +pub const FOPEN_MAX: c_uint = 20; +pub const FILENAME_MAX: c_uint = 1024; + +pub const O_RDONLY: c_int = 1; +pub const O_WRONLY: c_int = 2; +pub const O_RDWR: c_int = 4; +pub const O_APPEND: c_int = 8; +pub const O_CREAT: c_int = 0x10; +pub const O_EXCL: c_int = 0x400; +pub const O_TEXT: c_int = 0x100; +pub const O_BINARY: c_int = 0x200; +pub const O_TRUNC: c_int = 0x20; +pub const S_IEXEC: c_short = 0x0040; +pub const S_IWRITE: c_short = 0x0080; +pub const S_IREAD: c_short = 0x0100; +pub const S_IFCHR: c_short = 0x2000; +pub const S_IFDIR: c_short = 0x4000; +pub const S_IFMT: c_short = 0o160000; +pub const S_IFIFO: c_short = 0o0010000; +pub const S_IFBLK: c_short = 0o0060000; +pub const S_IFREG: c_short = 0o0100000; + +pub const LC_ALL: c_int = 0; +pub const LC_COLLATE: c_int = 1; +pub const LC_CTYPE: c_int = 2; +pub const LC_MONETARY: c_int = 3; +pub const LC_NUMERIC: c_int = 4; +pub const LC_TIME: c_int = 5; +pub const LC_MESSAGES: c_int = 6; +pub const _LC_LAST: c_int = 7; + +pub const EPERM: c_int = 1; +pub const ENOENT: c_int = 2; +pub const ESRCH: c_int = 3; +pub const EINTR: c_int = 4; +pub const EIO: c_int = 5; +pub const ENXIO: c_int = 6; +pub const E2BIG: c_int = 7; +pub const ENOEXEC: c_int = 8; +pub const EBADF: c_int = 9; +pub const ECHILD: c_int = 10; +pub const EAGAIN: c_int = 11; +pub const ENOMEM: c_int = 12; +pub const EACCES: c_int = 13; +pub const EFAULT: c_int = 14; +pub const ENOTBLK: c_int = 15; +pub const EBUSY: c_int = 16; +pub const EEXIST: c_int = 17; +pub const EXDEV: c_int = 18; +pub const ENODEV: c_int = 19; +pub const ENOTDIR: c_int = 20; +pub const EISDIR: c_int = 21; +pub const EINVAL: c_int = 22; +pub const ENFILE: c_int = 23; +pub const EMFILE: c_int = 24; +pub const ENOTTY: c_int = 25; +pub const ETXTBSY: c_int = 26; +pub const EFBIG: c_int = 27; +pub const ENOSPC: c_int = 28; +pub const ESPIPE: c_int = 29; +pub const EROFS: c_int = 30; +pub const EMLINK: c_int = 31; +pub const EPIPE: c_int = 32; +pub const EDOM: c_int = 33; +pub const ERANGE: c_int = 34; + +pub const EDEADLK: c_int = 35; +pub const ENAMETOOLONG: c_int = 36; +pub const ENOLCK: c_int = 37; +pub const ENOSYS: c_int = 38; +pub const ENOTEMPTY: c_int = 39; +pub const ELOOP: c_int = 40; +pub const EWOULDBLOCK: c_int = EAGAIN; +pub const ENOMSG: c_int = 42; +pub const EIDRM: c_int = 43; +pub const ECHRNG: c_int = 44; +pub const EL2NSYNC: c_int = 45; +pub const EL3HLT: c_int = 46; +pub const EL3RST: c_int = 47; +pub const ELNRNG: c_int = 48; +pub const EUNATCH: c_int = 49; +pub const ENOCSI: c_int = 50; +pub const EL2HLT: c_int = 51; +pub const EBADE: c_int = 52; +pub const EBADR: c_int = 53; +pub const EXFULL: c_int = 54; +pub const ENOANO: c_int = 55; +pub const EBADRQC: c_int = 56; +pub const EBADSLT: c_int = 57; + +pub const EDEADLOCK: c_int = EDEADLK; + +pub const EBFONT: c_int = 59; +pub const ENOSTR: c_int = 60; +pub const ENODATA: c_int = 61; +pub const ETIME: c_int = 62; +pub const ENOSR: c_int = 63; +pub const ENONET: c_int = 64; +pub const ENOPKG: c_int = 65; +pub const EREMOTE: c_int = 66; +pub const ENOLINK: c_int = 67; +pub const EADV: c_int = 68; +pub const ESRMNT: c_int = 69; +pub const ECOMM: c_int = 70; +pub const EPROTO: c_int = 71; +pub const EMULTIHOP: c_int = 72; +pub const EDOTDOT: c_int = 73; +pub const EBADMSG: c_int = 74; +pub const EOVERFLOW: c_int = 75; +pub const ENOTUNIQ: c_int = 76; +pub const EBADFD: c_int = 77; +pub const EREMCHG: c_int = 78; +pub const ELIBACC: c_int = 79; +pub const ELIBBAD: c_int = 80; +pub const ELIBSCN: c_int = 81; +pub const ELIBMAX: c_int = 82; +pub const ELIBEXEC: c_int = 83; +pub const EILSEQ: c_int = 84; +pub const ERESTART: c_int = 85; +pub const ESTRPIPE: c_int = 86; +pub const EUSERS: c_int = 87; +pub const ENOTSOCK: c_int = 88; +pub const EDESTADDRREQ: c_int = 89; +pub const EMSGSIZE: c_int = 90; +pub const EPROTOTYPE: c_int = 91; +pub const ENOPROTOOPT: c_int = 92; +pub const EPROTONOSUPPORT: c_int = 93; +pub const ESOCKTNOSUPPORT: c_int = 94; +pub const EOPNOTSUPP: c_int = 95; +pub const EPFNOSUPPORT: c_int = 96; +pub const EAFNOSUPPORT: c_int = 97; +pub const EADDRINUSE: c_int = 98; +pub const EADDRNOTAVAIL: c_int = 99; +pub const ENETDOWN: c_int = 100; +pub const ENETUNREACH: c_int = 101; +pub const ENETRESET: c_int = 102; +pub const ECONNABORTED: c_int = 103; +pub const ECONNRESET: c_int = 104; +pub const ENOBUFS: c_int = 105; +pub const EISCONN: c_int = 106; +pub const ENOTCONN: c_int = 107; +pub const ESHUTDOWN: c_int = 108; +pub const ETOOMANYREFS: c_int = 109; +pub const ETIMEDOUT: c_int = 110; +pub const ECONNREFUSED: c_int = 111; +pub const EHOSTDOWN: c_int = 112; +pub const EHOSTUNREACH: c_int = 113; +pub const EALREADY: c_int = 114; +pub const EINPROGRESS: c_int = 115; +pub const ESTALE: c_int = 116; +pub const EUCLEAN: c_int = 117; +pub const ENOTNAM: c_int = 118; +pub const ENAVAIL: c_int = 119; +pub const EISNAM: c_int = 120; +pub const EREMOTEIO: c_int = 121; +pub const EDQUOT: c_int = 122; + +pub const ENOMEDIUM: c_int = 123; +pub const EMEDIUMTYPE: c_int = 124; +pub const ECANCELED: c_int = 125; +pub const ENOKEY: c_int = 126; +pub const EKEYEXPIRED: c_int = 127; +pub const EKEYREVOKED: c_int = 128; +pub const EKEYREJECTED: c_int = 129; + +pub const EOWNERDEAD: c_int = 130; +pub const ENOTRECOVERABLE: c_int = 131; + +pub const ENOTSUP: c_int = 132; +pub const EFTYPE: c_int = 133; + +// signal codes +pub const SIGHUP: c_int = 1; +pub const SIGINT: c_int = 2; +pub const SIGQUIT: c_int = 3; +pub const SIGILL: c_int = 4; +pub const SIGTRAP: c_int = 5; +pub const SIGABRT: c_int = 6; +pub const SIGIOT: c_int = SIGABRT; +pub const SIGEMT: c_int = 7; +pub const SIGFPE: c_int = 8; +pub const SIGKILL: c_int = 9; +pub const SIGBUS: c_int = 10; +pub const SIGSEGV: c_int = 11; +pub const SIGSYS: c_int = 12; +pub const SIGPIPE: c_int = 13; +pub const SIGALRM: c_int = 14; +pub const SIGTERM: c_int = 15; +pub const SIGURG: c_int = 16; +pub const SIGSTOP: c_int = 17; +pub const SIGTSTP: c_int = 18; +pub const SIGCONT: c_int = 19; +pub const SIGCHLD: c_int = 20; +pub const SIGTTIN: c_int = 21; +pub const SIGTTOU: c_int = 22; +pub const SIGIO: c_int = 23; +pub const SIGXCPU: c_int = 24; +pub const SIGXFSZ: c_int = 25; +pub const SIGVTALRM: c_int = 26; +pub const SIGPROF: c_int = 27; +pub const SIGWINCH: c_int = 28; +pub const SIGINFO: c_int = 29; +pub const SIGUSR1: c_int = 30; +pub const SIGUSR2: c_int = 31; +pub const SIGPWR: c_int = 32; + +#[cfg_attr(feature = "extra_traits", derive(Debug))] +pub enum FILE {} +impl ::Copy for FILE {} +impl ::Clone for FILE { + fn clone(&self) -> FILE { + *self + } +} +#[cfg_attr(feature = "extra_traits", derive(Debug))] +pub enum fpos_t {} +impl ::Copy for fpos_t {} +impl ::Clone for fpos_t { + fn clone(&self) -> fpos_t { + *self + } +} + +extern "C" { + // ctype.h + pub fn isalnum(c: c_int) -> c_int; + pub fn isalpha(c: c_int) -> c_int; + pub fn iscntrl(c: c_int) -> c_int; + pub fn isdigit(c: c_int) -> c_int; + pub fn isgraph(c: c_int) -> c_int; + pub fn islower(c: c_int) -> c_int; + pub fn isprint(c: c_int) -> c_int; + pub fn ispunct(c: c_int) -> c_int; + pub fn isspace(c: c_int) -> c_int; + pub fn isupper(c: c_int) -> c_int; + pub fn isxdigit(c: c_int) -> c_int; + pub fn isblank(c: c_int) -> c_int; + pub fn tolower(c: c_int) -> c_int; + pub fn toupper(c: c_int) -> c_int; + + // stdio.h + pub fn __get_stdio_file(fileno: c_int) -> *mut FILE; + pub fn clearerr(arg1: *mut FILE); + pub fn fclose(arg1: *mut FILE) -> c_int; + pub fn feof(arg1: *mut FILE) -> c_int; + pub fn ferror(arg1: *mut FILE) -> c_int; + pub fn fflush(arg1: *mut FILE) -> c_int; + pub fn fgetc(arg1: *mut FILE) -> c_int; + pub fn fgets(arg1: *mut c_char, arg2: c_int, arg3: *mut FILE) -> *mut c_char; + pub fn fopen(arg1: *const c_char, arg2: *const c_char) -> *mut FILE; + pub fn fprintf(arg1: *mut FILE, arg2: *const c_char, ...) -> c_int; + pub fn fputc(arg1: c_int, arg2: *mut FILE) -> c_int; + pub fn fputs(arg1: *const c_char, arg2: *mut FILE) -> c_int; + pub fn fread(arg1: *mut c_void, arg2: size_t, arg3: size_t, arg4: *mut FILE) -> size_t; + pub fn freopen(arg1: *const c_char, arg2: *const c_char, arg3: *mut FILE) -> *mut FILE; + pub fn fscanf(arg1: *mut FILE, arg2: *const c_char, ...) -> c_int; + pub fn fseek(arg1: *mut FILE, arg2: c_long, arg3: c_int) -> c_int; + pub fn ftell(arg1: *mut FILE) -> c_long; + pub fn fwrite(arg1: *const c_void, arg2: size_t, arg3: size_t, arg4: *mut FILE) -> size_t; + pub fn getc(arg1: *mut FILE) -> c_int; + pub fn getchar() -> c_int; + pub fn perror(arg1: *const c_char); + pub fn printf(arg1: *const c_char, ...) -> c_int; + pub fn putc(arg1: c_int, arg2: *mut FILE) -> c_int; + pub fn putchar(arg1: c_int) -> c_int; + pub fn puts(arg1: *const c_char) -> c_int; + pub fn remove(arg1: *const c_char) -> c_int; + pub fn rewind(arg1: *mut FILE); + pub fn scanf(arg1: *const c_char, ...) -> c_int; + pub fn setbuf(arg1: *mut FILE, arg2: *mut c_char); + pub fn setvbuf(arg1: *mut FILE, arg2: *mut c_char, arg3: c_int, arg4: size_t) -> c_int; + pub fn sscanf(arg1: *const c_char, arg2: *const c_char, ...) -> c_int; + pub fn tmpfile() -> *mut FILE; + pub fn ungetc(arg1: c_int, arg2: *mut FILE) -> c_int; + pub fn vfprintf(arg1: *mut FILE, arg2: *const c_char, arg3: __va_list) -> c_int; + pub fn vprintf(arg1: *const c_char, arg2: __va_list) -> c_int; + pub fn gets(arg1: *mut c_char) -> *mut c_char; + pub fn sprintf(arg1: *mut c_char, arg2: *const c_char, ...) -> c_int; + pub fn tmpnam(arg1: *const c_char) -> *mut c_char; + pub fn vsprintf(arg1: *mut c_char, arg2: *const c_char, arg3: __va_list) -> c_int; + pub fn rename(arg1: *const c_char, arg2: *const c_char) -> c_int; + pub fn asiprintf(arg1: *mut *mut c_char, arg2: *const c_char, ...) -> c_int; + pub fn fiprintf(arg1: *mut FILE, arg2: *const c_char, ...) -> c_int; + pub fn fiscanf(arg1: *mut FILE, arg2: *const c_char, ...) -> c_int; + pub fn iprintf(arg1: *const c_char, ...) -> c_int; + pub fn iscanf(arg1: *const c_char, ...) -> c_int; + pub fn siprintf(arg1: *mut c_char, arg2: *const c_char, ...) -> c_int; + pub fn siscanf(arg1: *mut c_char, arg2: *const c_char, ...) -> c_int; + pub fn sniprintf(arg1: *mut c_char, arg2: size_t, arg3: *const c_char, ...) -> c_int; + pub fn vasiprintf(arg1: *mut *mut c_char, arg2: *const c_char, arg3: __va_list) -> c_int; + pub fn vfiprintf(arg1: *mut FILE, arg2: *const c_char, arg3: __va_list) -> c_int; + pub fn vfiscanf(arg1: *mut FILE, arg2: *const c_char, arg3: __va_list) -> c_int; + pub fn viprintf(arg1: *const c_char, arg2: __va_list) -> c_int; + pub fn viscanf(arg1: *const c_char, arg2: __va_list) -> c_int; + pub fn vsiprintf(arg1: *mut c_char, arg2: *const c_char, arg3: __va_list) -> c_int; + pub fn vsiscanf(arg1: *const c_char, arg2: *const c_char, arg3: __va_list) -> c_int; + pub fn vsniprintf( + arg1: *mut c_char, + arg2: size_t, + arg3: *const c_char, + arg4: __va_list, + ) -> c_int; + pub fn vdiprintf(arg1: c_int, arg2: *const c_char, arg3: __va_list) -> c_int; + pub fn diprintf(arg1: c_int, arg2: *const c_char, ...) -> c_int; + pub fn fgetpos(arg1: *mut FILE, arg2: *mut fpos_t) -> c_int; + pub fn fsetpos(arg1: *mut FILE, arg2: *const fpos_t) -> c_int; + pub fn fdopen(arg1: c_int, arg2: *const c_char) -> *mut FILE; + pub fn fileno(arg1: *mut FILE) -> c_int; + pub fn flockfile(arg1: *mut FILE); + pub fn ftrylockfile(arg1: *mut FILE) -> c_int; + pub fn funlockfile(arg1: *mut FILE); + pub fn getc_unlocked(arg1: *mut FILE) -> c_int; + pub fn getchar_unlocked() -> c_int; + pub fn putc_unlocked(arg1: c_int, arg2: *mut FILE) -> c_int; + pub fn putchar_unlocked(arg1: c_int) -> c_int; + pub fn snprintf(arg1: *mut c_char, arg2: size_t, arg3: *const c_char, ...) -> c_int; + pub fn vsnprintf( + arg1: *mut c_char, + arg2: size_t, + arg3: *const c_char, + arg4: __va_list, + ) -> c_int; + pub fn getw(arg1: *mut FILE) -> c_int; + pub fn putw(arg1: c_int, arg2: *mut FILE) -> c_int; + pub fn tempnam(arg1: *const c_char, arg2: *const c_char) -> *mut c_char; + pub fn fseeko(stream: *mut FILE, offset: off_t, whence: c_int) -> c_int; + pub fn ftello(stream: *mut FILE) -> off_t; + + // stdlib.h + pub fn atof(arg1: *const c_char) -> f64; + pub fn strtod(arg1: *const c_char, arg2: *mut *mut c_char) -> f64; + pub fn drand48() -> f64; + pub fn erand48(arg1: *mut c_ushort) -> f64; + pub fn strtof(arg1: *const c_char, arg2: *mut *mut c_char) -> f32; + pub fn strtold(arg1: *const c_char, arg2: *mut *mut c_char) -> f64; + pub fn strtod_l(arg1: *const c_char, arg2: *mut *mut c_char, arg3: locale_t) -> f64; + pub fn strtof_l(arg1: *const c_char, arg2: *mut *mut c_char, arg3: locale_t) -> f32; + pub fn strtold_l(arg1: *const c_char, arg2: *mut *mut c_char, arg3: locale_t) -> f64; + pub fn _Exit(arg1: c_int); + pub fn abort(); + pub fn abs(arg1: c_int) -> c_int; + pub fn atexit(arg1: ::Option<unsafe extern "C" fn()>) -> c_int; + pub fn atoi(arg1: *const c_char) -> c_int; + pub fn atol(arg1: *const c_char) -> c_long; + pub fn itoa(arg1: c_int, arg2: *mut c_char, arg3: c_int) -> *mut c_char; + pub fn ltoa(arg1: c_long, arg2: *mut c_char, arg3: c_int) -> *mut c_char; + pub fn ultoa(arg1: c_ulong, arg2: *mut c_char, arg3: c_int) -> *mut c_char; + pub fn bsearch( + arg1: *const c_void, + arg2: *const c_void, + arg3: size_t, + arg4: size_t, + arg5: ::Option<unsafe extern "C" fn(arg1: *const c_void, arg2: *const c_void) -> c_int>, + ) -> *mut c_void; + pub fn calloc(arg1: size_t, arg2: size_t) -> *mut c_void; + pub fn div(arg1: c_int, arg2: c_int) -> div_t; + pub fn exit(arg1: c_int); + pub fn free(arg1: *mut c_void); + pub fn getenv(arg1: *const c_char) -> *mut c_char; + pub fn labs(arg1: c_long) -> c_long; + pub fn ldiv(arg1: c_long, arg2: c_long) -> ldiv_t; + pub fn malloc(arg1: size_t) -> *mut c_void; + pub fn qsort( + arg1: *mut c_void, + arg2: size_t, + arg3: size_t, + arg4: ::Option<unsafe extern "C" fn(arg1: *const c_void, arg2: *const c_void) -> c_int>, + ); + pub fn rand() -> c_int; + pub fn realloc(arg1: *mut c_void, arg2: size_t) -> *mut c_void; + pub fn srand(arg1: c_uint); + pub fn strtol(arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int) -> c_long; + pub fn strtoul(arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int) -> c_ulong; + pub fn mblen(arg1: *const c_char, arg2: size_t) -> c_int; + pub fn mbstowcs(arg1: *mut wchar_t, arg2: *const c_char, arg3: size_t) -> size_t; + pub fn wctomb(arg1: *mut c_char, arg2: wchar_t) -> c_int; + pub fn mbtowc(arg1: *mut wchar_t, arg2: *const c_char, arg3: size_t) -> c_int; + pub fn wcstombs(arg1: *mut c_char, arg2: *const wchar_t, arg3: size_t) -> size_t; + pub fn rand_r(arg1: *mut c_uint) -> c_int; + pub fn jrand48(arg1: *mut c_ushort) -> c_long; + pub fn lcong48(arg1: *mut c_ushort); + pub fn lrand48() -> c_long; + pub fn mrand48() -> c_long; + pub fn nrand48(arg1: *mut c_ushort) -> c_long; + pub fn seed48(arg1: *mut c_ushort) -> *mut c_ushort; + pub fn srand48(arg1: c_long); + pub fn putenv(arg1: *mut c_char) -> c_int; + pub fn a64l(arg1: *const c_char) -> c_long; + pub fn l64a(arg1: c_long) -> *mut c_char; + pub fn random() -> c_long; + pub fn setstate(arg1: *mut c_char) -> *mut c_char; + pub fn initstate(arg1: c_uint, arg2: *mut c_char, arg3: size_t) -> *mut c_char; + pub fn srandom(arg1: c_uint); + pub fn mkostemp(arg1: *mut c_char, arg2: c_int) -> c_int; + pub fn mkostemps(arg1: *mut c_char, arg2: c_int, arg3: c_int) -> c_int; + pub fn mkdtemp(arg1: *mut c_char) -> *mut c_char; + pub fn mkstemp(arg1: *mut c_char) -> c_int; + pub fn mktemp(arg1: *mut c_char) -> *mut c_char; + pub fn atoll(arg1: *const c_char) -> c_longlong; + pub fn llabs(arg1: c_longlong) -> c_longlong; + pub fn lldiv(arg1: c_longlong, arg2: c_longlong) -> lldiv_t; + pub fn strtoll(arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int) -> c_longlong; + pub fn strtoull(arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int) -> c_ulonglong; + pub fn aligned_alloc(arg1: size_t, arg2: size_t) -> *mut c_void; + pub fn at_quick_exit(arg1: ::Option<unsafe extern "C" fn()>) -> c_int; + pub fn quick_exit(arg1: c_int); + pub fn setenv(arg1: *const c_char, arg2: *const c_char, arg3: c_int) -> c_int; + pub fn unsetenv(arg1: *const c_char) -> c_int; + pub fn humanize_number( + arg1: *mut c_char, + arg2: size_t, + arg3: i64, + arg4: *const c_char, + arg5: c_int, + arg6: c_int, + ) -> c_int; + pub fn dehumanize_number(arg1: *const c_char, arg2: *mut i64) -> c_int; + pub fn getenv_r(arg1: *const c_char, arg2: *mut c_char, arg3: size_t) -> c_int; + pub fn heapsort( + arg1: *mut c_void, + arg2: size_t, + arg3: size_t, + arg4: ::Option<unsafe extern "C" fn(arg1: *const c_void, arg2: *const c_void) -> c_int>, + ) -> c_int; + pub fn mergesort( + arg1: *mut c_void, + arg2: size_t, + arg3: size_t, + arg4: ::Option<unsafe extern "C" fn(arg1: *const c_void, arg2: *const c_void) -> c_int>, + ) -> c_int; + pub fn radixsort( + arg1: *mut *const c_uchar, + arg2: c_int, + arg3: *const c_uchar, + arg4: c_uint, + ) -> c_int; + pub fn sradixsort( + arg1: *mut *const c_uchar, + arg2: c_int, + arg3: *const c_uchar, + arg4: c_uint, + ) -> c_int; + pub fn getprogname() -> *const c_char; + pub fn setprogname(arg1: *const c_char); + pub fn qabs(arg1: quad_t) -> quad_t; + pub fn strtoq(arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int) -> quad_t; + pub fn strtouq(arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int) -> u_quad_t; + pub fn strsuftoll( + arg1: *const c_char, + arg2: *const c_char, + arg3: c_longlong, + arg4: c_longlong, + ) -> c_longlong; + pub fn strsuftollx( + arg1: *const c_char, + arg2: *const c_char, + arg3: c_longlong, + arg4: c_longlong, + arg5: *mut c_char, + arg6: size_t, + ) -> c_longlong; + pub fn l64a_r(arg1: c_long, arg2: *mut c_char, arg3: c_int) -> c_int; + pub fn qdiv(arg1: quad_t, arg2: quad_t) -> qdiv_t; + pub fn strtol_l( + arg1: *const c_char, + arg2: *mut *mut c_char, + arg3: c_int, + arg4: locale_t, + ) -> c_long; + pub fn strtoul_l( + arg1: *const c_char, + arg2: *mut *mut c_char, + arg3: c_int, + arg4: locale_t, + ) -> c_ulong; + pub fn strtoll_l( + arg1: *const c_char, + arg2: *mut *mut c_char, + arg3: c_int, + arg4: locale_t, + ) -> c_longlong; + pub fn strtoull_l( + arg1: *const c_char, + arg2: *mut *mut c_char, + arg3: c_int, + arg4: locale_t, + ) -> c_ulonglong; + pub fn strtoq_l( + arg1: *const c_char, + arg2: *mut *mut c_char, + arg3: c_int, + arg4: locale_t, + ) -> quad_t; + pub fn strtouq_l( + arg1: *const c_char, + arg2: *mut *mut c_char, + arg3: c_int, + arg4: locale_t, + ) -> u_quad_t; + pub fn _mb_cur_max_l(arg1: locale_t) -> size_t; + pub fn mblen_l(arg1: *const c_char, arg2: size_t, arg3: locale_t) -> c_int; + pub fn mbstowcs_l( + arg1: *mut wchar_t, + arg2: *const c_char, + arg3: size_t, + arg4: locale_t, + ) -> size_t; + pub fn wctomb_l(arg1: *mut c_char, arg2: wchar_t, arg3: locale_t) -> c_int; + pub fn mbtowc_l(arg1: *mut wchar_t, arg2: *const c_char, arg3: size_t, arg4: locale_t) + -> c_int; + pub fn wcstombs_l( + arg1: *mut c_char, + arg2: *const wchar_t, + arg3: size_t, + arg4: locale_t, + ) -> size_t; + + // string.h + pub fn memchr(arg1: *const c_void, arg2: c_int, arg3: size_t) -> *mut c_void; + pub fn memcmp(arg1: *const c_void, arg2: *const c_void, arg3: size_t) -> c_int; + pub fn memcpy(arg1: *mut c_void, arg2: *const c_void, arg3: size_t) -> *mut c_void; + pub fn memmove(arg1: *mut c_void, arg2: *const c_void, arg3: size_t) -> *mut c_void; + pub fn memset(arg1: *mut c_void, arg2: c_int, arg3: size_t) -> *mut c_void; + pub fn strcat(arg1: *mut c_char, arg2: *const c_char) -> *mut c_char; + pub fn strchr(arg1: *const c_char, arg2: c_int) -> *mut c_char; + pub fn strcmp(arg1: *const c_char, arg2: *const c_char) -> c_int; + pub fn strcoll(arg1: *const c_char, arg2: *const c_char) -> c_int; + pub fn strcpy(arg1: *mut c_char, arg2: *const c_char) -> *mut c_char; + pub fn strcspn(arg1: *const c_char, arg2: *const c_char) -> size_t; + pub fn strerror(arg1: c_int) -> *mut c_char; + pub fn strlen(arg1: *const c_char) -> size_t; + pub fn strncat(arg1: *mut c_char, arg2: *const c_char, arg3: size_t) -> *mut c_char; + pub fn strncmp(arg1: *const c_char, arg2: *const c_char, arg3: size_t) -> c_int; + pub fn strncpy(arg1: *mut c_char, arg2: *const c_char, arg3: size_t) -> *mut c_char; + pub fn strpbrk(arg1: *const c_char, arg2: *const c_char) -> *mut c_char; + pub fn strrchr(arg1: *const c_char, arg2: c_int) -> *mut c_char; + pub fn strspn(arg1: *const c_char, arg2: *const c_char) -> size_t; + pub fn strstr(arg1: *const c_char, arg2: *const c_char) -> *mut c_char; + pub fn strtok(arg1: *mut c_char, arg2: *const c_char) -> *mut c_char; + pub fn strtok_r(arg1: *mut c_char, arg2: *const c_char, arg3: *mut *mut c_char) -> *mut c_char; + pub fn strerror_r(arg1: c_int, arg2: *mut c_char, arg3: size_t) -> c_int; + pub fn strxfrm(arg1: *mut c_char, arg2: *const c_char, arg3: size_t) -> size_t; + pub fn memccpy( + arg1: *mut c_void, + arg2: *const c_void, + arg3: c_int, + arg4: size_t, + ) -> *mut c_void; + pub fn strdup(arg1: *const c_char) -> *mut c_char; + pub fn stpcpy(arg1: *mut c_char, arg2: *const c_char) -> *mut c_char; + pub fn stpncpy(arg1: *mut c_char, arg2: *const c_char, arg3: size_t) -> *mut c_char; + pub fn strnlen(arg1: *const c_char, arg2: size_t) -> size_t; + pub fn memmem( + arg1: *const c_void, + arg2: size_t, + arg3: *const c_void, + arg4: size_t, + ) -> *mut c_void; + pub fn strcasestr(arg1: *const c_char, arg2: *const c_char) -> *mut c_char; + pub fn strlcat(arg1: *mut c_char, arg2: *const c_char, arg3: size_t) -> size_t; + pub fn strlcpy(arg1: *mut c_char, arg2: *const c_char, arg3: size_t) -> size_t; + pub fn strsep(arg1: *mut *mut c_char, arg2: *const c_char) -> *mut c_char; + pub fn stresep(arg1: *mut *mut c_char, arg2: *const c_char, arg3: c_int) -> *mut c_char; + pub fn strndup(arg1: *const c_char, arg2: size_t) -> *mut c_char; + pub fn memrchr(arg1: *const c_void, arg2: c_int, arg3: size_t) -> *mut c_void; + pub fn explicit_memset(arg1: *mut c_void, arg2: c_int, arg3: size_t) -> *mut c_void; + pub fn consttime_memequal(arg1: *const c_void, arg2: *const c_void, arg3: size_t) -> c_int; + pub fn strcoll_l(arg1: *const c_char, arg2: *const c_char, arg3: locale_t) -> c_int; + pub fn strxfrm_l( + arg1: *mut c_char, + arg2: *const c_char, + arg3: size_t, + arg4: locale_t, + ) -> size_t; + pub fn strerror_l(arg1: c_int, arg2: locale_t) -> *mut c_char; + + // strings.h + pub fn bcmp(arg1: *const c_void, arg2: *const c_void, arg3: size_t) -> c_int; + pub fn bcopy(arg1: *const c_void, arg2: *mut c_void, arg3: size_t); + pub fn bzero(arg1: *mut c_void, arg2: size_t); + pub fn ffs(arg1: c_int) -> c_int; + pub fn popcount(arg1: c_uint) -> c_uint; + pub fn popcountl(arg1: c_ulong) -> c_uint; + pub fn popcountll(arg1: c_ulonglong) -> c_uint; + pub fn popcount32(arg1: u32) -> c_uint; + pub fn popcount64(arg1: u64) -> c_uint; + pub fn rindex(arg1: *const c_char, arg2: c_int) -> *mut c_char; + pub fn strcasecmp(arg1: *const c_char, arg2: *const c_char) -> c_int; + pub fn strncasecmp(arg1: *const c_char, arg2: *const c_char, arg3: size_t) -> c_int; + + // signal.h + pub fn signal(arg1: c_int, arg2: sighandler_t) -> sighandler_t; + pub fn raise(arg1: c_int) -> c_int; + + // time.h + pub fn asctime(arg1: *const tm) -> *mut c_char; + pub fn clock() -> clock_t; + pub fn ctime(arg1: *const time_t) -> *mut c_char; + pub fn difftime(arg1: time_t, arg2: time_t) -> f64; + pub fn gmtime(arg1: *const time_t) -> *mut tm; + pub fn localtime(arg1: *const time_t) -> *mut tm; + pub fn time(arg1: *mut time_t) -> time_t; + pub fn mktime(arg1: *mut tm) -> time_t; + pub fn strftime( + arg1: *mut c_char, + arg2: size_t, + arg3: *const c_char, + arg4: *const tm, + ) -> size_t; + pub fn utime(arg1: *const c_char, arg2: *mut time_t) -> c_int; + pub fn asctime_r(arg1: *const tm, arg2: *mut c_char) -> *mut c_char; + pub fn ctime_r(arg1: *const time_t, arg2: *mut c_char) -> *mut c_char; + pub fn gmtime_r(arg1: *const time_t, arg2: *mut tm) -> *mut tm; + pub fn localtime_r(arg1: *const time_t, arg2: *mut tm) -> *mut tm; + + // sys/stat.h + pub fn stat(arg1: *const c_char, arg2: *mut stat) -> c_int; + pub fn lstat(arg1: *const c_char, arg2: *mut stat) -> c_int; + pub fn fstat(arg1: c_int, arg2: *mut stat) -> c_int; + pub fn chmod(arg1: *const c_char, arg2: __mode_t) -> c_int; + pub fn mkdir(arg1: *const c_char, arg2: __mode_t) -> c_int; + + // fcntl.h + pub fn open(arg1: *const c_char, arg2: c_int, ...) -> c_int; + pub fn creat(arg1: *const c_char, arg2: c_int) -> c_int; + pub fn close(arg1: c_int) -> c_int; + pub fn read(arg1: c_int, arg2: *mut c_void, arg3: c_int) -> c_int; + pub fn write(arg1: c_int, arg2: *const c_void, arg3: c_int) -> c_int; + pub fn unlink(arg1: *const c_char) -> c_int; + pub fn tell(arg1: c_int) -> c_long; + pub fn dup(arg1: c_int) -> c_int; + pub fn dup2(arg1: c_int, arg2: c_int) -> c_int; + pub fn access(arg1: *const c_char, arg2: c_int) -> c_int; + pub fn rmdir(arg1: *const c_char) -> c_int; + pub fn chdir(arg1: *const c_char) -> c_int; + pub fn _exit(arg1: c_int); + pub fn getwd(arg1: *mut c_char) -> *mut c_char; + pub fn getcwd(arg1: *mut c_char, arg2: size_t) -> *mut c_char; + pub static mut optarg: *mut c_char; + pub static mut opterr: c_int; + pub static mut optind: c_int; + pub static mut optopt: c_int; + pub static mut optreset: c_int; + pub fn getopt(arg1: c_int, arg2: *mut *mut c_char, arg3: *const c_char) -> c_int; + pub static mut suboptarg: *mut c_char; + pub fn getsubopt( + arg1: *mut *mut c_char, + arg2: *const *mut c_char, + arg3: *mut *mut c_char, + ) -> c_int; + pub fn fcntl(arg1: c_int, arg2: c_int, ...) -> c_int; + pub fn getpid() -> pid_t; + pub fn sleep(arg1: c_uint) -> c_uint; + pub fn usleep(arg1: useconds_t) -> c_int; + + // locale.h + pub fn localeconv() -> *mut lconv; + pub fn setlocale(arg1: c_int, arg2: *const c_char) -> *mut c_char; + pub fn duplocale(arg1: locale_t) -> locale_t; + pub fn freelocale(arg1: locale_t); + pub fn localeconv_l(arg1: locale_t) -> *mut lconv; + pub fn newlocale(arg1: c_int, arg2: *const c_char, arg3: locale_t) -> locale_t; + + // langinfo.h + pub fn nl_langinfo(item: ::nl_item) -> *mut ::c_char; + pub fn nl_langinfo_l(item: ::nl_item, locale: locale_t) -> *mut ::c_char; + + // malloc.h + pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void; + + // sys/types.h + pub fn lseek(arg1: c_int, arg2: __off_t, arg3: c_int) -> __off_t; +} + +cfg_if! { + if #[cfg(libc_core_cvoid)] { + pub use ::ffi::c_void; + } else { + // Use repr(u8) as LLVM expects `void*` to be the same as `i8*` to help + // enable more optimization opportunities around it recognizing things + // like malloc/free. + #[repr(u8)] + #[allow(missing_copy_implementations)] + #[allow(missing_debug_implementations)] + pub enum c_void { + // Two dummy variants so the #[repr] attribute can be used. + #[doc(hidden)] + __variant1, + #[doc(hidden)] + __variant2, + } + } +} + +cfg_if! { + if #[cfg(target_arch = "aarch64")] { + mod aarch64; + pub use self::aarch64::*; + } else if #[cfg(any(target_arch = "arm"))] { + mod arm; + pub use self::arm::*; + } else { + // Unknown target_arch + } +} diff --git a/vendor/libc/src/unix/bsd/apple/b32/mod.rs b/vendor/libc/src/unix/bsd/apple/b32/mod.rs index 9248e3adf2..0f1722f975 100644 --- a/vendor/libc/src/unix/bsd/apple/b32/mod.rs +++ b/vendor/libc/src/unix/bsd/apple/b32/mod.rs @@ -43,6 +43,10 @@ s! { pub bh_datalen: u32, pub bh_hdrlen: ::c_ushort, } + + pub struct malloc_zone_t { + __private: [::uintptr_t; 18], // FIXME: keeping private for now + } } s_no_extra_traits! { diff --git a/vendor/libc/src/unix/bsd/apple/b64/aarch64/mod.rs b/vendor/libc/src/unix/bsd/apple/b64/aarch64/mod.rs index 83b62e97cf..79e9ac842f 100644 --- a/vendor/libc/src/unix/bsd/apple/b64/aarch64/mod.rs +++ b/vendor/libc/src/unix/bsd/apple/b64/aarch64/mod.rs @@ -1,5 +1,11 @@ pub type boolean_t = ::c_int; +s! { + pub struct malloc_zone_t { + __private: [::uintptr_t; 18], // FIXME: needs arm64 auth pointers support + } +} + cfg_if! { if #[cfg(libc_align)] { mod align; diff --git a/vendor/libc/src/unix/bsd/apple/b64/x86_64/mod.rs b/vendor/libc/src/unix/bsd/apple/b64/x86_64/mod.rs index 078666658c..653650c262 100644 --- a/vendor/libc/src/unix/bsd/apple/b64/x86_64/mod.rs +++ b/vendor/libc/src/unix/bsd/apple/b64/x86_64/mod.rs @@ -102,6 +102,74 @@ s! { pub struct __darwin_xmm_reg { pub __xmm_reg: [::c_char; 16], } + + pub struct malloc_introspection_t { + _private: [::uintptr_t; 16], // FIXME: keeping private for now + } + + pub struct malloc_zone_t { + _reserved1: *mut ::c_void, + _reserved2: *mut ::c_void, + pub size: ::Option<unsafe extern "C" fn( + zone: *mut malloc_zone_t, + ptr: *const ::c_void, + ) -> ::size_t>, + pub malloc: ::Option<unsafe extern "C" fn( + zone: *mut malloc_zone_t, + size: ::size_t, + ) -> *mut ::c_void>, + pub calloc: ::Option<unsafe extern "C" fn( + zone: *mut malloc_zone_t, + num_items: ::size_t, + size: ::size_t, + ) -> *mut ::c_void>, + pub valloc: ::Option<unsafe extern "C" fn( + zone: *mut malloc_zone_t, + size: ::size_t + ) -> *mut ::c_void>, + pub free: ::Option<unsafe extern "C" fn( + zone: *mut malloc_zone_t, + ptr: *mut ::c_void + )>, + pub realloc: ::Option<unsafe extern "C" fn( + zone: *mut malloc_zone_t, + ptr: *mut ::c_void, + size: ::size_t, + ) -> *mut ::c_void>, + pub destroy: ::Option<unsafe extern "C" fn(zone: *mut malloc_zone_t)>, + pub zone_name: *const ::c_char, + pub batch_malloc: ::Option<unsafe extern "C" fn( + zone: *mut malloc_zone_t, + size: ::size_t, + results: *mut *mut ::c_void, + num_requested: ::c_uint, + ) -> ::c_uint>, + pub batch_free: ::Option<unsafe extern "C" fn( + zone: *mut malloc_zone_t, + to_be_freed: *mut *mut ::c_void, + num_to_be_freed: ::c_uint, + )>, + pub introspect: *mut malloc_introspection_t, + pub version: ::c_uint, + pub memalign: ::Option<unsafe extern "C" fn( + zone: *mut malloc_zone_t, + alignment: ::size_t, + size: ::size_t, + ) -> *mut ::c_void>, + pub free_definite_size: ::Option<unsafe extern "C" fn( + zone: *mut malloc_zone_t, + ptr: *mut ::c_void, + size: ::size_t + )>, + pub pressure_relief: ::Option<unsafe extern "C" fn( + zone: *mut malloc_zone_t, + goal: ::size_t, + ) -> ::size_t>, + pub claimed_address: ::Option<unsafe extern "C" fn( + zone: *mut malloc_zone_t, + ptr: *mut ::c_void, + ) -> ::boolean_t>, + } } cfg_if! { diff --git a/vendor/libc/src/unix/bsd/apple/mod.rs b/vendor/libc/src/unix/bsd/apple/mod.rs index 4c38ded171..0183ae8152 100644 --- a/vendor/libc/src/unix/bsd/apple/mod.rs +++ b/vendor/libc/src/unix/bsd/apple/mod.rs @@ -52,7 +52,7 @@ pub type host_flavor_t = integer_t; pub type host_info64_t = *mut integer_t; pub type processor_flavor_t = ::c_int; pub type thread_flavor_t = natural_t; -pub type thread_inspect_t = mach_port_t; +pub type thread_inspect_t = ::mach_port_t; pub type policy_t = ::c_int; pub type mach_vm_address_t = u64; pub type mach_vm_offset_t = u64; @@ -90,7 +90,7 @@ pub type thread_identifier_info_data_t = thread_identifier_info; pub type thread_extended_info_t = *mut thread_extended_info; pub type thread_extended_info_data_t = thread_extended_info; -pub type thread_t = mach_port_t; +pub type thread_t = ::mach_port_t; pub type thread_policy_flavor_t = natural_t; pub type thread_policy_t = *mut integer_t; pub type thread_latency_qos_t = integer_t; @@ -112,11 +112,16 @@ pub type thread_latency_qos_policy_t = *mut thread_latency_qos_policy; pub type thread_throughput_qos_policy_data_t = thread_throughput_qos_policy; pub type thread_throughput_qos_policy_t = *mut thread_throughput_qos_policy; +pub type pthread_introspection_hook_t = + extern "C" fn(event: ::c_uint, thread: ::pthread_t, addr: *mut ::c_void, size: ::size_t); + pub type vm_statistics_t = *mut vm_statistics; pub type vm_statistics_data_t = vm_statistics; pub type vm_statistics64_t = *mut vm_statistics64; pub type vm_statistics64_data_t = vm_statistics64; +pub type task_t = ::mach_port_t; + pub type sysdir_search_path_enumeration_state = ::c_uint; pub type CCStatus = i32; @@ -741,8 +746,9 @@ s! { pub bytes_free: ::size_t, } - pub struct malloc_zone_t { - __private: [::uintptr_t; 18], // FIXME: keeping private for now + pub struct vm_range_t { + pub address: ::vm_address_t, + pub size: ::vm_size_t, } // sched.h @@ -2956,6 +2962,11 @@ pub const AT_SYMLINK_NOFOLLOW: ::c_int = 0x0020; pub const AT_SYMLINK_FOLLOW: ::c_int = 0x0040; pub const AT_REMOVEDIR: ::c_int = 0x0080; +pub const PTHREAD_INTROSPECTION_THREAD_CREATE: ::c_uint = 1; +pub const PTHREAD_INTROSPECTION_THREAD_START: ::c_uint = 2; +pub const PTHREAD_INTROSPECTION_THREAD_TERMINATE: ::c_uint = 3; +pub const PTHREAD_INTROSPECTION_THREAD_DESTROY: ::c_uint = 4; + pub const TIOCMODG: ::c_ulong = 0x40047403; pub const TIOCMODS: ::c_ulong = 0x80047404; pub const TIOCM_LE: ::c_int = 0x1; @@ -4226,6 +4237,8 @@ pub const RTF_CONDEMNED: ::c_int = 0x2000000; pub const RTF_IFREF: ::c_int = 0x4000000; pub const RTF_PROXY: ::c_int = 0x8000000; pub const RTF_ROUTER: ::c_int = 0x10000000; +pub const RTF_DEAD: ::c_int = 0x20000000; +pub const RTF_GLOBAL: ::c_int = 0x40000000; pub const RTM_VERSION: ::c_int = 5; @@ -4289,6 +4302,9 @@ pub const PROC_PIDTASKINFO: ::c_int = 4; pub const PROC_PIDTHREADINFO: ::c_int = 5; pub const PROC_PIDVNODEPATHINFO: ::c_int = 9; pub const PROC_PIDPATHINFO_MAXSIZE: ::c_int = 4096; +pub const PROC_CSM_ALL: ::c_uint = 0x0001; +pub const PROC_CSM_NOSMT: ::c_uint = 0x0002; +pub const PROC_CSM_TECS: ::c_uint = 0x0004; pub const MAXCOMLEN: usize = 16; pub const MAXTHREADNAMESIZE: usize = 64; @@ -4785,6 +4801,12 @@ extern "C" { pub fn pthread_getname_np(thread: ::pthread_t, name: *mut ::c_char, len: ::size_t) -> ::c_int; pub fn pthread_mach_thread_np(thread: ::pthread_t) -> ::mach_port_t; pub fn pthread_from_mach_thread_np(port: ::mach_port_t) -> ::pthread_t; + pub fn pthread_create_from_mach_thread( + thread: *mut ::pthread_t, + attr: *const ::pthread_attr_t, + f: extern "C" fn(*mut ::c_void) -> *mut ::c_void, + value: *mut ::c_void, + ) -> ::c_int; 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; @@ -4840,6 +4862,24 @@ extern "C" { policy: ::c_int, param: *const sched_param, ) -> ::c_int; + + // Available from Big Sur + pub fn pthread_introspection_hook_install( + hook: ::pthread_introspection_hook_t, + ) -> ::pthread_introspection_hook_t; + pub fn pthread_introspection_setspecific_np( + thread: ::pthread_t, + key: ::pthread_key_t, + value: *const ::c_void, + ) -> ::c_int; + pub fn pthread_introspection_getspecific_np( + thread: ::pthread_t, + key: ::pthread_key_t, + ) -> *mut ::c_void; + pub fn pthread_jit_write_protect_np(enabled: ::c_int); + pub fn pthread_jit_write_protect_supported_np() -> ::c_int; + pub fn pthread_cpu_number_np(cpu_number_out: *mut ::size_t) -> ::c_int; + pub fn thread_policy_set( thread: thread_t, flavor: thread_policy_flavor_t, @@ -4894,6 +4934,12 @@ extern "C" { flags: ::c_int, data: *mut ::c_void, ) -> ::c_int; + pub fn fmount( + src: *const ::c_char, + fd: ::c_int, + 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 quotactl( special: *const ::c_char, @@ -5070,6 +5116,20 @@ extern "C" { 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_setarchpref_np( + attr: *mut posix_spawnattr_t, + count: ::size_t, + pref: *mut ::cpu_type_t, + subpref: *mut ::cpu_subtype_t, + ocount: *mut ::size_t, + ) -> ::c_int; + pub fn posix_spawnattr_getarchpref_np( + attr: *const posix_spawnattr_t, + count: ::size_t, + pref: *mut ::cpu_type_t, + subpref: *mut ::cpu_subtype_t, + ocount: *mut ::size_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; @@ -5143,6 +5203,14 @@ extern "C" { pub fn memset_pattern8(b: *mut ::c_void, pattern8: *const ::c_void, len: ::size_t); pub fn memset_pattern16(b: *mut ::c_void, pattern16: *const ::c_void, len: ::size_t); + // Inherited from BSD but available from Big Sur only + pub fn strtonum( + __numstr: *const ::c_char, + __minval: ::c_longlong, + __maxval: ::c_longlong, + errstrp: *mut *const ::c_char, + ) -> ::c_longlong; + pub fn mstats() -> mstats; pub fn malloc_printf(format: *const ::c_char, ...); pub fn malloc_zone_check(zone: *mut ::malloc_zone_t) -> ::boolean_t; @@ -5212,6 +5280,12 @@ extern "C" { pub fn proc_kmsgbuf(buffer: *mut ::c_void, buffersize: u32) -> ::c_int; pub fn proc_libversion(major: *mut ::c_int, mintor: *mut ::c_int) -> ::c_int; pub fn proc_pid_rusage(pid: ::c_int, flavor: ::c_int, buffer: *mut rusage_info_t) -> ::c_int; + + // Available from Big Sur + pub fn proc_set_no_smt() -> ::c_int; + pub fn proc_setthread_no_smt() -> ::c_int; + pub fn proc_set_csm(flags: u32) -> ::c_int; + pub fn proc_setthread_csm(flags: u32) -> ::c_int; /// # Notes /// /// `id` is of type [`uuid_t`]. @@ -5259,11 +5333,14 @@ extern "C" { out_processor_infoCnt: *mut mach_msg_type_number_t, ) -> ::kern_return_t; - pub static mut mach_task_self_: mach_port_t; - pub fn task_for_pid(host: mach_port_t, pid: ::pid_t, task: *mut mach_port_t) - -> ::kern_return_t; + pub static mut mach_task_self_: ::mach_port_t; + pub fn task_for_pid( + host: ::mach_port_t, + pid: ::pid_t, + task: *mut ::mach_port_t, + ) -> ::kern_return_t; pub fn task_info( - host: mach_port_t, + host: ::mach_port_t, flavor: task_flavor_t, task_info_out: task_info_t, task_info_count: *mut mach_msg_type_number_t, @@ -5288,13 +5365,14 @@ extern "C" { pub static vm_page_size: vm_size_t; } -pub unsafe fn mach_task_self() -> mach_port_t { +pub unsafe fn mach_task_self() -> ::mach_port_t { mach_task_self_ } cfg_if! { if #[cfg(target_os = "macos")] { extern "C" { + pub fn clock_settime(clock_id: ::clockid_t, tp: *const ::timespec) -> ::c_int; pub fn memmem( haystack: *const ::c_void, haystacklen: ::size_t, diff --git a/vendor/libc/src/unix/bsd/freebsdlike/dragonfly/mod.rs b/vendor/libc/src/unix/bsd/freebsdlike/dragonfly/mod.rs index 4b99038784..e9dfc8a68f 100644 --- a/vendor/libc/src/unix/bsd/freebsdlike/dragonfly/mod.rs +++ b/vendor/libc/src/unix/bsd/freebsdlike/dragonfly/mod.rs @@ -106,6 +106,11 @@ s! { pub f_uid_uuid: ::uuid_t, } + #[deprecated( + since = "0.2.107", + note = "stat.st_blksize is an i64 and stat.st_qspare1 is replaced with \ + stat.st_blksize in DragonFly 5.8" + )] pub struct stat { pub st_ino: ::ino_t, pub st_nlink: ::nlink_t, @@ -701,6 +706,10 @@ cfg_if! { pub const RAND_MAX: ::c_int = 0x7fff_ffff; pub const PTHREAD_STACK_MIN: ::size_t = 16384; pub const SIGSTKSZ: ::size_t = 40960; +pub const SIGCKPT: ::c_int = 33; +pub const SIGCKPTEXIT: ::c_int = 34; +pub const CKPT_FREEZE: ::c_int = 0x1; +pub const CKPT_THAW: ::c_int = 0x2; pub const MADV_INVAL: ::c_int = 10; pub const MADV_SETMAP: ::c_int = 11; pub const O_CLOEXEC: ::c_int = 0x00020000; @@ -715,6 +724,9 @@ pub const RLIMIT_POSIXLOCKS: ::c_int = 11; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: ::rlim_t = 12; +#[deprecated(since = "0.2.105", note = "Only exists on FreeBSD, not DragonFly BSD")] +pub const XU_NGROUPS: ::c_int = 16; + pub const Q_GETQUOTA: ::c_int = 0x300; pub const Q_SETQUOTA: ::c_int = 0x400; @@ -875,6 +887,13 @@ pub const EV_ERROR: u16 = 0x4000; pub const EV_EOF: u16 = 0x8000; pub const EV_SYSFLAGS: u16 = 0xf000; +pub const FIODNAME: ::c_ulong = 0x80106678; +#[deprecated( + since = "0.2.106", + note = "FIODGNAME is not defined on DragonFly BSD. See FIODNAME." +)] +pub const FIODGNAME: ::c_ulong = 0x80106678; + pub const NOTE_TRIGGER: u32 = 0x01000000; pub const NOTE_FFNOP: u32 = 0x00000000; pub const NOTE_FFAND: u32 = 0x40000000; @@ -1356,6 +1375,14 @@ extern "C" { pub fn aio_waitcomplete(iocbp: *mut *mut aiocb, timeout: *mut ::timespec) -> ::c_int; + #[deprecated(since = "0.2.107", note = "len should be of type size_t")] + pub fn devname_r( + dev: ::dev_t, + mode: ::mode_t, + buf: *mut ::c_char, + len: ::c_int, + ) -> *mut ::c_char; + pub fn waitid( idtype: idtype_t, id: ::id_t, @@ -1404,6 +1431,8 @@ extern "C" { pub fn updlastlogx(fname: *const ::c_char, uid: ::uid_t, ll: *mut lastlogx) -> ::c_int; pub fn getutxuser(name: *const ::c_char) -> utmpx; pub fn utmpxname(file: *const ::c_char) -> ::c_int; + + pub fn sys_checkpoint(tpe: ::c_int, fd: ::c_int, pid: ::pid_t, retval: ::c_int) -> ::c_int; } #[link(name = "rt")] 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 a0b510514f..863de940f4 100644 --- a/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs +++ b/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs @@ -191,6 +191,7 @@ cfg_if! { pub const ELAST: ::c_int = 96; pub const RAND_MAX: ::c_int = 0x7fff_fffd; +pub const KI_NSPARE_PTR: usize = 6; extern "C" { // Return type ::c_int was removed in FreeBSD 12 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 05cadd1de9..e7b44b3eb0 100644 --- a/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs +++ b/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs @@ -26,6 +26,16 @@ s! { pub udata: *mut ::c_void, pub ext: [u64; 4], } + + pub struct kvm_page { + pub version: ::c_uint, + pub paddr: ::c_ulong, + pub kmap_vaddr: ::c_ulong, + pub dmap_vaddr: ::c_ulong, + pub prot: ::vm_prot_t, + pub offset: ::u_long, + pub len: ::size_t, + } } s_no_extra_traits! { @@ -190,28 +200,13 @@ cfg_if! { } } -pub const F_ADD_SEALS: ::c_int = 19; -pub const F_GET_SEALS: ::c_int = 20; -pub const F_SEAL_SEAL: ::c_int = 0x0001; -pub const F_SEAL_SHRINK: ::c_int = 0x0002; -pub const F_SEAL_GROW: ::c_int = 0x0004; -pub const F_SEAL_WRITE: ::c_int = 0x0008; - -pub const GRND_NONBLOCK: ::c_uint = 0x1; -pub const GRND_RANDOM: ::c_uint = 0x2; - pub const RAND_MAX: ::c_int = 0x7fff_fffd; - -pub const PROC_ASLR_CTL: ::c_int = 13; -pub const PROC_ASLR_STATUS: ::c_int = 14; - -pub const PROC_PROCCTL_MD_MIN: ::c_int = 0x10000000; - -pub const SO_DOMAIN: ::c_int = 0x1019; - -pub const EINTEGRITY: ::c_int = 97; pub const ELAST: ::c_int = 97; +/// max length of devicename +pub const SPECNAMELEN: ::c_int = 63; +pub const KI_NSPARE_PTR: usize = 6; + extern "C" { pub fn setgrent(); pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; 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 93ef2a2ad4..e8c4a4af2c 100644 --- a/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs +++ b/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs @@ -4,6 +4,9 @@ pub type nlink_t = u64; pub type dev_t = u64; pub type ino_t = ::c_ulong; pub type shmatt_t = ::c_uint; +pub type kpaddr_t = u64; +pub type kssize_t = i64; +pub type domainset_t = __c_anonymous_domainset; s! { pub struct shmid_ds { @@ -37,6 +40,20 @@ s! { pub sc_ngroups: ::c_int, pub sc_groups: [::gid_t; 1], } + + pub struct kvm_page { + pub kp_version: ::u_int, + pub kp_paddr: ::kpaddr_t, + pub kp_kmap_vaddr: ::kvaddr_t, + pub kp_dmap_vaddr: ::kvaddr_t, + pub kp_prot: ::vm_prot_t, + pub kp_offset: ::off_t, + pub kp_len: ::size_t, + } + + pub struct __c_anonymous_domainset { + _priv: [::uintptr_t; 4], + } } s_no_extra_traits! { @@ -201,32 +218,21 @@ cfg_if! { } } -pub const F_ADD_SEALS: ::c_int = 19; -pub const F_GET_SEALS: ::c_int = 20; -pub const F_SEAL_SEAL: ::c_int = 0x0001; -pub const F_SEAL_SHRINK: ::c_int = 0x0002; -pub const F_SEAL_GROW: ::c_int = 0x0004; -pub const F_SEAL_WRITE: ::c_int = 0x0008; - -pub const GRND_NONBLOCK: ::c_uint = 0x1; -pub const GRND_RANDOM: ::c_uint = 0x2; - pub const RAND_MAX: ::c_int = 0x7fff_ffff; - -pub const SO_DOMAIN: ::c_int = 0x1019; - -pub const EINTEGRITY: ::c_int = 97; pub const ELAST: ::c_int = 97; -pub const GRND_INSECURE: ::c_uint = 0x4; -pub const PROC_ASLR_CTL: ::c_int = 13; -pub const PROC_ASLR_STATUS: ::c_int = 14; -pub const PROC_PROTMAX_CTL: ::c_int = 15; -pub const PROC_PROTMAX_STATUS: ::c_int = 16; -pub const PROC_PROCCTL_MD_MIN: ::c_int = 0x10000000; +pub const KF_TYPE_EVENTFD: ::c_int = 13; + +/// max length of devicename +pub const SPECNAMELEN: ::c_int = 255; +pub const KI_NSPARE_PTR: usize = 5; -pub const LOCAL_CREDS_PERSISTENT: ::c_int = 3; -pub const SCM_CREDS2: ::c_int = 0x08; +/// domainset policies +pub const DOMAINSET_POLICY_INVALID: ::c_int = 0; +pub const DOMAINSET_POLICY_ROUNDROBIN: ::c_int = 1; +pub const DOMAINSET_POLICY_FIRSTTOUCH: ::c_int = 2; +pub const DOMAINSET_POLICY_PREFER: ::c_int = 3; +pub const DOMAINSET_POLICY_INTERLEAVE: ::c_int = 4; f! { pub fn SOCKCRED2SIZE(ngrps: usize) -> usize { @@ -259,6 +265,8 @@ extern "C" { rmtp: *mut ::timespec, ) -> ::c_int; + pub fn eventfd(init: ::c_uint, flags: ::c_int) -> ::c_int; + pub fn fdatasync(fd: ::c_int) -> ::c_int; pub fn getrandom(buf: *mut ::c_void, buflen: ::size_t, flags: ::c_uint) -> ::ssize_t; @@ -267,6 +275,37 @@ extern "C" { pub fn setproctitle_fast(fmt: *const ::c_char, ...); pub fn timingsafe_bcmp(a: *const ::c_void, b: *const ::c_void, len: ::size_t) -> ::c_int; pub fn timingsafe_memcmp(a: *const ::c_void, b: *const ::c_void, len: ::size_t) -> ::c_int; + + pub fn cpuset_getdomain( + level: ::cpulevel_t, + which: ::cpuwhich_t, + id: ::id_t, + setsize: ::size_t, + mask: *mut ::domainset_t, + policy: *mut ::c_int, + ) -> ::c_int; + pub fn cpuset_setdomain( + level: ::cpulevel_t, + which: ::cpuwhich_t, + id: ::id_t, + setsize: ::size_t, + mask: *const ::domainset_t, + policy: ::c_int, + ) -> ::c_int; + + pub fn copy_file_range( + infd: ::c_int, + inoffp: *mut ::off_t, + outfd: ::c_int, + outoffp: *mut ::off_t, + len: ::size_t, + flags: ::c_uint, + ) -> ::ssize_t; +} + +#[link(name = "kvm")] +extern "C" { + pub fn kvm_kerndisp(kd: *mut ::kvm_t) -> ::kssize_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 cc22a01536..ca9ad8a190 100644 --- a/vendor/libc/src/unix/bsd/freebsdlike/freebsd/mod.rs +++ b/vendor/libc/src/unix/bsd/freebsdlike/freebsd/mod.rs @@ -1,7 +1,13 @@ pub type fflags_t = u32; pub type clock_t = i32; -pub type lwpid_t = i32; +pub type vm_prot_t = u_char; +pub type kvaddr_t = u64; +pub type segsz_t = isize; +pub type __fixpt_t = u32; +pub type fixpt_t = __fixpt_t; +pub type __lwpid_t = i32; +pub type lwpid_t = __lwpid_t; pub type blksize_t = i32; pub type clockid_t = ::c_int; pub type sem_t = _sem; @@ -26,6 +32,14 @@ pub type pthread_barrierattr_t = *mut __c_anonymous_pthread_barrierattr; pub type pthread_barrier_t = *mut __c_anonymous_pthread_barrier; pub type uuid_t = ::uuid; +pub type u_int = ::c_uint; +pub type u_char = ::c_uchar; +pub type u_long = ::c_ulong; +pub type u_short = ::c_ushort; + +// It's an alias over "struct __kvm_t". However, its fields aren't supposed to be used directly, +// making the type definition system dependent. Better not bind it exactly. +pub type kvm_t = ::c_void; s! { pub struct aiocb { @@ -126,6 +140,24 @@ s! { pub pve_path: *mut ::c_char, } + pub struct ptrace_lwpinfo { + pub pl_lwpid: lwpid_t, + pub pl_event: ::c_int, + pub pl_flags: ::c_int, + pub pl_sigmask: ::sigset_t, + pub pl_siglist: ::sigset_t, + pub pl_siginfo: ::siginfo_t, + pub pl_tdname: [::c_char; ::MAXCOMLEN as usize + 1], + pub pl_child_pid: ::pid_t, + pub pl_syscall_code: ::c_uint, + pub pl_syscall_narg: ::c_uint, + } + + pub struct ptrace_sc_ret { + pub sr_retval: [::register_t; 2], + pub sr_error: ::c_int, + } + pub struct cpuset_t { #[cfg(target_pointer_width = "64")] __bits: [::c_long; 4], @@ -218,10 +250,6 @@ s! { pub kve_path: [[::c_char; 32]; 32], } - pub struct kinfo_proc { - __pad0: [[::uintptr_t; 17]; 8], - } - pub struct filestat { fs_type: ::c_int, fs_flags: ::c_int, @@ -259,6 +287,164 @@ s! { pub struct __c_anonymous__timer { _priv: [::c_int; 3], } + + /// Used to hold a copy of the command line, if it had a sane length. + pub struct pargs { + /// Reference count. + pub ar_ref: u_int, + /// Length. + pub ar_length: u_int, + /// Arguments. + pub ar_args: [::c_uchar; 1], + } + + pub struct priority { + /// Scheduling class. + pub pri_class: u_char, + /// Normal priority level. + pub pri_level: u_char, + /// Priority before propagation. + pub pri_native: u_char, + /// User priority based on p_cpu and p_nice. + pub pri_user: u_char, + } + + pub struct kinfo_proc { + pub ki_structsize: ::c_int, + pub ki_layout: ::c_int, + pub ki_args: *mut pargs, + // This is normally "struct proc". + pub ki_paddr: *mut ::c_void, + // This is normally "struct user". + pub ki_addr: *mut ::c_void, + // This is normally "struct vnode". + pub ki_tracep: *mut ::c_void, + // This is normally "struct vnode". + pub ki_textvp: *mut ::c_void, + // This is normally "struct filedesc". + pub ki_fd: *mut ::c_void, + // This is normally "struct vmspace". + pub ki_vmspace: *mut ::c_void, + #[cfg(freebsd13)] + pub ki_wchan: *const ::c_void, + #[cfg(not(freebsd13))] + pub ki_wchan: *mut ::c_void, + pub ki_pid: ::pid_t, + pub ki_ppid: ::pid_t, + pub ki_pgid: ::pid_t, + pub ki_tpgid: ::pid_t, + pub ki_sid: ::pid_t, + pub ki_tsid: ::pid_t, + pub ki_jobc: ::c_short, + pub ki_spare_short1: ::c_short, + #[cfg(any(freebsd12, freebsd13))] + pub ki_tdev_freebsd11: u32, + #[cfg(freebsd11)] + pub ki_tdev: ::dev_t, + pub ki_siglist: ::sigset_t, + pub ki_sigmask: ::sigset_t, + pub ki_sigignore: ::sigset_t, + pub ki_sigcatch: ::sigset_t, + pub ki_uid: ::uid_t, + pub ki_ruid: ::uid_t, + pub ki_svuid: ::uid_t, + pub ki_rgid: ::gid_t, + pub ki_svgid: ::gid_t, + pub ki_ngroups: ::c_short, + pub ki_spare_short2: ::c_short, + pub ki_groups: [::gid_t; ::KI_NGROUPS], + pub ki_size: ::vm_size_t, + pub ki_rssize: segsz_t, + pub ki_swrss: segsz_t, + pub ki_tsize: segsz_t, + pub ki_dsize: segsz_t, + pub ki_ssize: segsz_t, + pub ki_xstat: ::u_short, + pub ki_acflag: ::u_short, + pub ki_pctcpu: fixpt_t, + pub ki_estcpu: u_int, + pub ki_slptime: u_int, + pub ki_swtime: u_int, + pub ki_cow: u_int, + pub ki_runtime: u64, + pub ki_start: ::timeval, + pub ki_childtime: ::timeval, + pub ki_flag: ::c_long, + pub ki_kiflag: ::c_long, + pub ki_traceflag: ::c_int, + pub ki_stat: ::c_char, + pub ki_nice: i8, // signed char + pub ki_lock: ::c_char, + pub ki_rqindex: ::c_char, + pub ki_oncpu_old: ::c_uchar, + pub ki_lastcpu_old: ::c_uchar, + pub ki_tdname: [::c_char; TDNAMLEN + 1], + pub ki_wmesg: [::c_char; ::WMESGLEN + 1], + pub ki_login: [::c_char; ::LOGNAMELEN + 1], + pub ki_lockname: [::c_char; ::LOCKNAMELEN + 1], + pub ki_comm: [::c_char; ::COMMLEN + 1], + pub ki_emul: [::c_char; ::KI_EMULNAMELEN + 1], + pub ki_loginclass: [::c_char; ::LOGINCLASSLEN + 1], + pub ki_moretdname: [::c_char; ::MAXCOMLEN - ::TDNAMLEN + 1], + pub ki_sparestrings: [[::c_char; 23]; 2], // little hack to allow PartialEq + pub ki_spareints: [::c_int; ::KI_NSPARE_INT], + #[cfg(freebsd13)] + pub ki_tdev: u64, + #[cfg(freebsd12)] + pub ki_tdev: ::dev_t, + pub ki_oncpu: ::c_int, + pub ki_lastcpu: ::c_int, + pub ki_tracer: ::c_int, + pub ki_flag2: ::c_int, + pub ki_fibnum: ::c_int, + pub ki_cr_flags: u_int, + pub ki_jid: ::c_int, + pub ki_numthreads: ::c_int, + pub ki_tid: lwpid_t, + pub ki_pri: priority, + pub ki_rusage: ::rusage, + pub ki_rusage_ch: ::rusage, + // This is normally "struct pcb". + pub ki_pcb: *mut ::c_void, + pub ki_kstack: *mut ::c_void, + pub ki_udata: *mut ::c_void, + // This is normally "struct thread". + pub ki_tdaddr: *mut ::c_void, + // This is normally "struct pwddesc". + #[cfg(freebsd13)] + pub ki_pd: *mut ::c_void, + pub ki_spareptrs: [*mut ::c_void; ::KI_NSPARE_PTR], + pub ki_sparelongs: [::c_long; ::KI_NSPARE_LONG], + pub ki_sflag: ::c_long, + pub ki_tdflags: ::c_long, + } + + pub struct kvm_swap { + pub ksw_devname: [::c_char; 32], + pub ksw_used: u_int, + pub ksw_total: u_int, + pub ksw_flags: ::c_int, + pub ksw_reserved1: u_int, + pub ksw_reserved2: u_int, + } + + pub struct nlist { + /// symbol name (in memory) + pub n_name: *const ::c_char, + /// type defines + pub n_type: ::c_uchar, + /// "type" and binding information + pub n_other: ::c_char, + /// used by stab entries + pub n_desc: ::c_short, + pub n_value: ::c_ulong, + } + + pub struct kvm_nlist { + pub n_name: *const ::c_char, + pub n_type: ::c_uchar, + pub n_value: ::kvaddr_t, + } } s_no_extra_traits! { @@ -609,6 +795,8 @@ pub const EXTATTR_NAMESPACE_SYSTEM: ::c_int = 2; pub const PTHREAD_STACK_MIN: ::size_t = MINSIGSTKSZ; pub const PTHREAD_MUTEX_ADAPTIVE_NP: ::c_int = 4; +pub const PTHREAD_MUTEX_STALLED: ::c_int = 0; +pub const PTHREAD_MUTEX_ROBUST: ::c_int = 1; pub const SIGSTKSZ: ::size_t = MINSIGSTKSZ + 32768; pub const SF_NODISKIO: ::c_int = 0x00000001; pub const SF_MNOWAIT: ::c_int = 0x00000002; @@ -626,6 +814,7 @@ pub const ENOTCAPABLE: ::c_int = 93; pub const ECAPMODE: ::c_int = 94; pub const ENOTRECOVERABLE: ::c_int = 95; pub const EOWNERDEAD: ::c_int = 96; +pub const EINTEGRITY: ::c_int = 97; pub const RLIMIT_NPTS: ::c_int = 11; pub const RLIMIT_SWAP: ::c_int = 12; pub const RLIMIT_KQUEUES: ::c_int = 13; @@ -640,6 +829,8 @@ pub const NI_NUMERICSERV: ::c_int = 0x00000008; pub const NI_DGRAM: ::c_int = 0x00000010; pub const NI_NUMERICSCOPE: ::c_int = 0x00000020; +pub const XU_NGROUPS: ::c_int = 16; + pub const Q_GETQUOTA: ::c_int = 0x700; pub const Q_SETQUOTA: ::c_int = 0x800; @@ -714,7 +905,6 @@ pub const NOTE_USECONDS: u32 = 0x00000004; pub const NOTE_NSECONDS: u32 = 0x00000008; pub const MADV_PROTECT: ::c_int = 10; -pub const RUSAGE_THREAD: ::c_int = 1; #[doc(hidden)] #[deprecated( @@ -875,6 +1065,7 @@ pub const H4DISC: ::c_int = 0x7; pub const BIOCSETFNR: ::c_ulong = 0x80104282; +pub const FIODGNAME: ::c_ulong = 0x80106678; pub const FIONWRITE: ::c_ulong = 0x40046677; pub const FIONSPACE: ::c_ulong = 0x40046676; pub const FIOSEEKDATA: ::c_ulong = 0xc0086661; @@ -901,6 +1092,8 @@ pub const MNT_UNION: ::c_int = 0x00000020; pub const MNT_EXPUBLIC: ::c_int = 0x20000000; pub const MNT_NONBUSY: ::c_int = 0x04000000; +pub const SCM_CREDS2: ::c_int = 0x08; + pub const SO_BINTIME: ::c_int = 0x2000; pub const SO_NO_OFFLOAD: ::c_int = 0x4000; pub const SO_NO_DDP: ::c_int = 0x8000; @@ -914,12 +1107,29 @@ pub const SO_SETFIB: ::c_int = 0x1014; pub const SO_USER_COOKIE: ::c_int = 0x1015; pub const SO_PROTOCOL: ::c_int = 0x1016; pub const SO_PROTOTYPE: ::c_int = SO_PROTOCOL; +pub const SO_DOMAIN: ::c_int = 0x1019; pub const SO_VENDOR: ::c_int = 0x80000000; pub const LOCAL_CREDS: ::c_int = 2; +pub const LOCAL_CREDS_PERSISTENT: ::c_int = 3; pub const LOCAL_CONNWAIT: ::c_int = 4; pub const LOCAL_VENDOR: ::c_int = SO_VENDOR; +pub const PL_EVENT_NONE: ::c_int = 0; +pub const PL_EVENT_SIGNAL: ::c_int = 1; +pub const PL_FLAG_SA: ::c_int = 0x01; +pub const PL_FLAG_BOUND: ::c_int = 0x02; +pub const PL_FLAG_SCE: ::c_int = 0x04; +pub const PL_FLAG_SCX: ::c_int = 0x08; +pub const PL_FLAG_EXEC: ::c_int = 0x10; +pub const PL_FLAG_SI: ::c_int = 0x20; +pub const PL_FLAG_FORKED: ::c_int = 0x40; +pub const PL_FLAG_CHILD: ::c_int = 0x80; +pub const PL_FLAG_BORN: ::c_int = 0x100; +pub const PL_FLAG_EXITED: ::c_int = 0x200; +pub const PL_FLAG_VFORKED: ::c_int = 0x400; +pub const PL_FLAG_VFORK_DONE: ::c_int = 0x800; + pub const PT_LWPINFO: ::c_int = 13; pub const PT_GETNUMLWPS: ::c_int = 14; pub const PT_GETLWPLIST: ::c_int = 15; @@ -934,6 +1144,8 @@ pub const PT_FOLLOW_FORK: ::c_int = 23; pub const PT_LWP_EVENTS: ::c_int = 24; pub const PT_GET_EVENT_MASK: ::c_int = 25; pub const PT_SET_EVENT_MASK: ::c_int = 26; +pub const PT_GET_SC_ARGS: ::c_int = 27; +pub const PT_GET_SC_RET: ::c_int = 28; pub const PT_GETREGS: ::c_int = 33; pub const PT_SETREGS: ::c_int = 34; pub const PT_GETFPREGS: ::c_int = 35; @@ -965,8 +1177,40 @@ pub const PROC_TRAPCAP_CTL: ::c_int = 9; pub const PROC_TRAPCAP_STATUS: ::c_int = 10; pub const PROC_PDEATHSIG_CTL: ::c_int = 11; pub const PROC_PDEATHSIG_STATUS: ::c_int = 12; +pub const PROC_ASLR_CTL: ::c_int = 13; +pub const PROC_ASLR_STATUS: ::c_int = 14; +pub const PROC_PROTMAX_CTL: ::c_int = 15; +pub const PROC_PROTMAX_STATUS: ::c_int = 16; pub const PROC_STACKGAP_CTL: ::c_int = 17; pub const PROC_STACKGAP_STATUS: ::c_int = 18; +pub const PROC_PROCCTL_MD_MIN: ::c_int = 0x10000000; + +pub const PPROT_SET: ::c_int = 1; +pub const PPROT_CLEAR: ::c_int = 2; +pub const PPROT_DESCEND: ::c_int = 0x10; +pub const PPROT_INHERIT: ::c_int = 0x20; + +pub const PROC_TRACE_CTL_ENABLE: ::c_int = 1; +pub const PROC_TRACE_CTL_DISABLE: ::c_int = 2; +pub const PROC_TRACE_CTL_DISABLE_EXEC: ::c_int = 3; + +pub const PROC_TRAPCAP_CTL_ENABLE: ::c_int = 1; +pub const PROC_TRAPCAP_CTL_DISABLE: ::c_int = 2; + +pub const PROC_ASLR_FORCE_ENABLE: ::c_int = 1; +pub const PROC_ASLR_FORCE_DISABLE: ::c_int = 2; +pub const PROC_ASLR_NOFORCE: ::c_int = 3; +pub const PROC_ASLR_ACTIVE: ::c_int = 0x80000000; + +pub const PROC_PROTMAX_FORCE_ENABLE: ::c_int = 1; +pub const PROC_PROTMAX_FORCE_DISABLE: ::c_int = 2; +pub const PROC_PROTMAX_NOFORCE: ::c_int = 3; +pub const PROC_PROTMAX_ACTIVE: ::c_int = 0x80000000; + +pub const PROC_STACKGAP_ENABLE: ::c_int = 0x0001; +pub const PROC_STACKGAP_DISABLE: ::c_int = 0x0002; +pub const PROC_STACKGAP_ENABLE_EXEC: ::c_int = 0x0004; +pub const PROC_STACKGAP_DISABLE_EXEC: ::c_int = 0x0008; pub const AF_SLOW: ::c_int = 33; pub const AF_SCLUSTER: ::c_int = 34; @@ -1433,14 +1677,28 @@ pub const UF_READONLY: ::c_ulong = 0x00001000; pub const UF_HIDDEN: ::c_ulong = 0x00008000; pub const SF_SNAPSHOT: ::c_ulong = 0x00200000; +// fcntl commands +pub const F_ADD_SEALS: ::c_int = 19; +pub const F_DUP2FD: ::c_int = 10; +pub const F_DUP2FD_CLOEXEC: ::c_int = 18; +pub const F_GET_SEALS: ::c_int = 20; pub const F_OGETLK: ::c_int = 7; pub const F_OSETLK: ::c_int = 8; pub const F_OSETLKW: ::c_int = 9; -pub const F_DUP2FD: ::c_int = 10; -pub const F_SETLK_REMOTE: ::c_int = 14; -pub const F_READAHEAD: ::c_int = 15; pub const F_RDAHEAD: ::c_int = 16; -pub const F_DUP2FD_CLOEXEC: ::c_int = 18; +pub const F_READAHEAD: ::c_int = 15; +pub const F_SETLK_REMOTE: ::c_int = 14; + +// for use with F_ADD_SEALS +pub const F_SEAL_GROW: ::c_int = 4; +pub const F_SEAL_SEAL: ::c_int = 1; +pub const F_SEAL_SHRINK: ::c_int = 2; +pub const F_SEAL_WRITE: ::c_int = 8; + +// For getrandom() +pub const GRND_NONBLOCK: ::c_uint = 0x1; +pub const GRND_RANDOM: ::c_uint = 0x2; +pub const GRND_INSECURE: ::c_uint = 0x4; // For realhostname* api pub const HOSTNAME_FOUND: ::c_int = 0; @@ -1459,8 +1717,248 @@ pub const RFLINUXTHPN: ::c_int = 65536; pub const RFTSIGZMB: ::c_int = 524288; pub const RFSPAWN: ::c_int = 2147483648; +// For eventfd +pub const EFD_SEMAPHORE: ::c_int = 0x1; +pub const EFD_NONBLOCK: ::c_int = 0x4; +pub const EFD_CLOEXEC: ::c_int = 0x100000; + pub const MALLOCX_ZERO: ::c_int = 0x40; +/// size of returned wchan message +pub const WMESGLEN: usize = 8; +/// size of returned lock name +pub const LOCKNAMELEN: usize = 8; +/// size of returned thread name +pub const TDNAMLEN: usize = 16; +/// size of returned ki_comm name +pub const COMMLEN: usize = 19; +/// size of returned ki_emul +pub const KI_EMULNAMELEN: usize = 16; +/// number of groups in ki_groups +pub const KI_NGROUPS: usize = 16; +cfg_if! { + if #[cfg(freebsd11)] { + pub const KI_NSPARE_INT: usize = 4; + } else { + pub const KI_NSPARE_INT: usize = 2; + } +} +pub const KI_NSPARE_LONG: usize = 12; +/// Flags for the process credential. +pub const KI_CRF_CAPABILITY_MODE: usize = 0x00000001; +/// Steal a bit from ki_cr_flags to indicate that the cred had more than +/// KI_NGROUPS groups. +pub const KI_CRF_GRP_OVERFLOW: usize = 0x80000000; +/// controlling tty vnode active +pub const KI_CTTY: usize = 0x00000001; +/// session leader +pub const KI_SLEADER: usize = 0x00000002; +/// proc blocked on lock ki_lockname +pub const KI_LOCKBLOCK: usize = 0x00000004; +/// size of returned ki_login +pub const LOGNAMELEN: usize = 17; +/// size of returned ki_loginclass +pub const LOGINCLASSLEN: usize = 17; + +pub const KF_ATTR_VALID: ::c_int = 0x0001; +pub const KF_TYPE_NONE: ::c_int = 0; +pub const KF_TYPE_VNODE: ::c_int = 1; +pub const KF_TYPE_SOCKET: ::c_int = 2; +pub const KF_TYPE_PIPE: ::c_int = 3; +pub const KF_TYPE_FIFO: ::c_int = 4; +pub const KF_TYPE_KQUEUE: ::c_int = 5; +pub const KF_TYPE_MQUEUE: ::c_int = 7; +pub const KF_TYPE_SHM: ::c_int = 8; +pub const KF_TYPE_SEM: ::c_int = 9; +pub const KF_TYPE_PTS: ::c_int = 10; +pub const KF_TYPE_PROCDESC: ::c_int = 11; +pub const KF_TYPE_DEV: ::c_int = 12; +pub const KF_TYPE_UNKNOWN: ::c_int = 255; + +pub const KF_VTYPE_VNON: ::c_int = 0; +pub const KF_VTYPE_VREG: ::c_int = 1; +pub const KF_VTYPE_VDIR: ::c_int = 2; +pub const KF_VTYPE_VBLK: ::c_int = 3; +pub const KF_VTYPE_VCHR: ::c_int = 4; +pub const KF_VTYPE_VLNK: ::c_int = 5; +pub const KF_VTYPE_VSOCK: ::c_int = 6; +pub const KF_VTYPE_VFIFO: ::c_int = 7; +pub const KF_VTYPE_VBAD: ::c_int = 8; +pub const KF_VTYPE_UNKNOWN: ::c_int = 255; + +/// Current working directory +pub const KF_FD_TYPE_CWD: ::c_int = -1; +/// Root directory +pub const KF_FD_TYPE_ROOT: ::c_int = -2; +/// Jail directory +pub const KF_FD_TYPE_JAIL: ::c_int = -3; +/// Ktrace vnode +pub const KF_FD_TYPE_TRACE: ::c_int = -4; +pub const KF_FD_TYPE_TEXT: ::c_int = -5; +/// Controlling terminal +pub const KF_FD_TYPE_CTTY: ::c_int = -6; +pub const KF_FLAG_READ: ::c_int = 0x00000001; +pub const KF_FLAG_WRITE: ::c_int = 0x00000002; +pub const KF_FLAG_APPEND: ::c_int = 0x00000004; +pub const KF_FLAG_ASYNC: ::c_int = 0x00000008; +pub const KF_FLAG_FSYNC: ::c_int = 0x00000010; +pub const KF_FLAG_NONBLOCK: ::c_int = 0x00000020; +pub const KF_FLAG_DIRECT: ::c_int = 0x00000040; +pub const KF_FLAG_HASLOCK: ::c_int = 0x00000080; +pub const KF_FLAG_SHLOCK: ::c_int = 0x00000100; +pub const KF_FLAG_EXLOCK: ::c_int = 0x00000200; +pub const KF_FLAG_NOFOLLOW: ::c_int = 0x00000400; +pub const KF_FLAG_CREAT: ::c_int = 0x00000800; +pub const KF_FLAG_TRUNC: ::c_int = 0x00001000; +pub const KF_FLAG_EXCL: ::c_int = 0x00002000; +pub const KF_FLAG_EXEC: ::c_int = 0x00004000; + +pub const KVME_TYPE_NONE: ::c_int = 0; +pub const KVME_TYPE_DEFAULT: ::c_int = 1; +pub const KVME_TYPE_VNODE: ::c_int = 2; +pub const KVME_TYPE_SWAP: ::c_int = 3; +pub const KVME_TYPE_DEVICE: ::c_int = 4; +pub const KVME_TYPE_PHYS: ::c_int = 5; +pub const KVME_TYPE_DEAD: ::c_int = 6; +pub const KVME_TYPE_SG: ::c_int = 7; +pub const KVME_TYPE_MGTDEVICE: ::c_int = 8; +// Present in `sys/user.h` but is undefined for whatever reason... +// pub const KVME_TYPE_GUARD: ::c_int = 9; +pub const KVME_TYPE_UNKNOWN: ::c_int = 255; +pub const KVME_PROT_READ: ::c_int = 0x00000001; +pub const KVME_PROT_WRITE: ::c_int = 0x00000002; +pub const KVME_PROT_EXEC: ::c_int = 0x00000004; +pub const KVME_FLAG_COW: ::c_int = 0x00000001; +pub const KVME_FLAG_NEEDS_COPY: ::c_int = 0x00000002; +pub const KVME_FLAG_NOCOREDUMP: ::c_int = 0x00000004; +pub const KVME_FLAG_SUPER: ::c_int = 0x00000008; +pub const KVME_FLAG_GROWS_UP: ::c_int = 0x00000010; +pub const KVME_FLAG_GROWS_DOWN: ::c_int = 0x00000020; +cfg_if! { + if #[cfg(any(freebsd12, freebsd13))] { + pub const KVME_FLAG_USER_WIRED: ::c_int = 0x00000040; + } +} + +pub const KKST_MAXLEN: ::c_int = 1024; +/// Stack is valid. +pub const KKST_STATE_STACKOK: ::c_int = 0; +/// Stack swapped out. +pub const KKST_STATE_SWAPPED: ::c_int = 1; +pub const KKST_STATE_RUNNING: ::c_int = 2; + +// Constants about priority. +pub const PRI_MIN: ::c_int = 0; +pub const PRI_MAX: ::c_int = 255; +pub const PRI_MIN_ITHD: ::c_int = PRI_MIN; +pub const PRI_MAX_ITHD: ::c_int = PRI_MIN_REALTIME - 1; +pub const PI_REALTIME: ::c_int = PRI_MIN_ITHD + 0; +pub const PI_AV: ::c_int = PRI_MIN_ITHD + 4; +pub const PI_NET: ::c_int = PRI_MIN_ITHD + 8; +pub const PI_DISK: ::c_int = PRI_MIN_ITHD + 12; +pub const PI_TTY: ::c_int = PRI_MIN_ITHD + 16; +pub const PI_DULL: ::c_int = PRI_MIN_ITHD + 20; +pub const PI_SOFT: ::c_int = PRI_MIN_ITHD + 24; +pub const PRI_MIN_REALTIME: ::c_int = 48; +pub const PRI_MAX_REALTIME: ::c_int = PRI_MIN_KERN - 1; +pub const PRI_MIN_KERN: ::c_int = 80; +pub const PRI_MAX_KERN: ::c_int = PRI_MIN_TIMESHARE - 1; +pub const PSWP: ::c_int = PRI_MIN_KERN + 0; +pub const PVM: ::c_int = PRI_MIN_KERN + 4; +pub const PINOD: ::c_int = PRI_MIN_KERN + 8; +pub const PRIBIO: ::c_int = PRI_MIN_KERN + 12; +pub const PVFS: ::c_int = PRI_MIN_KERN + 16; +pub const PZERO: ::c_int = PRI_MIN_KERN + 20; +pub const PSOCK: ::c_int = PRI_MIN_KERN + 24; +pub const PWAIT: ::c_int = PRI_MIN_KERN + 28; +pub const PLOCK: ::c_int = PRI_MIN_KERN + 32; +pub const PPAUSE: ::c_int = PRI_MIN_KERN + 36; +pub const PRI_MIN_TIMESHARE: ::c_int = 120; +pub const PRI_MAX_TIMESHARE: ::c_int = PRI_MIN_IDLE - 1; +pub const PUSER: ::c_int = PRI_MIN_TIMESHARE; +pub const PRI_MIN_IDLE: ::c_int = 224; +pub const PRI_MAX_IDLE: ::c_int = PRI_MAX; + +// Resource utilization information. +pub const RUSAGE_THREAD: ::c_int = 1; + +cfg_if! { + if #[cfg(any(freebsd11, target_pointer_width = "32"))] { + pub const ARG_MAX: ::c_int = 256 * 1024; + } else { + pub const ARG_MAX: ::c_int = 2 * 256 * 1024; + } +} +pub const CHILD_MAX: ::c_int = 40; +/// max command name remembered +pub const MAXCOMLEN: usize = 19; +/// max interpreter file name length +pub const MAXINTERP: ::c_int = ::PATH_MAX; +/// max login name length (incl. NUL) +pub const MAXLOGNAME: ::c_int = 33; +/// max simultaneous processes +pub const MAXUPRC: ::c_int = CHILD_MAX; +/// max bytes for an exec function +pub const NCARGS: ::c_int = ARG_MAX; +/// /* max number groups +pub const NGROUPS: ::c_int = NGROUPS_MAX + 1; +/// max open files per process +pub const NOFILE: ::c_int = OPEN_MAX; +/// marker for empty group set member +pub const NOGROUP: ::c_int = 65535; +/// max hostname size +pub const MAXHOSTNAMELEN: ::c_int = 256; +/// max bytes in term canon input line +pub const MAX_CANON: ::c_int = 255; +/// max bytes in terminal input +pub const MAX_INPUT: ::c_int = 255; +/// max bytes in a file name +pub const NAME_MAX: ::c_int = 255; +pub const MAXSYMLINKS: ::c_int = 32; +/// max supplemental group id's +pub const NGROUPS_MAX: ::c_int = 1023; +/// max open files per process +pub const OPEN_MAX: ::c_int = 64; + +pub const _POSIX_ARG_MAX: ::c_int = 4096; +pub const _POSIX_LINK_MAX: ::c_int = 8; +pub const _POSIX_MAX_CANON: ::c_int = 255; +pub const _POSIX_MAX_INPUT: ::c_int = 255; +pub const _POSIX_NAME_MAX: ::c_int = 14; +pub const _POSIX_PIPE_BUF: ::c_int = 512; +pub const _POSIX_SSIZE_MAX: ::c_int = 32767; +pub const _POSIX_STREAM_MAX: ::c_int = 8; + +/// max ibase/obase values in bc(1) +pub const BC_BASE_MAX: ::c_int = 99; +/// max array elements in bc(1) +pub const BC_DIM_MAX: ::c_int = 2048; +/// max scale value in bc(1) +pub const BC_SCALE_MAX: ::c_int = 99; +/// max const string length in bc(1) +pub const BC_STRING_MAX: ::c_int = 1000; +/// max character class name size +pub const CHARCLASS_NAME_MAX: ::c_int = 14; +/// max weights for order keyword +pub const COLL_WEIGHTS_MAX: ::c_int = 10; +/// max expressions nested in expr(1) +pub const EXPR_NEST_MAX: ::c_int = 32; +/// max bytes in an input line +pub const LINE_MAX: ::c_int = 2048; +/// max RE's in interval notation +pub const RE_DUP_MAX: ::c_int = 255; + +pub const _POSIX2_BC_BASE_MAX: ::c_int = 99; +pub const _POSIX2_BC_DIM_MAX: ::c_int = 2048; +pub const _POSIX2_BC_SCALE_MAX: ::c_int = 99; +pub const _POSIX2_BC_STRING_MAX: ::c_int = 1000; +pub const _POSIX2_CHARCLASS_NAME_MAX: ::c_int = 14; +pub const _POSIX2_COLL_WEIGHTS_MAX: ::c_int = 2; +pub const _POSIX2_EQUIV_CLASS_MAX: ::c_int = 2; +pub const _POSIX2_EXPR_NEST_MAX: ::c_int = 32; +pub const _POSIX2_LINE_MAX: ::c_int = 2048; +pub const _POSIX2_RE_DUP_MAX: ::c_int = 255; + const_fn! { {const} fn _ALIGN(p: usize) -> usize { (p + _ALIGNBYTES) & !_ALIGNBYTES @@ -1579,6 +2077,13 @@ extern "C" { ) -> ::c_int; pub fn aio_write(aiocbp: *mut aiocb) -> ::c_int; + pub fn devname_r( + dev: ::dev_t, + mode: ::mode_t, + buf: *mut ::c_char, + len: ::c_int, + ) -> *mut ::c_char; + pub fn extattr_delete_fd( fd: ::c_int, attrnamespace: ::c_int, @@ -1700,11 +2205,6 @@ extern "C" { msgflg: ::c_int, ) -> ::c_int; pub fn cfmakesane(termios: *mut ::termios); - pub fn fexecve( - fd: ::c_int, - argv: *const *const ::c_char, - envp: *const *const ::c_char, - ) -> ::c_int; pub fn pdfork(fdp: *mut ::c_int, flags: ::c_int) -> ::pid_t; pub fn pdgetpid(fd: ::c_int, pidp: *mut ::pid_t) -> ::c_int; @@ -1791,6 +2291,9 @@ extern "C" { pub fn uuidgen(store: *mut uuid, count: ::c_int) -> ::c_int; + pub fn thr_kill(id: ::c_long, sig: ::c_int) -> ::c_int; + pub fn thr_kill2(pid: ::pid_t, id: ::c_long, sig: ::c_int) -> ::c_int; + pub fn thr_self(tid: *mut ::c_long) -> ::c_int; pub fn pthread_getthreadid_np() -> ::c_int; pub fn pthread_getaffinity_np( td: ::pthread_t, @@ -1803,6 +2306,17 @@ extern "C" { cpusetp: *const cpuset_t, ) -> ::c_int; + pub fn pthread_mutex_consistent(mutex: *mut ::pthread_mutex_t) -> ::c_int; + + pub fn pthread_mutexattr_getrobust( + attr: *mut ::pthread_mutexattr_t, + robust: *mut ::c_int, + ) -> ::c_int; + pub fn pthread_mutexattr_setrobust( + attr: *mut ::pthread_mutexattr_t, + robust: ::c_int, + ) -> ::c_int; + pub fn pthread_spin_init(lock: *mut pthread_spinlock_t, pshared: ::c_int) -> ::c_int; pub fn pthread_spin_destroy(lock: *mut pthread_spinlock_t) -> ::c_int; pub fn pthread_spin_lock(lock: *mut pthread_spinlock_t) -> ::c_int; @@ -1912,6 +2426,77 @@ extern "C" { pub fn nallocx(size: ::size_t, flags: ::c_int) -> ::size_t; pub fn procctl(idtype: ::idtype_t, id: ::id_t, cmd: ::c_int, data: *mut ::c_void) -> ::c_int; + + pub fn getpagesize() -> ::c_int; +} + +#[link(name = "kvm")] +extern "C" { + pub fn kvm_open( + execfile: *const ::c_char, + corefile: *const ::c_char, + swapfile: *const ::c_char, + flags: ::c_int, + errstr: *const ::c_char, + ) -> *mut kvm_t; + pub fn kvm_close(kd: *mut kvm_t) -> ::c_int; + pub fn kvm_dpcpu_setcpu(kd: *mut kvm_t, cpu: ::c_uint) -> ::c_int; + pub fn kvm_getargv(kd: *mut kvm_t, p: *const kinfo_proc, nchr: ::c_int) -> *mut *mut ::c_char; + pub fn kvm_getcptime(kd: *mut kvm_t, cp_time: *mut ::c_long) -> ::c_int; + pub fn kvm_getenvv(kd: *mut kvm_t, p: *const kinfo_proc, nchr: ::c_int) -> *mut *mut ::c_char; + pub fn kvm_geterr(kd: *mut kvm_t) -> *mut ::c_char; + pub fn kvm_getloadavg(kd: *mut kvm_t, loadavg: *mut ::c_double, nelem: ::c_int) -> ::c_int; + pub fn kvm_getmaxcpu(kd: *mut kvm_t) -> ::c_int; + pub fn kvm_getncpus(kd: *mut kvm_t) -> ::c_int; + pub fn kvm_getpcpu(kd: *mut kvm_t, cpu: ::c_int) -> *mut ::c_void; + pub fn kvm_counter_u64_fetch(kd: *mut kvm_t, base: ::c_ulong) -> u64; + pub fn kvm_getprocs( + kd: *mut kvm_t, + op: ::c_int, + arg: ::c_int, + cnt: *mut ::c_int, + ) -> *mut kinfo_proc; + pub fn kvm_getswapinfo( + kd: *mut kvm_t, + info: *mut kvm_swap, + maxswap: ::c_int, + flags: ::c_int, + ) -> ::c_int; + pub fn kvm_native(kd: *mut kvm_t) -> ::c_int; + pub fn kvm_nlist(kd: *mut kvm_t, nl: *mut nlist) -> ::c_int; + pub fn kvm_nlist2(kd: *mut kvm_t, nl: *mut kvm_nlist) -> ::c_int; + pub fn kvm_openfiles( + execfile: *const ::c_char, + corefile: *const ::c_char, + swapfile: *const ::c_char, + flags: ::c_int, + errbuf: *mut ::c_char, + ) -> *mut kvm_t; + pub fn kvm_read( + kd: *mut kvm_t, + addr: ::c_ulong, + buf: *mut ::c_void, + nbytes: ::size_t, + ) -> ::ssize_t; + pub fn kvm_read_zpcpu( + kd: *mut kvm_t, + base: ::c_ulong, + buf: *mut ::c_void, + size: ::size_t, + cpu: ::c_int, + ) -> ::ssize_t; + pub fn kvm_read2( + kd: *mut kvm_t, + addr: kvaddr_t, + buf: *mut ::c_void, + nbytes: ::size_t, + ) -> ::ssize_t; + pub fn kvm_write( + kd: *mut kvm_t, + addr: ::c_ulong, + buf: *const ::c_void, + nbytes: ::size_t, + ) -> ::ssize_t; } #[link(name = "util")] diff --git a/vendor/libc/src/unix/bsd/freebsdlike/mod.rs b/vendor/libc/src/unix/bsd/freebsdlike/mod.rs index da38f1abb0..66035f3fcd 100644 --- a/vendor/libc/src/unix/bsd/freebsdlike/mod.rs +++ b/vendor/libc/src/unix/bsd/freebsdlike/mod.rs @@ -724,6 +724,14 @@ pub const POLLSTANDARD: ::c_short = ::POLLIN | ::POLLHUP | ::POLLNVAL; +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_ALL: ::c_int = 0x00000100; +pub const AI_ADDRCONFIG: ::c_int = 0x00000400; +pub const AI_V4MAPPED: ::c_int = 0x00000800; + pub const EAI_AGAIN: ::c_int = 2; pub const EAI_BADFLAGS: ::c_int = 3; pub const EAI_FAIL: ::c_int = 4; @@ -1167,7 +1175,6 @@ 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; @@ -1253,7 +1260,6 @@ pub const BIOCGRTIMEOUT: ::c_ulong = 0x4010426e; pub const FIODTYPE: ::c_ulong = 0x4004667a; pub const FIOGETLBA: ::c_ulong = 0x40046679; -pub const FIODGNAME: ::c_ulong = 0x80106678; pub const B0: speed_t = 0; pub const B50: speed_t = 50; @@ -1436,6 +1442,11 @@ extern "C" { pub fn duplocale(base: ::locale_t) -> ::locale_t; pub fn endutxent(); pub fn fchflags(fd: ::c_int, flags: ::c_ulong) -> ::c_int; + pub fn fexecve( + fd: ::c_int, + argv: *const *const ::c_char, + envp: *const *const ::c_char, + ) -> ::c_int; pub fn futimens(fd: ::c_int, times: *const ::timespec) -> ::c_int; pub fn getdomainname(name: *mut ::c_char, len: ::c_int) -> ::c_int; pub fn getgrent_r( @@ -1466,6 +1477,8 @@ extern "C" { flags: ::c_int, ) -> ::c_int; pub fn getpriority(which: ::c_int, who: ::c_int) -> ::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 getutxent() -> *mut utmpx; pub fn getutxid(ut: *const utmpx) -> *mut utmpx; pub fn getutxline(ut: *const utmpx) -> *mut utmpx; @@ -1721,6 +1734,13 @@ extern "C" { winp: *mut ::winsize, ) -> ::pid_t; pub fn login_tty(fd: ::c_int) -> ::c_int; + pub fn fparseln( + stream: *mut ::FILE, + len: *mut ::size_t, + lineno: *mut ::size_t, + delim: *const ::c_char, + flags: ::c_int, + ) -> *mut ::c_char; } #[link(name = "execinfo")] diff --git a/vendor/libc/src/unix/bsd/netbsdlike/netbsd/mod.rs b/vendor/libc/src/unix/bsd/netbsdlike/netbsd/mod.rs index 2fa9d853d4..1e2affb7ee 100644 --- a/vendor/libc/src/unix/bsd/netbsdlike/netbsd/mod.rs +++ b/vendor/libc/src/unix/bsd/netbsdlike/netbsd/mod.rs @@ -35,6 +35,14 @@ pub type Elf64_Xword = u64; pub type iconv_t = *mut ::c_void; +e! { + pub enum fae_action { + FAE_OPEN, + FAE_DUP2, + FAE_CLOSE, + } +} + cfg_if! { if #[cfg(target_pointer_width = "64")] { type Elf_Addr = Elf64_Addr; @@ -497,6 +505,49 @@ s! { pub kve_vn_mode: u32, pub kve_path: [[::c_char; 32]; 32], } + + pub struct __c_anonymous_posix_spawn_fae_open { + pub path: *mut ::c_char, + pub oflag: ::c_int, + pub mode: ::mode_t, + } + + pub struct __c_anonymous_posix_spawn_fae_dup2 { + pub newfildes: ::c_int, + } + + pub struct posix_spawnattr_t { + pub sa_flags: ::c_short, + pub sa_pgroup: ::pid_t, + pub sa_schedparam: sched_param, + pub sa_schedpolicy: ::c_int, + pub sa_sigdefault: sigset_t, + pub sa_sigmask: sigset_t, + } + + pub struct posix_spawn_file_actions_entry_t { + pub fae_action: fae_action, + pub fae_fildes: ::c_int, + #[cfg(libc_union)] + pub fae_data: __c_anonymous_posix_spawn_fae, + } + + pub struct posix_spawn_file_actions_t { + pub size: ::c_uint, + pub len: ::c_uint, + #[cfg(libc_union)] + pub fae: *mut posix_spawn_file_actions_entry_t, + } + + pub struct ptrace_lwpinfo { + pub pl_lwpid: lwpid_t, + pub pl_event: ::c_int, + } + + pub struct ptrace_siginfo { + pub psi_siginfo: siginfo_t, + pub psi_lwpid: lwpid_t, + } } s_no_extra_traits! { @@ -609,6 +660,12 @@ s_no_extra_traits! { __unused1: *mut ::c_void, //actually a function pointer pub sigev_notify_attributes: *mut ::c_void } + + #[cfg(libc_union)] + pub union __c_anonymous_posix_spawn_fae { + pub open: __c_anonymous_posix_spawn_fae_open, + pub dup2: __c_anonymous_posix_spawn_fae_dup2, + } } cfg_if! { @@ -1036,6 +1093,41 @@ cfg_if! { self.sigev_notify_attributes.hash(state); } } + + #[cfg(libc_union)] + impl Eq for __c_anonymous_posix_spawn_fae {} + + #[cfg(libc_union)] + impl PartialEq for __c_anonymous_posix_spawn_fae { + fn eq(&self, other: &__c_anonymous_posix_spawn_fae) -> bool { + unsafe { + self.open == other.open + || self.dup2 == other.dup2 + } + } + } + + #[cfg(libc_union)] + impl ::fmt::Debug for __c_anonymous_posix_spawn_fae { + fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { + unsafe { + f.debug_struct("__c_anonymous_posix_fae") + .field("open", &self.open) + .field("dup2", &self.dup2) + .finish() + } + } + } + + #[cfg(libc_union)] + impl ::hash::Hash for __c_anonymous_posix_spawn_fae { + fn hash<H: ::hash::Hasher>(&self, state: &mut H) { + unsafe { + self.open.hash(state); + self.dup2.hash(state); + } + } + } } } @@ -1303,6 +1395,15 @@ pub const MAP_NORESERVE: ::c_int = 0x40; pub const MAP_HASSEMAPHORE: ::c_int = 0x200; pub const MAP_WIRED: ::c_int = 0x800; pub const MAP_STACK: ::c_int = 0x2000; +// map alignment aliases for MAP_ALIGNED +pub const MAP_ALIGNMENT_SHIFT: ::c_int = 24; +pub const MAP_ALIGNMENT_MASK: ::c_int = 0xff << MAP_ALIGNMENT_SHIFT; +pub const MAP_ALIGNMENT_64KB: ::c_int = 16 << MAP_ALIGNMENT_SHIFT; +pub const MAP_ALIGNMENT_16MB: ::c_int = 24 << MAP_ALIGNMENT_SHIFT; +pub const MAP_ALIGNMENT_4GB: ::c_int = 32 << MAP_ALIGNMENT_SHIFT; +pub const MAP_ALIGNMENT_1TB: ::c_int = 40 << MAP_ALIGNMENT_SHIFT; +pub const MAP_ALIGNMENT_256TB: ::c_int = 48 << MAP_ALIGNMENT_SHIFT; +pub const MAP_ALIGNMENT_64PB: ::c_int = 56 << MAP_ALIGNMENT_SHIFT; // mremap flag pub const MAP_REMAPDUP: ::c_int = 0x004; @@ -1516,6 +1617,10 @@ pub const TIME_ERROR: ::c_int = 5; pub const LITTLE_ENDIAN: ::c_int = 1234; pub const BIG_ENDIAN: ::c_int = 4321; +pub const PL_EVENT_NONE: ::c_int = 0; +pub const PL_EVENT_SIGNAL: ::c_int = 1; +pub const PL_EVENT_SUSPENDED: ::c_int = 2; + cfg_if! { if #[cfg(any(target_arch = "sparc", target_arch = "sparc64", target_arch = "x86", target_arch = "x86_64"))] { @@ -1614,6 +1719,13 @@ pub const NOTE_CHILD: u32 = 0x00000004; pub const TMP_MAX: ::c_uint = 308915776; +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_ADDRCONFIG: ::c_int = 0x00000400; +pub const AI_SRV: ::c_int = 0x00000800; + pub const NI_MAXHOST: ::socklen_t = 1025; pub const NI_MAXSERV: ::socklen_t = 32; @@ -1875,6 +1987,14 @@ pub const PT_GET_EVENT_MASK: ::c_int = 17; pub const PT_GET_PROCESS_STATE: ::c_int = 18; pub const PT_FIRSTMACH: ::c_int = 32; +pub const POSIX_SPAWN_RESETIDS: ::c_int = 0x01; +pub const POSIX_SPAWN_SETPGROUP: ::c_int = 0x02; +pub const POSIX_SPAWN_SETSCHEDPARAM: ::c_int = 0x04; +pub const POSIX_SPAWN_SETSCHEDULER: ::c_int = 0x08; +pub const POSIX_SPAWN_SETSIGDEF: ::c_int = 0x10; +pub const POSIX_SPAWN_SETSIGMASK: ::c_int = 0x20; +pub const POSIX_SPAWN_RETURNERROR: ::c_int = 0x40; + // Flags for chflags(2) pub const SF_SNAPSHOT: ::c_ulong = 0x00200000; pub const SF_LOG: ::c_ulong = 0x00400000; @@ -2307,6 +2427,83 @@ extern "C" { ts: *const ::timespec, sigmask: *const ::sigset_t, ) -> ::c_int; + + pub fn posix_spawn( + pid: *mut ::pid_t, + path: *const ::c_char, + file_actions: *const ::posix_spawn_file_actions_t, + attrp: *const ::posix_spawnattr_t, + argv: *const *mut ::c_char, + envp: *const *mut ::c_char, + ) -> ::c_int; + pub fn posix_spawnp( + pid: *mut ::pid_t, + file: *const ::c_char, + file_actions: *const ::posix_spawn_file_actions_t, + attrp: *const ::posix_spawnattr_t, + argv: *const *mut ::c_char, + envp: *const *mut ::c_char, + ) -> ::c_int; + pub fn posix_spawnattr_init(attr: *mut posix_spawnattr_t) -> ::c_int; + pub fn posix_spawnattr_destroy(attr: *mut posix_spawnattr_t) -> ::c_int; + pub fn posix_spawnattr_getsigdefault( + attr: *const posix_spawnattr_t, + default: *mut ::sigset_t, + ) -> ::c_int; + pub fn posix_spawnattr_setsigdefault( + attr: *mut posix_spawnattr_t, + default: *const ::sigset_t, + ) -> ::c_int; + pub fn posix_spawnattr_getsigmask( + attr: *const posix_spawnattr_t, + default: *mut ::sigset_t, + ) -> ::c_int; + pub fn posix_spawnattr_setsigmask( + attr: *mut posix_spawnattr_t, + default: *const ::sigset_t, + ) -> ::c_int; + pub fn posix_spawnattr_getflags( + 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_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_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_getschedparam( + attr: *const posix_spawnattr_t, + param: *mut ::sched_param, + ) -> ::c_int; + pub fn posix_spawnattr_setschedparam( + attr: *mut posix_spawnattr_t, + 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_addopen( + actions: *mut posix_spawn_file_actions_t, + fd: ::c_int, + path: *const ::c_char, + oflag: ::c_int, + mode: ::mode_t, + ) -> ::c_int; + pub fn posix_spawn_file_actions_addclose( + actions: *mut posix_spawn_file_actions_t, + fd: ::c_int, + ) -> ::c_int; + pub fn posix_spawn_file_actions_adddup2( + actions: *mut posix_spawn_file_actions_t, + fd: ::c_int, + newfd: ::c_int, + ) -> ::c_int; } #[link(name = "util")] @@ -2348,10 +2545,23 @@ extern "C" { pub fn emalloc(n: ::size_t) -> *mut ::c_void; pub fn ecalloc(n: ::size_t, c: ::size_t) -> *mut ::c_void; pub fn erealloc(p: *mut ::c_void, n: ::size_t) -> *mut ::c_void; + pub fn ereallocarr(p: *mut ::c_void, n: ::size_t, s: ::size_t); pub fn estrdup(s: *const ::c_char) -> *mut ::c_char; pub fn estrndup(s: *const ::c_char, len: ::size_t) -> *mut ::c_char; pub fn estrlcpy(dst: *mut ::c_char, src: *const ::c_char, len: ::size_t) -> ::size_t; pub fn estrlcat(dst: *mut ::c_char, src: *const ::c_char, len: ::size_t) -> ::size_t; + pub fn estrtoi( + nptr: *const ::c_char, + base: ::c_int, + lo: ::intmax_t, + hi: ::intmax_t, + ) -> ::intmax_t; + pub fn estrtou( + nptr: *const ::c_char, + base: ::c_int, + lo: ::uintmax_t, + hi: ::uintmax_t, + ) -> ::uintmax_t; pub fn easprintf(string: *mut *mut ::c_char, fmt: *const ::c_char, ...) -> ::c_int; pub fn evasprintf(string: *mut *mut ::c_char, fmt: *const ::c_char, ...) -> ::c_int; pub fn esetfunc( @@ -2419,6 +2629,50 @@ extern "C" { tpe: ::c_int, ); + pub fn getxattr( + path: *const ::c_char, + name: *const ::c_char, + value: *mut ::c_void, + size: ::size_t, + ) -> ::ssize_t; + pub fn lgetxattr( + path: *const ::c_char, + name: *const ::c_char, + value: *mut ::c_void, + size: ::size_t, + ) -> ::ssize_t; + pub fn fgetxattr( + filedes: ::c_int, + name: *const ::c_char, + value: *mut ::c_void, + size: ::size_t, + ) -> ::ssize_t; + pub fn setxattr( + path: *const ::c_char, + name: *const ::c_char, + value: *const ::c_void, + size: ::size_t, + ) -> ::c_int; + pub fn lsetxattr( + path: *const ::c_char, + name: *const ::c_char, + value: *const ::c_void, + size: ::size_t, + ) -> ::c_int; + pub fn fsetxattr( + filedes: ::c_int, + name: *const ::c_char, + value: *const ::c_void, + 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 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(fd: ::c_int, path: *const ::c_char, name: *const ::c_char) -> ::c_int; + pub fn string_to_flags( string_p: *mut *mut ::c_char, setp: *mut ::c_ulong, diff --git a/vendor/libc/src/unix/bsd/netbsdlike/openbsd/mod.rs b/vendor/libc/src/unix/bsd/netbsdlike/openbsd/mod.rs index 535d7b1665..c88dad31e0 100644 --- a/vendor/libc/src/unix/bsd/netbsdlike/openbsd/mod.rs +++ b/vendor/libc/src/unix/bsd/netbsdlike/openbsd/mod.rs @@ -1186,6 +1186,14 @@ pub const NOTE_CHILD: u32 = 0x00000004; pub const TMP_MAX: ::c_uint = 0x7fffffff; +pub const AI_PASSIVE: ::c_int = 1; +pub const AI_CANONNAME: ::c_int = 2; +pub const AI_NUMERICHOST: ::c_int = 4; +pub const AI_EXT: ::c_int = 8; +pub const AI_NUMERICSERV: ::c_int = 16; +pub const AI_FQDN: ::c_int = 32; +pub const AI_ADDRCONFIG: ::c_int = 64; + pub const NI_NUMERICHOST: ::c_int = 1; pub const NI_NUMERICSERV: ::c_int = 2; pub const NI_NOFQDN: ::c_int = 4; @@ -1527,6 +1535,8 @@ extern "C" { servlen: ::size_t, flags: ::c_int, ) -> ::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 kevent( kq: ::c_int, changelist: *const ::kevent, @@ -1536,6 +1546,7 @@ extern "C" { timeout: *const ::timespec, ) -> ::c_int; pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; + pub fn getthrid() -> ::pid_t; pub fn pthread_attr_getguardsize( attr: *const ::pthread_attr_t, guardsize: *mut ::size_t, diff --git a/vendor/libc/src/unix/haiku/mod.rs b/vendor/libc/src/unix/haiku/mod.rs index ee2af390a7..76a532a011 100644 --- a/vendor/libc/src/unix/haiku/mod.rs +++ b/vendor/libc/src/unix/haiku/mod.rs @@ -102,6 +102,16 @@ s! { pub ai_next: *mut addrinfo, } + pub struct ifaddrs { + pub ifa_next: *mut ifaddrs, + pub ifa_name: *mut ::c_char, + pub ifa_flags: ::c_uint, + pub ifa_addr: *mut ::sockaddr, + pub ifa_netmask: *mut ::sockaddr, + pub ifa_dstaddr: *mut ::sockaddr, + pub ida_data: *mut ::c_void, + } + pub struct fd_set { // size for 1024 bits, and a fd_mask with size u32 fds_bits: [fd_mask; 32], @@ -364,10 +374,63 @@ s_no_extra_traits! { __unused1: *mut ::c_void, // actually a function pointer pub sigev_notify_attributes: *mut ::pthread_attr_t, } + + pub struct utmpx { + pub ut_type: ::c_short, + pub ut_tv: ::timeval, + pub ut_id: [::c_char; 8], + pub ut_pid: ::pid_t, + pub ut_user: [::c_char; 32], + pub ut_line: [::c_char; 16], + pub ut_host: [::c_char; 128], + __ut_reserved: [::c_char; 64], + } } cfg_if! { if #[cfg(feature = "extra_traits")] { + impl PartialEq for utmpx { + fn eq(&self, other: &utmpx) -> bool { + self.ut_type == other.ut_type + && self.ut_tv == other.ut_tv + && self.ut_id == other.ut_id + && self.ut_pid == other.ut_pid + && self.ut_user == other.ut_user + && self.ut_line == other.ut_line + && self.ut_host.iter().zip(other.ut_host.iter()).all(|(a,b)| a == b) + && self.__ut_reserved == other.__ut_reserved + } + } + + impl Eq for utmpx {} + + impl ::fmt::Debug for utmpx { + fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { + f.debug_struct("utmpx") + .field("ut_type", &self.ut_type) + .field("ut_tv", &self.ut_tv) + .field("ut_id", &self.ut_id) + .field("ut_pid", &self.ut_pid) + .field("ut_user", &self.ut_user) + .field("ut_line", &self.ut_line) + .field("ut_host", &self.ut_host) + .field("__ut_reserved", &self.__ut_reserved) + .finish() + } + } + + impl ::hash::Hash for utmpx { + fn hash<H: ::hash::Hasher>(&self, state: &mut H) { + self.ut_type.hash(state); + self.ut_tv.hash(state); + self.ut_id.hash(state); + self.ut_pid.hash(state); + self.ut_user.hash(state); + self.ut_line.hash(state); + self.ut_host.hash(state); + self.__ut_reserved.hash(state); + } + } impl PartialEq for sockaddr_un { fn eq(&self, other: &sockaddr_un) -> bool { self.sun_len == other.sun_len @@ -1265,6 +1328,16 @@ pub const PRIO_PROCESS: ::c_int = 0; pub const PRIO_PGRP: ::c_int = 1; pub const PRIO_USER: ::c_int = 2; +// utmpx entry types +pub const EMPTY: ::c_short = 0; +pub const BOOT_TIME: ::c_short = 1; +pub const OLD_TIME: ::c_short = 2; +pub const NEW_TIME: ::c_short = 3; +pub const USER_PROCESS: ::c_short = 4; +pub const INIT_PROCESS: ::c_short = 5; +pub const LOGIN_PROCESS: ::c_short = 6; +pub const DEAD_PROCESS: ::c_short = 7; + pub const LOG_PID: ::c_int = 1 << 12; pub const LOG_CONS: ::c_int = 2 << 12; pub const LOG_ODELAY: ::c_int = 4 << 12; @@ -1402,6 +1475,8 @@ extern "C" { pub fn labs(i: ::c_long) -> ::c_long; pub fn rand() -> ::c_int; pub fn srand(seed: ::c_uint); + pub fn getifaddrs(ifap: *mut *mut ::ifaddrs) -> ::c_int; + pub fn freeifaddrs(ifa: *mut ::ifaddrs); } #[link(name = "bsd")] @@ -1510,6 +1585,12 @@ extern "C" { buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; + pub fn getgrouplist( + user: *const ::c_char, + basegroup: ::gid_t, + grouplist: *mut ::gid_t, + groupcount: *mut ::c_int, + ) -> ::c_int; pub fn sigaltstack(ss: *const stack_t, oss: *mut stack_t) -> ::c_int; pub fn sem_close(sem: *mut sem_t) -> ::c_int; pub fn getdtablesize() -> ::c_int; @@ -1563,6 +1644,12 @@ extern "C" { ) -> ::pid_t; pub fn sethostname(name: *const ::c_char, len: ::size_t) -> ::c_int; pub fn uname(buf: *mut ::utsname) -> ::c_int; + pub fn getutxent() -> *mut utmpx; + pub fn getutxid(ut: *const utmpx) -> *mut utmpx; + pub fn getutxline(ut: *const utmpx) -> *mut utmpx; + pub fn pututxline(ut: *const utmpx) -> *mut utmpx; + pub fn setutxent(); + pub fn endutxent(); } cfg_if! { diff --git a/vendor/libc/src/unix/linux_like/android/mod.rs b/vendor/libc/src/unix/linux_like/android/mod.rs index 5e6fae7dae..04cc89ea27 100644 --- a/vendor/libc/src/unix/linux_like/android/mod.rs +++ b/vendor/libc/src/unix/linux_like/android/mod.rs @@ -792,9 +792,6 @@ pub const EPROTO: ::c_int = 71; pub const EDOTDOT: ::c_int = 73; pub const EPOLL_CLOEXEC: ::c_int = 0x80000; -pub const EPOLLONESHOT: ::c_int = 0x40000000; -pub const EPOLLRDHUP: ::c_int = 0x00002000; -pub const EPOLLWAKEUP: ::c_int = 0x20000000; // sys/eventfd.h pub const EFD_SEMAPHORE: ::c_int = 0x1; @@ -1205,6 +1202,9 @@ pub const SO_SNDLOWAT: ::c_int = 19; pub const SO_RCVTIMEO: ::c_int = 20; pub const SO_SNDTIMEO: ::c_int = 21; 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_TIMESTAMP: ::c_int = 29; pub const SO_ACCEPTCONN: ::c_int = 30; pub const SO_PEERSEC: ::c_int = 31; @@ -1341,6 +1341,10 @@ pub const TCGETS: ::c_int = 0x5401; pub const TCSETS: ::c_int = 0x5402; pub const TCSETSW: ::c_int = 0x5403; pub const TCSETSF: ::c_int = 0x5404; +pub const TCGETS2: ::c_int = 0x802c542a; +pub const TCSETS2: ::c_int = 0x402c542b; +pub const TCSETSW2: ::c_int = 0x402c542c; +pub const TCSETSF2: ::c_int = 0x402c542d; pub const TCGETA: ::c_int = 0x5405; pub const TCSETA: ::c_int = 0x5406; pub const TCSETAW: ::c_int = 0x5407; @@ -1787,6 +1791,11 @@ pub const NETLINK_BROADCAST_ERROR: ::c_int = 4; pub const NETLINK_NO_ENOBUFS: ::c_int = 5; pub const NETLINK_RX_RING: ::c_int = 6; pub const NETLINK_TX_RING: ::c_int = 7; +pub const NETLINK_LISTEN_ALL_NSID: ::c_int = 8; +pub const NETLINK_LIST_MEMBERSHIPS: ::c_int = 9; +pub const NETLINK_CAP_ACK: ::c_int = 10; +pub const NETLINK_EXT_ACK: ::c_int = 11; +pub const NETLINK_GET_STRICT_CHK: ::c_int = 12; pub const GRND_NONBLOCK: ::c_uint = 0x0001; pub const GRND_RANDOM: ::c_uint = 0x0002; @@ -1867,6 +1876,25 @@ pub const MFD_CLOEXEC: ::c_uint = 0x0001; pub const MFD_ALLOW_SEALING: ::c_uint = 0x0002; pub const MFD_HUGETLB: ::c_uint = 0x0004; +// these are used in the p_type field of Elf32_Phdr and Elf64_Phdr, which has +// the type Elf32Word and Elf64Word respectively. Luckily, both of those are u32 +// so we can use that type here to avoid having to cast. +pub const PT_NULL: u32 = 0; +pub const PT_LOAD: u32 = 1; +pub const PT_DYNAMIC: u32 = 2; +pub const PT_INTERP: u32 = 3; +pub const PT_NOTE: u32 = 4; +pub const PT_SHLIB: u32 = 5; +pub const PT_PHDR: u32 = 6; +pub const PT_TLS: u32 = 7; +pub const PT_LOOS: u32 = 0x60000000; +pub const PT_GNU_EH_FRAME: u32 = 0x6474e550; +pub const PT_GNU_STACK: u32 = 0x6474e551; +pub const PT_GNU_RELRO: u32 = 0x6474e552; +pub const PT_HIOS: u32 = 0x6fffffff; +pub const PT_LOPROC: u32 = 0x70000000; +pub const PT_HIPROC: u32 = 0x7fffffff; + // linux/netfilter.h pub const NF_DROP: ::c_int = 0; pub const NF_ACCEPT: ::c_int = 1; @@ -2426,6 +2454,8 @@ pub const SCHED_DEADLINE: ::c_int = 6; pub const SCHED_RESET_ON_FORK: ::c_int = 0x40000000; +pub const CLONE_PIDFD: ::c_int = 0x1000; + // bits/seek_constants.h pub const SEEK_DATA: ::c_int = 3; pub const SEEK_HOLE: ::c_int = 4; @@ -2459,6 +2489,12 @@ f! { } } + pub fn CPU_ALLOC_SIZE(count: ::c_int) -> ::size_t { + let _dummy: cpu_set_t = ::mem::zeroed(); + let size_in_bits = 8 * ::mem::size_of_val(&_dummy.__bits[0]); + ((count as ::size_t + size_in_bits - 1) / 8) as ::size_t + } + pub fn CPU_ZERO(cpuset: &mut cpu_set_t) -> () { for slot in cpuset.__bits.iter_mut() { *slot = 0; @@ -2466,28 +2502,44 @@ f! { } pub fn CPU_SET(cpu: usize, cpuset: &mut cpu_set_t) -> () { - let size_in___bits = 8 * ::mem::size_of_val(&cpuset.__bits[0]); - let (idx, offset) = (cpu / size_in___bits, cpu % size_in___bits); + let size_in_bits + = 8 * ::mem::size_of_val(&cpuset.__bits[0]); // 32, 64 etc + let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); cpuset.__bits[idx] |= 1 << offset; () } pub fn CPU_CLR(cpu: usize, cpuset: &mut cpu_set_t) -> () { - let size_in___bits = 8 * ::mem::size_of_val(&cpuset.__bits[0]); - let (idx, offset) = (cpu / size_in___bits, cpu % size_in___bits); + let size_in_bits + = 8 * ::mem::size_of_val(&cpuset.__bits[0]); // 32, 64 etc + let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); cpuset.__bits[idx] &= !(1 << offset); () } pub fn CPU_ISSET(cpu: usize, cpuset: &cpu_set_t) -> bool { - let size_in___bits = 8 * ::mem::size_of_val(&cpuset.__bits[0]); - let (idx, offset) = (cpu / size_in___bits, cpu % size_in___bits); + let size_in_bits = 8 * ::mem::size_of_val(&cpuset.__bits[0]); + let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); 0 != (cpuset.__bits[idx] & (1 << offset)) } + pub fn CPU_COUNT_S(size: usize, cpuset: &cpu_set_t) -> ::c_int { + let mut s: u32 = 0; + let size_of_mask = ::mem::size_of_val(&cpuset.__bits[0]); + for i in cpuset.__bits[..(size / size_of_mask)].iter() { + s += i.count_ones(); + }; + s as ::c_int + } + + pub fn CPU_COUNT(cpuset: &cpu_set_t) -> ::c_int { + CPU_COUNT_S(::mem::size_of::<cpu_set_t>(), cpuset) + } + pub fn CPU_EQUAL(set1: &cpu_set_t, set2: &cpu_set_t) -> bool { set1.__bits == set2.__bits } + pub fn major(dev: ::dev_t) -> ::c_int { ((dev >> 8) & 0xfff) as ::c_int } diff --git a/vendor/libc/src/unix/linux_like/emscripten/mod.rs b/vendor/libc/src/unix/linux_like/emscripten/mod.rs index b83415a393..5494aad378 100644 --- a/vendor/libc/src/unix/linux_like/emscripten/mod.rs +++ b/vendor/libc/src/unix/linux_like/emscripten/mod.rs @@ -965,10 +965,6 @@ pub const SHM_UNLOCK: ::c_int = 12; pub const SHM_HUGETLB: ::c_int = 0o4000; pub const SHM_NORESERVE: ::c_int = 0o10000; -pub const EPOLLRDHUP: ::c_int = 0x2000; -pub const EPOLLEXCLUSIVE: ::c_int = 0x10000000; -pub const EPOLLONESHOT: ::c_int = 0x40000000; - pub const QFMT_VFS_OLD: ::c_int = 1; pub const QFMT_VFS_V0: ::c_int = 2; @@ -1372,8 +1368,6 @@ pub const PTRACE_INTERRUPT: ::c_int = 0x4207; pub const PTRACE_LISTEN: ::c_int = 0x4208; pub const PTRACE_PEEKSIGINFO: ::c_int = 0x4209; -pub const EPOLLWAKEUP: ::c_int = 0x20000000; - pub const PTRACE_GETFPREGS: ::c_uint = 14; pub const PTRACE_SETFPREGS: ::c_uint = 15; pub const PTRACE_GETFPXREGS: ::c_uint = 18; 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 index e3401d4b72..e5c636d64a 100644 --- a/vendor/libc/src/unix/linux_like/linux/arch/generic/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/arch/generic/mod.rs @@ -1,3 +1,16 @@ +s! { + pub struct termios2 { + pub c_iflag: ::tcflag_t, + pub c_oflag: ::tcflag_t, + pub c_cflag: ::tcflag_t, + pub c_lflag: ::tcflag_t, + pub c_line: ::cc_t, + pub c_cc: [::cc_t; 19], + pub c_ispeed: ::speed_t, + pub c_ospeed: ::speed_t, + } +} + // include/uapi/asm-generic/socket.h // arch/alpha/include/uapi/asm/socket.h // tools/include/uapi/asm-generic/socket.h @@ -98,3 +111,8 @@ cfg_if! { // pub const SCM_TIMESTAMP: ::c_int = SO_TIMESTAMP; pub const SCM_TIMESTAMPNS: ::c_int = SO_TIMESTAMPNS; pub const SCM_TIMESTAMPING: ::c_int = SO_TIMESTAMPING; + +pub const TCGETS2: ::c_ulong = 0x802c542a; +pub const TCSETS2: ::c_ulong = 0x402c542b; +pub const TCSETSW2: ::c_ulong = 0x402c542c; +pub const TCSETSF2: ::c_ulong = 0x402c542d; 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 index cdbdca2bbf..34d7022672 100644 --- a/vendor/libc/src/unix/linux_like/linux/arch/mips/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/arch/mips/mod.rs @@ -1,3 +1,16 @@ +s! { + pub struct termios2 { + pub c_iflag: ::tcflag_t, + pub c_oflag: ::tcflag_t, + pub c_cflag: ::tcflag_t, + pub c_lflag: ::tcflag_t, + pub c_line: ::cc_t, + pub c_cc: [::cc_t; 23], + pub c_ispeed: ::speed_t, + pub c_ospeed: ::speed_t, + } +} + // arch/mips/include/uapi/asm/socket.h pub const SOL_SOCKET: ::c_int = 0xffff; @@ -94,3 +107,8 @@ pub const SO_TIMESTAMPING: ::c_int = 37; // pub const SCM_TIMESTAMP: ::c_int = SO_TIMESTAMP; pub const SCM_TIMESTAMPNS: ::c_int = SO_TIMESTAMPNS; pub const SCM_TIMESTAMPING: ::c_int = SO_TIMESTAMPING; + +pub const TCGETS2: ::c_ulong = 0x4030542a; +pub const TCSETS2: ::c_ulong = 0x8030542b; +pub const TCSETSW2: ::c_ulong = 0x8030542c; +pub const TCSETSF2: ::c_ulong = 0x8030542d; 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 index d4f9bb0ebc..2c8fdd067f 100644 --- a/vendor/libc/src/unix/linux_like/linux/arch/sparc/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/arch/sparc/mod.rs @@ -1,3 +1,16 @@ +s! { + pub struct termios2 { + pub c_iflag: ::tcflag_t, + pub c_oflag: ::tcflag_t, + pub c_cflag: ::tcflag_t, + pub c_lflag: ::tcflag_t, + pub c_line: ::cc_t, + pub c_cc: [::cc_t; 19], + pub c_ispeed: ::speed_t, + pub c_ospeed: ::speed_t, + } +} + // arch/sparc/include/uapi/asm/socket.h pub const SOL_SOCKET: ::c_int = 0xffff; @@ -86,3 +99,8 @@ pub const SO_TIMESTAMPING: ::c_int = 0x0023; // pub const SCM_TIMESTAMP: ::c_int = SO_TIMESTAMP; pub const SCM_TIMESTAMPNS: ::c_int = SO_TIMESTAMPNS; pub const SCM_TIMESTAMPING: ::c_int = SO_TIMESTAMPING; + +pub const TCGETS2: ::c_ulong = 0x402c540c; +pub const TCSETS2: ::c_ulong = 0x802c540d; +pub const TCSETSW2: ::c_ulong = 0x802c540e; +pub const TCSETSF2: ::c_ulong = 0x802c540f; 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 0e7fb70f6e..f18df46e4a 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 @@ -141,17 +141,6 @@ s! { __glibc_reserved5: ::c_ulong, } - pub struct termios2 { - pub c_iflag: ::tcflag_t, - pub c_oflag: ::tcflag_t, - pub c_cflag: ::tcflag_t, - pub c_lflag: ::tcflag_t, - pub c_line: ::cc_t, - pub c_cc: [::cc_t; 19], - pub c_ispeed: ::speed_t, - pub c_ospeed: ::speed_t, - } - pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, 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 4ded201fb4..0a72eba4ab 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 @@ -153,17 +153,6 @@ s! { pub l_pid: ::pid_t, pad: [::c_long; 4], } - - pub struct termios2 { - pub c_iflag: ::tcflag_t, - pub c_oflag: ::tcflag_t, - pub c_cflag: ::tcflag_t, - pub c_lflag: ::tcflag_t, - pub c_line: ::cc_t, - pub c_cc: [::cc_t; 23], - pub c_ispeed: ::speed_t, - pub c_ospeed: ::speed_t, - } } pub const O_LARGEFILE: ::c_int = 0x2000; 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 4364814094..b5a74314be 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 @@ -191,17 +191,6 @@ s! { __glibc_reserved1: ::c_ulong, __glibc_reserved2: ::c_ulong, } - - pub struct termios2 { - pub c_iflag: ::tcflag_t, - pub c_oflag: ::tcflag_t, - pub c_cflag: ::tcflag_t, - pub c_lflag: ::tcflag_t, - pub c_line: ::cc_t, - pub c_cc: [::cc_t; 19], - pub c_ispeed: ::speed_t, - pub c_ospeed: ::speed_t, - } } pub const RLIM_INFINITY: ::rlim_t = !0; 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 75edd27885..a4b75f470c 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 @@ -215,17 +215,6 @@ s! { __glibc_reserved5: ::c_ulong, } - pub struct termios2 { - pub c_iflag: ::tcflag_t, - pub c_oflag: ::tcflag_t, - pub c_cflag: ::tcflag_t, - pub c_lflag: ::tcflag_t, - pub c_line: ::cc_t, - pub c_cc: [::cc_t; 19], - pub c_ispeed: ::speed_t, - pub c_ospeed: ::speed_t, - } - pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, 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 35fe306122..5a1ec7a1e6 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 @@ -168,17 +168,6 @@ s! { __unused5: ::c_ulong } - pub struct termios2 { - pub c_iflag: ::tcflag_t, - pub c_oflag: ::tcflag_t, - pub c_cflag: ::tcflag_t, - pub c_lflag: ::tcflag_t, - pub c_line: ::cc_t, - pub c_cc: [::cc_t; 19], - pub c_ispeed: ::speed_t, - pub c_ospeed: ::speed_t, - } - pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, 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 87939566f7..31eaf5a87b 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 @@ -183,17 +183,6 @@ s! { __unused4: ::c_ulong, __unused5: ::c_ulong } - - pub struct termios2 { - pub c_iflag: ::tcflag_t, - pub c_oflag: ::tcflag_t, - pub c_cflag: ::tcflag_t, - pub c_lflag: ::tcflag_t, - pub c_line: ::cc_t, - pub c_cc: [::cc_t; 23], - pub c_ispeed: ::speed_t, - pub c_ospeed: ::speed_t, - } } pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; 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 833997a6d0..b6bf1199d9 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 @@ -153,17 +153,6 @@ s! { __f_spare: [::c_int; 6], } - pub struct termios2 { - pub c_iflag: ::tcflag_t, - pub c_oflag: ::tcflag_t, - pub c_cflag: ::tcflag_t, - pub c_lflag: ::tcflag_t, - pub c_line: ::cc_t, - pub c_cc: [::cc_t; 19], - pub c_ispeed: ::speed_t, - pub c_ospeed: ::speed_t, - } - pub struct __psw_t { pub mask: u64, pub addr: u64, 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 5ed83ab8ed..9508190b21 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 @@ -193,17 +193,6 @@ s! { __reserved1: ::c_ulong, __reserved2: ::c_ulong } - - pub struct termios2 { - pub c_iflag: ::tcflag_t, - pub c_oflag: ::tcflag_t, - pub c_cflag: ::tcflag_t, - pub c_lflag: ::tcflag_t, - pub c_line: ::cc_t, - pub c_cc: [::cc_t; 19], - pub c_ispeed: ::speed_t, - pub c_ospeed: ::speed_t, - } } pub const POSIX_FADV_DONTNEED: ::c_int = 4; 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 99937dfabd..c7445f8d77 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 @@ -259,17 +259,6 @@ s! { __unused5: u64 } - pub struct termios2 { - pub c_iflag: ::tcflag_t, - pub c_oflag: ::tcflag_t, - pub c_cflag: ::tcflag_t, - pub c_lflag: ::tcflag_t, - pub c_line: ::cc_t, - pub c_cc: [::cc_t; 19], - pub c_ispeed: ::speed_t, - pub c_ospeed: ::speed_t, - } - pub struct ip_mreqn { pub imr_multiaddr: ::in_addr, pub imr_address: ::in_addr, 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 bb2a777d77..598bf465b4 100644 --- a/vendor/libc/src/unix/linux_like/linux/gnu/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/gnu/mod.rs @@ -956,6 +956,25 @@ pub const TIOCM_RTS: ::c_int = 0x004; pub const TIOCM_CD: ::c_int = TIOCM_CAR; pub const TIOCM_RI: ::c_int = TIOCM_RNG; +// elf.h +pub const NT_PRSTATUS: ::c_int = 1; +pub const NT_PRFPREG: ::c_int = 2; +pub const NT_FPREGSET: ::c_int = 2; +pub const NT_PRPSINFO: ::c_int = 3; +pub const NT_PRXREG: ::c_int = 4; +pub const NT_TASKSTRUCT: ::c_int = 4; +pub const NT_PLATFORM: ::c_int = 5; +pub const NT_AUXV: ::c_int = 6; +pub const NT_GWINDOWS: ::c_int = 7; +pub const NT_ASRS: ::c_int = 8; +pub const NT_PSTATUS: ::c_int = 10; +pub const NT_PSINFO: ::c_int = 13; +pub const NT_PRCRED: ::c_int = 14; +pub const NT_UTSNAME: ::c_int = 15; +pub const NT_LWPSTATUS: ::c_int = 16; +pub const NT_LWPSINFO: ::c_int = 17; +pub const NT_PRFPXREG: ::c_int = 20; + // linux/keyctl.h pub const KEYCTL_DH_COMPUTE: u32 = 23; pub const KEYCTL_PKEY_QUERY: u32 = 24; diff --git a/vendor/libc/src/unix/linux_like/linux/mod.rs b/vendor/libc/src/unix/linux_like/linux/mod.rs index e10a310a2e..2bb032dd37 100644 --- a/vendor/libc/src/unix/linux_like/linux/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/mod.rs @@ -670,6 +670,19 @@ s_no_extra_traits! { } } +cfg_if! { + if #[cfg(not(all(target_env = "musl", target_arch = "mips")))] { + s_no_extra_traits! { + // linux/net_tstamp.h + #[allow(missing_debug_implementations)] + pub struct sock_txtime { + pub clockid: ::clockid_t, + pub flags: ::__u32, + } + } + } +} + cfg_if! { if #[cfg(libc_union)] { s_no_extra_traits! { @@ -1317,6 +1330,7 @@ pub const POSIX_MADV_NORMAL: ::c_int = 0; pub const POSIX_MADV_RANDOM: ::c_int = 1; pub const POSIX_MADV_SEQUENTIAL: ::c_int = 2; pub const POSIX_MADV_WILLNEED: ::c_int = 3; +pub const POSIX_SPAWN_USEVFORK: ::c_int = 64; pub const S_IEXEC: mode_t = 64; pub const S_IWRITE: mode_t = 128; @@ -1478,6 +1492,8 @@ pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0; pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 1; pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 2; pub const PTHREAD_MUTEX_DEFAULT: ::c_int = PTHREAD_MUTEX_NORMAL; +pub const PTHREAD_MUTEX_STALLED: ::c_int = 0; +pub const PTHREAD_MUTEX_ROBUST: ::c_int = 1; pub const PTHREAD_PROCESS_PRIVATE: ::c_int = 0; pub const PTHREAD_PROCESS_SHARED: ::c_int = 1; pub const __SIZEOF_PTHREAD_COND_T: usize = 48; @@ -1494,6 +1510,8 @@ pub const SCHED_IDLE: ::c_int = 5; pub const SCHED_RESET_ON_FORK: ::c_int = 0x40000000; +pub const CLONE_PIDFD: ::c_int = 0x1000; + // netinet/in.h // NOTE: These are in addition to the constants defined in src/unix/mod.rs @@ -1538,11 +1556,6 @@ pub const SHM_HUGETLB: ::c_int = 0o4000; #[cfg(not(all(target_env = "uclibc", target_arch = "mips")))] pub const SHM_NORESERVE: ::c_int = 0o10000; -pub const EPOLLRDHUP: ::c_int = 0x2000; -pub const EPOLLEXCLUSIVE: ::c_int = 0x10000000; -pub const EPOLLWAKEUP: ::c_int = 0x20000000; -pub const EPOLLONESHOT: ::c_int = 0x40000000; - pub const QFMT_VFS_OLD: ::c_int = 1; pub const QFMT_VFS_V0: ::c_int = 2; pub const QFMT_VFS_V1: ::c_int = 4; @@ -1808,6 +1821,10 @@ pub const MFD_CLOEXEC: ::c_uint = 0x0001; pub const MFD_ALLOW_SEALING: ::c_uint = 0x0002; pub const MFD_HUGETLB: ::c_uint = 0x0004; +// linux/close_range.h +pub const CLOSE_RANGE_UNSHARE: ::c_uint = 1 << 1; +pub const CLOSE_RANGE_CLOEXEC: ::c_uint = 1 << 2; + // these are used in the p_type field of Elf32_Phdr and Elf64_Phdr, which has // the type Elf32Word and Elf64Word respectively. Luckily, both of those are u32 // so we can use that type here to avoid having to cast. @@ -2380,6 +2397,8 @@ pub const NETLINK_TX_RING: ::c_int = 7; pub const NETLINK_LISTEN_ALL_NSID: ::c_int = 8; pub const NETLINK_LIST_MEMBERSHIPS: ::c_int = 9; pub const NETLINK_CAP_ACK: ::c_int = 10; +pub const NETLINK_EXT_ACK: ::c_int = 11; +pub const NETLINK_GET_STRICT_CHK: ::c_int = 12; pub const NLA_F_NESTED: ::c_int = 1 << 15; pub const NLA_F_NET_BYTEORDER: ::c_int = 1 << 14; @@ -2528,6 +2547,12 @@ pub const SOF_TIMESTAMPING_RX_SOFTWARE: ::c_uint = 1 << 3; pub const SOF_TIMESTAMPING_SOFTWARE: ::c_uint = 1 << 4; pub const SOF_TIMESTAMPING_SYS_HARDWARE: ::c_uint = 1 << 5; pub const SOF_TIMESTAMPING_RAW_HARDWARE: ::c_uint = 1 << 6; +cfg_if! { + if #[cfg(not(all(target_env = "musl", target_arch = "mips")))] { + pub const SOF_TXTIME_DEADLINE_MODE: u32 = 1 << 0; + pub const SOF_TXTIME_REPORT_ERRORS: u32 = 1 << 1; + } +} // linux/if_alg.h pub const ALG_SET_KEY: ::c_int = 1; @@ -3055,18 +3080,14 @@ pub const SOL_CAN_BASE: ::c_int = 100; pub const CAN_INV_FILTER: canid_t = 0x20000000; pub const CAN_RAW_FILTER_MAX: ::c_int = 512; -#[deprecated( - since = "0.2.102", - note = "Errnoeously uses c_int; should use c_short." -)] -#[cfg(not(any(target_arch = "sparc", target_arch = "sparc64")))] -pub const POLLRDHUP: ::c_int = 0x2000; -#[deprecated( - since = "0.2.102", - note = "Errnoeously uses c_int; should use c_short." -)] -#[cfg(any(target_arch = "sparc", target_arch = "sparc64"))] -pub const POLLRDHUP: ::c_int = 0x800; +// linux/can/raw.h +pub const SOL_CAN_RAW: ::c_int = SOL_CAN_BASE + CAN_RAW; +pub const CAN_RAW_FILTER: ::c_int = 1; +pub const CAN_RAW_ERR_FILTER: ::c_int = 2; +pub const CAN_RAW_LOOPBACK: ::c_int = 3; +pub const CAN_RAW_RECV_OWN_MSGS: ::c_int = 4; +pub const CAN_RAW_FD_FRAMES: ::c_int = 5; +pub const CAN_RAW_JOIN_FILTERS: ::c_int = 6; f! { pub fn NLA_ALIGN(len: ::c_int) -> ::c_int { @@ -3596,6 +3617,7 @@ extern "C" { timeout: *const ::timespec, sigmask: *const sigset_t, ) -> ::c_int; + pub fn pthread_mutex_consistent(mutex: *mut pthread_mutex_t) -> ::c_int; pub fn pthread_mutex_timedlock( lock: *mut pthread_mutex_t, abstime: *const ::timespec, @@ -3711,6 +3733,14 @@ extern "C" { attr: *const pthread_mutexattr_t, pshared: *mut ::c_int, ) -> ::c_int; + pub fn pthread_mutexattr_getrobust( + attr: *const pthread_mutexattr_t, + robustness: *mut ::c_int, + ) -> ::c_int; + pub fn pthread_mutexattr_setrobust( + attr: *mut pthread_mutexattr_t, + robustness: ::c_int, + ) -> ::c_int; pub fn popen(command: *const c_char, mode: *const c_char) -> *mut ::FILE; pub fn faccessat( dirfd: ::c_int, @@ -3885,6 +3915,8 @@ extern "C" { needlelen: ::size_t, ) -> *mut ::c_void; pub fn sched_getcpu() -> ::c_int; + + pub fn memfd_create(name: *const ::c_char, flags: ::c_uint) -> ::c_int; } 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 a94ebb6afc..d8f51c7418 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 @@ -129,17 +129,6 @@ s! { pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } - - pub struct termios2 { - pub c_iflag: ::tcflag_t, - pub c_oflag: ::tcflag_t, - pub c_cflag: ::tcflag_t, - pub c_lflag: ::tcflag_t, - pub c_line: ::cc_t, - pub c_cc: [::cc_t; 19], - pub c_ispeed: ::speed_t, - pub c_ospeed: ::speed_t, - } } pub const AF_FILE: ::c_int = 1; 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 4f7974c5e9..7f80df4377 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 @@ -292,8 +292,13 @@ s_no_extra_traits! { } // constants +pub const ENAMETOOLONG: ::c_int = 36; // File name too long +pub const ENOTEMPTY: ::c_int = 39; // Directory not empty +pub const ELOOP: ::c_int = 40; // Too many symbolic links encountered pub const EADDRINUSE: ::c_int = 98; // Address already in use pub const EADDRNOTAVAIL: ::c_int = 99; // Cannot assign requested address +pub const ENETDOWN: ::c_int = 100; // Network is down +pub const ENETUNREACH: ::c_int = 101; // Network is unreachable pub const ECONNABORTED: ::c_int = 103; // Software caused connection abort pub const ECONNREFUSED: ::c_int = 111; // Connection refused pub const ECONNRESET: ::c_int = 104; // Connection reset by peer @@ -301,6 +306,9 @@ pub const EDEADLK: ::c_int = 35; // Resource deadlock would occur pub const ENOSYS: ::c_int = 38; // Function not implemented pub const ENOTCONN: ::c_int = 107; // Transport endpoint is not connected pub const ETIMEDOUT: ::c_int = 110; // connection timed out +pub const ESTALE: ::c_int = 116; // Stale file handle +pub const EHOSTUNREACH: ::c_int = 113; // No route to host +pub const EDQUOT: ::c_int = 122; // Quota exceeded pub const EOPNOTSUPP: ::c_int = 0x5f; pub const ENODATA: ::c_int = 0x3d; pub const O_APPEND: ::c_int = 02000; diff --git a/vendor/libc/src/unix/linux_like/mod.rs b/vendor/libc/src/unix/linux_like/mod.rs index 5940424721..96f179c4f2 100644 --- a/vendor/libc/src/unix/linux_like/mod.rs +++ b/vendor/libc/src/unix/linux_like/mod.rs @@ -1028,13 +1028,17 @@ pub const FD_SETSIZE: usize = 1024; pub const EPOLLIN: ::c_int = 0x1; pub const EPOLLPRI: ::c_int = 0x2; pub const EPOLLOUT: ::c_int = 0x4; +pub const EPOLLERR: ::c_int = 0x8; +pub const EPOLLHUP: ::c_int = 0x10; pub const EPOLLRDNORM: ::c_int = 0x40; pub const EPOLLRDBAND: ::c_int = 0x80; pub const EPOLLWRNORM: ::c_int = 0x100; pub const EPOLLWRBAND: ::c_int = 0x200; pub const EPOLLMSG: ::c_int = 0x400; -pub const EPOLLERR: ::c_int = 0x8; -pub const EPOLLHUP: ::c_int = 0x10; +pub const EPOLLRDHUP: ::c_int = 0x2000; +pub const EPOLLEXCLUSIVE: ::c_int = 0x10000000; +pub const EPOLLWAKEUP: ::c_int = 0x20000000; +pub const EPOLLONESHOT: ::c_int = 0x40000000; pub const EPOLLET: ::c_int = 0x80000000; pub const EPOLL_CTL_ADD: ::c_int = 1; @@ -1233,6 +1237,10 @@ pub const POLLHUP: ::c_short = 0x10; pub const POLLNVAL: ::c_short = 0x20; pub const POLLRDNORM: ::c_short = 0x040; pub const POLLRDBAND: ::c_short = 0x080; +#[cfg(not(any(target_arch = "sparc", target_arch = "sparc64")))] +pub const POLLRDHUP: ::c_short = 0x2000; +#[cfg(any(target_arch = "sparc", target_arch = "sparc64"))] +pub const POLLRDHUP: ::c_short = 0x800; pub const IPTOS_LOWDELAY: u8 = 0x10; pub const IPTOS_THROUGHPUT: u8 = 0x08; diff --git a/vendor/libc/src/unix/mod.rs b/vendor/libc/src/unix/mod.rs index 3ac1669b9a..52f8752182 100644 --- a/vendor/libc/src/unix/mod.rs +++ b/vendor/libc/src/unix/mod.rs @@ -305,21 +305,21 @@ cfg_if! { } else if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc"), feature = "rustc-dep-of-std"))] { - #[link(name = "util", kind = "static-nobundle", + #[link(name = "util", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] - #[link(name = "rt", kind = "static-nobundle", + #[link(name = "rt", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] - #[link(name = "pthread", kind = "static-nobundle", + #[link(name = "pthread", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] - #[link(name = "m", kind = "static-nobundle", + #[link(name = "m", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] - #[link(name = "dl", kind = "static-nobundle", + #[link(name = "dl", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] - #[link(name = "c", kind = "static-nobundle", + #[link(name = "c", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] - #[link(name = "gcc_eh", kind = "static-nobundle", + #[link(name = "gcc_eh", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] - #[link(name = "gcc", kind = "static-nobundle", + #[link(name = "gcc", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] #[link(name = "util", cfg(not(target_feature = "crt-static")))] #[link(name = "rt", cfg(not(target_feature = "crt-static")))] @@ -330,7 +330,7 @@ cfg_if! { extern {} } else if #[cfg(target_env = "musl")] { #[cfg_attr(feature = "rustc-dep-of-std", - link(name = "c", kind = "static", + link(name = "c", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static")))] #[cfg_attr(feature = "rustc-dep-of-std", link(name = "c", cfg(not(target_feature = "crt-static"))))] @@ -372,7 +372,7 @@ cfg_if! { extern {} } else if #[cfg(target_os = "redox")] { #[cfg_attr(feature = "rustc-dep-of-std", - link(name = "c", kind = "static-nobundle", + link(name = "c", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static")))] #[cfg_attr(feature = "rustc-dep-of-std", link(name = "c", cfg(not(target_feature = "crt-static"))))] @@ -699,6 +699,7 @@ extern "C" { all(target_os = "freebsd", any(freebsd11, freebsd10)), link_name = "fstat@FBSD_1.0" )] + #[cfg_attr(target_os = "dragonfly", allow(deprecated))] pub fn fstat(fildes: ::c_int, buf: *mut stat) -> ::c_int; pub fn mkdir(path: *const c_char, mode: mode_t) -> ::c_int; @@ -712,6 +713,7 @@ extern "C" { all(target_os = "freebsd", any(freebsd11, freebsd10)), link_name = "stat@FBSD_1.0" )] + #[cfg_attr(target_os = "dragonfly", allow(deprecated))] pub fn stat(path: *const c_char, buf: *mut stat) -> ::c_int; pub fn pclose(stream: *mut ::FILE) -> ::c_int; @@ -796,6 +798,7 @@ extern "C" { all(target_os = "freebsd", any(freebsd11, freebsd10)), link_name = "fstatat@FBSD_1.1" )] + #[cfg_attr(target_os = "dragonfly", allow(deprecated))] pub fn fstatat( dirfd: ::c_int, pathname: *const ::c_char, @@ -987,6 +990,7 @@ extern "C" { all(target_os = "freebsd", any(freebsd11, freebsd10)), link_name = "lstat@FBSD_1.0" )] + #[cfg_attr(target_os = "dragonfly", allow(deprecated))] pub fn lstat(path: *const c_char, buf: *mut stat) -> ::c_int; #[cfg_attr( diff --git a/vendor/libc/src/unix/redox/mod.rs b/vendor/libc/src/unix/redox/mod.rs index f2a2d62958..9836551d94 100644 --- a/vendor/libc/src/unix/redox/mod.rs +++ b/vendor/libc/src/unix/redox/mod.rs @@ -1001,6 +1001,8 @@ extern "C" { set: *const ::sigset_t, oldset: *mut ::sigset_t, ) -> ::c_int; + pub fn pthread_cancel(thread: ::pthread_t) -> ::c_int; + pub fn pthread_kill(thread: ::pthread_t, sig: ::c_int) -> ::c_int; // sys/epoll.h pub fn epoll_create(size: ::c_int) -> ::c_int; diff --git a/vendor/libc/src/unix/solarish/mod.rs b/vendor/libc/src/unix/solarish/mod.rs index 67147ea4a3..d1de31553e 100644 --- a/vendor/libc/src/unix/solarish/mod.rs +++ b/vendor/libc/src/unix/solarish/mod.rs @@ -35,6 +35,7 @@ pub type socklen_t = ::c_uint; pub type sa_family_t = u16; pub type pthread_t = ::c_uint; pub type pthread_key_t = ::c_uint; +pub type thread_t = ::c_uint; pub type blksize_t = ::c_int; pub type nl_item = ::c_int; pub type mqd_t = *mut ::c_void; @@ -266,6 +267,13 @@ s! { pub f_fstr: [::c_char; 32] } + pub struct sendfilevec_t { + pub sfv_fd: ::c_int, + pub sfv_flag: ::c_uint, + pub sfv_off: ::off_t, + pub sfv_len: ::size_t, + } + pub struct sched_param { pub sched_priority: ::c_int, sched_pad: [::c_int; 8] @@ -2191,6 +2199,15 @@ pub const SCHED_IA: ::c_int = 4; pub const SCHED_FSS: ::c_int = 5; pub const SCHED_FX: ::c_int = 6; +// sys/priv.h +pub const PRIV_DEBUG: ::c_uint = 0x0001; +pub const PRIV_AWARE: ::c_uint = 0x0002; +pub const PRIV_AWARE_INHERIT: ::c_uint = 0x0004; +pub const __PROC_PROTECT: ::c_uint = 0x0008; +pub const NET_MAC_AWARE: ::c_uint = 0x0010; +pub const NET_MAC_AWARE_INHERIT: ::c_uint = 0x0020; +pub const PRIV_AWARE_RESET: ::c_uint = 0x0040; + // As per sys/socket.h, header alignment must be 8 bytes on SPARC // and 4 bytes everywhere else: #[cfg(target_arch = "sparc64")] @@ -2594,6 +2611,7 @@ extern "C" { buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; + pub fn thr_self() -> ::thread_t; 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; @@ -2758,6 +2776,18 @@ extern "C" { pub fn gethostid() -> ::c_long; pub fn sethostid(hostid: ::c_long) -> ::c_int; + + pub fn getpflags(flags: ::c_uint) -> ::c_uint; + pub fn setpflags(flags: ::c_uint, value: ::c_uint) -> ::c_int; + + pub fn sendfile(out_fd: ::c_int, in_fd: ::c_int, off: *mut ::off_t, len: ::size_t) + -> ::ssize_t; + pub fn sendfilev( + fildes: ::c_int, + vec: *const sendfilevec_t, + sfvcnt: ::c_int, + xferred: *mut ::size_t, + ) -> ::ssize_t; } mod compat; diff --git a/vendor/libc/src/vxworks/mod.rs b/vendor/libc/src/vxworks/mod.rs old mode 100755 new mode 100644 diff --git a/vendor/libc/src/wasi.rs b/vendor/libc/src/wasi.rs index f66ca92857..f66550b20d 100644 --- a/vendor/libc/src/wasi.rs +++ b/vendor/libc/src/wasi.rs @@ -51,6 +51,16 @@ pub enum __locale_struct {} pub type locale_t = *mut __locale_struct; +s_paren! { + // in wasi-libc clockid_t is const struct __clockid* (where __clockid is an opaque struct), + // but that's an implementation detail that we don't want to have to deal with + #[repr(transparent)] + pub struct clockid_t(*const u8); +} + +unsafe impl Send for clockid_t {} +unsafe impl Sync for clockid_t {} + s! { #[repr(align(8))] pub struct fpos_t { @@ -342,9 +352,21 @@ pub const _SC_PAGE_SIZE: ::c_int = _SC_PAGESIZE; pub const _SC_IOV_MAX: c_int = 60; pub const _SC_SYMLOOP_MAX: c_int = 173; +pub static CLOCK_MONOTONIC: clockid_t = unsafe { clockid_t(ptr_addr_of!(_CLOCK_MONOTONIC)) }; +pub static CLOCK_PROCESS_CPUTIME_ID: clockid_t = + unsafe { clockid_t(ptr_addr_of!(_CLOCK_PROCESS_CPUTIME_ID)) }; +pub static CLOCK_REALTIME: clockid_t = unsafe { clockid_t(ptr_addr_of!(_CLOCK_REALTIME)) }; +pub static CLOCK_THREAD_CPUTIME_ID: clockid_t = + unsafe { clockid_t(ptr_addr_of!(_CLOCK_THREAD_CPUTIME_ID)) }; + #[cfg_attr( feature = "rustc-dep-of-std", - link(name = "c", kind = "static", cfg(target_feature = "crt-static")) + link( + name = "c", + kind = "static", + modifiers = "-bundle", + cfg(target_feature = "crt-static") + ) )] #[cfg_attr( feature = "rustc-dep-of-std", @@ -417,15 +439,14 @@ extern "C" { pub fn asctime_r(a: *const tm, b: *mut c_char) -> *mut c_char; pub fn ctime_r(a: *const time_t, b: *mut c_char) -> *mut c_char; + static _CLOCK_MONOTONIC: u8; + static _CLOCK_PROCESS_CPUTIME_ID: u8; + static _CLOCK_REALTIME: u8; + static _CLOCK_THREAD_CPUTIME_ID: u8; pub fn nanosleep(a: *const timespec, b: *mut timespec) -> c_int; - // pub fn clock_getres(a: clockid_t, b: *mut timespec) -> c_int; - // pub fn clock_gettime(a: clockid_t, b: *mut timespec) -> c_int; - // pub fn clock_nanosleep( - // a: clockid_t, - // a2: c_int, - // b: *const timespec, - // c: *mut timespec, - // ) -> c_int; + pub fn clock_getres(a: clockid_t, b: *mut timespec) -> c_int; + pub fn clock_gettime(a: clockid_t, b: *mut timespec) -> c_int; + pub fn clock_nanosleep(a: clockid_t, a2: c_int, b: *const timespec, c: *mut timespec) -> c_int; pub fn isalnum(c: c_int) -> c_int; pub fn isalpha(c: c_int) -> c_int; diff --git a/vendor/libc/src/windows/msvc/mod.rs b/vendor/libc/src/windows/msvc/mod.rs index 8cdb5bb176..f5a1d95f39 100644 --- a/vendor/libc/src/windows/msvc/mod.rs +++ b/vendor/libc/src/windows/msvc/mod.rs @@ -18,12 +18,3 @@ extern "C" { count: ::size_t, ) -> *mut ::c_void; } - -cfg_if! { - if #[cfg(target_arch = "x86_64")] { - mod x86_64; - pub use self::x86_64::*; - } else { - // Unknown target_arch - } -} diff --git a/vendor/libc/src/windows/msvc/x86_64.rs b/vendor/libc/src/windows/msvc/x86_64.rs deleted file mode 100644 index 249e590165..0000000000 --- a/vendor/libc/src/windows/msvc/x86_64.rs +++ /dev/null @@ -1,140 +0,0 @@ -pub type XMM_SAVE_AREA32 = XSAVE_FORMAT; - -s_no_extra_traits! { - #[repr(align(16))] - pub union __c_anonymous_CONTEXT_FP { - pub FltSave: ::XMM_SAVE_AREA32, - pub Xmm: __c_anonymous_CONTEXT_XMM, - } -} - -cfg_if! { - if #[cfg(feature = "extra_traits")] { - impl PartialEq for __c_anonymous_CONTEXT_FP { - fn eq(&self, other: &__c_anonymous_CONTEXT_FP) -> bool { - unsafe { - self.FltSave == other.FltSave || - self.Xmm == other.Xmm - } - } - } - impl Eq for __c_anonymous_CONTEXT_FP {} - impl ::fmt::Debug for __c_anonymous_CONTEXT_FP { - fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { - unsafe { - f.debug_struct("__c_anonymous_CONTEXT_FP") - .field("FltSave", &self.FltSave) - .finish() - } - } - } - impl ::hash::Hash for __c_anonymous_CONTEXT_FP { - fn hash<H: ::hash::Hasher>(&self, state: &mut H) { - unsafe { - self.FltSave.hash(state); - self.Xmm.hash(state); - } - } - } - } -} - -s! { - #[repr(align(16))] - pub struct M128A { - pub Low: ::c_ulonglong, - pub High: ::c_longlong, - } - - #[repr(align(16))] - pub struct XSAVE_FORMAT { - pub ControlWord: ::c_ushort, - pub StatusWord: ::c_ushort, - pub TagWord: ::c_uchar, - _Reserved1: ::c_uchar, - pub ErrorOpcode: ::c_ushort, - pub ErrorOffset: ::c_ulong, - pub ErrorSelector: ::c_ushort, - _Reserved2: ::c_ushort, - pub DataOffset: ::c_ulong, - pub DataSelector: ::c_ushort, - _Reserved3: ::c_ushort, - pub MxCsr: ::c_ulong, - pub MxCsr_Mask: ::c_ulong, - pub FloatRegisters: [M128A; 8], - pub XmmRegisters: [M128A; 16], - _Reserved4: [::c_uchar; 96], - } - - #[repr(align(16))] - pub struct __c_anonymous_CONTEXT_XMM { - pub Header: [M128A; 2], - pub Legacy: [M128A; 8], - pub Xmm0: M128A, - pub Xmm1: M128A, - pub Xmm2: M128A, - pub Xmm3: M128A, - pub Xmm4: M128A, - pub Xmm5: M128A, - pub Xmm6: M128A, - pub Xmm7: M128A, - pub Xmm8: M128A, - pub Xmm9: M128A, - pub Xmm10: M128A, - pub Xmm11: M128A, - pub Xmm12: M128A, - pub Xmm13: M128A, - pub Xmm14: M128A, - pub Xmm15: M128A, - } - - #[repr(align(16))] - pub struct CONTEXT { - pub P1Home: u64, - pub P2Home: u64, - pub P3Home: u64, - pub P4Home: u64, - pub P5Home: u64, - pub P6Home: u64, - pub ContextFlags: ::c_ulong, - pub MxCsr: ::c_ulong, - pub SegCs: ::c_ushort, - pub SegDs: ::c_ushort, - pub SegEs: ::c_ushort, - pub SegFs: ::c_ushort, - pub SegGs: ::c_ushort, - pub SegSs: ::c_ushort, - pub EFlags: ::c_ulong, - pub Dr0: u64, - pub Dr1: u64, - pub Dr2: u64, - pub Dr3: u64, - pub Dr6: u64, - pub Dr7: u64, - pub Rax: u64, - pub Rcx: u64, - pub Rdx: u64, - pub Rbx: u64, - pub Rsp: u64, - pub Rbp: u64, - pub Rsi: u64, - pub Rdi: u64, - pub R8: u64, - pub R9: u64, - pub R10: u64, - pub R11: u64, - pub R12: u64, - pub R13: u64, - pub R14: u64, - pub R15: u64, - pub Rip: u64, - pub Fp: __c_anonymous_CONTEXT_FP, - pub VectorRegister: [M128A; 26], - pub VectorControl: u64, - pub DebugControl: u64, - pub LastBranchToRip: u64, - pub LastBranchFromRip: u64, - pub LastExceptionToRip: u64, - pub LastExceptionFromRip: u64, - } -} diff --git a/vendor/measureme/.cargo-checksum.json b/vendor/measureme/.cargo-checksum.json index 96c5849222..df02d38378 100644 --- a/vendor/measureme/.cargo-checksum.json +++ b/vendor/measureme/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"0b0f356116651994c08186cbeacf53f1d42a84af37f0847ee217109a5bedbcd7","src/counters.rs":"5ffa4e33635bd514854b5068e85eb8e28be5e2907f9b541781bf830991bdcd1a","src/event_id.rs":"98bd9c318aa5dc52a340cafbfb023be36242b959af57226058143700282840ff","src/file_header.rs":"4057a9d61c20e0592a635cf818bc5aed913df55a260d8186757448bfc2ed2c74","src/lib.rs":"66f1f1d8ec62de22b191cb7dfd7a7d6bbe9d53f7619edbe7d69add2746c6c40c","src/profiler.rs":"f3cc47f06a0dbed64a9175e7f1b54c201fcbdef269a6d4d7f1cdef518b240233","src/raw_event.rs":"f2b9e40f8084147ee1213658cdc66380dd7ea360ae43f1bc4f083125e58bd6ad","src/rustc.rs":"c58c5fa9b23da76bf8b873dd7cb60ae4f525cdb7587bca676cc5507b97a2c96d","src/serialization.rs":"286a750a7fc95d9611f50c8ee27e2320b96e258a0e99f54000b9c920924d455a","src/stringtable.rs":"b6c07a1c30d8189b813ad95b9fe10aecd041332042dc9d629f854efddbe53ccf"},"package":"78f7a41bc6f856a2cf0e95094ad5121f82500e2d9a0f3c0171d98f6566d8117d"} \ No newline at end of file +{"files":{"Cargo.toml":"aeecbacaf0c59135fe327b596d9b2d4e59b47572b0cb49af6d707b861e9e4f92","src/counters.rs":"83e02b0fe601cfe7a951c51c5f11b8c1e089617f71d4ab75d7e4a1f55989602e","src/event_id.rs":"c1db7b65de1047ed0319d3dc9eca283d03762d3bbff57dbd6f3da41e7f0a3c99","src/file_header.rs":"07c81f3c2a0d08a9ced0631eb04c2adf5f7294c29ad91c8d21fe29f91a4cacc3","src/lib.rs":"b59c9cd98c2e00f695e1a5e3ef29b9f299ffbfec14e8cfb411a48ffff1ff7290","src/profiler.rs":"ee64a312a96f4560a45a92ab6d50942e041d4ef5cb35487ac17fd9ea3c208028","src/raw_event.rs":"0d5f70312582e5c38e20fbde5a5a11cbbd6be1ad293c907448e0fd996b888fbe","src/rustc.rs":"014d9a1bb61f6ebee39ff0b1d30b3ff14e34a76a71da2a53f5567398994d1eb7","src/serialization.rs":"abc73f80db25d21d4a73ef0524832a69a07ce6dd0a93223c618ad696a3def77e","src/stringtable.rs":"2bbf2eb606be3499985c7772622530df8d201a8ad7352e68893b271f672eb8fb"},"package":"bd460fad6e55ca82fa0cd9dab0d315294188fd9ec6efbf4105e5635d4872ef9c"} \ No newline at end of file diff --git a/vendor/measureme/Cargo.toml b/vendor/measureme/Cargo.toml index f442d3c951..284ab7202c 100644 --- a/vendor/measureme/Cargo.toml +++ b/vendor/measureme/Cargo.toml @@ -3,17 +3,16 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies +# to registry (e.g., crates.io) dependencies. # -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. [package] edition = "2018" name = "measureme" -version = "9.1.2" +version = "10.0.0" authors = ["Wesley Wiser <wwiser@gmail.com>", "Michael Woerister <michaelwoerister@posteo>"] description = "Support crate for rustc's self-profiling feature" homepage = "https://github.com/rust-lang/measureme" diff --git a/vendor/measureme/src/counters.rs b/vendor/measureme/src/counters.rs index b98efb5a53..7a053e9709 100644 --- a/vendor/measureme/src/counters.rs +++ b/vendor/measureme/src/counters.rs @@ -525,47 +525,22 @@ mod hw { /// the width of the register (32 to 64 bits, e.g. 48-bit seems common). #[inline(always)] fn rdpmc(reg_idx: u32) -> u64 { - let (lo, hi): (u32, u32); - unsafe { - // NOTE(eddyb) below comment is outdated (the other branch uses `cpuid`). - if cfg!(unserialized_rdpmc) && false { - // FIXME(eddyb) the Intel and AMD manuals warn about the need for - // "serializing instructions" before/after `rdpmc`, if avoiding any - // reordering is desired, but do not agree on the full set of usable - // "serializing instructions" (e.g. `mfence` isn't listed in both). - // - // The only usable, and guaranteed to work, "serializing instruction" - // appears to be `cpuid`, but it doesn't seem easy to use, especially - // due to the overlap in registers with `rdpmc` itself, and it might - // have too high of a cost, compared to serialization benefits (if any). - asm!("rdpmc", in("ecx") reg_idx, out("eax") lo, out("edx") hi, options(nostack)); - } else { - asm!( - // Dummy `cpuid(0)` to serialize instruction execution. - "xor %eax, %eax", // Intel syntax: "xor eax, eax" - "cpuid", - - "mov {rdpmc_ecx:e}, %ecx", // Intel syntax: "mov ecx, {rdpmc_ecx:e}" - "rdpmc", - rdpmc_ecx = in(reg) reg_idx, - out("eax") lo, - out("edx") hi, - - // `cpuid` clobbers (not overwritten by `rdpmc`). - out("ebx") _, - out("ecx") _, - - options(nostack), - - // HACK(eddyb) LLVM 9 and older do not support modifiers - // in Intel syntax inline asm; whenever Rust minimum LLVM - // version becomes LLVM 10, remove and replace above - // instructions with Intel syntax version (from comments). - options(att_syntax), - ); - } + // NOTE(eddyb) below comment is outdated (the other branch uses `cpuid`). + if cfg!(unserialized_rdpmc) && false { + // FIXME(eddyb) the Intel and AMD manuals warn about the need for + // "serializing instructions" before/after `rdpmc`, if avoiding any + // reordering is desired, but do not agree on the full set of usable + // "serializing instructions" (e.g. `mfence` isn't listed in both). + // + // The only usable, and guaranteed to work, "serializing instruction" + // appears to be `cpuid`, but it doesn't seem easy to use, especially + // due to the overlap in registers with `rdpmc` itself, and it might + // have too high of a cost, compared to serialization benefits (if any). + unserialized_rdpmc(reg_idx) + } else { + serialize_instruction_execution(); + unserialized_rdpmc(reg_idx) } - lo as u64 | (hi as u64) << 32 } /// Read two hardware performance counters at once (see `rdpmc`). @@ -574,44 +549,59 @@ mod hw { /// only requires one "serializing instruction", rather than two. #[inline(always)] fn rdpmc_pair(a_reg_idx: u32, b_reg_idx: u32) -> (u64, u64) { - let (a_lo, a_hi): (u32, u32); - let (b_lo, b_hi): (u32, u32); + serialize_instruction_execution(); + (unserialized_rdpmc(a_reg_idx), unserialized_rdpmc(b_reg_idx)) + } + + /// Dummy `cpuid(0)` to serialize instruction execution. + #[inline(always)] + fn serialize_instruction_execution() { unsafe { asm!( - // Dummy `cpuid(0)` to serialize instruction execution. "xor %eax, %eax", // Intel syntax: "xor eax, eax" + // LLVM sometimes reserves `ebx` for its internal use, so we need to use + // a scratch register for it instead. + "mov %rbx, {tmp_rbx:r}", // Intel syntax: "mov {tmp_rbx:r}, rbx" "cpuid", - - "mov {a_rdpmc_ecx:e}, %ecx", // Intel syntax: "mov ecx, {a_rdpmc_ecx:e}" - "rdpmc", - "mov %eax, {a_rdpmc_eax:e}", // Intel syntax: "mov {a_rdpmc_eax:e}, eax" - "mov %edx, {a_rdpmc_edx:e}", // Intel syntax: "mov {a_rdpmc_edx:e}, edx" - "mov {b_rdpmc_ecx:e}, %ecx", // Intel syntax: "mov ecx, {b_rdpmc_ecx:e}" - "rdpmc", - a_rdpmc_ecx = in(reg) a_reg_idx, - a_rdpmc_eax = out(reg) a_lo, - a_rdpmc_edx = out(reg) a_hi, - b_rdpmc_ecx = in(reg) b_reg_idx, - out("eax") b_lo, - out("edx") b_hi, - - // `cpuid` clobbers (not overwritten by `rdpmc`). - out("ebx") _, - out("ecx") _, + "mov {tmp_rbx:r}, %rbx", // Intel syntax: "mov rbx, {tmp_rbx:r}" + tmp_rbx = lateout(reg) _, + // `cpuid` clobbers. + lateout("eax") _, + lateout("edx") _, + lateout("ecx") _, options(nostack), + // Older versions of LLVM do not support modifiers in + // Intel syntax inline asm; whenever Rust minimum LLVM version + // supports Intel syntax inline asm, remove and replace above + // instructions with Intel syntax version (from comments). + options(att_syntax), + ); + } + } - // HACK(eddyb) LLVM 9 and older do not support modifiers - // in Intel syntax inline asm; whenever Rust minimum LLVM - // version becomes LLVM 10, remove and replace above + /// Read the hardware performance counter indicated by `reg_idx`. + /// + /// If the counter is signed, sign extension should be performed based on + /// the width of the register (32 to 64 bits, e.g. 48-bit seems common). + #[inline(always)] + fn unserialized_rdpmc(reg_idx: u32) -> u64 { + let (lo, hi): (u32, u32); + unsafe { + asm!( + "rdpmc", + in("ecx") reg_idx, + lateout("eax") lo, + lateout("edx") hi, + options(nostack), + // Older versions of LLVM do not support modifiers in + // Intel syntax inline asm; whenever Rust minimum LLVM version + // supports Intel syntax inline asm, remove and replace above // instructions with Intel syntax version (from comments). options(att_syntax), ); } - ( - a_lo as u64 | (a_hi as u64) << 32, - b_lo as u64 | (b_hi as u64) << 32, - ) + lo as u64 | (hi as u64) << 32 } /// Categorization of `x86_64` CPUs, primarily based on how they @@ -821,10 +811,11 @@ mod hw { atomic = in(reg) &mut atomic, tmp = inout(reg) _tmp, - // HACK(eddyb) LLVM 9 and older do not support modifiers - // in Intel syntax inline asm; whenever Rust minimum LLVM - // version becomes LLVM 10, remove and replace above - // instructions with Intel syntax version (from comments). + // Older versions of LLVM do not support modifiers in + // Intel syntax inline asm; whenever Rust minimum LLVM + // version supports Intel syntax inline asm, remove + // and replace above instructions with Intel syntax + // version (from comments). options(att_syntax), ); } diff --git a/vendor/measureme/src/event_id.rs b/vendor/measureme/src/event_id.rs index 7a10af42f4..0c361a3420 100644 --- a/vendor/measureme/src/event_id.rs +++ b/vendor/measureme/src/event_id.rs @@ -1,97 +1,97 @@ -use smallvec::SmallVec; - -use crate::{Profiler, StringComponent, StringId}; - -/// Event IDs are strings conforming to the following grammar: -/// -/// ```ignore -/// <event_id> = <label> {<argument>} -/// <label> = <text> -/// <argument> = '\x1E' <text> -/// <text> = regex([^[[:cntrl:]]]+) // Anything but ASCII control characters -/// ``` -/// -/// This means there's always a "label", followed by an optional list of -/// arguments. Future versions my support other optional suffixes (with a tag -/// other than '\x11' after the '\x1E' separator), such as a "category". - -/// The byte used to separate arguments from the label and each other. -pub const SEPARATOR_BYTE: &str = "\x1E"; - -/// An `EventId` is a `StringId` with the additional guarantee that the -/// corresponding string conforms to the event_id grammar. -#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] -#[repr(C)] -pub struct EventId(StringId); - -impl EventId { - pub const INVALID: EventId = EventId(StringId::INVALID); - - #[inline] - pub fn to_string_id(self) -> StringId { - self.0 - } - - #[inline] - pub fn as_u32(self) -> u32 { - self.0.as_u32() - } - - #[inline] - pub fn from_label(label: StringId) -> EventId { - EventId(label) - } - - #[inline] - pub fn from_virtual(virtual_id: StringId) -> EventId { - EventId(virtual_id) - } - - /// Create an EventId from a raw u32 value. Only used internally for - /// deserialization. - #[inline] - pub fn from_u32(raw_id: u32) -> EventId { - EventId(StringId::new(raw_id)) - } -} - -pub struct EventIdBuilder<'p> { - profiler: &'p Profiler, -} - -impl<'p> EventIdBuilder<'p> { - pub fn new(profiler: &Profiler) -> EventIdBuilder<'_> { - EventIdBuilder { profiler } - } - - #[inline] - pub fn from_label(&self, label: StringId) -> EventId { - // Just forward the string ID, a single identifier is a valid event_id - EventId::from_label(label) - } - - pub fn from_label_and_arg(&self, label: StringId, arg: StringId) -> EventId { - EventId(self.profiler.alloc_string(&[ - // Label - StringComponent::Ref(label), - // Seperator and start tag for arg - StringComponent::Value(SEPARATOR_BYTE), - // Arg string id - StringComponent::Ref(arg), - ])) - } - - pub fn from_label_and_args(&self, label: StringId, args: &[StringId]) -> EventId { - // Store up to 7 components on the stack: 1 label + 3 arguments + 3 argument separators - let mut parts = SmallVec::<[StringComponent; 7]>::with_capacity(1 + args.len() * 2); - - parts.push(StringComponent::Ref(label)); - - for arg in args { - parts.push(StringComponent::Value(SEPARATOR_BYTE)); - parts.push(StringComponent::Ref(*arg)); - } - - EventId(self.profiler.alloc_string(&parts[..])) - } -} +use smallvec::SmallVec; + +use crate::{Profiler, StringComponent, StringId}; + +/// Event IDs are strings conforming to the following grammar: +/// +/// ```ignore +/// <event_id> = <label> {<argument>} +/// <label> = <text> +/// <argument> = '\x1E' <text> +/// <text> = regex([^[[:cntrl:]]]+) // Anything but ASCII control characters +/// ``` +/// +/// This means there's always a "label", followed by an optional list of +/// arguments. Future versions my support other optional suffixes (with a tag +/// other than '\x11' after the '\x1E' separator), such as a "category". + +/// The byte used to separate arguments from the label and each other. +pub const SEPARATOR_BYTE: &str = "\x1E"; + +/// An `EventId` is a `StringId` with the additional guarantee that the +/// corresponding string conforms to the event_id grammar. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] +#[repr(C)] +pub struct EventId(StringId); + +impl EventId { + pub const INVALID: EventId = EventId(StringId::INVALID); + + #[inline] + pub fn to_string_id(self) -> StringId { + self.0 + } + + #[inline] + pub fn as_u32(self) -> u32 { + self.0.as_u32() + } + + #[inline] + pub fn from_label(label: StringId) -> EventId { + EventId(label) + } + + #[inline] + pub fn from_virtual(virtual_id: StringId) -> EventId { + EventId(virtual_id) + } + + /// Create an EventId from a raw u32 value. Only used internally for + /// deserialization. + #[inline] + pub fn from_u32(raw_id: u32) -> EventId { + EventId(StringId::new(raw_id)) + } +} + +pub struct EventIdBuilder<'p> { + profiler: &'p Profiler, +} + +impl<'p> EventIdBuilder<'p> { + pub fn new(profiler: &Profiler) -> EventIdBuilder<'_> { + EventIdBuilder { profiler } + } + + #[inline] + pub fn from_label(&self, label: StringId) -> EventId { + // Just forward the string ID, a single identifier is a valid event_id + EventId::from_label(label) + } + + pub fn from_label_and_arg(&self, label: StringId, arg: StringId) -> EventId { + EventId(self.profiler.alloc_string(&[ + // Label + StringComponent::Ref(label), + // Seperator and start tag for arg + StringComponent::Value(SEPARATOR_BYTE), + // Arg string id + StringComponent::Ref(arg), + ])) + } + + pub fn from_label_and_args(&self, label: StringId, args: &[StringId]) -> EventId { + // Store up to 7 components on the stack: 1 label + 3 arguments + 3 argument separators + let mut parts = SmallVec::<[StringComponent; 7]>::with_capacity(1 + args.len() * 2); + + parts.push(StringComponent::Ref(label)); + + for arg in args { + parts.push(StringComponent::Value(SEPARATOR_BYTE)); + parts.push(StringComponent::Ref(*arg)); + } + + EventId(self.profiler.alloc_string(&parts[..])) + } +} diff --git a/vendor/measureme/src/file_header.rs b/vendor/measureme/src/file_header.rs index 773d9e5dfd..8ad192895d 100644 --- a/vendor/measureme/src/file_header.rs +++ b/vendor/measureme/src/file_header.rs @@ -1,145 +1,145 @@ -//! All binary files generated by measureme have a simple file header that -//! consists of a 4 byte file magic string and a 4 byte little-endian version -//! number. -use std::convert::TryInto; -use std::error::Error; -use std::path::Path; - -pub const CURRENT_FILE_FORMAT_VERSION: u32 = 7; - -pub const FILE_MAGIC_TOP_LEVEL: &[u8; 4] = b"MMPD"; -pub const FILE_MAGIC_EVENT_STREAM: &[u8; 4] = b"MMES"; -pub const FILE_MAGIC_STRINGTABLE_DATA: &[u8; 4] = b"MMSD"; -pub const FILE_MAGIC_STRINGTABLE_INDEX: &[u8; 4] = b"MMSI"; - -pub const FILE_EXTENSION: &str = "mm_profdata"; - -/// The size of the file header in bytes. Note that functions in this module -/// rely on this size to be `8`. -pub const FILE_HEADER_SIZE: usize = 8; - -pub fn write_file_header( - s: &mut dyn std::io::Write, - file_magic: &[u8; 4], -) -> Result<(), Box<dyn Error + Send + Sync>> { - // The implementation here relies on FILE_HEADER_SIZE to have the value 8. - // Let's make sure this assumption cannot be violated without being noticed. - assert_eq!(FILE_HEADER_SIZE, 8); - - s.write_all(file_magic).map_err(Box::new)?; - s.write_all(&CURRENT_FILE_FORMAT_VERSION.to_le_bytes()) - .map_err(Box::new)?; - - Ok(()) -} - -#[must_use] -pub fn verify_file_header( - bytes: &[u8], - expected_magic: &[u8; 4], - diagnostic_file_path: Option<&Path>, - stream_tag: &str, -) -> Result<(), Box<dyn Error + Send + Sync>> { - // The implementation here relies on FILE_HEADER_SIZE to have the value 8. - // Let's make sure this assumption cannot be violated without being noticed. - assert_eq!(FILE_HEADER_SIZE, 8); - - let diagnostic_file_path = diagnostic_file_path.unwrap_or(Path::new("<in-memory>")); - - if bytes.len() < FILE_HEADER_SIZE { - let msg = format!( - "Error reading {} stream in file `{}`: Expected file to contain at least `{:?}` bytes but found `{:?}` bytes", - stream_tag, - diagnostic_file_path.display(), - FILE_HEADER_SIZE, - bytes.len() - ); - - return Err(From::from(msg)); - } - - let actual_magic = &bytes[0..4]; - - if actual_magic != expected_magic { - let msg = format!( - "Error reading {} stream in file `{}`: Expected file magic `{:?}` but found `{:?}`", - stream_tag, - diagnostic_file_path.display(), - expected_magic, - actual_magic - ); - - return Err(From::from(msg)); - } - - let file_format_version = u32::from_le_bytes(bytes[4..8].try_into().unwrap()); - - if file_format_version != CURRENT_FILE_FORMAT_VERSION { - let msg = format!( - "Error reading {} stream in file `{}`: Expected file format version {} but found `{}`", - stream_tag, - diagnostic_file_path.display(), - CURRENT_FILE_FORMAT_VERSION, - file_format_version - ); - - return Err(From::from(msg)); - } - - Ok(()) -} - -pub fn strip_file_header(data: &[u8]) -> &[u8] { - &data[FILE_HEADER_SIZE..] -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{PageTag, SerializationSinkBuilder}; - - #[test] - fn roundtrip() { - let data_sink = SerializationSinkBuilder::new_in_memory().new_sink(PageTag::Events); - - write_file_header(&mut data_sink.as_std_write(), FILE_MAGIC_EVENT_STREAM).unwrap(); - - let data = data_sink.into_bytes(); - - verify_file_header(&data, FILE_MAGIC_EVENT_STREAM, None, "test").unwrap(); - } - - #[test] - fn invalid_magic() { - let data_sink = SerializationSinkBuilder::new_in_memory().new_sink(PageTag::Events); - write_file_header(&mut data_sink.as_std_write(), FILE_MAGIC_STRINGTABLE_DATA).unwrap(); - let mut data = data_sink.into_bytes(); - - // Invalidate the filemagic - data[2] = 0; - assert!(verify_file_header(&data, FILE_MAGIC_STRINGTABLE_DATA, None, "test").is_err()); - } - - #[test] - fn other_version() { - let data_sink = SerializationSinkBuilder::new_in_memory().new_sink(PageTag::Events); - - write_file_header(&mut data_sink.as_std_write(), FILE_MAGIC_STRINGTABLE_INDEX).unwrap(); - - let mut data = data_sink.into_bytes(); - - // Change version - data[4] = 0xFF; - data[5] = 0xFF; - data[6] = 0xFF; - data[7] = 0xFF; - assert!(verify_file_header(&data, FILE_MAGIC_STRINGTABLE_INDEX, None, "test").is_err()); - } - - #[test] - fn empty_file() { - let data: [u8; 0] = []; - - assert!(verify_file_header(&data, FILE_MAGIC_STRINGTABLE_DATA, None, "test").is_err()); - } -} +//! All binary files generated by measureme have a simple file header that +//! consists of a 4 byte file magic string and a 4 byte little-endian version +//! number. +use std::convert::TryInto; +use std::error::Error; +use std::path::Path; + +pub const CURRENT_FILE_FORMAT_VERSION: u32 = 8; + +pub const FILE_MAGIC_TOP_LEVEL: &[u8; 4] = b"MMPD"; +pub const FILE_MAGIC_EVENT_STREAM: &[u8; 4] = b"MMES"; +pub const FILE_MAGIC_STRINGTABLE_DATA: &[u8; 4] = b"MMSD"; +pub const FILE_MAGIC_STRINGTABLE_INDEX: &[u8; 4] = b"MMSI"; + +pub const FILE_EXTENSION: &str = "mm_profdata"; + +/// The size of the file header in bytes. Note that functions in this module +/// rely on this size to be `8`. +pub const FILE_HEADER_SIZE: usize = 8; + +pub fn write_file_header( + s: &mut dyn std::io::Write, + file_magic: &[u8; 4], +) -> Result<(), Box<dyn Error + Send + Sync>> { + // The implementation here relies on FILE_HEADER_SIZE to have the value 8. + // Let's make sure this assumption cannot be violated without being noticed. + assert_eq!(FILE_HEADER_SIZE, 8); + + s.write_all(file_magic).map_err(Box::new)?; + s.write_all(&CURRENT_FILE_FORMAT_VERSION.to_le_bytes()) + .map_err(Box::new)?; + + Ok(()) +} + +#[must_use] +pub fn verify_file_header( + bytes: &[u8], + expected_magic: &[u8; 4], + diagnostic_file_path: Option<&Path>, + stream_tag: &str, +) -> Result<(), Box<dyn Error + Send + Sync>> { + // The implementation here relies on FILE_HEADER_SIZE to have the value 8. + // Let's make sure this assumption cannot be violated without being noticed. + assert_eq!(FILE_HEADER_SIZE, 8); + + let diagnostic_file_path = diagnostic_file_path.unwrap_or(Path::new("<in-memory>")); + + if bytes.len() < FILE_HEADER_SIZE { + let msg = format!( + "Error reading {} stream in file `{}`: Expected file to contain at least `{:?}` bytes but found `{:?}` bytes", + stream_tag, + diagnostic_file_path.display(), + FILE_HEADER_SIZE, + bytes.len() + ); + + return Err(From::from(msg)); + } + + let actual_magic = &bytes[0..4]; + + if actual_magic != expected_magic { + let msg = format!( + "Error reading {} stream in file `{}`: Expected file magic `{:?}` but found `{:?}`", + stream_tag, + diagnostic_file_path.display(), + expected_magic, + actual_magic + ); + + return Err(From::from(msg)); + } + + let file_format_version = u32::from_le_bytes(bytes[4..8].try_into().unwrap()); + + if file_format_version != CURRENT_FILE_FORMAT_VERSION { + let msg = format!( + "Error reading {} stream in file `{}`: Expected file format version {} but found `{}`", + stream_tag, + diagnostic_file_path.display(), + CURRENT_FILE_FORMAT_VERSION, + file_format_version + ); + + return Err(From::from(msg)); + } + + Ok(()) +} + +pub fn strip_file_header(data: &[u8]) -> &[u8] { + &data[FILE_HEADER_SIZE..] +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{PageTag, SerializationSinkBuilder}; + + #[test] + fn roundtrip() { + let data_sink = SerializationSinkBuilder::new_in_memory().new_sink(PageTag::Events); + + write_file_header(&mut data_sink.as_std_write(), FILE_MAGIC_EVENT_STREAM).unwrap(); + + let data = data_sink.into_bytes(); + + verify_file_header(&data, FILE_MAGIC_EVENT_STREAM, None, "test").unwrap(); + } + + #[test] + fn invalid_magic() { + let data_sink = SerializationSinkBuilder::new_in_memory().new_sink(PageTag::Events); + write_file_header(&mut data_sink.as_std_write(), FILE_MAGIC_STRINGTABLE_DATA).unwrap(); + let mut data = data_sink.into_bytes(); + + // Invalidate the filemagic + data[2] = 0; + assert!(verify_file_header(&data, FILE_MAGIC_STRINGTABLE_DATA, None, "test").is_err()); + } + + #[test] + fn other_version() { + let data_sink = SerializationSinkBuilder::new_in_memory().new_sink(PageTag::Events); + + write_file_header(&mut data_sink.as_std_write(), FILE_MAGIC_STRINGTABLE_INDEX).unwrap(); + + let mut data = data_sink.into_bytes(); + + // Change version + data[4] = 0xFF; + data[5] = 0xFF; + data[6] = 0xFF; + data[7] = 0xFF; + assert!(verify_file_header(&data, FILE_MAGIC_STRINGTABLE_INDEX, None, "test").is_err()); + } + + #[test] + fn empty_file() { + let data: [u8; 0] = []; + + assert!(verify_file_header(&data, FILE_MAGIC_STRINGTABLE_DATA, None, "test").is_err()); + } +} diff --git a/vendor/measureme/src/lib.rs b/vendor/measureme/src/lib.rs index aabaeea830..f40b04f8fa 100644 --- a/vendor/measureme/src/lib.rs +++ b/vendor/measureme/src/lib.rs @@ -1,10 +1,8 @@ //! This crate provides a library for high-performance event tracing which is used by //! the Rust compiler's unstable `-Z self-profile` feature. //! -//! The output of a tracing session will be three files: -//! 1. A `.events` file which contains all of the traced events. -//! 2. A `.string_data` file which contains all the strings referenced by events. -//! 3. A `.string_index` file which maps `StringId` values to offsets into the `.string_data` file. +//! The output of a tracing session will be an `.mm_profdata` file containing a stream +//! of events and a string table that allows to decode the `StringId`s in the event stream. //! //! # Writing event trace files //! @@ -50,8 +48,8 @@ pub mod stringtable; pub mod rustc; pub use crate::event_id::{EventId, EventIdBuilder}; -pub use crate::profiler::{Profiler, TimingGuard, DetachedTiming}; -pub use crate::raw_event::{RawEvent, MAX_INSTANT_TIMESTAMP, MAX_INTERVAL_TIMESTAMP}; +pub use crate::profiler::{DetachedTiming, Profiler, TimingGuard}; +pub use crate::raw_event::{RawEvent, MAX_INTERVAL_VALUE, MAX_SINGLE_VALUE}; pub use crate::serialization::{ split_streams, Addr, PageTag, SerializationSink, SerializationSinkBuilder, }; diff --git a/vendor/measureme/src/profiler.rs b/vendor/measureme/src/profiler.rs index d243d0f1f0..0fdf417274 100644 --- a/vendor/measureme/src/profiler.rs +++ b/vendor/measureme/src/profiler.rs @@ -104,6 +104,19 @@ impl Profiler { self.record_raw_event(&raw_event); } + /// Records an event with the given parameters. The event time is computed + /// automatically. + pub fn record_integer_event( + &self, + event_kind: StringId, + event_id: EventId, + thread_id: u32, + value: u64, + ) { + let raw_event = RawEvent::new_integer(event_kind, event_id, thread_id, value); + self.record_raw_event(&raw_event); + } + /// Creates a "start" event and returns a `TimingGuard` that will create /// the corresponding "end" event when it is dropped. #[inline] @@ -135,7 +148,7 @@ impl Profiler { &self, event_kind: StringId, event_id: EventId, - thread_id: u32 + thread_id: u32, ) -> DetachedTiming { DetachedTiming { event_id, @@ -148,10 +161,7 @@ impl Profiler { /// Creates the corresponding "end" event for /// the "start" event represented by `timing`. You /// must have obtained `timing` from the same `Profiler` - pub fn finish_recording_interval_event( - &self, - timing: DetachedTiming - ) { + pub fn finish_recording_interval_event(&self, timing: DetachedTiming) { drop(TimingGuard { profiler: self, event_id: timing.event_id, diff --git a/vendor/measureme/src/raw_event.rs b/vendor/measureme/src/raw_event.rs index b6996dce54..f181fb56f7 100644 --- a/vendor/measureme/src/raw_event.rs +++ b/vendor/measureme/src/raw_event.rs @@ -1,345 +1,409 @@ -use crate::event_id::EventId; -use crate::stringtable::StringId; -#[cfg(target_endian = "big")] -use std::convert::TryInto; - -/// `RawEvent` is how events are stored on-disk. If you change this struct, -/// make sure that you increment `file_header::CURRENT_FILE_FORMAT_VERSION`. -#[derive(Eq, PartialEq, Debug)] -#[repr(C)] -pub struct RawEvent { - pub event_kind: StringId, - pub event_id: EventId, - pub thread_id: u32, - - // The following 96 bits store the start and the end counter value, using - // 48 bits for each. - // FIXME(eddyb) s/time/count/ - pub start_time_lower: u32, - // FIXME(eddyb) s/time/count/ - pub end_time_lower: u32, - pub start_and_end_upper: u32, -} - -/// `RawEvents` that have an end counter value with this value are instant events. -const INSTANT_COUNT_MARKER: u64 = 0xFFFF_FFFF_FFFF; - -/// The max instant counter value we can represent with the 48 bits available. -// FIXME(eddyb) s/TIMESTAMP/COUNT/ -pub const MAX_INSTANT_TIMESTAMP: u64 = 0xFFFF_FFFF_FFFF; - -/// The max interval counter value we can represent with the 48 bits available. -/// The highest value is reserved for the `INSTANT_COUNT_MARKER`. -// FIXME(eddyb) s/TIMESTAMP/COUNT/ -pub const MAX_INTERVAL_TIMESTAMP: u64 = INSTANT_COUNT_MARKER - 1; - -impl RawEvent { - #[inline] - pub fn new_interval( - event_kind: StringId, - event_id: EventId, - thread_id: u32, - start_count: u64, - end_count: u64, - ) -> RawEvent { - assert!(start_count <= end_count); - assert!(end_count <= MAX_INTERVAL_TIMESTAMP); - - let start_time_lower = start_count as u32; - let end_time_lower = end_count as u32; - - let start_time_upper = (start_count >> 16) as u32 & 0xFFFF_0000; - let end_time_upper = (end_count >> 32) as u32; - - let start_and_end_upper = start_time_upper | end_time_upper; - - RawEvent { - event_kind, - event_id, - thread_id, - start_time_lower, - end_time_lower, - start_and_end_upper, - } - } - - #[inline] - pub fn new_instant( - event_kind: StringId, - event_id: EventId, - thread_id: u32, - count: u64, - ) -> RawEvent { - assert!(count <= MAX_INSTANT_TIMESTAMP); - - let start_time_lower = count as u32; - let end_time_lower = 0xFFFF_FFFF; - - let start_time_upper = (count >> 16) as u32; - let start_and_end_upper = start_time_upper | 0x0000_FFFF; - - RawEvent { - event_kind, - event_id, - thread_id, - start_time_lower, - end_time_lower, - start_and_end_upper, - } - } - - #[inline] - // FIXME(eddyb) s/nanos/count/ - pub fn start_nanos(&self) -> u64 { - self.start_time_lower as u64 | (((self.start_and_end_upper & 0xFFFF_0000) as u64) << 16) - } - - #[inline] - // FIXME(eddyb) s/nanos/count/ - pub fn end_nanos(&self) -> u64 { - self.end_time_lower as u64 | (((self.start_and_end_upper & 0x0000_FFFF) as u64) << 32) - } - - #[inline] - pub fn is_instant(&self) -> bool { - self.end_nanos() == INSTANT_COUNT_MARKER - } - - #[inline] - pub fn serialize(&self, bytes: &mut [u8]) { - assert!(bytes.len() == std::mem::size_of::<RawEvent>()); - - #[cfg(target_endian = "little")] - { - let raw_event_bytes: &[u8] = unsafe { - std::slice::from_raw_parts( - self as *const _ as *const u8, - std::mem::size_of::<RawEvent>(), - ) - }; - - bytes.copy_from_slice(raw_event_bytes); - } - - #[cfg(target_endian = "big")] - { - // We always emit data as little endian, which we have to do - // manually on big endian targets. - bytes[0..4].copy_from_slice(&self.event_kind.as_u32().to_le_bytes()); - bytes[4..8].copy_from_slice(&self.event_id.as_u32().to_le_bytes()); - bytes[8..12].copy_from_slice(&self.thread_id.to_le_bytes()); - bytes[12..16].copy_from_slice(&self.start_time_lower.to_le_bytes()); - bytes[16..20].copy_from_slice(&self.end_time_lower.to_le_bytes()); - bytes[20..24].copy_from_slice(&self.start_and_end_upper.to_le_bytes()); - } - } - - #[inline] - pub fn deserialize(bytes: &[u8]) -> RawEvent { - assert!(bytes.len() == std::mem::size_of::<RawEvent>()); - - #[cfg(target_endian = "little")] - { - let mut raw_event = RawEvent::default(); - unsafe { - let raw_event = std::slice::from_raw_parts_mut( - &mut raw_event as *mut RawEvent as *mut u8, - std::mem::size_of::<RawEvent>(), - ); - raw_event.copy_from_slice(bytes); - }; - raw_event - } - - #[cfg(target_endian = "big")] - { - RawEvent { - event_kind: StringId::new(u32::from_le_bytes(bytes[0..4].try_into().unwrap())), - event_id: EventId::from_u32(u32::from_le_bytes(bytes[4..8].try_into().unwrap())), - thread_id: u32::from_le_bytes(bytes[8..12].try_into().unwrap()), - start_time_lower: u32::from_le_bytes(bytes[12..16].try_into().unwrap()), - end_time_lower: u32::from_le_bytes(bytes[16..20].try_into().unwrap()), - start_and_end_upper: u32::from_le_bytes(bytes[20..24].try_into().unwrap()), - } - } - } -} - -impl Default for RawEvent { - fn default() -> Self { - RawEvent { - event_kind: StringId::INVALID, - event_id: EventId::INVALID, - thread_id: 0, - start_time_lower: 0, - end_time_lower: 0, - start_and_end_upper: 0, - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn raw_event_has_expected_size() { - // A test case to prevent accidental regressions of RawEvent's size. - assert_eq!(std::mem::size_of::<RawEvent>(), 24); - } - - #[test] - fn is_instant() { - assert!(RawEvent::new_instant(StringId::INVALID, EventId::INVALID, 987, 0,).is_instant()); - - assert!(RawEvent::new_instant( - StringId::INVALID, - EventId::INVALID, - 987, - MAX_INSTANT_TIMESTAMP, - ) - .is_instant()); - - assert!(!RawEvent::new_interval( - StringId::INVALID, - EventId::INVALID, - 987, - 0, - MAX_INTERVAL_TIMESTAMP, - ) - .is_instant()); - } - - #[test] - #[should_panic] - fn invalid_instant_count() { - let _ = RawEvent::new_instant( - StringId::INVALID, - EventId::INVALID, - 123, - // count too large - MAX_INSTANT_TIMESTAMP + 1, - ); - } - - #[test] - #[should_panic] - fn invalid_start_count() { - let _ = RawEvent::new_interval( - StringId::INVALID, - EventId::INVALID, - 123, - // start count too large - MAX_INTERVAL_TIMESTAMP + 1, - MAX_INTERVAL_TIMESTAMP + 1, - ); - } - - #[test] - #[should_panic] - fn invalid_end_count() { - let _ = RawEvent::new_interval( - StringId::INVALID, - EventId::INVALID, - 123, - 0, - // end count too large - MAX_INTERVAL_TIMESTAMP + 3, - ); - } - - #[test] - #[should_panic] - fn invalid_end_count2() { - let _ = RawEvent::new_interval( - StringId::INVALID, - EventId::INVALID, - 123, - 0, - INSTANT_COUNT_MARKER, - ); - } - - #[test] - #[should_panic] - fn start_greater_than_end_count() { - let _ = RawEvent::new_interval( - StringId::INVALID, - EventId::INVALID, - 123, - // start count greater than end count - 1, - 0, - ); - } - - #[test] - fn start_equal_to_end_count() { - // This is allowed, make sure we don't panic - let _ = RawEvent::new_interval(StringId::INVALID, EventId::INVALID, 123, 1, 1); - } - - #[test] - fn interval_count_decoding() { - // Check the upper limits - let e = RawEvent::new_interval( - StringId::INVALID, - EventId::INVALID, - 1234, - MAX_INTERVAL_TIMESTAMP, - MAX_INTERVAL_TIMESTAMP, - ); - - assert_eq!(e.start_nanos(), MAX_INTERVAL_TIMESTAMP); - assert_eq!(e.end_nanos(), MAX_INTERVAL_TIMESTAMP); - - // Check the lower limits - let e = RawEvent::new_interval(StringId::INVALID, EventId::INVALID, 1234, 0, 0); - - assert_eq!(e.start_nanos(), 0); - assert_eq!(e.end_nanos(), 0); - - // Check that end does not bleed into start - let e = RawEvent::new_interval( - StringId::INVALID, - EventId::INVALID, - 1234, - 0, - MAX_INTERVAL_TIMESTAMP, - ); - - assert_eq!(e.start_nanos(), 0); - assert_eq!(e.end_nanos(), MAX_INTERVAL_TIMESTAMP); - - // Test some random values - let e = RawEvent::new_interval( - StringId::INVALID, - EventId::INVALID, - 1234, - 0x1234567890, - 0x1234567890A, - ); - - assert_eq!(e.start_nanos(), 0x1234567890); - assert_eq!(e.end_nanos(), 0x1234567890A); - } - - #[test] - fn instant_count_decoding() { - assert_eq!( - RawEvent::new_instant(StringId::INVALID, EventId::INVALID, 987, 0,).start_nanos(), - 0 - ); - - assert_eq!( - RawEvent::new_instant( - StringId::INVALID, - EventId::INVALID, - 987, - MAX_INSTANT_TIMESTAMP, - ) - .start_nanos(), - MAX_INSTANT_TIMESTAMP - ); - } -} +use crate::event_id::EventId; +use crate::stringtable::StringId; +#[cfg(target_endian = "big")] +use std::convert::TryInto; + +/// `RawEvent` is how events are stored on-disk. If you change this struct, +/// make sure that you increment `file_header::CURRENT_FILE_FORMAT_VERSION`. +#[derive(Eq, PartialEq, Debug)] +#[repr(C)] +pub struct RawEvent { + pub event_kind: StringId, + pub event_id: EventId, + pub thread_id: u32, + + // The following 96 bits store the payload values, using + // 48 bits for each. + // Interval: + // Payload 1 is start value and payload 2 is end value + // SSSSSSSSSSSSSSSSEEEEEEEEEEEEEEEESSSSSSSEEEEEEEEE + // [payload1_lower][payload2_lower][payloads_upper] + // Instant: + // Payload2 is 0xFFFF_FFFF_FFFF + // VVVVVVVVVVVVVVVV1111111111111111VVVVVVV11111111 + // [payload1_lower][payload2_lower][payloads_upper] + // Integer: + // Payload2 is 0xFFFF_FFFF_FFFE + // VVVVVVVVVVVVVVVV1111111111111111VVVVVVV11111110 + // [payload1_lower][payload2_lower][payloads_upper] + pub payload1_lower: u32, + pub payload2_lower: u32, + pub payloads_upper: u32, +} + +/// `RawEvents` that have a payload 2 value with this value are instant events. +const INSTANT_MARKER: u64 = 0xFFFF_FFFF_FFFF; +/// `RawEvents` that have a payload 2 value with this value are integer events. +const INTEGER_MARKER: u64 = INSTANT_MARKER - 1; + +/// The max value we can represent with the 48 bits available. +pub const MAX_SINGLE_VALUE: u64 = 0xFFFF_FFFF_FFFF; + +/// The max value we can represent with the 48 bits available. +/// The highest two values are reserved for the `INSTANT_MARKER` and `INTEGER_MARKER`. +pub const MAX_INTERVAL_VALUE: u64 = INTEGER_MARKER - 1; + +impl RawEvent { + #[inline] + pub fn new_interval( + event_kind: StringId, + event_id: EventId, + thread_id: u32, + start: u64, + end: u64, + ) -> Self { + assert!(start <= end); + assert!(end <= MAX_INTERVAL_VALUE); + + Self::pack_values(event_kind, event_id, thread_id, start, end) + } + + #[inline] + pub fn new_instant( + event_kind: StringId, + event_id: EventId, + thread_id: u32, + instant: u64, + ) -> Self { + assert!(instant <= MAX_SINGLE_VALUE); + Self::pack_values(event_kind, event_id, thread_id, instant, INSTANT_MARKER) + } + + #[inline] + pub fn new_integer( + event_kind: StringId, + event_id: EventId, + thread_id: u32, + value: u64, + ) -> Self { + assert!(value <= MAX_SINGLE_VALUE); + Self::pack_values(event_kind, event_id, thread_id, value, INTEGER_MARKER) + } + + #[inline] + fn pack_values( + event_kind: StringId, + event_id: EventId, + thread_id: u32, + value1: u64, + value2: u64, + ) -> Self { + let payload1_lower = value1 as u32; + let payload2_lower = value2 as u32; + + let value1_upper = (value1 >> 16) as u32 & 0xFFFF_0000; + let value2_upper = (value2 >> 32) as u32; + + let payloads_upper = value1_upper | value2_upper; + + Self { + event_kind, + event_id, + thread_id, + payload1_lower, + payload2_lower, + payloads_upper, + } + } + + /// The start value assuming self is an interval + #[inline] + pub fn start_value(&self) -> u64 { + self.payload1_lower as u64 | (((self.payloads_upper & 0xFFFF_0000) as u64) << 16) + } + + /// The end value assuming self is an interval + #[inline] + pub fn end_value(&self) -> u64 { + self.payload2_lower as u64 | (((self.payloads_upper & 0x0000_FFFF) as u64) << 32) + } + + /// The value assuming self is an interval or integer. + #[inline] + pub fn value(&self) -> u64 { + self.payload1_lower as u64 | (((self.payloads_upper & 0xFFFF_0000) as u64) << 16) + } + + #[inline] + pub fn is_instant(&self) -> bool { + self.end_value() == INSTANT_MARKER + } + + #[inline] + pub fn is_integer(&self) -> bool { + self.end_value() == INTEGER_MARKER + } + + #[inline] + pub fn serialize(&self, bytes: &mut [u8]) { + assert!(bytes.len() == std::mem::size_of::<RawEvent>()); + + #[cfg(target_endian = "little")] + { + let raw_event_bytes: &[u8] = unsafe { + std::slice::from_raw_parts( + self as *const _ as *const u8, + std::mem::size_of::<RawEvent>(), + ) + }; + + bytes.copy_from_slice(raw_event_bytes); + } + + #[cfg(target_endian = "big")] + { + // We always emit data as little endian, which we have to do + // manually on big endian targets. + bytes[0..4].copy_from_slice(&self.event_kind.as_u32().to_le_bytes()); + bytes[4..8].copy_from_slice(&self.event_id.as_u32().to_le_bytes()); + bytes[8..12].copy_from_slice(&self.thread_id.to_le_bytes()); + bytes[12..16].copy_from_slice(&self.payload1_lower.to_le_bytes()); + bytes[16..20].copy_from_slice(&self.payload2_lower.to_le_bytes()); + bytes[20..24].copy_from_slice(&self.payloads_upper.to_le_bytes()); + } + } + + #[inline] + pub fn deserialize(bytes: &[u8]) -> RawEvent { + assert!(bytes.len() == std::mem::size_of::<RawEvent>()); + + #[cfg(target_endian = "little")] + { + let mut raw_event = RawEvent::default(); + unsafe { + let raw_event = std::slice::from_raw_parts_mut( + &mut raw_event as *mut RawEvent as *mut u8, + std::mem::size_of::<RawEvent>(), + ); + raw_event.copy_from_slice(bytes); + }; + raw_event + } + + #[cfg(target_endian = "big")] + { + RawEvent { + event_kind: StringId::new(u32::from_le_bytes(bytes[0..4].try_into().unwrap())), + event_id: EventId::from_u32(u32::from_le_bytes(bytes[4..8].try_into().unwrap())), + thread_id: u32::from_le_bytes(bytes[8..12].try_into().unwrap()), + payload1_lower: u32::from_le_bytes(bytes[12..16].try_into().unwrap()), + payload2_lower: u32::from_le_bytes(bytes[16..20].try_into().unwrap()), + payloads_upper: u32::from_le_bytes(bytes[20..24].try_into().unwrap()), + } + } + } +} + +impl Default for RawEvent { + fn default() -> Self { + RawEvent { + event_kind: StringId::INVALID, + event_id: EventId::INVALID, + thread_id: 0, + payload1_lower: 0, + payload2_lower: 0, + payloads_upper: 0, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn raw_event_has_expected_size() { + // A test case to prevent accidental regressions of RawEvent's size. + assert_eq!(std::mem::size_of::<RawEvent>(), 24); + } + + #[test] + fn is_instant() { + assert!(RawEvent::new_instant(StringId::INVALID, EventId::INVALID, 987, 0,).is_instant()); + + assert!( + RawEvent::new_instant(StringId::INVALID, EventId::INVALID, 987, MAX_SINGLE_VALUE,) + .is_instant() + ); + + assert!(!RawEvent::new_interval( + StringId::INVALID, + EventId::INVALID, + 987, + 0, + MAX_INTERVAL_VALUE, + ) + .is_instant()); + } + + #[test] + fn is_integer() { + let integer = RawEvent::new_integer(StringId::INVALID, EventId::INVALID, 987, 0); + assert!(integer.is_integer()); + assert_eq!(integer.value(), 0); + + let integer = RawEvent::new_integer(StringId::INVALID, EventId::INVALID, 987, 8769); + assert!(integer.is_integer()); + assert_eq!(integer.value(), 8769); + + assert!( + RawEvent::new_integer(StringId::INVALID, EventId::INVALID, 987, MAX_SINGLE_VALUE,) + .is_integer() + ); + + assert!(!RawEvent::new_interval( + StringId::INVALID, + EventId::INVALID, + 987, + 0, + MAX_INTERVAL_VALUE, + ) + .is_integer()); + } + + #[test] + #[should_panic] + fn invalid_instant_count() { + let _ = RawEvent::new_instant( + StringId::INVALID, + EventId::INVALID, + 123, + // count too large + MAX_SINGLE_VALUE + 1, + ); + } + + #[test] + #[should_panic] + fn invalid_start_count() { + let _ = RawEvent::new_interval( + StringId::INVALID, + EventId::INVALID, + 123, + // start count too large + MAX_INTERVAL_VALUE + 1, + MAX_INTERVAL_VALUE + 1, + ); + } + + #[test] + #[should_panic] + fn invalid_end_count() { + let _ = RawEvent::new_interval( + StringId::INVALID, + EventId::INVALID, + 123, + 0, + // end count too large + MAX_INTERVAL_VALUE + 3, + ); + } + + #[test] + #[should_panic] + fn invalid_end_count2() { + let _ = RawEvent::new_interval(StringId::INVALID, EventId::INVALID, 123, 0, INTEGER_MARKER); + } + + #[test] + #[should_panic] + fn start_greater_than_end_count() { + let _ = RawEvent::new_interval( + StringId::INVALID, + EventId::INVALID, + 123, + // start count greater than end count + 1, + 0, + ); + } + + #[test] + fn start_equal_to_end_count() { + // This is allowed, make sure we don't panic + let _ = RawEvent::new_interval(StringId::INVALID, EventId::INVALID, 123, 1, 1); + } + + #[test] + fn interval_count_decoding() { + // Check the upper limits + let e = RawEvent::new_interval( + StringId::INVALID, + EventId::INVALID, + 1234, + MAX_INTERVAL_VALUE, + MAX_INTERVAL_VALUE, + ); + + assert_eq!(e.start_value(), MAX_INTERVAL_VALUE); + assert_eq!(e.end_value(), MAX_INTERVAL_VALUE); + + // Check the lower limits + let e = RawEvent::new_interval(StringId::INVALID, EventId::INVALID, 1234, 0, 0); + + assert_eq!(e.start_value(), 0); + assert_eq!(e.end_value(), 0); + + // Check that end does not bleed into start + let e = RawEvent::new_interval( + StringId::INVALID, + EventId::INVALID, + 1234, + 0, + MAX_INTERVAL_VALUE, + ); + + assert_eq!(e.start_value(), 0); + assert_eq!(e.end_value(), MAX_INTERVAL_VALUE); + + // Test some random values + let e = RawEvent::new_interval( + StringId::INVALID, + EventId::INVALID, + 1234, + 0x1234567890, + 0x1234567890A, + ); + + assert_eq!(e.start_value(), 0x1234567890); + assert_eq!(e.end_value(), 0x1234567890A); + } + + #[test] + fn instant_count_decoding() { + assert_eq!( + RawEvent::new_instant(StringId::INVALID, EventId::INVALID, 987, 0,).start_value(), + 0 + ); + + assert_eq!( + RawEvent::new_instant(StringId::INVALID, EventId::INVALID, 987, 42,).start_value(), + 42 + ); + + assert_eq!( + RawEvent::new_instant(StringId::INVALID, EventId::INVALID, 987, MAX_SINGLE_VALUE,) + .start_value(), + MAX_SINGLE_VALUE + ); + } + + #[test] + fn integer_decoding() { + assert_eq!( + RawEvent::new_integer(StringId::INVALID, EventId::INVALID, 987, 0,).start_value(), + 0 + ); + + assert_eq!( + RawEvent::new_integer(StringId::INVALID, EventId::INVALID, 987, 42,).start_value(), + 42 + ); + + assert_eq!( + RawEvent::new_integer(StringId::INVALID, EventId::INVALID, 987, MAX_SINGLE_VALUE,) + .start_value(), + MAX_SINGLE_VALUE + ); + } +} diff --git a/vendor/measureme/src/rustc.rs b/vendor/measureme/src/rustc.rs index 6552dbe6df..11986561fc 100644 --- a/vendor/measureme/src/rustc.rs +++ b/vendor/measureme/src/rustc.rs @@ -1,11 +1,15 @@ -//! This module contains functionality specific to to the measureme integration with rustc - -pub const QUERY_EVENT_KIND: &str = "Query"; - -pub const GENERIC_ACTIVITY_EVENT_KIND: &str = "GenericActivity"; - -pub const INCREMENTAL_LOAD_RESULT_EVENT_KIND: &str = "IncrementalLoadResult"; - -pub const QUERY_BLOCKED_EVENT_KIND: &str = "QueryBlocked"; - -pub const QUERY_CACHE_HIT_EVENT_KIND: &str = "QueryCacheHit"; +//! This module contains functionality specific to to the measureme integration with rustc + +pub const QUERY_EVENT_KIND: &str = "Query"; + +pub const GENERIC_ACTIVITY_EVENT_KIND: &str = "GenericActivity"; + +pub const INCREMENTAL_LOAD_RESULT_EVENT_KIND: &str = "IncrementalLoadResult"; + +pub const INCREMENTAL_RESULT_HASHING_EVENT_KIND: &str = "IncrementalResultHashing"; + +pub const QUERY_BLOCKED_EVENT_KIND: &str = "QueryBlocked"; + +pub const QUERY_CACHE_HIT_EVENT_KIND: &str = "QueryCacheHit"; + +pub const ARTIFACT_SIZE_EVENT_KIND: &str = "ArtifactSize"; diff --git a/vendor/measureme/src/serialization.rs b/vendor/measureme/src/serialization.rs index 6dcc51d39b..28bfd96c03 100644 --- a/vendor/measureme/src/serialization.rs +++ b/vendor/measureme/src/serialization.rs @@ -1,498 +1,498 @@ -/// This module implements the "container" file format that `measureme` uses for -/// storing things on disk. The format supports storing three independent -/// streams of data: one for events, one for string data, and one for string -/// index data (in theory it could support an arbitrary number of separate -/// streams but three is all we need). The data of each stream is split into -/// "pages", where each page has a small header designating what kind of -/// data it is (i.e. event, string data, or string index), and the length of -/// the page. -/// -/// Pages of different kinds can be arbitrarily interleaved. The headers allow -/// for reconstructing each of the streams later on. An example file might thus -/// look like this: -/// -/// ```ignore -/// | file header | page (events) | page (string data) | page (events) | page (string index) | -/// ``` -/// -/// The exact encoding of a page is: -/// -/// | byte slice | contents | -/// |-------------------------|-----------------------------------------| -/// | &[0 .. 1] | page tag | -/// | &[1 .. 5] | page size as little endian u32 | -/// | &[5 .. (5 + page_size)] | page contents (exactly page_size bytes) | -/// -/// A page is immediately followed by the next page, without any padding. -use parking_lot::Mutex; -use rustc_hash::FxHashMap; -use std::cmp::min; -use std::convert::TryInto; -use std::error::Error; -use std::fmt::Debug; -use std::fs; -use std::io::Write; -use std::sync::Arc; - -const MAX_PAGE_SIZE: usize = 256 * 1024; - -/// The number of bytes we consider enough to warrant their own page when -/// deciding whether to flush a partially full buffer. Actual pages may need -/// to be smaller, e.g. when writing the tail of the data stream. -const MIN_PAGE_SIZE: usize = MAX_PAGE_SIZE / 2; - -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -#[repr(u8)] -pub enum PageTag { - Events = 0, - StringData = 1, - StringIndex = 2, -} - -impl std::convert::TryFrom<u8> for PageTag { - type Error = String; - - fn try_from(value: u8) -> Result<Self, Self::Error> { - match value { - 0 => Ok(PageTag::Events), - 1 => Ok(PageTag::StringData), - 2 => Ok(PageTag::StringIndex), - _ => Err(format!("Could not convert byte `{}` to PageTag.", value)), - } - } -} - -/// An address within a data stream. Each data stream has its own address space, -/// i.e. the first piece of data written to the events stream will have -/// `Addr(0)` and the first piece of data written to the string data stream -/// will *also* have `Addr(0)`. -// -// TODO: Evaluate if it makes sense to add a type tag to `Addr` in order to -// prevent accidental use of `Addr` values with the wrong address space. -#[derive(Clone, Copy, Eq, PartialEq, Debug)] -pub struct Addr(pub u32); - -impl Addr { - pub fn as_usize(self) -> usize { - self.0 as usize - } -} - -#[derive(Debug)] -pub struct SerializationSink { - shared_state: SharedState, - data: Mutex<SerializationSinkInner>, - page_tag: PageTag, -} - -pub struct SerializationSinkBuilder(SharedState); - -impl SerializationSinkBuilder { - pub fn new_from_file(file: fs::File) -> Result<Self, Box<dyn Error + Send + Sync>> { - Ok(Self(SharedState(Arc::new(Mutex::new( - BackingStorage::File(file), - ))))) - } - - pub fn new_in_memory() -> SerializationSinkBuilder { - Self(SharedState(Arc::new(Mutex::new(BackingStorage::Memory( - Vec::new(), - ))))) - } - - pub fn new_sink(&self, page_tag: PageTag) -> SerializationSink { - SerializationSink { - data: Mutex::new(SerializationSinkInner { - buffer: Vec::with_capacity(MAX_PAGE_SIZE), - addr: 0, - }), - shared_state: self.0.clone(), - page_tag, - } - } -} - -/// The `BackingStorage` is what the data gets written to. Usually that is a -/// file but for testing purposes it can also be an in-memory vec of bytes. -#[derive(Debug)] -enum BackingStorage { - File(fs::File), - Memory(Vec<u8>), -} - -impl Write for BackingStorage { - #[inline] - fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> { - match *self { - BackingStorage::File(ref mut file) => file.write(buf), - BackingStorage::Memory(ref mut vec) => vec.write(buf), - } - } - - fn flush(&mut self) -> std::io::Result<()> { - match *self { - BackingStorage::File(ref mut file) => file.flush(), - BackingStorage::Memory(_) => { - // Nothing to do - Ok(()) - } - } - } -} - -/// This struct allows to treat `SerializationSink` as `std::io::Write`. -pub struct StdWriteAdapter<'a>(&'a SerializationSink); - -impl<'a> Write for StdWriteAdapter<'a> { - fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> { - self.0.write_bytes_atomic(buf); - Ok(buf.len()) - } - - fn flush(&mut self) -> std::io::Result<()> { - let mut data = self.0.data.lock(); - let SerializationSinkInner { - ref mut buffer, - addr: _, - } = *data; - - // First flush the local buffer. - self.0.flush(buffer); - - // Then flush the backing store. - self.0.shared_state.0.lock().flush()?; - - Ok(()) - } -} - -#[derive(Debug)] -struct SerializationSinkInner { - buffer: Vec<u8>, - addr: u32, -} - -/// This state is shared between all `SerializationSink`s writing to the same -/// backing storage (e.g. the same file). -#[derive(Clone, Debug)] -struct SharedState(Arc<Mutex<BackingStorage>>); - -impl SharedState { - /// Copies out the contents of all pages with the given tag and - /// concatenates them into a single byte vec. This method is only meant to - /// be used for testing and will panic if the underlying backing storage is - /// a file instead of in memory. - fn copy_bytes_with_page_tag(&self, page_tag: PageTag) -> Vec<u8> { - let data = self.0.lock(); - let data = match *data { - BackingStorage::File(_) => panic!(), - BackingStorage::Memory(ref data) => data, - }; - - split_streams(data).remove(&page_tag).unwrap_or(Vec::new()) - } -} - -/// This function reconstructs the individual data streams from their paged -/// version. -/// -/// For example, if `E` denotes the page header of an events page, `S` denotes -/// the header of a string data page, and lower case letters denote page -/// contents then a paged stream could look like: -/// -/// ```ignore -/// s = Eabcd_Sopq_Eef_Eghi_Srst -/// ``` -/// -/// and `split_streams` would result in the following set of streams: -/// -/// ```ignore -/// split_streams(s) = { -/// events: [abcdefghi], -/// string_data: [opqrst], -/// } -/// ``` -pub fn split_streams(paged_data: &[u8]) -> FxHashMap<PageTag, Vec<u8>> { - let mut result: FxHashMap<PageTag, Vec<u8>> = FxHashMap::default(); - - let mut pos = 0; - while pos < paged_data.len() { - let tag = TryInto::try_into(paged_data[pos]).unwrap(); - let page_size = - u32::from_le_bytes(paged_data[pos + 1..pos + 5].try_into().unwrap()) as usize; - - assert!(page_size > 0); - - result - .entry(tag) - .or_default() - .extend_from_slice(&paged_data[pos + 5..pos + 5 + page_size]); - - pos += page_size + 5; - } - - result -} - -impl SerializationSink { - /// Writes `bytes` as a single page to the shared backing storage. The - /// method will first write the page header (consisting of the page tag and - /// the number of bytes in the page) and then the page contents - /// (i.e. `bytes`). - fn write_page(&self, bytes: &[u8]) { - if bytes.len() > 0 { - // We explicitly don't assert `bytes.len() >= MIN_PAGE_SIZE` because - // `MIN_PAGE_SIZE` is just a recommendation and the last page will - // often be smaller than that. - assert!(bytes.len() <= MAX_PAGE_SIZE); - - let mut file = self.shared_state.0.lock(); - - file.write_all(&[self.page_tag as u8]).unwrap(); - - let page_size: [u8; 4] = (bytes.len() as u32).to_le_bytes(); - file.write_all(&page_size).unwrap(); - file.write_all(&bytes[..]).unwrap(); - } - } - - /// Flushes `buffer` by writing its contents as a new page to the backing - /// storage and then clearing it. - fn flush(&self, buffer: &mut Vec<u8>) { - self.write_page(&buffer[..]); - buffer.clear(); - } - - /// Creates a copy of all data written so far. This method is meant to be - /// used for writing unit tests. It will panic if the underlying - /// `BackingStorage` is a file. - pub fn into_bytes(mut self) -> Vec<u8> { - // Swap out the contains of `self` with something that can safely be - // dropped without side effects. - let mut data = Mutex::new(SerializationSinkInner { - buffer: Vec::new(), - addr: 0, - }); - std::mem::swap(&mut self.data, &mut data); - - // Extract the data from the mutex. - let SerializationSinkInner { - ref mut buffer, - addr: _, - } = data.into_inner(); - - // Make sure we write the current contents of the buffer to the - // backing storage before proceeding. - self.flush(buffer); - - self.shared_state.copy_bytes_with_page_tag(self.page_tag) - } - - /// Atomically writes `num_bytes` of data to this `SerializationSink`. - /// Atomic means the data is guaranteed to be written as a contiguous range - /// of bytes. - /// - /// The buffer provided to the `write` callback is guaranteed to be of size - /// `num_bytes` and `write` is supposed to completely fill it with the data - /// to be written. - /// - /// The return value is the address of the data written and can be used to - /// refer to the data later on. - pub fn write_atomic<W>(&self, num_bytes: usize, write: W) -> Addr - where - W: FnOnce(&mut [u8]), - { - if num_bytes > MAX_PAGE_SIZE { - let mut bytes = vec![0u8; num_bytes]; - write(&mut bytes[..]); - return self.write_bytes_atomic(&bytes[..]); - } - - let mut data = self.data.lock(); - let SerializationSinkInner { - ref mut buffer, - ref mut addr, - } = *data; - - if buffer.len() + num_bytes > MAX_PAGE_SIZE { - self.flush(buffer); - assert!(buffer.is_empty()); - } - - let curr_addr = *addr; - - let buf_start = buffer.len(); - let buf_end = buf_start + num_bytes; - buffer.resize(buf_end, 0u8); - write(&mut buffer[buf_start..buf_end]); - - *addr += num_bytes as u32; - - Addr(curr_addr) - } - - /// Atomically writes the data in `bytes` to this `SerializationSink`. - /// Atomic means the data is guaranteed to be written as a contiguous range - /// of bytes. - /// - /// This method may perform better than `write_atomic` because it may be - /// able to skip the sink's internal buffer. Use this method if the data to - /// be written is already available as a `&[u8]`. - /// - /// The return value is the address of the data written and can be used to - /// refer to the data later on. - pub fn write_bytes_atomic(&self, bytes: &[u8]) -> Addr { - // For "small" data we go to the buffered version immediately. - if bytes.len() <= 128 { - return self.write_atomic(bytes.len(), |sink| { - sink.copy_from_slice(bytes); - }); - } - - let mut data = self.data.lock(); - let SerializationSinkInner { - ref mut buffer, - ref mut addr, - } = *data; - - let curr_addr = Addr(*addr); - *addr += bytes.len() as u32; - - let mut bytes_left = bytes; - - // Do we have too little data in the buffer? If so, fill up the buffer - // to the minimum page size. - if buffer.len() < MIN_PAGE_SIZE { - let num_bytes_to_take = min(MIN_PAGE_SIZE - buffer.len(), bytes_left.len()); - buffer.extend_from_slice(&bytes_left[..num_bytes_to_take]); - bytes_left = &bytes_left[num_bytes_to_take..]; - } - - if bytes_left.is_empty() { - return curr_addr; - } - - // Make sure we flush the buffer before writing out any other pages. - self.flush(buffer); - - for chunk in bytes_left.chunks(MAX_PAGE_SIZE) { - if chunk.len() == MAX_PAGE_SIZE { - // This chunk has the maximum size. It might or might not be the - // last one. In either case we want to write it to disk - // immediately because there is no reason to copy it to the - // buffer first. - self.write_page(chunk); - } else { - // This chunk is less than the chunk size that we requested, so - // it must be the last one. If it is big enough to warrant its - // own page, we write it to disk immediately. Otherwise, we copy - // it to the buffer. - if chunk.len() >= MIN_PAGE_SIZE { - self.write_page(chunk); - } else { - debug_assert!(buffer.is_empty()); - buffer.extend_from_slice(chunk); - } - } - } - - curr_addr - } - - pub fn as_std_write<'a>(&'a self) -> impl Write + 'a { - StdWriteAdapter(self) - } -} - -impl Drop for SerializationSink { - fn drop(&mut self) { - let mut data = self.data.lock(); - let SerializationSinkInner { - ref mut buffer, - addr: _, - } = *data; - - self.flush(buffer); - } -} - -#[cfg(test)] -mod tests { - use super::*; - - // This function writes `chunk_count` byte-slices of size `chunk_size` to - // three `SerializationSinks` that all map to the same underlying stream, - // so we get interleaved pages with different tags. - // It then extracts the data out again and asserts that it is the same as - // has been written. - fn test_roundtrip<W>(chunk_size: usize, chunk_count: usize, write: W) - where - W: Fn(&SerializationSink, &[u8]) -> Addr, - { - let sink_builder = SerializationSinkBuilder::new_in_memory(); - let tags = [PageTag::Events, PageTag::StringData, PageTag::StringIndex]; - let expected_chunk: Vec<u8> = (0..chunk_size).map(|x| (x % 239) as u8).collect(); - - { - let sinks: Vec<SerializationSink> = - tags.iter().map(|&tag| sink_builder.new_sink(tag)).collect(); - - for chunk_index in 0..chunk_count { - let expected_addr = Addr((chunk_index * chunk_size) as u32); - for sink in sinks.iter() { - assert_eq!(write(sink, &expected_chunk[..]), expected_addr); - } - } - } - - let streams: Vec<Vec<u8>> = tags - .iter() - .map(|&tag| sink_builder.0.copy_bytes_with_page_tag(tag)) - .collect(); - - for stream in streams { - for chunk in stream.chunks(chunk_size) { - assert_eq!(chunk, expected_chunk); - } - } - } - - fn write_closure(sink: &SerializationSink, bytes: &[u8]) -> Addr { - sink.write_atomic(bytes.len(), |dest| dest.copy_from_slice(bytes)) - } - - fn write_slice(sink: &SerializationSink, bytes: &[u8]) -> Addr { - sink.write_bytes_atomic(bytes) - } - - // Creates two roundtrip tests, one using `SerializationSink::write_atomic` - // and one using `SerializationSink::write_bytes_atomic`. - macro_rules! mk_roundtrip_test { - ($name:ident, $chunk_size:expr, $chunk_count:expr) => { - mod $name { - use super::*; - - #[test] - fn write_atomic() { - test_roundtrip($chunk_size, $chunk_count, write_closure); - } - - #[test] - fn write_bytes_atomic() { - test_roundtrip($chunk_size, $chunk_count, write_slice); - } - } - }; - } - - mk_roundtrip_test!(small_data, 10, (90 * MAX_PAGE_SIZE) / 100); - mk_roundtrip_test!(huge_data, MAX_PAGE_SIZE * 10, 5); - - mk_roundtrip_test!(exactly_max_page_size, MAX_PAGE_SIZE, 10); - mk_roundtrip_test!(max_page_size_plus_one, MAX_PAGE_SIZE + 1, 10); - mk_roundtrip_test!(max_page_size_minus_one, MAX_PAGE_SIZE - 1, 10); - - mk_roundtrip_test!(exactly_min_page_size, MIN_PAGE_SIZE, 10); - mk_roundtrip_test!(min_page_size_plus_one, MIN_PAGE_SIZE + 1, 10); - mk_roundtrip_test!(min_page_size_minus_one, MIN_PAGE_SIZE - 1, 10); -} +/// This module implements the "container" file format that `measureme` uses for +/// storing things on disk. The format supports storing three independent +/// streams of data: one for events, one for string data, and one for string +/// index data (in theory it could support an arbitrary number of separate +/// streams but three is all we need). The data of each stream is split into +/// "pages", where each page has a small header designating what kind of +/// data it is (i.e. event, string data, or string index), and the length of +/// the page. +/// +/// Pages of different kinds can be arbitrarily interleaved. The headers allow +/// for reconstructing each of the streams later on. An example file might thus +/// look like this: +/// +/// ```ignore +/// | file header | page (events) | page (string data) | page (events) | page (string index) | +/// ``` +/// +/// The exact encoding of a page is: +/// +/// | byte slice | contents | +/// |-------------------------|-----------------------------------------| +/// | &[0 .. 1] | page tag | +/// | &[1 .. 5] | page size as little endian u32 | +/// | &[5 .. (5 + page_size)] | page contents (exactly page_size bytes) | +/// +/// A page is immediately followed by the next page, without any padding. +use parking_lot::Mutex; +use rustc_hash::FxHashMap; +use std::cmp::min; +use std::convert::TryInto; +use std::error::Error; +use std::fmt::Debug; +use std::fs; +use std::io::Write; +use std::sync::Arc; + +const MAX_PAGE_SIZE: usize = 256 * 1024; + +/// The number of bytes we consider enough to warrant their own page when +/// deciding whether to flush a partially full buffer. Actual pages may need +/// to be smaller, e.g. when writing the tail of the data stream. +const MIN_PAGE_SIZE: usize = MAX_PAGE_SIZE / 2; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[repr(u8)] +pub enum PageTag { + Events = 0, + StringData = 1, + StringIndex = 2, +} + +impl std::convert::TryFrom<u8> for PageTag { + type Error = String; + + fn try_from(value: u8) -> Result<Self, Self::Error> { + match value { + 0 => Ok(PageTag::Events), + 1 => Ok(PageTag::StringData), + 2 => Ok(PageTag::StringIndex), + _ => Err(format!("Could not convert byte `{}` to PageTag.", value)), + } + } +} + +/// An address within a data stream. Each data stream has its own address space, +/// i.e. the first piece of data written to the events stream will have +/// `Addr(0)` and the first piece of data written to the string data stream +/// will *also* have `Addr(0)`. +// +// TODO: Evaluate if it makes sense to add a type tag to `Addr` in order to +// prevent accidental use of `Addr` values with the wrong address space. +#[derive(Clone, Copy, Eq, PartialEq, Debug)] +pub struct Addr(pub u32); + +impl Addr { + pub fn as_usize(self) -> usize { + self.0 as usize + } +} + +#[derive(Debug)] +pub struct SerializationSink { + shared_state: SharedState, + data: Mutex<SerializationSinkInner>, + page_tag: PageTag, +} + +pub struct SerializationSinkBuilder(SharedState); + +impl SerializationSinkBuilder { + pub fn new_from_file(file: fs::File) -> Result<Self, Box<dyn Error + Send + Sync>> { + Ok(Self(SharedState(Arc::new(Mutex::new( + BackingStorage::File(file), + ))))) + } + + pub fn new_in_memory() -> SerializationSinkBuilder { + Self(SharedState(Arc::new(Mutex::new(BackingStorage::Memory( + Vec::new(), + ))))) + } + + pub fn new_sink(&self, page_tag: PageTag) -> SerializationSink { + SerializationSink { + data: Mutex::new(SerializationSinkInner { + buffer: Vec::with_capacity(MAX_PAGE_SIZE), + addr: 0, + }), + shared_state: self.0.clone(), + page_tag, + } + } +} + +/// The `BackingStorage` is what the data gets written to. Usually that is a +/// file but for testing purposes it can also be an in-memory vec of bytes. +#[derive(Debug)] +enum BackingStorage { + File(fs::File), + Memory(Vec<u8>), +} + +impl Write for BackingStorage { + #[inline] + fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> { + match *self { + BackingStorage::File(ref mut file) => file.write(buf), + BackingStorage::Memory(ref mut vec) => vec.write(buf), + } + } + + fn flush(&mut self) -> std::io::Result<()> { + match *self { + BackingStorage::File(ref mut file) => file.flush(), + BackingStorage::Memory(_) => { + // Nothing to do + Ok(()) + } + } + } +} + +/// This struct allows to treat `SerializationSink` as `std::io::Write`. +pub struct StdWriteAdapter<'a>(&'a SerializationSink); + +impl<'a> Write for StdWriteAdapter<'a> { + fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> { + self.0.write_bytes_atomic(buf); + Ok(buf.len()) + } + + fn flush(&mut self) -> std::io::Result<()> { + let mut data = self.0.data.lock(); + let SerializationSinkInner { + ref mut buffer, + addr: _, + } = *data; + + // First flush the local buffer. + self.0.flush(buffer); + + // Then flush the backing store. + self.0.shared_state.0.lock().flush()?; + + Ok(()) + } +} + +#[derive(Debug)] +struct SerializationSinkInner { + buffer: Vec<u8>, + addr: u32, +} + +/// This state is shared between all `SerializationSink`s writing to the same +/// backing storage (e.g. the same file). +#[derive(Clone, Debug)] +struct SharedState(Arc<Mutex<BackingStorage>>); + +impl SharedState { + /// Copies out the contents of all pages with the given tag and + /// concatenates them into a single byte vec. This method is only meant to + /// be used for testing and will panic if the underlying backing storage is + /// a file instead of in memory. + fn copy_bytes_with_page_tag(&self, page_tag: PageTag) -> Vec<u8> { + let data = self.0.lock(); + let data = match *data { + BackingStorage::File(_) => panic!(), + BackingStorage::Memory(ref data) => data, + }; + + split_streams(data).remove(&page_tag).unwrap_or(Vec::new()) + } +} + +/// This function reconstructs the individual data streams from their paged +/// version. +/// +/// For example, if `E` denotes the page header of an events page, `S` denotes +/// the header of a string data page, and lower case letters denote page +/// contents then a paged stream could look like: +/// +/// ```ignore +/// s = Eabcd_Sopq_Eef_Eghi_Srst +/// ``` +/// +/// and `split_streams` would result in the following set of streams: +/// +/// ```ignore +/// split_streams(s) = { +/// events: [abcdefghi], +/// string_data: [opqrst], +/// } +/// ``` +pub fn split_streams(paged_data: &[u8]) -> FxHashMap<PageTag, Vec<u8>> { + let mut result: FxHashMap<PageTag, Vec<u8>> = FxHashMap::default(); + + let mut pos = 0; + while pos < paged_data.len() { + let tag = TryInto::try_into(paged_data[pos]).unwrap(); + let page_size = + u32::from_le_bytes(paged_data[pos + 1..pos + 5].try_into().unwrap()) as usize; + + assert!(page_size > 0); + + result + .entry(tag) + .or_default() + .extend_from_slice(&paged_data[pos + 5..pos + 5 + page_size]); + + pos += page_size + 5; + } + + result +} + +impl SerializationSink { + /// Writes `bytes` as a single page to the shared backing storage. The + /// method will first write the page header (consisting of the page tag and + /// the number of bytes in the page) and then the page contents + /// (i.e. `bytes`). + fn write_page(&self, bytes: &[u8]) { + if bytes.len() > 0 { + // We explicitly don't assert `bytes.len() >= MIN_PAGE_SIZE` because + // `MIN_PAGE_SIZE` is just a recommendation and the last page will + // often be smaller than that. + assert!(bytes.len() <= MAX_PAGE_SIZE); + + let mut file = self.shared_state.0.lock(); + + file.write_all(&[self.page_tag as u8]).unwrap(); + + let page_size: [u8; 4] = (bytes.len() as u32).to_le_bytes(); + file.write_all(&page_size).unwrap(); + file.write_all(&bytes[..]).unwrap(); + } + } + + /// Flushes `buffer` by writing its contents as a new page to the backing + /// storage and then clearing it. + fn flush(&self, buffer: &mut Vec<u8>) { + self.write_page(&buffer[..]); + buffer.clear(); + } + + /// Creates a copy of all data written so far. This method is meant to be + /// used for writing unit tests. It will panic if the underlying + /// `BackingStorage` is a file. + pub fn into_bytes(mut self) -> Vec<u8> { + // Swap out the contains of `self` with something that can safely be + // dropped without side effects. + let mut data = Mutex::new(SerializationSinkInner { + buffer: Vec::new(), + addr: 0, + }); + std::mem::swap(&mut self.data, &mut data); + + // Extract the data from the mutex. + let SerializationSinkInner { + ref mut buffer, + addr: _, + } = data.into_inner(); + + // Make sure we write the current contents of the buffer to the + // backing storage before proceeding. + self.flush(buffer); + + self.shared_state.copy_bytes_with_page_tag(self.page_tag) + } + + /// Atomically writes `num_bytes` of data to this `SerializationSink`. + /// Atomic means the data is guaranteed to be written as a contiguous range + /// of bytes. + /// + /// The buffer provided to the `write` callback is guaranteed to be of size + /// `num_bytes` and `write` is supposed to completely fill it with the data + /// to be written. + /// + /// The return value is the address of the data written and can be used to + /// refer to the data later on. + pub fn write_atomic<W>(&self, num_bytes: usize, write: W) -> Addr + where + W: FnOnce(&mut [u8]), + { + if num_bytes > MAX_PAGE_SIZE { + let mut bytes = vec![0u8; num_bytes]; + write(&mut bytes[..]); + return self.write_bytes_atomic(&bytes[..]); + } + + let mut data = self.data.lock(); + let SerializationSinkInner { + ref mut buffer, + ref mut addr, + } = *data; + + if buffer.len() + num_bytes > MAX_PAGE_SIZE { + self.flush(buffer); + assert!(buffer.is_empty()); + } + + let curr_addr = *addr; + + let buf_start = buffer.len(); + let buf_end = buf_start + num_bytes; + buffer.resize(buf_end, 0u8); + write(&mut buffer[buf_start..buf_end]); + + *addr += num_bytes as u32; + + Addr(curr_addr) + } + + /// Atomically writes the data in `bytes` to this `SerializationSink`. + /// Atomic means the data is guaranteed to be written as a contiguous range + /// of bytes. + /// + /// This method may perform better than `write_atomic` because it may be + /// able to skip the sink's internal buffer. Use this method if the data to + /// be written is already available as a `&[u8]`. + /// + /// The return value is the address of the data written and can be used to + /// refer to the data later on. + pub fn write_bytes_atomic(&self, bytes: &[u8]) -> Addr { + // For "small" data we go to the buffered version immediately. + if bytes.len() <= 128 { + return self.write_atomic(bytes.len(), |sink| { + sink.copy_from_slice(bytes); + }); + } + + let mut data = self.data.lock(); + let SerializationSinkInner { + ref mut buffer, + ref mut addr, + } = *data; + + let curr_addr = Addr(*addr); + *addr += bytes.len() as u32; + + let mut bytes_left = bytes; + + // Do we have too little data in the buffer? If so, fill up the buffer + // to the minimum page size. + if buffer.len() < MIN_PAGE_SIZE { + let num_bytes_to_take = min(MIN_PAGE_SIZE - buffer.len(), bytes_left.len()); + buffer.extend_from_slice(&bytes_left[..num_bytes_to_take]); + bytes_left = &bytes_left[num_bytes_to_take..]; + } + + if bytes_left.is_empty() { + return curr_addr; + } + + // Make sure we flush the buffer before writing out any other pages. + self.flush(buffer); + + for chunk in bytes_left.chunks(MAX_PAGE_SIZE) { + if chunk.len() == MAX_PAGE_SIZE { + // This chunk has the maximum size. It might or might not be the + // last one. In either case we want to write it to disk + // immediately because there is no reason to copy it to the + // buffer first. + self.write_page(chunk); + } else { + // This chunk is less than the chunk size that we requested, so + // it must be the last one. If it is big enough to warrant its + // own page, we write it to disk immediately. Otherwise, we copy + // it to the buffer. + if chunk.len() >= MIN_PAGE_SIZE { + self.write_page(chunk); + } else { + debug_assert!(buffer.is_empty()); + buffer.extend_from_slice(chunk); + } + } + } + + curr_addr + } + + pub fn as_std_write<'a>(&'a self) -> impl Write + 'a { + StdWriteAdapter(self) + } +} + +impl Drop for SerializationSink { + fn drop(&mut self) { + let mut data = self.data.lock(); + let SerializationSinkInner { + ref mut buffer, + addr: _, + } = *data; + + self.flush(buffer); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + // This function writes `chunk_count` byte-slices of size `chunk_size` to + // three `SerializationSinks` that all map to the same underlying stream, + // so we get interleaved pages with different tags. + // It then extracts the data out again and asserts that it is the same as + // has been written. + fn test_roundtrip<W>(chunk_size: usize, chunk_count: usize, write: W) + where + W: Fn(&SerializationSink, &[u8]) -> Addr, + { + let sink_builder = SerializationSinkBuilder::new_in_memory(); + let tags = [PageTag::Events, PageTag::StringData, PageTag::StringIndex]; + let expected_chunk: Vec<u8> = (0..chunk_size).map(|x| (x % 239) as u8).collect(); + + { + let sinks: Vec<SerializationSink> = + tags.iter().map(|&tag| sink_builder.new_sink(tag)).collect(); + + for chunk_index in 0..chunk_count { + let expected_addr = Addr((chunk_index * chunk_size) as u32); + for sink in sinks.iter() { + assert_eq!(write(sink, &expected_chunk[..]), expected_addr); + } + } + } + + let streams: Vec<Vec<u8>> = tags + .iter() + .map(|&tag| sink_builder.0.copy_bytes_with_page_tag(tag)) + .collect(); + + for stream in streams { + for chunk in stream.chunks(chunk_size) { + assert_eq!(chunk, expected_chunk); + } + } + } + + fn write_closure(sink: &SerializationSink, bytes: &[u8]) -> Addr { + sink.write_atomic(bytes.len(), |dest| dest.copy_from_slice(bytes)) + } + + fn write_slice(sink: &SerializationSink, bytes: &[u8]) -> Addr { + sink.write_bytes_atomic(bytes) + } + + // Creates two roundtrip tests, one using `SerializationSink::write_atomic` + // and one using `SerializationSink::write_bytes_atomic`. + macro_rules! mk_roundtrip_test { + ($name:ident, $chunk_size:expr, $chunk_count:expr) => { + mod $name { + use super::*; + + #[test] + fn write_atomic() { + test_roundtrip($chunk_size, $chunk_count, write_closure); + } + + #[test] + fn write_bytes_atomic() { + test_roundtrip($chunk_size, $chunk_count, write_slice); + } + } + }; + } + + mk_roundtrip_test!(small_data, 10, (90 * MAX_PAGE_SIZE) / 100); + mk_roundtrip_test!(huge_data, MAX_PAGE_SIZE * 10, 5); + + mk_roundtrip_test!(exactly_max_page_size, MAX_PAGE_SIZE, 10); + mk_roundtrip_test!(max_page_size_plus_one, MAX_PAGE_SIZE + 1, 10); + mk_roundtrip_test!(max_page_size_minus_one, MAX_PAGE_SIZE - 1, 10); + + mk_roundtrip_test!(exactly_min_page_size, MIN_PAGE_SIZE, 10); + mk_roundtrip_test!(min_page_size_plus_one, MIN_PAGE_SIZE + 1, 10); + mk_roundtrip_test!(min_page_size_minus_one, MIN_PAGE_SIZE - 1, 10); +} diff --git a/vendor/measureme/src/stringtable.rs b/vendor/measureme/src/stringtable.rs index 4c88f46fb2..a56bbcbfcd 100644 --- a/vendor/measureme/src/stringtable.rs +++ b/vendor/measureme/src/stringtable.rs @@ -1,328 +1,328 @@ -//! A string table implementation with a tree-like encoding. -//! -//! Each entry in the table represents a string and is encoded as a list of -//! components where each component can either be -//! -//! 1. a string _value_ that contains actual UTF-8 string content, -//! 2. a string _ID_ that contains a reference to another entry, or -//! 3. a terminator tag which marks the end of a component list. -//! -//! The string _content_ of an entry is defined as the concatenation of the -//! content of its components. The content of a string value is its actual -//! UTF-8 bytes. The content of a string ID is the contents of the entry -//! it references. -//! -//! The byte-level encoding of component lists uses the structure of UTF-8 in -//! order to save space: -//! -//! - A valid UTF-8 codepoint never starts with the byte `0xFE`. We make use -//! of this fact by letting all string ID components start with this `0xFE` -//! prefix. Thus when we parse the contents of a value we know to stop if -//! we encounter this byte. -//! -//! - A valid UTF-8 string cannot contain the `0xFF` byte. Thus we can safely -//! use `0xFF` as our component list terminator. -//! -//! The sample composite string ["abc", ID(42), "def", TERMINATOR] would thus be -//! encoded as: -//! -//! ```ignore -//! ['a', 'b' , 'c', 254, 42, 0, 0, 0, 'd', 'e', 'f', 255] -//! ^^^^^^^^^^^^^^^^ ^^^ -//! string ID with 0xFE prefix terminator (0xFF) -//! ``` -//! -//! As you can see string IDs are encoded in little endian format. -//! -//! ---------------------------------------------------------------------------- -//! -//! Each string in the table is referred to via a `StringId`. `StringId`s may -//! be generated in two ways: -//! -//! 1. Calling `StringTableBuilder::alloc()` which returns the `StringId` for -//! the allocated string. -//! 2. Calling `StringId::new_virtual()` to create a "virtual" `StringId` that -//! later can be mapped to an actual string via -//! `StringTableBuilder::map_virtual_to_concrete_string()`. -//! -//! String IDs allow you to deduplicate strings by allocating a string -//! once and then referring to it by id over and over. This is a useful trick -//! for strings which are recorded many times and it can significantly reduce -//! the size of profile trace files. -//! -//! `StringId`s are partitioned according to type: -//! -//! > [0 .. MAX_VIRTUAL_STRING_ID, METADATA_STRING_ID, .. ] -//! -//! From `0` to `MAX_VIRTUAL_STRING_ID` are the allowed values for virtual strings. -//! After `MAX_VIRTUAL_STRING_ID`, there is one string id (`METADATA_STRING_ID`) -//! which is used internally by `measureme` to record additional metadata about -//! the profiling session. After `METADATA_STRING_ID` are all other `StringId` -//! values. - -use crate::file_header::{ - write_file_header, FILE_MAGIC_STRINGTABLE_DATA, FILE_MAGIC_STRINGTABLE_INDEX, -}; -use crate::serialization::Addr; -use crate::serialization::SerializationSink; -use std::{error::Error, sync::Arc}; - -/// A `StringId` is used to identify a string in the `StringTable`. It is -/// either a regular `StringId`, meaning that it contains the absolute address -/// of a string within the string table data. Or it is "virtual", which means -/// that the address it points to is resolved via the string table index data, -/// that maps virtual `StringId`s to addresses. -#[derive(Clone, Copy, Eq, PartialEq, Debug, Hash)] -#[repr(C)] -pub struct StringId(u32); - -impl StringId { - pub const INVALID: StringId = StringId(INVALID_STRING_ID); - - #[inline] - pub fn new(id: u32) -> StringId { - StringId(id) - } - - #[inline] - pub fn new_virtual(id: u32) -> StringId { - assert!(id <= MAX_USER_VIRTUAL_STRING_ID); - StringId(id) - } - - #[inline] - pub fn is_virtual(self) -> bool { - self.0 <= METADATA_STRING_ID - } - - #[inline] - pub fn as_u32(self) -> u32 { - self.0 - } - - #[inline] - pub fn from_addr(addr: Addr) -> StringId { - let id = addr.0.checked_add(FIRST_REGULAR_STRING_ID).unwrap(); - StringId::new(id) - } - - #[inline] - pub fn to_addr(self) -> Addr { - Addr(self.0.checked_sub(FIRST_REGULAR_STRING_ID).unwrap()) - } -} - -// See module-level documentation for more information on the encoding. -pub const TERMINATOR: u8 = 0xFF; -pub const STRING_REF_TAG: u8 = 0xFE; -pub const STRING_REF_ENCODED_SIZE: usize = 5; - -/// The maximum id value a virtual string may be. -const MAX_USER_VIRTUAL_STRING_ID: u32 = 100_000_000; - -/// The id of the profile metadata string entry. -pub const METADATA_STRING_ID: u32 = MAX_USER_VIRTUAL_STRING_ID + 1; - -/// Some random string ID that we make sure cannot be generated or assigned to. -const INVALID_STRING_ID: u32 = METADATA_STRING_ID + 1; - -pub const FIRST_REGULAR_STRING_ID: u32 = INVALID_STRING_ID + 1; - -/// Write-only version of the string table -pub struct StringTableBuilder { - data_sink: Arc<SerializationSink>, - index_sink: Arc<SerializationSink>, -} - -/// Anything that implements `SerializableString` can be written to a -/// `StringTable`. -pub trait SerializableString { - fn serialized_size(&self) -> usize; - fn serialize(&self, bytes: &mut [u8]); -} - -// A single string is encoded as `[UTF-8 bytes][TERMINATOR]` -impl SerializableString for str { - #[inline] - fn serialized_size(&self) -> usize { - self.len() + // actual bytes - 1 // terminator - } - - #[inline] - fn serialize(&self, bytes: &mut [u8]) { - let last_byte_index = bytes.len() - 1; - bytes[0..last_byte_index].copy_from_slice(self.as_bytes()); - bytes[last_byte_index] = TERMINATOR; - } -} - -/// A single component of a string. Used for building composite table entries. -pub enum StringComponent<'s> { - Value(&'s str), - Ref(StringId), -} - -impl<'s> StringComponent<'s> { - #[inline] - fn serialized_size(&self) -> usize { - match *self { - StringComponent::Value(s) => s.len(), - StringComponent::Ref(_) => STRING_REF_ENCODED_SIZE, - } - } - - #[inline] - fn serialize<'b>(&self, bytes: &'b mut [u8]) -> &'b mut [u8] { - match *self { - StringComponent::Value(s) => { - bytes[..s.len()].copy_from_slice(s.as_bytes()); - &mut bytes[s.len()..] - } - StringComponent::Ref(string_id) => { - // The code below assumes we use a 5-byte encoding for string - // refs, where the first byte is STRING_REF_TAG and the - // following 4 bytes are a little-endian u32 string ID value. - assert!(STRING_REF_ENCODED_SIZE == 5); - - bytes[0] = STRING_REF_TAG; - &mut bytes[1..5].copy_from_slice(&string_id.0.to_le_bytes()); - &mut bytes[5..] - } - } - } -} - -impl<'a> SerializableString for [StringComponent<'a>] { - #[inline] - fn serialized_size(&self) -> usize { - self.iter().map(|c| c.serialized_size()).sum::<usize>() + // size of components - 1 // terminator - } - - #[inline] - fn serialize(&self, mut bytes: &mut [u8]) { - assert!(bytes.len() == self.serialized_size()); - for component in self.iter() { - bytes = component.serialize(bytes); - } - - // Assert that we used the exact number of bytes we anticipated. - assert!(bytes.len() == 1); - bytes[0] = TERMINATOR; - } -} - -macro_rules! impl_serializable_string_for_fixed_size { - ($n:expr) => { - impl<'a> SerializableString for [StringComponent<'a>; $n] { - #[inline(always)] - fn serialized_size(&self) -> usize { - (&self[..]).serialized_size() - } - - #[inline(always)] - fn serialize(&self, bytes: &mut [u8]) { - (&self[..]).serialize(bytes); - } - } - }; -} - -impl_serializable_string_for_fixed_size!(0); -impl_serializable_string_for_fixed_size!(1); -impl_serializable_string_for_fixed_size!(2); -impl_serializable_string_for_fixed_size!(3); -impl_serializable_string_for_fixed_size!(4); -impl_serializable_string_for_fixed_size!(5); -impl_serializable_string_for_fixed_size!(6); -impl_serializable_string_for_fixed_size!(7); -impl_serializable_string_for_fixed_size!(8); -impl_serializable_string_for_fixed_size!(9); -impl_serializable_string_for_fixed_size!(10); -impl_serializable_string_for_fixed_size!(11); -impl_serializable_string_for_fixed_size!(12); -impl_serializable_string_for_fixed_size!(13); -impl_serializable_string_for_fixed_size!(14); -impl_serializable_string_for_fixed_size!(15); -impl_serializable_string_for_fixed_size!(16); - -fn serialize_index_entry(sink: &SerializationSink, id: StringId, addr: Addr) { - sink.write_atomic(8, |bytes| { - bytes[0..4].copy_from_slice(&id.0.to_le_bytes()); - bytes[4..8].copy_from_slice(&addr.0.to_le_bytes()); - }); -} - -impl StringTableBuilder { - pub fn new( - data_sink: Arc<SerializationSink>, - index_sink: Arc<SerializationSink>, - ) -> Result<StringTableBuilder, Box<dyn Error + Send + Sync>> { - // The first thing in every stream we generate must be the stream header. - write_file_header(&mut data_sink.as_std_write(), FILE_MAGIC_STRINGTABLE_DATA)?; - write_file_header(&mut index_sink.as_std_write(), FILE_MAGIC_STRINGTABLE_INDEX)?; - - Ok(StringTableBuilder { - data_sink, - index_sink, - }) - } - - /// Creates a mapping so that `virtual_id` will resolve to the contents of - /// `concrete_id` when reading the string table. - pub fn map_virtual_to_concrete_string(&self, virtual_id: StringId, concrete_id: StringId) { - // This assertion does not use `is_virtual` on purpose because that - // would also allow to overwrite `METADATA_STRING_ID`. - assert!(virtual_id.0 <= MAX_USER_VIRTUAL_STRING_ID); - serialize_index_entry(&*self.index_sink, virtual_id, concrete_id.to_addr()); - } - - pub fn bulk_map_virtual_to_single_concrete_string<I>( - &self, - virtual_ids: I, - concrete_id: StringId, - ) where - I: Iterator<Item = StringId> + ExactSizeIterator, - { - // TODO: Index data encoding could have a special bulk mode that assigns - // multiple StringIds to the same addr, so we don't have to repeat - // the `concrete_id` over and over. - - type MappingEntry = [u32; 2]; - assert!(std::mem::size_of::<MappingEntry>() == 8); - - let to_addr_le = concrete_id.to_addr().0.to_le(); - - let serialized: Vec<MappingEntry> = virtual_ids - .map(|from| { - let id = from.0; - assert!(id <= MAX_USER_VIRTUAL_STRING_ID); - [id.to_le(), to_addr_le] - }) - .collect(); - - let num_bytes = serialized.len() * std::mem::size_of::<MappingEntry>(); - let byte_ptr = serialized.as_ptr() as *const u8; - - let bytes = unsafe { std::slice::from_raw_parts(byte_ptr, num_bytes) }; - - self.index_sink.write_bytes_atomic(bytes); - } - - pub(crate) fn alloc_metadata<STR: SerializableString + ?Sized>(&self, s: &STR) { - let concrete_id = self.alloc(s); - let virtual_id = StringId(METADATA_STRING_ID); - assert!(virtual_id.is_virtual()); - serialize_index_entry(&*self.index_sink, virtual_id, concrete_id.to_addr()); - } - - pub fn alloc<STR: SerializableString + ?Sized>(&self, s: &STR) -> StringId { - let size_in_bytes = s.serialized_size(); - let addr = self.data_sink.write_atomic(size_in_bytes, |mem| { - s.serialize(mem); - }); - - StringId::from_addr(addr) - } -} +//! A string table implementation with a tree-like encoding. +//! +//! Each entry in the table represents a string and is encoded as a list of +//! components where each component can either be +//! +//! 1. a string _value_ that contains actual UTF-8 string content, +//! 2. a string _ID_ that contains a reference to another entry, or +//! 3. a terminator tag which marks the end of a component list. +//! +//! The string _content_ of an entry is defined as the concatenation of the +//! content of its components. The content of a string value is its actual +//! UTF-8 bytes. The content of a string ID is the contents of the entry +//! it references. +//! +//! The byte-level encoding of component lists uses the structure of UTF-8 in +//! order to save space: +//! +//! - A valid UTF-8 codepoint never starts with the byte `0xFE`. We make use +//! of this fact by letting all string ID components start with this `0xFE` +//! prefix. Thus when we parse the contents of a value we know to stop if +//! we encounter this byte. +//! +//! - A valid UTF-8 string cannot contain the `0xFF` byte. Thus we can safely +//! use `0xFF` as our component list terminator. +//! +//! The sample composite string ["abc", ID(42), "def", TERMINATOR] would thus be +//! encoded as: +//! +//! ```ignore +//! ['a', 'b' , 'c', 254, 42, 0, 0, 0, 'd', 'e', 'f', 255] +//! ^^^^^^^^^^^^^^^^ ^^^ +//! string ID with 0xFE prefix terminator (0xFF) +//! ``` +//! +//! As you can see string IDs are encoded in little endian format. +//! +//! ---------------------------------------------------------------------------- +//! +//! Each string in the table is referred to via a `StringId`. `StringId`s may +//! be generated in two ways: +//! +//! 1. Calling `StringTableBuilder::alloc()` which returns the `StringId` for +//! the allocated string. +//! 2. Calling `StringId::new_virtual()` to create a "virtual" `StringId` that +//! later can be mapped to an actual string via +//! `StringTableBuilder::map_virtual_to_concrete_string()`. +//! +//! String IDs allow you to deduplicate strings by allocating a string +//! once and then referring to it by id over and over. This is a useful trick +//! for strings which are recorded many times and it can significantly reduce +//! the size of profile trace files. +//! +//! `StringId`s are partitioned according to type: +//! +//! > [0 .. MAX_VIRTUAL_STRING_ID, METADATA_STRING_ID, .. ] +//! +//! From `0` to `MAX_VIRTUAL_STRING_ID` are the allowed values for virtual strings. +//! After `MAX_VIRTUAL_STRING_ID`, there is one string id (`METADATA_STRING_ID`) +//! which is used internally by `measureme` to record additional metadata about +//! the profiling session. After `METADATA_STRING_ID` are all other `StringId` +//! values. + +use crate::file_header::{ + write_file_header, FILE_MAGIC_STRINGTABLE_DATA, FILE_MAGIC_STRINGTABLE_INDEX, +}; +use crate::serialization::Addr; +use crate::serialization::SerializationSink; +use std::{error::Error, sync::Arc}; + +/// A `StringId` is used to identify a string in the `StringTable`. It is +/// either a regular `StringId`, meaning that it contains the absolute address +/// of a string within the string table data. Or it is "virtual", which means +/// that the address it points to is resolved via the string table index data, +/// that maps virtual `StringId`s to addresses. +#[derive(Clone, Copy, Eq, PartialEq, Debug, Hash)] +#[repr(C)] +pub struct StringId(u32); + +impl StringId { + pub const INVALID: StringId = StringId(INVALID_STRING_ID); + + #[inline] + pub fn new(id: u32) -> StringId { + StringId(id) + } + + #[inline] + pub fn new_virtual(id: u32) -> StringId { + assert!(id <= MAX_USER_VIRTUAL_STRING_ID); + StringId(id) + } + + #[inline] + pub fn is_virtual(self) -> bool { + self.0 <= METADATA_STRING_ID + } + + #[inline] + pub fn as_u32(self) -> u32 { + self.0 + } + + #[inline] + pub fn from_addr(addr: Addr) -> StringId { + let id = addr.0.checked_add(FIRST_REGULAR_STRING_ID).unwrap(); + StringId::new(id) + } + + #[inline] + pub fn to_addr(self) -> Addr { + Addr(self.0.checked_sub(FIRST_REGULAR_STRING_ID).unwrap()) + } +} + +// See module-level documentation for more information on the encoding. +pub const TERMINATOR: u8 = 0xFF; +pub const STRING_REF_TAG: u8 = 0xFE; +pub const STRING_REF_ENCODED_SIZE: usize = 5; + +/// The maximum id value a virtual string may be. +const MAX_USER_VIRTUAL_STRING_ID: u32 = 100_000_000; + +/// The id of the profile metadata string entry. +pub const METADATA_STRING_ID: u32 = MAX_USER_VIRTUAL_STRING_ID + 1; + +/// Some random string ID that we make sure cannot be generated or assigned to. +const INVALID_STRING_ID: u32 = METADATA_STRING_ID + 1; + +pub const FIRST_REGULAR_STRING_ID: u32 = INVALID_STRING_ID + 1; + +/// Write-only version of the string table +pub struct StringTableBuilder { + data_sink: Arc<SerializationSink>, + index_sink: Arc<SerializationSink>, +} + +/// Anything that implements `SerializableString` can be written to a +/// `StringTable`. +pub trait SerializableString { + fn serialized_size(&self) -> usize; + fn serialize(&self, bytes: &mut [u8]); +} + +// A single string is encoded as `[UTF-8 bytes][TERMINATOR]` +impl SerializableString for str { + #[inline] + fn serialized_size(&self) -> usize { + self.len() + // actual bytes + 1 // terminator + } + + #[inline] + fn serialize(&self, bytes: &mut [u8]) { + let last_byte_index = bytes.len() - 1; + bytes[0..last_byte_index].copy_from_slice(self.as_bytes()); + bytes[last_byte_index] = TERMINATOR; + } +} + +/// A single component of a string. Used for building composite table entries. +pub enum StringComponent<'s> { + Value(&'s str), + Ref(StringId), +} + +impl<'s> StringComponent<'s> { + #[inline] + fn serialized_size(&self) -> usize { + match *self { + StringComponent::Value(s) => s.len(), + StringComponent::Ref(_) => STRING_REF_ENCODED_SIZE, + } + } + + #[inline] + fn serialize<'b>(&self, bytes: &'b mut [u8]) -> &'b mut [u8] { + match *self { + StringComponent::Value(s) => { + bytes[..s.len()].copy_from_slice(s.as_bytes()); + &mut bytes[s.len()..] + } + StringComponent::Ref(string_id) => { + // The code below assumes we use a 5-byte encoding for string + // refs, where the first byte is STRING_REF_TAG and the + // following 4 bytes are a little-endian u32 string ID value. + assert!(STRING_REF_ENCODED_SIZE == 5); + + bytes[0] = STRING_REF_TAG; + bytes[1..5].copy_from_slice(&string_id.0.to_le_bytes()); + &mut bytes[5..] + } + } + } +} + +impl<'a> SerializableString for [StringComponent<'a>] { + #[inline] + fn serialized_size(&self) -> usize { + self.iter().map(|c| c.serialized_size()).sum::<usize>() + // size of components + 1 // terminator + } + + #[inline] + fn serialize(&self, mut bytes: &mut [u8]) { + assert!(bytes.len() == self.serialized_size()); + for component in self.iter() { + bytes = component.serialize(bytes); + } + + // Assert that we used the exact number of bytes we anticipated. + assert!(bytes.len() == 1); + bytes[0] = TERMINATOR; + } +} + +macro_rules! impl_serializable_string_for_fixed_size { + ($n:expr) => { + impl<'a> SerializableString for [StringComponent<'a>; $n] { + #[inline(always)] + fn serialized_size(&self) -> usize { + (&self[..]).serialized_size() + } + + #[inline(always)] + fn serialize(&self, bytes: &mut [u8]) { + (&self[..]).serialize(bytes); + } + } + }; +} + +impl_serializable_string_for_fixed_size!(0); +impl_serializable_string_for_fixed_size!(1); +impl_serializable_string_for_fixed_size!(2); +impl_serializable_string_for_fixed_size!(3); +impl_serializable_string_for_fixed_size!(4); +impl_serializable_string_for_fixed_size!(5); +impl_serializable_string_for_fixed_size!(6); +impl_serializable_string_for_fixed_size!(7); +impl_serializable_string_for_fixed_size!(8); +impl_serializable_string_for_fixed_size!(9); +impl_serializable_string_for_fixed_size!(10); +impl_serializable_string_for_fixed_size!(11); +impl_serializable_string_for_fixed_size!(12); +impl_serializable_string_for_fixed_size!(13); +impl_serializable_string_for_fixed_size!(14); +impl_serializable_string_for_fixed_size!(15); +impl_serializable_string_for_fixed_size!(16); + +fn serialize_index_entry(sink: &SerializationSink, id: StringId, addr: Addr) { + sink.write_atomic(8, |bytes| { + bytes[0..4].copy_from_slice(&id.0.to_le_bytes()); + bytes[4..8].copy_from_slice(&addr.0.to_le_bytes()); + }); +} + +impl StringTableBuilder { + pub fn new( + data_sink: Arc<SerializationSink>, + index_sink: Arc<SerializationSink>, + ) -> Result<StringTableBuilder, Box<dyn Error + Send + Sync>> { + // The first thing in every stream we generate must be the stream header. + write_file_header(&mut data_sink.as_std_write(), FILE_MAGIC_STRINGTABLE_DATA)?; + write_file_header(&mut index_sink.as_std_write(), FILE_MAGIC_STRINGTABLE_INDEX)?; + + Ok(StringTableBuilder { + data_sink, + index_sink, + }) + } + + /// Creates a mapping so that `virtual_id` will resolve to the contents of + /// `concrete_id` when reading the string table. + pub fn map_virtual_to_concrete_string(&self, virtual_id: StringId, concrete_id: StringId) { + // This assertion does not use `is_virtual` on purpose because that + // would also allow to overwrite `METADATA_STRING_ID`. + assert!(virtual_id.0 <= MAX_USER_VIRTUAL_STRING_ID); + serialize_index_entry(&*self.index_sink, virtual_id, concrete_id.to_addr()); + } + + pub fn bulk_map_virtual_to_single_concrete_string<I>( + &self, + virtual_ids: I, + concrete_id: StringId, + ) where + I: Iterator<Item = StringId> + ExactSizeIterator, + { + // TODO: Index data encoding could have a special bulk mode that assigns + // multiple StringIds to the same addr, so we don't have to repeat + // the `concrete_id` over and over. + + type MappingEntry = [u32; 2]; + assert!(std::mem::size_of::<MappingEntry>() == 8); + + let to_addr_le = concrete_id.to_addr().0.to_le(); + + let serialized: Vec<MappingEntry> = virtual_ids + .map(|from| { + let id = from.0; + assert!(id <= MAX_USER_VIRTUAL_STRING_ID); + [id.to_le(), to_addr_le] + }) + .collect(); + + let num_bytes = serialized.len() * std::mem::size_of::<MappingEntry>(); + let byte_ptr = serialized.as_ptr() as *const u8; + + let bytes = unsafe { std::slice::from_raw_parts(byte_ptr, num_bytes) }; + + self.index_sink.write_bytes_atomic(bytes); + } + + pub fn alloc_metadata<STR: SerializableString + ?Sized>(&self, s: &STR) { + let concrete_id = self.alloc(s); + let virtual_id = StringId(METADATA_STRING_ID); + assert!(virtual_id.is_virtual()); + serialize_index_entry(&*self.index_sink, virtual_id, concrete_id.to_addr()); + } + + pub fn alloc<STR: SerializableString + ?Sized>(&self, s: &STR) -> StringId { + let size_in_bytes = s.serialized_size(); + let addr = self.data_sink.write_atomic(size_in_bytes, |mem| { + s.serialize(mem); + }); + + StringId::from_addr(addr) + } +} diff --git a/vendor/object/.cargo-checksum.json b/vendor/object-0.26.2/.cargo-checksum.json similarity index 100% rename from vendor/object/.cargo-checksum.json rename to vendor/object-0.26.2/.cargo-checksum.json diff --git a/vendor/object/CHANGELOG.md b/vendor/object-0.26.2/CHANGELOG.md similarity index 100% rename from vendor/object/CHANGELOG.md rename to vendor/object-0.26.2/CHANGELOG.md diff --git a/vendor/object/Cargo.lock b/vendor/object-0.26.2/Cargo.lock similarity index 100% rename from vendor/object/Cargo.lock rename to vendor/object-0.26.2/Cargo.lock diff --git a/vendor/object/Cargo.toml b/vendor/object-0.26.2/Cargo.toml similarity index 100% rename from vendor/object/Cargo.toml rename to vendor/object-0.26.2/Cargo.toml diff --git a/vendor/object-0.26.2/LICENSE-APACHE b/vendor/object-0.26.2/LICENSE-APACHE new file mode 100644 index 0000000000..16fe87b06e --- /dev/null +++ b/vendor/object-0.26.2/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/vendor/object/LICENSE-MIT b/vendor/object-0.26.2/LICENSE-MIT similarity index 100% rename from vendor/object/LICENSE-MIT rename to vendor/object-0.26.2/LICENSE-MIT diff --git a/vendor/object/README.md b/vendor/object-0.26.2/README.md similarity index 100% rename from vendor/object/README.md rename to vendor/object-0.26.2/README.md diff --git a/vendor/object/clippy.toml b/vendor/object-0.26.2/clippy.toml similarity index 100% rename from vendor/object/clippy.toml rename to vendor/object-0.26.2/clippy.toml diff --git a/vendor/object/examples/ar.rs b/vendor/object-0.26.2/examples/ar.rs similarity index 100% rename from vendor/object/examples/ar.rs rename to vendor/object-0.26.2/examples/ar.rs diff --git a/vendor/object/examples/dyldcachedump.rs b/vendor/object-0.26.2/examples/dyldcachedump.rs similarity index 100% rename from vendor/object/examples/dyldcachedump.rs rename to vendor/object-0.26.2/examples/dyldcachedump.rs diff --git a/vendor/object/examples/nm.rs b/vendor/object-0.26.2/examples/nm.rs similarity index 100% rename from vendor/object/examples/nm.rs rename to vendor/object-0.26.2/examples/nm.rs diff --git a/vendor/object/examples/objcopy.rs b/vendor/object-0.26.2/examples/objcopy.rs similarity index 100% rename from vendor/object/examples/objcopy.rs rename to vendor/object-0.26.2/examples/objcopy.rs diff --git a/vendor/object/examples/objdump.rs b/vendor/object-0.26.2/examples/objdump.rs similarity index 100% rename from vendor/object/examples/objdump.rs rename to vendor/object-0.26.2/examples/objdump.rs diff --git a/vendor/object/examples/objectmap.rs b/vendor/object-0.26.2/examples/objectmap.rs similarity index 100% rename from vendor/object/examples/objectmap.rs rename to vendor/object-0.26.2/examples/objectmap.rs diff --git a/vendor/object/examples/readobj.rs b/vendor/object-0.26.2/examples/readobj.rs similarity index 100% rename from vendor/object/examples/readobj.rs rename to vendor/object-0.26.2/examples/readobj.rs diff --git a/vendor/object/src/archive.rs b/vendor/object-0.26.2/src/archive.rs similarity index 100% rename from vendor/object/src/archive.rs rename to vendor/object-0.26.2/src/archive.rs diff --git a/vendor/object/src/common.rs b/vendor/object-0.26.2/src/common.rs similarity index 100% rename from vendor/object/src/common.rs rename to vendor/object-0.26.2/src/common.rs diff --git a/vendor/object/src/elf.rs b/vendor/object-0.26.2/src/elf.rs similarity index 100% rename from vendor/object/src/elf.rs rename to vendor/object-0.26.2/src/elf.rs diff --git a/vendor/object/src/endian.rs b/vendor/object-0.26.2/src/endian.rs similarity index 100% rename from vendor/object/src/endian.rs rename to vendor/object-0.26.2/src/endian.rs diff --git a/vendor/object/src/lib.rs b/vendor/object-0.26.2/src/lib.rs similarity index 100% rename from vendor/object/src/lib.rs rename to vendor/object-0.26.2/src/lib.rs diff --git a/vendor/object/src/macho.rs b/vendor/object-0.26.2/src/macho.rs similarity index 100% rename from vendor/object/src/macho.rs rename to vendor/object-0.26.2/src/macho.rs diff --git a/vendor/object/src/pe.rs b/vendor/object-0.26.2/src/pe.rs similarity index 100% rename from vendor/object/src/pe.rs rename to vendor/object-0.26.2/src/pe.rs diff --git a/vendor/object/src/pod.rs b/vendor/object-0.26.2/src/pod.rs similarity index 100% rename from vendor/object/src/pod.rs rename to vendor/object-0.26.2/src/pod.rs diff --git a/vendor/object/src/read/any.rs b/vendor/object-0.26.2/src/read/any.rs similarity index 100% rename from vendor/object/src/read/any.rs rename to vendor/object-0.26.2/src/read/any.rs diff --git a/vendor/object/src/read/archive.rs b/vendor/object-0.26.2/src/read/archive.rs similarity index 100% rename from vendor/object/src/read/archive.rs rename to vendor/object-0.26.2/src/read/archive.rs diff --git a/vendor/object/src/read/coff/comdat.rs b/vendor/object-0.26.2/src/read/coff/comdat.rs similarity index 100% rename from vendor/object/src/read/coff/comdat.rs rename to vendor/object-0.26.2/src/read/coff/comdat.rs diff --git a/vendor/object/src/read/coff/file.rs b/vendor/object-0.26.2/src/read/coff/file.rs similarity index 100% rename from vendor/object/src/read/coff/file.rs rename to vendor/object-0.26.2/src/read/coff/file.rs diff --git a/vendor/object/src/read/coff/mod.rs b/vendor/object-0.26.2/src/read/coff/mod.rs similarity index 100% rename from vendor/object/src/read/coff/mod.rs rename to vendor/object-0.26.2/src/read/coff/mod.rs diff --git a/vendor/object/src/read/coff/relocation.rs b/vendor/object-0.26.2/src/read/coff/relocation.rs similarity index 100% rename from vendor/object/src/read/coff/relocation.rs rename to vendor/object-0.26.2/src/read/coff/relocation.rs diff --git a/vendor/object/src/read/coff/section.rs b/vendor/object-0.26.2/src/read/coff/section.rs similarity index 100% rename from vendor/object/src/read/coff/section.rs rename to vendor/object-0.26.2/src/read/coff/section.rs diff --git a/vendor/object/src/read/coff/symbol.rs b/vendor/object-0.26.2/src/read/coff/symbol.rs similarity index 100% rename from vendor/object/src/read/coff/symbol.rs rename to vendor/object-0.26.2/src/read/coff/symbol.rs diff --git a/vendor/object/src/read/elf/comdat.rs b/vendor/object-0.26.2/src/read/elf/comdat.rs similarity index 100% rename from vendor/object/src/read/elf/comdat.rs rename to vendor/object-0.26.2/src/read/elf/comdat.rs diff --git a/vendor/object/src/read/elf/compression.rs b/vendor/object-0.26.2/src/read/elf/compression.rs similarity index 100% rename from vendor/object/src/read/elf/compression.rs rename to vendor/object-0.26.2/src/read/elf/compression.rs diff --git a/vendor/object/src/read/elf/dynamic.rs b/vendor/object-0.26.2/src/read/elf/dynamic.rs similarity index 100% rename from vendor/object/src/read/elf/dynamic.rs rename to vendor/object-0.26.2/src/read/elf/dynamic.rs diff --git a/vendor/object/src/read/elf/file.rs b/vendor/object-0.26.2/src/read/elf/file.rs similarity index 100% rename from vendor/object/src/read/elf/file.rs rename to vendor/object-0.26.2/src/read/elf/file.rs diff --git a/vendor/object/src/read/elf/hash.rs b/vendor/object-0.26.2/src/read/elf/hash.rs similarity index 100% rename from vendor/object/src/read/elf/hash.rs rename to vendor/object-0.26.2/src/read/elf/hash.rs diff --git a/vendor/object/src/read/elf/mod.rs b/vendor/object-0.26.2/src/read/elf/mod.rs similarity index 100% rename from vendor/object/src/read/elf/mod.rs rename to vendor/object-0.26.2/src/read/elf/mod.rs diff --git a/vendor/object/src/read/elf/note.rs b/vendor/object-0.26.2/src/read/elf/note.rs similarity index 100% rename from vendor/object/src/read/elf/note.rs rename to vendor/object-0.26.2/src/read/elf/note.rs diff --git a/vendor/object/src/read/elf/relocation.rs b/vendor/object-0.26.2/src/read/elf/relocation.rs similarity index 100% rename from vendor/object/src/read/elf/relocation.rs rename to vendor/object-0.26.2/src/read/elf/relocation.rs diff --git a/vendor/object/src/read/elf/section.rs b/vendor/object-0.26.2/src/read/elf/section.rs similarity index 100% rename from vendor/object/src/read/elf/section.rs rename to vendor/object-0.26.2/src/read/elf/section.rs diff --git a/vendor/object/src/read/elf/segment.rs b/vendor/object-0.26.2/src/read/elf/segment.rs similarity index 100% rename from vendor/object/src/read/elf/segment.rs rename to vendor/object-0.26.2/src/read/elf/segment.rs diff --git a/vendor/object/src/read/elf/symbol.rs b/vendor/object-0.26.2/src/read/elf/symbol.rs similarity index 100% rename from vendor/object/src/read/elf/symbol.rs rename to vendor/object-0.26.2/src/read/elf/symbol.rs diff --git a/vendor/object/src/read/elf/version.rs b/vendor/object-0.26.2/src/read/elf/version.rs similarity index 100% rename from vendor/object/src/read/elf/version.rs rename to vendor/object-0.26.2/src/read/elf/version.rs diff --git a/vendor/object/src/read/macho/dyld_cache.rs b/vendor/object-0.26.2/src/read/macho/dyld_cache.rs similarity index 100% rename from vendor/object/src/read/macho/dyld_cache.rs rename to vendor/object-0.26.2/src/read/macho/dyld_cache.rs diff --git a/vendor/object/src/read/macho/fat.rs b/vendor/object-0.26.2/src/read/macho/fat.rs similarity index 100% rename from vendor/object/src/read/macho/fat.rs rename to vendor/object-0.26.2/src/read/macho/fat.rs diff --git a/vendor/object/src/read/macho/file.rs b/vendor/object-0.26.2/src/read/macho/file.rs similarity index 100% rename from vendor/object/src/read/macho/file.rs rename to vendor/object-0.26.2/src/read/macho/file.rs diff --git a/vendor/object/src/read/macho/load_command.rs b/vendor/object-0.26.2/src/read/macho/load_command.rs similarity index 100% rename from vendor/object/src/read/macho/load_command.rs rename to vendor/object-0.26.2/src/read/macho/load_command.rs diff --git a/vendor/object/src/read/macho/mod.rs b/vendor/object-0.26.2/src/read/macho/mod.rs similarity index 100% rename from vendor/object/src/read/macho/mod.rs rename to vendor/object-0.26.2/src/read/macho/mod.rs diff --git a/vendor/object/src/read/macho/relocation.rs b/vendor/object-0.26.2/src/read/macho/relocation.rs similarity index 100% rename from vendor/object/src/read/macho/relocation.rs rename to vendor/object-0.26.2/src/read/macho/relocation.rs diff --git a/vendor/object/src/read/macho/section.rs b/vendor/object-0.26.2/src/read/macho/section.rs similarity index 100% rename from vendor/object/src/read/macho/section.rs rename to vendor/object-0.26.2/src/read/macho/section.rs diff --git a/vendor/object/src/read/macho/segment.rs b/vendor/object-0.26.2/src/read/macho/segment.rs similarity index 100% rename from vendor/object/src/read/macho/segment.rs rename to vendor/object-0.26.2/src/read/macho/segment.rs diff --git a/vendor/object/src/read/macho/symbol.rs b/vendor/object-0.26.2/src/read/macho/symbol.rs similarity index 100% rename from vendor/object/src/read/macho/symbol.rs rename to vendor/object-0.26.2/src/read/macho/symbol.rs diff --git a/vendor/object/src/read/mod.rs b/vendor/object-0.26.2/src/read/mod.rs similarity index 100% rename from vendor/object/src/read/mod.rs rename to vendor/object-0.26.2/src/read/mod.rs diff --git a/vendor/object/src/read/pe/file.rs b/vendor/object-0.26.2/src/read/pe/file.rs similarity index 100% rename from vendor/object/src/read/pe/file.rs rename to vendor/object-0.26.2/src/read/pe/file.rs diff --git a/vendor/object/src/read/pe/mod.rs b/vendor/object-0.26.2/src/read/pe/mod.rs similarity index 100% rename from vendor/object/src/read/pe/mod.rs rename to vendor/object-0.26.2/src/read/pe/mod.rs diff --git a/vendor/object/src/read/pe/section.rs b/vendor/object-0.26.2/src/read/pe/section.rs similarity index 100% rename from vendor/object/src/read/pe/section.rs rename to vendor/object-0.26.2/src/read/pe/section.rs diff --git a/vendor/object/src/read/read_cache.rs b/vendor/object-0.26.2/src/read/read_cache.rs similarity index 100% rename from vendor/object/src/read/read_cache.rs rename to vendor/object-0.26.2/src/read/read_cache.rs diff --git a/vendor/object/src/read/read_ref.rs b/vendor/object-0.26.2/src/read/read_ref.rs similarity index 100% rename from vendor/object/src/read/read_ref.rs rename to vendor/object-0.26.2/src/read/read_ref.rs diff --git a/vendor/object/src/read/traits.rs b/vendor/object-0.26.2/src/read/traits.rs similarity index 100% rename from vendor/object/src/read/traits.rs rename to vendor/object-0.26.2/src/read/traits.rs diff --git a/vendor/object/src/read/util.rs b/vendor/object-0.26.2/src/read/util.rs similarity index 100% rename from vendor/object/src/read/util.rs rename to vendor/object-0.26.2/src/read/util.rs diff --git a/vendor/object/src/read/wasm.rs b/vendor/object-0.26.2/src/read/wasm.rs similarity index 100% rename from vendor/object/src/read/wasm.rs rename to vendor/object-0.26.2/src/read/wasm.rs diff --git a/vendor/object/src/write/coff.rs b/vendor/object-0.26.2/src/write/coff.rs similarity index 100% rename from vendor/object/src/write/coff.rs rename to vendor/object-0.26.2/src/write/coff.rs diff --git a/vendor/object/src/write/elf.rs b/vendor/object-0.26.2/src/write/elf.rs similarity index 100% rename from vendor/object/src/write/elf.rs rename to vendor/object-0.26.2/src/write/elf.rs diff --git a/vendor/object/src/write/macho.rs b/vendor/object-0.26.2/src/write/macho.rs similarity index 100% rename from vendor/object/src/write/macho.rs rename to vendor/object-0.26.2/src/write/macho.rs diff --git a/vendor/object/src/write/mod.rs b/vendor/object-0.26.2/src/write/mod.rs similarity index 100% rename from vendor/object/src/write/mod.rs rename to vendor/object-0.26.2/src/write/mod.rs diff --git a/vendor/object/src/write/string.rs b/vendor/object-0.26.2/src/write/string.rs similarity index 100% rename from vendor/object/src/write/string.rs rename to vendor/object-0.26.2/src/write/string.rs diff --git a/vendor/object/src/write/util.rs b/vendor/object-0.26.2/src/write/util.rs similarity index 100% rename from vendor/object/src/write/util.rs rename to vendor/object-0.26.2/src/write/util.rs diff --git a/vendor/object/tests/integration.rs b/vendor/object-0.26.2/tests/integration.rs similarity index 100% rename from vendor/object/tests/integration.rs rename to vendor/object-0.26.2/tests/integration.rs diff --git a/vendor/object/tests/parse_self.rs b/vendor/object-0.26.2/tests/parse_self.rs similarity index 100% rename from vendor/object/tests/parse_self.rs rename to vendor/object-0.26.2/tests/parse_self.rs diff --git a/vendor/object/tests/round_trip/bss.rs b/vendor/object-0.26.2/tests/round_trip/bss.rs similarity index 100% rename from vendor/object/tests/round_trip/bss.rs rename to vendor/object-0.26.2/tests/round_trip/bss.rs diff --git a/vendor/object/tests/round_trip/comdat.rs b/vendor/object-0.26.2/tests/round_trip/comdat.rs similarity index 100% rename from vendor/object/tests/round_trip/comdat.rs rename to vendor/object-0.26.2/tests/round_trip/comdat.rs diff --git a/vendor/object/tests/round_trip/common.rs b/vendor/object-0.26.2/tests/round_trip/common.rs similarity index 100% rename from vendor/object/tests/round_trip/common.rs rename to vendor/object-0.26.2/tests/round_trip/common.rs diff --git a/vendor/object/tests/round_trip/elf.rs b/vendor/object-0.26.2/tests/round_trip/elf.rs similarity index 100% rename from vendor/object/tests/round_trip/elf.rs rename to vendor/object-0.26.2/tests/round_trip/elf.rs diff --git a/vendor/object/tests/round_trip/macho.rs b/vendor/object-0.26.2/tests/round_trip/macho.rs similarity index 100% rename from vendor/object/tests/round_trip/macho.rs rename to vendor/object-0.26.2/tests/round_trip/macho.rs diff --git a/vendor/object/tests/round_trip/mod.rs b/vendor/object-0.26.2/tests/round_trip/mod.rs similarity index 100% rename from vendor/object/tests/round_trip/mod.rs rename to vendor/object-0.26.2/tests/round_trip/mod.rs diff --git a/vendor/object/tests/round_trip/tls.rs b/vendor/object-0.26.2/tests/round_trip/tls.rs similarity index 100% rename from vendor/object/tests/round_trip/tls.rs rename to vendor/object-0.26.2/tests/round_trip/tls.rs diff --git a/vendor/proc-macro2/.cargo-checksum.json b/vendor/proc-macro2/.cargo-checksum.json index b88de6c18c..bbbcbce07e 100644 --- a/vendor/proc-macro2/.cargo-checksum.json +++ b/vendor/proc-macro2/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"0a5984c855f13db167b90022183c267afcebbafa42a5a66bbcba04953d23b7d7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"e1f9d4fc22cff2c049f166a403b41458632a94357890d31cf0e3ad83807fb430","build.rs":"4a6ea112a069e927e40dd79c4b2eaf054521c49eb381c1b24cd5a8a035ee06b5","src/detection.rs":"9d25d896889e65330858f2d6f6223c1b98cd1dad189813ad4161ff189fbda2b8","src/fallback.rs":"c161f65f18d7d19bcbd568f5c0bea1cfc1ce3bd9c66427b1fdb4944ad7966ce0","src/lib.rs":"993e046f5777ea09500775b6323eadd9c48cb48e9f818ec0d39faf50479f019e","src/marker.rs":"87fce2d0357f5b7998b6d9dfb064f4a0cbc9dabb19e33d4b514a446243ebe2e8","src/parse.rs":"b82101576fdc493793f040aa17c11267e2747964729df1f88c81fe413aed407e","src/wrapper.rs":"624527eaa49c272824ab5f7286e6ecbdd80b6eac54e99be11b6e8b29dcb0015d","tests/comments.rs":"ea6cbe6f4c8852e6a0612893c7d4f2c144a2e6a134a6c3db641a320cbfc3c800","tests/features.rs":"a86deb8644992a4eb64d9fd493eff16f9cf9c5cb6ade3a634ce0c990cf87d559","tests/marker.rs":"652db9f25c69ffc65baa60cdca8f195aa2e254d4de0a9ddc85de4dc2470544b6","tests/test.rs":"597186c00ebf51191934c88ff970b5457ca0fb8e608bf896be1ebf8d74c17f4d","tests/test_fmt.rs":"745dfdc41d09c5308c221395eb43f2041f0a1413d2927a813bc2ad4554438fe2"},"package":"b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d"} \ No newline at end of file +{"files":{"Cargo.toml":"738c9707b212d06a658513fad1b35d47a3518c1c98c84051269239f37cc0b7c6","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"fb633ca229c17dc9802db9b66c3b31792e9da8877856c52729e71f7412338387","build.rs":"aacb4f6af33623f070b53ae32dd7d91f8317861606d504b06bfb32a74ab70680","src/detection.rs":"794d0d720a4e0c92747c16086679ccd858f6e9f14ff1011f86196d1de808bbb6","src/fallback.rs":"bd91928a6c101727d844e2e047a223ca3312d12e144c71460c483de864c126e9","src/lib.rs":"c655c2ca8a023d4c69e93e6c154cb47f6392f74d9869ea7d7f3fe1623b6734e7","src/marker.rs":"87fce2d0357f5b7998b6d9dfb064f4a0cbc9dabb19e33d4b514a446243ebe2e8","src/parse.rs":"a7068413b1b7873543c704b9c494f47f94a7046553a6765e99d4a1ac4ae6501f","src/wrapper.rs":"624527eaa49c272824ab5f7286e6ecbdd80b6eac54e99be11b6e8b29dcb0015d","tests/comments.rs":"065132797580744767b7a854d5467757bd3433a990957f8dbccdfa779bfb275f","tests/features.rs":"a86deb8644992a4eb64d9fd493eff16f9cf9c5cb6ade3a634ce0c990cf87d559","tests/marker.rs":"cb6d776eba6a238d726b0f531883adf41957e06f2717ee8a069821c81e7081d6","tests/test.rs":"5ca52a1eb73ebe51368c3be1ad6898aa48dc8cfb1e76d170950c475b75dac743","tests/test_fmt.rs":"9357769945784354909259084ec8b34d2aa52081dd3967cac6dae3a5e3df3bc0"},"package":"ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43"} \ No newline at end of file diff --git a/vendor/proc-macro2/Cargo.toml b/vendor/proc-macro2/Cargo.toml index 901c787feb..d37fb6cc8e 100644 --- a/vendor/proc-macro2/Cargo.toml +++ b/vendor/proc-macro2/Cargo.toml @@ -11,16 +11,17 @@ [package] edition = "2018" +rust-version = "1.31" name = "proc-macro2" -version = "1.0.29" -authors = ["Alex Crichton <alex@alexcrichton.com>", "David Tolnay <dtolnay@gmail.com>"] +version = "1.0.32" +authors = ["David Tolnay <dtolnay@gmail.com>", "Alex Crichton <alex@alexcrichton.com>"] 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" readme = "README.md" keywords = ["macros"] categories = ["development-tools::procedural-macro-helpers"] license = "MIT OR Apache-2.0" -repository = "https://github.com/alexcrichton/proc-macro2" +repository = "https://github.com/dtolnay/proc-macro2" [package.metadata.docs.rs] rustc-args = ["--cfg", "procmacro2_semver_exempt"] rustdoc-args = ["--cfg", "procmacro2_semver_exempt", "--cfg", "doc_cfg"] diff --git a/vendor/proc-macro2/README.md b/vendor/proc-macro2/README.md index 3d05e871a7..35e1876212 100644 --- a/vendor/proc-macro2/README.md +++ b/vendor/proc-macro2/README.md @@ -1,8 +1,9 @@ # proc-macro2 -[![Build Status](https://img.shields.io/github/workflow/status/alexcrichton/proc-macro2/build%20and%20test)](https://github.com/alexcrichton/proc-macro2/actions) -[![Latest Version](https://img.shields.io/crates/v/proc-macro2.svg)](https://crates.io/crates/proc-macro2) -[![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/proc-macro2) +[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/proc--macro2-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/proc-macro2) +[<img alt="crates.io" src="https://img.shields.io/crates/v/proc-macro2.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/proc-macro2) +[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-proc--macro2-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K" height="20">](https://docs.rs/proc-macro2) +[<img alt="build status" src="https://img.shields.io/github/workflow/status/dtolnay/proc-macro2/CI/master?style=for-the-badge" height="20">](https://github.com/dtolnay/proc-macro2/actions?query=branch%3Amaster) A wrapper around the procedural macro API of the compiler's `proc_macro` crate. This library serves two purposes: diff --git a/vendor/proc-macro2/build.rs b/vendor/proc-macro2/build.rs index f32d5c8f0b..a25b42840f 100644 --- a/vendor/proc-macro2/build.rs +++ b/vendor/proc-macro2/build.rs @@ -33,6 +33,12 @@ // location of a token. Enabled by procmacro2_semver_exempt or the // "span-locations" Cargo cfg. This is behind a cfg because tracking // location inside spans is a performance hit. +// +// "is_available" +// Use proc_macro::is_available() to detect if the proc macro API is +// available or needs to be polyfilled instead of trying to use the proc +// macro API and catching a panic if it isn't available. Enabled on Rust +// 1.57+. use std::env; use std::iter; @@ -54,7 +60,7 @@ fn main() { let semver_exempt = cfg!(procmacro2_semver_exempt); if semver_exempt { - // https://github.com/alexcrichton/proc-macro2/issues/147 + // https://github.com/dtolnay/proc-macro2/issues/147 println!("cargo:rustc-cfg=procmacro2_semver_exempt"); } @@ -82,6 +88,10 @@ fn main() { println!("cargo:rustc-cfg=literal_from_str"); } + if version.minor >= 57 { + println!("cargo:rustc-cfg=is_available"); + } + let target = env::var("TARGET").unwrap(); if !enable_use_proc_macro(&target) { return; diff --git a/vendor/proc-macro2/src/detection.rs b/vendor/proc-macro2/src/detection.rs index c597bc99c6..c963abd7ca 100644 --- a/vendor/proc-macro2/src/detection.rs +++ b/vendor/proc-macro2/src/detection.rs @@ -1,5 +1,5 @@ use std::panic::{self, PanicInfo}; -use std::sync::atomic::*; +use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Once; static WORKS: AtomicUsize = AtomicUsize::new(0); @@ -24,6 +24,12 @@ pub(crate) fn unforce_fallback() { initialize(); } +#[cfg(feature = "is_available")] +fn initialize() { + let available = proc_macro::is_available(); + WORKS.store(available as usize + 1, Ordering::SeqCst); +} + // Swap in a null panic hook to avoid printing "thread panicked" to stderr, // then use catch_unwind to determine whether the compiler's proc_macro is // working. When proc-macro2 is used from outside of a procedural macro all @@ -48,6 +54,7 @@ pub(crate) fn unforce_fallback() { // here. For now, if a user needs to guarantee that this failure mode does // not occur, they need to call e.g. `proc_macro2::Span::call_site()` from // the main thread before launching any other threads. +#[cfg(not(feature = "is_available"))] fn initialize() { type PanicHook = dyn Fn(&PanicInfo) + Sync + Send + 'static; diff --git a/vendor/proc-macro2/src/fallback.rs b/vendor/proc-macro2/src/fallback.rs index 3d2feae151..ce878b21a1 100644 --- a/vendor/proc-macro2/src/fallback.rs +++ b/vendor/proc-macro2/src/fallback.rs @@ -65,7 +65,7 @@ impl TokenStream { } fn push_token(&mut self, token: TokenTree) { - // https://github.com/alexcrichton/proc-macro2/issues/235 + // https://github.com/dtolnay/proc-macro2/issues/235 match token { #[cfg(not(no_bind_by_move_pattern_guard))] TokenTree::Literal(crate::Literal { @@ -119,7 +119,7 @@ impl Drop for TokenStream { #[cfg(wrap_proc_macro)] let group = match group { crate::imp::Group::Fallback(group) => group, - _ => continue, + crate::imp::Group::Compiler(_) => continue, }; let mut group = group; self.inner.extend(group.stream.take_inner()); @@ -179,7 +179,7 @@ impl Display for TokenStream { Display::fmt(tt, f) } TokenTree::Literal(tt) => Display::fmt(tt, f), - }? + }?; } Ok(()) @@ -896,10 +896,20 @@ impl Literal { impl FromStr for Literal { type Err = LexError; - fn from_str(repr: &str) -> Result<Self, Self::Err> { + fn from_str(mut repr: &str) -> Result<Self, Self::Err> { + let negative = repr.starts_with('-'); + if negative { + repr = &repr[1..]; + if !repr.starts_with(|ch: char| ch.is_ascii_digit()) { + return Err(LexError::call_site()); + } + } let cursor = get_cursor(repr); - if let Ok((_rest, literal)) = parse::literal(cursor) { + if let Ok((_rest, mut literal)) = parse::literal(cursor) { if literal.text.len() == repr.len() { + if negative { + literal.text.insert(0, '-'); + } return Ok(literal); } } diff --git a/vendor/proc-macro2/src/lib.rs b/vendor/proc-macro2/src/lib.rs index 1d35bfd26e..b1a27aa4ef 100644 --- a/vendor/proc-macro2/src/lib.rs +++ b/vendor/proc-macro2/src/lib.rs @@ -1,3 +1,11 @@ +//! [![github]](https://github.com/dtolnay/proc-macro2) [![crates-io]](https://crates.io/crates/proc-macro2) [![docs-rs]](crate) +//! +//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github +//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust +//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K +//! +//! <br> +//! //! A wrapper around the procedural macro API of the compiler's [`proc_macro`] //! crate. This library serves two purposes: //! @@ -78,11 +86,25 @@ //! 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.29")] +#![doc(html_root_url = "https://docs.rs/proc-macro2/1.0.32")] #![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))] +#![cfg_attr(super_unstable, feature(proc_macro_def_site))] #![cfg_attr(doc_cfg, feature(doc_cfg))] -#![allow(clippy::needless_doctest_main, clippy::vec_init_then_push)] +#![allow( + clippy::cast_lossless, + clippy::cast_possible_truncation, + clippy::doc_markdown, + clippy::if_then_panic, + clippy::items_after_statements, + clippy::must_use_candidate, + clippy::needless_doctest_main, + clippy::shadow_unrelated, + clippy::trivially_copy_pass_by_ref, + clippy::unnecessary_wraps, + clippy::unused_self, + clippy::used_underscore_binding, + clippy::vec_init_then_push +)] #[cfg(use_proc_macro)] extern crate proc_macro; @@ -210,14 +232,14 @@ impl From<TokenTree> for TokenStream { impl Extend<TokenTree> for TokenStream { fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, streams: I) { - self.inner.extend(streams) + self.inner.extend(streams); } } impl Extend<TokenStream> for TokenStream { fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) { self.inner - .extend(streams.into_iter().map(|stream| stream.inner)) + .extend(streams.into_iter().map(|stream| stream.inner)); } } @@ -706,7 +728,7 @@ impl Group { /// by this group, but rather it will only set the span of the delimiter /// tokens at the level of the `Group`. pub fn set_span(&mut self, span: Span) { - self.inner.set_span(span.inner) + self.inner.set_span(span.inner); } } @@ -977,7 +999,7 @@ impl Ord for Ident { impl Hash for Ident { fn hash<H: Hasher>(&self, hasher: &mut H) { - self.to_string().hash(hasher) + self.to_string().hash(hasher); } } diff --git a/vendor/proc-macro2/src/parse.rs b/vendor/proc-macro2/src/parse.rs index eddb490164..e6e2b44dc1 100644 --- a/vendor/proc-macro2/src/parse.rs +++ b/vendor/proc-macro2/src/parse.rs @@ -621,8 +621,7 @@ fn float_digits(input: Cursor) -> Result<Cursor, Reject> { chars.next(); if chars .peek() - .map(|&ch| ch == '.' || is_ident_start(ch)) - .unwrap_or(false) + .map_or(false, |&ch| ch == '.' || is_ident_start(ch)) { return Err(Reject); } @@ -817,12 +816,12 @@ fn doc_comment(input: Cursor) -> PResult<Vec<TokenTree>> { TokenTree::Punct(Punct::new('=', Spacing::Alone)), TokenTree::Literal(crate::Literal::string(comment)), ]; - for tt in stream.iter_mut() { + for tt in &mut stream { tt.set_span(span); } let group = Group::new(Delimiter::Bracket, stream.into_iter().collect()); trees.push(crate::Group::_new_stable(group).into()); - for tt in trees.iter_mut() { + for tt in &mut trees { tt.set_span(span); } Ok((rest, trees)) diff --git a/vendor/proc-macro2/tests/comments.rs b/vendor/proc-macro2/tests/comments.rs index 708cccb880..71741080cd 100644 --- a/vendor/proc-macro2/tests/comments.rs +++ b/vendor/proc-macro2/tests/comments.rs @@ -1,16 +1,16 @@ use proc_macro2::{Delimiter, Literal, Spacing, TokenStream, TokenTree}; // #[doc = "..."] -> "..." -fn lit_of_outer_doc_comment(tokens: TokenStream) -> Literal { +fn lit_of_outer_doc_comment(tokens: &TokenStream) -> Literal { lit_of_doc_comment(tokens, false) } // #![doc = "..."] -> "..." -fn lit_of_inner_doc_comment(tokens: TokenStream) -> Literal { +fn lit_of_inner_doc_comment(tokens: &TokenStream) -> Literal { lit_of_doc_comment(tokens, true) } -fn lit_of_doc_comment(tokens: TokenStream, inner: bool) -> Literal { +fn lit_of_doc_comment(tokens: &TokenStream, inner: bool) -> Literal { let mut iter = tokens.clone().into_iter(); match iter.next().unwrap() { TokenTree::Punct(punct) => { @@ -71,30 +71,30 @@ fn incomplete() { #[test] fn lit() { let stream = "/// doc".parse::<TokenStream>().unwrap(); - let lit = lit_of_outer_doc_comment(stream); + let lit = lit_of_outer_doc_comment(&stream); assert_eq!(lit.to_string(), "\" doc\""); let stream = "//! doc".parse::<TokenStream>().unwrap(); - let lit = lit_of_inner_doc_comment(stream); + let lit = lit_of_inner_doc_comment(&stream); assert_eq!(lit.to_string(), "\" doc\""); let stream = "/** doc */".parse::<TokenStream>().unwrap(); - let lit = lit_of_outer_doc_comment(stream); + let lit = lit_of_outer_doc_comment(&stream); assert_eq!(lit.to_string(), "\" doc \""); let stream = "/*! doc */".parse::<TokenStream>().unwrap(); - let lit = lit_of_inner_doc_comment(stream); + let lit = lit_of_inner_doc_comment(&stream); assert_eq!(lit.to_string(), "\" doc \""); } #[test] fn carriage_return() { let stream = "///\r\n".parse::<TokenStream>().unwrap(); - let lit = lit_of_outer_doc_comment(stream); + let lit = lit_of_outer_doc_comment(&stream); assert_eq!(lit.to_string(), "\"\""); let stream = "/**\r\n*/".parse::<TokenStream>().unwrap(); - let lit = lit_of_outer_doc_comment(stream); + let lit = lit_of_outer_doc_comment(&stream); assert_eq!(lit.to_string(), "\"\\r\\n\""); "///\r".parse::<TokenStream>().unwrap_err(); diff --git a/vendor/proc-macro2/tests/marker.rs b/vendor/proc-macro2/tests/marker.rs index 70e57677cd..4fb2beb8e9 100644 --- a/vendor/proc-macro2/tests/marker.rs +++ b/vendor/proc-macro2/tests/marker.rs @@ -1,4 +1,6 @@ -use proc_macro2::*; +use proc_macro2::{ + Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree, +}; macro_rules! assert_impl { ($ty:ident is $($marker:ident) and +) => { @@ -51,7 +53,7 @@ assert_impl!(TokenTree is not Send or Sync); #[cfg(procmacro2_semver_exempt)] mod semver_exempt { - use super::*; + use proc_macro2::{LineColumn, SourceFile}; assert_impl!(LineColumn is Send and Sync); @@ -60,7 +62,11 @@ mod semver_exempt { #[cfg(not(no_libprocmacro_unwind_safe))] mod unwind_safe { - use super::*; + use proc_macro2::{ + Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree, + }; + #[cfg(procmacro2_semver_exempt)] + use proc_macro2::{LineColumn, SourceFile}; use std::panic::{RefUnwindSafe, UnwindSafe}; macro_rules! assert_unwind_safe { diff --git a/vendor/proc-macro2/tests/test.rs b/vendor/proc-macro2/tests/test.rs index 75a880f5ea..ab823907a6 100644 --- a/vendor/proc-macro2/tests/test.rs +++ b/vendor/proc-macro2/tests/test.rs @@ -1,3 +1,5 @@ +#![allow(clippy::non_ascii_literal)] + use proc_macro2::{Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; use std::panic; use std::str::{self, FromStr}; @@ -166,7 +168,11 @@ fn literal_iter_negative() { #[test] fn literal_parse() { assert!("1".parse::<Literal>().is_ok()); + assert!("-1".parse::<Literal>().is_ok()); + assert!("-1u12".parse::<Literal>().is_ok()); assert!("1.0".parse::<Literal>().is_ok()); + assert!("-1.0".parse::<Literal>().is_ok()); + assert!("-1.0f12".parse::<Literal>().is_ok()); assert!("'a'".parse::<Literal>().is_ok()); assert!("\"\n\"".parse::<Literal>().is_ok()); assert!("0 1".parse::<Literal>().is_err()); @@ -175,6 +181,9 @@ fn literal_parse() { assert!("/* comment */0".parse::<Literal>().is_err()); assert!("0/* comment */".parse::<Literal>().is_err()); assert!("0// comment".parse::<Literal>().is_err()); + assert!("- 1".parse::<Literal>().is_err()); + assert!("- 1.0".parse::<Literal>().is_err()); + assert!("-\"\"".parse::<Literal>().is_err()); } #[test] @@ -183,7 +192,7 @@ fn roundtrip() { println!("parse: {}", p); let s = p.parse::<TokenStream>().unwrap().to_string(); println!("first: {}", s); - let s2 = s.to_string().parse::<TokenStream>().unwrap().to_string(); + let s2 = s.parse::<TokenStream>().unwrap().to_string(); assert_eq!(s, s2); } roundtrip("a"); @@ -479,7 +488,7 @@ TokenStream [ #[test] fn default_tokenstream_is_empty() { - let default_token_stream: TokenStream = Default::default(); + let default_token_stream = <TokenStream as Default>::default(); assert!(default_token_stream.is_empty()); } diff --git a/vendor/proc-macro2/tests/test_fmt.rs b/vendor/proc-macro2/tests/test_fmt.rs index 99a0aee5c8..93dd19e3c6 100644 --- a/vendor/proc-macro2/tests/test_fmt.rs +++ b/vendor/proc-macro2/tests/test_fmt.rs @@ -1,3 +1,5 @@ +#![allow(clippy::from_iter_instead_of_collect)] + use proc_macro2::{Delimiter, Group, Ident, Span, TokenStream, TokenTree}; use std::iter::{self, FromIterator}; @@ -12,7 +14,7 @@ fn test_fmt_group() { let braces_empty = Group::new(Delimiter::Brace, TokenStream::new()); let braces_nonempty = Group::new(Delimiter::Brace, inner.clone()); let none_empty = Group::new(Delimiter::None, TokenStream::new()); - let none_nonempty = Group::new(Delimiter::None, inner.clone()); + let none_nonempty = Group::new(Delimiter::None, inner); // Matches libproc_macro. assert_eq!("()", parens_empty.to_string()); diff --git a/vendor/quote/.cargo-checksum.json b/vendor/quote/.cargo-checksum.json index 768055df4e..e0f72e40ca 100644 --- a/vendor/quote/.cargo-checksum.json +++ b/vendor/quote/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"d1e6bb8b4ac54b84f367a4e1b46e7dca3b1a744017d8f7fa2f4c11a8730e657a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","README.md":"9209682116de84bb9cc7be6ccf44478b46b909c7857f9e186d90bcff522af864","src/ext.rs":"a9fed3a1a4c9d3f2de717ba808af99291b995db2cbf8067f4b6927c39cc62bc6","src/format.rs":"a9c3e3a333c6dacf6e330d02b4c726862e273df1c2c6be6da199049cd1e521db","src/ident_fragment.rs":"e66a63f6e9020f2639a71f120d627bc6cfd60081a6caf8a1d735b59ee2413d29","src/lib.rs":"2500b1955d139e5b467df046cda4f2837fb1edace838aa190020752ab79314c4","src/runtime.rs":"f2d1fa6084764d98f98b96344cf675886a79b46a845c592e604f96bbde9aca07","src/spanned.rs":"adc0ed742ad17327c375879472d435cea168c208c303f53eb93cb2c0f10f3650","src/to_tokens.rs":"e589c1643479a9003d4dd1d9fa63714042b106f1b16d8ea3903cfe2f73a020f5","tests/compiletest.rs":"0a52a44786aea1c299c695bf948b2ed2081e4cc344e5c2cadceab4eb03d0010d","tests/test.rs":"6eb200350fa78405d4fd920ecf71d226e258c61aa88f850750efa99e065f06d6","tests/ui/does-not-have-iter-interpolated-dup.rs":"ad13eea21d4cdd2ab6c082f633392e1ff20fb0d1af5f2177041e0bf7f30da695","tests/ui/does-not-have-iter-interpolated.rs":"83a5b3f240651adcbe4b6e51076d76d653ad439b37442cf4054f1fd3c073f3b7","tests/ui/does-not-have-iter-separated.rs":"fe413c48331d5e3a7ae5fef6a5892a90c72f610d54595879eb49d0a94154ba3f","tests/ui/does-not-have-iter.rs":"09dc9499d861b63cebb0848b855b78e2dc9497bfde37ba6339f3625ae009a62f","tests/ui/not-quotable.rs":"5759d0884943417609f28faadc70254a3e2fd3d9bd6ff7297a3fb70a77fafd8a","tests/ui/not-repeatable.rs":"a4b115c04e4e41049a05f5b69450503fbffeba031218b4189cb931839f7f9a9c","tests/ui/wrong-type-span.rs":"5f310cb7fde3ef51bad01e7f286d244e3b6e67396cd2ea7eab77275c9d902699"},"package":"c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"} \ No newline at end of file +{"files":{"Cargo.toml":"4057136f408f566a2c06bcce49711d67bedcc8ce7a49351538086503afe59762","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","README.md":"9209682116de84bb9cc7be6ccf44478b46b909c7857f9e186d90bcff522af864","benches/bench.rs":"5dd3181a97b772e5691d4e6a48e00447250fa893fd63e49d154b519bc1b85fb9","src/ext.rs":"a9fed3a1a4c9d3f2de717ba808af99291b995db2cbf8067f4b6927c39cc62bc6","src/format.rs":"a9c3e3a333c6dacf6e330d02b4c726862e273df1c2c6be6da199049cd1e521db","src/ident_fragment.rs":"3ad27e331af8b54a4b97d19e7ae2bb45e01fb51dc410b24c083345ba6a0b20a8","src/lib.rs":"9c423facea42fe5c63763ba9a269d3f119865d43b4be16cb767ade7659e9356b","src/runtime.rs":"9257f094aefaefa4cf0653c39b5b72bb1922d8b8ac5f5cd45efb29e33acd0b98","src/spanned.rs":"adc0ed742ad17327c375879472d435cea168c208c303f53eb93cb2c0f10f3650","src/to_tokens.rs":"a351a680577d520ebb35905633c77533e8bc4b20642a5c438a51c94b2cc85145","tests/compiletest.rs":"0a52a44786aea1c299c695bf948b2ed2081e4cc344e5c2cadceab4eb03d0010d","tests/test.rs":"e2e829990115b51946d4776ade8eb65f3be1b9398b364bd3cfd4e1969b3a13be","tests/ui/does-not-have-iter-interpolated-dup.rs":"ad13eea21d4cdd2ab6c082f633392e1ff20fb0d1af5f2177041e0bf7f30da695","tests/ui/does-not-have-iter-interpolated-dup.stderr":"bd6a510c807eeda4c2207006d303bcc4bdb59b6122614d16af339ce1ac595449","tests/ui/does-not-have-iter-interpolated.rs":"83a5b3f240651adcbe4b6e51076d76d653ad439b37442cf4054f1fd3c073f3b7","tests/ui/does-not-have-iter-interpolated.stderr":"a0176a2091928037bba14a659d9619117b57112a4640e86466434a2a9cd2e362","tests/ui/does-not-have-iter-separated.rs":"fe413c48331d5e3a7ae5fef6a5892a90c72f610d54595879eb49d0a94154ba3f","tests/ui/does-not-have-iter-separated.stderr":"19287dc8cba743d89996c2d3ded0d5df292f591e6c148a92ea5e9e23d1250837","tests/ui/does-not-have-iter.rs":"09dc9499d861b63cebb0848b855b78e2dc9497bfde37ba6339f3625ae009a62f","tests/ui/does-not-have-iter.stderr":"fb595f24e0a133f705cf585692206ed9dce59b2872cc11eed9bf0ebc184c1d20","tests/ui/not-quotable.rs":"5759d0884943417609f28faadc70254a3e2fd3d9bd6ff7297a3fb70a77fafd8a","tests/ui/not-quotable.stderr":"2ed46f3d6975cc48852b63ece071fd170628c8bd4a4e89e3bb7b156dd139248b","tests/ui/not-repeatable.rs":"a4b115c04e4e41049a05f5b69450503fbffeba031218b4189cb931839f7f9a9c","tests/ui/not-repeatable.stderr":"49991d2b634c8620eb7c76653e2c546223baa473031b0fb4784eb2355f8e6b65","tests/ui/wrong-type-span.rs":"5f310cb7fde3ef51bad01e7f286d244e3b6e67396cd2ea7eab77275c9d902699","tests/ui/wrong-type-span.stderr":"6672d2c5995fe188228c2b24630a3ad658c27383accc03cdf90c30923eaf6906"},"package":"38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"} \ No newline at end of file diff --git a/vendor/quote/Cargo.toml b/vendor/quote/Cargo.toml index 411f943ab4..835d1a263d 100644 --- a/vendor/quote/Cargo.toml +++ b/vendor/quote/Cargo.toml @@ -3,19 +3,18 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies +# to registry (e.g., crates.io) dependencies. # -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. [package] edition = "2018" +rust-version = "1.31" name = "quote" -version = "1.0.9" +version = "1.0.10" authors = ["David Tolnay <dtolnay@gmail.com>"] -include = ["Cargo.toml", "src/**/*.rs", "tests/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] description = "Quasi-quoting macro quote!(...)" documentation = "https://docs.rs/quote/" readme = "README.md" diff --git a/vendor/quote/benches/bench.rs b/vendor/quote/benches/bench.rs new file mode 100644 index 0000000000..ed91508641 --- /dev/null +++ b/vendor/quote/benches/bench.rs @@ -0,0 +1,192 @@ +#![feature(test)] + +extern crate test; + +use quote::quote; +use test::Bencher; + +#[bench] +fn bench_impl(b: &mut Bencher) { + b.iter(|| { + quote! { + impl<'de> _serde::Deserialize<'de> for Response { + fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error> + where + __D: _serde::Deserializer<'de>, + { + #[allow(non_camel_case_types)] + enum __Field { + __field0, + __field1, + __ignore, + } + struct __FieldVisitor; + impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { + type Value = __Field; + fn expecting( + &self, + __formatter: &mut _serde::export::Formatter, + ) -> _serde::export::fmt::Result { + _serde::export::Formatter::write_str(__formatter, "field identifier") + } + fn visit_u64<__E>(self, __value: u64) -> _serde::export::Result<Self::Value, __E> + where + __E: _serde::de::Error, + { + match __value { + 0u64 => _serde::export::Ok(__Field::__field0), + 1u64 => _serde::export::Ok(__Field::__field1), + _ => _serde::export::Err(_serde::de::Error::invalid_value( + _serde::de::Unexpected::Unsigned(__value), + &"field index 0 <= i < 2", + )), + } + } + fn visit_str<__E>(self, __value: &str) -> _serde::export::Result<Self::Value, __E> + where + __E: _serde::de::Error, + { + match __value { + "id" => _serde::export::Ok(__Field::__field0), + "s" => _serde::export::Ok(__Field::__field1), + _ => _serde::export::Ok(__Field::__ignore), + } + } + fn visit_bytes<__E>( + self, + __value: &[u8], + ) -> _serde::export::Result<Self::Value, __E> + where + __E: _serde::de::Error, + { + match __value { + b"id" => _serde::export::Ok(__Field::__field0), + b"s" => _serde::export::Ok(__Field::__field1), + _ => _serde::export::Ok(__Field::__ignore), + } + } + } + impl<'de> _serde::Deserialize<'de> for __Field { + #[inline] + fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error> + where + __D: _serde::Deserializer<'de>, + { + _serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor) + } + } + struct __Visitor<'de> { + marker: _serde::export::PhantomData<Response>, + lifetime: _serde::export::PhantomData<&'de ()>, + } + impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> { + type Value = Response; + fn expecting( + &self, + __formatter: &mut _serde::export::Formatter, + ) -> _serde::export::fmt::Result { + _serde::export::Formatter::write_str(__formatter, "struct Response") + } + #[inline] + fn visit_seq<__A>( + self, + mut __seq: __A, + ) -> _serde::export::Result<Self::Value, __A::Error> + where + __A: _serde::de::SeqAccess<'de>, + { + let __field0 = + match try!(_serde::de::SeqAccess::next_element::<u64>(&mut __seq)) { + _serde::export::Some(__value) => __value, + _serde::export::None => { + return _serde::export::Err(_serde::de::Error::invalid_length( + 0usize, + &"struct Response with 2 elements", + )); + } + }; + let __field1 = + match try!(_serde::de::SeqAccess::next_element::<String>(&mut __seq)) { + _serde::export::Some(__value) => __value, + _serde::export::None => { + return _serde::export::Err(_serde::de::Error::invalid_length( + 1usize, + &"struct Response with 2 elements", + )); + } + }; + _serde::export::Ok(Response { + id: __field0, + s: __field1, + }) + } + #[inline] + fn visit_map<__A>( + self, + mut __map: __A, + ) -> _serde::export::Result<Self::Value, __A::Error> + where + __A: _serde::de::MapAccess<'de>, + { + let mut __field0: _serde::export::Option<u64> = _serde::export::None; + let mut __field1: _serde::export::Option<String> = _serde::export::None; + while let _serde::export::Some(__key) = + try!(_serde::de::MapAccess::next_key::<__Field>(&mut __map)) + { + match __key { + __Field::__field0 => { + if _serde::export::Option::is_some(&__field0) { + return _serde::export::Err( + <__A::Error as _serde::de::Error>::duplicate_field("id"), + ); + } + __field0 = _serde::export::Some( + try!(_serde::de::MapAccess::next_value::<u64>(&mut __map)), + ); + } + __Field::__field1 => { + if _serde::export::Option::is_some(&__field1) { + return _serde::export::Err( + <__A::Error as _serde::de::Error>::duplicate_field("s"), + ); + } + __field1 = _serde::export::Some( + try!(_serde::de::MapAccess::next_value::<String>(&mut __map)), + ); + } + _ => { + let _ = try!(_serde::de::MapAccess::next_value::< + _serde::de::IgnoredAny, + >(&mut __map)); + } + } + } + let __field0 = match __field0 { + _serde::export::Some(__field0) => __field0, + _serde::export::None => try!(_serde::private::de::missing_field("id")), + }; + let __field1 = match __field1 { + _serde::export::Some(__field1) => __field1, + _serde::export::None => try!(_serde::private::de::missing_field("s")), + }; + _serde::export::Ok(Response { + id: __field0, + s: __field1, + }) + } + } + const FIELDS: &'static [&'static str] = &["id", "s"]; + _serde::Deserializer::deserialize_struct( + __deserializer, + "Response", + FIELDS, + __Visitor { + marker: _serde::export::PhantomData::<Response>, + lifetime: _serde::export::PhantomData, + }, + ) + } + } + } + }); +} diff --git a/vendor/quote/src/ident_fragment.rs b/vendor/quote/src/ident_fragment.rs index e7472fe114..67e2e3393c 100644 --- a/vendor/quote/src/ident_fragment.rs +++ b/vendor/quote/src/ident_fragment.rs @@ -79,7 +79,7 @@ macro_rules! ident_fragment_display { } } )* - } + }; } ident_fragment_display!(bool, str, String, char); diff --git a/vendor/quote/src/lib.rs b/vendor/quote/src/lib.rs index 356e43a052..1dad8a14be 100644 --- a/vendor/quote/src/lib.rs +++ b/vendor/quote/src/lib.rs @@ -81,12 +81,14 @@ //! ``` // Quote types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/quote/1.0.9")] +#![doc(html_root_url = "https://docs.rs/quote/1.0.10")] #![allow( clippy::doc_markdown, clippy::missing_errors_doc, clippy::missing_panics_doc, - clippy::module_name_repetitions + clippy::module_name_repetitions, + // false positive https://github.com/rust-lang/rust-clippy/issues/6983 + clippy::wrong_self_convention, )] #[cfg(all( @@ -743,9 +745,15 @@ macro_rules! quote_token_with_context { // warnings on anything below the loop. We use has_iter to detect and // fail to compile when there are no iterators, so here we just work // around the unneeded extra warning. - while true { + // + // FIXME: temporariliy working around Clippy regression. + // https://github.com/rust-lang/rust-clippy/issues/7768 + loop { $crate::pounded_var_names!(quote_bind_next_or_break!() () $($inner)*); $crate::quote_each_token!($tokens $($inner)*); + if false { + break; + } } }}; ($tokens:ident $b3:tt $b2:tt # (( $($inner:tt)* )) * $a2:tt $a3:tt) => {}; @@ -757,13 +765,16 @@ macro_rules! quote_token_with_context { let has_iter = $crate::__private::ThereIsNoIteratorInRepetition; $crate::pounded_var_names!(quote_bind_into_iter!(has_iter) () $($inner)*); let _: $crate::__private::HasIterator = has_iter; - while true { + loop { $crate::pounded_var_names!(quote_bind_next_or_break!() () $($inner)*); if _i > 0 { $crate::quote_token!($tokens $sep); } _i += 1; $crate::quote_each_token!($tokens $($inner)*); + if false { + break; + } } }}; ($tokens:ident $b3:tt $b2:tt # (( $($inner:tt)* )) $sep:tt * $a3:tt) => {}; @@ -799,9 +810,15 @@ macro_rules! quote_token_with_context_spanned { // warnings on anything below the loop. We use has_iter to detect and // fail to compile when there are no iterators, so here we just work // around the unneeded extra warning. - while true { + // + // FIXME: temporariliy working around Clippy regression. + // https://github.com/rust-lang/rust-clippy/issues/7768 + loop { $crate::pounded_var_names!(quote_bind_next_or_break!() () $($inner)*); $crate::quote_each_token_spanned!($tokens $span $($inner)*); + if false { + break; + } } }}; ($tokens:ident $span:ident $b3:tt $b2:tt # (( $($inner:tt)* )) * $a2:tt $a3:tt) => {}; @@ -813,13 +830,16 @@ macro_rules! quote_token_with_context_spanned { let has_iter = $crate::__private::ThereIsNoIteratorInRepetition; $crate::pounded_var_names!(quote_bind_into_iter!(has_iter) () $($inner)*); let _: $crate::__private::HasIterator = has_iter; - while true { + loop { $crate::pounded_var_names!(quote_bind_next_or_break!() () $($inner)*); if _i > 0 { $crate::quote_token_spanned!($tokens $span $sep); } _i += 1; $crate::quote_each_token_spanned!($tokens $span $($inner)*); + if false { + break; + } } }}; ($tokens:ident $span:ident $b3:tt $b2:tt # (( $($inner:tt)* )) $sep:tt * $a3:tt) => {}; diff --git a/vendor/quote/src/runtime.rs b/vendor/quote/src/runtime.rs index db3b6a93d9..92e00f78bf 100644 --- a/vendor/quote/src/runtime.rs +++ b/vendor/quote/src/runtime.rs @@ -123,25 +123,6 @@ pub mod ext { } } - macro_rules! array_rep_slice { - ($($l:tt)*) => { - $( - impl<'q, T: 'q> RepAsIteratorExt<'q> for [T; $l] { - type Iter = slice::Iter<'q, T>; - - fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) { - (self.iter(), HasIter) - } - } - )* - } - } - - array_rep_slice!( - 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 - ); - impl<'q, T: RepAsIteratorExt<'q>> RepAsIteratorExt<'q> for RepInterp<T> { type Iter = T::Iter; diff --git a/vendor/quote/src/to_tokens.rs b/vendor/quote/src/to_tokens.rs index 7f98083963..dbb8dfc36e 100644 --- a/vendor/quote/src/to_tokens.rs +++ b/vendor/quote/src/to_tokens.rs @@ -127,13 +127,15 @@ impl ToTokens for String { } macro_rules! primitive { - ($($t:ident => $name:ident)*) => ($( - impl ToTokens for $t { - fn to_tokens(&self, tokens: &mut TokenStream) { - tokens.append(Literal::$name(*self)); + ($($t:ident => $name:ident)*) => { + $( + impl ToTokens for $t { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.append(Literal::$name(*self)); + } } - } - )*) + )* + }; } primitive! { diff --git a/vendor/quote/tests/test.rs b/vendor/quote/tests/test.rs index d5a3490c3d..ca633283b1 100644 --- a/vendor/quote/tests/test.rs +++ b/vendor/quote/tests/test.rs @@ -1,4 +1,10 @@ -#![cfg_attr(feature = "cargo-clippy", allow(blacklisted_name))] +#![allow( + clippy::blacklisted_name, + clippy::let_underscore_drop, + clippy::shadow_unrelated, + clippy::unseparated_literal_suffix, + clippy::used_underscore_binding +)] use std::borrow::Cow; use std::collections::BTreeSet; @@ -78,6 +84,27 @@ fn test_iter() { assert_eq!("X , X , X , X", quote!(#(#primes),*).to_string()); } +#[test] +fn test_array() { + let array: [u8; 40] = [0; 40]; + let _ = quote!(#(#array #array)*); + + let ref_array: &[u8; 40] = &[0; 40]; + let _ = quote!(#(#ref_array #ref_array)*); + + let ref_slice: &[u8] = &[0; 40]; + let _ = quote!(#(#ref_slice #ref_slice)*); + + let array: [X; 2] = [X, X]; // !Copy + let _ = quote!(#(#array #array)*); + + let ref_array: &[X; 2] = &[X, X]; + let _ = quote!(#(#ref_array #ref_array)*); + + let ref_slice: &[X] = &[X, X]; + let _ = quote!(#(#ref_slice #ref_slice)*); +} + #[test] fn test_advanced() { let generics = quote!( <'a, T> ); diff --git a/vendor/quote/tests/ui/does-not-have-iter-interpolated-dup.stderr b/vendor/quote/tests/ui/does-not-have-iter-interpolated-dup.stderr new file mode 100644 index 0000000000..176f828895 --- /dev/null +++ b/vendor/quote/tests/ui/does-not-have-iter-interpolated-dup.stderr @@ -0,0 +1,10 @@ +error[E0308]: mismatched types + --> $DIR/does-not-have-iter-interpolated-dup.rs:8:5 + | +8 | quote!(#(#nonrep #nonrep)*); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected struct `HasIterator`, found struct `ThereIsNoIteratorInRepetition` + | expected due to this + | + = note: this error originates in the macro `$crate::quote_token_with_context` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/vendor/quote/tests/ui/does-not-have-iter-interpolated.stderr b/vendor/quote/tests/ui/does-not-have-iter-interpolated.stderr new file mode 100644 index 0000000000..40c9eb8708 --- /dev/null +++ b/vendor/quote/tests/ui/does-not-have-iter-interpolated.stderr @@ -0,0 +1,10 @@ +error[E0308]: mismatched types + --> $DIR/does-not-have-iter-interpolated.rs:8:5 + | +8 | quote!(#(#nonrep)*); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | expected struct `HasIterator`, found struct `ThereIsNoIteratorInRepetition` + | expected due to this + | + = note: this error originates in the macro `$crate::quote_token_with_context` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/vendor/quote/tests/ui/does-not-have-iter-separated.stderr b/vendor/quote/tests/ui/does-not-have-iter-separated.stderr new file mode 100644 index 0000000000..8a8a805daf --- /dev/null +++ b/vendor/quote/tests/ui/does-not-have-iter-separated.stderr @@ -0,0 +1,10 @@ +error[E0308]: mismatched types + --> $DIR/does-not-have-iter-separated.rs:4:5 + | +4 | quote!(#(a b),*); + | ^^^^^^^^^^^^^^^^^ + | | + | expected struct `HasIterator`, found struct `ThereIsNoIteratorInRepetition` + | expected due to this + | + = note: this error originates in the macro `$crate::quote_token_with_context` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/vendor/quote/tests/ui/does-not-have-iter.stderr b/vendor/quote/tests/ui/does-not-have-iter.stderr new file mode 100644 index 0000000000..17871bf31f --- /dev/null +++ b/vendor/quote/tests/ui/does-not-have-iter.stderr @@ -0,0 +1,10 @@ +error[E0308]: mismatched types + --> $DIR/does-not-have-iter.rs:4:5 + | +4 | quote!(#(a b)*); + | ^^^^^^^^^^^^^^^^ + | | + | expected struct `HasIterator`, found struct `ThereIsNoIteratorInRepetition` + | expected due to this + | + = note: this error originates in the macro `$crate::quote_token_with_context` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/vendor/quote/tests/ui/not-quotable.stderr b/vendor/quote/tests/ui/not-quotable.stderr new file mode 100644 index 0000000000..c70c548f21 --- /dev/null +++ b/vendor/quote/tests/ui/not-quotable.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `Ipv4Addr: ToTokens` is not satisfied + --> $DIR/not-quotable.rs:6:13 + | +6 | let _ = quote! { #ip }; + | ^^^^^^^^^^^^^^ + | | + | the trait `ToTokens` is not implemented for `Ipv4Addr` + | required by a bound introduced by this call + | +note: required by `to_tokens` + --> $DIR/to_tokens.rs:55:5 + | +55 | fn to_tokens(&self, tokens: &mut TokenStream); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `$crate::quote_token_with_context` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/vendor/quote/tests/ui/not-repeatable.stderr b/vendor/quote/tests/ui/not-repeatable.stderr new file mode 100644 index 0000000000..94b8b8769f --- /dev/null +++ b/vendor/quote/tests/ui/not-repeatable.stderr @@ -0,0 +1,25 @@ +error[E0599]: the method `quote_into_iter` exists for struct `Ipv4Addr`, but its trait bounds were not satisfied + --> $DIR/not-repeatable.rs:7:13 + | +3 | struct Ipv4Addr; + | ---------------- + | | + | method `quote_into_iter` not found for this + | doesn't satisfy `Ipv4Addr: Iterator` + | doesn't satisfy `Ipv4Addr: ToTokens` + | doesn't satisfy `Ipv4Addr: quote::__private::ext::RepIteratorExt` + | doesn't satisfy `Ipv4Addr: quote::__private::ext::RepToTokensExt` +... +7 | let _ = quote! { #(#ip)* }; + | ^^^^^^^^^^^^^^^^^^ method cannot be called on `Ipv4Addr` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `Ipv4Addr: Iterator` + which is required by `Ipv4Addr: quote::__private::ext::RepIteratorExt` + `&Ipv4Addr: Iterator` + which is required by `&Ipv4Addr: quote::__private::ext::RepIteratorExt` + `Ipv4Addr: ToTokens` + which is required by `Ipv4Addr: quote::__private::ext::RepToTokensExt` + `&mut Ipv4Addr: Iterator` + which is required by `&mut Ipv4Addr: quote::__private::ext::RepIteratorExt` + = note: this error originates in the macro `$crate::quote_bind_into_iter` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/vendor/quote/tests/ui/wrong-type-span.stderr b/vendor/quote/tests/ui/wrong-type-span.stderr new file mode 100644 index 0000000000..6ac7b1a88f --- /dev/null +++ b/vendor/quote/tests/ui/wrong-type-span.stderr @@ -0,0 +1,8 @@ +error[E0308]: mismatched types + --> $DIR/wrong-type-span.rs:6:20 + | +6 | quote_spanned!(span=> #x); + | ---------------^^^^------- + | | | + | | expected struct `Span`, found `&str` + | expected due to this diff --git a/vendor/semver/.cargo-checksum.json b/vendor/semver/.cargo-checksum.json new file mode 100644 index 0000000000..d720b7227b --- /dev/null +++ b/vendor/semver/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"7cb02e1ff7ead40d52d571c10e12863efba33e29a6906516ab80e2771de226f2","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"bf8425471508b8e2b4bca009f9deefd48f79348becaaf8a9931c65fbfd22759e","benches/parse.rs":"6531f66f80ce2fc83878f9bf84f94c42e96f1e709466f2b88be8d95a3cec1511","build.rs":"9363637392638793f1a2b76b03c6e43d2f54efea90d0088f955d841e278f104e","src/backport.rs":"ed977aeb67741cf01ed00bbbfb9130b662b7f572478d326b1350aa7175db6cf0","src/display.rs":"9ba42f7a6579aa9c7dd72f2380036f5c9664592f3eacd09ea25cef291a3e64e5","src/error.rs":"d4291e0052c2456067ff808f7c289405a2b9ed54a3171c917d125a51324850dd","src/eval.rs":"b7e7ec976051b9f87ddf5cfdbaad64654d98d86ae0763f7d88b14eeaeac6013c","src/identifier.rs":"20e943b23e4492ffcd829dd05c4af92dc8d01a351c6a031cd274363ce0779ee0","src/impls.rs":"79b5a2ac6ca3d4cb46adfb1494756079f53bef780dd81c3a8d3adf86f91395c8","src/lib.rs":"829fce134eedb419f3e71419e1661846ad8390ffe79a7fbb78dd6d041f03f8fe","src/parse.rs":"3fda94d255283e5406d6a4ecc5e0d654ab3751bfd80c76f359f2439a532221c3","src/serde.rs":"970d343a6bac21ddd965168d3cc2af9998796bf29bf545e8b37c6bcdd97d9710","tests/node/mod.rs":"2a4a43f5ce8dd5dc1a0c1d62418f7a4935ef49d4361b79c4b4314c97386e6201","tests/test_identifier.rs":"a4723f61735b77b8f560039618b96e815ce4a54518a2dfe95da3375efe59a7e4","tests/test_version.rs":"e8dbfaea495d18867bbbb48af2f62fe199b01238640b01efd7ee2760a6d90490","tests/test_version_req.rs":"cecb8e1d0011516d50bf3be9dd26831bd8c08ecb2b964a51b6d818b35fa45e5b","tests/util/mod.rs":"db61c2cd86af864d8be4f2a3d5f25c86d7712201cc6ab47b715facf5f7f275b7"},"package":"568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012"} \ No newline at end of file diff --git a/vendor/semver/Cargo.toml b/vendor/semver/Cargo.toml new file mode 100644 index 0000000000..fb868d7be6 --- /dev/null +++ b/vendor/semver/Cargo.toml @@ -0,0 +1,32 @@ +# 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 are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +name = "semver" +version = "1.0.4" +authors = ["David Tolnay <dtolnay@gmail.com>"] +description = "Parser and evaluator for Cargo's flavor of Semantic Versioning" +documentation = "https://docs.rs/semver" +readme = "README.md" +license = "MIT OR Apache-2.0" +repository = "https://github.com/dtolnay/semver" +[package.metadata.docs.rs] +rustdoc-args = ["--cfg", "doc_cfg"] +targets = ["x86_64-unknown-linux-gnu"] +[dependencies.serde] +version = "1.0" +optional = true +default-features = false + +[features] +default = ["std"] +std = [] diff --git a/vendor/semver/LICENSE-APACHE b/vendor/semver/LICENSE-APACHE new file mode 100644 index 0000000000..16fe87b06e --- /dev/null +++ b/vendor/semver/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/vendor/semver/LICENSE-MIT b/vendor/semver/LICENSE-MIT new file mode 100644 index 0000000000..31aa79387f --- /dev/null +++ b/vendor/semver/LICENSE-MIT @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/vendor/semver/README.md b/vendor/semver/README.md new file mode 100644 index 0000000000..109efa3785 --- /dev/null +++ b/vendor/semver/README.md @@ -0,0 +1,84 @@ +semver +====== + +[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/semver-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/semver) +[<img alt="crates.io" src="https://img.shields.io/crates/v/semver.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/semver) +[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-semver-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K" height="20">](https://docs.rs/semver/1.0.0) +[<img alt="build status" src="https://img.shields.io/github/workflow/status/dtolnay/semver/CI/master?style=for-the-badge" height="20">](https://github.com/dtolnay/semver/actions?query=branch%3Amaster) + +A parser and evaluator for Cargo's flavor of Semantic Versioning. + +Semantic Versioning (see <https://semver.org>) is a guideline for how version +numbers are assigned and incremented. It is widely followed within the +Cargo/crates.io ecosystem for Rust. + +```toml +[dependencies] +semver = "1.0" +``` + +*Compiler support: requires rustc 1.31+* + +<br> + +## Example + +```rust +use semver::{BuildMetadata, Prerelease, Version, VersionReq}; + +fn main() { + let req = VersionReq::parse(">=1.2.3, <1.8.0").unwrap(); + + // Check whether this requirement matches version 1.2.3-alpha.1 (no) + let version = Version { + major: 1, + minor: 2, + patch: 3, + pre: Prerelease::new("alpha.1").unwrap(), + build: BuildMetadata::EMPTY, + }; + assert!(!req.matches(&version)); + + // Check whether it matches 1.3.0 (yes it does) + let version = Version::parse("1.3.0").unwrap(); + assert!(req.matches(&version)); +} +``` + +<br> + +## Scope of this crate + +Besides Cargo, several other package ecosystems and package managers for other +languages also use SemVer: RubyGems/Bundler for Ruby, npm for JavaScript, +Composer for PHP, CocoaPods for Objective-C... + +The `semver` crate is specifically intended to implement Cargo's interpretation +of Semantic Versioning. + +Where the various tools differ in their interpretation or implementation of the +spec, this crate follows the implementation choices made by Cargo. If you are +operating on version numbers from some other package ecosystem, you will want to +use a different semver library which is appropriate to that ecosystem. + +The extent of Cargo's SemVer support is documented in the *[Specifying +Dependencies]* chapter of the Cargo reference. + +[Specifying Dependencies]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html + +<br> + +#### License + +<sup> +Licensed under either of <a href="LICENSE-APACHE">Apache License, Version +2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option. +</sup> + +<br> + +<sub> +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in this crate by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. +</sub> diff --git a/vendor/semver/benches/parse.rs b/vendor/semver/benches/parse.rs new file mode 100644 index 0000000000..d6aded7802 --- /dev/null +++ b/vendor/semver/benches/parse.rs @@ -0,0 +1,24 @@ +#![feature(test)] + +extern crate test; + +use semver::{Prerelease, Version, VersionReq}; +use test::{black_box, Bencher}; + +#[bench] +fn parse_prerelease(b: &mut Bencher) { + let text = "x.7.z.92"; + b.iter(|| black_box(text).parse::<Prerelease>().unwrap()); +} + +#[bench] +fn parse_version(b: &mut Bencher) { + let text = "1.0.2021-beta+exp.sha.5114f85"; + b.iter(|| black_box(text).parse::<Version>().unwrap()); +} + +#[bench] +fn parse_version_req(b: &mut Bencher) { + let text = ">=1.2.3, <2.0.0"; + b.iter(|| black_box(text).parse::<VersionReq>().unwrap()); +} diff --git a/vendor/semver/build.rs b/vendor/semver/build.rs new file mode 100644 index 0000000000..b39468d261 --- /dev/null +++ b/vendor/semver/build.rs @@ -0,0 +1,79 @@ +use std::env; +use std::process::Command; +use std::str; + +fn main() { + let compiler = match rustc_minor_version() { + Some(compiler) => compiler, + None => return, + }; + + if compiler < 32 { + // u64::from_ne_bytes. + // https://doc.rust-lang.org/std/primitive.u64.html#method.from_ne_bytes + println!("cargo:rustc-cfg=no_from_ne_bytes"); + } + + if compiler < 33 { + // Exhaustive integer patterns. On older compilers, a final `_` arm is + // required even if every possible integer value is otherwise covered. + // https://github.com/rust-lang/rust/issues/50907 + println!("cargo:rustc-cfg=no_exhaustive_int_match"); + } + + if compiler < 36 { + // extern crate alloc. + // https://blog.rust-lang.org/2019/07/04/Rust-1.36.0.html#the-alloc-crate-is-stable + println!("cargo:rustc-cfg=no_alloc_crate"); + } + + if compiler < 39 { + // const Vec::new. + // https://doc.rust-lang.org/std/vec/struct.Vec.html#method.new + println!("cargo:rustc-cfg=no_const_vec_new"); + } + + if compiler < 40 { + // #[non_exhaustive]. + // https://blog.rust-lang.org/2019/12/19/Rust-1.40.0.html#non_exhaustive-structs-enums-and-variants + println!("cargo:rustc-cfg=no_non_exhaustive"); + } + + if compiler < 45 { + // String::strip_prefix. + // https://doc.rust-lang.org/std/primitive.str.html#method.repeat + println!("cargo:rustc-cfg=no_str_strip_prefix"); + } + + if compiler < 46 { + // #[track_caller]. + // https://blog.rust-lang.org/2020/08/27/Rust-1.46.0.html#track_caller + println!("cargo:rustc-cfg=no_track_caller"); + } + + if compiler < 52 { + // #![deny(unsafe_op_in_unsafe_fn)]. + // https://github.com/rust-lang/rust/issues/71668 + println!("cargo:rustc-cfg=no_unsafe_op_in_unsafe_fn_lint"); + } + + if compiler < 53 { + // Efficient intrinsics for count-leading-zeros and count-trailing-zeros + // on NonZero integers stabilized in 1.53.0. On many architectures these + // are more efficient than counting zeros on ordinary zeroable integers. + // https://doc.rust-lang.org/std/num/struct.NonZeroU64.html#method.leading_zeros + // https://doc.rust-lang.org/std/num/struct.NonZeroU64.html#method.trailing_zeros + println!("cargo:rustc-cfg=no_nonzero_bitscan"); + } +} + +fn rustc_minor_version() -> Option<u32> { + let rustc = env::var_os("RUSTC")?; + let output = Command::new(rustc).arg("--version").output().ok()?; + let version = str::from_utf8(&output.stdout).ok()?; + let mut pieces = version.split('.'); + if pieces.next() != Some("rustc 1") { + return None; + } + pieces.next()?.parse().ok() +} diff --git a/vendor/semver/src/backport.rs b/vendor/semver/src/backport.rs new file mode 100644 index 0000000000..f3a69c9528 --- /dev/null +++ b/vendor/semver/src/backport.rs @@ -0,0 +1,63 @@ +#[cfg(no_str_strip_prefix)] // rustc <1.45 +pub(crate) trait StripPrefixExt { + fn strip_prefix(&self, ch: char) -> Option<&str>; +} + +#[cfg(no_str_strip_prefix)] +impl StripPrefixExt for str { + fn strip_prefix(&self, ch: char) -> Option<&str> { + if self.starts_with(ch) { + Some(&self[ch.len_utf8()..]) + } else { + None + } + } +} + +#[cfg(no_from_ne_bytes)] // rustc <1.32 +pub(crate) trait FromNeBytes { + fn from_ne_bytes(bytes: [u8; 8]) -> Self; +} + +#[cfg(no_from_ne_bytes)] +impl FromNeBytes for u64 { + fn from_ne_bytes(bytes: [u8; 8]) -> Self { + unsafe { std::mem::transmute(bytes) } + } +} + +pub(crate) use crate::alloc::vec::Vec; + +#[cfg(no_alloc_crate)] // rustc <1.36 +pub(crate) mod alloc { + pub use std::vec; + + pub mod alloc { + use std::mem; + + pub struct Layout { + size: usize, + } + + impl Layout { + pub unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self { + assert_eq!(align, 2); + Layout { size } + } + } + + pub unsafe fn alloc(layout: Layout) -> *mut u8 { + let len_u16 = (layout.size + 1) / 2; + let mut vec = Vec::new(); + vec.reserve_exact(len_u16); + let ptr: *mut u16 = vec.as_mut_ptr(); + mem::forget(vec); + ptr as *mut u8 + } + + pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) { + let len_u16 = (layout.size + 1) / 2; + unsafe { Vec::from_raw_parts(ptr as *mut u16, 0, len_u16) }; + } + } +} diff --git a/vendor/semver/src/display.rs b/vendor/semver/src/display.rs new file mode 100644 index 0000000000..3c2871bb97 --- /dev/null +++ b/vendor/semver/src/display.rs @@ -0,0 +1,165 @@ +use crate::{BuildMetadata, Comparator, Op, Prerelease, Version, VersionReq}; +use core::fmt::{self, Alignment, Debug, Display, Write}; + +impl Display for Version { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + let do_display = |formatter: &mut fmt::Formatter| -> fmt::Result { + write!(formatter, "{}.{}.{}", self.major, self.minor, self.patch)?; + if !self.pre.is_empty() { + write!(formatter, "-{}", self.pre)?; + } + if !self.build.is_empty() { + write!(formatter, "+{}", self.build)?; + } + Ok(()) + }; + + let do_len = || -> usize { + digits(self.major) + + 1 + + digits(self.minor) + + 1 + + digits(self.patch) + + !self.pre.is_empty() as usize + + self.pre.len() + + !self.build.is_empty() as usize + + self.build.len() + }; + + pad(formatter, do_display, do_len) + } +} + +impl Display for VersionReq { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + if self.comparators.is_empty() { + return formatter.write_str("*"); + } + for (i, comparator) in self.comparators.iter().enumerate() { + if i > 0 { + formatter.write_str(", ")?; + } + write!(formatter, "{}", comparator)?; + } + Ok(()) + } +} + +impl Display for Comparator { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + let op = match self.op { + Op::Exact => "=", + Op::Greater => ">", + Op::GreaterEq => ">=", + Op::Less => "<", + Op::LessEq => "<=", + Op::Tilde => "~", + Op::Caret => "^", + Op::Wildcard => "", + #[cfg(no_non_exhaustive)] + Op::__NonExhaustive => unreachable!(), + }; + formatter.write_str(op)?; + write!(formatter, "{}", self.major)?; + if let Some(minor) = &self.minor { + write!(formatter, ".{}", minor)?; + if let Some(patch) = &self.patch { + write!(formatter, ".{}", patch)?; + if !self.pre.is_empty() { + write!(formatter, "-{}", self.pre)?; + } + } else if self.op == Op::Wildcard { + formatter.write_str(".*")?; + } + } else if self.op == Op::Wildcard { + formatter.write_str(".*")?; + } + Ok(()) + } +} + +impl Display for Prerelease { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str(self.as_str()) + } +} + +impl Display for BuildMetadata { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str(self.as_str()) + } +} + +impl Debug for Version { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + let mut debug = formatter.debug_struct("Version"); + debug + .field("major", &self.major) + .field("minor", &self.minor) + .field("patch", &self.patch); + if !self.pre.is_empty() { + debug.field("pre", &self.pre); + } + if !self.build.is_empty() { + debug.field("build", &self.build); + } + debug.finish() + } +} + +impl Debug for Prerelease { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "Prerelease(\"{}\")", self) + } +} + +impl Debug for BuildMetadata { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "BuildMetadata(\"{}\")", self) + } +} + +fn pad( + formatter: &mut fmt::Formatter, + do_display: impl FnOnce(&mut fmt::Formatter) -> fmt::Result, + do_len: impl FnOnce() -> usize, +) -> fmt::Result { + let min_width = match formatter.width() { + Some(min_width) => min_width, + None => return do_display(formatter), + }; + + let len = do_len(); + if len >= min_width { + return do_display(formatter); + } + + let default_align = Alignment::Left; + let align = formatter.align().unwrap_or(default_align); + let padding = min_width - len; + let (pre_pad, post_pad) = match align { + Alignment::Left => (0, padding), + Alignment::Right => (padding, 0), + Alignment::Center => (padding / 2, (padding + 1) / 2), + }; + + let fill = formatter.fill(); + for _ in 0..pre_pad { + formatter.write_char(fill)?; + } + + do_display(formatter)?; + + for _ in 0..post_pad { + formatter.write_char(fill)?; + } + Ok(()) +} + +fn digits(val: u64) -> usize { + if val < 10 { + 1 + } else { + 1 + digits(val / 10) + } +} diff --git a/vendor/semver/src/error.rs b/vendor/semver/src/error.rs new file mode 100644 index 0000000000..4d57950e68 --- /dev/null +++ b/vendor/semver/src/error.rs @@ -0,0 +1,90 @@ +use crate::parse::Error; +use core::fmt::{self, Debug, Display}; + +pub(crate) enum ErrorKind { + UnexpectedEnd(Position), + UnexpectedChar(Position, char), + UnexpectedCharAfter(Position, char), + ExpectedCommaFound(Position, char), + LeadingZero(Position), + Overflow(Position), + EmptySegment(Position), + IllegalCharacter(Position), + UnexpectedAfterWildcard, + ExcessiveComparators, +} + +#[derive(Copy, Clone, Eq, PartialEq)] +pub(crate) enum Position { + Major, + Minor, + Patch, + Pre, + Build, +} + +#[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +impl std::error::Error for Error {} + +impl Display for Error { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + match &self.kind { + ErrorKind::UnexpectedEnd(pos) => { + write!(formatter, "unexpected end of input while parsing {}", pos) + } + ErrorKind::UnexpectedChar(pos, ch) => { + write!( + formatter, + "unexpected character {:?} while parsing {}", + ch, pos, + ) + } + ErrorKind::UnexpectedCharAfter(pos, ch) => { + write!(formatter, "unexpected character {:?} after {}", ch, pos) + } + ErrorKind::ExpectedCommaFound(pos, ch) => { + write!(formatter, "expected comma after {}, found {:?}", pos, ch) + } + ErrorKind::LeadingZero(pos) => { + write!(formatter, "invalid leading zero in {}", pos) + } + ErrorKind::Overflow(pos) => { + write!(formatter, "value of {} exceeds u64::MAX", pos) + } + ErrorKind::EmptySegment(pos) => { + write!(formatter, "empty identifier segment in {}", pos) + } + ErrorKind::IllegalCharacter(pos) => { + write!(formatter, "unexpected character in {}", pos) + } + ErrorKind::UnexpectedAfterWildcard => { + formatter.write_str("unexpected character after wildcard in version req") + } + ErrorKind::ExcessiveComparators => { + formatter.write_str("excessive number of version comparators") + } + } + } +} + +impl Display for Position { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str(match self { + Position::Major => "major version number", + Position::Minor => "minor version number", + Position::Patch => "patch version number", + Position::Pre => "pre-release identifier", + Position::Build => "build metadata", + }) + } +} + +impl Debug for Error { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("Error(\"")?; + Display::fmt(self, formatter)?; + formatter.write_str("\")")?; + Ok(()) + } +} diff --git a/vendor/semver/src/eval.rs b/vendor/semver/src/eval.rs new file mode 100644 index 0000000000..e6e38949a9 --- /dev/null +++ b/vendor/semver/src/eval.rs @@ -0,0 +1,181 @@ +use crate::{Comparator, Op, Version, VersionReq}; + +pub(crate) fn matches_req(req: &VersionReq, ver: &Version) -> bool { + for cmp in &req.comparators { + if !matches_impl(cmp, ver) { + return false; + } + } + + if ver.pre.is_empty() { + return true; + } + + // If a version has a prerelease tag (for example, 1.2.3-alpha.3) then it + // will only be allowed to satisfy req if at least one comparator with the + // same major.minor.patch also has a prerelease tag. + for cmp in &req.comparators { + if pre_is_compatible(cmp, ver) { + return true; + } + } + + false +} + +pub(crate) fn matches_comparator(cmp: &Comparator, ver: &Version) -> bool { + matches_impl(cmp, ver) && (ver.pre.is_empty() || pre_is_compatible(cmp, ver)) +} + +fn matches_impl(cmp: &Comparator, ver: &Version) -> bool { + match cmp.op { + Op::Exact | Op::Wildcard => matches_exact(cmp, ver), + Op::Greater => matches_greater(cmp, ver), + Op::GreaterEq => matches_exact(cmp, ver) || matches_greater(cmp, ver), + Op::Less => matches_less(cmp, ver), + Op::LessEq => matches_exact(cmp, ver) || matches_less(cmp, ver), + Op::Tilde => matches_tilde(cmp, ver), + Op::Caret => matches_caret(cmp, ver), + #[cfg(no_non_exhaustive)] + Op::__NonExhaustive => unreachable!(), + } +} + +fn matches_exact(cmp: &Comparator, ver: &Version) -> bool { + if ver.major != cmp.major { + return false; + } + + if let Some(minor) = cmp.minor { + if ver.minor != minor { + return false; + } + } + + if let Some(patch) = cmp.patch { + if ver.patch != patch { + return false; + } + } + + ver.pre == cmp.pre +} + +fn matches_greater(cmp: &Comparator, ver: &Version) -> bool { + if ver.major != cmp.major { + return ver.major > cmp.major; + } + + match cmp.minor { + None => return false, + Some(minor) => { + if ver.minor != minor { + return ver.minor > minor; + } + } + } + + match cmp.patch { + None => return false, + Some(patch) => { + if ver.patch != patch { + return ver.patch > patch; + } + } + } + + ver.pre > cmp.pre +} + +fn matches_less(cmp: &Comparator, ver: &Version) -> bool { + if ver.major != cmp.major { + return ver.major < cmp.major; + } + + match cmp.minor { + None => return false, + Some(minor) => { + if ver.minor != minor { + return ver.minor < minor; + } + } + } + + match cmp.patch { + None => return false, + Some(patch) => { + if ver.patch != patch { + return ver.patch < patch; + } + } + } + + ver.pre < cmp.pre +} + +fn matches_tilde(cmp: &Comparator, ver: &Version) -> bool { + if ver.major != cmp.major { + return false; + } + + if let Some(minor) = cmp.minor { + if ver.minor != minor { + return false; + } + } + + if let Some(patch) = cmp.patch { + if ver.patch != patch { + return ver.patch > patch; + } + } + + ver.pre >= cmp.pre +} + +fn matches_caret(cmp: &Comparator, ver: &Version) -> bool { + if ver.major != cmp.major { + return false; + } + + let minor = match cmp.minor { + None => return true, + Some(minor) => minor, + }; + + let patch = match cmp.patch { + None => { + if cmp.major > 0 { + return ver.minor >= minor; + } else { + return ver.minor == minor; + } + } + Some(patch) => patch, + }; + + if cmp.major > 0 { + if ver.minor != minor { + return ver.minor > minor; + } else if ver.patch != patch { + return ver.patch > patch; + } + } else if minor > 0 { + if ver.minor != minor { + return false; + } else if ver.patch != patch { + return ver.patch > patch; + } + } else if ver.minor != minor || ver.patch != patch { + return false; + } + + ver.pre >= cmp.pre +} + +fn pre_is_compatible(cmp: &Comparator, ver: &Version) -> bool { + cmp.major == ver.major + && cmp.minor == Some(ver.minor) + && cmp.patch == Some(ver.patch) + && !cmp.pre.is_empty() +} diff --git a/vendor/semver/src/identifier.rs b/vendor/semver/src/identifier.rs new file mode 100644 index 0000000000..500239e762 --- /dev/null +++ b/vendor/semver/src/identifier.rs @@ -0,0 +1,356 @@ +// This module implements Identifier, a short-optimized string allowed to +// contain only the ASCII characters hyphen, dot, 0-9, A-Z, a-z. +// +// As of mid-2021, the distribution of pre-release lengths on crates.io is: +// +// length count length count length count +// 0 355929 11 81 24 2 +// 1 208 12 48 25 6 +// 2 236 13 55 26 10 +// 3 1909 14 25 27 4 +// 4 1284 15 15 28 1 +// 5 1742 16 35 30 1 +// 6 3440 17 9 31 5 +// 7 5624 18 6 32 1 +// 8 1321 19 12 36 2 +// 9 179 20 2 37 379 +// 10 65 23 11 +// +// and the distribution of build metadata lengths is: +// +// length count length count length count +// 0 364445 8 7725 18 1 +// 1 72 9 16 19 1 +// 2 7 10 85 20 1 +// 3 28 11 17 22 4 +// 4 9 12 10 26 1 +// 5 68 13 9 27 1 +// 6 73 14 10 40 5 +// 7 53 15 6 +// +// Therefore it really behooves us to be able to use the entire 8 bytes of a +// pointer for inline storage. For both pre-release and build metadata there are +// vastly more strings with length exactly 8 bytes than the sum over all lengths +// longer than 8 bytes. +// +// To differentiate the inline representation from the heap allocated long +// representation, we'll allocate heap pointers with 2-byte alignment so that +// they are guaranteed to have an unset least significant bit. Then in the repr +// we store for pointers, we rotate a 1 into the most significant bit of the +// most significant byte, which is never set for an ASCII byte. +// +// Inline repr: +// +// 0xxxxxxx 0xxxxxxx 0xxxxxxx 0xxxxxxx 0xxxxxxx 0xxxxxxx 0xxxxxxx 0xxxxxxx +// +// Heap allocated repr: +// +// 1ppppppp pppppppp pppppppp pppppppp pppppppp pppppppp pppppppp pppppppp 0 +// ^ most significant bit least significant bit of orig ptr, rotated out ^ +// +// Since the most significant bit doubles as a sign bit for the similarly sized +// signed integer type, the CPU has an efficient instruction for inspecting it, +// meaning we can differentiate between an inline repr and a heap allocated repr +// in one instruction. Effectively an inline repr always looks like a positive +// i64 while a heap allocated repr always looks like a negative i64. +// +// For the inline repr, we store \0 padding on the end of the stored characters, +// and thus the string length is readily determined efficiently by a cttz (count +// trailing zeros) or bsf (bit scan forward) instruction. +// +// For the heap allocated repr, the length is encoded as a base-128 varint at +// the head of the allocation. +// +// Empty strings are stored as an all-1 bit pattern, corresponding to -1i64. +// Consequently the all-0 bit pattern is never a legal representation in any +// repr, leaving it available as a niche for downstream code. For example this +// allows size_of::<Version>() == size_of::<Option<Version>>(). + +use crate::alloc::alloc::{alloc, dealloc, Layout}; +#[cfg(no_from_ne_bytes)] +use crate::backport::FromNeBytes; +use core::mem; +use core::num::{NonZeroU64, NonZeroUsize}; +use core::ptr; +use core::slice; +use core::str; + +#[repr(transparent)] +pub(crate) struct Identifier { + repr: NonZeroU64, +} + +impl Identifier { + const EMPTY: NonZeroU64 = unsafe { NonZeroU64::new_unchecked(!0) }; + + pub(crate) const fn empty() -> Self { + // `mov rax, -1` + Identifier { repr: Self::EMPTY } + } + + // SAFETY: string must be ASCII and not contain \0 bytes. + pub(crate) unsafe fn new_unchecked(string: &str) -> Self { + let len = string.len(); + let repr = match len as u64 { + 0 => Self::EMPTY, + 1..=8 => { + let mut bytes = [0u8; 8]; + // SAFETY: string is big enough to read len bytes, bytes is big + // enough to write len bytes, and they do not overlap. + unsafe { ptr::copy_nonoverlapping(string.as_ptr(), bytes.as_mut_ptr(), len) }; + // SAFETY: it's nonzero because the input string was at least 1 + // byte of ASCII and did not contain \0. + unsafe { NonZeroU64::new_unchecked(u64::from_ne_bytes(bytes)) } + } + 9..=0xff_ffff_ffff_ffff => { + // SAFETY: len is in a range that does not contain 0. + let size = bytes_for_varint(unsafe { NonZeroUsize::new_unchecked(len) }) + len; + let align = 2; + // SAFETY: align is not zero, align is a power of two, and + // rounding size up to align does not overflow usize::MAX. + let layout = unsafe { Layout::from_size_align_unchecked(size, align) }; + // SAFETY: layout's size is nonzero. + let ptr = unsafe { alloc(layout) }; + let mut write = ptr; + let mut varint_remaining = len; + while varint_remaining > 0 { + // SAFETY: size is bytes_for_varint(len) bytes + len bytes. + // This is writing the first bytes_for_varint(len) bytes. + unsafe { ptr::write(write, varint_remaining as u8 | 0x80) }; + varint_remaining >>= 7; + // SAFETY: still in bounds of the same allocation. + write = unsafe { write.add(1) }; + } + // SAFETY: size is bytes_for_varint(len) bytes + len bytes. This + // is writing to the last len bytes. + unsafe { ptr::copy_nonoverlapping(string.as_ptr(), write, len) }; + ptr_to_repr(ptr) + } + 0x100_0000_0000_0000..=0xffff_ffff_ffff_ffff => { + unreachable!("please refrain from storing >64 petabytes of text in semver version"); + } + #[cfg(no_exhaustive_int_match)] // rustc <1.33 + _ => unreachable!(), + }; + Identifier { repr } + } + + pub(crate) fn is_empty(&self) -> bool { + // `cmp rdi, -1` -- basically: `repr as i64 == -1` + self.repr == Self::EMPTY + } + + fn is_inline(&self) -> bool { + // `test rdi, rdi` -- basically: `repr as i64 >= 0` + self.repr.get() >> 63 == 0 + } + + fn is_empty_or_inline(&self) -> bool { + // `cmp rdi, -2` -- basically: `repr as i64 > -2` + self.is_empty() || self.is_inline() + } + + pub(crate) fn as_str(&self) -> &str { + if self.is_empty() { + "" + } else if self.is_inline() { + // SAFETY: repr is in the inline representation. + unsafe { inline_as_str(&self.repr) } + } else { + // SAFETY: repr is in the heap allocated representation. + unsafe { ptr_as_str(&self.repr) } + } + } +} + +impl Clone for Identifier { + fn clone(&self) -> Self { + let repr = if self.is_empty_or_inline() { + self.repr + } else { + let ptr = repr_to_ptr(self.repr); + // SAFETY: ptr is one of our own heap allocations. + let len = unsafe { decode_len(ptr) }; + let size = bytes_for_varint(len) + len.get(); + let align = 2; + // SAFETY: align is not zero, align is a power of two, and rounding + // size up to align does not overflow usize::MAX. This is just + // duplicating a previous allocation where all of these guarantees + // were already made. + let layout = unsafe { Layout::from_size_align_unchecked(size, align) }; + // SAFETY: layout's size is nonzero. + let clone = unsafe { alloc(layout) }; + // SAFETY: new allocation cannot overlap the previous one (this was + // not a realloc). The argument ptrs are readable/writeable + // respectively for size bytes. + unsafe { ptr::copy_nonoverlapping(ptr, clone, size) } + ptr_to_repr(clone) + }; + Identifier { repr } + } +} + +impl Drop for Identifier { + fn drop(&mut self) { + if self.is_empty_or_inline() { + return; + } + let ptr = repr_to_ptr_mut(self.repr); + // SAFETY: ptr is one of our own heap allocations. + let len = unsafe { decode_len(ptr) }; + let size = bytes_for_varint(len) + len.get(); + let align = 2; + // SAFETY: align is not zero, align is a power of two, and rounding + // size up to align does not overflow usize::MAX. These guarantees were + // made when originally allocating this memory. + let layout = unsafe { Layout::from_size_align_unchecked(size, align) }; + // SAFETY: ptr was previously allocated by the same allocator with the + // same layout. + unsafe { dealloc(ptr, layout) } + } +} + +impl PartialEq for Identifier { + fn eq(&self, rhs: &Self) -> bool { + if self.is_empty_or_inline() { + // Fast path (most common) + self.repr == rhs.repr + } else if rhs.is_empty_or_inline() { + false + } else { + // SAFETY: both reprs are in the heap allocated representation. + unsafe { ptr_as_str(&self.repr) == ptr_as_str(&rhs.repr) } + } + } +} + +// We use heap pointers that are 2-byte aligned, meaning they have an +// insignificant 0 in the least significant bit. We take advantage of that +// unneeded bit to rotate a 1 into the most significant bit to make the repr +// distinguishable from ASCII bytes. +fn ptr_to_repr(ptr: *mut u8) -> NonZeroU64 { + // `mov eax, 1` + // `shld rax, rdi, 63` + let repr = (ptr as u64 | 1).rotate_right(1); + + // SAFETY: the most significant bit of repr is known to be set, so the value + // is not zero. + unsafe { NonZeroU64::new_unchecked(repr) } +} + +// Shift out the 1 previously placed into the most significant bit of the least +// significant byte. Shift in a low 0 bit to reconstruct the original 2-byte +// aligned pointer. +fn repr_to_ptr(repr: NonZeroU64) -> *const u8 { + // `lea rax, [rdi + rdi]` + (repr.get() << 1) as *const u8 +} + +fn repr_to_ptr_mut(repr: NonZeroU64) -> *mut u8 { + repr_to_ptr(repr) as *mut u8 +} + +// Compute the length of the inline string, assuming the argument is in short +// string representation. Short strings are stored as 1 to 8 nonzero ASCII +// bytes, followed by \0 padding for the remaining bytes. +fn inline_len(repr: NonZeroU64) -> NonZeroUsize { + // Rustc >=1.53 has intrinsics for counting zeros on a non-zeroable integer. + // On many architectures these are more efficient than counting on ordinary + // zeroable integers (bsf vs cttz). On rustc <1.53 without those intrinsics, + // we count zeros in the u64 rather than the NonZeroU64. + #[cfg(no_nonzero_bitscan)] + let repr = repr.get(); + + #[cfg(target_endian = "little")] + let zero_bits_on_string_end = repr.leading_zeros(); + #[cfg(target_endian = "big")] + let zero_bits_on_string_end = repr.trailing_zeros(); + + let nonzero_bytes = 8 - zero_bits_on_string_end as usize / 8; + + // SAFETY: repr is nonzero, so it has at most 63 zero bits on either end, + // thus at least one nonzero byte. + unsafe { NonZeroUsize::new_unchecked(nonzero_bytes) } +} + +// SAFETY: repr must be in the inline representation, i.e. at least 1 and at +// most 8 nonzero ASCII bytes padded on the end with \0 bytes. +unsafe fn inline_as_str(repr: &NonZeroU64) -> &str { + let ptr = repr as *const NonZeroU64 as *const u8; + let len = inline_len(*repr).get(); + // SAFETY: we are viewing the nonzero ASCII prefix of the inline repr's + // contents as a slice of bytes. Input/output lifetimes are correctly + // associated. + let slice = unsafe { slice::from_raw_parts(ptr, len) }; + // SAFETY: the string contents are known to be only ASCII bytes, which are + // always valid UTF-8. + unsafe { str::from_utf8_unchecked(slice) } +} + +// Decode varint. Varints consist of between one and eight base-128 digits, each +// of which is stored in a byte with most significant bit set. Adjacent to the +// varint in memory there is guaranteed to be at least 9 ASCII bytes, each of +// which has an unset most significant bit. +// +// SAFETY: ptr must be one of our own heap allocations, with the varint header +// already written. +unsafe fn decode_len(ptr: *const u8) -> NonZeroUsize { + // SAFETY: There is at least one byte of varint followed by at least 9 bytes + // of string content, which is at least 10 bytes total for the allocation, + // so reading the first two is no problem. + let [first, second] = unsafe { ptr::read(ptr as *const [u8; 2]) }; + if second < 0x80 { + // SAFETY: the length of this heap allocated string has been encoded as + // one base-128 digit, so the length is at least 9 and at most 127. It + // cannot be zero. + unsafe { NonZeroUsize::new_unchecked((first & 0x7f) as usize) } + } else { + return unsafe { decode_len_cold(ptr) }; + + // Identifiers 128 bytes or longer. This is not exercised by any crate + // version currently published to crates.io. + #[cold] + #[inline(never)] + unsafe fn decode_len_cold(mut ptr: *const u8) -> NonZeroUsize { + let mut len = 0; + let mut shift = 0; + loop { + // SAFETY: varint continues while there are bytes having the + // most significant bit set, i.e. until we start hitting the + // ASCII string content with msb unset. + let byte = unsafe { *ptr }; + if byte < 0x80 { + // SAFETY: the string length is known to be 128 bytes or + // longer. + return unsafe { NonZeroUsize::new_unchecked(len) }; + } + // SAFETY: still in bounds of the same allocation. + ptr = unsafe { ptr.add(1) }; + len += ((byte & 0x7f) as usize) << shift; + shift += 7; + } + } + } +} + +// SAFETY: repr must be in the heap allocated representation, with varint header +// and string contents already written. +unsafe fn ptr_as_str(repr: &NonZeroU64) -> &str { + let ptr = repr_to_ptr(*repr); + let len = unsafe { decode_len(ptr) }; + let header = bytes_for_varint(len); + let slice = unsafe { slice::from_raw_parts(ptr.add(header), len.get()) }; + // SAFETY: all identifier contents are ASCII bytes, which are always valid + // UTF-8. + unsafe { str::from_utf8_unchecked(slice) } +} + +// Number of base-128 digits required for the varint representation of a length. +fn bytes_for_varint(len: NonZeroUsize) -> usize { + #[cfg(no_nonzero_bitscan)] // rustc <1.53 + let len = len.get(); + + let usize_bits = mem::size_of::<usize>() * 8; + let len_bits = usize_bits - len.leading_zeros() as usize; + (len_bits + 6) / 7 +} diff --git a/vendor/semver/src/impls.rs b/vendor/semver/src/impls.rs new file mode 100644 index 0000000000..c3b6c60133 --- /dev/null +++ b/vendor/semver/src/impls.rs @@ -0,0 +1,156 @@ +use crate::backport::*; +use crate::identifier::Identifier; +use crate::{BuildMetadata, Comparator, Prerelease, VersionReq}; +use core::cmp::Ordering; +use core::hash::{Hash, Hasher}; +use core::iter::FromIterator; +use core::ops::Deref; + +impl Default for Identifier { + fn default() -> Self { + Identifier::empty() + } +} + +impl Eq for Identifier {} + +impl Hash for Identifier { + fn hash<H: Hasher>(&self, hasher: &mut H) { + self.as_str().hash(hasher); + } +} + +impl Deref for Prerelease { + type Target = str; + + fn deref(&self) -> &Self::Target { + self.identifier.as_str() + } +} + +impl Deref for BuildMetadata { + type Target = str; + + fn deref(&self) -> &Self::Target { + self.identifier.as_str() + } +} + +impl PartialOrd for Prerelease { + fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> { + Some(Ord::cmp(self, rhs)) + } +} + +impl PartialOrd for BuildMetadata { + fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> { + Some(Ord::cmp(self, rhs)) + } +} + +impl Ord for Prerelease { + fn cmp(&self, rhs: &Self) -> Ordering { + match self.is_empty() { + true if rhs.is_empty() => return Ordering::Equal, + // A real release compares greater than prerelease. + true => return Ordering::Greater, + // Prerelease compares less than the real release. + false if rhs.is_empty() => return Ordering::Less, + false => {} + } + + let lhs = self.as_str().split('.'); + let mut rhs = rhs.as_str().split('.'); + + for lhs in lhs { + let rhs = match rhs.next() { + // Spec: "A larger set of pre-release fields has a higher + // precedence than a smaller set, if all of the preceding + // identifiers are equal." + None => return Ordering::Greater, + Some(rhs) => rhs, + }; + + let string_cmp = || Ord::cmp(lhs, rhs); + let is_ascii_digit = |b: u8| b.is_ascii_digit(); + let ordering = match ( + lhs.bytes().all(is_ascii_digit), + rhs.bytes().all(is_ascii_digit), + ) { + // Respect numeric ordering, for example 99 < 100. Spec says: + // "Identifiers consisting of only digits are compared + // numerically." + (true, true) => Ord::cmp(&lhs.len(), &rhs.len()).then_with(string_cmp), + // Spec: "Numeric identifiers always have lower precedence than + // non-numeric identifiers." + (true, false) => return Ordering::Less, + (false, true) => return Ordering::Greater, + // Spec: "Identifiers with letters or hyphens are compared + // lexically in ASCII sort order." + (false, false) => string_cmp(), + }; + + if ordering != Ordering::Equal { + return ordering; + } + } + + if rhs.next().is_none() { + Ordering::Equal + } else { + Ordering::Less + } + } +} + +impl Ord for BuildMetadata { + fn cmp(&self, rhs: &Self) -> Ordering { + let lhs = self.as_str().split('.'); + let mut rhs = rhs.as_str().split('.'); + + for lhs in lhs { + let rhs = match rhs.next() { + None => return Ordering::Greater, + Some(rhs) => rhs, + }; + + let is_ascii_digit = |b: u8| b.is_ascii_digit(); + let ordering = match ( + lhs.bytes().all(is_ascii_digit), + rhs.bytes().all(is_ascii_digit), + ) { + (true, true) => { + // 0 < 00 < 1 < 01 < 001 < 2 < 02 < 002 < 10 + let lhval = lhs.trim_start_matches('0'); + let rhval = rhs.trim_start_matches('0'); + Ord::cmp(&lhval.len(), &rhval.len()) + .then_with(|| Ord::cmp(lhval, rhval)) + .then_with(|| Ord::cmp(&lhs.len(), &rhs.len())) + } + (true, false) => return Ordering::Less, + (false, true) => return Ordering::Greater, + (false, false) => Ord::cmp(lhs, rhs), + }; + + if ordering != Ordering::Equal { + return ordering; + } + } + + if rhs.next().is_none() { + Ordering::Equal + } else { + Ordering::Less + } + } +} + +impl FromIterator<Comparator> for VersionReq { + fn from_iter<I>(iter: I) -> Self + where + I: IntoIterator<Item = Comparator>, + { + let comparators = Vec::from_iter(iter); + VersionReq { comparators } + } +} diff --git a/vendor/semver/src/lib.rs b/vendor/semver/src/lib.rs new file mode 100644 index 0000000000..adfd37d434 --- /dev/null +++ b/vendor/semver/src/lib.rs @@ -0,0 +1,523 @@ +//! [![github]](https://github.com/dtolnay/semver) [![crates-io]](https://crates.io/crates/semver) [![docs-rs]](https://docs.rs/semver) +//! +//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github +//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust +//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K +//! +//! <br> +//! +//! A parser and evaluator for Cargo's flavor of Semantic Versioning. +//! +//! Semantic Versioning (see <https://semver.org>) is a guideline for how +//! version numbers are assigned and incremented. It is widely followed within +//! the Cargo/crates.io ecosystem for Rust. +//! +//! <br> +//! +//! # Example +//! +//! ``` +//! use semver::{BuildMetadata, Prerelease, Version, VersionReq}; +//! +//! fn main() { +//! let req = VersionReq::parse(">=1.2.3, <1.8.0").unwrap(); +//! +//! // Check whether this requirement matches version 1.2.3-alpha.1 (no) +//! let version = Version { +//! major: 1, +//! minor: 2, +//! patch: 3, +//! pre: Prerelease::new("alpha.1").unwrap(), +//! build: BuildMetadata::EMPTY, +//! }; +//! assert!(!req.matches(&version)); +//! +//! // Check whether it matches 1.3.0 (yes it does) +//! let version = Version::parse("1.3.0").unwrap(); +//! assert!(req.matches(&version)); +//! } +//! ``` +//! +//! <br><br> +//! +//! # Scope of this crate +//! +//! Besides Cargo, several other package ecosystems and package managers for +//! other languages also use SemVer: RubyGems/Bundler for Ruby, npm for +//! JavaScript, Composer for PHP, CocoaPods for Objective-C... +//! +//! The `semver` crate is specifically intended to implement Cargo's +//! interpretation of Semantic Versioning. +//! +//! Where the various tools differ in their interpretation or implementation of +//! the spec, this crate follows the implementation choices made by Cargo. If +//! you are operating on version numbers from some other package ecosystem, you +//! will want to use a different semver library which is appropriate to that +//! ecosystem. +//! +//! The extent of Cargo's SemVer support is documented in the *[Specifying +//! Dependencies]* chapter of the Cargo reference. +//! +//! [Specifying Dependencies]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html + +#![doc(html_root_url = "https://docs.rs/semver/1.0.4")] +#![cfg_attr(doc_cfg, feature(doc_cfg))] +#![cfg_attr(all(not(feature = "std"), not(no_alloc_crate)), no_std)] +#![cfg_attr(not(no_unsafe_op_in_unsafe_fn_lint), deny(unsafe_op_in_unsafe_fn))] +#![cfg_attr(no_unsafe_op_in_unsafe_fn_lint, allow(unused_unsafe))] +#![cfg_attr(no_str_strip_prefix, allow(unstable_name_collisions))] +#![allow( + clippy::cast_lossless, + clippy::cast_possible_truncation, + clippy::doc_markdown, + clippy::items_after_statements, + clippy::match_bool, + clippy::missing_errors_doc, + clippy::must_use_candidate, + clippy::needless_doctest_main, + clippy::option_if_let_else, + clippy::ptr_as_ptr, + clippy::redundant_else, + clippy::semicolon_if_nothing_returned, // https://github.com/rust-lang/rust-clippy/issues/7324 + clippy::similar_names, + clippy::unnested_or_patterns, + clippy::unseparated_literal_suffix, + clippy::wildcard_imports +)] + +#[cfg(not(no_alloc_crate))] +extern crate alloc; + +mod backport; +mod display; +mod error; +mod eval; +mod identifier; +mod impls; +mod parse; + +#[cfg(feature = "serde")] +mod serde; + +use crate::alloc::vec::Vec; +use crate::identifier::Identifier; +use core::str::FromStr; + +#[allow(unused_imports)] +use crate::backport::*; + +pub use crate::parse::Error; + +/// **SemVer version** as defined by <https://semver.org>. +/// +/// # Syntax +/// +/// - The major, minor, and patch numbers may be any integer 0 through u64::MAX. +/// When representing a SemVer version as a string, each number is written as +/// a base 10 integer. For example, `1.0.119`. +/// +/// - Leading zeros are forbidden in those positions. For example `1.01.00` is +/// invalid as a SemVer version. +/// +/// - The pre-release identifier, if present, must conform to the syntax +/// documented for [`Prerelease`]. +/// +/// - The build metadata, if present, must conform to the syntax documented for +/// [`BuildMetadata`]. +/// +/// - Whitespace is not allowed anywhere in the version. +/// +/// # Total ordering +/// +/// Given any two SemVer versions, one is less than, greater than, or equal to +/// the other. Versions may be compared against one another using Rust's usual +/// comparison operators. +/// +/// - The major, minor, and patch number are compared numerically from left to +/// right, lexicographically ordered as a 3-tuple of integers. So for example +/// version `1.5.0` is less than version `1.19.0`, despite the fact that +/// "1.19.0" < "1.5.0" as ASCIIbetically compared strings and 1.19 < 1.5 +/// as real numbers. +/// +/// - When major, minor, and patch are equal, a pre-release version is +/// considered less than the ordinary release: version `1.0.0-alpha.1` is +/// less than version `1.0.0`. +/// +/// - Two pre-releases of the same major, minor, patch are compared by +/// lexicographic ordering of dot-separated components of the pre-release +/// string. +/// +/// - Identifiers consisting of only digits are compared +/// numerically: `1.0.0-pre.8` is less than `1.0.0-pre.12`. +/// +/// - Identifiers that contain a letter or hyphen are compared in ASCII sort +/// order: `1.0.0-pre12` is less than `1.0.0-pre8`. +/// +/// - Any numeric identifier is always less than any non-numeric +/// identifier: `1.0.0-pre.1` is less than `1.0.0-pre.x`. +/// +/// Example: `1.0.0-alpha` < `1.0.0-alpha.1` < `1.0.0-alpha.beta` < `1.0.0-beta` < `1.0.0-beta.2` < `1.0.0-beta.11` < `1.0.0-rc.1` < `1.0.0` +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +pub struct Version { + pub major: u64, + pub minor: u64, + pub patch: u64, + pub pre: Prerelease, + pub build: BuildMetadata, +} + +/// **SemVer version requirement** describing the intersection of some version +/// comparators, such as `>=1.2.3, <1.8`. +/// +/// # Syntax +/// +/// - Either `*` (meaning "any"), or one or more comma-separated comparators. +/// +/// - A [`Comparator`] is an operator ([`Op`]) and a partial version, separated +/// by optional whitespace. For example `>=1.0.0` or `>=1.0`. +/// +/// - Build metadata is syntactically permitted on the partial versions, but is +/// completely ignored, as it's never relevant to whether any comparator +/// matches a particular version. +/// +/// - Whitespace is permitted around commas and around operators. Whitespace is +/// not permitted within a partial version, i.e. anywhere between the major +/// version number and its minor, patch, pre-release, or build metadata. +#[derive(Default, Clone, Eq, PartialEq, Hash, Debug)] +pub struct VersionReq { + pub comparators: Vec<Comparator>, +} + +/// A pair of comparison operator and partial version, such as `>=1.2`. Forms +/// one piece of a VersionReq. +#[derive(Clone, Eq, PartialEq, Hash, Debug)] +pub struct Comparator { + pub op: Op, + pub major: u64, + pub minor: Option<u64>, + /// Patch is only allowed if minor is Some. + pub patch: Option<u64>, + /// Non-empty pre-release is only allowed if patch is Some. + pub pre: Prerelease, +} + +/// SemVer comparison operator: `=`, `>`, `>=`, `<`, `<=`, `~`, `^`, `*`. +/// +/// # Op::Exact +/// -  **`=I.J.K`** — exactly the version I.J.K +/// -  **`=I.J`** — equivalent to `>=I.J.0, <I.(J+1).0` +/// -  **`=I`** — equivalent to `>=I.0.0, <(I+1).0.0` +/// +/// # Op::Greater +/// -  **`>I.J.K`** +/// -  **`>I.J`** — equivalent to `>=I.(J+1).0` +/// -  **`>I`** — equivalent to `>=(I+1).0.0` +/// +/// # Op::GreaterEq +/// -  **`>=I.J.K`** +/// -  **`>=I.J`** — equivalent to `>=I.J.0` +/// -  **`>=I`** — equivalent to `>=I.0.0` +/// +/// # Op::Less +/// -  **`<I.J.K`** +/// -  **`<I.J`** — equivalent to `<I.J.0` +/// -  **`<I`** — equivalent to `<I.0.0` +/// +/// # Op::LessEq +/// -  **`<=I.J.K`** +/// -  **`<=I.J`** — equivalent to `<I.(J+1).0` +/// -  **`<=I`** — equivalent to `<(I+1).0.0` +/// +/// # Op::Tilde ("patch" updates) +/// *Tilde requirements allow the **patch** part of the semver version (the third number) to increase.* +/// -  **`~I.J.K`** — equivalent to `>=I.J.K, <I.(J+1).0` +/// -  **`~I.J`** — equivalent to `=I.J` +/// -  **`~I`** — equivalent to `=I` +/// +/// # Op::Caret ("compatible" updates) +/// *Caret requirements allow parts that are **right of the first nonzero** part of the semver version to increase.* +/// -  **`^I.J.K`** (for I\>0) — equivalent to `>=I.J.K, <(I+1).0.0` +/// -  **`^0.J.K`** (for J\>0) — equivalent to `>=0.J.K, <0.(J+1).0` +/// -  **`^0.0.K`** — equivalent to `=0.0.K` +/// -  **`^I.J`** (for I\>0 or J\>0) — equivalent to `^I.J.0` +/// -  **`^0.0`** — equivalent to `=0.0` +/// -  **`^I`** — equivalent to `=I` +/// +/// # Op::Wildcard +/// -  **`I.J.*`** — equivalent to `=I.J` +/// -  **`I.*`** or **`I.*.*`** — equivalent to `=I` +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +#[cfg_attr(not(no_non_exhaustive), non_exhaustive)] +pub enum Op { + Exact, + Greater, + GreaterEq, + Less, + LessEq, + Tilde, + Caret, + Wildcard, + + #[cfg(no_non_exhaustive)] // rustc <1.40 + #[doc(hidden)] + __NonExhaustive, +} + +/// Optional pre-release identifier on a version string. This comes after `-` in +/// a SemVer version, like `1.0.0-alpha.1` +/// +/// # Examples +/// +/// Some real world pre-release idioms drawn from crates.io: +/// +/// - **[mio]** <code>0.7.0-<b>alpha.1</b></code> — the most common style +/// for numbering pre-releases. +/// +/// - **[pest]** <code>1.0.0-<b>beta.8</b></code>, <code>1.0.0-<b>rc.0</b></code> +/// — this crate makes a distinction between betas and release +/// candidates. +/// +/// - **[sassers]** <code>0.11.0-<b>shitshow</b></code> — ???. +/// +/// - **[atomic-utils]** <code>0.0.0-<b>reserved</b></code> — a squatted +/// crate name. +/// +/// [mio]: https://crates.io/crates/mio +/// [pest]: https://crates.io/crates/pest +/// [atomic-utils]: https://crates.io/crates/atomic-utils +/// [sassers]: https://crates.io/crates/sassers +/// +/// *Tip:* Be aware that if you are planning to number your own pre-releases, +/// you should prefer to separate the numeric part from any non-numeric +/// identifiers by using a dot in between. That is, prefer pre-releases +/// `alpha.1`, `alpha.2`, etc rather than `alpha1`, `alpha2` etc. The SemVer +/// spec's rule for pre-release precedence has special treatment of numeric +/// components in the pre-release string, but only if there are no non-digit +/// characters in the same dot-separated component. So you'd have `alpha.2` < +/// `alpha.11` as intended, but `alpha11` < `alpha2`. +/// +/// # Syntax +/// +/// Pre-release strings are a series of dot separated identifiers immediately +/// following the patch version. Identifiers must comprise only ASCII +/// alphanumerics and hyphens: `0-9`, `A-Z`, `a-z`, `-`. Identifiers must not be +/// empty. Numeric identifiers must not include leading zeros. +/// +/// # Total ordering +/// +/// Pre-releases have a total order defined by the SemVer spec. It uses +/// lexicographic ordering of dot-separated components. Identifiers consisting +/// of only digits are compared numerically. Otherwise, identifiers are compared +/// in ASCII sort order. Any numeric identifier is always less than any +/// non-numeric identifier. +/// +/// Example: `alpha` < `alpha.85` < `alpha.90` < `alpha.200` < `alpha.0a` < `alpha.1a0` < `alpha.a` < `beta` +#[derive(Default, Clone, Eq, PartialEq, Hash)] +pub struct Prerelease { + identifier: Identifier, +} + +/// Optional build metadata identifier. This comes after `+` in a SemVer +/// version, as in `0.8.1+zstd.1.5.0`. +/// +/// # Examples +/// +/// Some real world build metadata idioms drawn from crates.io: +/// +/// - **[libgit2-sys]** <code>0.12.20+<b>1.1.0</b></code> — for this +/// crate, the build metadata indicates the version of the C libgit2 library +/// that the Rust crate is built against. +/// +/// - **[mashup]** <code>0.1.13+<b>deprecated</b></code> — just the word +/// "deprecated" for a crate that has been superseded by another. Eventually +/// people will take notice of this in Cargo's build output where it lists the +/// crates being compiled. +/// +/// - **[google-bigquery2]** <code>2.0.4+<b>20210327</b></code> — this +/// library is automatically generated from an official API schema, and the +/// build metadata indicates the date on which that schema was last captured. +/// +/// - **[fbthrift-git]** <code>0.0.6+<b>c7fcc0e</b></code> — this crate is +/// published from snapshots of a big company monorepo. In monorepo +/// development, there is no concept of versions, and all downstream code is +/// just updated atomically in the same commit that breaking changes to a +/// library are landed. Therefore for crates.io purposes, every published +/// version must be assumed to be incompatible with the previous. The build +/// metadata provides the source control hash of the snapshotted code. +/// +/// [libgit2-sys]: https://crates.io/crates/libgit2-sys +/// [mashup]: https://crates.io/crates/mashup +/// [google-bigquery2]: https://crates.io/crates/google-bigquery2 +/// [fbthrift-git]: https://crates.io/crates/fbthrift-git +/// +/// # Syntax +/// +/// Build metadata is a series of dot separated identifiers immediately +/// following the patch or pre-release version. Identifiers must comprise only +/// ASCII alphanumerics and hyphens: `0-9`, `A-Z`, `a-z`, `-`. Identifiers must +/// not be empty. Leading zeros *are* allowed, unlike any other place in the +/// SemVer grammar. +/// +/// # Total ordering +/// +/// Build metadata is ignored in evaluating `VersionReq`; it plays no role in +/// whether a `Version` matches any one of the comparison operators. +/// +/// However for comparing build metadatas among one another, they do have a +/// total order which is determined by lexicographic ordering of dot-separated +/// components. Identifiers consisting of only digits are compared numerically. +/// Otherwise, identifiers are compared in ASCII sort order. Any numeric +/// identifier is always less than any non-numeric identifier. +/// +/// Example: `demo` < `demo.85` < `demo.90` < `demo.090` < `demo.200` < `demo.1a0` < `demo.a` < `memo` +#[derive(Default, Clone, Eq, PartialEq, Hash)] +pub struct BuildMetadata { + identifier: Identifier, +} + +impl Version { + /// Create `Version` with an empty pre-release and build metadata. + /// + /// Equivalent to: + /// + /// ``` + /// # use semver::{BuildMetadata, Prerelease, Version}; + /// # + /// # const fn new(major: u64, minor: u64, patch: u64) -> Version { + /// Version { + /// major, + /// minor, + /// patch, + /// pre: Prerelease::EMPTY, + /// build: BuildMetadata::EMPTY, + /// } + /// # } + /// ``` + pub const fn new(major: u64, minor: u64, patch: u64) -> Self { + Version { + major, + minor, + patch, + pre: Prerelease::EMPTY, + build: BuildMetadata::EMPTY, + } + } + + /// Create `Version` by parsing from string representation. + /// + /// # Errors + /// + /// Possible reasons for the parse to fail include: + /// + /// - `1.0` — too few numeric components. A SemVer version must have + /// exactly three. If you are looking at something that has fewer than + /// three numbers in it, it's possible it is a `VersionReq` instead (with + /// an implicit default `^` comparison operator). + /// + /// - `1.0.01` — a numeric component has a leading zero. + /// + /// - `1.0.unknown` — unexpected character in one of the components. + /// + /// - `1.0.0-` or `1.0.0+` — the pre-release or build metadata are + /// indicated present but empty. + /// + /// - `1.0.0-alpha_123` — pre-release or build metadata have something + /// outside the allowed characters, which are `0-9`, `A-Z`, `a-z`, `-`, + /// and `.` (dot). + /// + /// - `23456789999999999999.0.0` — overflow of a u64. + pub fn parse(text: &str) -> Result<Self, Error> { + Version::from_str(text) + } +} + +impl VersionReq { + /// A `VersionReq` with no constraint on the version numbers it matches. + /// Equivalent to `VersionReq::parse("*").unwrap()`. + /// + /// In terms of comparators this is equivalent to `>=0.0.0`. + /// + /// Counterintuitively a `*` VersionReq does not match every possible + /// version number. In particular, in order for *any* `VersionReq` to match + /// a pre-release version, the `VersionReq` must contain at least one + /// `Comparator` that has an explicit major, minor, and patch version + /// identical to the pre-release being matched, and that has a nonempty + /// pre-release component. Since `*` is not written with an explicit major, + /// minor, and patch version, and does not contain a nonempty pre-release + /// component, it does not match any pre-release versions. + #[cfg(not(no_const_vec_new))] // rustc <1.39 + pub const STAR: Self = VersionReq { + comparators: Vec::new(), + }; + + /// Create `VersionReq` by parsing from string representation. + /// + /// # Errors + /// + /// Possible reasons for the parse to fail include: + /// + /// - `>a.b` — unexpected characters in the partial version. + /// + /// - `@1.0.0` — unrecognized comparison operator. + /// + /// - `^1.0.0, ` — unexpected end of input. + /// + /// - `>=1.0 <2.0` — missing comma between comparators. + /// + /// - `*.*` — unsupported wildcard syntax. + pub fn parse(text: &str) -> Result<Self, Error> { + VersionReq::from_str(text) + } + + /// Evaluate whether the given `Version` satisfies the version requirement + /// described by `self`. + pub fn matches(&self, version: &Version) -> bool { + eval::matches_req(self, version) + } +} + +impl Comparator { + pub fn parse(text: &str) -> Result<Self, Error> { + Comparator::from_str(text) + } + + pub fn matches(&self, version: &Version) -> bool { + eval::matches_comparator(self, version) + } +} + +impl Prerelease { + pub const EMPTY: Self = Prerelease { + identifier: Identifier::empty(), + }; + + pub fn new(text: &str) -> Result<Self, Error> { + Prerelease::from_str(text) + } + + pub fn as_str(&self) -> &str { + self.identifier.as_str() + } + + pub fn is_empty(&self) -> bool { + self.identifier.is_empty() + } +} + +impl BuildMetadata { + pub const EMPTY: Self = BuildMetadata { + identifier: Identifier::empty(), + }; + + pub fn new(text: &str) -> Result<Self, Error> { + BuildMetadata::from_str(text) + } + + pub fn as_str(&self) -> &str { + self.identifier.as_str() + } + + pub fn is_empty(&self) -> bool { + self.identifier.is_empty() + } +} diff --git a/vendor/semver/src/parse.rs b/vendor/semver/src/parse.rs new file mode 100644 index 0000000000..017a5b5305 --- /dev/null +++ b/vendor/semver/src/parse.rs @@ -0,0 +1,391 @@ +use crate::backport::*; +use crate::error::{ErrorKind, Position}; +use crate::identifier::Identifier; +use crate::{BuildMetadata, Comparator, Op, Prerelease, Version, VersionReq}; +use core::str::FromStr; + +/// Error parsing a SemVer version or version requirement. +/// +/// # Example +/// +/// ``` +/// use semver::Version; +/// +/// fn main() { +/// let err = Version::parse("1.q.r").unwrap_err(); +/// +/// // "unexpected character 'q' while parsing minor version number" +/// eprintln!("{}", err); +/// } +/// ``` +pub struct Error { + pub(crate) kind: ErrorKind, +} + +impl FromStr for Version { + type Err = Error; + + fn from_str(text: &str) -> Result<Self, Self::Err> { + let mut pos = Position::Major; + let (major, text) = numeric_identifier(text, pos)?; + let text = dot(text, pos)?; + + pos = Position::Minor; + let (minor, text) = numeric_identifier(text, pos)?; + let text = dot(text, pos)?; + + pos = Position::Patch; + let (patch, text) = numeric_identifier(text, pos)?; + + if text.is_empty() { + return Ok(Version::new(major, minor, patch)); + } + + let (pre, text) = if let Some(text) = text.strip_prefix('-') { + pos = Position::Pre; + let (pre, text) = prerelease_identifier(text)?; + if pre.is_empty() { + return Err(Error::new(ErrorKind::EmptySegment(pos))); + } + (pre, text) + } else { + (Prerelease::EMPTY, text) + }; + + let (build, text) = if let Some(text) = text.strip_prefix('+') { + pos = Position::Build; + let (build, text) = build_identifier(text)?; + if build.is_empty() { + return Err(Error::new(ErrorKind::EmptySegment(pos))); + } + (build, text) + } else { + (BuildMetadata::EMPTY, text) + }; + + if let Some(unexpected) = text.chars().next() { + return Err(Error::new(ErrorKind::UnexpectedCharAfter(pos, unexpected))); + } + + Ok(Version { + major, + minor, + patch, + pre, + build, + }) + } +} + +impl FromStr for VersionReq { + type Err = Error; + + fn from_str(text: &str) -> Result<Self, Self::Err> { + let text = text.trim_start_matches(' '); + if let Some(text) = wildcard(text) { + if text.trim_start_matches(' ').is_empty() { + #[cfg(not(no_const_vec_new))] + return Ok(VersionReq::STAR); + #[cfg(no_const_vec_new)] // rustc <1.39 + return Ok(VersionReq { + comparators: Vec::new(), + }); + } else { + return Err(Error::new(ErrorKind::UnexpectedAfterWildcard)); + } + } + + let depth = 0; + let mut comparators = Vec::new(); + let len = version_req(text, &mut comparators, depth)?; + unsafe { comparators.set_len(len) } + Ok(VersionReq { comparators }) + } +} + +impl FromStr for Comparator { + type Err = Error; + + fn from_str(text: &str) -> Result<Self, Self::Err> { + let text = text.trim_start_matches(' '); + let (comparator, pos, rest) = comparator(text)?; + if !rest.is_empty() { + let unexpected = rest.chars().next().unwrap(); + return Err(Error::new(ErrorKind::UnexpectedCharAfter(pos, unexpected))); + } + Ok(comparator) + } +} + +impl FromStr for Prerelease { + type Err = Error; + + fn from_str(text: &str) -> Result<Self, Self::Err> { + let (pre, rest) = prerelease_identifier(text)?; + if !rest.is_empty() { + return Err(Error::new(ErrorKind::IllegalCharacter(Position::Pre))); + } + Ok(pre) + } +} + +impl FromStr for BuildMetadata { + type Err = Error; + + fn from_str(text: &str) -> Result<Self, Self::Err> { + let (build, rest) = build_identifier(text)?; + if !rest.is_empty() { + return Err(Error::new(ErrorKind::IllegalCharacter(Position::Build))); + } + Ok(build) + } +} + +impl Error { + fn new(kind: ErrorKind) -> Self { + Error { kind } + } +} + +impl Op { + const DEFAULT: Self = Op::Caret; +} + +fn numeric_identifier(input: &str, pos: Position) -> Result<(u64, &str), Error> { + let mut len = 0; + let mut value = 0u64; + + while let Some(&digit) = input.as_bytes().get(len) { + if digit < b'0' || digit > b'9' { + break; + } + if value == 0 && len > 0 { + return Err(Error::new(ErrorKind::LeadingZero(pos))); + } + match value + .checked_mul(10) + .and_then(|value| value.checked_add((digit - b'0') as u64)) + { + Some(sum) => value = sum, + None => return Err(Error::new(ErrorKind::Overflow(pos))), + } + len += 1; + } + + if len > 0 { + Ok((value, &input[len..])) + } else if let Some(unexpected) = input[len..].chars().next() { + Err(Error::new(ErrorKind::UnexpectedChar(pos, unexpected))) + } else { + Err(Error::new(ErrorKind::UnexpectedEnd(pos))) + } +} + +fn wildcard(input: &str) -> Option<&str> { + if let Some(rest) = input.strip_prefix('*') { + Some(rest) + } else if let Some(rest) = input.strip_prefix('x') { + Some(rest) + } else if let Some(rest) = input.strip_prefix('X') { + Some(rest) + } else { + None + } +} + +fn dot(input: &str, pos: Position) -> Result<&str, Error> { + if let Some(rest) = input.strip_prefix('.') { + Ok(rest) + } else if let Some(unexpected) = input.chars().next() { + Err(Error::new(ErrorKind::UnexpectedCharAfter(pos, unexpected))) + } else { + Err(Error::new(ErrorKind::UnexpectedEnd(pos))) + } +} + +fn prerelease_identifier(input: &str) -> Result<(Prerelease, &str), Error> { + let (string, rest) = identifier(input, Position::Pre)?; + let identifier = unsafe { Identifier::new_unchecked(string) }; + Ok((Prerelease { identifier }, rest)) +} + +fn build_identifier(input: &str) -> Result<(BuildMetadata, &str), Error> { + let (string, rest) = identifier(input, Position::Build)?; + let identifier = unsafe { Identifier::new_unchecked(string) }; + Ok((BuildMetadata { identifier }, rest)) +} + +fn identifier(input: &str, pos: Position) -> Result<(&str, &str), Error> { + let mut accumulated_len = 0; + let mut segment_len = 0; + let mut segment_has_nondigit = false; + + loop { + match input.as_bytes().get(accumulated_len + segment_len) { + Some(b'A'..=b'Z') | Some(b'a'..=b'z') | Some(b'-') => { + segment_len += 1; + segment_has_nondigit = true; + } + Some(b'0'..=b'9') => { + segment_len += 1; + } + boundary => { + if segment_len == 0 { + if accumulated_len == 0 && boundary != Some(&b'.') { + return Ok(("", input)); + } else { + return Err(Error::new(ErrorKind::EmptySegment(pos))); + } + } + if pos == Position::Pre + && segment_len > 1 + && !segment_has_nondigit + && input[accumulated_len..].starts_with('0') + { + return Err(Error::new(ErrorKind::LeadingZero(pos))); + } + accumulated_len += segment_len; + if boundary == Some(&b'.') { + accumulated_len += 1; + segment_len = 0; + segment_has_nondigit = false; + } else { + return Ok(input.split_at(accumulated_len)); + } + } + } + } +} + +fn op(input: &str) -> (Op, &str) { + let bytes = input.as_bytes(); + if bytes.get(0) == Some(&b'=') { + (Op::Exact, &input[1..]) + } else if bytes.get(0) == Some(&b'>') { + if bytes.get(1) == Some(&b'=') { + (Op::GreaterEq, &input[2..]) + } else { + (Op::Greater, &input[1..]) + } + } else if bytes.get(0) == Some(&b'<') { + if bytes.get(1) == Some(&b'=') { + (Op::LessEq, &input[2..]) + } else { + (Op::Less, &input[1..]) + } + } else if bytes.get(0) == Some(&b'~') { + (Op::Tilde, &input[1..]) + } else if bytes.get(0) == Some(&b'^') { + (Op::Caret, &input[1..]) + } else { + (Op::DEFAULT, input) + } +} + +fn comparator(input: &str) -> Result<(Comparator, Position, &str), Error> { + let (mut op, text) = op(input); + let default_op = input.len() == text.len(); + let text = text.trim_start_matches(' '); + + let mut pos = Position::Major; + let (major, text) = numeric_identifier(text, pos)?; + let mut has_wildcard = false; + + let (minor, text) = if let Some(text) = text.strip_prefix('.') { + pos = Position::Minor; + if let Some(text) = wildcard(text) { + has_wildcard = true; + if default_op { + op = Op::Wildcard; + } + (None, text) + } else { + let (minor, text) = numeric_identifier(text, pos)?; + (Some(minor), text) + } + } else { + (None, text) + }; + + let (patch, text) = if let Some(text) = text.strip_prefix('.') { + pos = Position::Patch; + if let Some(text) = wildcard(text) { + if default_op { + op = Op::Wildcard; + } + (None, text) + } else if has_wildcard { + return Err(Error::new(ErrorKind::UnexpectedAfterWildcard)); + } else { + let (patch, text) = numeric_identifier(text, pos)?; + (Some(patch), text) + } + } else { + (None, text) + }; + + let (pre, text) = if patch.is_some() && text.starts_with('-') { + pos = Position::Pre; + let text = &text[1..]; + let (pre, text) = prerelease_identifier(text)?; + if pre.is_empty() { + return Err(Error::new(ErrorKind::EmptySegment(pos))); + } + (pre, text) + } else { + (Prerelease::EMPTY, text) + }; + + let text = if patch.is_some() && text.starts_with('+') { + pos = Position::Build; + let text = &text[1..]; + let (build, text) = build_identifier(text)?; + if build.is_empty() { + return Err(Error::new(ErrorKind::EmptySegment(pos))); + } + text + } else { + text + }; + + let text = text.trim_start_matches(' '); + + let comparator = Comparator { + op, + major, + minor, + patch, + pre, + }; + + Ok((comparator, pos, text)) +} + +fn version_req(input: &str, out: &mut Vec<Comparator>, depth: usize) -> Result<usize, Error> { + let (comparator, pos, text) = comparator(input)?; + + if text.is_empty() { + out.reserve_exact(depth + 1); + unsafe { out.as_mut_ptr().add(depth).write(comparator) } + return Ok(depth + 1); + } + + let text = if let Some(text) = text.strip_prefix(',') { + text.trim_start_matches(' ') + } else { + let unexpected = text.chars().next().unwrap(); + return Err(Error::new(ErrorKind::ExpectedCommaFound(pos, unexpected))); + }; + + const MAX_COMPARATORS: usize = 32; + if depth + 1 == MAX_COMPARATORS { + return Err(Error::new(ErrorKind::ExcessiveComparators)); + } + + // Recurse to collect parsed Comparator objects on the stack. We perform a + // single allocation to allocate exactly the right sized Vec only once the + // total number of comparators is known. + let len = version_req(text, out, depth + 1)?; + unsafe { out.as_mut_ptr().add(depth).write(comparator) } + Ok(len) +} diff --git a/vendor/semver/src/serde.rs b/vendor/semver/src/serde.rs new file mode 100644 index 0000000000..06eceb68f0 --- /dev/null +++ b/vendor/semver/src/serde.rs @@ -0,0 +1,74 @@ +use crate::{Version, VersionReq}; +use core::fmt; +use serde::de::{Deserialize, Deserializer, Error, Visitor}; +use serde::ser::{Serialize, Serializer}; + +impl Serialize for Version { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + serializer.collect_str(self) + } +} + +impl Serialize for VersionReq { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + serializer.collect_str(self) + } +} + +impl<'de> Deserialize<'de> for Version { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + struct VersionVisitor; + + impl<'de> Visitor<'de> for VersionVisitor { + type Value = Version; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("semver version") + } + + fn visit_str<E>(self, string: &str) -> Result<Self::Value, E> + where + E: Error, + { + string.parse().map_err(Error::custom) + } + } + + deserializer.deserialize_str(VersionVisitor) + } +} + +impl<'de> Deserialize<'de> for VersionReq { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + struct VersionReqVisitor; + + impl<'de> Visitor<'de> for VersionReqVisitor { + type Value = VersionReq; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("semver version") + } + + fn visit_str<E>(self, string: &str) -> Result<Self::Value, E> + where + E: Error, + { + string.parse().map_err(Error::custom) + } + } + + deserializer.deserialize_str(VersionReqVisitor) + } +} diff --git a/vendor/semver/tests/node/mod.rs b/vendor/semver/tests/node/mod.rs new file mode 100644 index 0000000000..9750a3102e --- /dev/null +++ b/vendor/semver/tests/node/mod.rs @@ -0,0 +1,43 @@ +#![cfg(test_node_semver)] + +use semver::Version; +use std::fmt::{self, Display}; +use std::process::Command; + +#[derive(Eq, PartialEq, Hash, Debug)] +pub(super) struct VersionReq(semver::VersionReq); + +impl VersionReq { + pub(super) const STAR: Self = VersionReq(semver::VersionReq::STAR); + + pub(super) fn matches(&self, version: &Version) -> bool { + let out = Command::new("node") + .arg("-e") + .arg(format!( + "console.log(require('semver').satisfies('{}', '{}'))", + version, + self.to_string().replace(',', ""), + )) + .output() + .unwrap(); + if out.stdout == b"true\n" { + true + } else if out.stdout == b"false\n" { + false + } else { + let s = String::from_utf8_lossy(&out.stdout) + String::from_utf8_lossy(&out.stderr); + panic!("unexpected output: {}", s); + } + } +} + +impl Display for VersionReq { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + Display::fmt(&self.0, formatter) + } +} + +#[cfg_attr(not(no_track_caller), track_caller)] +pub(super) fn req(text: &str) -> VersionReq { + VersionReq(crate::util::req(text)) +} diff --git a/vendor/semver/tests/test_identifier.rs b/vendor/semver/tests/test_identifier.rs new file mode 100644 index 0000000000..65c9ec5577 --- /dev/null +++ b/vendor/semver/tests/test_identifier.rs @@ -0,0 +1,38 @@ +mod util; + +use crate::util::*; +use semver::Prerelease; + +#[test] +fn test_new() { + fn test(identifier: Prerelease, expected: &str) { + assert_eq!(identifier.is_empty(), expected.is_empty()); + assert_eq!(identifier.len(), expected.len()); + assert_eq!(identifier.as_str(), expected); + assert_eq!(identifier, identifier); + assert_eq!(identifier, identifier.clone()); + } + + let ref mut string = String::new(); + let limit = if cfg!(miri) { 40 } else { 280 }; // miri is slow + for _ in 0..limit { + test(prerelease(string), string); + string.push('1'); + } + + if !cfg!(miri) { + let ref string = string.repeat(20000); + test(prerelease(string), string); + } +} + +#[test] +fn test_eq() { + assert_eq!(prerelease("-"), prerelease("-")); + assert_ne!(prerelease("a"), prerelease("aa")); + assert_ne!(prerelease("aa"), prerelease("a")); + assert_ne!(prerelease("aaaaaaaaa"), prerelease("a")); + assert_ne!(prerelease("a"), prerelease("aaaaaaaaa")); + assert_ne!(prerelease("aaaaaaaaa"), prerelease("bbbbbbbbb")); + assert_ne!(build_metadata("1"), build_metadata("001")); +} diff --git a/vendor/semver/tests/test_version.rs b/vendor/semver/tests/test_version.rs new file mode 100644 index 0000000000..c262be7911 --- /dev/null +++ b/vendor/semver/tests/test_version.rs @@ -0,0 +1,235 @@ +mod util; + +use crate::util::*; +use semver::{BuildMetadata, Prerelease, Version}; + +#[test] +fn test_parse() { + let err = version_err(""); + assert_to_string( + err, + "unexpected end of input while parsing major version number", + ); + + let err = version_err(" "); + assert_to_string( + err, + "unexpected character ' ' while parsing major version number", + ); + + let err = version_err("1"); + assert_to_string( + err, + "unexpected end of input while parsing major version number", + ); + + let err = version_err("1.2"); + assert_to_string( + err, + "unexpected end of input while parsing minor version number", + ); + + let err = version_err("1.2.3-"); + assert_to_string(err, "empty identifier segment in pre-release identifier"); + + let err = version_err("a.b.c"); + assert_to_string( + err, + "unexpected character 'a' while parsing major version number", + ); + + let err = version_err("1.2.3 abc"); + assert_to_string(err, "unexpected character ' ' after patch version number"); + + let err = version_err("1.2.3-01"); + assert_to_string(err, "invalid leading zero in pre-release identifier"); + + let parsed = version("1.2.3"); + let expected = Version::new(1, 2, 3); + assert_eq!(parsed, expected); + let expected = Version { + major: 1, + minor: 2, + patch: 3, + pre: Prerelease::EMPTY, + build: BuildMetadata::EMPTY, + }; + assert_eq!(parsed, expected); + + let parsed = version("1.2.3-alpha1"); + let expected = Version { + major: 1, + minor: 2, + patch: 3, + pre: prerelease("alpha1"), + build: BuildMetadata::EMPTY, + }; + assert_eq!(parsed, expected); + + let parsed = version("1.2.3+build5"); + let expected = Version { + major: 1, + minor: 2, + patch: 3, + pre: Prerelease::EMPTY, + build: build_metadata("build5"), + }; + assert_eq!(parsed, expected); + + let parsed = version("1.2.3+5build"); + let expected = Version { + major: 1, + minor: 2, + patch: 3, + pre: Prerelease::EMPTY, + build: build_metadata("5build"), + }; + assert_eq!(parsed, expected); + + let parsed = version("1.2.3-alpha1+build5"); + let expected = Version { + major: 1, + minor: 2, + patch: 3, + pre: prerelease("alpha1"), + build: build_metadata("build5"), + }; + assert_eq!(parsed, expected); + + let parsed = version("1.2.3-1.alpha1.9+build5.7.3aedf"); + let expected = Version { + major: 1, + minor: 2, + patch: 3, + pre: prerelease("1.alpha1.9"), + build: build_metadata("build5.7.3aedf"), + }; + assert_eq!(parsed, expected); + + let parsed = version("1.2.3-0a.alpha1.9+05build.7.3aedf"); + let expected = Version { + major: 1, + minor: 2, + patch: 3, + pre: prerelease("0a.alpha1.9"), + build: build_metadata("05build.7.3aedf"), + }; + assert_eq!(parsed, expected); + + let parsed = version("0.4.0-beta.1+0851523"); + let expected = Version { + major: 0, + minor: 4, + patch: 0, + pre: prerelease("beta.1"), + build: build_metadata("0851523"), + }; + assert_eq!(parsed, expected); + + // for https://nodejs.org/dist/index.json, where some older npm versions are "1.1.0-beta-10" + let parsed = version("1.1.0-beta-10"); + let expected = Version { + major: 1, + minor: 1, + patch: 0, + pre: prerelease("beta-10"), + build: BuildMetadata::EMPTY, + }; + assert_eq!(parsed, expected); +} + +#[test] +fn test_eq() { + assert_eq!(version("1.2.3"), version("1.2.3")); + assert_eq!(version("1.2.3-alpha1"), version("1.2.3-alpha1")); + assert_eq!(version("1.2.3+build.42"), version("1.2.3+build.42")); + assert_eq!(version("1.2.3-alpha1+42"), version("1.2.3-alpha1+42")); +} + +#[test] +fn test_ne() { + assert_ne!(version("0.0.0"), version("0.0.1")); + assert_ne!(version("0.0.0"), version("0.1.0")); + assert_ne!(version("0.0.0"), version("1.0.0")); + assert_ne!(version("1.2.3-alpha"), version("1.2.3-beta")); + assert_ne!(version("1.2.3+23"), version("1.2.3+42")); +} + +#[test] +fn test_display() { + assert_to_string(version("1.2.3"), "1.2.3"); + assert_to_string(version("1.2.3-alpha1"), "1.2.3-alpha1"); + assert_to_string(version("1.2.3+build.42"), "1.2.3+build.42"); + assert_to_string(version("1.2.3-alpha1+42"), "1.2.3-alpha1+42"); +} + +#[test] +fn test_lt() { + assert!(version("0.0.0") < version("1.2.3-alpha2")); + assert!(version("1.0.0") < version("1.2.3-alpha2")); + assert!(version("1.2.0") < version("1.2.3-alpha2")); + assert!(version("1.2.3-alpha1") < version("1.2.3")); + assert!(version("1.2.3-alpha1") < version("1.2.3-alpha2")); + assert!(!(version("1.2.3-alpha2") < version("1.2.3-alpha2"))); + assert!(version("1.2.3+23") < version("1.2.3+42")); +} + +#[test] +fn test_le() { + assert!(version("0.0.0") <= version("1.2.3-alpha2")); + assert!(version("1.0.0") <= version("1.2.3-alpha2")); + assert!(version("1.2.0") <= version("1.2.3-alpha2")); + assert!(version("1.2.3-alpha1") <= version("1.2.3-alpha2")); + assert!(version("1.2.3-alpha2") <= version("1.2.3-alpha2")); + assert!(version("1.2.3+23") <= version("1.2.3+42")); +} + +#[test] +fn test_gt() { + assert!(version("1.2.3-alpha2") > version("0.0.0")); + assert!(version("1.2.3-alpha2") > version("1.0.0")); + assert!(version("1.2.3-alpha2") > version("1.2.0")); + assert!(version("1.2.3-alpha2") > version("1.2.3-alpha1")); + assert!(version("1.2.3") > version("1.2.3-alpha2")); + assert!(!(version("1.2.3-alpha2") > version("1.2.3-alpha2"))); + assert!(!(version("1.2.3+23") > version("1.2.3+42"))); +} + +#[test] +fn test_ge() { + assert!(version("1.2.3-alpha2") >= version("0.0.0")); + assert!(version("1.2.3-alpha2") >= version("1.0.0")); + assert!(version("1.2.3-alpha2") >= version("1.2.0")); + assert!(version("1.2.3-alpha2") >= version("1.2.3-alpha1")); + assert!(version("1.2.3-alpha2") >= version("1.2.3-alpha2")); + assert!(!(version("1.2.3+23") >= version("1.2.3+42"))); +} + +#[test] +fn test_spec_order() { + let vs = [ + "1.0.0-alpha", + "1.0.0-alpha.1", + "1.0.0-alpha.beta", + "1.0.0-beta", + "1.0.0-beta.2", + "1.0.0-beta.11", + "1.0.0-rc.1", + "1.0.0", + ]; + let mut i = 1; + while i < vs.len() { + let a = version(vs[i - 1]); + let b = version(vs[i]); + assert!(a < b, "nope {:?} < {:?}", a, b); + i += 1; + } +} + +#[test] +fn test_align() { + let version = version("1.2.3-rc1"); + assert_eq!("1.2.3-rc1 ", format!("{:20}", version)); + assert_eq!("*****1.2.3-rc1******", format!("{:*^20}", version)); + assert_eq!(" 1.2.3-rc1", format!("{:>20}", version)); +} diff --git a/vendor/semver/tests/test_version_req.rs b/vendor/semver/tests/test_version_req.rs new file mode 100644 index 0000000000..982fcd6b2d --- /dev/null +++ b/vendor/semver/tests/test_version_req.rs @@ -0,0 +1,408 @@ +mod node; +mod util; + +use crate::util::*; +use std::collections::hash_map::DefaultHasher; +use std::hash::{Hash, Hasher}; + +#[cfg(test_node_semver)] +use node::{req, VersionReq}; +#[cfg(not(test_node_semver))] +use semver::VersionReq; + +#[cfg_attr(not(no_track_caller), track_caller)] +fn assert_match_all(req: &VersionReq, versions: &[&str]) { + for string in versions { + let parsed = version(string); + assert!(req.matches(&parsed), "did not match {}", string); + } +} + +#[cfg_attr(not(no_track_caller), track_caller)] +fn assert_match_none(req: &VersionReq, versions: &[&str]) { + for string in versions { + let parsed = version(string); + assert!(!req.matches(&parsed), "matched {}", string); + } +} + +#[test] +fn test_default() { + let ref r = req("1.0.0"); + assert_to_string(r, "^1.0.0"); + assert_match_all(r, &["1.0.0", "1.1.0", "1.0.1"]); + assert_match_none(r, &["0.9.9", "0.10.0", "0.1.0", "1.0.0-pre", "1.0.1-pre"]); +} + +#[test] +fn test_exact() { + let ref r = req("=1.0.0"); + assert_to_string(r, "=1.0.0"); + assert_match_all(r, &["1.0.0"]); + assert_match_none(r, &["1.0.1", "0.9.9", "0.10.0", "0.1.0", "1.0.0-pre"]); + + let ref r = req("=0.9.0"); + assert_to_string(r, "=0.9.0"); + assert_match_all(r, &["0.9.0"]); + assert_match_none(r, &["0.9.1", "1.9.0", "0.0.9", "0.9.0-pre"]); + + let ref r = req("=0.0.2"); + assert_to_string(r, "=0.0.2"); + assert_match_all(r, &["0.0.2"]); + assert_match_none(r, &["0.0.1", "0.0.3", "0.0.2-pre"]); + + let ref r = req("=0.1.0-beta2.a"); + assert_to_string(r, "=0.1.0-beta2.a"); + assert_match_all(r, &["0.1.0-beta2.a"]); + assert_match_none(r, &["0.9.1", "0.1.0", "0.1.1-beta2.a", "0.1.0-beta2"]); + + let ref r = req("=0.1.0+meta"); + assert_to_string(r, "=0.1.0"); + assert_match_all(r, &["0.1.0", "0.1.0+meta", "0.1.0+any"]); +} + +#[test] +pub fn test_greater_than() { + let ref r = req(">= 1.0.0"); + assert_to_string(r, ">=1.0.0"); + assert_match_all(r, &["1.0.0", "2.0.0"]); + assert_match_none(r, &["0.1.0", "0.0.1", "1.0.0-pre", "2.0.0-pre"]); + + let ref r = req(">= 2.1.0-alpha2"); + assert_to_string(r, ">=2.1.0-alpha2"); + assert_match_all(r, &["2.1.0-alpha2", "2.1.0-alpha3", "2.1.0", "3.0.0"]); + assert_match_none( + r, + &["2.0.0", "2.1.0-alpha1", "2.0.0-alpha2", "3.0.0-alpha2"], + ); +} + +#[test] +pub fn test_less_than() { + let ref r = req("< 1.0.0"); + assert_to_string(r, "<1.0.0"); + assert_match_all(r, &["0.1.0", "0.0.1"]); + assert_match_none(r, &["1.0.0", "1.0.0-beta", "1.0.1", "0.9.9-alpha"]); + + let ref r = req("<= 2.1.0-alpha2"); + assert_match_all(r, &["2.1.0-alpha2", "2.1.0-alpha1", "2.0.0", "1.0.0"]); + assert_match_none( + r, + &["2.1.0", "2.2.0-alpha1", "2.0.0-alpha2", "1.0.0-alpha2"], + ); + + let ref r = req(">1.0.0-alpha, <1.0.0"); + assert_match_all(r, &["1.0.0-beta"]); + + let ref r = req(">1.0.0-alpha, <1.0"); + assert_match_none(r, &["1.0.0-beta"]); + + let ref r = req(">1.0.0-alpha, <1"); + assert_match_none(r, &["1.0.0-beta"]); +} + +#[test] +pub fn test_multiple() { + let ref r = req("> 0.0.9, <= 2.5.3"); + assert_to_string(r, ">0.0.9, <=2.5.3"); + assert_match_all(r, &["0.0.10", "1.0.0", "2.5.3"]); + assert_match_none(r, &["0.0.8", "2.5.4"]); + + let ref r = req("0.3.0, 0.4.0"); + assert_to_string(r, "^0.3.0, ^0.4.0"); + assert_match_none(r, &["0.0.8", "0.3.0", "0.4.0"]); + + let ref r = req("<= 0.2.0, >= 0.5.0"); + assert_to_string(r, "<=0.2.0, >=0.5.0"); + assert_match_none(r, &["0.0.8", "0.3.0", "0.5.1"]); + + let ref r = req("0.1.0, 0.1.4, 0.1.6"); + assert_to_string(r, "^0.1.0, ^0.1.4, ^0.1.6"); + assert_match_all(r, &["0.1.6", "0.1.9"]); + assert_match_none(r, &["0.1.0", "0.1.4", "0.2.0"]); + + let err = req_err("> 0.1.0,"); + assert_to_string( + err, + "unexpected end of input while parsing major version number", + ); + + let err = req_err("> 0.3.0, ,"); + assert_to_string( + err, + "unexpected character ',' while parsing major version number", + ); + + let ref r = req(">=0.5.1-alpha3, <0.6"); + assert_to_string(r, ">=0.5.1-alpha3, <0.6"); + assert_match_all( + r, + &[ + "0.5.1-alpha3", + "0.5.1-alpha4", + "0.5.1-beta", + "0.5.1", + "0.5.5", + ], + ); + assert_match_none( + r, + &["0.5.1-alpha1", "0.5.2-alpha3", "0.5.5-pre", "0.5.0-pre"], + ); + assert_match_none(r, &["0.6.0", "0.6.0-pre"]); + + // https://github.com/steveklabnik/semver/issues/56 + let err = req_err("1.2.3 - 2.3.4"); + assert_to_string(err, "expected comma after patch version number, found '-'"); +} + +#[test] +pub fn test_whitespace_delimited_comparator_sets() { + // https://github.com/steveklabnik/semver/issues/55 + let err = req_err("> 0.0.9 <= 2.5.3"); + assert_to_string(err, "expected comma after patch version number, found '<'"); +} + +#[test] +pub fn test_tilde() { + let ref r = req("~1"); + assert_match_all(r, &["1.0.0", "1.0.1", "1.1.1"]); + assert_match_none(r, &["0.9.1", "2.9.0", "0.0.9"]); + + let ref r = req("~1.2"); + assert_match_all(r, &["1.2.0", "1.2.1"]); + assert_match_none(r, &["1.1.1", "1.3.0", "0.0.9"]); + + let ref r = req("~1.2.2"); + assert_match_all(r, &["1.2.2", "1.2.4"]); + assert_match_none(r, &["1.2.1", "1.9.0", "1.0.9", "2.0.1", "0.1.3"]); + + let ref r = req("~1.2.3-beta.2"); + assert_match_all(r, &["1.2.3", "1.2.4", "1.2.3-beta.2", "1.2.3-beta.4"]); + assert_match_none(r, &["1.3.3", "1.1.4", "1.2.3-beta.1", "1.2.4-beta.2"]); +} + +#[test] +pub fn test_caret() { + let ref r = req("^1"); + assert_match_all(r, &["1.1.2", "1.1.0", "1.2.1", "1.0.1"]); + assert_match_none(r, &["0.9.1", "2.9.0", "0.1.4"]); + assert_match_none(r, &["1.0.0-beta1", "0.1.0-alpha", "1.0.1-pre"]); + + let ref r = req("^1.1"); + assert_match_all(r, &["1.1.2", "1.1.0", "1.2.1"]); + assert_match_none(r, &["0.9.1", "2.9.0", "1.0.1", "0.1.4"]); + + let ref r = req("^1.1.2"); + assert_match_all(r, &["1.1.2", "1.1.4", "1.2.1"]); + assert_match_none(r, &["0.9.1", "2.9.0", "1.1.1", "0.0.1"]); + assert_match_none(r, &["1.1.2-alpha1", "1.1.3-alpha1", "2.9.0-alpha1"]); + + let ref r = req("^0.1.2"); + assert_match_all(r, &["0.1.2", "0.1.4"]); + assert_match_none(r, &["0.9.1", "2.9.0", "1.1.1", "0.0.1"]); + assert_match_none(r, &["0.1.2-beta", "0.1.3-alpha", "0.2.0-pre"]); + + let ref r = req("^0.5.1-alpha3"); + assert_match_all( + r, + &[ + "0.5.1-alpha3", + "0.5.1-alpha4", + "0.5.1-beta", + "0.5.1", + "0.5.5", + ], + ); + assert_match_none( + r, + &[ + "0.5.1-alpha1", + "0.5.2-alpha3", + "0.5.5-pre", + "0.5.0-pre", + "0.6.0", + ], + ); + + let ref r = req("^0.0.2"); + assert_match_all(r, &["0.0.2"]); + assert_match_none(r, &["0.9.1", "2.9.0", "1.1.1", "0.0.1", "0.1.4"]); + + let ref r = req("^0.0"); + assert_match_all(r, &["0.0.2", "0.0.0"]); + assert_match_none(r, &["0.9.1", "2.9.0", "1.1.1", "0.1.4"]); + + let ref r = req("^0"); + assert_match_all(r, &["0.9.1", "0.0.2", "0.0.0"]); + assert_match_none(r, &["2.9.0", "1.1.1"]); + + let ref r = req("^1.4.2-beta.5"); + assert_match_all( + r, + &["1.4.2", "1.4.3", "1.4.2-beta.5", "1.4.2-beta.6", "1.4.2-c"], + ); + assert_match_none( + r, + &[ + "0.9.9", + "2.0.0", + "1.4.2-alpha", + "1.4.2-beta.4", + "1.4.3-beta.5", + ], + ); +} + +#[test] +pub fn test_wildcard() { + let err = req_err(""); + assert_to_string( + err, + "unexpected end of input while parsing major version number", + ); + + let ref r = req("*"); + assert_match_all(r, &["0.9.1", "2.9.0", "0.0.9", "1.0.1", "1.1.1"]); + assert_match_none(r, &["1.0.0-pre"]); + + for s in &["x", "X"] { + assert_eq!(*r, req(s)); + } + + let ref r = req("1.*"); + assert_match_all(r, &["1.2.0", "1.2.1", "1.1.1", "1.3.0"]); + assert_match_none(r, &["0.0.9", "1.2.0-pre"]); + + for s in &["1.x", "1.X", "1.*.*"] { + assert_eq!(*r, req(s)); + } + + let ref r = req("1.2.*"); + assert_match_all(r, &["1.2.0", "1.2.2", "1.2.4"]); + assert_match_none(r, &["1.9.0", "1.0.9", "2.0.1", "0.1.3", "1.2.2-pre"]); + + for s in &["1.2.x", "1.2.X"] { + assert_eq!(*r, req(s)); + } +} + +#[test] +pub fn test_logical_or() { + // https://github.com/steveklabnik/semver/issues/57 + let err = req_err("=1.2.3 || =2.3.4"); + assert_to_string(err, "expected comma after patch version number, found '|'"); + + let err = req_err("1.1 || =1.2.3"); + assert_to_string(err, "expected comma after minor version number, found '|'"); + + let err = req_err("6.* || 8.* || >= 10.*"); + assert_to_string(err, "expected comma after minor version number, found '|'"); +} + +#[test] +pub fn test_any() { + #[cfg(not(no_const_vec_new))] + let ref r = VersionReq::STAR; + #[cfg(no_const_vec_new)] + let ref r = VersionReq { + comparators: Vec::new(), + }; + assert_match_all(r, &["0.0.1", "0.1.0", "1.0.0"]); +} + +#[test] +pub fn test_pre() { + let ref r = req("=2.1.1-really.0"); + assert_match_all(r, &["2.1.1-really.0"]); +} + +#[test] +pub fn test_parse_errors() { + let err = req_err("\0"); + assert_to_string( + err, + "unexpected character '\\u{0}' while parsing major version number", + ); + + let err = req_err(">= >= 0.0.2"); + assert_to_string( + err, + "unexpected character '>' while parsing major version number", + ); + + let err = req_err(">== 0.0.2"); + assert_to_string( + err, + "unexpected character '=' while parsing major version number", + ); + + let err = req_err("a.0.0"); + assert_to_string( + err, + "unexpected character 'a' while parsing major version number", + ); + + let err = req_err("1.0.0-"); + assert_to_string(err, "empty identifier segment in pre-release identifier"); + + let err = req_err(">="); + assert_to_string( + err, + "unexpected end of input while parsing major version number", + ); +} + +#[test] +fn test_cargo3202() { + let ref r = req("0.*.*"); + assert_to_string(r, "0.*"); + assert_match_all(r, &["0.5.0"]); + + let ref r = req("0.0.*"); + assert_to_string(r, "0.0.*"); +} + +#[test] +fn test_digit_after_wildcard() { + let err = req_err("*.1"); + assert_to_string(err, "unexpected character after wildcard in version req"); + + let err = req_err("1.*.1"); + assert_to_string(err, "unexpected character after wildcard in version req"); + + let err = req_err(">=1.*.1"); + assert_to_string(err, "unexpected character after wildcard in version req"); +} + +#[test] +fn test_eq_hash() { + fn calculate_hash(value: impl Hash) -> u64 { + let mut hasher = DefaultHasher::new(); + value.hash(&mut hasher); + hasher.finish() + } + + assert!(req("^1") == req("^1")); + assert!(calculate_hash(req("^1")) == calculate_hash(req("^1"))); + assert!(req("^1") != req("^2")); +} + +#[test] +fn test_parsing_pre_and_build_metadata_see_issue_217() { + for op in &["=", ">", ">=", "<", "<=", "~", "^"] { + // digit then alpha + req(&format!("{} 1.2.3-1a", op)); + req(&format!("{} 1.2.3+1a", op)); + + // digit then alpha (leading zero) + req(&format!("{} 1.2.3-01a", op)); + req(&format!("{} 1.2.3+01", op)); + + // multiple + req(&format!("{} 1.2.3-1+1", op)); + req(&format!("{} 1.2.3-1-1+1-1-1", op)); + req(&format!("{} 1.2.3-1a+1a", op)); + req(&format!("{} 1.2.3-1a-1a+1a-1a-1a", op)); + } +} diff --git a/vendor/semver/tests/util/mod.rs b/vendor/semver/tests/util/mod.rs new file mode 100644 index 0000000000..5cc142c484 --- /dev/null +++ b/vendor/semver/tests/util/mod.rs @@ -0,0 +1,39 @@ +#![allow(dead_code)] + +use semver::{BuildMetadata, Error, Prerelease, Version, VersionReq}; +use std::fmt::Display; + +#[cfg_attr(not(no_track_caller), track_caller)] +pub(super) fn version(text: &str) -> Version { + Version::parse(text).unwrap() +} + +#[cfg_attr(not(no_track_caller), track_caller)] +pub(super) fn version_err(text: &str) -> Error { + Version::parse(text).unwrap_err() +} + +#[cfg_attr(not(no_track_caller), track_caller)] +pub(super) fn req(text: &str) -> VersionReq { + VersionReq::parse(text).unwrap() +} + +#[cfg_attr(not(no_track_caller), track_caller)] +pub(super) fn req_err(text: &str) -> Error { + VersionReq::parse(text).unwrap_err() +} + +#[cfg_attr(not(no_track_caller), track_caller)] +pub(super) fn prerelease(text: &str) -> Prerelease { + Prerelease::new(text).unwrap() +} + +#[cfg_attr(not(no_track_caller), track_caller)] +pub(super) fn build_metadata(text: &str) -> BuildMetadata { + BuildMetadata::new(text).unwrap() +} + +#[cfg_attr(not(no_track_caller), track_caller)] +pub(super) fn assert_to_string(value: impl Display, expected: &str) { + assert_eq!(value.to_string(), expected); +} diff --git a/vendor/serde_json/.cargo-checksum.json b/vendor/serde_json/.cargo-checksum.json index 342136f048..0fdab239ef 100644 --- a/vendor/serde_json/.cargo-checksum.json +++ b/vendor/serde_json/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"0a8b6619534534d5c48cd79dcc8be30feec29cad57aebb16f96410647445394e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"4b3cc9514970c36469bd7ffcf30dcaa86b876f3c9e4720142d2414cb042e976e","build.rs":"daedcb68b22aa393d96aa2276e8b84e86c2353a2a3594040e66ed2ff08b2b0d4","src/de.rs":"125995e2a473ba5d56d71889737d325f2cefe482ab86c0a3608c9608946004bf","src/error.rs":"794a2953df09ffae60ee1d14a3c868f3838e40cbd08ba147fc27f5fd4aec40ea","src/features_check/error.rs":"d7359f864afbfe105a38abea9f563dc423036ebc4c956a5695a4beef144dc7ec","src/features_check/mod.rs":"2209f8d5c46b50c8a3b8dc22338dcaf0135d192e8b05d2f456cbe6a73104e958","src/io/core.rs":"ebe5bd5d74892fdfb630073a7961beaab18dfa155d6c551d18c2bb0e52947f99","src/io/mod.rs":"fd1ed5080495cab21117f6f7d3c2c9e3687cad0c69a0cd087b08a145a9e672da","src/iter.rs":"f832c469cd7999d26ba9b76baa69b257a212a7edb3dfdf9b1d1bb35e8da85fa9","src/lexical/algorithm.rs":"e35fb1d0c99cc706b0e3bd6d9fb4db25ecd5743fdba62aa45980637d12420704","src/lexical/bhcomp.rs":"56a36b0c06b962b0c620739fd5201e6ab529ef872582f297ed5ce845db8f1721","src/lexical/bignum.rs":"5fbab729044cbd9b0b63d8e2443a31f958828abfbe03a365a454856dfcf64750","src/lexical/cached.rs":"0e127398691f8042c19cde209e7f4b0161f0f3150342430145929f711e6fdac8","src/lexical/cached_float80.rs":"0f8f74a22cb7d871322a9893bffd0255ca10bf9dffd13afb2462dd3d7f51805f","src/lexical/digit.rs":"a265b9072194a62a67dfc4df3c86d4213097cf3f82280d025e0012a5a262fd9d","src/lexical/errors.rs":"6bc993febceb7dd96ac1c8c5c53b5f5a30297016c0f813ed8ff8d7938d01534d","src/lexical/exponent.rs":"387e945b97dc7ba48a7091c50d228a0dde3a1c4145703d4ab9c31191a91693b0","src/lexical/float.rs":"f3e6bd9abd88d50d82803fa550f8307112c25cccc0259218a382b7c8a1e899f5","src/lexical/large_powers.rs":"34537f5c701afce1ec2a1fd3c14950381b2e27c9ad74f002c91f3708e8da9ca5","src/lexical/large_powers32.rs":"d533037c6141e6671102aee490c9cdeaba81e667ddca781b2b99db2c455e4a1a","src/lexical/large_powers64.rs":"745dd7c0cbe499eec027ef586248881011d9df20c7efab7929c1807b59886ba1","src/lexical/math.rs":"78beaf6d38105b92b8252731d2b0bb8643e974a5b024ec29d649441d1b064863","src/lexical/mod.rs":"4b4c5228779c0f135a4cb018700e3bcd495da48b74421a86f6b8b304acdef924","src/lexical/num.rs":"cfc84a6769586aefec9949284e0e4c22e4480172ba7ccef6b9adeb76fc9cc825","src/lexical/parse.rs":"c2bfac4c70a19938ced61e991f4ec606764887cf12bac1a0978b5b5318a56aac","src/lexical/rounding.rs":"309e9d2cfd9f5253ae767e8cca292aee274bb57898beaf1b6b247674c064d321","src/lexical/shift.rs":"d932e88d13fab783ede722295cb958bf974b4606ea925445cad81d32fdcee900","src/lexical/small_powers.rs":"4608dd218b8002435db7e1ec79d2d0fef5f47ae257b93353326d52ecc80cccda","src/lib.rs":"91afc96970fc2e3a67f17a279a1c62caae4823de34c3178560311c1b2fc34a64","src/macros.rs":"c9f23156faec8d5216d72b6a97eebd768efb3f75870a6e2beed824308587b998","src/map.rs":"c6a3700822758a0a4937ce8709579e8e76a60b4cc359a70ac62f8fd4898d0590","src/number.rs":"722536634c94e165722a40615c941de6998b644343e23432c851bef3785f4109","src/raw.rs":"134dddc1cb97f1ddb79b5c8b9ac14a1f2f02db49daa583e5f4df91b542b24b73","src/read.rs":"b754797f6388cf484c6c5093ac97f85d619da44e5bbfd741404d35a0024e8022","src/ser.rs":"9cbe44a2ba6415d6828f827dc49fabe15586eca4d8bdc6660bed71e0610f2aab","src/value/de.rs":"03a428932701c043c0884c7b32de93e11bf028d80b312685531f7b1739684754","src/value/from.rs":"a7e2a4363c539f9d64c44d26fc705bc8e1003cad1876f3a64c7eb1d537df2b2c","src/value/index.rs":"3486361b3b94ebb9cb04cde5da7bc52e37c1cbb8b6258872441d77b42db526b3","src/value/mod.rs":"62c8f387db68de2c134a085b9379fdc89f8505abad7c95bbf6c282ddcfe410b6","src/value/partial_eq.rs":"4caacbab433a29f51bfbb3ad5c93f6b08da254e8ed174e491b3ebc509747d72a","src/value/ser.rs":"def8b03dd30c61a524cd9ccab6d6d2d5d4d7b615666206efc9600e2b30272854"},"package":"0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8"} \ No newline at end of file +{"files":{"Cargo.toml":"5c4255d6df9bc38666f8839637406359e997a59d033df217e17fa1e27560de37","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"4b3cc9514970c36469bd7ffcf30dcaa86b876f3c9e4720142d2414cb042e976e","build.rs":"daedcb68b22aa393d96aa2276e8b84e86c2353a2a3594040e66ed2ff08b2b0d4","src/de.rs":"125995e2a473ba5d56d71889737d325f2cefe482ab86c0a3608c9608946004bf","src/error.rs":"794a2953df09ffae60ee1d14a3c868f3838e40cbd08ba147fc27f5fd4aec40ea","src/features_check/error.rs":"d7359f864afbfe105a38abea9f563dc423036ebc4c956a5695a4beef144dc7ec","src/features_check/mod.rs":"2209f8d5c46b50c8a3b8dc22338dcaf0135d192e8b05d2f456cbe6a73104e958","src/io/core.rs":"ebe5bd5d74892fdfb630073a7961beaab18dfa155d6c551d18c2bb0e52947f99","src/io/mod.rs":"fd1ed5080495cab21117f6f7d3c2c9e3687cad0c69a0cd087b08a145a9e672da","src/iter.rs":"f832c469cd7999d26ba9b76baa69b257a212a7edb3dfdf9b1d1bb35e8da85fa9","src/lexical/algorithm.rs":"4fbeb1994049348d1fc388dd1a29e481f8abb8fe1e28bfebf50f3bbce5fa5fbe","src/lexical/bhcomp.rs":"56a36b0c06b962b0c620739fd5201e6ab529ef872582f297ed5ce845db8f1721","src/lexical/bignum.rs":"5fbab729044cbd9b0b63d8e2443a31f958828abfbe03a365a454856dfcf64750","src/lexical/cached.rs":"0e127398691f8042c19cde209e7f4b0161f0f3150342430145929f711e6fdac8","src/lexical/cached_float80.rs":"0f8f74a22cb7d871322a9893bffd0255ca10bf9dffd13afb2462dd3d7f51805f","src/lexical/digit.rs":"a265b9072194a62a67dfc4df3c86d4213097cf3f82280d025e0012a5a262fd9d","src/lexical/errors.rs":"6bc993febceb7dd96ac1c8c5c53b5f5a30297016c0f813ed8ff8d7938d01534d","src/lexical/exponent.rs":"387e945b97dc7ba48a7091c50d228a0dde3a1c4145703d4ab9c31191a91693b0","src/lexical/float.rs":"fe356213c92a049f4bef2f58bc0e3a26866ca06b8c1d74d0f961c5b883852cad","src/lexical/large_powers.rs":"34537f5c701afce1ec2a1fd3c14950381b2e27c9ad74f002c91f3708e8da9ca5","src/lexical/large_powers32.rs":"d533037c6141e6671102aee490c9cdeaba81e667ddca781b2b99db2c455e4a1a","src/lexical/large_powers64.rs":"745dd7c0cbe499eec027ef586248881011d9df20c7efab7929c1807b59886ba1","src/lexical/math.rs":"3b39df7d3a4fde0492e7199a603b45f398f37208ce654ec5b011b6ef0ad363d6","src/lexical/mod.rs":"4b4c5228779c0f135a4cb018700e3bcd495da48b74421a86f6b8b304acdef924","src/lexical/num.rs":"cfc84a6769586aefec9949284e0e4c22e4480172ba7ccef6b9adeb76fc9cc825","src/lexical/parse.rs":"c2bfac4c70a19938ced61e991f4ec606764887cf12bac1a0978b5b5318a56aac","src/lexical/rounding.rs":"309e9d2cfd9f5253ae767e8cca292aee274bb57898beaf1b6b247674c064d321","src/lexical/shift.rs":"d932e88d13fab783ede722295cb958bf974b4606ea925445cad81d32fdcee900","src/lexical/small_powers.rs":"4608dd218b8002435db7e1ec79d2d0fef5f47ae257b93353326d52ecc80cccda","src/lib.rs":"8a6cfff6082105bfc7b70689b90bf9b2365f268787e0cbecfdf00cc11bb1616a","src/macros.rs":"c9f23156faec8d5216d72b6a97eebd768efb3f75870a6e2beed824308587b998","src/map.rs":"c6a3700822758a0a4937ce8709579e8e76a60b4cc359a70ac62f8fd4898d0590","src/number.rs":"3d00939c0766d46bd3f2caf3a84a5d713ed8b4aa66d398cafe4b509eb27f91cc","src/raw.rs":"134dddc1cb97f1ddb79b5c8b9ac14a1f2f02db49daa583e5f4df91b542b24b73","src/read.rs":"53dc4236c6ce4b8d5b676fbe5c9c5c59b81134b59d5e8babca35221ca296d456","src/ser.rs":"59b78b97bdeddb591ed1117242bc97c7cbd267dbd2a41e09df35dadcb867b4e6","src/value/de.rs":"03a428932701c043c0884c7b32de93e11bf028d80b312685531f7b1739684754","src/value/from.rs":"a7e2a4363c539f9d64c44d26fc705bc8e1003cad1876f3a64c7eb1d537df2b2c","src/value/index.rs":"3486361b3b94ebb9cb04cde5da7bc52e37c1cbb8b6258872441d77b42db526b3","src/value/mod.rs":"62c8f387db68de2c134a085b9379fdc89f8505abad7c95bbf6c282ddcfe410b6","src/value/partial_eq.rs":"4caacbab433a29f51bfbb3ad5c93f6b08da254e8ed174e491b3ebc509747d72a","src/value/ser.rs":"def8b03dd30c61a524cd9ccab6d6d2d5d4d7b615666206efc9600e2b30272854"},"package":"e466864e431129c7e0d3476b92f20458e5879919a0596c6472738d9fa2d342f8"} \ No newline at end of file diff --git a/vendor/serde_json/Cargo.toml b/vendor/serde_json/Cargo.toml index bf7879d46d..2b61e88eb7 100644 --- a/vendor/serde_json/Cargo.toml +++ b/vendor/serde_json/Cargo.toml @@ -11,8 +11,9 @@ [package] edition = "2018" +rust-version = "1.31" name = "serde_json" -version = "1.0.68" +version = "1.0.69" authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"] include = ["build.rs", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] description = "A JSON serialization file format" @@ -59,7 +60,7 @@ version = "1.0" version = "0.1" [dev-dependencies.trybuild] -version = "1.0.19" +version = "1.0.49" features = ["diff"] [features] diff --git a/vendor/serde_json/src/lexical/algorithm.rs b/vendor/serde_json/src/lexical/algorithm.rs index d01e5b950d..a2cbf18aff 100644 --- a/vendor/serde_json/src/lexical/algorithm.rs +++ b/vendor/serde_json/src/lexical/algorithm.rs @@ -133,7 +133,7 @@ where let shift = fp.normalize(); errors <<= shift; - u64::error_is_accurate::<F>(errors, &fp) + u64::error_is_accurate::<F>(errors, fp) } } diff --git a/vendor/serde_json/src/lexical/float.rs b/vendor/serde_json/src/lexical/float.rs index e320ead16e..2d434a29cb 100644 --- a/vendor/serde_json/src/lexical/float.rs +++ b/vendor/serde_json/src/lexical/float.rs @@ -108,7 +108,7 @@ impl ExtendedFloat { F: Float, Algorithm: FnOnce(&mut ExtendedFloat, i32), { - round_to_native::<F, _>(self, algorithm) + round_to_native::<F, _>(self, algorithm); } // FROM diff --git a/vendor/serde_json/src/lexical/math.rs b/vendor/serde_json/src/lexical/math.rs index 4890c0fa30..45fb00d15e 100644 --- a/vendor/serde_json/src/lexical/math.rs +++ b/vendor/serde_json/src/lexical/math.rs @@ -613,7 +613,7 @@ mod large { /// AddAssign bigint to bigint. #[inline] pub fn iadd(x: &mut Vec<Limb>, y: &[Limb]) { - iadd_impl(x, y, 0) + iadd_impl(x, y, 0); } /// Add bigint to bigint. @@ -859,13 +859,13 @@ pub(crate) trait Math: Clone + Sized + Default { /// Multiply by a power of 2. #[inline] fn imul_pow2(&mut self, n: u32) { - self.ishl(n as usize) + self.ishl(n as usize); } /// Multiply by a power of 5. #[inline] fn imul_pow5(&mut self, n: u32) { - small::imul_pow5(self.data_mut(), n) + small::imul_pow5(self.data_mut(), n); } /// MulAssign by a power of 10. diff --git a/vendor/serde_json/src/lib.rs b/vendor/serde_json/src/lib.rs index 319ce71658..11ce1dc7ce 100644 --- a/vendor/serde_json/src/lib.rs +++ b/vendor/serde_json/src/lib.rs @@ -300,8 +300,7 @@ //! [macro]: https://docs.serde.rs/serde_json/macro.json.html //! [`serde-json-core`]: https://github.com/rust-embedded-community/serde-json-core -#![doc(html_root_url = "https://docs.rs/serde_json/1.0.68")] -#![deny(clippy::all, clippy::pedantic)] +#![doc(html_root_url = "https://docs.rs/serde_json/1.0.69")] // Ignored clippy lints #![allow( clippy::comparison_chain, @@ -380,7 +379,7 @@ mod lib { pub use self::core::convert::{self, From, Into}; pub use self::core::default::{self, Default}; pub use self::core::fmt::{self, Debug, Display}; - pub use self::core::hash::{self, Hash}; + pub use self::core::hash::{self, Hash, Hasher}; pub use self::core::iter::FusedIterator; pub use self::core::marker::{self, PhantomData}; pub use self::core::ops::{Bound, RangeBounds}; diff --git a/vendor/serde_json/src/number.rs b/vendor/serde_json/src/number.rs index c1476189b0..dfac7535e1 100644 --- a/vendor/serde_json/src/number.rs +++ b/vendor/serde_json/src/number.rs @@ -16,13 +16,13 @@ use serde::de::{IntoDeserializer, MapAccess}; pub(crate) const TOKEN: &str = "$serde_json::private::Number"; /// Represents a JSON number, whether integer or floating point. -#[derive(Clone, Eq, PartialEq)] +#[derive(Clone, PartialEq, Eq, Hash)] pub struct Number { n: N, } #[cfg(not(feature = "arbitrary_precision"))] -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone)] enum N { PosInt(u64), /// Always less than zero. @@ -31,10 +31,42 @@ enum N { Float(f64), } +#[cfg(not(feature = "arbitrary_precision"))] +impl PartialEq for N { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (N::PosInt(a), N::PosInt(b)) => a == b, + (N::NegInt(a), N::NegInt(b)) => a == b, + (N::Float(a), N::Float(b)) => a == b, + _ => false, + } + } +} + // Implementing Eq is fine since any float values are always finite. #[cfg(not(feature = "arbitrary_precision"))] impl Eq for N {} +#[cfg(not(feature = "arbitrary_precision"))] +impl Hash for N { + fn hash<H: Hasher>(&self, h: &mut H) { + match *self { + N::PosInt(i) => i.hash(h), + N::NegInt(i) => i.hash(h), + N::Float(f) => { + if f == 0.0f64 { + // There are 2 zero representations, +0 and -0, which + // compare equal but have different bits. We use the +0 hash + // for both so that hash(+0) == hash(-0). + 0.0f64.to_bits().hash(h); + } else { + f.to_bits().hash(h); + } + } + } + } +} + #[cfg(feature = "arbitrary_precision")] type N = String; @@ -130,7 +162,7 @@ impl Number { { for c in self.n.chars() { if c == '.' || c == 'e' || c == 'E' { - return self.n.parse::<f64>().ok().map_or(false, |f| f.is_finite()); + return self.n.parse::<f64>().ok().map_or(false, f64::is_finite); } } false diff --git a/vendor/serde_json/src/read.rs b/vendor/serde_json/src/read.rs index 8ed3d7d831..85514db03d 100644 --- a/vendor/serde_json/src/read.rs +++ b/vendor/serde_json/src/read.rs @@ -677,7 +677,7 @@ impl<'a> Read<'a> for StrRead<'a> { #[cfg(feature = "raw_value")] fn begin_raw_buffering(&mut self) { - self.delegate.begin_raw_buffering() + self.delegate.begin_raw_buffering(); } #[cfg(feature = "raw_value")] @@ -753,7 +753,7 @@ where #[cfg(feature = "raw_value")] fn begin_raw_buffering(&mut self) { - R::begin_raw_buffering(self) + R::begin_raw_buffering(self); } #[cfg(feature = "raw_value")] diff --git a/vendor/serde_json/src/ser.rs b/vendor/serde_json/src/ser.rs index 54b0bf2205..6637981f5d 100644 --- a/vendor/serde_json/src/ser.rs +++ b/vendor/serde_json/src/ser.rs @@ -756,7 +756,7 @@ where #[cfg(feature = "arbitrary_precision")] Compound::Number { ref mut ser, .. } => { if key == crate::number::TOKEN { - tri!(value.serialize(NumberStrEmitter(&mut *ser))); + tri!(value.serialize(NumberStrEmitter(ser))); Ok(()) } else { Err(invalid_number()) @@ -765,7 +765,7 @@ where #[cfg(feature = "raw_value")] Compound::RawValue { ref mut ser, .. } => { if key == crate::raw::TOKEN { - tri!(value.serialize(RawValueStrEmitter(&mut *ser))); + tri!(value.serialize(RawValueStrEmitter(ser))); Ok(()) } else { Err(invalid_raw_value()) diff --git a/vendor/sharded-slab/.cargo-checksum.json b/vendor/sharded-slab/.cargo-checksum.json index 5a093c46e6..2b594b836e 100644 --- a/vendor/sharded-slab/.cargo-checksum.json +++ b/vendor/sharded-slab/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"a3275390240da091be3007b24158444150d6e2256402f67a04ba60f9d91c3c0e","Cargo.toml":"55bbf8643f644e32cae7e41062293e99867d4b9277dd9fd2719cef37e0227da2","LICENSE":"eafbfa606bc005ed7fd2f623d65af17ffe4ef7c017221ac14405bf4140771ea9","README.md":"67d9378ca4eb6336a76616d74fe33f1bcf7fbafcff059efd6e11ddce1717c92d","benches/bench.rs":"6fad53f1d01c988240e827e5ceff8cf78ce4ac7e3eb0a72d7ddc6306741dd619","bin/loom.sh":"903241204befb0f1f6e7ea98e2a24244c98e8567595c03af42f65b78a4b231c1","src/cfg.rs":"b26b129bd1e27f279f76b4ce3a7e2d22b092077be50dab3cfde195d6ea662d2d","src/clear.rs":"765537aa6a4c65d9b42d6eb46b3dd801c2723b5c5b6bcdcabf671d63278f938e","src/implementation.rs":"8c3abf4f37c432a9ecf841676055c929ab8043185fd8d39d0828f4605e608f4c","src/iter.rs":"a6880250c411471842cac8b9d28b7cbba4600ef33958530fd39ab54fbe2fdbe0","src/lib.rs":"c30055e3162bf0a44b07df5aff922ac21aeb6767466360ae2b2d6a52230b5529","src/macros.rs":"3d22bc75b29c551e8a8cde347e61ebe7c981862190ca82bbf5f529ff7ec1d1dd","src/page/mod.rs":"1c61f1b42e2fab7e402ee22edac0dc71101da833fe4139651f4c79139e42d277","src/page/slot.rs":"053f3090af39e5d5205a969b808bf29eda34ce31e1c40c79b9e4ccfd60220332","src/page/stack.rs":"549853d1a2c1c15987eee89d4327c4592f274c3cc1c5b695e419bd460f61c5c4","src/pool.rs":"393f4326610f8686655dec2e722002f7dfb4a7ef4f7b33d442c392da90e50f17","src/shard.rs":"3938da1732b887238a0c4589f6748f35669fed26b6ad916debb2a890bf876b98","src/sync.rs":"9ad35bbb515f7e56c62b9e5e048a147a3490b419e2ebe79f66047674953f1689","src/tests/loom_pool.rs":"363bb7fbd6b99b870cc51ae3eb5b5a9cc02e5ef7ba0e5b83a495d7f1aab58dcc","src/tests/loom_slab.rs":"3d230cdf0048f02fc5046038e1574bc9c5f61972952aa21d86992e856161d3e6","src/tests/mod.rs":"44808a038c645f16ec26658a835fee815850f06563a2e680136b0fdbe6e44e39","src/tid.rs":"6a87728bebb947a47a9593d0274d1c332f4f6c4ffc733211546dc447de55d913"},"package":"740223c51853f3145fe7c90360d2d4232f2b62e3449489c207eccde818979982"} \ No newline at end of file +{"files":{"CHANGELOG.md":"9c0e06d18ed28fa4c4f0e010e392c0b3562c8ada22fcc2f22133d654686c7f15","Cargo.toml":"5967b83356e0272aa80a10f37dbec0bc2968f08bee6626c83a5be74d32ce767e","IMPLEMENTATION.md":"c192c8288dffc0ecbf41d59ae8b1664ea9b323b3dd16f99f3041019b464fb55e","LICENSE":"eafbfa606bc005ed7fd2f623d65af17ffe4ef7c017221ac14405bf4140771ea9","README.md":"4406c839a896217ab92e2f17d9162270d57b24204bcbbb12284a66cc72f3a40a","benches/bench.rs":"dd2b45ae38b3480537649d8fef80d566aa71c21933b59f3bb2200eb1793adc3b","bin/loom.sh":"903241204befb0f1f6e7ea98e2a24244c98e8567595c03af42f65b78a4b231c1","src/cfg.rs":"b26b129bd1e27f279f76b4ce3a7e2d22b092077be50dab3cfde195d6ea662d2d","src/clear.rs":"765537aa6a4c65d9b42d6eb46b3dd801c2723b5c5b6bcdcabf671d63278f938e","src/implementation.rs":"dec81aebb88e006ab405256fb16e8ecca6b07c3582c1c803bdfcc2a84b1d21cf","src/iter.rs":"a6880250c411471842cac8b9d28b7cbba4600ef33958530fd39ab54fbe2fdbe0","src/lib.rs":"b881289761889e91f7963a5e6d7d12377dc4600cac7b63fd69b06c8e2054d178","src/macros.rs":"3d22bc75b29c551e8a8cde347e61ebe7c981862190ca82bbf5f529ff7ec1d1dd","src/page/mod.rs":"1c61f1b42e2fab7e402ee22edac0dc71101da833fe4139651f4c79139e42d277","src/page/slot.rs":"053f3090af39e5d5205a969b808bf29eda34ce31e1c40c79b9e4ccfd60220332","src/page/stack.rs":"549853d1a2c1c15987eee89d4327c4592f274c3cc1c5b695e419bd460f61c5c4","src/pool.rs":"cf04cec4e24984a40c9300dc86baf6fb79432be7cd3a2276ad69a0c932be4098","src/shard.rs":"dd2e97d1357f7792b56a37d09e9598ccecfab3e3f8e602a3cf562978fa20e888","src/sync.rs":"9ad35bbb515f7e56c62b9e5e048a147a3490b419e2ebe79f66047674953f1689","src/tests/loom_pool.rs":"363bb7fbd6b99b870cc51ae3eb5b5a9cc02e5ef7ba0e5b83a495d7f1aab58dcc","src/tests/loom_slab.rs":"3d230cdf0048f02fc5046038e1574bc9c5f61972952aa21d86992e856161d3e6","src/tests/mod.rs":"44808a038c645f16ec26658a835fee815850f06563a2e680136b0fdbe6e44e39","src/tid.rs":"6a87728bebb947a47a9593d0274d1c332f4f6c4ffc733211546dc447de55d913"},"package":"900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31"} \ No newline at end of file diff --git a/vendor/sharded-slab/CHANGELOG.md b/vendor/sharded-slab/CHANGELOG.md index 7a3b21b09a..9dc7c2f700 100644 --- a/vendor/sharded-slab/CHANGELOG.md +++ b/vendor/sharded-slab/CHANGELOG.md @@ -1,5 +1,15 @@ -<a name="v0.1.3"></a> -### v0.1.3 (2021-08-02) +<a name="0.1.4"></a> +### 0.1.4 (2021-10-12) + + +#### Features + +* emit a nicer panic when thread count overflows `MAX_SHARDS` (#64) ([f1ed058a](https://github.com/hawkw/sharded-slab/commit/f1ed058a3ee296eff033fc0fb88f62a8b2f83f10)) + + + +<a name="0.1.3"></a> +### 0.1.3 (2021-08-02) #### Bug Fixes diff --git a/vendor/sharded-slab/Cargo.toml b/vendor/sharded-slab/Cargo.toml index a6b60a2258..210621aded 100644 --- a/vendor/sharded-slab/Cargo.toml +++ b/vendor/sharded-slab/Cargo.toml @@ -12,16 +12,19 @@ [package] edition = "2018" name = "sharded-slab" -version = "0.1.3" +version = "0.1.4" authors = ["Eliza Weisman <eliza@buoyant.io>"] description = "A lock-free concurrent slab.\n" homepage = "https://github.com/hawkw/sharded-slab" -documentation = "https://docs.rs/sharded-slab/0.1.3/sharded_slab" +documentation = "https://docs.rs/sharded-slab/0.1.4/sharded_slab" readme = "README.md" keywords = ["slab", "allocator", "lock-free", "atomic"] categories = ["memory-management", "data-structures", "concurrency"] license = "MIT" repository = "https://github.com/hawkw/sharded-slab" +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] [[bench]] name = "bench" diff --git a/vendor/sharded-slab/IMPLEMENTATION.md b/vendor/sharded-slab/IMPLEMENTATION.md new file mode 100644 index 0000000000..5494302cbc --- /dev/null +++ b/vendor/sharded-slab/IMPLEMENTATION.md @@ -0,0 +1,135 @@ +Notes on `sharded-slab`'s implementation and design. + +# Design + +The sharded slab's design is strongly inspired by the ideas presented by +Leijen, Zorn, and de Moura in [Mimalloc: Free List Sharding in +Action][mimalloc]. In this report, the authors present a novel design for a +memory allocator based on a concept of _free list sharding_. + +Memory allocators must keep track of what memory regions are not currently +allocated ("free") in order to provide them to future allocation requests. +The term [_free list_][freelist] refers to a technique for performing this +bookkeeping, where each free block stores a pointer to the next free block, +forming a linked list. The memory allocator keeps a pointer to the most +recently freed block, the _head_ of the free list. To allocate more memory, +the allocator pops from the free list by setting the head pointer to the +next free block of the current head block, and returning the previous head. +To deallocate a block, the block is pushed to the free list by setting its +first word to the current head pointer, and the head pointer is set to point +to the deallocated block. Most implementations of slab allocators backed by +arrays or vectors use a similar technique, where pointers are replaced by +indices into the backing array. + +When allocations and deallocations can occur concurrently across threads, +they must synchronize accesses to the free list; either by putting the +entire allocator state inside of a lock, or by using atomic operations to +treat the free list as a lock-free structure (such as a [Treiber stack]). In +both cases, there is a significant performance cost — even when the free +list is lock-free, it is likely that a noticeable amount of time will be +spent in compare-and-swap loops. Ideally, the global synchronzation point +created by the single global free list could be avoided as much as possible. + +The approach presented by Leijen, Zorn, and de Moura is to introduce +sharding and thus increase the granularity of synchronization significantly. +In mimalloc, the heap is _sharded_ so that each thread has its own +thread-local heap. Objects are always allocated from the local heap of the +thread where the allocation is performed. Because allocations are always +done from a thread's local heap, they need not be synchronized. + +However, since objects can move between threads before being deallocated, +_deallocations_ may still occur concurrently. Therefore, Leijen et al. +introduce a concept of _local_ and _global_ free lists. When an object is +deallocated on the same thread it was originally allocated on, it is placed +on the local free list; if it is deallocated on another thread, it goes on +the global free list for the heap of the thread from which it originated. To +allocate, the local free list is used first; if it is empty, the entire +global free list is popped onto the local free list. Since the local free +list is only ever accessed by the thread it belongs to, it does not require +synchronization at all, and because the global free list is popped from +infrequently, the cost of synchronization has a reduced impact. A majority +of allocations can occur without any synchronization at all; and +deallocations only require synchronization when an object has left its +parent thread (a relatively uncommon case). + +[mimalloc]: https://www.microsoft.com/en-us/research/uploads/prod/2019/06/mimalloc-tr-v1.pdf +[freelist]: https://en.wikipedia.org/wiki/Free_list +[Treiber stack]: https://en.wikipedia.org/wiki/Treiber_stack + +# Implementation + +A slab is represented as an array of [`MAX_THREADS`] _shards_. A shard +consists of a vector of one or more _pages_ plus associated metadata. +Finally, a page consists of an array of _slots_, head indices for the local +and remote free lists. + +```text +┌─────────────┐ +│ shard 1 │ +│ │ ┌─────────────┐ ┌────────┐ +│ pages───────┼───▶│ page 1 │ │ │ +├─────────────┤ ├─────────────┤ ┌────▶│ next──┼─┐ +│ shard 2 │ │ page 2 │ │ ├────────┤ │ +├─────────────┤ │ │ │ │XXXXXXXX│ │ +│ shard 3 │ │ local_head──┼──┘ ├────────┤ │ +└─────────────┘ │ remote_head─┼──┐ │ │◀┘ + ... ├─────────────┤ │ │ next──┼─┐ +┌─────────────┐ │ page 3 │ │ ├────────┤ │ +│ shard n │ └─────────────┘ │ │XXXXXXXX│ │ +└─────────────┘ ... │ ├────────┤ │ + ┌─────────────┐ │ │XXXXXXXX│ │ + │ page n │ │ ├────────┤ │ + └─────────────┘ │ │ │◀┘ + └────▶│ next──┼───▶ ... + ├────────┤ + │XXXXXXXX│ + └────────┘ +``` + + +The size of the first page in a shard is always a power of two, and every +subsequent page added after the first is twice as large as the page that +preceeds it. + +```text + +pg. +┌───┐ ┌─┬─┐ +│ 0 │───▶ │ │ +├───┤ ├─┼─┼─┬─┐ +│ 1 │───▶ │ │ │ │ +├───┤ ├─┼─┼─┼─┼─┬─┬─┬─┐ +│ 2 │───▶ │ │ │ │ │ │ │ │ +├───┤ ├─┼─┼─┼─┼─┼─┼─┼─┼─┬─┬─┬─┬─┬─┬─┬─┐ +│ 3 │───▶ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +└───┘ └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘ +``` + +When searching for a free slot, the smallest page is searched first, and if +it is full, the search proceeds to the next page until either a free slot is +found or all available pages have been searched. If all available pages have +been searched and the maximum number of pages has not yet been reached, a +new page is then allocated. + +Since every page is twice as large as the previous page, and all page sizes +are powers of two, we can determine the page index that contains a given +address by shifting the address down by the smallest page size and +looking at how many twos places necessary to represent that number, +telling us what power of two page size it fits inside of. We can +determine the number of twos places by counting the number of leading +zeros (unused twos places) in the number's binary representation, and +subtracting that count from the total number of bits in a word. + +The formula for determining the page number that contains an offset is thus: + +```rust,ignore +WIDTH - ((offset + INITIAL_PAGE_SIZE) >> INDEX_SHIFT).leading_zeros() +``` + +where `WIDTH` is the number of bits in a `usize`, and `INDEX_SHIFT` is + +```rust,ignore +INITIAL_PAGE_SIZE.trailing_zeros() + 1; +``` + +[`MAX_THREADS`]: https://docs.rs/sharded-slab/latest/sharded_slab/trait.Config.html#associatedconstant.MAX_THREADS diff --git a/vendor/sharded-slab/README.md b/vendor/sharded-slab/README.md index 2eab4ed1ab..ea4be64ea7 100644 --- a/vendor/sharded-slab/README.md +++ b/vendor/sharded-slab/README.md @@ -11,7 +11,7 @@ A lock-free concurrent slab. [crates-badge]: https://img.shields.io/crates/v/sharded-slab.svg [crates-url]: https://crates.io/crates/sharded-slab [docs-badge]: https://docs.rs/sharded-slab/badge.svg -[docs-url]: https://docs.rs/sharded-slab/0.1.3/sharded_slab +[docs-url]: https://docs.rs/sharded-slab/0.1.4/sharded_slab [ci-badge]: https://github.com/hawkw/sharded-slab/workflows/CI/badge.svg [ci-url]: https://github.com/hawkw/sharded-slab/actions?workflow=CI [license-badge]: https://img.shields.io/crates/l/sharded-slab @@ -57,12 +57,12 @@ _data_ they store, but retaining any previously-allocated capacity. This means that a [`Pool`] may be used to reuse a set of existing heap allocations, reducing allocator load. -[`Slab`]: https://docs.rs/sharded-slab/0.1.3/sharded_slab/struct.Slab.html -[inserting]: https://docs.rs/sharded-slab/0.1.3/sharded_slab/struct.Slab.html#method.insert -[taking]: https://docs.rs/sharded-slab/0.1.3/sharded_slab/struct.Slab.html#method.take -[`Pool`]: https://docs.rs/sharded-slab/0.1.3/sharded_slab/struct.Pool.html -[create]: https://docs.rs/sharded-slab/0.1.3/sharded_slab/struct.Pool.html#method.create -[cleared]: https://docs.rs/sharded-slab/0.1.3/sharded_slab/trait.Clear.html +[`Slab`]: https://docs.rs/sharded-slab/0.1.4/sharded_slab/struct.Slab.html +[inserting]: https://docs.rs/sharded-slab/0.1.4/sharded_slab/struct.Slab.html#method.insert +[taking]: https://docs.rs/sharded-slab/0.1.4/sharded_slab/struct.Slab.html#method.take +[`Pool`]: https://docs.rs/sharded-slab/0.1.4/sharded_slab/struct.Pool.html +[create]: https://docs.rs/sharded-slab/0.1.4/sharded_slab/struct.Pool.html#method.create +[cleared]: https://docs.rs/sharded-slab/0.1.4/sharded_slab/trait.Clear.html [object pool]: https://en.wikipedia.org/wiki/Object_pool_pattern ### Examples diff --git a/vendor/sharded-slab/benches/bench.rs b/vendor/sharded-slab/benches/bench.rs index 2316aa96fa..c95bd4e383 100644 --- a/vendor/sharded-slab/benches/bench.rs +++ b/vendor/sharded-slab/benches/bench.rs @@ -40,7 +40,7 @@ impl<T: Send + Sync + 'static> MultithreadedBench<T> { } } -const N_INSERTIONS: &'static [usize] = &[100, 300, 500, 700, 1000, 3000, 5000]; +const N_INSERTIONS: &[usize] = &[100, 300, 500, 700, 1000, 3000, 5000]; fn insert_remove_local(c: &mut Criterion) { // the 10000-insertion benchmark takes the `slab` crate about an hour to diff --git a/vendor/sharded-slab/src/implementation.rs b/vendor/sharded-slab/src/implementation.rs index 396f531e37..01f08a5824 100644 --- a/vendor/sharded-slab/src/implementation.rs +++ b/vendor/sharded-slab/src/implementation.rs @@ -27,7 +27,7 @@ //! When allocations and deallocations can occur concurrently across threads, //! they must synchronize accesses to the free list; either by putting the //! entire allocator state inside of a lock, or by using atomic operations to -//! treat the free list as a lock-free structure (such as a Treiber stack). In +//! treat the free list as a lock-free structure (such as a [Treiber stack]). In //! both cases, there is a significant performance cost — even when the free //! list is lock-free, it is likely that a noticeable amount of time will be //! spent in compare-and-swap loops. Ideally, the global synchronzation point @@ -57,6 +57,7 @@ //! //! [mimalloc]: https://www.microsoft.com/en-us/research/uploads/prod/2019/06/mimalloc-tr-v1.pdf //! [freelist]: https://en.wikipedia.org/wiki/Free_list +//! [Treiber stack]: https://en.wikipedia.org/wiki/Treiber_stack //! //! # Implementation //! @@ -64,6 +65,7 @@ //! consists of a vector of one or more _pages_ plus associated metadata. //! Finally, a page consists of an array of _slots_, head indices for the local //! and remote free lists. +//! //! ```text //! ┌─────────────┐ //! │ shard 1 │ @@ -75,7 +77,7 @@ //! │ shard 3 │ │ local_head──┼──┘ ├────────┤ │ //! └─────────────┘ │ remote_head─┼──┐ │ │◀┘ //! ... ├─────────────┤ │ │ next──┼─┐ -//! ┌─────────────┐ │ page 3 │ │ ├────────┤ │ +//! ┌─────────────┐ │ page 3 │ │ ├────────┤ │ //! │ shard n │ └─────────────┘ │ │XXXXXXXX│ │ //! └─────────────┘ ... │ ├────────┤ │ //! ┌─────────────┐ │ │XXXXXXXX│ │ @@ -87,12 +89,14 @@ //! └────────┘ //! ``` //! +//! //! The size of the first page in a shard is always a power of two, and every //! subsequent page added after the first is twice as large as the page that //! preceeds it. +//! //! ```text //! -//! pg. +//! pg. //! ┌───┐ ┌─┬─┐ //! │ 0 │───▶ │ │ //! ├───┤ ├─┼─┼─┬─┐ @@ -103,6 +107,7 @@ //! │ 3 │───▶ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ //! └───┘ └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘ //! ``` +//! //! When searching for a free slot, the smallest page is searched first, and if //! it is full, the search proceeds to the next page until either a free slot is //! found or all available pages have been searched. If all available pages have @@ -119,11 +124,15 @@ //! subtracting that count from the total number of bits in a word. //! //! The formula for determining the page number that contains an offset is thus: +//! //! ```rust,ignore //! WIDTH - ((offset + INITIAL_PAGE_SIZE) >> INDEX_SHIFT).leading_zeros() //! ``` +//! //! where `WIDTH` is the number of bits in a `usize`, and `INDEX_SHIFT` is +//! //! ```rust,ignore //! INITIAL_PAGE_SIZE.trailing_zeros() + 1; -//!``` -//![`MAX_THREADS`]: ../trait.Config.html#associatedconstant.MAX_THREADS +//! ``` +//! +//! [`MAX_THREADS`]: https://docs.rs/sharded-slab/latest/sharded_slab/trait.Config.html#associatedconstant.MAX_THREADS diff --git a/vendor/sharded-slab/src/lib.rs b/vendor/sharded-slab/src/lib.rs index 224312c8ce..e57cf50e2b 100644 --- a/vendor/sharded-slab/src/lib.rs +++ b/vendor/sharded-slab/src/lib.rs @@ -36,12 +36,10 @@ //! [`Pool`] may be used to reuse a set of existing heap allocations, reducing //! allocator load. //! -//! [`Slab`]: struct.Slab.html -//! [inserting]: struct.Slab.html#method.insert -//! [taking]: struct.Slab.html#method.take -//! [`Pool`]: struct.Pool.html -//! [create]: struct.Pool.html#method.create -//! [cleared]: trait.Clear.html +//! [inserting]: Slab::insert +//! [taking]: Slab::take +//! [create]: Pool::create +//! [cleared]: Clear //! [object pool]: https://en.wikipedia.org/wiki/Object_pool_pattern //! //! # Examples @@ -196,12 +194,12 @@ //! //! # Implementation Notes //! -//! See [this page](implementation/index.html) for details on this crate's design +//! See [this page](crate::implementation) for details on this crate's design //! and implementation. //! -#![doc(html_root_url = "https://docs.rs/sharded-slab/0.1.3")] -#![warn(missing_debug_implementations, missing_docs, missing_doc_code_examples)] - +#![doc(html_root_url = "https://docs.rs/sharded-slab/0.1.4")] +#![warn(missing_debug_implementations, missing_docs)] +#![cfg_attr(docsrs, warn(rustdoc::broken_intra_doc_links))] #[macro_use] mod macros; @@ -230,17 +228,18 @@ use std::{fmt, marker::PhantomData, ptr, sync::Arc}; /// A sharded slab. /// -/// See the [crate-level documentation](index.html) for details on using this type. +/// See the [crate-level documentation](crate) for details on using this type. pub struct Slab<T, C: cfg::Config = DefaultConfig> { shards: shard::Array<Option<T>, C>, _cfg: PhantomData<C>, } -/// A handle that allows access to an object in a slab. +/// A handle that allows access to an occupied entry in a [`Slab`]. /// /// While the guard exists, it indicates to the slab that the item the guard /// references is currently being accessed. If the item is removed from the slab -/// while a guard exists, the removal will be deferred until all guards are dropped. +/// while a guard exists, the removal will be deferred until all guards are +/// dropped. pub struct Entry<'a, T, C: cfg::Config = DefaultConfig> { inner: page::slot::Guard<Option<T>, C>, value: ptr::NonNull<T>, @@ -248,7 +247,7 @@ pub struct Entry<'a, T, C: cfg::Config = DefaultConfig> { key: usize, } -/// A handle to a vacant entry in a `Slab`. +/// A handle to a vacant entry in a [`Slab`]. /// /// `VacantEntry` allows constructing values with the key that they will be /// assigned to. @@ -277,13 +276,14 @@ pub struct VacantEntry<'a, T, C: cfg::Config = DefaultConfig> { _lt: PhantomData<&'a ()>, } -/// An owned guard that allows access to an object in a `S.ab`. +/// An owned reference to an occupied entry in a [`Slab`]. /// -/// While the guard exists, it indicates to the slab that the item the guard references is -/// currently being accessed. If the item is removed from the slab while the guard exists, the -/// removal will be deferred until all guards are dropped. +/// While the guard exists, it indicates to the slab that the item the guard +/// references is currently being accessed. If the item is removed from the slab +/// while the guard exists, the removal will be deferred until all guards are +/// dropped. /// -/// Unlike [`Entry`], which borrows the slab, an `OwnedEntry` clones the `Arc` +/// Unlike [`Entry`], which borrows the slab, an `OwnedEntry` clones the [`Arc`] /// around the slab. Therefore, it keeps the slab from being dropped until all /// such guards have been dropped. This means that an `OwnedEntry` may be held for /// an arbitrary lifetime. @@ -358,10 +358,7 @@ pub struct VacantEntry<'a, T, C: cfg::Config = DefaultConfig> { /// ``` /// /// [`get`]: Slab::get -/// [`OwnedEntry`]: crate::OwnedEntry -/// [`Entry`]: crate::Entry -/// -/// [`Entry`]: crate::Entry +/// [`Arc`]: std::sync::Arc pub struct OwnedEntry<T, C = DefaultConfig> where C: cfg::Config, @@ -399,13 +396,11 @@ impl<T, C: cfg::Config> Slab<T, C> { /// parameters. By default, all bits are used; this can be changed by /// overriding the [`Config::RESERVED_BITS`][res] constant. /// - /// [`Config`]: trait.Config.html - /// [res]: trait.Config.html#associatedconstant.RESERVED_BITS - /// [`Slab::insert`]: struct.Slab.html#method.insert + /// [res]: crate::Config#RESERVED_BITS pub const USED_BITS: usize = C::USED_BITS; - /// Inserts a value into the slab, returning a key that can be used to - /// access it. + /// Inserts a value into the slab, returning the integer index at which that + /// value was inserted. This index can then be used to access the entry. /// /// If this function returns `None`, then the shard for the current thread /// is full and no items can be added until some are removed, or the maximum @@ -434,8 +429,8 @@ impl<T, C: cfg::Config> Slab<T, C> { /// Return a handle to a vacant entry allowing for further manipulation. /// /// This function is useful when creating values that must contain their - /// slab key. The returned `VacantEntry` reserves a slot in the slab and is - /// able to query the associated key. + /// slab index. The returned [`VacantEntry`] reserves a slot in the slab and + /// is able to return the index of the entry. /// /// # Examples /// @@ -468,8 +463,8 @@ impl<T, C: cfg::Config> Slab<T, C> { }) } - /// Remove the value associated with the given key from the slab, returning - /// `true` if a value was removed. + /// Remove the value at the given index in the slab, returning `true` if a + /// value was removed. /// /// Unlike [`take`], this method does _not_ block the current thread until /// the value can be removed. Instead, if another thread is currently @@ -510,7 +505,7 @@ impl<T, C: cfg::Config> Slab<T, C> { /// thread2.join().unwrap(); /// assert!(!slab.contains(key)); /// ``` - /// [`take`]: #method.take + /// [`take`]: Slab::take pub fn remove(&self, idx: usize) -> bool { // The `Drop` impl for `Entry` calls `remove_local` or `remove_remote` based // on where the guard was dropped from. If the dropped guard was the last one, this will @@ -579,7 +574,7 @@ impl<T, C: cfg::Config> Slab<T, C> { /// thread2.join().unwrap(); /// assert!(!slab.contains(key)); /// ``` - /// [`remove`]: #method.remove + /// [`remove`]: Slab::remove pub fn take(&self, idx: usize) -> Option<T> { let tid = C::unpack_tid(idx); @@ -624,12 +619,12 @@ impl<T, C: cfg::Config> Slab<T, C> { }) } - /// Return an owned reference to the value associated with the given key. + /// Return an owned reference to the value at the given index. /// /// If the slab does not contain a value for the given key, `None` is /// returned instead. /// - /// Unlike [`get`], which borrows the slab, this method _clones_ the `Arc` + /// Unlike [`get`], which borrows the slab, this method _clones_ the [`Arc`] /// around the slab. This means that the returned [`OwnedEntry`] can be held /// for an arbitrary lifetime. However, this method requires that the slab /// itself be wrapped in an `Arc`. @@ -685,7 +680,7 @@ impl<T, C: cfg::Config> Slab<T, C> { /// function_requiring_static(&my_struct); /// ``` /// - /// `OwnedEntry`s may be sent between threads: + /// [`OwnedEntry`]s may be sent between threads: /// /// ``` /// # use sharded_slab::Slab; @@ -704,8 +699,7 @@ impl<T, C: cfg::Config> Slab<T, C> { /// ``` /// /// [`get`]: Slab::get - /// [`OwnedEntry`]: crate::OwnedEntry - /// [`Entry`]: crate::Entry + /// [`Arc`]: std::sync::Arc pub fn get_owned(self: Arc<Self>, key: usize) -> Option<OwnedEntry<T, C>> { let tid = C::unpack_tid(key); @@ -841,8 +835,8 @@ where impl<'a, T, C: cfg::Config> VacantEntry<'a, T, C> { /// Insert a value in the entry. /// - /// To get the key associated with the value, use `key` prior to calling - /// `insert`. + /// To get the integer index at which this value will be inserted, use + /// [`key`] prior to calling `insert`. /// /// # Examples /// @@ -861,6 +855,8 @@ impl<'a, T, C: cfg::Config> VacantEntry<'a, T, C> { /// assert_eq!(hello, slab.get(hello).unwrap().0); /// assert_eq!("hello", slab.get(hello).unwrap().1); /// ``` + /// + /// [`key`]: VacantEntry::key pub fn insert(mut self, val: T) { let value = unsafe { // Safety: this `VacantEntry` only lives as long as the `Slab` it was @@ -884,7 +880,7 @@ impl<'a, T, C: cfg::Config> VacantEntry<'a, T, C> { ) } - /// Return the key associated with this entry. + /// Return the integer index at which this entry will be inserted. /// /// A value stored in this entry will be associated with this key. /// diff --git a/vendor/sharded-slab/src/pool.rs b/vendor/sharded-slab/src/pool.rs index 5abb879d41..115e36eefa 100644 --- a/vendor/sharded-slab/src/pool.rs +++ b/vendor/sharded-slab/src/pool.rs @@ -74,13 +74,13 @@ use std::{fmt, marker::PhantomData, sync::Arc}; /// Both `Pool` and [`Slab`] share the same configuration mechanism. See [crate level documentation][config-doc] /// for more details. /// -/// [`Slab::take`]: ../struct.Slab.html#method.take -/// [`Slab::insert`]: ../struct.Slab.html#method.insert -/// [`Pool::create`]: struct.Pool.html#method.create -/// [`Pool::clear`]: struct.Pool.html#method.clear -/// [config-doc]: ../index.html#configuration -/// [`Clear`]: trait.Clear.html -/// [`Slab`]: struct.Slab.html +/// [`Slab::take`]: crate::Slab::take +/// [`Slab::insert`]: crate::Slab::insert +/// [`Pool::create`]: Pool::create +/// [`Pool::clear`]: Pool::clear +/// [config-doc]: crate#configuration +/// [`Clear`]: crate::Clear +/// [`Slab`]: crate::Slab pub struct Pool<T, C = DefaultConfig> where T: Clear + Default, @@ -447,7 +447,7 @@ where /// }).join().unwrap(); /// ``` /// - /// [`RefMut`]: pool/struct.RefMut.html + /// [`RefMut`]: crate::pool::RefMut pub fn create(&self) -> Option<RefMut<'_, T, C>> { let (tid, shard) = self.shards.current(); test_println!("pool: create {:?}", tid); diff --git a/vendor/sharded-slab/src/shard.rs b/vendor/sharded-slab/src/shard.rs index 960e030c8a..0d054d7e51 100644 --- a/vendor/sharded-slab/src/shard.rs +++ b/vendor/sharded-slab/src/shard.rs @@ -292,6 +292,13 @@ where let tid = Tid::<C>::current(); test_println!("current: {:?}", tid); let idx = tid.as_usize(); + assert!( + idx < self.shards.len(), + "Thread count overflowed the configured max count. \ + Thread index = {}, max threads = {}.", + idx, + C::MAX_SHARDS, + ); // It's okay for this to be relaxed. The value is only ever stored by // the thread that corresponds to the index, and we are that thread. let shard = self.shards[idx].load(Relaxed).unwrap_or_else(|| { diff --git a/vendor/syn/.cargo-checksum.json b/vendor/syn/.cargo-checksum.json index b614e9d711..9a66cafdf0 100644 --- a/vendor/syn/.cargo-checksum.json +++ b/vendor/syn/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"8284505376a36f1132cf73881d3c747c643d0007c7ed027fcbe081b94a7dc3c8","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"417bb33dc685fb0036f91229dd0d828b104a4c35010d362f2a6e5d8b4cf1e36d","benches/file.rs":"b5f458687896253823b642778ee091e42b0d423282e5c177a66d74d429cc39e6","benches/rust.rs":"9c41ecf8cff9ea278befa2f0336dea392c4e85041909ea9eff3402f15b2312c1","build.rs":"241f9e3af93b32d2d928ef9251d8ed2e67c6c64acc4aacce81f3aca58778e655","src/attr.rs":"234d9cebe2c5e92cd0f5e1117bf5755037e2e905788a337000a65d4bd82b63aa","src/await.rs":"8aa22e3c201cb2bdb6b4817fa00901f308ab06817607aa7b884c58c957705969","src/bigint.rs":"efc7f64959980653d73fe4f8bc2a3a2904dc05f45b02c6dc15cd316fa3d7c338","src/buffer.rs":"a5d6692938c2ec6ec140f70ec89fa93659fa227b52e8d381e9da7dd440f0249e","src/custom_keyword.rs":"a834c617b4a0aa87c21275ded72a4e04d7fac2d2255cfc037c0690d21488fc31","src/custom_punctuation.rs":"8a666298e774b0d326642f0f73284f6677d0d0a7c9e4a712c9c98d010b4d8a2c","src/data.rs":"ff565899aa435104a0cc6fdf3184ad4b8a4524de2f917a3efe8c3ae0559deed3","src/derive.rs":"d4205fb2b699e784c0889bcde7e80b77ab222ee74ec3c349b5b1fa63a5f3b0b0","src/discouraged.rs":"6c6a9298f8d24f578da119557bc588f3bd928f7b79fca27d6bdfe3e786dd005f","src/error.rs":"30ed3ab35ba852ac2cfc1f5f388845bf0d0576aa485f045c7da3af0fb24b9f84","src/export.rs":"d18438464c7ee1de7092c7c5d48dd9d114bdf184c1ea452c4fa709265cd19469","src/expr.rs":"dd4fffbe2b616c7cea6b2441738205157a0b52f3ebfb6f86846a77408241c9cd","src/ext.rs":"1f648cff1d705a1cea64b32b77482b97a82d2fe0aaf63b40cade91e5c02dc969","src/file.rs":"f86697655222ae294215114f4eae8e6b0b5e2a935d6c479ff8f8f889c4efd2e2","src/gen/clone.rs":"8db60fc2bf515f9a65f4e98669427ce02ed0ccc9ffdad25d8fb39b38768ecaf1","src/gen/debug.rs":"facf4fb5c7e017dd890c4a9531f337659d7b55475aa44124abf48e088ad56fc5","src/gen/eq.rs":"576a4f1e4030434b0f0170f4d681d2c46292fda64ad5f3913623e1c6e858c24f","src/gen/fold.rs":"3f59e59ed8ad2ab5dd347bfbe41bbc785c2aabd8ae902087a584a6daed597182","src/gen/hash.rs":"458052bb0d64b2a722eaeef4461af80bce109cd97d19bd44dbd608e4c53a6520","src/gen/visit.rs":"94f2c6bed4ef1cd0e83d91dddaa95730619fa48fdd4a0be2fd8740e730ff744d","src/gen/visit_mut.rs":"abc8cb67ad3300d0667761daf1e057b80b4d3f3980d94e8d6f3ed68bdcda3776","src/gen_helper.rs":"ea6c66388365971db6a2fc86cbb208f7eacde77e245bc8623f27a3642a3d7741","src/generics.rs":"0336be014dbdf3b4336d7c998204f9521ccb172fe54cc83b5acb2ea6f7e31403","src/group.rs":"d9cd30ea5bd4d453293e8e8debbe388a0360c3c766f67c8499fec453a9a43cdc","src/ident.rs":"d67975d3dd89becde96579c0454a1357aa7c62da11bdf94f29ccf63514ffbc9d","src/item.rs":"9abf51aaaa0c2fbb3c633f407fa200a3274de68ce735c7d4da9aa97905a3c3ab","src/lib.rs":"3f53df8baa19917ec4a8cf1d39bf23ed1dfa449befec6d089e9e904d12d23c0e","src/lifetime.rs":"b18862ef1e690037a4f308ea897debad7bc5038584e3b26c6d8809752ea0e3c2","src/lit.rs":"1cf2700ff9b992bfbe660654abb2af4c816765f901451a359ce450c3dd5f2651","src/lookahead.rs":"92ee63b48de02d3f6f1b09121f0fbac41d55cebc5771c8320e27df8482906152","src/mac.rs":"004cb89f9697564f6c9ee837e08ead68463ef946fb4c13c6c105adf2ba364b2b","src/macros.rs":"266590fd63a4a9d8637c6f8d36702acaace4ba59ab74c0883859efd1e260bae5","src/op.rs":"9d499022902743a6a0a19223b356449a979b90e60552d0446497d72750e646a4","src/parse.rs":"8b4aa518660dfd6310a5455b5624de01ad7ba42d11527b217f811b687b26e1fc","src/parse_macro_input.rs":"88929a1a7e5e72aa2d0b3459e52d8975afea856d159047ba4ab02ecbc5878a9c","src/parse_quote.rs":"80db945403d9731c5f3299a5819a5e2bb726c19fd9f256d50240bc32703c96b1","src/pat.rs":"c78c394b8a31bd41b3d3bec7e9746a75838a895d17e3b651c0b7d0d105426206","src/path.rs":"6e890d2d1ceb3d70ede5825d1d74eb98f8c716f444c7eb6ef5026dd610baa202","src/print.rs":"da6529c1d9d21aaf6c835f66b4e67eacb7cf91a10eb5e9a2143b49bf99b3b5e1","src/punctuated.rs":"f389f99adafde96e6d9cc5a00fe95acbaf1ea556191dde2cce98bbd8155aed23","src/reserved.rs":"e70e028bd55cfa43e23cab4ba29e4dc53a3d91eff685ef2b6e57efc2b87a3428","src/sealed.rs":"896a495a5340eec898527f18bd4ddca408ea03ea0ee3af30074ff48deace778d","src/span.rs":"748c51c6feb223c26d3b1701f5bb98aee823666c775c98106cfa24fe29d8cec1","src/spanned.rs":"3ca016a943637653ab98e373dfb826a120f3c159867346fa38a844439944eb39","src/stmt.rs":"33e575004fe74d792e19ed3753eca1f5e51dba442b4da2418e6d2b82e85a1064","src/thread.rs":"815eca6bd64f4eef7c447f0809e84108f5428ff50225224b373efd8fbb696874","src/token.rs":"5e423a696f80e281c322f37c87577f9fdc28607e9c007e24896a2b12da62d5ad","src/tt.rs":"32402645b6e82ef1e882945721b59b5fb7b0ee337d1972876362ecacef643d0f","src/ty.rs":"e4f5a4bab6ed7bdd4878e3450a9b36e5c4d9c14de342a99c105e3e93095de86a","src/verbatim.rs":"802a97df997432f18cac6e6200ff6ea29fb2474986005e0fcdbc2b65197f87f7","src/whitespace.rs":"e63dd0aa3d34029f17766a8b09c1a6e4479e36c552c8b7023d710a399333aace","tests/.gitignore":"22e782449a3c216db3f7215d5fb8882e316768e40beeec3833aae419ad8941db","tests/common/eq.rs":"3219ebde1d73c33cfd0b5761beaf8d6997a722db6309af32101f0c623d23e74d","tests/common/mod.rs":"25ef6d7daa09bad3198a0e9e91b2812425f92db7c585c1e34a03a84d7362ccd8","tests/common/parse.rs":"81580f23583723f7a2a337c4d13ebc021057cd825562fb4e474caa7cc641fed9","tests/debug/gen.rs":"e30e2b6c61feb15abe11cee86c4edff9f7e7c9c79080447d44be97869c9a3adb","tests/debug/mod.rs":"868763d0ef1609a3ad5e05e9f1bfa0f813e91e7e9a36653414a188bb2fdaa425","tests/macros/mod.rs":"a93136b172377ffebe8b68fd596a86d6625f64ed6c3d5e7f5d6ad859e25d5623","tests/repo/mod.rs":"cb7361cdc0cbb83979d0f91fd6143048c00bf0f1dd7722a3572081cb1b78f620","tests/repo/progress.rs":"c08d0314a7f3ecf760d471f27da3cd2a500aeb9f1c8331bffb2aa648f9fabf3f","tests/test_asyncness.rs":"cff01db49d28ab23b0b258bc6c0a5cc4071be4fe7248eef344a5d79d2fb649b7","tests/test_attribute.rs":"0ffd99384e1a52ae17d9fed5c4053e411e8f9018decef07ffa621d1faa7329d8","tests/test_derive_input.rs":"610444351e3bf99366976bbf1da109c334a70ac9500caef366bcf9b68819829f","tests/test_expr.rs":"e68b5827415471ccfb7efd91bbfba2f025f1cb8f993c417e7b3c0c3bec6a1fa6","tests/test_generics.rs":"9d713f90a79d6145efc89fb6f946029ca03486c632219950889da39940152ba0","tests/test_grouping.rs":"6276c3c73bba649dec5c97904ad2492879f918bc887a2c425d095c654ca0d925","tests/test_ident.rs":"9eb53d1e21edf23e7c9e14dc74dcc2b2538e9221e19dbcc0a44e3acc2e90f3f6","tests/test_item.rs":"2a8ba326963d758b5a3395bfa07375844f8e043885bb752b69be84a2fe6b4e17","tests/test_iterators.rs":"53ed6078d37550bd6765d2411e3660be401aef8a31a407350cc064a7d08c7c33","tests/test_lit.rs":"ef3f39da6ed67ba73b05eab3dda299887a455bac8e97701a90a94b636681588f","tests/test_meta.rs":"bd6910ec0eba05e814dad27dda0ea65e1f8b483e64d943213066ffd114a82b45","tests/test_parse_buffer.rs":"8bbe2d24ca8a3788f72c6908fc96c26d546f11c69687bf8d72727f851d5e2d27","tests/test_parse_stream.rs":"2f449a2c41a3dee6fd14bee24e1666a453cb808eda17332fd91afd127fcdd2a6","tests/test_pat.rs":"d4465f4fc3fd5d6e534ba8efabe1e0ed6da89de4ac7c96effa6bfb880c4287cf","tests/test_path.rs":"13ae78e958f0d7334d11f32519f593968e5503d46e29ec345feede025f16113d","tests/test_precedence.rs":"2d82f9598db3bd9d6a0d12477a4dd3e38367b31d3962586b8e057d42599a34ba","tests/test_receiver.rs":"084eca59984b9a18651da52f2c4407355da3de1335916a12477652999e2d01cc","tests/test_round_trip.rs":"a077c861e125b9b169c32ef64cb7e23e54fd05306067e067986dad4013fe13dd","tests/test_shebang.rs":"f5772cadad5b56e3112cb16308b779f92bce1c3a48091fc9933deb2276a69331","tests/test_should_parse.rs":"1d3535698a446e2755bfc360676bdb161841a1f454cdef6e7556c6d06a95c89d","tests/test_size.rs":"5fae772bab66809d6708232f35cfb4a287882486763b0f763feec2ad79fbb68b","tests/test_stmt.rs":"ff6f6f447f46a52fb544353b7dcd2cd9e60781b297dcc86551bee613beaf2280","tests/test_token_trees.rs":"43e56a701817e3c3bfd0cae54a457dd7a38ccb3ca19da41e2b995fdf20e6ed18","tests/test_ty.rs":"c59dfc8952f35befa52cf97af99098b9a042499601c78fa2ea3e169359a3ee5f","tests/test_visibility.rs":"7456fcb3a6634db509748aededff9c2d8b242d511a3e5ee3022e40b232892704","tests/zzz_stable.rs":"2a862e59cb446235ed99aec0e6ada8e16d3ecc30229b29d825b7c0bbc2602989"},"package":"5239bc68e0fef57495900cfea4e8dc75596d9a319d7e16b1e0a440d24e6fe0a0"} \ No newline at end of file +{"files":{"Cargo.toml":"fc8d519126e5af859cf02d330aa24a3f89a4a65fe7183a997302a1feaa91cff4","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"417bb33dc685fb0036f91229dd0d828b104a4c35010d362f2a6e5d8b4cf1e36d","benches/file.rs":"b5f458687896253823b642778ee091e42b0d423282e5c177a66d74d429cc39e6","benches/rust.rs":"9c41ecf8cff9ea278befa2f0336dea392c4e85041909ea9eff3402f15b2312c1","build.rs":"9c7f8cdcfd97bba0e7c893f7a2eb68e8362106cd5d2e4db9cc4bcf0652583ce1","src/attr.rs":"234d9cebe2c5e92cd0f5e1117bf5755037e2e905788a337000a65d4bd82b63aa","src/await.rs":"8aa22e3c201cb2bdb6b4817fa00901f308ab06817607aa7b884c58c957705969","src/bigint.rs":"efc7f64959980653d73fe4f8bc2a3a2904dc05f45b02c6dc15cd316fa3d7c338","src/buffer.rs":"a5d6692938c2ec6ec140f70ec89fa93659fa227b52e8d381e9da7dd440f0249e","src/custom_keyword.rs":"a834c617b4a0aa87c21275ded72a4e04d7fac2d2255cfc037c0690d21488fc31","src/custom_punctuation.rs":"8a666298e774b0d326642f0f73284f6677d0d0a7c9e4a712c9c98d010b4d8a2c","src/data.rs":"ff565899aa435104a0cc6fdf3184ad4b8a4524de2f917a3efe8c3ae0559deed3","src/derive.rs":"d4205fb2b699e784c0889bcde7e80b77ab222ee74ec3c349b5b1fa63a5f3b0b0","src/discouraged.rs":"6c6a9298f8d24f578da119557bc588f3bd928f7b79fca27d6bdfe3e786dd005f","src/error.rs":"30ed3ab35ba852ac2cfc1f5f388845bf0d0576aa485f045c7da3af0fb24b9f84","src/export.rs":"60e27ba28108b56e63981b6e946273cd159e9cae42d665dc9c6a09ad8c20046a","src/expr.rs":"dd4fffbe2b616c7cea6b2441738205157a0b52f3ebfb6f86846a77408241c9cd","src/ext.rs":"1f648cff1d705a1cea64b32b77482b97a82d2fe0aaf63b40cade91e5c02dc969","src/file.rs":"f86697655222ae294215114f4eae8e6b0b5e2a935d6c479ff8f8f889c4efd2e2","src/gen/clone.rs":"8db60fc2bf515f9a65f4e98669427ce02ed0ccc9ffdad25d8fb39b38768ecaf1","src/gen/debug.rs":"facf4fb5c7e017dd890c4a9531f337659d7b55475aa44124abf48e088ad56fc5","src/gen/eq.rs":"576a4f1e4030434b0f0170f4d681d2c46292fda64ad5f3913623e1c6e858c24f","src/gen/fold.rs":"3f59e59ed8ad2ab5dd347bfbe41bbc785c2aabd8ae902087a584a6daed597182","src/gen/hash.rs":"458052bb0d64b2a722eaeef4461af80bce109cd97d19bd44dbd608e4c53a6520","src/gen/visit.rs":"94f2c6bed4ef1cd0e83d91dddaa95730619fa48fdd4a0be2fd8740e730ff744d","src/gen/visit_mut.rs":"abc8cb67ad3300d0667761daf1e057b80b4d3f3980d94e8d6f3ed68bdcda3776","src/gen_helper.rs":"ea6c66388365971db6a2fc86cbb208f7eacde77e245bc8623f27a3642a3d7741","src/generics.rs":"ecfdff223dc80f42c6c6b382ee9629c680631ff3917ceb1e135bf36b77650024","src/group.rs":"d9cd30ea5bd4d453293e8e8debbe388a0360c3c766f67c8499fec453a9a43cdc","src/ident.rs":"d67975d3dd89becde96579c0454a1357aa7c62da11bdf94f29ccf63514ffbc9d","src/item.rs":"9abf51aaaa0c2fbb3c633f407fa200a3274de68ce735c7d4da9aa97905a3c3ab","src/lib.rs":"60b12a9b2a9bce799b5097e25af876af0fc7087f87a306e2025eff1ba41b7d54","src/lifetime.rs":"b18862ef1e690037a4f308ea897debad7bc5038584e3b26c6d8809752ea0e3c2","src/lit.rs":"61c15a44267281c9970e1994ae4b64068305957272d1fcc112c091a3257d9fad","src/lookahead.rs":"92ee63b48de02d3f6f1b09121f0fbac41d55cebc5771c8320e27df8482906152","src/mac.rs":"004cb89f9697564f6c9ee837e08ead68463ef946fb4c13c6c105adf2ba364b2b","src/macros.rs":"266590fd63a4a9d8637c6f8d36702acaace4ba59ab74c0883859efd1e260bae5","src/op.rs":"9d499022902743a6a0a19223b356449a979b90e60552d0446497d72750e646a4","src/parse.rs":"8b4aa518660dfd6310a5455b5624de01ad7ba42d11527b217f811b687b26e1fc","src/parse_macro_input.rs":"88929a1a7e5e72aa2d0b3459e52d8975afea856d159047ba4ab02ecbc5878a9c","src/parse_quote.rs":"2b3504a0e4e360b10d746968842a66e69392c680a39897a487c51097e6a4d623","src/pat.rs":"c78c394b8a31bd41b3d3bec7e9746a75838a895d17e3b651c0b7d0d105426206","src/path.rs":"6e890d2d1ceb3d70ede5825d1d74eb98f8c716f444c7eb6ef5026dd610baa202","src/print.rs":"da6529c1d9d21aaf6c835f66b4e67eacb7cf91a10eb5e9a2143b49bf99b3b5e1","src/punctuated.rs":"838fa432149d064f5d5dca6501df2e1051f15f753398493e7740aec22fe13b8c","src/reserved.rs":"e70e028bd55cfa43e23cab4ba29e4dc53a3d91eff685ef2b6e57efc2b87a3428","src/sealed.rs":"896a495a5340eec898527f18bd4ddca408ea03ea0ee3af30074ff48deace778d","src/span.rs":"748c51c6feb223c26d3b1701f5bb98aee823666c775c98106cfa24fe29d8cec1","src/spanned.rs":"3ca016a943637653ab98e373dfb826a120f3c159867346fa38a844439944eb39","src/stmt.rs":"33e575004fe74d792e19ed3753eca1f5e51dba442b4da2418e6d2b82e85a1064","src/thread.rs":"815eca6bd64f4eef7c447f0809e84108f5428ff50225224b373efd8fbb696874","src/token.rs":"5e423a696f80e281c322f37c87577f9fdc28607e9c007e24896a2b12da62d5ad","src/tt.rs":"32402645b6e82ef1e882945721b59b5fb7b0ee337d1972876362ecacef643d0f","src/ty.rs":"bfcc159ec28a78222cd14263a5f963c02da6efc2c6767d2c23f2a7734e131b2f","src/verbatim.rs":"802a97df997432f18cac6e6200ff6ea29fb2474986005e0fcdbc2b65197f87f7","src/whitespace.rs":"e63dd0aa3d34029f17766a8b09c1a6e4479e36c552c8b7023d710a399333aace","tests/.gitignore":"22e782449a3c216db3f7215d5fb8882e316768e40beeec3833aae419ad8941db","tests/common/eq.rs":"6e46500b2caae7ad16062fc2065fc12c5f308566d6a737bf8421dc0d5209565a","tests/common/mod.rs":"432ad35577f836a20b517d8c26ed994ac25fe73ef2f461c67688b61b99762015","tests/common/parse.rs":"81580f23583723f7a2a337c4d13ebc021057cd825562fb4e474caa7cc641fed9","tests/debug/gen.rs":"e30e2b6c61feb15abe11cee86c4edff9f7e7c9c79080447d44be97869c9a3adb","tests/debug/mod.rs":"73e702b67e0708a79c084b051bd47745daf12079d3c7c411dc8d7463e81f228c","tests/macros/mod.rs":"a93136b172377ffebe8b68fd596a86d6625f64ed6c3d5e7f5d6ad859e25d5623","tests/repo/mod.rs":"e9033a04f80445c5b12501f915419b1701ce24708b99db563ca8e82fd016bdc6","tests/repo/progress.rs":"c08d0314a7f3ecf760d471f27da3cd2a500aeb9f1c8331bffb2aa648f9fabf3f","tests/test_asyncness.rs":"cff01db49d28ab23b0b258bc6c0a5cc4071be4fe7248eef344a5d79d2fb649b7","tests/test_attribute.rs":"0ffd99384e1a52ae17d9fed5c4053e411e8f9018decef07ffa621d1faa7329d8","tests/test_derive_input.rs":"63f0b4d56f3f421e0bb523ce2924afe9e349f0ccefda52ccb8e1e5f342e6d525","tests/test_expr.rs":"e68b5827415471ccfb7efd91bbfba2f025f1cb8f993c417e7b3c0c3bec6a1fa6","tests/test_generics.rs":"54b7d2afc19aa6e9049585f4c8f7d3f0c29ac3bd11a2c769e9df76f18a4f5ecb","tests/test_grouping.rs":"6276c3c73bba649dec5c97904ad2492879f918bc887a2c425d095c654ca0d925","tests/test_ident.rs":"9eb53d1e21edf23e7c9e14dc74dcc2b2538e9221e19dbcc0a44e3acc2e90f3f6","tests/test_item.rs":"a3642c80066f1e7787becfd0278af90a6b7968d6c1249e25e81663aa454cfb2a","tests/test_iterators.rs":"53ed6078d37550bd6765d2411e3660be401aef8a31a407350cc064a7d08c7c33","tests/test_lit.rs":"19740ea9cd4a980bcab9b0dcaa4b032bb6ebb137fa5e4237140b97da1d9679fa","tests/test_meta.rs":"65d4586d131f6cac66694ca5e936748ec4e7f7423af6d8da509240e6be14800b","tests/test_parse_buffer.rs":"68d857f776396d064fcc0023c37093c2fbf75ee68e8241d4014d00d1423c18e9","tests/test_parse_stream.rs":"2f449a2c41a3dee6fd14bee24e1666a453cb808eda17332fd91afd127fcdd2a6","tests/test_pat.rs":"d4465f4fc3fd5d6e534ba8efabe1e0ed6da89de4ac7c96effa6bfb880c4287cf","tests/test_path.rs":"13ae78e958f0d7334d11f32519f593968e5503d46e29ec345feede025f16113d","tests/test_precedence.rs":"457e3984f33232b25ee790f85b47ed7aa9a45d3676ce6ed37070eebf9f89afda","tests/test_receiver.rs":"084eca59984b9a18651da52f2c4407355da3de1335916a12477652999e2d01cc","tests/test_round_trip.rs":"c4cbdc504fe821f3c32e2d66b1327cb25157b371dbd20204b74e2e4694d28760","tests/test_shebang.rs":"f5772cadad5b56e3112cb16308b779f92bce1c3a48091fc9933deb2276a69331","tests/test_should_parse.rs":"1d3535698a446e2755bfc360676bdb161841a1f454cdef6e7556c6d06a95c89d","tests/test_size.rs":"1aa0dd489bd844a4a9cf32a5310abd66dad1dae3ffb24fe1288b62a26bfdd8dc","tests/test_stmt.rs":"4bf9979705792cbfa8811f8eb5e1350efcbf10200ad43e38680f88c2903b9708","tests/test_token_trees.rs":"43e56a701817e3c3bfd0cae54a457dd7a38ccb3ca19da41e2b995fdf20e6ed18","tests/test_ty.rs":"bf9fe1f31a7115286f9f98cd56a749ff2a410cecf0badfa482b88860e00169a9","tests/test_visibility.rs":"7456fcb3a6634db509748aededff9c2d8b242d511a3e5ee3022e40b232892704","tests/zzz_stable.rs":"2a862e59cb446235ed99aec0e6ada8e16d3ecc30229b29d825b7c0bbc2602989"},"package":"f2afee18b8beb5a596ecb4a2dce128c719b4ba399d34126b9e4396e3f9860966"} \ No newline at end of file diff --git a/vendor/syn/Cargo.toml b/vendor/syn/Cargo.toml index f604a38018..a94a6d3937 100644 --- a/vendor/syn/Cargo.toml +++ b/vendor/syn/Cargo.toml @@ -11,8 +11,9 @@ [package] edition = "2018" +rust-version = "1.31" name = "syn" -version = "1.0.77" +version = "1.0.81" authors = ["David Tolnay <dtolnay@gmail.com>"] include = ["/benches/**", "/build.rs", "/Cargo.toml", "/LICENSE-APACHE", "/LICENSE-MIT", "/README.md", "/src/**", "/tests/**"] description = "Parser for Rust source code" @@ -38,7 +39,7 @@ required-features = ["full", "parsing"] name = "file" required-features = ["full", "parsing"] [dependencies.proc-macro2] -version = "1.0.26" +version = "1.0.32" default-features = false [dependencies.quote] diff --git a/vendor/syn/build.rs b/vendor/syn/build.rs index 25190f4c87..f16fc17698 100644 --- a/vendor/syn/build.rs +++ b/vendor/syn/build.rs @@ -19,6 +19,10 @@ fn main() { println!("cargo:rustc-cfg=syn_no_const_vec_new"); } + if compiler.minor < 56 { + println!("cargo:rustc-cfg=syn_no_negative_literal_parse"); + } + if !compiler.nightly { println!("cargo:rustc-cfg=syn_disable_nightly_tests"); } diff --git a/vendor/syn/src/export.rs b/vendor/syn/src/export.rs index 601a214b1e..d3a087841e 100644 --- a/vendor/syn/src/export.rs +++ b/vendor/syn/src/export.rs @@ -1,6 +1,5 @@ pub use std::clone::Clone; pub use std::cmp::{Eq, PartialEq}; -pub use std::convert::From; pub use std::default::Default; pub use std::fmt::{self, Debug, Formatter}; pub use std::hash::{Hash, Hasher}; diff --git a/vendor/syn/src/generics.rs b/vendor/syn/src/generics.rs index 9df6b405d3..e6e0b61bad 100644 --- a/vendor/syn/src/generics.rs +++ b/vendor/syn/src/generics.rs @@ -831,6 +831,15 @@ pub mod parsing { #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] impl Parse for TraitBound { fn parse(input: ParseStream) -> Result<Self> { + #[cfg(feature = "full")] + let tilde_const = if input.peek(Token![~]) && input.peek2(Token![const]) { + let tilde_token = input.parse::<Token![~]>()?; + let const_token = input.parse::<Token![const]>()?; + Some((tilde_token, const_token)) + } else { + None + }; + let modifier: TraitBoundModifier = input.parse()?; let lifetimes: Option<BoundLifetimes> = input.parse()?; @@ -840,6 +849,21 @@ pub mod parsing { path.segments.last_mut().unwrap().arguments = parenthesized; } + #[cfg(feature = "full")] + { + if let Some((tilde_token, const_token)) = tilde_const { + path.segments.insert( + 0, + PathSegment { + ident: Ident::new("const", const_token.span), + arguments: PathArguments::None, + }, + ); + let (_const, punct) = path.segments.pairs_mut().next().unwrap().into_tuple(); + *punct.unwrap() = Token![::](tilde_token.span); + } + } + Ok(TraitBound { paren_token: None, modifier, @@ -994,6 +1018,8 @@ mod printing { use super::*; use crate::attr::FilterAttrs; use crate::print::TokensOrDefault; + #[cfg(feature = "full")] + use crate::punctuated::Pair; use proc_macro2::TokenStream; #[cfg(feature = "full")] use proc_macro2::TokenTree; @@ -1214,9 +1240,26 @@ mod printing { impl ToTokens for TraitBound { fn to_tokens(&self, tokens: &mut TokenStream) { let to_tokens = |tokens: &mut TokenStream| { + #[cfg(feature = "full")] + let skip = match self.path.segments.pairs().next() { + Some(Pair::Punctuated(t, p)) if t.ident == "const" => { + Token![~](p.spans[0]).to_tokens(tokens); + t.to_tokens(tokens); + 1 + } + _ => 0, + }; self.modifier.to_tokens(tokens); self.lifetimes.to_tokens(tokens); - self.path.to_tokens(tokens); + #[cfg(feature = "full")] + { + self.path.leading_colon.to_tokens(tokens); + tokens.append_all(self.path.segments.pairs().skip(skip)); + } + #[cfg(not(feature = "full"))] + { + self.path.to_tokens(tokens); + } }; match &self.paren_token { Some(paren) => paren.surround(tokens, to_tokens), diff --git a/vendor/syn/src/lib.rs b/vendor/syn/src/lib.rs index deeb9d3027..6b556b97aa 100644 --- a/vendor/syn/src/lib.rs +++ b/vendor/syn/src/lib.rs @@ -250,7 +250,7 @@ //! dynamic library libproc_macro from rustc toolchain. // Syn types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/syn/1.0.77")] +#![doc(html_root_url = "https://docs.rs/syn/1.0.81")] #![cfg_attr(doc_cfg, feature(doc_cfg))] #![allow(non_camel_case_types)] // Ignored clippy lints. @@ -258,6 +258,7 @@ clippy::collapsible_match, // https://github.com/rust-lang/rust-clippy/issues/7575 clippy::doc_markdown, clippy::eval_order_dependence, + clippy::if_then_panic, clippy::inherent_to_string, clippy::large_enum_variant, clippy::manual_map, // https://github.com/rust-lang/rust-clippy/issues/6795 @@ -823,6 +824,7 @@ mod verbatim; #[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))] mod print; +#[cfg(any(feature = "full", feature = "derive"))] use crate::__private::private; //////////////////////////////////////////////////////////////////////////////// diff --git a/vendor/syn/src/lit.rs b/vendor/syn/src/lit.rs index 9ea2e8c078..33a7b44767 100644 --- a/vendor/syn/src/lit.rs +++ b/vendor/syn/src/lit.rs @@ -925,7 +925,6 @@ mod printing { mod value { use super::*; use crate::bigint::BigInt; - use proc_macro2::TokenStream; use std::char; use std::ops::{Index, RangeFrom}; @@ -1540,35 +1539,37 @@ mod value { } } + #[allow(clippy::unnecessary_wraps)] pub fn to_literal(repr: &str, digits: &str, suffix: &str) -> Option<Literal> { - if repr.starts_with('-') { - let f64_parse_finite = || digits.parse().ok().filter(|x: &f64| x.is_finite()); - let f32_parse_finite = || digits.parse().ok().filter(|x: &f32| x.is_finite()); - if suffix == "f64" { - f64_parse_finite().map(Literal::f64_suffixed) - } else if suffix == "f32" { - f32_parse_finite().map(Literal::f32_suffixed) - } else if suffix == "i64" { - digits.parse().ok().map(Literal::i64_suffixed) - } else if suffix == "i32" { - digits.parse().ok().map(Literal::i32_suffixed) - } else if suffix == "i16" { - digits.parse().ok().map(Literal::i16_suffixed) - } else if suffix == "i8" { - digits.parse().ok().map(Literal::i8_suffixed) - } else if !suffix.is_empty() { - None - } else if digits.contains('.') { - f64_parse_finite().map(Literal::f64_unsuffixed) - } else { - digits.parse().ok().map(Literal::i64_unsuffixed) - } - } else { - let stream = repr.parse::<TokenStream>().unwrap(); - match stream.into_iter().next().unwrap() { - TokenTree::Literal(l) => Some(l), - _ => unreachable!(), + #[cfg(syn_no_negative_literal_parse)] + { + // Rustc older than https://github.com/rust-lang/rust/pull/87262. + if repr.starts_with('-') { + let f64_parse_finite = || digits.parse().ok().filter(|x: &f64| x.is_finite()); + let f32_parse_finite = || digits.parse().ok().filter(|x: &f32| x.is_finite()); + return if suffix == "f64" { + f64_parse_finite().map(Literal::f64_suffixed) + } else if suffix == "f32" { + f32_parse_finite().map(Literal::f32_suffixed) + } else if suffix == "i64" { + digits.parse().ok().map(Literal::i64_suffixed) + } else if suffix == "i32" { + digits.parse().ok().map(Literal::i32_suffixed) + } else if suffix == "i16" { + digits.parse().ok().map(Literal::i16_suffixed) + } else if suffix == "i8" { + digits.parse().ok().map(Literal::i8_suffixed) + } else if !suffix.is_empty() { + None + } else if digits.contains('.') { + f64_parse_finite().map(Literal::f64_unsuffixed) + } else { + digits.parse().ok().map(Literal::i64_unsuffixed) + }; } } + let _ = digits; + let _ = suffix; + Some(repr.parse::<Literal>().unwrap()) } } diff --git a/vendor/syn/src/parse_quote.rs b/vendor/syn/src/parse_quote.rs index ec551ef973..cc283db820 100644 --- a/vendor/syn/src/parse_quote.rs +++ b/vendor/syn/src/parse_quote.rs @@ -73,11 +73,7 @@ #[macro_export] macro_rules! parse_quote { ($($tt:tt)*) => { - $crate::parse_quote::parse( - $crate::__private::From::from( - $crate::__private::quote::quote!($($tt)*) - ) - ) + $crate::parse_quote::parse($crate::__private::quote::quote!($($tt)*)) }; } diff --git a/vendor/syn/src/punctuated.rs b/vendor/syn/src/punctuated.rs index 5cf5235e5b..5e9a34bdf7 100644 --- a/vendor/syn/src/punctuated.rs +++ b/vendor/syn/src/punctuated.rs @@ -193,7 +193,7 @@ impl<T, P> Punctuated<T, P> { if self.last.is_some() { self.last.take().map(|t| Pair::End(*t)) } else { - self.inner.pop().map(|(t, d)| Pair::Punctuated(t, d)) + self.inner.pop().map(|(t, p)| Pair::Punctuated(t, p)) } } @@ -937,16 +937,16 @@ impl<T, P> Pair<T, P> { /// the final one and there is no trailing punctuation. pub fn punct(&self) -> Option<&P> { match self { - Pair::Punctuated(_, d) => Some(d), + Pair::Punctuated(_, p) => Some(p), Pair::End(_) => None, } } /// Creates a punctuated pair out of a syntax tree node and an optional /// following punctuation. - pub fn new(t: T, d: Option<P>) -> Self { - match d { - Some(d) => Pair::Punctuated(t, d), + pub fn new(t: T, p: Option<P>) -> Self { + match p { + Some(p) => Pair::Punctuated(t, p), None => Pair::End(t), } } @@ -955,7 +955,7 @@ impl<T, P> Pair<T, P> { /// optional following punctuation. pub fn into_tuple(self) -> (T, Option<P>) { match self { - Pair::Punctuated(t, d) => (t, Some(d)), + Pair::Punctuated(t, p) => (t, Some(p)), Pair::End(t) => (t, None), } } diff --git a/vendor/syn/src/ty.rs b/vendor/syn/src/ty.rs index 3df340d5d7..8a15031369 100644 --- a/vendor/syn/src/ty.rs +++ b/vendor/syn/src/ty.rs @@ -541,7 +541,7 @@ pub mod parsing { || lookahead.peek(Token![<]) { if input.peek(Token![dyn]) { - let trait_object: TypeTraitObject = input.parse()?; + let trait_object = TypeTraitObject::parse(input, allow_plus)?; return Ok(Type::TraitObject(trait_object)); } @@ -586,7 +586,12 @@ pub mod parsing { if allow_plus { while input.peek(Token![+]) { bounds.push_punct(input.parse()?); - if input.peek(Token![>]) { + if !(input.peek(Ident::peek_any) + || input.peek(Token![::]) + || input.peek(Token![?]) + || input.peek(Lifetime) + || input.peek(token::Paren)) + { break; } bounds.push_value(input.parse()?); @@ -623,7 +628,7 @@ pub mod parsing { } else if lookahead.peek(Token![!]) && !input.peek(Token![=]) { input.parse().map(Type::Never) } else if lookahead.peek(Token![impl]) { - input.parse().map(Type::ImplTrait) + TypeImplTrait::parse(input, allow_plus).map(Type::ImplTrait) } else if lookahead.peek(Token![_]) { input.parse().map(Type::Infer) } else if lookahead.peek(Lifetime) { @@ -827,13 +832,13 @@ pub mod parsing { } impl ReturnType { + #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] pub fn without_plus(input: ParseStream) -> Result<Self> { let allow_plus = false; Self::parse(input, allow_plus) } - #[doc(hidden)] - pub fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> { + pub(crate) fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> { if input.peek(Token![->]) { let arrow = input.parse()?; let ty = ambig_ty(input, allow_plus)?; @@ -847,14 +852,16 @@ pub mod parsing { #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] impl Parse for ReturnType { fn parse(input: ParseStream) -> Result<Self> { - Self::parse(input, true) + let allow_plus = true; + Self::parse(input, allow_plus) } } #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] impl Parse for TypeTraitObject { fn parse(input: ParseStream) -> Result<Self> { - Self::parse(input, true) + let allow_plus = true; + Self::parse(input, allow_plus) } } @@ -868,60 +875,67 @@ pub mod parsing { } impl TypeTraitObject { + #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] pub fn without_plus(input: ParseStream) -> Result<Self> { let allow_plus = false; Self::parse(input, allow_plus) } // Only allow multiple trait references if allow_plus is true. - #[doc(hidden)] - pub fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> { + pub(crate) fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> { Ok(TypeTraitObject { dyn_token: input.parse()?, - bounds: { - let mut bounds = Punctuated::new(); - if allow_plus { - loop { - bounds.push_value(input.parse()?); - if !input.peek(Token![+]) { - break; - } - bounds.push_punct(input.parse()?); - if input.peek(Token![>]) { - break; - } - } - } else { - bounds.push_value(input.parse()?); - } - // Just lifetimes like `'a + 'b` is not a TraitObject. - if !at_least_one_type(&bounds) { - return Err(input.error("expected at least one type")); - } - bounds - }, + bounds: Self::parse_bounds(input, allow_plus)?, }) } + + fn parse_bounds( + input: ParseStream, + allow_plus: bool, + ) -> Result<Punctuated<TypeParamBound, Token![+]>> { + let mut bounds = Punctuated::new(); + loop { + bounds.push_value(input.parse()?); + if !(allow_plus && input.peek(Token![+])) { + break; + } + bounds.push_punct(input.parse()?); + if !(input.peek(Ident::peek_any) + || input.peek(Token![::]) + || input.peek(Token![?]) + || input.peek(Lifetime) + || input.peek(token::Paren)) + { + break; + } + } + // Just lifetimes like `'a + 'b` is not a TraitObject. + if !at_least_one_type(&bounds) { + return Err(input.error("expected at least one type")); + } + Ok(bounds) + } } #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] impl Parse for TypeImplTrait { fn parse(input: ParseStream) -> Result<Self> { + let allow_plus = true; + Self::parse(input, allow_plus) + } + } + + impl TypeImplTrait { + #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] + pub fn without_plus(input: ParseStream) -> Result<Self> { + let allow_plus = false; + Self::parse(input, allow_plus) + } + + pub(crate) fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> { Ok(TypeImplTrait { impl_token: input.parse()?, - // NOTE: rust-lang/rust#34511 includes discussion about whether - // or not + should be allowed in ImplTrait directly without (). - bounds: { - let mut bounds = Punctuated::new(); - loop { - bounds.push_value(input.parse()?); - if !input.peek(Token![+]) { - break; - } - bounds.push_punct(input.parse()?); - } - bounds - }, + bounds: TypeTraitObject::parse_bounds(input, allow_plus)?, }) } } diff --git a/vendor/syn/tests/common/eq.rs b/vendor/syn/tests/common/eq.rs index e63b01098d..bebd9a8a64 100644 --- a/vendor/syn/tests/common/eq.rs +++ b/vendor/syn/tests/common/eq.rs @@ -528,7 +528,7 @@ impl SpanlessEq for TokenStream { } } -fn doc_comment<'a>( +fn doc_comment( style: AttrStyle, unescaped: Symbol, trees: &mut impl Iterator<Item = TokenTree>, diff --git a/vendor/syn/tests/common/mod.rs b/vendor/syn/tests/common/mod.rs index a1cc80a16f..2156530b7c 100644 --- a/vendor/syn/tests/common/mod.rs +++ b/vendor/syn/tests/common/mod.rs @@ -1,4 +1,5 @@ #![allow(dead_code)] +#![allow(clippy::module_name_repetitions, clippy::shadow_unrelated)] use rayon::ThreadPoolBuilder; use std::env; diff --git a/vendor/syn/tests/debug/mod.rs b/vendor/syn/tests/debug/mod.rs index cefebacef7..bac3a3d2b9 100644 --- a/vendor/syn/tests/debug/mod.rs +++ b/vendor/syn/tests/debug/mod.rs @@ -1,3 +1,9 @@ +#![allow( + clippy::no_effect_underscore_binding, + clippy::too_many_lines, + clippy::used_underscore_binding +)] + mod gen; use proc_macro2::{Ident, Literal, TokenStream}; diff --git a/vendor/syn/tests/repo/mod.rs b/vendor/syn/tests/repo/mod.rs index 1176620c11..a71daef511 100644 --- a/vendor/syn/tests/repo/mod.rs +++ b/vendor/syn/tests/repo/mod.rs @@ -1,3 +1,5 @@ +#![allow(clippy::if_then_panic)] + mod progress; use self::progress::Progress; @@ -16,13 +18,6 @@ static EXCLUDE: &[&str] = &[ // https://github.com/dtolnay/syn/issues/1051 "src/test/ui/rfc-2632-const-trait-impl/syntax.rs", - // TODO: ~const in where-clause - // https://github.com/dtolnay/syn/issues/1051 - "library/alloc/src/borrow.rs", - "src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs", - "src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs", - "src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs", - // Compile-fail expr parameter in const generic position: f::<1 + 2>() "src/test/ui/const-generics/early/closing-args-token.rs", "src/test/ui/const-generics/early/const-expression-parameter.rs", @@ -68,7 +63,7 @@ pub fn base_dir_filter(entry: &DirEntry) -> bool { if path.is_dir() { return true; // otherwise walkdir does not visit the files } - if path.extension().map(|e| e != "rs").unwrap_or(true) { + if path.extension().map_or(true, |e| e != "rs") { return false; } diff --git a/vendor/syn/tests/test_derive_input.rs b/vendor/syn/tests/test_derive_input.rs index bf1ebdb67d..93634e5772 100644 --- a/vendor/syn/tests/test_derive_input.rs +++ b/vendor/syn/tests/test_derive_input.rs @@ -1,3 +1,5 @@ +#![allow(clippy::too_many_lines)] + #[macro_use] mod macros; diff --git a/vendor/syn/tests/test_generics.rs b/vendor/syn/tests/test_generics.rs index b29434a147..330f02f4dc 100644 --- a/vendor/syn/tests/test_generics.rs +++ b/vendor/syn/tests/test_generics.rs @@ -1,3 +1,5 @@ +#![allow(clippy::too_many_lines)] + #[macro_use] mod macros; diff --git a/vendor/syn/tests/test_item.rs b/vendor/syn/tests/test_item.rs index a991e62d33..96df4b1aad 100644 --- a/vendor/syn/tests/test_item.rs +++ b/vendor/syn/tests/test_item.rs @@ -299,3 +299,38 @@ fn test_impl_type_parameter_defaults() { self_ty: Type::Tuple, }"###); } + +#[test] +fn test_impl_trait_trailing_plus() { + let tokens = quote! { + fn f() -> impl Sized + {} + }; + + snapshot!(tokens as Item, @r###" + Item::Fn { + vis: Inherited, + sig: Signature { + ident: "f", + generics: Generics, + output: Type( + Type::ImplTrait { + bounds: [ + Trait(TraitBound { + modifier: None, + path: Path { + segments: [ + PathSegment { + ident: "Sized", + arguments: None, + }, + ], + }, + }), + ], + }, + ), + }, + block: Block, + } + "###); +} diff --git a/vendor/syn/tests/test_lit.rs b/vendor/syn/tests/test_lit.rs index 099daf10ab..ebe077c617 100644 --- a/vendor/syn/tests/test_lit.rs +++ b/vendor/syn/tests/test_lit.rs @@ -1,3 +1,5 @@ +#![allow(clippy::float_cmp, clippy::non_ascii_literal)] + #[macro_use] mod macros; @@ -176,7 +178,6 @@ fn ints() { #[test] fn floats() { - #[cfg_attr(feature = "cargo-clippy", allow(float_cmp))] fn test_float(s: &str, value: f64, suffix: &str) { match lit(s) { Lit::Float(lit) => { @@ -214,12 +215,6 @@ fn negative() { assert_eq!("-1.5f64", LitFloat::new("-1.5f64", span).to_string()); } -#[test] -fn negative_overflow() { - assert!(syn::parse_str::<LitFloat>("-1.0e99f64").is_ok()); - assert!(syn::parse_str::<LitFloat>("-1.0e999f64").is_err()); -} - #[test] fn suffix() { fn get_suffix(token: &str) -> String { diff --git a/vendor/syn/tests/test_meta.rs b/vendor/syn/tests/test_meta.rs index de6cc4da8c..9b3f30deeb 100644 --- a/vendor/syn/tests/test_meta.rs +++ b/vendor/syn/tests/test_meta.rs @@ -1,3 +1,5 @@ +#![allow(clippy::shadow_unrelated, clippy::too_many_lines)] + #[macro_use] mod macros; diff --git a/vendor/syn/tests/test_parse_buffer.rs b/vendor/syn/tests/test_parse_buffer.rs index 57a3c7c38c..cc23e9ba6c 100644 --- a/vendor/syn/tests/test_parse_buffer.rs +++ b/vendor/syn/tests/test_parse_buffer.rs @@ -1,3 +1,5 @@ +#![allow(clippy::non_ascii_literal)] + use proc_macro2::{Delimiter, Group, Punct, Spacing, TokenStream, TokenTree}; use std::iter::FromIterator; use syn::parse::{discouraged::Speculative, Parse, ParseStream, Parser, Result}; @@ -10,7 +12,7 @@ fn smuggled_speculative_cursor_between_sources() { impl Parse for BreakRules { fn parse(input1: ParseStream) -> Result<Self> { let nested = |input2: ParseStream| { - input1.advance_to(&input2); + input1.advance_to(input2); Ok(Self) }; nested.parse_str("") diff --git a/vendor/syn/tests/test_precedence.rs b/vendor/syn/tests/test_precedence.rs index 8d212b03af..e97d5da74a 100644 --- a/vendor/syn/tests/test_precedence.rs +++ b/vendor/syn/tests/test_precedence.rs @@ -1,6 +1,12 @@ #![cfg(not(syn_disable_nightly_tests))] #![recursion_limit = "1024"] #![feature(rustc_private)] +#![allow( + clippy::explicit_deref_methods, + clippy::if_then_panic, + clippy::match_wildcard_for_single_variants, + clippy::too_many_lines +)] //! The tests in this module do the following: //! @@ -340,8 +346,8 @@ fn librustc_brackets(mut librustc_expr: P<ast::Expr>) -> Option<P<ast::Expr>> { /// reveal the precedence of the parsed expressions, and produce a stringified /// form of the resulting expression. fn syn_brackets(syn_expr: syn::Expr) -> syn::Expr { - use syn::fold::*; - use syn::*; + use syn::fold::{fold_expr, fold_generic_argument, fold_generic_method_argument, Fold}; + use syn::{token, Expr, ExprParen, GenericArgument, GenericMethodArgument, Pat, Stmt, Type}; struct ParenthesizeEveryExpr; impl Fold for ParenthesizeEveryExpr { @@ -417,9 +423,9 @@ fn syn_brackets(syn_expr: syn::Expr) -> syn::Expr { /// Walk through a crate collecting all expressions we can find in it. fn collect_exprs(file: syn::File) -> Vec<syn::Expr> { - use syn::fold::*; + use syn::fold::Fold; use syn::punctuated::Punctuated; - use syn::*; + use syn::{token, Expr, ExprTuple}; struct CollectExprs(Vec<Expr>); impl Fold for CollectExprs { diff --git a/vendor/syn/tests/test_round_trip.rs b/vendor/syn/tests/test_round_trip.rs index f350c3fa70..5f8bb73706 100644 --- a/vendor/syn/tests/test_round_trip.rs +++ b/vendor/syn/tests/test_round_trip.rs @@ -1,6 +1,7 @@ #![cfg(not(syn_disable_nightly_tests))] #![recursion_limit = "1024"] #![feature(rustc_private)] +#![allow(clippy::if_then_panic)] extern crate rustc_ast; extern crate rustc_errors; diff --git a/vendor/syn/tests/test_size.rs b/vendor/syn/tests/test_size.rs index 01e8401158..e172df2bc2 100644 --- a/vendor/syn/tests/test_size.rs +++ b/vendor/syn/tests/test_size.rs @@ -1,7 +1,7 @@ #![cfg(target_pointer_width = "64")] use std::mem; -use syn::*; +use syn::{Expr, Item, Lit, Pat, Type}; #[test] fn test_expr_size() { diff --git a/vendor/syn/tests/test_stmt.rs b/vendor/syn/tests/test_stmt.rs index 943d856ef6..dbe1c76589 100644 --- a/vendor/syn/tests/test_stmt.rs +++ b/vendor/syn/tests/test_stmt.rs @@ -1,3 +1,5 @@ +#![allow(clippy::non_ascii_literal)] + #[macro_use] mod macros; diff --git a/vendor/syn/tests/test_ty.rs b/vendor/syn/tests/test_ty.rs index 907fb20173..a03abaa32c 100644 --- a/vendor/syn/tests/test_ty.rs +++ b/vendor/syn/tests/test_ty.rs @@ -285,3 +285,67 @@ fn test_trait_object() { syn::parse_str::<Type>("for<'a> dyn Trait<'a>").unwrap_err(); syn::parse_str::<Type>("dyn for<'a> 'a + Trait").unwrap_err(); } + +#[test] +fn test_trailing_plus() { + #[rustfmt::skip] + let tokens = quote!(impl Trait +); + snapshot!(tokens as Type, @r###" + Type::ImplTrait { + bounds: [ + Trait(TraitBound { + modifier: None, + path: Path { + segments: [ + PathSegment { + ident: "Trait", + arguments: None, + }, + ], + }, + }), + ], + } + "###); + + #[rustfmt::skip] + let tokens = quote!(dyn Trait +); + snapshot!(tokens as Type, @r###" + Type::TraitObject { + dyn_token: Some, + bounds: [ + Trait(TraitBound { + modifier: None, + path: Path { + segments: [ + PathSegment { + ident: "Trait", + arguments: None, + }, + ], + }, + }), + ], + } + "###); + + #[rustfmt::skip] + let tokens = quote!(Trait +); + snapshot!(tokens as Type, @r###" + Type::TraitObject { + bounds: [ + Trait(TraitBound { + modifier: None, + path: Path { + segments: [ + PathSegment { + ident: "Trait", + arguments: None, + }, + ], + }, + }), + ], + } + "###); +} diff --git a/vendor/synstructure/.cargo-checksum.json b/vendor/synstructure/.cargo-checksum.json index 7e5633c577..bb02a4ca35 100644 --- a/vendor/synstructure/.cargo-checksum.json +++ b/vendor/synstructure/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"abc84d445b8b2b61cbb4698a2a9de7e37e53171cd5c2a0ff69f3aca7d3e17c6b","LICENSE":"219920e865eee70b7dcfc948a86b099e7f4fe2de01bcca2ca9a20c0a033f2b59","README.md":"a528e7356db49ea813c3290dd4f6b15d8e6c0a870cfc07a2df0f3d1381c575bf","src/lib.rs":"93474f72c378ee177cf6563f507095884c854eed02124ad475c402b9a6db3729","src/macros.rs":"e7cf1808faf5dac5ca25bd40ad99e95c2aab4f9899bd9327898761ea86271f7c"},"package":"474aaa926faa1603c40b7885a9eaea29b444d1cb2850cb7c0e37bb1a4182f4fa"} \ No newline at end of file +{"files":{"Cargo.toml":"b9f3ce31a9ac80dc24f4afac7108b7cff44399f8d7503dc4addea4d256431a73","LICENSE":"219920e865eee70b7dcfc948a86b099e7f4fe2de01bcca2ca9a20c0a033f2b59","README.md":"a528e7356db49ea813c3290dd4f6b15d8e6c0a870cfc07a2df0f3d1381c575bf","src/lib.rs":"b8d9885399b22a5ee92b51e4ca757427da07775e940b25e1573180d9e8faf7d0","src/macros.rs":"e7cf1808faf5dac5ca25bd40ad99e95c2aab4f9899bd9327898761ea86271f7c"},"package":"f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"} \ No newline at end of file diff --git a/vendor/synstructure/Cargo.toml b/vendor/synstructure/Cargo.toml index dbfc2396d0..03398567e6 100644 --- a/vendor/synstructure/Cargo.toml +++ b/vendor/synstructure/Cargo.toml @@ -3,17 +3,16 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies +# to registry (e.g., crates.io) dependencies. # -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. [package] edition = "2018" name = "synstructure" -version = "0.12.5" +version = "0.12.6" authors = ["Nika Layzell <nika@thelayzells.com>"] include = ["src/**/*", "Cargo.toml", "README.md", "LICENSE"] description = "Helper methods and macros for custom derives" diff --git a/vendor/synstructure/src/lib.rs b/vendor/synstructure/src/lib.rs index be45b683ca..2cd2b88011 100644 --- a/vendor/synstructure/src/lib.rs +++ b/vendor/synstructure/src/lib.rs @@ -346,6 +346,9 @@ pub struct BindingInfo<'a> { // These are used to determine which type parameters are avaliable. generics: &'a Generics, seen_generics: Vec<bool>, + // The original index of the binding + // this will not change when .filter() is called + index: usize, } impl<'a> ToTokens for BindingInfo<'a> { @@ -434,9 +437,10 @@ pub struct VariantAst<'a> { pub struct VariantInfo<'a> { pub prefix: Option<&'a Ident>, bindings: Vec<BindingInfo<'a>>, - omitted_fields: bool, ast: VariantAst<'a>, generics: &'a Generics, + // The original length of `bindings` before any `.filter()` calls + original_length: usize, } /// Helper function used by the VariantInfo constructor. Walks all of the types @@ -503,18 +507,20 @@ impl<'a> VariantInfo<'a> { field, generics, seen_generics: get_ty_params(field, generics), + index: i, } }) .collect::<Vec<_>>() } }; + let original_length = bindings.len(); VariantInfo { prefix, bindings, - omitted_fields: false, ast, generics, + original_length, } } @@ -536,7 +542,7 @@ impl<'a> VariantInfo<'a> { /// True if any bindings were omitted due to a `filter` call. pub fn omitted_bindings(&self) -> bool { - self.omitted_fields + self.original_length != self.bindings.len() } /// Generates the match-arm pattern which could be used to match against this Variant. @@ -571,11 +577,17 @@ impl<'a> VariantInfo<'a> { assert!(self.bindings.is_empty()); } Fields::Unnamed(..) => token::Paren(Span::call_site()).surround(&mut t, |t| { + let mut expected_index = 0; for binding in &self.bindings { + while expected_index < binding.index { + quote!(_,).to_tokens(t); + expected_index += 1; + } binding.pat().to_tokens(t); quote!(,).to_tokens(t); + expected_index += 1; } - if self.omitted_fields { + if expected_index != self.original_length { quote!(..).to_tokens(t); } }), @@ -586,7 +598,7 @@ impl<'a> VariantInfo<'a> { binding.pat().to_tokens(t); quote!(,).to_tokens(t); } - if self.omitted_fields { + if self.omitted_bindings() { quote!(..).to_tokens(t); } }), @@ -787,11 +799,7 @@ impl<'a> VariantInfo<'a> { where F: FnMut(&BindingInfo<'_>) -> bool, { - let before_len = self.bindings.len(); self.bindings.retain(f); - if self.bindings.len() != before_len { - self.omitted_fields = true; - } self } @@ -802,7 +810,6 @@ impl<'a> VariantInfo<'a> { /// Panics if the index is out of range. pub fn remove_binding(&mut self, idx: usize) -> &mut Self { self.bindings.remove(idx); - self.omitted_fields = true; self } @@ -2335,7 +2342,7 @@ impl<'a> Structure<'a> { /// }), /// "# [ /// allow ( -/// non_upper_case_globals) +/// non_upper_case_globals ) /// ] /// const _DERIVE_krate_Trait_FOR_A : ( /// ) @@ -2440,3 +2447,42 @@ impl<T: MacroResult> MacroResult for Result<T> { } } } + +#[cfg(test)] +mod tests { + use super::*; + + // Regression test for #48 + #[test] + fn test_each_enum() { + let di: syn::DeriveInput = syn::parse_quote! { + enum A { + Foo(usize, bool), + Bar(bool, usize), + Baz(usize, bool, usize), + Quux(bool, usize, bool) + } + }; + let mut s = Structure::new(&di); + + s.filter(|bi| bi.ast().ty.to_token_stream().to_string() == "bool"); + + assert_eq!( + s.each(|bi| quote!(do_something(#bi))).to_string(), + quote! { + A::Foo(_, ref __binding_1,) => { { do_something(__binding_1) } } + A::Bar(ref __binding_0, ..) => { { do_something(__binding_0) } } + A::Baz(_, ref __binding_1, ..) => { { do_something(__binding_1) } } + A::Quux(ref __binding_0, _, ref __binding_2,) => { + { + do_something(__binding_0) + } + { + do_something(__binding_2) + } + } + } + .to_string() + ); + } +} diff --git a/vendor/tracing-attributes/.cargo-checksum.json b/vendor/tracing-attributes/.cargo-checksum.json index 6b905f349a..dafff659a7 100644 --- a/vendor/tracing-attributes/.cargo-checksum.json +++ b/vendor/tracing-attributes/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"8b561a4a281cb777c4b2e481fbbd168bfaa89f27ed939b71df5dcba87816b634","Cargo.toml":"896f317bbf6a214d6dab2d65ff48519490ccf2c09e6eb864e405f457a2b0e4d9","LICENSE":"898b1ae9821e98daf8964c8d6c7f61641f5f5aa78ad500020771c0939ee0dea1","README.md":"efc099593138b1f1dab4aaa6bfb9d202eefb86c74d6f88f09530c988271e0c47","src/lib.rs":"04c4c6dee32667b7c79984265cac4d17a6372a924404ae634ee736117b323f0f","tests/async_fn.rs":"8b9dbda5cf7d714e1d54f05ff42e67d3bd5c6bd3a43f19837ad3ddc09461756f","tests/destructuring.rs":"e453ab87a595f09a25dbe27fc4955d118f1932fb92fa544f8e63a823df6a9b54","tests/err.rs":"3b57cc9cba54115d6460708e37966a3016bcc0aebbcc0a4f0b0d43f585112036","tests/fields.rs":"50cc14b848730b3cffe1fb82f902e1a0c07bad0c9fa8d17f73ad9af854139a5c","tests/instrument.rs":"c1216ae7b587e0066b2c8d756752963378207c0ecbbd58e4dc18a193f94d120c","tests/levels.rs":"5d82ef5c55d1e53c240ad8d6ad3ecaeb330207a0c18a73a0ae46d75f6ca2679a","tests/names.rs":"89cf1d423d9fdfea1c1d08f6b05bd02564eaa58c10e17c41c8b4c8aba1a52c45","tests/support.rs":"7dcd5ee94222daec2e116bb65d0a9f0bcc38a5199b2cfa51eadd2d330b3c5159","tests/targets.rs":"6dc10489a505f1d2124a38c10eaaeaf8f9108ab50d925c77f9b9214d058d716b"},"package":"c4f915eb6abf914599c200260efced9203504c4c37380af10cdf3b7d36970650"} \ No newline at end of file +{"files":{"CHANGELOG.md":"7ebcf80e3fb6e30c173537a445c525a333d8aeb4ecc42ac2d9c2e72b67f520fc","Cargo.toml":"e2388f45b6d6d7cf4daad10988faaaf89c91f38d2ea33489221b2df1ec844df7","LICENSE":"898b1ae9821e98daf8964c8d6c7f61641f5f5aa78ad500020771c0939ee0dea1","README.md":"e88fadcdc20df9114234d8bc31e0361b9035fcb57d360751c4554ba8671a50f1","src/lib.rs":"8151d3a945b9ae420fde4195d4a5182feb272c13cfa9c55e0a290cdd709c32ca","tests/async_fn.rs":"b43626cbe7b9cd44ef8904d1d51913e2ebc2b7ef65b6b122f0e8244b7f67ca1a","tests/destructuring.rs":"e453ab87a595f09a25dbe27fc4955d118f1932fb92fa544f8e63a823df6a9b54","tests/err.rs":"77d693386c70e37a8b213078607495e7f610ee536d284192d45173884fdd64c8","tests/fields.rs":"50cc14b848730b3cffe1fb82f902e1a0c07bad0c9fa8d17f73ad9af854139a5c","tests/instrument.rs":"c1216ae7b587e0066b2c8d756752963378207c0ecbbd58e4dc18a193f94d120c","tests/levels.rs":"5d82ef5c55d1e53c240ad8d6ad3ecaeb330207a0c18a73a0ae46d75f6ca2679a","tests/names.rs":"89cf1d423d9fdfea1c1d08f6b05bd02564eaa58c10e17c41c8b4c8aba1a52c45","tests/support.rs":"7dcd5ee94222daec2e116bb65d0a9f0bcc38a5199b2cfa51eadd2d330b3c5159","tests/targets.rs":"6dc10489a505f1d2124a38c10eaaeaf8f9108ab50d925c77f9b9214d058d716b"},"package":"f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e"} \ No newline at end of file diff --git a/vendor/tracing-attributes/CHANGELOG.md b/vendor/tracing-attributes/CHANGELOG.md index d853ab994d..4a85dfcfb8 100644 --- a/vendor/tracing-attributes/CHANGELOG.md +++ b/vendor/tracing-attributes/CHANGELOG.md @@ -1,4 +1,21 @@ -# 0.1.17 (October 1, 2021) +# 0.1.18 (October 5, 2021) + +This release fixes issues introduced in v0.1.17. + +### Fixed + +- fixed mismatched types compiler error that may occur when using + `#[instrument]` on an `async fn` that returns an `impl Trait` value that + includes a closure ([#1616]) +- fixed false positives for `clippy::suspicious_else_formatting` warnings due to + rust-lang/rust-clippy#7760 and rust-lang/rust-clippy#6249 ([#1617]) +- fixed `clippy::let_unit_value` lints when using `#[instrument]` ([#1614]) + +[#1617]: https://github.com/tokio-rs/tracing/pull/1617 +[#1616]: https://github.com/tokio-rs/tracing/pull/1616 +[#1614]: https://github.com/tokio-rs/tracing/pull/1614 + +# 0.1.17 (YANKED) (October 1, 2021) This release significantly improves performance when `#[instrument]`-generated spans are below the maximum enabled level. diff --git a/vendor/tracing-attributes/Cargo.toml b/vendor/tracing-attributes/Cargo.toml index 857522c560..67b81b4e1b 100644 --- a/vendor/tracing-attributes/Cargo.toml +++ b/vendor/tracing-attributes/Cargo.toml @@ -12,7 +12,7 @@ [package] edition = "2018" name = "tracing-attributes" -version = "0.1.17" +version = "0.1.18" authors = ["Tokio Contributors <team@tokio.rs>", "Eliza Weisman <eliza@buoyant.io>", "David Barsky <dbarsky@amazon.com>"] description = "Procedural macro attributes for automatically instrumenting functions.\n" homepage = "https://tokio.rs" diff --git a/vendor/tracing-attributes/README.md b/vendor/tracing-attributes/README.md index 75935a1426..c90abafa6e 100644 --- a/vendor/tracing-attributes/README.md +++ b/vendor/tracing-attributes/README.md @@ -18,7 +18,7 @@ Macro attributes for application-level tracing. [crates-badge]: https://img.shields.io/crates/v/tracing-attributes.svg [crates-url]: https://crates.io/crates/tracing-attributes [docs-badge]: https://docs.rs/tracing-attributes/badge.svg -[docs-url]: https://docs.rs/tracing-attributes/0.1.17 +[docs-url]: https://docs.rs/tracing-attributes/0.1.18 [docs-master-badge]: https://img.shields.io/badge/docs-master-blue [docs-master-url]: https://tracing-rs.netlify.com/tracing_attributes [mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg @@ -47,7 +47,7 @@ First, add this to your `Cargo.toml`: ```toml [dependencies] -tracing-attributes = "0.1.17" +tracing-attributes = "0.1.18" ``` diff --git a/vendor/tracing-attributes/src/lib.rs b/vendor/tracing-attributes/src/lib.rs index cf09804585..e34fb9ad9f 100644 --- a/vendor/tracing-attributes/src/lib.rs +++ b/vendor/tracing-attributes/src/lib.rs @@ -16,7 +16,7 @@ //! //! ```toml //! [dependencies] -//! tracing-attributes = "0.1.17" +//! tracing-attributes = "0.1.18" //! ``` //! //! The [`#[instrument]`][instrument] attribute can now be added to a function @@ -52,7 +52,7 @@ //! supported compiler version is not considered a semver breaking change as //! long as doing so complies with this policy. //! -#![doc(html_root_url = "https://docs.rs/tracing-attributes/0.1.17")] +#![doc(html_root_url = "https://docs.rs/tracing-attributes/0.1.18")] #![doc( html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png", issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/" @@ -730,21 +730,22 @@ fn gen_block( ) }; - return quote_spanned!(block.span()=> - if tracing::level_enabled!(#level) { - let __tracing_attr_span = #span; + return quote!( + let __tracing_attr_span = #span; + let __tracing_instrument_future = #mk_fut; + if !__tracing_attr_span.is_disabled() { tracing::Instrument::instrument( - #mk_fut, + __tracing_instrument_future, __tracing_attr_span ) .await } else { - #mk_fut.await + __tracing_instrument_future.await } ); } - let span = quote_spanned!(block.span()=> + let span = quote!( // These variables are left uninitialized and initialized only // if the tracing level is statically enabled at this point. // While the tracing level is also checked at span creation @@ -761,8 +762,6 @@ fn gen_block( __tracing_attr_span = #span; __tracing_attr_guard = __tracing_attr_span.enter(); } - // pacify clippy::suspicious_else_formatting - let _ = (); ); if err { @@ -780,9 +779,18 @@ fn gen_block( ); } - quote_spanned!(block.span()=> - #span - #block + quote_spanned!(block.span() => + // Because `quote` produces a stream of tokens _without_ whitespace, the + // `if` and the block will appear directly next to each other. This + // generates a clippy lint about suspicious `if/else` formatting. + // Therefore, suppress the lint inside the generated code... + #[allow(clippy::suspicious_else_formatting)] + { + #span + // ...but turn the lint back on inside the function body. + #[warn(clippy::suspicious_else_formatting)] + #block + } ) } diff --git a/vendor/tracing-attributes/tests/async_fn.rs b/vendor/tracing-attributes/tests/async_fn.rs index 11fcc2f73c..1f5e3d0bf6 100644 --- a/vendor/tracing-attributes/tests/async_fn.rs +++ b/vendor/tracing-attributes/tests/async_fn.rs @@ -15,6 +15,46 @@ async fn test_async_fn(polls: usize) -> Result<(), ()> { future.await } +// Reproduces a compile error when returning an `impl Trait` from an +// instrumented async fn (see https://github.com/tokio-rs/tracing/issues/1615) +#[instrument] +async fn test_ret_impl_trait(n: i32) -> Result<impl Iterator<Item = i32>, ()> { + let n = n; + Ok((0..10).filter(move |x| *x < n)) +} + +// Reproduces a compile error when returning an `impl Trait` from an +// instrumented async fn (see https://github.com/tokio-rs/tracing/issues/1615) +#[instrument(err)] +async fn test_ret_impl_trait_err(n: i32) -> Result<impl Iterator<Item = i32>, &'static str> { + Ok((0..10).filter(move |x| *x < n)) +} + +#[instrument] +async fn test_async_fn_empty() {} + +// Reproduces https://github.com/tokio-rs/tracing/issues/1613 +#[instrument] +// LOAD-BEARING `#[rustfmt::skip]`! This is necessary to reproduce the bug; +// with the rustfmt-generated formatting, the lint will not be triggered! +#[rustfmt::skip] +#[deny(clippy::suspicious_else_formatting)] +async fn repro_1613(var: bool) { + println!( + "{}", + if var { "true" } else { "false" } + ); +} + +// Reproduces https://github.com/tokio-rs/tracing/issues/1613 +// and https://github.com/rust-lang/rust-clippy/issues/7760 +#[instrument] +#[deny(clippy::suspicious_else_formatting)] +async fn repro_1613_2() { + // hello world + // else +} + #[test] fn async_fn_only_enters_for_polls() { let (subscriber, handle) = subscriber::mock() diff --git a/vendor/tracing-attributes/tests/err.rs b/vendor/tracing-attributes/tests/err.rs index 6e283d52f8..66ce76aa86 100644 --- a/vendor/tracing-attributes/tests/err.rs +++ b/vendor/tracing-attributes/tests/err.rs @@ -16,6 +16,12 @@ fn err() -> Result<u8, TryFromIntError> { u8::try_from(1234) } +#[instrument(err)] +fn err_suspicious_else() -> Result<u8, TryFromIntError> { + {} + u8::try_from(1234) +} + #[test] fn test() { let span = span::mock().named("err"); diff --git a/vendor/tracing-subscriber/.cargo-checksum.json b/vendor/tracing-subscriber/.cargo-checksum.json index 8ea34a8252..75b6d3fef8 100644 --- a/vendor/tracing-subscriber/.cargo-checksum.json +++ b/vendor/tracing-subscriber/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"12fc92ad7d3c116144553b33d214bb4cb6ffd2d3791c76296e5911390adc6d96","Cargo.toml":"648caa802e57b885570c2821fef19fd8570966d1631b9508fdfd1811f4ee9dc8","LICENSE":"898b1ae9821e98daf8964c8d6c7f61641f5f5aa78ad500020771c0939ee0dea1","README.md":"3f0919546a2a8b4addc458f4b532dbf8d40e68a6aafa5d56c1388a7794746d2d","benches/enter.rs":"4a94a04e2abd07950ef2f0b646f4dcdf4ff00abf6396edb5a53c8b41b7691b1a","benches/filter.rs":"6374005ffa47fa19880bb95e3e37406f40ea72a02c5136f4d5eb4c663d452b18","benches/filter_log.rs":"612716bdf9a188093e84d014a4847f18157f148f7d64e54150cd5c91ac709a8a","benches/fmt.rs":"5a0ff37967ffef3a221eebb78855d031e2e883a8a67528c8e794cc6f16cbee8a","benches/support/mod.rs":"72bef51154da9c9b3d81300195c1929a818858fa4b4fc2aa07b49ca586f4cd39","src/field/debug.rs":"c940c901dd0a80f4a0e5be4541f56dba223f8191d51d330ff15fece70c1d2cee","src/field/delimited.rs":"cfafcad5b3e9a3f018149ec4803ce53277ebc54a92a8eaf05bbb191b2058d691","src/field/display.rs":"845a30665614549d42c5fcfe9c7f72a5a45872a35963e3425d91fb744a42e951","src/field/mod.rs":"4cd3f1cb29c627e034f1f1ccb863d5f1530ab0864e03cea7e7cd757fc852ef1e","src/filter/directive.rs":"c46616f183587be70ff5d7b2e74519a01b9e4def1c37b4da5510d8bbd5e3115d","src/filter/env/directive.rs":"628f9f566ccee924d43d79b287c569abfc32c2fb74e078958aed6cb8285cfb4f","src/filter/env/field.rs":"9f2ceaedf2e2ecefaff863347ef8dfa85cd5f64a0fd09a0f77f64f412c9bb548","src/filter/env/mod.rs":"fa5597ac0fda323721945ffe72e4a3abedc1d402f5e6d102c19f96ab3dc61ee6","src/filter/filter_fn.rs":"acc659f2cb0624a9efc4cd879e587ef667ea1ad21172937358e9c52d09baa352","src/filter/layer_filters.rs":"4c3d5f6ebcf462b3b36cee310816d81f1d369c000e732d8d54b6d12e8cbef9e7","src/filter/level.rs":"cc449757aac47caaf19dd5ba4d74c8efbcd7531fcd6c13da0c5f6fdda12cc9ca","src/filter/mod.rs":"cde10fe584a6161cfbf5d840337be4e8bf1806d3d8155ca9f49604efc63c25c0","src/filter/targets.rs":"e5e0a4376fc1ad556af756210d21f4e7e2a7bbdfd82b303cb4cf78792e4dc02f","src/fmt/fmt_layer.rs":"dbe024bdff435c3dd55d77927637008a4881a9f867288cb1c21e14aa24564679","src/fmt/format/json.rs":"c8cd06150fb2012d0ba4670001dcb333ed4d9a297b674fa5c898d0128c55ab52","src/fmt/format/mod.rs":"9caccfc2e5c4bac70df3a36c3d4f500ae9af6b93b779fb309f883ba9a9883d3f","src/fmt/format/pretty.rs":"27df1f55a75f0005fc442c5b55d981845dee1851b3c9a9b7b5cf966bc120dca9","src/fmt/mod.rs":"8829f44c0593ed916ace6904e20846f124dddf6711afd886abea092af37d0a59","src/fmt/time/datetime.rs":"1e77f550fa9bf9d019f8337aedb84a1077bd4d054a89080c3babf97a88ca6911","src/fmt/time/mod.rs":"7f3f5f72cdab40c463a0b02ff05f12e749982d29b0dedb44e4d2256aa15fb381","src/fmt/writer.rs":"ccf6b4fded02bcca75bb43b1b5adb18fb573ddd6a3c22cae7e7435386c24b5a2","src/layer/context.rs":"9a2bada54ea38bb28679b95899623a945932d00d20e2d3b0acb72dcd7933c732","src/layer/layered.rs":"9fb1d670e922ea779239046d6d9b7a89dc8d76e38d2c9f6dcc1abd2c37be6251","src/layer/mod.rs":"b8b91f43bdee58ae3eda678f1e7cfad9907899dcaf213a11d2185c687011a991","src/layer/tests.rs":"74b487ee4768712b46a354840f2da8a77dc23a00a5f8a1923087262edf3c62c5","src/lib.rs":"5c1aa62b7d2b87bb2f354e26ad3a3af541f445a0a01d19e96945f6b323a78375","src/prelude.rs":"33de6bc8a5482763c67a0d39859535572f4565b7ff74add9f2de007713ce77f8","src/registry/extensions.rs":"eb0bd2bd630f634d2a0b74bf4da792c3bacd4a585f1ad5102e0767cd3038d02c","src/registry/mod.rs":"c2bc423abcd861d94143beacdec0fc8df137037b2e9bb0c77e16e950f1f44e27","src/registry/sharded.rs":"ab9b41eacfb893f938ddb90fa7f4a397a96c17ad27611525b786f6421dfac9d4","src/registry/stack.rs":"9ef333d6a8a28a064e80ff1e376dbb07bc597009010ec332b2dc3ab435d737c2","src/reload.rs":"def21b1667c68eb7f78cdf5c0aa4d0aa7318cab325e665668442e7d4187f7b7b","src/sync.rs":"7f78f3de5b618a999be0e61f936a233975e7769f1ebb55a0e48c3d199e9c45e3","src/thread.rs":"32f03a56d68c494c999f58a5d242a5e43b82b00d40ffde424280a4343945099d","src/util.rs":"119e16eb0423eacebc10bc9b1952ad24b698c5054e68cf74a076d12935e78961","tests/cached_layer_filters_dont_break_other_layers.rs":"b2084542a014abeff821b30b2b8c21e32bfdcffae53ce5335fb588f557fa4244","tests/duplicate_spans.rs":"48f596bbfabcc6618244afddcf3c3f2e915b9d79284f17bdd0e0616ad29929be","tests/field_filter.rs":"c44d88ab711164a2b1b3a09377284b469f79ddf4651416515a035782c7c64b79","tests/filter.rs":"a43d23e867af779031b6245047092aca57ee26980a8f3faa19036542bcd37f06","tests/filter_log.rs":"e0cd9d394dbfeeb80570a7686bc7f588c5489657980436810711ed8852f86169","tests/fmt_max_level_hint.rs":"d4c6d6f976ae41ab8052fa610a7337ad7150802cbd5634cb30fc45c1f215cfcd","tests/hinted_layer_filters_dont_break_other_layers.rs":"d5ba9cfb6784cf59f007e673ad549dc722d109f6b3d4a69f6aa11b25ca10b469","tests/layer_filter_interests_are_cached.rs":"d036d1c4bc3754e94ebfdda9c841f4858ccec40aba0720f3fbf26c817bfe5a83","tests/layer_filters/boxed.rs":"e471f3d91142513116f07ec3f551e2b237d8278698c1e9f7d82b4997ac80ed21","tests/layer_filters/filter_scopes.rs":"02611bc58d0d8a67a127eca8cab1b2d9a9901bd2c8a8daad41adf6089b28aee0","tests/layer_filters/main.rs":"4d5ccf1a67762405f1ac4fd7dc4534c5970644a29fb437c7e7b686bc7fff51cf","tests/layer_filters/targets.rs":"138e3f9ddd68571d94c5aff9d54ee2fbc5f44724c6ee42477a411740ccb79ee6","tests/layer_filters/trees.rs":"4df7b5cf12da44a9255c56e5b80e2b0cf84820230ba916f324c67bc3ee4e4605","tests/multiple_layer_filter_interests_cached.rs":"1ea195f03e58d715228ec1b604f85bda2fc82812d05b2f6370d5edd34a035f32","tests/registry_max_level_hint.rs":"ba386d32b8d13832d7009163241c3d0723488c0393d85647eb9368776251e4fc","tests/registry_with_subscriber.rs":"13b92ed68d9013aefefbc4c73e695c690630e4460634206d214db4c19abb7c0f","tests/reload.rs":"4566386b1b26e6609f5a4bf0e6bef1c2245a591d12417cee189b26dfa14f7f95","tests/same_len_filters.rs":"50c8f5fa1494773410a9f52a56b303534a01a023b186cf2f3131e5e7706eb156","tests/support.rs":"b6b80ce41146a59e018fcfa01c47462bd86e3b1d098f98572d3016ad39d14a58","tests/unhinted_layer_filters_dont_break_other_layers.rs":"519cfef4977e511af938546d4208c645a28248c8ed8666daf180f0ad32f0a261","tests/utils.rs":"d49ccc2b38054e9bec6ed55989045d0a84df64983efcc762d20a117c1180ed20"},"package":"fdd0568dbfe3baf7048b7908d2b32bca0d81cd56bec6d2a8f894b01d74f86be3"} \ No newline at end of file +{"files":{"CHANGELOG.md":"bd7fdde473f21c2de094fd133cd0bffcd06e316828df318a4eadae54de769dc1","Cargo.toml":"a8d3cf3e4cba6b05f481348c3fabcd7455bed829fcf263d92744e2056b929d45","LICENSE":"898b1ae9821e98daf8964c8d6c7f61641f5f5aa78ad500020771c0939ee0dea1","README.md":"1713c528cf9d4f8b81f4e7805f643f4a0700aab3b7345a6500640143c20e33cc","benches/enter.rs":"4a94a04e2abd07950ef2f0b646f4dcdf4ff00abf6396edb5a53c8b41b7691b1a","benches/filter.rs":"6374005ffa47fa19880bb95e3e37406f40ea72a02c5136f4d5eb4c663d452b18","benches/filter_log.rs":"612716bdf9a188093e84d014a4847f18157f148f7d64e54150cd5c91ac709a8a","benches/fmt.rs":"5a0ff37967ffef3a221eebb78855d031e2e883a8a67528c8e794cc6f16cbee8a","benches/support/mod.rs":"72bef51154da9c9b3d81300195c1929a818858fa4b4fc2aa07b49ca586f4cd39","src/field/debug.rs":"c940c901dd0a80f4a0e5be4541f56dba223f8191d51d330ff15fece70c1d2cee","src/field/delimited.rs":"cfafcad5b3e9a3f018149ec4803ce53277ebc54a92a8eaf05bbb191b2058d691","src/field/display.rs":"845a30665614549d42c5fcfe9c7f72a5a45872a35963e3425d91fb744a42e951","src/field/mod.rs":"4cd3f1cb29c627e034f1f1ccb863d5f1530ab0864e03cea7e7cd757fc852ef1e","src/filter/directive.rs":"c46616f183587be70ff5d7b2e74519a01b9e4def1c37b4da5510d8bbd5e3115d","src/filter/env/directive.rs":"628f9f566ccee924d43d79b287c569abfc32c2fb74e078958aed6cb8285cfb4f","src/filter/env/field.rs":"9f2ceaedf2e2ecefaff863347ef8dfa85cd5f64a0fd09a0f77f64f412c9bb548","src/filter/env/mod.rs":"fa5597ac0fda323721945ffe72e4a3abedc1d402f5e6d102c19f96ab3dc61ee6","src/filter/filter_fn.rs":"acc659f2cb0624a9efc4cd879e587ef667ea1ad21172937358e9c52d09baa352","src/filter/layer_filters.rs":"2c25c9e3cca95eed3f58ca3cae04ecec47be72ae5ff68f82acffc3b6a2e66aee","src/filter/level.rs":"cc449757aac47caaf19dd5ba4d74c8efbcd7531fcd6c13da0c5f6fdda12cc9ca","src/filter/mod.rs":"cde10fe584a6161cfbf5d840337be4e8bf1806d3d8155ca9f49604efc63c25c0","src/filter/targets.rs":"f1198267984ca2f9e77fee2090036657e2787feaed93b35af8337e6aeb5e6fa5","src/fmt/fmt_layer.rs":"dbe024bdff435c3dd55d77927637008a4881a9f867288cb1c21e14aa24564679","src/fmt/format/json.rs":"c8cd06150fb2012d0ba4670001dcb333ed4d9a297b674fa5c898d0128c55ab52","src/fmt/format/mod.rs":"9caccfc2e5c4bac70df3a36c3d4f500ae9af6b93b779fb309f883ba9a9883d3f","src/fmt/format/pretty.rs":"27df1f55a75f0005fc442c5b55d981845dee1851b3c9a9b7b5cf966bc120dca9","src/fmt/mod.rs":"8829f44c0593ed916ace6904e20846f124dddf6711afd886abea092af37d0a59","src/fmt/time/datetime.rs":"1e77f550fa9bf9d019f8337aedb84a1077bd4d054a89080c3babf97a88ca6911","src/fmt/time/mod.rs":"7f3f5f72cdab40c463a0b02ff05f12e749982d29b0dedb44e4d2256aa15fb381","src/fmt/writer.rs":"ccf6b4fded02bcca75bb43b1b5adb18fb573ddd6a3c22cae7e7435386c24b5a2","src/layer/context.rs":"9a2bada54ea38bb28679b95899623a945932d00d20e2d3b0acb72dcd7933c732","src/layer/layered.rs":"9fb1d670e922ea779239046d6d9b7a89dc8d76e38d2c9f6dcc1abd2c37be6251","src/layer/mod.rs":"16f252c165f9dc961dad7066b97ca7c8e155b27488ee0ce74c19028477810a0c","src/layer/tests.rs":"74b487ee4768712b46a354840f2da8a77dc23a00a5f8a1923087262edf3c62c5","src/lib.rs":"ff2b9ebfca8af47e9a81ee931c3f71f130706e9bdd645bec7c5e68f04a2f176c","src/prelude.rs":"33de6bc8a5482763c67a0d39859535572f4565b7ff74add9f2de007713ce77f8","src/registry/extensions.rs":"eb0bd2bd630f634d2a0b74bf4da792c3bacd4a585f1ad5102e0767cd3038d02c","src/registry/mod.rs":"c2bc423abcd861d94143beacdec0fc8df137037b2e9bb0c77e16e950f1f44e27","src/registry/sharded.rs":"ab9b41eacfb893f938ddb90fa7f4a397a96c17ad27611525b786f6421dfac9d4","src/registry/stack.rs":"9ef333d6a8a28a064e80ff1e376dbb07bc597009010ec332b2dc3ab435d737c2","src/reload.rs":"def21b1667c68eb7f78cdf5c0aa4d0aa7318cab325e665668442e7d4187f7b7b","src/sync.rs":"7f78f3de5b618a999be0e61f936a233975e7769f1ebb55a0e48c3d199e9c45e3","src/thread.rs":"32f03a56d68c494c999f58a5d242a5e43b82b00d40ffde424280a4343945099d","src/util.rs":"119e16eb0423eacebc10bc9b1952ad24b698c5054e68cf74a076d12935e78961","tests/cached_layer_filters_dont_break_other_layers.rs":"b2084542a014abeff821b30b2b8c21e32bfdcffae53ce5335fb588f557fa4244","tests/duplicate_spans.rs":"48f596bbfabcc6618244afddcf3c3f2e915b9d79284f17bdd0e0616ad29929be","tests/field_filter.rs":"c44d88ab711164a2b1b3a09377284b469f79ddf4651416515a035782c7c64b79","tests/filter.rs":"a43d23e867af779031b6245047092aca57ee26980a8f3faa19036542bcd37f06","tests/filter_log.rs":"e0cd9d394dbfeeb80570a7686bc7f588c5489657980436810711ed8852f86169","tests/fmt_max_level_hint.rs":"d4c6d6f976ae41ab8052fa610a7337ad7150802cbd5634cb30fc45c1f215cfcd","tests/hinted_layer_filters_dont_break_other_layers.rs":"d5ba9cfb6784cf59f007e673ad549dc722d109f6b3d4a69f6aa11b25ca10b469","tests/layer_filter_interests_are_cached.rs":"d036d1c4bc3754e94ebfdda9c841f4858ccec40aba0720f3fbf26c817bfe5a83","tests/layer_filters/boxed.rs":"e471f3d91142513116f07ec3f551e2b237d8278698c1e9f7d82b4997ac80ed21","tests/layer_filters/downcast_raw.rs":"9b90ead571543cbe14e89b4fe637360d9baf3069f6f656ed3bdf65e7318648f1","tests/layer_filters/filter_scopes.rs":"02611bc58d0d8a67a127eca8cab1b2d9a9901bd2c8a8daad41adf6089b28aee0","tests/layer_filters/main.rs":"0316d611c740e234b78ed9a9dae392fe80472c1e8b004a007ad2dd87d068c67b","tests/layer_filters/targets.rs":"138e3f9ddd68571d94c5aff9d54ee2fbc5f44724c6ee42477a411740ccb79ee6","tests/layer_filters/trees.rs":"4df7b5cf12da44a9255c56e5b80e2b0cf84820230ba916f324c67bc3ee4e4605","tests/multiple_layer_filter_interests_cached.rs":"1ea195f03e58d715228ec1b604f85bda2fc82812d05b2f6370d5edd34a035f32","tests/registry_max_level_hint.rs":"ba386d32b8d13832d7009163241c3d0723488c0393d85647eb9368776251e4fc","tests/registry_with_subscriber.rs":"13b92ed68d9013aefefbc4c73e695c690630e4460634206d214db4c19abb7c0f","tests/reload.rs":"4566386b1b26e6609f5a4bf0e6bef1c2245a591d12417cee189b26dfa14f7f95","tests/same_len_filters.rs":"50c8f5fa1494773410a9f52a56b303534a01a023b186cf2f3131e5e7706eb156","tests/support.rs":"b6b80ce41146a59e018fcfa01c47462bd86e3b1d098f98572d3016ad39d14a58","tests/unhinted_layer_filters_dont_break_other_layers.rs":"519cfef4977e511af938546d4208c645a28248c8ed8666daf180f0ad32f0a261","tests/utils.rs":"d49ccc2b38054e9bec6ed55989045d0a84df64983efcc762d20a117c1180ed20"},"package":"0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71"} \ No newline at end of file diff --git a/vendor/tracing-subscriber/CHANGELOG.md b/vendor/tracing-subscriber/CHANGELOG.md index 0e703164af..898cbe7277 100644 --- a/vendor/tracing-subscriber/CHANGELOG.md +++ b/vendor/tracing-subscriber/CHANGELOG.md @@ -1,3 +1,23 @@ +# 0.2.25 (October 5, 2021) + +This release fixes an issue where a `Layer` implementation's custom +`downcast_raw` implementation was lost when wrapping that layer with a per-layer +filter. + +### Fixed + +- **registry**: Forward `Filtered::downcast_raw` to wrapped `Layer` ([#1619]) + +### Added + +- Documentation improvements ([#1596], [#1601]) + +Thanks to @bryanburgers for contributing to this release! + +[#1619]: https://github.com/tokio-rs/tracing/pull/1619 +[#1601]: https://github.com/tokio-rs/tracing/pull/1601 +[#1596]: https://github.com/tokio-rs/tracing/pull/1596 + # 0.2.24 (September 19, 2021) This release contains a number of bug fixes, including a fix for diff --git a/vendor/tracing-subscriber/Cargo.toml b/vendor/tracing-subscriber/Cargo.toml index a882d38272..9a851cd36d 100644 --- a/vendor/tracing-subscriber/Cargo.toml +++ b/vendor/tracing-subscriber/Cargo.toml @@ -3,17 +3,16 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies +# to registry (e.g., crates.io) dependencies. # -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. [package] edition = "2018" name = "tracing-subscriber" -version = "0.2.24" +version = "0.2.25" authors = ["Eliza Weisman <eliza@buoyant.io>", "David Barsky <me@davidbarsky.com>", "Tokio Contributors <team@tokio.rs>"] description = "Utilities for implementing and composing `tracing` subscribers.\n" homepage = "https://tokio.rs" diff --git a/vendor/tracing-subscriber/README.md b/vendor/tracing-subscriber/README.md index 8244a1d3b5..2624564739 100644 --- a/vendor/tracing-subscriber/README.md +++ b/vendor/tracing-subscriber/README.md @@ -21,7 +21,7 @@ Utilities for implementing and composing [`tracing`][tracing] subscribers. [crates-badge]: https://img.shields.io/crates/v/tracing-subscriber.svg [crates-url]: https://crates.io/crates/tracing-subscriber [docs-badge]: https://docs.rs/tracing-subscriber/badge.svg -[docs-url]: https://docs.rs/tracing-subscriber/0.2.24 +[docs-url]: https://docs.rs/tracing-subscriber/0.2.25 [docs-master-badge]: https://img.shields.io/badge/docs-master-blue [docs-master-url]: https://tracing-rs.netlify.com/tracing_subscriber [mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg diff --git a/vendor/tracing-subscriber/src/filter/layer_filters.rs b/vendor/tracing-subscriber/src/filter/layer_filters.rs index 9b23419493..7515080676 100644 --- a/vendor/tracing-subscriber/src/filter/layer_filters.rs +++ b/vendor/tracing-subscriber/src/filter/layer_filters.rs @@ -386,7 +386,7 @@ where id if id == TypeId::of::<MagicPlfDowncastMarker>() => { Some(&self.id as *const _ as *const ()) } - _ => None, + _ => self.layer.downcast_raw(id), } } } diff --git a/vendor/tracing-subscriber/src/filter/targets.rs b/vendor/tracing-subscriber/src/filter/targets.rs index 70dae3665a..ac4abb750e 100644 --- a/vendor/tracing-subscriber/src/filter/targets.rs +++ b/vendor/tracing-subscriber/src/filter/targets.rs @@ -118,7 +118,7 @@ use tracing_core::{Interest, Metadata, Subscriber}; /// }; /// use tracing_core::Level; /// use std::{sync::Arc, fs::File}; -/// # fn main() -> Result<(), Box<dyn std::error::Error>> { +/// # fn docs() -> Result<(), Box<dyn std::error::Error>> { /// /// // A layer that logs events to stdout using the human-readable "pretty" /// // format. diff --git a/vendor/tracing-subscriber/src/layer/mod.rs b/vendor/tracing-subscriber/src/layer/mod.rs index 5ba89575b4..cebbb3d9c2 100644 --- a/vendor/tracing-subscriber/src/layer/mod.rs +++ b/vendor/tracing-subscriber/src/layer/mod.rs @@ -6,7 +6,7 @@ //! complete strategy for collecting traces; but it _also_ means that the //! `Subscriber` trait cannot easily be composed with other `Subscriber`s. //! -//! In particular, [`Subscriber`]'s are responsible for generating [span IDs] and +//! In particular, [`Subscriber`]s are responsible for generating [span IDs] and //! assigning them to spans. Since these IDs must uniquely identify a span //! within the context of the current trace, this means that there may only be //! a single `Subscriber` for a given thread at any point in time — @@ -393,6 +393,84 @@ //! # Ok(()) } //! ``` //! +//! ## Runtime Configuration With Layers +//! +//! In some cases, a particular [`Layer`] may be enabled or disabled based on +//! runtime configuration. This can introduce challenges, because the type of a +//! layered [`Subscriber`] depends on which layers are added to it: if an `if` +//! or `match` expression adds some [`Layer`]s in one branch and other layers +//! in another, the [`Subscriber`] values returned by those branches will have +//! different types. For example, the following _will not_ work: +//! +//! ```compile_fail +//! # fn docs() -> Result<(), Box<dyn std::error::Error + 'static>> { +//! # struct Config { +//! # is_prod: bool, +//! # path: &'static str, +//! # } +//! # let cfg = Config { is_prod: false, path: "debug.log" }; +//! use std::{fs::File, sync::Arc}; +//! use tracing_subscriber::{Registry, prelude::*}; +//! +//! let stdout_log = tracing_subscriber::fmt::layer().pretty(); +//! let subscriber = Registry::default().with(stdout_log); +//! +//! // The compile error will occur here because the if and else +//! // branches have different (and therefore incompatible) types. +//! let subscriber = if cfg.is_prod { +//! let file = File::create(cfg.path)?; +//! let layer = tracing_subscriber::fmt::layer() +//! .json() +//! .with_writer(Arc::new(file)); +//! subscriber.with(layer) +//! } else { +//! subscriber +//! }; +//! +//! tracing::subscriber::set_global_default(subscriber) +//! .expect("Unable to set global subscriber"); +//! # Ok(()) } +//! ``` +//! +//! However, a [`Layer`] wrapped in an [`Option`] [also implements the `Layer` +//! trait][option-impl]. This allows individual layers to be enabled or disabled at +//! runtime while always producing a [`Subscriber`] of the same type. For +//! example: +//! +//! ``` +//! # fn docs() -> Result<(), Box<dyn std::error::Error + 'static>> { +//! # struct Config { +//! # is_prod: bool, +//! # path: &'static str, +//! # } +//! # let cfg = Config { is_prod: false, path: "debug.log" }; +//! use std::{fs::File, sync::Arc}; +//! use tracing_subscriber::{Registry, prelude::*}; +//! +//! let stdout_log = tracing_subscriber::fmt::layer().pretty(); +//! let subscriber = Registry::default().with(stdout_log); +//! +//! // if `cfg.is_prod` is true, also log JSON-formatted logs to a file. +//! let json_log = if cfg.is_prod { +//! let file = File::create(cfg.path)?; +//! let json_log = tracing_subscriber::fmt::layer() +//! .json() +//! .with_writer(Arc::new(file)); +//! Some(json_log) +//! } else { +//! None +//! }; +//! +//! // If `cfg.is_prod` is false, then `json` will be `None`, and this layer +//! // will do nothing. However, the subscriber will still have the same type +//! // regardless of whether the `Option`'s value is `None` or `Some`. +//! let subscriber = subscriber.with(json_log); +//! +//! tracing::subscriber::set_global_default(subscriber) +//! .expect("Unable to set global subscriber"); +//! # Ok(()) } +//! ``` +//! //! [`Subscriber`]: https://docs.rs/tracing-core/latest/tracing_core/subscriber/trait.Subscriber.html //! [span IDs]: https://docs.rs/tracing-core/latest/tracing_core/span/struct.Id.html //! [the current span]: Context::current_span @@ -402,6 +480,7 @@ //! [`Layer::register_callsite`]: Layer::register_callsite //! [`Layer::enabled`]: Layer::enabled //! [`Interest::never()`]: https://docs.rs/tracing-core/latest/tracing_core/subscriber/struct.Interest.html#method.never +//! [option-impl]: crate::layer::Layer#impl-Layer<S>-for-Option<L> //! [`Filtered`]: crate::filter::Filtered //! [`filter`]: crate::filter //! [`Targets`]: crate::filter::Targets diff --git a/vendor/tracing-subscriber/src/lib.rs b/vendor/tracing-subscriber/src/lib.rs index b0dc9f2add..c9dc45984b 100644 --- a/vendor/tracing-subscriber/src/lib.rs +++ b/vendor/tracing-subscriber/src/lib.rs @@ -91,7 +91,7 @@ //! [`env_logger` crate]: https://crates.io/crates/env_logger //! [`parking_lot`]: https://crates.io/crates/parking_lot //! [`registry`]: registry/index.html -#![doc(html_root_url = "https://docs.rs/tracing-subscriber/0.2.24")] +#![doc(html_root_url = "https://docs.rs/tracing-subscriber/0.2.25")] #![doc( html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png", issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/" diff --git a/vendor/tracing-subscriber/tests/layer_filters/downcast_raw.rs b/vendor/tracing-subscriber/tests/layer_filters/downcast_raw.rs new file mode 100644 index 0000000000..b5f7e35ced --- /dev/null +++ b/vendor/tracing-subscriber/tests/layer_filters/downcast_raw.rs @@ -0,0 +1,68 @@ +use tracing::Subscriber; +use tracing_subscriber::filter::Targets; +use tracing_subscriber::prelude::*; +use tracing_subscriber::Layer; + +#[test] +fn downcast_ref_to_inner_layer_and_filter() { + // Test that a filtered layer gives downcast_ref access to + // both the layer and the filter. + + struct WrappedLayer; + + impl<S> Layer<S> for WrappedLayer + where + S: Subscriber, + S: for<'lookup> tracing_subscriber::registry::LookupSpan<'lookup>, + { + } + + let layer = WrappedLayer; + let filter = Targets::new().with_default(tracing::Level::INFO); + let registry = tracing_subscriber::registry().with(layer.with_filter(filter)); + let dispatch = tracing::dispatcher::Dispatch::new(registry); + + // The filter is available + assert!(dispatch.downcast_ref::<Targets>().is_some()); + // The wrapped layer is available + assert!(dispatch.downcast_ref::<WrappedLayer>().is_some()); +} + +#[test] +fn forward_downcast_raw_to_layer() { + // Test that a filtered layer still gives its wrapped layer a chance to + // return a custom struct from downcast_raw. + // https://github.com/tokio-rs/tracing/issues/1618 + + struct WrappedLayer { + with_context: WithContext, + } + + struct WithContext; + + impl<S> Layer<S> for WrappedLayer + where + S: Subscriber, + S: for<'lookup> tracing_subscriber::registry::LookupSpan<'lookup>, + { + unsafe fn downcast_raw(&self, id: std::any::TypeId) -> Option<*const ()> { + match id { + id if id == std::any::TypeId::of::<Self>() => Some(self as *const _ as *const ()), + id if id == std::any::TypeId::of::<WithContext>() => { + Some(&self.with_context as *const _ as *const ()) + } + _ => None, + } + } + } + + let layer = WrappedLayer { + with_context: WithContext, + }; + let filter = Targets::new().with_default(tracing::Level::INFO); + let registry = tracing_subscriber::registry().with(layer.with_filter(filter)); + let dispatch = tracing::dispatcher::Dispatch::new(registry); + + // Types from a custom implementation of `downcast_raw` are available + assert!(dispatch.downcast_ref::<WithContext>().is_some()); +} diff --git a/vendor/tracing-subscriber/tests/layer_filters/main.rs b/vendor/tracing-subscriber/tests/layer_filters/main.rs index dfe3309c62..2359584d72 100644 --- a/vendor/tracing-subscriber/tests/layer_filters/main.rs +++ b/vendor/tracing-subscriber/tests/layer_filters/main.rs @@ -3,6 +3,7 @@ mod support; use self::support::*; mod boxed; +mod downcast_raw; mod filter_scopes; mod targets; mod trees; diff --git a/vendor/tracing/.cargo-checksum.json b/vendor/tracing/.cargo-checksum.json index 41ce631643..e0601149e9 100644 --- a/vendor/tracing/.cargo-checksum.json +++ b/vendor/tracing/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"cda0de258e242e5846eb722cabe7f00f85c63f4d86e23d1fbeddeef8bb6ba539","Cargo.toml":"43fc954dde6b186fa77b2fee921b2ba47dd140415d1710461dc241d94f128963","LICENSE":"898b1ae9821e98daf8964c8d6c7f61641f5f5aa78ad500020771c0939ee0dea1","README.md":"a511af794530591322ab3ceb134f3e7d973841dfec28585c9e4c8cc1e9a237ef","benches/no_subscriber.rs":"799c293113c78255e1cb45eec3656ee85c0f8910458bc3412f3175c44c2bff46","benches/subscriber.rs":"066a69119ffc8dc5ccf2801b0d75fb73cbd563dbaadb824121b9a68301a68a4e","src/dispatcher.rs":"8046172df6287f9f91db3a57bc59882639504f1934af2abd18451155408a23b9","src/field.rs":"c741dee2df973d0dfae906c38ac6a0f0ce940ee76619c396678a9307ca70fa56","src/instrument.rs":"f4d0dd95208cb77cd23b0f0d9fa877ec542c7d4258ce57b1baa535026a7569de","src/level_filters.rs":"b763c481137d2f46d9cf82616cb2dc0eb493c205ee8638ae8948ae3478ea2580","src/lib.rs":"5f31ec7b36b1e0e790a34a84a7c9ba98ec8578b373ea2654b676bf433310b871","src/macros.rs":"bf739ba70ccd2c42699b5d83cd3c2699d3c58da632ccd3b51fd5c25ef9ea7da6","src/span.rs":"d117996adcd163f007d1e1b86b0684328149cca9d92a82573237596f7aa5d394","src/stdlib.rs":"248514a9bae6106e436358aee44c92abf8e7f79022895c4a25136ddef211d198","src/subscriber.rs":"4d489dfa55b29db439b447bb42eedd5fa030579634b9f403603afb0055fb9371","tests/event.rs":"60c827f857ebea39bd46f314ab4ab997bd7aa25406b26fb7f3afaf27c4d78526","tests/filter_caching_is_lexically_scoped.rs":"0845255a0cf0b3288f8d641fd7d72277051b759fdbce6ff24e266523219ee68c","tests/filters_are_not_reevaluated_for_the_same_span.rs":"d3287dabe73e321870128e87b4084e20548ec18964004cd73cc3ca6383b73c26","tests/filters_are_reevaluated_for_different_call_sites.rs":"98c891a0ebd8c2297c9f4a38a7a0406b0a55757f99cc0deea968929d2a998092","tests/filters_dont_leak.rs":"f302ea2ba976f32400206b81a8de6110aa53a4d4555cd4c284242d0417220dab","tests/macro_imports.rs":"d5de857162185d4a2384f3cb644bfcf76c7f5c1a3b5f72bfa0d2620ac6e3873c","tests/macros.rs":"5a5891cf694c9e652da01695483fd0ca761ef109336071b0866d4047a5f23502","tests/max_level_hint.rs":"973124e340f6250ecb2ef8a8e5602623702ddfc75885187b15107accfb378e08","tests/multiple_max_level_hints.rs":"c8339fe81dafdc89ab4a86658be2a44d0ddd70d639522a76cd273f03f563d09c","tests/span.rs":"80c0ad666d5ff9b5bc4a5ba5d585f4933023d21320395491a1189794fe4ffe07","tests/subscriber.rs":"757cd6a8c589c600ccb6a0c08497636d3a23150929aab7fa36f2cfcef17817ce","tests/support/event.rs":"02022cb58b72d6540e133f9a699307778ed23bc14a779a4c7819188b7091ea19","tests/support/field.rs":"41d9a28a3f4b2b6ab8051d932c2a5ff2835f3c3260fb3572ad97b4d2830eff87","tests/support/metadata.rs":"e12f5e2f5ed9ddf32dd1199471a67876d8de21d9468de89ca784a3e36a28f712","tests/support/mod.rs":"7bc9b4984fcc59c3c118c417bb77fecb37409083be9f58dd6be4353a6d951c82","tests/support/span.rs":"1337950caf365bdd4355c86484316adb2a4e4d08a068698503df872cfba8633e","tests/support/subscriber.rs":"d2a56463649e7358dc46b051e48923e0a4b038339edac9a127abde54b5eb0ae5"},"package":"84f96e095c0c82419687c20ddf5cb3eadb61f4e1405923c9dc8e53a1adacbda8"} \ No newline at end of file +{"files":{"CHANGELOG.md":"66adbc4a0b95a65d15892c9ca202f0efdc7227a60b91e7cca6909cdfb92b3a8f","Cargo.toml":"5340085a14f5bb04f72b5d90a067399e6ab599adc22f02f069fb31efeabc895e","LICENSE":"898b1ae9821e98daf8964c8d6c7f61641f5f5aa78ad500020771c0939ee0dea1","README.md":"a642d42e9c7890c1903f8c97b90a226a2582bf4983b8e3eebcdd79987881522c","benches/no_subscriber.rs":"799c293113c78255e1cb45eec3656ee85c0f8910458bc3412f3175c44c2bff46","benches/subscriber.rs":"066a69119ffc8dc5ccf2801b0d75fb73cbd563dbaadb824121b9a68301a68a4e","src/dispatcher.rs":"8046172df6287f9f91db3a57bc59882639504f1934af2abd18451155408a23b9","src/field.rs":"c741dee2df973d0dfae906c38ac6a0f0ce940ee76619c396678a9307ca70fa56","src/instrument.rs":"71602d7f8ef246359e6aafdf6748d8743c543a1f9565b7518a2c8bb84fa9e57b","src/level_filters.rs":"b763c481137d2f46d9cf82616cb2dc0eb493c205ee8638ae8948ae3478ea2580","src/lib.rs":"9aac824a89ac9cbf86004dbde9582ba4ff68fcdf5f3545c6ea33f6f21a7ddb33","src/macros.rs":"bf739ba70ccd2c42699b5d83cd3c2699d3c58da632ccd3b51fd5c25ef9ea7da6","src/span.rs":"d117996adcd163f007d1e1b86b0684328149cca9d92a82573237596f7aa5d394","src/stdlib.rs":"248514a9bae6106e436358aee44c92abf8e7f79022895c4a25136ddef211d198","src/subscriber.rs":"4d489dfa55b29db439b447bb42eedd5fa030579634b9f403603afb0055fb9371","tests/event.rs":"bbb159fa0fd4a2e355bc33f57b3a00b8aace418f4399d8682a368282e92dbff2","tests/filter_caching_is_lexically_scoped.rs":"0845255a0cf0b3288f8d641fd7d72277051b759fdbce6ff24e266523219ee68c","tests/filters_are_not_reevaluated_for_the_same_span.rs":"d3287dabe73e321870128e87b4084e20548ec18964004cd73cc3ca6383b73c26","tests/filters_are_reevaluated_for_different_call_sites.rs":"98c891a0ebd8c2297c9f4a38a7a0406b0a55757f99cc0deea968929d2a998092","tests/filters_dont_leak.rs":"f302ea2ba976f32400206b81a8de6110aa53a4d4555cd4c284242d0417220dab","tests/macro_imports.rs":"d5de857162185d4a2384f3cb644bfcf76c7f5c1a3b5f72bfa0d2620ac6e3873c","tests/macros.rs":"5a5891cf694c9e652da01695483fd0ca761ef109336071b0866d4047a5f23502","tests/max_level_hint.rs":"973124e340f6250ecb2ef8a8e5602623702ddfc75885187b15107accfb378e08","tests/multiple_max_level_hints.rs":"c8339fe81dafdc89ab4a86658be2a44d0ddd70d639522a76cd273f03f563d09c","tests/span.rs":"80c0ad666d5ff9b5bc4a5ba5d585f4933023d21320395491a1189794fe4ffe07","tests/subscriber.rs":"757cd6a8c589c600ccb6a0c08497636d3a23150929aab7fa36f2cfcef17817ce","tests/support/event.rs":"02022cb58b72d6540e133f9a699307778ed23bc14a779a4c7819188b7091ea19","tests/support/field.rs":"41d9a28a3f4b2b6ab8051d932c2a5ff2835f3c3260fb3572ad97b4d2830eff87","tests/support/metadata.rs":"e12f5e2f5ed9ddf32dd1199471a67876d8de21d9468de89ca784a3e36a28f712","tests/support/mod.rs":"7bc9b4984fcc59c3c118c417bb77fecb37409083be9f58dd6be4353a6d951c82","tests/support/span.rs":"1337950caf365bdd4355c86484316adb2a4e4d08a068698503df872cfba8633e","tests/support/subscriber.rs":"d2a56463649e7358dc46b051e48923e0a4b038339edac9a127abde54b5eb0ae5"},"package":"375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105"} \ No newline at end of file diff --git a/vendor/tracing/CHANGELOG.md b/vendor/tracing/CHANGELOG.md index 9019673472..a6cefb0f59 100644 --- a/vendor/tracing/CHANGELOG.md +++ b/vendor/tracing/CHANGELOG.md @@ -1,3 +1,41 @@ +# 0.1.29 (October 5th, 2021 + +This release adds support for recording `Option<T> where T: Value` as typed +`tracing` field values. It also includes significant performance improvements +for functions annotated with the `#[instrument]` attribute when the generated +span is disabled. + +### Changed + +- `tracing-core`: updated to v0.1.21 +- `tracing-attributes`: updated to v0.1.19 + +### Added + +- **field**: `Value` impl for `Option<T> where T: Value` ([#1585]) +- **attributes**: - improved performance when skipping `#[instrument]`-generated + spans below the max level ([#1600], [#1605], [#1614], [#1616], [#1617]) + +### Fixed + +- **instrument**: added missing `Future` implementation for `WithSubscriber`, + making the `WithDispatch` extension trait actually useable ([#1602]) +- Documentation fixes and improvements ([#1595], [#1601], [#1597]) + +Thanks to @brianburgers, @mattiast, @DCjanus, @oli-obk, and @matklad for +contributing to this release! + +[#1585]: https://github.com/tokio-rs/tracing/pull/1585 +[#1595]: https://github.com/tokio-rs/tracing/pull/1596 +[#1597]: https://github.com/tokio-rs/tracing/pull/1597 +[#1600]: https://github.com/tokio-rs/tracing/pull/1600 +[#1601]: https://github.com/tokio-rs/tracing/pull/1601 +[#1602]: https://github.com/tokio-rs/tracing/pull/1602 +[#1605]: https://github.com/tokio-rs/tracing/pull/1605 +[#1614]: https://github.com/tokio-rs/tracing/pull/1614 +[#1616]: https://github.com/tokio-rs/tracing/pull/1616 +[#1617]: https://github.com/tokio-rs/tracing/pull/1617 + # 0.1.28 (September 17th, 2021) This release fixes an issue where the RustDoc documentation was rendered diff --git a/vendor/tracing/Cargo.toml b/vendor/tracing/Cargo.toml index 09300e79f8..f7e4da4f16 100644 --- a/vendor/tracing/Cargo.toml +++ b/vendor/tracing/Cargo.toml @@ -3,17 +3,16 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies +# to registry (e.g., crates.io) dependencies. # -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. [package] edition = "2018" name = "tracing" -version = "0.1.28" +version = "0.1.29" authors = ["Eliza Weisman <eliza@buoyant.io>", "Tokio Contributors <team@tokio.rs>"] description = "Application-level tracing for Rust.\n" homepage = "https://tokio.rs" @@ -44,11 +43,11 @@ optional = true version = "0.2" [dependencies.tracing-attributes] -version = "0.1.16" +version = "0.1.18" optional = true [dependencies.tracing-core] -version = "0.1.20" +version = "0.1.21" default-features = false [dev-dependencies.criterion] version = "0.3" diff --git a/vendor/tracing/README.md b/vendor/tracing/README.md index a8b7d8d10e..18ed47e11b 100644 --- a/vendor/tracing/README.md +++ b/vendor/tracing/README.md @@ -16,9 +16,9 @@ Application-level tracing for Rust. [Documentation][docs-url] | [Chat][discord-url] [crates-badge]: https://img.shields.io/crates/v/tracing.svg -[crates-url]: https://crates.io/crates/tracing/0.1.28 +[crates-url]: https://crates.io/crates/tracing/0.1.29 [docs-badge]: https://docs.rs/tracing/badge.svg -[docs-url]: https://docs.rs/tracing/0.1.28 +[docs-url]: https://docs.rs/tracing/0.1.29 [docs-master-badge]: https://img.shields.io/badge/docs-master-blue [docs-master-url]: https://tracing-rs.netlify.com/tracing [mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg @@ -251,7 +251,7 @@ my_future is as long as the future's. The second, and preferred, option is through the -[`#[instrument]`](https://docs.rs/tracing/0.1.28/tracing/attr.instrument.html) +[`#[instrument]`](https://docs.rs/tracing/0.1.29/tracing/attr.instrument.html) attribute: ```rust @@ -298,7 +298,7 @@ span.in_scope(|| { // Dropping the span will close it, indicating that it has ended. ``` -The [`#[instrument]`](https://docs.rs/tracing/0.1.28/tracing/attr.instrument.html) attribute macro +The [`#[instrument]`](https://docs.rs/tracing/0.1.29/tracing/attr.instrument.html) attribute macro can reduce some of this boilerplate: ```rust diff --git a/vendor/tracing/src/instrument.rs b/vendor/tracing/src/instrument.rs index 3525a76c4e..d3fae70f8c 100644 --- a/vendor/tracing/src/instrument.rs +++ b/vendor/tracing/src/instrument.rs @@ -1,20 +1,24 @@ use crate::stdlib::pin::Pin; use crate::stdlib::task::{Context, Poll}; use crate::stdlib::{future::Future, marker::Sized}; -use crate::{dispatcher, span::Span, Dispatch}; +use crate::{ + dispatcher::{self, Dispatch}, + span::Span, +}; use pin_project_lite::pin_project; -/// Attaches spans to a `std::future::Future`. +/// Attaches spans to a [`std::future::Future`]. /// /// Extension trait allowing futures to be /// instrumented with a `tracing` [span]. /// -/// [span]: ../struct.Span.html +/// [span]: super::Span pub trait Instrument: Sized { - /// Instruments this type with the provided `Span`, returning an + /// Instruments this type with the provided [`Span`], returning an /// `Instrumented` wrapper. /// - /// The attached `Span` will be [entered] every time the instrumented `Future` is polled. + /// The attached [`Span`] will be [entered] every time the instrumented + /// [`Future`] is polled. /// /// # Examples /// @@ -38,7 +42,7 @@ pub trait Instrument: Sized { /// `instrument` to ensure that the [current span] is attached to the /// future if the span passed to `instrument` is [disabled]: /// - /// ```W + /// ``` /// use tracing::Instrument; /// # mod tokio { /// # pub(super) fn spawn(_: impl std::future::Future) {} @@ -74,17 +78,16 @@ pub trait Instrument: Sized { /// [`Span::or_current`]: super::Span::or_current() /// [current span]: super::Span::current() /// [disabled]: super::Span::is_disabled() + /// [`Future`]: std::future::Future fn instrument(self, span: Span) -> Instrumented<Self> { Instrumented { inner: self, span } } - /// Instruments this type with the [current] `Span`, returning an + /// Instruments this type with the [current] [`Span`], returning an /// `Instrumented` wrapper. /// - /// If the instrumented type is a future, stream, or sink, the attached `Span` - /// will be [entered] every time it is polled. If the instrumented type - /// is a future executor, every future spawned on that executor will be - /// instrumented by the attached `Span`. + /// The attached [`Span`] will be [entered] every time the instrumented + /// [`Future`] is polled. /// /// This can be used to propagate the current span when spawning a new future. /// @@ -93,6 +96,9 @@ pub trait Instrument: Sized { /// ```rust /// use tracing::Instrument; /// + /// # mod tokio { + /// # pub(super) fn spawn(_: impl std::future::Future) {} + /// # } /// # async fn doc() { /// let span = tracing::info_span!("my_span"); /// let _enter = span.enter(); @@ -107,8 +113,10 @@ pub trait Instrument: Sized { /// # } /// ``` /// - /// [current]: ../struct.Span.html#method.current - /// [entered]: ../struct.Span.html#method.enter + /// [current]: super::Span::current() + /// [entered]: super::Span::enter() + /// [`Span`]: crate::Span + /// [`Future`]: std::future::Future #[inline] fn in_current_span(self) -> Instrumented<Self> { self.instrument(Span::current()) @@ -117,63 +125,133 @@ pub trait Instrument: Sized { /// Extension trait allowing futures to be instrumented with /// a `tracing` [`Subscriber`]. -/// -/// [`Subscriber`]: ../trait.Subscriber.html +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub trait WithSubscriber: Sized { /// Attaches the provided [`Subscriber`] to this type, returning a - /// `WithDispatch` wrapper. + /// [`WithDispatch`] wrapper. + /// + /// The attached [`Subscriber`] will be set as the [default] when the returned + /// [`Future`] is polled. + /// + /// # Examples + /// + /// ``` + /// # use tracing::subscriber::NoSubscriber as MySubscriber; + /// # use tracing::subscriber::NoSubscriber as MyOtherSubscriber; + /// # async fn docs() { + /// use tracing::instrument::WithSubscriber; /// - /// The attached subscriber will be set as the [default] when the returned `Future` is polled. + /// // Set the default `Subscriber` + /// let _default = tracing::subscriber::set_default(MySubscriber::default()); /// - /// [`Subscriber`]: ../trait.Subscriber.html - /// [default]: https://docs.rs/tracing/latest/tracing/dispatcher/index.html#setting-the-default-subscriber + /// tracing::info!("this event will be recorded by the default `Subscriber`"); + /// + /// // Create a different `Subscriber` and attach it to a future. + /// let other_subscriber = MyOtherSubscriber::default(); + /// let future = async { + /// tracing::info!("this event will be recorded by the other `Subscriber`"); + /// // ... + /// }; + /// + /// future + /// // Attach the other `Subscriber` to the future before awaiting it + /// .with_subscriber(other_subscriber) + /// .await; + /// + /// // Once the future has completed, we return to the default `Subscriber`. + /// tracing::info!("this event will be recorded by the default `Subscriber`"); + /// # } + /// ``` + /// + /// [`Subscriber`]: super::Subscriber + /// [default]: crate::dispatcher#setting-the-default-subscriber + /// [`Future`]: std::future::Future fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> where S: Into<Dispatch>, { WithDispatch { inner: self, - dispatch: subscriber.into(), + dispatcher: subscriber.into(), } } /// Attaches the current [default] [`Subscriber`] to this type, returning a - /// `WithDispatch` wrapper. + /// [`WithDispatch`] wrapper. /// - /// When the wrapped type is a future, stream, or sink, the attached - /// subscriber will be set as the [default] while it is being polled. - /// When the wrapped type is an executor, the subscriber will be set as the - /// default for any futures spawned on that executor. + /// The attached `Subscriber` will be set as the [default] when the returned + /// [`Future`] is polled. /// /// This can be used to propagate the current dispatcher context when - /// spawning a new future. + /// spawning a new future that may run on a different thread. /// - /// [`Subscriber`]: ../trait.Subscriber.html - /// [default]: https://docs.rs/tracing/latest/tracing/dispatcher/index.html#setting-the-default-subscriber + /// # Examples + /// + /// ``` + /// # mod tokio { + /// # pub(super) fn spawn(_: impl std::future::Future) {} + /// # } + /// # use tracing::subscriber::NoSubscriber as MySubscriber; + /// # async fn docs() { + /// use tracing::instrument::WithSubscriber; + /// + /// // Using `set_default` (rather than `set_global_default`) sets the + /// // default `Subscriber` for *this* thread only. + /// let _default = tracing::subscriber::set_default(MySubscriber::default()); + /// + /// let future = async { + /// // ... + /// }; + /// + /// // If a multi-threaded async runtime is in use, this spawned task may + /// // run on a different thread, in a different default `Subscriber`'s context. + /// tokio::spawn(future); + /// + /// // However, calling `with_current_subscriber` on the future before + /// // spawning it, ensures that the current thread's default `Subscriber` is + /// // propagated to the spawned task, regardless of where it executes: + /// # let future = async { }; + /// tokio::spawn(future.with_current_subscriber()); + /// # } + /// ``` + /// [`Subscriber`]: super::Subscriber + /// [default]: crate::dispatcher#setting-the-default-subscriber + /// [`Future`]: std::future::Future #[inline] fn with_current_subscriber(self) -> WithDispatch<Self> { WithDispatch { inner: self, - dispatch: dispatcher::get_default(|default| default.clone()), + dispatcher: crate::dispatcher::get_default(|default| default.clone()), } } } -impl<T: Sized> WithSubscriber for T {} - pin_project! { - /// A future that has been instrumented with a `tracing` subscriber. + /// A [`Future`] that has been instrumented with a `tracing` [`Subscriber`]. + /// + /// This type is returned by the [`WithSubscriber`] extension trait. See that + /// trait's documentation for details. + /// + /// [`Future`]: std::future::Future + /// [`Subscriber`]: crate::Subscriber #[derive(Clone, Debug)] #[must_use = "futures do nothing unless you `.await` or poll them"] + #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub struct WithDispatch<T> { #[pin] inner: T, - dispatch: Dispatch, + dispatcher: Dispatch, } } pin_project! { - /// A future that has been instrumented with a `tracing` span. + /// A [`Future`] that has been instrumented with a `tracing` [`Span`]. + /// + /// This type is returned by the [`Instrument`] extension trait. See that + /// trait's documentation for details. + /// + /// [`Future`]: std::future::Future + /// [`Span`]: crate::Span #[derive(Debug, Clone)] #[must_use = "futures do nothing unless you `.await` or poll them"] pub struct Instrumented<T> { @@ -183,6 +261,8 @@ pin_project! { } } +// === impl Instrumented === + impl<T: Future> Future for Instrumented<T> { type Output = T::Output; @@ -233,3 +313,58 @@ impl<T> Instrumented<T> { self.inner } } + +// === impl WithDispatch === + +#[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl<T: Future> Future for WithDispatch<T> { + type Output = T::Output; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { + let this = self.project(); + let dispatcher = this.dispatcher; + let future = this.inner; + let _default = dispatcher::set_default(dispatcher); + future.poll(cx) + } +} + +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl<T: Sized> WithSubscriber for T {} + +#[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl<T> WithDispatch<T> { + /// Borrows the [`Dispatch`] that is entered when this type is polled. + pub fn dispatcher(&self) -> &Dispatch { + &self.dispatcher + } + + /// Borrows the wrapped type. + pub fn inner(&self) -> &T { + &self.inner + } + + /// Mutably borrows the wrapped type. + pub fn inner_mut(&mut self) -> &mut T { + &mut self.inner + } + + /// Get a pinned reference to the wrapped type. + pub fn inner_pin_ref(self: Pin<&Self>) -> Pin<&T> { + self.project_ref().inner + } + + /// Get a pinned mutable reference to the wrapped type. + pub fn inner_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> { + self.project().inner + } + + /// Consumes the `Instrumented`, returning the wrapped type. + /// + /// Note that this drops the span. + pub fn into_inner(self) -> T { + self.inner + } +} diff --git a/vendor/tracing/src/lib.rs b/vendor/tracing/src/lib.rs index a4015a9182..9196934c75 100644 --- a/vendor/tracing/src/lib.rs +++ b/vendor/tracing/src/lib.rs @@ -171,7 +171,7 @@ //! ``` //! //! For functions which don't have built-in tracing support and can't have -//! the `#[instrument]` attribute applied (such as from an external crate, +//! the `#[instrument]` attribute applied (such as from an external crate), //! the [`Span` struct][`Span`] has a [`in_scope()` method][`in_scope`] //! which can be used to easily wrap synchonous code in a span. //! @@ -795,7 +795,7 @@ //! //! ```toml //! [dependencies] -//! tracing = { version = "0.1.28", default-features = false } +//! tracing = { version = "0.1.29", default-features = false } //! ``` //! //! <pre class="ignore" style="white-space:normal;font:inherit;"> @@ -847,7 +847,7 @@ //! [flags]: #crate-feature-flags #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(docsrs, feature(doc_cfg), deny(rustdoc::broken_intra_doc_links))] -#![doc(html_root_url = "https://docs.rs/tracing/0.1.28")] +#![doc(html_root_url = "https://docs.rs/tracing/0.1.29")] #![doc( html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png", issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/" diff --git a/vendor/tracing/tests/event.rs b/vendor/tracing/tests/event.rs index b29d622330..4b30032dbe 100644 --- a/vendor/tracing/tests/event.rs +++ b/vendor/tracing/tests/event.rs @@ -369,3 +369,111 @@ fn explicit_child_at_levels() { handle.assert_finished(); } + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] +#[test] +fn option_values() { + let (subscriber, handle) = subscriber::mock() + .event( + event::mock().with_fields( + field::mock("some_str") + .with_value(&"yes") + .and(field::mock("some_bool").with_value(&true)) + .and(field::mock("some_u64").with_value(&42_u64)) + .only(), + ), + ) + .done() + .run_with_handle(); + + with_default(subscriber, || { + let some_str = Some("yes"); + let none_str: Option<&'static str> = None; + let some_bool = Some(true); + let none_bool: Option<bool> = None; + let some_u64 = Some(42_u64); + let none_u64: Option<u64> = None; + trace!( + some_str = some_str, + none_str = none_str, + some_bool = some_bool, + none_bool = none_bool, + some_u64 = some_u64, + none_u64 = none_u64 + ); + }); + + handle.assert_finished(); +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] +#[test] +fn option_ref_values() { + let (subscriber, handle) = subscriber::mock() + .event( + event::mock().with_fields( + field::mock("some_str") + .with_value(&"yes") + .and(field::mock("some_bool").with_value(&true)) + .and(field::mock("some_u64").with_value(&42_u64)) + .only(), + ), + ) + .done() + .run_with_handle(); + + with_default(subscriber, || { + let some_str = &Some("yes"); + let none_str: &Option<&'static str> = &None; + let some_bool = &Some(true); + let none_bool: &Option<bool> = &None; + let some_u64 = &Some(42_u64); + let none_u64: &Option<u64> = &None; + trace!( + some_str = some_str, + none_str = none_str, + some_bool = some_bool, + none_bool = none_bool, + some_u64 = some_u64, + none_u64 = none_u64 + ); + }); + + handle.assert_finished(); +} + +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] +#[test] +fn option_ref_mut_values() { + let (subscriber, handle) = subscriber::mock() + .event( + event::mock().with_fields( + field::mock("some_str") + .with_value(&"yes") + .and(field::mock("some_bool").with_value(&true)) + .and(field::mock("some_u64").with_value(&42_u64)) + .only(), + ), + ) + .done() + .run_with_handle(); + + with_default(subscriber, || { + let some_str = &mut Some("yes"); + let none_str: &mut Option<&'static str> = &mut None; + let some_bool = &mut Some(true); + let none_bool: &mut Option<bool> = &mut None; + let some_u64 = &mut Some(42_u64); + let none_u64: &mut Option<u64> = &mut None; + trace!( + some_str = some_str, + none_str = none_str, + some_bool = some_bool, + none_bool = none_bool, + some_u64 = some_u64, + none_u64 = none_u64 + ); + }); + + handle.assert_finished(); +} diff --git a/vendor/unic-char-property/.cargo-checksum.json b/vendor/unic-char-property/.cargo-checksum.json new file mode 100644 index 0000000000..b10f557054 --- /dev/null +++ b/vendor/unic-char-property/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"1c21185c9bd84959d197f681719106c1a5f4dface3db421b6660bb9801787929","src/lib.rs":"200af9360e201caaa404fea0c8ec5387fa3ead07f8c056adf56d869768b0201b","src/macros.rs":"969bde9782647b7b8acd8fea1721372eb41e747a6a11de0b7dd8ac9b286759f2","src/pkg_info.rs":"37cbe4efd0b0205d251e1ef7714b23e3be27052c8a0de6b1ae3cbf3aefae1fe5","src/property.rs":"f0e34e995306fef0d2a11bac0f7c385d936f6c7d68aed2ec3e33fc7f5eea57ee","src/range_types.rs":"269d781d752c90c0d8d24a299c4d6318ce5d47d843120f019a53df036030def9","src/tables.rs":"1f2a0213d78fc55a6421df8c74b490b9fd60f37a0b882aacccc6838af14b5279","tests/bool_property_macro.rs":"ce18763a5f7eb86925b0fbad1129dd770c9ddefbab76c1ea27d0a437acb20514","tests/enum_property_macro.rs":"3d19cbdfc9f174dbbba696f791f10659af0d1bc5676969e7f84f269faed174f8","tests/tables/property_table.rsv":"efa2f4a8b3a564a35c9412d095920d5aebad515e11a4a1a415f5ef9d1259974c","tests/tables_tests.rs":"94c4e5f1fcf6b7914deb9295c7e7b3840a5310718e5ea875ae3bc01c7349e0da"},"package":"a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221"} \ No newline at end of file diff --git a/vendor/unic-char-property/Cargo.toml b/vendor/unic-char-property/Cargo.toml new file mode 100644 index 0000000000..2937374504 --- /dev/null +++ b/vendor/unic-char-property/Cargo.toml @@ -0,0 +1,42 @@ +# 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 = "unic-char-property" +version = "0.9.0" +authors = ["The UNIC Project Developers"] +exclude = [] +description = "UNIC — Unicode Character Tools — Character Property taxonomy, contracts and build macros" +keywords = ["text", "unicode", "character-property"] +categories = ["internationalization", "text-processing", "parsing"] +license = "MIT/Apache-2.0" +repository = "https://github.com/open-i18n/rust-unic/" +[dependencies.unic-char-range] +version = "0.9.0" +[badges.appveyor] +branch = "master" +repository = "open-i18n/rust-unic" +service = "github" + +[badges.is-it-maintained-issue-resolution] +repository = "open-i18n/rust-unic" + +[badges.is-it-maintained-open-issues] +repository = "open-i18n/rust-unic" + +[badges.maintenance] +status = "actively-developed" + +[badges.travis-ci] +branch = "master" +repository = "open-i18n/rust-unic" diff --git a/vendor/unic-char-property/src/lib.rs b/vendor/unic-char-property/src/lib.rs new file mode 100644 index 0000000000..360a67165a --- /dev/null +++ b/vendor/unic-char-property/src/lib.rs @@ -0,0 +1,59 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![no_std] +#![warn( + bad_style, + missing_debug_implementations, + missing_docs, + unconditional_recursion +)] +#![forbid(unsafe_code)] + +//! # UNIC — Unicode Character Tools — Character Property +//! +//! A component of [`unic`: Unicode and Internationalization Crates for Rust](/unic/). +//! +//! Character Property taxonomy, contracts and build macros. +//! +//! ## References +//! +//! * [Unicode UTR #23: The Unicode Character Property Model](http://unicode.org/reports/tr23/). +//! +//! * [Unicode UAX #44: Unicode Character Database](http://unicode.org/reports/tr44/). +//! +//! * [PropertyAliases.txt](https://www.unicode.org/Public/UCD/latest/ucd/PropertyAliases.txt). + +#[macro_use] +extern crate unic_char_range; + +mod pkg_info; +pub use crate::pkg_info::{PKG_DESCRIPTION, PKG_NAME, PKG_VERSION}; + +mod property; +pub use self::property::{CharProperty, PartialCharProperty, TotalCharProperty}; + +mod range_types; +pub use crate::range_types::{ + BinaryCharProperty, + CustomCharProperty, + EnumeratedCharProperty, + NumericCharProperty, + NumericCharPropertyValue, +}; + +mod macros; + +// pub because is used in macros, called from macro call-site. +pub mod tables; + +// Used in macros +#[doc(hidden)] +pub use core::{fmt as __fmt, str as __str}; diff --git a/vendor/unic-char-property/src/macros.rs b/vendor/unic-char-property/src/macros.rs new file mode 100644 index 0000000000..b5f054347c --- /dev/null +++ b/vendor/unic-char-property/src/macros.rs @@ -0,0 +1,293 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/// Macro for declaring a character property. +/// +/// # Syntax (Enumerated Property) +/// +/// ``` +/// #[macro_use] +/// extern crate unic_char_property; +/// +/// // First we define the type itself. +/// char_property! { +/// /// This is the enum type created for the character property. +/// pub enum MyProp { +/// abbr => "AbbrPropName"; +/// long => "Long_Property_Name"; +/// human => "Human-Readable Property Name"; +/// +/// /// Zero or more documentation or other attributes. +/// RustName { +/// abbr => AbbrName, +/// long => Long_Name, +/// human => "&'static str that is a nicer presentation of the name", +/// } +/// } +/// +/// /// Module aliasing property value abbreviated names. +/// pub mod abbr_names for abbr; +/// +/// /// Module aliasing property value long names. +/// pub mod long_names for long; +/// } +/// +/// // We also need to impl `PartialCharProperty` or `TotalCharProperty` manually. +/// # impl unic_char_property::PartialCharProperty for MyProp { +/// # fn of(_: char) -> Option<Self> { None } +/// # } +/// # +/// # fn main() {} +/// ``` +/// +/// # Syntax (Binary Property) +/// +/// ``` +/// #[macro_use] extern crate unic_char_property; +/// # #[macro_use] extern crate unic_char_range; +/// +/// char_property! { +/// /// This is the newtype used for the character property. +/// pub struct MyProp(bool) { +/// abbr => "AbbrPropName"; +/// long => "Long_Property_Name"; +/// human => "Human-Readable Property Name"; +/// +/// // Unlike an enumerated property, a binary property will handle the table for you. +/// data_table_path => "../tests/tables/property_table.rsv"; +/// } +/// +/// /// A function that returns whether the given character has the property or not. +/// pub fn is_prop(char) -> bool; +/// } +/// +/// // You may also want to create a trait for easy access to the properties you define. +/// # fn main() {} +/// ``` +/// +/// # Effect +/// +/// - Implements the `CharProperty` trait and appropriate range trait +/// - Implements `FromStr` accepting either the abbr or long name, ascii case insensitive +/// - Implements `Display` using the `human` string +/// - Populates the module `abbr_names` with `pub use` bindings of variants to their abbr names +/// (Enumerated properties only) +/// - Populates the module `long_names` with `pub use` bindings of variants to their long names +/// (Enumerated properties only) +/// - Maintains all documentation comments and other `#[attributes]` as would be expected +/// (with some limitations, listed below) +/// +#[macro_export] +macro_rules! char_property { + + // == Enumerated Property == // + + ( + $(#[$prop_meta:meta])* + pub enum $prop_name:ident { + abbr => $prop_abbr:expr; + long => $prop_long:expr; + human => $prop_human:expr; + + $( + $(#[$variant_meta:meta])* + $variant_name:ident { + abbr => $variant_abbr:ident, + long => $variant_long:ident, + human => $variant_human:expr, + } + )* + } + + $(#[$abbr_mod_meta:meta])* + pub mod $abbr_mod:ident for abbr; + + $(#[$long_mod_meta:meta])* + pub mod $long_mod:ident for long; + + ) => { + $(#[$prop_meta])* + #[allow(bad_style)] + #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] + pub enum $prop_name { + $( $(#[$variant_meta])* $variant_name, )* + } + + $(#[$abbr_mod_meta])* + #[allow(bad_style)] + pub mod $abbr_mod { + $( pub use super::$prop_name::$variant_name as $variant_abbr; )* + } + + $(#[$long_mod_meta])* + #[allow(bad_style)] + pub mod $long_mod { + $( pub use super::$prop_name::$variant_name as $variant_long; )* + } + + char_property! { + __impl FromStr for $prop_name; + $( + stringify!($variant_abbr) => $prop_name::$variant_name; + stringify!($variant_long) => $prop_name::$variant_name; + )* + } + + char_property! { + __impl CharProperty for $prop_name; + $prop_abbr; + $prop_long; + $prop_human; + } + + char_property! { + __impl Display for $prop_name by EnumeratedCharProperty + } + + impl $crate::EnumeratedCharProperty for $prop_name { + fn all_values() -> &'static [$prop_name] { + const VALUES: &[$prop_name] = &[ + $( $prop_name::$variant_name, )* + ]; + VALUES + } + fn abbr_name(&self) -> &'static str { + match *self { + $( $prop_name::$variant_name => stringify!($variant_abbr), )* + } + } + fn long_name(&self) -> &'static str { + match *self { + $( $prop_name::$variant_name => stringify!($variant_long), )* + } + } + fn human_name(&self) -> &'static str { + match *self { + $( $prop_name::$variant_name => $variant_human, )* + } + } + } + }; + + // == Binary Property == // + + ( + $(#[$prop_meta:meta])* + pub struct $prop_name:ident(bool) { + abbr => $prop_abbr:expr; + long => $prop_long:expr; + human => $prop_human:expr; + + data_table_path => $data_path:expr; + } + + $(#[$is_fn_meta:meta])* + pub fn $is_fn:ident(char) -> bool; + + ) => { + $(#[$prop_meta])* + #[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Hash)] + pub struct $prop_name(bool); + + $(#[$is_fn_meta])* + pub fn $is_fn(ch: char) -> bool { + $prop_name::of(ch).as_bool() + } + + impl $prop_name { + /// Get (struct) property value of the character. + pub fn of(ch: char) -> Self { + use $crate::tables::CharDataTable; + const TABLE: CharDataTable<()> = include!($data_path); + $prop_name(TABLE.contains(ch)) + } + + /// Get boolean property value of the character. + pub fn as_bool(&self) -> bool { self.0 } + } + + char_property! { + __impl FromStr for $prop_name; + // Yes + "y" => $prop_name(true); + "yes" => $prop_name(true); + "t" => $prop_name(true); + "true" => $prop_name(true); + // No + "n" => $prop_name(false); + "no" => $prop_name(false); + "f" => $prop_name(false); + "false" => $prop_name(false); + } + + char_property! { + __impl CharProperty for $prop_name; + $prop_abbr; + $prop_long; + $prop_human; + } + + impl $crate::TotalCharProperty for $prop_name { + fn of(ch: char) -> Self { Self::of(ch) } + } + + impl $crate::BinaryCharProperty for $prop_name { + fn as_bool(&self) -> bool { self.as_bool() } + } + + impl From<$prop_name> for bool { + fn from(prop: $prop_name) -> bool { prop.as_bool() } + } + + char_property! { + __impl Display for $prop_name by BinaryCharProperty + } + }; + + // == Shared == // + + ( + __impl CharProperty for $prop_name:ident; + $prop_abbr:expr; + $prop_long:expr; + $prop_human:expr; + ) => { + impl $crate::CharProperty for $prop_name { + fn prop_abbr_name() -> &'static str { $prop_abbr } + fn prop_long_name() -> &'static str { $prop_long } + fn prop_human_name() -> &'static str { $prop_human } + } + }; + + ( + __impl FromStr for $prop_name:ident; + $( $id:expr => $value:expr; )* + ) => { + #[allow(unreachable_patterns)] + impl $crate::__str::FromStr for $prop_name { + type Err = (); + fn from_str(s: &str) -> Result<Self, Self::Err> { + match s { + $( $id => Ok($value), )* + $( s if s.eq_ignore_ascii_case($id) => Ok($value), )* + _ => Err(()), + } + } + } + }; + + ( __impl Display for $prop_name:ident by $trait:ident ) => { + impl $crate::__fmt::Display for $prop_name { + fn fmt(&self, f: &mut $crate::__fmt::Formatter) -> $crate::__fmt::Result { + $crate::$trait::human_name(self).fmt(f) + } + } + }; +} diff --git a/vendor/unic-char-property/src/pkg_info.rs b/vendor/unic-char-property/src/pkg_info.rs new file mode 100644 index 0000000000..a1ab2853fd --- /dev/null +++ b/vendor/unic-char-property/src/pkg_info.rs @@ -0,0 +1,20 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Package information + +/// UNIC component version. +pub const PKG_VERSION: &str = env!("CARGO_PKG_VERSION"); + +/// UNIC component name. +pub const PKG_NAME: &str = env!("CARGO_PKG_NAME"); + +/// UNIC component description. +pub const PKG_DESCRIPTION: &str = env!("CARGO_PKG_DESCRIPTION"); diff --git a/vendor/unic-char-property/src/property.rs b/vendor/unic-char-property/src/property.rs new file mode 100644 index 0000000000..47d367f4dd --- /dev/null +++ b/vendor/unic-char-property/src/property.rs @@ -0,0 +1,48 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Taxonomy and contracts for Character Property types. + +use core::fmt::Debug; +use core::hash::Hash; + +/// A Character Property, defined for some or all Unicode characters. +pub trait CharProperty: PartialCharProperty + Debug + Eq + Hash { + /// The *abbreviated name* of the property. + fn prop_abbr_name() -> &'static str; + + /// The *long name* of the property. + fn prop_long_name() -> &'static str; + + /// The *human-readable* name of the property. + fn prop_human_name() -> &'static str; +} + +/// A Character Property defined for some characters. +/// +/// Examples: `Decomposition_Type`, `Numeric_Type` +pub trait PartialCharProperty: Copy { + /// The property value for the character, or None. + fn of(ch: char) -> Option<Self>; +} + +/// A Character Property defined on all characters. +/// +/// Examples: `Age`, `Name`, `General_Category`, `Bidi_Class` +pub trait TotalCharProperty: PartialCharProperty + Default { + /// The property value for the character. + fn of(ch: char) -> Self; +} + +impl<T: TotalCharProperty> PartialCharProperty for T { + fn of(ch: char) -> Option<Self> { + Some(<Self as TotalCharProperty>::of(ch)) + } +} diff --git a/vendor/unic-char-property/src/range_types.rs b/vendor/unic-char-property/src/range_types.rs new file mode 100644 index 0000000000..e3cd479153 --- /dev/null +++ b/vendor/unic-char-property/src/range_types.rs @@ -0,0 +1,104 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Character Property Range types. +//! +//! NOTE: At the moment, it is not possible to define a marker for all character property range +//! types and enforce their implementation from `CharProperty`. We need to fix this whenever the +//! compiler becomes able to do to so. + +use super::property::CharProperty; + +// == Enumerated/Catalog Types == + +/// A Character Property with enumerated values. +/// +/// This is similar to types *Enumeration* and *Catalog*, as defined in UAX#44. +/// +/// Usage Note: If the property is of type *Catalog*, it's recommended to (in some way) mark the +/// type as *non-exhaustive*, so that adding new variants to the `enum` type won't result in API +/// breakage. +pub trait EnumeratedCharProperty: Sized + CharProperty { + /// Exhaustive list of all property values. + fn all_values() -> &'static [Self]; + + /// The *abbreviated name* of the property value. + fn abbr_name(&self) -> &'static str; + + /// The *long name* of the property value. + fn long_name(&self) -> &'static str; + + /// The *human-readable name* of the property value. + fn human_name(&self) -> &'static str; +} + +// == Binary Types == + +/// A Character Property with binary values. +/// +/// Examples: `Alphabetic`, `Bidi_Mirrored`, `White_Space` +pub trait BinaryCharProperty: CharProperty { + /// The boolean value of the property value. + fn as_bool(&self) -> bool; + + /// The *abbreviated name* of the property value. + fn abbr_name(&self) -> &'static str { + if self.as_bool() { + "Y" + } else { + "N" + } + } + + /// The *long name* of the property value. + fn long_name(&self) -> &'static str { + if self.as_bool() { + "Yes" + } else { + "No" + } + } + + /// The *human-readable name* of the property value. + fn human_name(&self) -> &'static str { + if self.as_bool() { + "Yes" + } else { + "No" + } + } +} + +// == Numeric Types == + +/// Marker for numeric types accepted by `NumericCharProperty`. +pub trait NumericCharPropertyValue {} + +impl NumericCharPropertyValue for u8 {} + +/// A Character Property with numeric values. +/// +/// Examples: `Numeric_Value`, `Canonical_Combining_Class` +pub trait NumericCharProperty<NumericValue: NumericCharPropertyValue>: CharProperty { + /// The numeric value for the property value. + fn number(&self) -> NumericValue; +} + +// == Custom Types == + +/// A Character Property with custom values. +/// +/// Custom values means any non-enumerated, non-numeric value. +/// +/// Examples: `Age` property that returns a `UnicodeVersion` value. +pub trait CustomCharProperty<Value>: CharProperty { + /// The actual (inner) value for the property value. + fn actual(&self) -> Value; +} diff --git a/vendor/unic-char-property/src/tables.rs b/vendor/unic-char-property/src/tables.rs new file mode 100644 index 0000000000..ab419d5524 --- /dev/null +++ b/vendor/unic-char-property/src/tables.rs @@ -0,0 +1,117 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Character data tables used in UNIC. + +use unic_char_range::CharRange; + +/// A mapping from characters to some associated data. +/// +/// For the set case, use `()` as the associated value. +#[derive(Copy, Clone, Debug)] +pub enum CharDataTable<V: 'static> { + #[doc(hidden)] + Direct(&'static [(char, V)]), + #[doc(hidden)] + Range(&'static [(CharRange, V)]), +} + +impl<V> Default for CharDataTable<V> { + fn default() -> Self { + CharDataTable::Direct(&[]) + } +} + +impl<V> CharDataTable<V> { + /// Does this table contain a mapping for a character? + pub fn contains(&self, needle: char) -> bool { + match *self { + CharDataTable::Direct(table) => { + table.binary_search_by_key(&needle, |&(k, _)| k).is_ok() + } + CharDataTable::Range(table) => table + .binary_search_by(|&(range, _)| range.cmp_char(needle)) + .is_ok(), + } + } +} + +impl<V: Copy> CharDataTable<V> { + /// Find the associated data for a character in this table. + pub fn find(&self, needle: char) -> Option<V> { + match *self { + CharDataTable::Direct(table) => table + .binary_search_by_key(&needle, |&(k, _)| k) + .map(|idx| table[idx].1) + .ok(), + CharDataTable::Range(table) => table + .binary_search_by(|&(range, _)| range.cmp_char(needle)) + .map(|idx| table[idx].1) + .ok(), + } + } + + /// Find the range and the associated data for a character in the range table. + pub fn find_with_range(&self, needle: char) -> Option<(CharRange, V)> { + match *self { + CharDataTable::Direct(_) => None, + CharDataTable::Range(table) => table + .binary_search_by(|&(range, _)| range.cmp_char(needle)) + .map(|idx| table[idx]) + .ok(), + } + } +} + +impl<V: Copy + Default> CharDataTable<V> { + /// Find the associated data for a character in this table, or the default value if not entered. + pub fn find_or_default(&self, needle: char) -> V { + self.find(needle).unwrap_or_else(Default::default) + } +} + +/// Iterator for `CharDataTable`. Iterates over pairs `(CharRange, V)`. +#[derive(Debug)] +pub struct CharDataTableIter<'a, V: 'static>(&'a CharDataTable<V>, usize); + +impl<'a, V: Copy> Iterator for CharDataTableIter<'a, V> { + type Item = (CharRange, V); + + fn next(&mut self) -> Option<Self::Item> { + match *self.0 { + CharDataTable::Direct(arr) => { + if self.1 >= arr.len() { + None + } else { + let idx = self.1; + self.1 += 1; + let (ch, v) = arr[idx]; + Some((chars!(ch..=ch), v)) + } + } + CharDataTable::Range(arr) => { + if self.1 >= arr.len() { + None + } else { + let idx = self.1; + self.1 += 1; + Some(arr[idx]) + } + } + } + } +} + +impl<V> CharDataTable<V> { + /// Iterate over the entries in this table. Yields pairs `(CharRange, V)`. + pub fn iter(&self) -> CharDataTableIter<'_, V> { + CharDataTableIter(self, 0) + } +} diff --git a/vendor/unic-char-property/tests/bool_property_macro.rs b/vendor/unic-char-property/tests/bool_property_macro.rs new file mode 100644 index 0000000000..7b452eea92 --- /dev/null +++ b/vendor/unic-char-property/tests/bool_property_macro.rs @@ -0,0 +1,73 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate unic_char_property; + +#[macro_use] +extern crate unic_char_range; + +char_property! { + /// This is a test property. + pub struct MyProp(bool) { + abbr => "mp"; + long => "My_Prop"; + human => "My Property"; + + data_table_path => "tables/property_table.rsv"; + } + + /// This is the shorthand function. + pub fn is_my_prop(char) -> bool; +} + +#[test] +fn test_basics() { + assert_eq!(MyProp::of('\u{0000}').as_bool(), false); + assert_eq!(MyProp::of('\u{0065}').as_bool(), true); + + assert_eq!(is_my_prop('\u{0000}'), false); + assert_eq!(is_my_prop('\u{0065}'), true); +} + +#[cfg_attr(feature = "cargo-clippy", allow(needless_bool))] +#[test] +fn test_into_bool() { + assert!(if MyProp::of('\u{0065}').into() { + true + } else { + false + }); +} + +#[test] +fn test_from_str() { + assert_eq!("y".parse(), Ok(MyProp(true))); + assert_eq!("yes".parse(), Ok(MyProp(true))); + assert_eq!("t".parse(), Ok(MyProp(true))); + assert_eq!("true".parse(), Ok(MyProp(true))); + + assert_eq!("N".parse(), Ok(MyProp(false))); + assert_eq!("NO".parse(), Ok(MyProp(false))); + assert_eq!("F".parse(), Ok(MyProp(false))); + assert_eq!("FALSE".parse(), Ok(MyProp(false))); +} + +#[test] +fn test_display() { + use unic_char_property::BinaryCharProperty; + + assert_eq!(MyProp::of('\u{0000}').abbr_name(), "N"); + assert_eq!(MyProp::of('\u{0065}').abbr_name(), "Y"); + assert_eq!(MyProp::of('\u{0000}').long_name(), "No"); + assert_eq!(MyProp::of('\u{0065}').long_name(), "Yes"); + assert_eq!(MyProp::of('\u{0000}').human_name(), "No"); + assert_eq!(MyProp::of('\u{0065}').human_name(), "Yes"); +} diff --git a/vendor/unic-char-property/tests/enum_property_macro.rs b/vendor/unic-char-property/tests/enum_property_macro.rs new file mode 100644 index 0000000000..e1caa41f54 --- /dev/null +++ b/vendor/unic-char-property/tests/enum_property_macro.rs @@ -0,0 +1,87 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate unic_char_property; + +use unic_char_property::PartialCharProperty; + +char_property! { + pub enum MyProp { + abbr => "mp"; + long => "My_Prop"; + human => "My Property"; + + /// Variants can have multi-line documentations, + /// and/or other attributes. + Variant1 { + abbr => V1, + long => Variant_1, + human => "Variant 1", + } + + /// One line works too, or... + Variant2 { + abbr => V2, + long => Variant_2, + human => "Variant 2", + } + + Variant3 { + abbr => V3, + long => Variant_3, + human => "Variant 3", + } + } + + pub mod abbr_names for abbr; + pub mod long_names for long; +} + +impl PartialCharProperty for MyProp { + fn of(_: char) -> Option<Self> { + None + } +} + +#[test] +fn test_basic_macro_use() { + use unic_char_property::EnumeratedCharProperty; + + assert_eq!(MyProp::Variant1, abbr_names::V1); + assert_eq!(MyProp::Variant2, abbr_names::V2); + assert_eq!(MyProp::Variant3, abbr_names::V3); + + assert_eq!(MyProp::Variant1, long_names::Variant_1); + assert_eq!(MyProp::Variant2, long_names::Variant_2); + assert_eq!(MyProp::Variant3, long_names::Variant_3); + + assert_eq!(MyProp::Variant1.abbr_name(), "V1"); + assert_eq!(MyProp::Variant2.abbr_name(), "V2"); + assert_eq!(MyProp::Variant3.abbr_name(), "V3"); + + assert_eq!(MyProp::Variant1.long_name(), "Variant_1"); + assert_eq!(MyProp::Variant2.long_name(), "Variant_2"); + assert_eq!(MyProp::Variant3.long_name(), "Variant_3"); + + assert_eq!(MyProp::Variant1.human_name(), "Variant 1"); + assert_eq!(MyProp::Variant2.human_name(), "Variant 2"); + assert_eq!(MyProp::Variant3.human_name(), "Variant 3"); +} + +#[test] +fn test_fromstr_ignores_case() { + use crate::abbr_names::V1; + + assert_eq!("variant_1".parse(), Ok(V1)); + assert_eq!("VaRiAnT_1".parse(), Ok(V1)); + assert_eq!("vArIaNt_1".parse(), Ok(V1)); + assert_eq!("VARIANT_1".parse(), Ok(V1)); +} diff --git a/vendor/unic-char-property/tests/tables/property_table.rsv b/vendor/unic-char-property/tests/tables/property_table.rsv new file mode 100644 index 0000000000..a4391b162d --- /dev/null +++ b/vendor/unic-char-property/tests/tables/property_table.rsv @@ -0,0 +1,3 @@ +CharDataTable::Range(&[ + (chars!(' '..='~'), ()), +]) diff --git a/vendor/unic-char-property/tests/tables_tests.rs b/vendor/unic-char-property/tests/tables_tests.rs new file mode 100644 index 0000000000..d206495879 --- /dev/null +++ b/vendor/unic-char-property/tests/tables_tests.rs @@ -0,0 +1,43 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate unic_char_range; + +use unic_char_property::tables::CharDataTable; + +#[test] +fn test_range_value_table() { + const TABLE: CharDataTable<u32> = CharDataTable::Range(&[ + (chars!('a'..='g'), 1), + (chars!('j'..='q'), 2), + (chars!('w'..='z'), 3), + ]); + for ch in chars!('a'..='g') { + assert_eq!(TABLE.find(ch), Some(1)); + assert_eq!(TABLE.find_or_default(ch), 1); + } + for ch in chars!('h'..='i') { + assert_eq!(TABLE.find(ch), None); + assert_eq!(TABLE.find_or_default(ch), 0); + } + for ch in chars!('j'..='q') { + assert_eq!(TABLE.find(ch), Some(2)); + assert_eq!(TABLE.find_or_default(ch), 2); + } + for ch in chars!('r'..='v') { + assert_eq!(TABLE.find(ch), None); + assert_eq!(TABLE.find_or_default(ch), 0); + } + for ch in chars!('x'..='z') { + assert_eq!(TABLE.find(ch), Some(3)); + assert_eq!(TABLE.find_or_default(ch), 3); + } +} diff --git a/vendor/unic-char-range/.cargo-checksum.json b/vendor/unic-char-range/.cargo-checksum.json new file mode 100644 index 0000000000..3f53bcd997 --- /dev/null +++ b/vendor/unic-char-range/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"36d694fec9b997f5cd86861a5d062d0e69794e051b07d8ebf1b79ab9482c3462","benches/benchmarks.rs":"43c24a525f93c2417e09e4a3914523faf5802e8d4e33697070ddb429ef16fbe0","examples/macro_use_std_tests.rs":"f96109f197e7750ed5ab10041542a5b59a0f3a791e52cc88ebfe5e098b05711e","src/iter.rs":"aeb949486a521f8c273d7875536d030643f74603112ef6688bafdd639bd8f487","src/iter_fused.rs":"2ab4a76b8e9610163deda5c602881c2b8e9696f607580a04bb4e17754e4f8f9b","src/iter_trusted_len.rs":"b89e6d7dbbc2f46a1b66015b1b5d2bc12d91309880847d4f980f7b39ff4a8945","src/lib.rs":"955ee0b9069740fd1ee724943562f9189b7eb29b49d79c8c352a6f193c12c3ec","src/macros.rs":"7f0a7eedfdd31a0d5f10b16f342524663b4f2c82a0c97728f8677d0d29490241","src/par_iter.rs":"d6a213e83fc3bd0b0d248c0a7e42fe1b8e24eeca1424195c4638c7328795d018","src/pkg_info.rs":"37cbe4efd0b0205d251e1ef7714b23e3be27052c8a0de6b1ae3cbf3aefae1fe5","src/range.rs":"5ce555d9cf8513c76f3b45002a3eed4a07cfe8a51e769f9888270091d319cb05","src/step.rs":"66cbc3e291f1014f994c88b61a741e4cd84e9ef62debef5e160b4ae4f5211bd7","tests/iter_tests.rs":"5af9a84509e992e83d1ee90e86ec1e88352edf7926013b4c7cbdfe1f90c61b7a"},"package":"0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc"} \ No newline at end of file diff --git a/vendor/unic-char-range/Cargo.toml b/vendor/unic-char-range/Cargo.toml new file mode 100644 index 0000000000..42731411e7 --- /dev/null +++ b/vendor/unic-char-range/Cargo.toml @@ -0,0 +1,51 @@ +# 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 = "unic-char-range" +version = "0.9.0" +authors = ["The UNIC Project Developers"] +exclude = [] +description = "UNIC — Unicode Character Tools — Character Range and Iteration" +keywords = ["text", "unicode", "utilities", "iteration"] +categories = ["internationalization", "text-processing"] +license = "MIT/Apache-2.0" +repository = "https://github.com/open-i18n/rust-unic/" +[dependencies.rayon] +version = "1.0" +optional = true + +[features] +default = [] +exact-size-is-empty = [] +fused = [] +std = [] +trusted-len = [] +unstable = ["exact-size-is-empty", "fused", "trusted-len"] +[badges.appveyor] +branch = "master" +repository = "open-i18n/rust-unic" +service = "github" + +[badges.is-it-maintained-issue-resolution] +repository = "open-i18n/rust-unic" + +[badges.is-it-maintained-open-issues] +repository = "open-i18n/rust-unic" + +[badges.maintenance] +status = "actively-developed" + +[badges.travis-ci] +branch = "master" +repository = "open-i18n/rust-unic" diff --git a/vendor/unic-char-range/benches/benchmarks.rs b/vendor/unic-char-range/benches/benchmarks.rs new file mode 100644 index 0000000000..a05ac271e7 --- /dev/null +++ b/vendor/unic-char-range/benches/benchmarks.rs @@ -0,0 +1,41 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(test)] + +extern crate test; + +use std::char; +use unic_char_range::CharRange; + +#[bench] +fn forward_iteration(b: &mut test::Bencher) { + b.iter(|| CharRange::all().iter().count()) +} + +#[bench] +fn forward_iteration_baseline(b: &mut test::Bencher) { + b.iter(|| (0..0x11_0000).filter_map(char::from_u32).count()) +} + +#[bench] +fn reverse_iteration(b: &mut test::Bencher) { + b.iter(|| CharRange::all().iter().rev().count()) +} + +#[bench] +fn reverse_iteration_baseline(b: &mut test::Bencher) { + b.iter(|| (0..0x11_0000).rev().filter_map(char::from_u32).count()) +} + +#[bench] +fn range_length(b: &mut test::Bencher) { + b.iter(|| CharRange::all().len()) +} diff --git a/vendor/unic-char-range/examples/macro_use_std_tests.rs b/vendor/unic-char-range/examples/macro_use_std_tests.rs new file mode 100644 index 0000000000..751f93ae3e --- /dev/null +++ b/vendor/unic-char-range/examples/macro_use_std_tests.rs @@ -0,0 +1,18 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate unic_char_range; + +fn main() { + assert!(chars!('\u{0}'..='\u{2}') + .iter() + .eq(['\u{0}', '\u{1}', '\u{2}'].iter().cloned())); +} diff --git a/vendor/unic-char-range/src/iter.rs b/vendor/unic-char-range/src/iter.rs new file mode 100644 index 0000000000..44901dfe3c --- /dev/null +++ b/vendor/unic-char-range/src/iter.rs @@ -0,0 +1,151 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::{char, ops}; + +use crate::{step, CharRange}; + +const SURROGATE_RANGE: ops::Range<u32> = 0xD800..0xE000; + +/// An iterator over a range of unicode code points. +/// +/// Constructed via `CharRange::iter`. See `CharRange` for more information. +#[derive(Clone, Debug)] +pub struct CharIter { + /// The lowest uniterated character (inclusive). + /// + /// Iteration is finished if this is higher than `high`. + low: char, + + /// The highest uniterated character (inclusive). + /// + /// Iteration is finished if this is lower than `low`. + high: char, +} + +impl From<CharRange> for CharIter { + fn from(range: CharRange) -> CharIter { + CharIter { + low: range.low, + high: range.high, + } + } +} + +impl From<CharIter> for CharRange { + fn from(iter: CharIter) -> CharRange { + CharRange { + low: iter.low, + high: iter.high, + } + } +} + +impl CharIter { + #[inline] + #[allow(unsafe_code)] + // When stepping `self.low` forward would go over `char::MAX`, + // Set `self.high` to `'\0'` instead. It will have the same effect -- + // consuming the last element from the iterator and ending iteration. + fn step_forward(&mut self) { + if self.low == char::MAX { + self.high = '\0' + } else { + self.low = unsafe { step::forward(self.low) } + } + } + + #[inline] + #[allow(unsafe_code)] + // When stepping `self.high` backward would cause underflow, + // set `self.low` to `char::MAX` instead. It will have the same effect -- + // consuming the last element from the iterator and ending iteration. + fn step_backward(&mut self) { + if self.high == '\0' { + self.low = char::MAX; + } else { + self.high = unsafe { step::backward(self.high) } + } + } + + #[inline] + /// ExactSizeIterator::is_empty() for stable + fn is_finished(&self) -> bool { + self.low > self.high + } +} + +impl Iterator for CharIter { + type Item = char; + + #[inline] + fn next(&mut self) -> Option<char> { + if self.is_finished() { + return None; + } + + let ch = self.low; + self.step_forward(); + Some(ch) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + let len = self.len(); + (len, Some(len)) + } + + fn last(self) -> Option<char> { + if self.is_finished() { + None + } else { + Some(self.high) + } + } + + fn max(self) -> Option<char> { + self.last() + } + + fn min(mut self) -> Option<char> { + self.next() + } +} + +impl DoubleEndedIterator for CharIter { + #[inline] + fn next_back(&mut self) -> Option<Self::Item> { + if self.is_finished() { + None + } else { + let ch = self.high; + self.step_backward(); + Some(ch) + } + } +} + +impl ExactSizeIterator for CharIter { + fn len(&self) -> usize { + if self.is_finished() { + return 0; + } + let naive_range = (self.low as u32)..(self.high as u32 + 1); + if naive_range.start <= SURROGATE_RANGE.start && SURROGATE_RANGE.end <= naive_range.end { + naive_range.len() - SURROGATE_RANGE.len() + } else { + naive_range.len() + } + } + + #[cfg(feature = "exact-size-is-empty")] + fn is_empty(&self) -> bool { + self.is_finished() + } +} diff --git a/vendor/unic-char-range/src/iter_fused.rs b/vendor/unic-char-range/src/iter_fused.rs new file mode 100644 index 0000000000..f0a3faeb34 --- /dev/null +++ b/vendor/unic-char-range/src/iter_fused.rs @@ -0,0 +1,15 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::iter; + +use super::iter::CharIter; + +impl iter::FusedIterator for CharIter {} diff --git a/vendor/unic-char-range/src/iter_trusted_len.rs b/vendor/unic-char-range/src/iter_trusted_len.rs new file mode 100644 index 0000000000..aaf8e53405 --- /dev/null +++ b/vendor/unic-char-range/src/iter_trusted_len.rs @@ -0,0 +1,16 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::iter; + +use super::iter::CharIter; + +#[allow(unsafe_code)] +unsafe impl iter::TrustedLen for CharIter {} diff --git a/vendor/unic-char-range/src/lib.rs b/vendor/unic-char-range/src/lib.rs new file mode 100644 index 0000000000..1f6e82c474 --- /dev/null +++ b/vendor/unic-char-range/src/lib.rs @@ -0,0 +1,75 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(feature = "exact-size-is-empty", feature(exact_size_is_empty))] +#![cfg_attr(feature = "trusted-len", feature(trusted_len))] +#![warn( + bad_style, + missing_debug_implementations, + missing_docs, + unconditional_recursion +)] +#![deny(unsafe_code)] + +//! # UNIC — Unicode Character Tools — Character Range +//! +//! A simple way to control iteration over a range of characters. +//! +//! # Examples +//! +//! ``` +//! #[macro_use] extern crate unic_char_range; +//! +//! # fn main() { +//! for character in chars!('a'..='z') { +//! // character is each character in the lowercase english alphabet in order +//! } +//! +//! for character in chars!(..) { +//! // character is every valid char from lowest codepoint to highest +//! } +//! # } +//! ``` +//! +//! # Features +//! +//! None of these features are included by default; they rely on unstable Rust feature gates. +//! +//! - `unstable`: enables all features +//! - `exact-size-is-empty`: provide a specific impl of [`ExactSizeIterator::is_empty`][is_empty] +//! - `trusted-len`: impl the [`TrustedLen`] contract +//! +//! [is_empty]: https://doc.rust-lang.org/std/iter/trait.ExactSizeIterator.html#method.is_empty +//! [`FusedIterator`]: https://doc.rust-lang.org/std/iter/trait.FusedIterator.html +//! [`TrustedLen`]: https://doc.rust-lang.org/std/iter/trait.TrustedLen.html +//! + +mod pkg_info; +pub use crate::pkg_info::{PKG_DESCRIPTION, PKG_NAME, PKG_VERSION}; + +mod iter; +pub use crate::iter::CharIter; + +mod range; +pub use crate::range::CharRange; + +#[macro_use] +mod macros; + +mod step; + +mod iter_fused; + +#[cfg(feature = "trusted-len")] +mod iter_trusted_len; + +#[cfg(feature = "rayon")] +mod par_iter; diff --git a/vendor/unic-char-range/src/macros.rs b/vendor/unic-char-range/src/macros.rs new file mode 100644 index 0000000000..a1b41d2957 --- /dev/null +++ b/vendor/unic-char-range/src/macros.rs @@ -0,0 +1,44 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_export] +/// Convenience macro for the initialization of `CharRange`s. +/// +/// # Syntax +/// +/// ``` +/// # #[macro_use] extern crate unic_char_range; +/// # fn main() { +/// chars!('a'..'z'); // The half open range including 'a' and excluding 'z' +/// chars!('a'..='z'); // The closed range including 'a' and including 'z' +/// chars!(..); // All characters +/// # } +/// ``` +/// +/// `chars!('a'..='z')` and `chars!(..)` are constant-time expressions, and can be used +/// where such are required, such as in the initialization of constant data structures. +/// +/// NOTE: Because an `expr` capture cannot be followed by a `..`/`..=`, this macro captures token +/// trees. This means that if you want to pass more than one token, you must parenthesize it (e.g. +/// `chars!('\0' ..= (char::MAX))`). +macro_rules! chars { + ( $low:tt .. $high:tt ) => { + $crate::CharRange::open_right($low, $high) + }; + ( $low:tt ..= $high:tt ) => { + $crate::CharRange { + low: $low, + high: $high, + } + }; + ( .. ) => { + $crate::CharRange::all() + }; +} diff --git a/vendor/unic-char-range/src/par_iter.rs b/vendor/unic-char-range/src/par_iter.rs new file mode 100644 index 0000000000..5b40d221a0 --- /dev/null +++ b/vendor/unic-char-range/src/par_iter.rs @@ -0,0 +1,110 @@ +// Copyright 2018 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use rayon; + +use self::rayon::iter::plumbing::{Consumer, ProducerCallback, UnindexedConsumer}; +use self::rayon::prelude::*; +use crate::step::{AFTER_SURROGATE, BEFORE_SURROGATE}; +use crate::CharRange; +use core::char; +use core::ops::Range; + +const SKIP_LENGTH: u32 = + crate::step::AFTER_SURROGATE as u32 - crate::step::BEFORE_SURROGATE as u32 - 1; + +#[derive(Clone, Debug)] +pub struct Iter(rayon::iter::Map<rayon::range::Iter<u32>, fn(u32) -> char>); + +impl ParallelIterator for Iter { + type Item = char; + + fn drive_unindexed<C>(self, consumer: C) -> C::Result + where + C: UnindexedConsumer<Self::Item>, + { + self.0.drive_unindexed(consumer) + } +} + +impl IndexedParallelIterator for Iter { + fn len(&self) -> usize { + self.0.len() + } + + fn drive<C: Consumer<Self::Item>>(self, consumer: C) -> C::Result { + self.0.drive(consumer) + } + + fn with_producer<CB: ProducerCallback<Self::Item>>(self, callback: CB) -> CB::Output { + self.0.with_producer(callback) + } +} + +impl CharRange { + fn compact_range(&self) -> Range<u32> { + let low = self.low as u32; + let high = self.high as u32 + 1; + low..(if self.high >= AFTER_SURROGATE { + high - SKIP_LENGTH + } else { + high + }) + } +} + +impl IntoParallelIterator for CharRange { + type Item = char; + type Iter = Iter; + + fn into_par_iter(self) -> Self::Iter { + Iter(self.compact_range().into_par_iter().map(|c| { + let c = if c > BEFORE_SURROGATE as u32 { + c + SKIP_LENGTH + } else { + c + }; + debug_assert!(c <= BEFORE_SURROGATE as u32 || c >= AFTER_SURROGATE as u32); + debug_assert!(c <= char::MAX as u32); + #[allow(unsafe_code)] + unsafe { + char::from_u32_unchecked(c) + } + })) + } +} + +impl<'a> IntoParallelIterator for &'a CharRange { + type Item = char; + type Iter = Iter; + + fn into_par_iter(self) -> Self::Iter { + (*self).into_par_iter() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn length_agrees() { + assert_eq!(chars!(..).iter().count(), chars!(..).par_iter().count()) + } + + #[test] + #[cfg(feature = "std")] + fn content_agrees() { + assert_eq!( + chars!(..).iter().collect::<Vec<_>>(), + chars!(..).par_iter().collect::<Vec<_>>() + ) + } +} diff --git a/vendor/unic-char-range/src/pkg_info.rs b/vendor/unic-char-range/src/pkg_info.rs new file mode 100644 index 0000000000..a1ab2853fd --- /dev/null +++ b/vendor/unic-char-range/src/pkg_info.rs @@ -0,0 +1,20 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Package information + +/// UNIC component version. +pub const PKG_VERSION: &str = env!("CARGO_PKG_VERSION"); + +/// UNIC component name. +pub const PKG_NAME: &str = env!("CARGO_PKG_NAME"); + +/// UNIC component description. +pub const PKG_DESCRIPTION: &str = env!("CARGO_PKG_DESCRIPTION"); diff --git a/vendor/unic-char-range/src/range.rs b/vendor/unic-char-range/src/range.rs new file mode 100644 index 0000000000..d958016fc5 --- /dev/null +++ b/vendor/unic-char-range/src/range.rs @@ -0,0 +1,231 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::{char, cmp}; + +#[cfg(feature = "std")] +use std::collections::Bound; + +use self::cmp::Ordering; +use crate::CharIter; + +/// A range of unicode code points. +/// +/// The most idiomatic way to construct this range is through the use of the `chars!` macro: +/// +/// ``` +/// #[macro_use] extern crate unic_char_range; +/// use unic_char_range::CharRange; +/// +/// # fn main() { +/// assert_eq!(chars!('a'..='z'), CharRange::closed('a', 'z')); +/// assert_eq!(chars!('a'..'z'), CharRange::open_right('a', 'z')); +/// assert_eq!(chars!(..), CharRange::all()); +/// # } +/// ``` +/// +/// If constructed in reverse order, such that `self.high` is ordered before `self.low`, +/// the range is empty. If you want to iterate in decreasing order, use `.iter().rev()`. +/// All empty ranges are considered equal no matter the internal state. +#[derive(Copy, Clone, Debug, Eq)] +pub struct CharRange { + /// The lowest character in this range (inclusive). + pub low: char, + + /// The highest character in this range (inclusive). + pub high: char, +} + +/// Constructors +impl CharRange { + /// Construct a closed range of characters. + /// + /// If `stop` is ordered before `start`, the resulting range will be empty. + /// + /// # Example + /// + /// ``` + /// # use unic_char_range::*; + /// assert_eq!( + /// CharRange::closed('a', 'd').iter().collect::<Vec<_>>(), + /// vec!['a', 'b', 'c', 'd'] + /// ) + /// ``` + pub fn closed(start: char, stop: char) -> CharRange { + CharRange { + low: start, + high: stop, + } + } + + /// Construct a half open (right) range of characters. + /// + /// # Example + /// + /// ``` + /// # use unic_char_range::*; + /// assert_eq!( + /// CharRange::open_right('a', 'd').iter().collect::<Vec<_>>(), + /// vec!['a', 'b', 'c'] + /// ) + /// ``` + pub fn open_right(start: char, stop: char) -> CharRange { + let mut iter = CharRange::closed(start, stop).iter(); + let _ = iter.next_back(); + iter.into() + } + + /// Construct a half open (left) range of characters. + /// + /// # Example + /// + /// ``` + /// # use unic_char_range::*; + /// assert_eq!( + /// CharRange::open_left('a', 'd').iter().collect::<Vec<_>>(), + /// vec!['b', 'c', 'd'] + /// ) + /// ``` + pub fn open_left(start: char, stop: char) -> CharRange { + let mut iter = CharRange::closed(start, stop).iter(); + let _ = iter.next(); + iter.into() + } + + /// Construct a fully open range of characters. + /// + /// # Example + /// + /// ``` + /// # use unic_char_range::*; + /// assert_eq!( + /// CharRange::open('a', 'd').iter().collect::<Vec<_>>(), + /// vec!['b', 'c'] + /// ) + /// ``` + pub fn open(start: char, stop: char) -> CharRange { + let mut iter = CharRange::closed(start, stop).iter(); + let _ = iter.next(); + let _ = iter.next_back(); + iter.into() + } + + #[cfg(feature = "std")] + /// Construct a range of characters from bounds. + pub fn bound(start: Bound<char>, stop: Bound<char>) -> CharRange { + let start = if start == Bound::Unbounded { + Bound::Included('\u{0}') + } else { + start + }; + let stop = if stop == Bound::Unbounded { + Bound::Included(char::MAX) + } else { + stop + }; + match (start, stop) { + (Bound::Included(start), Bound::Included(stop)) => CharRange::closed(start, stop), + (Bound::Excluded(start), Bound::Excluded(stop)) => CharRange::open(start, stop), + (Bound::Included(start), Bound::Excluded(stop)) => CharRange::open_right(start, stop), + (Bound::Excluded(start), Bound::Included(stop)) => CharRange::open_left(start, stop), + (Bound::Unbounded, _) | (_, Bound::Unbounded) => unreachable!(), + } + } + + /// Construct a range over all Unicode characters (Unicode Scalar Values). + pub fn all() -> CharRange { + CharRange::closed('\u{0}', char::MAX) + } + + /// Construct a range over all characters of *assigned* Unicode Planes. + /// + /// Assigned *normal* (non-special) Unicode Planes are: + /// - Plane 0: *Basic Multilingual Plane* (BMP) + /// - Plane 1: *Supplementary Multilingual Plane* (SMP) + /// - Plane 2: *Supplementary Ideographic Plane* (SIP) + /// + /// Unicode Plane 14, *Supplementary Special-purpose Plane* (SSP), is not included in this + /// range, mainly because of the limit of `CharRange` only supporting a continuous range. + /// + /// Unicode Planes 3 to 13 are *Unassigned* planes and therefore excluded. + /// + /// Unicode Planes 15 and 16 are *Private Use Area* planes and won't have Unicode-assigned + /// characters. + pub fn assigned_normal_planes() -> CharRange { + CharRange::closed('\u{0}', '\u{2_FFFF}') + } +} + +/// Collection-like fns +impl CharRange { + /// Does this range include a character? + /// + /// # Examples + /// + /// ``` + /// # use unic_char_range::CharRange; + /// assert!( CharRange::closed('a', 'g').contains('d')); + /// assert!( ! CharRange::closed('a', 'g').contains('z')); + /// + /// assert!( ! CharRange:: open ('a', 'a').contains('a')); + /// assert!( ! CharRange::closed('z', 'a').contains('g')); + /// ``` + pub fn contains(&self, ch: char) -> bool { + self.low <= ch && ch <= self.high + } + + /// Determine the ordering of this range and a character. + /// + /// # Panics + /// + /// Panics if the range is empty. This fn may be adjusted in the future to not panic + /// in optimized builds. Even if so, an empty range will never compare as `Ordering::Equal`. + pub fn cmp_char(&self, ch: char) -> Ordering { + // possible optimization: only assert this in debug builds + assert!(!self.is_empty(), "Cannot compare empty range's ordering"); + if self.high < ch { + Ordering::Less + } else if self.low > ch { + Ordering::Greater + } else { + Ordering::Equal + } + } + + /// How many characters are in this range? + pub fn len(&self) -> usize { + self.iter().len() + } + + /// Is this range empty? + pub fn is_empty(&self) -> bool { + self.low > self.high + } + + /// Create an iterator over this range. + pub fn iter(&self) -> CharIter { + (*self).into() + } +} + +impl IntoIterator for CharRange { + type IntoIter = CharIter; + type Item = char; + + fn into_iter(self) -> CharIter { + self.iter() + } +} + +impl PartialEq<CharRange> for CharRange { + fn eq(&self, other: &CharRange) -> bool { + (self.is_empty() && other.is_empty()) || (self.low == other.low && self.high == other.high) + } +} diff --git a/vendor/unic-char-range/src/step.rs b/vendor/unic-char-range/src/step.rs new file mode 100644 index 0000000000..1140edd9e8 --- /dev/null +++ b/vendor/unic-char-range/src/step.rs @@ -0,0 +1,45 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::char; + +pub const BEFORE_SURROGATE: char = '\u{D7FF}'; +pub const AFTER_SURROGATE: char = '\u{E000}'; + +#[inline] +#[allow(unsafe_code)] +/// Step a character one step towards `char::MAX`. +/// +/// # Safety +/// +/// If the given character is `char::MAX`, the return value is not a valid character. +pub unsafe fn forward(ch: char) -> char { + if ch == BEFORE_SURROGATE { + AFTER_SURROGATE + } else { + char::from_u32_unchecked(ch as u32 + 1) + } +} + +#[inline] +#[allow(unsafe_code)] +/// Step a character one step towards `'\0'`. +/// +/// # Safety +/// +/// If the given character is `'\0'`, this will cause an underflow. +/// (Thus, it will panic in debug mode, undefined behavior in release mode.) +pub unsafe fn backward(ch: char) -> char { + if ch == AFTER_SURROGATE { + BEFORE_SURROGATE + } else { + char::from_u32_unchecked(ch as u32 - 1) + } +} diff --git a/vendor/unic-char-range/tests/iter_tests.rs b/vendor/unic-char-range/tests/iter_tests.rs new file mode 100644 index 0000000000..9678009a94 --- /dev/null +++ b/vendor/unic-char-range/tests/iter_tests.rs @@ -0,0 +1,78 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::{char, u32, vec}; + +use unic_char_range::CharRange; + +fn all_chars() -> vec::IntoIter<char> { + (u32::MIN..u32::MAX) + .take_while(|&u| u <= char::MAX as u32) + .filter_map(char::from_u32) + .collect::<Vec<_>>() + .into_iter() +} + +#[test] +fn test_iter_all_chars() { + assert!(CharRange::all().iter().eq(all_chars())) +} + +#[test] +fn test_iter_all_chars_rev() { + assert!(CharRange::all().iter().rev().eq(all_chars().rev())) +} + +#[test] +fn test_iter_all_chars_mixed_next_back() { + let mut custom = CharRange::all().iter(); + let mut simple = all_chars(); + while let Some(custom_char) = custom.next() { + assert_eq!(Some(custom_char), simple.next()); + assert_eq!(custom.next_back(), simple.next_back()); + } + assert_eq!(None, simple.next()); +} + +#[test] +fn test_iter_all_chars_into_iter() { + for _ch in CharRange::all() { + // nothing + } +} + +#[test] +fn test_iter_fused() { + let mut iter = CharRange::all().iter(); + let mut fused = all_chars().fuse(); + assert!(iter.by_ref().eq(fused.by_ref())); + for _ in 0..100 { + assert_eq!(iter.next(), fused.next()); + } +} + +#[test] +fn test_iter_exact_trusted_len() { + fn assert_presents_right_len<I: ExactSizeIterator>(iter: &I, len: usize) { + assert_eq!(iter.len(), len); + assert_eq!(iter.size_hint(), (len, Some(len))); + } + + let mut iter = CharRange::all().iter(); + let mut predicted_length = iter.len(); + assert_eq!(predicted_length, all_chars().len()); + + while let Some(_) = iter.next() { + predicted_length -= 1; + assert_presents_right_len(&iter, predicted_length); + } + + assert_presents_right_len(&iter, 0); +} diff --git a/vendor/unic-common/.cargo-checksum.json b/vendor/unic-common/.cargo-checksum.json new file mode 100644 index 0000000000..c218ae248d --- /dev/null +++ b/vendor/unic-common/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"719fc6cbaa72559247169192a041fc1c4dfcec442987b204a7237e22836bbb14","README.md":"54c3f5551f27720e50315ba3ed76b2bf47db4692de1e6bdc12434022971b5ee3","src/lib.rs":"726d922245ebdf3bc474d48edf032b9af7fe24fc79ee17d87e2d295103e39ea0","src/pkg_info.rs":"37cbe4efd0b0205d251e1ef7714b23e3be27052c8a0de6b1ae3cbf3aefae1fe5","src/version.rs":"ee5f50444acc2df5f9cd4ec97bd81444c6425b55fd37327c254ccd1736270898"},"package":"80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc"} \ No newline at end of file diff --git a/vendor/unic-common/Cargo.toml b/vendor/unic-common/Cargo.toml new file mode 100644 index 0000000000..41f1abd74f --- /dev/null +++ b/vendor/unic-common/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 = "unic-common" +version = "0.9.0" +authors = ["The UNIC Project Developers"] +exclude = [] +description = "UNIC — Common Utilities" +keywords = ["unicode", "version"] +categories = ["internationalization", "text-processing"] +license = "MIT/Apache-2.0" +repository = "https://github.com/open-i18n/rust-unic/" + +[features] +default = [] +unstable = [] +[badges.appveyor] +branch = "master" +repository = "open-i18n/rust-unic" +service = "github" + +[badges.is-it-maintained-issue-resolution] +repository = "open-i18n/rust-unic" + +[badges.is-it-maintained-open-issues] +repository = "open-i18n/rust-unic" + +[badges.maintenance] +status = "actively-developed" + +[badges.travis-ci] +branch = "master" +repository = "open-i18n/rust-unic" diff --git a/vendor/unic-common/README.md b/vendor/unic-common/README.md new file mode 100644 index 0000000000..9d86d22915 --- /dev/null +++ b/vendor/unic-common/README.md @@ -0,0 +1,7 @@ +# UNIC — Common Utilities + +[![Crates.io](https://img.shields.io/crates/v/unic-common.svg)](https://crates.io/crates/unic-common) +[![Documentation](https://docs.rs/unic-common/badge.svg)](https://docs.rs/unic-common/) + +This UNIC component provides common types, algorithms and macros not shared +between many components. diff --git a/vendor/unic-common/src/lib.rs b/vendor/unic-common/src/lib.rs new file mode 100644 index 0000000000..0ce4f213e9 --- /dev/null +++ b/vendor/unic-common/src/lib.rs @@ -0,0 +1,31 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![no_std] +#![warn( + bad_style, + missing_debug_implementations, + missing_docs, + unconditional_recursion +)] +#![forbid(unsafe_code)] +#![cfg_attr(feature = "unstable", feature(unicode_version))] + +//! # UNIC — Common Utilities +//! +//! A component of [`unic`: Unicode and Internationalization Crates for Rust](/unic/). +//! +//! This UNIC component provides common types, algorithms and macros not shared between many +//! components. + +mod pkg_info; +pub use crate::pkg_info::{PKG_DESCRIPTION, PKG_NAME, PKG_VERSION}; + +pub mod version; diff --git a/vendor/unic-common/src/pkg_info.rs b/vendor/unic-common/src/pkg_info.rs new file mode 100644 index 0000000000..a1ab2853fd --- /dev/null +++ b/vendor/unic-common/src/pkg_info.rs @@ -0,0 +1,20 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Package information + +/// UNIC component version. +pub const PKG_VERSION: &str = env!("CARGO_PKG_VERSION"); + +/// UNIC component name. +pub const PKG_NAME: &str = env!("CARGO_PKG_NAME"); + +/// UNIC component description. +pub const PKG_DESCRIPTION: &str = env!("CARGO_PKG_DESCRIPTION"); diff --git a/vendor/unic-common/src/version.rs b/vendor/unic-common/src/version.rs new file mode 100644 index 0000000000..6faf7def0e --- /dev/null +++ b/vendor/unic-common/src/version.rs @@ -0,0 +1,72 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! *Version* data types. + +use core::fmt; + +#[cfg(feature = "unstable")] +use core::char; + +/// Represents a *Unicode Version* type. +/// +/// UNIC's *Unicode Version* type is used for Unicode datasets and specifications, including The +/// Unicode Standard (TUS), Unicode Character Database (UCD), Common Local Data Repository (CLDR), +/// IDNA, Emoji, etc. +/// +/// TODO: *Unicode Version* is guaranteed to have three integer fields between 0 and 255. We are +/// going to switch over to `u8` after Unicode 11.0.0 release. +/// +/// Refs: +/// - <https://www.unicode.org/versions/> +/// - <https://www.unicode.org/L2/L2017/17222.htm#152-C3> +#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Default)] +pub struct UnicodeVersion { + /// Major version. + pub major: u16, + + /// Minor version. + pub minor: u16, + + /// Micro (or Update) version. + pub micro: u16, +} + +impl fmt::Display for UnicodeVersion { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}.{}.{}", self.major, self.minor, self.micro) + } +} + +#[cfg(feature = "unstable")] +/// Convert from Rust's internal Unicode Version. +impl From<char::UnicodeVersion> for UnicodeVersion { + fn from(value: char::UnicodeVersion) -> UnicodeVersion { + UnicodeVersion { + major: value.major as u16, + minor: value.minor as u16, + micro: value.micro as u16, + } + } +} + +#[cfg(test)] +mod tests { + #[cfg(feature = "unstable")] + #[test] + fn test_against_rust_internal() { + use core::char; + + use super::UnicodeVersion; + + let core_unicode_version: UnicodeVersion = char::UNICODE_VERSION.into(); + assert!(core_unicode_version.major >= 10); + } +} diff --git a/vendor/unic-emoji-char/.cargo-checksum.json b/vendor/unic-emoji-char/.cargo-checksum.json new file mode 100644 index 0000000000..e5e00e2818 --- /dev/null +++ b/vendor/unic-emoji-char/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"a00c0a6a58a2e0a8d7c4d83d627592788e0994e3277c2f623d21b8509af36cad","src/emoji.rs":"59d4963c363e90d994e587e9db843943406cea4ee009ac1cc5cac5e1d3d67547","src/emoji_component.rs":"40ffc89f4c67b761d16daa6fda31ec149e9bcd9f29f50d115d62b903b5a38054","src/emoji_modifier.rs":"353314425f17fca26f3c8997f07e694cbd52868b3adc348d3b43f18f1d8b3079","src/emoji_modifier_base.rs":"c34ffe1f4bf8a6e97890f9b4f1365e25c6cb91a49e8fff3d3ba105044fb0b127","src/emoji_presentation.rs":"5a23c04dbaa699b2c8bbdb1cb072ffb0682624821075de28bc427c737e9e0218","src/emoji_version.rs":"99f3d457b6eae2309ddb161f62fe74beec097fff882bb10ed3824ab82890ae95","src/lib.rs":"cfbb4c81b3f7f6de962c508bb227064e0a9136b12d66e65846d65ab3eb117bd8","src/pkg_info.rs":"37cbe4efd0b0205d251e1ef7714b23e3be27052c8a0de6b1ae3cbf3aefae1fe5","tables/emoji.rsv":"0fba40642fd7d1e81f83cae136540066c79e6d5f1a3f1b3a6add60945787e93d","tables/emoji_component.rsv":"15f692af62d6494185dace932ba4b630a9bb2e7a91a40fbd67a379ebc47767bc","tables/emoji_modifier.rsv":"c483a783ff9a6b2a4e7545e405dc33b1ea48670ae3ae835eb0a840b11f25950d","tables/emoji_modifier_base.rsv":"ca4d5da63706e43ec407923474dec5da1e278dc6f558419c909d2978cb8cf4a9","tables/emoji_presentation.rsv":"6b7a54c0d193b6bb0acab2f0ac1af6db65736db1d2e952cf4a31bb72fc271dfb","tables/emoji_version.rsv":"770dc11d51a76b2868244ff2a3de9718b5f14479c9e14944e978da890752c485","tests/emoji_version_tests.rs":"0c27fbc81dc4ad0804ae47558664ae77cf9ba073cf50eca978ebd7c9f05cdaf4"},"package":"0b07221e68897210270a38bde4babb655869637af0f69407f96053a34f76494d"} \ No newline at end of file diff --git a/vendor/unic-emoji-char/Cargo.toml b/vendor/unic-emoji-char/Cargo.toml new file mode 100644 index 0000000000..e108128d9b --- /dev/null +++ b/vendor/unic-emoji-char/Cargo.toml @@ -0,0 +1,48 @@ +# 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 = "unic-emoji-char" +version = "0.9.0" +authors = ["The UNIC Project Developers"] +exclude = [] +description = "UNIC — Unicode Emoji — Emoji Character Properties" +keywords = ["text", "unicode", "character-property", "emoji"] +categories = ["internationalization", "text-processing", "parsing", "rendering"] +license = "MIT/Apache-2.0" +repository = "https://github.com/open-i18n/rust-unic/" +[dependencies.unic-char-property] +version = "0.9.0" + +[dependencies.unic-char-range] +version = "0.9.0" + +[dependencies.unic-ucd-version] +version = "0.9.0" +[badges.appveyor] +branch = "master" +repository = "open-i18n/rust-unic" +service = "github" + +[badges.is-it-maintained-issue-resolution] +repository = "open-i18n/rust-unic" + +[badges.is-it-maintained-open-issues] +repository = "open-i18n/rust-unic" + +[badges.maintenance] +status = "actively-developed" + +[badges.travis-ci] +branch = "master" +repository = "open-i18n/rust-unic" diff --git a/vendor/unic-emoji-char/src/emoji.rs b/vendor/unic-emoji-char/src/emoji.rs new file mode 100644 index 0000000000..1e5388bcf4 --- /dev/null +++ b/vendor/unic-emoji-char/src/emoji.rs @@ -0,0 +1,106 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Unicode `Emoji` Character Property. + +char_property! { + /// Represents values of the Unicode character property + /// [`Emoji`](https://www.unicode.org/reports/tr51/#Emoji_Properties). + /// + /// The value is `true` for characters that are emoji. + pub struct Emoji(bool) { + abbr => "Emoji"; + long => "Emoji"; + human => "Emoji"; + + data_table_path => "../tables/emoji.rsv"; + } + + /// The value is `true` for characters that are emoji. + pub fn is_emoji(char) -> bool; +} + +#[cfg(test)] +mod tests { + #[test] + fn test_values() { + use super::is_emoji; + + // ASCII + assert_eq!(is_emoji('\u{0000}'), false); + assert_eq!(is_emoji('\u{0021}'), false); + + assert_eq!(is_emoji('\u{0027}'), false); + assert_eq!(is_emoji('\u{0028}'), false); + assert_eq!(is_emoji('\u{0029}'), false); + assert_eq!(is_emoji('\u{002a}'), true); + + assert_eq!(is_emoji('\u{003b}'), false); + assert_eq!(is_emoji('\u{003c}'), false); + assert_eq!(is_emoji('\u{003d}'), false); + + assert_eq!(is_emoji('\u{007a}'), false); + assert_eq!(is_emoji('\u{007b}'), false); + assert_eq!(is_emoji('\u{007c}'), false); + assert_eq!(is_emoji('\u{007d}'), false); + assert_eq!(is_emoji('\u{007e}'), false); + + // Other BMP + assert_eq!(is_emoji('\u{061b}'), false); + assert_eq!(is_emoji('\u{061c}'), false); + assert_eq!(is_emoji('\u{061d}'), false); + + assert_eq!(is_emoji('\u{200d}'), false); + assert_eq!(is_emoji('\u{200e}'), false); + assert_eq!(is_emoji('\u{200f}'), false); + assert_eq!(is_emoji('\u{2010}'), false); + + assert_eq!(is_emoji('\u{2029}'), false); + assert_eq!(is_emoji('\u{202a}'), false); + assert_eq!(is_emoji('\u{202e}'), false); + assert_eq!(is_emoji('\u{202f}'), false); + + // Other Planes + assert_eq!(is_emoji('\u{10000}'), false); + assert_eq!(is_emoji('\u{10001}'), false); + + assert_eq!(is_emoji('\u{1f1e5}'), false); + assert_eq!(is_emoji('\u{1f1e6}'), true); + assert_eq!(is_emoji('\u{1f1ff}'), true); + assert_eq!(is_emoji('\u{1f200}'), false); + + assert_eq!(is_emoji('\u{20000}'), false); + assert_eq!(is_emoji('\u{30000}'), false); + assert_eq!(is_emoji('\u{40000}'), false); + assert_eq!(is_emoji('\u{50000}'), false); + assert_eq!(is_emoji('\u{60000}'), false); + assert_eq!(is_emoji('\u{70000}'), false); + assert_eq!(is_emoji('\u{80000}'), false); + assert_eq!(is_emoji('\u{90000}'), false); + assert_eq!(is_emoji('\u{a0000}'), false); + assert_eq!(is_emoji('\u{b0000}'), false); + assert_eq!(is_emoji('\u{c0000}'), false); + assert_eq!(is_emoji('\u{d0000}'), false); + assert_eq!(is_emoji('\u{e0000}'), false); + + assert_eq!(is_emoji('\u{efffe}'), false); + assert_eq!(is_emoji('\u{effff}'), false); + + // Priavte-Use Area + assert_eq!(is_emoji('\u{f0000}'), false); + assert_eq!(is_emoji('\u{f0001}'), false); + assert_eq!(is_emoji('\u{ffffe}'), false); + assert_eq!(is_emoji('\u{fffff}'), false); + assert_eq!(is_emoji('\u{100000}'), false); + assert_eq!(is_emoji('\u{100001}'), false); + assert_eq!(is_emoji('\u{10fffe}'), false); + assert_eq!(is_emoji('\u{10ffff}'), false); + } +} diff --git a/vendor/unic-emoji-char/src/emoji_component.rs b/vendor/unic-emoji-char/src/emoji_component.rs new file mode 100644 index 0000000000..eb629d3990 --- /dev/null +++ b/vendor/unic-emoji-char/src/emoji_component.rs @@ -0,0 +1,108 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Unicode `Emoji_Component` Character Property. + +char_property! { + /// Represents values of the Unicode character property + /// [`Emoji_Component`](https://www.unicode.org/reports/tr51/#Emoji_Properties). + /// + /// The value is `true` for characters that normally do not appear on emoji keyboards as + /// separate choices, such as Keycap base characters, Regional_Indicators, …, `false` otherwise. + pub struct EmojiComponent(bool) { + abbr => "Emoji_Component"; + long => "Emoji_Component"; + human => "Emoji Component"; + + data_table_path => "../tables/emoji_component.rsv"; + } + + /// The value is `true` for characters that normally do not appear on emoji keyboards as + /// separate choices, such as Keycap base characters, Regional_Indicators, …, `false` otherwise. + pub fn is_emoji_component(char) -> bool; +} + +#[cfg(test)] +mod tests { + #[test] + fn test_values() { + use super::is_emoji_component; + + // ASCII + assert_eq!(is_emoji_component('\u{0000}'), false); + assert_eq!(is_emoji_component('\u{0021}'), false); + + assert_eq!(is_emoji_component('\u{0027}'), false); + assert_eq!(is_emoji_component('\u{0028}'), false); + assert_eq!(is_emoji_component('\u{0029}'), false); + assert_eq!(is_emoji_component('\u{002a}'), true); + + assert_eq!(is_emoji_component('\u{003b}'), false); + assert_eq!(is_emoji_component('\u{003c}'), false); + assert_eq!(is_emoji_component('\u{003d}'), false); + + assert_eq!(is_emoji_component('\u{007a}'), false); + assert_eq!(is_emoji_component('\u{007b}'), false); + assert_eq!(is_emoji_component('\u{007c}'), false); + assert_eq!(is_emoji_component('\u{007d}'), false); + assert_eq!(is_emoji_component('\u{007e}'), false); + + // Other BMP + assert_eq!(is_emoji_component('\u{061b}'), false); + assert_eq!(is_emoji_component('\u{061c}'), false); + assert_eq!(is_emoji_component('\u{061d}'), false); + + assert_eq!(is_emoji_component('\u{200d}'), false); + assert_eq!(is_emoji_component('\u{200e}'), false); + assert_eq!(is_emoji_component('\u{200f}'), false); + assert_eq!(is_emoji_component('\u{2010}'), false); + + assert_eq!(is_emoji_component('\u{2029}'), false); + assert_eq!(is_emoji_component('\u{202a}'), false); + assert_eq!(is_emoji_component('\u{202e}'), false); + assert_eq!(is_emoji_component('\u{202f}'), false); + + // Other Planes + assert_eq!(is_emoji_component('\u{10000}'), false); + assert_eq!(is_emoji_component('\u{10001}'), false); + + assert_eq!(is_emoji_component('\u{1f1e5}'), false); + assert_eq!(is_emoji_component('\u{1f1e6}'), true); + assert_eq!(is_emoji_component('\u{1f1ff}'), true); + assert_eq!(is_emoji_component('\u{1f200}'), false); + + assert_eq!(is_emoji_component('\u{20000}'), false); + assert_eq!(is_emoji_component('\u{30000}'), false); + assert_eq!(is_emoji_component('\u{40000}'), false); + assert_eq!(is_emoji_component('\u{50000}'), false); + assert_eq!(is_emoji_component('\u{60000}'), false); + assert_eq!(is_emoji_component('\u{70000}'), false); + assert_eq!(is_emoji_component('\u{80000}'), false); + assert_eq!(is_emoji_component('\u{90000}'), false); + assert_eq!(is_emoji_component('\u{a0000}'), false); + assert_eq!(is_emoji_component('\u{b0000}'), false); + assert_eq!(is_emoji_component('\u{c0000}'), false); + assert_eq!(is_emoji_component('\u{d0000}'), false); + assert_eq!(is_emoji_component('\u{e0000}'), false); + + assert_eq!(is_emoji_component('\u{efffe}'), false); + assert_eq!(is_emoji_component('\u{effff}'), false); + + // Priavte-Use Area + assert_eq!(is_emoji_component('\u{f0000}'), false); + assert_eq!(is_emoji_component('\u{f0001}'), false); + assert_eq!(is_emoji_component('\u{ffffe}'), false); + assert_eq!(is_emoji_component('\u{fffff}'), false); + assert_eq!(is_emoji_component('\u{100000}'), false); + assert_eq!(is_emoji_component('\u{100001}'), false); + assert_eq!(is_emoji_component('\u{10fffe}'), false); + assert_eq!(is_emoji_component('\u{10ffff}'), false); + } +} diff --git a/vendor/unic-emoji-char/src/emoji_modifier.rs b/vendor/unic-emoji-char/src/emoji_modifier.rs new file mode 100644 index 0000000000..863370ab18 --- /dev/null +++ b/vendor/unic-emoji-char/src/emoji_modifier.rs @@ -0,0 +1,106 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Unicode `Emoji_Modifier` Character Property. + +char_property! { + /// Represents values of the Unicode character property + /// [`Emoji_Modifier`](https://www.unicode.org/reports/tr51/#Emoji_Properties). + /// + /// The value is `true` for characters that have emoji presentation by default. + pub struct EmojiModifier(bool) { + abbr => "Emoji_Modifier"; + long => "Emoji_Modifier"; + human => "Emoji Modifier"; + + data_table_path => "../tables/emoji_modifier.rsv"; + } + + /// The value is `true` for characters that have emoji presentation by default. + pub fn is_emoji_modifier(char) -> bool; +} + +#[cfg(test)] +mod tests { + #[test] + fn test_values() { + use super::is_emoji_modifier; + + // ASCII + assert_eq!(is_emoji_modifier('\u{0000}'), false); + assert_eq!(is_emoji_modifier('\u{0021}'), false); + + assert_eq!(is_emoji_modifier('\u{0027}'), false); + assert_eq!(is_emoji_modifier('\u{0028}'), false); + assert_eq!(is_emoji_modifier('\u{0029}'), false); + assert_eq!(is_emoji_modifier('\u{002a}'), false); + + assert_eq!(is_emoji_modifier('\u{003b}'), false); + assert_eq!(is_emoji_modifier('\u{003c}'), false); + assert_eq!(is_emoji_modifier('\u{003d}'), false); + + assert_eq!(is_emoji_modifier('\u{007a}'), false); + assert_eq!(is_emoji_modifier('\u{007b}'), false); + assert_eq!(is_emoji_modifier('\u{007c}'), false); + assert_eq!(is_emoji_modifier('\u{007d}'), false); + assert_eq!(is_emoji_modifier('\u{007e}'), false); + + // Other BMP + assert_eq!(is_emoji_modifier('\u{061b}'), false); + assert_eq!(is_emoji_modifier('\u{061c}'), false); + assert_eq!(is_emoji_modifier('\u{061d}'), false); + + assert_eq!(is_emoji_modifier('\u{200d}'), false); + assert_eq!(is_emoji_modifier('\u{200e}'), false); + assert_eq!(is_emoji_modifier('\u{200f}'), false); + assert_eq!(is_emoji_modifier('\u{2010}'), false); + + assert_eq!(is_emoji_modifier('\u{2029}'), false); + assert_eq!(is_emoji_modifier('\u{202a}'), false); + assert_eq!(is_emoji_modifier('\u{202e}'), false); + assert_eq!(is_emoji_modifier('\u{202f}'), false); + + // Other Planes + assert_eq!(is_emoji_modifier('\u{10000}'), false); + assert_eq!(is_emoji_modifier('\u{10001}'), false); + + assert_eq!(is_emoji_modifier('\u{1f1e5}'), false); + assert_eq!(is_emoji_modifier('\u{1f1e6}'), false); + assert_eq!(is_emoji_modifier('\u{1f1ff}'), false); + assert_eq!(is_emoji_modifier('\u{1f200}'), false); + + assert_eq!(is_emoji_modifier('\u{20000}'), false); + assert_eq!(is_emoji_modifier('\u{30000}'), false); + assert_eq!(is_emoji_modifier('\u{40000}'), false); + assert_eq!(is_emoji_modifier('\u{50000}'), false); + assert_eq!(is_emoji_modifier('\u{60000}'), false); + assert_eq!(is_emoji_modifier('\u{70000}'), false); + assert_eq!(is_emoji_modifier('\u{80000}'), false); + assert_eq!(is_emoji_modifier('\u{90000}'), false); + assert_eq!(is_emoji_modifier('\u{a0000}'), false); + assert_eq!(is_emoji_modifier('\u{b0000}'), false); + assert_eq!(is_emoji_modifier('\u{c0000}'), false); + assert_eq!(is_emoji_modifier('\u{d0000}'), false); + assert_eq!(is_emoji_modifier('\u{e0000}'), false); + + assert_eq!(is_emoji_modifier('\u{efffe}'), false); + assert_eq!(is_emoji_modifier('\u{effff}'), false); + + // Priavte-Use Area + assert_eq!(is_emoji_modifier('\u{f0000}'), false); + assert_eq!(is_emoji_modifier('\u{f0001}'), false); + assert_eq!(is_emoji_modifier('\u{ffffe}'), false); + assert_eq!(is_emoji_modifier('\u{fffff}'), false); + assert_eq!(is_emoji_modifier('\u{100000}'), false); + assert_eq!(is_emoji_modifier('\u{100001}'), false); + assert_eq!(is_emoji_modifier('\u{10fffe}'), false); + assert_eq!(is_emoji_modifier('\u{10ffff}'), false); + } +} diff --git a/vendor/unic-emoji-char/src/emoji_modifier_base.rs b/vendor/unic-emoji-char/src/emoji_modifier_base.rs new file mode 100644 index 0000000000..c903914ff6 --- /dev/null +++ b/vendor/unic-emoji-char/src/emoji_modifier_base.rs @@ -0,0 +1,106 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Unicode `Emoji_Modifier_Base` Character Property. + +char_property! { + /// Represents values of the Unicode character property + /// [`Emoji_Modifier_Base`](https://www.unicode.org/reports/tr51/#Emoji_Properties). + /// + /// The value is `true` for characters that are emoji modifiers. + pub struct EmojiModifierBase(bool) { + abbr => "Emoji_Modifier_Base"; + long => "Emoji_Modifier_Base"; + human => "Emoji Modifier Base"; + + data_table_path => "../tables/emoji_modifier_base.rsv"; + } + + /// The value is `true` for characters that are emoji modifiers. + pub fn is_emoji_modifier_base(char) -> bool; +} + +#[cfg(test)] +mod tests { + #[test] + fn test_values() { + use super::is_emoji_modifier_base; + + // ASCII + assert_eq!(is_emoji_modifier_base('\u{0000}'), false); + assert_eq!(is_emoji_modifier_base('\u{0021}'), false); + + assert_eq!(is_emoji_modifier_base('\u{0027}'), false); + assert_eq!(is_emoji_modifier_base('\u{0028}'), false); + assert_eq!(is_emoji_modifier_base('\u{0029}'), false); + assert_eq!(is_emoji_modifier_base('\u{002a}'), false); + + assert_eq!(is_emoji_modifier_base('\u{003b}'), false); + assert_eq!(is_emoji_modifier_base('\u{003c}'), false); + assert_eq!(is_emoji_modifier_base('\u{003d}'), false); + + assert_eq!(is_emoji_modifier_base('\u{007a}'), false); + assert_eq!(is_emoji_modifier_base('\u{007b}'), false); + assert_eq!(is_emoji_modifier_base('\u{007c}'), false); + assert_eq!(is_emoji_modifier_base('\u{007d}'), false); + assert_eq!(is_emoji_modifier_base('\u{007e}'), false); + + // Other BMP + assert_eq!(is_emoji_modifier_base('\u{061b}'), false); + assert_eq!(is_emoji_modifier_base('\u{061c}'), false); + assert_eq!(is_emoji_modifier_base('\u{061d}'), false); + + assert_eq!(is_emoji_modifier_base('\u{200d}'), false); + assert_eq!(is_emoji_modifier_base('\u{200e}'), false); + assert_eq!(is_emoji_modifier_base('\u{200f}'), false); + assert_eq!(is_emoji_modifier_base('\u{2010}'), false); + + assert_eq!(is_emoji_modifier_base('\u{2029}'), false); + assert_eq!(is_emoji_modifier_base('\u{202a}'), false); + assert_eq!(is_emoji_modifier_base('\u{202e}'), false); + assert_eq!(is_emoji_modifier_base('\u{202f}'), false); + + // Other Planes + assert_eq!(is_emoji_modifier_base('\u{10000}'), false); + assert_eq!(is_emoji_modifier_base('\u{10001}'), false); + + assert_eq!(is_emoji_modifier_base('\u{1f1e5}'), false); + assert_eq!(is_emoji_modifier_base('\u{1f1e6}'), false); + assert_eq!(is_emoji_modifier_base('\u{1f1ff}'), false); + assert_eq!(is_emoji_modifier_base('\u{1f200}'), false); + + assert_eq!(is_emoji_modifier_base('\u{20000}'), false); + assert_eq!(is_emoji_modifier_base('\u{30000}'), false); + assert_eq!(is_emoji_modifier_base('\u{40000}'), false); + assert_eq!(is_emoji_modifier_base('\u{50000}'), false); + assert_eq!(is_emoji_modifier_base('\u{60000}'), false); + assert_eq!(is_emoji_modifier_base('\u{70000}'), false); + assert_eq!(is_emoji_modifier_base('\u{80000}'), false); + assert_eq!(is_emoji_modifier_base('\u{90000}'), false); + assert_eq!(is_emoji_modifier_base('\u{a0000}'), false); + assert_eq!(is_emoji_modifier_base('\u{b0000}'), false); + assert_eq!(is_emoji_modifier_base('\u{c0000}'), false); + assert_eq!(is_emoji_modifier_base('\u{d0000}'), false); + assert_eq!(is_emoji_modifier_base('\u{e0000}'), false); + + assert_eq!(is_emoji_modifier_base('\u{efffe}'), false); + assert_eq!(is_emoji_modifier_base('\u{effff}'), false); + + // Priavte-Use Area + assert_eq!(is_emoji_modifier_base('\u{f0000}'), false); + assert_eq!(is_emoji_modifier_base('\u{f0001}'), false); + assert_eq!(is_emoji_modifier_base('\u{ffffe}'), false); + assert_eq!(is_emoji_modifier_base('\u{fffff}'), false); + assert_eq!(is_emoji_modifier_base('\u{100000}'), false); + assert_eq!(is_emoji_modifier_base('\u{100001}'), false); + assert_eq!(is_emoji_modifier_base('\u{10fffe}'), false); + assert_eq!(is_emoji_modifier_base('\u{10ffff}'), false); + } +} diff --git a/vendor/unic-emoji-char/src/emoji_presentation.rs b/vendor/unic-emoji-char/src/emoji_presentation.rs new file mode 100644 index 0000000000..25e9e4cd85 --- /dev/null +++ b/vendor/unic-emoji-char/src/emoji_presentation.rs @@ -0,0 +1,106 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Unicode `Emoji_Presentation` Character Property. + +char_property! { + /// Represents values of the Unicode character property + /// [`Emoji_Presentation`](https://www.unicode.org/reports/tr51/#Emoji_Properties). + /// + /// The value is `true` for characters that have emoji presentation by default. + pub struct EmojiPresentation(bool) { + abbr => "Emoji_Presentation"; + long => "Emoji_Presentation"; + human => "Emoji Presentation"; + + data_table_path => "../tables/emoji_presentation.rsv"; + } + + /// The value is `true` for characters that have emoji presentation by default. + pub fn is_emoji_presentation(char) -> bool; +} + +#[cfg(test)] +mod tests { + #[test] + fn test_values() { + use super::is_emoji_presentation; + + // ASCII + assert_eq!(is_emoji_presentation('\u{0000}'), false); + assert_eq!(is_emoji_presentation('\u{0021}'), false); + + assert_eq!(is_emoji_presentation('\u{0027}'), false); + assert_eq!(is_emoji_presentation('\u{0028}'), false); + assert_eq!(is_emoji_presentation('\u{0029}'), false); + assert_eq!(is_emoji_presentation('\u{002a}'), false); + + assert_eq!(is_emoji_presentation('\u{003b}'), false); + assert_eq!(is_emoji_presentation('\u{003c}'), false); + assert_eq!(is_emoji_presentation('\u{003d}'), false); + + assert_eq!(is_emoji_presentation('\u{007a}'), false); + assert_eq!(is_emoji_presentation('\u{007b}'), false); + assert_eq!(is_emoji_presentation('\u{007c}'), false); + assert_eq!(is_emoji_presentation('\u{007d}'), false); + assert_eq!(is_emoji_presentation('\u{007e}'), false); + + // Other BMP + assert_eq!(is_emoji_presentation('\u{061b}'), false); + assert_eq!(is_emoji_presentation('\u{061c}'), false); + assert_eq!(is_emoji_presentation('\u{061d}'), false); + + assert_eq!(is_emoji_presentation('\u{200d}'), false); + assert_eq!(is_emoji_presentation('\u{200e}'), false); + assert_eq!(is_emoji_presentation('\u{200f}'), false); + assert_eq!(is_emoji_presentation('\u{2010}'), false); + + assert_eq!(is_emoji_presentation('\u{2029}'), false); + assert_eq!(is_emoji_presentation('\u{202a}'), false); + assert_eq!(is_emoji_presentation('\u{202e}'), false); + assert_eq!(is_emoji_presentation('\u{202f}'), false); + + // Other Planes + assert_eq!(is_emoji_presentation('\u{10000}'), false); + assert_eq!(is_emoji_presentation('\u{10001}'), false); + + assert_eq!(is_emoji_presentation('\u{1f1e5}'), false); + assert_eq!(is_emoji_presentation('\u{1f1e6}'), true); + assert_eq!(is_emoji_presentation('\u{1f1ff}'), true); + assert_eq!(is_emoji_presentation('\u{1f200}'), false); + + assert_eq!(is_emoji_presentation('\u{20000}'), false); + assert_eq!(is_emoji_presentation('\u{30000}'), false); + assert_eq!(is_emoji_presentation('\u{40000}'), false); + assert_eq!(is_emoji_presentation('\u{50000}'), false); + assert_eq!(is_emoji_presentation('\u{60000}'), false); + assert_eq!(is_emoji_presentation('\u{70000}'), false); + assert_eq!(is_emoji_presentation('\u{80000}'), false); + assert_eq!(is_emoji_presentation('\u{90000}'), false); + assert_eq!(is_emoji_presentation('\u{a0000}'), false); + assert_eq!(is_emoji_presentation('\u{b0000}'), false); + assert_eq!(is_emoji_presentation('\u{c0000}'), false); + assert_eq!(is_emoji_presentation('\u{d0000}'), false); + assert_eq!(is_emoji_presentation('\u{e0000}'), false); + + assert_eq!(is_emoji_presentation('\u{efffe}'), false); + assert_eq!(is_emoji_presentation('\u{effff}'), false); + + // Priavte-Use Area + assert_eq!(is_emoji_presentation('\u{f0000}'), false); + assert_eq!(is_emoji_presentation('\u{f0001}'), false); + assert_eq!(is_emoji_presentation('\u{ffffe}'), false); + assert_eq!(is_emoji_presentation('\u{fffff}'), false); + assert_eq!(is_emoji_presentation('\u{100000}'), false); + assert_eq!(is_emoji_presentation('\u{100001}'), false); + assert_eq!(is_emoji_presentation('\u{10fffe}'), false); + assert_eq!(is_emoji_presentation('\u{10ffff}'), false); + } +} diff --git a/vendor/unic-emoji-char/src/emoji_version.rs b/vendor/unic-emoji-char/src/emoji_version.rs new file mode 100644 index 0000000000..62a419626d --- /dev/null +++ b/vendor/unic-emoji-char/src/emoji_version.rs @@ -0,0 +1,17 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub use unic_ucd_version::UnicodeVersion; + +/// The [Emoji Version] of character property data. +/// +/// Refs: +/// - <https://unicode.org/reports/tr51/> +pub const EMOJI_VERSION: UnicodeVersion = include!("../tables/emoji_version.rsv"); diff --git a/vendor/unic-emoji-char/src/lib.rs b/vendor/unic-emoji-char/src/lib.rs new file mode 100644 index 0000000000..38be971692 --- /dev/null +++ b/vendor/unic-emoji-char/src/lib.rs @@ -0,0 +1,47 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![warn( + bad_style, + missing_debug_implementations, + missing_docs, + unconditional_recursion +)] +#![forbid(unsafe_code)] + +//! # UNIC — Unicode Emoji — Emoji Character Properties +//! +//! A component of [`unic`: Unicode and Internationalization Crates for Rust](/unic/). + +#[macro_use] +extern crate unic_char_property; +#[macro_use] +extern crate unic_char_range; + +mod pkg_info; +pub use crate::pkg_info::{PKG_DESCRIPTION, PKG_NAME, PKG_VERSION}; + +mod emoji_version; +pub use crate::emoji_version::{UnicodeVersion, EMOJI_VERSION}; + +mod emoji; +pub use crate::emoji::{is_emoji, Emoji}; + +mod emoji_component; +pub use crate::emoji_component::{is_emoji_component, EmojiComponent}; + +mod emoji_modifier; +pub use crate::emoji_modifier::{is_emoji_modifier, EmojiModifier}; + +mod emoji_modifier_base; +pub use crate::emoji_modifier_base::{is_emoji_modifier_base, EmojiModifierBase}; + +mod emoji_presentation; +pub use crate::emoji_presentation::{is_emoji_presentation, EmojiPresentation}; diff --git a/vendor/unic-emoji-char/src/pkg_info.rs b/vendor/unic-emoji-char/src/pkg_info.rs new file mode 100644 index 0000000000..a1ab2853fd --- /dev/null +++ b/vendor/unic-emoji-char/src/pkg_info.rs @@ -0,0 +1,20 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Package information + +/// UNIC component version. +pub const PKG_VERSION: &str = env!("CARGO_PKG_VERSION"); + +/// UNIC component name. +pub const PKG_NAME: &str = env!("CARGO_PKG_NAME"); + +/// UNIC component description. +pub const PKG_DESCRIPTION: &str = env!("CARGO_PKG_DESCRIPTION"); diff --git a/vendor/unic-emoji-char/tables/emoji.rsv b/vendor/unic-emoji-char/tables/emoji.rsv new file mode 100644 index 0000000000..620aca301d --- /dev/null +++ b/vendor/unic-emoji-char/tables/emoji.rsv @@ -0,0 +1,149 @@ +// WARNING: Auto-generated by the `unic-gen` crate. +// WARNING: DO NOT EDIT MANUALLY! +CharDataTable::Range(&[ + (chars!('\u{23}'..='\u{23}'), ()), + (chars!('\u{2a}'..='\u{2a}'), ()), + (chars!('\u{30}'..='\u{39}'), ()), + (chars!('\u{a9}'..='\u{a9}'), ()), + (chars!('\u{ae}'..='\u{ae}'), ()), + (chars!('\u{203c}'..='\u{203c}'), ()), + (chars!('\u{2049}'..='\u{2049}'), ()), + (chars!('\u{2122}'..='\u{2122}'), ()), + (chars!('\u{2139}'..='\u{2139}'), ()), + (chars!('\u{2194}'..='\u{2199}'), ()), + (chars!('\u{21a9}'..='\u{21aa}'), ()), + (chars!('\u{231a}'..='\u{231b}'), ()), + (chars!('\u{2328}'..='\u{2328}'), ()), + (chars!('\u{23cf}'..='\u{23cf}'), ()), + (chars!('\u{23e9}'..='\u{23f3}'), ()), + (chars!('\u{23f8}'..='\u{23fa}'), ()), + (chars!('\u{24c2}'..='\u{24c2}'), ()), + (chars!('\u{25aa}'..='\u{25ab}'), ()), + (chars!('\u{25b6}'..='\u{25b6}'), ()), + (chars!('\u{25c0}'..='\u{25c0}'), ()), + (chars!('\u{25fb}'..='\u{25fe}'), ()), + (chars!('\u{2600}'..='\u{2604}'), ()), + (chars!('\u{260e}'..='\u{260e}'), ()), + (chars!('\u{2611}'..='\u{2611}'), ()), + (chars!('\u{2614}'..='\u{2615}'), ()), + (chars!('\u{2618}'..='\u{2618}'), ()), + (chars!('\u{261d}'..='\u{261d}'), ()), + (chars!('\u{2620}'..='\u{2620}'), ()), + (chars!('\u{2622}'..='\u{2623}'), ()), + (chars!('\u{2626}'..='\u{2626}'), ()), + (chars!('\u{262a}'..='\u{262a}'), ()), + (chars!('\u{262e}'..='\u{262f}'), ()), + (chars!('\u{2638}'..='\u{263a}'), ()), + (chars!('\u{2640}'..='\u{2640}'), ()), + (chars!('\u{2642}'..='\u{2642}'), ()), + (chars!('\u{2648}'..='\u{2653}'), ()), + (chars!('\u{2660}'..='\u{2660}'), ()), + (chars!('\u{2663}'..='\u{2663}'), ()), + (chars!('\u{2665}'..='\u{2666}'), ()), + (chars!('\u{2668}'..='\u{2668}'), ()), + (chars!('\u{267b}'..='\u{267b}'), ()), + (chars!('\u{267f}'..='\u{267f}'), ()), + (chars!('\u{2692}'..='\u{2697}'), ()), + (chars!('\u{2699}'..='\u{2699}'), ()), + (chars!('\u{269b}'..='\u{269c}'), ()), + (chars!('\u{26a0}'..='\u{26a1}'), ()), + (chars!('\u{26aa}'..='\u{26ab}'), ()), + (chars!('\u{26b0}'..='\u{26b1}'), ()), + (chars!('\u{26bd}'..='\u{26be}'), ()), + (chars!('\u{26c4}'..='\u{26c5}'), ()), + (chars!('\u{26c8}'..='\u{26c8}'), ()), + (chars!('\u{26ce}'..='\u{26cf}'), ()), + (chars!('\u{26d1}'..='\u{26d1}'), ()), + (chars!('\u{26d3}'..='\u{26d4}'), ()), + (chars!('\u{26e9}'..='\u{26ea}'), ()), + (chars!('\u{26f0}'..='\u{26f5}'), ()), + (chars!('\u{26f7}'..='\u{26fa}'), ()), + (chars!('\u{26fd}'..='\u{26fd}'), ()), + (chars!('\u{2702}'..='\u{2702}'), ()), + (chars!('\u{2705}'..='\u{2705}'), ()), + (chars!('\u{2708}'..='\u{270d}'), ()), + (chars!('\u{270f}'..='\u{270f}'), ()), + (chars!('\u{2712}'..='\u{2712}'), ()), + (chars!('\u{2714}'..='\u{2714}'), ()), + (chars!('\u{2716}'..='\u{2716}'), ()), + (chars!('\u{271d}'..='\u{271d}'), ()), + (chars!('\u{2721}'..='\u{2721}'), ()), + (chars!('\u{2728}'..='\u{2728}'), ()), + (chars!('\u{2733}'..='\u{2734}'), ()), + (chars!('\u{2744}'..='\u{2744}'), ()), + (chars!('\u{2747}'..='\u{2747}'), ()), + (chars!('\u{274c}'..='\u{274c}'), ()), + (chars!('\u{274e}'..='\u{274e}'), ()), + (chars!('\u{2753}'..='\u{2755}'), ()), + (chars!('\u{2757}'..='\u{2757}'), ()), + (chars!('\u{2763}'..='\u{2764}'), ()), + (chars!('\u{2795}'..='\u{2797}'), ()), + (chars!('\u{27a1}'..='\u{27a1}'), ()), + (chars!('\u{27b0}'..='\u{27b0}'), ()), + (chars!('\u{27bf}'..='\u{27bf}'), ()), + (chars!('\u{2934}'..='\u{2935}'), ()), + (chars!('\u{2b05}'..='\u{2b07}'), ()), + (chars!('\u{2b1b}'..='\u{2b1c}'), ()), + (chars!('\u{2b50}'..='\u{2b50}'), ()), + (chars!('\u{2b55}'..='\u{2b55}'), ()), + (chars!('\u{3030}'..='\u{3030}'), ()), + (chars!('\u{303d}'..='\u{303d}'), ()), + (chars!('\u{3297}'..='\u{3297}'), ()), + (chars!('\u{3299}'..='\u{3299}'), ()), + (chars!('\u{1f004}'..='\u{1f004}'), ()), + (chars!('\u{1f0cf}'..='\u{1f0cf}'), ()), + (chars!('\u{1f170}'..='\u{1f171}'), ()), + (chars!('\u{1f17e}'..='\u{1f17f}'), ()), + (chars!('\u{1f18e}'..='\u{1f18e}'), ()), + (chars!('\u{1f191}'..='\u{1f19a}'), ()), + (chars!('\u{1f1e6}'..='\u{1f1ff}'), ()), + (chars!('\u{1f201}'..='\u{1f202}'), ()), + (chars!('\u{1f21a}'..='\u{1f21a}'), ()), + (chars!('\u{1f22f}'..='\u{1f22f}'), ()), + (chars!('\u{1f232}'..='\u{1f23a}'), ()), + (chars!('\u{1f250}'..='\u{1f251}'), ()), + (chars!('\u{1f300}'..='\u{1f321}'), ()), + (chars!('\u{1f324}'..='\u{1f393}'), ()), + (chars!('\u{1f396}'..='\u{1f397}'), ()), + (chars!('\u{1f399}'..='\u{1f39b}'), ()), + (chars!('\u{1f39e}'..='\u{1f3f0}'), ()), + (chars!('\u{1f3f3}'..='\u{1f3f5}'), ()), + (chars!('\u{1f3f7}'..='\u{1f4fd}'), ()), + (chars!('\u{1f4ff}'..='\u{1f53d}'), ()), + (chars!('\u{1f549}'..='\u{1f54e}'), ()), + (chars!('\u{1f550}'..='\u{1f567}'), ()), + (chars!('\u{1f56f}'..='\u{1f570}'), ()), + (chars!('\u{1f573}'..='\u{1f57a}'), ()), + (chars!('\u{1f587}'..='\u{1f587}'), ()), + (chars!('\u{1f58a}'..='\u{1f58d}'), ()), + (chars!('\u{1f590}'..='\u{1f590}'), ()), + (chars!('\u{1f595}'..='\u{1f596}'), ()), + (chars!('\u{1f5a4}'..='\u{1f5a5}'), ()), + (chars!('\u{1f5a8}'..='\u{1f5a8}'), ()), + (chars!('\u{1f5b1}'..='\u{1f5b2}'), ()), + (chars!('\u{1f5bc}'..='\u{1f5bc}'), ()), + (chars!('\u{1f5c2}'..='\u{1f5c4}'), ()), + (chars!('\u{1f5d1}'..='\u{1f5d3}'), ()), + (chars!('\u{1f5dc}'..='\u{1f5de}'), ()), + (chars!('\u{1f5e1}'..='\u{1f5e1}'), ()), + (chars!('\u{1f5e3}'..='\u{1f5e3}'), ()), + (chars!('\u{1f5e8}'..='\u{1f5e8}'), ()), + (chars!('\u{1f5ef}'..='\u{1f5ef}'), ()), + (chars!('\u{1f5f3}'..='\u{1f5f3}'), ()), + (chars!('\u{1f5fa}'..='\u{1f64f}'), ()), + (chars!('\u{1f680}'..='\u{1f6c5}'), ()), + (chars!('\u{1f6cb}'..='\u{1f6d2}'), ()), + (chars!('\u{1f6e0}'..='\u{1f6e5}'), ()), + (chars!('\u{1f6e9}'..='\u{1f6e9}'), ()), + (chars!('\u{1f6eb}'..='\u{1f6ec}'), ()), + (chars!('\u{1f6f0}'..='\u{1f6f0}'), ()), + (chars!('\u{1f6f3}'..='\u{1f6f8}'), ()), + (chars!('\u{1f910}'..='\u{1f93a}'), ()), + (chars!('\u{1f93c}'..='\u{1f93e}'), ()), + (chars!('\u{1f940}'..='\u{1f945}'), ()), + (chars!('\u{1f947}'..='\u{1f94c}'), ()), + (chars!('\u{1f950}'..='\u{1f96b}'), ()), + (chars!('\u{1f980}'..='\u{1f997}'), ()), + (chars!('\u{1f9c0}'..='\u{1f9c0}'), ()), + (chars!('\u{1f9d0}'..='\u{1f9e6}'), ()), +]) diff --git a/vendor/unic-emoji-char/tables/emoji_component.rsv b/vendor/unic-emoji-char/tables/emoji_component.rsv new file mode 100644 index 0000000000..bc94955182 --- /dev/null +++ b/vendor/unic-emoji-char/tables/emoji_component.rsv @@ -0,0 +1,9 @@ +// WARNING: Auto-generated by the `unic-gen` crate. +// WARNING: DO NOT EDIT MANUALLY! +CharDataTable::Range(&[ + (chars!('\u{23}'..='\u{23}'), ()), + (chars!('\u{2a}'..='\u{2a}'), ()), + (chars!('\u{30}'..='\u{39}'), ()), + (chars!('\u{1f1e6}'..='\u{1f1ff}'), ()), + (chars!('\u{1f3fb}'..='\u{1f3ff}'), ()), +]) diff --git a/vendor/unic-emoji-char/tables/emoji_modifier.rsv b/vendor/unic-emoji-char/tables/emoji_modifier.rsv new file mode 100644 index 0000000000..b42c98e1b1 --- /dev/null +++ b/vendor/unic-emoji-char/tables/emoji_modifier.rsv @@ -0,0 +1,5 @@ +// WARNING: Auto-generated by the `unic-gen` crate. +// WARNING: DO NOT EDIT MANUALLY! +CharDataTable::Range(&[ + (chars!('\u{1f3fb}'..='\u{1f3ff}'), ()), +]) diff --git a/vendor/unic-emoji-char/tables/emoji_modifier_base.rsv b/vendor/unic-emoji-char/tables/emoji_modifier_base.rsv new file mode 100644 index 0000000000..3df4df11cc --- /dev/null +++ b/vendor/unic-emoji-char/tables/emoji_modifier_base.rsv @@ -0,0 +1,36 @@ +// WARNING: Auto-generated by the `unic-gen` crate. +// WARNING: DO NOT EDIT MANUALLY! +CharDataTable::Range(&[ + (chars!('\u{261d}'..='\u{261d}'), ()), + (chars!('\u{26f9}'..='\u{26f9}'), ()), + (chars!('\u{270a}'..='\u{270d}'), ()), + (chars!('\u{1f385}'..='\u{1f385}'), ()), + (chars!('\u{1f3c2}'..='\u{1f3c4}'), ()), + (chars!('\u{1f3c7}'..='\u{1f3c7}'), ()), + (chars!('\u{1f3ca}'..='\u{1f3cc}'), ()), + (chars!('\u{1f442}'..='\u{1f443}'), ()), + (chars!('\u{1f446}'..='\u{1f450}'), ()), + (chars!('\u{1f466}'..='\u{1f469}'), ()), + (chars!('\u{1f46e}'..='\u{1f46e}'), ()), + (chars!('\u{1f470}'..='\u{1f478}'), ()), + (chars!('\u{1f47c}'..='\u{1f47c}'), ()), + (chars!('\u{1f481}'..='\u{1f483}'), ()), + (chars!('\u{1f485}'..='\u{1f487}'), ()), + (chars!('\u{1f4aa}'..='\u{1f4aa}'), ()), + (chars!('\u{1f574}'..='\u{1f575}'), ()), + (chars!('\u{1f57a}'..='\u{1f57a}'), ()), + (chars!('\u{1f590}'..='\u{1f590}'), ()), + (chars!('\u{1f595}'..='\u{1f596}'), ()), + (chars!('\u{1f645}'..='\u{1f647}'), ()), + (chars!('\u{1f64b}'..='\u{1f64f}'), ()), + (chars!('\u{1f6a3}'..='\u{1f6a3}'), ()), + (chars!('\u{1f6b4}'..='\u{1f6b6}'), ()), + (chars!('\u{1f6c0}'..='\u{1f6c0}'), ()), + (chars!('\u{1f6cc}'..='\u{1f6cc}'), ()), + (chars!('\u{1f918}'..='\u{1f91c}'), ()), + (chars!('\u{1f91e}'..='\u{1f91f}'), ()), + (chars!('\u{1f926}'..='\u{1f926}'), ()), + (chars!('\u{1f930}'..='\u{1f939}'), ()), + (chars!('\u{1f93d}'..='\u{1f93e}'), ()), + (chars!('\u{1f9d1}'..='\u{1f9dd}'), ()), +]) diff --git a/vendor/unic-emoji-char/tables/emoji_presentation.rsv b/vendor/unic-emoji-char/tables/emoji_presentation.rsv new file mode 100644 index 0000000000..5e594f1e92 --- /dev/null +++ b/vendor/unic-emoji-char/tables/emoji_presentation.rsv @@ -0,0 +1,79 @@ +// WARNING: Auto-generated by the `unic-gen` crate. +// WARNING: DO NOT EDIT MANUALLY! +CharDataTable::Range(&[ + (chars!('\u{231a}'..='\u{231b}'), ()), + (chars!('\u{23e9}'..='\u{23ec}'), ()), + (chars!('\u{23f0}'..='\u{23f0}'), ()), + (chars!('\u{23f3}'..='\u{23f3}'), ()), + (chars!('\u{25fd}'..='\u{25fe}'), ()), + (chars!('\u{2614}'..='\u{2615}'), ()), + (chars!('\u{2648}'..='\u{2653}'), ()), + (chars!('\u{267f}'..='\u{267f}'), ()), + (chars!('\u{2693}'..='\u{2693}'), ()), + (chars!('\u{26a1}'..='\u{26a1}'), ()), + (chars!('\u{26aa}'..='\u{26ab}'), ()), + (chars!('\u{26bd}'..='\u{26be}'), ()), + (chars!('\u{26c4}'..='\u{26c5}'), ()), + (chars!('\u{26ce}'..='\u{26ce}'), ()), + (chars!('\u{26d4}'..='\u{26d4}'), ()), + (chars!('\u{26ea}'..='\u{26ea}'), ()), + (chars!('\u{26f2}'..='\u{26f3}'), ()), + (chars!('\u{26f5}'..='\u{26f5}'), ()), + (chars!('\u{26fa}'..='\u{26fa}'), ()), + (chars!('\u{26fd}'..='\u{26fd}'), ()), + (chars!('\u{2705}'..='\u{2705}'), ()), + (chars!('\u{270a}'..='\u{270b}'), ()), + (chars!('\u{2728}'..='\u{2728}'), ()), + (chars!('\u{274c}'..='\u{274c}'), ()), + (chars!('\u{274e}'..='\u{274e}'), ()), + (chars!('\u{2753}'..='\u{2755}'), ()), + (chars!('\u{2757}'..='\u{2757}'), ()), + (chars!('\u{2795}'..='\u{2797}'), ()), + (chars!('\u{27b0}'..='\u{27b0}'), ()), + (chars!('\u{27bf}'..='\u{27bf}'), ()), + (chars!('\u{2b1b}'..='\u{2b1c}'), ()), + (chars!('\u{2b50}'..='\u{2b50}'), ()), + (chars!('\u{2b55}'..='\u{2b55}'), ()), + (chars!('\u{1f004}'..='\u{1f004}'), ()), + (chars!('\u{1f0cf}'..='\u{1f0cf}'), ()), + (chars!('\u{1f18e}'..='\u{1f18e}'), ()), + (chars!('\u{1f191}'..='\u{1f19a}'), ()), + (chars!('\u{1f1e6}'..='\u{1f1ff}'), ()), + (chars!('\u{1f201}'..='\u{1f201}'), ()), + (chars!('\u{1f21a}'..='\u{1f21a}'), ()), + (chars!('\u{1f22f}'..='\u{1f22f}'), ()), + (chars!('\u{1f232}'..='\u{1f236}'), ()), + (chars!('\u{1f238}'..='\u{1f23a}'), ()), + (chars!('\u{1f250}'..='\u{1f251}'), ()), + (chars!('\u{1f300}'..='\u{1f320}'), ()), + (chars!('\u{1f32d}'..='\u{1f335}'), ()), + (chars!('\u{1f337}'..='\u{1f37c}'), ()), + (chars!('\u{1f37e}'..='\u{1f393}'), ()), + (chars!('\u{1f3a0}'..='\u{1f3ca}'), ()), + (chars!('\u{1f3cf}'..='\u{1f3d3}'), ()), + (chars!('\u{1f3e0}'..='\u{1f3f0}'), ()), + (chars!('\u{1f3f4}'..='\u{1f3f4}'), ()), + (chars!('\u{1f3f8}'..='\u{1f43e}'), ()), + (chars!('\u{1f440}'..='\u{1f440}'), ()), + (chars!('\u{1f442}'..='\u{1f4fc}'), ()), + (chars!('\u{1f4ff}'..='\u{1f53d}'), ()), + (chars!('\u{1f54b}'..='\u{1f54e}'), ()), + (chars!('\u{1f550}'..='\u{1f567}'), ()), + (chars!('\u{1f57a}'..='\u{1f57a}'), ()), + (chars!('\u{1f595}'..='\u{1f596}'), ()), + (chars!('\u{1f5a4}'..='\u{1f5a4}'), ()), + (chars!('\u{1f5fb}'..='\u{1f64f}'), ()), + (chars!('\u{1f680}'..='\u{1f6c5}'), ()), + (chars!('\u{1f6cc}'..='\u{1f6cc}'), ()), + (chars!('\u{1f6d0}'..='\u{1f6d2}'), ()), + (chars!('\u{1f6eb}'..='\u{1f6ec}'), ()), + (chars!('\u{1f6f4}'..='\u{1f6f8}'), ()), + (chars!('\u{1f910}'..='\u{1f93a}'), ()), + (chars!('\u{1f93c}'..='\u{1f93e}'), ()), + (chars!('\u{1f940}'..='\u{1f945}'), ()), + (chars!('\u{1f947}'..='\u{1f94c}'), ()), + (chars!('\u{1f950}'..='\u{1f96b}'), ()), + (chars!('\u{1f980}'..='\u{1f997}'), ()), + (chars!('\u{1f9c0}'..='\u{1f9c0}'), ()), + (chars!('\u{1f9d0}'..='\u{1f9e6}'), ()), +]) diff --git a/vendor/unic-emoji-char/tables/emoji_version.rsv b/vendor/unic-emoji-char/tables/emoji_version.rsv new file mode 100644 index 0000000000..57dfe2b575 --- /dev/null +++ b/vendor/unic-emoji-char/tables/emoji_version.rsv @@ -0,0 +1,3 @@ +// WARNING: Auto-generated by the `unic-gen` crate. +// WARNING: DO NOT EDIT MANUALLY! +UnicodeVersion { major: 5, minor: 0, micro: 0 } diff --git a/vendor/unic-emoji-char/tests/emoji_version_tests.rs b/vendor/unic-emoji-char/tests/emoji_version_tests.rs new file mode 100644 index 0000000000..856d5a8976 --- /dev/null +++ b/vendor/unic-emoji-char/tests/emoji_version_tests.rs @@ -0,0 +1,19 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use unic_emoji_char; +use unic_ucd_version; + +#[test] +fn test_emoji_data_version_against_ucd_version() { + // At the moment, Emoji Version is strictly smaller than Unicode Version. Emoji Version is going + // to be *synced* with Unicode Version, but may receive minor updates separately. + assert!(unic_emoji_char::EMOJI_VERSION.major <= unic_ucd_version::UNICODE_VERSION.major); +} diff --git a/vendor/unic-ucd-version/.cargo-checksum.json b/vendor/unic-ucd-version/.cargo-checksum.json new file mode 100644 index 0000000000..ff13a3a985 --- /dev/null +++ b/vendor/unic-ucd-version/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"75628c37e215f72578113d96f746acba57b8a2f3448675a2f2a807f0930d4ce7","src/lib.rs":"51d52da8220e430f32523aa5972708e698fca29fea8b64a4cbdc67d3d1830f37","src/pkg_info.rs":"37cbe4efd0b0205d251e1ef7714b23e3be27052c8a0de6b1ae3cbf3aefae1fe5","src/unicode_version.rs":"bc2fe0341c2a60909f1ef7e56593b836344ca4b4ae8f73e7f7aa07259963dd03","tables/unicode_version.rsv":"a2efcb89606ee821ff9ac5595e5126a65f2b00b70ca1054c1884f741827ab230","tests/basic_tests.rs":"8d3597a7c3365b5516a2e6200386b5e8dac836aa6f90b8a329ff120f0c54f207"},"package":"96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4"} \ No newline at end of file diff --git a/vendor/unic-ucd-version/Cargo.toml b/vendor/unic-ucd-version/Cargo.toml new file mode 100644 index 0000000000..c6328141c6 --- /dev/null +++ b/vendor/unic-ucd-version/Cargo.toml @@ -0,0 +1,42 @@ +# 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 = "unic-ucd-version" +version = "0.9.0" +authors = ["The UNIC Project Developers"] +exclude = [] +description = "UNIC — Unicode Character Database — Version" +keywords = ["text", "unicode", "version"] +categories = ["internationalization", "text-processing", "parsing", "rendering"] +license = "MIT/Apache-2.0" +repository = "https://github.com/open-i18n/rust-unic/" +[dependencies.unic-common] +version = "0.9.0" +[badges.appveyor] +branch = "master" +repository = "open-i18n/rust-unic" +service = "github" + +[badges.is-it-maintained-issue-resolution] +repository = "open-i18n/rust-unic" + +[badges.is-it-maintained-open-issues] +repository = "open-i18n/rust-unic" + +[badges.maintenance] +status = "actively-developed" + +[badges.travis-ci] +branch = "master" +repository = "open-i18n/rust-unic" diff --git a/vendor/unic-ucd-version/src/lib.rs b/vendor/unic-ucd-version/src/lib.rs new file mode 100644 index 0000000000..3877f04d7d --- /dev/null +++ b/vendor/unic-ucd-version/src/lib.rs @@ -0,0 +1,32 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![no_std] +#![warn( + bad_style, + missing_debug_implementations, + missing_docs, + unconditional_recursion +)] +#![forbid(unsafe_code)] + +//! # UNIC — UCD — Core +//! +//! A component of [`unic`: Unicode and Internationalization Crates for Rust](/unic/). +//! +//! Core create indicating the version of Unicode Character Database. + +pub use unic_common::version::UnicodeVersion; + +mod pkg_info; +pub use crate::pkg_info::{PKG_DESCRIPTION, PKG_NAME, PKG_VERSION}; + +mod unicode_version; +pub use crate::unicode_version::UNICODE_VERSION; diff --git a/vendor/unic-ucd-version/src/pkg_info.rs b/vendor/unic-ucd-version/src/pkg_info.rs new file mode 100644 index 0000000000..a1ab2853fd --- /dev/null +++ b/vendor/unic-ucd-version/src/pkg_info.rs @@ -0,0 +1,20 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Package information + +/// UNIC component version. +pub const PKG_VERSION: &str = env!("CARGO_PKG_VERSION"); + +/// UNIC component name. +pub const PKG_NAME: &str = env!("CARGO_PKG_NAME"); + +/// UNIC component description. +pub const PKG_DESCRIPTION: &str = env!("CARGO_PKG_DESCRIPTION"); diff --git a/vendor/unic-ucd-version/src/unicode_version.rs b/vendor/unic-ucd-version/src/unicode_version.rs new file mode 100644 index 0000000000..8e96e7f0a4 --- /dev/null +++ b/vendor/unic-ucd-version/src/unicode_version.rs @@ -0,0 +1,29 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use unic_common::version::UnicodeVersion; + +/// The [Version of The Unicode Standard](https://www.unicode.org/versions/) of the Unicode +/// Character Database in use. +pub const UNICODE_VERSION: UnicodeVersion = include!("../tables/unicode_version.rsv"); + +#[cfg(test)] +mod tests { + use super::UNICODE_VERSION; + + #[test] + fn validate_version_values() { + assert!(UNICODE_VERSION.major > 0); + + // Current release schedule of Unicode is to have one Major version update each year, with + // no Minor updates. We hard-code this internal policy while it stands. + assert!(UNICODE_VERSION.minor == 0); + } +} diff --git a/vendor/unic-ucd-version/tables/unicode_version.rsv b/vendor/unic-ucd-version/tables/unicode_version.rsv new file mode 100644 index 0000000000..63d0ef1578 --- /dev/null +++ b/vendor/unic-ucd-version/tables/unicode_version.rsv @@ -0,0 +1,3 @@ +// WARNING: Auto-generated by the `unic-gen` crate. +// WARNING: DO NOT EDIT MANUALLY! +UnicodeVersion { major: 10, minor: 0, micro: 0 } diff --git a/vendor/unic-ucd-version/tests/basic_tests.rs b/vendor/unic-ucd-version/tests/basic_tests.rs new file mode 100644 index 0000000000..e385bcf985 --- /dev/null +++ b/vendor/unic-ucd-version/tests/basic_tests.rs @@ -0,0 +1,26 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use unic_ucd_version::UnicodeVersion; + +#[test] +fn test_display() { + assert_eq!( + format!( + "Unicode {}", + UnicodeVersion { + major: 1, + minor: 2, + micro: 0, + } + ), + "Unicode 1.2.0" + ); +} diff --git a/vendor/unicode-bidi/.cargo-checksum.json b/vendor/unicode-bidi/.cargo-checksum.json index 84299589c4..2bedeba2c7 100644 --- a/vendor/unicode-bidi/.cargo-checksum.json +++ b/vendor/unicode-bidi/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"AUTHORS":"1ff3a7c8519b29544bb28ba9b1e7502df0cb764051fb9a1172e60006aa2b8dcc","COPYRIGHT":"edb20b474f6cbd4f4db066b54a9e0f687d0009d309412a63431189b59b8e2a07","Cargo.toml":"8475e307214518bf8a2a3f1e6f8c172631f55287902ebba6781dcdfea6f6138f","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"70f94b408efa530b77b82b6aedfb35801ae62fca8bb80b12d81b7f70450297c0","src/char_data/mod.rs":"84c30d5e3f92aefa29143bf426284ec8fbb0de065cbe080cdb5ed49905f2b055","src/char_data/tables.rs":"a27f625544bc49817b02b78cf55997a73d27dc4d616724aa96f70128b9629b23","src/deprecated.rs":"ae5a384d534d9cc3aa17db276eba631b8b95f50121a5e2f527daf7d67490334a","src/explicit.rs":"a5da86526a77d49e0377332f5c840ef3d0088ae5f1db1196edbec5445b55fb7f","src/format_chars.rs":"678399fec3f4bfaf4093f38cfdb8956288313386dc3511dab9fb58164e8dc01b","src/implicit.rs":"9280aab98d22daf8ab44665d906a2e0831dbfe7810bb66d89fbf1bd91fe6be20","src/level.rs":"53bca436ea235aab5850817c615ad685bf059d9c40d2b52729ffdcd897136cfe","src/lib.rs":"df214814a4d0e7be0600a91426333c025f8c293f6a8c714688a014bb3b2a7289","src/prepare.rs":"6c58beef882b2d5c5bf2fe22e12cbccb5a4592f82272e8bce3ddedf005ee1149"},"package":"246f4c42e67e7a4e3c6106ff716a5d067d4132a642840b242e357e468a2a0085"} \ No newline at end of file +{"files":{"AUTHORS":"1ff3a7c8519b29544bb28ba9b1e7502df0cb764051fb9a1172e60006aa2b8dcc","COPYRIGHT":"edb20b474f6cbd4f4db066b54a9e0f687d0009d309412a63431189b59b8e2a07","Cargo.toml":"0d1bab4e23f1f2454686bbaeb568e20922bb878edfb447cbeb947b1a45fee389","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"70f94b408efa530b77b82b6aedfb35801ae62fca8bb80b12d81b7f70450297c0","src/char_data/mod.rs":"84c30d5e3f92aefa29143bf426284ec8fbb0de065cbe080cdb5ed49905f2b055","src/char_data/tables.rs":"a27f625544bc49817b02b78cf55997a73d27dc4d616724aa96f70128b9629b23","src/deprecated.rs":"ae5a384d534d9cc3aa17db276eba631b8b95f50121a5e2f527daf7d67490334a","src/explicit.rs":"a5da86526a77d49e0377332f5c840ef3d0088ae5f1db1196edbec5445b55fb7f","src/format_chars.rs":"678399fec3f4bfaf4093f38cfdb8956288313386dc3511dab9fb58164e8dc01b","src/implicit.rs":"9280aab98d22daf8ab44665d906a2e0831dbfe7810bb66d89fbf1bd91fe6be20","src/level.rs":"53bca436ea235aab5850817c615ad685bf059d9c40d2b52729ffdcd897136cfe","src/lib.rs":"7f04307e7c235bd89f32232a2138c37ef520d755dd6f1797cb49c6fb0d9ba986","src/prepare.rs":"6c58beef882b2d5c5bf2fe22e12cbccb5a4592f82272e8bce3ddedf005ee1149"},"package":"1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f"} \ No newline at end of file diff --git a/vendor/unicode-bidi/Cargo.toml b/vendor/unicode-bidi/Cargo.toml index d64220ec6f..91f32baabe 100644 --- a/vendor/unicode-bidi/Cargo.toml +++ b/vendor/unicode-bidi/Cargo.toml @@ -3,17 +3,16 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies +# to registry (e.g., crates.io) dependencies. # -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. [package] edition = "2018" name = "unicode-bidi" -version = "0.3.6" +version = "0.3.7" authors = ["The Servo Project Developers"] exclude = ["benches/**", "data/**", "examples/**", "tests/**", "tools/**"] description = "Implementation of the Unicode Bidirectional Algorithm" diff --git a/vendor/unicode-bidi/src/lib.rs b/vendor/unicode-bidi/src/lib.rs index 09bbcfbd51..bb318a0ad4 100644 --- a/vendor/unicode-bidi/src/lib.rs +++ b/vendor/unicode-bidi/src/lib.rs @@ -66,7 +66,7 @@ #![no_std] // We need to link to std to make doc tests work on older Rust versions -#![cfg(feature = "std")] +#[cfg(feature = "std")] extern crate std; #[macro_use] extern crate alloc; diff --git a/vendor/unindent/.cargo-checksum.json b/vendor/unindent/.cargo-checksum.json new file mode 100644 index 0000000000..39c483f715 --- /dev/null +++ b/vendor/unindent/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"77abf43ab966a7b6eb84b57010e3a9367652fd7ddad2f91b1f75431d4185afc7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"3a4ac0900d63ad03b77d612c3df04fe7282001a9a76cca148f3770db03b10a13","src/lib.rs":"842aa81b6844ce6d63f33247261b7b06a2839fe4cef1a0253ea33276f05bdf29"},"package":"f14ee04d9415b52b3aeab06258a3f07093182b88ba0f9b8d203f211a7a7d41c7"} \ No newline at end of file diff --git a/vendor/unindent/Cargo.toml b/vendor/unindent/Cargo.toml new file mode 100644 index 0000000000..7f0f75bf22 --- /dev/null +++ b/vendor/unindent/Cargo.toml @@ -0,0 +1,25 @@ +# 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 = "unindent" +version = "0.1.7" +authors = ["David Tolnay <dtolnay@gmail.com>"] +description = "Remove a column of leading whitespace from a string" +documentation = "https://docs.rs/unindent" +readme = "README.md" +keywords = ["heredoc", "nowdoc", "multiline", "string", "literal"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/dtolnay/indoc" +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] diff --git a/vendor/unindent/LICENSE-APACHE b/vendor/unindent/LICENSE-APACHE new file mode 100644 index 0000000000..16fe87b06e --- /dev/null +++ b/vendor/unindent/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/vendor/unindent/LICENSE-MIT b/vendor/unindent/LICENSE-MIT new file mode 100644 index 0000000000..31aa79387f --- /dev/null +++ b/vendor/unindent/LICENSE-MIT @@ -0,0 +1,23 @@ +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/unindent/README.md b/vendor/unindent/README.md new file mode 100644 index 0000000000..317db73d8e --- /dev/null +++ b/vendor/unindent/README.md @@ -0,0 +1,65 @@ +# Unindent + +[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/indoc-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/indoc) +[<img alt="crates.io" src="https://img.shields.io/crates/v/unindent.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/unindent) +[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-unindent-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K" height="20">](https://docs.rs/unindent) +[<img alt="build status" src="https://img.shields.io/github/workflow/status/dtolnay/indoc/CI/master?style=for-the-badge" height="20">](https://github.com/dtolnay/indoc/actions?query=branch%3Amaster) + +This crate provides [`indoc`]'s indentation logic for use with strings that are +not statically known at compile time. For unindenting string literals, use +`indoc` instead. + +[`indoc`]: https://github.com/dtolnay/indoc + +This crate exposes two functions: + +- `unindent(&str) -> String` +- `unindent_bytes(&[u8]) -> Vec<u8>` + +```rust +use unindent::unindent; + +fn main() { + let indented = " + line one + line two"; + assert_eq!("line one\nline two", unindent(indented)); +} +``` + +## Explanation + +The following rules characterize the behavior of unindent: + +1. Count the leading spaces of each line, ignoring the first line and any lines + that are empty or contain spaces only. +2. Take the minimum. +3. If the first line is empty i.e. the string begins with a newline, remove the + first line. +4. Remove the computed number of spaces from the beginning of each line. + +This means there are a few equivalent ways to format the same string, so choose +one you like. All of the following result in the string `"line one\nline +two\n"`: + +``` +unindent(" / unindent( / unindent("line one + line one / "line one / line two + line two / line two / ") + ") / ") / +``` + +## 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 Indoc 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/unindent/src/lib.rs b/vendor/unindent/src/lib.rs new file mode 100644 index 0000000000..d72aac3d7a --- /dev/null +++ b/vendor/unindent/src/lib.rs @@ -0,0 +1,181 @@ +//! [![github]](https://github.com/dtolnay/indoc) [![crates-io]](https://crates.io/crates/unindent) [![docs-rs]](https://docs.rs/unindent) +//! +//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github +//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust +//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K +//! +//! <br> +//! +//! ## Unindent +//! +//! This crate provides [`indoc`]'s indentation logic for use with strings that +//! are not statically known at compile time. For unindenting string literals, +//! use `indoc` instead. +//! +//! [`indoc`]: https://github.com/dtolnay/indoc +//! +//! This crate exposes two unindent functions and an extension trait: +//! +//! - `fn unindent(&str) -> String` +//! - `fn unindent_bytes(&[u8]) -> Vec<u8>` +//! - `trait Unindent` +//! +//! ``` +//! use unindent::unindent; +//! +//! fn main() { +//! let indented = " +//! line one +//! line two"; +//! assert_eq!("line one\nline two", unindent(indented)); +//! } +//! ``` +//! +//! The `Unindent` extension trait expose the same functionality under an +//! extension method. +//! +//! ``` +//! use unindent::Unindent; +//! +//! fn main() { +//! let indented = format!(" +//! line {} +//! line {}", "one", "two"); +//! assert_eq!("line one\nline two", indented.unindent()); +//! } +//! ``` + +#![doc(html_root_url = "https://docs.rs/unindent/0.1.6")] +#![allow(clippy::type_complexity)] + +use std::iter::Peekable; +use std::slice::Split; + +pub fn unindent(s: &str) -> String { + let bytes = s.as_bytes(); + let unindented = unindent_bytes(bytes); + String::from_utf8(unindented).unwrap() +} + +// Compute the maximal number of spaces that can be removed from every line, and +// remove them. +pub fn unindent_bytes(s: &[u8]) -> Vec<u8> { + // Document may start either on the same line as opening quote or + // on the next line + let ignore_first_line = s.starts_with(b"\n") || s.starts_with(b"\r\n"); + + // Largest number of spaces that can be removed from every + // non-whitespace-only line after the first + let spaces = s + .lines() + .skip(1) + .filter_map(count_spaces) + .min() + .unwrap_or(0); + + let mut result = Vec::with_capacity(s.len()); + for (i, line) in s.lines().enumerate() { + if i > 1 || (i == 1 && !ignore_first_line) { + result.push(b'\n'); + } + if i == 0 { + // Do not un-indent anything on same line as opening quote + result.extend_from_slice(line); + } else if line.len() > spaces { + // Whitespace-only lines may have fewer than the number of spaces + // being removed + result.extend_from_slice(&line[spaces..]); + } + } + result +} + +pub trait Unindent { + type Output; + + fn unindent(&self) -> Self::Output; +} + +impl Unindent for str { + type Output = String; + + fn unindent(&self) -> Self::Output { + unindent(self) + } +} + +impl Unindent for String { + type Output = String; + + fn unindent(&self) -> Self::Output { + unindent(self) + } +} + +impl Unindent for [u8] { + type Output = Vec<u8>; + + fn unindent(&self) -> Self::Output { + unindent_bytes(self) + } +} + +impl<'a, T: ?Sized + Unindent> Unindent for &'a T { + type Output = T::Output; + + fn unindent(&self) -> Self::Output { + (**self).unindent() + } +} + +// Number of leading spaces in the line, or None if the line is entirely spaces. +fn count_spaces(line: &[u8]) -> Option<usize> { + for (i, ch) in line.iter().enumerate() { + if *ch != b' ' && *ch != b'\t' { + return Some(i); + } + } + None +} + +// Based on core::str::StrExt. +trait BytesExt { + fn lines(&self) -> Lines; +} + +impl BytesExt for [u8] { + fn lines(&self) -> Lines { + fn is_newline(b: &u8) -> bool { + *b == b'\n' + } + let bytestring = if self.starts_with(b"\r\n") { + &self[1..] + } else { + self + }; + Lines { + split: bytestring.split(is_newline as fn(&u8) -> bool).peekable(), + } + } +} + +struct Lines<'a> { + split: Peekable<Split<'a, u8, fn(&u8) -> bool>>, +} + +impl<'a> Iterator for Lines<'a> { + type Item = &'a [u8]; + + fn next(&mut self) -> Option<Self::Item> { + match self.split.next() { + None => None, + Some(fragment) => { + if fragment.is_empty() && self.split.peek().is_none() { + None + } else { + Some(fragment) + } + } + } + } +} diff --git a/version b/version index d283cd4de3..4485d06dd7 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.57.0 (f1edd0429 2021-11-29) \ No newline at end of file +1.58.1 (db9d1b20b 2022-01-20) \ No newline at end of file -- 2.39.2